@intx/workflow-host 0.2.2 → 0.4.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.
Files changed (101) hide show
  1. package/README.md +77 -14
  2. package/dist/adapters/mail-part-store.d.ts +46 -0
  3. package/dist/adapters/mail-part-store.js +251 -0
  4. package/dist/adapters/repo-store.d.ts +22 -1
  5. package/dist/adapters/repo-store.js +56 -65
  6. package/dist/adapters/spawn-child.d.ts +109 -44
  7. package/dist/adapters/spawn-child.js +77 -81
  8. package/dist/adapters/step-invoker.d.ts +52 -2
  9. package/dist/adapters/step-invoker.js +284 -37
  10. package/dist/adapters/substrate-mailbox-store.d.ts +80 -0
  11. package/dist/adapters/substrate-mailbox-store.js +404 -0
  12. package/dist/child/child-mailbox-reader.d.ts +10 -0
  13. package/dist/child/child-mailbox-reader.js +23 -0
  14. package/dist/child/credential-cell.d.ts +8 -0
  15. package/dist/child/credential-cell.js +66 -0
  16. package/dist/child/env-bootstrap.d.ts +20 -6
  17. package/dist/child/env-bootstrap.js +9 -1
  18. package/dist/child/from-process-env.d.ts +12 -0
  19. package/dist/child/from-process-env.js +6 -0
  20. package/dist/child/index.d.ts +6 -2
  21. package/dist/child/index.js +4 -1
  22. package/dist/child/mailbox-mutation-bridge.d.ts +61 -0
  23. package/dist/child/mailbox-mutation-bridge.js +101 -0
  24. package/dist/child/mailbox-watch-registry.d.ts +17 -0
  25. package/dist/child/mailbox-watch-registry.js +61 -0
  26. package/dist/child/outbound-mail-bridge.d.ts +3 -2
  27. package/dist/child/outbound-mail-bridge.js +20 -32
  28. package/dist/child/parked-correlations.d.ts +42 -0
  29. package/dist/child/parked-correlations.js +80 -0
  30. package/dist/child/pending-request.d.ts +89 -0
  31. package/dist/child/pending-request.js +80 -0
  32. package/dist/child/proxy-repo-store.d.ts +3 -2
  33. package/dist/child/proxy-repo-store.js +2 -0
  34. package/dist/child/run-child.d.ts +170 -14
  35. package/dist/child/run-child.js +569 -155
  36. package/dist/child/self-discovery.d.ts +10 -0
  37. package/dist/child/self-discovery.js +25 -1
  38. package/dist/child/substrate-write-bridge.d.ts +3 -2
  39. package/dist/child/substrate-write-bridge.js +21 -38
  40. package/dist/child/supervisor-backed-transport.d.ts +52 -6
  41. package/dist/child/supervisor-backed-transport.js +205 -62
  42. package/dist/child/verified-definition-loader.d.ts +33 -0
  43. package/dist/child/verified-definition-loader.js +43 -0
  44. package/dist/child/warm-agent-cache.d.ts +44 -4
  45. package/dist/child/warm-agent-cache.js +41 -10
  46. package/dist/index.d.ts +6 -4
  47. package/dist/index.js +6 -4
  48. package/dist/ipc/control-channel.d.ts +151 -2
  49. package/dist/ipc/control-channel.js +222 -29
  50. package/dist/ipc/event-channel.d.ts +32 -1
  51. package/dist/ipc/index.d.ts +1 -1
  52. package/dist/ipc/index.js +1 -1
  53. package/dist/mail-bus/hub-transport-adapter.d.ts +12 -7
  54. package/dist/mail-bus/hub-transport-adapter.js +9 -5
  55. package/dist/run-body-then-cleanup.d.ts +17 -0
  56. package/dist/run-body-then-cleanup.js +38 -0
  57. package/dist/seams/scheduler.d.ts +16 -6
  58. package/dist/seams/scheduler.js +87 -97
  59. package/dist/supervisor/cancel-signing.d.ts +2 -2
  60. package/dist/supervisor/cancel-signing.js +4 -8
  61. package/dist/supervisor/credentials.d.ts +28 -15
  62. package/dist/supervisor/credentials.js +7 -7
  63. package/dist/supervisor/dispatch-attribution.js +1 -1
  64. package/dist/supervisor/drain-timeout.d.ts +2 -2
  65. package/dist/supervisor/drain-timeout.js +1 -1
  66. package/dist/supervisor/index.d.ts +3 -3
  67. package/dist/supervisor/index.js +2 -2
  68. package/dist/supervisor/recycle.d.ts +10 -3
  69. package/dist/supervisor/recycle.js +18 -7
  70. package/dist/supervisor/run-event-compaction.d.ts +5 -5
  71. package/dist/supervisor/run-event-compaction.js +14 -19
  72. package/dist/supervisor/run-event-recovery.d.ts +34 -0
  73. package/dist/supervisor/run-event-recovery.js +45 -0
  74. package/dist/supervisor/spawn-env.d.ts +2 -2
  75. package/dist/supervisor/spawn-env.js +1 -1
  76. package/dist/supervisor/supervisor.d.ts +106 -26
  77. package/dist/supervisor/supervisor.js +1903 -414
  78. package/dist/supervisor/terminal-commit.d.ts +36 -0
  79. package/dist/supervisor/terminal-commit.js +130 -0
  80. package/dist/supervisor/types.d.ts +180 -23
  81. package/dist/testing/change-notifier.d.ts +12 -0
  82. package/dist/testing/change-notifier.js +63 -0
  83. package/dist/testing/index.d.ts +8 -0
  84. package/dist/testing/index.js +16 -0
  85. package/dist/testing/log-capture.d.ts +52 -0
  86. package/dist/testing/log-capture.js +124 -0
  87. package/dist/testing/mail-bus.d.ts +22 -0
  88. package/dist/testing/mail-bus.js +78 -0
  89. package/dist/testing/memory-streams.d.ts +43 -0
  90. package/dist/testing/memory-streams.js +211 -0
  91. package/dist/testing/spawn-observer.d.ts +12 -0
  92. package/dist/testing/spawn-observer.js +36 -0
  93. package/dist/testing/stub-repo-store.d.ts +10 -0
  94. package/dist/testing/stub-repo-store.js +39 -0
  95. package/dist/testing/supervisor-reaper.d.ts +24 -0
  96. package/dist/testing/supervisor-reaper.js +49 -0
  97. package/dist/testing/upstream-frames.d.ts +47 -0
  98. package/dist/testing/upstream-frames.js +94 -0
  99. package/dist/workflow-definition-loader.d.ts +187 -0
  100. package/dist/workflow-definition-loader.js +422 -0
  101. package/package.json +18 -11
@@ -0,0 +1,43 @@
1
+ // Source-ref definition load + re-verify barrier for the workflow-process child.
2
+ //
3
+ // A source-ref deployment's runnable definition is the evaluated pinned code
4
+ // closure, not an on-disk `workflow.json`. `loadVerifiedWorkflowDefinitionFromClosure`
5
+ // evaluates that closure to a live `WorkflowDefinition` and re-verifies it by
6
+ // project-then-hash: it projects the live definition back to its inert form,
7
+ // hashes it (`computeLiveDefinitionHash`), and refuses to return a definition
8
+ // whose recompute does not match the hub-approved hash. A mismatch throws --
9
+ // fail closed, no fallback and no coercion.
10
+ //
11
+ // The re-verify barrier is load-bearing because the approved hash arrives
12
+ // OUT-OF-BAND from the bytes being checked (a signed spawn env the closure
13
+ // materializer cannot forge). It lives at the LOAD boundary, not at run start:
14
+ // a resumed run reuses the definition this loader returned at child boot, so
15
+ // gating the load covers fresh runs, resumed runs, and referenced onTrigger
16
+ // bodies (which the child extracts from the same re-verified closure) with a
17
+ // single check. `RunStarted.definitionHash` is deliberately NOT the barrier: it
18
+ // hashes a different projection and never fires when the run log already carries
19
+ // a `RunStarted`, so it is skipped on resume.
20
+ import { computeLiveDefinitionHash } from "@intx/workflow";
21
+ import { loadWorkflowDefinitionFromClosure } from "../workflow-definition-loader.js";
22
+ /**
23
+ * Evaluate a source-ref deployment's pinned code closure to a live
24
+ * `WorkflowDefinition` and re-verify it by project-then-hash before returning
25
+ * it. The inert projection is a non-executable approval surface, so the runtime
26
+ * needs the live definition the closure evaluates to. The re-verify projects
27
+ * that live definition back to its inert form and hashes it
28
+ * (`computeLiveDefinitionHash`), matching the hub-approved wire hash by byte
29
+ * equality; a divergent closure fails closed here and never runs.
30
+ */
31
+ export async function loadVerifiedWorkflowDefinitionFromClosure(opts) {
32
+ const definition = await loadWorkflowDefinitionFromClosure({
33
+ packageDir: opts.packageDir,
34
+ ...(opts.importModule !== undefined
35
+ ? { importModule: opts.importModule }
36
+ : {}),
37
+ });
38
+ const recomputed = await computeLiveDefinitionHash(definition);
39
+ if (recomputed !== opts.approvedHash) {
40
+ throw new Error(`workflow-host verified-definition loader: recomputed wire hash ${recomputed} for the source-ref closure at ${opts.packageDir} does not match the approved hash ${opts.approvedHash}; refusing to run a definition that no longer projects to the hub-approved content`);
41
+ }
42
+ return definition;
43
+ }
@@ -11,6 +11,35 @@ import type { InferenceEvent, InferenceSource } from "@intx/types/runtime";
11
11
  export interface WarmEventSinkRef {
12
12
  current: ((event: InferenceEvent) => void) | null;
13
13
  }
14
+ /**
15
+ * Per-turn settle barrier the connector reply drain exposes to the warm
16
+ * step (design §3c durability). The step snapshots `replySeq()` before its
17
+ * `agent.send` and, for a turn that produced a reply, awaits
18
+ * `waitForReplyAfter(snapshot)` so the run parks -- and the supervisor
19
+ * consumes the inbound mail -- only after the reply is durably sent. This is
20
+ * the structural subset of the harness `ConnectorReplyDrain` the warm path
21
+ * needs; declaring it here keeps the workflow-host package independent of
22
+ * `@intx/harness`, while the drain the sidecar builds satisfies it.
23
+ */
24
+ export type WarmReplySettlement = {
25
+ readonly ok: true;
26
+ } | {
27
+ readonly ok: false;
28
+ readonly cause: unknown;
29
+ };
30
+ export interface WarmReplyDrive {
31
+ /** Settles when the drain loop exits at eviction. Folded into `eventForward`. */
32
+ readonly done: Promise<void>;
33
+ /** Monotonic count of replies that have settled (sent-and-acked or failed). */
34
+ replySeq(): number;
35
+ /**
36
+ * Resolve once the reply at index `n` has settled, with its outcome. A
37
+ * failure outcome (or a drain that tears down before reply `n` arrives)
38
+ * carries `ok: false` so the caller fails the turn rather than treating the
39
+ * reply as sent.
40
+ */
41
+ waitForReplyAfter(n: number): Promise<WarmReplySettlement>;
42
+ }
14
43
  /**
15
44
  * Per-address warm-agent cache. Keyed by the step's stable identity (the
16
45
  * single step's id), so a long-lived agent resolves to the same entry on
@@ -28,11 +57,22 @@ export interface WarmAgentCache {
28
57
  /**
29
58
  * Cache a freshly-built warm agent under `key`. The `eventSinkRef` is
30
59
  * the mutable sink the agent's stream forwarder reads; `eventForward`
31
- * is the forwarder loop's settle promise. Throws if an entry already
32
- * exists for `key` -- a double-build is a step-invoker bug, not a
33
- * silent overwrite that would leak the prior agent's LSP subprocess.
60
+ * is the forwarder loop's settle promise. `replyDrive` is the connector
61
+ * reply drain's per-turn barrier, or `null` when the deployment drives no
62
+ * threaded replies. Throws if an entry already exists for `key` -- a
63
+ * double-build is a step-invoker bug, not a silent overwrite that would
64
+ * leak the prior agent's LSP subprocess.
65
+ */
66
+ store(key: string, agent: Agent, eventSinkRef: WarmEventSinkRef, eventForward: Promise<void>, replyDrive: WarmReplyDrive | null): void;
67
+ /**
68
+ * Return the connector reply drain's per-turn barrier cached for `key`, or
69
+ * `null` when the deployment drives no threaded replies. The step-invoker
70
+ * fetches it on every message -- the drain is established once at the
71
+ * first-message build but each message's send must snapshot and await it.
72
+ * Throws when no entry exists for `key`: a barrier fetch before the warm
73
+ * agent is stored is a step-invoker sequencing bug.
34
74
  */
35
- store(key: string, agent: Agent, eventSinkRef: WarmEventSinkRef, eventForward: Promise<void>): void;
75
+ getReplyDrive(key: string): WarmReplyDrive | null;
36
76
  /**
37
77
  * Point the warm agent's stream forwarder at the active step's event
38
78
  * sink before its `agent.send`. Throws when no entry exists for
@@ -45,11 +45,18 @@ export function createWarmAgentCache() {
45
45
  const entry = entries.get(key);
46
46
  return entry === undefined ? null : entry.agent;
47
47
  }
48
- function store(key, agent, eventSinkRef, eventForward) {
48
+ function store(key, agent, eventSinkRef, eventForward, replyDrive) {
49
49
  if (entries.has(key)) {
50
50
  throw new Error(`warm-agent cache: an entry already exists for ${key}; the step-invoker must reuse the cached agent rather than rebuild it`);
51
51
  }
52
- entries.set(key, { agent, eventSinkRef, eventForward });
52
+ entries.set(key, { agent, eventSinkRef, eventForward, replyDrive });
53
+ }
54
+ function getReplyDrive(key) {
55
+ const entry = entries.get(key);
56
+ if (entry === undefined) {
57
+ throw new Error(`warm-agent cache: getReplyDrive for ${key} with no cached entry; the step-invoker must store the warm agent before fetching its reply barrier`);
58
+ }
59
+ return entry.replyDrive;
53
60
  }
54
61
  function setEventSink(key, onEvent) {
55
62
  const entry = entries.get(key);
@@ -65,8 +72,24 @@ export function createWarmAgentCache() {
65
72
  entry.eventSinkRef.current = null;
66
73
  }
67
74
  function applySources(sources, defaultSource) {
75
+ // Rotate every retained agent before surfacing any failure: one agent
76
+ // rejecting the rotation (an invalid source, or a closed agent racing
77
+ // eviction) must not skip the rest. Collect failures and throw them
78
+ // together. (Warm-keep is single-step today, so the cache holds 0 or 1
79
+ // entry; this keeps the contract honest if warm-keep ever spans steps.)
80
+ const failures = [];
68
81
  for (const entry of entries.values()) {
69
- entry.agent.setSources(sources, defaultSource);
82
+ try {
83
+ entry.agent.setSources(sources, defaultSource);
84
+ }
85
+ catch (cause) {
86
+ const message = cause instanceof Error ? cause.message : String(cause);
87
+ logger.error `warm-agent rotation: setSources failed: ${message}`;
88
+ failures.push(cause);
89
+ }
90
+ }
91
+ if (failures.length > 0) {
92
+ throw new AggregateError(failures, `warm-agent rotation: ${String(failures.length)} agent(s) rejected the source rotation`);
70
93
  }
71
94
  }
72
95
  async function evictAll(reason) {
@@ -74,24 +97,28 @@ export function createWarmAgentCache() {
74
97
  return;
75
98
  const toEvict = [...entries.values()];
76
99
  entries.clear();
100
+ // Close every entry before surfacing any failure. The wrapped close
101
+ // (see `createToolBearingAgentFactory`) runs the agent's own close and
102
+ // then the plugin + tool-bundle disposers, killing the LSP subprocess,
103
+ // and it rejects when a disposer fails. One entry's close rejecting
104
+ // must not strand the remaining entries' teardown -- that would leak
105
+ // exactly the LSP subprocesses warm-keep risks. Collect failures and
106
+ // throw them together once every agent has been closed and drained.
107
+ // (Warm-keep is single-step today, so the cache holds 0 or 1 entry;
108
+ // this keeps the contract honest if warm-keep ever spans steps.)
109
+ const failures = [];
77
110
  for (const entry of toEvict) {
78
111
  // Clear the sink first so any event emitted during the agent's
79
112
  // shutdown window is dropped rather than delivered to a per-run
80
113
  // channel the run-loop is tearing down.
81
114
  entry.eventSinkRef.current = null;
82
115
  try {
83
- // The wrapped close (see `createToolBearingAgentFactory`) runs
84
- // the agent's own close and then the plugin + tool-bundle
85
- // disposers, killing the LSP subprocess. A close failure must
86
- // surface, not be swallowed -- a leaked LSP subprocess is
87
- // exactly the failure warm-keep risks -- so it propagates after
88
- // we have drained what we can.
89
116
  await entry.agent.close();
90
117
  }
91
118
  catch (cause) {
92
119
  const message = cause instanceof Error ? cause.message : String(cause);
93
120
  logger.error `warm-agent eviction (${reason}): agent.close failed: ${message}`;
94
- throw cause instanceof Error ? cause : new Error(message);
121
+ failures.push(cause);
95
122
  }
96
123
  finally {
97
124
  // `agent.close()` terminates the stream iterator, so the
@@ -100,10 +127,14 @@ export function createWarmAgentCache() {
100
127
  await entry.eventForward;
101
128
  }
102
129
  }
130
+ if (failures.length > 0) {
131
+ throw new AggregateError(failures, `warm-agent eviction (${reason}): ${String(failures.length)} agent(s) failed to close; an LSP subprocess may be leaked`);
132
+ }
103
133
  }
104
134
  return {
105
135
  acquire,
106
136
  store,
137
+ getReplyDrive,
107
138
  setEventSink,
108
139
  clearEventSink,
109
140
  applySources,
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
+ export { loadWorkflowDefinitionFromClosure, loadWorkflowDirectorRegistryFromClosure, loadWorkflowLoopFnsFromClosure, loadWorkflowPluginFactoriesFromClosure, loadWorkflowPluginToolDefinitionsFromClosure, type LoadWorkflowDefinitionFromClosureArgs, type LoadWorkflowDirectorRegistryFromClosureArgs, type LoadWorkflowLoopFnsFromClosureArgs, type LoadWorkflowPluginsFromClosureArgs, } from "./workflow-definition-loader.js";
1
2
  export { createWorkflowRunRepoStore, type WorkflowRunRepoStoreOpts, } from "./adapters/repo-store.js";
2
3
  export { createWorkflowRunBlobSubstrate, type WorkflowRunBlobSubstrateOpts, } from "./adapters/blob-substrate.js";
4
+ export { createSubstrateMailboxStore, MAILBOX_PREFIX, MAILBOX_INBOX_DIR, MAILBOX_INDEX_FILE, MAILBOX_EML_SUFFIX, MAILBOX_INBOX_PREFIX, type SubstrateMailboxStore, type SubstrateMailboxStoreOpts, type MailboxSyncKnownState, type MailboxSyncResult, } from "./adapters/substrate-mailbox-store.js";
3
5
  export { createWorkflowStepInvoker, type StepEnvBase, type WorkflowStepInvokerOpts, } from "./adapters/step-invoker.js";
4
- export { createWorkflowSpawnChild, type ChildTerminalStatus, type RunChildWorkflow, type WorkflowSpawnChildOpts, } from "./adapters/spawn-child.js";
5
- export { createWorkflowSupervisor, assembleCredentialsSnapshot, commitCancelRequested, createDrainTimeoutAccumulator, createRecyclePolicy, defaultStepRepoId, hashGrants, triggerRecycle, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_KILL_TIMEOUT_MS, DEFAULT_POLICY_INTERVAL_MS, DEFAULT_TERMINAL_WRITE_WATCHDOG_MS, MAX_BUFFERED_MAIL, STEP_GRANTS_PATH, STEP_GRANTS_REF, SUPERVISOR_PRINCIPAL_KIND, type AssembleCredentialsSnapshotOpts, type CancelCommitInfo, type CancelRequestOpts, type CommitCancelRequestedOpts, type CommitCancelRequestedResult, type CredentialsSnapshot, type CredentialsSnapshotStep, type DeliverSignalOpts, type DeliverSourcesOpts, type DeriveMailAuditRef, type DeriveStepAddress, type DeriveStepRepoId, type DrainOpts, type DrainTimeoutAccumulator, type DrainTimeoutAccumulatorFactory, type DrainTimeoutOpts, type InboxPrimitives, type MailAuditRef, type MailBusBindings, type PrincipalSigner, type RecycleAttempt, type RecycleContext, type RecycleOpts, type RecycleOrigin, type RecyclePolicy, type RecyclePolicyBounds, type RecyclePolicyOpts, type SignedPayload, type SpawnOpts, type SpawnResult, type SubprocessHandle, type SubprocessSpawner, type TerminalEventSource, type TerminalRunEvent, type TriggerRecycleOpts, type DispatchTimingMark, type DispatchStructuralCounters, type DispatchSubstrateLeg, type WorkflowSupervisor, type WorkflowSupervisorBindings, type WorkflowSupervisorPrincipalKind, } from "./supervisor/index.js";
6
+ export { createInMemorySpawnChild, createInMemorySpawnSuspendableChild, type ChildTerminalStatus, type RunChildWorkflow, type RunSuspendableChild, } from "./adapters/spawn-child.js";
7
+ export { createWorkflowSupervisor, assembleCredentialsSnapshot, isErrnoNotFound, commitCancelRequested, createDrainTimeoutAccumulator, createRecyclePolicy, defaultStepRepoId, hashGrants, triggerRecycle, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_KILL_TIMEOUT_MS, DEFAULT_POLICY_INTERVAL_MS, MAX_BUFFERED_MAIL, STEP_GRANTS_PATH, STEP_GRANTS_REF, SUPERVISOR_PRINCIPAL_KIND, type AssembleCredentialsSnapshotOpts, type CancelCommitInfo, type CancelRequestOpts, type CommitCancelRequestedOpts, type CommitCancelRequestedResult, type CredentialsSnapshot, type CredentialsSnapshotStep, type DeliverSignalOpts, type DeliverSourcesOpts, type DeriveMailAuditRef, type DeriveStepAddress, type DeriveStepRepoId, type DrainOpts, type DrainTimeoutAccumulator, type DrainTimeoutAccumulatorFactory, type DrainTimeoutOpts, type InboxPrimitives, type MailAuditRef, type MailBusBindings, type PrincipalSigner, type RecycleAttempt, type RecycleContext, type RecycleOpts, type RecycleOrigin, type RecyclePolicy, type RecyclePolicyBounds, type RecyclePolicyOpts, type SignedPayload, type SpawnOpts, type SpawnResult, type SubprocessHandle, type SubprocessSpawner, type SuspensionRegistration, type TerminalEventSource, type TerminalRunEvent, type TriggerRecycleOpts, type DispatchTimingMark, type DispatchStructuralCounters, type DispatchSubstrateLeg, type WorkflowSupervisor, type WorkflowSupervisorBindings, type WorkflowSupervisorPrincipalKind, } from "./supervisor/index.js";
6
8
  export { createWorkflowHostDrainController, type WorkflowHostDrainController, type CreateWorkflowHostDrainControllerOpts, } from "./drain-controller.js";
7
9
  export { wrapHubTransportAsMailBus, type HubTransportMailBusAdapter, } from "./mail-bus/index.js";
8
- export { ControlPayload, DEFAULT_EVENT_BUFFER_LIMIT, EventPayload, FrameEnvelope, IPC_CRYPTO, SourcesUpdatedData, MacedEnvelope, OutboundAttachmentPayload, OutboundMessagePayload, SignedEnvelope, createControlChannelSender, createEventChannelSender, decodeEnvelope, encodeEnvelope, generateChannelId, generateHmacKey, receiveControlChannel, receiveEventChannel, signEd25519, signHmac, verifyEd25519, verifyHmac, type ControlChannelReceiverOpts, type ControlChannelSender, type ControlChannelSenderOpts, type EventChannelReceiverOpts, type EventChannelSender, type EventChannelSenderOpts, type FrameReader, type FrameWriter, type NdjsonReader, type NdjsonWriter, } from "./ipc/index.js";
9
- export { EVENT_CHANNEL_FD, createChildOutboundMailBridge, createChildSubstrateWriteBridge, createCredentialsBackedAuthorize, createProxyWorkflowRunRepoStore, createSupervisorBackedTransport, createWarmAgentCache, discoverInFlightRuns, parseSpawnTimeEnv, runWorkflowChild, runWorkflowChildFromProcessEnv, type ChildOutboundMailBridge, type ChildStepInvoker, type ChildSubstrateWriteBridge, type CreateChildOutboundMailBridgeOpts, type CreateChildSubstrateWriteBridgeOpts, type CreateProxyWorkflowRunRepoStoreOpts, type CredentialsSnapshotRef, type DiscoverRunsOpts, type DiscoveredRun, type DrainController, type GrantEvaluator, type RunWorkflowChildBindings, type RunWorkflowChildFromProcessEnvOpts, type RunWorkflowChildOpts, type RunWorkflowChildResult, type SourcesSnapshotRef, type SpawnTimeEnv, type SubstrateFactory, type SubstrateFactoryEnv, type SubstrateWriteRequest, type SubstrateWriteResponseSink, type WarmAgentCache, type WarmEventSinkRef, } from "./child/index.js";
10
+ export { ControlPayload, DEFAULT_EVENT_BUFFER_LIMIT, EventPayload, FrameEnvelope, IPC_CRYPTO, MailboxNotifyHeaders, SourcesUpdatedData, MacedEnvelope, OutboundAttachmentPayload, OutboundMessagePayload, SignedEnvelope, createControlChannelSender, createEventChannelSender, decodeEnvelope, encodeEnvelope, generateChannelId, generateHmacKey, receiveControlChannel, receiveEventChannel, signEd25519, signHmac, verifyEd25519, verifyHmac, type ControlChannelReceiverOpts, type ControlChannelSender, type ControlChannelSenderOpts, type EventChannelReceiverOpts, type EventChannelSender, type EventChannelSenderOpts, type FrameReader, type FrameWriter, type NdjsonReader, type NdjsonWriter, } from "./ipc/index.js";
11
+ export { EVENT_CHANNEL_FD, createChildMailboxReader, createChildMailboxMutationBridge, createChildOutboundMailBridge, createChildSubstrateWriteBridge, createCredentialsBackedAuthorize, createMailboxWatchRegistry, createProxyWorkflowRunRepoStore, createSupervisorBackedTransport, createWarmAgentCache, discoverInFlightRuns, parseSpawnTimeEnv, runWorkflowChild, runWorkflowChildFromProcessEnv, type ChildMailboxMutationBridge, type ChildMailboxReader, type ChildOutboundMailBridge, type ChildStepInvoker, type ChildSubstrateWriteBridge, type CreateChildMailboxMutationBridgeOpts, type CreateChildOutboundMailBridgeOpts, type CreateChildSubstrateWriteBridgeOpts, type CreateProxyWorkflowRunRepoStoreOpts, type CredentialsSnapshotRef, type CredentialWiring, type DiscoverRunsOpts, type DiscoveredRun, type DrainController, type GrantEvaluator, type LoadParkedApproval, type MailboxWatchRegistry, type RunWorkflowChildBindings, type RunWorkflowChildFromProcessEnvOpts, type RunWorkflowChildOpts, type RunWorkflowChildResult, type SourcesSnapshotRef, type SpawnTimeEnv, type SubstrateFactory, type SubstrateFactoryEnv, type SubstrateWriteRequest, type SubstrateWriteResponseSink, type SupervisorBackedTransportInbound, type WarmAgentCache, type WarmEventSinkRef, } from "./child/index.js";
10
12
  export { adaptHostScheduler, createWorkflowHostScheduler, createWorkflowHostSignalChannel, SignalReceivedEnvelope, type SchedulerHandle, type SchedulerOpts, type SignalChannelHandle, type SignalChannelOpts, } from "./seams/index.js";
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
+ export { loadWorkflowDefinitionFromClosure, loadWorkflowDirectorRegistryFromClosure, loadWorkflowLoopFnsFromClosure, loadWorkflowPluginFactoriesFromClosure, loadWorkflowPluginToolDefinitionsFromClosure, } from "./workflow-definition-loader.js";
1
2
  export { createWorkflowRunRepoStore, } from "./adapters/repo-store.js";
2
3
  export { createWorkflowRunBlobSubstrate, } from "./adapters/blob-substrate.js";
4
+ export { createSubstrateMailboxStore, MAILBOX_PREFIX, MAILBOX_INBOX_DIR, MAILBOX_INDEX_FILE, MAILBOX_EML_SUFFIX, MAILBOX_INBOX_PREFIX, } from "./adapters/substrate-mailbox-store.js";
3
5
  export { createWorkflowStepInvoker, } from "./adapters/step-invoker.js";
4
- export { createWorkflowSpawnChild, } from "./adapters/spawn-child.js";
5
- export { createWorkflowSupervisor, assembleCredentialsSnapshot, commitCancelRequested, createDrainTimeoutAccumulator, createRecyclePolicy, defaultStepRepoId, hashGrants, triggerRecycle, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_KILL_TIMEOUT_MS, DEFAULT_POLICY_INTERVAL_MS, DEFAULT_TERMINAL_WRITE_WATCHDOG_MS, MAX_BUFFERED_MAIL, STEP_GRANTS_PATH, STEP_GRANTS_REF, SUPERVISOR_PRINCIPAL_KIND, } from "./supervisor/index.js";
6
+ export { createInMemorySpawnChild, createInMemorySpawnSuspendableChild, } from "./adapters/spawn-child.js";
7
+ export { createWorkflowSupervisor, assembleCredentialsSnapshot, isErrnoNotFound, commitCancelRequested, createDrainTimeoutAccumulator, createRecyclePolicy, defaultStepRepoId, hashGrants, triggerRecycle, DEFAULT_DRAIN_TIMEOUT_MS, DEFAULT_KILL_TIMEOUT_MS, DEFAULT_POLICY_INTERVAL_MS, MAX_BUFFERED_MAIL, STEP_GRANTS_PATH, STEP_GRANTS_REF, SUPERVISOR_PRINCIPAL_KIND, } from "./supervisor/index.js";
6
8
  export { createWorkflowHostDrainController, } from "./drain-controller.js";
7
9
  export { wrapHubTransportAsMailBus, } from "./mail-bus/index.js";
8
- export { ControlPayload, DEFAULT_EVENT_BUFFER_LIMIT, EventPayload, FrameEnvelope, IPC_CRYPTO, SourcesUpdatedData, MacedEnvelope, OutboundAttachmentPayload, OutboundMessagePayload, SignedEnvelope, createControlChannelSender, createEventChannelSender, decodeEnvelope, encodeEnvelope, generateChannelId, generateHmacKey, receiveControlChannel, receiveEventChannel, signEd25519, signHmac, verifyEd25519, verifyHmac, } from "./ipc/index.js";
9
- export { EVENT_CHANNEL_FD, createChildOutboundMailBridge, createChildSubstrateWriteBridge, createCredentialsBackedAuthorize, createProxyWorkflowRunRepoStore, createSupervisorBackedTransport, createWarmAgentCache, discoverInFlightRuns, parseSpawnTimeEnv, runWorkflowChild, runWorkflowChildFromProcessEnv, } from "./child/index.js";
10
+ export { ControlPayload, DEFAULT_EVENT_BUFFER_LIMIT, EventPayload, FrameEnvelope, IPC_CRYPTO, MailboxNotifyHeaders, SourcesUpdatedData, MacedEnvelope, OutboundAttachmentPayload, OutboundMessagePayload, SignedEnvelope, createControlChannelSender, createEventChannelSender, decodeEnvelope, encodeEnvelope, generateChannelId, generateHmacKey, receiveControlChannel, receiveEventChannel, signEd25519, signHmac, verifyEd25519, verifyHmac, } from "./ipc/index.js";
11
+ export { EVENT_CHANNEL_FD, createChildMailboxReader, createChildMailboxMutationBridge, createChildOutboundMailBridge, createChildSubstrateWriteBridge, createCredentialsBackedAuthorize, createMailboxWatchRegistry, createProxyWorkflowRunRepoStore, createSupervisorBackedTransport, createWarmAgentCache, discoverInFlightRuns, parseSpawnTimeEnv, runWorkflowChild, runWorkflowChildFromProcessEnv, } from "./child/index.js";
10
12
  export { adaptHostScheduler, createWorkflowHostScheduler, createWorkflowHostSignalChannel, SignalReceivedEnvelope, } from "./seams/index.js";
@@ -44,13 +44,14 @@ export declare const SourcesUpdatedData: import("arktype/internal/variants/objec
44
44
  id: string;
45
45
  provider: string;
46
46
  baseURL: string;
47
- apiKey: string;
47
+ credentialId: string;
48
48
  model: string;
49
49
  defaults?: {
50
50
  maxTokens?: number;
51
51
  providerOptions?: Record<string, unknown>;
52
52
  };
53
53
  capabilities?: string[];
54
+ quirks?: Record<string, unknown>;
54
55
  }[];
55
56
  defaultSource: string;
56
57
  }, {}>;
@@ -94,11 +95,45 @@ export declare const OutboundMessagePayload: import("arktype/internal/variants/o
94
95
  dataBase64: string;
95
96
  }[];
96
97
  inReplyTo?: string;
98
+ references?: string[];
97
99
  correlationId?: string;
98
100
  sessionId?: string;
99
101
  tenantId?: string;
100
102
  }, {}>;
101
103
  export type OutboundMessagePayload = typeof OutboundMessagePayload.infer;
104
+ /**
105
+ * Wire shape of the parsed `MessageHeaders` the supervisor rides inline on a
106
+ * `mailbox.notify` frame. Mirrors `@intx/types/runtime`'s `MessageHeaders`
107
+ * field-for-field so a child watcher gets the arrived message's envelope for
108
+ * its `exists` `MailboxEvent` without a substrate round-trip. The four
109
+ * unconditionally-dereferenced fields (`from`, `to`, `date`, `messageId`) are
110
+ * required; the rest are optional, matching the runtime type.
111
+ *
112
+ * Duplicated here as an arktype validator (rather than importing the TypeScript
113
+ * `MessageHeaders` type) so the IPC module validates the header block at the
114
+ * wire boundary, exactly as `OutboundMessagePayload` does for outbound mail.
115
+ */
116
+ export declare const MailboxNotifyHeaders: import("arktype/internal/variants/object.ts").ObjectType<{
117
+ from: string;
118
+ to: string[];
119
+ date: string;
120
+ messageId: string;
121
+ cc?: string[];
122
+ inReplyTo?: string;
123
+ references?: string[];
124
+ subject?: string;
125
+ listId?: string;
126
+ interchangeType?: "conversation.message" | "conversation.join" | "conversation.leave" | "offering.request" | "offering.response" | "offering.error" | "offering.discover" | "offering.catalog" | "payment.required" | "payment.receipt" | "payment.verified" | "approval.request" | "approval.granted" | "approval.denied" | "system.health" | "system.register" | "system.deregister" | "system.credential.refresh";
127
+ interchangeCorrelationId?: string;
128
+ interchangeTenantId?: string;
129
+ interchangeAgentId?: string;
130
+ interchangeSessionId?: string;
131
+ interchangeOfferingId?: string;
132
+ interchangeSchemaVersion?: string;
133
+ traceparent?: string;
134
+ tracestate?: string;
135
+ }, {}>;
136
+ export type MailboxNotifyHeaders = typeof MailboxNotifyHeaders.infer;
102
137
  /**
103
138
  * Discriminated union of every control-channel payload kind. The
104
139
  * `type` discriminator namespaces the control-plane vocabulary so a
@@ -112,6 +147,7 @@ export declare const ControlPayload: import("arktype/internal/variants/object.ts
112
147
  runId: string;
113
148
  messageId: string;
114
149
  receivedAt: number;
150
+ payload: unknown;
115
151
  };
116
152
  } | {
117
153
  type: "signal.deliver";
@@ -151,16 +187,35 @@ export declare const ControlPayload: import("arktype/internal/variants/object.ts
151
187
  id: string;
152
188
  provider: string;
153
189
  baseURL: string;
154
- apiKey: string;
190
+ credentialId: string;
155
191
  model: string;
156
192
  defaults?: {
157
193
  maxTokens?: number;
158
194
  providerOptions?: Record<string, unknown>;
159
195
  };
160
196
  capabilities?: string[];
197
+ quirks?: Record<string, unknown>;
161
198
  }[];
162
199
  defaultSource: string;
163
200
  };
201
+ } | {
202
+ type: "credentials-updated";
203
+ data: {
204
+ delivery: {
205
+ bindings: {
206
+ handle: string;
207
+ credentialId: string;
208
+ consumer: string;
209
+ }[];
210
+ materials: {
211
+ credentialId: string;
212
+ providerKey: string;
213
+ origin: string;
214
+ secret: string;
215
+ }[];
216
+ };
217
+ revoke?: string[];
218
+ };
164
219
  } | {
165
220
  type: "ready";
166
221
  data: {
@@ -239,6 +294,7 @@ export declare const ControlPayload: import("arktype/internal/variants/object.ts
239
294
  dataBase64: string;
240
295
  }[];
241
296
  inReplyTo?: string;
297
+ references?: string[];
242
298
  correlationId?: string;
243
299
  sessionId?: string;
244
300
  tenantId?: string;
@@ -269,6 +325,99 @@ export declare const ControlPayload: import("arktype/internal/variants/object.ts
269
325
  message: string;
270
326
  };
271
327
  };
328
+ } | {
329
+ type: "park.notify";
330
+ data: {
331
+ runId: string;
332
+ correlationId: string;
333
+ parkKind: "approval" | "input" | "signal-relay";
334
+ snapshot?: {
335
+ name: string;
336
+ description: string;
337
+ inputSchema: Record<string, unknown>;
338
+ arguments: Record<string, unknown>;
339
+ };
340
+ };
341
+ } | {
342
+ type: "parked-correlations.request";
343
+ data: {
344
+ requestId: string;
345
+ };
346
+ } | {
347
+ type: "parked-correlations.response";
348
+ data: {
349
+ requestId: string;
350
+ parked: {
351
+ runId: string;
352
+ correlationId: string;
353
+ parkKind: "approval" | "input" | "signal-relay";
354
+ snapshot?: {
355
+ name: string;
356
+ description: string;
357
+ inputSchema: Record<string, unknown>;
358
+ arguments: Record<string, unknown>;
359
+ };
360
+ }[];
361
+ };
362
+ } | {
363
+ type: "resumed.runs";
364
+ data: {
365
+ runIds: string[];
366
+ };
367
+ } | {
368
+ type: "mailbox.notify";
369
+ data: {
370
+ runId: string;
371
+ mailbox: string;
372
+ uid: number;
373
+ headers: {
374
+ from: string;
375
+ to: string[];
376
+ date: string;
377
+ messageId: string;
378
+ cc?: string[];
379
+ inReplyTo?: string;
380
+ references?: string[];
381
+ subject?: string;
382
+ listId?: string;
383
+ interchangeType?: "conversation.message" | "conversation.join" | "conversation.leave" | "offering.request" | "offering.response" | "offering.error" | "offering.discover" | "offering.catalog" | "payment.required" | "payment.receipt" | "payment.verified" | "approval.request" | "approval.granted" | "approval.denied" | "system.health" | "system.register" | "system.deregister" | "system.credential.refresh";
384
+ interchangeCorrelationId?: string;
385
+ interchangeTenantId?: string;
386
+ interchangeAgentId?: string;
387
+ interchangeSessionId?: string;
388
+ interchangeOfferingId?: string;
389
+ interchangeSchemaVersion?: string;
390
+ traceparent?: string;
391
+ tracestate?: string;
392
+ };
393
+ };
394
+ } | {
395
+ type: "mailbox.mutate.request";
396
+ data: {
397
+ requestId: string;
398
+ runId: string;
399
+ mailbox: string;
400
+ op: "addFlags" | "removeFlags";
401
+ uid: number;
402
+ flags: string[];
403
+ } | {
404
+ requestId: string;
405
+ runId: string;
406
+ mailbox: string;
407
+ op: "expunge";
408
+ };
409
+ } | {
410
+ type: "mailbox.mutate.response";
411
+ data: {
412
+ requestId: string;
413
+ result: {
414
+ ok: true;
415
+ expungedUids?: number[];
416
+ } | {
417
+ ok: false;
418
+ reason: string;
419
+ };
420
+ };
272
421
  }, {}>;
273
422
  export type ControlPayload = typeof ControlPayload.infer;
274
423
  export interface NdjsonWriter {