@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2

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.
Files changed (258) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +11 -11
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"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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","names":[]}
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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"}
package/dist/mcp/types.js CHANGED
@@ -1 +1 @@
1
- //# sourceMappingURL=types.js.map
1
+ export {};
@@ -1,20 +1,17 @@
1
+ //#region src/onboarding/custom-packs.ts
1
2
  function removeCustomPackFromSettings(settings, packId) {
2
- if (!packId.startsWith("custom:")) return;
3
- const packName = packId.slice("custom:".length);
4
- const removedPack = settings.customModelPacks.find((p) => p.name === packName);
5
- settings.customModelPacks = settings.customModelPacks.filter((p) => p.name !== packName);
6
- const modeDefaultsMatchRemovedPack = !!removedPack && settings.models.modeDefaults.plan === removedPack.models.plan && settings.models.modeDefaults.build === removedPack.models.build && settings.models.modeDefaults.fast === removedPack.models.fast;
7
- if (settings.models.activeModelPackId === packId) {
8
- settings.models.activeModelPackId = null;
9
- settings.models.modeDefaults = {};
10
- } else if (modeDefaultsMatchRemovedPack) {
11
- settings.models.modeDefaults = {};
12
- }
13
- if (settings.onboarding.modePackId === packId) {
14
- settings.onboarding.modePackId = null;
15
- }
3
+ if (!packId.startsWith("custom:")) return;
4
+ const packName = packId.slice(7);
5
+ const removedPack = settings.customModelPacks.find((p) => p.name === packName);
6
+ settings.customModelPacks = settings.customModelPacks.filter((p) => p.name !== packName);
7
+ const modeDefaultsMatchRemovedPack = !!removedPack && settings.models.modeDefaults.plan === removedPack.models.plan && settings.models.modeDefaults.build === removedPack.models.build && settings.models.modeDefaults.fast === removedPack.models.fast;
8
+ if (settings.models.activeModelPackId === packId) {
9
+ settings.models.activeModelPackId = null;
10
+ settings.models.modeDefaults = {};
11
+ } else if (modeDefaultsMatchRemovedPack) settings.models.modeDefaults = {};
12
+ if (settings.onboarding.modePackId === packId) settings.onboarding.modePackId = null;
16
13
  }
17
- export {
18
- removeCustomPackFromSettings
19
- };
14
+ //#endregion
15
+ export { removeCustomPackFromSettings };
16
+
20
17
  //# sourceMappingURL=custom-packs.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/onboarding/custom-packs.ts"],"sourcesContent":["/**\n * Pure `GlobalSettings` mutation helpers for custom model packs. Shared by the\n * TUI `/models` command and the web settings routes — no UI dependencies.\n */\nimport type { GlobalSettings } from './settings.js';\n\nexport function removeCustomPackFromSettings(settings: GlobalSettings, packId: string): void {\n if (!packId.startsWith('custom:')) return;\n const packName = packId.slice('custom:'.length);\n const removedPack = settings.customModelPacks.find(p => p.name === packName);\n settings.customModelPacks = settings.customModelPacks.filter(p => p.name !== packName);\n\n const modeDefaultsMatchRemovedPack =\n !!removedPack &&\n settings.models.modeDefaults.plan === removedPack.models.plan &&\n settings.models.modeDefaults.build === removedPack.models.build &&\n settings.models.modeDefaults.fast === removedPack.models.fast;\n\n if (settings.models.activeModelPackId === packId) {\n settings.models.activeModelPackId = null;\n settings.models.modeDefaults = {};\n } else if (modeDefaultsMatchRemovedPack) {\n settings.models.modeDefaults = {};\n }\n\n if (settings.onboarding.modePackId === packId) {\n settings.onboarding.modePackId = null;\n }\n}\n"],"mappings":"AAMO,SAAS,6BAA6B,UAA0B,QAAsB;AAC3F,MAAI,CAAC,OAAO,WAAW,SAAS,EAAG;AACnC,QAAM,WAAW,OAAO,MAAM,UAAU,MAAM;AAC9C,QAAM,cAAc,SAAS,iBAAiB,KAAK,OAAK,EAAE,SAAS,QAAQ;AAC3E,WAAS,mBAAmB,SAAS,iBAAiB,OAAO,OAAK,EAAE,SAAS,QAAQ;AAErF,QAAM,+BACJ,CAAC,CAAC,eACF,SAAS,OAAO,aAAa,SAAS,YAAY,OAAO,QACzD,SAAS,OAAO,aAAa,UAAU,YAAY,OAAO,SAC1D,SAAS,OAAO,aAAa,SAAS,YAAY,OAAO;AAE3D,MAAI,SAAS,OAAO,sBAAsB,QAAQ;AAChD,aAAS,OAAO,oBAAoB;AACpC,aAAS,OAAO,eAAe,CAAC;AAAA,EAClC,WAAW,8BAA8B;AACvC,aAAS,OAAO,eAAe,CAAC;AAAA,EAClC;AAEA,MAAI,SAAS,WAAW,eAAe,QAAQ;AAC7C,aAAS,WAAW,aAAa;AAAA,EACnC;AACF;","names":[]}
1
+ {"version":3,"file":"custom-packs.js","names":[],"sources":["../../src/onboarding/custom-packs.ts"],"sourcesContent":["/**\n * Pure `GlobalSettings` mutation helpers for custom model packs. Shared by the\n * TUI `/models` command and the web settings routes — no UI dependencies.\n */\nimport type { GlobalSettings } from './settings.js';\n\nexport function removeCustomPackFromSettings(settings: GlobalSettings, packId: string): void {\n if (!packId.startsWith('custom:')) return;\n const packName = packId.slice('custom:'.length);\n const removedPack = settings.customModelPacks.find(p => p.name === packName);\n settings.customModelPacks = settings.customModelPacks.filter(p => p.name !== packName);\n\n const modeDefaultsMatchRemovedPack =\n !!removedPack &&\n settings.models.modeDefaults.plan === removedPack.models.plan &&\n settings.models.modeDefaults.build === removedPack.models.build &&\n settings.models.modeDefaults.fast === removedPack.models.fast;\n\n if (settings.models.activeModelPackId === packId) {\n settings.models.activeModelPackId = null;\n settings.models.modeDefaults = {};\n } else if (modeDefaultsMatchRemovedPack) {\n settings.models.modeDefaults = {};\n }\n\n if (settings.onboarding.modePackId === packId) {\n settings.onboarding.modePackId = null;\n }\n}\n"],"mappings":";AAMA,SAAgB,6BAA6B,UAA0B,QAAsB;CAC3F,IAAI,CAAC,OAAO,WAAW,SAAS,GAAG;CACnC,MAAM,WAAW,OAAO,MAAM,CAAgB;CAC9C,MAAM,cAAc,SAAS,iBAAiB,MAAK,MAAK,EAAE,SAAS,QAAQ;CAC3E,SAAS,mBAAmB,SAAS,iBAAiB,QAAO,MAAK,EAAE,SAAS,QAAQ;CAErF,MAAM,+BACJ,CAAC,CAAC,eACF,SAAS,OAAO,aAAa,SAAS,YAAY,OAAO,QACzD,SAAS,OAAO,aAAa,UAAU,YAAY,OAAO,SAC1D,SAAS,OAAO,aAAa,SAAS,YAAY,OAAO;CAE3D,IAAI,SAAS,OAAO,sBAAsB,QAAQ;EAChD,SAAS,OAAO,oBAAoB;EACpC,SAAS,OAAO,eAAe,CAAC;CAClC,OAAO,IAAI,8BACT,SAAS,OAAO,eAAe,CAAC;CAGlC,IAAI,SAAS,WAAW,eAAe,QACrC,SAAS,WAAW,aAAa;AAErC"}
@@ -1,28 +1,30 @@
1
1
  import { getCustomProviderId } from "./settings.js";
2
+ //#region src/onboarding/custom-providers.ts
3
+ /**
4
+ * Pure `GlobalSettings` mutation helpers for custom OpenAI-compatible
5
+ * providers. Shared by the TUI `/custom-providers` command and the web
6
+ * settings routes — no UI dependencies.
7
+ */
2
8
  function normalizeProvider(input) {
3
- return {
4
- name: input.name.trim(),
5
- url: input.url.trim(),
6
- apiKey: input.apiKey?.trim() || void 0,
7
- models: [...new Set(input.models.map((model) => model.trim()).filter(Boolean))]
8
- };
9
+ return {
10
+ name: input.name.trim(),
11
+ url: input.url.trim(),
12
+ apiKey: input.apiKey?.trim() || void 0,
13
+ models: [...new Set(input.models.map((model) => model.trim()).filter(Boolean))]
14
+ };
9
15
  }
10
16
  function upsertCustomProviderInSettings(settings, provider, previousProviderId) {
11
- const next = normalizeProvider(provider);
12
- const nextProviderId = getCustomProviderId(next.name);
13
- const filteredProviders = settings.customProviders.filter((existing) => {
14
- const id = getCustomProviderId(existing.name);
15
- return id !== nextProviderId && (!previousProviderId || id !== previousProviderId);
16
- });
17
- settings.customProviders = [...filteredProviders, next];
17
+ const next = normalizeProvider(provider);
18
+ const nextProviderId = getCustomProviderId(next.name);
19
+ settings.customProviders = [...settings.customProviders.filter((existing) => {
20
+ const id = getCustomProviderId(existing.name);
21
+ return id !== nextProviderId && (!previousProviderId || id !== previousProviderId);
22
+ }), next];
18
23
  }
19
24
  function removeCustomProviderFromSettings(settings, providerId) {
20
- settings.customProviders = settings.customProviders.filter(
21
- (provider) => getCustomProviderId(provider.name) !== providerId
22
- );
25
+ settings.customProviders = settings.customProviders.filter((provider) => getCustomProviderId(provider.name) !== providerId);
23
26
  }
24
- export {
25
- removeCustomProviderFromSettings,
26
- upsertCustomProviderInSettings
27
- };
27
+ //#endregion
28
+ export { removeCustomProviderFromSettings, upsertCustomProviderInSettings };
29
+
28
30
  //# sourceMappingURL=custom-providers.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/onboarding/custom-providers.ts"],"sourcesContent":["/**\n * Pure `GlobalSettings` mutation helpers for custom OpenAI-compatible\n * providers. Shared by the TUI `/custom-providers` command and the web\n * settings routes — no UI dependencies.\n */\nimport { getCustomProviderId } from './settings.js';\nimport type { CustomProviderSetting, GlobalSettings } from './settings.js';\n\nfunction normalizeProvider(input: CustomProviderSetting): CustomProviderSetting {\n return {\n name: input.name.trim(),\n url: input.url.trim(),\n apiKey: input.apiKey?.trim() || undefined,\n models: [...new Set(input.models.map(model => model.trim()).filter(Boolean))],\n };\n}\n\nexport function upsertCustomProviderInSettings(\n settings: GlobalSettings,\n provider: CustomProviderSetting,\n previousProviderId?: string,\n): void {\n const next = normalizeProvider(provider);\n const nextProviderId = getCustomProviderId(next.name);\n const filteredProviders = settings.customProviders.filter(existing => {\n const id = getCustomProviderId(existing.name);\n return id !== nextProviderId && (!previousProviderId || id !== previousProviderId);\n });\n settings.customProviders = [...filteredProviders, next];\n}\n\nexport function removeCustomProviderFromSettings(settings: GlobalSettings, providerId: string): void {\n settings.customProviders = settings.customProviders.filter(\n provider => getCustomProviderId(provider.name) !== providerId,\n );\n}\n"],"mappings":"AAKA,SAAS,2BAA2B;AAGpC,SAAS,kBAAkB,OAAqD;AAC9E,SAAO;AAAA,IACL,MAAM,MAAM,KAAK,KAAK;AAAA,IACtB,KAAK,MAAM,IAAI,KAAK;AAAA,IACpB,QAAQ,MAAM,QAAQ,KAAK,KAAK;AAAA,IAChC,QAAQ,CAAC,GAAG,IAAI,IAAI,MAAM,OAAO,IAAI,WAAS,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC;AAAA,EAC9E;AACF;AAEO,SAAS,+BACd,UACA,UACA,oBACM;AACN,QAAM,OAAO,kBAAkB,QAAQ;AACvC,QAAM,iBAAiB,oBAAoB,KAAK,IAAI;AACpD,QAAM,oBAAoB,SAAS,gBAAgB,OAAO,cAAY;AACpE,UAAM,KAAK,oBAAoB,SAAS,IAAI;AAC5C,WAAO,OAAO,mBAAmB,CAAC,sBAAsB,OAAO;AAAA,EACjE,CAAC;AACD,WAAS,kBAAkB,CAAC,GAAG,mBAAmB,IAAI;AACxD;AAEO,SAAS,iCAAiC,UAA0B,YAA0B;AACnG,WAAS,kBAAkB,SAAS,gBAAgB;AAAA,IAClD,cAAY,oBAAoB,SAAS,IAAI,MAAM;AAAA,EACrD;AACF;","names":[]}
1
+ {"version":3,"file":"custom-providers.js","names":[],"sources":["../../src/onboarding/custom-providers.ts"],"sourcesContent":["/**\n * Pure `GlobalSettings` mutation helpers for custom OpenAI-compatible\n * providers. Shared by the TUI `/custom-providers` command and the web\n * settings routes — no UI dependencies.\n */\nimport { getCustomProviderId } from './settings.js';\nimport type { CustomProviderSetting, GlobalSettings } from './settings.js';\n\nfunction normalizeProvider(input: CustomProviderSetting): CustomProviderSetting {\n return {\n name: input.name.trim(),\n url: input.url.trim(),\n apiKey: input.apiKey?.trim() || undefined,\n models: [...new Set(input.models.map(model => model.trim()).filter(Boolean))],\n };\n}\n\nexport function upsertCustomProviderInSettings(\n settings: GlobalSettings,\n provider: CustomProviderSetting,\n previousProviderId?: string,\n): void {\n const next = normalizeProvider(provider);\n const nextProviderId = getCustomProviderId(next.name);\n const filteredProviders = settings.customProviders.filter(existing => {\n const id = getCustomProviderId(existing.name);\n return id !== nextProviderId && (!previousProviderId || id !== previousProviderId);\n });\n settings.customProviders = [...filteredProviders, next];\n}\n\nexport function removeCustomProviderFromSettings(settings: GlobalSettings, providerId: string): void {\n settings.customProviders = settings.customProviders.filter(\n provider => getCustomProviderId(provider.name) !== providerId,\n );\n}\n"],"mappings":";;;;;;;AAQA,SAAS,kBAAkB,OAAqD;CAC9E,OAAO;EACL,MAAM,MAAM,KAAK,KAAK;EACtB,KAAK,MAAM,IAAI,KAAK;EACpB,QAAQ,MAAM,QAAQ,KAAK,KAAK,KAAA;EAChC,QAAQ,CAAC,GAAG,IAAI,IAAI,MAAM,OAAO,KAAI,UAAS,MAAM,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC;CAC9E;AACF;AAEA,SAAgB,+BACd,UACA,UACA,oBACM;CACN,MAAM,OAAO,kBAAkB,QAAQ;CACvC,MAAM,iBAAiB,oBAAoB,KAAK,IAAI;CAKpD,SAAS,kBAAkB,CAAC,GAJF,SAAS,gBAAgB,QAAO,aAAY;EACpE,MAAM,KAAK,oBAAoB,SAAS,IAAI;EAC5C,OAAO,OAAO,mBAAmB,CAAC,sBAAsB,OAAO;CACjE,CAC+C,GAAG,IAAI;AACxD;AAEA,SAAgB,iCAAiC,UAA0B,YAA0B;CACnG,SAAS,kBAAkB,SAAS,gBAAgB,QAClD,aAAY,oBAAoB,SAAS,IAAI,MAAM,UACrD;AACF"}
@@ -1,4 +1,4 @@
1
- export { getAvailableModePacks, getAvailableOmPacks, ONBOARDING_VERSION } from './packs.js';
1
+ export { getAvailableModePacks, getAvailableOmPacks, selectPreferredOMPack, ONBOARDING_VERSION } from './packs.js';
2
2
  export type { ModePack, OMPack, ProviderAccess, ProviderAccessLevel } from './packs.js';
3
3
  export { loadSettings, saveSettings, getSettingsPath, resolveModelDefaults, resolveOmModel, resolveOmRoleModel, } from './settings.js';
4
4
  export type { GlobalSettings, CustomPack } from './settings.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/onboarding/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC5F,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/onboarding/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnH,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
@@ -1,21 +1,3 @@
1
- import { getAvailableModePacks, getAvailableOmPacks, ONBOARDING_VERSION } from "./packs.js";
2
- import {
3
- loadSettings,
4
- saveSettings,
5
- getSettingsPath,
6
- resolveModelDefaults,
7
- resolveOmModel,
8
- resolveOmRoleModel
9
- } from "./settings.js";
10
- export {
11
- ONBOARDING_VERSION,
12
- getAvailableModePacks,
13
- getAvailableOmPacks,
14
- getSettingsPath,
15
- loadSettings,
16
- resolveModelDefaults,
17
- resolveOmModel,
18
- resolveOmRoleModel,
19
- saveSettings
20
- };
21
- //# sourceMappingURL=index.js.map
1
+ import { getSettingsPath, loadSettings, resolveModelDefaults, resolveOmModel, resolveOmRoleModel, saveSettings } from "./settings.js";
2
+ import { ONBOARDING_VERSION, getAvailableModePacks, getAvailableOmPacks, selectPreferredOMPack } from "./packs.js";
3
+ export { ONBOARDING_VERSION, getAvailableModePacks, getAvailableOmPacks, getSettingsPath, loadSettings, resolveModelDefaults, resolveOmModel, resolveOmRoleModel, saveSettings, selectPreferredOMPack };
@@ -3,7 +3,12 @@
3
3
  * configuration. Shared by the TUI `/om` command and the web settings
4
4
  * routes — no UI dependencies.
5
5
  */
6
+ import type { OMPack } from './packs.js';
6
7
  import type { GlobalSettings } from './settings.js';
8
+ /** Whether the user has already chosen any persisted OM model or pack. */
9
+ export declare function hasExplicitOMConfiguration(settings: GlobalSettings): boolean;
10
+ /** Seed a built-in OM pack unless the user already chose one; true when settings changed. */
11
+ export declare function applyOMDefaultIfUnconfigured(settings: GlobalSettings, pack: OMPack): boolean;
7
12
  /**
8
13
  * Apply a role-specific OM model override to an in-memory `GlobalSettings`.
9
14
  *
@@ -1 +1 @@
1
- {"version":3,"file":"om-settings.d.ts","sourceRoot":"","sources":["../../src/onboarding/om-settings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,UAAU,GAAG,WAAW,EAC9B,OAAO,EAAE,MAAM,EACf,uBAAuB,EAAE,MAAM,GAAG,IAAI,GACrC,IAAI,CAgBN;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAIzE"}
1
+ {"version":3,"file":"om-settings.d.ts","sourceRoot":"","sources":["../../src/onboarding/om-settings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,0EAA0E;AAC1E,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAO5E;AAED,6FAA6F;AAC7F,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAO5F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,UAAU,GAAG,WAAW,EAC9B,OAAO,EAAE,MAAM,EACf,uBAAuB,EAAE,MAAM,GAAG,IAAI,GACrC,IAAI,CAgBN;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAIzE"}
@@ -1,26 +1,47 @@
1
1
  import { loadSettings, saveSettings } from "./settings.js";
2
+ //#region src/onboarding/om-settings.ts
3
+ /** Whether the user has already chosen any persisted OM model or pack. */
4
+ function hasExplicitOMConfiguration(settings) {
5
+ const { activeOmPackId, omModelOverride, observerModelOverride, reflectorModelOverride } = settings.models;
6
+ if (omModelOverride || observerModelOverride || reflectorModelOverride) return true;
7
+ return [settings.onboarding.omPackId, activeOmPackId].some((packId) => packId && packId !== "custom");
8
+ }
9
+ /** Seed a built-in OM pack unless the user already chose one; true when settings changed. */
10
+ function applyOMDefaultIfUnconfigured(settings, pack) {
11
+ if (hasExplicitOMConfiguration(settings)) return false;
12
+ settings.onboarding.omPackId = pack.id;
13
+ settings.models.activeOmPackId = pack.id;
14
+ settings.models.omModelOverride = null;
15
+ return true;
16
+ }
17
+ /**
18
+ * Apply a role-specific OM model override to an in-memory `GlobalSettings`.
19
+ *
20
+ * When switching `activeOmPackId` from a built-in pack to `'custom'` we also
21
+ * snapshot the *other* role's currently-resolved model into its override
22
+ * field. Without this, the other role would silently lose its model on next
23
+ * startup because `resolveOmRoleModel` would no longer resolve it from the
24
+ * (now-overridden) pack.
25
+ *
26
+ * Exported for unit testing; `persistOmRoleOverride` is the disk-backed wrapper.
27
+ */
2
28
  function applyOmRoleOverride(settings, role, modelId, otherRoleCurrentModelId) {
3
- const wasBuiltinPack = settings.models.activeOmPackId !== null && settings.models.activeOmPackId !== "custom";
4
- if (role === "observer") {
5
- if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.reflectorModelOverride) {
6
- settings.models.reflectorModelOverride = otherRoleCurrentModelId;
7
- }
8
- settings.models.observerModelOverride = modelId;
9
- } else {
10
- if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.observerModelOverride) {
11
- settings.models.observerModelOverride = otherRoleCurrentModelId;
12
- }
13
- settings.models.reflectorModelOverride = modelId;
14
- }
15
- settings.models.activeOmPackId = "custom";
29
+ const wasBuiltinPack = settings.models.activeOmPackId !== null && settings.models.activeOmPackId !== "custom";
30
+ if (role === "observer") {
31
+ if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.reflectorModelOverride) settings.models.reflectorModelOverride = otherRoleCurrentModelId;
32
+ settings.models.observerModelOverride = modelId;
33
+ } else {
34
+ if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.observerModelOverride) settings.models.observerModelOverride = otherRoleCurrentModelId;
35
+ settings.models.reflectorModelOverride = modelId;
36
+ }
37
+ settings.models.activeOmPackId = "custom";
16
38
  }
17
39
  function persistOmObserveAttachments(value) {
18
- const settings = loadSettings();
19
- settings.models.omObserveAttachments = value;
20
- saveSettings(settings);
40
+ const settings = loadSettings();
41
+ settings.models.omObserveAttachments = value;
42
+ saveSettings(settings);
21
43
  }
22
- export {
23
- applyOmRoleOverride,
24
- persistOmObserveAttachments
25
- };
44
+ //#endregion
45
+ export { applyOMDefaultIfUnconfigured, applyOmRoleOverride, hasExplicitOMConfiguration, persistOmObserveAttachments };
46
+
26
47
  //# sourceMappingURL=om-settings.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/onboarding/om-settings.ts"],"sourcesContent":["/**\n * Pure `GlobalSettings` mutation helpers for observational-memory (OM)\n * configuration. Shared by the TUI `/om` command and the web settings\n * routes — no UI dependencies.\n */\nimport type { GlobalSettings } from './settings.js';\nimport { loadSettings, saveSettings } from './settings.js';\n\n/**\n * Apply a role-specific OM model override to an in-memory `GlobalSettings`.\n *\n * When switching `activeOmPackId` from a built-in pack to `'custom'` we also\n * snapshot the *other* role's currently-resolved model into its override\n * field. Without this, the other role would silently lose its model on next\n * startup because `resolveOmRoleModel` would no longer resolve it from the\n * (now-overridden) pack.\n *\n * Exported for unit testing; `persistOmRoleOverride` is the disk-backed wrapper.\n */\nexport function applyOmRoleOverride(\n settings: GlobalSettings,\n role: 'observer' | 'reflector',\n modelId: string,\n otherRoleCurrentModelId: string | null,\n): void {\n const wasBuiltinPack = settings.models.activeOmPackId !== null && settings.models.activeOmPackId !== 'custom';\n\n if (role === 'observer') {\n if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.reflectorModelOverride) {\n settings.models.reflectorModelOverride = otherRoleCurrentModelId;\n }\n settings.models.observerModelOverride = modelId;\n } else {\n if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.observerModelOverride) {\n settings.models.observerModelOverride = otherRoleCurrentModelId;\n }\n settings.models.reflectorModelOverride = modelId;\n }\n\n settings.models.activeOmPackId = 'custom';\n}\n\nexport function persistOmObserveAttachments(value: 'auto' | boolean): void {\n const settings = loadSettings();\n settings.models.omObserveAttachments = value;\n saveSettings(settings);\n}\n"],"mappings":"AAMA,SAAS,cAAc,oBAAoB;AAapC,SAAS,oBACd,UACA,MACA,SACA,yBACM;AACN,QAAM,iBAAiB,SAAS,OAAO,mBAAmB,QAAQ,SAAS,OAAO,mBAAmB;AAErG,MAAI,SAAS,YAAY;AACvB,QAAI,kBAAkB,2BAA2B,CAAC,SAAS,OAAO,wBAAwB;AACxF,eAAS,OAAO,yBAAyB;AAAA,IAC3C;AACA,aAAS,OAAO,wBAAwB;AAAA,EAC1C,OAAO;AACL,QAAI,kBAAkB,2BAA2B,CAAC,SAAS,OAAO,uBAAuB;AACvF,eAAS,OAAO,wBAAwB;AAAA,IAC1C;AACA,aAAS,OAAO,yBAAyB;AAAA,EAC3C;AAEA,WAAS,OAAO,iBAAiB;AACnC;AAEO,SAAS,4BAA4B,OAA+B;AACzE,QAAM,WAAW,aAAa;AAC9B,WAAS,OAAO,uBAAuB;AACvC,eAAa,QAAQ;AACvB;","names":[]}
1
+ {"version":3,"file":"om-settings.js","names":[],"sources":["../../src/onboarding/om-settings.ts"],"sourcesContent":["/**\n * Pure `GlobalSettings` mutation helpers for observational-memory (OM)\n * configuration. Shared by the TUI `/om` command and the web settings\n * routes — no UI dependencies.\n */\nimport type { OMPack } from './packs.js';\nimport type { GlobalSettings } from './settings.js';\nimport { loadSettings, saveSettings } from './settings.js';\n\n/** Whether the user has already chosen any persisted OM model or pack. */\nexport function hasExplicitOMConfiguration(settings: GlobalSettings): boolean {\n const { activeOmPackId, omModelOverride, observerModelOverride, reflectorModelOverride } = settings.models;\n if (omModelOverride || observerModelOverride || reflectorModelOverride) return true;\n\n // 'custom' without a model is what onboarding persists when no provider was\n // reachable — a forced non-choice, not a preference worth preserving.\n return [settings.onboarding.omPackId, activeOmPackId].some(packId => packId && packId !== 'custom');\n}\n\n/** Seed a built-in OM pack unless the user already chose one; true when settings changed. */\nexport function applyOMDefaultIfUnconfigured(settings: GlobalSettings, pack: OMPack): boolean {\n if (hasExplicitOMConfiguration(settings)) return false;\n\n settings.onboarding.omPackId = pack.id;\n settings.models.activeOmPackId = pack.id;\n settings.models.omModelOverride = null;\n return true;\n}\n\n/**\n * Apply a role-specific OM model override to an in-memory `GlobalSettings`.\n *\n * When switching `activeOmPackId` from a built-in pack to `'custom'` we also\n * snapshot the *other* role's currently-resolved model into its override\n * field. Without this, the other role would silently lose its model on next\n * startup because `resolveOmRoleModel` would no longer resolve it from the\n * (now-overridden) pack.\n *\n * Exported for unit testing; `persistOmRoleOverride` is the disk-backed wrapper.\n */\nexport function applyOmRoleOverride(\n settings: GlobalSettings,\n role: 'observer' | 'reflector',\n modelId: string,\n otherRoleCurrentModelId: string | null,\n): void {\n const wasBuiltinPack = settings.models.activeOmPackId !== null && settings.models.activeOmPackId !== 'custom';\n\n if (role === 'observer') {\n if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.reflectorModelOverride) {\n settings.models.reflectorModelOverride = otherRoleCurrentModelId;\n }\n settings.models.observerModelOverride = modelId;\n } else {\n if (wasBuiltinPack && otherRoleCurrentModelId && !settings.models.observerModelOverride) {\n settings.models.observerModelOverride = otherRoleCurrentModelId;\n }\n settings.models.reflectorModelOverride = modelId;\n }\n\n settings.models.activeOmPackId = 'custom';\n}\n\nexport function persistOmObserveAttachments(value: 'auto' | boolean): void {\n const settings = loadSettings();\n settings.models.omObserveAttachments = value;\n saveSettings(settings);\n}\n"],"mappings":";;;AAUA,SAAgB,2BAA2B,UAAmC;CAC5E,MAAM,EAAE,gBAAgB,iBAAiB,uBAAuB,2BAA2B,SAAS;CACpG,IAAI,mBAAmB,yBAAyB,wBAAwB,OAAO;CAI/E,OAAO,CAAC,SAAS,WAAW,UAAU,cAAc,CAAC,CAAC,MAAK,WAAU,UAAU,WAAW,QAAQ;AACpG;;AAGA,SAAgB,6BAA6B,UAA0B,MAAuB;CAC5F,IAAI,2BAA2B,QAAQ,GAAG,OAAO;CAEjD,SAAS,WAAW,WAAW,KAAK;CACpC,SAAS,OAAO,iBAAiB,KAAK;CACtC,SAAS,OAAO,kBAAkB;CAClC,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,oBACd,UACA,MACA,SACA,yBACM;CACN,MAAM,iBAAiB,SAAS,OAAO,mBAAmB,QAAQ,SAAS,OAAO,mBAAmB;CAErG,IAAI,SAAS,YAAY;EACvB,IAAI,kBAAkB,2BAA2B,CAAC,SAAS,OAAO,wBAChE,SAAS,OAAO,yBAAyB;EAE3C,SAAS,OAAO,wBAAwB;CAC1C,OAAO;EACL,IAAI,kBAAkB,2BAA2B,CAAC,SAAS,OAAO,uBAChE,SAAS,OAAO,wBAAwB;EAE1C,SAAS,OAAO,yBAAyB;CAC3C;CAEA,SAAS,OAAO,iBAAiB;AACnC;AAEA,SAAgB,4BAA4B,OAA+B;CACzE,MAAM,WAAW,aAAa;CAC9B,SAAS,OAAO,uBAAuB;CACvC,aAAa,QAAQ;AACvB"}
@@ -1,9 +1,3 @@
1
- /**
2
- * Onboarding "packs" — predefined model configurations for each mode.
3
- *
4
- * Each pack assigns a default model to the build, plan, and fast modes,
5
- * plus an OM (observational memory) model.
6
- */
7
1
  export interface ModePack {
8
2
  id: string;
9
3
  name: string;
@@ -43,6 +37,10 @@ export declare function getAvailableModePacks(access: ProviderAccess, savedCusto
43
37
  name: string;
44
38
  models: Record<string, string>;
45
39
  }>): ModePack[];
40
+ /** A provider's low-cost OM pack, or a custom pack on `fallbackModelId` when it has none. */
41
+ export declare function resolveProviderOMDefault(providerId: string, fallbackModelId?: string): OMPack;
46
42
  export declare function getAvailableOmPacks(access: ProviderAccess): OMPack[];
43
+ /** Best reachable built-in OM pack: preferred provider, then OAuth, then built-in order. */
44
+ export declare function selectPreferredOMPack(access: ProviderAccess, preferredProviderId?: string): OMPack | undefined;
47
45
  export declare const ONBOARDING_VERSION = 1;
48
46
  //# sourceMappingURL=packs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packs.d.ts","sourceRoot":"","sources":["../../src/onboarding/packs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE7D,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,mBAAmB,CAAC;IAC/B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,gBAAgB,EAAE,mBAAmB,CAAC;IACtC,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAAC;CACzC;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,gBAAgB,GAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAM,GAC7E,QAAQ,EAAE,CAwEZ;AAMD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,CAgDpE;AAMD,eAAO,MAAM,kBAAkB,IAAI,CAAC"}
1
+ {"version":3,"file":"packs.d.ts","sourceRoot":"","sources":["../../src/onboarding/packs.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE7D,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,mBAAmB,CAAC;IAC/B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,gBAAgB,EAAE,mBAAmB,CAAC;IACtC,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAAC;CACzC;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,gBAAgB,GAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAM,GAC7E,QAAQ,EAAE,CAwEZ;AAyCD,6FAA6F;AAC7F,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,SAAsB,GAAG,MAAM,CAkB1G;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,CAuBpE;AAED,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc9G;AAMD,eAAO,MAAM,kBAAkB,IAAI,CAAC"}