mcp-rubber-duck 1.2.5 ā 1.3.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/.eslintrc.json +1 -0
- package/CHANGELOG.md +12 -0
- package/README.md +116 -2
- package/dist/config/types.d.ts +78 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +150 -0
- package/dist/server.js.map +1 -1
- package/dist/services/consensus.d.ts +28 -0
- package/dist/services/consensus.d.ts.map +1 -0
- package/dist/services/consensus.js +257 -0
- package/dist/services/consensus.js.map +1 -0
- package/dist/tools/duck-debate.d.ts +16 -0
- package/dist/tools/duck-debate.d.ts.map +1 -0
- package/dist/tools/duck-debate.js +272 -0
- package/dist/tools/duck-debate.js.map +1 -0
- package/dist/tools/duck-iterate.d.ts +14 -0
- package/dist/tools/duck-iterate.d.ts.map +1 -0
- package/dist/tools/duck-iterate.js +195 -0
- package/dist/tools/duck-iterate.js.map +1 -0
- package/dist/tools/duck-judge.d.ts +15 -0
- package/dist/tools/duck-judge.d.ts.map +1 -0
- package/dist/tools/duck-judge.js +208 -0
- package/dist/tools/duck-judge.js.map +1 -0
- package/dist/tools/duck-vote.d.ts +14 -0
- package/dist/tools/duck-vote.d.ts.map +1 -0
- package/dist/tools/duck-vote.js +46 -0
- package/dist/tools/duck-vote.js.map +1 -0
- package/package.json +1 -1
- package/src/config/types.ts +92 -0
- package/src/server.ts +154 -0
- package/src/services/consensus.ts +324 -0
- package/src/tools/duck-debate.ts +383 -0
- package/src/tools/duck-iterate.ts +253 -0
- package/src/tools/duck-judge.ts +301 -0
- package/src/tools/duck-vote.ts +87 -0
- package/tests/consensus.test.ts +282 -0
- package/tests/duck-debate.test.ts +286 -0
- package/tests/duck-iterate.test.ts +249 -0
- package/tests/duck-judge.test.ts +296 -0
- package/tests/duck-vote.test.ts +250 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
export class ConsensusService {
|
|
3
|
+
/**
|
|
4
|
+
* Build a voting prompt that asks the LLM to vote on options
|
|
5
|
+
*/
|
|
6
|
+
buildVotePrompt(question, options, requireReasoning = true) {
|
|
7
|
+
const optionsList = options.map((opt, i) => `${i + 1}. ${opt}`).join('\n');
|
|
8
|
+
const format = requireReasoning
|
|
9
|
+
? `{
|
|
10
|
+
"choice": "<exact option text>",
|
|
11
|
+
"confidence": <0-100>,
|
|
12
|
+
"reasoning": "<brief explanation>"
|
|
13
|
+
}`
|
|
14
|
+
: `{
|
|
15
|
+
"choice": "<exact option text>",
|
|
16
|
+
"confidence": <0-100>
|
|
17
|
+
}`;
|
|
18
|
+
return `You are voting on the following question. You MUST choose exactly ONE option from the list below.
|
|
19
|
+
|
|
20
|
+
QUESTION: ${question}
|
|
21
|
+
|
|
22
|
+
OPTIONS:
|
|
23
|
+
${optionsList}
|
|
24
|
+
|
|
25
|
+
INSTRUCTIONS:
|
|
26
|
+
1. Analyze each option carefully
|
|
27
|
+
2. Choose the BEST option based on your knowledge and reasoning
|
|
28
|
+
3. Respond with ONLY a JSON object in this exact format:
|
|
29
|
+
|
|
30
|
+
${format}
|
|
31
|
+
|
|
32
|
+
IMPORTANT:
|
|
33
|
+
- "choice" must be the EXACT text of one of the options above
|
|
34
|
+
- "confidence" must be a number from 0 to 100
|
|
35
|
+
- Do NOT include any text before or after the JSON
|
|
36
|
+
- Do NOT use markdown code blocks`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse a vote from an LLM response
|
|
40
|
+
*/
|
|
41
|
+
parseVote(response, voter, nickname, options) {
|
|
42
|
+
const result = {
|
|
43
|
+
voter,
|
|
44
|
+
nickname,
|
|
45
|
+
choice: '',
|
|
46
|
+
confidence: 0,
|
|
47
|
+
reasoning: '',
|
|
48
|
+
rawResponse: response,
|
|
49
|
+
};
|
|
50
|
+
try {
|
|
51
|
+
// Try to extract JSON from the response (greedy to handle nested objects)
|
|
52
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
53
|
+
if (!jsonMatch) {
|
|
54
|
+
logger.warn(`No JSON found in vote response from ${voter}`);
|
|
55
|
+
return this.fallbackParse(response, voter, nickname, options);
|
|
56
|
+
}
|
|
57
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
58
|
+
// Validate choice
|
|
59
|
+
const choice = parsed.choice?.toString().trim();
|
|
60
|
+
if (choice) {
|
|
61
|
+
// Try exact match first
|
|
62
|
+
const exactMatch = options.find(opt => opt.toLowerCase() === choice.toLowerCase());
|
|
63
|
+
if (exactMatch) {
|
|
64
|
+
result.choice = exactMatch;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Try partial match
|
|
68
|
+
const partialMatch = options.find(opt => opt.toLowerCase().includes(choice.toLowerCase()) ||
|
|
69
|
+
choice.toLowerCase().includes(opt.toLowerCase()));
|
|
70
|
+
if (partialMatch) {
|
|
71
|
+
result.choice = partialMatch;
|
|
72
|
+
logger.debug(`Fuzzy matched "${choice}" to "${partialMatch}" for ${voter}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Parse confidence
|
|
77
|
+
if (typeof parsed.confidence === 'number') {
|
|
78
|
+
result.confidence = Math.max(0, Math.min(100, parsed.confidence));
|
|
79
|
+
}
|
|
80
|
+
else if (typeof parsed.confidence === 'string') {
|
|
81
|
+
const conf = parseFloat(parsed.confidence);
|
|
82
|
+
if (!isNaN(conf)) {
|
|
83
|
+
result.confidence = Math.max(0, Math.min(100, conf));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Parse reasoning
|
|
87
|
+
if (parsed.reasoning) {
|
|
88
|
+
result.reasoning = parsed.reasoning.toString().trim();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
logger.warn(`Failed to parse JSON vote from ${voter}:`, error);
|
|
93
|
+
return this.fallbackParse(response, voter, nickname, options);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Fallback parsing when JSON fails - try to extract choice from text
|
|
99
|
+
*/
|
|
100
|
+
fallbackParse(response, voter, nickname, options) {
|
|
101
|
+
const result = {
|
|
102
|
+
voter,
|
|
103
|
+
nickname,
|
|
104
|
+
choice: '',
|
|
105
|
+
confidence: 50, // Default confidence for fallback
|
|
106
|
+
reasoning: 'Vote extracted via fallback parsing',
|
|
107
|
+
rawResponse: response,
|
|
108
|
+
};
|
|
109
|
+
// Try to find any option mentioned in the response
|
|
110
|
+
const responseLower = response.toLowerCase();
|
|
111
|
+
for (const option of options) {
|
|
112
|
+
if (responseLower.includes(option.toLowerCase())) {
|
|
113
|
+
result.choice = option;
|
|
114
|
+
logger.debug(`Fallback parsed choice "${option}" from ${voter}`);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Aggregate votes into a final result
|
|
122
|
+
*/
|
|
123
|
+
aggregateVotes(question, options, votes) {
|
|
124
|
+
// Initialize tally and confidence tracking
|
|
125
|
+
const tally = {};
|
|
126
|
+
const confidenceSums = {};
|
|
127
|
+
const confidenceCounts = {};
|
|
128
|
+
for (const option of options) {
|
|
129
|
+
tally[option] = 0;
|
|
130
|
+
confidenceSums[option] = 0;
|
|
131
|
+
confidenceCounts[option] = 0;
|
|
132
|
+
}
|
|
133
|
+
// Count votes
|
|
134
|
+
let validVotes = 0;
|
|
135
|
+
for (const vote of votes) {
|
|
136
|
+
if (vote.choice && options.includes(vote.choice)) {
|
|
137
|
+
tally[vote.choice]++;
|
|
138
|
+
confidenceSums[vote.choice] += vote.confidence;
|
|
139
|
+
confidenceCounts[vote.choice]++;
|
|
140
|
+
validVotes++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Calculate average confidence per option
|
|
144
|
+
const confidenceByOption = {};
|
|
145
|
+
for (const option of options) {
|
|
146
|
+
confidenceByOption[option] = confidenceCounts[option] > 0
|
|
147
|
+
? Math.round(confidenceSums[option] / confidenceCounts[option])
|
|
148
|
+
: 0;
|
|
149
|
+
}
|
|
150
|
+
// Determine winner
|
|
151
|
+
const maxVotes = Math.max(...Object.values(tally));
|
|
152
|
+
const winners = options.filter(opt => tally[opt] === maxVotes && maxVotes > 0);
|
|
153
|
+
const isTie = winners.length > 1;
|
|
154
|
+
let winner = null;
|
|
155
|
+
if (winners.length === 1) {
|
|
156
|
+
winner = winners[0];
|
|
157
|
+
}
|
|
158
|
+
else if (isTie && winners.length > 0) {
|
|
159
|
+
// Break tie by confidence
|
|
160
|
+
let highestConfidence = -1;
|
|
161
|
+
for (const w of winners) {
|
|
162
|
+
if (confidenceByOption[w] > highestConfidence) {
|
|
163
|
+
highestConfidence = confidenceByOption[w];
|
|
164
|
+
winner = w;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Determine consensus level
|
|
169
|
+
const consensusLevel = this.determineConsensusLevel(validVotes, votes.length, maxVotes, isTie);
|
|
170
|
+
return {
|
|
171
|
+
question,
|
|
172
|
+
options,
|
|
173
|
+
winner,
|
|
174
|
+
isTie,
|
|
175
|
+
tally,
|
|
176
|
+
confidenceByOption,
|
|
177
|
+
votes,
|
|
178
|
+
totalVoters: votes.length,
|
|
179
|
+
validVotes,
|
|
180
|
+
consensusLevel,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Determine the level of consensus reached
|
|
185
|
+
*/
|
|
186
|
+
determineConsensusLevel(validVotes, totalVoters, maxVotes, isTie) {
|
|
187
|
+
if (validVotes === 0) {
|
|
188
|
+
return 'none';
|
|
189
|
+
}
|
|
190
|
+
const winnerRatio = maxVotes / validVotes;
|
|
191
|
+
if (winnerRatio === 1 && validVotes === totalVoters) {
|
|
192
|
+
return 'unanimous';
|
|
193
|
+
}
|
|
194
|
+
else if (winnerRatio > 0.5) {
|
|
195
|
+
return 'majority';
|
|
196
|
+
}
|
|
197
|
+
else if (!isTie && maxVotes > 0) {
|
|
198
|
+
return 'plurality';
|
|
199
|
+
}
|
|
200
|
+
else if (isTie) {
|
|
201
|
+
return 'split';
|
|
202
|
+
}
|
|
203
|
+
return 'none';
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Format the aggregated vote result for display
|
|
207
|
+
*/
|
|
208
|
+
formatVoteResult(result) {
|
|
209
|
+
let output = `š³ļø **Vote Results**\n`;
|
|
210
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n`;
|
|
211
|
+
output += `**Question:** ${result.question}\n\n`;
|
|
212
|
+
// Winner announcement
|
|
213
|
+
if (result.winner) {
|
|
214
|
+
const emoji = result.consensusLevel === 'unanimous' ? 'š' :
|
|
215
|
+
result.consensusLevel === 'majority' ? 'ā
' : 'š';
|
|
216
|
+
output += `${emoji} **Winner:** ${result.winner}`;
|
|
217
|
+
if (result.isTie) {
|
|
218
|
+
output += ` (tie-breaker by confidence)`;
|
|
219
|
+
}
|
|
220
|
+
output += `\n`;
|
|
221
|
+
output += `š **Consensus:** ${result.consensusLevel}\n\n`;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
output += `ā ļø **No valid votes recorded**\n\n`;
|
|
225
|
+
}
|
|
226
|
+
// Vote tally
|
|
227
|
+
output += `**Vote Tally:**\n`;
|
|
228
|
+
const sortedOptions = [...result.options].sort((a, b) => result.tally[b] - result.tally[a]);
|
|
229
|
+
for (const option of sortedOptions) {
|
|
230
|
+
const votes = result.tally[option];
|
|
231
|
+
const confidence = result.confidenceByOption[option];
|
|
232
|
+
const bar = 'ā'.repeat(Math.min(votes * 3, 15));
|
|
233
|
+
const isWinner = option === result.winner;
|
|
234
|
+
const marker = isWinner ? ' š' : '';
|
|
235
|
+
output += ` ${option}: ${bar} ${votes} vote(s) (avg confidence: ${confidence}%)${marker}\n`;
|
|
236
|
+
}
|
|
237
|
+
output += `\n**Individual Votes:**\n`;
|
|
238
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
239
|
+
for (const vote of result.votes) {
|
|
240
|
+
if (vote.choice) {
|
|
241
|
+
output += `š¦ **${vote.nickname}** voted: **${vote.choice}**`;
|
|
242
|
+
output += ` (confidence: ${vote.confidence}%)\n`;
|
|
243
|
+
if (vote.reasoning) {
|
|
244
|
+
output += ` š "${vote.reasoning}"\n`;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
output += `š¦ **${vote.nickname}**: ā Invalid vote\n`;
|
|
249
|
+
}
|
|
250
|
+
output += `\n`;
|
|
251
|
+
}
|
|
252
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
253
|
+
output += `š ${result.validVotes}/${result.totalVoters} valid votes\n`;
|
|
254
|
+
return output;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=consensus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consensus.js","sourceRoot":"","sources":["../../src/services/consensus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ProviderManager } from '../providers/manager.js';
|
|
2
|
+
import { DebateFormat } from '../config/types.js';
|
|
3
|
+
export interface DuckDebateArgs {
|
|
4
|
+
prompt: string;
|
|
5
|
+
rounds?: number;
|
|
6
|
+
providers?: string[];
|
|
7
|
+
format: DebateFormat;
|
|
8
|
+
synthesizer?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function duckDebateTool(providerManager: ProviderManager, args: Record<string, unknown>): Promise<{
|
|
11
|
+
content: {
|
|
12
|
+
type: string;
|
|
13
|
+
text: string;
|
|
14
|
+
}[];
|
|
15
|
+
}>;
|
|
16
|
+
//# sourceMappingURL=duck-debate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duck-debate.d.ts","sourceRoot":"","sources":["../../src/tools/duck-debate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EACL,YAAY,EAKb,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,wBAAsB,cAAc,CAClC,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;GAgH9B"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
const DEFAULT_ROUNDS = 3;
|
|
3
|
+
export async function duckDebateTool(providerManager, args) {
|
|
4
|
+
const { prompt, rounds = DEFAULT_ROUNDS, providers, format, synthesizer, } = args;
|
|
5
|
+
// Validate inputs
|
|
6
|
+
if (!prompt || typeof prompt !== 'string') {
|
|
7
|
+
throw new Error('Prompt/topic is required');
|
|
8
|
+
}
|
|
9
|
+
if (!format || !['oxford', 'socratic', 'adversarial'].includes(format)) {
|
|
10
|
+
throw new Error('Format must be "oxford", "socratic", or "adversarial"');
|
|
11
|
+
}
|
|
12
|
+
if (rounds < 1 || rounds > 10) {
|
|
13
|
+
throw new Error('Rounds must be between 1 and 10');
|
|
14
|
+
}
|
|
15
|
+
// Get providers
|
|
16
|
+
const allProviders = providerManager.getProviderNames();
|
|
17
|
+
// If providers explicitly specified but less than 2, error
|
|
18
|
+
if (providers && providers.length < 2) {
|
|
19
|
+
throw new Error('At least 2 providers are required for a debate');
|
|
20
|
+
}
|
|
21
|
+
const debateProviders = providers && providers.length >= 2
|
|
22
|
+
? providers
|
|
23
|
+
: allProviders;
|
|
24
|
+
if (debateProviders.length < 2) {
|
|
25
|
+
throw new Error('At least 2 providers are required for a debate');
|
|
26
|
+
}
|
|
27
|
+
// Validate providers exist
|
|
28
|
+
for (const p of debateProviders) {
|
|
29
|
+
if (!allProviders.includes(p)) {
|
|
30
|
+
throw new Error(`Provider "${p}" not found`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
logger.info(`Starting ${format} debate with ${debateProviders.length} participants for ${rounds} rounds`);
|
|
34
|
+
// Assign positions based on format
|
|
35
|
+
const participants = assignPositions(debateProviders, format, providerManager);
|
|
36
|
+
// Run debate rounds
|
|
37
|
+
const debateRounds = [];
|
|
38
|
+
for (let roundNum = 1; roundNum <= rounds; roundNum++) {
|
|
39
|
+
logger.info(`Debate round ${roundNum}/${rounds}`);
|
|
40
|
+
const roundArguments = [];
|
|
41
|
+
// Each participant argues in this round
|
|
42
|
+
for (const participant of participants) {
|
|
43
|
+
const argumentPrompt = buildArgumentPrompt(prompt, format, participant, roundNum, debateRounds, participants);
|
|
44
|
+
const response = await providerManager.askDuck(participant.provider, argumentPrompt);
|
|
45
|
+
roundArguments.push({
|
|
46
|
+
round: roundNum,
|
|
47
|
+
provider: participant.provider,
|
|
48
|
+
nickname: participant.nickname,
|
|
49
|
+
position: participant.position,
|
|
50
|
+
content: response.content,
|
|
51
|
+
timestamp: new Date(),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
debateRounds.push(roundArguments);
|
|
55
|
+
}
|
|
56
|
+
// Generate synthesis
|
|
57
|
+
const synthesizerProvider = synthesizer || debateProviders[0];
|
|
58
|
+
const synthesisPrompt = buildSynthesisPrompt(prompt, format, debateRounds, participants);
|
|
59
|
+
const synthesisResponse = await providerManager.askDuck(synthesizerProvider, synthesisPrompt);
|
|
60
|
+
const result = {
|
|
61
|
+
topic: prompt,
|
|
62
|
+
format,
|
|
63
|
+
participants,
|
|
64
|
+
rounds: debateRounds,
|
|
65
|
+
synthesis: synthesisResponse.content,
|
|
66
|
+
synthesizer: synthesizerProvider,
|
|
67
|
+
totalRounds: rounds,
|
|
68
|
+
};
|
|
69
|
+
// Format output
|
|
70
|
+
const formattedOutput = formatDebateResult(result);
|
|
71
|
+
logger.info(`Debate completed: ${rounds} rounds, synthesized by ${synthesizerProvider}`);
|
|
72
|
+
return {
|
|
73
|
+
content: [
|
|
74
|
+
{
|
|
75
|
+
type: 'text',
|
|
76
|
+
text: formattedOutput,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function assignPositions(providers, format, providerManager) {
|
|
82
|
+
const participants = [];
|
|
83
|
+
for (let i = 0; i < providers.length; i++) {
|
|
84
|
+
const provider = providers[i];
|
|
85
|
+
const providerInfo = providerManager.getProvider(provider);
|
|
86
|
+
let position;
|
|
87
|
+
if (format === 'oxford') {
|
|
88
|
+
// Oxford: alternating pro/con
|
|
89
|
+
position = i % 2 === 0 ? 'pro' : 'con';
|
|
90
|
+
}
|
|
91
|
+
else if (format === 'adversarial') {
|
|
92
|
+
// Adversarial: first is defender, rest are challengers (con)
|
|
93
|
+
position = i === 0 ? 'pro' : 'con';
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Socratic: all neutral, questioning each other
|
|
97
|
+
position = 'neutral';
|
|
98
|
+
}
|
|
99
|
+
participants.push({
|
|
100
|
+
provider,
|
|
101
|
+
nickname: providerInfo.nickname,
|
|
102
|
+
position,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return participants;
|
|
106
|
+
}
|
|
107
|
+
function buildArgumentPrompt(topic, format, participant, round, previousRounds, allParticipants) {
|
|
108
|
+
const previousContext = buildPreviousContext(previousRounds);
|
|
109
|
+
if (format === 'oxford') {
|
|
110
|
+
return buildOxfordPrompt(topic, participant, round, previousContext);
|
|
111
|
+
}
|
|
112
|
+
else if (format === 'socratic') {
|
|
113
|
+
return buildSocraticPrompt(topic, participant, round, previousContext, allParticipants);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return buildAdversarialPrompt(topic, participant, round, previousContext);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function buildPreviousContext(previousRounds) {
|
|
120
|
+
if (previousRounds.length === 0) {
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
let context = '\n\nPREVIOUS ARGUMENTS:\n';
|
|
124
|
+
for (const round of previousRounds) {
|
|
125
|
+
for (const arg of round) {
|
|
126
|
+
const posLabel = arg.position === 'pro' ? '[PRO]' :
|
|
127
|
+
arg.position === 'con' ? '[CON]' : '[NEUTRAL]';
|
|
128
|
+
context += `\n--- Round ${arg.round} - ${arg.nickname} ${posLabel} ---\n`;
|
|
129
|
+
context += `${arg.content}\n`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return context;
|
|
133
|
+
}
|
|
134
|
+
function buildOxfordPrompt(topic, participant, round, previousContext) {
|
|
135
|
+
const position = participant.position === 'pro' ? 'IN FAVOR OF' : 'AGAINST';
|
|
136
|
+
const positionLabel = participant.position === 'pro' ? 'PRO' : 'CON';
|
|
137
|
+
return `You are participating in an Oxford-style debate.
|
|
138
|
+
|
|
139
|
+
TOPIC: "${topic}"
|
|
140
|
+
|
|
141
|
+
YOUR POSITION: ${position} (${positionLabel})
|
|
142
|
+
ROUND: ${round}
|
|
143
|
+
|
|
144
|
+
${previousContext}
|
|
145
|
+
|
|
146
|
+
INSTRUCTIONS:
|
|
147
|
+
1. Present clear, logical arguments ${position.toLowerCase()} the topic
|
|
148
|
+
2. ${round > 1 ? 'Address and rebut opposing arguments from previous rounds' : 'Establish your core thesis and supporting points'}
|
|
149
|
+
3. Use evidence, examples, and reasoning
|
|
150
|
+
4. Be persuasive but intellectually honest
|
|
151
|
+
5. Keep your argument focused and structured
|
|
152
|
+
|
|
153
|
+
Present your argument for Round ${round}:`;
|
|
154
|
+
}
|
|
155
|
+
function buildSocraticPrompt(topic, participant, round, previousContext, allParticipants) {
|
|
156
|
+
const otherParticipants = allParticipants
|
|
157
|
+
.filter(p => p.provider !== participant.provider)
|
|
158
|
+
.map(p => p.nickname)
|
|
159
|
+
.join(', ');
|
|
160
|
+
return `You are participating in a Socratic dialogue.
|
|
161
|
+
|
|
162
|
+
TOPIC: "${topic}"
|
|
163
|
+
|
|
164
|
+
YOUR ROLE: Philosophical inquirer exploring the topic through questions and reasoning
|
|
165
|
+
OTHER PARTICIPANTS: ${otherParticipants}
|
|
166
|
+
ROUND: ${round}
|
|
167
|
+
|
|
168
|
+
${previousContext}
|
|
169
|
+
|
|
170
|
+
INSTRUCTIONS:
|
|
171
|
+
1. ${round === 1 ? 'Begin by questioning assumptions about the topic' : 'Build on previous responses with deeper questions'}
|
|
172
|
+
2. Use the Socratic method: ask probing questions that reveal underlying assumptions
|
|
173
|
+
3. Offer your own perspective while remaining open to other views
|
|
174
|
+
4. Seek to understand the truth through dialogue, not to "win"
|
|
175
|
+
5. Challenge ideas respectfully and constructively
|
|
176
|
+
|
|
177
|
+
Present your contribution to Round ${round}:`;
|
|
178
|
+
}
|
|
179
|
+
function buildAdversarialPrompt(topic, participant, round, previousContext) {
|
|
180
|
+
const role = participant.position === 'pro' ? 'DEFENDER' : 'CHALLENGER';
|
|
181
|
+
const instruction = participant.position === 'pro'
|
|
182
|
+
? 'Defend the proposition and address all critiques raised'
|
|
183
|
+
: 'Attack weaknesses in the arguments, find flaws, and present counter-examples';
|
|
184
|
+
return `You are participating in an adversarial debate.
|
|
185
|
+
|
|
186
|
+
TOPIC: "${topic}"
|
|
187
|
+
|
|
188
|
+
YOUR ROLE: ${role}
|
|
189
|
+
ROUND: ${round}
|
|
190
|
+
|
|
191
|
+
${previousContext}
|
|
192
|
+
|
|
193
|
+
INSTRUCTIONS:
|
|
194
|
+
1. ${instruction}
|
|
195
|
+
2. Be rigorous and thorough in your analysis
|
|
196
|
+
3. ${participant.position === 'con' ? 'Identify logical fallacies, weak evidence, or missing considerations' : 'Strengthen your position against attacks'}
|
|
197
|
+
4. Use concrete examples and evidence
|
|
198
|
+
5. Be intellectually aggressive but fair
|
|
199
|
+
|
|
200
|
+
Present your ${role.toLowerCase()} argument for Round ${round}:`;
|
|
201
|
+
}
|
|
202
|
+
function buildSynthesisPrompt(topic, format, rounds, participants) {
|
|
203
|
+
let transcript = '';
|
|
204
|
+
for (const round of rounds) {
|
|
205
|
+
for (const arg of round) {
|
|
206
|
+
const posLabel = arg.position === 'pro' ? '[PRO]' :
|
|
207
|
+
arg.position === 'con' ? '[CON]' : '[NEUTRAL]';
|
|
208
|
+
transcript += `\n--- Round ${arg.round} - ${arg.nickname} ${posLabel} ---\n`;
|
|
209
|
+
transcript += `${arg.content}\n`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const participantList = participants
|
|
213
|
+
.map(p => `${p.nickname} (${p.position})`)
|
|
214
|
+
.join(', ');
|
|
215
|
+
return `You are the moderator synthesizing a ${format} debate.
|
|
216
|
+
|
|
217
|
+
TOPIC: "${topic}"
|
|
218
|
+
PARTICIPANTS: ${participantList}
|
|
219
|
+
|
|
220
|
+
DEBATE TRANSCRIPT:
|
|
221
|
+
${transcript}
|
|
222
|
+
|
|
223
|
+
YOUR TASK:
|
|
224
|
+
1. Summarize the key arguments from each side
|
|
225
|
+
2. Identify the strongest points made
|
|
226
|
+
3. Note where participants agreed or found common ground
|
|
227
|
+
4. Highlight unresolved tensions or questions
|
|
228
|
+
5. Provide a balanced conclusion (who had stronger arguments, or if it was a draw)
|
|
229
|
+
6. Suggest what additional considerations might be valuable
|
|
230
|
+
|
|
231
|
+
Provide your synthesis:`;
|
|
232
|
+
}
|
|
233
|
+
function formatDebateResult(result) {
|
|
234
|
+
const formatEmoji = result.format === 'oxford' ? 'š' :
|
|
235
|
+
result.format === 'socratic' ? 'šļø' : 'āļø';
|
|
236
|
+
let output = `${formatEmoji} **${result.format.charAt(0).toUpperCase() + result.format.slice(1)} Debate**\n`;
|
|
237
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n`;
|
|
238
|
+
output += `**Topic:** "${result.topic}"\n`;
|
|
239
|
+
output += `**Format:** ${result.format}\n`;
|
|
240
|
+
output += `**Rounds:** ${result.totalRounds}\n\n`;
|
|
241
|
+
// Participants
|
|
242
|
+
output += `**Participants:**\n`;
|
|
243
|
+
for (const p of result.participants) {
|
|
244
|
+
const posEmoji = p.position === 'pro' ? 'ā
' : p.position === 'con' ? 'ā' : 'š';
|
|
245
|
+
output += ` ${posEmoji} ${p.nickname} (${p.position})\n`;
|
|
246
|
+
}
|
|
247
|
+
output += `\n`;
|
|
248
|
+
// Debate rounds
|
|
249
|
+
output += `**Debate Transcript:**\n`;
|
|
250
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
251
|
+
for (let i = 0; i < result.rounds.length; i++) {
|
|
252
|
+
output += `\nš¢ **ROUND ${i + 1}**\n`;
|
|
253
|
+
for (const arg of result.rounds[i]) {
|
|
254
|
+
const posEmoji = arg.position === 'pro' ? 'ā
' : arg.position === 'con' ? 'ā' : 'š';
|
|
255
|
+
output += `\n${posEmoji} **${arg.nickname}** [${arg.position.toUpperCase()}]:\n`;
|
|
256
|
+
// Truncate long arguments
|
|
257
|
+
const displayContent = arg.content.length > 800
|
|
258
|
+
? arg.content.substring(0, 800) + '...[truncated]'
|
|
259
|
+
: arg.content;
|
|
260
|
+
output += `${displayContent}\n`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Synthesis
|
|
264
|
+
output += `\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
265
|
+
output += `šÆ **Synthesis** (by ${result.synthesizer})\n`;
|
|
266
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
267
|
+
output += `${result.synthesis}\n`;
|
|
268
|
+
output += `\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
269
|
+
output += `š ${result.totalRounds} rounds completed with ${result.participants.length} participants\n`;
|
|
270
|
+
return output;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=duck-debate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duck-debate.js","sourceRoot":"","sources":["../../src/tools/duck-debate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ProviderManager } from '../providers/manager.js';
|
|
2
|
+
export interface DuckIterateArgs {
|
|
3
|
+
prompt: string;
|
|
4
|
+
iterations?: number;
|
|
5
|
+
providers: [string, string];
|
|
6
|
+
mode: 'refine' | 'critique-improve';
|
|
7
|
+
}
|
|
8
|
+
export declare function duckIterateTool(providerManager: ProviderManager, args: Record<string, unknown>): Promise<{
|
|
9
|
+
content: {
|
|
10
|
+
type: string;
|
|
11
|
+
text: string;
|
|
12
|
+
}[];
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=duck-iterate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duck-iterate.d.ts","sourceRoot":"","sources":["../../src/tools/duck-iterate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI1D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,IAAI,EAAE,QAAQ,GAAG,kBAAkB,CAAC;CACrC;AAKD,wBAAsB,eAAe,CACnC,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;GAkH9B"}
|