palabre 0.6.4 → 0.8.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 +99 -63
- package/dist/adapters/cli-pty.js +14 -0
- package/dist/adapters/cli.js +32 -4
- package/dist/adapters/ollama.js +15 -0
- package/dist/agentRegistry.js +3 -2
- package/dist/args.js +22 -1
- package/dist/config.js +78 -4
- package/dist/configWizard.js +29 -6
- package/dist/discovery.js +3 -1
- package/dist/doctor.js +18 -0
- package/dist/index.js +593 -55
- package/dist/messages/agents.js +4 -2
- package/dist/messages/common.js +4 -0
- package/dist/messages/config.js +28 -8
- package/dist/messages/doctor.js +8 -0
- package/dist/messages/help.js +58 -2
- package/dist/messages/index.js +2 -0
- package/dist/messages/init.js +2 -2
- package/dist/messages/new.js +14 -0
- package/dist/messages/orchestrator.js +2 -0
- package/dist/messages/output.js +10 -0
- package/dist/messages/preview.js +4 -2
- package/dist/messages/prompt.js +46 -2
- package/dist/messages/renderers.js +2 -2
- package/dist/messages/tui.js +192 -0
- package/dist/messages/update.js +16 -2
- package/dist/new.js +158 -4
- package/dist/orchestrator.js +199 -6
- package/dist/output.js +31 -8
- package/dist/presets.js +48 -0
- package/dist/prompt.js +61 -10
- package/dist/renderers/console.js +39 -3
- package/dist/renderers/ndjson.js +30 -1
- package/dist/renderers/tui.js +932 -0
- package/dist/update.js +2 -0
- package/dist/version.js +54 -0
- package/package.json +2 -1
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { applyDetectedCommands } from "./agentRegistry.js";
|
|
4
|
+
import { applyDetectedCommands, detectedAgentNames } from "./agentRegistry.js";
|
|
5
5
|
export const DEFAULT_CONFIG_PATH = "palabre.config.json";
|
|
6
6
|
export const LEGACY_CONFIG_PATH = "chicane.config.json";
|
|
7
7
|
export const CONFIG_DIR_NAME = ".palabre";
|
|
@@ -13,9 +13,13 @@ export const exampleConfig = {
|
|
|
13
13
|
language: "fr",
|
|
14
14
|
outputDir: DEFAULT_OUTPUT_DIR,
|
|
15
15
|
defaults: {
|
|
16
|
+
interface: "tui",
|
|
17
|
+
mode: "debate",
|
|
16
18
|
agentA: "codex",
|
|
17
19
|
agentB: "claude",
|
|
20
|
+
askAgents: ["codex", "claude"],
|
|
18
21
|
summaryAgent: "claude",
|
|
22
|
+
askSummaryAgent: "claude",
|
|
19
23
|
turns: 4
|
|
20
24
|
},
|
|
21
25
|
agents: {
|
|
@@ -92,6 +96,23 @@ export const exampleConfig = {
|
|
|
92
96
|
role: "reviewer",
|
|
93
97
|
tier: "primary"
|
|
94
98
|
},
|
|
99
|
+
vibe: {
|
|
100
|
+
type: "cli",
|
|
101
|
+
command: "vibe",
|
|
102
|
+
args: [
|
|
103
|
+
"--output",
|
|
104
|
+
"text",
|
|
105
|
+
"--agent",
|
|
106
|
+
"plan",
|
|
107
|
+
"--trust",
|
|
108
|
+
"--prompt"
|
|
109
|
+
],
|
|
110
|
+
promptMode: "argument",
|
|
111
|
+
modelArg: "--model",
|
|
112
|
+
shell: process.platform === "win32",
|
|
113
|
+
role: "reviewer",
|
|
114
|
+
tier: "primary"
|
|
115
|
+
},
|
|
95
116
|
"ollama-local": {
|
|
96
117
|
type: "ollama",
|
|
97
118
|
baseUrl: "http://localhost:11434",
|
|
@@ -189,13 +210,62 @@ export function createConfigFromDiscovery(discovery) {
|
|
|
189
210
|
config.defaults = pair
|
|
190
211
|
? {
|
|
191
212
|
...config.defaults,
|
|
213
|
+
interface: config.defaults?.interface ?? "tui",
|
|
214
|
+
mode: config.defaults?.mode ?? "debate",
|
|
192
215
|
agentA: pair[0],
|
|
193
216
|
agentB: pair[1],
|
|
194
|
-
|
|
217
|
+
askAgents: pair,
|
|
218
|
+
summaryAgent: chooseDefaultSummaryAgent(pair),
|
|
219
|
+
askSummaryAgent: chooseDefaultSummaryAgent(pair)
|
|
195
220
|
}
|
|
196
|
-
: {
|
|
221
|
+
: {
|
|
222
|
+
interface: config.defaults?.interface ?? "tui",
|
|
223
|
+
mode: config.defaults?.mode ?? "debate",
|
|
224
|
+
turns: config.defaults?.turns,
|
|
225
|
+
askAgents: detectedAgentNames(discovery).slice(0, 2)
|
|
226
|
+
};
|
|
197
227
|
return config;
|
|
198
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Ajoute dans `config.agents` les agents détectés localement mais absents de la config.
|
|
231
|
+
* Mute `config` directement ; l'appelant est responsable de persister la config.
|
|
232
|
+
*/
|
|
233
|
+
export function syncDetectedAgents(config, discovery) {
|
|
234
|
+
const discoveredConfig = createConfigFromDiscovery(discovery);
|
|
235
|
+
const missingAgents = detectedAgentNames(discovery).filter((agentName) => !config.agents[agentName]);
|
|
236
|
+
applyDetectedCommands(config, discovery);
|
|
237
|
+
for (const agentName of missingAgents) {
|
|
238
|
+
config.agents[agentName] = discoveredConfig.agents[agentName];
|
|
239
|
+
}
|
|
240
|
+
return missingAgents;
|
|
241
|
+
}
|
|
242
|
+
export function syncOllamaModel(config, discovery) {
|
|
243
|
+
const agent = config.agents["ollama-local"];
|
|
244
|
+
if (agent?.type !== "ollama" || discovery.ollama.models.length === 0) {
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
if (discovery.ollama.models.includes(agent.model)) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
const previousModel = agent.model;
|
|
251
|
+
agent.model = chooseDefaultOllamaModel(discovery);
|
|
252
|
+
return {
|
|
253
|
+
previousModel,
|
|
254
|
+
nextModel: agent.model
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
export function setOllamaModel(config, model) {
|
|
258
|
+
const agent = config.agents["ollama-local"];
|
|
259
|
+
if (agent?.type !== "ollama") {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
const previousModel = agent.model;
|
|
263
|
+
agent.model = model;
|
|
264
|
+
return {
|
|
265
|
+
previousModel,
|
|
266
|
+
nextModel: agent.model
|
|
267
|
+
};
|
|
268
|
+
}
|
|
199
269
|
/** Écrit `config` sérialisé en JSON dans `configPath`. Crée le répertoire parent si nécessaire. */
|
|
200
270
|
export async function writeExampleConfig(configPath = DEFAULT_CONFIG_PATH, config = exampleConfig) {
|
|
201
271
|
const resolved = path.resolve(configPath);
|
|
@@ -209,7 +279,7 @@ function chooseDefaultOllamaModel(discovery) {
|
|
|
209
279
|
return discovery.ollama.models[0] ?? DEFAULT_OLLAMA_MODEL;
|
|
210
280
|
}
|
|
211
281
|
function chooseDefaultSummaryAgent(pair) {
|
|
212
|
-
for (const preferred of ["claude", "codex", "antigravity", "gemini"]) {
|
|
282
|
+
for (const preferred of ["claude", "codex", "antigravity", "vibe", "gemini"]) {
|
|
213
283
|
if (pair.includes(preferred)) {
|
|
214
284
|
return preferred;
|
|
215
285
|
}
|
|
@@ -229,6 +299,9 @@ function chooseDefaultPair(discovery) {
|
|
|
229
299
|
if (discovery.opencode.available && discovery.ollama.available) {
|
|
230
300
|
return ["opencode", "ollama-local"];
|
|
231
301
|
}
|
|
302
|
+
if (discovery.vibe.available && discovery.ollama.available) {
|
|
303
|
+
return ["vibe", "ollama-local"];
|
|
304
|
+
}
|
|
232
305
|
if (discovery.antigravity.available && discovery.ollama.available) {
|
|
233
306
|
return ["antigravity", "ollama-local"];
|
|
234
307
|
}
|
|
@@ -240,6 +313,7 @@ function chooseDefaultPair(discovery) {
|
|
|
240
313
|
discovery.claude.available ? "claude" : undefined,
|
|
241
314
|
discovery.antigravity.available ? "antigravity" : undefined,
|
|
242
315
|
discovery.opencode.available ? "opencode" : undefined,
|
|
316
|
+
discovery.vibe.available ? "vibe" : undefined,
|
|
243
317
|
discovery.gemini.available ? "gemini" : undefined
|
|
244
318
|
].filter((agent) => Boolean(agent));
|
|
245
319
|
if (cliAgents.length >= 2) {
|
package/dist/configWizard.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { stdin as input, stdout as output } from "node:process";
|
|
3
|
-
import { writeExampleConfig } from "./config.js";
|
|
3
|
+
import { syncDetectedAgents, writeExampleConfig } from "./config.js";
|
|
4
|
+
import { discoverLocalTools } from "./discovery.js";
|
|
4
5
|
import { DEFAULT_TURNS, MAX_TURNS, turnsOrDefault, validateTurns } from "./limits.js";
|
|
5
6
|
/**
|
|
6
7
|
* Lance le wizard interactif de configuration des defaults.
|
|
@@ -26,9 +27,10 @@ export async function runConfigWizard(configPath, config, messages) {
|
|
|
26
27
|
console.log(messages.config.wizardActionQuestion);
|
|
27
28
|
console.log(` 1) ${messages.config.wizardActionSetDefaults}`);
|
|
28
29
|
console.log(` 2) ${messages.config.wizardActionClearDefaults}`);
|
|
29
|
-
console.log(` 3) ${messages.config.
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
console.log(` 3) ${messages.config.wizardActionSyncAgents}`);
|
|
31
|
+
console.log(` 4) ${messages.config.wizardActionExit}`);
|
|
32
|
+
const action = await askChoice(rl, messages.config.wizardChoicePrompt, "1", ["1", "2", "3", "4"], messages);
|
|
33
|
+
if (!action || action === "4") {
|
|
32
34
|
console.log(messages.config.wizardUnchanged);
|
|
33
35
|
return;
|
|
34
36
|
}
|
|
@@ -38,6 +40,17 @@ export async function runConfigWizard(configPath, config, messages) {
|
|
|
38
40
|
console.log(messages.config.wizardCleared(configPath));
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
43
|
+
if (action === "3") {
|
|
44
|
+
const discovery = await discoverLocalTools();
|
|
45
|
+
const addedAgents = syncDetectedAgents(config, discovery);
|
|
46
|
+
if (addedAgents.length === 0) {
|
|
47
|
+
console.log(messages.config.syncNoMissing(configPath));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
await writeExampleConfig(configPath, config);
|
|
51
|
+
console.log(messages.config.syncAdded(configPath, addedAgents.join(", ")));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
41
54
|
const agentA = await askAgent(rl, choices, messages.config.wizardAgentADescription, config.defaults?.agentA, messages);
|
|
42
55
|
if (!agentA)
|
|
43
56
|
return;
|
|
@@ -51,11 +64,17 @@ export async function runConfigWizard(configPath, config, messages) {
|
|
|
51
64
|
if (summaryAgent === undefined)
|
|
52
65
|
return;
|
|
53
66
|
config.defaults = {
|
|
67
|
+
...(config.defaults ?? {}),
|
|
54
68
|
agentA,
|
|
55
69
|
agentB,
|
|
56
|
-
...(summaryAgent ? { summaryAgent } : {}),
|
|
57
70
|
turns
|
|
58
71
|
};
|
|
72
|
+
if (summaryAgent) {
|
|
73
|
+
config.defaults.summaryAgent = summaryAgent;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
delete config.defaults.summaryAgent;
|
|
77
|
+
}
|
|
59
78
|
await writeExampleConfig(configPath, config);
|
|
60
79
|
console.log(messages.config.wizardDefaultsSet(configPath, formatDefaults(config.defaults, messages)));
|
|
61
80
|
}
|
|
@@ -192,8 +211,12 @@ function formatDefaults(defaults, messages) {
|
|
|
192
211
|
return messages.config.wizardDefaults({
|
|
193
212
|
agentA: defaults.agentA,
|
|
194
213
|
agentB: defaults.agentB,
|
|
214
|
+
mode: defaults.mode,
|
|
215
|
+
interfaceName: defaults.interface,
|
|
216
|
+
askAgents: defaults.askAgents,
|
|
195
217
|
turns: turnsOrDefault(defaults.turns ?? DEFAULT_TURNS),
|
|
196
|
-
summaryAgent: defaults.summaryAgent
|
|
218
|
+
summaryAgent: defaults.summaryAgent,
|
|
219
|
+
askSummaryAgent: defaults.askSummaryAgent
|
|
197
220
|
});
|
|
198
221
|
}
|
|
199
222
|
function isQuit(value) {
|
package/dist/discovery.js
CHANGED
|
@@ -7,12 +7,13 @@ import { executableExtensions } from "./exec.js";
|
|
|
7
7
|
* Antigravity est exposé selon les installations sous `agy` ou `antigravity`.
|
|
8
8
|
*/
|
|
9
9
|
export async function discoverLocalTools() {
|
|
10
|
-
const [codex, claude, gemini, antigravity, opencode, ollamaCommand] = await Promise.all([
|
|
10
|
+
const [codex, claude, gemini, antigravity, opencode, vibe, ollamaCommand] = await Promise.all([
|
|
11
11
|
detectCommand("codex"),
|
|
12
12
|
detectFirstCommand(process.platform === "win32" ? ["claude.exe", "claude"] : ["claude"]),
|
|
13
13
|
detectCommand("gemini"),
|
|
14
14
|
detectFirstCommand(["agy", "antigravity"]),
|
|
15
15
|
detectCommand("opencode"),
|
|
16
|
+
detectCommand("vibe"),
|
|
16
17
|
detectCommand("ollama")
|
|
17
18
|
]);
|
|
18
19
|
const ollamaServer = await detectOllamaServer();
|
|
@@ -22,6 +23,7 @@ export async function discoverLocalTools() {
|
|
|
22
23
|
gemini,
|
|
23
24
|
antigravity,
|
|
24
25
|
opencode,
|
|
26
|
+
vibe,
|
|
25
27
|
ollama: {
|
|
26
28
|
...ollamaServer,
|
|
27
29
|
commandAvailable: ollamaCommand.available
|
package/dist/doctor.js
CHANGED
|
@@ -5,6 +5,7 @@ import { detectedAgentNames, detectionForCommand } from "./agentRegistry.js";
|
|
|
5
5
|
import { discoverLocalTools } from "./discovery.js";
|
|
6
6
|
import { createTranslator, resolveLanguage } from "./i18n.js";
|
|
7
7
|
import { DEFAULT_TURNS, MAX_TURNS } from "./limits.js";
|
|
8
|
+
import { compareSemver, getLatestPackageVersion, getPackageVersion } from "./version.js";
|
|
8
9
|
/**
|
|
9
10
|
* Exécute le diagnostic complet : config, outils locaux et agents.
|
|
10
11
|
* Retourne toujours un résultat (pas de throw) ; les erreurs de config sont reportées comme lignes `error`.
|
|
@@ -20,6 +21,7 @@ export async function runDoctor(explicitConfigPath, plain = false, explicitLangu
|
|
|
20
21
|
});
|
|
21
22
|
const t = createTranslator(language);
|
|
22
23
|
lines.push(info(t.doctor.title, "title"));
|
|
24
|
+
await inspectCliVersion(lines, t);
|
|
23
25
|
lines.push(info(t.doctor.currentDirectory(process.cwd()), "cwd"));
|
|
24
26
|
lines.push(hasConfig
|
|
25
27
|
? ok(t.doctor.configFound(configPath))
|
|
@@ -44,6 +46,7 @@ export async function runDoctor(explicitConfigPath, plain = false, explicitLangu
|
|
|
44
46
|
lines.push(formatCommand("Gemini CLI", discovery.gemini.available, discovery.gemini.command, discovery.gemini.path, t));
|
|
45
47
|
lines.push(formatCommand("Antigravity CLI", discovery.antigravity.available, discovery.antigravity.command, discovery.antigravity.path, t));
|
|
46
48
|
lines.push(formatCommand("OpenCode CLI", discovery.opencode.available, discovery.opencode.command, discovery.opencode.path, t));
|
|
49
|
+
lines.push(formatCommand("Mistral Vibe CLI", discovery.vibe.available, discovery.vibe.command, discovery.vibe.path, t));
|
|
47
50
|
lines.push(discovery.ollama.available
|
|
48
51
|
? ok(t.doctor.ollamaReachable(discovery.ollama.baseUrl, discovery.ollama.models.length))
|
|
49
52
|
: warn(discovery.ollama.commandAvailable
|
|
@@ -53,6 +56,18 @@ export async function runDoctor(explicitConfigPath, plain = false, explicitLangu
|
|
|
53
56
|
inspectAgents(config, discovery, lines, t);
|
|
54
57
|
return render(lines, plain, t);
|
|
55
58
|
}
|
|
59
|
+
async function inspectCliVersion(lines, t) {
|
|
60
|
+
const currentVersion = await getPackageVersion();
|
|
61
|
+
lines.push(info(t.doctor.cliVersion(currentVersion)));
|
|
62
|
+
const latestVersion = await getLatestPackageVersion();
|
|
63
|
+
if (!latestVersion) {
|
|
64
|
+
lines.push(info(t.doctor.updateUnknown));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
lines.push(compareSemver(currentVersion, latestVersion) < 0
|
|
68
|
+
? warn(t.doctor.updateAvailable(currentVersion, latestVersion))
|
|
69
|
+
: ok(t.doctor.updateCurrent(latestVersion)));
|
|
70
|
+
}
|
|
56
71
|
async function loadConfigSafely(configPath) {
|
|
57
72
|
try {
|
|
58
73
|
return await loadConfig(configPath);
|
|
@@ -91,6 +106,9 @@ async function inspectConfig(config, lines, t) {
|
|
|
91
106
|
else {
|
|
92
107
|
lines.push(warn(t.doctor.summaryAgentMissing));
|
|
93
108
|
}
|
|
109
|
+
if (config.defaults?.askSummaryAgent) {
|
|
110
|
+
inspectDefaultAgent("defaults.askSummaryAgent", config.defaults.askSummaryAgent, config, lines, t);
|
|
111
|
+
}
|
|
94
112
|
await inspectOutputDir(config.outputDir, lines, t);
|
|
95
113
|
}
|
|
96
114
|
function inspectDefaultAgent(label, agentName, config, lines, t) {
|