@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
|
@@ -376,6 +376,26 @@ const DEFAULT_MODEL_CONFIGS = [
|
|
|
376
376
|
patchFormat: 'search_replace',
|
|
377
377
|
strengths: ['french'],
|
|
378
378
|
},
|
|
379
|
+
// Lemonade GGUF ids (`Qwen3.6-35B-A3B-MTP-GGUF`) must win over the hosted
|
|
380
|
+
// `qwen3.6*` row below. That hosted row is a 262k OpenRouter ceiling with the
|
|
381
|
+
// default (standard) prompt profile — in the agent loop it drowns the model
|
|
382
|
+
// in schemas and the model shells `list_peers` via `bash` instead of calling
|
|
383
|
+
// `peer_tool_invoke` (mission 8: 33.7 tok/s raw tools OK, 9× bash in-loop).
|
|
384
|
+
// Match is case-insensitive (`matchModel` /i). Keep the same lite surface as
|
|
385
|
+
// `gemma4*` which completed the fleet recipe.
|
|
386
|
+
{
|
|
387
|
+
model: 'Qwen3.6-*-GGUF*',
|
|
388
|
+
strengths: ['code', 'french'],
|
|
389
|
+
supportsReasoning: true,
|
|
390
|
+
supportsToolCalls: true,
|
|
391
|
+
supportsVision: false,
|
|
392
|
+
contextWindow: 32768,
|
|
393
|
+
maxOutputTokens: 8192,
|
|
394
|
+
maxToolRounds: 20,
|
|
395
|
+
disabledTools: ['apply_patch', 'browser', 'computer_control'],
|
|
396
|
+
patchFormat: 'search_replace',
|
|
397
|
+
promptProfile: 'lite',
|
|
398
|
+
},
|
|
379
399
|
// Qwen 3.5 → 3.7 hébergés (262 144 chez tous les fournisseurs OpenRouter). Un runtime local
|
|
380
400
|
// qui en sert moins abaisse la valeur via la découverte Ollama/LM Studio.
|
|
381
401
|
{
|
|
@@ -896,6 +916,56 @@ const DEFAULT_MODEL_CONFIGS = [
|
|
|
896
916
|
patchFormat: 'full_file',
|
|
897
917
|
promptProfile: 'lite',
|
|
898
918
|
},
|
|
919
|
+
{
|
|
920
|
+
model: 'qwen2.5:14b*',
|
|
921
|
+
strengths: ['french'],
|
|
922
|
+
supportsReasoning: false,
|
|
923
|
+
supportsToolCalls: true,
|
|
924
|
+
supportsVision: false,
|
|
925
|
+
contextWindow: 32768,
|
|
926
|
+
maxOutputTokens: 4096,
|
|
927
|
+
patchFormat: 'search_replace',
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
model: 'qwen2.5:32b*',
|
|
931
|
+
strengths: ['french'],
|
|
932
|
+
supportsReasoning: false,
|
|
933
|
+
supportsToolCalls: true,
|
|
934
|
+
supportsVision: false,
|
|
935
|
+
contextWindow: 32768,
|
|
936
|
+
maxOutputTokens: 8192,
|
|
937
|
+
patchFormat: 'search_replace',
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
model: 'qwen2.5:72b*',
|
|
941
|
+
strengths: ['french'],
|
|
942
|
+
supportsReasoning: false,
|
|
943
|
+
supportsToolCalls: true,
|
|
944
|
+
supportsVision: false,
|
|
945
|
+
contextWindow: 32768,
|
|
946
|
+
maxOutputTokens: 8192,
|
|
947
|
+
patchFormat: 'search_replace',
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
model: 'qwen2.5-coder:14b*',
|
|
951
|
+
strengths: ['french', 'code'],
|
|
952
|
+
supportsReasoning: false,
|
|
953
|
+
supportsToolCalls: true,
|
|
954
|
+
supportsVision: false,
|
|
955
|
+
contextWindow: 32768,
|
|
956
|
+
maxOutputTokens: 4096,
|
|
957
|
+
patchFormat: 'search_replace',
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
model: 'qwen2.5-coder:32b*',
|
|
961
|
+
strengths: ['french', 'code'],
|
|
962
|
+
supportsReasoning: false,
|
|
963
|
+
supportsToolCalls: true,
|
|
964
|
+
supportsVision: false,
|
|
965
|
+
contextWindow: 32768,
|
|
966
|
+
maxOutputTokens: 8192,
|
|
967
|
+
patchFormat: 'search_replace',
|
|
968
|
+
},
|
|
899
969
|
{
|
|
900
970
|
model: 'qwen2.5*',
|
|
901
971
|
strengths: ['french'],
|
|
@@ -904,6 +974,7 @@ const DEFAULT_MODEL_CONFIGS = [
|
|
|
904
974
|
// tool_calls) via Ollama, so the agent can't execute them — it stays
|
|
905
975
|
// chat-only. Verified flaky against scripts/autonomy-lab/ (unlike qwen3,
|
|
906
976
|
// which does emit structured calls). Use qwen3+ for autonomous editing.
|
|
977
|
+
// Explicitly split by size: 14b+ are promoted above, <14b stay gated.
|
|
907
978
|
supportsToolCalls: false,
|
|
908
979
|
supportsVision: false,
|
|
909
980
|
contextWindow: 32768,
|
|
@@ -962,9 +1033,37 @@ const DEFAULT_MODEL_CONFIGS = [
|
|
|
962
1033
|
patchFormat: 'full_file',
|
|
963
1034
|
promptProfile: 'lite',
|
|
964
1035
|
},
|
|
1036
|
+
{
|
|
1037
|
+
model: 'llama3.1:70b*',
|
|
1038
|
+
supportsReasoning: false,
|
|
1039
|
+
supportsToolCalls: true,
|
|
1040
|
+
supportsVision: false,
|
|
1041
|
+
contextWindow: 131072,
|
|
1042
|
+
maxOutputTokens: 8192,
|
|
1043
|
+
patchFormat: 'search_replace',
|
|
1044
|
+
},
|
|
1045
|
+
{
|
|
1046
|
+
model: 'llama3.1:405b*',
|
|
1047
|
+
supportsReasoning: false,
|
|
1048
|
+
supportsToolCalls: true,
|
|
1049
|
+
supportsVision: false,
|
|
1050
|
+
contextWindow: 131072,
|
|
1051
|
+
maxOutputTokens: 8192,
|
|
1052
|
+
patchFormat: 'search_replace',
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
model: 'llama3.3*',
|
|
1056
|
+
supportsReasoning: false,
|
|
1057
|
+
supportsToolCalls: true,
|
|
1058
|
+
supportsVision: false,
|
|
1059
|
+
contextWindow: 131072,
|
|
1060
|
+
maxOutputTokens: 8192,
|
|
1061
|
+
patchFormat: 'search_replace',
|
|
1062
|
+
},
|
|
965
1063
|
{
|
|
966
1064
|
model: 'llama3*',
|
|
967
1065
|
supportsReasoning: false,
|
|
1066
|
+
// Explicitly split by size: 70b+ promoted above, 8b and below stay gated.
|
|
968
1067
|
supportsToolCalls: false,
|
|
969
1068
|
supportsVision: false,
|
|
970
1069
|
contextWindow: 8192,
|
|
@@ -1169,6 +1268,10 @@ export function resetRuntimeModelContextCache() {
|
|
|
1169
1268
|
export function findModelToolConfig(modelName, customConfigs) {
|
|
1170
1269
|
return findConfigMatch(modelName, [...(customConfigs || []), ...DEFAULT_MODEL_CONFIGS])?.config ?? null;
|
|
1171
1270
|
}
|
|
1271
|
+
/** Read-only view of the built-in table (consistency tests, e.g. P5 `codeExecEvidence`). */
|
|
1272
|
+
export function listDefaultModelToolConfigs() {
|
|
1273
|
+
return DEFAULT_MODEL_CONFIGS.map((config) => Object.freeze({ ...config }));
|
|
1274
|
+
}
|
|
1172
1275
|
export function getModelToolConfig(modelName, customConfigs) {
|
|
1173
1276
|
// Use cache for default config lookups (hot path)
|
|
1174
1277
|
if (!customConfigs && _configCache.has(modelName)) {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* - Content-type-aware Compression
|
|
13
13
|
* - Key Information Preservation
|
|
14
14
|
*/
|
|
15
|
+
import { truncateOutput } from '../utils/bounded-output.js';
|
|
15
16
|
import { createHash } from 'node:crypto';
|
|
16
17
|
import * as fs from 'fs';
|
|
17
18
|
import * as path from 'path';
|
|
@@ -703,8 +704,7 @@ export class ContextManagerV2 {
|
|
|
703
704
|
if (msg.content.length > MAX_TOOL_RESULT_LENGTH) {
|
|
704
705
|
return {
|
|
705
706
|
...msg,
|
|
706
|
-
content: msg.content
|
|
707
|
-
'\n... [truncated for context limits]',
|
|
707
|
+
content: truncateOutput(msg.content, MAX_TOOL_RESULT_LENGTH),
|
|
708
708
|
};
|
|
709
709
|
}
|
|
710
710
|
}
|
|
@@ -44,8 +44,9 @@ function stringArray(value) {
|
|
|
44
44
|
/** Resolve lm-resizer: explicit env -> stable install -> PATH -> mutable DEV build. */
|
|
45
45
|
export function resolveLmResizerBin() {
|
|
46
46
|
const env = process.env.CODEBUDDY_LM_RESIZER_BIN;
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// An explicit choice must not silently fall through to an older binary.
|
|
48
|
+
if (env?.trim())
|
|
49
|
+
return env.trim();
|
|
49
50
|
const stable = join(homedir(), '.local', 'bin', 'lm-resizer');
|
|
50
51
|
if (existsSync(stable))
|
|
51
52
|
return stable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Read-only host probe. Availability alone does not establish protocol support. */
|
|
2
|
+
export declare function diagnoseLmResizer(): Promise<{
|
|
3
|
+
binary: string;
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
available: boolean;
|
|
6
|
+
toolOutputSupported: boolean;
|
|
7
|
+
version: string;
|
|
8
|
+
warning: string;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { isLmResizerEnabled, resolveLmResizerBin } from './lm-resizer-compressor.js';
|
|
4
|
+
const run = promisify(execFile);
|
|
5
|
+
/** Read-only host probe. Availability alone does not establish protocol support. */
|
|
6
|
+
export async function diagnoseLmResizer() {
|
|
7
|
+
const binary = resolveLmResizerBin();
|
|
8
|
+
const result = { binary, enabled: isLmResizerEnabled(), available: false, toolOutputSupported: false, version: 'unknown', warning: '' };
|
|
9
|
+
const options = { timeout: 3000, maxBuffer: 64 * 1024, windowsHide: true };
|
|
10
|
+
try {
|
|
11
|
+
await run(binary, ['--help'], options);
|
|
12
|
+
result.available = true;
|
|
13
|
+
try {
|
|
14
|
+
result.version = (await run(binary, ['--version'], options)).stdout.trim();
|
|
15
|
+
}
|
|
16
|
+
catch { /* Older CLI has no version flag. */ }
|
|
17
|
+
try {
|
|
18
|
+
const probe = await run(binary, ['tool-output', '--help'], options);
|
|
19
|
+
result.toolOutputSupported = /tool-output/.test(probe.stdout);
|
|
20
|
+
}
|
|
21
|
+
catch { /* Old protocol: retain raw observations. */ }
|
|
22
|
+
if (!result.toolOutputSupported)
|
|
23
|
+
result.warning = 'This binary lacks the tool-output protocol. Buddy keeps raw observations; install a compatible release to enable observation compression.';
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
result.warning = 'LM Resizer is unavailable on the host. Buddy keeps raw observations.';
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=lm-resizer-diagnostics.js.map
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Inspired by Gemini CLI's toolOutputMaskingService.ts
|
|
10
10
|
*/
|
|
11
11
|
import { logger } from '../utils/logger.js';
|
|
12
|
+
import { truncateOutput } from '../utils/bounded-output.js';
|
|
12
13
|
/** Tokens worth of newest tool outputs to protect from masking */
|
|
13
14
|
const PROTECTION_THRESHOLD_CHARS = 200_000; // ~50K tokens * 4 chars/token
|
|
14
15
|
/** Only trigger masking if total prunable chars exceeds this */
|
|
@@ -41,14 +42,12 @@ function generatePreview(content) {
|
|
|
41
42
|
// Short enough — use char-based preview
|
|
42
43
|
if (content.length <= SHORT_PREVIEW_CHARS * 2)
|
|
43
44
|
return content;
|
|
44
|
-
return content
|
|
45
|
-
'\n...\n' +
|
|
46
|
-
content.substring(content.length - SHORT_PREVIEW_CHARS);
|
|
45
|
+
return truncateOutput(content, SHORT_PREVIEW_CHARS * 2);
|
|
47
46
|
}
|
|
48
47
|
const head = lines.slice(0, HEAD_PREVIEW_LINES).join('\n');
|
|
49
48
|
const tail = lines.slice(-TAIL_PREVIEW_LINES).join('\n');
|
|
50
49
|
const omitted = lines.length - HEAD_PREVIEW_LINES - TAIL_PREVIEW_LINES;
|
|
51
|
-
return `${head}\n\n... (${omitted} lines omitted) ...\n\n${tail}
|
|
50
|
+
return truncateOutput(`${head}\n\n... (${omitted} lines omitted) ...\n\n${tail}`, 4000);
|
|
52
51
|
}
|
|
53
52
|
/**
|
|
54
53
|
* Apply tool output masking to conversation messages.
|
|
@@ -63,6 +63,12 @@ export interface CuratorDeps {
|
|
|
63
63
|
}>>;
|
|
64
64
|
/** Ledger de performance modèles (défaut : ~/.codebuddy/fleet-model-performance.jsonl). */
|
|
65
65
|
modelLedgerPath?: string;
|
|
66
|
+
/** Activité des skills (défaut : readSkillActivity(), journal ~/.codebuddy/skill-usage). */
|
|
67
|
+
skillActivity?: () => Map<string, {
|
|
68
|
+
lastActivityAt: string;
|
|
69
|
+
}>;
|
|
70
|
+
/** Skills référencées par une tâche planifiée (défaut : jobs.json du scheduler cron). */
|
|
71
|
+
scheduledSkills?: () => Promise<Set<string>>;
|
|
66
72
|
}
|
|
67
73
|
export declare function runCuratorScan(cwd?: string, deps?: CuratorDeps): Promise<CuratorReport>;
|
|
68
74
|
/**
|
package/dist/curator/curator.js
CHANGED
|
@@ -81,6 +81,23 @@ async function scanAuthoredSkills(deps, cwd, now) {
|
|
|
81
81
|
const patches = [];
|
|
82
82
|
let authored = 0;
|
|
83
83
|
let pinned = 0;
|
|
84
|
+
let scheduled = 0;
|
|
85
|
+
let activity = new Map();
|
|
86
|
+
try {
|
|
87
|
+
activity = deps.skillActivity
|
|
88
|
+
? deps.skillActivity()
|
|
89
|
+
: (await import('../skills/skill-usage-store.js')).readSkillActivity();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Télémétrie absente : repli sur la date de modification.
|
|
93
|
+
}
|
|
94
|
+
let scheduledSkills = new Set();
|
|
95
|
+
try {
|
|
96
|
+
scheduledSkills = deps.scheduledSkills ? await deps.scheduledSkills() : await readScheduledSkillNames();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Pas de scheduler lisible : aucune protection supplémentaire.
|
|
100
|
+
}
|
|
84
101
|
let entries = [];
|
|
85
102
|
try {
|
|
86
103
|
entries = await fs.readdir(skillsDir);
|
|
@@ -103,12 +120,22 @@ async function scanAuthoredSkills(deps, cwd, now) {
|
|
|
103
120
|
pinned++;
|
|
104
121
|
continue; // une skill épinglée n'est jamais proposée
|
|
105
122
|
}
|
|
106
|
-
|
|
123
|
+
if (scheduledSkills.has(entry)) {
|
|
124
|
+
scheduled++;
|
|
125
|
+
continue; // utilisée par une tâche planifiée : jamais dormante
|
|
126
|
+
}
|
|
127
|
+
// Ancre = dernière activité (vue/usage) ou dernière modification, la plus récente.
|
|
128
|
+
const lastActivity = Date.parse(activity.get(entry)?.lastActivityAt ?? '');
|
|
129
|
+
const anchor = Math.max(stat.mtime.getTime(), Number.isFinite(lastActivity) ? lastActivity : 0);
|
|
130
|
+
const ageDays = (now.getTime() - anchor) / DAY_MS;
|
|
107
131
|
if (ageDays >= STALE_SKILL_DAYS) {
|
|
132
|
+
const usedBefore = Number.isFinite(lastActivity);
|
|
108
133
|
patches.push({
|
|
109
134
|
kind: 'REVIEW_SKILL',
|
|
110
135
|
target: entry,
|
|
111
|
-
reason:
|
|
136
|
+
reason: usedBefore
|
|
137
|
+
? `aucune activité ni modification depuis ${Math.round(ageDays)}j, non épinglée`
|
|
138
|
+
: `jamais utilisée et non modifiée depuis ${Math.round(ageDays)}j, non épinglée`,
|
|
112
139
|
autoAppliable: false, // juger l'utilité d'une skill = décision humaine
|
|
113
140
|
howToApply: `buddy improve skills-pin ${entry} (garder) ou buddy improve skills-consolidate (fusionner/archiver)`,
|
|
114
141
|
});
|
|
@@ -122,11 +149,34 @@ async function scanAuthoredSkills(deps, cwd, now) {
|
|
|
122
149
|
section: {
|
|
123
150
|
name: 'Skills authored',
|
|
124
151
|
ok: true,
|
|
125
|
-
summary: `${authored} authored (${pinned} épinglée(s)), ${patches.length} dormante(s) ≥ ${STALE_SKILL_DAYS}j à réviser`,
|
|
152
|
+
summary: `${authored} authored (${pinned} épinglée(s), ${scheduled} planifiée(s)), ${patches.length} dormante(s) ≥ ${STALE_SKILL_DAYS}j sans activité à réviser`,
|
|
126
153
|
},
|
|
127
154
|
patches,
|
|
128
155
|
};
|
|
129
156
|
}
|
|
157
|
+
/** Noms de skills référencées par une tâche cron `skill` (lecture seule de jobs.json). */
|
|
158
|
+
async function readScheduledSkillNames() {
|
|
159
|
+
const root = process.env.CODEBUDDY_CRON_HOME
|
|
160
|
+
? path.resolve(process.env.CODEBUDDY_CRON_HOME)
|
|
161
|
+
: path.join(os.homedir(), '.codebuddy', 'cron');
|
|
162
|
+
const names = new Set();
|
|
163
|
+
let raw = '';
|
|
164
|
+
try {
|
|
165
|
+
raw = await fs.readFile(path.join(root, 'jobs.json'), 'utf-8');
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return names;
|
|
169
|
+
}
|
|
170
|
+
const jobs = JSON.parse(raw);
|
|
171
|
+
if (!Array.isArray(jobs))
|
|
172
|
+
return names;
|
|
173
|
+
for (const job of jobs) {
|
|
174
|
+
const task = job?.task;
|
|
175
|
+
if (task?.type === 'skill' && typeof task.skill === 'string' && task.skill.trim())
|
|
176
|
+
names.add(task.skill.trim());
|
|
177
|
+
}
|
|
178
|
+
return names;
|
|
179
|
+
}
|
|
130
180
|
async function scanCkg(deps) {
|
|
131
181
|
const getStats = deps.ckgStats ??
|
|
132
182
|
(async () => {
|
|
@@ -25,6 +25,11 @@ export interface BridgeConfig {
|
|
|
25
25
|
* Left undefined, the bridge behaves exactly as before (no run records).
|
|
26
26
|
*/
|
|
27
27
|
runStore?: RunStore;
|
|
28
|
+
/**
|
|
29
|
+
* Directory of per-job notepad files. Defaults to `$CODEBUDDY_CRON_HOME/notepads`
|
|
30
|
+
* (or `~/.codebuddy/cron/notepads`). Isolated from jobs.json.
|
|
31
|
+
*/
|
|
32
|
+
notepadDir?: string;
|
|
28
33
|
}
|
|
29
34
|
export interface JobExecutionResult {
|
|
30
35
|
jobId: string;
|
|
@@ -50,6 +55,7 @@ export interface JobExecutionResult {
|
|
|
50
55
|
export declare class CronAgentBridge extends EventEmitter {
|
|
51
56
|
private config;
|
|
52
57
|
private activeJobs;
|
|
58
|
+
private notepad;
|
|
53
59
|
constructor(config: BridgeConfig);
|
|
54
60
|
/**
|
|
55
61
|
* Create a task executor function for the CronScheduler
|
|
@@ -10,6 +10,7 @@ import { executeHermesLifecycleHook } from '../hooks/hermes-lifecycle-hooks.js';
|
|
|
10
10
|
import { evaluateCronPreCheck } from '../scheduler/pre-check-runner.js';
|
|
11
11
|
import { runWatchdog } from '../scheduler/watchdog-handlers.js';
|
|
12
12
|
import { collectDeliveryTargets, resolveDeliveryBody } from '../scheduler/scheduled-delivery.js';
|
|
13
|
+
import { JobNotepadStore, defaultNotepadDir, isContinuityEnabled, } from '../scheduler/job-notepad.js';
|
|
13
14
|
const DEFAULT_BRIDGE_CONFIG = {
|
|
14
15
|
maxToolRounds: 20,
|
|
15
16
|
jobTimeoutMs: 300000, // 5 minutes
|
|
@@ -20,9 +21,11 @@ const DEFAULT_BRIDGE_CONFIG = {
|
|
|
20
21
|
export class CronAgentBridge extends EventEmitter {
|
|
21
22
|
config;
|
|
22
23
|
activeJobs = new Map();
|
|
24
|
+
notepad;
|
|
23
25
|
constructor(config) {
|
|
24
26
|
super();
|
|
25
27
|
this.config = { ...DEFAULT_BRIDGE_CONFIG, ...config };
|
|
28
|
+
this.notepad = new JobNotepadStore(config.notepadDir ?? defaultNotepadDir());
|
|
26
29
|
}
|
|
27
30
|
/**
|
|
28
31
|
* Create a task executor function for the CronScheduler
|
|
@@ -44,11 +47,13 @@ export class CronAgentBridge extends EventEmitter {
|
|
|
44
47
|
try {
|
|
45
48
|
// Pre-check gate: skip expensive LLM work when nothing changed.
|
|
46
49
|
// Watchdog jobs are non-LLM monitors, so they bypass the pre-check.
|
|
50
|
+
// Fingerprint is applied only after a skip or a successful task — a
|
|
51
|
+
// failed run must leave lastFingerprint alone so an unchanged source retries.
|
|
52
|
+
let pendingFingerprint;
|
|
47
53
|
if (job.preCheck && job.task.type !== 'watchdog') {
|
|
48
54
|
const preCheckResult = await evaluateCronPreCheck(job.preCheck);
|
|
49
55
|
if (typeof preCheckResult.fingerprint === 'string') {
|
|
50
|
-
|
|
51
|
-
job.preCheck.lastFingerprint = preCheckResult.fingerprint;
|
|
56
|
+
pendingFingerprint = preCheckResult.fingerprint;
|
|
52
57
|
}
|
|
53
58
|
this.emit('job:precheck', {
|
|
54
59
|
jobId: job.id,
|
|
@@ -57,6 +62,9 @@ export class CronAgentBridge extends EventEmitter {
|
|
|
57
62
|
evidence: preCheckResult.evidence,
|
|
58
63
|
});
|
|
59
64
|
if (!preCheckResult.shouldRun) {
|
|
65
|
+
if (pendingFingerprint !== undefined) {
|
|
66
|
+
job.preCheck.lastFingerprint = pendingFingerprint;
|
|
67
|
+
}
|
|
60
68
|
const duration = Date.now() - startTime;
|
|
61
69
|
const skipOutput = `Skipped by pre-check: ${preCheckResult.reason}`;
|
|
62
70
|
this.recordRunEvent(recordedRunId, 'decision', {
|
|
@@ -139,6 +147,17 @@ export class CronAgentBridge extends EventEmitter {
|
|
|
139
147
|
// data channel, capped at 64KB in the script runner). For all other
|
|
140
148
|
// task types, the full output serves as outputData.
|
|
141
149
|
const outputData = job.task.type === 'script' ? scriptStdout : output;
|
|
150
|
+
if (pendingFingerprint !== undefined && job.preCheck) {
|
|
151
|
+
job.preCheck.lastFingerprint = pendingFingerprint;
|
|
152
|
+
}
|
|
153
|
+
if (isContinuityEnabled(job.continuity)) {
|
|
154
|
+
try {
|
|
155
|
+
await this.notepad.saveLastSuccessfulOutput(job.id, outputData ?? output);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
logger.warn('Cron task succeeded but its continuity output could not be saved', { jobId: job.id, error: String(err) });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
142
161
|
const result = {
|
|
143
162
|
jobId: job.id,
|
|
144
163
|
runId: recordedRunId ?? `run-${Date.now()}`,
|
|
@@ -253,10 +272,18 @@ export class CronAgentBridge extends EventEmitter {
|
|
|
253
272
|
logger.debug(`Cron job ${job.id}: could not load session ${job.resolvedSessionId}, starting fresh`);
|
|
254
273
|
}
|
|
255
274
|
}
|
|
256
|
-
// Prepend inputData from parent chained job if available
|
|
257
275
|
let message = job.task.message;
|
|
276
|
+
const prefixes = [];
|
|
277
|
+
if (isContinuityEnabled(job.continuity)) {
|
|
278
|
+
const section = await this.notepad.renderSection(job.id);
|
|
279
|
+
if (section)
|
|
280
|
+
prefixes.push(section.trimEnd());
|
|
281
|
+
}
|
|
258
282
|
if (inputData) {
|
|
259
|
-
|
|
283
|
+
prefixes.push(`[Chained job context — output from parent job]:\n${inputData}`);
|
|
284
|
+
}
|
|
285
|
+
if (prefixes.length > 0) {
|
|
286
|
+
message = `${prefixes.join('\n\n')}\n\n[Task]:\n${message}`;
|
|
260
287
|
}
|
|
261
288
|
const entries = await agent.processUserMessage(message);
|
|
262
289
|
const assistantEntries = entries.filter(e => e.type === 'assistant');
|
package/dist/doctor/index.d.ts
CHANGED
|
@@ -32,7 +32,10 @@ export interface DoctorSummary {
|
|
|
32
32
|
* so `doctor` on a fresh machine reports 0 warnings for missing optional tools.
|
|
33
33
|
*/
|
|
34
34
|
export declare function summarizeDoctorChecks(checks: DoctorCheck[]): DoctorSummary;
|
|
35
|
-
|
|
35
|
+
/** PATH lookup without a child process (used by `buddy triage`). */
|
|
36
|
+
export declare function commandExistsOnPath(cmd: string, env?: NodeJS.ProcessEnv): boolean;
|
|
37
|
+
type CommandLookup = (cmd: string) => boolean;
|
|
38
|
+
export declare function checkTtsProviders(lookup?: CommandLookup): DoctorCheck[];
|
|
36
39
|
/**
|
|
37
40
|
* Check the server configuration derived from environment/defaults. Explicit
|
|
38
41
|
* CLI flags are diagnosed again from the effective config when the server
|
|
@@ -47,5 +50,11 @@ export type { OllamaModelCandidate } from '../wizard/environment-detection.js';
|
|
|
47
50
|
export declare function resolveOllamaModel(models: readonly string[], settings?: OllamaSelectionSettings): string | undefined;
|
|
48
51
|
/** Both persisted model fields must point at a model currently served by Ollama. */
|
|
49
52
|
export declare function isOllamaSelectionCurrent(models: readonly string[], settings?: OllamaSelectionSettings): boolean;
|
|
50
|
-
export
|
|
53
|
+
export interface DoctorRunOptions {
|
|
54
|
+
/** Skip every network call: live key validation, OAuth refresh/discovery, local runtime probes. */
|
|
55
|
+
offline?: boolean;
|
|
56
|
+
/** Never start a child process: PATH/.git filesystem lookups, sandbox probe skipped (`buddy triage`). */
|
|
57
|
+
noSubprocess?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare function runDoctorChecks(cwd?: string, options?: DoctorRunOptions): Promise<DoctorCheck[]>;
|
|
51
60
|
export declare function runFixes(checks: DoctorCheck[]): Promise<FixResult[]>;
|
package/dist/doctor/index.js
CHANGED
|
@@ -43,8 +43,34 @@ function commandExists(cmd) {
|
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
/** PATH lookup without a child process (used by `buddy triage`). */
|
|
47
|
+
export function commandExistsOnPath(cmd, env = process.env) {
|
|
48
|
+
const executable = (file) => {
|
|
49
|
+
try {
|
|
50
|
+
if (!statSync(file).isFile())
|
|
51
|
+
return false;
|
|
52
|
+
accessSync(file, fsConstants.X_OK);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
if (cmd.includes('/') || cmd.includes('\\'))
|
|
60
|
+
return executable(cmd);
|
|
61
|
+
const extensions = process.platform === 'win32'
|
|
62
|
+
? ['', ...(env.PATHEXT ?? '.EXE;.CMD;.BAT;.COM').split(';').filter(Boolean)]
|
|
63
|
+
: [''];
|
|
64
|
+
for (const dir of (env.PATH ?? env.Path ?? '').split(process.platform === 'win32' ? ';' : ':')) {
|
|
65
|
+
if (!dir)
|
|
66
|
+
continue;
|
|
67
|
+
if (extensions.some((ext) => executable(join(dir, cmd + ext))))
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
function getCommandAvailability(cmd, lookup = commandExists) {
|
|
73
|
+
return lookup(cmd) ? 'installed' : 'not found';
|
|
48
74
|
}
|
|
49
75
|
function checkNodeVersion() {
|
|
50
76
|
const major = parseInt(process.version.slice(1), 10);
|
|
@@ -79,7 +105,7 @@ async function checkNativeSqlite() {
|
|
|
79
105
|
};
|
|
80
106
|
}
|
|
81
107
|
}
|
|
82
|
-
function checkDependencies() {
|
|
108
|
+
function checkDependencies(lookup = commandExists) {
|
|
83
109
|
const checks = [];
|
|
84
110
|
// Optionality is INTRINSIC to the tool, never derived from whether it is
|
|
85
111
|
// installed: deriving `optional: !installed` would silently reclassify ANY
|
|
@@ -131,7 +157,7 @@ function checkDependencies() {
|
|
|
131
157
|
},
|
|
132
158
|
];
|
|
133
159
|
for (const dep of externalTools) {
|
|
134
|
-
const installed = getCommandAvailability(dep.cmd) === 'installed';
|
|
160
|
+
const installed = getCommandAvailability(dep.cmd, lookup) === 'installed';
|
|
135
161
|
checks.push({
|
|
136
162
|
name: dep.label,
|
|
137
163
|
status: installed ? 'ok' : dep.level,
|
|
@@ -140,7 +166,7 @@ function checkDependencies() {
|
|
|
140
166
|
});
|
|
141
167
|
}
|
|
142
168
|
const audioPlayers = ['ffplay', 'aplay', 'mpv'];
|
|
143
|
-
const found = audioPlayers.filter(cmd =>
|
|
169
|
+
const found = audioPlayers.filter(cmd => lookup(cmd));
|
|
144
170
|
checks.push({
|
|
145
171
|
name: 'Audio playback',
|
|
146
172
|
status: found.length > 0 ? 'ok' : 'warn',
|
|
@@ -171,7 +197,7 @@ function checkApiKeys() {
|
|
|
171
197
|
* credentials present (user might be using API keys instead — non-fatal).
|
|
172
198
|
* `error` only when the file is corrupt or refresh fails.
|
|
173
199
|
*/
|
|
174
|
-
async function checkChatGptOAuth() {
|
|
200
|
+
async function checkChatGptOAuth(offline = false) {
|
|
175
201
|
try {
|
|
176
202
|
const { hasCodexCredentials, getChatGptAuth, getCodexAuthFilePath } = await import('../providers/codex-oauth.js');
|
|
177
203
|
if (!hasCodexCredentials()) {
|
|
@@ -181,6 +207,14 @@ async function checkChatGptOAuth() {
|
|
|
181
207
|
message: `not signed in (run \`buddy login\` to use your ChatGPT subscription) — file: ${getCodexAuthFilePath()}`,
|
|
182
208
|
};
|
|
183
209
|
}
|
|
210
|
+
if (offline) {
|
|
211
|
+
// getChatGptAuth() may refresh (network + token rotation): never offline.
|
|
212
|
+
return {
|
|
213
|
+
name: 'ChatGPT OAuth',
|
|
214
|
+
status: 'ok',
|
|
215
|
+
message: 'credential file present (token refresh and model discovery skipped: --offline)',
|
|
216
|
+
};
|
|
217
|
+
}
|
|
184
218
|
const auth = await getChatGptAuth();
|
|
185
219
|
if (!auth) {
|
|
186
220
|
return {
|
|
@@ -283,8 +317,8 @@ function checkStaleLockFiles(cwd) {
|
|
|
283
317
|
}
|
|
284
318
|
return checks;
|
|
285
319
|
}
|
|
286
|
-
export function checkTtsProviders() {
|
|
287
|
-
const pocketLauncher = ['pocket-tts', 'uvx'].find((command) =>
|
|
320
|
+
export function checkTtsProviders(lookup = commandExists) {
|
|
321
|
+
const pocketLauncher = ['pocket-tts', 'uvx'].find((command) => lookup(command));
|
|
288
322
|
const available = [];
|
|
289
323
|
if (pocketLauncher)
|
|
290
324
|
available.push(`Pocket TTS (via ${pocketLauncher})`);
|
|
@@ -377,7 +411,10 @@ function checkProfilePermissions() {
|
|
|
377
411
|
message: `${dir} writable (mode ${mode.toString(8)})`,
|
|
378
412
|
};
|
|
379
413
|
}
|
|
380
|
-
function checkNativeSandbox() {
|
|
414
|
+
function checkNativeSandbox(noSubprocess = false) {
|
|
415
|
+
if (noSubprocess) {
|
|
416
|
+
return { name: 'Native sandbox (kernel)', status: 'ok', message: 'not probed (no child process in this mode); run `buddy doctor` to probe bwrap/Landlock', optional: true };
|
|
417
|
+
}
|
|
381
418
|
const caps = detectNativeSandboxCapabilities();
|
|
382
419
|
return {
|
|
383
420
|
name: 'Native sandbox (kernel)',
|
|
@@ -386,10 +423,26 @@ function checkNativeSandbox() {
|
|
|
386
423
|
optional: true,
|
|
387
424
|
};
|
|
388
425
|
}
|
|
389
|
-
function
|
|
390
|
-
|
|
426
|
+
function insideGitWorkTree(cwd) {
|
|
427
|
+
let dir = cwd;
|
|
428
|
+
for (;;) {
|
|
429
|
+
if (existsSync(join(dir, '.git')))
|
|
430
|
+
return true;
|
|
431
|
+
const parent = join(dir, '..');
|
|
432
|
+
if (parent === dir)
|
|
433
|
+
return false;
|
|
434
|
+
dir = parent;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function checkGit(cwd, noSubprocess = false) {
|
|
438
|
+
if (!(noSubprocess ? commandExistsOnPath('git') : commandExists('git'))) {
|
|
391
439
|
return { name: 'Git', status: 'error', message: 'git not found' };
|
|
392
440
|
}
|
|
441
|
+
if (noSubprocess) {
|
|
442
|
+
return insideGitWorkTree(cwd)
|
|
443
|
+
? { name: 'Git', status: 'ok', message: 'installed, inside a git repo (.git found)' }
|
|
444
|
+
: { name: 'Git', status: 'warn', message: 'installed, but not inside a git repo (no .git found)' };
|
|
445
|
+
}
|
|
393
446
|
try {
|
|
394
447
|
execSync('git rev-parse --is-inside-work-tree', { cwd, stdio: 'ignore' });
|
|
395
448
|
return { name: 'Git', status: 'ok', message: 'installed, inside a git repo' };
|
|
@@ -605,9 +658,9 @@ export function isOllamaSelectionCurrent(models, settings = {}) {
|
|
|
605
658
|
* it" (env var / onboarded settings / OAuth / API key), because a running
|
|
606
659
|
* Ollama that was never selected still dead-ends the first chat.
|
|
607
660
|
*/
|
|
608
|
-
async function checkProviderReadiness() {
|
|
661
|
+
async function checkProviderReadiness(offline = false) {
|
|
609
662
|
const { detectEnvironment } = await import('../wizard/environment-detection.js');
|
|
610
|
-
const snap = await detectEnvironment();
|
|
663
|
+
const snap = await detectEnvironment({ offline });
|
|
611
664
|
const oauthOrKey = snap.capabilities.some((c) => c.available && (c.kind === 'oauth' || c.kind === 'api-key'));
|
|
612
665
|
const ollama = snap.capabilities.find((c) => c.id === 'ollama');
|
|
613
666
|
const ollamaModels = ollama?.models?.length ?? 0;
|
|
@@ -651,6 +704,13 @@ async function checkProviderReadiness() {
|
|
|
651
704
|
};
|
|
652
705
|
}
|
|
653
706
|
const configured = oauthOrKey || ((envLocal || onboardedLocal) && ollamaModels > 0);
|
|
707
|
+
if (offline && !configured && (envLocal || onboardedLocal)) {
|
|
708
|
+
return {
|
|
709
|
+
name: 'AI provider ready',
|
|
710
|
+
status: 'warn',
|
|
711
|
+
message: `local ${p || 'runtime'} configured but not probed (--offline); run \`buddy doctor\` without --offline to verify it`,
|
|
712
|
+
};
|
|
713
|
+
}
|
|
654
714
|
if (configured) {
|
|
655
715
|
const rec = snap.recommended;
|
|
656
716
|
return {
|
|
@@ -737,30 +797,33 @@ function checkProviderFailoverHealth() {
|
|
|
737
797
|
message: lines.slice(1).join('; ') || `${down.length} provider(s) benched`,
|
|
738
798
|
};
|
|
739
799
|
}
|
|
740
|
-
export async function runDoctorChecks(cwd) {
|
|
800
|
+
export async function runDoctorChecks(cwd, options = {}) {
|
|
741
801
|
const dir = cwd ?? process.cwd();
|
|
802
|
+
const offline = options.offline === true;
|
|
803
|
+
const noSubprocess = options.noSubprocess === true;
|
|
804
|
+
const lookup = noSubprocess ? (cmd) => commandExistsOnPath(cmd) : commandExists;
|
|
742
805
|
const { checkLlmKeysLive } = await import('./llm-key-check.js');
|
|
743
806
|
return [
|
|
744
|
-
await checkProviderReadiness(),
|
|
807
|
+
await checkProviderReadiness(offline),
|
|
745
808
|
checkNodeVersion(),
|
|
746
809
|
await checkNativeSqlite(),
|
|
747
|
-
...checkDependencies(),
|
|
810
|
+
...checkDependencies(lookup),
|
|
748
811
|
...checkApiKeys(),
|
|
749
812
|
// Validation LIVE des clés configurées (endpoint /models, 0 token) :
|
|
750
813
|
// distingue clé invalide (401/403 → error) de quota épuisé (429 → warn).
|
|
751
|
-
...(await checkLlmKeysLive()),
|
|
752
|
-
await checkChatGptOAuth(),
|
|
814
|
+
...(offline ? [] : await checkLlmKeysLive()),
|
|
815
|
+
await checkChatGptOAuth(offline),
|
|
753
816
|
...checkConfigFiles(dir),
|
|
754
817
|
// Accidents de collage dans .env (commande shell, guillemets, doublons) —
|
|
755
818
|
// détectés sans jamais afficher les valeurs. src/doctor/env-sanity.ts.
|
|
756
819
|
...(await import('./env-sanity.js')).checkEnvSanity(dir),
|
|
757
820
|
...checkStaleLockFiles(dir),
|
|
758
|
-
...checkTtsProviders(),
|
|
821
|
+
...checkTtsProviders(lookup),
|
|
759
822
|
checkServerExposureEnvironment(),
|
|
760
823
|
checkProfilePermissions(),
|
|
761
824
|
checkDiskSpace(dir),
|
|
762
|
-
checkGit(dir),
|
|
763
|
-
checkNativeSandbox(),
|
|
825
|
+
checkGit(dir, noSubprocess),
|
|
826
|
+
checkNativeSandbox(noSubprocess),
|
|
764
827
|
checkProviderFailoverHealth(),
|
|
765
828
|
];
|
|
766
829
|
}
|