@mastra/code-sdk 1.7.3-alpha.0 → 1.8.0-alpha.10

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 (127) hide show
  1. package/dist/agent-connections/tools.d.ts.map +1 -1
  2. package/dist/agent-connections/tools.js +26 -8
  3. package/dist/agent-connections/tools.js.map +1 -1
  4. package/dist/agents/background-completion-events.d.ts +16 -0
  5. package/dist/agents/background-completion-events.d.ts.map +1 -0
  6. package/dist/agents/background-completion-events.js +19 -0
  7. package/dist/agents/background-completion-events.js.map +1 -0
  8. package/dist/agents/background-completion.d.ts +9 -0
  9. package/dist/agents/background-completion.d.ts.map +1 -0
  10. package/dist/agents/background-completion.js +59 -0
  11. package/dist/agents/background-completion.js.map +1 -0
  12. package/dist/agents/mastracode-gateway.d.ts +2 -0
  13. package/dist/agents/mastracode-gateway.d.ts.map +1 -1
  14. package/dist/agents/mastracode-gateway.js +29 -10
  15. package/dist/agents/mastracode-gateway.js.map +1 -1
  16. package/dist/agents/memory.d.ts +1 -1
  17. package/dist/agents/memory.d.ts.map +1 -1
  18. package/dist/agents/memory.js +32 -25
  19. package/dist/agents/memory.js.map +1 -1
  20. package/dist/agents/model.d.ts +41 -1
  21. package/dist/agents/model.d.ts.map +1 -1
  22. package/dist/agents/model.js +141 -7
  23. package/dist/agents/model.js.map +1 -1
  24. package/dist/agents/tool-availability.d.ts +2 -0
  25. package/dist/agents/tool-availability.d.ts.map +1 -1
  26. package/dist/agents/tool-availability.js +33 -4
  27. package/dist/agents/tool-availability.js.map +1 -1
  28. package/dist/agents/tools.d.ts +1 -1
  29. package/dist/agents/tools.d.ts.map +1 -1
  30. package/dist/agents/tools.js +30 -2
  31. package/dist/agents/tools.js.map +1 -1
  32. package/dist/agents/workspace.d.ts +2 -1
  33. package/dist/agents/workspace.d.ts.map +1 -1
  34. package/dist/agents/workspace.js +3 -3
  35. package/dist/agents/workspace.js.map +1 -1
  36. package/dist/auth/account-rotation-processor.d.ts +207 -0
  37. package/dist/auth/account-rotation-processor.d.ts.map +1 -0
  38. package/dist/auth/account-rotation-processor.js +669 -0
  39. package/dist/auth/account-rotation-processor.js.map +1 -0
  40. package/dist/auth/account-routing-context.d.ts +13 -0
  41. package/dist/auth/account-routing-context.d.ts.map +1 -0
  42. package/dist/auth/account-routing-context.js +41 -0
  43. package/dist/auth/account-routing-context.js.map +1 -0
  44. package/dist/auth/index.d.ts +1 -0
  45. package/dist/auth/index.d.ts.map +1 -1
  46. package/dist/auth/index.js +2 -1
  47. package/dist/auth/providers/anthropic.d.ts.map +1 -1
  48. package/dist/auth/providers/anthropic.js +2 -8
  49. package/dist/auth/providers/anthropic.js.map +1 -1
  50. package/dist/auth/providers/github-copilot.d.ts.map +1 -1
  51. package/dist/auth/providers/github-copilot.js +34 -12
  52. package/dist/auth/providers/github-copilot.js.map +1 -1
  53. package/dist/auth/providers/kimi-coding.d.ts.map +1 -1
  54. package/dist/auth/providers/kimi-coding.js +2 -6
  55. package/dist/auth/providers/kimi-coding.js.map +1 -1
  56. package/dist/auth/providers/openai-codex.d.ts +3 -1
  57. package/dist/auth/providers/openai-codex.d.ts.map +1 -1
  58. package/dist/auth/providers/openai-codex.js +50 -24
  59. package/dist/auth/providers/openai-codex.js.map +1 -1
  60. package/dist/auth/providers/xai.d.ts +1 -1
  61. package/dist/auth/providers/xai.d.ts.map +1 -1
  62. package/dist/auth/providers/xai.js +36 -16
  63. package/dist/auth/providers/xai.js.map +1 -1
  64. package/dist/auth/storage.d.ts +130 -8
  65. package/dist/auth/storage.d.ts.map +1 -1
  66. package/dist/auth/storage.js +602 -39
  67. package/dist/auth/storage.js.map +1 -1
  68. package/dist/auth/types.d.ts +69 -2
  69. package/dist/auth/types.d.ts.map +1 -1
  70. package/dist/goal-signal.d.ts +1 -1
  71. package/dist/goal-signal.d.ts.map +1 -1
  72. package/dist/goal-signal.js +1 -1
  73. package/dist/goal-signal.js.map +1 -1
  74. package/dist/index.d.ts +4 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +155 -38
  77. package/dist/index.js.map +1 -1
  78. package/dist/mcp/config.d.ts +17 -2
  79. package/dist/mcp/config.d.ts.map +1 -1
  80. package/dist/mcp/config.js +18 -3
  81. package/dist/mcp/config.js.map +1 -1
  82. package/dist/mcp/manager.d.ts +2 -1
  83. package/dist/mcp/manager.d.ts.map +1 -1
  84. package/dist/mcp/manager.js +13 -8
  85. package/dist/mcp/manager.js.map +1 -1
  86. package/dist/mcp/types.d.ts +15 -3
  87. package/dist/mcp/types.d.ts.map +1 -1
  88. package/dist/onboarding/custom-packs.d.ts.map +1 -1
  89. package/dist/onboarding/custom-packs.js +3 -0
  90. package/dist/onboarding/custom-packs.js.map +1 -1
  91. package/dist/onboarding/index.js +1 -1
  92. package/dist/onboarding/packs.d.ts +44 -0
  93. package/dist/onboarding/packs.d.ts.map +1 -1
  94. package/dist/onboarding/packs.js +80 -2
  95. package/dist/onboarding/packs.js.map +1 -1
  96. package/dist/onboarding/settings.d.ts +33 -0
  97. package/dist/onboarding/settings.d.ts.map +1 -1
  98. package/dist/onboarding/settings.js +88 -8
  99. package/dist/onboarding/settings.js.map +1 -1
  100. package/dist/plugin.d.ts +12 -0
  101. package/dist/plugin.d.ts.map +1 -1
  102. package/dist/plugin.js.map +1 -1
  103. package/dist/plugins/loader.d.ts.map +1 -1
  104. package/dist/plugins/loader.js +2 -1
  105. package/dist/plugins/loader.js.map +1 -1
  106. package/dist/providers/claude-max.d.ts.map +1 -1
  107. package/dist/providers/claude-max.js +4 -5
  108. package/dist/providers/claude-max.js.map +1 -1
  109. package/dist/providers/github-copilot.d.ts +1 -1
  110. package/dist/providers/github-copilot.d.ts.map +1 -1
  111. package/dist/providers/github-copilot.js +89 -37
  112. package/dist/providers/github-copilot.js.map +1 -1
  113. package/dist/providers/kimi-coding.d.ts.map +1 -1
  114. package/dist/providers/kimi-coding.js +16 -2
  115. package/dist/providers/kimi-coding.js.map +1 -1
  116. package/dist/providers/openai-codex.d.ts.map +1 -1
  117. package/dist/providers/openai-codex.js +42 -27
  118. package/dist/providers/openai-codex.js.map +1 -1
  119. package/dist/schema.d.ts +28 -1
  120. package/dist/schema.d.ts.map +1 -1
  121. package/dist/schema.js +9 -0
  122. package/dist/schema.js.map +1 -1
  123. package/dist/tools/workflows/save-workflow.d.ts +1 -1
  124. package/dist/tools/workflows/save-workflow.d.ts.map +1 -1
  125. package/dist/workflows/register-primitives.js +2 -2
  126. package/dist/workflows/register-primitives.js.map +1 -1
  127. package/package.json +17 -17
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","names":[],"sources":["../../src/agents/workspace.ts"],"sourcesContent":["import fs, { existsSync } from 'node:fs';\nimport os from 'node:os';\nimport path, { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { Mastra } from '@mastra/core/mastra';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { Workspace, LocalFilesystem, LocalSandbox, createWorkspaceTools } from '@mastra/core/workspace';\nimport type { LSPConfig, SkillSource } from '@mastra/core/workspace';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { loadSettings, resolveLspSetting } from '../onboarding/settings.js';\nimport type { MastraCodeState } from '../schema.js';\nimport { isPathWithinRoot } from '../utils/path-security.js';\nimport { getPlansDir } from '../utils/plans.js';\n\nimport { GOAL_JUDGE_READONLY_TOOLS, MASTRACODE_WORKSPACE_TOOLS } from './tool-availability.js';\n\n// =============================================================================\n// Sandbox Environment\n// =============================================================================\n\nfunction buildSandboxEnv(): NodeJS.ProcessEnv {\n return {\n ...process.env,\n // Explicit overrides for non-interactive subprocess execution\n FORCE_COLOR: '1',\n CLICOLOR_FORCE: '1',\n TERM: process.env.TERM || 'xterm-256color',\n CI: 'true',\n NONINTERACTIVE: '1',\n DEBIAN_FRONTEND: 'noninteractive',\n };\n}\n\n// =============================================================================\n// Create Workspace with Skills\n// =============================================================================\n\n// We support multiple skill locations for compatibility:\n// 1. Project-local: <configDir>/skills (project-specific mastracode skills)\n// 2. Project-local: .claude/skills (Claude Code compatible skills)\n// 3. Project-local: .agents/skills (Agent Skills spec compatible)\n// 4. Global: ~/<configDir>/skills (user-wide mastracode skills)\n// 5. Global: ~/.claude/skills (user-wide Claude Code skills)\n// 6. Global: ~/.agents/skills (user-wide Agent Skills spec compatible)\n\n// Mastra's LocalSkillSource.readdir uses Node's Dirent.isDirectory() which\n// returns false for symlinks. Tools like `npx skills add` install skills as\n// symlinks, so we need to resolve them. For each symlinked skill directory,\n// we add the real (resolved) parent path as an additional skill scan path.\nfunction collectSkillPaths(skillsDirs: string[], allowedRoot?: string): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n let realAllowedRoot: string | undefined;\n\n if (allowedRoot) {\n try {\n realAllowedRoot = fs.realpathSync(allowedRoot);\n } catch {\n return [];\n }\n }\n\n for (const skillsDir of skillsDirs) {\n const skillsDirExists = fs.existsSync(skillsDir);\n if (skillsDirExists && realAllowedRoot) {\n try {\n const realSkillsDir = fs.realpathSync(skillsDir);\n if (!isPathWithinRoot(realSkillsDir, realAllowedRoot)) continue;\n } catch {\n continue;\n }\n }\n\n const resolved = path.resolve(skillsDir);\n if (!seen.has(resolved)) {\n seen.add(resolved);\n paths.push(skillsDir);\n }\n\n if (!skillsDirExists) continue;\n\n try {\n const entries = fs.readdirSync(skillsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isSymbolicLink()) {\n try {\n const linkPath = path.join(skillsDir, entry.name);\n const realPath = fs.realpathSync(linkPath);\n if (realAllowedRoot && !isPathWithinRoot(realPath, realAllowedRoot)) continue;\n const stat = fs.statSync(realPath);\n if (stat.isDirectory()) {\n const realParent = path.dirname(realPath);\n if (realAllowedRoot && !isPathWithinRoot(realParent, realAllowedRoot)) continue;\n if (!seen.has(realParent)) {\n seen.add(realParent);\n paths.push(realParent);\n }\n }\n } catch {\n continue;\n }\n }\n }\n } catch {\n // Ignore errors during symlink resolution\n }\n }\n\n return paths;\n}\n\n// Build skill paths dynamically based on configDir and projectPath\nexport function buildSkillPaths(\n projectPath: string,\n configDir: string,\n homeDir = os.homedir(),\n pluginSkillPaths: string[] = [],\n): string[] {\n const mastraCodeLocalSkillsPath = path.join(projectPath, configDir, 'skills');\n const claudeLocalSkillsPath = path.join(projectPath, '.claude', 'skills');\n const agentSkillsLocalPath = path.join(projectPath, '.agents', 'skills');\n const mastraCodeGlobalSkillsPath = path.join(homeDir, configDir, 'skills');\n const claudeGlobalSkillsPath = path.join(homeDir, '.claude', 'skills');\n const agentSkillsGlobalPath = path.join(homeDir, '.agents', 'skills');\n\n const paths = [\n ...collectSkillPaths([mastraCodeLocalSkillsPath, claudeLocalSkillsPath, agentSkillsLocalPath], projectPath),\n ...collectSkillPaths([mastraCodeGlobalSkillsPath, claudeGlobalSkillsPath, agentSkillsGlobalPath]),\n ...pluginSkillPaths.flatMap(pluginSkillPath => collectSkillPaths([pluginSkillPath], pluginSkillPath)),\n ];\n\n const seenPaths = new Set<string>();\n return paths.filter(skillPath => {\n let resolved: string;\n try {\n resolved = fs.realpathSync(skillPath);\n } catch {\n resolved = path.resolve(skillPath);\n }\n if (seenPaths.has(resolved)) return false;\n seenPaths.add(resolved);\n return true;\n });\n}\n\nexport interface WorkspaceSkillExtension {\n /** Distinguishes extended workspaces from the default resolver cache. */\n id: string;\n /** Additional read-only skill roots prepended to normal project/global skill roots. */\n paths: string[];\n /** Compose the additional roots with the workspace's normal skill source. */\n createSource: (fallback: SkillSource, fallbackSkillRoots: string[]) => SkillSource;\n}\n\n/**\n * Paths the agent is always allowed to access (in addition to the project root\n * and any per-thread sandboxAllowedPaths). The OS temp directory is included\n * so the agent can use it as a scratchpad without requesting access every time.\n */\nconst DEFAULT_ALLOWED_PATHS: string[] = [os.tmpdir(), '/tmp', getPlansDir()].reduce<string[]>((acc, p) => {\n const resolved = path.resolve(p);\n if (!acc.includes(resolved)) acc.push(resolved);\n return acc;\n}, []);\n\nconst WORKSPACE_ID_PREFIX = 'mastra-code-workspace';\n\n/**\n * Detect the project's package runner from lock files.\n * Used as a fallback packageRunner for LSP when no binary is found locally or on PATH.\n */\nfunction detectPackageRunner(projectPath: string): string | undefined {\n if (existsSync(join(projectPath, 'pnpm-lock.yaml'))) return 'pnpm dlx';\n if (existsSync(join(projectPath, 'bun.lockb')) || existsSync(join(projectPath, 'bun.lock'))) return 'bunx';\n if (existsSync(join(projectPath, 'yarn.lock'))) return 'yarn dlx';\n if (existsSync(join(projectPath, 'package-lock.json'))) return 'npx --yes';\n return 'npx --yes';\n}\n\nexport async function getDynamicWorkspace({\n requestContext,\n mastra,\n skillExtension,\n}: {\n requestContext: RequestContext;\n mastra?: Mastra;\n skillExtension?: WorkspaceSkillExtension;\n}) {\n const ctx = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n const state = ctx?.getState();\n\n const rawProjectPath = state?.projectPath;\n\n if (!rawProjectPath) {\n throw new Error('Project path is required');\n }\n\n const projectPath = path.resolve(rawProjectPath);\n const configDir = state?.configDir ?? DEFAULT_CONFIG_DIR;\n const projectSkillPaths = buildSkillPaths(projectPath, configDir, state?.homeDir, state?.pluginSkillPaths ?? []);\n const skillPaths = [...(skillExtension?.paths ?? []), ...projectSkillPaths];\n const extensionId = skillExtension ? `-${skillExtension.id}` : '';\n const workspaceId = `${WORKSPACE_ID_PREFIX}-${projectPath}${extensionId}`;\n const sandboxPaths = state?.sandboxAllowedPaths ?? [];\n const allowedPaths = [\n ...projectSkillPaths,\n ...DEFAULT_ALLOWED_PATHS,\n ...sandboxPaths.map((p: string) => path.resolve(p)),\n ];\n\n // All modes share the same workspace tool configuration. Per-mode tool\n // visibility is enforced at LLM-call time via `availableTools` /\n // `activeTools` on the AgentController, not by mutating workspace capabilities.\n const workspaceTools = MASTRACODE_WORKSPACE_TOOLS;\n\n // Reuse existing workspace if already registered (preserves ProcessManager state)\n let existing: Workspace<LocalFilesystem, LocalSandbox> | undefined;\n try {\n existing = mastra?.getWorkspaceById(workspaceId) as Workspace<LocalFilesystem, LocalSandbox>;\n } catch {\n // Not registered yet\n }\n\n if (existing) {\n existing.filesystem.setAllowedPaths(allowedPaths);\n existing.setToolsConfig(workspaceTools);\n return existing;\n }\n\n // LSP is opt-in. When disabled we pass `false` so core skips the dependency\n // check, the LSP manager, and the `lsp_inspect` tool entirely.\n const userLsp = resolveLspSetting(loadSettings().lsp);\n let lspConfig: LSPConfig | false = false;\n if (userLsp !== false) {\n const mcModulePath = join(dirname(fileURLToPath(import.meta.url)), '..');\n lspConfig = {\n maxOpenClients: 4,\n ...userLsp,\n packageRunner: userLsp.packageRunner || detectPackageRunner(projectPath), // Detected runner is the fallback — user's packageRunner always wins\n searchPaths: [mcModulePath, ...(userLsp.searchPaths ?? [])],\n };\n }\n\n // First call for this project — create the workspace\n const filesystem = new LocalFilesystem({\n basePath: projectPath,\n allowedPaths,\n });\n return new Workspace({\n id: workspaceId,\n name: 'Mastra Code Workspace',\n filesystem,\n sandbox: new LocalSandbox({\n workingDirectory: projectPath,\n env: buildSandboxEnv(),\n }),\n tools: workspaceTools,\n skills: skillPaths,\n ...(skillExtension ? { skillSource: skillExtension.createSource(filesystem, projectSkillPaths) } : {}),\n lsp: lspConfig,\n });\n}\n\n/**\n * Resolver for the agent's `goal.tools` config. Builds the request's workspace\n * (same per-request resolution as the agent's own tools) and returns only the\n * read-only verification subset, remapped to mastracode's tool names (`view`,\n * `search_content`, etc.). Returns `undefined` when no workspace can be resolved\n * (e.g. no project path), keeping the default judge text-only rather than\n * throwing inside the goal step.\n */\nexport async function getGoalJudgeTools({\n requestContext,\n mastra,\n}: {\n requestContext: RequestContext;\n mastra?: Mastra;\n}): Promise<ToolsInput | undefined> {\n let workspace: Workspace;\n try {\n workspace = await getDynamicWorkspace({ requestContext, mastra });\n } catch {\n return undefined;\n }\n\n const allTools = await createWorkspaceTools(workspace, { requestContext, workspace });\n const readonly: ToolsInput = {};\n for (const name of GOAL_JUDGE_READONLY_TOOLS) {\n if (allTools[name]) readonly[name] = allTools[name];\n }\n return Object.keys(readonly).length > 0 ? readonly : undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"workspace.js","names":[],"sources":["../../src/agents/workspace.ts"],"sourcesContent":["import fs, { existsSync } from 'node:fs';\nimport os from 'node:os';\nimport path, { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { Mastra } from '@mastra/core/mastra';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { Workspace, LocalFilesystem, LocalSandbox, createWorkspaceTools } from '@mastra/core/workspace';\nimport type { LSPConfig, SkillSource } from '@mastra/core/workspace';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { loadSettings, resolveLspSetting } from '../onboarding/settings.js';\nimport type { MastraCodeState } from '../schema.js';\nimport { isPathWithinRoot } from '../utils/path-security.js';\nimport { getPlansDir } from '../utils/plans.js';\n\nimport { createMastraCodeWorkspaceTools, GOAL_JUDGE_READONLY_TOOLS } from './tool-availability.js';\n\n// =============================================================================\n// Sandbox Environment\n// =============================================================================\n\nfunction buildSandboxEnv(): NodeJS.ProcessEnv {\n return {\n ...process.env,\n // Explicit overrides for non-interactive subprocess execution\n FORCE_COLOR: '1',\n CLICOLOR_FORCE: '1',\n TERM: process.env.TERM || 'xterm-256color',\n CI: 'true',\n NONINTERACTIVE: '1',\n DEBIAN_FRONTEND: 'noninteractive',\n };\n}\n\n// =============================================================================\n// Create Workspace with Skills\n// =============================================================================\n\n// We support multiple skill locations for compatibility:\n// 1. Project-local: <configDir>/skills (project-specific mastracode skills)\n// 2. Project-local: .claude/skills (Claude Code compatible skills)\n// 3. Project-local: .agents/skills (Agent Skills spec compatible)\n// 4. Global: ~/<configDir>/skills (user-wide mastracode skills)\n// 5. Global: ~/.claude/skills (user-wide Claude Code skills)\n// 6. Global: ~/.agents/skills (user-wide Agent Skills spec compatible)\n\n// Mastra's LocalSkillSource.readdir uses Node's Dirent.isDirectory() which\n// returns false for symlinks. Tools like `npx skills add` install skills as\n// symlinks, so we need to resolve them. For each symlinked skill directory,\n// we add the real (resolved) parent path as an additional skill scan path.\nfunction collectSkillPaths(skillsDirs: string[], allowedRoot?: string): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n let realAllowedRoot: string | undefined;\n\n if (allowedRoot) {\n try {\n realAllowedRoot = fs.realpathSync(allowedRoot);\n } catch {\n return [];\n }\n }\n\n for (const skillsDir of skillsDirs) {\n const skillsDirExists = fs.existsSync(skillsDir);\n if (skillsDirExists && realAllowedRoot) {\n try {\n const realSkillsDir = fs.realpathSync(skillsDir);\n if (!isPathWithinRoot(realSkillsDir, realAllowedRoot)) continue;\n } catch {\n continue;\n }\n }\n\n const resolved = path.resolve(skillsDir);\n if (!seen.has(resolved)) {\n seen.add(resolved);\n paths.push(skillsDir);\n }\n\n if (!skillsDirExists) continue;\n\n try {\n const entries = fs.readdirSync(skillsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isSymbolicLink()) {\n try {\n const linkPath = path.join(skillsDir, entry.name);\n const realPath = fs.realpathSync(linkPath);\n if (realAllowedRoot && !isPathWithinRoot(realPath, realAllowedRoot)) continue;\n const stat = fs.statSync(realPath);\n if (stat.isDirectory()) {\n const realParent = path.dirname(realPath);\n if (realAllowedRoot && !isPathWithinRoot(realParent, realAllowedRoot)) continue;\n if (!seen.has(realParent)) {\n seen.add(realParent);\n paths.push(realParent);\n }\n }\n } catch {\n continue;\n }\n }\n }\n } catch {\n // Ignore errors during symlink resolution\n }\n }\n\n return paths;\n}\n\n// Build skill paths dynamically based on configDir and projectPath\nexport function buildSkillPaths(\n projectPath: string,\n configDir: string,\n homeDir = os.homedir(),\n pluginSkillPaths: string[] = [],\n): string[] {\n const mastraCodeLocalSkillsPath = path.join(projectPath, configDir, 'skills');\n const claudeLocalSkillsPath = path.join(projectPath, '.claude', 'skills');\n const agentSkillsLocalPath = path.join(projectPath, '.agents', 'skills');\n const mastraCodeGlobalSkillsPath = path.join(homeDir, configDir, 'skills');\n const claudeGlobalSkillsPath = path.join(homeDir, '.claude', 'skills');\n const agentSkillsGlobalPath = path.join(homeDir, '.agents', 'skills');\n\n const paths = [\n ...collectSkillPaths([mastraCodeLocalSkillsPath, claudeLocalSkillsPath, agentSkillsLocalPath], projectPath),\n ...collectSkillPaths([mastraCodeGlobalSkillsPath, claudeGlobalSkillsPath, agentSkillsGlobalPath]),\n ...pluginSkillPaths.flatMap(pluginSkillPath => collectSkillPaths([pluginSkillPath], pluginSkillPath)),\n ];\n\n const seenPaths = new Set<string>();\n return paths.filter(skillPath => {\n let resolved: string;\n try {\n resolved = fs.realpathSync(skillPath);\n } catch {\n resolved = path.resolve(skillPath);\n }\n if (seenPaths.has(resolved)) return false;\n seenPaths.add(resolved);\n return true;\n });\n}\n\nexport interface WorkspaceSkillExtension {\n /** Distinguishes extended workspaces from the default resolver cache. */\n id: string;\n /** Additional read-only skill roots prepended to normal project/global skill roots. */\n paths: string[];\n /** Compose the additional roots with the workspace's normal skill source. */\n createSource: (fallback: SkillSource, fallbackSkillRoots: string[]) => SkillSource;\n}\n\n/**\n * Paths the agent is always allowed to access (in addition to the project root\n * and any per-thread sandboxAllowedPaths). The OS temp directory is included\n * so the agent can use it as a scratchpad without requesting access every time.\n */\nconst DEFAULT_ALLOWED_PATHS: string[] = [os.tmpdir(), '/tmp', getPlansDir()].reduce<string[]>((acc, p) => {\n const resolved = path.resolve(p);\n if (!acc.includes(resolved)) acc.push(resolved);\n return acc;\n}, []);\n\nconst WORKSPACE_ID_PREFIX = 'mastra-code-workspace';\n\n/**\n * Detect the project's package runner from lock files.\n * Used as a fallback packageRunner for LSP when no binary is found locally or on PATH.\n */\nfunction detectPackageRunner(projectPath: string): string | undefined {\n if (existsSync(join(projectPath, 'pnpm-lock.yaml'))) return 'pnpm dlx';\n if (existsSync(join(projectPath, 'bun.lockb')) || existsSync(join(projectPath, 'bun.lock'))) return 'bunx';\n if (existsSync(join(projectPath, 'yarn.lock'))) return 'yarn dlx';\n if (existsSync(join(projectPath, 'package-lock.json'))) return 'npx --yes';\n return 'npx --yes';\n}\n\nexport async function getDynamicWorkspace({\n requestContext,\n mastra,\n skillExtension,\n backgroundToolsEnabled = false,\n}: {\n requestContext: RequestContext;\n mastra?: Mastra;\n skillExtension?: WorkspaceSkillExtension;\n backgroundToolsEnabled?: boolean;\n}) {\n const ctx = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n const state = ctx?.getState();\n\n const rawProjectPath = state?.projectPath;\n\n if (!rawProjectPath) {\n throw new Error('Project path is required');\n }\n\n const projectPath = path.resolve(rawProjectPath);\n const configDir = state?.configDir ?? DEFAULT_CONFIG_DIR;\n const projectSkillPaths = buildSkillPaths(projectPath, configDir, state?.homeDir, state?.pluginSkillPaths ?? []);\n const skillPaths = [...(skillExtension?.paths ?? []), ...projectSkillPaths];\n const extensionId = skillExtension ? `-${skillExtension.id}` : '';\n const workspaceId = `${WORKSPACE_ID_PREFIX}-${projectPath}${extensionId}`;\n const sandboxPaths = state?.sandboxAllowedPaths ?? [];\n const allowedPaths = [\n ...projectSkillPaths,\n ...DEFAULT_ALLOWED_PATHS,\n ...sandboxPaths.map((p: string) => path.resolve(p)),\n ];\n\n // All modes share the same workspace tool configuration. Per-mode tool\n // visibility is enforced at LLM-call time via `availableTools` /\n // `activeTools` on the AgentController, not by mutating workspace capabilities.\n const workspaceTools = createMastraCodeWorkspaceTools(backgroundToolsEnabled);\n\n // Reuse existing workspace if already registered (preserves ProcessManager state)\n let existing: Workspace<LocalFilesystem, LocalSandbox> | undefined;\n try {\n existing = mastra?.getWorkspaceById(workspaceId) as Workspace<LocalFilesystem, LocalSandbox>;\n } catch {\n // Not registered yet\n }\n\n if (existing) {\n existing.filesystem.setAllowedPaths(allowedPaths);\n existing.setToolsConfig(workspaceTools);\n return existing;\n }\n\n // LSP is opt-in. When disabled we pass `false` so core skips the dependency\n // check, the LSP manager, and the `lsp_inspect` tool entirely.\n const userLsp = resolveLspSetting(loadSettings().lsp);\n let lspConfig: LSPConfig | false = false;\n if (userLsp !== false) {\n const mcModulePath = join(dirname(fileURLToPath(import.meta.url)), '..');\n lspConfig = {\n maxOpenClients: 4,\n ...userLsp,\n packageRunner: userLsp.packageRunner || detectPackageRunner(projectPath), // Detected runner is the fallback — user's packageRunner always wins\n searchPaths: [mcModulePath, ...(userLsp.searchPaths ?? [])],\n };\n }\n\n // First call for this project — create the workspace\n const filesystem = new LocalFilesystem({\n basePath: projectPath,\n allowedPaths,\n });\n return new Workspace({\n id: workspaceId,\n name: 'Mastra Code Workspace',\n filesystem,\n sandbox: new LocalSandbox({\n workingDirectory: projectPath,\n env: buildSandboxEnv(),\n }),\n tools: workspaceTools,\n skills: skillPaths,\n ...(skillExtension ? { skillSource: skillExtension.createSource(filesystem, projectSkillPaths) } : {}),\n lsp: lspConfig,\n });\n}\n\n/**\n * Resolver for the agent's `goal.tools` config. Builds the request's workspace\n * (same per-request resolution as the agent's own tools) and returns only the\n * read-only verification subset, remapped to mastracode's tool names (`view`,\n * `search_content`, etc.). Returns `undefined` when no workspace can be resolved\n * (e.g. no project path), keeping the default judge text-only rather than\n * throwing inside the goal step.\n */\nexport async function getGoalJudgeTools({\n requestContext,\n mastra,\n}: {\n requestContext: RequestContext;\n mastra?: Mastra;\n}): Promise<ToolsInput | undefined> {\n let workspace: Workspace;\n try {\n workspace = await getDynamicWorkspace({ requestContext, mastra });\n } catch {\n return undefined;\n }\n\n const allTools = await createWorkspaceTools(workspace, { requestContext, workspace });\n const readonly: ToolsInput = {};\n for (const name of GOAL_JUDGE_READONLY_TOOLS) {\n if (allTools[name]) readonly[name] = allTools[name];\n }\n return Object.keys(readonly).length > 0 ? readonly : undefined;\n}\n"],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ import type { ProcessAPIErrorArgs, ProcessInputArgs, ProcessInputResult, Processor } from '@mastra/core/processors';
2
+ import type { CredentialStore } from './types.js';
3
+ export declare const ACCOUNT_SWITCH_PART_TYPE = "data-mastracode-account-switch";
4
+ /** Labels and instance ids only — never token material (do-not list). */
5
+ export interface AccountSwitchPartData {
6
+ provider: string;
7
+ from: {
8
+ id: string;
9
+ label: string;
10
+ } | null;
11
+ to: {
12
+ id: string;
13
+ label: string;
14
+ } | null;
15
+ reason: 'rate-limit' | 'quota-exhausted' | 'auth-failed' | 'pool-exhausted' | 'persistent-outage' | 'preferred-routing' | 'starting-on-account';
16
+ at: string;
17
+ /**
18
+ * Set on a `to: null` part when a route pinned to a single account reported
19
+ * that account unusable. The provider's other subscriptions were never
20
+ * consulted (A12), so "all accounts unavailable" would misreport what
21
+ * happened.
22
+ */
23
+ exclusive?: boolean;
24
+ }
25
+ /** The store surface rotation needs; `AuthStorage` satisfies it structurally. */
26
+ export type RotationCredentialStore = CredentialStore & {
27
+ /**
28
+ * Force one refresh of the active account's tokens regardless of expiry
29
+ * (401/403 path — a rejected-but-unexpired token usually means clock skew
30
+ * or a refresh race). `AuthStorage` provides it; deployed per-tenant stores
31
+ * don't, and the auth path degrades to plain rotation (which itself no-ops
32
+ * without registry methods).
33
+ */
34
+ forceRefreshActiveAccount?(providerId: string, accountInstanceId?: string): Promise<string | undefined>;
35
+ };
36
+ /** Persisted data-part type for a fallback-pack hop. */
37
+ export declare const PACK_FALLBACK_PART_TYPE: "data-mastracode-pack-fallback";
38
+ /**
39
+ * Payload of a pack-fallback part: the pack the cascade is leaving, the pack
40
+ * core's fallback array advances to, and why. Labels and pack ids only —
41
+ * never credential material.
42
+ */
43
+ export interface PackFallbackPartData {
44
+ from: {
45
+ packId: string;
46
+ label: string;
47
+ };
48
+ to: {
49
+ packId: string;
50
+ label: string;
51
+ };
52
+ reason: 'pool-exhausted' | 'persistent-outage';
53
+ at: string;
54
+ }
55
+ /**
56
+ * Session-state key the processor sets when a pack hop happens. The TUI
57
+ * listens for it on the typed `state_changed` controller event (data parts
58
+ * never ride controller message events) and applies thread stickiness.
59
+ */
60
+ export declare const PACK_FALLBACK_STATE_KEY: "mastracodePendingPackFallback";
61
+ /** Payload written to session state under PACK_FALLBACK_STATE_KEY. */
62
+ export interface PendingPackFallback {
63
+ fromPackId: string;
64
+ toPackId: string;
65
+ /** Landed pack's model for the mode the cascade is serving. */
66
+ toModelId: string;
67
+ /** Originating thread. Absent only on pending hops written by older clients. */
68
+ threadId?: string;
69
+ reason: 'pool-exhausted' | 'persistent-outage';
70
+ at: string;
71
+ }
72
+ export type RotationClassification = {
73
+ kind: 'rotate';
74
+ reason: 'rate-limit' | 'quota-exhausted' | 'auth-failed';
75
+ } | {
76
+ kind: 'hop';
77
+ } | {
78
+ kind: 'never';
79
+ };
80
+ /**
81
+ * The locked Q7 taxonomy. 429/402/usage-limit rotate immediately (429 is not
82
+ * covered by any transient matcher, so it arrives here on first occurrence);
83
+ * 401/403 and `ProviderAuthRequiredError` rotate after one forced refresh;
84
+ * 5xx/network hop only when the transient retry budget is already spent (they
85
+ * reach this processor because `StreamErrorRetryProcessor` declined); 400 and
86
+ * everything unknown never touch the registry.
87
+ */
88
+ export declare function classifyRotationError(error: unknown): RotationClassification;
89
+ /** Provider id off a router model id: `mastracode/<provider>/<model>` or `<provider>/<model>`. */
90
+ export declare function providerFromModelId(modelId: string): string | undefined;
91
+ /**
92
+ * Identify the provider an error came from: the request URL's hostname
93
+ * (`APICallError.url`, cause chain included), falling back to the router
94
+ * model id. Unknown → undefined (caller treats as never-rotate).
95
+ */
96
+ export declare function providerFromError(error: unknown): string | undefined;
97
+ /** Friendly names for the part/notice copy (display only — never auth data). */
98
+ export declare const PROVIDER_DISPLAY_NAMES: Record<string, string>;
99
+ /** Validates untrusted `reason` values (e.g. persisted message parts). */
100
+ export declare function isAccountSwitchReason(value: unknown): value is AccountSwitchPartData['reason'];
101
+ /**
102
+ * One-line transcript copy for a switch part. Shared by the live `info`
103
+ * controller event (the TUI shows controller `info` events as transcript
104
+ * lines, and no message event carries data parts mid-run) and by the TUI's
105
+ * history rendering of the persisted part — one formatter, identical text.
106
+ */
107
+ export declare function accountSwitchNoticeText(data: AccountSwitchPartData): string;
108
+ /** Transcript line for a pack-fallback hop; shared by the live info event and the TUI's history render. */
109
+ export declare function packFallbackNoticeText(data: PackFallbackPartData): string;
110
+ /**
111
+ * Whether a persisted pack-fallback reason is one this build understands.
112
+ * `REASON_TEXT` also covers the account-switch reasons, so the notice text
113
+ * alone would happily render a foreign value such as `rate-limit` as a
114
+ * pack-fallback reason; history parsed from another build's part must be
115
+ * rejected instead.
116
+ */
117
+ export declare function isPackFallbackReason(value: unknown): value is PackFallbackPartData['reason'];
118
+ /**
119
+ * Controller-shaped accessors for a thread's routing metadata. Core supplies this
120
+ * via `requestContext.get('controller')`; the TUI builds the same shape from its
121
+ * session so both writers share one serialization key and one read source.
122
+ */
123
+ export type RoutingControllerContext = {
124
+ session?: {
125
+ modelId?: unknown;
126
+ modeId?: unknown;
127
+ };
128
+ threadId?: unknown;
129
+ getState?: () => Record<string, unknown>;
130
+ setState?: (updates: Record<string, unknown>) => Promise<void>;
131
+ getThreadSetting?: (key: string) => Promise<unknown>;
132
+ setThreadSetting?: (setting: {
133
+ key: string;
134
+ value: unknown;
135
+ }) => Promise<void>;
136
+ isThreadActive?: () => boolean;
137
+ };
138
+ export declare class AccountRotationProcessor implements Processor {
139
+ private readonly options;
140
+ readonly id: "mastracode-account-rotation";
141
+ constructor(options: {
142
+ credentialStore: RotationCredentialStore;
143
+ maxProcessorRetries: number;
144
+ settingsPath?: string;
145
+ });
146
+ processAPIError(args: ProcessAPIErrorArgs): Promise<{
147
+ retry: boolean;
148
+ }>;
149
+ /**
150
+ * The request's pack cascade, computed once from the session's pack and
151
+ * cached in processor state. Truncated at the first pack that lacks the
152
+ * session mode's model — mirroring getDynamicModel's truncation — so the
153
+ * cascade never promises a hop core's fallback array cannot make. The
154
+ * position advances per hop, so a second hop in the same turn reports B→C
155
+ * even though the session modelId still points at pack A (stickiness lands
156
+ * TUI-side only after the part renders). Returns null when the session has
157
+ * no active pack or the pack has no fallback chain.
158
+ */
159
+ private getPackCascade;
160
+ /**
161
+ * Q14 gate: 400/unknown/unattributable errors never hop packs. Core's
162
+ * fallback array advances on ANY thrown error except TripWire
163
+ * (llm-execution-step.ts), so when the session's pack has a chain and the
164
+ * current entry is non-last, a bare `retry: false` would silently hop on an
165
+ * error class the user excluded from hop triggers. TripWire is the only
166
+ * no-advance escape: the runner rethrows it and the fallback loop declines
167
+ * to advance. No chain (or already on the last entry) → return and let the
168
+ * plain `retry: false` surface the error exactly as before.
169
+ */
170
+ private gateChainHop;
171
+ /**
172
+ * Emit the pack-fallback part when a configured chain has a next pack and
173
+ * queue the thread stickiness trigger. Core's fallback array does the hop
174
+ * itself on `retry: false`; this only announces it. The cascade is
175
+ * truncated exactly like getDynamicModel's chain (missing mode model or
176
+ * unresolvable model), so an announced hop is always one core can make;
177
+ * the toModelId guard stays as defense against a stale cache.
178
+ */
179
+ private emitPackFallbackPart;
180
+ /**
181
+ * Pool done for this request: every instance recorded in the tried-set and
182
+ * a `to: null` part emitted. Returns `retry: false` so core's fallback
183
+ * array can hop to the next pack (announced by `emitPackFallbackPart`).
184
+ * Silent on the account part when the provider has no registry at all —
185
+ * there are no accounts to declare unavailable, but the hop still applies.
186
+ */
187
+ private declarePoolUnavailable;
188
+ }
189
+ /**
190
+ * Emits the "starting on a non-default account" notice (Q19) once per
191
+ * request when the active registry account is not the first entry.
192
+ *
193
+ * TYPE CONSTRAINT: this class must NEVER implement `processAPIError`. It
194
+ * lives in `inputProcessors`; the runner walks input processors first when
195
+ * running `processAPIError`, so adding the method here would classify and
196
+ * rotate errors BEFORE `StreamErrorRetryProcessor`'s transient retries run.
197
+ */
198
+ export declare class AccountStartNoticeProcessor implements Processor {
199
+ private readonly options;
200
+ readonly id: "mastracode-account-start-notice";
201
+ constructor(options: {
202
+ credentialStore: CredentialStore;
203
+ settingsPath?: string;
204
+ });
205
+ processInput(args: ProcessInputArgs): Promise<ProcessInputResult>;
206
+ }
207
+ //# sourceMappingURL=account-rotation-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-rotation-processor.d.ts","sourceRoot":"","sources":["../../src/auth/account-rotation-processor.ts"],"names":[],"mappings":"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"}