@defai.digital/discussion-domain 13.3.1 → 13.4.1
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/consensus/moderator.d.ts.map +1 -1
- package/dist/consensus/moderator.js +19 -2
- package/dist/consensus/moderator.js.map +1 -1
- package/dist/consensus/synthesis.d.ts.map +1 -1
- package/dist/consensus/synthesis.js +20 -2
- package/dist/consensus/synthesis.js.map +1 -1
- package/dist/consensus/voting.d.ts.map +1 -1
- package/dist/consensus/voting.js +20 -3
- package/dist/consensus/voting.js.map +1 -1
- package/dist/executor.d.ts +2 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +38 -4
- package/dist/executor.js.map +1 -1
- package/dist/participant-resolver.d.ts.map +1 -1
- package/dist/participant-resolver.js +14 -5
- package/dist/participant-resolver.js.map +1 -1
- package/dist/patterns/synthesis.d.ts +5 -0
- package/dist/patterns/synthesis.d.ts.map +1 -1
- package/dist/patterns/synthesis.js +92 -2
- package/dist/patterns/synthesis.js.map +1 -1
- package/dist/recursive-executor.d.ts.map +1 -1
- package/dist/recursive-executor.js +4 -2
- package/dist/recursive-executor.js.map +1 -1
- package/dist/types.d.ts +77 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/consensus/moderator.ts +20 -3
- package/src/consensus/synthesis.ts +21 -3
- package/src/consensus/voting.ts +22 -3
- package/src/executor.ts +48 -3
- package/src/participant-resolver.ts +19 -5
- package/src/patterns/synthesis.ts +102 -2
- package/src/recursive-executor.ts +4 -1
- package/src/types.ts +70 -1
package/src/consensus/voting.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - INV-DISC-642: Agent responses weighted by agentWeightMultiplier (default 1.5x)
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { DEFAULT_AGENT_WEIGHT_MULTIPLIER, type VotingResults, type VoteRecord } from '@defai.digital/contracts';
|
|
11
|
+
import { DEFAULT_AGENT_WEIGHT_MULTIPLIER, DEFAULT_VOTING_SUMMARY_TIMEOUT, type VotingResults, type VoteRecord } from '@defai.digital/contracts';
|
|
12
12
|
import type { ConsensusExecutor, ConsensusExecutionContext, ConsensusExecutionResult } from '../types.js';
|
|
13
13
|
import {
|
|
14
14
|
VOTING_TALLY,
|
|
@@ -69,6 +69,21 @@ export class VotingConsensus implements ConsensusExecutor {
|
|
|
69
69
|
onProgress
|
|
70
70
|
);
|
|
71
71
|
|
|
72
|
+
const consensusDurationMs = Date.now() - startTime;
|
|
73
|
+
|
|
74
|
+
// Emit consensus_complete event for Phase 2 tracing
|
|
75
|
+
onProgress?.({
|
|
76
|
+
type: 'consensus_complete',
|
|
77
|
+
message: `Voting consensus reached: ${votingResults.winner} won${votingResults.unanimous ? ' unanimously' : ''}`,
|
|
78
|
+
timestamp: new Date().toISOString(),
|
|
79
|
+
success: true,
|
|
80
|
+
consensusMethod: 'voting',
|
|
81
|
+
confidence: votingResults.unanimous ? 1.0 : votingResults.margin,
|
|
82
|
+
winner: votingResults.winner,
|
|
83
|
+
votes: votingResults.votes,
|
|
84
|
+
durationMs: consensusDurationMs,
|
|
85
|
+
});
|
|
86
|
+
|
|
72
87
|
return {
|
|
73
88
|
synthesis,
|
|
74
89
|
consensus: {
|
|
@@ -77,7 +92,7 @@ export class VotingConsensus implements ConsensusExecutor {
|
|
|
77
92
|
agreementScore: votingResults.unanimous ? 1.0 : votingResults.margin,
|
|
78
93
|
},
|
|
79
94
|
votingResults,
|
|
80
|
-
durationMs:
|
|
95
|
+
durationMs: consensusDurationMs,
|
|
81
96
|
success: true,
|
|
82
97
|
};
|
|
83
98
|
}
|
|
@@ -185,7 +200,7 @@ export class VotingConsensus implements ConsensusExecutor {
|
|
|
185
200
|
prompt,
|
|
186
201
|
systemPrompt: getProviderSystemPrompt(synthesizerId),
|
|
187
202
|
temperature: 0.5,
|
|
188
|
-
timeoutMs:
|
|
203
|
+
timeoutMs: DEFAULT_VOTING_SUMMARY_TIMEOUT, // Vote summary is simpler (90 sec default)
|
|
189
204
|
abortSignal,
|
|
190
205
|
});
|
|
191
206
|
|
|
@@ -193,6 +208,10 @@ export class VotingConsensus implements ConsensusExecutor {
|
|
|
193
208
|
type: 'synthesis_complete',
|
|
194
209
|
provider: synthesizerId,
|
|
195
210
|
timestamp: new Date().toISOString(),
|
|
211
|
+
// Extended fields for Phase 2 tracing
|
|
212
|
+
success: result.success,
|
|
213
|
+
durationMs: result.durationMs,
|
|
214
|
+
tokenCount: result.tokenCount,
|
|
196
215
|
});
|
|
197
216
|
|
|
198
217
|
if (result.success && result.content) {
|
package/src/executor.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_PROVIDERS,
|
|
16
|
+
DEFAULT_PROVIDER_TIMEOUT,
|
|
16
17
|
DiscussionErrorCodes,
|
|
17
18
|
createFailedDiscussionResult,
|
|
18
19
|
DEFAULT_AGENT_WEIGHT_MULTIPLIER,
|
|
@@ -26,9 +27,14 @@ import type {
|
|
|
26
27
|
DiscussionExecutorOptions,
|
|
27
28
|
PatternExecutionContext,
|
|
28
29
|
DiscussionProgressEvent,
|
|
30
|
+
ResolvedParticipantLike,
|
|
29
31
|
} from './types.js';
|
|
30
32
|
import { getPatternExecutor } from './patterns/index.js';
|
|
31
33
|
import { getConsensusExecutor } from './consensus/index.js';
|
|
34
|
+
import {
|
|
35
|
+
resolveParticipants,
|
|
36
|
+
getProviderIds,
|
|
37
|
+
} from './participant-resolver.js';
|
|
32
38
|
|
|
33
39
|
/**
|
|
34
40
|
* Main discussion executor class.
|
|
@@ -40,12 +46,16 @@ export class DiscussionExecutor {
|
|
|
40
46
|
private readonly defaultTimeoutMs: number;
|
|
41
47
|
private readonly checkProviderHealth: boolean;
|
|
42
48
|
private readonly traceId: string | undefined;
|
|
49
|
+
private readonly participantResolverOptions: DiscussionExecutorOptions['participantResolverOptions'];
|
|
50
|
+
private readonly cascadingConfidence: DiscussionExecutorOptions['cascadingConfidence'];
|
|
43
51
|
|
|
44
52
|
constructor(options: DiscussionExecutorOptions) {
|
|
45
53
|
this.providerExecutor = options.providerExecutor;
|
|
46
|
-
this.defaultTimeoutMs = options.defaultTimeoutMs ??
|
|
54
|
+
this.defaultTimeoutMs = options.defaultTimeoutMs ?? DEFAULT_PROVIDER_TIMEOUT;
|
|
47
55
|
this.checkProviderHealth = options.checkProviderHealth ?? true;
|
|
48
56
|
this.traceId = options.traceId;
|
|
57
|
+
this.participantResolverOptions = options.participantResolverOptions ?? {};
|
|
58
|
+
this.cascadingConfidence = options.cascadingConfidence;
|
|
49
59
|
}
|
|
50
60
|
|
|
51
61
|
/**
|
|
@@ -77,6 +87,7 @@ export class DiscussionExecutor {
|
|
|
77
87
|
minProviders: 2,
|
|
78
88
|
temperature: 0.7,
|
|
79
89
|
agentWeightMultiplier: DEFAULT_AGENT_WEIGHT_MULTIPLIER,
|
|
90
|
+
fastMode: false,
|
|
80
91
|
};
|
|
81
92
|
|
|
82
93
|
return this.execute(config, options);
|
|
@@ -106,10 +117,39 @@ export class DiscussionExecutor {
|
|
|
106
117
|
);
|
|
107
118
|
}
|
|
108
119
|
|
|
120
|
+
// Resolve participants if provided (INV-DISC-640, INV-DISC-641)
|
|
121
|
+
let resolvedParticipants: ResolvedParticipantLike[] | undefined;
|
|
122
|
+
let providersToCheck: string[];
|
|
123
|
+
|
|
124
|
+
if (config.participants && config.participants.length > 0) {
|
|
125
|
+
// Resolve participants (agents + providers) to execution config
|
|
126
|
+
try {
|
|
127
|
+
resolvedParticipants = await resolveParticipants(config.participants, {
|
|
128
|
+
...this.participantResolverOptions,
|
|
129
|
+
topic: config.prompt,
|
|
130
|
+
agentWeightMultiplier: config.agentWeightMultiplier,
|
|
131
|
+
});
|
|
132
|
+
// Extract unique provider IDs from resolved participants
|
|
133
|
+
providersToCheck = getProviderIds(resolvedParticipants);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
136
|
+
return createFailedDiscussionResult(
|
|
137
|
+
config.pattern,
|
|
138
|
+
config.prompt,
|
|
139
|
+
DiscussionErrorCodes.INVALID_CONFIG,
|
|
140
|
+
`Failed to resolve participants: ${errorMessage}`,
|
|
141
|
+
startedAt
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
// Use legacy providers array
|
|
146
|
+
providersToCheck = config.providers;
|
|
147
|
+
}
|
|
148
|
+
|
|
109
149
|
// INV-DISC-100: Check provider availability
|
|
110
150
|
let availableProviders: string[];
|
|
111
151
|
try {
|
|
112
|
-
availableProviders = await this.checkProviders(
|
|
152
|
+
availableProviders = await this.checkProviders(providersToCheck);
|
|
113
153
|
} catch (error) {
|
|
114
154
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
115
155
|
return createFailedDiscussionResult(
|
|
@@ -143,7 +183,10 @@ export class DiscussionExecutor {
|
|
|
143
183
|
abortSignal,
|
|
144
184
|
traceId: this.traceId,
|
|
145
185
|
onProgress,
|
|
146
|
-
//
|
|
186
|
+
// Pass resolved participants for agent-aware execution
|
|
187
|
+
resolvedParticipants,
|
|
188
|
+
// Cascading confidence for early exit (INV-DISC-622, INV-DISC-623)
|
|
189
|
+
cascadingConfidence: this.cascadingConfidence,
|
|
147
190
|
};
|
|
148
191
|
|
|
149
192
|
// Execute pattern
|
|
@@ -293,6 +336,7 @@ export class DiscussionExecutor {
|
|
|
293
336
|
minProviders: 3,
|
|
294
337
|
temperature: 0.7,
|
|
295
338
|
agentWeightMultiplier: DEFAULT_AGENT_WEIGHT_MULTIPLIER,
|
|
339
|
+
fastMode: false,
|
|
296
340
|
};
|
|
297
341
|
|
|
298
342
|
return this.execute(config, options);
|
|
@@ -328,6 +372,7 @@ export class DiscussionExecutor {
|
|
|
328
372
|
minProviders: 2,
|
|
329
373
|
temperature: 0.5, // Lower temperature for more consistent voting
|
|
330
374
|
agentWeightMultiplier: DEFAULT_AGENT_WEIGHT_MULTIPLIER,
|
|
375
|
+
fastMode: false,
|
|
331
376
|
};
|
|
332
377
|
|
|
333
378
|
return this.execute(config, options);
|
|
@@ -203,8 +203,12 @@ export async function resolveParticipant(
|
|
|
203
203
|
if (injection.combinedContent) {
|
|
204
204
|
resolved.abilityContent = injection.combinedContent;
|
|
205
205
|
}
|
|
206
|
-
} catch {
|
|
207
|
-
//
|
|
206
|
+
} catch (error) {
|
|
207
|
+
// Log warning for diagnostics, but don't fail discussion
|
|
208
|
+
console.warn(
|
|
209
|
+
`[participant-resolver] Ability injection failed for agent ${agentId}:`,
|
|
210
|
+
error instanceof Error ? error.message : String(error)
|
|
211
|
+
);
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
|
|
@@ -236,13 +240,23 @@ export function providersToParticipants(providers: string[]): DiscussionParticip
|
|
|
236
240
|
* Parse participant string (e.g., "claude" or "reviewer:agent")
|
|
237
241
|
*/
|
|
238
242
|
export function parseParticipantString(input: string): DiscussionParticipant {
|
|
239
|
-
const
|
|
243
|
+
const trimmed = input.trim();
|
|
244
|
+
if (!trimmed) {
|
|
245
|
+
throw new Error('Participant string cannot be empty');
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const parts = trimmed.split(':');
|
|
249
|
+
const id = parts[0]!.trim();
|
|
250
|
+
|
|
251
|
+
if (!id) {
|
|
252
|
+
throw new Error('Participant ID cannot be empty');
|
|
253
|
+
}
|
|
240
254
|
|
|
241
255
|
if (parts.length === 2 && parts[1] === 'agent') {
|
|
242
|
-
return { type: 'agent', id
|
|
256
|
+
return { type: 'agent', id };
|
|
243
257
|
}
|
|
244
258
|
|
|
245
|
-
return { type: 'provider', id
|
|
259
|
+
return { type: 'provider', id };
|
|
246
260
|
}
|
|
247
261
|
|
|
248
262
|
/**
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import type { DiscussionRound, DebateRole } from '@defai.digital/contracts';
|
|
18
|
+
import { DEFAULT_ROUND_AGREEMENT_THRESHOLD } from '@defai.digital/contracts';
|
|
18
19
|
import type {
|
|
19
20
|
PatternExecutor,
|
|
20
21
|
PatternExecutionContext,
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
formatPreviousResponses,
|
|
29
30
|
getProviderSystemPrompt,
|
|
30
31
|
} from '../prompts/templates.js';
|
|
31
|
-
import { extractConfidence, evaluateEarlyExit } from '../confidence-extractor.js';
|
|
32
|
+
import { extractConfidence, evaluateEarlyExit, calculateAgreementScore } from '../confidence-extractor.js';
|
|
32
33
|
|
|
33
34
|
// Local type for discussion DiscussionProviderResponse (avoids conflict with provider/v1 DiscussionProviderResponse)
|
|
34
35
|
interface DiscussionProviderResponse {
|
|
@@ -57,6 +58,9 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
57
58
|
const failedProviders = new Set<string>();
|
|
58
59
|
let earlyExit: EarlyExitInfo | undefined;
|
|
59
60
|
|
|
61
|
+
// Extract round early exit config
|
|
62
|
+
const roundEarlyExit = config.roundEarlyExit ?? { enabled: true, agreementThreshold: DEFAULT_ROUND_AGREEMENT_THRESHOLD, minRounds: 1 };
|
|
63
|
+
|
|
60
64
|
// Filter to available providers
|
|
61
65
|
const providers = config.providers.filter(p => availableProviders.includes(p));
|
|
62
66
|
|
|
@@ -75,7 +79,9 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
75
79
|
onProgress?.({
|
|
76
80
|
type: 'round_start',
|
|
77
81
|
round: 1,
|
|
78
|
-
message:
|
|
82
|
+
message: config.fastMode
|
|
83
|
+
? 'Fast mode: Gathering perspectives (single round)'
|
|
84
|
+
: 'Gathering initial perspectives in parallel',
|
|
79
85
|
timestamp: new Date().toISOString(),
|
|
80
86
|
});
|
|
81
87
|
|
|
@@ -98,6 +104,11 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
98
104
|
round: 1,
|
|
99
105
|
message: `Initial perspectives gathered from ${initialRound.succeeded.length} providers`,
|
|
100
106
|
timestamp: new Date().toISOString(),
|
|
107
|
+
// Extended fields for Phase 2 tracing
|
|
108
|
+
participatingProviders: initialRound.succeeded,
|
|
109
|
+
failedProviders: initialRound.failed,
|
|
110
|
+
responseCount: initialRound.round.responses.length,
|
|
111
|
+
durationMs: initialRound.round.durationMs,
|
|
101
112
|
});
|
|
102
113
|
|
|
103
114
|
// Check if enough providers participated
|
|
@@ -112,6 +123,28 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
112
123
|
};
|
|
113
124
|
}
|
|
114
125
|
|
|
126
|
+
// FAST MODE: Skip cross-discussion rounds entirely
|
|
127
|
+
if (config.fastMode) {
|
|
128
|
+
onProgress?.({
|
|
129
|
+
type: 'round_complete',
|
|
130
|
+
message: 'Fast mode: Skipping cross-discussion, proceeding to synthesis',
|
|
131
|
+
timestamp: new Date().toISOString(),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
rounds,
|
|
136
|
+
participatingProviders: Array.from(participatingProviders),
|
|
137
|
+
failedProviders: Array.from(failedProviders),
|
|
138
|
+
totalDurationMs: Date.now() - startTime,
|
|
139
|
+
success: true,
|
|
140
|
+
earlyExit: {
|
|
141
|
+
triggered: true,
|
|
142
|
+
reason: 'Fast mode enabled - single round',
|
|
143
|
+
atProviderCount: participatingProviders.size,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
115
148
|
// Check for early exit after round 1 (INV-DISC-643)
|
|
116
149
|
if (cascadingConfidence?.enabled) {
|
|
117
150
|
const responsesWithConfidence = initialRound.round.responses.map(r => ({
|
|
@@ -149,6 +182,34 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
149
182
|
}
|
|
150
183
|
}
|
|
151
184
|
|
|
185
|
+
// ROUND-LEVEL EARLY EXIT: Check agreement after round 1
|
|
186
|
+
if (roundEarlyExit.enabled && rounds.length >= (roundEarlyExit.minRounds ?? 1)) {
|
|
187
|
+
const agreementScore = this.calculateRoundAgreement(initialRound.round.responses);
|
|
188
|
+
const threshold = roundEarlyExit.agreementThreshold ?? DEFAULT_ROUND_AGREEMENT_THRESHOLD;
|
|
189
|
+
|
|
190
|
+
if (agreementScore >= threshold) {
|
|
191
|
+
onProgress?.({
|
|
192
|
+
type: 'round_complete',
|
|
193
|
+
message: `Round early exit: High agreement detected (${(agreementScore * 100).toFixed(0)}% >= ${(threshold * 100).toFixed(0)}%)`,
|
|
194
|
+
timestamp: new Date().toISOString(),
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
rounds,
|
|
199
|
+
participatingProviders: Array.from(participatingProviders),
|
|
200
|
+
failedProviders: Array.from(failedProviders),
|
|
201
|
+
totalDurationMs: Date.now() - startTime,
|
|
202
|
+
success: true,
|
|
203
|
+
earlyExit: {
|
|
204
|
+
triggered: true,
|
|
205
|
+
reason: `High agreement after round 1 (${(agreementScore * 100).toFixed(0)}%)`,
|
|
206
|
+
atProviderCount: participatingProviders.size,
|
|
207
|
+
confidenceScore: agreementScore,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
152
213
|
// Additional rounds: Cross-discussion
|
|
153
214
|
for (let roundNum = 2; roundNum <= config.rounds; roundNum++) {
|
|
154
215
|
if (abortSignal?.aborted) {
|
|
@@ -180,6 +241,11 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
180
241
|
round: roundNum,
|
|
181
242
|
message: `Cross-discussion round ${roundNum} complete`,
|
|
182
243
|
timestamp: new Date().toISOString(),
|
|
244
|
+
// Extended fields for Phase 2 tracing
|
|
245
|
+
participatingProviders: providers.filter(p => !crossRound.failed.includes(p)),
|
|
246
|
+
failedProviders: crossRound.failed,
|
|
247
|
+
responseCount: crossRound.round.responses.length,
|
|
248
|
+
durationMs: crossRound.round.durationMs,
|
|
183
249
|
});
|
|
184
250
|
|
|
185
251
|
// Check for early exit after each round
|
|
@@ -297,6 +363,11 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
297
363
|
provider: providerId,
|
|
298
364
|
message: result.success ? 'completed' : `failed: ${result.error}`,
|
|
299
365
|
timestamp: new Date().toISOString(),
|
|
366
|
+
// Extended fields for Phase 2 tracing
|
|
367
|
+
success: result.success,
|
|
368
|
+
durationMs: result.durationMs,
|
|
369
|
+
tokenCount: result.tokenCount,
|
|
370
|
+
error: result.success ? undefined : result.error,
|
|
300
371
|
});
|
|
301
372
|
|
|
302
373
|
return response;
|
|
@@ -405,6 +476,11 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
405
476
|
round: roundNum,
|
|
406
477
|
provider: providerId,
|
|
407
478
|
timestamp: new Date().toISOString(),
|
|
479
|
+
// Extended fields for Phase 2 tracing
|
|
480
|
+
success: result.success,
|
|
481
|
+
durationMs: result.durationMs,
|
|
482
|
+
tokenCount: result.tokenCount,
|
|
483
|
+
error: result.success ? undefined : result.error,
|
|
408
484
|
});
|
|
409
485
|
|
|
410
486
|
return response;
|
|
@@ -436,4 +512,28 @@ export class SynthesisPattern implements PatternExecutor {
|
|
|
436
512
|
failed,
|
|
437
513
|
};
|
|
438
514
|
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Calculate agreement score for responses in a round.
|
|
518
|
+
* Uses semantic similarity and key phrase overlap to detect consensus.
|
|
519
|
+
*/
|
|
520
|
+
private calculateRoundAgreement(responses: DiscussionProviderResponse[]): number {
|
|
521
|
+
if (responses.length < 2) {
|
|
522
|
+
return 1.0; // Single response = full agreement
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const successfulResponses = responses.filter(r => !r.error && r.content.length > 0);
|
|
526
|
+
if (successfulResponses.length < 2) {
|
|
527
|
+
return 0.5; // Not enough responses to compare
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Use the calculateAgreementScore function from confidence-extractor
|
|
531
|
+
const responsesForScoring = successfulResponses.map(r => ({
|
|
532
|
+
provider: r.provider,
|
|
533
|
+
content: r.content,
|
|
534
|
+
confidence: r.confidence,
|
|
535
|
+
}));
|
|
536
|
+
|
|
537
|
+
return calculateAgreementScore(responsesForScoring);
|
|
538
|
+
}
|
|
439
539
|
}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_PROVIDERS,
|
|
16
|
+
DEFAULT_PROVIDER_TIMEOUT,
|
|
16
17
|
DiscussionErrorCodes,
|
|
17
18
|
createFailedDiscussionResult,
|
|
18
19
|
type DiscussStepConfig,
|
|
@@ -77,7 +78,7 @@ export class RecursiveDiscussionExecutor {
|
|
|
77
78
|
|
|
78
79
|
constructor(options: RecursiveDiscussionExecutorOptions) {
|
|
79
80
|
this.providerExecutor = options.providerExecutor;
|
|
80
|
-
this.defaultTimeoutMs = options.defaultTimeoutMs ??
|
|
81
|
+
this.defaultTimeoutMs = options.defaultTimeoutMs ?? DEFAULT_PROVIDER_TIMEOUT;
|
|
81
82
|
this.checkProviderHealth = options.checkProviderHealth ?? true;
|
|
82
83
|
this.traceId = options.traceId;
|
|
83
84
|
this.parentContext = options.parentContext;
|
|
@@ -141,6 +142,7 @@ export class RecursiveDiscussionExecutor {
|
|
|
141
142
|
minProviders: 2,
|
|
142
143
|
temperature: 0.7,
|
|
143
144
|
agentWeightMultiplier: DEFAULT_AGENT_WEIGHT_MULTIPLIER,
|
|
145
|
+
fastMode: false,
|
|
144
146
|
};
|
|
145
147
|
|
|
146
148
|
return this.execute(config, options);
|
|
@@ -288,6 +290,7 @@ export class RecursiveDiscussionExecutor {
|
|
|
288
290
|
temperature: 0.7,
|
|
289
291
|
verbose: false,
|
|
290
292
|
agentWeightMultiplier: DEFAULT_AGENT_WEIGHT_MULTIPLIER,
|
|
293
|
+
fastMode: true, // Sub-discussions use fast mode
|
|
291
294
|
},
|
|
292
295
|
abortSignal ? { abortSignal } : {}
|
|
293
296
|
);
|
package/src/types.ts
CHANGED
|
@@ -117,6 +117,27 @@ export interface CascadingConfidenceOptions {
|
|
|
117
117
|
/**
|
|
118
118
|
* Context passed to pattern executors
|
|
119
119
|
*/
|
|
120
|
+
/**
|
|
121
|
+
* Resolved participant for pattern execution (subset of full type)
|
|
122
|
+
* Full type is in participant-resolver.ts
|
|
123
|
+
*/
|
|
124
|
+
export interface ResolvedParticipantLike {
|
|
125
|
+
/** Original participant identifier */
|
|
126
|
+
id: string;
|
|
127
|
+
/** Whether this is an agent (vs raw provider) */
|
|
128
|
+
isAgent: boolean;
|
|
129
|
+
/** Provider ID to use for LLM calls */
|
|
130
|
+
providerId: string;
|
|
131
|
+
/** Agent ID (if isAgent) */
|
|
132
|
+
agentId?: string | undefined;
|
|
133
|
+
/** System prompt override (from agent config) */
|
|
134
|
+
systemPromptOverride?: string | undefined;
|
|
135
|
+
/** Injected ability content */
|
|
136
|
+
abilityContent?: string | undefined;
|
|
137
|
+
/** Weight multiplier for consensus */
|
|
138
|
+
weightMultiplier: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
120
141
|
export interface PatternExecutionContext {
|
|
121
142
|
/** The discussion configuration */
|
|
122
143
|
config: DiscussStepConfig;
|
|
@@ -138,17 +159,46 @@ export interface PatternExecutionContext {
|
|
|
138
159
|
|
|
139
160
|
/** Cascading confidence configuration for early exit */
|
|
140
161
|
cascadingConfidence?: CascadingConfidenceOptions | undefined;
|
|
162
|
+
|
|
163
|
+
/** Resolved participants including agents (when participants array is used) */
|
|
164
|
+
resolvedParticipants?: ResolvedParticipantLike[] | undefined;
|
|
141
165
|
}
|
|
142
166
|
|
|
143
167
|
/**
|
|
144
168
|
* Progress event during discussion execution
|
|
169
|
+
* Extended with detailed data for Phase 2 trace event emission
|
|
145
170
|
*/
|
|
146
171
|
export interface DiscussionProgressEvent {
|
|
147
|
-
type: 'round_start' | 'provider_start' | 'provider_complete' | 'round_complete' | 'synthesis_start' | 'synthesis_complete';
|
|
172
|
+
type: 'round_start' | 'provider_start' | 'provider_complete' | 'round_complete' | 'synthesis_start' | 'synthesis_complete' | 'consensus_complete';
|
|
148
173
|
round?: number | undefined;
|
|
149
174
|
provider?: string | undefined;
|
|
150
175
|
message?: string | undefined;
|
|
151
176
|
timestamp: string;
|
|
177
|
+
// Extended fields for granular tracing (Phase 2)
|
|
178
|
+
/** Provider response success status */
|
|
179
|
+
success?: boolean | undefined;
|
|
180
|
+
/** Duration in milliseconds */
|
|
181
|
+
durationMs?: number | undefined;
|
|
182
|
+
/** Token count for provider response */
|
|
183
|
+
tokenCount?: number | undefined;
|
|
184
|
+
/** Error message for failed responses */
|
|
185
|
+
error?: string | undefined;
|
|
186
|
+
/** Role in debate pattern */
|
|
187
|
+
role?: string | undefined;
|
|
188
|
+
/** Participating providers (for round_complete) */
|
|
189
|
+
participatingProviders?: string[] | undefined;
|
|
190
|
+
/** Failed providers (for round_complete) */
|
|
191
|
+
failedProviders?: string[] | undefined;
|
|
192
|
+
/** Response count (for round_complete) */
|
|
193
|
+
responseCount?: number | undefined;
|
|
194
|
+
/** Consensus method (for consensus_complete) */
|
|
195
|
+
consensusMethod?: string | undefined;
|
|
196
|
+
/** Agreement/confidence score (for consensus_complete) */
|
|
197
|
+
confidence?: number | undefined;
|
|
198
|
+
/** Vote counts (for voting consensus) */
|
|
199
|
+
votes?: Record<string, number> | undefined;
|
|
200
|
+
/** Winner (for voting consensus) */
|
|
201
|
+
winner?: string | undefined;
|
|
152
202
|
}
|
|
153
203
|
|
|
154
204
|
/**
|
|
@@ -283,6 +333,19 @@ export interface ConsensusExecutor {
|
|
|
283
333
|
/**
|
|
284
334
|
* Options for creating a discussion executor
|
|
285
335
|
*/
|
|
336
|
+
/**
|
|
337
|
+
* Options for participant resolution (subset of full type)
|
|
338
|
+
* Full type is in participant-resolver.ts
|
|
339
|
+
*/
|
|
340
|
+
export interface ParticipantResolverOptionsLike {
|
|
341
|
+
/** Agent registry for looking up agents */
|
|
342
|
+
agentRegistry?: { get(agentId: string): Promise<{ agentId: string; systemPrompt?: string } | null> } | undefined;
|
|
343
|
+
/** Ability manager for injecting abilities */
|
|
344
|
+
abilityManager?: { injectAbilities(agentId: string, task: string, coreAbilities: string[], options: { maxAbilities: number; maxTokens: number }): Promise<{ combinedContent: string; injectedAbilities: string[] }> } | undefined;
|
|
345
|
+
/** Default provider to use when agent has no preference */
|
|
346
|
+
defaultProvider?: string | undefined;
|
|
347
|
+
}
|
|
348
|
+
|
|
286
349
|
export interface DiscussionExecutorOptions {
|
|
287
350
|
/** Provider executor implementation */
|
|
288
351
|
providerExecutor: DiscussionProviderExecutor;
|
|
@@ -295,6 +358,12 @@ export interface DiscussionExecutorOptions {
|
|
|
295
358
|
|
|
296
359
|
/** Trace ID for debugging */
|
|
297
360
|
traceId?: string | undefined;
|
|
361
|
+
|
|
362
|
+
/** Options for resolving agent participants (INV-DISC-640, INV-DISC-641) */
|
|
363
|
+
participantResolverOptions?: ParticipantResolverOptionsLike | undefined;
|
|
364
|
+
|
|
365
|
+
/** Cascading confidence config for early exit (INV-DISC-622, INV-DISC-623) */
|
|
366
|
+
cascadingConfidence?: CascadingConfidenceOptions | undefined;
|
|
298
367
|
}
|
|
299
368
|
|
|
300
369
|
// ============================================================================
|