@jr2/orchestrator 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/console/components/app.ts +2 -0
- package/console/components/fleet.ts +14 -1
- package/console/components/machine-pane.ts +41 -2
- package/console/main.ts +13 -1
- package/console/store.ts +102 -6
- package/console/style.css +21 -0
- package/docs/agents-block.md +5 -0
- package/docs/concepts/agents-and-turns.md +478 -0
- package/docs/concepts/architecture.md +243 -0
- package/docs/concepts/charts.md +146 -0
- package/docs/concepts/composition.md +357 -0
- package/docs/concepts/converge.md +257 -0
- package/docs/concepts/durable-runs.md +189 -0
- package/docs/concepts/effects.md +658 -0
- package/docs/concepts/gates.md +208 -0
- package/docs/concepts/machines-and-workflows.md +298 -0
- package/docs/concepts/pools-and-sources.md +230 -0
- package/docs/concepts/secrets-and-trust.md +306 -0
- package/docs/concepts/the-menu.md +381 -0
- package/docs/concepts/workspaces.md +756 -0
- package/docs/get-started/a-model-decides.md +563 -0
- package/docs/get-started/an-agent-in-a-sandbox.md +383 -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 +993 -0
- package/docs/get-started/install.md +130 -0
- package/docs/guides/add-tools-to-the-sandbox.md +308 -0
- package/docs/guides/answer-a-gate.md +304 -0
- package/docs/guides/bind-open-parts.md +224 -0
- package/docs/guides/cancel-a-run.md +146 -0
- package/docs/guides/clean-up.md +206 -0
- package/docs/guides/cut-a-worktree.md +560 -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 +230 -0
- package/docs/guides/look-inside-a-sandbox.md +177 -0
- package/docs/guides/mirror-the-kit-images.md +176 -0
- package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -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 +532 -0
- package/docs/guides/run-a-chart-by-name.md +270 -0
- package/docs/guides/run-a-command-or-call-a-url.md +587 -0
- package/docs/guides/run-one-worker-per-item.md +322 -0
- package/docs/guides/set-an-agents-access-and-dials.md +420 -0
- package/docs/guides/size-a-workspace.md +217 -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 +214 -0
- package/docs/guides/use-a-local-model.md +313 -0
- package/docs/guides/watch-a-run.md +349 -0
- package/docs/guides/write-a-workflow.md +318 -0
- package/docs/index.md +44 -0
- package/docs/llms.txt +237 -0
- package/docs/reference/authoring-surface/agent.md +151 -0
- package/docs/reference/authoring-surface/answer.md +156 -0
- package/docs/reference/authoring-surface/arg.md +82 -0
- package/docs/reference/authoring-surface/basic.md +62 -0
- package/docs/reference/authoring-surface/bearer.md +53 -0
- package/docs/reference/authoring-surface/branchname.md +15 -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 +206 -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 +96 -0
- package/docs/reference/authoring-surface/file.md +142 -0
- package/docs/reference/authoring-surface/frompick.md +277 -0
- package/docs/reference/authoring-surface/http.md +259 -0
- package/docs/reference/authoring-surface/isfailure.md +58 -0
- package/docs/reference/authoring-surface/isready.md +14 -0
- package/docs/reference/authoring-surface/jr2setup.md +237 -0
- package/docs/reference/authoring-surface/open.md +105 -0
- package/docs/reference/authoring-surface/openbody.md +86 -0
- package/docs/reference/authoring-surface/paramsof.md +143 -0
- package/docs/reference/authoring-surface/pool.md +186 -0
- package/docs/reference/authoring-surface/push.md +130 -0
- package/docs/reference/authoring-surface/readyof.md +21 -0
- package/docs/reference/authoring-surface/secret.md +139 -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 +15 -0
- package/docs/reference/authoring-surface/type-answeraction.md +12 -0
- package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
- package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -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-bindactors.md +14 -0
- package/docs/reference/authoring-surface/type-binding.md +61 -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 +20 -0
- package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
- package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
- package/docs/reference/authoring-surface/type-customize.md +111 -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 +72 -0
- package/docs/reference/authoring-surface/type-doorlessinput.md +19 -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 +37 -0
- package/docs/reference/authoring-surface/type-framepath.md +14 -0
- package/docs/reference/authoring-surface/type-frominput.md +14 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
- package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
- package/docs/reference/authoring-surface/type-httpfileinput.md +20 -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 +95 -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-lateroutcome.md +21 -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-namestart.md +77 -0
- package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
- package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -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 +22 -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 +26 -0
- package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
- package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
- package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
- package/docs/reference/authoring-surface/type-poolspec.md +60 -0
- package/docs/reference/authoring-surface/type-pushinput.md +34 -0
- package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
- package/docs/reference/authoring-surface/type-pushoutput.md +149 -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 +84 -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 +24 -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 +115 -0
- package/docs/reference/authoring-surface/type-workspacehandles.md +22 -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 +27 -0
- package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
- package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
- package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
- package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
- package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
- package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
- package/docs/reference/authoring-surface/workspace.md +287 -0
- package/docs/reference/authoring-surface/worktree.md +71 -0
- package/docs/reference/authoring-surface.md +217 -0
- package/docs/reference/cli.md +433 -0
- package/docs/reference/config.md +765 -0
- package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
- package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
- package/docs/reference/decisions/0006-agent-control-surface.md +50 -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 +175 -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 +271 -0
- package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -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 +287 -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 +101 -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 +175 -0
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -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 +245 -0
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -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 +193 -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 +126 -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 +238 -0
- package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
- package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -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 +108 -0
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -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 +239 -0
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -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 +552 -0
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -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 +334 -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/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
- package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
- package/docs/reference/decisions.md +86 -0
- package/docs/reference/glossary.md +687 -0
- package/docs/reference/http-api.md +1386 -0
- package/docs/reference/machines.md +189 -0
- package/docs/reference/mechanism-events.md +72 -0
- package/docs/why.md +207 -0
- package/package.json +5 -3
- package/src/actor.ts +694 -106
- package/src/agent.ts +114 -38
- package/src/ambient.ts +3 -4
- package/src/assembly-checks.ts +189 -7
- package/src/cause.ts +234 -0
- package/src/chart.ts +345 -46
- package/src/charts.ts +43 -8
- package/src/config.ts +440 -178
- package/src/custodian.lua +17 -5
- package/src/custodian.ts +325 -99
- package/src/customize.ts +199 -49
- 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 +50 -3
- package/src/effect.ts +641 -128
- package/src/effector-wire.ts +165 -13
- package/src/fail.ts +222 -0
- package/src/harness-client.ts +587 -50
- package/src/harness-env.ts +33 -0
- package/src/held-secrets.ts +125 -16
- package/src/holds.ts +3 -0
- package/src/http-effect.ts +556 -58
- package/src/http.ts +480 -30
- package/src/index.ts +74 -82
- package/src/instance.ts +68 -8
- package/src/internal.ts +85 -0
- package/src/kube-client.ts +6 -3
- package/src/machine-doc.ts +24 -7
- package/src/mechanism-routes.ts +168 -0
- package/src/model-keys.generated.ts +53 -0
- package/src/model-keys.ts +42 -58
- package/src/names.ts +19 -6
- package/src/notices.ts +483 -41
- package/src/open-body.ts +242 -40
- package/src/open-effect.ts +81 -8
- package/src/open.ts +90 -6
- package/src/parts.ts +213 -30
- package/src/party.ts +101 -2
- package/src/pick.ts +497 -11
- package/src/pool.ts +282 -50
- package/src/registration.ts +133 -12
- package/src/repo-identity.ts +7 -3
- package/src/repos.ts +22 -3
- package/src/run-host.ts +665 -45
- package/src/run-output.ts +38 -0
- package/src/sandbox-effect.ts +457 -71
- package/src/sandbox-kube.ts +66 -17
- package/src/secret-placement.ts +59 -17
- package/src/server.ts +3 -0
- package/src/setup.ts +325 -62
- package/src/size.ts +121 -9
- package/src/snapshot-store.ts +54 -10
- package/src/stub-harness.ts +44 -16
- package/src/timers.ts +14 -1
- package/src/tokens.ts +107 -32
- package/src/vocabulary.ts +88 -14
- package/src/wire.ts +100 -26
- package/src/workspace.ts +771 -238
- package/src/worktree.ts +249 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: command
|
|
3
|
+
description: "Make a `command` Effect: an actor slot that runs one program in the Workspace's Sandbox when a state invokes it."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `command`
|
|
7
|
+
|
|
8
|
+
Function, in `@jr2/orchestrator/src/harness-client.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
|
|
9
|
+
|
|
10
|
+
## Overload 1
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
function command<
|
|
14
|
+
const A extends readonly (string | Arg)[],
|
|
15
|
+
const Opt extends CommandOptions = CommandOptions,
|
|
16
|
+
>(
|
|
17
|
+
argv: A,
|
|
18
|
+
options?: Opt,
|
|
19
|
+
): EffectLogic<CommandInput<A, Opt["pin"], Opt>, CommandOutput> & OpenOf<EnvOpenParts<Opt>>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Make a `command` Effect: an actor slot that runs one program in the Workspace's Sandbox when a
|
|
23
|
+
state invokes it. Put it under `actors` and invoke it by its key: `actors: { tests:
|
|
24
|
+
command(["node", "--test"]) }`, then `invoke: { src: "tests", onDone: … }`.
|
|
25
|
+
|
|
26
|
+
`argv` is a list, never shell text: each entry is one argument. An `arg("name")` entry is filled
|
|
27
|
+
from the invoke's `input` (`input: { name: "…" }`), as one argument whatever its text. To use a
|
|
28
|
+
shell, write it: `["sh", "-c", "…"]`.
|
|
29
|
+
|
|
30
|
+
Where it runs:
|
|
31
|
+
- With no Effect secret in `env`, in the Harness container of the enclosing Workspace's Sandbox.
|
|
32
|
+
It runs in the Worktree that `worktree` of the invoke's input names, or in `/work` in a
|
|
33
|
+
Workspace with no Repo Slot. The Agent's Working tools also run in this container.
|
|
34
|
+
- With an Effect secret in `env`, in the Sandbox Effector, against a commit of the branch. This
|
|
35
|
+
is the branch tip when it starts, or with `pin: true` the commit that the invoke's `input.sha`
|
|
36
|
+
names. The output then says `dirty: true` when the Worktree held edits that the command did
|
|
37
|
+
not see.
|
|
38
|
+
|
|
39
|
+
Every outcome is output for `onDone`, never an error: `{ outcome: "exited", code, tail }`,
|
|
40
|
+
`{ outcome: "timeout", tail }`, `{ outcome: "killed", signal, tail }`, or `{ outcome: "unknown",
|
|
41
|
+
reason }` when jr2 cannot know what happened. `tail` is the end of the output stream.
|
|
42
|
+
|
|
43
|
+
After an Orchestrator restart:
|
|
44
|
+
- A command with no Effect secret in `env` never runs twice. jr2 attaches to it again, or settles
|
|
45
|
+
`unknown`.
|
|
46
|
+
- A command with an Effect secret in `env` runs again when the Sandbox Effector no longer holds
|
|
47
|
+
it. It runs against the same commit. If jr2 has no commit for it, it settles `unknown`.
|
|
48
|
+
|
|
49
|
+
When the state exits, the command stops: jr2 kills its process group. `onError` is only for a
|
|
50
|
+
Machine or config defect.
|
|
51
|
+
|
|
52
|
+
It refuses, when you call it:
|
|
53
|
+
- an empty `argv`: `command(argv): argv is a non-empty list — each entry one argument, never
|
|
54
|
+
shell text`
|
|
55
|
+
- an entry that is not a string or `arg()`: `command(argv): an argv entry is a string or
|
|
56
|
+
arg("name"), got <entry>`
|
|
57
|
+
- a `timeout` that is not a positive duration: `command: timeout "<timeout>" is not a positive
|
|
58
|
+
duration (like "90s", "10m", "1h")`
|
|
59
|
+
- an `env` name that is not a variable name, or `PATH`, `HOME` or `TMPDIR`: ``command(argv, {
|
|
60
|
+
env }): "<name>" is not a variable the author sets — PATH, HOME and TMPDIR are the Effector's
|
|
61
|
+
(ADR-0067)``
|
|
62
|
+
- `pin: true` with no Effect secret in `env`: ``command(argv, { pin: true }) names no secret in
|
|
63
|
+
its env: `pin` chooses the commit a credentialed command runs against in the Sandbox
|
|
64
|
+
Effector, and a command that names no secret runs in the live Worktree (ADR-0067) — name its
|
|
65
|
+
secret, command(argv, { env: { NAME: secret("x") }, pin: true }), or drop `pin` ``
|
|
66
|
+
|
|
67
|
+
And when it starts, with no Effect secret in `env`:
|
|
68
|
+
- outside a `workspace()`: `command "<slot>" runs in the Harness container of a Workspace, and
|
|
69
|
+
its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
|
|
70
|
+
- no `worktree` under Repo Slots: `` command "<slot>" runs under a Workspace with Repo Slots
|
|
71
|
+
(<slots>) and its input names no `worktree`: say which, a Worktree that a cut gave or
|
|
72
|
+
`<slot>/default` ``
|
|
73
|
+
- an `arg()` with no string in `input`: `command "<slot>": argv slot <<name>> has no string
|
|
74
|
+
value in its input (got <type>) — map it in the invoke's input`. The angle brackets around the
|
|
75
|
+
arg's name are in the text: `argv slot <file>`. `<type>` is `nothing` when `input` has no such
|
|
76
|
+
field, or the type of its value, such as `number`.
|
|
77
|
+
|
|
78
|
+
And when it starts, with an Effect secret in `env`:
|
|
79
|
+
- outside a `workspace()`: `command "<slot>" runs in the Sandbox Effector of a Workspace, and its
|
|
80
|
+
state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
|
|
81
|
+
- a Workspace with no Repo Slot: `command "<slot>" runs under a Workspace with no Repo Slot: a
|
|
82
|
+
command with an Effect secret runs against one commit of a Repo Slot's branch, and there is
|
|
83
|
+
none — declare a Repo Slot, or name no secret in its env, and it runs in /work beside the Agent
|
|
84
|
+
(ADR-0051)`. `jr2 up` refuses it first, with the same reason
|
|
85
|
+
- a `worktree` that no cut made in this Sandbox: the output is `exited` 127, with `no cut made
|
|
86
|
+
<path> in this Sandbox: cut it with worktree()` in its tail. A detached Worktree gets the same
|
|
87
|
+
form
|
|
88
|
+
- `pin: true` and an `input.sha` that is not a full commit id: `command "<slot>" (pin): its
|
|
89
|
+
input's sha is not a full commit id`
|
|
90
|
+
- an `arg()` with no string in `input`: the same text as above.
|
|
91
|
+
|
|
92
|
+
**Parameters**
|
|
93
|
+
|
|
94
|
+
- `argv`: The program and its arguments: strings and `arg("name")` entries. Or `open`, in a
|
|
95
|
+
Machine that you publish as a package, for the Instance that registers it to bind with
|
|
96
|
+
`customize()`.
|
|
97
|
+
- `options` ([`CommandOptions`](type-commandoptions.md)): Optional. `timeout`: `"90s"`, `"10m"` or `"1h"`, default
|
|
98
|
+
`"10m"`; when it expires, the output is `timeout`. `tail`: how many characters of the end of
|
|
99
|
+
the output stream to keep, default 4096. `env`: environment variables. Each value is
|
|
100
|
+
`secret("name")` for the value of an Effect secret, or `secret("name").path` for the path of a
|
|
101
|
+
file that holds it. `pin`: `true` to run against the commit in `input.sha`. Use `pin` only
|
|
102
|
+
with an Effect secret in `env`.
|
|
103
|
+
|
|
104
|
+
**Returns**: The actor logic of the Effect's slot. Its output is a `CommandOutput`.
|
|
105
|
+
|
|
106
|
+
**Example**
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { z } from "zod";
|
|
110
|
+
import {
|
|
111
|
+
arg,
|
|
112
|
+
command,
|
|
113
|
+
fail,
|
|
114
|
+
isReady,
|
|
115
|
+
jr2Setup,
|
|
116
|
+
workspace,
|
|
117
|
+
worktree,
|
|
118
|
+
type Workspaced,
|
|
119
|
+
} from "@jr2/orchestrator";
|
|
120
|
+
|
|
121
|
+
const runInput = z.object({ branch: z.string() });
|
|
122
|
+
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
|
|
123
|
+
|
|
124
|
+
const testTree = (context: BodyInput) => `${context.workspace.repos.app}/test` as const;
|
|
125
|
+
|
|
126
|
+
const body = jr2Setup({
|
|
127
|
+
types: {} as { input: BodyInput; context: BodyInput },
|
|
128
|
+
actors: {
|
|
129
|
+
cut: worktree(),
|
|
130
|
+
tests: command(["node", "--test", arg("file")], { timeout: "5m" }),
|
|
131
|
+
fail: fail(),
|
|
132
|
+
},
|
|
133
|
+
}).createMachine({
|
|
134
|
+
id: "check",
|
|
135
|
+
context: ({ input }) => input,
|
|
136
|
+
on: { "workspace.lost": ".lost" },
|
|
137
|
+
initial: "cutting",
|
|
138
|
+
states: {
|
|
139
|
+
cutting: {
|
|
140
|
+
invoke: {
|
|
141
|
+
src: "cut",
|
|
142
|
+
input: ({ context }) => ({ path: testTree(context), branch: context.branch }),
|
|
143
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "testing" }, { target: "notCut" }],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
testing: {
|
|
147
|
+
invoke: {
|
|
148
|
+
src: "tests",
|
|
149
|
+
input: ({ context }) => ({ file: "test/greet.test.js", worktree: testTree(context) }),
|
|
150
|
+
onDone: [
|
|
151
|
+
{
|
|
152
|
+
guard: ({ event }) => event.output.outcome === "exited" && event.output.code === 0,
|
|
153
|
+
target: "passed",
|
|
154
|
+
},
|
|
155
|
+
{ target: "failed" },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
passed: { type: "final" },
|
|
160
|
+
// Not final states: each one fails the run, and the run ends `failed`.
|
|
161
|
+
failed: { invoke: { src: "fail", input: { reason: "the test did not pass" } } },
|
|
162
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
163
|
+
lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
export const machine = workspace(body, {
|
|
168
|
+
input: runInput,
|
|
169
|
+
repos: { app: "https://github.com/you/app.git" },
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**See also**
|
|
174
|
+
|
|
175
|
+
- [Effects](../../concepts/effects.md)
|
|
176
|
+
- [Run a command or call a URL with an Effect](../../guides/run-a-command-or-call-a-url.md)
|
|
177
|
+
- [ADR-0067: An Effect is an actor slot, and runs at most once unless marked idempotent](../decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
|
|
178
|
+
- [ADR-0068: An Effector holds an Effect's secrets and signs its wire](../decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md)
|
|
179
|
+
|
|
180
|
+
## Overload 2
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
function command<
|
|
184
|
+
const Opt extends CommandOptions = CommandOptions,
|
|
185
|
+
>(
|
|
186
|
+
argv: typeof open,
|
|
187
|
+
options?: Opt,
|
|
188
|
+
): EffectLogic<OpenCommandInput<Opt["pin"], Opt>, CommandOutput> & OpenEffect<"argv" | EnvOpenParts<Opt>>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Make a `command` Effect whose argv is Open: `command(open, options)`, in a Machine that you
|
|
192
|
+
publish as a package. The Instance that registers the Machine binds the argv one time:
|
|
193
|
+
`customize(machine, { effects: { <slot>: { argv } } })`. `command` tells the rest, and
|
|
194
|
+
what it refuses.
|
|
195
|
+
|
|
196
|
+
**Parameters**
|
|
197
|
+
|
|
198
|
+
- `argv`: `open`.
|
|
199
|
+
- `options` ([`CommandOptions`](type-commandoptions.md)): Optional. The same options as for a written argv.
|
|
200
|
+
|
|
201
|
+
**Returns**: The actor logic of the Effect's slot. Its output is a `CommandOutput`.
|
|
202
|
+
|
|
203
|
+
**See also**
|
|
204
|
+
|
|
205
|
+
- [Bind a shipped Machine's Open parts](../../guides/bind-open-parts.md)
|
|
206
|
+
- [ADR-0054: The kit ships Machines, and a shipped Machine leaves its parts Open](../decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: customize
|
|
3
|
+
description: Retune the parts that a Machine carries, without a change to the module that exports it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `customize`
|
|
7
|
+
|
|
8
|
+
Function, in `@jr2/orchestrator/src/customize.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Composition.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
function customize<M extends AnyStateMachine>(machine: M, parts: Customize<M>): M
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Retune the parts that a Machine carries, without a change to the module that exports it. Use it
|
|
15
|
+
where you register a Machine as a Workflow. It binds the parts that a packaged Machine leaves
|
|
16
|
+
Open: its Repo Slots, an Agent's model, or an Effect's url, argv or secret. It also changes the
|
|
17
|
+
parts that its author fixed: an Agent's instructions, the Sandbox Image, or the Size.
|
|
18
|
+
|
|
19
|
+
It gives back a new Machine of the same type. The original does not change, so two
|
|
20
|
+
`customize()` calls on one import give two Machines. Only the parts the Machine declares can be
|
|
21
|
+
retuned. You cannot add a part: a Machine that needs another Agent is a new Machine. The types
|
|
22
|
+
refuse most mistakes when you compile. At run time, `customize()` also throws:
|
|
23
|
+
|
|
24
|
+
- `customize(): machine "<id>" carries no Agent slot "<slot>" — its Agents are: <slots>`
|
|
25
|
+
- `customize(): machine "<id>" composes no Machine under "<slot>" — the Machines it composes are: <slots>`
|
|
26
|
+
- `customize(): machine "<id>" carries no Effect slot "<slot>" — its Effects are: <slots>`
|
|
27
|
+
- `customize(): machine "<id>" declares no Repo Slot "<slot>" — its slots are: <slots>`
|
|
28
|
+
- `customize(): machine "<id>" declares its Repo Slots open as a map — name at least one`
|
|
29
|
+
- `` customize(): `repos` say what a SANDBOX is made of, how big it is and which Repos it
|
|
30
|
+
attaches, and machine "<id>" composes none `` (for `resources`, the text starts
|
|
31
|
+
`` customize(): `resources` ``; for `image` or `user`, it starts `` customize(): `image`/`user` ``)
|
|
32
|
+
- `customize(): machine "<id>": <errors>`, when an Effect argv that you bind fails the checks
|
|
33
|
+
that the Machine passed when it was built
|
|
34
|
+
- the refusals of [`EffectBinding`](type-effectbinding.md), [`RepoSlot`](type-reposlot.md), [`Size`](type-size.md) and
|
|
35
|
+
[`UserContainer`](type-usercontainer.md), which start with `customize()`
|
|
36
|
+
|
|
37
|
+
**Parameters**
|
|
38
|
+
|
|
39
|
+
- `machine`: The Machine to retune: one you import from a package, or one you wrote. When
|
|
40
|
+
its root is a `workspace()` or a `pool()`, `customize()` reaches through to the Machine inside,
|
|
41
|
+
so you never name the wrapper's own slot.
|
|
42
|
+
- `parts`: The parts to change. See [`Customize`](type-customize.md).
|
|
43
|
+
|
|
44
|
+
**Returns**: A new Machine of the same type, with the parts changed.
|
|
45
|
+
|
|
46
|
+
**Example**
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { customize } from "@jr2/orchestrator";
|
|
50
|
+
import { task } from "@jr2/machines";
|
|
51
|
+
|
|
52
|
+
export const machine = customize(task, {
|
|
53
|
+
repos: { app: { url: "https://github.com/you/app.git" } },
|
|
54
|
+
agents: { coder: { model: "anthropic/claude-haiku-5-5" } },
|
|
55
|
+
resources: { limits: { memory: "4Gi" } },
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**See also**
|
|
60
|
+
|
|
61
|
+
- [Bind a shipped Machine's Open parts](../../guides/bind-open-parts.md)
|
|
62
|
+
- [Composition](../../concepts/composition.md)
|
|
63
|
+
- [ADR-0049: A Machine carries its parts and composes by invoke](../decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md)
|
|
64
|
+
- [ADR-0054: The kit ships Machines, and a shipped Machine leaves its parts Open](../decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: defineConfig
|
|
3
|
+
description: "Declare the config of an Instance: the default export of `jr2.config.ts`."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `defineConfig`
|
|
7
|
+
|
|
8
|
+
Function, in `@jr2/orchestrator/src/config.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Config.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
function defineConfig(c: JR2Config): JR2Config
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Declare the config of an Instance: the default export of `jr2.config.ts`. It gives back the
|
|
15
|
+
object that you pass. Its only work is to check that object against [`JR2Config`](type-jr2config.md) where you
|
|
16
|
+
write it, at every depth, a misspelled key included. `jr2 up` typechecks the file before it
|
|
17
|
+
converges.
|
|
18
|
+
|
|
19
|
+
**Parameters**
|
|
20
|
+
|
|
21
|
+
- `c`: The Instance's config. See [`JR2Config`](type-jr2config.md) for every field.
|
|
22
|
+
|
|
23
|
+
**Returns**: The same object.
|
|
24
|
+
|
|
25
|
+
**Example**
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { defineConfig } from "@jr2/orchestrator";
|
|
29
|
+
|
|
30
|
+
export default defineConfig({
|
|
31
|
+
name: "my-instance",
|
|
32
|
+
secrets: [{ name: "ANTHROPIC_API_KEY", value: process.env.ANTHROPIC_API_KEY }],
|
|
33
|
+
git: { credentials: [{ match: "github.com/you/", token: "GITHUB_TOKEN" }] },
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**See also**
|
|
38
|
+
|
|
39
|
+
- [jr2.config.ts](../config.md)
|
|
40
|
+
- [Create an Instance](../../get-started/create-an-instance.md)
|
|
41
|
+
- [ADR-0050: What code names, config declares; what the CLI names, discovery finds](../decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: defineEvent
|
|
3
|
+
description: "Define one workflow event: an event that an Agent or the caller of a Gate may send into your Machine."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `defineEvent`
|
|
7
|
+
|
|
8
|
+
Function, in `src/define-event.ts` of `@jr2/agent-protocol`, a dependency of `@jr2/orchestrator`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Machine and events.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
function defineEvent<const Name extends string, Input extends z.ZodObject>(def: {
|
|
12
|
+
name: Name;
|
|
13
|
+
description?: string;
|
|
14
|
+
input: Input;
|
|
15
|
+
semantics?: EventSemantics;
|
|
16
|
+
audience?: EventAudience;
|
|
17
|
+
}): EventDef<Name, Input>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Define one workflow event: an event that an Agent or the caller of a Gate may send into your
|
|
21
|
+
Machine. Give the result to `jr2Setup({ events })`, and write its name as an `on` key on the
|
|
22
|
+
states that take it. An Agent sees each event it may send as one tool on its Menu.
|
|
23
|
+
|
|
24
|
+
It gives back a frozen [`EventDef`](type-eventdef.md) and registers nothing. Each Machine whose `jr2Setup`
|
|
25
|
+
lists the event takes it. A Machine that does not list it does not take it.
|
|
26
|
+
|
|
27
|
+
Give an event only the params that the Machine reads. When a pick enters a state that invokes an
|
|
28
|
+
Effect, `createMachine` refuses each param of the pick that nothing reads: the input of the
|
|
29
|
+
Effect, an `assign`, or the `fill` of `fromPick`. The compiler does not find this error.
|
|
30
|
+
`jr2 check` and `jr2 up` find it when they load the module. Thus when you copy a `finish` event with a `summary`
|
|
31
|
+
and nothing uses the summary, drop `summary` from the `input`, or store it with `assign`.
|
|
32
|
+
|
|
33
|
+
It refuses:
|
|
34
|
+
- a name with a character other than a letter, a digit, `_` or `-`:
|
|
35
|
+
`defineEvent: invalid name "<name>" — must match /^[a-zA-Z0-9_-]+$/ (it becomes an MCP tool
|
|
36
|
+
name and an xstate event type)`
|
|
37
|
+
- an `input` with a `sender` field:
|
|
38
|
+
``defineEvent: "<name>" declares `sender` in its input — the Orchestrator writes that field
|
|
39
|
+
on every delivered event (who sent it); name the payload field something else``
|
|
40
|
+
- an `output` field:
|
|
41
|
+
``defineEvent: "<name>" declares an `output`, which is retired — every pick is answered when
|
|
42
|
+
the work it started is done, and the answer is the Machine's, not the def's``. With
|
|
43
|
+
`semantics: "deferred"`, the text says ``declares `deferred` `` in place of
|
|
44
|
+
``declares an `output` ``.
|
|
45
|
+
|
|
46
|
+
**Parameters**
|
|
47
|
+
|
|
48
|
+
- `def`: The event: its `name`, its `input` schema, and optionally its `description`,
|
|
49
|
+
`semantics` and `audience`.
|
|
50
|
+
|
|
51
|
+
- `name`: `Name`
|
|
52
|
+
|
|
53
|
+
The event's name: the `on` key that takes it, and the name of its tool on the Agent's Menu.
|
|
54
|
+
Letters, digits, `_` and `-` only.
|
|
55
|
+
- `description` (optional): `string`
|
|
56
|
+
|
|
57
|
+
What the event means, and when to send it. An Agent's model reads it as the tool's
|
|
58
|
+
description. Make it true at every state that takes the event.
|
|
59
|
+
- `input`: `Input`
|
|
60
|
+
|
|
61
|
+
The schema of the payload: a flat `z.object`. Use `z.object({})` for an event with no
|
|
62
|
+
payload. Do not name a field `sender`: jr2 writes that field.
|
|
63
|
+
- `semantics` (optional): [`EventSemantics`](type-eventsemantics.md)
|
|
64
|
+
|
|
65
|
+
How the sender gets its answer. Default: `"ack"`, the only value `createMachine` accepts.
|
|
66
|
+
- `audience` (optional): [`EventAudience`](type-eventaudience.md)
|
|
67
|
+
|
|
68
|
+
Who may send the event: `"agent"`, `"external"` or `"any"`. Default: unset, and the state of
|
|
69
|
+
each `on` key decides (see [`EventAudience`](type-eventaudience.md)).
|
|
70
|
+
|
|
71
|
+
**Returns**: The event, as plain data to list in `jr2Setup({ events })`.
|
|
72
|
+
|
|
73
|
+
**Example**
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { z } from "zod";
|
|
77
|
+
import { agent, defineEvent, fail, jr2Setup } from "@jr2/orchestrator";
|
|
78
|
+
|
|
79
|
+
const done = defineEvent({
|
|
80
|
+
name: "done",
|
|
81
|
+
description: "Call this when the summary is written.",
|
|
82
|
+
input: z.object({ summary: z.string() }),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export const machine = jr2Setup({
|
|
86
|
+
events: [done],
|
|
87
|
+
actors: {
|
|
88
|
+
writer: agent({
|
|
89
|
+
model: "anthropic/claude-haiku-5-5",
|
|
90
|
+
instructions: "You write short summaries.",
|
|
91
|
+
workspace: "none",
|
|
92
|
+
}),
|
|
93
|
+
fail: fail(),
|
|
94
|
+
},
|
|
95
|
+
}).createMachine({
|
|
96
|
+
id: "summary",
|
|
97
|
+
on: { "agent.fault": ".failed" },
|
|
98
|
+
initial: "writing",
|
|
99
|
+
states: {
|
|
100
|
+
writing: {
|
|
101
|
+
invoke: { src: "writer", input: { prompt: "Summarize the release notes in one line." } },
|
|
102
|
+
on: { done: "finished" },
|
|
103
|
+
},
|
|
104
|
+
finished: { type: "final" },
|
|
105
|
+
failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**See also**
|
|
111
|
+
|
|
112
|
+
- [Write a Workflow](../../guides/write-a-workflow.md)
|
|
113
|
+
- [The Menu](../../concepts/the-menu.md)
|
|
114
|
+
- [ADR-0011: Control events are workflow-defined and delivered by closure, not routed](../decisions/0011-workflow-defined-events.md)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: dispatch
|
|
3
|
+
description: "Make a `dispatch` Effect: it starts a run of a Workflow."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `dispatch`
|
|
7
|
+
|
|
8
|
+
Function, in `@jr2/orchestrator/src/dispatch-effect.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
function dispatch<
|
|
12
|
+
S extends z.ZodObject | undefined = undefined,
|
|
13
|
+
const T extends DispatchDefinition<S>["target"] = undefined,
|
|
14
|
+
>(
|
|
15
|
+
workflow: string,
|
|
16
|
+
def?: DispatchDefinition<S> & { target?: T },
|
|
17
|
+
): EffectLogic<DispatchInput<S>, DispatchOutput> & OpenOf<DispatchOpenParts<T>>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Make a `dispatch` Effect: it starts a run of a Workflow. Put it in `actors`, and invoke it from a
|
|
21
|
+
state: `actors: { triage: dispatch("triage", { input }) }`. The input of the invoke is the run
|
|
22
|
+
input of the new run, as `jr2 run --input` gives it.
|
|
23
|
+
|
|
24
|
+
The new run is a run of its own, with its own id, its own Workspaces and its own `CANCEL`. Its
|
|
25
|
+
record names this run as the run that dispatched it. A `CANCEL` of this run does not end it.
|
|
26
|
+
|
|
27
|
+
With no `target`, the run starts in this Orchestrator, under the current Assembly. With
|
|
28
|
+
`target: { url, token }`, it starts on the Orchestrator at `url`, and the Effect runs in the
|
|
29
|
+
Instance Effector. Every outcome is output ([`DispatchOutput`](type-dispatchoutput.md)): `started`, `settled`,
|
|
30
|
+
`refused`, `unreachable` or `unknown`. Each start carries a key, so a start that jr2 sends again
|
|
31
|
+
after a restart starts no second run.
|
|
32
|
+
|
|
33
|
+
It refuses:
|
|
34
|
+
- a name that is not a Workflow name: ``dispatch("<name>"): the Workflow is named as `jr2 run`
|
|
35
|
+
names it — a Machine's filename stem ("review"), or "<wrapper>/<name>" for a named Chart:
|
|
36
|
+
lowercase letters, digits and "-" (ADR-0071)``
|
|
37
|
+
- a `wait` that is not a boolean: `dispatch("<name>", { wait }): wait is true or false — a slot
|
|
38
|
+
that needs both declares two`
|
|
39
|
+
- an `input` that is not a `z.object()`: `dispatch("<name>", { input }): the input is a
|
|
40
|
+
z.object(...) — the run's body is a JSON object (ADR-0071)`
|
|
41
|
+
- a `timeout` that is not a duration: `dispatch("<name>"): timeout "<timeout>" is not a positive
|
|
42
|
+
duration (like "30s", "10m", "1h")`
|
|
43
|
+
- a `target` url that is not an origin: `dispatch("<name>", { target }): "<url>" is not an
|
|
44
|
+
origin — write the scheme and the host, with a port if it is not the scheme's, and no path,
|
|
45
|
+
query or userinfo`, then two examples
|
|
46
|
+
- `secret(open)` in a target: `dispatch("<name>", { target }): secret(open) in a target — the
|
|
47
|
+
target is the Open part, not its secret`, then the fix
|
|
48
|
+
|
|
49
|
+
`jr2 up` refuses a dispatch with no target whose Workflow the Assembly does not have, and an
|
|
50
|
+
`input` schema that the input of that Workflow does not take.
|
|
51
|
+
|
|
52
|
+
**Parameters**
|
|
53
|
+
|
|
54
|
+
- `workflow`: The Workflow to start, as `jr2 run` names it: `"triage"`, or
|
|
55
|
+
`"<wrapper>/<name>"` for a named Chart.
|
|
56
|
+
- `def`: Optional. Each field tells what it does.
|
|
57
|
+
|
|
58
|
+
- `input` (optional): `S`
|
|
59
|
+
|
|
60
|
+
A zod schema of the run input of the Workflow. It types the `input` of the invoke and
|
|
61
|
+
`fromPick`, and `jr2 up` compares it with the input that the Workflow declares. Without it,
|
|
62
|
+
only the Workflow checks the input.
|
|
63
|
+
- `wait` (optional): `boolean`
|
|
64
|
+
|
|
65
|
+
`true`: end when the new run ends (`settled`). `false`, the default: end when the
|
|
66
|
+
Orchestrator accepts the run (`started`).
|
|
67
|
+
- `timeout` (optional): [`Duration`](type-duration.md)
|
|
68
|
+
|
|
69
|
+
How long the Effect waits: by default 30s for the start, and 10m with `wait`.
|
|
70
|
+
- `target` (optional): `{ url: string; token: NamedSecret; } | typeof open`
|
|
71
|
+
|
|
72
|
+
A different Orchestrator: `url` is its origin, and `token` is the secret that holds its
|
|
73
|
+
Instance token. Or `open`, which the composer binds with `customize(<import>, { effects: {
|
|
74
|
+
<slot>: { target: { url, token } } } })`. Without it, the run starts in this Orchestrator.
|
|
75
|
+
|
|
76
|
+
**Returns**: An Effect, for `actors`.
|
|
77
|
+
|
|
78
|
+
**Example**
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { assign } from "xstate";
|
|
82
|
+
import { z } from "zod";
|
|
83
|
+
import { defineEvent, dispatch, jr2Setup } from "@jr2/orchestrator";
|
|
84
|
+
|
|
85
|
+
const triageInput = z.object({ request: z.string() });
|
|
86
|
+
|
|
87
|
+
const report = defineEvent({
|
|
88
|
+
name: "report",
|
|
89
|
+
description: "Report a request. A run of triage starts for it.",
|
|
90
|
+
input: triageInput,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export const machine = jr2Setup({
|
|
94
|
+
types: {} as { context: { request: string } },
|
|
95
|
+
events: [report],
|
|
96
|
+
// `wait: true`: the Effect ends when the run of triage ends.
|
|
97
|
+
actors: { triage: dispatch("triage", { input: triageInput, wait: true }) },
|
|
98
|
+
}).createMachine({
|
|
99
|
+
id: "intake",
|
|
100
|
+
context: { request: "" },
|
|
101
|
+
initial: "listening",
|
|
102
|
+
states: {
|
|
103
|
+
listening: {
|
|
104
|
+
invoke: { src: "gate" },
|
|
105
|
+
on: { report: { target: "starting", actions: assign({ request: ({ event }) => event.request }) } },
|
|
106
|
+
},
|
|
107
|
+
starting: {
|
|
108
|
+
invoke: {
|
|
109
|
+
src: "triage",
|
|
110
|
+
input: ({ context }) => ({ request: context.request }),
|
|
111
|
+
onDone: [
|
|
112
|
+
{ guard: ({ event }) => event.output.outcome === "settled", target: "done" },
|
|
113
|
+
{ target: "listening" },
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
done: { type: "final" },
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**See also**
|
|
123
|
+
|
|
124
|
+
- [Start a run from a run](../../guides/start-a-run-from-a-run.md)
|
|
125
|
+
- [Effects](../../concepts/effects.md)
|
|
126
|
+
- [ADR-0071: A run starts a run through a `dispatch` Effect](../decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: fail
|
|
3
|
+
description: "Fail the run: the Part a Machine invokes to end work that did not succeed."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `fail`
|
|
7
|
+
|
|
8
|
+
Function, in `@jr2/orchestrator/src/fail.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Failure.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
function fail(): FailSlot
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Fail the run: the Part a Machine invokes to end work that did not succeed. Put it in `actors`
|
|
15
|
+
under a name, and invoke it from any state, at any depth: `actors: { fail: fail() }`, then
|
|
16
|
+
`invoke: { src: "fail", input: { reason } }`.
|
|
17
|
+
|
|
18
|
+
The input is `{ reason: string; detail?: unknown }`. `reason` is text for a person, and it must
|
|
19
|
+
not be empty. `detail` is optional JSON for a machine reader.
|
|
20
|
+
|
|
21
|
+
The Failure goes up from the state that invokes `fail`, through each parent Machine, as an error
|
|
22
|
+
does. An `onError` on the way catches it; [`isFailure`](isfailure.md) tells it from a defect. When no state
|
|
23
|
+
catches it, the run ends `failed`: its output is `{ reason, detail }`, and `jr2 run` exits 1. A
|
|
24
|
+
`workspace()` that a Failure goes through deletes its Sandbox first.
|
|
25
|
+
|
|
26
|
+
To fail, invoke `fail`. Do not throw from a promise to fail: a throw is a defect, and the run
|
|
27
|
+
ends `error`. A final state means `done`: do not use one for work that did not succeed. To keep
|
|
28
|
+
the work for a person to read, wait at a Gate before the state that fails.
|
|
29
|
+
|
|
30
|
+
It refuses an input that is not a Failure's, and the run ends `error`: ``fail: the input must be
|
|
31
|
+
{ reason: string; detail?: unknown } with a reason that is not empty (got <value>) — invoke:
|
|
32
|
+
{ src: "fail", input: { reason: "the tests failed" } } (ADR-0073)``.
|
|
33
|
+
|
|
34
|
+
**Returns**: The actor logic of the slot.
|
|
35
|
+
|
|
36
|
+
**Example**
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { z } from "zod";
|
|
40
|
+
import { command, fail, isReady, jr2Setup, workspace, worktree, type Workspaced } from "@jr2/orchestrator";
|
|
41
|
+
|
|
42
|
+
const runInput = z.object({ branch: z.string() });
|
|
43
|
+
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
|
|
44
|
+
|
|
45
|
+
const testTree = (context: BodyInput) => `${context.workspace.repos.app}/test` as const;
|
|
46
|
+
|
|
47
|
+
const body = jr2Setup({
|
|
48
|
+
types: {} as { input: BodyInput; context: BodyInput },
|
|
49
|
+
actors: {
|
|
50
|
+
cut: worktree(),
|
|
51
|
+
tests: command(["npm", "test"], { timeout: "15m" }),
|
|
52
|
+
fail: fail(),
|
|
53
|
+
},
|
|
54
|
+
}).createMachine({
|
|
55
|
+
id: "check",
|
|
56
|
+
context: ({ input }) => input,
|
|
57
|
+
on: { "workspace.lost": ".lost" },
|
|
58
|
+
initial: "cutting",
|
|
59
|
+
states: {
|
|
60
|
+
cutting: {
|
|
61
|
+
invoke: {
|
|
62
|
+
src: "cut",
|
|
63
|
+
input: ({ context }) => ({ path: testTree(context), branch: context.branch }),
|
|
64
|
+
onDone: [{ guard: ({ event }) => isReady(event.output), target: "testing" }, { target: "notCut" }],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
testing: {
|
|
68
|
+
invoke: {
|
|
69
|
+
src: "tests",
|
|
70
|
+
input: ({ context }) => ({ worktree: testTree(context) }),
|
|
71
|
+
onDone: [
|
|
72
|
+
{
|
|
73
|
+
guard: ({ event }) => event.output.outcome === "exited" && event.output.code === 0,
|
|
74
|
+
target: "passed",
|
|
75
|
+
},
|
|
76
|
+
{ target: "failing" },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
// Not a final state: the run ends `failed`, and the Workspace deletes the Sandbox.
|
|
81
|
+
failing: { invoke: { src: "fail", input: { reason: "npm test did not pass" } } },
|
|
82
|
+
passed: { type: "final" },
|
|
83
|
+
notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
|
|
84
|
+
lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const machine = workspace(body, {
|
|
89
|
+
input: runInput,
|
|
90
|
+
repos: { app: "https://github.com/you/app.git" },
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**See also**
|
|
95
|
+
|
|
96
|
+
- [ADR-0073: A Machine fails a run with `fail()`, and an uncaught Failure ends it `failed`](../decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)
|