@aipack-ai/multi-agent 1.1.5 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +87 -5
- package/dist/index.js +828 -356
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -57,6 +57,10 @@ function createSharedContext(init) {
|
|
|
57
57
|
meta: init?.meta ?? {}
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
function storeOriginalInput(ctx, input) {
|
|
61
|
+
const inputText = typeof input === "string" ? input : input.message;
|
|
62
|
+
ctx.blackboard.set("__original_input__", inputText);
|
|
63
|
+
}
|
|
60
64
|
|
|
61
65
|
// ../agent/core/types.ts
|
|
62
66
|
function extractText(content) {
|
|
@@ -582,6 +586,14 @@ function resourceToMessage(resource) {
|
|
|
582
586
|
content: resource.content,
|
|
583
587
|
timestamp: resource.timestamp
|
|
584
588
|
};
|
|
589
|
+
case "state_snapshot": {
|
|
590
|
+
const text = typeof resource.content === "string" ? resource.content : extractText(resource.content);
|
|
591
|
+
return {
|
|
592
|
+
role: "stateSnapshot",
|
|
593
|
+
content: text,
|
|
594
|
+
timestamp: resource.timestamp
|
|
595
|
+
};
|
|
596
|
+
}
|
|
585
597
|
default:
|
|
586
598
|
return resource.content;
|
|
587
599
|
}
|
|
@@ -890,18 +902,25 @@ function withTimeoutSignal(parent, ms) {
|
|
|
890
902
|
() => controller.abort(new Error(`Tool execution timeout after ${ms}ms`)),
|
|
891
903
|
ms
|
|
892
904
|
);
|
|
905
|
+
let onAbort;
|
|
893
906
|
if (parent) {
|
|
894
907
|
if (parent.aborted) {
|
|
895
908
|
controller.abort(parent.reason);
|
|
896
909
|
} else {
|
|
897
|
-
parent.
|
|
898
|
-
|
|
899
|
-
() => controller.abort(parent.reason),
|
|
900
|
-
{ once: true }
|
|
901
|
-
);
|
|
910
|
+
onAbort = () => controller.abort(parent.reason);
|
|
911
|
+
parent.addEventListener("abort", onAbort, { once: true });
|
|
902
912
|
}
|
|
903
913
|
}
|
|
904
|
-
return {
|
|
914
|
+
return {
|
|
915
|
+
signal: controller.signal,
|
|
916
|
+
clear: () => {
|
|
917
|
+
clearTimeout(timer);
|
|
918
|
+
if (onAbort && parent) {
|
|
919
|
+
parent.removeEventListener("abort", onAbort);
|
|
920
|
+
onAbort = void 0;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
};
|
|
905
924
|
}
|
|
906
925
|
function buildImageContent(media) {
|
|
907
926
|
const dataMatch = media.match(/^data:([^;]+);base64,(.*)$/s);
|
|
@@ -935,6 +954,7 @@ var DEFAULT_COMPACTION_PROMPT = [
|
|
|
935
954
|
"5. \u76F4\u63A5\u8F93\u51FA\u6458\u8981\u6B63\u6587\uFF0C\u4E0D\u8981\u4EFB\u4F55\u524D\u540E\u7F00\u8BF4\u660E\u3002"
|
|
936
955
|
].join("\n");
|
|
937
956
|
var COMPACTION_USER_PREFIX = "[\u4EE5\u4E0B\u4E3A\u6B64\u524D\u5BF9\u8BDD\u5386\u53F2\u7684\u538B\u7F29\u6458\u8981\uFF0C\u4F5C\u4E3A\u4E0A\u4E0B\u6587\u53C2\u8003]";
|
|
957
|
+
var STATE_SNAPSHOT_USER_PREFIX = "[\u4EE5\u4E0B\u4E3A\u5F53\u524D\u72B6\u6001\u5FEB\u7167\uFF0C\u4F5C\u4E3A\u4E0A\u4E0B\u6587\u53C2\u8003]";
|
|
938
958
|
function messageToSummaryLine(msg) {
|
|
939
959
|
const clamp = (text) => text.length > COMPACTION_LINE_CLAMP ? `${text.slice(0, COMPACTION_LINE_CLAMP)}\u2026(\u5DF2\u622A\u65AD)` : text;
|
|
940
960
|
switch (msg.role) {
|
|
@@ -1446,7 +1466,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
1446
1466
|
toolCallId: toolCall.id
|
|
1447
1467
|
};
|
|
1448
1468
|
}
|
|
1449
|
-
const outcome = await this.
|
|
1469
|
+
const outcome = await this.executeToolCalls(
|
|
1450
1470
|
compilation,
|
|
1451
1471
|
toolCalls,
|
|
1452
1472
|
session.abortController.signal
|
|
@@ -1482,16 +1502,6 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
1482
1502
|
}
|
|
1483
1503
|
return outcome;
|
|
1484
1504
|
}
|
|
1485
|
-
/** 流式循环:执行工具调用,返回结果(消息由调用方追加) */
|
|
1486
|
-
async executeToolCallsStreaming(compilation, toolCalls, signal) {
|
|
1487
|
-
const outcome = await this.runTools(toolCalls, signal, compilation.request, compilation.traceId);
|
|
1488
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
1489
|
-
compilation.messages.push(
|
|
1490
|
-
this.buildToolResultMessage(toolCalls[i], outcome.results[i])
|
|
1491
|
-
);
|
|
1492
|
-
}
|
|
1493
|
-
return outcome;
|
|
1494
|
-
}
|
|
1495
1505
|
/**
|
|
1496
1506
|
* 执行一组工具调用:parallelToolCalls 为 true 时并行,否则串行。
|
|
1497
1507
|
* 返回 ToolExecutionOutcome:任一工具请求 terminate 即终止整个 run;
|
|
@@ -1849,9 +1859,14 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
1849
1859
|
const tools = Array.from(this._globalTools.values());
|
|
1850
1860
|
return {
|
|
1851
1861
|
systemPrompt: this._systemPrompt,
|
|
1852
|
-
// compactionSummary 为内部扩展 role,provider
|
|
1853
|
-
// user/assistant/toolResult,发出前统一转为带标注的 user 消息
|
|
1854
|
-
messages: messages.filter((m) => m.role !== "system").map((m) =>
|
|
1862
|
+
// compactionSummary / stateSnapshot 为内部扩展 role,provider 适配层
|
|
1863
|
+
// 仅支持 user/assistant/toolResult,发出前统一转为带标注的 user 消息
|
|
1864
|
+
messages: messages.filter((m) => m.role !== "system").map((m) => {
|
|
1865
|
+
const role = m.role;
|
|
1866
|
+
if (role === "compactionSummary") return this.compactionSummaryToUser(m);
|
|
1867
|
+
if (role === "stateSnapshot") return this.stateSnapshotToUser(m);
|
|
1868
|
+
return m;
|
|
1869
|
+
}),
|
|
1855
1870
|
tools: tools.length > 0 ? tools : void 0
|
|
1856
1871
|
};
|
|
1857
1872
|
}
|
|
@@ -1861,6 +1876,16 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
1861
1876
|
return {
|
|
1862
1877
|
role: "user",
|
|
1863
1878
|
content: `${COMPACTION_USER_PREFIX}
|
|
1879
|
+
${text}`,
|
|
1880
|
+
timestamp: msg.timestamp
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
/** stateSnapshot 消息 → user 消息(所有 provider 均兼容 user role) */
|
|
1884
|
+
stateSnapshotToUser(msg) {
|
|
1885
|
+
const text = typeof msg.content === "string" ? msg.content : extractText(msg.content);
|
|
1886
|
+
return {
|
|
1887
|
+
role: "user",
|
|
1888
|
+
content: `${STATE_SNAPSHOT_USER_PREFIX}
|
|
1864
1889
|
${text}`,
|
|
1865
1890
|
timestamp: msg.timestamp
|
|
1866
1891
|
};
|
|
@@ -2457,7 +2482,55 @@ function createRuntime(options) {
|
|
|
2457
2482
|
return AgentRuntime.create(options);
|
|
2458
2483
|
}
|
|
2459
2484
|
|
|
2485
|
+
// core/event-stream.ts
|
|
2486
|
+
function createEventStream(execute, sink) {
|
|
2487
|
+
const eventQueue = [];
|
|
2488
|
+
let resolveEvent = null;
|
|
2489
|
+
let done = false;
|
|
2490
|
+
const emit = (event) => {
|
|
2491
|
+
eventQueue.push(event);
|
|
2492
|
+
if (sink) {
|
|
2493
|
+
try {
|
|
2494
|
+
sink(event);
|
|
2495
|
+
} catch {
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
resolveEvent?.();
|
|
2499
|
+
};
|
|
2500
|
+
const graphPromise = execute(emit).finally(() => {
|
|
2501
|
+
done = true;
|
|
2502
|
+
resolveEvent?.();
|
|
2503
|
+
});
|
|
2504
|
+
return (async function* () {
|
|
2505
|
+
while (!done || eventQueue.length > 0) {
|
|
2506
|
+
if (eventQueue.length > 0) {
|
|
2507
|
+
yield eventQueue.shift();
|
|
2508
|
+
} else {
|
|
2509
|
+
await new Promise((resolve) => {
|
|
2510
|
+
resolveEvent = resolve;
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
await graphPromise;
|
|
2515
|
+
})();
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2460
2518
|
// core/executor.ts
|
|
2519
|
+
var GraphAbortedError = class extends Error {
|
|
2520
|
+
constructor() {
|
|
2521
|
+
super("AgentGraph: \u6267\u884C\u5DF2\u88AB\u4E2D\u6B62");
|
|
2522
|
+
this.name = "GraphAbortedError";
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
function toInputText(input) {
|
|
2526
|
+
return typeof input === "string" ? input : input.message;
|
|
2527
|
+
}
|
|
2528
|
+
var NodeTimeoutError = class extends Error {
|
|
2529
|
+
constructor(nodeId, timeoutMs) {
|
|
2530
|
+
super(`AgentGraph: \u8282\u70B9 "${nodeId}" \u6267\u884C\u8D85\u65F6\uFF08${timeoutMs}ms\uFF09`);
|
|
2531
|
+
this.name = "NodeTimeoutError";
|
|
2532
|
+
}
|
|
2533
|
+
};
|
|
2461
2534
|
var runtimeCache = /* @__PURE__ */ new WeakMap();
|
|
2462
2535
|
function ensureRuntime(node) {
|
|
2463
2536
|
let rt = runtimeCache.get(node);
|
|
@@ -2470,19 +2543,52 @@ function ensureRuntime(node) {
|
|
|
2470
2543
|
runtimeCache.set(node, rt);
|
|
2471
2544
|
return rt;
|
|
2472
2545
|
}
|
|
2473
|
-
async function
|
|
2546
|
+
async function executeNodeOnce(node, req) {
|
|
2474
2547
|
const runtime = ensureRuntime(node);
|
|
2548
|
+
if (node.timeoutMs != null && node.timeoutMs > 0) {
|
|
2549
|
+
let timer;
|
|
2550
|
+
try {
|
|
2551
|
+
return await Promise.race([
|
|
2552
|
+
runtime.run(req),
|
|
2553
|
+
new Promise((_, reject) => {
|
|
2554
|
+
timer = setTimeout(() => reject(new NodeTimeoutError(node.id, node.timeoutMs)), node.timeoutMs);
|
|
2555
|
+
})
|
|
2556
|
+
]);
|
|
2557
|
+
} finally {
|
|
2558
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
return runtime.run(req);
|
|
2562
|
+
}
|
|
2563
|
+
async function executeNode(node, input, ctx) {
|
|
2475
2564
|
let req;
|
|
2476
2565
|
if (typeof input === "string") {
|
|
2477
2566
|
req = createRequest(input, { sessionKey: `multi-agent:${node.id}` });
|
|
2478
2567
|
} else {
|
|
2479
2568
|
req = { ...input, sessionKey: input.sessionKey ?? `multi-agent:${node.id}` };
|
|
2480
2569
|
}
|
|
2481
|
-
const
|
|
2570
|
+
const maxAttempts = Math.max(1, node.retry?.maxAttempts ?? 1);
|
|
2571
|
+
const backoffMs = node.retry?.backoffMs ?? 0;
|
|
2572
|
+
let lastErr;
|
|
2573
|
+
let succeeded;
|
|
2574
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
2575
|
+
if (attempt > 1 && backoffMs > 0) {
|
|
2576
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
2577
|
+
}
|
|
2578
|
+
try {
|
|
2579
|
+
succeeded = await executeNodeOnce(node, req);
|
|
2580
|
+
break;
|
|
2581
|
+
} catch (err) {
|
|
2582
|
+
lastErr = err;
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
if (succeeded === void 0) {
|
|
2586
|
+
throw lastErr;
|
|
2587
|
+
}
|
|
2482
2588
|
if (node.outputMapping) {
|
|
2483
|
-
node.outputMapping(
|
|
2589
|
+
node.outputMapping(succeeded, ctx);
|
|
2484
2590
|
}
|
|
2485
|
-
return
|
|
2591
|
+
return succeeded;
|
|
2486
2592
|
}
|
|
2487
2593
|
function resolveInput(edge, prevResult, ctx, node, originalInput) {
|
|
2488
2594
|
if (edge?.transform) {
|
|
@@ -2509,12 +2615,22 @@ var GraphExecutor = class {
|
|
|
2509
2615
|
entryId;
|
|
2510
2616
|
finishCondition;
|
|
2511
2617
|
abortController = new AbortController();
|
|
2618
|
+
/** 外部事件监听(on() API 的底层接线),事件会同步分发 */
|
|
2619
|
+
eventSink;
|
|
2620
|
+
/** 并行分支最大并发数(默认不限制) */
|
|
2621
|
+
concurrency;
|
|
2622
|
+
/** 单节点最大访问次数(环图防死循环) */
|
|
2623
|
+
maxVisitsPerNode;
|
|
2512
2624
|
state = {
|
|
2513
2625
|
nodeStates: /* @__PURE__ */ new Map(),
|
|
2514
2626
|
nodeResults: /* @__PURE__ */ new Map(),
|
|
2515
2627
|
stepsCompleted: 0,
|
|
2516
2628
|
finished: false
|
|
2517
2629
|
};
|
|
2630
|
+
constructor(opts) {
|
|
2631
|
+
this.concurrency = opts?.concurrency ?? Infinity;
|
|
2632
|
+
this.maxVisitsPerNode = opts?.maxVisitsPerNode ?? 10;
|
|
2633
|
+
}
|
|
2518
2634
|
addNode(node) {
|
|
2519
2635
|
this.nodes.set(node.id, node);
|
|
2520
2636
|
this.state.nodeStates.set(node.id, "pending");
|
|
@@ -2532,12 +2648,42 @@ var GraphExecutor = class {
|
|
|
2532
2648
|
this.finishCondition = condition;
|
|
2533
2649
|
return this;
|
|
2534
2650
|
}
|
|
2651
|
+
/** 注入外部事件监听(由 AgentGraph 实现的 on() 接线) */
|
|
2652
|
+
setEventSink(sink) {
|
|
2653
|
+
this.eventSink = sink;
|
|
2654
|
+
return this;
|
|
2655
|
+
}
|
|
2535
2656
|
getState() {
|
|
2536
|
-
return {
|
|
2657
|
+
return {
|
|
2658
|
+
...this.state,
|
|
2659
|
+
nodeStates: new Map(this.state.nodeStates),
|
|
2660
|
+
nodeResults: new Map(this.state.nodeResults)
|
|
2661
|
+
};
|
|
2537
2662
|
}
|
|
2538
2663
|
abort() {
|
|
2539
2664
|
this.abortController.abort();
|
|
2540
2665
|
}
|
|
2666
|
+
/** 每次 run/stream 前重置中止信号,避免上一次的 abort 永久失效 */
|
|
2667
|
+
resetAbortController() {
|
|
2668
|
+
this.abortController = new AbortController();
|
|
2669
|
+
}
|
|
2670
|
+
/** 每次 run/stream 前重置执行状态,避免残留上一次的 nodeStates/结果 */
|
|
2671
|
+
resetState() {
|
|
2672
|
+
this.state = {
|
|
2673
|
+
nodeStates: /* @__PURE__ */ new Map(),
|
|
2674
|
+
nodeResults: /* @__PURE__ */ new Map(),
|
|
2675
|
+
stepsCompleted: 0,
|
|
2676
|
+
finished: false
|
|
2677
|
+
};
|
|
2678
|
+
for (const id of this.nodes.keys()) {
|
|
2679
|
+
this.state.nodeStates.set(id, "pending");
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
throwIfAborted() {
|
|
2683
|
+
if (this.abortController.signal.aborted) {
|
|
2684
|
+
throw new GraphAbortedError();
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2541
2687
|
/** 同步执行图 */
|
|
2542
2688
|
async run(input) {
|
|
2543
2689
|
if (!this.entryId) {
|
|
@@ -2546,66 +2692,78 @@ var GraphExecutor = class {
|
|
|
2546
2692
|
if (!this.nodes.has(this.entryId)) {
|
|
2547
2693
|
throw new Error(`AgentGraph: \u5165\u53E3\u8282\u70B9 "${this.entryId}" \u4E0D\u5B58\u5728`);
|
|
2548
2694
|
}
|
|
2695
|
+
this.resetAbortController();
|
|
2696
|
+
this.resetState();
|
|
2549
2697
|
const ctx = createSharedContext({
|
|
2550
2698
|
meta: { traceId: `ma-${Date.now()}`, startTime: Date.now() }
|
|
2551
2699
|
});
|
|
2552
|
-
|
|
2700
|
+
storeOriginalInput(ctx, input);
|
|
2701
|
+
const emit = this.eventSink ?? (() => {
|
|
2702
|
+
});
|
|
2553
2703
|
try {
|
|
2554
|
-
const result = await this.executeGraph(input, ctx,
|
|
2704
|
+
const result = await this.executeGraph(input, ctx, emit);
|
|
2705
|
+
emit({ type: "graph_done", result });
|
|
2555
2706
|
return result;
|
|
2556
2707
|
} catch (err) {
|
|
2708
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2709
|
+
this.state.error = errorMsg;
|
|
2710
|
+
if (err instanceof GraphAbortedError) {
|
|
2711
|
+
const lastCompleted = [...this.state.nodeResults.values()].at(-1);
|
|
2712
|
+
const abortedResult = {
|
|
2713
|
+
content: lastCompleted?.content ?? "",
|
|
2714
|
+
lastAgentId: this.state.currentAgentId ?? "",
|
|
2715
|
+
agentResults: new Map(this.state.nodeResults),
|
|
2716
|
+
totalUsage: {},
|
|
2717
|
+
stepsCompleted: this.state.stepsCompleted,
|
|
2718
|
+
stopReason: "aborted",
|
|
2719
|
+
context: ctx,
|
|
2720
|
+
success: false,
|
|
2721
|
+
error: err.message
|
|
2722
|
+
};
|
|
2723
|
+
emit({ type: "graph_error", error: err.message });
|
|
2724
|
+
return abortedResult;
|
|
2725
|
+
}
|
|
2726
|
+
emit({ type: "graph_error", error: errorMsg });
|
|
2557
2727
|
return {
|
|
2558
2728
|
content: "",
|
|
2559
2729
|
lastAgentId: this.state.currentAgentId ?? "",
|
|
2560
|
-
agentResults: this.state.nodeResults,
|
|
2730
|
+
agentResults: new Map(this.state.nodeResults),
|
|
2561
2731
|
totalUsage: {},
|
|
2562
2732
|
stepsCompleted: this.state.stepsCompleted,
|
|
2563
2733
|
stopReason: "error",
|
|
2564
2734
|
context: ctx,
|
|
2565
2735
|
success: false,
|
|
2566
|
-
error:
|
|
2736
|
+
error: errorMsg
|
|
2567
2737
|
};
|
|
2568
2738
|
}
|
|
2569
2739
|
}
|
|
2570
2740
|
/** 流式执行图 */
|
|
2571
|
-
|
|
2741
|
+
stream(input) {
|
|
2572
2742
|
if (!this.entryId) {
|
|
2573
2743
|
throw new Error("AgentGraph: \u5165\u53E3\u8282\u70B9\u672A\u8BBE\u7F6E\uFF0C\u8BF7\u8C03\u7528 setEntry()");
|
|
2574
2744
|
}
|
|
2575
2745
|
if (!this.nodes.has(this.entryId)) {
|
|
2576
2746
|
throw new Error(`AgentGraph: \u5165\u53E3\u8282\u70B9 "${this.entryId}" \u4E0D\u5B58\u5728`);
|
|
2577
2747
|
}
|
|
2748
|
+
this.resetAbortController();
|
|
2749
|
+
this.resetState();
|
|
2578
2750
|
const ctx = createSharedContext({
|
|
2579
2751
|
meta: { traceId: `ma-${Date.now()}`, startTime: Date.now() }
|
|
2580
2752
|
});
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
).finally(() => {
|
|
2596
|
-
done = true;
|
|
2597
|
-
resolveEvent?.();
|
|
2598
|
-
});
|
|
2599
|
-
while (!done || eventQueue.length > 0) {
|
|
2600
|
-
if (eventQueue.length > 0) {
|
|
2601
|
-
yield eventQueue.shift();
|
|
2602
|
-
} else {
|
|
2603
|
-
await new Promise((resolve) => {
|
|
2604
|
-
resolveEvent = resolve;
|
|
2605
|
-
});
|
|
2606
|
-
}
|
|
2607
|
-
}
|
|
2608
|
-
await graphPromise;
|
|
2753
|
+
storeOriginalInput(ctx, input);
|
|
2754
|
+
return createEventStream(
|
|
2755
|
+
(emit) => this.executeGraph(input, ctx, emit).then(
|
|
2756
|
+
(result) => {
|
|
2757
|
+
emit({ type: "graph_done", result });
|
|
2758
|
+
},
|
|
2759
|
+
(err) => {
|
|
2760
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2761
|
+
this.state.error = errorMsg;
|
|
2762
|
+
emit({ type: "graph_error", error: errorMsg });
|
|
2763
|
+
}
|
|
2764
|
+
),
|
|
2765
|
+
this.eventSink
|
|
2766
|
+
);
|
|
2609
2767
|
}
|
|
2610
2768
|
/** 核心执行逻辑 */
|
|
2611
2769
|
async executeGraph(input, ctx, emit) {
|
|
@@ -2618,7 +2776,7 @@ var GraphExecutor = class {
|
|
|
2618
2776
|
const totalUsage = {};
|
|
2619
2777
|
this.state.currentAgentId = currentId;
|
|
2620
2778
|
this.state.nodeStates.set(currentId, "running");
|
|
2621
|
-
emit({ type: "agent_start", agentId: currentId, agentName: entryNode.name });
|
|
2779
|
+
emit({ type: "agent_start", agentId: currentId, agentName: entryNode.name, input: toInputText(currentInput) });
|
|
2622
2780
|
try {
|
|
2623
2781
|
lastResult = await executeNode(entryNode, currentInput, ctx);
|
|
2624
2782
|
this.state.nodeStates.set(currentId, "completed");
|
|
@@ -2637,50 +2795,134 @@ var GraphExecutor = class {
|
|
|
2637
2795
|
if (this.finishCondition?.(ctx)) {
|
|
2638
2796
|
return this.buildResult(lastResult, lastAgentId, ctx, totalUsage, stepsCompleted, "finish_condition");
|
|
2639
2797
|
}
|
|
2640
|
-
|
|
2798
|
+
let frontier = [{ id: currentId, result: lastResult }];
|
|
2641
2799
|
const visitCount = /* @__PURE__ */ new Map();
|
|
2642
|
-
|
|
2643
|
-
while (
|
|
2644
|
-
|
|
2645
|
-
|
|
2800
|
+
let stopReason = "completed";
|
|
2801
|
+
while (frontier.length > 0) {
|
|
2802
|
+
this.throwIfAborted();
|
|
2803
|
+
const candidates = [];
|
|
2804
|
+
const seenTargets = /* @__PURE__ */ new Set();
|
|
2805
|
+
for (const from of frontier) {
|
|
2806
|
+
const nextEdges = findNextEdges(from.id, this.edges, from.result, ctx);
|
|
2807
|
+
for (const edge of nextEdges) {
|
|
2808
|
+
if (seenTargets.has(edge.to)) continue;
|
|
2809
|
+
seenTargets.add(edge.to);
|
|
2810
|
+
const nextNode = this.nodes.get(edge.to);
|
|
2811
|
+
if (!nextNode) {
|
|
2812
|
+
throw new Error(`AgentGraph: \u76EE\u6807\u8282\u70B9 "${edge.to}" \u4E0D\u5B58\u5728`);
|
|
2813
|
+
}
|
|
2814
|
+
candidates.push({ edge, from, node: nextNode });
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
if (candidates.length === 0) {
|
|
2646
2818
|
break;
|
|
2647
2819
|
}
|
|
2648
|
-
const
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2820
|
+
const allowed = [];
|
|
2821
|
+
let truncated = false;
|
|
2822
|
+
for (const c of candidates) {
|
|
2823
|
+
const count = (visitCount.get(c.edge.to) ?? 0) + 1;
|
|
2824
|
+
if (count > this.maxVisitsPerNode) {
|
|
2825
|
+
truncated = true;
|
|
2826
|
+
continue;
|
|
2827
|
+
}
|
|
2828
|
+
visitCount.set(c.edge.to, count);
|
|
2829
|
+
allowed.push(c);
|
|
2652
2830
|
}
|
|
2653
|
-
|
|
2654
|
-
|
|
2831
|
+
if (allowed.length === 0) {
|
|
2832
|
+
if (truncated) stopReason = "max_visits_exceeded";
|
|
2655
2833
|
break;
|
|
2656
2834
|
}
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
this.state.nodeStates.set(
|
|
2667
|
-
|
|
2668
|
-
|
|
2835
|
+
const tasks = allowed.map((c) => ({
|
|
2836
|
+
node: c.node,
|
|
2837
|
+
input: resolveInput(c.edge, c.from.result, ctx, c.node, input),
|
|
2838
|
+
fromId: c.edge.from
|
|
2839
|
+
}));
|
|
2840
|
+
let waveResults;
|
|
2841
|
+
if (tasks.length === 1) {
|
|
2842
|
+
const t = tasks[0];
|
|
2843
|
+
this.state.currentAgentId = t.node.id;
|
|
2844
|
+
this.state.nodeStates.set(t.node.id, "running");
|
|
2845
|
+
emit({ type: "edge_traversed", from: t.fromId, to: t.node.id });
|
|
2846
|
+
emit({ type: "agent_start", agentId: t.node.id, agentName: t.node.name, input: toInputText(t.input) });
|
|
2847
|
+
let result;
|
|
2848
|
+
try {
|
|
2849
|
+
result = await executeNode(t.node, t.input, ctx);
|
|
2850
|
+
} catch (err) {
|
|
2851
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2852
|
+
this.state.nodeStates.set(t.node.id, "failed");
|
|
2853
|
+
emit({ type: "agent_error", agentId: t.node.id, agentName: t.node.name, error: errorMsg });
|
|
2854
|
+
throw err;
|
|
2855
|
+
}
|
|
2856
|
+
this.state.nodeStates.set(t.node.id, "completed");
|
|
2857
|
+
this.state.nodeResults.set(t.node.id, result);
|
|
2858
|
+
this.mergeUsage(totalUsage, result.usage);
|
|
2669
2859
|
stepsCompleted++;
|
|
2670
2860
|
this.state.stepsCompleted = stepsCompleted;
|
|
2671
|
-
emit({ type: "agent_result", agentId:
|
|
2861
|
+
emit({ type: "agent_result", agentId: t.node.id, agentName: t.node.name, result });
|
|
2862
|
+
waveResults = [{ id: t.node.id, result }];
|
|
2863
|
+
} else {
|
|
2864
|
+
waveResults = await this.executeWave(tasks, ctx, emit, totalUsage);
|
|
2865
|
+
stepsCompleted += waveResults.length;
|
|
2866
|
+
this.state.stepsCompleted = stepsCompleted;
|
|
2867
|
+
}
|
|
2868
|
+
lastResult = waveResults[waveResults.length - 1].result;
|
|
2869
|
+
lastAgentId = waveResults[waveResults.length - 1].id;
|
|
2870
|
+
frontier = waveResults;
|
|
2871
|
+
if (this.finishCondition?.(ctx)) {
|
|
2872
|
+
return this.buildResult(lastResult, lastAgentId, ctx, totalUsage, stepsCompleted, "finish_condition");
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
return this.buildResult(lastResult, lastAgentId, ctx, totalUsage, stepsCompleted, stopReason);
|
|
2876
|
+
}
|
|
2877
|
+
/** 并行执行一个 wave 的节点(fail-fast + concurrency 限流) */
|
|
2878
|
+
async executeWave(tasks, ctx, emit, totalUsage) {
|
|
2879
|
+
const results = [];
|
|
2880
|
+
emit({ type: "parallel_start", agentIds: tasks.map((t) => t.node.id) });
|
|
2881
|
+
const runOne = async (t) => {
|
|
2882
|
+
this.state.currentAgentId = t.node.id;
|
|
2883
|
+
this.state.nodeStates.set(t.node.id, "running");
|
|
2884
|
+
emit({ type: "edge_traversed", from: t.fromId, to: t.node.id });
|
|
2885
|
+
emit({ type: "agent_start", agentId: t.node.id, agentName: t.node.name, input: toInputText(t.input) });
|
|
2886
|
+
try {
|
|
2887
|
+
const result = await executeNode(t.node, t.input, ctx);
|
|
2888
|
+
this.state.nodeStates.set(t.node.id, "completed");
|
|
2889
|
+
this.state.nodeResults.set(t.node.id, result);
|
|
2890
|
+
this.mergeUsage(totalUsage, result.usage);
|
|
2891
|
+
results.push({ id: t.node.id, result });
|
|
2892
|
+
emit({ type: "agent_result", agentId: t.node.id, agentName: t.node.name, result });
|
|
2672
2893
|
} catch (err) {
|
|
2673
2894
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2674
|
-
this.state.nodeStates.set(
|
|
2675
|
-
emit({ type: "agent_error", agentId:
|
|
2895
|
+
this.state.nodeStates.set(t.node.id, "failed");
|
|
2896
|
+
emit({ type: "agent_error", agentId: t.node.id, agentName: t.node.name, error: errorMsg });
|
|
2676
2897
|
throw err;
|
|
2677
2898
|
}
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2899
|
+
};
|
|
2900
|
+
if (this.concurrency >= tasks.length) {
|
|
2901
|
+
await Promise.all(tasks.map((t) => runOne(t)));
|
|
2902
|
+
} else {
|
|
2903
|
+
let index = 0;
|
|
2904
|
+
const executing = /* @__PURE__ */ new Set();
|
|
2905
|
+
const enqueue = () => {
|
|
2906
|
+
if (index >= tasks.length) return null;
|
|
2907
|
+
const i = index++;
|
|
2908
|
+
const p = runOne(tasks[i]).finally(() => {
|
|
2909
|
+
executing.delete(p);
|
|
2910
|
+
});
|
|
2911
|
+
executing.add(p);
|
|
2912
|
+
p.catch(() => {
|
|
2913
|
+
});
|
|
2914
|
+
return p;
|
|
2915
|
+
};
|
|
2916
|
+
for (let i = 0; i < this.concurrency && index < tasks.length; i++) {
|
|
2917
|
+
enqueue();
|
|
2918
|
+
}
|
|
2919
|
+
while (executing.size > 0) {
|
|
2920
|
+
await Promise.race(executing);
|
|
2921
|
+
enqueue();
|
|
2681
2922
|
}
|
|
2682
2923
|
}
|
|
2683
|
-
|
|
2924
|
+
emit({ type: "parallel_done", results: new Map(results.map((r) => [r.id, r.result])) });
|
|
2925
|
+
return results;
|
|
2684
2926
|
}
|
|
2685
2927
|
buildResult(lastResult, lastAgentId, ctx, totalUsage, stepsCompleted, stopReason) {
|
|
2686
2928
|
this.state.finished = true;
|
|
@@ -2705,8 +2947,12 @@ var GraphExecutor = class {
|
|
|
2705
2947
|
|
|
2706
2948
|
// core/graph.ts
|
|
2707
2949
|
var AgentGraphImpl = class {
|
|
2708
|
-
executor
|
|
2709
|
-
|
|
2950
|
+
executor;
|
|
2951
|
+
/** on() 注册的监听器,按 MultiAgentEvent.type 分发 */
|
|
2952
|
+
bus = new SimpleEventBus();
|
|
2953
|
+
constructor(opts) {
|
|
2954
|
+
this.executor = new GraphExecutor(opts);
|
|
2955
|
+
}
|
|
2710
2956
|
addNode(node) {
|
|
2711
2957
|
this.executor.addNode(node);
|
|
2712
2958
|
return this;
|
|
@@ -2724,9 +2970,11 @@ var AgentGraphImpl = class {
|
|
|
2724
2970
|
return this;
|
|
2725
2971
|
}
|
|
2726
2972
|
async run(input) {
|
|
2973
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
2727
2974
|
return this.executor.run(input);
|
|
2728
2975
|
}
|
|
2729
2976
|
async *stream(input) {
|
|
2977
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
2730
2978
|
yield* this.executor.stream(input);
|
|
2731
2979
|
}
|
|
2732
2980
|
getState() {
|
|
@@ -2736,17 +2984,12 @@ var AgentGraphImpl = class {
|
|
|
2736
2984
|
this.executor.abort();
|
|
2737
2985
|
}
|
|
2738
2986
|
on(event, listener) {
|
|
2739
|
-
|
|
2740
|
-
if (!set) {
|
|
2741
|
-
set = /* @__PURE__ */ new Set();
|
|
2742
|
-
this.eventListeners.set(event, set);
|
|
2743
|
-
}
|
|
2744
|
-
set.add(listener);
|
|
2987
|
+
this.bus.on(event, listener);
|
|
2745
2988
|
return this;
|
|
2746
2989
|
}
|
|
2747
2990
|
};
|
|
2748
|
-
function createAgentGraph() {
|
|
2749
|
-
return new AgentGraphImpl();
|
|
2991
|
+
function createAgentGraph(opts) {
|
|
2992
|
+
return new AgentGraphImpl(opts);
|
|
2750
2993
|
}
|
|
2751
2994
|
|
|
2752
2995
|
// patterns/pipeline.ts
|
|
@@ -2784,14 +3027,19 @@ function createRouter(router, targets, opts) {
|
|
|
2784
3027
|
}
|
|
2785
3028
|
graph.setEntry(router.id);
|
|
2786
3029
|
const targetIds = new Set(targets.map((t) => t.id));
|
|
3030
|
+
const defaultTarget = opts.defaultTarget && targetIds.has(opts.defaultTarget) ? opts.defaultTarget : void 0;
|
|
3031
|
+
const resolveTarget = (routerResult) => {
|
|
3032
|
+
const resolvedId = opts.resolve(routerResult);
|
|
3033
|
+
if (targetIds.has(resolvedId)) return resolvedId;
|
|
3034
|
+
return defaultTarget ?? resolvedId;
|
|
3035
|
+
};
|
|
2787
3036
|
for (const target of targets) {
|
|
2788
3037
|
graph.addEdge({
|
|
2789
3038
|
from: router.id,
|
|
2790
3039
|
to: target.id,
|
|
2791
|
-
// 条件:从路由器结果中解析目标ID
|
|
3040
|
+
// 条件:从路由器结果中解析目标ID(含 defaultTarget 兜底),匹配当前目标
|
|
2792
3041
|
condition: (routerResult, _ctx) => {
|
|
2793
|
-
|
|
2794
|
-
return resolvedId === target.id;
|
|
3042
|
+
return resolveTarget(routerResult) === target.id;
|
|
2795
3043
|
},
|
|
2796
3044
|
// 转换:决定传给目标Agent的输入
|
|
2797
3045
|
transform: (_routerResult, _ctx) => {
|
|
@@ -2803,8 +3051,6 @@ function createRouter(router, targets, opts) {
|
|
|
2803
3051
|
}
|
|
2804
3052
|
});
|
|
2805
3053
|
}
|
|
2806
|
-
if (opts.defaultTarget && targetIds.has(opts.defaultTarget)) {
|
|
2807
|
-
}
|
|
2808
3054
|
return graph;
|
|
2809
3055
|
}
|
|
2810
3056
|
|
|
@@ -2813,6 +3059,11 @@ var SupervisorExecutor = class {
|
|
|
2813
3059
|
supervisorNode;
|
|
2814
3060
|
workerNodes;
|
|
2815
3061
|
opts;
|
|
3062
|
+
abortController = new AbortController();
|
|
3063
|
+
/** 外部事件监听(on() API 的底层接线) */
|
|
3064
|
+
eventSink;
|
|
3065
|
+
/** 最近一次 run 中失败的 Worker ID(onWorkerError='skip' 时使用) */
|
|
3066
|
+
failedAgents = [];
|
|
2816
3067
|
state = {
|
|
2817
3068
|
nodeStates: /* @__PURE__ */ new Map(),
|
|
2818
3069
|
nodeResults: /* @__PURE__ */ new Map(),
|
|
@@ -2825,7 +3076,8 @@ var SupervisorExecutor = class {
|
|
|
2825
3076
|
this.opts = {
|
|
2826
3077
|
schedule: opts?.schedule ?? "parallel",
|
|
2827
3078
|
concurrency: opts?.concurrency ?? Infinity,
|
|
2828
|
-
passOriginalInput: opts?.passOriginalInput ?? true
|
|
3079
|
+
passOriginalInput: opts?.passOriginalInput ?? true,
|
|
3080
|
+
onWorkerError: opts?.onWorkerError ?? "fail-fast"
|
|
2829
3081
|
};
|
|
2830
3082
|
this.state.nodeStates.set(supervisor.id, "pending");
|
|
2831
3083
|
for (const w of workers) {
|
|
@@ -2833,69 +3085,91 @@ var SupervisorExecutor = class {
|
|
|
2833
3085
|
}
|
|
2834
3086
|
}
|
|
2835
3087
|
getState() {
|
|
2836
|
-
return {
|
|
3088
|
+
return {
|
|
3089
|
+
...this.state,
|
|
3090
|
+
nodeStates: new Map(this.state.nodeStates),
|
|
3091
|
+
nodeResults: new Map(this.state.nodeResults)
|
|
3092
|
+
};
|
|
3093
|
+
}
|
|
3094
|
+
/** 注入外部事件监听(由 AgentGraph 实现的 on() 接线) */
|
|
3095
|
+
setEventSink(sink) {
|
|
3096
|
+
this.eventSink = sink;
|
|
3097
|
+
return this;
|
|
3098
|
+
}
|
|
3099
|
+
abort() {
|
|
3100
|
+
this.abortController.abort();
|
|
3101
|
+
}
|
|
3102
|
+
/** 每次 run/stream 前重置中止信号、失败记录与执行状态 */
|
|
3103
|
+
resetRun() {
|
|
3104
|
+
this.abortController = new AbortController();
|
|
3105
|
+
this.failedAgents = [];
|
|
3106
|
+
this.state = {
|
|
3107
|
+
nodeStates: /* @__PURE__ */ new Map(),
|
|
3108
|
+
nodeResults: /* @__PURE__ */ new Map(),
|
|
3109
|
+
stepsCompleted: 0,
|
|
3110
|
+
finished: false
|
|
3111
|
+
};
|
|
3112
|
+
this.state.nodeStates.set(this.supervisorNode.id, "pending");
|
|
3113
|
+
for (const w of this.workerNodes) {
|
|
3114
|
+
this.state.nodeStates.set(w.id, "pending");
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
throwIfAborted() {
|
|
3118
|
+
if (this.abortController.signal.aborted) {
|
|
3119
|
+
throw new GraphAbortedError();
|
|
3120
|
+
}
|
|
2837
3121
|
}
|
|
2838
3122
|
/** 执行 Supervisor 模式 */
|
|
2839
3123
|
async run(input) {
|
|
3124
|
+
this.resetRun();
|
|
2840
3125
|
const ctx = createSharedContext({
|
|
2841
3126
|
meta: { traceId: `sv-${Date.now()}`, startTime: Date.now() }
|
|
2842
3127
|
});
|
|
2843
3128
|
if (this.opts.passOriginalInput) {
|
|
2844
|
-
|
|
2845
|
-
ctx.blackboard.set("__original_input__", inputText);
|
|
3129
|
+
storeOriginalInput(ctx, input);
|
|
2846
3130
|
}
|
|
3131
|
+
const emit = this.eventSink ?? (() => {
|
|
3132
|
+
});
|
|
2847
3133
|
try {
|
|
2848
|
-
|
|
2849
|
-
});
|
|
3134
|
+
const result = await this.executeSupervisor(input, ctx, emit);
|
|
3135
|
+
emit({ type: "graph_done", result });
|
|
3136
|
+
return result;
|
|
2850
3137
|
} catch (err) {
|
|
2851
|
-
|
|
3138
|
+
const result = this.buildErrorResult(ctx, err);
|
|
3139
|
+
emit({ type: "graph_error", error: result.error ?? "" });
|
|
3140
|
+
return result;
|
|
2852
3141
|
}
|
|
2853
3142
|
}
|
|
2854
3143
|
/** 流式执行 Supervisor 模式 */
|
|
2855
|
-
|
|
3144
|
+
stream(input) {
|
|
3145
|
+
this.resetRun();
|
|
2856
3146
|
const ctx = createSharedContext({
|
|
2857
3147
|
meta: { traceId: `sv-${Date.now()}`, startTime: Date.now() }
|
|
2858
3148
|
});
|
|
2859
3149
|
if (this.opts.passOriginalInput) {
|
|
2860
|
-
|
|
2861
|
-
ctx.blackboard.set("__original_input__", inputText);
|
|
2862
|
-
}
|
|
2863
|
-
const eventQueue = [];
|
|
2864
|
-
let resolveEvent = null;
|
|
2865
|
-
let done = false;
|
|
2866
|
-
const emit = (event) => {
|
|
2867
|
-
eventQueue.push(event);
|
|
2868
|
-
resolveEvent?.();
|
|
2869
|
-
};
|
|
2870
|
-
const graphPromise = this.executeSupervisor(input, ctx, emit).then(
|
|
2871
|
-
(result) => {
|
|
2872
|
-
emit({ type: "graph_done", result });
|
|
2873
|
-
},
|
|
2874
|
-
(err) => {
|
|
2875
|
-
emit({ type: "graph_error", error: err instanceof Error ? err.message : String(err) });
|
|
2876
|
-
}
|
|
2877
|
-
).finally(() => {
|
|
2878
|
-
done = true;
|
|
2879
|
-
resolveEvent?.();
|
|
2880
|
-
});
|
|
2881
|
-
while (!done || eventQueue.length > 0) {
|
|
2882
|
-
if (eventQueue.length > 0) {
|
|
2883
|
-
yield eventQueue.shift();
|
|
2884
|
-
} else {
|
|
2885
|
-
await new Promise((resolve) => {
|
|
2886
|
-
resolveEvent = resolve;
|
|
2887
|
-
});
|
|
2888
|
-
}
|
|
3150
|
+
storeOriginalInput(ctx, input);
|
|
2889
3151
|
}
|
|
2890
|
-
|
|
3152
|
+
return createEventStream(
|
|
3153
|
+
(emit) => this.executeSupervisor(input, ctx, emit).then(
|
|
3154
|
+
(result) => {
|
|
3155
|
+
emit({ type: "graph_done", result });
|
|
3156
|
+
},
|
|
3157
|
+
(err) => {
|
|
3158
|
+
this.state.error = err instanceof Error ? err.message : String(err);
|
|
3159
|
+
emit({ type: "graph_error", error: this.state.error });
|
|
3160
|
+
}
|
|
3161
|
+
),
|
|
3162
|
+
this.eventSink
|
|
3163
|
+
);
|
|
2891
3164
|
}
|
|
2892
3165
|
/** 核心执行逻辑 */
|
|
2893
3166
|
async executeSupervisor(input, ctx, emit) {
|
|
2894
3167
|
let stepsCompleted = 0;
|
|
2895
3168
|
const totalUsage = {};
|
|
3169
|
+
this.throwIfAborted();
|
|
2896
3170
|
this.state.currentAgentId = this.supervisorNode.id;
|
|
2897
3171
|
this.state.nodeStates.set(this.supervisorNode.id, "running");
|
|
2898
|
-
emit({ type: "agent_start", agentId: this.supervisorNode.id, agentName: this.supervisorNode.name });
|
|
3172
|
+
emit({ type: "agent_start", agentId: this.supervisorNode.id, agentName: this.supervisorNode.name, input: toInputText(input) });
|
|
2899
3173
|
let supervisorResult;
|
|
2900
3174
|
try {
|
|
2901
3175
|
supervisorResult = await executeNode(this.supervisorNode, input, ctx);
|
|
@@ -2922,18 +3196,21 @@ var SupervisorExecutor = class {
|
|
|
2922
3196
|
}
|
|
2923
3197
|
stepsCompleted += workerResults.size;
|
|
2924
3198
|
this.state.stepsCompleted = stepsCompleted;
|
|
2925
|
-
const
|
|
2926
|
-
const finalResult =
|
|
3199
|
+
const lastEntry = [...workerResults.entries()].at(-1);
|
|
3200
|
+
const finalResult = lastEntry?.[1] ?? supervisorResult;
|
|
3201
|
+
const finalAgentId = lastEntry?.[0] ?? this.supervisorNode.id;
|
|
3202
|
+
const hasFailures = this.failedAgents.length > 0;
|
|
2927
3203
|
this.state.finished = true;
|
|
2928
3204
|
return {
|
|
2929
3205
|
content: finalResult.content,
|
|
2930
|
-
lastAgentId:
|
|
3206
|
+
lastAgentId: finalAgentId,
|
|
2931
3207
|
agentResults: new Map(this.state.nodeResults),
|
|
2932
3208
|
totalUsage,
|
|
2933
3209
|
stepsCompleted,
|
|
2934
|
-
stopReason: "completed",
|
|
3210
|
+
stopReason: hasFailures ? "partial_failure" : "completed",
|
|
2935
3211
|
context: ctx,
|
|
2936
|
-
success: true
|
|
3212
|
+
success: true,
|
|
3213
|
+
...hasFailures ? { failedAgents: [...this.failedAgents] } : {}
|
|
2937
3214
|
};
|
|
2938
3215
|
}
|
|
2939
3216
|
/** 并行执行所有 Worker */
|
|
@@ -2941,16 +3218,28 @@ var SupervisorExecutor = class {
|
|
|
2941
3218
|
const results = /* @__PURE__ */ new Map();
|
|
2942
3219
|
const workers = this.workerNodes;
|
|
2943
3220
|
const concurrency = this.opts.concurrency;
|
|
3221
|
+
const skip = this.opts.onWorkerError === "skip";
|
|
2944
3222
|
emit({ type: "parallel_start", agentIds: workers.map((w) => w.id) });
|
|
2945
3223
|
if (concurrency >= workers.length) {
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
3224
|
+
if (!skip) {
|
|
3225
|
+
await Promise.all(
|
|
3226
|
+
workers.map(async (worker) => {
|
|
3227
|
+
const r = await this.executeWorker(worker, ctx, emit, totalUsage);
|
|
3228
|
+
results.set(worker.id, r);
|
|
3229
|
+
return r;
|
|
3230
|
+
})
|
|
3231
|
+
);
|
|
3232
|
+
} else {
|
|
3233
|
+
const settled = await Promise.allSettled(
|
|
3234
|
+
workers.map((worker) => this.executeWorker(worker, ctx, emit, totalUsage))
|
|
3235
|
+
);
|
|
3236
|
+
for (let i = 0; i < settled.length; i++) {
|
|
3237
|
+
const s = settled[i];
|
|
3238
|
+
if (s.status === "fulfilled") {
|
|
3239
|
+
results.set(workers[i].id, s.value);
|
|
3240
|
+
} else {
|
|
3241
|
+
this.failedAgents.push(workers[i].id);
|
|
3242
|
+
}
|
|
2954
3243
|
}
|
|
2955
3244
|
}
|
|
2956
3245
|
} else {
|
|
@@ -2959,12 +3248,20 @@ var SupervisorExecutor = class {
|
|
|
2959
3248
|
const enqueue = () => {
|
|
2960
3249
|
if (index >= workers.length) return null;
|
|
2961
3250
|
const worker = workers[index++];
|
|
2962
|
-
const p = this.executeWorker(worker, ctx, emit, totalUsage).then(
|
|
2963
|
-
|
|
3251
|
+
const p = this.executeWorker(worker, ctx, emit, totalUsage).then(
|
|
3252
|
+
(r) => {
|
|
3253
|
+
results.set(worker.id, r);
|
|
3254
|
+
},
|
|
3255
|
+
(err) => {
|
|
3256
|
+
if (!skip) throw err;
|
|
3257
|
+
this.failedAgents.push(worker.id);
|
|
3258
|
+
}
|
|
3259
|
+
).finally(() => {
|
|
2964
3260
|
executing.delete(p);
|
|
2965
|
-
return r;
|
|
2966
3261
|
});
|
|
2967
3262
|
executing.add(p);
|
|
3263
|
+
p.catch(() => {
|
|
3264
|
+
});
|
|
2968
3265
|
return p;
|
|
2969
3266
|
};
|
|
2970
3267
|
for (let i = 0; i < concurrency && index < workers.length; i++) {
|
|
@@ -2981,40 +3278,122 @@ var SupervisorExecutor = class {
|
|
|
2981
3278
|
/** 顺序执行所有 Worker */
|
|
2982
3279
|
async executeWorkersSequential(ctx, emit, totalUsage) {
|
|
2983
3280
|
const results = /* @__PURE__ */ new Map();
|
|
3281
|
+
const skip = this.opts.onWorkerError === "skip";
|
|
2984
3282
|
for (const worker of this.workerNodes) {
|
|
2985
|
-
|
|
2986
|
-
|
|
3283
|
+
try {
|
|
3284
|
+
const result = await this.executeWorker(worker, ctx, emit, totalUsage);
|
|
3285
|
+
results.set(worker.id, result);
|
|
3286
|
+
} catch (err) {
|
|
3287
|
+
if (!skip) throw err;
|
|
3288
|
+
this.failedAgents.push(worker.id);
|
|
3289
|
+
}
|
|
2987
3290
|
}
|
|
2988
3291
|
return results;
|
|
2989
3292
|
}
|
|
2990
|
-
/**
|
|
3293
|
+
/** 自动调度:按依赖分层执行
|
|
3294
|
+
*
|
|
3295
|
+
* 依赖推导规则:
|
|
3296
|
+
* 1. 显式声明 dependsOn 的 worker:依赖指定的 worker(依赖必须都在 workers 列表中,否则报错)
|
|
3297
|
+
* 2. 未声明 dependsOn 但有 inputMapping 的 worker:隐式依赖所有"第 0 层"worker(保持向后兼容)
|
|
3298
|
+
* 3. 其余 worker(无 dependsOn 且无 inputMapping):第 0 层,首批并行
|
|
3299
|
+
*
|
|
3300
|
+
* 按拓扑分层:同层并行执行(受 concurrency 限制),层间按序执行;依赖成环时报错。
|
|
3301
|
+
*/
|
|
2991
3302
|
async executeWorkersAuto(ctx, emit, totalUsage) {
|
|
2992
3303
|
const results = /* @__PURE__ */ new Map();
|
|
2993
|
-
const
|
|
2994
|
-
const
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3304
|
+
const skip = this.opts.onWorkerError === "skip";
|
|
3305
|
+
const workerIds = new Set(this.workerNodes.map((w) => w.id));
|
|
3306
|
+
const layer0 = this.workerNodes.filter((w) => !w.inputMapping && !w.dependsOn);
|
|
3307
|
+
const deps = /* @__PURE__ */ new Map();
|
|
3308
|
+
for (const w of this.workerNodes) {
|
|
3309
|
+
if (w.dependsOn) {
|
|
3310
|
+
for (const dep of w.dependsOn) {
|
|
3311
|
+
if (!workerIds.has(dep)) {
|
|
3312
|
+
throw new Error(`Supervisor: Worker "${w.id}" \u7684 dependsOn \u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684 Worker "${dep}"`);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
deps.set(w.id, new Set(w.dependsOn));
|
|
3316
|
+
} else if (w.inputMapping) {
|
|
3317
|
+
deps.set(w.id, new Set(layer0.map((l) => l.id)));
|
|
3318
|
+
} else {
|
|
3319
|
+
deps.set(w.id, /* @__PURE__ */ new Set());
|
|
3002
3320
|
}
|
|
3003
|
-
emit({ type: "parallel_done", results: new Map(results) });
|
|
3004
3321
|
}
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3322
|
+
const remaining = new Map(deps);
|
|
3323
|
+
const layers = [];
|
|
3324
|
+
const doneIds = /* @__PURE__ */ new Set();
|
|
3325
|
+
while (remaining.size > 0) {
|
|
3326
|
+
const layer = [];
|
|
3327
|
+
for (const [id, depSet] of remaining) {
|
|
3328
|
+
if ([...depSet].every((d) => doneIds.has(d))) {
|
|
3329
|
+
layer.push(this.workerNodes.find((w) => w.id === id));
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
if (layer.length === 0) {
|
|
3333
|
+
throw new Error(`Supervisor: auto \u8C03\u5EA6\u7684 Worker \u4F9D\u8D56\u5B58\u5728\u73AF\uFF08\u6D89\u53CA: ${[...remaining.keys()].join(", ")}\uFF09`);
|
|
3334
|
+
}
|
|
3335
|
+
for (const w of layer) {
|
|
3336
|
+
remaining.delete(w.id);
|
|
3337
|
+
doneIds.add(w.id);
|
|
3338
|
+
}
|
|
3339
|
+
layers.push(layer);
|
|
3340
|
+
}
|
|
3341
|
+
for (const layer of layers) {
|
|
3342
|
+
if (layer.length === 1) {
|
|
3343
|
+
try {
|
|
3344
|
+
const r = await this.executeWorker(layer[0], ctx, emit, totalUsage);
|
|
3345
|
+
results.set(layer[0].id, r);
|
|
3346
|
+
} catch (err) {
|
|
3347
|
+
if (!skip) throw err;
|
|
3348
|
+
this.failedAgents.push(layer[0].id);
|
|
3349
|
+
}
|
|
3350
|
+
continue;
|
|
3351
|
+
}
|
|
3352
|
+
emit({ type: "parallel_start", agentIds: layer.map((w) => w.id) });
|
|
3353
|
+
const runOne = async (worker) => {
|
|
3354
|
+
try {
|
|
3355
|
+
const r = await this.executeWorker(worker, ctx, emit, totalUsage);
|
|
3356
|
+
results.set(worker.id, r);
|
|
3357
|
+
} catch (err) {
|
|
3358
|
+
if (!skip) throw err;
|
|
3359
|
+
this.failedAgents.push(worker.id);
|
|
3360
|
+
}
|
|
3361
|
+
};
|
|
3362
|
+
if (this.opts.concurrency >= layer.length) {
|
|
3363
|
+
await Promise.all(layer.map((w) => runOne(w)));
|
|
3364
|
+
} else {
|
|
3365
|
+
let index = 0;
|
|
3366
|
+
const executing = /* @__PURE__ */ new Set();
|
|
3367
|
+
const enqueue = () => {
|
|
3368
|
+
if (index >= layer.length) return null;
|
|
3369
|
+
const i = index++;
|
|
3370
|
+
const p = runOne(layer[i]).finally(() => {
|
|
3371
|
+
executing.delete(p);
|
|
3372
|
+
});
|
|
3373
|
+
executing.add(p);
|
|
3374
|
+
p.catch(() => {
|
|
3375
|
+
});
|
|
3376
|
+
return p;
|
|
3377
|
+
};
|
|
3378
|
+
for (let i = 0; i < this.opts.concurrency && index < layer.length; i++) {
|
|
3379
|
+
enqueue();
|
|
3380
|
+
}
|
|
3381
|
+
while (executing.size > 0) {
|
|
3382
|
+
await Promise.race(executing);
|
|
3383
|
+
enqueue();
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
emit({ type: "parallel_done", results: new Map(results) });
|
|
3008
3387
|
}
|
|
3009
3388
|
return results;
|
|
3010
3389
|
}
|
|
3011
3390
|
/** 执行单个 Worker */
|
|
3012
3391
|
async executeWorker(worker, ctx, emit, totalUsage) {
|
|
3392
|
+
this.throwIfAborted();
|
|
3013
3393
|
this.state.currentAgentId = worker.id;
|
|
3014
3394
|
this.state.nodeStates.set(worker.id, "running");
|
|
3015
|
-
|
|
3395
|
+
let workerInput;
|
|
3016
3396
|
try {
|
|
3017
|
-
let workerInput;
|
|
3018
3397
|
if (worker.inputMapping) {
|
|
3019
3398
|
workerInput = worker.inputMapping(ctx);
|
|
3020
3399
|
} else {
|
|
@@ -3022,6 +3401,14 @@ var SupervisorExecutor = class {
|
|
|
3022
3401
|
const myTask = tasks?.find((t) => t.assignee === worker.id);
|
|
3023
3402
|
workerInput = myTask ? myTask.task : ctx.blackboard.get("__original_input__") ?? "";
|
|
3024
3403
|
}
|
|
3404
|
+
} catch (err) {
|
|
3405
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3406
|
+
this.state.nodeStates.set(worker.id, "failed");
|
|
3407
|
+
emit({ type: "agent_error", agentId: worker.id, agentName: worker.name, error: errorMsg });
|
|
3408
|
+
throw err;
|
|
3409
|
+
}
|
|
3410
|
+
emit({ type: "agent_start", agentId: worker.id, agentName: worker.name, input: toInputText(workerInput) });
|
|
3411
|
+
try {
|
|
3025
3412
|
const result = await executeNode(worker, workerInput, ctx);
|
|
3026
3413
|
this.state.nodeStates.set(worker.id, "completed");
|
|
3027
3414
|
this.state.nodeResults.set(worker.id, result);
|
|
@@ -3038,16 +3425,21 @@ var SupervisorExecutor = class {
|
|
|
3038
3425
|
}
|
|
3039
3426
|
buildErrorResult(ctx, err) {
|
|
3040
3427
|
this.state.finished = true;
|
|
3428
|
+
const aborted = err instanceof GraphAbortedError;
|
|
3429
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3430
|
+
this.state.error = errorMsg;
|
|
3431
|
+
const lastCompleted = [...this.state.nodeResults.values()].at(-1);
|
|
3041
3432
|
return {
|
|
3042
|
-
content: "",
|
|
3043
|
-
lastAgentId: this.supervisorNode.id,
|
|
3433
|
+
content: aborted ? lastCompleted?.content ?? "" : "",
|
|
3434
|
+
lastAgentId: this.state.currentAgentId ?? this.supervisorNode.id,
|
|
3044
3435
|
agentResults: new Map(this.state.nodeResults),
|
|
3045
3436
|
totalUsage: {},
|
|
3046
3437
|
stepsCompleted: this.state.stepsCompleted,
|
|
3047
|
-
stopReason: "error",
|
|
3438
|
+
stopReason: aborted ? "aborted" : "error",
|
|
3048
3439
|
context: ctx,
|
|
3049
3440
|
success: false,
|
|
3050
|
-
error:
|
|
3441
|
+
error: errorMsg,
|
|
3442
|
+
...this.failedAgents.length > 0 ? { failedAgents: [...this.failedAgents] } : {}
|
|
3051
3443
|
};
|
|
3052
3444
|
}
|
|
3053
3445
|
mergeUsage(total, usage) {
|
|
@@ -3060,7 +3452,8 @@ var SupervisorExecutor = class {
|
|
|
3060
3452
|
// patterns/supervisor.ts
|
|
3061
3453
|
var SupervisorGraphImpl = class {
|
|
3062
3454
|
executor;
|
|
3063
|
-
|
|
3455
|
+
/** on() 注册的监听器,按 MultiAgentEvent.type 分发 */
|
|
3456
|
+
bus = new SimpleEventBus();
|
|
3064
3457
|
constructor(supervisor, workers, opts) {
|
|
3065
3458
|
this.executor = new SupervisorExecutor(supervisor, workers, opts);
|
|
3066
3459
|
}
|
|
@@ -3078,23 +3471,21 @@ var SupervisorGraphImpl = class {
|
|
|
3078
3471
|
throw new Error("Supervisor \u6A21\u5F0F\u4E0D\u652F\u6301 setFinish\uFF0C\u7EC8\u6B62\u7531 Supervisor \u5224\u5B9A");
|
|
3079
3472
|
}
|
|
3080
3473
|
async run(input) {
|
|
3474
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
3081
3475
|
return this.executor.run(input);
|
|
3082
3476
|
}
|
|
3083
3477
|
async *stream(input) {
|
|
3478
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
3084
3479
|
yield* this.executor.stream(input);
|
|
3085
3480
|
}
|
|
3086
3481
|
getState() {
|
|
3087
3482
|
return this.executor.getState();
|
|
3088
3483
|
}
|
|
3089
3484
|
abort() {
|
|
3485
|
+
this.executor.abort();
|
|
3090
3486
|
}
|
|
3091
3487
|
on(event, listener) {
|
|
3092
|
-
|
|
3093
|
-
if (!set) {
|
|
3094
|
-
set = /* @__PURE__ */ new Set();
|
|
3095
|
-
this.eventListeners.set(event, set);
|
|
3096
|
-
}
|
|
3097
|
-
set.add(listener);
|
|
3488
|
+
this.bus.on(event, listener);
|
|
3098
3489
|
return this;
|
|
3099
3490
|
}
|
|
3100
3491
|
};
|
|
@@ -3112,6 +3503,9 @@ var DebateExecutor = class {
|
|
|
3112
3503
|
maxRounds;
|
|
3113
3504
|
convergeWhen;
|
|
3114
3505
|
feedbackTransform;
|
|
3506
|
+
abortController = new AbortController();
|
|
3507
|
+
/** 外部事件监听(on() API 的底层接线) */
|
|
3508
|
+
eventSink;
|
|
3115
3509
|
state = {
|
|
3116
3510
|
nodeStates: /* @__PURE__ */ new Map(),
|
|
3117
3511
|
nodeResults: /* @__PURE__ */ new Map(),
|
|
@@ -3134,53 +3528,75 @@ ${proposerResult.content}`;
|
|
|
3134
3528
|
this.state.nodeStates.set(reviewer.id, "pending");
|
|
3135
3529
|
}
|
|
3136
3530
|
getState() {
|
|
3137
|
-
return {
|
|
3531
|
+
return {
|
|
3532
|
+
...this.state,
|
|
3533
|
+
nodeStates: new Map(this.state.nodeStates),
|
|
3534
|
+
nodeResults: new Map(this.state.nodeResults)
|
|
3535
|
+
};
|
|
3536
|
+
}
|
|
3537
|
+
/** 注入外部事件监听(由 AgentGraph 实现的 on() 接线) */
|
|
3538
|
+
setEventSink(sink) {
|
|
3539
|
+
this.eventSink = sink;
|
|
3540
|
+
return this;
|
|
3541
|
+
}
|
|
3542
|
+
abort() {
|
|
3543
|
+
this.abortController.abort();
|
|
3544
|
+
}
|
|
3545
|
+
/** 每次 run/stream 前重置中止信号与执行状态 */
|
|
3546
|
+
resetAbortController() {
|
|
3547
|
+
this.abortController = new AbortController();
|
|
3548
|
+
this.state = {
|
|
3549
|
+
nodeStates: /* @__PURE__ */ new Map(),
|
|
3550
|
+
nodeResults: /* @__PURE__ */ new Map(),
|
|
3551
|
+
stepsCompleted: 0,
|
|
3552
|
+
finished: false
|
|
3553
|
+
};
|
|
3554
|
+
this.state.nodeStates.set(this.proposerNode.id, "pending");
|
|
3555
|
+
this.state.nodeStates.set(this.reviewerNode.id, "pending");
|
|
3556
|
+
}
|
|
3557
|
+
throwIfAborted() {
|
|
3558
|
+
if (this.abortController.signal.aborted) {
|
|
3559
|
+
throw new GraphAbortedError();
|
|
3560
|
+
}
|
|
3138
3561
|
}
|
|
3139
3562
|
/** 执行 Debate */
|
|
3140
3563
|
async run(input) {
|
|
3564
|
+
this.resetAbortController();
|
|
3141
3565
|
const ctx = createSharedContext({
|
|
3142
3566
|
meta: { traceId: `debate-${Date.now()}`, startTime: Date.now() }
|
|
3143
3567
|
});
|
|
3568
|
+
storeOriginalInput(ctx, input);
|
|
3569
|
+
const emit = this.eventSink ?? (() => {
|
|
3570
|
+
});
|
|
3144
3571
|
try {
|
|
3145
|
-
|
|
3146
|
-
});
|
|
3572
|
+
const result = await this.executeDebate(input, ctx, emit);
|
|
3573
|
+
emit({ type: "graph_done", result });
|
|
3574
|
+
return result;
|
|
3147
3575
|
} catch (err) {
|
|
3148
|
-
|
|
3576
|
+
const result = this.buildErrorResult(ctx, err);
|
|
3577
|
+
emit({ type: "graph_error", error: result.error ?? "" });
|
|
3578
|
+
return result;
|
|
3149
3579
|
}
|
|
3150
3580
|
}
|
|
3151
3581
|
/** 流式执行 Debate */
|
|
3152
|
-
|
|
3582
|
+
stream(input) {
|
|
3583
|
+
this.resetAbortController();
|
|
3153
3584
|
const ctx = createSharedContext({
|
|
3154
3585
|
meta: { traceId: `debate-${Date.now()}`, startTime: Date.now() }
|
|
3155
3586
|
});
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
}
|
|
3170
|
-
).finally(() => {
|
|
3171
|
-
done = true;
|
|
3172
|
-
resolveEvent?.();
|
|
3173
|
-
});
|
|
3174
|
-
while (!done || eventQueue.length > 0) {
|
|
3175
|
-
if (eventQueue.length > 0) {
|
|
3176
|
-
yield eventQueue.shift();
|
|
3177
|
-
} else {
|
|
3178
|
-
await new Promise((resolve) => {
|
|
3179
|
-
resolveEvent = resolve;
|
|
3180
|
-
});
|
|
3181
|
-
}
|
|
3182
|
-
}
|
|
3183
|
-
await graphPromise;
|
|
3587
|
+
storeOriginalInput(ctx, input);
|
|
3588
|
+
return createEventStream(
|
|
3589
|
+
(emit) => this.executeDebate(input, ctx, emit).then(
|
|
3590
|
+
(result) => {
|
|
3591
|
+
emit({ type: "graph_done", result });
|
|
3592
|
+
},
|
|
3593
|
+
(err) => {
|
|
3594
|
+
this.state.error = err instanceof Error ? err.message : String(err);
|
|
3595
|
+
emit({ type: "graph_error", error: this.state.error });
|
|
3596
|
+
}
|
|
3597
|
+
),
|
|
3598
|
+
this.eventSink
|
|
3599
|
+
);
|
|
3184
3600
|
}
|
|
3185
3601
|
/** 核心执行逻辑 */
|
|
3186
3602
|
async executeDebate(input, ctx, emit) {
|
|
@@ -3192,10 +3608,11 @@ ${proposerResult.content}`;
|
|
|
3192
3608
|
let convergeReason = "";
|
|
3193
3609
|
let currentInput = input;
|
|
3194
3610
|
for (let round = 1; round <= this.maxRounds; round++) {
|
|
3611
|
+
this.throwIfAborted();
|
|
3195
3612
|
emit({ type: "round_start", round });
|
|
3196
3613
|
this.state.currentAgentId = this.proposerNode.id;
|
|
3197
3614
|
this.state.nodeStates.set(this.proposerNode.id, "running");
|
|
3198
|
-
emit({ type: "agent_start", agentId: this.proposerNode.id, agentName: this.proposerNode.name });
|
|
3615
|
+
emit({ type: "agent_start", agentId: this.proposerNode.id, agentName: this.proposerNode.name, input: toInputText(currentInput) });
|
|
3199
3616
|
try {
|
|
3200
3617
|
lastProposerResult = await executeNode(this.proposerNode, currentInput, ctx);
|
|
3201
3618
|
this.state.nodeStates.set(this.proposerNode.id, "completed");
|
|
@@ -3212,7 +3629,7 @@ ${proposerResult.content}`;
|
|
|
3212
3629
|
}
|
|
3213
3630
|
this.state.currentAgentId = this.reviewerNode.id;
|
|
3214
3631
|
this.state.nodeStates.set(this.reviewerNode.id, "running");
|
|
3215
|
-
emit({ type: "agent_start", agentId: this.reviewerNode.id, agentName: this.reviewerNode.name });
|
|
3632
|
+
emit({ type: "agent_start", agentId: this.reviewerNode.id, agentName: this.reviewerNode.name, input: lastProposerResult.content });
|
|
3216
3633
|
try {
|
|
3217
3634
|
lastReviewerResult = await executeNode(this.reviewerNode, lastProposerResult.content, ctx);
|
|
3218
3635
|
this.state.nodeStates.set(this.reviewerNode.id, "completed");
|
|
@@ -3251,16 +3668,20 @@ ${proposerResult.content}`;
|
|
|
3251
3668
|
}
|
|
3252
3669
|
buildErrorResult(ctx, err) {
|
|
3253
3670
|
this.state.finished = true;
|
|
3671
|
+
const aborted = err instanceof GraphAbortedError;
|
|
3672
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3673
|
+
this.state.error = errorMsg;
|
|
3674
|
+
const lastCompleted = [...this.state.nodeResults.values()].at(-1);
|
|
3254
3675
|
return {
|
|
3255
|
-
content: "",
|
|
3676
|
+
content: aborted ? lastCompleted?.content ?? "" : "",
|
|
3256
3677
|
lastAgentId: this.proposerNode.id,
|
|
3257
3678
|
agentResults: new Map(this.state.nodeResults),
|
|
3258
3679
|
totalUsage: {},
|
|
3259
3680
|
stepsCompleted: this.state.stepsCompleted,
|
|
3260
|
-
stopReason: "error",
|
|
3681
|
+
stopReason: aborted ? "aborted" : "error",
|
|
3261
3682
|
context: ctx,
|
|
3262
3683
|
success: false,
|
|
3263
|
-
error:
|
|
3684
|
+
error: errorMsg
|
|
3264
3685
|
};
|
|
3265
3686
|
}
|
|
3266
3687
|
mergeUsage(total, usage) {
|
|
@@ -3273,7 +3694,8 @@ ${proposerResult.content}`;
|
|
|
3273
3694
|
// patterns/debate.ts
|
|
3274
3695
|
var DebateGraphImpl = class {
|
|
3275
3696
|
executor;
|
|
3276
|
-
|
|
3697
|
+
/** on() 注册的监听器,按 MultiAgentEvent.type 分发 */
|
|
3698
|
+
bus = new SimpleEventBus();
|
|
3277
3699
|
constructor(proposer, reviewer, opts) {
|
|
3278
3700
|
this.executor = new DebateExecutor(proposer, reviewer, opts);
|
|
3279
3701
|
}
|
|
@@ -3290,23 +3712,21 @@ var DebateGraphImpl = class {
|
|
|
3290
3712
|
throw new Error("Debate \u6A21\u5F0F\u4E0D\u652F\u6301 setFinish");
|
|
3291
3713
|
}
|
|
3292
3714
|
async run(input) {
|
|
3715
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
3293
3716
|
return this.executor.run(input);
|
|
3294
3717
|
}
|
|
3295
3718
|
async *stream(input) {
|
|
3719
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
3296
3720
|
yield* this.executor.stream(input);
|
|
3297
3721
|
}
|
|
3298
3722
|
getState() {
|
|
3299
3723
|
return this.executor.getState();
|
|
3300
3724
|
}
|
|
3301
3725
|
abort() {
|
|
3726
|
+
this.executor.abort();
|
|
3302
3727
|
}
|
|
3303
3728
|
on(event, listener) {
|
|
3304
|
-
|
|
3305
|
-
if (!set) {
|
|
3306
|
-
set = /* @__PURE__ */ new Set();
|
|
3307
|
-
this.eventListeners.set(event, set);
|
|
3308
|
-
}
|
|
3309
|
-
set.add(listener);
|
|
3729
|
+
this.bus.on(event, listener);
|
|
3310
3730
|
return this;
|
|
3311
3731
|
}
|
|
3312
3732
|
};
|
|
@@ -3320,7 +3740,11 @@ var MapReduceExecutor = class {
|
|
|
3320
3740
|
reducerNode;
|
|
3321
3741
|
split;
|
|
3322
3742
|
concurrency;
|
|
3743
|
+
onMapperError;
|
|
3323
3744
|
reduceInputFormat;
|
|
3745
|
+
abortController = new AbortController();
|
|
3746
|
+
/** 外部事件监听(on() API 的底层接线) */
|
|
3747
|
+
eventSink;
|
|
3324
3748
|
state = {
|
|
3325
3749
|
nodeStates: /* @__PURE__ */ new Map(),
|
|
3326
3750
|
nodeResults: /* @__PURE__ */ new Map(),
|
|
@@ -3332,6 +3756,7 @@ var MapReduceExecutor = class {
|
|
|
3332
3756
|
this.reducerNode = reducer;
|
|
3333
3757
|
this.split = opts.split;
|
|
3334
3758
|
this.concurrency = opts.concurrency ?? Infinity;
|
|
3759
|
+
this.onMapperError = opts.onMapperError ?? "fail-fast";
|
|
3335
3760
|
this.reduceInputFormat = opts.reduceInputFormat ?? ((mapperResults) => {
|
|
3336
3761
|
const parts = [];
|
|
3337
3762
|
for (const [idx, result] of mapperResults) {
|
|
@@ -3344,132 +3769,98 @@ ${result.content}`);
|
|
|
3344
3769
|
this.state.nodeStates.set(reducer.id, "pending");
|
|
3345
3770
|
}
|
|
3346
3771
|
getState() {
|
|
3347
|
-
return {
|
|
3772
|
+
return {
|
|
3773
|
+
...this.state,
|
|
3774
|
+
nodeStates: new Map(this.state.nodeStates),
|
|
3775
|
+
nodeResults: new Map(this.state.nodeResults)
|
|
3776
|
+
};
|
|
3348
3777
|
}
|
|
3349
|
-
/**
|
|
3350
|
-
|
|
3778
|
+
/** 注入外部事件监听(由 AgentGraph 实现的 on() 接线) */
|
|
3779
|
+
setEventSink(sink) {
|
|
3780
|
+
this.eventSink = sink;
|
|
3781
|
+
return this;
|
|
3782
|
+
}
|
|
3783
|
+
abort() {
|
|
3784
|
+
this.abortController.abort();
|
|
3785
|
+
}
|
|
3786
|
+
/** 每次 run/stream 前重置中止信号与执行状态 */
|
|
3787
|
+
resetAbortController() {
|
|
3788
|
+
this.abortController = new AbortController();
|
|
3789
|
+
this.state = {
|
|
3790
|
+
nodeStates: /* @__PURE__ */ new Map(),
|
|
3791
|
+
nodeResults: /* @__PURE__ */ new Map(),
|
|
3792
|
+
stepsCompleted: 0,
|
|
3793
|
+
finished: false
|
|
3794
|
+
};
|
|
3795
|
+
this.state.nodeStates.set(this.mapperNode.id, "pending");
|
|
3796
|
+
this.state.nodeStates.set(this.reducerNode.id, "pending");
|
|
3797
|
+
}
|
|
3798
|
+
throwIfAborted() {
|
|
3799
|
+
if (this.abortController.signal.aborted) {
|
|
3800
|
+
throw new GraphAbortedError();
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
/** 拆分输入并校验(每次 run/stream 只调用一次 split,避免副作用放大) */
|
|
3804
|
+
splitInput(input) {
|
|
3351
3805
|
const inputText = typeof input === "string" ? input : input.message;
|
|
3352
3806
|
const chunks = this.split(inputText);
|
|
3353
3807
|
if (chunks.length === 0) {
|
|
3354
3808
|
throw new Error("MapReduce: split \u51FD\u6570\u8FD4\u56DE\u4E86\u7A7A\u6570\u7EC4\uFF0C\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u5B50\u4EFB\u52A1");
|
|
3355
3809
|
}
|
|
3810
|
+
return chunks;
|
|
3811
|
+
}
|
|
3812
|
+
/** 执行 MapReduce */
|
|
3813
|
+
async run(input) {
|
|
3814
|
+
this.resetAbortController();
|
|
3815
|
+
const chunks = this.splitInput(input);
|
|
3356
3816
|
const ctx = createSharedContext({
|
|
3357
3817
|
meta: { traceId: `mr-${Date.now()}`, startTime: Date.now() }
|
|
3358
3818
|
});
|
|
3819
|
+
storeOriginalInput(ctx, input);
|
|
3820
|
+
const emit = this.eventSink ?? (() => {
|
|
3821
|
+
});
|
|
3359
3822
|
try {
|
|
3360
|
-
|
|
3361
|
-
});
|
|
3823
|
+
const result = await this.executeMapReduce(chunks, ctx, emit);
|
|
3824
|
+
emit({ type: "graph_done", result });
|
|
3825
|
+
return result;
|
|
3362
3826
|
} catch (err) {
|
|
3363
|
-
|
|
3827
|
+
const result = this.buildErrorResult(ctx, err);
|
|
3828
|
+
emit({ type: "graph_error", error: result.error ?? "" });
|
|
3829
|
+
return result;
|
|
3364
3830
|
}
|
|
3365
3831
|
}
|
|
3366
3832
|
/** 流式执行 MapReduce */
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
const chunks = this.
|
|
3370
|
-
if (chunks.length === 0) {
|
|
3371
|
-
throw new Error("MapReduce: split \u51FD\u6570\u8FD4\u56DE\u4E86\u7A7A\u6570\u7EC4\uFF0C\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u5B50\u4EFB\u52A1");
|
|
3372
|
-
}
|
|
3833
|
+
stream(input) {
|
|
3834
|
+
this.resetAbortController();
|
|
3835
|
+
const chunks = this.splitInput(input);
|
|
3373
3836
|
const ctx = createSharedContext({
|
|
3374
3837
|
meta: { traceId: `mr-${Date.now()}`, startTime: Date.now() }
|
|
3375
3838
|
});
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
}
|
|
3390
|
-
).finally(() => {
|
|
3391
|
-
done = true;
|
|
3392
|
-
resolveEvent?.();
|
|
3393
|
-
});
|
|
3394
|
-
while (!done || eventQueue.length > 0) {
|
|
3395
|
-
if (eventQueue.length > 0) {
|
|
3396
|
-
yield eventQueue.shift();
|
|
3397
|
-
} else {
|
|
3398
|
-
await new Promise((resolve) => {
|
|
3399
|
-
resolveEvent = resolve;
|
|
3400
|
-
});
|
|
3401
|
-
}
|
|
3402
|
-
}
|
|
3403
|
-
await graphPromise;
|
|
3839
|
+
storeOriginalInput(ctx, input);
|
|
3840
|
+
return createEventStream(
|
|
3841
|
+
(emit) => this.executeMapReduce(chunks, ctx, emit).then(
|
|
3842
|
+
(result) => {
|
|
3843
|
+
emit({ type: "graph_done", result });
|
|
3844
|
+
},
|
|
3845
|
+
(err) => {
|
|
3846
|
+
this.state.error = err instanceof Error ? err.message : String(err);
|
|
3847
|
+
emit({ type: "graph_error", error: this.state.error });
|
|
3848
|
+
}
|
|
3849
|
+
),
|
|
3850
|
+
this.eventSink
|
|
3851
|
+
);
|
|
3404
3852
|
}
|
|
3405
3853
|
/** 核心执行逻辑 */
|
|
3406
|
-
async executeMapReduce(
|
|
3407
|
-
let stepsCompleted = 0;
|
|
3854
|
+
async executeMapReduce(chunks, ctx, emit) {
|
|
3408
3855
|
const totalUsage = {};
|
|
3409
|
-
|
|
3410
|
-
const chunks = this.split(inputText);
|
|
3411
|
-
const mapperResults = /* @__PURE__ */ new Map();
|
|
3856
|
+
this.throwIfAborted();
|
|
3412
3857
|
this.state.nodeStates.set(this.mapperNode.id, "running");
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
const result = await executeNode(this.mapperNode, chunk, ctx);
|
|
3420
|
-
this.state.nodeResults.set(`${this.mapperNode.id}_${index}`, result);
|
|
3421
|
-
this.mergeUsage(totalUsage, result.usage);
|
|
3422
|
-
stepsCompleted++;
|
|
3423
|
-
this.state.stepsCompleted = stepsCompleted;
|
|
3424
|
-
emit({ type: "agent_result", agentId: `${this.mapperNode.id}_${index}`, agentName: `${this.mapperNode.name}#${index + 1}`, result });
|
|
3425
|
-
return { index, result };
|
|
3426
|
-
} catch (err) {
|
|
3427
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3428
|
-
emit({ type: "agent_error", agentId: `${this.mapperNode.id}_${index}`, agentName: `${this.mapperNode.name}#${index + 1}`, error: errorMsg });
|
|
3429
|
-
throw err;
|
|
3430
|
-
}
|
|
3431
|
-
});
|
|
3432
|
-
const settled = await Promise.allSettled(promises);
|
|
3433
|
-
for (const s of settled) {
|
|
3434
|
-
if (s.status === "fulfilled") {
|
|
3435
|
-
mapperResults.set(s.value.index, s.value.result);
|
|
3436
|
-
}
|
|
3437
|
-
}
|
|
3438
|
-
} else {
|
|
3439
|
-
let index = 0;
|
|
3440
|
-
const executing = /* @__PURE__ */ new Set();
|
|
3441
|
-
const enqueue = () => {
|
|
3442
|
-
if (index >= chunks.length) return null;
|
|
3443
|
-
const currentIndex = index++;
|
|
3444
|
-
const chunk = chunks[currentIndex];
|
|
3445
|
-
const p = (async () => {
|
|
3446
|
-
emit({ type: "agent_start", agentId: `${this.mapperNode.id}_${currentIndex}`, agentName: `${this.mapperNode.name}#${currentIndex + 1}` });
|
|
3447
|
-
try {
|
|
3448
|
-
const result = await executeNode(this.mapperNode, chunk, ctx);
|
|
3449
|
-
mapperResults.set(currentIndex, result);
|
|
3450
|
-
this.state.nodeResults.set(`${this.mapperNode.id}_${currentIndex}`, result);
|
|
3451
|
-
this.mergeUsage(totalUsage, result.usage);
|
|
3452
|
-
stepsCompleted++;
|
|
3453
|
-
this.state.stepsCompleted = stepsCompleted;
|
|
3454
|
-
emit({ type: "agent_result", agentId: `${this.mapperNode.id}_${currentIndex}`, agentName: `${this.mapperNode.name}#${currentIndex + 1}`, result });
|
|
3455
|
-
} catch (err) {
|
|
3456
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3457
|
-
emit({ type: "agent_error", agentId: `${this.mapperNode.id}_${currentIndex}`, agentName: `${this.mapperNode.name}#${currentIndex + 1}`, error: errorMsg });
|
|
3458
|
-
throw err;
|
|
3459
|
-
}
|
|
3460
|
-
})();
|
|
3461
|
-
executing.add(p);
|
|
3462
|
-
p.finally(() => executing.delete(p));
|
|
3463
|
-
return p;
|
|
3464
|
-
};
|
|
3465
|
-
for (let i = 0; i < this.concurrency && index < chunks.length; i++) {
|
|
3466
|
-
enqueue();
|
|
3467
|
-
}
|
|
3468
|
-
while (executing.size > 0) {
|
|
3469
|
-
await Promise.race(executing);
|
|
3470
|
-
enqueue();
|
|
3471
|
-
}
|
|
3472
|
-
}
|
|
3858
|
+
chunks.forEach((_, i) => {
|
|
3859
|
+
this.state.nodeStates.set(`${this.mapperNode.id}_${i}`, "pending");
|
|
3860
|
+
});
|
|
3861
|
+
const { results: mapperResults, failed } = await this.runMappers(chunks, ctx, emit, totalUsage);
|
|
3862
|
+
let stepsCompleted = mapperResults.size + failed.length;
|
|
3863
|
+
this.state.stepsCompleted = stepsCompleted;
|
|
3473
3864
|
this.state.nodeStates.set(this.mapperNode.id, "completed");
|
|
3474
3865
|
const mapperResultsForEmit = /* @__PURE__ */ new Map();
|
|
3475
3866
|
for (const [idx, result] of mapperResults) {
|
|
@@ -3477,10 +3868,14 @@ ${result.content}`);
|
|
|
3477
3868
|
}
|
|
3478
3869
|
emit({ type: "parallel_done", results: mapperResultsForEmit });
|
|
3479
3870
|
ctx.blackboard.set("mapper_results", mapperResults);
|
|
3871
|
+
if (failed.length > 0 && mapperResults.size === 0) {
|
|
3872
|
+
throw new Error(`MapReduce: \u6240\u6709 mapper \u5747\u5931\u8D25\uFF08${failed.length}/${chunks.length}\uFF09`);
|
|
3873
|
+
}
|
|
3480
3874
|
const reduceInput = this.reduceInputFormat(mapperResults);
|
|
3875
|
+
this.throwIfAborted();
|
|
3481
3876
|
this.state.currentAgentId = this.reducerNode.id;
|
|
3482
3877
|
this.state.nodeStates.set(this.reducerNode.id, "running");
|
|
3483
|
-
emit({ type: "agent_start", agentId: this.reducerNode.id, agentName: this.reducerNode.name });
|
|
3878
|
+
emit({ type: "agent_start", agentId: this.reducerNode.id, agentName: this.reducerNode.name, input: reduceInput });
|
|
3484
3879
|
let reducerResult;
|
|
3485
3880
|
try {
|
|
3486
3881
|
reducerResult = await executeNode(this.reducerNode, reduceInput, ctx);
|
|
@@ -3497,29 +3892,94 @@ ${result.content}`);
|
|
|
3497
3892
|
throw err;
|
|
3498
3893
|
}
|
|
3499
3894
|
this.state.finished = true;
|
|
3895
|
+
const hasFailures = failed.length > 0;
|
|
3500
3896
|
return {
|
|
3501
3897
|
content: reducerResult.content,
|
|
3502
3898
|
lastAgentId: this.reducerNode.id,
|
|
3503
3899
|
agentResults: new Map(this.state.nodeResults),
|
|
3504
3900
|
totalUsage,
|
|
3505
3901
|
stepsCompleted,
|
|
3506
|
-
stopReason: "completed",
|
|
3902
|
+
stopReason: hasFailures ? "partial_failure" : "completed",
|
|
3507
3903
|
context: ctx,
|
|
3508
|
-
success: true
|
|
3904
|
+
success: true,
|
|
3905
|
+
...hasFailures ? { failedAgents: failed } : {}
|
|
3509
3906
|
};
|
|
3510
3907
|
}
|
|
3908
|
+
/** 并行执行所有 mapper 子任务(统一处理并发限制与失败策略) */
|
|
3909
|
+
async runMappers(chunks, ctx, emit, totalUsage) {
|
|
3910
|
+
const results = /* @__PURE__ */ new Map();
|
|
3911
|
+
const failed = [];
|
|
3912
|
+
const skip = this.onMapperError === "skip";
|
|
3913
|
+
const mapperId = this.mapperNode.id;
|
|
3914
|
+
const mapperAgentIds = chunks.map((_, i) => `${mapperId}_${i}`);
|
|
3915
|
+
emit({ type: "parallel_start", agentIds: mapperAgentIds });
|
|
3916
|
+
const runOne = async (index) => {
|
|
3917
|
+
const agentId = `${mapperId}_${index}`;
|
|
3918
|
+
const agentName = `${this.mapperNode.name}#${index + 1}`;
|
|
3919
|
+
emit({ type: "agent_start", agentId, agentName, input: chunks[index] });
|
|
3920
|
+
this.state.nodeStates.set(agentId, "running");
|
|
3921
|
+
try {
|
|
3922
|
+
const result = await executeNode(this.mapperNode, chunks[index], ctx);
|
|
3923
|
+
this.state.nodeResults.set(agentId, result);
|
|
3924
|
+
this.state.nodeStates.set(agentId, "completed");
|
|
3925
|
+
this.mergeUsage(totalUsage, result.usage);
|
|
3926
|
+
results.set(index, result);
|
|
3927
|
+
emit({ type: "agent_result", agentId, agentName, result });
|
|
3928
|
+
} catch (err) {
|
|
3929
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3930
|
+
this.state.nodeStates.set(agentId, "failed");
|
|
3931
|
+
emit({ type: "agent_error", agentId, agentName, error: errorMsg });
|
|
3932
|
+
if (!skip) throw err;
|
|
3933
|
+
failed.push(agentId);
|
|
3934
|
+
}
|
|
3935
|
+
};
|
|
3936
|
+
if (this.concurrency >= chunks.length) {
|
|
3937
|
+
const promises = chunks.map((_, i) => runOne(i));
|
|
3938
|
+
if (!skip) {
|
|
3939
|
+
await Promise.all(promises);
|
|
3940
|
+
} else {
|
|
3941
|
+
await Promise.allSettled(promises);
|
|
3942
|
+
}
|
|
3943
|
+
} else {
|
|
3944
|
+
let index = 0;
|
|
3945
|
+
const executing = /* @__PURE__ */ new Set();
|
|
3946
|
+
const enqueue = () => {
|
|
3947
|
+
if (index >= chunks.length) return null;
|
|
3948
|
+
const i = index++;
|
|
3949
|
+
const p = runOne(i).finally(() => {
|
|
3950
|
+
executing.delete(p);
|
|
3951
|
+
});
|
|
3952
|
+
executing.add(p);
|
|
3953
|
+
p.catch(() => {
|
|
3954
|
+
});
|
|
3955
|
+
return p;
|
|
3956
|
+
};
|
|
3957
|
+
for (let i = 0; i < this.concurrency && index < chunks.length; i++) {
|
|
3958
|
+
enqueue();
|
|
3959
|
+
}
|
|
3960
|
+
while (executing.size > 0) {
|
|
3961
|
+
await Promise.race(executing);
|
|
3962
|
+
enqueue();
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
return { results, failed };
|
|
3966
|
+
}
|
|
3511
3967
|
buildErrorResult(ctx, err) {
|
|
3512
3968
|
this.state.finished = true;
|
|
3969
|
+
const aborted = err instanceof GraphAbortedError;
|
|
3970
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3971
|
+
this.state.error = errorMsg;
|
|
3972
|
+
const lastCompleted = [...this.state.nodeResults.values()].at(-1);
|
|
3513
3973
|
return {
|
|
3514
|
-
content: "",
|
|
3974
|
+
content: aborted ? lastCompleted?.content ?? "" : "",
|
|
3515
3975
|
lastAgentId: this.mapperNode.id,
|
|
3516
3976
|
agentResults: new Map(this.state.nodeResults),
|
|
3517
3977
|
totalUsage: {},
|
|
3518
3978
|
stepsCompleted: this.state.stepsCompleted,
|
|
3519
|
-
stopReason: "error",
|
|
3979
|
+
stopReason: aborted ? "aborted" : "error",
|
|
3520
3980
|
context: ctx,
|
|
3521
3981
|
success: false,
|
|
3522
|
-
error:
|
|
3982
|
+
error: errorMsg
|
|
3523
3983
|
};
|
|
3524
3984
|
}
|
|
3525
3985
|
mergeUsage(total, usage) {
|
|
@@ -3532,7 +3992,8 @@ ${result.content}`);
|
|
|
3532
3992
|
// patterns/map-reduce.ts
|
|
3533
3993
|
var MapReduceGraphImpl = class {
|
|
3534
3994
|
executor;
|
|
3535
|
-
|
|
3995
|
+
/** on() 注册的监听器,按 MultiAgentEvent.type 分发 */
|
|
3996
|
+
bus = new SimpleEventBus();
|
|
3536
3997
|
constructor(mapper, reducer, opts) {
|
|
3537
3998
|
this.executor = new MapReduceExecutor(mapper, reducer, opts);
|
|
3538
3999
|
}
|
|
@@ -3549,23 +4010,21 @@ var MapReduceGraphImpl = class {
|
|
|
3549
4010
|
throw new Error("MapReduce \u6A21\u5F0F\u4E0D\u652F\u6301 setFinish");
|
|
3550
4011
|
}
|
|
3551
4012
|
async run(input) {
|
|
4013
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
3552
4014
|
return this.executor.run(input);
|
|
3553
4015
|
}
|
|
3554
4016
|
async *stream(input) {
|
|
4017
|
+
this.executor.setEventSink((event) => this.bus.emit(event.type, event));
|
|
3555
4018
|
yield* this.executor.stream(input);
|
|
3556
4019
|
}
|
|
3557
4020
|
getState() {
|
|
3558
4021
|
return this.executor.getState();
|
|
3559
4022
|
}
|
|
3560
4023
|
abort() {
|
|
4024
|
+
this.executor.abort();
|
|
3561
4025
|
}
|
|
3562
4026
|
on(event, listener) {
|
|
3563
|
-
|
|
3564
|
-
if (!set) {
|
|
3565
|
-
set = /* @__PURE__ */ new Set();
|
|
3566
|
-
this.eventListeners.set(event, set);
|
|
3567
|
-
}
|
|
3568
|
-
set.add(listener);
|
|
4027
|
+
this.bus.on(event, listener);
|
|
3569
4028
|
return this;
|
|
3570
4029
|
}
|
|
3571
4030
|
};
|
|
@@ -3786,6 +4245,13 @@ var McpServerHost = class {
|
|
|
3786
4245
|
notifyToolsListChanged() {
|
|
3787
4246
|
this.onNotification?.(createListChangedNotification());
|
|
3788
4247
|
}
|
|
4248
|
+
/**
|
|
4249
|
+
* 注入通知分发钩子(由传输层如 http-runner 调用):host 经此回调发出主动通知。
|
|
4250
|
+
* 与 setOutboundRequest 对称。重复调用以最后一次为准。
|
|
4251
|
+
*/
|
|
4252
|
+
setOnNotification(fn) {
|
|
4253
|
+
this.onNotification = fn;
|
|
4254
|
+
}
|
|
3789
4255
|
/**
|
|
3790
4256
|
* 注入出站请求通道(由传输层如 stdio-runner 调用):写入 JSON-RPC 请求
|
|
3791
4257
|
* 并关联响应。注入后 `sampleLLM` 可向外部 client 请求 LLM 补全。
|
|
@@ -4197,6 +4663,7 @@ var GraphDebugger = class {
|
|
|
4197
4663
|
const graphStartTime = Date.now();
|
|
4198
4664
|
const steps = [];
|
|
4199
4665
|
let stepIndex = 0;
|
|
4666
|
+
let finalResult;
|
|
4200
4667
|
for await (const event of this.graph.stream(input)) {
|
|
4201
4668
|
if (event.type === "agent_start") {
|
|
4202
4669
|
stepIndex++;
|
|
@@ -4206,7 +4673,7 @@ var GraphDebugger = class {
|
|
|
4206
4673
|
agentName: event.agentName,
|
|
4207
4674
|
startTime: Date.now(),
|
|
4208
4675
|
duration: 0,
|
|
4209
|
-
input: "",
|
|
4676
|
+
input: event.input ?? "",
|
|
4210
4677
|
output: "",
|
|
4211
4678
|
state: "running"
|
|
4212
4679
|
});
|
|
@@ -4231,6 +4698,8 @@ var GraphDebugger = class {
|
|
|
4231
4698
|
step.error = event.error;
|
|
4232
4699
|
step.state = "failed";
|
|
4233
4700
|
}
|
|
4701
|
+
} else if (event.type === "graph_done") {
|
|
4702
|
+
finalResult = event.result;
|
|
4234
4703
|
}
|
|
4235
4704
|
}
|
|
4236
4705
|
const state = this.graph.getState();
|
|
@@ -4241,10 +4710,10 @@ var GraphDebugger = class {
|
|
|
4241
4710
|
duration: graphDuration,
|
|
4242
4711
|
steps,
|
|
4243
4712
|
result: {
|
|
4244
|
-
success: !state.error,
|
|
4245
|
-
content:
|
|
4246
|
-
stopReason: state.error ? "error" : "completed",
|
|
4247
|
-
stepsCompleted: state.stepsCompleted
|
|
4713
|
+
success: finalResult ? finalResult.success : !state.error,
|
|
4714
|
+
content: finalResult?.content ?? "",
|
|
4715
|
+
stopReason: finalResult?.stopReason ?? (state.error ? "error" : "completed"),
|
|
4716
|
+
stepsCompleted: finalResult?.stepsCompleted ?? state.stepsCompleted
|
|
4248
4717
|
}
|
|
4249
4718
|
};
|
|
4250
4719
|
}
|
|
@@ -4296,13 +4765,16 @@ function createDebugger(graph) {
|
|
|
4296
4765
|
return new GraphDebugger(graph);
|
|
4297
4766
|
}
|
|
4298
4767
|
export {
|
|
4768
|
+
GraphAbortedError,
|
|
4299
4769
|
GraphDebugger,
|
|
4300
4770
|
MCPBridge,
|
|
4771
|
+
NodeTimeoutError,
|
|
4301
4772
|
SimpleEventBus,
|
|
4302
4773
|
SimpleToolRegistry,
|
|
4303
4774
|
createAgentGraph,
|
|
4304
4775
|
createDebate,
|
|
4305
4776
|
createDebugger,
|
|
4777
|
+
createEventStream,
|
|
4306
4778
|
createMCPBridge,
|
|
4307
4779
|
createMapReduce,
|
|
4308
4780
|
createMultiAgentMcpServerHost,
|