nexus-ai-pro 2.0.0 → 2.2.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 (282) hide show
  1. package/API_STABILITY.md +65 -0
  2. package/CHANGELOG.md +267 -1
  3. package/MIGRATING.md +1 -1
  4. package/README.md +17 -8
  5. package/dist/agent/create-agent.d.ts +9 -1
  6. package/dist/agent/create-agent.js +40 -1
  7. package/dist/cache/memory-cache.d.ts +8 -0
  8. package/dist/cache/memory-cache.js +9 -0
  9. package/dist/cache/semantic-cache.d.ts +6 -3
  10. package/dist/cache/semantic-cache.js +5 -2
  11. package/dist/cli/args.js +3 -0
  12. package/dist/cli/db.d.ts +16 -4
  13. package/dist/cli/db.js +169 -22
  14. package/dist/cli/doctor.d.ts +17 -0
  15. package/dist/cli/doctor.js +53 -0
  16. package/dist/cli/graph.d.ts +9 -0
  17. package/dist/cli/graph.js +47 -0
  18. package/dist/cli.js +21 -2
  19. package/dist/core/lifecycle.js +11 -6
  20. package/dist/core/nexus.d.ts +12 -2
  21. package/dist/core/nexus.js +106 -23
  22. package/dist/doctor/index.d.ts +90 -0
  23. package/dist/doctor/index.js +237 -0
  24. package/dist/evals/judge.d.ts +11 -0
  25. package/dist/evals/judge.js +33 -0
  26. package/dist/evaluate/index.d.ts +1 -0
  27. package/dist/evaluate/index.js +1 -0
  28. package/dist/evaluate/provenance.d.ts +22 -0
  29. package/dist/evaluate/provenance.js +10 -0
  30. package/dist/evaluate/run.js +20 -4
  31. package/dist/graph/durability.d.ts +27 -0
  32. package/dist/graph/durability.js +66 -0
  33. package/dist/graph/errors.d.ts +30 -4
  34. package/dist/graph/errors.js +18 -2
  35. package/dist/graph/event-stream.d.ts +75 -0
  36. package/dist/graph/event-stream.js +289 -0
  37. package/dist/graph/functional.d.ts +80 -7
  38. package/dist/graph/functional.js +138 -35
  39. package/dist/graph/graph.d.ts +56 -8
  40. package/dist/graph/graph.js +331 -49
  41. package/dist/graph/index.d.ts +4 -2
  42. package/dist/graph/index.js +3 -1
  43. package/dist/graph/lint.d.ts +57 -0
  44. package/dist/graph/lint.js +141 -0
  45. package/dist/graph/run-control.d.ts +28 -0
  46. package/dist/graph/run-control.js +26 -0
  47. package/dist/images/evals.js +4 -2
  48. package/dist/operations/adapters.d.ts +52 -4
  49. package/dist/operations/adapters.js +194 -7
  50. package/dist/operations/runner.js +14 -15
  51. package/dist/operations/stats.js +8 -1
  52. package/dist/operations/store.d.ts +5 -1
  53. package/dist/operations/store.js +7 -0
  54. package/dist/ops/circuit-breaker.d.ts +52 -0
  55. package/dist/ops/circuit-breaker.js +4 -0
  56. package/dist/ops/circuit-store.d.ts +13 -2
  57. package/dist/ops/circuit-store.js +68 -0
  58. package/dist/ops/circuit-sync.d.ts +17 -0
  59. package/dist/ops/circuit-sync.js +86 -0
  60. package/dist/ops/health.d.ts +24 -0
  61. package/dist/ops/health.js +38 -10
  62. package/dist/ops/index.d.ts +1 -1
  63. package/dist/ops/index.js +1 -1
  64. package/dist/ops/rate-limit-adapters.d.ts +23 -0
  65. package/dist/ops/rate-limit-adapters.js +34 -0
  66. package/dist/ops/rate-limiter.d.ts +14 -2
  67. package/dist/ops/rate-limiter.js +31 -0
  68. package/dist/postgres/circuits.d.ts +21 -4
  69. package/dist/postgres/circuits.js +65 -4
  70. package/dist/postgres/client.d.ts +0 -2
  71. package/dist/postgres/client.js +0 -4
  72. package/dist/postgres/evaluate.d.ts +16 -4
  73. package/dist/postgres/evaluate.js +17 -5
  74. package/dist/postgres/index.d.ts +32 -11
  75. package/dist/postgres/index.js +65 -31
  76. package/dist/postgres/migrations.d.ts +60 -0
  77. package/dist/postgres/migrations.js +121 -0
  78. package/dist/postgres/operations.d.ts +14 -3
  79. package/dist/postgres/operations.js +45 -15
  80. package/dist/postgres/prompts.d.ts +11 -2
  81. package/dist/postgres/prompts.js +14 -3
  82. package/dist/postgres/rollups.d.ts +35 -0
  83. package/dist/postgres/rollups.js +129 -0
  84. package/dist/postgres/store.d.ts +11 -2
  85. package/dist/postgres/store.js +14 -3
  86. package/dist/postgres/traces.d.ts +13 -3
  87. package/dist/postgres/traces.js +25 -3
  88. package/dist/postgres/vectors.d.ts +11 -2
  89. package/dist/postgres/vectors.js +14 -3
  90. package/dist/router/auto-router.d.ts +34 -7
  91. package/dist/router/auto-router.js +201 -68
  92. package/dist/server/assistant.d.ts +44 -0
  93. package/dist/server/assistant.js +39 -0
  94. package/dist/server/errors.d.ts +12 -0
  95. package/dist/server/errors.js +7 -0
  96. package/dist/server/index.d.ts +1 -1
  97. package/dist/server/index.js +1 -1
  98. package/dist/server/runs.d.ts +28 -1
  99. package/dist/server/runs.js +110 -14
  100. package/dist/sqlite/index.d.ts +16 -3
  101. package/dist/sqlite/index.js +16 -3
  102. package/dist/sqlite/migrations.d.ts +26 -0
  103. package/dist/sqlite/migrations.js +63 -0
  104. package/dist/sqlite/operations.d.ts +14 -3
  105. package/dist/sqlite/operations.js +42 -15
  106. package/dist/sqlite/store.d.ts +9 -2
  107. package/dist/sqlite/store.js +13 -3
  108. package/dist/sqlite/vectors.d.ts +11 -2
  109. package/dist/sqlite/vectors.js +13 -2
  110. package/dist/store/tenant.d.ts +12 -0
  111. package/dist/store/tenant.js +29 -0
  112. package/dist/tenancy/index.d.ts +113 -0
  113. package/dist/tenancy/index.js +233 -0
  114. package/dist/testing/record.d.ts +42 -0
  115. package/dist/testing/record.js +57 -5
  116. package/dist/tracing/index.d.ts +3 -3
  117. package/dist/tracing/index.js +2 -2
  118. package/dist/tracing/instrument.js +30 -0
  119. package/dist/tracing/otlp.d.ts +91 -0
  120. package/dist/tracing/otlp.js +124 -0
  121. package/dist/tracing/rollups.d.ts +100 -0
  122. package/dist/tracing/rollups.js +139 -0
  123. package/dist/tracing/stores.d.ts +17 -0
  124. package/dist/tracing/stores.js +23 -0
  125. package/dist/tracing/tracer.d.ts +50 -4
  126. package/dist/tracing/tracer.js +85 -6
  127. package/dist/types/config.d.ts +33 -2
  128. package/dist/types/evaluate.d.ts +37 -0
  129. package/dist/types/graph.d.ts +354 -9
  130. package/dist/types/graph.js +3 -1
  131. package/dist/types/messages.d.ts +5 -0
  132. package/dist/types/operations.d.ts +22 -2
  133. package/dist/types/response.d.ts +20 -0
  134. package/dist/types/server.d.ts +18 -0
  135. package/dist/types/tracing.d.ts +11 -0
  136. package/dist/utils/schema-migrations.d.ts +97 -0
  137. package/dist/utils/schema-migrations.js +91 -0
  138. package/dist/utils/signals.d.ts +17 -0
  139. package/dist/utils/signals.js +26 -0
  140. package/dist/utils/tenant.d.ts +14 -0
  141. package/dist/utils/tenant.js +16 -0
  142. package/dist/version.d.ts +5 -0
  143. package/dist/version.js +1 -0
  144. package/dist-cjs/agent/create-agent.d.ts +9 -1
  145. package/dist-cjs/agent/create-agent.js +40 -1
  146. package/dist-cjs/cache/memory-cache.d.ts +8 -0
  147. package/dist-cjs/cache/memory-cache.js +9 -0
  148. package/dist-cjs/cache/semantic-cache.d.ts +6 -3
  149. package/dist-cjs/cache/semantic-cache.js +5 -2
  150. package/dist-cjs/cli/args.js +3 -0
  151. package/dist-cjs/cli/db.d.ts +16 -4
  152. package/dist-cjs/cli/db.js +200 -20
  153. package/dist-cjs/cli/doctor.d.ts +17 -0
  154. package/dist-cjs/cli/doctor.js +56 -0
  155. package/dist-cjs/cli/graph.d.ts +9 -0
  156. package/dist-cjs/cli/graph.js +50 -0
  157. package/dist-cjs/core/lifecycle.js +11 -6
  158. package/dist-cjs/core/nexus.d.ts +12 -2
  159. package/dist-cjs/core/nexus.js +106 -23
  160. package/dist-cjs/doctor/index.d.ts +90 -0
  161. package/dist-cjs/doctor/index.js +276 -0
  162. package/dist-cjs/evals/judge.d.ts +11 -0
  163. package/dist-cjs/evals/judge.js +33 -0
  164. package/dist-cjs/evaluate/index.d.ts +1 -0
  165. package/dist-cjs/evaluate/index.js +3 -1
  166. package/dist-cjs/evaluate/provenance.d.ts +22 -0
  167. package/dist-cjs/evaluate/provenance.js +14 -0
  168. package/dist-cjs/evaluate/run.js +20 -4
  169. package/dist-cjs/graph/durability.d.ts +27 -0
  170. package/dist-cjs/graph/durability.js +70 -0
  171. package/dist-cjs/graph/errors.d.ts +30 -4
  172. package/dist-cjs/graph/errors.js +20 -3
  173. package/dist-cjs/graph/event-stream.d.ts +75 -0
  174. package/dist-cjs/graph/event-stream.js +295 -0
  175. package/dist-cjs/graph/functional.d.ts +80 -7
  176. package/dist-cjs/graph/functional.js +137 -34
  177. package/dist-cjs/graph/graph.d.ts +56 -8
  178. package/dist-cjs/graph/graph.js +330 -48
  179. package/dist-cjs/graph/index.d.ts +4 -2
  180. package/dist-cjs/graph/index.js +7 -1
  181. package/dist-cjs/graph/lint.d.ts +57 -0
  182. package/dist-cjs/graph/lint.js +144 -0
  183. package/dist-cjs/graph/run-control.d.ts +28 -0
  184. package/dist-cjs/graph/run-control.js +30 -0
  185. package/dist-cjs/images/evals.js +4 -2
  186. package/dist-cjs/operations/adapters.d.ts +52 -4
  187. package/dist-cjs/operations/adapters.js +193 -6
  188. package/dist-cjs/operations/runner.js +14 -15
  189. package/dist-cjs/operations/stats.js +8 -1
  190. package/dist-cjs/operations/store.d.ts +5 -1
  191. package/dist-cjs/operations/store.js +7 -0
  192. package/dist-cjs/ops/circuit-breaker.d.ts +52 -0
  193. package/dist-cjs/ops/circuit-breaker.js +4 -0
  194. package/dist-cjs/ops/circuit-store.d.ts +13 -2
  195. package/dist-cjs/ops/circuit-store.js +68 -0
  196. package/dist-cjs/ops/circuit-sync.d.ts +17 -0
  197. package/dist-cjs/ops/circuit-sync.js +87 -0
  198. package/dist-cjs/ops/health.d.ts +24 -0
  199. package/dist-cjs/ops/health.js +38 -10
  200. package/dist-cjs/ops/index.d.ts +1 -1
  201. package/dist-cjs/ops/rate-limit-adapters.d.ts +23 -0
  202. package/dist-cjs/ops/rate-limit-adapters.js +35 -1
  203. package/dist-cjs/ops/rate-limiter.d.ts +14 -2
  204. package/dist-cjs/ops/rate-limiter.js +32 -0
  205. package/dist-cjs/postgres/circuits.d.ts +21 -4
  206. package/dist-cjs/postgres/circuits.js +98 -3
  207. package/dist-cjs/postgres/client.d.ts +0 -2
  208. package/dist-cjs/postgres/client.js +0 -5
  209. package/dist-cjs/postgres/evaluate.d.ts +16 -4
  210. package/dist-cjs/postgres/evaluate.js +50 -4
  211. package/dist-cjs/postgres/index.d.ts +32 -11
  212. package/dist-cjs/postgres/index.js +69 -20
  213. package/dist-cjs/postgres/migrations.d.ts +60 -0
  214. package/dist-cjs/postgres/migrations.js +129 -0
  215. package/dist-cjs/postgres/operations.d.ts +14 -3
  216. package/dist-cjs/postgres/operations.js +78 -14
  217. package/dist-cjs/postgres/prompts.d.ts +11 -2
  218. package/dist-cjs/postgres/prompts.js +47 -2
  219. package/dist-cjs/postgres/rollups.d.ts +35 -0
  220. package/dist-cjs/postgres/rollups.js +168 -0
  221. package/dist-cjs/postgres/store.d.ts +11 -2
  222. package/dist-cjs/postgres/store.js +47 -2
  223. package/dist-cjs/postgres/traces.d.ts +13 -3
  224. package/dist-cjs/postgres/traces.js +58 -2
  225. package/dist-cjs/postgres/vectors.d.ts +11 -2
  226. package/dist-cjs/postgres/vectors.js +47 -2
  227. package/dist-cjs/router/auto-router.d.ts +34 -7
  228. package/dist-cjs/router/auto-router.js +201 -68
  229. package/dist-cjs/server/assistant.d.ts +44 -0
  230. package/dist-cjs/server/assistant.js +39 -0
  231. package/dist-cjs/server/errors.d.ts +12 -0
  232. package/dist-cjs/server/errors.js +9 -1
  233. package/dist-cjs/server/index.d.ts +1 -1
  234. package/dist-cjs/server/index.js +2 -1
  235. package/dist-cjs/server/runs.d.ts +28 -1
  236. package/dist-cjs/server/runs.js +109 -13
  237. package/dist-cjs/sqlite/index.d.ts +16 -3
  238. package/dist-cjs/sqlite/index.js +31 -10
  239. package/dist-cjs/sqlite/migrations.d.ts +26 -0
  240. package/dist-cjs/sqlite/migrations.js +71 -0
  241. package/dist-cjs/sqlite/operations.d.ts +14 -3
  242. package/dist-cjs/sqlite/operations.js +76 -15
  243. package/dist-cjs/sqlite/store.d.ts +9 -2
  244. package/dist-cjs/sqlite/store.js +47 -3
  245. package/dist-cjs/sqlite/vectors.d.ts +11 -2
  246. package/dist-cjs/sqlite/vectors.js +47 -2
  247. package/dist-cjs/store/tenant.d.ts +12 -0
  248. package/dist-cjs/store/tenant.js +33 -0
  249. package/dist-cjs/tenancy/index.d.ts +113 -0
  250. package/dist-cjs/tenancy/index.js +250 -0
  251. package/dist-cjs/testing/record.d.ts +42 -0
  252. package/dist-cjs/testing/record.js +57 -5
  253. package/dist-cjs/tracing/index.d.ts +3 -3
  254. package/dist-cjs/tracing/index.js +4 -1
  255. package/dist-cjs/tracing/instrument.js +30 -0
  256. package/dist-cjs/tracing/otlp.d.ts +91 -0
  257. package/dist-cjs/tracing/otlp.js +129 -0
  258. package/dist-cjs/tracing/rollups.d.ts +100 -0
  259. package/dist-cjs/tracing/rollups.js +147 -0
  260. package/dist-cjs/tracing/stores.d.ts +17 -0
  261. package/dist-cjs/tracing/stores.js +24 -0
  262. package/dist-cjs/tracing/tracer.d.ts +50 -4
  263. package/dist-cjs/tracing/tracer.js +87 -6
  264. package/dist-cjs/types/config.d.ts +33 -2
  265. package/dist-cjs/types/evaluate.d.ts +37 -0
  266. package/dist-cjs/types/graph.d.ts +354 -9
  267. package/dist-cjs/types/graph.js +3 -1
  268. package/dist-cjs/types/messages.d.ts +5 -0
  269. package/dist-cjs/types/operations.d.ts +22 -2
  270. package/dist-cjs/types/response.d.ts +20 -0
  271. package/dist-cjs/types/server.d.ts +18 -0
  272. package/dist-cjs/types/tracing.d.ts +11 -0
  273. package/dist-cjs/utils/schema-migrations.d.ts +97 -0
  274. package/dist-cjs/utils/schema-migrations.js +102 -0
  275. package/dist-cjs/utils/signals.d.ts +17 -0
  276. package/dist-cjs/utils/signals.js +29 -0
  277. package/dist-cjs/utils/tenant.d.ts +14 -0
  278. package/dist-cjs/utils/tenant.js +22 -0
  279. package/dist-cjs/version.d.ts +5 -0
  280. package/dist-cjs/version.js +4 -0
  281. package/llms.txt +4 -3
  282. package/package.json +110 -2
@@ -1,8 +1,12 @@
1
1
  import { randomBytes } from 'node:crypto';
2
2
  import { Command, END, Send, START } from '../types/graph.js';
3
+ import { tenantStore } from '../store/tenant.js';
4
+ import { linkSignals } from '../utils/signals.js';
3
5
  import { MemoryGraphCheckpointer } from './checkpointer.js';
4
6
  import { migrateCheckpoint, toCheckpoint } from './checkpoint-migration.js';
5
- import { GraphInterrupt, GraphNodeError, GraphNodeTimeoutError, GraphNotInterruptedError, GraphStepLimitError, GraphThreadNotFoundError, GraphValidationError, interruptKey, } from './errors.js';
7
+ import { CheckpointWriter } from './durability.js';
8
+ import { GraphEventStream, streamSettings } from './event-stream.js';
9
+ import { GraphDrainedError, GraphInterrupt, GraphNodeError, GraphNodeTimeoutError, GraphNotInterruptedError, GraphStepLimitError, GraphThreadNotFoundError, GraphValidationError, interruptKey, } from './errors.js';
6
10
  const DEFAULT_MAX_STEPS = 25;
7
11
  const DEFAULT_MAX_CONCURRENCY = 16;
8
12
  const DEFAULT_RETRY = {
@@ -13,6 +17,7 @@ const DEFAULT_RETRY = {
13
17
  jitter: true,
14
18
  };
15
19
  const SUBGRAPH = Symbol('nexus.graph.subgraph');
20
+ const FORWARD_EVENT = Symbol('nexus.graph.forwardEvent');
16
21
  const FOLLOWING_UPDATES = Symbol('nexus.graph.followingUpdates');
17
22
  export class StateGraph {
18
23
  channels;
@@ -123,6 +128,7 @@ export class CompiledGraph {
123
128
  now;
124
129
  store;
125
130
  nodeCache;
131
+ writers = new Set();
126
132
  constructor(channels, nodes, edges, options, scope = {}) {
127
133
  this.channels = channels;
128
134
  this.nodes = nodes;
@@ -132,6 +138,9 @@ export class CompiledGraph {
132
138
  this.now = options.now ?? (() => new Date());
133
139
  this.store = options.checkpointer === false ? undefined : (options.checkpointer ?? new MemoryGraphCheckpointer());
134
140
  }
141
+ async flush() {
142
+ await Promise.all([...this.writers].map((writer) => writer.flush()));
143
+ }
135
144
  async invoke(input = {}, runOptions = {}) {
136
145
  const threadId = resolveThreadId(runOptions.threadId);
137
146
  let last;
@@ -143,11 +152,42 @@ export class CompiledGraph {
143
152
  const threadId = resolveThreadId(runOptions.threadId);
144
153
  return this.run(threadId, runOptions, async () => {
145
154
  this.assertInput(input);
155
+ if (runOptions.tenantId !== undefined) {
156
+ const existing = await this.checkpointer()?.get(threadId);
157
+ if (existing && !ownedBy(existing, runOptions.tenantId)) {
158
+ throw new GraphValidationError(`Thread "${threadId}" cannot be used by this tenant; choose another id`);
159
+ }
160
+ }
146
161
  const state = this.seedState(input);
147
162
  const next = this.entryNodes();
148
163
  return { threadId, step: 0, state, next, status: 'running', createdAt: this.now().toISOString() };
149
164
  });
150
165
  }
166
+ events(input = {}, options = {}) {
167
+ const threadId = resolveThreadId(options.threadId);
168
+ return this.eventStream(threadId, options, (runOptions) => this.stream(input, runOptions));
169
+ }
170
+ resumeEvents(threadId, value, options = {}) {
171
+ return this.eventStream(threadId, options, (runOptions) => this.resume(threadId, value, runOptions));
172
+ }
173
+ continueEvents(threadId, options = {}) {
174
+ return this.eventStream(threadId, options, (runOptions) => this.continue(threadId, runOptions));
175
+ }
176
+ eventStream(threadId, options, run) {
177
+ return new GraphEventStream((onEvent, signal) => {
178
+ const linked = linkSignals([options.signal, signal]);
179
+ return releasing(run({
180
+ ...options,
181
+ threadId,
182
+ signal: linked.signal,
183
+ ...(options.subgraphs ? { subgraphEvents: true } : {}),
184
+ onEvent: (event) => {
185
+ options.onEvent?.(event);
186
+ onEvent(event);
187
+ },
188
+ }), linked.dispose);
189
+ }, (last) => this.toResult(threadId, last), streamSettings(options));
190
+ }
151
191
  resume(threadId, value, runOptions = {}) {
152
192
  return this.run(threadId, runOptions, async () => {
153
193
  const checkpoint = await this.requireCheckpoint(threadId);
@@ -197,7 +237,7 @@ export class CompiledGraph {
197
237
  continue(threadId, runOptions = {}) {
198
238
  return this.run(threadId, runOptions, async () => {
199
239
  const checkpoint = await this.requireCheckpoint(threadId);
200
- return { ...checkpoint, status: 'running', error: undefined };
240
+ return { ...checkpoint, status: 'running', error: undefined, drained: undefined };
201
241
  });
202
242
  }
203
243
  resumeFrom(threadId, step, runOptions = {}) {
@@ -208,19 +248,25 @@ export class CompiledGraph {
208
248
  return { ...migrateCheckpoint(stored), status: 'running' };
209
249
  });
210
250
  }
211
- async state(threadId, step) {
251
+ async state(threadId, step, options = {}) {
212
252
  const stored = await this.checkpointer()?.get(threadId, step);
213
- return stored ? migrateCheckpoint(stored) : undefined;
253
+ if (!stored || !ownedBy(stored, options.tenantId))
254
+ return undefined;
255
+ return migrateCheckpoint(stored);
214
256
  }
215
- async history(threadId, limit) {
257
+ async history(threadId, limit, options = {}) {
216
258
  const stored = (await this.checkpointer()?.history(threadId, limit)) ?? [];
259
+ if (stored[0] && !ownedBy(stored[0], options.tenantId))
260
+ return [];
217
261
  return stored.map((item) => migrateCheckpoint(item));
218
262
  }
219
263
  asNode() {
220
264
  const node = async (context) => {
265
+ const forward = context[FORWARD_EVENT];
221
266
  const runOptions = {
222
267
  threadId: `${context.threadId}:${context.taskId}`,
223
268
  signal: context.signal,
269
+ ...(forward ? { onEvent: forward, subgraphEvents: true } : {}),
224
270
  };
225
271
  const paused = await this.state(runOptions.threadId);
226
272
  let result;
@@ -263,13 +309,18 @@ export class CompiledGraph {
263
309
  describe() {
264
310
  const nodes = [...this.nodes.entries()].map(([id, definition]) => {
265
311
  const subgraph = definition.fn[SUBGRAPH];
266
- const { ends, defer, retry, timeoutMs, cache } = definition.options;
312
+ const { ends, defer, timeoutMs, cache, idempotent } = definition.options;
313
+ const maxAttempts = this.retryPolicy(definition).maxAttempts;
314
+ const timeout = this.timeoutOf(definition);
267
315
  return {
268
316
  id,
269
317
  ...(ends?.length ? { ends: [...ends] } : {}),
270
318
  ...(defer ? { defer } : {}),
271
- ...((retry?.maxAttempts ?? this.options.retry?.maxAttempts ?? 1) > 1 ? { retry: true } : {}),
319
+ ...(maxAttempts > 1 ? { retry: true, maxAttempts } : {}),
272
320
  ...(timeoutMs !== undefined ? { timeoutMs } : {}),
321
+ ...(timeout.runMs !== undefined || timeout.idleMs !== undefined ? { timeout } : {}),
322
+ ...(this.errorHandler(definition) ? { onError: true } : {}),
323
+ ...(idempotent ? { idempotent: true } : {}),
273
324
  ...(cache ? { cache: true } : {}),
274
325
  ...(subgraph ? { subgraph: subgraph.describe() } : {}),
275
326
  };
@@ -304,10 +355,13 @@ export class CompiledGraph {
304
355
  dynamic: [...dynamic],
305
356
  ...(this.scope.input ? { input: [...this.scope.input] } : {}),
306
357
  ...(this.scope.output ? { output: [...this.scope.output] } : {}),
358
+ durability: this.options.durability ?? 'sync',
359
+ checkpointer: this.options.checkpointer === false ? 'none' : this.options.checkpointer === undefined ? 'memory' : 'custom',
360
+ maxConcurrency: this.options.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY,
307
361
  };
308
362
  }
309
363
  async updateState(threadId, update, options = {}) {
310
- const checkpoint = await this.requireCheckpoint(threadId);
364
+ const checkpoint = await this.requireCheckpoint(threadId, options.tenantId);
311
365
  const state = this.reduce(checkpoint.state, [update]);
312
366
  const createdAt = this.now().toISOString();
313
367
  if (!options.asNode) {
@@ -342,8 +396,9 @@ export class CompiledGraph {
342
396
  if (!store)
343
397
  throw new GraphValidationError('fork() needs a checkpointer to copy history from');
344
398
  const history = (await store.history(threadId, Number.MAX_SAFE_INTEGER)).map((item) => migrateCheckpoint(item));
345
- if (history.length === 0)
399
+ if (history.length === 0 || !ownedBy(history[0], options.tenantId)) {
346
400
  throw new GraphThreadNotFoundError(threadId);
401
+ }
347
402
  const cutoff = options.step ?? history[0].step;
348
403
  const lineage = history.filter((item) => item.step <= cutoff).reverse();
349
404
  if (lineage.at(-1)?.step !== cutoff) {
@@ -394,22 +449,69 @@ export class CompiledGraph {
394
449
  }
395
450
  }
396
451
  async *runSteps(threadId, runOptions, seed) {
452
+ const mode = runOptions.durability ?? this.options.durability ?? 'sync';
453
+ const writer = new CheckpointWriter(async (written) => {
454
+ await this.save(written);
455
+ notify(runOptions, { type: 'checkpoint', step: written.step, status: written.status, next: written.next });
456
+ }, mode, this.options.maxPendingWrites);
457
+ this.writers.add(writer);
458
+ let failed = false;
459
+ try {
460
+ yield* this.steps(threadId, runOptions, seed, (written, durable) => writer.persist(written, durable));
461
+ }
462
+ catch (error) {
463
+ failed = true;
464
+ throw error;
465
+ }
466
+ finally {
467
+ this.writers.delete(writer);
468
+ if (failed)
469
+ await writer.flush().catch(() => undefined);
470
+ else
471
+ await writer.flush();
472
+ }
473
+ }
474
+ async *steps(threadId, runOptions, seed, persist) {
397
475
  const maxSteps = runOptions.maxSteps ?? this.options.maxSteps ?? DEFAULT_MAX_STEPS;
398
476
  const stopBefore = runOptions.interruptBefore ?? this.options.interruptBefore ?? [];
399
477
  const stopAfter = runOptions.interruptAfter ?? this.options.interruptAfter ?? [];
400
- const persist = async (written) => {
401
- await this.save(written);
402
- notify(runOptions, { type: 'checkpoint', step: written.step, status: written.status, next: written.next });
403
- };
404
478
  let checkpoint = await seed();
479
+ const owner = tenantOf(checkpoint);
480
+ if (runOptions.tenantId !== undefined && owner !== undefined && owner !== runOptions.tenantId) {
481
+ throw new GraphThreadNotFoundError(threadId);
482
+ }
483
+ const tenantId = runOptions.tenantId ?? owner;
484
+ if (tenantId !== undefined) {
485
+ runOptions = { ...runOptions, tenantId, metadata: { ...runOptions.metadata, tenantId } };
486
+ if (owner === undefined)
487
+ checkpoint = { ...checkpoint, metadata: { ...checkpoint.metadata, tenantId } };
488
+ }
405
489
  let passBreakpoint = checkpoint.breakpoint?.when === 'before';
406
490
  if (checkpoint.breakpoint)
407
491
  checkpoint = { ...checkpoint, breakpoint: undefined };
492
+ if (checkpoint.next.length === 0) {
493
+ if (checkpoint.status === 'running')
494
+ checkpoint = { ...checkpoint, status: 'completed' };
495
+ await persist(checkpoint, true);
496
+ yield this.toEvent(checkpoint, []);
497
+ return;
498
+ }
408
499
  await persist(checkpoint);
409
500
  while (checkpoint.next.length > 0) {
501
+ if (runOptions.control?.draining) {
502
+ const at = this.now().toISOString();
503
+ checkpoint = {
504
+ ...checkpoint,
505
+ status: 'interrupted',
506
+ drained: { ...(runOptions.control.reason ? { reason: runOptions.control.reason } : {}), at },
507
+ createdAt: at,
508
+ };
509
+ await persist(checkpoint, true);
510
+ throw new GraphDrainedError(threadId, checkpoint.step, runOptions.control.reason);
511
+ }
410
512
  if (runOptions.signal?.aborted) {
411
513
  checkpoint = { ...checkpoint, status: 'interrupted', createdAt: this.now().toISOString() };
412
- await persist(checkpoint);
514
+ await persist(checkpoint, true);
413
515
  yield this.toEvent(checkpoint, []);
414
516
  return;
415
517
  }
@@ -434,7 +536,7 @@ export class CompiledGraph {
434
536
  breakpoint: { when: 'before', nodes: breakBefore },
435
537
  createdAt: this.now().toISOString(),
436
538
  };
437
- await persist(checkpoint);
539
+ await persist(checkpoint, true);
438
540
  yield this.toEvent(checkpoint, []);
439
541
  return;
440
542
  }
@@ -454,6 +556,7 @@ export class CompiledGraph {
454
556
  const gotos = { ...(checkpoint.gotos ?? {}) };
455
557
  let parentCommand;
456
558
  let failure;
559
+ const recovered = [];
457
560
  for (const [index, task] of pendingTasks.entries()) {
458
561
  const outcome = outcomes[index];
459
562
  if (!outcome)
@@ -465,6 +568,8 @@ export class CompiledGraph {
465
568
  if (outcome.goto?.length)
466
569
  gotos[task.id] = outcome.goto;
467
570
  parentCommand ??= outcome.parent;
571
+ if (outcome.recovered)
572
+ recovered.push(outcome.recovered);
468
573
  finished.push(task.id);
469
574
  }
470
575
  else if (outcome.kind === 'interrupt') {
@@ -480,6 +585,7 @@ export class CompiledGraph {
480
585
  const ranNodes = distinctNodes(allTasks.filter((task) => completed.includes(task.id)));
481
586
  const ranTasks = pendingTasks;
482
587
  const routeFields = Object.keys(gotos).length > 0 ? { gotos } : {};
588
+ const recoveryFields = recovered.length > 0 ? { recovered } : {};
483
589
  if (failure) {
484
590
  const failed = {
485
591
  ...checkpoint,
@@ -487,6 +593,7 @@ export class CompiledGraph {
487
593
  ...pausedFields(allTasks, unfinished),
488
594
  completed,
489
595
  ...routeFields,
596
+ ...recoveryFields,
490
597
  status: 'failed',
491
598
  error: {
492
599
  name: failure.error instanceof Error ? failure.error.name : 'Error',
@@ -494,7 +601,7 @@ export class CompiledGraph {
494
601
  },
495
602
  createdAt: this.now().toISOString(),
496
603
  };
497
- await persist(failed);
604
+ await persist(failed, true);
498
605
  throw failure.error instanceof GraphNodeError
499
606
  ? failure.error
500
607
  : new GraphNodeError(failure.task.node, step, failure.error);
@@ -507,11 +614,12 @@ export class CompiledGraph {
507
614
  ...pausedFields(allTasks, unfinished),
508
615
  completed,
509
616
  ...routeFields,
617
+ ...recoveryFields,
510
618
  status: asking ? 'awaiting_input' : 'interrupted',
511
619
  interrupts,
512
620
  createdAt: this.now().toISOString(),
513
621
  };
514
- await persist(checkpoint);
622
+ await persist(checkpoint, true);
515
623
  yield this.toEvent(checkpoint, ranNodes, ranTasks, attempts);
516
624
  return;
517
625
  }
@@ -523,10 +631,11 @@ export class CompiledGraph {
523
631
  next: [],
524
632
  status: 'completed',
525
633
  resolved: checkpoint.resolved,
634
+ ...recoveryFields,
526
635
  createdAt: this.now().toISOString(),
527
636
  ...(runOptions.metadata ? { metadata: runOptions.metadata } : {}),
528
637
  };
529
- await persist(checkpoint);
638
+ await persist(checkpoint, true);
530
639
  yield { ...this.toEvent(checkpoint, ranNodes, ranTasks, attempts), parentCommand };
531
640
  return;
532
641
  }
@@ -545,10 +654,11 @@ export class CompiledGraph {
545
654
  status: breakAfter.length > 0 ? 'interrupted' : next.length > 0 ? 'running' : 'completed',
546
655
  ...(breakAfter.length > 0 ? { breakpoint: { when: 'after', nodes: breakAfter } } : {}),
547
656
  resolved: checkpoint.resolved,
657
+ ...recoveryFields,
548
658
  createdAt: this.now().toISOString(),
549
659
  ...(runOptions.metadata ? { metadata: runOptions.metadata } : {}),
550
660
  };
551
- await persist(checkpoint);
661
+ await persist(checkpoint, recovered.length > 0 || next.length === 0 || breakAfter.length > 0);
552
662
  yield this.toEvent(checkpoint, ranNodes, ranTasks, attempts);
553
663
  if (breakAfter.length > 0)
554
664
  return;
@@ -558,8 +668,8 @@ export class CompiledGraph {
558
668
  const definition = this.nodes.get(task.node);
559
669
  if (!definition)
560
670
  throw new GraphValidationError(`Node "${task.node}" disappeared before it could run`);
561
- const policy = { ...DEFAULT_RETRY, ...this.options.retry, ...definition.options.retry };
562
- const timeoutMs = definition.options.timeoutMs;
671
+ const policy = this.retryPolicy(definition);
672
+ const limits = { ...this.timeoutOf(definition), ...task.timeout };
563
673
  const cachePolicy = definition.options.cache;
564
674
  const cache = cachePolicy ? await this.loadNodeCache() : undefined;
565
675
  const cacheKey = cachePolicy && cache ? cache.key(cachePolicy, task.node, checkpoint.state, task.input) : undefined;
@@ -581,22 +691,18 @@ export class CompiledGraph {
581
691
  }
582
692
  }
583
693
  let attempts = 0;
694
+ const firstAttemptAt = this.now().toISOString();
584
695
  while (true) {
585
696
  attempts += 1;
586
697
  notify(runOptions, { type: 'task_start', step, taskId: task.id, node: task.node, attempt: attempts });
587
- const timeout = timeoutMs === undefined ? undefined : AbortSignal.timeout(timeoutMs);
588
- const sources = [stepSignal, ...(runOptions.signal ? [runOptions.signal] : []), ...(timeout ? [timeout] : [])];
589
- const signal = sources.length === 1 ? sources[0] : AbortSignal.any(sources);
698
+ const timer = attemptTimer(task.node, limits);
699
+ const linked = linkSignals([stepSignal, runOptions.signal, timer?.signal]);
700
+ const signal = linked.signal;
590
701
  try {
591
- const running = this.runNode(definition.fn, task, step, threadId, checkpoint, runOptions, signal, attempts);
592
- if (timeout)
702
+ const running = this.runNode(definition.fn, task, step, threadId, checkpoint, runOptions, signal, attempts, timer?.touch);
703
+ if (timer)
593
704
  running.catch(() => undefined);
594
- const output = timeout
595
- ? await Promise.race([
596
- running,
597
- rejectWhenAborted(timeout, () => new GraphNodeTimeoutError(task.node, timeoutMs)),
598
- ])
599
- : await running;
705
+ const output = timer ? await Promise.race([running, timer.expired]) : await running;
600
706
  const parent = output.command?.graph === Command.PARENT ? output.command : undefined;
601
707
  const goto = parent ? undefined : toRouteRecords(output.command?.goto);
602
708
  const updates = parent ? [] : output.updates;
@@ -614,6 +720,7 @@ export class CompiledGraph {
614
720
  return { kind: 'ok', updates, goto, parent, attempts };
615
721
  }
616
722
  catch (error) {
723
+ timer?.stop();
617
724
  if (error instanceof GraphInterrupt) {
618
725
  return {
619
726
  kind: 'interrupt',
@@ -631,10 +738,24 @@ export class CompiledGraph {
631
738
  }
632
739
  if (runOptions.signal?.aborted || stepSignal.aborted)
633
740
  return { kind: 'aborted', attempts };
634
- const failure = timeout?.aborted ? new GraphNodeTimeoutError(task.node, timeoutMs) : error;
741
+ const failure = timer?.error() ?? error;
635
742
  const retryable = policy.retryOn ? policy.retryOn(failure, attempts) : isRetryable(failure);
636
743
  if (attempts >= Math.max(1, policy.maxAttempts) || !retryable) {
637
- return { kind: 'failed', error: failure, attempts };
744
+ return this.recover(definition, task, step, checkpoint, runOptions, {
745
+ node: task.node,
746
+ taskId: task.id,
747
+ step,
748
+ attempts,
749
+ firstAttemptAt,
750
+ failedAt: this.now().toISOString(),
751
+ error: failure,
752
+ retryExhausted: retryable,
753
+ ...(failure instanceof GraphNodeTimeoutError
754
+ ? { timeout: { type: failure.kind, limitMs: failure.timeoutMs } }
755
+ : {}),
756
+ ...(task.input === undefined ? {} : { input: task.input }),
757
+ threadId,
758
+ });
638
759
  }
639
760
  notify(runOptions, {
640
761
  type: 'task_retry',
@@ -646,9 +767,81 @@ export class CompiledGraph {
646
767
  });
647
768
  await delay(backoffDelay(policy, attempts), runOptions.signal);
648
769
  }
770
+ finally {
771
+ timer?.stop();
772
+ linked.dispose();
773
+ }
774
+ }
775
+ }
776
+ async recover(definition, task, step, checkpoint, runOptions, failure) {
777
+ const handler = this.errorHandler(definition);
778
+ const event = {
779
+ type: 'task_failed',
780
+ step,
781
+ taskId: task.id,
782
+ node: task.node,
783
+ attempts: failure.attempts,
784
+ error: describe(failure.error),
785
+ };
786
+ if (!handler || failure.error instanceof GraphValidationError) {
787
+ notify(runOptions, { ...event, recovered: false });
788
+ return { kind: 'failed', error: failure.error, attempts: failure.attempts };
789
+ }
790
+ let decided;
791
+ try {
792
+ decided = await handler(failure, { state: Object.freeze({ ...checkpoint.state }) });
649
793
  }
794
+ catch (error) {
795
+ notify(runOptions, { ...event, recovered: false });
796
+ return { kind: 'failed', error, attempts: failure.attempts };
797
+ }
798
+ const command = decided instanceof Command ? decided : undefined;
799
+ const parent = command?.graph === Command.PARENT ? command : undefined;
800
+ const goto = parent ? undefined : toRouteRecords(command?.goto);
801
+ const own = command ? command.update : decided;
802
+ const updates = parent || !own ? [] : [own];
803
+ notify(runOptions, { ...event, recovered: true });
804
+ return {
805
+ kind: 'ok',
806
+ updates,
807
+ goto,
808
+ parent,
809
+ attempts: failure.attempts,
810
+ recovered: {
811
+ node: failure.node,
812
+ taskId: failure.taskId,
813
+ step,
814
+ attempts: failure.attempts,
815
+ error: {
816
+ name: failure.error instanceof Error ? failure.error.name : 'Error',
817
+ message: describe(failure.error),
818
+ },
819
+ failedAt: failure.failedAt,
820
+ retryExhausted: failure.retryExhausted,
821
+ ...(failure.timeout ? { timeout: failure.timeout } : {}),
822
+ ...(goto?.length ? { goto: goto.map(routeName) } : {}),
823
+ },
824
+ };
825
+ }
826
+ retryPolicy(definition) {
827
+ return {
828
+ ...DEFAULT_RETRY,
829
+ ...this.options.retry,
830
+ ...this.options.nodeDefaults?.retry,
831
+ ...definition.options.retry,
832
+ };
650
833
  }
651
- async runNode(fn, task, step, threadId, checkpoint, runOptions, signal, attempt) {
834
+ timeoutOf(definition) {
835
+ const defaults = this.options.nodeDefaults?.timeout;
836
+ const own = definition.options;
837
+ const runMs = own.timeout?.runMs ?? own.timeoutMs ?? defaults?.runMs;
838
+ const idleMs = own.timeout?.idleMs ?? defaults?.idleMs;
839
+ return { ...(runMs === undefined ? {} : { runMs }), ...(idleMs === undefined ? {} : { idleMs }) };
840
+ }
841
+ errorHandler(definition) {
842
+ return definition.options.onError ?? this.options.nodeDefaults?.onError;
843
+ }
844
+ async runNode(fn, task, step, threadId, checkpoint, runOptions, signal, attempt, touch = noop) {
652
845
  const node = task.node;
653
846
  let interruptIndex = 0;
654
847
  const context = {
@@ -656,11 +849,18 @@ export class CompiledGraph {
656
849
  node,
657
850
  step,
658
851
  threadId,
852
+ ...(runOptions.tenantId !== undefined ? { tenantId: runOptions.tenantId } : {}),
659
853
  taskId: task.id,
660
854
  input: task.input,
661
855
  attempt,
662
856
  signal,
663
- ...(this.options.store ? { store: this.options.store } : {}),
857
+ ...(this.options.store
858
+ ? {
859
+ store: runOptions.tenantId !== undefined
860
+ ? tenantStore(this.options.store, runOptions.tenantId)
861
+ : this.options.store,
862
+ }
863
+ : {}),
664
864
  interrupt: (request) => {
665
865
  const index = interruptIndex++;
666
866
  const key = interruptKey({ node, taskId: task.id, step, index });
@@ -672,8 +872,21 @@ export class CompiledGraph {
672
872
  }
673
873
  throw new GraphInterrupt(request, node, step, index, task.id);
674
874
  },
675
- emit: (data) => notify(runOptions, { type: 'custom', step, taskId: task.id, node, data }),
875
+ emit: (data) => {
876
+ touch();
877
+ notify(runOptions, { type: 'custom', step, taskId: task.id, node, data });
878
+ },
879
+ heartbeat: touch,
880
+ message: (chunk) => {
881
+ touch();
882
+ notify(runOptions, { type: 'message', step, taskId: task.id, node, chunk });
883
+ },
884
+ tool: (event) => {
885
+ touch();
886
+ notify(runOptions, { type: 'tool', step, taskId: task.id, node, tool: event });
887
+ },
676
888
  report: (progress) => {
889
+ touch();
677
890
  if (!runOptions.onProgress)
678
891
  return;
679
892
  try {
@@ -683,6 +896,11 @@ export class CompiledGraph {
683
896
  }
684
897
  },
685
898
  };
899
+ if (runOptions.subgraphEvents) {
900
+ Object.defineProperty(context, FORWARD_EVENT, {
901
+ value: (event) => notify(runOptions, { ...event, namespace: [node, ...(event.namespace ?? [])] }),
902
+ });
903
+ }
686
904
  const result = await fn(context);
687
905
  const interrupted = interruptIndex > 0;
688
906
  if (result instanceof Command) {
@@ -742,7 +960,12 @@ export class CompiledGraph {
742
960
  if (!this.nodes.has(target.node)) {
743
961
  throw new GraphValidationError(`Send from "${from}" targets unknown node "${target.node}"`);
744
962
  }
745
- tasks.push({ id: `${target.node}#${step + 1}.${sends++}`, node: target.node, input: target.input });
963
+ tasks.push({
964
+ id: `${target.node}#${step + 1}.${sends++}`,
965
+ node: target.node,
966
+ input: target.input,
967
+ ...(target.options?.timeout ? { timeout: target.options.timeout } : {}),
968
+ });
746
969
  return;
747
970
  }
748
971
  if (target === END)
@@ -769,7 +992,9 @@ export class CompiledGraph {
769
992
  }
770
993
  }
771
994
  for (const { from, target } of routes) {
772
- add(typeof target === 'string' ? target : new Send(target.node, target.input), from);
995
+ add(typeof target === 'string'
996
+ ? target
997
+ : new Send(target.node, target.input, target.timeout ? { timeout: target.timeout } : undefined), from);
773
998
  }
774
999
  return tasks;
775
1000
  }
@@ -785,9 +1010,9 @@ export class CompiledGraph {
785
1010
  }
786
1011
  return this.reduce(state, [input]);
787
1012
  }
788
- async requireCheckpoint(threadId) {
1013
+ async requireCheckpoint(threadId, tenantId) {
789
1014
  const checkpoint = await this.checkpointer()?.get(threadId);
790
- if (!checkpoint)
1015
+ if (!checkpoint || !ownedBy(checkpoint, tenantId))
791
1016
  throw new GraphThreadNotFoundError(threadId);
792
1017
  return migrateCheckpoint(checkpoint);
793
1018
  }
@@ -837,6 +1062,7 @@ export class CompiledGraph {
837
1062
  ? { interrupt: checkpoint.interrupts[0], interrupts: checkpoint.interrupts }
838
1063
  : {}),
839
1064
  ...(checkpoint.breakpoint ? { breakpoint: checkpoint.breakpoint } : {}),
1065
+ ...(checkpoint.recovered?.length ? { recovered: checkpoint.recovered } : {}),
840
1066
  };
841
1067
  }
842
1068
  toResult(threadId, last) {
@@ -932,21 +1158,77 @@ function toRouteRecords(goto) {
932
1158
  if (goto === undefined)
933
1159
  return undefined;
934
1160
  return (Array.isArray(goto) ? goto : [goto]).map((target) => target instanceof Send
935
- ? { node: target.node, ...(target.input === undefined ? {} : { input: target.input }) }
1161
+ ? {
1162
+ node: target.node,
1163
+ ...(target.input === undefined ? {} : { input: target.input }),
1164
+ ...(target.options?.timeout ? { timeout: target.options.timeout } : {}),
1165
+ }
936
1166
  : target);
937
1167
  }
938
1168
  function routeName(route) {
939
1169
  return typeof route === 'string' ? route : route.node;
940
1170
  }
941
- function rejectWhenAborted(signal, error) {
942
- return new Promise((_, reject) => {
943
- if (signal.aborted) {
944
- reject(error());
945
- return;
946
- }
947
- signal.addEventListener('abort', () => reject(error()), { once: true });
1171
+ function noop() { }
1172
+ function attemptTimer(node, limits) {
1173
+ const { runMs, idleMs } = limits;
1174
+ if (runMs === undefined && idleMs === undefined)
1175
+ return undefined;
1176
+ const controller = new AbortController();
1177
+ let reached;
1178
+ let reject = noop;
1179
+ const expired = new Promise((_, fail) => {
1180
+ reject = fail;
948
1181
  });
1182
+ expired.catch(noop);
1183
+ const fire = (error) => {
1184
+ if (reached)
1185
+ return;
1186
+ reached = error;
1187
+ controller.abort(error);
1188
+ reject(error);
1189
+ };
1190
+ const runTimer = runMs === undefined ? undefined : setTimeout(() => fire(new GraphNodeTimeoutError(node, runMs)), runMs);
1191
+ let idleTimer;
1192
+ const armIdle = () => {
1193
+ if (idleMs === undefined || reached)
1194
+ return;
1195
+ if (idleTimer)
1196
+ clearTimeout(idleTimer);
1197
+ idleTimer = setTimeout(() => fire(new GraphNodeTimeoutError(node, idleMs, 'idle')), idleMs);
1198
+ };
1199
+ armIdle();
1200
+ return {
1201
+ signal: controller.signal,
1202
+ expired,
1203
+ touch: armIdle,
1204
+ error: () => reached,
1205
+ stop: () => {
1206
+ if (runTimer)
1207
+ clearTimeout(runTimer);
1208
+ if (idleTimer)
1209
+ clearTimeout(idleTimer);
1210
+ idleTimer = undefined;
1211
+ },
1212
+ };
949
1213
  }
950
1214
  function isRetryable(error) {
951
1215
  return !(error instanceof GraphValidationError);
952
1216
  }
1217
+ function tenantOf(checkpoint) {
1218
+ const tenantId = checkpoint.metadata?.tenantId;
1219
+ return typeof tenantId === 'string' ? tenantId : undefined;
1220
+ }
1221
+ function ownedBy(checkpoint, tenantId) {
1222
+ if (tenantId === undefined)
1223
+ return true;
1224
+ const owner = tenantOf(checkpoint);
1225
+ return owner === undefined || owner === tenantId;
1226
+ }
1227
+ async function* releasing(source, release) {
1228
+ try {
1229
+ yield* source;
1230
+ }
1231
+ finally {
1232
+ release();
1233
+ }
1234
+ }
@@ -2,6 +2,8 @@ export { CompiledGraph, StateGraph, createGraph } from './graph.js';
2
2
  export { type CheckpointDraft, type GraphCheckpointV2, migrateCheckpoint, toCheckpoint, } from './checkpoint-migration.js';
3
3
  export { appendList, appendSet, counter, lastValue, mergeObject, reducerChannel, } from './channels.js';
4
4
  export { MemoryGraphCheckpointer, OperationStoreCheckpointer, type MemoryGraphCheckpointerOptions, type OperationStoreCheckpointerOptions, } from './checkpointer.js';
5
- export { GraphError, GraphInterrupt, GraphNodeError, GraphNodeTimeoutError, GraphNotInterruptedError, GraphStepLimitError, GraphThreadNotFoundError, GraphValidationError, interruptKey, } from './errors.js';
5
+ export { GraphDrainedError, GraphError, GraphInterrupt, GraphNodeError, GraphNodeTimeoutError, GraphNotInterruptedError, GraphStepLimitError, GraphThreadNotFoundError, GraphValidationError, interruptKey, } from './errors.js';
6
+ export { RunControl } from './run-control.js';
7
+ export { GraphEventStream, GraphStreamOverflowError } from './event-stream.js';
6
8
  export { Command, END, Send, START } from '../types/graph.js';
7
- export type { Channel, ChannelSchema, CommandTarget, CompileOptions, EdgeRouter, GraphBreakpoint, GraphCheckpoint, GraphCheckpointV1, GraphCheckpointer, GraphDescription, GraphEvent, GraphInput, GraphProgress, GraphResult, GraphRunOptions, GraphRouteTarget, GraphStatus, GraphStepEvent, GraphTask, InterruptRequest, NodeCacheEntry, NodeCachePolicy, NodeContext, NodeFn, NodeOptions, NodeResult, PendingInterrupt, RetryPolicy, StateOf, StateUpdate, StoredGraphCheckpoint, } from '../types/graph.js';
9
+ export type { Channel, ChannelSchema, CommandTarget, CompileOptions, DurabilityMode, EdgeRouter, GraphBreakpoint, GraphCheckpoint, GraphCheckpointV1, GraphCheckpointer, GraphDescription, GraphEvent, GraphEventsOptions, GraphInput, GraphProgress, GraphResult, GraphRunOptions, GraphRouteTarget, GraphStatus, GraphStepEvent, GraphMessageChunk, GraphStreamEvent, GraphStreamOverflow, GraphStreamProjection, GraphStreamStats, GraphToolEvent, GraphTask, InterruptRequest, NodeCacheEntry, NodeCachePolicy, NodeContext, NodeErrorHandler, NodeFailure, NodeFn, NodeOptions, NodeResult, NodeTimeout, PendingInterrupt, RecoveredFailure, RetryPolicy, RunControlLike, SendOptions, StateOf, StateUpdate, StoredGraphCheckpoint, } from '../types/graph.js';