@jr2/orchestrator 0.6.0 → 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 +86 -9
- package/docs/concepts/architecture.md +41 -28
- package/docs/concepts/callers-and-hooks.md +205 -0
- package/docs/concepts/charts.md +7 -5
- package/docs/concepts/composition.md +10 -1
- package/docs/concepts/converge.md +4 -2
- package/docs/concepts/durable-runs.md +43 -16
- package/docs/concepts/effects.md +50 -22
- package/docs/concepts/gates.md +95 -25
- package/docs/concepts/machines-and-workflows.md +5 -4
- package/docs/concepts/pools-and-sources.md +187 -11
- package/docs/concepts/secrets-and-trust.md +73 -33
- package/docs/concepts/the-menu.md +11 -0
- package/docs/concepts/workspaces.md +6 -5
- package/docs/get-started/a-model-decides.md +14 -13
- package/docs/get-started/an-agent-in-a-sandbox.md +43 -34
- package/docs/get-started/connect-a-model.md +1 -1
- package/docs/get-started/create-an-instance.md +17 -14
- package/docs/guides/add-tools-to-the-sandbox.md +55 -11
- 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 +24 -8
- 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/fix-a-failed-converge.md +18 -6
- 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 +9 -6
- package/docs/guides/look-inside-a-sandbox.md +101 -31
- package/docs/guides/open-the-console.md +63 -14
- package/docs/guides/read-a-conversation.md +225 -0
- package/docs/guides/run-a-chart-by-name.md +17 -16
- package/docs/guides/run-one-worker-per-item.md +15 -9
- package/docs/guides/set-an-agents-access-and-dials.md +2 -0
- 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 +1 -1
- package/docs/guides/watch-a-run.md +127 -121
- 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 +17 -7
- package/docs/llms.txt +81 -15
- package/docs/reference/authoring-surface/agent.md +1 -1
- package/docs/reference/authoring-surface/answer.md +1 -1
- package/docs/reference/authoring-surface/arg.md +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/file.md +1 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/isfailure.md +1 -1
- package/docs/reference/authoring-surface/isready.md +1 -1
- package/docs/reference/authoring-surface/jr2setup.md +13 -3
- package/docs/reference/authoring-surface/mcp.md +107 -0
- package/docs/reference/authoring-surface/open.md +5 -3
- package/docs/reference/authoring-surface/openbody.md +1 -1
- package/docs/reference/authoring-surface/paramsof.md +1 -1
- package/docs/reference/authoring-surface/pool.md +77 -9
- package/docs/reference/authoring-surface/push.md +1 -1
- package/docs/reference/authoring-surface/readyof.md +1 -1
- package/docs/reference/authoring-surface/reread.md +19 -0
- package/docs/reference/authoring-surface/secret.md +1 -1
- 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 +56 -1
- 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 +14 -1
- package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
- package/docs/reference/authoring-surface/type-anyframepath.md +1 -1
- package/docs/reference/authoring-surface/type-anyworktreepath.md +1 -1
- package/docs/reference/authoring-surface/type-binding.md +1 -1
- 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-commandoutput.md +1 -1
- package/docs/reference/authoring-surface/type-customize.md +16 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
- package/docs/reference/authoring-surface/type-framepath.md +1 -1
- 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 +1 -1
- package/docs/reference/authoring-surface/type-httpoutput.md +1 -1
- package/docs/reference/authoring-surface/type-jr2config.md +37 -2
- package/docs/reference/authoring-surface/type-lateroutcome.md +1 -1
- 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-openbodydeclaration.md +1 -1
- package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
- package/docs/reference/authoring-surface/type-poolnextinput.md +1 -1
- package/docs/reference/authoring-surface/type-poolspec.md +11 -6
- package/docs/reference/authoring-surface/type-pushoutput.md +1 -1
- 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 +1 -1
- 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-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-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 +16 -7
- 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 +1 -1
- package/docs/reference/authoring-surface/type-worktreefound.md +3 -3
- package/docs/reference/authoring-surface/type-worktreeinput.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeoptions.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeoutput.md +1 -1
- package/docs/reference/authoring-surface/type-worktreepath.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeready.md +1 -1
- package/docs/reference/authoring-surface/type-worktreerefused.md +4 -4
- package/docs/reference/authoring-surface/workspace.md +1 -1
- package/docs/reference/authoring-surface/worktree.md +1 -1
- package/docs/reference/authoring-surface.md +88 -167
- package/docs/reference/cli.md +413 -74
- package/docs/reference/config.md +235 -2
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +71 -11
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +14 -10
- package/docs/reference/decisions/0006-agent-control-surface.md +4 -4
- 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 +9 -2
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +20 -14
- 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 +18 -14
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -12
- 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 +32 -18
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +14 -1
- 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 +116 -34
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +38 -37
- 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 +7 -6
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +23 -7
- 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 -18
- 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 +4 -3
- 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 +5 -4
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +19 -19
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
- 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 +7 -0
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +13 -7
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +38 -30
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +64 -17
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +2 -1
- 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 +51 -23
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +94 -54
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +101 -47
- 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 +17 -13
- 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/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +4 -3
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +37 -10
- 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 +6 -4
- package/docs/reference/glossary.md +96 -42
- package/docs/reference/hooks.md +1077 -0
- package/docs/reference/http-api.md +976 -149
- package/docs/why.md +2 -1
- package/package.json +10 -3
- package/src/actor.ts +36 -10
- package/src/agent.ts +50 -0
- package/src/assembly-checks.ts +530 -4
- package/src/callers.ts +245 -0
- package/src/chart.ts +52 -7
- package/src/config.ts +550 -1
- package/src/conversations.ts +453 -0
- package/src/custodian.ts +8 -2
- package/src/customize.ts +143 -4
- package/src/dispatch-effect.ts +142 -26
- package/src/durability.ts +2 -0
- package/src/duration.ts +20 -0
- package/src/effect-checks.ts +2 -1
- package/src/effect.ts +60 -7
- package/src/effector-wire.ts +272 -27
- package/src/gate-brand.ts +16 -0
- package/src/gate.ts +634 -48
- package/src/harness-client.ts +10 -4
- package/src/held-secrets.ts +72 -23
- package/src/holds.ts +2 -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 +76 -38
- package/src/http.ts +889 -94
- package/src/index.ts +16 -5
- package/src/instance.ts +196 -26
- package/src/internal.ts +22 -3
- package/src/machine-doc.ts +26 -1
- package/src/mcp-effect.ts +424 -0
- package/src/mount-digest.ts +41 -7
- package/src/names.ts +64 -2
- package/src/notices.ts +138 -10
- package/src/open-body.ts +25 -11
- package/src/open-effect.ts +17 -4
- package/src/open.ts +4 -2
- package/src/parts.ts +87 -9
- package/src/party.ts +2 -1
- package/src/pick.ts +2 -2
- package/src/pool.ts +1142 -163
- package/src/registration.ts +203 -13
- package/src/run-host.ts +1509 -171
- package/src/run-list.ts +191 -0
- package/src/sandbox-kube.ts +53 -5
- package/src/secret-placement.ts +239 -33
- package/src/server.ts +53 -4
- package/src/setup.ts +72 -32
- package/src/snapshot-store.ts +565 -48
- package/src/steer.ts +111 -0
- package/src/stub-harness.ts +6 -2
- package/src/tokens.ts +263 -22
- package/src/wire.ts +17 -0
- package/src/workspace.ts +50 -6
- package/src/worktree.ts +3 -3
- 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/registration.ts
CHANGED
|
@@ -28,9 +28,11 @@ import { getStateNodes } from "xstate";
|
|
|
28
28
|
import type { ActorSystem, AnyActorRef, AnyEventObject, AnyMachineSnapshot, AnyStateMachine } from "xstate";
|
|
29
29
|
import { SENDER_KEY, type EventDef, type Sender } from "@jr2/agent-protocol";
|
|
30
30
|
import type { AgentAdmission } from "./actor.ts";
|
|
31
|
+
import type { CallerRecord } from "./callers.ts";
|
|
32
|
+
import type { AnyHandler, GateSlotParts } from "./gate.ts";
|
|
31
33
|
import type { EffectMarker, EffectRow } from "./effect.ts";
|
|
32
34
|
import type { EffectorPlacement, EffectorTarget } from "./http-effect.ts";
|
|
33
|
-
import type { NoticeScope, RaiseOptions, TakenNotices } from "./notices.ts";
|
|
35
|
+
import type { LedgerBody, NoticeScope, RaiseOptions, TakenNotices } from "./notices.ts";
|
|
34
36
|
import type { AnswerSeat } from "./pick.ts";
|
|
35
37
|
import type { Notice, PickAnswer } from "./wire.ts";
|
|
36
38
|
import type { SandboxPort } from "./workspace.ts";
|
|
@@ -92,7 +94,7 @@ export type Registration = {
|
|
|
92
94
|
slot?: string;
|
|
93
95
|
/** An Agent's: the step boundary's read of its conversation's pending notices (ADR-0062), each
|
|
94
96
|
* reserved for this Turn until {@link noticesHeard} or the Turn's end releases it. */
|
|
95
|
-
boundaryNotices?: () => Promise<Array<{ id: string; notice:
|
|
97
|
+
boundaryNotices?: () => Promise<Array<{ id: string; notice: LedgerBody }>>;
|
|
96
98
|
/** An Agent's: the Harness appended these step-boundary notices — they are heard, ledgered in one
|
|
97
99
|
* save. Answers how many were this Turn's reservations. */
|
|
98
100
|
noticesHeard?: (ids: readonly string[]) => number;
|
|
@@ -124,6 +126,57 @@ export type Registration = {
|
|
|
124
126
|
* answer has nowhere to go.
|
|
125
127
|
*/
|
|
126
128
|
conversation?: string;
|
|
129
|
+
/**
|
|
130
|
+
* A Gate slot's (ADR-0011): its handlers by Hook kind id and event key, its `reply`, and the names
|
|
131
|
+
* of its `delivers`. What the Hook's door reads to fan a delivery out to this Gate. Absent on a
|
|
132
|
+
* plain Gate and on an Agent.
|
|
133
|
+
*/
|
|
134
|
+
hooked?: {
|
|
135
|
+
hooks: Readonly<Record<string, Readonly<Record<string, AnyHandler>>>>;
|
|
136
|
+
reply?: GateSlotParts["reply"];
|
|
137
|
+
delivers: readonly string[];
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* A Pool's `source` Gate (ADR-0017): the push half of its Source. `hears` says whether a handler
|
|
141
|
+
* of the Source hears a Hook kind and event key; `hear` runs that handler and answers the
|
|
142
|
+
* Source's verdict. What the Hook's door reads to bring a delivery to the Pool. Absent on every
|
|
143
|
+
* other Gate and on an Agent.
|
|
144
|
+
*/
|
|
145
|
+
source?: SourceSeat;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/** One Hook delivery as a Source's handler hears it (ADR-0017): the Hook, its kind and event key,
|
|
149
|
+
* the delivery id, the parsed payload and the Hook as a Caller. */
|
|
150
|
+
export type SourceDelivery = {
|
|
151
|
+
hook: string;
|
|
152
|
+
kind: string;
|
|
153
|
+
key: string;
|
|
154
|
+
delivery: string;
|
|
155
|
+
payload: unknown;
|
|
156
|
+
caller: CallerRecord;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/** The verdicts of a Source on one delivery (ADR-0017). */
|
|
160
|
+
export const SOURCE_VERDICTS = ["held", "existing", "hold-full", "reread", "skipped", "paused"] as const;
|
|
161
|
+
export type SourceVerdictName = (typeof SOURCE_VERDICTS)[number];
|
|
162
|
+
|
|
163
|
+
/** A Source's verdict on one delivery (ADR-0017): `key` for a carried item, `run` when a run holds
|
|
164
|
+
* that key, `reason` for a skip. */
|
|
165
|
+
export type SourceVerdictLine = { verdict: SourceVerdictName; key?: string; run?: string; reason?: string };
|
|
166
|
+
|
|
167
|
+
/** A Source's verdict as its seat gives it: the line, and the carried item, which only the
|
|
168
|
+
* Source's `reply` reads (ADR-0011). The item never goes in the outcome. */
|
|
169
|
+
export type SourceHeard = SourceVerdictLine & { item?: unknown };
|
|
170
|
+
|
|
171
|
+
/** The push half of a Pool's Source, on its `source` Gate's registration (ADR-0017). */
|
|
172
|
+
export type SourceSeat = {
|
|
173
|
+
hears(kind: string, key: string): boolean;
|
|
174
|
+
/** Run the handler, check the key and hold the item. The answer is the verdict; a `held` item is
|
|
175
|
+
* in the Pool's context when it resolves, and the caller saves the run before it answers. */
|
|
176
|
+
hear(d: SourceDelivery): Promise<SourceHeard>;
|
|
177
|
+
/** The Source's `reply`, when it has one: the text that the person who acted reads, from the
|
|
178
|
+
* verdict (ADR-0011). Pure; a throw is the caller's to log. */
|
|
179
|
+
reply?(verdict: SourceHeard, caller: CallerRecord): unknown;
|
|
127
180
|
};
|
|
128
181
|
|
|
129
182
|
/**
|
|
@@ -280,6 +333,9 @@ export class OutstandingError extends Error {
|
|
|
280
333
|
}
|
|
281
334
|
}
|
|
282
335
|
|
|
336
|
+
/** The Caller that a Gate's event carries on its {@link Sender} (ADR-0011, ADR-0078). */
|
|
337
|
+
export type SenderCaller = Pick<Sender, "via" | "name" | "onBehalfOf" | "checked">;
|
|
338
|
+
|
|
283
339
|
/** Refuse a caller's body that carries the sender (ADR-0013, ADR-0015): only the Orchestrator writes
|
|
284
340
|
* it, from the registration, so neither the Agent's wire nor the gates route takes it. */
|
|
285
341
|
export function refuseSenderField(payload: unknown): void {
|
|
@@ -328,10 +384,42 @@ export function actorPath(ref: AnyActorRef): string[] {
|
|
|
328
384
|
* names the conversation it burns with it.
|
|
329
385
|
*/
|
|
330
386
|
/** An Agent's slot (ADR-0076): its continued conversation's Instance ID without the run id —
|
|
331
|
-
* `<machine actor path>/<agent>`. What the Harness states and the registration records.
|
|
387
|
+
* `<machine actor path>/<agent>`. What the Harness states and the registration records. Each
|
|
388
|
+
* segment of the path is encoded ({@link slotSegment}) before the segments are joined with `.`,
|
|
389
|
+
* so two paths never have one spelling (ADR-0057). The root Machine's path is `root`, a spelling
|
|
390
|
+
* that no encoded path has: a segment `root` and the empty segment are escaped. */
|
|
332
391
|
export function agentSlot(machine: AnyActorRef | undefined, agentName: string): string {
|
|
333
|
-
|
|
334
|
-
|
|
392
|
+
return `${slotPath(machine)}/${agentName}`;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** The Machine part of a slot ({@link agentSlot}): the encoded actor path of the Machine instance,
|
|
396
|
+
* `root` for the run's root. A Steering message held for a slot ends with this Machine (ADR-0002). */
|
|
397
|
+
export function slotPath(machine: AnyActorRef | undefined): string {
|
|
398
|
+
return (machine ? actorPath(machine).map(slotSegment).join(".") : "") || "root";
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* One actor id as a segment of a slot's path (ADR-0057). A letter, a digit, `-` and `_` stay as
|
|
403
|
+
* they are; each other character becomes `~` and two upper-case hex digits for each of its UTF-8
|
|
404
|
+
* bytes. So a segment has no `.` (the joint), no `/` (the iid's joint) and nothing that a URL or
|
|
405
|
+
* a header must escape, and the encoding is one to one: `~` occurs only as an escape. A Pool's
|
|
406
|
+
* worker has its item's id as its actor id, and an item id can be any text. Two segments are
|
|
407
|
+
* escaped although each character in them may stay: `root` is `~72oot` and the empty id is `~`
|
|
408
|
+
* (a `~` that no hex follows), so no encoded path spells `root`, the root Machine's path, or is
|
|
409
|
+
* empty, which the root's path also was.
|
|
410
|
+
*/
|
|
411
|
+
export function slotSegment(id: string): string {
|
|
412
|
+
if (id === "") return "~";
|
|
413
|
+
if (id === "root") return "~72oot";
|
|
414
|
+
let out = "";
|
|
415
|
+
for (const ch of id) {
|
|
416
|
+
if (/^[A-Za-z0-9_-]$/.test(ch)) {
|
|
417
|
+
out += ch;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
for (const byte of new TextEncoder().encode(ch)) out += `~${byte.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
421
|
+
}
|
|
422
|
+
return out;
|
|
335
423
|
}
|
|
336
424
|
|
|
337
425
|
export function continuedIid(machine: AnyActorRef | undefined, runId: string, agentName: string): string {
|
|
@@ -348,11 +436,23 @@ export function agentAddress(instanceId: string): string {
|
|
|
348
436
|
return `agent/${instanceId}`;
|
|
349
437
|
}
|
|
350
438
|
|
|
439
|
+
/** What the run host hears of the table: a surface that opens, and one that closes. A Gate's
|
|
440
|
+
* `openedAt` is recorded here (ADR-0011). */
|
|
441
|
+
export type RegistrationWatch = {
|
|
442
|
+
opened?: (reg: Registration) => void;
|
|
443
|
+
closed?: (reg: Registration) => void;
|
|
444
|
+
};
|
|
445
|
+
|
|
351
446
|
export class RegistrationTable {
|
|
352
447
|
private readonly byAddress = new Map<string, Registration>();
|
|
353
448
|
/** The same registrations by run, so a run's are read without a scan of every run's: the run host
|
|
354
449
|
* reads them on every microstep of the run (`cause.ts`). */
|
|
355
450
|
private readonly ofRun = new Map<string, Set<Registration>>();
|
|
451
|
+
private readonly watch: RegistrationWatch;
|
|
452
|
+
|
|
453
|
+
constructor(watch: RegistrationWatch = {}) {
|
|
454
|
+
this.watch = watch;
|
|
455
|
+
}
|
|
356
456
|
|
|
357
457
|
/** Register a live surface; returns its disposer (actors call it from their stop cleanup). */
|
|
358
458
|
register(reg: Registration): () => void {
|
|
@@ -365,6 +465,8 @@ export class RegistrationTable {
|
|
|
365
465
|
const ofRun = this.ofRun.get(reg.runId) ?? new Set<Registration>();
|
|
366
466
|
ofRun.add(reg);
|
|
367
467
|
this.ofRun.set(reg.runId, ofRun);
|
|
468
|
+
this.watch.opened?.(reg);
|
|
469
|
+
let disposed = false;
|
|
368
470
|
return () => {
|
|
369
471
|
// Dispose only our own entry — a re-registration under the same address must not be
|
|
370
472
|
// clobbered by a stale disposer running late (dev reload, restore races).
|
|
@@ -372,6 +474,8 @@ export class RegistrationTable {
|
|
|
372
474
|
const runRegs = this.ofRun.get(reg.runId);
|
|
373
475
|
runRegs?.delete(reg);
|
|
374
476
|
if (runRegs?.size === 0) this.ofRun.delete(reg.runId);
|
|
477
|
+
if (!disposed) this.watch.closed?.(reg);
|
|
478
|
+
disposed = true;
|
|
375
479
|
};
|
|
376
480
|
}
|
|
377
481
|
|
|
@@ -391,9 +495,10 @@ export class RegistrationTable {
|
|
|
391
495
|
* to their wire (404 / 400, MCP tool errors). The payload is parsed by the named def's
|
|
392
496
|
* schema, so what lands in the Machine is exactly the validated shape — plus the registration's
|
|
393
497
|
* sender, written here and nowhere else (ADR-0015). A delivery that would run another party's
|
|
394
|
-
* writing throws {@link NotTakenError}.
|
|
498
|
+
* writing throws {@link NotTakenError}. `caller` is the Caller that answers a Gate (ADR-0011,
|
|
499
|
+
* ADR-0078): a Gate's Sender carries it, and an Agent's never does.
|
|
395
500
|
*/
|
|
396
|
-
deliver(address: string, type: string, payload: unknown): void {
|
|
501
|
+
deliver(address: string, type: string, payload: unknown, caller?: SenderCaller): void {
|
|
397
502
|
const reg = this.byAddress.get(address);
|
|
398
503
|
if (!reg) throw new UnknownAddressError(`no live registration at "${address}"`);
|
|
399
504
|
refuseSenderField(payload);
|
|
@@ -408,10 +513,11 @@ export class RegistrationTable {
|
|
|
408
513
|
throw new EventValidationError(`invalid "${type}" payload: ${parsed.error.message}`);
|
|
409
514
|
}
|
|
410
515
|
// `type` after the payload: a payload never names the event the Machine receives (ADR-0011).
|
|
516
|
+
const sender = reg.sender && caller && reg.sender.party === "gate" ? { ...reg.sender, ...caller } : reg.sender;
|
|
411
517
|
const event: DeliveredEvent = {
|
|
412
518
|
...parsed.data,
|
|
413
519
|
type: def.name,
|
|
414
|
-
...(
|
|
520
|
+
...(sender ? { [SENDER_KEY]: sender } : {}),
|
|
415
521
|
};
|
|
416
522
|
// Exact, with the real payload (ADR-0015): a delivery whose selection holds a writing that is
|
|
417
523
|
// not this sender's never reaches the Machine.
|
|
@@ -437,12 +543,34 @@ export class RegistrationTable {
|
|
|
437
543
|
* and on the row. `instance` is set for a foreign caller, whose Orchestrator this one cannot
|
|
438
544
|
* verify: opaque text, never resolved.
|
|
439
545
|
*/
|
|
440
|
-
export type DispatchedBy = {
|
|
546
|
+
export type DispatchedBy = {
|
|
547
|
+
run: string;
|
|
548
|
+
slot: string;
|
|
549
|
+
effect: string;
|
|
550
|
+
depth: number;
|
|
551
|
+
instance?: string;
|
|
552
|
+
/** The idempotency key when a Pool of runs started the run (ADR-0017): the item's id. The store
|
|
553
|
+
* scopes it to the callee Workflow, as it scopes `effect`. Absent: the key is `effect`. */
|
|
554
|
+
key?: string;
|
|
555
|
+
/** The Hook delivery that carried the item to the Pool (ADR-0017): the Hook's name, the delivery
|
|
556
|
+
* id, and the party that the signed payload names. Absent for an item that a read or `next` gave. */
|
|
557
|
+
hook?: { name: string; delivery: string; onBehalfOf?: string };
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
/** The idempotency key that a start carries (ADR-0017, ADR-0071): a Pool's `key`, else the caller's
|
|
561
|
+
* ledger row id. */
|
|
562
|
+
export const dispatchKeyOf = (by: Pick<DispatchedBy, "effect" | "key">): string => by.key ?? by.effect;
|
|
441
563
|
|
|
442
564
|
/** The header a foreign `dispatch` carries its {@link DispatchedBy} in, as JSON (ADR-0071): out of
|
|
443
565
|
* band, so the callee's door reserves no body field for it. */
|
|
444
566
|
export const DISPATCHED_BY_HEADER = "jr2-dispatched-by";
|
|
445
567
|
|
|
568
|
+
/** The header that makes a foreign start a key-only ask (ADR-0071), with the value `true`: the door
|
|
569
|
+
* answers the run under the key of {@link DISPATCHED_BY_HEADER}, or `200 { existing: false }`, and
|
|
570
|
+
* starts nothing. The Instance Effector sends it, with no body, when the slot's schema refuses the
|
|
571
|
+
* body. */
|
|
572
|
+
export const KEY_ONLY_HEADER = "jr2-key-only";
|
|
573
|
+
|
|
446
574
|
/**
|
|
447
575
|
* A dispatch's start as the run host answers it in-process (ADR-0071): the run, and whether the key
|
|
448
576
|
* found one that already existed; or the door's refusal, with the status `POST /workflows/:name/runs`
|
|
@@ -467,16 +595,24 @@ export type RunBinding = {
|
|
|
467
595
|
/** The run's depth in a chain of dispatches (ADR-0071): 0 for a run nothing dispatched. Absent
|
|
468
596
|
* on a bare unit-test binding, which reads 0. */
|
|
469
597
|
depth?: number;
|
|
598
|
+
/** The first Caller of the run's chain of starts (ADR-0078): the Caller that started this run,
|
|
599
|
+
* or the run that dispatched it, and so on. A foreign `dispatch` sends it to the other door as
|
|
600
|
+
* `onBehalfOf` (ADR-0071). Undefined when jr2 started the chain. Absent on a bare binding. */
|
|
601
|
+
firstCaller?: () => Promise<{ via: string; name: string; shown?: string; onBehalfOf?: string } | undefined>;
|
|
470
602
|
/**
|
|
471
603
|
* The in-process half of a `dispatch` Effect (ADR-0071): the run host, reached directly, with no
|
|
472
604
|
* wire and no token — the Orchestrator is the single writer of runs. `start` answers a refusal as
|
|
473
605
|
* {@link DispatchStart}, never by throwing; `settled` resolves with the run's status once it is no
|
|
474
606
|
* longer live — at once for a run already settled, and across a restore in either order — and
|
|
475
|
-
* rejects when `signal` aborts.
|
|
607
|
+
* rejects when `signal` aborts. `lookup` is the key check alone: the run of `workflow` that
|
|
608
|
+
* carries the key `key`, in any status, while its row lives; the Effect asks it before it reads
|
|
609
|
+
* its input, so a run that exists is answered whatever the slot's schema says now. Absent
|
|
610
|
+
* outside a RunHost: a dispatch with no target faults.
|
|
476
611
|
*/
|
|
477
612
|
dispatch?: {
|
|
478
613
|
start(workflow: string, input: Record<string, unknown>, by: DispatchedBy): Promise<DispatchStart>;
|
|
479
614
|
settled(runId: string, signal: AbortSignal): Promise<RunStatus>;
|
|
615
|
+
lookup?(workflow: string, key: string): Promise<{ runId: string } | undefined>;
|
|
480
616
|
};
|
|
481
617
|
/** The hash of the Assembly the run holds (ADR-0069): the one it started under, through
|
|
482
618
|
* restarts. Absent for a run no Assembly started. */
|
|
@@ -554,14 +690,18 @@ export type RunBinding = {
|
|
|
554
690
|
/** Put back a notice an admission carried that no model heard, WITH its source (`NoticeLedger.restore`):
|
|
555
691
|
* a raise would drop it, its source being seen. A Workspace notice is pending again for `taker`,
|
|
556
692
|
* the conversation that did not hear it. Persisted at the write. */
|
|
557
|
-
restoreNotice?: (notice:
|
|
693
|
+
restoreNotice?: (notice: LedgerBody, to: string, source?: string, taker?: string) => void;
|
|
558
694
|
/** Reserve the pending notices in one admission's scope, for its conversation (`scope.taker`).
|
|
559
695
|
* They are delivered by the `recordAdmission` that ledgers it (its `delivered` ids and `taker`),
|
|
560
696
|
* or released for that conversation if the admission fails. */
|
|
561
697
|
takeNotices?: (scope: NoticeScope) => TakenNotices;
|
|
562
698
|
releaseNotices?: (ids: readonly string[], taker?: string) => void;
|
|
563
699
|
/** What `takeNotices` would reserve in this scope, reserving nothing (`NoticeLedger.peek`). */
|
|
564
|
-
peekNotices?: (scope: NoticeScope) => Array<{ id: string; notice:
|
|
700
|
+
peekNotices?: (scope: NoticeScope) => Array<{ id: string; notice: LedgerBody; source?: string }>;
|
|
701
|
+
/** The Machine's `steer` action (ADR-0002): hold a Steering message for the Agent `agentName` of
|
|
702
|
+
* `machine`, with the Sender whose words it relays. Throws when `machine` carries no Agent of
|
|
703
|
+
* that name. Absent outside a RunHost: the action then does nothing. */
|
|
704
|
+
steer?: (machine: AnyActorRef, agentName: string, text: string, from?: Sender) => void;
|
|
565
705
|
/** The Harness acknowledged a step boundary's notices (ADR-0062): each that `taker` reserved is
|
|
566
706
|
* heard there, persisted at the write. Answers how many were. */
|
|
567
707
|
acknowledgeNotices?: (ids: readonly string[], taker: string) => number;
|
|
@@ -727,7 +867,57 @@ export type ChildErrorMarker = { kind: "child-error"; agent: string; pick: strin
|
|
|
727
867
|
|
|
728
868
|
/** Every marker a run's mechanism puts on its per-run feed — an Effect's lines among them
|
|
729
869
|
* (ADR-0067): its start, its stream, its output, its abort. */
|
|
730
|
-
export type RunMarker =
|
|
870
|
+
export type RunMarker =
|
|
871
|
+
| TurnMarker
|
|
872
|
+
| PlacingMarker
|
|
873
|
+
| ChildErrorMarker
|
|
874
|
+
| EffectMarker
|
|
875
|
+
| GateMarker
|
|
876
|
+
| HookRefusedMarker
|
|
877
|
+
| PoolMarker;
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* What a Pool of runs did with one item (ADR-0017): `started` (its run, and `existing` when the key
|
|
881
|
+
* found a run that was there before), `settled` (the run ended, with its status, or the start
|
|
882
|
+
* ended with no run: `start-refused` with the door's report, `dispatch-error` with the error), and
|
|
883
|
+
* `carry-refused` (a held item that the Source's `item` schema does not parse), and `skipped` (an
|
|
884
|
+
* item of a read whose `itemId` threw or gave no id: it has no `key`, and `reason` says which item
|
|
885
|
+
* and why; one mark per item in a run's life). `pool` is the Pool's Machine id. Instance-token class
|
|
886
|
+
* like the Turn markers: a key is the workflow's data.
|
|
887
|
+
*/
|
|
888
|
+
export type PoolMarker = {
|
|
889
|
+
kind: "pool";
|
|
890
|
+
pool: string;
|
|
891
|
+
mark: "started" | "settled" | "carry-refused" | "skipped";
|
|
892
|
+
/** The item's id: absent on `skipped`, whose item has none. */
|
|
893
|
+
key?: string;
|
|
894
|
+
run?: string;
|
|
895
|
+
existing?: boolean;
|
|
896
|
+
status?: string;
|
|
897
|
+
reason?: string;
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* A Gate's look gave its event, and the run took it (ADR-0011): the Gate's id and the event's name.
|
|
902
|
+
* The event's Sender is the Gate, and no Caller answered it. Instance-token class like the Turn
|
|
903
|
+
* markers: a Gate id can be one that the workflow computed from its data.
|
|
904
|
+
*/
|
|
905
|
+
export type GateMarker = { kind: "looked"; gate: string; event: string };
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* A Hook's delivery reached an open Gate of the run, and the Gate did not take it (ADR-0011): its
|
|
909
|
+
* handler threw, gave an event that is not in its `delivers`, or gave one that the run does not take
|
|
910
|
+
* now. The run goes on. The Hook's name, the delivery id, the Gate, the event when there was one,
|
|
911
|
+
* and why. Instance-token class like the Turn markers: the reason can be a handler's own words.
|
|
912
|
+
*/
|
|
913
|
+
export type HookRefusedMarker = {
|
|
914
|
+
kind: "hook-refused";
|
|
915
|
+
hook: string;
|
|
916
|
+
delivery: string;
|
|
917
|
+
gate: string;
|
|
918
|
+
event?: string;
|
|
919
|
+
reason: string;
|
|
920
|
+
};
|
|
731
921
|
|
|
732
922
|
const bindings = new WeakMap<AnyActorSystem, RunBinding>();
|
|
733
923
|
|