@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
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Companion Toolset definition, authorization and execution gates.
|
|
3
|
+
*
|
|
4
|
+
* Defines which tools Lisa can use based on the interlocutor's identity tier:
|
|
5
|
+
* - 'owner': image_generate, image_edit, remind, web_search, weather, stock_quote,
|
|
6
|
+
* understand_video, camera_analyze, recall.
|
|
7
|
+
* - 'present': same tools WITHOUT remind and WITHOUT camera (camera_analyze).
|
|
8
|
+
* - 'guest': NO tools (fail-closed, byte-identical to historical turn).
|
|
9
|
+
*
|
|
10
|
+
* Hard security invariants:
|
|
11
|
+
* - NEVER bash, shell_exec, file writing (create_file, edit, patch), MCP, fleet tools.
|
|
12
|
+
* - Circuit-breaker: CODEBUDDY_COMPANION_TOOLS_ENABLED (default: false -> 0 tools).
|
|
13
|
+
* - Surcharge: CODEBUDDY_COMPANION_TOOLS (csv list, filtered against hard constraints).
|
|
14
|
+
*
|
|
15
|
+
* @module companion/companion-toolset
|
|
16
|
+
*/
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import { logger } from '../utils/logger.js';
|
|
19
|
+
import { FormalToolRegistry } from '../tools/registry/tool-registry.js';
|
|
20
|
+
export const OWNER_COMPANION_TOOLS = Object.freeze([
|
|
21
|
+
'image_generate',
|
|
22
|
+
'image_edit',
|
|
23
|
+
'remind',
|
|
24
|
+
'web_search',
|
|
25
|
+
'weather',
|
|
26
|
+
'stock_quote',
|
|
27
|
+
'understand_video',
|
|
28
|
+
'camera_analyze',
|
|
29
|
+
'recall',
|
|
30
|
+
]);
|
|
31
|
+
export const PRESENT_COMPANION_TOOLS = Object.freeze([
|
|
32
|
+
'image_generate',
|
|
33
|
+
'image_edit',
|
|
34
|
+
'web_search',
|
|
35
|
+
'weather',
|
|
36
|
+
'stock_quote',
|
|
37
|
+
'understand_video',
|
|
38
|
+
'recall',
|
|
39
|
+
]);
|
|
40
|
+
export const GUEST_COMPANION_TOOLS = Object.freeze([]);
|
|
41
|
+
/** Strictly forbidden tool patterns that can NEVER be exposed to companion */
|
|
42
|
+
export const COMPANION_FORBIDDEN_PATTERNS = Object.freeze([
|
|
43
|
+
// bash* family (bash, bash_exec, etc.)
|
|
44
|
+
/^bash/i,
|
|
45
|
+
'terminal',
|
|
46
|
+
'interactive_shell',
|
|
47
|
+
// shell* family (shell_exec, shell_git, shell_process, shell_docker, shell_k8s, etc.)
|
|
48
|
+
/^shell/i,
|
|
49
|
+
// *_exec family and code execution (code_exec, shell_exec, execute_code, etc.)
|
|
50
|
+
/(?:^|_)exec(?:$|_)/i,
|
|
51
|
+
/^execute_/i,
|
|
52
|
+
'js_repl',
|
|
53
|
+
// write_* family & file writing
|
|
54
|
+
/^write_/i,
|
|
55
|
+
/^file_write/i,
|
|
56
|
+
'create_file',
|
|
57
|
+
// patch family
|
|
58
|
+
'patch',
|
|
59
|
+
/^apply_patch/i,
|
|
60
|
+
// str_replace* family (str_replace, str_replace_editor, etc.)
|
|
61
|
+
/^str_replace/i,
|
|
62
|
+
// multi_edit and edit_* family (file editing; does NOT match image_edit)
|
|
63
|
+
'multi_edit',
|
|
64
|
+
/^multi_edit/i,
|
|
65
|
+
/^edit_/i,
|
|
66
|
+
/^file_edit/i,
|
|
67
|
+
// delete_* family
|
|
68
|
+
/^delete_/i,
|
|
69
|
+
// system / infra / process / code execution / app server
|
|
70
|
+
'docker',
|
|
71
|
+
'kubernetes',
|
|
72
|
+
'process',
|
|
73
|
+
/^process/i,
|
|
74
|
+
'git',
|
|
75
|
+
/^git_/i,
|
|
76
|
+
'resolve_conflicts',
|
|
77
|
+
'app_server',
|
|
78
|
+
'computer_control',
|
|
79
|
+
'office_macro_execute',
|
|
80
|
+
'codebase_replace',
|
|
81
|
+
'scaffold_app',
|
|
82
|
+
'tool_search',
|
|
83
|
+
'extension_forge',
|
|
84
|
+
'scan_vulnerabilities',
|
|
85
|
+
'env_doctor',
|
|
86
|
+
'resource_catalog',
|
|
87
|
+
'port_check',
|
|
88
|
+
'lint_project',
|
|
89
|
+
'test_runner',
|
|
90
|
+
'format_project',
|
|
91
|
+
'build_project',
|
|
92
|
+
// A2A / MCP / orchestration / registration
|
|
93
|
+
/^a2a_/i,
|
|
94
|
+
/^mcp_/i,
|
|
95
|
+
/^fleet_/i,
|
|
96
|
+
/^peer_/i,
|
|
97
|
+
/^delegate_/i,
|
|
98
|
+
/^register_tool/i,
|
|
99
|
+
'register_tool',
|
|
100
|
+
]);
|
|
101
|
+
/**
|
|
102
|
+
* Check if a tool is strictly forbidden for the companion.
|
|
103
|
+
*/
|
|
104
|
+
export function isForbiddenCompanionTool(toolName) {
|
|
105
|
+
const norm = toolName.trim().toLowerCase();
|
|
106
|
+
for (const pattern of COMPANION_FORBIDDEN_PATTERNS) {
|
|
107
|
+
if (typeof pattern === 'string') {
|
|
108
|
+
if (norm === pattern.toLowerCase())
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
else if (pattern instanceof RegExp) {
|
|
112
|
+
if (pattern.test(norm))
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check if companion tools are enabled via circuit-breaker.
|
|
120
|
+
* Default is FALSE (OFF).
|
|
121
|
+
*/
|
|
122
|
+
export function isCompanionToolsEnabled(env = process.env) {
|
|
123
|
+
const raw = (env.CODEBUDDY_COMPANION_TOOLS_ENABLED ?? '').trim().toLowerCase();
|
|
124
|
+
return raw === 'true' || raw === '1' || raw === 'yes' || raw === 'on';
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Resolve allowed tool names for a given identity and environment.
|
|
128
|
+
*/
|
|
129
|
+
export function getCompanionToolNames(identity, env = process.env) {
|
|
130
|
+
// 1. Circuit breaker OFF -> zero tools
|
|
131
|
+
if (!isCompanionToolsEnabled(env)) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
// 2. Guest role -> zero tools (fail-closed)
|
|
135
|
+
if (identity.role === 'guest') {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
// 3. Baseline per role
|
|
139
|
+
const baseline = identity.role === 'owner' ? OWNER_COMPANION_TOOLS : PRESENT_COMPANION_TOOLS;
|
|
140
|
+
// 4. Surcharge via CODEBUDDY_COMPANION_TOOLS (CSV)
|
|
141
|
+
// Hard invariant: CSV can ONLY INTERSECT the role's baseline tools, NEVER extend it.
|
|
142
|
+
let allowed;
|
|
143
|
+
const configured = (env.CODEBUDDY_COMPANION_TOOLS ?? '').trim();
|
|
144
|
+
if (configured) {
|
|
145
|
+
const requested = new Set(configured
|
|
146
|
+
.split(',')
|
|
147
|
+
.map((s) => s.trim().toLowerCase())
|
|
148
|
+
.filter(Boolean));
|
|
149
|
+
// Strict intersection with role baseline (order preserved from baseline)
|
|
150
|
+
allowed = baseline.filter((tool) => {
|
|
151
|
+
const match = requested.has(tool.toLowerCase());
|
|
152
|
+
if (!match)
|
|
153
|
+
return false;
|
|
154
|
+
if (isForbiddenCompanionTool(tool)) {
|
|
155
|
+
logger.warn(`[companion-toolset] Surcharge tool "${tool}" rejected: strictly forbidden`);
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
allowed = [...baseline];
|
|
163
|
+
}
|
|
164
|
+
// Final sanity filter: eliminate any forbidden tool that could have leaked
|
|
165
|
+
return allowed.filter((tool) => !isForbiddenCompanionTool(tool));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Human-friendly waiting phrase when a slow tool starts executing.
|
|
169
|
+
*/
|
|
170
|
+
export function getCompanionToolWaitingWord(toolName) {
|
|
171
|
+
switch (toolName) {
|
|
172
|
+
case 'image_generate':
|
|
173
|
+
return 'Je dessine…';
|
|
174
|
+
case 'image_edit':
|
|
175
|
+
return 'Je modifie l’image…';
|
|
176
|
+
case 'camera_analyze':
|
|
177
|
+
case 'camera_snapshot':
|
|
178
|
+
return 'Je regarde…';
|
|
179
|
+
case 'web_search':
|
|
180
|
+
return 'Je cherche sur le web…';
|
|
181
|
+
case 'weather':
|
|
182
|
+
return 'Je regarde la météo…';
|
|
183
|
+
case 'stock_quote':
|
|
184
|
+
return 'Je vérifie les cours de bourse…';
|
|
185
|
+
case 'understand_video':
|
|
186
|
+
return 'J’analyse la vidéo…';
|
|
187
|
+
case 'remind':
|
|
188
|
+
return 'Je note ton rappel…';
|
|
189
|
+
case 'recall':
|
|
190
|
+
return 'Je vérifie dans mes souvenirs…';
|
|
191
|
+
default:
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get OpenAI-compatible function tool definitions for allowed companion tools.
|
|
197
|
+
*/
|
|
198
|
+
export async function getCompanionToolDefinitions(identity, options = {}) {
|
|
199
|
+
const env = options.env ?? process.env;
|
|
200
|
+
const toolNames = getCompanionToolNames(identity, env);
|
|
201
|
+
if (toolNames.length === 0)
|
|
202
|
+
return [];
|
|
203
|
+
const registry = options.registry ?? FormalToolRegistry.getInstance();
|
|
204
|
+
if (registry.getNames().length === 0) {
|
|
205
|
+
const { registerBuiltinTools } = await import('../tools/registry/index.js');
|
|
206
|
+
registerBuiltinTools(registry);
|
|
207
|
+
}
|
|
208
|
+
const definitions = [];
|
|
209
|
+
for (const name of toolNames) {
|
|
210
|
+
const registered = registry.get(name);
|
|
211
|
+
if (!registered) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const schema = registered.tool.getSchema();
|
|
215
|
+
definitions.push({
|
|
216
|
+
type: 'function',
|
|
217
|
+
function: {
|
|
218
|
+
name: schema.name,
|
|
219
|
+
description: schema.description,
|
|
220
|
+
parameters: {
|
|
221
|
+
type: 'object',
|
|
222
|
+
properties: schema.parameters?.properties ?? {},
|
|
223
|
+
required: schema.parameters?.required ?? [],
|
|
224
|
+
...(schema.parameters?.additionalProperties !== undefined
|
|
225
|
+
? { additionalProperties: schema.parameters.additionalProperties }
|
|
226
|
+
: {}),
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return definitions;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Safely execute a companion tool call.
|
|
235
|
+
*/
|
|
236
|
+
export async function executeCompanionTool(toolName, args, context) {
|
|
237
|
+
const env = context.env ?? process.env;
|
|
238
|
+
// 1. Hard invariant: forbidden tool
|
|
239
|
+
if (isForbiddenCompanionTool(toolName)) {
|
|
240
|
+
const err = `Tool "${toolName}" is strictly forbidden in companion mode.`;
|
|
241
|
+
logger.warn(`[companion-toolset] ${err}`);
|
|
242
|
+
return { success: false, error: err };
|
|
243
|
+
}
|
|
244
|
+
// 2. Authorization check against identity role
|
|
245
|
+
const allowedNames = getCompanionToolNames(context.identity, env);
|
|
246
|
+
if (!allowedNames.includes(toolName)) {
|
|
247
|
+
const err = `Tool "${toolName}" is not permitted for companion identity role "${context.identity.role}".`;
|
|
248
|
+
logger.warn(`[companion-toolset] ${err}`);
|
|
249
|
+
return { success: false, error: err };
|
|
250
|
+
}
|
|
251
|
+
// 3. Confirmation gate:
|
|
252
|
+
// Destructive tools are blocked by isForbiddenCompanionTool.
|
|
253
|
+
// For permitted companion read/generation tools, validate against policy engine kill-switch
|
|
254
|
+
// and honor any explicit confirmationService passed in context.
|
|
255
|
+
if (context.confirmationService) {
|
|
256
|
+
const confirmationRes = await context.confirmationService.requestConfirmation({
|
|
257
|
+
operation: `companion:${toolName}`,
|
|
258
|
+
filename: toolName,
|
|
259
|
+
toolName,
|
|
260
|
+
toolArgs: args,
|
|
261
|
+
showVSCodeOpen: false,
|
|
262
|
+
content: `Companion tool: ${toolName}\nArguments:\n${JSON.stringify(args, null, 2)}`,
|
|
263
|
+
}, 'tool');
|
|
264
|
+
if (!confirmationRes.confirmed) {
|
|
265
|
+
return {
|
|
266
|
+
success: false,
|
|
267
|
+
error: confirmationRes.feedback ?? `Execution of "${toolName}" was rejected by confirmation policy.`,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
const { PolicyEngine } = await import('../security/policy-engine.js');
|
|
273
|
+
if (PolicyEngine.getInstance().isKilled()) {
|
|
274
|
+
return {
|
|
275
|
+
success: false,
|
|
276
|
+
error: `Security kill-switch active: ${PolicyEngine.getInstance().getKillReason()}`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// 4. Retrieve tool from registry
|
|
281
|
+
const registry = context.registry ?? FormalToolRegistry.getInstance();
|
|
282
|
+
if (registry.getNames().length === 0) {
|
|
283
|
+
const { registerBuiltinTools } = await import('../tools/registry/index.js');
|
|
284
|
+
registerBuiltinTools(registry);
|
|
285
|
+
}
|
|
286
|
+
const registered = registry.get(toolName);
|
|
287
|
+
if (!registered) {
|
|
288
|
+
return {
|
|
289
|
+
success: false,
|
|
290
|
+
error: `Companion tool "${toolName}" is not registered in the tool registry.`,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// 5. Execute
|
|
294
|
+
try {
|
|
295
|
+
return await registered.tool.execute(args, {
|
|
296
|
+
cwd: context.cwd ?? process.cwd(),
|
|
297
|
+
abortSignal: context.signal,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
catch (execError) {
|
|
301
|
+
const msg = execError instanceof Error ? execError.message : String(execError);
|
|
302
|
+
logger.warn(`[companion-toolset] Error executing tool "${toolName}": ${msg}`);
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
error: `Tool execution error: ${msg}`,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Extract image path from tool execution result if one was created/returned.
|
|
311
|
+
*/
|
|
312
|
+
export function extractImagePathFromToolResult(result, cwd = process.cwd()) {
|
|
313
|
+
if (!result || !result.success)
|
|
314
|
+
return undefined;
|
|
315
|
+
const isImagePath = (val) => {
|
|
316
|
+
if (typeof val !== 'string' || !val.trim())
|
|
317
|
+
return false;
|
|
318
|
+
const clean = val.trim();
|
|
319
|
+
return /\.(png|jpe?g|webp)$/i.test(clean);
|
|
320
|
+
};
|
|
321
|
+
const toAbs = (filePath) => {
|
|
322
|
+
return path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
323
|
+
};
|
|
324
|
+
const data = result.data;
|
|
325
|
+
if (data && typeof data === 'object') {
|
|
326
|
+
if (isImagePath(data.mediaPath))
|
|
327
|
+
return toAbs(data.mediaPath);
|
|
328
|
+
if (isImagePath(data.imagePath))
|
|
329
|
+
return toAbs(data.imagePath);
|
|
330
|
+
if (isImagePath(data.outputPath))
|
|
331
|
+
return toAbs(data.outputPath);
|
|
332
|
+
if (isImagePath(data.path))
|
|
333
|
+
return toAbs(data.path);
|
|
334
|
+
if (isImagePath(data.image))
|
|
335
|
+
return toAbs(data.image);
|
|
336
|
+
if (Array.isArray(data.images) && isImagePath(data.images[0]?.path)) {
|
|
337
|
+
return toAbs(data.images[0].path);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Fallback: check output string if JSON
|
|
341
|
+
if (typeof result.output === 'string') {
|
|
342
|
+
try {
|
|
343
|
+
const parsed = JSON.parse(result.output);
|
|
344
|
+
if (parsed && typeof parsed === 'object') {
|
|
345
|
+
if (isImagePath(parsed.mediaPath))
|
|
346
|
+
return toAbs(parsed.mediaPath);
|
|
347
|
+
if (isImagePath(parsed.imagePath))
|
|
348
|
+
return toAbs(parsed.imagePath);
|
|
349
|
+
if (isImagePath(parsed.outputPath))
|
|
350
|
+
return toAbs(parsed.outputPath);
|
|
351
|
+
if (isImagePath(parsed.path))
|
|
352
|
+
return toAbs(parsed.path);
|
|
353
|
+
if (isImagePath(parsed.image))
|
|
354
|
+
return toAbs(parsed.image);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
// not JSON
|
|
359
|
+
}
|
|
360
|
+
// Search for an absolute POSIX or Windows image path in human-readable output.
|
|
361
|
+
const match = result.output.match(/(?:^|[\s"'`])((?:[a-z]:[\\/]|\/)[^\s"'`]+\.(?:png|jpe?g|webp))/i);
|
|
362
|
+
if (match && match[1]) {
|
|
363
|
+
return match[1];
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=companion-toolset.js.map
|
|
@@ -31,6 +31,7 @@ import type { CompanionSelfieServeResult, CompanionSelfieSurface, TryServeCompan
|
|
|
31
31
|
/** A companion surface. `voice` keeps its own loop; it is listed for symmetry. */
|
|
32
32
|
export type CompanionSurface = CompanionSelfieSurface;
|
|
33
33
|
export type { CompanionHistoryTurn } from './companion-history.js';
|
|
34
|
+
import { type CompanionIdentity } from './companion-identity.js';
|
|
34
35
|
export interface CompanionTurnResult {
|
|
35
36
|
text: string;
|
|
36
37
|
kind: 'selfie' | 'text';
|
|
@@ -40,6 +41,8 @@ export interface CompanionTurnResult {
|
|
|
40
41
|
};
|
|
41
42
|
imagePath?: string;
|
|
42
43
|
model?: string;
|
|
44
|
+
historySuffix?: string;
|
|
45
|
+
executedTools?: import('../channels/companion-channel-turn.js').CompanionExecutedTool[];
|
|
43
46
|
/** Present only when the user shared photos in this turn. */
|
|
44
47
|
photos?: {
|
|
45
48
|
/** Where the image went. `local` means the bytes never left the machine. */
|
|
@@ -60,6 +63,11 @@ export interface RunCompanionTurnOptions {
|
|
|
60
63
|
history?: CompanionHistoryTurn[];
|
|
61
64
|
env?: NodeJS.ProcessEnv;
|
|
62
65
|
signal?: AbortSignal;
|
|
66
|
+
/** Explicit identity of the user, or resolved from surface and IDs */
|
|
67
|
+
identity?: CompanionIdentity;
|
|
68
|
+
userId?: string;
|
|
69
|
+
chatId?: string;
|
|
70
|
+
onWaitingWord?: (word: string) => Promise<void> | void;
|
|
63
71
|
/**
|
|
64
72
|
* Photos the user shared with this message. Absent (the default) the turn is
|
|
65
73
|
* byte-identical to a text-only turn: no photo module is even imported.
|
|
@@ -70,11 +78,11 @@ export interface RunCompanionTurnOptions {
|
|
|
70
78
|
/** Injectables — production resolves each of these itself. */
|
|
71
79
|
resolveProvider?: (env: NodeJS.ProcessEnv) => CompanionTurnProvider | null;
|
|
72
80
|
serveSelfie?: (text: string, options: TryServeCompanionSelfieOptions) => Promise<CompanionSelfieServeResult | null>;
|
|
73
|
-
chat?: (messages: CodeBuddyMessage[], tools: [], opts: {
|
|
81
|
+
chat?: (messages: CodeBuddyMessage[], tools: unknown[], opts: {
|
|
74
82
|
model: string;
|
|
75
83
|
maxTokens?: number;
|
|
76
84
|
signal?: AbortSignal;
|
|
77
|
-
tool_choice
|
|
85
|
+
tool_choice?: unknown;
|
|
78
86
|
}) => Promise<CodeBuddyResponse>;
|
|
79
87
|
/** Photo seams — production uses the real pipeline and the real album. */
|
|
80
88
|
preparePhotos?: typeof prepareCompanionPhotos;
|
|
@@ -32,6 +32,7 @@ import { attachPhotoParts, looksLikeVisionRefusal, prepareCompanionPhotos, } fro
|
|
|
32
32
|
import { rememberSharedPhotos } from './shared-photo-memory.js';
|
|
33
33
|
import { applyLimitsContract } from './reply-augment.js';
|
|
34
34
|
import { guardRelationshipReply } from '../conversation/relationship-safety.js';
|
|
35
|
+
import { resolveCompanionIdentity } from './companion-identity.js';
|
|
35
36
|
/** Fallback when no provider is configured — spoken, never a silent empty reply. */
|
|
36
37
|
const NO_PROVIDER_MESSAGE = 'unreachable: no configured provider for the companion turn';
|
|
37
38
|
export { historyHasRecentSelfie } from './companion-history.js';
|
|
@@ -132,6 +133,13 @@ export async function runCompanionTurn(message, options) {
|
|
|
132
133
|
const messagesFor = (batch, base) => batch && batch.mode === 'cloud' && batch.photos.length > 0
|
|
133
134
|
? attachPhotoParts(base, batch.photos)
|
|
134
135
|
: base;
|
|
136
|
+
const identity = options.identity ??
|
|
137
|
+
resolveCompanionIdentity({
|
|
138
|
+
channel: options.surface === 'mobile' ? 'pwa' : options.surface,
|
|
139
|
+
userId: options.userId,
|
|
140
|
+
chatId: options.chatId,
|
|
141
|
+
env,
|
|
142
|
+
});
|
|
135
143
|
try {
|
|
136
144
|
let batch = prepared;
|
|
137
145
|
let generated = await runCompanionChannelTurn({
|
|
@@ -139,6 +147,10 @@ export async function runCompanionTurn(message, options) {
|
|
|
139
147
|
baseUrl: provider.baseUrl,
|
|
140
148
|
model: provider.model,
|
|
141
149
|
messages: messagesFor(batch, prompt.messages),
|
|
150
|
+
identity,
|
|
151
|
+
surface: options.surface,
|
|
152
|
+
env,
|
|
153
|
+
...(options.onWaitingWord ? { onWaitingWord: options.onWaitingWord } : {}),
|
|
142
154
|
...(options.signal ? { signal: options.signal } : {}),
|
|
143
155
|
...(options.chat ? { chat: options.chat } : {}),
|
|
144
156
|
});
|
|
@@ -168,6 +180,10 @@ export async function runCompanionTurn(message, options) {
|
|
|
168
180
|
baseUrl: provider.baseUrl,
|
|
169
181
|
model: provider.model,
|
|
170
182
|
messages: localPrompt.messages,
|
|
183
|
+
identity,
|
|
184
|
+
surface: options.surface,
|
|
185
|
+
env,
|
|
186
|
+
...(options.onWaitingWord ? { onWaitingWord: options.onWaitingWord } : {}),
|
|
171
187
|
...(options.signal ? { signal: options.signal } : {}),
|
|
172
188
|
...(options.chat ? { chat: options.chat } : {}),
|
|
173
189
|
});
|
|
@@ -184,10 +200,31 @@ export async function runCompanionTurn(message, options) {
|
|
|
184
200
|
}
|
|
185
201
|
const guarded = guardRelationshipReply(text);
|
|
186
202
|
const limited = applyLimitsContract(guarded.response, { heard: message, env });
|
|
203
|
+
const firstMedia = generated.media?.[0];
|
|
204
|
+
let generatedImage;
|
|
205
|
+
if (firstMedia?.imagePath && (options.includeImageBytes === true || options.surface === 'mobile')) {
|
|
206
|
+
try {
|
|
207
|
+
const fsMod = await import('fs/promises');
|
|
208
|
+
const pathMod = await import('path');
|
|
209
|
+
const ext = pathMod.extname(firstMedia.imagePath).slice(1).toLowerCase();
|
|
210
|
+
const mimeType = ext === 'jpg' || ext === 'jpeg' ? 'image/jpeg' : `image/${ext || 'png'}`;
|
|
211
|
+
const data = (await fsMod.readFile(firstMedia.imagePath)).toString('base64');
|
|
212
|
+
generatedImage = { mimeType, data };
|
|
213
|
+
}
|
|
214
|
+
catch (readErr) {
|
|
215
|
+
logger.warn('[companion-turn] Failed to read generated media bytes', {
|
|
216
|
+
error: readErr instanceof Error ? readErr.message : String(readErr),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
187
220
|
return {
|
|
188
221
|
text: prependUserFacingFailoverNotice(limited.text, 'companion-turn'),
|
|
189
|
-
kind: 'text',
|
|
222
|
+
kind: firstMedia ? 'selfie' : 'text',
|
|
223
|
+
...(firstMedia?.imagePath ? { imagePath: firstMedia.imagePath } : {}),
|
|
224
|
+
...(generatedImage ? { image: generatedImage } : {}),
|
|
190
225
|
model: generated.model,
|
|
226
|
+
...(generated.historySuffix ? { historySuffix: generated.historySuffix } : {}),
|
|
227
|
+
...(generated.executedTools ? { executedTools: generated.executedTools } : {}),
|
|
191
228
|
...(photoSummary ? { photos: photoSummary } : {}),
|
|
192
229
|
};
|
|
193
230
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic tool calling (`code_exec`) policy per model (comparatif plan P5).
|
|
3
|
+
*
|
|
4
|
+
* - `offer` (default, unchanged behaviour): `code_exec` is selected by relevance
|
|
5
|
+
* or when the user explicitly asks for programmatic tool calling.
|
|
6
|
+
* - `prefer`: `code_exec` is always offered and the model gets a short hint to
|
|
7
|
+
* batch multi-step reads/computations into one program.
|
|
8
|
+
* - `off`: `code_exec` is never offered, even on explicit request; the model is
|
|
9
|
+
* told why through the runtime settings snapshot.
|
|
10
|
+
*
|
|
11
|
+
* Promotion rule: NO model ships with `prefer`. A `prefer` entry in
|
|
12
|
+
* `model-tools.ts` must carry `codeExecEvidence` (a Buddy recette report proving
|
|
13
|
+
* ADV01–ADV09 on that model). Other projects' "preferred" lists are not evidence.
|
|
14
|
+
* `CODEBUDDY_CODE_EXEC_POLICY` is an explicit operator override for trials.
|
|
15
|
+
*/
|
|
16
|
+
export type CodeExecPolicy = 'off' | 'offer' | 'prefer';
|
|
17
|
+
export interface ResolvedCodeExecPolicy {
|
|
18
|
+
policy: CodeExecPolicy;
|
|
19
|
+
source: 'env' | 'model' | 'default';
|
|
20
|
+
evidence?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function isCodeExecPolicy(value: unknown): value is CodeExecPolicy;
|
|
23
|
+
export declare function resolveCodeExecPolicy(model: string | undefined): ResolvedCodeExecPolicy;
|
|
24
|
+
export declare const CODE_EXEC_PREFER_HINT = "Programmatic tool calling is preferred for this model: when a task needs several reads, searches or computations whose results feed each other, run them in ONE code_exec program (tools.call) instead of many separate tool rounds. Keep single-step tasks as direct tool calls.";
|
|
25
|
+
export declare const CODE_EXEC_OFF_NOTICE = "Programmatic tool calling (code_exec) is disabled by the model policy for this model. If the user asks for code_exec or tools.call, say that it is disabled for this model and use direct tool calls instead.";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic tool calling (`code_exec`) policy per model (comparatif plan P5).
|
|
3
|
+
*
|
|
4
|
+
* - `offer` (default, unchanged behaviour): `code_exec` is selected by relevance
|
|
5
|
+
* or when the user explicitly asks for programmatic tool calling.
|
|
6
|
+
* - `prefer`: `code_exec` is always offered and the model gets a short hint to
|
|
7
|
+
* batch multi-step reads/computations into one program.
|
|
8
|
+
* - `off`: `code_exec` is never offered, even on explicit request; the model is
|
|
9
|
+
* told why through the runtime settings snapshot.
|
|
10
|
+
*
|
|
11
|
+
* Promotion rule: NO model ships with `prefer`. A `prefer` entry in
|
|
12
|
+
* `model-tools.ts` must carry `codeExecEvidence` (a Buddy recette report proving
|
|
13
|
+
* ADV01–ADV09 on that model). Other projects' "preferred" lists are not evidence.
|
|
14
|
+
* `CODEBUDDY_CODE_EXEC_POLICY` is an explicit operator override for trials.
|
|
15
|
+
*/
|
|
16
|
+
import { getModelToolConfig } from './model-tools.js';
|
|
17
|
+
const POLICIES = new Set(['off', 'offer', 'prefer']);
|
|
18
|
+
export function isCodeExecPolicy(value) {
|
|
19
|
+
return typeof value === 'string' && POLICIES.has(value);
|
|
20
|
+
}
|
|
21
|
+
export function resolveCodeExecPolicy(model) {
|
|
22
|
+
const override = process.env.CODEBUDDY_CODE_EXEC_POLICY?.trim().toLowerCase();
|
|
23
|
+
if (isCodeExecPolicy(override))
|
|
24
|
+
return { policy: override, source: 'env' };
|
|
25
|
+
if (model) {
|
|
26
|
+
const config = getModelToolConfig(model);
|
|
27
|
+
if (isCodeExecPolicy(config.codeExec)) {
|
|
28
|
+
return {
|
|
29
|
+
policy: config.codeExec,
|
|
30
|
+
source: 'model',
|
|
31
|
+
...(config.codeExecEvidence ? { evidence: config.codeExecEvidence } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { policy: 'offer', source: 'default' };
|
|
36
|
+
}
|
|
37
|
+
export const CODE_EXEC_PREFER_HINT = 'Programmatic tool calling is preferred for this model: when a task needs several reads, searches or computations whose results feed each other, run them in ONE code_exec program (tools.call) instead of many separate tool rounds. Keep single-step tasks as direct tool calls.';
|
|
38
|
+
export const CODE_EXEC_OFF_NOTICE = 'Programmatic tool calling (code_exec) is disabled by the model policy for this model. If the user asks for code_exec or tools.call, say that it is disabled for this model and use direct tool calls instead.';
|
|
39
|
+
//# sourceMappingURL=code-exec-policy.js.map
|
|
@@ -54,6 +54,13 @@ export interface ModelToolConfig {
|
|
|
54
54
|
* full instruction set.
|
|
55
55
|
*/
|
|
56
56
|
promptProfile?: 'lite' | 'standard' | 'rich';
|
|
57
|
+
/**
|
|
58
|
+
* Programmatic tool calling policy (P5, `src/config/code-exec-policy.ts`).
|
|
59
|
+
* Absent = `offer` (historical behaviour). `prefer` requires `codeExecEvidence`.
|
|
60
|
+
*/
|
|
61
|
+
codeExec?: 'off' | 'offer' | 'prefer';
|
|
62
|
+
/** Path of the Buddy recette report (ADV01–ADV09) that justifies `codeExec: 'prefer'`. */
|
|
63
|
+
codeExecEvidence?: string;
|
|
57
64
|
}
|
|
58
65
|
/**
|
|
59
66
|
* Nom « nu » d'un modèle : sans préfixe fournisseur (`moonshotai/kimi-k3` → `kimi-k3`) ni tag
|
|
@@ -81,6 +88,8 @@ export declare function resetRuntimeModelContextCache(): void;
|
|
|
81
88
|
* décrits ici sans les dupliquer dans `SUPPORTED_MODELS`.
|
|
82
89
|
*/
|
|
83
90
|
export declare function findModelToolConfig(modelName: string, customConfigs?: ModelToolConfig[]): ModelToolConfig | null;
|
|
91
|
+
/** Read-only view of the built-in table (consistency tests, e.g. P5 `codeExecEvidence`). */
|
|
92
|
+
export declare function listDefaultModelToolConfigs(): readonly Readonly<ModelToolConfig>[];
|
|
84
93
|
export declare function getModelToolConfig(modelName: string, customConfigs?: ModelToolConfig[]): ModelToolConfig;
|
|
85
94
|
/** Test seam — clear the strengths memo. */
|
|
86
95
|
export declare function resetModelStrengthsCache(): void;
|