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.
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Confidence Filter — Multi-agent result confidence scoring & filtering
3
+ *
4
+ * Scores agent findings by confidence, filters by threshold, and optionally
5
+ * validates low-confidence findings with a secondary agent. Inspired by
6
+ * Claude Code's confidence-based multi-agent filtering pattern.
7
+ *
8
+ * @module ConfidenceFilter
9
+ * @version 1.0.0
10
+ */
11
+ import type { AgentPayload, AgentContext } from '../types/agent-adapter';
12
+ import type { AdapterRegistry } from '../adapters/adapter-registry';
13
+ /**
14
+ * A single finding produced by an agent, annotated with confidence.
15
+ */
16
+ export interface Finding {
17
+ /** Unique identifier for this finding */
18
+ id: string;
19
+ /** Human-readable description of the finding */
20
+ description: string;
21
+ /** Confidence score from 0 to 100 */
22
+ confidence: number;
23
+ /** Agent that produced this finding */
24
+ sourceAgent: string;
25
+ /** Agent that validated this finding (set after validation) */
26
+ validatedBy?: string;
27
+ /** Whether validation passed (set after validation) */
28
+ validated?: boolean;
29
+ /** Arbitrary metadata attached to the finding */
30
+ metadata?: Record<string, unknown>;
31
+ }
32
+ /**
33
+ * Result of filtering findings by confidence threshold.
34
+ */
35
+ export interface FilterResult {
36
+ /** Findings that passed the threshold */
37
+ accepted: Finding[];
38
+ /** Findings below the threshold */
39
+ rejected: Finding[];
40
+ /** Threshold that was applied */
41
+ threshold: number;
42
+ }
43
+ /**
44
+ * Aggregation strategies for combining findings from multiple agents.
45
+ */
46
+ export type AggregationStrategy = 'highest' | 'average' | 'unanimous' | 'majority';
47
+ /**
48
+ * Result of aggregating multiple sets of findings.
49
+ */
50
+ export interface AggregatedResult {
51
+ /** Merged findings after applying aggregation strategy */
52
+ findings: Finding[];
53
+ /** Strategy that was used */
54
+ strategy: AggregationStrategy;
55
+ /** Total number of input findings before aggregation */
56
+ totalInput: number;
57
+ /** Number of sources that contributed */
58
+ sourceCount: number;
59
+ }
60
+ /**
61
+ * Options for the ConfidenceFilter constructor.
62
+ */
63
+ export interface ConfidenceFilterOptions {
64
+ /** Default confidence threshold (0–100). Default: 70 */
65
+ defaultThreshold?: number;
66
+ /** If true, findings below threshold are auto-validated with a second agent */
67
+ autoValidate?: boolean;
68
+ /** Agent to use for validation passes */
69
+ validatorAgent?: string;
70
+ /** Payload factory for validation calls */
71
+ validationPayloadFactory?: (finding: Finding) => AgentPayload;
72
+ }
73
+ /**
74
+ * Filters and validates multi-agent findings based on confidence scores.
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const filter = new ConfidenceFilter(registry, baseCtx, { defaultThreshold: 70 });
79
+ *
80
+ * const findings: Finding[] = [
81
+ * { id: '1', description: 'SQL injection in login.ts', confidence: 95, sourceAgent: 'scanner-a' },
82
+ * { id: '2', description: 'Possible XSS in comments', confidence: 45, sourceAgent: 'scanner-b' },
83
+ * ];
84
+ *
85
+ * const filtered = filter.filter(findings);
86
+ * // filtered.accepted → finding #1, filtered.rejected → finding #2
87
+ *
88
+ * // Validate a low-confidence finding with a secondary agent
89
+ * const validated = await filter.validate(findings[1], 'expert-reviewer');
90
+ * ```
91
+ */
92
+ export declare class ConfidenceFilter {
93
+ private registry;
94
+ private baseContext;
95
+ private options;
96
+ /**
97
+ * @param registry Adapter registry for validation calls (optional — filter-only mode if null)
98
+ * @param baseContext Default execution context for validation agents
99
+ * @param options Filter configuration
100
+ */
101
+ constructor(registry: AdapterRegistry | null, baseContext: AgentContext | null, options?: ConfidenceFilterOptions);
102
+ /**
103
+ * Score a single finding. Returns a normalised 0–100 confidence score.
104
+ * Currently a pass-through; override or extend for custom scoring logic.
105
+ */
106
+ score(finding: Finding): number;
107
+ /**
108
+ * Filter findings by confidence threshold.
109
+ *
110
+ * @param findings Findings to filter
111
+ * @param threshold Override the default threshold for this call
112
+ */
113
+ filter(findings: Finding[], threshold?: number): FilterResult;
114
+ /**
115
+ * Validate a finding using a secondary agent.
116
+ * The validator agent's result is used to update `validatedBy` and `validated`.
117
+ *
118
+ * @param finding The finding to validate
119
+ * @param validatorAgentId Agent to perform the validation (overrides options)
120
+ * @returns Updated finding with validation metadata
121
+ */
122
+ validate(finding: Finding, validatorAgentId?: string): Promise<Finding>;
123
+ /**
124
+ * Validate all rejected findings from a filter result.
125
+ * Returns the updated filter result with re-scored findings.
126
+ */
127
+ validateRejected(filterResult: FilterResult, validatorAgentId?: string): Promise<FilterResult>;
128
+ /**
129
+ * Aggregate findings from multiple sources using a strategy.
130
+ *
131
+ * - `highest`: Keep the finding with the highest confidence for each id
132
+ * - `average`: Average the confidence scores for each id
133
+ * - `unanimous`: Only keep findings that appear in ALL sources
134
+ * - `majority`: Only keep findings that appear in more than half of sources
135
+ *
136
+ * @param findingSets Arrays of findings from different agents
137
+ * @param strategy Aggregation strategy to use
138
+ */
139
+ aggregate(findingSets: Finding[][], strategy?: AggregationStrategy): AggregatedResult;
140
+ }
141
+ //# sourceMappingURL=confidence-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confidence-filter.d.ts","sourceRoot":"","sources":["../../lib/confidence-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAe,MAAM,wBAAwB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMpE;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mCAAmC;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,6BAA6B;IAC7B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2CAA2C;IAC3C,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC;CAC/D;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,OAAO,CAA0B;IAEzC;;;;OAIG;gBAED,QAAQ,EAAE,eAAe,GAAG,IAAI,EAChC,WAAW,EAAE,YAAY,GAAG,IAAI,EAChC,OAAO,GAAE,uBAA4B;IAOvC;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAI/B;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY;IAiB7D;;;;;;;OAOG;IACG,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiC7E;;;OAGG;IACG,gBAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwBpG;;;;;;;;;;OAUG;IACH,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,GAAE,mBAA+B,GAAG,gBAAgB;CA6DjG"}
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ /**
3
+ * Confidence Filter — Multi-agent result confidence scoring & filtering
4
+ *
5
+ * Scores agent findings by confidence, filters by threshold, and optionally
6
+ * validates low-confidence findings with a secondary agent. Inspired by
7
+ * Claude Code's confidence-based multi-agent filtering pattern.
8
+ *
9
+ * @module ConfidenceFilter
10
+ * @version 1.0.0
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ConfidenceFilter = void 0;
14
+ // ============================================================================
15
+ // CONFIDENCE FILTER
16
+ // ============================================================================
17
+ /**
18
+ * Filters and validates multi-agent findings based on confidence scores.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const filter = new ConfidenceFilter(registry, baseCtx, { defaultThreshold: 70 });
23
+ *
24
+ * const findings: Finding[] = [
25
+ * { id: '1', description: 'SQL injection in login.ts', confidence: 95, sourceAgent: 'scanner-a' },
26
+ * { id: '2', description: 'Possible XSS in comments', confidence: 45, sourceAgent: 'scanner-b' },
27
+ * ];
28
+ *
29
+ * const filtered = filter.filter(findings);
30
+ * // filtered.accepted → finding #1, filtered.rejected → finding #2
31
+ *
32
+ * // Validate a low-confidence finding with a secondary agent
33
+ * const validated = await filter.validate(findings[1], 'expert-reviewer');
34
+ * ```
35
+ */
36
+ class ConfidenceFilter {
37
+ registry;
38
+ baseContext;
39
+ options;
40
+ /**
41
+ * @param registry Adapter registry for validation calls (optional — filter-only mode if null)
42
+ * @param baseContext Default execution context for validation agents
43
+ * @param options Filter configuration
44
+ */
45
+ constructor(registry, baseContext, options = {}) {
46
+ this.registry = registry;
47
+ this.baseContext = baseContext;
48
+ this.options = options;
49
+ }
50
+ /**
51
+ * Score a single finding. Returns a normalised 0–100 confidence score.
52
+ * Currently a pass-through; override or extend for custom scoring logic.
53
+ */
54
+ score(finding) {
55
+ return Math.max(0, Math.min(100, finding.confidence));
56
+ }
57
+ /**
58
+ * Filter findings by confidence threshold.
59
+ *
60
+ * @param findings Findings to filter
61
+ * @param threshold Override the default threshold for this call
62
+ */
63
+ filter(findings, threshold) {
64
+ const t = threshold ?? this.options.defaultThreshold ?? 70;
65
+ const accepted = [];
66
+ const rejected = [];
67
+ for (const f of findings) {
68
+ const s = this.score(f);
69
+ if (s >= t) {
70
+ accepted.push(f);
71
+ }
72
+ else {
73
+ rejected.push(f);
74
+ }
75
+ }
76
+ return { accepted, rejected, threshold: t };
77
+ }
78
+ /**
79
+ * Validate a finding using a secondary agent.
80
+ * The validator agent's result is used to update `validatedBy` and `validated`.
81
+ *
82
+ * @param finding The finding to validate
83
+ * @param validatorAgentId Agent to perform the validation (overrides options)
84
+ * @returns Updated finding with validation metadata
85
+ */
86
+ async validate(finding, validatorAgentId) {
87
+ const agentId = validatorAgentId ?? this.options.validatorAgent;
88
+ if (!agentId) {
89
+ throw new Error('No validator agent specified');
90
+ }
91
+ if (!this.registry || !this.baseContext) {
92
+ throw new Error('Registry and baseContext required for validation');
93
+ }
94
+ const payload = this.options.validationPayloadFactory
95
+ ? this.options.validationPayloadFactory(finding)
96
+ : {
97
+ action: 'validate',
98
+ params: { findingId: finding.id, description: finding.description, confidence: finding.confidence },
99
+ };
100
+ const ctx = {
101
+ ...this.baseContext,
102
+ metadata: { ...this.baseContext.metadata, validating: finding.id },
103
+ };
104
+ const result = await this.registry.executeAgent(agentId, payload, ctx);
105
+ return {
106
+ ...finding,
107
+ validatedBy: agentId,
108
+ validated: result.success,
109
+ confidence: result.success
110
+ ? Math.min(100, finding.confidence + 20) // boost confidence if validated
111
+ : Math.max(0, finding.confidence - 10), // reduce if validation failed
112
+ };
113
+ }
114
+ /**
115
+ * Validate all rejected findings from a filter result.
116
+ * Returns the updated filter result with re-scored findings.
117
+ */
118
+ async validateRejected(filterResult, validatorAgentId) {
119
+ const validated = [];
120
+ for (const f of filterResult.rejected) {
121
+ validated.push(await this.validate(f, validatorAgentId));
122
+ }
123
+ // Re-filter after validation
124
+ const newAccepted = [];
125
+ const newRejected = [];
126
+ for (const f of validated) {
127
+ if (f.confidence >= filterResult.threshold) {
128
+ newAccepted.push(f);
129
+ }
130
+ else {
131
+ newRejected.push(f);
132
+ }
133
+ }
134
+ return {
135
+ accepted: [...filterResult.accepted, ...newAccepted],
136
+ rejected: newRejected,
137
+ threshold: filterResult.threshold,
138
+ };
139
+ }
140
+ /**
141
+ * Aggregate findings from multiple sources using a strategy.
142
+ *
143
+ * - `highest`: Keep the finding with the highest confidence for each id
144
+ * - `average`: Average the confidence scores for each id
145
+ * - `unanimous`: Only keep findings that appear in ALL sources
146
+ * - `majority`: Only keep findings that appear in more than half of sources
147
+ *
148
+ * @param findingSets Arrays of findings from different agents
149
+ * @param strategy Aggregation strategy to use
150
+ */
151
+ aggregate(findingSets, strategy = 'highest') {
152
+ const totalInput = findingSets.reduce((sum, s) => sum + s.length, 0);
153
+ const sourceCount = findingSets.length;
154
+ if (sourceCount === 0) {
155
+ return { findings: [], strategy, totalInput: 0, sourceCount: 0 };
156
+ }
157
+ // Group by finding id
158
+ const grouped = new Map();
159
+ for (const set of findingSets) {
160
+ for (const f of set) {
161
+ if (!grouped.has(f.id))
162
+ grouped.set(f.id, []);
163
+ grouped.get(f.id).push(f);
164
+ }
165
+ }
166
+ let findings;
167
+ switch (strategy) {
168
+ case 'highest': {
169
+ findings = [];
170
+ for (const [, group] of grouped) {
171
+ const best = group.reduce((a, b) => (a.confidence > b.confidence ? a : b));
172
+ findings.push(best);
173
+ }
174
+ break;
175
+ }
176
+ case 'average': {
177
+ findings = [];
178
+ for (const [, group] of grouped) {
179
+ const avgConfidence = Math.round(group.reduce((s, f) => s + f.confidence, 0) / group.length);
180
+ findings.push({ ...group[0], confidence: avgConfidence });
181
+ }
182
+ break;
183
+ }
184
+ case 'unanimous': {
185
+ findings = [];
186
+ for (const [, group] of grouped) {
187
+ if (group.length === sourceCount) {
188
+ const avgConfidence = Math.round(group.reduce((s, f) => s + f.confidence, 0) / group.length);
189
+ findings.push({ ...group[0], confidence: avgConfidence });
190
+ }
191
+ }
192
+ break;
193
+ }
194
+ case 'majority': {
195
+ findings = [];
196
+ const majorityThreshold = Math.floor(sourceCount / 2) + 1;
197
+ for (const [, group] of grouped) {
198
+ if (group.length >= majorityThreshold) {
199
+ const avgConfidence = Math.round(group.reduce((s, f) => s + f.confidence, 0) / group.length);
200
+ findings.push({ ...group[0], confidence: avgConfidence });
201
+ }
202
+ }
203
+ break;
204
+ }
205
+ }
206
+ return { findings, strategy, totalInput, sourceCount };
207
+ }
208
+ }
209
+ exports.ConfidenceFilter = ConfidenceFilter;
210
+ //# sourceMappingURL=confidence-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confidence-filter.js","sourceRoot":"","sources":["../../lib/confidence-filter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AA0EH,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,gBAAgB;IACnB,QAAQ,CAAyB;IACjC,WAAW,CAAsB;IACjC,OAAO,CAA0B;IAEzC;;;;OAIG;IACH,YACE,QAAgC,EAChC,WAAgC,EAChC,UAAmC,EAAE;QAErC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAgB;QACpB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACxD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAmB,EAAE,SAAkB;QAC5C,MAAM,CAAC,GAAG,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC9C,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,OAAgB,EAAE,gBAAyB;QACxD,MAAM,OAAO,GAAG,gBAAgB,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QAChE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,wBAAwB;YACnD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC;YAChD,CAAC,CAAC;gBACE,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;aACpG,CAAC;QAEN,MAAM,GAAG,GAAiB;YACxB,GAAG,IAAI,CAAC,WAAW;YACnB,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE;SACnE,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAEvE,OAAO;YACL,GAAG,OAAO;YACV,WAAW,EAAE,OAAO;YACpB,SAAS,EAAE,MAAM,CAAC,OAAO;YACzB,UAAU,EAAE,MAAM,CAAC,OAAO;gBACxB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,gCAAgC;gBACzE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,GAAG,EAAE,CAAC,EAAG,8BAA8B;SAC1E,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,YAA0B,EAAE,gBAAyB;QAC1E,MAAM,SAAS,GAAc,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;YACtC,SAAS,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,6BAA6B;QAC7B,MAAM,WAAW,GAAc,EAAE,CAAC;QAClC,MAAM,WAAW,GAAc,EAAE,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,UAAU,IAAI,YAAY,CAAC,SAAS,EAAE,CAAC;gBAC3C,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;YACpD,QAAQ,EAAE,WAAW;YACrB,SAAS,EAAE,YAAY,CAAC,SAAS;SAClC,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,SAAS,CAAC,WAAwB,EAAE,WAAgC,SAAS;QAC3E,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC;QAEvC,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QACnE,CAAC;QAED,sBAAsB;QACtB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;QAC7C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;gBACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,IAAI,QAAmB,CAAC;QAExB,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,QAAQ,GAAG,EAAE,CAAC;gBACd,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;oBAChC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC3E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,QAAQ,GAAG,EAAE,CAAC;gBACd,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;oBAChC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC;gBAC5D,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,QAAQ,GAAG,EAAE,CAAC;gBACd,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;oBAChC,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;wBACjC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;wBAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC;oBAC5D,CAAC;gBACH,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,QAAQ,GAAG,EAAE,CAAC;gBACd,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC1D,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;oBAChC,IAAI,KAAK,CAAC,MAAM,IAAI,iBAAiB,EAAE,CAAC;wBACtC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;wBAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC;oBAC5D,CAAC;gBACH,CAAC;gBACD,MAAM;YACR,CAAC;QACH,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IACzD,CAAC;CACF;AAhMD,4CAgMC"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Fan-Out / Fan-In — Parallel agent spawning and result aggregation
3
+ *
4
+ * Launches multiple agents in parallel (fan-out) and combines their results
5
+ * using pluggable strategies (fan-in). Supports concurrency limits, timeouts,
6
+ * and custom aggregation. Inspired by Claude Code's parallel agent patterns.
7
+ *
8
+ * @module FanOutFanIn
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
+ /**
14
+ * A single agent invocation for the fan-out step.
15
+ */
16
+ export interface FanOutStep {
17
+ /** Agent to execute */
18
+ agentId: string;
19
+ /** Payload to send */
20
+ payload: AgentPayload;
21
+ /** Optional context overrides (merged with baseContext) */
22
+ context?: Partial<AgentContext>;
23
+ /** Per-step timeout in ms (overrides global timeout) */
24
+ timeoutMs?: number;
25
+ /** Arbitrary label for this step (used in result mapping) */
26
+ label?: string;
27
+ }
28
+ /**
29
+ * Result of a single fan-out execution, tagged with its step info.
30
+ */
31
+ export interface TaggedResult {
32
+ /** The agent that produced this result */
33
+ agentId: string;
34
+ /** Step label (if provided) */
35
+ label?: string;
36
+ /** Index of the step in the original fan-out array */
37
+ index: number;
38
+ /** Actual agent result */
39
+ result: AgentResult;
40
+ /** Execution duration in ms */
41
+ durationMs: number;
42
+ }
43
+ /**
44
+ * Fan-in aggregation strategy.
45
+ *
46
+ * - `merge`: Collect all results into an array
47
+ * - `firstSuccess`: Return the first successful result
48
+ * - `vote`: Return the result that occurs most often (by data equality)
49
+ * - `consensus`: Return result only if all agents agree
50
+ * - `custom`: Use a custom reducer function
51
+ */
52
+ export type FanInStrategy = 'merge' | 'firstSuccess' | 'vote' | 'consensus' | 'custom';
53
+ /**
54
+ * Result of a fan-in aggregation.
55
+ */
56
+ export interface FanInResult {
57
+ /** Whether aggregation was successful */
58
+ success: boolean;
59
+ /** Strategy that was used */
60
+ strategy: FanInStrategy;
61
+ /** Aggregated data (depends on strategy) */
62
+ data: unknown;
63
+ /** All individual tagged results */
64
+ results: TaggedResult[];
65
+ /** Total execution time in ms */
66
+ totalMs: number;
67
+ /** Count of successful individual results */
68
+ successCount: number;
69
+ /** Count of failed individual results */
70
+ failureCount: number;
71
+ }
72
+ /**
73
+ * Custom reducer for the 'custom' fan-in strategy.
74
+ */
75
+ export type FanInReducer = (results: TaggedResult[]) => {
76
+ success: boolean;
77
+ data: unknown;
78
+ };
79
+ /**
80
+ * Options for FanOutFanIn execution.
81
+ */
82
+ export interface FanOutOptions {
83
+ /** Max concurrent agent executions (default: unlimited) */
84
+ concurrency?: number;
85
+ /** Global timeout in ms for all fan-out (default: none) */
86
+ timeoutMs?: number;
87
+ /** If true, continue even when some agents fail (default: true) */
88
+ continueOnError?: boolean;
89
+ }
90
+ /**
91
+ * Parallel agent execution with pluggable result aggregation.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const fanout = new FanOutFanIn(registry, { agentId: 'orchestrator' });
96
+ *
97
+ * const steps: FanOutStep[] = [
98
+ * { agentId: 'researcher-a', payload: { action: 'search', params: { q: 'AI safety' } }, label: 'web' },
99
+ * { agentId: 'researcher-b', payload: { action: 'search', params: { q: 'AI safety' } }, label: 'papers' },
100
+ * { agentId: 'researcher-c', payload: { action: 'search', params: { q: 'AI safety' } }, label: 'news' },
101
+ * ];
102
+ *
103
+ * const results = await fanout.fanOut(steps, { concurrency: 2 });
104
+ * const aggregated = fanout.fanIn(results, 'merge');
105
+ * ```
106
+ */
107
+ export declare class FanOutFanIn {
108
+ private registry;
109
+ private baseContext;
110
+ /**
111
+ * @param registry Adapter registry for agent execution
112
+ * @param baseContext Default execution context (merged with step-level overrides)
113
+ */
114
+ constructor(registry: AdapterRegistry, baseContext: AgentContext);
115
+ /**
116
+ * Execute agents in parallel (fan-out phase).
117
+ *
118
+ * @param steps Steps to execute
119
+ * @param options Concurrency and timeout settings
120
+ */
121
+ fanOut(steps: FanOutStep[], options?: FanOutOptions): Promise<TaggedResult[]>;
122
+ /**
123
+ * Aggregate results (fan-in phase).
124
+ *
125
+ * @param results Tagged results from fan-out
126
+ * @param strategy Aggregation strategy to apply
127
+ * @param customReducer Required when strategy is 'custom'
128
+ */
129
+ fanIn(results: TaggedResult[], strategy?: FanInStrategy, customReducer?: FanInReducer): FanInResult;
130
+ /**
131
+ * Convenience: fan-out + fan-in in a single call.
132
+ */
133
+ run(steps: FanOutStep[], strategy?: FanInStrategy, options?: FanOutOptions, customReducer?: FanInReducer): Promise<FanInResult>;
134
+ private executeStep;
135
+ }
136
+ //# sourceMappingURL=fan-out.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fan-out.d.ts","sourceRoot":"","sources":["../../lib/fan-out.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMpE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,QAAQ,EAAE,aAAa,CAAC;IACxB,4CAA4C;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,oCAAoC;IACpC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAe;IAElC;;;OAGG;gBACS,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY;IAKhE;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA6DvF;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,QAAQ,GAAE,aAAuB,EAAE,aAAa,CAAC,EAAE,YAAY,GAAG,WAAW;IAwE5G;;OAEG;IACG,GAAG,CACP,KAAK,EAAE,UAAU,EAAE,EACnB,QAAQ,GAAE,aAAuB,EACjC,OAAO,CAAC,EAAE,aAAa,EACvB,aAAa,CAAC,EAAE,YAAY,GAC3B,OAAO,CAAC,WAAW,CAAC;YAST,WAAW;CAyB1B"}