@pify/swarm 0.7.3 → 0.7.5
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/extensions/swarm.ts +9 -1
- package/package.json +1 -1
- package/src/widget-clamp.ts +35 -0
- package/src/widget.ts +8 -3
package/extensions/swarm.ts
CHANGED
|
@@ -316,7 +316,15 @@ export default function swarm(pi: ExtensionAPI) {
|
|
|
316
316
|
try {
|
|
317
317
|
const iso = createIsolationWorktree(ctx.cwd, run.runId + "-i" + (item.index + 1));
|
|
318
318
|
await runItem(ctx, run.runId, def, item, context, iso.path, mailbox);
|
|
319
|
-
|
|
319
|
+
// Remove the worktree when the item changed nothing — the cleanup
|
|
320
|
+
// the README promised but the code never performed (removeIfUnchanged
|
|
321
|
+
// was imported and never called, leaking a worktree + branch per
|
|
322
|
+
// read-only item). Kept when there is work to merge, and only then
|
|
323
|
+
// is the merge note worth showing.
|
|
324
|
+
const removed = removeIfUnchanged(ctx.cwd, iso);
|
|
325
|
+
if (item.result !== null) {
|
|
326
|
+
item.result = `${item.result}\n\n${removed ? CLEAN_WORKTREE_NOTE : isolationNote(iso)}`;
|
|
327
|
+
}
|
|
320
328
|
} catch (err) {
|
|
321
329
|
item.status = "error";
|
|
322
330
|
item.error = err instanceof Error ? err.message : String(err);
|
package/package.json
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep a widget from overrunning the screen.
|
|
3
|
+
*
|
|
4
|
+
* pi caps string-array widgets at ten lines, but a Text-factory widget — the
|
|
5
|
+
* pattern every @pify widget uses because it caches and renders efficiently —
|
|
6
|
+
* bypasses that guard entirely (measured in pi's interactive-mode source). So
|
|
7
|
+
* the bound is ours to keep: an unbounded row count pushes the editor off
|
|
8
|
+
* screen, and a single line wider than the terminal can crash the renderer.
|
|
9
|
+
*
|
|
10
|
+
* Two rules, applied before any colour escape is added (slicing a coloured
|
|
11
|
+
* string would cut through an escape sequence):
|
|
12
|
+
* - `clampWidth` truncates one segment's *visible* text.
|
|
13
|
+
* - `clampRows` caps the row list and, per the suite's no-silent-caps rule,
|
|
14
|
+
* replaces the overflow with a visible "+N more" line rather than dropping
|
|
15
|
+
* it in silence.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** A widget line's variable segment never exceeds this many characters. */
|
|
19
|
+
export const MAX_SEGMENT = 44;
|
|
20
|
+
/** A widget never shows more than this many item rows. */
|
|
21
|
+
export const MAX_WIDGET_ROWS = 8;
|
|
22
|
+
|
|
23
|
+
export function clampWidth(text: string, max = MAX_SEGMENT): string {
|
|
24
|
+
const t = text.replace(/[\r\n]+/g, " ");
|
|
25
|
+
return t.length > max ? `${t.slice(0, max - 1)}…` : t;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Return at most `max` rows; when more were supplied, `more(hidden)` renders
|
|
30
|
+
* the summary line that stands in for the rest.
|
|
31
|
+
*/
|
|
32
|
+
export function clampRows(rows: string[], max: number, more: (hidden: number) => string): string[] {
|
|
33
|
+
if (rows.length <= max) return rows;
|
|
34
|
+
return [...rows.slice(0, max), more(rows.length - max)];
|
|
35
|
+
}
|
package/src/widget.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clampRows, clampWidth, MAX_WIDGET_ROWS } from "./widget-clamp.ts";
|
|
1
2
|
import type { SwarmRun, ThemeLike } from "./types.ts";
|
|
2
3
|
|
|
3
4
|
const WIDTH = 54;
|
|
@@ -29,7 +30,9 @@ export function buildWidgetLines(run: SwarmRun | null, theme: ThemeLike, now: nu
|
|
|
29
30
|
const pad = Math.max(1, WIDTH - title.length - hint.length);
|
|
30
31
|
lines.push(dim(`╭${title}${"─".repeat(pad)}${hint}╮`));
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
// Cap the rows: a large swarm would otherwise push the editor off screen,
|
|
34
|
+
// since a Text-factory widget bypasses pi's ten-line guard.
|
|
35
|
+
const rows = run.items.map((item) => {
|
|
33
36
|
const paint =
|
|
34
37
|
item.status === "running"
|
|
35
38
|
? (s: string) => theme.fg("warning", s)
|
|
@@ -38,8 +41,10 @@ export function buildWidgetLines(run: SwarmRun | null, theme: ThemeLike, now: nu
|
|
|
38
41
|
: item.status === "queued"
|
|
39
42
|
? dim
|
|
40
43
|
: (s: string) => theme.fg("error", s);
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
return `${dim("│ ")}${paint(`${icon(item.status)} ${clampWidth(item.agent, 24)}`)}${dim(` ${clampWidth(item.item, 32)}`)}`;
|
|
45
|
+
});
|
|
46
|
+
for (const row of clampRows(rows, MAX_WIDGET_ROWS, (hidden) => dim(`│ … +${hidden} more`))) {
|
|
47
|
+
lines.push(row);
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
lines.push(dim(`╰${"─".repeat(WIDTH)}╯`));
|