palabre 0.7.0 → 0.8.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.
@@ -64,11 +64,17 @@ export async function runConfigWizard(configPath, config, messages) {
64
64
  if (summaryAgent === undefined)
65
65
  return;
66
66
  config.defaults = {
67
+ ...(config.defaults ?? {}),
67
68
  agentA,
68
69
  agentB,
69
- ...(summaryAgent ? { summaryAgent } : {}),
70
70
  turns
71
71
  };
72
+ if (summaryAgent) {
73
+ config.defaults.summaryAgent = summaryAgent;
74
+ }
75
+ else {
76
+ delete config.defaults.summaryAgent;
77
+ }
72
78
  await writeExampleConfig(configPath, config);
73
79
  console.log(messages.config.wizardDefaultsSet(configPath, formatDefaults(config.defaults, messages)));
74
80
  }
@@ -205,8 +211,12 @@ function formatDefaults(defaults, messages) {
205
211
  return messages.config.wizardDefaults({
206
212
  agentA: defaults.agentA,
207
213
  agentB: defaults.agentB,
214
+ mode: defaults.mode,
215
+ interfaceName: defaults.interface,
216
+ askAgents: defaults.askAgents,
208
217
  turns: turnsOrDefault(defaults.turns ?? DEFAULT_TURNS),
209
- summaryAgent: defaults.summaryAgent
218
+ summaryAgent: defaults.summaryAgent,
219
+ askSummaryAgent: defaults.askSummaryAgent
210
220
  });
211
221
  }
212
222
  function isQuit(value) {
package/dist/context.js CHANGED
@@ -80,7 +80,11 @@ async function addContextPaths(paths, cwd, state) {
80
80
  const uniquePaths = [...new Set(paths.map((item) => item.trim()).filter(Boolean))];
81
81
  for (const inputPath of uniquePaths) {
82
82
  const absolutePath = path.resolve(cwd, inputPath);
83
- const fileStat = await stat(absolutePath);
83
+ const fileStat = await stat(absolutePath).catch(() => undefined);
84
+ if (!fileStat) {
85
+ state.warnings.push(state.messages.context.ignoredNotFileOrDirectory(inputPath));
86
+ continue;
87
+ }
84
88
  if (fileStat.isFile()) {
85
89
  await addContextFile(absolutePath, cwd, state);
86
90
  continue;
package/dist/discovery.js CHANGED
@@ -7,21 +7,21 @@ 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, antigravity, opencode, vibe, ollamaCommand] = await Promise.all([
11
11
  detectCommand("codex"),
12
12
  detectFirstCommand(process.platform === "win32" ? ["claude.exe", "claude"] : ["claude"]),
13
- detectCommand("gemini"),
14
13
  detectFirstCommand(["agy", "antigravity"]),
15
14
  detectCommand("opencode"),
15
+ detectCommand("vibe"),
16
16
  detectCommand("ollama")
17
17
  ]);
18
18
  const ollamaServer = await detectOllamaServer();
19
19
  return {
20
20
  codex,
21
21
  claude,
22
- gemini,
23
22
  antigravity,
24
23
  opencode,
24
+ vibe,
25
25
  ollama: {
26
26
  ...ollamaServer,
27
27
  commandAvailable: ollamaCommand.available
package/dist/doctor.js CHANGED
@@ -43,9 +43,9 @@ export async function runDoctor(explicitConfigPath, plain = false, explicitLangu
43
43
  lines.push(info(t.doctor.localTools, "tools"));
44
44
  lines.push(formatCommand("Codex CLI", discovery.codex.available, discovery.codex.command, discovery.codex.path, t));
45
45
  lines.push(formatCommand("Claude CLI", discovery.claude.available, discovery.claude.command, discovery.claude.path, t));
46
- lines.push(formatCommand("Gemini CLI", discovery.gemini.available, discovery.gemini.command, discovery.gemini.path, t));
47
46
  lines.push(formatCommand("Antigravity CLI", discovery.antigravity.available, discovery.antigravity.command, discovery.antigravity.path, t));
48
47
  lines.push(formatCommand("OpenCode CLI", discovery.opencode.available, discovery.opencode.command, discovery.opencode.path, t));
48
+ lines.push(formatCommand("Mistral Vibe CLI", discovery.vibe.available, discovery.vibe.command, discovery.vibe.path, t));
49
49
  lines.push(discovery.ollama.available
50
50
  ? ok(t.doctor.ollamaReachable(discovery.ollama.baseUrl, discovery.ollama.models.length))
51
51
  : warn(discovery.ollama.commandAvailable
@@ -105,6 +105,9 @@ async function inspectConfig(config, lines, t) {
105
105
  else {
106
106
  lines.push(warn(t.doctor.summaryAgentMissing));
107
107
  }
108
+ if (config.defaults?.askSummaryAgent) {
109
+ inspectDefaultAgent("defaults.askSummaryAgent", config.defaults.askSummaryAgent, config, lines, t);
110
+ }
108
111
  await inspectOutputDir(config.outputDir, lines, t);
109
112
  }
110
113
  function inspectDefaultAgent(label, agentName, config, lines, t) {
@@ -0,0 +1,85 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const maxHeaderBytes = 12_000;
4
+ export async function listHistoryEntries(outputDir, limit = 10) {
5
+ const resolved = path.resolve(outputDir);
6
+ let entries;
7
+ try {
8
+ entries = await readdir(resolved, { withFileTypes: true });
9
+ }
10
+ catch {
11
+ return [];
12
+ }
13
+ const markdownFiles = entries
14
+ .filter((entry) => entry.isFile() && /\.(debate|ask)\.md$/i.test(entry.name))
15
+ .map((entry) => path.join(resolved, entry.name));
16
+ const history = await Promise.all(markdownFiles.map(readHistoryFile));
17
+ return history
18
+ .filter((entry) => Boolean(entry))
19
+ .sort((left, right) => right.mtimeMs - left.mtimeMs)
20
+ .slice(0, limit);
21
+ }
22
+ async function readHistoryFile(filePath) {
23
+ try {
24
+ const [metadata, raw] = await Promise.all([
25
+ stat(filePath),
26
+ readFile(filePath, "utf8")
27
+ ]);
28
+ const header = raw.slice(0, maxHeaderBytes);
29
+ const table = parseMetadataTable(header);
30
+ const fileName = path.basename(filePath);
31
+ const mode = fileName.endsWith(".ask.md") ? "ask" : "debate";
32
+ return {
33
+ fileName,
34
+ path: filePath,
35
+ mode,
36
+ topic: table.Sujet ?? table.Subject ?? topicFromFileName(fileName),
37
+ agents: table.Agents ?? "",
38
+ date: table["Date locale"] ?? table["Local date"] ?? table["Session demarree a"] ?? table["Session started at"] ?? "",
39
+ count: countFromTable(mode, table),
40
+ mtimeMs: metadata.mtimeMs
41
+ };
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ }
47
+ function countFromTable(mode, table) {
48
+ if (mode === "ask") {
49
+ const received = table["Reponses recues"] ?? table["Received responses"];
50
+ const requested = table["Reponses attendues"] ?? table["Expected responses"];
51
+ return received && requested ? `${received}/${requested}` : received ?? requested ?? "";
52
+ }
53
+ const played = table["Tours joues"] ?? table["Played turns"];
54
+ const requested = table["Tours demandes"] ?? table["Requested turns"];
55
+ return played && requested ? `${played}/${requested}` : played ?? requested ?? "";
56
+ }
57
+ function parseMetadataTable(markdown) {
58
+ const fields = {};
59
+ const lines = markdown.split(/\r?\n/);
60
+ for (const line of lines) {
61
+ const match = line.match(/^\|\s*([^|]+?)\s*\|\s*([^|]*?)\s*\|$/);
62
+ if (!match)
63
+ continue;
64
+ const key = stripMarkdown(match[1] ?? "");
65
+ const value = stripMarkdown(match[2] ?? "");
66
+ if (!key || key === "Champ" || key === "Field" || /^-+$/.test(key))
67
+ continue;
68
+ fields[key] = value;
69
+ }
70
+ return fields;
71
+ }
72
+ function stripMarkdown(value) {
73
+ return value
74
+ .replace(/\*\*/g, "")
75
+ .replace(/`/g, "")
76
+ .trim();
77
+ }
78
+ function topicFromFileName(fileName) {
79
+ return fileName
80
+ .replace(/^palabre-/, "")
81
+ .replace(/\.(debate|ask)\.md$/i, "")
82
+ .replace(/-\d{4}-\d{2}-\d{2}t.*$/i, "")
83
+ .replace(/-/g, " ")
84
+ .trim() || fileName;
85
+ }