smol-symphony 0.2.0 → 0.3.1
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/AGENTS.md +41 -22
- package/DESIGN.md +494 -273
- package/README.md +109 -57
- package/SPEC.md +33 -24
- package/WORKFLOW.minimal.yaml +34 -0
- package/{WORKFLOW.template.md → WORKFLOW.template.yaml} +409 -256
- package/WORKFLOW.yaml +487 -0
- package/assets/skills/symphony-issues/SKILL.md +136 -0
- package/assets/symphony-mise.system.toml +68 -0
- package/dist/bin/symphony.js +22 -786
- package/dist/bin/symphony.js.map +1 -1
- package/dist/core/actions/context.js +109 -0
- package/dist/core/actions/context.js.map +1 -0
- package/dist/{actions/parsing.js → core/actions/parse.js} +33 -114
- package/dist/core/actions/parse.js.map +1 -0
- package/dist/core/actions/plan.js +197 -0
- package/dist/core/actions/plan.js.map +1 -0
- package/dist/core/actions/predicates.js +111 -0
- package/dist/core/actions/predicates.js.map +1 -0
- package/dist/core/actions/run-fold.js +248 -0
- package/dist/core/actions/run-fold.js.map +1 -0
- package/dist/core/actions/template.js +118 -0
- package/dist/core/actions/template.js.map +1 -0
- package/dist/core/cli/args.js +116 -0
- package/dist/core/cli/args.js.map +1 -0
- package/dist/core/coerce.js +75 -0
- package/dist/core/coerce.js.map +1 -0
- package/dist/core/credential/account-id.js +20 -0
- package/dist/core/credential/account-id.js.map +1 -0
- package/dist/core/credential/adapter-config.js +136 -0
- package/dist/core/credential/adapter-config.js.map +1 -0
- package/dist/core/credential/availability.js +98 -0
- package/dist/core/credential/availability.js.map +1 -0
- package/dist/core/credential/extract.js +228 -0
- package/dist/core/credential/extract.js.map +1 -0
- package/dist/core/credential/fake-creds.js +171 -0
- package/dist/core/credential/fake-creds.js.map +1 -0
- package/dist/core/credential/identity.js +125 -0
- package/dist/core/credential/identity.js.map +1 -0
- package/dist/core/credential/shape.js +230 -0
- package/dist/core/credential/shape.js.map +1 -0
- package/dist/core/credential/strings.js +15 -0
- package/dist/core/credential/strings.js.map +1 -0
- package/dist/core/doctor/checks.js +303 -0
- package/dist/core/doctor/checks.js.map +1 -0
- package/dist/core/git/result.js +107 -0
- package/dist/core/git/result.js.map +1 -0
- package/dist/core/http/decisions.js +225 -0
- package/dist/core/http/decisions.js.map +1 -0
- package/dist/{http.js → core/http/render.js} +472 -738
- package/dist/core/http/render.js.map +1 -0
- package/dist/{http-handlers.js → core/http/routes.js} +52 -87
- package/dist/core/http/routes.js.map +1 -0
- package/dist/core/http/views.js +181 -0
- package/dist/core/http/views.js.map +1 -0
- package/dist/core/image/managed-image.js +95 -0
- package/dist/core/image/managed-image.js.map +1 -0
- package/dist/core/issue/file.js +149 -0
- package/dist/core/issue/file.js.map +1 -0
- package/dist/core/issue/parse.js +210 -0
- package/dist/core/issue/parse.js.map +1 -0
- package/dist/core/mcp/dispatch.js +239 -0
- package/dist/core/mcp/dispatch.js.map +1 -0
- package/dist/core/mcp/post-move.js +92 -0
- package/dist/core/mcp/post-move.js.map +1 -0
- package/dist/core/mcp/protocol.js +293 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/url.js +162 -0
- package/dist/core/mcp/url.js.map +1 -0
- package/dist/core/path.js +63 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/reconcile/image-decide.js +48 -0
- package/dist/core/reconcile/image-decide.js.map +1 -0
- package/dist/core/reconcile/ledger.js +142 -0
- package/dist/core/reconcile/ledger.js.map +1 -0
- package/dist/core/reconcile/pr-classify.js +62 -0
- package/dist/core/reconcile/pr-classify.js.map +1 -0
- package/dist/{reconciler → core/reconcile}/pr-decide.js +25 -12
- package/dist/core/reconcile/pr-decide.js.map +1 -0
- package/dist/core/reconcile/pr-loop.js +161 -0
- package/dist/core/reconcile/pr-loop.js.map +1 -0
- package/dist/core/reconcile/pr-notes.js +35 -0
- package/dist/core/reconcile/pr-notes.js.map +1 -0
- package/dist/core/reconcile/vm-decide.js +70 -0
- package/dist/core/reconcile/vm-decide.js.map +1 -0
- package/dist/core/reconcile/vm-reap.js +207 -0
- package/dist/core/reconcile/vm-reap.js.map +1 -0
- package/dist/core/reconcile/workspace-decide.js +162 -0
- package/dist/core/reconcile/workspace-decide.js.map +1 -0
- package/dist/core/runlog/summary.js +231 -0
- package/dist/core/runlog/summary.js.map +1 -0
- package/dist/core/runner/dispatch-config.js +95 -0
- package/dist/core/runner/dispatch-config.js.map +1 -0
- package/dist/core/runner/injection.js +61 -0
- package/dist/core/runner/injection.js.map +1 -0
- package/dist/core/runner/mise.js +210 -0
- package/dist/core/runner/mise.js.map +1 -0
- package/dist/core/runner/prompt.js +720 -0
- package/dist/core/runner/prompt.js.map +1 -0
- package/dist/core/runner/turn.js +242 -0
- package/dist/core/runner/turn.js.map +1 -0
- package/dist/core/runner/vm-plan.js +390 -0
- package/dist/core/runner/vm-plan.js.map +1 -0
- package/dist/core/schedule/admission.js +123 -0
- package/dist/core/schedule/admission.js.map +1 -0
- package/dist/core/schedule/circuit-breaker.js +111 -0
- package/dist/core/schedule/circuit-breaker.js.map +1 -0
- package/dist/core/schedule/eligibility.js +83 -0
- package/dist/core/schedule/eligibility.js.map +1 -0
- package/dist/core/schedule/reconcile-issue.js +82 -0
- package/dist/core/schedule/reconcile-issue.js.map +1 -0
- package/dist/core/schedule/retry.js +96 -0
- package/dist/core/schedule/retry.js.map +1 -0
- package/dist/core/schedule/sleep-cycle.js +133 -0
- package/dist/core/schedule/sleep-cycle.js.map +1 -0
- package/dist/core/schedule/slots.js +124 -0
- package/dist/core/schedule/slots.js.map +1 -0
- package/dist/core/schedule/tick.js +553 -0
- package/dist/core/schedule/tick.js.map +1 -0
- package/dist/core/schedule/token-fold.js +181 -0
- package/dist/core/schedule/token-fold.js.map +1 -0
- package/dist/core/state-resolve.js +86 -0
- package/dist/core/state-resolve.js.map +1 -0
- package/dist/core/vm-guards.js +278 -0
- package/dist/core/vm-guards.js.map +1 -0
- package/dist/core/workflow/derive.js +107 -0
- package/dist/core/workflow/derive.js.map +1 -0
- package/dist/core/workflow/parse.js +687 -0
- package/dist/core/workflow/parse.js.map +1 -0
- package/dist/core/workflow/prompt-probe.js +78 -0
- package/dist/core/workflow/prompt-probe.js.map +1 -0
- package/dist/core/workflow/validate.js +189 -0
- package/dist/core/workflow/validate.js.map +1 -0
- package/dist/core/workspace-key.js +19 -0
- package/dist/core/workspace-key.js.map +1 -0
- package/dist/shell/actions-runner.js +356 -0
- package/dist/shell/actions-runner.js.map +1 -0
- package/dist/shell/adapter/adapter-registry.js +45 -0
- package/dist/shell/adapter/adapter-registry.js.map +1 -0
- package/dist/shell/adapter/clock-random.js +96 -0
- package/dist/shell/adapter/clock-random.js.map +1 -0
- package/dist/shell/adapter/gondolin-dispatch-helpers.js +158 -0
- package/dist/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
- package/dist/shell/adapter/gondolin-dispatch.js +385 -0
- package/dist/shell/adapter/gondolin-dispatch.js.map +1 -0
- package/dist/shell/adapter/gondolin-image-converter.js +233 -0
- package/dist/shell/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/shell/adapter/gondolin-image-fetch.js +180 -0
- package/dist/shell/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/shell/adapter/launcher-asset.js +57 -0
- package/dist/shell/adapter/launcher-asset.js.map +1 -0
- package/dist/shell/adapter/mise-config-asset.js +65 -0
- package/dist/shell/adapter/mise-config-asset.js.map +1 -0
- package/dist/shell/adapter/workflow-loader.js +304 -0
- package/dist/shell/adapter/workflow-loader.js.map +1 -0
- package/dist/shell/cli/doctor.js +268 -0
- package/dist/shell/cli/doctor.js.map +1 -0
- package/dist/shell/effect-interpreter-families.js +314 -0
- package/dist/shell/effect-interpreter-families.js.map +1 -0
- package/dist/shell/effect-interpreter.js +29 -0
- package/dist/shell/effect-interpreter.js.map +1 -0
- package/dist/shell/interp/acp-frame.js +137 -0
- package/dist/shell/interp/acp-frame.js.map +1 -0
- package/dist/shell/interp/acp-ws-conn.js +320 -0
- package/dist/shell/interp/acp-ws-conn.js.map +1 -0
- package/dist/shell/interp/acp-ws-frames.js +159 -0
- package/dist/shell/interp/acp-ws-frames.js.map +1 -0
- package/dist/shell/interp/acp-ws.js +197 -0
- package/dist/shell/interp/acp-ws.js.map +1 -0
- package/dist/shell/interp/acp.js +319 -0
- package/dist/shell/interp/acp.js.map +1 -0
- package/dist/shell/interp/credential-defaults.js +128 -0
- package/dist/shell/interp/credential-defaults.js.map +1 -0
- package/dist/shell/interp/credential-hooks.js +149 -0
- package/dist/shell/interp/credential-hooks.js.map +1 -0
- package/dist/shell/interp/credential-registry.js +226 -0
- package/dist/shell/interp/credential-registry.js.map +1 -0
- package/dist/shell/interp/credential.js +103 -0
- package/dist/shell/interp/credential.js.map +1 -0
- package/dist/shell/interp/gh.js +163 -0
- package/dist/shell/interp/gh.js.map +1 -0
- package/dist/shell/interp/git.js +28 -0
- package/dist/shell/interp/git.js.map +1 -0
- package/dist/shell/interp/log.js +213 -0
- package/dist/shell/interp/log.js.map +1 -0
- package/dist/shell/interp/process.js +178 -0
- package/dist/shell/interp/process.js.map +1 -0
- package/dist/shell/interp/runlog.js +193 -0
- package/dist/shell/interp/runlog.js.map +1 -0
- package/dist/shell/interp/timer.js +64 -0
- package/dist/shell/interp/timer.js.map +1 -0
- package/dist/shell/interp/tracker-disk.js +99 -0
- package/dist/shell/interp/tracker-disk.js.map +1 -0
- package/dist/shell/interp/tracker-parse.js +71 -0
- package/dist/shell/interp/tracker-parse.js.map +1 -0
- package/dist/shell/interp/tracker-scan.js +238 -0
- package/dist/shell/interp/tracker-scan.js.map +1 -0
- package/dist/shell/interp/tracker-write.js +91 -0
- package/dist/shell/interp/tracker-write.js.map +1 -0
- package/dist/shell/interp/tracker.js +41 -0
- package/dist/shell/interp/tracker.js.map +1 -0
- package/dist/shell/interp/tty.js +48 -0
- package/dist/shell/interp/tty.js.map +1 -0
- package/dist/shell/interp/vm.js +199 -0
- package/dist/shell/interp/vm.js.map +1 -0
- package/dist/shell/interp/workspace.js +310 -0
- package/dist/shell/interp/workspace.js.map +1 -0
- package/dist/shell/main-acp.js +78 -0
- package/dist/shell/main-acp.js.map +1 -0
- package/dist/shell/main-adapters.js +222 -0
- package/dist/shell/main-adapters.js.map +1 -0
- package/dist/shell/main-credential.js +122 -0
- package/dist/shell/main-credential.js.map +1 -0
- package/dist/shell/main-doctor.js +22 -0
- package/dist/shell/main-doctor.js.map +1 -0
- package/dist/shell/main-entry.js +46 -0
- package/dist/shell/main-entry.js.map +1 -0
- package/dist/shell/main-http-csrf.js +45 -0
- package/dist/shell/main-http-csrf.js.map +1 -0
- package/dist/shell/main-http-handler.js +389 -0
- package/dist/shell/main-http-handler.js.map +1 -0
- package/dist/shell/main-http-mcp.js +122 -0
- package/dist/shell/main-http-mcp.js.map +1 -0
- package/dist/shell/main-http-views.js +253 -0
- package/dist/shell/main-http-views.js.map +1 -0
- package/dist/shell/main-http.js +76 -0
- package/dist/shell/main-http.js.map +1 -0
- package/dist/shell/main-loops.js +130 -0
- package/dist/shell/main-loops.js.map +1 -0
- package/dist/shell/main-mcp.js +129 -0
- package/dist/shell/main-mcp.js.map +1 -0
- package/dist/shell/main-orchestrator.js +120 -0
- package/dist/shell/main-orchestrator.js.map +1 -0
- package/dist/shell/main-preflight.js +43 -0
- package/dist/shell/main-preflight.js.map +1 -0
- package/dist/shell/main-reconcilers-helpers.js +244 -0
- package/dist/shell/main-reconcilers-helpers.js.map +1 -0
- package/dist/shell/main-reconcilers-pr.js +148 -0
- package/dist/shell/main-reconcilers-pr.js.map +1 -0
- package/dist/shell/main-reconcilers.js +225 -0
- package/dist/shell/main-reconcilers.js.map +1 -0
- package/dist/shell/main-runner.js +355 -0
- package/dist/shell/main-runner.js.map +1 -0
- package/dist/shell/main-scaffold.js +116 -0
- package/dist/shell/main-scaffold.js.map +1 -0
- package/dist/shell/main-shutdown.js +115 -0
- package/dist/shell/main-shutdown.js.map +1 -0
- package/dist/shell/main-startup.js +48 -0
- package/dist/shell/main-startup.js.map +1 -0
- package/dist/shell/main-substrates.js +43 -0
- package/dist/shell/main-substrates.js.map +1 -0
- package/dist/shell/main.js +385 -0
- package/dist/shell/main.js.map +1 -0
- package/dist/shell/orchestrator-feedback.js +69 -0
- package/dist/shell/orchestrator-feedback.js.map +1 -0
- package/dist/shell/orchestrator-image.js +167 -0
- package/dist/shell/orchestrator-image.js.map +1 -0
- package/dist/shell/orchestrator-loop.js +468 -0
- package/dist/shell/orchestrator-loop.js.map +1 -0
- package/dist/shell/orchestrator-reconcile.js +36 -0
- package/dist/shell/orchestrator-reconcile.js.map +1 -0
- package/dist/shell/reconciler-loop.js +228 -0
- package/dist/shell/reconciler-loop.js.map +1 -0
- package/dist/shell/runner-loop-turn.js +301 -0
- package/dist/shell/runner-loop-turn.js.map +1 -0
- package/dist/shell/runner-loop.js +338 -0
- package/dist/shell/runner-loop.js.map +1 -0
- package/dist/shell/server/http.js +208 -0
- package/dist/shell/server/http.js.map +1 -0
- package/dist/shell/server/mcp-runtime-effects.js +237 -0
- package/dist/shell/server/mcp-runtime-effects.js.map +1 -0
- package/dist/shell/server/mcp-runtime.js +99 -0
- package/dist/shell/server/mcp-runtime.js.map +1 -0
- package/dist/shell/workspace-key.js +14 -0
- package/dist/shell/workspace-key.js.map +1 -0
- package/dist/types/acp.js +8 -0
- package/dist/types/acp.js.map +1 -0
- package/dist/types/actions/plan.js +6 -0
- package/dist/types/actions/plan.js.map +1 -0
- package/dist/types/actions/predicates.js +6 -0
- package/dist/types/actions/predicates.js.map +1 -0
- package/dist/types/actions/run-fold.js +8 -0
- package/dist/types/actions/run-fold.js.map +1 -0
- package/dist/types/actions.js +7 -0
- package/dist/types/actions.js.map +1 -0
- package/dist/types/adapter/clock-random.js +4 -0
- package/dist/types/adapter/clock-random.js.map +1 -0
- package/dist/types/adapter/gondolin-image-converter.js +5 -0
- package/dist/types/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/types/adapter/gondolin-image-fetch.js +5 -0
- package/dist/types/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/types/adapter/workflow-loader.js +4 -0
- package/dist/types/adapter/workflow-loader.js.map +1 -0
- package/dist/types/cli/args.js +8 -0
- package/dist/types/cli/args.js.map +1 -0
- package/dist/types/config.js +8 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/credential-interp.js +6 -0
- package/dist/types/credential-interp.js.map +1 -0
- package/dist/types/credentials.js +10 -0
- package/dist/types/credentials.js.map +1 -0
- package/dist/types/doctor.js +7 -0
- package/dist/types/doctor.js.map +1 -0
- package/dist/types/domain.js +7 -0
- package/dist/types/domain.js.map +1 -0
- package/dist/types/effect.js +15 -0
- package/dist/types/effect.js.map +1 -0
- package/dist/types/errors.js +39 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/http/decisions.js +6 -0
- package/dist/types/http/decisions.js.map +1 -0
- package/dist/types/http/render.js +10 -0
- package/dist/types/http/render.js.map +1 -0
- package/dist/types/http/views.js +6 -0
- package/dist/types/http/views.js.map +1 -0
- package/dist/types/http.js +9 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/image/managed-image.js +7 -0
- package/dist/types/image/managed-image.js.map +1 -0
- package/dist/types/interp/effect-interpreter.js +8 -0
- package/dist/types/interp/effect-interpreter.js.map +1 -0
- package/dist/types/interp/tracker.js +7 -0
- package/dist/types/interp/tracker.js.map +1 -0
- package/dist/types/issue/file.js +6 -0
- package/dist/types/issue/file.js.map +1 -0
- package/dist/types/issue/parse.js +8 -0
- package/dist/types/issue/parse.js.map +1 -0
- package/dist/types/main-acp.js +13 -0
- package/dist/types/main-acp.js.map +1 -0
- package/dist/types/main-adapters.js +5 -0
- package/dist/types/main-adapters.js.map +1 -0
- package/dist/types/main-credential.js +21 -0
- package/dist/types/main-credential.js.map +1 -0
- package/dist/types/main-doctor.js +6 -0
- package/dist/types/main-doctor.js.map +1 -0
- package/dist/types/main-http-handler.js +12 -0
- package/dist/types/main-http-handler.js.map +1 -0
- package/dist/types/main-http.js +5 -0
- package/dist/types/main-http.js.map +1 -0
- package/dist/types/main-loops.js +5 -0
- package/dist/types/main-loops.js.map +1 -0
- package/dist/types/main-mcp.js +12 -0
- package/dist/types/main-mcp.js.map +1 -0
- package/dist/types/main-orchestrator.js +5 -0
- package/dist/types/main-orchestrator.js.map +1 -0
- package/dist/types/main-reconcilers.js +11 -0
- package/dist/types/main-reconcilers.js.map +1 -0
- package/dist/types/main-runner.js +13 -0
- package/dist/types/main-runner.js.map +1 -0
- package/dist/types/main-startup.js +5 -0
- package/dist/types/main-startup.js.map +1 -0
- package/dist/types/main-substrates.js +5 -0
- package/dist/types/main-substrates.js.map +1 -0
- package/dist/types/mcp/dispatch.js +4 -0
- package/dist/types/mcp/dispatch.js.map +1 -0
- package/dist/types/mcp/post-move.js +7 -0
- package/dist/types/mcp/post-move.js.map +1 -0
- package/dist/types/mcp.js +9 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/ports.js +12 -0
- package/dist/types/ports.js.map +1 -0
- package/dist/types/reconcile/image-decide.js +5 -0
- package/dist/types/reconcile/image-decide.js.map +1 -0
- package/dist/types/reconcile/ledger.js +7 -0
- package/dist/types/reconcile/ledger.js.map +1 -0
- package/dist/types/reconcile/pr-loop.js +8 -0
- package/dist/types/reconcile/pr-loop.js.map +1 -0
- package/dist/types/reconcile/vm-reap.js +8 -0
- package/dist/types/reconcile/vm-reap.js.map +1 -0
- package/dist/types/reconcile/workspace-decide.js +7 -0
- package/dist/types/reconcile/workspace-decide.js.map +1 -0
- package/dist/types/reconcile.js +9 -0
- package/dist/types/reconcile.js.map +1 -0
- package/dist/types/runlog.js +7 -0
- package/dist/types/runlog.js.map +1 -0
- package/dist/types/runner/actions-runner.js +12 -0
- package/dist/types/runner/actions-runner.js.map +1 -0
- package/dist/types/runner/gondolin-dispatch.js +5 -0
- package/dist/types/runner/gondolin-dispatch.js.map +1 -0
- package/dist/types/runner/injection.js +6 -0
- package/dist/types/runner/injection.js.map +1 -0
- package/dist/types/runner/runner-loop.js +5 -0
- package/dist/types/runner/runner-loop.js.map +1 -0
- package/dist/types/runner/turn.js +4 -0
- package/dist/types/runner/turn.js.map +1 -0
- package/dist/types/runner/vm-plan.js +4 -0
- package/dist/types/runner/vm-plan.js.map +1 -0
- package/dist/types/runtime.js +9 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/schedule/admission.js +7 -0
- package/dist/types/schedule/admission.js.map +1 -0
- package/dist/types/schedule/circuit-breaker.js +2 -0
- package/dist/types/schedule/circuit-breaker.js.map +1 -0
- package/dist/types/schedule/eligibility.js +9 -0
- package/dist/types/schedule/eligibility.js.map +1 -0
- package/dist/types/schedule/orchestrator-loop.js +10 -0
- package/dist/types/schedule/orchestrator-loop.js.map +1 -0
- package/dist/types/schedule/sleep-cycle.js +4 -0
- package/dist/types/schedule/sleep-cycle.js.map +1 -0
- package/dist/types/schedule/slots.js +8 -0
- package/dist/types/schedule/slots.js.map +1 -0
- package/dist/types/schedule/tick.js +9 -0
- package/dist/types/schedule/tick.js.map +1 -0
- package/dist/types/server/mcp-runtime.js +8 -0
- package/dist/types/server/mcp-runtime.js.map +1 -0
- package/dist/types/workflow/parse.js +4 -0
- package/dist/types/workflow/parse.js.map +1 -0
- package/package.json +22 -10
- package/patches/@earendil-works+gondolin+0.12.0.patch +173 -0
- package/prompts/Reflect.md +91 -0
- package/prompts/Review.md +97 -0
- package/prompts/Todo.md +96 -0
- package/prompts/_footer.md +41 -0
- package/prompts/_preamble.md +42 -0
- package/prompts-minimal/Todo.md +26 -0
- package/scripts/postinstall.mjs +63 -0
- package/scripts/vm-agent.mjs +312 -90
- package/WORKFLOW.md +0 -744
- package/dist/acp-bridge.js +0 -324
- package/dist/acp-bridge.js.map +0 -1
- package/dist/actions/cache.js +0 -191
- package/dist/actions/cache.js.map +0 -1
- package/dist/actions/effects.js +0 -41
- package/dist/actions/effects.js.map +0 -1
- package/dist/actions/executor.js +0 -570
- package/dist/actions/executor.js.map +0 -1
- package/dist/actions/index.js +0 -13
- package/dist/actions/index.js.map +0 -1
- package/dist/actions/parsing.js.map +0 -1
- package/dist/actions/predicate-env.js +0 -27
- package/dist/actions/predicate-env.js.map +0 -1
- package/dist/actions/predicates.js +0 -49
- package/dist/actions/predicates.js.map +0 -1
- package/dist/actions/templating.js +0 -66
- package/dist/actions/templating.js.map +0 -1
- package/dist/actions/types.js +0 -15
- package/dist/actions/types.js.map +0 -1
- package/dist/agent/acp.js +0 -473
- package/dist/agent/acp.js.map +0 -1
- package/dist/agent/adapter-names.js +0 -159
- package/dist/agent/adapter-names.js.map +0 -1
- package/dist/agent/adapters.js +0 -511
- package/dist/agent/adapters.js.map +0 -1
- package/dist/agent/credential-extractors.js +0 -342
- package/dist/agent/credential-extractors.js.map +0 -1
- package/dist/agent/credential-secrets.js +0 -628
- package/dist/agent/credential-secrets.js.map +0 -1
- package/dist/agent/credential-ticker.js +0 -57
- package/dist/agent/credential-ticker.js.map +0 -1
- package/dist/agent/gondolin-creds-staging.js +0 -356
- package/dist/agent/gondolin-creds-staging.js.map +0 -1
- package/dist/agent/gondolin-dispatch.js +0 -375
- package/dist/agent/gondolin-dispatch.js.map +0 -1
- package/dist/agent/gondolin.js +0 -124
- package/dist/agent/gondolin.js.map +0 -1
- package/dist/agent/runner-decisions.js +0 -134
- package/dist/agent/runner-decisions.js.map +0 -1
- package/dist/agent/runner.js +0 -1456
- package/dist/agent/runner.js.map +0 -1
- package/dist/agent/tool-call-summary.js +0 -102
- package/dist/agent/tool-call-summary.js.map +0 -1
- package/dist/agent/vm-acp-mapping.js +0 -73
- package/dist/agent/vm-acp-mapping.js.map +0 -1
- package/dist/agent/vm-guards.js +0 -262
- package/dist/agent/vm-guards.js.map +0 -1
- package/dist/agent/vm-port.js +0 -22
- package/dist/agent/vm-port.js.map +0 -1
- package/dist/agent/vm-process-registry.js +0 -79
- package/dist/agent/vm-process-registry.js.map +0 -1
- package/dist/bin/cli-args.js +0 -105
- package/dist/bin/cli-args.js.map +0 -1
- package/dist/errors.js +0 -15
- package/dist/errors.js.map +0 -1
- package/dist/http-disk.js +0 -135
- package/dist/http-disk.js.map +0 -1
- package/dist/http-handlers.js.map +0 -1
- package/dist/http.js.map +0 -1
- package/dist/issues.js +0 -178
- package/dist/issues.js.map +0 -1
- package/dist/logging.js +0 -203
- package/dist/logging.js.map +0 -1
- package/dist/mcp.js +0 -706
- package/dist/mcp.js.map +0 -1
- package/dist/memory.js +0 -85
- package/dist/memory.js.map +0 -1
- package/dist/orchestrator-decisions.js +0 -331
- package/dist/orchestrator-decisions.js.map +0 -1
- package/dist/orchestrator.js +0 -1569
- package/dist/orchestrator.js.map +0 -1
- package/dist/prompt.js +0 -65
- package/dist/prompt.js.map +0 -1
- package/dist/reconciler/cache.js +0 -65
- package/dist/reconciler/cache.js.map +0 -1
- package/dist/reconciler/index.js +0 -448
- package/dist/reconciler/index.js.map +0 -1
- package/dist/reconciler/ledger.js +0 -131
- package/dist/reconciler/ledger.js.map +0 -1
- package/dist/reconciler/pr-adapters.js +0 -174
- package/dist/reconciler/pr-adapters.js.map +0 -1
- package/dist/reconciler/pr-decide.js.map +0 -1
- package/dist/reconciler/pr.js +0 -422
- package/dist/reconciler/pr.js.map +0 -1
- package/dist/reconciler/types.js +0 -12
- package/dist/reconciler/types.js.map +0 -1
- package/dist/reconciler/vm.js +0 -243
- package/dist/reconciler/vm.js.map +0 -1
- package/dist/reconciler/workspace-defaults.js +0 -83
- package/dist/reconciler/workspace-defaults.js.map +0 -1
- package/dist/reconciler/workspace.js +0 -272
- package/dist/reconciler/workspace.js.map +0 -1
- package/dist/runlog.js +0 -403
- package/dist/runlog.js.map +0 -1
- package/dist/scaffold.js +0 -165
- package/dist/scaffold.js.map +0 -1
- package/dist/trackers/local.js +0 -445
- package/dist/trackers/local.js.map +0 -1
- package/dist/trackers/types.js +0 -10
- package/dist/trackers/types.js.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/util/clock.js +0 -12
- package/dist/util/clock.js.map +0 -1
- package/dist/util/crypto.js +0 -25
- package/dist/util/crypto.js.map +0 -1
- package/dist/util/frontmatter.js +0 -70
- package/dist/util/frontmatter.js.map +0 -1
- package/dist/util/fs-issues.js +0 -22
- package/dist/util/fs-issues.js.map +0 -1
- package/dist/util/process.js +0 -152
- package/dist/util/process.js.map +0 -1
- package/dist/util/workspace-key.js +0 -10
- package/dist/util/workspace-key.js.map +0 -1
- package/dist/workflow-loader.js +0 -147
- package/dist/workflow-loader.js.map +0 -1
- package/dist/workflow.js +0 -822
- package/dist/workflow.js.map +0 -1
- package/dist/workspace-types.js +0 -8
- package/dist/workspace-types.js.map +0 -1
- package/dist/workspace.js +0 -443
- package/dist/workspace.js.map +0 -1
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// Production-side adapter for `PredicateEnv` (issue 96). Backs
|
|
2
|
-
// `branchExists` with `git rev-parse --verify --quiet` (via the unified
|
|
3
|
-
// `runProcess`) and `pathExists` with `fs.stat`. Lives outside the
|
|
4
|
-
// functional-core lint group so `src/actions/predicates.ts` can stay free of
|
|
5
|
-
// `node:fs/promises` and `runProcess` direct imports; the runner threads
|
|
6
|
-
// `defaultPredicateEnv` into the executor.
|
|
7
|
-
import { stat } from 'node:fs/promises';
|
|
8
|
-
import { runProcess } from '../util/process.js';
|
|
9
|
-
export const defaultPredicateEnv = {
|
|
10
|
-
async branchExists(ref, workspacePath) {
|
|
11
|
-
// `--verify --quiet` keeps both streams empty on the happy path; the
|
|
12
|
-
// tiny default byte clamp is plenty and `appendErrorToStderr: false`
|
|
13
|
-
// skips stderr decoration for the missing-ref case (the common one).
|
|
14
|
-
const r = await runProcess('git', ['rev-parse', '--verify', '--quiet', `refs/heads/${ref}`], { cwd: workspacePath, appendErrorToStderr: false });
|
|
15
|
-
return r.exit_code === 0;
|
|
16
|
-
},
|
|
17
|
-
async pathExists(absPath) {
|
|
18
|
-
try {
|
|
19
|
-
const st = await stat(absPath);
|
|
20
|
-
return st.isFile() || st.isDirectory();
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
//# sourceMappingURL=predicate-env.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"predicate-env.js","sourceRoot":"","sources":["../../src/actions/predicate-env.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wEAAwE;AACxE,mEAAmE;AACnE,6EAA6E;AAC7E,yEAAyE;AACzE,2CAA2C;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,aAAa;QACnC,qEAAqE;QACrE,qEAAqE;QACrE,qEAAqE;QACrE,MAAM,CAAC,GAAG,MAAM,UAAU,CACxB,KAAK,EACL,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,GAAG,EAAE,CAAC,EACzD,EAAE,GAAG,EAAE,aAAa,EAAE,mBAAmB,EAAE,KAAK,EAAE,CACnD,CAAC;QACF,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,OAAO;QACtB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
// `if:` predicate evaluation (issue 36).
|
|
2
|
-
//
|
|
3
|
-
// Three predicate shapes — env-var-truthy, branch-exists, file-present.
|
|
4
|
-
// These are the three predicates the hook shell actually exercised across
|
|
5
|
-
// today's WORKFLOW.md; the issue body explicitly caps the predicate set
|
|
6
|
-
// there: "If users want more, they've outgrown declarative."
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import { renderTemplate } from './templating.js';
|
|
9
|
-
/**
|
|
10
|
-
* Evaluate a predicate against the context. `null`/undefined → always true
|
|
11
|
-
* (no `if:` → run unconditionally).
|
|
12
|
-
*
|
|
13
|
-
* The string form `"$var"` is a truthiness check on the named context field
|
|
14
|
-
* — `if: $repo` matches the issue body's example exactly. A bare literal
|
|
15
|
-
* (`if: yes`) is treated as truthy; the literal-false case `if: ""` /
|
|
16
|
-
* `if: null` falls through to "always".
|
|
17
|
-
*
|
|
18
|
-
* IO is routed through the injected `PredicateEnv` so the evaluator core
|
|
19
|
-
* stays pure (no `node:fs` / `runProcess` imports). String-truthy predicates
|
|
20
|
-
* never touch the env.
|
|
21
|
-
*/
|
|
22
|
-
export async function evaluatePredicate(predicate, ctx, workspacePath, env) {
|
|
23
|
-
if (predicate === null || predicate === undefined)
|
|
24
|
-
return true;
|
|
25
|
-
if (typeof predicate === 'string') {
|
|
26
|
-
// Templates may already have been rendered by the executor's renderTree
|
|
27
|
-
// pass before evaluatePredicate is called; re-rendering an already-rendered
|
|
28
|
-
// empty string is a no-op. An empty (or empty-after-render) predicate is
|
|
29
|
-
// explicitly false — the intent of `if: $repo` with $repo unset is "skip
|
|
30
|
-
// when the var is empty," not "always run".
|
|
31
|
-
const expanded = renderTemplate(predicate, ctx).trim();
|
|
32
|
-
return expanded.length > 0;
|
|
33
|
-
}
|
|
34
|
-
if ('branch_exists' in predicate) {
|
|
35
|
-
const ref = renderTemplate(predicate.branch_exists, ctx).trim();
|
|
36
|
-
if (ref.length === 0)
|
|
37
|
-
return false;
|
|
38
|
-
return env.branchExists(ref, workspacePath);
|
|
39
|
-
}
|
|
40
|
-
if ('file_present' in predicate) {
|
|
41
|
-
const file = renderTemplate(predicate.file_present, ctx).trim();
|
|
42
|
-
if (file.length === 0)
|
|
43
|
-
return false;
|
|
44
|
-
const abs = path.isAbsolute(file) ? file : path.join(workspacePath, file);
|
|
45
|
-
return env.pathExists(abs);
|
|
46
|
-
}
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=predicates.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../src/actions/predicates.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,wEAAwE;AACxE,6DAA6D;AAE7D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAsC,EACtC,GAAkB,EAClB,aAAqB,EACrB,GAAiB;IAEjB,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,wEAAwE;QACxE,4EAA4E;QAC5E,yEAAyE;QACzE,yEAAyE;QACzE,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,eAAe,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACnC,OAAO,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,cAAc,IAAI,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QAC1E,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// $-substitution against a fixed ActionContext namespace (issue 36).
|
|
2
|
-
//
|
|
3
|
-
// The issue body explicitly says "Mustache or `$`-substitution with a fixed
|
|
4
|
-
// namespace is enough; Bazel's Starlark is overkill." We pick `$identifier`
|
|
5
|
-
// over `${{ identifier }}` because the Done after_run already uses
|
|
6
|
-
// `$SYMPHONY_*` env-var shapes; sharing the prefix style keeps cognitive
|
|
7
|
-
// load low for operators converting hooks to actions.
|
|
8
|
-
//
|
|
9
|
-
// Behavior:
|
|
10
|
-
// • `$name` expands to the named ActionContext field.
|
|
11
|
-
// • An unknown `$name` throws — silent expansion to "" was the most common
|
|
12
|
-
// hook-shell bug (typo'd `$SYMPHONY_PR_TITTLE` is the canonical example).
|
|
13
|
-
// • Literal `$` followed by a non-word char is left alone.
|
|
14
|
-
// • `\$name` escapes the substitution (literal `$name` in output).
|
|
15
|
-
export class TemplateError extends Error {
|
|
16
|
-
name;
|
|
17
|
-
constructor(name, message) {
|
|
18
|
-
super(message);
|
|
19
|
-
this.name = name;
|
|
20
|
-
this.name = 'TemplateError';
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
const VAR_RE = /(\\?)\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
24
|
-
/**
|
|
25
|
-
* Substitute `$name` references in `template` against the ActionContext.
|
|
26
|
-
* Throws TemplateError when a referenced variable is not in the fixed
|
|
27
|
-
* namespace — silent "" expansion masks operator typos.
|
|
28
|
-
*/
|
|
29
|
-
export function renderTemplate(template, ctx) {
|
|
30
|
-
if (typeof template !== 'string') {
|
|
31
|
-
return template;
|
|
32
|
-
}
|
|
33
|
-
return template.replace(VAR_RE, (full, escape, name) => {
|
|
34
|
-
if (escape === '\\')
|
|
35
|
-
return `$${name}`;
|
|
36
|
-
if (!(name in ctx)) {
|
|
37
|
-
throw new TemplateError(name, `unknown template variable "$${name}" (available: ${Object.keys(ctx).join(', ')})`);
|
|
38
|
-
}
|
|
39
|
-
const v = ctx[name];
|
|
40
|
-
if (v === null || v === undefined)
|
|
41
|
-
return '';
|
|
42
|
-
return String(v);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Render every string field of an object. Used to render an action's
|
|
47
|
-
* declarative fields in one pass before execution. Recurses into arrays and
|
|
48
|
-
* plain objects; primitives other than strings (numbers, booleans) pass
|
|
49
|
-
* through unchanged.
|
|
50
|
-
*/
|
|
51
|
-
export function renderTree(value, ctx) {
|
|
52
|
-
if (typeof value === 'string')
|
|
53
|
-
return renderTemplate(value, ctx);
|
|
54
|
-
if (Array.isArray(value)) {
|
|
55
|
-
return value.map((v) => renderTree(v, ctx));
|
|
56
|
-
}
|
|
57
|
-
if (value && typeof value === 'object') {
|
|
58
|
-
const out = {};
|
|
59
|
-
for (const [k, v] of Object.entries(value)) {
|
|
60
|
-
out[k] = renderTree(v, ctx);
|
|
61
|
-
}
|
|
62
|
-
return out;
|
|
63
|
-
}
|
|
64
|
-
return value;
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=templating.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"templating.js","sourceRoot":"","sources":["../../src/actions/templating.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,mEAAmE;AACnE,yEAAyE;AACzE,sDAAsD;AACtD,EAAE;AACF,YAAY;AACZ,wDAAwD;AACxD,6EAA6E;AAC7E,8EAA8E;AAC9E,6DAA6D;AAC7D,qEAAqE;AAIrE,MAAM,OAAO,aAAc,SAAQ,KAAK;IACnB;IAAnB,YAAmB,IAAY,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAQ;QAE7B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,MAAM,GAAG,kCAAkC,CAAC;AAElD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,GAAkB;IACjE,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAc,EAAE,IAAY,EAAE,EAAE;QACrE,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,aAAa,CACrB,IAAI,EACJ,+BAA+B,IAAI,iBAAiB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACnF,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,GAAI,GAA0C,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QAC7C,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAI,KAAQ,EAAE,GAAkB;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC,KAAK,EAAE,GAAG,CAAiB,CAAC;IACjF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAiB,CAAC;IAC9D,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,GAAG,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,GAAmB,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/actions/types.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Workflow action records (issue 36 — reconciler v2 / typed action DAG).
|
|
2
|
-
//
|
|
3
|
-
// Per-state `actions:` blocks declare a closed set of typed records that the
|
|
4
|
-
// orchestrator runs in place of an `after_run` shell hook. Each kind has a
|
|
5
|
-
// fixed schema; the only escape hatch for arbitrary commands is `run_in_vm`,
|
|
6
|
-
// which is content-hash cached so identical (workspace, cmd, env) tuples
|
|
7
|
-
// don't re-execute.
|
|
8
|
-
//
|
|
9
|
-
// Action records are pure data; the executor (src/actions/executor.ts) is the
|
|
10
|
-
// one place that knows how to apply each kind. This mirrors the reconciler's
|
|
11
|
-
// `KillSessionAction`/`RemoveWorkspaceAction`/… pattern (records, not closures)
|
|
12
|
-
// so the snapshot machinery and the dashboard can render per-action state
|
|
13
|
-
// uniformly across both surfaces.
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=types.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/actions/types.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,oBAAoB;AACpB,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,kCAAkC"}
|
package/dist/agent/acp.js
DELETED
|
@@ -1,473 +0,0 @@
|
|
|
1
|
-
// ACP (Agent Client Protocol) client wrapper.
|
|
2
|
-
//
|
|
3
|
-
// Symphony talks the Zed Agent Client Protocol (https://agentclientprotocol.com) so that a
|
|
4
|
-
// single integration covers Claude (`claude-agent-acp`), Codex (`codex-acp`), and OpenCode
|
|
5
|
-
// (`opencode acp`). The protocol is JSON-RPC over stdio.
|
|
6
|
-
//
|
|
7
|
-
// This wrapper:
|
|
8
|
-
// * spawns the adapter command inside a Gondolin VM (the child process stdio is the
|
|
9
|
-
// transport; nothing local is mutated outside the VM)
|
|
10
|
-
// * bridges Node child process stdio to the SDK's WHATWG streams via Readable.toWeb / etc.
|
|
11
|
-
// * implements the small Client surface ACP requires — session update streaming,
|
|
12
|
-
// permission requests, and (optionally) fs/terminal — under a documented high-trust
|
|
13
|
-
// posture (auto-approve, no client-side fs writes; the agent uses its own tools in-VM)
|
|
14
|
-
// * exposes high-level methods `initSession()` and `runPrompt()` that the agent runner
|
|
15
|
-
// uses to drive one turn of work.
|
|
16
|
-
import { Readable, Transform, Writable } from 'node:stream';
|
|
17
|
-
import { StringDecoder } from 'node:string_decoder';
|
|
18
|
-
import { ClientSideConnection, ndJsonStream, PROTOCOL_VERSION, } from '@agentclientprotocol/sdk';
|
|
19
|
-
import { log } from '../logging.js';
|
|
20
|
-
import { summarizeToolCall, summarizeToolCallUpdate } from './tool-call-summary.js';
|
|
21
|
-
// Connection/transport faults surfaced by the in-VM agent's model API client
|
|
22
|
-
// (ECONNRESET, socket hang up, "Unable to connect to API", …) arrive as a thrown
|
|
23
|
-
// JSON-RPC error on session/prompt — they are NOT an agent decision. Issue 135:
|
|
24
|
-
// bucketing these as `refusal` made a transient upstream stream reset look like
|
|
25
|
-
// the agent giving up, so a long turn's transport blip got scored an "agent turn
|
|
26
|
-
// refusal", the whole run was discarded, and the issue re-dispatched in a loop.
|
|
27
|
-
// Label them distinctly (`transport_error`) so the run log / summary stay honest
|
|
28
|
-
// and downstream policy can treat them as transient rather than as a refusal.
|
|
29
|
-
const TRANSPORT_ERROR_RE = /econnreset|etimedout|econnrefused|epipe|enetunreach|ehostunreach|eai_again|socket hang up|unable to connect to api|fetch failed|network error|other side closed|terminated/i;
|
|
30
|
-
/** True when a thrown prompt error is a connection/transport fault, not an agent decision. */
|
|
31
|
-
export function isTransportError(message) {
|
|
32
|
-
return TRANSPORT_ERROR_RE.test(message);
|
|
33
|
-
}
|
|
34
|
-
export class AcpProtocolError extends Error {
|
|
35
|
-
code;
|
|
36
|
-
constructor(code, message) {
|
|
37
|
-
super(message);
|
|
38
|
-
this.code = code;
|
|
39
|
-
this.name = 'AcpProtocolError';
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function nowIso() {
|
|
43
|
-
return new Date().toISOString();
|
|
44
|
-
}
|
|
45
|
-
function summarize(raw, max = 240) {
|
|
46
|
-
let s;
|
|
47
|
-
try {
|
|
48
|
-
s = typeof raw === 'string' ? raw : JSON.stringify(raw);
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
s = String(raw);
|
|
52
|
-
}
|
|
53
|
-
if (s.length > max)
|
|
54
|
-
s = s.slice(0, max) + '…';
|
|
55
|
-
return s;
|
|
56
|
-
}
|
|
57
|
-
function extractTextContent(content) {
|
|
58
|
-
if (!content || typeof content !== 'object')
|
|
59
|
-
return '';
|
|
60
|
-
const c = content;
|
|
61
|
-
if (c.type === 'text' && typeof c.text === 'string')
|
|
62
|
-
return c.text;
|
|
63
|
-
return '';
|
|
64
|
-
}
|
|
65
|
-
function truncate(s, max) {
|
|
66
|
-
return s.length > max ? s.slice(0, max) + '…' : s;
|
|
67
|
-
}
|
|
68
|
-
// Transform that hands each newline-delimited frame to `onLine` while passing the raw bytes
|
|
69
|
-
// through to downstream consumers unchanged. Used to tap the ACP JSON-RPC transport in both
|
|
70
|
-
// directions for the per-issue JSONL run log. Buffering lives in `_transform`; a final flush
|
|
71
|
-
// surfaces any unterminated tail so a clean shutdown does not drop the last frame.
|
|
72
|
-
//
|
|
73
|
-
// We decode with a `StringDecoder` rather than `chunk.toString('utf8')` because TCP/stdout
|
|
74
|
-
// chunk boundaries can fall inside a multibyte UTF-8 sequence: an unaccompanied byte split
|
|
75
|
-
// would otherwise be silently converted to a U+FFFD replacement character, corrupting the
|
|
76
|
-
// JSON we record. The decoder buffers the trailing incomplete sequence and returns it
|
|
77
|
-
// prepended to the next chunk's decode.
|
|
78
|
-
class LineTap extends Transform {
|
|
79
|
-
onLine;
|
|
80
|
-
buf = '';
|
|
81
|
-
decoder = new StringDecoder('utf8');
|
|
82
|
-
constructor(onLine) {
|
|
83
|
-
super();
|
|
84
|
-
this.onLine = onLine;
|
|
85
|
-
}
|
|
86
|
-
_transform(chunk, _enc, cb) {
|
|
87
|
-
this.buf +=
|
|
88
|
-
typeof chunk === 'string' ? chunk : this.decoder.write(chunk);
|
|
89
|
-
let idx;
|
|
90
|
-
while ((idx = this.buf.indexOf('\n')) !== -1) {
|
|
91
|
-
const line = this.buf.slice(0, idx);
|
|
92
|
-
this.buf = this.buf.slice(idx + 1);
|
|
93
|
-
if (line.length > 0) {
|
|
94
|
-
try {
|
|
95
|
-
this.onLine(line);
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
// Tap failures must not interrupt the stream.
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
cb(null, chunk);
|
|
103
|
-
}
|
|
104
|
-
_flush(cb) {
|
|
105
|
-
// Drain any incomplete multibyte sequence the decoder is still holding, then surface
|
|
106
|
-
// an unterminated tail so a clean shutdown does not drop the last frame.
|
|
107
|
-
const tail = this.decoder.end();
|
|
108
|
-
if (tail.length > 0)
|
|
109
|
-
this.buf += tail;
|
|
110
|
-
if (this.buf.length > 0) {
|
|
111
|
-
try {
|
|
112
|
-
this.onLine(this.buf);
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
/* see _transform */
|
|
116
|
-
}
|
|
117
|
-
this.buf = '';
|
|
118
|
-
}
|
|
119
|
-
cb();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// Record one ACP frame to the run log. Lines that parse as JSON are stored as parsed values
|
|
123
|
-
// so the evaluator agent doesn't double-decode; anything else lands as `kind: "unparseable"`
|
|
124
|
-
// with the raw bytes preserved for forensic value.
|
|
125
|
-
//
|
|
126
|
-
// Before recording, capability tokens in the frame are redacted in place. The most common
|
|
127
|
-
// one is the symphony MCP bearer that we inject into `session/new` as
|
|
128
|
-
// `mcpServers[].headers[].value = "Bearer <token>"`; that token is the agent's per-issue
|
|
129
|
-
// capability to call `transition` and `request_human_steering`, and the JSONL log is a
|
|
130
|
-
// long-lived append-only file an evaluator may share. Replace any string starting with
|
|
131
|
-
// `Bearer ` with `Bearer <redacted>` anywhere in the tree.
|
|
132
|
-
function recordAcpFrame(runLog, direction, line) {
|
|
133
|
-
if (!runLog)
|
|
134
|
-
return;
|
|
135
|
-
let frame;
|
|
136
|
-
try {
|
|
137
|
-
frame = JSON.parse(line);
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
runLog.record({ channel: 'acp', direction, kind: 'unparseable', raw: line });
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
redactBearerTokens(frame);
|
|
144
|
-
runLog.record({ channel: 'acp', direction, frame });
|
|
145
|
-
}
|
|
146
|
-
// Walk `value` and replace any string of the form `Bearer <token>` with `Bearer <redacted>`.
|
|
147
|
-
// Mutates in place; callers must pass the parsed JSON (which is single-use per call). We
|
|
148
|
-
// walk arrays and plain objects only; primitives other than strings are skipped, and we
|
|
149
|
-
// guard against cycles even though ACP frames shouldn't contain them.
|
|
150
|
-
function redactBearerTokens(value, seen = new WeakSet()) {
|
|
151
|
-
if (!value || typeof value !== 'object')
|
|
152
|
-
return;
|
|
153
|
-
if (seen.has(value))
|
|
154
|
-
return;
|
|
155
|
-
seen.add(value);
|
|
156
|
-
if (Array.isArray(value)) {
|
|
157
|
-
for (let i = 0; i < value.length; i++) {
|
|
158
|
-
const redacted = redactedBearer(value[i]);
|
|
159
|
-
if (redacted !== undefined)
|
|
160
|
-
value[i] = redacted;
|
|
161
|
-
else
|
|
162
|
-
redactBearerTokens(value[i], seen);
|
|
163
|
-
}
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const obj = value;
|
|
167
|
-
for (const k of Object.keys(obj)) {
|
|
168
|
-
const redacted = redactedBearer(obj[k]);
|
|
169
|
-
if (redacted !== undefined)
|
|
170
|
-
obj[k] = redacted;
|
|
171
|
-
else
|
|
172
|
-
redactBearerTokens(obj[k], seen);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
// Returns the redacted replacement when `v` is a Bearer-token string, else
|
|
176
|
-
// undefined. Non-string and non-Bearer values fall through so the caller can
|
|
177
|
-
// decide whether to recurse.
|
|
178
|
-
function redactedBearer(v) {
|
|
179
|
-
if (typeof v === 'string' && v.startsWith('Bearer '))
|
|
180
|
-
return 'Bearer <redacted>';
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
// One open ACP session bound to a single child process. The adapter is expected to be
|
|
184
|
-
// already running; `initSession()` performs `initialize` + `session/new`, and `runPrompt()`
|
|
185
|
-
// drives one prompt-to-stop_reason cycle.
|
|
186
|
-
export class AcpClient {
|
|
187
|
-
opts;
|
|
188
|
-
conn;
|
|
189
|
-
sessionId = null;
|
|
190
|
-
closed = false;
|
|
191
|
-
cancelled = false;
|
|
192
|
-
// Tracked here so the runner snapshot picks up the most recent assistant text per turn.
|
|
193
|
-
lastAssistantText = '';
|
|
194
|
-
// Held so `handleTransportClose` can forcibly end the SDK's reader/writer streams.
|
|
195
|
-
// Without this, destroying the underlying socket emits `'close'` on `opts.stdout` but
|
|
196
|
-
// the LineTap Transform in between may not propagate end-of-stream synchronously to
|
|
197
|
-
// `Readable.toWeb`'s output. The SDK's `receive()` reader loop then stays parked in
|
|
198
|
-
// `reader.read()`, so the in-flight `session/prompt` promise never rejects and the
|
|
199
|
-
// runner hangs in `runPrompt()` despite the socket being gone.
|
|
200
|
-
inboundTap;
|
|
201
|
-
outboundTap;
|
|
202
|
-
constructor(opts) {
|
|
203
|
-
this.opts = opts;
|
|
204
|
-
// Bridge child stdio to the WHATWG streams the SDK speaks. `ndJsonStream` expects raw
|
|
205
|
-
// bytes; we use Readable.toWeb / Writable.toWeb for the conversion. Both directions
|
|
206
|
-
// pass through a LineTap so the per-issue JSONL run log captures every JSON-RPC frame
|
|
207
|
-
// verbatim (parsed JSON when possible, raw bytes when not).
|
|
208
|
-
this.inboundTap = new LineTap((line) => recordAcpFrame(opts.runLog, 'vm_to_host', line));
|
|
209
|
-
this.outboundTap = new LineTap((line) => recordAcpFrame(opts.runLog, 'host_to_vm', line));
|
|
210
|
-
opts.stdout.pipe(this.inboundTap);
|
|
211
|
-
this.outboundTap.pipe(opts.stdin);
|
|
212
|
-
const input = Readable.toWeb(this.inboundTap);
|
|
213
|
-
const output = Writable.toWeb(this.outboundTap);
|
|
214
|
-
const stream = ndJsonStream(output, input);
|
|
215
|
-
this.conn = new ClientSideConnection((_agent) => this.makeClient(), stream);
|
|
216
|
-
// Stderr handling lives in the AgentRunner now — it attaches a tap immediately after
|
|
217
|
-
// launching the sandbox process so pre-bridge startup failures (vm-agent missing,
|
|
218
|
-
// bad env, adapter crash before connect) are captured in the JSONL run log and the
|
|
219
|
-
// per-issue event ring. AcpClient no longer consumes opts.stderr; the field is kept
|
|
220
|
-
// on the options type for backward compatibility and so callers retain a single
|
|
221
|
-
// place to think about where the stderr stream goes.
|
|
222
|
-
opts.stdout.on('close', () => this.handleTransportClose('stdout_closed'));
|
|
223
|
-
opts.stdin.on('error', () => {
|
|
224
|
-
/* surface through transport close */
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
// The Client interface implementation that the adapter calls back into. Every method is
|
|
228
|
-
// implemented because we run the agent inside a Gondolin VM; ACP requires the client to handle
|
|
229
|
-
// requests it advertises, and the SDK's Client interface lists them all.
|
|
230
|
-
makeClient() {
|
|
231
|
-
const self = this;
|
|
232
|
-
return {
|
|
233
|
-
async sessionUpdate(params) {
|
|
234
|
-
return self.onSessionUpdate(params);
|
|
235
|
-
},
|
|
236
|
-
async requestPermission(params) {
|
|
237
|
-
return self.onPermissionRequest(params);
|
|
238
|
-
},
|
|
239
|
-
async readTextFile(_params) {
|
|
240
|
-
// §6.1 "high-trust" posture: the agent has direct workspace access inside the VM,
|
|
241
|
-
// so client-mediated reads are unsupported. Returning an error keeps the session
|
|
242
|
-
// alive (per §6.1 "unsupported dynamic tool calls return failure without stall").
|
|
243
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client fs read not supported');
|
|
244
|
-
},
|
|
245
|
-
async writeTextFile(_params) {
|
|
246
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client fs write not supported');
|
|
247
|
-
},
|
|
248
|
-
async createTerminal(_params) {
|
|
249
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client terminal not supported');
|
|
250
|
-
},
|
|
251
|
-
async terminalOutput(_params) {
|
|
252
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client terminal not supported');
|
|
253
|
-
},
|
|
254
|
-
async waitForTerminalExit(_params) {
|
|
255
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client terminal not supported');
|
|
256
|
-
},
|
|
257
|
-
async killTerminal(_params) {
|
|
258
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client terminal not supported');
|
|
259
|
-
},
|
|
260
|
-
async releaseTerminal(_params) {
|
|
261
|
-
throw new AcpProtocolError('client_capability_not_implemented', 'client terminal not supported');
|
|
262
|
-
},
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
emit(event, message) {
|
|
266
|
-
this.opts.onEvent({ at: nowIso(), event, message });
|
|
267
|
-
}
|
|
268
|
-
onSessionUpdate(params) {
|
|
269
|
-
const update = params.update;
|
|
270
|
-
switch (update.sessionUpdate) {
|
|
271
|
-
case 'agent_message_chunk':
|
|
272
|
-
return this.onAgentMessageChunk(update);
|
|
273
|
-
case 'agent_thought_chunk':
|
|
274
|
-
return this.onAgentThoughtChunk(update);
|
|
275
|
-
case 'tool_call':
|
|
276
|
-
return this.emit('tool_call', summarizeToolCall(update));
|
|
277
|
-
case 'tool_call_update':
|
|
278
|
-
return this.emit('tool_call_update', summarizeToolCallUpdate(update));
|
|
279
|
-
case 'plan':
|
|
280
|
-
return this.emit('plan', summarize(update.entries ?? update));
|
|
281
|
-
case 'usage_update':
|
|
282
|
-
return this.onUsageUpdate(update);
|
|
283
|
-
default:
|
|
284
|
-
return this.emit('session_update', `${update.sessionUpdate}: ${summarize(update)}`);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
onAgentMessageChunk(update) {
|
|
288
|
-
const text = extractTextContent(update.content);
|
|
289
|
-
if (!text)
|
|
290
|
-
return;
|
|
291
|
-
this.lastAssistantText += text;
|
|
292
|
-
this.emit('agent_message_chunk', truncate(text, 80));
|
|
293
|
-
}
|
|
294
|
-
onAgentThoughtChunk(update) {
|
|
295
|
-
const text = extractTextContent(update.content);
|
|
296
|
-
if (text)
|
|
297
|
-
this.emit('agent_thought_chunk', truncate(text, 80));
|
|
298
|
-
}
|
|
299
|
-
// ACP usage is "context-window used / size", not cumulative I/O tokens. We map it
|
|
300
|
-
// into total_tokens so the existing orchestrator accounting stays meaningful; the
|
|
301
|
-
// I/O split is recorded as zero because ACP does not expose it.
|
|
302
|
-
onUsageUpdate(update) {
|
|
303
|
-
const used = Number(update.used ?? 0);
|
|
304
|
-
const size = Number(update.size ?? 0);
|
|
305
|
-
this.opts.onTokenUsage({ input_tokens: 0, output_tokens: 0, total_tokens: used });
|
|
306
|
-
this.emit('usage_update', `used=${used}/${size}`);
|
|
307
|
-
}
|
|
308
|
-
onPermissionRequest(params) {
|
|
309
|
-
// §6.1 high-trust posture: auto-approve every prompt with "allow_always" so the
|
|
310
|
-
// agent doesn't ask twice in the same session. Falls back to the first listed option
|
|
311
|
-
// if no "allow_*" kind is present, which keeps the session alive in degraded mode.
|
|
312
|
-
const preferred = params.options.find((o) => o.kind === 'allow_always') ??
|
|
313
|
-
params.options.find((o) => o.kind === 'allow_once') ??
|
|
314
|
-
params.options[0];
|
|
315
|
-
const optionId = preferred?.optionId ?? '';
|
|
316
|
-
const tool = summarizeToolCallUpdate(params.toolCall);
|
|
317
|
-
this.emit('approval_auto_approved', `${optionId || 'unknown'}: ${tool}`);
|
|
318
|
-
return { outcome: { outcome: 'selected', optionId } };
|
|
319
|
-
}
|
|
320
|
-
handleTransportClose(reason) {
|
|
321
|
-
if (this.closed)
|
|
322
|
-
return;
|
|
323
|
-
this.closed = true;
|
|
324
|
-
this.emit('subprocess_exit', reason);
|
|
325
|
-
// Force-end the LineTap streams so the SDK's `receive()` reader loop observes
|
|
326
|
-
// `done: true` from `reader.read()`. That makes the SDK call its internal `close()`,
|
|
327
|
-
// which rejects every entry in `pendingResponses` (including the in-flight
|
|
328
|
-
// `session/prompt`). Without this, the runner hangs in `runPrompt()` for the full
|
|
329
|
-
// `prompt_timeout_ms` (30 min) even though the socket is gone, because `socket.destroy()`
|
|
330
|
-
// emits `'close'` on the socket but Node's pipe machinery does not always propagate an
|
|
331
|
-
// end-of-stream through the Transform synchronously. `Transform.end()` is idempotent
|
|
332
|
-
// and safe to call here even if the natural pipe-EOF would have eventually arrived.
|
|
333
|
-
try {
|
|
334
|
-
this.inboundTap.end();
|
|
335
|
-
}
|
|
336
|
-
catch {
|
|
337
|
-
/* idempotent — already ended */
|
|
338
|
-
}
|
|
339
|
-
try {
|
|
340
|
-
this.outboundTap.end();
|
|
341
|
-
}
|
|
342
|
-
catch {
|
|
343
|
-
/* idempotent — already ended */
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Explicit force-close for cancel paths. Idempotent. Triggers `handleTransportClose`
|
|
348
|
-
* (and thus the SDK's internal close + pendingResponses rejection) without waiting for
|
|
349
|
-
* the underlying socket to surface its own `'close'` event. Safe to call from cancel
|
|
350
|
-
* timers that fire repeatedly.
|
|
351
|
-
*/
|
|
352
|
-
forceClose(reason) {
|
|
353
|
-
this.handleTransportClose(reason);
|
|
354
|
-
}
|
|
355
|
-
// Negotiate protocol + open a session. Throws on either failure.
|
|
356
|
-
async initSession() {
|
|
357
|
-
const init = await withTimeout(this.conn.initialize({
|
|
358
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
359
|
-
clientInfo: { name: 'smol-symphony', version: '0.1.0' },
|
|
360
|
-
clientCapabilities: {
|
|
361
|
-
// Advertise the minimum: the agent can read/write the workspace itself inside
|
|
362
|
-
// the VM, so we do not offer fs/terminal capabilities.
|
|
363
|
-
fs: { readTextFile: false, writeTextFile: false },
|
|
364
|
-
terminal: false,
|
|
365
|
-
},
|
|
366
|
-
}), this.opts.readTimeoutMs, 'initialize');
|
|
367
|
-
this.emit('session_init', `protocolVersion=${init.protocolVersion}`);
|
|
368
|
-
// MCP is required for symphony operations: if the agent doesn't advertise support
|
|
369
|
-
// for a requested transport, we refuse to start the session rather than silently
|
|
370
|
-
// dropping the entry and running a degraded agent that has no transition /
|
|
371
|
-
// request_human_steering tools. ACP's mcpCapabilities is optional and advertises
|
|
372
|
-
// `http`/`sse`/`acp` as booleans; missing/undefined means "not supported." Stdio is
|
|
373
|
-
// implicit (the spec treats it as the baseline) and has no `type` discriminator.
|
|
374
|
-
const requested = this.opts.mcpServers ?? [];
|
|
375
|
-
const caps = (init.agentCapabilities ?? {});
|
|
376
|
-
const mcpCaps = caps.mcpCapabilities ?? {};
|
|
377
|
-
const supportsKind = (kind) => {
|
|
378
|
-
if (kind === 'stdio')
|
|
379
|
-
return true;
|
|
380
|
-
if (kind === 'http')
|
|
381
|
-
return mcpCaps.http === true;
|
|
382
|
-
if (kind === 'sse')
|
|
383
|
-
return mcpCaps.sse === true;
|
|
384
|
-
if (kind === 'acp')
|
|
385
|
-
return mcpCaps.acp === true;
|
|
386
|
-
return false;
|
|
387
|
-
};
|
|
388
|
-
const unsupported = requested.filter((s) => {
|
|
389
|
-
const kind = (s.type ?? 'stdio');
|
|
390
|
-
return !supportsKind(kind);
|
|
391
|
-
});
|
|
392
|
-
if (unsupported.length > 0) {
|
|
393
|
-
const kinds = unsupported
|
|
394
|
-
.map((s) => s.type ?? 'stdio')
|
|
395
|
-
.join(', ');
|
|
396
|
-
this.emit('mcp_capability_mismatch', `unsupported=${kinds} adapter_caps=${JSON.stringify(mcpCaps)}`);
|
|
397
|
-
throw new AcpProtocolError('mcp_capability_mismatch', `agent does not support required MCP transport(s): ${kinds}. Adapter caps: ${JSON.stringify(mcpCaps)}`);
|
|
398
|
-
}
|
|
399
|
-
const session = await withTimeout(this.conn.newSession({ cwd: this.opts.cwd, mcpServers: requested }), this.opts.readTimeoutMs, 'session/new');
|
|
400
|
-
this.sessionId = session.sessionId;
|
|
401
|
-
this.emit('session_started', `sessionId=${session.sessionId} cwd=${this.opts.cwd} mcp_servers=${requested.length}`);
|
|
402
|
-
return { sessionId: session.sessionId };
|
|
403
|
-
}
|
|
404
|
-
async runPrompt(promptText) {
|
|
405
|
-
if (this.closed)
|
|
406
|
-
return { reason: 'subprocess_exit', message: 'adapter already closed' };
|
|
407
|
-
if (!this.sessionId)
|
|
408
|
-
return { reason: 'startup_failed', message: 'no active session' };
|
|
409
|
-
this.lastAssistantText = '';
|
|
410
|
-
const request = {
|
|
411
|
-
sessionId: this.sessionId,
|
|
412
|
-
prompt: [{ type: 'text', text: promptText }],
|
|
413
|
-
};
|
|
414
|
-
let resp;
|
|
415
|
-
try {
|
|
416
|
-
resp = await withTimeout(this.conn.prompt(request), this.opts.promptTimeoutMs, 'session/prompt');
|
|
417
|
-
}
|
|
418
|
-
catch (err) {
|
|
419
|
-
if (err instanceof TimeoutError) {
|
|
420
|
-
// Best-effort cancel so the adapter doesn't keep working in the background.
|
|
421
|
-
this.cancel().catch(() => undefined);
|
|
422
|
-
return { reason: 'prompt_timeout', message: err.message };
|
|
423
|
-
}
|
|
424
|
-
if (this.closed)
|
|
425
|
-
return { reason: 'subprocess_exit', message: err.message };
|
|
426
|
-
const message = err.message;
|
|
427
|
-
if (isTransportError(message))
|
|
428
|
-
return { reason: 'transport_error', message };
|
|
429
|
-
return { reason: 'refusal', message };
|
|
430
|
-
}
|
|
431
|
-
return mapStopReason(resp.stopReason, this.lastAssistantText);
|
|
432
|
-
}
|
|
433
|
-
async cancel() {
|
|
434
|
-
if (!this.sessionId || this.closed || this.cancelled)
|
|
435
|
-
return;
|
|
436
|
-
this.cancelled = true;
|
|
437
|
-
const note = { sessionId: this.sessionId };
|
|
438
|
-
try {
|
|
439
|
-
await this.conn.cancel(note);
|
|
440
|
-
}
|
|
441
|
-
catch (err) {
|
|
442
|
-
log.debug('acp cancel failed', { error: err.message });
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
function mapStopReason(stopReason, lastText) {
|
|
447
|
-
switch (stopReason) {
|
|
448
|
-
case 'end_turn':
|
|
449
|
-
return { reason: 'end_turn', message: summarize(lastText) };
|
|
450
|
-
case 'max_tokens':
|
|
451
|
-
case 'max_turn_requests':
|
|
452
|
-
case 'refusal':
|
|
453
|
-
case 'cancelled':
|
|
454
|
-
return { reason: stopReason, message: summarize(lastText) };
|
|
455
|
-
default:
|
|
456
|
-
return { reason: 'refusal', message: `unknown stop_reason ${stopReason}` };
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
class TimeoutError extends Error {
|
|
460
|
-
}
|
|
461
|
-
function withTimeout(p, ms, label) {
|
|
462
|
-
return new Promise((resolve, reject) => {
|
|
463
|
-
const t = setTimeout(() => reject(new TimeoutError(`${label} timed out after ${ms}ms`)), ms);
|
|
464
|
-
p.then((v) => {
|
|
465
|
-
clearTimeout(t);
|
|
466
|
-
resolve(v);
|
|
467
|
-
}, (e) => {
|
|
468
|
-
clearTimeout(t);
|
|
469
|
-
reject(e);
|
|
470
|
-
});
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
//# sourceMappingURL=acp.js.map
|