network-ai 4.12.1 → 4.13.0
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/INTEGRATION_GUIDE.md +1 -1
- package/README.md +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adapter-hooks.d.ts +29 -0
- package/dist/lib/adapter-hooks.d.ts.map +1 -1
- package/dist/lib/adapter-hooks.js +56 -0
- package/dist/lib/adapter-hooks.js.map +1 -1
- package/dist/lib/confidence-filter.d.ts +141 -0
- package/dist/lib/confidence-filter.d.ts.map +1 -0
- package/dist/lib/confidence-filter.js +210 -0
- package/dist/lib/confidence-filter.js.map +1 -0
- package/dist/lib/fan-out.d.ts +136 -0
- package/dist/lib/fan-out.d.ts.map +1 -0
- package/dist/lib/fan-out.js +221 -0
- package/dist/lib/fan-out.js.map +1 -0
- package/dist/lib/phase-pipeline.d.ts +153 -0
- package/dist/lib/phase-pipeline.d.ts.map +1 -0
- package/dist/lib/phase-pipeline.js +216 -0
- package/dist/lib/phase-pipeline.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fan-Out / Fan-In — Parallel agent spawning and result aggregation
|
|
4
|
+
*
|
|
5
|
+
* Launches multiple agents in parallel (fan-out) and combines their results
|
|
6
|
+
* using pluggable strategies (fan-in). Supports concurrency limits, timeouts,
|
|
7
|
+
* and custom aggregation. Inspired by Claude Code's parallel agent patterns.
|
|
8
|
+
*
|
|
9
|
+
* @module FanOutFanIn
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.FanOutFanIn = void 0;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// FAN-OUT / FAN-IN
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Parallel agent execution with pluggable result aggregation.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const fanout = new FanOutFanIn(registry, { agentId: 'orchestrator' });
|
|
23
|
+
*
|
|
24
|
+
* const steps: FanOutStep[] = [
|
|
25
|
+
* { agentId: 'researcher-a', payload: { action: 'search', params: { q: 'AI safety' } }, label: 'web' },
|
|
26
|
+
* { agentId: 'researcher-b', payload: { action: 'search', params: { q: 'AI safety' } }, label: 'papers' },
|
|
27
|
+
* { agentId: 'researcher-c', payload: { action: 'search', params: { q: 'AI safety' } }, label: 'news' },
|
|
28
|
+
* ];
|
|
29
|
+
*
|
|
30
|
+
* const results = await fanout.fanOut(steps, { concurrency: 2 });
|
|
31
|
+
* const aggregated = fanout.fanIn(results, 'merge');
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
class FanOutFanIn {
|
|
35
|
+
registry;
|
|
36
|
+
baseContext;
|
|
37
|
+
/**
|
|
38
|
+
* @param registry Adapter registry for agent execution
|
|
39
|
+
* @param baseContext Default execution context (merged with step-level overrides)
|
|
40
|
+
*/
|
|
41
|
+
constructor(registry, baseContext) {
|
|
42
|
+
this.registry = registry;
|
|
43
|
+
this.baseContext = baseContext;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Execute agents in parallel (fan-out phase).
|
|
47
|
+
*
|
|
48
|
+
* @param steps Steps to execute
|
|
49
|
+
* @param options Concurrency and timeout settings
|
|
50
|
+
*/
|
|
51
|
+
async fanOut(steps, options = {}) {
|
|
52
|
+
const concurrency = options.concurrency ?? steps.length;
|
|
53
|
+
const continueOnError = options.continueOnError ?? true;
|
|
54
|
+
const results = new Array(steps.length);
|
|
55
|
+
// Process in chunks of `concurrency`
|
|
56
|
+
for (let i = 0; i < steps.length; i += concurrency) {
|
|
57
|
+
const chunk = steps.slice(i, i + concurrency);
|
|
58
|
+
const chunkPromises = chunk.map((step, cIdx) => {
|
|
59
|
+
const idx = i + cIdx;
|
|
60
|
+
return this.executeStep(step, idx, options.timeoutMs);
|
|
61
|
+
});
|
|
62
|
+
const settled = await Promise.allSettled(chunkPromises);
|
|
63
|
+
for (let j = 0; j < settled.length; j++) {
|
|
64
|
+
const outcome = settled[j];
|
|
65
|
+
if (outcome.status === 'fulfilled') {
|
|
66
|
+
results[i + j] = outcome.value;
|
|
67
|
+
// Check for logical failure (agent returned success: false)
|
|
68
|
+
if (!continueOnError && !outcome.value.result.success) {
|
|
69
|
+
for (let k = i + j + 1; k < steps.length; k++) {
|
|
70
|
+
results[k] = {
|
|
71
|
+
agentId: steps[k].agentId,
|
|
72
|
+
label: steps[k].label,
|
|
73
|
+
index: k,
|
|
74
|
+
result: { success: false, error: { code: 'FANOUT_SKIPPED', message: 'Skipped due to earlier failure', recoverable: false } },
|
|
75
|
+
durationMs: 0,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return results.filter(Boolean);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const step = chunk[j];
|
|
83
|
+
results[i + j] = {
|
|
84
|
+
agentId: step.agentId,
|
|
85
|
+
label: step.label,
|
|
86
|
+
index: i + j,
|
|
87
|
+
result: { success: false, error: { code: 'FANOUT_ERROR', message: String(outcome.reason), recoverable: false } },
|
|
88
|
+
durationMs: 0,
|
|
89
|
+
};
|
|
90
|
+
if (!continueOnError) {
|
|
91
|
+
// Fill remaining with skipped results
|
|
92
|
+
for (let k = i + j + 1; k < steps.length; k++) {
|
|
93
|
+
results[k] = {
|
|
94
|
+
agentId: steps[k].agentId,
|
|
95
|
+
label: steps[k].label,
|
|
96
|
+
index: k,
|
|
97
|
+
result: { success: false, error: { code: 'FANOUT_SKIPPED', message: 'Skipped due to earlier failure', recoverable: false } },
|
|
98
|
+
durationMs: 0,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return results.filter(Boolean);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return results;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Aggregate results (fan-in phase).
|
|
110
|
+
*
|
|
111
|
+
* @param results Tagged results from fan-out
|
|
112
|
+
* @param strategy Aggregation strategy to apply
|
|
113
|
+
* @param customReducer Required when strategy is 'custom'
|
|
114
|
+
*/
|
|
115
|
+
fanIn(results, strategy = 'merge', customReducer) {
|
|
116
|
+
const totalMs = results.reduce((sum, r) => sum + r.durationMs, 0);
|
|
117
|
+
const successCount = results.filter(r => r.result.success).length;
|
|
118
|
+
const failureCount = results.length - successCount;
|
|
119
|
+
let success;
|
|
120
|
+
let data;
|
|
121
|
+
switch (strategy) {
|
|
122
|
+
case 'merge': {
|
|
123
|
+
success = successCount > 0;
|
|
124
|
+
data = results.map(r => ({
|
|
125
|
+
agentId: r.agentId,
|
|
126
|
+
label: r.label,
|
|
127
|
+
success: r.result.success,
|
|
128
|
+
data: r.result.data,
|
|
129
|
+
}));
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case 'firstSuccess': {
|
|
133
|
+
const first = results.find(r => r.result.success);
|
|
134
|
+
success = !!first;
|
|
135
|
+
data = first?.result.data ?? null;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case 'vote': {
|
|
139
|
+
const votes = new Map();
|
|
140
|
+
for (const r of results) {
|
|
141
|
+
if (!r.result.success)
|
|
142
|
+
continue;
|
|
143
|
+
const key = JSON.stringify(r.result.data);
|
|
144
|
+
const existing = votes.get(key);
|
|
145
|
+
if (existing) {
|
|
146
|
+
existing.count++;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
votes.set(key, { count: 1, data: r.result.data });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
let best;
|
|
153
|
+
for (const v of votes.values()) {
|
|
154
|
+
if (!best || v.count > best.count)
|
|
155
|
+
best = v;
|
|
156
|
+
}
|
|
157
|
+
success = !!best;
|
|
158
|
+
data = best?.data ?? null;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case 'consensus': {
|
|
162
|
+
const successResults = results.filter(r => r.result.success);
|
|
163
|
+
if (successResults.length === 0) {
|
|
164
|
+
success = false;
|
|
165
|
+
data = null;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const first = JSON.stringify(successResults[0].result.data);
|
|
169
|
+
const allAgree = successResults.every(r => JSON.stringify(r.result.data) === first);
|
|
170
|
+
success = allAgree;
|
|
171
|
+
data = allAgree ? successResults[0].result.data : null;
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case 'custom': {
|
|
176
|
+
if (!customReducer) {
|
|
177
|
+
throw new Error('customReducer is required when strategy is "custom"');
|
|
178
|
+
}
|
|
179
|
+
const reduced = customReducer(results);
|
|
180
|
+
success = reduced.success;
|
|
181
|
+
data = reduced.data;
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return { success, strategy, data, results, totalMs, successCount, failureCount };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Convenience: fan-out + fan-in in a single call.
|
|
189
|
+
*/
|
|
190
|
+
async run(steps, strategy = 'merge', options, customReducer) {
|
|
191
|
+
const results = await this.fanOut(steps, options);
|
|
192
|
+
return this.fanIn(results, strategy, customReducer);
|
|
193
|
+
}
|
|
194
|
+
// --------------------------------------------------------------------------
|
|
195
|
+
// Private helpers
|
|
196
|
+
// --------------------------------------------------------------------------
|
|
197
|
+
async executeStep(step, index, globalTimeout) {
|
|
198
|
+
const ctx = { ...this.baseContext, ...step.context };
|
|
199
|
+
const timeout = step.timeoutMs ?? globalTimeout;
|
|
200
|
+
const start = Date.now();
|
|
201
|
+
let result;
|
|
202
|
+
if (timeout) {
|
|
203
|
+
result = await Promise.race([
|
|
204
|
+
this.registry.executeAgent(step.agentId, step.payload, ctx),
|
|
205
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Fan-out timeout: agent "${step.agentId}" exceeded ${timeout}ms`)), timeout)),
|
|
206
|
+
]);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
result = await this.registry.executeAgent(step.agentId, step.payload, ctx);
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
agentId: step.agentId,
|
|
213
|
+
label: step.label,
|
|
214
|
+
index,
|
|
215
|
+
result,
|
|
216
|
+
durationMs: Date.now() - start,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
exports.FanOutFanIn = FanOutFanIn;
|
|
221
|
+
//# sourceMappingURL=fan-out.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fan-out.js","sourceRoot":"","sources":["../../lib/fan-out.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAyFH,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAa,WAAW;IACd,QAAQ,CAAkB;IAC1B,WAAW,CAAe;IAElC;;;OAGG;IACH,YAAY,QAAyB,EAAE,WAAyB;QAC9D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,KAAmB,EAAE,UAAyB,EAAE;QAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;QACxD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC;QACxD,MAAM,OAAO,GAAmB,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAExD,qCAAqC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;YAC9C,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;gBAC7C,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;gBACrB,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YACxD,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;YAExD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBACnC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;oBAC/B,4DAA4D;oBAC5D,IAAI,CAAC,eAAe,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;wBACtD,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;4BAC9C,OAAO,CAAC,CAAC,CAAC,GAAG;gCACX,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO;gCACzB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;gCACrB,KAAK,EAAE,CAAC;gCACR,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,gCAAgC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;gCAC5H,UAAU,EAAE,CAAC;6BACd,CAAC;wBACJ,CAAC;wBACD,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;oBACjC,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACtB,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG;wBACf,OAAO,EAAE,IAAI,CAAC,OAAO;wBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,KAAK,EAAE,CAAC,GAAG,CAAC;wBACZ,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;wBAChH,UAAU,EAAE,CAAC;qBACd,CAAC;oBACF,IAAI,CAAC,eAAe,EAAE,CAAC;wBACrB,sCAAsC;wBACtC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;4BAC9C,OAAO,CAAC,CAAC,CAAC,GAAG;gCACX,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO;gCACzB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;gCACrB,KAAK,EAAE,CAAC;gCACR,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,gCAAgC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;gCAC5H,UAAU,EAAE,CAAC;6BACd,CAAC;wBACJ,CAAC;wBACD,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;oBACjC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAuB,EAAE,WAA0B,OAAO,EAAE,aAA4B;QAC5F,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAClE,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC;QAEnD,IAAI,OAAgB,CAAC;QACrB,IAAI,IAAa,CAAC;QAElB,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,OAAO,GAAG,YAAY,GAAG,CAAC,CAAC;gBAC3B,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACvB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO;oBACzB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI;iBACpB,CAAC,CAAC,CAAC;gBACJ,MAAM;YACR,CAAC;YACD,KAAK,cAAc,CAAC,CAAC,CAAC;gBACpB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAClD,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC;gBAClB,IAAI,GAAG,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC;gBAClC,MAAM;YACR,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4C,CAAC;gBAClE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO;wBAAE,SAAS;oBAChC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAChC,IAAI,QAAQ,EAAE,CAAC;wBACb,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACnB,CAAC;yBAAM,CAAC;wBACN,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;oBACpD,CAAC;gBACH,CAAC;gBACD,IAAI,IAAkD,CAAC;gBACvD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC/B,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;wBAAE,IAAI,GAAG,CAAC,CAAC;gBAC9C,CAAC;gBACD,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjB,IAAI,GAAG,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC;gBAC1B,MAAM;YACR,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC7D,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAChC,OAAO,GAAG,KAAK,CAAC;oBAChB,IAAI,GAAG,IAAI,CAAC;gBACd,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBAC5D,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;oBACpF,OAAO,GAAG,QAAQ,CAAC;oBACnB,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzD,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;gBACzE,CAAC;gBACD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;gBACvC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;gBAC1B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;gBACpB,MAAM;YACR,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IACnF,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CACP,KAAmB,EACnB,WAA0B,OAAO,EACjC,OAAuB,EACvB,aAA4B;QAE5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtD,CAAC;IAED,6EAA6E;IAC7E,kBAAkB;IAClB,6EAA6E;IAErE,KAAK,CAAC,WAAW,CAAC,IAAgB,EAAE,KAAa,EAAE,aAAsB;QAC/E,MAAM,GAAG,GAAiB,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,aAAa,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,IAAI,MAAmB,CAAC;QACxB,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAC1B,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC;gBAC3D,IAAI,OAAO,CAAc,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CACrC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,OAAO,cAAc,OAAO,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAC/G;aACF,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7E,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK;YACL,MAAM;YACN,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAC/B,CAAC;IACJ,CAAC;CACF;AAzMD,kCAyMC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase Pipeline — Multi-phase workflows with approval gates
|
|
3
|
+
*
|
|
4
|
+
* Defines ordered execution phases. Each phase can optionally require human
|
|
5
|
+
* approval before proceeding. Phases may run their assigned agents in parallel
|
|
6
|
+
* or sequentially. Inspired by Claude Code's multi-phase orchestration pattern.
|
|
7
|
+
*
|
|
8
|
+
* @module PhasePipeline
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentPayload, AgentContext, AgentResult } from '../types/agent-adapter';
|
|
12
|
+
import type { AdapterRegistry } from '../adapters/adapter-registry';
|
|
13
|
+
/** Current execution status of a phase */
|
|
14
|
+
export type PhaseStatus = 'pending' | 'running' | 'awaiting_approval' | 'approved' | 'rejected' | 'completed' | 'failed' | 'skipped';
|
|
15
|
+
/**
|
|
16
|
+
* Defines a single phase in the pipeline.
|
|
17
|
+
*/
|
|
18
|
+
export interface PhaseDefinition {
|
|
19
|
+
/** Unique phase name */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Human-readable description */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Agent IDs to execute in this phase */
|
|
24
|
+
agents: string[];
|
|
25
|
+
/** If true, pipeline pauses after this phase until approval is granted */
|
|
26
|
+
requiresApproval?: boolean;
|
|
27
|
+
/** If true, agents within this phase run in parallel (default: sequential) */
|
|
28
|
+
parallel?: boolean;
|
|
29
|
+
/** Payload factory — builds the payload for each agent in this phase */
|
|
30
|
+
payloadFactory?: (agentId: string, previousResults: PhaseResult[]) => AgentPayload;
|
|
31
|
+
/** Maximum time (ms) allowed for this phase before timeout */
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Result from a single phase execution.
|
|
36
|
+
*/
|
|
37
|
+
export interface PhaseResult {
|
|
38
|
+
/** Phase name */
|
|
39
|
+
phaseName: string;
|
|
40
|
+
/** Final status */
|
|
41
|
+
status: PhaseStatus;
|
|
42
|
+
/** Agent results, keyed by agentId */
|
|
43
|
+
agentResults: Map<string, AgentResult>;
|
|
44
|
+
/** Phase execution time in milliseconds */
|
|
45
|
+
durationMs: number;
|
|
46
|
+
/** Approval metadata (if phase required approval) */
|
|
47
|
+
approval?: {
|
|
48
|
+
approvedBy?: string;
|
|
49
|
+
reason?: string;
|
|
50
|
+
timestamp: number;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Result from the entire pipeline execution.
|
|
55
|
+
*/
|
|
56
|
+
export interface PipelineResult {
|
|
57
|
+
/** Whether the entire pipeline completed successfully */
|
|
58
|
+
success: boolean;
|
|
59
|
+
/** Results per phase */
|
|
60
|
+
phases: PhaseResult[];
|
|
61
|
+
/** Total execution time in milliseconds */
|
|
62
|
+
totalMs: number;
|
|
63
|
+
/** Name of the phase that stopped the pipeline (if any) */
|
|
64
|
+
stoppedAt?: string;
|
|
65
|
+
/** Reason the pipeline stopped (rejection, failure, timeout) */
|
|
66
|
+
stopReason?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Callback signature for approval gates.
|
|
70
|
+
* Return `{ approved: true }` to proceed, `{ approved: false, reason }` to reject.
|
|
71
|
+
*/
|
|
72
|
+
export type ApprovalCallback = (phaseName: string, phaseResult: PhaseResult, pipelineContext: PipelineExecutionContext) => Promise<{
|
|
73
|
+
approved: boolean;
|
|
74
|
+
approvedBy?: string;
|
|
75
|
+
reason?: string;
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Options for creating a PhasePipeline.
|
|
79
|
+
*/
|
|
80
|
+
export interface PhasePipelineOptions {
|
|
81
|
+
/** Ordered list of phase definitions */
|
|
82
|
+
phases: PhaseDefinition[];
|
|
83
|
+
/** Called when a phase requires approval */
|
|
84
|
+
onApproval?: ApprovalCallback;
|
|
85
|
+
/** Called when each phase starts */
|
|
86
|
+
onPhaseStart?: (phaseName: string, index: number) => void;
|
|
87
|
+
/** Called when each phase completes */
|
|
88
|
+
onPhaseComplete?: (result: PhaseResult, index: number) => void;
|
|
89
|
+
/** If true, auto-approve all gates (useful for testing) */
|
|
90
|
+
autoApprove?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Runtime context available during pipeline execution.
|
|
94
|
+
*/
|
|
95
|
+
export interface PipelineExecutionContext {
|
|
96
|
+
/** Results from previously completed phases */
|
|
97
|
+
completedPhases: PhaseResult[];
|
|
98
|
+
/** Index of the current phase */
|
|
99
|
+
currentPhaseIndex: number;
|
|
100
|
+
/** Total number of phases */
|
|
101
|
+
totalPhases: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Orchestrates multi-phase workflows with optional approval gates.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const pipeline = new PhasePipeline(registry, baseContext, {
|
|
109
|
+
* phases: [
|
|
110
|
+
* { name: 'research', agents: ['researcher'], parallel: false },
|
|
111
|
+
* { name: 'review', agents: ['reviewer-a', 'reviewer-b'], parallel: true, requiresApproval: true },
|
|
112
|
+
* { name: 'publish', agents: ['publisher'] },
|
|
113
|
+
* ],
|
|
114
|
+
* onApproval: async (name, result) => {
|
|
115
|
+
* // In production: prompt the user
|
|
116
|
+
* return { approved: true, approvedBy: 'admin' };
|
|
117
|
+
* },
|
|
118
|
+
* });
|
|
119
|
+
*
|
|
120
|
+
* const result = await pipeline.run();
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare class PhasePipeline {
|
|
124
|
+
private registry;
|
|
125
|
+
private baseContext;
|
|
126
|
+
private options;
|
|
127
|
+
private phaseResults;
|
|
128
|
+
private _status;
|
|
129
|
+
constructor(registry: AdapterRegistry, baseContext: AgentContext, options: PhasePipelineOptions);
|
|
130
|
+
/** Current pipeline status */
|
|
131
|
+
get status(): string;
|
|
132
|
+
/** Results from all executed phases (even if pipeline was aborted) */
|
|
133
|
+
get results(): ReadonlyArray<PhaseResult>;
|
|
134
|
+
/** Phase definitions */
|
|
135
|
+
get phases(): ReadonlyArray<PhaseDefinition>;
|
|
136
|
+
/**
|
|
137
|
+
* Execute the entire pipeline, phase by phase.
|
|
138
|
+
*
|
|
139
|
+
* For each phase:
|
|
140
|
+
* 1. Run all assigned agents (parallel or sequential)
|
|
141
|
+
* 2. If `requiresApproval`, call the approval callback and wait
|
|
142
|
+
* 3. If rejected, stop the pipeline
|
|
143
|
+
* 4. Otherwise move to the next phase
|
|
144
|
+
*/
|
|
145
|
+
run(defaultPayload?: AgentPayload): Promise<PipelineResult>;
|
|
146
|
+
/**
|
|
147
|
+
* Reset the pipeline for re-execution.
|
|
148
|
+
*/
|
|
149
|
+
reset(): void;
|
|
150
|
+
private buildPayload;
|
|
151
|
+
private executeWithTimeout;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=phase-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-pipeline.d.ts","sourceRoot":"","sources":["../../lib/phase-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase Pipeline — Multi-phase workflows with approval gates
|
|
4
|
+
*
|
|
5
|
+
* Defines ordered execution phases. Each phase can optionally require human
|
|
6
|
+
* approval before proceeding. Phases may run their assigned agents in parallel
|
|
7
|
+
* or sequentially. Inspired by Claude Code's multi-phase orchestration pattern.
|
|
8
|
+
*
|
|
9
|
+
* @module PhasePipeline
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.PhasePipeline = void 0;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// PHASE PIPELINE
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Orchestrates multi-phase workflows with optional approval gates.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const pipeline = new PhasePipeline(registry, baseContext, {
|
|
23
|
+
* phases: [
|
|
24
|
+
* { name: 'research', agents: ['researcher'], parallel: false },
|
|
25
|
+
* { name: 'review', agents: ['reviewer-a', 'reviewer-b'], parallel: true, requiresApproval: true },
|
|
26
|
+
* { name: 'publish', agents: ['publisher'] },
|
|
27
|
+
* ],
|
|
28
|
+
* onApproval: async (name, result) => {
|
|
29
|
+
* // In production: prompt the user
|
|
30
|
+
* return { approved: true, approvedBy: 'admin' };
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* const result = await pipeline.run();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
class PhasePipeline {
|
|
38
|
+
registry;
|
|
39
|
+
baseContext;
|
|
40
|
+
options;
|
|
41
|
+
phaseResults = [];
|
|
42
|
+
_status = 'idle';
|
|
43
|
+
constructor(registry, baseContext, options) {
|
|
44
|
+
if (!options.phases.length) {
|
|
45
|
+
throw new Error('PhasePipeline requires at least one phase');
|
|
46
|
+
}
|
|
47
|
+
const names = new Set();
|
|
48
|
+
for (const p of options.phases) {
|
|
49
|
+
if (names.has(p.name)) {
|
|
50
|
+
throw new Error(`Duplicate phase name: "${p.name}"`);
|
|
51
|
+
}
|
|
52
|
+
names.add(p.name);
|
|
53
|
+
}
|
|
54
|
+
this.registry = registry;
|
|
55
|
+
this.baseContext = baseContext;
|
|
56
|
+
this.options = options;
|
|
57
|
+
}
|
|
58
|
+
/** Current pipeline status */
|
|
59
|
+
get status() {
|
|
60
|
+
return this._status;
|
|
61
|
+
}
|
|
62
|
+
/** Results from all executed phases (even if pipeline was aborted) */
|
|
63
|
+
get results() {
|
|
64
|
+
return this.phaseResults;
|
|
65
|
+
}
|
|
66
|
+
/** Phase definitions */
|
|
67
|
+
get phases() {
|
|
68
|
+
return this.options.phases;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Execute the entire pipeline, phase by phase.
|
|
72
|
+
*
|
|
73
|
+
* For each phase:
|
|
74
|
+
* 1. Run all assigned agents (parallel or sequential)
|
|
75
|
+
* 2. If `requiresApproval`, call the approval callback and wait
|
|
76
|
+
* 3. If rejected, stop the pipeline
|
|
77
|
+
* 4. Otherwise move to the next phase
|
|
78
|
+
*/
|
|
79
|
+
async run(defaultPayload) {
|
|
80
|
+
const pipelineStart = Date.now();
|
|
81
|
+
this._status = 'running';
|
|
82
|
+
this.phaseResults = [];
|
|
83
|
+
for (let i = 0; i < this.options.phases.length; i++) {
|
|
84
|
+
const phaseDef = this.options.phases[i];
|
|
85
|
+
this.options.onPhaseStart?.(phaseDef.name, i);
|
|
86
|
+
const phaseStart = Date.now();
|
|
87
|
+
const agentResults = new Map();
|
|
88
|
+
let phaseStatus = 'running';
|
|
89
|
+
// --- Execute agents -------------------------------------------------
|
|
90
|
+
try {
|
|
91
|
+
if (phaseDef.parallel) {
|
|
92
|
+
const executions = phaseDef.agents.map(agentId => {
|
|
93
|
+
const payload = this.buildPayload(agentId, phaseDef, defaultPayload);
|
|
94
|
+
const ctx = { ...this.baseContext, metadata: { ...this.baseContext.metadata, phase: phaseDef.name } };
|
|
95
|
+
return this.executeWithTimeout(agentId, payload, ctx, phaseDef.timeoutMs)
|
|
96
|
+
.then(result => ({ agentId, result }));
|
|
97
|
+
});
|
|
98
|
+
const results = await Promise.all(executions);
|
|
99
|
+
for (const { agentId, result } of results) {
|
|
100
|
+
agentResults.set(agentId, result);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
for (const agentId of phaseDef.agents) {
|
|
105
|
+
const payload = this.buildPayload(agentId, phaseDef, defaultPayload);
|
|
106
|
+
const ctx = { ...this.baseContext, metadata: { ...this.baseContext.metadata, phase: phaseDef.name } };
|
|
107
|
+
const result = await this.executeWithTimeout(agentId, payload, ctx, phaseDef.timeoutMs);
|
|
108
|
+
agentResults.set(agentId, result);
|
|
109
|
+
if (!result.success)
|
|
110
|
+
break; // stop this phase on first failure
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Check if any agent failed
|
|
114
|
+
const anyFailed = Array.from(agentResults.values()).some(r => !r.success);
|
|
115
|
+
phaseStatus = anyFailed ? 'failed' : 'completed';
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
phaseStatus = 'failed';
|
|
119
|
+
}
|
|
120
|
+
const phaseResult = {
|
|
121
|
+
phaseName: phaseDef.name,
|
|
122
|
+
status: phaseStatus,
|
|
123
|
+
agentResults,
|
|
124
|
+
durationMs: Date.now() - phaseStart,
|
|
125
|
+
};
|
|
126
|
+
// --- Check failure --------------------------------------------------
|
|
127
|
+
if (phaseStatus === 'failed') {
|
|
128
|
+
phaseResult.status = 'failed';
|
|
129
|
+
this.phaseResults.push(phaseResult);
|
|
130
|
+
this.options.onPhaseComplete?.(phaseResult, i);
|
|
131
|
+
this._status = 'failed';
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
phases: this.phaseResults,
|
|
135
|
+
totalMs: Date.now() - pipelineStart,
|
|
136
|
+
stoppedAt: phaseDef.name,
|
|
137
|
+
stopReason: 'Phase failed',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// --- Approval gate --------------------------------------------------
|
|
141
|
+
if (phaseDef.requiresApproval) {
|
|
142
|
+
phaseResult.status = 'awaiting_approval';
|
|
143
|
+
const pipelineCtx = {
|
|
144
|
+
completedPhases: [...this.phaseResults],
|
|
145
|
+
currentPhaseIndex: i,
|
|
146
|
+
totalPhases: this.options.phases.length,
|
|
147
|
+
};
|
|
148
|
+
let approval;
|
|
149
|
+
if (this.options.autoApprove) {
|
|
150
|
+
approval = { approved: true, approvedBy: 'auto' };
|
|
151
|
+
}
|
|
152
|
+
else if (this.options.onApproval) {
|
|
153
|
+
approval = await this.options.onApproval(phaseDef.name, phaseResult, pipelineCtx);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// No approval handler and not auto-approved → reject by default
|
|
157
|
+
approval = { approved: false, reason: 'No approval callback configured' };
|
|
158
|
+
}
|
|
159
|
+
phaseResult.approval = {
|
|
160
|
+
approvedBy: approval.approvedBy,
|
|
161
|
+
reason: approval.reason,
|
|
162
|
+
timestamp: Date.now(),
|
|
163
|
+
};
|
|
164
|
+
if (!approval.approved) {
|
|
165
|
+
phaseResult.status = 'rejected';
|
|
166
|
+
this.phaseResults.push(phaseResult);
|
|
167
|
+
this.options.onPhaseComplete?.(phaseResult, i);
|
|
168
|
+
this._status = 'rejected';
|
|
169
|
+
return {
|
|
170
|
+
success: false,
|
|
171
|
+
phases: this.phaseResults,
|
|
172
|
+
totalMs: Date.now() - pipelineStart,
|
|
173
|
+
stoppedAt: phaseDef.name,
|
|
174
|
+
stopReason: approval.reason ?? 'Approval rejected',
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
phaseResult.status = 'approved';
|
|
178
|
+
}
|
|
179
|
+
this.phaseResults.push(phaseResult);
|
|
180
|
+
this.options.onPhaseComplete?.(phaseResult, i);
|
|
181
|
+
}
|
|
182
|
+
this._status = 'completed';
|
|
183
|
+
return {
|
|
184
|
+
success: true,
|
|
185
|
+
phases: this.phaseResults,
|
|
186
|
+
totalMs: Date.now() - pipelineStart,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Reset the pipeline for re-execution.
|
|
191
|
+
*/
|
|
192
|
+
reset() {
|
|
193
|
+
this.phaseResults = [];
|
|
194
|
+
this._status = 'idle';
|
|
195
|
+
}
|
|
196
|
+
// --------------------------------------------------------------------------
|
|
197
|
+
// Private helpers
|
|
198
|
+
// --------------------------------------------------------------------------
|
|
199
|
+
buildPayload(agentId, phase, defaultPayload) {
|
|
200
|
+
if (phase.payloadFactory) {
|
|
201
|
+
return phase.payloadFactory(agentId, this.phaseResults);
|
|
202
|
+
}
|
|
203
|
+
return defaultPayload ?? { action: phase.name, params: {} };
|
|
204
|
+
}
|
|
205
|
+
async executeWithTimeout(agentId, payload, ctx, timeoutMs) {
|
|
206
|
+
if (!timeoutMs) {
|
|
207
|
+
return this.registry.executeAgent(agentId, payload, ctx);
|
|
208
|
+
}
|
|
209
|
+
return Promise.race([
|
|
210
|
+
this.registry.executeAgent(agentId, payload, ctx),
|
|
211
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Phase timeout: agent "${agentId}" exceeded ${timeoutMs}ms`)), timeoutMs)),
|
|
212
|
+
]);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.PhasePipeline = PhasePipeline;
|
|
216
|
+
//# sourceMappingURL=phase-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-pipeline.js","sourceRoot":"","sources":["../../lib/phase-pipeline.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAsGH,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAa,aAAa;IAChB,QAAQ,CAAkB;IAC1B,WAAW,CAAe;IAC1B,OAAO,CAAuB;IAC9B,YAAY,GAAkB,EAAE,CAAC;IACjC,OAAO,GAA6D,MAAM,CAAC;IAEnF,YAAY,QAAyB,EAAE,WAAyB,EAAE,OAA6B;QAC7F,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YACvD,CAAC;YACD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,8BAA8B;IAC9B,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,sEAAsE;IACtE,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,wBAAwB;IACxB,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CAAC,cAA6B;QACrC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAE9C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAuB,CAAC;YACpD,IAAI,WAAW,GAAgB,SAAS,CAAC;YAEzC,uEAAuE;YACvE,IAAI,CAAC;gBACH,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;oBACtB,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;wBAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;wBACrE,MAAM,GAAG,GAAiB,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;wBACpH,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC;6BACtE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;oBAC3C,CAAC,CAAC,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBAC9C,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;wBAC1C,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;wBACtC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;wBACrE,MAAM,GAAG,GAAiB,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;wBACpH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;wBACxF,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;wBAClC,IAAI,CAAC,MAAM,CAAC,OAAO;4BAAE,MAAM,CAAC,mCAAmC;oBACjE,CAAC;gBACH,CAAC;gBAED,4BAA4B;gBAC5B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBAC1E,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;YACnD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,WAAW,GAAG,QAAQ,CAAC;YACzB,CAAC;YAED,MAAM,WAAW,GAAgB;gBAC/B,SAAS,EAAE,QAAQ,CAAC,IAAI;gBACxB,MAAM,EAAE,WAAW;gBACnB,YAAY;gBACZ,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU;aACpC,CAAC;YAEF,uEAAuE;YACvE,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;gBAC7B,WAAW,CAAC,MAAM,GAAG,QAAQ,CAAC;gBAC9B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACpC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;gBAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;gBACxB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,IAAI,CAAC,YAAY;oBACzB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa;oBACnC,SAAS,EAAE,QAAQ,CAAC,IAAI;oBACxB,UAAU,EAAE,cAAc;iBAC3B,CAAC;YACJ,CAAC;YAED,uEAAuE;YACvE,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;gBAC9B,WAAW,CAAC,MAAM,GAAG,mBAAmB,CAAC;gBACzC,MAAM,WAAW,GAA6B;oBAC5C,eAAe,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;oBACvC,iBAAiB,EAAE,CAAC;oBACpB,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM;iBACxC,CAAC;gBAEF,IAAI,QAAqE,CAAC;gBAC1E,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;oBAC7B,QAAQ,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;gBACpD,CAAC;qBAAM,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;oBACnC,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;gBACpF,CAAC;qBAAM,CAAC;oBACN,gEAAgE;oBAChE,QAAQ,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;gBAC5E,CAAC;gBAED,WAAW,CAAC,QAAQ,GAAG;oBACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM;oBACvB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;iBACtB,CAAC;gBAEF,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;oBACvB,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;oBAChC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBACpC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;oBAC/C,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC;oBAC1B,OAAO;wBACL,OAAO,EAAE,KAAK;wBACd,MAAM,EAAE,IAAI,CAAC,YAAY;wBACzB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa;wBACnC,SAAS,EAAE,QAAQ,CAAC,IAAI;wBACxB,UAAU,EAAE,QAAQ,CAAC,MAAM,IAAI,mBAAmB;qBACnD,CAAC;gBACJ,CAAC;gBAED,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;YAClC,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,IAAI,CAAC,YAAY;YACzB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa;SACpC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,6EAA6E;IAC7E,kBAAkB;IAClB,6EAA6E;IAErE,YAAY,CAAC,OAAe,EAAE,KAAsB,EAAE,cAA6B;QACzF,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,cAAc,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC9D,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,OAAe,EAAE,OAAqB,EAAE,GAAiB,EAAE,SAAkB;QAC5G,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,OAAO,CAAC,IAAI,CAAC;YAClB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC;YACjD,IAAI,OAAO,CAAc,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CACrC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,OAAO,cAAc,SAAS,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAC5G;SACF,CAAC,CAAC;IACL,CAAC;CACF;AArMD,sCAqMC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "network-ai",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.0",
|
|
4
4
|
"description": "AI agent orchestration framework for TypeScript/Node.js - 17 adapters (LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, OpenClaw, A2A, Codex, MiniMax, NemoClaw, APS + streaming variants). Built-in CLI, security, swarm intelligence, real-time streaming, and agentic workflow patterns.",
|
|
5
5
|
"homepage": "https://network-ai.org",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"test:cli": "npx ts-node test-cli.ts",
|
|
35
35
|
"test:qa": "npx ts-node test-qa.ts",
|
|
36
36
|
"test:phase7": "npx ts-node test-phase7.ts",
|
|
37
|
+
"test:phase8": "npx ts-node test-phase8.ts",
|
|
37
38
|
"test:all": "npx ts-node run-tests.ts",
|
|
38
39
|
"setup": "npx ts-node setup.ts",
|
|
39
40
|
"setup:check": "npx ts-node setup.ts --check",
|