@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
|
@@ -5,6 +5,9 @@ import path from 'path';
|
|
|
5
5
|
import { getImageGenerationModel } from '../config/agent-defaults.js';
|
|
6
6
|
import { resolveToolGatewayRoute } from '../agent/tool-gateway-router.js';
|
|
7
7
|
import { logger } from '../utils/logger.js';
|
|
8
|
+
import { getChatGptAuth, hasCodexCredentials, refreshChatGptAuth, } from '../providers/codex-oauth.js';
|
|
9
|
+
import { buildChatGptHeaders, CHATGPT_RESPONSES_URL, } from '../codebuddy/providers/chatgpt-headers.js';
|
|
10
|
+
import { CHATGPT_OAUTH_DEFAULT_MODEL } from '../providers/chatgpt-models.js';
|
|
8
11
|
const IMAGE_SIZES = {
|
|
9
12
|
landscape: '1536x1024',
|
|
10
13
|
square: '1024x1024',
|
|
@@ -38,7 +41,7 @@ export async function generateImage(input, runtime = {}) {
|
|
|
38
41
|
if (!prompt) {
|
|
39
42
|
throw new Error('prompt is required for image generation');
|
|
40
43
|
}
|
|
41
|
-
const config = resolveImageProvider(runtime.env ?? process.env);
|
|
44
|
+
const config = resolveImageProvider(runtime.env ?? process.env, { hasAuthOverride: Boolean(runtime.chatGptAuth) });
|
|
42
45
|
const aspect = resolveImageAspect(input.aspectRatio);
|
|
43
46
|
const fetchImpl = runtime.fetch ?? fetch;
|
|
44
47
|
const generatedAt = (runtime.now ?? (() => new Date()))().toISOString();
|
|
@@ -48,6 +51,9 @@ export async function generateImage(input, runtime = {}) {
|
|
|
48
51
|
await ingestLisaSelfieIfNeeded(comfy, runtime);
|
|
49
52
|
return comfy;
|
|
50
53
|
}
|
|
54
|
+
if (config.provider === 'chatgpt') {
|
|
55
|
+
return generateChatGptImage(prompt, aspect, config, runtime, generatedAt);
|
|
56
|
+
}
|
|
51
57
|
const size = IMAGE_SIZES[aspect];
|
|
52
58
|
const body = {
|
|
53
59
|
model: config.model,
|
|
@@ -155,7 +161,7 @@ export async function editImage(input, runtime = {}) {
|
|
|
155
161
|
const imageUrl = validateImageReference(input.imageUrl, 'source image');
|
|
156
162
|
const selections = normalizeEditSelections(input.selections);
|
|
157
163
|
const maskUrl = input.maskUrl ? validateDataImage(input.maskUrl, 'mask') : undefined;
|
|
158
|
-
const config = resolveImageProvider(runtime.env ?? process.env);
|
|
164
|
+
const config = resolveImageProvider(runtime.env ?? process.env, { hasAuthOverride: Boolean(runtime.chatGptAuth) });
|
|
159
165
|
const fetchImpl = runtime.fetch ?? fetch;
|
|
160
166
|
const generatedAt = (runtime.now ?? (() => new Date()))().toISOString();
|
|
161
167
|
const selectionHint = selections.length > 0
|
|
@@ -174,6 +180,15 @@ export async function editImage(input, runtime = {}) {
|
|
|
174
180
|
sourceRef: input.sourceRef,
|
|
175
181
|
}, config, runtime, generatedAt);
|
|
176
182
|
}
|
|
183
|
+
if (config.provider === 'chatgpt') {
|
|
184
|
+
return editChatGptImage({
|
|
185
|
+
prompt,
|
|
186
|
+
effectivePrompt,
|
|
187
|
+
imageUrl,
|
|
188
|
+
selections,
|
|
189
|
+
sourceRef: input.sourceRef,
|
|
190
|
+
}, config, runtime, generatedAt);
|
|
191
|
+
}
|
|
177
192
|
let response;
|
|
178
193
|
if (config.provider === 'xai') {
|
|
179
194
|
response = await postJson(fetchImpl, joinUrl(config.baseUrl, '/images/edits'), {
|
|
@@ -264,6 +279,299 @@ export async function editImage(input, runtime = {}) {
|
|
|
264
279
|
...(revisedPrompt ? { revised_prompt: revisedPrompt } : {}),
|
|
265
280
|
};
|
|
266
281
|
}
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
// ChatGPT Codex image backend ($0 subscription, gpt-image-2 via /responses).
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
export function parseChatGptImageResponse(text) {
|
|
286
|
+
const trimmed = text.trim();
|
|
287
|
+
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
288
|
+
try {
|
|
289
|
+
const parsed = JSON.parse(trimmed);
|
|
290
|
+
if (parsed.error?.message) {
|
|
291
|
+
throw new Error(`ChatGPT error: ${parsed.error.message}`);
|
|
292
|
+
}
|
|
293
|
+
if (Array.isArray(parsed.data) && parsed.data[0]?.b64_json) {
|
|
294
|
+
return {
|
|
295
|
+
b64: parsed.data[0].b64_json,
|
|
296
|
+
revisedPrompt: parsed.data[0].revised_prompt,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
if (parsed.item?.type === 'image_generation_call' && parsed.item.result) {
|
|
300
|
+
return {
|
|
301
|
+
b64: parsed.item.result,
|
|
302
|
+
revisedPrompt: parsed.item.revised_prompt,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (e) {
|
|
307
|
+
if (e instanceof Error && e.message.startsWith('ChatGPT'))
|
|
308
|
+
throw e;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
let b64;
|
|
312
|
+
let revisedPrompt;
|
|
313
|
+
const lines = text.split('\n');
|
|
314
|
+
for (const rawLine of lines) {
|
|
315
|
+
const line = rawLine.trim();
|
|
316
|
+
if (!line.startsWith('data:'))
|
|
317
|
+
continue;
|
|
318
|
+
const dataStr = line.slice(5).trim();
|
|
319
|
+
if (!dataStr || dataStr === '[DONE]')
|
|
320
|
+
continue;
|
|
321
|
+
try {
|
|
322
|
+
const event = JSON.parse(dataStr);
|
|
323
|
+
if (event.error?.message) {
|
|
324
|
+
throw new Error(`ChatGPT image error: ${event.error.message}`);
|
|
325
|
+
}
|
|
326
|
+
if (event.type === 'response.failed' && event.response?.error?.message) {
|
|
327
|
+
throw new Error(`ChatGPT image response failed: ${event.response.error.message}`);
|
|
328
|
+
}
|
|
329
|
+
if (event.item?.type === 'image_generation_call') {
|
|
330
|
+
if (event.item.result)
|
|
331
|
+
b64 = event.item.result;
|
|
332
|
+
if (event.item.revised_prompt)
|
|
333
|
+
revisedPrompt = event.item.revised_prompt;
|
|
334
|
+
}
|
|
335
|
+
else if (Array.isArray(event.data) && event.data[0]?.b64_json) {
|
|
336
|
+
b64 = event.data[0].b64_json;
|
|
337
|
+
if (event.data[0].revised_prompt)
|
|
338
|
+
revisedPrompt = event.data[0].revised_prompt;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch (e) {
|
|
342
|
+
if (e instanceof Error && e.message.startsWith('ChatGPT'))
|
|
343
|
+
throw e;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (!b64) {
|
|
347
|
+
throw new Error('ChatGPT image generation response did not contain image data');
|
|
348
|
+
}
|
|
349
|
+
return { b64, revisedPrompt };
|
|
350
|
+
}
|
|
351
|
+
async function executeChatGptResponsesImage(options) {
|
|
352
|
+
const { prompt, imageUrl, config, runtime, timeoutMs } = options;
|
|
353
|
+
const fetchImpl = runtime.fetch ?? fetch;
|
|
354
|
+
const envSource = runtime.env ?? process.env;
|
|
355
|
+
let auth = runtime.chatGptAuth;
|
|
356
|
+
if (!auth) {
|
|
357
|
+
try {
|
|
358
|
+
auth = (await getChatGptAuth()) ?? undefined;
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
// getChatGptAuth may throw or return null
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (!auth?.access_token) {
|
|
365
|
+
throw new Error('No ChatGPT credentials found for provider chatgpt. Run `buddy login` (or `/login chatgpt`) to connect.');
|
|
366
|
+
}
|
|
367
|
+
const endpoint = config.baseUrl;
|
|
368
|
+
const isDirectImageEndpoint = endpoint.includes('/images/');
|
|
369
|
+
let requestBody;
|
|
370
|
+
if (isDirectImageEndpoint) {
|
|
371
|
+
requestBody = {
|
|
372
|
+
model: config.model,
|
|
373
|
+
prompt,
|
|
374
|
+
...(imageUrl ? { image: imageUrl } : {}),
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
const conversationalModel = env(envSource, 'CODEBUDDY_CHATGPT_MODEL') ?? CHATGPT_OAUTH_DEFAULT_MODEL;
|
|
379
|
+
const content = [
|
|
380
|
+
{ type: 'input_text', text: prompt },
|
|
381
|
+
];
|
|
382
|
+
if (imageUrl) {
|
|
383
|
+
content.push({ type: 'input_image', image_url: imageUrl });
|
|
384
|
+
}
|
|
385
|
+
requestBody = {
|
|
386
|
+
model: conversationalModel,
|
|
387
|
+
store: false,
|
|
388
|
+
stream: true,
|
|
389
|
+
instructions: 'You are an image generation assistant. When the user asks to generate or edit an image, invoke the image_generation tool immediately with the prompt and any provided input image.',
|
|
390
|
+
input: [
|
|
391
|
+
{
|
|
392
|
+
type: 'message',
|
|
393
|
+
role: 'user',
|
|
394
|
+
content,
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
tools: [
|
|
398
|
+
{
|
|
399
|
+
type: 'image_generation',
|
|
400
|
+
// The Codex backend honours a per-tool model (verified live 2026-09-10):
|
|
401
|
+
// Images 2.5 (`gpt-image-2.5-flare` by default) instead of the backend default.
|
|
402
|
+
model: config.model,
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
let res;
|
|
408
|
+
try {
|
|
409
|
+
res = await fetchWithTimeout(fetchImpl, endpoint, {
|
|
410
|
+
method: 'POST',
|
|
411
|
+
headers: buildChatGptHeaders(auth, {
|
|
412
|
+
accept: isDirectImageEndpoint ? 'application/json' : 'text/event-stream',
|
|
413
|
+
}),
|
|
414
|
+
body: JSON.stringify(requestBody),
|
|
415
|
+
}, timeoutMs, runtime.signal);
|
|
416
|
+
}
|
|
417
|
+
catch (err) {
|
|
418
|
+
if (runtime.signal?.aborted)
|
|
419
|
+
throw err;
|
|
420
|
+
throw new Error(`ChatGPT image generation network error: ${err instanceof Error ? err.message : String(err)}`);
|
|
421
|
+
}
|
|
422
|
+
if (res.status === 401) {
|
|
423
|
+
try {
|
|
424
|
+
const refreshed = await refreshChatGptAuth();
|
|
425
|
+
if (refreshed?.access_token) {
|
|
426
|
+
auth = refreshed;
|
|
427
|
+
res = await fetchWithTimeout(fetchImpl, endpoint, {
|
|
428
|
+
method: 'POST',
|
|
429
|
+
headers: buildChatGptHeaders(auth, {
|
|
430
|
+
accept: isDirectImageEndpoint ? 'application/json' : 'text/event-stream',
|
|
431
|
+
}),
|
|
432
|
+
body: JSON.stringify(requestBody),
|
|
433
|
+
}, timeoutMs, runtime.signal);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// Refresh failed, proceed to status checks
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (res.status === 401) {
|
|
441
|
+
throw new Error('ChatGPT authentication expired (401). Please run `buddy login` (or `/login chatgpt`) to reconnect.');
|
|
442
|
+
}
|
|
443
|
+
if (res.status === 429) {
|
|
444
|
+
const errText = await res.text().catch(() => '');
|
|
445
|
+
let message = 'ChatGPT image generation rate limit reached (429). Please wait before requesting another image.';
|
|
446
|
+
try {
|
|
447
|
+
const parsed = JSON.parse(errText);
|
|
448
|
+
if (parsed.error?.message) {
|
|
449
|
+
message = `ChatGPT image generation rate limit reached (429): ${parsed.error.message}`;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
// ignore JSON parse error
|
|
454
|
+
}
|
|
455
|
+
throw new Error(message);
|
|
456
|
+
}
|
|
457
|
+
if (!res.ok) {
|
|
458
|
+
const errText = await res.text().catch(() => '');
|
|
459
|
+
let message = `ChatGPT image generation failed with status ${res.status}`;
|
|
460
|
+
try {
|
|
461
|
+
const parsed = JSON.parse(errText);
|
|
462
|
+
if (parsed.error?.message) {
|
|
463
|
+
message += `: ${parsed.error.message}`;
|
|
464
|
+
}
|
|
465
|
+
else if (errText) {
|
|
466
|
+
message += `: ${errText}`;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
catch {
|
|
470
|
+
if (errText)
|
|
471
|
+
message += `: ${errText}`;
|
|
472
|
+
}
|
|
473
|
+
throw new Error(message);
|
|
474
|
+
}
|
|
475
|
+
const responseText = await res.text();
|
|
476
|
+
return parseChatGptImageResponse(responseText);
|
|
477
|
+
}
|
|
478
|
+
async function generateChatGptImage(prompt, aspect, config, runtime, generatedAt) {
|
|
479
|
+
const envSource = runtime.env ?? process.env;
|
|
480
|
+
const timeoutMs = Number(envSource.CODEBUDDY_CHATGPT_IMAGE_TIMEOUT_MS) || 180_000;
|
|
481
|
+
const aspectHint = aspect === 'square'
|
|
482
|
+
? ' (aspect ratio: square 1:1)'
|
|
483
|
+
: aspect === 'portrait'
|
|
484
|
+
? ' (aspect ratio: portrait 2:3)'
|
|
485
|
+
: ' (aspect ratio: landscape 3:2)';
|
|
486
|
+
const effectivePrompt = `${prompt}${aspectHint}`;
|
|
487
|
+
const { b64, revisedPrompt } = await executeChatGptResponsesImage({
|
|
488
|
+
prompt: effectivePrompt,
|
|
489
|
+
config,
|
|
490
|
+
runtime,
|
|
491
|
+
timeoutMs,
|
|
492
|
+
});
|
|
493
|
+
const bytes = Buffer.from(b64, 'base64');
|
|
494
|
+
const outputPath = await saveGeneratedAsset(bytes, {
|
|
495
|
+
rootDir: runtime.rootDir,
|
|
496
|
+
dirName: 'images',
|
|
497
|
+
prefix: 'image',
|
|
498
|
+
extension: 'png',
|
|
499
|
+
createId: runtime.createId,
|
|
500
|
+
});
|
|
501
|
+
await writeMediaSidecar(outputPath, {
|
|
502
|
+
kind: 'image',
|
|
503
|
+
prompt,
|
|
504
|
+
...(revisedPrompt ? { revisedPrompt } : {}),
|
|
505
|
+
provider: config.provider,
|
|
506
|
+
model: config.model,
|
|
507
|
+
aspect_ratio: aspect,
|
|
508
|
+
generatedAt,
|
|
509
|
+
});
|
|
510
|
+
const result = {
|
|
511
|
+
kind: 'image_generate_result',
|
|
512
|
+
success: true,
|
|
513
|
+
image: outputPath,
|
|
514
|
+
outputPath,
|
|
515
|
+
mediaPath: `MEDIA:${outputPath}`,
|
|
516
|
+
provider: config.provider,
|
|
517
|
+
model: config.model,
|
|
518
|
+
prompt,
|
|
519
|
+
aspect_ratio: aspect,
|
|
520
|
+
generatedAt,
|
|
521
|
+
...(revisedPrompt ? { revised_prompt: revisedPrompt } : {}),
|
|
522
|
+
};
|
|
523
|
+
await ingestLisaSelfieIfNeeded(result, runtime);
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
async function editChatGptImage(input, config, runtime, generatedAt) {
|
|
527
|
+
const envSource = runtime.env ?? process.env;
|
|
528
|
+
const timeoutMs = Number(envSource.CODEBUDDY_CHATGPT_IMAGE_TIMEOUT_MS) || 180_000;
|
|
529
|
+
const { b64, revisedPrompt } = await executeChatGptResponsesImage({
|
|
530
|
+
prompt: input.effectivePrompt,
|
|
531
|
+
imageUrl: input.imageUrl,
|
|
532
|
+
config,
|
|
533
|
+
runtime,
|
|
534
|
+
timeoutMs,
|
|
535
|
+
});
|
|
536
|
+
const bytes = Buffer.from(b64, 'base64');
|
|
537
|
+
const outputPath = await saveGeneratedAsset(bytes, {
|
|
538
|
+
rootDir: runtime.rootDir,
|
|
539
|
+
dirName: 'images',
|
|
540
|
+
prefix: 'image-edit',
|
|
541
|
+
extension: 'png',
|
|
542
|
+
createId: runtime.createId,
|
|
543
|
+
});
|
|
544
|
+
const maskMode = input.selections.length > 0 ? 'region-prompt' : 'none';
|
|
545
|
+
const sourceReference = sanitizeImageSourceReference(input.sourceRef) ?? redactDataUrl(input.imageUrl);
|
|
546
|
+
await writeMediaSidecar(outputPath, {
|
|
547
|
+
kind: 'image-edit',
|
|
548
|
+
prompt: input.prompt,
|
|
549
|
+
...(revisedPrompt ? { revisedPrompt } : {}),
|
|
550
|
+
provider: config.provider,
|
|
551
|
+
model: config.model,
|
|
552
|
+
source: sourceReference,
|
|
553
|
+
masked: false,
|
|
554
|
+
maskMode,
|
|
555
|
+
selections: input.selections,
|
|
556
|
+
generatedAt,
|
|
557
|
+
});
|
|
558
|
+
return {
|
|
559
|
+
kind: 'image_edit_result',
|
|
560
|
+
success: true,
|
|
561
|
+
image: outputPath,
|
|
562
|
+
outputPath,
|
|
563
|
+
mediaPath: `MEDIA:${outputPath}`,
|
|
564
|
+
provider: config.provider,
|
|
565
|
+
model: config.model,
|
|
566
|
+
prompt: input.prompt,
|
|
567
|
+
source: sourceReference,
|
|
568
|
+
masked: false,
|
|
569
|
+
maskMode,
|
|
570
|
+
selections: input.selections,
|
|
571
|
+
generatedAt,
|
|
572
|
+
...(revisedPrompt ? { revised_prompt: revisedPrompt } : {}),
|
|
573
|
+
};
|
|
574
|
+
}
|
|
267
575
|
const COMFY_DIMS = {
|
|
268
576
|
landscape: { width: 1024, height: 768 },
|
|
269
577
|
square: { width: 768, height: 768 },
|
|
@@ -525,13 +833,16 @@ function comfyDelay(ms, signal) {
|
|
|
525
833
|
});
|
|
526
834
|
}
|
|
527
835
|
export async function getImageEditCapabilities(runtime = {}) {
|
|
528
|
-
const config = resolveImageProvider(runtime.env ?? process.env);
|
|
836
|
+
const config = resolveImageProvider(runtime.env ?? process.env, { hasAuthOverride: Boolean(runtime.chatGptAuth) });
|
|
529
837
|
if (config.provider === 'openai') {
|
|
530
838
|
return { provider: config.provider, available: true, alphaMasking: true };
|
|
531
839
|
}
|
|
532
840
|
if (config.provider === 'xai') {
|
|
533
841
|
return { provider: config.provider, available: true, alphaMasking: false };
|
|
534
842
|
}
|
|
843
|
+
if (config.provider === 'chatgpt') {
|
|
844
|
+
return { provider: config.provider, available: true, alphaMasking: false };
|
|
845
|
+
}
|
|
535
846
|
if (config.provider !== 'comfyui') {
|
|
536
847
|
return { provider: config.provider, available: false, alphaMasking: false, reason: 'Provider does not support image editing' };
|
|
537
848
|
}
|
|
@@ -1483,7 +1794,7 @@ async function materializeVideoResult(videoUrl, options) {
|
|
|
1483
1794
|
...(options.endpoint ? { endpoint: options.endpoint } : {}),
|
|
1484
1795
|
};
|
|
1485
1796
|
}
|
|
1486
|
-
function resolveImageProvider(envSource) {
|
|
1797
|
+
export function resolveImageProvider(envSource = process.env, options) {
|
|
1487
1798
|
let requested = (envSource.CODEBUDDY_IMAGE_PROVIDER ?? '').trim().toLowerCase();
|
|
1488
1799
|
// Prefer ComfyUI when explicitly requested OR when a ComfyUI endpoint is
|
|
1489
1800
|
// declared and no other provider was chosen (selfie / local-first companion
|
|
@@ -1498,6 +1809,13 @@ function resolveImageProvider(envSource) {
|
|
|
1498
1809
|
|| declaredFallbacks.length > 0)) {
|
|
1499
1810
|
requested = 'comfyui';
|
|
1500
1811
|
}
|
|
1812
|
+
const hasOpenAiKey = Boolean(envSource.OPENAI_API_KEY?.trim() || envSource.CODEBUDDY_IMAGE_API_KEY?.trim());
|
|
1813
|
+
const hasXaiKey = Boolean(envSource.XAI_API_KEY?.trim());
|
|
1814
|
+
const hasFalKey = Boolean(envSource.FAL_KEY?.trim() || envSource.FAL_API_KEY?.trim());
|
|
1815
|
+
const hasChatGptAuth = Boolean(options?.hasAuthOverride || hasCodexCredentials());
|
|
1816
|
+
if (!requested && !hasOpenAiKey && !hasXaiKey && !hasFalKey && hasChatGptAuth) {
|
|
1817
|
+
requested = 'chatgpt';
|
|
1818
|
+
}
|
|
1501
1819
|
// Local ComfyUI backend (offline, GPU) — no API key, workflow-based API.
|
|
1502
1820
|
if (requested === 'comfyui') {
|
|
1503
1821
|
const baseUrl = (envSource.COMFYUI_URL
|
|
@@ -1515,17 +1833,25 @@ function resolveImageProvider(envSource) {
|
|
|
1515
1833
|
}
|
|
1516
1834
|
return { provider: 'comfyui', model, baseUrl, apiKey: '' };
|
|
1517
1835
|
}
|
|
1518
|
-
|
|
1836
|
+
if (requested === 'chatgpt') {
|
|
1837
|
+
const baseUrl = (envSource.CHATGPT_RESPONSES_URL
|
|
1838
|
+
?? envSource.CODEBUDDY_IMAGE_BASE_URL
|
|
1839
|
+
?? CHATGPT_RESPONSES_URL).trim().replace(/\/+$/, '');
|
|
1840
|
+
const model = (envSource.CODEBUDDY_IMAGE_MODEL ?? 'gpt-image-2.5-flare').trim();
|
|
1841
|
+
assertProviderReady('chatgpt', '', baseUrl, 'image', { hasCredentials: hasChatGptAuth });
|
|
1842
|
+
return { provider: 'chatgpt', model, baseUrl, apiKey: '' };
|
|
1843
|
+
}
|
|
1844
|
+
const provider = requested === 'xai' ? 'xai' : (requested === 'fal' ? 'fal' : 'openai');
|
|
1519
1845
|
const baseUrl = (envSource.CODEBUDDY_IMAGE_BASE_URL
|
|
1520
|
-
?? (provider === 'xai' ? envSource.XAI_BASE_URL : envSource.OPENAI_BASE_URL)
|
|
1846
|
+
?? (provider === 'xai' ? envSource.XAI_BASE_URL : (provider === 'fal' ? 'https://queue.fal.run' : envSource.OPENAI_BASE_URL))
|
|
1521
1847
|
?? (provider === 'xai' ? 'https://api.x.ai/v1' : 'https://api.openai.com/v1')).trim().replace(/\/+$/, '');
|
|
1522
1848
|
const apiKey = (envSource.CODEBUDDY_IMAGE_API_KEY
|
|
1523
|
-
?? (provider === 'xai' ? envSource.XAI_API_KEY : envSource.OPENAI_API_KEY)
|
|
1849
|
+
?? (provider === 'xai' ? envSource.XAI_API_KEY : (provider === 'fal' ? (envSource.FAL_KEY ?? envSource.FAL_API_KEY) : envSource.OPENAI_API_KEY))
|
|
1524
1850
|
?? '').trim();
|
|
1525
1851
|
const model = (envSource.CODEBUDDY_IMAGE_MODEL
|
|
1526
1852
|
?? (provider === 'xai' ? envSource.XAI_IMAGE_MODEL : envSource.OPENAI_IMAGE_MODEL)
|
|
1527
1853
|
?? getImageGenerationModel()
|
|
1528
|
-
?? (provider === 'xai' ? 'grok-imagine-image' : 'gpt-image-2')).trim();
|
|
1854
|
+
?? (provider === 'xai' ? 'grok-imagine-image' : 'gpt-image-2.5-flare')).trim();
|
|
1529
1855
|
// Route through the Nous Tool Gateway when configured (transparent base-URL +
|
|
1530
1856
|
// token substitution); otherwise use the direct provider.
|
|
1531
1857
|
const route = resolveToolGatewayRoute('image_gen', envSource);
|
|
@@ -1783,10 +2109,16 @@ function resolveVideoProvider(modelOverride, envSource) {
|
|
|
1783
2109
|
assertProviderReady(provider, effectiveApiKey, effectiveBaseUrl, 'video');
|
|
1784
2110
|
return { provider, model, baseUrl: effectiveBaseUrl, apiKey: effectiveApiKey };
|
|
1785
2111
|
}
|
|
1786
|
-
function assertProviderReady(provider, apiKey, baseUrl, kind) {
|
|
2112
|
+
function assertProviderReady(provider, apiKey, baseUrl, kind, options) {
|
|
1787
2113
|
if (!baseUrl) {
|
|
1788
2114
|
throw new Error(`No ${kind} generation base URL configured for provider ${provider}`);
|
|
1789
2115
|
}
|
|
2116
|
+
if (provider === 'chatgpt') {
|
|
2117
|
+
if (!options?.hasCredentials) {
|
|
2118
|
+
throw new Error('No ChatGPT credentials found for provider chatgpt. Run `buddy login` (or `/login chatgpt`) to connect.');
|
|
2119
|
+
}
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
1790
2122
|
if (!apiKey && !isLocalBaseUrl(baseUrl)) {
|
|
1791
2123
|
throw new Error(`No ${kind} generation credentials configured for provider ${provider}`);
|
|
1792
2124
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Parses Git merge conflict markers, provides strategy-based resolution
|
|
5
5
|
* (ours, theirs, both, ai), and exposes a tool for the agent to use.
|
|
6
6
|
*/
|
|
7
|
+
import { spawnSync } from 'child_process';
|
|
7
8
|
import * as fs from 'fs';
|
|
8
9
|
import * as path from 'path';
|
|
9
10
|
import { logger } from '../utils/logger.js';
|
|
@@ -209,34 +210,61 @@ function indent(text, prefix = ' ') {
|
|
|
209
210
|
/**
|
|
210
211
|
* Scan the project for files containing merge conflict markers.
|
|
211
212
|
*/
|
|
213
|
+
function runGit(args, cwd) {
|
|
214
|
+
const result = spawnSync('git', args, {
|
|
215
|
+
cwd,
|
|
216
|
+
encoding: 'utf-8',
|
|
217
|
+
timeout: 10000,
|
|
218
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
219
|
+
windowsHide: true,
|
|
220
|
+
});
|
|
221
|
+
if (result.error) {
|
|
222
|
+
const code = result.error.code;
|
|
223
|
+
return { ok: false, reason: code === 'ENOENT' ? 'git is not installed or not on PATH' : result.error.message };
|
|
224
|
+
}
|
|
225
|
+
if (result.status !== 0) {
|
|
226
|
+
return { ok: false, reason: (result.stderr || '').trim() || `git ${args.join(' ')} exited with status ${result.status}` };
|
|
227
|
+
}
|
|
228
|
+
return { ok: true, stdout: result.stdout || '' };
|
|
229
|
+
}
|
|
212
230
|
function scanForConflicts(cwd) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
231
|
+
// Distinguish "not a repository" and "git unavailable" from "no conflicts":
|
|
232
|
+
// the former used to be reported for every scan because the ESM module
|
|
233
|
+
// called an undefined `require` and the catch-all blamed git.
|
|
234
|
+
const inside = runGit(['rev-parse', '--is-inside-work-tree'], cwd);
|
|
235
|
+
if (!inside.ok) {
|
|
236
|
+
return { success: false, error: `Unable to scan for conflicts: ${inside.reason}` };
|
|
237
|
+
}
|
|
238
|
+
if (inside.stdout.trim() !== 'true') {
|
|
239
|
+
return { success: false, error: 'Unable to scan for conflicts: not inside a Git work tree.' };
|
|
240
|
+
}
|
|
241
|
+
const diff = runGit(['diff', '--name-only', '--diff-filter=U'], cwd);
|
|
242
|
+
if (!diff.ok) {
|
|
243
|
+
return { success: false, error: `Unable to scan for conflicts: ${diff.reason}` };
|
|
244
|
+
}
|
|
245
|
+
const output = diff.stdout.trim();
|
|
246
|
+
if (!output) {
|
|
247
|
+
return { success: true, output: 'No files with merge conflicts found.' };
|
|
248
|
+
}
|
|
249
|
+
// `git diff --name-only` paths are relative to the repository root.
|
|
250
|
+
const topLevel = runGit(['rev-parse', '--show-toplevel'], cwd);
|
|
251
|
+
const root = topLevel.ok ? topLevel.stdout.trim() : cwd;
|
|
252
|
+
const files = output.split('\n').filter(Boolean);
|
|
253
|
+
const summaries = [];
|
|
254
|
+
for (const file of files) {
|
|
255
|
+
const fullPath = path.join(root, file);
|
|
256
|
+
try {
|
|
257
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
258
|
+
const conflicts = parseConflicts(content, fullPath);
|
|
259
|
+
summaries.push(` ${file}: ${conflicts.length} conflict(s)`);
|
|
218
260
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
for (const file of files) {
|
|
222
|
-
const fullPath = path.join(cwd, file);
|
|
223
|
-
try {
|
|
224
|
-
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
225
|
-
const conflicts = parseConflicts(content, fullPath);
|
|
226
|
-
summaries.push(` ${file}: ${conflicts.length} conflict(s)`);
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
summaries.push(` ${file}: (unable to read)`);
|
|
230
|
-
}
|
|
261
|
+
catch {
|
|
262
|
+
summaries.push(` ${file}: (unable to read)`);
|
|
231
263
|
}
|
|
232
|
-
return {
|
|
233
|
-
success: true,
|
|
234
|
-
output: `Files with merge conflicts:\n${summaries.join('\n')}`,
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
catch {
|
|
238
|
-
// Fallback: not in a git repo or git not available
|
|
239
|
-
return { success: true, output: 'Unable to scan for conflicts (git not available or not in a repository).' };
|
|
240
264
|
}
|
|
265
|
+
return {
|
|
266
|
+
success: true,
|
|
267
|
+
output: `Files with merge conflicts:\n${summaries.join('\n')}`,
|
|
268
|
+
};
|
|
241
269
|
}
|
|
242
270
|
//# sourceMappingURL=merge-conflict-tool.js.map
|
package/dist/tools/metadata.d.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { ToolMetadata, ToolCategory
|
|
1
|
+
import type { ToolMetadata, ToolCategory } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Default tool metadata for all built-in tools
|
|
4
4
|
*/
|
|
5
5
|
export declare const TOOL_METADATA: ToolMetadata[];
|
|
6
|
-
/** Resolve a tool's declared effect class. Missing catalog/MCP entries warn once and return `unknown`. */
|
|
7
|
-
export declare function resolveToolEffect(name: string, metadata?: Pick<ToolMetadata, 'effect'> | null): ToolEffectClass | 'unknown';
|
|
8
|
-
/** Test hook: unique-warning latch. */
|
|
9
|
-
export declare function resetToolEffectWarningLatch(): void;
|
|
10
6
|
/** Metadata visible to RAG / BM25. Gated tools stay out of the index when disabled. */
|
|
11
7
|
export declare function getActiveToolMetadata(): ToolMetadata[];
|
|
12
8
|
/**
|
package/dist/tools/metadata.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { TOOL_EFFECT_CLASSES } from "./types.js";
|
|
2
|
-
import { logger } from "../utils/logger.js";
|
|
3
1
|
/**
|
|
4
2
|
* Default tool metadata for all built-in tools
|
|
5
3
|
*/
|
|
6
4
|
export const TOOL_METADATA = [
|
|
5
|
+
{ name: 'a2a_call', effect: 'emission', category: 'web', keywords: ['a2a', 'peer', 'hermes', 'openclaw', 'delegate'], priority: 6, fleetSafe: false, description: 'Send a task to a configured remote A2A peer; remote execution can have effects and requires permission.' },
|
|
6
|
+
{ name: 'resource_catalog', effect: 'read', category: 'system', keywords: ['resource', 'catalog', 'network', 'fleet', 'ragchat', 'available', 'ressources', 'réseau'], priority: 7, fleetSafe: false, description: 'Read explicit resource declarations and select fresh permitted resources; no probes or dispatch.' },
|
|
7
|
+
{ name: 'ragchat_search', effect: 'read', category: 'web',
|
|
8
|
+
keywords: ['ragchat', 'pdf', 'corpus', 'citations', 'pages', 'ocr', 'recherche documentaire'],
|
|
9
|
+
priority: 7, description: 'Search configured authenticated RagChat PDF profiles with exact page citations; read-only.', fleetSafe: false },
|
|
7
10
|
// File reading
|
|
8
11
|
{
|
|
9
12
|
name: 'view_file',
|
|
@@ -85,7 +88,7 @@ export const TOOL_METADATA = [
|
|
|
85
88
|
name: 'self_describe',
|
|
86
89
|
effect: 'read',
|
|
87
90
|
category: 'file_read',
|
|
88
|
-
keywords: ['self', 'describe', 'components', 'composants', 'briques', 'bricks', 'architecture', 'de quoi es-tu fait', 'de quoi es-tu compose', 'qui es-tu', 'capabilities', 'capacites', 'capteur', 'capteurs', 'sensors', 'modules', 'buddy-sense', 'buddy-vision', 'buddy-memory', 'introspection', 'auto inspection', 'etudie', 'examine', 'inspecte', 'propre code', 'ton code', 'fonctionne', 'fonctionnes', 'fonctionnement', 'limites', 'version', 'conscient', 'consciente', 'conscience', 'consciousness', 'modele de soi'],
|
|
91
|
+
keywords: ['self', 'describe', 'components', 'composants', 'briques', 'bricks', 'architecture', 'de quoi es-tu fait', 'de quoi es-tu compose', 'qui es-tu', 'capabilities', 'capacites', 'capteur', 'capteurs', 'sensors', 'modules', 'buddy-sense', 'buddy-vision', 'buddy-memory', 'introspection', 'auto inspection', 'etudie', 'examine', 'inspecte', 'propre code', 'ton code', 'fonctionne', 'fonctionnes', 'fonctionnement', 'limites', 'version', 'conscient', 'consciente', 'conscience', 'consciousness', 'modele de soi', 'theme', 'parametres', 'parametrage', 'settings', 'configuration'],
|
|
89
92
|
priority: 50,
|
|
90
93
|
description: "Inspect the robot's attested core, bounded code structure, turn metadata, configured faculties, and epistemic limits without live probes",
|
|
91
94
|
fleetSafe: true,
|
|
@@ -215,7 +218,8 @@ export const TOOL_METADATA = [
|
|
|
215
218
|
category: 'system',
|
|
216
219
|
keywords: ['process', 'spawn', 'kill', 'list', 'logs', 'pid', 'monitor'],
|
|
217
220
|
priority: 6,
|
|
218
|
-
description: 'Manage system processes (spawn, inspect, logs, terminate)'
|
|
221
|
+
description: 'Manage system processes (spawn, inspect, logs, terminate)',
|
|
222
|
+
repeatSafe: true,
|
|
219
223
|
},
|
|
220
224
|
{
|
|
221
225
|
name: 'app_server',
|
|
@@ -1151,7 +1155,8 @@ export const TOOL_METADATA = [
|
|
|
1151
1155
|
category: 'media',
|
|
1152
1156
|
keywords: ['gpuNode', 'gpu', 'panoworld', 'longcat', 'avatar', '3dgs', 'world model', 'reconstruction', 'render'],
|
|
1153
1157
|
priority: 8,
|
|
1154
|
-
description: 'Submit and monitor isolated PanoWorld or LongCat jobs on a configured GPU worker'
|
|
1158
|
+
description: 'Submit and monitor isolated PanoWorld or LongCat jobs on a configured GPU worker',
|
|
1159
|
+
repeatSafe: true,
|
|
1155
1160
|
},
|
|
1156
1161
|
{
|
|
1157
1162
|
name: 'ocr',
|
|
@@ -1377,7 +1382,7 @@ export const TOOL_METADATA = [
|
|
|
1377
1382
|
category: 'utility',
|
|
1378
1383
|
keywords: ['skill', 'skills', 'list', 'installed', 'enabled', 'disabled', 'hub', 'hermes'],
|
|
1379
1384
|
priority: 5,
|
|
1380
|
-
description: 'List
|
|
1385
|
+
description: 'List available local skills across bundled, built-in, workspace and hub sources',
|
|
1381
1386
|
fleetSafe: true,
|
|
1382
1387
|
},
|
|
1383
1388
|
{
|
|
@@ -1386,7 +1391,7 @@ export const TOOL_METADATA = [
|
|
|
1386
1391
|
category: 'utility',
|
|
1387
1392
|
keywords: ['skill', 'skills', 'view', 'read', 'content', 'inspect', 'show', 'hub', 'hermes'],
|
|
1388
1393
|
priority: 6,
|
|
1389
|
-
description: 'Read one
|
|
1394
|
+
description: 'Read one local skill and its source or hub integrity metadata',
|
|
1390
1395
|
fleetSafe: true,
|
|
1391
1396
|
},
|
|
1392
1397
|
{
|
|
@@ -1714,6 +1719,15 @@ export const TOOL_METADATA = [
|
|
|
1714
1719
|
description: 'Generate professional documents (PowerPoint/Word/Excel/PDF) from markdown content'
|
|
1715
1720
|
},
|
|
1716
1721
|
// Fleet — multi-Claude orchestration via peer-RPC (Phase (d).17)
|
|
1722
|
+
{
|
|
1723
|
+
name: 'fleet_room',
|
|
1724
|
+
effect: 'emission',
|
|
1725
|
+
fleetSafe: false,
|
|
1726
|
+
category: 'utility',
|
|
1727
|
+
keywords: ['fleet', 'room', 'salon', 'message', 'coordination', 'history', 'robot', 'communication', 'flotte'],
|
|
1728
|
+
priority: 7,
|
|
1729
|
+
description: 'Send messages, read history or check access in the configured Fleet room; messages remain external data, not action authorization',
|
|
1730
|
+
},
|
|
1717
1731
|
{
|
|
1718
1732
|
name: 'peer_delegate',
|
|
1719
1733
|
effect: 'emission',
|
|
@@ -2030,27 +2044,6 @@ export const TOOL_METADATA = [
|
|
|
2030
2044
|
fleetSafe: true,
|
|
2031
2045
|
},
|
|
2032
2046
|
];
|
|
2033
|
-
const missingEffectWarned = new Set();
|
|
2034
|
-
function isToolEffectClass(value) {
|
|
2035
|
-
return TOOL_EFFECT_CLASSES.includes(value);
|
|
2036
|
-
}
|
|
2037
|
-
/** Resolve a tool's declared effect class. Missing catalog/MCP entries warn once and return `unknown`. */
|
|
2038
|
-
export function resolveToolEffect(name, metadata) {
|
|
2039
|
-
if (isToolEffectClass(metadata?.effect))
|
|
2040
|
-
return metadata.effect;
|
|
2041
|
-
const catalog = TOOL_METADATA.find((entry) => entry.name === name)?.effect;
|
|
2042
|
-
if (isToolEffectClass(catalog))
|
|
2043
|
-
return catalog;
|
|
2044
|
-
if (!missingEffectWarned.has(name)) {
|
|
2045
|
-
missingEffectWarned.add(name);
|
|
2046
|
-
logger.warn('tool metadata missing effect class; treating as unknown', { tool: name });
|
|
2047
|
-
}
|
|
2048
|
-
return 'unknown';
|
|
2049
|
-
}
|
|
2050
|
-
/** Test hook: unique-warning latch. */
|
|
2051
|
-
export function resetToolEffectWarningLatch() {
|
|
2052
|
-
missingEffectWarned.clear();
|
|
2053
|
-
}
|
|
2054
2047
|
/** Metadata visible to RAG / BM25. Gated tools stay out of the index when disabled. */
|
|
2055
2048
|
export function getActiveToolMetadata() {
|
|
2056
2049
|
if (process.env.CODEBUDDY_CONTEXT_ZOOM === 'true')
|