@axiom-lattice/core 2.1.78 → 2.1.80

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/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -15,17 +18,1631 @@ var __copyProps = (to, from, except, desc) => {
15
18
  if (!__hasOwnProp.call(to, key) && key !== except)
16
19
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
20
  }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/base/BaseLatticeManager.ts
34
+ var _BaseLatticeManager, BaseLatticeManager;
35
+ var init_BaseLatticeManager = __esm({
36
+ "src/base/BaseLatticeManager.ts"() {
37
+ "use strict";
38
+ _BaseLatticeManager = class _BaseLatticeManager {
39
+ /**
40
+ * 受保护的构造函数,防止外部直接实例化
41
+ */
42
+ constructor() {
43
+ }
44
+ /**
45
+ * 获取管理器实例(由子类实现)
46
+ */
47
+ static getInstance() {
48
+ throw new Error("\u5FC5\u987B\u7531\u5B50\u7C7B\u5B9E\u73B0");
49
+ }
50
+ /**
51
+ * 构造完整的键名,包含类型前缀和租户ID
52
+ * @param tenantId 租户ID,全局共享使用 "default"
53
+ * @param key 原始键名
54
+ */
55
+ getFullKey(tenantId, key) {
56
+ return `${this.getLatticeType()}:${tenantId}:${key}`;
57
+ }
58
+ // ========== 带租户的新API ==========
59
+ /**
60
+ * 带租户的注册项目
61
+ * @param tenantId 租户ID
62
+ * @param key 项目键名(不含前缀)
63
+ * @param item 项目实例
64
+ */
65
+ registerWithTenant(tenantId, key, item) {
66
+ const fullKey = this.getFullKey(tenantId, key);
67
+ if (_BaseLatticeManager.registry.has(fullKey)) {
68
+ throw new Error(`\u9879\u76EE "${fullKey}" \u5DF2\u7ECF\u5B58\u5728\uFF0C\u65E0\u6CD5\u91CD\u590D\u6CE8\u518C`);
69
+ }
70
+ _BaseLatticeManager.registry.set(fullKey, item);
71
+ }
72
+ /**
73
+ * 带租户的获取指定项目(同步)
74
+ * @param tenantId 租户ID
75
+ * @param key 项目键名(不含前缀)
76
+ */
77
+ getWithTenant(tenantId, key) {
78
+ const fullKey = this.getFullKey(tenantId, key);
79
+ return _BaseLatticeManager.registry.get(fullKey);
80
+ }
81
+ /**
82
+ * 带租户的获取指定项目(异步,支持从store回退加载)
83
+ * 如果内存中不存在且子类实现了loadItemFromStore,则尝试从store加载
84
+ * @param tenantId 租户ID
85
+ * @param key 项目键名(不含前缀)
86
+ * @returns 项目实例,如果未找到则返回undefined
87
+ */
88
+ async getOrLoadWithTenant(tenantId, key) {
89
+ const item = this.getWithTenant(tenantId, key);
90
+ if (item !== void 0) {
91
+ return item;
92
+ }
93
+ if (this.loadItemFromStore) {
94
+ const loadedItem = await this.loadItemFromStore(tenantId, key);
95
+ if (loadedItem !== void 0) {
96
+ this.registerWithTenant(tenantId, key, loadedItem);
97
+ return loadedItem;
98
+ }
99
+ }
100
+ return void 0;
101
+ }
102
+ /**
103
+ * 带租户的检查项目是否存在(同步)
104
+ * @param tenantId 租户ID
105
+ * @param key 项目键名(不含前缀)
106
+ */
107
+ hasWithTenant(tenantId, key) {
108
+ const fullKey = this.getFullKey(tenantId, key);
109
+ return _BaseLatticeManager.registry.has(fullKey);
110
+ }
111
+ /**
112
+ * 带租户的检查项目是否存在(异步,支持从store回退加载)
113
+ * 如果内存中不存在且子类实现了loadItemFromStore,则尝试从store加载
114
+ * @param tenantId 租户ID
115
+ * @param key 项目键名(不含前缀)
116
+ * @returns 如果存在或能从store加载则返回true
117
+ */
118
+ async hasOrLoadWithTenant(tenantId, key) {
119
+ if (this.hasWithTenant(tenantId, key)) {
120
+ return true;
121
+ }
122
+ if (this.loadItemFromStore) {
123
+ const loadedItem = await this.loadItemFromStore(tenantId, key);
124
+ if (loadedItem !== void 0) {
125
+ this.registerWithTenant(tenantId, key, loadedItem);
126
+ return true;
127
+ }
128
+ }
129
+ return false;
130
+ }
131
+ /**
132
+ * 带租户的移除项目
133
+ * @param tenantId 租户ID
134
+ * @param key 项目键名(不含前缀)
135
+ */
136
+ removeWithTenant(tenantId, key) {
137
+ const fullKey = this.getFullKey(tenantId, key);
138
+ return _BaseLatticeManager.registry.delete(fullKey);
139
+ }
140
+ /**
141
+ * 获取指定租户的所有项目
142
+ * @param tenantId 租户ID
143
+ */
144
+ getAllByTenant(tenantId) {
145
+ const prefix = `${this.getLatticeType()}:${tenantId}:`;
146
+ const result = [];
147
+ for (const [key, value] of _BaseLatticeManager.registry.entries()) {
148
+ if (key.startsWith(prefix)) {
149
+ result.push(value);
150
+ }
151
+ }
152
+ return result;
153
+ }
154
+ /**
155
+ * 清空指定租户的所有项目
156
+ * @param tenantId 租户ID
157
+ */
158
+ clearByTenant(tenantId) {
159
+ const prefix = `${this.getLatticeType()}:${tenantId}:`;
160
+ const keysToDelete = [];
161
+ for (const key of _BaseLatticeManager.registry.keys()) {
162
+ if (key.startsWith(prefix)) {
163
+ keysToDelete.push(key);
164
+ }
165
+ }
166
+ for (const key of keysToDelete) {
167
+ _BaseLatticeManager.registry.delete(key);
168
+ }
169
+ }
170
+ // ========== 向后兼容的旧API(使用 default 租户) ==========
171
+ /**
172
+ * 注册项目(向后兼容,使用 "default" 租户)
173
+ * @deprecated Use registerWithTenant(tenantId, key, item) instead
174
+ * @param key 项目键名(不含前缀)
175
+ * @param item 项目实例
176
+ */
177
+ register(key, item) {
178
+ this.registerWithTenant("default", key, item);
179
+ }
180
+ /**
181
+ * 获取指定项目(向后兼容,使用 "default" 租户)
182
+ * @deprecated Use getWithTenant(tenantId, key) instead
183
+ * @param key 项目键名(不含前缀)
184
+ */
185
+ get(key) {
186
+ return this.getWithTenant("default", key);
187
+ }
188
+ /**
189
+ * 获取所有当前类型的项目(向后兼容,包含所有租户)
190
+ */
191
+ getAll() {
192
+ const prefix = `${this.getLatticeType()}:`;
193
+ const result = [];
194
+ for (const [key, value] of _BaseLatticeManager.registry.entries()) {
195
+ if (key.startsWith(prefix)) {
196
+ result.push(value);
197
+ }
198
+ }
199
+ return result;
200
+ }
201
+ /**
202
+ * 检查项目是否存在(向后兼容,使用 "default" 租户)
203
+ * @deprecated Use hasWithTenant(tenantId, key) instead
204
+ * @param key 项目键名(不含前缀)
205
+ */
206
+ has(key) {
207
+ return this.hasWithTenant("default", key);
208
+ }
209
+ /**
210
+ * 移除项目(向后兼容,使用 "default" 租户)
211
+ * @deprecated Use removeWithTenant(tenantId, key) instead
212
+ * @param key 项目键名(不含前缀)
213
+ */
214
+ remove(key) {
215
+ return this.removeWithTenant("default", key);
216
+ }
217
+ /**
218
+ * 清空当前类型的所有项目(向后兼容,包含所有租户)
219
+ */
220
+ clear() {
221
+ const prefix = `${this.getLatticeType()}:`;
222
+ const keysToDelete = [];
223
+ for (const key of _BaseLatticeManager.registry.keys()) {
224
+ if (key.startsWith(prefix)) {
225
+ keysToDelete.push(key);
226
+ }
227
+ }
228
+ for (const key of keysToDelete) {
229
+ _BaseLatticeManager.registry.delete(key);
230
+ }
231
+ }
232
+ /**
233
+ * 获取当前类型的项目数量(向后兼容,包含所有租户)
234
+ */
235
+ count() {
236
+ const prefix = `${this.getLatticeType()}:`;
237
+ let count = 0;
238
+ for (const key of _BaseLatticeManager.registry.keys()) {
239
+ if (key.startsWith(prefix)) {
240
+ count++;
241
+ }
242
+ }
243
+ return count;
244
+ }
245
+ /**
246
+ * 获取当前类型的项目键名列表(向后兼容,包含所有租户)
247
+ * 返回格式: {tenantId}:{key}
248
+ */
249
+ keys() {
250
+ const prefix = `${this.getLatticeType()}:`;
251
+ const prefixLength = prefix.length;
252
+ const result = [];
253
+ for (const key of _BaseLatticeManager.registry.keys()) {
254
+ if (key.startsWith(prefix)) {
255
+ result.push(key.substring(prefixLength));
256
+ }
257
+ }
258
+ return result;
259
+ }
260
+ /**
261
+ * 获取当前类型的项目键名列表(仅指定租户,不含租户前缀)
262
+ * @param tenantId 租户ID
263
+ */
264
+ keysByTenant(tenantId) {
265
+ const prefix = `${this.getLatticeType()}:${tenantId}:`;
266
+ const prefixLength = prefix.length;
267
+ const result = [];
268
+ for (const key of _BaseLatticeManager.registry.keys()) {
269
+ if (key.startsWith(prefix)) {
270
+ result.push(key.substring(prefixLength));
271
+ }
272
+ }
273
+ return result;
274
+ }
275
+ };
276
+ // 全局统一的Lattice注册表
277
+ _BaseLatticeManager.registry = /* @__PURE__ */ new Map();
278
+ BaseLatticeManager = _BaseLatticeManager;
279
+ }
280
+ });
281
+
282
+ // src/memory_lattice/MemoryLatticeManager.ts
283
+ var import_protocols2, _MemoryLatticeManager, MemoryLatticeManager, getCheckpointSaver, registerCheckpointSaver;
284
+ var init_MemoryLatticeManager = __esm({
285
+ "src/memory_lattice/MemoryLatticeManager.ts"() {
286
+ "use strict";
287
+ init_BaseLatticeManager();
288
+ import_protocols2 = require("@axiom-lattice/protocols");
289
+ _MemoryLatticeManager = class _MemoryLatticeManager extends BaseLatticeManager {
290
+ /**
291
+ * 私有构造函数,防止外部直接实例化
292
+ */
293
+ constructor() {
294
+ super();
295
+ }
296
+ /**
297
+ * 获取单例实例
298
+ */
299
+ static getInstance() {
300
+ if (!_MemoryLatticeManager.instance) {
301
+ _MemoryLatticeManager.instance = new _MemoryLatticeManager();
302
+ }
303
+ return _MemoryLatticeManager.instance;
304
+ }
305
+ /**
306
+ * 获取Lattice类型
307
+ */
308
+ getLatticeType() {
309
+ return "memory";
310
+ }
311
+ /**
312
+ * 注册检查点保存器
313
+ * @param key 保存器键名
314
+ * @param saver 检查点保存器实例
315
+ */
316
+ registerCheckpointSaver(key, saver) {
317
+ if (_MemoryLatticeManager.checkpointSavers.has(key)) {
318
+ console.warn(`\u68C0\u67E5\u70B9\u4FDD\u5B58\u5668 "${key}" \u5DF2\u7ECF\u5B58\u5728\uFF0C\u5C06\u4F1A\u8986\u76D6\u65E7\u7684\u68C0\u67E5\u70B9\u4FDD\u5B58\u5668`);
319
+ }
320
+ _MemoryLatticeManager.checkpointSavers.set(key, saver);
321
+ }
322
+ /**
323
+ * 获取检查点保存器
324
+ * @param key 保存器键名
325
+ */
326
+ getCheckpointSaver(key) {
327
+ const saver = _MemoryLatticeManager.checkpointSavers.get(key);
328
+ if (!saver) {
329
+ throw new Error(`\u68C0\u67E5\u70B9\u4FDD\u5B58\u5668 "${key}" \u4E0D\u5B58\u5728`);
330
+ }
331
+ return saver;
332
+ }
333
+ /**
334
+ * 获取所有已注册的检查点保存器键名
335
+ */
336
+ getCheckpointSaverKeys() {
337
+ return Array.from(_MemoryLatticeManager.checkpointSavers.keys());
338
+ }
339
+ /**
340
+ * 检查检查点保存器是否存在
341
+ * @param key 保存器键名
342
+ */
343
+ hasCheckpointSaver(key) {
344
+ return _MemoryLatticeManager.checkpointSavers.has(key);
345
+ }
346
+ /**
347
+ * 移除检查点保存器
348
+ * @param key 保存器键名
349
+ */
350
+ removeCheckpointSaver(key) {
351
+ return _MemoryLatticeManager.checkpointSavers.delete(key);
352
+ }
353
+ };
354
+ // 检查点保存器注册表
355
+ _MemoryLatticeManager.checkpointSavers = /* @__PURE__ */ new Map();
356
+ MemoryLatticeManager = _MemoryLatticeManager;
357
+ getCheckpointSaver = (key) => MemoryLatticeManager.getInstance().getCheckpointSaver(key);
358
+ registerCheckpointSaver = (key, saver) => MemoryLatticeManager.getInstance().registerCheckpointSaver(key, saver);
359
+ }
360
+ });
361
+
362
+ // src/memory_lattice/DefaultMemorySaver.ts
363
+ var import_langgraph2, memory;
364
+ var init_DefaultMemorySaver = __esm({
365
+ "src/memory_lattice/DefaultMemorySaver.ts"() {
366
+ "use strict";
367
+ import_langgraph2 = require("@langchain/langgraph");
368
+ init_MemoryLatticeManager();
369
+ memory = new import_langgraph2.MemorySaver();
370
+ registerCheckpointSaver("default", memory);
371
+ }
372
+ });
373
+
374
+ // src/memory_lattice/index.ts
375
+ var memory_lattice_exports = {};
376
+ __export(memory_lattice_exports, {
377
+ MemoryLatticeManager: () => MemoryLatticeManager,
378
+ MemoryType: () => import_protocols2.MemoryType,
379
+ getCheckpointSaver: () => getCheckpointSaver,
380
+ registerCheckpointSaver: () => registerCheckpointSaver
381
+ });
382
+ var init_memory_lattice = __esm({
383
+ "src/memory_lattice/index.ts"() {
384
+ "use strict";
385
+ init_DefaultMemorySaver();
386
+ init_MemoryLatticeManager();
387
+ }
388
+ });
389
+
390
+ // src/workflow/utils.ts
391
+ function buildStateAnnotation(fields) {
392
+ const annotations = {};
393
+ if (fields) {
394
+ for (const [key, field] of Object.entries(fields)) {
395
+ annotations[key] = (0, import_langgraph15.Annotation)({
396
+ default: () => field.default ?? defaultValueForType(field.type),
397
+ reducer: buildReducer(field.reducer ?? "replace")
398
+ });
399
+ }
400
+ }
401
+ if (!annotations["messages"]) {
402
+ annotations["messages"] = (0, import_langgraph15.Annotation)({
403
+ default: () => [],
404
+ reducer: (prev, next) => [...prev, ...next]
405
+ });
406
+ }
407
+ annotations["phase"] = (0, import_langgraph15.Annotation)({
408
+ default: () => "init",
409
+ reducer: (_prev, next) => next
410
+ });
411
+ if (!annotations["status"]) {
412
+ annotations["status"] = (0, import_langgraph15.Annotation)({
413
+ default: () => "",
414
+ reducer: (_prev, next) => next
415
+ });
416
+ }
417
+ if (!annotations["_runId"]) {
418
+ annotations["_runId"] = (0, import_langgraph15.Annotation)({
419
+ default: () => void 0,
420
+ reducer: (_prev, next) => next ?? _prev
421
+ });
422
+ }
423
+ return import_langgraph15.Annotation.Root(annotations);
424
+ }
425
+ function defaultValueForType(type) {
426
+ switch (type) {
427
+ case "string":
428
+ return "";
429
+ case "number":
430
+ return null;
431
+ case "boolean":
432
+ return false;
433
+ case "object":
434
+ return null;
435
+ case "array":
436
+ return [];
437
+ default:
438
+ return null;
439
+ }
440
+ }
441
+ function buildReducer(kind) {
442
+ switch (kind) {
443
+ case "append":
444
+ return (prev, next) => {
445
+ const arr = Array.isArray(prev) ? prev : [];
446
+ return arr.concat(Array.isArray(next) ? next : [next]);
447
+ };
448
+ case "merge":
449
+ return (prev, next) => {
450
+ const obj = prev && typeof prev === "object" && !Array.isArray(prev) ? prev : {};
451
+ const merge = next && typeof next === "object" && !Array.isArray(next) ? next : {};
452
+ return { ...obj, ...merge };
453
+ };
454
+ case "replace":
455
+ default:
456
+ return (_prev, next) => next;
457
+ }
458
+ }
459
+ function resolvePath(obj, path3) {
460
+ const cleanPath = path3.startsWith("state.") ? path3.slice(6) : path3;
461
+ const parts = cleanPath.split(/\.|\[|\]\.?/).filter(Boolean);
462
+ let current = obj;
463
+ for (const part of parts) {
464
+ if (current === null || current === void 0) return void 0;
465
+ if (typeof current === "object") {
466
+ current = current[part];
467
+ } else {
468
+ return void 0;
469
+ }
470
+ }
471
+ return current;
472
+ }
473
+ function renderTemplate(template, state, item) {
474
+ return template.replace(/\$\{([^}]+)\}/g, (_match, expr) => {
475
+ const trimmed = expr.trim();
476
+ if (trimmed.startsWith("state.")) {
477
+ const val = resolvePath(state, trimmed);
478
+ return val === void 0 ? "" : formatValue(val);
479
+ }
480
+ if (trimmed.startsWith("item.") || trimmed === "item") {
481
+ if (!item) return "";
482
+ if (trimmed === "item") {
483
+ if (typeof item === "object" && "item" in item) {
484
+ return formatValue(item.item);
485
+ }
486
+ return formatValue(item);
487
+ }
488
+ const itemPath = trimmed;
489
+ const val = resolvePath({ item }, itemPath);
490
+ return val === void 0 ? "" : formatValue(val);
491
+ }
492
+ if (item && typeof item === "object") {
493
+ const firstSeg = trimmed.split(".")[0];
494
+ if (firstSeg in item) {
495
+ const val = resolvePath({ item }, `item.${trimmed}`);
496
+ return val === void 0 ? "" : formatValue(val);
497
+ }
498
+ }
499
+ return `\${${trimmed}}`;
500
+ });
501
+ }
502
+ function formatValue(val) {
503
+ if (typeof val === "string") return val;
504
+ if (val === null || val === void 0) return "";
505
+ if (Array.isArray(val)) {
506
+ const parts = val.map((item) => {
507
+ const content = item?.content ?? item?.kwargs?.content;
508
+ if (typeof content === "string") return content;
509
+ if (Array.isArray(content)) {
510
+ return content.filter((c) => c?.type === "text").map((c) => String(c.text ?? "")).join("\n");
511
+ }
512
+ if (content && typeof content === "object") return JSON.stringify(content, null, 2);
513
+ if (item && typeof item === "object") return JSON.stringify(item, null, 2);
514
+ return String(item);
515
+ });
516
+ const result = parts.filter(Boolean).join("\n");
517
+ return result || JSON.stringify(val, null, 2);
518
+ }
519
+ return JSON.stringify(val, null, 2);
520
+ }
521
+ function buildInput(input, state, item, outputSchema) {
522
+ let prompt = input?.template ? renderTemplate(input.template, state, item) : "";
523
+ if (outputSchema) {
524
+ const example = schemaToExample(outputSchema);
525
+ const schemaInstruction = `
526
+
527
+ Output must be valid JSON in exactly this shape. Return ONLY the JSON, no other text or markdown:
528
+ ${example}`;
529
+ prompt = prompt + schemaInstruction;
530
+ }
531
+ return { messages: [new import_messages6.HumanMessage(prompt)] };
532
+ }
533
+ function schemaToExample(schema) {
534
+ const example = schemaValueToExample(schema);
535
+ return JSON.stringify(example, null, 2);
536
+ }
537
+ function schemaValueToExample(value) {
538
+ if (value === null || value === void 0) return null;
539
+ if (typeof value !== "object") return value;
540
+ const obj = value;
541
+ if (obj.type === "string") return "<string>";
542
+ if (obj.type === "number") return "<number>";
543
+ if (obj.type === "boolean") return "<boolean>";
544
+ if (obj.type === "integer") return "<integer>";
545
+ if (obj.type === "array" && obj.items) {
546
+ return [schemaValueToExample(obj.items)];
547
+ }
548
+ if (obj.type === "object" && obj.properties && typeof obj.properties === "object") {
549
+ const example2 = {};
550
+ for (const [k, v] of Object.entries(obj.properties)) {
551
+ example2[k] = schemaValueToExample(v);
552
+ }
553
+ return example2;
554
+ }
555
+ if (obj.type === "object") return {};
556
+ if (Array.isArray(value)) {
557
+ if (value.length === 1) {
558
+ return [schemaValueToExample(value[0])];
559
+ }
560
+ return value.map(schemaValueToExample);
561
+ }
562
+ const example = {};
563
+ for (const [k, v] of Object.entries(obj)) {
564
+ example[k] = schemaValueToExample(v);
565
+ }
566
+ return example;
567
+ }
568
+ function extractOutput(result) {
569
+ if ("structuredResponse" in result && result.structuredResponse !== void 0) {
570
+ return result.structuredResponse;
571
+ }
572
+ const messages = result.messages;
573
+ if (messages && Array.isArray(messages)) {
574
+ for (let i = messages.length - 1; i >= 0; i--) {
575
+ const msg = messages[i];
576
+ if (msg._getType() === "ai") {
577
+ const content = msg.content;
578
+ if (typeof content === "object" && content !== null && !Array.isArray(content)) {
579
+ return content;
580
+ }
581
+ if (Array.isArray(content)) {
582
+ const textParts = content.filter(
583
+ (c) => typeof c === "object" && c !== null && c.type === "text"
584
+ ).map((c) => c.text).join("\n");
585
+ if (textParts) {
586
+ try {
587
+ return JSON.parse(textParts);
588
+ } catch {
589
+ const fenced = extractJsonFromFence(textParts);
590
+ if (fenced !== void 0) return fenced;
591
+ return textParts;
592
+ }
593
+ }
594
+ return content;
595
+ }
596
+ if (typeof content === "string") {
597
+ try {
598
+ return JSON.parse(content);
599
+ } catch {
600
+ const fenced = extractJsonFromFence(content);
601
+ if (fenced !== void 0) return fenced;
602
+ return content;
603
+ }
604
+ }
605
+ return content;
606
+ }
607
+ }
608
+ }
609
+ const { messages: _msgs, ...rest } = result;
610
+ void _msgs;
611
+ return rest;
612
+ }
613
+ function extractJsonFromFence(text) {
614
+ const jsonFence = text.match(/```json\s*\n([\s\S]*?)```/);
615
+ if (jsonFence) {
616
+ try {
617
+ return JSON.parse(jsonFence[1].trim());
618
+ } catch {
619
+ }
620
+ }
621
+ const plainFence = text.match(/```\s*\n([\s\S]*?)```/);
622
+ if (plainFence) {
623
+ try {
624
+ return JSON.parse(plainFence[1].trim());
625
+ } catch {
626
+ }
627
+ }
628
+ return void 0;
629
+ }
630
+ async function parallelLimit(items, limit, fn) {
631
+ const results = new Array(items.length);
632
+ let index = 0;
633
+ async function worker() {
634
+ while (index < items.length) {
635
+ const i = index++;
636
+ results[i] = await fn(items[i], i);
637
+ }
638
+ }
639
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));
640
+ return results;
641
+ }
642
+ async function invokeWithRetry(fn, maxRetries, retryOn, timeoutMs) {
643
+ let lastError;
644
+ for (let i = 0; i <= maxRetries; i++) {
645
+ try {
646
+ const promise = fn();
647
+ if (timeoutMs && timeoutMs > 0) {
648
+ return await withTimeout(promise, timeoutMs);
649
+ }
650
+ return await promise;
651
+ } catch (err) {
652
+ if (err?.name === "GraphInterrupt") {
653
+ throw err;
654
+ }
655
+ lastError = err;
656
+ if (i === maxRetries) throw err;
657
+ if (retryOn?.length) {
658
+ const errName = err?.name ?? "";
659
+ if (!retryOn.includes(errName)) throw err;
660
+ }
661
+ }
662
+ }
663
+ throw lastError;
664
+ }
665
+ function withTimeout(promise, ms) {
666
+ return Promise.race([
667
+ promise,
668
+ new Promise(
669
+ (_, reject) => setTimeout(() => reject(new Error(`Operation timed out after ${ms}ms`)), ms)
670
+ )
671
+ ]);
672
+ }
673
+ function createAgentNode(node, resolveAgent, trackingStore) {
674
+ return async (state, config) => {
675
+ const runId = state._runId;
676
+ const tenantId = config?.configurable?.tenantId ?? "default";
677
+ const startedAt = Date.now();
678
+ let stepId;
679
+ if (trackingStore && runId) {
680
+ trackingStore.updateWorkflowRun(runId, {
681
+ status: "running",
682
+ completedAt: null
683
+ }).catch(() => {
684
+ });
685
+ }
686
+ try {
687
+ console.log(`[WF][${node.id}] START "${node.name}" | hasSchema=${!!node.output?.schema}`);
688
+ const responseFormat = node.output?.schema;
689
+ console.log(`[WF][${node.id}] resolving agent...`);
690
+ const client = await resolveAgent(node.ref, responseFormat, node.type);
691
+ console.log(`[WF][${node.id}] agent resolved, building input...`);
692
+ const input = buildInput(
693
+ node.input,
694
+ state,
695
+ void 0,
696
+ responseFormat ? void 0 : node.output?.schema
697
+ );
698
+ const renderedInput = input.messages[0]?.content ?? "";
699
+ console.log(`[WF][${node.id}] === INPUT (full) ===
700
+ ${renderedInput}
701
+ === END INPUT ===`);
702
+ if (trackingStore && runId) {
703
+ const step = await trackingStore.upsertRunStep({
704
+ runId,
705
+ tenantId,
706
+ stepType: node.type,
707
+ stepName: node.name,
708
+ input: { template: node.input?.template, rendered: renderedInput }
709
+ }).catch((e) => {
710
+ console.warn("Failed to upsert run step:", e.message);
711
+ return null;
712
+ });
713
+ stepId = step?.id;
714
+ if (step && step.status === "interrupted") {
715
+ trackingStore.updateRunStep(runId, step.id, { status: "running" }).catch(() => {
716
+ });
717
+ }
718
+ }
719
+ const subConfig = {
720
+ ...config,
721
+ configurable: {
722
+ ...config?.configurable ?? {},
723
+ thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}`
724
+ }
725
+ };
726
+ let result;
727
+ try {
728
+ console.log(`[WF][${node.id}] invoking agent.invoke()...`);
729
+ result = await invokeWithRetry(
730
+ () => client.invoke(input, subConfig),
731
+ node.config?.maxRetries ?? 0,
732
+ node.config?.retryOn,
733
+ node.config?.timeout
734
+ );
735
+ console.log(`[WF][${node.id}] invoke SUCCESS, extracting output...`);
736
+ } catch (err) {
737
+ if (err?.name === "GraphInterrupt") {
738
+ if (trackingStore && runId && stepId) {
739
+ trackingStore.updateRunStep(runId, stepId, { status: "interrupted" }).catch(() => {
740
+ });
741
+ }
742
+ if (trackingStore && runId) {
743
+ trackingStore.updateWorkflowRun(runId, { status: "interrupted", completedAt: null }).catch(() => {
744
+ });
745
+ }
746
+ throw err;
747
+ }
748
+ const errMsg = err?.message ?? "";
749
+ console.log(`[WF][${node.id}] invoke FAILED: ${errMsg}`);
750
+ if (responseFormat && (errMsg.includes("tool_choice") || errMsg.includes("thinking") || errMsg.includes("reasoning") || errMsg.includes("InvalidParameter"))) {
751
+ console.log(`[WF][${node.id}] attempting fallback (text-based schema injection)...`);
752
+ const fallbackClient = await resolveAgent(node.ref, void 0, node.type);
753
+ const fallbackInput = buildInput(node.input, state, void 0, responseFormat);
754
+ result = await invokeWithRetry(
755
+ () => fallbackClient.invoke(fallbackInput, subConfig),
756
+ node.config?.maxRetries ?? 0,
757
+ node.config?.retryOn,
758
+ node.config?.timeout
759
+ );
760
+ console.log(`[WF][${node.id}] fallback invoke SUCCESS`);
761
+ } else {
762
+ throw err;
763
+ }
764
+ }
765
+ const output = extractOutput(result);
766
+ console.log(`[WF][${node.id}] === OUTPUT (full) | key=${node.output?.key} ===
767
+ ${JSON.stringify(output, null, 2)}
768
+ === END OUTPUT ===`);
769
+ const update = { phase: node.id };
770
+ if (node.output?.key) {
771
+ update[node.output.key] = output;
772
+ }
773
+ const subMessages = result.messages;
774
+ if (subMessages && Array.isArray(subMessages)) {
775
+ const aiMessages = subMessages.filter((m) => {
776
+ const t = typeof m._getType === "function" ? m._getType() : m.role ?? m.type;
777
+ return t === "ai";
778
+ });
779
+ if (aiMessages.length > 0) {
780
+ update.messages = aiMessages;
781
+ }
782
+ }
783
+ console.log(`[WF][${node.id}] DONE (${Date.now() - startedAt}ms)`);
784
+ if (trackingStore && runId && stepId) {
785
+ trackingStore.updateRunStep(runId, stepId, {
786
+ status: "completed",
787
+ output,
788
+ completedAt: /* @__PURE__ */ new Date(),
789
+ durationMs: Date.now() - startedAt
790
+ }).catch((e) => {
791
+ console.warn("Failed to update run step:", e.message);
792
+ });
793
+ }
794
+ return update;
795
+ } catch (err) {
796
+ if (err?.name === "GraphInterrupt") {
797
+ throw err;
798
+ }
799
+ if (trackingStore && runId) {
800
+ if (stepId) {
801
+ trackingStore.updateRunStep(runId, stepId, {
802
+ status: "failed",
803
+ errorMessage: err.message,
804
+ completedAt: /* @__PURE__ */ new Date(),
805
+ durationMs: Date.now() - startedAt
806
+ }).catch((e) => {
807
+ console.warn("Failed to update run step:", e.message);
808
+ });
809
+ }
810
+ trackingStore.updateWorkflowRun(runId, {
811
+ status: "failed",
812
+ errorMessage: err.message,
813
+ completedAt: /* @__PURE__ */ new Date()
814
+ }).catch((e) => {
815
+ console.warn("Failed to finalize WorkflowRun:", e.message);
816
+ });
817
+ }
818
+ throw err;
819
+ }
820
+ };
821
+ }
822
+ function createHumanFeedbackNode(node, resolveAgent, trackingStore) {
823
+ return async (state, config) => {
824
+ const runId = state._runId;
825
+ const tenantId = config?.configurable?.tenantId ?? "default";
826
+ const startedAt = Date.now();
827
+ let stepId;
828
+ if (trackingStore && runId) {
829
+ trackingStore.updateWorkflowRun(runId, {
830
+ status: "running",
831
+ completedAt: null
832
+ }).catch(() => {
833
+ });
834
+ }
835
+ try {
836
+ console.log(`[WF][${node.id}] HUMAN_FEEDBACK START "${node.config?.title || node.name}"`);
837
+ const responseFormat = node.output?.schema;
838
+ const client = await resolveAgent(void 0, responseFormat, node.type);
839
+ console.log(`[WF][${node.id}] agent resolved, building input...`);
840
+ const input = buildInput(
841
+ node.input,
842
+ state,
843
+ void 0,
844
+ responseFormat ? void 0 : node.output?.schema
845
+ );
846
+ const humanContent = input.messages[0]?.content ?? "";
847
+ input.messages = [
848
+ new import_messages6.SystemMessage(
849
+ `Follow this exact procedure. Do NOT skip any step.
850
+
851
+ STEP 1: Read the prompt. It contains content to present to the user and a question to ask.
852
+
853
+ STEP 2: Call ask_user_to_clarify. Your question text MUST contain the ACTUAL content from the prompt \u2014 copy-paste the relevant text, data, or facts directly into the question. A question like "Do you approve this recommendation?" is WRONG because the user has no idea what the recommendation says. Instead: "Do you approve this recommendation: [paste the actual recommendation text here]?"
854
+
855
+ STEP 3: The tool will pause. The user will see your questions and respond. You will receive their answers.
856
+
857
+ STEP 4: Based on the user's answers, produce your final output.`
858
+ ),
859
+ ...input.messages
860
+ ];
861
+ const renderedInput = humanContent;
862
+ if (trackingStore && runId) {
863
+ const step = await trackingStore.upsertRunStep({
864
+ runId,
865
+ tenantId,
866
+ stepType: node.type,
867
+ stepName: node.name,
868
+ input: { template: node.input?.template, rendered: renderedInput }
869
+ }).catch((e) => {
870
+ console.warn("Failed to upsert run step:", e.message);
871
+ return null;
872
+ });
873
+ stepId = step?.id;
874
+ if (step && step.status === "interrupted") {
875
+ trackingStore.updateRunStep(runId, step.id, { status: "running" }).catch(() => {
876
+ });
877
+ }
878
+ }
879
+ const subConfig = {
880
+ ...config,
881
+ configurable: {
882
+ ...config?.configurable ?? {},
883
+ thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}`
884
+ }
885
+ };
886
+ console.log(`[WF][${node.id}] === INPUT (full) ===
887
+ ${renderedInput}
888
+ === END INPUT ===`);
889
+ const result = await invokeWithRetry(
890
+ () => client.invoke(input, subConfig),
891
+ node.config?.maxRetries ?? 0,
892
+ node.config?.retryOn,
893
+ node.config?.timeout
894
+ );
895
+ console.log(`[WF][${node.id}] invoke SUCCESS, extracting output...`);
896
+ const output = extractOutput(result);
897
+ console.log(`[WF][${node.id}] === OUTPUT (full) | key=${node.output?.key} ===
898
+ ${JSON.stringify(output, null, 2)}
899
+ === END OUTPUT ===`);
900
+ const update = { phase: node.id };
901
+ if (node.output?.key) {
902
+ update[node.output.key] = output;
903
+ }
904
+ if (output && typeof output === "object" && !Array.isArray(output)) {
905
+ Object.assign(update, output);
906
+ }
907
+ const subMessages = result.messages;
908
+ if (subMessages && Array.isArray(subMessages)) {
909
+ const aiMessages = subMessages.filter((m) => {
910
+ const t = typeof m._getType === "function" ? m._getType() : m.role ?? m.type;
911
+ return t === "ai";
912
+ });
913
+ if (aiMessages.length > 0) {
914
+ update.messages = aiMessages;
915
+ }
916
+ }
917
+ console.log(`[WF][${node.id}] DONE (${Date.now() - startedAt}ms)`);
918
+ if (trackingStore && runId && stepId) {
919
+ trackingStore.updateRunStep(runId, stepId, {
920
+ status: "completed",
921
+ output,
922
+ completedAt: /* @__PURE__ */ new Date(),
923
+ durationMs: Date.now() - startedAt
924
+ }).catch((e) => {
925
+ console.warn("Failed to update run step:", e.message);
926
+ });
927
+ }
928
+ return update;
929
+ } catch (err) {
930
+ if (err?.name === "GraphInterrupt") {
931
+ if (trackingStore && runId && stepId) {
932
+ trackingStore.updateRunStep(runId, stepId, {
933
+ status: "interrupted"
934
+ }).catch(() => {
935
+ });
936
+ }
937
+ if (trackingStore && runId) {
938
+ trackingStore.updateWorkflowRun(runId, {
939
+ status: "interrupted",
940
+ completedAt: null
941
+ }).catch(() => {
942
+ });
943
+ }
944
+ throw err;
945
+ }
946
+ if (trackingStore && runId) {
947
+ if (stepId) {
948
+ trackingStore.updateRunStep(runId, stepId, {
949
+ status: "failed",
950
+ errorMessage: err.message,
951
+ completedAt: /* @__PURE__ */ new Date(),
952
+ durationMs: Date.now() - startedAt
953
+ }).catch((e) => {
954
+ console.warn("Failed to update run step:", e.message);
955
+ });
956
+ }
957
+ trackingStore.updateWorkflowRun(runId, {
958
+ status: "failed",
959
+ errorMessage: err.message,
960
+ completedAt: /* @__PURE__ */ new Date()
961
+ }).catch((e) => {
962
+ console.warn("Failed to finalize WorkflowRun:", e.message);
963
+ });
964
+ }
965
+ throw err;
966
+ }
967
+ };
968
+ }
969
+ function createMapNode(node, resolveAgent, trackingStore) {
970
+ return async (state, config) => {
971
+ const runId = state._runId;
972
+ const tenantId = config?.configurable?.tenantId ?? "default";
973
+ const startedAt = Date.now();
974
+ let stepId;
975
+ if (trackingStore && runId) {
976
+ trackingStore.updateWorkflowRun(runId, {
977
+ status: "running",
978
+ completedAt: null
979
+ }).catch(() => {
980
+ });
981
+ }
982
+ try {
983
+ const items = resolvePath(state, node.source);
984
+ if (trackingStore && runId) {
985
+ const step = await trackingStore.upsertRunStep({
986
+ runId,
987
+ tenantId,
988
+ stepType: node.type,
989
+ stepName: node.name,
990
+ input: { source: node.source, itemCount: Array.isArray(items) ? items.length : 0 }
991
+ }).catch((e) => {
992
+ console.warn("Failed to upsert run step:", e.message);
993
+ return null;
994
+ });
995
+ stepId = step?.id;
996
+ if (step && step.status === "interrupted") {
997
+ trackingStore.updateRunStep(runId, step.id, { status: "running" }).catch(() => {
998
+ });
999
+ }
1000
+ }
1001
+ if (!Array.isArray(items)) {
1002
+ throw new Error(
1003
+ `Map source "${node.source}" resolved to ${typeof items}, expected array`
1004
+ );
1005
+ }
1006
+ const batchSize = node.config?.batchSize ?? 50;
1007
+ const maxConcurrency = node.config?.maxConcurrency ?? 10;
1008
+ const innerConcurrency = node.config?.innerConcurrency ?? 5;
1009
+ const itemKey = node.itemKey ?? "item";
1010
+ const innerClient = await resolveAgent(node.node.ref, node.node.schema, node.type);
1011
+ const batches = chunk(items, batchSize);
1012
+ const batchResults = await parallelLimit(batches, maxConcurrency, async (batch) => {
1013
+ const itemResults = await parallelLimit(batch, innerConcurrency, async (item, itemIdx) => {
1014
+ const itemCtx = { [itemKey]: item };
1015
+ const input = buildInput(node.node.input, state, itemCtx);
1016
+ const subConfig = {
1017
+ ...config,
1018
+ configurable: {
1019
+ ...config?.configurable ?? {},
1020
+ thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}:item:${itemIdx}`
1021
+ }
1022
+ };
1023
+ const result = await invokeWithRetry(
1024
+ () => innerClient.invoke(input, subConfig),
1025
+ node.config?.maxRetries ?? 0,
1026
+ node.config?.retryOn,
1027
+ node.config?.timeout
1028
+ );
1029
+ return extractOutput(result);
1030
+ });
1031
+ return itemResults;
1032
+ });
1033
+ const allResults = batchResults.flat();
1034
+ let finalOutput = allResults;
1035
+ if (node.reduce) {
1036
+ const reduceClient = await resolveAgent(node.reduce.ref, node.reduce.schema, node.type);
1037
+ const tempResultsKey = node.output?.key ?? `${node.id}_results`;
1038
+ const tempState = { ...state, [tempResultsKey]: allResults };
1039
+ const reduceInput = buildInput(node.reduce.input, tempState);
1040
+ const reduceResult = await invokeWithRetry(
1041
+ () => reduceClient.invoke(reduceInput, {
1042
+ ...config,
1043
+ configurable: {
1044
+ ...config?.configurable ?? {},
1045
+ thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}:reduce`
1046
+ }
1047
+ }),
1048
+ node.config?.maxRetries ?? 0,
1049
+ node.config?.retryOn,
1050
+ node.config?.timeout
1051
+ );
1052
+ finalOutput = extractOutput(reduceResult);
1053
+ }
1054
+ const update = { phase: node.id };
1055
+ if (node.output?.key) {
1056
+ update[node.output.key] = finalOutput;
1057
+ }
1058
+ if (trackingStore && runId && stepId) {
1059
+ trackingStore.updateRunStep(runId, stepId, {
1060
+ status: "completed",
1061
+ output: finalOutput,
1062
+ completedAt: /* @__PURE__ */ new Date(),
1063
+ durationMs: Date.now() - startedAt
1064
+ }).catch((e) => {
1065
+ console.warn("Failed to update run step:", e.message);
1066
+ });
1067
+ }
1068
+ return update;
1069
+ } catch (err) {
1070
+ if (err?.name === "GraphInterrupt") {
1071
+ if (trackingStore && runId && stepId) {
1072
+ trackingStore.updateRunStep(runId, stepId, { status: "interrupted" }).catch(() => {
1073
+ });
1074
+ }
1075
+ if (trackingStore && runId) {
1076
+ trackingStore.updateWorkflowRun(runId, { status: "interrupted", completedAt: null }).catch(() => {
1077
+ });
1078
+ }
1079
+ throw err;
1080
+ }
1081
+ console.error(`[WF][${node.id}] FAILED after ${Date.now() - startedAt}ms:`, err.stack || err.message);
1082
+ if (trackingStore && runId) {
1083
+ if (stepId) {
1084
+ trackingStore.updateRunStep(runId, stepId, {
1085
+ status: "failed",
1086
+ errorMessage: err.message,
1087
+ completedAt: /* @__PURE__ */ new Date(),
1088
+ durationMs: Date.now() - startedAt
1089
+ }).catch(() => {
1090
+ });
1091
+ }
1092
+ trackingStore.updateWorkflowRun(runId, {
1093
+ status: "failed",
1094
+ errorMessage: err.message,
1095
+ completedAt: /* @__PURE__ */ new Date()
1096
+ }).catch(() => {
1097
+ });
1098
+ }
1099
+ throw err;
1100
+ }
1101
+ };
1102
+ }
1103
+ function createInputNode(node, trackingStore) {
1104
+ return async (state, config) => {
1105
+ const tenantId = config?.configurable?.tenantId ?? "default";
1106
+ const threadId = config?.configurable?.thread_id ?? "default";
1107
+ const assistantId = config?.configurable?.assistantId || config?.configurable?.assistant_id || "unknown";
1108
+ const messages = state.messages;
1109
+ const humanMsg = messages?.find((m) => m._getType() === "human");
1110
+ const inputText = typeof humanMsg?.content === "string" ? humanMsg.content : JSON.stringify(humanMsg?.content ?? "");
1111
+ console.log(`[WF][n_input] input captured: "${inputText.slice(0, 200)}"`);
1112
+ const update = { phase: node.id };
1113
+ if (node.output?.key) update[node.output.key] = inputText;
1114
+ if (trackingStore && !state._runId) {
1115
+ try {
1116
+ const run = await trackingStore.createWorkflowRun({
1117
+ tenantId,
1118
+ assistantId,
1119
+ threadId,
1120
+ topologyEdges: [],
1121
+ metadata: { workflowName: node.name }
1122
+ });
1123
+ update._runId = run.id;
1124
+ await trackingStore.createRunStep({
1125
+ runId: run.id,
1126
+ tenantId,
1127
+ stepType: node.type,
1128
+ stepName: node.name,
1129
+ input: { rendered: inputText }
1130
+ }).catch((e) => {
1131
+ console.warn("Failed to create input run step:", e.message);
1132
+ });
1133
+ } catch (e) {
1134
+ console.warn("Failed to create workflow run:", e.message);
1135
+ }
1136
+ }
1137
+ return update;
1138
+ };
1139
+ }
1140
+ function terminalStatusToRunStatus(status) {
1141
+ switch (status) {
1142
+ case "failed":
1143
+ return "failed";
1144
+ case "cancelled":
1145
+ return "cancelled";
1146
+ case "success":
1147
+ default:
1148
+ return "completed";
1149
+ }
1150
+ }
1151
+ function createTerminalNode(node, trackingStore) {
1152
+ const runStatus = terminalStatusToRunStatus(node.status);
1153
+ return async (state) => {
1154
+ const runId = state._runId;
1155
+ if (trackingStore && runId) {
1156
+ try {
1157
+ await trackingStore.updateWorkflowRun(runId, {
1158
+ status: runStatus,
1159
+ completedAt: /* @__PURE__ */ new Date()
1160
+ });
1161
+ } catch (e) {
1162
+ console.warn(`[WF][terminal] Failed to finalize WorkflowRun "${runId}":`, e.message);
1163
+ }
1164
+ try {
1165
+ await trackingStore.createRunStep({
1166
+ runId,
1167
+ tenantId: state._tenantId ?? "default",
1168
+ stepType: "terminal",
1169
+ stepName: node.name,
1170
+ input: { status: node.status }
1171
+ });
1172
+ } catch (e) {
1173
+ console.warn(`[WF][terminal] Failed to create terminal RunStep:`, e.message);
1174
+ }
1175
+ }
1176
+ return {
1177
+ status: node.status,
1178
+ phase: node.id
1179
+ };
1180
+ };
1181
+ }
1182
+ function createNodeHandler(node, resolveAgent, trackingStore) {
1183
+ switch (node.type) {
1184
+ case "agent":
1185
+ return createAgentNode(node, resolveAgent, trackingStore);
1186
+ case "human_feedback":
1187
+ return createHumanFeedbackNode(node, resolveAgent, trackingStore);
1188
+ case "map":
1189
+ return createMapNode(node, resolveAgent, trackingStore);
1190
+ case "terminal":
1191
+ return createTerminalNode(node, trackingStore);
1192
+ case "input":
1193
+ return createInputNode(node, trackingStore);
1194
+ default:
1195
+ throw new Error(`Unknown node type: ${node.type}`);
1196
+ }
1197
+ }
1198
+ function chunk(arr, size) {
1199
+ const result = [];
1200
+ for (let i = 0; i < arr.length; i += size) {
1201
+ result.push(arr.slice(i, i + size));
1202
+ }
1203
+ return result;
1204
+ }
1205
+ var import_langgraph15, import_messages6;
1206
+ var init_utils = __esm({
1207
+ "src/workflow/utils.ts"() {
1208
+ "use strict";
1209
+ import_langgraph15 = require("@langchain/langgraph");
1210
+ import_messages6 = require("@langchain/core/messages");
1211
+ }
1212
+ });
1213
+
1214
+ // src/workflow/normalize.ts
1215
+ function uid(prefix) {
1216
+ return `${prefix}_${_counter++}`;
1217
+ }
1218
+ function nodeId(stepId) {
1219
+ return `n_${stepId}`;
1220
+ }
1221
+ function translate(template) {
1222
+ return template.replace(/\{\{([^}]+)\}\}/g, (_m, expr) => {
1223
+ const t = expr.trim();
1224
+ if (t === "item") return "${item}";
1225
+ return `\${state.${t}}`;
1226
+ });
1227
+ }
1228
+ function inferFieldType(id) {
1229
+ if (/s$|list|array|items|results/i.test(id)) return { type: "array", default: [] };
1230
+ return { type: "string" };
1231
+ }
1232
+ function expandStep(step) {
1233
+ switch (step.type ?? "agent") {
1234
+ case "agent":
1235
+ return expandAgent(step);
1236
+ case "human":
1237
+ return expandHuman(step);
1238
+ case "condition":
1239
+ return expandCondition(step);
1240
+ case "map":
1241
+ return expandMap(step);
1242
+ case "parallel":
1243
+ return expandParallel(step);
1244
+ case "end":
1245
+ return expandEnd(step);
1246
+ }
1247
+ }
1248
+ function validateSchema(schema, stepId) {
1249
+ if (schema.type !== "object") {
1250
+ throw new Error(
1251
+ `Step "${stepId}": schema.type must be "object", got "${String(schema.type)}". Use standard JSON Schema: { "type": "object", "properties": { ... } }`
1252
+ );
1253
+ }
1254
+ if (!schema.properties || typeof schema.properties !== "object") {
1255
+ throw new Error(
1256
+ `Step "${stepId}": schema must have a "properties" object. Legacy shorthand like { "field": "string" } is not supported. Use: { "type": "object", "properties": { "field": { "type": "string" } } }`
1257
+ );
1258
+ }
1259
+ }
1260
+ function expandAgent(s) {
1261
+ const sid = s.id || uid("agent");
1262
+ const nid = nodeId(sid);
1263
+ if (s.schema !== void 0 && s.schema !== null) {
1264
+ if (typeof s.schema !== "object") {
1265
+ throw new Error(
1266
+ `Step "${sid}": schema must be a JSON Schema object, e.g. { "type": "object", "properties": { ... } }. Got ${typeof s.schema} (${JSON.stringify(s.schema)}).`
1267
+ );
1268
+ }
1269
+ validateSchema(s.schema, sid);
1270
+ }
1271
+ const schema = s.schema && typeof s.schema === "object" ? s.schema : void 0;
1272
+ console.log(`[WF EXPAND] agent step id="${sid}" nodeId="${nid}" | hasSchema=${!!schema}`);
1273
+ return {
1274
+ nodes: [{ id: nid, type: "agent", name: sid, input: { template: translate(s.prompt) }, output: { key: sid, ...schema ? { schema } : {} } }],
1275
+ edges: [],
1276
+ entryId: nid,
1277
+ exitIds: [nid]
1278
+ };
1279
+ }
1280
+ function expandHuman(s) {
1281
+ const sid = s.id || uid("human");
1282
+ const nid = nodeId(sid);
1283
+ if (s.schema !== void 0 && s.schema !== null) {
1284
+ if (typeof s.schema !== "object") {
1285
+ throw new Error(
1286
+ `Step "${sid}": schema must be a JSON Schema object, e.g. { "type": "object", "properties": { ... } }. Got ${typeof s.schema} (${JSON.stringify(s.schema)}).`
1287
+ );
1288
+ }
1289
+ validateSchema(s.schema, sid);
1290
+ }
1291
+ const schema = s.schema && typeof s.schema === "object" ? s.schema : void 0;
1292
+ return {
1293
+ nodes: [{ id: nid, type: "human_feedback", name: sid, config: { title: s.title ?? sid }, input: { template: translate(s.prompt) }, output: { key: sid, ...schema ? { schema } : {} } }],
1294
+ edges: [],
1295
+ entryId: nid,
1296
+ exitIds: [nid]
1297
+ };
1298
+ }
1299
+ function expandCondition(s) {
1300
+ const sid = s.id || uid("cond");
1301
+ const nid = nodeId(sid);
1302
+ if (s.branches) {
1303
+ const branchExps = {};
1304
+ for (const [key, steps] of Object.entries(s.branches)) {
1305
+ branchExps[key] = expandSteps(Array.isArray(steps) ? steps : [steps]);
1306
+ }
1307
+ const allNodes = Object.values(branchExps).flatMap((e) => e.nodes);
1308
+ const allEdges = Object.values(branchExps).flatMap((e) => e.edges);
1309
+ const allExitIds = [...new Set(Object.values(branchExps).flatMap((e) => e.exitIds))];
1310
+ const branchEntryIds = Object.fromEntries(
1311
+ Object.entries(branchExps).map(([k, v]) => [k, v.entryId])
1312
+ );
1313
+ return {
1314
+ nodes: allNodes,
1315
+ edges: allEdges,
1316
+ entryId: nid,
1317
+ exitIds: allExitIds,
1318
+ branchEntryIds
1319
+ };
1320
+ }
1321
+ if (!s.then) {
1322
+ throw new Error(`Condition step "${sid}": must have either "then" or "branches"`);
1323
+ }
1324
+ const thenSteps = Array.isArray(s.then) ? s.then : [s.then];
1325
+ const elseSteps = s.else ? Array.isArray(s.else) ? s.else : [s.else] : [];
1326
+ const thenExp = expandSteps(thenSteps);
1327
+ const elseExp = expandSteps(elseSteps);
1328
+ return {
1329
+ nodes: [...thenExp.nodes, ...elseExp.nodes],
1330
+ edges: [...thenExp.edges, ...elseExp.edges],
1331
+ entryId: nid,
1332
+ exitIds: [...thenExp.exitIds, ...elseExp.exitIds],
1333
+ thenEntryId: thenExp.entryId,
1334
+ elseEntryId: elseExp.entryId
1335
+ };
1336
+ }
1337
+ function expandMap(s) {
1338
+ const sid = s.id;
1339
+ const nid = nodeId(sid);
1340
+ const inner = s.each;
1341
+ return {
1342
+ nodes: [{
1343
+ id: nid,
1344
+ type: "map",
1345
+ name: sid,
1346
+ source: `state.${s.source}`,
1347
+ itemKey: "item",
1348
+ config: { batchSize: s.batch ?? 50, maxConcurrency: s.concurrency ?? 5, innerConcurrency: s.concurrency ?? 5 },
1349
+ node: { type: "agent", input: inner.prompt ? { template: translate(inner.prompt) } : void 0, ...inner.schema && typeof inner.schema === "object" ? { schema: inner.schema } : {} },
1350
+ ...s.reduce ? { reduce: { input: s.reduce.prompt ? { template: translate(s.reduce.prompt) } : void 0, ...s.reduce.schema && typeof s.reduce.schema === "object" ? { schema: s.reduce.schema } : {} } } : {},
1351
+ output: { key: sid }
1352
+ }],
1353
+ edges: [],
1354
+ entryId: nid,
1355
+ exitIds: [nid]
1356
+ };
1357
+ }
1358
+ function expandParallel(s) {
1359
+ const nodes = [];
1360
+ const edges = [];
1361
+ const entryIds = [];
1362
+ const exitIds = [];
1363
+ for (const step of s.steps) {
1364
+ const exp = expandStep(step);
1365
+ nodes.push(...exp.nodes);
1366
+ edges.push(...exp.edges);
1367
+ entryIds.push(exp.entryId);
1368
+ if (exp.exitIds.length > 0) exitIds.push(...exp.exitIds);
1369
+ }
1370
+ return { nodes, edges, entryId: entryIds[0], exitIds };
1371
+ }
1372
+ function expandEnd(s) {
1373
+ const sid = uid("end");
1374
+ const nid = nodeId(sid);
1375
+ return { nodes: [{ id: nid, type: "terminal", name: sid, status: s.status ?? "success" }], edges: [], entryId: nid, exitIds: [] };
1376
+ }
1377
+ function expandSteps(steps, fromStart = false) {
1378
+ if (steps.length === 0) return { nodes: [], edges: [], entryId: "END", exitIds: ["END"] };
1379
+ const allNodes = [];
1380
+ const allEdges = [];
1381
+ let prevExitIds = [];
1382
+ let firstEntryId = null;
1383
+ for (let i = 0; i < steps.length; i++) {
1384
+ const exp = expandStep(steps[i]);
1385
+ if (exp.nodes.length > 0) allNodes.push(...exp.nodes);
1386
+ if (exp.edges.length > 0) allEdges.push(...exp.edges);
1387
+ if (firstEntryId === null) firstEntryId = exp.entryId;
1388
+ if (prevExitIds.length > 0) addEdge(steps[i], exp, prevExitIds, allEdges);
1389
+ else if (fromStart && i === 0) addEdge(steps[i], exp, ["START"], allEdges);
1390
+ prevExitIds = exp.exitIds.length > 0 ? exp.exitIds : prevExitIds;
1391
+ }
1392
+ return { nodes: allNodes, edges: allEdges, entryId: firstEntryId || "END", exitIds: prevExitIds };
1393
+ }
1394
+ function toSafeStateExpr(expr) {
1395
+ const match = expr.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)/);
1396
+ if (!match) return `state.${expr}`;
1397
+ const field = match[0];
1398
+ const rest = expr.slice(field.length);
1399
+ return `state["${field}"]${rest}`;
1400
+ }
1401
+ function addEdge(step, exp, fromIds, allEdges) {
1402
+ if (step.type === "condition") {
1403
+ const s = step;
1404
+ if (s.if.includes("{{")) {
1405
+ throw new Error(
1406
+ `Condition step "${s.id || "unnamed"}": the \`if\` field contains "{{". Use a plain state field name or JavaScript expression (e.g. "intent", "score >= 60"). Template markers {{...}} are only for \`prompt\` fields, not \`if\`. Found: "${s.if}"`
1407
+ );
1408
+ }
1409
+ if (s.branches) {
1410
+ const condExp = exp;
1411
+ const exprCode = toSafeStateExpr(s.if);
1412
+ const mapping = {};
1413
+ for (const [key, branchId] of Object.entries(condExp.branchEntryIds)) {
1414
+ if (branchId) mapping[key] = branchId;
1415
+ }
1416
+ for (const fromId of fromIds) allEdges.push({ from: fromId, type: "conditional", rule: { type: "expression", code: exprCode, mapping } });
1417
+ } else {
1418
+ const condExp = exp;
1419
+ const exprCode = `${toSafeStateExpr(s.if)} ? 'then' : 'else'`;
1420
+ const mapping = {};
1421
+ if (condExp.thenEntryId) mapping.then = condExp.thenEntryId;
1422
+ if (condExp.elseEntryId) mapping.else = condExp.elseEntryId;
1423
+ for (const fromId of fromIds) allEdges.push({ from: fromId, type: "conditional", rule: { type: "expression", code: exprCode, mapping } });
1424
+ }
1425
+ } else if (step.type === "parallel") {
1426
+ for (const fromId of fromIds) {
1427
+ for (const sub of step.steps) allEdges.push({ from: fromId, to: expandStep(sub).entryId });
1428
+ }
1429
+ } else {
1430
+ for (const fromId of fromIds) allEdges.push({ from: fromId, to: exp.entryId });
1431
+ }
1432
+ }
1433
+ function collectIds(steps) {
1434
+ const ids = [];
1435
+ function walk(s) {
1436
+ const id = s.type === "condition" ? s.id || uid("cond") : s.type === "parallel" ? s.id || uid("par") : s.type === "end" ? uid("end") : s.id || s.id || uid("human");
1437
+ if (s.type !== "end" && s.type !== "condition") ids.push(id);
1438
+ if (s.type === "condition") {
1439
+ const c = s;
1440
+ if (c.branches) {
1441
+ for (const steps2 of Object.values(c.branches)) {
1442
+ (Array.isArray(steps2) ? steps2 : [steps2]).forEach(walk);
1443
+ }
1444
+ } else {
1445
+ (Array.isArray(c.then) ? c.then : [c.then]).forEach(walk);
1446
+ if (c.else) (Array.isArray(c.else) ? c.else : [c.else]).forEach(walk);
1447
+ }
1448
+ }
1449
+ if (s.type === "parallel") s.steps.forEach(walk);
1450
+ }
1451
+ steps.forEach(walk);
1452
+ return [...new Set(ids)];
1453
+ }
1454
+ function collectSourceIds(steps) {
1455
+ const ids = [];
1456
+ function walk(s) {
1457
+ if (s.type === "map") ids.push(s.source);
1458
+ if (s.type === "condition") {
1459
+ const c = s;
1460
+ if (c.branches) {
1461
+ for (const steps2 of Object.values(c.branches)) {
1462
+ (Array.isArray(steps2) ? steps2 : [steps2]).forEach(walk);
1463
+ }
1464
+ } else {
1465
+ (Array.isArray(c.then) ? c.then : [c.then]).forEach(walk);
1466
+ if (c.else) (Array.isArray(c.else) ? c.else : [c.else]).forEach(walk);
1467
+ }
1468
+ }
1469
+ if (s.type === "parallel") s.steps.forEach(walk);
1470
+ }
1471
+ steps.forEach(walk);
1472
+ return [...new Set(ids)];
1473
+ }
1474
+ function expand(dsl) {
1475
+ _counter = 0;
1476
+ console.log(`[WF EXPAND] expanding workflow "${dsl.name}" | stepCount=${dsl.steps.length}`);
1477
+ const inputNode = {
1478
+ id: "n_input",
1479
+ type: "input",
1480
+ name: "input",
1481
+ output: { key: "input" }
1482
+ };
1483
+ const expanded = expandSteps(dsl.steps, true);
1484
+ const edges = expanded.entryId === "END" ? [{ from: "START", to: "n_input" }] : [
1485
+ ...expanded.edges.map((e) => ({ ...e, from: e.from === "START" ? "n_input" : e.from })),
1486
+ { from: "START", to: "n_input" }
1487
+ ];
1488
+ const nodes = [inputNode, ...expanded.nodes];
1489
+ const ids = collectIds(dsl.steps);
1490
+ const sourceIds = collectSourceIds(dsl.steps);
1491
+ const fields = { input: { type: "string" } };
1492
+ for (const id of ids) fields[id] = inferFieldType(id);
1493
+ for (const id of sourceIds) {
1494
+ if (!fields[id]) fields[id] = inferFieldType(id);
1495
+ }
1496
+ const result = { version: "1.0", name: dsl.name, state: { fields }, nodes, edges };
1497
+ console.log(`[WF EXPAND] done | nodeCount=${result.nodes.length} | nodeIds=[${result.nodes.map((n) => `${n.id}:${n.type}`).join(", ")}] | fieldIds=[${Object.keys(fields).join(", ")}]`);
1498
+ return result;
1499
+ }
1500
+ var _counter;
1501
+ var init_normalize = __esm({
1502
+ "src/workflow/normalize.ts"() {
1503
+ "use strict";
1504
+ _counter = 0;
1505
+ }
1506
+ });
1507
+
1508
+ // src/workflow/compile.ts
1509
+ var compile_exports = {};
1510
+ __export(compile_exports, {
1511
+ compileWorkflow: () => compileWorkflow,
1512
+ validateDSL: () => validateDSL
1513
+ });
1514
+ function compileWorkflow(dsl, resolveAgent, checkpointer, trackingStore) {
1515
+ console.log(`[WF COMPILE] compiling "${dsl.name}" | stepCount=${dsl.steps.length}`);
1516
+ const ir = expand(dsl);
1517
+ validateAndThrow(ir);
1518
+ console.log(`[WF COMPILE] validation passed`);
1519
+ const StateAnnotation = buildStateAnnotation(ir.state?.fields);
1520
+ const builder = new import_langgraph16.StateGraph(StateAnnotation);
1521
+ for (const node of ir.nodes) {
1522
+ console.log(`[WF COMPILE] registering node: id=${node.id} type=${node.type} name=${node.name}`);
1523
+ const handler = createNodeHandler(node, resolveAgent, trackingStore);
1524
+ builder.addNode(node.id, handler);
1525
+ }
1526
+ for (const node of ir.nodes) {
1527
+ if (node.type === "terminal") {
1528
+ builder.addEdge(node.id, import_langgraph16.END);
1529
+ }
1530
+ }
1531
+ for (const edge of ir.edges) {
1532
+ const from = edge.from === "START" ? import_langgraph16.START : edge.from;
1533
+ if (edge.type === "conditional") {
1534
+ if (!edge.rule) {
1535
+ throw new Error(`Conditional edge from "${edge.from}" has no rule`);
1536
+ }
1537
+ const router = buildRouter(edge.rule);
1538
+ builder.addConditionalEdges(from, router, edge.rule.mapping);
1539
+ } else {
1540
+ const targets = Array.isArray(edge.to) ? edge.to : [edge.to];
1541
+ for (const to of targets) {
1542
+ builder.addEdge(from, to === "END" ? import_langgraph16.END : to);
1543
+ }
1544
+ }
1545
+ }
1546
+ const graph = builder.compile({ checkpointer, name: ir.name });
1547
+ console.log(`[WF COMPILE] graph compiled successfully, ready to run`);
1548
+ return graph;
1549
+ }
1550
+ function validateDSL(dsl) {
1551
+ const errors = [];
1552
+ const nodeIds = /* @__PURE__ */ new Set();
1553
+ for (const node of dsl.nodes) {
1554
+ if (nodeIds.has(node.id)) {
1555
+ errors.push({ type: "error", message: `Duplicate node id "${node.id}"` });
1556
+ }
1557
+ nodeIds.add(node.id);
1558
+ }
1559
+ const terminalIds = new Set(
1560
+ dsl.nodes.filter((n) => n.type === "terminal").map((n) => n.id)
1561
+ );
1562
+ const declaredFields = new Set(Object.keys(dsl.state?.fields ?? {}));
1563
+ for (const edge of dsl.edges) {
1564
+ if (edge.from !== "START" && !nodeIds.has(edge.from)) {
1565
+ errors.push({ type: "error", message: `Edge from "${edge.from}" references unknown node` });
1566
+ }
1567
+ if (edge.from !== "START" && terminalIds.has(edge.from)) {
1568
+ errors.push({ type: "error", message: `Terminal node "${edge.from}" cannot have outgoing edges` });
1569
+ }
1570
+ const targets = Array.isArray(edge.to) ? edge.to : edge.to ? [edge.to] : [];
1571
+ for (const to of targets) {
1572
+ if (to !== "END" && !nodeIds.has(to)) {
1573
+ errors.push({ type: "error", message: `Edge to "${to}" references unknown node` });
1574
+ }
1575
+ }
1576
+ if (edge.type === "conditional" && edge.rule) {
1577
+ for (const targetId of Object.values(edge.rule.mapping)) {
1578
+ if (targetId !== "END" && !nodeIds.has(targetId)) {
1579
+ errors.push({ type: "error", message: `Conditional edge mapping references unknown node "${targetId}"` });
1580
+ }
1581
+ }
1582
+ if (edge.rule.type === "state_field" && edge.rule.field) {
1583
+ if (!declaredFields.has(edge.rule.field)) {
1584
+ errors.push({ type: "warning", message: `Conditional edge reads "${edge.rule.field}" but it is not declared in state.fields` });
1585
+ }
1586
+ }
1587
+ }
1588
+ }
1589
+ for (const node of dsl.nodes) {
1590
+ if (node.type === "terminal") {
1591
+ const hasIncoming = dsl.edges.some((e) => {
1592
+ const targets = Array.isArray(e.to) ? e.to : e.to ? [e.to] : [];
1593
+ return targets.includes(node.id) || e.type === "conditional" && e.rule && Object.values(e.rule.mapping).includes(node.id);
1594
+ });
1595
+ if (!hasIncoming) {
1596
+ errors.push({ type: "warning", message: `Terminal node "${node.id}" has no incoming edge` });
1597
+ }
1598
+ }
1599
+ }
1600
+ return errors;
1601
+ }
1602
+ function validateAndThrow(dsl) {
1603
+ const errors = validateDSL(dsl);
1604
+ const critical = errors.filter((e) => e.type === "error");
1605
+ if (critical.length > 0) {
1606
+ throw new Error(critical.map((e) => e.message).join("; "));
1607
+ }
1608
+ }
1609
+ function buildRouter(rule) {
1610
+ if (rule.type === "state_field") {
1611
+ if (!rule.field) throw new Error("state_field rule requires a field name");
1612
+ return (state) => {
1613
+ const value = resolvePath(state, `state.${rule.field}`);
1614
+ const key = String(value);
1615
+ if (rule.mapping[key] !== void 0) return key;
1616
+ if (rule.mapping["default"] !== void 0) return "default";
1617
+ throw new Error(
1618
+ `Conditional router produced key "${key}" (from field "${rule.field}"), but it is not in mapping: ${JSON.stringify(Object.keys(rule.mapping))}`
1619
+ );
1620
+ };
1621
+ }
1622
+ if (rule.type === "expression") {
1623
+ if (!rule.code) throw new Error("expression rule requires code");
1624
+ const fn = new Function("state", `return ${rule.code}`);
1625
+ return (state) => {
1626
+ const value = fn(state);
1627
+ const key = String(value);
1628
+ if (rule.mapping[key] !== void 0) return key;
1629
+ if (rule.mapping["default"] !== void 0) return "default";
1630
+ throw new Error(
1631
+ `Conditional router produced key "${key}" (from expression "${rule.code}"), but it is not in mapping: ${JSON.stringify(Object.keys(rule.mapping))}`
1632
+ );
1633
+ };
1634
+ }
1635
+ throw new Error(`Unknown rule type: ${rule.type}`);
1636
+ }
1637
+ var import_langgraph16;
1638
+ var init_compile = __esm({
1639
+ "src/workflow/compile.ts"() {
1640
+ "use strict";
1641
+ import_langgraph16 = require("@langchain/langgraph");
1642
+ init_utils();
1643
+ init_normalize();
1644
+ }
1645
+ });
29
1646
 
30
1647
  // src/index.ts
31
1648
  var index_exports = {};
@@ -52,7 +1669,7 @@ __export(index_exports, {
52
1669
  EmbeddingsLatticeManager: () => EmbeddingsLatticeManager,
53
1670
  FileSystemSkillStore: () => FileSystemSkillStore,
54
1671
  FilesystemBackend: () => FilesystemBackend,
55
- HumanMessage: () => import_messages6.HumanMessage,
1672
+ HumanMessage: () => import_messages7.HumanMessage,
56
1673
  InMemoryA2AApiKeyStore: () => InMemoryA2AApiKeyStore,
57
1674
  InMemoryAssistantStore: () => InMemoryAssistantStore,
58
1675
  InMemoryBindingStore: () => InMemoryBindingStore,
@@ -111,21 +1728,28 @@ __export(index_exports, {
111
1728
  agentInstanceManager: () => agentInstanceManager,
112
1729
  agentLatticeManager: () => agentLatticeManager,
113
1730
  buildGrepResultsDict: () => buildGrepResultsDict,
1731
+ buildInput: () => buildInput,
114
1732
  buildNamedVolumeName: () => buildNamedVolumeName,
115
1733
  buildSandboxMetadataEnv: () => buildSandboxMetadataEnv,
116
1734
  buildSkillFile: () => buildSkillFile,
1735
+ buildStateAnnotation: () => buildStateAnnotation,
117
1736
  checkEmptyContent: () => checkEmptyContent,
118
1737
  clearEncryptionKeyCache: () => clearEncryptionKeyCache,
1738
+ compileWorkflow: () => compileWorkflow,
119
1739
  computeSandboxName: () => computeSandboxName,
120
1740
  configureStores: () => configureStores,
1741
+ createAgentNode: () => createAgentNode,
121
1742
  createAgentTeam: () => createAgentTeam,
122
1743
  createExecuteSqlQueryTool: () => createExecuteSqlQueryTool,
123
1744
  createFileData: () => createFileData,
1745
+ createHumanFeedbackNode: () => createHumanFeedbackNode,
124
1746
  createInfoSqlTool: () => createInfoSqlTool,
125
1747
  createListMetricsDataSourcesTool: () => createListMetricsDataSourcesTool,
126
1748
  createListMetricsServersTool: () => createListMetricsServersTool,
127
1749
  createListTablesSqlTool: () => createListTablesSqlTool,
1750
+ createMapNode: () => createMapNode,
128
1751
  createModelSelectorMiddleware: () => createModelSelectorMiddleware,
1752
+ createNodeHandler: () => createNodeHandler,
129
1753
  createProcessingAgent: () => createProcessingAgent,
130
1754
  createQueryCheckerSqlTool: () => createQueryCheckerSqlTool,
131
1755
  createQueryMetricDefinitionTool: () => createQueryMetricDefinitionTool,
@@ -138,6 +1762,7 @@ __export(index_exports, {
138
1762
  createSchedulerMiddleware: () => createSchedulerMiddleware,
139
1763
  createTeamMiddleware: () => createTeamMiddleware,
140
1764
  createTeammateTools: () => createTeammateTools,
1765
+ createTerminalNode: () => createTerminalNode,
141
1766
  createUnknownToolHandlerMiddleware: () => createUnknownToolHandlerMiddleware,
142
1767
  createWidgetMiddleware: () => createWidgetMiddleware,
143
1768
  decrypt: () => decrypt,
@@ -147,7 +1772,9 @@ __export(index_exports, {
147
1772
  ensureBuiltinAgentsForTenant: () => ensureBuiltinAgentsForTenant,
148
1773
  eventBus: () => eventBus,
149
1774
  eventBusDefault: () => event_bus_default,
1775
+ expand: () => expand,
150
1776
  extractFetcherError: () => extractFetcherError,
1777
+ extractOutput: () => extractOutput,
151
1778
  fileDataToString: () => fileDataToString,
152
1779
  formatContentWithLineNumbers: () => formatContentWithLineNumbers,
153
1780
  formatGrepMatches: () => formatGrepMatches,
@@ -157,323 +1784,88 @@ __export(index_exports, {
157
1784
  getAgentConfig: () => getAgentConfig,
158
1785
  getAllAgentConfigs: () => getAllAgentConfigs,
159
1786
  getAllBuiltInSkillMetas: () => getAllBuiltInSkillMetas,
160
- getAllToolDefinitions: () => getAllToolDefinitions,
161
- getBindingRegistry: () => getBindingRegistry,
162
- getBuiltInSkillContent: () => getBuiltInSkillContent,
163
- getBuiltInSkillMeta: () => getBuiltInSkillMeta,
164
- getBuiltInSkillNames: () => getBuiltInSkillNames,
165
- getCheckpointSaver: () => getCheckpointSaver,
166
- getChunkBuffer: () => getChunkBuffer,
167
- getEmbeddingsClient: () => getEmbeddingsClient,
168
- getEmbeddingsLattice: () => getEmbeddingsLattice,
169
- getEncryptionKey: () => getEncryptionKey,
170
- getLoggerLattice: () => getLoggerLattice,
171
- getModelLattice: () => getModelLattice,
172
- getNextCronTime: () => getNextCronTime,
173
- getQueueLattice: () => getQueueLattice,
174
- getSandBoxManager: () => getSandBoxManager,
175
- getScheduleLattice: () => getScheduleLattice,
176
- getStoreLattice: () => getStoreLattice,
177
- getToolClient: () => getToolClient,
178
- getToolDefinition: () => getToolDefinition,
179
- getToolLattice: () => getToolLattice,
180
- getVectorStoreClient: () => getVectorStoreClient,
181
- getVectorStoreLattice: () => getVectorStoreLattice,
182
- globSearchFiles: () => globSearchFiles,
183
- grepMatchesFromFiles: () => grepMatchesFromFiles,
184
- grepSearchFiles: () => grepSearchFiles,
185
- hasChunkBuffer: () => hasChunkBuffer,
186
- isBuiltInSkill: () => isBuiltInSkill,
187
- isUsingDefaultKey: () => isUsingDefaultKey,
188
- isValidCronExpression: () => isValidCronExpression,
189
- isValidSandboxName: () => isValidSandboxName,
190
- isValidSkillName: () => isValidSkillName,
191
- loggerLatticeManager: () => loggerLatticeManager,
192
- mcpManager: () => mcpManager,
193
- metricsServerManager: () => metricsServerManager,
194
- modelLatticeManager: () => modelLatticeManager,
195
- normalizeSandboxName: () => normalizeSandboxName,
196
- parseCronExpression: () => parseCronExpression,
197
- parseSkillFrontmatter: () => parseSkillFrontmatter,
198
- performStringReplacement: () => performStringReplacement,
199
- queueLatticeManager: () => queueLatticeManager,
200
- registerAgentLattice: () => registerAgentLattice,
201
- registerAgentLatticeWithTenant: () => registerAgentLatticeWithTenant,
202
- registerAgentLattices: () => registerAgentLattices,
203
- registerCheckpointSaver: () => registerCheckpointSaver,
204
- registerChunkBuffer: () => registerChunkBuffer,
205
- registerEmbeddingsLattice: () => registerEmbeddingsLattice,
206
- registerExistingTool: () => registerExistingTool,
207
- registerLoggerLattice: () => registerLoggerLattice,
208
- registerModelLattice: () => registerModelLattice,
209
- registerQueueLattice: () => registerQueueLattice,
210
- registerScheduleLattice: () => registerScheduleLattice,
211
- registerStoreLattice: () => registerStoreLattice,
212
- registerTeammateAgent: () => registerTeammateAgent,
213
- registerToolLattice: () => registerToolLattice,
214
- registerVectorStoreLattice: () => registerVectorStoreLattice,
215
- sandboxLatticeManager: () => sandboxLatticeManager,
216
- sanitizeToolCallId: () => sanitizeToolCallId,
217
- scheduleLatticeManager: () => scheduleLatticeManager,
218
- setBindingRegistry: () => setBindingRegistry,
219
- skillLatticeManager: () => skillLatticeManager,
220
- sqlDatabaseManager: () => sqlDatabaseManager,
221
- storeLatticeManager: () => storeLatticeManager,
222
- toolLatticeManager: () => toolLatticeManager,
223
- truncateIfTooLong: () => truncateIfTooLong,
224
- unregisterTeammateAgent: () => unregisterTeammateAgent,
225
- updateFileData: () => updateFileData,
226
- validateAgentInput: () => validateAgentInput,
227
- validateEncryptionKey: () => validateEncryptionKey,
228
- validatePath: () => validatePath,
229
- validateSkillName: () => validateSkillName,
230
- validateToolInput: () => validateToolInput,
231
- vectorStoreLatticeManager: () => vectorStoreLatticeManager
232
- });
233
- module.exports = __toCommonJS(index_exports);
234
-
235
- // src/base/BaseLatticeManager.ts
236
- var _BaseLatticeManager = class _BaseLatticeManager {
237
- /**
238
- * 受保护的构造函数,防止外部直接实例化
239
- */
240
- constructor() {
241
- }
242
- /**
243
- * 获取管理器实例(由子类实现)
244
- */
245
- static getInstance() {
246
- throw new Error("\u5FC5\u987B\u7531\u5B50\u7C7B\u5B9E\u73B0");
247
- }
248
- /**
249
- * 构造完整的键名,包含类型前缀和租户ID
250
- * @param tenantId 租户ID,全局共享使用 "default"
251
- * @param key 原始键名
252
- */
253
- getFullKey(tenantId, key) {
254
- return `${this.getLatticeType()}:${tenantId}:${key}`;
255
- }
256
- // ========== 带租户的新API ==========
257
- /**
258
- * 带租户的注册项目
259
- * @param tenantId 租户ID
260
- * @param key 项目键名(不含前缀)
261
- * @param item 项目实例
262
- */
263
- registerWithTenant(tenantId, key, item) {
264
- const fullKey = this.getFullKey(tenantId, key);
265
- if (_BaseLatticeManager.registry.has(fullKey)) {
266
- throw new Error(`\u9879\u76EE "${fullKey}" \u5DF2\u7ECF\u5B58\u5728\uFF0C\u65E0\u6CD5\u91CD\u590D\u6CE8\u518C`);
267
- }
268
- _BaseLatticeManager.registry.set(fullKey, item);
269
- }
270
- /**
271
- * 带租户的获取指定项目(同步)
272
- * @param tenantId 租户ID
273
- * @param key 项目键名(不含前缀)
274
- */
275
- getWithTenant(tenantId, key) {
276
- const fullKey = this.getFullKey(tenantId, key);
277
- return _BaseLatticeManager.registry.get(fullKey);
278
- }
279
- /**
280
- * 带租户的获取指定项目(异步,支持从store回退加载)
281
- * 如果内存中不存在且子类实现了loadItemFromStore,则尝试从store加载
282
- * @param tenantId 租户ID
283
- * @param key 项目键名(不含前缀)
284
- * @returns 项目实例,如果未找到则返回undefined
285
- */
286
- async getOrLoadWithTenant(tenantId, key) {
287
- const item = this.getWithTenant(tenantId, key);
288
- if (item !== void 0) {
289
- return item;
290
- }
291
- if (this.loadItemFromStore) {
292
- const loadedItem = await this.loadItemFromStore(tenantId, key);
293
- if (loadedItem !== void 0) {
294
- this.registerWithTenant(tenantId, key, loadedItem);
295
- return loadedItem;
296
- }
297
- }
298
- return void 0;
299
- }
300
- /**
301
- * 带租户的检查项目是否存在(同步)
302
- * @param tenantId 租户ID
303
- * @param key 项目键名(不含前缀)
304
- */
305
- hasWithTenant(tenantId, key) {
306
- const fullKey = this.getFullKey(tenantId, key);
307
- return _BaseLatticeManager.registry.has(fullKey);
308
- }
309
- /**
310
- * 带租户的检查项目是否存在(异步,支持从store回退加载)
311
- * 如果内存中不存在且子类实现了loadItemFromStore,则尝试从store加载
312
- * @param tenantId 租户ID
313
- * @param key 项目键名(不含前缀)
314
- * @returns 如果存在或能从store加载则返回true
315
- */
316
- async hasOrLoadWithTenant(tenantId, key) {
317
- if (this.hasWithTenant(tenantId, key)) {
318
- return true;
319
- }
320
- if (this.loadItemFromStore) {
321
- const loadedItem = await this.loadItemFromStore(tenantId, key);
322
- if (loadedItem !== void 0) {
323
- this.registerWithTenant(tenantId, key, loadedItem);
324
- return true;
325
- }
326
- }
327
- return false;
328
- }
329
- /**
330
- * 带租户的移除项目
331
- * @param tenantId 租户ID
332
- * @param key 项目键名(不含前缀)
333
- */
334
- removeWithTenant(tenantId, key) {
335
- const fullKey = this.getFullKey(tenantId, key);
336
- return _BaseLatticeManager.registry.delete(fullKey);
337
- }
338
- /**
339
- * 获取指定租户的所有项目
340
- * @param tenantId 租户ID
341
- */
342
- getAllByTenant(tenantId) {
343
- const prefix = `${this.getLatticeType()}:${tenantId}:`;
344
- const result = [];
345
- for (const [key, value] of _BaseLatticeManager.registry.entries()) {
346
- if (key.startsWith(prefix)) {
347
- result.push(value);
348
- }
349
- }
350
- return result;
351
- }
352
- /**
353
- * 清空指定租户的所有项目
354
- * @param tenantId 租户ID
355
- */
356
- clearByTenant(tenantId) {
357
- const prefix = `${this.getLatticeType()}:${tenantId}:`;
358
- const keysToDelete = [];
359
- for (const key of _BaseLatticeManager.registry.keys()) {
360
- if (key.startsWith(prefix)) {
361
- keysToDelete.push(key);
362
- }
363
- }
364
- for (const key of keysToDelete) {
365
- _BaseLatticeManager.registry.delete(key);
366
- }
367
- }
368
- // ========== 向后兼容的旧API(使用 default 租户) ==========
369
- /**
370
- * 注册项目(向后兼容,使用 "default" 租户)
371
- * @deprecated Use registerWithTenant(tenantId, key, item) instead
372
- * @param key 项目键名(不含前缀)
373
- * @param item 项目实例
374
- */
375
- register(key, item) {
376
- this.registerWithTenant("default", key, item);
377
- }
378
- /**
379
- * 获取指定项目(向后兼容,使用 "default" 租户)
380
- * @deprecated Use getWithTenant(tenantId, key) instead
381
- * @param key 项目键名(不含前缀)
382
- */
383
- get(key) {
384
- return this.getWithTenant("default", key);
385
- }
386
- /**
387
- * 获取所有当前类型的项目(向后兼容,包含所有租户)
388
- */
389
- getAll() {
390
- const prefix = `${this.getLatticeType()}:`;
391
- const result = [];
392
- for (const [key, value] of _BaseLatticeManager.registry.entries()) {
393
- if (key.startsWith(prefix)) {
394
- result.push(value);
395
- }
396
- }
397
- return result;
398
- }
399
- /**
400
- * 检查项目是否存在(向后兼容,使用 "default" 租户)
401
- * @deprecated Use hasWithTenant(tenantId, key) instead
402
- * @param key 项目键名(不含前缀)
403
- */
404
- has(key) {
405
- return this.hasWithTenant("default", key);
406
- }
407
- /**
408
- * 移除项目(向后兼容,使用 "default" 租户)
409
- * @deprecated Use removeWithTenant(tenantId, key) instead
410
- * @param key 项目键名(不含前缀)
411
- */
412
- remove(key) {
413
- return this.removeWithTenant("default", key);
414
- }
415
- /**
416
- * 清空当前类型的所有项目(向后兼容,包含所有租户)
417
- */
418
- clear() {
419
- const prefix = `${this.getLatticeType()}:`;
420
- const keysToDelete = [];
421
- for (const key of _BaseLatticeManager.registry.keys()) {
422
- if (key.startsWith(prefix)) {
423
- keysToDelete.push(key);
424
- }
425
- }
426
- for (const key of keysToDelete) {
427
- _BaseLatticeManager.registry.delete(key);
428
- }
429
- }
430
- /**
431
- * 获取当前类型的项目数量(向后兼容,包含所有租户)
432
- */
433
- count() {
434
- const prefix = `${this.getLatticeType()}:`;
435
- let count = 0;
436
- for (const key of _BaseLatticeManager.registry.keys()) {
437
- if (key.startsWith(prefix)) {
438
- count++;
439
- }
440
- }
441
- return count;
442
- }
443
- /**
444
- * 获取当前类型的项目键名列表(向后兼容,包含所有租户)
445
- * 返回格式: {tenantId}:{key}
446
- */
447
- keys() {
448
- const prefix = `${this.getLatticeType()}:`;
449
- const prefixLength = prefix.length;
450
- const result = [];
451
- for (const key of _BaseLatticeManager.registry.keys()) {
452
- if (key.startsWith(prefix)) {
453
- result.push(key.substring(prefixLength));
454
- }
455
- }
456
- return result;
457
- }
458
- /**
459
- * 获取当前类型的项目键名列表(仅指定租户,不含租户前缀)
460
- * @param tenantId 租户ID
461
- */
462
- keysByTenant(tenantId) {
463
- const prefix = `${this.getLatticeType()}:${tenantId}:`;
464
- const prefixLength = prefix.length;
465
- const result = [];
466
- for (const key of _BaseLatticeManager.registry.keys()) {
467
- if (key.startsWith(prefix)) {
468
- result.push(key.substring(prefixLength));
469
- }
470
- }
471
- return result;
472
- }
473
- };
474
- // 全局统一的Lattice注册表
475
- _BaseLatticeManager.registry = /* @__PURE__ */ new Map();
476
- var BaseLatticeManager = _BaseLatticeManager;
1787
+ getAllToolDefinitions: () => getAllToolDefinitions,
1788
+ getBindingRegistry: () => getBindingRegistry,
1789
+ getBuiltInSkillContent: () => getBuiltInSkillContent,
1790
+ getBuiltInSkillMeta: () => getBuiltInSkillMeta,
1791
+ getBuiltInSkillNames: () => getBuiltInSkillNames,
1792
+ getCheckpointSaver: () => getCheckpointSaver,
1793
+ getChunkBuffer: () => getChunkBuffer,
1794
+ getEmbeddingsClient: () => getEmbeddingsClient,
1795
+ getEmbeddingsLattice: () => getEmbeddingsLattice,
1796
+ getEncryptionKey: () => getEncryptionKey,
1797
+ getLoggerLattice: () => getLoggerLattice,
1798
+ getModelLattice: () => getModelLattice,
1799
+ getNextCronTime: () => getNextCronTime,
1800
+ getQueueLattice: () => getQueueLattice,
1801
+ getSandBoxManager: () => getSandBoxManager,
1802
+ getScheduleLattice: () => getScheduleLattice,
1803
+ getStoreLattice: () => getStoreLattice,
1804
+ getToolClient: () => getToolClient,
1805
+ getToolDefinition: () => getToolDefinition,
1806
+ getToolLattice: () => getToolLattice,
1807
+ getVectorStoreClient: () => getVectorStoreClient,
1808
+ getVectorStoreLattice: () => getVectorStoreLattice,
1809
+ globSearchFiles: () => globSearchFiles,
1810
+ grepMatchesFromFiles: () => grepMatchesFromFiles,
1811
+ grepSearchFiles: () => grepSearchFiles,
1812
+ hasChunkBuffer: () => hasChunkBuffer,
1813
+ invokeWithRetry: () => invokeWithRetry,
1814
+ isBuiltInSkill: () => isBuiltInSkill,
1815
+ isUsingDefaultKey: () => isUsingDefaultKey,
1816
+ isValidCronExpression: () => isValidCronExpression,
1817
+ isValidSandboxName: () => isValidSandboxName,
1818
+ isValidSkillName: () => isValidSkillName,
1819
+ loggerLatticeManager: () => loggerLatticeManager,
1820
+ mcpManager: () => mcpManager,
1821
+ metricsServerManager: () => metricsServerManager,
1822
+ modelLatticeManager: () => modelLatticeManager,
1823
+ normalizeSandboxName: () => normalizeSandboxName,
1824
+ parallelLimit: () => parallelLimit,
1825
+ parseCronExpression: () => parseCronExpression,
1826
+ parseSkillFrontmatter: () => parseSkillFrontmatter,
1827
+ performStringReplacement: () => performStringReplacement,
1828
+ queueLatticeManager: () => queueLatticeManager,
1829
+ registerAgentLattice: () => registerAgentLattice,
1830
+ registerAgentLatticeWithTenant: () => registerAgentLatticeWithTenant,
1831
+ registerAgentLattices: () => registerAgentLattices,
1832
+ registerCheckpointSaver: () => registerCheckpointSaver,
1833
+ registerChunkBuffer: () => registerChunkBuffer,
1834
+ registerEmbeddingsLattice: () => registerEmbeddingsLattice,
1835
+ registerExistingTool: () => registerExistingTool,
1836
+ registerLoggerLattice: () => registerLoggerLattice,
1837
+ registerModelLattice: () => registerModelLattice,
1838
+ registerQueueLattice: () => registerQueueLattice,
1839
+ registerScheduleLattice: () => registerScheduleLattice,
1840
+ registerStoreLattice: () => registerStoreLattice,
1841
+ registerTeammateAgent: () => registerTeammateAgent,
1842
+ registerToolLattice: () => registerToolLattice,
1843
+ registerVectorStoreLattice: () => registerVectorStoreLattice,
1844
+ renderTemplate: () => renderTemplate,
1845
+ resolvePath: () => resolvePath,
1846
+ sandboxLatticeManager: () => sandboxLatticeManager,
1847
+ sanitizeToolCallId: () => sanitizeToolCallId,
1848
+ scheduleLatticeManager: () => scheduleLatticeManager,
1849
+ setBindingRegistry: () => setBindingRegistry,
1850
+ skillLatticeManager: () => skillLatticeManager,
1851
+ sqlDatabaseManager: () => sqlDatabaseManager,
1852
+ storeLatticeManager: () => storeLatticeManager,
1853
+ toolLatticeManager: () => toolLatticeManager,
1854
+ truncateIfTooLong: () => truncateIfTooLong,
1855
+ unregisterTeammateAgent: () => unregisterTeammateAgent,
1856
+ updateFileData: () => updateFileData,
1857
+ validateAgentInput: () => validateAgentInput,
1858
+ validateDSL: () => validateDSL,
1859
+ validateEncryptionKey: () => validateEncryptionKey,
1860
+ validatePath: () => validatePath,
1861
+ validateSkillName: () => validateSkillName,
1862
+ validateToolInput: () => validateToolInput,
1863
+ vectorStoreLatticeManager: () => vectorStoreLatticeManager
1864
+ });
1865
+ module.exports = __toCommonJS(index_exports);
1866
+
1867
+ // src/model_lattice/ModelLatticeManager.ts
1868
+ init_BaseLatticeManager();
477
1869
 
478
1870
  // src/model_lattice/ModelLattice.ts
479
1871
  var import_deepseek = require("@langchain/deepseek");
@@ -722,6 +2114,7 @@ var import_zod = __toESM(require("zod"));
722
2114
 
723
2115
  // src/tool_lattice/ToolLatticeManager.ts
724
2116
  var import_tools = require("@langchain/core/tools");
2117
+ init_BaseLatticeManager();
725
2118
 
726
2119
  // src/util/genUIMarkdown.ts
727
2120
  var genUIMarkdown = (type, data) => {
@@ -1001,6 +2394,9 @@ function getBindingRegistry() {
1001
2394
  return registry;
1002
2395
  }
1003
2396
 
2397
+ // src/store_lattice/StoreLatticeManager.ts
2398
+ init_BaseLatticeManager();
2399
+
1004
2400
  // src/store_lattice/InMemoryThreadStore.ts
1005
2401
  var InMemoryThreadStore = class {
1006
2402
  constructor() {
@@ -2666,6 +4062,14 @@ var InMemoryWorkflowTrackingStore = class {
2666
4062
  this.steps.set(request.runId, runSteps);
2667
4063
  return step;
2668
4064
  }
4065
+ async upsertRunStep(request) {
4066
+ const runSteps = this.steps.get(request.runId) || [];
4067
+ const existing = runSteps.find(
4068
+ (s) => s.stepType === request.stepType && s.stepName === request.stepName
4069
+ );
4070
+ if (existing) return existing;
4071
+ return this.createRunStep(request);
4072
+ }
2669
4073
  async updateRunStep(runId, stepId, updates) {
2670
4074
  const runSteps = this.steps.get(runId);
2671
4075
  if (!runSteps) return null;
@@ -5999,6 +7403,9 @@ ${serverKeys.map(
5999
7403
  // src/tool_lattice/code_eval/index.ts
6000
7404
  var import_zod16 = __toESM(require("zod"));
6001
7405
 
7406
+ // src/sandbox_lattice/SandboxLatticeManager.ts
7407
+ init_BaseLatticeManager();
7408
+
6002
7409
  // src/deep_agent_new/backends/volumeFilesystem.ts
6003
7410
  var VolumeFilesystem = class {
6004
7411
  constructor(client, mountPrefix = "") {
@@ -7265,90 +8672,16 @@ var createBrowserGetInfoTool = ({ vmIsolation }) => {
7265
8672
  };
7266
8673
 
7267
8674
  // src/index.ts
7268
- var import_messages6 = require("@langchain/core/messages");
8675
+ var import_messages7 = require("@langchain/core/messages");
7269
8676
 
7270
8677
  // src/agent_lattice/types.ts
7271
8678
  var import_protocols = require("@axiom-lattice/protocols");
7272
8679
 
7273
- // src/memory_lattice/DefaultMemorySaver.ts
7274
- var import_langgraph2 = require("@langchain/langgraph");
7275
-
7276
- // src/memory_lattice/MemoryLatticeManager.ts
7277
- var import_protocols2 = require("@axiom-lattice/protocols");
7278
- var _MemoryLatticeManager = class _MemoryLatticeManager extends BaseLatticeManager {
7279
- /**
7280
- * 私有构造函数,防止外部直接实例化
7281
- */
7282
- constructor() {
7283
- super();
7284
- }
7285
- /**
7286
- * 获取单例实例
7287
- */
7288
- static getInstance() {
7289
- if (!_MemoryLatticeManager.instance) {
7290
- _MemoryLatticeManager.instance = new _MemoryLatticeManager();
7291
- }
7292
- return _MemoryLatticeManager.instance;
7293
- }
7294
- /**
7295
- * 获取Lattice类型
7296
- */
7297
- getLatticeType() {
7298
- return "memory";
7299
- }
7300
- /**
7301
- * 注册检查点保存器
7302
- * @param key 保存器键名
7303
- * @param saver 检查点保存器实例
7304
- */
7305
- registerCheckpointSaver(key, saver) {
7306
- if (_MemoryLatticeManager.checkpointSavers.has(key)) {
7307
- console.warn(`\u68C0\u67E5\u70B9\u4FDD\u5B58\u5668 "${key}" \u5DF2\u7ECF\u5B58\u5728\uFF0C\u5C06\u4F1A\u8986\u76D6\u65E7\u7684\u68C0\u67E5\u70B9\u4FDD\u5B58\u5668`);
7308
- }
7309
- _MemoryLatticeManager.checkpointSavers.set(key, saver);
7310
- }
7311
- /**
7312
- * 获取检查点保存器
7313
- * @param key 保存器键名
7314
- */
7315
- getCheckpointSaver(key) {
7316
- const saver = _MemoryLatticeManager.checkpointSavers.get(key);
7317
- if (!saver) {
7318
- throw new Error(`\u68C0\u67E5\u70B9\u4FDD\u5B58\u5668 "${key}" \u4E0D\u5B58\u5728`);
7319
- }
7320
- return saver;
7321
- }
7322
- /**
7323
- * 获取所有已注册的检查点保存器键名
7324
- */
7325
- getCheckpointSaverKeys() {
7326
- return Array.from(_MemoryLatticeManager.checkpointSavers.keys());
7327
- }
7328
- /**
7329
- * 检查检查点保存器是否存在
7330
- * @param key 保存器键名
7331
- */
7332
- hasCheckpointSaver(key) {
7333
- return _MemoryLatticeManager.checkpointSavers.has(key);
7334
- }
7335
- /**
7336
- * 移除检查点保存器
7337
- * @param key 保存器键名
7338
- */
7339
- removeCheckpointSaver(key) {
7340
- return _MemoryLatticeManager.checkpointSavers.delete(key);
7341
- }
7342
- };
7343
- // 检查点保存器注册表
7344
- _MemoryLatticeManager.checkpointSavers = /* @__PURE__ */ new Map();
7345
- var MemoryLatticeManager = _MemoryLatticeManager;
7346
- var getCheckpointSaver = (key) => MemoryLatticeManager.getInstance().getCheckpointSaver(key);
7347
- var registerCheckpointSaver = (key, saver) => MemoryLatticeManager.getInstance().registerCheckpointSaver(key, saver);
8680
+ // src/agent_lattice/AgentLatticeManager.ts
8681
+ init_BaseLatticeManager();
7348
8682
 
7349
- // src/memory_lattice/DefaultMemorySaver.ts
7350
- var memory = new import_langgraph2.MemorySaver();
7351
- registerCheckpointSaver("default", memory);
8683
+ // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
8684
+ init_memory_lattice();
7352
8685
 
7353
8686
  // src/agent_lattice/builders/state.ts
7354
8687
  var import_zod41 = require("@langchain/langgraph/zod");
@@ -7753,81 +9086,429 @@ When iterating based on feedback:
7753
9086
  3. **Look for repeated work** \u2014 if all test runs involved writing the same helper script, bundle that script into \`resources/scripts/\` and have the skill reference it instead.
7754
9087
  4. **Explain the why** \u2014 if you're adding a constraint because of a failure, explain the context so the model understands when to apply it and when it's safe to deviate.
7755
9088
 
7756
- Repeat the test \u2192 review \u2192 improve loop until the user is satisfied.
9089
+ Repeat the test \u2192 review \u2192 improve loop until the user is satisfied.
9090
+
9091
+ ---
9092
+
9093
+ ## Step 5: Optimize the Description (Optional)
9094
+
9095
+ After the skill works well, offer to optimize the description for better triggering accuracy.
9096
+
9097
+ ### How Triggering Works
9098
+
9099
+ The agent sees skills as a list of name + description pairs. It decides whether to consult a skill based on that description. Important: agents only consult skills for tasks they can't easily handle on their own. Simple one-step queries may not trigger a skill even if the description matches \u2014 so make sure the description emphasizes the COMPLEX or SPECIALIZED nature of the task.
9100
+
9101
+ ### Optimization Approach
9102
+
9103
+ 1. Create 10-15 eval queries \u2014 a mix of should-trigger and should-not-trigger prompts
9104
+ 2. For **should-trigger** (6-8): different phrasings of the same intent \u2014 formal, casual, indirect. Include cases where the user doesn't explicitly name the skill but clearly needs it
9105
+ 3. For **should-not-trigger** (6-8): focus on near-misses \u2014 queries that share keywords but need something different. Don't make them obviously irrelevant
9106
+ 4. Test the description against these queries and adjust based on misfires
9107
+ 5. Show the user before/after and explain what changed
9108
+
9109
+ ---
9110
+
9111
+ ## Step 6: Package and Present
9112
+
9113
+ When the skill is ready:
9114
+ 1. Verify the SKILL.md is at \`/root/.agents/skills/{skill-name}/SKILL.md\` with correct frontmatter
9115
+ 2. Confirm all resource files are in place under \`resources/\`
9116
+ 3. Tell the user the skill is ready and available at its path
9117
+ 4. Remind them that the skill will now appear in the available skills list for any agent using the skill system
9118
+
9119
+ ## Updating Existing Skills
9120
+
9121
+ When the user wants to improve an existing skill:
9122
+ 1. Read the current SKILL.md from \`/root/.agents/skills/{skill-name}/SKILL.md\`
9123
+ 2. Understand what it currently does and where it falls short
9124
+ 3. Follow the same interview \u2192 draft \u2192 test \u2192 iterate loop
9125
+ 4. **Preserve the original name** \u2014 the directory name and \`name\` frontmatter field should stay the same
9126
+ 5. Write the updated version back to the same path
9127
+
9128
+ ---
9129
+
9130
+ ## Example Walkthrough
9131
+
9132
+ **User**: "I want a skill that helps me analyze CSV data"
9133
+
9134
+ **You** (interview):
9135
+ - "What kinds of analysis \u2014 summary stats, filtering, charting?"
9136
+ - "Are the CSVs always the same format or varied?"
9137
+ - "Should it output results as text, new CSV, or visualizations?"
9138
+
9139
+ **User**: "Mostly summary stats and filtering. The files vary but all have headers."
9140
+
9141
+ **You** (draft frontmatter):
9142
+ \`\`\`yaml
9143
+ ---
9144
+ name: csv-analyzer
9145
+ description: Analyze CSV data with statistical summaries, filtering, and aggregation. Use whenever users want to explore, summarize, or extract insights from CSV files \u2014 even if they don't say "analyze" explicitly.
9146
+ metadata:
9147
+ category: data
9148
+ version: "1.0"
9149
+ ---
9150
+ \`\`\`
9151
+
9152
+ **You** (draft body): Write a workflow that teaches the agent to:
9153
+ 1. Inspect the CSV structure and headers
9154
+ 2. Let the user choose analysis type (summary, filter, aggregate)
9155
+ 3. Execute the analysis and present results clearly
9156
+ 4. Handle edge cases: missing headers, empty files, mixed types
9157
+
9158
+ **You** (write): Create \`/root/.agents/skills/csv-analyzer/SKILL.md\`
9159
+
9160
+ **You** (test): "Here are 3 test cases \u2014 'summarize this sales CSV', 'filter rows where region is West', 'show monthly revenue trends'. Let me run these and we'll review."
9161
+
9162
+ Then iterate based on what the user says.
9163
+ `,
9164
+ "create-workflow": `---
9165
+ name: create-workflow
9166
+ description: Design and build multi-step AI workflows using the concise Workflow DSL. Use whenever users want to orchestrate agents in a pipeline, build process automation with branching/parallel logic, design approval flows with human-in-the-loop, or process data in stages.
9167
+ license: MIT
9168
+ metadata:
9169
+ category: meta
9170
+ version: "3.0"
9171
+ ---
9172
+
9173
+ # Workflow Designer
9174
+
9175
+ This skill guides you through designing and creating workflow agents. A workflow is a LangGraph state machine compiled from a concise JSON DSL \u2014 steps define what happens, order defines the flow, and the engine handles the rest.
9176
+
9177
+ Every step runs on the workflow's built-in general-purpose agent \u2014 no external agent registration needed.
9178
+
9179
+ ## Core Principle: id is everything
9180
+
9181
+ A step's \`id\` serves triple duty:
9182
+ 1. **Node identifier** in the graph
9183
+ 2. **State key** \u2014 output is stored at \`state.<id>\`
9184
+ 3. **Template reference** \u2014 downstream steps use \`{{id}}\` to read it
9185
+
9186
+ If you omit \`id\`, a unique identifier is auto-generated (but you won't be able to reference the output).
9187
+
9188
+ ## Step Types
9189
+
9190
+ ### agent \u2014 a step for the workflow's built-in agent
9191
+
9192
+ \`\`\`json
9193
+ { "id": "classify", "name": "Classify Intent", "prompt": "Classify the intent of: {{input}}", "schema": { "type": "object", "properties": { "intent": { "type": "string" } } } }
9194
+ \`\`\`
9195
+
9196
+ | Field | Required | Description |
9197
+ |-------|----------|-------------|
9198
+ | id | no | State key for referencing output. Auto-generated if omitted, but required if downstream steps reference this step via \`{{id}}\` |
9199
+ | name | no | Human-readable label for this step |
9200
+ | prompt | yes | Task description with {{id}} refs |
9201
+ | schema | **yes** | Standard JSON Schema ONLY: \`{ "type": "object", "properties": { "field": { "type": "string" } } }\`. \`true\` is REJECTED \u2014 must be a concrete schema. Legacy shorthand \`{ "field": "string" }\` is REJECTED.
9202
+
9203
+ **Schema Rules (MUST follow \u2014 shorthand is rejected):**
9204
+ - Always wrap in \`{ "type": "object", "properties": { ... } }\`
9205
+ - Each property must be \`{ "type": "string"|"number"|"boolean"|"array"|"object" }\`
9206
+ - Arrays need \`"items"\`: \`{ "type": "array", "items": { "type": "string" } }\`
9207
+ - \u274C \`{ "field": "string" }\` \u2014 REJECTED (no "type"/"properties" wrapper)
9208
+ - \u274C \`{ "schema": { "intent": "string" } }\` \u2014 REJECTED (legacy shorthand)
9209
+
9210
+ The agent's response is stored at \`state.<id>\` (or an auto-generated key if \`id\` is omitted).
9211
+
9212
+ ### condition \u2014 branch on state
9213
+
9214
+ **Binary (then/else):**
9215
+
9216
+ \`\`\`json
9217
+ { "type": "condition", "if": "intent",
9218
+ "then": { "id": "support", "name": "Handle Support", "prompt": "Handle support: {{input}}" },
9219
+ "else": { "id": "sales", "name": "Handle Sales", "prompt": "Handle sales: {{input}}" }
9220
+ }
9221
+ \`\`\`
9222
+
9223
+ | Field | Required | Description |
9224
+ |-------|----------|-------------|
9225
+ | if | yes | State field name (e.g. "approved") or expression (e.g. "score >= 60"). **CRITICAL: \`{{}}\` is FORBIDDEN in \`if\`** \u2014 it is a plain JavaScript expression, not a template. \u274C \`"if": "{{intent}}"\` is WRONG. \u2705 \`"if": "intent"\` is correct. |
9226
+ | then | yes | Step(s) to run when condition is truthy |
9227
+ | else | no | Step(s) to run when condition is falsy |
9228
+
9229
+ The engine evaluates \`if\` as a JavaScript expression prefixed with \`state.\`. Both \`then\` and \`else\` can be a single step or an array of steps. After both branches, execution rejoins at the next step after the condition.
9230
+
9231
+ **Switch (branches):**
9232
+
9233
+ When branching on a discrete set of known values, use \`branches\` for cleaner multi-way routing:
9234
+
9235
+ \`\`\`json
9236
+ { "type": "condition", "if": "intent",
9237
+ "branches": {
9238
+ "support": { "id": "support", "prompt": "Handle support: {{input}}" },
9239
+ "sales": { "id": "sales", "prompt": "Handle sales: {{input}}" },
9240
+ "billing": { "id": "billing", "prompt": "Handle billing: {{input}}" },
9241
+ "default": { "id": "fallback", "prompt": "Send to human: {{input}}" }
9242
+ }
9243
+ }
9244
+ \`\`\`
9245
+
9246
+ | Field | Required | Description |
9247
+ |-------|----------|-------------|
9248
+ | if | yes | State field whose STRING VALUE is matched against branch keys. **Same rule \u2014 \`{{}}\` is FORBIDDEN here.** |
9249
+ | branches | yes | Map of value \u2192 step(s). \`"default"\` key is a catch-all for unmatched values |
9250
+ | then/else | no | Not used when branches is present |
9251
+
9252
+ Unlike \`then\`/\`else\` (truthy/falsy ternary), \`branches\` does exact string match against the state field value. Always include a \`"default"\` branch.
9253
+
9254
+ ### human \u2014 pause for human input
9255
+
9256
+ The human step invokes an agent with ask_user_to_clarify middleware. The agent is a **facilitator** \u2014 it presents information to the user and collects their response. The agent does NOT make decisions itself; it asks the user. The agent's structured output is stored under the step's \`id\`.
9257
+
9258
+ \`\`\`json
9259
+ { "id": "review", "type": "human",
9260
+ "title": "Approval",
9261
+ "prompt": "Present the following draft to the user for approval. Ask whether to approve or reject, and collect any comments.\\n\\nDraft:\\n{{draft}}",
9262
+ "schema": { "type": "object", "properties": { "approved": { "type": "boolean" }, "comments": { "type": "string" } } }
9263
+ }
9264
+ \`\`\`
9265
+
9266
+ Access results with dot notation: \`{{review.approved}}\`, \`{{review.comments}}\`. Use \`schema\` to constrain the agent's output.
9267
+
9268
+ | Field | Required | Description |
9269
+ |-------|----------|-------------|
9270
+ | id | no | State key for the agent's structured output |
9271
+ | type | yes | Must be \`"human"\` |
9272
+ | prompt | yes | Tell the agent what to present to the user and what to ask. The agent is a facilitator \u2014 write instructions like "Present X to the user and ask Y", NOT "You are a reviewer. Review X..." |
9273
+ | title | no | Display label for the human step |
9274
+ | schema | no | JSON Schema constraining the agent's structured output format |
9275
+
9276
+ ### map \u2014 iterate over an array
9277
+
9278
+ \`\`\`json
9279
+ { "id": "results", "type": "map",
9280
+ "source": "items",
9281
+ "each": { "prompt": "Audit: {{item}}", "schema": { "type": "object", "properties": { "result": { "type": "string" } } } },
9282
+ "batch": 10, "concurrency": 3
9283
+ }
9284
+ \`\`\`
9285
+
9286
+ | Field | Required | Description |
9287
+ |-------|----------|-------------|
9288
+ | id | yes | Output key for the results array |
9289
+ | source | yes | id of the step whose output is the array to iterate |
9290
+ | each | yes | Step applied to each element. Use {{item}} for the current element |
9291
+ | reduce | no | Step to aggregate results |
9292
+ | batch | no | Items per batch (default 50) |
9293
+ | concurrency | no | Max parallel items (default 5) |
9294
+
9295
+ ### parallel \u2014 fixed fan-out
9296
+
9297
+ \`\`\`json
9298
+ { "type": "parallel", "steps": [
9299
+ { "id": "legal", "prompt": "Legal review: {{input}}" },
9300
+ { "id": "finance", "prompt": "Finance: {{input}}" }
9301
+ ]}
9302
+ \`\`\`
9303
+
9304
+ All steps run simultaneously. After all complete, execution continues to the next step.
9305
+
9306
+ ### end \u2014 terminate the workflow
9307
+
9308
+ \`\`\`json
9309
+ { "type": "end" }
9310
+ \`\`\`
9311
+
9312
+ Always include at the end of the steps array. \`status\` defaults to "success".
9313
+
9314
+ **Number of terminal nodes:**
9315
+
9316
+ - **Every workflow MUST have at least one \`{ "type": "end" }\`** \u2014 without it, the graph hangs at the last node.
9317
+ - **One is enough** even for complex workflows: all branches can converge to a single \`end\` node (parallel fan-in, condition branches rejoining, etc.).
9318
+ - **Use multiple end nodes ONLY when different branches need different \`status\`** values \u2014 e.g., success path vs failure path:
9319
+
9320
+ \`\`\`json
9321
+ { "type": "condition", "if": "score >= 60",
9322
+ "then": { "type": "end", "status": "success" },
9323
+ "else": { "type": "end", "status": "failed" }
9324
+ }
9325
+ \`\`\`
9326
+
9327
+ - If all outcomes share the same final status, use a single \`end\` node after the condition/parallel block \u2014 the engine automatically converges all paths to it.
9328
+
9329
+ ## Template Syntax
9330
+
9331
+ | Syntax | Resolves to | When to use |
9332
+ |--------|------------|-------------|
9333
+ | \`{{input}}\` | Initial user message | First step or any step needing the original question |
9334
+ | \`{{id}}\` | Output of step with given id | Referencing any upstream step's result |
9335
+ | \`{{item}}\` | Current element in map iteration | Inside map \`each.prompt\` |
9336
+
9337
+ ## \u26A0\uFE0F CRITICAL: \`{{}}\` is ONLY for \`prompt\` fields
9338
+
9339
+ The template markers \`{{id}}\`, \`{{input}}\`, and \`{{item}}\` work **exclusively inside \`prompt\` strings**. All other string fields \u2014 including \`if\`, \`source\`, \`id\`, \`name\`, \`title\`, \`status\` \u2014 must use plain values without any \`{{}}\` wrapping.
9340
+
9341
+ **Common mistake the AI makes:**
9342
+ \`\`\`json
9343
+ // \u274C WRONG \u2014 {{}} does not belong in if:
9344
+ { "type": "condition", "if": "{{intent}}", "then": {...}, "else": {...} }
9345
+
9346
+ // \u2705 CORRECT \u2014 if is a plain expression:
9347
+ { "type": "condition", "if": "intent", "then": {...}, "else": {...} }
9348
+ \`\`\`
9349
+
9350
+ ## What You NEVER Write
7757
9351
 
7758
- ---
9352
+ The engine auto-generates these \u2014 do NOT include them in your DSL:
7759
9353
 
7760
- ## Step 5: Optimize the Description (Optional)
9354
+ - **state.fields** \u2014 auto-declared from every \`id\`
9355
+ - **edges** \u2014 auto-generated from step order (linear) and types (fan-out for parallel, conditional for condition)
9356
+ - **output.key** \u2014 always equals \`id\`
9357
+ - **version** \u2014 always "1.0" internally
9358
+ - **node IDs** \u2014 prefixed internally to avoid conflicts with state channel names
9359
+ - **human step type** \u2014 the human step has ask_user_to_clarify built-in. Use \`{ "type": "human", ... }\` in the DSL for user interaction. Do NOT manually add ask_user_to_clarify middleware to regular agent steps \u2014 use the dedicated \`human\` step instead.
7761
9360
 
7762
- After the skill works well, offer to optimize the description for better triggering accuracy.
9361
+ ## Design Patterns
7763
9362
 
7764
- ### How Triggering Works
9363
+ ### Pattern 1: Linear Pipeline
7765
9364
 
7766
- The agent sees skills as a list of name + description pairs. It decides whether to consult a skill based on that description. Important: agents only consult skills for tasks they can't easily handle on their own. Simple one-step queries may not trigger a skill even if the description matches \u2014 so make sure the description emphasizes the COMPLEX or SPECIALIZED nature of the task.
9365
+ \`\`\`json
9366
+ {
9367
+ "name": "knowledge-qa",
9368
+ "steps": [
9369
+ { "id": "research", "name": "Research Topic", "prompt": "Research: {{input}}", "schema": { "type": "object", "properties": { "findings": { "type": "string" } } } },
9370
+ { "id": "answer", "name": "Write Answer", "prompt": "Write answer based on: {{research}}", "schema": { "type": "object", "properties": { "answer": { "type": "string" } } } },
9371
+ { "type": "end" }
9372
+ ]
9373
+ }
9374
+ \`\`\`
7767
9375
 
7768
- ### Optimization Approach
9376
+ ### Pattern 2: Classify then Route
7769
9377
 
7770
- 1. Create 10-15 eval queries \u2014 a mix of should-trigger and should-not-trigger prompts
7771
- 2. For **should-trigger** (6-8): different phrasings of the same intent \u2014 formal, casual, indirect. Include cases where the user doesn't explicitly name the skill but clearly needs it
7772
- 3. For **should-not-trigger** (6-8): focus on near-misses \u2014 queries that share keywords but need something different. Don't make them obviously irrelevant
7773
- 4. Test the description against these queries and adjust based on misfires
7774
- 5. Show the user before/after and explain what changed
9378
+ \`\`\`json
9379
+ {
9380
+ "name": "customer-router",
9381
+ "steps": [
9382
+ { "id": "intent", "name": "Classify Intent", "prompt": "Classify: {{input}}", "schema": { "type": "object", "properties": { "intent": { "type": "string" } } } },
9383
+ { "type": "condition", "if": "intent",
9384
+ "then": { "id": "support", "name": "Handle Support", "prompt": "Handle support: {{input}}", "schema": { "type": "object", "properties": { "response": { "type": "string" } } } },
9385
+ "else": { "id": "sales", "name": "Handle Sales", "prompt": "Handle sales: {{input}}", "schema": { "type": "object", "properties": { "response": { "type": "string" } } } }
9386
+ },
9387
+ { "type": "end" }
9388
+ ]
9389
+ }
9390
+ \`\`\`
7775
9391
 
7776
- ---
9392
+ ### Pattern 2b: Classify then Switch
7777
9393
 
7778
- ## Step 6: Package and Present
9394
+ For routing to 3+ categories, use \`branches\` instead of nested \`then\`/\`else\`:
7779
9395
 
7780
- When the skill is ready:
7781
- 1. Verify the SKILL.md is at \`/root/.agents/skills/{skill-name}/SKILL.md\` with correct frontmatter
7782
- 2. Confirm all resource files are in place under \`resources/\`
7783
- 3. Tell the user the skill is ready and available at its path
7784
- 4. Remind them that the skill will now appear in the available skills list for any agent using the skill system
9396
+ \`\`\`json
9397
+ {
9398
+ "name": "ticket-router",
9399
+ "steps": [
9400
+ { "id": "intent", "name": "Classify", "prompt": "Classify: {{input}}", "schema": { "type": "object", "properties": { "category": { "type": "string" } } } },
9401
+ { "type": "condition", "if": "intent.category",
9402
+ "branches": {
9403
+ "support": { "id": "support", "prompt": "Handle support: {{input}}" },
9404
+ "sales": { "id": "sales", "prompt": "Handle sales: {{input}}" },
9405
+ "billing": { "id": "billing", "prompt": "Handle billing: {{input}}" },
9406
+ "default": { "id": "fallback", "prompt": "Send to human: {{input}}" }
9407
+ }
9408
+ },
9409
+ { "type": "end" }
9410
+ ]
9411
+ }
9412
+ \`\`\`
9413
+
9414
+ ### Pattern 3: Extract \u2192 Review \u2192 Approve
9415
+
9416
+ \`\`\`json
9417
+ {
9418
+ "name": "approval-flow",
9419
+ "steps": [
9420
+ { "id": "draft", "name": "Draft Response", "prompt": "Draft a response to: {{input}}", "schema": { "type": "object", "properties": { "content": { "type": "string" } } } },
9421
+ { "id": "review", "type": "human",
9422
+ "title": "Approval",
9423
+ "prompt": "Present the draft below to the user for approval. Ask whether to approve or reject with comments.\\n\\nDraft:\\n{{draft}}",
9424
+ "schema": { "type": "object", "properties": { "approved": { "type": "boolean" }, "comments": { "type": "string" } } } },
9425
+ { "type": "condition", "if": "review.approved",
9426
+ "then": { "id": "published", "name": "Publish", "prompt": "Publish: {{draft}}", "schema": { "type": "object", "properties": { "status": { "type": "string" } } } },
9427
+ "else": { "id": "revised", "name": "Revise", "prompt": "Revise based on: {{review.comments}}", "schema": { "type": "object", "properties": { "content": { "type": "string" } } } }
9428
+ },
9429
+ { "type": "end" }
9430
+ ]
9431
+ }
9432
+ \`\`\`
7785
9433
 
7786
- ## Updating Existing Skills
9434
+ ### Pattern 4: Parallel Research
9435
+
9436
+ \`\`\`json
9437
+ {
9438
+ "name": "due-diligence",
9439
+ "steps": [
9440
+ { "id": "info", "name": "Gather Info", "prompt": "Gather info: {{input}}", "schema": { "type": "object", "properties": { "rawData": { "type": "string" } } } },
9441
+ { "type": "parallel", "steps": [
9442
+ { "id": "legal", "name": "Legal Review", "prompt": "Legal review: {{info}}", "schema": { "type": "object", "properties": { "risks": { "type": "array", "items": { "type": "string" } } } } },
9443
+ { "id": "finance", "name": "Finance Review", "prompt": "Finance review: {{info}}", "schema": { "type": "object", "properties": { "score": { "type": "number" } } } },
9444
+ { "id": "market", "name": "Market Analysis", "prompt": "Market analysis: {{info}}", "schema": { "type": "object", "properties": { "trend": { "type": "string" } } } }
9445
+ ]},
9446
+ { "id": "synthesis", "name": "Synthesize", "prompt": "Synthesize: legal={{legal}} finance={{finance}} market={{market}}", "schema": { "type": "object", "properties": { "report": { "type": "string" } } } },
9447
+ { "type": "end" }
9448
+ ]
9449
+ }
9450
+ \`\`\`
7787
9451
 
7788
- When the user wants to improve an existing skill:
7789
- 1. Read the current SKILL.md from \`/root/.agents/skills/{skill-name}/SKILL.md\`
7790
- 2. Understand what it currently does and where it falls short
7791
- 3. Follow the same interview \u2192 draft \u2192 test \u2192 iterate loop
7792
- 4. **Preserve the original name** \u2014 the directory name and \`name\` frontmatter field should stay the same
7793
- 5. Write the updated version back to the same path
9452
+ ### Pattern 5: Batch Map + Reduce
9453
+
9454
+ \`\`\`json
9455
+ {
9456
+ "name": "sentiment-analysis",
9457
+ "steps": [
9458
+ { "id": "posts", "name": "Scrape Posts", "prompt": "Scrape posts about: {{input}}", "schema": { "type": "object", "properties": { "posts": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string" } } } } } } },
9459
+ { "id": "sentiments", "type": "map", "source": "posts",
9460
+ "each": { "prompt": "Analyze sentiment: {{item}}", "schema": { "type": "object", "properties": { "sentiment": { "type": "string" } } } },
9461
+ "reduce": { "prompt": "Summarize: {{sentiments}}", "schema": { "type": "object", "properties": { "summary": { "type": "string" } } } }
9462
+ },
9463
+ { "id": "report", "name": "Generate Report", "prompt": "Generate report from: {{sentiments}}", "schema": { "type": "object", "properties": { "report": { "type": "string" } } } },
9464
+ { "type": "end" }
9465
+ ]
9466
+ }
9467
+ \`\`\`
7794
9468
 
7795
- ---
9469
+ ## Step 1: Understand the Process
7796
9470
 
7797
- ## Example Walkthrough
9471
+ Ask the user:
9472
+ - What are the steps in order?
9473
+ - Are there branches (if condition then A else B)?
9474
+ - Can any steps run in parallel?
9475
+ - Is human approval/review needed?
9476
+ - What data flows between steps?
7798
9477
 
7799
- **User**: "I want a skill that helps me analyze CSV data"
9478
+ ## Step 2: Prepare Dependencies
7800
9479
 
7801
- **You** (interview):
7802
- - "What kinds of analysis \u2014 summary stats, filtering, charting?"
7803
- - "Are the CSVs always the same format or varied?"
7804
- - "Should it output results as text, new CSV, or visualizations?"
9480
+ 1. Call \`list_tools\` to see available tools for the workflow agent.
7805
9481
 
7806
- **User**: "Mostly summary stats and filtering. The files vary but all have headers."
9482
+ ## Step 3: Write the DSL
7807
9483
 
7808
- **You** (draft frontmatter):
7809
- \`\`\`yaml
7810
- ---
7811
- name: csv-analyzer
7812
- description: Analyze CSV data with statistical summaries, filtering, and aggregation. Use whenever users want to explore, summarize, or extract insights from CSV files \u2014 even if they don't say "analyze" explicitly.
7813
- metadata:
7814
- category: data
7815
- version: "1.0"
7816
- ---
7817
- \`\`\`
9484
+ Use \`create_workflow\` with \`skillLoaded: true\`. Never write \`state.fields\`, \`edges\`, \`version\`, or \`output.key\` \u2014 they are auto-generated.
7818
9485
 
7819
- **You** (draft body): Write a workflow that teaches the agent to:
7820
- 1. Inspect the CSV structure and headers
7821
- 2. Let the user choose analysis type (summary, filter, aggregate)
7822
- 3. Execute the analysis and present results clearly
7823
- 4. Handle edge cases: missing headers, empty files, mixed types
9486
+ **Checklist before calling:**
9487
+ - Every step that produces data referenced downstream has an \`id\`
9488
+ - Every agent/map-each step has a valid \`schema\` in standard JSON Schema format (with \`"type": "object"\` and \`"properties"\`)
9489
+ - Schema uses \`{ "type": "object", "properties": { ... } }\` \u2014 \`true\` and legacy \`{ "field": "string" }\` are REJECTED
9490
+ - Downstream steps reference upstream data with \`{{id}}\`
9491
+ - **Condition \`if\` fields do NOT use \`{{}}\`** \u2014 they are plain expressions like \`"intent"\` or \`"score >= 60"\`
9492
+ - Condition steps have \`then\`/\`else\` (binary) or \`branches\` (switch)
9493
+ - Human steps have \`schema\` constraining the agent's structured output
9494
+ - Map steps have \`source\` pointing to an existing step id
9495
+ - Parallel steps have sibling steps with unique \`id\`s
9496
+ - Workflow ends with \`{ "type": "end" }\`
9497
+ - Use \`human\` step type for user interaction (clarify middleware is built-in)
7824
9498
 
7825
- **You** (write): Create \`/root/.agents/skills/csv-analyzer/SKILL.md\`
9499
+ ## Step 4: Test
7826
9500
 
7827
- **You** (test): "Here are 3 test cases \u2014 'summarize this sales CSV', 'filter rows where region is West', 'show monthly revenue trends'. Let me run these and we'll review."
9501
+ After creating, optionally call \`validate_workflow(id)\` to check the workflow compiles correctly. Then test with \`invoke_agent\`.
7828
9502
 
7829
- Then iterate based on what the user says.
7830
- `
9503
+ ## Debugging Tips
9504
+
9505
+ - If output is missing: check the producing step has an \`id\`
9506
+ - The human step invokes an agent that can use ask_user_to_clarify. The agent's structured output is stored under the step's \`id\`. Access nested results with dot notation: \`{{review.approved}}\`, \`{{review.comments}}\`
9507
+ - Map results are an array; use \`reduce\` to aggregate into a summary
9508
+ - Condition branching uses truthiness: empty string, 0, null, false \u2192 else path
9509
+ - \`{{input}}\` contains the user's initial message; it's always available
9510
+ - Parallel + condition: a parallel group cannot be the first step inside a condition's then/else (LangGraph limitation). Add a preceding agent step.
9511
+ `
7831
9512
  };
7832
9513
  function getBuiltInSkillMeta(name) {
7833
9514
  const content = BUILTIN_SKILLS[name];
@@ -8064,15 +9745,15 @@ function formatContentWithLineNumbers(content, startLine = 1) {
8064
9745
  for (let chunkIdx = 0; chunkIdx < numChunks; chunkIdx++) {
8065
9746
  const start = chunkIdx * MAX_LINE_LENGTH;
8066
9747
  const end = Math.min(start + MAX_LINE_LENGTH, line.length);
8067
- const chunk = line.substring(start, end);
9748
+ const chunk2 = line.substring(start, end);
8068
9749
  if (chunkIdx === 0) {
8069
9750
  resultLines.push(
8070
- `${lineNum.toString().padStart(LINE_NUMBER_WIDTH)} ${chunk}`
9751
+ `${lineNum.toString().padStart(LINE_NUMBER_WIDTH)} ${chunk2}`
8071
9752
  );
8072
9753
  } else {
8073
9754
  const continuationMarker = `${lineNum}.${chunkIdx}`;
8074
9755
  resultLines.push(
8075
- `${continuationMarker.padStart(LINE_NUMBER_WIDTH)} ${chunk}`
9756
+ `${continuationMarker.padStart(LINE_NUMBER_WIDTH)} ${chunk2}`
8076
9757
  );
8077
9758
  }
8078
9759
  }
@@ -10742,6 +12423,7 @@ var import_uuid2 = require("uuid");
10742
12423
  var import_protocols8 = require("@axiom-lattice/protocols");
10743
12424
 
10744
12425
  // src/schedule_lattice/ScheduleLatticeManager.ts
12426
+ init_BaseLatticeManager();
10745
12427
  var import_protocols5 = require("@axiom-lattice/protocols");
10746
12428
 
10747
12429
  // src/schedule_lattice/DefaultScheduleClient.ts
@@ -11733,6 +13415,7 @@ var getScheduleLattice = (key) => scheduleLatticeManager.getScheduleLattice(key)
11733
13415
  var import_events = require("events");
11734
13416
 
11735
13417
  // src/queue_lattice/QueueLatticeManager.ts
13418
+ init_BaseLatticeManager();
11736
13419
  var import_protocols6 = require("@axiom-lattice/protocols");
11737
13420
 
11738
13421
  // src/queue_lattice/MemoryQueueClient.ts
@@ -12070,9 +13753,9 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
12070
13753
  }
12071
13754
  async addChunk(threadId, arg2, arg3) {
12072
13755
  const buffer2 = this.getOrCreateBuffer(threadId);
12073
- let chunk;
13756
+ let chunk2;
12074
13757
  if (typeof arg2 === "string" && arg3 !== void 0) {
12075
- chunk = {
13758
+ chunk2 = {
12076
13759
  type: import_protocols7.MessageChunkTypes.AI,
12077
13760
  data: {
12078
13761
  id: arg2,
@@ -12080,10 +13763,10 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
12080
13763
  }
12081
13764
  };
12082
13765
  } else {
12083
- chunk = arg2;
13766
+ chunk2 = arg2;
12084
13767
  }
12085
- buffer2.chunks.push(chunk);
12086
- buffer2.chunks$.next(chunk);
13768
+ buffer2.chunks.push(chunk2);
13769
+ buffer2.chunks$.next(chunk2);
12087
13770
  buffer2.updatedAt = Date.now();
12088
13771
  buffer2.expiresAt = Date.now() + this.config.ttl;
12089
13772
  buffer2.status = "active" /* ACTIVE */;
@@ -12130,12 +13813,12 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
12130
13813
  async getAccumulatedContent(threadId) {
12131
13814
  const buffer2 = this.getBufferIfValid(threadId);
12132
13815
  if (!buffer2) return "";
12133
- return buffer2.chunks.map((chunk) => chunk.data?.content || "").join("");
13816
+ return buffer2.chunks.map((chunk2) => chunk2.data?.content || "").join("");
12134
13817
  }
12135
13818
  async getChunksByMessageId(threadId, messageId) {
12136
13819
  const buffer2 = this.getBufferIfValid(threadId);
12137
13820
  if (!buffer2) return [];
12138
- return buffer2.chunks.filter((chunk) => chunk.data?.id === messageId);
13821
+ return buffer2.chunks.filter((chunk2) => chunk2.data?.id === messageId);
12139
13822
  }
12140
13823
  async clearThread(threadId) {
12141
13824
  this.buffers.delete(threadId);
@@ -12203,12 +13886,12 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
12203
13886
  const filtered$ = buffer2.chunks$.pipe(
12204
13887
  (0, import_rxjs.observeOn)(import_rxjs.asyncScheduler),
12205
13888
  // 1. 从指定 messageId 开始
12206
- (0, import_operators.filter)((chunk) => {
12207
- if (chunk.data?.id === messageId) startYieldChunk = true;
13889
+ (0, import_operators.filter)((chunk2) => {
13890
+ if (chunk2.data?.id === messageId) startYieldChunk = true;
12208
13891
  return startYieldChunk;
12209
13892
  }),
12210
13893
  // 2. 包含指定的停止类型,但收到后停止
12211
- (0, import_operators.takeWhile)((chunk) => !typesToStop.includes(chunk.type), true)
13894
+ (0, import_operators.takeWhile)((chunk2) => !typesToStop.includes(chunk2.type), true)
12212
13895
  );
12213
13896
  yield* (0, import_rxjs_for_await.eachValueFrom)(filtered$);
12214
13897
  }
@@ -12255,6 +13938,7 @@ var InMemoryChunkBuffer = class extends ChunkBuffer {
12255
13938
  };
12256
13939
 
12257
13940
  // src/chunk_buffer_lattice/ChunkBufferLatticeManager.ts
13941
+ init_BaseLatticeManager();
12258
13942
  var ChunkBufferLatticeManager = class _ChunkBufferLatticeManager extends BaseLatticeManager {
12259
13943
  /**
12260
13944
  * Private constructor for singleton pattern
@@ -12422,26 +14106,26 @@ var Agent = class {
12422
14106
  }
12423
14107
  );
12424
14108
  try {
12425
- for await (const chunk of agentStream) {
14109
+ for await (const chunk2 of agentStream) {
12426
14110
  if (signal?.aborted) {
12427
14111
  await lifecycleManager.chunkBuffer.abortThread(lifecycleManager.thread_id);
12428
14112
  throw new Error("Agent execution was aborted");
12429
14113
  }
12430
14114
  let data;
12431
14115
  let chunkContent = "";
12432
- if (chunk[0] === "updates") {
12433
- const update = chunk[1];
14116
+ if (chunk2[0] === "updates") {
14117
+ const update = chunk2[1];
12434
14118
  const values = Object.values(update);
12435
14119
  const messages2 = values[0]?.messages;
12436
14120
  if (messages2?.[0]?.tool_call_id) {
12437
14121
  data = messages2[0].toDict();
12438
14122
  }
12439
- } else if (chunk[0] === "messages") {
12440
- const messages2 = chunk[1];
14123
+ } else if (chunk2[0] === "messages") {
14124
+ const messages2 = chunk2[1];
12441
14125
  data = messages2?.[0]?.toDict();
12442
14126
  }
12443
- if (chunk?.[1]?.__interrupt__) {
12444
- const interruptData = chunk?.[1]?.__interrupt__[0];
14127
+ if (chunk2?.[1]?.__interrupt__) {
14128
+ const interruptData = chunk2?.[1]?.__interrupt__[0];
12445
14129
  data = {
12446
14130
  type: "interrupt",
12447
14131
  id: interruptData.id,
@@ -12784,8 +14468,8 @@ var Agent = class {
12784
14468
  return {
12785
14469
  [Symbol.asyncIterator]: async function* () {
12786
14470
  try {
12787
- for await (const chunk of stream) {
12788
- yield chunk;
14471
+ for await (const chunk2 of stream) {
14472
+ yield chunk2;
12789
14473
  }
12790
14474
  } catch (error) {
12791
14475
  if (error?.message === "Thread aborted") {
@@ -13972,7 +15656,8 @@ var ReActAgentGraphBuilder = class {
13972
15656
  name: agentLattice.config.name,
13973
15657
  checkpointer: getCheckpointSaver("default"),
13974
15658
  stateSchema: stateSchema2,
13975
- middleware: middlewares
15659
+ middleware: middlewares,
15660
+ responseFormat: params.responseFormat
13976
15661
  });
13977
15662
  }
13978
15663
  };
@@ -14145,6 +15830,7 @@ function createAgentWorkerGraph() {
14145
15830
  var agentWorkerGraph = createAgentWorkerGraph();
14146
15831
 
14147
15832
  // src/deep_agent_new/middleware/subagents.ts
15833
+ init_MemoryLatticeManager();
14148
15834
  var DEFAULT_SUBAGENT_PROMPT = "In order to complete the objective that the user asks of you, you have access to a number of standard tools.";
14149
15835
  var EXCLUDED_STATE_KEYS = ["messages", "todos", "jumpTo"];
14150
15836
  var DEFAULT_GENERAL_PURPOSE_DESCRIPTION = "General-purpose agent for researching complex questions, searching for files and content, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you. This agent has access to all tools as the main agent.";
@@ -16273,6 +17959,7 @@ ${BASE_PROMPT}` : BASE_PROMPT;
16273
17959
  }
16274
17960
 
16275
17961
  // src/agent_lattice/builders/DeepAgentGraphBuilder.ts
17962
+ init_MemoryLatticeManager();
16276
17963
  var DeepAgentGraphBuilder = class {
16277
17964
  /**
16278
17965
  * 构建Deep Agent Graph
@@ -16315,6 +18002,7 @@ var DeepAgentGraphBuilder = class {
16315
18002
  contextSchema: params.stateSchema,
16316
18003
  systemPrompt: params.prompt,
16317
18004
  subagents,
18005
+ responseFormat: params.responseFormat,
16318
18006
  checkpointer: getCheckpointSaver("default"),
16319
18007
  skills: params.skillCategories,
16320
18008
  backend: filesystemBackend,
@@ -16324,6 +18012,9 @@ var DeepAgentGraphBuilder = class {
16324
18012
  }
16325
18013
  };
16326
18014
 
18015
+ // src/agent_team/builders/TeamAgentGraphBuilder.ts
18016
+ init_MemoryLatticeManager();
18017
+
16327
18018
  // src/agent_team/agent_team.ts
16328
18019
  var import_v35 = require("zod/v3");
16329
18020
  var import_langchain63 = require("langchain");
@@ -17024,6 +18715,7 @@ function createTeammateTools(options) {
17024
18715
  }
17025
18716
 
17026
18717
  // src/agent_team/middleware/team.ts
18718
+ init_MemoryLatticeManager();
17027
18719
  var TEAM_LEAD_AGENT_ID = "team_lead";
17028
18720
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
17029
18721
  var DEFAULT_SCHEDULE_LATTICE_KEY = "default";
@@ -18323,6 +20015,7 @@ ${BASE_PROMPT2}` : BASE_PROMPT2;
18323
20015
  }
18324
20016
 
18325
20017
  // src/agent_lattice/builders/ProcessingAgentGraphBuilder.ts
20018
+ init_MemoryLatticeManager();
18326
20019
  var ProcessingAgentGraphBuilder = class {
18327
20020
  async build(agentLattice, params) {
18328
20021
  const tools = params.tools.map((t) => {
@@ -18362,6 +20055,7 @@ var ProcessingAgentGraphBuilder = class {
18362
20055
  contextSchema: params.stateSchema,
18363
20056
  systemPrompt: params.prompt,
18364
20057
  subagents,
20058
+ responseFormat: params.responseFormat,
18365
20059
  checkpointer: getCheckpointSaver("default"),
18366
20060
  skills: params.skillCategories,
18367
20061
  backend: filesystemBackend,
@@ -18593,6 +20287,102 @@ function extractLastHumanMessage(messages) {
18593
20287
  return "";
18594
20288
  }
18595
20289
 
20290
+ // src/agent_lattice/builders/WorkflowAgentGraphBuilder.ts
20291
+ var import_langchain67 = require("langchain");
20292
+ init_MemoryLatticeManager();
20293
+ var import_protocols10 = require("@axiom-lattice/protocols");
20294
+ init_compile();
20295
+ var DEFAULT_AGENT_PROMPT = "Complete the task accurately and concisely. Follow the instructions in the user's message.";
20296
+ var WorkflowAgentGraphBuilder = class {
20297
+ async build(agentLattice, params) {
20298
+ if (!(0, import_protocols10.isWorkflowAgentConfig)(agentLattice.config)) {
20299
+ throw new Error(
20300
+ `WorkflowAgentGraphBuilder received wrong agent type: ${agentLattice.config.type}`
20301
+ );
20302
+ }
20303
+ const config = agentLattice.config;
20304
+ const dsl = config.workflow;
20305
+ const tenantId = agentLattice.config.tenantId ?? "default";
20306
+ const checkpointer = getCheckpointSaver("default");
20307
+ const tools = params.tools.map((t) => t.executor).filter(Boolean);
20308
+ const middlewareConfigs = params.middleware || [];
20309
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false);
20310
+ const humanMiddlewares = await createCommonMiddlewares([
20311
+ {
20312
+ id: "ask_user_to_clarify",
20313
+ type: "ask_user_to_clarify",
20314
+ name: "Ask User Clarify",
20315
+ description: "For human_feedback workflow nodes",
20316
+ enabled: true,
20317
+ config: {}
20318
+ }
20319
+ ], void 0, false);
20320
+ const noWrapMiddlewares = middlewares.filter((m) => !m.wrapModelCall);
20321
+ const noWrapHumanMiddlewares = humanMiddlewares.filter((m) => !m.wrapModelCall);
20322
+ console.log(`[WF BUILDER] building default agent | toolCount=${tools.length} | middlewareCount=${middlewares.length}`);
20323
+ const defaultAgent = (0, import_langchain67.createAgent)({
20324
+ model: params.model,
20325
+ tools,
20326
+ systemPrompt: params.prompt || DEFAULT_AGENT_PROMPT,
20327
+ checkpointer,
20328
+ middleware: middlewares
20329
+ });
20330
+ console.log(`[WF BUILDER] default agent built`);
20331
+ const agentCache = /* @__PURE__ */ new Map();
20332
+ const resolveAgent = async (ref, responseFormat, stepType) => {
20333
+ if (ref) {
20334
+ console.log(`[WF BUILDER] resolveAgent: looking up ref="${ref}"`);
20335
+ return await getAgentClientAsync(tenantId, ref);
20336
+ }
20337
+ const isHuman = stepType === "human_feedback";
20338
+ if (responseFormat) {
20339
+ const key = (isHuman ? "human:" : "agent:") + JSON.stringify(responseFormat);
20340
+ console.log(`[WF BUILDER] resolveAgent: cacheKey=${key.slice(0, 80)}... | cached=${agentCache.has(key)}`);
20341
+ if (!agentCache.has(key)) {
20342
+ console.log(`[WF BUILDER] creating ${isHuman ? "human" : "agent"} with responseFormat`);
20343
+ const agent = (0, import_langchain67.createAgent)({
20344
+ model: params.model,
20345
+ tools,
20346
+ systemPrompt: params.prompt || DEFAULT_AGENT_PROMPT,
20347
+ checkpointer,
20348
+ middleware: isHuman ? noWrapHumanMiddlewares : noWrapMiddlewares,
20349
+ responseFormat
20350
+ });
20351
+ agentCache.set(key, agent);
20352
+ }
20353
+ return agentCache.get(key);
20354
+ }
20355
+ if (isHuman) {
20356
+ const key = "human:default";
20357
+ if (!agentCache.has(key)) {
20358
+ console.log(`[WF BUILDER] creating human_feedback default agent`);
20359
+ const agent = (0, import_langchain67.createAgent)({
20360
+ model: params.model,
20361
+ tools,
20362
+ systemPrompt: params.prompt || DEFAULT_AGENT_PROMPT,
20363
+ checkpointer,
20364
+ middleware: humanMiddlewares
20365
+ });
20366
+ agentCache.set(key, agent);
20367
+ }
20368
+ return agentCache.get(key);
20369
+ }
20370
+ console.log(`[WF BUILDER] resolveAgent: using defaultAgent`);
20371
+ return defaultAgent;
20372
+ };
20373
+ let trackingStore;
20374
+ try {
20375
+ const storeLattice = getStoreLattice("default", "workflowTracking");
20376
+ trackingStore = storeLattice.store;
20377
+ console.log(`[WF BUILDER] trackingStore registered: step input/output will be persisted`);
20378
+ } catch {
20379
+ console.warn(`[WF BUILDER] no trackingStore registered \u2014 step input/output will NOT be persisted. Register a WorkflowTrackingStore under key "workflowTracking".`);
20380
+ }
20381
+ const graph = compileWorkflow(dsl, resolveAgent, checkpointer, trackingStore);
20382
+ return graph;
20383
+ }
20384
+ };
20385
+
18596
20386
  // src/agent_lattice/builders/AgentGraphBuilderFactory.ts
18597
20387
  var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
18598
20388
  constructor() {
@@ -18617,6 +20407,7 @@ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
18617
20407
  this.builders.set(import_protocols.AgentType.TEAM, new TeamAgentGraphBuilder());
18618
20408
  this.builders.set(import_protocols.AgentType.PROCESSING, new ProcessingAgentGraphBuilder());
18619
20409
  this.builders.set(import_protocols.AgentType.A2A_REMOTE, new RemoteAgentGraphBuilder());
20410
+ this.builders.set(import_protocols.AgentType.WORKFLOW, new WorkflowAgentGraphBuilder());
18620
20411
  }
18621
20412
  /**
18622
20413
  * 注册自定义Builder
@@ -18643,7 +20434,7 @@ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
18643
20434
  };
18644
20435
 
18645
20436
  // src/agent_lattice/builders/AgentParamsBuilder.ts
18646
- var import_protocols10 = require("@axiom-lattice/protocols");
20437
+ var import_protocols11 = require("@axiom-lattice/protocols");
18647
20438
  var AgentParamsBuilder = class {
18648
20439
  /**
18649
20440
  * constructor
@@ -18661,8 +20452,8 @@ var AgentParamsBuilder = class {
18661
20452
  * @returns Agent build parameters
18662
20453
  */
18663
20454
  async buildParams(agentLattice, options) {
18664
- const skills = (0, import_protocols10.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols10.isProcessingAgentConfig)(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
18665
- const toolKeys = options?.overrideTools || (0, import_protocols10.getToolsFromConfig)(agentLattice.config);
20455
+ const skills = (0, import_protocols11.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols11.isProcessingAgentConfig)(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
20456
+ const toolKeys = options?.overrideTools || (0, import_protocols11.getToolsFromConfig)(agentLattice.config);
18666
20457
  const tools = toolKeys.map((toolKey) => {
18667
20458
  const toolLattice = toolLatticeManager.getToolLattice(toolKey);
18668
20459
  if (!toolLattice) {
@@ -18679,7 +20470,7 @@ var AgentParamsBuilder = class {
18679
20470
  if (!model) {
18680
20471
  throw new Error(`Model "${modelKey}" does not exist`);
18681
20472
  }
18682
- const subAgentKeys = (0, import_protocols10.getSubAgentsFromConfig)(agentLattice.config);
20473
+ const subAgentKeys = (0, import_protocols11.getSubAgentsFromConfig)(agentLattice.config);
18683
20474
  const subAgents = await Promise.all(subAgentKeys.map(async (agentKey) => {
18684
20475
  const subAgentLattice = await this.getAgentLatticeFunc(agentKey);
18685
20476
  if (!subAgentLattice) {
@@ -18692,7 +20483,7 @@ var AgentParamsBuilder = class {
18692
20483
  };
18693
20484
  }));
18694
20485
  let internalSubAgents = [];
18695
- if ((0, import_protocols10.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols10.isProcessingAgentConfig)(agentLattice.config)) {
20486
+ if ((0, import_protocols11.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols11.isProcessingAgentConfig)(agentLattice.config)) {
18696
20487
  internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
18697
20488
  key: i.key,
18698
20489
  config: i
@@ -18704,6 +20495,7 @@ var AgentParamsBuilder = class {
18704
20495
  subAgents: [...subAgents, ...internalSubAgents],
18705
20496
  prompt: agentLattice.config.prompt,
18706
20497
  stateSchema: agentLattice.config.schema,
20498
+ responseFormat: agentLattice.config.responseFormat,
18707
20499
  skillCategories: skills,
18708
20500
  middleware: agentLattice.config.middleware,
18709
20501
  tenantId: agentLattice.config.tenantId
@@ -18732,6 +20524,7 @@ function mergeAgentConfig(parent, child) {
18732
20524
  }
18733
20525
 
18734
20526
  // src/store_lattice/configureStores.ts
20527
+ init_MemoryLatticeManager();
18735
20528
  var _disposables = [];
18736
20529
  var _cleanupRegistered = false;
18737
20530
  function registerSignalCleanup() {
@@ -19289,7 +21082,7 @@ ${body}` : `${frontmatter}
19289
21082
  // src/agent_lattice/agentArchitectTools.ts
19290
21083
  var import_zod53 = __toESM(require("zod"));
19291
21084
  var import_uuid5 = require("uuid");
19292
- var import_protocols11 = require("@axiom-lattice/protocols");
21085
+ var import_protocols12 = require("@axiom-lattice/protocols");
19293
21086
  function getTenantId(exeConfig) {
19294
21087
  const runConfig = exeConfig?.configurable?.runConfig || {};
19295
21088
  return runConfig.tenantId || "default";
@@ -19397,7 +21190,7 @@ registerToolLattice(
19397
21190
  key: id,
19398
21191
  name: input.name,
19399
21192
  description: input.description || "",
19400
- type: input.type === "deep_agent" ? import_protocols11.AgentType.DEEP_AGENT : import_protocols11.AgentType.REACT,
21193
+ type: input.type === "deep_agent" ? import_protocols12.AgentType.DEEP_AGENT : import_protocols12.AgentType.REACT,
19401
21194
  prompt: input.prompt,
19402
21195
  ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
19403
21196
  ...input.middleware && input.middleware.length > 0 ? { middleware: input.middleware } : {},
@@ -19486,7 +21279,7 @@ registerToolLattice(
19486
21279
  key: id,
19487
21280
  name: input.name,
19488
21281
  description: input.description || "",
19489
- type: import_protocols11.AgentType.PROCESSING,
21282
+ type: import_protocols12.AgentType.PROCESSING,
19490
21283
  prompt: input.prompt,
19491
21284
  ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
19492
21285
  middleware,
@@ -19513,6 +21306,190 @@ registerToolLattice(
19513
21306
  }
19514
21307
  }
19515
21308
  );
21309
+ var workflowStepLazy = import_zod53.default.lazy(
21310
+ () => import_zod53.default.discriminatedUnion("type", [
21311
+ import_zod53.default.object({ type: import_zod53.default.literal("agent").optional(), id: import_zod53.default.string().optional(), name: import_zod53.default.string().optional(), prompt: import_zod53.default.string(), schema: import_zod53.default.record(import_zod53.default.any()) }),
21312
+ import_zod53.default.object({ type: import_zod53.default.literal("human"), id: import_zod53.default.string().optional(), prompt: import_zod53.default.string(), title: import_zod53.default.string().optional(), schema: import_zod53.default.union([import_zod53.default.boolean(), import_zod53.default.record(import_zod53.default.any())]).optional() }),
21313
+ import_zod53.default.object({ type: import_zod53.default.literal("condition"), id: import_zod53.default.string().optional(), if: import_zod53.default.string().refine((v) => !v.includes("{{"), { message: 'The `if` field takes a plain state field name or JavaScript expression (e.g. "intent", "score >= 60"). Do NOT use {{}} template markers \u2014 those are only for `prompt` fields.' }), then: import_zod53.default.union([import_zod53.default.lazy(() => workflowStepLazy), import_zod53.default.array(import_zod53.default.lazy(() => workflowStepLazy))]).optional(), else: import_zod53.default.union([import_zod53.default.lazy(() => workflowStepLazy), import_zod53.default.array(import_zod53.default.lazy(() => workflowStepLazy))]).optional(), branches: import_zod53.default.record(import_zod53.default.union([import_zod53.default.lazy(() => workflowStepLazy), import_zod53.default.array(import_zod53.default.lazy(() => workflowStepLazy))])).optional() }),
21314
+ import_zod53.default.object({ type: import_zod53.default.literal("map"), id: import_zod53.default.string(), source: import_zod53.default.string(), each: import_zod53.default.object({ prompt: import_zod53.default.string(), schema: import_zod53.default.record(import_zod53.default.any()) }), reduce: import_zod53.default.object({ prompt: import_zod53.default.string(), schema: import_zod53.default.record(import_zod53.default.any()) }).optional(), batch: import_zod53.default.number().int().min(1).optional(), concurrency: import_zod53.default.number().int().min(1).optional() }),
21315
+ import_zod53.default.object({ type: import_zod53.default.literal("parallel"), id: import_zod53.default.string().optional(), steps: import_zod53.default.array(import_zod53.default.lazy(() => workflowStepLazy)) }),
21316
+ import_zod53.default.object({ type: import_zod53.default.literal("end"), status: import_zod53.default.enum(["success", "failed"]).optional() })
21317
+ ])
21318
+ );
21319
+ var workflowDSLSchema = import_zod53.default.object({
21320
+ name: import_zod53.default.string().describe("Workflow identifier (kebab-case slug)"),
21321
+ steps: import_zod53.default.array(workflowStepLazy).min(1).describe("Workflow steps. Edges and state fields are auto-generated. Use {{id}} to reference step outputs. Always end with { type: 'end' }.")
21322
+ });
21323
+ var createWorkflowSchema = import_zod53.default.object({
21324
+ name: import_zod53.default.string().describe("Display name for the workflow agent"),
21325
+ description: import_zod53.default.string().optional().describe("Short description of what this workflow does"),
21326
+ skillLoaded: import_zod53.default.literal(true).describe("MUST be true. Set this to true ONLY after loading the 'create-workflow' skill via skill(skill_name: 'create-workflow'). This confirms you have read the DSL specification and design guidelines."),
21327
+ workflow: workflowDSLSchema.describe("The concise Workflow DSL definition. Each step has a type (agent/human/condition/map/parallel/end) and a prompt. Edges are auto-generated from step order. Use {{id}} to reference upstream step outputs."),
21328
+ tools: import_zod53.default.array(import_zod53.default.string()).optional().describe("Tool keys for the workflow's built-in general agent"),
21329
+ middleware: import_zod53.default.array(middlewareConfigSchema).optional().describe("Middleware configs for the workflow's general agent"),
21330
+ modelKey: import_zod53.default.string().optional().describe("Model key for the workflow's general agent")
21331
+ });
21332
+ registerToolLattice(
21333
+ "create_workflow",
21334
+ {
21335
+ name: "create_workflow",
21336
+ description: `Create a WORKFLOW agent from a concise DSL. IMPORTANT: Load the 'create-workflow' skill first, then set skillLoaded=true. Steps are defined in order \u2014 the engine auto-generates edges and state fields. Types: agent(id?, name?, prompt, schema), human(prompt, title?, schema?), condition(if, then, else? OR if, branches with 'default' catch-all), map(source, each, reduce?), parallel(steps), end. Use {{id}} to reference step outputs, {{input}} for user message, {{item}} in map each prompts. Always end with { type: 'end' }. CRITICAL: schema MUST be standard JSON Schema: { "type": "object", "properties": { ... } }. Legacy shorthand { "field": "string" } is REJECTED.`,
21337
+ schema: createWorkflowSchema
21338
+ },
21339
+ async (input, exeConfig) => {
21340
+ try {
21341
+ const tenantId = getTenantId(exeConfig);
21342
+ const store = getAssistStore();
21343
+ const id = await generateAgentId(tenantId, input.name);
21344
+ const config = {
21345
+ key: id,
21346
+ name: input.name,
21347
+ description: input.description || "",
21348
+ type: import_protocols12.AgentType.WORKFLOW,
21349
+ prompt: input.description || `Workflow: ${input.name}`,
21350
+ workflow: input.workflow,
21351
+ ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
21352
+ ...input.middleware && input.middleware.length > 0 ? { middleware: input.middleware } : {},
21353
+ ...input.modelKey ? { modelKey: input.modelKey } : {}
21354
+ };
21355
+ try {
21356
+ const { compileWorkflow: compileWorkflow2 } = await Promise.resolve().then(() => (init_compile(), compile_exports));
21357
+ const { getCheckpointSaver: getCheckpointSaver2 } = await Promise.resolve().then(() => (init_memory_lattice(), memory_lattice_exports));
21358
+ await compileWorkflow2(input.workflow, async () => ({ invoke: async () => ({}) }), getCheckpointSaver2("default"));
21359
+ } catch (e) {
21360
+ return JSON.stringify({ error: `DSL validation failed: ${e.message}`, issues: [{ type: "error", message: e.message }] });
21361
+ }
21362
+ await store.createAssistant(tenantId, id, {
21363
+ name: input.name,
21364
+ description: input.description,
21365
+ graphDefinition: config
21366
+ });
21367
+ eventBus.publish("assistant:created", { id, name: input.name, tenantId });
21368
+ return JSON.stringify({
21369
+ id,
21370
+ name: input.name,
21371
+ type: "workflow",
21372
+ stepCount: input.workflow.steps.length
21373
+ });
21374
+ } catch (error) {
21375
+ return JSON.stringify({ error: `Failed to create workflow: ${error.message}` });
21376
+ }
21377
+ }
21378
+ );
21379
+ registerToolLattice(
21380
+ "validate_workflow",
21381
+ {
21382
+ name: "validate_workflow",
21383
+ description: "Validate a workflow agent's DSL for correctness by compiling it. Returns errors if the DSL is invalid. Use after create_workflow or update_workflow to verify.",
21384
+ schema: import_zod53.default.object({
21385
+ id: import_zod53.default.string().describe("The workflow agent ID to validate")
21386
+ })
21387
+ },
21388
+ async (input, exeConfig) => {
21389
+ try {
21390
+ const tenantId = getTenantId(exeConfig);
21391
+ const store = getAssistStore();
21392
+ const agent = await store.getAssistantById(tenantId, input.id);
21393
+ if (!agent) {
21394
+ return JSON.stringify({ error: `Agent '${input.id}' not found` });
21395
+ }
21396
+ const graphDef = agent.graphDefinition;
21397
+ if (!graphDef || graphDef.type !== import_protocols12.AgentType.WORKFLOW) {
21398
+ return JSON.stringify({ error: `Agent '${input.id}' is not a workflow agent (type: ${graphDef?.type ?? "unknown"})` });
21399
+ }
21400
+ const workflow = graphDef.workflow;
21401
+ if (!workflow || !workflow.steps) {
21402
+ return JSON.stringify({ error: `Agent '${input.id}' has no valid workflow DSL` });
21403
+ }
21404
+ try {
21405
+ const { compileWorkflow: compileWorkflow2 } = await Promise.resolve().then(() => (init_compile(), compile_exports));
21406
+ const { getCheckpointSaver: getCheckpointSaver2 } = await Promise.resolve().then(() => (init_memory_lattice(), memory_lattice_exports));
21407
+ await compileWorkflow2(workflow, async () => ({ invoke: async () => ({}) }), getCheckpointSaver2("default"));
21408
+ } catch (e) {
21409
+ return JSON.stringify({
21410
+ agentId: input.id,
21411
+ valid: false,
21412
+ stepCount: workflow.steps?.length ?? 0,
21413
+ issues: [{ type: "error", message: e.message }]
21414
+ });
21415
+ }
21416
+ return JSON.stringify({
21417
+ agentId: input.id,
21418
+ valid: true,
21419
+ stepCount: workflow.steps?.length ?? 0,
21420
+ issues: []
21421
+ });
21422
+ } catch (error) {
21423
+ return JSON.stringify({ error: `Failed to validate workflow: ${error.message}` });
21424
+ }
21425
+ }
21426
+ );
21427
+ var updateWorkflowSchema = import_zod53.default.object({
21428
+ id: import_zod53.default.string().describe("The workflow agent ID to update"),
21429
+ name: import_zod53.default.string().optional().describe("New display name"),
21430
+ description: import_zod53.default.string().optional().describe("New description"),
21431
+ workflow: workflowDSLSchema.optional().describe("Replacement Workflow DSL definition. Omit to keep the existing."),
21432
+ tools: import_zod53.default.array(import_zod53.default.string()).optional().describe("Replacement tool keys for the general agent"),
21433
+ middleware: import_zod53.default.array(middlewareConfigSchema).optional().describe("Replacement middleware configs"),
21434
+ modelKey: import_zod53.default.string().optional().describe("Replacement model key")
21435
+ });
21436
+ registerToolLattice(
21437
+ "update_workflow",
21438
+ {
21439
+ name: "update_workflow",
21440
+ description: "Update an existing workflow agent. Provide the agent ID and only the fields you want to change. To replace the entire DSL, pass a new workflow object. To keep the DSL and only update config (tools, middleware, modelKey), omit the workflow field. Use validate_workflow after updating to check for issues.",
21441
+ schema: updateWorkflowSchema
21442
+ },
21443
+ async (input, exeConfig) => {
21444
+ try {
21445
+ const tenantId = getTenantId(exeConfig);
21446
+ const store = getAssistStore();
21447
+ const existing = await store.getAssistantById(tenantId, input.id);
21448
+ if (!existing) {
21449
+ return JSON.stringify({ error: `Agent '${input.id}' not found` });
21450
+ }
21451
+ const existingConfig = existing.graphDefinition || {};
21452
+ if (existingConfig.type !== import_protocols12.AgentType.WORKFLOW) {
21453
+ return JSON.stringify({ error: `Agent '${input.id}' is not a workflow agent` });
21454
+ }
21455
+ const mergedConfig = { ...existingConfig };
21456
+ if (input.name !== void 0) mergedConfig.name = input.name;
21457
+ if (input.description !== void 0) mergedConfig.description = input.description;
21458
+ if (input.workflow !== void 0) mergedConfig.workflow = input.workflow;
21459
+ if (input.tools !== void 0) mergedConfig.tools = input.tools;
21460
+ if (input.middleware !== void 0) mergedConfig.middleware = input.middleware;
21461
+ if (input.modelKey !== void 0) mergedConfig.modelKey = input.modelKey;
21462
+ if (input.workflow !== void 0) {
21463
+ try {
21464
+ const { compileWorkflow: compileWorkflow2 } = await Promise.resolve().then(() => (init_compile(), compile_exports));
21465
+ const { getCheckpointSaver: getCheckpointSaver2 } = await Promise.resolve().then(() => (init_memory_lattice(), memory_lattice_exports));
21466
+ await compileWorkflow2(input.workflow, async () => ({ invoke: async () => ({}) }), getCheckpointSaver2("default"));
21467
+ } catch (e) {
21468
+ return JSON.stringify({
21469
+ error: `DSL validation failed: ${e.message}`,
21470
+ issues: [{ type: "error", message: e.message }]
21471
+ });
21472
+ }
21473
+ }
21474
+ const newName = input.name || existing.name;
21475
+ await store.updateAssistant(tenantId, input.id, {
21476
+ name: newName,
21477
+ description: input.description !== void 0 ? input.description : existing.description,
21478
+ graphDefinition: mergedConfig
21479
+ });
21480
+ eventBus.publish("assistant:updated", { id: input.id, name: newName, tenantId });
21481
+ const workflow = mergedConfig.workflow;
21482
+ return JSON.stringify({
21483
+ id: input.id,
21484
+ name: newName,
21485
+ type: "workflow",
21486
+ stepCount: workflow?.steps?.length ?? 0
21487
+ });
21488
+ } catch (error) {
21489
+ return JSON.stringify({ error: `Failed to update workflow: ${error.message}` });
21490
+ }
21491
+ }
21492
+ );
19516
21493
  var updateProcessingAgentSchema = import_zod53.default.object({
19517
21494
  id: import_zod53.default.string().describe("The PROCESSING agent ID to update"),
19518
21495
  name: import_zod53.default.string().optional().describe("New display name for the orchestrator"),
@@ -19554,7 +21531,7 @@ registerToolLattice(
19554
21531
  return JSON.stringify({ error: `Agent '${input.id}' not found` });
19555
21532
  }
19556
21533
  const existingConfig = existing.graphDefinition || {};
19557
- if (existingConfig.type !== import_protocols11.AgentType.PROCESSING) {
21534
+ if (existingConfig.type !== import_protocols12.AgentType.PROCESSING) {
19558
21535
  return JSON.stringify({ error: `Agent '${input.id}' is not a PROCESSING agent (type: ${existingConfig.type})` });
19559
21536
  }
19560
21537
  const normalize = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
@@ -19769,24 +21746,16 @@ registerToolLattice(
19769
21746
  thread_id: threadId
19770
21747
  });
19771
21748
  const result = await agent.invoke({ input: { message } });
19772
- const messages = result?.messages || [];
19773
- const lastAi = [...messages].reverse().find(
19774
- (m) => m.role === "ai" || m.type === "ai"
19775
- );
19776
- const content = lastAi?.content ?? "(no response)";
19777
- return JSON.stringify({
19778
- agentId: id,
19779
- threadId,
19780
- response: typeof content === "string" ? content : JSON.stringify(content)
19781
- });
21749
+ return JSON.stringify({ agentId: id, threadId, result });
19782
21750
  } catch (error) {
21751
+ console.error(`[invoke_agent] FAILED for agent="${input.id}":`, error.stack || error.message);
19783
21752
  return JSON.stringify({ error: `Failed to invoke agent: ${error.message}` });
19784
21753
  }
19785
21754
  }
19786
21755
  );
19787
21756
 
19788
21757
  // src/agent_lattice/agentArchitectConfig.ts
19789
- var import_protocols13 = require("@axiom-lattice/protocols");
21758
+ var import_protocols14 = require("@axiom-lattice/protocols");
19790
21759
 
19791
21760
  // src/agent_lattice/agentArchitectPrompt.ts
19792
21761
  var AGENT_ARCHITECT_PROMPT = `# Agent Architect
@@ -19803,12 +21772,12 @@ Every agent interaction follows this cycle. You MUST NOT skip any phase:
19803
21772
  |-------|-------------|-------------------|
19804
21773
  | **1. DESIGN** | Understand requirements, choose agent type, design config (prompt, middleware, sub-agents), create topology/architecture diagram | Present the design clearly. Use \`show_widget\` for visual diagrams. |
19805
21774
  | **2. CONFIRM** | User reviews and approves the design | **MUST explicitly ask for approval.** Say: "Does this design look good? Shall I create it?" NEVER create or update anything without clear user confirmation. |
19806
- | **3. BUILD** | Call \`create_agent\`, \`create_processing_agent\`, or \`update_agent\` | Only after confirmation. Report the result (ID, name). |
21775
+ | **3. BUILD** | Call \`create_agent\`, \`create_workflow\`, or \`update_agent\` / \`update_workflow\` | Only after confirmation. Report the result (ID, name). |
19807
21776
  | **4. TEST** | Verify the agent works correctly | You may ask the user if they want you to test. If yes, delegate to the **Agent Reviewer** sub-agent. Do NOT test until the user confirms. |
19808
21777
 
19809
21778
  **CRITICAL RULES:**
19810
21779
  - **NEVER build before confirming.** Design \u2192 ask \u2192 wait for "yes" \u2192 only then build.
19811
- - **Edit, don't re-create.** After an agent exists, modifying it ALWAYS means \`update_agent\` or \`update_processing_agent\` \u2014 NEVER \`create_agent\` or \`create_processing_agent\` again. If you just created an agent and the user wants to change something, use the update tool for that agent.
21780
+ - **Edit, don't re-create.** After an agent exists, modifying it ALWAYS means \`update_agent\` or \`update_workflow\` \u2014 NEVER \`create_agent\` or \`create_workflow\` again. If you just created an agent and the user wants to change something, use the update tool for that agent.
19812
21781
  - **NEVER test proactively.** You may ask if the user wants to test \u2014 but do NOT invoke the Reviewer until they say yes. Never test yourself.
19813
21782
  - **One decision at a time.** Each message asks exactly one question.
19814
21783
 
@@ -19819,7 +21788,7 @@ Once an agent is created, NEVER create another agent for the same purpose. If th
19819
21788
  | User wants to... | Use |
19820
21789
  |-----------------|-----|
19821
21790
  | Change prompt, tools, middleware, name | \`update_agent\` |
19822
- | Change topology, edges, sub-agents | \`update_processing_agent\` |
21791
+ | Change workflow DSL, tools, middleware | \`update_workflow\` |
19823
21792
  | See current config | \`get_agent\` |
19824
21793
 
19825
21794
  If the user's intent is unclear after creation, ask: "Edit this agent or create a new one?"
@@ -19831,8 +21800,9 @@ You have nine tools for agent management:
19831
21800
  - **list_tools** \u2014 See all available tools that can be assigned to agents
19832
21801
  - **get_agent** \u2014 View the full configuration of a specific agent
19833
21802
  - **create_agent** \u2014 Create a REACT or DEEP_AGENT agent
19834
- - **create_processing_agent** \u2014 Create a PROCESSING agent with business-defined workflow topology
19835
- - **update_processing_agent** \u2014 Modify a PROCESSING agent's topology edges, name, prompt, or sub-agents
21803
+ - **create_workflow** \u2014 Create a WORKFLOW agent from a concise DSL (load create-workflow skill first)
21804
+ - **validate_workflow** \u2014 Validate a workflow agent's DSL
21805
+ - **update_workflow** \u2014 Update a workflow agent's DSL or config
19836
21806
  - **update_agent** \u2014 Modify an existing REACT or DEEP_AGENT agent's configuration
19837
21807
  - **delete_agent** \u2014 Remove an agent permanently
19838
21808
  - **manage_binding** \u2014 Bind a sender (email, Lark, Slack user) to an agent so external messages are routed to it
@@ -19870,7 +21840,7 @@ Let the \`show_widget\` tool handle rendering details \u2014 it has its own guid
19870
21840
  | Type | Best for | Execution Model |
19871
21841
  |------|----------|----------------|
19872
21842
  | **react** | Simple, single-responsibility tasks | Classic ReAct loop (think \u2192 act \u2192 observe) |
19873
- | **processing** | Standard BPO workflows, preset process orchestration | Topology-driven: predefined agent topology with reliable multi-agent coordination |
21843
+ | **workflow** | Deterministic multi-step pipelines with branching, parallel, and human-in-the-loop | Concise DSL compiled into LangGraph state machine |
19874
21844
  | **deep_agent** | Complex, open-ended tasks requiring dynamic decomposition | Self-generating dynamic todos: agent analyzes the task and creates its own execution plan at runtime |
19875
21845
 
19876
21846
  When a user is unsure which type to choose, use \`show_widget\` to render a visual comparison \u2014 show each type's execution model side-by-side as an interactive diagram so the user can intuitively understand the differences.
@@ -19908,233 +21878,61 @@ You may ask: "Want me to send this to the Agent Reviewer for testing?" If yes, d
19908
21878
 
19909
21879
  ---
19910
21880
 
19911
- ## Workflow B: Workflow Agent (PROCESSING type)
19912
-
19913
- Use this when the task follows a standard BPO (Business Process Orchestration) pattern \u2014 a predefined topology of sub-agents working through a preset pipeline.
19914
-
19915
- ### Phase 1: Design
19916
-
19917
- **Step 1: Process analysis.** Ask: What is the end-to-end process? Map the stages.
19918
-
19919
- **Business rule \u2014 Draft-then-confirm pattern:** When a workflow creates business objects that require human approval (e.g., draft orders in SAP B1, purchase requisitions, expense reports), the design MUST include a confirmation step AFTER the creation step. The create step must complete successfully before the confirm step runs. The flow is always: **Create draft \u2192 User confirms \u2192 Finalize**. Reason: systems like SAP B1 only expose drafts to users after they are created \u2014 the user cannot see or approve something that doesn't exist yet. The confirm step MUST use the \`ask_user_to_clarify\` middleware.
19920
-
19921
- **Business pattern \u2014 SAP B1 Draft SO Creation:** When designing a sub-agent responsible for creating draft Sales Orders in SAP B1, embed the following standards into its system prompt. These ensure consistent data construction, API usage, and user presentation:
21881
+ ## Workflow B: Processing Agent (PROCESSING type) [DEPRECATED]
19922
21882
 
19923
- **Step 1: Construct SO Data Structure**
19924
- Build the JSON payload. For each DocumentLines item:
19925
- - Include \`WarehouseCode\` ONLY if sku.json provides a value; if missing or empty, OMIT the field entirely
19926
- - Generate \`Comments\` dynamically based on context (customer name, PO reference, special instructions)
21883
+ The PROCESSING agent type is deprecated. Use the WORKFLOW DSL type (Workflow D below) instead. If a user asks for a multi-step pipeline, guide them toward the WORKFLOW DSL approach.
19927
21884
 
19928
- \`\`\`json
19929
- {
19930
- "DocObjectCode": "17",
19931
- "DocType": "dDocument_Items",
19932
- "CardCode": "C001",
19933
- "DocDate": "current date",
19934
- "DocDueDate": "delivery date",
19935
- "TaxDate": "current date",
19936
- "U_YWLX": "Modern Trade",
19937
- "Comments": "SO for Kaimay Retail - PO ref: PO-2024-001234",
19938
- "DocumentLines": [
19939
- {
19940
- "ItemCode": "SKU001",
19941
- "Quantity": 240,
19942
- "UnitPrice": 15.84
19943
- }
19944
- ]
19945
- }
19946
- \`\`\`
21885
+ ---
19947
21886
 
19948
- Field mapping rules:
19949
- | SAP Field | Data Source |
19950
- |-----------|-------------|
19951
- | CardCode | customer.json \u2192 CardCode |
19952
- | DocDate | Current date (yyyy-MM-dd) |
19953
- | DocDueDate | extracted.json \u2192 delivery_date |
19954
- | TaxDate | Current date (yyyy-MM-dd) |
19955
- | U_YWLX | customer.json \u2192 SalesType |
19956
- | ItemCode | sku.json \u2192 ItemCode |
19957
- | Quantity | extracted.json \u2192 Quantity |
19958
- | WarehouseCode | sku.json \u2192 WarehouseCode (OMIT if missing/empty) |
19959
- | UnitPrice | price.json \u2192 UnitPrice |
19960
- | Comments | AI-generated based on customer name, PO reference, and context |
19961
-
19962
- **Step 2: Call SAP API to Create Draft (MUST EXECUTE)**
19963
- Use the \`sap_api_call\` tool with EXACTLY these parameters:
19964
- - **Method**: POST
19965
- - **Endpoint**: \`Drafts\` (ONLY allowed endpoint; do NOT call SalesOrders or any other endpoint)
19966
- - **Body**: The JSON constructed in Step 1
19967
-
19968
- CRITICAL: You MUST call sap_api_call BEFORE proceeding to Step 3. This step is NOT optional.
19969
-
19970
- If the API call fails:
19971
- - Log the error details
19972
- - STOP the process
19973
- - Report the failure to the user with the error message
19974
- - Do NOT proceed to Step 3
19975
-
19976
- **Step 3: Present Draft for User Review (MUST EXECUTE AFTER Step 2)**
19977
- ONLY after the SAP API call in Step 2 succeeds, use the \`ask_user_to_clarify\` tool to present the complete SO summary.
19978
-
19979
- Message format (STRICT \u2014 no emoji, no summary, field names match Service Layer):
19980
-
19981
- === Sales Order Draft ===
19982
-
19983
- DocEntry: {DocEntry}
19984
- DocNum: {DocNum}
19985
- DocDate: {DocDate}
19986
- DocDueDate: {DocDueDate}
19987
- CardCode: {CardCode}
19988
- CardName: {CardName}
19989
- U_YWLX: {SalesType}
19990
- Comments: {Comments}
19991
-
19992
- DocumentLines:
19993
- LineNum | ItemCode | Quantity | WarehouseCode | UnitPrice | LineTotal
19994
- 0 | {ItemCode} | {Quantity} | {WarehouseCode} | {UnitPrice} | {LineTotal}
19995
- 1 | {ItemCode} | {Quantity} | {WarehouseCode} | {UnitPrice} | {LineTotal}
19996
- ...
19997
-
19998
- DocTotal: {DocTotal}
19999
-
20000
- Warnings:
20001
- - {warning1}
20002
- - {warning2}
20003
-
20004
- Options:
20005
- [Confirm generating draft]
20006
- [Cancel, do not generate]
20007
-
20008
- **Data sharing pattern \u2014 File-based handoff:** Every sub-agent in the pipeline MUST persist its work results as files under a shared project directory, never rely on in-memory data passing between steps. Deep agents have built-in file capabilities, so no middleware is needed.
20009
-
20010
- Rules:
20011
- 1. The **orchestrator** generates a unique project ID at the start (e.g., timestamp-based) and passes it to each sub-agent in the task context
20012
- 2. Each sub-agent reads input from \`/project/{project-id}/\` and writes output files into the same directory
20013
- 3. Establish clear file naming conventions so downstream steps know exactly which files to read (e.g., \`extracted.json\`, \`sku.json\`, \`customer.json\`, \`so_draft.json\`)
20014
- 4. The orchestrator's system prompt MUST specify for each edge: which files the target sub-agent should read and which files it should produce
20015
-
20016
- **Step 2: Topology design.** Design the agent topology and use \`show_widget\` to render an interactive diagram showing the flow: Orchestrator \u2192 Stage 1 \u2192 Stage 2 \u2192 ... \u2192 Output. Each edge should be labeled with its business purpose.
20017
-
20018
- **Step 3: Design each sub-agent** as a **deep_agent** type (one at a time). For each:
20019
- - Responsibility, system prompt, middleware, file input/output contract (which files from \`/project/{project-id}/\` it reads, which files it writes)
20020
- - Deep agents have built-in file capabilities (ls, read, write, edit, glob, grep), so do NOT add filesystem middleware.
20021
- - **Ask for confirmation before moving to the next sub-agent.**
20022
-
20023
- **Step 4: Design the orchestrator.** Responsibility, system prompt, topology edges, sub-agent list.
20024
-
20025
- **Step 5: Self-review checklist.** Before presenting to the user, verify:
20026
- - Completeness (every stage covered by an edge?)
20027
- - Purposes clear (each edge's business intent?)
20028
- - Order correct (serial chain logical?)
20029
- - Edge cases (invalid input, failure, timeout?)
20030
-
20031
- **Step 6: Write the workflow description (Spec).** After designing the topology and sub-agents, compose a comprehensive **\`description\`** for the orchestrator. This description serves as the workflow's specification \u2014 anyone reading it should understand exactly what this workflow does without needing to inspect individual sub-agent configs.
20032
-
20033
- The description MUST include ALL of the following:
20034
-
20035
- | Section | Content |
20036
- |---------|---------|
20037
- | **Overview** | One-sentence summary of the workflow's purpose and business value |
20038
- | **Steps** | Numbered list of each stage in the pipeline. For each step: which sub-agent handles it, what it does, what tools it uses, what files it reads from \`/project/{project-id}/\`, and what files it writes. |
20039
- | **Data Flow** | How data moves between steps via files under \`/project/{project-id}/\`. For each step: which files it reads as input and which files it writes as output. |
20040
- | **Logic & Conditions** | Any conditional branching, decision points, retry logic, or exception handling. When does the workflow take path A vs path B? What happens on failure? |
20041
- | **Tools Used** | Summary table or list of all tools used across sub-agents, grouped by sub-agent |
20042
- | **Expected Input** | What input does the workflow expect from the user? (format, examples) |
20043
- | **Expected Output** | What does the workflow produce at the end? (format, examples) |
20044
-
20045
- **Formatting rules:**
20046
- - Write in **English**
20047
- - Use **Markdown** for formatting (headings, lists, tables, code blocks)
20048
- - Be detailed but concise \u2014 each section should be 1-5 lines
20049
- - Avoid placeholder text like "TODO" or "TBD"
20050
-
20051
- **Example structure** (\u5B50 Agent \u5747\u4E3A deep_agent \u7C7B\u578B\uFF0C\u65E0\u9700 filesystem \u4E2D\u95F4\u4EF6):
20052
-
20053
- \`\`\`markdown
20054
- ## Overview
20055
- \u672C\u5DE5\u4F5C\u6D41\u81EA\u52A8\u4ECE\u591A\u4E2A\u6570\u636E\u6E90\u91C7\u96C6\u7ADE\u54C1\u4EF7\u683C\uFF0C\u751F\u6210\u5BF9\u6BD4\u5206\u6790\u62A5\u544A\u5E76\u63A8\u9001\u901A\u77E5\u3002
20056
-
20057
- ## Steps
20058
- 1. **\u6570\u636E\u91C7\u96C6 (data-collector)** \u2014 \u4F7F\u7528 browser \u5DE5\u5177\u722C\u53D6\u6307\u5B9AURL\u7684\u7ADE\u54C1\u4EF7\u683C\u6570\u636E\uFF0C\u8C03\u7528 metrics API \u62C9\u53D6\u5386\u53F2\u4EF7\u683C\u3002\u8F93\u51FA \u2192 \`raw_prices.json\`
20059
- 2. **\u6570\u636E\u6E05\u6D17 (data-cleaner)** \u2014 \u8BFB\u53D6 \`raw_prices.json\`\uFF0C\u4F7F\u7528 code_eval \u6267\u884C Python \u811A\u672C\u6E05\u6D17\u5F02\u5E38\u503C\u548C\u7F3A\u5931\u503C\uFF0C\u7EDF\u4E00\u8D27\u5E01\u5355\u4F4D\u3002\u8F93\u51FA \u2192 \`cleaned_prices.json\`
20060
- 3. **\u62A5\u544A\u751F\u6210 (report-generator)** \u2014 \u8BFB\u53D6 \`cleaned_prices.json\` \u548C\u6A21\u677F\u6587\u4EF6\uFF0Ccode_eval \u8BA1\u7B97\u6DA8\u8DCC\u5E45\u548C\u8D8B\u52BF\uFF0C\u751F\u6210 Markdown \u5BF9\u6BD4\u62A5\u544A\u3002\u8F93\u51FA \u2192 \`report.md\`
20061
- 4. **\u901A\u77E5\u63A8\u9001 (notifier)** \u2014 \u8BFB\u53D6 \`report.md\`\uFF0C\u8C03\u7528 scheduler \u5B89\u6392\u5B9A\u65F6\u53D1\u9001\uFF0C\u4F7F\u7528 ask_user_to_clarify \u8BF7\u6C42\u53D1\u9001\u786E\u8BA4\u3002\u8F93\u51FA\u53D1\u9001\u7ED3\u679C\u3002
20062
-
20063
- ## Data Flow
20064
- All data is shared via files under \`/project/{project-id}/\`:
20065
- \`\u7528\u6237\u8F93\u5165\` \u2192 data-collector writes \`raw_prices.json\` \u2192 data-cleaner reads \`raw_prices.json\`, writes \`cleaned_prices.json\` \u2192 report-generator reads \`cleaned_prices.json\`, writes \`report.md\` \u2192 notifier reads \`report.md\`, pushes
20066
-
20067
- ## Logic & Conditions
20068
- - data-collector \u722C\u53D6\u5931\u8D25\u65F6\u91CD\u8BD5\u6700\u591A3\u6B21\uFF0C\u95F4\u969430\u79D2
20069
- - \u82E5\u67D0\u4E00\u5546\u54C1\u4EF7\u683C\u7F3A\u5931\u8D85\u8FC77\u5929\uFF0C\u6807\u8BB0\u4E3A\u300C\u6570\u636E\u4E0D\u5168\u300D\u5E76\u5728\u62A5\u544A\u4E2D\u9AD8\u4EAE
20070
- - report-generator \u8BA1\u7B97\u6DA8\u5E45\u8D85\u8FC720%\u65F6\u81EA\u52A8\u6807\u8BB0\u300C\u5F02\u5E38\u6CE2\u52A8\u300D\u8B66\u544A
20071
- - \u4EFB\u4F55\u6B65\u9AA4\u5931\u8D25\u65F6\uFF0Cworkflow \u505C\u6B62\u5E76\u5C06\u9519\u8BEF\u4FE1\u606F\u8F93\u51FA\u5230\u6700\u7EC8\u62A5\u544A
20072
-
20073
- ## Tools Used
20074
- | \u5B50Agent | \u5DE5\u5177 |
20075
- |---------|------|
20076
- | data-collector | browser, metrics |
20077
- | data-cleaner | code_eval |
20078
- | report-generator | code_eval |
20079
- | notifier | scheduler, ask_user_to_clarify |
20080
-
20081
- ## Expected Input
20082
- - \u7ADE\u54C1URL\u5217\u8868\uFF08\u6BCF\u884C\u4E00\u4E2A\uFF09
20083
- - \u65E5\u671F\u8303\u56F4\uFF08\u8D77\u59CB-\u7ED3\u675F\uFF0C\u683C\u5F0F YYYY-MM-DD\uFF09
20084
- - \u63A8\u9001\u6E20\u9053\u9009\u62E9\uFF08\u90AE\u4EF6/\u9489\u9489/\u4F01\u4E1A\u5FAE\u4FE1\uFF09
20085
-
20086
- ## Expected Output
20087
- - Markdown \u683C\u5F0F\u5BF9\u6BD4\u62A5\u544A\uFF0C\u5305\u542B\u4EF7\u683C\u8D8B\u52BF\u56FE\u3001\u6DA8\u8DCC\u5E45\u3001\u5F02\u5E38\u6807\u8BB0
20088
- - \u62A5\u544A\u6587\u4EF6\u8DEF\u5F84\u53CA\u63A8\u9001\u72B6\u6001\u786E\u8BA4
20089
- \`\`\`
21887
+ ## Workflow C: Workflow DSL Agent (WORKFLOW type)
20090
21888
 
20091
- **The description field is the single source of truth for the workflow.** When the user clicks the info icon on the workflow in the automation view, they will see this description rendered as a Popover. It must be comprehensive enough to stand alone as a spec document.
21889
+ Use this when the process is fully known. A workflow is a deterministic LangGraph state machine compiled from a concise JSON DSL.
20092
21890
 
20093
- ### Phase 2: Confirm
21891
+ ### When to choose WORKFLOW
20094
21892
 
20095
- Present the full design: topology diagram, all sub-agent configs, orchestrator config, AND the workflow description (spec). **Ask for explicit approval:** "Ready to build? I'll create {N} sub-agents, then the orchestrator. Proceed?" **Do NOT build until the user confirms.**
21893
+ | WORKFLOW (DSL) | PROCESSING (deprecated) |
21894
+ |---|---|
21895
+ | Fixed graph \u2014 all paths pre-defined | LLM-driven runtime routing |
21896
+ | Conditional branching via \`if\` field | Topology-constrained delegation |
21897
+ | human, map, parallel, condition | Single orchestrator delegates linearly |
21898
+ | No LLM routing decisions | Orchestrator uses LLM to route |
20096
21899
 
20097
- ### Phase 3: Build
21900
+ ### Phase 0: Load the Skill
20098
21901
 
20099
- Create sub-agents FIRST, then the orchestrator:
21902
+ **BEFORE designing, you MUST load the create-workflow skill:**
20100
21903
 
20101
21904
  \`\`\`
20102
- 1. create_agent(name: "stage-1", type: "deep_agent", ...)
20103
- 2. create_agent(name: "stage-2", type: "deep_agent", ...)
20104
- 3. create_agent(name: "stage-3", type: "deep_agent", ...)
20105
- 4. create_processing_agent(
20106
- name: "orchestrator",
20107
- prompt: "...",
20108
- edges: [
20109
- { from: "orchestrator", to: "stage-1-id", purpose: "Validate input" },
20110
- { from: "stage-1-id", to: "stage-2-id", purpose: "Transform data" },
20111
- { from: "stage-2-id", to: "stage-3-id", purpose: "Generate output" },
20112
- ],
20113
- subAgents: ["stage-1-id", "stage-2-id", "stage-3-id"],
20114
- )
21905
+ skill(skill_name: "create-workflow")
20115
21906
  \`\`\`
20116
21907
 
20117
- First edge's \`from\` uses orchestrator name as placeholder (auto-resolved). Subsequent edges chain from previous sub-agent IDs.
20118
-
20119
- ### Phase 4: Test (ask first)
21908
+ ### Phase 1: Design
20120
21909
 
20121
- You may ask: "Want me to test the orchestrator end-to-end?" If yes, delegate to the **Agent Reviewer** sub-agent.
21910
+ 1. **Analyze the process.** Map every step, branch, data dependency.
21911
+ 2. **Choose step types:**
21912
+ - \`agent\` \u2014 runs on the workflow's built-in agent. Output at \`state.<id>\`.
21913
+ - \`human\` \u2014 pauses for human input (built-in clarify middleware). Has \`prompt\`, \`title\`, \`schema\`.
21914
+ - \`condition\` \u2014 branches on \`if\` (field or expression). Has \`then\`/\`else\` or \`branches\` (switch with \`default\`).
21915
+ - \`map\` \u2014 iterates array from \`source\`, applies \`each\`, optionally \`reduce\`.
21916
+ - \`parallel\` \u2014 runs \`steps\` simultaneously, then rejoins.
21917
+ - \`end\` \u2014 terminates. Always required at end.
21918
+ 3. **Write prompts** with \`{{id}}\` refs. \`{{input}}\` = user message. \`{{item}}\` = map element.
21919
+ 4. **No edges or state fields needed** \u2014 the engine auto-generates them.
20122
21920
 
20123
- ### Phase 5: Bind channel (ask)
21921
+ ### Phase 2: Confirm
20124
21922
 
20125
- After the workflow is created, ask the user if they want to bind an email address (or Lark/Slack sender) to drive the workflow. This allows external users to trigger the workflow by sending messages to the channel.
21923
+ Present the design. Ask: "Ready to create this workflow?"
20126
21924
 
20127
- **Step 1: Check installations.** Call \`manage_binding\` with \`action: "list_installations"\` to see available channel installations.
21925
+ ### Phase 3: Build
20128
21926
 
20129
- **Step 2: Ask user.** Present the available channels and ask: "Would you like to bind an email address to drive this workflow? If so, what email address should trigger it?"
21927
+ Call \`create_workflow\` with \`skillLoaded: true\`. Then \`validate_workflow(id)\`.
20130
21928
 
20131
- **Step 3: Bind.** Call \`manage_binding\` with \`action: "create"\`, providing \`channel\`, \`senderId\` (the email), and \`agentId\` (the orchestrator's ID).
21929
+ ### Phase 4: Test
20132
21930
 
20133
- **IMPORTANT:** Only create a binding after the user explicitly provides the email address. Do NOT guess or fabricate sender information.
21931
+ Ask the user if they want to test.
20134
21932
 
20135
21933
  ---
20136
21934
 
20137
- ## Workflow C: Dynamic Agent (DEEP_AGENT type)
21935
+ ## Workflow D: Dynamic Agent (DEEP_AGENT type)
20138
21936
 
20139
21937
  Use this for complex, open-ended tasks where the execution path cannot be fully predetermined. The DEEP_AGENT self-generates a dynamic todo list and iteratively works through it.
20140
21938
 
@@ -20185,7 +21983,7 @@ Follow the same Design \u2192 Confirm \u2192 Build cycle. Test only on request.
20185
21983
  2. Understand what the user wants to change
20186
21984
  3. **DESIGN**: Present the proposed changes clearly. Show a before/after diff.
20187
21985
  4. **CONFIRM**: Ask for explicit approval. Do NOT call update_agent until confirmed.
20188
- 5. **BUILD**: Call **update_agent** (or **update_processing_agent** for PROCESSING agents)
21986
+ 5. **BUILD**: Call **update_agent** (or **update_workflow** for WORKFLOW agents)
20189
21987
  6. **TEST**: You may ask if they want to test. If yes, delegate to the **Agent Reviewer** sub-agent
20190
21988
 
20191
21989
  ## Deleting Agents
@@ -20216,28 +22014,53 @@ All fields except name, type, and prompt are optional.
20216
22014
  }
20217
22015
  \`\`\`
20218
22016
 
20219
- ### create_processing_agent (PROCESSING)
22017
+ ### create_workflow (WORKFLOW)
20220
22018
 
20221
- Creates a PROCESSING agent with a business-defined workflow topology. Sub-agents must already exist (created as **deep_agent** type).
22019
+ Creates a WORKFLOW agent from a concise DSL. Before calling, load the \`create-workflow\` skill for the complete DSL specification. Must pass \`skillLoaded: true\`.
20222
22020
 
20223
22021
  \`\`\`typescript
20224
22022
  {
20225
- name: string, // Required. Display name for the orchestrator
20226
- description?: string, // Required for good UX. Comprehensive workflow spec in Markdown (English). Must cover: Overview, Steps (with tools per step), Data Flow, Logic & Conditions, Tools Used, Expected Input, Expected Output. This is the single source of truth displayed in the automation view info popover.
20227
- prompt: string, // Required. System prompt \u2014 how to route through the topology
20228
- edges: [{ // Required. At least 1 edge defining the serial workflow chain
20229
- from: string, // Source agent ID. First edge: use orchestrator name as placeholder (tool auto-replaces). Subsequent edges: previous sub-agent ID
20230
- to: string, // Sub-agent ID to delegate to
20231
- purpose: string, // Business purpose \u2014 what this step accomplishes
20232
- }],
20233
- tools?: string[], // Optional. Tool keys from list_tools
20234
- subAgents: string[], // Required. IDs of sub-agents in the pipeline
20235
- internalSubAgents?: AgentConfig[], // Optional. Inline sub-agent configs
20236
- middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology is auto-added)
20237
- modelKey?: string, // Optional. Model to use
22023
+ name: string, // Required. Display name
22024
+ description?: string, // Optional. Short description
22025
+ skillLoaded: true, // Required. Must be true \u2014 confirms skill was loaded
22026
+ workflow: { // Required. Concise DSL definition
22027
+ name: string, // Workflow slug identifier
22028
+ steps: WorkflowStep[], // agent | human | condition | map | parallel | end
22029
+ },
22030
+ tools?: string[], // Optional. Tool keys for the built-in general agent
22031
+ middleware?: MiddlewareConfig[], // Optional. Middleware for the general agent
22032
+ modelKey?: string, // Optional. Model for the general agent
20238
22033
  }
20239
22034
  \`\`\`
20240
22035
 
22036
+ ### update_workflow
22037
+
22038
+ Updates an existing WORKFLOW agent. Only include fields you want to change.
22039
+
22040
+ \`\`\`typescript
22041
+ {
22042
+ id: string, // Required. Workflow agent ID
22043
+ name?: string, // Optional
22044
+ description?: string, // Optional
22045
+ workflow?: { name: string, steps: WorkflowStep[] }, // Optional. Replacement DSL
22046
+ tools?: string[], // Optional
22047
+ middleware?: MiddlewareConfig[], // Optional
22048
+ modelKey?: string, // Optional
22049
+ }
22050
+ \`\`\`
22051
+
22052
+ ### validate_workflow
22053
+
22054
+ Validates a workflow agent's DSL and returns any errors or warnings.
22055
+
22056
+ \`\`\`typescript
22057
+ {
22058
+ id: string, // Required. Workflow agent ID to validate
22059
+ }
22060
+ \`\`\`
22061
+
22062
+ Returns: \`{ valid: boolean, stepCount, issues: [{ type: "error"|"warning", message }] }\`
22063
+
20241
22064
  ### Middleware Config Reference
20242
22065
 
20243
22066
  Each middleware entry uses this base shape:
@@ -20329,8 +22152,8 @@ Provides: \`schedule_at\`, \`schedule_after\`, \`schedule_recurring\`, \`cancel_
20329
22152
  |-------------|------|-------------|
20330
22153
  | defaultMaxRetries | number? | Default max retries for scheduled tasks. Default: \`0\` |
20331
22154
 
20332
- #### topology
20333
- Provides: \`read_topo_progress\` \u2014 enforces multi-agent workflow topology. **Required for PROCESSING agents \u2014 auto-injected by create_processing_agent.**
22155
+ #### topology [DEPRECATED \u2014 use WORKFLOW DSL instead]
22156
+ Provides: \`read_topo_progress\` \u2014 enforces multi-agent workflow topology for PROCESSING agents only. Not needed for WORKFLOW agents.
20334
22157
  | config field | type | description |
20335
22158
  |-------------|------|-------------|
20336
22159
  | edges | TopologyEdge[] | **Required.** Directed edges: \`{ from: string, to: string, purpose: string }\`. The \`purpose\` must describe the business intent of this delegation step. |
@@ -20386,29 +22209,6 @@ Use \`manage_binding\` to bind external senders (email, Lark, Slack) to agents.
20386
22209
  - **threadMode**: Always use \`"per_conversation"\` (new thread per conversation). Do NOT use \`"fixed"\`.
20387
22210
  - **channelInstallationId**: Auto-detected if only one installation exists for the channel. Use \`list_installations\` first if unsure.
20388
22211
 
20389
- ### update_processing_agent
20390
-
20391
- Updates a PROCESSING agent's topology edges, name, prompt, or sub-agents. Unlike update_agent, this properly handles placeholder resolution for edge \`from\` values and manages the topology middleware correctly.
20392
-
20393
- \`\`\`typescript
20394
- {
20395
- id: string, // Required. The PROCESSING agent ID to update
20396
- name?: string, // Optional. New display name
20397
- description?: string, // Optional. New short description
20398
- prompt?: string, // Optional. New orchestrator system prompt
20399
- edges?: [{ // Optional. New topology edges (serial chain)
20400
- from: string, // First edge: orchestrator name placeholder. Subsequent: previous sub-agent ID
20401
- to: string, // Sub-agent ID
20402
- purpose: string, // Business purpose
20403
- }],
20404
- subAgents?: string[], // Optional. New sub-agent IDs
20405
- middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology auto-managed)
20406
- modelKey?: string, // Optional. New model
20407
- }
20408
- \`\`\`
20409
-
20410
- **When to use:** Use this whenever you need to change a PROCESSING agent's topology \u2014 adding/removing/recruiting pipeline stages, changing the flow order, or updating edge purposes. Use regular \`update_agent\` only for REACT and DEEP_AGENT agents.
20411
-
20412
22212
  ### update_agent parameters
20413
22213
 
20414
22214
  \`\`\`typescript
@@ -20426,7 +22226,7 @@ Updates a PROCESSING agent's topology edges, name, prompt, or sub-agents. Unlike
20426
22226
  `;
20427
22227
 
20428
22228
  // src/agent_lattice/agentReviewerConfig.ts
20429
- var import_protocols12 = require("@axiom-lattice/protocols");
22229
+ var import_protocols13 = require("@axiom-lattice/protocols");
20430
22230
 
20431
22231
  // src/agent_lattice/agentReviewerPrompt.ts
20432
22232
  var AGENT_REVIEWER_PROMPT = `# Agent Reviewer
@@ -20489,7 +22289,7 @@ var agentReviewerConfig = {
20489
22289
  key: AGENT_REVIEWER_KEY,
20490
22290
  name: "Agent Reviewer",
20491
22291
  description: "Review and test AI agents. Use this agent to check agent configurations for correctness and to test agents by invoking them with realistic messages.",
20492
- type: import_protocols12.AgentType.REACT,
22292
+ type: import_protocols13.AgentType.REACT,
20493
22293
  prompt: AGENT_REVIEWER_PROMPT,
20494
22294
  tools: [
20495
22295
  "invoke_agent",
@@ -20515,21 +22315,30 @@ var agentArchitectConfig = {
20515
22315
  key: AGENT_ARCHITECT_KEY,
20516
22316
  name: "Agent Architect",
20517
22317
  description: "Design and manage AI agents through natural language conversation. Use this agent when you want to create a new agent, modify an existing agent, or manage your agent collection (list, view, update, delete).",
20518
- type: import_protocols13.AgentType.DEEP_AGENT,
22318
+ type: import_protocols14.AgentType.DEEP_AGENT,
20519
22319
  prompt: AGENT_ARCHITECT_PROMPT,
20520
22320
  tools: [
20521
22321
  "list_agents",
20522
22322
  "list_tools",
20523
22323
  "get_agent",
20524
22324
  "create_agent",
20525
- "create_processing_agent",
20526
- "update_processing_agent",
22325
+ "create_workflow",
22326
+ "validate_workflow",
22327
+ "update_workflow",
20527
22328
  "update_agent",
20528
22329
  "delete_agent",
20529
22330
  "manage_binding"
20530
22331
  ],
20531
22332
  internalSubAgents: [agentReviewerConfig],
20532
22333
  middleware: [
22334
+ {
22335
+ id: "skill",
22336
+ type: "skill",
22337
+ name: "Skill",
22338
+ description: "Load skill content and instructions",
22339
+ enabled: true,
22340
+ config: { readAll: true }
22341
+ },
20533
22342
  {
20534
22343
  id: "widget",
20535
22344
  type: "widget",
@@ -20996,7 +22805,11 @@ var getAgentClient = (tenantId, key, options) => agentLatticeManager.initializeC
20996
22805
  var getAgentClientAsync = async (tenantId, key, options) => agentLatticeManager.initializeClientAsync(tenantId, key, options);
20997
22806
  var createAgentClientFromAgentLattice = async (agentLattice, options) => await agentLatticeManager.createAgentClientFromConfig(agentLattice, options);
20998
22807
 
22808
+ // src/index.ts
22809
+ init_memory_lattice();
22810
+
20999
22811
  // src/embeddings_lattice/EmbeddingsLatticeManager.ts
22812
+ init_BaseLatticeManager();
21000
22813
  var EmbeddingsLatticeManager = class _EmbeddingsLatticeManager extends BaseLatticeManager {
21001
22814
  /**
21002
22815
  * Get EmbeddingsLatticeManager singleton instance
@@ -21089,6 +22902,7 @@ var getEmbeddingsLattice = (key) => embeddingsLatticeManager.getEmbeddingsLattic
21089
22902
  var getEmbeddingsClient = (key) => embeddingsLatticeManager.getEmbeddingsClient(key);
21090
22903
 
21091
22904
  // src/vectorstore_lattice/VectorStoreLatticeManager.ts
22905
+ init_BaseLatticeManager();
21092
22906
  var VectorStoreLatticeManager = class _VectorStoreLatticeManager extends BaseLatticeManager {
21093
22907
  /**
21094
22908
  * Get VectorStoreLatticeManager singleton instance
@@ -21181,7 +22995,8 @@ var getVectorStoreLattice = (key) => vectorStoreLatticeManager.getVectorStoreLat
21181
22995
  var getVectorStoreClient = (key) => vectorStoreLatticeManager.getVectorStoreClient(key);
21182
22996
 
21183
22997
  // src/logger_lattice/LoggerLatticeManager.ts
21184
- var import_protocols14 = require("@axiom-lattice/protocols");
22998
+ init_BaseLatticeManager();
22999
+ var import_protocols15 = require("@axiom-lattice/protocols");
21185
23000
 
21186
23001
  // src/logger_lattice/PinoLoggerClient.ts
21187
23002
  var import_pino = __toESM(require("pino"));
@@ -21403,11 +23218,11 @@ var LoggerLatticeManager = class _LoggerLatticeManager extends BaseLatticeManage
21403
23218
  if (client) {
21404
23219
  loggerClient = client;
21405
23220
  } else {
21406
- if (config.type === import_protocols14.LoggerType.PINO) {
23221
+ if (config.type === import_protocols15.LoggerType.PINO) {
21407
23222
  loggerClient = new PinoLoggerClient(config);
21408
- } else if (config.type === import_protocols14.LoggerType.CONSOLE) {
23223
+ } else if (config.type === import_protocols15.LoggerType.CONSOLE) {
21409
23224
  loggerClient = new ConsoleLoggerClient(config);
21410
- } else if (config.type === import_protocols14.LoggerType.CUSTOM) {
23225
+ } else if (config.type === import_protocols15.LoggerType.CUSTOM) {
21411
23226
  throw new Error(
21412
23227
  `Custom logger client must be provided. Please pass the client to registerLattice.`
21413
23228
  );
@@ -21496,6 +23311,7 @@ var registerLoggerLattice = (key, config, client) => loggerLatticeManager.regist
21496
23311
  var getLoggerLattice = (key) => loggerLatticeManager.getLoggerLattice(key);
21497
23312
 
21498
23313
  // src/skill_lattice/SkillLatticeManager.ts
23314
+ init_BaseLatticeManager();
21499
23315
  var SkillLatticeManager = class _SkillLatticeManager extends BaseLatticeManager {
21500
23316
  /**
21501
23317
  * Get SkillLatticeManager singleton instance
@@ -21867,6 +23683,7 @@ var skillLatticeManager = SkillLatticeManager.getInstance();
21867
23683
 
21868
23684
  // src/mcp_lattice/McpLatticeManager.ts
21869
23685
  var import_mcp_adapters = require("@langchain/mcp-adapters");
23686
+ init_BaseLatticeManager();
21870
23687
  var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
21871
23688
  constructor() {
21872
23689
  super(...arguments);
@@ -23319,6 +25136,11 @@ function clearEncryptionKeyCache() {
23319
25136
  cachedKey = null;
23320
25137
  keyValidated = false;
23321
25138
  }
25139
+
25140
+ // src/workflow/index.ts
25141
+ init_compile();
25142
+ init_normalize();
25143
+ init_utils();
23322
25144
  // Annotate the CommonJS export names for ESM import in node:
23323
25145
  0 && (module.exports = {
23324
25146
  AGENT_TASK_EVENT,
@@ -23402,21 +25224,28 @@ function clearEncryptionKeyCache() {
23402
25224
  agentInstanceManager,
23403
25225
  agentLatticeManager,
23404
25226
  buildGrepResultsDict,
25227
+ buildInput,
23405
25228
  buildNamedVolumeName,
23406
25229
  buildSandboxMetadataEnv,
23407
25230
  buildSkillFile,
25231
+ buildStateAnnotation,
23408
25232
  checkEmptyContent,
23409
25233
  clearEncryptionKeyCache,
25234
+ compileWorkflow,
23410
25235
  computeSandboxName,
23411
25236
  configureStores,
25237
+ createAgentNode,
23412
25238
  createAgentTeam,
23413
25239
  createExecuteSqlQueryTool,
23414
25240
  createFileData,
25241
+ createHumanFeedbackNode,
23415
25242
  createInfoSqlTool,
23416
25243
  createListMetricsDataSourcesTool,
23417
25244
  createListMetricsServersTool,
23418
25245
  createListTablesSqlTool,
25246
+ createMapNode,
23419
25247
  createModelSelectorMiddleware,
25248
+ createNodeHandler,
23420
25249
  createProcessingAgent,
23421
25250
  createQueryCheckerSqlTool,
23422
25251
  createQueryMetricDefinitionTool,
@@ -23429,6 +25258,7 @@ function clearEncryptionKeyCache() {
23429
25258
  createSchedulerMiddleware,
23430
25259
  createTeamMiddleware,
23431
25260
  createTeammateTools,
25261
+ createTerminalNode,
23432
25262
  createUnknownToolHandlerMiddleware,
23433
25263
  createWidgetMiddleware,
23434
25264
  decrypt,
@@ -23438,7 +25268,9 @@ function clearEncryptionKeyCache() {
23438
25268
  ensureBuiltinAgentsForTenant,
23439
25269
  eventBus,
23440
25270
  eventBusDefault,
25271
+ expand,
23441
25272
  extractFetcherError,
25273
+ extractOutput,
23442
25274
  fileDataToString,
23443
25275
  formatContentWithLineNumbers,
23444
25276
  formatGrepMatches,
@@ -23474,6 +25306,7 @@ function clearEncryptionKeyCache() {
23474
25306
  grepMatchesFromFiles,
23475
25307
  grepSearchFiles,
23476
25308
  hasChunkBuffer,
25309
+ invokeWithRetry,
23477
25310
  isBuiltInSkill,
23478
25311
  isUsingDefaultKey,
23479
25312
  isValidCronExpression,
@@ -23484,6 +25317,7 @@ function clearEncryptionKeyCache() {
23484
25317
  metricsServerManager,
23485
25318
  modelLatticeManager,
23486
25319
  normalizeSandboxName,
25320
+ parallelLimit,
23487
25321
  parseCronExpression,
23488
25322
  parseSkillFrontmatter,
23489
25323
  performStringReplacement,
@@ -23503,6 +25337,8 @@ function clearEncryptionKeyCache() {
23503
25337
  registerTeammateAgent,
23504
25338
  registerToolLattice,
23505
25339
  registerVectorStoreLattice,
25340
+ renderTemplate,
25341
+ resolvePath,
23506
25342
  sandboxLatticeManager,
23507
25343
  sanitizeToolCallId,
23508
25344
  scheduleLatticeManager,
@@ -23515,6 +25351,7 @@ function clearEncryptionKeyCache() {
23515
25351
  unregisterTeammateAgent,
23516
25352
  updateFileData,
23517
25353
  validateAgentInput,
25354
+ validateDSL,
23518
25355
  validateEncryptionKey,
23519
25356
  validatePath,
23520
25357
  validateSkillName,