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,121 @@
|
|
|
1
|
+
import { grepDef, GREP_MAX_OUTPUT_LINES } from "./grep.js";
|
|
2
|
+
import { globDef, GLOB_MAX_RESULTS } from "./glob.js";
|
|
3
|
+
import { listDir, MAX_ENTRIES } from "./listDir.js";
|
|
4
|
+
export const search = {
|
|
5
|
+
name: "search",
|
|
6
|
+
readOnly: true,
|
|
7
|
+
description: "Find things in the project. Pass `pattern` to search file CONTENTS with a regular " +
|
|
8
|
+
"expression, or `files` to find files by PATH, or both to search contents only " +
|
|
9
|
+
"within files whose path matches — which saves a separate lookup first. Pass " +
|
|
10
|
+
"NEITHER to LIST what is there, one level deep.\n" +
|
|
11
|
+
"CONTENTS (`pattern`): `output_mode` is 'files_with_matches' (default, just paths), " +
|
|
12
|
+
"'content' (matching lines), or 'count'. Avoid lookahead, lookbehind and " +
|
|
13
|
+
"backreferences; the search engine rejects them. Character classes, groups, " +
|
|
14
|
+
"alternation and anchors are all fine. `multiline` lets a pattern cross line breaks, " +
|
|
15
|
+
"which is how you find a construct that is not on one line (a signature and its body, " +
|
|
16
|
+
`an object literal, a JSX block). Output stops after ${GREP_MAX_OUTPUT_LINES} matching ` +
|
|
17
|
+
"lines and tells you the `offset` to pass for the next page — a capped search is " +
|
|
18
|
+
"something to CONTINUE, not a reason to start reading whole files. Use `after` when " +
|
|
19
|
+
"you want what follows a match (a declaration's body) rather than a symmetric window.\n" +
|
|
20
|
+
`PATHS (\`files\`): a glob like \`**/*.ts\` or \`src/**/*.{ts,tsx}\`, matched against ` +
|
|
21
|
+
"each file's path RELATIVE to the root being searched, so a leading slash does not " +
|
|
22
|
+
`work. Results stop after ${GLOB_MAX_RESULTS} paths and say so when they do.\n` +
|
|
23
|
+
"LISTING (neither argument): the immediate contents of `path`, one level, not " +
|
|
24
|
+
"recursive — or of every session root if you give no path. Entries come directories " +
|
|
25
|
+
"first, then alphabetically. A trailing slash means a directory. `(symlink)` marks a " +
|
|
26
|
+
"link, and it still gets the slash when it points at a directory; `(broken symlink)` " +
|
|
27
|
+
"means the target is gone. `(skipped by search)` marks a directory that is really " +
|
|
28
|
+
"there but that the two searches above will not descend into, which is why a file " +
|
|
29
|
+
`inside it can exist and never appear in a search. Listings stop after ${MAX_ENTRIES} ` +
|
|
30
|
+
"entries and say how many were left out.\n" +
|
|
31
|
+
"Searches every session root unless `path` (a file, directory, or root label) is given.\n" +
|
|
32
|
+
"WHAT IS NOT SEARCHED, so an empty result is NOT proof something is absent: anything " +
|
|
33
|
+
"the project's .gitignore excludes (build output, dist, generated code), node_modules " +
|
|
34
|
+
"and .git always, and secrets (.env, keys) plus other coding agents' data, which are " +
|
|
35
|
+
"refused rather than missing. If what you need lives in one of those, read the file " +
|
|
36
|
+
"directly instead of concluding it is not there. LISTING is the exception and the " +
|
|
37
|
+
"reason to reach for it: it reports the DISK, so ignored build output, secrets and " +
|
|
38
|
+
"other agents' folders all appear. Seeing something listed is not a promise you may " +
|
|
39
|
+
"open it — read_file still refuses secrets and asks before another agent's data. " +
|
|
40
|
+
"Treat a listing as evidence of what exists, and let the read decide what you see.\n" +
|
|
41
|
+
"To find the uses of a symbol you can NAME, try references first: it reads parsed " +
|
|
42
|
+
"code rather than raw text, so a mention in a comment or a string is not a match. " +
|
|
43
|
+
"Come back here when it reports a name-level answer and exact identity matters.",
|
|
44
|
+
parameters: {
|
|
45
|
+
type: "object",
|
|
46
|
+
additionalProperties: false,
|
|
47
|
+
properties: {
|
|
48
|
+
pattern: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Regular expression to search file CONTENTS for. Omit to search by path only.",
|
|
51
|
+
},
|
|
52
|
+
files: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: 'Glob for file paths (e.g. "**/*.ts"). Alone: find files by name. With `pattern`: ' +
|
|
55
|
+
"search contents only inside these files.",
|
|
56
|
+
},
|
|
57
|
+
path: {
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "File, directory, or root label to search — or, with neither `pattern` nor " +
|
|
60
|
+
"`files`, the directory to list. Defaults to all session roots.",
|
|
61
|
+
},
|
|
62
|
+
output_mode: {
|
|
63
|
+
type: "string",
|
|
64
|
+
enum: ["files_with_matches", "content", "count"],
|
|
65
|
+
description: "Contents search only. What to return. Defaults to files_with_matches.",
|
|
66
|
+
},
|
|
67
|
+
ignore_case: { type: "boolean", description: "Contents search only. Case-insensitive." },
|
|
68
|
+
context: {
|
|
69
|
+
type: "integer",
|
|
70
|
+
minimum: 0,
|
|
71
|
+
description: "Contents search only. Lines of context around each match (content mode).",
|
|
72
|
+
},
|
|
73
|
+
before: {
|
|
74
|
+
type: "integer",
|
|
75
|
+
minimum: 0,
|
|
76
|
+
description: "Lines to show BEFORE each match (content mode). Overrides `context` on that side.",
|
|
77
|
+
},
|
|
78
|
+
after: {
|
|
79
|
+
type: "integer",
|
|
80
|
+
minimum: 0,
|
|
81
|
+
description: "Lines to show AFTER each match (content mode). Overrides `context` on that side.",
|
|
82
|
+
},
|
|
83
|
+
multiline: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
description: "Let the pattern span line breaks, with `.` matching newlines too. Off by default. " +
|
|
86
|
+
"Use it for constructs that are not on one line — a function signature and its body, " +
|
|
87
|
+
"an object literal, a JSX block.",
|
|
88
|
+
},
|
|
89
|
+
head_limit: {
|
|
90
|
+
type: "integer",
|
|
91
|
+
minimum: 0,
|
|
92
|
+
description: "Return at most this many results. 0 means no limit. Defaults to the cap below.",
|
|
93
|
+
},
|
|
94
|
+
offset: {
|
|
95
|
+
type: "integer",
|
|
96
|
+
minimum: 0,
|
|
97
|
+
description: "Skip this many results first — page through a capped search instead of narrowing it. " +
|
|
98
|
+
"The result tells you the offset to pass next.",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
async execute(args, ctx) {
|
|
103
|
+
const pattern = typeof args.pattern === "string" ? args.pattern.trim() : "";
|
|
104
|
+
const files = typeof args.files === "string" ? args.files.trim() : "";
|
|
105
|
+
// Contents search. `files` becomes the path filter it always was under grep's own
|
|
106
|
+
// `glob` argument — the merge is what makes that reachable without knowing two tools.
|
|
107
|
+
//
|
|
108
|
+
// Neither argument is no longer an error: nothing to match by means "show me what
|
|
109
|
+
// is here", which is what a model reaching for a listing meant anyway.
|
|
110
|
+
const result = pattern
|
|
111
|
+
? await grepDef.execute({ ...args, pattern, ...(files ? { glob: files } : {}) }, ctx)
|
|
112
|
+
: files
|
|
113
|
+
? await globDef.execute({ ...args, pattern: files }, ctx)
|
|
114
|
+
: await listDir.execute({ ...(args.path ? { path: args.path } : {}) }, ctx);
|
|
115
|
+
// Quiet is applied HERE, on every path including errors, rather than inside either
|
|
116
|
+
// implementation. One tool, one display policy — and a failed search is exactly the
|
|
117
|
+
// row most likely to creep back onto the screen if each branch decided for itself.
|
|
118
|
+
return { ...result, quiet: true };
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { anchorOf } from "./paths.js";
|
|
2
|
+
import { listSessions, loadSessionNotes, loadTranscript } from "../memory/store.js";
|
|
3
|
+
import { fail } from "./results.js";
|
|
4
|
+
/** How many sessions to list at once unless asked for more. */
|
|
5
|
+
const DEFAULT_LIMIT = 10;
|
|
6
|
+
/** Characters of transcript to return before clipping — a transcript is unbounded. */
|
|
7
|
+
const MAX_TRANSCRIPT_CHARS = 20_000;
|
|
8
|
+
/**
|
|
9
|
+
* One tool, two levels of specificity: no `id` lists, an `id` reads.
|
|
10
|
+
*
|
|
11
|
+
* These were `list_sessions` and `read_session`. Same store, same access pattern, and
|
|
12
|
+
* the second was almost always a direct follow-up to the first — so the split bought
|
|
13
|
+
* the model a routing decision and cost two advertised schemas to describe one idea.
|
|
14
|
+
*/
|
|
15
|
+
export const sessionsTool = {
|
|
16
|
+
name: "sessions",
|
|
17
|
+
deferred: true,
|
|
18
|
+
readOnly: true,
|
|
19
|
+
description: "Look at your own past sessions in this project. Use this whenever the user refers " +
|
|
20
|
+
"to earlier work ('last session', 'what did we do', 'the bug we fixed yesterday') — " +
|
|
21
|
+
"you have this history, so look it up instead of guessing or saying you cannot see " +
|
|
22
|
+
"it.\n" +
|
|
23
|
+
"With no `id` it LISTS past sessions, newest first: when each ran, what the user " +
|
|
24
|
+
"opened with, what they last asked, how long it went. Cheap — no transcripts are " +
|
|
25
|
+
"opened.\n" +
|
|
26
|
+
"With an `id` it READS that session, returning its maintained notes (its own running " +
|
|
27
|
+
"summary of the work and where it got to, which is what 'what did we do' means). If " +
|
|
28
|
+
"that session kept no notes you get its raw exchange instead, in the same call, so " +
|
|
29
|
+
"one call always answers. Pass `id: 'latest'` for the most recent past session, and " +
|
|
30
|
+
"`full: true` only when you specifically want the raw exchange over the notes.",
|
|
31
|
+
parameters: {
|
|
32
|
+
type: "object",
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
properties: {
|
|
35
|
+
id: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "A session id to read, or 'latest' for the most recent. Omit entirely to list sessions instead.",
|
|
38
|
+
},
|
|
39
|
+
limit: {
|
|
40
|
+
type: "integer",
|
|
41
|
+
minimum: 1,
|
|
42
|
+
maximum: 50,
|
|
43
|
+
description: `Listing only: how many to list (default ${DEFAULT_LIMIT}, newest first).`,
|
|
44
|
+
},
|
|
45
|
+
full: {
|
|
46
|
+
type: "boolean",
|
|
47
|
+
description: "Reading only: return the raw transcript instead of the notes. Large.",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
async execute(args, ctx) {
|
|
52
|
+
// The dispatch: naming a session means read it, otherwise list what there is.
|
|
53
|
+
const wanted = typeof args.id === "string" ? args.id.trim() : "";
|
|
54
|
+
return wanted ? readOne(args, ctx, wanted) : listAll(args, ctx);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
async function listAll(args, ctx) {
|
|
58
|
+
const root = anchorOf(ctx);
|
|
59
|
+
const all = await listSessions(root);
|
|
60
|
+
const past = all.filter((m) => m.id !== ctx.sessionId);
|
|
61
|
+
if (past.length === 0) {
|
|
62
|
+
return { output: "No earlier sessions are saved for this project.", summary: "no past sessions", quiet: true };
|
|
63
|
+
}
|
|
64
|
+
const limit = clampInt(args.limit, DEFAULT_LIMIT, 1, 50);
|
|
65
|
+
const shown = past.slice(0, limit);
|
|
66
|
+
const lines = shown.map(describe);
|
|
67
|
+
const more = past.length > shown.length ? `\n\n(${past.length - shown.length} older, raise \`limit\` to see them.)` : "";
|
|
68
|
+
return {
|
|
69
|
+
output: `Your past sessions in this project, newest first. Call sessions again with an ` +
|
|
70
|
+
`id for what happened in one:\n\n${lines.join("\n\n")}${more}`,
|
|
71
|
+
summary: `${past.length} past session${past.length === 1 ? "" : "s"}`,
|
|
72
|
+
// Looking up its own history is bookkeeping, not news — same call made for
|
|
73
|
+
// compaction/verification. The answer shows up in the reply itself.
|
|
74
|
+
quiet: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function readOne(args, ctx, wanted) {
|
|
78
|
+
const root = anchorOf(ctx);
|
|
79
|
+
const all = await listSessions(root);
|
|
80
|
+
const past = all.filter((m) => m.id !== ctx.sessionId);
|
|
81
|
+
if (past.length === 0) {
|
|
82
|
+
return { output: "No earlier sessions are saved for this project.", summary: "no past sessions", quiet: true };
|
|
83
|
+
}
|
|
84
|
+
// "latest" is the explicit spelling of what used to be "omit the id". Omitting it
|
|
85
|
+
// now means LIST, so the shorthand needs a word of its own rather than a gap.
|
|
86
|
+
const meta = wanted === "latest" ? past[0] : past.find((m) => m.id === wanted);
|
|
87
|
+
if (!meta) {
|
|
88
|
+
return fail(`no saved session with id '${wanted}'. Call sessions with no id to see which ids exist.`);
|
|
89
|
+
}
|
|
90
|
+
const header = describe(meta);
|
|
91
|
+
if (args.full === true) {
|
|
92
|
+
const transcript = await loadTranscript(root, meta.id);
|
|
93
|
+
return {
|
|
94
|
+
output: `${header}\n\n${renderTranscript(transcript ?? [])}`,
|
|
95
|
+
summary: `session ${short(meta.id)} (transcript)`,
|
|
96
|
+
quiet: true,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const notes = await loadSessionNotes(root, meta.id);
|
|
100
|
+
if (!notes) {
|
|
101
|
+
// No notes → answer anyway, from the transcript, in THIS call. Telling the model
|
|
102
|
+
// to come back with full:true bought nothing: it spent an extra round trip to
|
|
103
|
+
// reach the same clipped transcript we can already return, and a model that reads
|
|
104
|
+
// "call again" as "that failed" answers from the project files instead — the exact
|
|
105
|
+
// deflection these tools exist to stop. The render is bounded, so this is safe.
|
|
106
|
+
const transcript = await loadTranscript(root, meta.id);
|
|
107
|
+
const body = renderTranscript(transcript ?? []);
|
|
108
|
+
return {
|
|
109
|
+
output: `${header}\n\nThat session kept no notes (it may have been short), so this is its ` +
|
|
110
|
+
`raw exchange instead:\n\n${body}`,
|
|
111
|
+
summary: `session ${short(meta.id)} (transcript, no notes)`,
|
|
112
|
+
quiet: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
output: `${header}\n\nWhat that session recorded about its own work:\n\n${notes}`,
|
|
117
|
+
summary: `session ${short(meta.id)} (notes)`,
|
|
118
|
+
// Reading its own history is bookkeeping, not news — same as the listing above.
|
|
119
|
+
// The answer is what shows up, not the lookup itself.
|
|
120
|
+
quiet: true,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/** One session as a compact block: id, when, size, and the prompts that bracket it. */
|
|
124
|
+
function describe(meta) {
|
|
125
|
+
const parts = [
|
|
126
|
+
`id: ${meta.id}`,
|
|
127
|
+
`when: ${timeAgo(meta.updatedAt)} (${new Date(meta.updatedAt).toISOString().slice(0, 16).replace("T", " ")})`,
|
|
128
|
+
`length: ${meta.entryCount} messages`,
|
|
129
|
+
`opened with: ${clip(meta.firstPrompt)}`,
|
|
130
|
+
];
|
|
131
|
+
// The last prompt is only worth a line when it differs — a one-exchange session
|
|
132
|
+
// would otherwise print the same text twice.
|
|
133
|
+
if (meta.lastPrompt && meta.lastPrompt.trim() !== meta.firstPrompt.trim()) {
|
|
134
|
+
parts.push(`last asked: ${clip(meta.lastPrompt)}`);
|
|
135
|
+
}
|
|
136
|
+
return parts.join("\n");
|
|
137
|
+
}
|
|
138
|
+
/** Render a saved transcript readably, clipped — transcripts have no size bound. */
|
|
139
|
+
function renderTranscript(entries) {
|
|
140
|
+
const body = entries
|
|
141
|
+
.filter((e) => e.role === "user" || e.role === "assistant")
|
|
142
|
+
.map((e) => `${e.role === "user" ? "User" : "You"}: ${e.content.trim()}`)
|
|
143
|
+
.filter((line) => line.length > 6)
|
|
144
|
+
.join("\n\n");
|
|
145
|
+
if (!body)
|
|
146
|
+
return "(that session's transcript is empty)";
|
|
147
|
+
return body.length > MAX_TRANSCRIPT_CHARS
|
|
148
|
+
? body.slice(0, MAX_TRANSCRIPT_CHARS) + "\n\n… (transcript clipped)"
|
|
149
|
+
: body;
|
|
150
|
+
}
|
|
151
|
+
/** "3 days ago" / "2 hours ago" — how a human refers to a past session. */
|
|
152
|
+
export function timeAgo(when, now = Date.now()) {
|
|
153
|
+
const seconds = Math.max(0, Math.round((now - when) / 1000));
|
|
154
|
+
if (seconds < 60)
|
|
155
|
+
return "just now";
|
|
156
|
+
const units = [
|
|
157
|
+
[60, "minute"],
|
|
158
|
+
[3600, "hour"],
|
|
159
|
+
[86400, "day"],
|
|
160
|
+
[604800, "week"],
|
|
161
|
+
];
|
|
162
|
+
let label = "minute";
|
|
163
|
+
let size = 60;
|
|
164
|
+
for (const [unitSeconds, name] of units) {
|
|
165
|
+
if (seconds >= unitSeconds) {
|
|
166
|
+
size = unitSeconds;
|
|
167
|
+
label = name;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const n = Math.floor(seconds / size);
|
|
171
|
+
return `${n} ${label}${n === 1 ? "" : "s"} ago`;
|
|
172
|
+
}
|
|
173
|
+
function short(id) {
|
|
174
|
+
return id.slice(0, 8);
|
|
175
|
+
}
|
|
176
|
+
function clip(text, max = 140) {
|
|
177
|
+
const line = (text ?? "").replace(/\s+/g, " ").trim();
|
|
178
|
+
if (!line)
|
|
179
|
+
return "(nothing recorded)";
|
|
180
|
+
return line.length > max ? line.slice(0, max - 1) + "…" : line;
|
|
181
|
+
}
|
|
182
|
+
function clampInt(value, fallback, min, max) {
|
|
183
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
184
|
+
return fallback;
|
|
185
|
+
return Math.min(max, Math.max(min, Math.floor(value)));
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=sessionTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionTools.js","sourceRoot":"","sources":["../../src/tools/sessionTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shellCheckpoint.ts — bringing shell-caused file changes into /undo.
|
|
3
|
+
*
|
|
4
|
+
* `run_command` was the one mutation path that bypassed checkpoints entirely. The
|
|
5
|
+
* write tools snapshot a file before they touch it, so /undo can put it back; a shell
|
|
6
|
+
* command that rewrites the same file through a formatter, a codemod, or an improvised
|
|
7
|
+
* one-off script left nothing to restore. The turn was flagged as "a shell ran" and the
|
|
8
|
+
* user was told, in effect, that some unspecified part of it could not be undone.
|
|
9
|
+
*
|
|
10
|
+
* That gap matters more than it looks, because improvisation via run_command is a
|
|
11
|
+
* FEATURE — a capable model covers missing capabilities by writing a script, and the
|
|
12
|
+
* tool-trimming work leans on that being possible. Every capability reached that way was
|
|
13
|
+
* landing outside the safety net that the equivalent dedicated tool sits inside.
|
|
14
|
+
*
|
|
15
|
+
* ── WHAT THIS CAN AND CANNOT DO, PRECISELY ──────────────────────────────────────
|
|
16
|
+
*
|
|
17
|
+
* Undo needs the bytes from BEFORE the change, and after a command has run they are
|
|
18
|
+
* gone. So the only honest fix is to snapshot first, and snapshotting the whole working
|
|
19
|
+
* tree before every command is not affordable.
|
|
20
|
+
*
|
|
21
|
+
* The bounded thing that IS affordable is the read ledger: the files this session has
|
|
22
|
+
* actually opened. That set is capped, usually small, and warm in the OS cache — and it
|
|
23
|
+
* is overwhelmingly the set an improvised script aims at, because the model writes the
|
|
24
|
+
* script about the files it has been working on. So those files get a real, restorable
|
|
25
|
+
* checkpoint.
|
|
26
|
+
*
|
|
27
|
+
* Files the session never read are not covered, and that is not papered over: they are
|
|
28
|
+
* counted and reported, so /undo says what it did not cover rather than implying it
|
|
29
|
+
* covered everything. An honest gap beats a silent one.
|
|
30
|
+
*/
|
|
31
|
+
import { promises as fs } from "node:fs";
|
|
32
|
+
/** Per-file ceiling for a pre-command snapshot. Above this, skip rather than stall. */
|
|
33
|
+
const MAX_SNAPSHOT_FILE_BYTES = 512 * 1024;
|
|
34
|
+
/** Total ceiling across one snapshot, so a big ledger cannot pause a command. */
|
|
35
|
+
const MAX_SNAPSHOT_TOTAL_BYTES = 8 * 1024 * 1024;
|
|
36
|
+
/**
|
|
37
|
+
* Commands that cannot change files, so the snapshot is skipped entirely.
|
|
38
|
+
*
|
|
39
|
+
* Deliberately a SMALL allow-list of obviously-read-only starts, not an attempt to
|
|
40
|
+
* classify shell commands in general. Getting this wrong in the permissive direction
|
|
41
|
+
* silently drops undo coverage, so anything unrecognised is treated as mutating and
|
|
42
|
+
* pays for a snapshot it may not need. A wasted stat is cheap; a lost file is not.
|
|
43
|
+
*/
|
|
44
|
+
const READ_ONLY_STARTS = [
|
|
45
|
+
"cat", "head", "tail", "less", "more", "ls", "dir", "pwd", "echo", "which", "type",
|
|
46
|
+
"git status", "git log", "git diff", "git show", "git branch",
|
|
47
|
+
"node --version", "npm --version", "npm ls", "npm list",
|
|
48
|
+
];
|
|
49
|
+
export function looksReadOnly(command) {
|
|
50
|
+
const c = command.trim().toLowerCase();
|
|
51
|
+
// Anything chaining or redirecting can write, whatever it starts with.
|
|
52
|
+
if (/[>|;&]/.test(c))
|
|
53
|
+
return false;
|
|
54
|
+
return READ_ONLY_STARTS.some((p) => c === p || c.startsWith(`${p} `));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Capture the ledger's files before a command runs.
|
|
58
|
+
*
|
|
59
|
+
* Failures are silent per file: a file that vanished or cannot be read is simply not
|
|
60
|
+
* covered, which is the same outcome as not being in the ledger. This must never be
|
|
61
|
+
* the reason a command does not run.
|
|
62
|
+
*/
|
|
63
|
+
export async function snapshotBeforeCommand(ctx) {
|
|
64
|
+
const snapshot = new Map();
|
|
65
|
+
if (!ctx.checkpoints || ctx.reads.size === 0)
|
|
66
|
+
return snapshot;
|
|
67
|
+
let total = 0;
|
|
68
|
+
for (const absPath of ctx.reads.keys()) {
|
|
69
|
+
try {
|
|
70
|
+
const stat = await fs.stat(absPath);
|
|
71
|
+
if (!stat.isFile() || stat.size > MAX_SNAPSHOT_FILE_BYTES)
|
|
72
|
+
continue;
|
|
73
|
+
if (total + stat.size > MAX_SNAPSHOT_TOTAL_BYTES)
|
|
74
|
+
break;
|
|
75
|
+
const content = await fs.readFile(absPath, "utf8");
|
|
76
|
+
snapshot.set(absPath, { content, mtimeMs: stat.mtimeMs, size: stat.size });
|
|
77
|
+
total += stat.size;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Gone, unreadable, or binary — not coverable, and not worth failing over.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return snapshot;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Compare the tree against the snapshot and check in whatever the command changed.
|
|
87
|
+
*
|
|
88
|
+
* Mtime AND size are both compared, for the same reason the edit-freshness gate does:
|
|
89
|
+
* a coarse filesystem clock hides a fast rewrite, and a same-size change (a flipped
|
|
90
|
+
* boolean, a renamed identifier) hides from a size check. Either signal alone misses
|
|
91
|
+
* real cases.
|
|
92
|
+
*/
|
|
93
|
+
export async function captureAfterCommand(ctx, before) {
|
|
94
|
+
const captured = [];
|
|
95
|
+
const uncaptured = [];
|
|
96
|
+
if (!ctx.checkpoints)
|
|
97
|
+
return { captured, uncaptured };
|
|
98
|
+
for (const [absPath, prior] of before) {
|
|
99
|
+
let now;
|
|
100
|
+
try {
|
|
101
|
+
const stat = await fs.stat(absPath);
|
|
102
|
+
if (stat.mtimeMs === prior.mtimeMs && stat.size === prior.size)
|
|
103
|
+
continue;
|
|
104
|
+
now = { content: await fs.readFile(absPath, "utf8"), changed: true };
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Deleted by the command: still a change, and one undo can reverse by writing
|
|
108
|
+
// the old bytes back.
|
|
109
|
+
now = { content: null, changed: true };
|
|
110
|
+
}
|
|
111
|
+
if (!now.changed)
|
|
112
|
+
continue;
|
|
113
|
+
if (now.content === prior.content)
|
|
114
|
+
continue; // touched but identical: nothing to undo
|
|
115
|
+
ctx.checkpoints.backup(absPath, prior.content, now.content ?? "");
|
|
116
|
+
captured.push(absPath);
|
|
117
|
+
}
|
|
118
|
+
// Anything the session had never read is outside the snapshot by construction. We
|
|
119
|
+
// cannot enumerate it without walking the tree, so it is reported as a category
|
|
120
|
+
// rather than a list — see noteShell, which still fires for exactly this reason.
|
|
121
|
+
return { captured, uncaptured };
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=shellCheckpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellCheckpoint.js","sourceRoot":"","sources":["../../src/tools/shellCheckpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shellLint.ts — a conservative advisory for bash-isms in a Windows PowerShell
|
|
3
|
+
* command (pure, so it's unit-tested).
|
|
4
|
+
*
|
|
5
|
+
* Models are overwhelmingly bash-trained, but Mindweave runs commands in
|
|
6
|
+
* powershell.exe (5.1) on Windows, where some bash constructs silently break:
|
|
7
|
+
* `&&`/`||` are parse errors, `2>/dev/null` isn't a thing, and tools like `grep`
|
|
8
|
+
* / `sed` / `head` don't exist. This returns a short note the caller appends to
|
|
9
|
+
* the command result so the model corrects itself next time.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately conservative — it must NOT flag valid PowerShell. In particular
|
|
12
|
+
* `ls`, `cat`, `rm`, `cp`, `mv`, `echo`, `pwd`, `sort` are real PowerShell
|
|
13
|
+
* ALIASES and work fine, so they are never flagged. Only genuinely-broken
|
|
14
|
+
* constructs are. Quoted substrings are ignored to avoid matching inside strings.
|
|
15
|
+
*/
|
|
16
|
+
/** GNU/bash tools with no PowerShell alias (so they fail on a stock Windows box). */
|
|
17
|
+
const BASH_ONLY_TOOLS = ["grep", "sed", "awk", "head", "tail", "touch", "which", "wc"];
|
|
18
|
+
/**
|
|
19
|
+
* The subset of bash-isms that are GUARANTEED Windows PowerShell 5.1 PARSE ERRORS —
|
|
20
|
+
* the command cannot run at all. Used as a PRE-execution gate so a run isn't wasted on
|
|
21
|
+
* a command that will only ever fail to parse. ONLY `&&`/`||` qualify: everything else
|
|
22
|
+
* the advisory notes (missing tools, `/dev/null`, `export`) actually executes — and a
|
|
23
|
+
* tool like `grep` may even be on PATH — so those must stay advisory, never blocked.
|
|
24
|
+
* Returns a fix hint (including the `shell:'cmd'` escape hatch) or null.
|
|
25
|
+
*/
|
|
26
|
+
export function powershellParseError(command) {
|
|
27
|
+
const bare = command.replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
|
|
28
|
+
if (/\&\&|\|\|/.test(bare)) {
|
|
29
|
+
return ("`&&`/`||` are parse errors in Windows PowerShell — this command won't run. Join with `;` " +
|
|
30
|
+
"(use `if`/`$?` to stop on failure), or pass shell:'cmd' to run it in cmd.exe, which supports `&&`/`||`.");
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* PowerShell automatic variables that are read-only/constant — assigning to one throws
|
|
36
|
+
* "Cannot overwrite variable X because it is read-only or constant" and the command dies.
|
|
37
|
+
* `$pid` is the one models reach for constantly (parsing a PID out of netstat), which is
|
|
38
|
+
* exactly the wall that turned a "start the app" request into a 90-second flailing loop.
|
|
39
|
+
* This is the constant set from PowerShell's own `AvoidAssignmentToAutomaticVariable`
|
|
40
|
+
* rule that hard-errors on assignment ($null is excluded — assigning it is a silent no-op).
|
|
41
|
+
*/
|
|
42
|
+
const PS_READONLY_VARS = ["PID", "Host", "ExecutionContext", "PSHOME", "ShellId", "true", "false"];
|
|
43
|
+
/**
|
|
44
|
+
* A guaranteed runtime failure: assigning to a read-only automatic variable. Detected
|
|
45
|
+
* pre-execution (like the `&&` parse gate) so the run isn't wasted — the model gets the
|
|
46
|
+
* fix immediately instead of firing the command, reading the error, and retrying. Only
|
|
47
|
+
* ASSIGNMENT is flagged (`$pid = …`), never a read/compare (`if ($pid -eq …)`). Quoted
|
|
48
|
+
* spans are blanked first so a literal inside a string never trips it. Returns the fix
|
|
49
|
+
* hint or null.
|
|
50
|
+
*/
|
|
51
|
+
export function powershellReservedAssignmentReason(command) {
|
|
52
|
+
const bare = command.replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
|
|
53
|
+
const re = new RegExp(`\\$(${PS_READONLY_VARS.join("|")})\\s*\\+?=(?!=)`, "i");
|
|
54
|
+
const m = bare.match(re);
|
|
55
|
+
if (!m)
|
|
56
|
+
return null;
|
|
57
|
+
const name = m[1];
|
|
58
|
+
return (`\`$${name}\` is a read-only automatic variable in Windows PowerShell — assigning to it fails with ` +
|
|
59
|
+
`"Cannot overwrite variable ${name} because it is read-only or constant." Use a different variable ` +
|
|
60
|
+
`name (e.g. \`$procId\` instead of \`$pid\`).`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A one-line advisory if `command` contains a clear bash-ism that breaks in
|
|
64
|
+
* Windows PowerShell, else null. `command` is the raw command the model sent.
|
|
65
|
+
*/
|
|
66
|
+
export function powershellLintReason(command) {
|
|
67
|
+
// Blank out quoted spans so we don't match inside string literals.
|
|
68
|
+
const bare = command
|
|
69
|
+
.replace(/'[^']*'/g, " ")
|
|
70
|
+
.replace(/"[^"]*"/g, " ");
|
|
71
|
+
const problems = [];
|
|
72
|
+
if (/\&\&|\|\|/.test(bare)) {
|
|
73
|
+
problems.push("`&&`/`||` are parse errors in Windows PowerShell 5.1 — run separate commands or join with `;` (use `if`/`$?` to stop on failure)");
|
|
74
|
+
}
|
|
75
|
+
if (/\/dev\/null/.test(bare)) {
|
|
76
|
+
problems.push("`/dev/null` doesn't exist — redirect with `2>$null` / `>$null`");
|
|
77
|
+
}
|
|
78
|
+
// A bash-only tool in command position: at the start, or right after ; | & (
|
|
79
|
+
const toolRe = new RegExp(`(^|[;|&(])\\s*(${BASH_ONLY_TOOLS.join("|")})\\b`, "i");
|
|
80
|
+
const m = bare.match(toolRe);
|
|
81
|
+
if (m) {
|
|
82
|
+
const tool = m[2].toLowerCase();
|
|
83
|
+
const suggestion = {
|
|
84
|
+
grep: "Select-String",
|
|
85
|
+
sed: "-replace / Get-Content",
|
|
86
|
+
awk: "Select-Object / ForEach-Object",
|
|
87
|
+
head: "Get-Content -TotalCount N",
|
|
88
|
+
tail: "Get-Content -Tail N",
|
|
89
|
+
touch: "New-Item",
|
|
90
|
+
which: "(Get-Command x).Source",
|
|
91
|
+
wc: "Measure-Object",
|
|
92
|
+
};
|
|
93
|
+
problems.push(`\`${tool}\` isn't available in PowerShell — use \`${suggestion[tool]}\` (or Mindweave's grep/read tools)`);
|
|
94
|
+
}
|
|
95
|
+
if (/(^|[;|&(])\s*export\s+\w+=/.test(bare)) {
|
|
96
|
+
problems.push("bash `export VAR=...` doesn't work — use `$env:VAR = '...'`");
|
|
97
|
+
}
|
|
98
|
+
if (problems.length === 0)
|
|
99
|
+
return null;
|
|
100
|
+
return `Note: this looks like bash, but the shell is Windows PowerShell. ${problems.join("; ")}.`;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=shellLint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellLint.js","sourceRoot":"","sources":["../../src/tools/shellLint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,qFAAqF;AACrF,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAEvF;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACvE,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,CACL,2FAA2F;YAC3F,yGAAyG,CAC1G,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnG;;;;;;;GAOG;AACH,MAAM,UAAU,kCAAkC,CAAC,OAAe;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACvE,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAC/E,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IACnB,OAAO,CACL,MAAM,IAAI,0FAA0F;QACpG,8BAA8B,IAAI,kEAAkE;QACpG,8CAA8C,CAC/C,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,mEAAmE;IACnE,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAE5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,CAAC,kIAAkI,CAAC,CAAC;IACpJ,CAAC;IACD,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IAClF,CAAC;IACD,6EAA6E;IAC7E,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,kBAAkB,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,UAAU,GAA2B;YACzC,IAAI,EAAE,eAAe;YACrB,GAAG,EAAE,wBAAwB;YAC7B,GAAG,EAAE,gCAAgC;YACrC,IAAI,EAAE,2BAA2B;YACjC,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,UAAU;YACjB,KAAK,EAAE,wBAAwB;YAC/B,EAAE,EAAE,gBAAgB;SACrB,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,4CAA4C,UAAU,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAC5H,CAAC;IACD,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,QAAQ,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,oEAAoE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACpG,CAAC"}
|