smol-symphony 0.2.0 → 0.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/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/src/bin/symphony.js +30 -0
- package/dist/src/bin/symphony.js.map +1 -0
- package/dist/src/core/actions/context.js +109 -0
- package/dist/src/core/actions/context.js.map +1 -0
- package/dist/{actions/parsing.js → src/core/actions/parse.js} +33 -114
- package/dist/src/core/actions/parse.js.map +1 -0
- package/dist/src/core/actions/plan.js +197 -0
- package/dist/src/core/actions/plan.js.map +1 -0
- package/dist/src/core/actions/predicates.js +111 -0
- package/dist/src/core/actions/predicates.js.map +1 -0
- package/dist/src/core/actions/run-fold.js +248 -0
- package/dist/src/core/actions/run-fold.js.map +1 -0
- package/dist/src/core/actions/template.js +118 -0
- package/dist/src/core/actions/template.js.map +1 -0
- package/dist/src/core/cli/args.js +116 -0
- package/dist/src/core/cli/args.js.map +1 -0
- package/dist/src/core/coerce.js +75 -0
- package/dist/src/core/coerce.js.map +1 -0
- package/dist/src/core/credential/account-id.js +20 -0
- package/dist/src/core/credential/account-id.js.map +1 -0
- package/dist/src/core/credential/adapter-config.js +136 -0
- package/dist/src/core/credential/adapter-config.js.map +1 -0
- package/dist/src/core/credential/availability.js +98 -0
- package/dist/src/core/credential/availability.js.map +1 -0
- package/dist/src/core/credential/extract.js +228 -0
- package/dist/src/core/credential/extract.js.map +1 -0
- package/dist/src/core/credential/fake-creds.js +171 -0
- package/dist/src/core/credential/fake-creds.js.map +1 -0
- package/dist/src/core/credential/identity.js +125 -0
- package/dist/src/core/credential/identity.js.map +1 -0
- package/dist/src/core/credential/shape.js +230 -0
- package/dist/src/core/credential/shape.js.map +1 -0
- package/dist/src/core/credential/strings.js +15 -0
- package/dist/src/core/credential/strings.js.map +1 -0
- package/dist/src/core/doctor/checks.js +303 -0
- package/dist/src/core/doctor/checks.js.map +1 -0
- package/dist/src/core/git/result.js +107 -0
- package/dist/src/core/git/result.js.map +1 -0
- package/dist/src/core/http/decisions.js +225 -0
- package/dist/src/core/http/decisions.js.map +1 -0
- package/dist/{http.js → src/core/http/render.js} +472 -738
- package/dist/src/core/http/render.js.map +1 -0
- package/dist/{http-handlers.js → src/core/http/routes.js} +52 -87
- package/dist/src/core/http/routes.js.map +1 -0
- package/dist/src/core/http/views.js +181 -0
- package/dist/src/core/http/views.js.map +1 -0
- package/dist/src/core/image/managed-image.js +95 -0
- package/dist/src/core/image/managed-image.js.map +1 -0
- package/dist/src/core/issue/file.js +149 -0
- package/dist/src/core/issue/file.js.map +1 -0
- package/dist/src/core/issue/parse.js +210 -0
- package/dist/src/core/issue/parse.js.map +1 -0
- package/dist/src/core/mcp/dispatch.js +239 -0
- package/dist/src/core/mcp/dispatch.js.map +1 -0
- package/dist/src/core/mcp/post-move.js +92 -0
- package/dist/src/core/mcp/post-move.js.map +1 -0
- package/dist/src/core/mcp/protocol.js +293 -0
- package/dist/src/core/mcp/protocol.js.map +1 -0
- package/dist/src/core/mcp/url.js +162 -0
- package/dist/src/core/mcp/url.js.map +1 -0
- package/dist/src/core/path.js +63 -0
- package/dist/src/core/path.js.map +1 -0
- package/dist/src/core/reconcile/image-decide.js +48 -0
- package/dist/src/core/reconcile/image-decide.js.map +1 -0
- package/dist/src/core/reconcile/ledger.js +142 -0
- package/dist/src/core/reconcile/ledger.js.map +1 -0
- package/dist/src/core/reconcile/pr-classify.js +62 -0
- package/dist/src/core/reconcile/pr-classify.js.map +1 -0
- package/dist/{reconciler → src/core/reconcile}/pr-decide.js +25 -12
- package/dist/src/core/reconcile/pr-decide.js.map +1 -0
- package/dist/src/core/reconcile/pr-loop.js +161 -0
- package/dist/src/core/reconcile/pr-loop.js.map +1 -0
- package/dist/src/core/reconcile/pr-notes.js +35 -0
- package/dist/src/core/reconcile/pr-notes.js.map +1 -0
- package/dist/src/core/reconcile/vm-decide.js +70 -0
- package/dist/src/core/reconcile/vm-decide.js.map +1 -0
- package/dist/src/core/reconcile/vm-reap.js +207 -0
- package/dist/src/core/reconcile/vm-reap.js.map +1 -0
- package/dist/src/core/reconcile/workspace-decide.js +162 -0
- package/dist/src/core/reconcile/workspace-decide.js.map +1 -0
- package/dist/src/core/runlog/summary.js +231 -0
- package/dist/src/core/runlog/summary.js.map +1 -0
- package/dist/src/core/runner/dispatch-config.js +95 -0
- package/dist/src/core/runner/dispatch-config.js.map +1 -0
- package/dist/src/core/runner/injection.js +61 -0
- package/dist/src/core/runner/injection.js.map +1 -0
- package/dist/src/core/runner/mise.js +210 -0
- package/dist/src/core/runner/mise.js.map +1 -0
- package/dist/src/core/runner/prompt.js +720 -0
- package/dist/src/core/runner/prompt.js.map +1 -0
- package/dist/src/core/runner/turn.js +242 -0
- package/dist/src/core/runner/turn.js.map +1 -0
- package/dist/src/core/runner/vm-plan.js +390 -0
- package/dist/src/core/runner/vm-plan.js.map +1 -0
- package/dist/src/core/schedule/admission.js +123 -0
- package/dist/src/core/schedule/admission.js.map +1 -0
- package/dist/src/core/schedule/circuit-breaker.js +111 -0
- package/dist/src/core/schedule/circuit-breaker.js.map +1 -0
- package/dist/src/core/schedule/eligibility.js +83 -0
- package/dist/src/core/schedule/eligibility.js.map +1 -0
- package/dist/src/core/schedule/reconcile-issue.js +82 -0
- package/dist/src/core/schedule/reconcile-issue.js.map +1 -0
- package/dist/src/core/schedule/retry.js +96 -0
- package/dist/src/core/schedule/retry.js.map +1 -0
- package/dist/src/core/schedule/sleep-cycle.js +133 -0
- package/dist/src/core/schedule/sleep-cycle.js.map +1 -0
- package/dist/src/core/schedule/slots.js +124 -0
- package/dist/src/core/schedule/slots.js.map +1 -0
- package/dist/src/core/schedule/tick.js +553 -0
- package/dist/src/core/schedule/tick.js.map +1 -0
- package/dist/src/core/schedule/token-fold.js +181 -0
- package/dist/src/core/schedule/token-fold.js.map +1 -0
- package/dist/src/core/state-resolve.js +86 -0
- package/dist/src/core/state-resolve.js.map +1 -0
- package/dist/src/core/vm-guards.js +278 -0
- package/dist/src/core/vm-guards.js.map +1 -0
- package/dist/src/core/workflow/derive.js +107 -0
- package/dist/src/core/workflow/derive.js.map +1 -0
- package/dist/src/core/workflow/parse.js +687 -0
- package/dist/src/core/workflow/parse.js.map +1 -0
- package/dist/src/core/workflow/prompt-probe.js +78 -0
- package/dist/src/core/workflow/prompt-probe.js.map +1 -0
- package/dist/src/core/workflow/validate.js +189 -0
- package/dist/src/core/workflow/validate.js.map +1 -0
- package/dist/src/core/workspace-key.js +19 -0
- package/dist/src/core/workspace-key.js.map +1 -0
- package/dist/src/shell/actions-runner.js +356 -0
- package/dist/src/shell/actions-runner.js.map +1 -0
- package/dist/src/shell/adapter/adapter-registry.js +45 -0
- package/dist/src/shell/adapter/adapter-registry.js.map +1 -0
- package/dist/src/shell/adapter/clock-random.js +96 -0
- package/dist/src/shell/adapter/clock-random.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-dispatch-helpers.js +158 -0
- package/dist/src/shell/adapter/gondolin-dispatch-helpers.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-dispatch.js +385 -0
- package/dist/src/shell/adapter/gondolin-dispatch.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-image-converter.js +233 -0
- package/dist/src/shell/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/src/shell/adapter/gondolin-image-fetch.js +180 -0
- package/dist/src/shell/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/src/shell/adapter/launcher-asset.js +57 -0
- package/dist/src/shell/adapter/launcher-asset.js.map +1 -0
- package/dist/src/shell/adapter/mise-config-asset.js +65 -0
- package/dist/src/shell/adapter/mise-config-asset.js.map +1 -0
- package/dist/src/shell/adapter/workflow-loader.js +304 -0
- package/dist/src/shell/adapter/workflow-loader.js.map +1 -0
- package/dist/src/shell/cli/doctor.js +268 -0
- package/dist/src/shell/cli/doctor.js.map +1 -0
- package/dist/src/shell/effect-interpreter-families.js +314 -0
- package/dist/src/shell/effect-interpreter-families.js.map +1 -0
- package/dist/src/shell/effect-interpreter.js +29 -0
- package/dist/src/shell/effect-interpreter.js.map +1 -0
- package/dist/src/shell/interp/acp-frame.js +137 -0
- package/dist/src/shell/interp/acp-frame.js.map +1 -0
- package/dist/src/shell/interp/acp-ws-conn.js +320 -0
- package/dist/src/shell/interp/acp-ws-conn.js.map +1 -0
- package/dist/src/shell/interp/acp-ws-frames.js +159 -0
- package/dist/src/shell/interp/acp-ws-frames.js.map +1 -0
- package/dist/src/shell/interp/acp-ws.js +197 -0
- package/dist/src/shell/interp/acp-ws.js.map +1 -0
- package/dist/src/shell/interp/acp.js +319 -0
- package/dist/src/shell/interp/acp.js.map +1 -0
- package/dist/src/shell/interp/credential-defaults.js +128 -0
- package/dist/src/shell/interp/credential-defaults.js.map +1 -0
- package/dist/src/shell/interp/credential-hooks.js +149 -0
- package/dist/src/shell/interp/credential-hooks.js.map +1 -0
- package/dist/src/shell/interp/credential-registry.js +226 -0
- package/dist/src/shell/interp/credential-registry.js.map +1 -0
- package/dist/src/shell/interp/credential.js +103 -0
- package/dist/src/shell/interp/credential.js.map +1 -0
- package/dist/src/shell/interp/gh.js +163 -0
- package/dist/src/shell/interp/gh.js.map +1 -0
- package/dist/src/shell/interp/git.js +28 -0
- package/dist/src/shell/interp/git.js.map +1 -0
- package/dist/src/shell/interp/log.js +213 -0
- package/dist/src/shell/interp/log.js.map +1 -0
- package/dist/src/shell/interp/process.js +178 -0
- package/dist/src/shell/interp/process.js.map +1 -0
- package/dist/src/shell/interp/runlog.js +193 -0
- package/dist/src/shell/interp/runlog.js.map +1 -0
- package/dist/src/shell/interp/timer.js +64 -0
- package/dist/src/shell/interp/timer.js.map +1 -0
- package/dist/src/shell/interp/tracker-disk.js +99 -0
- package/dist/src/shell/interp/tracker-disk.js.map +1 -0
- package/dist/src/shell/interp/tracker-parse.js +71 -0
- package/dist/src/shell/interp/tracker-parse.js.map +1 -0
- package/dist/src/shell/interp/tracker-scan.js +238 -0
- package/dist/src/shell/interp/tracker-scan.js.map +1 -0
- package/dist/src/shell/interp/tracker-write.js +91 -0
- package/dist/src/shell/interp/tracker-write.js.map +1 -0
- package/dist/src/shell/interp/tracker.js +41 -0
- package/dist/src/shell/interp/tracker.js.map +1 -0
- package/dist/src/shell/interp/tty.js +48 -0
- package/dist/src/shell/interp/tty.js.map +1 -0
- package/dist/src/shell/interp/vm.js +199 -0
- package/dist/src/shell/interp/vm.js.map +1 -0
- package/dist/src/shell/interp/workspace.js +310 -0
- package/dist/src/shell/interp/workspace.js.map +1 -0
- package/dist/src/shell/main-acp.js +78 -0
- package/dist/src/shell/main-acp.js.map +1 -0
- package/dist/src/shell/main-adapters.js +222 -0
- package/dist/src/shell/main-adapters.js.map +1 -0
- package/dist/src/shell/main-credential.js +122 -0
- package/dist/src/shell/main-credential.js.map +1 -0
- package/dist/src/shell/main-doctor.js +22 -0
- package/dist/src/shell/main-doctor.js.map +1 -0
- package/dist/src/shell/main-entry.js +46 -0
- package/dist/src/shell/main-entry.js.map +1 -0
- package/dist/src/shell/main-http-csrf.js +45 -0
- package/dist/src/shell/main-http-csrf.js.map +1 -0
- package/dist/src/shell/main-http-handler.js +389 -0
- package/dist/src/shell/main-http-handler.js.map +1 -0
- package/dist/src/shell/main-http-mcp.js +122 -0
- package/dist/src/shell/main-http-mcp.js.map +1 -0
- package/dist/src/shell/main-http-views.js +253 -0
- package/dist/src/shell/main-http-views.js.map +1 -0
- package/dist/src/shell/main-http.js +76 -0
- package/dist/src/shell/main-http.js.map +1 -0
- package/dist/src/shell/main-loops.js +130 -0
- package/dist/src/shell/main-loops.js.map +1 -0
- package/dist/src/shell/main-mcp.js +129 -0
- package/dist/src/shell/main-mcp.js.map +1 -0
- package/dist/src/shell/main-orchestrator.js +120 -0
- package/dist/src/shell/main-orchestrator.js.map +1 -0
- package/dist/src/shell/main-preflight.js +43 -0
- package/dist/src/shell/main-preflight.js.map +1 -0
- package/dist/src/shell/main-reconcilers-helpers.js +244 -0
- package/dist/src/shell/main-reconcilers-helpers.js.map +1 -0
- package/dist/src/shell/main-reconcilers-pr.js +148 -0
- package/dist/src/shell/main-reconcilers-pr.js.map +1 -0
- package/dist/src/shell/main-reconcilers.js +225 -0
- package/dist/src/shell/main-reconcilers.js.map +1 -0
- package/dist/src/shell/main-runner.js +355 -0
- package/dist/src/shell/main-runner.js.map +1 -0
- package/dist/src/shell/main-scaffold.js +116 -0
- package/dist/src/shell/main-scaffold.js.map +1 -0
- package/dist/src/shell/main-shutdown.js +115 -0
- package/dist/src/shell/main-shutdown.js.map +1 -0
- package/dist/src/shell/main-startup.js +48 -0
- package/dist/src/shell/main-startup.js.map +1 -0
- package/dist/src/shell/main-substrates.js +43 -0
- package/dist/src/shell/main-substrates.js.map +1 -0
- package/dist/src/shell/main.js +385 -0
- package/dist/src/shell/main.js.map +1 -0
- package/dist/src/shell/orchestrator-feedback.js +69 -0
- package/dist/src/shell/orchestrator-feedback.js.map +1 -0
- package/dist/src/shell/orchestrator-image.js +167 -0
- package/dist/src/shell/orchestrator-image.js.map +1 -0
- package/dist/src/shell/orchestrator-loop.js +468 -0
- package/dist/src/shell/orchestrator-loop.js.map +1 -0
- package/dist/src/shell/orchestrator-reconcile.js +36 -0
- package/dist/src/shell/orchestrator-reconcile.js.map +1 -0
- package/dist/src/shell/reconciler-loop.js +228 -0
- package/dist/src/shell/reconciler-loop.js.map +1 -0
- package/dist/src/shell/runner-loop-turn.js +301 -0
- package/dist/src/shell/runner-loop-turn.js.map +1 -0
- package/dist/src/shell/runner-loop.js +338 -0
- package/dist/src/shell/runner-loop.js.map +1 -0
- package/dist/src/shell/server/http.js +208 -0
- package/dist/src/shell/server/http.js.map +1 -0
- package/dist/src/shell/server/mcp-runtime-effects.js +237 -0
- package/dist/src/shell/server/mcp-runtime-effects.js.map +1 -0
- package/dist/src/shell/server/mcp-runtime.js +99 -0
- package/dist/src/shell/server/mcp-runtime.js.map +1 -0
- package/dist/src/shell/workspace-key.js +14 -0
- package/dist/src/shell/workspace-key.js.map +1 -0
- package/dist/src/types/acp.js +8 -0
- package/dist/src/types/acp.js.map +1 -0
- package/dist/src/types/actions/plan.js +6 -0
- package/dist/src/types/actions/plan.js.map +1 -0
- package/dist/src/types/actions/predicates.js +6 -0
- package/dist/src/types/actions/predicates.js.map +1 -0
- package/dist/src/types/actions/run-fold.js +8 -0
- package/dist/src/types/actions/run-fold.js.map +1 -0
- package/dist/src/types/actions.js +7 -0
- package/dist/src/types/actions.js.map +1 -0
- package/dist/src/types/adapter/clock-random.js +4 -0
- package/dist/src/types/adapter/clock-random.js.map +1 -0
- package/dist/src/types/adapter/gondolin-image-converter.js +5 -0
- package/dist/src/types/adapter/gondolin-image-converter.js.map +1 -0
- package/dist/src/types/adapter/gondolin-image-fetch.js +5 -0
- package/dist/src/types/adapter/gondolin-image-fetch.js.map +1 -0
- package/dist/src/types/adapter/workflow-loader.js +4 -0
- package/dist/src/types/adapter/workflow-loader.js.map +1 -0
- package/dist/src/types/cli/args.js +8 -0
- package/dist/src/types/cli/args.js.map +1 -0
- package/dist/src/types/config.js +8 -0
- package/dist/src/types/config.js.map +1 -0
- package/dist/src/types/credential-interp.js +6 -0
- package/dist/src/types/credential-interp.js.map +1 -0
- package/dist/src/types/credentials.js +10 -0
- package/dist/src/types/credentials.js.map +1 -0
- package/dist/src/types/doctor.js +7 -0
- package/dist/src/types/doctor.js.map +1 -0
- package/dist/src/types/domain.js +7 -0
- package/dist/src/types/domain.js.map +1 -0
- package/dist/src/types/effect.js +15 -0
- package/dist/src/types/effect.js.map +1 -0
- package/dist/src/types/errors.js +39 -0
- package/dist/src/types/errors.js.map +1 -0
- package/dist/src/types/http/decisions.js +6 -0
- package/dist/src/types/http/decisions.js.map +1 -0
- package/dist/src/types/http/render.js +10 -0
- package/dist/src/types/http/render.js.map +1 -0
- package/dist/src/types/http/views.js +6 -0
- package/dist/src/types/http/views.js.map +1 -0
- package/dist/src/types/http.js +9 -0
- package/dist/src/types/http.js.map +1 -0
- package/dist/src/types/image/managed-image.js +7 -0
- package/dist/src/types/image/managed-image.js.map +1 -0
- package/dist/src/types/interp/effect-interpreter.js +8 -0
- package/dist/src/types/interp/effect-interpreter.js.map +1 -0
- package/dist/src/types/interp/tracker.js +7 -0
- package/dist/src/types/interp/tracker.js.map +1 -0
- package/dist/src/types/issue/file.js +6 -0
- package/dist/src/types/issue/file.js.map +1 -0
- package/dist/src/types/issue/parse.js +8 -0
- package/dist/src/types/issue/parse.js.map +1 -0
- package/dist/src/types/main-acp.js +13 -0
- package/dist/src/types/main-acp.js.map +1 -0
- package/dist/src/types/main-adapters.js +5 -0
- package/dist/src/types/main-adapters.js.map +1 -0
- package/dist/src/types/main-credential.js +21 -0
- package/dist/src/types/main-credential.js.map +1 -0
- package/dist/src/types/main-doctor.js +6 -0
- package/dist/src/types/main-doctor.js.map +1 -0
- package/dist/src/types/main-http-handler.js +12 -0
- package/dist/src/types/main-http-handler.js.map +1 -0
- package/dist/src/types/main-http.js +5 -0
- package/dist/src/types/main-http.js.map +1 -0
- package/dist/src/types/main-loops.js +5 -0
- package/dist/src/types/main-loops.js.map +1 -0
- package/dist/src/types/main-mcp.js +12 -0
- package/dist/src/types/main-mcp.js.map +1 -0
- package/dist/src/types/main-orchestrator.js +5 -0
- package/dist/src/types/main-orchestrator.js.map +1 -0
- package/dist/src/types/main-reconcilers.js +11 -0
- package/dist/src/types/main-reconcilers.js.map +1 -0
- package/dist/src/types/main-runner.js +13 -0
- package/dist/src/types/main-runner.js.map +1 -0
- package/dist/src/types/main-startup.js +5 -0
- package/dist/src/types/main-startup.js.map +1 -0
- package/dist/src/types/main-substrates.js +5 -0
- package/dist/src/types/main-substrates.js.map +1 -0
- package/dist/src/types/mcp/dispatch.js +4 -0
- package/dist/src/types/mcp/dispatch.js.map +1 -0
- package/dist/src/types/mcp/post-move.js +7 -0
- package/dist/src/types/mcp/post-move.js.map +1 -0
- package/dist/src/types/mcp.js +9 -0
- package/dist/src/types/mcp.js.map +1 -0
- package/dist/src/types/ports.js +12 -0
- package/dist/src/types/ports.js.map +1 -0
- package/dist/src/types/reconcile/image-decide.js +5 -0
- package/dist/src/types/reconcile/image-decide.js.map +1 -0
- package/dist/src/types/reconcile/ledger.js +7 -0
- package/dist/src/types/reconcile/ledger.js.map +1 -0
- package/dist/src/types/reconcile/pr-loop.js +8 -0
- package/dist/src/types/reconcile/pr-loop.js.map +1 -0
- package/dist/src/types/reconcile/vm-reap.js +8 -0
- package/dist/src/types/reconcile/vm-reap.js.map +1 -0
- package/dist/src/types/reconcile/workspace-decide.js +7 -0
- package/dist/src/types/reconcile/workspace-decide.js.map +1 -0
- package/dist/src/types/reconcile.js +9 -0
- package/dist/src/types/reconcile.js.map +1 -0
- package/dist/src/types/runlog.js +7 -0
- package/dist/src/types/runlog.js.map +1 -0
- package/dist/src/types/runner/actions-runner.js +12 -0
- package/dist/src/types/runner/actions-runner.js.map +1 -0
- package/dist/src/types/runner/gondolin-dispatch.js +5 -0
- package/dist/src/types/runner/gondolin-dispatch.js.map +1 -0
- package/dist/src/types/runner/injection.js +6 -0
- package/dist/src/types/runner/injection.js.map +1 -0
- package/dist/src/types/runner/runner-loop.js +5 -0
- package/dist/src/types/runner/runner-loop.js.map +1 -0
- package/dist/src/types/runner/turn.js +4 -0
- package/dist/src/types/runner/turn.js.map +1 -0
- package/dist/src/types/runner/vm-plan.js +4 -0
- package/dist/src/types/runner/vm-plan.js.map +1 -0
- package/dist/src/types/runtime.js +9 -0
- package/dist/src/types/runtime.js.map +1 -0
- package/dist/src/types/schedule/admission.js +7 -0
- package/dist/src/types/schedule/admission.js.map +1 -0
- package/dist/src/types/schedule/circuit-breaker.js +2 -0
- package/dist/src/types/schedule/circuit-breaker.js.map +1 -0
- package/dist/src/types/schedule/eligibility.js +9 -0
- package/dist/src/types/schedule/eligibility.js.map +1 -0
- package/dist/src/types/schedule/orchestrator-loop.js +10 -0
- package/dist/src/types/schedule/orchestrator-loop.js.map +1 -0
- package/dist/src/types/schedule/sleep-cycle.js +4 -0
- package/dist/src/types/schedule/sleep-cycle.js.map +1 -0
- package/dist/src/types/schedule/slots.js +8 -0
- package/dist/src/types/schedule/slots.js.map +1 -0
- package/dist/src/types/schedule/tick.js +9 -0
- package/dist/src/types/schedule/tick.js.map +1 -0
- package/dist/src/types/server/mcp-runtime.js +8 -0
- package/dist/src/types/server/mcp-runtime.js.map +1 -0
- package/dist/src/types/workflow/parse.js +4 -0
- package/dist/src/types/workflow/parse.js.map +1 -0
- package/dist/tests/core/account-id.test.js +35 -0
- package/dist/tests/core/account-id.test.js.map +1 -0
- package/dist/tests/core/actions-parse.test.js +176 -0
- package/dist/tests/core/actions-parse.test.js.map +1 -0
- package/dist/tests/core/adapter-config.test.js +133 -0
- package/dist/tests/core/adapter-config.test.js.map +1 -0
- package/dist/tests/core/admission.test.js +215 -0
- package/dist/tests/core/admission.test.js.map +1 -0
- package/dist/tests/core/args.test.js +132 -0
- package/dist/tests/core/args.test.js.map +1 -0
- package/dist/tests/core/availability.test.js +62 -0
- package/dist/tests/core/availability.test.js.map +1 -0
- package/dist/tests/core/checks.test.js +395 -0
- package/dist/tests/core/checks.test.js.map +1 -0
- package/dist/tests/core/circuit-breaker.test.js +172 -0
- package/dist/tests/core/circuit-breaker.test.js.map +1 -0
- package/dist/tests/core/coerce.test.js +87 -0
- package/dist/tests/core/coerce.test.js.map +1 -0
- package/dist/tests/core/context.test.js +228 -0
- package/dist/tests/core/context.test.js.map +1 -0
- package/dist/tests/core/decisions.test.js +310 -0
- package/dist/tests/core/decisions.test.js.map +1 -0
- package/dist/tests/core/derive.test.js +205 -0
- package/dist/tests/core/derive.test.js.map +1 -0
- package/dist/tests/core/dispatch-config.test.js +164 -0
- package/dist/tests/core/dispatch-config.test.js.map +1 -0
- package/dist/tests/core/dispatch.test.js +302 -0
- package/dist/tests/core/dispatch.test.js.map +1 -0
- package/dist/tests/core/eligibility.test.js +163 -0
- package/dist/tests/core/eligibility.test.js.map +1 -0
- package/dist/tests/core/extract.test.js +139 -0
- package/dist/tests/core/extract.test.js.map +1 -0
- package/dist/tests/core/fake-creds.test.js +134 -0
- package/dist/tests/core/fake-creds.test.js.map +1 -0
- package/dist/tests/core/file.test.js +197 -0
- package/dist/tests/core/file.test.js.map +1 -0
- package/dist/tests/core/git-result.test.js +113 -0
- package/dist/tests/core/git-result.test.js.map +1 -0
- package/dist/tests/core/identity.test.js +180 -0
- package/dist/tests/core/identity.test.js.map +1 -0
- package/dist/tests/core/image-decide.test.js +59 -0
- package/dist/tests/core/image-decide.test.js.map +1 -0
- package/dist/tests/core/injection.test.js +163 -0
- package/dist/tests/core/injection.test.js.map +1 -0
- package/dist/tests/core/ledger.test.js +218 -0
- package/dist/tests/core/ledger.test.js.map +1 -0
- package/dist/tests/core/managed-image.test.js +68 -0
- package/dist/tests/core/managed-image.test.js.map +1 -0
- package/dist/tests/core/mise.test.js +138 -0
- package/dist/tests/core/mise.test.js.map +1 -0
- package/dist/tests/core/parse.test.js +174 -0
- package/dist/tests/core/parse.test.js.map +1 -0
- package/dist/tests/core/path.test.js +50 -0
- package/dist/tests/core/path.test.js.map +1 -0
- package/dist/tests/core/plan.test.js +218 -0
- package/dist/tests/core/plan.test.js.map +1 -0
- package/dist/tests/core/post-move.test.js +162 -0
- package/dist/tests/core/post-move.test.js.map +1 -0
- package/dist/tests/core/pr-classify.test.js +117 -0
- package/dist/tests/core/pr-classify.test.js.map +1 -0
- package/dist/tests/core/pr-decide.test.js +298 -0
- package/dist/tests/core/pr-decide.test.js.map +1 -0
- package/dist/tests/core/pr-loop.test.js +301 -0
- package/dist/tests/core/pr-loop.test.js.map +1 -0
- package/dist/tests/core/pr-notes.test.js +165 -0
- package/dist/tests/core/pr-notes.test.js.map +1 -0
- package/dist/tests/core/predicates.test.js +154 -0
- package/dist/tests/core/predicates.test.js.map +1 -0
- package/dist/tests/core/prompt.test.js +189 -0
- package/dist/tests/core/prompt.test.js.map +1 -0
- package/dist/tests/core/protocol.test.js +195 -0
- package/dist/tests/core/protocol.test.js.map +1 -0
- package/dist/tests/core/reconcile-issue.test.js +116 -0
- package/dist/tests/core/reconcile-issue.test.js.map +1 -0
- package/dist/tests/core/render.test.js +549 -0
- package/dist/tests/core/render.test.js.map +1 -0
- package/dist/tests/core/retry.test.js +186 -0
- package/dist/tests/core/retry.test.js.map +1 -0
- package/dist/tests/core/routes.test.js +247 -0
- package/dist/tests/core/routes.test.js.map +1 -0
- package/dist/tests/core/run-fold.test.js +299 -0
- package/dist/tests/core/run-fold.test.js.map +1 -0
- package/dist/tests/core/shape.test.js +185 -0
- package/dist/tests/core/shape.test.js.map +1 -0
- package/dist/tests/core/sleep-cycle.test.js +150 -0
- package/dist/tests/core/sleep-cycle.test.js.map +1 -0
- package/dist/tests/core/slots.test.js +201 -0
- package/dist/tests/core/slots.test.js.map +1 -0
- package/dist/tests/core/state-resolve.test.js +80 -0
- package/dist/tests/core/state-resolve.test.js.map +1 -0
- package/dist/tests/core/summary.test.js +200 -0
- package/dist/tests/core/summary.test.js.map +1 -0
- package/dist/tests/core/template.test.js +116 -0
- package/dist/tests/core/template.test.js.map +1 -0
- package/dist/tests/core/tick.test.js +558 -0
- package/dist/tests/core/tick.test.js.map +1 -0
- package/dist/tests/core/token-fold.test.js +176 -0
- package/dist/tests/core/token-fold.test.js.map +1 -0
- package/dist/tests/core/turn.test.js +388 -0
- package/dist/tests/core/turn.test.js.map +1 -0
- package/dist/tests/core/url.test.js +118 -0
- package/dist/tests/core/url.test.js.map +1 -0
- package/dist/tests/core/validate.test.js +247 -0
- package/dist/tests/core/validate.test.js.map +1 -0
- package/dist/tests/core/views.test.js +252 -0
- package/dist/tests/core/views.test.js.map +1 -0
- package/dist/tests/core/vm-decide.test.js +110 -0
- package/dist/tests/core/vm-decide.test.js.map +1 -0
- package/dist/tests/core/vm-guards.test.js +153 -0
- package/dist/tests/core/vm-guards.test.js.map +1 -0
- package/dist/tests/core/vm-plan.test.js +332 -0
- package/dist/tests/core/vm-plan.test.js.map +1 -0
- package/dist/tests/core/vm-reap.test.js +196 -0
- package/dist/tests/core/vm-reap.test.js.map +1 -0
- package/dist/tests/core/workflow-parse.test.js +493 -0
- package/dist/tests/core/workflow-parse.test.js.map +1 -0
- package/dist/tests/core/workspace-decide.test.js +236 -0
- package/dist/tests/core/workspace-decide.test.js.map +1 -0
- package/dist/tests/helpers/fixtures.js +167 -0
- package/dist/tests/helpers/fixtures.js.map +1 -0
- package/dist/tests/shell/acp-substrate.test.js +101 -0
- package/dist/tests/shell/acp-substrate.test.js.map +1 -0
- package/dist/tests/shell/actions-runner-push.test.js +203 -0
- package/dist/tests/shell/actions-runner-push.test.js.map +1 -0
- package/dist/tests/shell/credential-hooks.test.js +36 -0
- package/dist/tests/shell/credential-hooks.test.js.map +1 -0
- package/dist/tests/shell/credential-registry.test.js +165 -0
- package/dist/tests/shell/credential-registry.test.js.map +1 -0
- package/dist/tests/shell/credential-substrate.test.js +179 -0
- package/dist/tests/shell/credential-substrate.test.js.map +1 -0
- package/dist/tests/shell/dockerfile-mise-pin.test.js +51 -0
- package/dist/tests/shell/dockerfile-mise-pin.test.js.map +1 -0
- package/dist/tests/shell/doctor.test.js +101 -0
- package/dist/tests/shell/doctor.test.js.map +1 -0
- package/dist/tests/shell/effect-vm-create.test.js +52 -0
- package/dist/tests/shell/effect-vm-create.test.js.map +1 -0
- package/dist/tests/shell/gh-port.test.js +63 -0
- package/dist/tests/shell/gh-port.test.js.map +1 -0
- package/dist/tests/shell/gondolin-dispatch-guard.test.js +144 -0
- package/dist/tests/shell/gondolin-dispatch-guard.test.js.map +1 -0
- package/dist/tests/shell/gondolin-dispatch-shquote.test.js +168 -0
- package/dist/tests/shell/gondolin-dispatch-shquote.test.js.map +1 -0
- package/dist/tests/shell/gondolin-image-converter.test.js +208 -0
- package/dist/tests/shell/gondolin-image-converter.test.js.map +1 -0
- package/dist/tests/shell/gondolin-image-fetch.test.js +93 -0
- package/dist/tests/shell/gondolin-image-fetch.test.js.map +1 -0
- package/dist/tests/shell/http-handler.test.js +608 -0
- package/dist/tests/shell/http-handler.test.js.map +1 -0
- package/dist/tests/shell/http-server.test.js +53 -0
- package/dist/tests/shell/http-server.test.js.map +1 -0
- package/dist/tests/shell/mcp-runtime.test.js +366 -0
- package/dist/tests/shell/mcp-runtime.test.js.map +1 -0
- package/dist/tests/shell/mise-config-asset.test.js +87 -0
- package/dist/tests/shell/mise-config-asset.test.js.map +1 -0
- package/dist/tests/shell/orchestrator-loop.test.js +583 -0
- package/dist/tests/shell/orchestrator-loop.test.js.map +1 -0
- package/dist/tests/shell/reconciler-passes.test.js +314 -0
- package/dist/tests/shell/reconciler-passes.test.js.map +1 -0
- package/dist/tests/shell/runner-loop-turn.test.js +97 -0
- package/dist/tests/shell/runner-loop-turn.test.js.map +1 -0
- package/dist/tests/shell/runner-slice.test.js +536 -0
- package/dist/tests/shell/runner-slice.test.js.map +1 -0
- package/dist/tests/shell/scaffold.test.js +65 -0
- package/dist/tests/shell/scaffold.test.js.map +1 -0
- package/dist/tests/shell/tick-config.test.js +83 -0
- package/dist/tests/shell/tick-config.test.js.map +1 -0
- package/dist/tests/shell/tracker-parse-dates.test.js +44 -0
- package/dist/tests/shell/tracker-parse-dates.test.js.map +1 -0
- package/dist/tests/shell/tracker-write-issue.test.js +154 -0
- package/dist/tests/shell/tracker-write-issue.test.js.map +1 -0
- package/dist/tests/shell/workflow-prompt-split.test.js +208 -0
- package/dist/tests/shell/workflow-prompt-split.test.js.map +1 -0
- package/dist/tests/shell/workspace-live-config.test.js +140 -0
- package/dist/tests/shell/workspace-live-config.test.js.map +1 -0
- package/package.json +21 -9
- 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/bin/symphony.js +0 -794
- package/dist/bin/symphony.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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// FCIS rewrite — default IO providers for the host-only credential adapter (kind:
|
|
2
|
+
// adapter). Holds the real side effects the {@link CredentialPort} threads in:
|
|
3
|
+
// default host credential paths, JSON file reads, the flock(1) cross-process
|
|
4
|
+
// refresh lock, and the claude/codex refresher spawns. Re-exported from
|
|
5
|
+
// interp/credential.ts so callers stay untouched.
|
|
6
|
+
//
|
|
7
|
+
// NodeNext ESM, .js extensions on relative imports. Imports src/types ONLY (plus
|
|
8
|
+
// real node builtins) per the shell rule.
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import { Buffer } from 'node:buffer';
|
|
12
|
+
import { readFile, mkdir } from 'node:fs/promises';
|
|
13
|
+
import { spawn } from 'node:child_process';
|
|
14
|
+
// ─── default host paths ─────────────────────────────────────────────────────────
|
|
15
|
+
export const defaultClaudeCredentialsPath = () => path.join(os.homedir(), '.claude', '.credentials.json');
|
|
16
|
+
export const defaultCodexCredentialsPath = () => path.join(os.homedir(), '.codex', 'auth.json');
|
|
17
|
+
export const defaultClaudeIdentityPath = () => path.join(os.homedir(), '.claude.json');
|
|
18
|
+
export const defaultLockPath = () => path.join(os.homedir(), '.symphony', 'oauth', 'refresh.lock');
|
|
19
|
+
/** Read+parse a JSON file; returns null on any IO/parse failure (warns once). */
|
|
20
|
+
export async function readJsonFile(p, log) {
|
|
21
|
+
let raw;
|
|
22
|
+
try {
|
|
23
|
+
raw = await readFile(p, 'utf8');
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
log.emit('warn', 'credential: cannot read credentials', { path: p, error: err.message });
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(raw);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
log.emit('warn', 'credential: credentials JSON parse failed', { path: p, error: err.message });
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// ─── flock(1) cross-process refresh lock ────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Default cross-process lock: spawn `flock(1)` holding LOCK_EX on `lockPath`. The
|
|
40
|
+
* child prints `READY` once the kernel grants the lock then blocks on stdin via
|
|
41
|
+
* `exec cat`; release closes stdin → cat EOFs → flock exits → the kernel releases
|
|
42
|
+
* the lock on FD close. `-o` closes the lock FD in the exec'd child so only the
|
|
43
|
+
* flock parent holds it. Ported verbatim from credential-extractors.ts.
|
|
44
|
+
*/
|
|
45
|
+
export function defaultFlockAcquire(lockPath) {
|
|
46
|
+
return async (timeoutMs) => {
|
|
47
|
+
await mkdir(path.dirname(lockPath), { recursive: true });
|
|
48
|
+
const child = spawn('flock', ['-x', '-o', lockPath, 'sh', '-c', 'echo READY; exec cat'], {
|
|
49
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
50
|
+
});
|
|
51
|
+
try {
|
|
52
|
+
await waitForFlockReady(child, timeoutMs);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
try {
|
|
56
|
+
child.kill('SIGKILL');
|
|
57
|
+
}
|
|
58
|
+
catch { /* ignore */ }
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
return makeFlockRelease(child);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function waitForFlockReady(child, timeoutMs) {
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
let settled = false;
|
|
67
|
+
let stdoutBuf = '';
|
|
68
|
+
let stderrBuf = '';
|
|
69
|
+
const timer = setTimeout(() => {
|
|
70
|
+
if (settled)
|
|
71
|
+
return;
|
|
72
|
+
settled = true;
|
|
73
|
+
reject(new Error('credential: refresh lock acquire timeout'));
|
|
74
|
+
}, timeoutMs);
|
|
75
|
+
const settle = (err) => {
|
|
76
|
+
if (settled)
|
|
77
|
+
return;
|
|
78
|
+
settled = true;
|
|
79
|
+
clearTimeout(timer);
|
|
80
|
+
if (err)
|
|
81
|
+
reject(err);
|
|
82
|
+
else
|
|
83
|
+
resolve();
|
|
84
|
+
};
|
|
85
|
+
child.stdout?.on('data', (c) => { stdoutBuf += c.toString('utf8'); if (stdoutBuf.includes('READY'))
|
|
86
|
+
settle(null); });
|
|
87
|
+
child.stderr?.on('data', (c) => { stderrBuf += c.toString('utf8'); });
|
|
88
|
+
child.once('error', (err) => settle(err));
|
|
89
|
+
child.once('exit', (code, signal) => settle(new Error(`flock exited before ready (code=${code}, signal=${signal}, stderr=${stderrBuf.trim()})`)));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function makeFlockRelease(child) {
|
|
93
|
+
let released = false;
|
|
94
|
+
return async () => {
|
|
95
|
+
if (released)
|
|
96
|
+
return;
|
|
97
|
+
released = true;
|
|
98
|
+
try {
|
|
99
|
+
child.stdin?.end();
|
|
100
|
+
}
|
|
101
|
+
catch { /* ignore */ }
|
|
102
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
103
|
+
return;
|
|
104
|
+
const sigterm = setTimeout(() => { try {
|
|
105
|
+
child.kill('SIGTERM');
|
|
106
|
+
}
|
|
107
|
+
catch { /* ignore */ } }, 2_000);
|
|
108
|
+
await new Promise((resolve) => child.once('exit', () => resolve()));
|
|
109
|
+
clearTimeout(sigterm);
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// ─── default refreshers (claude -p / codex exec) ────────────────────────────────
|
|
113
|
+
/** Spawn `claude -p ok` — Anthropic's own client refreshes + rewrites ~/.claude/.credentials.json. */
|
|
114
|
+
export function defaultClaudeRefresher() {
|
|
115
|
+
return () => spawnExit('claude', ['-p', 'ok']);
|
|
116
|
+
}
|
|
117
|
+
/** Spawn `codex exec` — codex's own auth manager rotates ~/.codex/auth.json (issue 161). */
|
|
118
|
+
export function defaultCodexRefresher() {
|
|
119
|
+
return () => spawnExit('codex', ['exec', '--skip-git-repo-check', '-s', 'read-only', 'ok']);
|
|
120
|
+
}
|
|
121
|
+
function spawnExit(cmd, args) {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
const p = spawn(cmd, args, { stdio: 'ignore' });
|
|
124
|
+
p.once('error', reject);
|
|
125
|
+
p.once('exit', (code) => (code === 0 ? resolve() : reject(new Error(`${cmd} exited with code ${code ?? '<null>'}`))));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=credential-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-defaults.js","sourceRoot":"","sources":["../../../../src/shell/interp/credential-defaults.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// FCIS rewrite — Gondolin egress onRequest hooks + per-VM createHttpHooks builder
|
|
2
|
+
// for the host-only credential adapter (kind: adapter). Standing egress audit, the
|
|
3
|
+
// codex chatgpt-backend route swap, the hook chainer, and buildVmHttpHooks.
|
|
4
|
+
// Re-exported from interp/credential.ts.
|
|
5
|
+
//
|
|
6
|
+
// NodeNext ESM, .js extensions on relative imports. Imports src/types ONLY (plus
|
|
7
|
+
// the real Gondolin SDK) per the shell rule.
|
|
8
|
+
import { createHttpHooks, } from '@earendil-works/gondolin';
|
|
9
|
+
/**
|
|
10
|
+
* The codex METERED platform host the chatgpt-backend route redirects FROM. The route
|
|
11
|
+
* swap applies ONLY to this host (→ `route.host`) and to requests already aimed at the
|
|
12
|
+
* backend host (`route.host`, so the path rewrite + `chatgpt-account-id` header still
|
|
13
|
+
* attach); EVERY other egress host passes through untouched. Without this gate the hook
|
|
14
|
+
* host-rewrites all non-backend egress to chatgpt.com — which broke a codex VM's
|
|
15
|
+
* `mise install` egress to registry.npmjs.org / nodejs.org (403 "Invalid URL").
|
|
16
|
+
* RCA: docs/research/codex-route-hook-host-rewrite-rca.md.
|
|
17
|
+
*/
|
|
18
|
+
const CODEX_PLATFORM_HOST = 'api.openai.com';
|
|
19
|
+
/**
|
|
20
|
+
* Egress audit. Logs method+host+path (NEVER query/headers — a token can ride
|
|
21
|
+
* either) for EVERY guest egress request, then delegates to `inner`. Gondolin runs
|
|
22
|
+
* onRequest BEFORE its allow/deny check, so this is the only host-side window into
|
|
23
|
+
* in-VM egress. Pure pass-through. Ported from credential-secrets.ts.
|
|
24
|
+
*/
|
|
25
|
+
export function makeEgressAuditHook(adapterId, allowedHosts, inner, log) {
|
|
26
|
+
return async (request) => {
|
|
27
|
+
try {
|
|
28
|
+
const u = new URL(request.url);
|
|
29
|
+
const host = u.hostname;
|
|
30
|
+
const allowed = allowedHosts.some((h) => host === h || host.endsWith(`.${h}`));
|
|
31
|
+
log.emit('info', 'egress request', { adapter: adapterId, method: request.method, host, path: u.pathname, allowed });
|
|
32
|
+
}
|
|
33
|
+
catch { /* logging must never break egress */ }
|
|
34
|
+
return inner ? inner(request) : undefined;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Apply a codex chatgpt-backend route (critic gap): swap host → chatgpt.com,
|
|
39
|
+
* rewrite `/v1/*` → `/backend-api/codex/*`, and attach `chatgpt-account-id` when
|
|
40
|
+
* present. The DECISION (codexUpstreamRoute over a TokenInfo) lives in core; this
|
|
41
|
+
* shell hook just rebuilds the outbound Request with the decided host/path/headers
|
|
42
|
+
* so a ChatGPT-OAuth subscription token reaches the backend that accepts it (the
|
|
43
|
+
* platform API 401s the missing `api.responses.write` scope). API-key creds get a
|
|
44
|
+
* null route → the request passes through unchanged.
|
|
45
|
+
*/
|
|
46
|
+
export function makeCodexUpstreamRouteHook(resolveRoute) {
|
|
47
|
+
return (request) => {
|
|
48
|
+
const route = resolveRoute();
|
|
49
|
+
if (route === null)
|
|
50
|
+
return; // API-key credential: default platform route, untouched
|
|
51
|
+
let url;
|
|
52
|
+
try {
|
|
53
|
+
url = new URL(request.url);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Source-host gate: ONLY the metered platform host gets host-redirected to the
|
|
59
|
+
// backend; a request already at the backend host keeps its host but still gets the
|
|
60
|
+
// path rewrite + header; every OTHER host (npm, nodejs, the mise registry, …) passes
|
|
61
|
+
// through untouched (see CODEX_PLATFORM_HOST).
|
|
62
|
+
if (url.hostname !== CODEX_PLATFORM_HOST && url.hostname !== route.host)
|
|
63
|
+
return;
|
|
64
|
+
if (url.hostname === CODEX_PLATFORM_HOST) {
|
|
65
|
+
url.host = route.host;
|
|
66
|
+
url.hostname = route.host;
|
|
67
|
+
}
|
|
68
|
+
url.pathname = route.rewritePath(url.pathname);
|
|
69
|
+
const headers = new Headers(request.headers);
|
|
70
|
+
for (const [k, v] of Object.entries(route.extraHeaders))
|
|
71
|
+
headers.set(k, v);
|
|
72
|
+
// `duplex: 'half'` is required by undici/Node when a body stream is present; it
|
|
73
|
+
// is not in the lib `RequestInit` type, so the init object is cast at this seam.
|
|
74
|
+
const init = {
|
|
75
|
+
method: request.method,
|
|
76
|
+
headers,
|
|
77
|
+
body: request.body,
|
|
78
|
+
duplex: 'half',
|
|
79
|
+
redirect: request.redirect,
|
|
80
|
+
};
|
|
81
|
+
return new Request(url.toString(), init);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Egress request-side lazy refresh (issue 214). A pass-through `onRequest` hook that,
|
|
86
|
+
* for requests bound to one of the credential's substitution hosts, awaits `ensureFresh`
|
|
87
|
+
* (the registry's expiry-gated host refresh + fan-out) BEFORE returning — so when Gondolin
|
|
88
|
+
* substitutes the SecretManager value into the Authorization header, it injects the
|
|
89
|
+
* fresh token rather than the one that just expired in the refresh/request race.
|
|
90
|
+
*
|
|
91
|
+
* REQUEST-side ONLY: it never returns a Response and never buffers — so it cannot
|
|
92
|
+
* re-introduce the issue-135 streaming regression that an `onResponse` hook would (the
|
|
93
|
+
* NON-goal this issue pins). Other hosts pass straight through; refresh failures inside
|
|
94
|
+
* `ensureFresh` are swallowed (logging must never break egress).
|
|
95
|
+
*/
|
|
96
|
+
export function makeLazyRefreshHook(substitutionHosts, ensureFresh, log) {
|
|
97
|
+
return async (request) => {
|
|
98
|
+
try {
|
|
99
|
+
const host = new URL(request.url).hostname;
|
|
100
|
+
const onSubstitutionHost = substitutionHosts.some((h) => host === h || host.endsWith(`.${h}`));
|
|
101
|
+
if (onSubstitutionHost)
|
|
102
|
+
await ensureFresh();
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
log.emit('warn', 'credential: lazy refresh hook error (egress continues)', { error: err.message });
|
|
106
|
+
}
|
|
107
|
+
// Pass-through: Gondolin substitutes the (now-fresh) secret value after this returns.
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Chain two optional onRequest hooks; a Response/Request short-circuit from the first wins. */
|
|
111
|
+
export function chainOnRequest(first, second) {
|
|
112
|
+
if (!first)
|
|
113
|
+
return second;
|
|
114
|
+
if (!second)
|
|
115
|
+
return first;
|
|
116
|
+
return async (request) => {
|
|
117
|
+
const r = await first(request);
|
|
118
|
+
if (r instanceof Response)
|
|
119
|
+
return r;
|
|
120
|
+
return second(r instanceof Request ? r : request);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build the Gondolin `createHttpHooks` result for one adapter's VM. Wraps the
|
|
125
|
+
* adapter's optional guard in the egress-audit hook (standing observability).
|
|
126
|
+
*
|
|
127
|
+
* FIX (issue 135): NEVER register an `onResponse` hook — Gondolin only streams when
|
|
128
|
+
* `!onResponse` (`canStream = Boolean(body) && !httpHooks.onResponse`); with one set
|
|
129
|
+
* it FULLY BUFFERS every response, starving the in-VM streaming SDK → stream timeout
|
|
130
|
+
* → silent retry → ECONNRESET loop. The old onResponse was a pure billing-tell.
|
|
131
|
+
*/
|
|
132
|
+
export function buildVmHttpHooks(input, log) {
|
|
133
|
+
const allowedHosts = [...input.allowedHosts];
|
|
134
|
+
const onRequest = makeEgressAuditHook(input.adapterId, allowedHosts, input.onRequest, log);
|
|
135
|
+
const options = {
|
|
136
|
+
allowedHosts,
|
|
137
|
+
secrets: {
|
|
138
|
+
[input.secretName]: {
|
|
139
|
+
hosts: [...input.substitutionHosts],
|
|
140
|
+
// Seeded via updateSecret (registry seeds BEFORE first exec); never forwarded empty on the happy path.
|
|
141
|
+
value: '',
|
|
142
|
+
placeholder: input.placeholder,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
onRequest,
|
|
146
|
+
};
|
|
147
|
+
return createHttpHooks(options);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=credential-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-hooks.js","sourceRoot":"","sources":["../../../../src/shell/interp/credential-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// FCIS rewrite — live per-VM SecretManager registry (the §4.3 fan-out + proactive
|
|
2
|
+
// expiresAt tick) + the periodic refresh ticker, for the host-only credential
|
|
3
|
+
// adapter (kind: adapter). Re-exported from interp/credential.ts so callers stay
|
|
4
|
+
// untouched.
|
|
5
|
+
//
|
|
6
|
+
// NodeNext ESM, .js extensions on relative imports. Imports src/types ONLY (plus
|
|
7
|
+
// the real Gondolin SDK) per the shell rule.
|
|
8
|
+
/**
|
|
9
|
+
* Owns the live per-VM SecretManagers + the cached latest value per adapter. The
|
|
10
|
+
* §4.3 fan-out contract: register seeds from the latest cached value before
|
|
11
|
+
* returning (so a VM created during a refresh never starts stale) and schedules a
|
|
12
|
+
* per-VM proactive `expiresAt` tick; pushToAll updates every live manager (dropping
|
|
13
|
+
* any torn down mid-push); refreshAdapter runs the host refresh, re-reads, and fans
|
|
14
|
+
* out. Ported faithfully from credential-secrets.CredentialSecretRegistry.
|
|
15
|
+
*/
|
|
16
|
+
/** Default proactive-refresh margin when the substrate doesn't override it (5 min). */
|
|
17
|
+
const DEFAULT_REFRESH_MARGIN_MS = 5 * 60 * 1000;
|
|
18
|
+
export class CredentialSecretRegistry {
|
|
19
|
+
entries = new Map();
|
|
20
|
+
cachedValue = new Map();
|
|
21
|
+
cacheSeq = new Map();
|
|
22
|
+
/** Latest known absolute expiry per adapter (null = unknown); drives the lazy refresh. */
|
|
23
|
+
cachedExpiresAt = new Map();
|
|
24
|
+
/** In-flight host refresh per adapter, so concurrent egress requests share one round-trip. */
|
|
25
|
+
inFlight = new Map();
|
|
26
|
+
seq = 0;
|
|
27
|
+
readToken;
|
|
28
|
+
refresh;
|
|
29
|
+
log;
|
|
30
|
+
now;
|
|
31
|
+
setTimer;
|
|
32
|
+
clearTimer;
|
|
33
|
+
refreshMarginMs;
|
|
34
|
+
constructor(opts) {
|
|
35
|
+
this.readToken = opts.readToken;
|
|
36
|
+
this.refresh = opts.refresh;
|
|
37
|
+
this.log = opts.log;
|
|
38
|
+
this.now = opts.now ?? (() => Date.now());
|
|
39
|
+
this.setTimer =
|
|
40
|
+
opts.setTimer ??
|
|
41
|
+
((cb, delayMs) => {
|
|
42
|
+
const t = setTimeout(cb, delayMs);
|
|
43
|
+
if (typeof t.unref === 'function')
|
|
44
|
+
t.unref();
|
|
45
|
+
return t;
|
|
46
|
+
});
|
|
47
|
+
this.clearTimer = opts.clearTimer ?? ((t) => clearTimeout(t));
|
|
48
|
+
this.refreshMarginMs = opts.refreshMarginMs ?? DEFAULT_REFRESH_MARGIN_MS;
|
|
49
|
+
}
|
|
50
|
+
async register(args) {
|
|
51
|
+
const key = `vm-${++this.seq}`;
|
|
52
|
+
const entry = { manager: args.manager, secretName: args.secretName, adapterId: args.adapterId, timer: null };
|
|
53
|
+
this.entries.set(key, entry);
|
|
54
|
+
const seqBefore = this.cacheSeq.get(args.adapterId) ?? 0;
|
|
55
|
+
const token = await this.safeReadToken(args.adapterId);
|
|
56
|
+
this.seedUnlessRotated(key, entry, args.adapterId, seqBefore, token);
|
|
57
|
+
if (token?.expiresAtMs != null)
|
|
58
|
+
this.scheduleProactive(key, entry, token.expiresAtMs);
|
|
59
|
+
return { key, deregister: () => this.deregister(key) };
|
|
60
|
+
}
|
|
61
|
+
deregister(key) {
|
|
62
|
+
const entry = this.entries.get(key);
|
|
63
|
+
if (!entry)
|
|
64
|
+
return;
|
|
65
|
+
if (entry.timer !== null) {
|
|
66
|
+
this.clearTimer(entry.timer);
|
|
67
|
+
entry.timer = null;
|
|
68
|
+
}
|
|
69
|
+
this.entries.delete(key);
|
|
70
|
+
}
|
|
71
|
+
size() {
|
|
72
|
+
return this.entries.size;
|
|
73
|
+
}
|
|
74
|
+
/** Push a fresh value to EVERY live manager for `adapterId` (cache first; drop the dead). */
|
|
75
|
+
pushToAll(adapterId, value) {
|
|
76
|
+
this.cachedValue.set(adapterId, value);
|
|
77
|
+
this.cacheSeq.set(adapterId, (this.cacheSeq.get(adapterId) ?? 0) + 1);
|
|
78
|
+
for (const [key, entry] of [...this.entries]) {
|
|
79
|
+
if (entry.adapterId !== adapterId)
|
|
80
|
+
continue;
|
|
81
|
+
this.applyToEntry(key, entry, value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Run a host refresh for `adapterId`, re-read, fan out, and reschedule each VM's tick.
|
|
86
|
+
* Returns true when the host refresh SPAWN succeeded and a token was re-read; false on a
|
|
87
|
+
* GENUINE auth failure — the refresh threw (e.g. a revoked/expired refresh token that
|
|
88
|
+
* `claude -p ok` can't rotate, needing operator re-login) or no token could be re-read.
|
|
89
|
+
* The in-session 401 recovery (issue 214) keys its re-prompt-vs-end decision on this
|
|
90
|
+
* boolean — it ends the attempt only when the refresh itself failed. Either way the
|
|
91
|
+
* re-read value is still fanned out (a peer may have rotated the file under the shared
|
|
92
|
+
* flock). Concurrent callers share one host round-trip.
|
|
93
|
+
*/
|
|
94
|
+
refreshAdapter(adapterId) {
|
|
95
|
+
const existing = this.inFlight.get(adapterId);
|
|
96
|
+
if (existing)
|
|
97
|
+
return existing;
|
|
98
|
+
const pending = this.runRefreshAndFanOut(adapterId).finally(() => {
|
|
99
|
+
if (this.inFlight.get(adapterId) === pending)
|
|
100
|
+
this.inFlight.delete(adapterId);
|
|
101
|
+
});
|
|
102
|
+
this.inFlight.set(adapterId, pending);
|
|
103
|
+
return pending;
|
|
104
|
+
}
|
|
105
|
+
async runRefreshAndFanOut(adapterId) {
|
|
106
|
+
let refreshOk = true;
|
|
107
|
+
try {
|
|
108
|
+
await this.refresh(adapterId);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
refreshOk = false;
|
|
112
|
+
this.log.emit('warn', 'credential: refresh failed', { adapter: adapterId, error: err.message });
|
|
113
|
+
// Fall through: re-read anyway — a peer may have rotated the file under the shared flock.
|
|
114
|
+
}
|
|
115
|
+
const token = await this.safeReadToken(adapterId);
|
|
116
|
+
if (token === null)
|
|
117
|
+
return false;
|
|
118
|
+
this.pushToAll(adapterId, token.accessToken);
|
|
119
|
+
this.cachedExpiresAt.set(adapterId, token.expiresAtMs ?? null);
|
|
120
|
+
if (token.expiresAtMs != null) {
|
|
121
|
+
for (const [key, entry] of [...this.entries]) {
|
|
122
|
+
if (entry.adapterId !== adapterId)
|
|
123
|
+
continue;
|
|
124
|
+
this.scheduleProactive(key, entry, token.expiresAtMs);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return refreshOk;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Egress request-side lazy refresh (issue 214): called from the per-VM `onRequest`
|
|
131
|
+
* hook BEFORE Gondolin substitutes the secret value. If the cached token's expiry is
|
|
132
|
+
* KNOWN and within the refresh margin, await a host refresh + fan-out so the request
|
|
133
|
+
* proceeds on the fresh token. Expiry-unknown adapters are left to the proactive tick /
|
|
134
|
+
* ticker (refreshing on every request would hammer the host). Never throws.
|
|
135
|
+
*/
|
|
136
|
+
async ensureFreshForRequest(adapterId) {
|
|
137
|
+
const expiresAt = this.cachedExpiresAt.get(adapterId);
|
|
138
|
+
if (expiresAt == null)
|
|
139
|
+
return; // unknown expiry → proactive tick owns it
|
|
140
|
+
if (expiresAt - this.now() > this.refreshMarginMs)
|
|
141
|
+
return; // still comfortably fresh
|
|
142
|
+
await this.refreshAdapter(adapterId);
|
|
143
|
+
}
|
|
144
|
+
seedUnlessRotated(key, entry, adapterId, seqBefore, token) {
|
|
145
|
+
if ((this.cacheSeq.get(adapterId) ?? 0) !== seqBefore)
|
|
146
|
+
return;
|
|
147
|
+
const seedValue = token?.accessToken ?? this.cachedValue.get(adapterId) ?? '';
|
|
148
|
+
if (token?.accessToken) {
|
|
149
|
+
this.cachedValue.set(adapterId, token.accessToken);
|
|
150
|
+
this.cachedExpiresAt.set(adapterId, token.expiresAtMs ?? null);
|
|
151
|
+
}
|
|
152
|
+
this.applyToEntry(key, entry, seedValue);
|
|
153
|
+
}
|
|
154
|
+
applyToEntry(key, entry, value) {
|
|
155
|
+
try {
|
|
156
|
+
entry.manager.updateSecret(entry.secretName, { value });
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
this.log.emit('warn', 'credential: dropping dead secret manager', { adapter: entry.adapterId, error: err.message });
|
|
160
|
+
this.deregister(key);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async safeReadToken(adapterId) {
|
|
164
|
+
try {
|
|
165
|
+
return await this.readToken(adapterId);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
this.log.emit('warn', 'credential: readToken failed', { adapter: adapterId, error: err.message });
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
scheduleProactive(key, entry, expiresAtMs) {
|
|
173
|
+
if (entry.timer !== null) {
|
|
174
|
+
this.clearTimer(entry.timer);
|
|
175
|
+
entry.timer = null;
|
|
176
|
+
}
|
|
177
|
+
const delay = Math.max(0, expiresAtMs - this.now() - this.refreshMarginMs);
|
|
178
|
+
entry.timer = this.setTimer(() => {
|
|
179
|
+
entry.timer = null;
|
|
180
|
+
void this.refreshAdapter(entry.adapterId);
|
|
181
|
+
}, delay);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/** Periodic host-side refresh so a long idle window doesn't strand the access token. */
|
|
185
|
+
export class CredentialTicker {
|
|
186
|
+
timer = null;
|
|
187
|
+
stopped = false;
|
|
188
|
+
intervalMs;
|
|
189
|
+
refreshAll;
|
|
190
|
+
log;
|
|
191
|
+
constructor(opts) {
|
|
192
|
+
this.intervalMs = opts.intervalMs;
|
|
193
|
+
this.refreshAll = opts.refreshAll;
|
|
194
|
+
this.log = opts.log;
|
|
195
|
+
}
|
|
196
|
+
start() {
|
|
197
|
+
if (this.timer || this.stopped)
|
|
198
|
+
return;
|
|
199
|
+
if (this.intervalMs <= 0) {
|
|
200
|
+
this.log.emit('info', 'credential ticker disabled (interval_ms <= 0)');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
this.timer = setInterval(() => void this.tick(), this.intervalMs);
|
|
204
|
+
if (typeof this.timer.unref === 'function')
|
|
205
|
+
this.timer.unref();
|
|
206
|
+
this.log.emit('info', 'credential ticker started', { interval_ms: this.intervalMs });
|
|
207
|
+
}
|
|
208
|
+
stop() {
|
|
209
|
+
this.stopped = true;
|
|
210
|
+
if (this.timer) {
|
|
211
|
+
clearInterval(this.timer);
|
|
212
|
+
this.timer = null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async tick() {
|
|
216
|
+
if (this.stopped)
|
|
217
|
+
return;
|
|
218
|
+
try {
|
|
219
|
+
await this.refreshAll();
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
this.log.emit('warn', 'credential ticker: refresh failed', { error: err.message });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=credential-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-registry.js","sourceRoot":"","sources":["../../../../src/shell/interp/credential-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// FCIS rewrite — host-only credential adapter (kind: adapter).
|
|
2
|
+
//
|
|
3
|
+
// Interprets the CredentialEffect family by implementing the {@link CredentialPort}
|
|
4
|
+
// from src/types/ports. The host stays the SOLE owner of the durable refresh token;
|
|
5
|
+
// the guest only ever sees a token-shaped placeholder that Gondolin substitutes at
|
|
6
|
+
// egress (TLS-MITM).
|
|
7
|
+
//
|
|
8
|
+
// This is the IMPURE half of the original src/agent/credential-secrets.ts +
|
|
9
|
+
// credential-extractors.ts + credential-ticker.ts. The PURE half (token/JWT
|
|
10
|
+
// extraction, placeholder-JWT assembly, host-identity extraction, allowlist union,
|
|
11
|
+
// codexUpstreamRoute decision) lives in src/core/credential and is wired in by the
|
|
12
|
+
// composition root, which passes the pure deciders into this adapter as injected
|
|
13
|
+
// function deps — so this file imports from src/types ONLY (plus the real Gondolin
|
|
14
|
+
// SDK + node builtins + its credential-* shell siblings), per the shell rule.
|
|
15
|
+
//
|
|
16
|
+
// The cohesive IO providers / hooks / registry live in sibling files that
|
|
17
|
+
// consumers import DIRECTLY (no barrel re-export here):
|
|
18
|
+
// - credential-defaults.ts: default paths, readJsonFile, flock, refreshers
|
|
19
|
+
// - credential-hooks.ts: egress audit, codex route, builder
|
|
20
|
+
// - credential-registry.ts: the per-VM SecretManager registry + the refresh ticker
|
|
21
|
+
//
|
|
22
|
+
// NodeNext ESM, .js extensions on relative imports. Keep THIN — decisions live in core.
|
|
23
|
+
import { defaultClaudeCredentialsPath, defaultCodexCredentialsPath, defaultClaudeIdentityPath, defaultLockPath, defaultFlockAcquire, defaultClaudeRefresher, defaultCodexRefresher, readJsonFile, } from './credential-defaults.js';
|
|
24
|
+
function resolvePaths(opts) {
|
|
25
|
+
return {
|
|
26
|
+
claudeCredsPath: opts.claudeCredentialsPath ?? defaultClaudeCredentialsPath(),
|
|
27
|
+
codexCredsPath: opts.codexCredentialsPath ?? defaultCodexCredentialsPath(),
|
|
28
|
+
claudeIdentityPath: opts.claudeIdentityPath ?? defaultClaudeIdentityPath(),
|
|
29
|
+
codexIdentityPath: opts.codexIdentityPath ?? defaultCodexCredentialsPath(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function resolveProviders(opts) {
|
|
33
|
+
return {
|
|
34
|
+
env: opts.env ?? process.env,
|
|
35
|
+
lockTimeoutMs: opts.lockAcquireTimeoutMs ?? 90_000,
|
|
36
|
+
acquireLock: opts.lockAcquire ?? defaultFlockAcquire(opts.lockPath ?? defaultLockPath()),
|
|
37
|
+
claudeRefresher: opts.claudeRefresher ?? defaultClaudeRefresher(),
|
|
38
|
+
codexRefresher: opts.codexRefresher ?? defaultCodexRefresher(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function resolveConfig(opts) {
|
|
42
|
+
return { ...resolvePaths(opts), ...resolveProviders(opts) };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The host-only CredentialPort over real files + flock + refresher spawns. Probe
|
|
46
|
+
* does the file READ here, then hands the parsed JSON to the injected PURE
|
|
47
|
+
* extractor — keeping every decision in core.
|
|
48
|
+
*/
|
|
49
|
+
export class GondolinCredentialAdapter {
|
|
50
|
+
acquireLock;
|
|
51
|
+
pure;
|
|
52
|
+
log;
|
|
53
|
+
cfg;
|
|
54
|
+
constructor(opts) {
|
|
55
|
+
this.pure = opts.pure;
|
|
56
|
+
this.log = opts.log;
|
|
57
|
+
this.cfg = resolveConfig(opts);
|
|
58
|
+
this.acquireLock = this.cfg.acquireLock;
|
|
59
|
+
}
|
|
60
|
+
async probe(adapter) {
|
|
61
|
+
switch (adapter) {
|
|
62
|
+
case 'claude':
|
|
63
|
+
return this.pure.extractClaudeToken(await readJsonFile(this.cfg.claudeCredsPath, this.log));
|
|
64
|
+
case 'codex':
|
|
65
|
+
return (this.pure.extractCodexToken(await readJsonFile(this.cfg.codexCredsPath, this.log)) ??
|
|
66
|
+
this.pure.codexEnvFallback(this.cfg.env));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async readClaudeIdentity() {
|
|
70
|
+
return this.pure.extractClaudeIdentity(await readJsonFile(this.cfg.claudeIdentityPath, this.log));
|
|
71
|
+
}
|
|
72
|
+
async readCodexIdentity() {
|
|
73
|
+
return this.pure.extractCodexMetadata(await readJsonFile(this.cfg.codexIdentityPath, this.log));
|
|
74
|
+
}
|
|
75
|
+
/** Refresh under the shared flock (fail-closed: never run the refresher unserialized). */
|
|
76
|
+
async refresh(adapter) {
|
|
77
|
+
await this.underLock(() => this.runRefresh(adapter));
|
|
78
|
+
}
|
|
79
|
+
async runRefresh(adapter) {
|
|
80
|
+
if (adapter === 'claude')
|
|
81
|
+
return this.cfg.claudeRefresher();
|
|
82
|
+
return this.cfg.codexRefresher();
|
|
83
|
+
}
|
|
84
|
+
async underLock(fn) {
|
|
85
|
+
let release = null;
|
|
86
|
+
try {
|
|
87
|
+
release = await this.acquireLock(this.cfg.lockTimeoutMs);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
// Fail closed: never run the refresher unserialized (would race a peer on the
|
|
91
|
+
// same creds file). The caller re-reads the cache and picks up the peer's rotation.
|
|
92
|
+
this.log.emit('warn', 'credential: lock acquire failed; skipping refresh', { error: err.message });
|
|
93
|
+
throw new Error('credential: refresh lock acquire timeout');
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
await fn();
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await release().catch((err) => this.log.emit('warn', 'credential: lock release error', { error: err.message }));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../../../../src/shell/interp/credential.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,oFAAoF;AACpF,oFAAoF;AACpF,mFAAmF;AACnF,qBAAqB;AACrB,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,mFAAmF;AACnF,mFAAmF;AACnF,iFAAiF;AACjF,mFAAmF;AACnF,8EAA8E;AAC9E,EAAE;AACF,0EAA0E;AAC1E,wDAAwD;AACxD,6EAA6E;AAC7E,iEAAiE;AACjE,qFAAqF;AACrF,EAAE;AACF,wFAAwF;AAexF,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,yBAAyB,EACzB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAiBlC,SAAS,YAAY,CAAC,IAAsC;IAG1D,OAAO;QACL,eAAe,EAAE,IAAI,CAAC,qBAAqB,IAAI,4BAA4B,EAAE;QAC7E,cAAc,EAAE,IAAI,CAAC,oBAAoB,IAAI,2BAA2B,EAAE;QAC1E,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,yBAAyB,EAAE;QAC1E,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,2BAA2B,EAAE;KAC3E,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAsC;IAG9D,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;QAC5B,aAAa,EAAE,IAAI,CAAC,oBAAoB,IAAI,MAAM;QAClD,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,mBAAmB,CAAC,IAAI,CAAC,QAAQ,IAAI,eAAe,EAAE,CAAC;QACxF,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,sBAAsB,EAAE;QACjE,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,qBAAqB,EAAE;KAC/D,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAsC;IAC3D,OAAO,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,yBAAyB;IAC3B,WAAW,CAAc;IAEjB,IAAI,CAAqB;IACzB,GAAG,CAAc;IACjB,GAAG,CAAiB;IAErC,YAAY,IAAsC;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9F,KAAK,OAAO;gBACV,OAAO,CACL,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;oBAClF,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CACzC,CAAC;QACN,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpG,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,0FAA0F;IAC1F,KAAK,CAAC,OAAO,CAAC,OAAqB;QACjC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,OAAqB;QAC5C,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,EAAuB;QAC7C,IAAI,OAAO,GAAiC,IAAI,CAAC;QACjD,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,8EAA8E;YAC9E,oFAAoF;YACpF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,mDAAmD,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9G,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,EAAE,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,gCAAgC,EAAE,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC7H,CAAC;IACH,CAAC;CACF"}
|