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,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bootstrap.ts — make `mindweave` runnable from any directory.
|
|
3
|
+
*
|
|
4
|
+
* The whole point of a global command is that you `cd` into ANY project, type
|
|
5
|
+
* `mindweave`, and it works — including the API key. A random project won't carry
|
|
6
|
+
* Mindweave's `.env`, so the key has to live somewhere global. We layer config the
|
|
7
|
+
* way every CLI does, lowest priority first:
|
|
8
|
+
*
|
|
9
|
+
* 1. ~/.mindweave/.env — the global store (write your key here once).
|
|
10
|
+
* 2. <project>/.env — per-project overrides (optional).
|
|
11
|
+
* 3. real shell env — always wins (export a provider's key for a one-off).
|
|
12
|
+
*
|
|
13
|
+
* We parse `.env` ourselves (a tiny, dependency-free reader) so we control that
|
|
14
|
+
* precedence exactly: a value is only applied if the variable isn't already set,
|
|
15
|
+
* and we load project before global — so shell > project > global falls out
|
|
16
|
+
* naturally. On first run we also drop a commented template at ~/.mindweave/.env so
|
|
17
|
+
* the user has an obvious place to paste their key.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { stateRoot } from "../memory/store.js";
|
|
22
|
+
import { allProviders } from "../drivers/registry.js";
|
|
23
|
+
import { keysFor, slotVar } from "./keyStore.js";
|
|
24
|
+
/**
|
|
25
|
+
* The global Mindweave config directory (~/.mindweave).
|
|
26
|
+
*
|
|
27
|
+
* The SAME directory the state lives in, and now the same function that resolves it.
|
|
28
|
+
* They were computed separately and only one honoured `MINDWEAVE_STATE_DIR`, so a test
|
|
29
|
+
* run — or anyone relocating Mindweave's files — moved the sessions and left the config
|
|
30
|
+
* behind in the real home. The suite creates this template, which meant a clean machine
|
|
31
|
+
* got a config file written into `~/.mindweave` by `npm test`: exactly the pollution
|
|
32
|
+
* scripts/testState.mjs exists to prevent, still open on the config side.
|
|
33
|
+
*/
|
|
34
|
+
export function globalConfigDir() {
|
|
35
|
+
return stateRoot();
|
|
36
|
+
}
|
|
37
|
+
/** The global env file (~/.mindweave/.env) — where the API key lives. */
|
|
38
|
+
export function globalEnvPath() {
|
|
39
|
+
return join(globalConfigDir(), ".env");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Load configuration into process.env. Call once, before anything reads a key.
|
|
43
|
+
* Order matters: project first, then global, each set-if-absent, so already-set
|
|
44
|
+
* shell variables win and a project `.env` overrides the global one.
|
|
45
|
+
*/
|
|
46
|
+
export function loadConfig(cwd = process.cwd()) {
|
|
47
|
+
ensureGlobalTemplate();
|
|
48
|
+
reloadConfig(cwd);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Re-read the env files into process.env without recreating the template. Used to
|
|
52
|
+
* pick up a key the user just pasted while Mindweave is already running — once a real
|
|
53
|
+
* key appears we adopt it with no restart. (Empty values are ignored, so the
|
|
54
|
+
* blank key lines in the fresh template never count as "set".)
|
|
55
|
+
*/
|
|
56
|
+
export function reloadConfig(cwd = process.cwd()) {
|
|
57
|
+
applyEnvFile(join(cwd, ".env"));
|
|
58
|
+
applyEnvFile(globalEnvPath());
|
|
59
|
+
activateStoredKeys();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Point each provider at its first stored key, unless something already has.
|
|
63
|
+
*
|
|
64
|
+
* Storage is `VAR_1..VAR_9` and the LIVE key is the bare `VAR` that every driver reads —
|
|
65
|
+
* two roles, deliberately two variables. Nothing on disk fills the live one, so without
|
|
66
|
+
* this a key added through /key would be written, reloaded, and then invisible on the
|
|
67
|
+
* next launch: the app would ask for a key it already had.
|
|
68
|
+
*
|
|
69
|
+
* Set-if-absent, so a shell export still wins and a key chosen for this session with
|
|
70
|
+
* /key is not overwritten by a later reload.
|
|
71
|
+
*/
|
|
72
|
+
function activateStoredKeys() {
|
|
73
|
+
for (const provider of allProviders()) {
|
|
74
|
+
if (process.env[provider.apiKeyEnv]?.trim())
|
|
75
|
+
continue;
|
|
76
|
+
const first = keysFor(provider.apiKeyEnv)[0];
|
|
77
|
+
if (first)
|
|
78
|
+
process.env[provider.apiKeyEnv] = first.value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* True once the named provider's key is available from any source.
|
|
83
|
+
*
|
|
84
|
+
* The variable name is a parameter rather than a constant because which key is
|
|
85
|
+
* needed depends on which model the user is about to run — each provider declares
|
|
86
|
+
* its own in its manifest. This module stays a plain config utility and never
|
|
87
|
+
* imports the driver registry.
|
|
88
|
+
*/
|
|
89
|
+
export function hasApiKey(envVar) {
|
|
90
|
+
return Boolean(process.env[envVar]);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Persist a key the user typed in the terminal: write it into ~/.mindweave/.env (so
|
|
94
|
+
* it's there next launch too) and apply it to this process right away (so the
|
|
95
|
+
* chat can start immediately — no restart). Updates that provider's line in place,
|
|
96
|
+
* preserving every other line, so adding a second provider's key never disturbs
|
|
97
|
+
* the first one.
|
|
98
|
+
*/
|
|
99
|
+
/**
|
|
100
|
+
* Write a variable into the global env file, or remove it when `value` is null.
|
|
101
|
+
*
|
|
102
|
+
* One place, because saving and removing have to agree about the file's shape — a
|
|
103
|
+
* remover that only deleted from `process.env` would leave the key on disk and it would
|
|
104
|
+
* come back on the next launch.
|
|
105
|
+
*/
|
|
106
|
+
function writeEnvVar(envVar, value) {
|
|
107
|
+
const NL = String.fromCharCode(10);
|
|
108
|
+
const dir = globalConfigDir();
|
|
109
|
+
if (!existsSync(dir))
|
|
110
|
+
mkdirSync(dir, { recursive: true });
|
|
111
|
+
const path = globalEnvPath();
|
|
112
|
+
let existing = "";
|
|
113
|
+
try {
|
|
114
|
+
existing = readFileSync(path, "utf8");
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
/* no file yet */
|
|
118
|
+
}
|
|
119
|
+
// Find the variable's line the way applyEnvFile READS it: leading spaces or tabs, and
|
|
120
|
+
// an optional `export ` prefix, are both accepted there. A writer that matched neither
|
|
121
|
+
// would fail to find a line the reader had loaded, append a second one, and let the
|
|
122
|
+
// stale line win on the next launch — a key updated in the app but not on disk. Only
|
|
123
|
+
// spaces and tabs, never `\s`, so the match cannot run across a line break.
|
|
124
|
+
const body = `(?:export[ \\t]+)?${envVar}=`;
|
|
125
|
+
let next;
|
|
126
|
+
if (value === null) {
|
|
127
|
+
// Take the trailing newline with the line, then collapse any blank run left behind.
|
|
128
|
+
const remove = new RegExp(`^[ \\t]*${body}.*(?:\\r?\\n|$)`, "m");
|
|
129
|
+
next = existing.replace(remove, "").replace(new RegExp(`${NL}{3,}`, "g"), NL + NL);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const line = `${envVar}=${value}`;
|
|
133
|
+
const replace = new RegExp(`^[ \\t]*${body}.*$`, "m");
|
|
134
|
+
next = replace.test(existing)
|
|
135
|
+
? existing.replace(replace, line)
|
|
136
|
+
: (existing ? existing.replace(/\s*$/, NL) : "") + line + NL;
|
|
137
|
+
}
|
|
138
|
+
writeFileSync(path, next, { mode: 0o600 });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Move a bare `VAR=value` into `VAR_1`, once, so storage and the live key stop sharing a
|
|
142
|
+
* variable. An existing config or a shell export arrives that way; everything written
|
|
143
|
+
* after this point is numbered.
|
|
144
|
+
*/
|
|
145
|
+
function normalizeLegacy(apiKeyEnv) {
|
|
146
|
+
const bare = process.env[apiKeyEnv]?.trim();
|
|
147
|
+
if (!bare)
|
|
148
|
+
return;
|
|
149
|
+
if (process.env[slotVar(apiKeyEnv, 1)]?.trim())
|
|
150
|
+
return;
|
|
151
|
+
process.env[slotVar(apiKeyEnv, 1)] = bare;
|
|
152
|
+
writeEnvVar(slotVar(apiKeyEnv, 1), bare);
|
|
153
|
+
writeEnvVar(apiKeyEnv, null);
|
|
154
|
+
}
|
|
155
|
+
/** Store a key in a slot. Slot 1 also becomes the live key when nothing else is. */
|
|
156
|
+
export function saveApiKey(apiKeyEnv, key, slot = 1) {
|
|
157
|
+
const trimmed = key.trim();
|
|
158
|
+
if (!trimmed)
|
|
159
|
+
return;
|
|
160
|
+
normalizeLegacy(apiKeyEnv);
|
|
161
|
+
const envVar = slotVar(apiKeyEnv, slot);
|
|
162
|
+
process.env[envVar] = trimmed;
|
|
163
|
+
writeEnvVar(envVar, trimmed);
|
|
164
|
+
if (!process.env[apiKeyEnv]?.trim() || slot === 1)
|
|
165
|
+
process.env[apiKeyEnv] = trimmed;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Remove one stored key, closing the gap behind it.
|
|
169
|
+
*
|
|
170
|
+
* Slots are renumbered so there is never a hole: with `_2` gone, `_3` becomes `_2`. A
|
|
171
|
+
* hole reads fine to a program and badly to a person opening the file. Cleared first and
|
|
172
|
+
* rewritten from 1, because renumbering in place would overwrite a value before it had
|
|
173
|
+
* been moved.
|
|
174
|
+
*/
|
|
175
|
+
export function removeApiKey(apiKeyEnv, slot) {
|
|
176
|
+
normalizeLegacy(apiKeyEnv);
|
|
177
|
+
const before = keysFor(apiKeyEnv);
|
|
178
|
+
const live = process.env[apiKeyEnv]?.trim();
|
|
179
|
+
const remaining = before.filter((k) => k.slot !== slot);
|
|
180
|
+
for (const k of before) {
|
|
181
|
+
delete process.env[k.envVar];
|
|
182
|
+
writeEnvVar(k.envVar, null);
|
|
183
|
+
}
|
|
184
|
+
remaining.forEach((k, i) => {
|
|
185
|
+
const envVar = slotVar(apiKeyEnv, i + 1);
|
|
186
|
+
process.env[envVar] = k.value;
|
|
187
|
+
writeEnvVar(envVar, k.value);
|
|
188
|
+
});
|
|
189
|
+
// Removing the key that was in use must not leave the provider pointing at nothing.
|
|
190
|
+
if (!remaining.some((k) => k.value === live)) {
|
|
191
|
+
if (remaining[0])
|
|
192
|
+
process.env[apiKeyEnv] = remaining[0].value;
|
|
193
|
+
else
|
|
194
|
+
delete process.env[apiKeyEnv];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Make a stored key the one the drivers send, for this session.
|
|
199
|
+
*
|
|
200
|
+
* Assigned into the variable they already read, and the stored slots are left alone: a
|
|
201
|
+
* key that is merely rate-limited today belongs back in its usual place tomorrow, and
|
|
202
|
+
* choosing one should not reorder a file the user maintains.
|
|
203
|
+
*/
|
|
204
|
+
export function useApiKey(apiKeyEnv, slot) {
|
|
205
|
+
const found = keysFor(apiKeyEnv).find((k) => k.slot === slot);
|
|
206
|
+
if (!found)
|
|
207
|
+
return false;
|
|
208
|
+
process.env[apiKeyEnv] = found.value;
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* What lands in ~/.mindweave/.env the first time Mindweave runs.
|
|
213
|
+
*
|
|
214
|
+
* Every provider, because this is the file a new user actually opens — it listed two of
|
|
215
|
+
* thirteen, and someone who came for Gemini or Groq found no sign their provider existed.
|
|
216
|
+
* Built from the registry rather than typed out, so a new driver cannot be forgotten
|
|
217
|
+
* here (docsCurrent.test.ts holds the same line for .env.example and PROVIDERS.md).
|
|
218
|
+
*/
|
|
219
|
+
const GLOBAL_ENV_TEMPLATE = [
|
|
220
|
+
"# Mindweave global config — applies in every project.",
|
|
221
|
+
"# Paste a key below (no quotes needed). You only need the one for the provider you",
|
|
222
|
+
"# actually use; fill in several and /provider moves between them.",
|
|
223
|
+
"",
|
|
224
|
+
// The name on its OWN line, never trailing the assignment. `KEY= # DeepSeek` reads
|
|
225
|
+
// fine and parses as a VALUE of "# DeepSeek", so every provider would have reported a
|
|
226
|
+
// key it did not have: no first-run prompt, and every request rejected with no
|
|
227
|
+
// explanation. Caught by reading the parsed result rather than the file.
|
|
228
|
+
...allProviders().flatMap((p) => [`# ${p.label}`, `${p.apiKeyEnv}=`]),
|
|
229
|
+
"",
|
|
230
|
+
"# Optional:",
|
|
231
|
+
"# MINDWEAVE_MODEL — which model to open with. Run /model in Mindweave for the list.",
|
|
232
|
+
"# MINDWEAVE_MODEL=",
|
|
233
|
+
"",
|
|
234
|
+
].join(String.fromCharCode(10));
|
|
235
|
+
/** Create ~/.mindweave/.env with a commented template the first time we run. */
|
|
236
|
+
function ensureGlobalTemplate() {
|
|
237
|
+
try {
|
|
238
|
+
const dir = globalConfigDir();
|
|
239
|
+
if (!existsSync(dir))
|
|
240
|
+
mkdirSync(dir, { recursive: true });
|
|
241
|
+
const path = globalEnvPath();
|
|
242
|
+
if (!existsSync(path)) {
|
|
243
|
+
writeFileSync(path, GLOBAL_ENV_TEMPLATE, { mode: 0o600 });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Best-effort: if we can't write the template, config loading still works.
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/** Apply a single .env file (set-if-absent), tolerating a missing/garbled file. */
|
|
251
|
+
function applyEnvFile(path) {
|
|
252
|
+
let text;
|
|
253
|
+
try {
|
|
254
|
+
text = readFileSync(path, "utf8");
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return; // no file here — fine
|
|
258
|
+
}
|
|
259
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
260
|
+
const line = raw.trim();
|
|
261
|
+
if (!line || line.startsWith("#"))
|
|
262
|
+
continue;
|
|
263
|
+
const body = line.startsWith("export ") ? line.slice(7) : line;
|
|
264
|
+
const eq = body.indexOf("=");
|
|
265
|
+
if (eq <= 0)
|
|
266
|
+
continue;
|
|
267
|
+
const key = body.slice(0, eq).trim();
|
|
268
|
+
if (!key || key in process.env)
|
|
269
|
+
continue; // already set wins
|
|
270
|
+
let value = body.slice(eq + 1).trim();
|
|
271
|
+
if (value.length >= 2 && (value[0] === '"' || value[0] === "'") && value[value.length - 1] === value[0]) {
|
|
272
|
+
value = value.slice(1, -1);
|
|
273
|
+
}
|
|
274
|
+
if (!value)
|
|
275
|
+
continue; // ignore empty assignments (e.g. the blank template line)
|
|
276
|
+
process.env[key] = value;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chatAnchor.ts — where the transcript sits inside the chat viewport.
|
|
3
|
+
*
|
|
4
|
+
* The viewport is a fixed-height clipped box and the transcript renders in FULL
|
|
5
|
+
* inside it; a vertical offset decides which part shows. That mechanism is
|
|
6
|
+
* deliberately dumb — no height estimation, no per-block scrolling — because both
|
|
7
|
+
* of those were tried and both are why it broke. This module owns the decision that
|
|
8
|
+
* positions it, so the rule can be tested instead of eyeballed.
|
|
9
|
+
*
|
|
10
|
+
* Two regimes, and the whole point of the shape below is that they cannot interfere:
|
|
11
|
+
*
|
|
12
|
+
* - The transcript OVERFLOWS. Then it scrolls, and the offset is negative:
|
|
13
|
+
* `-shift` slides the content up so the newest lines are on screen. `scrollUp`
|
|
14
|
+
* counts lines back from the bottom, so 0 always means pinned to the newest and
|
|
15
|
+
* fresh output stays put with no special case.
|
|
16
|
+
* - The transcript FITS. Then there is nothing to scroll, and the only question is
|
|
17
|
+
* where the spare rows go. They used to go below the text, stranding a short
|
|
18
|
+
* conversation at the top of the screen with a growing void above the input box.
|
|
19
|
+
* They now go above it, so the conversation rests on the input the way a chat is
|
|
20
|
+
* expected to.
|
|
21
|
+
*
|
|
22
|
+
* HOW the spare rows are moved matters more than it looks. The obvious version — pad
|
|
23
|
+
* the transcript down by `chatRows - contentHeight` — was written first and a render
|
|
24
|
+
* probe rejected it: `chatRows` is a MEASURED value that lags a frame, and on the
|
|
25
|
+
* first render it is not yet known at all. Padding by a stale number leaves a gap on
|
|
26
|
+
* a good frame and, when the number is too large, pushes the whole conversation down
|
|
27
|
+
* past the clip edge and off the screen.
|
|
28
|
+
*
|
|
29
|
+
* So the offset here is only ever the scroll offset, and the resting case is done in
|
|
30
|
+
* the layout instead: `restsOnFooter` tells the view to put a flex-grow spacer ABOVE
|
|
31
|
+
* the transcript. Yoga then measures the leftover space itself, in the same pass that
|
|
32
|
+
* lays the frame out, and no stale measurement can be wrong about it.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Position the transcript.
|
|
36
|
+
*
|
|
37
|
+
* @param contentHeight measured height of the whole transcript, in rows
|
|
38
|
+
* @param chatRows measured height of the viewport it renders into
|
|
39
|
+
* @param scrollUp lines the user has scrolled back from the newest
|
|
40
|
+
*/
|
|
41
|
+
export function chatLayout(contentHeight, chatRows, scrollUp) {
|
|
42
|
+
// A viewport of zero rows would compute an offset that slides the ENTIRE
|
|
43
|
+
// transcript off the top — every line hidden, with nothing on screen to explain
|
|
44
|
+
// it. App already clamps this, but a positioning rule should not depend on its
|
|
45
|
+
// caller to stay sane: one row always shows the newest line, which is the right
|
|
46
|
+
// failure for a viewport too small to be useful.
|
|
47
|
+
const rows = Math.max(1, chatRows);
|
|
48
|
+
const maxScroll = Math.max(0, contentHeight - rows);
|
|
49
|
+
const scrolled = Math.min(Math.max(0, scrollUp), maxScroll);
|
|
50
|
+
const shift = maxScroll - scrolled;
|
|
51
|
+
return {
|
|
52
|
+
// `|| 0` because negating zero yields `-0`, which is the same frame but a
|
|
53
|
+
// different value to anything comparing with Object.is.
|
|
54
|
+
marginTop: -shift || 0,
|
|
55
|
+
// Nothing to scroll means nothing to scroll TO — the transcript is short, and
|
|
56
|
+
// the spare rows belong above it.
|
|
57
|
+
restsOnFooter: maxScroll === 0,
|
|
58
|
+
maxScroll,
|
|
59
|
+
scrolled,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Where the reader should sit after the transcript re-wraps at a new width.
|
|
64
|
+
*
|
|
65
|
+
* `scrollUp` counts LINES back from the newest, and a line is not a stable unit
|
|
66
|
+
* across a resize: narrow the terminal and every wrapped paragraph grows more rows,
|
|
67
|
+
* so the same count lands somewhere else entirely. Being at the bottom survives that
|
|
68
|
+
* by luck, because zero is zero at any width, but any scrolled-back reader is moved
|
|
69
|
+
* without touching anything.
|
|
70
|
+
*
|
|
71
|
+
* The position is therefore carried as a PROPORTION of the scrollable range, which is
|
|
72
|
+
* the one thing about "where I was reading" that a re-wrap preserves. It is not exact
|
|
73
|
+
* — the same fraction of a taller transcript is a slightly different paragraph — but
|
|
74
|
+
* it keeps the reader within a line or two of where they were, where a raw line count
|
|
75
|
+
* can move them by pages.
|
|
76
|
+
*
|
|
77
|
+
* Pinned to the newest stays pinned, though that falls out of the arithmetic on its
|
|
78
|
+
* own — a red-check showed the guard below is not what produces it. What the guard is
|
|
79
|
+
* really for is a NEGATIVE position, which the proportion would carry through into a
|
|
80
|
+
* negative offset and slide the transcript off the top of the viewport.
|
|
81
|
+
*/
|
|
82
|
+
export function reflowScroll(scrolled, oldMaxScroll, newMaxScroll) {
|
|
83
|
+
if (scrolled <= 0)
|
|
84
|
+
return 0;
|
|
85
|
+
if (newMaxScroll <= 0)
|
|
86
|
+
return 0;
|
|
87
|
+
// Nothing scrollable before means there is no proportion to carry; the reader was
|
|
88
|
+
// looking at the whole transcript, and the bottom is where they still belong.
|
|
89
|
+
if (oldMaxScroll <= 0)
|
|
90
|
+
return 0;
|
|
91
|
+
const fraction = Math.min(1, scrolled / oldMaxScroll);
|
|
92
|
+
return Math.min(newMaxScroll, Math.round(fraction * newMaxScroll));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=chatAnchor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatAnchor.js","sourceRoot":"","sources":["../../src/cli/chatAnchor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAqBH;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,aAAqB,EAAE,QAAgB,EAAE,QAAgB;IAClF,yEAAyE;IACzE,gFAAgF;IAChF,+EAA+E;IAC/E,gFAAgF;IAChF,iDAAiD;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;IACnC,OAAO;QACL,0EAA0E;QAC1E,wDAAwD;QACxD,SAAS,EAAE,CAAC,KAAK,IAAI,CAAC;QACtB,8EAA8E;QAC9E,kCAAkC;QAClC,aAAa,EAAE,SAAS,KAAK,CAAC;QAC9B,SAAS;QACT,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,YAAoB,EAAE,YAAoB;IACvF,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC5B,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,kFAAkF;IAClF,8EAA8E;IAC9E,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commandArgs.ts — turning what someone typed after a command into a choice.
|
|
3
|
+
*
|
|
4
|
+
* `/model`, `/think` and `/compact` all took an argument and threw it away without a
|
|
5
|
+
* word. Naming a model after `/model` opened the picker as if you had typed nothing,
|
|
6
|
+
* which reads as the app not having heard you — and is worse than an error, because an
|
|
7
|
+
* error tells you to try something else and silence tells you nothing.
|
|
8
|
+
*
|
|
9
|
+
* Terminal agents generally accept an argument on all three, so it is what someone
|
|
10
|
+
* will type without thinking about it — which is exactly when silence is worst.
|
|
11
|
+
*
|
|
12
|
+
* Nothing here knows any provider's lineup: the candidates are handed in by the caller,
|
|
13
|
+
* which reads them from the registry. That is the rule for core code, and it is also
|
|
14
|
+
* what makes this testable without a key.
|
|
15
|
+
*
|
|
16
|
+
* The matching is deliberately forgiving in a bounded way: exact id, then exact label,
|
|
17
|
+
* then a UNIQUE prefix, then a UNIQUE substring. Never a "closest guess" — picking a
|
|
18
|
+
* model or a reasoning budget is a decision with a cost attached, and quietly choosing
|
|
19
|
+
* the nearest thing to a typo is how you end up billed for the wrong one. Ambiguity
|
|
20
|
+
* and misses both come back as a message naming the real options.
|
|
21
|
+
*/
|
|
22
|
+
function norm(s) {
|
|
23
|
+
return s.trim().toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
/** "a, b or c" — a list a person reads, not a machine dump. */
|
|
26
|
+
function list(items) {
|
|
27
|
+
if (items.length <= 1)
|
|
28
|
+
return items[0] ?? "";
|
|
29
|
+
return `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Which candidate the typed argument means.
|
|
33
|
+
*
|
|
34
|
+
* `what` names the thing being chosen, so the message reads as a sentence rather than
|
|
35
|
+
* as a template ("No model called…", "No reasoning level called…").
|
|
36
|
+
*/
|
|
37
|
+
export function resolveChoice(arg, candidates, what) {
|
|
38
|
+
const wanted = norm(arg);
|
|
39
|
+
if (!wanted)
|
|
40
|
+
return { kind: "error", message: `Which ${what}?` };
|
|
41
|
+
const names = candidates.map((c) => c.label);
|
|
42
|
+
// Exact wins outright, and is checked against BOTH the id and the label — the id is
|
|
43
|
+
// what a script or a copied command line carries, the label is what the picker shows.
|
|
44
|
+
const exact = candidates.findIndex((c) => norm(c.label) === wanted || (c.id !== undefined && norm(c.id) === wanted));
|
|
45
|
+
if (exact >= 0)
|
|
46
|
+
return { kind: "match", index: exact };
|
|
47
|
+
const starts = matchesFor(candidates, (c) => startsWith(c, wanted));
|
|
48
|
+
if (starts.length === 1)
|
|
49
|
+
return { kind: "match", index: starts[0] };
|
|
50
|
+
if (starts.length > 1)
|
|
51
|
+
return { kind: "error", message: ambiguous(arg, starts.map((i) => names[i])) };
|
|
52
|
+
const contains = matchesFor(candidates, (c) => includes(c, wanted));
|
|
53
|
+
if (contains.length === 1)
|
|
54
|
+
return { kind: "match", index: contains[0] };
|
|
55
|
+
if (contains.length > 1)
|
|
56
|
+
return { kind: "error", message: ambiguous(arg, contains.map((i) => names[i])) };
|
|
57
|
+
return {
|
|
58
|
+
kind: "error",
|
|
59
|
+
message: `No ${what} called "${arg.trim()}". Available: ${list(names)}.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function matchesFor(candidates, pred) {
|
|
63
|
+
const out = [];
|
|
64
|
+
candidates.forEach((c, i) => {
|
|
65
|
+
if (pred(c))
|
|
66
|
+
out.push(i);
|
|
67
|
+
});
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
function startsWith(c, wanted) {
|
|
71
|
+
return norm(c.label).startsWith(wanted) || (c.id !== undefined && norm(c.id).startsWith(wanted));
|
|
72
|
+
}
|
|
73
|
+
function includes(c, wanted) {
|
|
74
|
+
return norm(c.label).includes(wanted) || (c.id !== undefined && norm(c.id).includes(wanted));
|
|
75
|
+
}
|
|
76
|
+
function ambiguous(arg, matched) {
|
|
77
|
+
return `"${arg.trim()}" matches ${list(matched)}. Which one?`;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=commandArgs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandArgs.js","sourceRoot":"","sources":["../../src/cli/commandArgs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commandRoute.ts — deciding WHICH command a typed line is.
|
|
3
|
+
*
|
|
4
|
+
* This used to be the condition half of a 460-line `if (name === "/x")` chain inside a
|
|
5
|
+
* React component, which is why every one of the eighteen commands had zero coverage:
|
|
6
|
+
* there was nothing to call. The bodies still live in `App.tsx`. Only the decision
|
|
7
|
+
* moved here, because the decision is where the defects were:
|
|
8
|
+
*
|
|
9
|
+
* - **`/mcp add` and `/mcp remove` were DEAD.** The guard read
|
|
10
|
+
* `/^(add|remove|rm)\b/` on screen, but the byte where `\b` should have been was a
|
|
11
|
+
* literal backspace (0x08) — an escape lost somewhere in editing. The pattern
|
|
12
|
+
* therefore required the user to type a backspace character, so it never matched
|
|
13
|
+
* anything, and every `/mcp add …` silently opened the server-health view instead.
|
|
14
|
+
* The command was advertised in its own `/help` description the whole time.
|
|
15
|
+
* - The unknown-command reply listed thirteen of the eighteen commands, hardcoded. It
|
|
16
|
+
* had drifted, and the four it omitted included `/help`.
|
|
17
|
+
*
|
|
18
|
+
* Both are the same shape as the bugs found in the queue and the first run: the feature
|
|
19
|
+
* worked, the routing to it did not, and reading the code did not show it — the first
|
|
20
|
+
* one was INVISIBLE in the source, which is why the verb list here is data rather than
|
|
21
|
+
* a pattern. There is nothing in `["add","remove","rm"]` that can be mistyped into
|
|
22
|
+
* something that still compiles and never matches.
|
|
23
|
+
*
|
|
24
|
+
* Order matters and is deliberate: a builtin beats a project skill, a project skill
|
|
25
|
+
* beats a third-party server's prompt. A server cannot shadow `/undo`, and a project's
|
|
26
|
+
* own command always wins over something a dependency installed.
|
|
27
|
+
*/
|
|
28
|
+
import { findSkill } from "../governor/skills.js";
|
|
29
|
+
import { parsePromptCommand } from "../mcp/prompts.js";
|
|
30
|
+
/** The sub-commands `/mcp` understands as configuration rather than as a status view. */
|
|
31
|
+
export const MCP_CONFIG_VERBS = ["add", "remove", "rm"];
|
|
32
|
+
/**
|
|
33
|
+
* Split a typed line into the command word and its argument.
|
|
34
|
+
*
|
|
35
|
+
* The name is lowercased so `/Help` works; the argument is not, because it is as
|
|
36
|
+
* likely to be a path, a label or a directive, and lowercasing `/include SRC/Api`
|
|
37
|
+
* would break it on a case-sensitive checkout.
|
|
38
|
+
*/
|
|
39
|
+
export function parseCommandLine(raw) {
|
|
40
|
+
const trimmed = raw.trim();
|
|
41
|
+
const first = trimmed.split(/\s+/)[0] ?? "";
|
|
42
|
+
return { name: first.toLowerCase(), arg: trimmed.slice(first.length).trim() };
|
|
43
|
+
}
|
|
44
|
+
export function routeCommand(raw, catalog) {
|
|
45
|
+
const { name, arg } = parseCommandLine(raw);
|
|
46
|
+
if (catalog.builtins.includes(name)) {
|
|
47
|
+
// `/mcp` is the one builtin that splits: with a configuration verb it writes the
|
|
48
|
+
// server config, bare it shows server health. An EXACT first word — a prefix match
|
|
49
|
+
// would send `/mcp rmdir-server` to the remove branch, which fails its own exact
|
|
50
|
+
// check one layer down and falls through to being parsed as an ADD.
|
|
51
|
+
if (name === "/mcp") {
|
|
52
|
+
const verb = arg.split(/\s+/)[0]?.toLowerCase() ?? "";
|
|
53
|
+
if (MCP_CONFIG_VERBS.includes(verb)) {
|
|
54
|
+
return { kind: "mcp-config", arg };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { kind: "builtin", name, arg };
|
|
58
|
+
}
|
|
59
|
+
// A project's own skill beats a server's prompt of the same name.
|
|
60
|
+
const skill = findSkill(catalog.skills, name);
|
|
61
|
+
if (skill)
|
|
62
|
+
return { kind: "skill", skill, arg };
|
|
63
|
+
const promptRef = parsePromptCommand(name);
|
|
64
|
+
if (promptRef)
|
|
65
|
+
return { kind: "prompt", server: promptRef.server, prompt: promptRef.name, arg };
|
|
66
|
+
return { kind: "unknown", name };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* What to say when nothing matched.
|
|
70
|
+
*
|
|
71
|
+
* The old message hardcoded thirteen command names and had drifted from the real
|
|
72
|
+
* eighteen — including omitting `/help`, the one that would have answered the
|
|
73
|
+
* question. Pointing at `/help` cannot drift, and is shorter than the list it replaces.
|
|
74
|
+
*/
|
|
75
|
+
export function unknownCommandMessage(name) {
|
|
76
|
+
return `Unknown command ${name}. /help lists every command.`;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=commandRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandRoute.js","sourceRoot":"","sources":["../../src/cli/commandRoute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,yFAAyF;AACzF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAU,CAAC;AASjE;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AAChF,CAAC;AAuBD,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,OAAqB;IAC7D,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAE5C,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,iFAAiF;QACjF,mFAAmF;QACnF,iFAAiF;QACjF,oEAAoE;QACpE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;YACtD,IAAK,gBAAsC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IACxC,CAAC;IAED,kEAAkE;IAClE,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,MAAqB,EAAE,IAAI,CAAC,CAAC;IAC7D,IAAI,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAEhD,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;IAEhG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,mBAAmB,IAAI,8BAA8B,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compaction.ts — how a compaction reports itself, as pure text (no React).
|
|
3
|
+
*
|
|
4
|
+
* [████████████████████] 100% context full
|
|
5
|
+
* ✔ Reclaimed 106K tokens (22K / 128K)
|
|
6
|
+
* [███░░░░░░░░░░░░░░░░░] 17% context used
|
|
7
|
+
*
|
|
8
|
+
* Compaction is the one piece of background machinery worth showing. Everything else
|
|
9
|
+
* Mindweave does to manage context is invisible on purpose, but a summarizing pass
|
|
10
|
+
* REWRITES the conversation — the model will not remember the middle of it afterwards
|
|
11
|
+
* — and a user who does not know that happened is left wondering why it forgot.
|
|
12
|
+
*
|
|
13
|
+
* ONE block, already settled. There is no "Compacting…" state that later fills in: the
|
|
14
|
+
* before-figure is only interesting next to the after-figure, and a row that changes
|
|
15
|
+
* under the reader is the exact transition the transcript design removes elsewhere.
|
|
16
|
+
*
|
|
17
|
+
* The numbers are the SAME arithmetic the compaction thresholds run on (transcript
|
|
18
|
+
* estimate + measured overhead). That coupling is deliberate. If the estimate is off,
|
|
19
|
+
* the bar is wrong in precisely the way the decision to compact was wrong, so what the
|
|
20
|
+
* user sees is what the system actually believed — rather than a second, prettier
|
|
21
|
+
* number that disagrees with the machinery.
|
|
22
|
+
*/
|
|
23
|
+
import { formatTokens } from "../dynamo/pricing.js";
|
|
24
|
+
/** Cells in a bar. Matches the reference design; shrinks only on a narrow terminal. */
|
|
25
|
+
const BAR_CELLS = 20;
|
|
26
|
+
const FULL = "█";
|
|
27
|
+
const EMPTY = "░";
|
|
28
|
+
/** A `[████░░░░]` bar for a fraction of the window (pure). Clamped, so a measurement
|
|
29
|
+
* that overshoots the window renders as full rather than overflowing the row. */
|
|
30
|
+
export function bar(used, window, cells = BAR_CELLS) {
|
|
31
|
+
const safeCells = Math.max(4, cells);
|
|
32
|
+
const frac = window > 0 ? Math.min(1, Math.max(0, used / window)) : 0;
|
|
33
|
+
// Round rather than floor, so a nearly-full context does not read as one cell short —
|
|
34
|
+
// but never round UP to full while any room remains, which would say "full" wrongly.
|
|
35
|
+
let filled = Math.round(frac * safeCells);
|
|
36
|
+
if (frac < 1 && filled === safeCells)
|
|
37
|
+
filled = safeCells - 1;
|
|
38
|
+
if (frac > 0 && filled === 0)
|
|
39
|
+
filled = 1; // and never show a used context as empty
|
|
40
|
+
return `[${FULL.repeat(filled)}${EMPTY.repeat(safeCells - filled)}]`;
|
|
41
|
+
}
|
|
42
|
+
/** The percentage shown beside a bar (pure), right-aligned to three columns so the
|
|
43
|
+
* before/after pair line up whatever the digits. */
|
|
44
|
+
export function percent(used, window) {
|
|
45
|
+
const pct = window > 0 ? Math.round((used / window) * 100) : 0;
|
|
46
|
+
return `${Math.min(100, Math.max(0, pct))}%`.padStart(4);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The finished block, one string per row (pure).
|
|
50
|
+
*
|
|
51
|
+
* `width` shrinks the bars on a narrow terminal rather than letting a row wrap, since
|
|
52
|
+
* a wrapped bar reads as two broken bars.
|
|
53
|
+
*/
|
|
54
|
+
export function compactionLines(r, width = 80) {
|
|
55
|
+
// Row overhead: the two-space indent, the brackets, a space, four percent columns,
|
|
56
|
+
// two spaces, and the label. Leave the bar whatever is left, within reason.
|
|
57
|
+
const cells = Math.max(4, Math.min(BAR_CELLS, width - 26));
|
|
58
|
+
const reclaimed = Math.max(0, r.before - r.after);
|
|
59
|
+
// Labelled "before"/"after" rather than the reference's "Context Full"/"Context
|
|
60
|
+
// Used". That wording only reads correctly when the pass ran at 100%, and `/compact`
|
|
61
|
+
// can be typed at any moment — a bar showing 75% next to the words "context full"
|
|
62
|
+
// is a caption contradicting the picture directly above it.
|
|
63
|
+
return [
|
|
64
|
+
`${bar(r.before, r.window, cells)} ${percent(r.before, r.window)} before`,
|
|
65
|
+
`✔ Reclaimed ${formatTokens(reclaimed)} tokens (${formatTokens(r.after)} / ${formatTokens(r.window)})`,
|
|
66
|
+
`${bar(r.after, r.window, cells)} ${percent(r.after, r.window)} after`,
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../src/cli/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAKpD,uFAAuF;AACvF,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,IAAI,GAAG,GAAG,CAAC;AACjB,MAAM,KAAK,GAAG,GAAG,CAAC;AAElB;kFACkF;AAClF,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,KAAK,GAAG,SAAS;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,sFAAsF;IACtF,qFAAqF;IACrF,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC;IAC7D,IAAI,IAAI,GAAG,CAAC,IAAI,MAAM,KAAK,CAAC;QAAE,MAAM,GAAG,CAAC,CAAC,CAAC,yCAAyC;IACnF,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;AACvE,CAAC;AAED;qDACqD;AACrD,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,MAAc;IAClD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,CAAmB,EAAE,KAAK,GAAG,EAAE;IAC7D,mFAAmF;IACnF,4EAA4E;IAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAClD,gFAAgF;IAChF,qFAAqF;IACrF,kFAAkF;IAClF,4DAA4D;IAC5D,OAAO;QACL,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU;QAC1E,eAAe,YAAY,CAAC,SAAS,CAAC,YAAY,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG;QACtG,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS;KACxE,CAAC;AACJ,CAAC"}
|