@oni.bot/core 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +308 -0
- package/dist/agents/context.d.ts +24 -0
- package/dist/agents/context.d.ts.map +1 -0
- package/dist/agents/context.js +93 -0
- package/dist/agents/context.js.map +1 -0
- package/dist/agents/define-agent.d.ts +10 -0
- package/dist/agents/define-agent.d.ts.map +1 -0
- package/dist/agents/define-agent.js +121 -0
- package/dist/agents/define-agent.js.map +1 -0
- package/dist/agents/functional-agent.d.ts +12 -0
- package/dist/agents/functional-agent.d.ts.map +1 -0
- package/dist/agents/functional-agent.js +115 -0
- package/dist/agents/functional-agent.js.map +1 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +7 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/types.d.ts +62 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +8 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/checkpoint.d.ts +27 -0
- package/dist/checkpoint.d.ts.map +1 -0
- package/dist/checkpoint.js +91 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/checkpointers/index.d.ts +4 -0
- package/dist/checkpointers/index.d.ts.map +1 -0
- package/dist/checkpointers/index.js +5 -0
- package/dist/checkpointers/index.js.map +1 -0
- package/dist/checkpointers/namespaced.d.ts +12 -0
- package/dist/checkpointers/namespaced.d.ts.map +1 -0
- package/dist/checkpointers/namespaced.js +37 -0
- package/dist/checkpointers/namespaced.js.map +1 -0
- package/dist/checkpointers/postgres.d.ts +13 -0
- package/dist/checkpointers/postgres.d.ts.map +1 -0
- package/dist/checkpointers/postgres.js +100 -0
- package/dist/checkpointers/postgres.js.map +1 -0
- package/dist/checkpointers/sqlite.d.ts +14 -0
- package/dist/checkpointers/sqlite.d.ts.map +1 -0
- package/dist/checkpointers/sqlite.js +98 -0
- package/dist/checkpointers/sqlite.js.map +1 -0
- package/dist/context.d.ts +24 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +47 -0
- package/dist/context.js.map +1 -0
- package/dist/coordination/index.d.ts +3 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +3 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/pubsub.d.ts +38 -0
- package/dist/coordination/pubsub.d.ts.map +1 -0
- package/dist/coordination/pubsub.js +73 -0
- package/dist/coordination/pubsub.js.map +1 -0
- package/dist/coordination/request-reply.d.ts +40 -0
- package/dist/coordination/request-reply.d.ts.map +1 -0
- package/dist/coordination/request-reply.js +77 -0
- package/dist/coordination/request-reply.js.map +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/events/bus.d.ts +13 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +52 -0
- package/dist/events/bus.js.map +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +87 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +2 -0
- package/dist/events/types.js.map +1 -0
- package/dist/functional.d.ts +36 -0
- package/dist/functional.d.ts.map +1 -0
- package/dist/functional.js +103 -0
- package/dist/functional.js.map +1 -0
- package/dist/graph.d.ts +74 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +119 -0
- package/dist/graph.js.map +1 -0
- package/dist/guardrails/audit.d.ts +13 -0
- package/dist/guardrails/audit.d.ts.map +1 -0
- package/dist/guardrails/audit.js +31 -0
- package/dist/guardrails/audit.js.map +1 -0
- package/dist/guardrails/budget.d.ts +30 -0
- package/dist/guardrails/budget.d.ts.map +1 -0
- package/dist/guardrails/budget.js +154 -0
- package/dist/guardrails/budget.js.map +1 -0
- package/dist/guardrails/filters.d.ts +24 -0
- package/dist/guardrails/filters.d.ts.map +1 -0
- package/dist/guardrails/filters.js +87 -0
- package/dist/guardrails/filters.js.map +1 -0
- package/dist/guardrails/index.d.ts +8 -0
- package/dist/guardrails/index.d.ts.map +1 -0
- package/dist/guardrails/index.js +9 -0
- package/dist/guardrails/index.js.map +1 -0
- package/dist/guardrails/permissions.d.ts +9 -0
- package/dist/guardrails/permissions.d.ts.map +1 -0
- package/dist/guardrails/permissions.js +29 -0
- package/dist/guardrails/permissions.js.map +1 -0
- package/dist/guardrails/types.d.ts +30 -0
- package/dist/guardrails/types.d.ts.map +1 -0
- package/dist/guardrails/types.js +2 -0
- package/dist/guardrails/types.js.map +1 -0
- package/dist/hitl/index.d.ts +5 -0
- package/dist/hitl/index.d.ts.map +1 -0
- package/dist/hitl/index.js +3 -0
- package/dist/hitl/index.js.map +1 -0
- package/dist/hitl/interrupt.d.ts +81 -0
- package/dist/hitl/interrupt.d.ts.map +1 -0
- package/dist/hitl/interrupt.js +116 -0
- package/dist/hitl/interrupt.js.map +1 -0
- package/dist/hitl/resume.d.ts +33 -0
- package/dist/hitl/resume.d.ts.map +1 -0
- package/dist/hitl/resume.js +72 -0
- package/dist/hitl/resume.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/injected.d.ts +26 -0
- package/dist/injected.d.ts.map +1 -0
- package/dist/injected.js +25 -0
- package/dist/injected.js.map +1 -0
- package/dist/inspect.d.ts +31 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +139 -0
- package/dist/inspect.js.map +1 -0
- package/dist/messages/index.d.ts +66 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +123 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/models/anthropic.d.ts +6 -0
- package/dist/models/anthropic.d.ts.map +1 -0
- package/dist/models/anthropic.js +317 -0
- package/dist/models/anthropic.js.map +1 -0
- package/dist/models/google.d.ts +3 -0
- package/dist/models/google.d.ts.map +1 -0
- package/dist/models/google.js +310 -0
- package/dist/models/google.js.map +1 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +5 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/ollama.d.ts +7 -0
- package/dist/models/ollama.d.ts.map +1 -0
- package/dist/models/ollama.js +205 -0
- package/dist/models/ollama.js.map +1 -0
- package/dist/models/openai.d.ts +3 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +331 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/types.d.ts +77 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +2 -0
- package/dist/models/types.js.map +1 -0
- package/dist/prebuilt/index.d.ts +5 -0
- package/dist/prebuilt/index.d.ts.map +1 -0
- package/dist/prebuilt/index.js +4 -0
- package/dist/prebuilt/index.js.map +1 -0
- package/dist/prebuilt/react-agent.d.ts +35 -0
- package/dist/prebuilt/react-agent.d.ts.map +1 -0
- package/dist/prebuilt/react-agent.js +55 -0
- package/dist/prebuilt/react-agent.js.map +1 -0
- package/dist/prebuilt/tool-node.d.ts +15 -0
- package/dist/prebuilt/tool-node.d.ts.map +1 -0
- package/dist/prebuilt/tool-node.js +61 -0
- package/dist/prebuilt/tool-node.js.map +1 -0
- package/dist/pregel.d.ts +48 -0
- package/dist/pregel.d.ts.map +1 -0
- package/dist/pregel.js +583 -0
- package/dist/pregel.js.map +1 -0
- package/dist/retry.d.ts +3 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +40 -0
- package/dist/retry.js.map +1 -0
- package/dist/store/index.d.ts +90 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +214 -0
- package/dist/store/index.js.map +1 -0
- package/dist/stream-events.d.ts +15 -0
- package/dist/stream-events.d.ts.map +1 -0
- package/dist/stream-events.js +53 -0
- package/dist/stream-events.js.map +1 -0
- package/dist/streaming.d.ts +56 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +143 -0
- package/dist/streaming.js.map +1 -0
- package/dist/swarm/graph.d.ts +184 -0
- package/dist/swarm/graph.d.ts.map +1 -0
- package/dist/swarm/graph.js +534 -0
- package/dist/swarm/graph.js.map +1 -0
- package/dist/swarm/index.d.ts +11 -0
- package/dist/swarm/index.d.ts.map +1 -0
- package/dist/swarm/index.js +10 -0
- package/dist/swarm/index.js.map +1 -0
- package/dist/swarm/mailbox.d.ts +12 -0
- package/dist/swarm/mailbox.d.ts.map +1 -0
- package/dist/swarm/mailbox.js +36 -0
- package/dist/swarm/mailbox.js.map +1 -0
- package/dist/swarm/pool.d.ts +27 -0
- package/dist/swarm/pool.d.ts.map +1 -0
- package/dist/swarm/pool.js +87 -0
- package/dist/swarm/pool.js.map +1 -0
- package/dist/swarm/registry.d.ts +37 -0
- package/dist/swarm/registry.d.ts.map +1 -0
- package/dist/swarm/registry.js +115 -0
- package/dist/swarm/registry.js.map +1 -0
- package/dist/swarm/supervisor.d.ts +18 -0
- package/dist/swarm/supervisor.d.ts.map +1 -0
- package/dist/swarm/supervisor.js +117 -0
- package/dist/swarm/supervisor.js.map +1 -0
- package/dist/swarm/types.d.ts +111 -0
- package/dist/swarm/types.d.ts.map +1 -0
- package/dist/swarm/types.js +16 -0
- package/dist/swarm/types.js.map +1 -0
- package/dist/tools/define.d.ts +14 -0
- package/dist/tools/define.d.ts.map +1 -0
- package/dist/tools/define.js +39 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/types.d.ts +23 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/package.json +108 -0
package/dist/pregel.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type NodeDefinition, type Edge, type ChannelSchema, type ONIConfig, type ONIStreamEvent, type StreamMode, type InterruptConfig, type ONICheckpointer, type ONICheckpoint } from "./types.js";
|
|
2
|
+
import type { BaseStore } from "./store/index.js";
|
|
3
|
+
import { HITLSessionStore } from "./hitl/index.js";
|
|
4
|
+
import { EventBus } from "./events/bus.js";
|
|
5
|
+
import type { GuardrailsConfig } from "./guardrails/types.js";
|
|
6
|
+
import type { EventListeners } from "./events/types.js";
|
|
7
|
+
import { AuditLog } from "./guardrails/audit.js";
|
|
8
|
+
import { BudgetTracker } from "./guardrails/budget.js";
|
|
9
|
+
export declare class ONIPregelRunner<S extends Record<string, unknown>> {
|
|
10
|
+
private readonly nodes;
|
|
11
|
+
private readonly edges;
|
|
12
|
+
private readonly channels;
|
|
13
|
+
private readonly interruptConfig;
|
|
14
|
+
private readonly checkpointer;
|
|
15
|
+
private readonly store;
|
|
16
|
+
private hitlStore;
|
|
17
|
+
private nodeCache;
|
|
18
|
+
/** Set to true when this runner is being invoked as a subgraph */
|
|
19
|
+
private _isSubgraph;
|
|
20
|
+
/** Accumulated parent updates from Command.PARENT during subgraph execution */
|
|
21
|
+
_parentUpdates: Array<Partial<unknown>>;
|
|
22
|
+
readonly eventBus: EventBus;
|
|
23
|
+
readonly auditLog: AuditLog | null;
|
|
24
|
+
readonly budgetTracker: BudgetTracker | null;
|
|
25
|
+
constructor(nodes: Map<string, NodeDefinition<S>>, edges: Edge<S>[], channels: ChannelSchema<S>, interruptConfig?: InterruptConfig, checkpointer?: ONICheckpointer<S> | null, store?: BaseStore | null, guardrails?: GuardrailsConfig, listeners?: EventListeners);
|
|
26
|
+
private buildInitialState;
|
|
27
|
+
private applyUpdate;
|
|
28
|
+
private resetEphemeral;
|
|
29
|
+
private getNextNodes;
|
|
30
|
+
private executeNode;
|
|
31
|
+
private checkDynamicInterrupt;
|
|
32
|
+
_stream(input: Partial<S>, config?: ONIConfig, streamMode?: StreamMode | StreamMode[]): AsyncGenerator<ONIStreamEvent<S>>;
|
|
33
|
+
invoke(input: Partial<S>, config?: ONIConfig): Promise<S>;
|
|
34
|
+
stream(input: Partial<S>, config?: ONIConfig & {
|
|
35
|
+
streamMode?: StreamMode | StreamMode[];
|
|
36
|
+
}): AsyncGenerator<ONIStreamEvent<S>>;
|
|
37
|
+
batch(inputs: Partial<S>[], config?: ONIConfig): Promise<S[]>;
|
|
38
|
+
getState(threadId: string): Promise<S | null>;
|
|
39
|
+
updateState(threadId: string, update: Partial<S>): Promise<void>;
|
|
40
|
+
getStateAt(threadId: string, step: number): Promise<S | null>;
|
|
41
|
+
getHistory(threadId: string): Promise<ONICheckpoint<S>[]>;
|
|
42
|
+
forkFrom(threadId: string, step: number, newThreadId: string): Promise<void>;
|
|
43
|
+
getPendingInterrupts(threadId: string): import("./hitl/resume.js").HITLSession<S>[];
|
|
44
|
+
hitlSessionStore(): HITLSessionStore<S>;
|
|
45
|
+
private saveCheckpoint;
|
|
46
|
+
private evt;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=pregel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pregel.d.ts","sourceRoot":"","sources":["../src/pregel.ts"],"names":[],"mappings":"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"}
|
package/dist/pregel.js
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @oni.bot/core — Pregel Execution Engine v3
|
|
3
|
+
// New: interrupt() context management, HITL resume, token streaming
|
|
4
|
+
// ============================================================
|
|
5
|
+
import { START, END, Send, Command, } from "./types.js";
|
|
6
|
+
import { RecursionLimitError, NodeNotFoundError, ONIInterrupt } from "./errors.js";
|
|
7
|
+
import { withRetry } from "./retry.js";
|
|
8
|
+
import { NamespacedCheckpointer } from "./checkpointers/namespaced.js";
|
|
9
|
+
import { _runWithContext } from "./context.js";
|
|
10
|
+
import { StreamWriterImpl } from "./streaming.js";
|
|
11
|
+
import { NodeInterruptSignal, HITLInterruptException, HITLSessionStore, _installInterruptContext, _clearInterruptContext, } from "./hitl/index.js";
|
|
12
|
+
import { EventBus } from "./events/bus.js";
|
|
13
|
+
import { AuditLog } from "./guardrails/audit.js";
|
|
14
|
+
import { BudgetTracker } from "./guardrails/budget.js";
|
|
15
|
+
const DEFAULT_RECURSION_LIMIT = 25;
|
|
16
|
+
export class ONIPregelRunner {
|
|
17
|
+
nodes;
|
|
18
|
+
edges;
|
|
19
|
+
channels;
|
|
20
|
+
interruptConfig;
|
|
21
|
+
checkpointer;
|
|
22
|
+
store;
|
|
23
|
+
hitlStore = new HITLSessionStore();
|
|
24
|
+
nodeCache = new Map();
|
|
25
|
+
/** Set to true when this runner is being invoked as a subgraph */
|
|
26
|
+
_isSubgraph = false;
|
|
27
|
+
/** Accumulated parent updates from Command.PARENT during subgraph execution */
|
|
28
|
+
_parentUpdates = [];
|
|
29
|
+
eventBus;
|
|
30
|
+
auditLog;
|
|
31
|
+
budgetTracker;
|
|
32
|
+
constructor(nodes, edges, channels, interruptConfig = {}, checkpointer = null, store = null, guardrails, listeners) {
|
|
33
|
+
this.nodes = nodes;
|
|
34
|
+
this.edges = edges;
|
|
35
|
+
this.channels = channels;
|
|
36
|
+
this.interruptConfig = interruptConfig;
|
|
37
|
+
this.checkpointer = checkpointer;
|
|
38
|
+
this.store = store;
|
|
39
|
+
this.eventBus = new EventBus(listeners);
|
|
40
|
+
this.auditLog = guardrails?.audit ? new AuditLog() : null;
|
|
41
|
+
this.budgetTracker = guardrails?.budget ? new BudgetTracker(guardrails.budget) : null;
|
|
42
|
+
}
|
|
43
|
+
// ----------------------------------------------------------------
|
|
44
|
+
// State helpers
|
|
45
|
+
// ----------------------------------------------------------------
|
|
46
|
+
buildInitialState() {
|
|
47
|
+
const state = {};
|
|
48
|
+
for (const key of Object.keys(this.channels)) {
|
|
49
|
+
state[key] = this.channels[key].default();
|
|
50
|
+
}
|
|
51
|
+
return state;
|
|
52
|
+
}
|
|
53
|
+
applyUpdate(current, update) {
|
|
54
|
+
const next = { ...current };
|
|
55
|
+
for (const key of Object.keys(update)) {
|
|
56
|
+
if (update[key] !== undefined) {
|
|
57
|
+
const ch = this.channels[key];
|
|
58
|
+
next[key] = ch
|
|
59
|
+
? ch.reducer(current[key], update[key])
|
|
60
|
+
: update[key];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return next;
|
|
64
|
+
}
|
|
65
|
+
resetEphemeral(state) {
|
|
66
|
+
const next = { ...state };
|
|
67
|
+
for (const key of Object.keys(this.channels)) {
|
|
68
|
+
if (this.channels[key].ephemeral)
|
|
69
|
+
next[key] = this.channels[key].default();
|
|
70
|
+
}
|
|
71
|
+
return next;
|
|
72
|
+
}
|
|
73
|
+
// ----------------------------------------------------------------
|
|
74
|
+
// Edge resolution
|
|
75
|
+
// ----------------------------------------------------------------
|
|
76
|
+
getNextNodes(fromNode, state, config) {
|
|
77
|
+
const outgoing = this.edges.filter((e) => e.from === fromNode);
|
|
78
|
+
const nodes = [];
|
|
79
|
+
const sends = [];
|
|
80
|
+
for (const edge of outgoing) {
|
|
81
|
+
if (edge.type === "static") {
|
|
82
|
+
nodes.push(edge.to);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const result = edge.condition(state, config);
|
|
86
|
+
const resolved = Array.isArray(result) ? result : [result];
|
|
87
|
+
for (const r of resolved) {
|
|
88
|
+
if (r instanceof Send)
|
|
89
|
+
sends.push({ node: r.node, args: r.args });
|
|
90
|
+
else
|
|
91
|
+
nodes.push(edge.pathMap?.[r] ?? r);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { nodes, sends };
|
|
96
|
+
}
|
|
97
|
+
// ----------------------------------------------------------------
|
|
98
|
+
// Execute a node with interrupt() context installed
|
|
99
|
+
// ----------------------------------------------------------------
|
|
100
|
+
async executeNode(nodeDef, state, config, resumeValue, hasResume, writer, step, recursionLimit) {
|
|
101
|
+
// Check cache
|
|
102
|
+
if (nodeDef.cache) {
|
|
103
|
+
const policy = typeof nodeDef.cache === "object" ? nodeDef.cache : {};
|
|
104
|
+
const keyFn = policy.key ?? ((s) => JSON.stringify(s));
|
|
105
|
+
const cacheKey = `${nodeDef.name}::${keyFn(state)}`;
|
|
106
|
+
const cached = this.nodeCache.get(cacheKey);
|
|
107
|
+
if (cached) {
|
|
108
|
+
const ttl = policy.ttl ?? Infinity;
|
|
109
|
+
if (Date.now() - cached.timestamp < ttl) {
|
|
110
|
+
return cached.result;
|
|
111
|
+
}
|
|
112
|
+
this.nodeCache.delete(cacheKey);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const ctx = {
|
|
116
|
+
config: config ?? {},
|
|
117
|
+
store: this.store,
|
|
118
|
+
writer: writer ?? null,
|
|
119
|
+
state: state,
|
|
120
|
+
parentGraph: null,
|
|
121
|
+
parentUpdates: [],
|
|
122
|
+
step: step ?? 0,
|
|
123
|
+
recursionLimit: recursionLimit ?? DEFAULT_RECURSION_LIMIT,
|
|
124
|
+
};
|
|
125
|
+
return _runWithContext(ctx, async () => {
|
|
126
|
+
_installInterruptContext({
|
|
127
|
+
nodeName: nodeDef.name,
|
|
128
|
+
resumeValue: resumeValue,
|
|
129
|
+
hasResume: hasResume ?? false,
|
|
130
|
+
});
|
|
131
|
+
try {
|
|
132
|
+
const run = () => Promise.resolve(nodeDef.fn(state, config));
|
|
133
|
+
let result;
|
|
134
|
+
if (nodeDef.retry)
|
|
135
|
+
result = await withRetry(run, nodeDef.name, nodeDef.retry);
|
|
136
|
+
else
|
|
137
|
+
result = await run();
|
|
138
|
+
// Store in cache
|
|
139
|
+
if (nodeDef.cache) {
|
|
140
|
+
const policy = typeof nodeDef.cache === "object" ? nodeDef.cache : {};
|
|
141
|
+
const keyFn = policy.key ?? ((s) => JSON.stringify(s));
|
|
142
|
+
const cacheKey = `${nodeDef.name}::${keyFn(state)}`;
|
|
143
|
+
this.nodeCache.set(cacheKey, { result, timestamp: Date.now() });
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
_clearInterruptContext();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// ----------------------------------------------------------------
|
|
153
|
+
// Dynamic interrupt check
|
|
154
|
+
// ----------------------------------------------------------------
|
|
155
|
+
checkDynamicInterrupt(node, timing, state, config) {
|
|
156
|
+
const dynamics = config?.dynamicInterrupts;
|
|
157
|
+
if (!dynamics)
|
|
158
|
+
return;
|
|
159
|
+
for (const di of dynamics) {
|
|
160
|
+
if (di.node === node && di.timing === timing && di.condition(state)) {
|
|
161
|
+
throw new ONIInterrupt(node, timing, state);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// ----------------------------------------------------------------
|
|
166
|
+
// Core stream generator
|
|
167
|
+
// ----------------------------------------------------------------
|
|
168
|
+
async *_stream(input, config, streamMode = "updates") {
|
|
169
|
+
const threadId = config?.threadId ?? `oni-${Date.now()}`;
|
|
170
|
+
const recursionLimit = config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT;
|
|
171
|
+
const agentId = config?.agentId;
|
|
172
|
+
const modes = new Set(Array.isArray(streamMode) ? streamMode : [streamMode]);
|
|
173
|
+
const isMultiMode = Array.isArray(streamMode);
|
|
174
|
+
const tag = (evt, mode) => isMultiMode ? { ...evt, mode } : evt;
|
|
175
|
+
// Load resume values from config (set by resume() call)
|
|
176
|
+
const resumeMap = config?.__resumeValues ?? {};
|
|
177
|
+
// Load or init state
|
|
178
|
+
let state;
|
|
179
|
+
let step = 0;
|
|
180
|
+
let pendingNodes = [];
|
|
181
|
+
let pendingSends = [];
|
|
182
|
+
if (this.checkpointer && config?.threadId) {
|
|
183
|
+
const cp = await this.checkpointer.get(threadId);
|
|
184
|
+
if (cp) {
|
|
185
|
+
state = this.applyUpdate(cp.state, input);
|
|
186
|
+
step = cp.step;
|
|
187
|
+
pendingNodes = cp.nextNodes;
|
|
188
|
+
pendingSends = cp.pendingSends ?? [];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
state = this.applyUpdate(this.buildInitialState(), input);
|
|
192
|
+
const init = this.getNextNodes(START, state, config);
|
|
193
|
+
pendingNodes = init.nodes;
|
|
194
|
+
pendingSends = init.sends;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
state = this.applyUpdate(this.buildInitialState(), input);
|
|
199
|
+
const init = this.getNextNodes(START, state, config);
|
|
200
|
+
pendingNodes = init.nodes;
|
|
201
|
+
pendingSends = init.sends;
|
|
202
|
+
}
|
|
203
|
+
if (modes.has("values"))
|
|
204
|
+
yield tag(this.evt("state_update", state, step, agentId), "values");
|
|
205
|
+
// ---- Main superstep loop ----
|
|
206
|
+
while (true) {
|
|
207
|
+
const nextNodes = [];
|
|
208
|
+
const nextSends = [];
|
|
209
|
+
// Drain sends — group by target node for parallel fan-out execution
|
|
210
|
+
const sendGroups = new Map();
|
|
211
|
+
for (const send of pendingSends) {
|
|
212
|
+
if (!sendGroups.has(send.node))
|
|
213
|
+
sendGroups.set(send.node, []);
|
|
214
|
+
sendGroups.get(send.node).push(send);
|
|
215
|
+
if (modes.has("debug"))
|
|
216
|
+
yield tag(this.evt("send", send, step, agentId, send.node), "debug");
|
|
217
|
+
}
|
|
218
|
+
// Execute fan-out sends (each Send → separate node execution with its own state)
|
|
219
|
+
if (sendGroups.size > 0) {
|
|
220
|
+
const sendResults = await Promise.all([...sendGroups.entries()].flatMap(([node, sends]) => sends.map(async (send) => {
|
|
221
|
+
const nodeDef = this.nodes.get(node);
|
|
222
|
+
if (!nodeDef)
|
|
223
|
+
throw new NodeNotFoundError(node);
|
|
224
|
+
const sendState = this.applyUpdate(state, send.args);
|
|
225
|
+
const result = await this.executeNode(nodeDef, sendState, config, undefined, undefined, undefined, step, recursionLimit);
|
|
226
|
+
return { name: node, result };
|
|
227
|
+
})));
|
|
228
|
+
// Reduce all send results through channels
|
|
229
|
+
for (const { name, result } of sendResults) {
|
|
230
|
+
if (result instanceof Command) {
|
|
231
|
+
if (result.update)
|
|
232
|
+
state = this.applyUpdate(state, result.update);
|
|
233
|
+
const gotos = result.goto
|
|
234
|
+
? (Array.isArray(result.goto) ? result.goto : [result.goto])
|
|
235
|
+
: this.getNextNodes(name, state, config).nodes;
|
|
236
|
+
nextNodes.push(...gotos);
|
|
237
|
+
}
|
|
238
|
+
else if (result && typeof result === "object") {
|
|
239
|
+
state = this.applyUpdate(state, result);
|
|
240
|
+
const { nodes, sends } = this.getNextNodes(name, state, config);
|
|
241
|
+
nextNodes.push(...nodes);
|
|
242
|
+
nextSends.push(...sends);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
const { nodes, sends } = this.getNextNodes(name, state, config);
|
|
246
|
+
nextNodes.push(...nodes);
|
|
247
|
+
nextSends.push(...sends);
|
|
248
|
+
}
|
|
249
|
+
if (modes.has("updates") || modes.has("debug")) {
|
|
250
|
+
const delta = result instanceof Command ? (result.update ?? {}) : (result ?? {});
|
|
251
|
+
if (modes.has("updates"))
|
|
252
|
+
yield tag(this.evt("node_end", delta, step, agentId, name), "updates");
|
|
253
|
+
if (modes.has("debug"))
|
|
254
|
+
yield tag(this.evt("node_end", delta, step, agentId, name), "debug");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
pendingSends = [];
|
|
259
|
+
// Filter executable nodes (non-END), excluding nodes already handled by sends
|
|
260
|
+
const executableNodes = pendingNodes.filter((n) => n !== END && !sendGroups.has(n));
|
|
261
|
+
if (executableNodes.length === 0 && sendGroups.size === 0)
|
|
262
|
+
break;
|
|
263
|
+
if (step >= recursionLimit)
|
|
264
|
+
throw new RecursionLimitError(recursionLimit);
|
|
265
|
+
state = this.resetEphemeral(state);
|
|
266
|
+
// Emit debug node_start events before parallel execution
|
|
267
|
+
if (modes.has("debug")) {
|
|
268
|
+
for (const nodeName of executableNodes) {
|
|
269
|
+
const name = nodeName;
|
|
270
|
+
if (!this.nodes.has(name))
|
|
271
|
+
throw new NodeNotFoundError(name);
|
|
272
|
+
// Static interrupt BEFORE (check before emitting start)
|
|
273
|
+
if (this.interruptConfig.interruptBefore?.includes(name))
|
|
274
|
+
throw new ONIInterrupt(name, "before", state);
|
|
275
|
+
this.checkDynamicInterrupt(name, "before", state, config);
|
|
276
|
+
yield tag(this.evt("node_start", {}, step, agentId, name), "debug");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Execute all active nodes in parallel
|
|
280
|
+
const allCustomEvents = [];
|
|
281
|
+
const allMessageEvents = [];
|
|
282
|
+
const allSubgraphEvents = [];
|
|
283
|
+
const nodeWriters = new Map();
|
|
284
|
+
const nodeResults = await Promise.all(executableNodes.map(async (nodeName) => {
|
|
285
|
+
const name = nodeName;
|
|
286
|
+
const nodeDef = this.nodes.get(name);
|
|
287
|
+
if (!nodeDef)
|
|
288
|
+
throw new NodeNotFoundError(name);
|
|
289
|
+
// Static interrupt BEFORE (non-debug mode)
|
|
290
|
+
if (!modes.has("debug")) {
|
|
291
|
+
if (this.interruptConfig.interruptBefore?.includes(name))
|
|
292
|
+
throw new ONIInterrupt(name, "before", state);
|
|
293
|
+
this.checkDynamicInterrupt(name, "before", state, config);
|
|
294
|
+
}
|
|
295
|
+
// Create a StreamWriter for this node
|
|
296
|
+
const messageId = `msg-${threadId}-${step}-${name}`;
|
|
297
|
+
const customEvents = [];
|
|
298
|
+
const messageEvents = [];
|
|
299
|
+
const writerImpl = new StreamWriterImpl((evt) => customEvents.push(evt), (token) => { }, (evt) => messageEvents.push(evt), name, step, messageId, agentId);
|
|
300
|
+
nodeWriters.set(name, writerImpl);
|
|
301
|
+
// Check if this node has a pending resume value
|
|
302
|
+
const resumeValue = resumeMap[name];
|
|
303
|
+
const hasResume = name in resumeMap;
|
|
304
|
+
// Emit agent.start lifecycle event
|
|
305
|
+
const nodeStartTime = Date.now();
|
|
306
|
+
this.eventBus.emit({ type: "agent.start", agent: name, timestamp: nodeStartTime, step });
|
|
307
|
+
let result;
|
|
308
|
+
let subParentUpdates = [];
|
|
309
|
+
try {
|
|
310
|
+
if (nodeDef.subgraph) {
|
|
311
|
+
// Mark child runner as a subgraph so Command.PARENT works
|
|
312
|
+
const childRunner = nodeDef.subgraph._runner;
|
|
313
|
+
if (childRunner) {
|
|
314
|
+
childRunner._isSubgraph = true;
|
|
315
|
+
childRunner._parentUpdates = [];
|
|
316
|
+
}
|
|
317
|
+
// Namespace the subgraph's checkpointer for isolation
|
|
318
|
+
if (this.checkpointer && childRunner) {
|
|
319
|
+
childRunner.checkpointer = new NamespacedCheckpointer(this.checkpointer, name);
|
|
320
|
+
}
|
|
321
|
+
// Stream the subgraph instead of invoke — buffer events for yielding after Promise.all
|
|
322
|
+
// Use debug+values so we capture ALL event types AND state_update for final state
|
|
323
|
+
let subFinalState;
|
|
324
|
+
const childStreamMode = ["debug", "values"];
|
|
325
|
+
for await (const evt of nodeDef.subgraph.stream(state, {
|
|
326
|
+
...config,
|
|
327
|
+
parentRunId: config?.threadId,
|
|
328
|
+
streamMode: childStreamMode,
|
|
329
|
+
})) {
|
|
330
|
+
// Namespace-prefix the node name
|
|
331
|
+
allSubgraphEvents.push({
|
|
332
|
+
...evt,
|
|
333
|
+
node: evt.node ? `${name}:${evt.node}` : name,
|
|
334
|
+
});
|
|
335
|
+
// Track the last state_update as the final subgraph state
|
|
336
|
+
if (evt.event === "state_update") {
|
|
337
|
+
subFinalState = evt.data;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Collect parent updates from child
|
|
341
|
+
if (childRunner) {
|
|
342
|
+
subParentUpdates = childRunner._parentUpdates;
|
|
343
|
+
childRunner._isSubgraph = false;
|
|
344
|
+
childRunner._parentUpdates = [];
|
|
345
|
+
}
|
|
346
|
+
result = subFinalState ?? {};
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
result = await this.executeNode(nodeDef, state, config, resumeValue, hasResume, writerImpl, step, recursionLimit);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
// Catch interrupt() signals thrown from inside nodes
|
|
354
|
+
if (err instanceof NodeInterruptSignal) {
|
|
355
|
+
const iv = {
|
|
356
|
+
value: err.value,
|
|
357
|
+
node: name,
|
|
358
|
+
resumeId: err.resumeId,
|
|
359
|
+
timestamp: Date.now(),
|
|
360
|
+
};
|
|
361
|
+
// Save checkpoint before surfacing interrupt
|
|
362
|
+
await this.saveCheckpoint(threadId, step, state, [name], pendingSends, agentId, config?.metadata);
|
|
363
|
+
// Record HITL session if checkpointer exists
|
|
364
|
+
if (this.checkpointer) {
|
|
365
|
+
const cp = await this.checkpointer.get(threadId);
|
|
366
|
+
if (cp)
|
|
367
|
+
this.hitlStore.record(threadId, iv, cp);
|
|
368
|
+
}
|
|
369
|
+
throw new HITLInterruptException(threadId, iv, state);
|
|
370
|
+
}
|
|
371
|
+
throw err;
|
|
372
|
+
}
|
|
373
|
+
// Emit agent.end lifecycle event
|
|
374
|
+
this.eventBus.emit({ type: "agent.end", agent: name, timestamp: Date.now(), step, duration: Date.now() - nodeStartTime });
|
|
375
|
+
// Collect events for yielding after parallel execution
|
|
376
|
+
allCustomEvents.push(...customEvents);
|
|
377
|
+
allMessageEvents.push(...messageEvents);
|
|
378
|
+
return { name, result, subParentUpdates };
|
|
379
|
+
}));
|
|
380
|
+
// Yield buffered subgraph events — filtered by parent's active modes
|
|
381
|
+
for (const evt of allSubgraphEvents) {
|
|
382
|
+
const e = evt;
|
|
383
|
+
if (modes.has("debug")) {
|
|
384
|
+
yield tag(e, "debug");
|
|
385
|
+
}
|
|
386
|
+
else if (modes.has("updates") && (e.event === "node_end")) {
|
|
387
|
+
yield tag(e, "updates");
|
|
388
|
+
}
|
|
389
|
+
else if (modes.has("values") && e.event === "state_update") {
|
|
390
|
+
yield tag(e, "values");
|
|
391
|
+
}
|
|
392
|
+
// Custom and message events from subgraphs are forwarded if those modes are active
|
|
393
|
+
if (modes.has("custom") && e.event === "custom") {
|
|
394
|
+
yield tag(e, "custom");
|
|
395
|
+
}
|
|
396
|
+
if (modes.has("messages") && (e.event === "messages" || e.event === "messages/complete")) {
|
|
397
|
+
yield tag(e, "messages");
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// Apply results
|
|
401
|
+
const stepWrites = [];
|
|
402
|
+
for (const { name, result, subParentUpdates: parentUpdates } of nodeResults) {
|
|
403
|
+
if (result instanceof Command) {
|
|
404
|
+
if (result.graph === Command.PARENT) {
|
|
405
|
+
// Push update to parent — do NOT apply locally
|
|
406
|
+
if (!this._isSubgraph) {
|
|
407
|
+
throw new Error("Command.PARENT used but graph is not running as a subgraph");
|
|
408
|
+
}
|
|
409
|
+
if (result.update)
|
|
410
|
+
this._parentUpdates.push(result.update);
|
|
411
|
+
// Still resolve next nodes normally
|
|
412
|
+
const { nodes, sends } = this.getNextNodes(name, state, config);
|
|
413
|
+
nextNodes.push(...nodes);
|
|
414
|
+
nextSends.push(...sends);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
if (result.update) {
|
|
418
|
+
state = this.applyUpdate(state, result.update);
|
|
419
|
+
if (Object.keys(result.update).length > 0) {
|
|
420
|
+
stepWrites.push({ nodeId: name, writes: result.update });
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const gotos = result.goto
|
|
424
|
+
? (Array.isArray(result.goto) ? result.goto : [result.goto])
|
|
425
|
+
: this.getNextNodes(name, state, config).nodes;
|
|
426
|
+
nextNodes.push(...gotos);
|
|
427
|
+
if (result.send)
|
|
428
|
+
nextSends.push(...result.send.map((s) => ({ node: s.node, args: s.args })));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
else if (result && typeof result === "object") {
|
|
432
|
+
state = this.applyUpdate(state, result);
|
|
433
|
+
const writes = result;
|
|
434
|
+
if (Object.keys(writes).length > 0) {
|
|
435
|
+
stepWrites.push({ nodeId: name, writes });
|
|
436
|
+
}
|
|
437
|
+
const { nodes, sends } = this.getNextNodes(name, state, config);
|
|
438
|
+
nextNodes.push(...nodes);
|
|
439
|
+
nextSends.push(...sends);
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
const { nodes, sends } = this.getNextNodes(name, state, config);
|
|
443
|
+
nextNodes.push(...nodes);
|
|
444
|
+
nextSends.push(...sends);
|
|
445
|
+
}
|
|
446
|
+
// Apply parent updates from subgraph Command.PARENT (after normal result)
|
|
447
|
+
for (const pu of parentUpdates) {
|
|
448
|
+
state = this.applyUpdate(state, pu);
|
|
449
|
+
}
|
|
450
|
+
if (modes.has("updates") || modes.has("debug")) {
|
|
451
|
+
const delta = result instanceof Command ? (result.update ?? {}) : (result ?? {});
|
|
452
|
+
if (modes.has("updates"))
|
|
453
|
+
yield tag(this.evt("node_end", delta, step, agentId, name), "updates");
|
|
454
|
+
if (modes.has("debug"))
|
|
455
|
+
yield tag(this.evt("node_end", delta, step, agentId, name), "debug");
|
|
456
|
+
}
|
|
457
|
+
// Static interrupt AFTER
|
|
458
|
+
if (this.interruptConfig.interruptAfter?.includes(name)) {
|
|
459
|
+
await this.saveCheckpoint(threadId, step, state, nextNodes, nextSends, agentId, config?.metadata);
|
|
460
|
+
throw new ONIInterrupt(name, "after", state);
|
|
461
|
+
}
|
|
462
|
+
this.checkDynamicInterrupt(name, "after", state, config);
|
|
463
|
+
}
|
|
464
|
+
// Yield buffered custom/message events based on stream mode
|
|
465
|
+
if (modes.has("custom") || modes.has("debug")) {
|
|
466
|
+
for (const evt of allCustomEvents) {
|
|
467
|
+
if (modes.has("custom"))
|
|
468
|
+
yield tag(evt, "custom");
|
|
469
|
+
if (modes.has("debug"))
|
|
470
|
+
yield tag(evt, "debug");
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (modes.has("messages") || modes.has("debug")) {
|
|
474
|
+
for (const evt of allMessageEvents) {
|
|
475
|
+
if (modes.has("messages"))
|
|
476
|
+
yield tag(evt, "messages");
|
|
477
|
+
if (modes.has("debug"))
|
|
478
|
+
yield tag(evt, "debug");
|
|
479
|
+
}
|
|
480
|
+
// Emit messages/complete for each node that produced tokens
|
|
481
|
+
for (const [, writer] of nodeWriters) {
|
|
482
|
+
const complete = writer._complete();
|
|
483
|
+
if (complete) {
|
|
484
|
+
if (modes.has("messages"))
|
|
485
|
+
yield tag(complete, "messages");
|
|
486
|
+
if (modes.has("debug"))
|
|
487
|
+
yield tag(complete, "debug");
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (modes.has("values"))
|
|
492
|
+
yield tag(this.evt("state_update", state, step, agentId), "values");
|
|
493
|
+
pendingNodes = [...new Set(nextNodes)];
|
|
494
|
+
pendingSends = nextSends;
|
|
495
|
+
step++;
|
|
496
|
+
await this.saveCheckpoint(threadId, step, state, pendingNodes, pendingSends, agentId, config?.metadata, stepWrites);
|
|
497
|
+
}
|
|
498
|
+
if (modes.has("values"))
|
|
499
|
+
yield tag(this.evt("state_update", state, step, agentId), "values");
|
|
500
|
+
}
|
|
501
|
+
// ----------------------------------------------------------------
|
|
502
|
+
// Public API
|
|
503
|
+
// ----------------------------------------------------------------
|
|
504
|
+
async invoke(input, config) {
|
|
505
|
+
let finalState;
|
|
506
|
+
for await (const evt of this._stream(input, config, "values")) {
|
|
507
|
+
if (evt.event === "state_update")
|
|
508
|
+
finalState = evt.data;
|
|
509
|
+
}
|
|
510
|
+
return finalState;
|
|
511
|
+
}
|
|
512
|
+
async *stream(input, config) {
|
|
513
|
+
yield* this._stream(input, config, config?.streamMode ?? "updates");
|
|
514
|
+
}
|
|
515
|
+
async batch(inputs, config) {
|
|
516
|
+
return Promise.all(inputs.map((inp, i) => this.invoke(inp, {
|
|
517
|
+
...config,
|
|
518
|
+
threadId: config?.threadId ? `${config.threadId}-${i}` : undefined,
|
|
519
|
+
})));
|
|
520
|
+
}
|
|
521
|
+
// ---- State ----
|
|
522
|
+
async getState(threadId) {
|
|
523
|
+
if (!this.checkpointer)
|
|
524
|
+
return null;
|
|
525
|
+
return (await this.checkpointer.get(threadId))?.state ?? null;
|
|
526
|
+
}
|
|
527
|
+
async updateState(threadId, update) {
|
|
528
|
+
if (!this.checkpointer)
|
|
529
|
+
return;
|
|
530
|
+
const cp = await this.checkpointer.get(threadId);
|
|
531
|
+
if (!cp)
|
|
532
|
+
return;
|
|
533
|
+
await this.checkpointer.put({ ...cp, state: this.applyUpdate(cp.state, update), timestamp: Date.now() });
|
|
534
|
+
}
|
|
535
|
+
// ---- Time-travel ----
|
|
536
|
+
async getStateAt(threadId, step) {
|
|
537
|
+
if (!this.checkpointer)
|
|
538
|
+
return null;
|
|
539
|
+
const history = await this.checkpointer.list(threadId);
|
|
540
|
+
return history.find((c) => c.step === step)?.state ?? null;
|
|
541
|
+
}
|
|
542
|
+
async getHistory(threadId) {
|
|
543
|
+
if (!this.checkpointer)
|
|
544
|
+
return [];
|
|
545
|
+
return this.checkpointer.list(threadId);
|
|
546
|
+
}
|
|
547
|
+
async forkFrom(threadId, step, newThreadId) {
|
|
548
|
+
if (!this.checkpointer)
|
|
549
|
+
return;
|
|
550
|
+
const cp = this.checkpointer;
|
|
551
|
+
if (typeof cp.fork === "function") {
|
|
552
|
+
await cp.fork(threadId, step, newThreadId);
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
const history = await this.checkpointer.list(threadId);
|
|
556
|
+
for (const c of history.filter((x) => x.step <= step)) {
|
|
557
|
+
await this.checkpointer.put({ ...c, threadId: newThreadId });
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
// ---- HITL ----
|
|
562
|
+
getPendingInterrupts(threadId) {
|
|
563
|
+
return this.hitlStore.getByThread(threadId);
|
|
564
|
+
}
|
|
565
|
+
hitlSessionStore() {
|
|
566
|
+
return this.hitlStore;
|
|
567
|
+
}
|
|
568
|
+
// ---- Helpers ----
|
|
569
|
+
async saveCheckpoint(threadId, step, state, nextNodes, pendingSends, agentId, metadata, pendingWrites) {
|
|
570
|
+
if (!this.checkpointer)
|
|
571
|
+
return;
|
|
572
|
+
await this.checkpointer.put({
|
|
573
|
+
threadId, step, state, agentId, metadata, pendingWrites,
|
|
574
|
+
nextNodes: nextNodes.map(String),
|
|
575
|
+
pendingSends: pendingSends,
|
|
576
|
+
timestamp: Date.now(),
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
evt(event, data, step, agentId, node) {
|
|
580
|
+
return { event, data, step, timestamp: Date.now(), agentId, node };
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
//# sourceMappingURL=pregel.js.map
|