ソースを参照

Automatically generate `roo-code.d.ts` (including type generation via zod-to-ts) (#2024)

Chris Estreich 9 ヶ月 前
コミット
0fd399de78

+ 5 - 0
.changeset/sweet-bugs-glow.md

@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Automatically generate .d.ts from zod schemas

+ 9 - 1
.husky/pre-commit

@@ -12,4 +12,12 @@ else
   npx_cmd="npx"
 fi
 
-"$npx_cmd" lint-staged
+npm run generate-types
+
+if [ -n "$(git diff --name-only src/exports/roo-code.d.ts)" ]; then
+  echo "Error: There are unstaged changes to roo-code.d.ts after running 'npm run generate-types'."
+  echo "Please review and stage the changes before committing."
+  exit 1
+fi
+
+"$npx_cmd" lint-staged

+ 1 - 1
e2e/src/suite/utils.ts

@@ -9,7 +9,7 @@ type WaitForOptions = {
 
 export const waitFor = (
 	condition: (() => Promise<boolean>) | (() => boolean),
-	{ timeout = 30_000, interval = 250 }: WaitForOptions = {},
+	{ timeout = 60_000, interval = 250 }: WaitForOptions = {},
 ) => {
 	let timeoutId: NodeJS.Timeout | undefined = undefined
 

+ 2 - 1
package.json

@@ -351,7 +351,8 @@
 		"clean:webview": "cd webview-ui && npm run clean",
 		"clean:e2e": "cd e2e && npm run clean",
 		"clean:benchmark": "cd benchmark && npm run clean",
-		"update-contributors": "node scripts/update-contributors.js"
+		"update-contributors": "node scripts/update-contributors.js",
+		"generate-types": "tsx scripts/generate-types.mts"
 	},
 	"dependencies": {
 		"@anthropic-ai/bedrock-sdk": "^0.10.2",

+ 26 - 0
scripts/generate-types.mts

@@ -0,0 +1,26 @@
+import fs from "fs/promises"
+
+import { zodToTs, createTypeAlias, printNode } from "zod-to-ts"
+import { $ } from "execa"
+
+import { typeDefinitions } from "../src/schemas"
+
+async function main() {
+	const types: string[] = [
+		"// This file is automatically generated by running `npm run generate-types`\n// Do not edit it directly.",
+	]
+
+	for (const { schema, identifier } of typeDefinitions) {
+		types.push(printNode(createTypeAlias(zodToTs(schema, identifier).node, identifier)))
+		types.push(`export type { ${identifier} }`)
+	}
+
+	await fs.writeFile("src/exports/types.ts", types.join("\n\n"))
+
+	await $`npx tsup src/exports/interface.ts --dts-only -d out`
+	await fs.copyFile('out/interface.d.ts', 'src/exports/roo-code.d.ts')
+
+	await $`npx prettier --write src/exports/types.ts src/exports/roo-code.d.ts`
+}
+
+main()

+ 2 - 2
src/core/Cline.ts

@@ -11,9 +11,8 @@ import pWaitFor from "p-wait-for"
 import getFolderSize from "get-folder-size"
 import { serializeError } from "serialize-error"
 import * as vscode from "vscode"
-import { isPathOutsideWorkspace } from "../utils/pathUtils"
 
-import { TokenUsage } from "../exports/roo-code"
+import { TokenUsage } from "../schemas"
 import { ApiHandler, buildApiHandler } from "../api"
 import { ApiStream } from "../api/transform/stream"
 import { DIFF_VIEW_URI_SCHEME, DiffViewProvider } from "../integrations/editor/DiffViewProvider"
@@ -65,6 +64,7 @@ import { defaultModeSlug, getModeBySlug, getFullModeDetails } from "../shared/mo
 import { EXPERIMENT_IDS, experiments as Experiments, ExperimentId } from "../shared/experiments"
 import { calculateApiCostAnthropic } from "../utils/cost"
 import { fileExistsAtPath } from "../utils/fs"
+import { isPathOutsideWorkspace } from "../utils/pathUtils"
 import { arePathsEqual, getReadablePath } from "../utils/path"
 import { parseMentions } from "./mentions"
 import { RooIgnoreController } from "./ignore/RooIgnoreController"

+ 6 - 5
src/core/__tests__/mode-validator.test.ts

@@ -1,6 +1,7 @@
-import { Mode, isToolAllowedForMode, getModeConfig, modes } from "../../shared/modes"
-import { validateToolUse } from "../mode-validator"
+import { isToolAllowedForMode, getModeConfig, modes, ModeConfig } from "../../shared/modes"
 import { TOOL_GROUPS } from "../../shared/tool-groups"
+import { validateToolUse } from "../mode-validator"
+
 const [codeMode, architectMode, askMode] = modes.map((mode) => mode.slug)
 
 describe("mode-validator", () => {
@@ -49,7 +50,7 @@ describe("mode-validator", () => {
 
 		describe("custom modes", () => {
 			it("allows tools from custom mode configuration", () => {
-				const customModes = [
+				const customModes: ModeConfig[] = [
 					{
 						slug: "custom-mode",
 						name: "Custom Mode",
@@ -65,7 +66,7 @@ describe("mode-validator", () => {
 			})
 
 			it("allows custom mode to override built-in mode", () => {
-				const customModes = [
+				const customModes: ModeConfig[] = [
 					{
 						slug: codeMode,
 						name: "Custom Code Mode",
@@ -80,7 +81,7 @@ describe("mode-validator", () => {
 			})
 
 			it("respects tool requirements in custom modes", () => {
-				const customModes = [
+				const customModes: ModeConfig[] = [
 					{
 						slug: "custom-mode",
 						name: "Custom Mode",

+ 18 - 16
src/core/config/ContextProxy.ts

@@ -1,25 +1,27 @@
 import * as vscode from "vscode"
 
-import { logger } from "../../utils/logging"
-import type {
-	ProviderSettings,
-	RooCodeSettings,
-	RooCodeSettingsKey,
-	GlobalStateKey,
-	GlobalState,
-	SecretStateKey,
-	SecretState,
-	GlobalSettings,
-} from "../../exports/roo-code"
 import {
 	PROVIDER_SETTINGS_KEYS,
-	GLOBAL_STATE_KEYS,
+	ProviderSettings,
+	providerSettingsSchema,
+	GlobalSettings,
+	globalSettingsSchema,
+	RooCodeSettings,
 	SECRET_STATE_KEYS,
+	SecretState,
 	isSecretStateKey,
-	isPassThroughStateKey,
-	globalSettingsSchema,
-	providerSettingsSchema,
-} from "../../shared/globalState"
+	GLOBAL_STATE_KEYS,
+	GlobalState,
+} from "../../schemas"
+import { logger } from "../../utils/logging"
+
+type GlobalStateKey = keyof GlobalState
+type SecretStateKey = keyof SecretState
+type RooCodeSettingsKey = keyof RooCodeSettings
+
+const PASS_THROUGH_STATE_KEYS = ["taskHistory"]
+
+export const isPassThroughStateKey = (key: string) => PASS_THROUGH_STATE_KEYS.includes(key)
 
 const globalSettingsExportSchema = globalSettingsSchema.omit({
 	taskHistory: true,

+ 1 - 2
src/core/config/ProviderSettingsManager.ts

@@ -1,9 +1,8 @@
 import { ExtensionContext } from "vscode"
 import { z } from "zod"
 
-import { providerSettingsSchema } from "../../shared/globalState"
+import { providerSettingsSchema, ApiConfigMeta } from "../../schemas"
 import { Mode } from "../../shared/modes"
-import { ApiConfigMeta } from "../../shared/ExtensionMessage"
 
 const providerSettingsWithIdSchema = providerSettingsSchema.extend({ id: z.string().optional() })
 

+ 1 - 4
src/core/config/__tests__/ContextProxy.test.ts

@@ -1,12 +1,9 @@
 // npx jest src/core/config/__tests__/ContextProxy.test.ts
 
-import fs from "fs/promises"
-
 import * as vscode from "vscode"
 import { ContextProxy } from "../ContextProxy"
 
-import { logger } from "../../../utils/logging"
-import { GLOBAL_STATE_KEYS, SECRET_STATE_KEYS } from "../../../shared/globalState"
+import { GLOBAL_STATE_KEYS, SECRET_STATE_KEYS } from "../../../schemas"
 
 jest.mock("vscode", () => ({
 	Uri: {

+ 1 - 1
src/core/config/__tests__/ProviderSettingsManager.test.ts

@@ -2,7 +2,7 @@
 
 import { ExtensionContext } from "vscode"
 
-import { ProviderSettings } from "../../../exports/roo-code"
+import { ProviderSettings } from "../../../schemas"
 import { ProviderSettingsManager, ProviderProfiles } from "../ProviderSettingsManager"
 
 // Mock VSCode ExtensionContext

+ 1 - 1
src/core/config/__tests__/importExport.test.ts

@@ -6,10 +6,10 @@ import os from "os"
 
 import * as vscode from "vscode"
 
+import { ProviderName } from "../../../schemas"
 import { importSettings, exportSettings } from "../importExport"
 import { ProviderSettingsManager } from "../ProviderSettingsManager"
 import { ContextProxy } from "../ContextProxy"
-import { ProviderName } from "../../../exports/roo-code"
 
 // Mock VSCode modules
 jest.mock("vscode", () => ({

+ 1 - 1
src/core/config/importExport.ts

@@ -5,7 +5,7 @@ import fs from "fs/promises"
 import * as vscode from "vscode"
 import { z } from "zod"
 
-import { globalSettingsSchema } from "../../shared/globalState"
+import { globalSettingsSchema } from "../../schemas"
 import { ProviderSettingsManager, providerProfilesSchema } from "./ProviderSettingsManager"
 import { ContextProxy } from "./ContextProxy"
 

+ 1 - 1
src/core/mode-validator.ts

@@ -1,4 +1,4 @@
-import { Mode, isToolAllowedForMode, getModeConfig, ModeConfig, FileRestrictionError } from "../shared/modes"
+import { Mode, isToolAllowedForMode, ModeConfig } from "../shared/modes"
 import { ToolName } from "../shared/tool-groups"
 
 export { isToolAllowedForMode }

+ 6 - 9
src/core/prompts/__tests__/system.test.ts

@@ -1,16 +1,12 @@
+import * as vscode from "vscode"
+
 import { SYSTEM_PROMPT } from "../system"
 import { McpHub } from "../../../services/mcp/McpHub"
-import { McpServer } from "../../../shared/mcp"
 import { ClineProvider } from "../../../core/webview/ClineProvider"
 import { SearchReplaceDiffStrategy } from "../../../core/diff/strategies/search-replace"
-import * as vscode from "vscode"
-import fs from "fs/promises"
-import os from "os"
-import { defaultModeSlug, modes, Mode, isToolAllowedForMode } from "../../../shared/modes"
-// Import path utils to get access to toPosix string extension
-import "../../../utils/path"
+import { defaultModeSlug, modes, Mode, ModeConfig } from "../../../shared/modes"
+import "../../../utils/path" // Import path utils to get access to toPosix string extension.
 import { addCustomInstructions } from "../sections/custom-instructions"
-import * as modesSection from "../sections/modes"
 import { EXPERIMENT_IDS } from "../../../shared/experiments"
 
 // Mock the sections
@@ -386,7 +382,8 @@ describe("SYSTEM_PROMPT", () => {
 
 	it("should include custom mode role definition at top and instructions at bottom", async () => {
 		const modeCustomInstructions = "Custom mode instructions"
-		const customModes = [
+
+		const customModes: ModeConfig[] = [
 			{
 				slug: "custom-mode",
 				name: "Custom Mode",

+ 1 - 2
src/core/prompts/sections/custom-instructions.ts

@@ -1,8 +1,7 @@
 import fs from "fs/promises"
 import path from "path"
 
-import { LANGUAGES } from "../../../shared/language"
-import { isLanguage } from "../../../shared/globalState"
+import { LANGUAGES, isLanguage } from "../../../shared/language"
 
 async function safeReadFile(filePath: string): Promise<string> {
 	try {

+ 8 - 8
src/core/webview/ClineProvider.ts

@@ -12,12 +12,12 @@ import * as vscode from "vscode"
 import {
 	CheckpointStorage,
 	GlobalState,
+	SecretState,
 	Language,
 	ProviderSettings,
 	RooCodeSettings,
-	GlobalStateKey,
-	SecretStateKey,
-} from "../../exports/roo-code"
+	ApiConfigMeta,
+} from "../../schemas"
 import { changeLanguage, t } from "../../i18n"
 import { setPanel } from "../../activate/registerCommands"
 import {
@@ -35,7 +35,7 @@ import { findLast } from "../../shared/array"
 import { supportPrompt } from "../../shared/support-prompt"
 import { GlobalFileNames } from "../../shared/globalFileNames"
 import { HistoryItem } from "../../shared/HistoryItem"
-import { ApiConfigMeta, ExtensionMessage } from "../../shared/ExtensionMessage"
+import { ExtensionMessage } from "../../shared/ExtensionMessage"
 import { checkoutDiffPayloadSchema, checkoutRestorePayloadSchema, WebviewMessage } from "../../shared/WebviewMessage"
 import { Mode, PromptComponent, defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes"
 import { checkExistKey } from "../../shared/checkExistApiConfig"
@@ -2804,21 +2804,21 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 
 	// global
 
-	public async updateGlobalState<K extends GlobalStateKey>(key: K, value: GlobalState[K]) {
+	public async updateGlobalState<K extends keyof GlobalState>(key: K, value: GlobalState[K]) {
 		await this.contextProxy.setValue(key, value)
 	}
 
-	public getGlobalState<K extends GlobalStateKey>(key: K) {
+	public getGlobalState<K extends keyof GlobalState>(key: K) {
 		return this.contextProxy.getValue(key)
 	}
 
 	// secrets
 
-	public async storeSecret(key: SecretStateKey, value?: string) {
+	public async storeSecret(key: keyof SecretState, value?: string) {
 		await this.contextProxy.setValue(key, value)
 	}
 
-	private getSecret(key: SecretStateKey) {
+	private getSecret(key: keyof SecretState) {
 		return this.contextProxy.getValue(key)
 	}
 

+ 94 - 0
src/exports/interface.ts

@@ -0,0 +1,94 @@
+import { EventEmitter } from "events"
+
+import type { ProviderSettings, GlobalSettings, ClineMessage, TokenUsage } from "./types"
+
+type RooCodeSettings = GlobalSettings & ProviderSettings
+
+export type { RooCodeSettings, ProviderSettings, GlobalSettings, ClineMessage, TokenUsage }
+
+export interface RooCodeEvents {
+	message: [{ taskId: string; action: "created" | "updated"; message: ClineMessage }]
+	taskCreated: [taskId: string]
+	taskStarted: [taskId: string]
+	taskPaused: [taskId: string]
+	taskUnpaused: [taskId: string]
+	taskAskResponded: [taskId: string]
+	taskAborted: [taskId: string]
+	taskSpawned: [taskId: string, childTaskId: string]
+	taskCompleted: [taskId: string, usage: TokenUsage]
+	taskTokenUsageUpdated: [taskId: string, usage: TokenUsage]
+}
+
+export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
+	/**
+	 * Starts a new task with an optional initial message and images.
+	 * @param task Optional initial task message.
+	 * @param images Optional array of image data URIs (e.g., "data:image/webp;base64,...").
+	 * @returns The ID of the new task.
+	 */
+	startNewTask(task?: string, images?: string[]): Promise<string>
+
+	/**
+	 * Returns the current task stack.
+	 * @returns An array of task IDs.
+	 */
+	getCurrentTaskStack(): string[]
+
+	/**
+	 * Clears the current task.
+	 */
+	clearCurrentTask(lastMessage?: string): Promise<void>
+
+	/**
+	 * Cancels the current task.
+	 */
+	cancelCurrentTask(): Promise<void>
+
+	/**
+	 * Sends a message to the current task.
+	 * @param message Optional message to send.
+	 * @param images Optional array of image data URIs (e.g., "data:image/webp;base64,...").
+	 */
+	sendMessage(message?: string, images?: string[]): Promise<void>
+
+	/**
+	 * Simulates pressing the primary button in the chat interface.
+	 */
+	pressPrimaryButton(): Promise<void>
+
+	/**
+	 * Simulates pressing the secondary button in the chat interface.
+	 */
+	pressSecondaryButton(): Promise<void>
+
+	/**
+	 * Sets the configuration for the current task.
+	 * @param values An object containing key-value pairs to set.
+	 */
+	setConfiguration(values: RooCodeSettings): Promise<void>
+
+	/**
+	 * Returns true if the API is ready to use.
+	 */
+	isReady(): boolean
+
+	/**
+	 * Returns the messages for a given task.
+	 * @param taskId The ID of the task.
+	 * @returns An array of ClineMessage objects.
+	 */
+	getMessages(taskId: string): ClineMessage[]
+
+	/**
+	 * Returns the token usage for a given task.
+	 * @param taskId The ID of the task.
+	 * @returns A TokenUsage object.
+	 */
+	getTokenUsage(taskId: string): TokenUsage
+
+	/**
+	 * Logs a message to the output channel.
+	 * @param message The message to log.
+	 */
+	log(message: string): void
+}

+ 404 - 490
src/exports/roo-code.d.ts

@@ -1,18 +1,412 @@
-import * as vscode from "vscode"
-
 import { EventEmitter } from "events"
 
-export interface TokenUsage {
+type ProviderSettings = {
+	apiProvider?:
+		| (
+				| "anthropic"
+				| "glama"
+				| "openrouter"
+				| "bedrock"
+				| "vertex"
+				| "openai"
+				| "ollama"
+				| "vscode-lm"
+				| "lmstudio"
+				| "gemini"
+				| "openai-native"
+				| "mistral"
+				| "deepseek"
+				| "unbound"
+				| "requesty"
+				| "human-relay"
+				| "fake-ai"
+		  )
+		| undefined
+	apiModelId?: string | undefined
+	apiKey?: string | undefined
+	anthropicBaseUrl?: string | undefined
+	glamaModelId?: string | undefined
+	glamaModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	glamaApiKey?: string | undefined
+	openRouterApiKey?: string | undefined
+	openRouterModelId?: string | undefined
+	openRouterModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	openRouterBaseUrl?: string | undefined
+	openRouterSpecificProvider?: string | undefined
+	openRouterUseMiddleOutTransform?: boolean | undefined
+	awsAccessKey?: string | undefined
+	awsSecretKey?: string | undefined
+	awsSessionToken?: string | undefined
+	awsRegion?: string | undefined
+	awsUseCrossRegionInference?: boolean | undefined
+	awsUsePromptCache?: boolean | undefined
+	awspromptCacheId?: string | undefined
+	awsProfile?: string | undefined
+	awsUseProfile?: boolean | undefined
+	awsCustomArn?: string | undefined
+	vertexKeyFile?: string | undefined
+	vertexJsonCredentials?: string | undefined
+	vertexProjectId?: string | undefined
+	vertexRegion?: string | undefined
+	openAiBaseUrl?: string | undefined
+	openAiApiKey?: string | undefined
+	openAiR1FormatEnabled?: boolean | undefined
+	openAiModelId?: string | undefined
+	openAiCustomModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	openAiUseAzure?: boolean | undefined
+	azureApiVersion?: string | undefined
+	openAiStreamingEnabled?: boolean | undefined
+	ollamaModelId?: string | undefined
+	ollamaBaseUrl?: string | undefined
+	vsCodeLmModelSelector?:
+		| {
+				vendor?: string | undefined
+				family?: string | undefined
+				version?: string | undefined
+				id?: string | undefined
+		  }
+		| undefined
+	lmStudioModelId?: string | undefined
+	lmStudioBaseUrl?: string | undefined
+	lmStudioDraftModelId?: string | undefined
+	lmStudioSpeculativeDecodingEnabled?: boolean | undefined
+	geminiApiKey?: string | undefined
+	googleGeminiBaseUrl?: string | undefined
+	openAiNativeApiKey?: string | undefined
+	mistralApiKey?: string | undefined
+	mistralCodestralUrl?: string | undefined
+	deepSeekBaseUrl?: string | undefined
+	deepSeekApiKey?: string | undefined
+	unboundApiKey?: string | undefined
+	unboundModelId?: string | undefined
+	unboundModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	requestyApiKey?: string | undefined
+	requestyModelId?: string | undefined
+	requestyModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	modelTemperature?: (number | null) | undefined
+	modelMaxTokens?: number | undefined
+	modelMaxThinkingTokens?: number | undefined
+	includeMaxTokens?: boolean | undefined
+	fakeAi?: unknown | undefined
+}
+
+type GlobalSettings = {
+	currentApiConfigName?: string | undefined
+	listApiConfigMeta?:
+		| {
+				id: string
+				name: string
+				apiProvider?:
+					| (
+							| "anthropic"
+							| "glama"
+							| "openrouter"
+							| "bedrock"
+							| "vertex"
+							| "openai"
+							| "ollama"
+							| "vscode-lm"
+							| "lmstudio"
+							| "gemini"
+							| "openai-native"
+							| "mistral"
+							| "deepseek"
+							| "unbound"
+							| "requesty"
+							| "human-relay"
+							| "fake-ai"
+					  )
+					| undefined
+		  }[]
+		| undefined
+	pinnedApiConfigs?:
+		| {
+				[x: string]: boolean
+		  }
+		| undefined
+	lastShownAnnouncementId?: string | undefined
+	customInstructions?: string | undefined
+	taskHistory?:
+		| {
+				id: string
+				number: number
+				ts: number
+				task: string
+				tokensIn: number
+				tokensOut: number
+				cacheWrites?: number | undefined
+				cacheReads?: number | undefined
+				totalCost: number
+				size?: number | undefined
+		  }[]
+		| undefined
+	autoApprovalEnabled?: boolean | undefined
+	alwaysAllowReadOnly?: boolean | undefined
+	alwaysAllowReadOnlyOutsideWorkspace?: boolean | undefined
+	alwaysAllowWrite?: boolean | undefined
+	alwaysAllowWriteOutsideWorkspace?: boolean | undefined
+	writeDelayMs?: number | undefined
+	alwaysAllowBrowser?: boolean | undefined
+	alwaysApproveResubmit?: boolean | undefined
+	requestDelaySeconds?: number | undefined
+	alwaysAllowMcp?: boolean | undefined
+	alwaysAllowModeSwitch?: boolean | undefined
+	alwaysAllowSubtasks?: boolean | undefined
+	alwaysAllowExecute?: boolean | undefined
+	allowedCommands?: string[] | undefined
+	browserToolEnabled?: boolean | undefined
+	browserViewportSize?: string | undefined
+	screenshotQuality?: number | undefined
+	remoteBrowserEnabled?: boolean | undefined
+	remoteBrowserHost?: string | undefined
+	enableCheckpoints?: boolean | undefined
+	checkpointStorage?: ("task" | "workspace") | undefined
+	ttsEnabled?: boolean | undefined
+	ttsSpeed?: number | undefined
+	soundEnabled?: boolean | undefined
+	soundVolume?: number | undefined
+	maxOpenTabsContext?: number | undefined
+	maxWorkspaceFiles?: number | undefined
+	showRooIgnoredFiles?: boolean | undefined
+	maxReadFileLine?: number | undefined
+	terminalOutputLineLimit?: number | undefined
+	terminalShellIntegrationTimeout?: number | undefined
+	rateLimitSeconds?: number | undefined
+	diffEnabled?: boolean | undefined
+	fuzzyMatchThreshold?: number | undefined
+	experiments?:
+		| {
+				experimentalDiffStrategy: boolean
+				search_and_replace: boolean
+				insert_content: boolean
+				powerSteering: boolean
+				multi_search_and_replace: boolean
+		  }
+		| undefined
+	language?:
+		| (
+				| "ca"
+				| "de"
+				| "en"
+				| "es"
+				| "fr"
+				| "hi"
+				| "it"
+				| "ja"
+				| "ko"
+				| "pl"
+				| "pt-BR"
+				| "tr"
+				| "vi"
+				| "zh-CN"
+				| "zh-TW"
+		  )
+		| undefined
+	telemetrySetting?: ("unset" | "enabled" | "disabled") | undefined
+	mcpEnabled?: boolean | undefined
+	enableMcpServerCreation?: boolean | undefined
+	mode?: string | undefined
+	modeApiConfigs?:
+		| {
+				[x: string]: string
+		  }
+		| undefined
+	customModes?:
+		| {
+				slug: string
+				name: string
+				roleDefinition: string
+				customInstructions?: string | undefined
+				groups: (
+					| ("read" | "edit" | "browser" | "command" | "mcp" | "modes")
+					| [
+							"read" | "edit" | "browser" | "command" | "mcp" | "modes",
+							{
+								fileRegex?: string | undefined
+								description?: string | undefined
+							},
+					  ]
+				)[]
+				source?: ("global" | "project") | undefined
+		  }[]
+		| undefined
+	customModePrompts?:
+		| {
+				[x: string]:
+					| {
+							roleDefinition?: string | undefined
+							customInstructions?: string | undefined
+					  }
+					| undefined
+		  }
+		| undefined
+	customSupportPrompts?:
+		| {
+				[x: string]: string | undefined
+		  }
+		| undefined
+	enhancementApiConfigId?: string | undefined
+}
+
+type ClineMessage = {
+	ts: number
+	type: "ask" | "say"
+	ask?:
+		| (
+				| "followup"
+				| "command"
+				| "command_output"
+				| "completion_result"
+				| "tool"
+				| "api_req_failed"
+				| "resume_task"
+				| "resume_completed_task"
+				| "mistake_limit_reached"
+				| "browser_action_launch"
+				| "use_mcp_server"
+				| "finishTask"
+		  )
+		| undefined
+	say?:
+		| (
+				| "task"
+				| "error"
+				| "api_req_started"
+				| "api_req_finished"
+				| "api_req_retried"
+				| "api_req_retry_delayed"
+				| "api_req_deleted"
+				| "text"
+				| "reasoning"
+				| "completion_result"
+				| "user_feedback"
+				| "user_feedback_diff"
+				| "command_output"
+				| "tool"
+				| "shell_integration_warning"
+				| "browser_action"
+				| "browser_action_result"
+				| "command"
+				| "mcp_server_request_started"
+				| "mcp_server_response"
+				| "new_task_started"
+				| "new_task"
+				| "checkpoint_saved"
+				| "rooignore_error"
+		  )
+		| undefined
+	text?: string | undefined
+	images?: string[] | undefined
+	partial?: boolean | undefined
+	reasoning?: string | undefined
+	conversationHistoryIndex?: number | undefined
+	checkpoint?:
+		| {
+				[x: string]: unknown
+		  }
+		| undefined
+	progressStatus?:
+		| {
+				icon?: string | undefined
+				text?: string | undefined
+		  }
+		| undefined
+}
+
+type TokenUsage = {
 	totalTokensIn: number
 	totalTokensOut: number
-	totalCacheWrites?: number
-	totalCacheReads?: number
+	totalCacheWrites?: number | undefined
+	totalCacheReads?: number | undefined
 	totalCost: number
 	contextTokens: number
 }
 
-export interface RooCodeEvents {
-	message: [{ taskId: string; action: "created" | "updated"; message: ClineMessage }]
+type RooCodeSettings = GlobalSettings & ProviderSettings
+
+interface RooCodeEvents {
+	message: [
+		{
+			taskId: string
+			action: "created" | "updated"
+			message: ClineMessage
+		},
+	]
 	taskCreated: [taskId: string]
 	taskStarted: [taskId: string]
 	taskPaused: [taskId: string]
@@ -23,8 +417,7 @@ export interface RooCodeEvents {
 	taskCompleted: [taskId: string, usage: TokenUsage]
 	taskTokenUsageUpdated: [taskId: string, usage: TokenUsage]
 }
-
-export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
+interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	/**
 	 * Starts a new task with an optional initial message and images.
 	 * @param task Optional initial task message.
@@ -32,65 +425,54 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	 * @returns The ID of the new task.
 	 */
 	startNewTask(task?: string, images?: string[]): Promise<string>
-
 	/**
 	 * Returns the current task stack.
 	 * @returns An array of task IDs.
 	 */
 	getCurrentTaskStack(): string[]
-
 	/**
 	 * Clears the current task.
 	 */
 	clearCurrentTask(lastMessage?: string): Promise<void>
-
 	/**
 	 * Cancels the current task.
 	 */
 	cancelCurrentTask(): Promise<void>
-
 	/**
 	 * Sends a message to the current task.
 	 * @param message Optional message to send.
 	 * @param images Optional array of image data URIs (e.g., "data:image/webp;base64,...").
 	 */
 	sendMessage(message?: string, images?: string[]): Promise<void>
-
 	/**
 	 * Simulates pressing the primary button in the chat interface.
 	 */
 	pressPrimaryButton(): Promise<void>
-
 	/**
 	 * Simulates pressing the secondary button in the chat interface.
 	 */
 	pressSecondaryButton(): Promise<void>
-
 	/**
 	 * Sets the configuration for the current task.
 	 * @param values An object containing key-value pairs to set.
 	 */
-	setConfiguration(values: Partial<ConfigurationValues>): Promise<void>
-
+	setConfiguration(values: RooCodeSettings): Promise<void>
 	/**
 	 * Returns true if the API is ready to use.
 	 */
 	isReady(): boolean
-
 	/**
 	 * Returns the messages for a given task.
 	 * @param taskId The ID of the task.
 	 * @returns An array of ClineMessage objects.
 	 */
 	getMessages(taskId: string): ClineMessage[]
-
 	/**
 	 * Returns the token usage for a given task.
 	 * @param taskId The ID of the task.
 	 * @returns A TokenUsage object.
 	 */
 	getTokenUsage(taskId: string): TokenUsage
-
 	/**
 	 * Logs a message to the output channel.
 	 * @param message The message to log.
@@ -98,472 +480,4 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	log(message: string): void
 }
 
-export type ClineAsk =
-	| "followup"
-	| "command"
-	| "command_output"
-	| "completion_result"
-	| "tool"
-	| "api_req_failed"
-	| "resume_task"
-	| "resume_completed_task"
-	| "mistake_limit_reached"
-	| "browser_action_launch"
-	| "use_mcp_server"
-	| "finishTask"
-
-export type ClineSay =
-	| "task"
-	| "error"
-	| "api_req_started"
-	| "api_req_finished"
-	| "api_req_retried"
-	| "api_req_retry_delayed"
-	| "api_req_deleted"
-	| "text"
-	| "reasoning"
-	| "completion_result"
-	| "user_feedback"
-	| "user_feedback_diff"
-	| "command_output"
-	| "tool"
-	| "shell_integration_warning"
-	| "browser_action"
-	| "browser_action_result"
-	| "command"
-	| "mcp_server_request_started"
-	| "mcp_server_response"
-	| "new_task_started"
-	| "new_task"
-	| "checkpoint_saved"
-	| "rooignore_error"
-
-export interface ClineMessage {
-	ts: number
-	type: "ask" | "say"
-	ask?: ClineAsk
-	say?: ClineSay
-	text?: string
-	images?: string[]
-	partial?: boolean
-	reasoning?: string
-	conversationHistoryIndex?: number
-	checkpoint?: Record<string, unknown>
-	progressStatus?: ToolProgressStatus
-}
-
-export interface ModelInfo {
-	maxTokens?: number
-	contextWindow: number
-	supportsImages?: boolean
-	supportsComputerUse?: boolean
-	supportsPromptCache: boolean // This value is hardcoded for now.
-	inputPrice?: number
-	outputPrice?: number
-	cacheWritesPrice?: number
-	cacheReadsPrice?: number
-	description?: string
-	reasoningEffort?: "low" | "medium" | "high"
-	thinking?: boolean
-}
-
-export interface ApiConfigMeta {
-	id: string
-	name: string
-	apiProvider?: ProviderName
-}
-
-export type HistoryItem = {
-	id: string
-	number: number
-	ts: number
-	task: string
-	tokensIn: number
-	tokensOut: number
-	cacheWrites?: number
-	cacheReads?: number
-	totalCost: number
-	size?: number
-}
-
-export type ExperimentId =
-	| "experimentalDiffStrategy"
-	| "search_and_replace"
-	| "insert_content"
-	| "powerSteering"
-	| "multi_search_and_replace"
-
-export type CheckpointStorage = "task" | "workspace"
-
-export type GroupOptions = {
-	fileRegex?: string // Regular expression pattern.
-	description?: string // Human-readable description of the pattern.
-}
-
-export type ToolGroup = "read" | "edit" | "browser" | "command" | "mcp" | "modes"
-
-export type GroupEntry = ToolGroup | readonly [ToolGroup, GroupOptions]
-
-export type ModeConfig = {
-	slug: string
-	name: string
-	roleDefinition: string
-	customInstructions?: string
-	groups: readonly GroupEntry[] // Now supports both simple strings and tuples with options
-	source?: "global" | "project" // Where this mode was loaded from
-}
-
-export type PromptComponent = {
-	roleDefinition?: string
-	customInstructions?: string
-}
-
-export type CustomModePrompts = {
-	[key: string]: PromptComponent | undefined
-}
-
-export type CustomSupportPrompts = {
-	[key: string]: string | undefined
-}
-
-export type TelemetrySetting = "unset" | "enabled" | "disabled"
-
-export type Language =
-	| "ca"
-	| "de"
-	| "en"
-	| "es"
-	| "fr"
-	| "hi"
-	| "it"
-	| "ja"
-	| "ko"
-	| "pl"
-	| "pt-BR"
-	| "tr"
-	| "vi"
-	| "zh-CN"
-	| "zh-TW"
-
-/**
- * GlobalSettings
- *
- * These are settings that apply globally.
- * They are all stored in the global state.
- */
-
-export interface GlobalSettings {
-	currentApiConfigName?: string
-	listApiConfigMeta?: ApiConfigMeta[]
-	pinnedApiConfigs?: Record<string, boolean>
-
-	lastShownAnnouncementId?: string
-	customInstructions?: string
-	taskHistory?: HistoryItem[]
-
-	autoApprovalEnabled?: boolean
-	alwaysAllowReadOnly?: boolean
-	alwaysAllowReadOnlyOutsideWorkspace?: boolean
-	alwaysAllowWrite?: boolean
-	alwaysAllowWriteOutsideWorkspace?: boolean
-	writeDelayMs?: number
-	alwaysAllowBrowser?: boolean
-	alwaysApproveResubmit?: boolean
-	requestDelaySeconds?: number
-	alwaysAllowMcp?: boolean
-	alwaysAllowModeSwitch?: boolean
-	alwaysAllowSubtasks?: boolean
-	alwaysAllowExecute?: boolean
-	allowedCommands?: string[]
-
-	browserToolEnabled?: boolean
-	browserViewportSize?: string
-	screenshotQuality?: number
-	remoteBrowserEnabled?: boolean
-	remoteBrowserHost?: string
-
-	enableCheckpoints?: boolean
-	checkpointStorage?: CheckpointStorage
-
-	ttsEnabled?: boolean
-	ttsSpeed?: number
-	soundEnabled?: boolean
-	soundVolume?: number
-
-	maxOpenTabsContext?: number
-	maxWorkspaceFiles?: number
-	showRooIgnoredFiles?: boolean
-	maxReadFileLine?: number
-
-	terminalOutputLineLimit?: number
-	terminalShellIntegrationTimeout?: number
-
-	rateLimitSeconds?: number
-	diffEnabled?: boolean
-	fuzzyMatchThreshold?: number
-	experiments?: Record<ExperimentId, boolean> // Map of experiment IDs to their enabled state.
-
-	language?: Language
-
-	telemetrySetting?: TelemetrySetting
-
-	mcpEnabled?: boolean
-	enableMcpServerCreation?: boolean
-
-	mode?: string
-	modeApiConfigs?: Record<string, string>
-	customModes?: ModeConfig[]
-	customModePrompts?: CustomModePrompts
-	customSupportPrompts?: CustomSupportPrompts
-	enhancementApiConfigId?: string
-}
-
-export type GlobalSettingsKey = keyof GlobalSettings
-
-/**
- * ProviderSettings
- *
- * These are settings that apply on a per-provider basis.
- * Non-sensitive values  are stored in the global state.
- * Sensitive values are stored in VSCode secrets.
- */
-
-/**
- * DiscriminatedProviderSettings
- *
- * NOTE: This is actually how our provider settings should be typed, but it
- * will take a little elbow grease to move to this shape. For now we're just
- * using it to generate the `ProviderName`.
- */
-
-export type DiscriminatedProviderSettings =
-	| {
-			apiProvider: "anthropic"
-			apiKey?: string
-			anthropicBaseUrl?: string
-			apiModelId?: string
-	  }
-	| {
-			apiProvider: "glama"
-			glamaApiKey?: string
-			glamaModelId?: string
-	  }
-	| {
-			apiProvider: "openrouter"
-			openRouterApiKey?: string
-			openRouterModelId?: string
-			openRouterBaseUrl?: string
-			openRouterSpecificProvider?: string
-			openRouterUseMiddleOutTransform?: boolean
-	  }
-	| {
-			apiProvider: "bedrock"
-			awsAccessKey?: string
-			awsSecretKey?: string
-			awsSessionToken?: string
-			awsRegion?: string
-			awsUseCrossRegionInference?: boolean
-			awsUsePromptCache?: boolean
-			awspromptCacheId?: string
-			awsProfile?: string
-			awsUseProfile?: boolean
-			awsCustomArn?: string
-	  }
-	| {
-			apiProvider: "vertex"
-			vertexKeyFile?: string
-			vertexJsonCredentials?: string
-			vertexProjectId?: string
-			vertexRegion?: string
-	  }
-	| {
-			apiProvider: "openai"
-			openAiApiKey?: string
-			openAiBaseUrl?: string
-			openAiR1FormatEnabled?: boolean
-			openAiModelId?: string
-			openAiUseAzure?: boolean
-			azureApiVersion?: string
-			openAiStreamingEnabled?: boolean
-	  }
-	| {
-			apiProvider: "ollama"
-			ollamaModelId?: string
-			ollamaBaseUrl?: string
-	  }
-	| {
-			apiProvider: "vscode-lm"
-			vsCodeLmModelSelector?: vscode.LanguageModelChatSelector
-	  }
-	| {
-			apiProvider: "lmstudio"
-			lmStudioModelId?: string
-			lmStudioBaseUrl?: string
-			lmStudioDraftModelId?: string
-			lmStudioSpeculativeDecodingEnabled?: boolean
-	  }
-	| {
-			apiProvider: "gemini"
-			googleGeminiBaseUrl?: string
-	  }
-	| {
-			apiProvider: "openai-native"
-			openAiNativeApiKey?: string
-	  }
-	| {
-			apiProvider: "mistral"
-			mistralApiKey?: string
-			mistralCodestralUrl?: string
-	  }
-	| {
-			apiProvider: "deepseek"
-			deepSeekApiKey?: string
-			deepSeekBaseUrl?: string
-	  }
-	| {
-			apiProvider: "unbound"
-			unboundApiKey?: string
-			unboundModelId?: string
-	  }
-	| {
-			apiProvider: "requesty"
-			requestyApiKey?: string
-			requestyModelId?: string
-	  }
-	| {
-			apiProvider: "human-relay"
-	  }
-	| {
-			apiProvider: "fake-ai"
-			fakeAi?: unknown
-	  }
-
-export type ProviderName = DiscriminatedProviderSettings["apiProvider"]
-
-export interface ProviderSettings {
-	apiProvider?: ProviderName
-	apiModelId?: string
-	// Anthropic
-	apiKey?: string // secret
-	anthropicBaseUrl?: string
-	// Glama
-	glamaApiKey?: string // secret
-	glamaModelId?: string
-	glamaModelInfo?: ModelInfo
-	// OpenRouter
-	openRouterApiKey?: string // secret
-	openRouterModelId?: string
-	openRouterModelInfo?: ModelInfo
-	openRouterBaseUrl?: string
-	openRouterSpecificProvider?: string
-	openRouterUseMiddleOutTransform?: boolean
-	// AWS Bedrock
-	awsAccessKey?: string // secret
-	awsSecretKey?: string // secret
-	awsSessionToken?: string // secret
-	awsRegion?: string
-	awsUseCrossRegionInference?: boolean
-	awsUsePromptCache?: boolean
-	awspromptCacheId?: string
-	awsProfile?: string
-	awsUseProfile?: boolean
-	awsCustomArn?: string
-	// Google Vertex
-	vertexKeyFile?: string
-	vertexJsonCredentials?: string
-	vertexProjectId?: string
-	vertexRegion?: string
-	// OpenAI
-	openAiApiKey?: string // secret
-	openAiBaseUrl?: string
-	openAiR1FormatEnabled?: boolean
-	openAiModelId?: string
-	openAiCustomModelInfo?: ModelInfo
-	openAiUseAzure?: boolean
-	azureApiVersion?: string
-	openAiStreamingEnabled?: boolean
-	// Ollama
-	ollamaModelId?: string
-	ollamaBaseUrl?: string
-	// VS Code LM
-	vsCodeLmModelSelector?: vscode.LanguageModelChatSelector
-	// LM Studio
-	lmStudioModelId?: string
-	lmStudioBaseUrl?: string
-	lmStudioDraftModelId?: string
-	lmStudioSpeculativeDecodingEnabled?: boolean
-	// Gemini
-	geminiApiKey?: string // secret
-	googleGeminiBaseUrl?: string
-	// OpenAI Native
-	openAiNativeApiKey?: string // secret
-	// Mistral
-	mistralApiKey?: string // secret
-	mistralCodestralUrl?: string // New option for Codestral URL.
-	// DeepSeek
-	deepSeekApiKey?: string // secret
-	deepSeekBaseUrl?: string
-	// Unbound
-	unboundApiKey?: string // secret
-	unboundModelId?: string
-	unboundModelInfo?: ModelInfo
-	// Requesty
-	requestyApiKey?: string
-	requestyModelId?: string
-	requestyModelInfo?: ModelInfo
-	// Claude 3.7 Sonnet Thinking
-	modelTemperature?: number | null
-	modelMaxTokens?: number
-	modelMaxThinkingTokens?: number
-	// Generic (For now though, OpenAI, DeekSeek, Mistral, and Requesty make reference to it.)
-	includeMaxTokens?: boolean
-	// Fake AI
-	fakeAi?: unknown
-}
-
-export type ProviderSettingsKey = keyof ProviderSettings
-
-/**
- * RooCodeSettings
- *
- * All settings, irrespective of scope and storage.
- */
-
-export type RooCodeSettings = GlobalSettings & ProviderSettings
-
-export type RooCodeSettingsKey = keyof RooCodeSettings
-
-/**
- * SecretState
- *
- * All settings that are stored in VSCode secrets.
- */
-
-export type SecretState = Pick<
-	RooCodeSettings,
-	| "apiKey"
-	| "glamaApiKey"
-	| "openRouterApiKey"
-	| "awsAccessKey"
-	| "awsSecretKey"
-	| "awsSessionToken"
-	| "openAiApiKey"
-	| "geminiApiKey"
-	| "openAiNativeApiKey"
-	| "deepSeekApiKey"
-	| "mistralApiKey"
-	| "unboundApiKey"
-	| "requestyApiKey"
->
-
-export type SecretStateKey = keyof SecretState
-
-/**
- * GlobalState
- *
- * All settings that are stored in the global state.
- */
-
-export type GlobalState = Omit<RooCodeSettings, SecretStateKey>
-
-export type GlobalStateKey = keyof GlobalState
+export type { ClineMessage, GlobalSettings, ProviderSettings, RooCodeAPI, RooCodeEvents, RooCodeSettings, TokenUsage }

+ 407 - 0
src/exports/types.ts

@@ -0,0 +1,407 @@
+// This file is automatically generated by running `npm run generate-types`
+// Do not edit it directly.
+
+type ProviderSettings = {
+	apiProvider?:
+		| (
+				| "anthropic"
+				| "glama"
+				| "openrouter"
+				| "bedrock"
+				| "vertex"
+				| "openai"
+				| "ollama"
+				| "vscode-lm"
+				| "lmstudio"
+				| "gemini"
+				| "openai-native"
+				| "mistral"
+				| "deepseek"
+				| "unbound"
+				| "requesty"
+				| "human-relay"
+				| "fake-ai"
+		  )
+		| undefined
+	apiModelId?: string | undefined
+	apiKey?: string | undefined
+	anthropicBaseUrl?: string | undefined
+	glamaModelId?: string | undefined
+	glamaModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	glamaApiKey?: string | undefined
+	openRouterApiKey?: string | undefined
+	openRouterModelId?: string | undefined
+	openRouterModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	openRouterBaseUrl?: string | undefined
+	openRouterSpecificProvider?: string | undefined
+	openRouterUseMiddleOutTransform?: boolean | undefined
+	awsAccessKey?: string | undefined
+	awsSecretKey?: string | undefined
+	awsSessionToken?: string | undefined
+	awsRegion?: string | undefined
+	awsUseCrossRegionInference?: boolean | undefined
+	awsUsePromptCache?: boolean | undefined
+	awspromptCacheId?: string | undefined
+	awsProfile?: string | undefined
+	awsUseProfile?: boolean | undefined
+	awsCustomArn?: string | undefined
+	vertexKeyFile?: string | undefined
+	vertexJsonCredentials?: string | undefined
+	vertexProjectId?: string | undefined
+	vertexRegion?: string | undefined
+	openAiBaseUrl?: string | undefined
+	openAiApiKey?: string | undefined
+	openAiR1FormatEnabled?: boolean | undefined
+	openAiModelId?: string | undefined
+	openAiCustomModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	openAiUseAzure?: boolean | undefined
+	azureApiVersion?: string | undefined
+	openAiStreamingEnabled?: boolean | undefined
+	ollamaModelId?: string | undefined
+	ollamaBaseUrl?: string | undefined
+	vsCodeLmModelSelector?:
+		| {
+				vendor?: string | undefined
+				family?: string | undefined
+				version?: string | undefined
+				id?: string | undefined
+		  }
+		| undefined
+	lmStudioModelId?: string | undefined
+	lmStudioBaseUrl?: string | undefined
+	lmStudioDraftModelId?: string | undefined
+	lmStudioSpeculativeDecodingEnabled?: boolean | undefined
+	geminiApiKey?: string | undefined
+	googleGeminiBaseUrl?: string | undefined
+	openAiNativeApiKey?: string | undefined
+	mistralApiKey?: string | undefined
+	mistralCodestralUrl?: string | undefined
+	deepSeekBaseUrl?: string | undefined
+	deepSeekApiKey?: string | undefined
+	unboundApiKey?: string | undefined
+	unboundModelId?: string | undefined
+	unboundModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	requestyApiKey?: string | undefined
+	requestyModelId?: string | undefined
+	requestyModelInfo?:
+		| {
+				maxTokens?: number | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+		  }
+		| undefined
+	modelTemperature?: (number | null) | undefined
+	modelMaxTokens?: number | undefined
+	modelMaxThinkingTokens?: number | undefined
+	includeMaxTokens?: boolean | undefined
+	fakeAi?: unknown | undefined
+}
+
+export type { ProviderSettings }
+
+type GlobalSettings = {
+	currentApiConfigName?: string | undefined
+	listApiConfigMeta?:
+		| {
+				id: string
+				name: string
+				apiProvider?:
+					| (
+							| "anthropic"
+							| "glama"
+							| "openrouter"
+							| "bedrock"
+							| "vertex"
+							| "openai"
+							| "ollama"
+							| "vscode-lm"
+							| "lmstudio"
+							| "gemini"
+							| "openai-native"
+							| "mistral"
+							| "deepseek"
+							| "unbound"
+							| "requesty"
+							| "human-relay"
+							| "fake-ai"
+					  )
+					| undefined
+		  }[]
+		| undefined
+	pinnedApiConfigs?:
+		| {
+				[x: string]: boolean
+		  }
+		| undefined
+	lastShownAnnouncementId?: string | undefined
+	customInstructions?: string | undefined
+	taskHistory?:
+		| {
+				id: string
+				number: number
+				ts: number
+				task: string
+				tokensIn: number
+				tokensOut: number
+				cacheWrites?: number | undefined
+				cacheReads?: number | undefined
+				totalCost: number
+				size?: number | undefined
+		  }[]
+		| undefined
+	autoApprovalEnabled?: boolean | undefined
+	alwaysAllowReadOnly?: boolean | undefined
+	alwaysAllowReadOnlyOutsideWorkspace?: boolean | undefined
+	alwaysAllowWrite?: boolean | undefined
+	alwaysAllowWriteOutsideWorkspace?: boolean | undefined
+	writeDelayMs?: number | undefined
+	alwaysAllowBrowser?: boolean | undefined
+	alwaysApproveResubmit?: boolean | undefined
+	requestDelaySeconds?: number | undefined
+	alwaysAllowMcp?: boolean | undefined
+	alwaysAllowModeSwitch?: boolean | undefined
+	alwaysAllowSubtasks?: boolean | undefined
+	alwaysAllowExecute?: boolean | undefined
+	allowedCommands?: string[] | undefined
+	browserToolEnabled?: boolean | undefined
+	browserViewportSize?: string | undefined
+	screenshotQuality?: number | undefined
+	remoteBrowserEnabled?: boolean | undefined
+	remoteBrowserHost?: string | undefined
+	enableCheckpoints?: boolean | undefined
+	checkpointStorage?: ("task" | "workspace") | undefined
+	ttsEnabled?: boolean | undefined
+	ttsSpeed?: number | undefined
+	soundEnabled?: boolean | undefined
+	soundVolume?: number | undefined
+	maxOpenTabsContext?: number | undefined
+	maxWorkspaceFiles?: number | undefined
+	showRooIgnoredFiles?: boolean | undefined
+	maxReadFileLine?: number | undefined
+	terminalOutputLineLimit?: number | undefined
+	terminalShellIntegrationTimeout?: number | undefined
+	rateLimitSeconds?: number | undefined
+	diffEnabled?: boolean | undefined
+	fuzzyMatchThreshold?: number | undefined
+	experiments?:
+		| {
+				experimentalDiffStrategy: boolean
+				search_and_replace: boolean
+				insert_content: boolean
+				powerSteering: boolean
+				multi_search_and_replace: boolean
+		  }
+		| undefined
+	language?:
+		| (
+				| "ca"
+				| "de"
+				| "en"
+				| "es"
+				| "fr"
+				| "hi"
+				| "it"
+				| "ja"
+				| "ko"
+				| "pl"
+				| "pt-BR"
+				| "tr"
+				| "vi"
+				| "zh-CN"
+				| "zh-TW"
+		  )
+		| undefined
+	telemetrySetting?: ("unset" | "enabled" | "disabled") | undefined
+	mcpEnabled?: boolean | undefined
+	enableMcpServerCreation?: boolean | undefined
+	mode?: string | undefined
+	modeApiConfigs?:
+		| {
+				[x: string]: string
+		  }
+		| undefined
+	customModes?:
+		| {
+				slug: string
+				name: string
+				roleDefinition: string
+				customInstructions?: string | undefined
+				groups: (
+					| ("read" | "edit" | "browser" | "command" | "mcp" | "modes")
+					| [
+							"read" | "edit" | "browser" | "command" | "mcp" | "modes",
+							{
+								fileRegex?: string | undefined
+								description?: string | undefined
+							},
+					  ]
+				)[]
+				source?: ("global" | "project") | undefined
+		  }[]
+		| undefined
+	customModePrompts?:
+		| {
+				[x: string]:
+					| {
+							roleDefinition?: string | undefined
+							customInstructions?: string | undefined
+					  }
+					| undefined
+		  }
+		| undefined
+	customSupportPrompts?:
+		| {
+				[x: string]: string | undefined
+		  }
+		| undefined
+	enhancementApiConfigId?: string | undefined
+}
+
+export type { GlobalSettings }
+
+type ClineMessage = {
+	ts: number
+	type: "ask" | "say"
+	ask?:
+		| (
+				| "followup"
+				| "command"
+				| "command_output"
+				| "completion_result"
+				| "tool"
+				| "api_req_failed"
+				| "resume_task"
+				| "resume_completed_task"
+				| "mistake_limit_reached"
+				| "browser_action_launch"
+				| "use_mcp_server"
+				| "finishTask"
+		  )
+		| undefined
+	say?:
+		| (
+				| "task"
+				| "error"
+				| "api_req_started"
+				| "api_req_finished"
+				| "api_req_retried"
+				| "api_req_retry_delayed"
+				| "api_req_deleted"
+				| "text"
+				| "reasoning"
+				| "completion_result"
+				| "user_feedback"
+				| "user_feedback_diff"
+				| "command_output"
+				| "tool"
+				| "shell_integration_warning"
+				| "browser_action"
+				| "browser_action_result"
+				| "command"
+				| "mcp_server_request_started"
+				| "mcp_server_response"
+				| "new_task_started"
+				| "new_task"
+				| "checkpoint_saved"
+				| "rooignore_error"
+		  )
+		| undefined
+	text?: string | undefined
+	images?: string[] | undefined
+	partial?: boolean | undefined
+	reasoning?: string | undefined
+	conversationHistoryIndex?: number | undefined
+	checkpoint?:
+		| {
+				[x: string]: unknown
+		  }
+		| undefined
+	progressStatus?:
+		| {
+				icon?: string | undefined
+				text?: string | undefined
+		  }
+		| undefined
+}
+
+export type { ClineMessage }
+
+type TokenUsage = {
+	totalTokensIn: number
+	totalTokensOut: number
+	totalCacheWrites?: number | undefined
+	totalCacheReads?: number | undefined
+	totalCost: number
+	contextTokens: number
+}
+
+export type { TokenUsage }

+ 17 - 0
src/schemas/__tests__/index.test.ts

@@ -0,0 +1,17 @@
+// npx jest src/schemas/__tests__/index.test.ts
+
+import { GLOBAL_STATE_KEYS } from "../index"
+
+describe("GLOBAL_STATE_KEYS", () => {
+	it("should contain provider settings keys", () => {
+		expect(GLOBAL_STATE_KEYS).toContain("autoApprovalEnabled")
+	})
+
+	it("should contain provider settings keys", () => {
+		expect(GLOBAL_STATE_KEYS).toContain("anthropicBaseUrl")
+	})
+
+	it("should not contain secret state keys", () => {
+		expect(GLOBAL_STATE_KEYS).not.toContain("openRouterApiKey")
+	})
+})

+ 742 - 0
src/schemas/index.ts

@@ -0,0 +1,742 @@
+// Updates to this file will automatically propgate to src/exports/types.ts
+// via a pre-commit hook. If you want to update the types before committing you
+// can run `npm run generate-types`.
+
+import { z } from "zod"
+
+import { Equals, Keys, AssertEqual } from "../utils/type-fu"
+
+/**
+ * ProviderName
+ */
+
+export const providerNames = [
+	"anthropic",
+	"glama",
+	"openrouter",
+	"bedrock",
+	"vertex",
+	"openai",
+	"ollama",
+	"vscode-lm",
+	"lmstudio",
+	"gemini",
+	"openai-native",
+	"mistral",
+	"deepseek",
+	"unbound",
+	"requesty",
+	"human-relay",
+	"fake-ai",
+] as const
+
+export const providerNamesSchema = z.enum(providerNames)
+
+export type ProviderName = z.infer<typeof providerNamesSchema>
+
+/**
+ * ToolGroup
+ */
+
+export const toolGroups = ["read", "edit", "browser", "command", "mcp", "modes"] as const
+
+export const toolGroupsSchema = z.enum(toolGroups)
+
+export type ToolGroup = z.infer<typeof toolGroupsSchema>
+
+/**
+ * CheckpointStorage
+ */
+
+export const checkpointStorages = ["task", "workspace"] as const
+
+export const checkpointStoragesSchema = z.enum(checkpointStorages)
+
+export type CheckpointStorage = z.infer<typeof checkpointStoragesSchema>
+
+export const isCheckpointStorage = (value: string): value is CheckpointStorage =>
+	checkpointStorages.includes(value as CheckpointStorage)
+
+/**
+ * Language
+ */
+
+export const languages = [
+	"ca",
+	"de",
+	"en",
+	"es",
+	"fr",
+	"hi",
+	"it",
+	"ja",
+	"ko",
+	"pl",
+	"pt-BR",
+	"tr",
+	"vi",
+	"zh-CN",
+	"zh-TW",
+] as const
+
+export const languagesSchema = z.enum(languages)
+
+export type Language = z.infer<typeof languagesSchema>
+
+export const isLanguage = (value: string): value is Language => languages.includes(value as Language)
+
+/**
+ * TelemetrySetting
+ */
+
+export const telemetrySettings = ["unset", "enabled", "disabled"] as const
+
+export const telemetrySettingsSchema = z.enum(telemetrySettings)
+
+export type TelemetrySetting = z.infer<typeof telemetrySettingsSchema>
+
+/**
+ * ModelInfo
+ */
+
+export const modelInfoSchema = z.object({
+	maxTokens: z.number().optional(),
+	contextWindow: z.number(),
+	supportsImages: z.boolean().optional(),
+	supportsComputerUse: z.boolean().optional(),
+	supportsPromptCache: z.boolean(),
+	inputPrice: z.number().optional(),
+	outputPrice: z.number().optional(),
+	cacheWritesPrice: z.number().optional(),
+	cacheReadsPrice: z.number().optional(),
+	description: z.string().optional(),
+	reasoningEffort: z.enum(["low", "medium", "high"]).optional(),
+	thinking: z.boolean().optional(),
+})
+
+export type ModelInfo = z.infer<typeof modelInfoSchema>
+
+/**
+ * ApiConfigMeta
+ */
+
+export const apiConfigMetaSchema = z.object({
+	id: z.string(),
+	name: z.string(),
+	apiProvider: providerNamesSchema.optional(),
+})
+
+export type ApiConfigMeta = z.infer<typeof apiConfigMetaSchema>
+
+/**
+ * HistoryItem
+ */
+
+export const historyItemSchema = z.object({
+	id: z.string(),
+	number: z.number(),
+	ts: z.number(),
+	task: z.string(),
+	tokensIn: z.number(),
+	tokensOut: z.number(),
+	cacheWrites: z.number().optional(),
+	cacheReads: z.number().optional(),
+	totalCost: z.number(),
+	size: z.number().optional(),
+})
+
+export type HistoryItem = z.infer<typeof historyItemSchema>
+
+/**
+ * GroupOptions
+ */
+
+export const groupOptionsSchema = z.object({
+	fileRegex: z.string().optional(),
+	description: z.string().optional(),
+})
+
+export type GroupOptions = z.infer<typeof groupOptionsSchema>
+
+/**
+ * GroupEntry
+ */
+
+export const groupEntrySchema = z.union([toolGroupsSchema, z.tuple([toolGroupsSchema, groupOptionsSchema])])
+
+export type GroupEntry = z.infer<typeof groupEntrySchema>
+
+/**
+ * ModeConfig
+ */
+
+export const modeConfigSchema = z.object({
+	slug: z.string(),
+	name: z.string(),
+	roleDefinition: z.string(),
+	customInstructions: z.string().optional(),
+	groups: z.array(groupEntrySchema),
+	source: z.enum(["global", "project"]).optional(),
+})
+
+export type ModeConfig = z.infer<typeof modeConfigSchema>
+
+/**
+ * PromptComponent
+ */
+
+export const promptComponentSchema = z.object({
+	roleDefinition: z.string().optional(),
+	customInstructions: z.string().optional(),
+})
+
+export type PromptComponent = z.infer<typeof promptComponentSchema>
+
+/**
+ * CustomModePrompts
+ */
+
+export const customModePromptsSchema = z.record(z.string(), promptComponentSchema.optional())
+
+export type CustomModePrompts = z.infer<typeof customModePromptsSchema>
+
+/**
+ * CustomSupportPrompts
+ */
+
+export const customSupportPromptsSchema = z.record(z.string(), z.string().optional())
+
+export type CustomSupportPrompts = z.infer<typeof customSupportPromptsSchema>
+
+/**
+ * ExperimentId
+ */
+
+export const experimentIds = [
+	"experimentalDiffStrategy",
+	"search_and_replace",
+	"insert_content",
+	"powerSteering",
+	"multi_search_and_replace",
+] as const
+
+export const experimentIdsSchema = z.enum(experimentIds)
+
+export type ExperimentId = z.infer<typeof experimentIdsSchema>
+
+/**
+ * Experiments
+ */
+
+const experimentsSchema = z.object({
+	experimentalDiffStrategy: z.boolean(),
+	search_and_replace: z.boolean(),
+	insert_content: z.boolean(),
+	powerSteering: z.boolean(),
+	multi_search_and_replace: z.boolean(),
+})
+
+export type Experiments = z.infer<typeof experimentsSchema>
+
+type _AssertExperiments = AssertEqual<Equals<ExperimentId, Keys<Experiments>>>
+
+/**
+ * ProviderSettings
+ */
+
+export const providerSettingsSchema = z.object({
+	apiProvider: providerNamesSchema.optional(),
+	// Anthropic
+	apiModelId: z.string().optional(),
+	apiKey: z.string().optional(),
+	anthropicBaseUrl: z.string().optional(),
+	// Glama
+	glamaModelId: z.string().optional(),
+	glamaModelInfo: modelInfoSchema.optional(),
+	glamaApiKey: z.string().optional(),
+	// OpenRouter
+	openRouterApiKey: z.string().optional(),
+	openRouterModelId: z.string().optional(),
+	openRouterModelInfo: modelInfoSchema.optional(),
+	openRouterBaseUrl: z.string().optional(),
+	openRouterSpecificProvider: z.string().optional(),
+	openRouterUseMiddleOutTransform: z.boolean().optional(),
+	// AWS Bedrock
+	awsAccessKey: z.string().optional(),
+	awsSecretKey: z.string().optional(),
+	awsSessionToken: z.string().optional(),
+	awsRegion: z.string().optional(),
+	awsUseCrossRegionInference: z.boolean().optional(),
+	awsUsePromptCache: z.boolean().optional(),
+	awspromptCacheId: z.string().optional(),
+	awsProfile: z.string().optional(),
+	awsUseProfile: z.boolean().optional(),
+	awsCustomArn: z.string().optional(),
+	// Google Vertex
+	vertexKeyFile: z.string().optional(),
+	vertexJsonCredentials: z.string().optional(),
+	vertexProjectId: z.string().optional(),
+	vertexRegion: z.string().optional(),
+	// OpenAI
+	openAiBaseUrl: z.string().optional(),
+	openAiApiKey: z.string().optional(),
+	openAiR1FormatEnabled: z.boolean().optional(),
+	openAiModelId: z.string().optional(),
+	openAiCustomModelInfo: modelInfoSchema.optional(),
+	openAiUseAzure: z.boolean().optional(),
+	azureApiVersion: z.string().optional(),
+	openAiStreamingEnabled: z.boolean().optional(),
+	// Ollama
+	ollamaModelId: z.string().optional(),
+	ollamaBaseUrl: z.string().optional(),
+	// VS Code LM
+	vsCodeLmModelSelector: z
+		.object({
+			vendor: z.string().optional(),
+			family: z.string().optional(),
+			version: z.string().optional(),
+			id: z.string().optional(),
+		})
+		.optional(),
+	// LM Studio
+	lmStudioModelId: z.string().optional(),
+	lmStudioBaseUrl: z.string().optional(),
+	lmStudioDraftModelId: z.string().optional(),
+	lmStudioSpeculativeDecodingEnabled: z.boolean().optional(),
+	// Gemini
+	geminiApiKey: z.string().optional(),
+	googleGeminiBaseUrl: z.string().optional(),
+	// OpenAI Native
+	openAiNativeApiKey: z.string().optional(),
+	// Mistral
+	mistralApiKey: z.string().optional(),
+	mistralCodestralUrl: z.string().optional(),
+	// DeepSeek
+	deepSeekBaseUrl: z.string().optional(),
+	deepSeekApiKey: z.string().optional(),
+	// Unbound
+	unboundApiKey: z.string().optional(),
+	unboundModelId: z.string().optional(),
+	unboundModelInfo: modelInfoSchema.optional(),
+	// Requesty
+	requestyApiKey: z.string().optional(),
+	requestyModelId: z.string().optional(),
+	requestyModelInfo: modelInfoSchema.optional(),
+	// Claude 3.7 Sonnet Thinking
+	modelTemperature: z.number().nullish(),
+	modelMaxTokens: z.number().optional(),
+	modelMaxThinkingTokens: z.number().optional(),
+	// Generic
+	includeMaxTokens: z.boolean().optional(),
+	// Fake AI
+	fakeAi: z.unknown().optional(),
+})
+
+export type ProviderSettings = z.infer<typeof providerSettingsSchema>
+
+type ProviderSettingsRecord = Record<Keys<ProviderSettings>, undefined>
+
+const providerSettingsRecord: ProviderSettingsRecord = {
+	apiProvider: undefined,
+	// Anthropic
+	apiModelId: undefined,
+	apiKey: undefined,
+	anthropicBaseUrl: undefined,
+	// Glama
+	glamaModelId: undefined,
+	glamaModelInfo: undefined,
+	glamaApiKey: undefined,
+	// OpenRouter
+	openRouterApiKey: undefined,
+	openRouterModelId: undefined,
+	openRouterModelInfo: undefined,
+	openRouterBaseUrl: undefined,
+	openRouterSpecificProvider: undefined,
+	openRouterUseMiddleOutTransform: undefined,
+	// AWS Bedrock
+	awsAccessKey: undefined,
+	awsSecretKey: undefined,
+	awsSessionToken: undefined,
+	awsRegion: undefined,
+	awsUseCrossRegionInference: undefined,
+	awsUsePromptCache: undefined,
+	awspromptCacheId: undefined,
+	awsProfile: undefined,
+	awsUseProfile: undefined,
+	awsCustomArn: undefined,
+	// Google Vertex
+	vertexKeyFile: undefined,
+	vertexJsonCredentials: undefined,
+	vertexProjectId: undefined,
+	vertexRegion: undefined,
+	// OpenAI
+	openAiBaseUrl: undefined,
+	openAiApiKey: undefined,
+	openAiR1FormatEnabled: undefined,
+	openAiModelId: undefined,
+	openAiCustomModelInfo: undefined,
+	openAiUseAzure: undefined,
+	azureApiVersion: undefined,
+	openAiStreamingEnabled: undefined,
+	// Ollama
+	ollamaModelId: undefined,
+	ollamaBaseUrl: undefined,
+	// VS Code LM
+	vsCodeLmModelSelector: undefined,
+	lmStudioModelId: undefined,
+	lmStudioBaseUrl: undefined,
+	lmStudioDraftModelId: undefined,
+	lmStudioSpeculativeDecodingEnabled: undefined,
+	// Gemini
+	geminiApiKey: undefined,
+	googleGeminiBaseUrl: undefined,
+	// OpenAI Native
+	openAiNativeApiKey: undefined,
+	// Mistral
+	mistralApiKey: undefined,
+	mistralCodestralUrl: undefined,
+	// DeepSeek
+	deepSeekBaseUrl: undefined,
+	deepSeekApiKey: undefined,
+	// Unbound
+	unboundApiKey: undefined,
+	unboundModelId: undefined,
+	unboundModelInfo: undefined,
+	// Requesty
+	requestyApiKey: undefined,
+	requestyModelId: undefined,
+	requestyModelInfo: undefined,
+	// Claude 3.7 Sonnet Thinking
+	modelTemperature: undefined,
+	modelMaxTokens: undefined,
+	modelMaxThinkingTokens: undefined,
+	// Generic
+	includeMaxTokens: undefined,
+	// Fake AI
+	fakeAi: undefined,
+}
+
+export const PROVIDER_SETTINGS_KEYS = Object.keys(providerSettingsRecord) as Keys<ProviderSettings>[]
+
+/**
+ * GlobalSettings
+ */
+
+export const globalSettingsSchema = z.object({
+	currentApiConfigName: z.string().optional(),
+	listApiConfigMeta: z.array(apiConfigMetaSchema).optional(),
+	pinnedApiConfigs: z.record(z.string(), z.boolean()).optional(),
+
+	lastShownAnnouncementId: z.string().optional(),
+	customInstructions: z.string().optional(),
+	taskHistory: z.array(historyItemSchema).optional(),
+
+	autoApprovalEnabled: z.boolean().optional(),
+	alwaysAllowReadOnly: z.boolean().optional(),
+	alwaysAllowReadOnlyOutsideWorkspace: z.boolean().optional(),
+	alwaysAllowWrite: z.boolean().optional(),
+	alwaysAllowWriteOutsideWorkspace: z.boolean().optional(),
+	writeDelayMs: z.number().optional(),
+	alwaysAllowBrowser: z.boolean().optional(),
+	alwaysApproveResubmit: z.boolean().optional(),
+	requestDelaySeconds: z.number().optional(),
+	alwaysAllowMcp: z.boolean().optional(),
+	alwaysAllowModeSwitch: z.boolean().optional(),
+	alwaysAllowSubtasks: z.boolean().optional(),
+	alwaysAllowExecute: z.boolean().optional(),
+	allowedCommands: z.array(z.string()).optional(),
+
+	browserToolEnabled: z.boolean().optional(),
+	browserViewportSize: z.string().optional(),
+	screenshotQuality: z.number().optional(),
+	remoteBrowserEnabled: z.boolean().optional(),
+	remoteBrowserHost: z.string().optional(),
+
+	enableCheckpoints: z.boolean().optional(),
+	checkpointStorage: checkpointStoragesSchema.optional(),
+
+	ttsEnabled: z.boolean().optional(),
+	ttsSpeed: z.number().optional(),
+	soundEnabled: z.boolean().optional(),
+	soundVolume: z.number().optional(),
+
+	maxOpenTabsContext: z.number().optional(),
+	maxWorkspaceFiles: z.number().optional(),
+	showRooIgnoredFiles: z.boolean().optional(),
+	maxReadFileLine: z.number().optional(),
+
+	terminalOutputLineLimit: z.number().optional(),
+	terminalShellIntegrationTimeout: z.number().optional(),
+
+	rateLimitSeconds: z.number().optional(),
+	diffEnabled: z.boolean().optional(),
+	fuzzyMatchThreshold: z.number().optional(),
+	experiments: experimentsSchema.optional(),
+
+	language: languagesSchema.optional(),
+
+	telemetrySetting: telemetrySettingsSchema.optional(),
+
+	mcpEnabled: z.boolean().optional(),
+	enableMcpServerCreation: z.boolean().optional(),
+
+	mode: z.string().optional(),
+	modeApiConfigs: z.record(z.string(), z.string()).optional(),
+	customModes: z.array(modeConfigSchema).optional(),
+	customModePrompts: customModePromptsSchema.optional(),
+	customSupportPrompts: customSupportPromptsSchema.optional(),
+	enhancementApiConfigId: z.string().optional(),
+})
+
+export type GlobalSettings = z.infer<typeof globalSettingsSchema>
+
+type GlobalSettingsRecord = Record<Keys<GlobalSettings>, undefined>
+
+const globalSettingsRecord: GlobalSettingsRecord = {
+	currentApiConfigName: undefined,
+	listApiConfigMeta: undefined,
+	pinnedApiConfigs: undefined,
+
+	lastShownAnnouncementId: undefined,
+	customInstructions: undefined,
+	taskHistory: undefined,
+
+	autoApprovalEnabled: undefined,
+	alwaysAllowReadOnly: undefined,
+	alwaysAllowReadOnlyOutsideWorkspace: undefined,
+	alwaysAllowWrite: undefined,
+	alwaysAllowWriteOutsideWorkspace: undefined,
+	writeDelayMs: undefined,
+	alwaysAllowBrowser: undefined,
+	alwaysApproveResubmit: undefined,
+	requestDelaySeconds: undefined,
+	alwaysAllowMcp: undefined,
+	alwaysAllowModeSwitch: undefined,
+	alwaysAllowSubtasks: undefined,
+	alwaysAllowExecute: undefined,
+	allowedCommands: undefined,
+
+	browserToolEnabled: undefined,
+	browserViewportSize: undefined,
+	screenshotQuality: undefined,
+	remoteBrowserEnabled: undefined,
+	remoteBrowserHost: undefined,
+
+	enableCheckpoints: undefined,
+	checkpointStorage: undefined,
+
+	ttsEnabled: undefined,
+	ttsSpeed: undefined,
+	soundEnabled: undefined,
+	soundVolume: undefined,
+
+	maxOpenTabsContext: undefined,
+	maxWorkspaceFiles: undefined,
+	showRooIgnoredFiles: undefined,
+	maxReadFileLine: undefined,
+
+	terminalOutputLineLimit: undefined,
+	terminalShellIntegrationTimeout: undefined,
+
+	rateLimitSeconds: undefined,
+	diffEnabled: undefined,
+	fuzzyMatchThreshold: undefined,
+	experiments: undefined,
+
+	language: undefined,
+
+	telemetrySetting: undefined,
+
+	mcpEnabled: undefined,
+	enableMcpServerCreation: undefined,
+
+	mode: undefined,
+	modeApiConfigs: undefined,
+	customModes: undefined,
+	customModePrompts: undefined,
+	customSupportPrompts: undefined,
+	enhancementApiConfigId: undefined,
+}
+
+export const GLOBAL_SETTINGS_KEYS = Object.keys(globalSettingsRecord) as Keys<GlobalSettings>[]
+
+/**
+ * RooCodeSettings
+ */
+
+export type RooCodeSettings = GlobalSettings & ProviderSettings
+
+/**
+ * SecretState
+ */
+
+export type SecretState = Pick<
+	ProviderSettings,
+	| "apiKey"
+	| "glamaApiKey"
+	| "openRouterApiKey"
+	| "awsAccessKey"
+	| "awsSecretKey"
+	| "awsSessionToken"
+	| "openAiApiKey"
+	| "geminiApiKey"
+	| "openAiNativeApiKey"
+	| "deepSeekApiKey"
+	| "mistralApiKey"
+	| "unboundApiKey"
+	| "requestyApiKey"
+>
+
+type SecretStateRecord = Record<Keys<SecretState>, undefined>
+
+const secretStateRecord: SecretStateRecord = {
+	apiKey: undefined,
+	glamaApiKey: undefined,
+	openRouterApiKey: undefined,
+	awsAccessKey: undefined,
+	awsSecretKey: undefined,
+	awsSessionToken: undefined,
+	openAiApiKey: undefined,
+	geminiApiKey: undefined,
+	openAiNativeApiKey: undefined,
+	deepSeekApiKey: undefined,
+	mistralApiKey: undefined,
+	unboundApiKey: undefined,
+	requestyApiKey: undefined,
+}
+
+export const SECRET_STATE_KEYS = Object.keys(secretStateRecord) as Keys<SecretState>[]
+
+export const isSecretStateKey = (key: string): key is Keys<SecretState> =>
+	SECRET_STATE_KEYS.includes(key as Keys<SecretState>)
+
+/**
+ * GlobalState
+ */
+
+export type GlobalState = Omit<RooCodeSettings, Keys<SecretState>>
+
+export const GLOBAL_STATE_KEYS = [...GLOBAL_SETTINGS_KEYS, ...PROVIDER_SETTINGS_KEYS].filter(
+	(key: Keys<RooCodeSettings>) => !SECRET_STATE_KEYS.includes(key as Keys<SecretState>),
+) as Keys<GlobalState>[]
+
+export const isGlobalStateKey = (key: string): key is Keys<GlobalState> =>
+	GLOBAL_STATE_KEYS.includes(key as Keys<GlobalState>)
+
+/**
+ * ClineAsk
+ */
+
+export const clineAsks = [
+	"followup",
+	"command",
+	"command_output",
+	"completion_result",
+	"tool",
+	"api_req_failed",
+	"resume_task",
+	"resume_completed_task",
+	"mistake_limit_reached",
+	"browser_action_launch",
+	"use_mcp_server",
+	"finishTask",
+] as const
+
+export const clineAskSchema = z.enum(clineAsks)
+
+export type ClineAsk = z.infer<typeof clineAskSchema>
+
+// ClineSay
+
+export const clineSays = [
+	"task",
+	"error",
+	"api_req_started",
+	"api_req_finished",
+	"api_req_retried",
+	"api_req_retry_delayed",
+	"api_req_deleted",
+	"text",
+	"reasoning",
+	"completion_result",
+	"user_feedback",
+	"user_feedback_diff",
+	"command_output",
+	"tool",
+	"shell_integration_warning",
+	"browser_action",
+	"browser_action_result",
+	"command",
+	"mcp_server_request_started",
+	"mcp_server_response",
+	"new_task_started",
+	"new_task",
+	"checkpoint_saved",
+	"rooignore_error",
+] as const
+
+export const clineSaySchema = z.enum(clineSays)
+
+export type ClineSay = z.infer<typeof clineSaySchema>
+
+/**
+ * ToolProgressStatus
+ */
+
+export const toolProgressStatusSchema = z.object({
+	icon: z.string().optional(),
+	text: z.string().optional(),
+})
+
+export type ToolProgressStatus = z.infer<typeof toolProgressStatusSchema>
+
+/**
+ * ClineMessage
+ */
+
+export const clineMessageSchema = z.object({
+	ts: z.number(),
+	type: z.union([z.literal("ask"), z.literal("say")]),
+	ask: clineAskSchema.optional(),
+	say: clineSaySchema.optional(),
+	text: z.string().optional(),
+	images: z.array(z.string()).optional(),
+	partial: z.boolean().optional(),
+	reasoning: z.string().optional(),
+	conversationHistoryIndex: z.number().optional(),
+	checkpoint: z.record(z.string(), z.unknown()).optional(),
+	progressStatus: toolProgressStatusSchema.optional(),
+})
+
+export type ClineMessage = z.infer<typeof clineMessageSchema>
+
+/**
+ * TokenUsage
+ */
+
+export const tokenUsageSchema = z.object({
+	totalTokensIn: z.number(),
+	totalTokensOut: z.number(),
+	totalCacheWrites: z.number().optional(),
+	totalCacheReads: z.number().optional(),
+	totalCost: z.number(),
+	contextTokens: z.number(),
+})
+
+export type TokenUsage = z.infer<typeof tokenUsageSchema>
+
+/**
+ * TypeDefinition
+ */
+
+type TypeDefinition = {
+	schema: z.ZodTypeAny
+	identifier: string
+}
+
+export const typeDefinitions: TypeDefinition[] = [
+	{ schema: providerSettingsSchema, identifier: "ProviderSettings" },
+	{ schema: globalSettingsSchema, identifier: "GlobalSettings" },
+	{ schema: clineMessageSchema, identifier: "ClineMessage" },
+	{ schema: tokenUsageSchema, identifier: "TokenUsage" },
+]

+ 17 - 13
src/shared/ExtensionMessage.ts

@@ -1,14 +1,23 @@
-import { ApiConfiguration, ModelInfo } from "./api"
-import { HistoryItem } from "./HistoryItem"
+import {
+	ModelInfo,
+	GlobalSettings,
+	ApiConfigMeta,
+	ProviderSettings as ApiConfiguration,
+	HistoryItem,
+	ModeConfig,
+	CheckpointStorage,
+	TelemetrySetting,
+	ExperimentId,
+	ClineAsk,
+	ClineSay,
+	ToolProgressStatus,
+	ClineMessage,
+} from "../schemas"
 import { McpServer } from "./mcp"
 import { GitCommit } from "../utils/git"
-import { Mode, ModeConfig } from "./modes"
-import { ExperimentId } from "./experiments"
-import { CheckpointStorage } from "./checkpoints"
-import { TelemetrySetting } from "./TelemetrySetting"
-import type { GlobalSettings, ApiConfigMeta, ClineMessage, ClineAsk, ClineSay } from "../exports/roo-code"
+import { Mode } from "./modes"
 
-export type { ApiConfigMeta }
+export type { ApiConfigMeta, ToolProgressStatus }
 
 export interface LanguageModelChatSelector {
 	vendor?: string
@@ -261,8 +270,3 @@ export interface ClineApiReqInfo {
 }
 
 export type ClineApiReqCancelReason = "streaming_failed" | "user_cancelled"
-
-export type ToolProgressStatus = {
-	icon?: string
-	text?: string
-}

+ 1 - 1
src/shared/HistoryItem.ts

@@ -1,3 +1,3 @@
-import type { HistoryItem } from "../exports/roo-code"
+import type { HistoryItem } from "../schemas"
 
 export type { HistoryItem }

+ 1 - 1
src/shared/api.ts

@@ -1,4 +1,4 @@
-import { ModelInfo, ProviderName, ProviderSettings } from "../exports/roo-code"
+import { ModelInfo, ProviderName, ProviderSettings } from "../schemas"
 
 export type { ModelInfo, ProviderName as ApiProvider }
 

+ 1 - 2
src/shared/checkExistApiConfig.ts

@@ -1,5 +1,4 @@
-import { ProviderSettings } from "../exports/roo-code"
-import { SECRET_STATE_KEYS } from "./globalState"
+import { SECRET_STATE_KEYS, ProviderSettings } from "../schemas"
 
 export function checkExistKey(config: ProviderSettings | undefined) {
 	if (!config) {

+ 2 - 6
src/shared/checkpoints.ts

@@ -1,7 +1,3 @@
-import { CheckpointStorage } from "../exports/roo-code"
+import { CheckpointStorage, isCheckpointStorage } from "../schemas"
 
-export type { CheckpointStorage }
-
-export const isCheckpointStorage = (value: string): value is CheckpointStorage => {
-	return value === "task" || value === "workspace"
-}
+export { type CheckpointStorage, isCheckpointStorage }

+ 1 - 2
src/shared/experiments.ts

@@ -1,5 +1,4 @@
-import { ExperimentId } from "../exports/roo-code"
-
+import { ExperimentId } from "../schemas"
 import { AssertEqual, Equals, Keys, Values } from "../utils/type-fu"
 
 export type { ExperimentId }

+ 1 - 1
src/shared/getApiMetrics.ts

@@ -1,4 +1,4 @@
-import { TokenUsage } from "../exports/roo-code"
+import { TokenUsage } from "../schemas"
 
 import { ClineMessage } from "./ExtensionMessage"
 

+ 0 - 695
src/shared/globalState.ts

@@ -1,695 +0,0 @@
-import { z } from "zod"
-
-import type {
-	ProviderName,
-	CheckpointStorage,
-	ToolGroup,
-	Language,
-	TelemetrySetting,
-	ProviderSettingsKey,
-	SecretStateKey,
-	GlobalStateKey,
-	ModelInfo,
-	ApiConfigMeta,
-	HistoryItem,
-	GroupEntry,
-	ModeConfig,
-	ExperimentId,
-	ProviderSettings,
-	GlobalSettings,
-} from "../exports/roo-code"
-
-import { Keys, AssertEqual, Equals } from "../utils/type-fu"
-
-/**
- * ProviderName
- */
-
-const providerNames: Record<ProviderName, true> = {
-	anthropic: true,
-	glama: true,
-	openrouter: true,
-	bedrock: true,
-	vertex: true,
-	openai: true,
-	ollama: true,
-	lmstudio: true,
-	gemini: true,
-	"openai-native": true,
-	deepseek: true,
-	"vscode-lm": true,
-	mistral: true,
-	unbound: true,
-	requesty: true,
-	"human-relay": true,
-	"fake-ai": true,
-}
-
-const PROVIDER_NAMES = Object.keys(providerNames) as ProviderName[]
-
-const providerNamesEnum: [ProviderName, ...ProviderName[]] = [
-	PROVIDER_NAMES[0],
-	...PROVIDER_NAMES.slice(1).map((p) => p),
-]
-
-/**
- * CheckpointStorage
- */
-
-const checkpointStorages: Record<CheckpointStorage, true> = {
-	task: true,
-	workspace: true,
-}
-
-const CHECKPOINT_STORAGES = Object.keys(checkpointStorages) as CheckpointStorage[]
-
-const checkpointStoragesEnum: [CheckpointStorage, ...CheckpointStorage[]] = [
-	CHECKPOINT_STORAGES[0],
-	...CHECKPOINT_STORAGES.slice(1).map((p) => p),
-]
-
-/**
- * ToolGroup
- */
-
-const toolGroups: Record<ToolGroup, true> = {
-	read: true,
-	edit: true,
-	browser: true,
-	command: true,
-	mcp: true,
-	modes: true,
-}
-
-const TOOL_GROUPS = Object.keys(toolGroups) as ToolGroup[]
-
-const toolGroupsEnum: [ToolGroup, ...ToolGroup[]] = [TOOL_GROUPS[0], ...TOOL_GROUPS.slice(1).map((p) => p)]
-
-/**
- * Language
- */
-
-const languages: Record<Language, true> = {
-	ca: true,
-	de: true,
-	en: true,
-	es: true,
-	fr: true,
-	hi: true,
-	it: true,
-	ja: true,
-	ko: true,
-	pl: true,
-	"pt-BR": true,
-	tr: true,
-	vi: true,
-	"zh-CN": true,
-	"zh-TW": true,
-}
-
-const LANGUAGES = Object.keys(languages) as Language[]
-
-const languagesEnum: [Language, ...Language[]] = [LANGUAGES[0], ...LANGUAGES.slice(1).map((p) => p)]
-
-export const isLanguage = (key: string): key is Language => LANGUAGES.includes(key as Language)
-
-/**
- * TelemetrySetting
- */
-
-const telemetrySettings: Record<TelemetrySetting, true> = {
-	unset: true,
-	enabled: true,
-	disabled: true,
-}
-
-const TELEMETRY_SETTINGS = Object.keys(telemetrySettings) as TelemetrySetting[]
-
-const telemetrySettingsEnum: [TelemetrySetting, ...TelemetrySetting[]] = [
-	TELEMETRY_SETTINGS[0],
-	...TELEMETRY_SETTINGS.slice(1).map((p) => p),
-]
-
-/**
- * ProviderSettingsKey
- */
-
-const providerSettingsKeys: Record<ProviderSettingsKey, true> = {
-	apiProvider: true,
-	apiModelId: true,
-	// Anthropic
-	apiKey: true,
-	anthropicBaseUrl: true,
-	// Glama
-	glamaApiKey: true,
-	glamaModelId: true,
-	glamaModelInfo: true,
-	// OpenRouter
-	openRouterApiKey: true,
-	openRouterModelId: true,
-	openRouterModelInfo: true,
-	openRouterBaseUrl: true,
-	openRouterSpecificProvider: true,
-	openRouterUseMiddleOutTransform: true,
-	// AWS Bedrock
-	awsAccessKey: true,
-	awsSecretKey: true,
-	awsSessionToken: true,
-	awsRegion: true,
-	awsUseCrossRegionInference: true,
-	awsUsePromptCache: true,
-	awspromptCacheId: true,
-	awsProfile: true,
-	awsUseProfile: true,
-	awsCustomArn: true,
-	// Google Vertex
-	vertexKeyFile: true,
-	vertexJsonCredentials: true,
-	vertexProjectId: true,
-	vertexRegion: true,
-	// OpenAI
-	openAiApiKey: true,
-	openAiBaseUrl: true,
-	openAiR1FormatEnabled: true,
-	openAiModelId: true,
-	openAiCustomModelInfo: true,
-	openAiUseAzure: true,
-	azureApiVersion: true,
-	openAiStreamingEnabled: true,
-	// Ollama
-	ollamaModelId: true,
-	ollamaBaseUrl: true,
-	// VS Code LM
-	vsCodeLmModelSelector: true,
-	// LM Studio
-	lmStudioModelId: true,
-	lmStudioBaseUrl: true,
-	lmStudioDraftModelId: true,
-	lmStudioSpeculativeDecodingEnabled: true,
-	// Gemini
-	geminiApiKey: true,
-	googleGeminiBaseUrl: true,
-	// OpenAI Native
-	openAiNativeApiKey: true,
-	// Mistral
-	mistralApiKey: true,
-	mistralCodestralUrl: true,
-	// DeepSeek
-	deepSeekApiKey: true,
-	deepSeekBaseUrl: true,
-	includeMaxTokens: true,
-	// Unbound
-	unboundApiKey: true,
-	unboundModelId: true,
-	unboundModelInfo: true,
-	// Requesty
-	requestyApiKey: true,
-	requestyModelId: true,
-	requestyModelInfo: true,
-	// Claude 3.7 Sonnet Thinking
-	modelTemperature: true,
-	modelMaxTokens: true,
-	modelMaxThinkingTokens: true,
-	// Fake AI
-	fakeAi: true,
-}
-
-export const PROVIDER_SETTINGS_KEYS = Object.keys(providerSettingsKeys) as ProviderSettingsKey[]
-
-/**
- * SecretStateKey
- */
-
-const secretStateKeys: Record<SecretStateKey, true> = {
-	apiKey: true,
-	glamaApiKey: true,
-	openRouterApiKey: true,
-	awsAccessKey: true,
-	awsSecretKey: true,
-	awsSessionToken: true,
-	openAiApiKey: true,
-	geminiApiKey: true,
-	openAiNativeApiKey: true,
-	deepSeekApiKey: true,
-	mistralApiKey: true,
-	unboundApiKey: true,
-	requestyApiKey: true,
-}
-
-export const SECRET_STATE_KEYS = Object.keys(secretStateKeys) as SecretStateKey[]
-
-export const isSecretStateKey = (key: string): key is SecretStateKey =>
-	SECRET_STATE_KEYS.includes(key as SecretStateKey)
-
-/**
- * GlobalStateKey
- */
-
-const globalStateKeys: Record<GlobalStateKey, true> = {
-	apiProvider: true,
-	apiModelId: true,
-	// Anthropic
-	// apiKey: true,
-	anthropicBaseUrl: true,
-	// Glama
-	// glamaApiKey: true,
-	glamaModelId: true,
-	glamaModelInfo: true,
-	// OpenRouter
-	// openRouterApiKey: true,
-	openRouterModelId: true,
-	openRouterModelInfo: true,
-	openRouterBaseUrl: true,
-	openRouterSpecificProvider: true,
-	openRouterUseMiddleOutTransform: true,
-	// AWS Bedrock
-	// awsAccessKey: true,
-	// awsSecretKey: true,
-	// awsSessionToken: true,
-	awsRegion: true,
-	awsUseCrossRegionInference: true,
-	awsUsePromptCache: true,
-	awspromptCacheId: true,
-	awsProfile: true,
-	awsUseProfile: true,
-	awsCustomArn: true,
-	// Google Vertex
-	vertexKeyFile: true,
-	vertexJsonCredentials: true,
-	vertexProjectId: true,
-	vertexRegion: true,
-	// OpenAI
-	// openAiApiKey: true,
-	openAiBaseUrl: true,
-	openAiR1FormatEnabled: true,
-	openAiModelId: true,
-	openAiCustomModelInfo: true,
-	openAiUseAzure: true,
-	azureApiVersion: true,
-	openAiStreamingEnabled: true,
-	// Ollama
-	ollamaModelId: true,
-	ollamaBaseUrl: true,
-	// VS Code LM
-	vsCodeLmModelSelector: true,
-	// LM Studio
-	lmStudioModelId: true,
-	lmStudioBaseUrl: true,
-	lmStudioDraftModelId: true,
-	lmStudioSpeculativeDecodingEnabled: true,
-	// Gemini
-	// geminiApiKey: true,
-	googleGeminiBaseUrl: true,
-	// OpenAI Native
-	// openAiNativeApiKey: true,
-	// Mistral
-	// mistralApiKey: true,
-	mistralCodestralUrl: true,
-	// DeepSeek
-	// deepSeekApiKey: true,
-	deepSeekBaseUrl: true,
-	includeMaxTokens: true,
-	// Unbound
-	// unboundApiKey: true,
-	unboundModelId: true,
-	unboundModelInfo: true,
-	// Requesty
-	// requestyApiKey: true,
-	requestyModelId: true,
-	requestyModelInfo: true,
-	// Claude 3.7 Sonnet Thinking
-	modelTemperature: true,
-	modelMaxTokens: true,
-	modelMaxThinkingTokens: true,
-	// Fake AI
-	fakeAi: true,
-
-	currentApiConfigName: true,
-	listApiConfigMeta: true,
-	pinnedApiConfigs: true,
-
-	lastShownAnnouncementId: true,
-	customInstructions: true,
-	taskHistory: true,
-
-	autoApprovalEnabled: true,
-	alwaysAllowReadOnly: true,
-	alwaysAllowReadOnlyOutsideWorkspace: true,
-	alwaysAllowWrite: true,
-	alwaysAllowWriteOutsideWorkspace: true,
-	writeDelayMs: true,
-	alwaysAllowBrowser: true,
-	alwaysApproveResubmit: true,
-	requestDelaySeconds: true,
-	alwaysAllowMcp: true,
-	alwaysAllowModeSwitch: true,
-	alwaysAllowSubtasks: true,
-	alwaysAllowExecute: true,
-	allowedCommands: true,
-
-	browserToolEnabled: true,
-	browserViewportSize: true,
-	screenshotQuality: true,
-	remoteBrowserEnabled: true,
-	remoteBrowserHost: true,
-
-	enableCheckpoints: true,
-	checkpointStorage: true,
-
-	ttsEnabled: true,
-	ttsSpeed: true,
-	soundEnabled: true,
-	soundVolume: true,
-
-	maxOpenTabsContext: true,
-	maxWorkspaceFiles: true,
-	showRooIgnoredFiles: true,
-	maxReadFileLine: true,
-
-	terminalOutputLineLimit: true,
-	terminalShellIntegrationTimeout: true,
-
-	rateLimitSeconds: true,
-	diffEnabled: true,
-	fuzzyMatchThreshold: true,
-	experiments: true,
-
-	language: true,
-
-	telemetrySetting: true,
-
-	mcpEnabled: true,
-	enableMcpServerCreation: true,
-
-	mode: true,
-	modeApiConfigs: true,
-	customModes: true,
-	customModePrompts: true,
-	customSupportPrompts: true,
-	enhancementApiConfigId: true,
-}
-
-export const GLOBAL_STATE_KEYS = Object.keys(globalStateKeys) as GlobalStateKey[]
-
-/**
- * PassThroughStateKey
- *
- * TODO: Why is this necessary?
- */
-
-const PASS_THROUGH_STATE_KEYS = ["taskHistory"] as const
-
-type PassThroughStateKey = (typeof PASS_THROUGH_STATE_KEYS)[number]
-
-export const isPassThroughStateKey = (key: string): key is PassThroughStateKey =>
-	PASS_THROUGH_STATE_KEYS.includes(key as PassThroughStateKey)
-
-/**
- * Schemas
- */
-
-/**
- * ModelInfo
- */
-
-const modelInfoSchema = z.object({
-	maxTokens: z.number().optional(),
-	contextWindow: z.number(),
-	supportsImages: z.boolean().optional(),
-	supportsComputerUse: z.boolean().optional(),
-	supportsPromptCache: z.boolean(),
-	inputPrice: z.number().optional(),
-	outputPrice: z.number().optional(),
-	cacheWritesPrice: z.number().optional(),
-	cacheReadsPrice: z.number().optional(),
-	description: z.string().optional(),
-	reasoningEffort: z.enum(["low", "medium", "high"]).optional(),
-	thinking: z.boolean().optional(),
-})
-
-// Throws a type error if the inferred type of the modelInfoSchema is not equal
-// to ModelInfo.
-type _AssertModelInfo = AssertEqual<Equals<ModelInfo, z.infer<typeof modelInfoSchema>>>
-
-/**
- * ApiConfigMeta
- */
-
-const apiConfigMetaSchema = z.object({
-	id: z.string(),
-	name: z.string(),
-	apiProvider: z.enum(providerNamesEnum).optional(),
-})
-
-type _AssertApiConfigMeta = AssertEqual<Equals<ApiConfigMeta, z.infer<typeof apiConfigMetaSchema>>>
-
-/**
- * HistoryItem
- */
-
-const historyItemSchema = z.object({
-	id: z.string(),
-	number: z.number(),
-	ts: z.number(),
-	task: z.string(),
-	tokensIn: z.number(),
-	tokensOut: z.number(),
-	cacheWrites: z.number().optional(),
-	cacheReads: z.number().optional(),
-	totalCost: z.number(),
-	size: z.number().optional(),
-})
-
-type _AssertHistoryItem = AssertEqual<Equals<HistoryItem, z.infer<typeof historyItemSchema>>>
-
-/**
- * GroupEntry
- */
-
-const groupEntrySchema = z.union([
-	z.enum(toolGroupsEnum),
-	z
-		.tuple([
-			z.enum(toolGroupsEnum),
-			z.object({
-				fileRegex: z.string().optional(),
-				description: z.string().optional(),
-			}),
-		])
-		.readonly(),
-])
-
-type _AssertGroupEntry = AssertEqual<Equals<GroupEntry, z.infer<typeof groupEntrySchema>>>
-
-/**
- * ModeConfig
- */
-
-const modeConfigSchema = z.object({
-	slug: z.string(),
-	name: z.string(),
-	roleDefinition: z.string(),
-	customInstructions: z.string().optional(),
-	groups: z.array(groupEntrySchema).readonly(),
-	source: z.enum(["global", "project"]).optional(),
-})
-
-type _AssertModeConfig = AssertEqual<Equals<ModeConfig, z.infer<typeof modeConfigSchema>>>
-
-/**
- * ExperimentId
- */
-
-const experimentsSchema = z.object({
-	experimentalDiffStrategy: z.boolean(),
-	search_and_replace: z.boolean(),
-	insert_content: z.boolean(),
-	powerSteering: z.boolean(),
-	multi_search_and_replace: z.boolean(),
-})
-
-// Throws a type error if the inferred type of the experimentsSchema is not
-// equal to  ExperimentId.
-type _AssertExperiments = AssertEqual<Equals<ExperimentId, Keys<z.infer<typeof experimentsSchema>>>>
-
-/**
- * GlobalSettings
- */
-
-export const globalSettingsSchema = z.object({
-	currentApiConfigName: z.string().optional(),
-	listApiConfigMeta: z.array(apiConfigMetaSchema).optional(),
-	pinnedApiConfigs: z.record(z.string(), z.boolean()).optional(),
-
-	lastShownAnnouncementId: z.string().optional(),
-	customInstructions: z.string().optional(),
-	taskHistory: z.array(historyItemSchema).optional(),
-
-	autoApprovalEnabled: z.boolean().optional(),
-	alwaysAllowReadOnly: z.boolean().optional(),
-	alwaysAllowReadOnlyOutsideWorkspace: z.boolean().optional(),
-	alwaysAllowWrite: z.boolean().optional(),
-	alwaysAllowWriteOutsideWorkspace: z.boolean().optional(),
-	writeDelayMs: z.number().optional(),
-	alwaysAllowBrowser: z.boolean().optional(),
-	alwaysApproveResubmit: z.boolean().optional(),
-	requestDelaySeconds: z.number().optional(),
-	alwaysAllowMcp: z.boolean().optional(),
-	alwaysAllowModeSwitch: z.boolean().optional(),
-	alwaysAllowSubtasks: z.boolean().optional(),
-	alwaysAllowExecute: z.boolean().optional(),
-	allowedCommands: z.array(z.string()).optional(),
-
-	browserToolEnabled: z.boolean().optional(),
-	browserViewportSize: z.string().optional(),
-	screenshotQuality: z.number().optional(),
-	remoteBrowserEnabled: z.boolean().optional(),
-	remoteBrowserHost: z.string().optional(),
-
-	enableCheckpoints: z.boolean().optional(),
-	checkpointStorage: z.enum(checkpointStoragesEnum).optional(),
-
-	ttsEnabled: z.boolean().optional(),
-	ttsSpeed: z.number().optional(),
-	soundEnabled: z.boolean().optional(),
-	soundVolume: z.number().optional(),
-
-	maxOpenTabsContext: z.number().optional(),
-	maxWorkspaceFiles: z.number().optional(),
-	showRooIgnoredFiles: z.boolean().optional(),
-	maxReadFileLine: z.number().optional(),
-
-	terminalOutputLineLimit: z.number().optional(),
-	terminalShellIntegrationTimeout: z.number().optional(),
-
-	rateLimitSeconds: z.number().optional(),
-	diffEnabled: z.boolean().optional(),
-	fuzzyMatchThreshold: z.number().optional(),
-	experiments: experimentsSchema.optional(),
-
-	language: z.enum(languagesEnum).optional(),
-
-	telemetrySetting: z.enum(telemetrySettingsEnum).optional(),
-
-	mcpEnabled: z.boolean().optional(),
-	enableMcpServerCreation: z.boolean().optional(),
-
-	mode: z.string().optional(),
-	modeApiConfigs: z.record(z.string(), z.string()).optional(),
-	customModes: z.array(modeConfigSchema).optional(),
-	customModePrompts: z
-		.record(
-			z.string(),
-			z
-				.object({
-					roleDefinition: z.string().optional(),
-					customInstructions: z.string().optional(),
-				})
-				.optional(),
-		)
-		.optional(),
-	customSupportPrompts: z.record(z.string(), z.string().optional()).optional(),
-	enhancementApiConfigId: z.string().optional(),
-})
-
-// Throws a type error if the inferred type of the globalSettingsSchema is not
-// equal to GlobalSettings.
-type _AssertGlobalSettings = AssertEqual<Equals<GlobalSettings, z.infer<typeof globalSettingsSchema>>>
-
-/**
- * ProviderSettings
- */
-
-export const providerSettingsSchema = z.object({
-	apiProvider: z.enum(providerNamesEnum).optional(),
-	// Anthropic
-	apiModelId: z.string().optional(),
-	apiKey: z.string().optional(),
-	anthropicBaseUrl: z.string().optional(),
-	// Glama
-	glamaModelId: z.string().optional(),
-	glamaModelInfo: modelInfoSchema.optional(),
-	glamaApiKey: z.string().optional(),
-	// OpenRouter
-	openRouterApiKey: z.string().optional(),
-	openRouterModelId: z.string().optional(),
-	openRouterModelInfo: modelInfoSchema.optional(),
-	openRouterBaseUrl: z.string().optional(),
-	openRouterSpecificProvider: z.string().optional(),
-	// AWS Bedrock
-	awsAccessKey: z.string().optional(),
-	awsSecretKey: z.string().optional(),
-	awsSessionToken: z.string().optional(),
-	awsRegion: z.string().optional(),
-	awsUseCrossRegionInference: z.boolean().optional(),
-	awsUsePromptCache: z.boolean().optional(),
-	awspromptCacheId: z.string().optional(),
-	awsProfile: z.string().optional(),
-	awsUseProfile: z.boolean().optional(),
-	awsCustomArn: z.string().optional(),
-	// Google Vertex
-	vertexKeyFile: z.string().optional(),
-	vertexJsonCredentials: z.string().optional(),
-	vertexProjectId: z.string().optional(),
-	vertexRegion: z.string().optional(),
-	// OpenAI
-	openAiBaseUrl: z.string().optional(),
-	openAiApiKey: z.string().optional(),
-	openAiR1FormatEnabled: z.boolean().optional(),
-	openAiModelId: z.string().optional(),
-	openAiCustomModelInfo: modelInfoSchema.optional(),
-	openAiUseAzure: z.boolean().optional(),
-	// Ollama
-	ollamaModelId: z.string().optional(),
-	ollamaBaseUrl: z.string().optional(),
-	// VS Code LM
-	vsCodeLmModelSelector: z
-		.object({
-			vendor: z.string().optional(),
-			family: z.string().optional(),
-			version: z.string().optional(),
-			id: z.string().optional(),
-		})
-		.optional(),
-	// LM Studio
-	lmStudioModelId: z.string().optional(),
-	lmStudioBaseUrl: z.string().optional(),
-	lmStudioDraftModelId: z.string().optional(),
-	lmStudioSpeculativeDecodingEnabled: z.boolean().optional(),
-	// Gemini
-	geminiApiKey: z.string().optional(),
-	googleGeminiBaseUrl: z.string().optional(),
-	// OpenAI Native
-	openAiNativeApiKey: z.string().optional(),
-	// Mistral
-	mistralApiKey: z.string().optional(),
-	mistralCodestralUrl: z.string().optional(),
-	// Azure
-	azureApiVersion: z.string().optional(),
-	// OpenRouter
-	openRouterUseMiddleOutTransform: z.boolean().optional(),
-	openAiStreamingEnabled: z.boolean().optional(),
-	// DeepSeek
-	deepSeekBaseUrl: z.string().optional(),
-	deepSeekApiKey: z.string().optional(),
-	// Unbound
-	unboundApiKey: z.string().optional(),
-	unboundModelId: z.string().optional(),
-	unboundModelInfo: modelInfoSchema.optional(),
-	// Requesty
-	requestyApiKey: z.string().optional(),
-	requestyModelId: z.string().optional(),
-	requestyModelInfo: modelInfoSchema.optional(),
-	// Claude 3.7 Sonnet Thinking
-	modelTemperature: z.number().nullish(),
-	modelMaxTokens: z.number().optional(),
-	modelMaxThinkingTokens: z.number().optional(),
-	// Generic
-	includeMaxTokens: z.boolean().optional(),
-	// Fake AI
-	fakeAi: z.unknown().optional(),
-})
-
-// Throws a type error if the inferred type of the providerSettingsSchema is not
-// equal to ProviderSettings.
-type _AssertProviderSettings = AssertEqual<Equals<ProviderSettings, z.infer<typeof providerSettingsSchema>>>

+ 2 - 3
src/shared/language.ts

@@ -1,7 +1,6 @@
-import { type Language } from "../exports/roo-code"
-import { isLanguage } from "./globalState"
+import { type Language, isLanguage } from "../schemas"
 
-export type { Language }
+export { type Language, isLanguage }
 
 /**
  * Language name mapping from ISO codes to full language names

+ 1 - 1
src/shared/modes.ts

@@ -1,6 +1,6 @@
 import * as vscode from "vscode"
 
-import { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts } from "../exports/roo-code"
+import { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts } from "../schemas"
 import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tool-groups"
 import { addCustomInstructions } from "../core/prompts/sections/custom-instructions"
 

+ 1 - 1
src/shared/tool-groups.ts

@@ -1,4 +1,4 @@
-import type { ToolGroup } from "../exports/roo-code"
+import type { ToolGroup } from "../schemas"
 
 // Define tool group configuration
 export type ToolGroupConfig = {