@phuetz/code-buddy 1.1.0 → 1.3.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.md +211 -163
- package/dist/agent/autonomous/agentic-coding-contract.d.ts +12 -12
- package/dist/agent/base-agent.d.ts +4 -0
- package/dist/agent/base-agent.js +6 -0
- package/dist/agent/codebuddy-agent.d.ts +1 -1
- package/dist/agent/codebuddy-agent.js +69 -14
- package/dist/agent/execution/agent-executor.js +122 -12
- package/dist/agent/execution/tool-dependency-graph.js +7 -0
- package/dist/agent/execution/tool-hooks.d.ts +6 -0
- package/dist/agent/execution/tool-hooks.js +13 -5
- package/dist/agent/execution/tool-selection-strategy.d.ts +11 -2
- package/dist/agent/execution/tool-selection-strategy.js +67 -10
- package/dist/agent/extended-thinking.d.ts +8 -0
- package/dist/agent/extended-thinking.js +27 -0
- package/dist/agent/facades/infrastructure-facade.d.ts +9 -2
- package/dist/agent/facades/infrastructure-facade.js +15 -6
- package/dist/agent/hermes-browser-backends.js +151 -11
- package/dist/agent/hermes-claw-migrate.d.ts +59 -0
- package/dist/agent/hermes-claw-migrate.js +427 -26
- package/dist/agent/hermes-parity-manifest.js +78 -71
- package/dist/agent/hermes-runtime-lifecycle.d.ts +67 -0
- package/dist/agent/hermes-runtime-lifecycle.js +468 -0
- package/dist/agent/middleware/index.d.ts +1 -0
- package/dist/agent/middleware/index.js +1 -0
- package/dist/agent/middleware/visual-validation-middleware.d.ts +17 -0
- package/dist/agent/middleware/visual-validation-middleware.js +67 -0
- package/dist/agent/model-benchmark.d.ts +77 -0
- package/dist/agent/model-benchmark.js +309 -0
- package/dist/agent/model-tier.d.ts +14 -0
- package/dist/agent/model-tier.js +71 -0
- package/dist/agent/multi-agent/agents/orchestrator-agent.js +17 -6
- package/dist/agent/multi-agent/multi-agent-system.js +3 -1
- package/dist/agent/multi-agent/session-fleet-bridge.d.ts +2 -0
- package/dist/agent/multi-agent/session-fleet-bridge.js +9 -1
- package/dist/agent/multi-agent/session-tools.js +22 -5
- package/dist/agent/reasoning/mcts.js +20 -6
- package/dist/agent/self-improvement/authored-artifact-gate.d.ts +18 -0
- package/dist/agent/self-improvement/authored-artifact-gate.js +42 -0
- package/dist/agent/self-improvement/authored-tool-runtime.d.ts +27 -0
- package/dist/agent/self-improvement/authored-tool-runtime.js +57 -0
- package/dist/agent/self-improvement/authored-tool-store.d.ts +24 -0
- package/dist/agent/self-improvement/authored-tool-store.js +57 -0
- package/dist/agent/self-improvement/llm-tool-proposer.d.ts +41 -0
- package/dist/agent/self-improvement/llm-tool-proposer.js +136 -0
- package/dist/agent/self-improvement/sandbox-scorer.d.ts +17 -0
- package/dist/agent/self-improvement/sandbox-scorer.js +43 -0
- package/dist/agent/self-improvement/self-knowledge.d.ts +8 -0
- package/dist/agent/self-improvement/self-knowledge.js +24 -0
- package/dist/agent/self-improvement/skill-benchmark.d.ts +9 -0
- package/dist/agent/self-improvement/skill-benchmark.js +22 -0
- package/dist/agent/self-improvement/skill-consolidator.d.ts +71 -0
- package/dist/agent/self-improvement/skill-consolidator.js +137 -0
- package/dist/agent/self-improvement/skill-engine.d.ts +42 -0
- package/dist/agent/self-improvement/skill-engine.js +87 -0
- package/dist/agent/self-improvement/skill-gate.d.ts +19 -0
- package/dist/agent/self-improvement/skill-gate.js +62 -0
- package/dist/agent/self-improvement/skill-mutator.d.ts +74 -0
- package/dist/agent/self-improvement/skill-mutator.js +223 -0
- package/dist/agent/self-improvement/skill-proposer.d.ts +40 -0
- package/dist/agent/self-improvement/skill-proposer.js +82 -0
- package/dist/agent/self-improvement/skill-types.d.ts +41 -0
- package/dist/agent/self-improvement/skill-types.js +13 -0
- package/dist/agent/self-improvement/tool-benchmark.d.ts +10 -0
- package/dist/agent/self-improvement/tool-benchmark.js +37 -0
- package/dist/agent/self-improvement/tool-engine.d.ts +54 -0
- package/dist/agent/self-improvement/tool-engine.js +101 -0
- package/dist/agent/self-improvement/tool-gate.d.ts +20 -0
- package/dist/agent/self-improvement/tool-gate.js +78 -0
- package/dist/agent/self-improvement/tool-proposer.d.ts +31 -0
- package/dist/agent/self-improvement/tool-proposer.js +34 -0
- package/dist/agent/self-improvement/tool-skill-mutator.d.ts +40 -0
- package/dist/agent/self-improvement/tool-skill-mutator.js +79 -0
- package/dist/agent/self-improvement/tool-types.d.ts +48 -0
- package/dist/agent/self-improvement/tool-types.js +9 -0
- package/dist/agent/self-improvement/types.d.ts +3 -1
- package/dist/agent/session-end-flush.d.ts +6 -1
- package/dist/agent/session-end-flush.js +20 -4
- package/dist/agent/streaming/streaming-handler.d.ts +7 -0
- package/dist/agent/streaming/streaming-handler.js +8 -1
- package/dist/agent/tool-executor.js +1 -0
- package/dist/agent/tool-handler.d.ts +5 -0
- package/dist/agent/tool-handler.js +133 -4
- package/dist/browser-automation/browser-operator-executor.js +15 -0
- package/dist/browser-automation/browser-use-runner.d.ts +96 -0
- package/dist/browser-automation/browser-use-runner.js +492 -0
- package/dist/browser-automation/camofox-runner.d.ts +107 -0
- package/dist/browser-automation/camofox-runner.js +287 -0
- package/dist/channels/dingtalk/index.js +3 -0
- package/dist/channels/discord/client.d.ts +9 -0
- package/dist/channels/discord/client.js +12 -0
- package/dist/channels/feishu/index.d.ts +167 -1
- package/dist/channels/feishu/index.js +432 -7
- package/dist/channels/gateway-lifecycle.d.ts +132 -0
- package/dist/channels/gateway-lifecycle.js +219 -0
- package/dist/channels/google-chat/index.d.ts +5 -1
- package/dist/channels/google-chat/index.js +5 -1
- package/dist/channels/imessage/index.d.ts +14 -0
- package/dist/channels/imessage/index.js +64 -17
- package/dist/channels/index.d.ts +4 -0
- package/dist/channels/index.js +4 -0
- package/dist/channels/irc/index.d.ts +73 -3
- package/dist/channels/irc/index.js +446 -11
- package/dist/channels/line/index.js +3 -0
- package/dist/channels/mattermost/index.d.ts +51 -4
- package/dist/channels/mattermost/index.js +303 -20
- package/dist/channels/nextcloud-talk/index.d.ts +89 -8
- package/dist/channels/nextcloud-talk/index.js +367 -16
- package/dist/channels/nostr/index.d.ts +121 -1
- package/dist/channels/nostr/index.js +396 -8
- package/dist/channels/ntfy/index.js +3 -0
- package/dist/channels/qq/index.js +3 -0
- package/dist/channels/slash-parity.d.ts +117 -0
- package/dist/channels/slash-parity.js +185 -0
- package/dist/channels/synology-chat/index.js +3 -0
- package/dist/channels/teams/index.d.ts +3 -0
- package/dist/channels/teams/index.js +3 -0
- package/dist/channels/telegram/client.d.ts +9 -0
- package/dist/channels/telegram/client.js +12 -0
- package/dist/channels/twilio-voice/index.js +3 -0
- package/dist/channels/webchat/index.d.ts +7 -1
- package/dist/channels/webchat/index.js +7 -1
- package/dist/channels/wecom/index.js +3 -0
- package/dist/channels/weixin/index.js +3 -0
- package/dist/channels/zalo/index.js +3 -0
- package/dist/cli/config-loader.js +1 -1
- package/dist/codebuddy/client.d.ts +30 -1
- package/dist/codebuddy/client.js +167 -20
- package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +5 -0
- package/dist/codebuddy/providers/provider-chatgpt-responses.js +7 -1
- package/dist/codebuddy/providers/provider-gemini-native.js +1 -1
- package/dist/codebuddy/providers/provider-openai-compat.d.ts +5 -0
- package/dist/codebuddy/providers/provider-openai-compat.js +82 -2
- package/dist/codebuddy/tool-definitions/computer-control-tools.js +32 -2
- package/dist/codebuddy/tool-definitions/core-tools.js +3 -3
- package/dist/codebuddy/tool-definitions/index.d.ts +2 -1
- package/dist/codebuddy/tool-definitions/index.js +2 -1
- package/dist/codebuddy/tool-definitions/multimodal-tools.d.ts +1 -0
- package/dist/codebuddy/tool-definitions/multimodal-tools.js +44 -1
- package/dist/codebuddy/tool-definitions/windows-tools.d.ts +2 -0
- package/dist/codebuddy/tool-definitions/windows-tools.js +34 -0
- package/dist/codebuddy/tools.d.ts +8 -1
- package/dist/codebuddy/tools.js +67 -24
- package/dist/commands/cli/hermes-commands.js +108 -0
- package/dist/commands/cli/improve-command.js +123 -0
- package/dist/commands/cli/native-engine-commands.js +102 -3
- package/dist/commands/cli/utility-commands.js +45 -0
- package/dist/commands/enhanced-command-handler.js +2 -2
- package/dist/commands/goal-cli.d.ts +30 -0
- package/dist/commands/goal-cli.js +210 -27
- package/dist/commands/handlers/goal-handler.d.ts +9 -2
- package/dist/commands/handlers/goal-handler.js +36 -9
- package/dist/commands/handlers/infra-handlers.js +36 -0
- package/dist/commands/handlers/memory-handlers.js +96 -1
- package/dist/commands/handlers/missing-handlers.d.ts +1 -1
- package/dist/commands/handlers/missing-handlers.js +26 -3
- package/dist/commands/headless-slash.d.ts +2 -0
- package/dist/commands/headless-slash.js +12 -0
- package/dist/commands/llm-provider-resolution.d.ts +5 -3
- package/dist/commands/llm-provider-resolution.js +87 -33
- package/dist/commands/ollama.d.ts +25 -0
- package/dist/commands/ollama.js +100 -0
- package/dist/commands/provider.d.ts +5 -0
- package/dist/commands/provider.js +106 -55
- package/dist/commands/skills-cli/index.js +123 -0
- package/dist/commands/slash/builtin-commands.js +1 -1
- package/dist/commands/spec-next.js +2 -1
- package/dist/commands/spec-plan.js +5 -16
- package/dist/commands/tunnel.d.ts +2 -0
- package/dist/commands/tunnel.js +48 -0
- package/dist/companion/percepts.js +11 -1
- package/dist/config/config-resolver.d.ts +2 -1
- package/dist/config/config-resolver.js +54 -41
- package/dist/config/constants.d.ts +28 -0
- package/dist/config/constants.js +7 -0
- package/dist/config/env-schema.js +756 -0
- package/dist/config/model-tools.js +4 -4
- package/dist/config/toml-config.d.ts +16 -0
- package/dist/config/toml-config.js +3 -0
- package/dist/context/bootstrap-loader.js +6 -23
- package/dist/context/context-manager-v2.js +1 -0
- package/dist/context/import-directive-parser.d.ts +4 -0
- package/dist/context/import-directive-parser.js +51 -6
- package/dist/context/instruction-excludes.d.ts +30 -1
- package/dist/context/instruction-excludes.js +71 -1
- package/dist/context/jit-context.d.ts +8 -10
- package/dist/context/jit-context.js +28 -106
- package/dist/context/project-context.d.ts +90 -0
- package/dist/context/project-context.js +295 -0
- package/dist/daemon/autonomous-daemon.d.ts +1 -1
- package/dist/daemon/autonomous-daemon.js +3 -3
- package/dist/daemon/autonomous-loop.d.ts +31 -1
- package/dist/daemon/autonomous-loop.js +91 -4
- package/dist/daemon/colab-goal.js +9 -1
- package/dist/daemon/cron-agent-bridge.d.ts +12 -3
- package/dist/daemon/cron-agent-bridge.js +25 -9
- package/dist/desktop/codebuddy-engine-adapter.d.ts +32 -0
- package/dist/desktop/codebuddy-engine-adapter.js +257 -80
- package/dist/desktop/engine-adapter.d.ts +14 -0
- package/dist/desktop-automation/automation-manager.js +16 -0
- package/dist/desktop-automation/omniparser-runner.d.ts +63 -0
- package/dist/desktop-automation/omniparser-runner.js +115 -0
- package/dist/desktop-automation/smart-snapshot.d.ts +11 -0
- package/dist/desktop-automation/smart-snapshot.js +72 -5
- package/dist/doctor/index.js +40 -23
- package/dist/events/types.d.ts +11 -0
- package/dist/fleet/colab-store.js +14 -2
- package/dist/fleet/peer-session-bridge.js +50 -12
- package/dist/fleet/peer-tool-bridge.js +14 -0
- package/dist/goals/goal-decomposer.d.ts +27 -0
- package/dist/goals/goal-decomposer.js +293 -0
- package/dist/goals/goal-judge-client.d.ts +15 -0
- package/dist/goals/goal-judge-client.js +45 -0
- package/dist/goals/goal-judge.d.ts +2 -0
- package/dist/goals/goal-judge.js +35 -6
- package/dist/goals/goal-loop.d.ts +14 -0
- package/dist/goals/goal-loop.js +47 -2
- package/dist/goals/goal-manager.d.ts +6 -0
- package/dist/goals/goal-manager.js +67 -14
- package/dist/goals/goal-state.d.ts +13 -0
- package/dist/goals/goal-state.js +83 -13
- package/dist/goals/goal-store.d.ts +3 -0
- package/dist/goals/goal-store.js +31 -15
- package/dist/harness/contract.d.ts +28 -28
- package/dist/hooks/user-hooks.js +17 -3
- package/dist/identity/identity-manager.js +3 -2
- package/dist/index.js +481 -26
- package/dist/input/text-to-speech.d.ts +2 -6
- package/dist/input/text-to-speech.js +2 -27
- package/dist/integrations/screenpipe/screenpipe-client.d.ts +10 -0
- package/dist/integrations/screenpipe/screenpipe-client.js +12 -2
- package/dist/integrations/tailscale.d.ts +13 -0
- package/dist/integrations/tailscale.js +87 -34
- package/dist/knowledge/workspace-indexer.js +53 -9
- package/dist/mcp/client.js +1 -0
- package/dist/mcp/mcp-desktop-tools.d.ts +23 -0
- package/dist/mcp/mcp-desktop-tools.js +158 -0
- package/dist/mcp/mcp-resources.js +2 -3
- package/dist/mcp/mcp-server.js +2 -0
- package/dist/memory/enhanced-memory.d.ts +10 -0
- package/dist/memory/enhanced-memory.js +33 -2
- package/dist/memory/index.d.ts +3 -1
- package/dist/memory/index.js +4 -1
- package/dist/memory/memory-auto-proposer.d.ts +23 -0
- package/dist/memory/memory-auto-proposer.js +308 -0
- package/dist/memory/memory-candidate-queue.d.ts +92 -0
- package/dist/memory/memory-candidate-queue.js +261 -0
- package/dist/memory/persistent-memory.d.ts +45 -2
- package/dist/memory/persistent-memory.js +236 -40
- package/dist/ml/bayesian-qualifier.d.ts +1 -1
- package/dist/ml/bayesian-qualifier.js +35 -2
- package/dist/openclaw/gateway-bridge.js +5 -0
- package/dist/plugins/marketplace.d.ts +1 -0
- package/dist/plugins/marketplace.js +7 -0
- package/dist/prompts/execution-discipline.d.ts +14 -0
- package/dist/prompts/execution-discipline.js +29 -0
- package/dist/prompts/variation-injector.js +9 -2
- package/dist/protocols/acp/acp-agentic-runner.d.ts +7 -6
- package/dist/protocols/acp/acp-agentic-runner.js +115 -18
- package/dist/protocols/acp/acp-session-store.d.ts +23 -0
- package/dist/protocols/acp/acp-session-store.js +77 -0
- package/dist/protocols/acp/acp-stdio-server.d.ts +7 -0
- package/dist/protocols/acp/acp-stdio-server.js +71 -16
- package/dist/providers/active-llm-registry.d.ts +37 -0
- package/dist/providers/active-llm-registry.js +186 -0
- package/dist/providers/auxiliary-provider.d.ts +25 -0
- package/dist/providers/auxiliary-provider.js +192 -0
- package/dist/providers/codex-oauth.d.ts +1 -1
- package/dist/providers/codex-oauth.js +27 -4
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.js +4 -0
- package/dist/providers/provider-catalog.d.ts +70 -0
- package/dist/providers/provider-catalog.js +738 -0
- package/dist/providers/provider-fallback.d.ts +35 -0
- package/dist/providers/provider-fallback.js +171 -0
- package/dist/providers/xai-oauth.d.ts +128 -0
- package/dist/providers/xai-oauth.js +735 -0
- package/dist/scheduler/cron-scheduler.d.ts +15 -3
- package/dist/scheduler/cron-scheduler.js +53 -7
- package/dist/scheduler/script-runner.d.ts +2 -0
- package/dist/scheduler/script-runner.js +19 -4
- package/dist/scheduler/watchdog-handlers.js +7 -20
- package/dist/search/usearch-index.js +7 -2
- package/dist/security/tool-policy/tool-groups.js +2 -0
- package/dist/sensory/dreaming.d.ts +45 -0
- package/dist/sensory/dreaming.js +114 -0
- package/dist/sensory/heartbeat-scheduler.d.ts +38 -0
- package/dist/sensory/heartbeat-scheduler.js +72 -0
- package/dist/sensory/reactions.d.ts +24 -0
- package/dist/sensory/reactions.js +31 -0
- package/dist/sensory/screen-reaction.d.ts +23 -0
- package/dist/sensory/screen-reaction.js +59 -0
- package/dist/sensory/sensory-bridge.d.ts +23 -0
- package/dist/sensory/sensory-bridge.js +85 -0
- package/dist/sensory/sensory-memory.d.ts +20 -0
- package/dist/sensory/sensory-memory.js +39 -0
- package/dist/sensory/speech-reaction.d.ts +21 -0
- package/dist/sensory/speech-reaction.js +83 -0
- package/dist/sensory/vision-reaction.d.ts +31 -0
- package/dist/sensory/vision-reaction.js +74 -0
- package/dist/server/index.js +106 -2
- package/dist/server/routes/mobile.d.ts +12 -4
- package/dist/server/routes/mobile.js +116 -1
- package/dist/server/tls-config.d.ts +35 -0
- package/dist/server/tls-config.js +142 -0
- package/dist/server/tunnel-manager.d.ts +20 -0
- package/dist/server/tunnel-manager.js +58 -0
- package/dist/server/websocket/fleet-bridge.js +5 -0
- package/dist/services/prompt-builder.d.ts +11 -0
- package/dist/services/prompt-builder.js +124 -17
- package/dist/shared/engine-types.d.ts +15 -1
- package/dist/sidecar/sidecar-bridge.d.ts +1 -0
- package/dist/sidecar/sidecar-bridge.js +21 -10
- package/dist/skills/parser.js +3 -0
- package/dist/skills/skill-importer.d.ts +58 -0
- package/dist/skills/skill-importer.js +261 -0
- package/dist/skills/skill-sources.d.ts +20 -0
- package/dist/skills/skill-sources.js +102 -0
- package/dist/skills/types.d.ts +6 -0
- package/dist/spec/spec-store.js +8 -1
- package/dist/talk-mode/providers/audioreader-tts.d.ts +1 -1
- package/dist/talk-mode/providers/audioreader-tts.js +8 -8
- package/dist/templates/project-scaffolding.js +3 -2
- package/dist/themes/theme-schema.d.ts +10 -10
- package/dist/tools/application-profiles.js +38 -0
- package/dist/tools/bash/bash-tool.d.ts +1 -0
- package/dist/tools/bash/bash-tool.js +16 -2
- package/dist/tools/bash/command-validator.js +3 -0
- package/dist/tools/bash/rtk-rewrite.d.ts +16 -0
- package/dist/tools/bash/rtk-rewrite.js +100 -0
- package/dist/tools/bash/streaming-executor.js +14 -1
- package/dist/tools/computer-control-tool.d.ts +16 -1
- package/dist/tools/computer-control-tool.js +317 -5
- package/dist/tools/document-generator.d.ts +14 -0
- package/dist/tools/document-generator.js +79 -0
- package/dist/tools/execute-code-rpc-invoker.d.ts +26 -2
- package/dist/tools/execute-code-rpc-invoker.js +46 -5
- package/dist/tools/metadata.js +28 -0
- package/dist/tools/office-macro-tool.d.ts +10 -0
- package/dist/tools/office-macro-tool.js +93 -0
- package/dist/tools/register-tool-handler.d.ts +25 -0
- package/dist/tools/register-tool-handler.js +100 -0
- package/dist/tools/registry/index.d.ts +2 -1
- package/dist/tools/registry/index.js +2 -1
- package/dist/tools/registry/memory-tools.d.ts +20 -0
- package/dist/tools/registry/memory-tools.js +225 -3
- package/dist/tools/registry/multimodal-tools.js +2 -2
- package/dist/tools/registry/vision-tools.d.ts +33 -0
- package/dist/tools/registry/vision-tools.js +308 -6
- package/dist/tools/registry/windows-tools.d.ts +2 -0
- package/dist/tools/registry/windows-tools.js +47 -0
- package/dist/tools/registry.d.ts +6 -0
- package/dist/tools/registry.js +8 -0
- package/dist/tools/route-peer-tool.js +14 -0
- package/dist/tools/screenshot-tool.js +14 -2
- package/dist/tools/text-to-speech-tool.d.ts +1 -1
- package/dist/tools/text-to-speech-tool.js +2 -12
- package/dist/tools/tool-selector.js +3 -59
- package/dist/utils/config-validation/schema.d.ts +40 -7
- package/dist/utils/config-validation/schema.js +130 -1
- package/dist/utils/cost-tracker.js +21 -1
- package/dist/utils/disk-guard.d.ts +180 -0
- package/dist/utils/disk-guard.js +404 -0
- package/dist/utils/init-project.d.ts +7 -0
- package/dist/utils/init-project.js +37 -0
- package/dist/utils/interactive-setup.js +35 -2
- package/dist/utils/model-utils.js +11 -2
- package/dist/utils/output-sanitizer.js +11 -0
- package/dist/utils/provider-detector.d.ts +8 -7
- package/dist/utils/provider-detector.js +19 -77
- package/dist/utils/settings-manager.d.ts +19 -0
- package/dist/utils/token-display.d.ts +3 -3
- package/dist/utils/token-display.js +22 -4
- package/dist/wizard/onboarding.d.ts +39 -0
- package/dist/wizard/onboarding.js +433 -21
- package/dist/wizard/provider-onboarding.d.ts +8 -23
- package/dist/wizard/provider-onboarding.js +39 -158
- package/package.json +4 -2
- package/dist/plugins/provider-onboarding.d.ts +0 -23
- package/dist/plugins/provider-onboarding.js +0 -116
- package/dist/utils/kokoro-tts.d.ts +0 -8
- package/dist/utils/kokoro-tts.js +0 -67
|
@@ -190,8 +190,17 @@ export class BayesianQualifier {
|
|
|
190
190
|
* Load the qualifier state from a JSON string
|
|
191
191
|
*/
|
|
192
192
|
loadState(stateJson) {
|
|
193
|
+
const trimmed = stateJson.trim();
|
|
194
|
+
if (!trimmed) {
|
|
195
|
+
logger.debug('[BayesianQualifier] Ignoring empty persisted state');
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
193
198
|
try {
|
|
194
|
-
const
|
|
199
|
+
const parsed = JSON.parse(trimmed);
|
|
200
|
+
if (!isBayesianState(parsed)) {
|
|
201
|
+
throw new Error('invalid bayesian state shape');
|
|
202
|
+
}
|
|
203
|
+
const state = parsed;
|
|
195
204
|
this.X = state.X;
|
|
196
205
|
this.y = state.y;
|
|
197
206
|
this.scaler.means = state.means;
|
|
@@ -202,9 +211,12 @@ export class BayesianQualifier {
|
|
|
202
211
|
if (this.X.length > 0) {
|
|
203
212
|
this.train();
|
|
204
213
|
}
|
|
214
|
+
return true;
|
|
205
215
|
}
|
|
206
216
|
catch (err) {
|
|
207
|
-
|
|
217
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
218
|
+
logger.debug(`[BayesianQualifier] Ignoring invalid persisted state: ${message}`);
|
|
219
|
+
return false;
|
|
208
220
|
}
|
|
209
221
|
}
|
|
210
222
|
// ============================================================================
|
|
@@ -248,4 +260,25 @@ export class BayesianQualifier {
|
|
|
248
260
|
return x;
|
|
249
261
|
}
|
|
250
262
|
}
|
|
263
|
+
function isNumberArray(value) {
|
|
264
|
+
return Array.isArray(value) && value.every(item => typeof item === 'number' && Number.isFinite(item));
|
|
265
|
+
}
|
|
266
|
+
function isNumberMatrix(value) {
|
|
267
|
+
return Array.isArray(value) && value.every(isNumberArray);
|
|
268
|
+
}
|
|
269
|
+
function isBayesianState(value) {
|
|
270
|
+
if (!value || typeof value !== 'object')
|
|
271
|
+
return false;
|
|
272
|
+
const state = value;
|
|
273
|
+
return (isNumberMatrix(state.X) &&
|
|
274
|
+
isNumberArray(state.y) &&
|
|
275
|
+
isNumberArray(state.means) &&
|
|
276
|
+
isNumberArray(state.stds) &&
|
|
277
|
+
typeof state.lengthScale === 'number' &&
|
|
278
|
+
Number.isFinite(state.lengthScale) &&
|
|
279
|
+
typeof state.signalVariance === 'number' &&
|
|
280
|
+
Number.isFinite(state.signalVariance) &&
|
|
281
|
+
typeof state.noiseVariance === 'number' &&
|
|
282
|
+
Number.isFinite(state.noiseVariance));
|
|
283
|
+
}
|
|
251
284
|
//# sourceMappingURL=bayesian-qualifier.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { constants as fsConstants } from 'fs';
|
|
2
2
|
import { access, appendFile, mkdir, readFile, writeFile } from 'fs/promises';
|
|
3
|
+
import { rotateIfLarge } from '../utils/disk-guard.js';
|
|
3
4
|
import * as os from 'os';
|
|
4
5
|
import * as path from 'path';
|
|
5
6
|
import { createPublicKey, randomUUID, sign as signPayload } from 'crypto';
|
|
@@ -355,6 +356,7 @@ function responseSummary(response) {
|
|
|
355
356
|
}
|
|
356
357
|
async function appendAttachRecord(attachLogPath, record) {
|
|
357
358
|
await mkdir(path.dirname(attachLogPath), { recursive: true });
|
|
359
|
+
rotateIfLarge(attachLogPath);
|
|
358
360
|
await appendFile(attachLogPath, `${JSON.stringify(record)}\n`, 'utf8');
|
|
359
361
|
}
|
|
360
362
|
function sendResponseSummary(response) {
|
|
@@ -378,14 +380,17 @@ function sendResponseSummary(response) {
|
|
|
378
380
|
}
|
|
379
381
|
async function appendSendRecord(sendLogPath, record) {
|
|
380
382
|
await mkdir(path.dirname(sendLogPath), { recursive: true });
|
|
383
|
+
rotateIfLarge(sendLogPath);
|
|
381
384
|
await appendFile(sendLogPath, `${JSON.stringify(record)}\n`, 'utf8');
|
|
382
385
|
}
|
|
383
386
|
async function appendWebSocketProbeRecord(probeLogPath, record) {
|
|
384
387
|
await mkdir(path.dirname(probeLogPath), { recursive: true });
|
|
388
|
+
rotateIfLarge(probeLogPath);
|
|
385
389
|
await appendFile(probeLogPath, `${JSON.stringify(record)}\n`, 'utf8');
|
|
386
390
|
}
|
|
387
391
|
async function appendWebSocketCallRecord(callLogPath, record) {
|
|
388
392
|
await mkdir(path.dirname(callLogPath), { recursive: true });
|
|
393
|
+
rotateIfLarge(callLogPath);
|
|
389
394
|
await appendFile(callLogPath, `${JSON.stringify(record)}\n`, 'utf8');
|
|
390
395
|
}
|
|
391
396
|
function parseOpenClawWebSocketFrame(data) {
|
|
@@ -41,6 +41,7 @@ export class PluginMarketplace extends EventEmitter {
|
|
|
41
41
|
providers = new Map();
|
|
42
42
|
hooks = new Map();
|
|
43
43
|
updateCheckerIntervalId = null;
|
|
44
|
+
disposed = false;
|
|
44
45
|
constructor(config = {}) {
|
|
45
46
|
super();
|
|
46
47
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
@@ -55,6 +56,8 @@ export class PluginMarketplace extends EventEmitter {
|
|
|
55
56
|
await fs.ensureDir(path.join(this.pluginsDir, 'installed'));
|
|
56
57
|
await fs.ensureDir(path.join(this.pluginsDir, 'cache'));
|
|
57
58
|
await this.loadInstalledPlugins();
|
|
59
|
+
if (this.disposed)
|
|
60
|
+
return;
|
|
58
61
|
if (this.config.autoUpdate) {
|
|
59
62
|
this.startUpdateChecker();
|
|
60
63
|
}
|
|
@@ -273,9 +276,12 @@ export class PluginMarketplace extends EventEmitter {
|
|
|
273
276
|
* Start update checker
|
|
274
277
|
*/
|
|
275
278
|
startUpdateChecker() {
|
|
279
|
+
if (this.disposed || this.updateCheckerIntervalId)
|
|
280
|
+
return;
|
|
276
281
|
this.updateCheckerIntervalId = setInterval(() => {
|
|
277
282
|
this.checkUpdates();
|
|
278
283
|
}, this.config.checkUpdatesInterval);
|
|
284
|
+
this.updateCheckerIntervalId.unref?.();
|
|
279
285
|
}
|
|
280
286
|
/**
|
|
281
287
|
* Validate plugin path is within allowed directory
|
|
@@ -641,6 +647,7 @@ export class PluginMarketplace extends EventEmitter {
|
|
|
641
647
|
* Dispose
|
|
642
648
|
*/
|
|
643
649
|
async dispose() {
|
|
650
|
+
this.disposed = true;
|
|
644
651
|
if (this.updateCheckerIntervalId) {
|
|
645
652
|
clearInterval(this.updateCheckerIntervalId);
|
|
646
653
|
this.updateCheckerIntervalId = null;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution-discipline guidance — the highest-leverage prompt block borrowed
|
|
3
|
+
* from the Hermes Agent prompt audit (2026-06-16). Hermes ships an always-on
|
|
4
|
+
* `TASK_COMPLETION_GUIDANCE` + `<tool_persistence>` / `<mandatory_tool_use>` /
|
|
5
|
+
* `<verification>` set that pushes the model to *act with tools and deliver a
|
|
6
|
+
* verified artifact* rather than describe one. Code Buddy previously had only a
|
|
7
|
+
* gated `workflow-rules` Verification Contract (off for simple/lite queries) and
|
|
8
|
+
* no anti-stub / tool-persistence / mandatory-tool guidance at all.
|
|
9
|
+
*
|
|
10
|
+
* Kept short (~12 lines, ~150 tokens) and model-agnostic. Gated off for
|
|
11
|
+
* trivial/lite queries and for models without tool-call support
|
|
12
|
+
* (see prompt-builder.ts gating).
|
|
13
|
+
*/
|
|
14
|
+
export declare function getExecutionDisciplineBlock(): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution-discipline guidance — the highest-leverage prompt block borrowed
|
|
3
|
+
* from the Hermes Agent prompt audit (2026-06-16). Hermes ships an always-on
|
|
4
|
+
* `TASK_COMPLETION_GUIDANCE` + `<tool_persistence>` / `<mandatory_tool_use>` /
|
|
5
|
+
* `<verification>` set that pushes the model to *act with tools and deliver a
|
|
6
|
+
* verified artifact* rather than describe one. Code Buddy previously had only a
|
|
7
|
+
* gated `workflow-rules` Verification Contract (off for simple/lite queries) and
|
|
8
|
+
* no anti-stub / tool-persistence / mandatory-tool guidance at all.
|
|
9
|
+
*
|
|
10
|
+
* Kept short (~12 lines, ~150 tokens) and model-agnostic. Gated off for
|
|
11
|
+
* trivial/lite queries and for models without tool-call support
|
|
12
|
+
* (see prompt-builder.ts gating).
|
|
13
|
+
*/
|
|
14
|
+
export function getExecutionDisciplineBlock() {
|
|
15
|
+
return [
|
|
16
|
+
'## Execution discipline',
|
|
17
|
+
'You take ACTION with tools — you do not describe what you would do. Each response either makes',
|
|
18
|
+
'progress via tool calls or delivers a verified final result.',
|
|
19
|
+
'- The deliverable is a working artifact backed by real tool output, not a description of one.',
|
|
20
|
+
' Do not stop after writing a stub, a plan, or a single command.',
|
|
21
|
+
'- Keep using tools until (1) the task is complete AND (2) you have verified the result with a tool',
|
|
22
|
+
' (test output, file read-back, command exit code). Never claim success you have not verified.',
|
|
23
|
+
'- For anything checkable — file contents, git state, arithmetic, current time, command results —',
|
|
24
|
+
' ALWAYS use a tool. Never guess or fabricate tool output.',
|
|
25
|
+
'- Before finalizing, self-check: Correctness (every requirement met?), Grounding (claims backed by',
|
|
26
|
+
' tool output?), Scope (no unintended file changes?).',
|
|
27
|
+
].join('\n');
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=execution-discipline.js.map
|
|
@@ -142,11 +142,18 @@ export function extractBlocks(prompt) {
|
|
|
142
142
|
const prefix = lines.slice(0, blockStart).join('\n');
|
|
143
143
|
const rawBlocks = lines.slice(blockStart, blockEnd);
|
|
144
144
|
const suffix = '';
|
|
145
|
-
// Split rawBlocks into
|
|
145
|
+
// Split rawBlocks into HEADING-ATOMIC sections: a new block begins at every
|
|
146
|
+
// `##`/`###` heading and absorbs ALL following lines (bullets, numbered items,
|
|
147
|
+
// blank lines) until the next heading. Previously this split at every bullet
|
|
148
|
+
// line, so the Fisher-Yates shuffle in applyVariation() interleaved foreign
|
|
149
|
+
// bullets (e.g. tool-parameter docs) into the middle of a `##`-headed block
|
|
150
|
+
// such as the Verification Contract (`## Workflow Orchestration`), corrupting
|
|
151
|
+
// structured guidance. Heading-atomic grouping shuffles whole sections instead
|
|
152
|
+
// — the anti-repetition variation is preserved, but no block is ever fragmented.
|
|
146
153
|
const blocks = [];
|
|
147
154
|
let current = '';
|
|
148
155
|
for (const line of rawBlocks) {
|
|
149
|
-
if ((line.
|
|
156
|
+
if (/^#{2,3}\s+/.test(line.trim()) && current.trim()) {
|
|
150
157
|
blocks.push(current.trim());
|
|
151
158
|
current = line;
|
|
152
159
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* (https://agentclientprotocol.com). Unlike the original text-only runner,
|
|
6
6
|
* this drives a real agentic loop:
|
|
7
7
|
*
|
|
8
|
-
* 1. Ask the LLM (with a small
|
|
8
|
+
* 1. Ask the LLM (with a small toolset) for the next step.
|
|
9
9
|
* 2. If it emits tool calls, EXECUTE each one and feed the result back.
|
|
10
10
|
* 3. Repeat until the model stops calling tools (`end_turn`) or we hit
|
|
11
11
|
* the round cap (`max_turn_requests`).
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
* `session/request_permission` when that round-trip is available; a
|
|
27
27
|
* rejection fails the tool call instead of leaking content.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
* `search`)
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* Read-only tools are always exposed (`view_file`, `list_directory`,
|
|
30
|
+
* `search`). `write_file` is exposed only when the editor advertises
|
|
31
|
+
* `fs.writeTextFile`, and the write is routed through the editor permission
|
|
32
|
+
* flow. Cancellation is honoured by checking `signal.aborted` on every loop
|
|
33
|
+
* iteration and after every client round-trip.
|
|
33
34
|
*/
|
|
34
35
|
import type { AcpPromptContext, AcpStopReason } from './acp-stdio-server.js';
|
|
35
36
|
import type { CodeBuddyMessage, CodeBuddyResponse, CodeBuddyTool } from '../../codebuddy/client.js';
|
|
@@ -50,5 +51,5 @@ export interface AcpAgenticRunnerOptions {
|
|
|
50
51
|
export declare function createAcpAgenticRunner(options: AcpAgenticRunnerOptions): (ctx: AcpPromptContext) => Promise<{
|
|
51
52
|
stopReason: AcpStopReason;
|
|
52
53
|
}>;
|
|
53
|
-
/** Test-only: the static read-only toolset this runner exposes. */
|
|
54
|
+
/** Test-only: the static read-only toolset this runner always exposes. */
|
|
54
55
|
export declare const ACP_READONLY_TOOLS: ReadonlyArray<CodeBuddyTool>;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* (https://agentclientprotocol.com). Unlike the original text-only runner,
|
|
6
6
|
* this drives a real agentic loop:
|
|
7
7
|
*
|
|
8
|
-
* 1. Ask the LLM (with a small
|
|
8
|
+
* 1. Ask the LLM (with a small toolset) for the next step.
|
|
9
9
|
* 2. If it emits tool calls, EXECUTE each one and feed the result back.
|
|
10
10
|
* 3. Repeat until the model stops calling tools (`end_turn`) or we hit
|
|
11
11
|
* the round cap (`max_turn_requests`).
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
* `session/request_permission` when that round-trip is available; a
|
|
27
27
|
* rejection fails the tool call instead of leaking content.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
* `search`)
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* Read-only tools are always exposed (`view_file`, `list_directory`,
|
|
30
|
+
* `search`). `write_file` is exposed only when the editor advertises
|
|
31
|
+
* `fs.writeTextFile`, and the write is routed through the editor permission
|
|
32
|
+
* flow. Cancellation is honoured by checking `signal.aborted` on every loop
|
|
33
|
+
* iteration and after every client round-trip.
|
|
33
34
|
*/
|
|
34
35
|
import { spawn } from 'child_process';
|
|
35
36
|
import { rgPath } from '@vscode/ripgrep';
|
|
@@ -42,9 +43,9 @@ const LIST_DIRECTORY_MAX_ENTRIES = 256;
|
|
|
42
43
|
const SEARCH_TIMEOUT_MS = 30_000;
|
|
43
44
|
const SEARCH_MAX_RESULTS = 200;
|
|
44
45
|
const SYSTEM_PROMPT = 'You are Code Buddy, a coding assistant operating over the Agent Client Protocol ' +
|
|
45
|
-
'inside a code editor.
|
|
46
|
-
'
|
|
47
|
-
'
|
|
46
|
+
'inside a code editor. Use the tools provided for this turn when you need workspace context. ' +
|
|
47
|
+
'If write_file is not available, never claim to have modified files. If write_file is available, ' +
|
|
48
|
+
'writes are routed through the editor and require client permission. Answer concisely in Markdown.';
|
|
48
49
|
const READONLY_TOOLS = [
|
|
49
50
|
{
|
|
50
51
|
type: 'function',
|
|
@@ -90,11 +91,26 @@ const READONLY_TOOLS = [
|
|
|
90
91
|
},
|
|
91
92
|
},
|
|
92
93
|
];
|
|
93
|
-
|
|
94
|
+
const WRITE_FILE_TOOL = {
|
|
95
|
+
type: 'function',
|
|
96
|
+
function: {
|
|
97
|
+
name: 'write_file',
|
|
98
|
+
description: 'Write text content to a file through the editor client. Will overwrite existing files after permission.',
|
|
99
|
+
parameters: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
file_path: { type: 'string', description: 'Path to the file (absolute, or relative to the workspace).' },
|
|
103
|
+
content: { type: 'string', description: 'The exact string content to write into the file.' },
|
|
104
|
+
},
|
|
105
|
+
required: ['file_path', 'content'],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
94
109
|
const TOOL_KIND = {
|
|
95
110
|
view_file: 'read',
|
|
96
111
|
list_directory: 'read',
|
|
97
112
|
search: 'search',
|
|
113
|
+
write_file: 'edit',
|
|
98
114
|
};
|
|
99
115
|
/**
|
|
100
116
|
* Build an injectable ACP prompt runner that performs a bounded,
|
|
@@ -103,22 +119,63 @@ const TOOL_KIND = {
|
|
|
103
119
|
export function createAcpAgenticRunner(options) {
|
|
104
120
|
const maxRounds = options.maxRounds ?? DEFAULT_MAX_ROUNDS;
|
|
105
121
|
const maxToolOutputBytes = options.maxToolOutputBytes ?? DEFAULT_MAX_TOOL_OUTPUT_BYTES;
|
|
122
|
+
// Cache of MCPClientManager instances per session, so we don't reconnect on every prompt
|
|
123
|
+
const mcpManagers = new Map();
|
|
106
124
|
return async function run(ctx) {
|
|
107
125
|
const userText = extractPromptText(ctx.prompt);
|
|
108
126
|
if (!userText) {
|
|
109
127
|
return { stopReason: 'end_turn' };
|
|
110
128
|
}
|
|
129
|
+
let mcpManager = mcpManagers.get(ctx.sessionId);
|
|
130
|
+
if (!mcpManager && ctx.mcpServers) {
|
|
131
|
+
try {
|
|
132
|
+
const { MCPManager } = await import('../../mcp/client.js');
|
|
133
|
+
mcpManager = new MCPManager();
|
|
134
|
+
mcpManagers.set(ctx.sessionId, mcpManager);
|
|
135
|
+
const servers = Array.isArray(ctx.mcpServers)
|
|
136
|
+
? ctx.mcpServers
|
|
137
|
+
: typeof ctx.mcpServers === 'object' && ctx.mcpServers !== null
|
|
138
|
+
? Object.entries(ctx.mcpServers).map(([name, conf]) => ({ name, ...conf }))
|
|
139
|
+
: [];
|
|
140
|
+
for (const server of servers) {
|
|
141
|
+
try {
|
|
142
|
+
await mcpManager.addServer(server);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
logger.warn(`Failed to add MCP server ${server.name}`, { error: String(e) });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
logger.warn('Failed to initialize MCPManager for passthrough', { error: String(e) });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
111
153
|
const messages = [
|
|
112
154
|
{ role: 'system', content: SYSTEM_PROMPT },
|
|
113
155
|
{ role: 'user', content: userText },
|
|
114
156
|
];
|
|
157
|
+
const allTools = [...READONLY_TOOLS];
|
|
158
|
+
if (ctx.canRequestClient('fs/write_text_file')) {
|
|
159
|
+
allTools.push(WRITE_FILE_TOOL);
|
|
160
|
+
}
|
|
161
|
+
if (mcpManager) {
|
|
162
|
+
const mcpTools = mcpManager.getTools().map((tool) => ({
|
|
163
|
+
type: 'function',
|
|
164
|
+
function: {
|
|
165
|
+
name: tool.name,
|
|
166
|
+
description: tool.description,
|
|
167
|
+
parameters: tool.inputSchema,
|
|
168
|
+
}
|
|
169
|
+
}));
|
|
170
|
+
allTools.push(...mcpTools);
|
|
171
|
+
}
|
|
115
172
|
let toolCallSeq = 0;
|
|
116
173
|
for (let round = 0; round < maxRounds; round++) {
|
|
117
174
|
if (ctx.signal.aborted)
|
|
118
175
|
return { stopReason: 'cancelled' };
|
|
119
176
|
let response;
|
|
120
177
|
try {
|
|
121
|
-
response = await options.chat(messages,
|
|
178
|
+
response = await options.chat(messages, allTools);
|
|
122
179
|
}
|
|
123
180
|
catch (err) {
|
|
124
181
|
if (ctx.signal.aborted)
|
|
@@ -164,13 +221,28 @@ export function createAcpAgenticRunner(options) {
|
|
|
164
221
|
status: 'in_progress',
|
|
165
222
|
rawInput: args,
|
|
166
223
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
224
|
+
let result;
|
|
225
|
+
if (call.function.name.startsWith('mcp__') && mcpManager) {
|
|
226
|
+
try {
|
|
227
|
+
const mcpRes = await mcpManager.callTool(call.function.name, args);
|
|
228
|
+
const outputText = Array.isArray(mcpRes.content)
|
|
229
|
+
? mcpRes.content.map((c) => c.text).join('\n')
|
|
230
|
+
: String(mcpRes);
|
|
231
|
+
result = { output: outputText, isError: !!mcpRes.isError };
|
|
232
|
+
}
|
|
233
|
+
catch (e) {
|
|
234
|
+
result = { output: String(e), isError: true };
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
result = await executeAcpTool({
|
|
239
|
+
name: call.function.name,
|
|
240
|
+
args,
|
|
241
|
+
ctx,
|
|
242
|
+
toolCallId,
|
|
243
|
+
maxToolOutputBytes,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
174
246
|
if (ctx.signal.aborted)
|
|
175
247
|
return { stopReason: 'cancelled' };
|
|
176
248
|
ctx.sendUpdate({
|
|
@@ -205,6 +277,8 @@ async function executeAcpTool(input) {
|
|
|
205
277
|
return { output: await listDirectory(args, ctx.cwd), isError: false };
|
|
206
278
|
case 'search':
|
|
207
279
|
return { output: await searchWorkspace(args, ctx.cwd, maxToolOutputBytes), isError: false };
|
|
280
|
+
case 'write_file':
|
|
281
|
+
return { output: await writeFileViaClientOrDisk(args, ctx, toolCallId), isError: false };
|
|
208
282
|
default:
|
|
209
283
|
return { output: `Unknown tool: ${name}`, isError: true };
|
|
210
284
|
}
|
|
@@ -248,6 +322,29 @@ async function readFileViaClientOrDisk(args, ctx, toolCallId, maxBytes) {
|
|
|
248
322
|
const content = await fs.readFile(resolved, 'utf-8');
|
|
249
323
|
return truncate(content, maxBytes);
|
|
250
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Write a file through the editor client. There is deliberately no direct disk
|
|
327
|
+
* fallback: ACP writes are only allowed when the editor advertises
|
|
328
|
+
* `fs.writeTextFile`, and they are always gated by client permission.
|
|
329
|
+
*/
|
|
330
|
+
async function writeFileViaClientOrDisk(args, ctx, toolCallId) {
|
|
331
|
+
const rawPath = stringArg(args, 'file_path') ?? stringArg(args, 'path');
|
|
332
|
+
const content = stringArg(args, 'content');
|
|
333
|
+
if (!rawPath)
|
|
334
|
+
throw new Error('write_file: missing string file_path');
|
|
335
|
+
if (typeof content !== 'string')
|
|
336
|
+
throw new Error('write_file: missing string content');
|
|
337
|
+
if (!ctx.canRequestClient('fs/write_text_file')) {
|
|
338
|
+
throw new Error('write_file is unavailable because the ACP client did not advertise fs.writeTextFile.');
|
|
339
|
+
}
|
|
340
|
+
const absolute = path.isAbsolute(rawPath) ? rawPath : path.resolve(ctx.cwd, rawPath);
|
|
341
|
+
const allowed = await requestPermission(ctx, toolCallId, absolute);
|
|
342
|
+
if (!allowed) {
|
|
343
|
+
throw new Error(`Permission to write ${rawPath} was denied by the editor.`);
|
|
344
|
+
}
|
|
345
|
+
await ctx.requestClient('fs/write_text_file', { sessionId: ctx.sessionId, path: absolute, content });
|
|
346
|
+
return `Successfully wrote to ${rawPath} via editor client`;
|
|
347
|
+
}
|
|
251
348
|
async function requestPermission(ctx, toolCallId, target) {
|
|
252
349
|
const outcome = await ctx.requestClient('session/request_permission', {
|
|
253
350
|
sessionId: ctx.sessionId,
|
|
@@ -402,6 +499,6 @@ function truncate(text, maxBytes) {
|
|
|
402
499
|
return text;
|
|
403
500
|
return `${text.slice(0, maxBytes)}\n... [truncated]`;
|
|
404
501
|
}
|
|
405
|
-
/** Test-only: the static read-only toolset this runner exposes. */
|
|
502
|
+
/** Test-only: the static read-only toolset this runner always exposes. */
|
|
406
503
|
export const ACP_READONLY_TOOLS = READONLY_TOOLS;
|
|
407
504
|
//# sourceMappingURL=acp-agentic-runner.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface AcpPersistedSession {
|
|
2
|
+
sessionId: string;
|
|
3
|
+
cwd: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
history: unknown[];
|
|
6
|
+
mcpServers?: unknown;
|
|
7
|
+
updatedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AcpSessionStoreConfig {
|
|
10
|
+
storeDir?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class AcpSessionStore {
|
|
13
|
+
private readonly dir;
|
|
14
|
+
constructor(config?: AcpSessionStoreConfig);
|
|
15
|
+
save(session: AcpPersistedSession): Promise<void>;
|
|
16
|
+
load(sessionId: string): Promise<AcpPersistedSession | null>;
|
|
17
|
+
delete(sessionId: string): Promise<void>;
|
|
18
|
+
listAll(): Promise<AcpPersistedSession[]>;
|
|
19
|
+
private writeUnlocked;
|
|
20
|
+
private fileFor;
|
|
21
|
+
private ensureDir;
|
|
22
|
+
private defaultDir;
|
|
23
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { withSessionLock } from '../../persistence/session-lock.js';
|
|
5
|
+
import { logger } from '../../utils/logger.js';
|
|
6
|
+
export class AcpSessionStore {
|
|
7
|
+
dir;
|
|
8
|
+
constructor(config = {}) {
|
|
9
|
+
this.dir = config.storeDir ?? this.defaultDir();
|
|
10
|
+
this.ensureDir();
|
|
11
|
+
}
|
|
12
|
+
async save(session) {
|
|
13
|
+
const file = this.fileFor(session.sessionId);
|
|
14
|
+
await withSessionLock(file, async () => {
|
|
15
|
+
await this.writeUnlocked(session);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async load(sessionId) {
|
|
19
|
+
const file = this.fileFor(sessionId);
|
|
20
|
+
if (!fs.existsSync(file))
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const raw = await fs.promises.readFile(file, 'utf-8');
|
|
24
|
+
return JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
logger.warn?.('[acp-session-store] failed to read session', {
|
|
28
|
+
sessionId,
|
|
29
|
+
error: err instanceof Error ? err.message : String(err),
|
|
30
|
+
});
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async delete(sessionId) {
|
|
35
|
+
const file = this.fileFor(sessionId);
|
|
36
|
+
await withSessionLock(file, async () => {
|
|
37
|
+
if (fs.existsSync(file)) {
|
|
38
|
+
await fs.promises.unlink(file);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async listAll() {
|
|
43
|
+
if (!fs.existsSync(this.dir))
|
|
44
|
+
return [];
|
|
45
|
+
const files = await fs.promises.readdir(this.dir);
|
|
46
|
+
const sessions = [];
|
|
47
|
+
for (const f of files) {
|
|
48
|
+
if (!f.endsWith('.json'))
|
|
49
|
+
continue;
|
|
50
|
+
const sessionId = f.slice(0, -5);
|
|
51
|
+
const s = await this.load(sessionId);
|
|
52
|
+
if (s)
|
|
53
|
+
sessions.push(s);
|
|
54
|
+
}
|
|
55
|
+
return sessions;
|
|
56
|
+
}
|
|
57
|
+
async writeUnlocked(session) {
|
|
58
|
+
const file = this.fileFor(session.sessionId);
|
|
59
|
+
const temp = `${file}.tmp.${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
60
|
+
await fs.promises.writeFile(temp, JSON.stringify(session, null, 2), 'utf-8');
|
|
61
|
+
await fs.promises.rename(temp, file);
|
|
62
|
+
}
|
|
63
|
+
fileFor(sessionId) {
|
|
64
|
+
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
65
|
+
return path.join(this.dir, `${safe}.json`);
|
|
66
|
+
}
|
|
67
|
+
ensureDir() {
|
|
68
|
+
if (!fs.existsSync(this.dir)) {
|
|
69
|
+
fs.mkdirSync(this.dir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
defaultDir() {
|
|
73
|
+
const home = os.homedir();
|
|
74
|
+
return path.join(home, '.codebuddy', 'acp-sessions');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=acp-session-store.js.map
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
* backed by client `fs/*` + `session/request_permission`, and MCP passthrough.
|
|
31
31
|
*/
|
|
32
32
|
import type { Readable, Writable } from 'node:stream';
|
|
33
|
+
import { AcpSessionStore } from './acp-session-store.js';
|
|
33
34
|
export declare const ACP_PROTOCOL_VERSION = 1;
|
|
34
35
|
export interface AcpContentBlock {
|
|
35
36
|
type: string;
|
|
@@ -53,6 +54,7 @@ export interface AcpPromptContext {
|
|
|
53
54
|
sessionId: string;
|
|
54
55
|
cwd: string;
|
|
55
56
|
clientCapabilities: AcpClientCapabilities;
|
|
57
|
+
mcpServers?: unknown;
|
|
56
58
|
canRequestClient: (method: string) => boolean;
|
|
57
59
|
prompt: AcpContentBlock[];
|
|
58
60
|
signal: AbortSignal;
|
|
@@ -68,6 +70,7 @@ export interface AcpAgentInfo {
|
|
|
68
70
|
version: string;
|
|
69
71
|
}
|
|
70
72
|
export interface AcpStdioServerOptions {
|
|
73
|
+
store?: AcpSessionStore;
|
|
71
74
|
promptRunner: AcpPromptRunner;
|
|
72
75
|
/** Defaults to process.stdin. */
|
|
73
76
|
input?: Readable;
|
|
@@ -87,6 +90,8 @@ export declare class AcpStdioServer {
|
|
|
87
90
|
private readonly clientRequestTimeoutMs;
|
|
88
91
|
private readonly sessions;
|
|
89
92
|
private readonly pendingClientRequests;
|
|
93
|
+
private readonly store;
|
|
94
|
+
private storeLoaded;
|
|
90
95
|
private clientCapabilities;
|
|
91
96
|
private nextClientRequestId;
|
|
92
97
|
private buffer;
|
|
@@ -98,6 +103,8 @@ export declare class AcpStdioServer {
|
|
|
98
103
|
private ingest;
|
|
99
104
|
private write;
|
|
100
105
|
private sendUpdate;
|
|
106
|
+
private ensureStoreLoaded;
|
|
107
|
+
private persistSession;
|
|
101
108
|
private requestClient;
|
|
102
109
|
private handleLine;
|
|
103
110
|
private dispatch;
|