@nonbot/cli 0.5.15 → 0.7.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/CHANGELOG.md +35 -0
- package/dist/commands/choir-mcp.js +4 -0
- package/dist/commands/choir.js +110 -0
- package/dist/commands/daemon.js +63 -3
- package/dist/index.js +12 -0
- package/dist/lib/choir/brief.js +55 -0
- package/dist/lib/choir/debounce.js +0 -0
- package/dist/lib/choir/health.js +59 -0
- package/dist/lib/choir/hub-reducer.js +190 -0
- package/dist/lib/choir/hub.js +478 -0
- package/dist/lib/choir/journal.js +59 -0
- package/dist/lib/choir/launcher.js +133 -0
- package/dist/lib/choir/mcp-hub-client.js +119 -0
- package/dist/lib/choir/mcp-server.js +173 -0
- package/dist/lib/choir/names.js +39 -0
- package/dist/lib/choir/needs-you.js +210 -0
- package/dist/lib/choir/progress-events.js +228 -0
- package/dist/lib/choir/reconcile.js +271 -0
- package/dist/lib/choir/types.js +54 -0
- package/dist/lib/choir/worktree.js +128 -0
- package/dist/lib/completion.js +2 -1
- package/dist/lib/output.js +27 -0
- package/dist/lib/pane-title.js +51 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/lib/output.js
CHANGED
|
@@ -287,6 +287,33 @@ export function pollTick(args) {
|
|
|
287
287
|
const statusSeg = c.muted(statusText, stream);
|
|
288
288
|
return `${ts} ${pollCount} ${sep} ${sleepSeg} ${sep} ${statusSeg}`;
|
|
289
289
|
}
|
|
290
|
+
export function formatElapsed(ms) {
|
|
291
|
+
if (!Number.isFinite(ms) || ms < 0)
|
|
292
|
+
return '0s';
|
|
293
|
+
const totalSec = Math.floor(ms / 1000);
|
|
294
|
+
if (totalSec < 60)
|
|
295
|
+
return `${totalSec}s`;
|
|
296
|
+
const totalMin = Math.floor(totalSec / 60);
|
|
297
|
+
if (totalMin < 60)
|
|
298
|
+
return `${totalMin}m ${totalSec % 60}s`;
|
|
299
|
+
const hours = Math.floor(totalMin / 60);
|
|
300
|
+
return `${hours}h ${totalMin % 60}m`;
|
|
301
|
+
}
|
|
302
|
+
function summaryAnchor(stream) {
|
|
303
|
+
const glyph = asciiOnly() ? '*' : '◆';
|
|
304
|
+
return c.cyan(glyph, stream);
|
|
305
|
+
}
|
|
306
|
+
export function runSummary(args) {
|
|
307
|
+
const stream = args.stream ?? process.stdout;
|
|
308
|
+
const failed = args.failed ?? 0;
|
|
309
|
+
const sep = c.muted('·', stream);
|
|
310
|
+
const segs = [];
|
|
311
|
+
segs.push(c.green(`${args.running} running`, stream));
|
|
312
|
+
segs.push(c.muted(`${args.done} done`, stream));
|
|
313
|
+
if (failed > 0)
|
|
314
|
+
segs.push(c.red(`${failed} failed`, stream));
|
|
315
|
+
return `${summaryAnchor(stream)} ` + segs.join(` ${sep} `);
|
|
316
|
+
}
|
|
290
317
|
export function fixBlock(args) {
|
|
291
318
|
const stream = args.stream ?? process.stdout;
|
|
292
319
|
const title = c.amber(`| ${args.title.toUpperCase()} |`, stream);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { spawnSync as nodeSpawnSync } from 'node:child_process';
|
|
2
|
+
const STATE_GLYPH = {
|
|
3
|
+
running: '▶',
|
|
4
|
+
completed: '✓',
|
|
5
|
+
failed: '✗',
|
|
6
|
+
stopping: '■',
|
|
7
|
+
};
|
|
8
|
+
const STATE_GLYPH_ASCII = {
|
|
9
|
+
running: '>',
|
|
10
|
+
completed: 'OK',
|
|
11
|
+
failed: 'XX',
|
|
12
|
+
stopping: '#',
|
|
13
|
+
};
|
|
14
|
+
function asciiOnly(env = process.env) {
|
|
15
|
+
return env.NONBOT_ASCII_ONLY === '1' || env.NONBOT_ASCII_ONLY === 'true';
|
|
16
|
+
}
|
|
17
|
+
export function paneStateGlyph(state, env = process.env) {
|
|
18
|
+
return asciiOnly(env) ? STATE_GLYPH_ASCII[state] : STATE_GLYPH[state];
|
|
19
|
+
}
|
|
20
|
+
export const PANE_TITLE_MAX = 44;
|
|
21
|
+
export function formatPaneTitle(state, story, env = process.env) {
|
|
22
|
+
const glyph = paneStateGlyph(state, env);
|
|
23
|
+
const cleaned = (story ?? '')
|
|
24
|
+
.replace(/[\x00-\x1f\x7f]/g, ' ')
|
|
25
|
+
.replace(/ {2,}/g, ' ')
|
|
26
|
+
.trim();
|
|
27
|
+
const label = cleaned.length > 0 ? cleaned : 'nonbot run';
|
|
28
|
+
const title = `${glyph} ${label}`;
|
|
29
|
+
return title.length > PANE_TITLE_MAX ? title.slice(0, PANE_TITLE_MAX - 1) + '…' : title;
|
|
30
|
+
}
|
|
31
|
+
export function buildPaneTitleCommand(paneId, state, story, env = process.env) {
|
|
32
|
+
if (!/^%\d+$/.test(paneId))
|
|
33
|
+
return null;
|
|
34
|
+
const title = formatPaneTitle(state, story, env);
|
|
35
|
+
return { cmd: 'tmux', args: ['select-pane', '-t', paneId, '-T', title] };
|
|
36
|
+
}
|
|
37
|
+
export function applyPaneTitle(paneId, state, story, spawnImpl = nodeSpawnSync, env = process.env) {
|
|
38
|
+
const command = buildPaneTitleCommand(paneId, state, story, env);
|
|
39
|
+
if (!command)
|
|
40
|
+
return false;
|
|
41
|
+
try {
|
|
42
|
+
spawnImpl(command.cmd, command.args, {
|
|
43
|
+
encoding: 'utf-8',
|
|
44
|
+
timeout: 1000,
|
|
45
|
+
windowsHide: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.7.0';
|
package/package.json
CHANGED