attocode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/dist/src/adapters.d.ts +83 -0
- package/dist/src/adapters.d.ts.map +1 -0
- package/dist/src/adapters.js +221 -0
- package/dist/src/adapters.js.map +1 -0
- package/dist/src/agent-tools/index.d.ts +7 -0
- package/dist/src/agent-tools/index.d.ts.map +1 -0
- package/dist/src/agent-tools/index.js +8 -0
- package/dist/src/agent-tools/index.js.map +1 -0
- package/dist/src/agent-tools/lsp-file-tools.d.ts +33 -0
- package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -0
- package/dist/src/agent-tools/lsp-file-tools.js +200 -0
- package/dist/src/agent-tools/lsp-file-tools.js.map +1 -0
- package/dist/src/agent.d.ts +667 -0
- package/dist/src/agent.d.ts.map +1 -0
- package/dist/src/agent.js +2824 -0
- package/dist/src/agent.js.map +1 -0
- package/dist/src/cli.d.ts +36 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +176 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/handler.d.ts +22 -0
- package/dist/src/commands/handler.d.ts.map +1 -0
- package/dist/src/commands/handler.js +1320 -0
- package/dist/src/commands/handler.js.map +1 -0
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +153 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/types.d.ts +70 -0
- package/dist/src/commands/types.d.ts.map +1 -0
- package/dist/src/commands/types.js +8 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/config.d.ts +22 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +25 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/core/index.d.ts +32 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +35 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/process-handlers.d.ts +43 -0
- package/dist/src/core/process-handlers.d.ts.map +1 -0
- package/dist/src/core/process-handlers.js +117 -0
- package/dist/src/core/process-handlers.js.map +1 -0
- package/dist/src/core/protocol/bridge.d.ts +117 -0
- package/dist/src/core/protocol/bridge.d.ts.map +1 -0
- package/dist/src/core/protocol/bridge.js +149 -0
- package/dist/src/core/protocol/bridge.js.map +1 -0
- package/dist/src/core/protocol/index.d.ts +8 -0
- package/dist/src/core/protocol/index.d.ts.map +1 -0
- package/dist/src/core/protocol/index.js +8 -0
- package/dist/src/core/protocol/index.js.map +1 -0
- package/dist/src/core/protocol/types.d.ts +539 -0
- package/dist/src/core/protocol/types.d.ts.map +1 -0
- package/dist/src/core/protocol/types.js +149 -0
- package/dist/src/core/protocol/types.js.map +1 -0
- package/dist/src/core/queues/atomic-counter.d.ts +36 -0
- package/dist/src/core/queues/atomic-counter.d.ts.map +1 -0
- package/dist/src/core/queues/atomic-counter.js +46 -0
- package/dist/src/core/queues/atomic-counter.js.map +1 -0
- package/dist/src/core/queues/event-queue.d.ts +126 -0
- package/dist/src/core/queues/event-queue.d.ts.map +1 -0
- package/dist/src/core/queues/event-queue.js +208 -0
- package/dist/src/core/queues/event-queue.js.map +1 -0
- package/dist/src/core/queues/index.d.ts +12 -0
- package/dist/src/core/queues/index.d.ts.map +1 -0
- package/dist/src/core/queues/index.js +15 -0
- package/dist/src/core/queues/index.js.map +1 -0
- package/dist/src/core/queues/submission-queue.d.ts +116 -0
- package/dist/src/core/queues/submission-queue.d.ts.map +1 -0
- package/dist/src/core/queues/submission-queue.js +236 -0
- package/dist/src/core/queues/submission-queue.js.map +1 -0
- package/dist/src/costs/index.d.ts +22 -0
- package/dist/src/costs/index.d.ts.map +1 -0
- package/dist/src/costs/index.js +22 -0
- package/dist/src/costs/index.js.map +1 -0
- package/dist/src/costs/model-registry.d.ts +80 -0
- package/dist/src/costs/model-registry.d.ts.map +1 -0
- package/dist/src/costs/model-registry.js +237 -0
- package/dist/src/costs/model-registry.js.map +1 -0
- package/dist/src/costs/types.d.ts +50 -0
- package/dist/src/costs/types.d.ts.map +1 -0
- package/dist/src/costs/types.js +2 -0
- package/dist/src/costs/types.js.map +1 -0
- package/dist/src/defaults.d.ts +114 -0
- package/dist/src/defaults.d.ts.map +1 -0
- package/dist/src/defaults.js +457 -0
- package/dist/src/defaults.js.map +1 -0
- package/dist/src/first-run.d.ts +35 -0
- package/dist/src/first-run.d.ts.map +1 -0
- package/dist/src/first-run.js +94 -0
- package/dist/src/first-run.js.map +1 -0
- package/dist/src/hello.d.ts +2 -0
- package/dist/src/hello.d.ts.map +1 -0
- package/dist/src/hello.js +4 -0
- package/dist/src/hello.js.map +1 -0
- package/dist/src/integrations/agent-registry.d.ts +160 -0
- package/dist/src/integrations/agent-registry.d.ts.map +1 -0
- package/dist/src/integrations/agent-registry.js +446 -0
- package/dist/src/integrations/agent-registry.js.map +1 -0
- package/dist/src/integrations/auto-compaction.d.ts +177 -0
- package/dist/src/integrations/auto-compaction.d.ts.map +1 -0
- package/dist/src/integrations/auto-compaction.js +428 -0
- package/dist/src/integrations/auto-compaction.js.map +1 -0
- package/dist/src/integrations/cancellation.d.ts +162 -0
- package/dist/src/integrations/cancellation.d.ts.map +1 -0
- package/dist/src/integrations/cancellation.js +339 -0
- package/dist/src/integrations/cancellation.js.map +1 -0
- package/dist/src/integrations/codebase-context.d.ts +319 -0
- package/dist/src/integrations/codebase-context.d.ts.map +1 -0
- package/dist/src/integrations/codebase-context.js +816 -0
- package/dist/src/integrations/codebase-context.js.map +1 -0
- package/dist/src/integrations/compaction.d.ts +192 -0
- package/dist/src/integrations/compaction.d.ts.map +1 -0
- package/dist/src/integrations/compaction.js +376 -0
- package/dist/src/integrations/compaction.js.map +1 -0
- package/dist/src/integrations/context-engineering.d.ts +246 -0
- package/dist/src/integrations/context-engineering.d.ts.map +1 -0
- package/dist/src/integrations/context-engineering.js +394 -0
- package/dist/src/integrations/context-engineering.js.map +1 -0
- package/dist/src/integrations/diff-utils.d.ts +105 -0
- package/dist/src/integrations/diff-utils.d.ts.map +1 -0
- package/dist/src/integrations/diff-utils.js +497 -0
- package/dist/src/integrations/diff-utils.js.map +1 -0
- package/dist/src/integrations/economics.d.ts +192 -0
- package/dist/src/integrations/economics.d.ts.map +1 -0
- package/dist/src/integrations/economics.js +431 -0
- package/dist/src/integrations/economics.js.map +1 -0
- package/dist/src/integrations/execution-policy.d.ts +189 -0
- package/dist/src/integrations/execution-policy.d.ts.map +1 -0
- package/dist/src/integrations/execution-policy.js +352 -0
- package/dist/src/integrations/execution-policy.js.map +1 -0
- package/dist/src/integrations/file-change-tracker.d.ts +161 -0
- package/dist/src/integrations/file-change-tracker.d.ts.map +1 -0
- package/dist/src/integrations/file-change-tracker.js +520 -0
- package/dist/src/integrations/file-change-tracker.js.map +1 -0
- package/dist/src/integrations/hierarchical-config.d.ts +212 -0
- package/dist/src/integrations/hierarchical-config.d.ts.map +1 -0
- package/dist/src/integrations/hierarchical-config.js +484 -0
- package/dist/src/integrations/hierarchical-config.js.map +1 -0
- package/dist/src/integrations/hooks.d.ts +114 -0
- package/dist/src/integrations/hooks.d.ts.map +1 -0
- package/dist/src/integrations/hooks.js +326 -0
- package/dist/src/integrations/hooks.js.map +1 -0
- package/dist/src/integrations/ignore.d.ts +143 -0
- package/dist/src/integrations/ignore.d.ts.map +1 -0
- package/dist/src/integrations/ignore.js +417 -0
- package/dist/src/integrations/ignore.js.map +1 -0
- package/dist/src/integrations/image-renderer.d.ts +119 -0
- package/dist/src/integrations/image-renderer.d.ts.map +1 -0
- package/dist/src/integrations/image-renderer.js +306 -0
- package/dist/src/integrations/image-renderer.js.map +1 -0
- package/dist/src/integrations/index.d.ts +42 -0
- package/dist/src/integrations/index.d.ts.map +1 -0
- package/dist/src/integrations/index.js +73 -0
- package/dist/src/integrations/index.js.map +1 -0
- package/dist/src/integrations/lsp.d.ts +196 -0
- package/dist/src/integrations/lsp.d.ts.map +1 -0
- package/dist/src/integrations/lsp.js +582 -0
- package/dist/src/integrations/lsp.js.map +1 -0
- package/dist/src/integrations/mcp-client.d.ts +270 -0
- package/dist/src/integrations/mcp-client.d.ts.map +1 -0
- package/dist/src/integrations/mcp-client.js +698 -0
- package/dist/src/integrations/mcp-client.js.map +1 -0
- package/dist/src/integrations/mcp-tool-search.d.ts +77 -0
- package/dist/src/integrations/mcp-tool-search.d.ts.map +1 -0
- package/dist/src/integrations/mcp-tool-search.js +220 -0
- package/dist/src/integrations/mcp-tool-search.js.map +1 -0
- package/dist/src/integrations/memory.d.ts +108 -0
- package/dist/src/integrations/memory.d.ts.map +1 -0
- package/dist/src/integrations/memory.js +288 -0
- package/dist/src/integrations/memory.js.map +1 -0
- package/dist/src/integrations/multi-agent.d.ts +150 -0
- package/dist/src/integrations/multi-agent.d.ts.map +1 -0
- package/dist/src/integrations/multi-agent.js +306 -0
- package/dist/src/integrations/multi-agent.js.map +1 -0
- package/dist/src/integrations/observability.d.ts +162 -0
- package/dist/src/integrations/observability.d.ts.map +1 -0
- package/dist/src/integrations/observability.js +406 -0
- package/dist/src/integrations/observability.js.map +1 -0
- package/dist/src/integrations/openrouter-pricing.d.ts +42 -0
- package/dist/src/integrations/openrouter-pricing.d.ts.map +1 -0
- package/dist/src/integrations/openrouter-pricing.js +124 -0
- package/dist/src/integrations/openrouter-pricing.js.map +1 -0
- package/dist/src/integrations/pending-plan.d.ts +171 -0
- package/dist/src/integrations/pending-plan.d.ts.map +1 -0
- package/dist/src/integrations/pending-plan.js +244 -0
- package/dist/src/integrations/pending-plan.js.map +1 -0
- package/dist/src/integrations/persistence.d.ts +48 -0
- package/dist/src/integrations/persistence.d.ts.map +1 -0
- package/dist/src/integrations/persistence.js +196 -0
- package/dist/src/integrations/persistence.js.map +1 -0
- package/dist/src/integrations/planning.d.ts +96 -0
- package/dist/src/integrations/planning.d.ts.map +1 -0
- package/dist/src/integrations/planning.js +338 -0
- package/dist/src/integrations/planning.js.map +1 -0
- package/dist/src/integrations/pty-shell.d.ts +169 -0
- package/dist/src/integrations/pty-shell.d.ts.map +1 -0
- package/dist/src/integrations/pty-shell.js +367 -0
- package/dist/src/integrations/pty-shell.js.map +1 -0
- package/dist/src/integrations/react.d.ts +139 -0
- package/dist/src/integrations/react.d.ts.map +1 -0
- package/dist/src/integrations/react.js +273 -0
- package/dist/src/integrations/react.js.map +1 -0
- package/dist/src/integrations/resources.d.ts +177 -0
- package/dist/src/integrations/resources.d.ts.map +1 -0
- package/dist/src/integrations/resources.js +311 -0
- package/dist/src/integrations/resources.js.map +1 -0
- package/dist/src/integrations/result-synthesizer.d.ts +389 -0
- package/dist/src/integrations/result-synthesizer.d.ts.map +1 -0
- package/dist/src/integrations/result-synthesizer.js +951 -0
- package/dist/src/integrations/result-synthesizer.js.map +1 -0
- package/dist/src/integrations/routing.d.ts +117 -0
- package/dist/src/integrations/routing.d.ts.map +1 -0
- package/dist/src/integrations/routing.js +347 -0
- package/dist/src/integrations/routing.js.map +1 -0
- package/dist/src/integrations/rules.d.ts +131 -0
- package/dist/src/integrations/rules.d.ts.map +1 -0
- package/dist/src/integrations/rules.js +284 -0
- package/dist/src/integrations/rules.js.map +1 -0
- package/dist/src/integrations/safety.d.ts +142 -0
- package/dist/src/integrations/safety.d.ts.map +1 -0
- package/dist/src/integrations/safety.js +342 -0
- package/dist/src/integrations/safety.js.map +1 -0
- package/dist/src/integrations/sandbox/basic.d.ts +74 -0
- package/dist/src/integrations/sandbox/basic.d.ts.map +1 -0
- package/dist/src/integrations/sandbox/basic.js +310 -0
- package/dist/src/integrations/sandbox/basic.js.map +1 -0
- package/dist/src/integrations/sandbox/docker.d.ts +94 -0
- package/dist/src/integrations/sandbox/docker.d.ts.map +1 -0
- package/dist/src/integrations/sandbox/docker.js +293 -0
- package/dist/src/integrations/sandbox/docker.js.map +1 -0
- package/dist/src/integrations/sandbox/index.d.ts +182 -0
- package/dist/src/integrations/sandbox/index.d.ts.map +1 -0
- package/dist/src/integrations/sandbox/index.js +382 -0
- package/dist/src/integrations/sandbox/index.js.map +1 -0
- package/dist/src/integrations/sandbox/landlock.d.ts +59 -0
- package/dist/src/integrations/sandbox/landlock.d.ts.map +1 -0
- package/dist/src/integrations/sandbox/landlock.js +326 -0
- package/dist/src/integrations/sandbox/landlock.js.map +1 -0
- package/dist/src/integrations/sandbox/seatbelt.d.ts +68 -0
- package/dist/src/integrations/sandbox/seatbelt.d.ts.map +1 -0
- package/dist/src/integrations/sandbox/seatbelt.js +298 -0
- package/dist/src/integrations/sandbox/seatbelt.js.map +1 -0
- package/dist/src/integrations/semantic-cache.d.ts +178 -0
- package/dist/src/integrations/semantic-cache.d.ts.map +1 -0
- package/dist/src/integrations/semantic-cache.js +372 -0
- package/dist/src/integrations/semantic-cache.js.map +1 -0
- package/dist/src/integrations/session-store.d.ts +183 -0
- package/dist/src/integrations/session-store.d.ts.map +1 -0
- package/dist/src/integrations/session-store.js +345 -0
- package/dist/src/integrations/session-store.js.map +1 -0
- package/dist/src/integrations/shared-blackboard.d.ts +403 -0
- package/dist/src/integrations/shared-blackboard.d.ts.map +1 -0
- package/dist/src/integrations/shared-blackboard.js +710 -0
- package/dist/src/integrations/shared-blackboard.js.map +1 -0
- package/dist/src/integrations/skills.d.ts +171 -0
- package/dist/src/integrations/skills.d.ts.map +1 -0
- package/dist/src/integrations/skills.js +403 -0
- package/dist/src/integrations/skills.js.map +1 -0
- package/dist/src/integrations/smart-decomposer.d.ts +322 -0
- package/dist/src/integrations/smart-decomposer.d.ts.map +1 -0
- package/dist/src/integrations/smart-decomposer.js +856 -0
- package/dist/src/integrations/smart-decomposer.js.map +1 -0
- package/dist/src/integrations/sourcegraph.d.ts +169 -0
- package/dist/src/integrations/sourcegraph.d.ts.map +1 -0
- package/dist/src/integrations/sourcegraph.js +379 -0
- package/dist/src/integrations/sourcegraph.js.map +1 -0
- package/dist/src/integrations/sqlite-store.d.ts +518 -0
- package/dist/src/integrations/sqlite-store.d.ts.map +1 -0
- package/dist/src/integrations/sqlite-store.js +1423 -0
- package/dist/src/integrations/sqlite-store.js.map +1 -0
- package/dist/src/integrations/streaming.d.ts +102 -0
- package/dist/src/integrations/streaming.d.ts.map +1 -0
- package/dist/src/integrations/streaming.js +362 -0
- package/dist/src/integrations/streaming.js.map +1 -0
- package/dist/src/integrations/thread-manager.d.ts +199 -0
- package/dist/src/integrations/thread-manager.d.ts.map +1 -0
- package/dist/src/integrations/thread-manager.js +357 -0
- package/dist/src/integrations/thread-manager.js.map +1 -0
- package/dist/src/main.d.ts +26 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/main.js +170 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/modes/index.d.ts +10 -0
- package/dist/src/modes/index.d.ts.map +1 -0
- package/dist/src/modes/index.js +10 -0
- package/dist/src/modes/index.js.map +1 -0
- package/dist/src/modes/repl.d.ts +19 -0
- package/dist/src/modes/repl.d.ts.map +1 -0
- package/dist/src/modes/repl.js +393 -0
- package/dist/src/modes/repl.js.map +1 -0
- package/dist/src/modes/tui.d.ts +29 -0
- package/dist/src/modes/tui.d.ts.map +1 -0
- package/dist/src/modes/tui.js +272 -0
- package/dist/src/modes/tui.js.map +1 -0
- package/dist/src/modes.d.ts +179 -0
- package/dist/src/modes.d.ts.map +1 -0
- package/dist/src/modes.js +385 -0
- package/dist/src/modes.js.map +1 -0
- package/dist/src/observability/tracer.d.ts +111 -0
- package/dist/src/observability/tracer.d.ts.map +1 -0
- package/dist/src/observability/tracer.js +300 -0
- package/dist/src/observability/tracer.js.map +1 -0
- package/dist/src/observability/types.d.ts +271 -0
- package/dist/src/observability/types.d.ts.map +1 -0
- package/dist/src/observability/types.js +24 -0
- package/dist/src/observability/types.js.map +1 -0
- package/dist/src/paths.d.ts +101 -0
- package/dist/src/paths.d.ts.map +1 -0
- package/dist/src/paths.js +148 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/persistence/index.d.ts +38 -0
- package/dist/src/persistence/index.d.ts.map +1 -0
- package/dist/src/persistence/index.js +48 -0
- package/dist/src/persistence/index.js.map +1 -0
- package/dist/src/persistence/migrator.d.ts +135 -0
- package/dist/src/persistence/migrator.d.ts.map +1 -0
- package/dist/src/persistence/migrator.js +303 -0
- package/dist/src/persistence/migrator.js.map +1 -0
- package/dist/src/persistence/schema.d.ts +101 -0
- package/dist/src/persistence/schema.d.ts.map +1 -0
- package/dist/src/persistence/schema.js +395 -0
- package/dist/src/persistence/schema.js.map +1 -0
- package/dist/src/providers/adapters/anthropic.d.ts +20 -0
- package/dist/src/providers/adapters/anthropic.d.ts.map +1 -0
- package/dist/src/providers/adapters/anthropic.js +124 -0
- package/dist/src/providers/adapters/anthropic.js.map +1 -0
- package/dist/src/providers/adapters/mock.d.ts +25 -0
- package/dist/src/providers/adapters/mock.d.ts.map +1 -0
- package/dist/src/providers/adapters/mock.js +133 -0
- package/dist/src/providers/adapters/mock.js.map +1 -0
- package/dist/src/providers/adapters/openai.d.ts +21 -0
- package/dist/src/providers/adapters/openai.d.ts.map +1 -0
- package/dist/src/providers/adapters/openai.js +126 -0
- package/dist/src/providers/adapters/openai.js.map +1 -0
- package/dist/src/providers/adapters/openrouter.d.ts +49 -0
- package/dist/src/providers/adapters/openrouter.d.ts.map +1 -0
- package/dist/src/providers/adapters/openrouter.js +363 -0
- package/dist/src/providers/adapters/openrouter.js.map +1 -0
- package/dist/src/providers/provider.d.ts +54 -0
- package/dist/src/providers/provider.d.ts.map +1 -0
- package/dist/src/providers/provider.js +111 -0
- package/dist/src/providers/provider.js.map +1 -0
- package/dist/src/providers/resilient-fetch.d.ts +99 -0
- package/dist/src/providers/resilient-fetch.d.ts.map +1 -0
- package/dist/src/providers/resilient-fetch.js +208 -0
- package/dist/src/providers/resilient-fetch.js.map +1 -0
- package/dist/src/providers/types.d.ts +227 -0
- package/dist/src/providers/types.d.ts.map +1 -0
- package/dist/src/providers/types.js +24 -0
- package/dist/src/providers/types.js.map +1 -0
- package/dist/src/session-picker.d.ts +28 -0
- package/dist/src/session-picker.d.ts.map +1 -0
- package/dist/src/session-picker.js +256 -0
- package/dist/src/session-picker.js.map +1 -0
- package/dist/src/test-sqlite.d.ts +2 -0
- package/dist/src/test-sqlite.d.ts.map +1 -0
- package/dist/src/test-sqlite.js +114 -0
- package/dist/src/test-sqlite.js.map +1 -0
- package/dist/src/tools/agent.d.ts +44 -0
- package/dist/src/tools/agent.d.ts.map +1 -0
- package/dist/src/tools/agent.js +110 -0
- package/dist/src/tools/agent.js.map +1 -0
- package/dist/src/tools/bash.d.ts +52 -0
- package/dist/src/tools/bash.d.ts.map +1 -0
- package/dist/src/tools/bash.js +141 -0
- package/dist/src/tools/bash.js.map +1 -0
- package/dist/src/tools/file.d.ts +47 -0
- package/dist/src/tools/file.d.ts.map +1 -0
- package/dist/src/tools/file.js +263 -0
- package/dist/src/tools/file.js.map +1 -0
- package/dist/src/tools/permission.d.ts +43 -0
- package/dist/src/tools/permission.d.ts.map +1 -0
- package/dist/src/tools/permission.js +216 -0
- package/dist/src/tools/permission.js.map +1 -0
- package/dist/src/tools/registry.d.ts +63 -0
- package/dist/src/tools/registry.d.ts.map +1 -0
- package/dist/src/tools/registry.js +250 -0
- package/dist/src/tools/registry.js.map +1 -0
- package/dist/src/tools/standard.d.ts +57 -0
- package/dist/src/tools/standard.d.ts.map +1 -0
- package/dist/src/tools/standard.js +113 -0
- package/dist/src/tools/standard.js.map +1 -0
- package/dist/src/tools/types.d.ts +146 -0
- package/dist/src/tools/types.d.ts.map +1 -0
- package/dist/src/tools/types.js +28 -0
- package/dist/src/tools/types.js.map +1 -0
- package/dist/src/tools/undo.d.ts +71 -0
- package/dist/src/tools/undo.d.ts.map +1 -0
- package/dist/src/tools/undo.js +123 -0
- package/dist/src/tools/undo.js.map +1 -0
- package/dist/src/tracing/cache-boundary-tracker.d.ts +189 -0
- package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -0
- package/dist/src/tracing/cache-boundary-tracker.js +411 -0
- package/dist/src/tracing/cache-boundary-tracker.js.map +1 -0
- package/dist/src/tracing/trace-collector.d.ts +274 -0
- package/dist/src/tracing/trace-collector.d.ts.map +1 -0
- package/dist/src/tracing/trace-collector.js +727 -0
- package/dist/src/tracing/trace-collector.js.map +1 -0
- package/dist/src/tracing/types.d.ts +657 -0
- package/dist/src/tracing/types.d.ts.map +1 -0
- package/dist/src/tracing/types.js +39 -0
- package/dist/src/tracing/types.js.map +1 -0
- package/dist/src/tricks/failure-evidence.d.ts +268 -0
- package/dist/src/tricks/failure-evidence.d.ts.map +1 -0
- package/dist/src/tricks/failure-evidence.js +544 -0
- package/dist/src/tricks/failure-evidence.js.map +1 -0
- package/dist/src/tricks/json-utils.d.ts +77 -0
- package/dist/src/tricks/json-utils.d.ts.map +1 -0
- package/dist/src/tricks/json-utils.js +247 -0
- package/dist/src/tricks/json-utils.js.map +1 -0
- package/dist/src/tricks/kv-cache-context.d.ts +227 -0
- package/dist/src/tricks/kv-cache-context.d.ts.map +1 -0
- package/dist/src/tricks/kv-cache-context.js +377 -0
- package/dist/src/tricks/kv-cache-context.js.map +1 -0
- package/dist/src/tricks/recitation.d.ts +208 -0
- package/dist/src/tricks/recitation.d.ts.map +1 -0
- package/dist/src/tricks/recitation.js +374 -0
- package/dist/src/tricks/recitation.js.map +1 -0
- package/dist/src/tricks/reversible-compaction.d.ts +251 -0
- package/dist/src/tricks/reversible-compaction.d.ts.map +1 -0
- package/dist/src/tricks/reversible-compaction.js +555 -0
- package/dist/src/tricks/reversible-compaction.js.map +1 -0
- package/dist/src/tricks/serialization-diversity.d.ts +197 -0
- package/dist/src/tricks/serialization-diversity.d.ts.map +1 -0
- package/dist/src/tricks/serialization-diversity.js +460 -0
- package/dist/src/tricks/serialization-diversity.js.map +1 -0
- package/dist/src/tui/app.d.ts +42 -0
- package/dist/src/tui/app.d.ts.map +1 -0
- package/dist/src/tui/app.js +1076 -0
- package/dist/src/tui/app.js.map +1 -0
- package/dist/src/tui/components/ApprovalDialog.d.ts +28 -0
- package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -0
- package/dist/src/tui/components/ApprovalDialog.js +59 -0
- package/dist/src/tui/components/ApprovalDialog.js.map +1 -0
- package/dist/src/tui/components/InputArea.d.ts +35 -0
- package/dist/src/tui/components/InputArea.d.ts.map +1 -0
- package/dist/src/tui/components/InputArea.js +144 -0
- package/dist/src/tui/components/InputArea.js.map +1 -0
- package/dist/src/tui/components/MessageItem.d.ts +28 -0
- package/dist/src/tui/components/MessageItem.d.ts.map +1 -0
- package/dist/src/tui/components/MessageItem.js +27 -0
- package/dist/src/tui/components/MessageItem.js.map +1 -0
- package/dist/src/tui/components/ScrollableBox.d.ts +41 -0
- package/dist/src/tui/components/ScrollableBox.d.ts.map +1 -0
- package/dist/src/tui/components/ScrollableBox.js +101 -0
- package/dist/src/tui/components/ScrollableBox.js.map +1 -0
- package/dist/src/tui/components/ToolCallItem.d.ts +33 -0
- package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -0
- package/dist/src/tui/components/ToolCallItem.js +91 -0
- package/dist/src/tui/components/ToolCallItem.js.map +1 -0
- package/dist/src/tui/components/index.d.ts +13 -0
- package/dist/src/tui/components/index.d.ts.map +1 -0
- package/dist/src/tui/components/index.js +15 -0
- package/dist/src/tui/components/index.js.map +1 -0
- package/dist/src/tui/event-display.d.ts +19 -0
- package/dist/src/tui/event-display.d.ts.map +1 -0
- package/dist/src/tui/event-display.js +178 -0
- package/dist/src/tui/event-display.js.map +1 -0
- package/dist/src/tui/index.d.ts +105 -0
- package/dist/src/tui/index.d.ts.map +1 -0
- package/dist/src/tui/index.js +214 -0
- package/dist/src/tui/index.js.map +1 -0
- package/dist/src/tui/input/CommandPalette.d.ts +55 -0
- package/dist/src/tui/input/CommandPalette.d.ts.map +1 -0
- package/dist/src/tui/input/CommandPalette.js +135 -0
- package/dist/src/tui/input/CommandPalette.js.map +1 -0
- package/dist/src/tui/input/index.d.ts +7 -0
- package/dist/src/tui/input/index.d.ts.map +1 -0
- package/dist/src/tui/input/index.js +7 -0
- package/dist/src/tui/input/index.js.map +1 -0
- package/dist/src/tui/theme/index.d.ts +45 -0
- package/dist/src/tui/theme/index.d.ts.map +1 -0
- package/dist/src/tui/theme/index.js +215 -0
- package/dist/src/tui/theme/index.js.map +1 -0
- package/dist/src/tui/types.d.ts +214 -0
- package/dist/src/tui/types.d.ts.map +1 -0
- package/dist/src/tui/types.js +27 -0
- package/dist/src/tui/types.js.map +1 -0
- package/dist/src/types.d.ts +905 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +9 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lesson 25: MCP Client
|
|
3
|
+
*
|
|
4
|
+
* Connects to Model Context Protocol (MCP) servers to extend agent capabilities.
|
|
5
|
+
* Supports stdio-based servers (spawned as child processes).
|
|
6
|
+
*/
|
|
7
|
+
import { spawn } from 'node:child_process';
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { createInterface } from 'node:readline';
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// MCP CLIENT
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* MCP Client manages connections to MCP servers.
|
|
16
|
+
*/
|
|
17
|
+
export class MCPClient {
|
|
18
|
+
config;
|
|
19
|
+
servers = new Map();
|
|
20
|
+
listeners = [];
|
|
21
|
+
constructor(config = {}) {
|
|
22
|
+
this.config = {
|
|
23
|
+
configPath: config.configPath || '.mcp.json',
|
|
24
|
+
configPaths: config.configPaths ?? [],
|
|
25
|
+
requestTimeout: config.requestTimeout ?? 30000,
|
|
26
|
+
autoConnect: config.autoConnect ?? true,
|
|
27
|
+
lazyLoading: config.lazyLoading ?? false,
|
|
28
|
+
alwaysLoadTools: config.alwaysLoadTools ?? [],
|
|
29
|
+
summaryDescriptionLimit: config.summaryDescriptionLimit ?? 100,
|
|
30
|
+
maxToolsPerSearch: config.maxToolsPerSearch ?? 5,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Load servers from config file.
|
|
35
|
+
*/
|
|
36
|
+
async loadFromConfig(configPath) {
|
|
37
|
+
const path = configPath || this.config.configPath;
|
|
38
|
+
if (!existsSync(path)) {
|
|
39
|
+
return; // No config file, silently skip
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const content = await readFile(path, 'utf-8');
|
|
43
|
+
const mcpConfig = JSON.parse(content);
|
|
44
|
+
for (const [name, serverConfig] of Object.entries(mcpConfig.servers)) {
|
|
45
|
+
// Expand environment variables in config
|
|
46
|
+
const expandedConfig = this.expandEnvVars(serverConfig);
|
|
47
|
+
this.registerServer(name, expandedConfig);
|
|
48
|
+
if (this.config.autoConnect) {
|
|
49
|
+
await this.connectServer(name).catch(err => {
|
|
50
|
+
console.warn(`[MCP] Failed to connect to ${name}:`, err.message);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.warn(`[MCP] Failed to load config from ${path}:`, err);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Load servers from multiple config files (hierarchical).
|
|
61
|
+
* Later configs override earlier ones for the same server name.
|
|
62
|
+
* Servers from all configs are merged together.
|
|
63
|
+
*/
|
|
64
|
+
async loadFromHierarchicalConfigs(configPaths) {
|
|
65
|
+
const mergedServers = {};
|
|
66
|
+
// Load and merge all configs
|
|
67
|
+
for (const configPath of configPaths) {
|
|
68
|
+
if (!existsSync(configPath)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const content = await readFile(configPath, 'utf-8');
|
|
73
|
+
const mcpConfig = JSON.parse(content);
|
|
74
|
+
// Merge servers (later overrides earlier)
|
|
75
|
+
for (const [name, serverConfig] of Object.entries(mcpConfig.servers)) {
|
|
76
|
+
mergedServers[name] = this.expandEnvVars(serverConfig);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.warn(`[MCP] Failed to load config from ${configPath}:`, err);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Register all merged servers
|
|
84
|
+
for (const [name, config] of Object.entries(mergedServers)) {
|
|
85
|
+
this.registerServer(name, config);
|
|
86
|
+
if (this.config.autoConnect) {
|
|
87
|
+
await this.connectServer(name).catch(err => {
|
|
88
|
+
console.warn(`[MCP] Failed to connect to ${name}:`, err.message);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Expand environment variables in config.
|
|
95
|
+
*/
|
|
96
|
+
expandEnvVars(config) {
|
|
97
|
+
const expand = (str) => {
|
|
98
|
+
return str.replace(/\$\{(\w+)\}/g, (_, name) => process.env[name] || '');
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
command: expand(config.command),
|
|
102
|
+
args: config.args?.map(expand),
|
|
103
|
+
env: config.env
|
|
104
|
+
? Object.fromEntries(Object.entries(config.env).map(([k, v]) => [k, expand(v)]))
|
|
105
|
+
: undefined,
|
|
106
|
+
cwd: config.cwd ? expand(config.cwd) : undefined,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Register a server (without connecting).
|
|
111
|
+
*/
|
|
112
|
+
registerServer(name, config) {
|
|
113
|
+
this.servers.set(name, {
|
|
114
|
+
name,
|
|
115
|
+
config,
|
|
116
|
+
process: null,
|
|
117
|
+
readline: null,
|
|
118
|
+
tools: [],
|
|
119
|
+
status: 'disconnected',
|
|
120
|
+
pendingRequests: new Map(),
|
|
121
|
+
nextRequestId: 1,
|
|
122
|
+
loadedTools: new Set(),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Connect to a registered server.
|
|
127
|
+
*/
|
|
128
|
+
async connectServer(name) {
|
|
129
|
+
const server = this.servers.get(name);
|
|
130
|
+
if (!server) {
|
|
131
|
+
throw new Error(`Server not registered: ${name}`);
|
|
132
|
+
}
|
|
133
|
+
if (server.status === 'connected') {
|
|
134
|
+
return; // Already connected
|
|
135
|
+
}
|
|
136
|
+
server.status = 'connecting';
|
|
137
|
+
this.emit({ type: 'server.connecting', name });
|
|
138
|
+
try {
|
|
139
|
+
// Spawn the server process
|
|
140
|
+
const proc = spawn(server.config.command, server.config.args || [], {
|
|
141
|
+
env: { ...process.env, ...server.config.env },
|
|
142
|
+
cwd: server.config.cwd,
|
|
143
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
144
|
+
});
|
|
145
|
+
server.process = proc;
|
|
146
|
+
// Set up readline for stdout
|
|
147
|
+
server.readline = createInterface({
|
|
148
|
+
input: proc.stdout,
|
|
149
|
+
crlfDelay: Infinity,
|
|
150
|
+
});
|
|
151
|
+
// Handle incoming messages
|
|
152
|
+
server.readline.on('line', (line) => {
|
|
153
|
+
this.handleServerMessage(server, line);
|
|
154
|
+
});
|
|
155
|
+
// Handle errors
|
|
156
|
+
proc.stderr?.on('data', (data) => {
|
|
157
|
+
console.error(`[MCP ${name}] stderr:`, data.toString());
|
|
158
|
+
});
|
|
159
|
+
proc.on('error', (err) => {
|
|
160
|
+
server.status = 'error';
|
|
161
|
+
server.error = err.message;
|
|
162
|
+
// CRITICAL: Reject ALL pending requests before clearing
|
|
163
|
+
const errorMsg = new Error(`MCP server "${name}" process error: ${err.message}`);
|
|
164
|
+
for (const [_id, pending] of server.pendingRequests) {
|
|
165
|
+
pending.reject(errorMsg);
|
|
166
|
+
}
|
|
167
|
+
server.pendingRequests.clear();
|
|
168
|
+
this.emit({ type: 'server.error', name, error: err.message });
|
|
169
|
+
});
|
|
170
|
+
proc.on('exit', (code, signal) => {
|
|
171
|
+
// CRITICAL: Reject ALL pending requests before clearing
|
|
172
|
+
// This prevents orphaned promises that never resolve
|
|
173
|
+
const exitError = new Error(`MCP server "${name}" exited unexpectedly (code: ${code}, signal: ${signal})`);
|
|
174
|
+
for (const [_id, pending] of server.pendingRequests) {
|
|
175
|
+
pending.reject(exitError);
|
|
176
|
+
}
|
|
177
|
+
server.pendingRequests.clear();
|
|
178
|
+
server.status = 'disconnected';
|
|
179
|
+
server.process = null;
|
|
180
|
+
server.readline = null;
|
|
181
|
+
this.emit({ type: 'server.disconnected', name });
|
|
182
|
+
});
|
|
183
|
+
// Initialize the connection
|
|
184
|
+
await this.initializeServer(server);
|
|
185
|
+
server.status = 'connected';
|
|
186
|
+
this.emit({ type: 'server.connected', name, toolCount: server.tools.length });
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
server.status = 'error';
|
|
190
|
+
server.error = err instanceof Error ? err.message : String(err);
|
|
191
|
+
this.emit({ type: 'server.error', name, error: server.error });
|
|
192
|
+
throw err;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Initialize MCP protocol with server.
|
|
197
|
+
*/
|
|
198
|
+
async initializeServer(server) {
|
|
199
|
+
// Send initialize request
|
|
200
|
+
const initResult = await this.sendRequest(server, 'initialize', {
|
|
201
|
+
protocolVersion: '2024-11-05',
|
|
202
|
+
capabilities: {},
|
|
203
|
+
clientInfo: {
|
|
204
|
+
name: 'first-principles-agent',
|
|
205
|
+
version: '1.0.0',
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
// Send initialized notification
|
|
209
|
+
this.sendNotification(server, 'notifications/initialized', {});
|
|
210
|
+
// List available tools
|
|
211
|
+
const toolsResult = await this.sendRequest(server, 'tools/list', {});
|
|
212
|
+
server.tools = toolsResult.tools || [];
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Send a JSON-RPC request and wait for response.
|
|
216
|
+
*/
|
|
217
|
+
sendRequest(server, method, params) {
|
|
218
|
+
return new Promise((resolve, reject) => {
|
|
219
|
+
const id = server.nextRequestId++;
|
|
220
|
+
const request = {
|
|
221
|
+
jsonrpc: '2.0',
|
|
222
|
+
id,
|
|
223
|
+
method,
|
|
224
|
+
params,
|
|
225
|
+
};
|
|
226
|
+
server.pendingRequests.set(id, { resolve, reject });
|
|
227
|
+
// Set timeout
|
|
228
|
+
const timeout = setTimeout(() => {
|
|
229
|
+
server.pendingRequests.delete(id);
|
|
230
|
+
reject(new Error(`Request timeout: ${method}`));
|
|
231
|
+
}, this.config.requestTimeout);
|
|
232
|
+
// Store timeout to clear later
|
|
233
|
+
const originalResolve = resolve;
|
|
234
|
+
server.pendingRequests.set(id, {
|
|
235
|
+
resolve: (result) => {
|
|
236
|
+
clearTimeout(timeout);
|
|
237
|
+
originalResolve(result);
|
|
238
|
+
},
|
|
239
|
+
reject: (error) => {
|
|
240
|
+
clearTimeout(timeout);
|
|
241
|
+
reject(error);
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
// Send request
|
|
245
|
+
server.process?.stdin?.write(JSON.stringify(request) + '\n');
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Send a JSON-RPC notification (no response expected).
|
|
250
|
+
*/
|
|
251
|
+
sendNotification(server, method, params) {
|
|
252
|
+
const notification = {
|
|
253
|
+
jsonrpc: '2.0',
|
|
254
|
+
method,
|
|
255
|
+
params,
|
|
256
|
+
};
|
|
257
|
+
server.process?.stdin?.write(JSON.stringify(notification) + '\n');
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Handle incoming message from server.
|
|
261
|
+
*/
|
|
262
|
+
handleServerMessage(server, line) {
|
|
263
|
+
let message;
|
|
264
|
+
try {
|
|
265
|
+
message = JSON.parse(line);
|
|
266
|
+
}
|
|
267
|
+
catch (parseError) {
|
|
268
|
+
// Log malformed JSON instead of silently ignoring
|
|
269
|
+
// This helps diagnose protocol desync issues
|
|
270
|
+
const preview = line.length > 100 ? line.substring(0, 100) + '...' : line;
|
|
271
|
+
console.error(`[MCP ${server.name}] Malformed JSON-RPC message: ${preview}`);
|
|
272
|
+
this.emit({ type: 'server.error', name: server.name, error: 'Protocol error: malformed JSON' });
|
|
273
|
+
return; // Don't crash, just skip this malformed message
|
|
274
|
+
}
|
|
275
|
+
// Handle response
|
|
276
|
+
if (message.id !== undefined) {
|
|
277
|
+
const pending = server.pendingRequests.get(message.id);
|
|
278
|
+
if (pending) {
|
|
279
|
+
server.pendingRequests.delete(message.id);
|
|
280
|
+
if (message.error) {
|
|
281
|
+
pending.reject(new Error(message.error.message || 'Unknown error'));
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
pending.resolve(message.result);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Handle notifications from server (if any)
|
|
289
|
+
// MCP servers can send notifications for things like resource updates
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Disconnect from a server.
|
|
293
|
+
*/
|
|
294
|
+
async disconnectServer(name) {
|
|
295
|
+
const server = this.servers.get(name);
|
|
296
|
+
if (!server) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (server.process) {
|
|
300
|
+
server.process.kill();
|
|
301
|
+
server.process = null;
|
|
302
|
+
}
|
|
303
|
+
if (server.readline) {
|
|
304
|
+
server.readline.close();
|
|
305
|
+
server.readline = null;
|
|
306
|
+
}
|
|
307
|
+
server.status = 'disconnected';
|
|
308
|
+
server.tools = [];
|
|
309
|
+
this.emit({ type: 'server.disconnected', name });
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Call a tool on a specific server.
|
|
313
|
+
*/
|
|
314
|
+
async callTool(serverName, toolName, args) {
|
|
315
|
+
const server = this.servers.get(serverName);
|
|
316
|
+
if (!server) {
|
|
317
|
+
throw new Error(`Server not found: ${serverName}`);
|
|
318
|
+
}
|
|
319
|
+
if (server.status !== 'connected') {
|
|
320
|
+
throw new Error(`Server not connected: ${serverName}`);
|
|
321
|
+
}
|
|
322
|
+
this.emit({ type: 'tool.call', server: serverName, tool: toolName });
|
|
323
|
+
try {
|
|
324
|
+
const result = await this.sendRequest(server, 'tools/call', {
|
|
325
|
+
name: toolName,
|
|
326
|
+
arguments: args,
|
|
327
|
+
});
|
|
328
|
+
this.emit({ type: 'tool.result', server: serverName, tool: toolName, success: true });
|
|
329
|
+
// Extract text content from result
|
|
330
|
+
const textContent = result.content
|
|
331
|
+
?.filter(c => c.type === 'text')
|
|
332
|
+
.map(c => c.text)
|
|
333
|
+
.join('\n');
|
|
334
|
+
return textContent || result;
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
this.emit({ type: 'tool.result', server: serverName, tool: toolName, success: false });
|
|
338
|
+
throw err;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* List all servers and their status.
|
|
343
|
+
*/
|
|
344
|
+
listServers() {
|
|
345
|
+
return Array.from(this.servers.values()).map(s => ({
|
|
346
|
+
name: s.name,
|
|
347
|
+
status: s.status,
|
|
348
|
+
toolCount: s.tools.length,
|
|
349
|
+
error: s.error,
|
|
350
|
+
}));
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get tools from a specific server.
|
|
354
|
+
*/
|
|
355
|
+
getServerTools(serverName) {
|
|
356
|
+
const server = this.servers.get(serverName);
|
|
357
|
+
return server?.tools || [];
|
|
358
|
+
}
|
|
359
|
+
// ===========================================================================
|
|
360
|
+
// LAZY LOADING METHODS
|
|
361
|
+
// ===========================================================================
|
|
362
|
+
/**
|
|
363
|
+
* Get lightweight summaries for all tools (low token cost).
|
|
364
|
+
* Use this for initial context, then load full definitions on-demand.
|
|
365
|
+
*/
|
|
366
|
+
getAllToolSummaries() {
|
|
367
|
+
const summaries = [];
|
|
368
|
+
const descLimit = this.config.summaryDescriptionLimit;
|
|
369
|
+
for (const server of this.servers.values()) {
|
|
370
|
+
if (server.status !== 'connected')
|
|
371
|
+
continue;
|
|
372
|
+
for (const tool of server.tools) {
|
|
373
|
+
const fullName = `mcp_${server.name}_${tool.name}`;
|
|
374
|
+
const desc = tool.description || `MCP tool: ${tool.name}`;
|
|
375
|
+
summaries.push({
|
|
376
|
+
name: fullName,
|
|
377
|
+
description: desc.length > descLimit ? desc.slice(0, descLimit) + '...' : desc,
|
|
378
|
+
serverName: server.name,
|
|
379
|
+
originalName: tool.name,
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return summaries;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Search tools by name or description with BM25-style scoring.
|
|
387
|
+
* Returns matching tool summaries sorted by relevance.
|
|
388
|
+
*/
|
|
389
|
+
searchTools(query, options = {}) {
|
|
390
|
+
const { limit = this.config.maxToolsPerSearch, regex = false } = options;
|
|
391
|
+
const summaries = this.getAllToolSummaries();
|
|
392
|
+
if (!query.trim()) {
|
|
393
|
+
return summaries.slice(0, limit);
|
|
394
|
+
}
|
|
395
|
+
// Normalize query
|
|
396
|
+
const queryLower = query.toLowerCase();
|
|
397
|
+
const queryTerms = queryLower.split(/\s+/).filter(t => t.length > 0);
|
|
398
|
+
// Score each tool
|
|
399
|
+
const scored = summaries.map(summary => {
|
|
400
|
+
let score = 0;
|
|
401
|
+
const nameLower = summary.name.toLowerCase();
|
|
402
|
+
const descLower = summary.description.toLowerCase();
|
|
403
|
+
const originalLower = summary.originalName.toLowerCase();
|
|
404
|
+
if (regex) {
|
|
405
|
+
try {
|
|
406
|
+
const re = new RegExp(query, 'i');
|
|
407
|
+
if (re.test(summary.name))
|
|
408
|
+
score += 10;
|
|
409
|
+
if (re.test(summary.description))
|
|
410
|
+
score += 5;
|
|
411
|
+
if (re.test(summary.originalName))
|
|
412
|
+
score += 8;
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
// Invalid regex, fall back to substring matching
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// BM25-style term frequency scoring
|
|
419
|
+
for (const term of queryTerms) {
|
|
420
|
+
// Exact match bonuses
|
|
421
|
+
if (originalLower === term)
|
|
422
|
+
score += 20;
|
|
423
|
+
if (nameLower.includes(term))
|
|
424
|
+
score += 10;
|
|
425
|
+
if (originalLower.includes(term))
|
|
426
|
+
score += 8;
|
|
427
|
+
if (descLower.includes(term))
|
|
428
|
+
score += 3;
|
|
429
|
+
// Partial match (prefix)
|
|
430
|
+
if (originalLower.startsWith(term))
|
|
431
|
+
score += 5;
|
|
432
|
+
}
|
|
433
|
+
// Boost if all terms appear
|
|
434
|
+
const allTermsInName = queryTerms.every(t => nameLower.includes(t));
|
|
435
|
+
const allTermsInDesc = queryTerms.every(t => descLower.includes(t));
|
|
436
|
+
if (allTermsInName)
|
|
437
|
+
score += 15;
|
|
438
|
+
if (allTermsInDesc)
|
|
439
|
+
score += 5;
|
|
440
|
+
return { summary, score };
|
|
441
|
+
});
|
|
442
|
+
// Filter and sort by score
|
|
443
|
+
const results = scored
|
|
444
|
+
.filter(s => s.score > 0)
|
|
445
|
+
.sort((a, b) => b.score - a.score)
|
|
446
|
+
.slice(0, limit)
|
|
447
|
+
.map(s => s.summary);
|
|
448
|
+
this.emit({ type: 'tool.search', query, resultCount: results.length });
|
|
449
|
+
return results;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Get full tool definition for a specific tool.
|
|
453
|
+
* Marks the tool as loaded for context tracking.
|
|
454
|
+
*/
|
|
455
|
+
getFullToolDefinition(toolName) {
|
|
456
|
+
// Parse tool name: mcp_{serverName}_{originalToolName}
|
|
457
|
+
const match = toolName.match(/^mcp_([^_]+)_(.+)$/);
|
|
458
|
+
if (!match)
|
|
459
|
+
return null;
|
|
460
|
+
const [, serverName, originalName] = match;
|
|
461
|
+
const server = this.servers.get(serverName);
|
|
462
|
+
if (!server || server.status !== 'connected')
|
|
463
|
+
return null;
|
|
464
|
+
const mcpTool = server.tools.find(t => t.name === originalName);
|
|
465
|
+
if (!mcpTool)
|
|
466
|
+
return null;
|
|
467
|
+
// Mark as loaded
|
|
468
|
+
server.loadedTools.add(originalName);
|
|
469
|
+
this.emit({ type: 'tool.dynamicLoad', name: toolName, serverName });
|
|
470
|
+
return {
|
|
471
|
+
name: toolName,
|
|
472
|
+
description: mcpTool.description || `MCP tool: ${mcpTool.name} (from ${serverName})`,
|
|
473
|
+
parameters: mcpTool.inputSchema || { type: 'object', properties: {} },
|
|
474
|
+
execute: async (args) => {
|
|
475
|
+
return this.callTool(serverName, originalName, args);
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Batch load multiple tools by name.
|
|
481
|
+
* Returns array of loaded ToolDefinitions.
|
|
482
|
+
*/
|
|
483
|
+
loadTools(toolNames) {
|
|
484
|
+
const loaded = [];
|
|
485
|
+
for (const name of toolNames) {
|
|
486
|
+
const tool = this.getFullToolDefinition(name);
|
|
487
|
+
if (tool) {
|
|
488
|
+
loaded.push(tool);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return loaded;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Get context statistics for MCP tools.
|
|
495
|
+
* Useful for monitoring token usage with lazy loading.
|
|
496
|
+
*/
|
|
497
|
+
getContextStats() {
|
|
498
|
+
let summaryCount = 0;
|
|
499
|
+
let loadedCount = 0;
|
|
500
|
+
let summaryTokens = 0;
|
|
501
|
+
let definitionTokens = 0;
|
|
502
|
+
for (const server of this.servers.values()) {
|
|
503
|
+
if (server.status !== 'connected')
|
|
504
|
+
continue;
|
|
505
|
+
for (const tool of server.tools) {
|
|
506
|
+
const isLoaded = server.loadedTools.has(tool.name);
|
|
507
|
+
if (isLoaded) {
|
|
508
|
+
loadedCount++;
|
|
509
|
+
// Full definition tokens: name + description + schema
|
|
510
|
+
const schemaStr = tool.inputSchema ? JSON.stringify(tool.inputSchema) : '{}';
|
|
511
|
+
const defChars = (tool.name.length) +
|
|
512
|
+
(tool.description?.length || 0) +
|
|
513
|
+
schemaStr.length;
|
|
514
|
+
definitionTokens += Math.ceil(defChars / 4); // ~4 chars per token
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
summaryCount++;
|
|
518
|
+
// Summary tokens: name + truncated description
|
|
519
|
+
const descLen = Math.min(tool.description?.length || 0, this.config.summaryDescriptionLimit);
|
|
520
|
+
const sumChars = tool.name.length + descLen + server.name.length;
|
|
521
|
+
summaryTokens += Math.ceil(sumChars / 4);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return {
|
|
526
|
+
summaryTokens,
|
|
527
|
+
definitionTokens,
|
|
528
|
+
summaryCount,
|
|
529
|
+
loadedCount,
|
|
530
|
+
totalTools: summaryCount + loadedCount,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Check if a tool is fully loaded (has schema in context).
|
|
535
|
+
*/
|
|
536
|
+
isToolLoaded(toolName) {
|
|
537
|
+
const match = toolName.match(/^mcp_([^_]+)_(.+)$/);
|
|
538
|
+
if (!match)
|
|
539
|
+
return false;
|
|
540
|
+
const [, serverName, originalName] = match;
|
|
541
|
+
const server = this.servers.get(serverName);
|
|
542
|
+
return server?.loadedTools.has(originalName) ?? false;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Get all tools with lazy loading support.
|
|
546
|
+
* When lazyMode is true, only returns always-loaded tools + previously loaded tools.
|
|
547
|
+
* When lazyMode is false (default), returns all tools with full definitions.
|
|
548
|
+
*/
|
|
549
|
+
getAllTools(options = {}) {
|
|
550
|
+
const { lazyMode = this.config.lazyLoading } = options;
|
|
551
|
+
if (!lazyMode) {
|
|
552
|
+
// Original behavior: return all tools with full definitions
|
|
553
|
+
const tools = [];
|
|
554
|
+
for (const server of this.servers.values()) {
|
|
555
|
+
if (server.status !== 'connected')
|
|
556
|
+
continue;
|
|
557
|
+
for (const tool of server.tools) {
|
|
558
|
+
tools.push({
|
|
559
|
+
name: `mcp_${server.name}_${tool.name}`,
|
|
560
|
+
description: tool.description || `MCP tool: ${tool.name} (from ${server.name})`,
|
|
561
|
+
parameters: tool.inputSchema || { type: 'object', properties: {} },
|
|
562
|
+
execute: async (args) => {
|
|
563
|
+
return this.callTool(server.name, tool.name, args);
|
|
564
|
+
},
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return tools;
|
|
569
|
+
}
|
|
570
|
+
// Lazy mode: only return always-loaded tools + previously loaded tools
|
|
571
|
+
const tools = [];
|
|
572
|
+
for (const server of this.servers.values()) {
|
|
573
|
+
if (server.status !== 'connected')
|
|
574
|
+
continue;
|
|
575
|
+
for (const tool of server.tools) {
|
|
576
|
+
const fullName = `mcp_${server.name}_${tool.name}`;
|
|
577
|
+
const isAlwaysLoaded = this.config.alwaysLoadTools.some(pattern => fullName.includes(pattern) || tool.name.includes(pattern));
|
|
578
|
+
const isPreviouslyLoaded = server.loadedTools.has(tool.name);
|
|
579
|
+
if (isAlwaysLoaded || isPreviouslyLoaded) {
|
|
580
|
+
// Mark as loaded
|
|
581
|
+
server.loadedTools.add(tool.name);
|
|
582
|
+
tools.push({
|
|
583
|
+
name: fullName,
|
|
584
|
+
description: tool.description || `MCP tool: ${tool.name} (from ${server.name})`,
|
|
585
|
+
parameters: tool.inputSchema || { type: 'object', properties: {} },
|
|
586
|
+
execute: async (args) => {
|
|
587
|
+
return this.callTool(server.name, tool.name, args);
|
|
588
|
+
},
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return tools;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Check if a server is connected.
|
|
597
|
+
*/
|
|
598
|
+
isConnected(serverName) {
|
|
599
|
+
const server = this.servers.get(serverName);
|
|
600
|
+
return server?.status === 'connected';
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Subscribe to events.
|
|
604
|
+
*/
|
|
605
|
+
on(listener) {
|
|
606
|
+
this.listeners.push(listener);
|
|
607
|
+
return () => {
|
|
608
|
+
const idx = this.listeners.indexOf(listener);
|
|
609
|
+
if (idx >= 0)
|
|
610
|
+
this.listeners.splice(idx, 1);
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Emit an event.
|
|
615
|
+
*/
|
|
616
|
+
emit(event) {
|
|
617
|
+
for (const listener of this.listeners) {
|
|
618
|
+
try {
|
|
619
|
+
listener(event);
|
|
620
|
+
}
|
|
621
|
+
catch {
|
|
622
|
+
// Ignore listener errors
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Cleanup - disconnect all servers.
|
|
628
|
+
*/
|
|
629
|
+
async cleanup() {
|
|
630
|
+
for (const name of this.servers.keys()) {
|
|
631
|
+
await this.disconnectServer(name);
|
|
632
|
+
}
|
|
633
|
+
this.servers.clear();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
// =============================================================================
|
|
637
|
+
// FACTORY
|
|
638
|
+
// =============================================================================
|
|
639
|
+
/**
|
|
640
|
+
* Create and initialize an MCP client.
|
|
641
|
+
*/
|
|
642
|
+
export async function createMCPClient(config) {
|
|
643
|
+
const client = new MCPClient(config);
|
|
644
|
+
// Use hierarchical loading if configPaths provided, otherwise single config
|
|
645
|
+
if (config?.configPaths && config.configPaths.length > 0) {
|
|
646
|
+
await client.loadFromHierarchicalConfigs(config.configPaths);
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
await client.loadFromConfig();
|
|
650
|
+
}
|
|
651
|
+
return client;
|
|
652
|
+
}
|
|
653
|
+
// =============================================================================
|
|
654
|
+
// UTILITIES
|
|
655
|
+
// =============================================================================
|
|
656
|
+
/**
|
|
657
|
+
* Format server list for display.
|
|
658
|
+
*/
|
|
659
|
+
export function formatServerList(servers) {
|
|
660
|
+
if (servers.length === 0) {
|
|
661
|
+
return 'No MCP servers configured.';
|
|
662
|
+
}
|
|
663
|
+
const lines = ['MCP Servers:'];
|
|
664
|
+
for (const server of servers) {
|
|
665
|
+
const statusIcon = server.status === 'connected' ? '✓' : server.status === 'error' ? '✗' : '○';
|
|
666
|
+
const statusColor = server.status === 'connected' ? 'green' : server.status === 'error' ? 'red' : 'dim';
|
|
667
|
+
lines.push(` ${statusIcon} ${server.name} (${server.status}) - ${server.toolCount} tools`);
|
|
668
|
+
if (server.error) {
|
|
669
|
+
lines.push(` Error: ${server.error}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return lines.join('\n');
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Create a sample .mcp.json config file content.
|
|
676
|
+
*/
|
|
677
|
+
export function getSampleMCPConfig() {
|
|
678
|
+
return JSON.stringify({
|
|
679
|
+
servers: {
|
|
680
|
+
filesystem: {
|
|
681
|
+
command: 'npx',
|
|
682
|
+
args: ['-y', '@anthropic/mcp-server-filesystem', '/path/to/allowed/dir'],
|
|
683
|
+
},
|
|
684
|
+
sqlite: {
|
|
685
|
+
command: 'npx',
|
|
686
|
+
args: ['-y', '@anthropic/mcp-server-sqlite', '~/database.db'],
|
|
687
|
+
},
|
|
688
|
+
github: {
|
|
689
|
+
command: 'npx',
|
|
690
|
+
args: ['-y', '@anthropic/mcp-server-github'],
|
|
691
|
+
env: {
|
|
692
|
+
GITHUB_TOKEN: '${GITHUB_TOKEN}',
|
|
693
|
+
},
|
|
694
|
+
},
|
|
695
|
+
},
|
|
696
|
+
}, null, 2);
|
|
697
|
+
}
|
|
698
|
+
//# sourceMappingURL=mcp-client.js.map
|