@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/console/store.ts
CHANGED
|
@@ -24,6 +24,55 @@ export type ObservedRun = {
|
|
|
24
24
|
status: string;
|
|
25
25
|
value: unknown;
|
|
26
26
|
children: Array<Record<string, unknown>>;
|
|
27
|
+
/** The run binds at least one Chart (ADR-0070): its Machine is the Chart wrapper's with each bound
|
|
28
|
+
* Open body's Chart compiled in, served per run. Absent when it binds none. */
|
|
29
|
+
bound?: true;
|
|
30
|
+
/** The hashes of the Charts the run binds now, distinct and sorted. A run can bind a second Chart
|
|
31
|
+
* in its life, so these, with the run id, key its doc. Absent from an older Orchestrator. */
|
|
32
|
+
chartHashes?: string[];
|
|
33
|
+
/** The run that dispatched this one, the caller's slot, and this run's depth in the chain
|
|
34
|
+
* (ADR-0071). Routing, on the open band (ADR-0014): the page reads it off the observation it
|
|
35
|
+
* already holds, with no fetch and no token. `instance` is set for a foreign caller, opaque text.
|
|
36
|
+
* Absent for a run nobody dispatched, and from an Orchestrator older than ADR-0071. */
|
|
37
|
+
dispatchedBy?: DispatchedByView;
|
|
38
|
+
/** The runs this run's `dispatch` Effects started, oldest first, by slot (ADR-0071): the chain's
|
|
39
|
+
* other direction, the same routing on the same band. Absent when it started none. */
|
|
40
|
+
dispatched?: Array<{ slot: string; run: string }>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** {@link ObservedRun.dispatchedBy} — mirrors `RunObservation.dispatchedBy` in run-host.ts. The
|
|
44
|
+
* idempotency key is not on the open band: it names the caller's ledger. */
|
|
45
|
+
export type DispatchedByView = { run: string; slot: string; depth: number; instance?: string };
|
|
46
|
+
|
|
47
|
+
/** Where a Workflow came from (ADR-0070): a Machine or a Chart file in the Assembly, or a runtime
|
|
48
|
+
* Chart put on the Instance. */
|
|
49
|
+
export type WorkflowOrigin = "machine" | "file" | "runtime";
|
|
50
|
+
|
|
51
|
+
/** One entry of `GET /workflows` (ADR-0070) — mirrors `WorkflowListing` in run-host.ts. A Chart
|
|
52
|
+
* wrapper's named Charts are inside its entry, not beside it. */
|
|
53
|
+
export type WorkflowListing = {
|
|
54
|
+
name: string;
|
|
55
|
+
origin: WorkflowOrigin;
|
|
56
|
+
wrapper?: {
|
|
57
|
+
body: string;
|
|
58
|
+
oneShot: boolean;
|
|
59
|
+
charts: Array<{ name: string; origin: "file" | "runtime"; unrunnable?: string }>;
|
|
60
|
+
};
|
|
61
|
+
unrunnable?: string;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** One row of the fleet rail: a Workflow, or a named Chart indented under its Chart wrapper. */
|
|
65
|
+
export type FleetEntry = {
|
|
66
|
+
name: string;
|
|
67
|
+
origin: WorkflowOrigin;
|
|
68
|
+
/** 0 for a Workflow, 1 for a Chart under its wrapper. */
|
|
69
|
+
depth: 0 | 1;
|
|
70
|
+
/** A Chart wrapper's Open body slot, and whether its door takes a Chart one-shot. */
|
|
71
|
+
wrapper?: { body: string; oneShot: boolean };
|
|
72
|
+
unrunnable?: string;
|
|
73
|
+
/** A runtime Chart of the same name that this Chart file shadows (ADR-0070): one row per name,
|
|
74
|
+
* so the rail keys stay distinct; the shadowed Chart is unrunnable, and this says why. */
|
|
75
|
+
shadows?: { origin: WorkflowOrigin; unrunnable?: string };
|
|
27
76
|
};
|
|
28
77
|
|
|
29
78
|
/** One open gate as `GET /runs/:id` reports it — mirrors `GateView` in run-host.ts. */
|
|
@@ -34,6 +83,15 @@ export type GateCard = {
|
|
|
34
83
|
meta?: Record<string, unknown>;
|
|
35
84
|
};
|
|
36
85
|
|
|
86
|
+
/** One Workspace waiting for capacity as `GET /runs/:id` reports it (ADR-0064) — mirrors
|
|
87
|
+
* `RunWaiting` in run-host.ts. Guarded: `message` is the scheduler's or the quota's own words. */
|
|
88
|
+
export type WaitingLine = { child: string; on: "node" | "quota"; message: string; since: string };
|
|
89
|
+
|
|
90
|
+
/** One outstanding pick as `GET /runs/:id` reports it (ADR-0024) — mirrors `RunHeld` in
|
|
91
|
+
* run-host.ts. There is no default time bound on a held Turn: "held since" is how a human sees one.
|
|
92
|
+
* Guarded like the reason a Workspace waits: a pick names what an Agent did. */
|
|
93
|
+
export type HeldLine = { agent: string; pick: string; since: string };
|
|
94
|
+
|
|
37
95
|
/** The credential's state — never its value, which stays in sessionStorage (ADR-0032). */
|
|
38
96
|
export type TokenState = "none" | "checking" | "live" | "invalid";
|
|
39
97
|
|
|
@@ -45,7 +103,7 @@ export type Frame =
|
|
|
45
103
|
| { kind: "gone"; runId: string }
|
|
46
104
|
| { kind: "emit"; runId: string; type: string }
|
|
47
105
|
| { kind: "connection"; state: Store["connection"] }
|
|
48
|
-
| { kind: "workflows"; workflows: string
|
|
106
|
+
| { kind: "workflows"; workflows: ReadonlyArray<WorkflowListing | string> }
|
|
49
107
|
| { kind: "select"; workflow: string | null }
|
|
50
108
|
| { kind: "selectRun"; runId: string | null }
|
|
51
109
|
| { kind: "selectNode"; nodeId: string | null }
|
|
@@ -53,6 +111,8 @@ export type Frame =
|
|
|
53
111
|
| { kind: "toggleWorkflow"; workflow: string }
|
|
54
112
|
| { kind: "token"; state: TokenState }
|
|
55
113
|
| { kind: "gates"; runId: string; workflow: string; gates: GateCard[] }
|
|
114
|
+
| { kind: "waiting"; runId: string; workflow: string; waiting: WaitingLine[]; held?: HeldLine[] }
|
|
115
|
+
| { kind: "failure"; runId: string; reason: string | null }
|
|
56
116
|
| { kind: "inboxScope"; all: boolean }
|
|
57
117
|
| { kind: "startForm"; workflow: string | null };
|
|
58
118
|
|
|
@@ -66,7 +126,10 @@ export type Frame =
|
|
|
66
126
|
* `emits` newest-first, across the selected workflow's runs — each tagged with its run.
|
|
67
127
|
* `connection` the socket's state, owned by the page, never by a frame off the wire.
|
|
68
128
|
* `workflow` the selection the ADDRESS carries (`/workflows/:name`); null at `/`.
|
|
69
|
-
* `workflows`
|
|
129
|
+
* `workflows` every registered name (`GET /workflows`), Machines and named Charts alike — what the
|
|
130
|
+
* fleet polls and selects. A Chart's name is `<wrapper>/<name>` (ADR-0070).
|
|
131
|
+
* `listing` the same answer with its structure: each Workflow's origin, a Chart wrapper's Charts
|
|
132
|
+
* inside its entry — what the fleet rail draws ({@link fleetEntries}).
|
|
70
133
|
* `fleet` REST snapshots per workflow (`GET /workflows/:name/runs`), for the workflows that do
|
|
71
134
|
* NOT hold the feed. Never more than one EventSource — the rest of the fleet is polled.
|
|
72
135
|
* `expanded` which workflows the rail shows runs for (the reader's folding, plus auto-expand on
|
|
@@ -76,6 +139,14 @@ export type Frame =
|
|
|
76
139
|
* "invalid". Anything but "live" means observer mode.
|
|
77
140
|
* `gates` the gate inbox: runId -> { workflow, gates } from `GET /runs/:id` re-fetches. Guarded
|
|
78
141
|
* data (Instance band), so it cannot outlive the credential that read it.
|
|
142
|
+
* `waiting` why each run's Workspaces in `placing` wait (ADR-0064): runId -> { workflow, waiting },
|
|
143
|
+
* off the SAME `GET /runs/:id` re-fetch as `gates`, under the same rules — guarded, whole
|
|
144
|
+
* per run, gone with the credential. The open band sees `placing` lit and nothing more.
|
|
145
|
+
* `failures` the reason of each run this page knows that ended `failed` (ADR-0073): runId -> reason,
|
|
146
|
+
* off the SAME `GET /runs/:id` re-fetch, under the same rules — guarded (the open band
|
|
147
|
+
* sees the `failed` status and its color, never the output), gone with the credential.
|
|
148
|
+
* A failed run is a settled run, so `gone` keeps it; it goes with the run when the run
|
|
149
|
+
* leaves both `runs` and `settled`.
|
|
79
150
|
* `inboxAll` the widen control: false = the inbox follows the selection, true = every workflow.
|
|
80
151
|
* `startFormFor` which workflow's start-run form is open, if any.
|
|
81
152
|
* `selectedNodeId` the diagram node the reader clicked — an elk node id (scope + state id), one at
|
|
@@ -93,10 +164,13 @@ export type Store = {
|
|
|
93
164
|
connection: "connecting" | "live" | "retrying";
|
|
94
165
|
workflow: string | null;
|
|
95
166
|
workflows: string[];
|
|
167
|
+
listing: WorkflowListing[];
|
|
96
168
|
fleet: Map<string, ObservedRun[]>;
|
|
97
169
|
expanded: Set<string>;
|
|
98
170
|
token: TokenState;
|
|
99
171
|
gates: Map<string, { workflow: string; gates: GateCard[] }>;
|
|
172
|
+
waiting: Map<string, { workflow: string; waiting: WaitingLine[]; held: HeldLine[] }>;
|
|
173
|
+
failures: Map<string, string>;
|
|
100
174
|
inboxAll: boolean;
|
|
101
175
|
startFormFor: string | null;
|
|
102
176
|
};
|
|
@@ -119,10 +193,13 @@ export function emptyStore(): Store {
|
|
|
119
193
|
connection: "connecting",
|
|
120
194
|
workflow: null,
|
|
121
195
|
workflows: [],
|
|
196
|
+
listing: [],
|
|
122
197
|
fleet: new Map(),
|
|
123
198
|
expanded: new Set(),
|
|
124
199
|
token: "none",
|
|
125
200
|
gates: new Map(),
|
|
201
|
+
waiting: new Map(),
|
|
202
|
+
failures: new Map(),
|
|
126
203
|
inboxAll: false,
|
|
127
204
|
startFormFor: null,
|
|
128
205
|
};
|
|
@@ -132,16 +209,24 @@ export function emptyStore(): Store {
|
|
|
132
209
|
* that learns a new frame type does not break a page still running yesterday's script. */
|
|
133
210
|
export function applyFrame(store: Store, frame: Frame): Store {
|
|
134
211
|
switch (frame.kind) {
|
|
135
|
-
case "runs":
|
|
212
|
+
case "runs": {
|
|
136
213
|
// The server's whole truth about what is live. Runs that ended during a disconnect are simply
|
|
137
214
|
// ABSENT — no `gone` was delivered for them and none is needed; they were never ours to settle.
|
|
138
215
|
// The same wholeness settles the inbox: a selected-workflow run the frame does not mention can
|
|
139
|
-
// never be re-fetched again, so its card leaves with it.
|
|
216
|
+
// never be re-fetched again, so its card leaves with it. A failure stays while its run is live
|
|
217
|
+
// or settled here.
|
|
218
|
+
const runs = new Map(frame.runs.map((r): [string, ObservedRun] => [r.runId, r]));
|
|
219
|
+
const orphans = [...store.failures.keys()].filter((id) => !runs.has(id) && !store.settled.has(id));
|
|
220
|
+
let failures = store.failures;
|
|
221
|
+
for (const id of orphans) failures = mapWithout(failures, id);
|
|
140
222
|
return select({
|
|
141
223
|
...store,
|
|
142
|
-
runs
|
|
224
|
+
runs,
|
|
143
225
|
gates: dropAbsent(store.gates, store.workflow, new Set(frame.runs.map((r) => r.runId))),
|
|
226
|
+
waiting: dropAbsent(store.waiting, store.workflow, new Set(frame.runs.map((r) => r.runId))),
|
|
227
|
+
failures,
|
|
144
228
|
});
|
|
229
|
+
}
|
|
145
230
|
|
|
146
231
|
case "status":
|
|
147
232
|
return select({ ...store, runs: new Map(store.runs).set(frame.status.runId, frame.status) });
|
|
@@ -152,13 +237,19 @@ export function applyFrame(store: Store, frame: Frame): Store {
|
|
|
152
237
|
// a reconnect window, which is ordinary. Its inbox card goes either way: a gate exists exactly
|
|
153
238
|
// while its invoking state is entered (ADR-0011), and this run has no entered states left.
|
|
154
239
|
const gates = mapWithout(store.gates, frame.runId);
|
|
240
|
+
const waiting = mapWithout(store.waiting, frame.runId);
|
|
155
241
|
const departing = store.runs.get(frame.runId);
|
|
156
|
-
if (!departing) return store.gates === gates ? store : { ...store, gates };
|
|
242
|
+
if (!departing) return store.gates === gates && store.waiting === waiting ? store : { ...store, gates, waiting };
|
|
157
243
|
const runs = new Map(store.runs);
|
|
158
244
|
runs.delete(frame.runId);
|
|
159
245
|
const settled = new Map(store.settled).set(frame.runId, departing);
|
|
160
|
-
|
|
161
|
-
|
|
246
|
+
let failures = store.failures;
|
|
247
|
+
while (settled.size > SETTLED_CAP) {
|
|
248
|
+
const evicted = settled.keys().next().value!;
|
|
249
|
+
settled.delete(evicted);
|
|
250
|
+
failures = mapWithout(failures, evicted);
|
|
251
|
+
}
|
|
252
|
+
return select({ ...store, runs, settled, gates, waiting, failures });
|
|
162
253
|
}
|
|
163
254
|
|
|
164
255
|
case "emit":
|
|
@@ -167,8 +258,14 @@ export function applyFrame(store: Store, frame: Frame): Store {
|
|
|
167
258
|
case "connection":
|
|
168
259
|
return { ...store, connection: frame.state };
|
|
169
260
|
|
|
170
|
-
case "workflows":
|
|
171
|
-
|
|
261
|
+
case "workflows": {
|
|
262
|
+
// Replaced wholesale. An Orchestrator older than ADR-0070 answers bare names: each reads as
|
|
263
|
+
// a Machine, so the rail has one shape to draw.
|
|
264
|
+
const listing = frame.workflows.map(
|
|
265
|
+
(w): WorkflowListing => (typeof w === "string" ? { name: w, origin: "machine" } : w),
|
|
266
|
+
);
|
|
267
|
+
return { ...store, listing, workflows: fleetEntries(listing).map((e) => e.name) };
|
|
268
|
+
}
|
|
172
269
|
|
|
173
270
|
case "select": {
|
|
174
271
|
// The address moved. The feed's state belongs to the OLD selection — the new feed's opening
|
|
@@ -188,6 +285,8 @@ export function applyFrame(store: Store, frame: Frame): Store {
|
|
|
188
285
|
selectedRunId: null,
|
|
189
286
|
selectedNodeId: null,
|
|
190
287
|
connection: "connecting",
|
|
288
|
+
// Each failure belongs to a run of the old selection's `runs` or `settled`, which go.
|
|
289
|
+
failures: new Map(),
|
|
191
290
|
};
|
|
192
291
|
}
|
|
193
292
|
|
|
@@ -206,8 +305,9 @@ export function applyFrame(store: Store, frame: Frame): Store {
|
|
|
206
305
|
// so it settles that workflow's inbox cards the same way (a run the snapshot does not carry
|
|
207
306
|
// will never be re-fetched again).
|
|
208
307
|
const fleet = new Map(store.fleet).set(frame.workflow, frame.runs);
|
|
209
|
-
const
|
|
210
|
-
|
|
308
|
+
const present = new Set(frame.runs.map((r) => r.runId));
|
|
309
|
+
const gates = dropAbsent(store.gates, frame.workflow, present);
|
|
310
|
+
return { ...store, fleet, gates, waiting: dropAbsent(store.waiting, frame.workflow, present) };
|
|
211
311
|
}
|
|
212
312
|
|
|
213
313
|
case "toggleWorkflow": {
|
|
@@ -221,7 +321,7 @@ export function applyFrame(store: Store, frame: Frame): Store {
|
|
|
221
321
|
// "invalid" (the any-later-401 drop of ADR-0032) empties the inbox. "checking" keeps it — a
|
|
222
322
|
// re-validation of a token that turns out fine should not flash the inbox empty.
|
|
223
323
|
if (frame.state === "none" || frame.state === "invalid") {
|
|
224
|
-
return { ...store, token: frame.state, gates: new Map() };
|
|
324
|
+
return { ...store, token: frame.state, gates: new Map(), waiting: new Map(), failures: new Map() };
|
|
225
325
|
}
|
|
226
326
|
return { ...store, token: frame.state };
|
|
227
327
|
|
|
@@ -238,6 +338,38 @@ export function applyFrame(store: Store, frame: Frame): Store {
|
|
|
238
338
|
return { ...store, gates };
|
|
239
339
|
}
|
|
240
340
|
|
|
341
|
+
case "waiting": {
|
|
342
|
+
// The same guarded re-fetch's other half (ADR-0064), folded the same way: whole per run, and
|
|
343
|
+
// nothing folded without the credential that read it.
|
|
344
|
+
// The run's outstanding picks (ADR-0024) ride the same frame: one re-fetch, one fold.
|
|
345
|
+
if (store.token !== "live") return store;
|
|
346
|
+
const held = frame.held ?? [];
|
|
347
|
+
if (!frame.waiting.length && !held.length) {
|
|
348
|
+
const waiting = mapWithout(store.waiting, frame.runId);
|
|
349
|
+
return waiting === store.waiting ? store : { ...store, waiting };
|
|
350
|
+
}
|
|
351
|
+
const waiting = new Map(store.waiting).set(frame.runId, {
|
|
352
|
+
workflow: frame.workflow,
|
|
353
|
+
waiting: frame.waiting,
|
|
354
|
+
held,
|
|
355
|
+
});
|
|
356
|
+
return { ...store, waiting };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
case "failure": {
|
|
360
|
+
// The same guarded re-fetch's third half (ADR-0073): the reason of a run that ended `failed`.
|
|
361
|
+
// Nothing folded without the credential, and nothing for a run that the page does not hold:
|
|
362
|
+
// the re-fetch can come back after a `select` moved on. `null` says the run did not fail.
|
|
363
|
+
if (store.token !== "live") return store;
|
|
364
|
+
if (frame.reason === null) {
|
|
365
|
+
const failures = mapWithout(store.failures, frame.runId);
|
|
366
|
+
return failures === store.failures ? store : { ...store, failures };
|
|
367
|
+
}
|
|
368
|
+
if (!store.runs.has(frame.runId) && !store.settled.has(frame.runId)) return store;
|
|
369
|
+
if (store.failures.get(frame.runId) === frame.reason) return store;
|
|
370
|
+
return { ...store, failures: new Map(store.failures).set(frame.runId, frame.reason) };
|
|
371
|
+
}
|
|
372
|
+
|
|
241
373
|
case "inboxScope":
|
|
242
374
|
return { ...store, inboxAll: frame.all };
|
|
243
375
|
|
|
@@ -258,15 +390,20 @@ function mapWithout<K, V>(map: Map<K, V>, key: K): Map<K, V> {
|
|
|
258
390
|
return next;
|
|
259
391
|
}
|
|
260
392
|
|
|
261
|
-
/** Drop `workflow`'s
|
|
262
|
-
* never be re-fetched again (frames and snapshots are per-run triggers),
|
|
263
|
-
* be stale forever — this is the level-triggered idiom applied to the
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
393
|
+
/** Drop `workflow`'s guarded entries (inbox cards, waits) for runs a whole-set frame did not
|
|
394
|
+
* mention. Those runs will never be re-fetched again (frames and snapshots are per-run triggers),
|
|
395
|
+
* so an entry kept here would be stale forever — this is the level-triggered idiom applied to the
|
|
396
|
+
* guarded maps, not bookkeeping. */
|
|
397
|
+
function dropAbsent<V extends { workflow: string }>(
|
|
398
|
+
entries: Map<string, V>,
|
|
399
|
+
workflow: string | null,
|
|
400
|
+
present: Set<string>,
|
|
401
|
+
): Map<string, V> {
|
|
402
|
+
if (!workflow) return entries;
|
|
403
|
+
let next = entries;
|
|
404
|
+
for (const [runId, entry] of entries) {
|
|
268
405
|
if (entry.workflow !== workflow || present.has(runId)) continue;
|
|
269
|
-
if (next ===
|
|
406
|
+
if (next === entries) next = new Map(entries);
|
|
270
407
|
next.delete(runId);
|
|
271
408
|
}
|
|
272
409
|
return next;
|
|
@@ -310,6 +447,103 @@ export function fleetRuns(store: Store, workflow: string): Array<{ run: Observed
|
|
|
310
447
|
return (store.fleet.get(workflow) ?? []).map((run) => ({ run, settled: false }));
|
|
311
448
|
}
|
|
312
449
|
|
|
450
|
+
/**
|
|
451
|
+
* The fleet rail's rows (ADR-0070): each Workflow in the listing's order, a Chart wrapper's named
|
|
452
|
+
* Charts indented under it as `<wrapper>/<name>`. A Chart the listing also gives at the top level
|
|
453
|
+
* is drawn once, under its wrapper; one whose wrapper the listing does not give stays at the top.
|
|
454
|
+
*/
|
|
455
|
+
export function fleetEntries(listing: readonly WorkflowListing[]): FleetEntry[] {
|
|
456
|
+
const full = (wrapper: string, name: string): string => (name.includes("/") ? name : `${wrapper}/${name}`);
|
|
457
|
+
const nested = new Set<string>();
|
|
458
|
+
for (const w of listing) for (const c of w.wrapper?.charts ?? []) nested.add(full(w.name, c.name));
|
|
459
|
+
const rows: FleetEntry[] = [];
|
|
460
|
+
for (const w of listing) {
|
|
461
|
+
if (w.origin !== "machine" && nested.has(w.name)) continue;
|
|
462
|
+
rows.push({
|
|
463
|
+
name: w.name,
|
|
464
|
+
origin: w.origin,
|
|
465
|
+
depth: 0,
|
|
466
|
+
...(w.wrapper ? { wrapper: { body: w.wrapper.body, oneShot: w.wrapper.oneShot } } : {}),
|
|
467
|
+
...(w.unrunnable ? { unrunnable: w.unrunnable } : {}),
|
|
468
|
+
});
|
|
469
|
+
for (const c of w.wrapper?.charts ?? []) {
|
|
470
|
+
const name = full(w.name, c.name);
|
|
471
|
+
// A Chart file and a runtime Chart of one name: the listing gives both, the file wins
|
|
472
|
+
// (ADR-0070). One row per name, the shadowed Chart a note on it, so no two rows share a key.
|
|
473
|
+
const twin = rows.find((r) => r.depth === 1 && r.name === name);
|
|
474
|
+
if (twin) {
|
|
475
|
+
const fileFirst = twin.origin === "file" || c.origin !== "file";
|
|
476
|
+
const shadowed = fileFirst ? c : { origin: twin.origin, unrunnable: twin.unrunnable };
|
|
477
|
+
if (!fileFirst) {
|
|
478
|
+
twin.origin = c.origin;
|
|
479
|
+
if (c.unrunnable) twin.unrunnable = c.unrunnable;
|
|
480
|
+
else delete twin.unrunnable;
|
|
481
|
+
}
|
|
482
|
+
twin.shadows = { origin: shadowed.origin, ...(shadowed.unrunnable ? { unrunnable: shadowed.unrunnable } : {}) };
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
rows.push({
|
|
486
|
+
name,
|
|
487
|
+
origin: c.origin,
|
|
488
|
+
depth: 1,
|
|
489
|
+
...(c.unrunnable ? { unrunnable: c.unrunnable } : {}),
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return rows;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Which Machine doc the center pane draws (ADR-0070), as a cache key and the route that serves it.
|
|
498
|
+
* A run that binds a Chart draws its own Machine, the Chart compiled into the Open body, so its doc
|
|
499
|
+
* is per run id; every other selection draws the Workflow's Machine, shared by all its runs. The
|
|
500
|
+
* Workflow name rides the route as one encoded segment (`<wrapper>%2F<name>` for a named Chart).
|
|
501
|
+
*/
|
|
502
|
+
export function machineDocSource(
|
|
503
|
+
workflow: string,
|
|
504
|
+
run: Pick<ObservedRun, "runId" | "bound" | "chartHashes"> | null,
|
|
505
|
+
): { key: string; path: string } {
|
|
506
|
+
const base = `/workflows/${encodeURIComponent(workflow)}`;
|
|
507
|
+
if (run?.bound === true) {
|
|
508
|
+
// The run id and the Charts it binds now: a second Chart in the run's life is a new doc.
|
|
509
|
+
const charts = run.chartHashes?.length ? `:${run.chartHashes.join(",")}` : "";
|
|
510
|
+
return { key: `run:${run.runId}${charts}`, path: `${base}/runs/${encodeURIComponent(run.runId)}/machine` };
|
|
511
|
+
}
|
|
512
|
+
return { key: `workflow:${workflow}`, path: `${base}/machine` };
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** The fleet row's badge for a dispatched run (ADR-0071): `↳ <run8>`, the caller's run id cut as
|
|
516
|
+
* the row cuts its own. Null for a run nobody dispatched. */
|
|
517
|
+
export function dispatchBadge(run: ObservedRun): string | null {
|
|
518
|
+
const by = run.dispatchedBy;
|
|
519
|
+
return by ? `↳ ${by.run.slice(0, 8)}` : null;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/** The Machine pane's strip for a dispatched run (ADR-0071): `dispatched by <run8> · <slot> ·
|
|
523
|
+
* depth n`, and `· from Orchestrator <name>` when the caller is on another Orchestrator (its
|
|
524
|
+
* name as it sent it, never an Instance ID). Null for a run
|
|
525
|
+
* nobody dispatched. */
|
|
526
|
+
export function dispatchStrip(run: ObservedRun | null): string | null {
|
|
527
|
+
const by = run?.dispatchedBy;
|
|
528
|
+
if (!by) return null;
|
|
529
|
+
const from = by.instance ? ` · from Orchestrator ${by.instance}` : "";
|
|
530
|
+
return `dispatched by ${by.run.slice(0, 8)} · ${by.slot} · depth ${by.depth}${from}`;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/** The most runs the pane's `dispatched` strip names: a watcher dispatches on every pass. */
|
|
534
|
+
const DISPATCHED_SHOWN = 5;
|
|
535
|
+
|
|
536
|
+
/** The Machine pane's strip for a run that dispatched (ADR-0071): `dispatched <run8> (<slot>) · …`,
|
|
537
|
+
* newest last, the older ones counted. Null for a run that started none. */
|
|
538
|
+
export function dispatchedStrip(run: ObservedRun | null): string | null {
|
|
539
|
+
const all = run?.dispatched ?? [];
|
|
540
|
+
if (all.length === 0) return null;
|
|
541
|
+
const shown = all.slice(-DISPATCHED_SHOWN);
|
|
542
|
+
const older = all.length - shown.length;
|
|
543
|
+
const named = shown.map((d) => `${d.run.slice(0, 8)} (${d.slot})`).join(" · ");
|
|
544
|
+
return `dispatched ${older > 0 ? `${older} more · ` : ""}${named}`;
|
|
545
|
+
}
|
|
546
|
+
|
|
313
547
|
/** The inbox as the Attention tab draws it: every card, or the selection's slice. The inbox itself
|
|
314
548
|
* is GLOBAL (every workflow the fleet knows) — the filter is presentation, which is why it lives
|
|
315
549
|
* in a selector and not in `applyFrame`. */
|
|
@@ -327,6 +561,72 @@ export function selectedRunGates(store: Store): GateCard[] {
|
|
|
327
561
|
return store.gates.get(store.selectedRunId)?.gates ?? [];
|
|
328
562
|
}
|
|
329
563
|
|
|
564
|
+
/** Why the SELECTED run's Workspaces wait for capacity (ADR-0064) — empty in observer mode, where
|
|
565
|
+
* the diagram still lights `placing` but the reason is not the page's to know. */
|
|
566
|
+
export function selectedRunWaiting(store: Store): WaitingLine[] {
|
|
567
|
+
if (store.selectedRunId === null) return [];
|
|
568
|
+
return store.waiting.get(store.selectedRunId)?.waiting ?? [];
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/** The reason of a run that ended `failed`, off a `GET /runs/:id` answer (ADR-0073): the Failure's
|
|
572
|
+
* `reason` in the run's output. Null for every other status, and for an output with no reason
|
|
573
|
+
* text — the same reading as `jr2 status`'s `failed:` line. */
|
|
574
|
+
export function failureReason(body: { status?: string; output?: unknown }): string | null {
|
|
575
|
+
if (body.status !== "failed") return null;
|
|
576
|
+
const reason = (body.output as { reason?: unknown } | null | undefined)?.reason;
|
|
577
|
+
return typeof reason === "string" ? reason : null;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/** Why the SELECTED run failed (ADR-0073): the reason of its Failure, or null when it did not fail
|
|
581
|
+
* or the page has no live token to read it with. */
|
|
582
|
+
export function selectedRunFailure(store: Store): string | null {
|
|
583
|
+
if (store.selectedRunId === null) return null;
|
|
584
|
+
return store.failures.get(store.selectedRunId) ?? null;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/** The SELECTED run's outstanding picks, each with since when it is held (ADR-0024) — empty in
|
|
588
|
+
* observer mode. */
|
|
589
|
+
export function selectedRunHeld(store: Store): HeldLine[] {
|
|
590
|
+
if (store.selectedRunId === null) return [];
|
|
591
|
+
return store.waiting.get(store.selectedRunId)?.held ?? [];
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/** One party's seat on one state (ADR-0015): who may send which names there — mirrors
|
|
595
|
+
* `MachineSeat` in vocabulary.ts. */
|
|
596
|
+
export type Seat = { state: string; party: "agent" | "gate"; agent?: string; names: string[] };
|
|
597
|
+
|
|
598
|
+
/** The part of a Machine doc the seats are read from: each body's `seats` and `warnings`, and the
|
|
599
|
+
* child Machines below its states (canvas.ts's `MachineBodyDoc`, structurally). */
|
|
600
|
+
export type SeatedBody = {
|
|
601
|
+
seats?: Seat[];
|
|
602
|
+
warnings?: string[];
|
|
603
|
+
root: SeatedState;
|
|
604
|
+
};
|
|
605
|
+
type SeatedState = { states: SeatedState[]; children: Array<{ machine?: SeatedBody }> };
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Who may send what, per state, and what the build found suspect (ADR-0015) — for the Machine and
|
|
609
|
+
* every Machine it composes, in the order `jr2 up` prints them: the root's body, then each child
|
|
610
|
+
* Machine's, depth-first in state order. A function of the doc, not of the store: the doc is
|
|
611
|
+
* structure the server serves (app.ts's `MachineView`), and this is the one piece of it worth a
|
|
612
|
+
* unit test outside the canvas.
|
|
613
|
+
*/
|
|
614
|
+
export function docSeats(doc: SeatedBody | null): { seats: Seat[]; warnings: string[] } {
|
|
615
|
+
const seats: Seat[] = [];
|
|
616
|
+
const warnings: string[] = [];
|
|
617
|
+
const body = (b: SeatedBody): void => {
|
|
618
|
+
seats.push(...(b.seats ?? []));
|
|
619
|
+
warnings.push(...(b.warnings ?? []));
|
|
620
|
+
state(b.root);
|
|
621
|
+
};
|
|
622
|
+
const state = (s: SeatedState): void => {
|
|
623
|
+
for (const child of s.children) if (child.machine) body(child.machine);
|
|
624
|
+
s.states.forEach(state);
|
|
625
|
+
};
|
|
626
|
+
if (doc) body(doc);
|
|
627
|
+
return { seats, warnings };
|
|
628
|
+
}
|
|
629
|
+
|
|
330
630
|
/** What the nav badge counts: every open gate everywhere — attention is global even when the
|
|
331
631
|
* inbox view is filtered. */
|
|
332
632
|
export function gateCount(store: Store): number {
|
package/console/style.css
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
--phosphor-soft: rgba(78, 240, 167, 0.12);
|
|
13
13
|
--amber: #f0c04e;
|
|
14
14
|
--red: #f06a5f;
|
|
15
|
+
/* A Failure (ADR-0073): an end the Machine chose, so not the red of a fault. */
|
|
16
|
+
--orange: #f0954e;
|
|
15
17
|
--blue: #6aa7f0;
|
|
16
18
|
--mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
|
|
17
19
|
}
|
|
@@ -162,6 +164,112 @@ main {
|
|
|
162
164
|
display: none;
|
|
163
165
|
}
|
|
164
166
|
|
|
167
|
+
/* Who may send what, per state (ADR-0015) — structure, folded by default so the diagram keeps the
|
|
168
|
+
pane; open, it scrolls inside its own cap rather than push the diagram out. */
|
|
169
|
+
#seats {
|
|
170
|
+
margin: 0 28px 16px;
|
|
171
|
+
max-width: 720px;
|
|
172
|
+
}
|
|
173
|
+
#root-transitions:empty + #seats {
|
|
174
|
+
margin-top: 28px;
|
|
175
|
+
}
|
|
176
|
+
#seats summary {
|
|
177
|
+
cursor: pointer;
|
|
178
|
+
color: var(--text-dim);
|
|
179
|
+
}
|
|
180
|
+
#seats .seats-warned {
|
|
181
|
+
color: var(--amber);
|
|
182
|
+
}
|
|
183
|
+
#seats ul {
|
|
184
|
+
list-style: none;
|
|
185
|
+
margin: 8px 0 0;
|
|
186
|
+
padding: 0;
|
|
187
|
+
max-height: 30vh;
|
|
188
|
+
overflow: auto;
|
|
189
|
+
}
|
|
190
|
+
#seats .seat-list li {
|
|
191
|
+
padding: 2px 0;
|
|
192
|
+
}
|
|
193
|
+
#seats .seat-names {
|
|
194
|
+
color: var(--blue);
|
|
195
|
+
}
|
|
196
|
+
#seats .seat-warnings li {
|
|
197
|
+
border: 1px solid var(--amber);
|
|
198
|
+
border-radius: 4px;
|
|
199
|
+
padding: 6px 10px;
|
|
200
|
+
margin-bottom: 6px;
|
|
201
|
+
color: var(--amber);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* A wait for capacity (ADR-0064): the selected run's Workspaces in "placing", and why. Amber like
|
|
205
|
+
the notice — the run is not wrong, it is waiting on the cluster. */
|
|
206
|
+
#waiting {
|
|
207
|
+
list-style: none;
|
|
208
|
+
margin: 0 28px 16px;
|
|
209
|
+
padding: 0;
|
|
210
|
+
max-width: 720px;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
#waiting:empty {
|
|
214
|
+
display: none;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#waiting li {
|
|
218
|
+
border: 1px solid var(--amber);
|
|
219
|
+
border-radius: 4px;
|
|
220
|
+
padding: 8px 12px;
|
|
221
|
+
margin-bottom: 8px;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
#waiting .waiting-head {
|
|
225
|
+
color: var(--amber);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
#waiting .waiting-message {
|
|
229
|
+
margin-top: 4px;
|
|
230
|
+
font-family: var(--mono);
|
|
231
|
+
color: var(--text-dim);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* A failed run (ADR-0073): the reason of its Failure. Orange like the rail's `failed` status — the
|
|
235
|
+
Machine chose this end, so it is not the red of an `error`. */
|
|
236
|
+
#failure {
|
|
237
|
+
margin: 0 28px 16px;
|
|
238
|
+
max-width: 720px;
|
|
239
|
+
border: 1px solid var(--orange);
|
|
240
|
+
border-radius: 4px;
|
|
241
|
+
padding: 8px 12px;
|
|
242
|
+
color: var(--orange);
|
|
243
|
+
font-family: var(--mono);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#failure[hidden] {
|
|
247
|
+
display: none;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* An outstanding pick (ADR-0024): an Agent's Turn held while the workflow runs its pick. */
|
|
251
|
+
#held {
|
|
252
|
+
list-style: none;
|
|
253
|
+
margin: 0 28px 16px;
|
|
254
|
+
padding: 0;
|
|
255
|
+
max-width: 720px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
#held:empty {
|
|
259
|
+
display: none;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#held li {
|
|
263
|
+
border: 1px solid var(--line);
|
|
264
|
+
border-radius: 4px;
|
|
265
|
+
padding: 8px 12px;
|
|
266
|
+
margin-bottom: 8px;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
#held .held-head {
|
|
270
|
+
font-family: var(--mono);
|
|
271
|
+
}
|
|
272
|
+
|
|
165
273
|
/* ---- Machine (SVG) ---- */
|
|
166
274
|
|
|
167
275
|
/* Every box is click-to-select (outline only — the click is reserved beyond that). */
|
|
@@ -525,6 +633,9 @@ ul {
|
|
|
525
633
|
.wf-runs .run-status.status--error {
|
|
526
634
|
color: var(--red);
|
|
527
635
|
}
|
|
636
|
+
.wf-runs .run-status.status--failed {
|
|
637
|
+
color: var(--orange);
|
|
638
|
+
}
|
|
528
639
|
.wf-runs .run-status.status--done {
|
|
529
640
|
color: var(--phosphor);
|
|
530
641
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
jr2 is newer than your training data. Before you write a Machine or change jr2.config.ts, read the bundled docs in node_modules/@jr2/orchestrator/docs/. They are the docs of this Instance's Kit version, 0.5.1. Start with guides/write-a-workflow.md and with reference/authoring-surface.md, the contents page of the Authoring surface. Read one page with each call of your file tool, because a file tool cuts off a long output. Before you give a change to the user, run `npx --no jr2 check` in the Instance folder. It does the typecheck and the load of each Workflow that `jr2 up` does first, with no cluster, and it gives the same refusals.
|
|
2
|
+
|
|
3
|
+
A final state means that the work succeeded: the run ends `done`. When the work did not succeed, invoke `fail()` from a state (reference/authoring-surface/fail.md), and the run ends `failed`. Do not throw to fail: a throw is a defect, and the run ends `error`.
|
|
4
|
+
|
|
5
|
+
[jr2 docs index]|root: ./node_modules/@jr2/orchestrator/docs|reference:{authoring-surface.md,machines.md,config.md,cli.md,http-api.md,mechanism-events.md,glossary.md,decisions.md}|reference/authoring-surface:{one file per export and type; reference/authoring-surface.md lists them}|guides:{iterate-on-a-machine-on-kind.md,write-a-workflow.md,bind-open-parts.md,set-an-agents-access-and-dials.md,run-a-command-or-call-a-url.md,push-and-sign-a-branch.md,start-a-run-from-a-run.md,add-tools-to-the-sandbox.md,size-a-workspace.md,run-one-worker-per-item.md,publish-a-machine-as-an-npm-package.md,let-an-agent-write-a-chart.md,run-a-chart-by-name.md,start-a-run.md,answer-a-gate.md,watch-a-run.md,look-inside-a-sandbox.md,cancel-a-run.md,open-the-console.md,use-a-local-model.md,use-a-hosted-provider.md,give-the-cluster-git-credentials.md,move-from-kind-to-a-shared-cluster.md,mirror-the-kit-images.md,upgrade-the-kit-version.md,clean-up.md,fix-a-failed-converge.md}|concepts:{machines-and-workflows.md,agents-and-turns.md,the-menu.md,gates.md,effects.md,workspaces.md,composition.md,charts.md,pools-and-sources.md,architecture.md,secrets-and-trust.md,converge.md,durable-runs.md}|.:{index.md,why.md}|get-started:{install.md,create-an-instance.md,connect-a-model.md,a-model-decides.md,an-agent-in-a-sandbox.md,have-your-assistant-write-a-machine.md}|reference/decisions:{one file per ADR; reference/decisions.md lists them}
|