kaizen-agent 1.3.3 → 1.3.4
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/cli/dashboard.ts +38 -13
- package/package.json +1 -1
package/cli/dashboard.ts
CHANGED
|
@@ -79,6 +79,20 @@ function findTerminal(cwd: string, fullCmd: string[]): { cmd: string[]; detached
|
|
|
79
79
|
const hasDisplay = Boolean(process.env.WAYLAND_DISPLAY || process.env.DISPLAY);
|
|
80
80
|
const inTmux = Boolean(process.env.TMUX);
|
|
81
81
|
|
|
82
|
+
// Windows has no xdg anything, and none of the terminals below exist there.
|
|
83
|
+
// PowerShell is what a Windows user has open anyway: one -Command string,
|
|
84
|
+
// where a single quote is doubled rather than escaped. Windows Terminal hosts
|
|
85
|
+
// it when installed; otherwise `start` gives it a window of its own.
|
|
86
|
+
if (process.platform === "win32") {
|
|
87
|
+
const q = (a: string) => `'${a.replace(/'/g, "''")}'`;
|
|
88
|
+
const shell = Bun.which("pwsh.exe") ? "pwsh.exe" : "powershell.exe";
|
|
89
|
+
const ps = `Set-Location -LiteralPath ${q(cwd)}; & ${fullCmd.map(q).join(" ")}`;
|
|
90
|
+
if (Bun.which("wt.exe")) {
|
|
91
|
+
return { cmd: ["wt.exe", "-d", cwd, shell, "-NoExit", "-Command", ps], detached: true };
|
|
92
|
+
}
|
|
93
|
+
return { cmd: ["cmd.exe", "/c", "start", "kaizen", shell, "-NoExit", "-Command", ps], detached: true };
|
|
94
|
+
}
|
|
95
|
+
|
|
82
96
|
if (process.env.TERMINAL && Bun.which(process.env.TERMINAL)) {
|
|
83
97
|
const term = process.env.TERMINAL;
|
|
84
98
|
if (term.includes("kitty")) return { cmd: [term, "--directory", cwd, ...fullCmd], detached: true };
|
|
@@ -209,15 +223,15 @@ export async function dashboard(
|
|
|
209
223
|
...(state ? [
|
|
210
224
|
{ key: "board", label: "Board", hint: "ideas and runs, by stage" },
|
|
211
225
|
{ key: "runs", label: "Runs", hint: "every run, and what each is waiting on" },
|
|
212
|
-
{ key: "backlog", label: "Backlog", hint: "
|
|
226
|
+
{ key: "backlog", label: "Backlog", hint: "things to do later" },
|
|
213
227
|
] : []),
|
|
214
|
-
{ key: "settings", label: "Settings", hint: "
|
|
228
|
+
{ key: "settings", label: "Settings", hint: "change how kaizen works" },
|
|
215
229
|
// ~/.kaizen is the global state, not a project: there is nothing to set up
|
|
216
230
|
// there, and it never holds the spec files a project copy does.
|
|
217
231
|
...(state && state !== join(home, ".kaizen") && !existsSync(join(state, "spec.md"))
|
|
218
|
-
? [{ key: "init", label: "Set up this project", hint: "
|
|
219
|
-
...(!state ? [{ key: "init", label: "Set up this project", hint: "
|
|
220
|
-
{ key: "upgrade", label: "Upgrade", hint: "
|
|
232
|
+
? [{ key: "init", label: "Set up this project", hint: "add kaizen to this folder" }] : []),
|
|
233
|
+
...(!state ? [{ key: "init", label: "Set up this project", hint: "add kaizen to this folder" }] : []),
|
|
234
|
+
{ key: "upgrade", label: "Upgrade", hint: "get the latest version" },
|
|
221
235
|
{ key: "quit", label: "Quit", hint: "" },
|
|
222
236
|
];
|
|
223
237
|
|
|
@@ -430,14 +444,18 @@ export async function dashboard(
|
|
|
430
444
|
for (;;) {
|
|
431
445
|
const here = from ?? state!;
|
|
432
446
|
const runs = readRuns(here);
|
|
433
|
-
const
|
|
447
|
+
const now = Date.now();
|
|
448
|
+
// The dot the board already uses, a four-letter word for anyone not reading
|
|
449
|
+
// colour, and the date dropped from the id: every run made the same day
|
|
450
|
+
// repeated it, which is ten columns saying nothing.
|
|
451
|
+
const width = Math.max(0, ...runs.map((r) => short(r.id).length));
|
|
434
452
|
const rows = runs.map((r) => {
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
453
|
+
const { dot, status } = dotFor(r, now);
|
|
454
|
+
const word = { waiting: "wait", running: "run", stalled: "idle", done: "done", abandoned: "drop" }[status] ?? status;
|
|
455
|
+
const mark = status === "waiting" ? c.amber(word.padEnd(4)) : c.dim(word.padEnd(4));
|
|
438
456
|
// The mark already says done or dropped; repeating the stage beside it is noise.
|
|
439
457
|
const tail = r.stage === "done" || r.stage === "abandoned" ? "" : (r.awaiting ?? r.stage);
|
|
440
|
-
return `${mark} ${r.id.padEnd(width)} ${c.dim(tail)}`;
|
|
458
|
+
return `${dot} ${mark} ${short(r.id).padEnd(width)} ${c.dim(tail)}`;
|
|
441
459
|
});
|
|
442
460
|
const { index } = await pick(from ? `Runs — ${label(from)}` : "Runs", rows);
|
|
443
461
|
if (index === null) return;
|
|
@@ -637,7 +655,10 @@ export async function dashboard(
|
|
|
637
655
|
stdout.write(`\n ${c.bold("Board")} ${c.dim(scope)}\n\n`);
|
|
638
656
|
stdout.write(" " + cols.map(({ meta }, n) =>
|
|
639
657
|
pad(n === col ? c.cyan(meta.title) : c.dim(meta.title), inner)).join(" ") + "\n");
|
|
640
|
-
|
|
658
|
+
// Only the column you are in gets a solid rule; the rest fade to a dotted one,
|
|
659
|
+
// which says where the cursor is without painting a block over the card.
|
|
660
|
+
stdout.write(" " + cols.map((_, n) =>
|
|
661
|
+
n === col ? c.cyan("─".repeat(inner)) : c.dim("┈".repeat(inner))).join(" ") + "\n");
|
|
641
662
|
const height = Math.max(4, (stdout.rows ?? 24) - 11);
|
|
642
663
|
const deep = Math.max(0, ...cols.map((x) => x.lines.length));
|
|
643
664
|
// The selected card drags the viewport with it; a cursor that can leave the
|
|
@@ -1011,10 +1032,14 @@ export async function dashboard(
|
|
|
1011
1032
|
await report([
|
|
1012
1033
|
c.bold("Could not open terminal"),
|
|
1013
1034
|
"",
|
|
1014
|
-
c.dim(
|
|
1035
|
+
c.dim(process.platform === "darwin"
|
|
1036
|
+
? "Terminal.app could not be driven from here."
|
|
1037
|
+
: "No supported terminal emulator found (xdg-terminal-exec, kitty, ghostty, alacritty, tmux)."),
|
|
1015
1038
|
"",
|
|
1016
1039
|
"Run manually:",
|
|
1017
|
-
` ${c.cyan(
|
|
1040
|
+
` ${c.cyan(process.platform === "win32"
|
|
1041
|
+
? `Set-Location '${projectDir}'; & ${agent.cmd} '${prompt.replace(/'/g, "''")}'`
|
|
1042
|
+
: `cd "${projectDir}" && ${agent.cmd} "${prompt}"`)}`,
|
|
1018
1043
|
]);
|
|
1019
1044
|
return;
|
|
1020
1045
|
}
|
package/package.json
CHANGED