@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
|
@@ -1595,6 +1595,8 @@ export async function registerAIMessageHandler(manager) {
|
|
|
1595
1595
|
let successfulLisaSelfieToolResult = false;
|
|
1596
1596
|
let shouldPersistChannelSession = Boolean(agent);
|
|
1597
1597
|
let telegramWidget;
|
|
1598
|
+
let companionMediaResult;
|
|
1599
|
+
let companionHistorySuffix;
|
|
1598
1600
|
if (prefetchedDirectResponse) {
|
|
1599
1601
|
response = prefetchedDirectResponse;
|
|
1600
1602
|
if (agent && !agent.recordTrustedExternalConversationTurn(agentInput, response)) {
|
|
@@ -1632,16 +1634,34 @@ export async function registerAIMessageHandler(manager) {
|
|
|
1632
1634
|
sharedPhotos: companionPhotos?.photos.length ?? 0,
|
|
1633
1635
|
});
|
|
1634
1636
|
try {
|
|
1637
|
+
let companionIdentity;
|
|
1638
|
+
if (channel.type === 'telegram') {
|
|
1639
|
+
const { resolveCompanionIdentity } = await import('../../companion/companion-identity.js');
|
|
1640
|
+
const telegramChannel = channel;
|
|
1641
|
+
companionIdentity = resolveCompanionIdentity({
|
|
1642
|
+
channel: 'telegram',
|
|
1643
|
+
chatId: message.channel.id,
|
|
1644
|
+
senderId: message.sender?.id,
|
|
1645
|
+
senderUsername: message.sender?.username,
|
|
1646
|
+
allowedUsers: telegramChannel.config?.allowedUsers ?? [],
|
|
1647
|
+
env: process.env,
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1635
1650
|
const generated = await runCompanionChannelTurn({
|
|
1636
1651
|
apiKey: effectiveRuntime.apiKey,
|
|
1637
1652
|
baseUrl: effectiveRuntime.baseUrl,
|
|
1638
1653
|
model: effectiveRuntime.model,
|
|
1639
1654
|
messages: companionMessages,
|
|
1640
1655
|
signal: turn.signal,
|
|
1656
|
+
...(companionIdentity ? { identity: companionIdentity } : {}),
|
|
1657
|
+
surface: channel.type,
|
|
1658
|
+
env: process.env,
|
|
1641
1659
|
});
|
|
1642
1660
|
turn.throwIfAborted();
|
|
1643
1661
|
response = generated.text;
|
|
1644
1662
|
hasGeneratedResponse = response.trim() !== '';
|
|
1663
|
+
companionMediaResult = generated.media;
|
|
1664
|
+
companionHistorySuffix = generated.historySuffix;
|
|
1645
1665
|
if (hasSharedPhotos && companionPhotos) {
|
|
1646
1666
|
// The album write is deliberately after the reply: a full disk must
|
|
1647
1667
|
// cost the memory, never the reaction.
|
|
@@ -1860,7 +1880,35 @@ export async function registerAIMessageHandler(manager) {
|
|
|
1860
1880
|
turn.throwIfAborted();
|
|
1861
1881
|
turn.phase('delivery');
|
|
1862
1882
|
deliveryState = 'started';
|
|
1863
|
-
if (channel.type === 'telegram' && response.trim() &&
|
|
1883
|
+
if (channel.type === 'telegram' && response.trim() && companionMediaResult && companionMediaResult.length > 0) {
|
|
1884
|
+
const media = companionMediaResult[0];
|
|
1885
|
+
if (media) {
|
|
1886
|
+
const pathMod = await import('path');
|
|
1887
|
+
const ext = pathMod.extname(media.imagePath).slice(1) || 'png';
|
|
1888
|
+
const result = await channel.send({
|
|
1889
|
+
channelId: message.channel.id,
|
|
1890
|
+
content: response,
|
|
1891
|
+
replyTo: message.id,
|
|
1892
|
+
attachments: [
|
|
1893
|
+
{
|
|
1894
|
+
type: 'image',
|
|
1895
|
+
filePath: media.imagePath,
|
|
1896
|
+
fileName: pathMod.basename(media.imagePath),
|
|
1897
|
+
mimeType: ext === 'jpg' || ext === 'jpeg' ? 'image/jpeg' : `image/${ext}`,
|
|
1898
|
+
},
|
|
1899
|
+
],
|
|
1900
|
+
});
|
|
1901
|
+
delivered = result?.success === true;
|
|
1902
|
+
deliveredChunks = delivered ? 1 : 0;
|
|
1903
|
+
if (delivered)
|
|
1904
|
+
deliveredAssistantContent = response;
|
|
1905
|
+
if (delivered)
|
|
1906
|
+
deliveryMode = 'telegram-photo';
|
|
1907
|
+
else
|
|
1908
|
+
deliveryMode = 'failed';
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
else if (channel.type === 'telegram' && response.trim() && telegramWidget) {
|
|
1864
1912
|
const result = await channel.send({
|
|
1865
1913
|
channelId: message.channel.id,
|
|
1866
1914
|
content: response,
|
|
@@ -2070,7 +2118,10 @@ export async function registerAIMessageHandler(manager) {
|
|
|
2070
2118
|
turn.throwIfAborted();
|
|
2071
2119
|
turn.phase('persistence');
|
|
2072
2120
|
if (useCompanionProfile && response.trim()) {
|
|
2073
|
-
|
|
2121
|
+
const recordedResponse = companionHistorySuffix
|
|
2122
|
+
? `${response}${companionHistorySuffix}`
|
|
2123
|
+
: response;
|
|
2124
|
+
rememberCompanionChannelTurn(sessionKey, message.content, recordedResponse);
|
|
2074
2125
|
}
|
|
2075
2126
|
if (shouldPersistChannelSession && agent)
|
|
2076
2127
|
await persistChannelSession(agent, sessionKey);
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handlers for exporting sessions, conversations, and tool results
|
|
5
5
|
*/
|
|
6
|
+
import type { ChatEntry } from '../../agent/types.js';
|
|
6
7
|
import { CommandHandlerResult } from './branch-handlers.js';
|
|
7
8
|
/**
|
|
8
9
|
* Handle /export command
|
|
9
|
-
* Export current or
|
|
10
|
+
* Export the current conversation, or a saved session with session:<id>
|
|
10
11
|
*/
|
|
11
|
-
export declare function handleExport(args: string[]): Promise<CommandHandlerResult>;
|
|
12
|
+
export declare function handleExport(args: string[], conversationHistory?: ChatEntry[], currentModel?: string): Promise<CommandHandlerResult>;
|
|
12
13
|
/**
|
|
13
14
|
* Handle /export-list command
|
|
14
15
|
* List all exported files
|
|
@@ -3,54 +3,81 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handlers for exporting sessions, conversations, and tool results
|
|
5
5
|
*/
|
|
6
|
+
import { initializeDatabase } from '../../database/database-manager.js';
|
|
6
7
|
import { getExportManager } from '../../utils/export-manager.js';
|
|
7
|
-
|
|
8
|
+
function reply(content) {
|
|
9
|
+
return { handled: true, entry: { type: 'assistant', content, timestamp: new Date() } };
|
|
10
|
+
}
|
|
11
|
+
/** Map the visible transcript to export messages; UI-only entries are skipped. */
|
|
12
|
+
function chatEntriesToMessages(history) {
|
|
13
|
+
const messages = [];
|
|
14
|
+
for (const entry of history) {
|
|
15
|
+
if (entry.type === 'user' || entry.type === 'assistant') {
|
|
16
|
+
messages.push({ role: entry.type, content: entry.content, timestamp: entry.timestamp });
|
|
17
|
+
}
|
|
18
|
+
else if (entry.type === 'tool_result') {
|
|
19
|
+
messages.push({
|
|
20
|
+
role: 'tool',
|
|
21
|
+
content: entry.content,
|
|
22
|
+
timestamp: entry.timestamp,
|
|
23
|
+
toolName: entry.toolCall?.function?.name ?? 'tool',
|
|
24
|
+
toolCallId: entry.toolCall?.id,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return messages;
|
|
29
|
+
}
|
|
8
30
|
/**
|
|
9
31
|
* Handle /export command
|
|
10
|
-
* Export current or
|
|
32
|
+
* Export the current conversation, or a saved session with session:<id>
|
|
11
33
|
*/
|
|
12
|
-
export async function handleExport(args) {
|
|
34
|
+
export async function handleExport(args, conversationHistory = [], currentModel) {
|
|
13
35
|
const exportManager = getExportManager();
|
|
14
|
-
const sessionRepo = getSessionRepository();
|
|
15
36
|
// Parse arguments
|
|
16
37
|
const format = args.find(a => ['json', 'markdown', 'html', 'text'].includes(a)) || 'markdown';
|
|
17
38
|
const sessionIdArg = args.find(a => a.startsWith('session:'))?.split(':')[1];
|
|
18
39
|
const includeSecrets = args.includes('--include-secrets');
|
|
19
40
|
const noToolCalls = args.includes('--no-tools');
|
|
20
41
|
const noMetadata = args.includes('--no-metadata');
|
|
21
|
-
|
|
22
|
-
|
|
42
|
+
const options = {
|
|
43
|
+
redactSecrets: !includeSecrets,
|
|
44
|
+
includeToolCalls: !noToolCalls,
|
|
45
|
+
includeMetadata: !noMetadata,
|
|
46
|
+
};
|
|
47
|
+
let result;
|
|
23
48
|
if (sessionIdArg) {
|
|
24
|
-
|
|
49
|
+
// Saved sessions live in the SQLite session database, which the
|
|
50
|
+
// interactive CLI does not open at startup.
|
|
51
|
+
try {
|
|
52
|
+
await initializeDatabase();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return reply(`Failed to export session ${sessionIdArg}: session database unavailable (${error instanceof Error ? error.message : String(error)}).`);
|
|
56
|
+
}
|
|
57
|
+
result = await exportManager.exportSession(sessionIdArg, format, options);
|
|
25
58
|
}
|
|
26
59
|
else {
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
return
|
|
32
|
-
handled: true,
|
|
33
|
-
entry: {
|
|
34
|
-
type: 'assistant',
|
|
35
|
-
content: 'No sessions found to export.',
|
|
36
|
-
timestamp: new Date(),
|
|
37
|
-
},
|
|
38
|
-
};
|
|
60
|
+
// The current session is the conversation on screen, not the most recent
|
|
61
|
+
// database row (which may belong to another project).
|
|
62
|
+
const messages = chatEntriesToMessages(conversationHistory);
|
|
63
|
+
if (messages.length === 0) {
|
|
64
|
+
return reply('Nothing to export yet: the current conversation is empty.\n\nSend a message first, or export a saved session with /export <format> session:<id>.');
|
|
39
65
|
}
|
|
40
|
-
|
|
66
|
+
result = await exportManager.exportConversationData({
|
|
67
|
+
title: 'Code Buddy conversation',
|
|
68
|
+
model: currentModel,
|
|
69
|
+
startTime: messages[0]?.timestamp,
|
|
70
|
+
endTime: messages[messages.length - 1]?.timestamp,
|
|
71
|
+
messages,
|
|
72
|
+
metadata: { projectPath: process.cwd(), messageCount: messages.length },
|
|
73
|
+
}, format, options);
|
|
41
74
|
}
|
|
42
|
-
// Export session
|
|
43
|
-
const result = await exportManager.exportSession(sessionId, format, {
|
|
44
|
-
redactSecrets: !includeSecrets,
|
|
45
|
-
includeToolCalls: !noToolCalls,
|
|
46
|
-
includeMetadata: !noMetadata,
|
|
47
|
-
});
|
|
48
75
|
if (result.success && result.filePath) {
|
|
49
76
|
return {
|
|
50
77
|
handled: true,
|
|
51
78
|
entry: {
|
|
52
79
|
type: 'assistant',
|
|
53
|
-
content: `Session exported successfully!
|
|
80
|
+
content: `${sessionIdArg ? `Session ${sessionIdArg}` : 'Current conversation'} exported successfully!
|
|
54
81
|
|
|
55
82
|
**Format:** ${format}
|
|
56
83
|
**File:** ${result.filePath}
|
|
@@ -68,7 +95,7 @@ cat "${result.filePath}"
|
|
|
68
95
|
handled: true,
|
|
69
96
|
entry: {
|
|
70
97
|
type: 'assistant',
|
|
71
|
-
content: `Failed to export session: ${result.error}`,
|
|
98
|
+
content: `Failed to export ${sessionIdArg ? `session ${sessionIdArg}` : 'the current conversation'}: ${result.error}`,
|
|
72
99
|
timestamp: new Date(),
|
|
73
100
|
},
|
|
74
101
|
};
|
|
@@ -311,7 +311,10 @@ export async function handleSearch(args) {
|
|
|
311
311
|
try {
|
|
312
312
|
const cwd = process.cwd();
|
|
313
313
|
let output = '';
|
|
314
|
-
|
|
314
|
+
// Explicit `.` path: without one, ripgrep searches stdin whenever stdin is
|
|
315
|
+
// not a TTY (every non-interactive spawn), so real matches were reported as
|
|
316
|
+
// "No matches" (status 1).
|
|
317
|
+
const rgResult = runCommand('rg', ['--line-number', '--no-heading', '--color=never', '--max-count=20', '--', query, '.'], { cwd, timeoutMs: 10000 });
|
|
315
318
|
if (rgResult.success) {
|
|
316
319
|
output = rgResult.output;
|
|
317
320
|
}
|
|
@@ -586,6 +589,7 @@ function createProgressBar(percent, width) {
|
|
|
586
589
|
function runCommand(command, args, { cwd, timeoutMs, env }) {
|
|
587
590
|
const result = spawnSync(command, args, {
|
|
588
591
|
cwd,
|
|
592
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
589
593
|
encoding: 'utf-8',
|
|
590
594
|
maxBuffer: 5 * 1024 * 1024,
|
|
591
595
|
timeout: timeoutMs,
|
|
@@ -1,32 +1,40 @@
|
|
|
1
|
+
// Written as the user's own request about their own work. The previous wording
|
|
2
|
+
// (role orders addressed to the assistant: "Mène un interrogatoire", "Exige",
|
|
3
|
+
// "Ne flatte pas l'auteur", "ce qui ment") made qwen3:4b answer the injection
|
|
4
|
+
// refusal sentence in the real CLI (recette 2026-09-14), without any tool call.
|
|
1
5
|
function buildPrompt(target, yolo) {
|
|
2
6
|
const scope = target
|
|
3
|
-
? `Sujet ciblé
|
|
4
|
-
: 'Sujet par défaut :
|
|
7
|
+
? `Sujet ciblé : ${target}`
|
|
8
|
+
: 'Sujet par défaut : mon travail récent dans ce dépôt.';
|
|
9
|
+
// The recent work includes uncommitted changes, and HEAD~1 does not exist in
|
|
10
|
+
// a single-commit repository: inspect the working tree first.
|
|
11
|
+
const gitInspection = 'git status --short, git diff (modifications non indexées), git diff --cached (modifications indexées) et git log -5 --oneline ; git diff HEAD~1 seulement si le dépôt compte au moins deux commits';
|
|
5
12
|
const baseInstructions = target
|
|
6
|
-
? `Examine d'abord ce sujet
|
|
7
|
-
:
|
|
13
|
+
? `Examine d'abord ce sujet avec les outils disponibles : ${target}. Utilise aussi le contexte git utile et la liste des fichiers modifiés : ${gitInspection}.`
|
|
14
|
+
: `Examine d'abord mon travail récent et la liste des fichiers modifiés avec les outils disponibles : ${gitInspection}.`;
|
|
8
15
|
if (yolo) {
|
|
9
|
-
return
|
|
16
|
+
return `J'ai lancé /grill-me --yolo : je veux une revue technique de mon propre travail en mode ROAST intégral.
|
|
17
|
+
|
|
18
|
+
${scope}
|
|
10
19
|
|
|
11
20
|
${baseInstructions}
|
|
12
21
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Si une critique n'est pas étayée par le dépôt ou le diff, ne la formule pas.`;
|
|
22
|
+
Ensuite, sois brutal et sarcastique avec moi, sans politesse ni précautions diplomatiques.
|
|
23
|
+
Chaque critique doit rester techniquement exacte, vérifiable et actionnable : cite les fichiers, diffs, noms, tests ou choix qui la justifient.
|
|
24
|
+
Vise mes choix discutables, la dette introduite, les tests manquants, les cas limites ignorés, la sécurité, les abstractions inutiles et les noms trompeurs.
|
|
25
|
+
Pour chaque critique, demande-moi quelle preuve, quel test ou quel correctif fermera le sujet.
|
|
26
|
+
N'invente rien : une critique que le dépôt ou le diff ne prouve pas ne doit pas être formulée.`;
|
|
19
27
|
}
|
|
20
|
-
return
|
|
28
|
+
return `J'ai lancé /grill-me : je veux une revue technique exigeante de mon propre travail.
|
|
29
|
+
|
|
30
|
+
${scope}
|
|
21
31
|
|
|
22
32
|
${baseInstructions}
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Ajoute ensuite 3 risques classés par sévérité, avec pour chacun l'impact, la probabilité et l'action minimale pour le réduire.
|
|
29
|
-
Ne flatte pas l'auteur : aide-le à voir ce qui casse, ce qui ment et ce qui manque.`;
|
|
34
|
+
Ensuite, pose-moi 5 à 7 questions difficiles et précises sur mes choix discutables, la dette introduite, les tests manquants, les cas limites ignorés, la sécurité et les noms trompeurs.
|
|
35
|
+
Chaque question doit viser des lignes, fichiers, comportements ou décisions observables, pas des généralités, et me demander une preuve concrète.
|
|
36
|
+
Termine par 3 risques classés par sévérité, avec pour chacun l'impact, la probabilité et l'action minimale pour le réduire.
|
|
37
|
+
Reste franc et constructif, sans compliments inutiles : aide-moi à voir ce qui casse, ce qui est inexact et ce qui manque.`;
|
|
30
38
|
}
|
|
31
39
|
export async function handleGrillMe(args) {
|
|
32
40
|
const remainingArgs = args.filter(arg => arg !== '--yolo');
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { ChatEntry } from "../../agent/codebuddy-agent.js";
|
|
2
|
+
export interface MemoryCommandContext {
|
|
3
|
+
cwd?: string;
|
|
4
|
+
botId?: string;
|
|
5
|
+
}
|
|
2
6
|
export interface CommandHandlerResult {
|
|
3
7
|
handled: boolean;
|
|
4
8
|
entry?: ChatEntry;
|
|
@@ -9,11 +13,11 @@ export interface CommandHandlerResult {
|
|
|
9
13
|
/**
|
|
10
14
|
* Memory - Manage persistent memory using PersistentMemoryManager (Markdown) and EnhancedMemory (SQLite/Vector)
|
|
11
15
|
*/
|
|
12
|
-
export declare function handleMemory(args: string[]): Promise<CommandHandlerResult>;
|
|
16
|
+
export declare function handleMemory(args: string[], context?: MemoryCommandContext): Promise<CommandHandlerResult>;
|
|
13
17
|
/**
|
|
14
18
|
* Remember - Quick memory store using PersistentMemoryManager and EnhancedMemory
|
|
15
19
|
*/
|
|
16
|
-
export declare function handleRemember(args: string[]): Promise<CommandHandlerResult>;
|
|
20
|
+
export declare function handleRemember(args: string[], context?: MemoryCommandContext): Promise<CommandHandlerResult>;
|
|
17
21
|
/**
|
|
18
22
|
* Scan Todos - Find AI-directed comments
|
|
19
23
|
*/
|
|
@@ -27,17 +27,37 @@ function formatTimeAgo(date, now = new Date()) {
|
|
|
27
27
|
const yr = Math.floor(day / 365);
|
|
28
28
|
return `${yr} year${yr === 1 ? "" : "s"} ago`;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Report a remember operation honestly: the persistent write is the primary
|
|
32
|
+
* result; fact reconciliation and the semantic index are secondary and their
|
|
33
|
+
* failures are shown without hiding (or overstating) the saved memory.
|
|
34
|
+
*/
|
|
35
|
+
async function describeRememberOutcome(write, requestedKey, scope, storeSemantic) {
|
|
36
|
+
const lines = [`✅ Remembered: "${write?.key ?? requestedKey}" in persistent ${scope} memory.`];
|
|
37
|
+
if (write?.reconciliation?.status === "failed") {
|
|
38
|
+
lines.push(`⚠️ Fact reconciliation failed (${write.reconciliation.reason ?? "unknown error"}); the memory was saved directly and existing memories were kept unchanged.`);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
await storeSemantic();
|
|
42
|
+
lines.push("Semantic index updated.");
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
lines.push(`⚠️ Semantic index not updated: ${getErrorMessage(error)}`);
|
|
46
|
+
}
|
|
47
|
+
return lines.join("\n");
|
|
48
|
+
}
|
|
30
49
|
function clip(text, max = 180) {
|
|
31
50
|
return text.length > max ? text.slice(0, max - 1) + "…" : text;
|
|
32
51
|
}
|
|
33
52
|
/**
|
|
34
53
|
* Memory - Manage persistent memory using PersistentMemoryManager (Markdown) and EnhancedMemory (SQLite/Vector)
|
|
35
54
|
*/
|
|
36
|
-
export async function handleMemory(args) {
|
|
55
|
+
export async function handleMemory(args, context) {
|
|
37
56
|
const enhancedMemory = getEnhancedMemory();
|
|
38
|
-
const persistentMemory = getMemoryManager();
|
|
57
|
+
const persistentMemory = getMemoryManager(undefined, context?.botId, context?.cwd);
|
|
39
58
|
const action = args[0]?.toLowerCase() || 'list';
|
|
40
59
|
try {
|
|
60
|
+
await persistentMemory.initialize();
|
|
41
61
|
let content;
|
|
42
62
|
switch (action) {
|
|
43
63
|
case "recall":
|
|
@@ -151,14 +171,13 @@ export async function handleMemory(args) {
|
|
|
151
171
|
: "project";
|
|
152
172
|
const value = args.slice(2).join(" ");
|
|
153
173
|
// Store in both for redundancy and better retrieval
|
|
154
|
-
await persistentMemory.remember(key, value, { scope, category: "custom" });
|
|
155
|
-
await enhancedMemory.store({
|
|
174
|
+
const write = await persistentMemory.remember(key, value, { scope, category: "custom" });
|
|
175
|
+
content = await describeRememberOutcome(write, key, scope, () => enhancedMemory.store({
|
|
156
176
|
type: 'fact',
|
|
157
177
|
content: `${key}: ${value}`,
|
|
158
178
|
tags: [key, scope],
|
|
159
179
|
importance: 0.8
|
|
160
|
-
});
|
|
161
|
-
content = `✅ Remembered: "${key}" in persistent ${scope} memory and semantic index.`;
|
|
180
|
+
}));
|
|
162
181
|
}
|
|
163
182
|
else {
|
|
164
183
|
content = `Usage: /memory remember <key> <content> [project|user]`;
|
|
@@ -231,7 +250,7 @@ export async function handleMemory(args) {
|
|
|
231
250
|
: undefined;
|
|
232
251
|
const rawLimit = parseInt(args[status ? 2 : 1] ?? "20", 10);
|
|
233
252
|
const limit = Math.min(50, Math.max(1, Number.isFinite(rawLimit) ? rawLimit : 20));
|
|
234
|
-
const candidates = getMemoryCandidateQueue(process.cwd()).list(status).slice(0, limit);
|
|
253
|
+
const candidates = getMemoryCandidateQueue(context?.cwd ?? process.cwd(), context?.botId).list(status).slice(0, limit);
|
|
235
254
|
if (candidates.length === 0) {
|
|
236
255
|
content = status ? `No ${status} memory candidates.` : "No memory candidates yet.";
|
|
237
256
|
}
|
|
@@ -268,7 +287,7 @@ export async function handleMemory(args) {
|
|
|
268
287
|
}
|
|
269
288
|
const reviewedBy = args.slice(2).join(" ").trim() || "user";
|
|
270
289
|
const { getMemoryCandidateQueue } = await import("../../memory/memory-candidate-queue.js");
|
|
271
|
-
const { candidate, write } = await getMemoryCandidateQueue(process.cwd()).accept(id, { reviewedBy });
|
|
290
|
+
const { candidate, write } = await getMemoryCandidateQueue(context?.cwd ?? process.cwd(), context?.botId).accept(id, { reviewedBy });
|
|
272
291
|
content = `✅ Accepted ${candidate.id} into ${candidate.scope} memory as "${candidate.key}".\n` +
|
|
273
292
|
`Write status: ${write.status}. Capacity: ${write.usage.used}/${write.usage.limit} chars (${write.usage.percent}%).`;
|
|
274
293
|
break;
|
|
@@ -282,7 +301,7 @@ export async function handleMemory(args) {
|
|
|
282
301
|
}
|
|
283
302
|
const reason = args.slice(2).join(" ").trim();
|
|
284
303
|
const { getMemoryCandidateQueue } = await import("../../memory/memory-candidate-queue.js");
|
|
285
|
-
const candidate = getMemoryCandidateQueue(process.cwd()).reject(id, {
|
|
304
|
+
const candidate = getMemoryCandidateQueue(context?.cwd ?? process.cwd(), context?.botId).reject(id, {
|
|
286
305
|
reviewedBy: "user",
|
|
287
306
|
...(reason ? { reason } : {}),
|
|
288
307
|
});
|
|
@@ -319,7 +338,7 @@ export async function handleMemory(args) {
|
|
|
319
338
|
/**
|
|
320
339
|
* Remember - Quick memory store using PersistentMemoryManager and EnhancedMemory
|
|
321
340
|
*/
|
|
322
|
-
export async function handleRemember(args) {
|
|
341
|
+
export async function handleRemember(args, context) {
|
|
323
342
|
if (args.length < 2) {
|
|
324
343
|
return {
|
|
325
344
|
handled: true,
|
|
@@ -346,20 +365,21 @@ export async function handleRemember(args) {
|
|
|
346
365
|
: "project";
|
|
347
366
|
const value = args.slice(1).join(" ");
|
|
348
367
|
try {
|
|
349
|
-
const persistentMemory = getMemoryManager();
|
|
368
|
+
const persistentMemory = getMemoryManager(undefined, context?.botId, context?.cwd);
|
|
350
369
|
const enhancedMemory = getEnhancedMemory();
|
|
351
|
-
await persistentMemory.
|
|
352
|
-
await
|
|
370
|
+
await persistentMemory.initialize();
|
|
371
|
+
const write = await persistentMemory.remember(key, value, { scope, category: "custom" });
|
|
372
|
+
const content = await describeRememberOutcome(write, key, scope, () => enhancedMemory.store({
|
|
353
373
|
type: 'fact',
|
|
354
374
|
content: `${key}: ${value}`,
|
|
355
375
|
tags: [key, scope],
|
|
356
376
|
importance: 0.8
|
|
357
|
-
});
|
|
377
|
+
}));
|
|
358
378
|
return {
|
|
359
379
|
handled: true,
|
|
360
380
|
entry: {
|
|
361
381
|
type: "assistant",
|
|
362
|
-
content
|
|
382
|
+
content,
|
|
363
383
|
timestamp: new Date(),
|
|
364
384
|
},
|
|
365
385
|
};
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* - __RESTORE_CHECKPOINT__ - /restore
|
|
15
15
|
*/
|
|
16
16
|
import type { CommandHandlerResult } from './branch-handlers.js';
|
|
17
|
-
export declare function handleChangeModel(args: string[]): Promise<CommandHandlerResult>;
|
|
17
|
+
export declare function handleChangeModel(args: string[], activeModel?: string): Promise<CommandHandlerResult>;
|
|
18
18
|
export declare function handleChangeMode(args: string[]): Promise<CommandHandlerResult>;
|
|
19
19
|
export declare function handleClearChat(): CommandHandlerResult;
|
|
20
20
|
export declare function handleColab(args: string[]): Promise<CommandHandlerResult>;
|
|
@@ -24,5 +24,5 @@ export declare function handleListCheckpoints(_args: string[]): Promise<CommandH
|
|
|
24
24
|
export declare function handleRestoreCheckpoint(args: string[]): Promise<CommandHandlerResult>;
|
|
25
25
|
export declare function handleInitGrok(args?: string[]): Promise<CommandHandlerResult>;
|
|
26
26
|
export declare function handleReinitGrok(): Promise<CommandHandlerResult>;
|
|
27
|
-
export declare function handleStatus(): Promise<CommandHandlerResult>;
|
|
27
|
+
export declare function handleStatus(activeModel?: string): Promise<CommandHandlerResult>;
|
|
28
28
|
export declare function handleNew(args: string[]): Promise<CommandHandlerResult>;
|
|
@@ -17,14 +17,14 @@ import { handleColabCommand } from './colab-handler.js';
|
|
|
17
17
|
// ============================================================================
|
|
18
18
|
// /model - Change Model
|
|
19
19
|
// ============================================================================
|
|
20
|
-
export async function handleChangeModel(args) {
|
|
20
|
+
export async function handleChangeModel(args, activeModel) {
|
|
21
21
|
const { getSupportedModels, getModelInfo, suggestModel } = await import('../../utils/model-utils.js');
|
|
22
22
|
const { getSettingsManager } = await import('../../utils/settings-manager.js');
|
|
23
23
|
const modelName = args[0];
|
|
24
24
|
const settingsManager = getSettingsManager();
|
|
25
25
|
// If no model specified, show current model and list available models
|
|
26
26
|
if (!modelName || modelName === 'list') {
|
|
27
|
-
const currentModel =
|
|
27
|
+
const currentModel = activeModel ?? settingsManager.getCurrentModel();
|
|
28
28
|
const supportedModels = getSupportedModels();
|
|
29
29
|
// Group models by provider
|
|
30
30
|
const modelsByProvider = {};
|
|
@@ -803,13 +803,13 @@ function formatStatusTimeAgo(date, now = new Date()) {
|
|
|
803
803
|
const day = Math.floor(hr / 24);
|
|
804
804
|
return `${day}d ago`;
|
|
805
805
|
}
|
|
806
|
-
export async function handleStatus() {
|
|
806
|
+
export async function handleStatus(activeModel) {
|
|
807
807
|
const lines = [];
|
|
808
808
|
lines.push('Status Dashboard');
|
|
809
809
|
lines.push('='.repeat(50));
|
|
810
810
|
lines.push('');
|
|
811
811
|
// Current model
|
|
812
|
-
const currentModel =
|
|
812
|
+
const currentModel = activeModel ?? (await import('../../utils/settings-manager.js')).getSettingsManager().getCurrentModel();
|
|
813
813
|
lines.push(` Model: ${currentModel}`);
|
|
814
814
|
// Agent mode
|
|
815
815
|
try {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /resources — read-only view of the explicit resource catalog (P8).
|
|
3
|
+
*
|
|
4
|
+
* Reads ~/.codebuddy/resources/catalog.json through ResourceCatalog.list():
|
|
5
|
+
* no probe, no network, no write, no dispatch. Shows endpoint REFERENCES
|
|
6
|
+
* (environment variable names), never resolved URLs or fingerprints.
|
|
7
|
+
*/
|
|
8
|
+
import type { CommandHandlerResult } from './branch-handlers.js';
|
|
9
|
+
import { ResourceCatalog, type PublicResourceStatus } from '../../fleet/resource-catalog.js';
|
|
10
|
+
export declare const RESOURCES_EMPTY_HINT: string;
|
|
11
|
+
export declare function formatResourcesTable(resources: PublicResourceStatus[], now?: number): string;
|
|
12
|
+
export declare function handleResources(catalog?: ResourceCatalog, now?: () => number): Promise<CommandHandlerResult>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /resources — read-only view of the explicit resource catalog (P8).
|
|
3
|
+
*
|
|
4
|
+
* Reads ~/.codebuddy/resources/catalog.json through ResourceCatalog.list():
|
|
5
|
+
* no probe, no network, no write, no dispatch. Shows endpoint REFERENCES
|
|
6
|
+
* (environment variable names), never resolved URLs or fingerprints.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import { publicResourceStatus, ResourceCatalog } from '../../fleet/resource-catalog.js';
|
|
10
|
+
export const RESOURCES_EMPTY_HINT = 'No resource catalog yet. Declare one with `buddy resources add <file.json>` (fields: `buddy resources schema`), '
|
|
11
|
+
+ 'then refresh its health explicitly with `buddy resources probe <id>`.';
|
|
12
|
+
function textResult(content) {
|
|
13
|
+
return { handled: true, entry: { type: 'assistant', content, timestamp: new Date() } };
|
|
14
|
+
}
|
|
15
|
+
function age(from, now) {
|
|
16
|
+
if (from === null)
|
|
17
|
+
return 'never';
|
|
18
|
+
const minutes = Math.max(0, Math.round((now - from) / 60_000));
|
|
19
|
+
if (minutes < 1)
|
|
20
|
+
return 'just now';
|
|
21
|
+
if (minutes < 120)
|
|
22
|
+
return `${minutes} min ago`;
|
|
23
|
+
return `${Math.round(minutes / 60)} h ago`;
|
|
24
|
+
}
|
|
25
|
+
export function formatResourcesTable(resources, now = Date.now()) {
|
|
26
|
+
const lines = [`Resources (${resources.length}) — read-only, no probe`, ''];
|
|
27
|
+
for (const entry of resources) {
|
|
28
|
+
const r = entry.resource;
|
|
29
|
+
const use = r.permissions.use ? 'use' : 'no-use';
|
|
30
|
+
const probe = r.permissions.probe ? 'probe' : 'no-probe';
|
|
31
|
+
lines.push(` ${r.id} [${r.kind}] on ${r.hostId}`);
|
|
32
|
+
lines.push(` state: ${entry.state} (${entry.reason}), checked ${age(entry.checkedAt, now)}`);
|
|
33
|
+
lines.push(` capabilities: ${r.declaredCapabilities.join(', ')} · endpoint ref: ${r.endpointRef} · ${use}, ${probe}`);
|
|
34
|
+
}
|
|
35
|
+
lines.push('', 'Health is not proof of usage and load is unknown. Refresh with `buddy resources probe <id>`.');
|
|
36
|
+
return lines.join('\n');
|
|
37
|
+
}
|
|
38
|
+
export async function handleResources(catalog = new ResourceCatalog(), now = Date.now) {
|
|
39
|
+
let resources;
|
|
40
|
+
try {
|
|
41
|
+
resources = (await catalog.list()).map(publicResourceStatus);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
const code = error instanceof Error ? error.message : 'INVALID_CATALOG';
|
|
45
|
+
return textResult(`Resource catalog unreadable (${code}). Nothing was changed; inspect ${catalog.filename}.`);
|
|
46
|
+
}
|
|
47
|
+
if (resources.length === 0) {
|
|
48
|
+
return textResult(fs.existsSync(catalog.filename) ? `The resource catalog is empty. ${RESOURCES_EMPTY_HINT.replace(/^No resource catalog yet\. /, '')}` : RESOURCES_EMPTY_HINT);
|
|
49
|
+
}
|
|
50
|
+
return textResult(formatResourcesTable(resources, now()));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=resources-handler.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Starter Pack Slash Command Handler
|
|
3
3
|
*
|
|
4
|
-
* /starter
|
|
4
|
+
* /starter, /starter list - List all starter packs grouped by language
|
|
5
5
|
* /starter <name> - Activate a specific starter pack (name or alias)
|
|
6
6
|
* /starter search <q> - Search starters by keyword
|
|
7
7
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Starter Pack Slash Command Handler
|
|
3
3
|
*
|
|
4
|
-
* /starter
|
|
4
|
+
* /starter, /starter list - List all starter packs grouped by language
|
|
5
5
|
* /starter <name> - Activate a specific starter pack (name or alias)
|
|
6
6
|
* /starter search <q> - Search starters by keyword
|
|
7
7
|
*/
|
|
@@ -25,7 +25,16 @@ const LANGUAGE_FAMILIES = {
|
|
|
25
25
|
function formatStarterList() {
|
|
26
26
|
const starters = getStarterPacks();
|
|
27
27
|
if (starters.length === 0) {
|
|
28
|
-
|
|
28
|
+
// No starter pack ships with the package today: say where packs are found
|
|
29
|
+
// instead of implying a loading failure.
|
|
30
|
+
return [
|
|
31
|
+
'No starter packs are installed.',
|
|
32
|
+
'',
|
|
33
|
+
'Starter packs are SKILL.md skills tagged "starter", discovered in:',
|
|
34
|
+
' .codebuddy/skills/ (this project)',
|
|
35
|
+
' ~/.codebuddy/skills/ (user)',
|
|
36
|
+
' the bundled skills directory shipped with Code Buddy',
|
|
37
|
+
].join('\n');
|
|
29
38
|
}
|
|
30
39
|
const lines = [
|
|
31
40
|
`Starter Packs (${starters.length} available)`,
|
|
@@ -82,6 +91,27 @@ export async function handleStarter(args) {
|
|
|
82
91
|
};
|
|
83
92
|
}
|
|
84
93
|
const action = first.toLowerCase();
|
|
94
|
+
// /starter list — documented alias of the bare command
|
|
95
|
+
if (action === 'list' && args.length === 1) {
|
|
96
|
+
return {
|
|
97
|
+
handled: true,
|
|
98
|
+
entry: {
|
|
99
|
+
type: 'assistant',
|
|
100
|
+
content: formatStarterList(),
|
|
101
|
+
timestamp: new Date(),
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (action === 'search' && args.length === 1) {
|
|
106
|
+
return {
|
|
107
|
+
handled: true,
|
|
108
|
+
entry: {
|
|
109
|
+
type: 'assistant',
|
|
110
|
+
content: 'Usage: /starter search <query>',
|
|
111
|
+
timestamp: new Date(),
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
85
115
|
// /starter search <query>
|
|
86
116
|
if (action === 'search' && args.length > 1) {
|
|
87
117
|
const query = args.slice(1).join(' ');
|