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.
- package/API_STABILITY.md +65 -0
- package/CHANGELOG.md +267 -1
- package/MIGRATING.md +1 -1
- package/README.md +17 -8
- package/dist/agent/create-agent.d.ts +9 -1
- package/dist/agent/create-agent.js +40 -1
- package/dist/cache/memory-cache.d.ts +8 -0
- package/dist/cache/memory-cache.js +9 -0
- package/dist/cache/semantic-cache.d.ts +6 -3
- package/dist/cache/semantic-cache.js +5 -2
- package/dist/cli/args.js +3 -0
- package/dist/cli/db.d.ts +16 -4
- package/dist/cli/db.js +169 -22
- package/dist/cli/doctor.d.ts +17 -0
- package/dist/cli/doctor.js +53 -0
- package/dist/cli/graph.d.ts +9 -0
- package/dist/cli/graph.js +47 -0
- package/dist/cli.js +21 -2
- package/dist/core/lifecycle.js +11 -6
- package/dist/core/nexus.d.ts +12 -2
- package/dist/core/nexus.js +106 -23
- package/dist/doctor/index.d.ts +90 -0
- package/dist/doctor/index.js +237 -0
- package/dist/evals/judge.d.ts +11 -0
- package/dist/evals/judge.js +33 -0
- package/dist/evaluate/index.d.ts +1 -0
- package/dist/evaluate/index.js +1 -0
- package/dist/evaluate/provenance.d.ts +22 -0
- package/dist/evaluate/provenance.js +10 -0
- package/dist/evaluate/run.js +20 -4
- package/dist/graph/durability.d.ts +27 -0
- package/dist/graph/durability.js +66 -0
- package/dist/graph/errors.d.ts +30 -4
- package/dist/graph/errors.js +18 -2
- package/dist/graph/event-stream.d.ts +75 -0
- package/dist/graph/event-stream.js +289 -0
- package/dist/graph/functional.d.ts +80 -7
- package/dist/graph/functional.js +138 -35
- package/dist/graph/graph.d.ts +56 -8
- package/dist/graph/graph.js +331 -49
- package/dist/graph/index.d.ts +4 -2
- package/dist/graph/index.js +3 -1
- package/dist/graph/lint.d.ts +57 -0
- package/dist/graph/lint.js +141 -0
- package/dist/graph/run-control.d.ts +28 -0
- package/dist/graph/run-control.js +26 -0
- package/dist/images/evals.js +4 -2
- package/dist/operations/adapters.d.ts +52 -4
- package/dist/operations/adapters.js +194 -7
- package/dist/operations/runner.js +14 -15
- package/dist/operations/stats.js +8 -1
- package/dist/operations/store.d.ts +5 -1
- package/dist/operations/store.js +7 -0
- package/dist/ops/circuit-breaker.d.ts +52 -0
- package/dist/ops/circuit-breaker.js +4 -0
- package/dist/ops/circuit-store.d.ts +13 -2
- package/dist/ops/circuit-store.js +68 -0
- package/dist/ops/circuit-sync.d.ts +17 -0
- package/dist/ops/circuit-sync.js +86 -0
- package/dist/ops/health.d.ts +24 -0
- package/dist/ops/health.js +38 -10
- package/dist/ops/index.d.ts +1 -1
- package/dist/ops/index.js +1 -1
- package/dist/ops/rate-limit-adapters.d.ts +23 -0
- package/dist/ops/rate-limit-adapters.js +34 -0
- package/dist/ops/rate-limiter.d.ts +14 -2
- package/dist/ops/rate-limiter.js +31 -0
- package/dist/postgres/circuits.d.ts +21 -4
- package/dist/postgres/circuits.js +65 -4
- package/dist/postgres/client.d.ts +0 -2
- package/dist/postgres/client.js +0 -4
- package/dist/postgres/evaluate.d.ts +16 -4
- package/dist/postgres/evaluate.js +17 -5
- package/dist/postgres/index.d.ts +32 -11
- package/dist/postgres/index.js +65 -31
- package/dist/postgres/migrations.d.ts +60 -0
- package/dist/postgres/migrations.js +121 -0
- package/dist/postgres/operations.d.ts +14 -3
- package/dist/postgres/operations.js +45 -15
- package/dist/postgres/prompts.d.ts +11 -2
- package/dist/postgres/prompts.js +14 -3
- package/dist/postgres/rollups.d.ts +35 -0
- package/dist/postgres/rollups.js +129 -0
- package/dist/postgres/store.d.ts +11 -2
- package/dist/postgres/store.js +14 -3
- package/dist/postgres/traces.d.ts +13 -3
- package/dist/postgres/traces.js +25 -3
- package/dist/postgres/vectors.d.ts +11 -2
- package/dist/postgres/vectors.js +14 -3
- package/dist/router/auto-router.d.ts +34 -7
- package/dist/router/auto-router.js +201 -68
- package/dist/server/assistant.d.ts +44 -0
- package/dist/server/assistant.js +39 -0
- package/dist/server/errors.d.ts +12 -0
- package/dist/server/errors.js +7 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/runs.d.ts +28 -1
- package/dist/server/runs.js +110 -14
- package/dist/sqlite/index.d.ts +16 -3
- package/dist/sqlite/index.js +16 -3
- package/dist/sqlite/migrations.d.ts +26 -0
- package/dist/sqlite/migrations.js +63 -0
- package/dist/sqlite/operations.d.ts +14 -3
- package/dist/sqlite/operations.js +42 -15
- package/dist/sqlite/store.d.ts +9 -2
- package/dist/sqlite/store.js +13 -3
- package/dist/sqlite/vectors.d.ts +11 -2
- package/dist/sqlite/vectors.js +13 -2
- package/dist/store/tenant.d.ts +12 -0
- package/dist/store/tenant.js +29 -0
- package/dist/tenancy/index.d.ts +113 -0
- package/dist/tenancy/index.js +233 -0
- package/dist/testing/record.d.ts +42 -0
- package/dist/testing/record.js +57 -5
- package/dist/tracing/index.d.ts +3 -3
- package/dist/tracing/index.js +2 -2
- package/dist/tracing/instrument.js +30 -0
- package/dist/tracing/otlp.d.ts +91 -0
- package/dist/tracing/otlp.js +124 -0
- package/dist/tracing/rollups.d.ts +100 -0
- package/dist/tracing/rollups.js +139 -0
- package/dist/tracing/stores.d.ts +17 -0
- package/dist/tracing/stores.js +23 -0
- package/dist/tracing/tracer.d.ts +50 -4
- package/dist/tracing/tracer.js +85 -6
- package/dist/types/config.d.ts +33 -2
- package/dist/types/evaluate.d.ts +37 -0
- package/dist/types/graph.d.ts +354 -9
- package/dist/types/graph.js +3 -1
- package/dist/types/messages.d.ts +5 -0
- package/dist/types/operations.d.ts +22 -2
- package/dist/types/response.d.ts +20 -0
- package/dist/types/server.d.ts +18 -0
- package/dist/types/tracing.d.ts +11 -0
- package/dist/utils/schema-migrations.d.ts +97 -0
- package/dist/utils/schema-migrations.js +91 -0
- package/dist/utils/signals.d.ts +17 -0
- package/dist/utils/signals.js +26 -0
- package/dist/utils/tenant.d.ts +14 -0
- package/dist/utils/tenant.js +16 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.js +1 -0
- package/dist-cjs/agent/create-agent.d.ts +9 -1
- package/dist-cjs/agent/create-agent.js +40 -1
- package/dist-cjs/cache/memory-cache.d.ts +8 -0
- package/dist-cjs/cache/memory-cache.js +9 -0
- package/dist-cjs/cache/semantic-cache.d.ts +6 -3
- package/dist-cjs/cache/semantic-cache.js +5 -2
- package/dist-cjs/cli/args.js +3 -0
- package/dist-cjs/cli/db.d.ts +16 -4
- package/dist-cjs/cli/db.js +200 -20
- package/dist-cjs/cli/doctor.d.ts +17 -0
- package/dist-cjs/cli/doctor.js +56 -0
- package/dist-cjs/cli/graph.d.ts +9 -0
- package/dist-cjs/cli/graph.js +50 -0
- package/dist-cjs/core/lifecycle.js +11 -6
- package/dist-cjs/core/nexus.d.ts +12 -2
- package/dist-cjs/core/nexus.js +106 -23
- package/dist-cjs/doctor/index.d.ts +90 -0
- package/dist-cjs/doctor/index.js +276 -0
- package/dist-cjs/evals/judge.d.ts +11 -0
- package/dist-cjs/evals/judge.js +33 -0
- package/dist-cjs/evaluate/index.d.ts +1 -0
- package/dist-cjs/evaluate/index.js +3 -1
- package/dist-cjs/evaluate/provenance.d.ts +22 -0
- package/dist-cjs/evaluate/provenance.js +14 -0
- package/dist-cjs/evaluate/run.js +20 -4
- package/dist-cjs/graph/durability.d.ts +27 -0
- package/dist-cjs/graph/durability.js +70 -0
- package/dist-cjs/graph/errors.d.ts +30 -4
- package/dist-cjs/graph/errors.js +20 -3
- package/dist-cjs/graph/event-stream.d.ts +75 -0
- package/dist-cjs/graph/event-stream.js +295 -0
- package/dist-cjs/graph/functional.d.ts +80 -7
- package/dist-cjs/graph/functional.js +137 -34
- package/dist-cjs/graph/graph.d.ts +56 -8
- package/dist-cjs/graph/graph.js +330 -48
- package/dist-cjs/graph/index.d.ts +4 -2
- package/dist-cjs/graph/index.js +7 -1
- package/dist-cjs/graph/lint.d.ts +57 -0
- package/dist-cjs/graph/lint.js +144 -0
- package/dist-cjs/graph/run-control.d.ts +28 -0
- package/dist-cjs/graph/run-control.js +30 -0
- package/dist-cjs/images/evals.js +4 -2
- package/dist-cjs/operations/adapters.d.ts +52 -4
- package/dist-cjs/operations/adapters.js +193 -6
- package/dist-cjs/operations/runner.js +14 -15
- package/dist-cjs/operations/stats.js +8 -1
- package/dist-cjs/operations/store.d.ts +5 -1
- package/dist-cjs/operations/store.js +7 -0
- package/dist-cjs/ops/circuit-breaker.d.ts +52 -0
- package/dist-cjs/ops/circuit-breaker.js +4 -0
- package/dist-cjs/ops/circuit-store.d.ts +13 -2
- package/dist-cjs/ops/circuit-store.js +68 -0
- package/dist-cjs/ops/circuit-sync.d.ts +17 -0
- package/dist-cjs/ops/circuit-sync.js +87 -0
- package/dist-cjs/ops/health.d.ts +24 -0
- package/dist-cjs/ops/health.js +38 -10
- package/dist-cjs/ops/index.d.ts +1 -1
- package/dist-cjs/ops/rate-limit-adapters.d.ts +23 -0
- package/dist-cjs/ops/rate-limit-adapters.js +35 -1
- package/dist-cjs/ops/rate-limiter.d.ts +14 -2
- package/dist-cjs/ops/rate-limiter.js +32 -0
- package/dist-cjs/postgres/circuits.d.ts +21 -4
- package/dist-cjs/postgres/circuits.js +98 -3
- package/dist-cjs/postgres/client.d.ts +0 -2
- package/dist-cjs/postgres/client.js +0 -5
- package/dist-cjs/postgres/evaluate.d.ts +16 -4
- package/dist-cjs/postgres/evaluate.js +50 -4
- package/dist-cjs/postgres/index.d.ts +32 -11
- package/dist-cjs/postgres/index.js +69 -20
- package/dist-cjs/postgres/migrations.d.ts +60 -0
- package/dist-cjs/postgres/migrations.js +129 -0
- package/dist-cjs/postgres/operations.d.ts +14 -3
- package/dist-cjs/postgres/operations.js +78 -14
- package/dist-cjs/postgres/prompts.d.ts +11 -2
- package/dist-cjs/postgres/prompts.js +47 -2
- package/dist-cjs/postgres/rollups.d.ts +35 -0
- package/dist-cjs/postgres/rollups.js +168 -0
- package/dist-cjs/postgres/store.d.ts +11 -2
- package/dist-cjs/postgres/store.js +47 -2
- package/dist-cjs/postgres/traces.d.ts +13 -3
- package/dist-cjs/postgres/traces.js +58 -2
- package/dist-cjs/postgres/vectors.d.ts +11 -2
- package/dist-cjs/postgres/vectors.js +47 -2
- package/dist-cjs/router/auto-router.d.ts +34 -7
- package/dist-cjs/router/auto-router.js +201 -68
- package/dist-cjs/server/assistant.d.ts +44 -0
- package/dist-cjs/server/assistant.js +39 -0
- package/dist-cjs/server/errors.d.ts +12 -0
- package/dist-cjs/server/errors.js +9 -1
- package/dist-cjs/server/index.d.ts +1 -1
- package/dist-cjs/server/index.js +2 -1
- package/dist-cjs/server/runs.d.ts +28 -1
- package/dist-cjs/server/runs.js +109 -13
- package/dist-cjs/sqlite/index.d.ts +16 -3
- package/dist-cjs/sqlite/index.js +31 -10
- package/dist-cjs/sqlite/migrations.d.ts +26 -0
- package/dist-cjs/sqlite/migrations.js +71 -0
- package/dist-cjs/sqlite/operations.d.ts +14 -3
- package/dist-cjs/sqlite/operations.js +76 -15
- package/dist-cjs/sqlite/store.d.ts +9 -2
- package/dist-cjs/sqlite/store.js +47 -3
- package/dist-cjs/sqlite/vectors.d.ts +11 -2
- package/dist-cjs/sqlite/vectors.js +47 -2
- package/dist-cjs/store/tenant.d.ts +12 -0
- package/dist-cjs/store/tenant.js +33 -0
- package/dist-cjs/tenancy/index.d.ts +113 -0
- package/dist-cjs/tenancy/index.js +250 -0
- package/dist-cjs/testing/record.d.ts +42 -0
- package/dist-cjs/testing/record.js +57 -5
- package/dist-cjs/tracing/index.d.ts +3 -3
- package/dist-cjs/tracing/index.js +4 -1
- package/dist-cjs/tracing/instrument.js +30 -0
- package/dist-cjs/tracing/otlp.d.ts +91 -0
- package/dist-cjs/tracing/otlp.js +129 -0
- package/dist-cjs/tracing/rollups.d.ts +100 -0
- package/dist-cjs/tracing/rollups.js +147 -0
- package/dist-cjs/tracing/stores.d.ts +17 -0
- package/dist-cjs/tracing/stores.js +24 -0
- package/dist-cjs/tracing/tracer.d.ts +50 -4
- package/dist-cjs/tracing/tracer.js +87 -6
- package/dist-cjs/types/config.d.ts +33 -2
- package/dist-cjs/types/evaluate.d.ts +37 -0
- package/dist-cjs/types/graph.d.ts +354 -9
- package/dist-cjs/types/graph.js +3 -1
- package/dist-cjs/types/messages.d.ts +5 -0
- package/dist-cjs/types/operations.d.ts +22 -2
- package/dist-cjs/types/response.d.ts +20 -0
- package/dist-cjs/types/server.d.ts +18 -0
- package/dist-cjs/types/tracing.d.ts +11 -0
- package/dist-cjs/utils/schema-migrations.d.ts +97 -0
- package/dist-cjs/utils/schema-migrations.js +102 -0
- package/dist-cjs/utils/signals.d.ts +17 -0
- package/dist-cjs/utils/signals.js +29 -0
- package/dist-cjs/utils/tenant.d.ts +14 -0
- package/dist-cjs/utils/tenant.js +22 -0
- package/dist-cjs/version.d.ts +5 -0
- package/dist-cjs/version.js +4 -0
- package/llms.txt +4 -3
- package/package.json +110 -2
package/dist-cjs/graph/graph.js
CHANGED
|
@@ -37,8 +37,12 @@ exports.CompiledGraph = exports.StateGraph = void 0;
|
|
|
37
37
|
exports.createGraph = createGraph;
|
|
38
38
|
const node_crypto_1 = require("node:crypto");
|
|
39
39
|
const graph_js_1 = require("../types/graph.js");
|
|
40
|
+
const tenant_js_1 = require("../store/tenant.js");
|
|
41
|
+
const signals_js_1 = require("../utils/signals.js");
|
|
40
42
|
const checkpointer_js_1 = require("./checkpointer.js");
|
|
41
43
|
const checkpoint_migration_js_1 = require("./checkpoint-migration.js");
|
|
44
|
+
const durability_js_1 = require("./durability.js");
|
|
45
|
+
const event_stream_js_1 = require("./event-stream.js");
|
|
42
46
|
const errors_js_1 = require("./errors.js");
|
|
43
47
|
const DEFAULT_MAX_STEPS = 25;
|
|
44
48
|
const DEFAULT_MAX_CONCURRENCY = 16;
|
|
@@ -50,6 +54,7 @@ const DEFAULT_RETRY = {
|
|
|
50
54
|
jitter: true,
|
|
51
55
|
};
|
|
52
56
|
const SUBGRAPH = Symbol('nexus.graph.subgraph');
|
|
57
|
+
const FORWARD_EVENT = Symbol('nexus.graph.forwardEvent');
|
|
53
58
|
const FOLLOWING_UPDATES = Symbol('nexus.graph.followingUpdates');
|
|
54
59
|
class StateGraph {
|
|
55
60
|
channels;
|
|
@@ -161,6 +166,7 @@ class CompiledGraph {
|
|
|
161
166
|
now;
|
|
162
167
|
store;
|
|
163
168
|
nodeCache;
|
|
169
|
+
writers = new Set();
|
|
164
170
|
constructor(channels, nodes, edges, options, scope = {}) {
|
|
165
171
|
this.channels = channels;
|
|
166
172
|
this.nodes = nodes;
|
|
@@ -170,6 +176,9 @@ class CompiledGraph {
|
|
|
170
176
|
this.now = options.now ?? (() => new Date());
|
|
171
177
|
this.store = options.checkpointer === false ? undefined : (options.checkpointer ?? new checkpointer_js_1.MemoryGraphCheckpointer());
|
|
172
178
|
}
|
|
179
|
+
async flush() {
|
|
180
|
+
await Promise.all([...this.writers].map((writer) => writer.flush()));
|
|
181
|
+
}
|
|
173
182
|
async invoke(input = {}, runOptions = {}) {
|
|
174
183
|
const threadId = resolveThreadId(runOptions.threadId);
|
|
175
184
|
let last;
|
|
@@ -181,11 +190,42 @@ class CompiledGraph {
|
|
|
181
190
|
const threadId = resolveThreadId(runOptions.threadId);
|
|
182
191
|
return this.run(threadId, runOptions, async () => {
|
|
183
192
|
this.assertInput(input);
|
|
193
|
+
if (runOptions.tenantId !== undefined) {
|
|
194
|
+
const existing = await this.checkpointer()?.get(threadId);
|
|
195
|
+
if (existing && !ownedBy(existing, runOptions.tenantId)) {
|
|
196
|
+
throw new errors_js_1.GraphValidationError(`Thread "${threadId}" cannot be used by this tenant; choose another id`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
184
199
|
const state = this.seedState(input);
|
|
185
200
|
const next = this.entryNodes();
|
|
186
201
|
return { threadId, step: 0, state, next, status: 'running', createdAt: this.now().toISOString() };
|
|
187
202
|
});
|
|
188
203
|
}
|
|
204
|
+
events(input = {}, options = {}) {
|
|
205
|
+
const threadId = resolveThreadId(options.threadId);
|
|
206
|
+
return this.eventStream(threadId, options, (runOptions) => this.stream(input, runOptions));
|
|
207
|
+
}
|
|
208
|
+
resumeEvents(threadId, value, options = {}) {
|
|
209
|
+
return this.eventStream(threadId, options, (runOptions) => this.resume(threadId, value, runOptions));
|
|
210
|
+
}
|
|
211
|
+
continueEvents(threadId, options = {}) {
|
|
212
|
+
return this.eventStream(threadId, options, (runOptions) => this.continue(threadId, runOptions));
|
|
213
|
+
}
|
|
214
|
+
eventStream(threadId, options, run) {
|
|
215
|
+
return new event_stream_js_1.GraphEventStream((onEvent, signal) => {
|
|
216
|
+
const linked = (0, signals_js_1.linkSignals)([options.signal, signal]);
|
|
217
|
+
return releasing(run({
|
|
218
|
+
...options,
|
|
219
|
+
threadId,
|
|
220
|
+
signal: linked.signal,
|
|
221
|
+
...(options.subgraphs ? { subgraphEvents: true } : {}),
|
|
222
|
+
onEvent: (event) => {
|
|
223
|
+
options.onEvent?.(event);
|
|
224
|
+
onEvent(event);
|
|
225
|
+
},
|
|
226
|
+
}), linked.dispose);
|
|
227
|
+
}, (last) => this.toResult(threadId, last), (0, event_stream_js_1.streamSettings)(options));
|
|
228
|
+
}
|
|
189
229
|
resume(threadId, value, runOptions = {}) {
|
|
190
230
|
return this.run(threadId, runOptions, async () => {
|
|
191
231
|
const checkpoint = await this.requireCheckpoint(threadId);
|
|
@@ -235,7 +275,7 @@ class CompiledGraph {
|
|
|
235
275
|
continue(threadId, runOptions = {}) {
|
|
236
276
|
return this.run(threadId, runOptions, async () => {
|
|
237
277
|
const checkpoint = await this.requireCheckpoint(threadId);
|
|
238
|
-
return { ...checkpoint, status: 'running', error: undefined };
|
|
278
|
+
return { ...checkpoint, status: 'running', error: undefined, drained: undefined };
|
|
239
279
|
});
|
|
240
280
|
}
|
|
241
281
|
resumeFrom(threadId, step, runOptions = {}) {
|
|
@@ -246,19 +286,25 @@ class CompiledGraph {
|
|
|
246
286
|
return { ...(0, checkpoint_migration_js_1.migrateCheckpoint)(stored), status: 'running' };
|
|
247
287
|
});
|
|
248
288
|
}
|
|
249
|
-
async state(threadId, step) {
|
|
289
|
+
async state(threadId, step, options = {}) {
|
|
250
290
|
const stored = await this.checkpointer()?.get(threadId, step);
|
|
251
|
-
|
|
291
|
+
if (!stored || !ownedBy(stored, options.tenantId))
|
|
292
|
+
return undefined;
|
|
293
|
+
return (0, checkpoint_migration_js_1.migrateCheckpoint)(stored);
|
|
252
294
|
}
|
|
253
|
-
async history(threadId, limit) {
|
|
295
|
+
async history(threadId, limit, options = {}) {
|
|
254
296
|
const stored = (await this.checkpointer()?.history(threadId, limit)) ?? [];
|
|
297
|
+
if (stored[0] && !ownedBy(stored[0], options.tenantId))
|
|
298
|
+
return [];
|
|
255
299
|
return stored.map((item) => (0, checkpoint_migration_js_1.migrateCheckpoint)(item));
|
|
256
300
|
}
|
|
257
301
|
asNode() {
|
|
258
302
|
const node = async (context) => {
|
|
303
|
+
const forward = context[FORWARD_EVENT];
|
|
259
304
|
const runOptions = {
|
|
260
305
|
threadId: `${context.threadId}:${context.taskId}`,
|
|
261
306
|
signal: context.signal,
|
|
307
|
+
...(forward ? { onEvent: forward, subgraphEvents: true } : {}),
|
|
262
308
|
};
|
|
263
309
|
const paused = await this.state(runOptions.threadId);
|
|
264
310
|
let result;
|
|
@@ -301,13 +347,18 @@ class CompiledGraph {
|
|
|
301
347
|
describe() {
|
|
302
348
|
const nodes = [...this.nodes.entries()].map(([id, definition]) => {
|
|
303
349
|
const subgraph = definition.fn[SUBGRAPH];
|
|
304
|
-
const { ends, defer,
|
|
350
|
+
const { ends, defer, timeoutMs, cache, idempotent } = definition.options;
|
|
351
|
+
const maxAttempts = this.retryPolicy(definition).maxAttempts;
|
|
352
|
+
const timeout = this.timeoutOf(definition);
|
|
305
353
|
return {
|
|
306
354
|
id,
|
|
307
355
|
...(ends?.length ? { ends: [...ends] } : {}),
|
|
308
356
|
...(defer ? { defer } : {}),
|
|
309
|
-
...(
|
|
357
|
+
...(maxAttempts > 1 ? { retry: true, maxAttempts } : {}),
|
|
310
358
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
359
|
+
...(timeout.runMs !== undefined || timeout.idleMs !== undefined ? { timeout } : {}),
|
|
360
|
+
...(this.errorHandler(definition) ? { onError: true } : {}),
|
|
361
|
+
...(idempotent ? { idempotent: true } : {}),
|
|
311
362
|
...(cache ? { cache: true } : {}),
|
|
312
363
|
...(subgraph ? { subgraph: subgraph.describe() } : {}),
|
|
313
364
|
};
|
|
@@ -342,10 +393,13 @@ class CompiledGraph {
|
|
|
342
393
|
dynamic: [...dynamic],
|
|
343
394
|
...(this.scope.input ? { input: [...this.scope.input] } : {}),
|
|
344
395
|
...(this.scope.output ? { output: [...this.scope.output] } : {}),
|
|
396
|
+
durability: this.options.durability ?? 'sync',
|
|
397
|
+
checkpointer: this.options.checkpointer === false ? 'none' : this.options.checkpointer === undefined ? 'memory' : 'custom',
|
|
398
|
+
maxConcurrency: this.options.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY,
|
|
345
399
|
};
|
|
346
400
|
}
|
|
347
401
|
async updateState(threadId, update, options = {}) {
|
|
348
|
-
const checkpoint = await this.requireCheckpoint(threadId);
|
|
402
|
+
const checkpoint = await this.requireCheckpoint(threadId, options.tenantId);
|
|
349
403
|
const state = this.reduce(checkpoint.state, [update]);
|
|
350
404
|
const createdAt = this.now().toISOString();
|
|
351
405
|
if (!options.asNode) {
|
|
@@ -380,8 +434,9 @@ class CompiledGraph {
|
|
|
380
434
|
if (!store)
|
|
381
435
|
throw new errors_js_1.GraphValidationError('fork() needs a checkpointer to copy history from');
|
|
382
436
|
const history = (await store.history(threadId, Number.MAX_SAFE_INTEGER)).map((item) => (0, checkpoint_migration_js_1.migrateCheckpoint)(item));
|
|
383
|
-
if (history.length === 0)
|
|
437
|
+
if (history.length === 0 || !ownedBy(history[0], options.tenantId)) {
|
|
384
438
|
throw new errors_js_1.GraphThreadNotFoundError(threadId);
|
|
439
|
+
}
|
|
385
440
|
const cutoff = options.step ?? history[0].step;
|
|
386
441
|
const lineage = history.filter((item) => item.step <= cutoff).reverse();
|
|
387
442
|
if (lineage.at(-1)?.step !== cutoff) {
|
|
@@ -432,22 +487,69 @@ class CompiledGraph {
|
|
|
432
487
|
}
|
|
433
488
|
}
|
|
434
489
|
async *runSteps(threadId, runOptions, seed) {
|
|
490
|
+
const mode = runOptions.durability ?? this.options.durability ?? 'sync';
|
|
491
|
+
const writer = new durability_js_1.CheckpointWriter(async (written) => {
|
|
492
|
+
await this.save(written);
|
|
493
|
+
notify(runOptions, { type: 'checkpoint', step: written.step, status: written.status, next: written.next });
|
|
494
|
+
}, mode, this.options.maxPendingWrites);
|
|
495
|
+
this.writers.add(writer);
|
|
496
|
+
let failed = false;
|
|
497
|
+
try {
|
|
498
|
+
yield* this.steps(threadId, runOptions, seed, (written, durable) => writer.persist(written, durable));
|
|
499
|
+
}
|
|
500
|
+
catch (error) {
|
|
501
|
+
failed = true;
|
|
502
|
+
throw error;
|
|
503
|
+
}
|
|
504
|
+
finally {
|
|
505
|
+
this.writers.delete(writer);
|
|
506
|
+
if (failed)
|
|
507
|
+
await writer.flush().catch(() => undefined);
|
|
508
|
+
else
|
|
509
|
+
await writer.flush();
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
async *steps(threadId, runOptions, seed, persist) {
|
|
435
513
|
const maxSteps = runOptions.maxSteps ?? this.options.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
436
514
|
const stopBefore = runOptions.interruptBefore ?? this.options.interruptBefore ?? [];
|
|
437
515
|
const stopAfter = runOptions.interruptAfter ?? this.options.interruptAfter ?? [];
|
|
438
|
-
const persist = async (written) => {
|
|
439
|
-
await this.save(written);
|
|
440
|
-
notify(runOptions, { type: 'checkpoint', step: written.step, status: written.status, next: written.next });
|
|
441
|
-
};
|
|
442
516
|
let checkpoint = await seed();
|
|
517
|
+
const owner = tenantOf(checkpoint);
|
|
518
|
+
if (runOptions.tenantId !== undefined && owner !== undefined && owner !== runOptions.tenantId) {
|
|
519
|
+
throw new errors_js_1.GraphThreadNotFoundError(threadId);
|
|
520
|
+
}
|
|
521
|
+
const tenantId = runOptions.tenantId ?? owner;
|
|
522
|
+
if (tenantId !== undefined) {
|
|
523
|
+
runOptions = { ...runOptions, tenantId, metadata: { ...runOptions.metadata, tenantId } };
|
|
524
|
+
if (owner === undefined)
|
|
525
|
+
checkpoint = { ...checkpoint, metadata: { ...checkpoint.metadata, tenantId } };
|
|
526
|
+
}
|
|
443
527
|
let passBreakpoint = checkpoint.breakpoint?.when === 'before';
|
|
444
528
|
if (checkpoint.breakpoint)
|
|
445
529
|
checkpoint = { ...checkpoint, breakpoint: undefined };
|
|
530
|
+
if (checkpoint.next.length === 0) {
|
|
531
|
+
if (checkpoint.status === 'running')
|
|
532
|
+
checkpoint = { ...checkpoint, status: 'completed' };
|
|
533
|
+
await persist(checkpoint, true);
|
|
534
|
+
yield this.toEvent(checkpoint, []);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
446
537
|
await persist(checkpoint);
|
|
447
538
|
while (checkpoint.next.length > 0) {
|
|
539
|
+
if (runOptions.control?.draining) {
|
|
540
|
+
const at = this.now().toISOString();
|
|
541
|
+
checkpoint = {
|
|
542
|
+
...checkpoint,
|
|
543
|
+
status: 'interrupted',
|
|
544
|
+
drained: { ...(runOptions.control.reason ? { reason: runOptions.control.reason } : {}), at },
|
|
545
|
+
createdAt: at,
|
|
546
|
+
};
|
|
547
|
+
await persist(checkpoint, true);
|
|
548
|
+
throw new errors_js_1.GraphDrainedError(threadId, checkpoint.step, runOptions.control.reason);
|
|
549
|
+
}
|
|
448
550
|
if (runOptions.signal?.aborted) {
|
|
449
551
|
checkpoint = { ...checkpoint, status: 'interrupted', createdAt: this.now().toISOString() };
|
|
450
|
-
await persist(checkpoint);
|
|
552
|
+
await persist(checkpoint, true);
|
|
451
553
|
yield this.toEvent(checkpoint, []);
|
|
452
554
|
return;
|
|
453
555
|
}
|
|
@@ -472,7 +574,7 @@ class CompiledGraph {
|
|
|
472
574
|
breakpoint: { when: 'before', nodes: breakBefore },
|
|
473
575
|
createdAt: this.now().toISOString(),
|
|
474
576
|
};
|
|
475
|
-
await persist(checkpoint);
|
|
577
|
+
await persist(checkpoint, true);
|
|
476
578
|
yield this.toEvent(checkpoint, []);
|
|
477
579
|
return;
|
|
478
580
|
}
|
|
@@ -492,6 +594,7 @@ class CompiledGraph {
|
|
|
492
594
|
const gotos = { ...(checkpoint.gotos ?? {}) };
|
|
493
595
|
let parentCommand;
|
|
494
596
|
let failure;
|
|
597
|
+
const recovered = [];
|
|
495
598
|
for (const [index, task] of pendingTasks.entries()) {
|
|
496
599
|
const outcome = outcomes[index];
|
|
497
600
|
if (!outcome)
|
|
@@ -503,6 +606,8 @@ class CompiledGraph {
|
|
|
503
606
|
if (outcome.goto?.length)
|
|
504
607
|
gotos[task.id] = outcome.goto;
|
|
505
608
|
parentCommand ??= outcome.parent;
|
|
609
|
+
if (outcome.recovered)
|
|
610
|
+
recovered.push(outcome.recovered);
|
|
506
611
|
finished.push(task.id);
|
|
507
612
|
}
|
|
508
613
|
else if (outcome.kind === 'interrupt') {
|
|
@@ -518,6 +623,7 @@ class CompiledGraph {
|
|
|
518
623
|
const ranNodes = distinctNodes(allTasks.filter((task) => completed.includes(task.id)));
|
|
519
624
|
const ranTasks = pendingTasks;
|
|
520
625
|
const routeFields = Object.keys(gotos).length > 0 ? { gotos } : {};
|
|
626
|
+
const recoveryFields = recovered.length > 0 ? { recovered } : {};
|
|
521
627
|
if (failure) {
|
|
522
628
|
const failed = {
|
|
523
629
|
...checkpoint,
|
|
@@ -525,6 +631,7 @@ class CompiledGraph {
|
|
|
525
631
|
...pausedFields(allTasks, unfinished),
|
|
526
632
|
completed,
|
|
527
633
|
...routeFields,
|
|
634
|
+
...recoveryFields,
|
|
528
635
|
status: 'failed',
|
|
529
636
|
error: {
|
|
530
637
|
name: failure.error instanceof Error ? failure.error.name : 'Error',
|
|
@@ -532,7 +639,7 @@ class CompiledGraph {
|
|
|
532
639
|
},
|
|
533
640
|
createdAt: this.now().toISOString(),
|
|
534
641
|
};
|
|
535
|
-
await persist(failed);
|
|
642
|
+
await persist(failed, true);
|
|
536
643
|
throw failure.error instanceof errors_js_1.GraphNodeError
|
|
537
644
|
? failure.error
|
|
538
645
|
: new errors_js_1.GraphNodeError(failure.task.node, step, failure.error);
|
|
@@ -545,11 +652,12 @@ class CompiledGraph {
|
|
|
545
652
|
...pausedFields(allTasks, unfinished),
|
|
546
653
|
completed,
|
|
547
654
|
...routeFields,
|
|
655
|
+
...recoveryFields,
|
|
548
656
|
status: asking ? 'awaiting_input' : 'interrupted',
|
|
549
657
|
interrupts,
|
|
550
658
|
createdAt: this.now().toISOString(),
|
|
551
659
|
};
|
|
552
|
-
await persist(checkpoint);
|
|
660
|
+
await persist(checkpoint, true);
|
|
553
661
|
yield this.toEvent(checkpoint, ranNodes, ranTasks, attempts);
|
|
554
662
|
return;
|
|
555
663
|
}
|
|
@@ -561,10 +669,11 @@ class CompiledGraph {
|
|
|
561
669
|
next: [],
|
|
562
670
|
status: 'completed',
|
|
563
671
|
resolved: checkpoint.resolved,
|
|
672
|
+
...recoveryFields,
|
|
564
673
|
createdAt: this.now().toISOString(),
|
|
565
674
|
...(runOptions.metadata ? { metadata: runOptions.metadata } : {}),
|
|
566
675
|
};
|
|
567
|
-
await persist(checkpoint);
|
|
676
|
+
await persist(checkpoint, true);
|
|
568
677
|
yield { ...this.toEvent(checkpoint, ranNodes, ranTasks, attempts), parentCommand };
|
|
569
678
|
return;
|
|
570
679
|
}
|
|
@@ -583,10 +692,11 @@ class CompiledGraph {
|
|
|
583
692
|
status: breakAfter.length > 0 ? 'interrupted' : next.length > 0 ? 'running' : 'completed',
|
|
584
693
|
...(breakAfter.length > 0 ? { breakpoint: { when: 'after', nodes: breakAfter } } : {}),
|
|
585
694
|
resolved: checkpoint.resolved,
|
|
695
|
+
...recoveryFields,
|
|
586
696
|
createdAt: this.now().toISOString(),
|
|
587
697
|
...(runOptions.metadata ? { metadata: runOptions.metadata } : {}),
|
|
588
698
|
};
|
|
589
|
-
await persist(checkpoint);
|
|
699
|
+
await persist(checkpoint, recovered.length > 0 || next.length === 0 || breakAfter.length > 0);
|
|
590
700
|
yield this.toEvent(checkpoint, ranNodes, ranTasks, attempts);
|
|
591
701
|
if (breakAfter.length > 0)
|
|
592
702
|
return;
|
|
@@ -596,8 +706,8 @@ class CompiledGraph {
|
|
|
596
706
|
const definition = this.nodes.get(task.node);
|
|
597
707
|
if (!definition)
|
|
598
708
|
throw new errors_js_1.GraphValidationError(`Node "${task.node}" disappeared before it could run`);
|
|
599
|
-
const policy =
|
|
600
|
-
const
|
|
709
|
+
const policy = this.retryPolicy(definition);
|
|
710
|
+
const limits = { ...this.timeoutOf(definition), ...task.timeout };
|
|
601
711
|
const cachePolicy = definition.options.cache;
|
|
602
712
|
const cache = cachePolicy ? await this.loadNodeCache() : undefined;
|
|
603
713
|
const cacheKey = cachePolicy && cache ? cache.key(cachePolicy, task.node, checkpoint.state, task.input) : undefined;
|
|
@@ -619,22 +729,18 @@ class CompiledGraph {
|
|
|
619
729
|
}
|
|
620
730
|
}
|
|
621
731
|
let attempts = 0;
|
|
732
|
+
const firstAttemptAt = this.now().toISOString();
|
|
622
733
|
while (true) {
|
|
623
734
|
attempts += 1;
|
|
624
735
|
notify(runOptions, { type: 'task_start', step, taskId: task.id, node: task.node, attempt: attempts });
|
|
625
|
-
const
|
|
626
|
-
const
|
|
627
|
-
const signal =
|
|
736
|
+
const timer = attemptTimer(task.node, limits);
|
|
737
|
+
const linked = (0, signals_js_1.linkSignals)([stepSignal, runOptions.signal, timer?.signal]);
|
|
738
|
+
const signal = linked.signal;
|
|
628
739
|
try {
|
|
629
|
-
const running = this.runNode(definition.fn, task, step, threadId, checkpoint, runOptions, signal, attempts);
|
|
630
|
-
if (
|
|
740
|
+
const running = this.runNode(definition.fn, task, step, threadId, checkpoint, runOptions, signal, attempts, timer?.touch);
|
|
741
|
+
if (timer)
|
|
631
742
|
running.catch(() => undefined);
|
|
632
|
-
const output =
|
|
633
|
-
? await Promise.race([
|
|
634
|
-
running,
|
|
635
|
-
rejectWhenAborted(timeout, () => new errors_js_1.GraphNodeTimeoutError(task.node, timeoutMs)),
|
|
636
|
-
])
|
|
637
|
-
: await running;
|
|
743
|
+
const output = timer ? await Promise.race([running, timer.expired]) : await running;
|
|
638
744
|
const parent = output.command?.graph === graph_js_1.Command.PARENT ? output.command : undefined;
|
|
639
745
|
const goto = parent ? undefined : toRouteRecords(output.command?.goto);
|
|
640
746
|
const updates = parent ? [] : output.updates;
|
|
@@ -652,6 +758,7 @@ class CompiledGraph {
|
|
|
652
758
|
return { kind: 'ok', updates, goto, parent, attempts };
|
|
653
759
|
}
|
|
654
760
|
catch (error) {
|
|
761
|
+
timer?.stop();
|
|
655
762
|
if (error instanceof errors_js_1.GraphInterrupt) {
|
|
656
763
|
return {
|
|
657
764
|
kind: 'interrupt',
|
|
@@ -669,10 +776,24 @@ class CompiledGraph {
|
|
|
669
776
|
}
|
|
670
777
|
if (runOptions.signal?.aborted || stepSignal.aborted)
|
|
671
778
|
return { kind: 'aborted', attempts };
|
|
672
|
-
const failure =
|
|
779
|
+
const failure = timer?.error() ?? error;
|
|
673
780
|
const retryable = policy.retryOn ? policy.retryOn(failure, attempts) : isRetryable(failure);
|
|
674
781
|
if (attempts >= Math.max(1, policy.maxAttempts) || !retryable) {
|
|
675
|
-
return
|
|
782
|
+
return this.recover(definition, task, step, checkpoint, runOptions, {
|
|
783
|
+
node: task.node,
|
|
784
|
+
taskId: task.id,
|
|
785
|
+
step,
|
|
786
|
+
attempts,
|
|
787
|
+
firstAttemptAt,
|
|
788
|
+
failedAt: this.now().toISOString(),
|
|
789
|
+
error: failure,
|
|
790
|
+
retryExhausted: retryable,
|
|
791
|
+
...(failure instanceof errors_js_1.GraphNodeTimeoutError
|
|
792
|
+
? { timeout: { type: failure.kind, limitMs: failure.timeoutMs } }
|
|
793
|
+
: {}),
|
|
794
|
+
...(task.input === undefined ? {} : { input: task.input }),
|
|
795
|
+
threadId,
|
|
796
|
+
});
|
|
676
797
|
}
|
|
677
798
|
notify(runOptions, {
|
|
678
799
|
type: 'task_retry',
|
|
@@ -684,9 +805,81 @@ class CompiledGraph {
|
|
|
684
805
|
});
|
|
685
806
|
await delay(backoffDelay(policy, attempts), runOptions.signal);
|
|
686
807
|
}
|
|
808
|
+
finally {
|
|
809
|
+
timer?.stop();
|
|
810
|
+
linked.dispose();
|
|
811
|
+
}
|
|
687
812
|
}
|
|
688
813
|
}
|
|
689
|
-
async
|
|
814
|
+
async recover(definition, task, step, checkpoint, runOptions, failure) {
|
|
815
|
+
const handler = this.errorHandler(definition);
|
|
816
|
+
const event = {
|
|
817
|
+
type: 'task_failed',
|
|
818
|
+
step,
|
|
819
|
+
taskId: task.id,
|
|
820
|
+
node: task.node,
|
|
821
|
+
attempts: failure.attempts,
|
|
822
|
+
error: describe(failure.error),
|
|
823
|
+
};
|
|
824
|
+
if (!handler || failure.error instanceof errors_js_1.GraphValidationError) {
|
|
825
|
+
notify(runOptions, { ...event, recovered: false });
|
|
826
|
+
return { kind: 'failed', error: failure.error, attempts: failure.attempts };
|
|
827
|
+
}
|
|
828
|
+
let decided;
|
|
829
|
+
try {
|
|
830
|
+
decided = await handler(failure, { state: Object.freeze({ ...checkpoint.state }) });
|
|
831
|
+
}
|
|
832
|
+
catch (error) {
|
|
833
|
+
notify(runOptions, { ...event, recovered: false });
|
|
834
|
+
return { kind: 'failed', error, attempts: failure.attempts };
|
|
835
|
+
}
|
|
836
|
+
const command = decided instanceof graph_js_1.Command ? decided : undefined;
|
|
837
|
+
const parent = command?.graph === graph_js_1.Command.PARENT ? command : undefined;
|
|
838
|
+
const goto = parent ? undefined : toRouteRecords(command?.goto);
|
|
839
|
+
const own = command ? command.update : decided;
|
|
840
|
+
const updates = parent || !own ? [] : [own];
|
|
841
|
+
notify(runOptions, { ...event, recovered: true });
|
|
842
|
+
return {
|
|
843
|
+
kind: 'ok',
|
|
844
|
+
updates,
|
|
845
|
+
goto,
|
|
846
|
+
parent,
|
|
847
|
+
attempts: failure.attempts,
|
|
848
|
+
recovered: {
|
|
849
|
+
node: failure.node,
|
|
850
|
+
taskId: failure.taskId,
|
|
851
|
+
step,
|
|
852
|
+
attempts: failure.attempts,
|
|
853
|
+
error: {
|
|
854
|
+
name: failure.error instanceof Error ? failure.error.name : 'Error',
|
|
855
|
+
message: describe(failure.error),
|
|
856
|
+
},
|
|
857
|
+
failedAt: failure.failedAt,
|
|
858
|
+
retryExhausted: failure.retryExhausted,
|
|
859
|
+
...(failure.timeout ? { timeout: failure.timeout } : {}),
|
|
860
|
+
...(goto?.length ? { goto: goto.map(routeName) } : {}),
|
|
861
|
+
},
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
retryPolicy(definition) {
|
|
865
|
+
return {
|
|
866
|
+
...DEFAULT_RETRY,
|
|
867
|
+
...this.options.retry,
|
|
868
|
+
...this.options.nodeDefaults?.retry,
|
|
869
|
+
...definition.options.retry,
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
timeoutOf(definition) {
|
|
873
|
+
const defaults = this.options.nodeDefaults?.timeout;
|
|
874
|
+
const own = definition.options;
|
|
875
|
+
const runMs = own.timeout?.runMs ?? own.timeoutMs ?? defaults?.runMs;
|
|
876
|
+
const idleMs = own.timeout?.idleMs ?? defaults?.idleMs;
|
|
877
|
+
return { ...(runMs === undefined ? {} : { runMs }), ...(idleMs === undefined ? {} : { idleMs }) };
|
|
878
|
+
}
|
|
879
|
+
errorHandler(definition) {
|
|
880
|
+
return definition.options.onError ?? this.options.nodeDefaults?.onError;
|
|
881
|
+
}
|
|
882
|
+
async runNode(fn, task, step, threadId, checkpoint, runOptions, signal, attempt, touch = noop) {
|
|
690
883
|
const node = task.node;
|
|
691
884
|
let interruptIndex = 0;
|
|
692
885
|
const context = {
|
|
@@ -694,11 +887,18 @@ class CompiledGraph {
|
|
|
694
887
|
node,
|
|
695
888
|
step,
|
|
696
889
|
threadId,
|
|
890
|
+
...(runOptions.tenantId !== undefined ? { tenantId: runOptions.tenantId } : {}),
|
|
697
891
|
taskId: task.id,
|
|
698
892
|
input: task.input,
|
|
699
893
|
attempt,
|
|
700
894
|
signal,
|
|
701
|
-
...(this.options.store
|
|
895
|
+
...(this.options.store
|
|
896
|
+
? {
|
|
897
|
+
store: runOptions.tenantId !== undefined
|
|
898
|
+
? (0, tenant_js_1.tenantStore)(this.options.store, runOptions.tenantId)
|
|
899
|
+
: this.options.store,
|
|
900
|
+
}
|
|
901
|
+
: {}),
|
|
702
902
|
interrupt: (request) => {
|
|
703
903
|
const index = interruptIndex++;
|
|
704
904
|
const key = (0, errors_js_1.interruptKey)({ node, taskId: task.id, step, index });
|
|
@@ -710,8 +910,21 @@ class CompiledGraph {
|
|
|
710
910
|
}
|
|
711
911
|
throw new errors_js_1.GraphInterrupt(request, node, step, index, task.id);
|
|
712
912
|
},
|
|
713
|
-
emit: (data) =>
|
|
913
|
+
emit: (data) => {
|
|
914
|
+
touch();
|
|
915
|
+
notify(runOptions, { type: 'custom', step, taskId: task.id, node, data });
|
|
916
|
+
},
|
|
917
|
+
heartbeat: touch,
|
|
918
|
+
message: (chunk) => {
|
|
919
|
+
touch();
|
|
920
|
+
notify(runOptions, { type: 'message', step, taskId: task.id, node, chunk });
|
|
921
|
+
},
|
|
922
|
+
tool: (event) => {
|
|
923
|
+
touch();
|
|
924
|
+
notify(runOptions, { type: 'tool', step, taskId: task.id, node, tool: event });
|
|
925
|
+
},
|
|
714
926
|
report: (progress) => {
|
|
927
|
+
touch();
|
|
715
928
|
if (!runOptions.onProgress)
|
|
716
929
|
return;
|
|
717
930
|
try {
|
|
@@ -721,6 +934,11 @@ class CompiledGraph {
|
|
|
721
934
|
}
|
|
722
935
|
},
|
|
723
936
|
};
|
|
937
|
+
if (runOptions.subgraphEvents) {
|
|
938
|
+
Object.defineProperty(context, FORWARD_EVENT, {
|
|
939
|
+
value: (event) => notify(runOptions, { ...event, namespace: [node, ...(event.namespace ?? [])] }),
|
|
940
|
+
});
|
|
941
|
+
}
|
|
724
942
|
const result = await fn(context);
|
|
725
943
|
const interrupted = interruptIndex > 0;
|
|
726
944
|
if (result instanceof graph_js_1.Command) {
|
|
@@ -780,7 +998,12 @@ class CompiledGraph {
|
|
|
780
998
|
if (!this.nodes.has(target.node)) {
|
|
781
999
|
throw new errors_js_1.GraphValidationError(`Send from "${from}" targets unknown node "${target.node}"`);
|
|
782
1000
|
}
|
|
783
|
-
tasks.push({
|
|
1001
|
+
tasks.push({
|
|
1002
|
+
id: `${target.node}#${step + 1}.${sends++}`,
|
|
1003
|
+
node: target.node,
|
|
1004
|
+
input: target.input,
|
|
1005
|
+
...(target.options?.timeout ? { timeout: target.options.timeout } : {}),
|
|
1006
|
+
});
|
|
784
1007
|
return;
|
|
785
1008
|
}
|
|
786
1009
|
if (target === graph_js_1.END)
|
|
@@ -807,7 +1030,9 @@ class CompiledGraph {
|
|
|
807
1030
|
}
|
|
808
1031
|
}
|
|
809
1032
|
for (const { from, target } of routes) {
|
|
810
|
-
add(typeof target === 'string'
|
|
1033
|
+
add(typeof target === 'string'
|
|
1034
|
+
? target
|
|
1035
|
+
: new graph_js_1.Send(target.node, target.input, target.timeout ? { timeout: target.timeout } : undefined), from);
|
|
811
1036
|
}
|
|
812
1037
|
return tasks;
|
|
813
1038
|
}
|
|
@@ -823,9 +1048,9 @@ class CompiledGraph {
|
|
|
823
1048
|
}
|
|
824
1049
|
return this.reduce(state, [input]);
|
|
825
1050
|
}
|
|
826
|
-
async requireCheckpoint(threadId) {
|
|
1051
|
+
async requireCheckpoint(threadId, tenantId) {
|
|
827
1052
|
const checkpoint = await this.checkpointer()?.get(threadId);
|
|
828
|
-
if (!checkpoint)
|
|
1053
|
+
if (!checkpoint || !ownedBy(checkpoint, tenantId))
|
|
829
1054
|
throw new errors_js_1.GraphThreadNotFoundError(threadId);
|
|
830
1055
|
return (0, checkpoint_migration_js_1.migrateCheckpoint)(checkpoint);
|
|
831
1056
|
}
|
|
@@ -875,6 +1100,7 @@ class CompiledGraph {
|
|
|
875
1100
|
? { interrupt: checkpoint.interrupts[0], interrupts: checkpoint.interrupts }
|
|
876
1101
|
: {}),
|
|
877
1102
|
...(checkpoint.breakpoint ? { breakpoint: checkpoint.breakpoint } : {}),
|
|
1103
|
+
...(checkpoint.recovered?.length ? { recovered: checkpoint.recovered } : {}),
|
|
878
1104
|
};
|
|
879
1105
|
}
|
|
880
1106
|
toResult(threadId, last) {
|
|
@@ -971,21 +1197,77 @@ function toRouteRecords(goto) {
|
|
|
971
1197
|
if (goto === undefined)
|
|
972
1198
|
return undefined;
|
|
973
1199
|
return (Array.isArray(goto) ? goto : [goto]).map((target) => target instanceof graph_js_1.Send
|
|
974
|
-
? {
|
|
1200
|
+
? {
|
|
1201
|
+
node: target.node,
|
|
1202
|
+
...(target.input === undefined ? {} : { input: target.input }),
|
|
1203
|
+
...(target.options?.timeout ? { timeout: target.options.timeout } : {}),
|
|
1204
|
+
}
|
|
975
1205
|
: target);
|
|
976
1206
|
}
|
|
977
1207
|
function routeName(route) {
|
|
978
1208
|
return typeof route === 'string' ? route : route.node;
|
|
979
1209
|
}
|
|
980
|
-
function
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1210
|
+
function noop() { }
|
|
1211
|
+
function attemptTimer(node, limits) {
|
|
1212
|
+
const { runMs, idleMs } = limits;
|
|
1213
|
+
if (runMs === undefined && idleMs === undefined)
|
|
1214
|
+
return undefined;
|
|
1215
|
+
const controller = new AbortController();
|
|
1216
|
+
let reached;
|
|
1217
|
+
let reject = noop;
|
|
1218
|
+
const expired = new Promise((_, fail) => {
|
|
1219
|
+
reject = fail;
|
|
987
1220
|
});
|
|
1221
|
+
expired.catch(noop);
|
|
1222
|
+
const fire = (error) => {
|
|
1223
|
+
if (reached)
|
|
1224
|
+
return;
|
|
1225
|
+
reached = error;
|
|
1226
|
+
controller.abort(error);
|
|
1227
|
+
reject(error);
|
|
1228
|
+
};
|
|
1229
|
+
const runTimer = runMs === undefined ? undefined : setTimeout(() => fire(new errors_js_1.GraphNodeTimeoutError(node, runMs)), runMs);
|
|
1230
|
+
let idleTimer;
|
|
1231
|
+
const armIdle = () => {
|
|
1232
|
+
if (idleMs === undefined || reached)
|
|
1233
|
+
return;
|
|
1234
|
+
if (idleTimer)
|
|
1235
|
+
clearTimeout(idleTimer);
|
|
1236
|
+
idleTimer = setTimeout(() => fire(new errors_js_1.GraphNodeTimeoutError(node, idleMs, 'idle')), idleMs);
|
|
1237
|
+
};
|
|
1238
|
+
armIdle();
|
|
1239
|
+
return {
|
|
1240
|
+
signal: controller.signal,
|
|
1241
|
+
expired,
|
|
1242
|
+
touch: armIdle,
|
|
1243
|
+
error: () => reached,
|
|
1244
|
+
stop: () => {
|
|
1245
|
+
if (runTimer)
|
|
1246
|
+
clearTimeout(runTimer);
|
|
1247
|
+
if (idleTimer)
|
|
1248
|
+
clearTimeout(idleTimer);
|
|
1249
|
+
idleTimer = undefined;
|
|
1250
|
+
},
|
|
1251
|
+
};
|
|
988
1252
|
}
|
|
989
1253
|
function isRetryable(error) {
|
|
990
1254
|
return !(error instanceof errors_js_1.GraphValidationError);
|
|
991
1255
|
}
|
|
1256
|
+
function tenantOf(checkpoint) {
|
|
1257
|
+
const tenantId = checkpoint.metadata?.tenantId;
|
|
1258
|
+
return typeof tenantId === 'string' ? tenantId : undefined;
|
|
1259
|
+
}
|
|
1260
|
+
function ownedBy(checkpoint, tenantId) {
|
|
1261
|
+
if (tenantId === undefined)
|
|
1262
|
+
return true;
|
|
1263
|
+
const owner = tenantOf(checkpoint);
|
|
1264
|
+
return owner === undefined || owner === tenantId;
|
|
1265
|
+
}
|
|
1266
|
+
async function* releasing(source, release) {
|
|
1267
|
+
try {
|
|
1268
|
+
yield* source;
|
|
1269
|
+
}
|
|
1270
|
+
finally {
|
|
1271
|
+
release();
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
@@ -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';
|