@phuetz/code-buddy 2.0.0 → 2.2.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/README.fr.md +56 -0
- package/README.md +74 -16
- package/codebuddy-runtime.json +5 -5
- package/dist/agent/codebuddy-agent.d.ts +18 -0
- package/dist/agent/codebuddy-agent.js +45 -8
- package/dist/agent/execution/agent-executor.d.ts +0 -9
- package/dist/agent/execution/agent-executor.js +176 -12
- package/dist/agent/execution/context-pipeline.d.ts +9 -0
- package/dist/agent/execution/context-pipeline.js +64 -2
- package/dist/agent/execution/tool-loop-guard.d.ts +76 -0
- package/dist/agent/execution/tool-loop-guard.js +165 -0
- package/dist/agent/execution/tool-selection-strategy.d.ts +7 -0
- package/dist/agent/execution/tool-selection-strategy.js +32 -2
- package/dist/agent/facades/session-facade.d.ts +0 -6
- package/dist/agent/facades/session-facade.js +0 -45
- package/dist/agent/hermes-claw-migrate.d.ts +0 -21
- package/dist/agent/hermes-claw-migrate.js +9 -4
- package/dist/agent/hermes-protocol-gateways.js +8 -1
- package/dist/agent/repo-profiler.js +17 -4
- package/dist/agent/self-improvement/authored-tool-runtime.js +10 -2
- package/dist/agent/self-improvement/evolution/ast-novelty.d.ts +5 -0
- package/dist/agent/self-improvement/evolution/ast-novelty.js +58 -23
- package/dist/agent/self-improvement/evolution/code-variant-store.d.ts +3 -0
- package/dist/agent/self-improvement/evolution/evolution-engine.js +2 -0
- package/dist/agent/self-improvement/evolution/protected-paths.js +6 -0
- package/dist/agent/self-improvement/evolution/variant-fitness.d.ts +13 -2
- package/dist/agent/self-improvement/evolution/variant-fitness.js +184 -58
- package/dist/agent/self-improvement/evolution/worktree-scorer.d.ts +2 -0
- package/dist/agent/self-improvement/evolution/worktree-scorer.js +15 -0
- package/dist/agent/self-improvement/evolutionary-archive.d.ts +2 -1
- package/dist/agent/self-improvement/evolutionary-archive.js +34 -5
- package/dist/agent/self-improvement/proposal-store.d.ts +1 -0
- package/dist/agent/self-improvement/proposal-store.js +79 -17
- package/dist/agent/self-improvement/skill-apply-journal.d.ts +44 -0
- package/dist/agent/self-improvement/skill-apply-journal.js +178 -0
- package/dist/agent/self-improvement/skill-behavior-benchmark.d.ts +3 -0
- package/dist/agent/self-improvement/skill-behavior-benchmark.js +19 -0
- package/dist/agent/self-improvement/skill-behavior-gate.d.ts +34 -0
- package/dist/agent/self-improvement/skill-behavior-gate.js +96 -0
- package/dist/agent/self-improvement/skill-engine.d.ts +22 -0
- package/dist/agent/self-improvement/skill-engine.js +385 -13
- package/dist/agent/self-improvement/skill-gate.d.ts +2 -0
- package/dist/agent/self-improvement/skill-gate.js +17 -2
- package/dist/agent/self-improvement/skill-mutator.d.ts +6 -1
- package/dist/agent/self-improvement/skill-mutator.js +51 -15
- package/dist/agent/self-improvement/skill-types.d.ts +2 -1
- package/dist/agent/self-improvement/types.d.ts +11 -0
- package/dist/agent/tool-handler.d.ts +1 -1
- package/dist/agent/tool-handler.js +28 -9
- package/dist/auth/profile-manager.js +1 -1
- package/dist/channels/companion-channel-turn.d.ts +53 -4
- package/dist/channels/companion-channel-turn.js +218 -16
- package/dist/channels/slash-parity.d.ts +4 -6
- package/dist/channels/slash-parity.js +9 -44
- package/dist/cli/session-commands.d.ts +9 -0
- package/dist/cli/session-commands.js +45 -5
- package/dist/cli/session-picker.d.ts +43 -0
- package/dist/cli/session-picker.js +128 -0
- package/dist/codebuddy/a2a-call-tool-defs.d.ts +26 -0
- package/dist/codebuddy/a2a-call-tool-defs.js +12 -0
- package/dist/codebuddy/fleet-tool-defs.d.ts +2 -0
- package/dist/codebuddy/fleet-tool-defs.js +55 -0
- package/dist/codebuddy/providers/chatgpt-headers.d.ts +18 -0
- package/dist/codebuddy/providers/chatgpt-headers.js +37 -0
- package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +2 -1
- package/dist/codebuddy/providers/provider-chatgpt-responses.js +10 -23
- package/dist/codebuddy/providers/provider-openai-compat.d.ts +7 -0
- package/dist/codebuddy/providers/provider-openai-compat.js +29 -1
- package/dist/codebuddy/ragchat-tool-defs.d.ts +31 -0
- package/dist/codebuddy/ragchat-tool-defs.js +19 -0
- package/dist/codebuddy/resource-catalog-tool-defs.d.ts +28 -0
- package/dist/codebuddy/resource-catalog-tool-defs.js +18 -0
- package/dist/codebuddy/tool-definitions/agent-tools.js +2 -2
- package/dist/codebuddy/tool-definitions/code-exec-tools.js +5 -1
- package/dist/codebuddy/tool-definitions/cron-tools.js +6 -0
- package/dist/codebuddy/tool-definitions/self-describe-tools.js +6 -1
- package/dist/codebuddy/tools.d.ts +0 -6
- package/dist/codebuddy/tools.js +25 -3
- package/dist/commands/cli/daemon-commands.js +3 -1
- package/dist/commands/cli/evolve-command.js +21 -5
- package/dist/commands/cli/fleet-collaboration-commands.d.ts +2 -0
- package/dist/commands/cli/fleet-collaboration-commands.js +57 -0
- package/dist/commands/cli/fleet-commands.js +29 -0
- package/dist/commands/cli/fleet-mission-commands.d.ts +3 -0
- package/dist/commands/cli/fleet-mission-commands.js +72 -0
- package/dist/commands/cli/fleet-rooms-commands.d.ts +10 -0
- package/dist/commands/cli/fleet-rooms-commands.js +289 -0
- package/dist/commands/cli/tools-commands.js +2 -1
- package/dist/commands/cli/triage-command.d.ts +8 -0
- package/dist/commands/cli/triage-command.js +72 -0
- package/dist/commands/cli/utility-commands.js +25 -1
- package/dist/commands/client-dispatcher.d.ts +7 -0
- package/dist/commands/client-dispatcher.js +73 -21
- package/dist/commands/cron-cli/index.d.ts +3 -1
- package/dist/commands/cron-cli/index.js +25 -0
- package/dist/commands/device-auth.d.ts +10 -0
- package/dist/commands/device-auth.js +91 -0
- package/dist/commands/enhanced-command-handler.d.ts +9 -0
- package/dist/commands/enhanced-command-handler.js +28 -6
- package/dist/commands/handlers/agent-handlers.d.ts +1 -1
- package/dist/commands/handlers/agent-handlers.js +4 -4
- package/dist/commands/handlers/channel-handlers.js +53 -2
- package/dist/commands/handlers/export-handlers.d.ts +3 -2
- package/dist/commands/handlers/export-handlers.js +55 -28
- package/dist/commands/handlers/extra-handlers.js +5 -1
- package/dist/commands/handlers/grill-me-handler.js +26 -18
- package/dist/commands/handlers/memory-handlers.d.ts +6 -2
- package/dist/commands/handlers/memory-handlers.js +35 -15
- package/dist/commands/handlers/missing-handlers.d.ts +2 -2
- package/dist/commands/handlers/missing-handlers.js +12 -4
- package/dist/commands/handlers/resources-handler.d.ts +12 -0
- package/dist/commands/handlers/resources-handler.js +52 -0
- package/dist/commands/handlers/starter-handlers.d.ts +1 -1
- package/dist/commands/handlers/starter-handlers.js +32 -2
- package/dist/commands/handlers/switch-handler.d.ts +1 -1
- package/dist/commands/handlers/switch-handler.js +15 -0
- package/dist/commands/handlers/test-handlers.js +4 -86
- package/dist/commands/handlers/ui-handlers.js +11 -5
- package/dist/commands/login-chatgpt.d.ts +8 -0
- package/dist/commands/login-chatgpt.js +17 -0
- package/dist/commands/mcp-import.d.ts +11 -0
- package/dist/commands/mcp-import.js +67 -0
- package/dist/commands/mcp-invoke.d.ts +2 -0
- package/dist/commands/mcp-invoke.js +68 -0
- package/dist/commands/mcp.d.ts +13 -0
- package/dist/commands/mcp.js +66 -21
- package/dist/commands/pipeline.d.ts +7 -1
- package/dist/commands/pipeline.js +104 -7
- package/dist/commands/resources.d.ts +2 -0
- package/dist/commands/resources.js +64 -0
- package/dist/commands/skills-cli/index.js +35 -12
- package/dist/commands/slash/builtin-commands.js +16 -3
- package/dist/commands/slash/index.d.ts +3 -1
- package/dist/commands/slash/index.js +2 -0
- package/dist/commands/slash/surfaces.d.ts +53 -0
- package/dist/commands/slash/surfaces.js +177 -0
- package/dist/commands/slash/types.d.ts +17 -0
- package/dist/commands/try.d.ts +1 -1
- package/dist/commands/try.js +1 -1
- package/dist/companion/companion-identity.d.ts +43 -0
- package/dist/companion/companion-identity.js +136 -0
- package/dist/companion/companion-toolset.d.ts +66 -0
- package/dist/companion/companion-toolset.js +368 -0
- package/dist/companion/companion-turn.d.ts +10 -2
- package/dist/companion/companion-turn.js +38 -1
- package/dist/config/code-exec-policy.d.ts +25 -0
- package/dist/config/code-exec-policy.js +39 -0
- package/dist/config/model-tools.d.ts +9 -0
- package/dist/config/model-tools.js +103 -0
- package/dist/context/context-manager-v2.js +2 -2
- package/dist/context/lm-resizer-compressor.js +3 -2
- package/dist/context/lm-resizer-diagnostics.d.ts +9 -0
- package/dist/context/lm-resizer-diagnostics.js +30 -0
- package/dist/context/tool-output-masking.js +3 -4
- package/dist/curator/curator.d.ts +6 -0
- package/dist/curator/curator.js +53 -3
- package/dist/daemon/cron-agent-bridge.d.ts +6 -0
- package/dist/daemon/cron-agent-bridge.js +31 -4
- package/dist/doctor/index.d.ts +11 -2
- package/dist/doctor/index.js +84 -21
- package/dist/doctor/integrations.d.ts +197 -0
- package/dist/doctor/integrations.js +241 -0
- package/dist/doctor/triage.d.ts +108 -0
- package/dist/doctor/triage.js +304 -0
- package/dist/errors/crash-handler.js +2 -0
- package/dist/fleet/collaboration.d.ts +44 -0
- package/dist/fleet/collaboration.js +170 -0
- package/dist/fleet/fleet-listener.d.ts +1 -0
- package/dist/fleet/fleet-listener.js +87 -46
- package/dist/fleet/fleet-registry.d.ts +2 -0
- package/dist/fleet/resource-catalog.d.ts +245 -0
- package/dist/fleet/resource-catalog.js +211 -0
- package/dist/fleet/rooms/room-access.d.ts +138 -0
- package/dist/fleet/rooms/room-access.js +196 -0
- package/dist/fleet/rooms/room-client.d.ts +158 -0
- package/dist/fleet/rooms/room-client.js +685 -0
- package/dist/fleet/rooms/room-event.d.ts +139 -0
- package/dist/fleet/rooms/room-event.js +330 -0
- package/dist/fleet/rooms/room-filter.d.ts +48 -0
- package/dist/fleet/rooms/room-filter.js +152 -0
- package/dist/fleet/rooms/room-hub.d.ts +154 -0
- package/dist/fleet/rooms/room-hub.js +363 -0
- package/dist/fleet/rooms/room-identity.d.ts +26 -0
- package/dist/fleet/rooms/room-identity.js +82 -0
- package/dist/fleet/rooms/room-lock.d.ts +34 -0
- package/dist/fleet/rooms/room-lock.js +180 -0
- package/dist/fleet/rooms/room-observations.d.ts +7 -0
- package/dist/fleet/rooms/room-observations.js +61 -0
- package/dist/fleet/rooms/room-server.d.ts +28 -0
- package/dist/fleet/rooms/room-server.js +75 -0
- package/dist/fleet/rooms/room-store.d.ts +119 -0
- package/dist/fleet/rooms/room-store.js +448 -0
- package/dist/fleet/rooms/room-ws-bridge.d.ts +27 -0
- package/dist/fleet/rooms/room-ws-bridge.js +137 -0
- package/dist/fleet/sensory-mission-bridge.d.ts +42 -0
- package/dist/fleet/sensory-mission-bridge.js +136 -0
- package/dist/git/worktree-sessions.js +1 -0
- package/dist/harness/contract.d.ts +4 -4
- package/dist/harness/fleet-supervisor.d.ts +16 -0
- package/dist/harness/fleet-supervisor.js +64 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.js +4 -0
- package/dist/harness/mission-runner.d.ts +3 -0
- package/dist/harness/mission-runner.js +53 -0
- package/dist/harness/mission-store.d.ts +93 -0
- package/dist/harness/mission-store.js +297 -0
- package/dist/harness/tool-harness.d.ts +56 -0
- package/dist/harness/tool-harness.js +153 -0
- package/dist/hooks/use-enhanced-input.js +48 -4
- package/dist/hooks/use-input-handler.d.ts +1 -0
- package/dist/hooks/use-input-handler.js +82 -22
- package/dist/hooks/use-input-history.js +1 -0
- package/dist/identity/lisa-introspection.js +5 -2
- package/dist/identity/operational-self-model.d.ts +2 -0
- package/dist/identity/operational-self-model.js +4 -0
- package/dist/index.js +52 -6
- package/dist/mcp/client.d.ts +11 -0
- package/dist/mcp/client.js +68 -3
- package/dist/mcp/config.d.ts +20 -0
- package/dist/mcp/config.js +121 -8
- package/dist/mcp/import-normalize.d.ts +12 -0
- package/dist/mcp/import-normalize.js +114 -0
- package/dist/mcp/mcp-oauth-constants.d.ts +8 -0
- package/dist/mcp/mcp-oauth-constants.js +9 -0
- package/dist/mcp/mcp-oauth-provider.d.ts +80 -0
- package/dist/mcp/mcp-oauth-provider.js +241 -0
- package/dist/mcp/mcp-oauth.d.ts +60 -1
- package/dist/mcp/mcp-oauth.js +241 -65
- package/dist/mcp/transports.d.ts +14 -5
- package/dist/mcp/transports.js +112 -101
- package/dist/mcp/types.d.ts +5 -0
- package/dist/media/comfyui-recipe-contract.d.ts +7 -7
- package/dist/memory/facts-memory.d.ts +11 -1
- package/dist/memory/facts-memory.js +47 -8
- package/dist/memory/memory-candidate-queue.d.ts +2 -2
- package/dist/memory/memory-candidate-queue.js +6 -6
- package/dist/memory/persistent-memory.d.ts +13 -8
- package/dist/memory/persistent-memory.js +77 -30
- package/dist/nodes/device-node.js +5 -9
- package/dist/observability/mobile-supervision-gateway-contract.js +20 -7
- package/dist/observability/run-event-writer.d.ts +21 -0
- package/dist/observability/run-event-writer.js +81 -0
- package/dist/observability/run-store.d.ts +5 -0
- package/dist/observability/run-store.js +18 -13
- package/dist/observability/run-trajectory.js +1 -1
- package/dist/optimization/prompt-cache.d.ts +19 -2
- package/dist/optimization/prompt-cache.js +41 -6
- package/dist/orchestration/orchestrator.d.ts +21 -0
- package/dist/orchestration/orchestrator.js +122 -15
- package/dist/persistence/session-content.d.ts +8 -0
- package/dist/persistence/session-content.js +76 -0
- package/dist/persistence/session-handoff.d.ts +64 -0
- package/dist/persistence/session-handoff.js +80 -0
- package/dist/persistence/session-history.d.ts +4 -0
- package/dist/persistence/session-history.js +38 -0
- package/dist/persistence/session-store.d.ts +9 -0
- package/dist/persistence/session-store.js +48 -20
- package/dist/personas/persona-manager.js +17 -1
- package/dist/plugins/code-explorer/CodeExplorerManager.d.ts +10 -4
- package/dist/plugins/code-explorer/CodeExplorerManager.js +69 -16
- package/dist/plugins/plugin-manager.js +10 -1
- package/dist/prompts/prompt-manager.js +11 -4
- package/dist/prompts/system-base.js +6 -2
- package/dist/protocols/a2a/codebuddy-executor.d.ts +11 -2
- package/dist/protocols/a2a/codebuddy-executor.js +9 -8
- package/dist/protocols/a2a/index.d.ts +1 -1
- package/dist/protocols/a2a/jsonrpc-v1.d.ts +41 -0
- package/dist/protocols/a2a/jsonrpc-v1.js +145 -0
- package/dist/protocols/a2a/peer-config.d.ts +20 -0
- package/dist/protocols/a2a/peer-config.js +55 -0
- package/dist/providers/codex-oauth.js +30 -6
- package/dist/providers/model-provider-compat.js +2 -1
- package/dist/sandbox/os-sandbox.d.ts +1 -1
- package/dist/scheduler/cron-scheduler.d.ts +15 -2
- package/dist/scheduler/cron-scheduler.js +35 -4
- package/dist/scheduler/job-notepad.d.ts +69 -0
- package/dist/scheduler/job-notepad.js +339 -0
- package/dist/security/audit-logger.d.ts +1 -1
- package/dist/security/compute-confinement.d.ts +4 -0
- package/dist/security/compute-confinement.js +89 -0
- package/dist/security/session-encryption.d.ts +4 -0
- package/dist/security/session-encryption.js +31 -0
- package/dist/sensory/voice-loop.d.ts +17 -0
- package/dist/sensory/voice-loop.js +72 -15
- package/dist/server/auth/device-session-context.d.ts +9 -0
- package/dist/server/auth/device-session-context.js +13 -0
- package/dist/server/auth/device-store.d.ts +89 -0
- package/dist/server/auth/device-store.js +261 -0
- package/dist/server/auth/device-token.d.ts +3 -0
- package/dist/server/auth/device-token.js +6 -0
- package/dist/server/auth/jwt.js +4 -0
- package/dist/server/index.d.ts +0 -10
- package/dist/server/index.js +28 -0
- package/dist/server/middleware/auth.js +3 -2
- package/dist/server/routes/a2a-jsonrpc.d.ts +9 -0
- package/dist/server/routes/a2a-jsonrpc.js +66 -0
- package/dist/server/routes/a2a-protocol.d.ts +12 -0
- package/dist/server/routes/a2a-protocol.js +1 -1
- package/dist/server/routes/device-auth.d.ts +4 -0
- package/dist/server/routes/device-auth.js +40 -0
- package/dist/server/types.d.ts +4 -0
- package/dist/server/websocket/handler.d.ts +13 -0
- package/dist/server/websocket/handler.js +102 -17
- package/dist/services/prompt-builder.d.ts +2 -0
- package/dist/services/prompt-builder.js +16 -6
- package/dist/services/runtime-settings-context.d.ts +81 -0
- package/dist/services/runtime-settings-context.js +79 -0
- package/dist/skills/executor.js +2 -0
- package/dist/skills/hub.js +16 -14
- package/dist/skills/local-inventory.d.ts +21 -0
- package/dist/skills/local-inventory.js +72 -0
- package/dist/skills/skill-loader.js +2 -2
- package/dist/skills/skill-usage-store.d.ts +49 -0
- package/dist/skills/skill-usage-store.js +121 -0
- package/dist/testing/ai-integration-tests.js +8 -5
- package/dist/themes/theme-manager.d.ts +12 -0
- package/dist/themes/theme-manager.js +29 -0
- package/dist/themes/theme-schema.d.ts +24 -24
- package/dist/tools/a2a-call-tool.d.ts +34 -0
- package/dist/tools/a2a-call-tool.js +75 -0
- package/dist/tools/bash/streaming-executor.d.ts +1 -0
- package/dist/tools/bash/streaming-executor.js +78 -90
- package/dist/tools/code-exec-preflight-runner.d.ts +41 -0
- package/dist/tools/code-exec-preflight-runner.js +254 -0
- package/dist/tools/code-exec-preflight.d.ts +44 -0
- package/dist/tools/code-exec-preflight.js +501 -0
- package/dist/tools/code-exec-tool.d.ts +48 -1
- package/dist/tools/code-exec-tool.js +191 -47
- package/dist/tools/comment-watcher.js +29 -12
- package/dist/tools/core-code-inspection.d.ts +56 -0
- package/dist/tools/core-code-inspection.js +86 -0
- package/dist/tools/create-skill-tool.d.ts +2 -3
- package/dist/tools/create-skill-tool.js +16 -75
- package/dist/tools/cronjob-tool.d.ts +1 -0
- package/dist/tools/cronjob-tool.js +1 -0
- package/dist/tools/env-doctor-tool.d.ts +2 -0
- package/dist/tools/env-doctor-tool.js +4 -3
- package/dist/tools/execute-code-rpc-invoker.d.ts +1 -1
- package/dist/tools/execute-code-rpc-invoker.js +35 -19
- package/dist/tools/execute-code-runner.d.ts +2 -0
- package/dist/tools/execute-code-runner.js +52 -17
- package/dist/tools/fleet-room-tool.d.ts +104 -0
- package/dist/tools/fleet-room-tool.js +124 -0
- package/dist/tools/integration-tool-hints.d.ts +4 -0
- package/dist/tools/integration-tool-hints.js +19 -0
- package/dist/tools/list-peers-tool.d.ts +3 -0
- package/dist/tools/list-peers-tool.js +11 -4
- package/dist/tools/media-generation-tool.d.ts +16 -1
- package/dist/tools/media-generation-tool.js +341 -9
- package/dist/tools/merge-conflict-tool.js +53 -25
- package/dist/tools/metadata.d.ts +1 -5
- package/dist/tools/metadata.js +30 -28
- package/dist/tools/peer-tool-invoke-tool.d.ts +61 -0
- package/dist/tools/peer-tool-invoke-tool.js +396 -0
- package/dist/tools/ragchat-tool.d.ts +39 -0
- package/dist/tools/ragchat-tool.js +105 -0
- package/dist/tools/registry/fleet-tools.d.ts +21 -3
- package/dist/tools/registry/fleet-tools.js +137 -4
- package/dist/tools/registry/index.d.ts +1 -1
- package/dist/tools/registry/index.js +2 -2
- package/dist/tools/registry/knowledge-tools.d.ts +2 -2
- package/dist/tools/registry/knowledge-tools.js +2 -2
- package/dist/tools/registry/lessons-tools.d.ts +7 -0
- package/dist/tools/registry/lessons-tools.js +43 -3
- package/dist/tools/registry/memory-tools.d.ts +1 -1
- package/dist/tools/registry/memory-tools.js +8 -8
- package/dist/tools/registry/research-tools.d.ts +1 -0
- package/dist/tools/registry/research-tools.js +4 -13
- package/dist/tools/registry/self-describe-tools.d.ts +1 -1
- package/dist/tools/registry/self-describe-tools.js +43 -30
- package/dist/tools/resource-catalog-tool.d.ts +38 -0
- package/dist/tools/resource-catalog-tool.js +46 -0
- package/dist/tools/skills-inspection-tool.js +30 -1
- package/dist/tools/stream-tool-output.d.ts +3 -0
- package/dist/tools/stream-tool-output.js +33 -0
- package/dist/tools/tool-call-scheduler.d.ts +10 -0
- package/dist/tools/tool-call-scheduler.js +58 -0
- package/dist/tools/tool-effect.d.ts +5 -0
- package/dist/tools/tool-effect.js +26 -0
- package/dist/tools/tool-search.d.ts +12 -11
- package/dist/tools/tool-search.js +67 -26
- package/dist/tools/types.d.ts +6 -0
- package/dist/ui/components/ChatHistory.d.ts +1 -1
- package/dist/ui/components/ChatHistory.js +2 -2
- package/dist/ui/components/ChatInput.d.ts +2 -1
- package/dist/ui/components/ChatInput.js +42 -88
- package/dist/ui/components/ChatInterface.d.ts +4 -2
- package/dist/ui/components/ChatInterface.js +27 -63
- package/dist/ui/components/CommandSuggestions.d.ts +0 -1
- package/dist/ui/components/CommandSuggestions.js +4 -6
- package/dist/ui/components/FileAutocomplete.js +1 -1
- package/dist/ui/components/KeyboardHelp.js +8 -6
- package/dist/ui/components/ModelSelection.js +6 -5
- package/dist/ui/components/StatusBar.d.ts +2 -1
- package/dist/ui/components/StatusBar.js +8 -7
- package/dist/ui/context/theme-context.js +3 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/utils/markdown-renderer.js +4 -13
- package/dist/utils/atomic-write.d.ts +22 -0
- package/dist/utils/atomic-write.js +29 -0
- package/dist/utils/bounded-output.d.ts +16 -0
- package/dist/utils/bounded-output.js +63 -0
- package/dist/utils/config-validation/schema.d.ts +2 -2
- package/dist/utils/device-store-file.d.ts +4 -0
- package/dist/utils/device-store-file.js +40 -0
- package/dist/utils/export-manager.d.ts +9 -0
- package/dist/utils/export-manager.js +19 -0
- package/dist/utils/first-use-hints.d.ts +25 -0
- package/dist/utils/first-use-hints.js +58 -0
- package/dist/utils/graceful-shutdown.d.ts +8 -0
- package/dist/utils/graceful-shutdown.js +23 -7
- package/dist/utils/history-manager.js +1 -1
- package/dist/utils/update-notifier.js +16 -18
- package/dist/wizard/environment-detection.d.ts +5 -1
- package/dist/wizard/environment-detection.js +49 -7
- package/dist/wizard/onboarding.d.ts +5 -1
- package/dist/wizard/onboarding.js +90 -30
- package/dist/wizard/provider-onboarding.d.ts +2 -0
- package/dist/wizard/provider-onboarding.js +55 -17
- package/package.json +7 -3
|
@@ -6,6 +6,16 @@ function serializePayload(payload) {
|
|
|
6
6
|
data: payload,
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
+
/** Activity telemetry is best-effort: a failure never changes the tool result. */
|
|
10
|
+
async function recordView(name) {
|
|
11
|
+
try {
|
|
12
|
+
const { recordSkillActivity } = await import('../skills/skill-usage-store.js');
|
|
13
|
+
recordSkillActivity(name, 'view', { source: 'skill_view' });
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// Telemetry must never make skill inspection fail.
|
|
17
|
+
}
|
|
18
|
+
}
|
|
9
19
|
function stripUsage(skill) {
|
|
10
20
|
const { usage: _usage, ...rest } = skill;
|
|
11
21
|
return rest;
|
|
@@ -19,8 +29,16 @@ export async function executeSkillsListTool(input) {
|
|
|
19
29
|
const includeUsage = input.include_usage !== false;
|
|
20
30
|
const shown = includeDisabled ? all : all.filter((skill) => skill.enabled !== false);
|
|
21
31
|
const skills = includeUsage ? shown : shown.map(stripUsage);
|
|
32
|
+
const { readLocalSkillInventory } = await import('../skills/local-inventory.js');
|
|
33
|
+
const inventory = await readLocalSkillInventory(all);
|
|
34
|
+
const availableSkills = inventory.entries.filter((skill) => skill.available);
|
|
22
35
|
return serializePayload({
|
|
23
36
|
action: 'skills_list',
|
|
37
|
+
availableSkills,
|
|
38
|
+
availableCount: availableSkills.length,
|
|
39
|
+
unavailableSkills: inventory.entries.filter((skill) => !skill.available),
|
|
40
|
+
discoveryErrors: inventory.errors,
|
|
41
|
+
guidance: 'Use availableSkills to answer which skills can be used. Requirements may need tools or external configuration. The skills/count/total fields below describe only hub records, not the complete local catalogue. Missing files are not configuration errors.',
|
|
24
42
|
count: skills.length,
|
|
25
43
|
total: all.length,
|
|
26
44
|
includeDisabled,
|
|
@@ -40,9 +58,20 @@ export async function executeSkillViewTool(input) {
|
|
|
40
58
|
const { getSkillsHub } = await import('../skills/hub.js');
|
|
41
59
|
const result = getSkillsHub().info(name);
|
|
42
60
|
if (!result) {
|
|
43
|
-
|
|
61
|
+
const { readLocalSkillInventory, readLocalSkillContent } = await import('../skills/local-inventory.js');
|
|
62
|
+
const inventory = await readLocalSkillInventory(getSkillsHub().listWithIntegrity());
|
|
63
|
+
const skill = inventory.entries.find((entry) => entry.name === name);
|
|
64
|
+
if (!skill)
|
|
65
|
+
return { success: false, error: `skill_view: skill not found: ${name}` };
|
|
66
|
+
await recordView(name);
|
|
67
|
+
return serializePayload({
|
|
68
|
+
action: 'skill_view',
|
|
69
|
+
skill,
|
|
70
|
+
...(input.include_content !== false ? { content: await readLocalSkillContent(skill) } : {}),
|
|
71
|
+
});
|
|
44
72
|
}
|
|
45
73
|
const includeContent = input.include_content !== false;
|
|
74
|
+
await recordView(name);
|
|
46
75
|
return serializePayload({
|
|
47
76
|
action: 'skill_view',
|
|
48
77
|
installed: result.installed,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ToolResult } from '../types/index.js';
|
|
2
|
+
/** Adapt a callback-based guarded tool invocation without bypassing its dispatch pipeline. */
|
|
3
|
+
export declare function streamToolOutput(run: (signal: AbortSignal, emit: (delta: string) => void) => Promise<ToolResult>, signal?: AbortSignal): AsyncGenerator<string, ToolResult, undefined>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BoundedOutput } from '../utils/bounded-output.js';
|
|
2
|
+
/** Adapt a callback-based guarded tool invocation without bypassing its dispatch pipeline. */
|
|
3
|
+
export async function* streamToolOutput(run, signal) {
|
|
4
|
+
const controller = new AbortController();
|
|
5
|
+
const abort = () => controller.abort();
|
|
6
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
7
|
+
if (signal?.aborted)
|
|
8
|
+
abort();
|
|
9
|
+
const pending = new BoundedOutput(64 * 1024);
|
|
10
|
+
let result;
|
|
11
|
+
let wake;
|
|
12
|
+
const notify = () => { wake?.(); wake = undefined; };
|
|
13
|
+
const completion = Promise.resolve().then(() => run(controller.signal, delta => { pending.append(delta); notify(); }))
|
|
14
|
+
.then(value => { result = value; })
|
|
15
|
+
.catch(error => { result = { success: false, error: error instanceof Error ? error.message : String(error) }; })
|
|
16
|
+
.finally(notify);
|
|
17
|
+
try {
|
|
18
|
+
while (!result || pending.retainedBytes) {
|
|
19
|
+
if (pending.retainedBytes)
|
|
20
|
+
yield pending.drain();
|
|
21
|
+
else
|
|
22
|
+
await new Promise(resolve => { wake = resolve; });
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
abort();
|
|
28
|
+
signal?.removeEventListener('abort', abort);
|
|
29
|
+
// Observe completion without blocking a consumer that intentionally stops.
|
|
30
|
+
void completion;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=stream-tool-output.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** FIFO barriers for mutations, bounded parallelism for explicitly safe reads. */
|
|
2
|
+
export declare class ToolCallScheduler {
|
|
3
|
+
private readonly concurrency;
|
|
4
|
+
private active;
|
|
5
|
+
private exclusive;
|
|
6
|
+
private queue;
|
|
7
|
+
constructor(concurrency?: number);
|
|
8
|
+
schedule<T>(parallel: boolean, action: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
9
|
+
private pump;
|
|
10
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** FIFO barriers for mutations, bounded parallelism for explicitly safe reads. */
|
|
2
|
+
export class ToolCallScheduler {
|
|
3
|
+
concurrency;
|
|
4
|
+
active = 0;
|
|
5
|
+
exclusive = false;
|
|
6
|
+
queue = [];
|
|
7
|
+
constructor(concurrency = 4) {
|
|
8
|
+
this.concurrency = concurrency;
|
|
9
|
+
if (!Number.isSafeInteger(concurrency) || concurrency < 1 || concurrency > 64)
|
|
10
|
+
throw new Error('Concurrency must be an integer between 1 and 64');
|
|
11
|
+
}
|
|
12
|
+
schedule(parallel, action, signal) {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
if (signal?.aborted) {
|
|
15
|
+
reject(new Error('Tool call cancelled'));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const entry = { parallel, run: async () => {
|
|
19
|
+
signal?.removeEventListener('abort', abort);
|
|
20
|
+
try {
|
|
21
|
+
resolve(await action());
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
reject(error);
|
|
25
|
+
}
|
|
26
|
+
} };
|
|
27
|
+
const abort = () => {
|
|
28
|
+
const index = this.queue.indexOf(entry);
|
|
29
|
+
if (index < 0)
|
|
30
|
+
return;
|
|
31
|
+
this.queue.splice(index, 1);
|
|
32
|
+
signal?.removeEventListener('abort', abort);
|
|
33
|
+
reject(new Error('Tool call cancelled'));
|
|
34
|
+
this.pump();
|
|
35
|
+
};
|
|
36
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
37
|
+
this.queue.push(entry);
|
|
38
|
+
this.pump();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
pump() {
|
|
42
|
+
while (!this.exclusive && this.active < this.concurrency && this.queue.length) {
|
|
43
|
+
const next = this.queue[0];
|
|
44
|
+
if (!next.parallel && this.active)
|
|
45
|
+
return;
|
|
46
|
+
this.queue.shift();
|
|
47
|
+
this.active++;
|
|
48
|
+
this.exclusive = !next.parallel;
|
|
49
|
+
void next.run().finally(() => {
|
|
50
|
+
this.active--;
|
|
51
|
+
if (!next.parallel)
|
|
52
|
+
this.exclusive = false;
|
|
53
|
+
this.pump();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=tool-call-scheduler.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ToolEffectClass, type ToolMetadata } from './types.js';
|
|
2
|
+
/** Resolve a tool's declared effect class. Missing catalog/MCP entries warn once and return `unknown`. */
|
|
3
|
+
export declare function resolveToolEffect(name: string, metadata?: Pick<ToolMetadata, 'effect'> | null): ToolEffectClass | 'unknown';
|
|
4
|
+
/** Test hook: unique-warning latch. */
|
|
5
|
+
export declare function resetToolEffectWarningLatch(): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
import { TOOL_METADATA } from './metadata.js';
|
|
3
|
+
import { TOOL_EFFECT_CLASSES } from './types.js';
|
|
4
|
+
// Runtime warnings live here so the tool catalog can also serve browser previews.
|
|
5
|
+
const missingEffectWarned = new Set();
|
|
6
|
+
function isToolEffectClass(value) {
|
|
7
|
+
return TOOL_EFFECT_CLASSES.includes(value);
|
|
8
|
+
}
|
|
9
|
+
/** Resolve a tool's declared effect class. Missing catalog/MCP entries warn once and return `unknown`. */
|
|
10
|
+
export function resolveToolEffect(name, metadata) {
|
|
11
|
+
if (isToolEffectClass(metadata?.effect))
|
|
12
|
+
return metadata.effect;
|
|
13
|
+
const catalog = TOOL_METADATA.find((entry) => entry.name === name)?.effect;
|
|
14
|
+
if (isToolEffectClass(catalog))
|
|
15
|
+
return catalog;
|
|
16
|
+
if (!missingEffectWarned.has(name)) {
|
|
17
|
+
missingEffectWarned.add(name);
|
|
18
|
+
logger.warn('tool metadata missing effect class; treating as unknown', { tool: name });
|
|
19
|
+
}
|
|
20
|
+
return 'unknown';
|
|
21
|
+
}
|
|
22
|
+
/** Test hook: unique-warning latch. */
|
|
23
|
+
export function resetToolEffectWarningLatch() {
|
|
24
|
+
missingEffectWarned.clear();
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=tool-effect.js.map
|
|
@@ -9,21 +9,26 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { BaseTool, ParameterDefinition } from './base-tool.js';
|
|
11
11
|
import { ToolResult } from '../types/index.js';
|
|
12
|
+
import type { IToolExecutionContext } from './registry/types.js';
|
|
13
|
+
export interface SearchableTool {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
keywords?: string[];
|
|
17
|
+
parameters?: unknown;
|
|
18
|
+
}
|
|
12
19
|
/**
|
|
13
20
|
* Build a BM25 index from tool definitions.
|
|
14
21
|
*/
|
|
15
22
|
export declare class BM25Index {
|
|
16
23
|
private documents;
|
|
17
24
|
private avgDL;
|
|
25
|
+
private catalog;
|
|
26
|
+
getTool(name: string): SearchableTool | undefined;
|
|
18
27
|
private idf;
|
|
19
28
|
/**
|
|
20
29
|
* Add tool definitions to the index.
|
|
21
30
|
*/
|
|
22
|
-
index(tools:
|
|
23
|
-
name: string;
|
|
24
|
-
description: string;
|
|
25
|
-
keywords?: string[];
|
|
26
|
-
}>): void;
|
|
31
|
+
index(tools: SearchableTool[]): void;
|
|
27
32
|
/**
|
|
28
33
|
* Search for tools matching a query.
|
|
29
34
|
* Returns results sorted by BM25 score (highest first).
|
|
@@ -37,11 +42,7 @@ export declare class BM25Index {
|
|
|
37
42
|
/**
|
|
38
43
|
* Initialize the BM25 index with available tools.
|
|
39
44
|
*/
|
|
40
|
-
export declare function initToolSearchIndex(tools:
|
|
41
|
-
name: string;
|
|
42
|
-
description: string;
|
|
43
|
-
keywords?: string[];
|
|
44
|
-
}>): void;
|
|
45
|
+
export declare function initToolSearchIndex(tools: SearchableTool[]): void;
|
|
45
46
|
/**
|
|
46
47
|
* Get the BM25 index (creates empty if not initialized).
|
|
47
48
|
*/
|
|
@@ -50,5 +51,5 @@ export declare class ToolSearchTool extends BaseTool {
|
|
|
50
51
|
readonly name = "tool_search";
|
|
51
52
|
readonly description = "Search for available tools by keyword. Useful when you need to find a specific tool from a large set (especially MCP tools).";
|
|
52
53
|
protected getParameters(): Record<string, ParameterDefinition>;
|
|
53
|
-
execute(input: Record<string, unknown
|
|
54
|
+
execute(input: Record<string, unknown>, context?: IToolExecutionContext): Promise<ToolResult>;
|
|
54
55
|
}
|
|
@@ -8,10 +8,36 @@
|
|
|
8
8
|
* Inspired by OpenAI Codex CLI's tool_search with BM25.
|
|
9
9
|
*/
|
|
10
10
|
import { BaseTool } from './base-tool.js';
|
|
11
|
-
import { resolveToolEffect } from './
|
|
11
|
+
import { resolveToolEffect } from './tool-effect.js';
|
|
12
12
|
// ============================================================================
|
|
13
13
|
// BM25 Implementation
|
|
14
14
|
// ============================================================================
|
|
15
|
+
const QUERY_EQUIVALENTS = {
|
|
16
|
+
lire: ['read', 'view'],
|
|
17
|
+
voir: ['view', 'read'],
|
|
18
|
+
contenu: ['content', 'contents'],
|
|
19
|
+
contenus: ['content', 'contents'],
|
|
20
|
+
consulter: ['view', 'read'],
|
|
21
|
+
ouvrir: ['open', 'read', 'view'],
|
|
22
|
+
afficher: ['show', 'display', 'view', 'list'],
|
|
23
|
+
fichier: ['file'],
|
|
24
|
+
fichiers: ['file', 'files'],
|
|
25
|
+
dossier: ['directory', 'folder'],
|
|
26
|
+
dossiers: ['directory', 'directories', 'folder', 'folders'],
|
|
27
|
+
repertoire: ['directory', 'folder'],
|
|
28
|
+
repertoires: ['directory', 'directories', 'folder', 'folders'],
|
|
29
|
+
chercher: ['search', 'find'],
|
|
30
|
+
rechercher: ['search', 'find'],
|
|
31
|
+
trouver: ['find', 'search'],
|
|
32
|
+
modifier: ['edit', 'replace'],
|
|
33
|
+
remplacer: ['replace', 'edit'],
|
|
34
|
+
creer: ['create'],
|
|
35
|
+
supprimer: ['delete', 'remove'],
|
|
36
|
+
memoire: ['memory'],
|
|
37
|
+
executer: ['execute', 'run'],
|
|
38
|
+
lancer: ['run', 'execute'],
|
|
39
|
+
commande: ['command'],
|
|
40
|
+
};
|
|
15
41
|
/** BM25 parameters */
|
|
16
42
|
const K1 = 1.2; // Term frequency saturation
|
|
17
43
|
const B = 0.75; // Length normalization
|
|
@@ -20,10 +46,11 @@ const B = 0.75; // Length normalization
|
|
|
20
46
|
*/
|
|
21
47
|
function tokenize(text) {
|
|
22
48
|
return text
|
|
49
|
+
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
50
|
+
.normalize('NFKD').replace(/\p{M}/gu, '')
|
|
23
51
|
.toLowerCase()
|
|
24
|
-
.
|
|
25
|
-
.
|
|
26
|
-
.filter(t => t.length > 1);
|
|
52
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
53
|
+
.filter(Boolean);
|
|
27
54
|
}
|
|
28
55
|
/**
|
|
29
56
|
* Build a BM25 index from tool definitions.
|
|
@@ -31,14 +58,18 @@ function tokenize(text) {
|
|
|
31
58
|
export class BM25Index {
|
|
32
59
|
documents = [];
|
|
33
60
|
avgDL = 0;
|
|
61
|
+
catalog = new Map();
|
|
62
|
+
getTool(name) { return this.catalog.get(name); }
|
|
34
63
|
idf = new Map();
|
|
35
64
|
/**
|
|
36
65
|
* Add tool definitions to the index.
|
|
37
66
|
*/
|
|
38
67
|
index(tools) {
|
|
39
|
-
this.
|
|
68
|
+
this.idf.clear();
|
|
69
|
+
this.catalog = new Map(tools.map(tool => [tool.name, tool]));
|
|
70
|
+
this.documents = [...this.catalog.values()].map(t => {
|
|
40
71
|
const tokens = [
|
|
41
|
-
...tokenize(t.name),
|
|
72
|
+
...Array.from({ length: 3 }, () => tokenize(t.name)).flat(),
|
|
42
73
|
...tokenize(t.description),
|
|
43
74
|
...(t.keywords ?? []).flatMap(k => tokenize(k)),
|
|
44
75
|
];
|
|
@@ -59,14 +90,13 @@ export class BM25Index {
|
|
|
59
90
|
this.avgDL = this.documents.reduce((sum, d) => sum + d.length, 0) / Math.max(this.documents.length, 1);
|
|
60
91
|
// Compute IDF for all terms
|
|
61
92
|
const N = this.documents.length;
|
|
62
|
-
const
|
|
93
|
+
const frequencies = new Map();
|
|
63
94
|
for (const doc of this.documents) {
|
|
64
95
|
for (const token of doc.tf.keys()) {
|
|
65
|
-
|
|
96
|
+
frequencies.set(token, (frequencies.get(token) ?? 0) + 1);
|
|
66
97
|
}
|
|
67
98
|
}
|
|
68
|
-
for (const term of
|
|
69
|
-
const df = this.documents.filter(d => d.tf.has(term)).length;
|
|
99
|
+
for (const [term, df] of frequencies) {
|
|
70
100
|
this.idf.set(term, Math.log((N - df + 0.5) / (df + 0.5) + 1));
|
|
71
101
|
}
|
|
72
102
|
}
|
|
@@ -75,11 +105,12 @@ export class BM25Index {
|
|
|
75
105
|
* Returns results sorted by BM25 score (highest first).
|
|
76
106
|
*/
|
|
77
107
|
search(query, maxResults = 10) {
|
|
78
|
-
const queryTokens = tokenize(query);
|
|
108
|
+
const queryTokens = [...new Set(tokenize(query).flatMap(term => [term, ...(QUERY_EQUIVALENTS[term] ?? [])]))];
|
|
109
|
+
const limit = Number.isFinite(maxResults) ? Math.max(1, Math.min(50, Math.floor(maxResults))) : 10;
|
|
79
110
|
if (queryTokens.length === 0)
|
|
80
111
|
return [];
|
|
81
112
|
const scored = this.documents.map(doc => {
|
|
82
|
-
let score = 0;
|
|
113
|
+
let score = doc.name.toLowerCase() === query.trim().toLowerCase() ? 100 : 0;
|
|
83
114
|
for (const qToken of queryTokens) {
|
|
84
115
|
const tf = doc.tf.get(qToken) ?? 0;
|
|
85
116
|
const idf = this.idf.get(qToken) ?? 0;
|
|
@@ -88,12 +119,15 @@ export class BM25Index {
|
|
|
88
119
|
const denominator = tf + K1 * (1 - B + B * (doc.length / this.avgDL));
|
|
89
120
|
score += idf * (numerator / denominator);
|
|
90
121
|
}
|
|
122
|
+
const nameTerms = new Set(tokenize(doc.name));
|
|
123
|
+
if (queryTokens.every(term => nameTerms.has(term)))
|
|
124
|
+
score += 5;
|
|
91
125
|
return { name: doc.name, description: doc.description, score };
|
|
92
126
|
});
|
|
93
127
|
return scored
|
|
94
128
|
.filter(s => s.score > 0)
|
|
95
|
-
.sort((a, b) => b.score - a.score)
|
|
96
|
-
.slice(0,
|
|
129
|
+
.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))
|
|
130
|
+
.slice(0, limit);
|
|
97
131
|
}
|
|
98
132
|
}
|
|
99
133
|
// ============================================================================
|
|
@@ -133,12 +167,17 @@ export class ToolSearchTool extends BaseTool {
|
|
|
133
167
|
},
|
|
134
168
|
};
|
|
135
169
|
}
|
|
136
|
-
async execute(input) {
|
|
170
|
+
async execute(input, context) {
|
|
137
171
|
const query = input.query;
|
|
138
|
-
if (!query)
|
|
139
|
-
return this.error('query
|
|
172
|
+
if (typeof query !== 'string' || !query.trim() || query.length > 2000)
|
|
173
|
+
return this.error('query must be a nonempty string of at most 2000 characters');
|
|
174
|
+
if (input.max_results !== undefined && (typeof input.max_results !== 'number' || !Number.isInteger(input.max_results) || input.max_results < 1 || input.max_results > 50))
|
|
175
|
+
return this.error('max_results must be an integer between 1 and 50');
|
|
140
176
|
const maxResults = typeof input.max_results === 'number' ? input.max_results : 10;
|
|
141
|
-
const
|
|
177
|
+
const catalog = context?.extra?.toolSearchCatalog;
|
|
178
|
+
const index = Array.isArray(catalog) ? new BM25Index() : getToolSearchIndex();
|
|
179
|
+
if (Array.isArray(catalog))
|
|
180
|
+
index.index(catalog);
|
|
142
181
|
const results = index.search(query, maxResults);
|
|
143
182
|
if (results.length === 0) {
|
|
144
183
|
return this.success(`No tools found matching "${query}".`);
|
|
@@ -154,22 +193,24 @@ export class ToolSearchTool extends BaseTool {
|
|
|
154
193
|
catch {
|
|
155
194
|
// tools.js not available — skip deferred schema resolution
|
|
156
195
|
}
|
|
157
|
-
const
|
|
196
|
+
const tools = results.map(result => ({
|
|
197
|
+
...result,
|
|
198
|
+
effect: resolveToolEffect(result.name),
|
|
199
|
+
parameters: index.getTool(result.name)?.parameters ??
|
|
200
|
+
deferredSchemas?.get(result.name)?.function?.parameters,
|
|
201
|
+
}));
|
|
202
|
+
const lines = tools.map((r, i) => {
|
|
158
203
|
const effect = resolveToolEffect(r.name);
|
|
159
204
|
let line = `${i + 1}. **${r.name}** (score: ${r.score.toFixed(2)})\n effect: ${effect}\n ${r.description}`;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const fullTool = deferredSchemas.get(r.name);
|
|
163
|
-
if (fullTool?.function?.parameters) {
|
|
164
|
-
line += `\n Schema: ${JSON.stringify(fullTool.function.parameters)}`;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
205
|
+
if (r.parameters)
|
|
206
|
+
line += `\n Schema: ${JSON.stringify(r.parameters)}`;
|
|
167
207
|
return line;
|
|
168
208
|
});
|
|
169
209
|
// data.names lets the executor EXPAND the current turn's tool selection
|
|
170
210
|
// with what was discovered — finding a tool must make it invocable on the
|
|
171
211
|
// next round (true progressive disclosure), not just describe it.
|
|
172
212
|
return this.success(`Found ${results.length} tools:\n\n${lines.join('\n\n')}`, {
|
|
213
|
+
tools,
|
|
173
214
|
names: results.map((r) => r.name),
|
|
174
215
|
effects: Object.fromEntries(results.map((r) => [r.name, resolveToolEffect(r.name)])),
|
|
175
216
|
});
|
package/dist/tools/types.d.ts
CHANGED
|
@@ -49,6 +49,12 @@ export interface ToolMetadata {
|
|
|
49
49
|
* silently filtered out from peer-visible tool lists.
|
|
50
50
|
*/
|
|
51
51
|
fleetSafe?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Polling/status tool that may legitimately be called repeatedly with the
|
|
54
|
+
* same arguments and result (e.g. waiting on a background job). The tool
|
|
55
|
+
* loop guard (`src/agent/execution/tool-loop-guard.ts`) never counts it.
|
|
56
|
+
*/
|
|
57
|
+
repeatSafe?: boolean;
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
60
|
* Result of classifying a user query into tool categories.
|
|
@@ -6,5 +6,5 @@ interface ChatHistoryProps {
|
|
|
6
6
|
/** Maximum number of messages to display (default: 50) */
|
|
7
7
|
maxMessages?: number;
|
|
8
8
|
}
|
|
9
|
-
export declare
|
|
9
|
+
export declare const ChatHistory: React.NamedExoticComponent<ChatHistoryProps>;
|
|
10
10
|
export {};
|
|
@@ -265,7 +265,7 @@ const MemoizedChatEntry = React.memo(({ entry, index, colors, avatars }) => {
|
|
|
265
265
|
}
|
|
266
266
|
});
|
|
267
267
|
MemoizedChatEntry.displayName = "MemoizedChatEntry";
|
|
268
|
-
export function ChatHistory({ entries, isConfirmationActive = false, maxMessages = 50, }) {
|
|
268
|
+
export const ChatHistory = React.memo(function ChatHistory({ entries, isConfirmationActive = false, maxMessages = 50, }) {
|
|
269
269
|
const { colors, avatars } = useTheme();
|
|
270
270
|
// Number of entries permanently committed to <Static> (monotonically increasing)
|
|
271
271
|
// Entries start in the dynamic section and move to static AFTER being finalized
|
|
@@ -336,5 +336,5 @@ export function ChatHistory({ entries, isConfirmationActive = false, maxMessages
|
|
|
336
336
|
" in scrollback"))),
|
|
337
337
|
React.createElement(Static, { items: staticItems }, (entry) => (React.createElement(MemoizedChatEntry, { key: entry.uniqueKey, entry: entry, index: 0, colors: colors, avatars: avatars }))),
|
|
338
338
|
dynamicItems.map((entry, index) => (React.createElement(MemoizedChatEntry, { key: entry.uniqueKey, entry: entry, index: index, colors: colors, avatars: avatars })))));
|
|
339
|
-
}
|
|
339
|
+
});
|
|
340
340
|
//# sourceMappingURL=ChatHistory.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
2
|
interface ChatInputProps {
|
|
3
3
|
input: string;
|
|
4
4
|
cursorPosition: number;
|
|
@@ -6,5 +6,6 @@ interface ChatInputProps {
|
|
|
6
6
|
isStreaming: boolean;
|
|
7
7
|
mode?: string;
|
|
8
8
|
}
|
|
9
|
+
/** A bounded draft viewport. Editing remains available while the agent works. */
|
|
9
10
|
export declare const ChatInput: React.NamedExoticComponent<ChatInputProps>;
|
|
10
11
|
export {};
|
|
@@ -1,93 +1,47 @@
|
|
|
1
|
-
import React, { useMemo } from
|
|
2
|
-
import { Box, Text } from
|
|
3
|
-
import { useTheme } from
|
|
4
|
-
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { useTheme } from '../context/theme-context.js';
|
|
4
|
+
/** A bounded draft viewport. Editing remains available while the agent works. */
|
|
5
5
|
export const ChatInput = React.memo(function ChatInput({ input, cursorPosition, isProcessing, isStreaming, mode = 'code', }) {
|
|
6
6
|
const { colors } = useTheme();
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
ask: colors.secondary,
|
|
17
|
-
};
|
|
18
|
-
const promptIcon = modePromptIcons[mode] || '❯';
|
|
19
|
-
const promptColor = modePromptColors[mode] || colors.primary;
|
|
20
|
-
// Memoize cursor calculations to avoid recomputing on every render
|
|
21
|
-
const cursorData = useMemo(() => {
|
|
22
|
-
const lines = input.split("\n");
|
|
23
|
-
const isMultiline = lines.length > 1;
|
|
24
|
-
const beforeCursor = input.slice(0, cursorPosition);
|
|
25
|
-
// Calculate cursor position across lines
|
|
26
|
-
let currentLineIndex = 0;
|
|
27
|
-
let currentCharIndex = 0;
|
|
28
|
-
let totalChars = 0;
|
|
29
|
-
for (let i = 0; i < lines.length; i++) {
|
|
30
|
-
const line = lines[i] ?? "";
|
|
31
|
-
if (totalChars + line.length >= cursorPosition) {
|
|
32
|
-
currentLineIndex = i;
|
|
33
|
-
currentCharIndex = cursorPosition - totalChars;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
totalChars += line.length + 1; // +1 for newline
|
|
37
|
-
}
|
|
38
|
-
return { lines, isMultiline, beforeCursor, currentLineIndex, currentCharIndex };
|
|
7
|
+
const busy = isProcessing || isStreaming;
|
|
8
|
+
const viewport = useMemo(() => {
|
|
9
|
+
const position = Math.max(0, Math.min(input.length, cursorPosition));
|
|
10
|
+
const lines = input.split('\n');
|
|
11
|
+
const before = input.slice(0, position).split('\n');
|
|
12
|
+
const row = before.length - 1;
|
|
13
|
+
const column = before[row]?.length ?? 0;
|
|
14
|
+
const start = Math.max(0, Math.min(row - 3, lines.length - 6));
|
|
15
|
+
return { lines, row, column, start, visible: lines.slice(start, start + 6) };
|
|
39
16
|
}, [input, cursorPosition]);
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
React.createElement(Text, {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
React.createElement(Text,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return (React.createElement(Box, { key: index },
|
|
70
|
-
React.createElement(Text, { color: promptColor },
|
|
71
|
-
promptChar,
|
|
72
|
-
" "),
|
|
73
|
-
React.createElement(Text, null, line)));
|
|
74
|
-
}
|
|
75
|
-
})));
|
|
76
|
-
}
|
|
77
|
-
// Single line input box
|
|
78
|
-
const cursorChar = input.slice(cursorPosition, cursorPosition + 1) || " ";
|
|
79
|
-
const afterCursorText = input.slice(cursorPosition + 1);
|
|
80
|
-
return (React.createElement(Box, { borderStyle: "round", borderColor: borderColor, paddingX: 1, paddingY: 0, marginTop: 1 },
|
|
81
|
-
React.createElement(Box, null,
|
|
82
|
-
React.createElement(Text, { color: promptColor },
|
|
83
|
-
promptIcon,
|
|
84
|
-
" "),
|
|
85
|
-
isPlaceholder ? (React.createElement(React.Fragment, null,
|
|
86
|
-
React.createElement(Text, { color: colors.textMuted, dimColor: true }, placeholderText),
|
|
87
|
-
showCursor && (React.createElement(Text, { backgroundColor: "white", color: "black" }, " ")))) : (React.createElement(Text, null,
|
|
88
|
-
beforeCursor,
|
|
89
|
-
showCursor && (React.createElement(Text, { backgroundColor: "white", color: "black" }, cursorChar)),
|
|
90
|
-
!showCursor && cursorChar !== " " && cursorChar,
|
|
91
|
-
afterCursorText)))));
|
|
17
|
+
const placeholder = mode === 'plan' ? 'Describe what you want to plan…'
|
|
18
|
+
: mode === 'ask' ? 'Ask a question…'
|
|
19
|
+
: busy ? 'Write a follow-up while I work…' : 'Describe a task, or type / for commands…';
|
|
20
|
+
return (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: busy ? colors.borderBusy : colors.borderActive, paddingX: 1, marginTop: 1 },
|
|
21
|
+
React.createElement(Box, { justifyContent: "space-between" },
|
|
22
|
+
React.createElement(Text, { bold: true, color: colors.primary }, mode === 'plan' ? 'Plan' : mode === 'ask' ? 'Question' : 'Message'),
|
|
23
|
+
React.createElement(Text, { color: colors.textMuted },
|
|
24
|
+
busy ? 'Draft · working' : 'Ready',
|
|
25
|
+
viewport.lines.length > 1 ? ` · ${viewport.lines.length} lines` : '')),
|
|
26
|
+
viewport.start > 0 && React.createElement(Text, { dimColor: true },
|
|
27
|
+
"\u2026 ",
|
|
28
|
+
viewport.start,
|
|
29
|
+
" lines above"),
|
|
30
|
+
viewport.visible.map((line, index) => {
|
|
31
|
+
const active = viewport.start + index === viewport.row;
|
|
32
|
+
const char = Array.from(line.slice(viewport.column))[0] || ' ';
|
|
33
|
+
return (React.createElement(Box, { key: viewport.start + index },
|
|
34
|
+
React.createElement(Text, { color: colors.primary }, active ? '❯ ' : ' '),
|
|
35
|
+
!input ? (React.createElement(Text, null,
|
|
36
|
+
React.createElement(Text, { inverse: true }, " "),
|
|
37
|
+
React.createElement(Text, { dimColor: true }, placeholder))) : active ? (React.createElement(Text, null,
|
|
38
|
+
line.slice(0, viewport.column),
|
|
39
|
+
React.createElement(Text, { inverse: true }, char),
|
|
40
|
+
line.slice(viewport.column + char.length))) : React.createElement(Text, null, line || ' ')));
|
|
41
|
+
}),
|
|
42
|
+
viewport.start + 6 < viewport.lines.length && React.createElement(Text, { dimColor: true },
|
|
43
|
+
"\u2026 ",
|
|
44
|
+
viewport.lines.length - viewport.start - 6,
|
|
45
|
+
" lines below")));
|
|
92
46
|
});
|
|
93
47
|
//# sourceMappingURL=ChatInput.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { CodeBuddyAgent } from "../../agent/codebuddy-agent.js";
|
|
2
|
+
import type { CodeBuddyAgent, ChatEntry } from "../../agent/codebuddy-agent.js";
|
|
3
3
|
interface ChatInterfaceProps {
|
|
4
4
|
agent?: CodeBuddyAgent;
|
|
5
5
|
initialMessage?: string;
|
|
6
|
+
/** History of a resumed session, shown before the first new turn. */
|
|
7
|
+
initialHistory?: ChatEntry[];
|
|
6
8
|
}
|
|
7
|
-
export default function ChatInterface({ agent, initialMessage, }: ChatInterfaceProps): React.JSX.Element;
|
|
9
|
+
export default function ChatInterface({ agent, initialMessage, initialHistory, }: ChatInterfaceProps): React.JSX.Element;
|
|
8
10
|
export {};
|