@xsft/panels 0.3.1 → 0.3.2

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.
Files changed (2) hide show
  1. package/lib/table.js +11 -3
  2. package/package.json +1 -1
package/lib/table.js CHANGED
@@ -23,13 +23,15 @@ const TABLE_MODES = '\x1b[?1049h\x1b[r\x1b[0m\x1b[4l\x1b[?6l\x1b[?7h\x1b[?1l\x1b
23
23
  * The lines of the table. rows hold { rank, name, state, result }, and state is queued, running, done, or error.
24
24
  * final is null until the report exists, then { status, path }. confirm is true while q waits for y.
25
25
  */
26
- export function render({ title, rows, final, confirm, width }) {
26
+ const SPIN = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
27
+
28
+ export function render({ title, rows, final, confirm, width, frame = 0 }) {
27
29
  const rule = `${GREY}${'─'.repeat(width)}${RESET}`;
28
30
  const pad = Math.max(...rows.map((r) => r.name.length)) + 2;
29
31
  const lines = [` ${BOLD}panels run${RESET} ${title}`, rule];
30
32
  for (const r of rows) {
31
33
  const head = `${String(r.rank).padStart(3)} ${r.name.padEnd(pad)}`;
32
- if (r.state === 'running') lines.push(`${ORANGE}${head}…${RESET}`);
34
+ if (r.state === 'running') lines.push(`${ORANGE}${head}${SPIN[frame % SPIN.length]}${RESET}`);
33
35
  else if (r.state === 'queued') lines.push(`${head}${GREY}queued${RESET}`);
34
36
  else if (r.state === 'error') lines.push(`${head}error`);
35
37
  else lines.push(`${head}${r.result.score} ${GREY}b${r.result.band}${RESET}`);
@@ -141,8 +143,9 @@ export function runTable({ panel, runDir, harness, cwd, target, brief, sources }
141
143
  final = { status: report.status, path: relative(cwd, reportPath) };
142
144
  }
143
145
 
146
+ let frame = 0;
144
147
  function draw() {
145
- const lines = render({ title: `${panel.owner}/${panel.name} v${panel.version}`, rows, final, confirm: ui.confirm, width: Math.min(out.columns, 100) });
148
+ const lines = render({ title: `${panel.owner}/${panel.name} v${panel.version}`, rows, final, confirm: ui.confirm, width: Math.min(out.columns, 100), frame });
146
149
  out.write(`\x1b[H${lines.map((l) => `${l}\x1b[K`).join('\n')}\x1b[J`);
147
150
  }
148
151
 
@@ -161,6 +164,10 @@ export function runTable({ panel, runDir, harness, cwd, target, brief, sources }
161
164
 
162
165
  return new Promise((done) => {
163
166
  const timer = setInterval(tick, 1000);
167
+ const spinner = setInterval(() => {
168
+ frame += 1;
169
+ if (!ui.view && !final) draw();
170
+ }, 100);
164
171
  out.write('\x1b[?1049h\x1b[?25l');
165
172
  process.stdin.setRawMode(true);
166
173
  process.stdin.on('data', (data) => {
@@ -172,6 +179,7 @@ export function runTable({ panel, runDir, harness, cwd, target, brief, sources }
172
179
  judges[from - 1].proc.write(key);
173
180
  } else if (next.quit) {
174
181
  clearInterval(timer);
182
+ clearInterval(spinner);
175
183
  // The harness on PATH can be a shell script that runs the real binary as a child and waits for it, so
176
184
  // SIGHUP goes to the process group of the judge. The pty makes each judge the leader of its own group.
177
185
  for (const j of judges) if (j && !j.exited) process.kill(-j.proc.pid, 'SIGHUP');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsft/panels",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "private": false,
5
5
  "description": "Run a panel of AI judges from cross.software/panels against a target.",
6
6
  "type": "module",