@mastra/code-sdk 1.1.3 → 1.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @mastra/code-sdk
2
2
 
3
+ ## 1.2.0-alpha.1
4
+
5
+ ### Minor Changes
6
+
7
+ - Added MCP disable-state controls to the MCP manager. Servers can be disabled for the current project or for every project, the state persists across runs in an app-data `mcp-state.json` (user MCP config files are never mutated), and disabled servers stay visible in statuses via the new `disabled`/`disabledScope` fields on `McpServerStatus`. ([#20834](https://github.com/mastra-ai/mastra/pull/20834))
8
+
9
+ ```ts
10
+ await mcpManager.setServerDisabled('filesystem', true); // project scope
11
+ await mcpManager.setServerDisabled('filesystem', true, { global: true }); // all projects
12
+ await mcpManager.setAllDisabled(true, { global: true }); // global kill switch
13
+ mcpManager.isAllDisabledGlobally();
14
+ mcpManager.getDisabledServers();
15
+ ```
16
+
17
+ ### Patch Changes
18
+
19
+ - dependencies updates: ([#19783](https://github.com/mastra-ai/mastra/pull/19783))
20
+ - Updated dependency [`posthog-node@^5.46.1` ↗︎](https://www.npmjs.com/package/posthog-node/v/5.46.1) (from `^5.37.0`, in `dependencies`)
21
+
22
+ - dependencies updates: ([#20406](https://github.com/mastra-ai/mastra/pull/20406))
23
+ - Updated dependency [`@aws-sdk/credential-providers@^3.1095.0` ↗︎](https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.1095.0) (from `^3.864.0`, in `dependencies`)
24
+
25
+ - Fixed custom provider models saved with a stray `mastracode/` prefix in settings, which broke selecting and using them after choosing them from `/models` (#20799) ([#20804](https://github.com/mastra-ai/mastra/pull/20804))
26
+
27
+ - Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`f5a17d9`](https://github.com/mastra-ai/mastra/commit/f5a17d95c19e7d4149996932bd8d1905089f031d), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`8627c23`](https://github.com/mastra-ai/mastra/commit/8627c23d794485fb97d533fc2a7a8323bfec2225), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`26ff3b9`](https://github.com/mastra-ai/mastra/commit/26ff3b9144132bd8570e4796d436fb57a9a2bf24), [`3ff2be3`](https://github.com/mastra-ai/mastra/commit/3ff2be3a5a579d2e2d7084ba0624ec24faadce4d), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`c71e307`](https://github.com/mastra-ai/mastra/commit/c71e3077e69eae3f25aa628e3778f153a9d6ab36), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`a4f6806`](https://github.com/mastra-ai/mastra/commit/a4f68065d082af57770e7ee3d34996fdc914dbd1), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`ffdfa25`](https://github.com/mastra-ai/mastra/commit/ffdfa25b5cdf3ecfd0c5a2e96363c3ba50995ce9), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`d6c63e4`](https://github.com/mastra-ai/mastra/commit/d6c63e4b757babb95a735d0e421d4dac67c1dcf1), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`e4d3761`](https://github.com/mastra-ai/mastra/commit/e4d376143cf3322885a7e6e4048e536ce441f785), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
28
+ - @mastra/core@1.58.0-alpha.1
29
+ - @mastra/libsql@1.20.0-alpha.0
30
+ - @mastra/pg@1.20.0-alpha.0
31
+ - @mastra/schema-compat@1.3.6-alpha.0
32
+ - @mastra/observability@1.16.6-alpha.0
33
+ - @mastra/mcp@1.16.0-alpha.0
34
+ - @mastra/memory@1.26.1-alpha.0
35
+ - @mastra/duckdb@1.6.1-alpha.0
36
+
37
+ ## 1.1.4-alpha.0
38
+
39
+ ### Patch Changes
40
+
41
+ - Updated dependencies [[`45a9147`](https://github.com/mastra-ai/mastra/commit/45a914741f578754d79d8b7de7b4e4f304d8e14a), [`990611b`](https://github.com/mastra-ai/mastra/commit/990611ba76eb876d86c9c594371ae5f02f94b432), [`ed5d606`](https://github.com/mastra-ai/mastra/commit/ed5d606739c5e3fbdfa9f272df7809aa5ab43b1d)]:
42
+ - @mastra/core@1.58.0-alpha.0
43
+
3
44
  ## 1.1.3
4
45
 
5
46
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agents/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,EAGL,iBAAiB,EAGlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,6BAA6B,EAC7B,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAa1C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAE5F;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,2BAA2B,6DAIxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,aAAa,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,cAAc,CAAA;CAAE,GACzG,oBAAoB,CAwEtB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,GAAG,aAAa,CAWrG;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,GAAG,SAAS,CAI3B"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agents/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,EAGL,iBAAiB,EAGlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,6BAA6B,EAC7B,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAa1C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAE5F;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,2BAA2B,6DAIxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,aAAa,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,cAAc,CAAA;CAAE,GACzG,oBAAoB,CA+EtB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,GAAG,aAAa,CAWrG;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,GAAG,SAAS,CAI3B"}
@@ -1,4 +1,4 @@
1
- import { loadSettings } from "../onboarding/settings.js";
1
+ import { loadSettings, stripMastraCodeCustomProviderPrefix } from "../onboarding/settings.js";
2
2
  import { hasCredentialStoreProvider, resolveCredentialStore, resolveTenantFromRequestContext, setCredentialStoreProvider } from "./credential-resolver.js";
3
3
  import { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from "../providers/amazon-bedrock-gateway.js";
4
4
  import { hasCustomProvidersSource, resolveCustomProviders, setCustomProvidersSource } from "./custom-provider-source.js";
@@ -40,7 +40,9 @@ function resolveModel(modelId, options) {
40
40
  const headers = getAgentControllerHeaders(options?.requestContext);
41
41
  const settings = loadSettings();
42
42
  const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;
43
- const normalizedInput = modelId.startsWith(bedrockLegacyPrefix) ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1) : modelId;
43
+ const bedrockNormalizedInput = modelId.startsWith(bedrockLegacyPrefix) ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1) : modelId;
44
+ const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;
45
+ const normalizedInput = stripMastraCodeCustomProviderPrefix(bedrockNormalizedInput, customProviders);
44
46
  const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);
45
47
  const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);
46
48
  const [providerId, ...modelParts] = normalizedModelId.split("/");
@@ -66,7 +68,6 @@ function resolveModel(modelId, options) {
66
68
  const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();
67
69
  const rawGatewayBase = settings.memoryGateway?.baseUrl ?? process.env["MASTRA_GATEWAY_URL"] ?? "https://gateway-api.mastra.ai";
68
70
  const credentialStore = resolveCredentialStore(options?.requestContext);
69
- const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;
70
71
  const gateway = createMastraCodeGateway({
71
72
  mastraGatewayBaseUrl: rawGatewayBase.replace(/\/+$/, "").replace(/\/v1$/, ""),
72
73
  mastraGatewayApiKey: mgApiKey,
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","names":[],"sources":["../../src/agents/model.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { loadSettings } from '../onboarding/settings.js';\nimport { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from '../providers/amazon-bedrock-gateway.js';\nimport type { ThinkingLevel } from '../providers/openai-codex.js';\nimport { resolveCredentialStore } from './credential-resolver.js';\nimport { resolveCustomProviders } from './custom-provider-source.js';\nimport {\n MASTRA_GATEWAY_PREFIX,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n reloadAuthStorage,\n stripMastraGatewayPrefix,\n} from './mastracode-gateway.js';\nimport type { MastraCodeGatewayOptions } from './mastracode-gateway.js';\n\nexport {\n getAnthropicApiKey,\n getOpenAIApiKey,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n remapOpenAIModelForCodexOAuth,\n resolveAuth,\n} from './mastracode-gateway.js';\nexport type { MastraCodeCustomProvider, MastraCodeGatewayOptions } from './mastracode-gateway.js';\nexport {\n setCredentialStoreProvider,\n hasCredentialStoreProvider,\n resolveTenantFromRequestContext,\n} from './credential-resolver.js';\nexport type { CredentialTenant, CredentialStoreProvider } from './credential-resolver.js';\nexport {\n setCustomProvidersSource,\n hasCustomProvidersSource,\n resolveCustomProviders,\n} from './custom-provider-source.js';\nexport type { CustomProvidersSource } from './custom-provider-source.js';\n\ntype ResolvedModel = GatewayLanguageModel;\ntype ModelRequestHeaders = Record<string, string>;\n\nfunction getAgentControllerHeaders(requestContext?: RequestContext): ModelRequestHeaders | undefined {\n const agentControllerContext = requestContext?.get('controller') as AgentControllerRequestContext<any> | undefined;\n const headers = {\n ...(agentControllerContext?.threadId ? { 'x-thread-id': agentControllerContext.threadId } : {}),\n ...(agentControllerContext?.resourceId ? { 'x-resource-id': agentControllerContext.resourceId } : {}),\n };\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nexport function createMastraCodeGateway(options: MastraCodeGatewayOptions): MastraCodeGateway {\n return new MastraCodeGateway(options);\n}\n\nexport function createMastraCodeModelCatalogProvider(gateway: MastraModelGatewayInterface) {\n return gateway instanceof MastraCodeGateway\n ? gateway.createModelCatalogProvider()\n : MastraCodeGateway.createModelCatalogProvider(gateway);\n}\n\n/**\n * Placeholder for future model ID normalization.\n * Currently returns the input unchanged, but exists as a seam\n * for aliasing, casing fixes, or validation in the future.\n */\nexport function resolveModelId(modelId: string): string {\n return modelId;\n}\n\n/**\n * Resolve a model ID to the correct provider instance.\n * Shared by the main agent, observer, and reflector.\n *\n * - For anthropic/* models: Uses stored OAuth credentials when present, otherwise direct API key\n * - For openai/* models: Uses OAuth when configured, otherwise direct API key from AuthStorage\n * - For moonshotai/* models: Uses Moonshot AI Anthropic-compatible endpoint\n * - For all other providers: Uses Mastra's model router (models.dev gateway)\n */\nexport function resolveModel(\n modelId: string,\n options?: { thinkingLevel?: ThinkingLevel; remapForCodexOAuth?: boolean; requestContext?: RequestContext },\n): GatewayLanguageModel {\n reloadAuthStorage();\n const headers = getAgentControllerHeaders(options?.requestContext);\n const settings = loadSettings();\n // Bedrock was previously cataloged under the MastraCode gateway namespace\n // (`mastracode/amazon-bedrock/<model>`). Normalize any legacy saved ids to the\n // standalone `amazon-bedrock/<model>` form so they resolve through the\n // dedicated Bedrock gateway.\n const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;\n const normalizedInput = modelId.startsWith(bedrockLegacyPrefix)\n ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1)\n : modelId;\n const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);\n const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);\n const [providerId, ...modelParts] = normalizedModelId.split('/');\n const bareModelId = modelParts.join('/');\n if (!providerId || !bareModelId) {\n throw new Error(`Invalid model id: ${modelId}`);\n }\n\n if (providerId === AMAZON_BEDROCK_GATEWAY_ID) {\n const bedrockGateway = createAmazonBedrockGateway();\n const routerId = `${AMAZON_BEDROCK_GATEWAY_ID}/${bareModelId}`;\n const auth = bedrockGateway.resolveAuth({\n gatewayId: AMAZON_BEDROCK_GATEWAY_ID,\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n routerId,\n });\n return bedrockGateway.resolveLanguageModel({\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n }\n\n const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;\n\n const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();\n const rawGatewayBase =\n settings.memoryGateway?.baseUrl ?? process.env['MASTRA_GATEWAY_URL'] ?? 'https://gateway-api.mastra.ai';\n // Deployed web registers a per-tenant credential store provider; when the\n // request carries an authenticated tenant, resolve credentials through the\n // caller's own store (user > org > env). Undefined = global AuthStorage.\n const credentialStore = resolveCredentialStore(options?.requestContext);\n // Deployed web registers a custom providers source (DB-backed, tenant\n // scoped); when registered it is authoritative and settings.json custom\n // providers are ignored. Undefined = local settings-based behavior.\n const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;\n const gateway = createMastraCodeGateway({\n mastraGatewayBaseUrl: rawGatewayBase.replace(/\\/+$/, '').replace(/\\/v1$/, ''),\n mastraGatewayApiKey: mgApiKey,\n routeThroughMastraGateway: Boolean(mgApiKey && isMastraGatewayModel),\n thinkingLevel: options?.thinkingLevel,\n customProviders,\n credentialStore,\n });\n\n const auth = gateway.resolveAuth({\n gatewayId: MASTRACODE_GATEWAY_ID,\n providerId,\n modelId: bareModelId,\n routerId,\n });\n\n return gateway.resolveLanguageModel({\n providerId,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? mgApiKey ?? '',\n headers,\n });\n}\n\n/**\n * Dynamic model function that reads the current model from controller state.\n * This allows runtime model switching via the /models picker.\n */\nexport function getDynamicModel({ requestContext }: { requestContext: RequestContext }): ResolvedModel {\n const agentControllerContext = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n\n const modelId = agentControllerContext?.session?.modelId;\n if (!modelId) {\n throw new Error('No model selected. Use /models to select a model first.');\n }\n\n const thinkingLevel = agentControllerContext?.state?.thinkingLevel as ThinkingLevel | undefined;\n\n return resolveModel(modelId, { thinkingLevel, remapForCodexOAuth: true, requestContext });\n}\n\n/**\n * Goal judge model resolver for the agent's `goal.judge` config. Resolves the\n * configured goal judge model through mastracode's gateway so provider\n * credentials (stored in auth storage, not just env) are injected — a bare model\n * id handed to core's default model router would fail to find the API key.\n *\n * Returns `undefined` when no judge model is configured, which keeps the goal\n * step a complete no-op (the goal mechanism requires a judge to do anything).\n *\n * `settingsPath` must be the same source `createMastraCode()` reads from so the\n * judge model and the goal budget (`goalMaxTurns`) come from one config — with a\n * custom `settingsPath` a bare `loadSettings()` here could read a different file\n * and silently turn the goal step into a no-op.\n */\nexport function getGoalJudgeModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | undefined {\n const judgeModelId = loadSettings(settingsPath).models.goalJudgeModel;\n if (!judgeModelId) return undefined;\n return resolveModel(judgeModelId, { remapForCodexOAuth: true, requestContext });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model.js","names":[],"sources":["../../src/agents/model.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { loadSettings, stripMastraCodeCustomProviderPrefix } from '../onboarding/settings.js';\nimport { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from '../providers/amazon-bedrock-gateway.js';\nimport type { ThinkingLevel } from '../providers/openai-codex.js';\nimport { resolveCredentialStore } from './credential-resolver.js';\nimport { resolveCustomProviders } from './custom-provider-source.js';\nimport {\n MASTRA_GATEWAY_PREFIX,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n reloadAuthStorage,\n stripMastraGatewayPrefix,\n} from './mastracode-gateway.js';\nimport type { MastraCodeGatewayOptions } from './mastracode-gateway.js';\n\nexport {\n getAnthropicApiKey,\n getOpenAIApiKey,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n remapOpenAIModelForCodexOAuth,\n resolveAuth,\n} from './mastracode-gateway.js';\nexport type { MastraCodeCustomProvider, MastraCodeGatewayOptions } from './mastracode-gateway.js';\nexport {\n setCredentialStoreProvider,\n hasCredentialStoreProvider,\n resolveTenantFromRequestContext,\n} from './credential-resolver.js';\nexport type { CredentialTenant, CredentialStoreProvider } from './credential-resolver.js';\nexport {\n setCustomProvidersSource,\n hasCustomProvidersSource,\n resolveCustomProviders,\n} from './custom-provider-source.js';\nexport type { CustomProvidersSource } from './custom-provider-source.js';\n\ntype ResolvedModel = GatewayLanguageModel;\ntype ModelRequestHeaders = Record<string, string>;\n\nfunction getAgentControllerHeaders(requestContext?: RequestContext): ModelRequestHeaders | undefined {\n const agentControllerContext = requestContext?.get('controller') as AgentControllerRequestContext<any> | undefined;\n const headers = {\n ...(agentControllerContext?.threadId ? { 'x-thread-id': agentControllerContext.threadId } : {}),\n ...(agentControllerContext?.resourceId ? { 'x-resource-id': agentControllerContext.resourceId } : {}),\n };\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nexport function createMastraCodeGateway(options: MastraCodeGatewayOptions): MastraCodeGateway {\n return new MastraCodeGateway(options);\n}\n\nexport function createMastraCodeModelCatalogProvider(gateway: MastraModelGatewayInterface) {\n return gateway instanceof MastraCodeGateway\n ? gateway.createModelCatalogProvider()\n : MastraCodeGateway.createModelCatalogProvider(gateway);\n}\n\n/**\n * Placeholder for future model ID normalization.\n * Currently returns the input unchanged, but exists as a seam\n * for aliasing, casing fixes, or validation in the future.\n */\nexport function resolveModelId(modelId: string): string {\n return modelId;\n}\n\n/**\n * Resolve a model ID to the correct provider instance.\n * Shared by the main agent, observer, and reflector.\n *\n * - For anthropic/* models: Uses stored OAuth credentials when present, otherwise direct API key\n * - For openai/* models: Uses OAuth when configured, otherwise direct API key from AuthStorage\n * - For moonshotai/* models: Uses Moonshot AI Anthropic-compatible endpoint\n * - For all other providers: Uses Mastra's model router (models.dev gateway)\n */\nexport function resolveModel(\n modelId: string,\n options?: { thinkingLevel?: ThinkingLevel; remapForCodexOAuth?: boolean; requestContext?: RequestContext },\n): GatewayLanguageModel {\n reloadAuthStorage();\n const headers = getAgentControllerHeaders(options?.requestContext);\n const settings = loadSettings();\n // Bedrock was previously cataloged under the MastraCode gateway namespace\n // (`mastracode/amazon-bedrock/<model>`). Normalize any legacy saved ids to the\n // standalone `amazon-bedrock/<model>` form so they resolve through the\n // dedicated Bedrock gateway.\n const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;\n const bedrockNormalizedInput = modelId.startsWith(bedrockLegacyPrefix)\n ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1)\n : modelId;\n // Deployed web registers a custom providers source (DB-backed, tenant\n // scoped); when registered it is authoritative and settings.json custom\n // providers are ignored. Undefined = local settings-based behavior.\n const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;\n // Ids selected from the shared /models catalog were previously persisted in\n // the gateway-qualified `mastracode/<customProviderId>/<model>` form, which\n // parses the provider as `mastracode` and breaks provider config lookup.\n // Normalize at resolution time (in addition to stripping at selection time)\n // so already-saved ids and any surface that persists the raw catalog id\n // still resolve to the custom provider.\n const normalizedInput = stripMastraCodeCustomProviderPrefix(bedrockNormalizedInput, customProviders);\n const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);\n const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);\n const [providerId, ...modelParts] = normalizedModelId.split('/');\n const bareModelId = modelParts.join('/');\n if (!providerId || !bareModelId) {\n throw new Error(`Invalid model id: ${modelId}`);\n }\n\n if (providerId === AMAZON_BEDROCK_GATEWAY_ID) {\n const bedrockGateway = createAmazonBedrockGateway();\n const routerId = `${AMAZON_BEDROCK_GATEWAY_ID}/${bareModelId}`;\n const auth = bedrockGateway.resolveAuth({\n gatewayId: AMAZON_BEDROCK_GATEWAY_ID,\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n routerId,\n });\n return bedrockGateway.resolveLanguageModel({\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n }\n\n const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;\n\n const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();\n const rawGatewayBase =\n settings.memoryGateway?.baseUrl ?? process.env['MASTRA_GATEWAY_URL'] ?? 'https://gateway-api.mastra.ai';\n // Deployed web registers a per-tenant credential store provider; when the\n // request carries an authenticated tenant, resolve credentials through the\n // caller's own store (user > org > env). Undefined = global AuthStorage.\n const credentialStore = resolveCredentialStore(options?.requestContext);\n const gateway = createMastraCodeGateway({\n mastraGatewayBaseUrl: rawGatewayBase.replace(/\\/+$/, '').replace(/\\/v1$/, ''),\n mastraGatewayApiKey: mgApiKey,\n routeThroughMastraGateway: Boolean(mgApiKey && isMastraGatewayModel),\n thinkingLevel: options?.thinkingLevel,\n customProviders,\n credentialStore,\n });\n\n const auth = gateway.resolveAuth({\n gatewayId: MASTRACODE_GATEWAY_ID,\n providerId,\n modelId: bareModelId,\n routerId,\n });\n\n return gateway.resolveLanguageModel({\n providerId,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? mgApiKey ?? '',\n headers,\n });\n}\n\n/**\n * Dynamic model function that reads the current model from controller state.\n * This allows runtime model switching via the /models picker.\n */\nexport function getDynamicModel({ requestContext }: { requestContext: RequestContext }): ResolvedModel {\n const agentControllerContext = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n\n const modelId = agentControllerContext?.session?.modelId;\n if (!modelId) {\n throw new Error('No model selected. Use /models to select a model first.');\n }\n\n const thinkingLevel = agentControllerContext?.state?.thinkingLevel as ThinkingLevel | undefined;\n\n return resolveModel(modelId, { thinkingLevel, remapForCodexOAuth: true, requestContext });\n}\n\n/**\n * Goal judge model resolver for the agent's `goal.judge` config. Resolves the\n * configured goal judge model through mastracode's gateway so provider\n * credentials (stored in auth storage, not just env) are injected — a bare model\n * id handed to core's default model router would fail to find the API key.\n *\n * Returns `undefined` when no judge model is configured, which keeps the goal\n * step a complete no-op (the goal mechanism requires a judge to do anything).\n *\n * `settingsPath` must be the same source `createMastraCode()` reads from so the\n * judge model and the goal budget (`goalMaxTurns`) come from one config — with a\n * custom `settingsPath` a bare `loadSettings()` here could read a different file\n * and silently turn the goal step into a no-op.\n */\nexport function getGoalJudgeModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | undefined {\n const judgeModelId = loadSettings(settingsPath).models.goalJudgeModel;\n if (!judgeModelId) return undefined;\n return resolveModel(judgeModelId, { remapForCodexOAuth: true, requestContext });\n}\n"],"mappings":"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"}
@@ -42,6 +42,33 @@ export interface McpManager {
42
42
  * so it can be retried. Returns `true` if a flow was cancelled.
43
43
  */
44
44
  cancelServerAuthentication(name: string): Promise<boolean>;
45
+ /**
46
+ * Disable or enable a single server by name. The change is persisted (in
47
+ * mastracode's app data, not the user's config files) and survives restarts.
48
+ * With `global: true` the change applies to every project; otherwise it is
49
+ * scoped to this project. Enabling only removes the server from the given
50
+ * scope — a server disabled in the other scope stays disabled, and the
51
+ * returned status's `disabledScope` says which scope still applies.
52
+ * Connections are rebuilt, so other servers reconnect — same behavior as
53
+ * {@link reload}. Returns the server's resulting status.
54
+ */
55
+ setServerDisabled(name: string, disabled: boolean, options?: {
56
+ global?: boolean;
57
+ }): Promise<McpServerStatus>;
58
+ /**
59
+ * Disable or enable all servers at once. Project scope records every
60
+ * currently-configured server name; enabling clears the project list.
61
+ * Global scope sets/clears a persisted all-MCP kill switch (and, when
62
+ * enabling, also clears globally disabled server names). Persisted like
63
+ * {@link setServerDisabled}.
64
+ */
65
+ setAllDisabled(disabled: boolean, options?: {
66
+ global?: boolean;
67
+ }): Promise<void>;
68
+ /** Names of configured servers that are currently disabled (any scope). */
69
+ getDisabledServers(): string[];
70
+ /** Whether all MCP is disabled globally (across every project). */
71
+ isAllDisabledGlobally(): boolean;
45
72
  /** Disconnect from all MCP servers and clean up. */
46
73
  disconnect(): Promise<void>;
47
74
  /** Get all tools from connected MCP servers (namespaced as serverName_toolName). */
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/mcp/manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,OAAO,KAAK,EACV,SAAS,EAGT,eAAe,EACf,eAAe,EACf,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAIpB,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,2FAA2F;IAC3F,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,kEAAkE;IAClE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,iEAAiE;IACjE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACxD;;;;;;;;;;OAUG;IACH,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3E,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5B;;;;;OAKG;IACH,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,oDAAoD;IACpD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,oFAAoF;IACpF,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,4DAA4D;IAC5D,UAAU,IAAI,OAAO,CAAC;IACtB,iCAAiC;IACjC,iBAAiB,IAAI,eAAe,EAAE,CAAC;IACvC,2DAA2D;IAC3D,iBAAiB,IAAI,gBAAgB,EAAE,CAAC;IACxC,yCAAyC;IACzC,cAAc,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,6BAA6B;IAC7B,SAAS,IAAI,SAAS,CAAC;IACvB,6CAA6C;IAC7C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACvC;AA0ED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,aAAa,SAAqB,EAClC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC7C,UAAU,CAgiBZ"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/mcp/manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiBH,OAAO,KAAK,EACV,SAAS,EAGT,eAAe,EACf,eAAe,EACf,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAIpB,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,2FAA2F;IAC3F,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,kEAAkE;IAClE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,iEAAiE;IACjE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACxD;;;;;;;;;;OAUG;IACH,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3E,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5B;;;;;OAKG;IACH,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D;;;;;;;;;OASG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7G;;;;;;OAMG;IACH,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,2EAA2E;IAC3E,kBAAkB,IAAI,MAAM,EAAE,CAAC;IAC/B,mEAAmE;IACnE,qBAAqB,IAAI,OAAO,CAAC;IACjC,oDAAoD;IACpD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,oFAAoF;IACpF,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,4DAA4D;IAC5D,UAAU,IAAI,OAAO,CAAC;IACtB,iCAAiC;IACjC,iBAAiB,IAAI,eAAe,EAAE,CAAC;IACvC,2DAA2D;IAC3D,iBAAiB,IAAI,gBAAgB,EAAE,CAAC;IACxC,yCAAyC;IACzC,cAAc,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,6BAA6B;IAC7B,SAAS,IAAI,SAAS,CAAC;IACvB,6CAA6C;IAC7C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACvC;AA0ED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,aAAa,SAAqB,EAClC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC7C,UAAU,CA0sBZ"}
@@ -1,6 +1,7 @@
1
1
  import { DEFAULT_CONFIG_DIR } from "../constants.js";
2
2
  import { getAppDataDir } from "../utils/project.js";
3
3
  import { DEFAULT_OAUTH_REDIRECT_URL, getClaudeSettingsPath, getGlobalMcpPath, getProjectMcpPath, loadMcpConfig, resolveOAuthRedirectUrl } from "./config.js";
4
+ import { loadDisabledServers, loadGlobalDisableState, saveDisabledServers, saveGlobalDisableState } from "./state.js";
4
5
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
5
6
  import { dirname, join } from "path";
6
7
  import { MCPClient, MCPOAuthClientProvider } from "@mastra/mcp";
@@ -94,6 +95,16 @@ function createMcpManager(projectDir, configDirName = DEFAULT_CONFIG_DIR, extraS
94
95
  };
95
96
  };
96
97
  let config = applyExtraServers(loadMcpConfig(projectDir, configDirName));
98
+ let disabledServers = new Set(loadDisabledServers(projectDir));
99
+ let globalDisableState = loadGlobalDisableState();
100
+ let globallyDisabledServers = new Set(globalDisableState.disabledServers);
101
+ /** Whether a server is disabled in any scope (global kill switch, global list, or project list). */
102
+ const isDisabled = (name) => globalDisableState.allDisabled || globallyDisabledServers.has(name) || disabledServers.has(name);
103
+ /** Which scope disables a server. Global takes precedence — project-level enable can't undo it. */
104
+ const disabledScopeOf = (name) => {
105
+ if (globalDisableState.allDisabled || globallyDisabledServers.has(name)) return "global";
106
+ if (disabledServers.has(name)) return "project";
107
+ };
97
108
  let client = null;
98
109
  let serverDefs = {};
99
110
  let tools = {};
@@ -187,9 +198,26 @@ function createMcpManager(projectDir, configDirName = DEFAULT_CONFIG_DIR, extraS
187
198
  };
188
199
  return defs;
189
200
  }
201
+ /** Seed a `disabled` status for every disabled server so it stays visible. */
202
+ function setDisabledStatuses() {
203
+ for (const [name, cfg] of Object.entries(config.mcpServers ?? {})) {
204
+ const scope = disabledScopeOf(name);
205
+ if (!scope) continue;
206
+ serverStatuses.set(name, {
207
+ name,
208
+ connected: false,
209
+ toolCount: 0,
210
+ toolNames: [],
211
+ transport: getTransport(cfg),
212
+ disabled: true,
213
+ disabledScope: scope
214
+ });
215
+ }
216
+ }
190
217
  async function connectAndCollectTools() {
191
- const servers = config.mcpServers;
192
- if (!servers || Object.keys(servers).length === 0) return;
218
+ setDisabledStatuses();
219
+ const servers = Object.fromEntries(Object.entries(config.mcpServers ?? {}).filter(([name]) => !isDisabled(name)));
220
+ if (Object.keys(servers).length === 0) return;
193
221
  const serverNames = Object.keys(servers);
194
222
  for (const name of serverNames) serverStatuses.set(name, {
195
223
  name,
@@ -343,6 +371,48 @@ function createMcpManager(projectDir, configDirName = DEFAULT_CONFIG_DIR, extraS
343
371
  client = null;
344
372
  }
345
373
  }
374
+ /** Tear down all connections and reconnect every enabled server. */
375
+ async function rebuildConnections() {
376
+ await disconnect();
377
+ tools = {};
378
+ serverStatuses = /* @__PURE__ */ new Map();
379
+ stderrLogs = /* @__PURE__ */ new Map();
380
+ initialized = false;
381
+ await connectAndCollectTools();
382
+ initialized = true;
383
+ }
384
+ function disabledStatus(name) {
385
+ const cfg = config.mcpServers?.[name];
386
+ return {
387
+ name,
388
+ connected: false,
389
+ toolCount: 0,
390
+ toolNames: [],
391
+ transport: cfg ? getTransport(cfg) : "stdio",
392
+ disabled: true,
393
+ disabledScope: disabledScopeOf(name)
394
+ };
395
+ }
396
+ function persistProjectDelta(mutate) {
397
+ const fresh = new Set(loadDisabledServers(projectDir));
398
+ mutate(fresh);
399
+ disabledServers = fresh;
400
+ saveDisabledServers(projectDir, Array.from(fresh));
401
+ }
402
+ function persistGlobalDelta(mutate) {
403
+ const onDisk = loadGlobalDisableState();
404
+ const fresh = {
405
+ allDisabled: onDisk.allDisabled,
406
+ disabledServers: new Set(onDisk.disabledServers)
407
+ };
408
+ mutate(fresh);
409
+ globallyDisabledServers = fresh.disabledServers;
410
+ globalDisableState = {
411
+ allDisabled: fresh.allDisabled,
412
+ disabledServers: Array.from(fresh.disabledServers)
413
+ };
414
+ saveGlobalDisableState(globalDisableState);
415
+ }
346
416
  return {
347
417
  async init() {
348
418
  if (initialized) return;
@@ -355,22 +425,66 @@ function createMcpManager(projectDir, configDirName = DEFAULT_CONFIG_DIR, extraS
355
425
  const connected = statuses.filter((s) => s.connected);
356
426
  return {
357
427
  connected,
358
- failed: statuses.filter((s) => !s.connected),
428
+ failed: statuses.filter((s) => !s.connected && !s.disabled),
359
429
  skipped: [...config.skippedServers ?? []],
360
430
  totalTools: connected.reduce((sum, s) => sum + s.toolCount, 0)
361
431
  };
362
432
  },
363
433
  async reload() {
364
- await disconnect();
365
434
  config = applyExtraServers(loadMcpConfig(projectDir, configDirName));
366
- tools = {};
367
- serverStatuses = /* @__PURE__ */ new Map();
368
- stderrLogs = /* @__PURE__ */ new Map();
369
- initialized = false;
370
- await connectAndCollectTools();
371
- initialized = true;
435
+ disabledServers = new Set(loadDisabledServers(projectDir));
436
+ globalDisableState = loadGlobalDisableState();
437
+ globallyDisabledServers = new Set(globalDisableState.disabledServers);
438
+ await rebuildConnections();
439
+ },
440
+ async setServerDisabled(name, disabled, options) {
441
+ if (!config.mcpServers?.[name]) return {
442
+ name,
443
+ connected: false,
444
+ toolCount: 0,
445
+ toolNames: [],
446
+ transport: "stdio",
447
+ error: `Server "${name}" not found in config`
448
+ };
449
+ const wasEffectivelyDisabled = isDisabled(name);
450
+ if (options?.global) persistGlobalDelta((state) => {
451
+ if (disabled) state.disabledServers.add(name);
452
+ else state.disabledServers.delete(name);
453
+ });
454
+ else persistProjectDelta((names) => {
455
+ if (disabled) names.add(name);
456
+ else names.delete(name);
457
+ });
458
+ if (isDisabled(name) !== wasEffectivelyDisabled) {
459
+ await rebuildConnections();
460
+ return withAuthenticating(serverStatuses.get(name) ?? disabledStatus(name));
461
+ }
462
+ return withAuthenticating(isDisabled(name) ? disabledStatus(name) : serverStatuses.get(name) ?? disabledStatus(name));
463
+ },
464
+ async setAllDisabled(disabled, options) {
465
+ const configuredNames = Object.keys(config.mcpServers ?? {});
466
+ const effectiveBefore = configuredNames.filter((name) => isDisabled(name)).join(",");
467
+ if (options?.global) persistGlobalDelta((state) => {
468
+ state.allDisabled = disabled;
469
+ if (!disabled) state.disabledServers.clear();
470
+ });
471
+ else persistProjectDelta((names) => {
472
+ if (disabled) for (const name of configuredNames) names.add(name);
473
+ else names.clear();
474
+ });
475
+ if (configuredNames.filter((name) => isDisabled(name)).join(",") !== effectiveBefore) await rebuildConnections();
476
+ },
477
+ getDisabledServers() {
478
+ return Object.keys(config.mcpServers ?? {}).filter((name) => isDisabled(name)).sort();
479
+ },
480
+ isAllDisabledGlobally() {
481
+ return globalDisableState.allDisabled;
372
482
  },
373
483
  async reconnectServer(name) {
484
+ if (isDisabled(name)) return {
485
+ ...disabledStatus(name),
486
+ error: `Server "${name}" is disabled — enable it first`
487
+ };
374
488
  const cfg = config.mcpServers?.[name];
375
489
  if (!cfg) return {
376
490
  name,
@@ -400,6 +514,10 @@ function createMcpManager(projectDir, configDirName = DEFAULT_CONFIG_DIR, extraS
400
514
  transport: "stdio",
401
515
  error: `Server "${name}" not found in config`
402
516
  };
517
+ if (isDisabled(name)) return {
518
+ ...disabledStatus(name),
519
+ error: `Server "${name}" is disabled — enable it first`
520
+ };
403
521
  if (!client) return {
404
522
  name,
405
523
  connected: false,
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","names":[],"sources":["../../src/mcp/manager.ts"],"sourcesContent":["/**\n * MCP manager — orchestrates MCP server connections using MCPClient directly.\n * Created once at startup, provides tools from connected MCP servers.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { MCPClient, MCPOAuthClientProvider } from '@mastra/mcp';\nimport type { MastraMCPServerDefinition, OAuthClientInformation, OAuthStorage } from '@mastra/mcp';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { getAppDataDir } from '../utils/project.js';\nimport {\n DEFAULT_OAUTH_REDIRECT_URL,\n loadMcpConfig,\n getProjectMcpPath,\n getGlobalMcpPath,\n getClaudeSettingsPath,\n resolveOAuthRedirectUrl,\n} from './config.js';\nimport type {\n McpConfig,\n McpHttpOAuthConfig,\n McpHttpServerConfig,\n McpServerConfig,\n McpServerStatus,\n McpSkippedServer,\n} from './types.js';\n\nconst MASTRACODE_MCP_TIMEOUT_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\n\n/** Summary of MCP initialization result. */\nexport interface McpInitResult {\n connected: McpServerStatus[];\n failed: McpServerStatus[];\n skipped: McpSkippedServer[];\n totalTools: number;\n}\n\n/** Public interface for the MCP manager returned by createMcpManager(). */\nexport interface McpManager {\n /** Connect to all configured MCP servers and collect their tools. */\n init(): Promise<void>;\n /** Start init in the background. Returns a promise that resolves with status when done. */\n initInBackground(): Promise<McpInitResult>;\n /** Disconnect all servers, reload config from disk, reconnect. */\n reload(): Promise<void>;\n /** Reconnect a single server by name. Returns updated status. */\n reconnectServer(name: string): Promise<McpServerStatus>;\n /**\n * Run the OAuth authorization-code flow for an HTTP server, then reconnect it.\n * Servers without an `oauth` config are provisioned with a zero-config default\n * (dynamic client registration). The authorization URL is surfaced through\n * `onAuthorizationUrl` for the caller to open in a browser.\n *\n * Resolves with the resulting {@link McpServerStatus}: a connected status on\n * success, or a status carrying an `error` message on failure (including\n * cancellation) — it does not reject. Inspect the returned status rather than\n * relying on a thrown error.\n */\n authenticateServer(\n name: string,\n options?: { onAuthorizationUrl?: (url: string) => void; timeoutMs?: number },\n ): Promise<McpServerStatus>;\n /**\n * Cancel a pending {@link authenticateServer} flow for a server (e.g. the\n * user closed the browser without completing consent). The pending\n * authenticate call rejects and the server returns to the `needsAuth` state\n * so it can be retried. Returns `true` if a flow was cancelled.\n */\n cancelServerAuthentication(name: string): Promise<boolean>;\n /** Disconnect from all MCP servers and clean up. */\n disconnect(): Promise<void>;\n /** Get all tools from connected MCP servers (namespaced as serverName_toolName). */\n getTools(): Record<string, any>;\n /** Check if any MCP servers are configured (or skipped). */\n hasServers(): boolean;\n /** Get status of all servers. */\n getServerStatuses(): McpServerStatus[];\n /** Get servers that were skipped during config loading. */\n getSkippedServers(): McpSkippedServer[];\n /** Get config file paths for display. */\n getConfigPaths(): { project: string; global: string; claude: string };\n /** Get the merged config. */\n getConfig(): McpConfig;\n /** Get captured stderr logs for a server. */\n getServerLogs(name: string): string[];\n}\n\nfunction getTransport(cfg: McpServerConfig): 'stdio' | 'http' {\n return 'url' in cfg ? 'http' : 'stdio';\n}\n\nclass FileOAuthStorage implements OAuthStorage {\n constructor(private filePath: string) {}\n\n get(key: string): string | undefined {\n return this.read()[key];\n }\n\n set(key: string, value: string): void {\n const data = this.read();\n data[key] = value;\n this.write(data);\n }\n\n delete(key: string): void {\n const data = this.read();\n delete data[key];\n this.write(data);\n }\n\n private read(): Record<string, string> {\n if (!existsSync(this.filePath)) return {};\n try {\n return JSON.parse(readFileSync(this.filePath, 'utf-8')) as Record<string, string>;\n } catch {\n return {};\n }\n }\n\n private write(data: Record<string, string>): void {\n const dir = dirname(this.filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n const tmpPath = `${this.filePath}.tmp`;\n writeFileSync(tmpPath, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 });\n renameSync(tmpPath, this.filePath);\n }\n}\n\n/**\n * Zero-config OAuth defaults for servers with a bare `url` entry. Dynamic\n * client registration provisions the client, so no `clientId` is needed.\n */\nconst DEFAULT_OAUTH_CONFIG: McpHttpOAuthConfig = { redirectUrl: DEFAULT_OAUTH_REDIRECT_URL };\n\nfunction getOAuthStoragePath(projectDir: string, name: string, cfg: McpHttpServerConfig): string {\n // The fingerprint always uses the resolved redirect URL so a bare `url`\n // entry keeps the same token file before and after zero-config provisioning.\n const key = JSON.stringify({\n projectDir,\n name,\n url: cfg.url,\n redirectUrl: resolveOAuthRedirectUrl(cfg.oauth),\n clientId: cfg.oauth?.clientId,\n scopes: cfg.oauth?.scopes ?? [],\n });\n return join(getAppDataDir(), 'mcp-oauth', `${getStorageKeyFingerprint(key)}.json`);\n}\n\nfunction getStorageKeyFingerprint(value: string): string {\n let fingerprint = 0xcbf29ce484222325n;\n for (let i = 0; i < value.length; i += 1) {\n fingerprint ^= BigInt(value.charCodeAt(i));\n fingerprint = BigInt.asUintN(64, fingerprint * 0x100000001b3n);\n }\n return fingerprint.toString(16).padStart(16, '0');\n}\n\n/**\n * Create an MCP manager that wraps MCPClient with config-file discovery\n * and per-server status tracking.\n */\nexport function createMcpManager(\n projectDir: string,\n configDirName = DEFAULT_CONFIG_DIR,\n extraServers?: Record<string, McpServerConfig>,\n): McpManager {\n /** Merge programmatic servers into a base config (highest priority). */\n const applyExtraServers = (base: McpConfig): McpConfig => {\n if (!extraServers || Object.keys(extraServers).length === 0) return base;\n return { ...base, mcpServers: { ...base.mcpServers, ...extraServers } };\n };\n\n let config = applyExtraServers(loadMcpConfig(projectDir, configDirName));\n let client: MCPClient | null = null;\n let serverDefs: Record<string, MastraMCPServerDefinition> = {};\n let tools: Record<string, any> = {};\n let serverStatuses = new Map<string, McpServerStatus>();\n let stderrLogs = new Map<string, string[]>();\n let initialized = false;\n\n /** Per-server handlers that receive the OAuth authorization URL during authenticateServer(). */\n const authUrlHandlers = new Map<string, (url: string) => void>();\n\n /**\n * Servers with an OAuth authorization flow currently in flight. Owned by the\n * manager (not the TUI) so the state survives a `/mcp` selector being closed\n * and reopened — the reopened selector reads it back off the server status and\n * can still offer \"Cancel authentication\".\n */\n const authenticatingServers = new Set<string>();\n\n /**\n * Servers whose in-flight authentication was cancelled by the caller. Set by\n * cancelServerAuthentication() so the resolving authenticateServer() call can\n * mark its failed status as a deliberate cancel rather than a genuine failure.\n * This lives on the manager (not the TUI selector) so the signal survives the\n * selector being closed and reopened mid-flow.\n */\n const cancelledAuthServers = new Set<string>();\n\n /** Overlay the manager-owned `authenticating` flag onto a status snapshot. */\n const withAuthenticating = (status: McpServerStatus): McpServerStatus =>\n authenticatingServers.has(status.name) ? { ...status, authenticating: true } : status;\n\n const MAX_STDERR_LINES = 200;\n\n /** Hook into a server's stderr stream and buffer its output. */\n function captureStderr(serverName: string): void {\n if (!client || typeof client.getServerStderr !== 'function') return;\n const stream = client.getServerStderr(serverName);\n if (!stream) return;\n\n let buffer = '';\n const lines = stderrLogs.get(serverName) ?? [];\n stderrLogs.set(serverName, lines);\n\n stream.on('data', (chunk: Buffer) => {\n buffer += chunk.toString();\n const parts = buffer.split('\\n');\n // Last element is incomplete line (or empty if ended with \\n)\n buffer = parts.pop()!;\n for (const line of parts) {\n if (line.trim()) {\n lines.push(line);\n if (lines.length > MAX_STDERR_LINES) {\n lines.shift();\n }\n }\n }\n });\n\n stream.on('end', () => {\n if (buffer.trim()) {\n lines.push(buffer);\n if (lines.length > MAX_STDERR_LINES) {\n lines.shift();\n }\n }\n });\n }\n\n function createOAuthProvider(name: string, cfg: McpHttpServerConfig) {\n // Bare `url` entries get no eager provider — auth is provisioned lazily\n // when the user authenticates — unless a previous session already stored\n // OAuth state for this server, in which case the provider is needed to\n // attach the persisted tokens on connect.\n const oauth =\n cfg.oauth ?? (existsSync(getOAuthStoragePath(projectDir, name, cfg)) ? DEFAULT_OAUTH_CONFIG : undefined);\n if (!oauth) return undefined;\n\n // redirectUrl is optional in the user-supplied config; resolve the stable\n // default (or the `callbackPort` shorthand, for programmatically registered\n // servers that bypass config parsing) so provider metadata always carries\n // a concrete URL.\n const redirectUrl = resolveOAuthRedirectUrl(oauth);\n\n return new MCPOAuthClientProvider({\n redirectUrl,\n clientMetadata: {\n redirect_uris: [redirectUrl],\n client_name: oauth.clientName ?? `Mastra Code MCP ${name}`,\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n ...(oauth.scopes?.length ? { scope: oauth.scopes.join(' ') } : {}),\n },\n clientInformation: oauth.clientId\n ? ({\n client_id: oauth.clientId,\n ...(oauth.clientSecret ? { client_secret: oauth.clientSecret } : {}),\n } satisfies OAuthClientInformation)\n : undefined,\n storage: new FileOAuthStorage(getOAuthStoragePath(projectDir, name, cfg)),\n onRedirectToAuthorization: url => {\n authUrlHandlers.get(name)?.(url.toString());\n },\n });\n }\n\n function buildServerDefs(servers: Record<string, McpServerConfig>): Record<string, MastraMCPServerDefinition> {\n const defs: Record<string, MastraMCPServerDefinition> = {};\n for (const [name, cfg] of Object.entries(servers)) {\n if ('url' in cfg) {\n const httpCfg = cfg as McpHttpServerConfig;\n defs[name] = {\n url: new URL(httpCfg.url),\n requestInit: httpCfg.headers ? { headers: httpCfg.headers } : undefined,\n authProvider: createOAuthProvider(name, httpCfg),\n };\n } else {\n defs[name] = { command: cfg.command, args: cfg.args, env: cfg.env, stderr: 'pipe' };\n }\n }\n return defs;\n }\n\n async function connectAndCollectTools(): Promise<void> {\n const servers = config.mcpServers;\n if (!servers || Object.keys(servers).length === 0) {\n return;\n }\n\n // Pre-populate statuses as \"connecting\" so callers can see in-progress state\n const serverNames = Object.keys(servers);\n for (const name of serverNames) {\n serverStatuses.set(name, {\n name,\n connected: false,\n connecting: true,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(servers[name]!),\n });\n }\n\n serverDefs = buildServerDefs(servers);\n client = new MCPClient({\n id: 'mastra-code-mcp',\n servers: serverDefs,\n timeout: MASTRACODE_MCP_TIMEOUT_MS,\n });\n\n // Use listToolsetsWithErrors() to get tools grouped by server name,\n // plus per-server error messages for servers that failed to connect.\n\n try {\n const { toolsets, errors } = await client.listToolsetsWithErrors();\n const typedToolsets = toolsets as Record<string, Record<string, any>>;\n\n // Flatten toolsets into the namespaced tools map (serverName_toolName)\n for (const [serverName, serverTools] of Object.entries(typedToolsets)) {\n for (const [toolName, toolConfig] of Object.entries(serverTools)) {\n tools[`${serverName}_${toolName}`] = toolConfig;\n }\n }\n\n for (const name of serverNames) {\n const serverTools = typedToolsets[name];\n if (serverTools && Object.keys(serverTools).length > 0) {\n const toolNames = Object.keys(serverTools).map(t => `${name}_${t}`);\n serverStatuses.set(name, {\n name,\n connected: true,\n toolCount: toolNames.length,\n toolNames,\n transport: getTransport(servers[name]!),\n });\n } else {\n // Server failed — use the real error from listToolsetsWithErrors()\n const error = errors[name] ?? 'Failed to connect';\n serverStatuses.set(name, {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(servers[name]!),\n error,\n ...(serverNeedsAuth(name, servers[name]!, error) ? { needsAuth: true } : {}),\n });\n }\n }\n\n // Capture stderr from all stdio servers (connected or failed)\n for (const name of serverNames) {\n captureStderr(name);\n }\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n\n for (const name of serverNames) {\n serverStatuses.set(name, {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(servers[name]!),\n error: errMsg,\n ...(serverNeedsAuth(name, servers[name]!, errMsg) ? { needsAuth: true } : {}),\n });\n }\n }\n }\n\n /**\n * Whether a failed HTTP server is blocked on OAuth authorization.\n *\n * Provider-backed servers report the exact state tracked by `@mastra/mcp`.\n * Bare `url` entries carry no provider until the user authenticates, so the\n * signal is a 401 in the connect error — surfaced either as the status text\n * or as the RFC 6750 `invalid_token` bearer error code in the response body.\n */\n function serverNeedsAuth(name: string, cfg: McpServerConfig, error?: string): boolean {\n if (getTransport(cfg) !== 'http') return false;\n if (client?.getServerAuthState?.(name) === 'needs-auth') return true;\n if (serverDefs[name]?.authProvider) return false;\n return error !== undefined && /\\b401\\b|unauthorized|invalid_token/i.test(error);\n }\n\n /**\n * Runs a single-server connect action (reconnect or authenticate), then\n * refreshes that server's tools and status from the client.\n */\n async function connectSingleServer(\n name: string,\n cfg: McpServerConfig,\n connect: () => Promise<unknown>,\n ): Promise<McpServerStatus> {\n const transport = getTransport(cfg);\n\n // Remove old tools for this server\n const prefix = `${name}_`;\n for (const key of Object.keys(tools)) {\n if (key.startsWith(prefix)) {\n delete tools[key];\n }\n }\n\n // Clear old logs and mark as connecting\n stderrLogs.delete(name);\n serverStatuses.set(name, {\n name,\n connected: false,\n connecting: true,\n toolCount: 0,\n toolNames: [],\n transport,\n });\n\n try {\n await connect();\n\n // Recapture stderr for the reconnected server\n captureStderr(name);\n\n // Fetch updated toolsets to get this server's tools\n const { toolsets, errors } = await client!.listToolsetsWithErrors();\n const serverTools = toolsets[name];\n const serverError = errors[name];\n\n if (serverError) {\n const status: McpServerStatus = {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport,\n error: serverError,\n ...(serverNeedsAuth(name, cfg, serverError) ? { needsAuth: true } : {}),\n };\n serverStatuses.set(name, status);\n return status;\n } else if (serverTools && Object.keys(serverTools).length > 0) {\n const toolNames = Object.keys(serverTools).map(t => `${name}_${t}`);\n for (const [toolName, toolConfig] of Object.entries(serverTools)) {\n tools[`${name}_${toolName}`] = toolConfig;\n }\n const status: McpServerStatus = {\n name,\n connected: true,\n toolCount: toolNames.length,\n toolNames,\n transport,\n };\n serverStatuses.set(name, status);\n return status;\n } else {\n const status: McpServerStatus = {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport,\n error: 'Failed to connect',\n };\n serverStatuses.set(name, status);\n return status;\n }\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n const status: McpServerStatus = {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport,\n error: errMsg,\n ...(serverNeedsAuth(name, cfg, errMsg) ? { needsAuth: true } : {}),\n };\n serverStatuses.set(name, status);\n return status;\n }\n }\n\n async function disconnect(): Promise<void> {\n if (client) {\n try {\n await client.disconnect();\n } catch {\n // Ignore disconnect errors\n }\n client = null;\n }\n }\n\n return {\n async init() {\n if (initialized) return;\n await connectAndCollectTools();\n initialized = true;\n },\n\n async initInBackground(): Promise<McpInitResult> {\n await this.init();\n const statuses = Array.from(serverStatuses.values());\n const connected = statuses.filter(s => s.connected);\n const failed = statuses.filter(s => !s.connected);\n return {\n connected,\n failed,\n skipped: [...(config.skippedServers ?? [])],\n totalTools: connected.reduce((sum, s) => sum + s.toolCount, 0),\n };\n },\n\n async reload() {\n await disconnect();\n config = applyExtraServers(loadMcpConfig(projectDir, configDirName));\n tools = {};\n serverStatuses = new Map();\n stderrLogs = new Map();\n initialized = false;\n await connectAndCollectTools();\n initialized = true;\n },\n\n async reconnectServer(name: string): Promise<McpServerStatus> {\n const cfg = config.mcpServers?.[name];\n if (!cfg) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" not found in config`,\n };\n }\n\n if (!client) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(cfg),\n error: 'MCP client not initialized',\n };\n }\n\n // Use MCPClient's per-server reconnect\n return connectSingleServer(name, cfg, () => client!.reconnectServer(name));\n },\n\n async authenticateServer(\n name: string,\n options?: { onAuthorizationUrl?: (url: string) => void; timeoutMs?: number },\n ): Promise<McpServerStatus> {\n const cfg = config.mcpServers?.[name];\n if (!cfg) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" not found in config`,\n };\n }\n\n if (!client) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(cfg),\n error: 'MCP client not initialized',\n };\n }\n\n if (getTransport(cfg) !== 'http') {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" uses stdio transport, which does not support OAuth`,\n };\n }\n\n // Zero-config provisioning: a bare `url` entry gets a provider with the\n // default redirect URL the first time the user authenticates. Dynamic\n // client registration takes care of the client credentials.\n //\n // NOTE: `serverDefs[name]` is the same object reference the MCPClient was\n // constructed with, and connectHttp reads `authProvider` live off it at\n // connect time, so mutating it here reaches the already-created client.\n // If MCPClient ever defensively copies its server config, zero-config auth\n // would need an explicit \"set this server's provider\" API instead.\n const def = serverDefs[name];\n if (def?.url && !def.authProvider) {\n def.authProvider = createOAuthProvider(name, { ...(cfg as McpHttpServerConfig), oauth: DEFAULT_OAUTH_CONFIG });\n }\n\n // Reject a concurrent second attempt for the same server. authUrlHandlers\n // has a single slot per server, so a second call with an onAuthorizationUrl\n // would overwrite the first caller's handler (which then never sees the\n // URL) and its finally would delete the handler out from under the other\n // in-flight call. Gate on authenticatingServers rather than authUrlHandlers\n // so callers without a URL handler are caught too. The underlying\n // client.authenticate already coalesces same-server calls into one flow.\n if (authenticatingServers.has(name)) {\n const current = serverStatuses.get(name);\n return {\n name,\n connected: current?.connected ?? false,\n connecting: current?.connecting,\n needsAuth: current?.needsAuth,\n toolCount: current?.toolCount ?? 0,\n toolNames: current?.toolNames ?? [],\n transport: current?.transport ?? getTransport(cfg),\n error: `Authentication for \"${name}\" is already in progress`,\n };\n }\n\n if (options?.onAuthorizationUrl) {\n authUrlHandlers.set(name, options.onAuthorizationUrl);\n }\n authenticatingServers.add(name);\n cancelledAuthServers.delete(name);\n try {\n const result = await connectSingleServer(name, cfg, () =>\n client!.authenticate(name, options?.timeoutMs === undefined ? undefined : { timeoutMs: options.timeoutMs }),\n );\n // A cancelled flow resolves with a failed status; mark it so callers can\n // distinguish a deliberate cancel from a genuine authentication failure.\n // Write the marker back to the durable status map (not just the returned\n // value) so a selector reopened after cancellation still sees it.\n const finalStatus =\n cancelledAuthServers.has(name) && !result.connected ? { ...result, cancelled: true } : result;\n serverStatuses.set(name, finalStatus);\n return finalStatus;\n } finally {\n authUrlHandlers.delete(name);\n authenticatingServers.delete(name);\n cancelledAuthServers.delete(name);\n }\n },\n\n async cancelServerAuthentication(name: string): Promise<boolean> {\n if (!client) {\n return false;\n }\n // Record the intent before aborting so the resolving authenticateServer()\n // call can tag its failed status as cancelled rather than failed.\n cancelledAuthServers.add(name);\n const cancelled = await client.cancelAuthentication(name);\n if (!cancelled) {\n cancelledAuthServers.delete(name);\n }\n return cancelled;\n },\n\n disconnect,\n\n getTools() {\n return { ...tools };\n },\n\n hasServers() {\n const hasConfigured = config.mcpServers !== undefined && Object.keys(config.mcpServers).length > 0;\n const hasSkipped = config.skippedServers !== undefined && config.skippedServers.length > 0;\n return hasConfigured || hasSkipped;\n },\n\n getServerStatuses() {\n return Array.from(serverStatuses.values(), withAuthenticating);\n },\n\n getSkippedServers() {\n return [...(config.skippedServers ?? [])];\n },\n\n getConfigPaths() {\n return {\n project: getProjectMcpPath(projectDir, configDirName),\n global: getGlobalMcpPath(configDirName),\n claude: getClaudeSettingsPath(projectDir),\n };\n },\n\n getConfig() {\n return config;\n },\n\n getServerLogs(name: string) {\n return [...(stderrLogs.get(name) ?? [])];\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"manager.js","names":[],"sources":["../../src/mcp/manager.ts"],"sourcesContent":["/**\n * MCP manager — orchestrates MCP server connections using MCPClient directly.\n * Created once at startup, provides tools from connected MCP servers.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { MCPClient, MCPOAuthClientProvider } from '@mastra/mcp';\nimport type { MastraMCPServerDefinition, OAuthClientInformation, OAuthStorage } from '@mastra/mcp';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { getAppDataDir } from '../utils/project.js';\nimport {\n DEFAULT_OAUTH_REDIRECT_URL,\n loadMcpConfig,\n getProjectMcpPath,\n getGlobalMcpPath,\n getClaudeSettingsPath,\n resolveOAuthRedirectUrl,\n} from './config.js';\nimport { loadDisabledServers, loadGlobalDisableState, saveDisabledServers, saveGlobalDisableState } from './state.js';\nimport type {\n McpConfig,\n McpHttpOAuthConfig,\n McpHttpServerConfig,\n McpServerConfig,\n McpServerStatus,\n McpSkippedServer,\n} from './types.js';\n\nconst MASTRACODE_MCP_TIMEOUT_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\n\n/** Summary of MCP initialization result. */\nexport interface McpInitResult {\n connected: McpServerStatus[];\n failed: McpServerStatus[];\n skipped: McpSkippedServer[];\n totalTools: number;\n}\n\n/** Public interface for the MCP manager returned by createMcpManager(). */\nexport interface McpManager {\n /** Connect to all configured MCP servers and collect their tools. */\n init(): Promise<void>;\n /** Start init in the background. Returns a promise that resolves with status when done. */\n initInBackground(): Promise<McpInitResult>;\n /** Disconnect all servers, reload config from disk, reconnect. */\n reload(): Promise<void>;\n /** Reconnect a single server by name. Returns updated status. */\n reconnectServer(name: string): Promise<McpServerStatus>;\n /**\n * Run the OAuth authorization-code flow for an HTTP server, then reconnect it.\n * Servers without an `oauth` config are provisioned with a zero-config default\n * (dynamic client registration). The authorization URL is surfaced through\n * `onAuthorizationUrl` for the caller to open in a browser.\n *\n * Resolves with the resulting {@link McpServerStatus}: a connected status on\n * success, or a status carrying an `error` message on failure (including\n * cancellation) — it does not reject. Inspect the returned status rather than\n * relying on a thrown error.\n */\n authenticateServer(\n name: string,\n options?: { onAuthorizationUrl?: (url: string) => void; timeoutMs?: number },\n ): Promise<McpServerStatus>;\n /**\n * Cancel a pending {@link authenticateServer} flow for a server (e.g. the\n * user closed the browser without completing consent). The pending\n * authenticate call rejects and the server returns to the `needsAuth` state\n * so it can be retried. Returns `true` if a flow was cancelled.\n */\n cancelServerAuthentication(name: string): Promise<boolean>;\n /**\n * Disable or enable a single server by name. The change is persisted (in\n * mastracode's app data, not the user's config files) and survives restarts.\n * With `global: true` the change applies to every project; otherwise it is\n * scoped to this project. Enabling only removes the server from the given\n * scope — a server disabled in the other scope stays disabled, and the\n * returned status's `disabledScope` says which scope still applies.\n * Connections are rebuilt, so other servers reconnect — same behavior as\n * {@link reload}. Returns the server's resulting status.\n */\n setServerDisabled(name: string, disabled: boolean, options?: { global?: boolean }): Promise<McpServerStatus>;\n /**\n * Disable or enable all servers at once. Project scope records every\n * currently-configured server name; enabling clears the project list.\n * Global scope sets/clears a persisted all-MCP kill switch (and, when\n * enabling, also clears globally disabled server names). Persisted like\n * {@link setServerDisabled}.\n */\n setAllDisabled(disabled: boolean, options?: { global?: boolean }): Promise<void>;\n /** Names of configured servers that are currently disabled (any scope). */\n getDisabledServers(): string[];\n /** Whether all MCP is disabled globally (across every project). */\n isAllDisabledGlobally(): boolean;\n /** Disconnect from all MCP servers and clean up. */\n disconnect(): Promise<void>;\n /** Get all tools from connected MCP servers (namespaced as serverName_toolName). */\n getTools(): Record<string, any>;\n /** Check if any MCP servers are configured (or skipped). */\n hasServers(): boolean;\n /** Get status of all servers. */\n getServerStatuses(): McpServerStatus[];\n /** Get servers that were skipped during config loading. */\n getSkippedServers(): McpSkippedServer[];\n /** Get config file paths for display. */\n getConfigPaths(): { project: string; global: string; claude: string };\n /** Get the merged config. */\n getConfig(): McpConfig;\n /** Get captured stderr logs for a server. */\n getServerLogs(name: string): string[];\n}\n\nfunction getTransport(cfg: McpServerConfig): 'stdio' | 'http' {\n return 'url' in cfg ? 'http' : 'stdio';\n}\n\nclass FileOAuthStorage implements OAuthStorage {\n constructor(private filePath: string) {}\n\n get(key: string): string | undefined {\n return this.read()[key];\n }\n\n set(key: string, value: string): void {\n const data = this.read();\n data[key] = value;\n this.write(data);\n }\n\n delete(key: string): void {\n const data = this.read();\n delete data[key];\n this.write(data);\n }\n\n private read(): Record<string, string> {\n if (!existsSync(this.filePath)) return {};\n try {\n return JSON.parse(readFileSync(this.filePath, 'utf-8')) as Record<string, string>;\n } catch {\n return {};\n }\n }\n\n private write(data: Record<string, string>): void {\n const dir = dirname(this.filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n const tmpPath = `${this.filePath}.tmp`;\n writeFileSync(tmpPath, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 });\n renameSync(tmpPath, this.filePath);\n }\n}\n\n/**\n * Zero-config OAuth defaults for servers with a bare `url` entry. Dynamic\n * client registration provisions the client, so no `clientId` is needed.\n */\nconst DEFAULT_OAUTH_CONFIG: McpHttpOAuthConfig = { redirectUrl: DEFAULT_OAUTH_REDIRECT_URL };\n\nfunction getOAuthStoragePath(projectDir: string, name: string, cfg: McpHttpServerConfig): string {\n // The fingerprint always uses the resolved redirect URL so a bare `url`\n // entry keeps the same token file before and after zero-config provisioning.\n const key = JSON.stringify({\n projectDir,\n name,\n url: cfg.url,\n redirectUrl: resolveOAuthRedirectUrl(cfg.oauth),\n clientId: cfg.oauth?.clientId,\n scopes: cfg.oauth?.scopes ?? [],\n });\n return join(getAppDataDir(), 'mcp-oauth', `${getStorageKeyFingerprint(key)}.json`);\n}\n\nfunction getStorageKeyFingerprint(value: string): string {\n let fingerprint = 0xcbf29ce484222325n;\n for (let i = 0; i < value.length; i += 1) {\n fingerprint ^= BigInt(value.charCodeAt(i));\n fingerprint = BigInt.asUintN(64, fingerprint * 0x100000001b3n);\n }\n return fingerprint.toString(16).padStart(16, '0');\n}\n\n/**\n * Create an MCP manager that wraps MCPClient with config-file discovery\n * and per-server status tracking.\n */\nexport function createMcpManager(\n projectDir: string,\n configDirName = DEFAULT_CONFIG_DIR,\n extraServers?: Record<string, McpServerConfig>,\n): McpManager {\n /** Merge programmatic servers into a base config (highest priority). */\n const applyExtraServers = (base: McpConfig): McpConfig => {\n if (!extraServers || Object.keys(extraServers).length === 0) return base;\n return { ...base, mcpServers: { ...base.mcpServers, ...extraServers } };\n };\n\n let config = applyExtraServers(loadMcpConfig(projectDir, configDirName));\n let disabledServers = new Set(loadDisabledServers(projectDir));\n let globalDisableState = loadGlobalDisableState();\n let globallyDisabledServers = new Set(globalDisableState.disabledServers);\n\n /** Whether a server is disabled in any scope (global kill switch, global list, or project list). */\n const isDisabled = (name: string): boolean =>\n globalDisableState.allDisabled || globallyDisabledServers.has(name) || disabledServers.has(name);\n\n /** Which scope disables a server. Global takes precedence — project-level enable can't undo it. */\n const disabledScopeOf = (name: string): 'project' | 'global' | undefined => {\n if (globalDisableState.allDisabled || globallyDisabledServers.has(name)) return 'global';\n if (disabledServers.has(name)) return 'project';\n return undefined;\n };\n let client: MCPClient | null = null;\n let serverDefs: Record<string, MastraMCPServerDefinition> = {};\n let tools: Record<string, any> = {};\n let serverStatuses = new Map<string, McpServerStatus>();\n let stderrLogs = new Map<string, string[]>();\n let initialized = false;\n\n /** Per-server handlers that receive the OAuth authorization URL during authenticateServer(). */\n const authUrlHandlers = new Map<string, (url: string) => void>();\n\n /**\n * Servers with an OAuth authorization flow currently in flight. Owned by the\n * manager (not the TUI) so the state survives a `/mcp` selector being closed\n * and reopened — the reopened selector reads it back off the server status and\n * can still offer \"Cancel authentication\".\n */\n const authenticatingServers = new Set<string>();\n\n /**\n * Servers whose in-flight authentication was cancelled by the caller. Set by\n * cancelServerAuthentication() so the resolving authenticateServer() call can\n * mark its failed status as a deliberate cancel rather than a genuine failure.\n * This lives on the manager (not the TUI selector) so the signal survives the\n * selector being closed and reopened mid-flow.\n */\n const cancelledAuthServers = new Set<string>();\n\n /** Overlay the manager-owned `authenticating` flag onto a status snapshot. */\n const withAuthenticating = (status: McpServerStatus): McpServerStatus =>\n authenticatingServers.has(status.name) ? { ...status, authenticating: true } : status;\n\n const MAX_STDERR_LINES = 200;\n\n /** Hook into a server's stderr stream and buffer its output. */\n function captureStderr(serverName: string): void {\n if (!client || typeof client.getServerStderr !== 'function') return;\n const stream = client.getServerStderr(serverName);\n if (!stream) return;\n\n let buffer = '';\n const lines = stderrLogs.get(serverName) ?? [];\n stderrLogs.set(serverName, lines);\n\n stream.on('data', (chunk: Buffer) => {\n buffer += chunk.toString();\n const parts = buffer.split('\\n');\n // Last element is incomplete line (or empty if ended with \\n)\n buffer = parts.pop()!;\n for (const line of parts) {\n if (line.trim()) {\n lines.push(line);\n if (lines.length > MAX_STDERR_LINES) {\n lines.shift();\n }\n }\n }\n });\n\n stream.on('end', () => {\n if (buffer.trim()) {\n lines.push(buffer);\n if (lines.length > MAX_STDERR_LINES) {\n lines.shift();\n }\n }\n });\n }\n\n function createOAuthProvider(name: string, cfg: McpHttpServerConfig) {\n // Bare `url` entries get no eager provider — auth is provisioned lazily\n // when the user authenticates — unless a previous session already stored\n // OAuth state for this server, in which case the provider is needed to\n // attach the persisted tokens on connect.\n const oauth =\n cfg.oauth ?? (existsSync(getOAuthStoragePath(projectDir, name, cfg)) ? DEFAULT_OAUTH_CONFIG : undefined);\n if (!oauth) return undefined;\n\n // redirectUrl is optional in the user-supplied config; resolve the stable\n // default (or the `callbackPort` shorthand, for programmatically registered\n // servers that bypass config parsing) so provider metadata always carries\n // a concrete URL.\n const redirectUrl = resolveOAuthRedirectUrl(oauth);\n\n return new MCPOAuthClientProvider({\n redirectUrl,\n clientMetadata: {\n redirect_uris: [redirectUrl],\n client_name: oauth.clientName ?? `Mastra Code MCP ${name}`,\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n ...(oauth.scopes?.length ? { scope: oauth.scopes.join(' ') } : {}),\n },\n clientInformation: oauth.clientId\n ? ({\n client_id: oauth.clientId,\n ...(oauth.clientSecret ? { client_secret: oauth.clientSecret } : {}),\n } satisfies OAuthClientInformation)\n : undefined,\n storage: new FileOAuthStorage(getOAuthStoragePath(projectDir, name, cfg)),\n onRedirectToAuthorization: url => {\n authUrlHandlers.get(name)?.(url.toString());\n },\n });\n }\n\n function buildServerDefs(servers: Record<string, McpServerConfig>): Record<string, MastraMCPServerDefinition> {\n const defs: Record<string, MastraMCPServerDefinition> = {};\n for (const [name, cfg] of Object.entries(servers)) {\n if ('url' in cfg) {\n const httpCfg = cfg as McpHttpServerConfig;\n defs[name] = {\n url: new URL(httpCfg.url),\n requestInit: httpCfg.headers ? { headers: httpCfg.headers } : undefined,\n authProvider: createOAuthProvider(name, httpCfg),\n };\n } else {\n defs[name] = { command: cfg.command, args: cfg.args, env: cfg.env, stderr: 'pipe' };\n }\n }\n return defs;\n }\n\n /** Seed a `disabled` status for every disabled server so it stays visible. */\n function setDisabledStatuses(): void {\n for (const [name, cfg] of Object.entries(config.mcpServers ?? {})) {\n const scope = disabledScopeOf(name);\n if (!scope) continue;\n serverStatuses.set(name, {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(cfg),\n disabled: true,\n disabledScope: scope,\n });\n }\n }\n\n async function connectAndCollectTools(): Promise<void> {\n setDisabledStatuses();\n\n const servers = Object.fromEntries(Object.entries(config.mcpServers ?? {}).filter(([name]) => !isDisabled(name)));\n if (Object.keys(servers).length === 0) {\n return;\n }\n\n // Pre-populate statuses as \"connecting\" so callers can see in-progress state\n const serverNames = Object.keys(servers);\n for (const name of serverNames) {\n serverStatuses.set(name, {\n name,\n connected: false,\n connecting: true,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(servers[name]!),\n });\n }\n\n serverDefs = buildServerDefs(servers);\n client = new MCPClient({\n id: 'mastra-code-mcp',\n servers: serverDefs,\n timeout: MASTRACODE_MCP_TIMEOUT_MS,\n });\n\n // Use listToolsetsWithErrors() to get tools grouped by server name,\n // plus per-server error messages for servers that failed to connect.\n\n try {\n const { toolsets, errors } = await client.listToolsetsWithErrors();\n const typedToolsets = toolsets as Record<string, Record<string, any>>;\n\n // Flatten toolsets into the namespaced tools map (serverName_toolName)\n for (const [serverName, serverTools] of Object.entries(typedToolsets)) {\n for (const [toolName, toolConfig] of Object.entries(serverTools)) {\n tools[`${serverName}_${toolName}`] = toolConfig;\n }\n }\n\n for (const name of serverNames) {\n const serverTools = typedToolsets[name];\n if (serverTools && Object.keys(serverTools).length > 0) {\n const toolNames = Object.keys(serverTools).map(t => `${name}_${t}`);\n serverStatuses.set(name, {\n name,\n connected: true,\n toolCount: toolNames.length,\n toolNames,\n transport: getTransport(servers[name]!),\n });\n } else {\n // Server failed — use the real error from listToolsetsWithErrors()\n const error = errors[name] ?? 'Failed to connect';\n serverStatuses.set(name, {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(servers[name]!),\n error,\n ...(serverNeedsAuth(name, servers[name]!, error) ? { needsAuth: true } : {}),\n });\n }\n }\n\n // Capture stderr from all stdio servers (connected or failed)\n for (const name of serverNames) {\n captureStderr(name);\n }\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n\n for (const name of serverNames) {\n serverStatuses.set(name, {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(servers[name]!),\n error: errMsg,\n ...(serverNeedsAuth(name, servers[name]!, errMsg) ? { needsAuth: true } : {}),\n });\n }\n }\n }\n\n /**\n * Whether a failed HTTP server is blocked on OAuth authorization.\n *\n * Provider-backed servers report the exact state tracked by `@mastra/mcp`.\n * Bare `url` entries carry no provider until the user authenticates, so the\n * signal is a 401 in the connect error — surfaced either as the status text\n * or as the RFC 6750 `invalid_token` bearer error code in the response body.\n */\n function serverNeedsAuth(name: string, cfg: McpServerConfig, error?: string): boolean {\n if (getTransport(cfg) !== 'http') return false;\n if (client?.getServerAuthState?.(name) === 'needs-auth') return true;\n if (serverDefs[name]?.authProvider) return false;\n return error !== undefined && /\\b401\\b|unauthorized|invalid_token/i.test(error);\n }\n\n /**\n * Runs a single-server connect action (reconnect or authenticate), then\n * refreshes that server's tools and status from the client.\n */\n async function connectSingleServer(\n name: string,\n cfg: McpServerConfig,\n connect: () => Promise<unknown>,\n ): Promise<McpServerStatus> {\n const transport = getTransport(cfg);\n\n // Remove old tools for this server\n const prefix = `${name}_`;\n for (const key of Object.keys(tools)) {\n if (key.startsWith(prefix)) {\n delete tools[key];\n }\n }\n\n // Clear old logs and mark as connecting\n stderrLogs.delete(name);\n serverStatuses.set(name, {\n name,\n connected: false,\n connecting: true,\n toolCount: 0,\n toolNames: [],\n transport,\n });\n\n try {\n await connect();\n\n // Recapture stderr for the reconnected server\n captureStderr(name);\n\n // Fetch updated toolsets to get this server's tools\n const { toolsets, errors } = await client!.listToolsetsWithErrors();\n const serverTools = toolsets[name];\n const serverError = errors[name];\n\n if (serverError) {\n const status: McpServerStatus = {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport,\n error: serverError,\n ...(serverNeedsAuth(name, cfg, serverError) ? { needsAuth: true } : {}),\n };\n serverStatuses.set(name, status);\n return status;\n } else if (serverTools && Object.keys(serverTools).length > 0) {\n const toolNames = Object.keys(serverTools).map(t => `${name}_${t}`);\n for (const [toolName, toolConfig] of Object.entries(serverTools)) {\n tools[`${name}_${toolName}`] = toolConfig;\n }\n const status: McpServerStatus = {\n name,\n connected: true,\n toolCount: toolNames.length,\n toolNames,\n transport,\n };\n serverStatuses.set(name, status);\n return status;\n } else {\n const status: McpServerStatus = {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport,\n error: 'Failed to connect',\n };\n serverStatuses.set(name, status);\n return status;\n }\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n const status: McpServerStatus = {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport,\n error: errMsg,\n ...(serverNeedsAuth(name, cfg, errMsg) ? { needsAuth: true } : {}),\n };\n serverStatuses.set(name, status);\n return status;\n }\n }\n\n async function disconnect(): Promise<void> {\n if (client) {\n try {\n await client.disconnect();\n } catch {\n // Ignore disconnect errors\n }\n client = null;\n }\n }\n\n /** Tear down all connections and reconnect every enabled server. */\n async function rebuildConnections(): Promise<void> {\n await disconnect();\n tools = {};\n serverStatuses = new Map();\n stderrLogs = new Map();\n initialized = false;\n await connectAndCollectTools();\n initialized = true;\n }\n\n function disabledStatus(name: string): McpServerStatus {\n const cfg = config.mcpServers?.[name];\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: cfg ? getTransport(cfg) : 'stdio',\n disabled: true,\n disabledScope: disabledScopeOf(name),\n };\n }\n\n // Read-merge-write persistence: re-read the persisted state and apply this\n // operation's delta on top, then adopt the merged result in memory. This\n // way a concurrent mastracode process's changes (e.g. another window\n // flipping the global kill switch) are never clobbered by this manager's\n // construction-time snapshot.\n function persistProjectDelta(mutate: (names: Set<string>) => void): void {\n const fresh = new Set(loadDisabledServers(projectDir));\n mutate(fresh);\n disabledServers = fresh;\n saveDisabledServers(projectDir, Array.from(fresh));\n }\n\n function persistGlobalDelta(mutate: (state: { allDisabled: boolean; disabledServers: Set<string> }) => void): void {\n const onDisk = loadGlobalDisableState();\n const fresh = { allDisabled: onDisk.allDisabled, disabledServers: new Set(onDisk.disabledServers) };\n mutate(fresh);\n globallyDisabledServers = fresh.disabledServers;\n globalDisableState = { allDisabled: fresh.allDisabled, disabledServers: Array.from(fresh.disabledServers) };\n saveGlobalDisableState(globalDisableState);\n }\n\n return {\n async init() {\n if (initialized) return;\n await connectAndCollectTools();\n initialized = true;\n },\n\n async initInBackground(): Promise<McpInitResult> {\n await this.init();\n const statuses = Array.from(serverStatuses.values());\n const connected = statuses.filter(s => s.connected);\n const failed = statuses.filter(s => !s.connected && !s.disabled);\n return {\n connected,\n failed,\n skipped: [...(config.skippedServers ?? [])],\n totalTools: connected.reduce((sum, s) => sum + s.toolCount, 0),\n };\n },\n\n async reload() {\n config = applyExtraServers(loadMcpConfig(projectDir, configDirName));\n disabledServers = new Set(loadDisabledServers(projectDir));\n globalDisableState = loadGlobalDisableState();\n globallyDisabledServers = new Set(globalDisableState.disabledServers);\n await rebuildConnections();\n },\n\n async setServerDisabled(name: string, disabled: boolean, options?: { global?: boolean }): Promise<McpServerStatus> {\n if (!config.mcpServers?.[name]) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" not found in config`,\n };\n }\n\n const wasEffectivelyDisabled = isDisabled(name);\n\n if (options?.global) {\n persistGlobalDelta(state => {\n if (disabled) {\n state.disabledServers.add(name);\n } else {\n state.disabledServers.delete(name);\n }\n });\n } else {\n persistProjectDelta(names => {\n if (disabled) {\n names.add(name);\n } else {\n names.delete(name);\n }\n });\n }\n\n // Only rebuild connections when the server's effective state actually\n // flipped — e.g. removing it from one scope while the other scope (or\n // the global kill switch) still disables it leaves connections alone.\n if (isDisabled(name) !== wasEffectivelyDisabled) {\n await rebuildConnections();\n return withAuthenticating(serverStatuses.get(name) ?? disabledStatus(name));\n }\n // Effective state unchanged. If still disabled, report a fresh status so\n // `disabledScope` reflects the scope that (still) applies.\n return withAuthenticating(\n isDisabled(name) ? disabledStatus(name) : (serverStatuses.get(name) ?? disabledStatus(name)),\n );\n },\n\n async setAllDisabled(disabled: boolean, options?: { global?: boolean }): Promise<void> {\n const configuredNames = Object.keys(config.mcpServers ?? {});\n const effectiveBefore = configuredNames.filter(name => isDisabled(name)).join(',');\n if (options?.global) {\n persistGlobalDelta(state => {\n state.allDisabled = disabled;\n if (!disabled) {\n // Enabling globally also clears globally disabled server names so\n // \"/mcp enable all --global\" fully restores global state.\n state.disabledServers.clear();\n }\n });\n } else {\n persistProjectDelta(names => {\n if (disabled) {\n for (const name of configuredNames) {\n names.add(name);\n }\n } else {\n names.clear();\n }\n });\n }\n // Skip the disconnect/reconnect cycle when the effective disabled set is\n // unchanged — e.g. repeating \"/mcp disable all\", or a project-scope\n // \"enable all\" while the global kill switch still disables everything.\n const effectiveAfter = configuredNames.filter(name => isDisabled(name)).join(',');\n if (effectiveAfter !== effectiveBefore) {\n await rebuildConnections();\n }\n },\n\n getDisabledServers() {\n return Object.keys(config.mcpServers ?? {})\n .filter(name => isDisabled(name))\n .sort();\n },\n\n isAllDisabledGlobally() {\n return globalDisableState.allDisabled;\n },\n\n async reconnectServer(name: string): Promise<McpServerStatus> {\n if (isDisabled(name)) {\n return { ...disabledStatus(name), error: `Server \"${name}\" is disabled — enable it first` };\n }\n const cfg = config.mcpServers?.[name];\n if (!cfg) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" not found in config`,\n };\n }\n\n if (!client) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(cfg),\n error: 'MCP client not initialized',\n };\n }\n\n // Use MCPClient's per-server reconnect\n return connectSingleServer(name, cfg, () => client!.reconnectServer(name));\n },\n\n async authenticateServer(\n name: string,\n options?: { onAuthorizationUrl?: (url: string) => void; timeoutMs?: number },\n ): Promise<McpServerStatus> {\n const cfg = config.mcpServers?.[name];\n if (!cfg) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" not found in config`,\n };\n }\n\n if (isDisabled(name)) {\n return { ...disabledStatus(name), error: `Server \"${name}\" is disabled — enable it first` };\n }\n\n if (!client) {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: getTransport(cfg),\n error: 'MCP client not initialized',\n };\n }\n\n if (getTransport(cfg) !== 'http') {\n return {\n name,\n connected: false,\n toolCount: 0,\n toolNames: [],\n transport: 'stdio',\n error: `Server \"${name}\" uses stdio transport, which does not support OAuth`,\n };\n }\n\n // Zero-config provisioning: a bare `url` entry gets a provider with the\n // default redirect URL the first time the user authenticates. Dynamic\n // client registration takes care of the client credentials.\n //\n // NOTE: `serverDefs[name]` is the same object reference the MCPClient was\n // constructed with, and connectHttp reads `authProvider` live off it at\n // connect time, so mutating it here reaches the already-created client.\n // If MCPClient ever defensively copies its server config, zero-config auth\n // would need an explicit \"set this server's provider\" API instead.\n const def = serverDefs[name];\n if (def?.url && !def.authProvider) {\n def.authProvider = createOAuthProvider(name, { ...(cfg as McpHttpServerConfig), oauth: DEFAULT_OAUTH_CONFIG });\n }\n\n // Reject a concurrent second attempt for the same server. authUrlHandlers\n // has a single slot per server, so a second call with an onAuthorizationUrl\n // would overwrite the first caller's handler (which then never sees the\n // URL) and its finally would delete the handler out from under the other\n // in-flight call. Gate on authenticatingServers rather than authUrlHandlers\n // so callers without a URL handler are caught too. The underlying\n // client.authenticate already coalesces same-server calls into one flow.\n if (authenticatingServers.has(name)) {\n const current = serverStatuses.get(name);\n return {\n name,\n connected: current?.connected ?? false,\n connecting: current?.connecting,\n needsAuth: current?.needsAuth,\n toolCount: current?.toolCount ?? 0,\n toolNames: current?.toolNames ?? [],\n transport: current?.transport ?? getTransport(cfg),\n error: `Authentication for \"${name}\" is already in progress`,\n };\n }\n\n if (options?.onAuthorizationUrl) {\n authUrlHandlers.set(name, options.onAuthorizationUrl);\n }\n authenticatingServers.add(name);\n cancelledAuthServers.delete(name);\n try {\n const result = await connectSingleServer(name, cfg, () =>\n client!.authenticate(name, options?.timeoutMs === undefined ? undefined : { timeoutMs: options.timeoutMs }),\n );\n // A cancelled flow resolves with a failed status; mark it so callers can\n // distinguish a deliberate cancel from a genuine authentication failure.\n // Write the marker back to the durable status map (not just the returned\n // value) so a selector reopened after cancellation still sees it.\n const finalStatus =\n cancelledAuthServers.has(name) && !result.connected ? { ...result, cancelled: true } : result;\n serverStatuses.set(name, finalStatus);\n return finalStatus;\n } finally {\n authUrlHandlers.delete(name);\n authenticatingServers.delete(name);\n cancelledAuthServers.delete(name);\n }\n },\n\n async cancelServerAuthentication(name: string): Promise<boolean> {\n if (!client) {\n return false;\n }\n // Record the intent before aborting so the resolving authenticateServer()\n // call can tag its failed status as cancelled rather than failed.\n cancelledAuthServers.add(name);\n const cancelled = await client.cancelAuthentication(name);\n if (!cancelled) {\n cancelledAuthServers.delete(name);\n }\n return cancelled;\n },\n\n disconnect,\n\n getTools() {\n return { ...tools };\n },\n\n hasServers() {\n const hasConfigured = config.mcpServers !== undefined && Object.keys(config.mcpServers).length > 0;\n const hasSkipped = config.skippedServers !== undefined && config.skippedServers.length > 0;\n return hasConfigured || hasSkipped;\n },\n\n getServerStatuses() {\n return Array.from(serverStatuses.values(), withAuthenticating);\n },\n\n getSkippedServers() {\n return [...(config.skippedServers ?? [])];\n },\n\n getConfigPaths() {\n return {\n project: getProjectMcpPath(projectDir, configDirName),\n global: getGlobalMcpPath(configDirName),\n claude: getClaudeSettingsPath(projectDir),\n };\n },\n\n getConfig() {\n return config;\n },\n\n getServerLogs(name: string) {\n return [...(stderrLogs.get(name) ?? [])];\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Persisted MCP disable state — mastracode-owned so user config files
3
+ * (mcp.json, .mcp.json, .claude/settings.local.json) are never mutated.
4
+ *
5
+ * Stored as a single JSON file in the app data dir, with a global section
6
+ * (applies to every project) and per-project entries:
7
+ *
8
+ * {
9
+ * "global": { "allDisabled": true, "disabledServers": ["name"] },
10
+ * "projects": { "/path/to/project": { "disabledServers": ["name"] } }
11
+ * }
12
+ *
13
+ * Disabled names are kept even if the server disappears from config, so a
14
+ * server that is removed and later re-added stays disabled until the user
15
+ * re-enables it.
16
+ */
17
+ /** Global (all-projects) MCP disable state. */
18
+ export interface McpGlobalDisableState {
19
+ /** When true, every MCP server is disabled regardless of per-server state. */
20
+ allDisabled: boolean;
21
+ /** Server names disabled across all projects. */
22
+ disabledServers: string[];
23
+ }
24
+ export declare function getMcpStatePath(): string;
25
+ /** Load the persisted disabled server names for a project. */
26
+ export declare function loadDisabledServers(projectDir: string): string[];
27
+ /** Persist the disabled server names for a project. */
28
+ export declare function saveDisabledServers(projectDir: string, disabledServers: string[]): void;
29
+ /** Load the persisted global disable state (applies to all projects). */
30
+ export declare function loadGlobalDisableState(): McpGlobalDisableState;
31
+ /** Persist the global disable state. Prunes the section when empty. */
32
+ export declare function saveGlobalDisableState(globalState: McpGlobalDisableState): void;
33
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/mcp/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,WAAW,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAgCD,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhE;AAED,uDAAuD;AACvD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CASvF;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,IAAI,qBAAqB,CAM9D;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAc/E"}
@@ -0,0 +1,88 @@
1
+ import { getAppDataDir } from "../utils/project.js";
2
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
3
+ import { dirname, join } from "path";
4
+ //#region src/mcp/state.ts
5
+ /**
6
+ * Persisted MCP disable state — mastracode-owned so user config files
7
+ * (mcp.json, .mcp.json, .claude/settings.local.json) are never mutated.
8
+ *
9
+ * Stored as a single JSON file in the app data dir, with a global section
10
+ * (applies to every project) and per-project entries:
11
+ *
12
+ * {
13
+ * "global": { "allDisabled": true, "disabledServers": ["name"] },
14
+ * "projects": { "/path/to/project": { "disabledServers": ["name"] } }
15
+ * }
16
+ *
17
+ * Disabled names are kept even if the server disappears from config, so a
18
+ * server that is removed and later re-added stays disabled until the user
19
+ * re-enables it.
20
+ */
21
+ function getMcpStatePath() {
22
+ return join(getAppDataDir(), "mcp-state.json");
23
+ }
24
+ function readStateFile() {
25
+ const filePath = getMcpStatePath();
26
+ if (!existsSync(filePath)) return {};
27
+ try {
28
+ const parsed = JSON.parse(readFileSync(filePath, "utf-8"));
29
+ return parsed && typeof parsed === "object" ? parsed : {};
30
+ } catch {
31
+ return {};
32
+ }
33
+ }
34
+ function writeStateFile(state) {
35
+ const filePath = getMcpStatePath();
36
+ const dir = dirname(filePath);
37
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
38
+ const tmpPath = `${filePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
39
+ writeFileSync(tmpPath, JSON.stringify(state, null, 2), "utf-8");
40
+ renameSync(tmpPath, filePath);
41
+ }
42
+ function cleanNames(names) {
43
+ if (!Array.isArray(names)) return [];
44
+ return names.filter((name) => typeof name === "string");
45
+ }
46
+ /** Load the persisted disabled server names for a project. */
47
+ function loadDisabledServers(projectDir) {
48
+ return cleanNames(readStateFile().projects?.[projectDir]?.disabledServers);
49
+ }
50
+ /** Persist the disabled server names for a project. */
51
+ function saveDisabledServers(projectDir, disabledServers) {
52
+ const state = readStateFile();
53
+ const projects = state.projects ?? {};
54
+ if (disabledServers.length > 0) projects[projectDir] = { disabledServers: [...disabledServers].sort() };
55
+ else delete projects[projectDir];
56
+ writeStateFile({
57
+ ...state,
58
+ projects
59
+ });
60
+ }
61
+ /** Load the persisted global disable state (applies to all projects). */
62
+ function loadGlobalDisableState() {
63
+ const global = readStateFile().global;
64
+ return {
65
+ allDisabled: global?.allDisabled === true,
66
+ disabledServers: cleanNames(global?.disabledServers)
67
+ };
68
+ }
69
+ /** Persist the global disable state. Prunes the section when empty. */
70
+ function saveGlobalDisableState(globalState) {
71
+ const state = readStateFile();
72
+ if (!globalState.allDisabled && globalState.disabledServers.length === 0) {
73
+ delete state.global;
74
+ writeStateFile(state);
75
+ return;
76
+ }
77
+ writeStateFile({
78
+ ...state,
79
+ global: {
80
+ ...globalState.allDisabled ? { allDisabled: true } : {},
81
+ ...globalState.disabledServers.length > 0 ? { disabledServers: [...globalState.disabledServers].sort() } : {}
82
+ }
83
+ });
84
+ }
85
+ //#endregion
86
+ export { getMcpStatePath, loadDisabledServers, loadGlobalDisableState, saveDisabledServers, saveGlobalDisableState };
87
+
88
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","names":[],"sources":["../../src/mcp/state.ts"],"sourcesContent":["/**\n * Persisted MCP disable state — mastracode-owned so user config files\n * (mcp.json, .mcp.json, .claude/settings.local.json) are never mutated.\n *\n * Stored as a single JSON file in the app data dir, with a global section\n * (applies to every project) and per-project entries:\n *\n * {\n * \"global\": { \"allDisabled\": true, \"disabledServers\": [\"name\"] },\n * \"projects\": { \"/path/to/project\": { \"disabledServers\": [\"name\"] } }\n * }\n *\n * Disabled names are kept even if the server disappears from config, so a\n * server that is removed and later re-added stays disabled until the user\n * re-enables it.\n */\n\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { getAppDataDir } from '../utils/project.js';\n\ninterface McpStateFile {\n global?: { allDisabled?: boolean; disabledServers?: string[] };\n projects?: Record<string, { disabledServers?: string[] }>;\n}\n\n/** Global (all-projects) MCP disable state. */\nexport interface McpGlobalDisableState {\n /** When true, every MCP server is disabled regardless of per-server state. */\n allDisabled: boolean;\n /** Server names disabled across all projects. */\n disabledServers: string[];\n}\n\nexport function getMcpStatePath(): string {\n return join(getAppDataDir(), 'mcp-state.json');\n}\n\nfunction readStateFile(): McpStateFile {\n const filePath = getMcpStatePath();\n if (!existsSync(filePath)) return {};\n try {\n const parsed = JSON.parse(readFileSync(filePath, 'utf-8'));\n return parsed && typeof parsed === 'object' ? (parsed as McpStateFile) : {};\n } catch {\n return {};\n }\n}\n\nfunction writeStateFile(state: McpStateFile): void {\n const filePath = getMcpStatePath();\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n // Atomic write (same pattern as FileOAuthStorage) so a crash mid-write\n // never leaves a truncated state file. The temp name is process-unique so\n // two concurrent mastracode processes never share a partially written file.\n const tmpPath = `${filePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;\n writeFileSync(tmpPath, JSON.stringify(state, null, 2), 'utf-8');\n renameSync(tmpPath, filePath);\n}\n\nfunction cleanNames(names: unknown): string[] {\n if (!Array.isArray(names)) return [];\n return names.filter((name): name is string => typeof name === 'string');\n}\n\n/** Load the persisted disabled server names for a project. */\nexport function loadDisabledServers(projectDir: string): string[] {\n return cleanNames(readStateFile().projects?.[projectDir]?.disabledServers);\n}\n\n/** Persist the disabled server names for a project. */\nexport function saveDisabledServers(projectDir: string, disabledServers: string[]): void {\n const state = readStateFile();\n const projects = state.projects ?? {};\n if (disabledServers.length > 0) {\n projects[projectDir] = { disabledServers: [...disabledServers].sort() };\n } else {\n delete projects[projectDir];\n }\n writeStateFile({ ...state, projects });\n}\n\n/** Load the persisted global disable state (applies to all projects). */\nexport function loadGlobalDisableState(): McpGlobalDisableState {\n const global = readStateFile().global;\n return {\n allDisabled: global?.allDisabled === true,\n disabledServers: cleanNames(global?.disabledServers),\n };\n}\n\n/** Persist the global disable state. Prunes the section when empty. */\nexport function saveGlobalDisableState(globalState: McpGlobalDisableState): void {\n const state = readStateFile();\n if (!globalState.allDisabled && globalState.disabledServers.length === 0) {\n delete state.global;\n writeStateFile(state);\n return;\n }\n writeStateFile({\n ...state,\n global: {\n ...(globalState.allDisabled ? { allDisabled: true } : {}),\n ...(globalState.disabledServers.length > 0 ? { disabledServers: [...globalState.disabledServers].sort() } : {}),\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,kBAA0B;CACxC,OAAO,KAAK,cAAc,GAAG,gBAAgB;AAC/C;AAEA,SAAS,gBAA8B;CACrC,MAAM,WAAW,gBAAgB;CACjC,IAAI,CAAC,WAAW,QAAQ,GAAG,OAAO,CAAC;CACnC,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;EACzD,OAAO,UAAU,OAAO,WAAW,WAAY,SAA0B,CAAC;CAC5E,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,eAAe,OAA2B;CACjD,MAAM,WAAW,gBAAgB;CACjC,MAAM,MAAM,QAAQ,QAAQ;CAC5B,IAAI,CAAC,WAAW,GAAG,GACjB,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CAKpC,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,IAAI,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE;CAClF,cAAc,SAAS,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,OAAO;CAC9D,WAAW,SAAS,QAAQ;AAC9B;AAEA,SAAS,WAAW,OAA0B;CAC5C,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,OAAO,MAAM,QAAQ,SAAyB,OAAO,SAAS,QAAQ;AACxE;;AAGA,SAAgB,oBAAoB,YAA8B;CAChE,OAAO,WAAW,cAAc,CAAC,CAAC,WAAW,WAAW,EAAE,eAAe;AAC3E;;AAGA,SAAgB,oBAAoB,YAAoB,iBAAiC;CACvF,MAAM,QAAQ,cAAc;CAC5B,MAAM,WAAW,MAAM,YAAY,CAAC;CACpC,IAAI,gBAAgB,SAAS,GAC3B,SAAS,cAAc,EAAE,iBAAiB,CAAC,GAAG,eAAe,CAAC,CAAC,KAAK,EAAE;MAEtE,OAAO,SAAS;CAElB,eAAe;EAAE,GAAG;EAAO;CAAS,CAAC;AACvC;;AAGA,SAAgB,yBAAgD;CAC9D,MAAM,SAAS,cAAc,CAAC,CAAC;CAC/B,OAAO;EACL,aAAa,QAAQ,gBAAgB;EACrC,iBAAiB,WAAW,QAAQ,eAAe;CACrD;AACF;;AAGA,SAAgB,uBAAuB,aAA0C;CAC/E,MAAM,QAAQ,cAAc;CAC5B,IAAI,CAAC,YAAY,eAAe,YAAY,gBAAgB,WAAW,GAAG;EACxE,OAAO,MAAM;EACb,eAAe,KAAK;EACpB;CACF;CACA,eAAe;EACb,GAAG;EACH,QAAQ;GACN,GAAI,YAAY,cAAc,EAAE,aAAa,KAAK,IAAI,CAAC;GACvD,GAAI,YAAY,gBAAgB,SAAS,IAAI,EAAE,iBAAiB,CAAC,GAAG,YAAY,eAAe,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;EAC/G;CACF,CAAC;AACH"}
@@ -103,5 +103,18 @@ export interface McpServerStatus {
103
103
  * The UI uses it to suppress a misleading "Failed to authenticate" message.
104
104
  */
105
105
  cancelled?: boolean;
106
+ /**
107
+ * Whether the user disabled this server. Disabled servers stay visible in
108
+ * status listings (so they can be re-enabled) but are never connected and
109
+ * contribute no tools.
110
+ */
111
+ disabled?: boolean;
112
+ /**
113
+ * Where the disable state comes from when `disabled` is true. `global`
114
+ * means the server (or all of MCP) is disabled across every project and
115
+ * must be re-enabled globally; `project` means only this project disabled
116
+ * it. Global takes precedence when both apply.
117
+ */
118
+ disabledScope?: 'project' | 'global';
106
119
  }
107
120
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mcp/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kEAAkE;IAClE,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wCAAwC;IACxC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mcp/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kEAAkE;IAClE,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wCAAwC;IACxC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CACtC"}
@@ -240,6 +240,17 @@ export declare function defaultVoiceEngine(): VoiceEngine;
240
240
  export declare function getSettingsPath(): string;
241
241
  export declare function getCustomProviderId(name: string): string;
242
242
  export declare function toCustomProviderModelId(providerName: string, modelName: string): string;
243
+ /**
244
+ * The shared gateway catalog namespaces provider keys under their owning
245
+ * gateway id, so a custom provider's models surface in the `/models` catalog
246
+ * as `mastracode/<providerId>/<model>` instead of the canonical
247
+ * `<providerId>/<model>` that model resolution expects. Persisting the
248
+ * gateway-qualified id verbatim breaks lookup later (the provider is parsed
249
+ * as `mastracode`). Strip the prefix before saving — but only when the
250
+ * middle segment matches one of the user's configured custom providers, so
251
+ * legitimate `mastracode/...` gateway-routed ids are left untouched.
252
+ */
253
+ export declare function stripMastraCodeCustomProviderPrefix(modelId: string, customProviders: Array<Pick<CustomProviderSetting, 'name'>>): string;
243
254
  export declare function parseCustomProviders(rawProviders: unknown): CustomProviderSetting[];
244
255
  export declare function migrateLegacyVariedPack(settings: GlobalSettings): boolean;
245
256
  export declare function loadSettings(filePath?: string): GlobalSettings;
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/onboarding/settings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/onboarding/settings.ts"],"names":[],"mappings":"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"}
@@ -160,6 +160,23 @@ function toCustomProviderModelId(providerName, modelName) {
160
160
  if (trimmedModelName.startsWith(providerPrefix)) return trimmedModelName;
161
161
  return `${providerId}/${trimmedModelName}`;
162
162
  }
163
+ /**
164
+ * The shared gateway catalog namespaces provider keys under their owning
165
+ * gateway id, so a custom provider's models surface in the `/models` catalog
166
+ * as `mastracode/<providerId>/<model>` instead of the canonical
167
+ * `<providerId>/<model>` that model resolution expects. Persisting the
168
+ * gateway-qualified id verbatim breaks lookup later (the provider is parsed
169
+ * as `mastracode`). Strip the prefix before saving — but only when the
170
+ * middle segment matches one of the user's configured custom providers, so
171
+ * legitimate `mastracode/...` gateway-routed ids are left untouched.
172
+ */
173
+ function stripMastraCodeCustomProviderPrefix(modelId, customProviders) {
174
+ if (!modelId.startsWith("mastracode/")) return modelId;
175
+ const rest = modelId.slice(11);
176
+ const [providerId, ...modelParts] = rest.split("/");
177
+ if (!providerId || modelParts.length === 0 || modelParts.some((part) => part.length === 0)) return modelId;
178
+ return customProviders.some((provider) => getCustomProviderId(provider.name) === providerId) ? rest : modelId;
179
+ }
163
180
  function parseCustomProviders(rawProviders) {
164
181
  if (!Array.isArray(rawProviders)) return [];
165
182
  const parsedProviders = [];
@@ -651,6 +668,6 @@ async function createBrowserFromSettings(settings) {
651
668
  throw new Error(`Unsupported browser provider: ${provider}`);
652
669
  }
653
670
  //#endregion
654
- export { MASTRA_GATEWAY_DEFAULT_URL, MASTRA_GATEWAY_PROVIDER, MEMORY_GATEWAY_DEFAULT_URL, MEMORY_GATEWAY_PROVIDER, OBSERVABILITY_AUTH_PREFIX, STORAGE_DEFAULTS, THREAD_ACTIVE_MODEL_PACK_ID_KEY, checkProfileProviderMismatch, createBrowserFromSettings, defaultVoiceEngine, getCustomProviderId, getProfileProvider, getSettingsPath, loadSettings, migrateLegacyVariedPack, parseCustomProviders, parseThreadSettings, resolveModelDefaults, resolveOmModel, resolveOmRoleModel, resolveThreadActiveModelPackId, saveSettings, setProfileProvider, toCustomProviderModelId };
671
+ export { MASTRA_GATEWAY_DEFAULT_URL, MASTRA_GATEWAY_PROVIDER, MEMORY_GATEWAY_DEFAULT_URL, MEMORY_GATEWAY_PROVIDER, OBSERVABILITY_AUTH_PREFIX, STORAGE_DEFAULTS, THREAD_ACTIVE_MODEL_PACK_ID_KEY, checkProfileProviderMismatch, createBrowserFromSettings, defaultVoiceEngine, getCustomProviderId, getProfileProvider, getSettingsPath, loadSettings, migrateLegacyVariedPack, parseCustomProviders, parseThreadSettings, resolveModelDefaults, resolveOmModel, resolveOmRoleModel, resolveThreadActiveModelPackId, saveSettings, setProfileProvider, stripMastraCodeCustomProviderPrefix, toCustomProviderModelId };
655
672
 
656
673
  //# sourceMappingURL=settings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","names":[],"sources":["../../src/onboarding/settings.ts"],"sourcesContent":["/**\n * Persistent global settings stored in the app data directory as settings.json.\n * This file persists onboarding state AND user preferences (model choices, yolo, etc.)\n * so they carry across threads and restarts.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { MastraBrowser } from '@mastra/core/browser';\nimport type { LSPConfig } from '@mastra/core/workspace';\nimport { AuthStorage } from '../auth/storage.js';\nimport { buildCodexStagehandFetch, createCodexMiddleware } from '../providers/openai-codex.js';\nimport { getAppDataDir } from '../utils/project.js';\nimport { DEFAULT_STT_PROVIDER, resolveSTTModel } from '../voice/stt-registry.js';\n\n/** A saved custom pack — user-defined model selections for each mode. */\nexport interface CustomPack {\n name: string;\n models: Record<string, string>;\n createdAt: string;\n}\n\n/** A saved custom provider for OpenAI-compatible endpoints. */\nexport interface CustomProviderSetting {\n name: string;\n url: string;\n apiKey?: string;\n models: string[];\n}\n\n/** Storage backend type. */\nexport type StorageBackend = 'libsql' | 'pg';\n\n/** LibSQL-specific storage settings. */\nexport interface LibSQLStorageSettings {\n url?: string;\n authToken?: string;\n}\n\n/** PostgreSQL-specific storage settings. */\nexport interface PgStorageSettings {\n connectionString?: string;\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n password?: string;\n schemaName?: string;\n disableInit?: boolean;\n skipDefaultIndexes?: boolean;\n}\n\n/** Storage configuration persisted in global settings. */\nexport interface StorageSettings {\n /** Which backend to use. Default: 'libsql'. */\n backend: StorageBackend;\n /** LibSQL-specific config (used when backend is 'libsql'). */\n libsql: LibSQLStorageSettings;\n /** PostgreSQL-specific config (used when backend is 'pg'). */\n pg: PgStorageSettings;\n}\n\n/** Gateway provider key used in AuthStorage. */\nexport const MASTRA_GATEWAY_PROVIDER = 'mastra-gateway';\n\n/** Default gateway URL. */\nexport const MASTRA_GATEWAY_DEFAULT_URL = 'https://gateway-api.mastra.ai';\n\n/** @deprecated Renamed to {@link MASTRA_GATEWAY_PROVIDER}. */\nexport const MEMORY_GATEWAY_PROVIDER = MASTRA_GATEWAY_PROVIDER;\n\n/** @deprecated Renamed to {@link MASTRA_GATEWAY_DEFAULT_URL}. */\nexport const MEMORY_GATEWAY_DEFAULT_URL = MASTRA_GATEWAY_DEFAULT_URL;\n\n/** Valid persisted thinking level values. */\nexport type ThinkingLevelSetting = 'off' | 'low' | 'medium' | 'high' | 'xhigh';\n\n/** Browser provider type. */\nexport type BrowserProvider = 'stagehand' | 'agent-browser';\n\n/** Direct TUI `!` shell passthrough mode. */\nexport type ShellPassthroughSettingsMode = 'default' | 'path' | 'login';\n\n/** Direct TUI `!` shell command language. */\nexport type ShellPassthroughSettingsFamily = 'posix' | 'cmd' | 'powershell';\n\n/** Direct TUI `!` shell passthrough configuration. */\nexport interface ShellPassthroughSettings {\n mode?: ShellPassthroughSettingsMode | string;\n executable?: string;\n family?: ShellPassthroughSettingsFamily | string;\n}\n\n/** STT engine: on-device macOS recognizer or a cloud provider. */\nexport type VoiceEngine = 'macos-native' | 'cloud';\n\n/** Voice (hold-space dictation) configuration persisted in global settings. */\nexport interface VoiceSettings {\n /** Whether hold-space voice input is enabled. */\n enabled: boolean;\n /** Which STT engine to use. Defaults to macOS native on darwin, else cloud. */\n engine: VoiceEngine;\n /** Cloud provider id (matches an STT registry entry). Cloud engine only. */\n provider: string;\n /** Cloud model id; defaults to the provider's first registry model. */\n model?: string;\n}\n\n/** Stagehand environment type. */\nexport type StagehandEnv = 'LOCAL' | 'BROWSERBASE';\n\n/** Stagehand-specific browser settings. */\nexport interface StagehandSettings {\n env: StagehandEnv;\n apiKey?: string;\n projectId?: string;\n /** Whether to preserve the user data directory after the browser closes. */\n preserveUserDataDir?: boolean;\n}\n\n/** AgentBrowser-specific browser settings. */\nexport interface AgentBrowserSettings {\n /** Path to a Playwright storage state file (JSON) containing cookies and localStorage. */\n storageState?: string;\n}\n\n/** Browser configuration persisted in global settings. */\nexport interface BrowserSettings {\n /** Whether browser automation is enabled. */\n enabled: boolean;\n /** Which browser provider to use. */\n provider: BrowserProvider;\n /** Whether to run headless (no visible browser window). */\n headless: boolean;\n /** Browser viewport dimensions. */\n viewport?: { width: number; height: number };\n /** CDP URL for connecting to an existing browser. */\n cdpUrl?: string;\n /** Path to a Chrome/Chromium user data directory (profile). */\n profile?: string;\n /** Path to the browser executable to use. */\n executablePath?: string;\n /** Browser scope — 'shared' (all threads share one browser) or 'thread' (each thread gets its own). */\n scope?: 'shared' | 'thread';\n /** Stagehand-specific settings. */\n stagehand?: StagehandSettings;\n /** AgentBrowser-specific settings. */\n agentBrowser?: AgentBrowserSettings;\n}\n\nexport interface GlobalSettings {\n // Onboarding tracking\n onboarding: {\n completedAt: string | null;\n skippedAt: string | null;\n version: number;\n modePackId: string | null;\n omPackId: string | null;\n quietModePreferenceSelected: boolean;\n };\n // Global model preferences (applied to new threads)\n models: {\n /**\n * Active model pack ID. Built-in packs use their id directly (\"anthropic\",\n * \"openai\"). Custom packs use \"custom:<name>\".\n * When set, models are resolved from the pack at startup so pack updates\n * (e.g. new model versions) apply automatically.\n * Cleared when the user manually overrides via /models (falls back to modeDefaults).\n */\n activeModelPackId: string | null;\n /** Explicit per-mode overrides — used when no activeModelPackId is set. */\n modeDefaults: Record<string, string>;\n /**\n * Active OM pack ID (e.g. \"gemini\", \"anthropic\", \"custom\").\n * When set, the OM model is resolved from the pack at startup so pack\n * updates (e.g. new model versions) apply automatically.\n * Cleared when the user manually overrides via /om (falls back to omModelOverride).\n */\n activeOmPackId: string | null;\n /**\n * Shared OM model override — used for both observer and reflector when a\n * role-specific override is not set. Kept for back-compat with older settings\n * files and set by onboarding when the user picks a custom OM pack.\n */\n omModelOverride: string | null;\n /**\n * Explicit Observer model override — takes precedence over `omModelOverride`\n * when set. Written by `/om` when the observer model is changed independently.\n */\n observerModelOverride: string | null;\n /**\n * Explicit Reflector model override — takes precedence over `omModelOverride`\n * when set. Written by `/om` when the reflector model is changed independently.\n */\n reflectorModelOverride: string | null;\n /** Default OM observation threshold used for new threads unless overridden per-thread. */\n omObservationThreshold: number | null;\n /** Default OM reflection threshold used for new threads unless overridden per-thread. */\n omReflectionThreshold: number | null;\n /**\n * Whether observations and reflections use the terse caveman-style instruction.\n * `null` means inherit the built-in default (currently `false` — caveman is\n * opt-in via `/om` settings). Used as the default for new threads unless\n * overridden per-thread.\n */\n omCavemanObservations: boolean | null;\n /**\n * Whether Observational Memory forwards image/file attachment parts to the\n * Observer LLM. `null` ⇒ inherit built-in default ('auto'). 'auto' checks\n * model capabilities; true/false forces the setting.\n */\n omObserveAttachments: 'auto' | boolean | null;\n /** Per-agent-type subagent model overrides (e.g. { explore: \"openai/gpt-5.1-codex-mini\" }) */\n subagentModels: Record<string, string>;\n /** Default judge model for /goal. */\n goalJudgeModel: string | null;\n /** Default max attempts for /goal. */\n goalMaxTurns: number | null;\n };\n // Global behavior preferences\n preferences: {\n yolo: boolean | null;\n theme: 'auto' | 'dark' | 'light';\n /** Default reasoning effort level used for all threads/models unless overridden in-session. */\n thinkingLevel: ThinkingLevelSetting;\n /** When true, components like subagent output collapse to compact summaries on completion. */\n quietMode: boolean;\n /** Maximum quiet-mode detail preview lines for compact tool calls. Set to 0 to hide previews. */\n quietModeMaxToolPreviewLines: number;\n };\n // Storage backend configuration\n storage: StorageSettings;\n // User-created custom model packs\n customModelPacks: CustomPack[];\n // User-created custom providers with custom models\n customProviders: CustomProviderSetting[];\n // Model usage counts for ranking in the selector\n modelUseCounts: Record<string, number>;\n // Version the user dismissed the update prompt for (skip until they manually update past this)\n updateDismissedVersion: string | null;\n // Mastra gateway configuration\n memoryGateway: { baseUrl?: string };\n // LSP configuration forwarded to the workspace\n lsp?: LSPConfig;\n // Browser automation configuration\n browser: BrowserSettings;\n // Direct TUI `!` shell passthrough configuration\n shellPassthrough: ShellPassthroughSettings;\n // Hold-space voice input configuration\n voice: VoiceSettings;\n // Signal routing configuration\n signals: SignalSettings;\n // Cloud observability configuration (per-resource project IDs; tokens stored in auth.json)\n observability: ObservabilitySettings;\n}\n\nexport interface SignalSettings {\n /** Opt into local Unix socket PubSub for cross-process signal routing. */\n unixSocketPubSub: boolean;\n /** Experimental: enable GitHub PR subscription signals backed by gitcrawl. */\n experimentalGithubSignals: boolean;\n}\n\nexport interface ObservabilityResourceConfig {\n /** Cloud project ID for this resource */\n projectId: string;\n /** When this config was created */\n configuredAt: string;\n}\n\nexport interface ObservabilitySettings {\n /** Per-resource cloud project configs, keyed by resourceId */\n resources: Record<string, ObservabilityResourceConfig>;\n /** Whether to store traces locally in DuckDB. Off by default to avoid disk usage. */\n localTracing: boolean;\n}\n\n/** Auth key prefix for observability tokens stored per-resource in auth.json */\nexport const OBSERVABILITY_AUTH_PREFIX = 'observability:';\n\nexport const STORAGE_DEFAULTS: StorageSettings = {\n backend: 'libsql',\n libsql: {},\n pg: {},\n};\n\n/** Default STT engine: on-device macOS recognizer where available, else cloud. */\nexport function defaultVoiceEngine(): VoiceEngine {\n return process.platform === 'darwin' ? 'macos-native' : 'cloud';\n}\n\nconst DEFAULTS: GlobalSettings = {\n onboarding: {\n completedAt: null,\n skippedAt: null,\n version: 0,\n modePackId: null,\n omPackId: null,\n quietModePreferenceSelected: true,\n },\n models: {\n activeModelPackId: null,\n modeDefaults: {},\n activeOmPackId: null,\n omModelOverride: null,\n observerModelOverride: null,\n reflectorModelOverride: null,\n omObservationThreshold: null,\n omReflectionThreshold: null,\n omCavemanObservations: null,\n omObserveAttachments: null,\n subagentModels: {},\n goalJudgeModel: null,\n goalMaxTurns: null,\n },\n preferences: {\n yolo: null,\n theme: 'auto',\n thinkingLevel: 'off',\n quietMode: false,\n quietModeMaxToolPreviewLines: 2,\n },\n storage: { ...STORAGE_DEFAULTS },\n customModelPacks: [],\n customProviders: [],\n modelUseCounts: {},\n updateDismissedVersion: null,\n memoryGateway: {},\n lsp: {},\n browser: {\n enabled: false,\n provider: 'stagehand',\n headless: false,\n viewport: { width: 1280, height: 720 },\n stagehand: { env: 'LOCAL' },\n },\n shellPassthrough: { mode: 'default' },\n voice: { enabled: false, engine: defaultVoiceEngine(), provider: DEFAULT_STT_PROVIDER },\n signals: { unixSocketPubSub: false, experimentalGithubSignals: false },\n observability: { resources: {}, localTracing: false },\n};\n\nconst THINKING_LEVEL_VALUES: ThinkingLevelSetting[] = ['off', 'low', 'medium', 'high', 'xhigh'];\nconst QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX = 8;\nconst loadedSignalSettings = new WeakMap<GlobalSettings, SignalSettings>();\n\nfunction cloneSignalSettings(signals: SignalSettings): SignalSettings {\n return { ...signals };\n}\n\nfunction rememberLoadedSettings(settings: GlobalSettings): GlobalSettings {\n loadedSignalSettings.set(settings, cloneSignalSettings(settings.signals));\n return settings;\n}\n\nfunction signalSettingsEqual(left: SignalSettings, right: SignalSettings): boolean {\n return (\n left.unixSocketPubSub === right.unixSocketPubSub &&\n left.experimentalGithubSignals === right.experimentalGithubSignals\n );\n}\n\nfunction parseThinkingLevel(value: unknown): ThinkingLevelSetting {\n return typeof value === 'string' && THINKING_LEVEL_VALUES.includes(value as ThinkingLevelSetting)\n ? (value as ThinkingLevelSetting)\n : DEFAULTS.preferences.thinkingLevel;\n}\n\nfunction parseQuietModeMaxToolPreviewLines(value: unknown): number {\n const rawValue =\n typeof value === 'number' && Number.isFinite(value) ? value : DEFAULTS.preferences.quietModeMaxToolPreviewLines;\n return Math.min(QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX, Math.max(0, Math.floor(rawValue)));\n}\n\nfunction parsePreferences(rawPreferences: unknown): GlobalSettings['preferences'] {\n const raw = rawPreferences && typeof rawPreferences === 'object' ? (rawPreferences as Record<string, unknown>) : {};\n\n return {\n ...DEFAULTS.preferences,\n ...raw,\n thinkingLevel: parseThinkingLevel(raw.thinkingLevel),\n quietModeMaxToolPreviewLines: parseQuietModeMaxToolPreviewLines(raw.quietModeMaxToolPreviewLines),\n };\n}\n\nfunction parseSignalSettings(rawSignals: unknown): SignalSettings {\n const raw = rawSignals && typeof rawSignals === 'object' ? (rawSignals as Record<string, unknown>) : {};\n return {\n unixSocketPubSub:\n typeof raw.unixSocketPubSub === 'boolean' ? raw.unixSocketPubSub : DEFAULTS.signals.unixSocketPubSub,\n experimentalGithubSignals:\n typeof raw.experimentalGithubSignals === 'boolean'\n ? raw.experimentalGithubSignals\n : DEFAULTS.signals.experimentalGithubSignals,\n };\n}\n\nfunction hasQuietModePreferenceSelected(rawOnboarding: unknown): boolean {\n return Boolean(\n rawOnboarding &&\n typeof rawOnboarding === 'object' &&\n Object.prototype.hasOwnProperty.call(rawOnboarding, 'quietModePreferenceSelected'),\n );\n}\n\nfunction applyQuietModePreferenceRollout(settings: GlobalSettings, rawOnboarding: unknown): void {\n if (hasQuietModePreferenceSelected(rawOnboarding)) return;\n settings.onboarding.quietModePreferenceSelected = settings.preferences.quietMode === true;\n}\n\nfunction getNewInstallDefaults(): GlobalSettings {\n const settings = structuredClone(DEFAULTS);\n settings.preferences.quietMode = true;\n settings.onboarding.quietModePreferenceSelected = true;\n return settings;\n}\n\nexport function getSettingsPath(): string {\n return join(getAppDataDir(), 'settings.json');\n}\n\nexport function getCustomProviderId(name: string): string {\n const slug = name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || 'provider';\n}\n\nexport function toCustomProviderModelId(providerName: string, modelName: string): string {\n const providerId = getCustomProviderId(providerName);\n const trimmedModelName = modelName.trim();\n const providerPrefix = `${providerId}/`;\n if (trimmedModelName.startsWith(providerPrefix)) {\n return trimmedModelName;\n }\n return `${providerId}/${trimmedModelName}`;\n}\n\nexport function parseCustomProviders(rawProviders: unknown): CustomProviderSetting[] {\n if (!Array.isArray(rawProviders)) return [];\n\n const parsedProviders: CustomProviderSetting[] = [];\n for (const rawProvider of rawProviders) {\n if (!rawProvider || typeof rawProvider !== 'object') continue;\n\n const candidate = rawProvider as Record<string, unknown>;\n const name = typeof candidate.name === 'string' ? candidate.name.trim() : '';\n const url = typeof candidate.url === 'string' ? candidate.url.trim() : '';\n if (!name || !url) continue;\n\n const providerId = getCustomProviderId(name);\n const models = Array.isArray(candidate.models)\n ? [\n ...new Set(\n candidate.models\n .filter((model): model is string => typeof model === 'string')\n .map(model => model.trim())\n .map(model => {\n const providerPrefix = `${providerId}/`;\n if (model.startsWith(providerPrefix)) {\n return model.slice(providerPrefix.length);\n }\n return model;\n }),\n ),\n ].filter(model => model.length > 0)\n : [];\n\n const apiKey =\n typeof candidate.apiKey === 'string' && candidate.apiKey.trim().length > 0 ? candidate.apiKey.trim() : undefined;\n\n parsedProviders.push({\n name,\n url,\n ...(apiKey ? { apiKey } : {}),\n models,\n });\n }\n\n return parsedProviders;\n}\n\nconst BROWSER_PROVIDERS = new Set<BrowserProvider>(['stagehand', 'agent-browser']);\nconst STAGEHAND_ENVS = new Set<StagehandEnv>(['LOCAL', 'BROWSERBASE']);\n\n/**\n * Deep-merge and validate browser settings from JSON.\n * Explicitly validates types to handle malformed settings.json gracefully.\n */\nfunction parseBrowserSettings(rawBrowser: unknown): BrowserSettings {\n const raw = rawBrowser && typeof rawBrowser === 'object' ? (rawBrowser as Record<string, unknown>) : {};\n const rawViewport = raw.viewport && typeof raw.viewport === 'object' ? (raw.viewport as Record<string, unknown>) : {};\n const rawStagehand =\n raw.stagehand && typeof raw.stagehand === 'object' ? (raw.stagehand as Record<string, unknown>) : {};\n const rawAgentBrowser =\n raw.agentBrowser && typeof raw.agentBrowser === 'object' ? (raw.agentBrowser as Record<string, unknown>) : {};\n\n return {\n enabled: typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULTS.browser.enabled,\n provider:\n typeof raw.provider === 'string' && BROWSER_PROVIDERS.has(raw.provider as BrowserProvider)\n ? (raw.provider as BrowserProvider)\n : DEFAULTS.browser.provider,\n headless: typeof raw.headless === 'boolean' ? raw.headless : DEFAULTS.browser.headless,\n cdpUrl: typeof raw.cdpUrl === 'string' && raw.cdpUrl.trim() ? raw.cdpUrl.trim() : undefined,\n profile: typeof raw.profile === 'string' && raw.profile.trim() ? raw.profile.trim() : undefined,\n executablePath:\n typeof raw.executablePath === 'string' && raw.executablePath.trim() ? raw.executablePath.trim() : undefined,\n viewport: {\n width: typeof rawViewport.width === 'number' ? rawViewport.width : DEFAULTS.browser.viewport!.width,\n height: typeof rawViewport.height === 'number' ? rawViewport.height : DEFAULTS.browser.viewport!.height,\n },\n scope: typeof raw.scope === 'string' && (raw.scope === 'shared' || raw.scope === 'thread') ? raw.scope : undefined,\n stagehand: {\n env:\n typeof rawStagehand.env === 'string' && STAGEHAND_ENVS.has(rawStagehand.env as StagehandEnv)\n ? (rawStagehand.env as StagehandEnv)\n : DEFAULTS.browser.stagehand!.env,\n ...(typeof rawStagehand.apiKey === 'string' && rawStagehand.apiKey.trim()\n ? { apiKey: rawStagehand.apiKey.trim() }\n : {}),\n ...(typeof rawStagehand.projectId === 'string' && rawStagehand.projectId.trim()\n ? { projectId: rawStagehand.projectId.trim() }\n : {}),\n ...(typeof rawStagehand.preserveUserDataDir === 'boolean'\n ? { preserveUserDataDir: rawStagehand.preserveUserDataDir }\n : {}),\n },\n agentBrowser:\n typeof rawAgentBrowser.storageState === 'string' && rawAgentBrowser.storageState.trim()\n ? { storageState: rawAgentBrowser.storageState.trim() }\n : undefined,\n };\n}\n\nfunction parseShellPassthroughSettings(rawShellPassthrough: unknown): ShellPassthroughSettings {\n const raw =\n rawShellPassthrough && typeof rawShellPassthrough === 'object'\n ? (rawShellPassthrough as Record<string, unknown>)\n : {};\n const executable = typeof raw.executable === 'string' && raw.executable.trim() ? raw.executable.trim() : undefined;\n const family = typeof raw.family === 'string' && raw.family.trim() ? raw.family.trim() : undefined;\n const mode = typeof raw.mode === 'string' && raw.mode.trim() ? raw.mode.trim() : undefined;\n const defaultMode = executable ? undefined : DEFAULTS.shellPassthrough.mode;\n\n return {\n ...((mode ?? defaultMode) ? { mode: mode ?? defaultMode } : {}),\n ...(executable ? { executable } : {}),\n ...(family ? { family } : {}),\n };\n}\n\nfunction parseVoiceSettings(rawVoice: unknown): VoiceSettings {\n const raw = rawVoice && typeof rawVoice === 'object' ? (rawVoice as Record<string, unknown>) : {};\n const enabled = typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULTS.voice.enabled;\n const engine: VoiceEngine =\n raw.engine === 'macos-native' || raw.engine === 'cloud' ? raw.engine : defaultVoiceEngine();\n // Validate provider/model against the registry, falling back to a usable entry\n // so old `{ enabled }`-only files and unknown values still resolve cleanly.\n const provider = typeof raw.provider === 'string' ? raw.provider : DEFAULTS.voice.provider;\n const model = typeof raw.model === 'string' ? raw.model : undefined;\n const resolved = resolveSTTModel(provider, model);\n return {\n enabled,\n engine,\n provider: resolved.provider,\n model: resolved.model,\n };\n}\n\nconst VALID_PROJECT_ID = /^[a-zA-Z0-9_-]+$/;\n\nfunction parseObservabilitySettings(raw: unknown): ObservabilitySettings {\n if (!raw || typeof raw !== 'object') return { resources: {}, localTracing: false };\n const obj = raw as Record<string, unknown>;\n const localTracing = obj.localTracing === true;\n const rawResources = obj.resources;\n if (!rawResources || typeof rawResources !== 'object') return { resources: {}, localTracing };\n const resources: Record<string, ObservabilityResourceConfig> = {};\n for (const [key, val] of Object.entries(rawResources as Record<string, unknown>)) {\n if (val && typeof val === 'object') {\n const v = val as Record<string, unknown>;\n if (typeof v.projectId === 'string' && VALID_PROJECT_ID.test(v.projectId)) {\n resources[key] = {\n projectId: v.projectId,\n configuredAt: typeof v.configuredAt === 'string' ? v.configuredAt : new Date().toISOString(),\n };\n }\n }\n }\n return { resources, localTracing };\n}\n\n/**\n * One-time migration: move model-related data from auth.json to settings.json.\n * Reads `_modelRanks`, `_modeModelId_*`, `_subagentModelId*` from auth.json,\n * merges them into settings, removes them from auth.json, and writes both files.\n * No-ops if auth.json has no _ prefixed model data.\n */\nfunction migrateFromAuth(settingsPath: string): boolean {\n const authPath = join(getAppDataDir(), 'auth.json');\n if (!existsSync(authPath)) return false;\n\n let authData: Record<string, any>;\n try {\n authData = JSON.parse(readFileSync(authPath, 'utf-8'));\n } catch {\n return false;\n }\n\n const modelKeys = Object.keys(authData).filter(k => k.startsWith('_'));\n if (modelKeys.length === 0) return false;\n\n // Load existing settings (or defaults) and merge auth data into it\n let settings: GlobalSettings;\n if (existsSync(settingsPath)) {\n try {\n const raw = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n settings = {\n onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },\n models: { ...DEFAULTS.models, ...raw.models },\n preferences: parsePreferences(raw.preferences),\n storage: {\n ...STORAGE_DEFAULTS,\n ...raw.storage,\n libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },\n pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg },\n },\n customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],\n customProviders: parseCustomProviders(raw.customProviders),\n modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === 'object' ? raw.modelUseCounts : {},\n updateDismissedVersion: typeof raw.updateDismissedVersion === 'string' ? raw.updateDismissedVersion : null,\n memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === 'object' ? raw.memoryGateway : {},\n lsp: raw.lsp && typeof raw.lsp === 'object' ? (raw.lsp as LSPConfig) : undefined,\n browser: parseBrowserSettings(raw.browser),\n shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),\n voice: parseVoiceSettings(raw.voice),\n signals: parseSignalSettings(raw.signals),\n observability: parseObservabilitySettings(raw.observability),\n };\n applyQuietModePreferenceRollout(settings, raw.onboarding);\n } catch {\n settings = structuredClone(DEFAULTS);\n }\n } else {\n settings = structuredClone(DEFAULTS);\n }\n\n // Migrate model use counts (only if settings doesn't already have them)\n if (authData._modelRanks && typeof authData._modelRanks === 'object') {\n settings.modelUseCounts = { ...authData._modelRanks, ...settings.modelUseCounts };\n }\n\n // Migrate per-mode model defaults (don't overwrite existing settings)\n for (const key of modelKeys) {\n const modeMatch = key.match(/^_modeModelId_(.+)$/);\n if (modeMatch?.[1] && typeof authData[key] === 'string' && !settings.models.modeDefaults[modeMatch[1]]) {\n settings.models.modeDefaults[modeMatch[1]] = authData[key];\n }\n }\n\n // Migrate subagent models (don't overwrite existing settings)\n for (const key of modelKeys) {\n if (key === '_subagentModelId' && typeof authData[key] === 'string' && !settings.models.subagentModels['default']) {\n settings.models.subagentModels['default'] = authData[key];\n }\n const saMatch = key.match(/^_subagentModelId_(.+)$/);\n if (saMatch?.[1] && typeof authData[key] === 'string' && !settings.models.subagentModels[saMatch[1]]) {\n settings.models.subagentModels[saMatch[1]] = authData[key];\n }\n }\n\n // Write migrated settings\n saveSettings(settings, settingsPath);\n\n // Clean up auth.json — remove _ prefixed keys\n for (const key of modelKeys) {\n delete authData[key];\n }\n try {\n writeFileSync(authPath, JSON.stringify(authData, null, 2), 'utf-8');\n } catch {\n // Non-fatal — settings are saved, auth cleanup can fail\n }\n\n return true;\n}\n\nconst LEGACY_VARIED_MODELS: Record<string, string> = {\n plan: 'openai/gpt-5.4',\n build: 'anthropic/claude-sonnet-4-5',\n fast: 'anthropic/claude-haiku-4-5',\n};\n\nexport function migrateLegacyVariedPack(settings: GlobalSettings): boolean {\n const legacyPackId = 'varied';\n const customPackId = 'custom:varied';\n const hasLegacyReference =\n settings.models.activeModelPackId === legacyPackId || settings.onboarding.modePackId === legacyPackId;\n\n if (!hasLegacyReference) return false;\n\n const existingIdx = settings.customModelPacks.findIndex(p => p.name === 'varied');\n if (existingIdx >= 0) {\n const existing = settings.customModelPacks[existingIdx]!;\n const modelsMatch = Object.entries(LEGACY_VARIED_MODELS).every(([k, v]) => existing.models[k] === v);\n if (!modelsMatch) {\n existing.models = { ...LEGACY_VARIED_MODELS };\n }\n } else {\n settings.customModelPacks.push({\n name: 'varied',\n models: { ...LEGACY_VARIED_MODELS },\n createdAt: new Date().toISOString(),\n });\n }\n\n if (settings.models.activeModelPackId === legacyPackId) {\n settings.models.activeModelPackId = customPackId;\n if (Object.keys(settings.models.modeDefaults).length === 0) {\n settings.models.modeDefaults = { ...LEGACY_VARIED_MODELS };\n }\n }\n\n if (settings.onboarding.modePackId === legacyPackId) {\n settings.onboarding.modePackId = customPackId;\n }\n\n return true;\n}\n\nexport function loadSettings(filePath: string = getSettingsPath()): GlobalSettings {\n // One-time migration: move model data from auth.json into settings.json\n migrateFromAuth(filePath);\n\n if (!existsSync(filePath)) return rememberLoadedSettings(getNewInstallDefaults());\n try {\n const raw = JSON.parse(readFileSync(filePath, 'utf-8'));\n // Spread raw first to preserve unknown top-level keys (forward-compatibility),\n // then overlay with parsed/typed fields so known keys are always correct.\n const settings: GlobalSettings = {\n ...raw,\n onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },\n models: { ...DEFAULTS.models, ...raw.models },\n preferences: parsePreferences(raw.preferences),\n storage: {\n ...STORAGE_DEFAULTS,\n ...raw.storage,\n libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },\n pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg },\n },\n customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],\n customProviders: parseCustomProviders(raw.customProviders),\n modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === 'object' ? raw.modelUseCounts : {},\n updateDismissedVersion: typeof raw.updateDismissedVersion === 'string' ? raw.updateDismissedVersion : null,\n memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === 'object' ? raw.memoryGateway : {},\n lsp: raw.lsp && typeof raw.lsp === 'object' ? (raw.lsp as LSPConfig) : undefined,\n browser: parseBrowserSettings(raw.browser),\n shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),\n voice: parseVoiceSettings(raw.voice),\n signals: parseSignalSettings(raw.signals),\n observability: parseObservabilitySettings(raw.observability),\n };\n\n // Migrate legacy omModelId → omModelOverride\n let settingsChanged = false;\n if (!hasQuietModePreferenceSelected(raw.onboarding)) {\n applyQuietModePreferenceRollout(settings, raw.onboarding);\n settingsChanged = true;\n }\n if (raw.models?.omModelId && !settings.models.omModelOverride) {\n settings.models.omModelOverride = raw.models.omModelId;\n settingsChanged = true;\n }\n\n if (migrateLegacyVariedPack(settings)) {\n settingsChanged = true;\n }\n\n if (settingsChanged) {\n saveSettings(settings, filePath);\n }\n\n return rememberLoadedSettings(settings);\n } catch {\n return rememberLoadedSettings(structuredClone(DEFAULTS));\n }\n}\n\nexport const THREAD_ACTIVE_MODEL_PACK_ID_KEY = 'activeModelPackId';\n\nexport interface ThreadSettings {\n activeModelPackId: string | null;\n modeModelIds: Record<string, string>;\n}\n\nexport function parseThreadSettings(metadata: Record<string, unknown> | undefined): ThreadSettings {\n const modeModelIds: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n const modeMatch = key.match(/^modeModelId_(.+)$/);\n if (modeMatch?.[1] && typeof value === 'string' && value.length > 0) {\n modeModelIds[modeMatch[1]] = value;\n }\n }\n\n const rawPackId = metadata?.[THREAD_ACTIVE_MODEL_PACK_ID_KEY];\n const activeModelPackId = typeof rawPackId === 'string' && rawPackId.length > 0 ? rawPackId : null;\n\n return {\n activeModelPackId,\n modeModelIds,\n };\n}\n\n/**\n * Resolve active model pack id for the current thread.\n *\n * Priority:\n * 1) explicit thread metadata activeModelPackId\n * 2) inferred from thread modeModelId_* values\n * 3) global settings.models.activeModelPackId\n */\nexport function resolveThreadActiveModelPackId(\n settings: GlobalSettings,\n builtinPacks: Array<{ id: string; models: Record<string, string> }>,\n metadata: Record<string, unknown> | undefined,\n): string | null {\n const threadSettings = parseThreadSettings(metadata);\n\n const isKnownPack = (packId: string): boolean => {\n if (packId.startsWith('custom:')) {\n const name = packId.slice('custom:'.length);\n return settings.customModelPacks.some(p => p.name === name);\n }\n return builtinPacks.some(p => p.id === packId);\n };\n\n if (threadSettings.activeModelPackId && isKnownPack(threadSettings.activeModelPackId)) {\n return threadSettings.activeModelPackId;\n }\n\n const allPacks: Array<{ id: string; models: Record<string, string> }> = [\n ...builtinPacks,\n ...settings.customModelPacks.map(p => ({ id: `custom:${p.name}`, models: p.models })),\n ];\n\n for (const pack of allPacks) {\n const packEntries = Object.entries(pack.models);\n const threadEntries = Object.keys(threadSettings.modeModelIds);\n const matches =\n packEntries.length === threadEntries.length &&\n packEntries.every(([modeId, modelId]) => threadSettings.modeModelIds[modeId] === modelId);\n if (matches) return pack.id;\n }\n\n if (settings.models.activeModelPackId && isKnownPack(settings.models.activeModelPackId)) {\n return settings.models.activeModelPackId;\n }\n\n return null;\n}\n\n/**\n * Resolve effective per-mode model defaults.\n *\n * If `activeModelPackId` is set, looks up the pack (built-in or custom) and\n * returns its models. Falls back to the explicit `modeDefaults` map.\n *\n * @param settings The loaded global settings.\n * @param builtinPacks Built-in packs for the current provider access\n * (from `getAvailableModePacks`). Pass `[]` if unavailable.\n */\nexport function resolveModelDefaults(\n settings: GlobalSettings,\n builtinPacks: Array<{ id: string; models: Record<string, string> }>,\n): Record<string, string> {\n const { activeModelPackId, modeDefaults } = settings.models;\n if (!activeModelPackId) return modeDefaults;\n\n // Custom pack: \"custom:<name>\"\n if (activeModelPackId.startsWith('custom:')) {\n const name = activeModelPackId.slice('custom:'.length);\n const pack = settings.customModelPacks.find(p => p.name === name);\n if (pack) return pack.models;\n // Custom pack was deleted — fall through to modeDefaults\n return modeDefaults;\n }\n\n // Built-in pack\n const builtin = builtinPacks.find(p => p.id === activeModelPackId);\n if (builtin) return builtin.models;\n\n // Unknown pack id — fall through\n return modeDefaults;\n}\n\n/**\n * Resolve the effective model ID for one of the two OM roles.\n *\n * Lookup order:\n * 1. The role-specific override (`observerModelOverride` /\n * `reflectorModelOverride`) if set.\n * 2. If `activeOmPackId` points at a built-in pack, that pack's model.\n * 3. The shared `omModelOverride` fallback.\n *\n * @param settings The loaded global settings.\n * @param role Which OM role to resolve (`'observer'` or `'reflector'`).\n * @param builtinOmPacks Built-in OM packs for the current provider access\n * (from `getAvailableOmPacks`). Pass `[]` if unavailable.\n */\nexport function resolveOmRoleModel(\n settings: GlobalSettings,\n role: 'observer' | 'reflector',\n builtinOmPacks: Array<{ id: string; modelId: string }>,\n): string | null {\n const { activeOmPackId, omModelOverride, observerModelOverride, reflectorModelOverride } = settings.models;\n const roleOverride = role === 'observer' ? observerModelOverride : reflectorModelOverride;\n if (roleOverride) return roleOverride;\n\n if (!activeOmPackId) return omModelOverride;\n if (activeOmPackId === 'custom') return omModelOverride;\n\n const pack = builtinOmPacks.find(p => p.id === activeOmPackId);\n if (pack) return pack.modelId;\n\n return omModelOverride;\n}\n\n/**\n * @deprecated Use `resolveOmRoleModel(settings, 'observer' | 'reflector', ...)`.\n * Equivalent to resolving the observer role (existing callers set both observer\n * and reflector to the same value).\n */\nexport function resolveOmModel(\n settings: GlobalSettings,\n builtinOmPacks: Array<{ id: string; modelId: string }>,\n): string | null {\n return resolveOmRoleModel(settings, 'observer', builtinOmPacks);\n}\n\nfunction getSignalSettingsForSave(settings: GlobalSettings, filePath: string): SignalSettings {\n const loadedSignals = loadedSignalSettings.get(settings);\n if (!loadedSignals || !signalSettingsEqual(settings.signals, loadedSignals) || !existsSync(filePath)) {\n return settings.signals;\n }\n\n try {\n const currentRaw = JSON.parse(readFileSync(filePath, 'utf-8')) as Record<string, unknown>;\n const currentSignals = parseSignalSettings(currentRaw.signals);\n if (!signalSettingsEqual(currentSignals, loadedSignals)) {\n return currentSignals;\n }\n } catch {\n // If the current file is unreadable, fall back to the caller's settings.\n }\n\n return settings.signals;\n}\n\nexport function saveSettings(settings: GlobalSettings, filePath: string = getSettingsPath()): void {\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const signals = getSignalSettingsForSave(settings, filePath);\n settings.signals = signals;\n loadedSignalSettings.set(settings, cloneSignalSettings(signals));\n writeFileSync(filePath, JSON.stringify(settings, null, 2), 'utf-8');\n}\n\n/** Marker file name to track which provider last used a profile. */\nconst PROFILE_PROVIDER_MARKER = '.mastra-provider';\n\n/**\n * Check which provider last used a profile directory.\n * Returns the provider name if the marker exists, undefined otherwise.\n */\nexport function getProfileProvider(profilePath: string): BrowserProvider | undefined {\n const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);\n if (!existsSync(markerPath)) {\n return undefined;\n }\n try {\n const content = readFileSync(markerPath, 'utf-8').trim();\n if (content === 'stagehand' || content === 'agent-browser') {\n return content;\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Write the provider marker to a profile directory.\n * Creates the directory if it doesn't exist.\n */\nexport function setProfileProvider(profilePath: string, provider: BrowserProvider): void {\n const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);\n if (!existsSync(profilePath)) {\n mkdirSync(profilePath, { recursive: true });\n }\n writeFileSync(markerPath, provider, 'utf-8');\n}\n\n/**\n * Check if a profile has a provider mismatch.\n * Returns the existing provider if there's a mismatch, undefined otherwise.\n */\nexport function checkProfileProviderMismatch(\n profilePath: string | undefined,\n targetProvider: BrowserProvider,\n): BrowserProvider | undefined {\n if (!profilePath) {\n return undefined;\n }\n const existingProvider = getProfileProvider(profilePath);\n if (existingProvider && existingProvider !== targetProvider) {\n return existingProvider;\n }\n return undefined;\n}\n\nfunction browserRecordingOptions() {\n return { outputDir: join(getAppDataDir(), 'browser-recordings') };\n}\n\n/**\n * Create a browser instance from settings.\n * Shared by startup (main.ts) and live reconfiguration (/browser command).\n * Returns undefined if browser is disabled.\n */\nexport async function createBrowserFromSettings(settings: BrowserSettings): Promise<MastraBrowser | undefined> {\n if (!settings.enabled) {\n return undefined;\n }\n\n const { provider, headless, viewport, cdpUrl, profile, executablePath, stagehand, agentBrowser } = settings;\n\n // Chrome only allows one process per profile directory, so force 'shared' scope\n // when a profile is set. Otherwise use the user's setting (or provider default).\n const scope = profile ? ('shared' as const) : settings.scope;\n\n // Common launch options (no CDP)\n const launchConfig = { headless, viewport, profile, executablePath, scope } as const;\n\n if (provider === 'stagehand') {\n const { StagehandBrowser } = await import('@mastra/stagehand');\n const stagehandOpts: Record<string, unknown> = {\n env: stagehand?.env ?? 'LOCAL',\n apiKey: stagehand?.apiKey ?? process.env.BROWSERBASE_API_KEY,\n projectId: stagehand?.projectId ?? process.env.BROWSERBASE_PROJECT_ID,\n preserveUserDataDir: stagehand?.preserveUserDataDir,\n recording: browserRecordingOptions(),\n };\n\n // When the user has an active OpenAI Codex (ChatGPT) subscription, route\n // Stagehand through the Codex endpoint. We use the AI SDK provider's\n // standard hooks (baseURL, headers, fetch, and middleware) instead of a\n // URL-rewriting fetch:\n // - baseURL: target Codex's Responses API directly (no URL rewriting).\n // - headers: static Codex identifiers (originator, UA, account id).\n // - fetch: a tiny refresher that injects the live OAuth bearer per call,\n // since AI SDK takes `apiKey` as a static string.\n // - middleware: createCodexMiddleware() sets `store: false`, which Codex\n // requires on every request.\n // Model is `gpt-5.4-mini`, the current ChatGPT-sign-in Codex whitelist\n // pick suited to Stagehand's vision + structured-output workload.\n const authStorage = new AuthStorage();\n const cred = authStorage.get('openai-codex');\n if (cred?.type === 'oauth') {\n const accountId = (cred as any).accountId as string | undefined;\n stagehandOpts.model = {\n modelName: 'openai/gpt-5.4-mini',\n apiKey: 'codex-oauth',\n baseURL: 'https://chatgpt.com/backend-api/codex',\n headers: {\n originator: 'mastracode',\n 'User-Agent': 'mastracode',\n ...(accountId ? { 'ChatGPT-Account-ID': accountId } : {}),\n },\n fetch: buildCodexStagehandFetch(authStorage),\n middleware: createCodexMiddleware(),\n } as any;\n }\n\n return cdpUrl\n ? new StagehandBrowser({ ...launchConfig, cdpUrl, scope: 'shared', ...stagehandOpts })\n : new StagehandBrowser({ ...launchConfig, ...stagehandOpts });\n } else if (provider === 'agent-browser') {\n const { AgentBrowser } = await import('@mastra/agent-browser');\n const agentBrowserOpts = {\n storageState: agentBrowser?.storageState,\n recording: browserRecordingOptions(),\n };\n return cdpUrl\n ? new AgentBrowser({ ...launchConfig, cdpUrl, scope: 'shared', ...agentBrowserOpts })\n : new AgentBrowser({ ...launchConfig, ...agentBrowserOpts, scope });\n }\n\n throw new Error(`Unsupported browser provider: ${provider}`);\n}\n"],"mappings":";;;;;;;;;;;;;AA+DA,MAAa,0BAA0B;;AAGvC,MAAa,6BAA6B;;AAG1C,MAAa,0BAA0B;;AAGvC,MAAa,6BAA6B;;AA8M1C,MAAa,4BAA4B;AAEzC,MAAa,mBAAoC;CAC/C,SAAS;CACT,QAAQ,CAAC;CACT,IAAI,CAAC;AACP;;AAGA,SAAgB,qBAAkC;CAChD,OAAO,QAAQ,aAAa,WAAW,iBAAiB;AAC1D;AAEA,MAAM,WAA2B;CAC/B,YAAY;EACV,aAAa;EACb,WAAW;EACX,SAAS;EACT,YAAY;EACZ,UAAU;EACV,6BAA6B;CAC/B;CACA,QAAQ;EACN,mBAAmB;EACnB,cAAc,CAAC;EACf,gBAAgB;EAChB,iBAAiB;EACjB,uBAAuB;EACvB,wBAAwB;EACxB,wBAAwB;EACxB,uBAAuB;EACvB,uBAAuB;EACvB,sBAAsB;EACtB,gBAAgB,CAAC;EACjB,gBAAgB;EAChB,cAAc;CAChB;CACA,aAAa;EACX,MAAM;EACN,OAAO;EACP,eAAe;EACf,WAAW;EACX,8BAA8B;CAChC;CACA,SAAS,EAAE,GAAG,iBAAiB;CAC/B,kBAAkB,CAAC;CACnB,iBAAiB,CAAC;CAClB,gBAAgB,CAAC;CACjB,wBAAwB;CACxB,eAAe,CAAC;CAChB,KAAK,CAAC;CACN,SAAS;EACP,SAAS;EACT,UAAU;EACV,UAAU;EACV,UAAU;GAAE,OAAO;GAAM,QAAQ;EAAI;EACrC,WAAW,EAAE,KAAK,QAAQ;CAC5B;CACA,kBAAkB,EAAE,MAAM,UAAU;CACpC,OAAO;EAAE,SAAS;EAAO,QAAQ,mBAAmB;EAAG,UAAU;CAAqB;CACtF,SAAS;EAAE,kBAAkB;EAAO,2BAA2B;CAAM;CACrE,eAAe;EAAE,WAAW,CAAC;EAAG,cAAc;CAAM;AACtD;AAEA,MAAM,wBAAgD;CAAC;CAAO;CAAO;CAAU;CAAQ;AAAO;AAC9F,MAAM,wCAAwC;AAC9C,MAAM,uCAAuB,IAAI,QAAwC;AAEzE,SAAS,oBAAoB,SAAyC;CACpE,OAAO,EAAE,GAAG,QAAQ;AACtB;AAEA,SAAS,uBAAuB,UAA0C;CACxE,qBAAqB,IAAI,UAAU,oBAAoB,SAAS,OAAO,CAAC;CACxE,OAAO;AACT;AAEA,SAAS,oBAAoB,MAAsB,OAAgC;CACjF,OACE,KAAK,qBAAqB,MAAM,oBAChC,KAAK,8BAA8B,MAAM;AAE7C;AAEA,SAAS,mBAAmB,OAAsC;CAChE,OAAO,OAAO,UAAU,YAAY,sBAAsB,SAAS,KAA6B,IAC3F,QACD,SAAS,YAAY;AAC3B;AAEA,SAAS,kCAAkC,OAAwB;CACjE,MAAM,WACJ,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ,SAAS,YAAY;CACrF,OAAO,KAAK,IAAI,uCAAuC,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC;AAC1F;AAEA,SAAS,iBAAiB,gBAAwD;CAChF,MAAM,MAAM,kBAAkB,OAAO,mBAAmB,WAAY,iBAA6C,CAAC;CAElH,OAAO;EACL,GAAG,SAAS;EACZ,GAAG;EACH,eAAe,mBAAmB,IAAI,aAAa;EACnD,8BAA8B,kCAAkC,IAAI,4BAA4B;CAClG;AACF;AAEA,SAAS,oBAAoB,YAAqC;CAChE,MAAM,MAAM,cAAc,OAAO,eAAe,WAAY,aAAyC,CAAC;CACtG,OAAO;EACL,kBACE,OAAO,IAAI,qBAAqB,YAAY,IAAI,mBAAmB,SAAS,QAAQ;EACtF,2BACE,OAAO,IAAI,8BAA8B,YACrC,IAAI,4BACJ,SAAS,QAAQ;CACzB;AACF;AAEA,SAAS,+BAA+B,eAAiC;CACvE,OAAO,QACL,iBACA,OAAO,kBAAkB,YACzB,OAAO,UAAU,eAAe,KAAK,eAAe,6BAA6B,CACnF;AACF;AAEA,SAAS,gCAAgC,UAA0B,eAA8B;CAC/F,IAAI,+BAA+B,aAAa,GAAG;CACnD,SAAS,WAAW,8BAA8B,SAAS,YAAY,cAAc;AACvF;AAEA,SAAS,wBAAwC;CAC/C,MAAM,WAAW,gBAAgB,QAAQ;CACzC,SAAS,YAAY,YAAY;CACjC,SAAS,WAAW,8BAA8B;CAClD,OAAO;AACT;AAEA,SAAgB,kBAA0B;CACxC,OAAO,KAAK,cAAc,GAAG,eAAe;AAC9C;AAEA,SAAgB,oBAAoB,MAAsB;CAMxD,OALa,KACV,KAAK,CAAC,CACN,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EACb,KAAK;AACjB;AAEA,SAAgB,wBAAwB,cAAsB,WAA2B;CACvF,MAAM,aAAa,oBAAoB,YAAY;CACnD,MAAM,mBAAmB,UAAU,KAAK;CACxC,MAAM,iBAAiB,GAAG,WAAW;CACrC,IAAI,iBAAiB,WAAW,cAAc,GAC5C,OAAO;CAET,OAAO,GAAG,WAAW,GAAG;AAC1B;AAEA,SAAgB,qBAAqB,cAAgD;CACnF,IAAI,CAAC,MAAM,QAAQ,YAAY,GAAG,OAAO,CAAC;CAE1C,MAAM,kBAA2C,CAAC;CAClD,KAAK,MAAM,eAAe,cAAc;EACtC,IAAI,CAAC,eAAe,OAAO,gBAAgB,UAAU;EAErD,MAAM,YAAY;EAClB,MAAM,OAAO,OAAO,UAAU,SAAS,WAAW,UAAU,KAAK,KAAK,IAAI;EAC1E,MAAM,MAAM,OAAO,UAAU,QAAQ,WAAW,UAAU,IAAI,KAAK,IAAI;EACvE,IAAI,CAAC,QAAQ,CAAC,KAAK;EAEnB,MAAM,aAAa,oBAAoB,IAAI;EAC3C,MAAM,SAAS,MAAM,QAAQ,UAAU,MAAM,IACzC,CACE,GAAG,IAAI,IACL,UAAU,OACP,QAAQ,UAA2B,OAAO,UAAU,QAAQ,CAAC,CAC7D,KAAI,UAAS,MAAM,KAAK,CAAC,CAAC,CAC1B,KAAI,UAAS;GACZ,MAAM,iBAAiB,GAAG,WAAW;GACrC,IAAI,MAAM,WAAW,cAAc,GACjC,OAAO,MAAM,MAAM,eAAe,MAAM;GAE1C,OAAO;EACT,CAAC,CACL,CACF,CAAC,CAAC,QAAO,UAAS,MAAM,SAAS,CAAC,IAClC,CAAC;EAEL,MAAM,SACJ,OAAO,UAAU,WAAW,YAAY,UAAU,OAAO,KAAK,CAAC,CAAC,SAAS,IAAI,UAAU,OAAO,KAAK,IAAI,KAAA;EAEzG,gBAAgB,KAAK;GACnB;GACA;GACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;GAC3B;EACF,CAAC;CACH;CAEA,OAAO;AACT;AAEA,MAAM,oCAAoB,IAAI,IAAqB,CAAC,aAAa,eAAe,CAAC;AACjF,MAAM,iCAAiB,IAAI,IAAkB,CAAC,SAAS,aAAa,CAAC;;;;;AAMrE,SAAS,qBAAqB,YAAsC;CAClE,MAAM,MAAM,cAAc,OAAO,eAAe,WAAY,aAAyC,CAAC;CACtG,MAAM,cAAc,IAAI,YAAY,OAAO,IAAI,aAAa,WAAY,IAAI,WAAuC,CAAC;CACpH,MAAM,eACJ,IAAI,aAAa,OAAO,IAAI,cAAc,WAAY,IAAI,YAAwC,CAAC;CACrG,MAAM,kBACJ,IAAI,gBAAgB,OAAO,IAAI,iBAAiB,WAAY,IAAI,eAA2C,CAAC;CAE9G,OAAO;EACL,SAAS,OAAO,IAAI,YAAY,YAAY,IAAI,UAAU,SAAS,QAAQ;EAC3E,UACE,OAAO,IAAI,aAAa,YAAY,kBAAkB,IAAI,IAAI,QAA2B,IACpF,IAAI,WACL,SAAS,QAAQ;EACvB,UAAU,OAAO,IAAI,aAAa,YAAY,IAAI,WAAW,SAAS,QAAQ;EAC9E,QAAQ,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,KAAA;EAClF,SAAS,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,KAAA;EACtF,gBACE,OAAO,IAAI,mBAAmB,YAAY,IAAI,eAAe,KAAK,IAAI,IAAI,eAAe,KAAK,IAAI,KAAA;EACpG,UAAU;GACR,OAAO,OAAO,YAAY,UAAU,WAAW,YAAY,QAAQ,SAAS,QAAQ,SAAU;GAC9F,QAAQ,OAAO,YAAY,WAAW,WAAW,YAAY,SAAS,SAAS,QAAQ,SAAU;EACnG;EACA,OAAO,OAAO,IAAI,UAAU,aAAa,IAAI,UAAU,YAAY,IAAI,UAAU,YAAY,IAAI,QAAQ,KAAA;EACzG,WAAW;GACT,KACE,OAAO,aAAa,QAAQ,YAAY,eAAe,IAAI,aAAa,GAAmB,IACtF,aAAa,MACd,SAAS,QAAQ,UAAW;GAClC,GAAI,OAAO,aAAa,WAAW,YAAY,aAAa,OAAO,KAAK,IACpE,EAAE,QAAQ,aAAa,OAAO,KAAK,EAAE,IACrC,CAAC;GACL,GAAI,OAAO,aAAa,cAAc,YAAY,aAAa,UAAU,KAAK,IAC1E,EAAE,WAAW,aAAa,UAAU,KAAK,EAAE,IAC3C,CAAC;GACL,GAAI,OAAO,aAAa,wBAAwB,YAC5C,EAAE,qBAAqB,aAAa,oBAAoB,IACxD,CAAC;EACP;EACA,cACE,OAAO,gBAAgB,iBAAiB,YAAY,gBAAgB,aAAa,KAAK,IAClF,EAAE,cAAc,gBAAgB,aAAa,KAAK,EAAE,IACpD,KAAA;CACR;AACF;AAEA,SAAS,8BAA8B,qBAAwD;CAC7F,MAAM,MACJ,uBAAuB,OAAO,wBAAwB,WACjD,sBACD,CAAC;CACP,MAAM,aAAa,OAAO,IAAI,eAAe,YAAY,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,IAAI,KAAA;CACzG,MAAM,SAAS,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,KAAA;CACzF,MAAM,OAAO,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,KAAA;CACjF,MAAM,cAAc,aAAa,KAAA,IAAY,SAAS,iBAAiB;CAEvE,OAAO;EACL,GAAK,QAAQ,cAAe,EAAE,MAAM,QAAQ,YAAY,IAAI,CAAC;EAC7D,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACnC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;CAC7B;AACF;AAEA,SAAS,mBAAmB,UAAkC;CAC5D,MAAM,MAAM,YAAY,OAAO,aAAa,WAAY,WAAuC,CAAC;CAChG,MAAM,UAAU,OAAO,IAAI,YAAY,YAAY,IAAI,UAAU,SAAS,MAAM;CAChF,MAAM,SACJ,IAAI,WAAW,kBAAkB,IAAI,WAAW,UAAU,IAAI,SAAS,mBAAmB;CAK5F,MAAM,WAAW,gBAFA,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW,SAAS,MAAM,UACpE,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ,KAAA,CACV;CAChD,OAAO;EACL;EACA;EACA,UAAU,SAAS;EACnB,OAAO,SAAS;CAClB;AACF;AAEA,MAAM,mBAAmB;AAEzB,SAAS,2BAA2B,KAAqC;CACvE,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,OAAO;EAAE,WAAW,CAAC;EAAG,cAAc;CAAM;CACjF,MAAM,MAAM;CACZ,MAAM,eAAe,IAAI,iBAAiB;CAC1C,MAAM,eAAe,IAAI;CACzB,IAAI,CAAC,gBAAgB,OAAO,iBAAiB,UAAU,OAAO;EAAE,WAAW,CAAC;EAAG;CAAa;CAC5F,MAAM,YAAyD,CAAC;CAChE,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,YAAuC,GAC7E,IAAI,OAAO,OAAO,QAAQ,UAAU;EAClC,MAAM,IAAI;EACV,IAAI,OAAO,EAAE,cAAc,YAAY,iBAAiB,KAAK,EAAE,SAAS,GACtE,UAAU,OAAO;GACf,WAAW,EAAE;GACb,cAAc,OAAO,EAAE,iBAAiB,WAAW,EAAE,gCAAe,IAAI,KAAK,EAAA,CAAE,YAAY;EAC7F;CAEJ;CAEF,OAAO;EAAE;EAAW;CAAa;AACnC;;;;;;;AAQA,SAAS,gBAAgB,cAA+B;CACtD,MAAM,WAAW,KAAK,cAAc,GAAG,WAAW;CAClD,IAAI,CAAC,WAAW,QAAQ,GAAG,OAAO;CAElC,IAAI;CACJ,IAAI;EACF,WAAW,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;CACvD,QAAQ;EACN,OAAO;CACT;CAEA,MAAM,YAAY,OAAO,KAAK,QAAQ,CAAC,CAAC,QAAO,MAAK,EAAE,WAAW,GAAG,CAAC;CACrE,IAAI,UAAU,WAAW,GAAG,OAAO;CAGnC,IAAI;CACJ,IAAI,WAAW,YAAY,GACzB,IAAI;EACF,MAAM,MAAM,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;EAC1D,WAAW;GACT,YAAY;IAAE,GAAG,SAAS;IAAY,GAAG,IAAI;GAAW;GACxD,QAAQ;IAAE,GAAG,SAAS;IAAQ,GAAG,IAAI;GAAO;GAC5C,aAAa,iBAAiB,IAAI,WAAW;GAC7C,SAAS;IACP,GAAG;IACH,GAAG,IAAI;IACP,QAAQ;KAAE,GAAG,iBAAiB;KAAQ,GAAG,IAAI,SAAS;IAAO;IAC7D,IAAI;KAAE,GAAG,iBAAiB;KAAI,GAAG,IAAI,SAAS;IAAG;GACnD;GACA,kBAAkB,MAAM,QAAQ,IAAI,gBAAgB,IAAI,IAAI,mBAAmB,CAAC;GAChF,iBAAiB,qBAAqB,IAAI,eAAe;GACzD,gBAAgB,IAAI,kBAAkB,OAAO,IAAI,mBAAmB,WAAW,IAAI,iBAAiB,CAAC;GACrG,wBAAwB,OAAO,IAAI,2BAA2B,WAAW,IAAI,yBAAyB;GACtG,eAAe,IAAI,iBAAiB,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAAgB,CAAC;GACjG,KAAK,IAAI,OAAO,OAAO,IAAI,QAAQ,WAAY,IAAI,MAAoB,KAAA;GACvE,SAAS,qBAAqB,IAAI,OAAO;GACzC,kBAAkB,8BAA8B,IAAI,gBAAgB;GACpE,OAAO,mBAAmB,IAAI,KAAK;GACnC,SAAS,oBAAoB,IAAI,OAAO;GACxC,eAAe,2BAA2B,IAAI,aAAa;EAC7D;EACA,gCAAgC,UAAU,IAAI,UAAU;CAC1D,QAAQ;EACN,WAAW,gBAAgB,QAAQ;CACrC;MAEA,WAAW,gBAAgB,QAAQ;CAIrC,IAAI,SAAS,eAAe,OAAO,SAAS,gBAAgB,UAC1D,SAAS,iBAAiB;EAAE,GAAG,SAAS;EAAa,GAAG,SAAS;CAAe;CAIlF,KAAK,MAAM,OAAO,WAAW;EAC3B,MAAM,YAAY,IAAI,MAAM,qBAAqB;EACjD,IAAI,YAAY,MAAM,OAAO,SAAS,SAAS,YAAY,CAAC,SAAS,OAAO,aAAa,UAAU,KACjG,SAAS,OAAO,aAAa,UAAU,MAAM,SAAS;CAE1D;CAGA,KAAK,MAAM,OAAO,WAAW;EAC3B,IAAI,QAAQ,sBAAsB,OAAO,SAAS,SAAS,YAAY,CAAC,SAAS,OAAO,eAAe,YACrG,SAAS,OAAO,eAAe,aAAa,SAAS;EAEvD,MAAM,UAAU,IAAI,MAAM,yBAAyB;EACnD,IAAI,UAAU,MAAM,OAAO,SAAS,SAAS,YAAY,CAAC,SAAS,OAAO,eAAe,QAAQ,KAC/F,SAAS,OAAO,eAAe,QAAQ,MAAM,SAAS;CAE1D;CAGA,aAAa,UAAU,YAAY;CAGnC,KAAK,MAAM,OAAO,WAChB,OAAO,SAAS;CAElB,IAAI;EACF,cAAc,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;CACpE,QAAQ,CAER;CAEA,OAAO;AACT;AAEA,MAAM,uBAA+C;CACnD,MAAM;CACN,OAAO;CACP,MAAM;AACR;AAEA,SAAgB,wBAAwB,UAAmC;CACzE,MAAM,eAAe;CACrB,MAAM,eAAe;CAIrB,IAAI,EAFF,SAAS,OAAO,sBAAsB,gBAAgB,SAAS,WAAW,eAAe,eAElE,OAAO;CAEhC,MAAM,cAAc,SAAS,iBAAiB,WAAU,MAAK,EAAE,SAAS,QAAQ;CAChF,IAAI,eAAe,GAAG;EACpB,MAAM,WAAW,SAAS,iBAAiB;EAE3C,IAAI,CADgB,OAAO,QAAQ,oBAAoB,CAAC,CAAC,OAAO,CAAC,GAAG,OAAO,SAAS,OAAO,OAAO,CACnF,GACb,SAAS,SAAS,EAAE,GAAG,qBAAqB;CAEhD,OACE,SAAS,iBAAiB,KAAK;EAC7B,MAAM;EACN,QAAQ,EAAE,GAAG,qBAAqB;EAClC,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;CACpC,CAAC;CAGH,IAAI,SAAS,OAAO,sBAAsB,cAAc;EACtD,SAAS,OAAO,oBAAoB;EACpC,IAAI,OAAO,KAAK,SAAS,OAAO,YAAY,CAAC,CAAC,WAAW,GACvD,SAAS,OAAO,eAAe,EAAE,GAAG,qBAAqB;CAE7D;CAEA,IAAI,SAAS,WAAW,eAAe,cACrC,SAAS,WAAW,aAAa;CAGnC,OAAO;AACT;AAEA,SAAgB,aAAa,WAAmB,gBAAgB,GAAmB;CAEjF,gBAAgB,QAAQ;CAExB,IAAI,CAAC,WAAW,QAAQ,GAAG,OAAO,uBAAuB,sBAAsB,CAAC;CAChF,IAAI;EACF,MAAM,MAAM,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;EAGtD,MAAM,WAA2B;GAC/B,GAAG;GACH,YAAY;IAAE,GAAG,SAAS;IAAY,GAAG,IAAI;GAAW;GACxD,QAAQ;IAAE,GAAG,SAAS;IAAQ,GAAG,IAAI;GAAO;GAC5C,aAAa,iBAAiB,IAAI,WAAW;GAC7C,SAAS;IACP,GAAG;IACH,GAAG,IAAI;IACP,QAAQ;KAAE,GAAG,iBAAiB;KAAQ,GAAG,IAAI,SAAS;IAAO;IAC7D,IAAI;KAAE,GAAG,iBAAiB;KAAI,GAAG,IAAI,SAAS;IAAG;GACnD;GACA,kBAAkB,MAAM,QAAQ,IAAI,gBAAgB,IAAI,IAAI,mBAAmB,CAAC;GAChF,iBAAiB,qBAAqB,IAAI,eAAe;GACzD,gBAAgB,IAAI,kBAAkB,OAAO,IAAI,mBAAmB,WAAW,IAAI,iBAAiB,CAAC;GACrG,wBAAwB,OAAO,IAAI,2BAA2B,WAAW,IAAI,yBAAyB;GACtG,eAAe,IAAI,iBAAiB,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAAgB,CAAC;GACjG,KAAK,IAAI,OAAO,OAAO,IAAI,QAAQ,WAAY,IAAI,MAAoB,KAAA;GACvE,SAAS,qBAAqB,IAAI,OAAO;GACzC,kBAAkB,8BAA8B,IAAI,gBAAgB;GACpE,OAAO,mBAAmB,IAAI,KAAK;GACnC,SAAS,oBAAoB,IAAI,OAAO;GACxC,eAAe,2BAA2B,IAAI,aAAa;EAC7D;EAGA,IAAI,kBAAkB;EACtB,IAAI,CAAC,+BAA+B,IAAI,UAAU,GAAG;GACnD,gCAAgC,UAAU,IAAI,UAAU;GACxD,kBAAkB;EACpB;EACA,IAAI,IAAI,QAAQ,aAAa,CAAC,SAAS,OAAO,iBAAiB;GAC7D,SAAS,OAAO,kBAAkB,IAAI,OAAO;GAC7C,kBAAkB;EACpB;EAEA,IAAI,wBAAwB,QAAQ,GAClC,kBAAkB;EAGpB,IAAI,iBACF,aAAa,UAAU,QAAQ;EAGjC,OAAO,uBAAuB,QAAQ;CACxC,QAAQ;EACN,OAAO,uBAAuB,gBAAgB,QAAQ,CAAC;CACzD;AACF;AAEA,MAAa,kCAAkC;AAO/C,SAAgB,oBAAoB,UAA+D;CACjG,MAAM,eAAuC,CAAC;CAC9C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,CAAC,CAAC,GAAG;EACzD,MAAM,YAAY,IAAI,MAAM,oBAAoB;EAChD,IAAI,YAAY,MAAM,OAAO,UAAU,YAAY,MAAM,SAAS,GAChE,aAAa,UAAU,MAAM;CAEjC;CAEA,MAAM,YAAY,WAAW;CAG7B,OAAO;EACL,mBAHwB,OAAO,cAAc,YAAY,UAAU,SAAS,IAAI,YAAY;EAI5F;CACF;AACF;;;;;;;;;AAUA,SAAgB,+BACd,UACA,cACA,UACe;CACf,MAAM,iBAAiB,oBAAoB,QAAQ;CAEnD,MAAM,eAAe,WAA4B;EAC/C,IAAI,OAAO,WAAW,SAAS,GAAG;GAChC,MAAM,OAAO,OAAO,MAAM,CAAgB;GAC1C,OAAO,SAAS,iBAAiB,MAAK,MAAK,EAAE,SAAS,IAAI;EAC5D;EACA,OAAO,aAAa,MAAK,MAAK,EAAE,OAAO,MAAM;CAC/C;CAEA,IAAI,eAAe,qBAAqB,YAAY,eAAe,iBAAiB,GAClF,OAAO,eAAe;CAGxB,MAAM,WAAkE,CACtE,GAAG,cACH,GAAG,SAAS,iBAAiB,KAAI,OAAM;EAAE,IAAI,UAAU,EAAE;EAAQ,QAAQ,EAAE;CAAO,EAAE,CACtF;CAEA,KAAK,MAAM,QAAQ,UAAU;EAC3B,MAAM,cAAc,OAAO,QAAQ,KAAK,MAAM;EAC9C,MAAM,gBAAgB,OAAO,KAAK,eAAe,YAAY;EAI7D,IAFE,YAAY,WAAW,cAAc,UACrC,YAAY,OAAO,CAAC,QAAQ,aAAa,eAAe,aAAa,YAAY,OAAO,GAC7E,OAAO,KAAK;CAC3B;CAEA,IAAI,SAAS,OAAO,qBAAqB,YAAY,SAAS,OAAO,iBAAiB,GACpF,OAAO,SAAS,OAAO;CAGzB,OAAO;AACT;;;;;;;;;;;AAYA,SAAgB,qBACd,UACA,cACwB;CACxB,MAAM,EAAE,mBAAmB,iBAAiB,SAAS;CACrD,IAAI,CAAC,mBAAmB,OAAO;CAG/B,IAAI,kBAAkB,WAAW,SAAS,GAAG;EAC3C,MAAM,OAAO,kBAAkB,MAAM,CAAgB;EACrD,MAAM,OAAO,SAAS,iBAAiB,MAAK,MAAK,EAAE,SAAS,IAAI;EAChE,IAAI,MAAM,OAAO,KAAK;EAEtB,OAAO;CACT;CAGA,MAAM,UAAU,aAAa,MAAK,MAAK,EAAE,OAAO,iBAAiB;CACjE,IAAI,SAAS,OAAO,QAAQ;CAG5B,OAAO;AACT;;;;;;;;;;;;;;;AAgBA,SAAgB,mBACd,UACA,MACA,gBACe;CACf,MAAM,EAAE,gBAAgB,iBAAiB,uBAAuB,2BAA2B,SAAS;CACpG,MAAM,eAAe,SAAS,aAAa,wBAAwB;CACnE,IAAI,cAAc,OAAO;CAEzB,IAAI,CAAC,gBAAgB,OAAO;CAC5B,IAAI,mBAAmB,UAAU,OAAO;CAExC,MAAM,OAAO,eAAe,MAAK,MAAK,EAAE,OAAO,cAAc;CAC7D,IAAI,MAAM,OAAO,KAAK;CAEtB,OAAO;AACT;;;;;;AAOA,SAAgB,eACd,UACA,gBACe;CACf,OAAO,mBAAmB,UAAU,YAAY,cAAc;AAChE;AAEA,SAAS,yBAAyB,UAA0B,UAAkC;CAC5F,MAAM,gBAAgB,qBAAqB,IAAI,QAAQ;CACvD,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,SAAS,SAAS,aAAa,KAAK,CAAC,WAAW,QAAQ,GACjG,OAAO,SAAS;CAGlB,IAAI;EAEF,MAAM,iBAAiB,oBADJ,KAAK,MAAM,aAAa,UAAU,OAAO,CACR,CAAC,CAAC,OAAO;EAC7D,IAAI,CAAC,oBAAoB,gBAAgB,aAAa,GACpD,OAAO;CAEX,QAAQ,CAER;CAEA,OAAO,SAAS;AAClB;AAEA,SAAgB,aAAa,UAA0B,WAAmB,gBAAgB,GAAS;CACjG,MAAM,MAAM,QAAQ,QAAQ;CAC5B,IAAI,CAAC,WAAW,GAAG,GACjB,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CAEpC,MAAM,UAAU,yBAAyB,UAAU,QAAQ;CAC3D,SAAS,UAAU;CACnB,qBAAqB,IAAI,UAAU,oBAAoB,OAAO,CAAC;CAC/D,cAAc,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AACpE;;AAGA,MAAM,0BAA0B;;;;;AAMhC,SAAgB,mBAAmB,aAAkD;CACnF,MAAM,aAAa,KAAK,aAAa,uBAAuB;CAC5D,IAAI,CAAC,WAAW,UAAU,GACxB;CAEF,IAAI;EACF,MAAM,UAAU,aAAa,YAAY,OAAO,CAAC,CAAC,KAAK;EACvD,IAAI,YAAY,eAAe,YAAY,iBACzC,OAAO;EAET;CACF,QAAQ;EACN;CACF;AACF;;;;;AAMA,SAAgB,mBAAmB,aAAqB,UAAiC;CACvF,MAAM,aAAa,KAAK,aAAa,uBAAuB;CAC5D,IAAI,CAAC,WAAW,WAAW,GACzB,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;CAE5C,cAAc,YAAY,UAAU,OAAO;AAC7C;;;;;AAMA,SAAgB,6BACd,aACA,gBAC6B;CAC7B,IAAI,CAAC,aACH;CAEF,MAAM,mBAAmB,mBAAmB,WAAW;CACvD,IAAI,oBAAoB,qBAAqB,gBAC3C,OAAO;AAGX;AAEA,SAAS,0BAA0B;CACjC,OAAO,EAAE,WAAW,KAAK,cAAc,GAAG,oBAAoB,EAAE;AAClE;;;;;;AAOA,eAAsB,0BAA0B,UAA+D;CAC7G,IAAI,CAAC,SAAS,SACZ;CAGF,MAAM,EAAE,UAAU,UAAU,UAAU,QAAQ,SAAS,gBAAgB,WAAW,iBAAiB;CAInG,MAAM,QAAQ,UAAW,WAAqB,SAAS;CAGvD,MAAM,eAAe;EAAE;EAAU;EAAU;EAAS;EAAgB;CAAM;CAE1E,IAAI,aAAa,aAAa;EAC5B,MAAM,EAAE,qBAAqB,MAAM,OAAO;EAC1C,MAAM,gBAAyC;GAC7C,KAAK,WAAW,OAAO;GACvB,QAAQ,WAAW,UAAU,QAAQ,IAAI;GACzC,WAAW,WAAW,aAAa,QAAQ,IAAI;GAC/C,qBAAqB,WAAW;GAChC,WAAW,wBAAwB;EACrC;EAcA,MAAM,cAAc,IAAI,YAAY;EACpC,MAAM,OAAO,YAAY,IAAI,cAAc;EAC3C,IAAI,MAAM,SAAS,SAAS;GAC1B,MAAM,YAAa,KAAa;GAChC,cAAc,QAAQ;IACpB,WAAW;IACX,QAAQ;IACR,SAAS;IACT,SAAS;KACP,YAAY;KACZ,cAAc;KACd,GAAI,YAAY,EAAE,sBAAsB,UAAU,IAAI,CAAC;IACzD;IACA,OAAO,yBAAyB,WAAW;IAC3C,YAAY,sBAAsB;GACpC;EACF;EAEA,OAAO,SACH,IAAI,iBAAiB;GAAE,GAAG;GAAc;GAAQ,OAAO;GAAU,GAAG;EAAc,CAAC,IACnF,IAAI,iBAAiB;GAAE,GAAG;GAAc,GAAG;EAAc,CAAC;CAChE,OAAO,IAAI,aAAa,iBAAiB;EACvC,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,MAAM,mBAAmB;GACvB,cAAc,cAAc;GAC5B,WAAW,wBAAwB;EACrC;EACA,OAAO,SACH,IAAI,aAAa;GAAE,GAAG;GAAc;GAAQ,OAAO;GAAU,GAAG;EAAiB,CAAC,IAClF,IAAI,aAAa;GAAE,GAAG;GAAc,GAAG;GAAkB;EAAM,CAAC;CACtE;CAEA,MAAM,IAAI,MAAM,iCAAiC,UAAU;AAC7D"}
1
+ {"version":3,"file":"settings.js","names":[],"sources":["../../src/onboarding/settings.ts"],"sourcesContent":["/**\n * Persistent global settings stored in the app data directory as settings.json.\n * This file persists onboarding state AND user preferences (model choices, yolo, etc.)\n * so they carry across threads and restarts.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { MastraBrowser } from '@mastra/core/browser';\nimport type { LSPConfig } from '@mastra/core/workspace';\nimport { AuthStorage } from '../auth/storage.js';\nimport { buildCodexStagehandFetch, createCodexMiddleware } from '../providers/openai-codex.js';\nimport { getAppDataDir } from '../utils/project.js';\nimport { DEFAULT_STT_PROVIDER, resolveSTTModel } from '../voice/stt-registry.js';\n\n/** A saved custom pack — user-defined model selections for each mode. */\nexport interface CustomPack {\n name: string;\n models: Record<string, string>;\n createdAt: string;\n}\n\n/** A saved custom provider for OpenAI-compatible endpoints. */\nexport interface CustomProviderSetting {\n name: string;\n url: string;\n apiKey?: string;\n models: string[];\n}\n\n/** Storage backend type. */\nexport type StorageBackend = 'libsql' | 'pg';\n\n/** LibSQL-specific storage settings. */\nexport interface LibSQLStorageSettings {\n url?: string;\n authToken?: string;\n}\n\n/** PostgreSQL-specific storage settings. */\nexport interface PgStorageSettings {\n connectionString?: string;\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n password?: string;\n schemaName?: string;\n disableInit?: boolean;\n skipDefaultIndexes?: boolean;\n}\n\n/** Storage configuration persisted in global settings. */\nexport interface StorageSettings {\n /** Which backend to use. Default: 'libsql'. */\n backend: StorageBackend;\n /** LibSQL-specific config (used when backend is 'libsql'). */\n libsql: LibSQLStorageSettings;\n /** PostgreSQL-specific config (used when backend is 'pg'). */\n pg: PgStorageSettings;\n}\n\n/** Gateway provider key used in AuthStorage. */\nexport const MASTRA_GATEWAY_PROVIDER = 'mastra-gateway';\n\n/** Default gateway URL. */\nexport const MASTRA_GATEWAY_DEFAULT_URL = 'https://gateway-api.mastra.ai';\n\n/** @deprecated Renamed to {@link MASTRA_GATEWAY_PROVIDER}. */\nexport const MEMORY_GATEWAY_PROVIDER = MASTRA_GATEWAY_PROVIDER;\n\n/** @deprecated Renamed to {@link MASTRA_GATEWAY_DEFAULT_URL}. */\nexport const MEMORY_GATEWAY_DEFAULT_URL = MASTRA_GATEWAY_DEFAULT_URL;\n\n/** Valid persisted thinking level values. */\nexport type ThinkingLevelSetting = 'off' | 'low' | 'medium' | 'high' | 'xhigh';\n\n/** Browser provider type. */\nexport type BrowserProvider = 'stagehand' | 'agent-browser';\n\n/** Direct TUI `!` shell passthrough mode. */\nexport type ShellPassthroughSettingsMode = 'default' | 'path' | 'login';\n\n/** Direct TUI `!` shell command language. */\nexport type ShellPassthroughSettingsFamily = 'posix' | 'cmd' | 'powershell';\n\n/** Direct TUI `!` shell passthrough configuration. */\nexport interface ShellPassthroughSettings {\n mode?: ShellPassthroughSettingsMode | string;\n executable?: string;\n family?: ShellPassthroughSettingsFamily | string;\n}\n\n/** STT engine: on-device macOS recognizer or a cloud provider. */\nexport type VoiceEngine = 'macos-native' | 'cloud';\n\n/** Voice (hold-space dictation) configuration persisted in global settings. */\nexport interface VoiceSettings {\n /** Whether hold-space voice input is enabled. */\n enabled: boolean;\n /** Which STT engine to use. Defaults to macOS native on darwin, else cloud. */\n engine: VoiceEngine;\n /** Cloud provider id (matches an STT registry entry). Cloud engine only. */\n provider: string;\n /** Cloud model id; defaults to the provider's first registry model. */\n model?: string;\n}\n\n/** Stagehand environment type. */\nexport type StagehandEnv = 'LOCAL' | 'BROWSERBASE';\n\n/** Stagehand-specific browser settings. */\nexport interface StagehandSettings {\n env: StagehandEnv;\n apiKey?: string;\n projectId?: string;\n /** Whether to preserve the user data directory after the browser closes. */\n preserveUserDataDir?: boolean;\n}\n\n/** AgentBrowser-specific browser settings. */\nexport interface AgentBrowserSettings {\n /** Path to a Playwright storage state file (JSON) containing cookies and localStorage. */\n storageState?: string;\n}\n\n/** Browser configuration persisted in global settings. */\nexport interface BrowserSettings {\n /** Whether browser automation is enabled. */\n enabled: boolean;\n /** Which browser provider to use. */\n provider: BrowserProvider;\n /** Whether to run headless (no visible browser window). */\n headless: boolean;\n /** Browser viewport dimensions. */\n viewport?: { width: number; height: number };\n /** CDP URL for connecting to an existing browser. */\n cdpUrl?: string;\n /** Path to a Chrome/Chromium user data directory (profile). */\n profile?: string;\n /** Path to the browser executable to use. */\n executablePath?: string;\n /** Browser scope — 'shared' (all threads share one browser) or 'thread' (each thread gets its own). */\n scope?: 'shared' | 'thread';\n /** Stagehand-specific settings. */\n stagehand?: StagehandSettings;\n /** AgentBrowser-specific settings. */\n agentBrowser?: AgentBrowserSettings;\n}\n\nexport interface GlobalSettings {\n // Onboarding tracking\n onboarding: {\n completedAt: string | null;\n skippedAt: string | null;\n version: number;\n modePackId: string | null;\n omPackId: string | null;\n quietModePreferenceSelected: boolean;\n };\n // Global model preferences (applied to new threads)\n models: {\n /**\n * Active model pack ID. Built-in packs use their id directly (\"anthropic\",\n * \"openai\"). Custom packs use \"custom:<name>\".\n * When set, models are resolved from the pack at startup so pack updates\n * (e.g. new model versions) apply automatically.\n * Cleared when the user manually overrides via /models (falls back to modeDefaults).\n */\n activeModelPackId: string | null;\n /** Explicit per-mode overrides — used when no activeModelPackId is set. */\n modeDefaults: Record<string, string>;\n /**\n * Active OM pack ID (e.g. \"gemini\", \"anthropic\", \"custom\").\n * When set, the OM model is resolved from the pack at startup so pack\n * updates (e.g. new model versions) apply automatically.\n * Cleared when the user manually overrides via /om (falls back to omModelOverride).\n */\n activeOmPackId: string | null;\n /**\n * Shared OM model override — used for both observer and reflector when a\n * role-specific override is not set. Kept for back-compat with older settings\n * files and set by onboarding when the user picks a custom OM pack.\n */\n omModelOverride: string | null;\n /**\n * Explicit Observer model override — takes precedence over `omModelOverride`\n * when set. Written by `/om` when the observer model is changed independently.\n */\n observerModelOverride: string | null;\n /**\n * Explicit Reflector model override — takes precedence over `omModelOverride`\n * when set. Written by `/om` when the reflector model is changed independently.\n */\n reflectorModelOverride: string | null;\n /** Default OM observation threshold used for new threads unless overridden per-thread. */\n omObservationThreshold: number | null;\n /** Default OM reflection threshold used for new threads unless overridden per-thread. */\n omReflectionThreshold: number | null;\n /**\n * Whether observations and reflections use the terse caveman-style instruction.\n * `null` means inherit the built-in default (currently `false` — caveman is\n * opt-in via `/om` settings). Used as the default for new threads unless\n * overridden per-thread.\n */\n omCavemanObservations: boolean | null;\n /**\n * Whether Observational Memory forwards image/file attachment parts to the\n * Observer LLM. `null` ⇒ inherit built-in default ('auto'). 'auto' checks\n * model capabilities; true/false forces the setting.\n */\n omObserveAttachments: 'auto' | boolean | null;\n /** Per-agent-type subagent model overrides (e.g. { explore: \"openai/gpt-5.1-codex-mini\" }) */\n subagentModels: Record<string, string>;\n /** Default judge model for /goal. */\n goalJudgeModel: string | null;\n /** Default max attempts for /goal. */\n goalMaxTurns: number | null;\n };\n // Global behavior preferences\n preferences: {\n yolo: boolean | null;\n theme: 'auto' | 'dark' | 'light';\n /** Default reasoning effort level used for all threads/models unless overridden in-session. */\n thinkingLevel: ThinkingLevelSetting;\n /** When true, components like subagent output collapse to compact summaries on completion. */\n quietMode: boolean;\n /** Maximum quiet-mode detail preview lines for compact tool calls. Set to 0 to hide previews. */\n quietModeMaxToolPreviewLines: number;\n };\n // Storage backend configuration\n storage: StorageSettings;\n // User-created custom model packs\n customModelPacks: CustomPack[];\n // User-created custom providers with custom models\n customProviders: CustomProviderSetting[];\n // Model usage counts for ranking in the selector\n modelUseCounts: Record<string, number>;\n // Version the user dismissed the update prompt for (skip until they manually update past this)\n updateDismissedVersion: string | null;\n // Mastra gateway configuration\n memoryGateway: { baseUrl?: string };\n // LSP configuration forwarded to the workspace\n lsp?: LSPConfig;\n // Browser automation configuration\n browser: BrowserSettings;\n // Direct TUI `!` shell passthrough configuration\n shellPassthrough: ShellPassthroughSettings;\n // Hold-space voice input configuration\n voice: VoiceSettings;\n // Signal routing configuration\n signals: SignalSettings;\n // Cloud observability configuration (per-resource project IDs; tokens stored in auth.json)\n observability: ObservabilitySettings;\n}\n\nexport interface SignalSettings {\n /** Opt into local Unix socket PubSub for cross-process signal routing. */\n unixSocketPubSub: boolean;\n /** Experimental: enable GitHub PR subscription signals backed by gitcrawl. */\n experimentalGithubSignals: boolean;\n}\n\nexport interface ObservabilityResourceConfig {\n /** Cloud project ID for this resource */\n projectId: string;\n /** When this config was created */\n configuredAt: string;\n}\n\nexport interface ObservabilitySettings {\n /** Per-resource cloud project configs, keyed by resourceId */\n resources: Record<string, ObservabilityResourceConfig>;\n /** Whether to store traces locally in DuckDB. Off by default to avoid disk usage. */\n localTracing: boolean;\n}\n\n/** Auth key prefix for observability tokens stored per-resource in auth.json */\nexport const OBSERVABILITY_AUTH_PREFIX = 'observability:';\n\nexport const STORAGE_DEFAULTS: StorageSettings = {\n backend: 'libsql',\n libsql: {},\n pg: {},\n};\n\n/** Default STT engine: on-device macOS recognizer where available, else cloud. */\nexport function defaultVoiceEngine(): VoiceEngine {\n return process.platform === 'darwin' ? 'macos-native' : 'cloud';\n}\n\nconst DEFAULTS: GlobalSettings = {\n onboarding: {\n completedAt: null,\n skippedAt: null,\n version: 0,\n modePackId: null,\n omPackId: null,\n quietModePreferenceSelected: true,\n },\n models: {\n activeModelPackId: null,\n modeDefaults: {},\n activeOmPackId: null,\n omModelOverride: null,\n observerModelOverride: null,\n reflectorModelOverride: null,\n omObservationThreshold: null,\n omReflectionThreshold: null,\n omCavemanObservations: null,\n omObserveAttachments: null,\n subagentModels: {},\n goalJudgeModel: null,\n goalMaxTurns: null,\n },\n preferences: {\n yolo: null,\n theme: 'auto',\n thinkingLevel: 'off',\n quietMode: false,\n quietModeMaxToolPreviewLines: 2,\n },\n storage: { ...STORAGE_DEFAULTS },\n customModelPacks: [],\n customProviders: [],\n modelUseCounts: {},\n updateDismissedVersion: null,\n memoryGateway: {},\n lsp: {},\n browser: {\n enabled: false,\n provider: 'stagehand',\n headless: false,\n viewport: { width: 1280, height: 720 },\n stagehand: { env: 'LOCAL' },\n },\n shellPassthrough: { mode: 'default' },\n voice: { enabled: false, engine: defaultVoiceEngine(), provider: DEFAULT_STT_PROVIDER },\n signals: { unixSocketPubSub: false, experimentalGithubSignals: false },\n observability: { resources: {}, localTracing: false },\n};\n\nconst THINKING_LEVEL_VALUES: ThinkingLevelSetting[] = ['off', 'low', 'medium', 'high', 'xhigh'];\nconst QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX = 8;\nconst loadedSignalSettings = new WeakMap<GlobalSettings, SignalSettings>();\n\nfunction cloneSignalSettings(signals: SignalSettings): SignalSettings {\n return { ...signals };\n}\n\nfunction rememberLoadedSettings(settings: GlobalSettings): GlobalSettings {\n loadedSignalSettings.set(settings, cloneSignalSettings(settings.signals));\n return settings;\n}\n\nfunction signalSettingsEqual(left: SignalSettings, right: SignalSettings): boolean {\n return (\n left.unixSocketPubSub === right.unixSocketPubSub &&\n left.experimentalGithubSignals === right.experimentalGithubSignals\n );\n}\n\nfunction parseThinkingLevel(value: unknown): ThinkingLevelSetting {\n return typeof value === 'string' && THINKING_LEVEL_VALUES.includes(value as ThinkingLevelSetting)\n ? (value as ThinkingLevelSetting)\n : DEFAULTS.preferences.thinkingLevel;\n}\n\nfunction parseQuietModeMaxToolPreviewLines(value: unknown): number {\n const rawValue =\n typeof value === 'number' && Number.isFinite(value) ? value : DEFAULTS.preferences.quietModeMaxToolPreviewLines;\n return Math.min(QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX, Math.max(0, Math.floor(rawValue)));\n}\n\nfunction parsePreferences(rawPreferences: unknown): GlobalSettings['preferences'] {\n const raw = rawPreferences && typeof rawPreferences === 'object' ? (rawPreferences as Record<string, unknown>) : {};\n\n return {\n ...DEFAULTS.preferences,\n ...raw,\n thinkingLevel: parseThinkingLevel(raw.thinkingLevel),\n quietModeMaxToolPreviewLines: parseQuietModeMaxToolPreviewLines(raw.quietModeMaxToolPreviewLines),\n };\n}\n\nfunction parseSignalSettings(rawSignals: unknown): SignalSettings {\n const raw = rawSignals && typeof rawSignals === 'object' ? (rawSignals as Record<string, unknown>) : {};\n return {\n unixSocketPubSub:\n typeof raw.unixSocketPubSub === 'boolean' ? raw.unixSocketPubSub : DEFAULTS.signals.unixSocketPubSub,\n experimentalGithubSignals:\n typeof raw.experimentalGithubSignals === 'boolean'\n ? raw.experimentalGithubSignals\n : DEFAULTS.signals.experimentalGithubSignals,\n };\n}\n\nfunction hasQuietModePreferenceSelected(rawOnboarding: unknown): boolean {\n return Boolean(\n rawOnboarding &&\n typeof rawOnboarding === 'object' &&\n Object.prototype.hasOwnProperty.call(rawOnboarding, 'quietModePreferenceSelected'),\n );\n}\n\nfunction applyQuietModePreferenceRollout(settings: GlobalSettings, rawOnboarding: unknown): void {\n if (hasQuietModePreferenceSelected(rawOnboarding)) return;\n settings.onboarding.quietModePreferenceSelected = settings.preferences.quietMode === true;\n}\n\nfunction getNewInstallDefaults(): GlobalSettings {\n const settings = structuredClone(DEFAULTS);\n settings.preferences.quietMode = true;\n settings.onboarding.quietModePreferenceSelected = true;\n return settings;\n}\n\nexport function getSettingsPath(): string {\n return join(getAppDataDir(), 'settings.json');\n}\n\nexport function getCustomProviderId(name: string): string {\n const slug = name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || 'provider';\n}\n\nexport function toCustomProviderModelId(providerName: string, modelName: string): string {\n const providerId = getCustomProviderId(providerName);\n const trimmedModelName = modelName.trim();\n const providerPrefix = `${providerId}/`;\n if (trimmedModelName.startsWith(providerPrefix)) {\n return trimmedModelName;\n }\n return `${providerId}/${trimmedModelName}`;\n}\n\n/**\n * The shared gateway catalog namespaces provider keys under their owning\n * gateway id, so a custom provider's models surface in the `/models` catalog\n * as `mastracode/<providerId>/<model>` instead of the canonical\n * `<providerId>/<model>` that model resolution expects. Persisting the\n * gateway-qualified id verbatim breaks lookup later (the provider is parsed\n * as `mastracode`). Strip the prefix before saving — but only when the\n * middle segment matches one of the user's configured custom providers, so\n * legitimate `mastracode/...` gateway-routed ids are left untouched.\n */\nexport function stripMastraCodeCustomProviderPrefix(\n modelId: string,\n customProviders: Array<Pick<CustomProviderSetting, 'name'>>,\n): string {\n const gatewayPrefix = 'mastracode/';\n if (!modelId.startsWith(gatewayPrefix)) return modelId;\n\n const rest = modelId.slice(gatewayPrefix.length);\n const [providerId, ...modelParts] = rest.split('/');\n if (!providerId || modelParts.length === 0 || modelParts.some(part => part.length === 0)) return modelId;\n\n const isCustomProvider = customProviders.some(provider => getCustomProviderId(provider.name) === providerId);\n return isCustomProvider ? rest : modelId;\n}\n\nexport function parseCustomProviders(rawProviders: unknown): CustomProviderSetting[] {\n if (!Array.isArray(rawProviders)) return [];\n\n const parsedProviders: CustomProviderSetting[] = [];\n for (const rawProvider of rawProviders) {\n if (!rawProvider || typeof rawProvider !== 'object') continue;\n\n const candidate = rawProvider as Record<string, unknown>;\n const name = typeof candidate.name === 'string' ? candidate.name.trim() : '';\n const url = typeof candidate.url === 'string' ? candidate.url.trim() : '';\n if (!name || !url) continue;\n\n const providerId = getCustomProviderId(name);\n const models = Array.isArray(candidate.models)\n ? [\n ...new Set(\n candidate.models\n .filter((model): model is string => typeof model === 'string')\n .map(model => model.trim())\n .map(model => {\n const providerPrefix = `${providerId}/`;\n if (model.startsWith(providerPrefix)) {\n return model.slice(providerPrefix.length);\n }\n return model;\n }),\n ),\n ].filter(model => model.length > 0)\n : [];\n\n const apiKey =\n typeof candidate.apiKey === 'string' && candidate.apiKey.trim().length > 0 ? candidate.apiKey.trim() : undefined;\n\n parsedProviders.push({\n name,\n url,\n ...(apiKey ? { apiKey } : {}),\n models,\n });\n }\n\n return parsedProviders;\n}\n\nconst BROWSER_PROVIDERS = new Set<BrowserProvider>(['stagehand', 'agent-browser']);\nconst STAGEHAND_ENVS = new Set<StagehandEnv>(['LOCAL', 'BROWSERBASE']);\n\n/**\n * Deep-merge and validate browser settings from JSON.\n * Explicitly validates types to handle malformed settings.json gracefully.\n */\nfunction parseBrowserSettings(rawBrowser: unknown): BrowserSettings {\n const raw = rawBrowser && typeof rawBrowser === 'object' ? (rawBrowser as Record<string, unknown>) : {};\n const rawViewport = raw.viewport && typeof raw.viewport === 'object' ? (raw.viewport as Record<string, unknown>) : {};\n const rawStagehand =\n raw.stagehand && typeof raw.stagehand === 'object' ? (raw.stagehand as Record<string, unknown>) : {};\n const rawAgentBrowser =\n raw.agentBrowser && typeof raw.agentBrowser === 'object' ? (raw.agentBrowser as Record<string, unknown>) : {};\n\n return {\n enabled: typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULTS.browser.enabled,\n provider:\n typeof raw.provider === 'string' && BROWSER_PROVIDERS.has(raw.provider as BrowserProvider)\n ? (raw.provider as BrowserProvider)\n : DEFAULTS.browser.provider,\n headless: typeof raw.headless === 'boolean' ? raw.headless : DEFAULTS.browser.headless,\n cdpUrl: typeof raw.cdpUrl === 'string' && raw.cdpUrl.trim() ? raw.cdpUrl.trim() : undefined,\n profile: typeof raw.profile === 'string' && raw.profile.trim() ? raw.profile.trim() : undefined,\n executablePath:\n typeof raw.executablePath === 'string' && raw.executablePath.trim() ? raw.executablePath.trim() : undefined,\n viewport: {\n width: typeof rawViewport.width === 'number' ? rawViewport.width : DEFAULTS.browser.viewport!.width,\n height: typeof rawViewport.height === 'number' ? rawViewport.height : DEFAULTS.browser.viewport!.height,\n },\n scope: typeof raw.scope === 'string' && (raw.scope === 'shared' || raw.scope === 'thread') ? raw.scope : undefined,\n stagehand: {\n env:\n typeof rawStagehand.env === 'string' && STAGEHAND_ENVS.has(rawStagehand.env as StagehandEnv)\n ? (rawStagehand.env as StagehandEnv)\n : DEFAULTS.browser.stagehand!.env,\n ...(typeof rawStagehand.apiKey === 'string' && rawStagehand.apiKey.trim()\n ? { apiKey: rawStagehand.apiKey.trim() }\n : {}),\n ...(typeof rawStagehand.projectId === 'string' && rawStagehand.projectId.trim()\n ? { projectId: rawStagehand.projectId.trim() }\n : {}),\n ...(typeof rawStagehand.preserveUserDataDir === 'boolean'\n ? { preserveUserDataDir: rawStagehand.preserveUserDataDir }\n : {}),\n },\n agentBrowser:\n typeof rawAgentBrowser.storageState === 'string' && rawAgentBrowser.storageState.trim()\n ? { storageState: rawAgentBrowser.storageState.trim() }\n : undefined,\n };\n}\n\nfunction parseShellPassthroughSettings(rawShellPassthrough: unknown): ShellPassthroughSettings {\n const raw =\n rawShellPassthrough && typeof rawShellPassthrough === 'object'\n ? (rawShellPassthrough as Record<string, unknown>)\n : {};\n const executable = typeof raw.executable === 'string' && raw.executable.trim() ? raw.executable.trim() : undefined;\n const family = typeof raw.family === 'string' && raw.family.trim() ? raw.family.trim() : undefined;\n const mode = typeof raw.mode === 'string' && raw.mode.trim() ? raw.mode.trim() : undefined;\n const defaultMode = executable ? undefined : DEFAULTS.shellPassthrough.mode;\n\n return {\n ...((mode ?? defaultMode) ? { mode: mode ?? defaultMode } : {}),\n ...(executable ? { executable } : {}),\n ...(family ? { family } : {}),\n };\n}\n\nfunction parseVoiceSettings(rawVoice: unknown): VoiceSettings {\n const raw = rawVoice && typeof rawVoice === 'object' ? (rawVoice as Record<string, unknown>) : {};\n const enabled = typeof raw.enabled === 'boolean' ? raw.enabled : DEFAULTS.voice.enabled;\n const engine: VoiceEngine =\n raw.engine === 'macos-native' || raw.engine === 'cloud' ? raw.engine : defaultVoiceEngine();\n // Validate provider/model against the registry, falling back to a usable entry\n // so old `{ enabled }`-only files and unknown values still resolve cleanly.\n const provider = typeof raw.provider === 'string' ? raw.provider : DEFAULTS.voice.provider;\n const model = typeof raw.model === 'string' ? raw.model : undefined;\n const resolved = resolveSTTModel(provider, model);\n return {\n enabled,\n engine,\n provider: resolved.provider,\n model: resolved.model,\n };\n}\n\nconst VALID_PROJECT_ID = /^[a-zA-Z0-9_-]+$/;\n\nfunction parseObservabilitySettings(raw: unknown): ObservabilitySettings {\n if (!raw || typeof raw !== 'object') return { resources: {}, localTracing: false };\n const obj = raw as Record<string, unknown>;\n const localTracing = obj.localTracing === true;\n const rawResources = obj.resources;\n if (!rawResources || typeof rawResources !== 'object') return { resources: {}, localTracing };\n const resources: Record<string, ObservabilityResourceConfig> = {};\n for (const [key, val] of Object.entries(rawResources as Record<string, unknown>)) {\n if (val && typeof val === 'object') {\n const v = val as Record<string, unknown>;\n if (typeof v.projectId === 'string' && VALID_PROJECT_ID.test(v.projectId)) {\n resources[key] = {\n projectId: v.projectId,\n configuredAt: typeof v.configuredAt === 'string' ? v.configuredAt : new Date().toISOString(),\n };\n }\n }\n }\n return { resources, localTracing };\n}\n\n/**\n * One-time migration: move model-related data from auth.json to settings.json.\n * Reads `_modelRanks`, `_modeModelId_*`, `_subagentModelId*` from auth.json,\n * merges them into settings, removes them from auth.json, and writes both files.\n * No-ops if auth.json has no _ prefixed model data.\n */\nfunction migrateFromAuth(settingsPath: string): boolean {\n const authPath = join(getAppDataDir(), 'auth.json');\n if (!existsSync(authPath)) return false;\n\n let authData: Record<string, any>;\n try {\n authData = JSON.parse(readFileSync(authPath, 'utf-8'));\n } catch {\n return false;\n }\n\n const modelKeys = Object.keys(authData).filter(k => k.startsWith('_'));\n if (modelKeys.length === 0) return false;\n\n // Load existing settings (or defaults) and merge auth data into it\n let settings: GlobalSettings;\n if (existsSync(settingsPath)) {\n try {\n const raw = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n settings = {\n onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },\n models: { ...DEFAULTS.models, ...raw.models },\n preferences: parsePreferences(raw.preferences),\n storage: {\n ...STORAGE_DEFAULTS,\n ...raw.storage,\n libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },\n pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg },\n },\n customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],\n customProviders: parseCustomProviders(raw.customProviders),\n modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === 'object' ? raw.modelUseCounts : {},\n updateDismissedVersion: typeof raw.updateDismissedVersion === 'string' ? raw.updateDismissedVersion : null,\n memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === 'object' ? raw.memoryGateway : {},\n lsp: raw.lsp && typeof raw.lsp === 'object' ? (raw.lsp as LSPConfig) : undefined,\n browser: parseBrowserSettings(raw.browser),\n shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),\n voice: parseVoiceSettings(raw.voice),\n signals: parseSignalSettings(raw.signals),\n observability: parseObservabilitySettings(raw.observability),\n };\n applyQuietModePreferenceRollout(settings, raw.onboarding);\n } catch {\n settings = structuredClone(DEFAULTS);\n }\n } else {\n settings = structuredClone(DEFAULTS);\n }\n\n // Migrate model use counts (only if settings doesn't already have them)\n if (authData._modelRanks && typeof authData._modelRanks === 'object') {\n settings.modelUseCounts = { ...authData._modelRanks, ...settings.modelUseCounts };\n }\n\n // Migrate per-mode model defaults (don't overwrite existing settings)\n for (const key of modelKeys) {\n const modeMatch = key.match(/^_modeModelId_(.+)$/);\n if (modeMatch?.[1] && typeof authData[key] === 'string' && !settings.models.modeDefaults[modeMatch[1]]) {\n settings.models.modeDefaults[modeMatch[1]] = authData[key];\n }\n }\n\n // Migrate subagent models (don't overwrite existing settings)\n for (const key of modelKeys) {\n if (key === '_subagentModelId' && typeof authData[key] === 'string' && !settings.models.subagentModels['default']) {\n settings.models.subagentModels['default'] = authData[key];\n }\n const saMatch = key.match(/^_subagentModelId_(.+)$/);\n if (saMatch?.[1] && typeof authData[key] === 'string' && !settings.models.subagentModels[saMatch[1]]) {\n settings.models.subagentModels[saMatch[1]] = authData[key];\n }\n }\n\n // Write migrated settings\n saveSettings(settings, settingsPath);\n\n // Clean up auth.json — remove _ prefixed keys\n for (const key of modelKeys) {\n delete authData[key];\n }\n try {\n writeFileSync(authPath, JSON.stringify(authData, null, 2), 'utf-8');\n } catch {\n // Non-fatal — settings are saved, auth cleanup can fail\n }\n\n return true;\n}\n\nconst LEGACY_VARIED_MODELS: Record<string, string> = {\n plan: 'openai/gpt-5.4',\n build: 'anthropic/claude-sonnet-4-5',\n fast: 'anthropic/claude-haiku-4-5',\n};\n\nexport function migrateLegacyVariedPack(settings: GlobalSettings): boolean {\n const legacyPackId = 'varied';\n const customPackId = 'custom:varied';\n const hasLegacyReference =\n settings.models.activeModelPackId === legacyPackId || settings.onboarding.modePackId === legacyPackId;\n\n if (!hasLegacyReference) return false;\n\n const existingIdx = settings.customModelPacks.findIndex(p => p.name === 'varied');\n if (existingIdx >= 0) {\n const existing = settings.customModelPacks[existingIdx]!;\n const modelsMatch = Object.entries(LEGACY_VARIED_MODELS).every(([k, v]) => existing.models[k] === v);\n if (!modelsMatch) {\n existing.models = { ...LEGACY_VARIED_MODELS };\n }\n } else {\n settings.customModelPacks.push({\n name: 'varied',\n models: { ...LEGACY_VARIED_MODELS },\n createdAt: new Date().toISOString(),\n });\n }\n\n if (settings.models.activeModelPackId === legacyPackId) {\n settings.models.activeModelPackId = customPackId;\n if (Object.keys(settings.models.modeDefaults).length === 0) {\n settings.models.modeDefaults = { ...LEGACY_VARIED_MODELS };\n }\n }\n\n if (settings.onboarding.modePackId === legacyPackId) {\n settings.onboarding.modePackId = customPackId;\n }\n\n return true;\n}\n\nexport function loadSettings(filePath: string = getSettingsPath()): GlobalSettings {\n // One-time migration: move model data from auth.json into settings.json\n migrateFromAuth(filePath);\n\n if (!existsSync(filePath)) return rememberLoadedSettings(getNewInstallDefaults());\n try {\n const raw = JSON.parse(readFileSync(filePath, 'utf-8'));\n // Spread raw first to preserve unknown top-level keys (forward-compatibility),\n // then overlay with parsed/typed fields so known keys are always correct.\n const settings: GlobalSettings = {\n ...raw,\n onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },\n models: { ...DEFAULTS.models, ...raw.models },\n preferences: parsePreferences(raw.preferences),\n storage: {\n ...STORAGE_DEFAULTS,\n ...raw.storage,\n libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },\n pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg },\n },\n customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],\n customProviders: parseCustomProviders(raw.customProviders),\n modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === 'object' ? raw.modelUseCounts : {},\n updateDismissedVersion: typeof raw.updateDismissedVersion === 'string' ? raw.updateDismissedVersion : null,\n memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === 'object' ? raw.memoryGateway : {},\n lsp: raw.lsp && typeof raw.lsp === 'object' ? (raw.lsp as LSPConfig) : undefined,\n browser: parseBrowserSettings(raw.browser),\n shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),\n voice: parseVoiceSettings(raw.voice),\n signals: parseSignalSettings(raw.signals),\n observability: parseObservabilitySettings(raw.observability),\n };\n\n // Migrate legacy omModelId → omModelOverride\n let settingsChanged = false;\n if (!hasQuietModePreferenceSelected(raw.onboarding)) {\n applyQuietModePreferenceRollout(settings, raw.onboarding);\n settingsChanged = true;\n }\n if (raw.models?.omModelId && !settings.models.omModelOverride) {\n settings.models.omModelOverride = raw.models.omModelId;\n settingsChanged = true;\n }\n\n if (migrateLegacyVariedPack(settings)) {\n settingsChanged = true;\n }\n\n if (settingsChanged) {\n saveSettings(settings, filePath);\n }\n\n return rememberLoadedSettings(settings);\n } catch {\n return rememberLoadedSettings(structuredClone(DEFAULTS));\n }\n}\n\nexport const THREAD_ACTIVE_MODEL_PACK_ID_KEY = 'activeModelPackId';\n\nexport interface ThreadSettings {\n activeModelPackId: string | null;\n modeModelIds: Record<string, string>;\n}\n\nexport function parseThreadSettings(metadata: Record<string, unknown> | undefined): ThreadSettings {\n const modeModelIds: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n const modeMatch = key.match(/^modeModelId_(.+)$/);\n if (modeMatch?.[1] && typeof value === 'string' && value.length > 0) {\n modeModelIds[modeMatch[1]] = value;\n }\n }\n\n const rawPackId = metadata?.[THREAD_ACTIVE_MODEL_PACK_ID_KEY];\n const activeModelPackId = typeof rawPackId === 'string' && rawPackId.length > 0 ? rawPackId : null;\n\n return {\n activeModelPackId,\n modeModelIds,\n };\n}\n\n/**\n * Resolve active model pack id for the current thread.\n *\n * Priority:\n * 1) explicit thread metadata activeModelPackId\n * 2) inferred from thread modeModelId_* values\n * 3) global settings.models.activeModelPackId\n */\nexport function resolveThreadActiveModelPackId(\n settings: GlobalSettings,\n builtinPacks: Array<{ id: string; models: Record<string, string> }>,\n metadata: Record<string, unknown> | undefined,\n): string | null {\n const threadSettings = parseThreadSettings(metadata);\n\n const isKnownPack = (packId: string): boolean => {\n if (packId.startsWith('custom:')) {\n const name = packId.slice('custom:'.length);\n return settings.customModelPacks.some(p => p.name === name);\n }\n return builtinPacks.some(p => p.id === packId);\n };\n\n if (threadSettings.activeModelPackId && isKnownPack(threadSettings.activeModelPackId)) {\n return threadSettings.activeModelPackId;\n }\n\n const allPacks: Array<{ id: string; models: Record<string, string> }> = [\n ...builtinPacks,\n ...settings.customModelPacks.map(p => ({ id: `custom:${p.name}`, models: p.models })),\n ];\n\n for (const pack of allPacks) {\n const packEntries = Object.entries(pack.models);\n const threadEntries = Object.keys(threadSettings.modeModelIds);\n const matches =\n packEntries.length === threadEntries.length &&\n packEntries.every(([modeId, modelId]) => threadSettings.modeModelIds[modeId] === modelId);\n if (matches) return pack.id;\n }\n\n if (settings.models.activeModelPackId && isKnownPack(settings.models.activeModelPackId)) {\n return settings.models.activeModelPackId;\n }\n\n return null;\n}\n\n/**\n * Resolve effective per-mode model defaults.\n *\n * If `activeModelPackId` is set, looks up the pack (built-in or custom) and\n * returns its models. Falls back to the explicit `modeDefaults` map.\n *\n * @param settings The loaded global settings.\n * @param builtinPacks Built-in packs for the current provider access\n * (from `getAvailableModePacks`). Pass `[]` if unavailable.\n */\nexport function resolveModelDefaults(\n settings: GlobalSettings,\n builtinPacks: Array<{ id: string; models: Record<string, string> }>,\n): Record<string, string> {\n const { activeModelPackId, modeDefaults } = settings.models;\n if (!activeModelPackId) return modeDefaults;\n\n // Custom pack: \"custom:<name>\"\n if (activeModelPackId.startsWith('custom:')) {\n const name = activeModelPackId.slice('custom:'.length);\n const pack = settings.customModelPacks.find(p => p.name === name);\n if (pack) return pack.models;\n // Custom pack was deleted — fall through to modeDefaults\n return modeDefaults;\n }\n\n // Built-in pack\n const builtin = builtinPacks.find(p => p.id === activeModelPackId);\n if (builtin) return builtin.models;\n\n // Unknown pack id — fall through\n return modeDefaults;\n}\n\n/**\n * Resolve the effective model ID for one of the two OM roles.\n *\n * Lookup order:\n * 1. The role-specific override (`observerModelOverride` /\n * `reflectorModelOverride`) if set.\n * 2. If `activeOmPackId` points at a built-in pack, that pack's model.\n * 3. The shared `omModelOverride` fallback.\n *\n * @param settings The loaded global settings.\n * @param role Which OM role to resolve (`'observer'` or `'reflector'`).\n * @param builtinOmPacks Built-in OM packs for the current provider access\n * (from `getAvailableOmPacks`). Pass `[]` if unavailable.\n */\nexport function resolveOmRoleModel(\n settings: GlobalSettings,\n role: 'observer' | 'reflector',\n builtinOmPacks: Array<{ id: string; modelId: string }>,\n): string | null {\n const { activeOmPackId, omModelOverride, observerModelOverride, reflectorModelOverride } = settings.models;\n const roleOverride = role === 'observer' ? observerModelOverride : reflectorModelOverride;\n if (roleOverride) return roleOverride;\n\n if (!activeOmPackId) return omModelOverride;\n if (activeOmPackId === 'custom') return omModelOverride;\n\n const pack = builtinOmPacks.find(p => p.id === activeOmPackId);\n if (pack) return pack.modelId;\n\n return omModelOverride;\n}\n\n/**\n * @deprecated Use `resolveOmRoleModel(settings, 'observer' | 'reflector', ...)`.\n * Equivalent to resolving the observer role (existing callers set both observer\n * and reflector to the same value).\n */\nexport function resolveOmModel(\n settings: GlobalSettings,\n builtinOmPacks: Array<{ id: string; modelId: string }>,\n): string | null {\n return resolveOmRoleModel(settings, 'observer', builtinOmPacks);\n}\n\nfunction getSignalSettingsForSave(settings: GlobalSettings, filePath: string): SignalSettings {\n const loadedSignals = loadedSignalSettings.get(settings);\n if (!loadedSignals || !signalSettingsEqual(settings.signals, loadedSignals) || !existsSync(filePath)) {\n return settings.signals;\n }\n\n try {\n const currentRaw = JSON.parse(readFileSync(filePath, 'utf-8')) as Record<string, unknown>;\n const currentSignals = parseSignalSettings(currentRaw.signals);\n if (!signalSettingsEqual(currentSignals, loadedSignals)) {\n return currentSignals;\n }\n } catch {\n // If the current file is unreadable, fall back to the caller's settings.\n }\n\n return settings.signals;\n}\n\nexport function saveSettings(settings: GlobalSettings, filePath: string = getSettingsPath()): void {\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n const signals = getSignalSettingsForSave(settings, filePath);\n settings.signals = signals;\n loadedSignalSettings.set(settings, cloneSignalSettings(signals));\n writeFileSync(filePath, JSON.stringify(settings, null, 2), 'utf-8');\n}\n\n/** Marker file name to track which provider last used a profile. */\nconst PROFILE_PROVIDER_MARKER = '.mastra-provider';\n\n/**\n * Check which provider last used a profile directory.\n * Returns the provider name if the marker exists, undefined otherwise.\n */\nexport function getProfileProvider(profilePath: string): BrowserProvider | undefined {\n const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);\n if (!existsSync(markerPath)) {\n return undefined;\n }\n try {\n const content = readFileSync(markerPath, 'utf-8').trim();\n if (content === 'stagehand' || content === 'agent-browser') {\n return content;\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Write the provider marker to a profile directory.\n * Creates the directory if it doesn't exist.\n */\nexport function setProfileProvider(profilePath: string, provider: BrowserProvider): void {\n const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);\n if (!existsSync(profilePath)) {\n mkdirSync(profilePath, { recursive: true });\n }\n writeFileSync(markerPath, provider, 'utf-8');\n}\n\n/**\n * Check if a profile has a provider mismatch.\n * Returns the existing provider if there's a mismatch, undefined otherwise.\n */\nexport function checkProfileProviderMismatch(\n profilePath: string | undefined,\n targetProvider: BrowserProvider,\n): BrowserProvider | undefined {\n if (!profilePath) {\n return undefined;\n }\n const existingProvider = getProfileProvider(profilePath);\n if (existingProvider && existingProvider !== targetProvider) {\n return existingProvider;\n }\n return undefined;\n}\n\nfunction browserRecordingOptions() {\n return { outputDir: join(getAppDataDir(), 'browser-recordings') };\n}\n\n/**\n * Create a browser instance from settings.\n * Shared by startup (main.ts) and live reconfiguration (/browser command).\n * Returns undefined if browser is disabled.\n */\nexport async function createBrowserFromSettings(settings: BrowserSettings): Promise<MastraBrowser | undefined> {\n if (!settings.enabled) {\n return undefined;\n }\n\n const { provider, headless, viewport, cdpUrl, profile, executablePath, stagehand, agentBrowser } = settings;\n\n // Chrome only allows one process per profile directory, so force 'shared' scope\n // when a profile is set. Otherwise use the user's setting (or provider default).\n const scope = profile ? ('shared' as const) : settings.scope;\n\n // Common launch options (no CDP)\n const launchConfig = { headless, viewport, profile, executablePath, scope } as const;\n\n if (provider === 'stagehand') {\n const { StagehandBrowser } = await import('@mastra/stagehand');\n const stagehandOpts: Record<string, unknown> = {\n env: stagehand?.env ?? 'LOCAL',\n apiKey: stagehand?.apiKey ?? process.env.BROWSERBASE_API_KEY,\n projectId: stagehand?.projectId ?? process.env.BROWSERBASE_PROJECT_ID,\n preserveUserDataDir: stagehand?.preserveUserDataDir,\n recording: browserRecordingOptions(),\n };\n\n // When the user has an active OpenAI Codex (ChatGPT) subscription, route\n // Stagehand through the Codex endpoint. We use the AI SDK provider's\n // standard hooks (baseURL, headers, fetch, and middleware) instead of a\n // URL-rewriting fetch:\n // - baseURL: target Codex's Responses API directly (no URL rewriting).\n // - headers: static Codex identifiers (originator, UA, account id).\n // - fetch: a tiny refresher that injects the live OAuth bearer per call,\n // since AI SDK takes `apiKey` as a static string.\n // - middleware: createCodexMiddleware() sets `store: false`, which Codex\n // requires on every request.\n // Model is `gpt-5.4-mini`, the current ChatGPT-sign-in Codex whitelist\n // pick suited to Stagehand's vision + structured-output workload.\n const authStorage = new AuthStorage();\n const cred = authStorage.get('openai-codex');\n if (cred?.type === 'oauth') {\n const accountId = (cred as any).accountId as string | undefined;\n stagehandOpts.model = {\n modelName: 'openai/gpt-5.4-mini',\n apiKey: 'codex-oauth',\n baseURL: 'https://chatgpt.com/backend-api/codex',\n headers: {\n originator: 'mastracode',\n 'User-Agent': 'mastracode',\n ...(accountId ? { 'ChatGPT-Account-ID': accountId } : {}),\n },\n fetch: buildCodexStagehandFetch(authStorage),\n middleware: createCodexMiddleware(),\n } as any;\n }\n\n return cdpUrl\n ? new StagehandBrowser({ ...launchConfig, cdpUrl, scope: 'shared', ...stagehandOpts })\n : new StagehandBrowser({ ...launchConfig, ...stagehandOpts });\n } else if (provider === 'agent-browser') {\n const { AgentBrowser } = await import('@mastra/agent-browser');\n const agentBrowserOpts = {\n storageState: agentBrowser?.storageState,\n recording: browserRecordingOptions(),\n };\n return cdpUrl\n ? new AgentBrowser({ ...launchConfig, cdpUrl, scope: 'shared', ...agentBrowserOpts })\n : new AgentBrowser({ ...launchConfig, ...agentBrowserOpts, scope });\n }\n\n throw new Error(`Unsupported browser provider: ${provider}`);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/code-sdk",
3
- "version": "1.1.3",
3
+ "version": "1.2.0-alpha.1",
4
4
  "description": "Mastra Code SDK: the agent core behind Mastra Code (everything except the TUI) — build your own UIs and surfaces on top of it",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -46,29 +46,29 @@
46
46
  "@ai-sdk/openai": "^3.0.88",
47
47
  "@ai-sdk/openai-compatible": "^2.0.62",
48
48
  "@ast-grep/napi": "^0.42.0",
49
- "@aws-sdk/credential-providers": "^3.864.0",
49
+ "@aws-sdk/credential-providers": "^3.1095.0",
50
50
  "ai": "^6.0.236",
51
51
  "execa": "^9.6.1",
52
52
  "libsql": "^0.5.29",
53
- "posthog-node": "^5.37.0",
53
+ "posthog-node": "^5.46.1",
54
54
  "tokenx": "^1.3.0",
55
55
  "vscode-jsonrpc": "^8.2.1",
56
56
  "vscode-languageserver-protocol": "^3.17.5",
57
57
  "yaml": "^2.7.1",
58
58
  "zod": "^4.3.6",
59
- "@mastra/core": "1.57.0",
60
- "@mastra/duckdb": "1.6.0",
59
+ "@mastra/agent-browser": "0.5.0",
60
+ "@mastra/duckdb": "1.6.1-alpha.0",
61
61
  "@mastra/fastembed": "1.2.0",
62
62
  "@mastra/github-signals": "0.2.4",
63
- "@mastra/libsql": "1.19.0",
64
- "@mastra/memory": "1.26.0",
65
- "@mastra/mcp": "1.15.1",
66
- "@mastra/observability": "1.16.5",
67
- "@mastra/schema-compat": "1.3.5",
68
- "@mastra/agent-browser": "0.5.0",
63
+ "@mastra/libsql": "1.20.0-alpha.0",
64
+ "@mastra/mcp": "1.16.0-alpha.0",
65
+ "@mastra/pg": "1.20.0-alpha.0",
66
+ "@mastra/schema-compat": "1.3.6-alpha.0",
69
67
  "@mastra/stagehand": "0.3.1",
70
68
  "@mastra/tavily": "1.1.1",
71
- "@mastra/pg": "1.19.0"
69
+ "@mastra/observability": "1.16.6-alpha.0",
70
+ "@mastra/memory": "1.26.1-alpha.0",
71
+ "@mastra/core": "1.58.0-alpha.1"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@libsql/client": "^0.17.4",
@@ -80,8 +80,8 @@
80
80
  "typescript-eslint": "^8.57.0",
81
81
  "vitest": "4.1.10",
82
82
  "@internal/lint": "0.0.121",
83
- "@internal/workspace-test-utils": "0.0.65",
84
- "@internal/types-builder": "0.0.96"
83
+ "@internal/types-builder": "0.0.96",
84
+ "@internal/workspace-test-utils": "0.0.65"
85
85
  },
86
86
  "engines": {
87
87
  "node": ">=22.19.0"