@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
package/dist/index.js CHANGED
@@ -1,765 +1,685 @@
1
- import { createHash } from "node:crypto";
2
- import { hostname } from "node:os";
3
- import path from "node:path";
4
- import { AgentController } from "@mastra/core/agent-controller";
5
- import { createCodingAgent } from "@mastra/core/coding-agent";
6
- import { PROVIDER_REGISTRY } from "@mastra/core/llm";
7
- import { Mastra } from "@mastra/core/mastra";
8
- import {
9
- AgentsMDInjector,
10
- isBadRequestError,
11
- PrefillErrorHandler,
12
- ProviderHistoryCompat,
13
- StreamErrorRetryProcessor
14
- } from "@mastra/core/processors";
15
- import { RequestContext } from "@mastra/core/request-context";
16
- import { TaskSignalProvider } from "@mastra/core/signals";
17
- import { InMemoryHarness, MastraCompositeStore } from "@mastra/core/storage";
18
- import { DEFAULT_GOAL_JUDGE_PROMPT } from "@mastra/core/tools";
19
- import { DuckDBStore } from "@mastra/duckdb";
20
- import { GithubSignals } from "@mastra/github-signals";
21
- import { LibSQLStore, LibSQLVector } from "@mastra/libsql";
22
- import {
23
- Observability,
24
- MastraStorageExporter,
25
- MastraPlatformExporter,
26
- SensitiveDataFilter
27
- } from "@mastra/observability";
28
- import { PostgresStore } from "@mastra/pg";
1
+ import { validateConfigDirName } from "./constants.js";
2
+ import { detectProject, getObservabilityDatabasePath, getResourceIdOverride, getStorageConfig } from "./utils/project.js";
3
+ import { AuthStorage } from "./auth/storage.js";
4
+ import { setAuthStorage } from "./providers/openai-codex.js";
5
+ import { MASTRA_GATEWAY_PROVIDER, OBSERVABILITY_AUTH_PREFIX, loadSettings, resolveModelDefaults, resolveOmRoleModel, saveSettings } from "./onboarding/settings.js";
29
6
  import { hasCredentialStoreProvider } from "./agents/credential-resolver.js";
7
+ import { getDynamicWorkspace, getGoalJudgeTools } from "./agents/workspace.js";
8
+ import { getStaticallyLoadedInstructionPaths } from "./agents/prompts/agent-instructions.js";
30
9
  import { getDynamicInstructions } from "./agents/instructions.js";
31
- import { getDynamicMemory } from "./agents/memory.js";
10
+ import { createAmazonBedrockGateway } from "./providers/amazon-bedrock-gateway.js";
11
+ import { setAuthStorage as setAuthStorage$1 } from "./providers/claude-max.js";
12
+ import { setAuthStorage as setAuthStorage$2 } from "./providers/github-copilot.js";
13
+ import { setAuthStorage as setAuthStorage$3 } from "./providers/xai.js";
32
14
  import { createMastraCodeGateway, getDynamicModel, getGoalJudgeModel, resolveModel } from "./agents/model.js";
15
+ import { getDynamicMemory } from "./agents/memory.js";
33
16
  import { buildMode } from "./agents/modes/build.js";
34
17
  import { fastMode } from "./agents/modes/explore.js";
35
18
  import { planMode } from "./agents/modes/plan.js";
36
- import { getStaticallyLoadedInstructionPaths } from "./agents/prompts/agent-instructions.js";
37
19
  import { attachOMThreadStatePersistence, restoreOMThreadStateForCurrentThread } from "./agents/thread-caveman-state.js";
38
20
  import { createDynamicTools, createToolHooks } from "./agents/tools.js";
39
- import { getDynamicWorkspace, getGoalJudgeTools } from "./agents/workspace.js";
40
- import { AuthStorage } from "./auth/storage.js";
41
- import { DEFAULT_CONFIG_DIR, validateConfigDirName } from "./constants.js";
42
- import { createOutcomeScorer, createEfficiencyScorer } from "./evals/scorers/index.js";
43
- import { HookManager } from "./hooks/index.js";
44
- import { createMcpManager } from "./mcp/index.js";
45
- import { getAvailableModePacks, getAvailableOmPacks } from "./onboarding/packs.js";
46
- import {
47
- loadSettings,
48
- MASTRA_GATEWAY_PROVIDER,
49
- OBSERVABILITY_AUTH_PREFIX,
50
- resolveModelDefaults,
51
- resolveOmRoleModel,
52
- saveSettings
53
- } from "./onboarding/settings.js";
21
+ import { createOutcomeScorer } from "./evals/scorers/outcome.js";
22
+ import { createEfficiencyScorer } from "./evals/scorers/efficiency.js";
23
+ import "./evals/scorers/index.js";
24
+ import { HookManager } from "./hooks/manager.js";
25
+ import "./hooks/index.js";
26
+ import { createMcpManager } from "./mcp/manager.js";
27
+ import "./mcp/index.js";
28
+ import { hasExplicitOMConfiguration } from "./onboarding/om-settings.js";
29
+ import { getAvailableModePacks, getAvailableOmPacks, selectPreferredOMPack } from "./onboarding/packs.js";
54
30
  import { getToolCategory } from "./permissions.js";
55
31
  import { PluginManager } from "./plugins/manager.js";
56
32
  import { PlanRejectionAbortProcessor } from "./processors/plan-rejection-abort.js";
57
- import { createAmazonBedrockGateway } from "./providers/amazon-bedrock-gateway.js";
58
- import { setAuthStorage } from "./providers/claude-max.js";
59
- import { setAuthStorage as setGitHubCopilotAuthStorage } from "./providers/github-copilot.js";
60
- import { setAuthStorage as setOpenAIAuthStorage } from "./providers/openai-codex.js";
61
- import { setAuthStorage as setXAIAuthStorage } from "./providers/xai.js";
62
33
  import { stateSchema } from "./schema.js";
63
34
  import { mastraBrand } from "./theme-palette.js";
64
35
  import { syncGateways } from "./utils/gateway-sync.js";
65
- import {
66
- detectProject,
67
- getObservabilityDatabasePath,
68
- getStorageConfig,
69
- getResourceIdOverride
70
- } from "./utils/project.js";
71
36
  import { createSignalsPubSub } from "./utils/signals-pubsub.js";
37
+ import { DEFAULT_RETENTION, createStorageMaintenance, resolveLocalDbFiles } from "./utils/storage-maintenance.js";
72
38
  import { createStorage, createVectorStore } from "./utils/storage-factory.js";
73
- import { createStorageMaintenance, DEFAULT_RETENTION, resolveLocalDbFiles } from "./utils/storage-maintenance.js";
74
39
  import { acquireThreadLock, releaseThreadLock } from "./utils/thread-lock.js";
40
+ import { autoApprovePolicy, denyPolicy, permissionModeToPolicy } from "./headless/policy.js";
41
+ import { runMC } from "./headless/run-mc.js";
42
+ import { formatHuman, formatJsonl, renderJsonResult, renderTextResult } from "./headless/format.js";
43
+ import { hasHeadlessFlag, runMCCli } from "./headless/cli.js";
44
+ import "./headless/index.js";
45
+ import { TaskSignalProvider } from "@mastra/core/signals";
46
+ import { createHash } from "crypto";
47
+ import { hostname } from "os";
48
+ import path from "path";
49
+ import { AgentController } from "@mastra/core/agent-controller";
50
+ import { createCodingAgent } from "@mastra/core/coding-agent";
51
+ import { PROVIDER_REGISTRY } from "@mastra/core/llm";
52
+ import { Mastra } from "@mastra/core/mastra";
53
+ import { AgentsMDInjector, PrefillErrorHandler, ProviderHistoryCompat, StreamErrorRetryProcessor, isBadRequestError } from "@mastra/core/processors";
54
+ import { RequestContext } from "@mastra/core/request-context";
55
+ import { InMemoryHarness, MastraCompositeStore } from "@mastra/core/storage";
56
+ import { DEFAULT_GOAL_JUDGE_PROMPT } from "@mastra/core/tools";
57
+ import { DuckDBStore } from "@mastra/duckdb";
58
+ import { GithubSignals } from "@mastra/github-signals";
59
+ import { LibSQLStore, LibSQLVector } from "@mastra/libsql";
60
+ import { MastraPlatformExporter, MastraStorageExporter, Observability, SensitiveDataFilter } from "@mastra/observability";
61
+ import { PostgresStore } from "@mastra/pg";
62
+ //#region src/index.ts
75
63
  const CODE_AGENT_ID = "code-agent";
76
64
  const MASTRACODE_TRANSIENT_CONNECTION_MAX_RETRIES = 2;
77
65
  const MASTRACODE_TRANSIENT_CONNECTION_RETRY_INITIAL_DELAY_MS = 1e3;
78
66
  const MASTRACODE_TRANSIENT_CONNECTION_RETRY_MAX_DELAY_MS = 3e4;
79
67
  const TRANSIENT_CONNECTION_ERROR_CODES = /* @__PURE__ */ new Set(["ECONNRESET", "EPIPE"]);
80
68
  const TRANSIENT_CONNECTION_MESSAGE_PATTERN = /econnreset|socket hang up|write epipe|other side closed/i;
69
+ /**
70
+ * Matcher for transient connection failures. Cause-chain traversal is handled
71
+ * by `StreamErrorRetryProcessor.isRetryableStreamError`, which calls each
72
+ * matcher at every level of the cause chain.
73
+ */
81
74
  function isTransientConnectionError(error) {
82
- if (!error) return false;
83
- const code = typeof error === "object" && "code" in error ? error.code : void 0;
84
- if (typeof code === "string" && TRANSIENT_CONNECTION_ERROR_CODES.has(code.toUpperCase())) return true;
85
- const message = error instanceof Error ? error.message : void 0;
86
- if (typeof message === "string" && TRANSIENT_CONNECTION_MESSAGE_PATTERN.test(message)) return true;
87
- return false;
75
+ if (!error) return false;
76
+ const code = typeof error === "object" && "code" in error ? error.code : void 0;
77
+ if (typeof code === "string" && TRANSIENT_CONNECTION_ERROR_CODES.has(code.toUpperCase())) return true;
78
+ const message = error instanceof Error ? error.message : void 0;
79
+ if (typeof message === "string" && TRANSIENT_CONNECTION_MESSAGE_PATTERN.test(message)) return true;
80
+ return false;
88
81
  }
82
+ /** Short deterministic hash (sha256, first 12 hex chars) matching project.ts shortHash style. */
89
83
  function shortHash(input) {
90
- return createHash("sha256").update(input).digest("hex").slice(0, 12);
84
+ return createHash("sha256").update(input).digest("hex").slice(0, 12);
91
85
  }
92
86
  function applyEffectiveDefaultsToModes(modes, effectiveDefaults) {
93
- return modes.map((mode) => {
94
- const savedModel = effectiveDefaults[mode.id];
95
- if (!savedModel) {
96
- return mode;
97
- }
98
- return {
99
- ...mode,
100
- defaultModelId: savedModel
101
- };
102
- });
87
+ return modes.map((mode) => {
88
+ const savedModel = effectiveDefaults[mode.id];
89
+ if (!savedModel) return mode;
90
+ return {
91
+ ...mode,
92
+ defaultModelId: savedModel
93
+ };
94
+ });
103
95
  }
104
96
  function addPluginToolsToModeAllowlists(modes, pluginToolNames) {
105
- if (pluginToolNames.length === 0) return modes;
106
- return modes.map((mode) => {
107
- if (!mode.availableTools) return mode;
108
- return {
109
- ...mode,
110
- availableTools: Array.from(/* @__PURE__ */ new Set([...mode.availableTools, ...pluginToolNames]))
111
- };
112
- });
97
+ if (pluginToolNames.length === 0) return modes;
98
+ return modes.map((mode) => {
99
+ if (!mode.availableTools) return mode;
100
+ return {
101
+ ...mode,
102
+ availableTools: Array.from(/* @__PURE__ */ new Set([...mode.availableTools, ...pluginToolNames]))
103
+ };
104
+ });
113
105
  }
114
106
  function createAuthStorage() {
115
- const authStorage = new AuthStorage();
116
- setAuthStorage(authStorage);
117
- setOpenAIAuthStorage(authStorage);
118
- setGitHubCopilotAuthStorage(authStorage);
119
- setXAIAuthStorage(authStorage);
120
- return authStorage;
107
+ const authStorage = new AuthStorage();
108
+ setAuthStorage$1(authStorage);
109
+ setAuthStorage(authStorage);
110
+ setAuthStorage$2(authStorage);
111
+ setAuthStorage$3(authStorage);
112
+ return authStorage;
121
113
  }
114
+ /**
115
+ * Resolve cloud observability credentials for the MastraPlatformExporter.
116
+ * Priority: per-resource settings > environment variables > disabled.
117
+ */
122
118
  function resolveCloudObservabilityConfig(settings, authStorage, resourceId) {
123
- const resourceConfig = settings.observability.resources[resourceId];
124
- if (resourceConfig) {
125
- const token = authStorage.getStoredApiKey(`${OBSERVABILITY_AUTH_PREFIX}${resourceId}`);
126
- if (token) {
127
- return { accessToken: token, projectId: resourceConfig.projectId };
128
- }
129
- }
130
- return {
131
- accessToken: process.env.MASTRA_CLOUD_ACCESS_TOKEN,
132
- projectId: process.env.MASTRA_PROJECT_ID
133
- };
119
+ const resourceConfig = settings.observability.resources[resourceId];
120
+ if (resourceConfig) {
121
+ const token = authStorage.getStoredApiKey(`${OBSERVABILITY_AUTH_PREFIX}${resourceId}`);
122
+ if (token) return {
123
+ accessToken: token,
124
+ projectId: resourceConfig.projectId
125
+ };
126
+ }
127
+ return {
128
+ accessToken: process.env.MASTRA_CLOUD_ACCESS_TOKEN,
129
+ projectId: process.env.MASTRA_PROJECT_ID
130
+ };
134
131
  }
132
+ /**
133
+ * Base factory: builds every shared MastraCode resource (storage, observability,
134
+ * memory, MCP, providers, gateways, agent, modes) and the {@link AgentController}, but
135
+ * does NOT call `init()` or create a session. The controller is returned inert so
136
+ * the composition layer can decide its Mastra ownership and session model.
137
+ *
138
+ * See {@link bootLocalAgentController} (Case 3) and `mountAgentControllerOnMastra` (Cases 1 & 2).
139
+ */
140
+ /**
141
+ * `instanceof` checks against Mastra classes are unreliable here: published
142
+ * packages pin exact `@mastra/core` versions, so a user's dependency graph can
143
+ * contain multiple copies of core (and peer-keyed copies of `@mastra/libsql` /
144
+ * `@mastra/pg`). A store built against one copy fails `instanceof` against
145
+ * another — the injected instance then silently fell through to the
146
+ * StorageConfig path and crashed on `config.url`. These structural checks work
147
+ * across duplicated copies.
148
+ */
135
149
  function isInjectedStorageInstance(storage) {
136
- if (!storage) return false;
137
- if (storage instanceof MastraCompositeStore) return true;
138
- const candidate = storage;
139
- return typeof candidate.init === "function" && typeof candidate.__registerMastra === "function";
150
+ if (!storage) return false;
151
+ if (storage instanceof MastraCompositeStore) return true;
152
+ const candidate = storage;
153
+ return typeof candidate.init === "function" && typeof candidate.__registerMastra === "function";
140
154
  }
155
+ /** Cross-copy-safe class check: walks the prototype chain by constructor name. */
141
156
  function hasAncestorClassNamed(value, className) {
142
- for (let proto = Object.getPrototypeOf(value); proto; proto = Object.getPrototypeOf(proto)) {
143
- if (proto.constructor?.name === className) return true;
144
- }
145
- return false;
157
+ for (let proto = Object.getPrototypeOf(value); proto; proto = Object.getPrototypeOf(proto)) if (proto.constructor?.name === className) return true;
158
+ return false;
146
159
  }
147
160
  function resolveInjectedStorageBackend(storage, configuredBackend) {
148
- if (configuredBackend) return configuredBackend;
149
- if (storage instanceof LibSQLStore || hasAncestorClassNamed(storage, "LibSQLStore")) return "libsql";
150
- if (storage instanceof PostgresStore || hasAncestorClassNamed(storage, "PostgresStore")) return "pg";
151
- throw new Error("storageBackend is required when injecting a custom storage instance.");
161
+ if (configuredBackend) return configuredBackend;
162
+ if (storage instanceof LibSQLStore || hasAncestorClassNamed(storage, "LibSQLStore")) return "libsql";
163
+ if (storage instanceof PostgresStore || hasAncestorClassNamed(storage, "PostgresStore")) return "pg";
164
+ throw new Error("storageBackend is required when injecting a custom storage instance.");
152
165
  }
153
166
  async function createMastraCodeAgentController(config) {
154
- const cwd = config?.cwd ?? process.cwd();
155
- const homeDir = config?.homeDir ?? config?.initialState?.homeDir;
156
- const configDir = config?.configDir ?? DEFAULT_CONFIG_DIR;
157
- let activeSession;
158
- if (configDir !== DEFAULT_CONFIG_DIR) {
159
- validateConfigDirName(configDir);
160
- }
161
- try {
162
- process.loadEnvFile(path.join(cwd, ".env"));
163
- } catch {
164
- }
165
- const authStorage = createAuthStorage();
166
- const globalSettings = loadSettings(config?.settingsPath);
167
- const storedGatewayKey = authStorage.getStoredApiKey(MASTRA_GATEWAY_PROVIDER);
168
- const storedGatewayUrl = globalSettings.memoryGateway?.baseUrl;
169
- if (storedGatewayKey) {
170
- process.env["MASTRA_GATEWAY_API_KEY"] ??= storedGatewayKey;
171
- }
172
- if (storedGatewayUrl) {
173
- process.env["MASTRA_GATEWAY_URL"] ??= storedGatewayUrl;
174
- }
175
- if (!hasCredentialStoreProvider()) {
176
- try {
177
- const registry = PROVIDER_REGISTRY;
178
- const providerEnvVars = {};
179
- for (const [provider, cfg] of Object.entries(registry)) {
180
- const envVars = cfg?.apiKeyEnvVar;
181
- providerEnvVars[provider] = Array.isArray(envVars) ? envVars[0] : envVars;
182
- }
183
- providerEnvVars[MASTRA_GATEWAY_PROVIDER] ??= "MASTRA_GATEWAY_API_KEY";
184
- authStorage.loadStoredApiKeysIntoEnv(providerEnvVars);
185
- } catch {
186
- authStorage.loadStoredApiKeysIntoEnv({
187
- [MASTRA_GATEWAY_PROVIDER]: "MASTRA_GATEWAY_API_KEY",
188
- anthropic: "ANTHROPIC_API_KEY",
189
- openai: "OPENAI_API_KEY",
190
- google: "GOOGLE_GENERATIVE_AI_API_KEY",
191
- cerebras: "CEREBRAS_API_KEY",
192
- deepseek: "DEEPSEEK_API_KEY"
193
- });
194
- }
195
- }
196
- const mgApiKey = process.env["MASTRA_GATEWAY_API_KEY"] ?? storedGatewayKey;
197
- const mastraGatewayBaseUrl = (process.env["MASTRA_GATEWAY_URL"] ?? storedGatewayUrl ?? "https://gateway-api.mastra.ai").replace(/\/+$/, "").replace(/\/v1$/, "");
198
- const mastraCodeGateway = createMastraCodeGateway({
199
- mastraGatewayBaseUrl,
200
- mastraGatewayApiKey: mgApiKey,
201
- routeThroughMastraGateway: false,
202
- settingsPath: config?.settingsPath
203
- });
204
- const amazonBedrockGateway = createAmazonBedrockGateway();
205
- const project = detectProject(cwd);
206
- const resourceIdOverride = getResourceIdOverride(project.rootPath, configDir);
207
- if (resourceIdOverride) {
208
- project.resourceId = resourceIdOverride;
209
- project.resourceIdOverride = true;
210
- }
211
- const sessionId = `mastracode-session-${shortHash(project.resourceId)}`;
212
- const ownerId = `mastracode-${shortHash(`${hostname()}\0${project.rootPath}`)}`;
213
- const configuredPubSub = config?.pubsub;
214
- const useUnixSocketPubSub = (config?.unixSocketPubSub ?? globalSettings.signals?.unixSocketPubSub ?? false) && process.platform !== "win32";
215
- const signalsPubSub = configuredPubSub ?? (useUnixSocketPubSub ? createSignalsPubSub(project.resourceId) : void 0);
216
- const crossProcessPubSub = config?.crossProcessPubSub ?? (!configuredPubSub && useUnixSocketPubSub);
217
- if (crossProcessPubSub && !signalsPubSub) {
218
- throw new Error("crossProcessPubSub requires a pubsub instance");
219
- }
220
- const injectedStorage = isInjectedStorageInstance(config?.storage) ? config.storage : void 0;
221
- const storageConfig = injectedStorage ? void 0 : config?.storage ?? getStorageConfig(project.rootPath, globalSettings.storage, configDir);
222
- const storageResult = injectedStorage ? { storage: injectedStorage, backend: resolveInjectedStorageBackend(injectedStorage, config?.storageBackend) } : await createStorage(storageConfig);
223
- const storageWarning = storageResult.warning;
224
- let observabilityDomain;
225
- let observabilityWarning;
226
- if (globalSettings.observability.localTracing) {
227
- try {
228
- const observabilityDuckDB = new DuckDBStore({
229
- id: "mastra-code-observability",
230
- path: getObservabilityDatabasePath()
231
- });
232
- await observabilityDuckDB.db.getConnection();
233
- observabilityDomain = observabilityDuckDB.observability;
234
- } catch (err) {
235
- const message = err instanceof Error ? err.message : String(err);
236
- const isLockError = /lock|locked|busy/i.test(message);
237
- if (isLockError) {
238
- observabilityWarning = "Observability unavailable \u2014 another MastraCode instance holds the database lock. Traces, scores, and feedback will not be recorded in this session.";
239
- } else {
240
- observabilityWarning = `Observability unavailable \u2014 DuckDB initialization failed: ${message}`;
241
- }
242
- }
243
- }
244
- const harnessStorage = new InMemoryHarness();
245
- const storage = new MastraCompositeStore({
246
- id: "mastra-code-storage",
247
- default: storageResult.storage,
248
- domains: {
249
- // When local tracing is off, disable the observability domain entirely so
250
- // trace/score/feedback writes never fall through to the default libsql store.
251
- observability: observabilityDomain ?? false,
252
- harness: harnessStorage
253
- }
254
- });
255
- const observability = new Observability({
256
- configs: {
257
- default: {
258
- serviceName: "mastracode",
259
- // Only these requestContext keys are stored on spans — prevents leaking
260
- // large objects (controller state, workspace, env vars) into trace data.
261
- // Use dot-notation because these are nested inside the 'controller' key.
262
- //
263
- // Session identifiers:
264
- // threadId, resourceId, session.modeId, agentControllerId
265
- // Environment & project:
266
- // state.projectName, state.gitBranch
267
- // Model configuration:
268
- // session.modelId, state.subagentModelId
269
- // Agent settings:
270
- // state.yolo, state.thinkingLevel, state.smartEditing
271
- // Observational memory settings:
272
- // state.omScope, state.observerModelId, state.reflectorModelId,
273
- // state.observationThreshold, state.reflectionThreshold
274
- requestContextKeys: [
275
- // Session identifiers
276
- "controller.threadId",
277
- "controller.resourceId",
278
- "controller.session.modeId",
279
- "controller.controllerId",
280
- // Environment & project
281
- "controller.state.projectName",
282
- "controller.state.gitBranch",
283
- // Model configuration
284
- "controller.session.modelId",
285
- "controller.state.subagentModelId",
286
- // Agent settings
287
- "controller.state.yolo",
288
- "controller.state.thinkingLevel",
289
- "controller.state.smartEditing",
290
- // Observational memory settings
291
- "controller.state.omScope",
292
- "controller.state.observerModelId",
293
- "controller.state.reflectorModelId",
294
- "controller.state.observationThreshold",
295
- "controller.state.reflectionThreshold"
296
- ],
297
- exporters: [
298
- // Only persist traces locally when DuckDB observability is available
299
- // (via `/observability local on`). Without this guard the storage
300
- // exporter falls through to the default libsql backend and silently
301
- // fills the main database with gigabytes of span data.
302
- ...observabilityDomain ? [new MastraStorageExporter({ strategy: "event-sourced" })] : [],
303
- new MastraPlatformExporter(resolveCloudObservabilityConfig(globalSettings, authStorage, project.resourceId))
304
- ],
305
- spanOutputProcessors: [new SensitiveDataFilter()]
306
- }
307
- }
308
- });
309
- const vector = config?.vector ?? (storageConfig ? await createVectorStore(storageConfig, storageResult.backend) : void 0);
310
- const storageMaintenance = createStorageMaintenance({
311
- storage: storageResult.storage,
312
- backend: storageResult.backend,
313
- retention: DEFAULT_RETENTION,
314
- localDbFiles: storageConfig ? resolveLocalDbFiles(storageConfig, storageResult.backend) : [],
315
- closeVector: vector instanceof LibSQLVector ? () => vector.close() : void 0
316
- });
317
- const memory = config?.memory === false ? void 0 : config?.memory ?? getDynamicMemory(storage, vector);
318
- const mcpManager = config?.disableMcp ? void 0 : createMcpManager(project.rootPath, configDir, config?.mcpServers);
319
- const hookManager = config?.disableHooks ? void 0 : new HookManager(project.rootPath, "session-init", configDir, homeDir);
320
- const pluginManager = config?.disablePlugins ? void 0 : config?.pluginManager ?? new PluginManager({ projectRoot: project.rootPath, configDir, homeDir });
321
- const loadedPlugins = pluginManager ? await pluginManager.reload() : [];
322
- const pluginTools = pluginManager?.getPluginTools() ?? {};
323
- const outcomeScorer = createOutcomeScorer();
324
- const efficiencyScorer = createEfficiencyScorer();
325
- const githubSignals = globalSettings.signals?.experimentalGithubSignals && !config?.disableGithubSignals ? new GithubSignals({
326
- cwd: project.rootPath,
327
- gitcrawlCommand: process.env.MASTRACODE_GITCRAWL_BIN ?? process.env.GITCRAWL_BIN ?? process.env.MASTRACODE_GITCRAWL_COMMAND ?? process.env.GITCRAWL_COMMAND,
328
- getNotificationStreamOptions: async ({ resourceId, threadId }) => {
329
- const session = await controller.getSessionByResource(resourceId) ?? activeSession;
330
- const modeId = session.mode.get();
331
- const defaultModeModelId = controller.listModes().find((mode) => mode.id === modeId)?.defaultModelId;
332
- const modelId = session.model.get() || activeSession?.model.get() || defaultModeModelId || "";
333
- const requestContext = new RequestContext();
334
- const agentControllerContext = {
335
- controllerId: controller.id,
336
- state: session.state.get(),
337
- getState: () => session.state.get(),
338
- setState: (updates) => session.state.set(updates),
339
- threadId,
340
- resourceId,
341
- session: {
342
- id: session.identity.getId(),
343
- ownerId: session.identity.getOwnerId(),
344
- modeId,
345
- modelId,
346
- state: {
347
- get: () => session.state.get(),
348
- set: (updates) => session.state.set(updates),
349
- update: (updater) => session.state.update(updater)
350
- }
351
- },
352
- workspace: controller.getWorkspace(),
353
- getSubagentModelId: (params) => session.subagents.model.get(params ?? {})
354
- };
355
- requestContext.set("controller", agentControllerContext);
356
- return {
357
- memory: { thread: threadId, resource: resourceId },
358
- requestContext,
359
- maxSteps: 1e3,
360
- savePerStep: false,
361
- requireToolApproval: session.state.get().yolo !== true,
362
- modelSettings: { temperature: 1 }
363
- };
364
- }
365
- }) : void 0;
366
- const codeAgent = createCodingAgent({
367
- id: CODE_AGENT_ID,
368
- name: "Code Agent",
369
- // Workspace is wired per-request at the AgentController level (see
370
- // `config.workspace` below), so opt out of the factory's default local
371
- // workspace. An explicit `undefined` is required: the factory only builds a
372
- // default when the `workspace` key is absent.
373
- workspace: void 0,
374
- instructions: getDynamicInstructions,
375
- model: getDynamicModel,
376
- tools: createDynamicTools(mcpManager, config?.extraTools, config?.disabledTools, storage, pluginTools),
377
- hooks: createToolHooks(hookManager, config?.postToolObserver),
378
- scorers: {
379
- outcome: {
380
- scorer: outcomeScorer,
381
- sampling: { type: "none" }
382
- },
383
- efficiency: {
384
- scorer: efficiencyScorer,
385
- sampling: { type: "ratio", rate: 0.3 }
386
- }
387
- },
388
- // TaskSignalProvider bundles the task tools + TaskStateProcessor: it merges
389
- // the tools into the toolset and registers the task state-signal processor,
390
- // so the task list persists across turns and survives OM truncation.
391
- signals: [new TaskSignalProvider(), ...githubSignals ? [githubSignals] : []],
392
- // Native goal mechanism: the in-loop goal step judges the thread's active
393
- // objective each qualifying iteration. The judge model is required for any
394
- // gating to occur; when unset the goal step is a complete no-op. A6 auto-wires
395
- // the GoalStateProcessor so the `<current-objective>` signal persists across
396
- // turns. Per-thread overrides live in the ThreadState `goal` record and win
397
- // over these defaults.
398
- goal: {
399
- // Resolve the judge model through mastracode's gateway (a model-resolver
400
- // function) so provider credentials are injected; returns undefined when no
401
- // judge model is configured, keeping the goal step a no-op. Bind the same
402
- // `settingsPath` used above so the judge model and `maxRuns` come from one
403
- // config (a custom settings file would otherwise diverge).
404
- judge: (ctx) => getGoalJudgeModel(ctx, config?.settingsPath),
405
- maxRuns: globalSettings.models.goalMaxTurns ?? 50,
406
- maxSteps: 1e3,
407
- prompt: DEFAULT_GOAL_JUDGE_PROMPT,
408
- // Read-only workspace tools the default goal judge may call to verify the
409
- // agent's work against the actual filesystem (view, search_content,
410
- // find_files, file_stat, lsp_inspect) rather than grading prose alone
411
- // restoring the original MastraCode judge's verification ability. Resolved
412
- // per-request from the active workspace (mirrors `judge`).
413
- tools: getGoalJudgeTools
414
- },
415
- inputProcessors: [
416
- ...config?.inputProcessors ?? [],
417
- new PlanRejectionAbortProcessor(),
418
- new AgentsMDInjector({
419
- getIgnoredInstructionPaths: ({ requestContext }) => {
420
- const agentControllerContext = requestContext?.get("controller");
421
- const state = agentControllerContext?.getState();
422
- return getStaticallyLoadedInstructionPaths(state?.projectPath ?? project.rootPath);
423
- }
424
- }),
425
- new ProviderHistoryCompat()
426
- ],
427
- errorProcessors: [
428
- // ProviderHistoryCompat must run before StreamErrorRetryProcessor: both react to
429
- // HTTP 400s, but ProviderHistoryCompat repairs the incompatible history (e.g.
430
- // sanitizing tool-call IDs) before retrying, while StreamErrorRetryProcessor's
431
- // isBadRequestError matcher retries the identical request. Error processors
432
- // short-circuit on the first `retry: true`, so a blind retry first would resend
433
- // the broken history and fail again.
434
- new ProviderHistoryCompat(),
435
- new StreamErrorRetryProcessor({
436
- matchers: [
437
- { match: isBadRequestError, maxRetries: 1, delayMs: 2e3 },
438
- {
439
- match: isTransientConnectionError,
440
- maxRetries: MASTRACODE_TRANSIENT_CONNECTION_MAX_RETRIES,
441
- delayMs: ({ retryCount }) => Math.min(
442
- MASTRACODE_TRANSIENT_CONNECTION_RETRY_INITIAL_DELAY_MS * Math.pow(2, retryCount),
443
- MASTRACODE_TRANSIENT_CONNECTION_RETRY_MAX_DELAY_MS
444
- )
445
- }
446
- ]
447
- }),
448
- new PrefillErrorHandler()
449
- ]
450
- });
451
- const defaultModes = [
452
- {
453
- ...buildMode,
454
- metadata: {
455
- ...buildMode.metadata,
456
- color: mastraBrand.green
457
- }
458
- },
459
- {
460
- ...planMode,
461
- metadata: {
462
- ...planMode.metadata,
463
- color: mastraBrand.purple
464
- }
465
- },
466
- {
467
- ...fastMode,
468
- metadata: {
469
- ...fastMode.metadata,
470
- color: mastraBrand.orange
471
- }
472
- }
473
- ];
474
- const defaultIntervalHandlers = [
475
- {
476
- id: "gateway-sync",
477
- intervalMs: 5 * 60 * 1e3,
478
- immediate: false,
479
- handler: () => syncGateways()
480
- }
481
- ];
482
- const intervalHandlers = config?.intervalHandlers ?? defaultIntervalHandlers;
483
- const anthropicCred = authStorage.get("anthropic");
484
- const openaiCred = authStorage.get("openai-codex");
485
- const githubCopilotCred = authStorage.get("github-copilot");
486
- const startupAccess = {
487
- anthropic: anthropicCred?.type === "oauth" ? "oauth" : anthropicCred?.type === "api_key" && anthropicCred.key.trim().length > 0 ? "apikey" : false,
488
- openai: openaiCred?.type === "oauth" ? "oauth" : openaiCred?.type === "api_key" && openaiCred.key.trim().length > 0 ? "apikey" : false,
489
- cerebras: process.env.CEREBRAS_API_KEY ? "apikey" : false,
490
- google: process.env.GOOGLE_GENERATIVE_AI_API_KEY ? "apikey" : false,
491
- deepseek: process.env.DEEPSEEK_API_KEY ? "apikey" : false,
492
- "github-copilot": githubCopilotCred?.type === "oauth" ? "oauth" : false
493
- };
494
- if (mgApiKey) {
495
- if (!startupAccess.anthropic) startupAccess.anthropic = "apikey";
496
- if (!startupAccess.openai) startupAccess.openai = "apikey";
497
- }
498
- try {
499
- const registry = PROVIDER_REGISTRY;
500
- for (const [provider, config2] of Object.entries(registry)) {
501
- if (startupAccess[provider] === "oauth" || startupAccess[provider] === "apikey") continue;
502
- if (provider === "anthropic" || provider === "openai") continue;
503
- const envVars = config2?.apiKeyEnvVar;
504
- const envVarList = Array.isArray(envVars) ? envVars : envVars ? [envVars] : [];
505
- if (envVarList.some((envVar) => process.env[envVar])) {
506
- startupAccess[provider] = "apikey";
507
- }
508
- }
509
- } catch {
510
- }
511
- const builtinPacks = getAvailableModePacks(startupAccess);
512
- const builtinOmPacks = getAvailableOmPacks(startupAccess);
513
- const effectiveDefaults = resolveModelDefaults(globalSettings, builtinPacks);
514
- const effectiveObserverModel = resolveOmRoleModel(globalSettings, "observer", builtinOmPacks);
515
- const effectiveReflectorModel = resolveOmRoleModel(globalSettings, "reflector", builtinOmPacks);
516
- const effectiveObservationThreshold = globalSettings.models.omObservationThreshold ?? void 0;
517
- const effectiveReflectionThreshold = globalSettings.models.omReflectionThreshold ?? void 0;
518
- const effectiveCavemanObservations = globalSettings.models.omCavemanObservations ?? void 0;
519
- const effectiveObserveAttachments = globalSettings.models.omObserveAttachments ?? "auto";
520
- const modes = addPluginToolsToModeAllowlists(
521
- applyEffectiveDefaultsToModes(config?.modes ? config.modes : defaultModes, effectiveDefaults),
522
- Object.keys(pluginTools)
523
- );
524
- const defaultModeId = modes.find((mode) => mode.metadata?.default === true)?.id ?? modes.find((mode) => mode.id === "build")?.id ?? modes[0]?.id;
525
- if (!defaultModeId) {
526
- throw new Error("MastraCode requires at least one mode");
527
- }
528
- const globalInitialState = {};
529
- if (!config?.disableSettingsOmSeed) {
530
- if (effectiveObserverModel) {
531
- globalInitialState.observerModelId = effectiveObserverModel;
532
- }
533
- if (effectiveReflectorModel) {
534
- globalInitialState.reflectorModelId = effectiveReflectorModel;
535
- }
536
- if (effectiveObservationThreshold !== void 0) {
537
- globalInitialState.observationThreshold = effectiveObservationThreshold;
538
- }
539
- if (effectiveReflectionThreshold !== void 0) {
540
- globalInitialState.reflectionThreshold = effectiveReflectionThreshold;
541
- }
542
- if (effectiveCavemanObservations !== void 0) {
543
- globalInitialState.cavemanObservations = effectiveCavemanObservations;
544
- }
545
- if (effectiveObserveAttachments !== void 0) {
546
- globalInitialState.observeAttachments = effectiveObserveAttachments;
547
- }
548
- }
549
- if (globalSettings.preferences.yolo !== null) {
550
- globalInitialState.yolo = globalSettings.preferences.yolo;
551
- }
552
- globalInitialState.thinkingLevel = globalSettings.preferences.thinkingLevel;
553
- if (config?.omScope) {
554
- globalInitialState.omScope = config.omScope;
555
- }
556
- for (const [key, modelId] of Object.entries(globalSettings.models.subagentModels)) {
557
- if (key === "default" || key === "_default") {
558
- globalInitialState.subagentModelId = modelId;
559
- } else {
560
- globalInitialState[`subagentModelId_${key}`] = modelId;
561
- }
562
- }
563
- const typedStateSchema = stateSchema;
564
- const controller = new AgentController({
565
- id: "mastra-code",
566
- resourceId: project.resourceId,
567
- storage,
568
- observability,
569
- memory,
570
- pubsub: signalsPubSub,
571
- stateSchema: typedStateSchema,
572
- agent: codeAgent,
573
- subagents: config?.subagents ?? [],
574
- gateways: [amazonBedrockGateway, mastraCodeGateway],
575
- workspace: config?.workspace ?? ((args) => getDynamicWorkspace(args)),
576
- browser: config?.browser,
577
- idGenerator: config?.idGenerator,
578
- toolCategoryResolver: getToolCategory,
579
- initialState: {
580
- projectPath: project.rootPath,
581
- projectName: project.name,
582
- gitBranch: project.gitBranch,
583
- pluginSkillPaths: loadedPlugins.flatMap((plugin) => plugin.status === "active" ? plugin.skillPaths ?? [] : []),
584
- pluginCommandPaths: loadedPlugins.flatMap(
585
- (plugin) => plugin.status === "active" ? plugin.commandPaths ?? [] : []
586
- ),
587
- pluginInstructions: loadedPlugins.flatMap(
588
- (plugin) => plugin.status === "active" && plugin.instructions ? [plugin.instructions] : []
589
- ),
590
- yolo: true,
591
- ...globalInitialState,
592
- ...config?.initialState,
593
- // configDir must always win over initialState spreads to stay in sync
594
- // with MCP/hooks/storage which were already initialized with this value.
595
- configDir
596
- },
597
- modes,
598
- intervalHandlers,
599
- modelUseCountProvider: () => loadSettings().modelUseCounts,
600
- modelUseCountTracker: (modelId) => {
601
- try {
602
- const settings = loadSettings();
603
- settings.modelUseCounts[modelId] = (settings.modelUseCounts[modelId] ?? 0) + 1;
604
- saveSettings(settings);
605
- } catch (error) {
606
- console.error("Failed to persist model usage count", error);
607
- }
608
- },
609
- threadLock: crossProcessPubSub ? void 0 : {
610
- acquire: acquireThreadLock,
611
- release: releaseThreadLock
612
- }
613
- });
614
- return {
615
- controller,
616
- storage,
617
- storageMaintenance,
618
- observability,
619
- memory,
620
- mcpManager,
621
- hookManager,
622
- pluginManager,
623
- loadedPlugins,
624
- pluginTools,
625
- signalsPubSub,
626
- authStorage,
627
- resolveModel,
628
- storageWarning,
629
- observabilityWarning,
630
- builtinPacks,
631
- builtinOmPacks,
632
- effectiveDefaults,
633
- githubSignals,
634
- // Identity for the single local session (Case 3). Servers ignore these and
635
- // mint per-request sessions with client-supplied resourceIds instead.
636
- sessionId,
637
- ownerId,
638
- // Lets the composition layer publish the created session back into the
639
- // config closures (e.g. notification stream options read it lazily).
640
- setActiveSession: (session) => {
641
- activeSession = session;
642
- }
643
- };
167
+ const cwd = config?.cwd ?? process.cwd();
168
+ const homeDir = config?.homeDir ?? config?.initialState?.homeDir;
169
+ const configDir = config?.configDir ?? ".mastracode";
170
+ let activeSession;
171
+ if (configDir !== ".mastracode") validateConfigDirName(configDir);
172
+ try {
173
+ process.loadEnvFile(path.join(cwd, ".env"));
174
+ } catch {}
175
+ const authStorage = createAuthStorage();
176
+ const globalSettings = loadSettings(config?.settingsPath);
177
+ const storedGatewayKey = authStorage.getStoredApiKey(MASTRA_GATEWAY_PROVIDER);
178
+ const storedGatewayUrl = globalSettings.memoryGateway?.baseUrl;
179
+ if (storedGatewayKey) process.env["MASTRA_GATEWAY_API_KEY"] ??= storedGatewayKey;
180
+ if (storedGatewayUrl) process.env["MASTRA_GATEWAY_URL"] ??= storedGatewayUrl;
181
+ if (!hasCredentialStoreProvider()) try {
182
+ const registry = PROVIDER_REGISTRY;
183
+ const providerEnvVars = {};
184
+ for (const [provider, cfg] of Object.entries(registry)) {
185
+ const envVars = cfg?.apiKeyEnvVar;
186
+ providerEnvVars[provider] = Array.isArray(envVars) ? envVars[0] : envVars;
187
+ }
188
+ providerEnvVars[MASTRA_GATEWAY_PROVIDER] ??= "MASTRA_GATEWAY_API_KEY";
189
+ authStorage.loadStoredApiKeysIntoEnv(providerEnvVars);
190
+ } catch {
191
+ authStorage.loadStoredApiKeysIntoEnv({
192
+ [MASTRA_GATEWAY_PROVIDER]: "MASTRA_GATEWAY_API_KEY",
193
+ anthropic: "ANTHROPIC_API_KEY",
194
+ openai: "OPENAI_API_KEY",
195
+ google: "GOOGLE_GENERATIVE_AI_API_KEY",
196
+ cerebras: "CEREBRAS_API_KEY",
197
+ deepseek: "DEEPSEEK_API_KEY"
198
+ });
199
+ }
200
+ const mgApiKey = process.env["MASTRA_GATEWAY_API_KEY"] ?? storedGatewayKey;
201
+ const mastraCodeGateway = createMastraCodeGateway({
202
+ mastraGatewayBaseUrl: (process.env["MASTRA_GATEWAY_URL"] ?? storedGatewayUrl ?? "https://gateway-api.mastra.ai").replace(/\/+$/, "").replace(/\/v1$/, ""),
203
+ mastraGatewayApiKey: mgApiKey,
204
+ routeThroughMastraGateway: false,
205
+ settingsPath: config?.settingsPath
206
+ });
207
+ const amazonBedrockGateway = createAmazonBedrockGateway();
208
+ const project = detectProject(cwd);
209
+ const resourceIdOverride = getResourceIdOverride(project.rootPath, configDir);
210
+ if (resourceIdOverride) {
211
+ project.resourceId = resourceIdOverride;
212
+ project.resourceIdOverride = true;
213
+ }
214
+ const sessionId = `mastracode-session-${shortHash(project.resourceId)}`;
215
+ const ownerId = `mastracode-${shortHash(`${hostname()}\0${project.rootPath}`)}`;
216
+ const configuredPubSub = config?.pubsub;
217
+ const useUnixSocketPubSub = (config?.unixSocketPubSub ?? globalSettings.signals?.unixSocketPubSub ?? false) && process.platform !== "win32";
218
+ const signalsPubSub = configuredPubSub ?? (useUnixSocketPubSub ? createSignalsPubSub(project.resourceId) : void 0);
219
+ const crossProcessPubSub = config?.crossProcessPubSub ?? (!configuredPubSub && useUnixSocketPubSub);
220
+ if (crossProcessPubSub && !signalsPubSub) throw new Error("crossProcessPubSub requires a pubsub instance");
221
+ const injectedStorage = isInjectedStorageInstance(config?.storage) ? config.storage : void 0;
222
+ const storageConfig = injectedStorage ? void 0 : config?.storage ?? getStorageConfig(project.rootPath, globalSettings.storage, configDir);
223
+ const storageResult = injectedStorage ? {
224
+ storage: injectedStorage,
225
+ backend: resolveInjectedStorageBackend(injectedStorage, config?.storageBackend)
226
+ } : await createStorage(storageConfig);
227
+ const storageWarning = storageResult.warning;
228
+ let observabilityDomain;
229
+ let observabilityWarning;
230
+ if (globalSettings.observability.localTracing) try {
231
+ const observabilityDuckDB = new DuckDBStore({
232
+ id: "mastra-code-observability",
233
+ path: getObservabilityDatabasePath()
234
+ });
235
+ await observabilityDuckDB.db.getConnection();
236
+ observabilityDomain = observabilityDuckDB.observability;
237
+ } catch (err) {
238
+ const message = err instanceof Error ? err.message : String(err);
239
+ if (/lock|locked|busy/i.test(message)) observabilityWarning = "Observability unavailable — another MastraCode instance holds the database lock. Traces, scores, and feedback will not be recorded in this session.";
240
+ else observabilityWarning = `Observability unavailable — DuckDB initialization failed: ${message}`;
241
+ }
242
+ const harnessStorage = new InMemoryHarness();
243
+ const storage = new MastraCompositeStore({
244
+ id: "mastra-code-storage",
245
+ default: storageResult.storage,
246
+ domains: {
247
+ observability: observabilityDomain ?? false,
248
+ harness: harnessStorage
249
+ }
250
+ });
251
+ const observability = new Observability({ configs: { default: {
252
+ serviceName: "mastracode",
253
+ requestContextKeys: [
254
+ "controller.threadId",
255
+ "controller.resourceId",
256
+ "controller.session.modeId",
257
+ "controller.controllerId",
258
+ "controller.state.projectName",
259
+ "controller.state.gitBranch",
260
+ "controller.session.modelId",
261
+ "controller.state.subagentModelId",
262
+ "controller.state.yolo",
263
+ "controller.state.thinkingLevel",
264
+ "controller.state.smartEditing",
265
+ "controller.state.omScope",
266
+ "controller.state.observerModelId",
267
+ "controller.state.reflectorModelId",
268
+ "controller.state.observationThreshold",
269
+ "controller.state.reflectionThreshold"
270
+ ],
271
+ exporters: [...observabilityDomain ? [new MastraStorageExporter({ strategy: "event-sourced" })] : [], new MastraPlatformExporter(resolveCloudObservabilityConfig(globalSettings, authStorage, project.resourceId))],
272
+ spanOutputProcessors: [new SensitiveDataFilter()]
273
+ } } });
274
+ const vector = config?.vector ?? (storageConfig ? await createVectorStore(storageConfig, storageResult.backend) : void 0);
275
+ const storageMaintenance = createStorageMaintenance({
276
+ storage: storageResult.storage,
277
+ backend: storageResult.backend,
278
+ retention: DEFAULT_RETENTION,
279
+ localDbFiles: storageConfig ? resolveLocalDbFiles(storageConfig, storageResult.backend) : [],
280
+ closeVector: vector instanceof LibSQLVector ? () => vector.close() : void 0
281
+ });
282
+ const memory = config?.memory === false ? void 0 : config?.memory ?? getDynamicMemory(storage, vector);
283
+ const mcpManager = config?.disableMcp ? void 0 : createMcpManager(project.rootPath, configDir, config?.mcpServers);
284
+ const hookManager = config?.disableHooks ? void 0 : new HookManager(project.rootPath, "session-init", configDir, homeDir);
285
+ const pluginManager = config?.disablePlugins ? void 0 : config?.pluginManager ?? new PluginManager({
286
+ projectRoot: project.rootPath,
287
+ configDir,
288
+ homeDir
289
+ });
290
+ const loadedPlugins = pluginManager ? await pluginManager.reload() : [];
291
+ const pluginTools = pluginManager?.getPluginTools() ?? {};
292
+ const outcomeScorer = createOutcomeScorer();
293
+ const efficiencyScorer = createEfficiencyScorer();
294
+ const githubSignals = globalSettings.signals?.experimentalGithubSignals && !config?.disableGithubSignals ? new GithubSignals({
295
+ cwd: project.rootPath,
296
+ gitcrawlCommand: process.env.MASTRACODE_GITCRAWL_BIN ?? process.env.GITCRAWL_BIN ?? process.env.MASTRACODE_GITCRAWL_COMMAND ?? process.env.GITCRAWL_COMMAND,
297
+ getNotificationStreamOptions: async ({ resourceId, threadId }) => {
298
+ const session = await controller.getSessionByResource(resourceId) ?? activeSession;
299
+ const modeId = session.mode.get();
300
+ const defaultModeModelId = controller.listModes().find((mode) => mode.id === modeId)?.defaultModelId;
301
+ const modelId = session.model.get() || activeSession?.model.get() || defaultModeModelId || "";
302
+ const requestContext = new RequestContext();
303
+ const agentControllerContext = {
304
+ controllerId: controller.id,
305
+ state: session.state.get(),
306
+ getState: () => session.state.get(),
307
+ setState: (updates) => session.state.set(updates),
308
+ threadId,
309
+ resourceId,
310
+ session: {
311
+ id: session.identity.getId(),
312
+ ownerId: session.identity.getOwnerId(),
313
+ modeId,
314
+ modelId,
315
+ state: {
316
+ get: () => session.state.get(),
317
+ set: (updates) => session.state.set(updates),
318
+ update: (updater) => session.state.update(updater)
319
+ }
320
+ },
321
+ workspace: controller.getWorkspace(),
322
+ getSubagentModelId: (params) => session.subagents.model.get(params ?? {})
323
+ };
324
+ requestContext.set("controller", agentControllerContext);
325
+ return {
326
+ memory: {
327
+ thread: threadId,
328
+ resource: resourceId
329
+ },
330
+ requestContext,
331
+ maxSteps: 1e3,
332
+ savePerStep: false,
333
+ requireToolApproval: session.state.get().yolo !== true,
334
+ modelSettings: { temperature: 1 }
335
+ };
336
+ }
337
+ }) : void 0;
338
+ const codeAgent = createCodingAgent({
339
+ id: CODE_AGENT_ID,
340
+ name: "Code Agent",
341
+ workspace: void 0,
342
+ instructions: getDynamicInstructions,
343
+ model: getDynamicModel,
344
+ tools: createDynamicTools(mcpManager, config?.extraTools, config?.disabledTools, storage, pluginTools),
345
+ hooks: createToolHooks(hookManager, config?.postToolObserver),
346
+ scorers: {
347
+ outcome: {
348
+ scorer: outcomeScorer,
349
+ sampling: { type: "none" }
350
+ },
351
+ efficiency: {
352
+ scorer: efficiencyScorer,
353
+ sampling: {
354
+ type: "ratio",
355
+ rate: .3
356
+ }
357
+ }
358
+ },
359
+ signals: [new TaskSignalProvider(), ...githubSignals ? [githubSignals] : []],
360
+ goal: {
361
+ judge: (ctx) => getGoalJudgeModel(ctx, config?.settingsPath),
362
+ maxRuns: globalSettings.models.goalMaxTurns ?? 50,
363
+ maxSteps: 1e3,
364
+ prompt: DEFAULT_GOAL_JUDGE_PROMPT,
365
+ tools: getGoalJudgeTools
366
+ },
367
+ inputProcessors: [
368
+ ...config?.inputProcessors ?? [],
369
+ new PlanRejectionAbortProcessor(),
370
+ new AgentsMDInjector({ getIgnoredInstructionPaths: ({ requestContext }) => {
371
+ const state = (requestContext?.get("controller"))?.getState();
372
+ return getStaticallyLoadedInstructionPaths(state?.projectPath ?? project.rootPath);
373
+ } }),
374
+ new ProviderHistoryCompat()
375
+ ],
376
+ errorProcessors: [
377
+ new ProviderHistoryCompat(),
378
+ new StreamErrorRetryProcessor({ matchers: [{
379
+ match: isBadRequestError,
380
+ maxRetries: 1,
381
+ delayMs: 2e3
382
+ }, {
383
+ match: isTransientConnectionError,
384
+ maxRetries: MASTRACODE_TRANSIENT_CONNECTION_MAX_RETRIES,
385
+ delayMs: ({ retryCount }) => Math.min(MASTRACODE_TRANSIENT_CONNECTION_RETRY_INITIAL_DELAY_MS * Math.pow(2, retryCount), MASTRACODE_TRANSIENT_CONNECTION_RETRY_MAX_DELAY_MS)
386
+ }] }),
387
+ new PrefillErrorHandler()
388
+ ]
389
+ });
390
+ const defaultModes = [
391
+ {
392
+ ...buildMode,
393
+ metadata: {
394
+ ...buildMode.metadata,
395
+ color: mastraBrand.green
396
+ }
397
+ },
398
+ {
399
+ ...planMode,
400
+ metadata: {
401
+ ...planMode.metadata,
402
+ color: mastraBrand.purple
403
+ }
404
+ },
405
+ {
406
+ ...fastMode,
407
+ metadata: {
408
+ ...fastMode.metadata,
409
+ color: mastraBrand.orange
410
+ }
411
+ }
412
+ ];
413
+ const intervalHandlers = config?.intervalHandlers ?? [{
414
+ id: "gateway-sync",
415
+ intervalMs: 300 * 1e3,
416
+ immediate: false,
417
+ handler: () => syncGateways()
418
+ }];
419
+ const anthropicCred = authStorage.get("anthropic");
420
+ const openaiCred = authStorage.get("openai-codex");
421
+ const githubCopilotCred = authStorage.get("github-copilot");
422
+ const startupAccess = {
423
+ anthropic: anthropicCred?.type === "oauth" ? "oauth" : anthropicCred?.type === "api_key" && anthropicCred.key.trim().length > 0 ? "apikey" : false,
424
+ openai: openaiCred?.type === "oauth" ? "oauth" : openaiCred?.type === "api_key" && openaiCred.key.trim().length > 0 ? "apikey" : false,
425
+ cerebras: process.env.CEREBRAS_API_KEY ? "apikey" : false,
426
+ google: process.env.GOOGLE_GENERATIVE_AI_API_KEY ? "apikey" : false,
427
+ deepseek: process.env.DEEPSEEK_API_KEY ? "apikey" : false,
428
+ "github-copilot": githubCopilotCred?.type === "oauth" ? "oauth" : false
429
+ };
430
+ if (mgApiKey) {
431
+ if (!startupAccess.anthropic) startupAccess.anthropic = "apikey";
432
+ if (!startupAccess.openai) startupAccess.openai = "apikey";
433
+ }
434
+ try {
435
+ const registry = PROVIDER_REGISTRY;
436
+ for (const [provider, config] of Object.entries(registry)) {
437
+ if (startupAccess[provider] === "oauth" || startupAccess[provider] === "apikey") continue;
438
+ if (provider === "anthropic" || provider === "openai") continue;
439
+ const envVars = config?.apiKeyEnvVar;
440
+ if ((Array.isArray(envVars) ? envVars : envVars ? [envVars] : []).some((envVar) => process.env[envVar])) startupAccess[provider] = "apikey";
441
+ }
442
+ } catch {}
443
+ const builtinPacks = getAvailableModePacks(startupAccess);
444
+ const builtinOmPacks = getAvailableOmPacks(startupAccess);
445
+ const effectiveDefaults = resolveModelDefaults(globalSettings, builtinPacks);
446
+ const activeProviderId = effectiveDefaults.build?.split("/")[0];
447
+ const preferredOmModel = hasExplicitOMConfiguration(globalSettings) ? void 0 : selectPreferredOMPack(startupAccess, activeProviderId)?.modelId;
448
+ const effectiveObserverModel = resolveOmRoleModel(globalSettings, "observer", builtinOmPacks) || preferredOmModel;
449
+ const effectiveReflectorModel = resolveOmRoleModel(globalSettings, "reflector", builtinOmPacks) || preferredOmModel;
450
+ const effectiveObservationThreshold = globalSettings.models.omObservationThreshold ?? void 0;
451
+ const effectiveReflectionThreshold = globalSettings.models.omReflectionThreshold ?? void 0;
452
+ const effectiveCavemanObservations = globalSettings.models.omCavemanObservations ?? void 0;
453
+ const effectiveObserveAttachments = globalSettings.models.omObserveAttachments ?? "auto";
454
+ const modes = addPluginToolsToModeAllowlists(applyEffectiveDefaultsToModes(config?.modes ? config.modes : defaultModes, effectiveDefaults), Object.keys(pluginTools));
455
+ if (!(modes.find((mode) => mode.metadata?.default === true)?.id ?? modes.find((mode) => mode.id === "build")?.id ?? modes[0]?.id)) throw new Error("MastraCode requires at least one mode");
456
+ const globalInitialState = {};
457
+ if (!config?.disableSettingsOmSeed) {
458
+ if (effectiveObserverModel) globalInitialState.observerModelId = effectiveObserverModel;
459
+ if (effectiveReflectorModel) globalInitialState.reflectorModelId = effectiveReflectorModel;
460
+ if (effectiveObservationThreshold !== void 0) globalInitialState.observationThreshold = effectiveObservationThreshold;
461
+ if (effectiveReflectionThreshold !== void 0) globalInitialState.reflectionThreshold = effectiveReflectionThreshold;
462
+ if (effectiveCavemanObservations !== void 0) globalInitialState.cavemanObservations = effectiveCavemanObservations;
463
+ if (effectiveObserveAttachments !== void 0) globalInitialState.observeAttachments = effectiveObserveAttachments;
464
+ }
465
+ if (globalSettings.preferences.yolo !== null) globalInitialState.yolo = globalSettings.preferences.yolo;
466
+ globalInitialState.thinkingLevel = globalSettings.preferences.thinkingLevel;
467
+ if (config?.omScope) globalInitialState.omScope = config.omScope;
468
+ for (const [key, modelId] of Object.entries(globalSettings.models.subagentModels)) if (key === "default" || key === "_default") globalInitialState.subagentModelId = modelId;
469
+ else globalInitialState[`subagentModelId_${key}`] = modelId;
470
+ const typedStateSchema = stateSchema;
471
+ const controller = new AgentController({
472
+ id: "mastra-code",
473
+ resourceId: project.resourceId,
474
+ storage,
475
+ observability,
476
+ memory,
477
+ pubsub: signalsPubSub,
478
+ stateSchema: typedStateSchema,
479
+ agent: codeAgent,
480
+ subagents: config?.subagents ?? [],
481
+ gateways: [amazonBedrockGateway, mastraCodeGateway],
482
+ workspace: config?.workspace ?? ((args) => getDynamicWorkspace(args)),
483
+ browser: config?.browser,
484
+ idGenerator: config?.idGenerator,
485
+ toolCategoryResolver: getToolCategory,
486
+ initialState: {
487
+ projectPath: project.rootPath,
488
+ projectName: project.name,
489
+ gitBranch: project.gitBranch,
490
+ pluginSkillPaths: loadedPlugins.flatMap((plugin) => plugin.status === "active" ? plugin.skillPaths ?? [] : []),
491
+ pluginCommandPaths: loadedPlugins.flatMap((plugin) => plugin.status === "active" ? plugin.commandPaths ?? [] : []),
492
+ pluginInstructions: loadedPlugins.flatMap((plugin) => plugin.status === "active" && plugin.instructions ? [plugin.instructions] : []),
493
+ yolo: true,
494
+ ...globalInitialState,
495
+ ...config?.initialState,
496
+ configDir
497
+ },
498
+ modes,
499
+ intervalHandlers,
500
+ modelUseCountProvider: () => loadSettings().modelUseCounts,
501
+ modelUseCountTracker: (modelId) => {
502
+ try {
503
+ const settings = loadSettings();
504
+ settings.modelUseCounts[modelId] = (settings.modelUseCounts[modelId] ?? 0) + 1;
505
+ saveSettings(settings);
506
+ } catch (error) {
507
+ console.error("Failed to persist model usage count", error);
508
+ }
509
+ },
510
+ threadLock: crossProcessPubSub ? void 0 : {
511
+ acquire: acquireThreadLock,
512
+ release: releaseThreadLock
513
+ }
514
+ });
515
+ return {
516
+ controller,
517
+ storage,
518
+ storageMaintenance,
519
+ observability,
520
+ memory,
521
+ mcpManager,
522
+ hookManager,
523
+ pluginManager,
524
+ loadedPlugins,
525
+ pluginTools,
526
+ signalsPubSub,
527
+ authStorage,
528
+ resolveModel,
529
+ storageWarning,
530
+ observabilityWarning,
531
+ builtinPacks,
532
+ builtinOmPacks,
533
+ effectiveDefaults,
534
+ githubSignals,
535
+ sessionId,
536
+ ownerId,
537
+ setActiveSession: (session) => {
538
+ activeSession = session;
539
+ }
540
+ };
644
541
  }
542
+ /**
543
+ * Wires the session-scoped concerns MastraCode layers on top of a Session:
544
+ * hookManager thread-id sync, GitHub PR polling for the current thread, and
545
+ * per-thread persistence of the mastracode-only `/om` settings.
546
+ *
547
+ * Used by {@link bootLocalAgentController} for the single local session. A server can
548
+ * call this for any session it mints if it wants the same background wiring.
549
+ */
645
550
  async function wireSessionConcerns(base, session) {
646
- const { hookManager, githubSignals } = base;
647
- base.setActiveSession(session);
648
- if (hookManager) {
649
- session.subscribe((event) => {
650
- if (event.type === "thread_changed") {
651
- hookManager.setSessionId(event.threadId);
652
- } else if (event.type === "thread_created") {
653
- hookManager.setSessionId(event.thread.id);
654
- }
655
- });
656
- }
657
- if (githubSignals) {
658
- const startGithubPollingForCurrentThread = async (threadId) => {
659
- if (!threadId) return;
660
- githubSignals.stopAllPolling();
661
- try {
662
- const threads = await session.thread.list({ allResources: true });
663
- const thread = threads.find((item) => item.id === threadId);
664
- await githubSignals.startPollingForThread(
665
- {
666
- threadId,
667
- resourceId: thread?.resourceId ?? session.identity.getResourceId()
668
- },
669
- { pollImmediately: true }
670
- );
671
- } catch (error) {
672
- console.warn("Failed to start GitHub PR polling:", error);
673
- }
674
- };
675
- session.subscribe((event) => {
676
- if (event.type === "thread_changed") void startGithubPollingForCurrentThread(event.threadId);
677
- else if (event.type === "thread_created") void startGithubPollingForCurrentThread(event.thread.id);
678
- });
679
- void startGithubPollingForCurrentThread(session.thread.getId());
680
- }
681
- const omThreadStateSession = session;
682
- attachOMThreadStatePersistence(omThreadStateSession);
683
- await restoreOMThreadStateForCurrentThread(omThreadStateSession).catch(() => {
684
- });
551
+ const { hookManager, githubSignals } = base;
552
+ base.setActiveSession(session);
553
+ if (hookManager) session.subscribe((event) => {
554
+ if (event.type === "thread_changed") hookManager.setSessionId(event.threadId);
555
+ else if (event.type === "thread_created") hookManager.setSessionId(event.thread.id);
556
+ });
557
+ if (githubSignals) {
558
+ const startGithubPollingForCurrentThread = async (threadId) => {
559
+ if (!threadId) return;
560
+ githubSignals.stopAllPolling();
561
+ try {
562
+ const thread = (await session.thread.list({ allResources: true })).find((item) => item.id === threadId);
563
+ await githubSignals.startPollingForThread({
564
+ threadId,
565
+ resourceId: thread?.resourceId ?? session.identity.getResourceId()
566
+ }, { pollImmediately: true });
567
+ } catch (error) {
568
+ console.warn("Failed to start GitHub PR polling:", error);
569
+ }
570
+ };
571
+ session.subscribe((event) => {
572
+ if (event.type === "thread_changed") startGithubPollingForCurrentThread(event.threadId);
573
+ else if (event.type === "thread_created") startGithubPollingForCurrentThread(event.thread.id);
574
+ });
575
+ startGithubPollingForCurrentThread(session.thread.getId());
576
+ }
577
+ const omThreadStateSession = session;
578
+ attachOMThreadStatePersistence(omThreadStateSession);
579
+ await restoreOMThreadStateForCurrentThread(omThreadStateSession).catch(() => {});
685
580
  }
581
+ /**
582
+ * Case 3 (AgentController local + TUI/headless): build the controller, let it stand up its
583
+ * own internal Mastra via `init()`, and mint the single eager session that all
584
+ * work in this process runs through. The AgentController owns no session of its own.
585
+ */
686
586
  async function bootLocalAgentController(config) {
687
- const base = await createMastraCodeAgentController(config);
688
- const { controller, sessionId, ownerId } = base;
689
- await controller.init();
690
- await controller.getMastra()?.startWorkers();
691
- const session = await controller.createSession({ id: sessionId, ownerId });
692
- await wireSessionConcerns(base, session);
693
- return { ...base, session };
587
+ const base = await createMastraCodeAgentController(config);
588
+ const { controller, sessionId, ownerId } = base;
589
+ await controller.init();
590
+ await controller.getMastra()?.startWorkers();
591
+ const session = await controller.createSession({
592
+ id: sessionId,
593
+ ownerId
594
+ });
595
+ await wireSessionConcerns(base, session);
596
+ return {
597
+ ...base,
598
+ session
599
+ };
694
600
  }
601
+ /**
602
+ * Cases 1 & 2 (AgentController in Server + Web/TUI): build the controller, register it on a
603
+ * server-owned Mastra, THEN init it. Registering before `init()` is what makes
604
+ * the controller inherit the server's Mastra (storage, agents, gateways) instead of
605
+ * spinning up its own internal one — there is a single shared Mastra.
606
+ *
607
+ * No eager session is minted: each client (browser or terminal) creates/resumes
608
+ * its own isolated session via `controller.createSession({ resourceId })`, so one
609
+ * server can drive many concurrent users.
610
+ *
611
+ * Pass an existing `mastra` to mount onto a Mastra that already hosts other
612
+ * primitives; otherwise a Mastra is created that owns the controller's storage so
613
+ * durability is configured in one place.
614
+ */
695
615
  async function mountAgentControllerOnMastra(config) {
696
- const prepared = await prepareAgentControllerMount(config);
697
- if (config?.mastra) {
698
- prepared.base.controller.__registerMastra(config.mastra);
699
- await prepared.finalize();
700
- return { ...prepared.base, mastra: config.mastra };
701
- }
702
- const mastra = new Mastra(prepared.mastraArgs);
703
- await prepared.finalize();
704
- return { ...prepared.base, mastra };
616
+ const prepared = await prepareAgentControllerMount(config);
617
+ if (config?.mastra) {
618
+ prepared.base.controller.__registerMastra(config.mastra);
619
+ await prepared.finalize();
620
+ return {
621
+ ...prepared.base,
622
+ mastra: config.mastra
623
+ };
624
+ }
625
+ const mastra = new Mastra(prepared.mastraArgs);
626
+ await prepared.finalize();
627
+ return {
628
+ ...prepared.base,
629
+ mastra
630
+ };
705
631
  }
632
+ /**
633
+ * Assemble everything needed to construct the server-owned Mastra WITHOUT
634
+ * constructing it, so a caller (the platform entry `src/mastra/index.ts`) can
635
+ * run the `new Mastra(...)` literal in its own module. The deployer's
636
+ * `checkConfigExport` Babel plugin only marks the config valid when it finds a
637
+ * top-level `new Mastra(...)` exported as `mastra` in the ENTRY file; hiding the
638
+ * construction inside this helper would trip the "Invalid Mastra config" warning.
639
+ *
640
+ * Returns the constructor args plus a `finalize()` that runs the post-construct
641
+ * boot (`controller.init()` + `startWorkers()`). The controller is registered on
642
+ * the Mastra via the `agentControllers` arg at construction time.
643
+ */
706
644
  async function prepareAgentControllerMount(config) {
707
- const base = await createMastraCodeAgentController(config);
708
- const { controller, storage, authStorage } = base;
709
- const controllerId = config?.controllerId ?? controller.id;
710
- const apiRoutes = config?.buildApiRoutes?.({ controller, authStorage });
711
- const extraServerConfig = config?.buildServerConfig?.({ controller, authStorage });
712
- const serverConfig = {
713
- ...extraServerConfig,
714
- ...apiRoutes?.length ? { apiRoutes } : {}
715
- };
716
- const mastraArgs = {
717
- agentControllers: { [controllerId]: controller },
718
- storage,
719
- // Mirror the controller's internal-Mastra construction (which passes
720
- // `config.pubsub` through): the server-owned Mastra must run its event
721
- // bus on the same transport so streams/workflows/signals stay
722
- // cross-process when a distributed PubSub (e.g. Redis Streams) is
723
- // configured.
724
- ...base.signalsPubSub ? { pubsub: base.signalsPubSub } : {},
725
- ...Object.keys(serverConfig).length ? { server: serverConfig } : {}
726
- };
727
- const finalize = async () => {
728
- await controller.init();
729
- await controller.getMastra()?.startWorkers();
730
- };
731
- return { base, mastraArgs, finalize };
645
+ const base = await createMastraCodeAgentController(config);
646
+ const { controller, storage, authStorage } = base;
647
+ const controllerId = config?.controllerId ?? controller.id;
648
+ const apiRoutes = config?.buildApiRoutes?.({
649
+ controller,
650
+ authStorage
651
+ });
652
+ const serverConfig = {
653
+ ...config?.buildServerConfig?.({
654
+ controller,
655
+ authStorage
656
+ }),
657
+ ...apiRoutes?.length ? { apiRoutes } : {}
658
+ };
659
+ const mastraArgs = {
660
+ agentControllers: { [controllerId]: controller },
661
+ storage,
662
+ ...base.signalsPubSub ? { pubsub: base.signalsPubSub } : {},
663
+ ...Object.keys(serverConfig).length ? { server: serverConfig } : {}
664
+ };
665
+ const finalize = async () => {
666
+ await controller.init();
667
+ await controller.getMastra()?.startWorkers();
668
+ };
669
+ return {
670
+ base,
671
+ mastraArgs,
672
+ finalize
673
+ };
732
674
  }
675
+ /**
676
+ * Back-compat alias. Historically `createMastraCode` built and booted a local
677
+ * controller with a single session; that behavior now lives in
678
+ * {@link bootLocalAgentController}. New code should call the explicit factory for its
679
+ * case: `bootLocalAgentController` (local) or {@link mountAgentControllerOnMastra} (server).
680
+ */
733
681
  const createMastraCode = bootLocalAgentController;
734
- import {
735
- runMC,
736
- runMCCli,
737
- hasHeadlessFlag,
738
- autoApprovePolicy,
739
- denyPolicy,
740
- permissionModeToPolicy,
741
- formatHuman,
742
- formatJsonl,
743
- renderTextResult,
744
- renderJsonResult
745
- } from "./headless/index.js";
746
- export {
747
- autoApprovePolicy,
748
- bootLocalAgentController,
749
- createAuthStorage,
750
- createMastraCode,
751
- createMastraCodeAgentController,
752
- denyPolicy,
753
- formatHuman,
754
- formatJsonl,
755
- hasHeadlessFlag,
756
- mountAgentControllerOnMastra,
757
- permissionModeToPolicy,
758
- prepareAgentControllerMount,
759
- renderJsonResult,
760
- renderTextResult,
761
- runMC,
762
- runMCCli,
763
- wireSessionConcerns
764
- };
682
+ //#endregion
683
+ export { autoApprovePolicy, bootLocalAgentController, createAuthStorage, createMastraCode, createMastraCodeAgentController, denyPolicy, formatHuman, formatJsonl, hasHeadlessFlag, mountAgentControllerOnMastra, permissionModeToPolicy, prepareAgentControllerMount, renderJsonResult, renderTextResult, runMC, runMCCli, wireSessionConcerns };
684
+
765
685
  //# sourceMappingURL=index.js.map