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
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import type { OperationLifecycleLike } from '../types/lifecycle.js';
|
|
2
2
|
import { GraphError } from './errors.js';
|
|
3
|
-
import type { GraphCheckpoint, GraphCheckpointer, GraphDescription, GraphEvent, GraphStatus, InterruptRequest, PendingInterrupt, RetryPolicy } from '../types/graph.js';
|
|
3
|
+
import type { GraphCheckpoint, GraphCheckpointer, GraphDescription, GraphEvent, GraphStatus, InterruptRequest, PendingInterrupt, RetryPolicy, RunControlLike } from '../types/graph.js';
|
|
4
4
|
import type { Store } from '../types/store.js';
|
|
5
5
|
/** What a workflow checkpoint holds: the input, every completed step's result, and the output. */
|
|
6
6
|
export interface WorkflowState<I = unknown, O = unknown> {
|
|
7
7
|
/** The input the workflow was started with. */
|
|
8
8
|
input: I;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Each completed step's result, keyed by step name — `name#2` for the second call with a name. A
|
|
11
|
+
* step whose `onError` supplied its result after its retries ran out also records `recovered`.
|
|
12
|
+
*/
|
|
10
13
|
steps: Record<string, {
|
|
11
14
|
value?: unknown;
|
|
15
|
+
recovered?: StepRecovery;
|
|
12
16
|
}>;
|
|
13
17
|
/** The workflow's return value, once it has completed. */
|
|
14
18
|
output?: O;
|
|
@@ -23,21 +27,68 @@ export interface StepContext {
|
|
|
23
27
|
readonly attempt: number;
|
|
24
28
|
/** Aborted when the run is cancelled or the step exceeds its timeout. */
|
|
25
29
|
readonly signal: AbortSignal;
|
|
30
|
+
/**
|
|
31
|
+
* Shows the step is still making progress, which refreshes its idle timeout. For long work that
|
|
32
|
+
* sends nothing else, such as a large upload or a slow tool call.
|
|
33
|
+
*/
|
|
34
|
+
heartbeat(): void;
|
|
35
|
+
}
|
|
36
|
+
/** Limits on one attempt of a step: its whole run, and the time it may go without progress. */
|
|
37
|
+
export interface StepTimeout {
|
|
38
|
+
/** Fails the attempt when it runs longer than this, in milliseconds. */
|
|
39
|
+
runMs?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Fails the attempt when this long passes without `context.heartbeat()`, in milliseconds, which
|
|
42
|
+
* tells a hung step from a slow one that is working.
|
|
43
|
+
*/
|
|
44
|
+
idleMs?: number;
|
|
45
|
+
}
|
|
46
|
+
/** What a step's `onError` receives once its retries have run out. */
|
|
47
|
+
export interface StepFailure {
|
|
48
|
+
/** The step's name. */
|
|
49
|
+
name: string;
|
|
50
|
+
/** The key its result is recorded under. */
|
|
51
|
+
key: string;
|
|
52
|
+
/** Attempts made. */
|
|
53
|
+
attempts: number;
|
|
54
|
+
/** The last attempt's error. */
|
|
55
|
+
error: unknown;
|
|
56
|
+
}
|
|
57
|
+
/** How a step's result was recovered, as recorded in the workflow state. */
|
|
58
|
+
export interface StepRecovery {
|
|
59
|
+
/** The error that exhausted the step's retries. */
|
|
60
|
+
error: {
|
|
61
|
+
name: string;
|
|
62
|
+
message: string;
|
|
63
|
+
};
|
|
64
|
+
/** Attempts made before `onError` decided. */
|
|
65
|
+
attempts: number;
|
|
26
66
|
}
|
|
27
67
|
/** How one step runs. */
|
|
28
|
-
export interface StepOptions {
|
|
68
|
+
export interface StepOptions<T = unknown> {
|
|
29
69
|
/** Retries a failing attempt, overriding the workflow's default policy. */
|
|
30
70
|
retry?: RetryPolicy;
|
|
31
71
|
/** Aborts the step's signal and fails the attempt when it runs longer than this, in milliseconds. */
|
|
32
72
|
timeoutMs?: number;
|
|
73
|
+
/** Run and idle limits on each attempt. `runMs` is `timeoutMs` by another name; `timeoutMs` wins when both are set. */
|
|
74
|
+
timeout?: StepTimeout;
|
|
75
|
+
/**
|
|
76
|
+
* Decides what happens once the step's retries run out. What it returns becomes the step's
|
|
77
|
+
* result, recorded with `recovered`, so a resumed run does not run the step again — a refund after
|
|
78
|
+
* a charge that kept failing, say. Throwing fails the step with that error. A cancelled run, a
|
|
79
|
+
* question, or a drain is never passed to it.
|
|
80
|
+
*/
|
|
81
|
+
onError?: (failure: StepFailure) => T | Promise<T>;
|
|
33
82
|
}
|
|
34
83
|
/** What a workflow function receives besides its input. */
|
|
35
84
|
export interface WorkflowContext {
|
|
36
85
|
/** The thread this run belongs to. */
|
|
37
86
|
readonly threadId: string;
|
|
87
|
+
/** The tenant the run is for, when it has one. */
|
|
88
|
+
readonly tenantId?: string;
|
|
38
89
|
/** Aborted when the run is cancelled. */
|
|
39
90
|
readonly signal: AbortSignal;
|
|
40
|
-
/** Long-term memory, when the workflow was created with a store. */
|
|
91
|
+
/** Long-term memory, when the workflow was created with a store. In a tenant's run, the tenant's view of it. */
|
|
41
92
|
readonly store?: Store;
|
|
42
93
|
/**
|
|
43
94
|
* Runs a piece of work once per thread and records its result.
|
|
@@ -46,7 +97,7 @@ export interface WorkflowContext {
|
|
|
46
97
|
* running. Name steps so the same call has the same name every time; a name used more than once
|
|
47
98
|
* is numbered in call order. The result must survive JSON serialization.
|
|
48
99
|
*/
|
|
49
|
-
step<T>(name: string, run: (context: StepContext) => Promise<T> | T, options?: StepOptions): Promise<T>;
|
|
100
|
+
step<T>(name: string, run: (context: StepContext) => Promise<T> | T, options?: StepOptions<T>): Promise<T>;
|
|
50
101
|
/**
|
|
51
102
|
* Suspends the workflow until a person answers.
|
|
52
103
|
*
|
|
@@ -73,6 +124,11 @@ export interface WorkflowOptions {
|
|
|
73
124
|
store?: Store;
|
|
74
125
|
/** Default retry policy for every step. A step's own policy wins. Defaults to one attempt. */
|
|
75
126
|
retry?: RetryPolicy;
|
|
127
|
+
/**
|
|
128
|
+
* Defaults for every step: its retries, its run and idle timeouts, and its `onError`. A step's own
|
|
129
|
+
* options win, field by field.
|
|
130
|
+
*/
|
|
131
|
+
stepDefaults?: Pick<StepOptions, 'retry' | 'timeout' | 'onError'>;
|
|
76
132
|
/** Steps that may run at once, for a workflow that starts many with `Promise.all`. Defaults to 16. */
|
|
77
133
|
maxConcurrency?: number;
|
|
78
134
|
/**
|
|
@@ -93,6 +149,19 @@ export interface WorkflowRunOptions {
|
|
|
93
149
|
metadata?: Record<string, unknown>;
|
|
94
150
|
/** Receives each step starting, retrying, and finishing, each checkpoint, and custom events. */
|
|
95
151
|
onEvent?: (event: GraphEvent) => void;
|
|
152
|
+
/**
|
|
153
|
+
* Lets the caller stop the run between steps: pass a `RunControl` and call `drain()`. Steps in
|
|
154
|
+
* flight finish and are recorded, no new step starts, and the run ends with `GraphDrainedError`;
|
|
155
|
+
* `continue()` carries it on, on this worker or another. The agent server drains a workflow it
|
|
156
|
+
* serves this way.
|
|
157
|
+
*/
|
|
158
|
+
control?: RunControlLike;
|
|
159
|
+
/**
|
|
160
|
+
* The tenant the run is for. Recorded on every checkpoint as `metadata.tenantId`, read as
|
|
161
|
+
* `context.tenantId`, and scoping `context.store`; another tenant's thread is not found. A run
|
|
162
|
+
* without one carries on the thread's.
|
|
163
|
+
*/
|
|
164
|
+
tenantId?: string;
|
|
96
165
|
}
|
|
97
166
|
/** One event of a streamed workflow run. */
|
|
98
167
|
export type WorkflowEvent<O = unknown> = {
|
|
@@ -152,17 +221,21 @@ export interface WorkflowResult<O = unknown> {
|
|
|
152
221
|
/** Every pending question. */
|
|
153
222
|
interrupts?: PendingInterrupt[];
|
|
154
223
|
}
|
|
155
|
-
/** Raised when a step outlives its
|
|
224
|
+
/** Raised when a step outlives its run timeout, or goes longer than its idle timeout without progress. */
|
|
156
225
|
export declare class WorkflowStepTimeoutError extends GraphError {
|
|
157
226
|
/** The step. */
|
|
158
227
|
readonly stepName: string;
|
|
159
228
|
/** The limit it exceeded, in milliseconds. */
|
|
160
229
|
readonly timeoutMs: number;
|
|
230
|
+
/** Which limit: `run` for the whole attempt, `idle` for the time without progress. */
|
|
231
|
+
readonly kind: 'run' | 'idle';
|
|
161
232
|
constructor(
|
|
162
233
|
/** The step. */
|
|
163
234
|
stepName: string,
|
|
164
235
|
/** The limit it exceeded, in milliseconds. */
|
|
165
|
-
timeoutMs: number
|
|
236
|
+
timeoutMs: number,
|
|
237
|
+
/** Which limit: `run` for the whole attempt, `idle` for the time without progress. */
|
|
238
|
+
kind?: 'run' | 'idle');
|
|
166
239
|
}
|
|
167
240
|
/**
|
|
168
241
|
* A durable workflow: a function whose steps are checkpointed, so it survives interrupts, restarts,
|
package/dist/graph/functional.js
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import { MemoryGraphCheckpointer } from './checkpointer.js';
|
|
2
2
|
import { withLifecycle } from '../lifecycle/run.js';
|
|
3
3
|
import { migrateCheckpoint, toCheckpoint } from './checkpoint-migration.js';
|
|
4
|
-
import {
|
|
4
|
+
import { tenantStore } from '../store/tenant.js';
|
|
5
|
+
import { GraphDrainedError, GraphError, GraphNotInterruptedError, GraphThreadNotFoundError } from './errors.js';
|
|
5
6
|
export class WorkflowStepTimeoutError extends GraphError {
|
|
6
7
|
stepName;
|
|
7
8
|
timeoutMs;
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
kind;
|
|
10
|
+
constructor(stepName, timeoutMs, kind = 'run') {
|
|
11
|
+
super(kind === 'idle'
|
|
12
|
+
? `Step "${stepName}" made no progress for ${timeoutMs} ms`
|
|
13
|
+
: `Step "${stepName}" exceeded its ${timeoutMs} ms timeout`, 'WORKFLOW_STEP_TIMEOUT');
|
|
10
14
|
this.stepName = stepName;
|
|
11
15
|
this.timeoutMs = timeoutMs;
|
|
16
|
+
this.kind = kind;
|
|
12
17
|
this.name = 'WorkflowStepTimeoutError';
|
|
13
18
|
}
|
|
14
19
|
}
|
|
20
|
+
class WorkflowDraining extends Error {
|
|
21
|
+
constructor() {
|
|
22
|
+
super('The workflow is draining');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
15
25
|
class WorkflowSuspended extends Error {
|
|
16
26
|
pending;
|
|
17
27
|
constructor(pending) {
|
|
@@ -40,10 +50,16 @@ export class Workflow {
|
|
|
40
50
|
}
|
|
41
51
|
stream(input, runOptions = {}) {
|
|
42
52
|
const threadId = runOptions.threadId ?? generatedId();
|
|
43
|
-
return this.execute(threadId, runOptions, async () =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
return this.execute(threadId, runOptions, async () => {
|
|
54
|
+
const latest = await this.latest(threadId);
|
|
55
|
+
if (latest && runOptions.tenantId !== undefined) {
|
|
56
|
+
const owner = latest.metadata?.tenantId;
|
|
57
|
+
if (typeof owner === 'string' && owner !== runOptions.tenantId) {
|
|
58
|
+
throw new GraphError(`Thread "${threadId}" cannot be used by this tenant; choose another id`, 'GRAPH_VALIDATION_ERROR');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { ...this.fresh(threadId, input), step: latest?.step ?? 0 };
|
|
62
|
+
});
|
|
47
63
|
}
|
|
48
64
|
resume(threadId, value, runOptions = {}) {
|
|
49
65
|
return this.execute(threadId, runOptions, async () => {
|
|
@@ -137,11 +153,21 @@ export class Workflow {
|
|
|
137
153
|
}
|
|
138
154
|
async run(threadId, runOptions, start, queue) {
|
|
139
155
|
const initial = await start();
|
|
156
|
+
const owner = typeof initial.metadata?.tenantId === 'string' ? initial.metadata.tenantId : undefined;
|
|
157
|
+
if (runOptions.tenantId !== undefined && owner !== undefined && owner !== runOptions.tenantId) {
|
|
158
|
+
throw new GraphThreadNotFoundError(threadId);
|
|
159
|
+
}
|
|
160
|
+
const tenantId = runOptions.tenantId ?? owner;
|
|
140
161
|
const checkpointer = this.checkpointer();
|
|
141
162
|
const state = structuredClone(initial.state);
|
|
142
163
|
state.steps ??= {};
|
|
143
164
|
const resolved = { ...initial.resolved };
|
|
144
|
-
const metadata = {
|
|
165
|
+
const metadata = {
|
|
166
|
+
...initial.metadata,
|
|
167
|
+
graph: this.name,
|
|
168
|
+
...runOptions.metadata,
|
|
169
|
+
...(tenantId === undefined ? {} : { tenantId }),
|
|
170
|
+
};
|
|
145
171
|
let stepNumber = initial.step;
|
|
146
172
|
let writes = Promise.resolve();
|
|
147
173
|
const persist = (checkpoint) => {
|
|
@@ -171,11 +197,16 @@ export class Workflow {
|
|
|
171
197
|
const inFlight = new Set();
|
|
172
198
|
const suspended = [];
|
|
173
199
|
let interruptIndex = 0;
|
|
200
|
+
let drained = false;
|
|
174
201
|
const limiter = new Limiter(this.options.maxConcurrency ?? 16);
|
|
202
|
+
const defaults = this.options.stepDefaults ?? {};
|
|
175
203
|
const context = {
|
|
176
204
|
threadId,
|
|
205
|
+
...(tenantId === undefined ? {} : { tenantId }),
|
|
177
206
|
signal: controller.signal,
|
|
178
|
-
...(this.options.store
|
|
207
|
+
...(this.options.store
|
|
208
|
+
? { store: tenantId === undefined ? this.options.store : tenantStore(this.options.store, tenantId) }
|
|
209
|
+
: {}),
|
|
179
210
|
step: (name, run, options = {}) => {
|
|
180
211
|
const count = (counts.get(name) ?? 0) + 1;
|
|
181
212
|
counts.set(name, count);
|
|
@@ -185,10 +216,22 @@ export class Workflow {
|
|
|
185
216
|
queue.push({ type: 'step', step: stepNumber, name, key, cached: true, state: snapshot(), status: 'running' });
|
|
186
217
|
return Promise.resolve(recorded.value);
|
|
187
218
|
}
|
|
219
|
+
if (runOptions.control?.draining) {
|
|
220
|
+
drained = true;
|
|
221
|
+
return Promise.reject(new WorkflowDraining());
|
|
222
|
+
}
|
|
223
|
+
const merged = {
|
|
224
|
+
...defaults,
|
|
225
|
+
...options,
|
|
226
|
+
timeout: { ...defaults.timeout, ...options.timeout },
|
|
227
|
+
};
|
|
188
228
|
const work = limiter
|
|
189
|
-
.run(() => this.runStep(name, key, run, { ...this.options.retry, ...options.retry },
|
|
190
|
-
.then(async (value) => {
|
|
191
|
-
state.steps[key] =
|
|
229
|
+
.run(() => this.runStep(name, key, run, { ...this.options.retry, ...defaults.retry, ...options.retry }, merged, controller.signal, runOptions, stepNumber))
|
|
230
|
+
.then(async ({ value, recovered }) => {
|
|
231
|
+
state.steps[key] = {
|
|
232
|
+
...(value === undefined ? {} : { value: structuredClone(value) }),
|
|
233
|
+
...(recovered ? { recovered } : {}),
|
|
234
|
+
};
|
|
192
235
|
await persist({ state: state, next: [this.name], status: 'running' });
|
|
193
236
|
queue.push({
|
|
194
237
|
type: 'step',
|
|
@@ -262,6 +305,18 @@ export class Workflow {
|
|
|
262
305
|
queue.push({ type: 'interrupt', step: stepNumber, state: snapshot(), status: 'interrupted' });
|
|
263
306
|
return;
|
|
264
307
|
}
|
|
308
|
+
if (drained && outcome.kind === 'failed') {
|
|
309
|
+
const reason = runOptions.control?.reason;
|
|
310
|
+
await persist({
|
|
311
|
+
state: state,
|
|
312
|
+
next: [this.name],
|
|
313
|
+
status: 'interrupted',
|
|
314
|
+
resolved,
|
|
315
|
+
drained: { ...(reason ? { reason } : {}), at: this.now().toISOString() },
|
|
316
|
+
});
|
|
317
|
+
await writes;
|
|
318
|
+
throw new GraphDrainedError(threadId, stepNumber, reason);
|
|
319
|
+
}
|
|
265
320
|
if (outcome.kind === 'failed') {
|
|
266
321
|
const error = outcome.error;
|
|
267
322
|
await persist({
|
|
@@ -284,41 +339,87 @@ export class Workflow {
|
|
|
284
339
|
}
|
|
285
340
|
async runStep(name, key, run, retry, options, signal, runOptions, step) {
|
|
286
341
|
const policy = { ...DEFAULT_RETRY, ...retry };
|
|
342
|
+
const runMs = options.timeoutMs ?? options.timeout?.runMs;
|
|
343
|
+
const idleMs = options.timeout?.idleMs;
|
|
287
344
|
for (let attempt = 1;; attempt += 1) {
|
|
288
345
|
notify(runOptions, { type: 'task_start', step, taskId: key, node: name, attempt });
|
|
289
346
|
const stepController = new AbortController();
|
|
290
347
|
const forward = () => stepController.abort(signal.reason);
|
|
291
348
|
signal.addEventListener('abort', forward, { once: true });
|
|
292
|
-
let
|
|
293
|
-
let
|
|
349
|
+
let runTimer;
|
|
350
|
+
let idleTimer;
|
|
351
|
+
let timedOut;
|
|
352
|
+
let expire = () => undefined;
|
|
353
|
+
const limits = runMs === undefined && idleMs === undefined
|
|
354
|
+
? undefined
|
|
355
|
+
: new Promise((_, reject) => {
|
|
356
|
+
expire = (error) => {
|
|
357
|
+
if (timedOut)
|
|
358
|
+
return;
|
|
359
|
+
timedOut = error;
|
|
360
|
+
reject(error);
|
|
361
|
+
stepController.abort();
|
|
362
|
+
};
|
|
363
|
+
});
|
|
364
|
+
limits?.catch(() => undefined);
|
|
365
|
+
if (runMs !== undefined)
|
|
366
|
+
runTimer = setTimeout(() => expire(new WorkflowStepTimeoutError(name, runMs)), runMs);
|
|
367
|
+
const armIdle = () => {
|
|
368
|
+
if (idleMs === undefined || timedOut)
|
|
369
|
+
return;
|
|
370
|
+
if (idleTimer)
|
|
371
|
+
clearTimeout(idleTimer);
|
|
372
|
+
idleTimer = setTimeout(() => expire(new WorkflowStepTimeoutError(name, idleMs, 'idle')), idleMs);
|
|
373
|
+
};
|
|
374
|
+
armIdle();
|
|
294
375
|
try {
|
|
295
|
-
const work = Promise.resolve(run({ name, key, attempt, signal: stepController.signal }));
|
|
296
|
-
const value =
|
|
297
|
-
? await work
|
|
298
|
-
: await Promise.race([
|
|
299
|
-
work,
|
|
300
|
-
new Promise((_, reject) => {
|
|
301
|
-
timer = setTimeout(() => {
|
|
302
|
-
timedOut = true;
|
|
303
|
-
reject(new WorkflowStepTimeoutError(name, options.timeoutMs));
|
|
304
|
-
stepController.abort();
|
|
305
|
-
}, options.timeoutMs);
|
|
306
|
-
}),
|
|
307
|
-
]);
|
|
376
|
+
const work = Promise.resolve(run({ name, key, attempt, signal: stepController.signal, heartbeat: armIdle }));
|
|
377
|
+
const value = limits ? await Promise.race([work, limits]) : await work;
|
|
308
378
|
if (timedOut)
|
|
309
|
-
throw
|
|
379
|
+
throw timedOut;
|
|
310
380
|
notify(runOptions, { type: 'task_end', step, taskId: key, node: name, update: value });
|
|
311
|
-
return value;
|
|
381
|
+
return { value };
|
|
312
382
|
}
|
|
313
383
|
catch (error) {
|
|
314
384
|
if (signal.aborted || error instanceof WorkflowSuspended)
|
|
315
385
|
throw error;
|
|
316
|
-
const failure = timedOut
|
|
386
|
+
const failure = timedOut ?? error;
|
|
317
387
|
const retryable = policy.retryOn
|
|
318
388
|
? policy.retryOn(failure, attempt)
|
|
319
|
-
: !(failure instanceof GraphError) || timedOut;
|
|
320
|
-
if (attempt >= Math.max(1, policy.maxAttempts) || !retryable)
|
|
321
|
-
|
|
389
|
+
: !(failure instanceof GraphError) || timedOut !== undefined;
|
|
390
|
+
if (attempt >= Math.max(1, policy.maxAttempts) || !retryable) {
|
|
391
|
+
if (!options.onError)
|
|
392
|
+
throw failure;
|
|
393
|
+
const failed = (recovered) => notify(runOptions, {
|
|
394
|
+
type: 'task_failed',
|
|
395
|
+
step,
|
|
396
|
+
taskId: key,
|
|
397
|
+
node: name,
|
|
398
|
+
attempts: attempt,
|
|
399
|
+
error: failure instanceof Error ? failure.message : String(failure),
|
|
400
|
+
recovered,
|
|
401
|
+
});
|
|
402
|
+
let value;
|
|
403
|
+
try {
|
|
404
|
+
value = await options.onError({ name, key, attempts: attempt, error: failure });
|
|
405
|
+
}
|
|
406
|
+
catch (decision) {
|
|
407
|
+
failed(false);
|
|
408
|
+
throw decision;
|
|
409
|
+
}
|
|
410
|
+
failed(true);
|
|
411
|
+
notify(runOptions, { type: 'task_end', step, taskId: key, node: name, update: value });
|
|
412
|
+
return {
|
|
413
|
+
value,
|
|
414
|
+
recovered: {
|
|
415
|
+
error: {
|
|
416
|
+
name: failure instanceof Error ? failure.name : 'Error',
|
|
417
|
+
message: failure instanceof Error ? failure.message : String(failure),
|
|
418
|
+
},
|
|
419
|
+
attempts: attempt,
|
|
420
|
+
},
|
|
421
|
+
};
|
|
422
|
+
}
|
|
322
423
|
notify(runOptions, {
|
|
323
424
|
type: 'task_retry',
|
|
324
425
|
step,
|
|
@@ -330,8 +431,10 @@ export class Workflow {
|
|
|
330
431
|
await sleep(backoff(policy, attempt), signal);
|
|
331
432
|
}
|
|
332
433
|
finally {
|
|
333
|
-
if (
|
|
334
|
-
clearTimeout(
|
|
434
|
+
if (runTimer)
|
|
435
|
+
clearTimeout(runTimer);
|
|
436
|
+
if (idleTimer)
|
|
437
|
+
clearTimeout(idleTimer);
|
|
335
438
|
signal.removeEventListener('abort', forward);
|
|
336
439
|
}
|
|
337
440
|
}
|
package/dist/graph/graph.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { ChannelSchema, CompileOptions, EdgeRouter, GraphCheckpoint, GraphDescription, GraphInput, GraphProgress, GraphResult, GraphRunOptions, GraphStatus, GraphStepEvent, NodeFn, NodeOptions, StateUpdate } from '../types/graph.js';
|
|
1
|
+
import type { ChannelSchema, CompileOptions, EdgeRouter, GraphCheckpoint, GraphDescription, GraphEventsOptions, GraphInput, GraphProgress, GraphResult, GraphRunOptions, GraphStatus, GraphStepEvent, NodeFn, NodeOptions, StateUpdate } from '../types/graph.js';
|
|
2
|
+
import { GraphEventStream } from './event-stream.js';
|
|
2
3
|
interface GraphNodeDefinition<S extends ChannelSchema> {
|
|
3
4
|
fn: NodeFn<S>;
|
|
4
|
-
options: NodeOptions
|
|
5
|
+
options: NodeOptions<S>;
|
|
5
6
|
}
|
|
6
7
|
/** Which channels a caller may write and read, as `createGraph()` declared them. */
|
|
7
8
|
interface GraphScope {
|
|
@@ -29,7 +30,7 @@ export declare class StateGraph<S extends ChannelSchema, I extends keyof S = key
|
|
|
29
30
|
private readonly edges;
|
|
30
31
|
constructor(channels: S, scope?: GraphScope);
|
|
31
32
|
/** Adds a node. Returns the graph, for chaining. */
|
|
32
|
-
addNode(name: string, fn: NodeFn<S>, options?: NodeOptions): this;
|
|
33
|
+
addNode(name: string, fn: NodeFn<S>, options?: NodeOptions<S>): this;
|
|
33
34
|
/** Adds an edge that always runs `to` after `from`. Returns the graph, for chaining. */
|
|
34
35
|
addEdge(from: string, to: string): this;
|
|
35
36
|
/**
|
|
@@ -55,11 +56,33 @@ export declare class CompiledGraph<S extends ChannelSchema, I extends keyof S =
|
|
|
55
56
|
private readonly store;
|
|
56
57
|
/** Loaded the first time a node that declares `cache` runs, and not before. */
|
|
57
58
|
private nodeCache;
|
|
59
|
+
/** The checkpoint writers of runs in progress, so `flush()` can wait for them. */
|
|
60
|
+
private readonly writers;
|
|
58
61
|
constructor(channels: S, nodes: Map<string, GraphNodeDefinition<S>>, edges: Array<Edge<S>>, options: CompileOptions, scope?: GraphScope);
|
|
62
|
+
/**
|
|
63
|
+
* Waits until every checkpoint written by runs in progress is in the store. Only `async` and
|
|
64
|
+
* `exit` durability leave any outstanding; a run always waits for its own before it returns.
|
|
65
|
+
*/
|
|
66
|
+
flush(): Promise<void>;
|
|
59
67
|
/** Runs to completion, to an interrupt, or to the step limit. */
|
|
60
68
|
invoke(input?: GraphInput<S, I>, runOptions?: GraphRunOptions): Promise<GraphResult<S, O>>;
|
|
61
69
|
/** Yields one event per superstep, so a caller can render progress as it happens. */
|
|
62
70
|
stream(input?: GraphInput<S, I>, runOptions?: GraphRunOptions): AsyncIterable<GraphStepEvent<S>>;
|
|
71
|
+
/**
|
|
72
|
+
* Runs the graph as one stream of typed events: the state after each superstep, each task's write,
|
|
73
|
+
* model output as nodes stream it, tool calls, task progress, checkpoints, and custom events.
|
|
74
|
+
*
|
|
75
|
+
* Iterate it for everything included, or read one projection with `messages()`, `tools()`,
|
|
76
|
+
* `values()`, or `updates()`. Each reader has its own bounded buffer, and the run waits for the
|
|
77
|
+
* slowest at the end of every superstep, so a slow reader slows the graph rather than filling
|
|
78
|
+
* memory. `result` resolves with the run's result.
|
|
79
|
+
*/
|
|
80
|
+
events(input?: GraphInput<S, I>, options?: GraphEventsOptions): GraphEventStream<S, O>;
|
|
81
|
+
/** Like `events()`, answering the question a paused thread is waiting on. */
|
|
82
|
+
resumeEvents(threadId: string, value: unknown, options?: GraphEventsOptions): GraphEventStream<S, O>;
|
|
83
|
+
/** Like `events()`, carrying a thread on from a breakpoint, a drain, or a failure. */
|
|
84
|
+
continueEvents(threadId: string, options?: GraphEventsOptions): GraphEventStream<S, O>;
|
|
85
|
+
private eventStream;
|
|
63
86
|
/**
|
|
64
87
|
* Supplies the value a node asked for and continues.
|
|
65
88
|
*
|
|
@@ -88,10 +111,17 @@ export declare class CompiledGraph<S extends ChannelSchema, I extends keyof S =
|
|
|
88
111
|
* once the rewound checkpoint is written.
|
|
89
112
|
*/
|
|
90
113
|
resumeFrom(threadId: string, step: number, runOptions?: GraphRunOptions): AsyncIterable<GraphStepEvent<S>>;
|
|
91
|
-
/**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Latest checkpoint, or the one at `step`. With a `tenantId`, a thread another tenant owns reads
|
|
116
|
+
* as absent.
|
|
117
|
+
*/
|
|
118
|
+
state(threadId: string, step?: number, options?: {
|
|
119
|
+
tenantId?: string;
|
|
120
|
+
}): Promise<GraphCheckpoint<S> | undefined>;
|
|
121
|
+
/** Checkpoints for a thread, newest first. With a `tenantId`, another tenant's thread has none. */
|
|
122
|
+
history(threadId: string, limit?: number, options?: {
|
|
123
|
+
tenantId?: string;
|
|
124
|
+
}): Promise<Array<GraphCheckpoint<S>>>;
|
|
95
125
|
/**
|
|
96
126
|
* Wraps this graph as a node in another graph.
|
|
97
127
|
*
|
|
@@ -120,26 +150,44 @@ export declare class CompiledGraph<S extends ChannelSchema, I extends keyof S =
|
|
|
120
150
|
*/
|
|
121
151
|
updateState(threadId: string, update: StateUpdate<S>, options?: {
|
|
122
152
|
asNode?: string;
|
|
153
|
+
tenantId?: string;
|
|
123
154
|
}): Promise<GraphCheckpoint<S>>;
|
|
124
155
|
/**
|
|
125
156
|
* Copies a thread's history up to `step` into a new thread, and returns the new thread's id.
|
|
126
157
|
*
|
|
127
158
|
* Rewinding with `resumeFrom()` replaces the original timeline. A fork keeps it: both threads stay
|
|
128
159
|
* readable and runnable, so two answers to the same question can be compared side by side. Every
|
|
129
|
-
* copied checkpoint records `metadata.forkedFrom
|
|
160
|
+
* copied checkpoint records `metadata.forkedFrom`, and keeps the tenant of the thread it came from.
|
|
161
|
+
* With a `tenantId`, another tenant's thread is not found.
|
|
130
162
|
*/
|
|
131
163
|
fork(threadId: string, options?: {
|
|
132
164
|
step?: number;
|
|
133
165
|
threadId?: string;
|
|
166
|
+
tenantId?: string;
|
|
134
167
|
}): Promise<string>;
|
|
135
168
|
/**
|
|
136
169
|
* Runs the supersteps, as one operation of the compiled lifecycle when there is one. The run is
|
|
137
170
|
* admitted before its first superstep and finishes with its last, however it ends.
|
|
138
171
|
*/
|
|
139
172
|
private run;
|
|
173
|
+
/**
|
|
174
|
+
* Runs the step loop with a checkpoint writer for the run's durability mode. However the run ends,
|
|
175
|
+
* every checkpoint it handed over is in the store before this returns or throws.
|
|
176
|
+
*/
|
|
140
177
|
private runSteps;
|
|
178
|
+
private steps;
|
|
141
179
|
/** Runs one task to a verdict, applying its retry policy and timeout. */
|
|
142
180
|
private runTask;
|
|
181
|
+
/**
|
|
182
|
+
* Hands a failure to the node's `onError`, and turns what it decides into the task's result. With
|
|
183
|
+
* no handler, or for a mistake in the graph itself, the task fails as it always did.
|
|
184
|
+
*/
|
|
185
|
+
private recover;
|
|
186
|
+
/** The node's retry policy over the graph's defaults. */
|
|
187
|
+
private retryPolicy;
|
|
188
|
+
/** The node's run and idle limits over the graph's defaults. `timeout.runMs` wins over `timeoutMs`. */
|
|
189
|
+
private timeoutOf;
|
|
190
|
+
private errorHandler;
|
|
143
191
|
private runNode;
|
|
144
192
|
private loadNodeCache;
|
|
145
193
|
/** Rejects writes to channels the graph does not accept from a caller. */
|