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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +11 -11
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,43 +1,52 @@
1
1
  import { WORKSPACE_TOOLS } from "@mastra/core/workspace";
2
+ //#region src/tool-names.ts
3
+ /**
4
+ * Mastracode tool name constants.
5
+ *
6
+ * These are the names exposed to the LLM via workspace tool name remapping.
7
+ * Used throughout mastracode for permissions, TUI rendering, tool guidance,
8
+ * subagent allowedTools, etc.
9
+ *
10
+ * The workspace tools get remapped from their core names (e.g. `mastra_workspace_read_file`)
11
+ * to these names (e.g. `view`) via the `name` property in workspace tool config.
12
+ */
2
13
  const MC_TOOLS = {
3
- // Filesystem
4
- VIEW: "view",
5
- WRITE_FILE: "write_file",
6
- STRING_REPLACE_LSP: "string_replace_lsp",
7
- FIND_FILES: "find_files",
8
- DELETE_FILE: "delete_file",
9
- FILE_STAT: "file_stat",
10
- MKDIR: "mkdir",
11
- // Search
12
- SEARCH_CONTENT: "search_content",
13
- // Code intelligence
14
- AST_SMART_EDIT: "ast_smart_edit",
15
- // Sandbox
16
- EXECUTE_COMMAND: "execute_command",
17
- GET_PROCESS_OUTPUT: "get_process_output",
18
- KILL_PROCESS: "kill_process",
19
- // Code intelligence
20
- LSP_INSPECT: "lsp_inspect",
21
- // Notifications
22
- NOTIFICATION_INBOX: "notification_inbox"
14
+ VIEW: "view",
15
+ WRITE_FILE: "write_file",
16
+ STRING_REPLACE_LSP: "string_replace_lsp",
17
+ FIND_FILES: "find_files",
18
+ DELETE_FILE: "delete_file",
19
+ FILE_STAT: "file_stat",
20
+ MKDIR: "mkdir",
21
+ SEARCH_CONTENT: "search_content",
22
+ AST_SMART_EDIT: "ast_smart_edit",
23
+ EXECUTE_COMMAND: "execute_command",
24
+ GET_PROCESS_OUTPUT: "get_process_output",
25
+ KILL_PROCESS: "kill_process",
26
+ LSP_INSPECT: "lsp_inspect",
27
+ NOTIFICATION_INBOX: "notification_inbox"
23
28
  };
29
+ /**
30
+ * Workspace tool name remapping config.
31
+ * Maps core workspace tool constants to mastracode's tool names.
32
+ * Pass this (or spread it) into `Workspace({ tools: ... })`.
33
+ */
24
34
  const TOOL_NAME_OVERRIDES = {
25
- [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: MC_TOOLS.VIEW },
26
- [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: { name: MC_TOOLS.WRITE_FILE },
27
- [WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE]: { name: MC_TOOLS.STRING_REPLACE_LSP },
28
- [WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES]: { name: MC_TOOLS.FIND_FILES },
29
- [WORKSPACE_TOOLS.FILESYSTEM.DELETE]: { name: MC_TOOLS.DELETE_FILE },
30
- [WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT]: { name: MC_TOOLS.FILE_STAT },
31
- [WORKSPACE_TOOLS.FILESYSTEM.MKDIR]: { name: MC_TOOLS.MKDIR },
32
- [WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: MC_TOOLS.SEARCH_CONTENT },
33
- [WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT]: { name: MC_TOOLS.AST_SMART_EDIT },
34
- [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { name: MC_TOOLS.EXECUTE_COMMAND },
35
- [WORKSPACE_TOOLS.SANDBOX.GET_PROCESS_OUTPUT]: { name: MC_TOOLS.GET_PROCESS_OUTPUT },
36
- [WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS]: { name: MC_TOOLS.KILL_PROCESS },
37
- [WORKSPACE_TOOLS.LSP.LSP_INSPECT]: { name: MC_TOOLS.LSP_INSPECT }
38
- };
39
- export {
40
- MC_TOOLS,
41
- TOOL_NAME_OVERRIDES
35
+ [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: MC_TOOLS.VIEW },
36
+ [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: { name: MC_TOOLS.WRITE_FILE },
37
+ [WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE]: { name: MC_TOOLS.STRING_REPLACE_LSP },
38
+ [WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES]: { name: MC_TOOLS.FIND_FILES },
39
+ [WORKSPACE_TOOLS.FILESYSTEM.DELETE]: { name: MC_TOOLS.DELETE_FILE },
40
+ [WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT]: { name: MC_TOOLS.FILE_STAT },
41
+ [WORKSPACE_TOOLS.FILESYSTEM.MKDIR]: { name: MC_TOOLS.MKDIR },
42
+ [WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: MC_TOOLS.SEARCH_CONTENT },
43
+ [WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT]: { name: MC_TOOLS.AST_SMART_EDIT },
44
+ [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { name: MC_TOOLS.EXECUTE_COMMAND },
45
+ [WORKSPACE_TOOLS.SANDBOX.GET_PROCESS_OUTPUT]: { name: MC_TOOLS.GET_PROCESS_OUTPUT },
46
+ [WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS]: { name: MC_TOOLS.KILL_PROCESS },
47
+ [WORKSPACE_TOOLS.LSP.LSP_INSPECT]: { name: MC_TOOLS.LSP_INSPECT }
42
48
  };
49
+ //#endregion
50
+ export { MC_TOOLS, TOOL_NAME_OVERRIDES };
51
+
43
52
  //# sourceMappingURL=tool-names.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tool-names.ts"],"sourcesContent":["/**\n * Mastracode tool name constants.\n *\n * These are the names exposed to the LLM via workspace tool name remapping.\n * Used throughout mastracode for permissions, TUI rendering, tool guidance,\n * subagent allowedTools, etc.\n *\n * The workspace tools get remapped from their core names (e.g. `mastra_workspace_read_file`)\n * to these names (e.g. `view`) via the `name` property in workspace tool config.\n */\n\nimport { WORKSPACE_TOOLS } from '@mastra/core/workspace';\n\nexport const MC_TOOLS = {\n // Filesystem\n VIEW: 'view',\n WRITE_FILE: 'write_file',\n STRING_REPLACE_LSP: 'string_replace_lsp',\n FIND_FILES: 'find_files',\n DELETE_FILE: 'delete_file',\n FILE_STAT: 'file_stat',\n MKDIR: 'mkdir',\n\n // Search\n SEARCH_CONTENT: 'search_content',\n\n // Code intelligence\n AST_SMART_EDIT: 'ast_smart_edit',\n\n // Sandbox\n EXECUTE_COMMAND: 'execute_command',\n GET_PROCESS_OUTPUT: 'get_process_output',\n KILL_PROCESS: 'kill_process',\n\n // Code intelligence\n LSP_INSPECT: 'lsp_inspect',\n\n // Notifications\n NOTIFICATION_INBOX: 'notification_inbox',\n} as const;\n\n/**\n * Workspace tool name remapping config.\n * Maps core workspace tool constants to mastracode's tool names.\n * Pass this (or spread it) into `Workspace({ tools: ... })`.\n */\nexport const TOOL_NAME_OVERRIDES = {\n [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: MC_TOOLS.VIEW },\n [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: { name: MC_TOOLS.WRITE_FILE },\n [WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE]: { name: MC_TOOLS.STRING_REPLACE_LSP },\n [WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES]: { name: MC_TOOLS.FIND_FILES },\n [WORKSPACE_TOOLS.FILESYSTEM.DELETE]: { name: MC_TOOLS.DELETE_FILE },\n [WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT]: { name: MC_TOOLS.FILE_STAT },\n [WORKSPACE_TOOLS.FILESYSTEM.MKDIR]: { name: MC_TOOLS.MKDIR },\n [WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: MC_TOOLS.SEARCH_CONTENT },\n [WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT]: { name: MC_TOOLS.AST_SMART_EDIT },\n [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { name: MC_TOOLS.EXECUTE_COMMAND },\n [WORKSPACE_TOOLS.SANDBOX.GET_PROCESS_OUTPUT]: { name: MC_TOOLS.GET_PROCESS_OUTPUT },\n [WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS]: { name: MC_TOOLS.KILL_PROCESS },\n [WORKSPACE_TOOLS.LSP.LSP_INSPECT]: { name: MC_TOOLS.LSP_INSPECT },\n} as const;\n"],"mappings":"AAWA,SAAS,uBAAuB;AAEzB,MAAM,WAAW;AAAA;AAAA,EAEtB,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,oBAAoB;AAAA,EACpB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,WAAW;AAAA,EACX,OAAO;AAAA;AAAA,EAGP,gBAAgB;AAAA;AAAA,EAGhB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,cAAc;AAAA;AAAA,EAGd,aAAa;AAAA;AAAA,EAGb,oBAAoB;AACtB;AAOO,MAAM,sBAAsB;AAAA,EACjC,CAAC,gBAAgB,WAAW,SAAS,GAAG,EAAE,MAAM,SAAS,KAAK;AAAA,EAC9D,CAAC,gBAAgB,WAAW,UAAU,GAAG,EAAE,MAAM,SAAS,WAAW;AAAA,EACrE,CAAC,gBAAgB,WAAW,SAAS,GAAG,EAAE,MAAM,SAAS,mBAAmB;AAAA,EAC5E,CAAC,gBAAgB,WAAW,UAAU,GAAG,EAAE,MAAM,SAAS,WAAW;AAAA,EACrE,CAAC,gBAAgB,WAAW,MAAM,GAAG,EAAE,MAAM,SAAS,YAAY;AAAA,EAClE,CAAC,gBAAgB,WAAW,SAAS,GAAG,EAAE,MAAM,SAAS,UAAU;AAAA,EACnE,CAAC,gBAAgB,WAAW,KAAK,GAAG,EAAE,MAAM,SAAS,MAAM;AAAA,EAC3D,CAAC,gBAAgB,WAAW,IAAI,GAAG,EAAE,MAAM,SAAS,eAAe;AAAA,EACnE,CAAC,gBAAgB,WAAW,QAAQ,GAAG,EAAE,MAAM,SAAS,eAAe;AAAA,EACvE,CAAC,gBAAgB,QAAQ,eAAe,GAAG,EAAE,MAAM,SAAS,gBAAgB;AAAA,EAC5E,CAAC,gBAAgB,QAAQ,kBAAkB,GAAG,EAAE,MAAM,SAAS,mBAAmB;AAAA,EAClF,CAAC,gBAAgB,QAAQ,YAAY,GAAG,EAAE,MAAM,SAAS,aAAa;AAAA,EACtE,CAAC,gBAAgB,IAAI,WAAW,GAAG,EAAE,MAAM,SAAS,YAAY;AAClE;","names":[]}
1
+ {"version":3,"file":"tool-names.js","names":[],"sources":["../src/tool-names.ts"],"sourcesContent":["/**\n * Mastracode tool name constants.\n *\n * These are the names exposed to the LLM via workspace tool name remapping.\n * Used throughout mastracode for permissions, TUI rendering, tool guidance,\n * subagent allowedTools, etc.\n *\n * The workspace tools get remapped from their core names (e.g. `mastra_workspace_read_file`)\n * to these names (e.g. `view`) via the `name` property in workspace tool config.\n */\n\nimport { WORKSPACE_TOOLS } from '@mastra/core/workspace';\n\nexport const MC_TOOLS = {\n // Filesystem\n VIEW: 'view',\n WRITE_FILE: 'write_file',\n STRING_REPLACE_LSP: 'string_replace_lsp',\n FIND_FILES: 'find_files',\n DELETE_FILE: 'delete_file',\n FILE_STAT: 'file_stat',\n MKDIR: 'mkdir',\n\n // Search\n SEARCH_CONTENT: 'search_content',\n\n // Code intelligence\n AST_SMART_EDIT: 'ast_smart_edit',\n\n // Sandbox\n EXECUTE_COMMAND: 'execute_command',\n GET_PROCESS_OUTPUT: 'get_process_output',\n KILL_PROCESS: 'kill_process',\n\n // Code intelligence\n LSP_INSPECT: 'lsp_inspect',\n\n // Notifications\n NOTIFICATION_INBOX: 'notification_inbox',\n} as const;\n\n/**\n * Workspace tool name remapping config.\n * Maps core workspace tool constants to mastracode's tool names.\n * Pass this (or spread it) into `Workspace({ tools: ... })`.\n */\nexport const TOOL_NAME_OVERRIDES = {\n [WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]: { name: MC_TOOLS.VIEW },\n [WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE]: { name: MC_TOOLS.WRITE_FILE },\n [WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE]: { name: MC_TOOLS.STRING_REPLACE_LSP },\n [WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES]: { name: MC_TOOLS.FIND_FILES },\n [WORKSPACE_TOOLS.FILESYSTEM.DELETE]: { name: MC_TOOLS.DELETE_FILE },\n [WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT]: { name: MC_TOOLS.FILE_STAT },\n [WORKSPACE_TOOLS.FILESYSTEM.MKDIR]: { name: MC_TOOLS.MKDIR },\n [WORKSPACE_TOOLS.FILESYSTEM.GREP]: { name: MC_TOOLS.SEARCH_CONTENT },\n [WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT]: { name: MC_TOOLS.AST_SMART_EDIT },\n [WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND]: { name: MC_TOOLS.EXECUTE_COMMAND },\n [WORKSPACE_TOOLS.SANDBOX.GET_PROCESS_OUTPUT]: { name: MC_TOOLS.GET_PROCESS_OUTPUT },\n [WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS]: { name: MC_TOOLS.KILL_PROCESS },\n [WORKSPACE_TOOLS.LSP.LSP_INSPECT]: { name: MC_TOOLS.LSP_INSPECT },\n} as const;\n"],"mappings":";;;;;;;;;;;;AAaA,MAAa,WAAW;CAEtB,MAAM;CACN,YAAY;CACZ,oBAAoB;CACpB,YAAY;CACZ,aAAa;CACb,WAAW;CACX,OAAO;CAGP,gBAAgB;CAGhB,gBAAgB;CAGhB,iBAAiB;CACjB,oBAAoB;CACpB,cAAc;CAGd,aAAa;CAGb,oBAAoB;AACtB;;;;;;AAOA,MAAa,sBAAsB;EAChC,gBAAgB,WAAW,YAAY,EAAE,MAAM,SAAS,KAAK;EAC7D,gBAAgB,WAAW,aAAa,EAAE,MAAM,SAAS,WAAW;EACpE,gBAAgB,WAAW,YAAY,EAAE,MAAM,SAAS,mBAAmB;EAC3E,gBAAgB,WAAW,aAAa,EAAE,MAAM,SAAS,WAAW;EACpE,gBAAgB,WAAW,SAAS,EAAE,MAAM,SAAS,YAAY;EACjE,gBAAgB,WAAW,YAAY,EAAE,MAAM,SAAS,UAAU;EAClE,gBAAgB,WAAW,QAAQ,EAAE,MAAM,SAAS,MAAM;EAC1D,gBAAgB,WAAW,OAAO,EAAE,MAAM,SAAS,eAAe;EAClE,gBAAgB,WAAW,WAAW,EAAE,MAAM,SAAS,eAAe;EACtE,gBAAgB,QAAQ,kBAAkB,EAAE,MAAM,SAAS,gBAAgB;EAC3E,gBAAgB,QAAQ,qBAAqB,EAAE,MAAM,SAAS,mBAAmB;EACjF,gBAAgB,QAAQ,eAAe,EAAE,MAAM,SAAS,aAAa;EACrE,gBAAgB,IAAI,cAAc,EAAE,MAAM,SAAS,YAAY;AAClE"}
@@ -1,9 +1,3 @@
1
- import { createWebSearchTool, createWebExtractTool, hasTavilyKey } from "./web-search.js";
1
+ import { createWebExtractTool, createWebSearchTool, hasTavilyKey } from "./web-search.js";
2
2
  import { requestSandboxAccessTool } from "./request-sandbox-access.js";
3
- export {
4
- createWebExtractTool,
5
- createWebSearchTool,
6
- hasTavilyKey,
7
- requestSandboxAccessTool
8
- };
9
- //# sourceMappingURL=index.js.map
3
+ export { createWebExtractTool, createWebSearchTool, hasTavilyKey, requestSandboxAccessTool };
@@ -1,88 +1,79 @@
1
- import * as os from "node:os";
2
- import * as path from "node:path";
1
+ import { getAllowedPathsFromContext, isPathAllowed } from "./utils.js";
2
+ import * as os$1 from "os";
3
+ import * as path$1 from "path";
3
4
  import { createTool } from "@mastra/core/tools";
4
5
  import { LocalFilesystem } from "@mastra/core/workspace";
5
6
  import { z } from "zod";
6
- import { isPathAllowed, getAllowedPathsFromContext } from "./utils.js";
7
+ //#region src/tools/request-sandbox-access.ts
8
+ /**
9
+ * request_access tool — requests permission to access a directory outside the project root.
10
+ * The user can approve or deny the request via TUI dialog.
11
+ */
7
12
  function expandTilde(p) {
8
- if (p === "~") return os.homedir();
9
- if (p.startsWith("~/") || p.startsWith("~\\")) return path.join(os.homedir(), p.slice(2));
10
- return p;
13
+ if (p === "~") return os$1.homedir();
14
+ if (p.startsWith("~/") || p.startsWith("~\\")) return path$1.join(os$1.homedir(), p.slice(2));
15
+ return p;
11
16
  }
12
- const requestSandboxAccessInputSchema = z.object({
13
- path: z.string().min(1).describe("The absolute path to the directory you need access to."),
14
- reason: z.string().min(1).describe("Brief explanation of why you need access to this directory.")
15
- });
16
17
  const requestSandboxAccessTool = createTool({
17
- id: "request_access",
18
- description: `Request permission to access a directory outside the current project. Use this when you need to read or write files in a directory that is not within the project root. The user will be prompted to approve or deny the request.`,
19
- inputSchema: requestSandboxAccessInputSchema,
20
- suspendSchema: z.object({
21
- kind: z.literal("sandbox_access_request"),
22
- path: z.string(),
23
- reason: z.string()
24
- }),
25
- resumeSchema: z.union([z.string(), z.array(z.string())]),
26
- execute: async ({ path: requestedPath, reason }, context) => {
27
- try {
28
- const agentControllerCtx = context?.requestContext?.get("controller");
29
- const expanded = expandTilde(requestedPath);
30
- const absolutePath = path.isAbsolute(expanded) ? expanded : path.resolve(process.cwd(), expanded);
31
- const projectRoot = process.cwd();
32
- const allowedPaths = getAllowedPathsFromContext(context);
33
- if (isPathAllowed(absolutePath, projectRoot, allowedPaths)) {
34
- return {
35
- content: `Access already granted: "${absolutePath}" is within the project root or allowed paths.`,
36
- isError: false
37
- };
38
- }
39
- const suspend = context?.agent?.suspend ?? context?.suspend;
40
- const resumeData = context?.agent?.resumeData ?? context?.resumeData;
41
- if (resumeData === void 0) {
42
- if (!suspend) {
43
- return {
44
- content: `Cannot request sandbox access: interactive context not available. The user should manually run /sandbox add ${absolutePath}`,
45
- isError: true
46
- };
47
- }
48
- await suspend({ kind: "sandbox_access_request", path: absolutePath, reason });
49
- return;
50
- }
51
- const answerText = Array.isArray(resumeData) ? resumeData.join(", ") : String(resumeData);
52
- const approved = answerText.toLowerCase().startsWith("y") || answerText.toLowerCase() === "approve";
53
- if (approved) {
54
- const controllerState = agentControllerCtx?.getState();
55
- const currentAllowed = controllerState?.sandboxAllowedPaths ?? [];
56
- const nextAllowed = currentAllowed.includes(absolutePath) ? currentAllowed : [...currentAllowed, absolutePath];
57
- if (!currentAllowed.includes(absolutePath)) {
58
- await agentControllerCtx?.setState({
59
- sandboxAllowedPaths: nextAllowed
60
- });
61
- }
62
- const fs = agentControllerCtx?.workspace?.filesystem ?? context?.workspace?.filesystem;
63
- if (fs instanceof LocalFilesystem) {
64
- fs.setAllowedPaths((prev) => [...prev, absolutePath]);
65
- }
66
- return {
67
- content: `Access granted: "${absolutePath}" has been added to allowed paths. You can now access files in this directory.`,
68
- isError: false
69
- };
70
- } else {
71
- return {
72
- content: `Access denied: The user declined access to "${absolutePath}".`,
73
- isError: false
74
- };
75
- }
76
- } catch (error) {
77
- const msg = error instanceof Error ? error.message : "Unknown error";
78
- return {
79
- content: `Failed to request sandbox access: ${msg}`,
80
- isError: true
81
- };
82
- }
83
- }
18
+ id: "request_access",
19
+ description: `Request permission to access a directory outside the current project. Use this when you need to read or write files in a directory that is not within the project root. The user will be prompted to approve or deny the request.`,
20
+ inputSchema: z.object({
21
+ path: z.string().min(1).describe("The absolute path to the directory you need access to."),
22
+ reason: z.string().min(1).describe("Brief explanation of why you need access to this directory.")
23
+ }),
24
+ suspendSchema: z.object({
25
+ kind: z.literal("sandbox_access_request"),
26
+ path: z.string(),
27
+ reason: z.string()
28
+ }),
29
+ resumeSchema: z.union([z.string(), z.array(z.string())]),
30
+ execute: async ({ path: requestedPath, reason }, context) => {
31
+ try {
32
+ const agentControllerCtx = context?.requestContext?.get("controller");
33
+ const expanded = expandTilde(requestedPath);
34
+ const absolutePath = path$1.isAbsolute(expanded) ? expanded : path$1.resolve(process.cwd(), expanded);
35
+ if (isPathAllowed(absolutePath, process.cwd(), getAllowedPathsFromContext(context))) return {
36
+ content: `Access already granted: "${absolutePath}" is within the project root or allowed paths.`,
37
+ isError: false
38
+ };
39
+ const suspend = context?.agent?.suspend ?? context?.suspend;
40
+ const resumeData = context?.agent?.resumeData ?? context?.resumeData;
41
+ if (resumeData === void 0) {
42
+ if (!suspend) return {
43
+ content: `Cannot request sandbox access: interactive context not available. The user should manually run /sandbox add ${absolutePath}`,
44
+ isError: true
45
+ };
46
+ await suspend({
47
+ kind: "sandbox_access_request",
48
+ path: absolutePath,
49
+ reason
50
+ });
51
+ return;
52
+ }
53
+ const answerText = Array.isArray(resumeData) ? resumeData.join(", ") : String(resumeData);
54
+ if (answerText.toLowerCase().startsWith("y") || answerText.toLowerCase() === "approve") {
55
+ const currentAllowed = (agentControllerCtx?.getState())?.sandboxAllowedPaths ?? [];
56
+ const nextAllowed = currentAllowed.includes(absolutePath) ? currentAllowed : [...currentAllowed, absolutePath];
57
+ if (!currentAllowed.includes(absolutePath)) await agentControllerCtx?.setState({ sandboxAllowedPaths: nextAllowed });
58
+ const fs = agentControllerCtx?.workspace?.filesystem ?? context?.workspace?.filesystem;
59
+ if (fs instanceof LocalFilesystem) fs.setAllowedPaths((prev) => [...prev, absolutePath]);
60
+ return {
61
+ content: `Access granted: "${absolutePath}" has been added to allowed paths. You can now access files in this directory.`,
62
+ isError: false
63
+ };
64
+ } else return {
65
+ content: `Access denied: The user declined access to "${absolutePath}".`,
66
+ isError: false
67
+ };
68
+ } catch (error) {
69
+ return {
70
+ content: `Failed to request sandbox access: ${error instanceof Error ? error.message : "Unknown error"}`,
71
+ isError: true
72
+ };
73
+ }
74
+ }
84
75
  });
85
- export {
86
- requestSandboxAccessTool
87
- };
76
+ //#endregion
77
+ export { requestSandboxAccessTool };
78
+
88
79
  //# sourceMappingURL=request-sandbox-access.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/request-sandbox-access.ts"],"sourcesContent":["/**\n * request_access tool — requests permission to access a directory outside the project root.\n * The user can approve or deny the request via TUI dialog.\n */\n\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport { createTool } from '@mastra/core/tools';\nimport { LocalFilesystem } from '@mastra/core/workspace';\nimport { z } from 'zod';\nimport type { MastraCodeState } from '../schema.js';\nimport { isPathAllowed, getAllowedPathsFromContext } from './utils.js';\n\nfunction expandTilde(p: string): string {\n if (p === '~') return os.homedir();\n if (p.startsWith('~/') || p.startsWith('~\\\\')) return path.join(os.homedir(), p.slice(2));\n return p;\n}\n\ntype RequestSandboxAccessInput = {\n path: string;\n reason: string;\n};\n\nconst requestSandboxAccessInputSchema = z.object({\n path: z.string().min(1).describe('The absolute path to the directory you need access to.'),\n reason: z.string().min(1).describe('Brief explanation of why you need access to this directory.'),\n});\n\nexport const requestSandboxAccessTool = createTool({\n id: 'request_access',\n description: `Request permission to access a directory outside the current project. Use this when you need to read or write files in a directory that is not within the project root. The user will be prompted to approve or deny the request.`,\n inputSchema: requestSandboxAccessInputSchema,\n suspendSchema: z.object({\n kind: z.literal('sandbox_access_request'),\n path: z.string(),\n reason: z.string(),\n }),\n resumeSchema: z.union([z.string(), z.array(z.string())]),\n execute: async ({ path: requestedPath, reason }: RequestSandboxAccessInput, context: any) => {\n try {\n const agentControllerCtx = context?.requestContext?.get('controller') as\n | AgentControllerRequestContext<MastraCodeState>\n | undefined;\n\n // Resolve to absolute path (expand ~ first since Node path APIs don't handle it)\n const expanded = expandTilde(requestedPath);\n const absolutePath = path.isAbsolute(expanded) ? expanded : path.resolve(process.cwd(), expanded);\n\n // Check if already allowed\n const projectRoot = process.cwd();\n const allowedPaths = getAllowedPathsFromContext(context);\n if (isPathAllowed(absolutePath, projectRoot, allowedPaths)) {\n return {\n content: `Access already granted: \"${absolutePath}\" is within the project root or allowed paths.`,\n isError: false,\n };\n }\n\n const suspend = context?.agent?.suspend ?? context?.suspend;\n const resumeData = context?.agent?.resumeData ?? context?.resumeData;\n\n // First pass: pause via the native tool-suspension primitive so the host can\n // prompt the user. The suspend payload carries the request details; the host\n // resumes with the user's answer as resume data.\n if (resumeData === undefined) {\n if (!suspend) {\n return {\n content: `Cannot request sandbox access: interactive context not available. The user should manually run /sandbox add ${absolutePath}`,\n isError: true,\n };\n }\n await suspend({ kind: 'sandbox_access_request', path: absolutePath, reason });\n return;\n }\n\n const answerText = Array.isArray(resumeData) ? resumeData.join(', ') : String(resumeData);\n const approved = answerText.toLowerCase().startsWith('y') || answerText.toLowerCase() === 'approve';\n if (approved) {\n // Persist to controller state first (and await it) so the value is\n // committed before the next tool call re-derives the workspace's\n // allowed paths from state. The workspace factory rebuilds the\n // filesystem allowlist from `sandboxAllowedPaths` on every call\n // (getDynamicWorkspace), so an unawaited setState would let that\n // rebuild clobber the in-turn widen below before the grant lands.\n const controllerState = agentControllerCtx?.getState();\n const currentAllowed = (controllerState?.sandboxAllowedPaths as string[] | undefined) ?? [];\n const nextAllowed = currentAllowed.includes(absolutePath) ? currentAllowed : [...currentAllowed, absolutePath];\n if (!currentAllowed.includes(absolutePath)) {\n await agentControllerCtx?.setState({\n sandboxAllowedPaths: nextAllowed,\n });\n }\n\n // Also update the live workspace filesystem immediately so tools in\n // the same turn (e.g. `view`) can access the path without waiting for\n // a fresh workspace build. The resolved workspace is carried on the\n // controller request context — the tool-execution context does not expose\n // it — so read the filesystem from there.\n const fs = agentControllerCtx?.workspace?.filesystem ?? context?.workspace?.filesystem;\n if (fs instanceof LocalFilesystem) {\n fs.setAllowedPaths((prev: readonly string[]) => [...prev, absolutePath]);\n }\n\n return {\n content: `Access granted: \"${absolutePath}\" has been added to allowed paths. You can now access files in this directory.`,\n isError: false,\n };\n } else {\n return {\n content: `Access denied: The user declined access to \"${absolutePath}\".`,\n isError: false,\n };\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n content: `Failed to request sandbox access: ${msg}`,\n isError: true,\n };\n }\n },\n} as any);\n"],"mappings":"AAKA,YAAY,QAAQ;AACpB,YAAY,UAAU;AAEtB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,SAAS;AAElB,SAAS,eAAe,kCAAkC;AAE1D,SAAS,YAAY,GAAmB;AACtC,MAAI,MAAM,IAAK,QAAO,GAAG,QAAQ;AACjC,MAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,KAAK,EAAG,QAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,EAAE,MAAM,CAAC,CAAC;AACxF,SAAO;AACT;AAOA,MAAM,kCAAkC,EAAE,OAAO;AAAA,EAC/C,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wDAAwD;AAAA,EACzF,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,6DAA6D;AAClG,CAAC;AAEM,MAAM,2BAA2B,WAAW;AAAA,EACjD,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe,EAAE,OAAO;AAAA,IACtB,MAAM,EAAE,QAAQ,wBAAwB;AAAA,IACxC,MAAM,EAAE,OAAO;AAAA,IACf,QAAQ,EAAE,OAAO;AAAA,EACnB,CAAC;AAAA,EACD,cAAc,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EACvD,SAAS,OAAO,EAAE,MAAM,eAAe,OAAO,GAA8B,YAAiB;AAC3F,QAAI;AACF,YAAM,qBAAqB,SAAS,gBAAgB,IAAI,YAAY;AAKpE,YAAM,WAAW,YAAY,aAAa;AAC1C,YAAM,eAAe,KAAK,WAAW,QAAQ,IAAI,WAAW,KAAK,QAAQ,QAAQ,IAAI,GAAG,QAAQ;AAGhG,YAAM,cAAc,QAAQ,IAAI;AAChC,YAAM,eAAe,2BAA2B,OAAO;AACvD,UAAI,cAAc,cAAc,aAAa,YAAY,GAAG;AAC1D,eAAO;AAAA,UACL,SAAS,4BAA4B,YAAY;AAAA,UACjD,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,UAAU,SAAS,OAAO,WAAW,SAAS;AACpD,YAAM,aAAa,SAAS,OAAO,cAAc,SAAS;AAK1D,UAAI,eAAe,QAAW;AAC5B,YAAI,CAAC,SAAS;AACZ,iBAAO;AAAA,YACL,SAAS,+GAA+G,YAAY;AAAA,YACpI,SAAS;AAAA,UACX;AAAA,QACF;AACA,cAAM,QAAQ,EAAE,MAAM,0BAA0B,MAAM,cAAc,OAAO,CAAC;AAC5E;AAAA,MACF;AAEA,YAAM,aAAa,MAAM,QAAQ,UAAU,IAAI,WAAW,KAAK,IAAI,IAAI,OAAO,UAAU;AACxF,YAAM,WAAW,WAAW,YAAY,EAAE,WAAW,GAAG,KAAK,WAAW,YAAY,MAAM;AAC1F,UAAI,UAAU;AAOZ,cAAM,kBAAkB,oBAAoB,SAAS;AACrD,cAAM,iBAAkB,iBAAiB,uBAAgD,CAAC;AAC1F,cAAM,cAAc,eAAe,SAAS,YAAY,IAAI,iBAAiB,CAAC,GAAG,gBAAgB,YAAY;AAC7G,YAAI,CAAC,eAAe,SAAS,YAAY,GAAG;AAC1C,gBAAM,oBAAoB,SAAS;AAAA,YACjC,qBAAqB;AAAA,UACvB,CAAC;AAAA,QACH;AAOA,cAAM,KAAK,oBAAoB,WAAW,cAAc,SAAS,WAAW;AAC5E,YAAI,cAAc,iBAAiB;AACjC,aAAG,gBAAgB,CAAC,SAA4B,CAAC,GAAG,MAAM,YAAY,CAAC;AAAA,QACzE;AAEA,eAAO;AAAA,UACL,SAAS,oBAAoB,YAAY;AAAA,UACzC,SAAS;AAAA,QACX;AAAA,MACF,OAAO;AACL,eAAO;AAAA,UACL,SAAS,+CAA+C,YAAY;AAAA,UACpE,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU;AACrD,aAAO;AAAA,QACL,SAAS,qCAAqC,GAAG;AAAA,QACjD,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF,CAAQ;","names":[]}
1
+ {"version":3,"file":"request-sandbox-access.js","names":["os","path"],"sources":["../../src/tools/request-sandbox-access.ts"],"sourcesContent":["/**\n * request_access tool — requests permission to access a directory outside the project root.\n * The user can approve or deny the request via TUI dialog.\n */\n\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport { createTool } from '@mastra/core/tools';\nimport { LocalFilesystem } from '@mastra/core/workspace';\nimport { z } from 'zod';\nimport type { MastraCodeState } from '../schema.js';\nimport { isPathAllowed, getAllowedPathsFromContext } from './utils.js';\n\nfunction expandTilde(p: string): string {\n if (p === '~') return os.homedir();\n if (p.startsWith('~/') || p.startsWith('~\\\\')) return path.join(os.homedir(), p.slice(2));\n return p;\n}\n\ntype RequestSandboxAccessInput = {\n path: string;\n reason: string;\n};\n\nconst requestSandboxAccessInputSchema = z.object({\n path: z.string().min(1).describe('The absolute path to the directory you need access to.'),\n reason: z.string().min(1).describe('Brief explanation of why you need access to this directory.'),\n});\n\nexport const requestSandboxAccessTool = createTool({\n id: 'request_access',\n description: `Request permission to access a directory outside the current project. Use this when you need to read or write files in a directory that is not within the project root. The user will be prompted to approve or deny the request.`,\n inputSchema: requestSandboxAccessInputSchema,\n suspendSchema: z.object({\n kind: z.literal('sandbox_access_request'),\n path: z.string(),\n reason: z.string(),\n }),\n resumeSchema: z.union([z.string(), z.array(z.string())]),\n execute: async ({ path: requestedPath, reason }: RequestSandboxAccessInput, context: any) => {\n try {\n const agentControllerCtx = context?.requestContext?.get('controller') as\n | AgentControllerRequestContext<MastraCodeState>\n | undefined;\n\n // Resolve to absolute path (expand ~ first since Node path APIs don't handle it)\n const expanded = expandTilde(requestedPath);\n const absolutePath = path.isAbsolute(expanded) ? expanded : path.resolve(process.cwd(), expanded);\n\n // Check if already allowed\n const projectRoot = process.cwd();\n const allowedPaths = getAllowedPathsFromContext(context);\n if (isPathAllowed(absolutePath, projectRoot, allowedPaths)) {\n return {\n content: `Access already granted: \"${absolutePath}\" is within the project root or allowed paths.`,\n isError: false,\n };\n }\n\n const suspend = context?.agent?.suspend ?? context?.suspend;\n const resumeData = context?.agent?.resumeData ?? context?.resumeData;\n\n // First pass: pause via the native tool-suspension primitive so the host can\n // prompt the user. The suspend payload carries the request details; the host\n // resumes with the user's answer as resume data.\n if (resumeData === undefined) {\n if (!suspend) {\n return {\n content: `Cannot request sandbox access: interactive context not available. The user should manually run /sandbox add ${absolutePath}`,\n isError: true,\n };\n }\n await suspend({ kind: 'sandbox_access_request', path: absolutePath, reason });\n return;\n }\n\n const answerText = Array.isArray(resumeData) ? resumeData.join(', ') : String(resumeData);\n const approved = answerText.toLowerCase().startsWith('y') || answerText.toLowerCase() === 'approve';\n if (approved) {\n // Persist to controller state first (and await it) so the value is\n // committed before the next tool call re-derives the workspace's\n // allowed paths from state. The workspace factory rebuilds the\n // filesystem allowlist from `sandboxAllowedPaths` on every call\n // (getDynamicWorkspace), so an unawaited setState would let that\n // rebuild clobber the in-turn widen below before the grant lands.\n const controllerState = agentControllerCtx?.getState();\n const currentAllowed = (controllerState?.sandboxAllowedPaths as string[] | undefined) ?? [];\n const nextAllowed = currentAllowed.includes(absolutePath) ? currentAllowed : [...currentAllowed, absolutePath];\n if (!currentAllowed.includes(absolutePath)) {\n await agentControllerCtx?.setState({\n sandboxAllowedPaths: nextAllowed,\n });\n }\n\n // Also update the live workspace filesystem immediately so tools in\n // the same turn (e.g. `view`) can access the path without waiting for\n // a fresh workspace build. The resolved workspace is carried on the\n // controller request context — the tool-execution context does not expose\n // it — so read the filesystem from there.\n const fs = agentControllerCtx?.workspace?.filesystem ?? context?.workspace?.filesystem;\n if (fs instanceof LocalFilesystem) {\n fs.setAllowedPaths((prev: readonly string[]) => [...prev, absolutePath]);\n }\n\n return {\n content: `Access granted: \"${absolutePath}\" has been added to allowed paths. You can now access files in this directory.`,\n isError: false,\n };\n } else {\n return {\n content: `Access denied: The user declined access to \"${absolutePath}\".`,\n isError: false,\n };\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n content: `Failed to request sandbox access: ${msg}`,\n isError: true,\n };\n }\n },\n} as any);\n"],"mappings":";;;;;;;;;;;AAcA,SAAS,YAAY,GAAmB;CACtC,IAAI,MAAM,KAAK,OAAOA,KAAG,QAAQ;CACjC,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,KAAK,GAAG,OAAOC,OAAK,KAAKD,KAAG,QAAQ,GAAG,EAAE,MAAM,CAAC,CAAC;CACxF,OAAO;AACT;AAYA,MAAa,2BAA2B,WAAW;CACjD,IAAI;CACJ,aAAa;CACb,aARsC,EAAE,OAAO;EAC/C,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,wDAAwD;EACzF,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,6DAA6D;CAClG,CAKe;CACb,eAAe,EAAE,OAAO;EACtB,MAAM,EAAE,QAAQ,wBAAwB;EACxC,MAAM,EAAE,OAAO;EACf,QAAQ,EAAE,OAAO;CACnB,CAAC;CACD,cAAc,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD,SAAS,OAAO,EAAE,MAAM,eAAe,UAAqC,YAAiB;EAC3F,IAAI;GACF,MAAM,qBAAqB,SAAS,gBAAgB,IAAI,YAAY;GAKpE,MAAM,WAAW,YAAY,aAAa;GAC1C,MAAM,eAAeC,OAAK,WAAW,QAAQ,IAAI,WAAWA,OAAK,QAAQ,QAAQ,IAAI,GAAG,QAAQ;GAKhG,IAAI,cAAc,cAFE,QAAQ,IAEc,GADrB,2BAA2B,OACQ,CAAC,GACvD,OAAO;IACL,SAAS,4BAA4B,aAAa;IAClD,SAAS;GACX;GAGF,MAAM,UAAU,SAAS,OAAO,WAAW,SAAS;GACpD,MAAM,aAAa,SAAS,OAAO,cAAc,SAAS;GAK1D,IAAI,eAAe,KAAA,GAAW;IAC5B,IAAI,CAAC,SACH,OAAO;KACL,SAAS,+GAA+G;KACxH,SAAS;IACX;IAEF,MAAM,QAAQ;KAAE,MAAM;KAA0B,MAAM;KAAc;IAAO,CAAC;IAC5E;GACF;GAEA,MAAM,aAAa,MAAM,QAAQ,UAAU,IAAI,WAAW,KAAK,IAAI,IAAI,OAAO,UAAU;GAExF,IADiB,WAAW,YAAY,CAAC,CAAC,WAAW,GAAG,KAAK,WAAW,YAAY,MAAM,WAC5E;IAQZ,MAAM,kBADkB,oBAAoB,SAAS,EAAA,EACZ,uBAAgD,CAAC;IAC1F,MAAM,cAAc,eAAe,SAAS,YAAY,IAAI,iBAAiB,CAAC,GAAG,gBAAgB,YAAY;IAC7G,IAAI,CAAC,eAAe,SAAS,YAAY,GACvC,MAAM,oBAAoB,SAAS,EACjC,qBAAqB,YACvB,CAAC;IAQH,MAAM,KAAK,oBAAoB,WAAW,cAAc,SAAS,WAAW;IAC5E,IAAI,cAAc,iBAChB,GAAG,iBAAiB,SAA4B,CAAC,GAAG,MAAM,YAAY,CAAC;IAGzE,OAAO;KACL,SAAS,oBAAoB,aAAa;KAC1C,SAAS;IACX;GACF,OACE,OAAO;IACL,SAAS,+CAA+C,aAAa;IACrE,SAAS;GACX;EAEJ,SAAS,OAAO;GAEd,OAAO;IACL,SAAS,qCAFC,iBAAiB,QAAQ,MAAM,UAAU;IAGnD,SAAS;GACX;EACF;CACF;AACF,CAAQ"}
@@ -1,22 +1,32 @@
1
- import * as path from "node:path";
1
+ import "../constants.js";
2
2
  import { buildSkillPaths } from "../agents/workspace.js";
3
- import { DEFAULT_CONFIG_DIR } from "../constants.js";
3
+ import * as path$1 from "path";
4
+ //#region src/tools/utils.ts
5
+ /**
6
+ * Check whether `targetPath` falls inside `projectRoot` or any of the
7
+ * additional `allowedPaths`. All arguments are expected to be absolute.
8
+ *
9
+ * Returns `true` when access should be **allowed**.
10
+ */
4
11
  function isPathAllowed(targetPath, projectRoot, allowedPaths = []) {
5
- const resolved = path.resolve(targetPath);
6
- const roots = [projectRoot, ...allowedPaths].map((p) => path.resolve(p));
7
- return roots.some((root) => resolved === root || resolved.startsWith(root + path.sep));
12
+ const resolved = path$1.resolve(targetPath);
13
+ return [projectRoot, ...allowedPaths].map((p) => path$1.resolve(p)).some((root) => resolved === root || resolved.startsWith(root + path$1.sep));
8
14
  }
15
+ /**
16
+ * Read allowed paths from the Mastra controller runtime context.
17
+ * Combines skill paths (computed dynamically from projectPath and configDir)
18
+ * with user-approved sandbox paths from controller state so that both parent
19
+ * and subagent tools have the same access.
20
+ * Returns default skill paths when the context is unavailable (e.g. in tests).
21
+ */
9
22
  function getAllowedPathsFromContext(toolContext) {
10
- const agentControllerCtx = toolContext?.requestContext?.get("controller");
11
- const state = agentControllerCtx?.getState?.() ?? agentControllerCtx?.session?.state?.get?.();
12
- const projectPath = state?.projectPath ? path.resolve(state.projectPath) : process.cwd();
13
- const configDir = state?.configDir ?? DEFAULT_CONFIG_DIR;
14
- const skillPaths = buildSkillPaths(projectPath, configDir);
15
- const sandboxPaths = state?.sandboxAllowedPaths ?? [];
16
- return [...skillPaths, ...sandboxPaths];
23
+ const agentControllerCtx = toolContext?.requestContext?.get("controller");
24
+ const state = agentControllerCtx?.getState?.() ?? agentControllerCtx?.session?.state?.get?.();
25
+ const skillPaths = buildSkillPaths(state?.projectPath ? path$1.resolve(state.projectPath) : process.cwd(), state?.configDir ?? ".mastracode");
26
+ const sandboxPaths = state?.sandboxAllowedPaths ?? [];
27
+ return [...skillPaths, ...sandboxPaths];
17
28
  }
18
- export {
19
- getAllowedPathsFromContext,
20
- isPathAllowed
21
- };
29
+ //#endregion
30
+ export { getAllowedPathsFromContext, isPathAllowed };
31
+
22
32
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/utils.ts"],"sourcesContent":["import * as path from 'node:path';\nimport { buildSkillPaths } from '../agents/workspace.js';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\n\n/**\n * Check whether `targetPath` falls inside `projectRoot` or any of the\n * additional `allowedPaths`. All arguments are expected to be absolute.\n *\n * Returns `true` when access should be **allowed**.\n */\nexport function isPathAllowed(targetPath: string, projectRoot: string, allowedPaths: string[] = []): boolean {\n const resolved = path.resolve(targetPath);\n const roots = [projectRoot, ...allowedPaths].map(p => path.resolve(p));\n\n return roots.some(root => resolved === root || resolved.startsWith(root + path.sep));\n}\n\n/**\n * Read allowed paths from the Mastra controller runtime context.\n * Combines skill paths (computed dynamically from projectPath and configDir)\n * with user-approved sandbox paths from controller state so that both parent\n * and subagent tools have the same access.\n * Returns default skill paths when the context is unavailable (e.g. in tests).\n */\nexport function getAllowedPathsFromContext(\n toolContext: { requestContext?: { get: (key: string) => unknown } } | undefined,\n): string[] {\n const agentControllerCtx = toolContext?.requestContext?.get('controller') as\n | {\n getState?: () => { sandboxAllowedPaths?: string[]; projectPath?: string; configDir?: string };\n session?: {\n state?: { get?: () => { sandboxAllowedPaths?: string[]; projectPath?: string; configDir?: string } };\n };\n }\n | undefined;\n const state = agentControllerCtx?.getState?.() ?? agentControllerCtx?.session?.state?.get?.();\n const projectPath = state?.projectPath ? path.resolve(state.projectPath) : process.cwd();\n const configDir = state?.configDir ?? DEFAULT_CONFIG_DIR;\n const skillPaths = buildSkillPaths(projectPath, configDir);\n const sandboxPaths = state?.sandboxAllowedPaths ?? [];\n\n return [...skillPaths, ...sandboxPaths];\n}\n"],"mappings":"AAAA,YAAY,UAAU;AACtB,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AAQ5B,SAAS,cAAc,YAAoB,aAAqB,eAAyB,CAAC,GAAY;AAC3G,QAAM,WAAW,KAAK,QAAQ,UAAU;AACxC,QAAM,QAAQ,CAAC,aAAa,GAAG,YAAY,EAAE,IAAI,OAAK,KAAK,QAAQ,CAAC,CAAC;AAErE,SAAO,MAAM,KAAK,UAAQ,aAAa,QAAQ,SAAS,WAAW,OAAO,KAAK,GAAG,CAAC;AACrF;AASO,SAAS,2BACd,aACU;AACV,QAAM,qBAAqB,aAAa,gBAAgB,IAAI,YAAY;AAQxE,QAAM,QAAQ,oBAAoB,WAAW,KAAK,oBAAoB,SAAS,OAAO,MAAM;AAC5F,QAAM,cAAc,OAAO,cAAc,KAAK,QAAQ,MAAM,WAAW,IAAI,QAAQ,IAAI;AACvF,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,aAAa,gBAAgB,aAAa,SAAS;AACzD,QAAM,eAAe,OAAO,uBAAuB,CAAC;AAEpD,SAAO,CAAC,GAAG,YAAY,GAAG,YAAY;AACxC;","names":[]}
1
+ {"version":3,"file":"utils.js","names":["path"],"sources":["../../src/tools/utils.ts"],"sourcesContent":["import * as path from 'node:path';\nimport { buildSkillPaths } from '../agents/workspace.js';\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\n\n/**\n * Check whether `targetPath` falls inside `projectRoot` or any of the\n * additional `allowedPaths`. All arguments are expected to be absolute.\n *\n * Returns `true` when access should be **allowed**.\n */\nexport function isPathAllowed(targetPath: string, projectRoot: string, allowedPaths: string[] = []): boolean {\n const resolved = path.resolve(targetPath);\n const roots = [projectRoot, ...allowedPaths].map(p => path.resolve(p));\n\n return roots.some(root => resolved === root || resolved.startsWith(root + path.sep));\n}\n\n/**\n * Read allowed paths from the Mastra controller runtime context.\n * Combines skill paths (computed dynamically from projectPath and configDir)\n * with user-approved sandbox paths from controller state so that both parent\n * and subagent tools have the same access.\n * Returns default skill paths when the context is unavailable (e.g. in tests).\n */\nexport function getAllowedPathsFromContext(\n toolContext: { requestContext?: { get: (key: string) => unknown } } | undefined,\n): string[] {\n const agentControllerCtx = toolContext?.requestContext?.get('controller') as\n | {\n getState?: () => { sandboxAllowedPaths?: string[]; projectPath?: string; configDir?: string };\n session?: {\n state?: { get?: () => { sandboxAllowedPaths?: string[]; projectPath?: string; configDir?: string } };\n };\n }\n | undefined;\n const state = agentControllerCtx?.getState?.() ?? agentControllerCtx?.session?.state?.get?.();\n const projectPath = state?.projectPath ? path.resolve(state.projectPath) : process.cwd();\n const configDir = state?.configDir ?? DEFAULT_CONFIG_DIR;\n const skillPaths = buildSkillPaths(projectPath, configDir);\n const sandboxPaths = state?.sandboxAllowedPaths ?? [];\n\n return [...skillPaths, ...sandboxPaths];\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,cAAc,YAAoB,aAAqB,eAAyB,CAAC,GAAY;CAC3G,MAAM,WAAWA,OAAK,QAAQ,UAAU;CAGxC,OAFc,CAAC,aAAa,GAAG,YAAY,CAAC,CAAC,KAAI,MAAKA,OAAK,QAAQ,CAAC,CAEzD,CAAC,CAAC,MAAK,SAAQ,aAAa,QAAQ,SAAS,WAAW,OAAOA,OAAK,GAAG,CAAC;AACrF;;;;;;;;AASA,SAAgB,2BACd,aACU;CACV,MAAM,qBAAqB,aAAa,gBAAgB,IAAI,YAAY;CAQxE,MAAM,QAAQ,oBAAoB,WAAW,KAAK,oBAAoB,SAAS,OAAO,MAAM;CAG5F,MAAM,aAAa,gBAFC,OAAO,cAAcA,OAAK,QAAQ,MAAM,WAAW,IAAI,QAAQ,IAAI,GACrE,OAAO,aAAA,aACgC;CACzD,MAAM,eAAe,OAAO,uBAAuB,CAAC;CAEpD,OAAO,CAAC,GAAG,YAAY,GAAG,YAAY;AACxC"}
@@ -1,65 +1,61 @@
1
- import { createTool } from "@mastra/core/tools";
2
- import { createTavilySearchTool, createTavilyExtractTool } from "@mastra/tavily";
3
1
  import { truncateStringForTokenEstimate } from "../utils/token-estimator.js";
2
+ import { createTool } from "@mastra/core/tools";
3
+ import { createTavilyExtractTool, createTavilySearchTool } from "@mastra/tavily";
4
+ //#region src/tools/web-search.ts
4
5
  const MAX_WEB_SEARCH_TOKENS = 2e3;
5
6
  const MAX_WEB_EXTRACT_TOKENS = 2e3;
6
- const MIN_RELEVANCE_SCORE = 0.25;
7
+ const MIN_RELEVANCE_SCORE = .25;
8
+ /**
9
+ * Check whether a Tavily API key is available in the environment.
10
+ * Used by main.ts to decide whether to include Tavily tools or fall back
11
+ * to Anthropic's native web search.
12
+ */
7
13
  function hasTavilyKey() {
8
- return !!process.env.TAVILY_API_KEY;
14
+ return !!process.env.TAVILY_API_KEY;
9
15
  }
16
+ /**
17
+ * Wraps the @mastra/tavily search tool with mastracode-specific behavior:
18
+ * relevance filtering, markdown string formatting, and token truncation.
19
+ * The underlying Tavily tool handles client init, input validation, and the API call.
20
+ */
10
21
  function createWebSearchTool() {
11
- const tavilySearchTool = createTavilySearchTool();
12
- return createTool({
13
- id: "web-search",
14
- description: tavilySearchTool.description,
15
- inputSchema: tavilySearchTool.inputSchema,
16
- execute: async (input, context) => {
17
- const output = await tavilySearchTool.execute(input, context);
18
- const parts = [];
19
- if (output.answer) {
20
- parts.push(`Answer: ${output.answer}`);
21
- }
22
- const filtered = output.results.filter((r) => (r.score ?? 1) >= MIN_RELEVANCE_SCORE);
23
- for (const r of filtered) {
24
- parts.push(`## ${r.title}
25
- ${r.url}
26
- ${r.content}`);
27
- }
28
- const images = (output.images || []).map((img) => img.url).filter(Boolean);
29
- if (images.length > 0) {
30
- parts.push(`Images:
31
- ${images.join("\n")}`);
32
- }
33
- const text = parts.join("\n\n");
34
- return truncateStringForTokenEstimate(text, MAX_WEB_SEARCH_TOKENS);
35
- }
36
- });
22
+ const tavilySearchTool = createTavilySearchTool();
23
+ return createTool({
24
+ id: "web-search",
25
+ description: tavilySearchTool.description,
26
+ inputSchema: tavilySearchTool.inputSchema,
27
+ execute: async (input, context) => {
28
+ const output = await tavilySearchTool.execute(input, context);
29
+ const parts = [];
30
+ if (output.answer) parts.push(`Answer: ${output.answer}`);
31
+ const filtered = output.results.filter((r) => (r.score ?? 1) >= MIN_RELEVANCE_SCORE);
32
+ for (const r of filtered) parts.push(`## ${r.title}\n${r.url}\n${r.content}`);
33
+ const images = (output.images || []).map((img) => img.url).filter(Boolean);
34
+ if (images.length > 0) parts.push(`Images:\n${images.join("\n")}`);
35
+ return truncateStringForTokenEstimate(parts.join("\n\n"), MAX_WEB_SEARCH_TOKENS);
36
+ }
37
+ });
37
38
  }
39
+ /**
40
+ * Wraps the @mastra/tavily extract tool with mastracode-specific behavior:
41
+ * markdown string formatting and token truncation.
42
+ */
38
43
  function createWebExtractTool() {
39
- const tavilyExtractTool = createTavilyExtractTool();
40
- return createTool({
41
- id: "web-extract",
42
- description: tavilyExtractTool.description,
43
- inputSchema: tavilyExtractTool.inputSchema,
44
- execute: async (input, context) => {
45
- const output = await tavilyExtractTool.execute(input, context);
46
- const parts = [];
47
- for (const r of output.results) {
48
- parts.push(`## ${r.url}
49
- ${r.rawContent}`);
50
- }
51
- for (const r of output.failedResults) {
52
- parts.push(`## ${r.url}
53
- Error: ${r.error}`);
54
- }
55
- const text = parts.join("\n\n");
56
- return truncateStringForTokenEstimate(text, MAX_WEB_EXTRACT_TOKENS);
57
- }
58
- });
44
+ const tavilyExtractTool = createTavilyExtractTool();
45
+ return createTool({
46
+ id: "web-extract",
47
+ description: tavilyExtractTool.description,
48
+ inputSchema: tavilyExtractTool.inputSchema,
49
+ execute: async (input, context) => {
50
+ const output = await tavilyExtractTool.execute(input, context);
51
+ const parts = [];
52
+ for (const r of output.results) parts.push(`## ${r.url}\n${r.rawContent}`);
53
+ for (const r of output.failedResults) parts.push(`## ${r.url}\nError: ${r.error}`);
54
+ return truncateStringForTokenEstimate(parts.join("\n\n"), MAX_WEB_EXTRACT_TOKENS);
55
+ }
56
+ });
59
57
  }
60
- export {
61
- createWebExtractTool,
62
- createWebSearchTool,
63
- hasTavilyKey
64
- };
58
+ //#endregion
59
+ export { createWebExtractTool, createWebSearchTool, hasTavilyKey };
60
+
65
61
  //# sourceMappingURL=web-search.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/web-search.ts"],"sourcesContent":["import { createTool } from '@mastra/core/tools';\nimport { createTavilySearchTool, createTavilyExtractTool } from '@mastra/tavily';\n\nimport { truncateStringForTokenEstimate } from '../utils/token-estimator.js';\n\nconst MAX_WEB_SEARCH_TOKENS = 2_000;\nconst MAX_WEB_EXTRACT_TOKENS = 2_000;\n\nconst MIN_RELEVANCE_SCORE = 0.25;\n\n/**\n * Check whether a Tavily API key is available in the environment.\n * Used by main.ts to decide whether to include Tavily tools or fall back\n * to Anthropic's native web search.\n */\nexport function hasTavilyKey(): boolean {\n return !!process.env.TAVILY_API_KEY;\n}\n\n/**\n * Wraps the @mastra/tavily search tool with mastracode-specific behavior:\n * relevance filtering, markdown string formatting, and token truncation.\n * The underlying Tavily tool handles client init, input validation, and the API call.\n */\nexport function createWebSearchTool() {\n const tavilySearchTool = createTavilySearchTool();\n\n return createTool({\n id: 'web-search',\n description: tavilySearchTool.description!,\n inputSchema: tavilySearchTool.inputSchema!,\n execute: async (input, context) => {\n const output: any = await tavilySearchTool.execute!(input as any, context as any);\n\n const parts: string[] = [];\n\n if (output.answer) {\n parts.push(`Answer: ${output.answer}`);\n }\n\n const filtered = output.results.filter((r: any) => (r.score ?? 1) >= MIN_RELEVANCE_SCORE);\n for (const r of filtered) {\n parts.push(`## ${r.title}\\n${r.url}\\n${r.content}`);\n }\n\n const images = (output.images || []).map((img: any) => img.url).filter(Boolean);\n if (images.length > 0) {\n parts.push(`Images:\\n${images.join('\\n')}`);\n }\n\n const text = parts.join('\\n\\n');\n return truncateStringForTokenEstimate(text, MAX_WEB_SEARCH_TOKENS);\n },\n });\n}\n\n/**\n * Wraps the @mastra/tavily extract tool with mastracode-specific behavior:\n * markdown string formatting and token truncation.\n */\nexport function createWebExtractTool() {\n const tavilyExtractTool = createTavilyExtractTool();\n\n return createTool({\n id: 'web-extract',\n description: tavilyExtractTool.description!,\n inputSchema: tavilyExtractTool.inputSchema!,\n execute: async (input, context) => {\n const output: any = await tavilyExtractTool.execute!(input as any, context as any);\n\n const parts: string[] = [];\n\n for (const r of output.results) {\n parts.push(`## ${r.url}\\n${r.rawContent}`);\n }\n\n for (const r of output.failedResults) {\n parts.push(`## ${r.url}\\nError: ${r.error}`);\n }\n\n const text = parts.join('\\n\\n');\n return truncateStringForTokenEstimate(text, MAX_WEB_EXTRACT_TOKENS);\n },\n });\n}\n"],"mappings":"AAAA,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB,+BAA+B;AAEhE,SAAS,sCAAsC;AAE/C,MAAM,wBAAwB;AAC9B,MAAM,yBAAyB;AAE/B,MAAM,sBAAsB;AAOrB,SAAS,eAAwB;AACtC,SAAO,CAAC,CAAC,QAAQ,IAAI;AACvB;AAOO,SAAS,sBAAsB;AACpC,QAAM,mBAAmB,uBAAuB;AAEhD,SAAO,WAAW;AAAA,IAChB,IAAI;AAAA,IACJ,aAAa,iBAAiB;AAAA,IAC9B,aAAa,iBAAiB;AAAA,IAC9B,SAAS,OAAO,OAAO,YAAY;AACjC,YAAM,SAAc,MAAM,iBAAiB,QAAS,OAAc,OAAc;AAEhF,YAAM,QAAkB,CAAC;AAEzB,UAAI,OAAO,QAAQ;AACjB,cAAM,KAAK,WAAW,OAAO,MAAM,EAAE;AAAA,MACvC;AAEA,YAAM,WAAW,OAAO,QAAQ,OAAO,CAAC,OAAY,EAAE,SAAS,MAAM,mBAAmB;AACxF,iBAAW,KAAK,UAAU;AACxB,cAAM,KAAK,MAAM,EAAE,KAAK;AAAA,EAAK,EAAE,GAAG;AAAA,EAAK,EAAE,OAAO,EAAE;AAAA,MACpD;AAEA,YAAM,UAAU,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,QAAa,IAAI,GAAG,EAAE,OAAO,OAAO;AAC9E,UAAI,OAAO,SAAS,GAAG;AACrB,cAAM,KAAK;AAAA,EAAY,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,MAC5C;AAEA,YAAM,OAAO,MAAM,KAAK,MAAM;AAC9B,aAAO,+BAA+B,MAAM,qBAAqB;AAAA,IACnE;AAAA,EACF,CAAC;AACH;AAMO,SAAS,uBAAuB;AACrC,QAAM,oBAAoB,wBAAwB;AAElD,SAAO,WAAW;AAAA,IAChB,IAAI;AAAA,IACJ,aAAa,kBAAkB;AAAA,IAC/B,aAAa,kBAAkB;AAAA,IAC/B,SAAS,OAAO,OAAO,YAAY;AACjC,YAAM,SAAc,MAAM,kBAAkB,QAAS,OAAc,OAAc;AAEjF,YAAM,QAAkB,CAAC;AAEzB,iBAAW,KAAK,OAAO,SAAS;AAC9B,cAAM,KAAK,MAAM,EAAE,GAAG;AAAA,EAAK,EAAE,UAAU,EAAE;AAAA,MAC3C;AAEA,iBAAW,KAAK,OAAO,eAAe;AACpC,cAAM,KAAK,MAAM,EAAE,GAAG;AAAA,SAAY,EAAE,KAAK,EAAE;AAAA,MAC7C;AAEA,YAAM,OAAO,MAAM,KAAK,MAAM;AAC9B,aAAO,+BAA+B,MAAM,sBAAsB;AAAA,IACpE;AAAA,EACF,CAAC;AACH;","names":[]}
1
+ {"version":3,"file":"web-search.js","names":[],"sources":["../../src/tools/web-search.ts"],"sourcesContent":["import { createTool } from '@mastra/core/tools';\nimport { createTavilySearchTool, createTavilyExtractTool } from '@mastra/tavily';\n\nimport { truncateStringForTokenEstimate } from '../utils/token-estimator.js';\n\nconst MAX_WEB_SEARCH_TOKENS = 2_000;\nconst MAX_WEB_EXTRACT_TOKENS = 2_000;\n\nconst MIN_RELEVANCE_SCORE = 0.25;\n\n/**\n * Check whether a Tavily API key is available in the environment.\n * Used by main.ts to decide whether to include Tavily tools or fall back\n * to Anthropic's native web search.\n */\nexport function hasTavilyKey(): boolean {\n return !!process.env.TAVILY_API_KEY;\n}\n\n/**\n * Wraps the @mastra/tavily search tool with mastracode-specific behavior:\n * relevance filtering, markdown string formatting, and token truncation.\n * The underlying Tavily tool handles client init, input validation, and the API call.\n */\nexport function createWebSearchTool() {\n const tavilySearchTool = createTavilySearchTool();\n\n return createTool({\n id: 'web-search',\n description: tavilySearchTool.description!,\n inputSchema: tavilySearchTool.inputSchema!,\n execute: async (input, context) => {\n const output: any = await tavilySearchTool.execute!(input as any, context as any);\n\n const parts: string[] = [];\n\n if (output.answer) {\n parts.push(`Answer: ${output.answer}`);\n }\n\n const filtered = output.results.filter((r: any) => (r.score ?? 1) >= MIN_RELEVANCE_SCORE);\n for (const r of filtered) {\n parts.push(`## ${r.title}\\n${r.url}\\n${r.content}`);\n }\n\n const images = (output.images || []).map((img: any) => img.url).filter(Boolean);\n if (images.length > 0) {\n parts.push(`Images:\\n${images.join('\\n')}`);\n }\n\n const text = parts.join('\\n\\n');\n return truncateStringForTokenEstimate(text, MAX_WEB_SEARCH_TOKENS);\n },\n });\n}\n\n/**\n * Wraps the @mastra/tavily extract tool with mastracode-specific behavior:\n * markdown string formatting and token truncation.\n */\nexport function createWebExtractTool() {\n const tavilyExtractTool = createTavilyExtractTool();\n\n return createTool({\n id: 'web-extract',\n description: tavilyExtractTool.description!,\n inputSchema: tavilyExtractTool.inputSchema!,\n execute: async (input, context) => {\n const output: any = await tavilyExtractTool.execute!(input as any, context as any);\n\n const parts: string[] = [];\n\n for (const r of output.results) {\n parts.push(`## ${r.url}\\n${r.rawContent}`);\n }\n\n for (const r of output.failedResults) {\n parts.push(`## ${r.url}\\nError: ${r.error}`);\n }\n\n const text = parts.join('\\n\\n');\n return truncateStringForTokenEstimate(text, MAX_WEB_EXTRACT_TOKENS);\n },\n });\n}\n"],"mappings":";;;;AAKA,MAAM,wBAAwB;AAC9B,MAAM,yBAAyB;AAE/B,MAAM,sBAAsB;;;;;;AAO5B,SAAgB,eAAwB;CACtC,OAAO,CAAC,CAAC,QAAQ,IAAI;AACvB;;;;;;AAOA,SAAgB,sBAAsB;CACpC,MAAM,mBAAmB,uBAAuB;CAEhD,OAAO,WAAW;EAChB,IAAI;EACJ,aAAa,iBAAiB;EAC9B,aAAa,iBAAiB;EAC9B,SAAS,OAAO,OAAO,YAAY;GACjC,MAAM,SAAc,MAAM,iBAAiB,QAAS,OAAc,OAAc;GAEhF,MAAM,QAAkB,CAAC;GAEzB,IAAI,OAAO,QACT,MAAM,KAAK,WAAW,OAAO,QAAQ;GAGvC,MAAM,WAAW,OAAO,QAAQ,QAAQ,OAAY,EAAE,SAAS,MAAM,mBAAmB;GACxF,KAAK,MAAM,KAAK,UACd,MAAM,KAAK,MAAM,EAAE,MAAM,IAAI,EAAE,IAAI,IAAI,EAAE,SAAS;GAGpD,MAAM,UAAU,OAAO,UAAU,CAAC,EAAA,CAAG,KAAK,QAAa,IAAI,GAAG,CAAC,CAAC,OAAO,OAAO;GAC9E,IAAI,OAAO,SAAS,GAClB,MAAM,KAAK,YAAY,OAAO,KAAK,IAAI,GAAG;GAI5C,OAAO,+BADM,MAAM,KAAK,MACiB,GAAG,qBAAqB;EACnE;CACF,CAAC;AACH;;;;;AAMA,SAAgB,uBAAuB;CACrC,MAAM,oBAAoB,wBAAwB;CAElD,OAAO,WAAW;EAChB,IAAI;EACJ,aAAa,kBAAkB;EAC/B,aAAa,kBAAkB;EAC/B,SAAS,OAAO,OAAO,YAAY;GACjC,MAAM,SAAc,MAAM,kBAAkB,QAAS,OAAc,OAAc;GAEjF,MAAM,QAAkB,CAAC;GAEzB,KAAK,MAAM,KAAK,OAAO,SACrB,MAAM,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,YAAY;GAG3C,KAAK,MAAM,KAAK,OAAO,eACrB,MAAM,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,OAAO;GAI7C,OAAO,+BADM,MAAM,KAAK,MACiB,GAAG,sBAAsB;EACpE;CACF,CAAC;AACH"}