mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-22 13:21:07 -05:00
merge(upstream): merge upstream changes keeping VSCode LM provider and adding Glama support
This commit is contained in:
@@ -12,7 +12,7 @@ import { ApiHandler, SingleCompletionHandler, buildApiHandler } from "../api"
|
||||
import { ApiStream } from "../api/transform/stream"
|
||||
import { DiffViewProvider } from "../integrations/editor/DiffViewProvider"
|
||||
import { findToolName, formatContentBlockToMarkdown } from "../integrations/misc/export-markdown"
|
||||
import { extractTextFromFile, addLineNumbers, stripLineNumbers, everyLineHasLineNumbers } from "../integrations/misc/extract-text"
|
||||
import { extractTextFromFile, addLineNumbers, stripLineNumbers, everyLineHasLineNumbers, truncateOutput } from "../integrations/misc/extract-text"
|
||||
import { TerminalManager } from "../integrations/terminal/TerminalManager"
|
||||
import { UrlContentFetcher } from "../services/browser/UrlContentFetcher"
|
||||
import { listFiles } from "../services/glob/list-files"
|
||||
@@ -716,22 +716,6 @@ export class Cline {
|
||||
}
|
||||
})
|
||||
|
||||
const getFormattedOutput = async () => {
|
||||
const { terminalOutputLineLimit } = await this.providerRef.deref()?.getState() ?? {}
|
||||
const limit = terminalOutputLineLimit ?? 0
|
||||
|
||||
if (limit > 0 && lines.length > limit) {
|
||||
const beforeLimit = Math.floor(limit * 0.2) // 20% of lines before
|
||||
const afterLimit = limit - beforeLimit // remaining 80% after
|
||||
return [
|
||||
...lines.slice(0, beforeLimit),
|
||||
`\n[...${lines.length - limit} lines omitted...]\n`,
|
||||
...lines.slice(-afterLimit)
|
||||
].join('\n')
|
||||
}
|
||||
return lines.join('\n')
|
||||
}
|
||||
|
||||
let completed = false
|
||||
process.once("completed", () => {
|
||||
completed = true
|
||||
@@ -750,7 +734,8 @@ export class Cline {
|
||||
// grouping command_output messages despite any gaps anyways)
|
||||
await delay(50)
|
||||
|
||||
const output = await getFormattedOutput()
|
||||
const { terminalOutputLineLimit } = await this.providerRef.deref()?.getState() ?? {}
|
||||
const output = truncateOutput(lines.join('\n'), terminalOutputLineLimit)
|
||||
const result = output.trim()
|
||||
|
||||
if (userFeedback) {
|
||||
|
||||
155
src/core/mentions/__tests__/index.test.ts
Normal file
155
src/core/mentions/__tests__/index.test.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
// Create mock vscode module before importing anything
|
||||
const createMockUri = (scheme: string, path: string) => ({
|
||||
scheme,
|
||||
authority: '',
|
||||
path,
|
||||
query: '',
|
||||
fragment: '',
|
||||
fsPath: path,
|
||||
with: jest.fn(),
|
||||
toString: () => path,
|
||||
toJSON: () => ({
|
||||
scheme,
|
||||
authority: '',
|
||||
path,
|
||||
query: '',
|
||||
fragment: ''
|
||||
})
|
||||
})
|
||||
|
||||
const mockExecuteCommand = jest.fn()
|
||||
const mockOpenExternal = jest.fn()
|
||||
const mockShowErrorMessage = jest.fn()
|
||||
|
||||
const mockVscode = {
|
||||
workspace: {
|
||||
workspaceFolders: [{
|
||||
uri: { fsPath: "/test/workspace" }
|
||||
}]
|
||||
},
|
||||
window: {
|
||||
showErrorMessage: mockShowErrorMessage,
|
||||
showInformationMessage: jest.fn(),
|
||||
showWarningMessage: jest.fn(),
|
||||
createTextEditorDecorationType: jest.fn(),
|
||||
createOutputChannel: jest.fn(),
|
||||
createWebviewPanel: jest.fn(),
|
||||
activeTextEditor: undefined
|
||||
},
|
||||
commands: {
|
||||
executeCommand: mockExecuteCommand
|
||||
},
|
||||
env: {
|
||||
openExternal: mockOpenExternal
|
||||
},
|
||||
Uri: {
|
||||
parse: jest.fn((url: string) => createMockUri('https', url)),
|
||||
file: jest.fn((path: string) => createMockUri('file', path))
|
||||
},
|
||||
Position: jest.fn(),
|
||||
Range: jest.fn(),
|
||||
TextEdit: jest.fn(),
|
||||
WorkspaceEdit: jest.fn(),
|
||||
DiagnosticSeverity: {
|
||||
Error: 0,
|
||||
Warning: 1,
|
||||
Information: 2,
|
||||
Hint: 3
|
||||
}
|
||||
}
|
||||
|
||||
// Mock modules
|
||||
jest.mock('vscode', () => mockVscode)
|
||||
jest.mock("../../../services/browser/UrlContentFetcher")
|
||||
jest.mock("../../../utils/git")
|
||||
|
||||
// Now import the modules that use the mocks
|
||||
import { parseMentions, openMention } from "../index"
|
||||
import { UrlContentFetcher } from "../../../services/browser/UrlContentFetcher"
|
||||
import * as git from "../../../utils/git"
|
||||
|
||||
describe("mentions", () => {
|
||||
const mockCwd = "/test/workspace"
|
||||
let mockUrlContentFetcher: UrlContentFetcher
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
// Create a mock instance with just the methods we need
|
||||
mockUrlContentFetcher = {
|
||||
launchBrowser: jest.fn().mockResolvedValue(undefined),
|
||||
closeBrowser: jest.fn().mockResolvedValue(undefined),
|
||||
urlToMarkdown: jest.fn().mockResolvedValue(""),
|
||||
} as unknown as UrlContentFetcher
|
||||
})
|
||||
|
||||
describe("parseMentions", () => {
|
||||
it("should parse git commit mentions", async () => {
|
||||
const commitHash = "abc1234"
|
||||
const commitInfo = `abc1234 Fix bug in parser
|
||||
|
||||
Author: John Doe
|
||||
Date: Mon Jan 5 23:50:06 2025 -0500
|
||||
|
||||
Detailed commit message with multiple lines
|
||||
- Fixed parsing issue
|
||||
- Added tests`
|
||||
|
||||
jest.mocked(git.getCommitInfo).mockResolvedValue(commitInfo)
|
||||
|
||||
const result = await parseMentions(
|
||||
`Check out this commit @${commitHash}`,
|
||||
mockCwd,
|
||||
mockUrlContentFetcher
|
||||
)
|
||||
|
||||
expect(result).toContain(`'${commitHash}' (see below for commit info)`)
|
||||
expect(result).toContain(`<git_commit hash="${commitHash}">`)
|
||||
expect(result).toContain(commitInfo)
|
||||
})
|
||||
|
||||
it("should handle errors fetching git info", async () => {
|
||||
const commitHash = "abc1234"
|
||||
const errorMessage = "Failed to get commit info"
|
||||
|
||||
jest.mocked(git.getCommitInfo).mockRejectedValue(new Error(errorMessage))
|
||||
|
||||
const result = await parseMentions(
|
||||
`Check out this commit @${commitHash}`,
|
||||
mockCwd,
|
||||
mockUrlContentFetcher
|
||||
)
|
||||
|
||||
expect(result).toContain(`'${commitHash}' (see below for commit info)`)
|
||||
expect(result).toContain(`<git_commit hash="${commitHash}">`)
|
||||
expect(result).toContain(`Error fetching commit info: ${errorMessage}`)
|
||||
})
|
||||
})
|
||||
|
||||
describe("openMention", () => {
|
||||
it("should handle file paths and problems", async () => {
|
||||
await openMention("/path/to/file")
|
||||
expect(mockExecuteCommand).not.toHaveBeenCalled()
|
||||
expect(mockOpenExternal).not.toHaveBeenCalled()
|
||||
expect(mockShowErrorMessage).toHaveBeenCalledWith("Could not open file!")
|
||||
|
||||
await openMention("problems")
|
||||
expect(mockExecuteCommand).toHaveBeenCalledWith("workbench.actions.view.problems")
|
||||
})
|
||||
|
||||
it("should handle URLs", async () => {
|
||||
const url = "https://example.com"
|
||||
await openMention(url)
|
||||
const mockUri = mockVscode.Uri.parse(url)
|
||||
expect(mockOpenExternal).toHaveBeenCalled()
|
||||
const calledArg = mockOpenExternal.mock.calls[0][0]
|
||||
expect(calledArg).toEqual(expect.objectContaining({
|
||||
scheme: mockUri.scheme,
|
||||
authority: mockUri.authority,
|
||||
path: mockUri.path,
|
||||
query: mockUri.query,
|
||||
fragment: mockUri.fragment
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -2,27 +2,28 @@ import * as vscode from "vscode"
|
||||
import * as path from "path"
|
||||
import { openFile } from "../../integrations/misc/open-file"
|
||||
import { UrlContentFetcher } from "../../services/browser/UrlContentFetcher"
|
||||
import { mentionRegexGlobal } from "../../shared/context-mentions"
|
||||
import { mentionRegexGlobal, formatGitSuggestion, type MentionSuggestion } from "../../shared/context-mentions"
|
||||
import fs from "fs/promises"
|
||||
import { extractTextFromFile } from "../../integrations/misc/extract-text"
|
||||
import { isBinaryFile } from "isbinaryfile"
|
||||
import { diagnosticsToProblemsString } from "../../integrations/diagnostics"
|
||||
import { getCommitInfo, getWorkingState } from "../../utils/git"
|
||||
|
||||
export function openMention(mention?: string): void {
|
||||
export async function openMention(mention?: string): Promise<void> {
|
||||
if (!mention) {
|
||||
return
|
||||
}
|
||||
|
||||
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
|
||||
if (!cwd) {
|
||||
return
|
||||
}
|
||||
|
||||
if (mention.startsWith("/")) {
|
||||
const relPath = mention.slice(1)
|
||||
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
|
||||
if (!cwd) {
|
||||
return
|
||||
}
|
||||
const absPath = path.resolve(cwd, relPath)
|
||||
if (mention.endsWith("/")) {
|
||||
vscode.commands.executeCommand("revealInExplorer", vscode.Uri.file(absPath))
|
||||
// vscode.commands.executeCommand("vscode.openFolder", , { forceNewWindow: false }) opens in new window
|
||||
} else {
|
||||
openFile(absPath)
|
||||
}
|
||||
@@ -40,12 +41,16 @@ export async function parseMentions(text: string, cwd: string, urlContentFetcher
|
||||
if (mention.startsWith("http")) {
|
||||
return `'${mention}' (see below for site content)`
|
||||
} else if (mention.startsWith("/")) {
|
||||
const mentionPath = mention.slice(1) // Remove the leading '/'
|
||||
const mentionPath = mention.slice(1)
|
||||
return mentionPath.endsWith("/")
|
||||
? `'${mentionPath}' (see below for folder content)`
|
||||
: `'${mentionPath}' (see below for file content)`
|
||||
} else if (mention === "problems") {
|
||||
return `Workspace Problems (see below for diagnostics)`
|
||||
} else if (mention === "git-changes") {
|
||||
return `Working directory changes (see below for details)`
|
||||
} else if (/^[a-f0-9]{7,40}$/.test(mention)) {
|
||||
return `Git commit '${mention}' (see below for commit info)`
|
||||
}
|
||||
return match
|
||||
})
|
||||
@@ -99,6 +104,20 @@ export async function parseMentions(text: string, cwd: string, urlContentFetcher
|
||||
} catch (error) {
|
||||
parsedText += `\n\n<workspace_diagnostics>\nError fetching diagnostics: ${error.message}\n</workspace_diagnostics>`
|
||||
}
|
||||
} else if (mention === "git-changes") {
|
||||
try {
|
||||
const workingState = await getWorkingState(cwd)
|
||||
parsedText += `\n\n<git_working_state>\n${workingState}\n</git_working_state>`
|
||||
} catch (error) {
|
||||
parsedText += `\n\n<git_working_state>\nError fetching working state: ${error.message}\n</git_working_state>`
|
||||
}
|
||||
} else if (/^[a-f0-9]{7,40}$/.test(mention)) {
|
||||
try {
|
||||
const commitInfo = await getCommitInfo(mention, cwd)
|
||||
parsedText += `\n\n<git_commit hash="${mention}">\n${commitInfo}\n</git_commit>`
|
||||
} catch (error) {
|
||||
parsedText += `\n\n<git_commit hash="${mention}">\nError fetching commit info: ${error.message}\n</git_commit>`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +156,6 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
|
||||
folderContent += `${linePrefix}${entry.name}\n`
|
||||
const filePath = path.join(mentionPath, entry.name)
|
||||
const absoluteFilePath = path.resolve(absPath, entry.name)
|
||||
// const relativeFilePath = path.relative(cwd, absoluteFilePath);
|
||||
fileContentPromises.push(
|
||||
(async () => {
|
||||
try {
|
||||
@@ -154,7 +172,6 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
|
||||
)
|
||||
} else if (entry.isDirectory()) {
|
||||
folderContent += `${linePrefix}${entry.name}/\n`
|
||||
// not recursively getting folder contents
|
||||
} else {
|
||||
folderContent += `${linePrefix}${entry.name}\n`
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { getNonce } from "./getNonce"
|
||||
import { getUri } from "./getUri"
|
||||
import { playSound, setSoundEnabled, setSoundVolume } from "../../utils/sound"
|
||||
import { enhancePrompt } from "../../utils/enhance-prompt"
|
||||
import { getCommitInfo, searchCommits, getWorkingState } from "../../utils/git"
|
||||
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
@@ -33,6 +34,7 @@ https://github.com/KumarVariable/vscode-extension-sidebar-html/blob/master/src/c
|
||||
|
||||
type SecretKey =
|
||||
| "apiKey"
|
||||
| "glamaApiKey"
|
||||
| "openRouterApiKey"
|
||||
| "awsAccessKey"
|
||||
| "awsSecretKey"
|
||||
@@ -45,6 +47,8 @@ type SecretKey =
|
||||
type GlobalStateKey =
|
||||
| "apiProvider"
|
||||
| "apiModelId"
|
||||
| "glamaModelId"
|
||||
| "glamaModelInfo"
|
||||
| "awsRegion"
|
||||
| "awsUseCrossRegionInference"
|
||||
| "vertexProjectId"
|
||||
@@ -64,7 +68,7 @@ type GlobalStateKey =
|
||||
| "lmStudioBaseUrl"
|
||||
| "anthropicBaseUrl"
|
||||
| "azureApiVersion"
|
||||
| "includeStreamOptions"
|
||||
| "openAiStreamingEnabled"
|
||||
| "openRouterModelId"
|
||||
| "openRouterModelInfo"
|
||||
| "openRouterUseMiddleOutTransform"
|
||||
@@ -85,6 +89,7 @@ type GlobalStateKey =
|
||||
export const GlobalFileNames = {
|
||||
apiConversationHistory: "api_conversation_history.json",
|
||||
uiMessages: "ui_messages.json",
|
||||
glamaModels: "glama_models.json",
|
||||
openRouterModels: "openrouter_models.json",
|
||||
mcpSettings: "cline_mcp_settings.json",
|
||||
}
|
||||
@@ -388,6 +393,24 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
}
|
||||
})
|
||||
this.readGlamaModels().then((glamaModels) => {
|
||||
if (glamaModels) {
|
||||
this.postMessageToWebview({ type: "glamaModels", glamaModels })
|
||||
}
|
||||
})
|
||||
this.refreshGlamaModels().then(async (glamaModels) => {
|
||||
if (glamaModels) {
|
||||
// update model info in state (this needs to be done here since we don't want to update state while settings is open, and we may refresh models there)
|
||||
const { apiConfiguration } = await this.getState()
|
||||
if (apiConfiguration.glamaModelId) {
|
||||
await this.updateGlobalState(
|
||||
"glamaModelInfo",
|
||||
glamaModels[apiConfiguration.glamaModelId],
|
||||
)
|
||||
await this.postStateToWebview()
|
||||
}
|
||||
}
|
||||
})
|
||||
break
|
||||
case "newTask":
|
||||
// Code that should run in response to the hello message command
|
||||
@@ -406,6 +429,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
apiProvider,
|
||||
apiModelId,
|
||||
apiKey,
|
||||
glamaModelId,
|
||||
glamaModelInfo,
|
||||
glamaApiKey,
|
||||
openRouterApiKey,
|
||||
awsAccessKey,
|
||||
awsSecretKey,
|
||||
@@ -425,7 +451,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
geminiApiKey,
|
||||
openAiNativeApiKey,
|
||||
azureApiVersion,
|
||||
includeStreamOptions,
|
||||
openAiStreamingEnabled,
|
||||
openRouterModelId,
|
||||
openRouterModelInfo,
|
||||
openRouterUseMiddleOutTransform,
|
||||
@@ -434,6 +460,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
await this.updateGlobalState("apiProvider", apiProvider)
|
||||
await this.updateGlobalState("apiModelId", apiModelId)
|
||||
await this.storeSecret("apiKey", apiKey)
|
||||
await this.updateGlobalState("glamaModelId", glamaModelId)
|
||||
await this.updateGlobalState("glamaModelInfo", glamaModelInfo)
|
||||
await this.storeSecret("glamaApiKey", glamaApiKey)
|
||||
await this.storeSecret("openRouterApiKey", openRouterApiKey)
|
||||
await this.storeSecret("awsAccessKey", awsAccessKey)
|
||||
await this.storeSecret("awsSecretKey", awsSecretKey)
|
||||
@@ -454,7 +483,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
await this.storeSecret("openAiNativeApiKey", openAiNativeApiKey)
|
||||
await this.storeSecret("deepSeekApiKey", message.apiConfiguration.deepSeekApiKey)
|
||||
await this.updateGlobalState("azureApiVersion", azureApiVersion)
|
||||
await this.updateGlobalState("includeStreamOptions", includeStreamOptions)
|
||||
await this.updateGlobalState("openAiStreamingEnabled", openAiStreamingEnabled)
|
||||
await this.updateGlobalState("openRouterModelId", openRouterModelId)
|
||||
await this.updateGlobalState("openRouterModelInfo", openRouterModelInfo)
|
||||
await this.updateGlobalState("openRouterUseMiddleOutTransform", openRouterUseMiddleOutTransform)
|
||||
@@ -534,6 +563,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
const vsCodeLmModels = await this.getVsCodeLmModels()
|
||||
this.postMessageToWebview({ type: "vsCodeLmModels", vsCodeLmModels })
|
||||
break
|
||||
case "refreshGlamaModels":
|
||||
await this.refreshGlamaModels()
|
||||
break
|
||||
case "refreshOpenRouterModels":
|
||||
await this.refreshOpenRouterModels()
|
||||
break
|
||||
@@ -710,6 +742,24 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
|
||||
case "searchCommits": {
|
||||
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
|
||||
if (cwd) {
|
||||
try {
|
||||
const commits = await searchCommits(message.query || "", cwd)
|
||||
await this.postMessageToWebview({
|
||||
type: "commitSearchResults",
|
||||
commits
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("Error searching commits:", error)
|
||||
vscode.window.showErrorMessage("Failed to search commits")
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
@@ -851,6 +901,94 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
return cacheDir
|
||||
}
|
||||
|
||||
async readGlamaModels(): Promise<Record<string, ModelInfo> | undefined> {
|
||||
const glamaModelsFilePath = path.join(
|
||||
await this.ensureCacheDirectoryExists(),
|
||||
GlobalFileNames.glamaModels,
|
||||
)
|
||||
const fileExists = await fileExistsAtPath(glamaModelsFilePath)
|
||||
if (fileExists) {
|
||||
const fileContents = await fs.readFile(glamaModelsFilePath, "utf8")
|
||||
return JSON.parse(fileContents)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
async refreshGlamaModels() {
|
||||
const glamaModelsFilePath = path.join(
|
||||
await this.ensureCacheDirectoryExists(),
|
||||
GlobalFileNames.glamaModels,
|
||||
)
|
||||
|
||||
let models: Record<string, ModelInfo> = {}
|
||||
try {
|
||||
const response = await axios.get("https://glama.ai/api/gateway/v1/models")
|
||||
/*
|
||||
{
|
||||
"added": "2024-12-24T15:12:49.324Z",
|
||||
"capabilities": [
|
||||
"adjustable_safety_settings",
|
||||
"caching",
|
||||
"code_execution",
|
||||
"function_calling",
|
||||
"json_mode",
|
||||
"json_schema",
|
||||
"system_instructions",
|
||||
"tuning",
|
||||
"input:audio",
|
||||
"input:image",
|
||||
"input:text",
|
||||
"input:video",
|
||||
"output:text"
|
||||
],
|
||||
"id": "google-vertex/gemini-1.5-flash-002",
|
||||
"maxTokensInput": 1048576,
|
||||
"maxTokensOutput": 8192,
|
||||
"pricePerToken": {
|
||||
"cacheRead": null,
|
||||
"cacheWrite": null,
|
||||
"input": "0.000000075",
|
||||
"output": "0.0000003"
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (response.data) {
|
||||
const rawModels = response.data;
|
||||
const parsePrice = (price: any) => {
|
||||
if (price) {
|
||||
return parseFloat(price) * 1_000_000
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
for (const rawModel of rawModels) {
|
||||
const modelInfo: ModelInfo = {
|
||||
maxTokens: rawModel.maxTokensOutput,
|
||||
contextWindow: rawModel.maxTokensInput,
|
||||
supportsImages: rawModel.capabilities?.includes("input:image"),
|
||||
supportsComputerUse: rawModel.capabilities?.includes("computer_use"),
|
||||
supportsPromptCache: rawModel.capabilities?.includes("caching"),
|
||||
inputPrice: parsePrice(rawModel.pricePerToken?.input),
|
||||
outputPrice: parsePrice(rawModel.pricePerToken?.output),
|
||||
description: undefined,
|
||||
cacheWritesPrice: parsePrice(rawModel.pricePerToken?.cacheWrite),
|
||||
cacheReadsPrice: parsePrice(rawModel.pricePerToken?.cacheRead),
|
||||
}
|
||||
|
||||
models[rawModel.id] = modelInfo
|
||||
}
|
||||
} else {
|
||||
console.error("Invalid response from Glama API")
|
||||
}
|
||||
await fs.writeFile(glamaModelsFilePath, JSON.stringify(models))
|
||||
console.log("Glama models fetched and saved", models)
|
||||
} catch (error) {
|
||||
console.error("Error fetching Glama models:", error)
|
||||
}
|
||||
|
||||
await this.postMessageToWebview({ type: "glamaModels", glamaModels: models })
|
||||
return models
|
||||
}
|
||||
|
||||
async readOpenRouterModels(): Promise<Record<string, ModelInfo> | undefined> {
|
||||
const openRouterModelsFilePath = path.join(
|
||||
await this.ensureCacheDirectoryExists(),
|
||||
@@ -1174,6 +1312,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
storedApiProvider,
|
||||
apiModelId,
|
||||
apiKey,
|
||||
glamaApiKey,
|
||||
glamaModelId,
|
||||
glamaModelInfo,
|
||||
openRouterApiKey,
|
||||
awsAccessKey,
|
||||
awsSecretKey,
|
||||
@@ -1194,7 +1335,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
openAiNativeApiKey,
|
||||
deepSeekApiKey,
|
||||
azureApiVersion,
|
||||
includeStreamOptions,
|
||||
openAiStreamingEnabled,
|
||||
openRouterModelId,
|
||||
openRouterModelInfo,
|
||||
openRouterUseMiddleOutTransform,
|
||||
@@ -1222,6 +1363,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
|
||||
this.getGlobalState("apiModelId") as Promise<string | undefined>,
|
||||
this.getSecret("apiKey") as Promise<string | undefined>,
|
||||
this.getSecret("glamaApiKey") as Promise<string | undefined>,
|
||||
this.getGlobalState("glamaModelId") as Promise<string | undefined>,
|
||||
this.getGlobalState("glamaModelInfo") as Promise<ModelInfo | undefined>,
|
||||
this.getSecret("openRouterApiKey") as Promise<string | undefined>,
|
||||
this.getSecret("awsAccessKey") as Promise<string | undefined>,
|
||||
this.getSecret("awsSecretKey") as Promise<string | undefined>,
|
||||
@@ -1242,7 +1386,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
this.getSecret("openAiNativeApiKey") as Promise<string | undefined>,
|
||||
this.getSecret("deepSeekApiKey") as Promise<string | undefined>,
|
||||
this.getGlobalState("azureApiVersion") as Promise<string | undefined>,
|
||||
this.getGlobalState("includeStreamOptions") as Promise<boolean | undefined>,
|
||||
this.getGlobalState("openAiStreamingEnabled") as Promise<boolean | undefined>,
|
||||
this.getGlobalState("openRouterModelId") as Promise<string | undefined>,
|
||||
this.getGlobalState("openRouterModelInfo") as Promise<ModelInfo | undefined>,
|
||||
this.getGlobalState("openRouterUseMiddleOutTransform") as Promise<boolean | undefined>,
|
||||
@@ -1287,6 +1431,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
apiProvider,
|
||||
apiModelId,
|
||||
apiKey,
|
||||
glamaApiKey,
|
||||
glamaModelId,
|
||||
glamaModelInfo,
|
||||
openRouterApiKey,
|
||||
awsAccessKey,
|
||||
awsSecretKey,
|
||||
@@ -1307,7 +1454,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
openAiNativeApiKey,
|
||||
deepSeekApiKey,
|
||||
azureApiVersion,
|
||||
includeStreamOptions,
|
||||
openAiStreamingEnabled,
|
||||
openRouterModelId,
|
||||
openRouterModelInfo,
|
||||
openRouterUseMiddleOutTransform,
|
||||
@@ -1426,6 +1573,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
const secretKeys: SecretKey[] = [
|
||||
"apiKey",
|
||||
"glamaApiKey",
|
||||
"openRouterApiKey",
|
||||
"awsAccessKey",
|
||||
"awsSecretKey",
|
||||
|
||||
Reference in New Issue
Block a user