@axiom-lattice/core 2.1.97 → 2.1.99
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/dist/{chunk-SGRFQY3E.mjs → chunk-BKUBS44O.mjs} +95 -328
- package/dist/chunk-BKUBS44O.mjs.map +1 -0
- package/dist/chunk-VCEF7ZDP.mjs +309 -0
- package/dist/chunk-VCEF7ZDP.mjs.map +1 -0
- package/dist/{compile-4RFYHUBE.mjs → compile-QEFI6YTD.mjs} +3 -2
- package/dist/index.d.mts +432 -87
- package/dist/index.d.ts +432 -87
- package/dist/index.js +17542 -16605
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15732 -14881
- package/dist/index.mjs.map +1 -1
- package/dist/parse-yaml-GQ6BNMC6.mjs +11 -0
- package/dist/parse-yaml-GQ6BNMC6.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-SGRFQY3E.mjs.map +0 -1
- /package/dist/{compile-4RFYHUBE.mjs.map → compile-QEFI6YTD.mjs.map} +0 -0
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseYaml,
|
|
3
|
+
toSafeStateExpr,
|
|
4
|
+
validateExpression
|
|
5
|
+
} from "./chunk-VCEF7ZDP.mjs";
|
|
6
|
+
|
|
1
7
|
// src/workflow/compile.ts
|
|
2
8
|
import {
|
|
3
9
|
StateGraph,
|
|
@@ -9,298 +15,28 @@ import {
|
|
|
9
15
|
import {
|
|
10
16
|
Annotation
|
|
11
17
|
} from "@langchain/langgraph";
|
|
12
|
-
import { HumanMessage
|
|
18
|
+
import { HumanMessage } from "@langchain/core/messages";
|
|
13
19
|
|
|
14
|
-
// src/workflow/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
35
|
-
const nested = toJsonSchema(value);
|
|
36
|
-
return nested ?? { type: "object" };
|
|
37
|
-
}
|
|
38
|
-
return { type: "string" };
|
|
39
|
-
}
|
|
40
|
-
function stringTypeToSchema(type) {
|
|
41
|
-
if (type.endsWith("[]")) {
|
|
42
|
-
const inner = type.slice(0, -2);
|
|
43
|
-
return { type: "array", items: stringTypeToSchema(inner) };
|
|
44
|
-
}
|
|
45
|
-
if (type === "string") return { type: "string" };
|
|
46
|
-
if (type === "number") return { type: "number" };
|
|
47
|
-
if (type === "boolean") return { type: "boolean" };
|
|
48
|
-
return { type };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// src/workflow/parse-yaml.ts
|
|
52
|
-
function nodeId(label) {
|
|
53
|
-
return `n_${label}`;
|
|
54
|
-
}
|
|
55
|
-
var _parallelSeq = 0;
|
|
56
|
-
function nextParallelLabel() {
|
|
57
|
-
return `parallel_${_parallelSeq++}`;
|
|
58
|
-
}
|
|
59
|
-
function translate(template) {
|
|
60
|
-
return template.replace(/\{\{([^}]+)\}\}/g, (_m, expr) => {
|
|
61
|
-
const t = expr.trim();
|
|
62
|
-
if (t === "item") return "${item}";
|
|
63
|
-
return `\${state.${t}}`;
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
function toSafeStateExpr(expr) {
|
|
67
|
-
const match = expr.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)/);
|
|
68
|
-
if (!match) return `state.${expr}`;
|
|
69
|
-
const field = match[0];
|
|
70
|
-
const rest = expr.slice(field.length);
|
|
71
|
-
return `state["${field}"]${rest}`;
|
|
72
|
-
}
|
|
73
|
-
function validateExpression(expr) {
|
|
74
|
-
if (/;/.test(expr)) {
|
|
75
|
-
throw new Error(`Condition expression must not contain semicolons: "${expr}"`);
|
|
76
|
-
}
|
|
77
|
-
if (/[{}]/.test(expr)) {
|
|
78
|
-
throw new Error(`Condition expression must not contain braces: "${expr}"`);
|
|
79
|
-
}
|
|
80
|
-
if (/\bfunction\b/.test(expr)) {
|
|
81
|
-
throw new Error(`Condition expression must not contain 'function': "${expr}"`);
|
|
82
|
-
}
|
|
83
|
-
if (/\brequire\b|\bimport\b|\bmodule\b/.test(expr)) {
|
|
84
|
-
throw new Error(`Condition expression must not contain require/import: "${expr}"`);
|
|
85
|
-
}
|
|
86
|
-
if (/\bprocess\b|\bglobal\b|\bglobalThis\b/.test(expr)) {
|
|
87
|
-
throw new Error(`Condition expression must not contain process/global: "${expr}"`);
|
|
88
|
-
}
|
|
89
|
-
if (/\beval\b|\bFunction\b/.test(expr)) {
|
|
90
|
-
throw new Error(`Condition expression must not contain eval/Function: "${expr}"`);
|
|
91
|
-
}
|
|
92
|
-
if (/\bconstructor\b|\b__proto__\b|\bprototype\b/.test(expr)) {
|
|
93
|
-
throw new Error(`Condition expression must not contain prototype access: "${expr}"`);
|
|
94
|
-
}
|
|
95
|
-
if (/\bsetTimeout\b|\bsetInterval\b|\bbuffer\b/i.test(expr)) {
|
|
96
|
-
throw new Error(`Condition expression must not contain timer or buffer references: "${expr}"`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function parseYaml(yamlStr) {
|
|
100
|
-
_parallelSeq = 0;
|
|
101
|
-
let raw;
|
|
102
|
-
try {
|
|
103
|
-
raw = yaml.load(yamlStr);
|
|
104
|
-
} catch (e) {
|
|
105
|
-
const line = e?.mark?.line != null ? ` (line ${e.mark.line + 1})` : "";
|
|
106
|
-
throw new Error(`YAML parse error${line}: ${e.message || e}`);
|
|
107
|
-
}
|
|
108
|
-
if (!raw || typeof raw !== "object" || !Array.isArray(raw.steps)) {
|
|
109
|
-
throw new Error("Workflow YAML must have 'steps' (array)");
|
|
110
|
-
}
|
|
111
|
-
const name = typeof raw.name === "string" ? raw.name : "workflow";
|
|
112
|
-
const wf = {
|
|
113
|
-
name,
|
|
114
|
-
steps: raw.steps.map((s, i) => parseStep(s, i))
|
|
115
|
-
};
|
|
116
|
-
return normalize(wf);
|
|
117
|
-
}
|
|
118
|
-
function parseStep(raw, index) {
|
|
119
|
-
if (raw.parallel !== void 0) {
|
|
120
|
-
if (!Array.isArray(raw.parallel)) {
|
|
121
|
-
throw new Error(`Step at position ${index}: parallel must be an array`);
|
|
122
|
-
}
|
|
123
|
-
const children = raw.parallel.map((c, ci) => {
|
|
124
|
-
const entries2 = Object.entries(c);
|
|
125
|
-
if (entries2.length !== 1) {
|
|
126
|
-
throw new Error(`Parallel child at position ${index}.${ci} must be a single-key mapping`);
|
|
127
|
-
}
|
|
128
|
-
const [label, config2] = entries2[0];
|
|
129
|
-
return {
|
|
130
|
-
label,
|
|
131
|
-
if: config2.if !== void 0 ? String(config2.if) : void 0,
|
|
132
|
-
prompt: String(config2.prompt ?? ""),
|
|
133
|
-
output: config2.output,
|
|
134
|
-
ask: config2.ask === true
|
|
135
|
-
};
|
|
136
|
-
});
|
|
137
|
-
return {
|
|
138
|
-
parallel: children,
|
|
139
|
-
if: raw.if !== void 0 ? String(raw.if) : void 0,
|
|
140
|
-
output: raw.output
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
const entries = Object.entries(raw);
|
|
144
|
-
if (entries.length !== 1) {
|
|
145
|
-
throw new Error(`Step at position ${index} must be a single-key mapping`);
|
|
146
|
-
}
|
|
147
|
-
const [key, config] = entries[0];
|
|
148
|
-
const mapConfig = config?.map;
|
|
149
|
-
if (mapConfig && typeof mapConfig === "object") {
|
|
150
|
-
return {
|
|
151
|
-
map: {
|
|
152
|
-
source: mapConfig.source,
|
|
153
|
-
label: key,
|
|
154
|
-
// always use the YAML key as the label
|
|
155
|
-
if: mapConfig.if !== void 0 ? String(mapConfig.if) : void 0,
|
|
156
|
-
each: {
|
|
157
|
-
prompt: String(mapConfig.each?.prompt ?? ""),
|
|
158
|
-
output: mapConfig.each?.output
|
|
159
|
-
},
|
|
160
|
-
output: mapConfig.output,
|
|
161
|
-
batch: mapConfig.batch,
|
|
162
|
-
concurrency: mapConfig.concurrency
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
if (key === "map") {
|
|
167
|
-
throw new Error(`Map steps must use named format: - <label>: { map: { source, each, ... } }. Anonymous "- map:" is not supported.`);
|
|
168
|
-
}
|
|
169
|
-
return {
|
|
170
|
-
label: key,
|
|
171
|
-
if: config.if !== void 0 ? String(config.if) : void 0,
|
|
172
|
-
prompt: String(config.prompt ?? ""),
|
|
173
|
-
output: config.output,
|
|
174
|
-
ask: config.ask === true
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function normalize(wf) {
|
|
178
|
-
validate(wf);
|
|
179
|
-
for (const step of wf.steps) {
|
|
180
|
-
if ("label" in step) {
|
|
181
|
-
const s = step;
|
|
182
|
-
if (s.if) validateExpression(s.if);
|
|
183
|
-
} else if ("parallel" in step) {
|
|
184
|
-
const pb = step;
|
|
185
|
-
if (pb.if) validateExpression(pb.if);
|
|
186
|
-
for (const child of pb.parallel) {
|
|
187
|
-
if (child.if) validateExpression(child.if);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const nodes = [];
|
|
192
|
-
const edges = [];
|
|
193
|
-
const fields = { input: { type: "string" } };
|
|
194
|
-
nodes.push({ id: "n_input", type: "input", name: "input", output: { key: "input" } });
|
|
195
|
-
edges.push({ from: "START", to: "n_input" });
|
|
196
|
-
let prevNodeId = "n_input";
|
|
197
|
-
for (const step of wf.steps) {
|
|
198
|
-
if ("label" in step) {
|
|
199
|
-
const s = step;
|
|
200
|
-
const nid = nodeId(s.label);
|
|
201
|
-
const schema = toJsonSchema(s.output);
|
|
202
|
-
nodes.push({
|
|
203
|
-
id: nid,
|
|
204
|
-
type: "agent",
|
|
205
|
-
name: s.label,
|
|
206
|
-
input: { template: translate(s.prompt) },
|
|
207
|
-
output: { key: s.label, ...schema ? { schema } : {} },
|
|
208
|
-
ask: s.ask,
|
|
209
|
-
condition: s.if
|
|
210
|
-
});
|
|
211
|
-
fields[s.label] = s.output ? { type: "object" } : { type: "string" };
|
|
212
|
-
addPrevEdges(edges, prevNodeId, nid);
|
|
213
|
-
prevNodeId = nid;
|
|
214
|
-
} else if ("parallel" in step) {
|
|
215
|
-
const pb = step;
|
|
216
|
-
const groupId = nextParallelLabel();
|
|
217
|
-
const groupNodeIds = [];
|
|
218
|
-
for (const child of pb.parallel) {
|
|
219
|
-
const nid = nodeId(child.label);
|
|
220
|
-
const schema = toJsonSchema(child.output);
|
|
221
|
-
nodes.push({
|
|
222
|
-
id: nid,
|
|
223
|
-
type: "agent",
|
|
224
|
-
name: child.label,
|
|
225
|
-
input: { template: translate(child.prompt) },
|
|
226
|
-
output: { key: child.label, ...schema ? { schema } : {} },
|
|
227
|
-
ask: child.ask,
|
|
228
|
-
condition: child.if,
|
|
229
|
-
parallelGroup: groupId
|
|
230
|
-
});
|
|
231
|
-
fields[child.label] = child.output ? { type: "object" } : { type: "string" };
|
|
232
|
-
groupNodeIds.push(nid);
|
|
233
|
-
}
|
|
234
|
-
addPrevEdges(edges, prevNodeId, groupNodeIds);
|
|
235
|
-
prevNodeId = groupNodeIds;
|
|
236
|
-
} else if ("map" in step) {
|
|
237
|
-
const ms = step.map;
|
|
238
|
-
const label = ms.label;
|
|
239
|
-
const nid = nodeId(label);
|
|
240
|
-
const innerSchema = toJsonSchema(ms.each?.output);
|
|
241
|
-
const mapSchema = toJsonSchema(ms.output);
|
|
242
|
-
nodes.push({
|
|
243
|
-
id: nid,
|
|
244
|
-
type: "map",
|
|
245
|
-
name: label,
|
|
246
|
-
source: `state.${ms.source}`,
|
|
247
|
-
itemKey: "item",
|
|
248
|
-
config: {
|
|
249
|
-
batchSize: ms.batch ?? 50,
|
|
250
|
-
maxConcurrency: ms.concurrency ?? 5,
|
|
251
|
-
innerConcurrency: ms.concurrency ?? 5
|
|
252
|
-
},
|
|
253
|
-
node: {
|
|
254
|
-
type: "agent",
|
|
255
|
-
input: ms.each?.prompt ? { template: translate(ms.each.prompt) } : void 0,
|
|
256
|
-
...innerSchema ? { schema: innerSchema } : {}
|
|
257
|
-
},
|
|
258
|
-
output: { key: label, ...mapSchema ? { schema: mapSchema } : {} },
|
|
259
|
-
condition: ms.if
|
|
260
|
-
});
|
|
261
|
-
fields[label] = { type: "array", default: [] };
|
|
262
|
-
addPrevEdges(edges, prevNodeId, nid);
|
|
263
|
-
prevNodeId = nid;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
const termNid = nodeId("__end");
|
|
267
|
-
nodes.push({ id: termNid, type: "terminal", name: "__end", status: "success" });
|
|
268
|
-
addPrevEdges(edges, prevNodeId, termNid);
|
|
269
|
-
return { version: "1.0", name: wf.name || "workflow", state: { fields }, nodes, edges };
|
|
270
|
-
}
|
|
271
|
-
function addPrevEdges(edges, fromNodes, toNodes) {
|
|
272
|
-
const fromList = Array.isArray(fromNodes) ? fromNodes : [fromNodes];
|
|
273
|
-
const toList = Array.isArray(toNodes) ? toNodes : [toNodes];
|
|
274
|
-
for (const from of fromList) {
|
|
275
|
-
for (const to of toList) {
|
|
276
|
-
if (!edges.some((e) => e.from === from && e.to === to)) {
|
|
277
|
-
edges.push({ from, to });
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
function validate(wf) {
|
|
283
|
-
const labels = /* @__PURE__ */ new Set();
|
|
284
|
-
for (const step of wf.steps) {
|
|
285
|
-
if ("label" in step) {
|
|
286
|
-
const s = step;
|
|
287
|
-
if (labels.has(s.label)) throw new Error(`Duplicate step label "${s.label}"`);
|
|
288
|
-
labels.add(s.label);
|
|
289
|
-
} else if ("parallel" in step) {
|
|
290
|
-
const pb = step;
|
|
291
|
-
if (pb.parallel.length === 0) {
|
|
292
|
-
throw new Error("parallel block must contain at least one child step");
|
|
293
|
-
}
|
|
294
|
-
for (const child of pb.parallel) {
|
|
295
|
-
if (labels.has(child.label)) throw new Error(`Duplicate step label "${child.label}"`);
|
|
296
|
-
labels.add(child.label);
|
|
297
|
-
}
|
|
298
|
-
} else if ("map" in step) {
|
|
299
|
-
const ms = step.map;
|
|
300
|
-
if (labels.has(ms.label)) throw new Error(`Duplicate step label "${ms.label}" (map step)`);
|
|
301
|
-
labels.add(ms.label);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
20
|
+
// src/workflow/WorkflowAbortRegistry.ts
|
|
21
|
+
var controllers = /* @__PURE__ */ new Map();
|
|
22
|
+
function registerWorkflowRun(runId) {
|
|
23
|
+
const existing = controllers.get(runId);
|
|
24
|
+
if (existing) return existing;
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
controllers.set(runId, controller);
|
|
27
|
+
return controller;
|
|
28
|
+
}
|
|
29
|
+
function getWorkflowSignal(runId) {
|
|
30
|
+
return controllers.get(runId)?.signal;
|
|
31
|
+
}
|
|
32
|
+
function abortWorkflowRun(runId) {
|
|
33
|
+
const controller = controllers.get(runId);
|
|
34
|
+
if (!controller) return false;
|
|
35
|
+
controller.abort();
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
function unregisterWorkflowRun(runId) {
|
|
39
|
+
controllers.delete(runId);
|
|
304
40
|
}
|
|
305
41
|
|
|
306
42
|
// src/workflow/utils.ts
|
|
@@ -402,7 +138,7 @@ function renderTemplate(template, state, item) {
|
|
|
402
138
|
return formatValue(item);
|
|
403
139
|
}
|
|
404
140
|
const itemPath = trimmed;
|
|
405
|
-
const val = resolvePath(
|
|
141
|
+
const val = resolvePath(item, itemPath);
|
|
406
142
|
return val === void 0 ? "" : formatValue(val);
|
|
407
143
|
}
|
|
408
144
|
if (item && typeof item === "object") {
|
|
@@ -631,7 +367,8 @@ function createAgentNode(node, resolveAgent, trackingStore) {
|
|
|
631
367
|
}
|
|
632
368
|
try {
|
|
633
369
|
console.log(`[WF][${node.id}] START "${node.name}" | hasSchema=${!!node.output?.schema}`);
|
|
634
|
-
const
|
|
370
|
+
const hasRef = !!node.ref;
|
|
371
|
+
const responseFormat = !hasRef && node.output?.schema ? node.output.schema : void 0;
|
|
635
372
|
console.log(`[WF][${node.id}] resolving agent...`);
|
|
636
373
|
const stepType = node.ask ? "ask" : node.type;
|
|
637
374
|
const client = await resolveAgent(node.ref, responseFormat, stepType);
|
|
@@ -642,20 +379,13 @@ function createAgentNode(node, resolveAgent, trackingStore) {
|
|
|
642
379
|
void 0,
|
|
643
380
|
responseFormat ? void 0 : node.output?.schema
|
|
644
381
|
);
|
|
645
|
-
if (node.ask) {
|
|
646
|
-
input.messages = [
|
|
647
|
-
new SystemMessage(
|
|
648
|
-
"Follow this exact procedure. Do NOT skip any step.\n\nSTEP 1: Read the prompt. It contains content to present to the user and a question to ask.\n\nSTEP 2: Call ask_user_to_clarify. Your question text MUST contain the ACTUAL content from the prompt.\n\nSTEP 3: The tool will pause. The user will see your questions and respond. You will receive their answers.\n\nSTEP 4: Based on the user's answers, produce your final output."
|
|
649
|
-
),
|
|
650
|
-
...input.messages
|
|
651
|
-
];
|
|
652
|
-
}
|
|
653
382
|
const renderedInput = input.messages[0]?.content ?? "";
|
|
654
383
|
console.log(`[WF][${node.id}] === INPUT (full) ===
|
|
655
384
|
${renderedInput}
|
|
656
385
|
=== END INPUT ===`);
|
|
657
386
|
const subConfig = {
|
|
658
387
|
...config,
|
|
388
|
+
signal: getWorkflowSignal(runId),
|
|
659
389
|
configurable: {
|
|
660
390
|
...config?.configurable ?? {},
|
|
661
391
|
thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}`
|
|
@@ -705,7 +435,7 @@ ${renderedInput}
|
|
|
705
435
|
console.log(`[WF][${node.id}] invoke FAILED: ${errMsg}`);
|
|
706
436
|
if (responseFormat && (errMsg.includes("tool_choice") || errMsg.includes("thinking") || errMsg.includes("reasoning") || errMsg.includes("InvalidParameter"))) {
|
|
707
437
|
console.log(`[WF][${node.id}] attempting fallback (text-based schema injection)...`);
|
|
708
|
-
const fallbackClient = await resolveAgent(node.ref, void 0,
|
|
438
|
+
const fallbackClient = await resolveAgent(node.ref, void 0, stepType);
|
|
709
439
|
const fallbackInput = buildInput(node.input, state, void 0, responseFormat);
|
|
710
440
|
result = await invokeWithRetry(
|
|
711
441
|
() => fallbackClient.invoke(fallbackInput, subConfig),
|
|
@@ -749,6 +479,26 @@ ${JSON.stringify(output, null, 2)}
|
|
|
749
479
|
}
|
|
750
480
|
return update;
|
|
751
481
|
} catch (err) {
|
|
482
|
+
if (err?.name === "AbortError") {
|
|
483
|
+
if (trackingStore && runId) {
|
|
484
|
+
if (stepId) {
|
|
485
|
+
trackingStore.updateRunStep(runId, stepId, {
|
|
486
|
+
status: "cancelled",
|
|
487
|
+
errorMessage: "Aborted by user",
|
|
488
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
489
|
+
durationMs: Date.now() - startedAt
|
|
490
|
+
}).catch(() => {
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
trackingStore.updateWorkflowRun(runId, {
|
|
494
|
+
status: "cancelled",
|
|
495
|
+
errorMessage: "Aborted by user",
|
|
496
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
497
|
+
}).catch(() => {
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
throw err;
|
|
501
|
+
}
|
|
752
502
|
if (err?.name === "GraphInterrupt") {
|
|
753
503
|
throw err;
|
|
754
504
|
}
|
|
@@ -848,15 +598,17 @@ function createMapNode(node, resolveAgent, trackingStore) {
|
|
|
848
598
|
const itemKey = node.itemKey ?? "item";
|
|
849
599
|
const innerClient = await resolveAgent(node.node.ref, node.node.schema, node.type);
|
|
850
600
|
const batches = chunk(items, batchSize);
|
|
851
|
-
const batchResults = await parallelLimit(batches, maxConcurrency, async (batch) => {
|
|
601
|
+
const batchResults = await parallelLimit(batches, maxConcurrency, async (batch, batchIdx) => {
|
|
852
602
|
const itemResults = await parallelLimit(batch, innerConcurrency, async (item, itemIdx) => {
|
|
603
|
+
const globalIdx = batchIdx * batchSize + itemIdx;
|
|
853
604
|
const itemCtx = { [itemKey]: item };
|
|
854
605
|
const input = buildInput(node.node.input, state, itemCtx);
|
|
855
606
|
const subConfig = {
|
|
856
607
|
...config,
|
|
608
|
+
signal: getWorkflowSignal(runId),
|
|
857
609
|
configurable: {
|
|
858
610
|
...config?.configurable ?? {},
|
|
859
|
-
thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}:item:${
|
|
611
|
+
thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}:item:${globalIdx}`
|
|
860
612
|
}
|
|
861
613
|
};
|
|
862
614
|
const result = await invokeWithRetry(
|
|
@@ -870,26 +622,7 @@ function createMapNode(node, resolveAgent, trackingStore) {
|
|
|
870
622
|
return itemResults;
|
|
871
623
|
});
|
|
872
624
|
const allResults = batchResults.flat();
|
|
873
|
-
|
|
874
|
-
if (node.reduce) {
|
|
875
|
-
const reduceClient = await resolveAgent(node.reduce.ref, node.reduce.schema, node.type);
|
|
876
|
-
const tempResultsKey = node.output?.key ?? `${node.id}_results`;
|
|
877
|
-
const tempState = { ...state, [tempResultsKey]: allResults };
|
|
878
|
-
const reduceInput = buildInput(node.reduce.input, tempState);
|
|
879
|
-
const reduceResult = await invokeWithRetry(
|
|
880
|
-
() => reduceClient.invoke(reduceInput, {
|
|
881
|
-
...config,
|
|
882
|
-
configurable: {
|
|
883
|
-
...config?.configurable ?? {},
|
|
884
|
-
thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}:reduce`
|
|
885
|
-
}
|
|
886
|
-
}),
|
|
887
|
-
node.config?.maxRetries ?? 0,
|
|
888
|
-
node.config?.retryOn,
|
|
889
|
-
node.config?.timeout
|
|
890
|
-
);
|
|
891
|
-
finalOutput = extractOutput(reduceResult);
|
|
892
|
-
}
|
|
625
|
+
const finalOutput = allResults;
|
|
893
626
|
const update = { phase: node.id };
|
|
894
627
|
if (node.output?.key) {
|
|
895
628
|
update[node.output.key] = finalOutput;
|
|
@@ -906,6 +639,26 @@ function createMapNode(node, resolveAgent, trackingStore) {
|
|
|
906
639
|
}
|
|
907
640
|
return update;
|
|
908
641
|
} catch (err) {
|
|
642
|
+
if (err?.name === "AbortError") {
|
|
643
|
+
if (trackingStore && runId) {
|
|
644
|
+
if (stepId) {
|
|
645
|
+
trackingStore.updateRunStep(runId, stepId, {
|
|
646
|
+
status: "cancelled",
|
|
647
|
+
errorMessage: "Aborted by user",
|
|
648
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
649
|
+
durationMs: Date.now() - startedAt
|
|
650
|
+
}).catch(() => {
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
trackingStore.updateWorkflowRun(runId, {
|
|
654
|
+
status: "cancelled",
|
|
655
|
+
errorMessage: "Aborted by user",
|
|
656
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
657
|
+
}).catch(() => {
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
throw err;
|
|
661
|
+
}
|
|
909
662
|
if (err?.name === "GraphInterrupt") {
|
|
910
663
|
if (trackingStore && runId && stepId) {
|
|
911
664
|
trackingStore.updateRunStep(runId, stepId, { status: "interrupted" }).catch(() => {
|
|
@@ -950,6 +703,17 @@ function createInputNode(node, trackingStore) {
|
|
|
950
703
|
console.log(`[WF][n_input] input captured: "${inputText.slice(0, 200)}"`);
|
|
951
704
|
const update = { phase: node.id };
|
|
952
705
|
if (node.output?.key) update[node.output.key] = inputText;
|
|
706
|
+
if (trackingStore) {
|
|
707
|
+
try {
|
|
708
|
+
const existingRuns = await trackingStore.getWorkflowRunsByThreadId(tenantId, threadId);
|
|
709
|
+
const wasAborted = existingRuns?.some((r) => r.status === "cancelled" && r.assistantId === assistantId);
|
|
710
|
+
if (wasAborted) {
|
|
711
|
+
console.log(`[WF][n_input] Workflow was aborted before restart, skipping execution`);
|
|
712
|
+
throw new Error("Workflow was aborted \u2014 execution cancelled");
|
|
713
|
+
}
|
|
714
|
+
} catch (e) {
|
|
715
|
+
}
|
|
716
|
+
}
|
|
953
717
|
if (trackingStore && !state._runId) {
|
|
954
718
|
try {
|
|
955
719
|
const run = await trackingStore.createWorkflowRun({
|
|
@@ -960,6 +724,7 @@ function createInputNode(node, trackingStore) {
|
|
|
960
724
|
metadata: { workflowName: node.name }
|
|
961
725
|
});
|
|
962
726
|
update._runId = run.id;
|
|
727
|
+
registerWorkflowRun(run.id);
|
|
963
728
|
await trackingStore.createRunStep({
|
|
964
729
|
runId: run.id,
|
|
965
730
|
tenantId,
|
|
@@ -1012,6 +777,7 @@ function createTerminalNode(node, trackingStore) {
|
|
|
1012
777
|
console.warn(`[WF][terminal] Failed to create terminal RunStep:`, e.message);
|
|
1013
778
|
}
|
|
1014
779
|
}
|
|
780
|
+
if (runId) unregisterWorkflowRun(runId);
|
|
1015
781
|
return {
|
|
1016
782
|
status: node.status,
|
|
1017
783
|
phase: node.id
|
|
@@ -1120,9 +886,10 @@ function validateAndThrow(dsl) {
|
|
|
1120
886
|
}
|
|
1121
887
|
|
|
1122
888
|
export {
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
889
|
+
registerWorkflowRun,
|
|
890
|
+
getWorkflowSignal,
|
|
891
|
+
abortWorkflowRun,
|
|
892
|
+
unregisterWorkflowRun,
|
|
1126
893
|
buildStateAnnotation,
|
|
1127
894
|
resolvePath,
|
|
1128
895
|
renderTemplate,
|
|
@@ -1137,4 +904,4 @@ export {
|
|
|
1137
904
|
compileInternal,
|
|
1138
905
|
validateDSL
|
|
1139
906
|
};
|
|
1140
|
-
//# sourceMappingURL=chunk-
|
|
907
|
+
//# sourceMappingURL=chunk-BKUBS44O.mjs.map
|