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,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* images.ts — the provider-neutral facts about an image attachment.
|
|
3
|
+
*
|
|
4
|
+
* One module owns everything core needs to know about an image without knowing
|
|
5
|
+
* which model will receive it: what kinds exist, what the caps are, how big it is
|
|
6
|
+
* on screen, and roughly what it will cost in context. Drivers own the wire shape;
|
|
7
|
+
* this owns the facts they all share.
|
|
8
|
+
*
|
|
9
|
+
* WHY A REFERENCE, NOT BYTES. An `ImageRef` is a path plus a media type — never the
|
|
10
|
+
* payload. The transcript stores refs, and the bytes are loaded only when a request
|
|
11
|
+
* is assembled. That keeps a session's JSONL small and readable, keeps resume cheap,
|
|
12
|
+
* and follows compaction's eviction rule directly: an image on disk is maximally
|
|
13
|
+
* reconstructible, and the path is the restoration key. The cost is that a file can
|
|
14
|
+
* change or vanish between the turn it was attached and a later turn; a missing file
|
|
15
|
+
* degrades to a note rather than an error, because a broken attachment must never
|
|
16
|
+
* take the conversation down with it.
|
|
17
|
+
*/
|
|
18
|
+
import { promises as fs } from "node:fs";
|
|
19
|
+
import { extname } from "node:path";
|
|
20
|
+
/**
|
|
21
|
+
* Media types every vision-capable provider accepts today. The intersection, not the
|
|
22
|
+
* union: a format only one provider takes would attach fine and then fail at the wire
|
|
23
|
+
* on the others, which is a worse experience than declining it up front.
|
|
24
|
+
*/
|
|
25
|
+
const MEDIA_TYPES = new Map([
|
|
26
|
+
[".png", "image/png"],
|
|
27
|
+
[".jpg", "image/jpeg"],
|
|
28
|
+
[".jpeg", "image/jpeg"],
|
|
29
|
+
[".gif", "image/gif"],
|
|
30
|
+
[".webp", "image/webp"],
|
|
31
|
+
]);
|
|
32
|
+
/**
|
|
33
|
+
* Image extensions Mindweave RECOGNIZES, which is deliberately wider than the set it
|
|
34
|
+
* can send. A `.bmp` or `.svg` is still identified as an image so the user gets
|
|
35
|
+
* "that format can't be sent" instead of a generic "binary file, skipped".
|
|
36
|
+
*/
|
|
37
|
+
export const IMAGE_EXTS = new Set([
|
|
38
|
+
...MEDIA_TYPES.keys(),
|
|
39
|
+
".bmp",
|
|
40
|
+
".svg",
|
|
41
|
+
".ico",
|
|
42
|
+
".tiff",
|
|
43
|
+
".avif",
|
|
44
|
+
".heic",
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Per-image ceiling. Providers state their limit on the BASE64 payload (10 MB is the
|
|
48
|
+
* common figure), and base64 inflates by 4/3, so the raw-file cap that keeps us under
|
|
49
|
+
* it is 7.5 MB. Enforced on the file, before encoding, so an oversized image is
|
|
50
|
+
* refused without ever being read into memory twice.
|
|
51
|
+
*/
|
|
52
|
+
export const MAX_IMAGE_BYTES = Math.floor(7.5 * 1024 * 1024);
|
|
53
|
+
/** Longest edge any provider accepts. Beyond this the request is rejected outright. */
|
|
54
|
+
export const MAX_IMAGE_EDGE = 8000;
|
|
55
|
+
/** The media type for a path, or null when it is not a format we can send. */
|
|
56
|
+
export function mediaTypeFor(path) {
|
|
57
|
+
return MEDIA_TYPES.get(extname(path).toLowerCase()) ?? null;
|
|
58
|
+
}
|
|
59
|
+
/** Whether a path looks like an image at all (sendable or not). */
|
|
60
|
+
export function isImage(path) {
|
|
61
|
+
return IMAGE_EXTS.has(extname(path).toLowerCase());
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Approximate context cost of an image, in tokens.
|
|
65
|
+
*
|
|
66
|
+
* Vision models bill by fixed-size patches rather than pixels, so cost scales with
|
|
67
|
+
* AREA: the published figures work out to roughly a 28x28-pixel patch per visual
|
|
68
|
+
* token, and providers downscale anything larger before charging, which caps the
|
|
69
|
+
* worst case. This reproduces that shape — area over patch area, clamped to the cap.
|
|
70
|
+
*
|
|
71
|
+
* It is an approximation, in the same spirit as `CHARS_PER_TOKEN` for text, and it
|
|
72
|
+
* exists for one reason: the compaction bars ask "how full is the context", and an
|
|
73
|
+
* image counted as zero would make every bar fire late. Counting it approximately is
|
|
74
|
+
* strictly better than counting it as nothing. When dimensions are unknown we assume
|
|
75
|
+
* the cap rather than a small number, so the error is on the safe side.
|
|
76
|
+
*/
|
|
77
|
+
const PATCH_PX = 28;
|
|
78
|
+
const MAX_IMAGE_TOKENS = 4784;
|
|
79
|
+
export function estimateImageTokens(ref) {
|
|
80
|
+
if (!ref.width || !ref.height)
|
|
81
|
+
return MAX_IMAGE_TOKENS;
|
|
82
|
+
const patches = Math.ceil(ref.width / PATCH_PX) * Math.ceil(ref.height / PATCH_PX);
|
|
83
|
+
return Math.min(patches, MAX_IMAGE_TOKENS);
|
|
84
|
+
}
|
|
85
|
+
/** Total approximate cost of a set of attachments. */
|
|
86
|
+
export function estimateImagesTokens(refs) {
|
|
87
|
+
if (!refs || refs.length === 0)
|
|
88
|
+
return 0;
|
|
89
|
+
let total = 0;
|
|
90
|
+
for (const r of refs)
|
|
91
|
+
total += estimateImageTokens(r);
|
|
92
|
+
return total;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Read the pixel dimensions out of an image's header.
|
|
96
|
+
*
|
|
97
|
+
* Only the container formats whose headers are unambiguous and cheap to parse are
|
|
98
|
+
* handled — PNG, JPEG and GIF, which covers every screenshot path that matters. WebP
|
|
99
|
+
* has three different chunk layouts and is not worth the surface here: it returns
|
|
100
|
+
* null, and the estimator then assumes the cap. Returning null is always safe.
|
|
101
|
+
*
|
|
102
|
+
* Reads a small prefix, never the whole file.
|
|
103
|
+
*/
|
|
104
|
+
export function readDimensions(buf) {
|
|
105
|
+
// PNG: signature, then an IHDR chunk with width/height at fixed offsets.
|
|
106
|
+
if (buf.length >= 24 && buf.readUInt32BE(0) === 0x89504e47) {
|
|
107
|
+
return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) };
|
|
108
|
+
}
|
|
109
|
+
// GIF: "GIF87a"/"GIF89a", then the logical screen size, little-endian.
|
|
110
|
+
if (buf.length >= 10 && buf.toString("ascii", 0, 3) === "GIF") {
|
|
111
|
+
return { width: buf.readUInt16LE(6), height: buf.readUInt16LE(8) };
|
|
112
|
+
}
|
|
113
|
+
// JPEG: walk the marker chain to the start-of-frame, which carries the size.
|
|
114
|
+
if (buf.length >= 4 && buf.readUInt16BE(0) === 0xffd8) {
|
|
115
|
+
let pos = 2;
|
|
116
|
+
while (pos + 9 < buf.length) {
|
|
117
|
+
if (buf[pos] !== 0xff)
|
|
118
|
+
return null; // not on a marker boundary; give up safely
|
|
119
|
+
const marker = buf[pos + 1];
|
|
120
|
+
// SOF0..SOF15 carry the frame size. C4/C8/CC share the range but are tables.
|
|
121
|
+
if (marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc) {
|
|
122
|
+
return { width: buf.readUInt16BE(pos + 7), height: buf.readUInt16BE(pos + 5) };
|
|
123
|
+
}
|
|
124
|
+
const segment = buf.readUInt16BE(pos + 2);
|
|
125
|
+
if (segment < 2)
|
|
126
|
+
return null; // malformed length would loop forever
|
|
127
|
+
pos += 2 + segment;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Turn a path into an `ImageRef`, or explain why not. Does the format check, the size
|
|
134
|
+
* check and the dimension read in one pass so callers get a single verdict.
|
|
135
|
+
*/
|
|
136
|
+
export async function describeImage(path, sizeBytes) {
|
|
137
|
+
const mediaType = mediaTypeFor(path);
|
|
138
|
+
if (!mediaType) {
|
|
139
|
+
return { reason: `${extname(path).toLowerCase() || "that format"} images can't be sent to a model` };
|
|
140
|
+
}
|
|
141
|
+
if (sizeBytes > MAX_IMAGE_BYTES) {
|
|
142
|
+
return { reason: `too large to send (${formatMb(sizeBytes)}, limit ${formatMb(MAX_IMAGE_BYTES)})` };
|
|
143
|
+
}
|
|
144
|
+
const dims = await readHeader(path);
|
|
145
|
+
if (dims && (dims.width > MAX_IMAGE_EDGE || dims.height > MAX_IMAGE_EDGE)) {
|
|
146
|
+
return { reason: `too big to send (${dims.width}x${dims.height}, limit ${MAX_IMAGE_EDGE}px per side)` };
|
|
147
|
+
}
|
|
148
|
+
return { path, mediaType, ...(dims ?? {}) };
|
|
149
|
+
}
|
|
150
|
+
/** True when a verdict from `describeImage` is a refusal rather than a ref. */
|
|
151
|
+
export function isRejection(v) {
|
|
152
|
+
return "reason" in v;
|
|
153
|
+
}
|
|
154
|
+
/** Read just enough of the file to find its dimensions. */
|
|
155
|
+
async function readHeader(path) {
|
|
156
|
+
let handle;
|
|
157
|
+
try {
|
|
158
|
+
handle = await fs.open(path, "r");
|
|
159
|
+
const buf = Buffer.alloc(65536);
|
|
160
|
+
const { bytesRead } = await handle.read(buf, 0, buf.length, 0);
|
|
161
|
+
return readDimensions(buf.subarray(0, bytesRead));
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return null; // unreadable header is not fatal — the estimator assumes the cap
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
await handle?.close();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function formatMb(n) {
|
|
171
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../../src/memory/images.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;GAIG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAiB;IAC1C,CAAC,MAAM,EAAE,WAAW,CAAC;IACrB,CAAC,MAAM,EAAE,YAAY,CAAC;IACtB,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,MAAM,EAAE,WAAW,CAAC;IACrB,CAAC,OAAO,EAAE,YAAY,CAAC;CACxB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IAChC,GAAG,WAAW,CAAC,IAAI,EAAE;IACrB,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;AAE7D,uFAAuF;AACvF,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAgBnC,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,MAAM,UAAU,mBAAmB,CAAC,GAAa;IAC/C,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,gBAAgB,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;IACnF,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,oBAAoB,CAAC,IAAqC;IACxE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,yEAAyE;IACzE,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QAC3D,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;IACvE,CAAC;IAED,uEAAuE;IACvE,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QAC9D,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,CAAC;IAED,6EAA6E;IAC7E,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACtD,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC,CAAC,2CAA2C;YAC/E,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAE,CAAC;YAC7B,6EAA6E;YAC7E,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC9F,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YACjF,CAAC;YACD,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAC1C,IAAI,OAAO,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC,CAAC,sCAAsC;YACpE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAKD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,SAAiB;IACjE,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,aAAa,kCAAkC,EAAE,CAAC;IACvG,CAAC;IACD,IAAI,SAAS,GAAG,eAAe,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,sBAAsB,QAAQ,CAAC,SAAS,CAAC,WAAW,QAAQ,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC;IACtG,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,cAAc,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC;QAC1E,OAAO,EAAE,MAAM,EAAE,oBAAoB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,WAAW,cAAc,cAAc,EAAE,CAAC;IAC1G,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,CAA4B;IACtD,OAAO,QAAQ,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,2DAA2D;AAC3D,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/D,OAAO,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,iEAAiE;IAChF,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { fullPathsOf } from "./types.js";
|
|
2
|
+
import { CLEARED_STUB } from "./compaction.js";
|
|
3
|
+
/**
|
|
4
|
+
* The set of absolute paths whose WHOLE content is still present in the transcript:
|
|
5
|
+
* a `read_file` call with no `offset`/`limit`, whose result has not been cleared to a
|
|
6
|
+
* stub by microcompaction.
|
|
7
|
+
*
|
|
8
|
+
* Pure. `resolve` turns the call's recorded (possibly relative or labelled) path into
|
|
9
|
+
* the same absolute key the read ledger uses; it returns undefined for anything it
|
|
10
|
+
* cannot resolve, which is simply left out.
|
|
11
|
+
*/
|
|
12
|
+
export function fullReadPaths(entries, resolve) {
|
|
13
|
+
const callById = new Map();
|
|
14
|
+
for (const e of entries) {
|
|
15
|
+
if (e.role === "assistant" && e.toolCalls) {
|
|
16
|
+
for (const tc of e.toolCalls)
|
|
17
|
+
callById.set(tc.id, { name: tc.name, arguments: tc.arguments });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const present = new Set();
|
|
21
|
+
for (const e of entries) {
|
|
22
|
+
if (e.role !== "tool")
|
|
23
|
+
continue;
|
|
24
|
+
// A cleared body is a stub: the entry survives for navigation, the content does not.
|
|
25
|
+
if (e.content.includes(CLEARED_STUB))
|
|
26
|
+
continue;
|
|
27
|
+
// The tool recorded which file this result IS, at the moment it was true. Exact:
|
|
28
|
+
// no re-resolution, so a `cd` since then cannot make it point somewhere else.
|
|
29
|
+
const recorded = fullPathsOf(e);
|
|
30
|
+
if (recorded.length > 0) {
|
|
31
|
+
for (const path of recorded)
|
|
32
|
+
present.add(path);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Fallback for sessions written before results carried that fact. Re-resolving the
|
|
36
|
+
// arguments is a guess about where a relative path pointed at the time, so it is
|
|
37
|
+
// used only when there is nothing better, never in preference to the recording.
|
|
38
|
+
const call = callById.get(e.toolCallId ?? "");
|
|
39
|
+
if (!call || call.name !== "read_file")
|
|
40
|
+
continue;
|
|
41
|
+
let args;
|
|
42
|
+
try {
|
|
43
|
+
args = JSON.parse(call.arguments);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
continue; // malformed args — nothing to claim
|
|
47
|
+
}
|
|
48
|
+
// A ranged read put only a window in the transcript, not the whole file.
|
|
49
|
+
if (args.offset !== undefined || args.limit !== undefined)
|
|
50
|
+
continue;
|
|
51
|
+
if (typeof args.path !== "string")
|
|
52
|
+
continue;
|
|
53
|
+
const abs = resolve(args.path);
|
|
54
|
+
if (abs)
|
|
55
|
+
present.add(abs);
|
|
56
|
+
}
|
|
57
|
+
return present;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=presence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/memory/presence.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,OAA6C;IAC3F,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA+C,CAAC;IACxE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAC1C,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,SAAS;gBAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAChC,qFAAqF;QACrF,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,SAAS;QAE/C,iFAAiF;QACjF,8EAA8E;QAC9E,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,MAAM,IAAI,IAAI,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/C,SAAS;QACX,CAAC;QAED,mFAAmF;QACnF,iFAAiF;QACjF,gFAAgF;QAChF,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QACjD,IAAI,IAA2D,CAAC;QAChE,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAgB,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,oCAAoC;QAChD,CAAC;QACD,yEAAyE;QACzE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,SAAS;QACpE,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,GAAG;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* projectNotes.ts — MINDWEAVE.md, and the files it pulls in.
|
|
3
|
+
*
|
|
4
|
+
* MINDWEAVE.md is the project's living notebook: what it is, how to run and test it,
|
|
5
|
+
* the conventions in play, where things stand. It is loaded for the agent at the start
|
|
6
|
+
* of every session, which is what makes a new conversation continue rather than start
|
|
7
|
+
* over. `/init` writes the first one; the agent maintains it after that.
|
|
8
|
+
*
|
|
9
|
+
* It began as exactly one file at the project root, read whole. That works until a real
|
|
10
|
+
* project has more to say than fits in one readable page, at which point the single file
|
|
11
|
+
* becomes either too long to keep accurate or too short to be worth loading. Three
|
|
12
|
+
* layers fix that without loading everything always:
|
|
13
|
+
*
|
|
14
|
+
* - **Imports.** `@./docs/architecture.md` inside a notes file pulls that file in.
|
|
15
|
+
* Split the notes the way the project is split, and the parts still arrive as one
|
|
16
|
+
* document.
|
|
17
|
+
* - **A personal layer.** `~/.mindweave/MINDWEAVE.md` applies to every project on the
|
|
18
|
+
* machine, for the things that are true of how YOU work rather than of one codebase.
|
|
19
|
+
* - **Per-directory notes.** A MINDWEAVE.md inside a folder describes that folder, and
|
|
20
|
+
* is delivered only while the agent is actually working in it.
|
|
21
|
+
*
|
|
22
|
+
* The first two are assembled here into the text loaded at session start. The third is
|
|
23
|
+
* resolved per turn against the files in play, and is deliberately NOT part of that
|
|
24
|
+
* text: see `directoryNotesFor`.
|
|
25
|
+
*
|
|
26
|
+
* The import rules are the ones this syntax conventionally carries, so nobody who has
|
|
27
|
+
* written a notes file before is surprised: `@path` in ordinary prose, depth capped,
|
|
28
|
+
* cycles broken, and — the part that is easy to miss — **never inside code**. A notes
|
|
29
|
+
* file that documents an npm scope or a decorator would otherwise try to import
|
|
30
|
+
* `@types` as a path.
|
|
31
|
+
*/
|
|
32
|
+
import { promises as fs } from "node:fs";
|
|
33
|
+
import { homedir } from "node:os";
|
|
34
|
+
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
35
|
+
/** The one filename, everywhere. */
|
|
36
|
+
export const NOTES_FILE = "MINDWEAVE.md";
|
|
37
|
+
/**
|
|
38
|
+
* How far an import chain may go before it stops.
|
|
39
|
+
*
|
|
40
|
+
* Five. A notes file importing a file that imports another is normal; five levels of it
|
|
41
|
+
* is a structure nobody is reading, and the cap is what stops a mistake from pulling in
|
|
42
|
+
* a whole documentation tree.
|
|
43
|
+
*/
|
|
44
|
+
export const MAX_IMPORT_DEPTH = 5;
|
|
45
|
+
/**
|
|
46
|
+
* Ceiling on the assembled notes.
|
|
47
|
+
*
|
|
48
|
+
* The pressure here runs one way: a file loaded every session, maintained by an agent
|
|
49
|
+
* rewarded for thoroughness, told to keep it concise by a sentence nothing enforces.
|
|
50
|
+
* Imports make that worse, because the size is now spread across files nobody sees
|
|
51
|
+
* together. This is the enforcement, and it is generous — roughly 4K tokens for "facts
|
|
52
|
+
* about this codebase".
|
|
53
|
+
*/
|
|
54
|
+
export const MAX_NOTES_CHARS = 16_000;
|
|
55
|
+
/**
|
|
56
|
+
* Pull the `@path` imports out of a notes file.
|
|
57
|
+
*
|
|
58
|
+
* Only from prose. Fenced blocks and inline code are skipped, because a notes file is
|
|
59
|
+
* exactly the kind of document that quotes `@scope/package`, `@Component`, or an email
|
|
60
|
+
* address, and treating those as file paths would produce a confusing failure in the
|
|
61
|
+
* one file whose whole job is to be trusted.
|
|
62
|
+
*
|
|
63
|
+
* `@~/x` is the user's home, `@/x` is absolute, `@./x` and `@x` are relative to the
|
|
64
|
+
* importing file. A `#fragment` is dropped, and `\ ` is an escaped space, both so a
|
|
65
|
+
* path written for a human still resolves.
|
|
66
|
+
*/
|
|
67
|
+
export function importPathsIn(text, fromFile) {
|
|
68
|
+
const prose = stripCode(text);
|
|
69
|
+
const found = [];
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
// Must follow start-of-line or whitespace: `foo@bar.md` is an address, not an import.
|
|
72
|
+
const re = /(?:^|\s)@((?:[^\s\\]|\\ )+)/g;
|
|
73
|
+
let m;
|
|
74
|
+
while ((m = re.exec(prose)) !== null) {
|
|
75
|
+
const raw = m[1];
|
|
76
|
+
if (!raw)
|
|
77
|
+
continue;
|
|
78
|
+
const hash = raw.indexOf("#");
|
|
79
|
+
const cleaned = (hash === -1 ? raw : raw.slice(0, hash)).replace(/\\ /g, " ");
|
|
80
|
+
if (!cleaned || cleaned === "/" || cleaned.startsWith("@"))
|
|
81
|
+
continue;
|
|
82
|
+
const abs = resolveImport(cleaned, fromFile);
|
|
83
|
+
if (!abs || seen.has(abs))
|
|
84
|
+
continue;
|
|
85
|
+
seen.add(abs);
|
|
86
|
+
found.push(abs);
|
|
87
|
+
}
|
|
88
|
+
return found;
|
|
89
|
+
}
|
|
90
|
+
function resolveImport(path, fromFile) {
|
|
91
|
+
if (path.startsWith("~/"))
|
|
92
|
+
return resolve(homedir(), path.slice(2));
|
|
93
|
+
if (isAbsolute(path))
|
|
94
|
+
return resolve(path);
|
|
95
|
+
return resolve(dirname(fromFile), path);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Remove fenced blocks and inline code so their contents cannot be read as imports.
|
|
99
|
+
*
|
|
100
|
+
* Replaced with blank lines rather than deleted, so nothing on a later line shifts into
|
|
101
|
+
* a position it was not written in — an `@path` at the start of a line must still look
|
|
102
|
+
* like one after this runs.
|
|
103
|
+
*/
|
|
104
|
+
function stripCode(text) {
|
|
105
|
+
const blanked = text.replace(/```[\s\S]*?(?:```|$)/g, (block) => block.replace(/[^\n]/g, " "));
|
|
106
|
+
return blanked.replace(/`[^`\n]*`/g, (span) => span.replace(/[^\n]/g, " "));
|
|
107
|
+
}
|
|
108
|
+
async function readIfPresent(path) {
|
|
109
|
+
try {
|
|
110
|
+
const text = await fs.readFile(path, "utf8");
|
|
111
|
+
return text.trim() ? text : null;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Read one notes file and everything it imports, depth-first.
|
|
119
|
+
*
|
|
120
|
+
* `seen` carries across the whole assembly rather than per branch, so a file imported
|
|
121
|
+
* from two places is included once and a cycle simply stops. Both are the same
|
|
122
|
+
* mechanism, which is why an import loop is not a special case here.
|
|
123
|
+
*/
|
|
124
|
+
async function collect(path, kind, seen, out, missing, depth, importedBy) {
|
|
125
|
+
const key = normalize(path).toLowerCase();
|
|
126
|
+
if (seen.has(key) || depth >= MAX_IMPORT_DEPTH)
|
|
127
|
+
return;
|
|
128
|
+
seen.add(key);
|
|
129
|
+
const body = await readIfPresent(path);
|
|
130
|
+
if (body === null) {
|
|
131
|
+
// Only an IMPORT is worth reporting. A project with no notes file at all, or a
|
|
132
|
+
// user who keeps none, is the ordinary case and not a problem.
|
|
133
|
+
if (kind === "import")
|
|
134
|
+
missing.push(path);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
out.push({ source: { path, kind, ...(importedBy ? { importedBy } : {}) }, body: body.trim() });
|
|
138
|
+
for (const target of importPathsIn(body, path)) {
|
|
139
|
+
await collect(target, "import", seen, out, missing, depth + 1, path);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Where the machine-wide notes live, beside the config the app already keeps there. */
|
|
143
|
+
export function userNotesPath(stateDir = join(homedir(), ".mindweave")) {
|
|
144
|
+
return join(stateDir, NOTES_FILE);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Assemble the notes a session starts with: the user's, then the project's, plus
|
|
148
|
+
* everything either imports.
|
|
149
|
+
*
|
|
150
|
+
* The user's layer comes FIRST and the project's second, because when the two disagree
|
|
151
|
+
* the project should win, and a model reading in order treats what it read last as more
|
|
152
|
+
* specific. Each file is headed with where it came from — without that, a rule from the
|
|
153
|
+
* home directory looks like it came from the repository, and someone debugging why the
|
|
154
|
+
* agent insists on something has nowhere to look.
|
|
155
|
+
*/
|
|
156
|
+
export async function assembleNotes(cwd, opts = {}) {
|
|
157
|
+
const seen = new Set();
|
|
158
|
+
const parts = [];
|
|
159
|
+
const missing = [];
|
|
160
|
+
if (opts.includeUser !== false) {
|
|
161
|
+
await collect(userNotesPath(opts.stateDir), "user", seen, parts, missing, 0);
|
|
162
|
+
}
|
|
163
|
+
await collect(join(cwd, NOTES_FILE), "project", seen, parts, missing, 0);
|
|
164
|
+
if (parts.length === 0)
|
|
165
|
+
return { text: "", sources: [], truncated: false, missing };
|
|
166
|
+
const blocks = parts.map(({ source, body }) => {
|
|
167
|
+
if (source.kind === "project")
|
|
168
|
+
return body;
|
|
169
|
+
const label = source.kind === "user"
|
|
170
|
+
? `${NOTES_FILE} (yours, applies to every project)`
|
|
171
|
+
: `imported from ${displayPath(source.path, cwd)}`;
|
|
172
|
+
return `--- ${label} ---\n${body}`;
|
|
173
|
+
});
|
|
174
|
+
// A named import that is not there is worth saying. Silence would leave the agent
|
|
175
|
+
// told to "see the architecture notes" with no architecture notes and no idea why.
|
|
176
|
+
if (missing.length > 0) {
|
|
177
|
+
const list = missing.map((p) => displayPath(p, cwd)).join(", ");
|
|
178
|
+
blocks.push(`[These notes import ${list}, which could not be read. That part is missing.]`);
|
|
179
|
+
}
|
|
180
|
+
return capped(blocks.join("\n\n"), parts.map((p) => p.source), missing);
|
|
181
|
+
}
|
|
182
|
+
/** A path as a person would refer to it: inside the project, relative; outside, whole. */
|
|
183
|
+
function displayPath(path, cwd) {
|
|
184
|
+
const rel = relative(cwd, path);
|
|
185
|
+
return rel && !rel.startsWith("..") ? rel.split(sep).join("/") : path;
|
|
186
|
+
}
|
|
187
|
+
function capped(text, sources, missing) {
|
|
188
|
+
if (text.length <= MAX_NOTES_CHARS)
|
|
189
|
+
return { text, sources, truncated: false, missing };
|
|
190
|
+
const cut = text.slice(0, MAX_NOTES_CHARS);
|
|
191
|
+
const atLine = cut.slice(0, cut.lastIndexOf("\n") + 1) || cut;
|
|
192
|
+
return {
|
|
193
|
+
text: `${atLine.trimEnd()}\n\n[The project notes are longer than fits here and were truncated at ` +
|
|
194
|
+
`this point. Read the file directly if you need the rest, and consider trimming it.]`,
|
|
195
|
+
sources,
|
|
196
|
+
truncated: true,
|
|
197
|
+
missing,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* The per-directory notes that apply to a set of files being worked on.
|
|
202
|
+
*
|
|
203
|
+
* For each file, every directory from the project root down to the file's own folder is
|
|
204
|
+
* checked for a MINDWEAVE.md. A note in `src/api/` therefore reaches the agent exactly
|
|
205
|
+
* when it opens something in `src/api/`, and not before — which is the point. Loading
|
|
206
|
+
* every folder's notes at session start would cost the whole budget to say things about
|
|
207
|
+
* code nobody is touching.
|
|
208
|
+
*
|
|
209
|
+
* The root's own file is excluded: it is already loaded at session start, and including
|
|
210
|
+
* it here would send it twice.
|
|
211
|
+
*
|
|
212
|
+
* Returned rather than concatenated into the session prompt on purpose. These change as
|
|
213
|
+
* the agent moves around a repository, and anything that changes mid-session belongs in
|
|
214
|
+
* the volatile part of the request; folding it into the cached prefix would rewrite that
|
|
215
|
+
* prefix every time the agent opened a file in a new folder, which is the single most
|
|
216
|
+
* expensive thing a turn can do.
|
|
217
|
+
*/
|
|
218
|
+
export async function directoryNotesFor(root, files) {
|
|
219
|
+
const dirs = new Set();
|
|
220
|
+
for (const file of files) {
|
|
221
|
+
const abs = isAbsolute(file) ? file : resolve(root, file);
|
|
222
|
+
const rel = relative(root, abs);
|
|
223
|
+
// Outside the project entirely, or the project root itself.
|
|
224
|
+
if (!rel || rel.startsWith(".."))
|
|
225
|
+
continue;
|
|
226
|
+
let dir = dirname(abs);
|
|
227
|
+
while (dir.length >= root.length) {
|
|
228
|
+
if (normalize(dir) !== normalize(root))
|
|
229
|
+
dirs.add(dir);
|
|
230
|
+
const up = dirname(dir);
|
|
231
|
+
if (up === dir)
|
|
232
|
+
break;
|
|
233
|
+
dir = up;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const out = [];
|
|
237
|
+
// Shallowest first: a folder's notes should read before the notes of a folder inside
|
|
238
|
+
// it, so the more specific text is the last thing the model sees.
|
|
239
|
+
for (const dir of [...dirs].sort((a, b) => a.length - b.length)) {
|
|
240
|
+
const path = join(dir, NOTES_FILE);
|
|
241
|
+
const body = await readIfPresent(path);
|
|
242
|
+
if (body !== null)
|
|
243
|
+
out.push({ path, text: body.trim() });
|
|
244
|
+
}
|
|
245
|
+
return out;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=projectNotes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectNotes.js","sourceRoot":"","sources":["../../src/memory/projectNotes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const env = (name, fallback) => {
|
|
2
|
+
const v = Number(process.env[name]);
|
|
3
|
+
return Number.isFinite(v) && v > 0 ? v : fallback;
|
|
4
|
+
};
|
|
5
|
+
/** Most files worth putting back. Past a handful this stops being "where I was" and
|
|
6
|
+
* becomes a second copy of the working set, which is what was removed for costing
|
|
7
|
+
* 12K on every model call. */
|
|
8
|
+
export const RESTORE_MAX_FILES = env("MINDWEAVE_RESTORE_MAX_FILES", 5);
|
|
9
|
+
/** Per-file ceiling. A single large file must not spend the whole budget. */
|
|
10
|
+
export const RESTORE_MAX_TOKENS_PER_FILE = env("MINDWEAVE_RESTORE_FILE_TOKENS", 3_000);
|
|
11
|
+
/**
|
|
12
|
+
* Total ceiling, before the model-anchored cap below is applied.
|
|
13
|
+
*
|
|
14
|
+
* 12K rather than the 50K a state-of-the-art client uses, and the difference is
|
|
15
|
+
* arithmetic rather than taste. Restored content is written once and then carried in
|
|
16
|
+
* the cached prefix for the rest of the session, so its cost is the write plus the
|
|
17
|
+
* carry. At 50K that totals more than a dozen saved re-read round trips on every model
|
|
18
|
+
* priced here — and since at most five files are restored, five round trips is the most
|
|
19
|
+
* it can ever save. A 50K budget cannot break even at any hit rate. 12K breaks even at
|
|
20
|
+
* roughly three of five.
|
|
21
|
+
*/
|
|
22
|
+
export const RESTORE_BUDGET_TOKENS = env("MINDWEAVE_RESTORE_BUDGET", 12_000);
|
|
23
|
+
/** Never let restoration take more than this share of the room compaction just made. */
|
|
24
|
+
const RESTORE_MAX_SHARE_OF_BAR = 0.15;
|
|
25
|
+
/** What restoration may spend for a given autocompact bar (pure). */
|
|
26
|
+
export function restoreBudgetFor(autoBar) {
|
|
27
|
+
return Math.min(RESTORE_BUDGET_TOKENS, Math.round(autoBar * RESTORE_MAX_SHARE_OF_BAR));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Choose which files to put back after a compaction (pure).
|
|
31
|
+
*
|
|
32
|
+
* `stillVisible` is what the kept tail already shows the model. Re-sending a file it
|
|
33
|
+
* can see costs its full length and buys nothing; the same diff-against-what-survived
|
|
34
|
+
* that a state-of-the-art client applies, and worth up to a whole budget on its own.
|
|
35
|
+
*/
|
|
36
|
+
export function selectForRestore(reads, stillVisible = new Set(), excluded = () => false, maxFiles = RESTORE_MAX_FILES) {
|
|
37
|
+
const candidates = [];
|
|
38
|
+
for (const [path, record] of reads) {
|
|
39
|
+
// A grep hit is not a read: it showed matching lines, never the file, so there is
|
|
40
|
+
// no "content the model had" to put back.
|
|
41
|
+
if (record.viaSearch)
|
|
42
|
+
continue;
|
|
43
|
+
// A ranged read never covered the whole file, so restoring it whole would hand the
|
|
44
|
+
// model more than it ever had and quietly reset what it believes it has seen.
|
|
45
|
+
if (!record.full)
|
|
46
|
+
continue;
|
|
47
|
+
if (stillVisible.has(path))
|
|
48
|
+
continue;
|
|
49
|
+
if (excluded(path))
|
|
50
|
+
continue;
|
|
51
|
+
candidates.push({ path, worked: (record.focus?.length ?? 0) > 0 });
|
|
52
|
+
}
|
|
53
|
+
const touchedAt = (path) => reads.get(path)?.touchedAt ?? 0;
|
|
54
|
+
// Worked-in files first, then by recency within each group. Recency alone is the
|
|
55
|
+
// selector this deliberately avoids; it is used only to break ties.
|
|
56
|
+
candidates.sort((a, b) => (a.worked === b.worked ? touchedAt(b.path) - touchedAt(a.path) : a.worked ? -1 : 1));
|
|
57
|
+
return candidates.slice(0, maxFiles);
|
|
58
|
+
}
|
|
59
|
+
/** Wrap restored contents for the transcript (pure).
|
|
60
|
+
*
|
|
61
|
+
* Says plainly that this is a restoration rather than something the model read, so it
|
|
62
|
+
* cannot mistake the block for its own earlier work, and states the one fact that
|
|
63
|
+
* makes the ledger reconciliation legible from the model's side: everything else it
|
|
64
|
+
* had open is gone and has to be read again. */
|
|
65
|
+
export function renderRestored(files) {
|
|
66
|
+
const blocks = files.map((f) => `<file path="${f.path}">\n${f.content}\n</file>`).join("\n\n");
|
|
67
|
+
return ("The files you were working in, restored after the compaction above so you can " +
|
|
68
|
+
"carry on without re-reading them. Any OTHER file you had open is no longer in " +
|
|
69
|
+
"context: read it again before you edit it.\n\n" +
|
|
70
|
+
`<restored_files>\n${blocks}\n</restored_files>`);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=restore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore.js","sourceRoot":"","sources":["../../src/memory/restore.ts"],"names":[],"mappings":"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"}
|