From d50e075c75842d98e07f48f771d425b9f5c0404f Mon Sep 17 00:00:00 2001 From: sam hoang Date: Sun, 12 Jan 2025 19:28:25 +0700 Subject: [PATCH 1/5] feat(openai): add custom model info configuration Adds support for configuring custom OpenAI-compatible model capabilities and pricing, including: Max output tokens Context window size Image/computer use support Input/output token pricing Cache read/write pricing --- src/api/providers/openai.ts | 2 +- src/core/webview/ClineProvider.ts | 6 + src/shared/WebviewMessage.ts | 1 + src/shared/api.ts | 1 + .../src/components/settings/ApiOptions.tsx | 180 +++++++++++++++++- 5 files changed, 188 insertions(+), 2 deletions(-) diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index 13922a4..c2c3a89 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -108,7 +108,7 @@ export class OpenAiHandler implements ApiHandler, SingleCompletionHandler { getModel(): { id: string; info: ModelInfo } { return { id: this.options.openAiModelId ?? "", - info: openAiModelInfoSaneDefaults, + info: this.options.openAiCusModelInfo ?? openAiModelInfoSaneDefaults, } } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 72e7e27..771aae3 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -68,6 +68,7 @@ type GlobalStateKey = | "taskHistory" | "openAiBaseUrl" | "openAiModelId" + | "openAiCusModelInfo" | "ollamaModelId" | "ollamaBaseUrl" | "lmStudioModelId" @@ -1198,6 +1199,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiBaseUrl, openAiApiKey, openAiModelId, + openAiCusModelInfo, ollamaModelId, ollamaBaseUrl, lmStudioModelId, @@ -1231,6 +1233,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("openAiBaseUrl", openAiBaseUrl) await this.storeSecret("openAiApiKey", openAiApiKey) await this.updateGlobalState("openAiModelId", openAiModelId) + await this.updateGlobalState("openAiCusModelInfo", openAiCusModelInfo) await this.updateGlobalState("ollamaModelId", ollamaModelId) await this.updateGlobalState("ollamaBaseUrl", ollamaBaseUrl) await this.updateGlobalState("lmStudioModelId", lmStudioModelId) @@ -1847,6 +1850,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiBaseUrl, openAiApiKey, openAiModelId, + openAiCusModelInfo, ollamaModelId, ollamaBaseUrl, lmStudioModelId, @@ -1910,6 +1914,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getGlobalState("openAiBaseUrl") as Promise, this.getSecret("openAiApiKey") as Promise, this.getGlobalState("openAiModelId") as Promise, + this.getGlobalState("openAiCusModelInfo") as Promise, this.getGlobalState("ollamaModelId") as Promise, this.getGlobalState("ollamaBaseUrl") as Promise, this.getGlobalState("lmStudioModelId") as Promise, @@ -1990,6 +1995,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiBaseUrl, openAiApiKey, openAiModelId, + openAiCusModelInfo, ollamaModelId, ollamaBaseUrl, lmStudioModelId, diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index ce05976..5aaaa82 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -76,6 +76,7 @@ export interface WebviewMessage { | "autoApprovalEnabled" | "updateCustomMode" | "deleteCustomMode" + | "setOpenAiCusModelInfo" text?: string disabled?: boolean askResponse?: ClineAskResponse diff --git a/src/shared/api.ts b/src/shared/api.ts index 8f65c67..5524a1e 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -38,6 +38,7 @@ export interface ApiHandlerOptions { openAiBaseUrl?: string openAiApiKey?: string openAiModelId?: string + openAiCusModelInfo?: ModelInfo ollamaModelId?: string ollamaBaseUrl?: string lmStudioModelId?: string diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 561ae5b..9fbb6d8 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -550,6 +550,184 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = placeholder={`Default: ${azureOpenAiDefaultApiVersion}`} /> )} + + {/* Model Info Configuration */} +
+
+ Model Configuration +

+ Configure the capabilities and pricing for your custom OpenAI-compatible model +

+
+ + {/* Capabilities Section */} +
+ Capabilities +
+ { + const value = parseInt(e.target.value) + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + maxTokens: isNaN(value) ? undefined : value + } + }) + }} + placeholder="e.g. 4096"> + Max Output Tokens + + + { + const parsed = parseInt(e.target.value) + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + contextWindow: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.contextWindow : parsed) + } + }) + }} + placeholder="e.g. 128000"> + Context Window Size + + +
+ { + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + supportsImages: e.target.checked + } + }) + }}> + Supports Images + + + { + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + supportsComputerUse: e.target.checked + } + }) + }}> + Supports Computer Use + +
+
+
+ + {/* Pricing Section */} +
+ Pricing (USD per million tokens) +
+ {/* Input/Output Prices */} +
+ { + const parsed = parseFloat(e.target.value) + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + inputPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.inputPrice : parsed) + } + }) + }} + placeholder="e.g. 0.0001"> + Input Price + + + { + const parsed = parseFloat(e.target.value) + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + outputPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.outputPrice : parsed) + } + }) + }} + placeholder="e.g. 0.0002"> + Output Price + +
+ + {/* Cache Prices */} +
+ { + const parsed = parseFloat(e.target.value) + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + cacheWritesPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.cacheWritesPrice : parsed) + } + }) + }} + placeholder="e.g. 0.0001"> + Cache Write Price + + + { + const parsed = parseFloat(e.target.value) + setApiConfiguration({ + ...apiConfiguration, + openAiCusModelInfo: { + ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), + cacheReadsPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.cacheReadsPrice : parsed) + } + }) + }} + placeholder="e.g. 0.00001"> + Cache Read Price + +
+
+
+
+ + { /* TODO: model info here */} + +

Date: Sun, 19 Jan 2025 00:34:05 +0700 Subject: [PATCH 2/5] fix ui and some error my has --- .../src/components/settings/ApiOptions.tsx | 223 ++++++++++-------- 1 file changed, 126 insertions(+), 97 deletions(-) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 9fbb6d8..a9ec8d5 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -166,7 +166,11 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = onChange={(checked: boolean) => { setAnthropicBaseUrlSelected(checked) if (!checked) { - setApiConfiguration({ ...apiConfiguration, anthropicBaseUrl: "" }) + handleInputChange("anthropicBaseUrl")({ + target: { + value: "", + }, + }) } }}> Use custom base URL @@ -537,7 +541,11 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = onChange={(checked: boolean) => { setAzureApiVersionSelected(checked) if (!checked) { - setApiConfiguration({ ...apiConfiguration, azureApiVersion: "" }) + handleInputChange("azureApiVersion")({ + target: { + value: "", + }, + }) } }}> Set Azure API version @@ -552,31 +560,47 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = )} {/* Model Info Configuration */} -

+
- Model Configuration -

+ Model Configuration +

Configure the capabilities and pricing for your custom OpenAI-compatible model

{/* Capabilities Section */}
- Capabilities
{ const value = parseInt(e.target.value) - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - maxTokens: isNaN(value) ? undefined : value - } + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + maxTokens: isNaN(value) ? undefined : value, + }, + }, }) }} placeholder="e.g. 4096"> @@ -584,18 +608,29 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = { const parsed = parseInt(e.target.value) - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - contextWindow: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.contextWindow : parsed) - } + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + contextWindow: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.contextWindow + : parsed, + }, + }, }) }} placeholder="e.g. 128000"> @@ -603,58 +638,83 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
- { - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - supportsImages: e.target.checked - } + onChange={(checked: boolean) => { + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + supportsImages: checked, + }, + }, }) }}> Supports Images - + - { - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - supportsComputerUse: e.target.checked - } + onChange={(checked: boolean) => { + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + supportsComputerUse: checked, + }, + }, }) }}> Supports Computer Use - +
{/* Pricing Section */}
- Pricing (USD per million tokens) + + Pricing (USD per million tokens) +
{/* Input/Output Prices */}
{ const parsed = parseFloat(e.target.value) - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - inputPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.inputPrice : parsed) - } + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo ?? + openAiModelInfoSaneDefaults), + inputPrice: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.inputPrice + : parsed, + }, + }, }) }} placeholder="e.g. 0.0001"> @@ -662,71 +722,40 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = { const parsed = parseFloat(e.target.value) - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - outputPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.outputPrice : parsed) - } + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + outputPrice: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.outputPrice + : parsed, + }, + }, }) }} placeholder="e.g. 0.0002"> Output Price
- - {/* Cache Prices */} -
- { - const parsed = parseFloat(e.target.value) - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - cacheWritesPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.cacheWritesPrice : parsed) - } - }) - }} - placeholder="e.g. 0.0001"> - Cache Write Price - - - { - const parsed = parseFloat(e.target.value) - setApiConfiguration({ - ...apiConfiguration, - openAiCusModelInfo: { - ...(apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults), - cacheReadsPrice: e.target.value === "" ? undefined : (isNaN(parsed) ? openAiModelInfoSaneDefaults.cacheReadsPrice : parsed) - } - }) - }} - placeholder="e.g. 0.00001"> - Cache Read Price - -
- { /* TODO: model info here */} - + {/* TODO: model info here */}

Date: Sun, 19 Jan 2025 15:19:21 +0700 Subject: [PATCH 3/5] feat(openai-compatible): tune UI UX custom model info --- .../src/components/settings/ApiOptions.tsx | 578 ++++++++++++------ 1 file changed, 400 insertions(+), 178 deletions(-) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index a9ec8d5..083c35b 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -1,4 +1,4 @@ -import { Checkbox, Dropdown } from "vscrui" +import { Checkbox, Dropdown, Pane } from "vscrui" import type { DropdownOption } from "vscrui" import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react" @@ -559,203 +559,425 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = /> )} - {/* Model Info Configuration */}

-
- Model Configuration + }} + /> + + handleInputChange("openAiCusModelInfo")({ + target: { value: openAiModelInfoSaneDefaults }, + }), + }, + ]}> +

Configure the capabilities and pricing for your custom OpenAI-compatible model

-
- {/* Capabilities Section */} -
-
- { - const value = parseInt(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - maxTokens: isNaN(value) ? undefined : value, - }, - }, - }) - }} - placeholder="e.g. 4096"> - Max Output Tokens - - - { - const parsed = parseInt(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - contextWindow: - e.target.value === "" - ? undefined - : isNaN(parsed) - ? openAiModelInfoSaneDefaults.contextWindow - : parsed, - }, - }, - }) - }} - placeholder="e.g. 128000"> - Context Window Size - - -
- { - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - supportsImages: checked, - }, - }, - }) - }}> - Supports Images - - - { - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - supportsComputerUse: checked, - }, - }, - }) - }}> - Supports Computer Use - -
-
-
- - {/* Pricing Section */} -
- - Pricing (USD per million tokens) - -
- {/* Input/Output Prices */} -
- { - const parsed = parseFloat(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo ?? - openAiModelInfoSaneDefaults), - inputPrice: - e.target.value === "" - ? undefined - : isNaN(parsed) - ? openAiModelInfoSaneDefaults.inputPrice - : parsed, + + Model Capabilities + +
+
+ { + const value = apiConfiguration?.openAiCusModelInfo?.maxTokens + if (!value) return "var(--vscode-input-border)" + return value > 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + title="Maximum number of tokens the model can generate in a single response" + onChange={(e: any) => { + const value = parseInt(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + maxTokens: isNaN(value) ? undefined : value, + }, }, - }, - }) - }} - placeholder="e.g. 0.0001"> - Input Price - + }) + }} + placeholder="e.g. 4096"> + Max Output Tokens + +
+ + + Maximum number of tokens the model can generate in a response. Higher + values allow longer outputs but may increase costs. + +
+
- { - const parsed = parseFloat(e.target.value) - handleInputChange("openAiCusModelInfo")({ - target: { - value: { - ...(apiConfiguration?.openAiCusModelInfo || - openAiModelInfoSaneDefaults), - outputPrice: - e.target.value === "" - ? undefined - : isNaN(parsed) - ? openAiModelInfoSaneDefaults.outputPrice - : parsed, +
+ { + const value = apiConfiguration?.openAiCusModelInfo?.contextWindow + if (!value) return "var(--vscode-input-border)" + return value > 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + title="Total number of tokens (input + output) the model can process in a single request" + onChange={(e: any) => { + const parsed = parseInt(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + contextWindow: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.contextWindow + : parsed, + }, }, - }, - }) - }} - placeholder="e.g. 0.0002"> - Output Price - + }) + }} + placeholder="e.g. 128000"> + Context Window Size + +
+ + + Total tokens (input + output) the model can process. Larger windows + allow processing more content but may increase memory usage. + +
+
+ +
+ + Model Features + + +
+
+
+ { + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + supportsImages: checked, + }, + }, + }) + }}> + Image Support + + +
+

+ Allows the model to analyze and understand images, essential for + visual code assistance +

+
+ +
+
+ { + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + supportsComputerUse: checked, + }, + }, + }) + }}> + Computer Interaction + + +
+

+ Enables the model to execute commands and modify files for automated + assistance +

+
+
+
+
+
+ + {/* Pricing Section */} +
+
+ + Model Pricing + + + Configure token-based pricing in USD per million tokens + +
+ +
+
+ { + const value = apiConfiguration?.openAiCusModelInfo?.inputPrice + if (!value && value !== 0) return "var(--vscode-input-border)" + return value >= 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + onChange={(e: any) => { + const parsed = parseFloat(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo ?? + openAiModelInfoSaneDefaults), + inputPrice: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.inputPrice + : parsed, + }, + }, + }) + }} + placeholder="e.g. 0.0001"> +
+ Input Price + +
+
+
+ +
+ { + const value = apiConfiguration?.openAiCusModelInfo?.outputPrice + if (!value && value !== 0) return "var(--vscode-input-border)" + return value >= 0 + ? "var(--vscode-charts-green)" + : "var(--vscode-errorForeground)" + })(), + }} + onChange={(e: any) => { + const parsed = parseFloat(e.target.value) + handleInputChange("openAiCusModelInfo")({ + target: { + value: { + ...(apiConfiguration?.openAiCusModelInfo || + openAiModelInfoSaneDefaults), + outputPrice: + e.target.value === "" + ? undefined + : isNaN(parsed) + ? openAiModelInfoSaneDefaults.outputPrice + : parsed, + }, + }, + }) + }} + placeholder="e.g. 0.0002"> +
+ Output Price + +
+
+
-
+
- {/* TODO: model info here */} + {/* end Model Info Configuration */}

Date: Tue, 21 Jan 2025 23:06:07 +0700 Subject: [PATCH 4/5] refactor: rename openAiCusModelInfo to openAiCustomModelInfo for better clarity - Rename openAiCusModelInfo to openAiCustomModelInfo across all files for better readability - Update related variable names and references to maintain consistency - Affects OpenAI provider, ClineProvider, WebviewMessage, API interfaces, and UI components --- src/api/providers/openai.ts | 2 +- src/core/webview/ClineProvider.ts | 12 ++--- src/shared/WebviewMessage.ts | 2 +- src/shared/api.ts | 2 +- .../src/components/settings/ApiOptions.tsx | 52 +++++++++---------- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index c2c3a89..d71a51f 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -108,7 +108,7 @@ export class OpenAiHandler implements ApiHandler, SingleCompletionHandler { getModel(): { id: string; info: ModelInfo } { return { id: this.options.openAiModelId ?? "", - info: this.options.openAiCusModelInfo ?? openAiModelInfoSaneDefaults, + info: this.options.openAiCustomModelInfo ?? openAiModelInfoSaneDefaults, } } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 771aae3..23fe36e 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -68,7 +68,7 @@ type GlobalStateKey = | "taskHistory" | "openAiBaseUrl" | "openAiModelId" - | "openAiCusModelInfo" + | "openAiCustomModelInfo" | "ollamaModelId" | "ollamaBaseUrl" | "lmStudioModelId" @@ -1199,7 +1199,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiBaseUrl, openAiApiKey, openAiModelId, - openAiCusModelInfo, + openAiCustomModelInfo, ollamaModelId, ollamaBaseUrl, lmStudioModelId, @@ -1233,7 +1233,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("openAiBaseUrl", openAiBaseUrl) await this.storeSecret("openAiApiKey", openAiApiKey) await this.updateGlobalState("openAiModelId", openAiModelId) - await this.updateGlobalState("openAiCusModelInfo", openAiCusModelInfo) + await this.updateGlobalState("openAiCustomModelInfo", openAiCustomModelInfo) await this.updateGlobalState("ollamaModelId", ollamaModelId) await this.updateGlobalState("ollamaBaseUrl", ollamaBaseUrl) await this.updateGlobalState("lmStudioModelId", lmStudioModelId) @@ -1850,7 +1850,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiBaseUrl, openAiApiKey, openAiModelId, - openAiCusModelInfo, + openAiCustomModelInfo, ollamaModelId, ollamaBaseUrl, lmStudioModelId, @@ -1914,7 +1914,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getGlobalState("openAiBaseUrl") as Promise, this.getSecret("openAiApiKey") as Promise, this.getGlobalState("openAiModelId") as Promise, - this.getGlobalState("openAiCusModelInfo") as Promise, + this.getGlobalState("openAiCustomModelInfo") as Promise, this.getGlobalState("ollamaModelId") as Promise, this.getGlobalState("ollamaBaseUrl") as Promise, this.getGlobalState("lmStudioModelId") as Promise, @@ -1995,7 +1995,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { openAiBaseUrl, openAiApiKey, openAiModelId, - openAiCusModelInfo, + openAiCustomModelInfo, ollamaModelId, ollamaBaseUrl, lmStudioModelId, diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 5aaaa82..5705378 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -76,7 +76,7 @@ export interface WebviewMessage { | "autoApprovalEnabled" | "updateCustomMode" | "deleteCustomMode" - | "setOpenAiCusModelInfo" + | "setopenAiCustomModelInfo" text?: string disabled?: boolean askResponse?: ClineAskResponse diff --git a/src/shared/api.ts b/src/shared/api.ts index 5524a1e..8d7b919 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -38,7 +38,7 @@ export interface ApiHandlerOptions { openAiBaseUrl?: string openAiApiKey?: string openAiModelId?: string - openAiCusModelInfo?: ModelInfo + openAiCustomModelInfo?: ModelInfo ollamaModelId?: string ollamaBaseUrl?: string lmStudioModelId?: string diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 083c35b..cda5191 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -45,7 +45,7 @@ interface ApiOptionsProps { } const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) => { - const { apiConfiguration, setApiConfiguration, uriScheme, handleInputChange } = useExtensionState() + const { apiConfiguration, uriScheme, handleInputChange } = useExtensionState() const [ollamaModels, setOllamaModels] = useState([]) const [lmStudioModels, setLmStudioModels] = useState([]) const [vsCodeLmModels, setVsCodeLmModels] = useState([]) @@ -571,7 +571,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = { iconName: "refresh", onClick: () => - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: openAiModelInfoSaneDefaults }, }), }, @@ -613,7 +613,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =

{ - const value = apiConfiguration?.openAiCusModelInfo?.maxTokens + const value = apiConfiguration?.openAiCustomModelInfo?.maxTokens if (!value) return "var(--vscode-input-border)" return value > 0 ? "var(--vscode-charts-green)" @@ -631,10 +631,10 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = title="Maximum number of tokens the model can generate in a single response" onChange={(e: any) => { const value = parseInt(e.target.value) - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: { - ...(apiConfiguration?.openAiCusModelInfo || + ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), maxTokens: isNaN(value) ? undefined : value, }, @@ -664,7 +664,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
{ - const value = apiConfiguration?.openAiCusModelInfo?.contextWindow + const value = apiConfiguration?.openAiCustomModelInfo?.contextWindow if (!value) return "var(--vscode-input-border)" return value > 0 ? "var(--vscode-charts-green)" @@ -682,10 +682,10 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = title="Total number of tokens (input + output) the model can process in a single request" onChange={(e: any) => { const parsed = parseInt(e.target.value) - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: { - ...(apiConfiguration?.openAiCusModelInfo || + ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), contextWindow: e.target.value === "" @@ -742,14 +742,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
{ - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: { - ...(apiConfiguration?.openAiCusModelInfo || + ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), supportsImages: checked, }, @@ -790,14 +790,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
{ - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: { - ...(apiConfiguration?.openAiCusModelInfo || + ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), supportsComputerUse: checked, }, @@ -874,7 +874,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
{ - const value = apiConfiguration?.openAiCusModelInfo?.inputPrice + const value = apiConfiguration?.openAiCustomModelInfo?.inputPrice if (!value && value !== 0) return "var(--vscode-input-border)" return value >= 0 ? "var(--vscode-charts-green)" @@ -891,10 +891,10 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = }} onChange={(e: any) => { const parsed = parseFloat(e.target.value) - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: { - ...(apiConfiguration?.openAiCusModelInfo ?? + ...(apiConfiguration?.openAiCustomModelInfo ?? openAiModelInfoSaneDefaults), inputPrice: e.target.value === "" @@ -925,7 +925,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
{ - const value = apiConfiguration?.openAiCusModelInfo?.outputPrice + const value = apiConfiguration?.openAiCustomModelInfo?.outputPrice if (!value && value !== 0) return "var(--vscode-input-border)" return value >= 0 ? "var(--vscode-charts-green)" @@ -942,10 +942,10 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = }} onChange={(e: any) => { const parsed = parseFloat(e.target.value) - handleInputChange("openAiCusModelInfo")({ + handleInputChange("openAiCustomModelInfo")({ target: { value: { - ...(apiConfiguration?.openAiCusModelInfo || + ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), outputPrice: e.target.value === "" @@ -1460,7 +1460,7 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) { return { selectedProvider: provider, selectedModelId: apiConfiguration?.openAiModelId || "", - selectedModelInfo: apiConfiguration?.openAiCusModelInfo || openAiModelInfoSaneDefaults, + selectedModelInfo: apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults, } case "ollama": return { From 95fa1e400d397418020e86ba8a80e2499772eba2 Mon Sep 17 00:00:00 2001 From: sam hoang Date: Tue, 21 Jan 2025 23:42:31 +0700 Subject: [PATCH 5/5] update: Improve model configuration UI text and styling - Clarify model capabilities description and impact on Roo Code - Update max tokens description to mention server dependency - Rename 'Computer Interaction' to 'Computer Use' for clarity - Add spacing after model info configuration section --- .../src/components/settings/ApiOptions.tsx | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index cda5191..13e7a57 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -588,7 +588,8 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = margin: "0 0 15px 0", lineHeight: "1.4", }}> - Configure the capabilities and pricing for your custom OpenAI-compatible model + Configure the capabilities and pricing for your custom OpenAI-compatible model.
+ Be careful for the model capabilities, as they can affect how Roo Code can work.

{/* Capabilities Section */} @@ -655,8 +656,8 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = }}> - Maximum number of tokens the model can generate in a response. Higher - values allow longer outputs but may increase costs. + Maximum number of tokens the model can generate in a response.
+ (-1 is depend on server)
@@ -711,8 +712,8 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = }}> - Total tokens (input + output) the model can process. Larger windows - allow processing more content but may increase memory usage. + Total tokens (input + output) the model can process. This will help Roo + Code run correctly.
@@ -804,7 +805,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = }, }) }}> - Computer Interaction + Computer Use - Enables the model to execute commands and modify files for automated - assistance + This model feature is for computer use like sonnet 3.5 support

@@ -976,6 +976,11 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
+
{/* end Model Info Configuration */}