palabre 0.8.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.
- package/README.md +13 -15
- package/dist/adapters/cli-pty.js +1 -1
- package/dist/adapters/cli.js +33 -3
- package/dist/adapters/ollama.js +1 -1
- package/dist/agentRegistry.js +1 -2
- package/dist/args.js +4 -2
- package/dist/config.js +25 -25
- package/dist/context.js +5 -1
- package/dist/discovery.js +1 -3
- package/dist/doctor.js +0 -1
- package/dist/history.js +85 -0
- package/dist/index.js +346 -179
- package/dist/messages/config.js +2 -0
- package/dist/messages/help.js +58 -8
- package/dist/messages/init.js +2 -2
- package/dist/messages/tui.js +64 -28
- package/dist/orchestrator.js +12 -4
- package/dist/presets.js +0 -48
- package/dist/renderers/tui.js +196 -73
- package/dist/tuiState.js +31 -0
- package/package.json +1 -1
- package/palabre.config.example.json +0 -17
package/dist/renderers/tui.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { stdin as input, stdout as output } from "node:process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
3
5
|
const supportsColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
4
6
|
const supportsInteractiveOutput = Boolean(process.stdout.isTTY);
|
|
5
7
|
/** Cree le premier renderer TUI leger, sans dependance UI externe. */
|
|
@@ -56,34 +58,50 @@ export function renderTuiHome(config, _configPath, messages, state = {}) {
|
|
|
56
58
|
}
|
|
57
59
|
/** Affiche l'aide interne du composer TUI. */
|
|
58
60
|
export function renderTuiHelp(messages) {
|
|
61
|
+
if (supportsInteractiveOutput) {
|
|
62
|
+
clearScreen();
|
|
63
|
+
}
|
|
59
64
|
const viewport = viewportWidth();
|
|
60
65
|
const width = surfaceWidth();
|
|
61
66
|
process.stdout.write([
|
|
67
|
+
"",
|
|
68
|
+
...centerLogo(viewport, messages),
|
|
62
69
|
"",
|
|
63
70
|
...centerBlock(card([
|
|
64
71
|
bold(messages.tui.helpTitle),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
"",
|
|
73
|
+
row("/ask", messages.tui.helpAsk),
|
|
74
|
+
row("/debat", messages.tui.helpDebate),
|
|
75
|
+
"",
|
|
76
|
+
row("/agents", messages.tui.helpAgents),
|
|
77
|
+
row("/roles", messages.tui.helpRoles),
|
|
78
|
+
row("/config", messages.tui.helpConfig),
|
|
79
|
+
"",
|
|
80
|
+
row("/new", messages.tui.helpNew),
|
|
81
|
+
row("/retry", messages.tui.helpRetry),
|
|
82
|
+
row("/history", messages.tui.helpHistory),
|
|
83
|
+
row("/home", messages.tui.backCommand),
|
|
84
|
+
row("/help", messages.tui.helpHelp),
|
|
85
|
+
row("/quit", messages.tui.helpQuit),
|
|
73
86
|
"",
|
|
74
87
|
dim(messages.tui.helpFallback)
|
|
75
|
-
],
|
|
88
|
+
], width), viewport),
|
|
76
89
|
""
|
|
77
90
|
].join("\n"));
|
|
78
91
|
}
|
|
79
92
|
/** Affiche l'aide rapide des agents configures. */
|
|
80
93
|
export function renderTuiAgentsHelp(config, mode, messages) {
|
|
94
|
+
if (supportsInteractiveOutput) {
|
|
95
|
+
clearScreen();
|
|
96
|
+
}
|
|
81
97
|
const viewport = viewportWidth();
|
|
82
98
|
const width = surfaceWidth();
|
|
83
99
|
const activeAgents = activeAgentNamesForMode(config, mode);
|
|
84
100
|
const separator = mode === "ask" ? ", " : " <-> ";
|
|
85
101
|
const exampleAgents = exampleAgentsForMode(config, mode);
|
|
86
102
|
process.stdout.write([
|
|
103
|
+
"",
|
|
104
|
+
...centerLogo(viewport, messages),
|
|
87
105
|
"",
|
|
88
106
|
...centerBlock(card([
|
|
89
107
|
bold(messages.tui.agentsTitle),
|
|
@@ -96,12 +114,15 @@ export function renderTuiAgentsHelp(config, mode, messages) {
|
|
|
96
114
|
...agentInventoryRows(config, messages),
|
|
97
115
|
"",
|
|
98
116
|
dim(`${messages.tui.example}: ${messages.tui.modeLabel(mode)} > ${messages.tui.agentsPrompt} > ${exampleAgents.join(" ")}`)
|
|
99
|
-
],
|
|
117
|
+
], width), viewport),
|
|
100
118
|
""
|
|
101
119
|
].join("\n"));
|
|
102
120
|
}
|
|
103
121
|
/** Affiche l'aide rapide des roles disponibles. */
|
|
104
122
|
export function renderTuiRolesHelp(mode, messages, config) {
|
|
123
|
+
if (supportsInteractiveOutput) {
|
|
124
|
+
clearScreen();
|
|
125
|
+
}
|
|
105
126
|
const viewport = viewportWidth();
|
|
106
127
|
const width = surfaceWidth();
|
|
107
128
|
const currentRoles = config ? roleLineForMode(config, mode, messages) : undefined;
|
|
@@ -109,6 +130,8 @@ export function renderTuiRolesHelp(mode, messages, config) {
|
|
|
109
130
|
const expectedCount = activeAgents.length || (mode === "ask" ? 3 : 2);
|
|
110
131
|
const exampleRoles = exampleRolesForMode(mode, expectedCount);
|
|
111
132
|
process.stdout.write([
|
|
133
|
+
"",
|
|
134
|
+
...centerLogo(viewport, messages),
|
|
112
135
|
"",
|
|
113
136
|
...centerBlock(card([
|
|
114
137
|
bold(messages.tui.rolesTitle),
|
|
@@ -129,6 +152,42 @@ export function renderTuiRolesHelp(mode, messages, config) {
|
|
|
129
152
|
""
|
|
130
153
|
].join("\n"));
|
|
131
154
|
}
|
|
155
|
+
/** Affiche les derniers exports Palabre disponibles. */
|
|
156
|
+
export function renderTuiHistory(entries, messages) {
|
|
157
|
+
if (supportsInteractiveOutput) {
|
|
158
|
+
clearScreen();
|
|
159
|
+
}
|
|
160
|
+
const viewport = viewportWidth();
|
|
161
|
+
const width = surfaceWidth();
|
|
162
|
+
const rows = entries.length === 0
|
|
163
|
+
? [dim(messages.tui.historyEmpty)]
|
|
164
|
+
: entries.flatMap((entry) => {
|
|
165
|
+
const folderPath = path.dirname(entry.path);
|
|
166
|
+
const folderLabel = folderPath === "." ? dirnamePortable(entry.path) : folderPath;
|
|
167
|
+
return [
|
|
168
|
+
row(messages.tui.historyMode(entry.mode), entry.topic),
|
|
169
|
+
row(messages.tui.activeAgents, entry.agents || messages.tui.noValue),
|
|
170
|
+
...(entry.count ? [row(messages.tui.historyCount(entry.mode), entry.count)] : []),
|
|
171
|
+
row(messages.tui.historyFile, terminalLink(entry.path, compactFileName(entry.fileName, width - 24))),
|
|
172
|
+
row(messages.tui.folder, terminalLink(folderPath, compactPath(folderLabel, width - 24))),
|
|
173
|
+
...(entry.date ? [row("Date", entry.date)] : []),
|
|
174
|
+
""
|
|
175
|
+
];
|
|
176
|
+
}).slice(0, -1);
|
|
177
|
+
process.stdout.write([
|
|
178
|
+
"",
|
|
179
|
+
...centerLogo(viewport, messages),
|
|
180
|
+
"",
|
|
181
|
+
...centerBlock(panel([
|
|
182
|
+
bold(messages.tui.historyTitle),
|
|
183
|
+
"",
|
|
184
|
+
...rows,
|
|
185
|
+
"",
|
|
186
|
+
dim(messages.tui.historyOpenHint)
|
|
187
|
+
], width), viewport),
|
|
188
|
+
""
|
|
189
|
+
].join("\n"));
|
|
190
|
+
}
|
|
132
191
|
/** Assistant minimal pour modifier les agents du mode courant. */
|
|
133
192
|
export async function promptTuiAgentsWizard(config, mode, messages) {
|
|
134
193
|
if (!input.isTTY) {
|
|
@@ -145,7 +204,7 @@ export async function promptTuiAgentsWizard(config, mode, messages) {
|
|
|
145
204
|
return { kind: "back" };
|
|
146
205
|
}
|
|
147
206
|
const value = result.value.trim();
|
|
148
|
-
if (!value || value === "/back") {
|
|
207
|
+
if (!value || value === "/home" || value === "/back") {
|
|
149
208
|
return { kind: "back" };
|
|
150
209
|
}
|
|
151
210
|
if (value === "/quit" || value === "/q") {
|
|
@@ -174,7 +233,7 @@ export async function promptTuiRolesWizard(config, mode, messages) {
|
|
|
174
233
|
}
|
|
175
234
|
const answer = result.value;
|
|
176
235
|
const value = answer.trim();
|
|
177
|
-
if (!value || value === "/back") {
|
|
236
|
+
if (!value || value === "/home" || value === "/back") {
|
|
178
237
|
return { kind: "back" };
|
|
179
238
|
}
|
|
180
239
|
if (value === "/quit" || value === "/q") {
|
|
@@ -216,30 +275,32 @@ export function renderTuiConfig(config, configPath, mode, messages, state = {})
|
|
|
216
275
|
const summary = mode === "ask"
|
|
217
276
|
? defaults.askSummaryAgent ?? defaults.summaryAgent ?? messages.tui.lastAskAgent
|
|
218
277
|
: defaults.summaryAgent ?? defaults.agentB ?? messages.tui.noValue;
|
|
278
|
+
const ollamaAgent = config.agents["ollama-local"];
|
|
279
|
+
const ollamaModel = ollamaAgent?.type === "ollama" ? ollamaAgent.model : undefined;
|
|
219
280
|
const currentLines = mode === "ask"
|
|
220
281
|
? [
|
|
221
282
|
row(messages.tui.activeAgents, askAgents),
|
|
222
|
-
row(messages.tui.
|
|
283
|
+
row(messages.tui.roles, askRoles),
|
|
223
284
|
row(messages.tui.summary, summary),
|
|
224
285
|
"",
|
|
225
286
|
bold(messages.tui.availableCommands),
|
|
226
287
|
"",
|
|
227
|
-
row("/agents",
|
|
228
|
-
row("/roles",
|
|
229
|
-
row("/summary",
|
|
288
|
+
row("/agents", messages.tui.askAgentsUsage),
|
|
289
|
+
row("/roles", messages.tui.rolesUsage),
|
|
290
|
+
row("/summary", messages.tui.summaryUsage)
|
|
230
291
|
]
|
|
231
292
|
: [
|
|
232
293
|
row(messages.tui.activeAgents, debateAgents),
|
|
233
|
-
row(messages.tui.
|
|
294
|
+
row(messages.tui.roles, debateRoles),
|
|
234
295
|
row(messages.tui.summary, summary),
|
|
235
296
|
row(messages.tui.responses, String(defaults.turns ?? "?")),
|
|
236
297
|
"",
|
|
237
298
|
bold(messages.tui.availableCommands),
|
|
238
299
|
"",
|
|
239
|
-
row("/agents",
|
|
240
|
-
row("/roles",
|
|
241
|
-
row("/turns",
|
|
242
|
-
row("/summary",
|
|
300
|
+
row("/agents", messages.tui.debateAgentsUsage),
|
|
301
|
+
row("/roles", messages.tui.rolesUsage),
|
|
302
|
+
row("/turns", messages.tui.turnsUsage),
|
|
303
|
+
row("/summary", messages.tui.summaryUsage)
|
|
243
304
|
];
|
|
244
305
|
const lines = [
|
|
245
306
|
"",
|
|
@@ -253,14 +314,22 @@ export function renderTuiConfig(config, configPath, mode, messages, state = {})
|
|
|
253
314
|
row(messages.tui.interface, defaults.interface ?? "tui"),
|
|
254
315
|
row(messages.tui.language, config.language ?? "fr"),
|
|
255
316
|
row(messages.tui.availableAgentsShort, agentInventoryLine(config, messages)),
|
|
317
|
+
...(ollamaModel ? [row(messages.tui.ollamaModel, ollamaModel)] : []),
|
|
256
318
|
"",
|
|
257
319
|
...currentLines,
|
|
258
320
|
"",
|
|
259
|
-
row("/default", messages.tui.defaultModeCommand(mode)),
|
|
260
|
-
row("/interface", `/interface tui ${dim(messages.tui.or)} /interface terminal`),
|
|
261
|
-
row("/language", `/language fr ${dim(messages.tui.or)} /language en`),
|
|
262
321
|
row("/mode", messages.tui.modeConfigCommand),
|
|
263
|
-
|
|
322
|
+
"",
|
|
323
|
+
...(ollamaModel ? [
|
|
324
|
+
row("/ollama", messages.tui.ollamaInfoCommand),
|
|
325
|
+
row("/ollama-model", messages.tui.ollamaModelUsage),
|
|
326
|
+
row("/ollama-sync", messages.tui.ollamaSyncCommand),
|
|
327
|
+
""
|
|
328
|
+
] : []),
|
|
329
|
+
row("/interface", messages.tui.interfaceUsage),
|
|
330
|
+
row("/language", messages.tui.languageUsage),
|
|
331
|
+
"",
|
|
332
|
+
row("/home", messages.tui.backCommand),
|
|
264
333
|
row("/quit", messages.tui.quitCommand)
|
|
265
334
|
], width), viewport),
|
|
266
335
|
...(state.message ? ["", ...centerBlock([state.message], viewport)] : [])
|
|
@@ -322,6 +391,15 @@ export async function promptTuiHomeTopic(mode = "debate", messages, options = {}
|
|
|
322
391
|
if (command === "/new") {
|
|
323
392
|
return { kind: "new" };
|
|
324
393
|
}
|
|
394
|
+
if (command === "/retry") {
|
|
395
|
+
return { kind: "retry" };
|
|
396
|
+
}
|
|
397
|
+
if (command === "/historique" || command === "/history") {
|
|
398
|
+
return { kind: "history" };
|
|
399
|
+
}
|
|
400
|
+
if (command === "/home" || command === "/back" || command === "/b") {
|
|
401
|
+
return { kind: "home" };
|
|
402
|
+
}
|
|
325
403
|
if (command === "/config") {
|
|
326
404
|
return { kind: "config" };
|
|
327
405
|
}
|
|
@@ -356,7 +434,6 @@ export async function promptTuiConfigCommand(mode, messages) {
|
|
|
356
434
|
}
|
|
357
435
|
const rl = createInterface({ input, output });
|
|
358
436
|
try {
|
|
359
|
-
renderTuiComposer(mode, messages, messages.tui.configPrompt);
|
|
360
437
|
const result = await questionWithInterrupt(rl, tuiPrompt(mode, messages.tui.configPrompt, messages));
|
|
361
438
|
if (result.kind === "quit") {
|
|
362
439
|
return { kind: "quit" };
|
|
@@ -367,7 +444,7 @@ export async function promptTuiConfigCommand(mode, messages) {
|
|
|
367
444
|
const answer = result.value;
|
|
368
445
|
const parts = answer.trim().split(/\s+/).filter(Boolean);
|
|
369
446
|
const command = parts[0]?.toLowerCase();
|
|
370
|
-
if (!command || command === "/back" || command === "/b") {
|
|
447
|
+
if (!command || command === "/home" || command === "/back" || command === "/b") {
|
|
371
448
|
return { kind: "back" };
|
|
372
449
|
}
|
|
373
450
|
if (command === "/quit" || command === "/q" || command === "/exit") {
|
|
@@ -414,6 +491,22 @@ export async function promptTuiConfigCommand(mode, messages) {
|
|
|
414
491
|
}
|
|
415
492
|
return { kind: "summary", agent: isNoneValue(value) ? undefined : value };
|
|
416
493
|
}
|
|
494
|
+
if (command === "/ollama") {
|
|
495
|
+
const value = parts[1];
|
|
496
|
+
return value ? { kind: "ollama-model", model: value } : { kind: "ollama-info" };
|
|
497
|
+
}
|
|
498
|
+
if (command === "/ollama-model") {
|
|
499
|
+
const value = parts[1];
|
|
500
|
+
return value ? { kind: "ollama-model", model: value } : { kind: "unknown", message: messages.tui.ollamaModelUsage };
|
|
501
|
+
}
|
|
502
|
+
if (command === "/model") {
|
|
503
|
+
const [first, second] = parts.slice(1);
|
|
504
|
+
const value = first === "ollama-local" ? second : first;
|
|
505
|
+
return value ? { kind: "ollama-model", model: value } : { kind: "unknown", message: messages.tui.ollamaModelUsage };
|
|
506
|
+
}
|
|
507
|
+
if (command === "/ollama-sync") {
|
|
508
|
+
return { kind: "ollama-sync" };
|
|
509
|
+
}
|
|
417
510
|
return { kind: "unknown", message: messages.tui.unknownCommand };
|
|
418
511
|
}
|
|
419
512
|
finally {
|
|
@@ -448,7 +541,11 @@ class TuiRenderer {
|
|
|
448
541
|
process.stdout.write(this.renderSessionHeader(options, agents).join("\n") + "\n");
|
|
449
542
|
}
|
|
450
543
|
notice(message) {
|
|
451
|
-
|
|
544
|
+
const viewport = viewportWidth();
|
|
545
|
+
const width = this.width();
|
|
546
|
+
process.stdout.write(`\n${centerBlock(card([
|
|
547
|
+
`${this.c("green", this.messages.renderers.infoPrefix)} ${message}`
|
|
548
|
+
], width), viewport).join("\n")}\n`);
|
|
452
549
|
}
|
|
453
550
|
warning(message) {
|
|
454
551
|
process.stderr.write(`${this.c("yellow", this.messages.renderers.warningPrefix)} ${message}\n`);
|
|
@@ -502,48 +599,46 @@ class TuiRenderer {
|
|
|
502
599
|
}
|
|
503
600
|
error(failure) {
|
|
504
601
|
this.thinkingEnd();
|
|
505
|
-
|
|
602
|
+
const viewport = viewportWidth();
|
|
603
|
+
const width = this.width();
|
|
604
|
+
process.stderr.write(`\n${centerBlock(card([
|
|
605
|
+
this.c("red", this.messages.common.errorPrefix),
|
|
606
|
+
`${formatFailureLocation(failure, this.messages)}: ${failure.message}`
|
|
607
|
+
], width), viewport).join("\n")}\n`);
|
|
506
608
|
}
|
|
507
609
|
done(outputPath) {
|
|
508
610
|
this.thinkingEnd();
|
|
509
611
|
const viewport = viewportWidth();
|
|
510
612
|
const width = this.width();
|
|
511
|
-
|
|
613
|
+
const folderPath = path.dirname(outputPath);
|
|
614
|
+
const fileName = path.basename(outputPath);
|
|
615
|
+
process.stdout.write(`\n${centerBlock(panel([
|
|
512
616
|
bold(this.messages.tui.sessionDone),
|
|
513
|
-
|
|
617
|
+
"",
|
|
618
|
+
row(this.messages.tui.historyFile, terminalLink(outputPath, compactFileName(fileName, width - 24))),
|
|
619
|
+
row(this.messages.tui.folder, terminalLink(folderPath, compactPath(folderPath, width - 24))),
|
|
620
|
+
"",
|
|
621
|
+
dim(this.messages.tui.sessionHistoryHint)
|
|
514
622
|
], width), viewport).join("\n")}\n\n`);
|
|
515
623
|
}
|
|
516
624
|
renderSessionHeader(options, agents) {
|
|
517
625
|
const viewport = viewportWidth();
|
|
518
626
|
const width = this.width();
|
|
519
627
|
const mode = messagesModeLabel(this.messages, options.mode).toUpperCase();
|
|
520
|
-
const main = [
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
...formatPtyNotice(agents, this.messages)
|
|
528
|
-
], width)
|
|
529
|
-
];
|
|
628
|
+
const main = panel([
|
|
629
|
+
accent(mode),
|
|
630
|
+
this.messages.renderers.subject(options.topic),
|
|
631
|
+
this.messages.renderers.agents(formatAgents(options, agents)),
|
|
632
|
+
formatSessionProgress(options, this.messages),
|
|
633
|
+
this.messages.renderers.context(formatContext(options, this.messages))
|
|
634
|
+
], width);
|
|
530
635
|
return [
|
|
531
|
-
...
|
|
636
|
+
...centerLogo(viewport, this.messages),
|
|
532
637
|
"",
|
|
533
|
-
...centerBlock(
|
|
638
|
+
...centerBlock(main, viewport),
|
|
534
639
|
""
|
|
535
640
|
];
|
|
536
641
|
}
|
|
537
|
-
planPanel(options, width) {
|
|
538
|
-
return panel([
|
|
539
|
-
bold(this.messages.tui.planTitle),
|
|
540
|
-
dim(options.session.localDate),
|
|
541
|
-
"",
|
|
542
|
-
`${accent("1")} ${options.mode === "ask" ? this.messages.tui.planCollectAsk : this.messages.tui.planLaunchDebate}`,
|
|
543
|
-
`${accent("2")} ${options.summaryEnabled ? this.messages.tui.planSummaryComparative : this.messages.tui.planSummaryDisabled}`,
|
|
544
|
-
`${accent("3")} ${this.messages.tui.planExport}`
|
|
545
|
-
], width);
|
|
546
|
-
}
|
|
547
642
|
promptBlock(title, agent) {
|
|
548
643
|
const viewport = viewportWidth();
|
|
549
644
|
const width = this.width();
|
|
@@ -601,13 +696,7 @@ function formatAgents(options, agents) {
|
|
|
601
696
|
return `${options.agentA} <-> ${options.agentB}`;
|
|
602
697
|
}
|
|
603
698
|
function formatAgent(agent) {
|
|
604
|
-
return agent ? `${agentLabel(agent.name)} (${agent.role}
|
|
605
|
-
}
|
|
606
|
-
function formatPtyNotice(agents, messages) {
|
|
607
|
-
const ptyAgents = agents.filter((agent) => agent.type === "cli-pty").map((agent) => agent.name);
|
|
608
|
-
return ptyAgents.length > 0
|
|
609
|
-
? ["", orange(messages.tui.ptyNotice(ptyAgents.join(", ")))]
|
|
610
|
-
: [];
|
|
699
|
+
return agent ? `${agentLabel(agent.name)} (${agent.role})` : "?";
|
|
611
700
|
}
|
|
612
701
|
function formatSummary(options, messages) {
|
|
613
702
|
if (!options.summaryEnabled) {
|
|
@@ -624,6 +713,9 @@ function formatSummary(options, messages) {
|
|
|
624
713
|
function formatResponseCount(options) {
|
|
625
714
|
return options.mode === "ask" ? options.askAgents?.length ?? 2 : options.turns;
|
|
626
715
|
}
|
|
716
|
+
function formatSessionProgress(options, messages) {
|
|
717
|
+
return `${messages.tui.historyCount(options.mode)}: ${formatResponseCount(options)} | ${messages.tui.summary}: ${formatSummary(options, messages)}`;
|
|
718
|
+
}
|
|
627
719
|
function formatContext(options, messages) {
|
|
628
720
|
return options.files.length === 0
|
|
629
721
|
? messages.renderers.noInjectedFiles
|
|
@@ -637,7 +729,9 @@ function formatFailureLocation(failure, messages) {
|
|
|
637
729
|
return `${failure.agent ?? "?"} (${failure.role ?? "?"}${turn})`;
|
|
638
730
|
}
|
|
639
731
|
function stripAnsi(value) {
|
|
640
|
-
return value
|
|
732
|
+
return value
|
|
733
|
+
.replace(/\u001b\][^\u001b]*(?:\u0007|\u001b\\)/g, "")
|
|
734
|
+
.replace(/\u001b\[[0-9;?]*[A-Za-z]/g, "");
|
|
641
735
|
}
|
|
642
736
|
function clearScreen() {
|
|
643
737
|
process.stdout.write("\u001bc\u001b[?25h");
|
|
@@ -649,18 +743,18 @@ function viewportWidth() {
|
|
|
649
743
|
return Math.max(72, Math.min(process.stdout.columns || 100, 180));
|
|
650
744
|
}
|
|
651
745
|
function tuiPrompt(mode, labelPrefix, messages, notice) {
|
|
652
|
-
const label =
|
|
746
|
+
const label = promptTrail(mode, labelPrefix, messages);
|
|
653
747
|
const padding = surfacePadding();
|
|
654
|
-
const promptLine = `${padding}${
|
|
748
|
+
const promptLine = `${padding}${label} ${dim(">")} `;
|
|
655
749
|
return [
|
|
656
750
|
"",
|
|
657
751
|
promptRuleLine(),
|
|
658
752
|
...(notice ? [
|
|
659
|
-
`${padding}${
|
|
753
|
+
`${padding}${label} ${dim(">")}`,
|
|
660
754
|
...promptNoticeLines(notice),
|
|
661
755
|
""
|
|
662
756
|
] : []),
|
|
663
|
-
promptLine
|
|
757
|
+
promptLine,
|
|
664
758
|
].join("\n");
|
|
665
759
|
}
|
|
666
760
|
function promptRuleLine() {
|
|
@@ -680,6 +774,13 @@ function surfacePadding() {
|
|
|
680
774
|
function promptModeLabel(mode, messages) {
|
|
681
775
|
return `Mode ${messages.tui.modeValue(mode).toLowerCase()}`;
|
|
682
776
|
}
|
|
777
|
+
function promptTrail(mode, labelPrefix, messages) {
|
|
778
|
+
const parts = [bold("Palabre"), accent(promptModeLabel(mode, messages))];
|
|
779
|
+
if (labelPrefix !== messages.tui.subject) {
|
|
780
|
+
parts.push(bold(labelPrefix));
|
|
781
|
+
}
|
|
782
|
+
return parts.join(` ${dim(">")} `);
|
|
783
|
+
}
|
|
683
784
|
function messagesModeLabel(messages, mode) {
|
|
684
785
|
return messages.tui.modeValue(mode);
|
|
685
786
|
}
|
|
@@ -691,6 +792,25 @@ function compactPath(value, maxLength) {
|
|
|
691
792
|
const tailLength = Math.max(12, maxLength - marker.length);
|
|
692
793
|
return `${marker}${value.slice(-tailLength)}`;
|
|
693
794
|
}
|
|
795
|
+
function dirnamePortable(value) {
|
|
796
|
+
const separatorIndex = Math.max(value.lastIndexOf("/"), value.lastIndexOf("\\"));
|
|
797
|
+
return separatorIndex > 0 ? value.slice(0, separatorIndex) : path.dirname(value);
|
|
798
|
+
}
|
|
799
|
+
function compactFileName(value, maxLength) {
|
|
800
|
+
if (value.length <= maxLength) {
|
|
801
|
+
return value;
|
|
802
|
+
}
|
|
803
|
+
const extension = value.match(/\.(debate|ask)\.md$/i)?.[0] ?? "";
|
|
804
|
+
const marker = "...";
|
|
805
|
+
const headLength = Math.max(12, maxLength - marker.length - extension.length);
|
|
806
|
+
return `${value.slice(0, headLength)}${marker}${extension}`;
|
|
807
|
+
}
|
|
808
|
+
function terminalLink(filePath, label) {
|
|
809
|
+
if (!supportsInteractiveOutput) {
|
|
810
|
+
return label;
|
|
811
|
+
}
|
|
812
|
+
return `\u001b]8;;${pathToFileURL(filePath).href}\u001b\\${label}\u001b]8;;\u001b\\`;
|
|
813
|
+
}
|
|
694
814
|
function roleFor(config, agent, messages) {
|
|
695
815
|
return config.agents[agent]?.role ?? messages.tui.noValue;
|
|
696
816
|
}
|
|
@@ -714,16 +834,24 @@ function activeAgentNamesForMode(config, mode) {
|
|
|
714
834
|
return [defaults.agentA, defaults.agentB].filter((agent) => Boolean(agent && config.agents[agent]));
|
|
715
835
|
}
|
|
716
836
|
function agentInventoryLine(config, messages) {
|
|
717
|
-
const agents = Object.
|
|
837
|
+
const agents = Object.entries(config.agents)
|
|
838
|
+
.filter(([name]) => !isRetiredAgentName(name))
|
|
839
|
+
.map(([name]) => name)
|
|
840
|
+
.sort();
|
|
718
841
|
return agents.length > 0 ? agents.map(agentLabel).join(", ") : messages.tui.noValue;
|
|
719
842
|
}
|
|
720
843
|
function agentInventoryRows(config, messages) {
|
|
721
|
-
const entries = Object.entries(config.agents)
|
|
844
|
+
const entries = Object.entries(config.agents)
|
|
845
|
+
.filter(([name]) => !isRetiredAgentName(name))
|
|
846
|
+
.sort(([agentA], [agentB]) => agentA.localeCompare(agentB));
|
|
722
847
|
if (entries.length === 0) {
|
|
723
848
|
return [dim(messages.tui.noConfiguredAgents)];
|
|
724
849
|
}
|
|
725
850
|
return entries.map(([name, agent]) => row(name, `${agent.type} ${dim("·")} ${agent.role}`));
|
|
726
851
|
}
|
|
852
|
+
function isRetiredAgentName(name) {
|
|
853
|
+
return name === "gemini";
|
|
854
|
+
}
|
|
727
855
|
function exampleAgentsForMode(config, mode) {
|
|
728
856
|
const activeAgents = activeAgentNamesForMode(config, mode);
|
|
729
857
|
if (activeAgents.length > 0) {
|
|
@@ -786,9 +914,8 @@ function centerLine(line, width) {
|
|
|
786
914
|
return `${" ".repeat(left)}${line}`;
|
|
787
915
|
}
|
|
788
916
|
function composerInputBox(mode, labelPrefix, width, messages) {
|
|
789
|
-
const label = promptModeLabel(mode, messages);
|
|
790
917
|
return composerCard([
|
|
791
|
-
`${
|
|
918
|
+
`${promptTrail(mode, labelPrefix, messages)} ${dim(">")}`
|
|
792
919
|
], width, "center");
|
|
793
920
|
}
|
|
794
921
|
function panel(lines, width) {
|
|
@@ -863,9 +990,6 @@ function accent(value) {
|
|
|
863
990
|
function violet(value) {
|
|
864
991
|
return supportsColor ? `${codes.violet}${value}${codes.reset}` : value;
|
|
865
992
|
}
|
|
866
|
-
function orange(value) {
|
|
867
|
-
return supportsColor ? `${codes.orange}${value}${codes.reset}` : value;
|
|
868
|
-
}
|
|
869
993
|
function muted(value) {
|
|
870
994
|
return supportsColor ? `${codes.gray}${value}${codes.reset}` : value;
|
|
871
995
|
}
|
|
@@ -909,7 +1033,6 @@ function hslToRgb(hue, saturation, lightness) {
|
|
|
909
1033
|
const agentColors = {
|
|
910
1034
|
antigravity: [76, 141, 255],
|
|
911
1035
|
claude: [222, 115, 86],
|
|
912
|
-
gemini: [71, 150, 227],
|
|
913
1036
|
codex: [136, 82, 197],
|
|
914
1037
|
opencode: [80, 168, 103],
|
|
915
1038
|
vibe: [234, 92, 126],
|
package/dist/tuiState.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const TUI_RUN_OVERRIDE_FLAGS = [
|
|
2
|
+
"preset",
|
|
3
|
+
"agent-a",
|
|
4
|
+
"agent-b",
|
|
5
|
+
"agents",
|
|
6
|
+
"model-a",
|
|
7
|
+
"model-b",
|
|
8
|
+
"summary-agent",
|
|
9
|
+
"summary-model",
|
|
10
|
+
"turns",
|
|
11
|
+
"files",
|
|
12
|
+
"context",
|
|
13
|
+
"no-summary",
|
|
14
|
+
"no-early-stop",
|
|
15
|
+
"pull-models",
|
|
16
|
+
"show-prompt",
|
|
17
|
+
"plain",
|
|
18
|
+
"terminal",
|
|
19
|
+
"json"
|
|
20
|
+
];
|
|
21
|
+
export function clearTuiRunOverrides(flags) {
|
|
22
|
+
for (const flag of TUI_RUN_OVERRIDE_FLAGS) {
|
|
23
|
+
delete flags[flag];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function askAgentSeedsForMode(mode, explicitAskAgents, defaultAskAgents) {
|
|
27
|
+
if (mode !== "ask") {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return explicitAskAgents.length > 0 ? explicitAskAgents : defaultAskAgents ?? [];
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -39,23 +39,6 @@
|
|
|
39
39
|
"role": "reviewer",
|
|
40
40
|
"tier": "primary"
|
|
41
41
|
},
|
|
42
|
-
"gemini": {
|
|
43
|
-
"type": "cli",
|
|
44
|
-
"command": "gemini",
|
|
45
|
-
"args": [
|
|
46
|
-
"--output-format",
|
|
47
|
-
"text",
|
|
48
|
-
"--approval-mode",
|
|
49
|
-
"plan",
|
|
50
|
-
"--skip-trust",
|
|
51
|
-
"--prompt",
|
|
52
|
-
"-"
|
|
53
|
-
],
|
|
54
|
-
"promptMode": "stdin",
|
|
55
|
-
"shell": true,
|
|
56
|
-
"role": "reviewer",
|
|
57
|
-
"tier": "primary"
|
|
58
|
-
},
|
|
59
42
|
"opencode": {
|
|
60
43
|
"type": "cli",
|
|
61
44
|
"command": "opencode",
|