|
|
@@ -12,9 +12,9 @@ import { selectImages } from "../../integrations/misc/process-images"
|
|
|
import { getTheme } from "../../integrations/theme/getTheme"
|
|
|
import WorkspaceTracker from "../../integrations/workspace/WorkspaceTracker"
|
|
|
import { McpHub } from "../../services/mcp/McpHub"
|
|
|
-import { ApiProvider, ModelInfo } from "../../shared/api"
|
|
|
+import { ApiConfiguration, ApiProvider, ModelInfo } from "../../shared/api"
|
|
|
import { findLast } from "../../shared/array"
|
|
|
-import { ExtensionMessage } from "../../shared/ExtensionMessage"
|
|
|
+import { ApiConfigMeta, ExtensionMessage } from "../../shared/ExtensionMessage"
|
|
|
import { HistoryItem } from "../../shared/HistoryItem"
|
|
|
import { WebviewMessage } from "../../shared/WebviewMessage"
|
|
|
import { fileExistsAtPath } from "../../utils/fs"
|
|
|
@@ -23,8 +23,10 @@ import { openMention } from "../mentions"
|
|
|
import { getNonce } from "./getNonce"
|
|
|
import { getUri } from "./getUri"
|
|
|
import { playSound, setSoundEnabled, setSoundVolume } from "../../utils/sound"
|
|
|
+import { checkExistKey } from "../../shared/checkExistApiConfig"
|
|
|
import { enhancePrompt } from "../../utils/enhance-prompt"
|
|
|
import { getCommitInfo, searchCommits, getWorkingState } from "../../utils/git"
|
|
|
+import { ConfigManager } from "../config/ConfigManager"
|
|
|
|
|
|
/*
|
|
|
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
|
|
@@ -84,6 +86,10 @@ type GlobalStateKey =
|
|
|
| "writeDelayMs"
|
|
|
| "terminalOutputLineLimit"
|
|
|
| "mcpEnabled"
|
|
|
+ | "alwaysApproveResubmit"
|
|
|
+ | "requestDelaySeconds"
|
|
|
+ | "currentApiConfigName"
|
|
|
+ | "listApiConfigMeta"
|
|
|
| "vsCodeLmModelSelector"
|
|
|
|
|
|
export const GlobalFileNames = {
|
|
|
@@ -104,6 +110,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
private workspaceTracker?: WorkspaceTracker
|
|
|
mcpHub?: McpHub
|
|
|
private latestAnnouncementId = "dec-10-2024" // update to some unique identifier when we add a new announcement
|
|
|
+ configManager: ConfigManager
|
|
|
|
|
|
constructor(
|
|
|
readonly context: vscode.ExtensionContext,
|
|
|
@@ -113,6 +120,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
ClineProvider.activeInstances.add(this)
|
|
|
this.workspaceTracker = new WorkspaceTracker(this)
|
|
|
this.mcpHub = new McpHub(this)
|
|
|
+ this.configManager = new ConfigManager(this.context)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -411,6 +419,55 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
+
|
|
|
+
|
|
|
+ this.configManager.ListConfig().then(async (listApiConfig) => {
|
|
|
+
|
|
|
+ if (!listApiConfig) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (listApiConfig.length === 1) {
|
|
|
+ // check if first time init then sync with exist config
|
|
|
+ if (!checkExistKey(listApiConfig[0])) {
|
|
|
+ const {
|
|
|
+ apiConfiguration,
|
|
|
+ } = await this.getState()
|
|
|
+ await this.configManager.SaveConfig(listApiConfig[0].name ?? "default", apiConfiguration)
|
|
|
+ listApiConfig[0].apiProvider = apiConfiguration.apiProvider
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let currentConfigName = await this.getGlobalState("currentApiConfigName") as string
|
|
|
+
|
|
|
+ if (currentConfigName) {
|
|
|
+ if (!await this.configManager.HasConfig(currentConfigName)) {
|
|
|
+ // current config name not valid, get first config in list
|
|
|
+ await this.updateGlobalState("currentApiConfigName", listApiConfig?.[0]?.name)
|
|
|
+ if (listApiConfig?.[0]?.name) {
|
|
|
+ const apiConfig = await this.configManager.LoadConfig(listApiConfig?.[0]?.name);
|
|
|
+
|
|
|
+ await Promise.all([
|
|
|
+ this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
|
|
+ this.postMessageToWebview({ type: "listApiConfig", listApiConfig }),
|
|
|
+ this.updateApiConfiguration(apiConfig),
|
|
|
+ ])
|
|
|
+ await this.postStateToWebview()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ await Promise.all(
|
|
|
+ [
|
|
|
+ await this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
|
|
+ await this.postMessageToWebview({ type: "listApiConfig", listApiConfig })
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ }).catch(console.error);
|
|
|
+
|
|
|
break
|
|
|
case "newTask":
|
|
|
// Code that should run in response to the hello message command
|
|
|
@@ -491,6 +548,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
if (this.cline) {
|
|
|
this.cline.api = buildApiHandler(message.apiConfiguration)
|
|
|
}
|
|
|
+ await this.updateApiConfiguration(message.apiConfiguration)
|
|
|
}
|
|
|
await this.postStateToWebview()
|
|
|
break
|
|
|
@@ -684,6 +742,14 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
await this.updateGlobalState("fuzzyMatchThreshold", message.value)
|
|
|
await this.postStateToWebview()
|
|
|
break
|
|
|
+ case "alwaysApproveResubmit":
|
|
|
+ await this.updateGlobalState("alwaysApproveResubmit", message.bool ?? false)
|
|
|
+ await this.postStateToWebview()
|
|
|
+ break
|
|
|
+ case "requestDelaySeconds":
|
|
|
+ await this.updateGlobalState("requestDelaySeconds", message.value ?? 5)
|
|
|
+ await this.postStateToWebview()
|
|
|
+ break
|
|
|
case "preferredLanguage":
|
|
|
await this.updateGlobalState("preferredLanguage", message.text)
|
|
|
await this.postStateToWebview()
|
|
|
@@ -698,21 +764,65 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
break
|
|
|
case "deleteMessage": {
|
|
|
const answer = await vscode.window.showInformationMessage(
|
|
|
- "Are you sure you want to delete this message and all subsequent messages?",
|
|
|
+ "What would you like to delete?",
|
|
|
{ modal: true },
|
|
|
- "Yes",
|
|
|
- "No"
|
|
|
+ "Just this message",
|
|
|
+ "This and all subsequent messages",
|
|
|
)
|
|
|
- if (answer === "Yes" && this.cline && typeof message.value === 'number' && message.value) {
|
|
|
+ if ((answer === "Just this message" || answer === "This and all subsequent messages") &&
|
|
|
+ this.cline && typeof message.value === 'number' && message.value) {
|
|
|
const timeCutoff = message.value - 1000; // 1 second buffer before the message to delete
|
|
|
const messageIndex = this.cline.clineMessages.findIndex(msg => msg.ts && msg.ts >= timeCutoff)
|
|
|
const apiConversationHistoryIndex = this.cline.apiConversationHistory.findIndex(msg => msg.ts && msg.ts >= timeCutoff)
|
|
|
+
|
|
|
if (messageIndex !== -1) {
|
|
|
const { historyItem } = await this.getTaskWithId(this.cline.taskId)
|
|
|
- await this.cline.overwriteClineMessages(this.cline.clineMessages.slice(0, messageIndex))
|
|
|
- if (apiConversationHistoryIndex !== -1) {
|
|
|
- await this.cline.overwriteApiConversationHistory(this.cline.apiConversationHistory.slice(0, apiConversationHistoryIndex))
|
|
|
+
|
|
|
+ if (answer === "Just this message") {
|
|
|
+ // Find the next user message first
|
|
|
+ const nextUserMessage = this.cline.clineMessages
|
|
|
+ .slice(messageIndex + 1)
|
|
|
+ .find(msg => msg.type === "say" && msg.say === "user_feedback")
|
|
|
+
|
|
|
+ // Handle UI messages
|
|
|
+ if (nextUserMessage) {
|
|
|
+ // Find absolute index of next user message
|
|
|
+ const nextUserMessageIndex = this.cline.clineMessages.findIndex(msg => msg === nextUserMessage)
|
|
|
+ // Keep messages before current message and after next user message
|
|
|
+ await this.cline.overwriteClineMessages([
|
|
|
+ ...this.cline.clineMessages.slice(0, messageIndex),
|
|
|
+ ...this.cline.clineMessages.slice(nextUserMessageIndex)
|
|
|
+ ])
|
|
|
+ } else {
|
|
|
+ // If no next user message, keep only messages before current message
|
|
|
+ await this.cline.overwriteClineMessages(
|
|
|
+ this.cline.clineMessages.slice(0, messageIndex)
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ // Handle API messages
|
|
|
+ if (apiConversationHistoryIndex !== -1) {
|
|
|
+ if (nextUserMessage && nextUserMessage.ts) {
|
|
|
+ // Keep messages before current API message and after next user message
|
|
|
+ await this.cline.overwriteApiConversationHistory([
|
|
|
+ ...this.cline.apiConversationHistory.slice(0, apiConversationHistoryIndex),
|
|
|
+ ...this.cline.apiConversationHistory.filter(msg => msg.ts && msg.ts >= nextUserMessage.ts)
|
|
|
+ ])
|
|
|
+ } else {
|
|
|
+ // If no next user message, keep only messages before current API message
|
|
|
+ await this.cline.overwriteApiConversationHistory(
|
|
|
+ this.cline.apiConversationHistory.slice(0, apiConversationHistoryIndex)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (answer === "This and all subsequent messages") {
|
|
|
+ // Delete this message and all that follow
|
|
|
+ await this.cline.overwriteClineMessages(this.cline.clineMessages.slice(0, messageIndex))
|
|
|
+ if (apiConversationHistoryIndex !== -1) {
|
|
|
+ await this.cline.overwriteApiConversationHistory(this.cline.apiConversationHistory.slice(0, apiConversationHistoryIndex))
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
await this.initClineWithHistoryItem(historyItem)
|
|
|
}
|
|
|
}
|
|
|
@@ -760,6 +870,113 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
}
|
|
|
break
|
|
|
}
|
|
|
+ case "upsertApiConfiguration":
|
|
|
+ if (message.text && message.apiConfiguration) {
|
|
|
+ try {
|
|
|
+ await this.configManager.SaveConfig(message.text, message.apiConfiguration);
|
|
|
+
|
|
|
+ let listApiConfig = await this.configManager.ListConfig();
|
|
|
+
|
|
|
+ await Promise.all([
|
|
|
+ this.updateApiConfiguration(message.apiConfiguration),
|
|
|
+ this.updateGlobalState("currentApiConfigName", message.text),
|
|
|
+ this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
|
|
+ ])
|
|
|
+
|
|
|
+ this.postStateToWebview()
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error create new api configuration:", error)
|
|
|
+ vscode.window.showErrorMessage("Failed to create api configuration")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case "renameApiConfiguration":
|
|
|
+ if (message.values && message.apiConfiguration) {
|
|
|
+ try {
|
|
|
+
|
|
|
+ const { oldName, newName } = message.values
|
|
|
+
|
|
|
+ await this.configManager.SaveConfig(newName, message.apiConfiguration);
|
|
|
+
|
|
|
+ await this.configManager.DeleteConfig(oldName)
|
|
|
+
|
|
|
+ let listApiConfig = await this.configManager.ListConfig();
|
|
|
+
|
|
|
+ await Promise.all([
|
|
|
+ this.updateGlobalState("currentApiConfigName", newName),
|
|
|
+ this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
|
|
+ ])
|
|
|
+
|
|
|
+ this.postStateToWebview()
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error create new api configuration:", error)
|
|
|
+ vscode.window.showErrorMessage("Failed to create api configuration")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case "loadApiConfiguration":
|
|
|
+ if (message.text) {
|
|
|
+ try {
|
|
|
+ const apiConfig = await this.configManager.LoadConfig(message.text);
|
|
|
+
|
|
|
+ await Promise.all([
|
|
|
+ this.updateGlobalState("currentApiConfigName", message.text),
|
|
|
+ this.updateApiConfiguration(apiConfig),
|
|
|
+ ])
|
|
|
+
|
|
|
+ await this.postStateToWebview()
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error load api configuration:", error)
|
|
|
+ vscode.window.showErrorMessage("Failed to load api configuration")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case "deleteApiConfiguration":
|
|
|
+ if (message.text) {
|
|
|
+
|
|
|
+ const answer = await vscode.window.showInformationMessage(
|
|
|
+ "Are you sure you want to delete this configuration profile?",
|
|
|
+ { modal: true },
|
|
|
+ "Yes",
|
|
|
+ )
|
|
|
+
|
|
|
+ if (answer !== "Yes") {
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ await this.configManager.DeleteConfig(message.text);
|
|
|
+ let listApiConfig = await this.configManager.ListConfig()
|
|
|
+ let currentApiConfigName = await this.getGlobalState("currentApiConfigName")
|
|
|
+
|
|
|
+ if (message.text === currentApiConfigName) {
|
|
|
+ await this.updateGlobalState("currentApiConfigName", listApiConfig?.[0]?.name)
|
|
|
+ if (listApiConfig?.[0]?.name) {
|
|
|
+ const apiConfig = await this.configManager.LoadConfig(listApiConfig?.[0]?.name);
|
|
|
+
|
|
|
+ await Promise.all([
|
|
|
+ this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
|
|
+ this.updateApiConfiguration(apiConfig),
|
|
|
+ ])
|
|
|
+ await this.postStateToWebview()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error delete api configuration:", error)
|
|
|
+ vscode.window.showErrorMessage("Failed to delete api configuration")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case "getListApiConfiguration":
|
|
|
+ try {
|
|
|
+ let listApiConfig = await this.configManager.ListConfig();
|
|
|
+ await this.updateGlobalState("listApiConfigMeta", listApiConfig)
|
|
|
+ this.postMessageToWebview({ type: "listApiConfig", listApiConfig })
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Error get list api configuration:", error)
|
|
|
+ vscode.window.showErrorMessage("Failed to get list api configuration")
|
|
|
+ }
|
|
|
+ break
|
|
|
}
|
|
|
},
|
|
|
null,
|
|
|
@@ -767,6 +984,74 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ private async updateApiConfiguration(apiConfiguration: ApiConfiguration) {
|
|
|
+ const {
|
|
|
+ apiProvider,
|
|
|
+ apiModelId,
|
|
|
+ apiKey,
|
|
|
+ glamaModelId,
|
|
|
+ glamaModelInfo,
|
|
|
+ glamaApiKey,
|
|
|
+ openRouterApiKey,
|
|
|
+ awsAccessKey,
|
|
|
+ awsSecretKey,
|
|
|
+ awsSessionToken,
|
|
|
+ awsRegion,
|
|
|
+ awsUseCrossRegionInference,
|
|
|
+ vertexProjectId,
|
|
|
+ vertexRegion,
|
|
|
+ openAiBaseUrl,
|
|
|
+ openAiApiKey,
|
|
|
+ openAiModelId,
|
|
|
+ ollamaModelId,
|
|
|
+ ollamaBaseUrl,
|
|
|
+ lmStudioModelId,
|
|
|
+ lmStudioBaseUrl,
|
|
|
+ anthropicBaseUrl,
|
|
|
+ geminiApiKey,
|
|
|
+ openAiNativeApiKey,
|
|
|
+ deepSeekApiKey,
|
|
|
+ azureApiVersion,
|
|
|
+ openAiStreamingEnabled,
|
|
|
+ openRouterModelId,
|
|
|
+ openRouterModelInfo,
|
|
|
+ openRouterUseMiddleOutTransform,
|
|
|
+ } = apiConfiguration
|
|
|
+ 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)
|
|
|
+ await this.storeSecret("awsSessionToken", awsSessionToken)
|
|
|
+ await this.updateGlobalState("awsRegion", awsRegion)
|
|
|
+ await this.updateGlobalState("awsUseCrossRegionInference", awsUseCrossRegionInference)
|
|
|
+ await this.updateGlobalState("vertexProjectId", vertexProjectId)
|
|
|
+ await this.updateGlobalState("vertexRegion", vertexRegion)
|
|
|
+ await this.updateGlobalState("openAiBaseUrl", openAiBaseUrl)
|
|
|
+ await this.storeSecret("openAiApiKey", openAiApiKey)
|
|
|
+ await this.updateGlobalState("openAiModelId", openAiModelId)
|
|
|
+ await this.updateGlobalState("ollamaModelId", ollamaModelId)
|
|
|
+ await this.updateGlobalState("ollamaBaseUrl", ollamaBaseUrl)
|
|
|
+ await this.updateGlobalState("lmStudioModelId", lmStudioModelId)
|
|
|
+ await this.updateGlobalState("lmStudioBaseUrl", lmStudioBaseUrl)
|
|
|
+ await this.updateGlobalState("anthropicBaseUrl", anthropicBaseUrl)
|
|
|
+ await this.storeSecret("geminiApiKey", geminiApiKey)
|
|
|
+ await this.storeSecret("openAiNativeApiKey", openAiNativeApiKey)
|
|
|
+ await this.storeSecret("deepSeekApiKey", deepSeekApiKey)
|
|
|
+ await this.updateGlobalState("azureApiVersion", azureApiVersion)
|
|
|
+ await this.updateGlobalState("openAiStreamingEnabled", openAiStreamingEnabled)
|
|
|
+ await this.updateGlobalState("openRouterModelId", openRouterModelId)
|
|
|
+ await this.updateGlobalState("openRouterModelInfo", openRouterModelInfo)
|
|
|
+ await this.updateGlobalState("openRouterUseMiddleOutTransform", openRouterUseMiddleOutTransform)
|
|
|
+ if (this.cline) {
|
|
|
+ this.cline.api = buildApiHandler(apiConfiguration)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
async updateCustomInstructions(instructions?: string) {
|
|
|
// User may be clearing the field
|
|
|
await this.updateGlobalState("customInstructions", instructions || undefined)
|
|
|
@@ -1220,9 +1505,12 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
terminalOutputLineLimit,
|
|
|
fuzzyMatchThreshold,
|
|
|
mcpEnabled,
|
|
|
+ alwaysApproveResubmit,
|
|
|
+ requestDelaySeconds,
|
|
|
+ currentApiConfigName,
|
|
|
+ listApiConfigMeta,
|
|
|
} = await this.getState()
|
|
|
|
|
|
-
|
|
|
const allowedCommands = vscode.workspace
|
|
|
.getConfiguration('roo-cline')
|
|
|
.get<string[]>('allowedCommands') || []
|
|
|
@@ -1253,6 +1541,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
|
|
|
fuzzyMatchThreshold: fuzzyMatchThreshold ?? 1.0,
|
|
|
mcpEnabled: mcpEnabled ?? true,
|
|
|
+ alwaysApproveResubmit: alwaysApproveResubmit ?? false,
|
|
|
+ requestDelaySeconds: requestDelaySeconds ?? 5,
|
|
|
+ currentApiConfigName: currentApiConfigName ?? "default",
|
|
|
+ listApiConfigMeta: listApiConfigMeta ?? [],
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1358,7 +1650,11 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
screenshotQuality,
|
|
|
terminalOutputLineLimit,
|
|
|
mcpEnabled,
|
|
|
- vsCodeLmModelSelector,
|
|
|
+ alwaysApproveResubmit,
|
|
|
+ requestDelaySeconds,
|
|
|
+ currentApiConfigName,
|
|
|
+ listApiConfigMeta,
|
|
|
+ vsCodeLmModelSelector
|
|
|
] = await Promise.all([
|
|
|
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
|
|
|
this.getGlobalState("apiModelId") as Promise<string | undefined>,
|
|
|
@@ -1409,7 +1705,12 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
this.getGlobalState("screenshotQuality") as Promise<number | undefined>,
|
|
|
this.getGlobalState("terminalOutputLineLimit") as Promise<number | undefined>,
|
|
|
this.getGlobalState("mcpEnabled") as Promise<boolean | undefined>,
|
|
|
+ this.getGlobalState("alwaysApproveResubmit") as Promise<boolean | undefined>,
|
|
|
+ this.getGlobalState("requestDelaySeconds") as Promise<number | undefined>,
|
|
|
+ this.getGlobalState("currentApiConfigName") as Promise<string | undefined>,
|
|
|
+ this.getGlobalState("listApiConfigMeta") as Promise<ApiConfigMeta[] | undefined>,
|
|
|
this.getGlobalState("vsCodeLmModelSelector") as Promise<vscode.LanguageModelChatSelector | undefined>,
|
|
|
+
|
|
|
])
|
|
|
|
|
|
let apiProvider: ApiProvider
|
|
|
@@ -1505,6 +1806,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|
|
return langMap[vscodeLang.split('-')[0]] ?? 'English';
|
|
|
})(),
|
|
|
mcpEnabled: mcpEnabled ?? true,
|
|
|
+ alwaysApproveResubmit: alwaysApproveResubmit ?? false,
|
|
|
+ requestDelaySeconds: requestDelaySeconds ?? 5,
|
|
|
+ currentApiConfigName: currentApiConfigName ?? "default",
|
|
|
+ listApiConfigMeta: listApiConfigMeta ?? [],
|
|
|
}
|
|
|
}
|
|
|
|