@jr2/orchestrator 0.5.1 → 0.7.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/console/components/app.ts +55 -15
- package/console/components/bottom-drawer.ts +259 -0
- package/console/components/drawer.ts +14 -6
- package/console/components/fleet.ts +36 -13
- package/console/components/machine-pane.ts +61 -5
- package/console/components/nav.ts +54 -8
- package/console/conversation.ts +161 -0
- package/console/login.ts +123 -0
- package/console/main.ts +600 -60
- package/console/store.ts +611 -64
- package/console/style.css +231 -0
- package/docs/agents-block.md +2 -2
- package/docs/concepts/agents-and-turns.md +142 -29
- package/docs/concepts/architecture.md +60 -34
- package/docs/concepts/callers-and-hooks.md +205 -0
- package/docs/concepts/charts.md +13 -8
- package/docs/concepts/composition.md +10 -1
- package/docs/concepts/converge.md +7 -2
- package/docs/concepts/durable-runs.md +43 -16
- package/docs/concepts/effects.md +133 -50
- package/docs/concepts/gates.md +95 -25
- package/docs/concepts/machines-and-workflows.md +14 -4
- package/docs/concepts/pools-and-sources.md +193 -17
- package/docs/concepts/secrets-and-trust.md +186 -62
- package/docs/concepts/the-menu.md +14 -0
- package/docs/concepts/workspaces.md +135 -56
- package/docs/get-started/a-model-decides.md +14 -13
- package/docs/get-started/an-agent-in-a-sandbox.md +46 -35
- package/docs/get-started/connect-a-model.md +1 -1
- package/docs/get-started/create-an-instance.md +17 -14
- package/docs/get-started/have-your-assistant-write-a-machine.md +111 -40
- package/docs/get-started/install.md +4 -0
- package/docs/guides/add-tools-to-the-sandbox.md +72 -15
- package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
- package/docs/guides/answer-a-gate.md +74 -37
- package/docs/guides/bind-open-parts.md +29 -12
- package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
- package/docs/guides/cancel-a-run.md +26 -16
- package/docs/guides/cut-a-worktree.md +560 -0
- package/docs/guides/fix-a-failed-converge.md +19 -7
- package/docs/guides/give-a-caller-a-scope.md +203 -0
- package/docs/guides/give-an-agent-mcp-tools.md +422 -0
- package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
- package/docs/guides/let-an-agent-write-a-chart.md +14 -7
- package/docs/guides/look-inside-a-sandbox.md +115 -42
- package/docs/guides/move-from-kind-to-a-shared-cluster.md +16 -0
- package/docs/guides/open-the-console.md +63 -14
- package/docs/guides/push-and-sign-a-branch.md +67 -21
- package/docs/guides/read-a-conversation.md +225 -0
- package/docs/guides/run-a-chart-by-name.md +17 -16
- package/docs/guides/run-a-command-or-call-a-url.md +84 -41
- package/docs/guides/run-one-worker-per-item.md +34 -27
- package/docs/guides/set-an-agents-access-and-dials.md +69 -22
- package/docs/guides/size-a-workspace.md +19 -6
- package/docs/guides/start-a-run-for-each-alert.md +290 -0
- package/docs/guides/start-a-run-from-a-run.md +18 -16
- package/docs/guides/start-a-run.md +24 -18
- package/docs/guides/steer-an-agent.md +332 -0
- package/docs/guides/use-a-hosted-provider.md +7 -1
- package/docs/guides/watch-a-run.md +146 -117
- package/docs/guides/write-a-hook-kind.md +238 -0
- package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
- package/docs/guides/write-a-workflow.md +18 -8
- package/docs/llms.txt +110 -23
- package/docs/reference/authoring-surface/agent.md +35 -12
- package/docs/reference/authoring-surface/answer.md +20 -4
- package/docs/reference/authoring-surface/arg.md +28 -6
- package/docs/reference/authoring-surface/basic.md +1 -1
- package/docs/reference/authoring-surface/bearer.md +1 -1
- package/docs/reference/authoring-surface/branchname.md +15 -0
- package/docs/reference/authoring-surface/carry.md +23 -0
- package/docs/reference/authoring-surface/chartschema.md +1 -1
- package/docs/reference/authoring-surface/chartschemafor.md +1 -1
- package/docs/reference/authoring-surface/command.md +37 -22
- package/docs/reference/authoring-surface/customize.md +4 -1
- package/docs/reference/authoring-surface/defineconfig.md +1 -1
- package/docs/reference/authoring-surface/defineevent.md +1 -1
- package/docs/reference/authoring-surface/dispatch.md +5 -4
- package/docs/reference/authoring-surface/fail.md +18 -5
- package/docs/reference/authoring-surface/file.md +37 -17
- package/docs/reference/authoring-surface/frompick.md +1 -1
- package/docs/reference/authoring-surface/gate.md +118 -0
- package/docs/reference/authoring-surface/group-agents.md +15 -0
- package/docs/reference/authoring-surface/group-charts.md +16 -0
- package/docs/reference/authoring-surface/group-composition.md +25 -0
- package/docs/reference/authoring-surface/group-config.md +17 -0
- package/docs/reference/authoring-surface/group-effects.md +48 -0
- package/docs/reference/authoring-surface/group-failure.md +13 -0
- package/docs/reference/authoring-surface/group-gates.md +16 -0
- package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
- package/docs/reference/authoring-surface/group-steering.md +12 -0
- package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
- package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
- package/docs/reference/authoring-surface/http.md +109 -9
- package/docs/reference/authoring-surface/isfailure.md +1 -1
- package/docs/reference/authoring-surface/isready.md +14 -0
- package/docs/reference/authoring-surface/jr2setup.md +14 -4
- package/docs/reference/authoring-surface/mcp.md +107 -0
- package/docs/reference/authoring-surface/open.md +41 -8
- package/docs/reference/authoring-surface/openbody.md +1 -1
- package/docs/reference/authoring-surface/paramsof.md +23 -5
- package/docs/reference/authoring-surface/pool.md +79 -11
- package/docs/reference/authoring-surface/push.md +31 -13
- package/docs/reference/authoring-surface/readyof.md +21 -0
- package/docs/reference/authoring-surface/reread.md +19 -0
- package/docs/reference/authoring-surface/secret.md +26 -5
- package/docs/reference/authoring-surface/sentby.md +1 -1
- package/docs/reference/authoring-surface/skip.md +22 -0
- package/docs/reference/authoring-surface/source.md +59 -4
- package/docs/reference/authoring-surface/steer.md +93 -0
- package/docs/reference/authoring-surface/text.md +1 -1
- package/docs/reference/authoring-surface/type-agentdefinition.md +16 -3
- package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
- package/docs/reference/authoring-surface/type-agentslots.md +4 -1
- 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-bindactors.md +14 -0
- package/docs/reference/authoring-surface/type-binding.md +6 -7
- package/docs/reference/authoring-surface/type-caller.md +40 -0
- package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
- package/docs/reference/authoring-surface/type-carry.md +19 -0
- package/docs/reference/authoring-surface/type-chainlink.md +3 -3
- package/docs/reference/authoring-surface/type-commandinput.md +4 -3
- package/docs/reference/authoring-surface/type-commandoptions.md +0 -22
- package/docs/reference/authoring-surface/type-commandoutput.md +23 -5
- package/docs/reference/authoring-surface/type-customize.md +20 -3
- package/docs/reference/authoring-surface/type-delivered.md +17 -0
- package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
- package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
- package/docs/reference/authoring-surface/type-dispatchoutput.md +9 -2
- package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
- package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
- package/docs/reference/authoring-surface/type-filebody.md +4 -8
- package/docs/reference/authoring-surface/type-framepath.md +14 -0
- package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
- package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
- package/docs/reference/authoring-surface/type-gatelook.md +37 -0
- package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
- package/docs/reference/authoring-surface/type-gatereply.md +19 -0
- package/docs/reference/authoring-surface/type-gateslot.md +21 -0
- package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
- package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
- package/docs/reference/authoring-surface/type-gateslots.md +12 -0
- package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +3 -5
- package/docs/reference/authoring-surface/type-httpdefinition.md +6 -3
- package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
- package/docs/reference/authoring-surface/type-httpoutput.md +8 -2
- package/docs/reference/authoring-surface/type-jr2config.md +37 -2
- package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
- package/docs/reference/authoring-surface/type-lends.md +5 -1
- package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
- package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
- package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
- package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
- package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
- package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
- package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
- package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
- package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
- package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
- package/docs/reference/authoring-surface/type-namestart.md +77 -0
- package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +1 -6
- package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
- package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
- package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
- package/docs/reference/authoring-surface/type-opencommandinput.md +7 -2
- package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +1 -6
- package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +5 -10
- package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
- package/docs/reference/authoring-surface/type-poolspec.md +11 -6
- package/docs/reference/authoring-surface/type-pushinput.md +22 -3
- package/docs/reference/authoring-surface/type-pushoutput.md +33 -8
- package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
- package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
- package/docs/reference/authoring-surface/type-reposlot.md +6 -6
- package/docs/reference/authoring-surface/type-reread.md +18 -0
- package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
- package/docs/reference/authoring-surface/type-sandboxoptions.md +11 -4
- package/docs/reference/authoring-surface/type-sender.md +26 -1
- package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
- package/docs/reference/authoring-surface/type-size.md +1 -1
- package/docs/reference/authoring-surface/type-skip.md +19 -0
- package/docs/reference/authoring-surface/type-slothandles.md +5 -13
- package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
- package/docs/reference/authoring-surface/type-sourcein.md +25 -0
- package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
- package/docs/reference/authoring-surface/type-sourcespec.md +26 -17
- package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
- package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
- package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
- package/docs/reference/authoring-surface/type-steerargs.md +20 -0
- package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
- package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
- package/docs/reference/authoring-surface/type-workspaced.md +30 -9
- package/docs/reference/authoring-surface/type-workspacehandles.md +5 -6
- package/docs/reference/authoring-surface/type-workspaceoptions.md +1 -13
- 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 +66 -38
- package/docs/reference/authoring-surface/worktree.md +71 -0
- package/docs/reference/authoring-surface.md +88 -147
- package/docs/reference/cli.md +413 -74
- package/docs/reference/config.md +248 -6
- package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +10 -9
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +81 -14
- package/docs/reference/decisions/0004-worktree-provisioning-model.md +27 -21
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +39 -25
- package/docs/reference/decisions/0006-agent-control-surface.md +6 -3
- package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
- package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
- package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
- package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
- package/docs/reference/decisions/0012-workspace-wrapper-machine.md +39 -32
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +54 -30
- package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
- package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +26 -16
- package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +9 -7
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -10
- package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
- package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +53 -27
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +16 -2
- package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
- package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +124 -43
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +36 -38
- package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
- package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +16 -7
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +36 -19
- package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
- package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
- package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -15
- package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
- package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +22 -22
- package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
- package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +13 -12
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +23 -23
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
- package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +57 -46
- package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +5 -0
- package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +20 -8
- package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
- package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
- package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +31 -24
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +18 -10
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +137 -86
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +165 -91
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +7 -7
- package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
- package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +53 -23
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +221 -153
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +161 -96
- package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
- package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +48 -33
- package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
- package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
- package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +1 -1
- package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +296 -0
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +347 -0
- package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
- package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
- package/docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md +198 -0
- package/docs/reference/decisions.md +9 -4
- package/docs/reference/glossary.md +138 -45
- package/docs/reference/hooks.md +1077 -0
- package/docs/reference/http-api.md +988 -123
- package/docs/reference/machines.md +0 -1
- package/docs/why.md +7 -5
- package/package.json +10 -3
- package/src/actor.ts +194 -42
- package/src/agent.ts +56 -6
- package/src/ambient.ts +3 -5
- package/src/assembly-checks.ts +530 -4
- package/src/callers.ts +245 -0
- package/src/chart.ts +238 -26
- package/src/charts.ts +9 -2
- package/src/config.ts +566 -7
- package/src/conversations.ts +453 -0
- package/src/custodian.lua +17 -5
- package/src/custodian.ts +257 -77
- package/src/customize.ts +154 -7
- package/src/dispatch-effect.ts +142 -26
- package/src/durability.ts +2 -0
- package/src/duration.ts +20 -0
- package/src/effect-checks.ts +52 -4
- package/src/effect.ts +401 -132
- package/src/effector-wire.ts +278 -30
- package/src/fail.ts +17 -4
- package/src/gate-brand.ts +16 -0
- package/src/gate.ts +634 -48
- package/src/harness-client.ts +84 -35
- package/src/harness-env.ts +33 -0
- package/src/held-secrets.ts +197 -39
- package/src/holds.ts +5 -2
- package/src/hook-kinds/discord.ts +92 -0
- package/src/hook-kinds/door.ts +107 -0
- package/src/hook-kinds/github.ts +89 -0
- package/src/hook-kinds/gitlab.ts +72 -0
- package/src/hook-kinds/hook.ts +7 -0
- package/src/hook-kinds/index.ts +465 -0
- package/src/hook-kinds/slack.ts +151 -0
- package/src/hook-kinds/webhook.ts +113 -0
- package/src/hooks.ts +506 -0
- package/src/http-effect.ts +164 -70
- package/src/http.ts +933 -99
- package/src/index.ts +30 -5
- package/src/instance.ts +196 -26
- package/src/internal.ts +23 -3
- package/src/kube-client.ts +6 -3
- package/src/machine-doc.ts +29 -5
- package/src/mcp-effect.ts +424 -0
- package/src/model-keys.ts +24 -0
- package/src/mount-digest.ts +41 -7
- package/src/names.ts +82 -7
- package/src/notices.ts +576 -59
- package/src/open-body.ts +110 -30
- package/src/open-effect.ts +17 -4
- package/src/open.ts +40 -7
- package/src/parts.ts +125 -35
- package/src/party.ts +35 -1
- package/src/pick.ts +43 -9
- package/src/pool.ts +1172 -172
- package/src/registration.ts +249 -17
- package/src/repo-identity.ts +7 -3
- package/src/repos.ts +20 -2
- package/src/run-host.ts +1614 -190
- package/src/run-list.ts +191 -0
- package/src/sandbox-effect.ts +217 -66
- package/src/sandbox-kube.ts +116 -21
- package/src/secret-placement.ts +248 -35
- package/src/server.ts +53 -4
- package/src/setup.ts +158 -38
- package/src/snapshot-store.ts +565 -48
- package/src/steer.ts +111 -0
- package/src/stub-harness.ts +6 -2
- package/src/tokens.ts +362 -46
- package/src/vocabulary.ts +23 -4
- package/src/wire.ts +27 -10
- package/src/workspace.ts +314 -259
- package/src/worktree.ts +249 -0
- package/docs/reference/authoring-surface/type-noslotspec.md +0 -26
- package/docs/reference/authoring-surface/type-workspacespec.md +0 -37
- package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
package/src/setup.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { randomUUID } from "node:crypto";
|
|
|
29
29
|
import {
|
|
30
30
|
setup,
|
|
31
31
|
type ActionFunction,
|
|
32
|
+
type ActorLogic,
|
|
32
33
|
type AnyActorRef,
|
|
33
34
|
type AnyStateMachine,
|
|
34
35
|
type DelayConfig,
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
type NonReducibleUnknown,
|
|
40
41
|
type ParameterizedObject,
|
|
41
42
|
type SetupReturn,
|
|
43
|
+
type Snapshot,
|
|
42
44
|
type UnknownActorLogic,
|
|
43
45
|
} from "xstate";
|
|
44
46
|
import type { z } from "zod";
|
|
@@ -46,11 +48,13 @@ import { eventMap, type EventDef, type EventFrom, type Sender } from "@jr2/agent
|
|
|
46
48
|
import type { AgentRunInput, AgentTurnInput, FaultTelemetry } from "./actor.ts";
|
|
47
49
|
import { isAgent } from "./agent.ts";
|
|
48
50
|
import { isEffect } from "./effect.ts";
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
+
import type { AnyFramePath, FramePath, WorktreePath, WorktreeReady } from "./worktree.ts";
|
|
52
|
+
import { effectChecks, refuseUnroutedOutcome } from "./effect-checks.ts";
|
|
53
|
+
import { isGateInvoke } from "./gate-brand.ts";
|
|
54
|
+
import { isGateSlot, plainGate, settlesOnItsOwn, type PlainGate } from "./gate.ts";
|
|
51
55
|
import { attachLent, isOpenBody, openBodyDeclarationOf, type LentParts } from "./open-body.ts";
|
|
52
56
|
import { refuseInlineParts } from "./parts.ts";
|
|
53
|
-
import { partyWarnings, refuseUnknownSentBy, SENT_BY, sentByGuard } from "./party.ts";
|
|
57
|
+
import { partyWarnings, refuseSlotActiveTwice, refuseUnknownSentBy, SENT_BY, sentByGuard } from "./party.ts";
|
|
54
58
|
import { refuseLostOutput } from "./run-output.ts";
|
|
55
59
|
import { refuseUnroutedAgentFault } from "./mechanism-routes.ts";
|
|
56
60
|
import { boundEpoch, boundRunId, continuedIid } from "./registration.ts";
|
|
@@ -109,7 +113,7 @@ type SentByGuards = { [SENT_BY]: { id: string } };
|
|
|
109
113
|
/** The jr2 actor every workflow can invoke by name without listing it (ADR-0015). `gate` is the
|
|
110
114
|
* whole set: an Agent is not pre-registered, because it is not one logic — it is the slot the
|
|
111
115
|
* Machine declares, `actors: { coder: agent(def) }` (ADR-0049). */
|
|
112
|
-
const jr2Actors = { gate };
|
|
116
|
+
const jr2Actors: { gate: PlainGate } = { gate: plainGate };
|
|
113
117
|
type JR2Actors = typeof jr2Actors;
|
|
114
118
|
|
|
115
119
|
/**
|
|
@@ -130,6 +134,74 @@ type ToProvidedActor<TActors extends Record<string, UnknownActorLogic>> = {
|
|
|
130
134
|
[K in keyof TActors & string]: { src: K; logic: TActors[K]; id: string | undefined };
|
|
131
135
|
}[keyof TActors & string];
|
|
132
136
|
|
|
137
|
+
// The types below carry the body's Repo Slots to every Worktree input.
|
|
138
|
+
/** @internal */
|
|
139
|
+
type NoHandles = { readonly noHandles: true };
|
|
140
|
+
/** `S`, the slots of the body, or {@link NoHandles} when its input and context hold no handles.
|
|
141
|
+
* @internal */
|
|
142
|
+
type RepoSlotsOf<TInput, TContext> = TInput extends { workspace: { repos: infer R } }
|
|
143
|
+
? keyof R & string
|
|
144
|
+
: TContext extends { workspace: { repos: infer R } }
|
|
145
|
+
? keyof R & string
|
|
146
|
+
: NoHandles;
|
|
147
|
+
/** The Worktrees of the slots `S` that this key takes: a `push({ slot })` keeps to its own slot.
|
|
148
|
+
* @internal */
|
|
149
|
+
type PathIn<W, S> = S extends string ? (`/work/${S}/x` extends NonNullable<W> ? WorktreePath<S> : never) : never;
|
|
150
|
+
/** One arm of an input. A key that names a Worktree or a Frame is REQUIRED under a body with Repo
|
|
151
|
+
* Slots, so that no mix of `cwd`, `worktree` and `path` lands in `/work`. Under a body with none,
|
|
152
|
+
* `worktree` goes: there is no Worktree. A Turn's arm that carries no kit path (the run's own form)
|
|
153
|
+
* and every other key stay.
|
|
154
|
+
* @internal */
|
|
155
|
+
type BindArm<I, S> = I extends object
|
|
156
|
+
? "worktree" extends keyof I
|
|
157
|
+
? [S] extends [never]
|
|
158
|
+
? Omit<I, "worktree"> & { worktree?: never }
|
|
159
|
+
: Omit<I, "worktree"> & { worktree: PathIn<I["worktree"], S> }
|
|
160
|
+
: "cwd" extends keyof I
|
|
161
|
+
? [NonNullable<I["cwd"]>] extends [AnyFramePath]
|
|
162
|
+
? [S] extends [never]
|
|
163
|
+
? I
|
|
164
|
+
: Omit<I, "cwd"> & { cwd: FramePath<S & string> }
|
|
165
|
+
: I
|
|
166
|
+
: "path" extends keyof I
|
|
167
|
+
? [S] extends [never]
|
|
168
|
+
? I
|
|
169
|
+
: Omit<I, "path"> & { path: PathIn<I["path"], S> }
|
|
170
|
+
: I
|
|
171
|
+
: I;
|
|
172
|
+
/** Does this input name a Worktree? @internal */
|
|
173
|
+
type NamesWorktree<I> = I extends object ? ("worktree" extends keyof I ? true : never) : never;
|
|
174
|
+
/** @internal */
|
|
175
|
+
type BindInput<I, S> = [NamesWorktree<I>] extends [never]
|
|
176
|
+
? BindArm<I, S>
|
|
177
|
+
: [S] extends [never]
|
|
178
|
+
? BindArm<I, S>
|
|
179
|
+
: Exclude<BindArm<I, S>, void | undefined>;
|
|
180
|
+
/** A cut's `ready` output with the body's slots. @internal */
|
|
181
|
+
type BindOutput<O, S> = O extends WorktreeReady ? WorktreeReady<S & string> : O;
|
|
182
|
+
/** @internal */
|
|
183
|
+
type BindSnapshot<Snap, S> = Snap extends { output: infer O }
|
|
184
|
+
? [O] extends [BindOutput<O, S>]
|
|
185
|
+
? Snap
|
|
186
|
+
: Omit<Snap, "output"> & { output: BindOutput<O, S> }
|
|
187
|
+
: Snap;
|
|
188
|
+
/** @internal */
|
|
189
|
+
type BindLogic<L extends UnknownActorLogic, S> = L extends AnyStateMachine
|
|
190
|
+
? L
|
|
191
|
+
: ([S] extends [never] ? false : [S] extends [NoHandles] ? true : false) extends true
|
|
192
|
+
? L
|
|
193
|
+
: L extends { readonly definition: { readonly workspace: "none" } }
|
|
194
|
+
? L
|
|
195
|
+
: L extends ActorLogic<infer Snap, infer Ev, infer I, infer Sys, infer Em>
|
|
196
|
+
? BindSnapshot<Snap, S> extends infer B extends Snapshot<unknown>
|
|
197
|
+
? Omit<L, keyof ActorLogic<Snap, Ev, I, Sys, Em>> & ActorLogic<B, Ev, BindInput<I, S>, any, Em>
|
|
198
|
+
: never
|
|
199
|
+
: L;
|
|
200
|
+
/** @internal */
|
|
201
|
+
type BindActors<A extends Record<string, UnknownActorLogic>, TInput, TContext> = {
|
|
202
|
+
[K in keyof A]: BindLogic<A[K], RepoSlotsOf<TInput, TContext>>;
|
|
203
|
+
};
|
|
204
|
+
|
|
133
205
|
/**
|
|
134
206
|
* Set up a Machine that takes workflow events: the jr2 form of xstate's `setup()`. Write a Machine
|
|
135
207
|
* with it when an Agent or a Gate sends events into the Machine, or when the Machine declares a
|
|
@@ -141,7 +213,9 @@ type ToProvidedActor<TActors extends Record<string, UnknownActorLogic>> = {
|
|
|
141
213
|
* `defineEvent` events you list, plus the events jr2 itself sends (`agent.fault`,
|
|
142
214
|
* `workspace.lost`). An event that a party sent has `event.sender`. A Machine that takes no
|
|
143
215
|
* workflow event leaves out `events`.
|
|
144
|
-
* - The `gate` actor is ready to invoke by name: `invoke: { src: "gate" }`.
|
|
216
|
+
* - The `gate` actor is ready to invoke by name: `invoke: { src: "gate" }`. A Gate slot that hears a
|
|
217
|
+
* Hook (`actors: { review: gate({ … }) }`) is invoked by its key. An event in its `delivers` whose
|
|
218
|
+
* def leaves `audience` unset is `audience: "external"` in this Machine.
|
|
145
219
|
* - Each Agent slot (`actors: { coder: agent(…) }`) gets its Menu from the states that invoke it.
|
|
146
220
|
* - The `sentBy(id)` guard is ready to use.
|
|
147
221
|
* - `createMachine` also takes `input`: a zod object for the input that starts a run. jr2 checks
|
|
@@ -198,6 +272,13 @@ type ToProvidedActor<TActors extends Record<string, UnknownActorLogic>> = {
|
|
|
198
272
|
* run an Agent`: the body sends it a Chart's unrouted `agent.fault`. When both kinds have no route,
|
|
199
273
|
* one line names both, joined by `, and`. One route on the root is a route for each state. A
|
|
200
274
|
* Chart's Machine does not get this refusal: in a Chart the route is optional (ADR-0070).
|
|
275
|
+
* - an event in a Gate slot's `delivers` that `events` does not list: ``machine "<id>": Gate slot
|
|
276
|
+
* "<slot>" delivers "<name>", which no def in jr2Setup({ events }) declares (declared: <names>) —
|
|
277
|
+
* list it in events (ADR-0011)``
|
|
278
|
+
* - an event in a Gate slot's `delivers` that the Gate does not accept at a state that invokes it:
|
|
279
|
+
* ``machine "<id>": state "<state>" invokes Gate slot "<slot>", which delivers "<name>", and its
|
|
280
|
+
* Gate does not accept it (accepts: <names>) — no handler or look could deliver it: handle it on
|
|
281
|
+
* that state, a state above it or a plain child, or drop it from delivers (ADR-0011)``
|
|
201
282
|
*
|
|
202
283
|
* It also refuses a `sentBy` that names no party (see `sentBy`). It refuses a pick param that
|
|
203
284
|
* nothing reads, where the pick enters a state that invokes an Effect (see `fromPick`). Shapes that
|
|
@@ -287,7 +368,8 @@ export function jr2Setup<
|
|
|
287
368
|
* listed, if it is not a jr2 or xstate event (an event with a `.` in its name). */
|
|
288
369
|
events?: TDefs;
|
|
289
370
|
/** The actors the states invoke by name, as in `setup()`: Agent slots (`agent(…)`), Effects
|
|
290
|
-
* (`command(…)`, `http(…)`, `push(…)`), child Machines, `workspace(…)`
|
|
371
|
+
* (`command(…)`, `http(…)`, `push(…)`), Gate slots (`gate({ … })`), child Machines, `workspace(…)`
|
|
372
|
+
* and plain xstate logic.
|
|
291
373
|
* The key is the slot's name. An actor named `gate` replaces jr2's Gate. */
|
|
292
374
|
actors?: TActors;
|
|
293
375
|
/** Named actions, as in `setup()`. Their `event` has the type of this Machine's events. */
|
|
@@ -321,7 +403,7 @@ export function jr2Setup<
|
|
|
321
403
|
): SetupReturn<
|
|
322
404
|
TContext,
|
|
323
405
|
WorkflowEvent<TDefs>,
|
|
324
|
-
MergedActors<TActors
|
|
406
|
+
MergedActors<BindActors<TActors, TInput, TContext>>,
|
|
325
407
|
{},
|
|
326
408
|
TActions,
|
|
327
409
|
TGuards & SentByGuards,
|
|
@@ -358,6 +440,10 @@ export function jr2Setup<
|
|
|
358
440
|
// Resolve the defs first (duplicates and reserved semantics fail HERE, naming the machine —
|
|
359
441
|
// the same loud failure `eventMap` gave the manifest, moved to machine-build time)…
|
|
360
442
|
const defs = eventMap((machineConfig as { id?: string }).id ?? "(machine)", def.events ?? []);
|
|
443
|
+
// A Gate slot's `delivers` (ADR-0011, ADR-0015): each name is one of this Machine's events, and
|
|
444
|
+
// one whose def leaves the audience unset reads as `external`, so no Agent has a Hook's event on
|
|
445
|
+
// its Menu. Before the Menus derive, so the walk, the Menu and the runtime read one vocabulary.
|
|
446
|
+
externalDelivers((machineConfig as { id?: string }).id ?? "(machine)", defs, def.actors ?? {});
|
|
361
447
|
|
|
362
448
|
// Every Open body slot (ADR-0070), found by its brand: each name it lends resolves against THIS
|
|
363
449
|
// setup's own parts, or the Machine is refused naming it. The resolved set is stamped on the slot,
|
|
@@ -370,6 +456,12 @@ export function jr2Setup<
|
|
|
370
456
|
// ADR-0007 restore path and invoke-time `resolveAccepts` validation are unchanged.
|
|
371
457
|
const derived = deriveMenus(machineConfig, defs, def.actors ?? {});
|
|
372
458
|
const machine = (inner.createMachine as unknown as (c: never) => AnyStateMachine)(derived.config as never);
|
|
459
|
+
// A Gate slot's event that its state's Gate does not accept (ADR-0011): no handler or look could
|
|
460
|
+
// ever deliver it.
|
|
461
|
+
if (derived.refused.length) {
|
|
462
|
+
const idOf = (path: readonly string[]): string => stateAt(machine, path).id;
|
|
463
|
+
throw new Error(`machine "${machine.id}": ${derived.refused.map((r) => r(idOf)).join("; ")}`);
|
|
464
|
+
}
|
|
373
465
|
|
|
374
466
|
// Close the nested-`on` typo hole (ADR-0015): with the manifest dead, a typo'd key would
|
|
375
467
|
// silently become vocabulary — so every non-dotted key the machine handles anywhere must map
|
|
@@ -411,13 +503,20 @@ export function jr2Setup<
|
|
|
411
503
|
// (ADR-0074): the run would wait for ever. Not in a compiled Chart: there the route is optional,
|
|
412
504
|
// and the Open body sends the event that no transition takes to the Machine that invoked it (ADR-0070).
|
|
413
505
|
if (compiledChart !== true) refuseUnroutedAgentFault(machine);
|
|
506
|
+
// An Effect's `onDone` with no last arm that always matches (ADR-0075): the run would stay in the
|
|
507
|
+
// state and show no fault. A compiled Chart comes here too, so the door refuses it.
|
|
508
|
+
refuseUnroutedOutcome(machine);
|
|
414
509
|
refuseParallelBelowAgents(machine, def.actors ?? {});
|
|
510
|
+
// One slot, two Turns at once (ADR-0015): one sender and one conversation cannot hold both.
|
|
511
|
+
refuseSlotActiveTwice(machine);
|
|
415
512
|
refuseUnknownSentBy(machine);
|
|
416
513
|
// Before the Effect checks: they ask who may send a writing (`mayTake`), which reads its audience.
|
|
417
514
|
attachVocabulary(machine, defs);
|
|
418
515
|
// The Effect checks (ADR-0067): a pick param nothing reads, a `fill` that overwrites one, a
|
|
419
516
|
// `fromPick` of another pick — refused; a mapper the probe cannot run — warned.
|
|
420
|
-
|
|
517
|
+
// A Chart's door reads each reference itself (rule 7), and it refuses every load warning: the
|
|
518
|
+
// walk's "I could not run this" says nothing of a Chart's `{{...}}` mapper or its `set`.
|
|
519
|
+
const effects = effectChecks(machine, def.actors ?? {}, defs, compiledChart === true);
|
|
421
520
|
if (effects.errors.length) throw new Error(`machine "${machine.id}": ${effects.errors.join("; ")}`);
|
|
422
521
|
|
|
423
522
|
const idOf = (path: readonly string[]): string => stateAt(machine, path).id;
|
|
@@ -441,7 +540,7 @@ export function jr2Setup<
|
|
|
441
540
|
return { ...inner, createMachine } as unknown as SetupReturn<
|
|
442
541
|
TContext,
|
|
443
542
|
WorkflowEvent<TDefs>,
|
|
444
|
-
MergedActors<TActors
|
|
543
|
+
MergedActors<BindActors<TActors, TInput, TContext>>,
|
|
445
544
|
{},
|
|
446
545
|
TActions,
|
|
447
546
|
TGuards & SentByGuards,
|
|
@@ -525,7 +624,7 @@ function deriveMenus(
|
|
|
525
624
|
config: unknown,
|
|
526
625
|
defs: Map<string, EventDef>,
|
|
527
626
|
actors: Record<string, UnknownActorLogic>,
|
|
528
|
-
): { config: unknown; seats: Seat[]; warnings: Warning[]; derivedGateIds: Set<string
|
|
627
|
+
): { config: unknown; seats: Seat[]; warnings: Warning[]; derivedGateIds: Set<string>; refused: Warning[] } {
|
|
529
628
|
const pick = (reach: Reach, kind: "agent" | "external", self: string): string[] =>
|
|
530
629
|
[...reach]
|
|
531
630
|
.filter(([name, owners]) => {
|
|
@@ -545,6 +644,8 @@ function deriveMenus(
|
|
|
545
644
|
const parties = new Map<string, { agents: string[]; gate: boolean }>();
|
|
546
645
|
// The Gate invoke ids this walk names: a party warning says how to name one instead.
|
|
547
646
|
const derivedGateIds = new Set<string>();
|
|
647
|
+
// A Gate slot's `delivers` that its state's Gate does not accept (ADR-0011): refusals.
|
|
648
|
+
const refused: Warning[] = [];
|
|
548
649
|
|
|
549
650
|
const walk = (
|
|
550
651
|
node: LooseState,
|
|
@@ -567,7 +668,7 @@ function deriveMenus(
|
|
|
567
668
|
const invokes = Array.isArray(node.invoke) ? node.invoke : [node.invoke];
|
|
568
669
|
// >1 unnamed gate in one state would collide on the state-key id; suffix ONLY then, so
|
|
569
670
|
// the common case (one gate per state) keeps the clean name.
|
|
570
|
-
const unnamedGates = invokes.filter((inv) => inv
|
|
671
|
+
const unnamedGates = invokes.filter((inv) => isGateInvoke(inv, actors) && inv.id == null).length;
|
|
571
672
|
let ordinal = 0;
|
|
572
673
|
const wrapOne = (inv: LooseInvoke): LooseInvoke => {
|
|
573
674
|
// The slot key IS the Agent name (ADR-0049) — read off the declaration, never authored.
|
|
@@ -600,7 +701,7 @@ function deriveMenus(
|
|
|
600
701
|
seats.push({ path, party: "agent", agent: inv.src, names: [...derived].sort() });
|
|
601
702
|
return { ...inv, input: wrapAgentInput(inv.input, derived, inv.src, menuOf) };
|
|
602
703
|
}
|
|
603
|
-
if (inv
|
|
704
|
+
if (isGateInvoke(inv, actors)) {
|
|
604
705
|
// A Gate's plain children — below it, with no party-invoking state between — are its own
|
|
605
706
|
// by position, as an Agent's modes are its (ADR-0015).
|
|
606
707
|
const reach: Reach = new Map([...names].map(([name, owners]) => [name, new Set(owners)]));
|
|
@@ -608,6 +709,20 @@ function deriveMenus(
|
|
|
608
709
|
reach.set(name, (reach.get(name) ?? new Set<string>()).add(owner));
|
|
609
710
|
const accepts = pick(reach, "external", owner);
|
|
610
711
|
seats.push({ path, party: "gate", names: [...accepts].sort() });
|
|
712
|
+
const slot = typeof inv.src === "string" ? actors[inv.src] : undefined;
|
|
713
|
+
if (isGateSlot(slot)) {
|
|
714
|
+
const outside = slot.gateSlot.delivers.map((d) => d.name).filter((name) => !accepts.includes(name));
|
|
715
|
+
if (outside.length) {
|
|
716
|
+
const name = inv.src as string;
|
|
717
|
+
refused.push(
|
|
718
|
+
(idOf) =>
|
|
719
|
+
`state "${idOf(path)}" invokes Gate slot "${name}", which delivers ${outside.map((n) => `"${n}"`).join(", ")}, ` +
|
|
720
|
+
`and its Gate does not accept ${outside.length > 1 ? "them" : "it"} (accepts: ${accepts.join(", ") || "nothing"}) — ` +
|
|
721
|
+
"no handler or look could deliver it: handle it on that state, a state above it or a plain child, " +
|
|
722
|
+
"or drop it from delivers (ADR-0011)",
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
611
726
|
const wrapped: LooseInvoke = { ...inv, input: wrapGateInput(inv.input, accepts) };
|
|
612
727
|
// A machine-root gate (empty path) is left to xstate's default id: a `""` id would be
|
|
613
728
|
// worse than a noisy one, and the derived gate id still works.
|
|
@@ -632,7 +747,7 @@ function deriveMenus(
|
|
|
632
747
|
};
|
|
633
748
|
|
|
634
749
|
const out = walk(config as LooseState, new Map(), new Map(), [], NOBODY);
|
|
635
|
-
return { config: out, seats, warnings: [...warnings.values()], derivedGateIds };
|
|
750
|
+
return { config: out, seats, warnings: [...warnings.values()], derivedGateIds, refused };
|
|
636
751
|
}
|
|
637
752
|
|
|
638
753
|
/**
|
|
@@ -767,7 +882,7 @@ function unenteredModes(machine: AnyStateMachine, actors: Record<string, Unknown
|
|
|
767
882
|
continue;
|
|
768
883
|
}
|
|
769
884
|
const party = child.invoke.some(
|
|
770
|
-
(inv) => inv
|
|
885
|
+
(inv) => isGateInvoke(inv, actors) || (typeof inv.src === "string" && isAgent(actors[inv.src])),
|
|
771
886
|
);
|
|
772
887
|
if (!party) descend(child);
|
|
773
888
|
continue;
|
|
@@ -790,27 +905,6 @@ function unenteredModes(machine: AnyStateMachine, actors: Record<string, Unknown
|
|
|
790
905
|
return out;
|
|
791
906
|
}
|
|
792
907
|
|
|
793
|
-
/**
|
|
794
|
-
* Does this logic settle on its own — a promise, the one plain xstate actor that ends without being
|
|
795
|
-
* stopped? Asked of its own transition: a promise logic's initial snapshot, sent xstate's resolve
|
|
796
|
-
* event, is `done`. That event name is an xstate internal (5.32.2); a bump that renamed it would
|
|
797
|
-
* make every promise read long-lived, and setup.test.ts pins it against the real constructors.
|
|
798
|
-
*/
|
|
799
|
-
function settlesOnItsOwn(logic: unknown): boolean {
|
|
800
|
-
const l = logic as {
|
|
801
|
-
getInitialSnapshot?: (scope: unknown, input: unknown) => unknown;
|
|
802
|
-
transition?: (snapshot: unknown, event: unknown, scope: unknown) => { status?: string } | undefined;
|
|
803
|
-
};
|
|
804
|
-
if (typeof l?.getInitialSnapshot !== "function" || typeof l.transition !== "function") return false;
|
|
805
|
-
try {
|
|
806
|
-
const scope = { self: {}, defer: () => {}, emit: () => {} };
|
|
807
|
-
const snapshot = l.getInitialSnapshot(scope, undefined);
|
|
808
|
-
return l.transition(snapshot, { type: "xstate.promise.resolve", data: undefined }, scope)?.status === "done";
|
|
809
|
-
} catch {
|
|
810
|
-
return false;
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
|
|
814
908
|
/**
|
|
815
909
|
* The load walk's Rest warnings (ADR-0024): shapes below an Agent's state that keep it from Rest, so
|
|
816
910
|
* every pick of the Agent is refused for longer than the author likely meant. Warnings, never
|
|
@@ -840,7 +934,7 @@ function restWarnings(machine: AnyStateMachine, actors: Record<string, UnknownAc
|
|
|
840
934
|
for (const inv of child.invoke) {
|
|
841
935
|
const logic = logicOf(inv.src);
|
|
842
936
|
const name = typeof inv.src === "string" ? inv.src : inv.id;
|
|
843
|
-
if (inv
|
|
937
|
+
if (isGateInvoke(inv, actors)) {
|
|
844
938
|
for (const [event, candidates] of child.transitions) {
|
|
845
939
|
if (event.includes(".") || event === "*") continue;
|
|
846
940
|
if (candidates.some((t) => (t.target ?? []).length > 0)) continue;
|
|
@@ -904,6 +998,7 @@ function stampOpenBodies(
|
|
|
904
998
|
["agents", "an Agent slot (agent(...))", isAgent],
|
|
905
999
|
["effects", "an Effect slot", isEffect],
|
|
906
1000
|
["machines", "a Machine", (l: unknown) => (l as { root?: unknown } | undefined)?.root !== undefined],
|
|
1001
|
+
["gates", "a Gate slot (gate({ … }))", isGateSlot],
|
|
907
1002
|
] as const;
|
|
908
1003
|
for (const [kind, what, test] of actorKinds) {
|
|
909
1004
|
for (const name of decl.lends[kind] ?? []) {
|
|
@@ -974,6 +1069,29 @@ function stateAt(machine: AnyStateMachine, path: readonly string[]): AnyStateMac
|
|
|
974
1069
|
return node;
|
|
975
1070
|
}
|
|
976
1071
|
|
|
1072
|
+
/**
|
|
1073
|
+
* The `delivers` of each Gate slot this setup declares (ADR-0011, ADR-0015). Each name must be an
|
|
1074
|
+
* event of the Machine: a handler or a look gives a plain event, which the Machine's own def parses.
|
|
1075
|
+
* An event whose def leaves the audience unset reads as `audience: "external"` in this Machine's
|
|
1076
|
+
* vocabulary, so no Agent of the Machine has it on its Menu, and the author does not have to know
|
|
1077
|
+
* this. An explicit audience stays.
|
|
1078
|
+
*/
|
|
1079
|
+
function externalDelivers(machineId: string, defs: Map<string, EventDef>, actors: Record<string, unknown>): void {
|
|
1080
|
+
for (const [slot, logic] of Object.entries(actors)) {
|
|
1081
|
+
if (!isGateSlot(logic)) continue;
|
|
1082
|
+
for (const d of logic.gateSlot.delivers) {
|
|
1083
|
+
const own = defs.get(d.name);
|
|
1084
|
+
if (!own) {
|
|
1085
|
+
throw new Error(
|
|
1086
|
+
`machine "${machineId}": Gate slot "${slot}" delivers "${d.name}", which no def in jr2Setup({ events }) ` +
|
|
1087
|
+
`declares (declared: ${[...defs.keys()].join(", ") || "none"}) — list it in events (ADR-0011)`,
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
if (own.audience === undefined) defs.set(d.name, Object.freeze({ ...own, audience: "external" as const }));
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
977
1095
|
/** A state's own workflow-event keys: dotted names are jr2's or xstate's, `*` is the wildcard. */
|
|
978
1096
|
function ownPicks(node: LooseState): string[] {
|
|
979
1097
|
return Object.keys(node.on ?? {}).filter((key) => !key.includes(".") && key !== "*");
|
|
@@ -984,7 +1102,7 @@ function partiesOf(node: LooseState, actors: Record<string, UnknownActorLogic>):
|
|
|
984
1102
|
const invokes = node.invoke ? (Array.isArray(node.invoke) ? node.invoke : [node.invoke]) : [];
|
|
985
1103
|
return {
|
|
986
1104
|
agents: invokes.flatMap((inv) => (typeof inv?.src === "string" && isAgent(actors[inv.src]) ? [inv.src] : [])),
|
|
987
|
-
gate: invokes.some((inv) => inv
|
|
1105
|
+
gate: invokes.some((inv) => isGateInvoke(inv, actors)),
|
|
988
1106
|
};
|
|
989
1107
|
}
|
|
990
1108
|
|
|
@@ -1066,7 +1184,7 @@ function refuseUnknownKeys(consumer: object, agentName: string): void {
|
|
|
1066
1184
|
/** Wrap an Agent slot's invoke input: name the Agent (the slot key), append the state's derived set
|
|
1067
1185
|
* and the Agent's Menu, and finalize the mechanism fields. */
|
|
1068
1186
|
function wrapAgentInput(orig: unknown, derived: string[], agentName: string, menuOf: (agentName: string) => string[]) {
|
|
1069
|
-
|
|
1187
|
+
const wrapped = (args: InputArgs): AgentRunInput => {
|
|
1070
1188
|
const consumer = resolveInput(orig, args) as Partial<AgentTurnInput & AgentRunInput>;
|
|
1071
1189
|
refuseUnknownKeys(consumer, agentName);
|
|
1072
1190
|
return {
|
|
@@ -1097,6 +1215,8 @@ function wrapAgentInput(orig: unknown, derived: string[], agentName: string, men
|
|
|
1097
1215
|
menu: menuOf(agentName),
|
|
1098
1216
|
};
|
|
1099
1217
|
};
|
|
1218
|
+
// The walk reads what the author wrote: `workspace()`, for a literal `cwd`.
|
|
1219
|
+
return Object.assign(wrapped, { consumerInput: orig });
|
|
1100
1220
|
}
|
|
1101
1221
|
|
|
1102
1222
|
/** Wrap a gate invoke input: append the derived accepted set. */
|