@mastra/code-sdk 1.0.3-alpha.1 → 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.
- package/CHANGELOG.md +38 -0
- package/dist/acp/agent.js +155 -167
- package/dist/acp/agent.js.map +1 -1
- package/dist/acp/event-mapper.js +193 -168
- package/dist/acp/event-mapper.js.map +1 -1
- package/dist/acp/index.js +60 -49
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/server.js +31 -30
- package/dist/acp/server.js.map +1 -1
- package/dist/acp.js +1 -4
- package/dist/agents/credential-resolver.js +40 -29
- package/dist/agents/credential-resolver.js.map +1 -1
- package/dist/agents/custom-provider-source.js +16 -9
- package/dist/agents/custom-provider-source.js.map +1 -1
- package/dist/agents/instructions.js +27 -36
- package/dist/agents/instructions.js.map +1 -1
- package/dist/agents/mastracode-gateway.js +355 -428
- package/dist/agents/mastracode-gateway.js.map +1 -1
- package/dist/agents/memory.js +87 -78
- package/dist/agents/memory.js.map +1 -1
- package/dist/agents/model.js +114 -119
- package/dist/agents/model.js.map +1 -1
- package/dist/agents/modes/build.js +12 -13
- package/dist/agents/modes/build.js.map +1 -1
- package/dist/agents/modes/explore.js +14 -13
- package/dist/agents/modes/explore.js.map +1 -1
- package/dist/agents/modes/plan.js +14 -15
- package/dist/agents/modes/plan.js.map +1 -1
- package/dist/agents/prompts/agent-instructions.js +78 -69
- package/dist/agents/prompts/agent-instructions.js.map +1 -1
- package/dist/agents/prompts/build.js +19 -16
- package/dist/agents/prompts/build.js.map +1 -1
- package/dist/agents/prompts/fast.js +8 -4
- package/dist/agents/prompts/fast.js.map +1 -1
- package/dist/agents/prompts/index.js +48 -47
- package/dist/agents/prompts/index.js.map +1 -1
- package/dist/agents/prompts/model.js +6 -5
- package/dist/agents/prompts/model.js.map +1 -1
- package/dist/agents/prompts/plan.js +20 -16
- package/dist/agents/prompts/plan.js.map +1 -1
- package/dist/agents/prompts/tool-guidance.js +77 -109
- package/dist/agents/prompts/tool-guidance.js.map +1 -1
- package/dist/agents/sandbox-filesystem.js +245 -259
- package/dist/agents/sandbox-filesystem.js.map +1 -1
- package/dist/agents/sandbox-reattach.js +9 -11
- package/dist/agents/sandbox-reattach.js.map +1 -1
- package/dist/agents/thread-caveman-state.js +92 -81
- package/dist/agents/thread-caveman-state.js.map +1 -1
- package/dist/agents/tool-availability.js +62 -80
- package/dist/agents/tool-availability.js.map +1 -1
- package/dist/agents/tools.js +99 -139
- package/dist/agents/tools.js.map +1 -1
- package/dist/agents/workspace.js +232 -225
- package/dist/agents/workspace.js.map +1 -1
- package/dist/analytics.js +139 -128
- package/dist/analytics.js.map +1 -1
- package/dist/auth/authorization-input.js +39 -25
- package/dist/auth/authorization-input.js.map +1 -1
- package/dist/auth/device-code.js +112 -80
- package/dist/auth/device-code.js.map +1 -1
- package/dist/auth/index.js +2 -9
- package/dist/auth/pkce.js +27 -16
- package/dist/auth/pkce.js.map +1 -1
- package/dist/auth/providers/anthropic.js +107 -93
- package/dist/auth/providers/anthropic.js.map +1 -1
- package/dist/auth/providers/github-copilot.js +304 -293
- package/dist/auth/providers/github-copilot.js.map +1 -1
- package/dist/auth/providers/openai-codex.js +442 -460
- package/dist/auth/providers/openai-codex.js.map +1 -1
- package/dist/auth/providers/xai.js +179 -145
- package/dist/auth/providers/xai.js.map +1 -1
- package/dist/auth/storage.js +182 -175
- package/dist/auth/storage.js.map +1 -1
- package/dist/auth/types.js +1 -1
- package/dist/clipboard/index.js +206 -172
- package/dist/clipboard/index.js.map +1 -1
- package/dist/constants.js +11 -16
- package/dist/constants.js.map +1 -1
- package/dist/error-classification.js +19 -11
- package/dist/error-classification.js.map +1 -1
- package/dist/evals/context-builder.js +145 -104
- package/dist/evals/context-builder.js.map +1 -1
- package/dist/evals/index.js +4 -7
- package/dist/evals/scorers/classify-command.js +62 -41
- package/dist/evals/scorers/classify-command.js.map +1 -1
- package/dist/evals/scorers/efficiency.js +239 -181
- package/dist/evals/scorers/efficiency.js.map +1 -1
- package/dist/evals/scorers/extract-tools.js +51 -47
- package/dist/evals/scorers/extract-tools.js.map +1 -1
- package/dist/evals/scorers/index.js +1 -5
- package/dist/evals/scorers/outcome.js +321 -212
- package/dist/evals/scorers/outcome.js.map +1 -1
- package/dist/goal-manager.js +266 -261
- package/dist/goal-manager.js.map +1 -1
- package/dist/goal-signal.js +14 -13
- package/dist/goal-signal.js.map +1 -1
- package/dist/headless/cli.js +153 -154
- package/dist/headless/cli.js.map +1 -1
- package/dist/headless/flags.js +180 -178
- package/dist/headless/flags.js.map +1 -1
- package/dist/headless/format.js +72 -71
- package/dist/headless/format.js.map +1 -1
- package/dist/headless/index.js +5 -31
- package/dist/headless/policy.js +35 -31
- package/dist/headless/policy.js.map +1 -1
- package/dist/headless/run-mc.js +332 -334
- package/dist/headless/run-mc.js.map +1 -1
- package/dist/headless/types.js +16 -7
- package/dist/headless/types.js.map +1 -1
- package/dist/hooks/config.js +56 -61
- package/dist/hooks/config.js.map +1 -1
- package/dist/hooks/executor.js +118 -116
- package/dist/hooks/executor.js.map +1 -1
- package/dist/hooks/index.js +4 -15
- package/dist/hooks/manager.js +221 -280
- package/dist/hooks/manager.js.map +1 -1
- package/dist/hooks/types.js +5 -4
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +632 -712
- package/dist/index.js.map +1 -1
- package/dist/ipc/ipc-reporter.js +19 -22
- package/dist/ipc/ipc-reporter.js.map +1 -1
- package/dist/lsp/client.js +248 -306
- package/dist/lsp/client.js.map +1 -1
- package/dist/lsp/index.js +1 -6
- package/dist/lsp/language.js +39 -43
- package/dist/lsp/language.js.map +1 -1
- package/dist/lsp/manager.js +78 -93
- package/dist/lsp/manager.js.map +1 -1
- package/dist/lsp/server.js +151 -120
- package/dist/lsp/server.js.map +1 -1
- package/dist/lsp/workspace.js +50 -47
- package/dist/lsp/workspace.js.map +1 -1
- package/dist/mcp/config.js +210 -199
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/index.js +2 -9
- package/dist/mcp/manager.js +482 -475
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/types.js +1 -1
- package/dist/onboarding/custom-packs.js +14 -17
- package/dist/onboarding/custom-packs.js.map +1 -1
- package/dist/onboarding/custom-providers.js +22 -20
- package/dist/onboarding/custom-providers.js.map +1 -1
- package/dist/onboarding/index.d.ts +1 -1
- package/dist/onboarding/index.d.ts.map +1 -1
- package/dist/onboarding/index.js +3 -21
- package/dist/onboarding/om-settings.d.ts +5 -0
- package/dist/onboarding/om-settings.d.ts.map +1 -1
- package/dist/onboarding/om-settings.js +41 -20
- package/dist/onboarding/om-settings.js.map +1 -1
- package/dist/onboarding/packs.d.ts +4 -6
- package/dist/onboarding/packs.d.ts.map +1 -1
- package/dist/onboarding/packs.js +154 -105
- package/dist/onboarding/packs.js.map +1 -1
- package/dist/onboarding/settings.js +575 -517
- package/dist/onboarding/settings.js.map +1 -1
- package/dist/permissions.js +112 -99
- package/dist/permissions.js.map +1 -1
- package/dist/plugin.js +21 -23
- package/dist/plugin.js.map +1 -1
- package/dist/plugins/dependencies.js +64 -87
- package/dist/plugins/dependencies.js.map +1 -1
- package/dist/plugins/install.js +159 -169
- package/dist/plugins/install.js.map +1 -1
- package/dist/plugins/loader.js +170 -185
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/manager.js +374 -380
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/manifest.js +38 -63
- package/dist/plugins/manifest.js.map +1 -1
- package/dist/plugins/package-link.js +48 -64
- package/dist/plugins/package-link.js.map +1 -1
- package/dist/plugins/paths.js +18 -19
- package/dist/plugins/paths.js.map +1 -1
- package/dist/plugins/registry.js +97 -81
- package/dist/plugins/registry.js.map +1 -1
- package/dist/plugins/scaffold.js +62 -98
- package/dist/plugins/scaffold.js.map +1 -1
- package/dist/plugins/types.js +1 -1
- package/dist/processors/plan-rejection-abort.js +45 -44
- package/dist/processors/plan-rejection-abort.js.map +1 -1
- package/dist/providers/amazon-bedrock-gateway.js +134 -125
- package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
- package/dist/providers/amazon-bedrock.js +68 -47
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/claude-max.js +153 -133
- package/dist/providers/claude-max.js.map +1 -1
- package/dist/providers/github-copilot.js +232 -230
- package/dist/providers/github-copilot.js.map +1 -1
- package/dist/providers/openai-codex.js +271 -260
- package/dist/providers/openai-codex.js.map +1 -1
- package/dist/providers/xai.js +57 -50
- package/dist/providers/xai.js.map +1 -1
- package/dist/schema.js +91 -89
- package/dist/schema.js.map +1 -1
- package/dist/theme-palette.js +18 -14
- package/dist/theme-palette.js.map +1 -1
- package/dist/tool-names.js +46 -37
- package/dist/tool-names.js.map +1 -1
- package/dist/tools/index.js +2 -8
- package/dist/tools/request-sandbox-access.js +71 -80
- package/dist/tools/request-sandbox-access.js.map +1 -1
- package/dist/tools/utils.js +26 -16
- package/dist/tools/utils.js.map +1 -1
- package/dist/tools/web-search.js +51 -55
- package/dist/tools/web-search.js.map +1 -1
- package/dist/utils/binaries.js +65 -61
- package/dist/utils/binaries.js.map +1 -1
- package/dist/utils/debug-log.js +51 -47
- package/dist/utils/debug-log.js.map +1 -1
- package/dist/utils/errors.js +157 -192
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/gateway-sync.js +49 -37
- package/dist/utils/gateway-sync.js.map +1 -1
- package/dist/utils/path-security.js +7 -6
- package/dist/utils/path-security.js.map +1 -1
- package/dist/utils/plan-diff.js +58 -39
- package/dist/utils/plan-diff.js.map +1 -1
- package/dist/utils/plans.js +92 -74
- package/dist/utils/plans.js.map +1 -1
- package/dist/utils/project.js +318 -256
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/signals-pubsub.js +117 -99
- package/dist/utils/signals-pubsub.js.map +1 -1
- package/dist/utils/slash-command-loader.js +118 -154
- package/dist/utils/slash-command-loader.js.map +1 -1
- package/dist/utils/slash-command-processor.js +92 -83
- package/dist/utils/slash-command-processor.js.map +1 -1
- package/dist/utils/stdin-pipe.js +87 -63
- package/dist/utils/stdin-pipe.js.map +1 -1
- package/dist/utils/storage-factory.js +104 -84
- package/dist/utils/storage-factory.js.map +1 -1
- package/dist/utils/storage-maintenance.js +249 -211
- package/dist/utils/storage-maintenance.js.map +1 -1
- package/dist/utils/thread-lock.js +96 -92
- package/dist/utils/thread-lock.js.map +1 -1
- package/dist/utils/token-estimator.js +12 -12
- package/dist/utils/token-estimator.js.map +1 -1
- package/dist/utils/update-check.d.ts +1 -1
- package/dist/utils/update-check.js +341 -259
- package/dist/utils/update-check.js.map +1 -1
- package/dist/voice/stt-registry.js +131 -113
- package/dist/voice/stt-registry.js.map +1 -1
- package/package.json +12 -12
- package/dist/acp.js.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/evals/index.js.map +0 -1
- package/dist/evals/scorers/index.js.map +0 -1
- package/dist/headless/index.js.map +0 -1
- package/dist/hooks/index.js.map +0 -1
- package/dist/lsp/index.js.map +0 -1
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/types.js.map +0 -1
- package/dist/onboarding/index.js.map +0 -1
- package/dist/plugins/types.js.map +0 -1
- package/dist/tools/index.js.map +0 -1
package/dist/tool-names.js
CHANGED
|
@@ -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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
package/dist/tool-names.js.map
CHANGED
|
@@ -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":"
|
|
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"}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
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
|
|
2
|
-
import * as
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
86
|
-
|
|
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":"
|
|
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"}
|
package/dist/tools/utils.js
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../constants.js";
|
|
2
2
|
import { buildSkillPaths } from "../agents/workspace.js";
|
|
3
|
-
import
|
|
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
|
-
|
|
6
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
29
|
+
//#endregion
|
|
30
|
+
export { getAllowedPathsFromContext, isPathAllowed };
|
|
31
|
+
|
|
22
32
|
//# sourceMappingURL=utils.js.map
|
package/dist/tools/utils.js.map
CHANGED
|
@@ -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":"
|
|
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"}
|
package/dist/tools/web-search.js
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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":"
|
|
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"}
|