palabre 0.8.0 → 0.9.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/README.md +13 -15
- package/dist/adapters/cli-pty.js +1 -1
- package/dist/adapters/cli.js +33 -3
- package/dist/adapters/index.js +2 -2
- package/dist/adapters/ollama.js +9 -7
- package/dist/agentRegistry.js +7 -2
- package/dist/args.js +5 -2
- package/dist/config.js +33 -25
- package/dist/context.js +5 -1
- package/dist/discovery.js +30 -9
- package/dist/doctor.js +19 -5
- package/dist/history.js +85 -0
- package/dist/index.js +450 -205
- package/dist/messages/common.js +6 -0
- package/dist/messages/config.js +2 -0
- package/dist/messages/doctor.js +2 -2
- package/dist/messages/help.js +64 -8
- package/dist/messages/init.js +2 -2
- package/dist/messages/tui.js +78 -28
- package/dist/ollamaUrl.js +76 -0
- package/dist/orchestrator.js +34 -13
- package/dist/presets.js +25 -52
- package/dist/renderers/tui.js +242 -77
- package/dist/tuiState.js +32 -0
- package/package.json +1 -1
- package/palabre.config.example.json +0 -17
package/dist/orchestrator.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createAgent } from "./adapters/index.js";
|
|
2
2
|
import { AdapterError } from "./errors.js";
|
|
3
3
|
import { createTranslator } from "./i18n.js";
|
|
4
|
+
import { OllamaUrlError } from "./ollamaUrl.js";
|
|
4
5
|
export const MAX_ASK_AGENTS = 4;
|
|
5
6
|
/**
|
|
6
7
|
* Point d'entrée de l'orchestration.
|
|
@@ -27,8 +28,8 @@ export async function runDebate(config, options, renderer, messages = createTran
|
|
|
27
28
|
{ name: options.agentB, role: agentBConfig.role, type: agentBConfig.type }
|
|
28
29
|
]);
|
|
29
30
|
const agents = [
|
|
30
|
-
createAgent(options.agentA, agentAConfig),
|
|
31
|
-
createAgent(options.agentB, agentBConfig)
|
|
31
|
+
createAgent(options.agentA, agentAConfig, { ollamaUrl: options.ollamaUrl }),
|
|
32
|
+
createAgent(options.agentB, agentBConfig, { ollamaUrl: options.ollamaUrl })
|
|
32
33
|
];
|
|
33
34
|
const transcript = [];
|
|
34
35
|
let stopReason;
|
|
@@ -73,7 +74,7 @@ export async function runDebate(config, options, renderer, messages = createTran
|
|
|
73
74
|
agent: current.name,
|
|
74
75
|
role: current.role,
|
|
75
76
|
turn
|
|
76
|
-
});
|
|
77
|
+
}, messages);
|
|
77
78
|
renderer?.error(failure);
|
|
78
79
|
return {
|
|
79
80
|
options,
|
|
@@ -106,6 +107,7 @@ export async function runDebate(config, options, renderer, messages = createTran
|
|
|
106
107
|
const cancellation = cancellationFailureIfAborted(options, messages, {
|
|
107
108
|
phase: "summary",
|
|
108
109
|
agent: resolveSummaryAgentName(options),
|
|
110
|
+
role: summaryRole(),
|
|
109
111
|
turn: transcript.length + 1
|
|
110
112
|
});
|
|
111
113
|
if (cancellation) {
|
|
@@ -123,8 +125,9 @@ export async function runDebate(config, options, renderer, messages = createTran
|
|
|
123
125
|
failure = toDebateFailure(error, {
|
|
124
126
|
phase: "summary",
|
|
125
127
|
agent: resolveSummaryAgentName(options),
|
|
128
|
+
role: summaryRole(),
|
|
126
129
|
turn: transcript.length + 1
|
|
127
|
-
});
|
|
130
|
+
}, messages);
|
|
128
131
|
renderer?.error(failure);
|
|
129
132
|
}
|
|
130
133
|
}
|
|
@@ -161,7 +164,7 @@ export async function runAsk(config, options, renderer, messages = createTransla
|
|
|
161
164
|
role: agentConfig.role,
|
|
162
165
|
type: agentConfig.type
|
|
163
166
|
})));
|
|
164
|
-
const agents = agentEntries.map(([name, agentConfig]) => createAgent(name, agentConfig));
|
|
167
|
+
const agents = agentEntries.map(([name, agentConfig]) => createAgent(name, agentConfig, { ollamaUrl: options.ollamaUrl }));
|
|
165
168
|
const transcript = [];
|
|
166
169
|
for (let index = 0; index < agents.length; index += 1) {
|
|
167
170
|
const current = agents[index];
|
|
@@ -210,7 +213,7 @@ export async function runAsk(config, options, renderer, messages = createTransla
|
|
|
210
213
|
agent: current.name,
|
|
211
214
|
role: current.role,
|
|
212
215
|
turn: response
|
|
213
|
-
});
|
|
216
|
+
}, messages);
|
|
214
217
|
renderer?.error(failure);
|
|
215
218
|
return {
|
|
216
219
|
options,
|
|
@@ -243,6 +246,7 @@ export async function runAsk(config, options, renderer, messages = createTransla
|
|
|
243
246
|
const cancellation = cancellationFailureIfAborted(options, messages, {
|
|
244
247
|
phase: "summary",
|
|
245
248
|
agent: summaryAgentName,
|
|
249
|
+
role: summaryRole(),
|
|
246
250
|
turn: transcript.length + 1
|
|
247
251
|
});
|
|
248
252
|
if (cancellation) {
|
|
@@ -259,8 +263,9 @@ export async function runAsk(config, options, renderer, messages = createTransla
|
|
|
259
263
|
failure = toDebateFailure(error, {
|
|
260
264
|
phase: "summary",
|
|
261
265
|
agent: resolveSummaryAgentName(options),
|
|
266
|
+
role: summaryRole(),
|
|
262
267
|
turn: transcript.length + 1
|
|
263
|
-
});
|
|
268
|
+
}, messages);
|
|
264
269
|
renderer?.error(failure);
|
|
265
270
|
}
|
|
266
271
|
}
|
|
@@ -331,16 +336,17 @@ async function generateSummary(config, options, transcript, renderer, messages =
|
|
|
331
336
|
if (!summaryConfig) {
|
|
332
337
|
throw new Error(messages.orchestrator.unknownSummaryAgent(summaryAgentName));
|
|
333
338
|
}
|
|
334
|
-
const summaryAgent = createAgent(summaryAgentName, summaryConfig);
|
|
335
|
-
|
|
336
|
-
renderer?.
|
|
339
|
+
const summaryAgent = createAgent(summaryAgentName, summaryConfig, { ollamaUrl: options.ollamaUrl });
|
|
340
|
+
const role = summaryRole();
|
|
341
|
+
renderer?.summaryStart(summaryAgent.name, role);
|
|
342
|
+
renderer?.thinkingStart(summaryAgent.name, role);
|
|
337
343
|
const response = await summaryAgent.generate({
|
|
338
344
|
topic: options.topic,
|
|
339
345
|
turn: transcript.length + 1,
|
|
340
346
|
totalTurns: options.mode === "ask" ? transcript.length : options.turns,
|
|
341
347
|
selfName: summaryAgent.name,
|
|
342
348
|
peerName: options.mode === "ask" ? "ask-responses" : "transcript",
|
|
343
|
-
selfRole:
|
|
349
|
+
selfRole: role,
|
|
344
350
|
mode: "summary",
|
|
345
351
|
language: options.language,
|
|
346
352
|
session: options.session,
|
|
@@ -350,13 +356,16 @@ async function generateSummary(config, options, transcript, renderer, messages =
|
|
|
350
356
|
}).finally(() => renderer?.thinkingEnd());
|
|
351
357
|
const summary = {
|
|
352
358
|
agent: summaryAgent.name,
|
|
353
|
-
role
|
|
359
|
+
role,
|
|
354
360
|
content: response.content,
|
|
355
361
|
createdAt: new Date().toISOString()
|
|
356
362
|
};
|
|
357
363
|
renderer?.message(summary.content);
|
|
358
364
|
return summary;
|
|
359
365
|
}
|
|
366
|
+
function summaryRole() {
|
|
367
|
+
return "summarizer";
|
|
368
|
+
}
|
|
360
369
|
function cancellationFailureIfAborted(options, messages, context) {
|
|
361
370
|
if (!options.signal?.aborted) {
|
|
362
371
|
return undefined;
|
|
@@ -385,7 +394,7 @@ function resolveSummaryAgentName(options) {
|
|
|
385
394
|
}
|
|
386
395
|
return options.agentB;
|
|
387
396
|
}
|
|
388
|
-
function toDebateFailure(error, context) {
|
|
397
|
+
function toDebateFailure(error, context, messages) {
|
|
389
398
|
if (error instanceof AdapterError) {
|
|
390
399
|
return {
|
|
391
400
|
phase: context.phase,
|
|
@@ -397,6 +406,18 @@ function toDebateFailure(error, context) {
|
|
|
397
406
|
details: error.details
|
|
398
407
|
};
|
|
399
408
|
}
|
|
409
|
+
if (error instanceof OllamaUrlError) {
|
|
410
|
+
const message = error.kind === "empty"
|
|
411
|
+
? messages.common.ollamaUrlEmpty
|
|
412
|
+
: error.kind === "protocol"
|
|
413
|
+
? messages.common.ollamaUrlProtocol(error.protocol ?? "")
|
|
414
|
+
: messages.common.ollamaUrlInvalid(error.value);
|
|
415
|
+
return {
|
|
416
|
+
...context,
|
|
417
|
+
kind: "unknown",
|
|
418
|
+
message
|
|
419
|
+
};
|
|
420
|
+
}
|
|
400
421
|
return {
|
|
401
422
|
phase: context.phase,
|
|
402
423
|
agent: context.agent,
|
package/dist/presets.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { detectionForCommand } from "./agentRegistry.js";
|
|
1
|
+
import { detectionForCommand, isRetiredAgentName } from "./agentRegistry.js";
|
|
2
2
|
const presets = {
|
|
3
3
|
"codex-claude": {
|
|
4
4
|
agentA: "codex",
|
|
@@ -56,30 +56,6 @@ const presets = {
|
|
|
56
56
|
agentA: "antigravity",
|
|
57
57
|
agentB: "claude"
|
|
58
58
|
},
|
|
59
|
-
"gemini-opencode": {
|
|
60
|
-
agentA: "gemini",
|
|
61
|
-
agentB: "opencode"
|
|
62
|
-
},
|
|
63
|
-
"opencode-gemini": {
|
|
64
|
-
agentA: "opencode",
|
|
65
|
-
agentB: "gemini"
|
|
66
|
-
},
|
|
67
|
-
"gemini-vibe": {
|
|
68
|
-
agentA: "gemini",
|
|
69
|
-
agentB: "vibe"
|
|
70
|
-
},
|
|
71
|
-
"vibe-gemini": {
|
|
72
|
-
agentA: "vibe",
|
|
73
|
-
agentB: "gemini"
|
|
74
|
-
},
|
|
75
|
-
"gemini-antigravity": {
|
|
76
|
-
agentA: "gemini",
|
|
77
|
-
agentB: "antigravity"
|
|
78
|
-
},
|
|
79
|
-
"antigravity-gemini": {
|
|
80
|
-
agentA: "antigravity",
|
|
81
|
-
agentB: "gemini"
|
|
82
|
-
},
|
|
83
59
|
"opencode-antigravity": {
|
|
84
60
|
agentA: "opencode",
|
|
85
61
|
agentB: "antigravity"
|
|
@@ -136,14 +112,6 @@ const presets = {
|
|
|
136
112
|
agentA: "ollama-local",
|
|
137
113
|
agentB: "claude"
|
|
138
114
|
},
|
|
139
|
-
"gemini-ollama": {
|
|
140
|
-
agentA: "gemini",
|
|
141
|
-
agentB: "ollama-local"
|
|
142
|
-
},
|
|
143
|
-
"ollama-gemini": {
|
|
144
|
-
agentA: "ollama-local",
|
|
145
|
-
agentB: "gemini"
|
|
146
|
-
},
|
|
147
115
|
"antigravity-ollama": {
|
|
148
116
|
agentA: "antigravity",
|
|
149
117
|
agentB: "ollama-local"
|
|
@@ -151,22 +119,6 @@ const presets = {
|
|
|
151
119
|
"ollama-antigravity": {
|
|
152
120
|
agentA: "ollama-local",
|
|
153
121
|
agentB: "antigravity"
|
|
154
|
-
},
|
|
155
|
-
"codex-gemini": {
|
|
156
|
-
agentA: "codex",
|
|
157
|
-
agentB: "gemini"
|
|
158
|
-
},
|
|
159
|
-
"gemini-codex": {
|
|
160
|
-
agentA: "gemini",
|
|
161
|
-
agentB: "codex"
|
|
162
|
-
},
|
|
163
|
-
"claude-gemini": {
|
|
164
|
-
agentA: "claude",
|
|
165
|
-
agentB: "gemini"
|
|
166
|
-
},
|
|
167
|
-
"gemini-claude": {
|
|
168
|
-
agentA: "gemini",
|
|
169
|
-
agentB: "claude"
|
|
170
122
|
}
|
|
171
123
|
};
|
|
172
124
|
/** Retourne la paire d'agents pour `name`. Lève une erreur avec la liste des presets disponibles si inconnu. */
|
|
@@ -209,6 +161,26 @@ export function listPresetsWithAvailability(config, discovery, messages) {
|
|
|
209
161
|
};
|
|
210
162
|
});
|
|
211
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Retourne tous les agents de la config avec la même disponibilité que celle
|
|
166
|
+
* utilisée pour les presets. Les intégrations ne doivent pas réimplémenter la
|
|
167
|
+
* découverte des commandes ou des modèles Ollama.
|
|
168
|
+
*/
|
|
169
|
+
export function listAgentsWithAvailability(config, discovery, messages) {
|
|
170
|
+
return Object.entries(config.agents)
|
|
171
|
+
.filter(([name]) => !isRetiredAgentName(name))
|
|
172
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
173
|
+
.map(([name, agentConfig]) => {
|
|
174
|
+
const check = checkAgentAvailability(name, config, discovery, messages);
|
|
175
|
+
return {
|
|
176
|
+
name,
|
|
177
|
+
type: agentConfig.type,
|
|
178
|
+
role: agentConfig.role,
|
|
179
|
+
available: check.available,
|
|
180
|
+
...(check.available ? {} : { unavailableReason: check.reason })
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
}
|
|
212
184
|
/** Recherche inverse : retourne le nom du preset correspondant à une paire `(agentA, agentB)`, ou `undefined`. */
|
|
213
185
|
export function findPresetNameForPair(agentA, agentB) {
|
|
214
186
|
return Object.entries(presets).find(([, preset]) => preset.agentA === agentA && preset.agentB === agentB)?.[0];
|
|
@@ -219,12 +191,13 @@ function checkAgentAvailability(agentName, config, discovery, messages) {
|
|
|
219
191
|
return unavailable(agentName, messages?.presets.missingAgent(agentName) ?? `agent absent de la config: ${agentName}`);
|
|
220
192
|
}
|
|
221
193
|
if (agent.type === "ollama") {
|
|
222
|
-
|
|
223
|
-
|
|
194
|
+
const ollama = discovery.ollamaAgents?.[agentName] ?? discovery.ollama;
|
|
195
|
+
if (!ollama.available) {
|
|
196
|
+
return unavailable(agentName, ollama.commandAvailable
|
|
224
197
|
? messages?.presets.ollamaUnreachable(agentName) ?? `Ollama non joignable pour ${agentName}`
|
|
225
198
|
: messages?.presets.ollamaNotDetected(agentName) ?? `Ollama non détecté pour ${agentName}`);
|
|
226
199
|
}
|
|
227
|
-
if (!
|
|
200
|
+
if (!ollama.models.includes(agent.model)) {
|
|
228
201
|
return unavailable(agentName, messages?.presets.missingOllamaModel(agentName, agent.model) ?? `modèle Ollama absent pour ${agentName}: ${agent.model}`);
|
|
229
202
|
}
|
|
230
203
|
return available(agentName);
|