@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
|
@@ -12,20 +12,18 @@ import { MCPStatus } from "./McpStatus.js";
|
|
|
12
12
|
import ConfirmationDialog from "./ConfirmationDialog.js";
|
|
13
13
|
import { ConfirmationService, } from "../../utils/confirmation-service.js";
|
|
14
14
|
import ApiKeyInput from "./ApiKeyInput.js";
|
|
15
|
-
import { renderColorBanner } from "../../utils/ascii-banner.js";
|
|
16
15
|
import { ThemeProvider, useTheme } from "../context/theme-context.js";
|
|
17
16
|
import { getErrorMessage } from "../../types/index.js";
|
|
18
17
|
import { MiniStatusBar } from "./StatusBar.js";
|
|
19
|
-
import { KeyboardHelp, useKeyboardHelp
|
|
18
|
+
import { KeyboardHelp, useKeyboardHelp } from "./KeyboardHelp.js";
|
|
20
19
|
import { ToastProvider } from "./ToastNotifications.js";
|
|
21
|
-
import { logger } from "../../utils/logger.js";
|
|
22
20
|
import { getTTSManager } from "../../input/text-to-speech.js";
|
|
23
21
|
import { announceToScreenReader, useAccessibilitySettings, useKeyboardShortcuts, } from "../utils/accessibility.js";
|
|
24
22
|
// Main chat component that handles input when agent is available
|
|
25
|
-
function ChatInterfaceWithAgent({ agent, initialMessage, }) {
|
|
26
|
-
const { colors
|
|
23
|
+
function ChatInterfaceWithAgent({ agent, initialMessage, initialHistory, }) {
|
|
24
|
+
const { colors } = useTheme();
|
|
27
25
|
const { settings } = useAccessibilitySettings();
|
|
28
|
-
const [chatHistory, setChatHistory] = useState([]);
|
|
26
|
+
const [chatHistory, setChatHistory] = useState(() => initialHistory ?? []);
|
|
29
27
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
30
28
|
const [processingTime, setProcessingTime] = useState(0);
|
|
31
29
|
const [tokenCount, setTokenCount] = useState(0);
|
|
@@ -98,7 +96,7 @@ function ChatInterfaceWithAgent({ agent, initialMessage, }) {
|
|
|
98
96
|
return prev;
|
|
99
97
|
});
|
|
100
98
|
}, []);
|
|
101
|
-
const { input, cursorPosition, showCommandSuggestions, selectedCommandIndex, showModelSelection, selectedModelIndex, showFileAutocomplete, selectedFileIndex, fileSuggestions, commandSuggestions, availableModels, autoEditEnabled, handleInputSubmit, } = useInputHandler({
|
|
99
|
+
const { input, cursorPosition, showCommandSuggestions, selectedCommandIndex, showModelSelection, selectedModelIndex, showFileAutocomplete, selectedFileIndex, fileSuggestions, commandSuggestions, availableModels, autoEditEnabled, queuedMessageCount, handleInputSubmit, } = useInputHandler({
|
|
102
100
|
agent,
|
|
103
101
|
chatHistory,
|
|
104
102
|
setChatHistory,
|
|
@@ -110,39 +108,15 @@ function ChatInterfaceWithAgent({ agent, initialMessage, }) {
|
|
|
110
108
|
processingStartTime,
|
|
111
109
|
isProcessing,
|
|
112
110
|
isStreaming,
|
|
113
|
-
isConfirmationActive: !!confirmationOptions,
|
|
111
|
+
isConfirmationActive: !!confirmationOptions || !!pendingQuestion || keyboardHelp.isVisible,
|
|
114
112
|
appendStreamingContent,
|
|
115
113
|
finalizeStreamingEntry,
|
|
116
114
|
updateToolCallEntry,
|
|
117
115
|
});
|
|
118
116
|
useEffect(() => {
|
|
119
|
-
// Only clear console on non-Windows platforms or if not PowerShell
|
|
120
|
-
// Windows PowerShell can have issues with console.clear() causing flickering
|
|
121
|
-
const isWindows = process.platform === "win32";
|
|
122
|
-
const isPowerShell = process.env.ComSpec?.toLowerCase().includes("powershell") ||
|
|
123
|
-
process.env.PSModulePath !== undefined;
|
|
124
|
-
if (!isWindows || !isPowerShell) {
|
|
125
|
-
process.stdout.write('\x1b[2J\x1b[0f'); // ANSI escape code to clear screen
|
|
126
|
-
}
|
|
127
|
-
// Add top padding
|
|
128
|
-
logger.info(" ");
|
|
129
|
-
// Generate logo with MIT-licensed ascii-banner (replaces GPL cfonts)
|
|
130
|
-
const logoOutput = renderColorBanner("CODE BUDDY", ["magenta", "cyan"]);
|
|
131
|
-
// Add horizontal margin (2 spaces) to match Ink paddingX={2}
|
|
132
|
-
const logoLines = logoOutput.split("\n");
|
|
133
|
-
logoLines.forEach((line) => {
|
|
134
|
-
if (line.trim()) {
|
|
135
|
-
logger.info(" " + line); // Add 2 spaces for horizontal margin
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
logger.info(line); // Keep empty lines as-is
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
logger.info(" "); // Spacing after logo
|
|
142
|
-
setChatHistory([]);
|
|
143
117
|
// Announce to screen readers
|
|
144
118
|
if (settings.screenReader) {
|
|
145
|
-
announceToScreenReader('Code Buddy started. Chat interface ready.
|
|
119
|
+
announceToScreenReader('Code Buddy started. Chat interface ready. Type /help for commands.', 'polite');
|
|
146
120
|
}
|
|
147
121
|
}, [settings.screenReader]);
|
|
148
122
|
// Process initial message if provided (streaming for faster feedback)
|
|
@@ -371,6 +345,7 @@ function ChatInterfaceWithAgent({ agent, initialMessage, }) {
|
|
|
371
345
|
announceToScreenReader(`Error occurred: ${errorMessage}`, 'assertive');
|
|
372
346
|
}
|
|
373
347
|
}
|
|
348
|
+
await agent.persistInteractiveSession();
|
|
374
349
|
setIsProcessing(false);
|
|
375
350
|
processingStartTime.current = 0;
|
|
376
351
|
};
|
|
@@ -422,53 +397,42 @@ function ChatInterfaceWithAgent({ agent, initialMessage, }) {
|
|
|
422
397
|
}
|
|
423
398
|
};
|
|
424
399
|
return (React.createElement(Box, { flexDirection: "column", paddingX: 2 },
|
|
425
|
-
chatHistory.length === 0 && !confirmationOptions && (React.createElement(Box, { flexDirection: "column", marginBottom:
|
|
426
|
-
React.createElement(Text, { color: colors.primary
|
|
427
|
-
React.createElement(
|
|
428
|
-
|
|
429
|
-
React.createElement(Text, { color: colors.textMuted }, "2. Be specific for the best results."),
|
|
430
|
-
React.createElement(Text, { color: colors.textMuted }, "3. Create CODEBUDDY.md files to customize your interactions with Code Buddy."),
|
|
431
|
-
React.createElement(Text, { color: colors.textMuted }, "4. Press Shift+Tab to toggle auto-edit mode."),
|
|
432
|
-
React.createElement(Text, { color: colors.textMuted }, "5. /help for more information."),
|
|
433
|
-
React.createElement(Text, { color: colors.textMuted }, "6. /theme to change the theme, /avatar to change avatars.")),
|
|
434
|
-
React.createElement(Box, { marginTop: 1 },
|
|
435
|
-
React.createElement(KeyboardHelpButton, null)))),
|
|
436
|
-
React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
437
|
-
React.createElement(Text, { color: colors.textMuted }, "Type your request in natural language. Ctrl+C to clear, 'exit' to quit.")),
|
|
400
|
+
chatHistory.length === 0 && !confirmationOptions && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
401
|
+
React.createElement(Text, { bold: true, color: colors.primary }, "Code Buddy"),
|
|
402
|
+
React.createElement(Text, { color: colors.textMuted, wrap: "truncate-middle" }, process.cwd()),
|
|
403
|
+
React.createElement(Text, { color: colors.textMuted }, "Ask a question or describe a change. /help commands \u00B7 /model choose a model"))),
|
|
438
404
|
React.createElement(Box, { flexDirection: "column", ref: scrollRef },
|
|
439
405
|
React.createElement(ChatHistory, { entries: chatHistory, isConfirmationActive: !!confirmationOptions })),
|
|
440
406
|
pendingQuestion && (React.createElement(TabbedQuestion, { question: pendingQuestion.question, options: pendingQuestion.options, onAnswer: (answer) => {
|
|
441
407
|
pendingQuestion.resolve(answer);
|
|
442
408
|
} })),
|
|
443
409
|
confirmationOptions && (React.createElement(ConfirmationDialog, { operation: confirmationOptions.operation, filename: confirmationOptions.filename, showVSCodeOpen: confirmationOptions.showVSCodeOpen, content: confirmationOptions.content, onConfirm: handleConfirmation, onReject: handleRejection })),
|
|
444
|
-
!confirmationOptions && (React.createElement(React.Fragment, null,
|
|
410
|
+
!confirmationOptions && !pendingQuestion && !keyboardHelp.isVisible && (React.createElement(React.Fragment, null,
|
|
445
411
|
React.createElement(StatusBlock, { isActive: isProcessing || isStreaming, processingTime: processingTime, tokenCount: tokenCount, activity: currentActivity }),
|
|
412
|
+
queuedMessageCount > 0 && React.createElement(Text, { color: colors.info },
|
|
413
|
+
queuedMessageCount,
|
|
414
|
+
" message(s) queued \u00B7 sent after the current reply"),
|
|
446
415
|
React.createElement(ChatInput, { input: input, cursorPosition: cursorPosition, isProcessing: isProcessing, isStreaming: isStreaming, mode: agent.getMode() }),
|
|
447
|
-
React.createElement(
|
|
448
|
-
|
|
416
|
+
React.createElement(Text, { color: colors.textMuted, dimColor: true },
|
|
417
|
+
isProcessing || isStreaming ? 'Enter queue' : 'Enter send',
|
|
418
|
+
" \u00B7 Ctrl+J newline \u00B7 Esc cancel \u00B7 Ctrl+C quit"),
|
|
419
|
+
React.createElement(Box, { flexDirection: "row", flexWrap: "wrap", marginTop: 1, justifyContent: "space-between" },
|
|
420
|
+
React.createElement(Box, { flexDirection: "row", flexWrap: "wrap" },
|
|
449
421
|
React.createElement(Box, { marginRight: 2 },
|
|
450
|
-
React.createElement(Text, { color: colors.primary },
|
|
451
|
-
autoEditEnabled ? "▶" : "⏸",
|
|
452
|
-
" auto-edit:",
|
|
453
|
-
" ",
|
|
454
|
-
autoEditEnabled ? "on" : "off"),
|
|
422
|
+
React.createElement(Text, { color: colors.primary }, autoEditEnabled ? "Edits: automatic" : "Edits: ask first"),
|
|
455
423
|
React.createElement(Text, { color: colors.textMuted, dimColor: true },
|
|
456
424
|
" ",
|
|
457
425
|
"(shift + tab)")),
|
|
458
|
-
React.createElement(Box, { marginRight: 2 },
|
|
459
|
-
React.createElement(Text, { color: colors.secondary },
|
|
460
|
-
"\u25D0 ",
|
|
461
|
-
theme.name)),
|
|
462
426
|
React.createElement(MCPStatus, null)),
|
|
463
427
|
React.createElement(Box, null,
|
|
464
|
-
React.createElement(MiniStatusBar, { tokenCount: tokenCount, modelName: agent.getCurrentModel(), mode: agent.getMode(), yolo: agent.isYoloModeEnabled() }))),
|
|
428
|
+
React.createElement(MiniStatusBar, { tokenCount: tokenCount, modelName: agent.getCurrentModel(), providerName: agent.getClient().getProviderName(), mode: agent.getMode(), yolo: agent.isYoloModeEnabled() }))),
|
|
465
429
|
React.createElement(CommandSuggestions, { suggestions: commandSuggestions, input: input, selectedIndex: selectedCommandIndex, isVisible: showCommandSuggestions }),
|
|
466
430
|
React.createElement(FileAutocomplete, { input: input, visible: showFileAutocomplete, selectedIndex: selectedFileIndex, suggestions: fileSuggestions }),
|
|
467
431
|
React.createElement(ModelSelection, { models: availableModels, selectedIndex: selectedModelIndex, isVisible: showModelSelection, currentModel: agent.getCurrentModel() }))),
|
|
468
432
|
React.createElement(KeyboardHelp, { isVisible: keyboardHelp.isVisible, onClose: keyboardHelp.hide })));
|
|
469
433
|
}
|
|
470
434
|
// Inner component that handles API key input or chat interface
|
|
471
|
-
function ChatInterfaceInner({ agent, initialMessage, }) {
|
|
435
|
+
function ChatInterfaceInner({ agent, initialMessage, initialHistory, }) {
|
|
472
436
|
const [currentAgent, setCurrentAgent] = useState(agent || null);
|
|
473
437
|
const handleApiKeySet = (newAgent) => {
|
|
474
438
|
setCurrentAgent(newAgent);
|
|
@@ -476,12 +440,12 @@ function ChatInterfaceInner({ agent, initialMessage, }) {
|
|
|
476
440
|
if (!currentAgent) {
|
|
477
441
|
return React.createElement(ApiKeyInput, { onApiKeySet: handleApiKeySet });
|
|
478
442
|
}
|
|
479
|
-
return (React.createElement(ChatInterfaceWithAgent, { agent: currentAgent, initialMessage: initialMessage }));
|
|
443
|
+
return (React.createElement(ChatInterfaceWithAgent, { agent: currentAgent, initialMessage: initialMessage, initialHistory: initialHistory }));
|
|
480
444
|
}
|
|
481
445
|
// Main component wrapped with ThemeProvider and ToastProvider
|
|
482
|
-
export default function ChatInterface({ agent, initialMessage, }) {
|
|
446
|
+
export default function ChatInterface({ agent, initialMessage, initialHistory, }) {
|
|
483
447
|
return (React.createElement(ThemeProvider, null,
|
|
484
448
|
React.createElement(ToastProvider, null,
|
|
485
|
-
React.createElement(ChatInterfaceInner, { agent: agent, initialMessage: initialMessage }))));
|
|
449
|
+
React.createElement(ChatInterfaceInner, { agent: agent, initialMessage: initialMessage, initialHistory: initialHistory }))));
|
|
486
450
|
}
|
|
487
451
|
//# sourceMappingURL=ChatInterface.js.map
|
|
@@ -10,7 +10,6 @@ interface CommandSuggestionsProps {
|
|
|
10
10
|
selectedIndex: number;
|
|
11
11
|
isVisible: boolean;
|
|
12
12
|
}
|
|
13
|
-
export declare const MAX_SUGGESTIONS = 15;
|
|
14
13
|
export declare const VISIBLE_SUGGESTIONS = 10;
|
|
15
14
|
export declare function filterCommandSuggestions<T extends {
|
|
16
15
|
command: string;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { getSlashCommandManager } from "../../commands/slash-commands.js";
|
|
4
|
-
export const MAX_SUGGESTIONS = 15;
|
|
5
4
|
export const VISIBLE_SUGGESTIONS = 10;
|
|
6
5
|
/**
|
|
7
6
|
* Get argument suggestions for a command
|
|
@@ -50,7 +49,7 @@ export function filterCommandSuggestions(suggestions, input) {
|
|
|
50
49
|
const currentArg = parts.length > 1 ? parts.slice(1).join(' ') : '';
|
|
51
50
|
const argSuggestions = getArgumentSuggestions(command, currentArg);
|
|
52
51
|
if (argSuggestions.length > 0) {
|
|
53
|
-
return argSuggestions
|
|
52
|
+
return argSuggestions;
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
}
|
|
@@ -72,11 +71,10 @@ export function filterCommandSuggestions(suggestions, input) {
|
|
|
72
71
|
return -1;
|
|
73
72
|
return aIndex - bIndex;
|
|
74
73
|
});
|
|
75
|
-
return sorted
|
|
74
|
+
return sorted;
|
|
76
75
|
}
|
|
77
76
|
return suggestions
|
|
78
|
-
.filter((s) => s.command.toLowerCase().startsWith(lowerInput))
|
|
79
|
-
.slice(0, MAX_SUGGESTIONS);
|
|
77
|
+
.filter((s) => s.command.toLowerCase().startsWith(lowerInput));
|
|
80
78
|
}
|
|
81
79
|
// Memoized individual suggestion item
|
|
82
80
|
const SuggestionItem = React.memo(function SuggestionItem({ command, description, isSelected, isArgument, }) {
|
|
@@ -126,7 +124,7 @@ export const CommandSuggestions = React.memo(function CommandSuggestions({ sugge
|
|
|
126
124
|
" more below..."))),
|
|
127
125
|
React.createElement(Box, { marginTop: 1 },
|
|
128
126
|
React.createElement(Text, { color: "gray", dimColor: true },
|
|
129
|
-
"\u2191\u2193 navigate \u2022
|
|
127
|
+
"\u2191\u2193 navigate \u2022 \u2192/Tab complete \u2022 Enter run \u2022 Esc close \u2022 ",
|
|
130
128
|
totalMatches,
|
|
131
129
|
"/",
|
|
132
130
|
totalCommands,
|
|
@@ -211,7 +211,7 @@ export const FileAutocomplete = React.memo(function FileAutocomplete({ input, vi
|
|
|
211
211
|
return null;
|
|
212
212
|
}
|
|
213
213
|
return (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderActive, marginTop: 1, paddingX: 1 },
|
|
214
|
-
React.createElement(Text, { color: colors.textMuted, dimColor: true }, "File suggestions (Tab
|
|
214
|
+
React.createElement(Text, { color: colors.textMuted, dimColor: true }, "File suggestions (\u2192/Tab complete, Enter select):"),
|
|
215
215
|
suggestions.map((suggestion, index) => {
|
|
216
216
|
const isSelected = index === selectedIndex;
|
|
217
217
|
const icon = getFileIcon(suggestion);
|
|
@@ -19,7 +19,9 @@ const KEYBOARD_SHORTCUTS = [
|
|
|
19
19
|
{ keys: 'Tab', description: 'Autocomplete command', category: 'Navigation' },
|
|
20
20
|
{ keys: 'Shift+Tab', description: 'Toggle auto-edit mode', category: 'Navigation' },
|
|
21
21
|
// Editing
|
|
22
|
-
{ keys: 'Ctrl+C', description: '
|
|
22
|
+
{ keys: 'Ctrl+C', description: 'Quit Code Buddy', category: 'Session' },
|
|
23
|
+
{ keys: 'Ctrl+J', description: 'Insert a new line', category: 'Editing' },
|
|
24
|
+
{ keys: 'Enter', description: 'Send message (queue while working)', category: 'Editing' },
|
|
23
25
|
{ keys: 'Ctrl+U', description: 'Clear line', category: 'Editing' },
|
|
24
26
|
{ keys: 'Ctrl+W', description: 'Delete word', category: 'Editing' },
|
|
25
27
|
{ keys: 'Ctrl+K', description: 'Delete to end of line', category: 'Editing' },
|
|
@@ -31,7 +33,7 @@ const KEYBOARD_SHORTCUTS = [
|
|
|
31
33
|
{ keys: '/review', description: 'Code review', category: 'Tools' },
|
|
32
34
|
{ keys: '/test', description: 'Run tests', category: 'Tools' },
|
|
33
35
|
// View
|
|
34
|
-
{ keys: '
|
|
36
|
+
{ keys: '/help', description: 'Show help', category: 'View' },
|
|
35
37
|
{ keys: '/theme', description: 'Change theme', category: 'View' },
|
|
36
38
|
{ keys: '/avatar', description: 'Change avatars', category: 'View' },
|
|
37
39
|
{ keys: '/stats', description: 'Show statistics', category: 'View' },
|
|
@@ -70,7 +72,7 @@ export function KeyboardHelp({ isVisible, onClose, categories, }) {
|
|
|
70
72
|
if (input === '?' || key.escape || key.return) {
|
|
71
73
|
onClose();
|
|
72
74
|
}
|
|
73
|
-
});
|
|
75
|
+
}, { isActive: isVisible });
|
|
74
76
|
if (!isVisible)
|
|
75
77
|
return null;
|
|
76
78
|
// Filter shortcuts by category if specified
|
|
@@ -138,9 +140,9 @@ export function KeyboardHelpButton() {
|
|
|
138
140
|
const { colors } = useTheme();
|
|
139
141
|
return (React.createElement(Box, null,
|
|
140
142
|
React.createElement(Text, { dimColor: true },
|
|
141
|
-
"
|
|
142
|
-
React.createElement(Text, { bold: true, color: colors.accent }, "
|
|
143
|
-
" for
|
|
143
|
+
"Type ",
|
|
144
|
+
React.createElement(Text, { bold: true, color: colors.accent }, "/help"),
|
|
145
|
+
" for commands")));
|
|
144
146
|
}
|
|
145
147
|
export default KeyboardHelp;
|
|
146
148
|
//# sourceMappingURL=KeyboardHelp.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
// Memoized individual model item to prevent re-renders
|
|
4
4
|
const ModelItem = React.memo(function ModelItem({ model, isSelected, }) {
|
|
@@ -9,13 +9,14 @@ export const ModelSelection = React.memo(function ModelSelection({ models, selec
|
|
|
9
9
|
// Early return for invisible state
|
|
10
10
|
if (!isVisible)
|
|
11
11
|
return null;
|
|
12
|
-
|
|
13
|
-
const
|
|
12
|
+
const headerText = `Select model (current: ${currentModel}):`;
|
|
13
|
+
const start = Math.max(0, Math.min(selectedIndex - 4, models.length - 8));
|
|
14
|
+
const visibleModels = models.slice(start, start + 8);
|
|
14
15
|
return (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
15
16
|
React.createElement(Box, { marginBottom: 1 },
|
|
16
17
|
React.createElement(Text, { color: "cyan" }, headerText)),
|
|
17
|
-
|
|
18
|
+
visibleModels.map((modelOption, index) => (React.createElement(ModelItem, { key: modelOption.model, model: modelOption.model, isSelected: start + index === selectedIndex }))),
|
|
18
19
|
React.createElement(Box, { marginTop: 1 },
|
|
19
|
-
React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193 navigate \u2022 Enter
|
|
20
|
+
React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193 navigate \u2022 \u2192/Enter select \u2022 \u2190/Esc cancel"))));
|
|
20
21
|
});
|
|
21
22
|
//# sourceMappingURL=ModelSelection.js.map
|
|
@@ -45,10 +45,11 @@ export declare function StatusBar({ tokenCount, maxTokens, cost, budget, modelNa
|
|
|
45
45
|
/**
|
|
46
46
|
* Mini Status Bar - For inline display in chat interface
|
|
47
47
|
*/
|
|
48
|
-
export declare function MiniStatusBar({ tokenCount, cost, modelName, mode, yolo, }: {
|
|
48
|
+
export declare function MiniStatusBar({ tokenCount, cost, modelName, providerName, mode, yolo, }: {
|
|
49
49
|
tokenCount: number;
|
|
50
50
|
cost?: number;
|
|
51
51
|
modelName?: string;
|
|
52
|
+
providerName?: string;
|
|
52
53
|
mode?: string;
|
|
53
54
|
yolo?: boolean;
|
|
54
55
|
}): React.JSX.Element;
|
|
@@ -256,16 +256,17 @@ export function StatusBar({ tokenCount, maxTokens = 128000, cost = 0, budget = 1
|
|
|
256
256
|
/**
|
|
257
257
|
* Mini Status Bar - For inline display in chat interface
|
|
258
258
|
*/
|
|
259
|
-
export function MiniStatusBar({ tokenCount, cost, modelName, mode = 'code', yolo = false, }) {
|
|
259
|
+
export function MiniStatusBar({ tokenCount, cost, modelName, providerName, mode = 'code', yolo = false, }) {
|
|
260
260
|
const { colors } = useTheme();
|
|
261
|
-
return (React.createElement(Box,
|
|
262
|
-
mode && (React.createElement(Text, { color: mode === 'plan' ? colors.info : colors.primary }, mode
|
|
263
|
-
yolo && React.createElement(Text, { color: colors.error }, " \
|
|
261
|
+
return (React.createElement(Box, { flexWrap: "wrap" },
|
|
262
|
+
mode && (React.createElement(Text, { color: mode === 'plan' ? colors.info : colors.primary }, mode)),
|
|
263
|
+
yolo && React.createElement(Text, { color: colors.error }, " \u00B7 YOLO"),
|
|
264
264
|
React.createElement(Text, { dimColor: true }, " \u2022 "),
|
|
265
|
+
providerName && React.createElement(Text, { color: colors.textMuted },
|
|
266
|
+
providerName,
|
|
267
|
+
" \u00B7 "),
|
|
265
268
|
modelName && (React.createElement(React.Fragment, null,
|
|
266
|
-
React.createElement(Text, { color: colors.accent },
|
|
267
|
-
"\u224B ",
|
|
268
|
-
modelName),
|
|
269
|
+
React.createElement(Text, { bold: true, color: colors.accent }, modelName),
|
|
269
270
|
React.createElement(Text, { dimColor: true }, " \u2022 "))),
|
|
270
271
|
React.createElement(Text, { color: colors.info },
|
|
271
272
|
"\u2191 ",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Theme Context for Code Buddy
|
|
3
3
|
* Provides theme and avatar information to all UI components
|
|
4
4
|
*/
|
|
5
|
-
import React, { createContext, useContext, useState, useCallback, useMemo } from 'react';
|
|
5
|
+
import React, { createContext, useContext, useState, useCallback, useMemo, useSyncExternalStore } from 'react';
|
|
6
6
|
import { getThemeManager } from '../../themes/theme-manager.js';
|
|
7
7
|
/**
|
|
8
8
|
* Create the theme context
|
|
@@ -14,6 +14,7 @@ const ThemeContext = createContext(null);
|
|
|
14
14
|
export function ThemeProvider({ children }) {
|
|
15
15
|
const [themeManager] = useState(() => getThemeManager());
|
|
16
16
|
const [refreshKey, setRefreshKey] = useState(0);
|
|
17
|
+
const revision = useSyncExternalStore(themeManager.subscribe, themeManager.getSnapshot, themeManager.getSnapshot);
|
|
17
18
|
// Force re-render when theme changes
|
|
18
19
|
const refreshTheme = useCallback(() => {
|
|
19
20
|
setRefreshKey(prev => prev + 1);
|
|
@@ -77,7 +78,7 @@ export function ThemeProvider({ children }) {
|
|
|
77
78
|
clearCustomColors,
|
|
78
79
|
refreshTheme,
|
|
79
80
|
}), [
|
|
80
|
-
theme, colors, avatars, refreshKey,
|
|
81
|
+
theme, colors, avatars, refreshKey, revision,
|
|
81
82
|
setTheme, getAvailableThemes, setAvatarPreset,
|
|
82
83
|
setCustomAvatar, clearCustomAvatars, getAvatarPresets,
|
|
83
84
|
setCustomColor, clearCustomColors, refreshTheme
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export { SectionHeader, StatusWithText, AccessibleProgress, KeyboardShortcut, HelpPanel, AccessibleList, DefinitionList, Announcement, AccessibleError, AccessibleSuccess, AccessibleTable, AccessibleCodeBlock, Divider, } from "./components/AccessibleOutput.js";
|
|
5
5
|
export { ChatHistory } from "./components/ChatHistory.js";
|
|
6
6
|
export { ChatInput } from "./components/ChatInput.js";
|
|
7
|
-
export {
|
|
7
|
+
export { VISIBLE_SUGGESTIONS, filterCommandSuggestions, CommandSuggestions, } from "./components/CommandSuggestions.js";
|
|
8
8
|
export { parseDiffWithLineNumbers, DiffRenderer, } from "./components/DiffRenderer.js";
|
|
9
9
|
export { EnhancedChatInput, useInputHistory, } from "./components/EnhancedChatInput.js";
|
|
10
10
|
export { EnhancedConfirmationDialog, type OperationType, } from "./components/EnhancedConfirmationDialog.js";
|
package/dist/ui/index.js
CHANGED
|
@@ -11,7 +11,7 @@ export { ChatHistory } from "./components/ChatHistory.js";
|
|
|
11
11
|
export { ChatInput } from "./components/ChatInput.js";
|
|
12
12
|
// ChatInterface (only has default export, not re-exported by barrel)
|
|
13
13
|
// To use: import ChatInterface from './ui/components/ChatInterface.js'
|
|
14
|
-
export {
|
|
14
|
+
export { VISIBLE_SUGGESTIONS, filterCommandSuggestions, CommandSuggestions, } from "./components/CommandSuggestions.js";
|
|
15
15
|
// ConfirmationDialog (only has default export, not re-exported by barrel)
|
|
16
16
|
// To use: import ConfirmationDialog from './ui/components/ConfirmationDialog.js'
|
|
17
17
|
export { parseDiffWithLineNumbers, DiffRenderer, } from "./components/DiffRenderer.js";
|
|
@@ -74,19 +74,10 @@ marked.setOptions({
|
|
|
74
74
|
},
|
|
75
75
|
// Inline code styling
|
|
76
76
|
codespan: (text) => `${ANSI.cyan}${text}${ANSI.reset}`,
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
ANSI.blueBold,
|
|
82
|
-
ANSI.yellowBold,
|
|
83
|
-
ANSI.blue,
|
|
84
|
-
ANSI.yellow,
|
|
85
|
-
ANSI.white,
|
|
86
|
-
];
|
|
87
|
-
const color = colors[Math.min(level - 1, colors.length - 1)];
|
|
88
|
-
return `\n${color}${'#'.repeat(level)} ${text}${ANSI.reset}\n`;
|
|
89
|
-
},
|
|
77
|
+
// marked-terminal supplies styled text only here (including its prefix),
|
|
78
|
+
// unlike a marked renderer method, which also receives the heading level.
|
|
79
|
+
heading: (text) => `${ANSI.blueBold}${text}${ANSI.reset}`,
|
|
80
|
+
firstHeading: (text) => `${ANSI.magentaBold}${text}${ANSI.reset}`,
|
|
90
81
|
// Text emphasis
|
|
91
82
|
strong: (text) => `${ANSI.bold}${text}${ANSI.reset}`,
|
|
92
83
|
em: (text) => `${ANSI.italic}${text}${ANSI.reset}`,
|
|
@@ -51,6 +51,28 @@ export declare function readTextAtomic(filePath: string, fallback: string, optio
|
|
|
51
51
|
export declare function readJsonLinesAtomic<T>(filePath: string, fallback: T[], isValid: (value: unknown) => value is T): Promise<T[]>;
|
|
52
52
|
/** Reset the process-local warning guard; intended for isolated tests. */
|
|
53
53
|
export declare function resetAtomicReadWarningsForTests(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Outcome of a strictly read-only JSON read. `missing` is normal (no file);
|
|
56
|
+
* `corrupt` means the file exists but is empty or not valid JSON; `unreadable`
|
|
57
|
+
* means the file exists but could not be read (permissions, EISDIR, ...).
|
|
58
|
+
*/
|
|
59
|
+
export type ReadOnlyJsonOutcome<T> = {
|
|
60
|
+
status: 'ok';
|
|
61
|
+
value: T;
|
|
62
|
+
} | {
|
|
63
|
+
status: 'missing';
|
|
64
|
+
} | {
|
|
65
|
+
status: 'corrupt';
|
|
66
|
+
} | {
|
|
67
|
+
status: 'unreadable';
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Strictly read-only JSON reader for diagnostics. Never restores, renames,
|
|
71
|
+
* chmods, creates, or writes anything — not the primary file, not `.bak`,
|
|
72
|
+
* not `.tmp.*`. Never consults recovery candidates. Callers that need the
|
|
73
|
+
* historical recovery policy must keep using `readJsonAtomicSync`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function readJsonAtomicSyncReadOnly<T>(filePath: string, isValid?: (value: unknown) => value is T): ReadOnlyJsonOutcome<T>;
|
|
54
76
|
export interface CleanupOrphanedTemporariesOptions extends AtomicWriteOptions {
|
|
55
77
|
/**
|
|
56
78
|
* A temporary older than this (in ms) is considered orphaned and removed.
|
|
@@ -475,6 +475,35 @@ async function recoverJsonLines(filePath, fallback, isValid) {
|
|
|
475
475
|
export function resetAtomicReadWarningsForTests() {
|
|
476
476
|
warnedReadPaths.clear();
|
|
477
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* Strictly read-only JSON reader for diagnostics. Never restores, renames,
|
|
480
|
+
* chmods, creates, or writes anything — not the primary file, not `.bak`,
|
|
481
|
+
* not `.tmp.*`. Never consults recovery candidates. Callers that need the
|
|
482
|
+
* historical recovery policy must keep using `readJsonAtomicSync`.
|
|
483
|
+
*/
|
|
484
|
+
export function readJsonAtomicSyncReadOnly(filePath, isValid) {
|
|
485
|
+
let contents;
|
|
486
|
+
try {
|
|
487
|
+
contents = fs.readFileSync(filePath, 'utf8');
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
return isMissing(error) ? { status: 'missing' } : { status: 'unreadable' };
|
|
491
|
+
}
|
|
492
|
+
if (!contents.trim()) {
|
|
493
|
+
return { status: 'corrupt' };
|
|
494
|
+
}
|
|
495
|
+
let value;
|
|
496
|
+
try {
|
|
497
|
+
value = JSON.parse(contents);
|
|
498
|
+
}
|
|
499
|
+
catch {
|
|
500
|
+
return { status: 'corrupt' };
|
|
501
|
+
}
|
|
502
|
+
if (isValid && !isValid(value)) {
|
|
503
|
+
return { status: 'corrupt' };
|
|
504
|
+
}
|
|
505
|
+
return { status: 'ok', value: value };
|
|
506
|
+
}
|
|
478
507
|
const warnedCleanupPaths = new Set();
|
|
479
508
|
/**
|
|
480
509
|
* Remove stale `<filePath>.tmp.*` (and legacy `<filePath>.tmp`) siblings left
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Bounded byte storage retaining the beginning and most recent end of output. */
|
|
2
|
+
export declare class BoundedOutput {
|
|
3
|
+
readonly capacity: number;
|
|
4
|
+
private head;
|
|
5
|
+
private tail;
|
|
6
|
+
private observed;
|
|
7
|
+
constructor(capacity?: number);
|
|
8
|
+
get retainedBytes(): number;
|
|
9
|
+
get omittedBytes(): number;
|
|
10
|
+
append(chunk: string | Buffer): void;
|
|
11
|
+
text(): string;
|
|
12
|
+
/** Consume the pending preview; producers can continue into a fresh bounded buffer. */
|
|
13
|
+
drain(): string;
|
|
14
|
+
}
|
|
15
|
+
/** A rendered byte budget, including the omission marker, for model context. */
|
|
16
|
+
export declare function truncateOutput(text: string, maxBytes: number): string;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
2
|
+
/** Decode a retained UTF-8 segment without exposing a cut code point. */
|
|
3
|
+
function decode(bytes) {
|
|
4
|
+
let start = 0;
|
|
5
|
+
while (start < bytes.length && (bytes[start] & 0xc0) === 0x80)
|
|
6
|
+
start++;
|
|
7
|
+
return new StringDecoder('utf8').write(bytes.subarray(start));
|
|
8
|
+
}
|
|
9
|
+
/** Bounded byte storage retaining the beginning and most recent end of output. */
|
|
10
|
+
export class BoundedOutput {
|
|
11
|
+
capacity;
|
|
12
|
+
head = Buffer.alloc(0);
|
|
13
|
+
tail = Buffer.alloc(0);
|
|
14
|
+
observed = 0;
|
|
15
|
+
constructor(capacity = 256 * 1024) {
|
|
16
|
+
this.capacity = capacity;
|
|
17
|
+
if (!Number.isSafeInteger(capacity) || capacity < 1)
|
|
18
|
+
throw new Error('Output capacity must be a positive integer');
|
|
19
|
+
}
|
|
20
|
+
get retainedBytes() { return this.head.length + this.tail.length; }
|
|
21
|
+
get omittedBytes() { return this.observed - this.retainedBytes; }
|
|
22
|
+
append(chunk) {
|
|
23
|
+
let bytes = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
|
|
24
|
+
this.observed += bytes.length;
|
|
25
|
+
const headRemaining = Math.ceil(this.capacity / 2) - this.head.length;
|
|
26
|
+
if (headRemaining > 0) {
|
|
27
|
+
this.head = Buffer.concat([this.head, bytes.subarray(0, headRemaining)]);
|
|
28
|
+
bytes = bytes.subarray(headRemaining);
|
|
29
|
+
}
|
|
30
|
+
const tailCapacity = Math.floor(this.capacity / 2);
|
|
31
|
+
if (tailCapacity > 0 && bytes.length > 0) {
|
|
32
|
+
this.tail = bytes.length >= tailCapacity
|
|
33
|
+
? Buffer.from(bytes.subarray(-tailCapacity))
|
|
34
|
+
: Buffer.concat([this.tail.subarray(Math.max(0, this.tail.length + bytes.length - tailCapacity)), bytes]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
text() {
|
|
38
|
+
if (!this.omittedBytes)
|
|
39
|
+
return decode(Buffer.concat([this.head, this.tail]));
|
|
40
|
+
return `${decode(this.head)}\n[... ${this.omittedBytes} bytes omitted ...]\n${decode(this.tail)}`;
|
|
41
|
+
}
|
|
42
|
+
/** Consume the pending preview; producers can continue into a fresh bounded buffer. */
|
|
43
|
+
drain() {
|
|
44
|
+
const result = this.text();
|
|
45
|
+
this.head = Buffer.alloc(0);
|
|
46
|
+
this.tail = Buffer.alloc(0);
|
|
47
|
+
this.observed = 0;
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** A rendered byte budget, including the omission marker, for model context. */
|
|
52
|
+
export function truncateOutput(text, maxBytes) {
|
|
53
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)
|
|
54
|
+
throw new Error('Output budget must be a positive integer');
|
|
55
|
+
if (Buffer.byteLength(text) <= maxBytes)
|
|
56
|
+
return text;
|
|
57
|
+
if (maxBytes < 80)
|
|
58
|
+
return decode(Buffer.from(text).subarray(0, maxBytes));
|
|
59
|
+
const buffer = new BoundedOutput(maxBytes - 80);
|
|
60
|
+
buffer.append(text);
|
|
61
|
+
return buffer.text();
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=bounded-output.js.map
|
|
@@ -266,17 +266,17 @@ export declare const UserSettingsSchema: z.ZodObject<{
|
|
|
266
266
|
theme: "default" | "minimal" | "auto" | "dark" | "light" | "neon" | "pastel" | "matrix" | "ocean" | "sunset" | "high-contrast";
|
|
267
267
|
language: string;
|
|
268
268
|
model?: string | undefined;
|
|
269
|
-
shell?: string | undefined;
|
|
270
269
|
baseURL?: string | undefined;
|
|
270
|
+
shell?: string | undefined;
|
|
271
271
|
apiKey?: string | undefined;
|
|
272
272
|
editor?: string | undefined;
|
|
273
273
|
}, {
|
|
274
274
|
provider?: "custom" | "xai" | "anthropic" | "google" | "openai" | "lmstudio" | "ollama" | "local" | "mistral" | "gemini" | "grok" | "lm-studio" | "minimax" | "moonshot" | "claude" | "vllm" | "deepseek" | "qwen" | "openrouter" | "groq" | "together" | "fireworks" | "agy-cli" | "chatgpt" | "lemonade" | "ollama-cloud" | "novita" | "zai" | "kimi-coding" | "kimi-coding-cn" | "arcee" | "gmi" | "minimax-cn" | "alibaba" | "alibaba-coding-plan" | "kilocode" | "xiaomi" | "tencent-tokenhub" | "opencode-zen" | "opencode-go" | "huggingface" | "nvidia" | "omniroute" | "ai21" | "ant-ling" | "cerebras" | "cohere" | "deepinfra" | "featherless-ai" | "friendliai" | "hyperbolic" | "inception" | "inference-net" | "internlm" | "liquid" | "longcat" | "modelscope" | "nscale" | "openadapter" | "pioneer" | "reka" | "sambanova" | "sarvam" | "scaleway" | "tokenrouter" | "typhoon" | "zenmux" | "stepfun" | "azure" | "bedrock" | "copilot" | "novita-ai" | "glm" | "kimi" | "kimi-cn" | "moonshot-cn" | "arcee-ai" | "gmi-cloud" | "gmicloud" | "dashscope" | "alibaba-coding" | "kilo-code" | "mimo" | "tencent" | "tokenhub" | "opencode" | "hf" | "nvidia-nim" | undefined;
|
|
275
275
|
model?: string | undefined;
|
|
276
|
+
baseURL?: string | undefined;
|
|
276
277
|
models?: string[] | undefined;
|
|
277
278
|
shell?: string | undefined;
|
|
278
279
|
defaultModel?: string | undefined;
|
|
279
|
-
baseURL?: string | undefined;
|
|
280
280
|
apiKey?: string | undefined;
|
|
281
281
|
theme?: "default" | "minimal" | "auto" | "dark" | "light" | "neon" | "pastel" | "matrix" | "ocean" | "sunset" | "high-contrast" | undefined;
|
|
282
282
|
editor?: string | undefined;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Shared envelope: legacy SSH/ADB nodes and Android authentication coexist. */
|
|
2
|
+
export declare function readDeviceStoreFile(file: string): Record<string, unknown>;
|
|
3
|
+
/** Cross-process exclusion for the local CLI and server. Busy/crashed locks fail closed. */
|
|
4
|
+
export declare function updateDeviceStoreFile<T>(file: string, update: (data: Record<string, unknown>) => T): T;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, rmdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { writeJsonAtomicSync } from './atomic-write.js';
|
|
4
|
+
/** Shared envelope: legacy SSH/ADB nodes and Android authentication coexist. */
|
|
5
|
+
export function readDeviceStoreFile(file) {
|
|
6
|
+
try {
|
|
7
|
+
const value = JSON.parse(readFileSync(file, 'utf8'));
|
|
8
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
9
|
+
throw new Error('Invalid device store');
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (error.code === 'ENOENT')
|
|
15
|
+
return {};
|
|
16
|
+
// Never recover a stale backup: that could resurrect a revoked key.
|
|
17
|
+
throw new Error('Device store unavailable');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Cross-process exclusion for the local CLI and server. Busy/crashed locks fail closed. */
|
|
21
|
+
export function updateDeviceStoreFile(file, update) {
|
|
22
|
+
mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
|
|
23
|
+
const lock = `${file}.lock`;
|
|
24
|
+
try {
|
|
25
|
+
mkdirSync(lock, { mode: 0o700 });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error('Device store unavailable');
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const data = readDeviceStoreFile(file);
|
|
32
|
+
const result = update(data);
|
|
33
|
+
writeJsonAtomicSync(file, data, { mode: 0o600 });
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
rmdirSync(lock);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=device-store-file.js.map
|