@jr2/orchestrator 0.3.0 → 0.5.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/README.md +20 -2
- package/bin/server.ts +7 -4
- package/console/canvas.ts +27 -14
- package/console/components/app.ts +12 -1
- package/console/components/fleet.ts +52 -6
- package/console/components/machine-pane.ts +128 -2
- package/console/components/nav.ts +1 -1
- package/console/components/schema-form.ts +12 -4
- package/console/json-field.ts +23 -0
- package/console/main.ts +122 -39
- package/console/store.ts +321 -21
- package/console/style.css +111 -0
- package/docs/agents-block.md +5 -0
- package/docs/concepts/agents-and-turns.md +442 -0
- package/docs/concepts/architecture.md +230 -0
- package/docs/concepts/charts.md +143 -0
- package/docs/concepts/composition.md +357 -0
- package/docs/concepts/converge.md +254 -0
- package/docs/concepts/durable-runs.md +189 -0
- package/docs/concepts/effects.md +603 -0
- package/docs/concepts/gates.md +208 -0
- package/docs/concepts/machines-and-workflows.md +289 -0
- package/docs/concepts/pools-and-sources.md +230 -0
- package/docs/concepts/secrets-and-trust.md +222 -0
- package/docs/concepts/the-menu.md +378 -0
- package/docs/concepts/workspaces.md +678 -0
- package/docs/get-started/a-model-decides.md +563 -0
- package/docs/get-started/an-agent-in-a-sandbox.md +381 -0
- package/docs/get-started/connect-a-model.md +248 -0
- package/docs/get-started/create-an-instance.md +194 -0
- package/docs/get-started/have-your-assistant-write-a-machine.md +922 -0
- package/docs/get-started/install.md +126 -0
- package/docs/guides/add-tools-to-the-sandbox.md +295 -0
- package/docs/guides/answer-a-gate.md +304 -0
- package/docs/guides/bind-open-parts.md +223 -0
- package/docs/guides/cancel-a-run.md +146 -0
- package/docs/guides/clean-up.md +206 -0
- package/docs/guides/fix-a-failed-converge.md +361 -0
- package/docs/guides/give-the-cluster-git-credentials.md +222 -0
- package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
- package/docs/guides/let-an-agent-write-a-chart.md +226 -0
- package/docs/guides/look-inside-a-sandbox.md +174 -0
- package/docs/guides/mirror-the-kit-images.md +176 -0
- package/docs/guides/move-from-kind-to-a-shared-cluster.md +302 -0
- package/docs/guides/open-the-console.md +91 -0
- package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
- package/docs/guides/push-and-sign-a-branch.md +486 -0
- package/docs/guides/run-a-chart-by-name.md +270 -0
- package/docs/guides/run-a-command-or-call-a-url.md +544 -0
- package/docs/guides/run-one-worker-per-item.md +321 -0
- package/docs/guides/set-an-agents-access-and-dials.md +375 -0
- package/docs/guides/size-a-workspace.md +204 -0
- package/docs/guides/start-a-run-from-a-run.md +237 -0
- package/docs/guides/start-a-run.md +207 -0
- package/docs/guides/upgrade-the-kit-version.md +240 -0
- package/docs/guides/use-a-hosted-provider.md +208 -0
- package/docs/guides/use-a-local-model.md +313 -0
- package/docs/guides/watch-a-run.md +326 -0
- package/docs/guides/write-a-workflow.md +318 -0
- package/docs/index.md +44 -0
- package/docs/llms.txt +216 -0
- package/docs/reference/authoring-surface/agent.md +128 -0
- package/docs/reference/authoring-surface/answer.md +140 -0
- package/docs/reference/authoring-surface/arg.md +60 -0
- package/docs/reference/authoring-surface/basic.md +62 -0
- package/docs/reference/authoring-surface/bearer.md +53 -0
- package/docs/reference/authoring-surface/chartschema.md +23 -0
- package/docs/reference/authoring-surface/chartschemafor.md +48 -0
- package/docs/reference/authoring-surface/command.md +191 -0
- package/docs/reference/authoring-surface/customize.md +64 -0
- package/docs/reference/authoring-surface/defineconfig.md +41 -0
- package/docs/reference/authoring-surface/defineevent.md +114 -0
- package/docs/reference/authoring-surface/dispatch.md +126 -0
- package/docs/reference/authoring-surface/fail.md +83 -0
- package/docs/reference/authoring-surface/file.md +122 -0
- package/docs/reference/authoring-surface/frompick.md +277 -0
- package/docs/reference/authoring-surface/http.md +159 -0
- package/docs/reference/authoring-surface/isfailure.md +58 -0
- package/docs/reference/authoring-surface/jr2setup.md +237 -0
- package/docs/reference/authoring-surface/open.md +74 -0
- package/docs/reference/authoring-surface/openbody.md +86 -0
- package/docs/reference/authoring-surface/paramsof.md +125 -0
- package/docs/reference/authoring-surface/pool.md +186 -0
- package/docs/reference/authoring-surface/push.md +112 -0
- package/docs/reference/authoring-surface/secret.md +118 -0
- package/docs/reference/authoring-surface/sentby.md +83 -0
- package/docs/reference/authoring-surface/source.md +51 -0
- package/docs/reference/authoring-surface/text.md +62 -0
- package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
- package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
- package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
- package/docs/reference/authoring-surface/type-agentslots.md +12 -0
- package/docs/reference/authoring-surface/type-answeraction.md +12 -0
- package/docs/reference/authoring-surface/type-arg.md +19 -0
- package/docs/reference/authoring-surface/type-argnames.md +12 -0
- package/docs/reference/authoring-surface/type-binding.md +62 -0
- package/docs/reference/authoring-surface/type-bindingof.md +12 -0
- package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
- package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
- package/docs/reference/authoring-surface/type-ceilings.md +41 -0
- package/docs/reference/authoring-surface/type-chainlink.md +19 -0
- package/docs/reference/authoring-surface/type-chartaction.md +46 -0
- package/docs/reference/authoring-surface/type-chartagent.md +28 -0
- package/docs/reference/authoring-surface/type-chartevent.md +20 -0
- package/docs/reference/authoring-surface/type-chartguard.md +20 -0
- package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
- package/docs/reference/authoring-surface/type-chartjson.md +14 -0
- package/docs/reference/authoring-surface/type-chartstate.md +46 -0
- package/docs/reference/authoring-surface/type-charttext.md +40 -0
- package/docs/reference/authoring-surface/type-charttransition.md +22 -0
- package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
- package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
- package/docs/reference/authoring-surface/type-childat.md +12 -0
- package/docs/reference/authoring-surface/type-childslots.md +12 -0
- package/docs/reference/authoring-surface/type-commandenv.md +15 -0
- package/docs/reference/authoring-surface/type-commandinput.md +19 -0
- package/docs/reference/authoring-surface/type-commandoptions.md +78 -0
- package/docs/reference/authoring-surface/type-commandoutput.md +104 -0
- package/docs/reference/authoring-surface/type-customize.md +109 -0
- package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
- package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
- package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
- package/docs/reference/authoring-surface/type-dispatchoutput.md +65 -0
- package/docs/reference/authoring-surface/type-duration.md +15 -0
- package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
- package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
- package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
- package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
- package/docs/reference/authoring-surface/type-eventdef.md +45 -0
- package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
- package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
- package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
- package/docs/reference/authoring-surface/type-failslot.md +14 -0
- package/docs/reference/authoring-surface/type-failure.md +19 -0
- package/docs/reference/authoring-surface/type-failureinput.md +20 -0
- package/docs/reference/authoring-surface/type-filebody.md +41 -0
- package/docs/reference/authoring-surface/type-frominput.md +14 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +58 -0
- package/docs/reference/authoring-surface/type-httpdefinition.md +101 -0
- package/docs/reference/authoring-surface/type-httpinput.md +12 -0
- package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
- package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
- package/docs/reference/authoring-surface/type-httpoutput.md +89 -0
- package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
- package/docs/reference/authoring-surface/type-jr2config.md +126 -0
- package/docs/reference/authoring-surface/type-lends.md +38 -0
- package/docs/reference/authoring-surface/type-logicat.md +12 -0
- package/docs/reference/authoring-surface/type-markedif.md +12 -0
- package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
- package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
- package/docs/reference/authoring-surface/type-noslotspec.md +26 -0
- package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +32 -0
- package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
- package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
- package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
- package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
- package/docs/reference/authoring-surface/type-opencommandinput.md +17 -0
- package/docs/reference/authoring-surface/type-openeffect.md +12 -0
- package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
- package/docs/reference/authoring-surface/type-openof.md +12 -0
- package/docs/reference/authoring-surface/type-opensecret.md +23 -0
- package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
- package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +31 -0
- package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +32 -0
- package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
- package/docs/reference/authoring-surface/type-poolspec.md +60 -0
- package/docs/reference/authoring-surface/type-pushinput.md +15 -0
- package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
- package/docs/reference/authoring-surface/type-pushoutput.md +124 -0
- package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
- package/docs/reference/authoring-surface/type-quantity.md +14 -0
- package/docs/reference/authoring-surface/type-reached.md +12 -0
- package/docs/reference/authoring-surface/type-reposlot.md +70 -0
- package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
- package/docs/reference/authoring-surface/type-sandboxoptions.md +77 -0
- package/docs/reference/authoring-surface/type-secret.md +25 -0
- package/docs/reference/authoring-surface/type-sender.md +19 -0
- package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
- package/docs/reference/authoring-surface/type-size.md +85 -0
- package/docs/reference/authoring-surface/type-slothandles.md +32 -0
- package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
- package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
- package/docs/reference/authoring-surface/type-syncstate.md +12 -0
- package/docs/reference/authoring-surface/type-text.md +19 -0
- package/docs/reference/authoring-surface/type-textpart.md +24 -0
- package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
- package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
- package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
- package/docs/reference/authoring-surface/type-unknown.md +21 -0
- package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
- package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
- package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
- package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
- package/docs/reference/authoring-surface/type-workspaced.md +94 -0
- package/docs/reference/authoring-surface/type-workspacehandles.md +23 -0
- package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
- package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
- package/docs/reference/authoring-surface/type-workspaceoptions.md +39 -0
- package/docs/reference/authoring-surface/type-workspacespec.md +37 -0
- package/docs/reference/authoring-surface/workspace.md +259 -0
- package/docs/reference/authoring-surface.md +197 -0
- package/docs/reference/cli.md +433 -0
- package/docs/reference/config.md +756 -0
- package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +113 -0
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +110 -0
- package/docs/reference/decisions/0004-worktree-provisioning-model.md +124 -0
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +230 -0
- package/docs/reference/decisions/0006-agent-control-surface.md +47 -0
- package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
- package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
- package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
- package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
- package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
- package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +157 -0
- package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
- package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +265 -0
- package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +124 -0
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +69 -0
- package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
- package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +275 -0
- package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +100 -0
- package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
- package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +176 -0
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +439 -0
- package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
- package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
- package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +237 -0
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +89 -0
- package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
- package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
- package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +190 -0
- package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
- package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +127 -0
- package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
- package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
- package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
- package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
- package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
- package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
- package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
- package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
- package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
- package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
- package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
- package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
- package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
- package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
- package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +227 -0
- package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +81 -0
- package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +111 -0
- package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
- package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
- package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
- package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +106 -0
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +384 -0
- package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
- package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +212 -0
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +83 -0
- package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
- package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +550 -0
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +430 -0
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +464 -0
- package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
- package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +323 -0
- package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
- package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
- package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
- package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
- package/docs/reference/decisions.md +83 -0
- package/docs/reference/glossary.md +648 -0
- package/docs/reference/http-api.md +1348 -0
- package/docs/reference/machines.md +190 -0
- package/docs/reference/mechanism-events.md +72 -0
- package/docs/why.md +206 -0
- package/package.json +6 -4
- package/src/actor.ts +976 -61
- package/src/agent.ts +114 -38
- package/src/ambient.ts +4 -1
- package/src/assembly-checks.ts +347 -0
- package/src/assembly-tar.ts +494 -0
- package/src/assembly.ts +721 -0
- package/src/cause.ts +234 -0
- package/src/chart.ts +2182 -0
- package/src/charts.ts +748 -0
- package/src/config.ts +520 -162
- package/src/content-hash.ts +105 -0
- package/src/custodian.lua +6 -5
- package/src/custodian.ts +143 -39
- package/src/customize.ts +388 -55
- package/src/dispatch-effect.ts +945 -0
- package/src/door-compat.ts +217 -0
- package/src/durability.ts +11 -4
- package/src/effect-checks.ts +557 -0
- package/src/effect.ts +1202 -0
- package/src/effector-wire.ts +674 -0
- package/src/fail.ts +209 -0
- package/src/fingerprint.ts +4 -3
- package/src/gate.ts +8 -0
- package/src/git-clone.ts +65 -0
- package/src/git-push.ts +336 -0
- package/src/harness-client.ts +764 -48
- package/src/held-secrets.ts +82 -26
- package/src/holds.ts +156 -0
- package/src/http-effect.ts +1423 -0
- package/src/http.ts +916 -113
- package/src/images.ts +47 -21
- package/src/index.ts +62 -43
- package/src/instance.ts +505 -59
- package/src/internal.ts +84 -0
- package/src/kube-client.ts +333 -0
- package/src/machine-doc.ts +106 -6
- package/src/mechanism-routes.ts +168 -0
- package/src/model-keys.generated.ts +53 -0
- package/src/model-keys.ts +18 -58
- package/src/mount-digest.ts +53 -0
- package/src/names.ts +66 -8
- package/src/notices.ts +141 -0
- package/src/open-body.ts +1580 -0
- package/src/open-effect.ts +217 -0
- package/src/open.ts +59 -6
- package/src/parts.ts +709 -41
- package/src/party.ts +534 -0
- package/src/pick.ts +761 -0
- package/src/pool.ts +248 -37
- package/src/registration.ts +382 -19
- package/src/repo-fetch.ts +60 -85
- package/src/repos.ts +65 -75
- package/src/rest.ts +133 -0
- package/src/run-host.ts +2383 -115
- package/src/run-output.ts +38 -0
- package/src/sandbox-effect.ts +1126 -0
- package/src/sandbox-effector.ts +111 -0
- package/src/sandbox-kube.ts +1721 -0
- package/src/sandbox-watch.ts +260 -0
- package/src/secret-placement.ts +529 -0
- package/src/server.ts +284 -84
- package/src/setup.ts +819 -117
- package/src/size.ts +454 -0
- package/src/snapshot-store.ts +115 -20
- package/src/stub-harness.ts +49 -16
- package/src/sync-client.ts +54 -0
- package/src/timers.ts +191 -0
- package/src/tokens.ts +35 -4
- package/src/vocabulary.ts +135 -15
- package/src/wire.ts +238 -10
- package/src/workspace.ts +1195 -338
- package/src/sandbox-kubectl.ts +0 -1108
package/src/registration.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// The internal registration table (ADR-0011): one structure behind both delivery dialects.
|
|
2
|
-
// An Agent slot and `gate` register `address → { accepted event defs, deliver closure, meta
|
|
3
|
-
// the
|
|
4
|
-
//
|
|
2
|
+
// An Agent slot and `gate` register `address → { accepted event defs, deliver closure, meta,
|
|
3
|
+
// sender }` — the sender written on every event it delivers (ADR-0015); the two HTTP surfaces
|
|
4
|
+
// (`/agents/:iid/*` for the Agent's Harness, `/runs/:id/gates/*` for humans and webhooks) are
|
|
5
|
+
// adapters over it — lookup, schema validation, delivery, discovery, and lifecycle
|
|
5
6
|
// are implemented ONCE. The table is implementation structure, not vocabulary: workflows speak
|
|
6
7
|
// only `defineEvent` / `agent` / `gate`.
|
|
7
8
|
//
|
|
@@ -23,11 +24,21 @@
|
|
|
23
24
|
// `resolveAccepts` reads them off the invoking Machine below and a nested Machine's names are
|
|
24
25
|
// never the root's problem.
|
|
25
26
|
|
|
26
|
-
import
|
|
27
|
-
import type {
|
|
27
|
+
import { getStateNodes } from "xstate";
|
|
28
|
+
import type { ActorSystem, AnyActorRef, AnyEventObject, AnyMachineSnapshot, AnyStateMachine } from "xstate";
|
|
29
|
+
import { SENDER_KEY, type EventDef, type Sender } from "@jr2/agent-protocol";
|
|
28
30
|
import type { AgentAdmission } from "./actor.ts";
|
|
31
|
+
import type { EffectMarker, EffectRow } from "./effect.ts";
|
|
32
|
+
import type { EffectorPlacement, EffectorTarget } from "./http-effect.ts";
|
|
33
|
+
import type { NoticeScope, TakenNotices } from "./notices.ts";
|
|
34
|
+
import type { AnswerSeat } from "./pick.ts";
|
|
35
|
+
import type { Notice, PickAnswer } from "./wire.ts";
|
|
29
36
|
import type { SandboxPort } from "./workspace.ts";
|
|
30
37
|
import { invokingMachine, vocabularyOf } from "./vocabulary.ts";
|
|
38
|
+
import type { ChartText } from "./chart.ts";
|
|
39
|
+
import { notTaken, senderText, takesNow, type NotTakenWriting } from "./party.ts";
|
|
40
|
+
import { restOf } from "./rest.ts";
|
|
41
|
+
import type { RunStatus } from "./run-host.ts";
|
|
31
42
|
|
|
32
43
|
/** xstate doesn't export its internal AnyActorSystem; this matches what actors receive. */
|
|
33
44
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -45,8 +56,17 @@ export type Registration = {
|
|
|
45
56
|
kind: "gate" | "agent";
|
|
46
57
|
/** The caller-facing id within its dialect (the gate id, or the agent's instance id). */
|
|
47
58
|
id: string;
|
|
48
|
-
/** Accepted events, name→def — the validation scope AND the discovery listing.
|
|
59
|
+
/** Accepted events, name→def — the validation scope AND the discovery listing. For an Agent,
|
|
60
|
+
* the invoking state's derived set: what its Allowed picks are narrowed from (ADR-0029). */
|
|
49
61
|
defs: Map<string, EventDef>;
|
|
62
|
+
/**
|
|
63
|
+
* An Agent's MENU (ADR-0029), in its fixed order: the union of the derived sets of every state
|
|
64
|
+
* that invokes an Agent of this name, and the tools block the Harness presents — byte-stable for
|
|
65
|
+
* the conversation, so it never breaks the provider's prompt cache. A superset of {@link defs};
|
|
66
|
+
* a pick on it that {@link defs} lacks is refused at delivery, naming the Allowed picks. Absent
|
|
67
|
+
* on gates, and on an Agent registered with no Menu, which serves its `defs` as the Menu.
|
|
68
|
+
*/
|
|
69
|
+
menu?: Map<string, EventDef>;
|
|
50
70
|
/** Serializable caller/integration context (PR URL, title …) — rides the discovery listing. */
|
|
51
71
|
meta?: Record<string, unknown>;
|
|
52
72
|
/**
|
|
@@ -64,6 +84,9 @@ export type Registration = {
|
|
|
64
84
|
sandbox?: string;
|
|
65
85
|
/** Close over the invoking state's `sendBack`; delivery lands where the actor was invoked. */
|
|
66
86
|
deliver: (event: DeliveredEvent) => void;
|
|
87
|
+
/** An Agent's: the Harness read this surface (`GET /agents/:iid/surface`), so it has the Turn in
|
|
88
|
+
* hand and prompts it. Until then the Turn may end with no model ever asked (ADR-0026). */
|
|
89
|
+
served?: () => void;
|
|
67
90
|
/**
|
|
68
91
|
* The Machine that invoked this actor — `self._parent`, captured at registration. The menu was
|
|
69
92
|
* derived from THIS machine's transitions (ADR-0015), so it is the only snapshot whose guards
|
|
@@ -71,6 +94,22 @@ export type Registration = {
|
|
|
71
94
|
* that have no parent to name, which is why every read of it fails open.
|
|
72
95
|
*/
|
|
73
96
|
invoker?: AnyActorRef;
|
|
97
|
+
/**
|
|
98
|
+
* Who this registration delivers as (ADR-0015): an Agent by its slot, a Gate by its invoke id.
|
|
99
|
+
* The table writes it on every event it delivers (`event.sender`), never taken from the caller.
|
|
100
|
+
* Absent on a registration no party made (a bare unit-test entry): its events carry none.
|
|
101
|
+
*/
|
|
102
|
+
sender?: Sender;
|
|
103
|
+
/** The invoke id of the actor that registered: what finds its state — its seat — in the
|
|
104
|
+
* Machine, for the party questions (`party.ts`). */
|
|
105
|
+
invokeId?: string;
|
|
106
|
+
/**
|
|
107
|
+
* An Agent's: the continued conversation ({@link continuedIid}) this Turn is part of — set only
|
|
108
|
+
* when the Turn continues one (`continue: true`). A pick whose route leaves the Agent's state is
|
|
109
|
+
* answered by a notice to it (ADR-0024); a fresh Turn's conversation is never heard again, so its
|
|
110
|
+
* answer has nowhere to go.
|
|
111
|
+
*/
|
|
112
|
+
conversation?: string;
|
|
74
113
|
};
|
|
75
114
|
|
|
76
115
|
/**
|
|
@@ -98,6 +137,41 @@ export function wouldMove(invoker: AnyActorRef | undefined, event: AnyEventObjec
|
|
|
98
137
|
}
|
|
99
138
|
}
|
|
100
139
|
|
|
140
|
+
/**
|
|
141
|
+
* The states this exact event's transitions name as targets, by id — empty for a pick with no
|
|
142
|
+
* target. Read before the send and checked after it with `leftAgain`: what tells a pick that entered
|
|
143
|
+
* a state and left it again inside its own send (an `always` back to where it was) from one that
|
|
144
|
+
* stayed where it went or went nowhere (ADR-0024). Fails CLOSED: a read that cannot be made reads
|
|
145
|
+
* as no target, the plain receipt.
|
|
146
|
+
*/
|
|
147
|
+
export function targetsOf(invoker: AnyActorRef | undefined, event: AnyEventObject): string[] {
|
|
148
|
+
if (!invoker) return [];
|
|
149
|
+
try {
|
|
150
|
+
const snapshot = invoker.getSnapshot() as AnyMachineSnapshot;
|
|
151
|
+
return (snapshot.machine as AnyStateMachine)
|
|
152
|
+
.getTransitionData(snapshot, event)
|
|
153
|
+
.flatMap((t) => (t.target ?? []).map((node) => node.id));
|
|
154
|
+
} catch {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Is some state of `targets` no longer active — entered by the send and left again inside it? A
|
|
161
|
+
* target to the state the pick was taken in (`drafting: { on: { note: "drafting" } }`) is still
|
|
162
|
+
* active, so it is not. Fails CLOSED: false, the plain receipt.
|
|
163
|
+
*/
|
|
164
|
+
export function leftAgain(invoker: AnyActorRef | undefined, targets: readonly string[]): boolean {
|
|
165
|
+
if (!invoker || targets.length === 0) return false;
|
|
166
|
+
try {
|
|
167
|
+
const snapshot = invoker.getSnapshot() as AnyMachineSnapshot;
|
|
168
|
+
const active = new Set(getStateNodes(snapshot.machine.root, snapshot.value).map((node) => node.id));
|
|
169
|
+
return targets.some((id) => !active.has(id));
|
|
170
|
+
} catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
101
175
|
/**
|
|
102
176
|
* COULD this event move the invoking Machine, judged before the Agent has picked its arguments?
|
|
103
177
|
* What the surface build can ask (ADR-0029) — there is no payload yet, so a guard reading one
|
|
@@ -138,10 +212,82 @@ export function mayMove(invoker: AnyActorRef | undefined, type: string): boolean
|
|
|
138
212
|
return readPayload;
|
|
139
213
|
}
|
|
140
214
|
|
|
215
|
+
/** Would the run take `type` from this registration now, payload-blind? Asked AS its sender
|
|
216
|
+
* ({@link takesNow}); a registration with no seat to ask from (a plain `setup()` actor tree, a bare
|
|
217
|
+
* test entry) falls back to {@link mayMove}. */
|
|
218
|
+
function takenNow(reg: Pick<Registration, "invoker" | "sender" | "invokeId">, type: string): boolean {
|
|
219
|
+
return takesNow(reg, type) ?? mayMove(reg.invoker, type);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* An Agent's Allowed picks now (ADR-0029): the invoking state's derived set, narrowed to what the
|
|
224
|
+
* invoking Machine would take from this Agent ({@link takenNow}), in Menu order — so the list reads
|
|
225
|
+
* in the order the tools block does. The ONE reading of the list: the surface, every receipt, the
|
|
226
|
+
* nudge and the wake all ask here, so no two of them can disagree about what the Turn may pick
|
|
227
|
+
* (ADR-0016).
|
|
228
|
+
*
|
|
229
|
+
* EMPTY while the Agent's state is not at Rest (rest.ts, ADR-0024): something below it runs, or a
|
|
230
|
+
* timer holds, and every pick is refused until it is back at Rest — so the Rest rule and the
|
|
231
|
+
* payload-blind selection give one list, and a Turn that starts busy is not asked into a refusal.
|
|
232
|
+
*/
|
|
233
|
+
export function allowedPicks(reg: Pick<Registration, "defs" | "menu" | "invoker" | "sender" | "invokeId">): string[] {
|
|
234
|
+
if (restOf(reg) === "busy") return [];
|
|
235
|
+
const ordered = new Set([...(reg.menu ?? reg.defs).keys()].filter((name) => reg.defs.has(name)));
|
|
236
|
+
for (const name of reg.defs.keys()) ordered.add(name);
|
|
237
|
+
return [...ordered].filter((name) => takenNow(reg, name));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** A Gate's `acceptsNow` (ADR-0011): its accepted set, narrowed the same way as an Agent's Allowed
|
|
241
|
+
* picks — the names the run would take from this Gate now. */
|
|
242
|
+
export function acceptsNow(reg: Pick<Registration, "defs" | "invoker" | "sender" | "invokeId">): string[] {
|
|
243
|
+
return [...reg.defs.keys()].filter((name) => takenNow(reg, name));
|
|
244
|
+
}
|
|
245
|
+
|
|
141
246
|
/** Delivery target absent (unknown address, settled run, exited state) — the one catch point. */
|
|
142
247
|
export class UnknownAddressError extends Error {}
|
|
143
|
-
/** Delivery body rejected (unaccepted name, or payload failing the named schema).
|
|
144
|
-
|
|
248
|
+
/** Delivery body rejected (unaccepted name, or payload failing the named schema). An Agent's
|
|
249
|
+
* refusal carries its Allowed picks, read after the refusal (ADR-0029), so the Harness can say
|
|
250
|
+
* what the Turn may pick instead. */
|
|
251
|
+
export class EventValidationError extends Error {
|
|
252
|
+
allowed?: string[];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* A pick that arrived while the Agent's state is not at Rest (ADR-0024): refused, `finish` included,
|
|
257
|
+
* and nothing is delivered — xstate would take it, and a pick its state handles would exit the child
|
|
258
|
+
* state and stop the work running there. `outstanding` names this Turn's pick still out, when there
|
|
259
|
+
* is one; without it, the state is busy with work the Turn did not pick (it started busy).
|
|
260
|
+
*/
|
|
261
|
+
export class OutstandingError extends Error {
|
|
262
|
+
readonly outstanding?: string;
|
|
263
|
+
constructor(message: string, outstanding?: string) {
|
|
264
|
+
super(message);
|
|
265
|
+
this.outstanding = outstanding;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Refuse a caller's body that carries the sender (ADR-0013, ADR-0015): only the Orchestrator writes
|
|
270
|
+
* it, from the registration, so neither the Agent's wire nor the gates route takes it. */
|
|
271
|
+
export function refuseSenderField(payload: unknown): void {
|
|
272
|
+
if (payload && typeof payload === "object" && SENDER_KEY in payload) {
|
|
273
|
+
throw new EventValidationError(
|
|
274
|
+
`\`${SENDER_KEY}\` is written by the Orchestrator on every delivered event; a caller cannot send it`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* The run would not take this event from this sender (ADR-0015, ADR-0029): xstate's selection holds
|
|
281
|
+
* a writing that is another party's, or — at a Gate — nothing would move. Refused BEFORE the Machine
|
|
282
|
+
* sees it. `writings` names the other party's writings, empty when nothing would move.
|
|
283
|
+
*/
|
|
284
|
+
export class NotTakenError extends Error {
|
|
285
|
+
readonly writings: readonly NotTakenWriting[];
|
|
286
|
+
constructor(message: string, writings: readonly NotTakenWriting[] = []) {
|
|
287
|
+
super(message);
|
|
288
|
+
this.writings = writings;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
145
291
|
|
|
146
292
|
/**
|
|
147
293
|
* The actor path below the run's root: every id from the root's children down to `ref` itself,
|
|
@@ -164,7 +310,7 @@ export function actorPath(ref: AnyActorRef): string[] {
|
|
|
164
310
|
* instances (two Pool children, whose ids are the items') can never meet.
|
|
165
311
|
*
|
|
166
312
|
* One derivation, two readers, so they cannot drift: `mintIid` builds every iid on it (a fresh
|
|
167
|
-
* Turn adds a random suffix, a burned conversation's successor its epoch), and the Agent
|
|
313
|
+
* Turn adds a random suffix, a burned conversation's successor its epoch), and the Agent's Actor
|
|
168
314
|
* names the conversation it burns with it.
|
|
169
315
|
*/
|
|
170
316
|
export function continuedIid(machine: AnyActorRef | undefined, runId: string, agentName: string): string {
|
|
@@ -184,6 +330,9 @@ export function agentAddress(instanceId: string): string {
|
|
|
184
330
|
|
|
185
331
|
export class RegistrationTable {
|
|
186
332
|
private readonly byAddress = new Map<string, Registration>();
|
|
333
|
+
/** The same registrations by run, so a run's are read without a scan of every run's: the run host
|
|
334
|
+
* reads them on every microstep of the run (`cause.ts`). */
|
|
335
|
+
private readonly ofRun = new Map<string, Set<Registration>>();
|
|
187
336
|
|
|
188
337
|
/** Register a live surface; returns its disposer (actors call it from their stop cleanup). */
|
|
189
338
|
register(reg: Registration): () => void {
|
|
@@ -193,10 +342,16 @@ export class RegistrationTable {
|
|
|
193
342
|
);
|
|
194
343
|
}
|
|
195
344
|
this.byAddress.set(reg.address, reg);
|
|
345
|
+
const ofRun = this.ofRun.get(reg.runId) ?? new Set<Registration>();
|
|
346
|
+
ofRun.add(reg);
|
|
347
|
+
this.ofRun.set(reg.runId, ofRun);
|
|
196
348
|
return () => {
|
|
197
349
|
// Dispose only our own entry — a re-registration under the same address must not be
|
|
198
350
|
// clobbered by a stale disposer running late (dev reload, restore races).
|
|
199
351
|
if (this.byAddress.get(reg.address) === reg) this.byAddress.delete(reg.address);
|
|
352
|
+
const runRegs = this.ofRun.get(reg.runId);
|
|
353
|
+
runRegs?.delete(reg);
|
|
354
|
+
if (runRegs?.size === 0) this.ofRun.delete(reg.runId);
|
|
200
355
|
};
|
|
201
356
|
}
|
|
202
357
|
|
|
@@ -204,20 +359,24 @@ export class RegistrationTable {
|
|
|
204
359
|
return this.byAddress.get(address);
|
|
205
360
|
}
|
|
206
361
|
|
|
207
|
-
/** All live registrations for one run — the `GET /runs/:id`
|
|
362
|
+
/** All live registrations for one run, in the order they registered — the `GET /runs/:id`
|
|
363
|
+
* discovery listing. */
|
|
208
364
|
byRun(runId: string): Registration[] {
|
|
209
|
-
return [...this.
|
|
365
|
+
return [...(this.ofRun.get(runId) ?? [])];
|
|
210
366
|
}
|
|
211
367
|
|
|
212
368
|
/**
|
|
213
369
|
* Validate and deliver one event to an address: the shared behavior both dialect adapters
|
|
214
370
|
* call. Unknown address / unaccepted name / bad payload throw typed errors the adapters map
|
|
215
371
|
* to their wire (404 / 400, MCP tool errors). The payload is parsed by the named def's
|
|
216
|
-
* schema, so what lands in the Machine is exactly the validated shape
|
|
372
|
+
* schema, so what lands in the Machine is exactly the validated shape — plus the registration's
|
|
373
|
+
* sender, written here and nowhere else (ADR-0015). A delivery that would run another party's
|
|
374
|
+
* writing throws {@link NotTakenError}.
|
|
217
375
|
*/
|
|
218
376
|
deliver(address: string, type: string, payload: unknown): void {
|
|
219
377
|
const reg = this.byAddress.get(address);
|
|
220
378
|
if (!reg) throw new UnknownAddressError(`no live registration at "${address}"`);
|
|
379
|
+
refuseSenderField(payload);
|
|
221
380
|
const def = reg.defs.get(type);
|
|
222
381
|
if (!def) {
|
|
223
382
|
throw new EventValidationError(
|
|
@@ -228,14 +387,80 @@ export class RegistrationTable {
|
|
|
228
387
|
if (!parsed.success) {
|
|
229
388
|
throw new EventValidationError(`invalid "${type}" payload: ${parsed.error.message}`);
|
|
230
389
|
}
|
|
231
|
-
|
|
390
|
+
// `type` after the payload: a payload never names the event the Machine receives (ADR-0011).
|
|
391
|
+
const event: DeliveredEvent = {
|
|
392
|
+
...parsed.data,
|
|
393
|
+
type: def.name,
|
|
394
|
+
...(reg.sender ? { [SENDER_KEY]: reg.sender } : {}),
|
|
395
|
+
};
|
|
396
|
+
// Exact, with the real payload (ADR-0015): a delivery whose selection holds a writing that is
|
|
397
|
+
// not this sender's never reaches the Machine.
|
|
398
|
+
const others = reg.sender ? notTaken(reg, event) : [];
|
|
399
|
+
if (others.length) {
|
|
400
|
+
const owned = (w: NotTakenWriting): string =>
|
|
401
|
+
w.owners.length ? `, which is ${w.owners.map(senderText).join(" and ")}'s` : "";
|
|
402
|
+
throw new NotTakenError(
|
|
403
|
+
`"${type}" from ${senderText(reg.sender!)} would run the writing on ` +
|
|
404
|
+
`${others.map((w) => `"${w.state}"${owned(w)}`).join(" and ")}`,
|
|
405
|
+
others,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
reg.deliver(event);
|
|
232
409
|
}
|
|
233
410
|
}
|
|
234
411
|
|
|
412
|
+
/**
|
|
413
|
+
* Which run dispatched a run (ADR-0071): the caller's run id, the slot of its `dispatch` Effect, and
|
|
414
|
+
* that Effect's ledger row id, which is the idempotency key — a start that carries a key some run
|
|
415
|
+
* already carries answers that run. `depth` is the dispatched run's depth in the chain, one below
|
|
416
|
+
* its caller, stated by the caller and recorded as sent: one meaning on the wire, on the binding
|
|
417
|
+
* and on the row. `instance` is set for a foreign caller, whose Orchestrator this one cannot
|
|
418
|
+
* verify: opaque text, never resolved.
|
|
419
|
+
*/
|
|
420
|
+
export type DispatchedBy = { run: string; slot: string; effect: string; depth: number; instance?: string };
|
|
421
|
+
|
|
422
|
+
/** The header a foreign `dispatch` carries its {@link DispatchedBy} in, as JSON (ADR-0071): out of
|
|
423
|
+
* band, so the callee's door reserves no body field for it. */
|
|
424
|
+
export const DISPATCHED_BY_HEADER = "jr2-dispatched-by";
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* A dispatch's start as the run host answers it in-process (ADR-0071): the run, and whether the key
|
|
428
|
+
* found one that already existed; or the door's refusal, with the status `POST /workflows/:name/runs`
|
|
429
|
+
* would answer — 400 input the door refuses, 404 a name the current Assembly lacks, 409 a named
|
|
430
|
+
* Chart that cannot run now, 422 a Chart the door refuses — and its report. A refusal is the
|
|
431
|
+
* Effect's output, never thrown.
|
|
432
|
+
*/
|
|
433
|
+
export type DispatchStart =
|
|
434
|
+
| { ok: true; runId: string; existing: boolean }
|
|
435
|
+
| { ok: false; status: 400 | 404 | 409 | 422; report: string[] };
|
|
436
|
+
|
|
235
437
|
/** What a callback actor needs from its host: run identity, the table, and the host's ports. */
|
|
236
438
|
export type RunBinding = {
|
|
237
439
|
runId: string;
|
|
238
440
|
workflow: string;
|
|
441
|
+
/** The name this run's Orchestrator gives itself at another Orchestrator's door (ADR-0071): the
|
|
442
|
+
* `instance` of a foreign dispatch's `dispatchedBy` — stable across its runs and restarts, and not
|
|
443
|
+
* secret, since the callee serves it on its open band. Deployed, its namespace. Never an Instance
|
|
444
|
+
* ID, which names an Agent's conversation and stays behind the token. Absent on a bare unit-test
|
|
445
|
+
* binding and an undeployed Orchestrator. */
|
|
446
|
+
orchestratorName?: string;
|
|
447
|
+
/** The run's depth in a chain of dispatches (ADR-0071): 0 for a run nothing dispatched. Absent
|
|
448
|
+
* on a bare unit-test binding, which reads 0. */
|
|
449
|
+
depth?: number;
|
|
450
|
+
/**
|
|
451
|
+
* The in-process half of a `dispatch` Effect (ADR-0071): the run host, reached directly, with no
|
|
452
|
+
* wire and no token — the Orchestrator is the single writer of runs. `start` answers a refusal as
|
|
453
|
+
* {@link DispatchStart}, never by throwing; `settled` resolves with the run's status once it is no
|
|
454
|
+
* longer live — at once for a run already settled, and across a restore in either order — and
|
|
455
|
+
* rejects when `signal` aborts. Absent outside a RunHost: a dispatch with no target faults.
|
|
456
|
+
*/
|
|
457
|
+
dispatch?: {
|
|
458
|
+
start(workflow: string, input: Record<string, unknown>, by: DispatchedBy): Promise<DispatchStart>;
|
|
459
|
+
settled(runId: string, signal: AbortSignal): Promise<RunStatus>;
|
|
460
|
+
};
|
|
461
|
+
/** The hash of the Assembly the run holds (ADR-0069): the one it started under, through
|
|
462
|
+
* restarts. Absent for a run no Assembly started. */
|
|
463
|
+
assembly?: string;
|
|
239
464
|
table: RegistrationTable;
|
|
240
465
|
/** The host's Sandbox backend, when it has a cluster (`workspace()` resolves it here —
|
|
241
466
|
* one cluster per orchestrator instance, so it is host infrastructure like the table). */
|
|
@@ -248,18 +473,30 @@ export type RunBinding = {
|
|
|
248
473
|
instanceHarness?: string;
|
|
249
474
|
/**
|
|
250
475
|
* The Harness bearer for a placement (ADR-0058): `harnessToken(signingKey, placement)`, closed
|
|
251
|
-
* over the key by the host. The Agent
|
|
476
|
+
* over the key by the host. The Agent's Actor asks it for the pod its Turn resolved to; the echo
|
|
252
477
|
* attach asks it for the Workspace's. Absent (bare unit-test bindings, the stub path), no bearer
|
|
253
478
|
* is sent — which only a Harness that checks nothing accepts.
|
|
254
479
|
*/
|
|
255
480
|
harnessBearer?: (placement: string) => string;
|
|
481
|
+
/**
|
|
482
|
+
* Where an Effector placement is, and the key its wire is signed with (ADR-0068): the Instance
|
|
483
|
+
* Effector's Service and `effectorKey(signingKey, "instance")`, closed over by the host. An http
|
|
484
|
+
* Effect asks it; absent (bare unit-test bindings, an instance with no Effector), it faults.
|
|
485
|
+
*/
|
|
486
|
+
effector?: (placement: EffectorPlacement) => EffectorTarget | undefined;
|
|
256
487
|
/**
|
|
257
488
|
* Record an Agent invocation's durable admission in the host ledger (ADR-0016): persisted
|
|
258
489
|
* beside the snapshot in the same RunBlob save, keyed by iid (globally unique, so the map is
|
|
259
490
|
* flat). Optional so a bare unit-test binding can omit it — then admissions simply are not
|
|
260
491
|
* durable.
|
|
261
492
|
*/
|
|
262
|
-
recordAdmission?: (instanceId: string, admission: AgentAdmission) => void;
|
|
493
|
+
recordAdmission?: (instanceId: string, admission: AgentAdmission, delivered?: readonly string[]) => void;
|
|
494
|
+
/**
|
|
495
|
+
* The admission ledger's READ half (ADR-0016): the last admission ledgered under this iid. A
|
|
496
|
+
* continued Turn asks it whether its conversation was ever admitted — only then can the Harness
|
|
497
|
+
* have lost it (ADR-0062).
|
|
498
|
+
*/
|
|
499
|
+
admissionOf?: (instanceId: string) => AgentAdmission | undefined;
|
|
263
500
|
/**
|
|
264
501
|
* The epoch ledger's READ half (ADR-0057): the current epoch of a continued conversation,
|
|
265
502
|
* keyed by its base Instance ID ({@link continuedIid}). The input mapper reads it AT MINT TIME,
|
|
@@ -273,9 +510,48 @@ export type RunBinding = {
|
|
|
273
510
|
* it ended, and the next `continue` on that Agent mints `<conversation>/<epoch>` — a virgin
|
|
274
511
|
* conversation. No fault leaves a conversation worth continuing (ADR-0035): a runaway either
|
|
275
512
|
* had its reroll or holds a poisoned context, and infra and no-signal mean the Harness that
|
|
276
|
-
* held it is unreachable. Persisted beside the snapshot with the admission ledger.
|
|
513
|
+
* held it is unreachable. Persisted beside the snapshot with the admission ledger. `reason` is
|
|
514
|
+
* the fault's: the host raises it as the next `continue`'s `conversation-new` notice (ADR-0062).
|
|
515
|
+
*/
|
|
516
|
+
bumpEpoch?: (conversation: string, reason: string) => void;
|
|
517
|
+
/**
|
|
518
|
+
* The notices' write half (ADR-0062): keep a notice for the next admission in scope — `to` is a
|
|
519
|
+
* continued conversation's base id or a Sandbox name, as the notice's `scope` says. Persisted at
|
|
520
|
+
* the write, like the ledgers. `source` names the event, so one event raised twice is one notice;
|
|
521
|
+
* `older` names earlier events this one tells the same as, marked raised with it (`NoticeLedger`).
|
|
522
|
+
* A burned conversation's notice is raised by `bumpEpoch` itself, in the same save.
|
|
523
|
+
*/
|
|
524
|
+
raiseNotice?: (notice: Notice, to: string, source?: string, older?: readonly string[]) => void;
|
|
525
|
+
/** Put back a notice an admission carried that no model heard, WITH its source (`NoticeLedger.restore`):
|
|
526
|
+
* a raise would drop it, its source being seen. Persisted at the write. */
|
|
527
|
+
restoreNotice?: (notice: Notice, to: string, source?: string) => void;
|
|
528
|
+
/** Reserve the pending notices in one admission's scope. They are delivered by the
|
|
529
|
+
* `recordAdmission` that ledgers it (its `delivered` ids), or released if the admission fails. */
|
|
530
|
+
takeNotices?: (scope: NoticeScope) => TakenNotices;
|
|
531
|
+
releaseNotices?: (ids: readonly string[]) => void;
|
|
532
|
+
/**
|
|
533
|
+
* The pick the Turn now at this address has outstanding, or answered and not yet read (ADR-0024):
|
|
534
|
+
* what the Agent's Actor asks when its Harness restarted under a Turn — a Turn whose pick is still
|
|
535
|
+
* out, or whose answer never reached the model, is cut, not faulted (ADR-0031). Read after the host
|
|
536
|
+
* settles its holds, so `answered` is the Rest rule's verdict now. An earlier Turn's pick on the
|
|
537
|
+
* same continued address is not this Turn's: its answer went as a notice. Absent outside a RunHost.
|
|
538
|
+
*/
|
|
539
|
+
outstandingOf?: (instanceId: string) => OutstandingPick | undefined;
|
|
540
|
+
/** The held answer reached the model by another road — a re-admission's notice — so the poll's
|
|
541
|
+
* copy is spent (ADR-0031). */
|
|
542
|
+
heldAnswerDelivered?: (instanceId: string) => void;
|
|
543
|
+
/**
|
|
544
|
+
* Did this Turn's own pick end it (ADR-0024)? Asked by the Agent's Actor as its invocation stops,
|
|
545
|
+
* before its registration goes, so its sweep can say so (`cause: "pick"`) and the Harness settles
|
|
546
|
+
* the Submission `ended`. True exactly when the transition that stopped the invocation came from
|
|
547
|
+
* the Turn's own pick, by the four rules of ADR-0024 (`cause.ts`): the pick in its own send; the
|
|
548
|
+
* work below the Agent's state while the pick is out; a send of an actor that takes a relay from
|
|
549
|
+
* the pick (rule 3); and a timer armed while its Machine took such a relay (rule 4) — so a timer
|
|
550
|
+
* that the pick's route armed gives true. False for every other end — a timer armed before the
|
|
551
|
+
* pick, an outside event, another party's event, the run's CANCEL, a fault. Absent outside a RunHost: the
|
|
552
|
+
* sweep then says no cause.
|
|
277
553
|
*/
|
|
278
|
-
|
|
554
|
+
turnEndedByPick?: (instanceId: string) => boolean;
|
|
279
555
|
/**
|
|
280
556
|
* Surface absorbed-retry telemetry on the run feed (ADR-0016): attempts are observable, but
|
|
281
557
|
* as `{ child, attempt }` — state-key-class data, never iids (ADR-0014's line holds on the
|
|
@@ -287,7 +563,7 @@ export type RunBinding = {
|
|
|
287
563
|
* settlement pick, so the run's narrative can name what a Turn hosted elsewhere decided.
|
|
288
564
|
* Host-supplied; absent (bare unit-test bindings), turns leave no markers.
|
|
289
565
|
*/
|
|
290
|
-
marker?: (event:
|
|
566
|
+
marker?: (event: RunMarker) => void;
|
|
291
567
|
/**
|
|
292
568
|
* Attach the run-narrative echo to a Workspace's Harness (ADR-0023): the host replays the
|
|
293
569
|
* run's feed-so-far to `endpoint` — the Harness in `placement`'s pod, pushed with that
|
|
@@ -306,13 +582,70 @@ export type RunBinding = {
|
|
|
306
582
|
*/
|
|
307
583
|
hostStopping?: boolean;
|
|
308
584
|
/**
|
|
309
|
-
*
|
|
585
|
+
* The Sandbox names that a live Workspace of this run holds now, a Workspace in `placing` too
|
|
586
|
+
* (ADR-0064, ADR-0073). A delete that runs after a stop leaves these alone: a parent that invokes
|
|
587
|
+
* the same Machine again gives its new Workspace the same invoke id, and so the same name. Absent
|
|
588
|
+
* outside a RunHost: no name is held.
|
|
589
|
+
*/
|
|
590
|
+
heldSandboxes?: () => ReadonlySet<string>;
|
|
591
|
+
/**
|
|
592
|
+
* Every reply since the pick that `machine`'s Agent has outstanding, or is delivering now, oldest
|
|
593
|
+
* first (ADR-0024) — what an `answer` action reads as its `chain` (ADR-0067). `seat` is the place
|
|
594
|
+
* the action runs from: an Agent's state, and then only that Agent's pick counts; or `null`, a
|
|
595
|
+
* transition below no Agent's state, and then `event` — the event whose transition runs the action
|
|
596
|
+
* — names the Agent: the sender of a pick, or the Agent whose pick started the child whose done
|
|
597
|
+
* or error event it is. Undefined when no such pick is being answered, when the event names an
|
|
598
|
+
* Agent with none, or when the event names no Agent outside a pick's own send while two Agents'
|
|
599
|
+
* states are active or more than one pick is outstanding: then the action cannot tell whose
|
|
600
|
+
* answer it shapes, and sets none.
|
|
601
|
+
*/
|
|
602
|
+
chainOf?: (machine: AnyActorRef, seat: AnswerSeat, event?: AnyEventObject) => PickAnswer[] | undefined;
|
|
603
|
+
/** Set what that pick's answer is (ADR-0067): it replaces the default, and the last call wins.
|
|
604
|
+
* Kept with the hold, so a restore answers the same. */
|
|
605
|
+
setAnswer?: (machine: AnyActorRef, seat: AnswerSeat, value: unknown, event?: AnyEventObject) => void;
|
|
606
|
+
/**
|
|
607
|
+
* The Effect ledger's READ half (ADR-0067): one Effect's row, by its id — what a restored Effect
|
|
608
|
+
* reads to deliver its output, re-attach, or settle `unknown`, and never to run twice.
|
|
609
|
+
*/
|
|
610
|
+
effectRow?: (effectId: string) => EffectRow | undefined;
|
|
611
|
+
/** Every row of the run's Effect ledger, by Effect id — what a push reads its pairs from (each
|
|
612
|
+
* push of its Workspace and Repo Slot that published, ADR-0067). */
|
|
613
|
+
effectRows?: () => Readonly<Record<string, EffectRow>>;
|
|
614
|
+
/**
|
|
615
|
+
* The Effect ledger's WRITE half (ADR-0067), in the same RunBlob as the snapshot. `"now"` (the
|
|
616
|
+
* default) saves AT THE WRITE — so an intent row is on disk, with the snapshot that holds its
|
|
617
|
+
* Effect, before the call leaves. `"with-transition"` is for a row written INSIDE a transition (an
|
|
618
|
+
* abort, D1): it is kept in memory for the save that carries that transition — a save now would
|
|
619
|
+
* read the Machine before its route — and saved after the transition if nothing else saves it.
|
|
620
|
+
* Optional: a bare binding keeps no ledger, and nothing it runs is durable.
|
|
621
|
+
*/
|
|
622
|
+
recordEffect?: (effectId: string, row: EffectRow, save?: "now" | "with-transition") => void;
|
|
623
|
+
/**
|
|
624
|
+
* iid → the abort still in flight for it (ADR-0024). The Agent's Actor fills this on the way out and
|
|
310
625
|
* waits on it before admitting, so an abort can never overtake the next turn on the same
|
|
311
626
|
* instance — flue QUEUES per instance, and an abort that lost that race would settle the new
|
|
312
627
|
* submission before it ran. Created on demand: the ordering must hold for ANY binding, not only
|
|
313
628
|
* one the host remembered to equip.
|
|
314
629
|
*/
|
|
315
630
|
pendingAborts?: Map<string, Promise<void>>;
|
|
631
|
+
/**
|
|
632
|
+
* A named Chart of the run's own Workflow, by its short name (ADR-0070, D-C): what an Open body
|
|
633
|
+
* whose input is `{ chart: { name } }` binds. The host resolves it among the Charts of the
|
|
634
|
+
* wrapper that is the run's Workflow (`<wrapper>` of `<wrapper>/<name>`, or the Workflow itself),
|
|
635
|
+
* and only for a body that wrapper invokes itself. Absent outside a RunHost: no name resolves.
|
|
636
|
+
*/
|
|
637
|
+
chartNamed?: (name: string) => ChartText | undefined;
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
/** A conversation's latest outstanding pick, as the Agent's Actor reads it (ADR-0024). `answered`: the Machine
|
|
641
|
+
* came back to Rest, or left the Agent's state (`turnComplete`); `fetched`: the answer reached the
|
|
642
|
+
* model. */
|
|
643
|
+
export type OutstandingPick = {
|
|
644
|
+
pick: string;
|
|
645
|
+
answered: boolean;
|
|
646
|
+
turnComplete: boolean;
|
|
647
|
+
answer?: PickAnswer;
|
|
648
|
+
fetched: boolean;
|
|
316
649
|
};
|
|
317
650
|
|
|
318
651
|
/** One absorbed-retry attempt (a no-signal nudge), as the run feed carries it. */
|
|
@@ -330,6 +663,30 @@ export type TurnMarker =
|
|
|
330
663
|
| { kind: "admission"; agent: string; endpoint: string; prompt: string }
|
|
331
664
|
| { kind: "pick"; agent: string; endpoint: string; event: string; payload?: Record<string, unknown> };
|
|
332
665
|
|
|
666
|
+
/**
|
|
667
|
+
* ADR-0064's two feed lines per wait for capacity: a Workspace's Sandbox has no node — `placing`,
|
|
668
|
+
* with the reason (`on`) and the scheduler's or the quota's own words — and then it has one —
|
|
669
|
+
* `placed`, `after` milliseconds since `since`. A changed reason adds no line: `RunStatus.waiting`
|
|
670
|
+
* carries the latest. `child` is the Workspace's actor path below the run root, its ids joined by
|
|
671
|
+
* `/` (`""` for a run whose root IS the Workspace). Instance-token class like the Turn markers: the
|
|
672
|
+
* message can name nodes and taints, so these ride the per-run feed alone.
|
|
673
|
+
*/
|
|
674
|
+
export type PlacingMarker =
|
|
675
|
+
| { kind: "placing"; child: string; on: "node" | "quota"; message: string; since: string }
|
|
676
|
+
| { kind: "placed"; child: string; since: string; after: number };
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* A child below an Agent's state failed while a pick of that Agent was outstanding (ADR-0024): the
|
|
680
|
+
* pick's answer carries no reply for it — the Agent is not told — so the operator reads it here: the
|
|
681
|
+
* Agent, its pick, the child (its slot, or its invoke id) and the error's message. Instance-token
|
|
682
|
+
* class like the Turn markers: an error message is mechanism text, as `fault` is.
|
|
683
|
+
*/
|
|
684
|
+
export type ChildErrorMarker = { kind: "child-error"; agent: string; pick: string; child: string; error: string };
|
|
685
|
+
|
|
686
|
+
/** Every marker a run's mechanism puts on its per-run feed — an Effect's lines among them
|
|
687
|
+
* (ADR-0067): its start, its stream, its output, its abort. */
|
|
688
|
+
export type RunMarker = TurnMarker | PlacingMarker | ChildErrorMarker | EffectMarker;
|
|
689
|
+
|
|
333
690
|
const bindings = new WeakMap<AnyActorSystem, RunBinding>();
|
|
334
691
|
|
|
335
692
|
/** Host-side: bind a run's actor system to its identity, before the actor starts. */
|
|
@@ -349,6 +706,12 @@ export function boundEpoch(system: AnyActorSystem, conversation: string): number
|
|
|
349
706
|
return bindings.get(system)?.epochOf?.(conversation) ?? 0;
|
|
350
707
|
}
|
|
351
708
|
|
|
709
|
+
/** The bound run, or undefined outside a jr2 host — the SOFT read an Effect uses: with no host it
|
|
710
|
+
* keeps no ledger and writes no feed, and still runs. */
|
|
711
|
+
export function boundRun(system: AnyActorSystem): RunBinding | undefined {
|
|
712
|
+
return bindings.get(system);
|
|
713
|
+
}
|
|
714
|
+
|
|
352
715
|
/** Actor-side: resolve the run this actor tree belongs to. Throws outside a jr2 host. */
|
|
353
716
|
export function runBindingOf(system: AnyActorSystem): RunBinding {
|
|
354
717
|
const binding = bindings.get(system);
|