@jr2/orchestrator 0.4.1 → 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/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 +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 +5 -3
- package/src/actor.ts +541 -79
- package/src/agent.ts +114 -38
- package/src/ambient.ts +2 -1
- package/src/assembly-checks.ts +189 -7
- package/src/cause.ts +234 -0
- package/src/chart.ts +169 -37
- package/src/charts.ts +34 -6
- package/src/config.ts +430 -178
- package/src/custodian.ts +74 -22
- package/src/customize.ts +188 -46
- package/src/dispatch-effect.ts +945 -0
- package/src/door-compat.ts +217 -0
- package/src/durability.ts +11 -4
- package/src/effect.ts +341 -44
- package/src/effector-wire.ts +160 -11
- package/src/fail.ts +209 -0
- package/src/harness-client.ts +541 -47
- package/src/http-effect.ts +495 -53
- package/src/http.ts +427 -16
- package/src/index.ts +60 -82
- package/src/instance.ts +68 -8
- package/src/internal.ts +84 -0
- package/src/machine-doc.ts +21 -3
- package/src/mechanism-routes.ts +168 -0
- package/src/model-keys.generated.ts +53 -0
- package/src/model-keys.ts +18 -58
- package/src/notices.ts +66 -13
- package/src/open-body.ts +159 -23
- package/src/open-effect.ts +81 -8
- package/src/open.ts +59 -6
- package/src/parts.ts +184 -13
- package/src/party.ts +68 -2
- package/src/pick.ts +463 -11
- package/src/pool.ts +247 -36
- package/src/registration.ts +83 -4
- package/src/repos.ts +2 -1
- package/src/run-host.ts +565 -31
- package/src/run-output.ts +38 -0
- package/src/sandbox-effect.ts +273 -38
- package/src/sandbox-kube.ts +3 -1
- package/src/secret-placement.ts +52 -17
- package/src/server.ts +3 -0
- package/src/setup.ts +239 -56
- 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/vocabulary.ts +69 -14
- package/src/wire.ts +90 -16
- package/src/workspace.ts +697 -175
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Run a command or call a URL with an Effect
|
|
3
|
+
description: Run a program or call a URL as an Effect, give it input from a pick, and route on its output.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run a command or call a URL with an Effect
|
|
7
|
+
|
|
8
|
+
Run a program in the [Workspace](../reference/glossary.md#workspace), or call a URL, as an
|
|
9
|
+
[Effect](../reference/glossary.md#effect), and route the [Machine](../reference/glossary.md#machine) on its output.
|
|
10
|
+
|
|
11
|
+
Put the Effect under `actors` in [`jr2Setup`](../reference/authoring-surface/jr2setup.md), beside the
|
|
12
|
+
[Agents](../reference/glossary.md#agent). Then invoke it by its key from a state, and route on its output in `onDone`.
|
|
13
|
+
In this [Workflow](../reference/glossary.md#workflow), a coder fixes the tests. It picks `run_test` to run one test file
|
|
14
|
+
with a [`command`](../reference/authoring-surface/command.md) Effect. When it picks `finished`, an
|
|
15
|
+
[`http`](../reference/authoring-surface/http.md) Effect posts its summary to a URL. Save the file as
|
|
16
|
+
`workflows/fix-and-report.ts` in your [Instance](../reference/glossary.md#instance):
|
|
17
|
+
|
|
18
|
+
**Anthropic**
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import {
|
|
23
|
+
agent,
|
|
24
|
+
answer,
|
|
25
|
+
arg,
|
|
26
|
+
bearer,
|
|
27
|
+
command,
|
|
28
|
+
defineEvent,
|
|
29
|
+
fail,
|
|
30
|
+
fromPick,
|
|
31
|
+
http,
|
|
32
|
+
jr2Setup,
|
|
33
|
+
secret,
|
|
34
|
+
workspace,
|
|
35
|
+
type CommandOutput,
|
|
36
|
+
type Workspaced,
|
|
37
|
+
} from "@jr2/orchestrator";
|
|
38
|
+
|
|
39
|
+
const runTest = defineEvent({
|
|
40
|
+
name: "run_test",
|
|
41
|
+
description: "Run one test file. The answer tells if it passes.",
|
|
42
|
+
input: z.object({ file: z.string() }),
|
|
43
|
+
});
|
|
44
|
+
const finished = defineEvent({
|
|
45
|
+
name: "finished",
|
|
46
|
+
description: "Call this when the tests pass and you committed the fix. Say what you changed.",
|
|
47
|
+
input: z.object({ summary: z.string() }),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const runInput = z.object({ prompt: z.string(), branch: z.string() });
|
|
51
|
+
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
|
|
52
|
+
|
|
53
|
+
const passed = (output: CommandOutput): boolean => output.outcome === "exited" && output.code === 0;
|
|
54
|
+
|
|
55
|
+
const body = jr2Setup({
|
|
56
|
+
types: {} as { input: BodyInput; context: BodyInput },
|
|
57
|
+
events: [runTest, finished],
|
|
58
|
+
actors: {
|
|
59
|
+
coder: agent({
|
|
60
|
+
model: "anthropic/claude-haiku-5-5",
|
|
61
|
+
instructions: "You fix failing tests. You change no test. You commit the fix.",
|
|
62
|
+
}),
|
|
63
|
+
// One program, with no shell. arg("file") is one argument, from the input of the Effect.
|
|
64
|
+
test: command(["node", "--test", arg("file")], { timeout: "5m" }),
|
|
65
|
+
// A call to a fixed URL. The Effector puts the value of the secret in the header.
|
|
66
|
+
report: http({
|
|
67
|
+
method: "POST",
|
|
68
|
+
url: "https://hooks.example.com/jr2",
|
|
69
|
+
auth: bearer(secret("hook-token")),
|
|
70
|
+
input: z.object({ branch: z.string(), summary: z.string() }),
|
|
71
|
+
request: ({ branch, summary }) => ({ json: { text: `${branch}: ${summary}` } }),
|
|
72
|
+
}),
|
|
73
|
+
// Fail the run: the end for work that did not succeed.
|
|
74
|
+
fail: fail(),
|
|
75
|
+
},
|
|
76
|
+
}).createMachine({
|
|
77
|
+
id: "fix-and-report",
|
|
78
|
+
context: ({ input }) => input,
|
|
79
|
+
on: { "workspace.lost": ".lost" },
|
|
80
|
+
initial: "coding",
|
|
81
|
+
states: {
|
|
82
|
+
coding: {
|
|
83
|
+
invoke: {
|
|
84
|
+
src: "coder",
|
|
85
|
+
input: ({ context }) => ({ prompt: context.prompt, cwd: context.workspace.repos.app }),
|
|
86
|
+
},
|
|
87
|
+
on: {
|
|
88
|
+
finished: "reporting",
|
|
89
|
+
// A Turn of the coder failed with no pick. Without this route, the run stays in `coding`.
|
|
90
|
+
"agent.fault": "failed",
|
|
91
|
+
},
|
|
92
|
+
initial: "ready",
|
|
93
|
+
states: {
|
|
94
|
+
ready: { on: { run_test: "testing" } },
|
|
95
|
+
testing: {
|
|
96
|
+
invoke: {
|
|
97
|
+
src: "test",
|
|
98
|
+
// The `file` of the pick goes to the arg("file") of the command.
|
|
99
|
+
input: fromPick(runTest),
|
|
100
|
+
onDone: {
|
|
101
|
+
target: "ready",
|
|
102
|
+
// The Agent reads this text as the answer to its run_test pick.
|
|
103
|
+
actions: answer(({ event }) =>
|
|
104
|
+
passed(event.output)
|
|
105
|
+
? "The test passes."
|
|
106
|
+
: `The test fails:\n${"tail" in event.output ? event.output.tail : event.output.reason}`,
|
|
107
|
+
),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
reporting: {
|
|
114
|
+
invoke: {
|
|
115
|
+
src: "report",
|
|
116
|
+
// The Agent gives `summary`. The Machine gives `branch`.
|
|
117
|
+
input: fromPick(finished, ({ context }) => ({ branch: context.workspace.branch })),
|
|
118
|
+
onDone: [
|
|
119
|
+
{ guard: ({ event }) => event.output.outcome === "response" && event.output.status < 300, target: "done" },
|
|
120
|
+
{ target: "notReported" },
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
done: { type: "final" },
|
|
125
|
+
// Not final states: a final state means `done`. Each one fails the run, and the run ends `failed`.
|
|
126
|
+
notReported: { invoke: { src: "fail", input: { reason: "the report did not go out" } } },
|
|
127
|
+
failed: { invoke: { src: "fail", input: { reason: "the coder could not go on" } } },
|
|
128
|
+
lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost" } } },
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
export const machine = workspace(body, {
|
|
133
|
+
input: runInput,
|
|
134
|
+
repos: { app: "https://github.com/<you>/app.git" },
|
|
135
|
+
spec: ({ input }) => ({ branch: input.branch }),
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Local**
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
import { z } from "zod";
|
|
143
|
+
import {
|
|
144
|
+
agent,
|
|
145
|
+
answer,
|
|
146
|
+
arg,
|
|
147
|
+
bearer,
|
|
148
|
+
command,
|
|
149
|
+
defineEvent,
|
|
150
|
+
fail,
|
|
151
|
+
fromPick,
|
|
152
|
+
http,
|
|
153
|
+
jr2Setup,
|
|
154
|
+
secret,
|
|
155
|
+
workspace,
|
|
156
|
+
type CommandOutput,
|
|
157
|
+
type Workspaced,
|
|
158
|
+
} from "@jr2/orchestrator";
|
|
159
|
+
|
|
160
|
+
const runTest = defineEvent({
|
|
161
|
+
name: "run_test",
|
|
162
|
+
description: "Run one test file. The answer tells if it passes.",
|
|
163
|
+
input: z.object({ file: z.string() }),
|
|
164
|
+
});
|
|
165
|
+
const finished = defineEvent({
|
|
166
|
+
name: "finished",
|
|
167
|
+
description: "Call this when the tests pass and you committed the fix. Say what you changed.",
|
|
168
|
+
input: z.object({ summary: z.string() }),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const runInput = z.object({ prompt: z.string(), branch: z.string() });
|
|
172
|
+
type BodyInput = Workspaced<z.infer<typeof runInput>, "app">;
|
|
173
|
+
|
|
174
|
+
const passed = (output: CommandOutput): boolean => output.outcome === "exited" && output.code === 0;
|
|
175
|
+
|
|
176
|
+
const body = jr2Setup({
|
|
177
|
+
types: {} as { input: BodyInput; context: BodyInput },
|
|
178
|
+
events: [runTest, finished],
|
|
179
|
+
actors: {
|
|
180
|
+
coder: agent({
|
|
181
|
+
model: "local/qwen3.6-35b-a3b",
|
|
182
|
+
instructions: "You fix failing tests. You change no test. You commit the fix.",
|
|
183
|
+
}),
|
|
184
|
+
// One program, with no shell. arg("file") is one argument, from the input of the Effect.
|
|
185
|
+
test: command(["node", "--test", arg("file")], { timeout: "5m" }),
|
|
186
|
+
// A call to a fixed URL. The Effector puts the value of the secret in the header.
|
|
187
|
+
report: http({
|
|
188
|
+
method: "POST",
|
|
189
|
+
url: "https://hooks.example.com/jr2",
|
|
190
|
+
auth: bearer(secret("hook-token")),
|
|
191
|
+
input: z.object({ branch: z.string(), summary: z.string() }),
|
|
192
|
+
request: ({ branch, summary }) => ({ json: { text: `${branch}: ${summary}` } }),
|
|
193
|
+
}),
|
|
194
|
+
// Fail the run: the end for work that did not succeed.
|
|
195
|
+
fail: fail(),
|
|
196
|
+
},
|
|
197
|
+
}).createMachine({
|
|
198
|
+
id: "fix-and-report",
|
|
199
|
+
context: ({ input }) => input,
|
|
200
|
+
on: { "workspace.lost": ".lost" },
|
|
201
|
+
initial: "coding",
|
|
202
|
+
states: {
|
|
203
|
+
coding: {
|
|
204
|
+
invoke: {
|
|
205
|
+
src: "coder",
|
|
206
|
+
input: ({ context }) => ({ prompt: context.prompt, cwd: context.workspace.repos.app }),
|
|
207
|
+
},
|
|
208
|
+
on: {
|
|
209
|
+
finished: "reporting",
|
|
210
|
+
// A Turn of the coder failed with no pick. Without this route, the run stays in `coding`.
|
|
211
|
+
"agent.fault": "failed",
|
|
212
|
+
},
|
|
213
|
+
initial: "ready",
|
|
214
|
+
states: {
|
|
215
|
+
ready: { on: { run_test: "testing" } },
|
|
216
|
+
testing: {
|
|
217
|
+
invoke: {
|
|
218
|
+
src: "test",
|
|
219
|
+
// The `file` of the pick goes to the arg("file") of the command.
|
|
220
|
+
input: fromPick(runTest),
|
|
221
|
+
onDone: {
|
|
222
|
+
target: "ready",
|
|
223
|
+
// The Agent reads this text as the answer to its run_test pick.
|
|
224
|
+
actions: answer(({ event }) =>
|
|
225
|
+
passed(event.output)
|
|
226
|
+
? "The test passes."
|
|
227
|
+
: `The test fails:\n${"tail" in event.output ? event.output.tail : event.output.reason}`,
|
|
228
|
+
),
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
reporting: {
|
|
235
|
+
invoke: {
|
|
236
|
+
src: "report",
|
|
237
|
+
// The Agent gives `summary`. The Machine gives `branch`.
|
|
238
|
+
input: fromPick(finished, ({ context }) => ({ branch: context.workspace.branch })),
|
|
239
|
+
onDone: [
|
|
240
|
+
{ guard: ({ event }) => event.output.outcome === "response" && event.output.status < 300, target: "done" },
|
|
241
|
+
{ target: "notReported" },
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
done: { type: "final" },
|
|
246
|
+
// Not final states: a final state means `done`. Each one fails the run, and the run ends `failed`.
|
|
247
|
+
notReported: { invoke: { src: "fail", input: { reason: "the report did not go out" } } },
|
|
248
|
+
failed: { invoke: { src: "fail", input: { reason: "the coder could not go on" } } },
|
|
249
|
+
lost: { invoke: { src: "fail", input: { reason: "the Sandbox was lost" } } },
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
export const machine = workspace(body, {
|
|
254
|
+
input: runInput,
|
|
255
|
+
repos: { app: "https://github.com/<you>/app.git" },
|
|
256
|
+
spec: ({ input }) => ({ branch: input.branch }),
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The `coding` state routes [`agent.fault`](../reference/mechanism-events.md#agent-fault) to `failed`. jr2 sends it when a
|
|
261
|
+
Turn of the coder fails with no pick. Each state that invokes an Agent has a route for it, on the state or on a state
|
|
262
|
+
above it: `jr2 check` refuses a Machine without one. When no transition takes the event, the run ends `error`.
|
|
263
|
+
|
|
264
|
+
`failed`, `notReported` and `lost` are not final states. Each one invokes
|
|
265
|
+
[`fail`](../reference/authoring-surface/fail.md), and the run ends `failed` with its reason: a final state means `done`.
|
|
266
|
+
Do not throw from a promise to fail, because a throw is a defect, and the run ends `error`.
|
|
267
|
+
|
|
268
|
+
Write your GitHub user name in place of `<you>`. The Agent uses the model of the tab. `https://hooks.example.com/jr2` is
|
|
269
|
+
an example. Write the URL of your own service.
|
|
270
|
+
|
|
271
|
+
The `http` Effect names the [Effect secret](../reference/glossary.md#effect-secret) `hook-token`. Add it to the
|
|
272
|
+
[`secrets`](../reference/config.md#secrets) list of `jr2.config.ts`, beside the entries that are there:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import { defineConfig } from "@jr2/orchestrator";
|
|
276
|
+
|
|
277
|
+
export default defineConfig({
|
|
278
|
+
// An Effect secret: secret("hook-token") names it. The value comes from HOOK_TOKEN in .env.
|
|
279
|
+
secrets: [{ name: "hook-token", value: process.env.HOOK_TOKEN }],
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The file shows only the `secrets` field. Keep the other fields and entries of your `jr2.config.ts`.
|
|
284
|
+
|
|
285
|
+
Then put the value in `.env`:
|
|
286
|
+
|
|
287
|
+
```sh
|
|
288
|
+
HOOK_TOKEN=<token>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
`<token>` is the token of your service. It has 8 characters or more.
|
|
292
|
+
|
|
293
|
+
## Run a command
|
|
294
|
+
|
|
295
|
+
`command(argv, options)` runs one program. `argv` is a list, and each entry is one argument. jr2 starts `argv[0]` with
|
|
296
|
+
no shell. An [`arg("name")`](../reference/authoring-surface/arg.md) entry is one argument that the input of the Effect
|
|
297
|
+
fills, whatever its characters. To use a shell, write it in the argv: `["sh", "-c", "<script>"]`.
|
|
298
|
+
|
|
299
|
+
The options:
|
|
300
|
+
|
|
301
|
+
- `timeout`: how long the program can run, such as `"90s"`, `"10m"` or `"1h"`. The default is `"10m"`. After it, jr2
|
|
302
|
+
kills the process group, and the outcome is `timeout`.
|
|
303
|
+
- `tail`: how many characters of the end of the output the Machine gets. The default is 4096.
|
|
304
|
+
- `slot`: the [Repo Slot](../reference/glossary.md#repo-slot) whose [Worktree](../reference/glossary.md#worktree) the
|
|
305
|
+
program runs in. Write it only when the Workspace has more than one Repo Slot.
|
|
306
|
+
|
|
307
|
+
The program starts in the root of the Worktree. In a Workspace with no Repo Slot, it starts in `/work`, the folder that
|
|
308
|
+
the steps of the Workspace share (see [Workspaces](../concepts/workspaces.md#a-workspace-with-no-repo)). To run it in a
|
|
309
|
+
subfolder, give the path as an argument, such as `["node", "--test", "<dir>/test/*.test.js"]`, or write
|
|
310
|
+
`["sh", "-c", "cd <dir> && <program>"]`.
|
|
311
|
+
|
|
312
|
+
A `command` with no Effect secret runs in the [Harness](../reference/glossary.md#harness) container of the
|
|
313
|
+
[Sandbox](../reference/glossary.md#sandbox), in the Worktree, beside the
|
|
314
|
+
[Working tools](../reference/glossary.md#working-tools) of the Agent. It uses the tools of the
|
|
315
|
+
[Sandbox Image](../reference/glossary.md#sandbox-image). Thus invoke it in the body of a
|
|
316
|
+
[`workspace()`](../reference/authoring-surface/workspace.md).
|
|
317
|
+
|
|
318
|
+
Each outcome is output for `onDone`, also a failure. Route on `outcome`
|
|
319
|
+
([`CommandOutput`](../reference/authoring-surface/type-commandoutput.md)):
|
|
320
|
+
|
|
321
|
+
- `exited`, with `code` and `tail`. A test that fails is `exited` with a `code` that is not 0. A program that the
|
|
322
|
+
container does not have is `exited` with code 127.
|
|
323
|
+
- `timeout`, with `tail`.
|
|
324
|
+
- `killed`, with `signal` and `tail`.
|
|
325
|
+
- `unknown`, with `reason`: jr2 cannot tell what the program did. jr2 does not run it again.
|
|
326
|
+
|
|
327
|
+
## Use an Effect secret in a command
|
|
328
|
+
|
|
329
|
+
A program that needs a credential gets it from the `env` option. Each value is an Effect secret, for example
|
|
330
|
+
`env: { NODE_AUTH_TOKEN: secret("npm-token") }`. [`secret("<name>")`](../reference/authoring-surface/secret.md) gives
|
|
331
|
+
the value. `secret("<name>").path` gives the path of a file that holds the value. The name is an entry of the `secrets`
|
|
332
|
+
list of `jr2.config.ts`, as for `hook-token`.
|
|
333
|
+
|
|
334
|
+
A `command` with an Effect secret in `env` does not run beside the Agent. It runs in the
|
|
335
|
+
[Sandbox Effector](../reference/glossary.md#sandbox-effector), a container that the Agent cannot reach. It runs against
|
|
336
|
+
one commit of the branch, not against the live Worktree:
|
|
337
|
+
|
|
338
|
+
- By default, the commit is the tip of the branch when the Effect starts. When the Worktree holds changes that the
|
|
339
|
+
program did not see, its output has `dirty: true`.
|
|
340
|
+
- With `pin: true`, the commit is the `sha` of the input of the Effect: `{ sha: "<full commit id>" }`. Use it for a
|
|
341
|
+
commit that a [Gate](../reference/glossary.md#gate) approved.
|
|
342
|
+
|
|
343
|
+
The Sandbox Effector runs in the Sandbox Image, or in the image of the `effector` option of `workspace()`. Thus that
|
|
344
|
+
image must hold the program.
|
|
345
|
+
|
|
346
|
+
## Call a URL
|
|
347
|
+
|
|
348
|
+
`http(definition)` makes one call to a URL. The definition fixes all of the call except what `request` makes:
|
|
349
|
+
|
|
350
|
+
- `method`: `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` or `OPTIONS`.
|
|
351
|
+
- `url`: `http://` or `https://`, then a literal host. An Effect secret can be only in the path, in a
|
|
352
|
+
[`text`](../reference/authoring-surface/text.md) template:
|
|
353
|
+
`` text`https://api.example.com/bot${secret("<name>")}/send` ``.
|
|
354
|
+
- `auth`: the `Authorization` header. Use [`bearer(secret("<name>"))`](../reference/authoring-surface/bearer.md),
|
|
355
|
+
[`basic(user, password)`](../reference/authoring-surface/basic.md), or a `text` that is the full value.
|
|
356
|
+
- `headers`: the headers that are the same for each run. Each name is in lower case. A value is a string, a
|
|
357
|
+
`secret("<name>")` or a `text`.
|
|
358
|
+
- `input`: the zod schema of the input of the Effect. jr2 parses the input with it before the call.
|
|
359
|
+
- `request`: a function of the input. It gives the `path` segments that jr2 adds to the URL, and a `json` or a `text`
|
|
360
|
+
body. It cannot change the host, a header or an Effect secret.
|
|
361
|
+
- `timeout`: how long jr2 waits for the answer. The default is `"30s"`. After it, the outcome is `unknown`.
|
|
362
|
+
- `maxBody`: how many bytes of a text body the output keeps. The default is 65536.
|
|
363
|
+
- `idempotent`: `true` when a second call is safe. The default is `false`. See [Effects](../concepts/effects.md).
|
|
364
|
+
|
|
365
|
+
To send a file of the Worktree as the body, use [`file(path)`](../reference/authoring-surface/file.md) as `body`. In a
|
|
366
|
+
Workspace with no Repo Slot, the path is relative to `/work`. jr2 sends a file body only with `PUT`, `POST` or `PATCH`.
|
|
367
|
+
|
|
368
|
+
An `http` Effect runs in the [Instance Effector](../reference/glossary.md#instance-effector). The
|
|
369
|
+
[Effector](../reference/glossary.md#effector) puts the value of each Effect secret into the call. The Agent never reads
|
|
370
|
+
the value. You can invoke an `http` Effect in a Machine with no Workspace. An `http` Effect with a file body runs in the
|
|
371
|
+
Sandbox Effector, so invoke it in the body of a `workspace()`.
|
|
372
|
+
|
|
373
|
+
Each outcome is output for `onDone`. Route on `outcome`
|
|
374
|
+
([`HttpOutput`](../reference/authoring-surface/type-httpoutput.md)):
|
|
375
|
+
|
|
376
|
+
- `response`, with `status`, `headers`, `contentType`, `size` and, for a text body, `body`. A 4xx or 5xx status is a
|
|
377
|
+
`response` too. The example goes to `done` only for a status below 300.
|
|
378
|
+
- `unreachable`: the call did not go out.
|
|
379
|
+
- `refused`: jr2 or the Effector refused the call, and sent nothing.
|
|
380
|
+
- `unknown`: the call can have gone out, but no answer came.
|
|
381
|
+
|
|
382
|
+
## Give the input from a pick
|
|
383
|
+
|
|
384
|
+
The input of an Effect is the `input` of the invoke. When a pick of the Agent enters the state, the input can come from
|
|
385
|
+
the params of the pick:
|
|
386
|
+
|
|
387
|
+
- [`fromPick(def)`](../reference/authoring-surface/frompick.md) gives each param of the pick to the key of the same
|
|
388
|
+
name. In the `testing` state, the `file` of `run_test` goes to `arg("file")`.
|
|
389
|
+
- `fromPick(def, fill)` adds the keys that `fill` gives. In the `reporting` state, the Agent gives `summary`, and the
|
|
390
|
+
Machine gives `branch`. Thus the Agent cannot choose the branch in the report.
|
|
391
|
+
- [`paramsOf(event, def)`](../reference/authoring-surface/paramsof.md) reads the params in a plain `input` function. Use
|
|
392
|
+
it when the Machine changes a param before the Effect gets it.
|
|
393
|
+
|
|
394
|
+
Each param of a pick that enters an Effect's state must go somewhere: to a key of the Effect's input, to `fill`, or to
|
|
395
|
+
the context with `assign`. `createMachine` refuses a param that nothing reads, because the Agent gives it and nothing
|
|
396
|
+
uses it. The compiler does not find this error. `jr2 check` and `jr2 up` find it when they load the module. Thus when
|
|
397
|
+
you copy `finished` with its `summary` into a Machine that does not send or keep the summary, drop `summary` from the
|
|
398
|
+
`input` of the event. [Rules](#rules) gives the text of each refusal.
|
|
399
|
+
|
|
400
|
+
TypeScript checks the keys of the pick and of `fill` against the input of the Effect. When the Agent's state holds the
|
|
401
|
+
Effect, the Agent waits for the answer to its pick. [`answer(fn)`](../reference/authoring-surface/answer.md) sets that
|
|
402
|
+
answer. In the `testing` state, the Agent reads one line, or the end of the test output. Without `answer`, it reads the
|
|
403
|
+
`CommandOutput` of the command, as JSON.
|
|
404
|
+
|
|
405
|
+
## What jr2 up shows
|
|
406
|
+
|
|
407
|
+
Run [`jr2 up`](../reference/cli.md#up). It reads each Effect without running it, and it shows what the Effect runs, and
|
|
408
|
+
where. It also shows where each Effect secret goes:
|
|
409
|
+
|
|
410
|
+
```sh
|
|
411
|
+
jr2 up
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
```text
|
|
415
|
+
…
|
|
416
|
+
effects: workflow "fix-and-report" — what it runs outside itself (ADR-0067)
|
|
417
|
+
test: command ["node","--test","<file>"] — 300s, in the Harness
|
|
418
|
+
report: http POST https://hooks.example.com — 30s, in the Instance Effector, secrets "hook-token"
|
|
419
|
+
failures: workflow "fix-and-report" — the states that fail the run (ADR-0073)
|
|
420
|
+
fix-and-report.notReported: invokes fail
|
|
421
|
+
fix-and-report.failed: invokes fail
|
|
422
|
+
fix-and-report.lost: invokes fail
|
|
423
|
+
…
|
|
424
|
+
secret hook-token: an Effect secret in the Instance Effector (fix-and-report/report)
|
|
425
|
+
…
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
`<file>` is the `arg("file")` entry. Each time is in seconds. `failures` lists each state that can end the run `failed`.
|
|
429
|
+
|
|
430
|
+
## Rules
|
|
431
|
+
|
|
432
|
+
When you call `command()`, it refuses:
|
|
433
|
+
|
|
434
|
+
- an empty argv: `command(argv): argv is a non-empty list — each entry one argument, never shell text`
|
|
435
|
+
- an entry that is not a string or an `arg()`: `command(argv): an argv entry is a string or arg("name"), got <entry>`
|
|
436
|
+
- a timeout that is not a positive duration:
|
|
437
|
+
`command: timeout "<timeout>" is not a positive duration (like "90s", "10m", "1h")`
|
|
438
|
+
- an `env` name that is not a variable name, or that is `PATH`, `HOME` or `TMPDIR`:
|
|
439
|
+
`command(argv, { env }): "<name>" is not a variable the author sets — PATH, HOME and TMPDIR are the Effector's (ADR-0067)`
|
|
440
|
+
- `pin: true` with no Effect secret in `env`:
|
|
441
|
+
``command(argv, { pin: true }) names no secret in its env: `pin` chooses the commit a credentialed command runs against in the Sandbox Effector, and a command that names no secret runs in the live Worktree (ADR-0067) — name its secret, command(argv, { env: { NAME: secret("x") }, pin: true }), or drop `pin` ``
|
|
442
|
+
|
|
443
|
+
When a `command` starts, it refuses:
|
|
444
|
+
|
|
445
|
+
- a state outside a `workspace()`. With no Effect secret in `env`:
|
|
446
|
+
`command "<slot>" runs in the Harness container of a Workspace, and its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`.
|
|
447
|
+
With one:
|
|
448
|
+
`command "<slot>" runs in the Sandbox Effector of a Workspace, and its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
|
|
449
|
+
- no `slot` under a Workspace with more than one Repo Slot:
|
|
450
|
+
`command "<slot>" runs under a Workspace carrying more than one Repo Slot (<slots>) and names none — say which Worktree it runs in: command(argv, { slot: "<slot>" }) (ADR-0051)`.
|
|
451
|
+
With an Effect secret in `env`, the text is
|
|
452
|
+
`command "<slot>" runs under a Workspace carrying more than one Repo Slot (<slots>) — say which: { slot: "<slot>" } (ADR-0051)`
|
|
453
|
+
- with an Effect secret in `env`, a Workspace with no Repo Slot:
|
|
454
|
+
`command "<slot>" runs under a Workspace with no Repo Slot: a command with an Effect secret runs against one commit of a Repo Slot's branch, and there is none — declare a Repo Slot, or name no secret in its env, and it runs in /work beside the Agent (ADR-0051)`
|
|
455
|
+
- a `slot` that the Workspace does not have:
|
|
456
|
+
`command "<slot>" names Repo Slot "<name>", which its Workspace does not carry (<slots>)`
|
|
457
|
+
- an `arg()` with no string in the input. The angle brackets around the name are in the text, and `<type>` is `nothing`
|
|
458
|
+
when the input has no such key:
|
|
459
|
+
`command "<slot>": argv slot <<name>> has no string value in its input (got <type>) — map it in the invoke's input`
|
|
460
|
+
- with `pin: true`, an input `sha` that is not a full commit id:
|
|
461
|
+
`command "<slot>" (pin): its input's sha is not a full commit id`
|
|
462
|
+
|
|
463
|
+
When you call `http()`, it refuses:
|
|
464
|
+
|
|
465
|
+
- a method that is not in the list:
|
|
466
|
+
`http({ method: "<method>" }): the method is one of GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`
|
|
467
|
+
- a scheme or a host that is not literal:
|
|
468
|
+
``http({ url }): the url is an http:// or https:// url whose scheme and host are literal — a secret may sit only in its path, after a "/": text`https://api.example.com/bot${secret("tg")}/send` (ADR-0068)``
|
|
469
|
+
- an Effect secret after `?` or `#` in the URL:
|
|
470
|
+
``http({ url }): secret("<name>") sits in the url's query or fragment — a secret may sit only in its path; send it in `auth` or a header instead: headers: { "x-api-key": text`${secret("...")}` } (ADR-0068)``
|
|
471
|
+
- a user name or a password in the URL: ``http({ url }): the url carries userinfo — use `auth` ``
|
|
472
|
+
- a header name that is not in lower case, or that frames or routes the request, such as `host` or `content-length`:
|
|
473
|
+
`http({ headers }): "<name>" is not a header an Effect sets — a lowercase name that does not frame or route the request (ADR-0068)`
|
|
474
|
+
- an `authorization` header beside `auth`: ``http({ headers }): "authorization" is set by `auth` — write one of them``
|
|
475
|
+
- a timeout that is not a positive duration: `http: timeout "<timeout>" is not a positive duration (like "30s", "2m")`
|
|
476
|
+
- a `maxBody` that is not a positive whole number: `http({ maxBody }): a positive number of bytes`
|
|
477
|
+
- a file body with a method other than `PUT`, `POST` or `PATCH`:
|
|
478
|
+
`http({ method: "<method>", body: file(...) }): a file body is sent with PUT, POST, PATCH (ADR-0068)`
|
|
479
|
+
- a `body` that is not `file()`:
|
|
480
|
+
``http({ body }): a body is file(path, { slot?, segments?, contentType? }) — json and text come from `request` ``
|
|
481
|
+
- a `content-type` header beside the `contentType` of `file()`:
|
|
482
|
+
`http({ headers, body: file(path, { contentType }) }): "content-type" is set by file()'s contentType — write one of them (ADR-0067)`
|
|
483
|
+
- a `request` with a file body:
|
|
484
|
+
``http({ body: file(...), request }): with a file body the run's part is file()'s — its path, from the input if it must be, and its `segments` — so write no `request` (ADR-0068)``
|
|
485
|
+
- a URL whose host is not a host: `http({ url }): "<scheme>://<host>" is not a host`
|
|
486
|
+
|
|
487
|
+
When an `http` Effect starts, it refuses an input that its `input` schema does not accept. The Effect takes its
|
|
488
|
+
`onError` route, and each problem is `<path>: <message>`, with `; ` between them:
|
|
489
|
+
`http "<slot>": its input does not match the definition's input schema — <path>: <message>`. With a file body, the text
|
|
490
|
+
ends after `input schema`.
|
|
491
|
+
|
|
492
|
+
An `http` Effect with a file body runs in the Sandbox Effector. When it starts, it refuses a state outside a
|
|
493
|
+
`workspace()`:
|
|
494
|
+
`http "<slot>" runs in the Sandbox Effector of a Workspace, and its state is not inside a workspace() — invoke it from a Workspace's body (ADR-0067)`
|
|
495
|
+
|
|
496
|
+
When you call `secret()`, `bearer()` or `text`, they refuse:
|
|
497
|
+
|
|
498
|
+
- an Effect secret name with characters other than letters, digits, `.`, `_` and `-`, or that starts with `.`:
|
|
499
|
+
`secret("<name>"): a secret's name is letters, digits, ".", "_" and "-", and does not start with "." — it is the file the Effector reads it from (ADR-0068)`
|
|
500
|
+
- a `bearer()` value that is not a `secret()`: `bearer(…) takes a secret("name")`
|
|
501
|
+
- a `text` value that is not a `secret()` or a string: ``text`…`: a value is a secret("name") or a string, got <value>``
|
|
502
|
+
|
|
503
|
+
`createMachine` refuses:
|
|
504
|
+
|
|
505
|
+
- an Effect that you write directly in an `invoke`:
|
|
506
|
+
`machine "<id>": state "<state>" invokes an Effect inline — a Part is a key of actors, so it has a name that the ledger, the report and customize() share: actors: { <name>: <kind>(...) }, then invoke: { src: "<name>" }`
|
|
507
|
+
- a param of a pick that reaches no key of the Effect's input, and that nothing else reads:
|
|
508
|
+
``machine "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>") with fromPick: "<param>" is no key of the Effect's input (<keys>), and nothing else reads it — the Agent supplies it and it reaches nothing; name an argv slot for it, read it in `fill`, store it with assign, or drop it from the def``
|
|
509
|
+
- a key that `fill` sets and that is also a param of the pick:
|
|
510
|
+
``machine "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>"): `fill` sets "<param>", which is also a param of the pick — the Machine's value wins and the Agent's is dropped; rename one, or drop it from the def``
|
|
511
|
+
- a `fromPick` in a state that a different event enters:
|
|
512
|
+
`machine "<id>": state "<state>" (Effect "<slot>") reads the params of pick "<pick>" but is entered on "<event>" — that event does not carry them`
|
|
513
|
+
- a param of a pick that enters an Effect's state with no `fromPick`, when nothing reads it:
|
|
514
|
+
`machine "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>"), which never reads "<param>": the Agent supplies it and nothing uses it — map it in an invoke's input, store it with assign, or drop it from the def`
|
|
515
|
+
|
|
516
|
+
[`paramsOf()`](../reference/authoring-surface/paramsof.md) refuses an event that is not the pick:
|
|
517
|
+
`state entered by "<event>", but its input reads the params of pick "<pick>"`
|
|
518
|
+
|
|
519
|
+
`jr2 up` refuses:
|
|
520
|
+
|
|
521
|
+
- a `command` with an Effect secret in a Workspace with no Repo Slot:
|
|
522
|
+
`workflow "<workflow>": command "<slot>" runs in Workspace of workflow "<workflow>", which has no Repo Slot: a command with an Effect secret runs against one commit of a Repo Slot's branch, and there is none — declare a Repo Slot, or name no secret in its env, and it runs in /work beside the Agent (ADR-0051)`
|
|
523
|
+
- an Effect secret that the `secrets` list does not have:
|
|
524
|
+
``workflow "<workflow>": the <kind> Effect "<slot>" names secret("<name>"), which the `secrets` list does not hold — add it: secrets: [{ name: "<name>", value: process.env.<NAME> }] (ADR-0068)``
|
|
525
|
+
- an Effect secret with no value, for example when `HOOK_TOKEN` is not in `.env`. `<name>` is the `name` of the entry,
|
|
526
|
+
such as `hook-token`. Set the variable that `process.env` reads, such as `HOOK_TOKEN`:
|
|
527
|
+
`secrets[<i>] needs exactly one of value or valueFrom — <name> has neither, which is what an unset .env variable reads as: set <name> in .env, or reference a Secret with valueFrom: { secretKeyRef: { name, key } } (ADR-0059)`
|
|
528
|
+
- an Effect secret with a value shorter than 8 characters:
|
|
529
|
+
`secrets[<i>] (<name>) is an Effect secret shorter than 8 characters — the Effector replaces every match of a secret in what it returns, and a value this short would match ordinary text. Use the whole credential; the value itself is not shown (ADR-0068)`
|
|
530
|
+
|
|
531
|
+
## Read next
|
|
532
|
+
|
|
533
|
+
- [Effects](../concepts/effects.md): the kinds of Effect, where each runs, and at most once.
|
|
534
|
+
- [Secrets and trust](../concepts/secrets-and-trust.md): who holds an Effect secret.
|
|
535
|
+
- [The Menu](../concepts/the-menu.md): how a pick waits for its answer.
|
|
536
|
+
- [Push and sign a branch](push-and-sign-a-branch.md): the `push` Effect.
|
|
537
|
+
- Reference: [`command`](../reference/authoring-surface/command.md),
|
|
538
|
+
[`CommandOptions`](../reference/authoring-surface/type-commandoptions.md),
|
|
539
|
+
[`http`](../reference/authoring-surface/http.md), [`secret`](../reference/authoring-surface/secret.md),
|
|
540
|
+
[`fromPick`](../reference/authoring-surface/frompick.md) and [`answer`](../reference/authoring-surface/answer.md).
|
|
541
|
+
- [ADR-0067](../reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md):
|
|
542
|
+
an Effect is an actor slot, and runs at most once unless marked idempotent.
|
|
543
|
+
- [ADR-0068](../reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md): an Effector holds
|
|
544
|
+
the secrets of an Effect, and signs its wire.
|