@phuetz/code-buddy 2.0.0 → 2.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/README.fr.md +56 -0
- package/README.md +73 -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 +165 -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.js +19 -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 +1 -0
- package/dist/codebuddy/fleet-tool-defs.js +24 -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.js +1 -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 +4 -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.js +4 -0
- 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 +4 -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 +179 -0
- package/dist/doctor/integrations.js +227 -0
- package/dist/doctor/triage.d.ts +108 -0
- package/dist/doctor/triage.js +304 -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.js +6 -0
- 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/transports.d.ts +10 -5
- package/dist/mcp/transports.js +61 -99
- 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 +13 -5
- package/dist/services/runtime-settings-context.d.ts +73 -0
- package/dist/services/runtime-settings-context.js +69 -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 +21 -28
- 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 +9 -0
- package/dist/tools/registry/fleet-tools.js +22 -1
- 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/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/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
|
@@ -113,6 +113,17 @@ export interface ArchiveEntry {
|
|
|
113
113
|
reviewedBy: string;
|
|
114
114
|
/** Origin of non-lesson archive entries, for example the project CHANGELOG or delegation logs. */
|
|
115
115
|
provenance?: 'changelog' | 'delegation-log' | string;
|
|
116
|
+
evidence?: {
|
|
117
|
+
artifactSha256: string;
|
|
118
|
+
benchmarkSha256: string;
|
|
119
|
+
wins: number;
|
|
120
|
+
losses: number;
|
|
121
|
+
cases: {
|
|
122
|
+
id: string;
|
|
123
|
+
before: boolean;
|
|
124
|
+
after: boolean;
|
|
125
|
+
}[];
|
|
126
|
+
};
|
|
116
127
|
}
|
|
117
128
|
export interface SelfImprovementCycleResult {
|
|
118
129
|
schemaVersion: typeof SELF_IMPROVEMENT_SCHEMA_VERSION;
|
|
@@ -243,7 +243,7 @@ export declare class ToolHandler {
|
|
|
243
243
|
private executeStreamingBash;
|
|
244
244
|
/**
|
|
245
245
|
* Execute a tool with streaming output.
|
|
246
|
-
*
|
|
246
|
+
* Supports process output, code_exec yields and progress-producing tools.
|
|
247
247
|
* Yields string deltas for real-time output.
|
|
248
248
|
*/
|
|
249
249
|
executeToolStreaming(toolCall: CodeBuddyToolCall, executionExtra?: Record<string, unknown>): AsyncGenerator<string, ToolResult, undefined>;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* All tools are registered as ITool adapters in the FormalToolRegistry.
|
|
16
16
|
* Tool instances are lazy-loaded on first access for optimal startup time.
|
|
17
17
|
*/
|
|
18
|
+
import { streamToolOutput } from '../tools/stream-tool-output.js';
|
|
18
19
|
import { TextEditorTool, MorphEditorTool, ImageTool, BashTool, } from "../tools/index.js";
|
|
19
20
|
import { isBareChangeDirectory } from "../tools/bash/bash-tool.js";
|
|
20
21
|
import { getFormalToolRegistry } from "../tools/registry/index.js";
|
|
@@ -1034,14 +1035,22 @@ export class ToolHandler {
|
|
|
1034
1035
|
...(abortSignal ? { abortSignal } : {}),
|
|
1035
1036
|
...(Object.keys(contextExtra).length > 0 ? { extra: contextExtra } : {}),
|
|
1036
1037
|
};
|
|
1038
|
+
const toolCatalog = toolName === 'code_exec' || toolName === 'tool_search' ? [
|
|
1039
|
+
...this.registry.getSchemas().map(tool => ({
|
|
1040
|
+
...tool, keywords: this.registry.get(tool.name)?.metadata.keywords,
|
|
1041
|
+
})),
|
|
1042
|
+
...getMCPManager().getTools().map(tool => ({ name: tool.name, description: tool.description, parameters: tool.inputSchema })),
|
|
1043
|
+
...this.deps.marketplace.getTools().map(name => {
|
|
1044
|
+
const definition = this.deps.marketplace.getToolDefinition(name);
|
|
1045
|
+
return { name: `plugin__${name}`, description: definition?.description ?? '', parameters: definition?.parameters };
|
|
1046
|
+
}),
|
|
1047
|
+
].filter(tool => isToolNameAllowed(tool.name) && isToolVisibleForSurface(tool.name)) : [];
|
|
1048
|
+
if (toolName === 'tool_search') {
|
|
1049
|
+
context = { ...context, extra: { ...context.extra, toolSearchCatalog: toolCatalog } };
|
|
1050
|
+
}
|
|
1037
1051
|
if (toolName === 'code_exec') {
|
|
1038
|
-
const availableTools =
|
|
1039
|
-
|
|
1040
|
-
...getMCPManager().getTools().map((tool) => tool.name),
|
|
1041
|
-
...this.deps.marketplace.getTools(),
|
|
1042
|
-
]))
|
|
1043
|
-
.filter((name) => name !== 'code_exec' && name !== 'exec' && isToolNameAllowed(name))
|
|
1044
|
-
.sort();
|
|
1052
|
+
const availableTools = [...new Set(toolCatalog.map(tool => tool.name))]
|
|
1053
|
+
.filter(name => name !== 'code_exec' && name !== 'exec').sort();
|
|
1045
1054
|
// HTTP uses one host agent and swaps logical conversations under a
|
|
1046
1055
|
// mutex. Its SessionStore ID therefore cannot isolate code_exec state;
|
|
1047
1056
|
// the opaque recovery scope is the authoritative logical session.
|
|
@@ -1055,7 +1064,11 @@ export class ToolHandler {
|
|
|
1055
1064
|
agentId: stateAgentId,
|
|
1056
1065
|
cwd: context.cwd,
|
|
1057
1066
|
availableTools,
|
|
1058
|
-
|
|
1067
|
+
abortSignal,
|
|
1068
|
+
onOutput: typeof executionExtra?.codeExecOnOutput === 'function' ? executionExtra.codeExecOnOutput : undefined,
|
|
1069
|
+
toolMetadata: toolCatalog.map(tool => ({ name: tool.name, description: tool.description })),
|
|
1070
|
+
parallelTools: availableTools.filter(name => this.registry.get(name)?.metadata.fleetSafe === true && this.registry.get(name)?.metadata.effect === 'read'),
|
|
1071
|
+
executor: async (nestedToolName, nestedArgs, nestedSignal) => {
|
|
1059
1072
|
// Defense in depth: code_exec is omitted from the child bridge and
|
|
1060
1073
|
// rejected again here so tools.call('code_exec', ...) cannot recurse.
|
|
1061
1074
|
if (nestedToolName === 'code_exec' || nestedToolName === 'exec') {
|
|
@@ -1083,6 +1096,7 @@ export class ToolHandler {
|
|
|
1083
1096
|
},
|
|
1084
1097
|
}, {
|
|
1085
1098
|
...(executionExtra ?? {}),
|
|
1099
|
+
abortSignal: nestedSignal ?? abortSignal,
|
|
1086
1100
|
recoverySessionId,
|
|
1087
1101
|
});
|
|
1088
1102
|
},
|
|
@@ -1385,7 +1399,7 @@ export class ToolHandler {
|
|
|
1385
1399
|
}
|
|
1386
1400
|
/**
|
|
1387
1401
|
* Execute a tool with streaming output.
|
|
1388
|
-
*
|
|
1402
|
+
* Supports process output, code_exec yields and progress-producing tools.
|
|
1389
1403
|
* Yields string deltas for real-time output.
|
|
1390
1404
|
*/
|
|
1391
1405
|
async *executeToolStreaming(toolCall, executionExtra) {
|
|
@@ -1401,6 +1415,11 @@ export class ToolHandler {
|
|
|
1401
1415
|
if (toolName === 'bash') {
|
|
1402
1416
|
return yield* this.executeStreamingBash(toolCall, executionExtra, startTime);
|
|
1403
1417
|
}
|
|
1418
|
+
if (toolName === 'code_exec') {
|
|
1419
|
+
return yield* streamToolOutput((abortSignal, codeExecOnOutput) => this.executeTool(toolCall, {
|
|
1420
|
+
...(executionExtra ?? {}), abortSignal, codeExecOnOutput,
|
|
1421
|
+
}), abortSignalFromExecutionExtra(executionExtra));
|
|
1422
|
+
}
|
|
1404
1423
|
// Reason: stream MCTS progress events in real-time
|
|
1405
1424
|
if (toolName === 'reason') {
|
|
1406
1425
|
try {
|
|
@@ -22,7 +22,7 @@ export const DEFAULT_AUTH_PROFILE_MANAGER_CONFIG = {
|
|
|
22
22
|
cooldownMs: 60_000, // 1 minute
|
|
23
23
|
billingCooldownMs: 18_000_000, // 5 hours
|
|
24
24
|
maxCooldownMs: 86_400_000, // 24 hours
|
|
25
|
-
persistPath
|
|
25
|
+
get persistPath() { return path.join(os.homedir(), '.codebuddy', 'auth-profiles.json'); },
|
|
26
26
|
};
|
|
27
27
|
// ============================================================================
|
|
28
28
|
// Auth Profile Manager
|
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Companion channel generation:
|
|
2
|
+
* Companion channel generation: single chat() call when without tools,
|
|
3
|
+
* or bounded tool loop (<= 3 rounds) when the speaker is identified.
|
|
3
4
|
*
|
|
4
5
|
* Failover seam: this goes through CodeBuddyClient.chat so
|
|
5
6
|
* feat/provider-fallback-2026-09-06 (`CODEBUDDY_PROVIDER_FALLBACK`) takes
|
|
6
7
|
* over when that lane is merged. Do not reimplement a fallback chain here.
|
|
8
|
+
*
|
|
9
|
+
* @module channels/companion-channel-turn
|
|
7
10
|
*/
|
|
8
|
-
import { type CodeBuddyMessage, type CodeBuddyResponse } from '../codebuddy/client.js';
|
|
11
|
+
import { type CodeBuddyMessage, type CodeBuddyResponse, type CodeBuddyTool } from '../codebuddy/client.js';
|
|
12
|
+
import type { CompanionIdentity } from '../companion/companion-identity.js';
|
|
13
|
+
import { type CompanionToolExecutionContext } from '../companion/companion-toolset.js';
|
|
14
|
+
import type { ToolResult } from '../types/index.js';
|
|
15
|
+
import type { FormalToolRegistry } from '../tools/registry/tool-registry.js';
|
|
16
|
+
import type { ConfirmationService } from '../utils/confirmation-service.js';
|
|
9
17
|
export declare const COMPANION_CHANNEL_FAILOVER_SEAM = "CodeBuddyClient.chat";
|
|
18
|
+
export declare const MAX_COMPANION_TOOL_ROUNDS = 3;
|
|
19
|
+
export interface CompanionChannelMedia {
|
|
20
|
+
type: 'image';
|
|
21
|
+
imagePath: string;
|
|
22
|
+
caption?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface CompanionExecutedTool {
|
|
25
|
+
name: string;
|
|
26
|
+
success: boolean;
|
|
27
|
+
output?: string;
|
|
28
|
+
imagePath?: string;
|
|
29
|
+
}
|
|
10
30
|
export interface CompanionChannelTurnInput {
|
|
11
31
|
apiKey: string;
|
|
12
32
|
baseUrl: string;
|
|
@@ -15,16 +35,45 @@ export interface CompanionChannelTurnInput {
|
|
|
15
35
|
signal?: AbortSignal;
|
|
16
36
|
maxTokens?: number;
|
|
17
37
|
/** Injectable chat for tests. Production uses CodeBuddyClient. */
|
|
18
|
-
chat?: (messages: CodeBuddyMessage[], tools: [], opts: {
|
|
38
|
+
chat?: (messages: CodeBuddyMessage[], tools: CodeBuddyTool[], opts: {
|
|
19
39
|
model: string;
|
|
20
40
|
maxTokens?: number;
|
|
21
41
|
signal?: AbortSignal;
|
|
22
|
-
tool_choice: 'none';
|
|
42
|
+
tool_choice: 'none' | 'auto' | 'required';
|
|
23
43
|
}) => Promise<CodeBuddyResponse>;
|
|
44
|
+
/** Authenticated identity of the interlocutor */
|
|
45
|
+
identity?: CompanionIdentity;
|
|
46
|
+
/** Surface: 'telegram' | 'mobile' | 'pwa' | 'voice' | 'channel' */
|
|
47
|
+
surface?: string;
|
|
48
|
+
/** Environment override */
|
|
49
|
+
env?: NodeJS.ProcessEnv;
|
|
50
|
+
/** Callback fired immediately when a long-running tool starts */
|
|
51
|
+
onWaitingWord?: (word: string) => Promise<void> | void;
|
|
52
|
+
/** Optional media delivery callback */
|
|
53
|
+
deliverMedia?: (media: CompanionChannelMedia) => Promise<void>;
|
|
54
|
+
/** Optional custom tool executor (injectable for tests) */
|
|
55
|
+
executeTool?: (toolName: string, args: Record<string, unknown>, context: CompanionToolExecutionContext) => Promise<ToolResult>;
|
|
56
|
+
/** Optional tool registry */
|
|
57
|
+
registry?: FormalToolRegistry;
|
|
58
|
+
/** Optional confirmation service */
|
|
59
|
+
confirmationService?: ConfirmationService;
|
|
60
|
+
/** Timeout in milliseconds (defaults to CODEBUDDY_CHANNEL_TURN_TIMEOUT_MS or 120_000) */
|
|
61
|
+
timeoutMs?: number;
|
|
62
|
+
/** Working directory */
|
|
63
|
+
cwd?: string;
|
|
24
64
|
}
|
|
25
65
|
export interface CompanionChannelTurnResult {
|
|
26
66
|
text: string;
|
|
27
67
|
model: string;
|
|
28
68
|
promptTokens?: number;
|
|
69
|
+
media?: CompanionChannelMedia[];
|
|
70
|
+
executedTools?: CompanionExecutedTool[];
|
|
71
|
+
historySuffix?: string;
|
|
29
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Executes a companion turn.
|
|
75
|
+
* If interlocutor is guest or tools circuit-breaker is OFF, runs the historical
|
|
76
|
+
* single chat(messages, [], tool_choice: 'none') call.
|
|
77
|
+
* If authorized, runs up to 3 tool turns and delivers media automatically.
|
|
78
|
+
*/
|
|
30
79
|
export declare function runCompanionChannelTurn(input: CompanionChannelTurnInput): Promise<CompanionChannelTurnResult>;
|
|
@@ -1,38 +1,240 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Companion channel generation:
|
|
2
|
+
* Companion channel generation: single chat() call when without tools,
|
|
3
|
+
* or bounded tool loop (<= 3 rounds) when the speaker is identified.
|
|
3
4
|
*
|
|
4
5
|
* Failover seam: this goes through CodeBuddyClient.chat so
|
|
5
6
|
* feat/provider-fallback-2026-09-06 (`CODEBUDDY_PROVIDER_FALLBACK`) takes
|
|
6
7
|
* over when that lane is merged. Do not reimplement a fallback chain here.
|
|
8
|
+
*
|
|
9
|
+
* @module channels/companion-channel-turn
|
|
7
10
|
*/
|
|
8
11
|
import { CodeBuddyClient } from '../codebuddy/client.js';
|
|
9
12
|
import { logger } from '../utils/logger.js';
|
|
13
|
+
import { isCompanionToolsEnabled, getCompanionToolDefinitions, getCompanionToolWaitingWord, executeCompanionTool, extractImagePathFromToolResult, } from '../companion/companion-toolset.js';
|
|
10
14
|
export const COMPANION_CHANNEL_FAILOVER_SEAM = 'CodeBuddyClient.chat';
|
|
15
|
+
export const MAX_COMPANION_TOOL_ROUNDS = 3;
|
|
16
|
+
/**
|
|
17
|
+
* Executes a companion turn.
|
|
18
|
+
* If interlocutor is guest or tools circuit-breaker is OFF, runs the historical
|
|
19
|
+
* single chat(messages, [], tool_choice: 'none') call.
|
|
20
|
+
* If authorized, runs up to 3 tool turns and delivers media automatically.
|
|
21
|
+
*/
|
|
11
22
|
export async function runCompanionChannelTurn(input) {
|
|
23
|
+
const env = input.env ?? process.env;
|
|
24
|
+
const identity = input.identity;
|
|
25
|
+
const toolsEnabled = isCompanionToolsEnabled(env) && Boolean(identity && identity.role !== 'guest');
|
|
12
26
|
const chat = input.chat ??
|
|
13
27
|
(async (messages, tools, opts) => {
|
|
14
28
|
const client = new CodeBuddyClient(input.apiKey, input.model, input.baseUrl);
|
|
15
29
|
return client.chat(messages, tools, opts);
|
|
16
30
|
});
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
// Resolve tool definitions if tools are allowed
|
|
32
|
+
let toolDefs = [];
|
|
33
|
+
if (toolsEnabled && identity) {
|
|
34
|
+
try {
|
|
35
|
+
toolDefs = await getCompanionToolDefinitions(identity, {
|
|
36
|
+
env,
|
|
37
|
+
registry: input.registry,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
logger.warn('[companion-channel-turn] Failed to resolve companion tool definitions', {
|
|
42
|
+
error: err instanceof Error ? err.message : String(err),
|
|
43
|
+
});
|
|
44
|
+
toolDefs = [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// 1. FAST / HISTORICAL PATH: No tools allowed or no tools registered
|
|
48
|
+
if (!toolsEnabled || toolDefs.length === 0) {
|
|
49
|
+
const response = await chat(input.messages, [], {
|
|
26
50
|
model: input.model,
|
|
27
|
-
|
|
51
|
+
maxTokens: input.maxTokens ?? 512,
|
|
52
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
53
|
+
tool_choice: 'none',
|
|
28
54
|
});
|
|
55
|
+
const text = response.choices[0]?.message?.content?.trim() ?? '';
|
|
56
|
+
if (!text) {
|
|
57
|
+
logger.warn('Companion channel turn returned empty content', {
|
|
58
|
+
model: input.model,
|
|
59
|
+
seam: COMPANION_CHANNEL_FAILOVER_SEAM,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
text,
|
|
64
|
+
model: response.model ?? input.model,
|
|
65
|
+
...(response.usage?.prompt_tokens !== undefined
|
|
66
|
+
? { promptTokens: response.usage.prompt_tokens }
|
|
67
|
+
: {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// 2. TOOL-ENABLED BOUNDED LOOP (<= 3 rounds)
|
|
71
|
+
const defaultTimeout = env.CODEBUDDY_CHANNEL_TURN_TIMEOUT_MS
|
|
72
|
+
? parseInt(env.CODEBUDDY_CHANNEL_TURN_TIMEOUT_MS, 10)
|
|
73
|
+
: 120_000;
|
|
74
|
+
const effectiveTimeout = input.timeoutMs ?? defaultTimeout;
|
|
75
|
+
// Signal management: propagate caller abort or timeout
|
|
76
|
+
let combinedSignal = input.signal;
|
|
77
|
+
let timeoutId;
|
|
78
|
+
if (!combinedSignal && effectiveTimeout > 0) {
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
timeoutId = setTimeout(() => controller.abort(), effectiveTimeout);
|
|
81
|
+
combinedSignal = controller.signal;
|
|
82
|
+
}
|
|
83
|
+
const activeMessages = [...input.messages];
|
|
84
|
+
const mediaProduced = [];
|
|
85
|
+
const executedTools = [];
|
|
86
|
+
const historyNotes = [];
|
|
87
|
+
let finalText = '';
|
|
88
|
+
let finalModel = input.model;
|
|
89
|
+
let totalPromptTokens;
|
|
90
|
+
try {
|
|
91
|
+
for (let round = 0; round < MAX_COMPANION_TOOL_ROUNDS; round += 1) {
|
|
92
|
+
const response = await chat(activeMessages, toolDefs, {
|
|
93
|
+
model: input.model,
|
|
94
|
+
maxTokens: input.maxTokens ?? 512,
|
|
95
|
+
...(combinedSignal ? { signal: combinedSignal } : {}),
|
|
96
|
+
tool_choice: 'auto',
|
|
97
|
+
});
|
|
98
|
+
finalModel = response.model ?? finalModel;
|
|
99
|
+
if (response.usage?.prompt_tokens !== undefined) {
|
|
100
|
+
totalPromptTokens = (totalPromptTokens ?? 0) + response.usage.prompt_tokens;
|
|
101
|
+
}
|
|
102
|
+
const assistantMsg = response.choices[0]?.message;
|
|
103
|
+
if (!assistantMsg) {
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
const content = assistantMsg.content?.trim() ?? '';
|
|
107
|
+
const toolCalls = assistantMsg.tool_calls;
|
|
108
|
+
// If no tool calls, this is the final conversational reply
|
|
109
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
110
|
+
finalText = content;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
// Add assistant response with tool_calls to conversation history
|
|
114
|
+
activeMessages.push(assistantMsg);
|
|
115
|
+
// Execute each tool call
|
|
116
|
+
for (const toolCall of toolCalls) {
|
|
117
|
+
const toolName = toolCall.function.name;
|
|
118
|
+
let args = {};
|
|
119
|
+
try {
|
|
120
|
+
args = JSON.parse(toolCall.function.arguments || '{}');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
args = {};
|
|
124
|
+
}
|
|
125
|
+
// Notify waiting word immediately before running long tools
|
|
126
|
+
const waitingWord = getCompanionToolWaitingWord(toolName);
|
|
127
|
+
if (waitingWord && input.onWaitingWord) {
|
|
128
|
+
try {
|
|
129
|
+
await input.onWaitingWord(waitingWord);
|
|
130
|
+
}
|
|
131
|
+
catch (waitErr) {
|
|
132
|
+
logger.debug('[companion-channel-turn] onWaitingWord error', { error: String(waitErr) });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Execute tool safely
|
|
136
|
+
const execFn = input.executeTool ?? executeCompanionTool;
|
|
137
|
+
let toolRes;
|
|
138
|
+
try {
|
|
139
|
+
toolRes = await execFn(toolName, args, {
|
|
140
|
+
identity: identity,
|
|
141
|
+
env,
|
|
142
|
+
cwd: input.cwd,
|
|
143
|
+
signal: combinedSignal,
|
|
144
|
+
registry: input.registry,
|
|
145
|
+
confirmationService: input.confirmationService,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (toolErr) {
|
|
149
|
+
toolRes = {
|
|
150
|
+
success: false,
|
|
151
|
+
error: toolErr instanceof Error ? toolErr.message : String(toolErr),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
// Check if an image was produced
|
|
155
|
+
const imagePath = extractImagePathFromToolResult(toolRes, input.cwd);
|
|
156
|
+
if (imagePath) {
|
|
157
|
+
mediaProduced.push({ type: 'image', imagePath });
|
|
158
|
+
historyNotes.push(`[Image générée : ${imagePath}]`);
|
|
159
|
+
}
|
|
160
|
+
// Record reminder in history notes
|
|
161
|
+
if (toolName === 'remind' && toolRes.success) {
|
|
162
|
+
const label = typeof args.label === 'string' ? args.label.trim() : 'rappel';
|
|
163
|
+
const time = typeof args.time === 'string' ? args.time.trim() : '';
|
|
164
|
+
historyNotes.push(`[Rappel créé : ${label}${time ? ` à ${time}` : ''}]`);
|
|
165
|
+
}
|
|
166
|
+
executedTools.push({
|
|
167
|
+
name: toolName,
|
|
168
|
+
success: toolRes.success,
|
|
169
|
+
output: toolRes.output ?? toolRes.error,
|
|
170
|
+
...(imagePath ? { imagePath } : {}),
|
|
171
|
+
});
|
|
172
|
+
// Add tool response message for LLM
|
|
173
|
+
activeMessages.push({
|
|
174
|
+
role: 'tool',
|
|
175
|
+
tool_call_id: toolCall.id,
|
|
176
|
+
content: toolRes.success
|
|
177
|
+
? (toolRes.output ?? 'Succès')
|
|
178
|
+
: `Erreur outil ${toolName} : ${toolRes.error ?? 'inconnue'}`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
if (timeoutId) {
|
|
185
|
+
clearTimeout(timeoutId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Fallback text if model left content blank after tool calls
|
|
189
|
+
if (!finalText && executedTools.length > 0) {
|
|
190
|
+
const hasImage = mediaProduced.length > 0;
|
|
191
|
+
if (hasImage) {
|
|
192
|
+
finalText = 'Voilà, j’ai créé l’image pour toi !';
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
finalText = 'C’est fait !';
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Deliver media (Telegram / PWA / Voice)
|
|
199
|
+
if (mediaProduced.length > 0) {
|
|
200
|
+
const surface = (input.surface ?? '').toLowerCase();
|
|
201
|
+
for (const media of mediaProduced) {
|
|
202
|
+
media.caption = finalText;
|
|
203
|
+
if (input.deliverMedia) {
|
|
204
|
+
try {
|
|
205
|
+
await input.deliverMedia(media);
|
|
206
|
+
}
|
|
207
|
+
catch (delivErr) {
|
|
208
|
+
logger.warn('[companion-channel-turn] deliverMedia failed', {
|
|
209
|
+
error: delivErr instanceof Error ? delivErr.message : String(delivErr),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (surface === 'voice') {
|
|
214
|
+
// Voice surface: alert owner on Telegram with the photo and announce it
|
|
215
|
+
try {
|
|
216
|
+
const { sendTelegramAlert } = await import('../sensory/alert.js');
|
|
217
|
+
await sendTelegramAlert(finalText, media.imagePath);
|
|
218
|
+
if (!/téléphone|telegram|envoie/i.test(finalText)) {
|
|
219
|
+
finalText = `${finalText} Je te l'envoie sur ton téléphone.`.trim();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (voiceSendErr) {
|
|
223
|
+
logger.warn('[companion-channel-turn] Voice media telegram delivery skipped', {
|
|
224
|
+
error: voiceSendErr instanceof Error ? voiceSendErr.message : String(voiceSendErr),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
29
229
|
}
|
|
230
|
+
const historySuffix = historyNotes.length > 0 ? `\n${historyNotes.join('\n')}` : undefined;
|
|
30
231
|
return {
|
|
31
|
-
text,
|
|
32
|
-
model:
|
|
33
|
-
...(
|
|
34
|
-
|
|
35
|
-
|
|
232
|
+
text: finalText,
|
|
233
|
+
model: finalModel,
|
|
234
|
+
...(totalPromptTokens !== undefined ? { promptTokens: totalPromptTokens } : {}),
|
|
235
|
+
...(mediaProduced.length > 0 ? { media: mediaProduced } : {}),
|
|
236
|
+
...(executedTools.length > 0 ? { executedTools } : {}),
|
|
237
|
+
...(historySuffix ? { historySuffix } : {}),
|
|
36
238
|
};
|
|
37
239
|
}
|
|
38
240
|
//# sourceMappingURL=companion-channel-turn.js.map
|
|
@@ -70,12 +70,10 @@ export interface SlashParityManifest {
|
|
|
70
70
|
platforms: PlatformSlashParityReport[];
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
* The canonical set of slash commands expected on each platform
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* intentionally conservative — platforms may support additional
|
|
78
|
-
* commands beyond what is listed here.
|
|
73
|
+
* The canonical set of slash commands expected on each platform, derived from
|
|
74
|
+
* the single surface declaration `CHANNEL_SLASH_SURFACES`
|
|
75
|
+
* (src/commands/slash/surfaces.ts) shared with the CLI catalog, Cowork and the
|
|
76
|
+
* slash wiki. Platforms may support additional commands beyond this list.
|
|
79
77
|
*/
|
|
80
78
|
export declare const EXPECTED_SLASH_COMMANDS: Record<string, SlashCommandSpec[]>;
|
|
81
79
|
/**
|
|
@@ -6,55 +6,20 @@
|
|
|
6
6
|
* Returns a machine-readable readiness report for each platform.
|
|
7
7
|
*/
|
|
8
8
|
import { getChannelManager } from './core.js';
|
|
9
|
+
import { CHANNEL_SLASH_SURFACES } from '../commands/slash/surfaces.js';
|
|
9
10
|
// ============================================================================
|
|
10
11
|
// Expected Commands Manifest
|
|
11
12
|
// ============================================================================
|
|
12
13
|
/**
|
|
13
|
-
* The canonical set of slash commands expected on each platform
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* intentionally conservative — platforms may support additional
|
|
18
|
-
* commands beyond what is listed here.
|
|
14
|
+
* The canonical set of slash commands expected on each platform, derived from
|
|
15
|
+
* the single surface declaration `CHANNEL_SLASH_SURFACES`
|
|
16
|
+
* (src/commands/slash/surfaces.ts) shared with the CLI catalog, Cowork and the
|
|
17
|
+
* slash wiki. Platforms may support additional commands beyond this list.
|
|
19
18
|
*/
|
|
20
|
-
export const EXPECTED_SLASH_COMMANDS =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{ name: 'clear', description: 'Clear conversation history' },
|
|
25
|
-
{ name: 'help', description: 'Show available commands' },
|
|
26
|
-
{ name: 'model', description: 'Switch or show current model' },
|
|
27
|
-
{ name: 'think', description: 'Set reasoning depth', required: false },
|
|
28
|
-
{ name: 'compact', description: 'Compact conversation context', required: false },
|
|
29
|
-
{ name: 'repo', description: 'Show repository info', required: false },
|
|
30
|
-
],
|
|
31
|
-
telegram: [
|
|
32
|
-
{ name: 'ask', description: 'Ask Code Buddy a question' },
|
|
33
|
-
{ name: 'status', description: 'Show bot and channel status' },
|
|
34
|
-
{ name: 'clear', description: 'Clear conversation history' },
|
|
35
|
-
{ name: 'help', description: 'Show available commands' },
|
|
36
|
-
{ name: 'model', description: 'Switch or show current model' },
|
|
37
|
-
{ name: 'yolo', description: 'Toggle YOLO mode', required: false },
|
|
38
|
-
{ name: 'repo', description: 'Show repository info', required: false },
|
|
39
|
-
{ name: 'branch', description: 'Show branch info', required: false },
|
|
40
|
-
],
|
|
41
|
-
slack: [
|
|
42
|
-
{ name: 'ask', description: 'Ask Code Buddy a question' },
|
|
43
|
-
{ name: 'status', description: 'Show bot and channel status' },
|
|
44
|
-
{ name: 'clear', description: 'Clear conversation history' },
|
|
45
|
-
{ name: 'help', description: 'Show available commands' },
|
|
46
|
-
{ name: 'model', description: 'Switch or show current model' },
|
|
47
|
-
{ name: 'compact', description: 'Compact conversation context', required: false },
|
|
48
|
-
{ name: 'think', description: 'Set reasoning depth', required: false },
|
|
49
|
-
],
|
|
50
|
-
matrix: [
|
|
51
|
-
{ name: 'ask', description: 'Ask Code Buddy a question' },
|
|
52
|
-
{ name: 'status', description: 'Show bot and channel status' },
|
|
53
|
-
{ name: 'clear', description: 'Clear conversation history' },
|
|
54
|
-
{ name: 'help', description: 'Show available commands' },
|
|
55
|
-
{ name: 'model', description: 'Switch or show current model', required: false },
|
|
56
|
-
],
|
|
57
|
-
};
|
|
19
|
+
export const EXPECTED_SLASH_COMMANDS = Object.fromEntries(Object.entries(CHANNEL_SLASH_SURFACES).map(([platform, specs]) => [
|
|
20
|
+
platform,
|
|
21
|
+
specs.map(({ name, description, required }) => ({ name, description, ...(required === false ? { required } : {}) })),
|
|
22
|
+
]));
|
|
58
23
|
/**
|
|
59
24
|
* Check if a channel adapter implements SlashCommandProvider.
|
|
60
25
|
*/
|
|
@@ -16,6 +16,15 @@ export declare function resumeLastSession(): Promise<void>;
|
|
|
16
16
|
* Resume a specific session by ID (--resume flag)
|
|
17
17
|
*/
|
|
18
18
|
export declare function resumeSessionById(sessionId: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Offer recent sessions without requiring an ID (P6). Non-interactive stdio:
|
|
21
|
+
* print the list and set exit code 1 (never waits for input). Returns the
|
|
22
|
+
* chosen session id, or null.
|
|
23
|
+
*/
|
|
24
|
+
export declare function pickRecentSession(limit?: number, streams?: {
|
|
25
|
+
input: NodeJS.ReadStream;
|
|
26
|
+
output: NodeJS.WriteStream;
|
|
27
|
+
}): Promise<string | null>;
|
|
19
28
|
/**
|
|
20
29
|
* List recent sessions
|
|
21
30
|
*/
|
|
@@ -97,10 +97,19 @@ export function registerSessionCommands(program) {
|
|
|
97
97
|
});
|
|
98
98
|
session
|
|
99
99
|
.command('resume')
|
|
100
|
-
.description('Resume a saved session by ID or partial ID')
|
|
101
|
-
.argument('
|
|
102
|
-
.
|
|
103
|
-
|
|
100
|
+
.description('Resume a saved session by ID or partial ID; without an ID, pick among recent sessions')
|
|
101
|
+
.argument('[sessionId]', 'session ID or unique prefix (omit to pick interactively)')
|
|
102
|
+
.option('--limit <count>', 'recent sessions offered by the picker', parsePositiveInteger, 20)
|
|
103
|
+
.action(async (sessionId, options) => {
|
|
104
|
+
if (sessionId) {
|
|
105
|
+
await resumeSessionById(sessionId);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const picked = await pickRecentSession(options.limit);
|
|
109
|
+
if (!picked)
|
|
110
|
+
return;
|
|
111
|
+
await resumeSessionById(picked);
|
|
112
|
+
console.log(`Continue it in the terminal with: buddy --resume ${picked.slice(0, 8)}`);
|
|
104
113
|
});
|
|
105
114
|
session
|
|
106
115
|
.command('last')
|
|
@@ -142,7 +151,38 @@ export async function resumeSessionById(sessionId) {
|
|
|
142
151
|
}
|
|
143
152
|
await sessionStore.resumeSession(session.id);
|
|
144
153
|
console.log(`Resuming session: ${session.name} (${session.id.slice(0, 8)})`);
|
|
145
|
-
console.log(` ${session.messages.length} messages, last accessed: ${session.lastAccessedAt.toLocaleString()}
|
|
154
|
+
console.log(` ${session.messages.length} messages, last accessed: ${session.lastAccessedAt.toLocaleString()}`);
|
|
155
|
+
const { buildSessionRecap, formatSessionRecap } = await import('./session-picker.js');
|
|
156
|
+
console.log(`${formatSessionRecap(buildSessionRecap(session)).join('\n')}\n`);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Offer recent sessions without requiring an ID (P6). Non-interactive stdio:
|
|
160
|
+
* print the list and set exit code 1 (never waits for input). Returns the
|
|
161
|
+
* chosen session id, or null.
|
|
162
|
+
*/
|
|
163
|
+
export async function pickRecentSession(limit = 20, streams = { input: process.stdin, output: process.stdout }) {
|
|
164
|
+
const { getSessionStore } = await import('../persistence/session-store.js');
|
|
165
|
+
const sessions = await getSessionStore().getRecentSessions(limit);
|
|
166
|
+
if (sessions.length === 0) {
|
|
167
|
+
console.log('No sessions found.');
|
|
168
|
+
process.exitCode = 1;
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
if (!streams.input.isTTY || !streams.output.isTTY) {
|
|
172
|
+
console.log(`Recent sessions (${sessions.length}):\n`);
|
|
173
|
+
sessions.forEach((session) => printSessionSummary(session));
|
|
174
|
+
console.log('\nNo interactive terminal: pass an ID, e.g. `buddy session resume <id>` or `buddy --resume <id>`.');
|
|
175
|
+
process.exitCode = 1;
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
const { pickSession } = await import('./session-picker.js');
|
|
179
|
+
const picked = await pickSession(sessions, streams);
|
|
180
|
+
if (!picked) {
|
|
181
|
+
console.log('Cancelled.');
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
return picked.id;
|
|
146
186
|
}
|
|
147
187
|
/**
|
|
148
188
|
* List recent sessions
|