mindweave 0.0.1 → 2.1.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/LICENSE +190 -0
- package/README.md +171 -14
- package/dist/alternator/chassis/cache.js +47 -0
- package/dist/alternator/chassis/cache.js.map +1 -0
- package/dist/alternator/chassis/domRefs.js +53 -0
- package/dist/alternator/chassis/domRefs.js.map +1 -0
- package/dist/alternator/chassis/extractWorker.js +65 -0
- package/dist/alternator/chassis/extractWorker.js.map +1 -0
- package/dist/alternator/chassis/graph.js +221 -0
- package/dist/alternator/chassis/graph.js.map +1 -0
- package/dist/alternator/chassis/index.js +463 -0
- package/dist/alternator/chassis/index.js.map +1 -0
- package/dist/alternator/chassis/isolation.js +336 -0
- package/dist/alternator/chassis/isolation.js.map +1 -0
- package/dist/alternator/chassis/langCases.js +69 -0
- package/dist/alternator/chassis/langCases.js.map +1 -0
- package/dist/alternator/chassis/lsp.js +469 -0
- package/dist/alternator/chassis/lsp.js.map +1 -0
- package/dist/alternator/chassis/markup.js +262 -0
- package/dist/alternator/chassis/markup.js.map +1 -0
- package/dist/alternator/chassis/provision.js +198 -0
- package/dist/alternator/chassis/provision.js.map +1 -0
- package/dist/alternator/chassis/rank.js +72 -0
- package/dist/alternator/chassis/rank.js.map +1 -0
- package/dist/alternator/chassis/servers.js +215 -0
- package/dist/alternator/chassis/servers.js.map +1 -0
- package/dist/alternator/chassis/treesitter.js +608 -0
- package/dist/alternator/chassis/treesitter.js.map +1 -0
- package/dist/alternator/chassis/types.js +24 -0
- package/dist/alternator/chassis/types.js.map +1 -0
- package/dist/alternator/lane.js +67 -0
- package/dist/alternator/lane.js.map +1 -0
- package/dist/cli/App.js +2586 -0
- package/dist/cli/App.js.map +1 -0
- package/dist/cli/altScreen.js +67 -0
- package/dist/cli/altScreen.js.map +1 -0
- package/dist/cli/approvalChannel.js +72 -0
- package/dist/cli/approvalChannel.js.map +1 -0
- package/dist/cli/attachments.js +188 -0
- package/dist/cli/attachments.js.map +1 -0
- package/dist/cli/bootstrap.js +279 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/chatAnchor.js +94 -0
- package/dist/cli/chatAnchor.js.map +1 -0
- package/dist/cli/commandArgs.js +79 -0
- package/dist/cli/commandArgs.js.map +1 -0
- package/dist/cli/commandRoute.js +78 -0
- package/dist/cli/commandRoute.js.map +1 -0
- package/dist/cli/compaction.js +69 -0
- package/dist/cli/compaction.js.map +1 -0
- package/dist/cli/components/ApprovalBox.js +100 -0
- package/dist/cli/components/ApprovalBox.js.map +1 -0
- package/dist/cli/components/BlockView.js +128 -0
- package/dist/cli/components/BlockView.js.map +1 -0
- package/dist/cli/components/FirstRunFrame.js +41 -0
- package/dist/cli/components/FirstRunFrame.js.map +1 -0
- package/dist/cli/components/KeyManager.js +197 -0
- package/dist/cli/components/KeyManager.js.map +1 -0
- package/dist/cli/components/KeySetup.js +125 -0
- package/dist/cli/components/KeySetup.js.map +1 -0
- package/dist/cli/components/MenuFrame.js +24 -0
- package/dist/cli/components/MenuFrame.js.map +1 -0
- package/dist/cli/components/Picker.js +82 -0
- package/dist/cli/components/Picker.js.map +1 -0
- package/dist/cli/components/PromptInput.js +509 -0
- package/dist/cli/components/PromptInput.js.map +1 -0
- package/dist/cli/components/SubagentView.js +86 -0
- package/dist/cli/components/SubagentView.js.map +1 -0
- package/dist/cli/components/ToolGroup.js +60 -0
- package/dist/cli/components/ToolGroup.js.map +1 -0
- package/dist/cli/components/ToolLine.js +123 -0
- package/dist/cli/components/ToolLine.js.map +1 -0
- package/dist/cli/components/TrustGate.js +37 -0
- package/dist/cli/components/TrustGate.js.map +1 -0
- package/dist/cli/costView.js +40 -0
- package/dist/cli/costView.js.map +1 -0
- package/dist/cli/frameRate.js +30 -0
- package/dist/cli/frameRate.js.map +1 -0
- package/dist/cli/framebuffer/paint.js +165 -0
- package/dist/cli/framebuffer/paint.js.map +1 -0
- package/dist/cli/framebuffer/parse.js +266 -0
- package/dist/cli/framebuffer/parse.js.map +1 -0
- package/dist/cli/framebuffer/screen.js +196 -0
- package/dist/cli/framebuffer/screen.js.map +1 -0
- package/dist/cli/framebuffer/writer.js +139 -0
- package/dist/cli/framebuffer/writer.js.map +1 -0
- package/dist/cli/groupReveal.js +51 -0
- package/dist/cli/groupReveal.js.map +1 -0
- package/dist/cli/help.js +55 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/inputView.js +105 -0
- package/dist/cli/inputView.js.map +1 -0
- package/dist/cli/keyManager.js +65 -0
- package/dist/cli/keyManager.js.map +1 -0
- package/dist/cli/keySetup.js +35 -0
- package/dist/cli/keySetup.js.map +1 -0
- package/dist/cli/keyStore.js +73 -0
- package/dist/cli/keyStore.js.map +1 -0
- package/dist/cli/markdown.js +460 -0
- package/dist/cli/markdown.js.map +1 -0
- package/dist/cli/messageQueue.js +96 -0
- package/dist/cli/messageQueue.js.map +1 -0
- package/dist/cli/modes.js +90 -0
- package/dist/cli/modes.js.map +1 -0
- package/dist/cli/mouse.js +78 -0
- package/dist/cli/mouse.js.map +1 -0
- package/dist/cli/pasteAssembler.js +44 -0
- package/dist/cli/pasteAssembler.js.map +1 -0
- package/dist/cli/pathComplete.js +39 -0
- package/dist/cli/pathComplete.js.map +1 -0
- package/dist/cli/perfLog.js +90 -0
- package/dist/cli/perfLog.js.map +1 -0
- package/dist/cli/reveal.js +32 -0
- package/dist/cli/reveal.js.map +1 -0
- package/dist/cli/revealPace.js +59 -0
- package/dist/cli/revealPace.js.map +1 -0
- package/dist/cli/sessionCarry.js +19 -0
- package/dist/cli/sessionCarry.js.map +1 -0
- package/dist/cli/smoothScroll.js +74 -0
- package/dist/cli/smoothScroll.js.map +1 -0
- package/dist/cli/startupArgs.js +96 -0
- package/dist/cli/startupArgs.js.map +1 -0
- package/dist/cli/terminalRestore.js +34 -0
- package/dist/cli/terminalRestore.js.map +1 -0
- package/dist/cli/toolDisplay.js +219 -0
- package/dist/cli/toolDisplay.js.map +1 -0
- package/dist/cli/toolItems.js +65 -0
- package/dist/cli/toolItems.js.map +1 -0
- package/dist/cli/transcript.js +351 -0
- package/dist/cli/transcript.js.map +1 -0
- package/dist/cli/trust.js +79 -0
- package/dist/cli/trust.js.map +1 -0
- package/dist/cli/updateCheck.js +107 -0
- package/dist/cli/updateCheck.js.map +1 -0
- package/dist/cli/version.js +39 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/viewport.js +179 -0
- package/dist/cli/viewport.js.map +1 -0
- package/dist/cli/virtualWindow.js +103 -0
- package/dist/cli/virtualWindow.js.map +1 -0
- package/dist/cli/workingVerb.js +37 -0
- package/dist/cli/workingVerb.js.map +1 -0
- package/dist/cli/wrap.js +145 -0
- package/dist/cli/wrap.js.map +1 -0
- package/dist/drivers/anthropic/cachePoints.js +77 -0
- package/dist/drivers/anthropic/cachePoints.js.map +1 -0
- package/dist/drivers/anthropic/client.js +432 -0
- package/dist/drivers/anthropic/client.js.map +1 -0
- package/dist/drivers/anthropic/index.js +10 -0
- package/dist/drivers/anthropic/index.js.map +1 -0
- package/dist/drivers/anthropic/manifest.js +221 -0
- package/dist/drivers/anthropic/manifest.js.map +1 -0
- package/dist/drivers/cerebras/client.js +69 -0
- package/dist/drivers/cerebras/client.js.map +1 -0
- package/dist/drivers/cerebras/index.js +5 -0
- package/dist/drivers/cerebras/index.js.map +1 -0
- package/dist/drivers/cerebras/manifest.js +140 -0
- package/dist/drivers/cerebras/manifest.js.map +1 -0
- package/dist/drivers/clientId.js +41 -0
- package/dist/drivers/clientId.js.map +1 -0
- package/dist/drivers/contextOverflow.js +77 -0
- package/dist/drivers/contextOverflow.js.map +1 -0
- package/dist/drivers/deepseek/client.js +168 -0
- package/dist/drivers/deepseek/client.js.map +1 -0
- package/dist/drivers/deepseek/index.js +16 -0
- package/dist/drivers/deepseek/index.js.map +1 -0
- package/dist/drivers/deepseek/inlineTools.js +46 -0
- package/dist/drivers/deepseek/inlineTools.js.map +1 -0
- package/dist/drivers/deepseek/manifest.js +166 -0
- package/dist/drivers/deepseek/manifest.js.map +1 -0
- package/dist/drivers/gemini/client.js +38 -0
- package/dist/drivers/gemini/client.js.map +1 -0
- package/dist/drivers/gemini/index.js +5 -0
- package/dist/drivers/gemini/index.js.map +1 -0
- package/dist/drivers/gemini/manifest.js +150 -0
- package/dist/drivers/gemini/manifest.js.map +1 -0
- package/dist/drivers/glm/client.js +90 -0
- package/dist/drivers/glm/client.js.map +1 -0
- package/dist/drivers/glm/index.js +9 -0
- package/dist/drivers/glm/index.js.map +1 -0
- package/dist/drivers/glm/manifest.js +183 -0
- package/dist/drivers/glm/manifest.js.map +1 -0
- package/dist/drivers/groq/client.js +80 -0
- package/dist/drivers/groq/client.js.map +1 -0
- package/dist/drivers/groq/index.js +5 -0
- package/dist/drivers/groq/index.js.map +1 -0
- package/dist/drivers/groq/manifest.js +160 -0
- package/dist/drivers/groq/manifest.js.map +1 -0
- package/dist/drivers/kimi/client.js +82 -0
- package/dist/drivers/kimi/client.js.map +1 -0
- package/dist/drivers/kimi/index.js +9 -0
- package/dist/drivers/kimi/index.js.map +1 -0
- package/dist/drivers/kimi/manifest.js +168 -0
- package/dist/drivers/kimi/manifest.js.map +1 -0
- package/dist/drivers/meta/client.js +30 -0
- package/dist/drivers/meta/client.js.map +1 -0
- package/dist/drivers/meta/index.js +5 -0
- package/dist/drivers/meta/index.js.map +1 -0
- package/dist/drivers/meta/manifest.js +101 -0
- package/dist/drivers/meta/manifest.js.map +1 -0
- package/dist/drivers/minimax/client.js +36 -0
- package/dist/drivers/minimax/client.js.map +1 -0
- package/dist/drivers/minimax/index.js +5 -0
- package/dist/drivers/minimax/index.js.map +1 -0
- package/dist/drivers/minimax/manifest.js +120 -0
- package/dist/drivers/minimax/manifest.js.map +1 -0
- package/dist/drivers/mistral/client.js +54 -0
- package/dist/drivers/mistral/client.js.map +1 -0
- package/dist/drivers/mistral/index.js +5 -0
- package/dist/drivers/mistral/index.js.map +1 -0
- package/dist/drivers/mistral/manifest.js +118 -0
- package/dist/drivers/mistral/manifest.js.map +1 -0
- package/dist/drivers/openai/client.js +290 -0
- package/dist/drivers/openai/client.js.map +1 -0
- package/dist/drivers/openai/index.js +9 -0
- package/dist/drivers/openai/index.js.map +1 -0
- package/dist/drivers/openai/manifest.js +133 -0
- package/dist/drivers/openai/manifest.js.map +1 -0
- package/dist/drivers/openaiCompat/wire.js +493 -0
- package/dist/drivers/openaiCompat/wire.js.map +1 -0
- package/dist/drivers/partialTurn.js +23 -0
- package/dist/drivers/partialTurn.js.map +1 -0
- package/dist/drivers/providerError.js +181 -0
- package/dist/drivers/providerError.js.map +1 -0
- package/dist/drivers/qwen/client.js +93 -0
- package/dist/drivers/qwen/client.js.map +1 -0
- package/dist/drivers/qwen/index.js +9 -0
- package/dist/drivers/qwen/index.js.map +1 -0
- package/dist/drivers/qwen/manifest.js +146 -0
- package/dist/drivers/qwen/manifest.js.map +1 -0
- package/dist/drivers/registry.js +177 -0
- package/dist/drivers/registry.js.map +1 -0
- package/dist/drivers/retryPolicy.js +129 -0
- package/dist/drivers/retryPolicy.js.map +1 -0
- package/dist/drivers/searchBlocks.js +61 -0
- package/dist/drivers/searchBlocks.js.map +1 -0
- package/dist/drivers/types.js +2 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/drivers/xai/client.js +63 -0
- package/dist/drivers/xai/client.js.map +1 -0
- package/dist/drivers/xai/index.js +5 -0
- package/dist/drivers/xai/index.js.map +1 -0
- package/dist/drivers/xai/manifest.js +137 -0
- package/dist/drivers/xai/manifest.js.map +1 -0
- package/dist/dynamo/_probe.tmp.js +20 -0
- package/dist/dynamo/_probe.tmp.js.map +1 -0
- package/dist/dynamo/cacheBreak.js +88 -0
- package/dist/dynamo/cacheBreak.js.map +1 -0
- package/dist/dynamo/contextWindow.js +243 -0
- package/dist/dynamo/contextWindow.js.map +1 -0
- package/dist/dynamo/engine.js +2011 -0
- package/dist/dynamo/engine.js.map +1 -0
- package/dist/dynamo/guard.js +132 -0
- package/dist/dynamo/guard.js.map +1 -0
- package/dist/dynamo/liveMeter.js +58 -0
- package/dist/dynamo/liveMeter.js.map +1 -0
- package/dist/dynamo/model.js +172 -0
- package/dist/dynamo/model.js.map +1 -0
- package/dist/dynamo/planArtifact.js +125 -0
- package/dist/dynamo/planArtifact.js.map +1 -0
- package/dist/dynamo/pricing.js +140 -0
- package/dist/dynamo/pricing.js.map +1 -0
- package/dist/dynamo/prompt.js +264 -0
- package/dist/dynamo/prompt.js.map +1 -0
- package/dist/dynamo/spend.js +45 -0
- package/dist/dynamo/spend.js.map +1 -0
- package/dist/dynamo/verify.js +483 -0
- package/dist/dynamo/verify.js.map +1 -0
- package/dist/governor/forbidden.js +181 -0
- package/dist/governor/forbidden.js.map +1 -0
- package/dist/governor/freshness.js +83 -0
- package/dist/governor/freshness.js.map +1 -0
- package/dist/governor/frontmatter.js +38 -0
- package/dist/governor/frontmatter.js.map +1 -0
- package/dist/governor/glob.js +75 -0
- package/dist/governor/glob.js.map +1 -0
- package/dist/governor/index.js +87 -0
- package/dist/governor/index.js.map +1 -0
- package/dist/governor/rules.js +80 -0
- package/dist/governor/rules.js.map +1 -0
- package/dist/governor/scope.js +91 -0
- package/dist/governor/scope.js.map +1 -0
- package/dist/governor/skills.js +176 -0
- package/dist/governor/skills.js.map +1 -0
- package/dist/governor/types.js +16 -0
- package/dist/governor/types.js.map +1 -0
- package/dist/governor/write.js +182 -0
- package/dist/governor/write.js.map +1 -0
- package/dist/index.js +89 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/catalog.js +232 -0
- package/dist/mcp/catalog.js.map +1 -0
- package/dist/mcp/config.js +116 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/configWrite.js +254 -0
- package/dist/mcp/configWrite.js.map +1 -0
- package/dist/mcp/connection.js +504 -0
- package/dist/mcp/connection.js.map +1 -0
- package/dist/mcp/deferred.js +104 -0
- package/dist/mcp/deferred.js.map +1 -0
- package/dist/mcp/discover.js +128 -0
- package/dist/mcp/discover.js.map +1 -0
- package/dist/mcp/manager.js +679 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/paramHeaders.js +163 -0
- package/dist/mcp/paramHeaders.js.map +1 -0
- package/dist/mcp/prompts.js +136 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/protocol.js +171 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/resources.js +119 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/resultStore.js +180 -0
- package/dist/mcp/resultStore.js.map +1 -0
- package/dist/mcp/subscriptions.js +74 -0
- package/dist/mcp/subscriptions.js.map +1 -0
- package/dist/mcp/transport/headerValue.js +40 -0
- package/dist/mcp/transport/headerValue.js.map +1 -0
- package/dist/mcp/transport/http.js +321 -0
- package/dist/mcp/transport/http.js.map +1 -0
- package/dist/mcp/transport/stdio.js +234 -0
- package/dist/mcp/transport/stdio.js.map +1 -0
- package/dist/mcp/transport/types.js +27 -0
- package/dist/mcp/transport/types.js.map +1 -0
- package/dist/mcp/trust.js +98 -0
- package/dist/mcp/trust.js.map +1 -0
- package/dist/mcp/trustStore.js +55 -0
- package/dist/mcp/trustStore.js.map +1 -0
- package/dist/memory/autoMemory.js +340 -0
- package/dist/memory/autoMemory.js.map +1 -0
- package/dist/memory/compaction.js +513 -0
- package/dist/memory/compaction.js.map +1 -0
- package/dist/memory/images.js +173 -0
- package/dist/memory/images.js.map +1 -0
- package/dist/memory/presence.js +59 -0
- package/dist/memory/presence.js.map +1 -0
- package/dist/memory/projectNotes.js +247 -0
- package/dist/memory/projectNotes.js.map +1 -0
- package/dist/memory/restore.js +72 -0
- package/dist/memory/restore.js.map +1 -0
- package/dist/memory/session.js +472 -0
- package/dist/memory/session.js.map +1 -0
- package/dist/memory/sessionMemory.js +142 -0
- package/dist/memory/sessionMemory.js.map +1 -0
- package/dist/memory/sessionMemoryCompact.js +136 -0
- package/dist/memory/sessionMemoryCompact.js.map +1 -0
- package/dist/memory/store.js +217 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/types.js +14 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/workingSet.js +383 -0
- package/dist/memory/workingSet.js.map +1 -0
- package/dist/project/context.js +425 -0
- package/dist/project/context.js.map +1 -0
- package/dist/tools/approval.js +189 -0
- package/dist/tools/approval.js.map +1 -0
- package/dist/tools/askUser.js +103 -0
- package/dist/tools/askUser.js.map +1 -0
- package/dist/tools/atomicWrite.js +151 -0
- package/dist/tools/atomicWrite.js.map +1 -0
- package/dist/tools/backgroundShells.js +468 -0
- package/dist/tools/backgroundShells.js.map +1 -0
- package/dist/tools/captureSweep.js +77 -0
- package/dist/tools/captureSweep.js.map +1 -0
- package/dist/tools/chassisMux.js +92 -0
- package/dist/tools/chassisMux.js.map +1 -0
- package/dist/tools/checkpoints.js +328 -0
- package/dist/tools/checkpoints.js.map +1 -0
- package/dist/tools/codeIntel.js +267 -0
- package/dist/tools/codeIntel.js.map +1 -0
- package/dist/tools/deferredNative.js +121 -0
- package/dist/tools/deferredNative.js.map +1 -0
- package/dist/tools/detail.js +135 -0
- package/dist/tools/detail.js.map +1 -0
- package/dist/tools/diagnostics.js +174 -0
- package/dist/tools/diagnostics.js.map +1 -0
- package/dist/tools/edit.js +167 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/editCore.js +283 -0
- package/dist/tools/editCore.js.map +1 -0
- package/dist/tools/editFile.js +183 -0
- package/dist/tools/editFile.js.map +1 -0
- package/dist/tools/editRipple.js +126 -0
- package/dist/tools/editRipple.js.map +1 -0
- package/dist/tools/editTarget.js +131 -0
- package/dist/tools/editTarget.js.map +1 -0
- package/dist/tools/editWindow.js +49 -0
- package/dist/tools/editWindow.js.map +1 -0
- package/dist/tools/eol.js +56 -0
- package/dist/tools/eol.js.map +1 -0
- package/dist/tools/exitPlan.js +175 -0
- package/dist/tools/exitPlan.js.map +1 -0
- package/dist/tools/focus.js +42 -0
- package/dist/tools/focus.js.map +1 -0
- package/dist/tools/gitignore.js +148 -0
- package/dist/tools/gitignore.js.map +1 -0
- package/dist/tools/glob.js +134 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/governorTools.js +258 -0
- package/dist/tools/governorTools.js.map +1 -0
- package/dist/tools/grep.js +450 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/guard.js +220 -0
- package/dist/tools/guard.js.map +1 -0
- package/dist/tools/killTree.js +215 -0
- package/dist/tools/killTree.js.map +1 -0
- package/dist/tools/listDir.js +143 -0
- package/dist/tools/listDir.js.map +1 -0
- package/dist/tools/mcpAdd.js +176 -0
- package/dist/tools/mcpAdd.js.map +1 -0
- package/dist/tools/mcpResources.js +116 -0
- package/dist/tools/mcpResources.js.map +1 -0
- package/dist/tools/mcpSearch.js +123 -0
- package/dist/tools/mcpSearch.js.map +1 -0
- package/dist/tools/multiEdit.js +168 -0
- package/dist/tools/multiEdit.js.map +1 -0
- package/dist/tools/paths.js +225 -0
- package/dist/tools/paths.js.map +1 -0
- package/dist/tools/posixShell.js +123 -0
- package/dist/tools/posixShell.js.map +1 -0
- package/dist/tools/readFile.js +371 -0
- package/dist/tools/readFile.js.map +1 -0
- package/dist/tools/readSymbol.js +145 -0
- package/dist/tools/readSymbol.js.map +1 -0
- package/dist/tools/registry.js +120 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/replaceSymbol.js +141 -0
- package/dist/tools/replaceSymbol.js.map +1 -0
- package/dist/tools/results.js +15 -0
- package/dist/tools/results.js.map +1 -0
- package/dist/tools/ripgrep.js +145 -0
- package/dist/tools/ripgrep.js.map +1 -0
- package/dist/tools/runCommand.js +633 -0
- package/dist/tools/runCommand.js.map +1 -0
- package/dist/tools/saveMemory.js +102 -0
- package/dist/tools/saveMemory.js.map +1 -0
- package/dist/tools/screenshot.js +200 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/screenshotWin.js +227 -0
- package/dist/tools/screenshotWin.js.map +1 -0
- package/dist/tools/search.js +121 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/sessionTools.js +187 -0
- package/dist/tools/sessionTools.js.map +1 -0
- package/dist/tools/shellCheckpoint.js +123 -0
- package/dist/tools/shellCheckpoint.js.map +1 -0
- package/dist/tools/shellLint.js +102 -0
- package/dist/tools/shellLint.js.map +1 -0
- package/dist/tools/shellTools.js +203 -0
- package/dist/tools/shellTools.js.map +1 -0
- package/dist/tools/spanCore.js +78 -0
- package/dist/tools/spanCore.js.map +1 -0
- package/dist/tools/subagent.js +224 -0
- package/dist/tools/subagent.js.map +1 -0
- package/dist/tools/subagentReport.js +114 -0
- package/dist/tools/subagentReport.js.map +1 -0
- package/dist/tools/tempSweep.js +118 -0
- package/dist/tools/tempSweep.js.map +1 -0
- package/dist/tools/todo.js +117 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/untrusted.js +46 -0
- package/dist/tools/untrusted.js.map +1 -0
- package/dist/tools/useSkill.js +62 -0
- package/dist/tools/useSkill.js.map +1 -0
- package/dist/tools/walk.js +152 -0
- package/dist/tools/walk.js.map +1 -0
- package/dist/tools/web.js +61 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/tools/webFetch.js +444 -0
- package/dist/tools/webFetch.js.map +1 -0
- package/dist/tools/webSearch.js +130 -0
- package/dist/tools/webSearch.js.map +1 -0
- package/dist/tools/workspace.js +212 -0
- package/dist/tools/workspace.js.map +1 -0
- package/dist/tools/workspaceDiscover.js +216 -0
- package/dist/tools/workspaceDiscover.js.map +1 -0
- package/dist/tools/writeFile.js +162 -0
- package/dist/tools/writeFile.js.map +1 -0
- package/package.json +74 -28
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { relativize } from "./paths.js";
|
|
2
|
+
import { MAX_READ_CHARS } from "./backgroundShells.js";
|
|
3
|
+
import { fail, failQuietly } from "./results.js";
|
|
4
|
+
/**
|
|
5
|
+
* One read-only tool at two levels of specificity: no `id` lists, an `id` reads.
|
|
6
|
+
*
|
|
7
|
+
* These were `list_shells` and `shell_output`. Same manager, same questions ("what is
|
|
8
|
+
* running" then "what did that one say"), and reading was almost always the direct
|
|
9
|
+
* follow-up to listing — so the split cost two advertised schemas and gave the model a
|
|
10
|
+
* routing decision it did not need.
|
|
11
|
+
*
|
|
12
|
+
* `kill_shell` deliberately stays a separate tool. It is the only mutating one of the
|
|
13
|
+
* three, and the plan-mode filter runs on `tool.readOnly` while BUILDING the advertised
|
|
14
|
+
* list — before any arguments exist. Folding a kill into this tool would therefore force
|
|
15
|
+
* a choice between hiding shell inspection from Architect mode and read-only sub-agents,
|
|
16
|
+
* or offering them a way to kill processes. Neither is acceptable, so the merge stops
|
|
17
|
+
* exactly where the read/write line is.
|
|
18
|
+
*/
|
|
19
|
+
export const shellsTool = {
|
|
20
|
+
name: "shells",
|
|
21
|
+
readOnly: true,
|
|
22
|
+
/**
|
|
23
|
+
* Advertised only once this session has actually started a background shell.
|
|
24
|
+
*
|
|
25
|
+
* Nothing is lost by hiding it before then: with no shells there is nothing to list
|
|
26
|
+
* and nothing to read, so the tool can only be called to be told so. It is worth
|
|
27
|
+
* roughly 600 tokens of standing prompt across this tool and `kill_shell`, paid on
|
|
28
|
+
* every uncached request of every session — including the many that never background
|
|
29
|
+
* anything.
|
|
30
|
+
*
|
|
31
|
+
* The condition is `list()`, which retains FINISHED shells, and not `running()`.
|
|
32
|
+
* That is deliberate and is about the prompt cache rather than about correctness: the
|
|
33
|
+
* tool list is part of the cached prefix, so a condition that flipped off again when
|
|
34
|
+
* the last process exited would invalidate the whole prefix twice per shell instead
|
|
35
|
+
* of once per session. `list()` only ever goes from empty to non-empty, so the cost
|
|
36
|
+
* is a single rebuild the first time a shell appears. Reading a finished shell's
|
|
37
|
+
* output is a real use anyway.
|
|
38
|
+
*/
|
|
39
|
+
relevantWhen: (ctx) => (ctx.backgroundShells?.list().length ?? 0) > 0,
|
|
40
|
+
// The description never mentioned polling, while the tool itself pushes a strong
|
|
41
|
+
// don't-poll nudge at runtime; the two now agree. It also never mentioned either cap,
|
|
42
|
+
// and the buffer one matters: a chatty process can roll output out of the retained
|
|
43
|
+
// log between reads, so "everything since last time" is not always literally true.
|
|
44
|
+
description: "Look at the background shells run_command has started.\n" +
|
|
45
|
+
"With no `id` it LISTS them, running and recently finished. Each line answers the " +
|
|
46
|
+
"two questions worth asking about a background process: IS IT UP, distinguishing a " +
|
|
47
|
+
"server still starting from one that has come up, and WHY DID IT STOP, " +
|
|
48
|
+
"distinguishing a crash from the user closing it themselves from you stopping it. " +
|
|
49
|
+
"Check this before restarting anything: a process the user shut down should not be " +
|
|
50
|
+
"reopened, and an exit code alone cannot tell you which case you are in.\n" +
|
|
51
|
+
"With an `id` it READS that shell's new output — only what has been printed since " +
|
|
52
|
+
"your last check, plus whether it is still running or has finished and with what " +
|
|
53
|
+
"exit code. " +
|
|
54
|
+
"You normally do NOT need to call this on a loop: whether you are told about the " +
|
|
55
|
+
"shell is set by run_command's 'notify', and when you will be told, you are told " +
|
|
56
|
+
"automatically. Use this when you want the output itself, not to find out whether " +
|
|
57
|
+
"something has happened. " +
|
|
58
|
+
`A single read returns at most ${MAX_READ_CHARS.toLocaleString("en-US")} characters and says when it ` +
|
|
59
|
+
"has dropped earlier lines to fit. Separately, a very chatty process can overflow " +
|
|
60
|
+
"the retained log, in which case the oldest output is gone for good and the status " +
|
|
61
|
+
"line says so.",
|
|
62
|
+
parameters: {
|
|
63
|
+
type: "object",
|
|
64
|
+
additionalProperties: false,
|
|
65
|
+
properties: {
|
|
66
|
+
id: {
|
|
67
|
+
type: "integer",
|
|
68
|
+
description: "A background shell id to read (e.g. 1). Omit entirely to list the shells instead.",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
async execute(args, ctx) {
|
|
73
|
+
const mgr = ctx.backgroundShells;
|
|
74
|
+
if (!mgr)
|
|
75
|
+
return { output: "No background shells are available in this context.", summary: "no background shells" };
|
|
76
|
+
// The dispatch: naming a shell reads it, otherwise list what there is.
|
|
77
|
+
if (args.id === undefined || args.id === null)
|
|
78
|
+
return listAll(ctx);
|
|
79
|
+
const id = toId(args.id);
|
|
80
|
+
if (id === null)
|
|
81
|
+
return failQuietly("`id` must be a shell number.");
|
|
82
|
+
const res = await mgr.read(id);
|
|
83
|
+
if (!res)
|
|
84
|
+
return fail(`no background shell #${id}.`);
|
|
85
|
+
const head = statusLine(res.info);
|
|
86
|
+
const body = res.chunk.trim();
|
|
87
|
+
// If it's still running, stop the model polling: the event is pushed to it, so a
|
|
88
|
+
// poll loop is pure waste and reads as spam. But the nudge has to promise the
|
|
89
|
+
// RIGHT event. A server is never told about its own stop, so telling the model it
|
|
90
|
+
// would hear "when it finishes" is a promise the tool does not keep — the same
|
|
91
|
+
// false claim that once had it announcing a report that never arrived.
|
|
92
|
+
const nudge = res.info.status !== "running"
|
|
93
|
+
? ""
|
|
94
|
+
: res.info.notify === "on_failure"
|
|
95
|
+
? "\n[Still starting. You'll be told automatically once it has come up, and you will NOT be " +
|
|
96
|
+
"told when it later stops — do NOT poll again. End your turn.]"
|
|
97
|
+
: res.info.notify === "never"
|
|
98
|
+
? "\n[Still running. Nothing about this will be reported to you — do NOT poll again. End your turn.]"
|
|
99
|
+
: "\n[Still running. You'll be notified automatically when it finishes — do NOT poll again. " +
|
|
100
|
+
"End your turn and let the user know you'll report when it's done.]";
|
|
101
|
+
return {
|
|
102
|
+
output: (body ? `${head}\n${body}` : `${head}\n(no new output)`) + nudge,
|
|
103
|
+
summary: `shell #${id} (${res.info.status})`,
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
export const killShell = {
|
|
108
|
+
name: "kill_shell",
|
|
109
|
+
readOnly: false,
|
|
110
|
+
/** Same gate as `shells`, and for the same reason — including using `list()` rather
|
|
111
|
+
* than `running()` so the tool list latches once per session instead of flipping
|
|
112
|
+
* with every process that starts and stops. */
|
|
113
|
+
relevantWhen: (ctx) => (ctx.backgroundShells?.list().length ?? 0) > 0,
|
|
114
|
+
description: "Stop a running background shell by id. Kills the whole process tree, not just the " +
|
|
115
|
+
"shell, so a dev server that spawned its own children goes down with it. " +
|
|
116
|
+
"It records that YOU stopped it, which is what later lets the status be reported as " +
|
|
117
|
+
"stopped deliberately rather than guessed at as a crash. " +
|
|
118
|
+
"Stopping something already finished is not an error: you get told it was not " +
|
|
119
|
+
"running, and nothing else happens.",
|
|
120
|
+
parameters: {
|
|
121
|
+
type: "object",
|
|
122
|
+
additionalProperties: false,
|
|
123
|
+
required: ["id"],
|
|
124
|
+
properties: {
|
|
125
|
+
id: { type: "integer", description: "The background shell id to stop." },
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
async execute(args, ctx) {
|
|
129
|
+
const mgr = ctx.backgroundShells;
|
|
130
|
+
if (!mgr)
|
|
131
|
+
return fail("no background shells are available in this context.");
|
|
132
|
+
const id = toId(args.id);
|
|
133
|
+
if (id === null)
|
|
134
|
+
return failQuietly("`id` must be a shell number.");
|
|
135
|
+
const killed = mgr.kill(id);
|
|
136
|
+
return killed
|
|
137
|
+
? { output: `Stopped background shell #${id}.`, summary: `killed shell #${id}` }
|
|
138
|
+
: { output: `Background shell #${id} wasn't running (already finished, or no such id).`, summary: `shell #${id} not running` };
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
/** The no-`id` half of `shells`: what is running, and why anything stopped. */
|
|
142
|
+
function listAll(ctx) {
|
|
143
|
+
const mgr = ctx.backgroundShells;
|
|
144
|
+
const shells = mgr?.list() ?? [];
|
|
145
|
+
if (shells.length === 0)
|
|
146
|
+
return { output: "No background shells.", summary: "no background shells" };
|
|
147
|
+
const running = mgr.runningCount();
|
|
148
|
+
// The same anti-poll discipline the read path (by `id`) enforces, but for the list. The
|
|
149
|
+
// events worth waking for — a task finishing, a server coming up, a server failing to come
|
|
150
|
+
// up — are PUSHED automatically, so re-listing on a loop is pure waste; and a server's
|
|
151
|
+
// normal stop is never reported, so waiting for one to "finish" waits forever. Without
|
|
152
|
+
// this a model that checks "what's running" repeatedly is told neither, and loops. Only
|
|
153
|
+
// attached while something is running: a finished list is a fact to read, not a poll.
|
|
154
|
+
const nudge = running > 0
|
|
155
|
+
? `\n[${running} still running. You are told automatically when there is something to act on — a ` +
|
|
156
|
+
"task finishing, a server coming up, or a failure to come up. A server's normal stop is NOT " +
|
|
157
|
+
'reported, so never wait for one to "finish." Do NOT list this on a loop — end your turn.]'
|
|
158
|
+
: "";
|
|
159
|
+
return {
|
|
160
|
+
output: shells.map((s) => statusLine(s, ctx)).join("\n") + nudge,
|
|
161
|
+
summary: `${running} running, ${shells.length} total`,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* One line describing a shell, including the facts that decide whether anything needs
|
|
166
|
+
* doing about it.
|
|
167
|
+
*
|
|
168
|
+
* `stoppedBy` and `ready` are recorded precisely so the model can answer "is my app
|
|
169
|
+
* up" and "why did it stop" without guessing, so they have to be rendered here — this
|
|
170
|
+
* is the only place it can go looking. Without them every ending reads as `exited 1`,
|
|
171
|
+
* which is the same thing a crash and a user closing a window both produce.
|
|
172
|
+
*/
|
|
173
|
+
function statusLine(info, ctx) {
|
|
174
|
+
const where = ctx ? ` in ${relativize(ctx, info.cwd)}` : "";
|
|
175
|
+
// A rolled buffer means output is permanently gone. It was recorded and never shown,
|
|
176
|
+
// so an incomplete log looked exactly like a complete one.
|
|
177
|
+
const rolled = info.truncated ? " [earlier output dropped: this log is incomplete]" : "";
|
|
178
|
+
if (info.status === "running") {
|
|
179
|
+
const secs = Math.round((Date.now() - info.startedAt) / 1000);
|
|
180
|
+
const state = info.notify === "on_failure" ? (info.ready ? "up" : "starting") : "running";
|
|
181
|
+
return `#${info.id} ${state} (${secs}s)${where}: ${info.command}${rolled}`;
|
|
182
|
+
}
|
|
183
|
+
const verb = info.stoppedBy === "user"
|
|
184
|
+
? "stopped by the user"
|
|
185
|
+
: info.stoppedBy === "agent"
|
|
186
|
+
? "stopped by you"
|
|
187
|
+
: info.status === "killed"
|
|
188
|
+
? "killed"
|
|
189
|
+
: // A signalled process reports no exit code, so reading the number gives
|
|
190
|
+
// "exited null" — which is how a stopped app used to describe itself.
|
|
191
|
+
info.signal
|
|
192
|
+
? `stopped (${info.signal})`
|
|
193
|
+
: `exited ${info.exitCode}`;
|
|
194
|
+
// Whether it ever came up is what separates "the user closed their app" from "it
|
|
195
|
+
// never started", which the exit code alone cannot tell you.
|
|
196
|
+
const cameUp = info.notify === "on_failure" && !info.stoppedBy ? (info.ready ? ", after it had come up" : ", never came up") : "";
|
|
197
|
+
return `#${info.id} ${verb}${cameUp}${where}: ${info.command}${rolled}`;
|
|
198
|
+
}
|
|
199
|
+
function toId(value) {
|
|
200
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
201
|
+
return Number.isInteger(n) && n >= 1 ? n : null;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=shellTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellTools.js","sourceRoot":"","sources":["../../src/tools/shellTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spanCore.ts — pure line-span helpers for reading/replacing a symbol's body.
|
|
3
|
+
*
|
|
4
|
+
* The two symbol tools (read_symbol, replace_symbol_body) need to turn a symbol
|
|
5
|
+
* into a range of lines and then slice or splice that range. All of that math is
|
|
6
|
+
* kept here — string/number in, string/number out, no fs, no tree-sitter — so it
|
|
7
|
+
* is unit-tested once and both tools (and the chassis's LSP `documentSymbol`
|
|
8
|
+
* reader) inherit the same, verified behavior. Deciding WHICH symbol to touch is
|
|
9
|
+
* the model's job; this module only does the mechanical slicing.
|
|
10
|
+
*/
|
|
11
|
+
/** Flatten a (possibly nested) documentSymbol tree to name + 1-based line range. */
|
|
12
|
+
export function flattenDocSymbols(raw) {
|
|
13
|
+
const out = [];
|
|
14
|
+
const visit = (nodes) => {
|
|
15
|
+
for (const n of nodes ?? []) {
|
|
16
|
+
const r = n.range ?? n.location?.range;
|
|
17
|
+
const name = typeof n.name === "string" ? n.name : "";
|
|
18
|
+
if (name && typeof r?.start?.line === "number" && typeof r?.end?.line === "number") {
|
|
19
|
+
out.push({ name, start: r.start.line + 1, end: r.end.line + 1 });
|
|
20
|
+
}
|
|
21
|
+
if (n.children && n.children.length)
|
|
22
|
+
visit(n.children);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
visit(raw ?? []);
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Pick the span whose start line is nearest `nearLine` (used to disambiguate
|
|
30
|
+
* overloads / same-named symbols in one file). With no hint, the first span.
|
|
31
|
+
*/
|
|
32
|
+
export function pickNearest(spans, nearLine) {
|
|
33
|
+
if (spans.length === 0)
|
|
34
|
+
return null;
|
|
35
|
+
if (nearLine === undefined)
|
|
36
|
+
return spans[0];
|
|
37
|
+
return spans.reduce((best, s) => Math.abs(s.start - nearLine) < Math.abs(best.start - nearLine) ? s : best);
|
|
38
|
+
}
|
|
39
|
+
/** Split on CRLF or LF so line math is identical regardless of the file's EOL. */
|
|
40
|
+
function toLines(content) {
|
|
41
|
+
return content.split(/\r?\n/);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The lines [start..end] (1-based, inclusive) of `content`, line-numbered like
|
|
45
|
+
* read_file. Clamped to the file's real bounds so a slightly-too-long span never
|
|
46
|
+
* throws.
|
|
47
|
+
*/
|
|
48
|
+
export function sliceBody(content, start, end) {
|
|
49
|
+
const lines = toLines(content);
|
|
50
|
+
const from = Math.max(1, start);
|
|
51
|
+
const to = Math.min(lines.length, end);
|
|
52
|
+
const width = String(to).length;
|
|
53
|
+
const out = [];
|
|
54
|
+
for (let i = from; i <= to; i++)
|
|
55
|
+
out.push(`${String(i).padStart(width)}\t${lines[i - 1] ?? ""}`);
|
|
56
|
+
return out.join("\n");
|
|
57
|
+
}
|
|
58
|
+
/** The raw text (no line numbers) of lines [start..end], for a diff or backup. */
|
|
59
|
+
export function rawLines(content, start, end) {
|
|
60
|
+
const lines = toLines(content);
|
|
61
|
+
return lines.slice(Math.max(0, start - 1), Math.min(lines.length, end)).join("\n");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Replace lines [start..end] (1-based, inclusive) of `content` with `replacement`.
|
|
65
|
+
* Operates on LF-normalized text (the caller re-applies the file's real EOL). The
|
|
66
|
+
* range is clamped to the file's bounds so an over-long end can't drop trailing
|
|
67
|
+
* content it didn't mean to.
|
|
68
|
+
*/
|
|
69
|
+
export function spliceLines(content, start, end, replacement) {
|
|
70
|
+
const lines = toLines(content);
|
|
71
|
+
const repl = replacement.replace(/\r\n/g, "\n").split("\n");
|
|
72
|
+
const from = Math.max(1, start);
|
|
73
|
+
const to = Math.min(lines.length, end);
|
|
74
|
+
const before = lines.slice(0, from - 1);
|
|
75
|
+
const after = lines.slice(to);
|
|
76
|
+
return [...before, ...repl, ...after].join("\n");
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=spanCore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spanCore.js","sourceRoot":"","sources":["../../src/tools/spanCore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subagent.ts — spawn_subagent: delegate a bounded task to a scoped child agent.
|
|
3
|
+
*
|
|
4
|
+
* The context-isolation lever, orchestrator-worker style. A wide search or a
|
|
5
|
+
* self-contained chunk of work can cost dozens of tool rounds whose intermediate
|
|
6
|
+
* output would bloat the main agent's context. spawn_subagent runs that work in a
|
|
7
|
+
* CHILD session — its own transcript, its own read ledger, its own step budget — and
|
|
8
|
+
* returns only the child's final, distilled summary. The lead agent gets the answer
|
|
9
|
+
* without the mess, and can spawn SEVERAL read-only workers in ONE message to fan out
|
|
10
|
+
* in parallel (the engine runs concurrency-safe calls together).
|
|
11
|
+
*
|
|
12
|
+
* It reuses the engine's own `respond()` loop on a forked session (via `ctx.forkChild`,
|
|
13
|
+
* injected by the engine), so a sub-agent is a full agent, not a lesser one. Recursion
|
|
14
|
+
* is capped by `subagentDepth` so a sub-agent can't spawn its own sub-agents.
|
|
15
|
+
*
|
|
16
|
+
* A child CANNOT reach the user. It has no approval channel, and nothing the user
|
|
17
|
+
* granted in person — a Sentinel allowance, a folder they let the agent write to, the
|
|
18
|
+
* plan they approved — comes with it. So under Sentinel a child's mutating tools are
|
|
19
|
+
* REFUSED rather than prompted, and it reports back instead. That is the failing
|
|
20
|
+
* direction to pick: the alternative is a question on screen from an agent the user
|
|
21
|
+
* never saw start, or worse, an action taken on a permission they gave for something
|
|
22
|
+
* else. `read_only` restricts a child to searching/reading for safe research tasks —
|
|
23
|
+
* and ONLY a read-only worker is concurrency-safe (an editing worker runs alone, in
|
|
24
|
+
* order, so parallel edits can't race). A process-wide semaphore bounds how many run
|
|
25
|
+
* at once.
|
|
26
|
+
*/
|
|
27
|
+
import { randomUUID } from "node:crypto";
|
|
28
|
+
import { STATUS_INSTRUCTION, renderVerdict, verifySubagentReport } from "./subagentReport.js";
|
|
29
|
+
import { fail, failQuietly } from "./results.js";
|
|
30
|
+
const MAX_SUBAGENT_DEPTH = 1;
|
|
31
|
+
/** Default step budget for a worker; the caller can scale it with `max_steps`. */
|
|
32
|
+
const SUBAGENT_BUDGET = envInt("MINDWEAVE_SUBAGENT_BUDGET", 20);
|
|
33
|
+
/** Ceiling on `max_steps` so one worker can't run away. */
|
|
34
|
+
const MAX_SUBAGENT_STEPS = envInt("MINDWEAVE_SUBAGENT_MAX_STEPS", 60);
|
|
35
|
+
/** How many workers may run concurrently, process-wide. */
|
|
36
|
+
const SUBAGENT_CONCURRENCY = envInt("MINDWEAVE_SUBAGENT_CONCURRENCY", 5);
|
|
37
|
+
/**
|
|
38
|
+
* A bounded gate so a wide fan-out queues instead of launching a swarm of agents at
|
|
39
|
+
* once. Hand-off release (the freed slot goes straight to the next waiter) keeps the
|
|
40
|
+
* live count at or below the limit even under interleaved arrivals.
|
|
41
|
+
*/
|
|
42
|
+
export class Semaphore {
|
|
43
|
+
limit;
|
|
44
|
+
active = 0;
|
|
45
|
+
waiters = [];
|
|
46
|
+
constructor(limit) {
|
|
47
|
+
this.limit = limit;
|
|
48
|
+
}
|
|
49
|
+
async run(fn) {
|
|
50
|
+
await this.acquire();
|
|
51
|
+
try {
|
|
52
|
+
return await fn();
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
this.release();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
acquire() {
|
|
59
|
+
if (this.active < this.limit) {
|
|
60
|
+
this.active++;
|
|
61
|
+
return Promise.resolve();
|
|
62
|
+
}
|
|
63
|
+
return new Promise((resolve) => this.waiters.push(resolve));
|
|
64
|
+
}
|
|
65
|
+
release() {
|
|
66
|
+
const next = this.waiters.shift();
|
|
67
|
+
if (next)
|
|
68
|
+
next(); // hand the slot over; active is unchanged, so we never exceed limit
|
|
69
|
+
else
|
|
70
|
+
this.active--;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const gate = new Semaphore(SUBAGENT_CONCURRENCY);
|
|
74
|
+
export const spawnSubagent = {
|
|
75
|
+
name: "spawn_subagent",
|
|
76
|
+
/** Deferred: fan-out is a decision made at planning time rather than a step in the edit
|
|
77
|
+
* loop, and at ~750 tokens it is the most expensive schema outside the core four. The
|
|
78
|
+
* index line names it, so the option is visible where the choice is made. */
|
|
79
|
+
deferred: true,
|
|
80
|
+
readOnly: false,
|
|
81
|
+
// A read-only worker changes nothing and is safe to fan out in parallel; an editing
|
|
82
|
+
// worker must run alone (serial lane) so concurrent edits can't race. This is what
|
|
83
|
+
// lets the model emit several read-only spawn_subagent calls in one message and have
|
|
84
|
+
// them run concurrently.
|
|
85
|
+
isConcurrencySafe: (args) => args.read_only === true,
|
|
86
|
+
// Three limits were enforced in code and absent from the text: a child cannot spawn
|
|
87
|
+
// its own child, parallel workers are capped, and running out of steps is a clean
|
|
88
|
+
// PAUSE rather than a failure. That last one changes what the model should do about
|
|
89
|
+
// it — re-spawn with a bigger budget, not abandon the approach or retry identically.
|
|
90
|
+
// The briefing advice was also making one point three times, which dilutes it.
|
|
91
|
+
description: "Delegate a focused, self-contained subtask to a child agent with its own context, " +
|
|
92
|
+
"then get back just its result. This is how a wide search, an inventory, or a " +
|
|
93
|
+
"bounded chunk of work stays out of your context (e.g. \"find and list every call " +
|
|
94
|
+
"site of authFetch\"). The child does NOT see this conversation and cannot ask the " +
|
|
95
|
+
"user anything, so the task must stand alone: the objective, its boundaries (what " +
|
|
96
|
+
"NOT to touch), and via output_format the exact shape of the result you want. " +
|
|
97
|
+
"Set read_only:true for research and inventory that must not change files.\n" +
|
|
98
|
+
"PARALLEL: emit several read-only calls in ONE message to fan out over independent " +
|
|
99
|
+
`areas, giving each a distinct slice so they do not duplicate work. Up to ` +
|
|
100
|
+
`${SUBAGENT_CONCURRENCY} run at once; beyond that they queue, so more workers stop ` +
|
|
101
|
+
"buying speed. A non-read-only child runs alone. Sub-agents cost far more tokens " +
|
|
102
|
+
"than doing the work inline, and most editing is sequential, so delegate for " +
|
|
103
|
+
"independent READ and discovery rather than to parallelise edits.\n" +
|
|
104
|
+
`LIMITS: a child gets ${SUBAGENT_BUDGET} tool rounds by default (raise with ` +
|
|
105
|
+
"max_steps). If it runs out it PAUSES cleanly and says so, with its findings " +
|
|
106
|
+
"intact — that is not a failure, and the fix is a bigger max_steps, not the same " +
|
|
107
|
+
"call again. A child cannot spawn its own children, so plan one level of " +
|
|
108
|
+
"delegation and do the rest yourself.\n" +
|
|
109
|
+
"BRIEF IT WELL: write to the child as you would to a competent colleague who just " +
|
|
110
|
+
"walked in and cannot see any of this. Do the thinking yourself and hand over " +
|
|
111
|
+
"specifics (file paths, line numbers, exactly what to change) rather than \"based " +
|
|
112
|
+
"on your findings, fix the bug\". Terse command-style prompts produce shallow work.",
|
|
113
|
+
parameters: {
|
|
114
|
+
type: "object",
|
|
115
|
+
additionalProperties: false,
|
|
116
|
+
required: ["task"],
|
|
117
|
+
properties: {
|
|
118
|
+
task: {
|
|
119
|
+
type: "string",
|
|
120
|
+
description: "A complete, standalone objective for the child, including any context and scope boundaries it needs " +
|
|
121
|
+
"(it cannot see your conversation).",
|
|
122
|
+
},
|
|
123
|
+
read_only: {
|
|
124
|
+
type: "boolean",
|
|
125
|
+
description: "When true, the child may only read/search — no edits or commands — AND it runs in parallel with other " +
|
|
126
|
+
"read-only workers spawned in the same message. Default false (runs alone). Use true for research/inventory.",
|
|
127
|
+
},
|
|
128
|
+
output_format: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "The exact shape the result should come back in (e.g. \"a bullet list of `file:line — what's there`\"). " +
|
|
131
|
+
"Strongly recommended — it keeps the report tight and directly usable.",
|
|
132
|
+
},
|
|
133
|
+
max_steps: {
|
|
134
|
+
type: "integer",
|
|
135
|
+
minimum: 1,
|
|
136
|
+
maximum: MAX_SUBAGENT_STEPS,
|
|
137
|
+
description: `Tool-round budget for the child (default ${SUBAGENT_BUDGET}). Scale it up for deeper tasks, down for quick lookups.`,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
async execute(args, ctx) {
|
|
142
|
+
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
143
|
+
if (!task)
|
|
144
|
+
return failQuietly("`task` is required — describe the subtask for the child agent.");
|
|
145
|
+
const depth = ctx.subagentDepth ?? 0;
|
|
146
|
+
if (depth >= MAX_SUBAGENT_DEPTH) {
|
|
147
|
+
return fail("a sub-agent cannot spawn another sub-agent — do this part of the work directly.");
|
|
148
|
+
}
|
|
149
|
+
if (!ctx.forkChild) {
|
|
150
|
+
return fail("sub-agents aren't available in this context.");
|
|
151
|
+
}
|
|
152
|
+
const outputFormat = typeof args.output_format === "string" ? args.output_format.trim() : "";
|
|
153
|
+
// The status line is asked for on EVERY child, not only formatted ones: it is the
|
|
154
|
+
// child's half of the verification contract (see subagentReport.ts), and a child
|
|
155
|
+
// with no output_format is if anything the one whose outcome is least obvious.
|
|
156
|
+
const framedTask = [
|
|
157
|
+
task,
|
|
158
|
+
outputFormat ? `Report your result in EXACTLY this format:\n${outputFormat}` : "",
|
|
159
|
+
STATUS_INSTRUCTION,
|
|
160
|
+
]
|
|
161
|
+
.filter(Boolean)
|
|
162
|
+
.join("\n\n");
|
|
163
|
+
const budget = clampSteps(args.max_steps) ?? SUBAGENT_BUDGET;
|
|
164
|
+
const readOnly = args.read_only === true;
|
|
165
|
+
const child = ctx.forkChild(framedTask, { readOnly });
|
|
166
|
+
// Dynamic import: the static registry ← engine edge would otherwise cycle. By the
|
|
167
|
+
// time execute() runs, both modules are fully loaded, so this is safe.
|
|
168
|
+
const { respond } = await import("../dynamo/engine.js");
|
|
169
|
+
// A short id for THIS worker. Every event it emits carries it, so the UI keeps each
|
|
170
|
+
// worker's nested rail distinct even when several fan out in parallel.
|
|
171
|
+
const agentId = randomUUID().slice(0, 8);
|
|
172
|
+
const taskLabel = task.replace(/\s+/g, " ").trim().slice(0, 100);
|
|
173
|
+
ctx.emitEvent?.({ type: "subagent", phase: "start", id: agentId, task: taskLabel, readOnly });
|
|
174
|
+
let reply;
|
|
175
|
+
try {
|
|
176
|
+
// Bounded: a wide fan-out queues here rather than launching every worker at once.
|
|
177
|
+
reply = await gate.run(() => respond(child, {
|
|
178
|
+
signal: ctx.abortSignal,
|
|
179
|
+
maxSteps: budget,
|
|
180
|
+
// Surface the child's activity, not its chatter: its usage counts toward the
|
|
181
|
+
// meter, and each of its tool calls is forwarded UP tagged with this worker's
|
|
182
|
+
// id so the UI nests them in the worker's rail (its prose/reasoning stays
|
|
183
|
+
// muted — only the final distilled report crosses back, as the tool result).
|
|
184
|
+
onEvent: (e) => {
|
|
185
|
+
if (e.type === "usage")
|
|
186
|
+
ctx.reportUsage?.(e);
|
|
187
|
+
else if (e.type === "tool")
|
|
188
|
+
ctx.emitEvent?.({ ...e, agent: agentId });
|
|
189
|
+
},
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
ctx.emitEvent?.({ type: "subagent", phase: "end", id: agentId, summary: "failed", error: true });
|
|
194
|
+
return fail(`the sub-agent failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
195
|
+
}
|
|
196
|
+
const steps = child.transcript.filter((e) => e.role === "assistant").length;
|
|
197
|
+
const scope = readOnly ? " · read-only" : "";
|
|
198
|
+
const stepLabel = `${steps} step${steps === 1 ? "" : "s"}${scope}`;
|
|
199
|
+
// The gate: a child's report is a claim, not a result, until the run behind it has
|
|
200
|
+
// been checked. Nothing is withheld — the parent decides whether a partial answer
|
|
201
|
+
// is still useful — but it is told what not to assume, above the report rather
|
|
202
|
+
// than after it.
|
|
203
|
+
const verdict = verifySubagentReport(reply, { steps, budget, outputFormat });
|
|
204
|
+
const flag = verdict.trustworthy ? "" : ` · ${verdict.status === "unstated" ? "unverified" : verdict.status}`;
|
|
205
|
+
ctx.emitEvent?.({ type: "subagent", phase: "end", id: agentId, summary: `${stepLabel}${flag}`, error: verdict.status === "failed" });
|
|
206
|
+
return {
|
|
207
|
+
output: renderVerdict(verdict),
|
|
208
|
+
summary: `subagent · ${stepLabel}${flag}`,
|
|
209
|
+
};
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
/** A clamped positive step budget from the model's `max_steps`, or undefined. */
|
|
213
|
+
export function clampSteps(value) {
|
|
214
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
215
|
+
if (!Number.isInteger(n) || n < 1)
|
|
216
|
+
return undefined;
|
|
217
|
+
return Math.min(MAX_SUBAGENT_STEPS, n);
|
|
218
|
+
}
|
|
219
|
+
/** A positive integer from an env var, or `fallback`. */
|
|
220
|
+
function envInt(name, fallback) {
|
|
221
|
+
const n = Number(process.env[name]);
|
|
222
|
+
return Number.isInteger(n) && n > 0 ? n : fallback;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=subagent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent.js","sourceRoot":"","sources":["../../src/tools/subagent.ts"],"names":[],"mappings":"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"}
|