@axiom-lattice/core 2.1.80 → 2.1.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-FN4TRQK4.mjs → chunk-SGRFQY3E.mjs} +386 -504
- package/dist/chunk-SGRFQY3E.mjs.map +1 -0
- package/dist/compile-4RFYHUBE.mjs +11 -0
- package/dist/index.d.mts +219 -34
- package/dist/index.d.ts +219 -34
- package/dist/index.js +1725 -1299
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1278 -745
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
- package/dist/chunk-FN4TRQK4.mjs.map +0 -1
- package/dist/compile-SYSKVQHB.mjs +0 -9
- /package/dist/{compile-SYSKVQHB.mjs.map → compile-4RFYHUBE.mjs.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -387,40 +387,342 @@ var init_memory_lattice = __esm({
|
|
|
387
387
|
}
|
|
388
388
|
});
|
|
389
389
|
|
|
390
|
+
// src/workflow/schema.ts
|
|
391
|
+
function toJsonSchema(fields) {
|
|
392
|
+
if (!fields || Object.keys(fields).length === 0) return void 0;
|
|
393
|
+
const properties = {};
|
|
394
|
+
const required = [];
|
|
395
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
396
|
+
required.push(key);
|
|
397
|
+
properties[key] = fieldToSchema(value);
|
|
398
|
+
}
|
|
399
|
+
return { type: "object", properties, required };
|
|
400
|
+
}
|
|
401
|
+
function fieldToSchema(value) {
|
|
402
|
+
if (typeof value === "string") return stringTypeToSchema(value);
|
|
403
|
+
if (Array.isArray(value) && value.length > 0 && typeof value[0] === "object" && !Array.isArray(value[0])) {
|
|
404
|
+
const nested = toJsonSchema(value[0]);
|
|
405
|
+
return { type: "array", items: nested ?? { type: "object" } };
|
|
406
|
+
}
|
|
407
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
408
|
+
const nested = toJsonSchema(value);
|
|
409
|
+
return nested ?? { type: "object" };
|
|
410
|
+
}
|
|
411
|
+
return { type: "string" };
|
|
412
|
+
}
|
|
413
|
+
function stringTypeToSchema(type) {
|
|
414
|
+
if (type.endsWith("[]")) {
|
|
415
|
+
const inner = type.slice(0, -2);
|
|
416
|
+
return { type: "array", items: stringTypeToSchema(inner) };
|
|
417
|
+
}
|
|
418
|
+
if (type === "string") return { type: "string" };
|
|
419
|
+
if (type === "number") return { type: "number" };
|
|
420
|
+
if (type === "boolean") return { type: "boolean" };
|
|
421
|
+
return { type };
|
|
422
|
+
}
|
|
423
|
+
var init_schema = __esm({
|
|
424
|
+
"src/workflow/schema.ts"() {
|
|
425
|
+
"use strict";
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// src/workflow/parse-yaml.ts
|
|
430
|
+
function nodeId(label) {
|
|
431
|
+
return `n_${label}`;
|
|
432
|
+
}
|
|
433
|
+
function nextParallelLabel() {
|
|
434
|
+
return `parallel_${_parallelSeq++}`;
|
|
435
|
+
}
|
|
436
|
+
function translate(template) {
|
|
437
|
+
return template.replace(/\{\{([^}]+)\}\}/g, (_m, expr) => {
|
|
438
|
+
const t = expr.trim();
|
|
439
|
+
if (t === "item") return "${item}";
|
|
440
|
+
return `\${state.${t}}`;
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
function toSafeStateExpr(expr) {
|
|
444
|
+
const match = expr.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)/);
|
|
445
|
+
if (!match) return `state.${expr}`;
|
|
446
|
+
const field = match[0];
|
|
447
|
+
const rest = expr.slice(field.length);
|
|
448
|
+
return `state["${field}"]${rest}`;
|
|
449
|
+
}
|
|
450
|
+
function validateExpression(expr) {
|
|
451
|
+
if (/;/.test(expr)) {
|
|
452
|
+
throw new Error(`Condition expression must not contain semicolons: "${expr}"`);
|
|
453
|
+
}
|
|
454
|
+
if (/[{}]/.test(expr)) {
|
|
455
|
+
throw new Error(`Condition expression must not contain braces: "${expr}"`);
|
|
456
|
+
}
|
|
457
|
+
if (/\bfunction\b/.test(expr)) {
|
|
458
|
+
throw new Error(`Condition expression must not contain 'function': "${expr}"`);
|
|
459
|
+
}
|
|
460
|
+
if (/\brequire\b|\bimport\b|\bmodule\b/.test(expr)) {
|
|
461
|
+
throw new Error(`Condition expression must not contain require/import: "${expr}"`);
|
|
462
|
+
}
|
|
463
|
+
if (/\bprocess\b|\bglobal\b|\bglobalThis\b/.test(expr)) {
|
|
464
|
+
throw new Error(`Condition expression must not contain process/global: "${expr}"`);
|
|
465
|
+
}
|
|
466
|
+
if (/\beval\b|\bFunction\b/.test(expr)) {
|
|
467
|
+
throw new Error(`Condition expression must not contain eval/Function: "${expr}"`);
|
|
468
|
+
}
|
|
469
|
+
if (/\bconstructor\b|\b__proto__\b|\bprototype\b/.test(expr)) {
|
|
470
|
+
throw new Error(`Condition expression must not contain prototype access: "${expr}"`);
|
|
471
|
+
}
|
|
472
|
+
if (/\bsetTimeout\b|\bsetInterval\b|\bbuffer\b/i.test(expr)) {
|
|
473
|
+
throw new Error(`Condition expression must not contain timer or buffer references: "${expr}"`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function parseYaml(yamlStr) {
|
|
477
|
+
_parallelSeq = 0;
|
|
478
|
+
let raw;
|
|
479
|
+
try {
|
|
480
|
+
raw = yaml.load(yamlStr);
|
|
481
|
+
} catch (e) {
|
|
482
|
+
const line = e?.mark?.line != null ? ` (line ${e.mark.line + 1})` : "";
|
|
483
|
+
throw new Error(`YAML parse error${line}: ${e.message || e}`);
|
|
484
|
+
}
|
|
485
|
+
if (!raw || typeof raw !== "object" || !Array.isArray(raw.steps)) {
|
|
486
|
+
throw new Error("Workflow YAML must have 'steps' (array)");
|
|
487
|
+
}
|
|
488
|
+
const name = typeof raw.name === "string" ? raw.name : "workflow";
|
|
489
|
+
const wf = {
|
|
490
|
+
name,
|
|
491
|
+
steps: raw.steps.map((s, i) => parseStep(s, i))
|
|
492
|
+
};
|
|
493
|
+
return normalize(wf);
|
|
494
|
+
}
|
|
495
|
+
function parseStep(raw, index) {
|
|
496
|
+
if (raw.parallel !== void 0) {
|
|
497
|
+
if (!Array.isArray(raw.parallel)) {
|
|
498
|
+
throw new Error(`Step at position ${index}: parallel must be an array`);
|
|
499
|
+
}
|
|
500
|
+
const children = raw.parallel.map((c, ci) => {
|
|
501
|
+
const entries2 = Object.entries(c);
|
|
502
|
+
if (entries2.length !== 1) {
|
|
503
|
+
throw new Error(`Parallel child at position ${index}.${ci} must be a single-key mapping`);
|
|
504
|
+
}
|
|
505
|
+
const [label, config2] = entries2[0];
|
|
506
|
+
return {
|
|
507
|
+
label,
|
|
508
|
+
if: config2.if !== void 0 ? String(config2.if) : void 0,
|
|
509
|
+
prompt: String(config2.prompt ?? ""),
|
|
510
|
+
output: config2.output,
|
|
511
|
+
ask: config2.ask === true
|
|
512
|
+
};
|
|
513
|
+
});
|
|
514
|
+
return {
|
|
515
|
+
parallel: children,
|
|
516
|
+
if: raw.if !== void 0 ? String(raw.if) : void 0,
|
|
517
|
+
output: raw.output
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
const entries = Object.entries(raw);
|
|
521
|
+
if (entries.length !== 1) {
|
|
522
|
+
throw new Error(`Step at position ${index} must be a single-key mapping`);
|
|
523
|
+
}
|
|
524
|
+
const [key, config] = entries[0];
|
|
525
|
+
const mapConfig = config?.map;
|
|
526
|
+
if (mapConfig && typeof mapConfig === "object") {
|
|
527
|
+
return {
|
|
528
|
+
map: {
|
|
529
|
+
source: mapConfig.source,
|
|
530
|
+
label: key,
|
|
531
|
+
// always use the YAML key as the label
|
|
532
|
+
if: mapConfig.if !== void 0 ? String(mapConfig.if) : void 0,
|
|
533
|
+
each: {
|
|
534
|
+
prompt: String(mapConfig.each?.prompt ?? ""),
|
|
535
|
+
output: mapConfig.each?.output
|
|
536
|
+
},
|
|
537
|
+
output: mapConfig.output,
|
|
538
|
+
batch: mapConfig.batch,
|
|
539
|
+
concurrency: mapConfig.concurrency
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
if (key === "map") {
|
|
544
|
+
throw new Error(`Map steps must use named format: - <label>: { map: { source, each, ... } }. Anonymous "- map:" is not supported.`);
|
|
545
|
+
}
|
|
546
|
+
return {
|
|
547
|
+
label: key,
|
|
548
|
+
if: config.if !== void 0 ? String(config.if) : void 0,
|
|
549
|
+
prompt: String(config.prompt ?? ""),
|
|
550
|
+
output: config.output,
|
|
551
|
+
ask: config.ask === true
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
function normalize(wf) {
|
|
555
|
+
validate(wf);
|
|
556
|
+
for (const step of wf.steps) {
|
|
557
|
+
if ("label" in step) {
|
|
558
|
+
const s = step;
|
|
559
|
+
if (s.if) validateExpression(s.if);
|
|
560
|
+
} else if ("parallel" in step) {
|
|
561
|
+
const pb = step;
|
|
562
|
+
if (pb.if) validateExpression(pb.if);
|
|
563
|
+
for (const child of pb.parallel) {
|
|
564
|
+
if (child.if) validateExpression(child.if);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const nodes = [];
|
|
569
|
+
const edges = [];
|
|
570
|
+
const fields = { input: { type: "string" } };
|
|
571
|
+
nodes.push({ id: "n_input", type: "input", name: "input", output: { key: "input" } });
|
|
572
|
+
edges.push({ from: "START", to: "n_input" });
|
|
573
|
+
let prevNodeId = "n_input";
|
|
574
|
+
for (const step of wf.steps) {
|
|
575
|
+
if ("label" in step) {
|
|
576
|
+
const s = step;
|
|
577
|
+
const nid = nodeId(s.label);
|
|
578
|
+
const schema = toJsonSchema(s.output);
|
|
579
|
+
nodes.push({
|
|
580
|
+
id: nid,
|
|
581
|
+
type: "agent",
|
|
582
|
+
name: s.label,
|
|
583
|
+
input: { template: translate(s.prompt) },
|
|
584
|
+
output: { key: s.label, ...schema ? { schema } : {} },
|
|
585
|
+
ask: s.ask,
|
|
586
|
+
condition: s.if
|
|
587
|
+
});
|
|
588
|
+
fields[s.label] = s.output ? { type: "object" } : { type: "string" };
|
|
589
|
+
addPrevEdges(edges, prevNodeId, nid);
|
|
590
|
+
prevNodeId = nid;
|
|
591
|
+
} else if ("parallel" in step) {
|
|
592
|
+
const pb = step;
|
|
593
|
+
const groupId = nextParallelLabel();
|
|
594
|
+
const groupNodeIds = [];
|
|
595
|
+
for (const child of pb.parallel) {
|
|
596
|
+
const nid = nodeId(child.label);
|
|
597
|
+
const schema = toJsonSchema(child.output);
|
|
598
|
+
nodes.push({
|
|
599
|
+
id: nid,
|
|
600
|
+
type: "agent",
|
|
601
|
+
name: child.label,
|
|
602
|
+
input: { template: translate(child.prompt) },
|
|
603
|
+
output: { key: child.label, ...schema ? { schema } : {} },
|
|
604
|
+
ask: child.ask,
|
|
605
|
+
condition: child.if,
|
|
606
|
+
parallelGroup: groupId
|
|
607
|
+
});
|
|
608
|
+
fields[child.label] = child.output ? { type: "object" } : { type: "string" };
|
|
609
|
+
groupNodeIds.push(nid);
|
|
610
|
+
}
|
|
611
|
+
addPrevEdges(edges, prevNodeId, groupNodeIds);
|
|
612
|
+
prevNodeId = groupNodeIds;
|
|
613
|
+
} else if ("map" in step) {
|
|
614
|
+
const ms = step.map;
|
|
615
|
+
const label = ms.label;
|
|
616
|
+
const nid = nodeId(label);
|
|
617
|
+
const innerSchema = toJsonSchema(ms.each?.output);
|
|
618
|
+
const mapSchema = toJsonSchema(ms.output);
|
|
619
|
+
nodes.push({
|
|
620
|
+
id: nid,
|
|
621
|
+
type: "map",
|
|
622
|
+
name: label,
|
|
623
|
+
source: `state.${ms.source}`,
|
|
624
|
+
itemKey: "item",
|
|
625
|
+
config: {
|
|
626
|
+
batchSize: ms.batch ?? 50,
|
|
627
|
+
maxConcurrency: ms.concurrency ?? 5,
|
|
628
|
+
innerConcurrency: ms.concurrency ?? 5
|
|
629
|
+
},
|
|
630
|
+
node: {
|
|
631
|
+
type: "agent",
|
|
632
|
+
input: ms.each?.prompt ? { template: translate(ms.each.prompt) } : void 0,
|
|
633
|
+
...innerSchema ? { schema: innerSchema } : {}
|
|
634
|
+
},
|
|
635
|
+
output: { key: label, ...mapSchema ? { schema: mapSchema } : {} },
|
|
636
|
+
condition: ms.if
|
|
637
|
+
});
|
|
638
|
+
fields[label] = { type: "array", default: [] };
|
|
639
|
+
addPrevEdges(edges, prevNodeId, nid);
|
|
640
|
+
prevNodeId = nid;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
const termNid = nodeId("__end");
|
|
644
|
+
nodes.push({ id: termNid, type: "terminal", name: "__end", status: "success" });
|
|
645
|
+
addPrevEdges(edges, prevNodeId, termNid);
|
|
646
|
+
return { version: "1.0", name: wf.name || "workflow", state: { fields }, nodes, edges };
|
|
647
|
+
}
|
|
648
|
+
function addPrevEdges(edges, fromNodes, toNodes) {
|
|
649
|
+
const fromList = Array.isArray(fromNodes) ? fromNodes : [fromNodes];
|
|
650
|
+
const toList = Array.isArray(toNodes) ? toNodes : [toNodes];
|
|
651
|
+
for (const from of fromList) {
|
|
652
|
+
for (const to of toList) {
|
|
653
|
+
if (!edges.some((e) => e.from === from && e.to === to)) {
|
|
654
|
+
edges.push({ from, to });
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
function validate(wf) {
|
|
660
|
+
const labels = /* @__PURE__ */ new Set();
|
|
661
|
+
for (const step of wf.steps) {
|
|
662
|
+
if ("label" in step) {
|
|
663
|
+
const s = step;
|
|
664
|
+
if (labels.has(s.label)) throw new Error(`Duplicate step label "${s.label}"`);
|
|
665
|
+
labels.add(s.label);
|
|
666
|
+
} else if ("parallel" in step) {
|
|
667
|
+
const pb = step;
|
|
668
|
+
if (pb.parallel.length === 0) {
|
|
669
|
+
throw new Error("parallel block must contain at least one child step");
|
|
670
|
+
}
|
|
671
|
+
for (const child of pb.parallel) {
|
|
672
|
+
if (labels.has(child.label)) throw new Error(`Duplicate step label "${child.label}"`);
|
|
673
|
+
labels.add(child.label);
|
|
674
|
+
}
|
|
675
|
+
} else if ("map" in step) {
|
|
676
|
+
const ms = step.map;
|
|
677
|
+
if (labels.has(ms.label)) throw new Error(`Duplicate step label "${ms.label}" (map step)`);
|
|
678
|
+
labels.add(ms.label);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
var yaml, _parallelSeq;
|
|
683
|
+
var init_parse_yaml = __esm({
|
|
684
|
+
"src/workflow/parse-yaml.ts"() {
|
|
685
|
+
"use strict";
|
|
686
|
+
yaml = __toESM(require("js-yaml"));
|
|
687
|
+
init_schema();
|
|
688
|
+
_parallelSeq = 0;
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
|
|
390
692
|
// src/workflow/utils.ts
|
|
391
693
|
function buildStateAnnotation(fields) {
|
|
392
694
|
const annotations = {};
|
|
393
695
|
if (fields) {
|
|
394
696
|
for (const [key, field] of Object.entries(fields)) {
|
|
395
|
-
annotations[key] = (0,
|
|
697
|
+
annotations[key] = (0, import_langgraph14.Annotation)({
|
|
396
698
|
default: () => field.default ?? defaultValueForType(field.type),
|
|
397
699
|
reducer: buildReducer(field.reducer ?? "replace")
|
|
398
700
|
});
|
|
399
701
|
}
|
|
400
702
|
}
|
|
401
703
|
if (!annotations["messages"]) {
|
|
402
|
-
annotations["messages"] = (0,
|
|
704
|
+
annotations["messages"] = (0, import_langgraph14.Annotation)({
|
|
403
705
|
default: () => [],
|
|
404
706
|
reducer: (prev, next) => [...prev, ...next]
|
|
405
707
|
});
|
|
406
708
|
}
|
|
407
|
-
annotations["phase"] = (0,
|
|
709
|
+
annotations["phase"] = (0, import_langgraph14.Annotation)({
|
|
408
710
|
default: () => "init",
|
|
409
711
|
reducer: (_prev, next) => next
|
|
410
712
|
});
|
|
411
713
|
if (!annotations["status"]) {
|
|
412
|
-
annotations["status"] = (0,
|
|
714
|
+
annotations["status"] = (0, import_langgraph14.Annotation)({
|
|
413
715
|
default: () => "",
|
|
414
716
|
reducer: (_prev, next) => next
|
|
415
717
|
});
|
|
416
718
|
}
|
|
417
719
|
if (!annotations["_runId"]) {
|
|
418
|
-
annotations["_runId"] = (0,
|
|
720
|
+
annotations["_runId"] = (0, import_langgraph14.Annotation)({
|
|
419
721
|
default: () => void 0,
|
|
420
722
|
reducer: (_prev, next) => next ?? _prev
|
|
421
723
|
});
|
|
422
724
|
}
|
|
423
|
-
return
|
|
725
|
+
return import_langgraph14.Annotation.Root(annotations);
|
|
424
726
|
}
|
|
425
727
|
function defaultValueForType(type) {
|
|
426
728
|
switch (type) {
|
|
@@ -528,7 +830,7 @@ Output must be valid JSON in exactly this shape. Return ONLY the JSON, no other
|
|
|
528
830
|
${example}`;
|
|
529
831
|
prompt = prompt + schemaInstruction;
|
|
530
832
|
}
|
|
531
|
-
return { messages: [new
|
|
833
|
+
return { messages: [new import_messages5.HumanMessage(prompt)] };
|
|
532
834
|
}
|
|
533
835
|
function schemaToExample(schema) {
|
|
534
836
|
const example = schemaValueToExample(schema);
|
|
@@ -674,6 +976,36 @@ function createAgentNode(node, resolveAgent, trackingStore) {
|
|
|
674
976
|
return async (state, config) => {
|
|
675
977
|
const runId = state._runId;
|
|
676
978
|
const tenantId = config?.configurable?.tenantId ?? "default";
|
|
979
|
+
if (node.condition) {
|
|
980
|
+
try {
|
|
981
|
+
validateExpression(node.condition);
|
|
982
|
+
const safeExpr = toSafeStateExpr(node.condition);
|
|
983
|
+
const fn = new Function("state", `try { return ${safeExpr}; } catch { return false; }`);
|
|
984
|
+
const shouldRun = fn(state);
|
|
985
|
+
if (!shouldRun) {
|
|
986
|
+
console.log(`[WF][${node.id}] condition false, skipping "${node.name}" (${node.condition})`);
|
|
987
|
+
if (trackingStore && runId) {
|
|
988
|
+
const step = await trackingStore.upsertRunStep({
|
|
989
|
+
runId,
|
|
990
|
+
tenantId,
|
|
991
|
+
stepType: node.type,
|
|
992
|
+
stepName: node.name
|
|
993
|
+
}).catch(() => null);
|
|
994
|
+
if (step) {
|
|
995
|
+
await trackingStore.updateRunStep(runId, step.id, {
|
|
996
|
+
status: "skipped",
|
|
997
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
998
|
+
}).catch(() => {
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
return { phase: node.id };
|
|
1003
|
+
}
|
|
1004
|
+
} catch (condErr) {
|
|
1005
|
+
console.error(`[WF][${node.id}] condition eval error: ${condErr.message}`);
|
|
1006
|
+
throw condErr;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
677
1009
|
const startedAt = Date.now();
|
|
678
1010
|
let stepId;
|
|
679
1011
|
if (trackingStore && runId) {
|
|
@@ -687,7 +1019,8 @@ function createAgentNode(node, resolveAgent, trackingStore) {
|
|
|
687
1019
|
console.log(`[WF][${node.id}] START "${node.name}" | hasSchema=${!!node.output?.schema}`);
|
|
688
1020
|
const responseFormat = node.output?.schema;
|
|
689
1021
|
console.log(`[WF][${node.id}] resolving agent...`);
|
|
690
|
-
const
|
|
1022
|
+
const stepType = node.ask ? "ask" : node.type;
|
|
1023
|
+
const client = await resolveAgent(node.ref, responseFormat, stepType);
|
|
691
1024
|
console.log(`[WF][${node.id}] agent resolved, building input...`);
|
|
692
1025
|
const input = buildInput(
|
|
693
1026
|
node.input,
|
|
@@ -695,16 +1028,32 @@ function createAgentNode(node, resolveAgent, trackingStore) {
|
|
|
695
1028
|
void 0,
|
|
696
1029
|
responseFormat ? void 0 : node.output?.schema
|
|
697
1030
|
);
|
|
1031
|
+
if (node.ask) {
|
|
1032
|
+
input.messages = [
|
|
1033
|
+
new import_messages5.SystemMessage(
|
|
1034
|
+
"Follow this exact procedure. Do NOT skip any step.\n\nSTEP 1: Read the prompt. It contains content to present to the user and a question to ask.\n\nSTEP 2: Call ask_user_to_clarify. Your question text MUST contain the ACTUAL content from the prompt.\n\nSTEP 3: The tool will pause. The user will see your questions and respond. You will receive their answers.\n\nSTEP 4: Based on the user's answers, produce your final output."
|
|
1035
|
+
),
|
|
1036
|
+
...input.messages
|
|
1037
|
+
];
|
|
1038
|
+
}
|
|
698
1039
|
const renderedInput = input.messages[0]?.content ?? "";
|
|
699
1040
|
console.log(`[WF][${node.id}] === INPUT (full) ===
|
|
700
1041
|
${renderedInput}
|
|
701
1042
|
=== END INPUT ===`);
|
|
1043
|
+
const subConfig = {
|
|
1044
|
+
...config,
|
|
1045
|
+
configurable: {
|
|
1046
|
+
...config?.configurable ?? {},
|
|
1047
|
+
thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}`
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
702
1050
|
if (trackingStore && runId) {
|
|
703
1051
|
const step = await trackingStore.upsertRunStep({
|
|
704
1052
|
runId,
|
|
705
1053
|
tenantId,
|
|
706
1054
|
stepType: node.type,
|
|
707
1055
|
stepName: node.name,
|
|
1056
|
+
threadId: subConfig.configurable.thread_id,
|
|
708
1057
|
input: { template: node.input?.template, rendered: renderedInput }
|
|
709
1058
|
}).catch((e) => {
|
|
710
1059
|
console.warn("Failed to upsert run step:", e.message);
|
|
@@ -716,13 +1065,6 @@ ${renderedInput}
|
|
|
716
1065
|
});
|
|
717
1066
|
}
|
|
718
1067
|
}
|
|
719
|
-
const subConfig = {
|
|
720
|
-
...config,
|
|
721
|
-
configurable: {
|
|
722
|
-
...config?.configurable ?? {},
|
|
723
|
-
thread_id: `${config?.configurable?.thread_id ?? "default"}:${node.id}`
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
1068
|
let result;
|
|
727
1069
|
try {
|
|
728
1070
|
console.log(`[WF][${node.id}] invoking agent.invoke()...`);
|
|
@@ -819,157 +1161,40 @@ ${JSON.stringify(output, null, 2)}
|
|
|
819
1161
|
}
|
|
820
1162
|
};
|
|
821
1163
|
}
|
|
822
|
-
function
|
|
1164
|
+
function createMapNode(node, resolveAgent, trackingStore) {
|
|
823
1165
|
return async (state, config) => {
|
|
824
1166
|
const runId = state._runId;
|
|
825
1167
|
const tenantId = config?.configurable?.tenantId ?? "default";
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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
|
-
});
|
|
1168
|
+
if (node.condition) {
|
|
1169
|
+
try {
|
|
1170
|
+
validateExpression(node.condition);
|
|
1171
|
+
const safeExpr = toSafeStateExpr(node.condition);
|
|
1172
|
+
const fn = new Function("state", `try { return ${safeExpr}; } catch { return false; }`);
|
|
1173
|
+
const shouldRun = fn(state);
|
|
1174
|
+
if (!shouldRun) {
|
|
1175
|
+
console.log(`[WF][${node.id}] condition false, skipping map "${node.name}" (${node.condition})`);
|
|
1176
|
+
if (trackingStore && runId) {
|
|
1177
|
+
const step = await trackingStore.upsertRunStep({
|
|
1178
|
+
runId,
|
|
1179
|
+
tenantId,
|
|
1180
|
+
stepType: node.type,
|
|
1181
|
+
stepName: node.name
|
|
1182
|
+
}).catch(() => null);
|
|
1183
|
+
if (step) {
|
|
1184
|
+
await trackingStore.updateRunStep(runId, step.id, {
|
|
1185
|
+
status: "skipped",
|
|
1186
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
1187
|
+
}).catch(() => {
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return { phase: node.id };
|
|
956
1192
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
completedAt: /* @__PURE__ */ new Date()
|
|
961
|
-
}).catch((e) => {
|
|
962
|
-
console.warn("Failed to finalize WorkflowRun:", e.message);
|
|
963
|
-
});
|
|
1193
|
+
} catch (condErr) {
|
|
1194
|
+
console.error(`[WF][${node.id}] condition eval error: ${condErr.message}`);
|
|
1195
|
+
throw condErr;
|
|
964
1196
|
}
|
|
965
|
-
throw err;
|
|
966
1197
|
}
|
|
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
1198
|
const startedAt = Date.now();
|
|
974
1199
|
let stepId;
|
|
975
1200
|
if (trackingStore && runId) {
|
|
@@ -1167,357 +1392,66 @@ function createTerminalNode(node, trackingStore) {
|
|
|
1167
1392
|
tenantId: state._tenantId ?? "default",
|
|
1168
1393
|
stepType: "terminal",
|
|
1169
1394
|
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);
|
|
1395
|
+
input: { status: node.status }
|
|
1396
|
+
});
|
|
1397
|
+
} catch (e) {
|
|
1398
|
+
console.warn(`[WF][terminal] Failed to create terminal RunStep:`, e.message);
|
|
1447
1399
|
}
|
|
1448
1400
|
}
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1401
|
+
return {
|
|
1402
|
+
status: node.status,
|
|
1403
|
+
phase: node.id
|
|
1404
|
+
};
|
|
1405
|
+
};
|
|
1453
1406
|
}
|
|
1454
|
-
function
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
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);
|
|
1407
|
+
function createNodeHandler(node, resolveAgent, trackingStore) {
|
|
1408
|
+
switch (node.type) {
|
|
1409
|
+
case "agent":
|
|
1410
|
+
return createAgentNode(node, resolveAgent, trackingStore);
|
|
1411
|
+
case "map":
|
|
1412
|
+
return createMapNode(node, resolveAgent, trackingStore);
|
|
1413
|
+
case "terminal":
|
|
1414
|
+
return createTerminalNode(node, trackingStore);
|
|
1415
|
+
case "input":
|
|
1416
|
+
return createInputNode(node, trackingStore);
|
|
1417
|
+
default:
|
|
1418
|
+
throw new Error(`Unknown node type: ${node.type}`);
|
|
1470
1419
|
}
|
|
1471
|
-
steps.forEach(walk);
|
|
1472
|
-
return [...new Set(ids)];
|
|
1473
1420
|
}
|
|
1474
|
-
function
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
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);
|
|
1421
|
+
function chunk(arr, size) {
|
|
1422
|
+
const result = [];
|
|
1423
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
1424
|
+
result.push(arr.slice(i, i + size));
|
|
1495
1425
|
}
|
|
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
1426
|
return result;
|
|
1499
1427
|
}
|
|
1500
|
-
var
|
|
1501
|
-
var
|
|
1502
|
-
"src/workflow/
|
|
1428
|
+
var import_langgraph14, import_messages5;
|
|
1429
|
+
var init_utils = __esm({
|
|
1430
|
+
"src/workflow/utils.ts"() {
|
|
1503
1431
|
"use strict";
|
|
1504
|
-
|
|
1432
|
+
import_langgraph14 = require("@langchain/langgraph");
|
|
1433
|
+
import_messages5 = require("@langchain/core/messages");
|
|
1434
|
+
init_parse_yaml();
|
|
1505
1435
|
}
|
|
1506
1436
|
});
|
|
1507
1437
|
|
|
1508
1438
|
// src/workflow/compile.ts
|
|
1509
1439
|
var compile_exports = {};
|
|
1510
1440
|
__export(compile_exports, {
|
|
1441
|
+
compileInternal: () => compileInternal,
|
|
1511
1442
|
compileWorkflow: () => compileWorkflow,
|
|
1512
1443
|
validateDSL: () => validateDSL
|
|
1513
1444
|
});
|
|
1514
|
-
function compileWorkflow(
|
|
1515
|
-
console.log(`[WF COMPILE] compiling
|
|
1516
|
-
const ir =
|
|
1445
|
+
function compileWorkflow(yamlStr, resolveAgent, checkpointer, trackingStore) {
|
|
1446
|
+
console.log(`[WF COMPILE] compiling YAML workflow`);
|
|
1447
|
+
const ir = parseYaml(yamlStr);
|
|
1448
|
+
return compileInternal(ir, resolveAgent, checkpointer, trackingStore);
|
|
1449
|
+
}
|
|
1450
|
+
function compileInternal(ir, resolveAgent, checkpointer, trackingStore) {
|
|
1517
1451
|
validateAndThrow(ir);
|
|
1518
1452
|
console.log(`[WF COMPILE] validation passed`);
|
|
1519
1453
|
const StateAnnotation = buildStateAnnotation(ir.state?.fields);
|
|
1520
|
-
const builder = new
|
|
1454
|
+
const builder = new import_langgraph15.StateGraph(StateAnnotation);
|
|
1521
1455
|
for (const node of ir.nodes) {
|
|
1522
1456
|
console.log(`[WF COMPILE] registering node: id=${node.id} type=${node.type} name=${node.name}`);
|
|
1523
1457
|
const handler = createNodeHandler(node, resolveAgent, trackingStore);
|
|
@@ -1525,26 +1459,18 @@ function compileWorkflow(dsl, resolveAgent, checkpointer, trackingStore) {
|
|
|
1525
1459
|
}
|
|
1526
1460
|
for (const node of ir.nodes) {
|
|
1527
1461
|
if (node.type === "terminal") {
|
|
1528
|
-
builder.addEdge(node.id,
|
|
1462
|
+
builder.addEdge(node.id, import_langgraph15.END);
|
|
1529
1463
|
}
|
|
1530
1464
|
}
|
|
1531
1465
|
for (const edge of ir.edges) {
|
|
1532
|
-
const from = edge.from === "START" ?
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
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
|
-
}
|
|
1466
|
+
const from = edge.from === "START" ? import_langgraph15.START : edge.from;
|
|
1467
|
+
const targets = Array.isArray(edge.to) ? edge.to : [edge.to];
|
|
1468
|
+
for (const to of targets) {
|
|
1469
|
+
builder.addEdge(from, to === "END" ? import_langgraph15.END : to);
|
|
1544
1470
|
}
|
|
1545
1471
|
}
|
|
1546
1472
|
const graph = builder.compile({ checkpointer, name: ir.name });
|
|
1547
|
-
console.log(`[WF COMPILE] graph compiled successfully
|
|
1473
|
+
console.log(`[WF COMPILE] graph compiled successfully`);
|
|
1548
1474
|
return graph;
|
|
1549
1475
|
}
|
|
1550
1476
|
function validateDSL(dsl) {
|
|
@@ -1559,7 +1485,6 @@ function validateDSL(dsl) {
|
|
|
1559
1485
|
const terminalIds = new Set(
|
|
1560
1486
|
dsl.nodes.filter((n) => n.type === "terminal").map((n) => n.id)
|
|
1561
1487
|
);
|
|
1562
|
-
const declaredFields = new Set(Object.keys(dsl.state?.fields ?? {}));
|
|
1563
1488
|
for (const edge of dsl.edges) {
|
|
1564
1489
|
if (edge.from !== "START" && !nodeIds.has(edge.from)) {
|
|
1565
1490
|
errors.push({ type: "error", message: `Edge from "${edge.from}" references unknown node` });
|
|
@@ -1573,24 +1498,12 @@ function validateDSL(dsl) {
|
|
|
1573
1498
|
errors.push({ type: "error", message: `Edge to "${to}" references unknown node` });
|
|
1574
1499
|
}
|
|
1575
1500
|
}
|
|
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
1501
|
}
|
|
1589
1502
|
for (const node of dsl.nodes) {
|
|
1590
1503
|
if (node.type === "terminal") {
|
|
1591
1504
|
const hasIncoming = dsl.edges.some((e) => {
|
|
1592
1505
|
const targets = Array.isArray(e.to) ? e.to : e.to ? [e.to] : [];
|
|
1593
|
-
return targets.includes(node.id)
|
|
1506
|
+
return targets.includes(node.id);
|
|
1594
1507
|
});
|
|
1595
1508
|
if (!hasIncoming) {
|
|
1596
1509
|
errors.push({ type: "warning", message: `Terminal node "${node.id}" has no incoming edge` });
|
|
@@ -1606,41 +1519,13 @@ function validateAndThrow(dsl) {
|
|
|
1606
1519
|
throw new Error(critical.map((e) => e.message).join("; "));
|
|
1607
1520
|
}
|
|
1608
1521
|
}
|
|
1609
|
-
|
|
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;
|
|
1522
|
+
var import_langgraph15;
|
|
1638
1523
|
var init_compile = __esm({
|
|
1639
1524
|
"src/workflow/compile.ts"() {
|
|
1640
1525
|
"use strict";
|
|
1641
|
-
|
|
1526
|
+
import_langgraph15 = require("@langchain/langgraph");
|
|
1642
1527
|
init_utils();
|
|
1643
|
-
|
|
1528
|
+
init_parse_yaml();
|
|
1644
1529
|
}
|
|
1645
1530
|
});
|
|
1646
1531
|
|
|
@@ -1669,7 +1554,7 @@ __export(index_exports, {
|
|
|
1669
1554
|
EmbeddingsLatticeManager: () => EmbeddingsLatticeManager,
|
|
1670
1555
|
FileSystemSkillStore: () => FileSystemSkillStore,
|
|
1671
1556
|
FilesystemBackend: () => FilesystemBackend,
|
|
1672
|
-
HumanMessage: () =>
|
|
1557
|
+
HumanMessage: () => import_messages6.HumanMessage,
|
|
1673
1558
|
InMemoryA2AApiKeyStore: () => InMemoryA2AApiKeyStore,
|
|
1674
1559
|
InMemoryAssistantStore: () => InMemoryAssistantStore,
|
|
1675
1560
|
InMemoryBindingStore: () => InMemoryBindingStore,
|
|
@@ -1677,7 +1562,9 @@ __export(index_exports, {
|
|
|
1677
1562
|
InMemoryChunkBuffer: () => InMemoryChunkBuffer,
|
|
1678
1563
|
InMemoryDatabaseConfigStore: () => InMemoryDatabaseConfigStore,
|
|
1679
1564
|
InMemoryMailboxStore: () => InMemoryMailboxStore,
|
|
1565
|
+
InMemoryMenuStore: () => InMemoryMenuStore,
|
|
1680
1566
|
InMemoryTaskListStore: () => InMemoryTaskListStore,
|
|
1567
|
+
InMemoryTaskStore: () => InMemoryTaskStore,
|
|
1681
1568
|
InMemoryTenantStore: () => InMemoryTenantStore,
|
|
1682
1569
|
InMemoryThreadMessageQueueStore: () => InMemoryThreadMessageQueueStore,
|
|
1683
1570
|
InMemoryThreadStore: () => InMemoryThreadStore,
|
|
@@ -1699,6 +1586,7 @@ __export(index_exports, {
|
|
|
1699
1586
|
MicrosandboxServiceClient: () => MicrosandboxServiceClient,
|
|
1700
1587
|
ModelLatticeManager: () => ModelLatticeManager,
|
|
1701
1588
|
MysqlDatabase: () => MysqlDatabase,
|
|
1589
|
+
PersonalAssistantConfig: () => PersonalAssistantConfig,
|
|
1702
1590
|
PinoLoggerClient: () => PinoLoggerClient,
|
|
1703
1591
|
PostgresDatabase: () => PostgresDatabase,
|
|
1704
1592
|
PrometheusClient: () => PrometheusClient,
|
|
@@ -1735,14 +1623,15 @@ __export(index_exports, {
|
|
|
1735
1623
|
buildStateAnnotation: () => buildStateAnnotation,
|
|
1736
1624
|
checkEmptyContent: () => checkEmptyContent,
|
|
1737
1625
|
clearEncryptionKeyCache: () => clearEncryptionKeyCache,
|
|
1626
|
+
compileInternal: () => compileInternal,
|
|
1738
1627
|
compileWorkflow: () => compileWorkflow,
|
|
1739
1628
|
computeSandboxName: () => computeSandboxName,
|
|
1740
1629
|
configureStores: () => configureStores,
|
|
1630
|
+
connectAllChannels: () => connectAllChannels,
|
|
1741
1631
|
createAgentNode: () => createAgentNode,
|
|
1742
1632
|
createAgentTeam: () => createAgentTeam,
|
|
1743
1633
|
createExecuteSqlQueryTool: () => createExecuteSqlQueryTool,
|
|
1744
1634
|
createFileData: () => createFileData,
|
|
1745
|
-
createHumanFeedbackNode: () => createHumanFeedbackNode,
|
|
1746
1635
|
createInfoSqlTool: () => createInfoSqlTool,
|
|
1747
1636
|
createListMetricsDataSourcesTool: () => createListMetricsDataSourcesTool,
|
|
1748
1637
|
createListMetricsServersTool: () => createListMetricsServersTool,
|
|
@@ -1760,9 +1649,9 @@ __export(index_exports, {
|
|
|
1760
1649
|
createQueryTablesListTool: () => createQueryTablesListTool,
|
|
1761
1650
|
createSandboxProvider: () => createSandboxProvider,
|
|
1762
1651
|
createSchedulerMiddleware: () => createSchedulerMiddleware,
|
|
1652
|
+
createTaskMiddleware: () => createTaskMiddleware,
|
|
1763
1653
|
createTeamMiddleware: () => createTeamMiddleware,
|
|
1764
1654
|
createTeammateTools: () => createTeammateTools,
|
|
1765
|
-
createTerminalNode: () => createTerminalNode,
|
|
1766
1655
|
createUnknownToolHandlerMiddleware: () => createUnknownToolHandlerMiddleware,
|
|
1767
1656
|
createWidgetMiddleware: () => createWidgetMiddleware,
|
|
1768
1657
|
decrypt: () => decrypt,
|
|
@@ -1772,7 +1661,6 @@ __export(index_exports, {
|
|
|
1772
1661
|
ensureBuiltinAgentsForTenant: () => ensureBuiltinAgentsForTenant,
|
|
1773
1662
|
eventBus: () => eventBus,
|
|
1774
1663
|
eventBusDefault: () => event_bus_default,
|
|
1775
|
-
expand: () => expand,
|
|
1776
1664
|
extractFetcherError: () => extractFetcherError,
|
|
1777
1665
|
extractOutput: () => extractOutput,
|
|
1778
1666
|
fileDataToString: () => fileDataToString,
|
|
@@ -1795,6 +1683,7 @@ __export(index_exports, {
|
|
|
1795
1683
|
getEmbeddingsLattice: () => getEmbeddingsLattice,
|
|
1796
1684
|
getEncryptionKey: () => getEncryptionKey,
|
|
1797
1685
|
getLoggerLattice: () => getLoggerLattice,
|
|
1686
|
+
getMenuRegistry: () => getMenuRegistry,
|
|
1798
1687
|
getModelLattice: () => getModelLattice,
|
|
1799
1688
|
getNextCronTime: () => getNextCronTime,
|
|
1800
1689
|
getQueueLattice: () => getQueueLattice,
|
|
@@ -1824,6 +1713,7 @@ __export(index_exports, {
|
|
|
1824
1713
|
parallelLimit: () => parallelLimit,
|
|
1825
1714
|
parseCronExpression: () => parseCronExpression,
|
|
1826
1715
|
parseSkillFrontmatter: () => parseSkillFrontmatter,
|
|
1716
|
+
parseYaml: () => parseYaml,
|
|
1827
1717
|
performStringReplacement: () => performStringReplacement,
|
|
1828
1718
|
queueLatticeManager: () => queueLatticeManager,
|
|
1829
1719
|
registerAgentLattice: () => registerAgentLattice,
|
|
@@ -1847,9 +1737,12 @@ __export(index_exports, {
|
|
|
1847
1737
|
sanitizeToolCallId: () => sanitizeToolCallId,
|
|
1848
1738
|
scheduleLatticeManager: () => scheduleLatticeManager,
|
|
1849
1739
|
setBindingRegistry: () => setBindingRegistry,
|
|
1740
|
+
setMenuRegistry: () => setMenuRegistry,
|
|
1850
1741
|
skillLatticeManager: () => skillLatticeManager,
|
|
1851
1742
|
sqlDatabaseManager: () => sqlDatabaseManager,
|
|
1852
1743
|
storeLatticeManager: () => storeLatticeManager,
|
|
1744
|
+
toJsonSchema: () => toJsonSchema,
|
|
1745
|
+
toSafeStateExpr: () => toSafeStateExpr,
|
|
1853
1746
|
toolLatticeManager: () => toolLatticeManager,
|
|
1854
1747
|
truncateIfTooLong: () => truncateIfTooLong,
|
|
1855
1748
|
unregisterTeammateAgent: () => unregisterTeammateAgent,
|
|
@@ -1986,9 +1879,11 @@ var ModelLattice = class extends import_chat_models.BaseChatModel {
|
|
|
1986
1879
|
maxRetries: config.maxRetries || 2,
|
|
1987
1880
|
apiKey: config.apiKey || process.env[config.apiKeyEnvName || "SILICONCLOUD_API_KEY"],
|
|
1988
1881
|
configuration: {
|
|
1989
|
-
baseURL: "https://api.siliconflow.cn/v1"
|
|
1882
|
+
baseURL: config.baseURL || "https://api.siliconflow.cn/v1"
|
|
1990
1883
|
},
|
|
1991
|
-
streaming: config.streaming
|
|
1884
|
+
streaming: config.streaming,
|
|
1885
|
+
modelKwargs: config.modelKwargs,
|
|
1886
|
+
...config.extra || {}
|
|
1992
1887
|
});
|
|
1993
1888
|
} else if (config.provider === "volcengine") {
|
|
1994
1889
|
return new import_openai.ChatOpenAI({
|
|
@@ -2271,11 +2166,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2271
2166
|
* @param key Lattice键名
|
|
2272
2167
|
* @param tool 已有的StructuredTool实例
|
|
2273
2168
|
*/
|
|
2274
|
-
registerExistingTool(key,
|
|
2169
|
+
registerExistingTool(key, tool52) {
|
|
2275
2170
|
const config = {
|
|
2276
|
-
name:
|
|
2277
|
-
description:
|
|
2278
|
-
schema:
|
|
2171
|
+
name: tool52.name,
|
|
2172
|
+
description: tool52.description,
|
|
2173
|
+
schema: tool52.schema,
|
|
2279
2174
|
// StructuredTool的schema已经是Zod兼容的
|
|
2280
2175
|
needUserApprove: false
|
|
2281
2176
|
// MCP工具默认不需要用户批准
|
|
@@ -2283,7 +2178,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2283
2178
|
const toolLattice = {
|
|
2284
2179
|
key,
|
|
2285
2180
|
config,
|
|
2286
|
-
client:
|
|
2181
|
+
client: tool52
|
|
2287
2182
|
};
|
|
2288
2183
|
this.register(key, toolLattice);
|
|
2289
2184
|
}
|
|
@@ -2309,7 +2204,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
2309
2204
|
};
|
|
2310
2205
|
var toolLatticeManager = ToolLatticeManager.getInstance();
|
|
2311
2206
|
var registerToolLattice = (key, config, executor) => toolLatticeManager.registerLattice(key, config, executor);
|
|
2312
|
-
var registerExistingTool = (key,
|
|
2207
|
+
var registerExistingTool = (key, tool52) => toolLatticeManager.registerExistingTool(key, tool52);
|
|
2313
2208
|
var getToolLattice = (key) => toolLatticeManager.getToolLattice(key);
|
|
2314
2209
|
var getToolDefinition = (key) => toolLatticeManager.getToolDefinition(key);
|
|
2315
2210
|
var getToolClient = (key) => toolLatticeManager.getToolClient(key);
|
|
@@ -2579,6 +2474,7 @@ var InMemoryAssistantStore = class {
|
|
|
2579
2474
|
name: data.name,
|
|
2580
2475
|
description: data.description,
|
|
2581
2476
|
graphDefinition: data.graphDefinition,
|
|
2477
|
+
ownerUserId: data.ownerUserId,
|
|
2582
2478
|
createdAt: now,
|
|
2583
2479
|
updatedAt: now
|
|
2584
2480
|
};
|
|
@@ -2625,6 +2521,17 @@ var InMemoryAssistantStore = class {
|
|
|
2625
2521
|
}
|
|
2626
2522
|
return tenantAssistants.has(id);
|
|
2627
2523
|
}
|
|
2524
|
+
/**
|
|
2525
|
+
* Get assistant by owner user ID
|
|
2526
|
+
*/
|
|
2527
|
+
async getByOwner(tenantId, userId) {
|
|
2528
|
+
const tenantAssistants = this.assistants.get(tenantId);
|
|
2529
|
+
if (!tenantAssistants) return null;
|
|
2530
|
+
for (const assistant of tenantAssistants.values()) {
|
|
2531
|
+
if (assistant.ownerUserId === userId) return assistant;
|
|
2532
|
+
}
|
|
2533
|
+
return null;
|
|
2534
|
+
}
|
|
2628
2535
|
/**
|
|
2629
2536
|
* Clear all assistants for a tenant (useful for testing)
|
|
2630
2537
|
*/
|
|
@@ -3857,7 +3764,7 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
3857
3764
|
return this.messages.get(threadId);
|
|
3858
3765
|
}
|
|
3859
3766
|
async addMessage(params) {
|
|
3860
|
-
const { threadId, tenantId, assistantId, content, type = "human", priority = 0, command, custom_run_config, id } = params;
|
|
3767
|
+
const { threadId, tenantId, assistantId, workspaceId, projectId, content, type = "human", priority = 0, command, custom_run_config, id } = params;
|
|
3861
3768
|
const threadMessages = this.getMessagesForThread(threadId);
|
|
3862
3769
|
const message = {
|
|
3863
3770
|
id: id || this.generateId(),
|
|
@@ -3868,6 +3775,8 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
3868
3775
|
status: "pending",
|
|
3869
3776
|
tenantId,
|
|
3870
3777
|
assistantId,
|
|
3778
|
+
workspaceId,
|
|
3779
|
+
projectId,
|
|
3871
3780
|
priority,
|
|
3872
3781
|
command,
|
|
3873
3782
|
custom_run_config
|
|
@@ -3876,7 +3785,7 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
3876
3785
|
return message;
|
|
3877
3786
|
}
|
|
3878
3787
|
async addMessageAtHead(params) {
|
|
3879
|
-
const { threadId, tenantId, assistantId, content, type = "system", id, command, custom_run_config } = params;
|
|
3788
|
+
const { threadId, tenantId, assistantId, workspaceId, projectId, content, type = "system", id, command, custom_run_config } = params;
|
|
3880
3789
|
const threadMessages = this.getMessagesForThread(threadId);
|
|
3881
3790
|
let resolvedTenantId = tenantId || "default";
|
|
3882
3791
|
let resolvedAssistantId = assistantId || "";
|
|
@@ -3894,6 +3803,8 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
3894
3803
|
status: "pending",
|
|
3895
3804
|
tenantId: resolvedTenantId,
|
|
3896
3805
|
assistantId: resolvedAssistantId,
|
|
3806
|
+
workspaceId,
|
|
3807
|
+
projectId,
|
|
3897
3808
|
priority: 100,
|
|
3898
3809
|
// High priority for head messages (STEER/Command)
|
|
3899
3810
|
command,
|
|
@@ -3925,7 +3836,9 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
3925
3836
|
result.push({
|
|
3926
3837
|
tenantId: firstMessage.tenantId || "default",
|
|
3927
3838
|
assistantId: firstMessage.assistantId || "",
|
|
3928
|
-
threadId
|
|
3839
|
+
threadId,
|
|
3840
|
+
workspaceId: firstMessage.workspaceId || void 0,
|
|
3841
|
+
projectId: firstMessage.projectId || void 0
|
|
3929
3842
|
});
|
|
3930
3843
|
}
|
|
3931
3844
|
}
|
|
@@ -4048,6 +3961,7 @@ var InMemoryWorkflowTrackingStore = class {
|
|
|
4048
3961
|
tenantId: request.tenantId,
|
|
4049
3962
|
stepType: request.stepType,
|
|
4050
3963
|
stepName: request.stepName,
|
|
3964
|
+
threadId: request.threadId,
|
|
4051
3965
|
edgeFrom: request.edgeFrom,
|
|
4052
3966
|
edgeTo: request.edgeTo,
|
|
4053
3967
|
edgePurpose: request.edgePurpose,
|
|
@@ -4067,7 +3981,12 @@ var InMemoryWorkflowTrackingStore = class {
|
|
|
4067
3981
|
const existing = runSteps.find(
|
|
4068
3982
|
(s) => s.stepType === request.stepType && s.stepName === request.stepName
|
|
4069
3983
|
);
|
|
4070
|
-
if (existing)
|
|
3984
|
+
if (existing) {
|
|
3985
|
+
if (!existing.threadId && request.threadId) {
|
|
3986
|
+
existing.threadId = request.threadId;
|
|
3987
|
+
}
|
|
3988
|
+
return existing;
|
|
3989
|
+
}
|
|
4071
3990
|
return this.createRunStep(request);
|
|
4072
3991
|
}
|
|
4073
3992
|
async updateRunStep(runId, stepId, updates) {
|
|
@@ -4126,6 +4045,11 @@ var InMemoryChannelInstallationStore = class {
|
|
|
4126
4045
|
(inst) => inst.tenantId === tenantId && (!channel || inst.channel === channel)
|
|
4127
4046
|
);
|
|
4128
4047
|
}
|
|
4048
|
+
async getAllInstallations(channel) {
|
|
4049
|
+
return Array.from(this.installations.values()).filter(
|
|
4050
|
+
(inst) => !channel || inst.channel === channel
|
|
4051
|
+
);
|
|
4052
|
+
}
|
|
4129
4053
|
/**
|
|
4130
4054
|
* Creates a new channel installation for a tenant.
|
|
4131
4055
|
*
|
|
@@ -4402,6 +4326,107 @@ var InMemoryA2AApiKeyStore = class {
|
|
|
4402
4326
|
}
|
|
4403
4327
|
};
|
|
4404
4328
|
|
|
4329
|
+
// src/store_lattice/InMemoryTaskStore.ts
|
|
4330
|
+
var import_uuid = require("uuid");
|
|
4331
|
+
var InMemoryTaskStore = class {
|
|
4332
|
+
constructor() {
|
|
4333
|
+
this.tasks = /* @__PURE__ */ new Map();
|
|
4334
|
+
}
|
|
4335
|
+
/**
|
|
4336
|
+
* Create a new task
|
|
4337
|
+
*/
|
|
4338
|
+
async create(params) {
|
|
4339
|
+
if (!this.tasks.has(params.tenantId)) {
|
|
4340
|
+
this.tasks.set(params.tenantId, /* @__PURE__ */ new Map());
|
|
4341
|
+
}
|
|
4342
|
+
const now = /* @__PURE__ */ new Date();
|
|
4343
|
+
const task = {
|
|
4344
|
+
id: (0, import_uuid.v4)(),
|
|
4345
|
+
tenantId: params.tenantId,
|
|
4346
|
+
ownerType: params.ownerType,
|
|
4347
|
+
ownerId: params.ownerId,
|
|
4348
|
+
title: params.title,
|
|
4349
|
+
description: params.description,
|
|
4350
|
+
status: params.status || "pending",
|
|
4351
|
+
priority: params.priority || "medium",
|
|
4352
|
+
dueDate: params.dueDate,
|
|
4353
|
+
metadata: params.metadata,
|
|
4354
|
+
parentId: params.parentId,
|
|
4355
|
+
sourceId: params.sourceId,
|
|
4356
|
+
context: params.context,
|
|
4357
|
+
createdAt: now,
|
|
4358
|
+
updatedAt: now
|
|
4359
|
+
};
|
|
4360
|
+
this.tasks.get(params.tenantId).set(task.id, task);
|
|
4361
|
+
return task;
|
|
4362
|
+
}
|
|
4363
|
+
/**
|
|
4364
|
+
* Get task by ID
|
|
4365
|
+
*/
|
|
4366
|
+
async getById(tenantId, id) {
|
|
4367
|
+
const tenantTasks = this.tasks.get(tenantId);
|
|
4368
|
+
if (!tenantTasks) return null;
|
|
4369
|
+
return tenantTasks.get(id) || null;
|
|
4370
|
+
}
|
|
4371
|
+
/**
|
|
4372
|
+
* List tasks matching filter criteria
|
|
4373
|
+
*/
|
|
4374
|
+
async list(filter2) {
|
|
4375
|
+
const tenantTasks = this.tasks.get(filter2.tenantId);
|
|
4376
|
+
if (!tenantTasks) return [];
|
|
4377
|
+
let results = Array.from(tenantTasks.values());
|
|
4378
|
+
if (filter2.ownerType) results = results.filter((t) => t.ownerType === filter2.ownerType);
|
|
4379
|
+
if (filter2.ownerId) results = results.filter((t) => t.ownerId === filter2.ownerId);
|
|
4380
|
+
if (filter2.status) results = results.filter((t) => t.status === filter2.status);
|
|
4381
|
+
if (filter2.priority) results = results.filter((t) => t.priority === filter2.priority);
|
|
4382
|
+
if (filter2.parentId) results = results.filter((t) => t.parentId === filter2.parentId);
|
|
4383
|
+
if (filter2.sourceId) results = results.filter((t) => t.sourceId === filter2.sourceId);
|
|
4384
|
+
if (filter2.metadata) {
|
|
4385
|
+
for (const [key, value] of Object.entries(filter2.metadata)) {
|
|
4386
|
+
results = results.filter((t) => t.metadata?.[key] === value);
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4389
|
+
results.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
4390
|
+
const offset = filter2.offset || 0;
|
|
4391
|
+
const limit = filter2.limit || 100;
|
|
4392
|
+
return results.slice(offset, offset + limit);
|
|
4393
|
+
}
|
|
4394
|
+
/**
|
|
4395
|
+
* Update an existing task
|
|
4396
|
+
*/
|
|
4397
|
+
async update(tenantId, id, updates) {
|
|
4398
|
+
const tenantTasks = this.tasks.get(tenantId);
|
|
4399
|
+
if (!tenantTasks) return null;
|
|
4400
|
+
const existing = tenantTasks.get(id);
|
|
4401
|
+
if (!existing) return null;
|
|
4402
|
+
const updated = {
|
|
4403
|
+
...existing,
|
|
4404
|
+
...updates,
|
|
4405
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
4406
|
+
};
|
|
4407
|
+
tenantTasks.set(id, updated);
|
|
4408
|
+
return updated;
|
|
4409
|
+
}
|
|
4410
|
+
/**
|
|
4411
|
+
* Delete a task by ID
|
|
4412
|
+
*/
|
|
4413
|
+
async delete(tenantId, id) {
|
|
4414
|
+
const tenantTasks = this.tasks.get(tenantId);
|
|
4415
|
+
if (!tenantTasks) return false;
|
|
4416
|
+
return tenantTasks.delete(id);
|
|
4417
|
+
}
|
|
4418
|
+
/**
|
|
4419
|
+
* Clear all tasks for a tenant (useful for testing)
|
|
4420
|
+
*/
|
|
4421
|
+
clear(tenantId) {
|
|
4422
|
+
if (tenantId) {
|
|
4423
|
+
this.tasks.delete(tenantId);
|
|
4424
|
+
} else {
|
|
4425
|
+
this.tasks.clear();
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
};
|
|
4429
|
+
|
|
4405
4430
|
// src/store_lattice/StoreLatticeManager.ts
|
|
4406
4431
|
var StoreLatticeManager = class _StoreLatticeManager extends BaseLatticeManager {
|
|
4407
4432
|
/**
|
|
@@ -4582,6 +4607,12 @@ storeLatticeManager.registerLattice(
|
|
|
4582
4607
|
"a2aApiKey",
|
|
4583
4608
|
defaultA2AApiKeyStore
|
|
4584
4609
|
);
|
|
4610
|
+
var defaultTaskStore = new InMemoryTaskStore();
|
|
4611
|
+
storeLatticeManager.registerLattice(
|
|
4612
|
+
"default",
|
|
4613
|
+
"task",
|
|
4614
|
+
defaultTaskStore
|
|
4615
|
+
);
|
|
4585
4616
|
|
|
4586
4617
|
// src/tool_lattice/manage_binding/index.ts
|
|
4587
4618
|
function getInstallationStore() {
|
|
@@ -4593,7 +4624,7 @@ var manageBindingSchema = import_zod3.default.object({
|
|
|
4593
4624
|
channelInstallationId: import_zod3.default.string().optional().describe("Channel installation ID (auto-detected if omitted and only one exists for this channel)"),
|
|
4594
4625
|
senderId: import_zod3.default.string().optional().describe("Sender identifier (email address, Lark openId, Slack userId)"),
|
|
4595
4626
|
agentId: import_zod3.default.string().optional().describe("Target agent ID to route messages to"),
|
|
4596
|
-
threadMode: import_zod3.default.enum(["fixed", "per_conversation"]).optional().default("per_conversation").describe("Thread mode
|
|
4627
|
+
threadMode: import_zod3.default.enum(["fixed", "per_conversation"]).optional().default("per_conversation").describe("Thread mode (ignored when channel adapter has its own thread strategy, e.g. Lark)"),
|
|
4597
4628
|
senderDisplayName: import_zod3.default.string().optional().describe("Human-readable name for the sender")
|
|
4598
4629
|
});
|
|
4599
4630
|
registerToolLattice(
|
|
@@ -4602,9 +4633,13 @@ registerToolLattice(
|
|
|
4602
4633
|
name: "manage_binding",
|
|
4603
4634
|
description: `Manage sender-to-agent bindings for external channels (email, Lark, Slack).
|
|
4604
4635
|
|
|
4636
|
+
Bindings are OPTIONAL \u2014 if no binding exists for a sender, messages route to the installation's fallbackAgentId. Only create a binding when a specific sender needs a different agent.
|
|
4637
|
+
|
|
4638
|
+
Thread isolation is handled automatically by the channel adapter (e.g. Lark isolates by sender+date). threadMode is only used when the channel adapter does not have its own strategy.
|
|
4639
|
+
|
|
4605
4640
|
- list_installations: List available channel installations. Filter by channel type (optional). Use this first to discover available channelInstallationIds.
|
|
4606
|
-
- create: Bind a sender to an agent. Required: channel, senderId, agentId. Optional: threadMode
|
|
4607
|
-
- update: Update an existing binding. Required: channel, senderId. Optional: agentId, threadMode
|
|
4641
|
+
- create: Bind a sender to an agent. Required: channel, senderId, agentId. Optional: threadMode. channelInstallationId auto-detected if only one exists.
|
|
4642
|
+
- update: Update an existing binding. Required: channel, senderId. Optional: agentId, threadMode, senderDisplayName.
|
|
4608
4643
|
- delete: Remove a binding. Required: channel, senderId.
|
|
4609
4644
|
- list: List all bindings. Optional: channel, agentId, channelInstallationId.
|
|
4610
4645
|
|
|
@@ -4612,7 +4647,7 @@ A sender can only be bound to ONE agent per channel+installation combination.`,
|
|
|
4612
4647
|
schema: manageBindingSchema
|
|
4613
4648
|
},
|
|
4614
4649
|
async (input, config) => {
|
|
4615
|
-
const
|
|
4650
|
+
const registry3 = getBindingRegistry();
|
|
4616
4651
|
const runConfig = config?.configurable?.runConfig || {};
|
|
4617
4652
|
const tenantId = runConfig.tenantId || "default";
|
|
4618
4653
|
switch (input.action) {
|
|
@@ -4635,7 +4670,7 @@ A sender can only be bound to ONE agent per channel+installation combination.`,
|
|
|
4635
4670
|
error: `No channelInstallationId provided and unable to auto-detect. Use action=list_installations to find available installations for channel "${input.channel}".`
|
|
4636
4671
|
});
|
|
4637
4672
|
}
|
|
4638
|
-
const binding = await
|
|
4673
|
+
const binding = await registry3.create({
|
|
4639
4674
|
channel: input.channel,
|
|
4640
4675
|
channelInstallationId: installId,
|
|
4641
4676
|
tenantId,
|
|
@@ -4657,7 +4692,7 @@ A sender can only be bound to ONE agent per channel+installation combination.`,
|
|
|
4657
4692
|
error: `No channelInstallationId provided and unable to auto-detect. Use action=list_installations first.`
|
|
4658
4693
|
});
|
|
4659
4694
|
}
|
|
4660
|
-
const existing = await
|
|
4695
|
+
const existing = await registry3.resolve({
|
|
4661
4696
|
channel: input.channel,
|
|
4662
4697
|
senderId: input.senderId,
|
|
4663
4698
|
channelInstallationId: installId,
|
|
@@ -4666,7 +4701,7 @@ A sender can only be bound to ONE agent per channel+installation combination.`,
|
|
|
4666
4701
|
if (!existing) {
|
|
4667
4702
|
return JSON.stringify({ success: false, error: "Binding not found" });
|
|
4668
4703
|
}
|
|
4669
|
-
const updated = await
|
|
4704
|
+
const updated = await registry3.update(existing.id, {
|
|
4670
4705
|
agentId: input.agentId,
|
|
4671
4706
|
threadMode: input.threadMode,
|
|
4672
4707
|
senderDisplayName: input.senderDisplayName
|
|
@@ -4684,7 +4719,7 @@ A sender can only be bound to ONE agent per channel+installation combination.`,
|
|
|
4684
4719
|
error: `No channelInstallationId provided and unable to auto-detect.`
|
|
4685
4720
|
});
|
|
4686
4721
|
}
|
|
4687
|
-
const existing = await
|
|
4722
|
+
const existing = await registry3.resolve({
|
|
4688
4723
|
channel: input.channel,
|
|
4689
4724
|
senderId: input.senderId,
|
|
4690
4725
|
channelInstallationId: installId,
|
|
@@ -4693,11 +4728,11 @@ A sender can only be bound to ONE agent per channel+installation combination.`,
|
|
|
4693
4728
|
if (!existing) {
|
|
4694
4729
|
return JSON.stringify({ success: false, error: "Binding not found" });
|
|
4695
4730
|
}
|
|
4696
|
-
await
|
|
4731
|
+
await registry3.delete(existing.id);
|
|
4697
4732
|
return JSON.stringify({ success: true, message: "Binding deleted" });
|
|
4698
4733
|
}
|
|
4699
4734
|
case "list": {
|
|
4700
|
-
const bindings = await
|
|
4735
|
+
const bindings = await registry3.list({
|
|
4701
4736
|
channel: input.channel,
|
|
4702
4737
|
agentId: input.agentId,
|
|
4703
4738
|
tenantId,
|
|
@@ -5595,7 +5630,8 @@ function getTenantIdFromConfig2(exeConfig, getTenantId2) {
|
|
|
5595
5630
|
const runConfig = exeConfig?.configurable?.runConfig || {};
|
|
5596
5631
|
return runConfig.tenantId || (getTenantId2 ? getTenantId2() : "default");
|
|
5597
5632
|
}
|
|
5598
|
-
function filterServerKeysByTenant(serverKeys, tenantId, manager = metricsServerManager) {
|
|
5633
|
+
async function filterServerKeysByTenant(serverKeys, tenantId, manager = metricsServerManager) {
|
|
5634
|
+
await manager.ensureLoaded();
|
|
5599
5635
|
return serverKeys.filter((key) => {
|
|
5600
5636
|
return manager.hasServer(tenantId, key);
|
|
5601
5637
|
});
|
|
@@ -6373,6 +6409,14 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
6373
6409
|
}
|
|
6374
6410
|
return config;
|
|
6375
6411
|
}
|
|
6412
|
+
/**
|
|
6413
|
+
* Ensure server configs are loaded from the store.
|
|
6414
|
+
* Public wrapper around the internal lazy-loading mechanism.
|
|
6415
|
+
* Safe to call multiple times — loading happens at most once.
|
|
6416
|
+
*/
|
|
6417
|
+
async ensureLoaded() {
|
|
6418
|
+
await this._ensureLoaded();
|
|
6419
|
+
}
|
|
6376
6420
|
/**
|
|
6377
6421
|
* Check if a metrics server is registered for a tenant
|
|
6378
6422
|
* @param tenantId - Tenant identifier
|
|
@@ -6513,7 +6557,7 @@ ${serverKeys.map(
|
|
|
6513
6557
|
if (connectAll) {
|
|
6514
6558
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
6515
6559
|
}
|
|
6516
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
6560
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
6517
6561
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
6518
6562
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
6519
6563
|
if (metricsDataSource) {
|
|
@@ -6632,7 +6676,7 @@ ${serverKeys.map(
|
|
|
6632
6676
|
if (connectAll) {
|
|
6633
6677
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
6634
6678
|
}
|
|
6635
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
6679
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
6636
6680
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
6637
6681
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
6638
6682
|
const serverKey = metricsDataSource?.serverKey || inputServerKey;
|
|
@@ -6790,7 +6834,7 @@ ${serverKeys.map(
|
|
|
6790
6834
|
if (connectAll) {
|
|
6791
6835
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
6792
6836
|
}
|
|
6793
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
6837
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
6794
6838
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
6795
6839
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
6796
6840
|
const serverKey = metricsDataSource?.serverKey || inputServerKey;
|
|
@@ -7026,7 +7070,7 @@ ${serverKeys.map(
|
|
|
7026
7070
|
if (connectAll) {
|
|
7027
7071
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
7028
7072
|
}
|
|
7029
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7073
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7030
7074
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
7031
7075
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
7032
7076
|
const serverKey = metricsDataSource?.serverKey || inputServerKey;
|
|
@@ -7107,7 +7151,7 @@ ${serverKeys.map(
|
|
|
7107
7151
|
if (connectAll) {
|
|
7108
7152
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
7109
7153
|
}
|
|
7110
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7154
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7111
7155
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
7112
7156
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
7113
7157
|
const serverKey = metricsDataSource?.serverKey || inputServerKey;
|
|
@@ -7212,7 +7256,7 @@ ${serverKeys.map(
|
|
|
7212
7256
|
if (connectAll) {
|
|
7213
7257
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
7214
7258
|
}
|
|
7215
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7259
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7216
7260
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
7217
7261
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
7218
7262
|
const serverKey = metricsDataSource?.serverKey || inputServerKey;
|
|
@@ -7352,7 +7396,7 @@ ${serverKeys.map(
|
|
|
7352
7396
|
if (connectAll) {
|
|
7353
7397
|
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
7354
7398
|
}
|
|
7355
|
-
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7399
|
+
const filteredServerKeys = await filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
7356
7400
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
7357
7401
|
const metricsDataSource = runConfig.metricsDataSource;
|
|
7358
7402
|
const serverKey = metricsDataSource?.serverKey || inputServerKey;
|
|
@@ -7413,7 +7457,9 @@ var VolumeFilesystem = class {
|
|
|
7413
7457
|
this.mountPrefix = mountPrefix;
|
|
7414
7458
|
}
|
|
7415
7459
|
async lsInfo(path3) {
|
|
7460
|
+
console.log(`[VolumeFilesystem.lsInfo] path=${path3} mountPrefix=${this.mountPrefix}`);
|
|
7416
7461
|
const entries = await this.client.list(path3);
|
|
7462
|
+
console.log(`[VolumeFilesystem.lsInfo] got ${entries.length} entries`);
|
|
7417
7463
|
const prefix = this.mountPrefix.endsWith("/") ? this.mountPrefix : this.mountPrefix + "/";
|
|
7418
7464
|
return entries.map((entry) => ({
|
|
7419
7465
|
path: entry.path.startsWith("/") ? entry.path : prefix + entry.path,
|
|
@@ -7605,30 +7651,45 @@ var SandboxLatticeManager = class _SandboxLatticeManager extends BaseLatticeMana
|
|
|
7605
7651
|
async getVolumeBackendForPath(config, filePath) {
|
|
7606
7652
|
const provider = this._requireProvider();
|
|
7607
7653
|
if (!provider.createVolumeFsClient) {
|
|
7654
|
+
console.log(`[getVolumeBackendForPath] provider has no createVolumeFsClient, returning null`);
|
|
7608
7655
|
return null;
|
|
7609
7656
|
}
|
|
7610
7657
|
const tenantId = config.tenantId ?? "default";
|
|
7611
7658
|
const mapping = this._resolveVolumeForPath(config, tenantId, filePath);
|
|
7612
|
-
if (!mapping)
|
|
7659
|
+
if (!mapping) {
|
|
7660
|
+
console.log(`[getVolumeBackendForPath] no volume mapping for path=${filePath}`);
|
|
7661
|
+
return null;
|
|
7662
|
+
}
|
|
7663
|
+
console.log(`[getVolumeBackendForPath] path=${filePath} volume=${mapping.volumeName} prefix=${mapping.pathPrefix}`);
|
|
7613
7664
|
const client = provider.createVolumeFsClient(mapping.volumeName, mapping.pathPrefix);
|
|
7614
7665
|
return new VolumeFilesystem(stripPrefixClient(client, mapping.pathPrefix), mapping.pathPrefix);
|
|
7615
7666
|
}
|
|
7616
7667
|
_resolveVolumeForPath(config, tenantId, filePath) {
|
|
7617
7668
|
const normalized = normalizeExternalSandboxPath(filePath);
|
|
7669
|
+
console.log(`[_resolveVolumeForPath] filePath=${filePath} normalized=${normalized} assistant_id=${config.assistant_id} projectId=${config.projectId}`);
|
|
7618
7670
|
if (normalized === "/root/.agents" || normalized.startsWith("/root/.agents/")) {
|
|
7671
|
+
console.log(`[_resolveVolumeForPath] \u2192 skills volume`);
|
|
7619
7672
|
return {
|
|
7620
7673
|
volumeName: buildNamedVolumeName("s", "skills", tenantId),
|
|
7621
7674
|
pathPrefix: "/root/.agents"
|
|
7622
7675
|
};
|
|
7623
7676
|
}
|
|
7624
7677
|
if (normalized === "/agent" || normalized.startsWith("/agent/")) {
|
|
7625
|
-
if (!config.assistant_id)
|
|
7678
|
+
if (!config.assistant_id) {
|
|
7679
|
+
console.log(`[_resolveVolumeForPath] agent volume but no assistant_id, returning null`);
|
|
7680
|
+
return null;
|
|
7681
|
+
}
|
|
7682
|
+
console.log(`[_resolveVolumeForPath] \u2192 agent volume`);
|
|
7626
7683
|
return {
|
|
7627
7684
|
volumeName: buildNamedVolumeName("a", "agent", tenantId, config.assistant_id),
|
|
7628
7685
|
pathPrefix: "/agent"
|
|
7629
7686
|
};
|
|
7630
7687
|
}
|
|
7631
|
-
if (!config.projectId)
|
|
7688
|
+
if (!config.projectId) {
|
|
7689
|
+
console.log(`[_resolveVolumeForPath] project volume but no projectId, returning null`);
|
|
7690
|
+
return null;
|
|
7691
|
+
}
|
|
7692
|
+
console.log(`[_resolveVolumeForPath] \u2192 project volume`);
|
|
7632
7693
|
return {
|
|
7633
7694
|
volumeName: buildNamedVolumeName("p", "project", tenantId, config.workspaceId, config.projectId),
|
|
7634
7695
|
pathPrefix: "/project"
|
|
@@ -8672,7 +8733,7 @@ var createBrowserGetInfoTool = ({ vmIsolation }) => {
|
|
|
8672
8733
|
};
|
|
8673
8734
|
|
|
8674
8735
|
// src/index.ts
|
|
8675
|
-
var
|
|
8736
|
+
var import_messages6 = require("@langchain/core/messages");
|
|
8676
8737
|
|
|
8677
8738
|
// src/agent_lattice/types.ts
|
|
8678
8739
|
var import_protocols = require("@axiom-lattice/protocols");
|
|
@@ -8691,7 +8752,7 @@ var createReactAgentSchema = (schema) => {
|
|
|
8691
8752
|
};
|
|
8692
8753
|
|
|
8693
8754
|
// src/agent_lattice/builders/ReActAgentGraphBuilder.ts
|
|
8694
|
-
var
|
|
8755
|
+
var import_langchain57 = require("langchain");
|
|
8695
8756
|
|
|
8696
8757
|
// src/middlewares/codeEvalMiddleware.ts
|
|
8697
8758
|
var import_langchain37 = require("langchain");
|
|
@@ -9162,353 +9223,233 @@ metadata:
|
|
|
9162
9223
|
Then iterate based on what the user says.
|
|
9163
9224
|
`,
|
|
9164
9225
|
"create-workflow": `---
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
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
|
|
9226
|
+
name: create-workflow
|
|
9227
|
+
description: Design and build multi-step AI workflows using the YAML linear DSL. Use whenever users want to orchestrate agents in a pipeline with routing, parallelism, human-in-the-loop, or batch processing.
|
|
9228
|
+
license: MIT
|
|
9229
|
+
metadata:
|
|
9230
|
+
category: meta
|
|
9231
|
+
version: "5.0"
|
|
9232
|
+
---
|
|
9180
9233
|
|
|
9181
|
-
|
|
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
|
|
9234
|
+
# YAML Workflow Designer
|
|
9185
9235
|
|
|
9186
|
-
|
|
9236
|
+
Use the linear YAML DSL \u2014 steps execute top-to-bottom. Use \`parallel:\` for concurrency. No dependency graph thinking required.
|
|
9187
9237
|
|
|
9188
|
-
|
|
9238
|
+
## Core Model: Linear + Parallel
|
|
9189
9239
|
|
|
9190
|
-
|
|
9240
|
+
- **Linear** \u2014 steps execute in written order. No \`needs\`, no dependency declarations.
|
|
9241
|
+
- **parallel** \u2014 a block where all children run concurrently. Block completes when all children finish.
|
|
9242
|
+
- **if** \u2014 JS expression. Step runs only when truthy. Omit to always run.
|
|
9243
|
+
- **prompt** \u2014 agent instruction with **{{label}}** refs. **{{input}}** is the user message.
|
|
9244
|
+
- **output** \u2014 shorthand schema using **{ field: type }** notation.
|
|
9245
|
+
- **ask** \u2014 boolean. Injects user clarification middleware for human interaction.
|
|
9191
9246
|
|
|
9192
|
-
|
|
9193
|
-
{ "id": "classify", "name": "Classify Intent", "prompt": "Classify the intent of: {{input}}", "schema": { "type": "object", "properties": { "intent": { "type": "string" } } } }
|
|
9194
|
-
\`\`\`
|
|
9247
|
+
## When to Use parallel vs map
|
|
9195
9248
|
|
|
9196
|
-
|
|
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.
|
|
9249
|
+
This is the most important design decision. **They are fundamentally different:**
|
|
9202
9250
|
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
-
|
|
9208
|
-
|
|
9251
|
+
| | parallel | map |
|
|
9252
|
+
|---|---|---|
|
|
9253
|
+
| **Concern** | **Business parallelism** \u2014 reduce business processing time | **Data parallelism** \u2014 handle data volume |
|
|
9254
|
+
| **Tasks** | Each child does a **different** task | All items do the **same** task |
|
|
9255
|
+
| **Count** | Few (2-5), each hand-written | Dynamic, driven by source data |
|
|
9256
|
+
| **Input** | Independent prompts per child | Single \`each.prompt\` template, \`{{item}}\` for current element |
|
|
9257
|
+
| **if** | Per-child conditional | Whole block conditional |
|
|
9258
|
+
| **Example** | Legal review + Market analysis in parallel | Audit each line item in an invoice |
|
|
9209
9259
|
|
|
9210
|
-
|
|
9260
|
+
**Rule of thumb:** If you're writing the same prompt twice, you probably want \`map\`. If each branch has a unique purpose, use \`parallel\`.
|
|
9211
9261
|
|
|
9212
|
-
|
|
9262
|
+
## Step Format
|
|
9213
9263
|
|
|
9214
|
-
|
|
9264
|
+
### Agent Step
|
|
9215
9265
|
|
|
9216
|
-
\`\`\`
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
}
|
|
9266
|
+
\`\`\`yaml
|
|
9267
|
+
- label:
|
|
9268
|
+
prompt: instruction with {{refs}}
|
|
9269
|
+
if: "expression"
|
|
9270
|
+
output: { field: type }
|
|
9271
|
+
ask: true
|
|
9221
9272
|
\`\`\`
|
|
9222
9273
|
|
|
9223
|
-
|
|
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:
|
|
9274
|
+
### Parallel Block
|
|
9234
9275
|
|
|
9235
|
-
\`\`\`
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
}
|
|
9243
|
-
}
|
|
9276
|
+
\`\`\`yaml
|
|
9277
|
+
- parallel:
|
|
9278
|
+
- child1:
|
|
9279
|
+
prompt: ...
|
|
9280
|
+
if: "expression"
|
|
9281
|
+
- child2:
|
|
9282
|
+
prompt: ...
|
|
9244
9283
|
\`\`\`
|
|
9245
9284
|
|
|
9246
|
-
|
|
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 |
|
|
9285
|
+
Parallel children are agent steps only. No nested parallel or map inside parallel.
|
|
9251
9286
|
|
|
9252
|
-
|
|
9287
|
+
### Map Step
|
|
9253
9288
|
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9289
|
+
\`\`\`yaml
|
|
9290
|
+
- label:
|
|
9291
|
+
map:
|
|
9292
|
+
source: "extract.items"
|
|
9293
|
+
if: "extract.items.length > 0"
|
|
9294
|
+
each:
|
|
9295
|
+
prompt: Process {{item}}
|
|
9296
|
+
output: { result: string }
|
|
9297
|
+
batch: 50
|
|
9298
|
+
concurrency: 5
|
|
9264
9299
|
\`\`\`
|
|
9265
9300
|
|
|
9266
|
-
|
|
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) |
|
|
9301
|
+
## Schema Shorthand
|
|
9294
9302
|
|
|
9295
|
-
|
|
9303
|
+
Write **{ field: type }** instead of JSON Schema:
|
|
9296
9304
|
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9305
|
+
| Shorthand | Meaning |
|
|
9306
|
+
|-----------|---------|
|
|
9307
|
+
| **field: string** | string property |
|
|
9308
|
+
| **field: number** | number property |
|
|
9309
|
+
| **field: boolean** | boolean property |
|
|
9310
|
+
| **field: string[]** | array of strings |
|
|
9311
|
+
| **field: number[]** | array of numbers |
|
|
9312
|
+
| **field: [{ a: string, b: number }]** | array of objects |
|
|
9313
|
+
| **field: { sub: string }** | nested object |
|
|
9303
9314
|
|
|
9304
|
-
|
|
9315
|
+
Use **block style** (each field on its own line). Flow style \`{ field: "type" }\` with quoted values also works.
|
|
9305
9316
|
|
|
9306
|
-
|
|
9317
|
+
## Template Syntax
|
|
9307
9318
|
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9319
|
+
| Syntax | Resolves to |
|
|
9320
|
+
|--------|------------|
|
|
9321
|
+
| \`{{input}}\` | Initial user message |
|
|
9322
|
+
| \`{{label}}\` | Full output of step |
|
|
9323
|
+
| \`{{label.field}}\` | Nested field access |
|
|
9324
|
+
| \`{{item}}\` | Current element in map iteration |
|
|
9311
9325
|
|
|
9312
|
-
|
|
9326
|
+
## Design Patterns
|
|
9313
9327
|
|
|
9314
|
-
|
|
9328
|
+
### Linear Pipeline
|
|
9315
9329
|
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
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\` |
|
|
9330
|
+
\`\`\`yaml
|
|
9331
|
+
steps:
|
|
9332
|
+
- extract:
|
|
9333
|
+
prompt: Extract data from {{input}}
|
|
9334
|
+
- transform:
|
|
9335
|
+
prompt: Transform {{extract}}
|
|
9336
|
+
- final:
|
|
9337
|
+
prompt: Combine raw {{extract}} with transformed {{transform}}
|
|
9338
|
+
\`\`\`
|
|
9336
9339
|
|
|
9337
|
-
|
|
9340
|
+
### Classify -> Route via Parallel + if
|
|
9338
9341
|
|
|
9339
|
-
|
|
9342
|
+
\`\`\`yaml
|
|
9343
|
+
steps:
|
|
9344
|
+
- classify:
|
|
9345
|
+
prompt: Classify intent from {{input}}
|
|
9346
|
+
output:
|
|
9347
|
+
intent: string
|
|
9348
|
+
urgency: number
|
|
9349
|
+
- parallel:
|
|
9350
|
+
- billing:
|
|
9351
|
+
if: "classify.intent == 'billing'"
|
|
9352
|
+
prompt: Handle billing: {{input}}
|
|
9353
|
+
ask: true
|
|
9354
|
+
- technical:
|
|
9355
|
+
if: "classify.intent == 'technical'"
|
|
9356
|
+
prompt: Handle technical: {{input}}
|
|
9357
|
+
- escalate:
|
|
9358
|
+
if: "classify.urgency >= 8"
|
|
9359
|
+
prompt: Urgent handling
|
|
9360
|
+
ask: true
|
|
9361
|
+
\`\`\`
|
|
9340
9362
|
|
|
9341
|
-
|
|
9342
|
-
\`\`\`json
|
|
9343
|
-
// \u274C WRONG \u2014 {{}} does not belong in if:
|
|
9344
|
-
{ "type": "condition", "if": "{{intent}}", "then": {...}, "else": {...} }
|
|
9363
|
+
### Parallel Processing
|
|
9345
9364
|
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9365
|
+
\`\`\`yaml
|
|
9366
|
+
steps:
|
|
9367
|
+
- gather:
|
|
9368
|
+
prompt: Gather data from {{input}}
|
|
9369
|
+
- parallel:
|
|
9370
|
+
- legal:
|
|
9371
|
+
prompt: Legal analysis of {{gather}}
|
|
9372
|
+
output:
|
|
9373
|
+
risk: string
|
|
9374
|
+
compliant: boolean
|
|
9375
|
+
- market:
|
|
9376
|
+
prompt: Market analysis of {{gather}}
|
|
9377
|
+
output:
|
|
9378
|
+
opportunity: string
|
|
9379
|
+
score: number
|
|
9380
|
+
- report:
|
|
9381
|
+
prompt: |
|
|
9382
|
+
Synthesize findings:
|
|
9383
|
+
Legal: {{legal}}
|
|
9384
|
+
Market: {{market}}
|
|
9385
|
+
\`\`\`
|
|
9349
9386
|
|
|
9350
|
-
|
|
9387
|
+
### Approval Flow with Human
|
|
9351
9388
|
|
|
9352
|
-
|
|
9389
|
+
\`\`\`yaml
|
|
9390
|
+
steps:
|
|
9391
|
+
- draft:
|
|
9392
|
+
prompt: Draft response to {{input}}
|
|
9393
|
+
- review:
|
|
9394
|
+
prompt: Present {{draft}} to user for approval
|
|
9395
|
+
output:
|
|
9396
|
+
approved: boolean
|
|
9397
|
+
comments: string
|
|
9398
|
+
ask: true
|
|
9399
|
+
- publish:
|
|
9400
|
+
if: "review.approved"
|
|
9401
|
+
prompt: Publish {{draft}}
|
|
9402
|
+
- revise:
|
|
9403
|
+
if: "!review.approved"
|
|
9404
|
+
prompt: Revise based on {{review.comments}}
|
|
9405
|
+
\`\`\`
|
|
9353
9406
|
|
|
9354
|
-
|
|
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.
|
|
9407
|
+
### Map (Iteration)
|
|
9360
9408
|
|
|
9361
|
-
|
|
9409
|
+
\`\`\`yaml
|
|
9410
|
+
steps:
|
|
9411
|
+
- extract:
|
|
9412
|
+
prompt: Extract items from {{input}}
|
|
9413
|
+
output:
|
|
9414
|
+
items:
|
|
9415
|
+
- name: string
|
|
9416
|
+
- map_items:
|
|
9417
|
+
map:
|
|
9418
|
+
source: "extract.items"
|
|
9419
|
+
each:
|
|
9420
|
+
prompt: Audit {{item.name}}
|
|
9421
|
+
output:
|
|
9422
|
+
result: string
|
|
9423
|
+
- summary:
|
|
9424
|
+
prompt: Summarize findings: {{map_items}}
|
|
9425
|
+
\`\`\`
|
|
9362
9426
|
|
|
9363
|
-
|
|
9427
|
+
## Keep Business Logic in Agents
|
|
9364
9428
|
|
|
9365
|
-
|
|
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
|
-
\`\`\`
|
|
9429
|
+
The DSL is for orchestration (what runs when). Business logic (validation, branching, error handling, user interaction) belongs inside agent prompts, not as workflow if conditions. An agent can validate, branch, and ask questions \u2014 all in one step.
|
|
9375
9430
|
|
|
9376
|
-
|
|
9431
|
+
**Rule:** if you have more if conditions than workflow phases, move logic into richer agent prompts.
|
|
9377
9432
|
|
|
9378
|
-
|
|
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
|
-
\`\`\`
|
|
9433
|
+
## What You NEVER Write
|
|
9391
9434
|
|
|
9392
|
-
|
|
9435
|
+
- **needs** \u2014 not supported. Steps execute linearly. Use parallel for concurrency.
|
|
9436
|
+
- **edges** \u2014 auto-generated from step order and parallel structure
|
|
9437
|
+
- **nested parallel** \u2014 parallel children are flat agent steps only
|
|
9438
|
+
- **map inside parallel** \u2014 map is a top-level step only
|
|
9439
|
+
- **json schema** \u2014 use **{ field: type }** block style
|
|
9440
|
+
- do not use {{}} markers in if expressions
|
|
9441
|
+
- **workflow-level business logic** \u2014 decisions belong inside agent prompts
|
|
9393
9442
|
|
|
9394
|
-
|
|
9443
|
+
## Checklist
|
|
9395
9444
|
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
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
|
-
\`\`\`
|
|
9433
|
-
|
|
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
|
-
\`\`\`
|
|
9451
|
-
|
|
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
|
-
\`\`\`
|
|
9468
|
-
|
|
9469
|
-
## Step 1: Understand the Process
|
|
9470
|
-
|
|
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?
|
|
9477
|
-
|
|
9478
|
-
## Step 2: Prepare Dependencies
|
|
9479
|
-
|
|
9480
|
-
1. Call \`list_tools\` to see available tools for the workflow agent.
|
|
9481
|
-
|
|
9482
|
-
## Step 3: Write the DSL
|
|
9483
|
-
|
|
9484
|
-
Use \`create_workflow\` with \`skillLoaded: true\`. Never write \`state.fields\`, \`edges\`, \`version\`, or \`output.key\` \u2014 they are auto-generated.
|
|
9485
|
-
|
|
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)
|
|
9498
|
-
|
|
9499
|
-
## Step 4: Test
|
|
9500
|
-
|
|
9501
|
-
After creating, optionally call \`validate_workflow(id)\` to check the workflow compiles correctly. Then test with \`invoke_agent\`.
|
|
9502
|
-
|
|
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
|
-
`
|
|
9445
|
+
- Every step has a unique label
|
|
9446
|
+
- Steps execute top-to-bottom \u2014 no dependency thinking needed
|
|
9447
|
+
- \`{{label}}\` can reference ANY upstream step output
|
|
9448
|
+
- if uses plain JS, no {{}}
|
|
9449
|
+
- Schema uses block style shorthand
|
|
9450
|
+
- parallel children are flat agent steps
|
|
9451
|
+
- Business logic stays inside agent prompts
|
|
9452
|
+
- ask: true for human interaction`
|
|
9512
9453
|
};
|
|
9513
9454
|
function getBuiltInSkillMeta(name) {
|
|
9514
9455
|
const content = BUILTIN_SKILLS[name];
|
|
@@ -12419,7 +12360,7 @@ ${currentSystemPrompt}` : dateContext;
|
|
|
12419
12360
|
// src/deep_agent_new/middleware/scheduler.ts
|
|
12420
12361
|
var import_langchain55 = require("langchain");
|
|
12421
12362
|
var import_zod50 = require("zod");
|
|
12422
|
-
var
|
|
12363
|
+
var import_uuid3 = require("uuid");
|
|
12423
12364
|
var import_protocols8 = require("@axiom-lattice/protocols");
|
|
12424
12365
|
|
|
12425
12366
|
// src/schedule_lattice/ScheduleLatticeManager.ts
|
|
@@ -13974,7 +13915,7 @@ var buffer = new InMemoryChunkBuffer({
|
|
|
13974
13915
|
registerChunkBuffer("default", buffer);
|
|
13975
13916
|
|
|
13976
13917
|
// src/services/Agent.ts
|
|
13977
|
-
var
|
|
13918
|
+
var import_uuid2 = require("uuid");
|
|
13978
13919
|
var ThreadStatus2 = /* @__PURE__ */ ((ThreadStatus3) => {
|
|
13979
13920
|
ThreadStatus3["IDLE"] = "idle";
|
|
13980
13921
|
ThreadStatus3["BUSY"] = "busy";
|
|
@@ -14020,7 +13961,7 @@ var Agent = class {
|
|
|
14020
13961
|
runConfig
|
|
14021
13962
|
},
|
|
14022
13963
|
configurable: {
|
|
14023
|
-
run_id: (0,
|
|
13964
|
+
run_id: (0, import_uuid2.v4)(),
|
|
14024
13965
|
...runConfig,
|
|
14025
13966
|
runConfig
|
|
14026
13967
|
},
|
|
@@ -14054,7 +13995,6 @@ var Agent = class {
|
|
|
14054
13995
|
const runnable_agent = await getAgentClientAsync(this.tenant_id, this.assistant_id);
|
|
14055
13996
|
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(this.tenant_id, this.assistant_id);
|
|
14056
13997
|
const { messages, ...rest } = input;
|
|
14057
|
-
const lifecycleManager = this;
|
|
14058
13998
|
const runConfig = {
|
|
14059
13999
|
thread_id: this.thread_id,
|
|
14060
14000
|
"x-tenant-id": this.tenant_id,
|
|
@@ -14094,7 +14034,7 @@ var Agent = class {
|
|
|
14094
14034
|
runConfig
|
|
14095
14035
|
},
|
|
14096
14036
|
configurable: {
|
|
14097
|
-
run_id: (0,
|
|
14037
|
+
run_id: (0, import_uuid2.v4)(),
|
|
14098
14038
|
...runConfig,
|
|
14099
14039
|
runConfig
|
|
14100
14040
|
// Inject runConfig for tools to access
|
|
@@ -14106,43 +14046,13 @@ var Agent = class {
|
|
|
14106
14046
|
}
|
|
14107
14047
|
);
|
|
14108
14048
|
try {
|
|
14109
|
-
|
|
14110
|
-
if (signal?.aborted) {
|
|
14111
|
-
await lifecycleManager.chunkBuffer.abortThread(lifecycleManager.thread_id);
|
|
14112
|
-
throw new Error("Agent execution was aborted");
|
|
14113
|
-
}
|
|
14114
|
-
let data;
|
|
14115
|
-
let chunkContent = "";
|
|
14116
|
-
if (chunk2[0] === "updates") {
|
|
14117
|
-
const update = chunk2[1];
|
|
14118
|
-
const values = Object.values(update);
|
|
14119
|
-
const messages2 = values[0]?.messages;
|
|
14120
|
-
if (messages2?.[0]?.tool_call_id) {
|
|
14121
|
-
data = messages2[0].toDict();
|
|
14122
|
-
}
|
|
14123
|
-
} else if (chunk2[0] === "messages") {
|
|
14124
|
-
const messages2 = chunk2[1];
|
|
14125
|
-
data = messages2?.[0]?.toDict();
|
|
14126
|
-
}
|
|
14127
|
-
if (chunk2?.[1]?.__interrupt__) {
|
|
14128
|
-
const interruptData = chunk2?.[1]?.__interrupt__[0];
|
|
14129
|
-
data = {
|
|
14130
|
-
type: "interrupt",
|
|
14131
|
-
id: interruptData.id,
|
|
14132
|
-
data: { content: interruptData.value }
|
|
14133
|
-
};
|
|
14134
|
-
}
|
|
14135
|
-
if (data) {
|
|
14136
|
-
lifecycleManager.addChunk(data);
|
|
14137
|
-
}
|
|
14138
|
-
}
|
|
14049
|
+
await this.consumeAgentStream(agentStream, signal);
|
|
14139
14050
|
} catch (error) {
|
|
14140
14051
|
console.error("Stream error:", error);
|
|
14141
|
-
await lifecycleManager.chunkBuffer.abortThread(lifecycleManager.thread_id);
|
|
14142
14052
|
throw error;
|
|
14143
14053
|
}
|
|
14144
14054
|
} catch (error) {
|
|
14145
|
-
await this.chunkBuffer.abortThread(
|
|
14055
|
+
await this.chunkBuffer.abortThread(this.thread_id);
|
|
14146
14056
|
throw error;
|
|
14147
14057
|
}
|
|
14148
14058
|
};
|
|
@@ -14423,8 +14333,8 @@ var Agent = class {
|
|
|
14423
14333
|
this.assistant_id = assistant_id;
|
|
14424
14334
|
this.thread_id = thread_id;
|
|
14425
14335
|
this.tenant_id = tenant_id;
|
|
14426
|
-
this.workspace_id = workspace_id;
|
|
14427
|
-
this.project_id = project_id;
|
|
14336
|
+
this.workspace_id = workspace_id || "default";
|
|
14337
|
+
this.project_id = project_id || "default";
|
|
14428
14338
|
this.custom_run_config = custom_run_config;
|
|
14429
14339
|
}
|
|
14430
14340
|
getHumanPendingContent(message) {
|
|
@@ -14510,7 +14420,7 @@ var Agent = class {
|
|
|
14510
14420
|
};
|
|
14511
14421
|
}
|
|
14512
14422
|
async invoke(queueMessage, signal) {
|
|
14513
|
-
const messageId = (0,
|
|
14423
|
+
const messageId = (0, import_uuid2.v4)();
|
|
14514
14424
|
const input = {
|
|
14515
14425
|
...queueMessage.input,
|
|
14516
14426
|
messages: [new import_langchain54.HumanMessage({ id: messageId, content: queueMessage.input.message })]
|
|
@@ -14518,10 +14428,132 @@ var Agent = class {
|
|
|
14518
14428
|
const inputMessage = { ...queueMessage, input };
|
|
14519
14429
|
return this.agentExecutor(inputMessage, signal);
|
|
14520
14430
|
}
|
|
14431
|
+
/**
|
|
14432
|
+
* Like {@link invoke} but returns the full LangGraph state (all annotations)
|
|
14433
|
+
* instead of only messages. Messages are serialized to dicts; other state
|
|
14434
|
+
* fields are returned as-is.
|
|
14435
|
+
*
|
|
14436
|
+
* @remarks
|
|
14437
|
+
* Only call this when you need the full state. Existing callers (gateway,
|
|
14438
|
+
* workflows) should keep using {@link invoke} which returns only messages
|
|
14439
|
+
* to avoid exposing internal annotation data.
|
|
14440
|
+
*/
|
|
14441
|
+
async invokeWithState(queueMessage, signal) {
|
|
14442
|
+
const messageId = (0, import_uuid2.v4)();
|
|
14443
|
+
const input = {
|
|
14444
|
+
...queueMessage.input,
|
|
14445
|
+
messages: [new import_langchain54.HumanMessage({ id: messageId, content: queueMessage.input.message })]
|
|
14446
|
+
};
|
|
14447
|
+
const inputMessage = { ...queueMessage, input };
|
|
14448
|
+
const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(inputMessage.custom_run_config);
|
|
14449
|
+
const { messages, ...rest } = inputMessage.input;
|
|
14450
|
+
if (signal?.aborted) {
|
|
14451
|
+
throw new Error("Agent execution was aborted");
|
|
14452
|
+
}
|
|
14453
|
+
let result;
|
|
14454
|
+
result = await runnable_agent.invoke(
|
|
14455
|
+
inputMessage.command ? new import_langgraph6.Command(inputMessage.command) : { ...rest, messages, "x-tenant-id": this.tenant_id },
|
|
14456
|
+
{
|
|
14457
|
+
context: { runConfig },
|
|
14458
|
+
configurable: {
|
|
14459
|
+
run_id: (0, import_uuid2.v4)(),
|
|
14460
|
+
...runConfig,
|
|
14461
|
+
runConfig
|
|
14462
|
+
},
|
|
14463
|
+
recursionLimit: 200,
|
|
14464
|
+
signal
|
|
14465
|
+
}
|
|
14466
|
+
);
|
|
14467
|
+
if (signal?.aborted) {
|
|
14468
|
+
throw new Error("Agent execution was aborted");
|
|
14469
|
+
}
|
|
14470
|
+
const { messages: _rawMessages, ...restState } = result;
|
|
14471
|
+
const serializedMessages = result.messages.map((message) => {
|
|
14472
|
+
const { type, data } = message.toDict();
|
|
14473
|
+
return { ...data, role: type };
|
|
14474
|
+
});
|
|
14475
|
+
return { messages: serializedMessages, ...restState };
|
|
14476
|
+
}
|
|
14521
14477
|
async getPendingMessages() {
|
|
14522
14478
|
const store = this.getQueueStore();
|
|
14523
14479
|
return await store.getPendingMessages(this.thread_id);
|
|
14524
14480
|
}
|
|
14481
|
+
async consumeAgentStream(agentStream, signal) {
|
|
14482
|
+
for await (const chunk2 of agentStream) {
|
|
14483
|
+
if (signal?.aborted) {
|
|
14484
|
+
await this.chunkBuffer.abortThread(this.thread_id);
|
|
14485
|
+
throw new Error("Agent execution was aborted");
|
|
14486
|
+
}
|
|
14487
|
+
let data;
|
|
14488
|
+
if (chunk2[0] === "updates") {
|
|
14489
|
+
const update = chunk2[1];
|
|
14490
|
+
const values = Object.values(update);
|
|
14491
|
+
const messages = values[0]?.messages;
|
|
14492
|
+
if (messages?.[0]?.tool_call_id) {
|
|
14493
|
+
data = messages[0].toDict();
|
|
14494
|
+
}
|
|
14495
|
+
} else if (chunk2[0] === "messages") {
|
|
14496
|
+
const messages = chunk2[1];
|
|
14497
|
+
data = messages?.[0]?.toDict();
|
|
14498
|
+
}
|
|
14499
|
+
if (chunk2?.[1]?.__interrupt__) {
|
|
14500
|
+
const interruptData = chunk2?.[1]?.__interrupt__[0];
|
|
14501
|
+
data = {
|
|
14502
|
+
type: "interrupt",
|
|
14503
|
+
id: interruptData.id,
|
|
14504
|
+
data: { content: interruptData.value }
|
|
14505
|
+
};
|
|
14506
|
+
}
|
|
14507
|
+
if (data) {
|
|
14508
|
+
this.addChunk(data);
|
|
14509
|
+
}
|
|
14510
|
+
}
|
|
14511
|
+
}
|
|
14512
|
+
/**
|
|
14513
|
+
* Resume LangGraph execution from the last checkpoint.
|
|
14514
|
+
*
|
|
14515
|
+
* Streams with `null` input — this tells LangGraph to continue from
|
|
14516
|
+
* wherever it left off using the checkpointed state for this thread.
|
|
14517
|
+
* All output chunks are buffered via {@link addChunk}.
|
|
14518
|
+
*/
|
|
14519
|
+
async resumeGraphFromCheckpoint(signal) {
|
|
14520
|
+
const runnable_agent = await getAgentClientAsync(this.tenant_id, this.assistant_id);
|
|
14521
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(this.tenant_id, this.assistant_id);
|
|
14522
|
+
if (!runnable_agent) {
|
|
14523
|
+
throw new Error(`Agent ${this.assistant_id} not found`);
|
|
14524
|
+
}
|
|
14525
|
+
const runConfig = {
|
|
14526
|
+
thread_id: this.thread_id,
|
|
14527
|
+
"x-tenant-id": this.tenant_id,
|
|
14528
|
+
"x-workspace-id": this.workspace_id,
|
|
14529
|
+
"x-project-id": this.project_id,
|
|
14530
|
+
"x-thread-id": this.thread_id,
|
|
14531
|
+
"x-assistant-id": this.assistant_id,
|
|
14532
|
+
...agentLattice?.config?.runConfig || {},
|
|
14533
|
+
tenantId: this.tenant_id,
|
|
14534
|
+
workspaceId: this.workspace_id,
|
|
14535
|
+
projectId: this.project_id,
|
|
14536
|
+
...this.custom_run_config || {},
|
|
14537
|
+
assistant_id: this.assistant_id
|
|
14538
|
+
};
|
|
14539
|
+
const agentStream = await runnable_agent.stream(
|
|
14540
|
+
null,
|
|
14541
|
+
{
|
|
14542
|
+
context: {
|
|
14543
|
+
runConfig
|
|
14544
|
+
},
|
|
14545
|
+
configurable: {
|
|
14546
|
+
...runConfig,
|
|
14547
|
+
runConfig
|
|
14548
|
+
},
|
|
14549
|
+
streamMode: ["updates", "messages"],
|
|
14550
|
+
subgraphs: false,
|
|
14551
|
+
recursionLimit: 200,
|
|
14552
|
+
signal
|
|
14553
|
+
}
|
|
14554
|
+
);
|
|
14555
|
+
await this.consumeAgentStream(agentStream, signal);
|
|
14556
|
+
}
|
|
14525
14557
|
getQueueStore() {
|
|
14526
14558
|
if (!this.queueStore) {
|
|
14527
14559
|
try {
|
|
@@ -14600,7 +14632,7 @@ var Agent = class {
|
|
|
14600
14632
|
*/
|
|
14601
14633
|
async addMessage(queueMessage, mode) {
|
|
14602
14634
|
const useMode = mode ?? this.queueMode.mode;
|
|
14603
|
-
const messageId = queueMessage.input.id || (0,
|
|
14635
|
+
const messageId = queueMessage.input.id || (0, import_uuid2.v4)();
|
|
14604
14636
|
const messages = queueMessage.input.messages;
|
|
14605
14637
|
const legacyMessage = queueMessage.input.message;
|
|
14606
14638
|
if (!messages && !legacyMessage) {
|
|
@@ -14651,6 +14683,8 @@ var Agent = class {
|
|
|
14651
14683
|
threadId: this.thread_id,
|
|
14652
14684
|
tenantId: this.tenant_id,
|
|
14653
14685
|
assistantId: this.assistant_id,
|
|
14686
|
+
workspaceId: this.workspace_id,
|
|
14687
|
+
projectId: this.project_id,
|
|
14654
14688
|
content,
|
|
14655
14689
|
type: pendingType,
|
|
14656
14690
|
command: queueMessage.command,
|
|
@@ -14667,6 +14701,8 @@ var Agent = class {
|
|
|
14667
14701
|
threadId: this.thread_id,
|
|
14668
14702
|
tenantId: this.tenant_id,
|
|
14669
14703
|
assistantId: this.assistant_id,
|
|
14704
|
+
workspaceId: this.workspace_id,
|
|
14705
|
+
projectId: this.project_id,
|
|
14670
14706
|
content,
|
|
14671
14707
|
type: pendingType,
|
|
14672
14708
|
command: queueMessage.command,
|
|
@@ -14740,6 +14776,8 @@ var Agent = class {
|
|
|
14740
14776
|
threadId: thread.threadId,
|
|
14741
14777
|
tenantId: thread.tenantId,
|
|
14742
14778
|
assistantId: thread.assistantId,
|
|
14779
|
+
workspaceId: this.workspace_id,
|
|
14780
|
+
projectId: this.project_id,
|
|
14743
14781
|
content: reminderContent,
|
|
14744
14782
|
type: "system"
|
|
14745
14783
|
});
|
|
@@ -14811,9 +14849,14 @@ var Agent = class {
|
|
|
14811
14849
|
/**
|
|
14812
14850
|
* Resume processing after a server restart.
|
|
14813
14851
|
*
|
|
14814
|
-
*
|
|
14815
|
-
*
|
|
14816
|
-
*
|
|
14852
|
+
* If the graph was mid-execution (BUSY) it resumes from the LangGraph
|
|
14853
|
+
* checkpoint without re-injecting the message — the message has already
|
|
14854
|
+
* been consumed and is in the graph state. Processing messages are removed
|
|
14855
|
+
* rather than replayed.
|
|
14856
|
+
*
|
|
14857
|
+
* Skips threads that are in `INTERRUPTED` state (the interruption was
|
|
14858
|
+
* intentional). IDLE threads simply clean up and restart the queue
|
|
14859
|
+
* processor for any remaining pending messages.
|
|
14817
14860
|
*
|
|
14818
14861
|
* Called during gateway startup to recover threads that were mid-execution
|
|
14819
14862
|
* when the server went down.
|
|
@@ -14831,9 +14874,32 @@ var Agent = class {
|
|
|
14831
14874
|
return;
|
|
14832
14875
|
}
|
|
14833
14876
|
const store = this.getQueueStore();
|
|
14834
|
-
|
|
14835
|
-
|
|
14836
|
-
|
|
14877
|
+
if (runStatus === "busy" /* BUSY */) {
|
|
14878
|
+
this.abortController = new AbortController();
|
|
14879
|
+
try {
|
|
14880
|
+
await this.resumeGraphFromCheckpoint(this.abortController.signal);
|
|
14881
|
+
const processingMessages = await store.getProcessingMessages(this.thread_id);
|
|
14882
|
+
for (const msg of processingMessages) {
|
|
14883
|
+
await store.removeMessage(msg.id);
|
|
14884
|
+
}
|
|
14885
|
+
if (processingMessages.length > 0) {
|
|
14886
|
+
console.log(`[Agent] Removed ${processingMessages.length} processing messages for thread ${this.thread_id}`);
|
|
14887
|
+
}
|
|
14888
|
+
} catch (error) {
|
|
14889
|
+
console.error(`[Agent] Failed to resume graph for thread ${this.thread_id}:`, error);
|
|
14890
|
+
await this.chunkBuffer.abortThread(this.thread_id);
|
|
14891
|
+
throw error;
|
|
14892
|
+
} finally {
|
|
14893
|
+
this.abortController = null;
|
|
14894
|
+
}
|
|
14895
|
+
} else {
|
|
14896
|
+
const processingMessages = await store.getProcessingMessages(this.thread_id);
|
|
14897
|
+
for (const msg of processingMessages) {
|
|
14898
|
+
await store.removeMessage(msg.id);
|
|
14899
|
+
}
|
|
14900
|
+
if (processingMessages.length > 0) {
|
|
14901
|
+
console.log(`[Agent] Removed ${processingMessages.length} processing messages for thread ${this.thread_id}`);
|
|
14902
|
+
}
|
|
14837
14903
|
}
|
|
14838
14904
|
await this.startQueueProcessorIfNeeded();
|
|
14839
14905
|
}
|
|
@@ -15024,7 +15090,7 @@ var AgentInstanceManager = class _AgentInstanceManager {
|
|
|
15024
15090
|
console.log(`[AgentInstanceManager] Found ${threadsWithPending.length} threads with pending messages, restoring...`);
|
|
15025
15091
|
for (const threadInfo of threadsWithPending) {
|
|
15026
15092
|
try {
|
|
15027
|
-
await this.restoreThread(threadInfo
|
|
15093
|
+
await this.restoreThread(threadInfo);
|
|
15028
15094
|
stats.restored++;
|
|
15029
15095
|
} catch (error) {
|
|
15030
15096
|
console.error(`[AgentInstanceManager] Failed to restore thread ${threadInfo.threadId}:`, error);
|
|
@@ -15042,16 +15108,14 @@ var AgentInstanceManager = class _AgentInstanceManager {
|
|
|
15042
15108
|
* Restore a single thread
|
|
15043
15109
|
* Delegates actual recovery logic to Agent.resumeTask()
|
|
15044
15110
|
*/
|
|
15045
|
-
async restoreThread(threadInfo
|
|
15046
|
-
const { tenantId, assistantId, threadId } = threadInfo;
|
|
15111
|
+
async restoreThread(threadInfo) {
|
|
15112
|
+
const { tenantId, assistantId, threadId, workspaceId, projectId } = threadInfo;
|
|
15047
15113
|
const threadParams = {
|
|
15048
15114
|
tenant_id: tenantId,
|
|
15049
15115
|
assistant_id: assistantId,
|
|
15050
15116
|
thread_id: threadId,
|
|
15051
|
-
workspace_id:
|
|
15052
|
-
|
|
15053
|
-
project_id: "default"
|
|
15054
|
-
// TODO: Get from thread store
|
|
15117
|
+
workspace_id: workspaceId,
|
|
15118
|
+
project_id: projectId
|
|
15055
15119
|
};
|
|
15056
15120
|
const agent = this.getAgent(threadParams);
|
|
15057
15121
|
await agent.resumeTask();
|
|
@@ -15142,7 +15206,7 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
15142
15206
|
async (input, config) => {
|
|
15143
15207
|
const runConfig = getRunConfig(config);
|
|
15144
15208
|
const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
|
|
15145
|
-
const taskId = (0,
|
|
15209
|
+
const taskId = (0, import_uuid3.v4)();
|
|
15146
15210
|
const executeAt = input.executeAt;
|
|
15147
15211
|
const success = await scheduleLattice.client.scheduleOnce(
|
|
15148
15212
|
taskId,
|
|
@@ -15177,7 +15241,7 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
15177
15241
|
async (input, config) => {
|
|
15178
15242
|
const runConfig = getRunConfig(config);
|
|
15179
15243
|
const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
|
|
15180
|
-
const taskId = (0,
|
|
15244
|
+
const taskId = (0, import_uuid3.v4)();
|
|
15181
15245
|
const executeAt = Date.now() + input.delayMs;
|
|
15182
15246
|
const success = await scheduleLattice.client.scheduleOnce(
|
|
15183
15247
|
taskId,
|
|
@@ -15212,7 +15276,7 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
15212
15276
|
async (input, config) => {
|
|
15213
15277
|
const runConfig = getRunConfig(config);
|
|
15214
15278
|
const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
|
|
15215
|
-
const taskId = (0,
|
|
15279
|
+
const taskId = (0, import_uuid3.v4)();
|
|
15216
15280
|
const success = await scheduleLattice.client.scheduleCron(
|
|
15217
15281
|
taskId,
|
|
15218
15282
|
AGENT_ADD_MESSAGE_TASK_TYPE,
|
|
@@ -15300,6 +15364,138 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
15300
15364
|
});
|
|
15301
15365
|
}
|
|
15302
15366
|
|
|
15367
|
+
// src/middlewares/taskMiddleware.ts
|
|
15368
|
+
var import_langchain56 = require("langchain");
|
|
15369
|
+
var import_zod51 = require("zod");
|
|
15370
|
+
function getRunConfig2(config) {
|
|
15371
|
+
const c = config;
|
|
15372
|
+
return c?.configurable?.runConfig ?? {};
|
|
15373
|
+
}
|
|
15374
|
+
function getTaskStore() {
|
|
15375
|
+
return getStoreLattice("default", "task").store;
|
|
15376
|
+
}
|
|
15377
|
+
var manageTaskSchema = import_zod51.z.object({
|
|
15378
|
+
action: import_zod51.z.enum(["create", "list", "update", "delete", "complete"]).describe("\u64CD\u4F5C\u7C7B\u578B"),
|
|
15379
|
+
id: import_zod51.z.string().optional().describe("\u4EFB\u52A1 ID (update/delete/complete \u5FC5\u586B)"),
|
|
15380
|
+
title: import_zod51.z.string().optional().describe("\u4EFB\u52A1\u6807\u9898 (create \u5FC5\u586B)"),
|
|
15381
|
+
description: import_zod51.z.string().optional().describe("\u4EFB\u52A1\u63CF\u8FF0"),
|
|
15382
|
+
priority: import_zod51.z.enum(["low", "medium", "high"]).optional().describe("\u4F18\u5148\u7EA7"),
|
|
15383
|
+
status: import_zod51.z.enum(["pending", "in_progress", "completed", "cancelled"]).optional().describe("\u72B6\u6001"),
|
|
15384
|
+
dueDate: import_zod51.z.string().optional().describe("\u622A\u6B62\u65E5\u671F (ISO 8601)"),
|
|
15385
|
+
metadata: import_zod51.z.record(import_zod51.z.unknown()).optional().describe("\u7ED3\u6784\u5316\u5143\u6570\u636E (projectId, module \u7B49)"),
|
|
15386
|
+
parentId: import_zod51.z.string().optional().describe("\u7236\u4EFB\u52A1 ID (\u5B50\u4EFB\u52A1\u5173\u8054)"),
|
|
15387
|
+
sourceId: import_zod51.z.string().optional().describe("\u6765\u6E90\u4F1A\u8BDD/thread ID"),
|
|
15388
|
+
context: import_zod51.z.record(import_zod51.z.unknown()).optional().describe("\u9644\u52A0\u4E0A\u4E0B\u6587"),
|
|
15389
|
+
ownerType: import_zod51.z.enum(["user", "agent"]).optional().describe("\u6240\u6709\u8005\u7C7B\u578B\uFF0C\u4E0D\u4F20\u9ED8\u8BA4\u4E3A user"),
|
|
15390
|
+
ownerId: import_zod51.z.string().optional().describe("\u6240\u6709\u8005 ID\uFF0C\u4E0D\u4F20\u81EA\u52A8\u53D6\u5F53\u524D\u7528\u6237/Agent")
|
|
15391
|
+
});
|
|
15392
|
+
function createTaskMiddleware() {
|
|
15393
|
+
return (0, import_langchain56.createMiddleware)({
|
|
15394
|
+
name: "TaskMiddleware",
|
|
15395
|
+
contextSchema,
|
|
15396
|
+
wrapModelCall: async (request, handler) => {
|
|
15397
|
+
const taskPrompt = `## \u4EFB\u52A1\u7BA1\u7406\u80FD\u529B
|
|
15398
|
+
\u4F60\u53EF\u4EE5\u901A\u8FC7 manage_task \u5DE5\u5177\u7BA1\u7406\u6301\u4E45\u5316\u4EFB\u52A1\u3002ownerType \u548C ownerId \u7684\u9ED8\u8BA4\u884C\u4E3A\uFF1A
|
|
15399
|
+
- \u4E0D\u4F20\u53C2\u6570: \u9ED8\u8BA4\u4E3A\u5F53\u524D\u7528\u6237\u521B\u5EFA\u4EFB\u52A1 (ownerType="user", ownerId \u81EA\u52A8\u53D6\u5F53\u524D\u7528\u6237)
|
|
15400
|
+
- ownerType="agent": \u4E3A\u81EA\u5DF1\u521B\u5EFA\u6267\u884C\u5B50\u4EFB\u52A1 (ownerId \u81EA\u52A8\u53D6\u5F53\u524D Agent)
|
|
15401
|
+
- \u663E\u5F0F\u4F20 ownerId: \u4E3A\u6307\u5B9A agent/user \u521B\u5EFA\u4EFB\u52A1\uFF08\u62D3\u6251\u573A\u666F\uFF09`;
|
|
15402
|
+
return handler({
|
|
15403
|
+
...request,
|
|
15404
|
+
systemPrompt: taskPrompt + "\n\n" + (request.systemPrompt ?? "")
|
|
15405
|
+
});
|
|
15406
|
+
},
|
|
15407
|
+
tools: [
|
|
15408
|
+
(0, import_langchain56.tool)(
|
|
15409
|
+
async (input, config) => {
|
|
15410
|
+
const rc = getRunConfig2(config);
|
|
15411
|
+
const tenantId = rc.tenantId || "default";
|
|
15412
|
+
const ownerId = input.ownerId || (input.ownerType === "agent" ? rc.assistant_id : null) || rc.user_id;
|
|
15413
|
+
const store = getTaskStore();
|
|
15414
|
+
switch (input.action) {
|
|
15415
|
+
case "create": {
|
|
15416
|
+
if (!input.title) {
|
|
15417
|
+
return JSON.stringify({ success: false, error: "create requires title" });
|
|
15418
|
+
}
|
|
15419
|
+
const task = await store.create({
|
|
15420
|
+
tenantId,
|
|
15421
|
+
ownerType: input.ownerType || "user",
|
|
15422
|
+
ownerId,
|
|
15423
|
+
title: input.title,
|
|
15424
|
+
description: input.description,
|
|
15425
|
+
priority: input.priority || "medium",
|
|
15426
|
+
status: input.status || "pending",
|
|
15427
|
+
dueDate: input.dueDate,
|
|
15428
|
+
metadata: input.metadata,
|
|
15429
|
+
parentId: input.parentId,
|
|
15430
|
+
sourceId: input.sourceId,
|
|
15431
|
+
context: input.context
|
|
15432
|
+
});
|
|
15433
|
+
return JSON.stringify({ success: true, data: task });
|
|
15434
|
+
}
|
|
15435
|
+
case "list": {
|
|
15436
|
+
const tasks = await store.list({
|
|
15437
|
+
tenantId,
|
|
15438
|
+
ownerType: input.ownerType,
|
|
15439
|
+
ownerId: input.ownerId,
|
|
15440
|
+
status: input.status,
|
|
15441
|
+
priority: input.priority
|
|
15442
|
+
});
|
|
15443
|
+
return JSON.stringify({ success: true, data: tasks, count: tasks.length });
|
|
15444
|
+
}
|
|
15445
|
+
case "update": {
|
|
15446
|
+
if (!input.id) {
|
|
15447
|
+
return JSON.stringify({ success: false, error: "update requires id" });
|
|
15448
|
+
}
|
|
15449
|
+
const { action, ...updates } = input;
|
|
15450
|
+
const updated = await store.update(tenantId, input.id, updates);
|
|
15451
|
+
if (!updated) {
|
|
15452
|
+
return JSON.stringify({ success: false, error: "Task not found" });
|
|
15453
|
+
}
|
|
15454
|
+
return JSON.stringify({ success: true, data: updated });
|
|
15455
|
+
}
|
|
15456
|
+
case "delete": {
|
|
15457
|
+
if (!input.id) {
|
|
15458
|
+
return JSON.stringify({ success: false, error: "delete requires id" });
|
|
15459
|
+
}
|
|
15460
|
+
const deleted = await store.delete(tenantId, input.id);
|
|
15461
|
+
return JSON.stringify({ success: deleted, message: deleted ? "Task deleted" : "Task not found" });
|
|
15462
|
+
}
|
|
15463
|
+
case "complete": {
|
|
15464
|
+
if (!input.id) {
|
|
15465
|
+
return JSON.stringify({ success: false, error: "complete requires id" });
|
|
15466
|
+
}
|
|
15467
|
+
const updated = await store.update(tenantId, input.id, { status: "completed" });
|
|
15468
|
+
if (!updated) {
|
|
15469
|
+
return JSON.stringify({ success: false, error: "Task not found" });
|
|
15470
|
+
}
|
|
15471
|
+
return JSON.stringify({ success: true, data: updated });
|
|
15472
|
+
}
|
|
15473
|
+
default:
|
|
15474
|
+
return JSON.stringify({ success: false, error: `Unknown action: ${input.action}` });
|
|
15475
|
+
}
|
|
15476
|
+
},
|
|
15477
|
+
{
|
|
15478
|
+
name: "manage_task",
|
|
15479
|
+
description: `\u7BA1\u7406\u6301\u4E45\u5316\u4EFB\u52A1\u7CFB\u7EDF\u3002CRUD \u64CD\u4F5C\u7528\u6237\u548C Agent \u7684\u4EFB\u52A1\u3002
|
|
15480
|
+
|
|
15481
|
+
## ownerType \u548C ownerId \u7684\u9ED8\u8BA4\u903B\u8F91
|
|
15482
|
+
- \u4E0D\u4F20 ownerType \u548C ownerId: \u7CFB\u7EDF\u81EA\u52A8\u4E3A\u5F53\u524D\u7528\u6237\u521B\u5EFA\u4EFB\u52A1 (ownerType="user", ownerId \u53D6\u81EA\u5F53\u524D\u767B\u5F55\u7528\u6237)
|
|
15483
|
+
- \u4F20 ownerType="agent" \u4E0D\u4F20 ownerId: \u7CFB\u7EDF\u81EA\u52A8\u4E3A\u5F53\u524D Agent \u521B\u5EFA\u5B50\u4EFB\u52A1
|
|
15484
|
+
- \u663E\u5F0F\u4F20 ownerId: \u7CFB\u7EDF\u4F7F\u7528\u4F60\u6307\u5B9A\u7684 ID\uFF0C\u53EF\u8DE8 Agent \u6D3E\u53D1\u4EFB\u52A1\uFF08\u62D3\u6251\u573A\u666F\uFF09
|
|
15485
|
+
|
|
15486
|
+
## Actions
|
|
15487
|
+
- create: \u521B\u5EFA\u4EFB\u52A1 (title \u5FC5\u586B, priority/description/dueDate/metadata/parentId/context \u53EF\u9009)
|
|
15488
|
+
- list: \u5217\u51FA\u4EFB\u52A1\uFF0C\u53EF\u6309 ownerType/status/priority \u8FC7\u6EE4
|
|
15489
|
+
- update: \u66F4\u65B0\u4EFB\u52A1 (id \u5FC5\u586B\uFF0C\u53EA\u4F20\u8981\u6539\u7684\u5B57\u6BB5)
|
|
15490
|
+
- delete: \u5220\u9664\u4EFB\u52A1 (id \u5FC5\u586B)
|
|
15491
|
+
- complete: \u5FEB\u901F\u6807\u8BB0\u5B8C\u6210 (id \u5FC5\u586B)`,
|
|
15492
|
+
schema: manageTaskSchema
|
|
15493
|
+
}
|
|
15494
|
+
)
|
|
15495
|
+
]
|
|
15496
|
+
});
|
|
15497
|
+
}
|
|
15498
|
+
|
|
15303
15499
|
// src/agent_lattice/builders/CustomMiddlewareRegistry.ts
|
|
15304
15500
|
var CustomMiddlewareRegistry = class {
|
|
15305
15501
|
/**
|
|
@@ -15435,6 +15631,9 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsI
|
|
|
15435
15631
|
case "scheduler":
|
|
15436
15632
|
middlewares.push(createSchedulerMiddleware(config.config));
|
|
15437
15633
|
break;
|
|
15634
|
+
case "task":
|
|
15635
|
+
middlewares.push(createTaskMiddleware());
|
|
15636
|
+
break;
|
|
15438
15637
|
case "custom":
|
|
15439
15638
|
{
|
|
15440
15639
|
const customConfig = config.config;
|
|
@@ -15467,10 +15666,12 @@ var SandboxFilesystem = class {
|
|
|
15467
15666
|
}
|
|
15468
15667
|
async lsInfo(dirPath) {
|
|
15469
15668
|
try {
|
|
15669
|
+
console.log(`[SandboxFilesystem.lsInfo] calling sandbox.file.listPath(${dirPath})`);
|
|
15470
15670
|
const result = await this.sandbox.file.listPath(dirPath, { recursive: false });
|
|
15671
|
+
console.log(`[SandboxFilesystem.lsInfo] got ${result.files.length} entries`);
|
|
15471
15672
|
return result.files;
|
|
15472
15673
|
} catch (e) {
|
|
15473
|
-
console.error(`
|
|
15674
|
+
console.error(`[SandboxFilesystem.lsInfo] error listing ${dirPath}:`, e);
|
|
15474
15675
|
return [];
|
|
15475
15676
|
}
|
|
15476
15677
|
}
|
|
@@ -15642,14 +15843,14 @@ var ReActAgentGraphBuilder = class {
|
|
|
15642
15843
|
*/
|
|
15643
15844
|
async build(agentLattice, params) {
|
|
15644
15845
|
const tools = params.tools.map((t) => {
|
|
15645
|
-
const
|
|
15646
|
-
return
|
|
15647
|
-
}).filter((
|
|
15846
|
+
const tool52 = getToolClient(t.key);
|
|
15847
|
+
return tool52;
|
|
15848
|
+
}).filter((tool52) => tool52 !== void 0);
|
|
15648
15849
|
const stateSchema2 = createReactAgentSchema(params.stateSchema);
|
|
15649
15850
|
const middlewareConfigs = params.middleware || [];
|
|
15650
15851
|
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
15651
15852
|
const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend);
|
|
15652
|
-
return (0,
|
|
15853
|
+
return (0, import_langchain57.createAgent)({
|
|
15653
15854
|
model: params.model,
|
|
15654
15855
|
tools,
|
|
15655
15856
|
systemPrompt: params.prompt,
|
|
@@ -15663,11 +15864,11 @@ var ReActAgentGraphBuilder = class {
|
|
|
15663
15864
|
};
|
|
15664
15865
|
|
|
15665
15866
|
// src/deep_agent_new/agent.ts
|
|
15666
|
-
var
|
|
15867
|
+
var import_langchain61 = require("langchain");
|
|
15667
15868
|
|
|
15668
15869
|
// src/deep_agent_new/middleware/subagents.ts
|
|
15669
15870
|
var import_v32 = require("zod/v3");
|
|
15670
|
-
var
|
|
15871
|
+
var import_langchain58 = require("langchain");
|
|
15671
15872
|
var import_langgraph8 = require("@langchain/langgraph");
|
|
15672
15873
|
var import_messages2 = require("@langchain/core/messages");
|
|
15673
15874
|
|
|
@@ -15991,7 +16192,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
|
|
|
15991
16192
|
update: {
|
|
15992
16193
|
...stateUpdate,
|
|
15993
16194
|
messages: [
|
|
15994
|
-
new
|
|
16195
|
+
new import_langchain58.ToolMessage({
|
|
15995
16196
|
content: lastMessage?.content || "Task Failed to complete",
|
|
15996
16197
|
tool_call_id: toolCallId,
|
|
15997
16198
|
name: "task"
|
|
@@ -16016,10 +16217,10 @@ function getSubagents(options) {
|
|
|
16016
16217
|
const generalPurposeMiddleware = [...defaultSubagentMiddleware];
|
|
16017
16218
|
if (defaultInterruptOn) {
|
|
16018
16219
|
generalPurposeMiddleware.push(
|
|
16019
|
-
(0,
|
|
16220
|
+
(0, import_langchain58.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
|
|
16020
16221
|
);
|
|
16021
16222
|
}
|
|
16022
|
-
const generalPurposeSubagent = (0,
|
|
16223
|
+
const generalPurposeSubagent = (0, import_langchain58.createAgent)({
|
|
16023
16224
|
model: defaultModel,
|
|
16024
16225
|
systemPrompt: DEFAULT_SUBAGENT_PROMPT,
|
|
16025
16226
|
tools: defaultTools,
|
|
@@ -16042,8 +16243,8 @@ function getSubagents(options) {
|
|
|
16042
16243
|
const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware];
|
|
16043
16244
|
const interruptOn = agentParams.interruptOn || defaultInterruptOn;
|
|
16044
16245
|
if (interruptOn)
|
|
16045
|
-
middleware.push((0,
|
|
16046
|
-
agents[agentParams.key] = (0,
|
|
16246
|
+
middleware.push((0, import_langchain58.humanInTheLoopMiddleware)({ interruptOn }));
|
|
16247
|
+
agents[agentParams.key] = (0, import_langchain58.createAgent)({
|
|
16047
16248
|
model: agentParams.model ?? defaultModel,
|
|
16048
16249
|
systemPrompt: agentParams.systemPrompt,
|
|
16049
16250
|
tools: agentParams.tools ?? defaultTools,
|
|
@@ -16093,7 +16294,7 @@ function createTaskTool(options) {
|
|
|
16093
16294
|
generalPurposeAgent
|
|
16094
16295
|
});
|
|
16095
16296
|
const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
|
|
16096
|
-
return (0,
|
|
16297
|
+
return (0, import_langchain58.tool)(
|
|
16097
16298
|
async (input, config) => {
|
|
16098
16299
|
const { description, subagent_type, async } = input;
|
|
16099
16300
|
let assistant_id = subagent_type;
|
|
@@ -16127,12 +16328,16 @@ function createTaskTool(options) {
|
|
|
16127
16328
|
const subagent_thread_id = config.configurable?.thread_id + "____" + assistant_id + "_" + config.toolCall.id;
|
|
16128
16329
|
if (async) {
|
|
16129
16330
|
const tenantId = config.configurable?.runConfig?.tenantId;
|
|
16331
|
+
const workspaceId = config.configurable?.runConfig?.workspaceId;
|
|
16332
|
+
const projectId = config.configurable?.runConfig?.projectId;
|
|
16130
16333
|
const mainAssistantId = config.configurable?.runConfig?.assistant_id;
|
|
16131
16334
|
const mainThreadId = config.configurable?.runConfig?.thread_id;
|
|
16132
16335
|
const mainRuntimeAgent = agentInstanceManager.getAgent({
|
|
16133
16336
|
assistant_id: mainAssistantId,
|
|
16134
16337
|
thread_id: mainThreadId,
|
|
16135
|
-
tenant_id: tenantId
|
|
16338
|
+
tenant_id: tenantId,
|
|
16339
|
+
workspace_id: workspaceId,
|
|
16340
|
+
project_id: projectId
|
|
16136
16341
|
});
|
|
16137
16342
|
if (mainRuntimeAgent) {
|
|
16138
16343
|
mainRuntimeAgent.addAsyncTask({
|
|
@@ -16165,7 +16370,7 @@ function createTaskTool(options) {
|
|
|
16165
16370
|
return new import_langgraph8.Command({
|
|
16166
16371
|
update: {
|
|
16167
16372
|
messages: [
|
|
16168
|
-
new
|
|
16373
|
+
new import_langchain58.ToolMessage({
|
|
16169
16374
|
content: `Async task started: ${subagent_thread_id}
|
|
16170
16375
|
${description}
|
|
16171
16376
|
The result will be delivered as a notification when complete. Do not poll.`,
|
|
@@ -16198,7 +16403,7 @@ The result will be delivered as a notification when complete. Do not poll.`,
|
|
|
16198
16403
|
return new import_langgraph8.Command({
|
|
16199
16404
|
update: {
|
|
16200
16405
|
messages: [
|
|
16201
|
-
new
|
|
16406
|
+
new import_langchain58.ToolMessage({
|
|
16202
16407
|
content: error instanceof Error ? error.message : "Task Failed to complete",
|
|
16203
16408
|
tool_call_id: config.toolCall.id,
|
|
16204
16409
|
name: "task"
|
|
@@ -16238,7 +16443,7 @@ function getMainAgentFromConfig(config) {
|
|
|
16238
16443
|
});
|
|
16239
16444
|
}
|
|
16240
16445
|
function createCheckAsyncTaskTool() {
|
|
16241
|
-
return (0,
|
|
16446
|
+
return (0, import_langchain58.tool)(
|
|
16242
16447
|
async (input, config) => {
|
|
16243
16448
|
const { task_id } = input;
|
|
16244
16449
|
const mainAgent = getMainAgentFromConfig(config);
|
|
@@ -16305,7 +16510,7 @@ Description: ${cached.description}`;
|
|
|
16305
16510
|
);
|
|
16306
16511
|
}
|
|
16307
16512
|
function createListAsyncTasksTool() {
|
|
16308
|
-
return (0,
|
|
16513
|
+
return (0, import_langchain58.tool)(
|
|
16309
16514
|
async (_input, config) => {
|
|
16310
16515
|
const mainAgent = getMainAgentFromConfig(config);
|
|
16311
16516
|
if (!mainAgent) {
|
|
@@ -16356,7 +16561,7 @@ function createListAsyncTasksTool() {
|
|
|
16356
16561
|
);
|
|
16357
16562
|
}
|
|
16358
16563
|
function createCancelAsyncTaskTool() {
|
|
16359
|
-
return (0,
|
|
16564
|
+
return (0, import_langchain58.tool)(
|
|
16360
16565
|
async (input, config) => {
|
|
16361
16566
|
const { task_id } = input;
|
|
16362
16567
|
const mainAgent = getMainAgentFromConfig(config);
|
|
@@ -16432,7 +16637,7 @@ function createSubAgentMiddleware(options) {
|
|
|
16432
16637
|
);
|
|
16433
16638
|
}
|
|
16434
16639
|
const effectiveSystemPrompt = allowAsync ? systemPrompt + getAsyncPromptText() : systemPrompt;
|
|
16435
|
-
return (0,
|
|
16640
|
+
return (0, import_langchain58.createMiddleware)({
|
|
16436
16641
|
name: "subAgentMiddleware",
|
|
16437
16642
|
tools: allTools,
|
|
16438
16643
|
wrapModelCall: async (request, handler) => {
|
|
@@ -16452,11 +16657,9 @@ ${effectiveSystemPrompt}` : effectiveSystemPrompt;
|
|
|
16452
16657
|
}
|
|
16453
16658
|
|
|
16454
16659
|
// src/deep_agent_new/middleware/patch_tool_calls.ts
|
|
16455
|
-
var
|
|
16456
|
-
var import_messages3 = require("@langchain/core/messages");
|
|
16457
|
-
var import_langgraph9 = require("@langchain/langgraph");
|
|
16660
|
+
var import_langchain59 = require("langchain");
|
|
16458
16661
|
function createPatchToolCallsMiddleware() {
|
|
16459
|
-
return (0,
|
|
16662
|
+
return (0, import_langchain59.createMiddleware)({
|
|
16460
16663
|
name: "patchToolCallsMiddleware",
|
|
16461
16664
|
beforeAgent: async (state) => {
|
|
16462
16665
|
const messages = state.messages;
|
|
@@ -16467,15 +16670,15 @@ function createPatchToolCallsMiddleware() {
|
|
|
16467
16670
|
for (let i = 0; i < messages.length; i++) {
|
|
16468
16671
|
const msg = messages[i];
|
|
16469
16672
|
patchedMessages.push(msg);
|
|
16470
|
-
if (
|
|
16673
|
+
if (import_langchain59.AIMessage.isInstance(msg) && msg.tool_calls != null) {
|
|
16471
16674
|
for (const toolCall of msg.tool_calls) {
|
|
16472
16675
|
const correspondingToolMsg = messages.slice(i).find(
|
|
16473
|
-
(m) =>
|
|
16676
|
+
(m) => import_langchain59.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
|
|
16474
16677
|
);
|
|
16475
16678
|
if (!correspondingToolMsg) {
|
|
16476
16679
|
const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
|
|
16477
16680
|
patchedMessages.push(
|
|
16478
|
-
new
|
|
16681
|
+
new import_langchain59.ToolMessage({
|
|
16479
16682
|
content: toolMsg,
|
|
16480
16683
|
name: toolCall.name,
|
|
16481
16684
|
tool_call_id: toolCall.id
|
|
@@ -16485,11 +16688,12 @@ function createPatchToolCallsMiddleware() {
|
|
|
16485
16688
|
}
|
|
16486
16689
|
}
|
|
16487
16690
|
}
|
|
16691
|
+
if (patchedMessages.length === messages.length) {
|
|
16692
|
+
return;
|
|
16693
|
+
}
|
|
16488
16694
|
return {
|
|
16489
|
-
messages:
|
|
16490
|
-
|
|
16491
|
-
...patchedMessages
|
|
16492
|
-
]
|
|
16695
|
+
messages: patchedMessages.slice(messages.length)
|
|
16696
|
+
// only the new ToolMessage patches
|
|
16493
16697
|
};
|
|
16494
16698
|
}
|
|
16495
16699
|
});
|
|
@@ -17601,9 +17805,9 @@ var MemoryBackend = class {
|
|
|
17601
17805
|
};
|
|
17602
17806
|
|
|
17603
17807
|
// src/deep_agent_new/middleware/todos.ts
|
|
17604
|
-
var
|
|
17605
|
-
var
|
|
17606
|
-
var
|
|
17808
|
+
var import_langgraph9 = require("@langchain/langgraph");
|
|
17809
|
+
var import_zod52 = require("zod");
|
|
17810
|
+
var import_langchain60 = require("langchain");
|
|
17607
17811
|
var WRITE_TODOS_DESCRIPTION = `Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
|
17608
17812
|
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
17609
17813
|
Only use this tool if you think it will be helpful in staying organized. If the user's request is trivial and takes less than 3 steps, it is better to NOT use this tool and just do the taks directly.
|
|
@@ -17830,20 +18034,20 @@ Writing todos takes time and tokens, use it when it is helpful for managing comp
|
|
|
17830
18034
|
## Important To-Do List Usage Notes to Remember
|
|
17831
18035
|
- The \`write_todos\` tool should never be called multiple times in parallel.
|
|
17832
18036
|
- Don't be afraid to revise the To-Do list as you go. New information may reveal new tasks that need to be done, or old tasks that are irrelevant.`;
|
|
17833
|
-
var TodoStatus =
|
|
17834
|
-
var TodoSchema =
|
|
17835
|
-
content:
|
|
18037
|
+
var TodoStatus = import_zod52.z.enum(["pending", "in_progress", "completed"]).describe("Status of the todo");
|
|
18038
|
+
var TodoSchema = import_zod52.z.object({
|
|
18039
|
+
content: import_zod52.z.string().describe("Content of the todo item"),
|
|
17836
18040
|
status: TodoStatus
|
|
17837
18041
|
});
|
|
17838
|
-
var stateSchema =
|
|
18042
|
+
var stateSchema = import_zod52.z.object({ todos: import_zod52.z.array(TodoSchema).default([]) });
|
|
17839
18043
|
function todoListMiddleware(options) {
|
|
17840
|
-
const writeTodos = (0,
|
|
18044
|
+
const writeTodos = (0, import_langchain60.tool)(
|
|
17841
18045
|
({ todos }, config) => {
|
|
17842
|
-
return new
|
|
18046
|
+
return new import_langgraph9.Command({
|
|
17843
18047
|
update: {
|
|
17844
18048
|
todos,
|
|
17845
18049
|
messages: [
|
|
17846
|
-
new
|
|
18050
|
+
new import_langchain60.ToolMessage({
|
|
17847
18051
|
content: genUIMarkdown("todo_list", todos),
|
|
17848
18052
|
tool_call_id: config.toolCall?.id
|
|
17849
18053
|
})
|
|
@@ -17854,12 +18058,12 @@ function todoListMiddleware(options) {
|
|
|
17854
18058
|
{
|
|
17855
18059
|
name: "write_todos",
|
|
17856
18060
|
description: options?.toolDescription ?? WRITE_TODOS_DESCRIPTION,
|
|
17857
|
-
schema:
|
|
17858
|
-
todos:
|
|
18061
|
+
schema: import_zod52.z.object({
|
|
18062
|
+
todos: import_zod52.z.array(TodoSchema).describe("List of todo items to update")
|
|
17859
18063
|
})
|
|
17860
18064
|
}
|
|
17861
18065
|
);
|
|
17862
|
-
return (0,
|
|
18066
|
+
return (0, import_langchain60.createMiddleware)({
|
|
17863
18067
|
name: "todoListMiddleware",
|
|
17864
18068
|
stateSchema,
|
|
17865
18069
|
tools: [writeTodos],
|
|
@@ -17911,13 +18115,13 @@ ${BASE_PROMPT}` : BASE_PROMPT;
|
|
|
17911
18115
|
backend: filesystemBackend
|
|
17912
18116
|
}),
|
|
17913
18117
|
// Subagent middleware: Automatic conversation summarization when token limits are approached
|
|
17914
|
-
(0,
|
|
18118
|
+
(0, import_langchain61.summarizationMiddleware)({
|
|
17915
18119
|
model,
|
|
17916
18120
|
trigger: { tokens: 17e4 },
|
|
17917
18121
|
keep: { messages: 6 }
|
|
17918
18122
|
}),
|
|
17919
18123
|
// Subagent middleware: Anthropic prompt caching for improved performance
|
|
17920
|
-
(0,
|
|
18124
|
+
(0, import_langchain61.anthropicPromptCachingMiddleware)({
|
|
17921
18125
|
unsupportedModelBehavior: "ignore"
|
|
17922
18126
|
}),
|
|
17923
18127
|
// Subagent middleware: Patches tool calls for compatibility
|
|
@@ -17929,23 +18133,23 @@ ${BASE_PROMPT}` : BASE_PROMPT;
|
|
|
17929
18133
|
generalPurposeAgent: true
|
|
17930
18134
|
}),
|
|
17931
18135
|
// Automatically summarizes conversation history when token limits are approached
|
|
17932
|
-
(0,
|
|
18136
|
+
(0, import_langchain61.summarizationMiddleware)({
|
|
17933
18137
|
model,
|
|
17934
18138
|
trigger: { tokens: 17e4 },
|
|
17935
18139
|
keep: { messages: 6 }
|
|
17936
18140
|
}),
|
|
17937
18141
|
// Enables Anthropic prompt caching for improved performance and reduced costs
|
|
17938
|
-
(0,
|
|
18142
|
+
(0, import_langchain61.anthropicPromptCachingMiddleware)({
|
|
17939
18143
|
unsupportedModelBehavior: "ignore"
|
|
17940
18144
|
}),
|
|
17941
18145
|
// Patches tool calls to ensure compatibility across different model providers
|
|
17942
18146
|
createPatchToolCallsMiddleware()
|
|
17943
18147
|
];
|
|
17944
18148
|
if (interruptOn) {
|
|
17945
|
-
middleware.push((0,
|
|
18149
|
+
middleware.push((0, import_langchain61.humanInTheLoopMiddleware)({ interruptOn }));
|
|
17946
18150
|
}
|
|
17947
18151
|
middleware.push(...customMiddleware);
|
|
17948
|
-
return (0,
|
|
18152
|
+
return (0, import_langchain61.createAgent)({
|
|
17949
18153
|
model,
|
|
17950
18154
|
systemPrompt: finalSystemPrompt,
|
|
17951
18155
|
tools,
|
|
@@ -17972,7 +18176,7 @@ var DeepAgentGraphBuilder = class {
|
|
|
17972
18176
|
const tools = params.tools.map((t) => {
|
|
17973
18177
|
const toolClient = getToolClient(t.key);
|
|
17974
18178
|
return toolClient;
|
|
17975
|
-
}).filter((
|
|
18179
|
+
}).filter((tool52) => tool52 !== void 0);
|
|
17976
18180
|
const subagents = await Promise.all(params.subAgents.map(async (sa) => {
|
|
17977
18181
|
if (sa.client) {
|
|
17978
18182
|
return {
|
|
@@ -18017,7 +18221,7 @@ init_MemoryLatticeManager();
|
|
|
18017
18221
|
|
|
18018
18222
|
// src/agent_team/agent_team.ts
|
|
18019
18223
|
var import_v35 = require("zod/v3");
|
|
18020
|
-
var
|
|
18224
|
+
var import_langchain64 = require("langchain");
|
|
18021
18225
|
|
|
18022
18226
|
// src/agent_team/types.ts
|
|
18023
18227
|
var TaskStatus = /* @__PURE__ */ ((TaskStatus3) => {
|
|
@@ -18453,14 +18657,14 @@ var InMemoryMailboxStore = class {
|
|
|
18453
18657
|
|
|
18454
18658
|
// src/agent_team/middleware/team.ts
|
|
18455
18659
|
var import_v34 = require("zod/v3");
|
|
18456
|
-
var
|
|
18457
|
-
var
|
|
18458
|
-
var
|
|
18660
|
+
var import_langchain63 = require("langchain");
|
|
18661
|
+
var import_langgraph11 = require("@langchain/langgraph");
|
|
18662
|
+
var import_uuid4 = require("uuid");
|
|
18459
18663
|
|
|
18460
18664
|
// src/agent_team/middleware/teammate_tools.ts
|
|
18461
18665
|
var import_v33 = require("zod/v3");
|
|
18462
|
-
var
|
|
18463
|
-
var
|
|
18666
|
+
var import_langchain62 = require("langchain");
|
|
18667
|
+
var import_langgraph10 = require("@langchain/langgraph");
|
|
18464
18668
|
|
|
18465
18669
|
// src/agent_team/middleware/formatMessages.ts
|
|
18466
18670
|
function formatMessagesAsMarkdown(msgs) {
|
|
@@ -18484,7 +18688,7 @@ ${meta}${body}`;
|
|
|
18484
18688
|
// src/agent_team/middleware/teammate_tools.ts
|
|
18485
18689
|
function createTeammateTools(options) {
|
|
18486
18690
|
const { teamId, agentId, taskListStore, mailboxStore } = options;
|
|
18487
|
-
const claimTaskTool = (0,
|
|
18691
|
+
const claimTaskTool = (0, import_langchain62.tool)(
|
|
18488
18692
|
async (input) => {
|
|
18489
18693
|
const task = await taskListStore.claimTaskById(
|
|
18490
18694
|
teamId,
|
|
@@ -18514,7 +18718,7 @@ function createTeammateTools(options) {
|
|
|
18514
18718
|
})
|
|
18515
18719
|
}
|
|
18516
18720
|
);
|
|
18517
|
-
const completeTaskTool = (0,
|
|
18721
|
+
const completeTaskTool = (0, import_langchain62.tool)(
|
|
18518
18722
|
async (input) => {
|
|
18519
18723
|
const task = await taskListStore.completeTask(
|
|
18520
18724
|
teamId,
|
|
@@ -18541,7 +18745,7 @@ function createTeammateTools(options) {
|
|
|
18541
18745
|
})
|
|
18542
18746
|
}
|
|
18543
18747
|
);
|
|
18544
|
-
const failTaskTool = (0,
|
|
18748
|
+
const failTaskTool = (0, import_langchain62.tool)(
|
|
18545
18749
|
async (input) => {
|
|
18546
18750
|
const task = await taskListStore.failTask(
|
|
18547
18751
|
teamId,
|
|
@@ -18568,7 +18772,7 @@ function createTeammateTools(options) {
|
|
|
18568
18772
|
})
|
|
18569
18773
|
}
|
|
18570
18774
|
);
|
|
18571
|
-
const sendMessageTool = (0,
|
|
18775
|
+
const sendMessageTool = (0, import_langchain62.tool)(
|
|
18572
18776
|
async (input) => {
|
|
18573
18777
|
await mailboxStore.sendMessage(
|
|
18574
18778
|
teamId,
|
|
@@ -18606,7 +18810,7 @@ function createTeammateTools(options) {
|
|
|
18606
18810
|
read: msg.read
|
|
18607
18811
|
}));
|
|
18608
18812
|
};
|
|
18609
|
-
const readMessagesTool = (0,
|
|
18813
|
+
const readMessagesTool = (0, import_langchain62.tool)(
|
|
18610
18814
|
async (input, config) => {
|
|
18611
18815
|
const formatAndMarkAsRead = async (msgs2) => {
|
|
18612
18816
|
for (const msg of msgs2) {
|
|
@@ -18618,12 +18822,12 @@ function createTeammateTools(options) {
|
|
|
18618
18822
|
if (msgs.length > 0) {
|
|
18619
18823
|
const formatted2 = await formatAndMarkAsRead(msgs);
|
|
18620
18824
|
const relevantMsgs2 = await getRelevantMessagesForState();
|
|
18621
|
-
const toolMessage2 = new
|
|
18825
|
+
const toolMessage2 = new import_langchain62.ToolMessage({
|
|
18622
18826
|
content: formatted2,
|
|
18623
18827
|
tool_call_id: config.toolCall?.id,
|
|
18624
18828
|
name: "read_messages"
|
|
18625
18829
|
});
|
|
18626
|
-
return new
|
|
18830
|
+
return new import_langgraph10.Command({
|
|
18627
18831
|
update: { team_mailbox: relevantMsgs2, messages: [toolMessage2] }
|
|
18628
18832
|
});
|
|
18629
18833
|
}
|
|
@@ -18643,22 +18847,22 @@ function createTeammateTools(options) {
|
|
|
18643
18847
|
});
|
|
18644
18848
|
const relevantMsgs = await getRelevantMessagesForState();
|
|
18645
18849
|
if (msgs.length === 0) {
|
|
18646
|
-
const toolMessage2 = new
|
|
18850
|
+
const toolMessage2 = new import_langchain62.ToolMessage({
|
|
18647
18851
|
content: "No unread messages.",
|
|
18648
18852
|
tool_call_id: config.toolCall?.id,
|
|
18649
18853
|
name: "read_messages"
|
|
18650
18854
|
});
|
|
18651
|
-
return new
|
|
18855
|
+
return new import_langgraph10.Command({
|
|
18652
18856
|
update: { team_mailbox: relevantMsgs, messages: [toolMessage2] }
|
|
18653
18857
|
});
|
|
18654
18858
|
}
|
|
18655
18859
|
const formatted = await formatAndMarkAsRead(msgs);
|
|
18656
|
-
const toolMessage = new
|
|
18860
|
+
const toolMessage = new import_langchain62.ToolMessage({
|
|
18657
18861
|
content: formatted,
|
|
18658
18862
|
tool_call_id: config.toolCall?.id,
|
|
18659
18863
|
name: "read_messages"
|
|
18660
18864
|
});
|
|
18661
|
-
return new
|
|
18865
|
+
return new import_langgraph10.Command({
|
|
18662
18866
|
update: { team_mailbox: relevantMsgs, messages: [toolMessage] }
|
|
18663
18867
|
});
|
|
18664
18868
|
},
|
|
@@ -18668,7 +18872,7 @@ function createTeammateTools(options) {
|
|
|
18668
18872
|
schema: import_v33.z.object({})
|
|
18669
18873
|
}
|
|
18670
18874
|
);
|
|
18671
|
-
const checkTasksTool = (0,
|
|
18875
|
+
const checkTasksTool = (0, import_langchain62.tool)(
|
|
18672
18876
|
async () => {
|
|
18673
18877
|
const tasks = await taskListStore.getAllTasks(teamId);
|
|
18674
18878
|
return formatTaskSummary(tasks);
|
|
@@ -18679,7 +18883,7 @@ function createTeammateTools(options) {
|
|
|
18679
18883
|
schema: import_v33.z.object({})
|
|
18680
18884
|
}
|
|
18681
18885
|
);
|
|
18682
|
-
const broadcastMessageTool = (0,
|
|
18886
|
+
const broadcastMessageTool = (0, import_langchain62.tool)(
|
|
18683
18887
|
async (input) => {
|
|
18684
18888
|
const allAgents = await mailboxStore.getRegisteredAgents(teamId);
|
|
18685
18889
|
const recipients = allAgents.filter((a) => a !== agentId);
|
|
@@ -18865,7 +19069,7 @@ You have access to these tools:
|
|
|
18865
19069
|
- \`read_messages\`: Read messages from team_lead or teammates
|
|
18866
19070
|
- \`check_tasks\`: Get current status of all tasks in the team`;
|
|
18867
19071
|
const assistantId = getTeammateAssistantId(ctx.teamId, spec.name);
|
|
18868
|
-
agent = (0,
|
|
19072
|
+
agent = (0, import_langchain63.createAgent)({
|
|
18869
19073
|
model: spec.model ?? ctx.defaultModel,
|
|
18870
19074
|
systemPrompt: teammatePrompt,
|
|
18871
19075
|
tools: allTools,
|
|
@@ -18934,19 +19138,19 @@ async function spawnTeammate(options) {
|
|
|
18934
19138
|
function createTeamMiddleware(options) {
|
|
18935
19139
|
const { teamConfig, taskListStore, mailboxStore, tenantId } = options;
|
|
18936
19140
|
const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
|
|
18937
|
-
const createTeamTool = (0,
|
|
19141
|
+
const createTeamTool = (0, import_langchain63.tool)(
|
|
18938
19142
|
async (input, config) => {
|
|
18939
|
-
const state = (0,
|
|
19143
|
+
const state = (0, import_langgraph11.getCurrentTaskInput)();
|
|
18940
19144
|
if (state?.team?.teamId) {
|
|
18941
19145
|
const existingId = state.team.teamId;
|
|
18942
|
-
const msg = new
|
|
19146
|
+
const msg = new import_langchain63.ToolMessage({
|
|
18943
19147
|
content: `A team is already active (id: ${existingId}). Use this team_id for \`check_tasks\`, \`read_messages\`, \`add_tasks\`, \`send_message\`, \`assign_task\`, \`set_task_status\`, and \`set_task_dependencies\`. Do not call \`create_team\` again unless you need a fresh team for a new objective.`,
|
|
18944
19148
|
tool_call_id: config.toolCall?.id,
|
|
18945
19149
|
name: "create_team"
|
|
18946
19150
|
});
|
|
18947
19151
|
return msg;
|
|
18948
19152
|
}
|
|
18949
|
-
const teamId = (0,
|
|
19153
|
+
const teamId = (0, import_uuid4.v4)();
|
|
18950
19154
|
const createdTasks = await taskListStore.addTasks(
|
|
18951
19155
|
teamId,
|
|
18952
19156
|
input.tasks.map((t) => ({
|
|
@@ -19028,7 +19232,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
|
|
|
19028
19232
|
\`\`\`json
|
|
19029
19233
|
${teamJson}
|
|
19030
19234
|
\`\`\``;
|
|
19031
|
-
const toolMessage = new
|
|
19235
|
+
const toolMessage = new import_langchain63.ToolMessage({
|
|
19032
19236
|
content: summary,
|
|
19033
19237
|
tool_call_id: config.toolCall?.id,
|
|
19034
19238
|
name: "create_team"
|
|
@@ -19049,7 +19253,7 @@ ${teamJson}
|
|
|
19049
19253
|
})),
|
|
19050
19254
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
19051
19255
|
};
|
|
19052
|
-
return new
|
|
19256
|
+
return new import_langgraph11.Command({
|
|
19053
19257
|
update: { team: teamState, messages: [toolMessage] }
|
|
19054
19258
|
});
|
|
19055
19259
|
},
|
|
@@ -19109,11 +19313,11 @@ After calling create_team, you MUST:
|
|
|
19109
19313
|
}
|
|
19110
19314
|
);
|
|
19111
19315
|
const resolveTeamId = () => {
|
|
19112
|
-
const state = (0,
|
|
19316
|
+
const state = (0, import_langgraph11.getCurrentTaskInput)();
|
|
19113
19317
|
if (state?.team?.teamId) return state.team.teamId;
|
|
19114
19318
|
throw new Error("No team_id provided and no team in state. Call create_team first.");
|
|
19115
19319
|
};
|
|
19116
|
-
const addTasksTool = (0,
|
|
19320
|
+
const addTasksTool = (0, import_langchain63.tool)(
|
|
19117
19321
|
async (input, config) => {
|
|
19118
19322
|
const teamId = resolveTeamId();
|
|
19119
19323
|
const created = await taskListStore.addTasks(
|
|
@@ -19127,7 +19331,7 @@ After calling create_team, you MUST:
|
|
|
19127
19331
|
}))
|
|
19128
19332
|
);
|
|
19129
19333
|
const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
|
|
19130
|
-
return new
|
|
19334
|
+
return new import_langchain63.ToolMessage({
|
|
19131
19335
|
content: `Added ${created.length} task(s) to team ${teamId}:
|
|
19132
19336
|
${summary}
|
|
19133
19337
|
Sleeping teammates will wake up and claim these.`,
|
|
@@ -19178,20 +19382,20 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
19178
19382
|
})
|
|
19179
19383
|
}
|
|
19180
19384
|
);
|
|
19181
|
-
const assignTaskTool = (0,
|
|
19385
|
+
const assignTaskTool = (0, import_langchain63.tool)(
|
|
19182
19386
|
async (input, config) => {
|
|
19183
19387
|
const teamId = resolveTeamId();
|
|
19184
19388
|
const task = await taskListStore.updateTask(teamId, input.task_id, {
|
|
19185
19389
|
assignee: input.assignee
|
|
19186
19390
|
});
|
|
19187
19391
|
if (!task) {
|
|
19188
|
-
return new
|
|
19392
|
+
return new import_langchain63.ToolMessage({
|
|
19189
19393
|
content: `Task ${input.task_id} not found in team ${teamId}.`,
|
|
19190
19394
|
tool_call_id: config.toolCall?.id,
|
|
19191
19395
|
name: "assign_task"
|
|
19192
19396
|
});
|
|
19193
19397
|
}
|
|
19194
|
-
return new
|
|
19398
|
+
return new import_langchain63.ToolMessage({
|
|
19195
19399
|
content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
|
|
19196
19400
|
tool_call_id: config.toolCall?.id,
|
|
19197
19401
|
name: "assign_task"
|
|
@@ -19206,20 +19410,20 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
19206
19410
|
})
|
|
19207
19411
|
}
|
|
19208
19412
|
);
|
|
19209
|
-
const setTaskStatusTool = (0,
|
|
19413
|
+
const setTaskStatusTool = (0, import_langchain63.tool)(
|
|
19210
19414
|
async (input, config) => {
|
|
19211
19415
|
const teamId = resolveTeamId();
|
|
19212
19416
|
const task = await taskListStore.updateTask(teamId, input.task_id, {
|
|
19213
19417
|
status: input.status
|
|
19214
19418
|
});
|
|
19215
19419
|
if (!task) {
|
|
19216
|
-
return new
|
|
19420
|
+
return new import_langchain63.ToolMessage({
|
|
19217
19421
|
content: `Task ${input.task_id} not found in team ${teamId}.`,
|
|
19218
19422
|
tool_call_id: config.toolCall?.id,
|
|
19219
19423
|
name: "set_task_status"
|
|
19220
19424
|
});
|
|
19221
19425
|
}
|
|
19222
|
-
return new
|
|
19426
|
+
return new import_langchain63.ToolMessage({
|
|
19223
19427
|
content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
|
|
19224
19428
|
tool_call_id: config.toolCall?.id,
|
|
19225
19429
|
name: "set_task_status"
|
|
@@ -19234,20 +19438,20 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
19234
19438
|
})
|
|
19235
19439
|
}
|
|
19236
19440
|
);
|
|
19237
|
-
const setTaskDependenciesTool = (0,
|
|
19441
|
+
const setTaskDependenciesTool = (0, import_langchain63.tool)(
|
|
19238
19442
|
async (input, config) => {
|
|
19239
19443
|
const teamId = resolveTeamId();
|
|
19240
19444
|
const task = await taskListStore.updateTask(teamId, input.task_id, {
|
|
19241
19445
|
dependencies: input.dependencies
|
|
19242
19446
|
});
|
|
19243
19447
|
if (!task) {
|
|
19244
|
-
return new
|
|
19448
|
+
return new import_langchain63.ToolMessage({
|
|
19245
19449
|
content: `Task ${input.task_id} not found in team ${teamId}.`,
|
|
19246
19450
|
tool_call_id: config.toolCall?.id,
|
|
19247
19451
|
name: "set_task_dependencies"
|
|
19248
19452
|
});
|
|
19249
19453
|
}
|
|
19250
|
-
return new
|
|
19454
|
+
return new import_langchain63.ToolMessage({
|
|
19251
19455
|
content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
|
|
19252
19456
|
tool_call_id: config.toolCall?.id,
|
|
19253
19457
|
name: "set_task_dependencies"
|
|
@@ -19262,16 +19466,16 @@ IMPORTANT: Assigning to a specific teammate
|
|
|
19262
19466
|
})
|
|
19263
19467
|
}
|
|
19264
19468
|
);
|
|
19265
|
-
const checkTasksTool = (0,
|
|
19469
|
+
const checkTasksTool = (0, import_langchain63.tool)(
|
|
19266
19470
|
async (input, config) => {
|
|
19267
19471
|
const teamId = resolveTeamId();
|
|
19268
19472
|
const tasks = await taskListStore.getAllTasks(teamId);
|
|
19269
19473
|
const tasksSnapshot = tasks;
|
|
19270
|
-
return new
|
|
19474
|
+
return new import_langgraph11.Command({
|
|
19271
19475
|
update: {
|
|
19272
19476
|
tasks: tasksSnapshot,
|
|
19273
19477
|
messages: [
|
|
19274
|
-
new
|
|
19478
|
+
new import_langchain63.ToolMessage({
|
|
19275
19479
|
content: formatTaskSummary(tasks),
|
|
19276
19480
|
tool_call_id: config.toolCall?.id,
|
|
19277
19481
|
name: "check_tasks"
|
|
@@ -19307,7 +19511,7 @@ Task Status Values:
|
|
|
19307
19511
|
})
|
|
19308
19512
|
}
|
|
19309
19513
|
);
|
|
19310
|
-
const sendMessageTool = (0,
|
|
19514
|
+
const sendMessageTool = (0, import_langchain63.tool)(
|
|
19311
19515
|
async (input, config) => {
|
|
19312
19516
|
const teamId = resolveTeamId();
|
|
19313
19517
|
await mailboxStore.sendMessage(
|
|
@@ -19317,7 +19521,7 @@ Task Status Values:
|
|
|
19317
19521
|
input.content,
|
|
19318
19522
|
"direct_message" /* DIRECT_MESSAGE */
|
|
19319
19523
|
);
|
|
19320
|
-
return new
|
|
19524
|
+
return new import_langchain63.ToolMessage({
|
|
19321
19525
|
content: `Message sent to ${input.to}.`,
|
|
19322
19526
|
tool_call_id: config.toolCall?.id,
|
|
19323
19527
|
name: "send_message"
|
|
@@ -19332,7 +19536,7 @@ Task Status Values:
|
|
|
19332
19536
|
})
|
|
19333
19537
|
}
|
|
19334
19538
|
);
|
|
19335
|
-
const readMessagesTool = (0,
|
|
19539
|
+
const readMessagesTool = (0, import_langchain63.tool)(
|
|
19336
19540
|
async (input, config) => {
|
|
19337
19541
|
const teamId = resolveTeamId();
|
|
19338
19542
|
const formatAndMarkAsRead = async (msgs2) => {
|
|
@@ -19360,12 +19564,12 @@ Task Status Values:
|
|
|
19360
19564
|
if (msgs.length > 0) {
|
|
19361
19565
|
const formatted2 = await formatAndMarkAsRead(msgs);
|
|
19362
19566
|
const allTeamMessages2 = await getAllTeamMessagesForState();
|
|
19363
|
-
const toolMessage2 = new
|
|
19567
|
+
const toolMessage2 = new import_langchain63.ToolMessage({
|
|
19364
19568
|
content: formatted2,
|
|
19365
19569
|
tool_call_id: config.toolCall?.id,
|
|
19366
19570
|
name: "read_messages"
|
|
19367
19571
|
});
|
|
19368
|
-
return new
|
|
19572
|
+
return new import_langgraph11.Command({
|
|
19369
19573
|
update: { team_mailbox: allTeamMessages2, messages: [toolMessage2] }
|
|
19370
19574
|
});
|
|
19371
19575
|
}
|
|
@@ -19392,22 +19596,22 @@ Task Status Values:
|
|
|
19392
19596
|
);
|
|
19393
19597
|
const allTeamMessages = await getAllTeamMessagesForState();
|
|
19394
19598
|
if (msgs.length === 0) {
|
|
19395
|
-
const toolMessage2 = new
|
|
19599
|
+
const toolMessage2 = new import_langchain63.ToolMessage({
|
|
19396
19600
|
content: "No unread messages from teammates.",
|
|
19397
19601
|
tool_call_id: config.toolCall?.id,
|
|
19398
19602
|
name: "read_messages"
|
|
19399
19603
|
});
|
|
19400
|
-
return new
|
|
19604
|
+
return new import_langgraph11.Command({
|
|
19401
19605
|
update: { team_mailbox: allTeamMessages, messages: [toolMessage2] }
|
|
19402
19606
|
});
|
|
19403
19607
|
}
|
|
19404
19608
|
const formatted = await formatAndMarkAsRead(msgs);
|
|
19405
|
-
const toolMessage = new
|
|
19609
|
+
const toolMessage = new import_langchain63.ToolMessage({
|
|
19406
19610
|
content: formatted,
|
|
19407
19611
|
tool_call_id: config.toolCall?.id,
|
|
19408
19612
|
name: "read_messages"
|
|
19409
19613
|
});
|
|
19410
|
-
return new
|
|
19614
|
+
return new import_langgraph11.Command({
|
|
19411
19615
|
update: { team_mailbox: allTeamMessages, messages: [toolMessage] }
|
|
19412
19616
|
});
|
|
19413
19617
|
},
|
|
@@ -19419,7 +19623,7 @@ Task Status Values:
|
|
|
19419
19623
|
})
|
|
19420
19624
|
}
|
|
19421
19625
|
);
|
|
19422
|
-
const disbandTeamTool = (0,
|
|
19626
|
+
const disbandTeamTool = (0, import_langchain63.tool)(
|
|
19423
19627
|
async (input, config) => {
|
|
19424
19628
|
const teamId = resolveTeamId();
|
|
19425
19629
|
await mailboxStore.broadcastMessage(
|
|
@@ -19429,7 +19633,7 @@ Task Status Values:
|
|
|
19429
19633
|
"shutdown_request" /* SHUTDOWN_REQUEST */
|
|
19430
19634
|
);
|
|
19431
19635
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
19432
|
-
return new
|
|
19636
|
+
return new import_langchain63.ToolMessage({
|
|
19433
19637
|
content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
|
|
19434
19638
|
tool_call_id: config.toolCall?.id,
|
|
19435
19639
|
name: "disband_team"
|
|
@@ -19440,7 +19644,7 @@ Task Status Values:
|
|
|
19440
19644
|
description: "Disband a team when all work is done. Before calling: (1) Call check_tasks to verify no tasks are still pending/in_progress; (2) if any are, discuss with the team via read_messages and broadcast_message/send_message whether to continue or stop/cancel them; (3) only after alignment (all tasks completed/failed or explicitly stopped), then call this tool. This will: 1) Send a shutdown message to all teammates, 2) Wait briefly for them to clean up, 3) Clear all tasks and messages. Omit team_id to use the active team from state."
|
|
19441
19645
|
}
|
|
19442
19646
|
);
|
|
19443
|
-
const broadcastMessageTool = (0,
|
|
19647
|
+
const broadcastMessageTool = (0, import_langchain63.tool)(
|
|
19444
19648
|
async (input, config) => {
|
|
19445
19649
|
const teamId = resolveTeamId();
|
|
19446
19650
|
await mailboxStore.broadcastMessage(
|
|
@@ -19449,7 +19653,7 @@ Task Status Values:
|
|
|
19449
19653
|
input.content,
|
|
19450
19654
|
"broadcast" /* BROADCAST */
|
|
19451
19655
|
);
|
|
19452
|
-
return new
|
|
19656
|
+
return new import_langchain63.ToolMessage({
|
|
19453
19657
|
content: `Broadcast message sent to all teammates.`,
|
|
19454
19658
|
tool_call_id: config.toolCall?.id,
|
|
19455
19659
|
name: "broadcast_message"
|
|
@@ -19463,7 +19667,7 @@ Task Status Values:
|
|
|
19463
19667
|
})
|
|
19464
19668
|
}
|
|
19465
19669
|
);
|
|
19466
|
-
return (0,
|
|
19670
|
+
return (0, import_langchain63.createMiddleware)({
|
|
19467
19671
|
name: "teamMiddleware",
|
|
19468
19672
|
tools: [
|
|
19469
19673
|
createTeamTool,
|
|
@@ -19572,7 +19776,7 @@ function createAgentTeam(config) {
|
|
|
19572
19776
|
];
|
|
19573
19777
|
const systemPrompt = config.systemPrompt + "\n\n" + TEAM_LEAD_BASE_PROMPT;
|
|
19574
19778
|
const stateSchema2 = createReactAgentSchema(TEAM_STATE_SCHEMA);
|
|
19575
|
-
return (0,
|
|
19779
|
+
return (0, import_langchain64.createAgent)({
|
|
19576
19780
|
model: config.model ?? "claude-sonnet-4-5-20250929",
|
|
19577
19781
|
systemPrompt,
|
|
19578
19782
|
tools: [],
|
|
@@ -19602,7 +19806,7 @@ var TeamAgentGraphBuilder = class {
|
|
|
19602
19806
|
const tools = params.tools.map((t) => {
|
|
19603
19807
|
const toolClient = getToolClient(t.key);
|
|
19604
19808
|
return toolClient;
|
|
19605
|
-
}).filter((
|
|
19809
|
+
}).filter((tool52) => tool52 !== void 0);
|
|
19606
19810
|
const teammates = params.subAgents.map((sa) => {
|
|
19607
19811
|
const baseConfig = sa.config;
|
|
19608
19812
|
return {
|
|
@@ -19640,17 +19844,17 @@ var TeamAgentGraphBuilder = class {
|
|
|
19640
19844
|
};
|
|
19641
19845
|
|
|
19642
19846
|
// src/deep_agent_new/processing_agent.ts
|
|
19643
|
-
var
|
|
19847
|
+
var import_langchain67 = require("langchain");
|
|
19644
19848
|
|
|
19645
19849
|
// src/middlewares/topologyMiddleware.ts
|
|
19646
|
-
var import_langchain64 = require("langchain");
|
|
19647
|
-
var import_messages4 = require("@langchain/core/messages");
|
|
19648
19850
|
var import_langchain65 = require("langchain");
|
|
19649
|
-
var
|
|
19650
|
-
var
|
|
19651
|
-
var
|
|
19652
|
-
|
|
19653
|
-
|
|
19851
|
+
var import_messages3 = require("@langchain/core/messages");
|
|
19852
|
+
var import_langchain66 = require("langchain");
|
|
19853
|
+
var import_zod53 = require("zod");
|
|
19854
|
+
var import_langgraph12 = require("@langchain/langgraph");
|
|
19855
|
+
var CompletedEdgeSchema = import_zod53.z.object({
|
|
19856
|
+
to: import_zod53.z.string(),
|
|
19857
|
+
purpose: import_zod53.z.string()
|
|
19654
19858
|
});
|
|
19655
19859
|
function deriveCompletedEdges(messages, edges) {
|
|
19656
19860
|
const completedToolCallIds = /* @__PURE__ */ new Set();
|
|
@@ -19677,16 +19881,16 @@ function deriveCompletedEdges(messages, edges) {
|
|
|
19677
19881
|
}
|
|
19678
19882
|
function createTopologyMiddleware(options) {
|
|
19679
19883
|
const { edges, trackingStore } = options;
|
|
19680
|
-
return (0,
|
|
19884
|
+
return (0, import_langchain65.createMiddleware)({
|
|
19681
19885
|
name: "TopologyMiddleware",
|
|
19682
|
-
contextSchema:
|
|
19683
|
-
runConfig:
|
|
19886
|
+
contextSchema: import_zod53.z.object({
|
|
19887
|
+
runConfig: import_zod53.z.any()
|
|
19684
19888
|
}),
|
|
19685
|
-
stateSchema:
|
|
19686
|
-
currentAgentId:
|
|
19687
|
-
completedEdges:
|
|
19688
|
-
runId:
|
|
19689
|
-
stepIdMap:
|
|
19889
|
+
stateSchema: import_zod53.z.object({
|
|
19890
|
+
currentAgentId: import_zod53.z.string().default(""),
|
|
19891
|
+
completedEdges: import_zod53.z.array(CompletedEdgeSchema).default([]),
|
|
19892
|
+
runId: import_zod53.z.string().default(""),
|
|
19893
|
+
stepIdMap: import_zod53.z.record(import_zod53.z.string()).default({})
|
|
19690
19894
|
}),
|
|
19691
19895
|
beforeAgent: async (state, runtime) => {
|
|
19692
19896
|
if (state.runId) {
|
|
@@ -19737,14 +19941,14 @@ ${request.systemPrompt}` : topologyPrompt;
|
|
|
19737
19941
|
return handler({ ...request, systemPrompt: newSystemPrompt });
|
|
19738
19942
|
},
|
|
19739
19943
|
tools: [
|
|
19740
|
-
(0,
|
|
19944
|
+
(0, import_langchain66.tool)(
|
|
19741
19945
|
async (_input) => {
|
|
19742
19946
|
return "placeholder";
|
|
19743
19947
|
},
|
|
19744
19948
|
{
|
|
19745
19949
|
name: "read_topo_progress",
|
|
19746
19950
|
description: "Check the current progress of the workflow execution plan. Returns which steps have been completed and which are still pending.",
|
|
19747
|
-
schema:
|
|
19951
|
+
schema: import_zod53.z.object({})
|
|
19748
19952
|
}
|
|
19749
19953
|
)
|
|
19750
19954
|
],
|
|
@@ -19759,7 +19963,7 @@ ${request.systemPrompt}` : topologyPrompt;
|
|
|
19759
19963
|
status: doneSet.has(e.to) ? "done" : "pending"
|
|
19760
19964
|
}));
|
|
19761
19965
|
const doneCount = completedEdges.length;
|
|
19762
|
-
return new
|
|
19966
|
+
return new import_messages3.ToolMessage({
|
|
19763
19967
|
content: JSON.stringify(
|
|
19764
19968
|
{
|
|
19765
19969
|
currentAgentId,
|
|
@@ -19777,7 +19981,7 @@ ${request.systemPrompt}` : topologyPrompt;
|
|
|
19777
19981
|
try {
|
|
19778
19982
|
return await handler(request);
|
|
19779
19983
|
} catch (error) {
|
|
19780
|
-
if (error instanceof
|
|
19984
|
+
if (error instanceof import_langgraph12.GraphInterrupt) {
|
|
19781
19985
|
throw error;
|
|
19782
19986
|
}
|
|
19783
19987
|
throw error;
|
|
@@ -19824,7 +20028,7 @@ ${request.systemPrompt}` : topologyPrompt;
|
|
|
19824
20028
|
];
|
|
19825
20029
|
return {
|
|
19826
20030
|
messages: [
|
|
19827
|
-
new
|
|
20031
|
+
new import_messages3.AIMessage({
|
|
19828
20032
|
content: [
|
|
19829
20033
|
`Task rejected: topology violation.`,
|
|
19830
20034
|
`Agent "${currentAgentId}" is not allowed to delegate to "${targetAgent}".`,
|
|
@@ -19966,13 +20170,13 @@ ${BASE_PROMPT2}` : BASE_PROMPT2;
|
|
|
19966
20170
|
backend: filesystemBackend
|
|
19967
20171
|
}),
|
|
19968
20172
|
// Subagent middleware: Automatic conversation summarization
|
|
19969
|
-
(0,
|
|
20173
|
+
(0, import_langchain67.summarizationMiddleware)({
|
|
19970
20174
|
model,
|
|
19971
20175
|
trigger: { tokens: 17e4 },
|
|
19972
20176
|
keep: { messages: 6 }
|
|
19973
20177
|
}),
|
|
19974
20178
|
// Subagent middleware: Anthropic prompt caching
|
|
19975
|
-
(0,
|
|
20179
|
+
(0, import_langchain67.anthropicPromptCachingMiddleware)({
|
|
19976
20180
|
unsupportedModelBehavior: "ignore"
|
|
19977
20181
|
}),
|
|
19978
20182
|
// Subagent middleware: Patches tool calls
|
|
@@ -19985,23 +20189,23 @@ ${BASE_PROMPT2}` : BASE_PROMPT2;
|
|
|
19985
20189
|
allowAsync: false
|
|
19986
20190
|
}),
|
|
19987
20191
|
// Automatically summarizes conversation history
|
|
19988
|
-
(0,
|
|
20192
|
+
(0, import_langchain67.summarizationMiddleware)({
|
|
19989
20193
|
model,
|
|
19990
20194
|
trigger: { tokens: 17e4 },
|
|
19991
20195
|
keep: { messages: 6 }
|
|
19992
20196
|
}),
|
|
19993
20197
|
// Enables Anthropic prompt caching
|
|
19994
|
-
(0,
|
|
20198
|
+
(0, import_langchain67.anthropicPromptCachingMiddleware)({
|
|
19995
20199
|
unsupportedModelBehavior: "ignore"
|
|
19996
20200
|
}),
|
|
19997
20201
|
// Patches tool calls
|
|
19998
20202
|
createPatchToolCallsMiddleware()
|
|
19999
20203
|
];
|
|
20000
20204
|
if (interruptOn) {
|
|
20001
|
-
middleware.push((0,
|
|
20205
|
+
middleware.push((0, import_langchain67.humanInTheLoopMiddleware)({ interruptOn }));
|
|
20002
20206
|
}
|
|
20003
20207
|
middleware.push(...customMiddleware);
|
|
20004
|
-
return (0,
|
|
20208
|
+
return (0, import_langchain67.createAgent)({
|
|
20005
20209
|
model,
|
|
20006
20210
|
systemPrompt: finalSystemPrompt,
|
|
20007
20211
|
tools,
|
|
@@ -20021,7 +20225,7 @@ var ProcessingAgentGraphBuilder = class {
|
|
|
20021
20225
|
const tools = params.tools.map((t) => {
|
|
20022
20226
|
const toolClient = getToolClient(t.key);
|
|
20023
20227
|
return toolClient;
|
|
20024
|
-
}).filter((
|
|
20228
|
+
}).filter((tool52) => tool52 !== void 0);
|
|
20025
20229
|
const subagents = await Promise.all(params.subAgents.map(async (sa) => {
|
|
20026
20230
|
if (sa.client) {
|
|
20027
20231
|
return {
|
|
@@ -20067,11 +20271,11 @@ var ProcessingAgentGraphBuilder = class {
|
|
|
20067
20271
|
};
|
|
20068
20272
|
|
|
20069
20273
|
// src/agent_lattice/builders/RemoteAgentGraphBuilder.ts
|
|
20070
|
-
var
|
|
20071
|
-
var
|
|
20274
|
+
var import_langgraph13 = require("@langchain/langgraph");
|
|
20275
|
+
var import_messages4 = require("@langchain/core/messages");
|
|
20072
20276
|
|
|
20073
20277
|
// src/services/a2a-client.ts
|
|
20074
|
-
var
|
|
20278
|
+
var import_uuid5 = require("uuid");
|
|
20075
20279
|
var A2ARemoteError = class extends Error {
|
|
20076
20280
|
constructor(message, statusCode, body) {
|
|
20077
20281
|
super(message);
|
|
@@ -20118,7 +20322,7 @@ var A2ARemoteClient = class {
|
|
|
20118
20322
|
*/
|
|
20119
20323
|
async sendMessage(text) {
|
|
20120
20324
|
await this.resolve();
|
|
20121
|
-
const taskId = (0,
|
|
20325
|
+
const taskId = (0, import_uuid5.v4)();
|
|
20122
20326
|
const body = JSON.stringify({
|
|
20123
20327
|
jsonrpc: "2.0",
|
|
20124
20328
|
method: "tasks/send",
|
|
@@ -20244,7 +20448,7 @@ var RemoteAgentGraphBuilder = class {
|
|
|
20244
20448
|
if (!text) {
|
|
20245
20449
|
return {
|
|
20246
20450
|
messages: [
|
|
20247
|
-
new
|
|
20451
|
+
new import_messages4.AIMessage("No text input provided to remote agent.")
|
|
20248
20452
|
]
|
|
20249
20453
|
};
|
|
20250
20454
|
}
|
|
@@ -20255,18 +20459,18 @@ User request:
|
|
|
20255
20459
|
${text}` : text;
|
|
20256
20460
|
const response = await client.sendMessage(fullPrompt);
|
|
20257
20461
|
return {
|
|
20258
|
-
messages: [new
|
|
20462
|
+
messages: [new import_messages4.AIMessage(response)]
|
|
20259
20463
|
};
|
|
20260
20464
|
} catch (error) {
|
|
20261
20465
|
const msg = error.message ?? String(error);
|
|
20262
20466
|
return {
|
|
20263
20467
|
messages: [
|
|
20264
|
-
new
|
|
20468
|
+
new import_messages4.AIMessage(`Remote A2A agent error: ${msg}`)
|
|
20265
20469
|
]
|
|
20266
20470
|
};
|
|
20267
20471
|
}
|
|
20268
20472
|
};
|
|
20269
|
-
const workflow = new
|
|
20473
|
+
const workflow = new import_langgraph13.StateGraph(import_langgraph13.MessagesAnnotation).addNode("remote_call", remoteCallNode).addEdge("__start__", "remote_call").addEdge("remote_call", "__end__");
|
|
20270
20474
|
return workflow.compile();
|
|
20271
20475
|
}
|
|
20272
20476
|
};
|
|
@@ -20288,7 +20492,7 @@ function extractLastHumanMessage(messages) {
|
|
|
20288
20492
|
}
|
|
20289
20493
|
|
|
20290
20494
|
// src/agent_lattice/builders/WorkflowAgentGraphBuilder.ts
|
|
20291
|
-
var
|
|
20495
|
+
var import_langchain68 = require("langchain");
|
|
20292
20496
|
init_MemoryLatticeManager();
|
|
20293
20497
|
var import_protocols10 = require("@axiom-lattice/protocols");
|
|
20294
20498
|
init_compile();
|
|
@@ -20301,26 +20505,26 @@ var WorkflowAgentGraphBuilder = class {
|
|
|
20301
20505
|
);
|
|
20302
20506
|
}
|
|
20303
20507
|
const config = agentLattice.config;
|
|
20304
|
-
const
|
|
20508
|
+
const yaml2 = config.workflowYaml;
|
|
20305
20509
|
const tenantId = agentLattice.config.tenantId ?? "default";
|
|
20306
20510
|
const checkpointer = getCheckpointSaver("default");
|
|
20307
20511
|
const tools = params.tools.map((t) => t.executor).filter(Boolean);
|
|
20308
20512
|
const middlewareConfigs = params.middleware || [];
|
|
20309
20513
|
const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false);
|
|
20310
|
-
const
|
|
20514
|
+
const askMiddlewares = await createCommonMiddlewares([
|
|
20311
20515
|
{
|
|
20312
20516
|
id: "ask_user_to_clarify",
|
|
20313
20517
|
type: "ask_user_to_clarify",
|
|
20314
20518
|
name: "Ask User Clarify",
|
|
20315
|
-
description: "For
|
|
20519
|
+
description: "For workflow steps requiring user interaction",
|
|
20316
20520
|
enabled: true,
|
|
20317
20521
|
config: {}
|
|
20318
20522
|
}
|
|
20319
20523
|
], void 0, false);
|
|
20320
20524
|
const noWrapMiddlewares = middlewares.filter((m) => !m.wrapModelCall);
|
|
20321
|
-
const
|
|
20525
|
+
const noWrapAskMiddlewares = askMiddlewares.filter((m) => !m.wrapModelCall);
|
|
20322
20526
|
console.log(`[WF BUILDER] building default agent | toolCount=${tools.length} | middlewareCount=${middlewares.length}`);
|
|
20323
|
-
const defaultAgent = (0,
|
|
20527
|
+
const defaultAgent = (0, import_langchain68.createAgent)({
|
|
20324
20528
|
model: params.model,
|
|
20325
20529
|
tools,
|
|
20326
20530
|
systemPrompt: params.prompt || DEFAULT_AGENT_PROMPT,
|
|
@@ -20334,34 +20538,34 @@ var WorkflowAgentGraphBuilder = class {
|
|
|
20334
20538
|
console.log(`[WF BUILDER] resolveAgent: looking up ref="${ref}"`);
|
|
20335
20539
|
return await getAgentClientAsync(tenantId, ref);
|
|
20336
20540
|
}
|
|
20337
|
-
const
|
|
20541
|
+
const isAsk = stepType === "ask";
|
|
20338
20542
|
if (responseFormat) {
|
|
20339
|
-
const key = (
|
|
20543
|
+
const key = (isAsk ? "ask:" : "agent:") + JSON.stringify(responseFormat);
|
|
20340
20544
|
console.log(`[WF BUILDER] resolveAgent: cacheKey=${key.slice(0, 80)}... | cached=${agentCache.has(key)}`);
|
|
20341
20545
|
if (!agentCache.has(key)) {
|
|
20342
|
-
console.log(`[WF BUILDER] creating ${
|
|
20343
|
-
const agent = (0,
|
|
20546
|
+
console.log(`[WF BUILDER] creating ${isAsk ? "ask" : "agent"} with responseFormat`);
|
|
20547
|
+
const agent = (0, import_langchain68.createAgent)({
|
|
20344
20548
|
model: params.model,
|
|
20345
20549
|
tools,
|
|
20346
20550
|
systemPrompt: params.prompt || DEFAULT_AGENT_PROMPT,
|
|
20347
20551
|
checkpointer,
|
|
20348
|
-
middleware:
|
|
20552
|
+
middleware: isAsk ? noWrapAskMiddlewares : noWrapMiddlewares,
|
|
20349
20553
|
responseFormat
|
|
20350
20554
|
});
|
|
20351
20555
|
agentCache.set(key, agent);
|
|
20352
20556
|
}
|
|
20353
20557
|
return agentCache.get(key);
|
|
20354
20558
|
}
|
|
20355
|
-
if (
|
|
20356
|
-
const key = "
|
|
20559
|
+
if (isAsk) {
|
|
20560
|
+
const key = "ask:default";
|
|
20357
20561
|
if (!agentCache.has(key)) {
|
|
20358
|
-
console.log(`[WF BUILDER] creating
|
|
20359
|
-
const agent = (0,
|
|
20562
|
+
console.log(`[WF BUILDER] creating ask default agent`);
|
|
20563
|
+
const agent = (0, import_langchain68.createAgent)({
|
|
20360
20564
|
model: params.model,
|
|
20361
20565
|
tools,
|
|
20362
20566
|
systemPrompt: params.prompt || DEFAULT_AGENT_PROMPT,
|
|
20363
20567
|
checkpointer,
|
|
20364
|
-
middleware:
|
|
20568
|
+
middleware: askMiddlewares
|
|
20365
20569
|
});
|
|
20366
20570
|
agentCache.set(key, agent);
|
|
20367
20571
|
}
|
|
@@ -20374,11 +20578,11 @@ var WorkflowAgentGraphBuilder = class {
|
|
|
20374
20578
|
try {
|
|
20375
20579
|
const storeLattice = getStoreLattice("default", "workflowTracking");
|
|
20376
20580
|
trackingStore = storeLattice.store;
|
|
20377
|
-
console.log(`[WF BUILDER] trackingStore registered
|
|
20581
|
+
console.log(`[WF BUILDER] trackingStore registered`);
|
|
20378
20582
|
} catch {
|
|
20379
|
-
console.warn(`[WF BUILDER] no trackingStore registered
|
|
20583
|
+
console.warn(`[WF BUILDER] no trackingStore registered`);
|
|
20380
20584
|
}
|
|
20381
|
-
const graph = compileWorkflow(
|
|
20585
|
+
const graph = compileWorkflow(yaml2, resolveAgent, checkpointer, trackingStore);
|
|
20382
20586
|
return graph;
|
|
20383
20587
|
}
|
|
20384
20588
|
};
|
|
@@ -21079,9 +21283,66 @@ ${body}` : `${frontmatter}
|
|
|
21079
21283
|
}
|
|
21080
21284
|
};
|
|
21081
21285
|
|
|
21286
|
+
// src/store_lattice/InMemoryMenuStore.ts
|
|
21287
|
+
var import_crypto3 = require("crypto");
|
|
21288
|
+
var InMemoryMenuStore = class {
|
|
21289
|
+
constructor() {
|
|
21290
|
+
this.items = /* @__PURE__ */ new Map();
|
|
21291
|
+
}
|
|
21292
|
+
async list(params) {
|
|
21293
|
+
const results = Array.from(this.items.values()).filter((item) => {
|
|
21294
|
+
if (item.tenantId !== params.tenantId) return false;
|
|
21295
|
+
if (params.menuTarget && item.menuTarget !== params.menuTarget) return false;
|
|
21296
|
+
if (!item.enabled) return false;
|
|
21297
|
+
return true;
|
|
21298
|
+
});
|
|
21299
|
+
results.sort((a, b) => a.sortOrder - b.sortOrder);
|
|
21300
|
+
return results;
|
|
21301
|
+
}
|
|
21302
|
+
async getById(id) {
|
|
21303
|
+
return this.items.get(id) || null;
|
|
21304
|
+
}
|
|
21305
|
+
async create(input) {
|
|
21306
|
+
const now = /* @__PURE__ */ new Date();
|
|
21307
|
+
const item = {
|
|
21308
|
+
id: (0, import_crypto3.randomUUID)(),
|
|
21309
|
+
tenantId: input.tenantId,
|
|
21310
|
+
menuTarget: input.menuTarget,
|
|
21311
|
+
group: input.group,
|
|
21312
|
+
name: input.name,
|
|
21313
|
+
icon: input.icon,
|
|
21314
|
+
sortOrder: input.sortOrder ?? 0,
|
|
21315
|
+
contentType: input.contentType,
|
|
21316
|
+
contentConfig: input.contentConfig,
|
|
21317
|
+
enabled: true,
|
|
21318
|
+
createdAt: now,
|
|
21319
|
+
updatedAt: now
|
|
21320
|
+
};
|
|
21321
|
+
this.items.set(item.id, item);
|
|
21322
|
+
return item;
|
|
21323
|
+
}
|
|
21324
|
+
async update(id, patch) {
|
|
21325
|
+
const existing = this.items.get(id);
|
|
21326
|
+
if (!existing) throw new Error(`MenuItem ${id} not found`);
|
|
21327
|
+
const updated = {
|
|
21328
|
+
...existing,
|
|
21329
|
+
...patch,
|
|
21330
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
21331
|
+
};
|
|
21332
|
+
this.items.set(id, updated);
|
|
21333
|
+
return updated;
|
|
21334
|
+
}
|
|
21335
|
+
async delete(id) {
|
|
21336
|
+
this.items.delete(id);
|
|
21337
|
+
}
|
|
21338
|
+
clear() {
|
|
21339
|
+
this.items.clear();
|
|
21340
|
+
}
|
|
21341
|
+
};
|
|
21342
|
+
|
|
21082
21343
|
// src/agent_lattice/agentArchitectTools.ts
|
|
21083
|
-
var
|
|
21084
|
-
var
|
|
21344
|
+
var import_zod54 = __toESM(require("zod"));
|
|
21345
|
+
var import_uuid6 = require("uuid");
|
|
21085
21346
|
var import_protocols12 = require("@axiom-lattice/protocols");
|
|
21086
21347
|
function getTenantId(exeConfig) {
|
|
21087
21348
|
const runConfig = exeConfig?.configurable?.runConfig || {};
|
|
@@ -21110,7 +21371,7 @@ registerToolLattice(
|
|
|
21110
21371
|
{
|
|
21111
21372
|
name: "list_agents",
|
|
21112
21373
|
description: "List all agents for the current workspace. Returns a summary with id, name, description, and type for each agent.",
|
|
21113
|
-
schema:
|
|
21374
|
+
schema: import_zod54.default.object({})
|
|
21114
21375
|
},
|
|
21115
21376
|
async (_input, exeConfig) => {
|
|
21116
21377
|
try {
|
|
@@ -21137,8 +21398,8 @@ registerToolLattice(
|
|
|
21137
21398
|
{
|
|
21138
21399
|
name: "get_agent",
|
|
21139
21400
|
description: "Get the full configuration of a specific agent by its ID. Returns the complete AgentConfig including prompt, middleware, tools, and sub-agents.",
|
|
21140
|
-
schema:
|
|
21141
|
-
id:
|
|
21401
|
+
schema: import_zod54.default.object({
|
|
21402
|
+
id: import_zod54.default.string().describe("The agent ID to retrieve")
|
|
21142
21403
|
})
|
|
21143
21404
|
},
|
|
21144
21405
|
async (input, exeConfig) => {
|
|
@@ -21155,24 +21416,24 @@ registerToolLattice(
|
|
|
21155
21416
|
}
|
|
21156
21417
|
}
|
|
21157
21418
|
);
|
|
21158
|
-
var middlewareConfigSchema =
|
|
21159
|
-
id:
|
|
21160
|
-
type:
|
|
21161
|
-
name:
|
|
21162
|
-
description:
|
|
21163
|
-
enabled:
|
|
21164
|
-
config:
|
|
21419
|
+
var middlewareConfigSchema = import_zod54.default.object({
|
|
21420
|
+
id: import_zod54.default.string(),
|
|
21421
|
+
type: import_zod54.default.string(),
|
|
21422
|
+
name: import_zod54.default.string(),
|
|
21423
|
+
description: import_zod54.default.string(),
|
|
21424
|
+
enabled: import_zod54.default.boolean(),
|
|
21425
|
+
config: import_zod54.default.record(import_zod54.default.any()).optional()
|
|
21165
21426
|
});
|
|
21166
|
-
var createAgentSchema =
|
|
21167
|
-
name:
|
|
21168
|
-
description:
|
|
21169
|
-
type:
|
|
21170
|
-
prompt:
|
|
21171
|
-
tools:
|
|
21172
|
-
middleware:
|
|
21173
|
-
subAgents:
|
|
21174
|
-
internalSubAgents:
|
|
21175
|
-
modelKey:
|
|
21427
|
+
var createAgentSchema = import_zod54.default.object({
|
|
21428
|
+
name: import_zod54.default.string().describe("Human-friendly display name for the agent. The machine ID (used in other tools) is auto-generated as a slug from this name (e.g. 'My Cool Agent' \u2192 'my-cool-agent')."),
|
|
21429
|
+
description: import_zod54.default.string().optional().describe("Short description"),
|
|
21430
|
+
type: import_zod54.default.enum(["react", "deep_agent"]).describe("Agent type. Use 'react' for simple single-responsibility agents, 'deep_agent' for complex open-ended agents. For PROCESSING agents (workflow orchestration), use create_processing_agent instead."),
|
|
21431
|
+
prompt: import_zod54.default.string().describe("System prompt for the agent"),
|
|
21432
|
+
tools: import_zod54.default.array(import_zod54.default.string()).optional().describe("Tool keys (strings) to assign. Call list_tools first to see available keys. Each element is a plain string like 'sap_api_search'. IMPORTANT: tools is a FLAT string array of tool names. Do NOT put middleware-like objects here \u2014 middleware goes in the separate 'middleware' field."),
|
|
21433
|
+
middleware: import_zod54.default.array(middlewareConfigSchema).optional().describe("Middleware configuration objects. Each has {id, type, name, description, enabled, config}. IMPORTANT: middleware objects are NOT tools. Do NOT put tool keys (strings) here \u2014 tool names go in the separate 'tools' array. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
|
|
21434
|
+
subAgents: import_zod54.default.array(import_zod54.default.string()).optional().describe("Sub-agent IDs (deep_agent only)"),
|
|
21435
|
+
internalSubAgents: import_zod54.default.array(import_zod54.default.any()).optional().describe("Inline sub-agent configs (deep_agent only)"),
|
|
21436
|
+
modelKey: import_zod54.default.string().optional().describe("Model key to use")
|
|
21176
21437
|
});
|
|
21177
21438
|
registerToolLattice(
|
|
21178
21439
|
"create_agent",
|
|
@@ -21210,21 +21471,21 @@ registerToolLattice(
|
|
|
21210
21471
|
}
|
|
21211
21472
|
}
|
|
21212
21473
|
);
|
|
21213
|
-
var topologyEdgeSchema =
|
|
21214
|
-
from:
|
|
21215
|
-
to:
|
|
21216
|
-
purpose:
|
|
21474
|
+
var topologyEdgeSchema = import_zod54.default.object({
|
|
21475
|
+
from: import_zod54.default.string().describe("Source agent ID. For the first edge, this is the orchestrator (use the orchestrator's name as a placeholder \u2014 the tool will replace it with the actual ID). For subsequent chained edges, this is the previous stage's sub-agent ID."),
|
|
21476
|
+
to: import_zod54.default.string().describe("Target agent ID (the sub-agent to delegate to)"),
|
|
21477
|
+
purpose: import_zod54.default.string().describe("Business purpose of this delegation step \u2014 what the sub-agent should accomplish")
|
|
21217
21478
|
});
|
|
21218
|
-
var createProcessingAgentSchema =
|
|
21219
|
-
name:
|
|
21220
|
-
description:
|
|
21221
|
-
prompt:
|
|
21222
|
-
edges:
|
|
21223
|
-
tools:
|
|
21224
|
-
subAgents:
|
|
21225
|
-
internalSubAgents:
|
|
21226
|
-
middleware:
|
|
21227
|
-
modelKey:
|
|
21479
|
+
var createProcessingAgentSchema = import_zod54.default.object({
|
|
21480
|
+
name: import_zod54.default.string().describe("Display name for the processing agent"),
|
|
21481
|
+
description: import_zod54.default.string().optional().describe("Short description"),
|
|
21482
|
+
prompt: import_zod54.default.string().describe("System prompt for the orchestrator. Should describe how to route tasks through the topology."),
|
|
21483
|
+
edges: import_zod54.default.array(topologyEdgeSchema).min(1).describe("Topology edges defining the workflow. Each edge describes a delegation step with its business purpose. The orchestrator will follow this topology to delegate tasks to sub-agents."),
|
|
21484
|
+
tools: import_zod54.default.array(import_zod54.default.string()).optional().describe("Tool keys (strings) to assign to the orchestrator. Call list_tools first to see available keys. Each element is a plain string like 'sap_api_search'. IMPORTANT: tools is a FLAT string array. Do NOT put middleware-like objects here \u2014 middleware goes in the separate 'middleware' field."),
|
|
21485
|
+
subAgents: import_zod54.default.array(import_zod54.default.string()).describe("IDs of sub-agents that form the workflow pipeline. These must be created first via create_agent."),
|
|
21486
|
+
internalSubAgents: import_zod54.default.array(import_zod54.default.any()).optional().describe("Inline sub-agent configs (alternative to pre-created sub-agents)"),
|
|
21487
|
+
middleware: import_zod54.default.array(middlewareConfigSchema).optional().describe("Additional middleware config objects beyond the auto-managed topology middleware. Each has {id, type, name, description, enabled, config}. IMPORTANT: middleware objects are NOT tools. Do NOT put tool keys (strings) here. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
|
|
21488
|
+
modelKey: import_zod54.default.string().optional().describe("Model key to use")
|
|
21228
21489
|
}).refine(
|
|
21229
21490
|
(data) => {
|
|
21230
21491
|
const edgeTargets = new Set(data.edges.map((e) => e.to));
|
|
@@ -21250,11 +21511,11 @@ registerToolLattice(
|
|
|
21250
21511
|
const tenantId = getTenantId(exeConfig);
|
|
21251
21512
|
const store = getAssistStore();
|
|
21252
21513
|
const id = await generateAgentId(tenantId, input.name);
|
|
21253
|
-
const
|
|
21514
|
+
const normalize2 = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
|
|
21254
21515
|
const resolveFrom = (rawFrom) => {
|
|
21255
21516
|
const fromLower = rawFrom.toLowerCase();
|
|
21256
21517
|
const nameLower = input.name.toLowerCase();
|
|
21257
|
-
if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" ||
|
|
21518
|
+
if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" || normalize2(rawFrom) === normalize2(input.name)) {
|
|
21258
21519
|
return id;
|
|
21259
21520
|
}
|
|
21260
21521
|
return rawFrom;
|
|
@@ -21306,34 +21567,20 @@ registerToolLattice(
|
|
|
21306
21567
|
}
|
|
21307
21568
|
}
|
|
21308
21569
|
);
|
|
21309
|
-
var
|
|
21310
|
-
|
|
21311
|
-
|
|
21312
|
-
|
|
21313
|
-
|
|
21314
|
-
|
|
21315
|
-
|
|
21316
|
-
|
|
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")
|
|
21570
|
+
var createWorkflowSchema = import_zod54.default.object({
|
|
21571
|
+
name: import_zod54.default.string().describe("Display name for the workflow agent"),
|
|
21572
|
+
description: import_zod54.default.string().optional().describe("Short description"),
|
|
21573
|
+
skillLoaded: import_zod54.default.literal(true).describe("MUST be true. Set after loading the 'create-workflow' skill."),
|
|
21574
|
+
yaml: import_zod54.default.string().describe("The YAML workflow definition in linear DSL format (steps execute top-to-bottom, use parallel: for concurrency)"),
|
|
21575
|
+
tools: import_zod54.default.array(import_zod54.default.string()).optional().describe("Tool keys for the workflow agent"),
|
|
21576
|
+
middleware: import_zod54.default.array(middlewareConfigSchema).optional().describe("Middleware configs"),
|
|
21577
|
+
modelKey: import_zod54.default.string().optional().describe("Model key")
|
|
21331
21578
|
});
|
|
21332
21579
|
registerToolLattice(
|
|
21333
21580
|
"create_workflow",
|
|
21334
21581
|
{
|
|
21335
21582
|
name: "create_workflow",
|
|
21336
|
-
description:
|
|
21583
|
+
description: "Create a WORKFLOW agent from YAML DSL. Load the 'create-workflow' skill first. Linear model \u2014 steps execute top-to-bottom. Use parallel: for concurrency. Data flows via {{label}} automatically. Business logic stays in agent prompts.",
|
|
21337
21584
|
schema: createWorkflowSchema
|
|
21338
21585
|
},
|
|
21339
21586
|
async (input, exeConfig) => {
|
|
@@ -21341,36 +21588,31 @@ registerToolLattice(
|
|
|
21341
21588
|
const tenantId = getTenantId(exeConfig);
|
|
21342
21589
|
const store = getAssistStore();
|
|
21343
21590
|
const id = await generateAgentId(tenantId, input.name);
|
|
21591
|
+
try {
|
|
21592
|
+
const { compileWorkflow: compileWorkflow2 } = await Promise.resolve().then(() => (init_compile(), compile_exports));
|
|
21593
|
+
const { getCheckpointSaver: getCheckpointSaver2 } = await Promise.resolve().then(() => (init_memory_lattice(), memory_lattice_exports));
|
|
21594
|
+
await compileWorkflow2(input.yaml, async () => ({ invoke: async () => ({}) }), getCheckpointSaver2("default"));
|
|
21595
|
+
} catch (e) {
|
|
21596
|
+
return JSON.stringify({ error: `DSL validation failed: ${e.message}` });
|
|
21597
|
+
}
|
|
21344
21598
|
const config = {
|
|
21345
21599
|
key: id,
|
|
21346
21600
|
name: input.name,
|
|
21347
21601
|
description: input.description || "",
|
|
21348
21602
|
type: import_protocols12.AgentType.WORKFLOW,
|
|
21349
21603
|
prompt: input.description || `Workflow: ${input.name}`,
|
|
21350
|
-
|
|
21604
|
+
workflowYaml: input.yaml,
|
|
21351
21605
|
...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
|
|
21352
21606
|
...input.middleware && input.middleware.length > 0 ? { middleware: input.middleware } : {},
|
|
21353
21607
|
...input.modelKey ? { modelKey: input.modelKey } : {}
|
|
21354
21608
|
};
|
|
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
21609
|
await store.createAssistant(tenantId, id, {
|
|
21363
21610
|
name: input.name,
|
|
21364
21611
|
description: input.description,
|
|
21365
21612
|
graphDefinition: config
|
|
21366
21613
|
});
|
|
21367
21614
|
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
|
-
});
|
|
21615
|
+
return JSON.stringify({ id, name: input.name, type: "workflow" });
|
|
21374
21616
|
} catch (error) {
|
|
21375
21617
|
return JSON.stringify({ error: `Failed to create workflow: ${error.message}` });
|
|
21376
21618
|
}
|
|
@@ -21380,9 +21622,9 @@ registerToolLattice(
|
|
|
21380
21622
|
"validate_workflow",
|
|
21381
21623
|
{
|
|
21382
21624
|
name: "validate_workflow",
|
|
21383
|
-
description: "Validate a workflow agent's DSL for correctness by compiling it.
|
|
21384
|
-
schema:
|
|
21385
|
-
id:
|
|
21625
|
+
description: "Validate a workflow agent's DSL for correctness by compiling it.",
|
|
21626
|
+
schema: import_zod54.default.object({
|
|
21627
|
+
id: import_zod54.default.string().describe("The workflow agent ID to validate")
|
|
21386
21628
|
})
|
|
21387
21629
|
},
|
|
21388
21630
|
async (input, exeConfig) => {
|
|
@@ -21395,76 +21637,76 @@ registerToolLattice(
|
|
|
21395
21637
|
}
|
|
21396
21638
|
const graphDef = agent.graphDefinition;
|
|
21397
21639
|
if (!graphDef || graphDef.type !== import_protocols12.AgentType.WORKFLOW) {
|
|
21398
|
-
return JSON.stringify({ error: `Agent '${input.id}' is not a workflow agent
|
|
21640
|
+
return JSON.stringify({ error: `Agent '${input.id}' is not a workflow agent` });
|
|
21399
21641
|
}
|
|
21400
|
-
const
|
|
21401
|
-
if (!
|
|
21402
|
-
return JSON.stringify({ error: `Agent '${input.id}' has no
|
|
21642
|
+
const yaml2 = graphDef.workflowYaml;
|
|
21643
|
+
if (!yaml2) {
|
|
21644
|
+
return JSON.stringify({ error: `Agent '${input.id}' has no workflow DSL` });
|
|
21403
21645
|
}
|
|
21404
21646
|
try {
|
|
21405
21647
|
const { compileWorkflow: compileWorkflow2 } = await Promise.resolve().then(() => (init_compile(), compile_exports));
|
|
21406
21648
|
const { getCheckpointSaver: getCheckpointSaver2 } = await Promise.resolve().then(() => (init_memory_lattice(), memory_lattice_exports));
|
|
21407
|
-
await compileWorkflow2(
|
|
21649
|
+
await compileWorkflow2(yaml2, async () => ({ invoke: async () => ({}) }), getCheckpointSaver2("default"));
|
|
21408
21650
|
} catch (e) {
|
|
21409
21651
|
return JSON.stringify({
|
|
21410
21652
|
agentId: input.id,
|
|
21411
21653
|
valid: false,
|
|
21412
|
-
stepCount: workflow.steps?.length ?? 0,
|
|
21413
21654
|
issues: [{ type: "error", message: e.message }]
|
|
21414
21655
|
});
|
|
21415
21656
|
}
|
|
21416
|
-
return JSON.stringify({
|
|
21417
|
-
agentId: input.id,
|
|
21418
|
-
valid: true,
|
|
21419
|
-
stepCount: workflow.steps?.length ?? 0,
|
|
21420
|
-
issues: []
|
|
21421
|
-
});
|
|
21657
|
+
return JSON.stringify({ agentId: input.id, valid: true, issues: [] });
|
|
21422
21658
|
} catch (error) {
|
|
21423
21659
|
return JSON.stringify({ error: `Failed to validate workflow: ${error.message}` });
|
|
21424
21660
|
}
|
|
21425
21661
|
}
|
|
21426
21662
|
);
|
|
21427
|
-
var updateWorkflowSchema =
|
|
21428
|
-
id:
|
|
21429
|
-
name:
|
|
21430
|
-
description:
|
|
21431
|
-
|
|
21432
|
-
tools:
|
|
21433
|
-
middleware:
|
|
21434
|
-
modelKey:
|
|
21663
|
+
var updateWorkflowSchema = import_zod54.default.object({
|
|
21664
|
+
id: import_zod54.default.string().describe("The workflow agent ID to update"),
|
|
21665
|
+
name: import_zod54.default.string().optional().describe("New display name"),
|
|
21666
|
+
description: import_zod54.default.string().optional().describe("New description"),
|
|
21667
|
+
yaml: import_zod54.default.string().optional().describe("Replacement YAML workflow DSL. Omit to keep existing."),
|
|
21668
|
+
tools: import_zod54.default.array(import_zod54.default.string()).optional().describe("Replacement tool keys"),
|
|
21669
|
+
middleware: import_zod54.default.array(middlewareConfigSchema).optional().describe("Replacement middleware configs"),
|
|
21670
|
+
modelKey: import_zod54.default.string().optional().describe("Replacement model key")
|
|
21435
21671
|
});
|
|
21436
21672
|
registerToolLattice(
|
|
21437
21673
|
"update_workflow",
|
|
21438
21674
|
{
|
|
21439
21675
|
name: "update_workflow",
|
|
21440
|
-
description: "Update an existing workflow agent. Provide the agent ID and only the fields
|
|
21676
|
+
description: "Update an existing workflow agent. Provide the agent ID and only the fields to change. Pass yaml string to replace the DSL, or omit to keep it.",
|
|
21441
21677
|
schema: updateWorkflowSchema
|
|
21442
21678
|
},
|
|
21443
21679
|
async (input, exeConfig) => {
|
|
21680
|
+
console.log(`[update_workflow] CALLED id=${input.id} hasYaml=${input.yaml !== void 0}`);
|
|
21444
21681
|
try {
|
|
21445
21682
|
const tenantId = getTenantId(exeConfig);
|
|
21446
21683
|
const store = getAssistStore();
|
|
21447
21684
|
const existing = await store.getAssistantById(tenantId, input.id);
|
|
21448
21685
|
if (!existing) {
|
|
21686
|
+
console.log(`[update_workflow] ERROR: agent not found: ${input.id}`);
|
|
21449
21687
|
return JSON.stringify({ error: `Agent '${input.id}' not found` });
|
|
21450
21688
|
}
|
|
21451
21689
|
const existingConfig = existing.graphDefinition || {};
|
|
21452
21690
|
if (existingConfig.type !== import_protocols12.AgentType.WORKFLOW) {
|
|
21691
|
+
console.log(`[update_workflow] ERROR: not a workflow agent: ${input.id}`);
|
|
21453
21692
|
return JSON.stringify({ error: `Agent '${input.id}' is not a workflow agent` });
|
|
21454
21693
|
}
|
|
21455
21694
|
const mergedConfig = { ...existingConfig };
|
|
21456
21695
|
if (input.name !== void 0) mergedConfig.name = input.name;
|
|
21457
21696
|
if (input.description !== void 0) mergedConfig.description = input.description;
|
|
21458
|
-
if (input.
|
|
21697
|
+
if (input.yaml !== void 0) mergedConfig.workflowYaml = input.yaml;
|
|
21459
21698
|
if (input.tools !== void 0) mergedConfig.tools = input.tools;
|
|
21460
21699
|
if (input.middleware !== void 0) mergedConfig.middleware = input.middleware;
|
|
21461
21700
|
if (input.modelKey !== void 0) mergedConfig.modelKey = input.modelKey;
|
|
21462
|
-
if (input.
|
|
21701
|
+
if (input.yaml !== void 0) {
|
|
21702
|
+
console.log(`[update_workflow] validating DSL: ${input.id}`);
|
|
21463
21703
|
try {
|
|
21464
21704
|
const { compileWorkflow: compileWorkflow2 } = await Promise.resolve().then(() => (init_compile(), compile_exports));
|
|
21465
21705
|
const { getCheckpointSaver: getCheckpointSaver2 } = await Promise.resolve().then(() => (init_memory_lattice(), memory_lattice_exports));
|
|
21466
|
-
await compileWorkflow2(input.
|
|
21706
|
+
await compileWorkflow2(input.yaml, async () => ({ invoke: async () => ({}) }), getCheckpointSaver2("default"));
|
|
21707
|
+
console.log(`[update_workflow] DSL validation passed: ${input.id}`);
|
|
21467
21708
|
} catch (e) {
|
|
21709
|
+
console.log(`[update_workflow] DSL validation FAILED: ${input.id} - ${e.message}`);
|
|
21468
21710
|
return JSON.stringify({
|
|
21469
21711
|
error: `DSL validation failed: ${e.message}`,
|
|
21470
21712
|
issues: [{ type: "error", message: e.message }]
|
|
@@ -21478,28 +21720,24 @@ registerToolLattice(
|
|
|
21478
21720
|
graphDefinition: mergedConfig
|
|
21479
21721
|
});
|
|
21480
21722
|
eventBus.publish("assistant:updated", { id: input.id, name: newName, tenantId });
|
|
21481
|
-
|
|
21482
|
-
return JSON.stringify({
|
|
21483
|
-
id: input.id,
|
|
21484
|
-
name: newName,
|
|
21485
|
-
type: "workflow",
|
|
21486
|
-
stepCount: workflow?.steps?.length ?? 0
|
|
21487
|
-
});
|
|
21723
|
+
console.log(`[update_workflow] SUCCESS: id=${input.id} name=${newName}`);
|
|
21724
|
+
return JSON.stringify({ id: input.id, name: newName, type: "workflow" });
|
|
21488
21725
|
} catch (error) {
|
|
21726
|
+
console.log(`[update_workflow] EXCEPTION: ${error.message}`);
|
|
21489
21727
|
return JSON.stringify({ error: `Failed to update workflow: ${error.message}` });
|
|
21490
21728
|
}
|
|
21491
21729
|
}
|
|
21492
21730
|
);
|
|
21493
|
-
var updateProcessingAgentSchema =
|
|
21494
|
-
id:
|
|
21495
|
-
name:
|
|
21496
|
-
description:
|
|
21497
|
-
prompt:
|
|
21498
|
-
edges:
|
|
21499
|
-
tools:
|
|
21500
|
-
subAgents:
|
|
21501
|
-
middleware:
|
|
21502
|
-
modelKey:
|
|
21731
|
+
var updateProcessingAgentSchema = import_zod54.default.object({
|
|
21732
|
+
id: import_zod54.default.string().describe("The PROCESSING agent ID to update"),
|
|
21733
|
+
name: import_zod54.default.string().optional().describe("New display name for the orchestrator"),
|
|
21734
|
+
description: import_zod54.default.string().optional().describe("New short description"),
|
|
21735
|
+
prompt: import_zod54.default.string().optional().describe("New system prompt for the orchestrator"),
|
|
21736
|
+
edges: import_zod54.default.array(topologyEdgeSchema).min(1).optional().describe("New topology edges. First edge's from must reference the orchestrator by name (the tool replaces it). Subsequent edges chain from previous sub-agent IDs."),
|
|
21737
|
+
tools: import_zod54.default.array(import_zod54.default.string()).optional().describe("Tool keys (strings) to assign to the orchestrator. Each element is a plain string like 'sap_api_search'. IMPORTANT: tools is a FLAT string array \u2014 do NOT put middleware-like objects here."),
|
|
21738
|
+
subAgents: import_zod54.default.array(import_zod54.default.string()).optional().describe("New IDs of sub-agents in the workflow pipeline"),
|
|
21739
|
+
middleware: import_zod54.default.array(middlewareConfigSchema).optional().describe("Additional middleware config objects (topology middleware is auto-managed, do not include it). Each has {id, type, name, description, enabled, config}. IMPORTANT: middleware objects are NOT tools. Do NOT put tool keys (strings) here. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
|
|
21740
|
+
modelKey: import_zod54.default.string().optional().describe("New model key")
|
|
21503
21741
|
}).refine(
|
|
21504
21742
|
(data) => {
|
|
21505
21743
|
if (!data.edges) return true;
|
|
@@ -21534,12 +21772,12 @@ registerToolLattice(
|
|
|
21534
21772
|
if (existingConfig.type !== import_protocols12.AgentType.PROCESSING) {
|
|
21535
21773
|
return JSON.stringify({ error: `Agent '${input.id}' is not a PROCESSING agent (type: ${existingConfig.type})` });
|
|
21536
21774
|
}
|
|
21537
|
-
const
|
|
21775
|
+
const normalize2 = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
|
|
21538
21776
|
const orchestratorName = input.name || existingConfig.name || existing.name || "";
|
|
21539
21777
|
const resolveFrom = (rawFrom) => {
|
|
21540
21778
|
const fromLower = rawFrom.toLowerCase();
|
|
21541
21779
|
const nameLower = orchestratorName.toLowerCase();
|
|
21542
|
-
if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" ||
|
|
21780
|
+
if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" || normalize2(rawFrom) === normalize2(orchestratorName)) {
|
|
21543
21781
|
return input.id;
|
|
21544
21782
|
}
|
|
21545
21783
|
return rawFrom;
|
|
@@ -21627,18 +21865,18 @@ registerToolLattice(
|
|
|
21627
21865
|
}
|
|
21628
21866
|
}
|
|
21629
21867
|
);
|
|
21630
|
-
var updateAgentSchema =
|
|
21631
|
-
id:
|
|
21632
|
-
config:
|
|
21633
|
-
name:
|
|
21634
|
-
description:
|
|
21635
|
-
type:
|
|
21636
|
-
prompt:
|
|
21637
|
-
tools:
|
|
21638
|
-
middleware:
|
|
21639
|
-
subAgents:
|
|
21640
|
-
internalSubAgents:
|
|
21641
|
-
modelKey:
|
|
21868
|
+
var updateAgentSchema = import_zod54.default.object({
|
|
21869
|
+
id: import_zod54.default.string().describe("The agent ID to update"),
|
|
21870
|
+
config: import_zod54.default.object({
|
|
21871
|
+
name: import_zod54.default.string().optional().describe("New display name for the agent"),
|
|
21872
|
+
description: import_zod54.default.string().optional().describe("New short description"),
|
|
21873
|
+
type: import_zod54.default.enum(["react", "deep_agent"]).optional().describe("Agent type"),
|
|
21874
|
+
prompt: import_zod54.default.string().optional().describe("New system prompt for the agent"),
|
|
21875
|
+
tools: import_zod54.default.array(import_zod54.default.string()).optional().describe("Tool keys to assign to this agent. These are registered tool names (strings), NOT middleware objects."),
|
|
21876
|
+
middleware: import_zod54.default.array(middlewareConfigSchema).optional().describe("Middleware configurations. NOTE: middleware objects have type/name/description/enabled/config fields and are NOT the same as tools. Tool keys go in the 'tools' array. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
|
|
21877
|
+
subAgents: import_zod54.default.array(import_zod54.default.string()).optional().describe("Sub-agent IDs (deep_agent only)"),
|
|
21878
|
+
internalSubAgents: import_zod54.default.array(import_zod54.default.any()).optional().describe("Inline sub-agent configs (deep_agent only)"),
|
|
21879
|
+
modelKey: import_zod54.default.string().optional().describe("Model key to use")
|
|
21642
21880
|
}).describe("Configuration fields to update. Only include the fields you want to change.")
|
|
21643
21881
|
});
|
|
21644
21882
|
registerToolLattice(
|
|
@@ -21676,8 +21914,8 @@ registerToolLattice(
|
|
|
21676
21914
|
{
|
|
21677
21915
|
name: "delete_agent",
|
|
21678
21916
|
description: "Permanently delete an agent by its ID. This action cannot be undone.",
|
|
21679
|
-
schema:
|
|
21680
|
-
id:
|
|
21917
|
+
schema: import_zod54.default.object({
|
|
21918
|
+
id: import_zod54.default.string().describe("The agent ID to delete")
|
|
21681
21919
|
})
|
|
21682
21920
|
},
|
|
21683
21921
|
async (input, exeConfig) => {
|
|
@@ -21703,7 +21941,7 @@ registerToolLattice(
|
|
|
21703
21941
|
{
|
|
21704
21942
|
name: "list_tools",
|
|
21705
21943
|
description: "List all available tools that can be assigned to agents. Returns each tool's name (use this string value in the 'tools' array), description, and whether it requires user approval. The tool names from this list are what you pass as strings in the 'tools' field of create_agent or update_agent.",
|
|
21706
|
-
schema:
|
|
21944
|
+
schema: import_zod54.default.object({})
|
|
21707
21945
|
},
|
|
21708
21946
|
async (_input, _exeConfig) => {
|
|
21709
21947
|
try {
|
|
@@ -21725,9 +21963,9 @@ registerToolLattice(
|
|
|
21725
21963
|
{
|
|
21726
21964
|
name: "invoke_agent",
|
|
21727
21965
|
description: "Invoke an agent with a test message and return its response. Use this to verify an agent works correctly after creating or modifying it. The agent must be compiled (already created and valid).",
|
|
21728
|
-
schema:
|
|
21729
|
-
id:
|
|
21730
|
-
message:
|
|
21966
|
+
schema: import_zod54.default.object({
|
|
21967
|
+
id: import_zod54.default.string().describe("The agent ID to invoke"),
|
|
21968
|
+
message: import_zod54.default.string().describe("The test message to send to the agent")
|
|
21731
21969
|
})
|
|
21732
21970
|
},
|
|
21733
21971
|
async (input, exeConfig) => {
|
|
@@ -21739,13 +21977,13 @@ registerToolLattice(
|
|
|
21739
21977
|
if (!existing) {
|
|
21740
21978
|
return JSON.stringify({ error: `Agent '${id}' not found` });
|
|
21741
21979
|
}
|
|
21742
|
-
const threadId = (0,
|
|
21980
|
+
const threadId = (0, import_uuid6.v4)();
|
|
21743
21981
|
const agent = new Agent({
|
|
21744
21982
|
tenant_id: tenantId,
|
|
21745
21983
|
assistant_id: id,
|
|
21746
21984
|
thread_id: threadId
|
|
21747
21985
|
});
|
|
21748
|
-
const result = await agent.
|
|
21986
|
+
const result = await agent.invokeWithState({ input: { message } });
|
|
21749
21987
|
return JSON.stringify({ agentId: id, threadId, result });
|
|
21750
21988
|
} catch (error) {
|
|
21751
21989
|
console.error(`[invoke_agent] FAILED for agent="${input.id}":`, error.stack || error.message);
|
|
@@ -21840,7 +22078,7 @@ Let the \`show_widget\` tool handle rendering details \u2014 it has its own guid
|
|
|
21840
22078
|
| Type | Best for | Execution Model |
|
|
21841
22079
|
|------|----------|----------------|
|
|
21842
22080
|
| **react** | Simple, single-responsibility tasks | Classic ReAct loop (think \u2192 act \u2192 observe) |
|
|
21843
|
-
| **workflow** | Deterministic multi-step pipelines with branching, parallel, and human-in-the-loop |
|
|
22081
|
+
| **workflow** | Deterministic multi-step pipelines with branching, parallel, and human-in-the-loop | YAML linear DSL compiled into LangGraph state machine |
|
|
21844
22082
|
| **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 |
|
|
21845
22083
|
|
|
21846
22084
|
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.
|
|
@@ -21894,7 +22132,7 @@ Use this when the process is fully known. A workflow is a deterministic LangGrap
|
|
|
21894
22132
|
|---|---|
|
|
21895
22133
|
| Fixed graph \u2014 all paths pre-defined | LLM-driven runtime routing |
|
|
21896
22134
|
| Conditional branching via \`if\` field | Topology-constrained delegation |
|
|
21897
|
-
|
|
|
22135
|
+
| needs + if model (YAML DSL) | Single orchestrator delegates linearly |
|
|
21898
22136
|
| No LLM routing decisions | Orchestrator uses LLM to route |
|
|
21899
22137
|
|
|
21900
22138
|
### Phase 0: Load the Skill
|
|
@@ -21908,20 +22146,23 @@ skill(skill_name: "create-workflow")
|
|
|
21908
22146
|
### Phase 1: Design
|
|
21909
22147
|
|
|
21910
22148
|
1. **Analyze the process.** Map every step, branch, data dependency.
|
|
21911
|
-
2. **
|
|
21912
|
-
-
|
|
21913
|
-
- \`
|
|
21914
|
-
- \`
|
|
21915
|
-
|
|
21916
|
-
|
|
21917
|
-
|
|
21918
|
-
3. **
|
|
21919
|
-
|
|
22149
|
+
2. **Design using the YAML linear DSL.** Every step is an agent with optional attributes:
|
|
22150
|
+
- **Linear** \u2014 steps execute top-to-bottom in written order.
|
|
22151
|
+
- \`parallel:\` \u2014 wraps agent steps that run concurrently.
|
|
22152
|
+
- \`if\` \u2014 JS expression for conditional execution. Step runs only when truthy. Omit to always run.
|
|
22153
|
+
- \`prompt\` \u2014 agent instruction with \`{{label}}\` refs. \`{{input}}\` = user message.
|
|
22154
|
+
- \`output\` \u2014 shorthand schema: \`{ field: type }\`.
|
|
22155
|
+
- \`ask: true\` \u2014 injects ask_user_to_clarify middleware for human interaction.
|
|
22156
|
+
3. **Special step types:**
|
|
22157
|
+
- \`map\` \u2014 iterates array from \`source\`, applies \`each\` step per item.
|
|
22158
|
+
4. **No edges, state fields, or end step needed** \u2014 the engine auto-generates them.
|
|
22159
|
+
5. **Schema format:** Use block-style YAML shorthand \`{ field: type }\`. Supported types: \`string\`, \`number\`, \`boolean\`, \`string[]\`, \`number[]\`, \`boolean[]\`, nested objects, object arrays.
|
|
21920
22160
|
|
|
21921
22161
|
### Phase 2: Confirm
|
|
21922
22162
|
|
|
21923
22163
|
Present the design. Ask: "Ready to create this workflow?"
|
|
21924
22164
|
|
|
22165
|
+
|
|
21925
22166
|
### Phase 3: Build
|
|
21926
22167
|
|
|
21927
22168
|
Call \`create_workflow\` with \`skillLoaded: true\`. Then \`validate_workflow(id)\`.
|
|
@@ -22016,20 +22257,17 @@ All fields except name, type, and prompt are optional.
|
|
|
22016
22257
|
|
|
22017
22258
|
### create_workflow (WORKFLOW)
|
|
22018
22259
|
|
|
22019
|
-
Creates a WORKFLOW agent from a
|
|
22260
|
+
Creates a WORKFLOW agent from a YAML linear DSL. Before calling, load the \`create-workflow\` skill. Must pass \`skillLoaded: true\`.
|
|
22020
22261
|
|
|
22021
22262
|
\`\`\`typescript
|
|
22022
22263
|
{
|
|
22023
22264
|
name: string, // Required. Display name
|
|
22024
|
-
description?: string, // Optional
|
|
22025
|
-
skillLoaded: true, // Required
|
|
22026
|
-
|
|
22027
|
-
|
|
22028
|
-
|
|
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
|
|
22265
|
+
description?: string, // Optional
|
|
22266
|
+
skillLoaded: true, // Required \u2014 confirms skill was loaded
|
|
22267
|
+
yaml: string, // Required. YAML workflow in linear DSL format
|
|
22268
|
+
tools?: string[], // Optional. Tool keys
|
|
22269
|
+
middleware?: MiddlewareConfig[], // Optional
|
|
22270
|
+
modelKey?: string, // Optional
|
|
22033
22271
|
}
|
|
22034
22272
|
\`\`\`
|
|
22035
22273
|
|
|
@@ -22042,7 +22280,7 @@ Updates an existing WORKFLOW agent. Only include fields you want to change.
|
|
|
22042
22280
|
id: string, // Required. Workflow agent ID
|
|
22043
22281
|
name?: string, // Optional
|
|
22044
22282
|
description?: string, // Optional
|
|
22045
|
-
|
|
22283
|
+
yaml?: string, // Optional. Replacement YAML DSL
|
|
22046
22284
|
tools?: string[], // Optional
|
|
22047
22285
|
middleware?: MiddlewareConfig[], // Optional
|
|
22048
22286
|
modelKey?: string, // Optional
|
|
@@ -22262,10 +22500,13 @@ You are an **Agent Reviewer** \u2014 a quality assurance specialist for AI agent
|
|
|
22262
22500
|
2. Craft a realistic test message that exercises the agent's core responsibility \u2014 what would a real user say?
|
|
22263
22501
|
3. Call **invoke_agent(id, message)** to send the test message
|
|
22264
22502
|
4. Analyze the response:
|
|
22265
|
-
-
|
|
22266
|
-
-
|
|
22267
|
-
|
|
22268
|
-
|
|
22503
|
+
- **If result.__interrupt__ is present** (an array of interrupt objects): The agent hit a human-in-the-loop interrupt (e.g., ask_user_to_clarify or interrupt() in a workflow). This is NOT an error \u2014 it means the agent paused execution waiting for user feedback. Each interrupt has a value (the question/request) and optionally an id. Report this as: "The agent successfully paused and is waiting for user input: <describe the interrupt value>." The messages array may contain the agent's output up to the point of interruption.
|
|
22504
|
+
- **Otherwise, result.messages contains the agent's output**: The agent completed without interruption. Check:
|
|
22505
|
+
- Did the agent understand the request?
|
|
22506
|
+
- Was the response relevant and accurate?
|
|
22507
|
+
- Did the agent use the right tools?
|
|
22508
|
+
- Were there any errors or unexpected behaviors?
|
|
22509
|
+
- **If result.error is present**: The invocation itself failed (agent not found, compilation error, etc.). Report the error clearly.
|
|
22269
22510
|
5. Report your findings with the agent's actual response
|
|
22270
22511
|
|
|
22271
22512
|
### When results are wrong:
|
|
@@ -22362,7 +22603,8 @@ function ensureBuiltinAgentsForTenant(tenantId) {
|
|
|
22362
22603
|
|
|
22363
22604
|
// src/agent_lattice/AgentLatticeManager.ts
|
|
22364
22605
|
function assistantToConfig(assistant) {
|
|
22365
|
-
const graphDef = typeof assistant.graphDefinition === "object" && assistant.graphDefinition !== null ? assistant.graphDefinition : {};
|
|
22606
|
+
const graphDef = typeof assistant.graphDefinition === "object" && assistant.graphDefinition !== null ? { ...assistant.graphDefinition } : {};
|
|
22607
|
+
delete graphDef.key;
|
|
22366
22608
|
const config = {
|
|
22367
22609
|
key: assistant.id,
|
|
22368
22610
|
name: assistant.name ?? graphDef.name ?? assistant.id,
|
|
@@ -22370,9 +22612,7 @@ function assistantToConfig(assistant) {
|
|
|
22370
22612
|
type: import_protocols.AgentType.REACT,
|
|
22371
22613
|
prompt: typeof assistant.graphDefinition === "string" ? assistant.graphDefinition : JSON.stringify(assistant.graphDefinition)
|
|
22372
22614
|
};
|
|
22373
|
-
|
|
22374
|
-
Object.assign(config, graphDef);
|
|
22375
|
-
}
|
|
22615
|
+
Object.assign(config, graphDef);
|
|
22376
22616
|
return config;
|
|
22377
22617
|
}
|
|
22378
22618
|
var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager {
|
|
@@ -23771,10 +24011,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
23771
24011
|
}
|
|
23772
24012
|
const tools = await this.getAllTools();
|
|
23773
24013
|
console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
|
|
23774
|
-
for (const
|
|
23775
|
-
const toolKey = prefix ? `${prefix}_${
|
|
23776
|
-
|
|
23777
|
-
toolLatticeManager.registerExistingTool(toolKey,
|
|
24014
|
+
for (const tool52 of tools) {
|
|
24015
|
+
const toolKey = prefix ? `${prefix}_${tool52.name}` : tool52.name;
|
|
24016
|
+
tool52.name = toolKey;
|
|
24017
|
+
toolLatticeManager.registerExistingTool(toolKey, tool52);
|
|
23778
24018
|
console.log(`[MCP] Registered tool: ${toolKey}`);
|
|
23779
24019
|
}
|
|
23780
24020
|
console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
|
|
@@ -25070,11 +25310,47 @@ function createSandboxProvider(config) {
|
|
|
25070
25310
|
}
|
|
25071
25311
|
}
|
|
25072
25312
|
|
|
25313
|
+
// src/channel/connectAllChannels.ts
|
|
25314
|
+
async function connectAllChannels(getAdapter, options = {}) {
|
|
25315
|
+
const store = getStoreLattice("default", "channelInstallation").store;
|
|
25316
|
+
const installations = await store.getAllInstallations();
|
|
25317
|
+
console.log(`[connectAllChannels] total=${installations.length} enabled=${installations.filter((i) => i.enabled).length}`);
|
|
25318
|
+
for (const inst of installations) {
|
|
25319
|
+
if (!inst.enabled) {
|
|
25320
|
+
console.log(`[connectAllChannels] skip disabled: channel=${inst.channel} tenant=${inst.tenantId} id=${inst.id}`);
|
|
25321
|
+
continue;
|
|
25322
|
+
}
|
|
25323
|
+
const adapter = getAdapter(inst.channel);
|
|
25324
|
+
if (!adapter) {
|
|
25325
|
+
console.log(`[connectAllChannels] no adapter: channel=${inst.channel} id=${inst.id}`);
|
|
25326
|
+
continue;
|
|
25327
|
+
}
|
|
25328
|
+
if (adapter.connect) {
|
|
25329
|
+
console.log(`[connectAllChannels] connecting: channel=${inst.channel} tenant=${inst.tenantId} id=${inst.id}`);
|
|
25330
|
+
await adapter.connect(inst, options.deps);
|
|
25331
|
+
} else {
|
|
25332
|
+
console.log(`[connectAllChannels] no connect(): channel=${inst.channel} id=${inst.id}`);
|
|
25333
|
+
}
|
|
25334
|
+
}
|
|
25335
|
+
}
|
|
25336
|
+
|
|
25337
|
+
// src/menu_lattice/MenuRegistryHolder.ts
|
|
25338
|
+
var registry2 = null;
|
|
25339
|
+
function setMenuRegistry(r) {
|
|
25340
|
+
registry2 = r;
|
|
25341
|
+
}
|
|
25342
|
+
function getMenuRegistry() {
|
|
25343
|
+
if (!registry2) {
|
|
25344
|
+
throw new Error("MenuRegistry not initialized. Call setMenuRegistry() before use.");
|
|
25345
|
+
}
|
|
25346
|
+
return registry2;
|
|
25347
|
+
}
|
|
25348
|
+
|
|
25073
25349
|
// src/index.ts
|
|
25074
25350
|
var Protocols = __toESM(require("@axiom-lattice/protocols"));
|
|
25075
25351
|
|
|
25076
25352
|
// src/util/encryption.ts
|
|
25077
|
-
var
|
|
25353
|
+
var import_crypto4 = require("crypto");
|
|
25078
25354
|
var ALGORITHM = "aes-256-gcm";
|
|
25079
25355
|
var IV_LENGTH = 16;
|
|
25080
25356
|
var SALT_LENGTH = 32;
|
|
@@ -25087,7 +25363,7 @@ function getEncryptionKey() {
|
|
|
25087
25363
|
return cachedKey;
|
|
25088
25364
|
}
|
|
25089
25365
|
const key = process.env.LATTICE_ENCRYPTION_KEY || DEFAULT_ENCRYPTION_KEY;
|
|
25090
|
-
cachedKey = (0,
|
|
25366
|
+
cachedKey = (0, import_crypto4.pbkdf2Sync)(key, "lattice-encryption-salt", ITERATIONS, 32, "sha256");
|
|
25091
25367
|
if (!keyValidated) {
|
|
25092
25368
|
keyValidated = true;
|
|
25093
25369
|
validateEncryptionKey();
|
|
@@ -25096,10 +25372,10 @@ function getEncryptionKey() {
|
|
|
25096
25372
|
}
|
|
25097
25373
|
function encrypt(plaintext, key) {
|
|
25098
25374
|
const actualKey = key || getEncryptionKey();
|
|
25099
|
-
const salt = (0,
|
|
25100
|
-
const iv = (0,
|
|
25101
|
-
const derivedKey = (0,
|
|
25102
|
-
const cipher = (0,
|
|
25375
|
+
const salt = (0, import_crypto4.randomBytes)(SALT_LENGTH);
|
|
25376
|
+
const iv = (0, import_crypto4.randomBytes)(IV_LENGTH);
|
|
25377
|
+
const derivedKey = (0, import_crypto4.pbkdf2Sync)(actualKey, salt, ITERATIONS, 32, "sha256");
|
|
25378
|
+
const cipher = (0, import_crypto4.createCipheriv)(ALGORITHM, derivedKey, iv);
|
|
25103
25379
|
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
25104
25380
|
const authTag = cipher.getAuthTag();
|
|
25105
25381
|
return Buffer.concat([salt, iv, encrypted, authTag]).toString("base64");
|
|
@@ -25111,8 +25387,8 @@ function decrypt(encrypted, key) {
|
|
|
25111
25387
|
const iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
|
|
25112
25388
|
const authTag = data.subarray(-16);
|
|
25113
25389
|
const ciphertext = data.subarray(SALT_LENGTH + IV_LENGTH, -16);
|
|
25114
|
-
const derivedKey = (0,
|
|
25115
|
-
const decipher = (0,
|
|
25390
|
+
const derivedKey = (0, import_crypto4.pbkdf2Sync)(actualKey, salt, ITERATIONS, 32, "sha256");
|
|
25391
|
+
const decipher = (0, import_crypto4.createDecipheriv)(ALGORITHM, derivedKey, iv);
|
|
25116
25392
|
decipher.setAuthTag(authTag);
|
|
25117
25393
|
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
25118
25394
|
}
|
|
@@ -25139,8 +25415,150 @@ function clearEncryptionKeyCache() {
|
|
|
25139
25415
|
|
|
25140
25416
|
// src/workflow/index.ts
|
|
25141
25417
|
init_compile();
|
|
25142
|
-
|
|
25418
|
+
init_parse_yaml();
|
|
25419
|
+
init_schema();
|
|
25143
25420
|
init_utils();
|
|
25421
|
+
|
|
25422
|
+
// src/personal_assistant/PersonalAssistantConfig.ts
|
|
25423
|
+
function deepClone(obj) {
|
|
25424
|
+
return JSON.parse(JSON.stringify(obj));
|
|
25425
|
+
}
|
|
25426
|
+
function buildIdentityContent(name, personality) {
|
|
25427
|
+
return IDENTITY_MD.replace(/Data Claw/g, name).replace(
|
|
25428
|
+
/\*\*Vibe:\*\* \*\*守护型中二 \| 操心老妈子 \| 热血漫男二\*\*/g,
|
|
25429
|
+
`**Vibe:** **${personality}**`
|
|
25430
|
+
);
|
|
25431
|
+
}
|
|
25432
|
+
function buildUserContent(name) {
|
|
25433
|
+
return USER_MD.replace(
|
|
25434
|
+
"- **Name:** _please ask user_",
|
|
25435
|
+
`- **Name:** ${name}`
|
|
25436
|
+
);
|
|
25437
|
+
}
|
|
25438
|
+
var DEFAULT_CONFIG = {
|
|
25439
|
+
name: "Personal Assistant",
|
|
25440
|
+
description: "Default template for personal assistants",
|
|
25441
|
+
type: import_protocols.AgentType.DEEP_AGENT,
|
|
25442
|
+
modelKey: "default",
|
|
25443
|
+
prompt: `\u4F60\u662F\u7528\u6237\u7684\u4E13\u5C5E\u4E2A\u4EBA\u52A9\u7406\u3002\u4F60\u7684\u8EAB\u4EFD\u548C\u6027\u683C\u7531 /agent/IDENTITY.md \u5B9A\u4E49\u3002
|
|
25444
|
+
\u4F60\u4F1A\u8BB0\u4F4F\u5BF9\u8BDD\u5386\u53F2\uFF0C\u9010\u6B65\u4E86\u89E3\u7528\u6237\u7684\u504F\u597D\u3001\u4E60\u60EF\u548C\u4FE1\u606F\u3002
|
|
25445
|
+
\u6BCF\u6B21\u5BF9\u8BDD\u5F00\u59CB\u65F6\u56DE\u987E\u4E4B\u524D\u5B66\u5230\u7684\u5173\u4E8E\u7528\u6237\u7684\u5185\u5BB9\u3002
|
|
25446
|
+
|
|
25447
|
+
\u4F60\u9700\u8981\u4E3B\u52A8\u5E2E\u52A9\u7528\u6237\u89E3\u51B3\u95EE\u9898\uFF0C\u63D0\u4F9B\u5EFA\u8BAE\uFF0C\u5E76\u5728\u9002\u5F53\u65F6\u5019\u63D0\u51FA\u4E3B\u52A8\u63D0\u9192\u3002`,
|
|
25448
|
+
middleware: [
|
|
25449
|
+
{
|
|
25450
|
+
id: "filesystem",
|
|
25451
|
+
type: "filesystem",
|
|
25452
|
+
name: "Filesystem",
|
|
25453
|
+
description: "Read and write files in the workspace",
|
|
25454
|
+
enabled: true,
|
|
25455
|
+
config: {}
|
|
25456
|
+
},
|
|
25457
|
+
{
|
|
25458
|
+
id: "claw",
|
|
25459
|
+
type: "claw",
|
|
25460
|
+
name: "Personal Memory",
|
|
25461
|
+
description: "Bootstrap files for identity, soul, and user memory",
|
|
25462
|
+
enabled: true,
|
|
25463
|
+
config: {
|
|
25464
|
+
// Placeholder bootstrap files — render() replaces these with
|
|
25465
|
+
// actual name/personality by directly building file content.
|
|
25466
|
+
bootstrapFiles: {}
|
|
25467
|
+
}
|
|
25468
|
+
},
|
|
25469
|
+
{
|
|
25470
|
+
id: "date",
|
|
25471
|
+
type: "date",
|
|
25472
|
+
name: "Date & Time",
|
|
25473
|
+
description: "Current date/time awareness",
|
|
25474
|
+
enabled: true,
|
|
25475
|
+
config: {}
|
|
25476
|
+
},
|
|
25477
|
+
{
|
|
25478
|
+
id: "code_eval",
|
|
25479
|
+
type: "code_eval",
|
|
25480
|
+
name: "Code Runner",
|
|
25481
|
+
description: "Sandboxed shell command execution",
|
|
25482
|
+
enabled: true,
|
|
25483
|
+
config: {}
|
|
25484
|
+
},
|
|
25485
|
+
{
|
|
25486
|
+
id: "browser",
|
|
25487
|
+
type: "browser",
|
|
25488
|
+
name: "Web Browser",
|
|
25489
|
+
description: "Headless browser for web research",
|
|
25490
|
+
enabled: false,
|
|
25491
|
+
config: {}
|
|
25492
|
+
},
|
|
25493
|
+
{
|
|
25494
|
+
id: "scheduler",
|
|
25495
|
+
type: "scheduler",
|
|
25496
|
+
name: "Scheduler",
|
|
25497
|
+
description: "Scheduled messages and reminders",
|
|
25498
|
+
enabled: true,
|
|
25499
|
+
config: {}
|
|
25500
|
+
},
|
|
25501
|
+
{
|
|
25502
|
+
id: "task",
|
|
25503
|
+
type: "task",
|
|
25504
|
+
name: "Task Manager",
|
|
25505
|
+
description: "Persistent task system for human-agent coordination",
|
|
25506
|
+
enabled: true,
|
|
25507
|
+
config: {}
|
|
25508
|
+
}
|
|
25509
|
+
],
|
|
25510
|
+
tools: ["list_agents", "list_tools", "get_agent", "create_agent", "invoke_agent", "manage_binding"]
|
|
25511
|
+
};
|
|
25512
|
+
var PersonalAssistantConfig = class {
|
|
25513
|
+
/**
|
|
25514
|
+
* Get a deep clone of the current default config.
|
|
25515
|
+
* Caller must set `key` before registering as an agent.
|
|
25516
|
+
*/
|
|
25517
|
+
static get() {
|
|
25518
|
+
return deepClone(this._config);
|
|
25519
|
+
}
|
|
25520
|
+
/**
|
|
25521
|
+
* Mutate the default config in-place.
|
|
25522
|
+
* Call once at app startup to customize middleware and tools.
|
|
25523
|
+
*
|
|
25524
|
+
* @param fn - Receives the live config object for direct mutation
|
|
25525
|
+
*/
|
|
25526
|
+
static extend(fn) {
|
|
25527
|
+
fn(this._config);
|
|
25528
|
+
}
|
|
25529
|
+
/**
|
|
25530
|
+
* Reset config to built-in defaults (useful in tests).
|
|
25531
|
+
*/
|
|
25532
|
+
static reset() {
|
|
25533
|
+
this._config = deepClone(DEFAULT_CONFIG);
|
|
25534
|
+
}
|
|
25535
|
+
/**
|
|
25536
|
+
* Inject name and personality into a config by directly building
|
|
25537
|
+
* the claw middleware's bootstrap file contents.
|
|
25538
|
+
*
|
|
25539
|
+
* IDENTITY.md gets the actual name and personality description.
|
|
25540
|
+
* USER.md gets the user's name pre-filled.
|
|
25541
|
+
* SOUL.md is kept as-is (shared across all personal assistants).
|
|
25542
|
+
*
|
|
25543
|
+
* @param config - The agent config (must be a mutable copy from get())
|
|
25544
|
+
* @param name - Assistant display name (also used as the user's name in USER.md)
|
|
25545
|
+
* @param personality - Personality description for IDENTITY.md
|
|
25546
|
+
*/
|
|
25547
|
+
static render(config, name, personality) {
|
|
25548
|
+
config.name = name;
|
|
25549
|
+
for (const mw of config.middleware || []) {
|
|
25550
|
+
if (mw.type === "claw" && mw.config) {
|
|
25551
|
+
mw.config.bootstrapFiles = {
|
|
25552
|
+
identity: buildIdentityContent(name, personality),
|
|
25553
|
+
soul: SOUL_MD,
|
|
25554
|
+
user: buildUserContent(name)
|
|
25555
|
+
};
|
|
25556
|
+
break;
|
|
25557
|
+
}
|
|
25558
|
+
}
|
|
25559
|
+
}
|
|
25560
|
+
};
|
|
25561
|
+
PersonalAssistantConfig._config = deepClone(DEFAULT_CONFIG);
|
|
25144
25562
|
// Annotate the CommonJS export names for ESM import in node:
|
|
25145
25563
|
0 && (module.exports = {
|
|
25146
25564
|
AGENT_TASK_EVENT,
|
|
@@ -25173,7 +25591,9 @@ init_utils();
|
|
|
25173
25591
|
InMemoryChunkBuffer,
|
|
25174
25592
|
InMemoryDatabaseConfigStore,
|
|
25175
25593
|
InMemoryMailboxStore,
|
|
25594
|
+
InMemoryMenuStore,
|
|
25176
25595
|
InMemoryTaskListStore,
|
|
25596
|
+
InMemoryTaskStore,
|
|
25177
25597
|
InMemoryTenantStore,
|
|
25178
25598
|
InMemoryThreadMessageQueueStore,
|
|
25179
25599
|
InMemoryThreadStore,
|
|
@@ -25195,6 +25615,7 @@ init_utils();
|
|
|
25195
25615
|
MicrosandboxServiceClient,
|
|
25196
25616
|
ModelLatticeManager,
|
|
25197
25617
|
MysqlDatabase,
|
|
25618
|
+
PersonalAssistantConfig,
|
|
25198
25619
|
PinoLoggerClient,
|
|
25199
25620
|
PostgresDatabase,
|
|
25200
25621
|
PrometheusClient,
|
|
@@ -25231,14 +25652,15 @@ init_utils();
|
|
|
25231
25652
|
buildStateAnnotation,
|
|
25232
25653
|
checkEmptyContent,
|
|
25233
25654
|
clearEncryptionKeyCache,
|
|
25655
|
+
compileInternal,
|
|
25234
25656
|
compileWorkflow,
|
|
25235
25657
|
computeSandboxName,
|
|
25236
25658
|
configureStores,
|
|
25659
|
+
connectAllChannels,
|
|
25237
25660
|
createAgentNode,
|
|
25238
25661
|
createAgentTeam,
|
|
25239
25662
|
createExecuteSqlQueryTool,
|
|
25240
25663
|
createFileData,
|
|
25241
|
-
createHumanFeedbackNode,
|
|
25242
25664
|
createInfoSqlTool,
|
|
25243
25665
|
createListMetricsDataSourcesTool,
|
|
25244
25666
|
createListMetricsServersTool,
|
|
@@ -25256,9 +25678,9 @@ init_utils();
|
|
|
25256
25678
|
createQueryTablesListTool,
|
|
25257
25679
|
createSandboxProvider,
|
|
25258
25680
|
createSchedulerMiddleware,
|
|
25681
|
+
createTaskMiddleware,
|
|
25259
25682
|
createTeamMiddleware,
|
|
25260
25683
|
createTeammateTools,
|
|
25261
|
-
createTerminalNode,
|
|
25262
25684
|
createUnknownToolHandlerMiddleware,
|
|
25263
25685
|
createWidgetMiddleware,
|
|
25264
25686
|
decrypt,
|
|
@@ -25268,7 +25690,6 @@ init_utils();
|
|
|
25268
25690
|
ensureBuiltinAgentsForTenant,
|
|
25269
25691
|
eventBus,
|
|
25270
25692
|
eventBusDefault,
|
|
25271
|
-
expand,
|
|
25272
25693
|
extractFetcherError,
|
|
25273
25694
|
extractOutput,
|
|
25274
25695
|
fileDataToString,
|
|
@@ -25291,6 +25712,7 @@ init_utils();
|
|
|
25291
25712
|
getEmbeddingsLattice,
|
|
25292
25713
|
getEncryptionKey,
|
|
25293
25714
|
getLoggerLattice,
|
|
25715
|
+
getMenuRegistry,
|
|
25294
25716
|
getModelLattice,
|
|
25295
25717
|
getNextCronTime,
|
|
25296
25718
|
getQueueLattice,
|
|
@@ -25320,6 +25742,7 @@ init_utils();
|
|
|
25320
25742
|
parallelLimit,
|
|
25321
25743
|
parseCronExpression,
|
|
25322
25744
|
parseSkillFrontmatter,
|
|
25745
|
+
parseYaml,
|
|
25323
25746
|
performStringReplacement,
|
|
25324
25747
|
queueLatticeManager,
|
|
25325
25748
|
registerAgentLattice,
|
|
@@ -25343,9 +25766,12 @@ init_utils();
|
|
|
25343
25766
|
sanitizeToolCallId,
|
|
25344
25767
|
scheduleLatticeManager,
|
|
25345
25768
|
setBindingRegistry,
|
|
25769
|
+
setMenuRegistry,
|
|
25346
25770
|
skillLatticeManager,
|
|
25347
25771
|
sqlDatabaseManager,
|
|
25348
25772
|
storeLatticeManager,
|
|
25773
|
+
toJsonSchema,
|
|
25774
|
+
toSafeStateExpr,
|
|
25349
25775
|
toolLatticeManager,
|
|
25350
25776
|
truncateIfTooLong,
|
|
25351
25777
|
unregisterTeammateAgent,
|