@phuetz/code-buddy 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.fr.md +56 -0
- package/README.md +73 -16
- package/codebuddy-runtime.json +5 -5
- package/dist/agent/codebuddy-agent.d.ts +18 -0
- package/dist/agent/codebuddy-agent.js +45 -8
- package/dist/agent/execution/agent-executor.d.ts +0 -9
- package/dist/agent/execution/agent-executor.js +165 -12
- package/dist/agent/execution/context-pipeline.d.ts +9 -0
- package/dist/agent/execution/context-pipeline.js +64 -2
- package/dist/agent/execution/tool-loop-guard.d.ts +76 -0
- package/dist/agent/execution/tool-loop-guard.js +165 -0
- package/dist/agent/execution/tool-selection-strategy.js +19 -2
- package/dist/agent/facades/session-facade.d.ts +0 -6
- package/dist/agent/facades/session-facade.js +0 -45
- package/dist/agent/hermes-claw-migrate.d.ts +0 -21
- package/dist/agent/hermes-claw-migrate.js +9 -4
- package/dist/agent/hermes-protocol-gateways.js +8 -1
- package/dist/agent/repo-profiler.js +17 -4
- package/dist/agent/self-improvement/authored-tool-runtime.js +10 -2
- package/dist/agent/self-improvement/evolution/ast-novelty.d.ts +5 -0
- package/dist/agent/self-improvement/evolution/ast-novelty.js +58 -23
- package/dist/agent/self-improvement/evolution/code-variant-store.d.ts +3 -0
- package/dist/agent/self-improvement/evolution/evolution-engine.js +2 -0
- package/dist/agent/self-improvement/evolution/protected-paths.js +6 -0
- package/dist/agent/self-improvement/evolution/variant-fitness.d.ts +13 -2
- package/dist/agent/self-improvement/evolution/variant-fitness.js +184 -58
- package/dist/agent/self-improvement/evolution/worktree-scorer.d.ts +2 -0
- package/dist/agent/self-improvement/evolution/worktree-scorer.js +15 -0
- package/dist/agent/self-improvement/evolutionary-archive.d.ts +2 -1
- package/dist/agent/self-improvement/evolutionary-archive.js +34 -5
- package/dist/agent/self-improvement/proposal-store.d.ts +1 -0
- package/dist/agent/self-improvement/proposal-store.js +79 -17
- package/dist/agent/self-improvement/skill-apply-journal.d.ts +44 -0
- package/dist/agent/self-improvement/skill-apply-journal.js +178 -0
- package/dist/agent/self-improvement/skill-behavior-benchmark.d.ts +3 -0
- package/dist/agent/self-improvement/skill-behavior-benchmark.js +19 -0
- package/dist/agent/self-improvement/skill-behavior-gate.d.ts +34 -0
- package/dist/agent/self-improvement/skill-behavior-gate.js +96 -0
- package/dist/agent/self-improvement/skill-engine.d.ts +22 -0
- package/dist/agent/self-improvement/skill-engine.js +385 -13
- package/dist/agent/self-improvement/skill-gate.d.ts +2 -0
- package/dist/agent/self-improvement/skill-gate.js +17 -2
- package/dist/agent/self-improvement/skill-mutator.d.ts +6 -1
- package/dist/agent/self-improvement/skill-mutator.js +51 -15
- package/dist/agent/self-improvement/skill-types.d.ts +2 -1
- package/dist/agent/self-improvement/types.d.ts +11 -0
- package/dist/agent/tool-handler.d.ts +1 -1
- package/dist/agent/tool-handler.js +28 -9
- package/dist/auth/profile-manager.js +1 -1
- package/dist/channels/companion-channel-turn.d.ts +53 -4
- package/dist/channels/companion-channel-turn.js +218 -16
- package/dist/channels/slash-parity.d.ts +4 -6
- package/dist/channels/slash-parity.js +9 -44
- package/dist/cli/session-commands.d.ts +9 -0
- package/dist/cli/session-commands.js +45 -5
- package/dist/cli/session-picker.d.ts +43 -0
- package/dist/cli/session-picker.js +128 -0
- package/dist/codebuddy/a2a-call-tool-defs.d.ts +26 -0
- package/dist/codebuddy/a2a-call-tool-defs.js +12 -0
- package/dist/codebuddy/fleet-tool-defs.d.ts +1 -0
- package/dist/codebuddy/fleet-tool-defs.js +24 -0
- package/dist/codebuddy/providers/chatgpt-headers.d.ts +18 -0
- package/dist/codebuddy/providers/chatgpt-headers.js +37 -0
- package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +2 -1
- package/dist/codebuddy/providers/provider-chatgpt-responses.js +10 -23
- package/dist/codebuddy/providers/provider-openai-compat.js +1 -1
- package/dist/codebuddy/ragchat-tool-defs.d.ts +31 -0
- package/dist/codebuddy/ragchat-tool-defs.js +19 -0
- package/dist/codebuddy/resource-catalog-tool-defs.d.ts +28 -0
- package/dist/codebuddy/resource-catalog-tool-defs.js +18 -0
- package/dist/codebuddy/tool-definitions/agent-tools.js +2 -2
- package/dist/codebuddy/tool-definitions/code-exec-tools.js +5 -1
- package/dist/codebuddy/tool-definitions/cron-tools.js +6 -0
- package/dist/codebuddy/tool-definitions/self-describe-tools.js +6 -1
- package/dist/codebuddy/tools.d.ts +0 -6
- package/dist/codebuddy/tools.js +25 -3
- package/dist/commands/cli/daemon-commands.js +3 -1
- package/dist/commands/cli/evolve-command.js +21 -5
- package/dist/commands/cli/fleet-collaboration-commands.d.ts +2 -0
- package/dist/commands/cli/fleet-collaboration-commands.js +57 -0
- package/dist/commands/cli/fleet-commands.js +29 -0
- package/dist/commands/cli/fleet-mission-commands.d.ts +3 -0
- package/dist/commands/cli/fleet-mission-commands.js +72 -0
- package/dist/commands/cli/fleet-rooms-commands.d.ts +10 -0
- package/dist/commands/cli/fleet-rooms-commands.js +289 -0
- package/dist/commands/cli/tools-commands.js +2 -1
- package/dist/commands/cli/triage-command.d.ts +8 -0
- package/dist/commands/cli/triage-command.js +72 -0
- package/dist/commands/cli/utility-commands.js +25 -1
- package/dist/commands/client-dispatcher.d.ts +7 -0
- package/dist/commands/client-dispatcher.js +73 -21
- package/dist/commands/cron-cli/index.d.ts +3 -1
- package/dist/commands/cron-cli/index.js +25 -0
- package/dist/commands/device-auth.d.ts +10 -0
- package/dist/commands/device-auth.js +91 -0
- package/dist/commands/enhanced-command-handler.d.ts +9 -0
- package/dist/commands/enhanced-command-handler.js +28 -6
- package/dist/commands/handlers/agent-handlers.d.ts +1 -1
- package/dist/commands/handlers/agent-handlers.js +4 -4
- package/dist/commands/handlers/channel-handlers.js +53 -2
- package/dist/commands/handlers/export-handlers.d.ts +3 -2
- package/dist/commands/handlers/export-handlers.js +55 -28
- package/dist/commands/handlers/extra-handlers.js +5 -1
- package/dist/commands/handlers/grill-me-handler.js +26 -18
- package/dist/commands/handlers/memory-handlers.d.ts +6 -2
- package/dist/commands/handlers/memory-handlers.js +35 -15
- package/dist/commands/handlers/missing-handlers.d.ts +2 -2
- package/dist/commands/handlers/missing-handlers.js +4 -4
- package/dist/commands/handlers/resources-handler.d.ts +12 -0
- package/dist/commands/handlers/resources-handler.js +52 -0
- package/dist/commands/handlers/starter-handlers.d.ts +1 -1
- package/dist/commands/handlers/starter-handlers.js +32 -2
- package/dist/commands/handlers/switch-handler.d.ts +1 -1
- package/dist/commands/handlers/switch-handler.js +15 -0
- package/dist/commands/handlers/test-handlers.js +4 -86
- package/dist/commands/handlers/ui-handlers.js +11 -5
- package/dist/commands/login-chatgpt.d.ts +8 -0
- package/dist/commands/login-chatgpt.js +17 -0
- package/dist/commands/mcp-import.d.ts +11 -0
- package/dist/commands/mcp-import.js +67 -0
- package/dist/commands/mcp-invoke.d.ts +2 -0
- package/dist/commands/mcp-invoke.js +68 -0
- package/dist/commands/mcp.js +4 -0
- package/dist/commands/pipeline.d.ts +7 -1
- package/dist/commands/pipeline.js +104 -7
- package/dist/commands/resources.d.ts +2 -0
- package/dist/commands/resources.js +64 -0
- package/dist/commands/skills-cli/index.js +35 -12
- package/dist/commands/slash/builtin-commands.js +16 -3
- package/dist/commands/slash/index.d.ts +3 -1
- package/dist/commands/slash/index.js +2 -0
- package/dist/commands/slash/surfaces.d.ts +53 -0
- package/dist/commands/slash/surfaces.js +177 -0
- package/dist/commands/slash/types.d.ts +17 -0
- package/dist/commands/try.d.ts +1 -1
- package/dist/commands/try.js +1 -1
- package/dist/companion/companion-identity.d.ts +43 -0
- package/dist/companion/companion-identity.js +136 -0
- package/dist/companion/companion-toolset.d.ts +66 -0
- package/dist/companion/companion-toolset.js +368 -0
- package/dist/companion/companion-turn.d.ts +10 -2
- package/dist/companion/companion-turn.js +38 -1
- package/dist/config/code-exec-policy.d.ts +25 -0
- package/dist/config/code-exec-policy.js +39 -0
- package/dist/config/model-tools.d.ts +9 -0
- package/dist/config/model-tools.js +4 -0
- package/dist/context/context-manager-v2.js +2 -2
- package/dist/context/lm-resizer-compressor.js +3 -2
- package/dist/context/lm-resizer-diagnostics.d.ts +9 -0
- package/dist/context/lm-resizer-diagnostics.js +30 -0
- package/dist/context/tool-output-masking.js +3 -4
- package/dist/curator/curator.d.ts +6 -0
- package/dist/curator/curator.js +53 -3
- package/dist/daemon/cron-agent-bridge.d.ts +6 -0
- package/dist/daemon/cron-agent-bridge.js +31 -4
- package/dist/doctor/index.d.ts +11 -2
- package/dist/doctor/index.js +84 -21
- package/dist/doctor/integrations.d.ts +179 -0
- package/dist/doctor/integrations.js +227 -0
- package/dist/doctor/triage.d.ts +108 -0
- package/dist/doctor/triage.js +304 -0
- package/dist/fleet/collaboration.d.ts +44 -0
- package/dist/fleet/collaboration.js +170 -0
- package/dist/fleet/fleet-listener.d.ts +1 -0
- package/dist/fleet/fleet-listener.js +87 -46
- package/dist/fleet/fleet-registry.d.ts +2 -0
- package/dist/fleet/resource-catalog.d.ts +245 -0
- package/dist/fleet/resource-catalog.js +211 -0
- package/dist/fleet/rooms/room-access.d.ts +138 -0
- package/dist/fleet/rooms/room-access.js +196 -0
- package/dist/fleet/rooms/room-client.d.ts +158 -0
- package/dist/fleet/rooms/room-client.js +685 -0
- package/dist/fleet/rooms/room-event.d.ts +139 -0
- package/dist/fleet/rooms/room-event.js +330 -0
- package/dist/fleet/rooms/room-filter.d.ts +48 -0
- package/dist/fleet/rooms/room-filter.js +152 -0
- package/dist/fleet/rooms/room-hub.d.ts +154 -0
- package/dist/fleet/rooms/room-hub.js +363 -0
- package/dist/fleet/rooms/room-identity.d.ts +26 -0
- package/dist/fleet/rooms/room-identity.js +82 -0
- package/dist/fleet/rooms/room-lock.d.ts +34 -0
- package/dist/fleet/rooms/room-lock.js +180 -0
- package/dist/fleet/rooms/room-observations.d.ts +7 -0
- package/dist/fleet/rooms/room-observations.js +61 -0
- package/dist/fleet/rooms/room-server.d.ts +28 -0
- package/dist/fleet/rooms/room-server.js +75 -0
- package/dist/fleet/rooms/room-store.d.ts +119 -0
- package/dist/fleet/rooms/room-store.js +448 -0
- package/dist/fleet/rooms/room-ws-bridge.d.ts +27 -0
- package/dist/fleet/rooms/room-ws-bridge.js +137 -0
- package/dist/fleet/sensory-mission-bridge.d.ts +42 -0
- package/dist/fleet/sensory-mission-bridge.js +136 -0
- package/dist/git/worktree-sessions.js +1 -0
- package/dist/harness/contract.d.ts +4 -4
- package/dist/harness/fleet-supervisor.d.ts +16 -0
- package/dist/harness/fleet-supervisor.js +64 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.js +4 -0
- package/dist/harness/mission-runner.d.ts +3 -0
- package/dist/harness/mission-runner.js +53 -0
- package/dist/harness/mission-store.d.ts +93 -0
- package/dist/harness/mission-store.js +297 -0
- package/dist/harness/tool-harness.d.ts +56 -0
- package/dist/harness/tool-harness.js +153 -0
- package/dist/hooks/use-enhanced-input.js +48 -4
- package/dist/hooks/use-input-handler.d.ts +1 -0
- package/dist/hooks/use-input-handler.js +82 -22
- package/dist/hooks/use-input-history.js +1 -0
- package/dist/identity/lisa-introspection.js +5 -2
- package/dist/identity/operational-self-model.d.ts +2 -0
- package/dist/identity/operational-self-model.js +4 -0
- package/dist/index.js +52 -6
- package/dist/mcp/client.js +6 -0
- package/dist/mcp/config.d.ts +20 -0
- package/dist/mcp/config.js +121 -8
- package/dist/mcp/import-normalize.d.ts +12 -0
- package/dist/mcp/import-normalize.js +114 -0
- package/dist/mcp/transports.d.ts +10 -5
- package/dist/mcp/transports.js +61 -99
- package/dist/mcp/types.d.ts +5 -0
- package/dist/media/comfyui-recipe-contract.d.ts +7 -7
- package/dist/memory/facts-memory.d.ts +11 -1
- package/dist/memory/facts-memory.js +47 -8
- package/dist/memory/memory-candidate-queue.d.ts +2 -2
- package/dist/memory/memory-candidate-queue.js +6 -6
- package/dist/memory/persistent-memory.d.ts +13 -8
- package/dist/memory/persistent-memory.js +77 -30
- package/dist/nodes/device-node.js +5 -9
- package/dist/observability/mobile-supervision-gateway-contract.js +20 -7
- package/dist/observability/run-event-writer.d.ts +21 -0
- package/dist/observability/run-event-writer.js +81 -0
- package/dist/observability/run-store.d.ts +5 -0
- package/dist/observability/run-store.js +18 -13
- package/dist/observability/run-trajectory.js +1 -1
- package/dist/optimization/prompt-cache.d.ts +19 -2
- package/dist/optimization/prompt-cache.js +41 -6
- package/dist/orchestration/orchestrator.d.ts +21 -0
- package/dist/orchestration/orchestrator.js +122 -15
- package/dist/persistence/session-content.d.ts +8 -0
- package/dist/persistence/session-content.js +76 -0
- package/dist/persistence/session-handoff.d.ts +64 -0
- package/dist/persistence/session-handoff.js +80 -0
- package/dist/persistence/session-history.d.ts +4 -0
- package/dist/persistence/session-history.js +38 -0
- package/dist/persistence/session-store.d.ts +9 -0
- package/dist/persistence/session-store.js +48 -20
- package/dist/personas/persona-manager.js +17 -1
- package/dist/plugins/code-explorer/CodeExplorerManager.d.ts +10 -4
- package/dist/plugins/code-explorer/CodeExplorerManager.js +69 -16
- package/dist/plugins/plugin-manager.js +10 -1
- package/dist/prompts/prompt-manager.js +11 -4
- package/dist/prompts/system-base.js +6 -2
- package/dist/protocols/a2a/codebuddy-executor.d.ts +11 -2
- package/dist/protocols/a2a/codebuddy-executor.js +9 -8
- package/dist/protocols/a2a/index.d.ts +1 -1
- package/dist/protocols/a2a/jsonrpc-v1.d.ts +41 -0
- package/dist/protocols/a2a/jsonrpc-v1.js +145 -0
- package/dist/protocols/a2a/peer-config.d.ts +20 -0
- package/dist/protocols/a2a/peer-config.js +55 -0
- package/dist/providers/codex-oauth.js +30 -6
- package/dist/providers/model-provider-compat.js +2 -1
- package/dist/sandbox/os-sandbox.d.ts +1 -1
- package/dist/scheduler/cron-scheduler.d.ts +15 -2
- package/dist/scheduler/cron-scheduler.js +35 -4
- package/dist/scheduler/job-notepad.d.ts +69 -0
- package/dist/scheduler/job-notepad.js +339 -0
- package/dist/security/audit-logger.d.ts +1 -1
- package/dist/security/compute-confinement.d.ts +4 -0
- package/dist/security/compute-confinement.js +89 -0
- package/dist/security/session-encryption.d.ts +4 -0
- package/dist/security/session-encryption.js +31 -0
- package/dist/sensory/voice-loop.d.ts +17 -0
- package/dist/sensory/voice-loop.js +72 -15
- package/dist/server/auth/device-session-context.d.ts +9 -0
- package/dist/server/auth/device-session-context.js +13 -0
- package/dist/server/auth/device-store.d.ts +89 -0
- package/dist/server/auth/device-store.js +261 -0
- package/dist/server/auth/device-token.d.ts +3 -0
- package/dist/server/auth/device-token.js +6 -0
- package/dist/server/auth/jwt.js +4 -0
- package/dist/server/index.d.ts +0 -10
- package/dist/server/index.js +28 -0
- package/dist/server/middleware/auth.js +3 -2
- package/dist/server/routes/a2a-jsonrpc.d.ts +9 -0
- package/dist/server/routes/a2a-jsonrpc.js +66 -0
- package/dist/server/routes/a2a-protocol.d.ts +12 -0
- package/dist/server/routes/a2a-protocol.js +1 -1
- package/dist/server/routes/device-auth.d.ts +4 -0
- package/dist/server/routes/device-auth.js +40 -0
- package/dist/server/types.d.ts +4 -0
- package/dist/server/websocket/handler.d.ts +13 -0
- package/dist/server/websocket/handler.js +102 -17
- package/dist/services/prompt-builder.d.ts +2 -0
- package/dist/services/prompt-builder.js +13 -5
- package/dist/services/runtime-settings-context.d.ts +73 -0
- package/dist/services/runtime-settings-context.js +69 -0
- package/dist/skills/executor.js +2 -0
- package/dist/skills/hub.js +16 -14
- package/dist/skills/local-inventory.d.ts +21 -0
- package/dist/skills/local-inventory.js +72 -0
- package/dist/skills/skill-loader.js +2 -2
- package/dist/skills/skill-usage-store.d.ts +49 -0
- package/dist/skills/skill-usage-store.js +121 -0
- package/dist/testing/ai-integration-tests.js +8 -5
- package/dist/themes/theme-manager.d.ts +12 -0
- package/dist/themes/theme-manager.js +29 -0
- package/dist/themes/theme-schema.d.ts +24 -24
- package/dist/tools/a2a-call-tool.d.ts +34 -0
- package/dist/tools/a2a-call-tool.js +75 -0
- package/dist/tools/bash/streaming-executor.d.ts +1 -0
- package/dist/tools/bash/streaming-executor.js +78 -90
- package/dist/tools/code-exec-preflight-runner.d.ts +41 -0
- package/dist/tools/code-exec-preflight-runner.js +254 -0
- package/dist/tools/code-exec-preflight.d.ts +44 -0
- package/dist/tools/code-exec-preflight.js +501 -0
- package/dist/tools/code-exec-tool.d.ts +48 -1
- package/dist/tools/code-exec-tool.js +191 -47
- package/dist/tools/comment-watcher.js +29 -12
- package/dist/tools/core-code-inspection.d.ts +56 -0
- package/dist/tools/core-code-inspection.js +86 -0
- package/dist/tools/create-skill-tool.d.ts +2 -3
- package/dist/tools/create-skill-tool.js +16 -75
- package/dist/tools/cronjob-tool.d.ts +1 -0
- package/dist/tools/cronjob-tool.js +1 -0
- package/dist/tools/env-doctor-tool.d.ts +2 -0
- package/dist/tools/env-doctor-tool.js +4 -3
- package/dist/tools/execute-code-rpc-invoker.d.ts +1 -1
- package/dist/tools/execute-code-rpc-invoker.js +35 -19
- package/dist/tools/execute-code-runner.d.ts +2 -0
- package/dist/tools/execute-code-runner.js +52 -17
- package/dist/tools/fleet-room-tool.d.ts +104 -0
- package/dist/tools/fleet-room-tool.js +124 -0
- package/dist/tools/integration-tool-hints.d.ts +4 -0
- package/dist/tools/integration-tool-hints.js +19 -0
- package/dist/tools/list-peers-tool.d.ts +3 -0
- package/dist/tools/list-peers-tool.js +11 -4
- package/dist/tools/media-generation-tool.d.ts +16 -1
- package/dist/tools/media-generation-tool.js +341 -9
- package/dist/tools/merge-conflict-tool.js +53 -25
- package/dist/tools/metadata.d.ts +1 -5
- package/dist/tools/metadata.js +21 -28
- package/dist/tools/ragchat-tool.d.ts +39 -0
- package/dist/tools/ragchat-tool.js +105 -0
- package/dist/tools/registry/fleet-tools.d.ts +9 -0
- package/dist/tools/registry/fleet-tools.js +22 -1
- package/dist/tools/registry/knowledge-tools.d.ts +2 -2
- package/dist/tools/registry/knowledge-tools.js +2 -2
- package/dist/tools/registry/lessons-tools.d.ts +7 -0
- package/dist/tools/registry/lessons-tools.js +43 -3
- package/dist/tools/registry/memory-tools.d.ts +1 -1
- package/dist/tools/registry/memory-tools.js +8 -8
- package/dist/tools/registry/research-tools.d.ts +1 -0
- package/dist/tools/registry/research-tools.js +4 -13
- package/dist/tools/registry/self-describe-tools.d.ts +1 -1
- package/dist/tools/registry/self-describe-tools.js +43 -30
- package/dist/tools/resource-catalog-tool.d.ts +38 -0
- package/dist/tools/resource-catalog-tool.js +46 -0
- package/dist/tools/skills-inspection-tool.js +30 -1
- package/dist/tools/stream-tool-output.d.ts +3 -0
- package/dist/tools/stream-tool-output.js +33 -0
- package/dist/tools/tool-call-scheduler.d.ts +10 -0
- package/dist/tools/tool-call-scheduler.js +58 -0
- package/dist/tools/tool-effect.d.ts +5 -0
- package/dist/tools/tool-effect.js +26 -0
- package/dist/tools/tool-search.d.ts +12 -11
- package/dist/tools/tool-search.js +67 -26
- package/dist/tools/types.d.ts +6 -0
- package/dist/ui/components/ChatHistory.d.ts +1 -1
- package/dist/ui/components/ChatHistory.js +2 -2
- package/dist/ui/components/ChatInput.d.ts +2 -1
- package/dist/ui/components/ChatInput.js +42 -88
- package/dist/ui/components/ChatInterface.d.ts +4 -2
- package/dist/ui/components/ChatInterface.js +27 -63
- package/dist/ui/components/CommandSuggestions.d.ts +0 -1
- package/dist/ui/components/CommandSuggestions.js +4 -6
- package/dist/ui/components/FileAutocomplete.js +1 -1
- package/dist/ui/components/KeyboardHelp.js +8 -6
- package/dist/ui/components/ModelSelection.js +6 -5
- package/dist/ui/components/StatusBar.d.ts +2 -1
- package/dist/ui/components/StatusBar.js +8 -7
- package/dist/ui/context/theme-context.js +3 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/utils/markdown-renderer.js +4 -13
- package/dist/utils/atomic-write.d.ts +22 -0
- package/dist/utils/atomic-write.js +29 -0
- package/dist/utils/bounded-output.d.ts +16 -0
- package/dist/utils/bounded-output.js +63 -0
- package/dist/utils/device-store-file.d.ts +4 -0
- package/dist/utils/device-store-file.js +40 -0
- package/dist/utils/export-manager.d.ts +9 -0
- package/dist/utils/export-manager.js +19 -0
- package/dist/utils/first-use-hints.d.ts +25 -0
- package/dist/utils/first-use-hints.js +58 -0
- package/dist/utils/history-manager.js +1 -1
- package/dist/utils/update-notifier.js +16 -18
- package/dist/wizard/environment-detection.d.ts +5 -1
- package/dist/wizard/environment-detection.js +49 -7
- package/dist/wizard/onboarding.d.ts +5 -1
- package/dist/wizard/onboarding.js +90 -30
- package/dist/wizard/provider-onboarding.d.ts +2 -0
- package/dist/wizard/provider-onboarding.js +55 -17
- package/package.json +7 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as readline from 'readline';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync, readFileSync, mkdirSync } from 'fs';
|
|
4
|
+
import { writeJsonAtomicSync } from '../utils/atomic-write.js';
|
|
4
5
|
import { isAbsolute, join, resolve } from 'path';
|
|
5
6
|
import { getValidationConfigForGuide, validateProviderKey, } from './provider-onboarding.js';
|
|
6
7
|
import { detectEnvironment, renderDetectionSummary, } from './environment-detection.js';
|
|
@@ -165,31 +166,39 @@ export const ONBOARDING_PHASES = [
|
|
|
165
166
|
successCheck: 'the selected layer has a doctor/status command or a focused smoke prompt.',
|
|
166
167
|
},
|
|
167
168
|
];
|
|
168
|
-
const TTS_PROVIDERS = ['
|
|
169
|
+
const TTS_PROVIDERS = ['piper', 'espeak', 'say', 'audioreader'];
|
|
170
|
+
class OnboardingCancelled extends Error {
|
|
171
|
+
}
|
|
169
172
|
function ask(rl, question, defaultValue) {
|
|
170
|
-
return new Promise((resolve) => {
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
const onClose = () => reject(new OnboardingCancelled('Setup cancelled.'));
|
|
175
|
+
rl.once('close', onClose);
|
|
171
176
|
const suffix = defaultValue ? ` [${defaultValue}]` : '';
|
|
172
177
|
rl.question(` ${question}${suffix}: `, (answer) => {
|
|
178
|
+
rl.removeListener('close', onClose);
|
|
173
179
|
resolve(answer.trim() || defaultValue || '');
|
|
174
180
|
});
|
|
175
181
|
});
|
|
176
182
|
}
|
|
177
|
-
function askChoice(rl, question, choices, defaultIdx) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
rl
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
|
|
183
|
+
async function askChoice(rl, question, choices, defaultIdx) {
|
|
184
|
+
console.log(`\n ${question}`);
|
|
185
|
+
choices.forEach((c, i) => console.log(` ${i + 1}. ${c}${i === defaultIdx ? ' (default)' : ''}`));
|
|
186
|
+
while (true) {
|
|
187
|
+
const answer = await ask(rl, 'Choice', String(defaultIdx + 1));
|
|
188
|
+
const idx = Number(answer) - 1;
|
|
189
|
+
if (/^\d+$/.test(answer) && Number.isInteger(idx) && idx >= 0 && idx < choices.length) {
|
|
190
|
+
return choices[idx];
|
|
191
|
+
}
|
|
192
|
+
console.log(` Please enter a number from 1 to ${choices.length}.`);
|
|
193
|
+
}
|
|
187
194
|
}
|
|
188
195
|
/** Read a secret without echoing it (masks keystrokes with '*'). The captured
|
|
189
196
|
* value is always correct regardless of echo; masking is cosmetic, and falls
|
|
190
197
|
* back to a visible prompt if the terminal doesn't support muting. */
|
|
191
198
|
function askSecret(rl, question) {
|
|
192
|
-
return new Promise((resolve) => {
|
|
199
|
+
return new Promise((resolve, reject) => {
|
|
200
|
+
const onClose = () => reject(new OnboardingCancelled('Setup cancelled.'));
|
|
201
|
+
rl.once('close', onClose);
|
|
193
202
|
const rlAny = rl;
|
|
194
203
|
const original = rlAny._writeToOutput?.bind(rl);
|
|
195
204
|
let muted = false;
|
|
@@ -202,6 +211,7 @@ function askSecret(rl, question) {
|
|
|
202
211
|
};
|
|
203
212
|
}
|
|
204
213
|
rl.question(` ${question}: `, (answer) => {
|
|
214
|
+
rl.removeListener('close', onClose);
|
|
205
215
|
if (typeof original === 'function')
|
|
206
216
|
rlAny._writeToOutput = original;
|
|
207
217
|
resolve(answer.trim());
|
|
@@ -216,10 +226,10 @@ function askSecret(rl, question) {
|
|
|
216
226
|
* - an entered API key → encrypted credential store (never plaintext in settings),
|
|
217
227
|
* plus `process.env[envVar]` so the current process resolves immediately.
|
|
218
228
|
* - ollama → default `OLLAMA_HOST` so auto-detection picks it up.
|
|
219
|
-
*
|
|
229
|
+
* Persistence errors propagate so the wizard cannot report a false success.
|
|
220
230
|
*/
|
|
221
231
|
export async function persistProviderSelection(guide, model, apiKey) {
|
|
222
|
-
|
|
232
|
+
{
|
|
223
233
|
const { getSettingsManager } = await import('../utils/settings-manager.js');
|
|
224
234
|
getSettingsManager().saveUserSettings({
|
|
225
235
|
provider: guide.id,
|
|
@@ -229,13 +239,11 @@ export async function persistProviderSelection(guide, model, apiKey) {
|
|
|
229
239
|
...(guide.baseURL ? { baseURL: guide.baseURL } : {}),
|
|
230
240
|
});
|
|
231
241
|
}
|
|
232
|
-
catch { /* non-fatal */ }
|
|
233
242
|
if (guide.authMode === 'api-key' && apiKey) {
|
|
234
|
-
|
|
243
|
+
{
|
|
235
244
|
const { getCredentialManager } = await import('../security/credential-manager.js');
|
|
236
245
|
getCredentialManager().setApiKey(apiKey);
|
|
237
246
|
}
|
|
238
|
-
catch { /* non-fatal */ }
|
|
239
247
|
if (guide.envVar)
|
|
240
248
|
process.env[guide.envVar] = apiKey;
|
|
241
249
|
}
|
|
@@ -255,7 +263,13 @@ export function writeConfig(configDir, result) {
|
|
|
255
263
|
mkdirSync(configDir, { recursive: true });
|
|
256
264
|
const authMode = result.authMode ?? getProviderGuide(result.provider).authMode;
|
|
257
265
|
const recommendedNextCommands = result.recommendedNextCommands ?? buildRecommendedNextCommands(result);
|
|
266
|
+
const configPath = join(configDir, 'config.json');
|
|
267
|
+
const previous = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf8')) : {};
|
|
268
|
+
if (!previous || typeof previous !== 'object' || Array.isArray(previous)) {
|
|
269
|
+
throw new Error('Existing project config must be a JSON object; it was not overwritten.');
|
|
270
|
+
}
|
|
258
271
|
const config = {
|
|
272
|
+
...previous,
|
|
259
273
|
provider: result.provider,
|
|
260
274
|
model: result.model,
|
|
261
275
|
authMode,
|
|
@@ -269,7 +283,9 @@ export function writeConfig(configDir, result) {
|
|
|
269
283
|
if (result.ttsProvider) {
|
|
270
284
|
config.ttsProvider = result.ttsProvider;
|
|
271
285
|
}
|
|
272
|
-
|
|
286
|
+
if (!result.ttsEnabled)
|
|
287
|
+
delete config.ttsProvider;
|
|
288
|
+
writeJsonAtomicSync(configPath, config);
|
|
273
289
|
}
|
|
274
290
|
export function getProviderGuide(provider) {
|
|
275
291
|
return (PROVIDER_GUIDES.find((guide) => guide.id === provider)
|
|
@@ -460,7 +476,7 @@ async function runQuickStart(rl, snapshot, projectDir) {
|
|
|
460
476
|
const free = snapshot.recommendedFree;
|
|
461
477
|
const ollama = snapshot.capabilities.find((c) => c.id === 'ollama');
|
|
462
478
|
// Case A: a ready free path exists — offer it directly.
|
|
463
|
-
if (free) {
|
|
479
|
+
if (free && PROVIDER_GUIDES.some((guide) => guide.id === free.id)) {
|
|
464
480
|
const answer = (await ask(rl, `Start now on ${free.label} — free, no API key needed? (Y/n)`, 'y')).toLowerCase();
|
|
465
481
|
if (answer === 'y' || answer === 'yes' || answer === '') {
|
|
466
482
|
const guide = getProviderGuide(free.id);
|
|
@@ -514,17 +530,40 @@ function finishQuickStart(provider, model, baseURL, projectDir) {
|
|
|
514
530
|
}
|
|
515
531
|
/** Offer to run the isolated 60-second demo right after setup — ending the
|
|
516
532
|
* wizard on proof (a green test), not prose. */
|
|
517
|
-
async function
|
|
533
|
+
export async function offerOnboardingDemo(rl, result) {
|
|
534
|
+
if (!['chatgpt', 'ollama', 'lmstudio'].includes(result.provider)) {
|
|
535
|
+
console.log(' Verify this provider with the first-chat command below.');
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
518
538
|
const answer = (await ask(rl, 'Run the 60-second demo now to confirm it works? (Y/n)', 'y')).toLowerCase();
|
|
519
539
|
if (answer === 'y' || answer === 'yes' || answer === '') {
|
|
520
540
|
try {
|
|
521
541
|
const { runTryDemo } = await import('../commands/try.js');
|
|
522
542
|
rl.pause();
|
|
523
|
-
await
|
|
524
|
-
|
|
543
|
+
const { getSettingsManager } = await import('../utils/settings-manager.js');
|
|
544
|
+
const code = await runTryDemo({
|
|
545
|
+
verbose: false,
|
|
546
|
+
resolveProvider: async () => ({
|
|
547
|
+
kind: result.provider === 'chatgpt' ? 'chatgpt' : 'ollama',
|
|
548
|
+
label: `${result.provider} (${result.model})`,
|
|
549
|
+
apiKey: result.provider === 'chatgpt' ? 'oauth-chatgpt' : 'local',
|
|
550
|
+
baseURL: result.provider === 'chatgpt'
|
|
551
|
+
? 'https://chatgpt.com/backend-api/codex'
|
|
552
|
+
: getSettingsManager().getBaseURL(),
|
|
553
|
+
model: result.model,
|
|
554
|
+
}),
|
|
555
|
+
});
|
|
556
|
+
if (code !== 0) {
|
|
557
|
+
process.exitCode = code;
|
|
558
|
+
console.log(' Setup saved, but the demo failed. First chat is not verified.');
|
|
559
|
+
}
|
|
525
560
|
}
|
|
526
561
|
catch {
|
|
527
|
-
|
|
562
|
+
process.exitCode = 1;
|
|
563
|
+
console.log('\n The demo failed. First chat is not verified.\n');
|
|
564
|
+
}
|
|
565
|
+
finally {
|
|
566
|
+
rl.resume();
|
|
528
567
|
}
|
|
529
568
|
}
|
|
530
569
|
else {
|
|
@@ -562,7 +601,7 @@ export async function runOnboarding() {
|
|
|
562
601
|
if (quick) {
|
|
563
602
|
console.log(renderCapabilitiesFooter());
|
|
564
603
|
console.log('');
|
|
565
|
-
await
|
|
604
|
+
await offerOnboardingDemo(rl, quick);
|
|
566
605
|
return quick;
|
|
567
606
|
}
|
|
568
607
|
console.log(renderOnboardingRoadmap());
|
|
@@ -571,8 +610,15 @@ export async function runOnboarding() {
|
|
|
571
610
|
// default lands on the recommended free path when there is one.
|
|
572
611
|
const orderedGuides = orderGuidesByDetection(snapshot);
|
|
573
612
|
const provider = await askChoice(rl, 'Which AI provider do you want to use?', orderedGuides.map((guide) => `${guide.id} — ${guide.label}`), 0).then((choice) => choice.split(/\s+—\s+/)[0] ?? choice);
|
|
574
|
-
const
|
|
575
|
-
const
|
|
613
|
+
const selectedGuide = getProviderGuide(provider);
|
|
614
|
+
const detected = snapshot.capabilities.find((capability) => capability.id === provider);
|
|
615
|
+
const guide = selectedGuide.authMode === 'local' && detected?.baseURL
|
|
616
|
+
? { ...selectedGuide, baseURL: detected.baseURL }
|
|
617
|
+
: selectedGuide;
|
|
618
|
+
const defaultValidation = getValidationConfigForGuide(provider);
|
|
619
|
+
const validationConfig = guide.authMode === 'local' && guide.baseURL && defaultValidation
|
|
620
|
+
? { ...defaultValidation, baseUrl: guide.baseURL.replace(/\/v1\/?$/, '') }
|
|
621
|
+
: defaultValidation;
|
|
576
622
|
// 2. Authentication — captured AND verified inline so you leave the wizard
|
|
577
623
|
// ready to chat. A rejected key never gets persisted; a successful probe
|
|
578
624
|
// also hands us the provider's real model list for step 3.
|
|
@@ -651,10 +697,18 @@ export async function runOnboarding() {
|
|
|
651
697
|
recommendedNextCommands: buildRecommendedNextCommands({ provider, apiKey, model }),
|
|
652
698
|
...(ttsProvider ? { ttsProvider } : {}),
|
|
653
699
|
};
|
|
700
|
+
{
|
|
701
|
+
const { getTTSManager } = await import('../input/text-to-speech.js');
|
|
702
|
+
getTTSManager().updateConfig({
|
|
703
|
+
enabled: ttsEnabled,
|
|
704
|
+
autoSpeak: ttsEnabled,
|
|
705
|
+
...(ttsProvider ? { provider: ttsProvider } : {}),
|
|
706
|
+
});
|
|
707
|
+
}
|
|
654
708
|
// 6. Write project config into the folder the user chose
|
|
655
709
|
applyOnboardingProjectConfig(projectDir, result);
|
|
656
710
|
// 7. Summary
|
|
657
|
-
const ready = verified
|
|
711
|
+
const ready = verified;
|
|
658
712
|
console.log('');
|
|
659
713
|
console.log(` ${ready ? 'Setup complete — you\'re ready to go!' : 'Setup saved.'}`);
|
|
660
714
|
console.log('');
|
|
@@ -688,10 +742,16 @@ export async function runOnboarding() {
|
|
|
688
742
|
console.log('');
|
|
689
743
|
// Close with a real, runnable test so the wizard ends on proof, not prose.
|
|
690
744
|
if (ready) {
|
|
691
|
-
await
|
|
745
|
+
await offerOnboardingDemo(rl, result);
|
|
692
746
|
}
|
|
693
747
|
return result;
|
|
694
748
|
}
|
|
749
|
+
catch (error) {
|
|
750
|
+
if (!(error instanceof OnboardingCancelled))
|
|
751
|
+
throw error;
|
|
752
|
+
console.log('\n Setup cancelled.');
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
695
755
|
finally {
|
|
696
756
|
rl.close();
|
|
697
757
|
}
|
|
@@ -19,6 +19,8 @@ export interface ProviderOnboardingConfig {
|
|
|
19
19
|
baseUrl: string;
|
|
20
20
|
/** GET endpoint to validate the key (relative to baseUrl) */
|
|
21
21
|
validateEndpoint: string;
|
|
22
|
+
/** Optional public catalog, fetched only after authentication succeeds. */
|
|
23
|
+
modelsEndpoint?: string;
|
|
22
24
|
/** User-facing instructions for obtaining an API key */
|
|
23
25
|
instructions: string;
|
|
24
26
|
}
|
|
@@ -57,7 +57,10 @@ export const PROVIDER_CONFIGS = [
|
|
|
57
57
|
name: 'OpenRouter',
|
|
58
58
|
envKey: 'OPENROUTER_API_KEY',
|
|
59
59
|
baseUrl: 'https://openrouter.ai/api',
|
|
60
|
-
|
|
60
|
+
// /models is public and cannot establish whether a key is valid.
|
|
61
|
+
// https://openrouter.ai/docs/api/api-reference/api-keys/get-current-api-key
|
|
62
|
+
validateEndpoint: '/v1/key',
|
|
63
|
+
modelsEndpoint: '/v1/models',
|
|
61
64
|
instructions: 'Get your API key from https://openrouter.ai/keys',
|
|
62
65
|
},
|
|
63
66
|
{
|
|
@@ -153,33 +156,68 @@ export async function validateProviderKey(config, apiKey) {
|
|
|
153
156
|
error: `API error (${response.status}): ${errorText.slice(0, 200)}`,
|
|
154
157
|
};
|
|
155
158
|
}
|
|
156
|
-
|
|
159
|
+
if (config.id === 'openrouter') {
|
|
160
|
+
let body;
|
|
161
|
+
try {
|
|
162
|
+
body = await response.json();
|
|
163
|
+
}
|
|
164
|
+
catch { /* invalid response below */ }
|
|
165
|
+
if (!isRecord(body) || !isRecord(body.data) || typeof body.data.label !== 'string') {
|
|
166
|
+
return { valid: false, error: `Invalid authentication response from ${config.name}` };
|
|
167
|
+
}
|
|
168
|
+
// The key is authenticated even if the optional model catalog is unavailable.
|
|
169
|
+
if (!config.modelsEndpoint)
|
|
170
|
+
return { valid: true };
|
|
171
|
+
try {
|
|
172
|
+
const catalog = await fetch(`${config.baseUrl}${config.modelsEndpoint}`, {
|
|
173
|
+
method: 'GET',
|
|
174
|
+
headers,
|
|
175
|
+
signal: AbortSignal.timeout(15000),
|
|
176
|
+
});
|
|
177
|
+
if (!catalog.ok)
|
|
178
|
+
return { valid: true };
|
|
179
|
+
const models = await extractModels(config, catalog);
|
|
180
|
+
return models === null ? { valid: true } : { valid: true, models };
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return { valid: true };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
157
186
|
const models = await extractModels(config, response);
|
|
187
|
+
if (models === null) {
|
|
188
|
+
return { valid: false, error: `Invalid model-list response from ${config.name}` };
|
|
189
|
+
}
|
|
158
190
|
return { valid: true, models };
|
|
159
191
|
}
|
|
160
192
|
/**
|
|
161
193
|
* Parse the model list from a provider's validation response.
|
|
162
194
|
*/
|
|
195
|
+
function isRecord(value) {
|
|
196
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
197
|
+
}
|
|
163
198
|
async function extractModels(config, response) {
|
|
164
199
|
try {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
200
|
+
const body = await response.json();
|
|
201
|
+
if (!isRecord(body))
|
|
202
|
+
return null;
|
|
203
|
+
const usesNames = config.id === 'ollama' || config.id === 'google';
|
|
204
|
+
const rows = usesNames ? body.models : body.data;
|
|
205
|
+
const field = usesNames ? 'name' : 'id';
|
|
206
|
+
if (!Array.isArray(rows))
|
|
207
|
+
return null;
|
|
208
|
+
const models = [];
|
|
209
|
+
for (const row of rows) {
|
|
210
|
+
if (!isRecord(row))
|
|
211
|
+
return null;
|
|
212
|
+
const value = row[field];
|
|
213
|
+
if (typeof value !== 'string' || !value.trim())
|
|
214
|
+
return null;
|
|
215
|
+
models.push(config.id === 'google' ? value.replace(/^models\//, '') : value);
|
|
176
216
|
}
|
|
177
|
-
|
|
178
|
-
const modelData = body.data;
|
|
179
|
-
return modelData?.map((m) => m.id) ?? [];
|
|
217
|
+
return models;
|
|
180
218
|
}
|
|
181
219
|
catch {
|
|
182
|
-
return
|
|
220
|
+
return null;
|
|
183
221
|
}
|
|
184
222
|
}
|
|
185
223
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phuetz/code-buddy",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "AI coding agent with terminal and HTTP interfaces, optional Cowork desktop integration, multi-provider routing, tools, fleet collaboration and inspectable memory. See release notes for supported integrations and limits.",
|
|
5
5
|
"author": "Patrice Huetz <patrice.huetz@gmail.com>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
],
|
|
18
18
|
"main": "dist/index.js",
|
|
19
19
|
"exports": {
|
|
20
|
+
"./harness": {
|
|
21
|
+
"types": "./dist/harness/index.d.ts",
|
|
22
|
+
"import": "./dist/harness/index.js"
|
|
23
|
+
},
|
|
20
24
|
".": {
|
|
21
25
|
"import": "./dist/index.js",
|
|
22
26
|
"types": "./dist/index.d.ts"
|
|
@@ -215,6 +219,7 @@
|
|
|
215
219
|
"terminal-image": "^4.1.0",
|
|
216
220
|
"tesseract.js": "^7.0.0",
|
|
217
221
|
"tiktoken": "^1.0.22",
|
|
222
|
+
"typescript": "^5.9.3",
|
|
218
223
|
"undici": "^6.28.0",
|
|
219
224
|
"yaml": "^2.9.0",
|
|
220
225
|
"youtube-caption-extractor": "^1.10.2",
|
|
@@ -275,7 +280,6 @@
|
|
|
275
280
|
"semantic-release": "^25.0.3",
|
|
276
281
|
"tsx": "^4.21.0",
|
|
277
282
|
"typedoc": "^0.28.15",
|
|
278
|
-
"typescript": "^5.9.3",
|
|
279
283
|
"vitest": "^4.0.18",
|
|
280
284
|
"vscode-languageserver": "^9.0.1",
|
|
281
285
|
"vscode-languageserver-textdocument": "^1.0.12"
|