@agen-ai/agent-orchestration 0.0.0-stage → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +415 -2
  3. package/dist/catalog/parse.d.ts +3 -0
  4. package/dist/catalog/parse.js +13 -0
  5. package/dist/catalog/schemas.d.ts +8 -0
  6. package/dist/catalog/schemas.js +78 -0
  7. package/dist/catalog/types.d.ts +53 -0
  8. package/dist/catalog/types.js +0 -0
  9. package/dist/coordinator/admission.d.ts +7 -0
  10. package/dist/coordinator/admission.js +189 -0
  11. package/dist/coordinator/cancel.d.ts +7 -0
  12. package/dist/coordinator/cancel.js +111 -0
  13. package/dist/coordinator/create.d.ts +3 -0
  14. package/dist/coordinator/create.js +87 -0
  15. package/dist/coordinator/parse.d.ts +11 -0
  16. package/dist/coordinator/parse.js +60 -0
  17. package/dist/coordinator/read.d.ts +4 -0
  18. package/dist/coordinator/read.js +267 -0
  19. package/dist/coordinator/recovery.d.ts +4 -0
  20. package/dist/coordinator/recovery.js +24 -0
  21. package/dist/coordinator/shutdown.d.ts +7 -0
  22. package/dist/coordinator/shutdown.js +66 -0
  23. package/dist/coordinator/types.d.ts +154 -0
  24. package/dist/coordinator/types.js +0 -0
  25. package/dist/delivery/calls.d.ts +4 -0
  26. package/dist/delivery/calls.js +34 -0
  27. package/dist/delivery/journal.d.ts +7 -0
  28. package/dist/delivery/journal.js +57 -0
  29. package/dist/delivery/parse.d.ts +4 -0
  30. package/dist/delivery/parse.js +31 -0
  31. package/dist/delivery/recovery.d.ts +3 -0
  32. package/dist/delivery/recovery.js +18 -0
  33. package/dist/delivery/scheduler.d.ts +3 -0
  34. package/dist/delivery/scheduler.js +123 -0
  35. package/dist/delivery/setup.d.ts +7 -0
  36. package/dist/delivery/setup.js +37 -0
  37. package/dist/delivery/types.d.ts +36 -0
  38. package/dist/delivery/types.js +0 -0
  39. package/dist/execution/authority.d.ts +16 -0
  40. package/dist/execution/authority.js +86 -0
  41. package/dist/execution/cleanup.d.ts +3 -0
  42. package/dist/execution/cleanup.js +75 -0
  43. package/dist/execution/control.d.ts +6 -0
  44. package/dist/execution/control.js +231 -0
  45. package/dist/execution/finish.d.ts +6 -0
  46. package/dist/execution/finish.js +49 -0
  47. package/dist/execution/journal.d.ts +19 -0
  48. package/dist/execution/journal.js +28 -0
  49. package/dist/execution/prepare.d.ts +3 -0
  50. package/dist/execution/prepare.js +153 -0
  51. package/dist/execution/scheduler.d.ts +4 -0
  52. package/dist/execution/scheduler.js +136 -0
  53. package/dist/execution/state.d.ts +107 -0
  54. package/dist/execution/state.js +118 -0
  55. package/dist/execution/stream.d.ts +9 -0
  56. package/dist/execution/stream.js +108 -0
  57. package/dist/host/types.d.ts +95 -0
  58. package/dist/host/types.js +0 -0
  59. package/dist/index.d.ts +20 -0
  60. package/dist/index.js +58 -0
  61. package/dist/mcp/bridge.d.ts +4 -0
  62. package/dist/mcp/bridge.js +222 -0
  63. package/dist/mcp/http.d.ts +11 -0
  64. package/dist/mcp/http.js +73 -0
  65. package/dist/mcp/index.d.ts +3 -0
  66. package/dist/mcp/index.js +4 -0
  67. package/dist/mcp/limits.d.ts +10 -0
  68. package/dist/mcp/limits.js +30 -0
  69. package/dist/mcp/protocol.d.ts +50 -0
  70. package/dist/mcp/protocol.js +81 -0
  71. package/dist/mcp/types.d.ts +22 -0
  72. package/dist/mcp/types.js +0 -0
  73. package/dist/policy/matching.d.ts +4 -0
  74. package/dist/policy/matching.js +18 -0
  75. package/dist/policy/parse.d.ts +3 -0
  76. package/dist/policy/parse.js +13 -0
  77. package/dist/policy/resolve.d.ts +7 -0
  78. package/dist/policy/resolve.js +67 -0
  79. package/dist/policy/schemas.d.ts +5 -0
  80. package/dist/policy/schemas.js +59 -0
  81. package/dist/policy/types.d.ts +60 -0
  82. package/dist/policy/types.js +0 -0
  83. package/dist/shared/bounds.d.ts +6 -0
  84. package/dist/shared/bounds.js +88 -0
  85. package/dist/shared/errors.d.ts +9 -0
  86. package/dist/shared/errors.js +27 -0
  87. package/dist/shared/identity.d.ts +6 -0
  88. package/dist/shared/identity.js +32 -0
  89. package/dist/shared/immutable.d.ts +2 -0
  90. package/dist/shared/immutable.js +10 -0
  91. package/dist/shared/limits.d.ts +32 -0
  92. package/dist/shared/limits.js +69 -0
  93. package/dist/shared/operational-errors.d.ts +7 -0
  94. package/dist/shared/operational-errors.js +14 -0
  95. package/dist/shared/schemas.d.ts +11 -0
  96. package/dist/shared/schemas.js +23 -0
  97. package/dist/shared/text.d.ts +2 -0
  98. package/dist/shared/text.js +15 -0
  99. package/dist/store/memory.d.ts +7 -0
  100. package/dist/store/memory.js +215 -0
  101. package/dist/store/pages.d.ts +16 -0
  102. package/dist/store/pages.js +46 -0
  103. package/dist/store/parse.d.ts +5 -0
  104. package/dist/store/parse.js +137 -0
  105. package/dist/store/types.d.ts +219 -0
  106. package/dist/store/types.js +0 -0
  107. package/dist/store-adapter/admission.d.ts +6 -0
  108. package/dist/store-adapter/admission.js +90 -0
  109. package/dist/store-adapter/context.d.ts +20 -0
  110. package/dist/store-adapter/context.js +107 -0
  111. package/dist/store-adapter/delivery.d.ts +15 -0
  112. package/dist/store-adapter/delivery.js +81 -0
  113. package/dist/store-adapter/execution.d.ts +12 -0
  114. package/dist/store-adapter/execution.js +151 -0
  115. package/dist/store-adapter/index.d.ts +7 -0
  116. package/dist/store-adapter/index.js +27 -0
  117. package/dist/store-adapter/lifecycle.d.ts +15 -0
  118. package/dist/store-adapter/lifecycle.js +80 -0
  119. package/dist/store-adapter/plan.d.ts +7 -0
  120. package/dist/store-adapter/plan.js +168 -0
  121. package/dist/store-adapter/types.d.ts +45 -0
  122. package/dist/store-adapter/types.js +0 -0
  123. package/dist/tasks/failure.d.ts +4 -0
  124. package/dist/tasks/failure.js +24 -0
  125. package/dist/tasks/parse.d.ts +18 -0
  126. package/dist/tasks/parse.js +66 -0
  127. package/dist/tasks/schemas.d.ts +47 -0
  128. package/dist/tasks/schemas.js +215 -0
  129. package/dist/tasks/types.d.ts +192 -0
  130. package/dist/tasks/types.js +0 -0
  131. package/dist/tools/create.d.ts +4 -0
  132. package/dist/tools/create.js +69 -0
  133. package/dist/tools/errors.d.ts +4 -0
  134. package/dist/tools/errors.js +35 -0
  135. package/dist/tools/guidance.d.ts +4 -0
  136. package/dist/tools/guidance.js +28 -0
  137. package/dist/tools/handlers.d.ts +4 -0
  138. package/dist/tools/handlers.js +84 -0
  139. package/dist/tools/projection.d.ts +13 -0
  140. package/dist/tools/projection.js +72 -0
  141. package/dist/tools/schemas.d.ts +6 -0
  142. package/dist/tools/schemas.js +93 -0
  143. package/dist/tools/types.d.ts +28 -0
  144. package/dist/tools/types.js +0 -0
  145. package/package.json +64 -3
@@ -0,0 +1,189 @@
1
+ import { admittedTarget, effectiveChoices, readCeiling, sameTarget } from "../execution/authority.js";
2
+ import { assertCompletionPolicy } from "../delivery/setup.js";
3
+ import { steerRun } from "../execution/control.js";
4
+ import { assertAccepting, schedule } from "../execution/scheduler.js";
5
+ import { sameScopeIdentity } from "../execution/state.js";
6
+ import { createDelegationId, delegationInputDigest } from "../shared/identity.js";
7
+ import { failDelegation } from "../shared/operational-errors.js";
8
+ import { parseSendTaskInput, parseSpawnTaskInput } from "./parse.js";
9
+ async function priorOperation(state, binding, operationId, digest, kind) {
10
+ const read = await state.options.store.read({ kind: "operation", parent: binding.scope, operationId });
11
+ if (read.kind !== "operation" || !read.operation) return void 0;
12
+ if (read.operation.inputDigest !== digest || read.operation.kind !== kind) failDelegation("operation_conflict", "The operation identity already has different retained input.");
13
+ const { task } = await state.task(read.operation.taskId);
14
+ state.options.host.assertResultAccess({ scope: binding.scope, task });
15
+ return read.operation;
16
+ }
17
+ async function admissionReceipt(state, operation, duplicate) {
18
+ const run = await state.run(operation.taskId, operation.runId);
19
+ return {
20
+ storeId: state.options.store.storeId,
21
+ operationId: operation.operationId,
22
+ taskId: operation.taskId,
23
+ runId: operation.runId,
24
+ target: run.admittedTarget,
25
+ revision: operation.receipt.taskRevision,
26
+ status: "queued",
27
+ duplicate
28
+ };
29
+ }
30
+ function createAdmissionClient(state, binding) {
31
+ return {
32
+ async spawn(raw) {
33
+ const input = parseSpawnTaskInput(raw, state.options.limits);
34
+ state.options.host.assertResultAccess({ scope: binding.scope });
35
+ const normalized = {
36
+ kind: "spawn",
37
+ target: input.target,
38
+ expectedPolicyRevision: input.expectedPolicyRevision,
39
+ input: input.input,
40
+ completionPolicy: input.completionPolicy ?? "collect",
41
+ timeoutMs: input.timeoutMs ?? state.options.limits.runTimeoutMs
42
+ };
43
+ const digest = delegationInputDigest(normalized);
44
+ const receipt = await state.gate(async () => {
45
+ const prior = await priorOperation(state, binding, input.operationId, digest, "admit");
46
+ if (prior) return admissionReceipt(state, prior, true);
47
+ assertAccepting(state);
48
+ assertCompletionPolicy(state, normalized.completionPolicy);
49
+ const choices = await effectiveChoices(state, binding);
50
+ const target = admittedTarget(choices, input.target, input.expectedPolicyRevision);
51
+ const depth = binding.depth ?? 1;
52
+ if (depth > state.options.limits.maxDepth) failDelegation("capacity_exceeded", "The managed descendant depth is exhausted.");
53
+ const created = Date.now();
54
+ const taskId = createDelegationId();
55
+ const runId = createDelegationId();
56
+ const commit = await state.commit({
57
+ owner: state.owner,
58
+ operationId: input.operationId,
59
+ inputDigest: digest,
60
+ taskId,
61
+ expectedTaskRevision: 0,
62
+ kind: "admit",
63
+ admission: {
64
+ parent: binding.scope,
65
+ ...binding.ancestor ? { ancestorTaskId: binding.ancestor.taskId } : {},
66
+ depth,
67
+ policyCeiling: choices.ceiling,
68
+ completionPolicy: normalized.completionPolicy,
69
+ runId,
70
+ target: target.reference,
71
+ policyRevision: choices.resolved.policyRevision,
72
+ originPolicyRevision: choices.originPolicyRevision,
73
+ input: input.input,
74
+ createdAt: new Date(created).toISOString(),
75
+ deadlineAt: new Date(created + normalized.timeoutMs).toISOString(),
76
+ queuedStartDeadlineAt: new Date(created + state.options.limits.queuedStartTimeoutMs).toISOString()
77
+ }
78
+ });
79
+ return {
80
+ storeId: state.options.store.storeId,
81
+ operationId: input.operationId,
82
+ taskId,
83
+ runId,
84
+ target: target.reference,
85
+ revision: commit.taskRevision,
86
+ status: "queued",
87
+ duplicate: false
88
+ };
89
+ });
90
+ schedule(state);
91
+ return receipt;
92
+ },
93
+ async send(raw) {
94
+ const input = parseSendTaskInput(raw, state.options.limits);
95
+ const { task } = await state.task(input.taskId);
96
+ if (!sameScopeIdentity(binding.scope, task.parent)) failDelegation("request_unavailable", "The managed task does not belong to this parent scope.");
97
+ state.options.host.assertResultAccess({ scope: binding.scope, task });
98
+ const { operationId: _operationId, ...semantic } = input;
99
+ const digest = delegationInputDigest({ kind: "send", ...semantic });
100
+ const prior = await priorOperation(state, binding, input.operationId, digest, input.mode === "steer" ? "steer" : "admit");
101
+ if (prior) {
102
+ if (prior.kind === "admit") return { status: "queued", admission: await admissionReceipt(state, prior, true), duplicate: true };
103
+ const pending = state.live.get(prior.runId)?.pendingOperations.get(input.operationId);
104
+ if (pending) return pending.promise.then((receipt2) => ({ ...receipt2, duplicate: true }));
105
+ return {
106
+ status: prior.disposition === "delivered" ? "delivered" : prior.disposition === "rejected" ? "rejected" : "delivery_uncertain",
107
+ taskId: prior.taskId,
108
+ runId: prior.runId,
109
+ operationId: input.operationId,
110
+ duplicate: true
111
+ };
112
+ }
113
+ assertAccepting(state);
114
+ assertCompletionPolicy(state, task.completionPolicy);
115
+ state.options.host.assertControl({ scope: binding.scope, task });
116
+ if (task.state === "recovery_required" || task.state === "retired") failDelegation("recovery_required", "This managed task requires explicit recovery retirement.");
117
+ const choices = await effectiveChoices(state, binding);
118
+ const ceiling = await readCeiling(state, task.policyCeilingRef);
119
+ const target = admittedTarget({ ...choices, targets: choices.targets.filter((entry) => ceiling.targets.some((ref) => sameTarget(ref, entry.reference))) }, input.target, input.expectedPolicyRevision);
120
+ if (input.mode === "steer") {
121
+ const live = [...state.live.values()].find((entry) => entry.taskId === task.taskId && entry.stream);
122
+ if (!live) failDelegation("unsupported_operation", "This managed child has no active steerable turn.");
123
+ return steerRun(state, live, input, digest, choices.originPolicyRevision);
124
+ }
125
+ const continuationMode = input.mode;
126
+ const receipt = await state.gate(async () => {
127
+ const retry = await priorOperation(state, binding, input.operationId, digest, "admit");
128
+ if (retry) return admissionReceipt(state, retry, true);
129
+ const current = await state.task(task.taskId);
130
+ const previous = await state.run(task.taskId, current.task.latestRunId);
131
+ if (current.runs.items.some((run) => run.phase === "queued")) failDelegation("capacity_exceeded", "This managed task already has its queued next turn.");
132
+ const live = state.live.get(previous.runId);
133
+ const continuation = state.continuations.get(task.taskId);
134
+ if (input.mode === "next_turn") {
135
+ if (previous.phase !== "running" || !live?.resources?.continuation || !live.session) failDelegation("unsupported_operation", "A queued next turn requires an active safely resumable conversation.");
136
+ if (!sameTarget(live.target.reference, target.reference) && !live.resources.continuation.allowTargetChange) failDelegation("unsupported_operation", "This conversation does not authorize a target change.");
137
+ } else if (previous.phase !== "settled" || !previous.outcome || previous.outcome.kind === "recovery_required" || !continuation) {
138
+ failDelegation("unsupported_operation", "A follow-up requires a definitive settled conversation with exact resume authority.");
139
+ }
140
+ const previousTarget = live?.target ?? continuation?.target;
141
+ if (!previousTarget || previousTarget.instanceId !== target.instanceId || previousTarget.providerKey !== target.providerKey) failDelegation("unsupported_operation", "A continuation must retain its exact provider instance.");
142
+ const created = Date.now();
143
+ const runId = createDelegationId();
144
+ const commit = await state.commit({
145
+ owner: state.owner,
146
+ operationId: input.operationId,
147
+ inputDigest: digest,
148
+ taskId: task.taskId,
149
+ expectedTaskRevision: current.task.revision,
150
+ runId: previous.runId,
151
+ expectedRunRevision: previous.revision,
152
+ kind: "admit",
153
+ admission: {
154
+ parent: task.parent,
155
+ ...task.ancestorTaskId ? { ancestorTaskId: task.ancestorTaskId } : {},
156
+ depth: task.depth,
157
+ policyCeiling: ceiling,
158
+ completionPolicy: task.completionPolicy,
159
+ runId,
160
+ previousRunId: previous.runId,
161
+ continuationMode,
162
+ target: target.reference,
163
+ policyRevision: choices.resolved.policyRevision,
164
+ originPolicyRevision: choices.originPolicyRevision,
165
+ input: input.input,
166
+ createdAt: new Date(created).toISOString(),
167
+ deadlineAt: new Date(created + state.options.limits.runTimeoutMs).toISOString(),
168
+ queuedStartDeadlineAt: new Date(created + state.options.limits.queuedStartTimeoutMs).toISOString()
169
+ }
170
+ });
171
+ return {
172
+ storeId: state.options.store.storeId,
173
+ operationId: input.operationId,
174
+ taskId: task.taskId,
175
+ runId,
176
+ target: target.reference,
177
+ revision: commit.taskRevision,
178
+ status: "queued",
179
+ duplicate: false
180
+ };
181
+ });
182
+ schedule(state);
183
+ return { status: "queued", admission: receipt, duplicate: receipt.duplicate };
184
+ }
185
+ };
186
+ }
187
+ export {
188
+ createAdmissionClient
189
+ };
@@ -0,0 +1,7 @@
1
+ import { type CoordinatorState, type ParentBinding } from "../execution/state.js";
2
+ import type { DelegationCancelReceipt } from "./types.js";
3
+ export declare function createCancelClient(state: CoordinatorState, binding: ParentBinding): (input: Readonly<{
4
+ operationId: string;
5
+ taskId: string;
6
+ }>) => Promise<DelegationCancelReceipt>;
7
+ //# sourceMappingURL=cancel.d.ts.map
@@ -0,0 +1,111 @@
1
+ import { cancelLive } from "../execution/control.js";
2
+ import { schedule } from "../execution/scheduler.js";
3
+ import { sameScopeIdentity, now } from "../execution/state.js";
4
+ import { delegationInputDigest, delegationSubordinateId } from "../shared/identity.js";
5
+ import { failDelegation } from "../shared/operational-errors.js";
6
+ import { parseOperationId, parseTaskId } from "./parse.js";
7
+ async function canonicalCancel(state, taskId, runId) {
8
+ let cursor;
9
+ do {
10
+ const page = await state.options.store.read({ kind: "operations", taskId, runId, limit: state.options.limits.maxPageRecords, ...cursor ? { cursor } : {} });
11
+ if (page.kind !== "operations") failDelegation("store_failed", "The operation page does not match its query.");
12
+ const cancel = page.page.items.find((operation) => operation.kind === "cancel");
13
+ if (cancel) return cancel;
14
+ cursor = page.page.cursor;
15
+ } while (cursor);
16
+ return void 0;
17
+ }
18
+ async function includesRun(state, operation, rootOrdinal, run) {
19
+ if (run.ordinal < rootOrdinal) return false;
20
+ if (run.ordinal === rootOrdinal) return true;
21
+ const admission = await state.options.store.read({ kind: "operation", parent: operation.parent, operationId: run.admissionOperationId });
22
+ if (admission.kind !== "operation" || !admission.operation || admission.operation.kind !== "admit") failDelegation("store_failed", "The cancellation admission history is unavailable.");
23
+ return admission.operation.receipt.taskRevision <= operation.receipt.taskRevision;
24
+ }
25
+ async function retainedReceipt(state, operation, duplicate) {
26
+ const root = await state.run(operation.taskId, operation.runId);
27
+ let status = "confirmed";
28
+ let cursor;
29
+ do {
30
+ const page = await state.options.store.read({ kind: "task", taskId: operation.taskId, limit: state.options.limits.maxPageRecords, ...cursor ? { cursor } : {} });
31
+ if (page.kind !== "task" || !page.view) failDelegation("store_failed", "The cancellation task history is unavailable.");
32
+ for (const run of page.view.runs.items) {
33
+ if (!await includesRun(state, operation, root.ordinal, run)) continue;
34
+ if (run.outcome?.kind === "recovery_required") status = "recovery_required";
35
+ else if (run.phase !== "settled" && status !== "recovery_required") status = "requested";
36
+ }
37
+ cursor = page.view.runs.cursor;
38
+ } while (cursor);
39
+ return { status, operationId: operation.operationId, taskId: operation.taskId, duplicate };
40
+ }
41
+ function createCancelClient(state, binding) {
42
+ return async (input) => {
43
+ const operationId = parseOperationId(input.operationId);
44
+ const taskId = parseTaskId(input.taskId);
45
+ const digest = delegationInputDigest({ kind: "cancel", taskId });
46
+ const captured = await state.gate(async () => {
47
+ const first = await state.task(taskId);
48
+ if (!sameScopeIdentity(binding.scope, first.task.parent)) failDelegation("request_unavailable", "The managed task does not belong to this parent scope.");
49
+ state.options.host.assertResultAccess({ scope: binding.scope, task: first.task });
50
+ state.options.host.assertControl({ scope: binding.scope, task: first.task });
51
+ const liveRuns = /* @__PURE__ */ new Set();
52
+ const prior = await state.options.store.read({ kind: "operation", parent: binding.scope, operationId });
53
+ let canonical;
54
+ if (prior.kind === "operation" && prior.operation) {
55
+ if (prior.operation.kind !== "cancel" || prior.operation.inputDigest !== digest || prior.operation.taskId !== taskId) failDelegation("operation_conflict", "The operation identity already has different retained input.");
56
+ canonical = prior.operation;
57
+ }
58
+ let rootOrdinal = canonical ? (await state.run(taskId, canonical.runId)).ordinal : 0;
59
+ let duplicate = canonical !== void 0;
60
+ let cursor;
61
+ do {
62
+ const page = cursor === void 0 ? first : await state.options.store.read({ kind: "task", taskId, cursor, limit: state.options.limits.maxPageRecords }).then((read) => {
63
+ if (read.kind !== "task" || !read.view) return failDelegation("request_unavailable", "The managed task is unavailable.");
64
+ return read.view;
65
+ });
66
+ state.options.host.assertControl({ scope: binding.scope, task: page.task });
67
+ for (const run of page.runs.items) {
68
+ if (canonical) {
69
+ if (!await includesRun(state, canonical, rootOrdinal, run)) continue;
70
+ } else if (run.phase === "settled" && (page.task.state === "active" || run.runId !== page.task.latestRunId)) continue;
71
+ const existing = await canonicalCancel(state, taskId, run.runId);
72
+ if (existing && !canonical) failDelegation("operation_conflict", `Cancellation is already recorded; retry operationId ${existing.operationId}.`);
73
+ if (!existing) {
74
+ const id = canonical ? delegationSubordinateId(run.runId, `cancel:${canonical.operationId}`) : operationId;
75
+ const [{ task }, current] = await Promise.all([state.task(taskId), state.run(taskId, run.runId)]);
76
+ const receipt = await state.commit({
77
+ owner: state.owner,
78
+ operationId: id,
79
+ inputDigest: digest,
80
+ taskId,
81
+ expectedTaskRevision: task.revision,
82
+ runId: run.runId,
83
+ expectedRunRevision: current.revision,
84
+ kind: "cancel",
85
+ at: now(),
86
+ reason: "user_requested"
87
+ });
88
+ if (!canonical) {
89
+ const recorded = await state.options.store.read({ kind: "operation", parent: binding.scope, operationId: receipt.operationId ?? id });
90
+ if (recorded.kind !== "operation" || !recorded.operation) failDelegation("store_failed", "The canonical cancellation receipt is unavailable.");
91
+ canonical = recorded.operation;
92
+ rootOrdinal = run.ordinal;
93
+ }
94
+ duplicate ||= receipt.duplicate;
95
+ }
96
+ const live = state.live.get(run.runId);
97
+ if (live) liveRuns.add(live);
98
+ }
99
+ cursor = page.runs.cursor;
100
+ } while (cursor);
101
+ if (!canonical) failDelegation("store_failed", "The canonical cancellation receipt is unavailable.");
102
+ return { operation: canonical, duplicate, liveRuns };
103
+ });
104
+ await Promise.all([...captured.liveRuns].map((live) => cancelLive(state, live, "user_requested")));
105
+ schedule(state);
106
+ return retainedReceipt(state, captured.operation, captured.duplicate);
107
+ };
108
+ }
109
+ export {
110
+ createCancelClient
111
+ };
@@ -0,0 +1,3 @@
1
+ import type { CreateDelegationCoordinatorOptions, DelegationCoordinator } from "./types.js";
2
+ export declare function createDelegationCoordinator(options: CreateDelegationCoordinatorOptions): Promise<DelegationCoordinator>;
3
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1,87 @@
1
+ import { bindingCeiling } from "../execution/authority.js";
2
+ import { assertRetainedDeliverySetup, validateDeliverySetup } from "../delivery/setup.js";
3
+ import { installDeliveryScheduler } from "../delivery/scheduler.js";
4
+ import { recoverNotificationClaims } from "../delivery/recovery.js";
5
+ import { cancelLive, resolveLiveRequest } from "../execution/control.js";
6
+ import { CoordinatorState, now } from "../execution/state.js";
7
+ import { schedule } from "../execution/scheduler.js";
8
+ import { delegationInputDigest } from "../shared/identity.js";
9
+ import { parseDelegationLimits } from "../shared/limits.js";
10
+ import { failDelegation } from "../shared/operational-errors.js";
11
+ import { parseDelegationParentScope } from "../tasks/parse.js";
12
+ import { createAdmissionClient } from "./admission.js";
13
+ import { createCancelClient } from "./cancel.js";
14
+ import { parseOperationId, parseTaskId } from "./parse.js";
15
+ import { createReadClient } from "./read.js";
16
+ import { recoverRuns } from "./recovery.js";
17
+ import { shutdown } from "./shutdown.js";
18
+ async function createDelegationCoordinator(options) {
19
+ const limits = parseDelegationLimits(options.limits);
20
+ if (options.store.contractVersion !== 3 || delegationInputDigest(limits) !== delegationInputDigest(options.store.limits)) {
21
+ failDelegation("store_failed", "The coordinator requires the exact store contract and limits.");
22
+ }
23
+ validateDeliverySetup(options);
24
+ const owner = await options.store.acquireOwner();
25
+ const state = new CoordinatorState({ ...options, limits }, owner);
26
+ state.onFailure = () => {
27
+ for (const live of state.live.values()) {
28
+ live.uncertain = "storage_failed";
29
+ live.lifetime.abort(new DOMException("Managed storage ownership failed.", "AbortError"));
30
+ void cancelLive(state, live, "storage_failed").catch(() => void 0);
31
+ }
32
+ };
33
+ try {
34
+ await assertRetainedDeliverySetup(state);
35
+ let cursor;
36
+ do {
37
+ cursor = (await recoverRuns(state, limits.maxPageRecords, cursor, false)).cursor;
38
+ } while (cursor);
39
+ await recoverNotificationClaims(state);
40
+ } catch (error) {
41
+ await options.store.releaseOwner(owner);
42
+ throw error;
43
+ }
44
+ schedule(state);
45
+ installDeliveryScheduler(state);
46
+ state.wakeDelivery?.();
47
+ return Object.freeze({
48
+ async bindParent(input) {
49
+ const scope = parseDelegationParentScope(input.scope);
50
+ options.host.assertResultAccess({ scope });
51
+ const initial = { scope, ...input.ancestor ? { ancestor: { taskId: parseTaskId(input.ancestor.taskId), runId: parseTaskId(input.ancestor.runId) } } : {} };
52
+ const ceiling = await bindingCeiling(state, initial);
53
+ const depth = initial.ancestor ? (await state.task(initial.ancestor.taskId)).task.depth + 1 : 1;
54
+ const binding = { ...initial, ...ceiling ? { ceiling } : {}, depth };
55
+ return Object.freeze({ ...createReadClient(state, binding), ...createAdmissionClient(state, binding), cancel: createCancelClient(state, binding) });
56
+ },
57
+ resolveRequest: (input) => resolveLiveRequest(state, input),
58
+ recover: (input) => recoverRuns(state, input.limit, input.cursor),
59
+ async retireRecoveryTask(input) {
60
+ const operationId = parseOperationId(input.operationId);
61
+ const taskId = parseTaskId(input.taskId);
62
+ if (typeof input.reason !== "string" || input.reason.length < 1 || input.reason.length > 512) failDelegation("capacity_exceeded", "Recovery retirement requires a bounded reason.");
63
+ const { task } = await state.task(taskId);
64
+ options.host.assertResultAccess({ scope: task.parent, task });
65
+ options.host.assertControl({ scope: task.parent, task });
66
+ if ([...state.live.values()].some((live) => live.taskId === taskId)) failDelegation("recovery_required", "Retained execution resources must quiesce before retirement.");
67
+ await state.gate(async () => {
68
+ const current = await state.task(taskId);
69
+ await state.commit({
70
+ owner,
71
+ operationId,
72
+ inputDigest: delegationInputDigest({ kind: "retire_recovery", taskId, reason: input.reason }),
73
+ taskId,
74
+ expectedTaskRevision: current.task.revision,
75
+ kind: "retire_recovery",
76
+ reason: input.reason,
77
+ at: now()
78
+ });
79
+ });
80
+ return state.task(taskId);
81
+ },
82
+ dispose: (input) => shutdown(state, input)
83
+ });
84
+ }
85
+ export {
86
+ createDelegationCoordinator
87
+ };
@@ -0,0 +1,11 @@
1
+ import type { AgentRequestResolution } from "@agen-ai/agent-protocol";
2
+ import { z } from "zod/v4";
3
+ import type { DelegationLimits } from "../shared/limits.js";
4
+ import type { DelegationSendTaskInput, DelegationSpawnTaskInput } from "./types.js";
5
+ export declare function parseCoordinatorInput<Value>(schema: z.ZodType<Value>, input: unknown): Value;
6
+ export declare function parseSpawnTaskInput(input: unknown, limits: DelegationLimits): DelegationSpawnTaskInput;
7
+ export declare function parseSendTaskInput(input: unknown, limits: DelegationLimits): DelegationSendTaskInput;
8
+ export declare const parseOperationId: (input: unknown) => string;
9
+ export declare const parseTaskId: (input: unknown) => string;
10
+ export declare const parseRequestResolution: (input: unknown) => AgentRequestResolution;
11
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1,60 @@
1
+ import { AgentRequestResolutionSchema, AgentTurnInputContentSchema } from "@agen-ai/agent-protocol/zod";
2
+ import { z } from "zod/v4";
3
+ import { copyBoundedDelegationData } from "../shared/bounds.js";
4
+ import { delegationSchemaError } from "../shared/errors.js";
5
+ import { delegationDataBytes } from "../shared/identity.js";
6
+ import { failDelegation } from "../shared/operational-errors.js";
7
+ import { CompletionPolicySchema, TargetReferenceSchema } from "../tasks/schemas.js";
8
+ const operation = z.uuid();
9
+ const revision = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
10
+ const timeout = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
11
+ const spawn = z.strictObject({
12
+ operationId: operation,
13
+ target: TargetReferenceSchema,
14
+ expectedPolicyRevision: revision,
15
+ input: AgentTurnInputContentSchema,
16
+ completionPolicy: CompletionPolicySchema.optional(),
17
+ timeoutMs: timeout.optional()
18
+ });
19
+ const send = z.strictObject({
20
+ operationId: operation,
21
+ taskId: z.uuid(),
22
+ mode: z.enum(["steer", "next_turn", "follow_up"]),
23
+ input: AgentTurnInputContentSchema,
24
+ target: TargetReferenceSchema,
25
+ expectedPolicyRevision: revision
26
+ });
27
+ function parseCoordinatorInput(schema, input) {
28
+ const captured = copyBoundedDelegationData(input);
29
+ const parsed = schema.safeParse(captured);
30
+ if (!parsed.success) return delegationSchemaError(parsed.error, captured);
31
+ return parsed.data;
32
+ }
33
+ function inputLimit(input, limits) {
34
+ const characters = input.parts.reduce((count, part) => count + (part.type === "text" ? part.text.length : 0), input.summary?.length ?? 0);
35
+ if (delegationDataBytes(input) > limits.maxInputBytes || characters > limits.maxInputTextCharacters) {
36
+ failDelegation("capacity_exceeded", "Managed task input exceeds its configured content limit.");
37
+ }
38
+ }
39
+ function parseSpawnTaskInput(input, limits) {
40
+ const parsed = parseCoordinatorInput(spawn, input);
41
+ inputLimit(parsed.input, limits);
42
+ if (parsed.timeoutMs !== void 0 && parsed.timeoutMs > limits.runTimeoutMs) failDelegation("capacity_exceeded", "Task timeout exceeds the configured run deadline.");
43
+ return parsed;
44
+ }
45
+ function parseSendTaskInput(input, limits) {
46
+ const parsed = parseCoordinatorInput(send, input);
47
+ inputLimit(parsed.input, limits);
48
+ return parsed;
49
+ }
50
+ const parseOperationId = (input) => parseCoordinatorInput(operation, input);
51
+ const parseTaskId = (input) => parseCoordinatorInput(z.uuid(), input);
52
+ const parseRequestResolution = (input) => parseCoordinatorInput(AgentRequestResolutionSchema, input);
53
+ export {
54
+ parseCoordinatorInput,
55
+ parseOperationId,
56
+ parseRequestResolution,
57
+ parseSendTaskInput,
58
+ parseSpawnTaskInput,
59
+ parseTaskId
60
+ };
@@ -0,0 +1,4 @@
1
+ import { type CoordinatorState, type ParentBinding } from "../execution/state.js";
2
+ import type { DelegationClient } from "./types.js";
3
+ export declare function createReadClient(state: CoordinatorState, binding: ParentBinding): Pick<DelegationClient, "bindingSnapshot" | "targets" | "inspect" | "observe" | "wait">;
4
+ //# sourceMappingURL=read.d.ts.map