@xynogen/pix-commands 0.6.0 → 0.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-commands",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Pi extension — slash commands for cache clearing and isolated side questions",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/btw/render.ts CHANGED
@@ -49,10 +49,10 @@ export function registerBtwRenderer(
49
49
  // header text embedded inside Markdown can confuse wrapping and parsing.
50
50
  const card = new Box(1, 1, (text) => theme.bg("selectedBg", text));
51
51
  card.addChild(
52
- new Text(`${statusGlyph} ${theme.bold("BTW")} ${theme.fg("dim", `· ${meta}`)}`, 0, 0),
52
+ new Text(`${statusGlyph} ${theme.bold("BTW")} ${theme.fg("muted", `· ${meta}`)}`, 0, 0),
53
53
  );
54
54
  card.addChild(
55
- new Text(`${theme.fg("accent", "▐")} ${theme.fg("muted", details.question)}`, 0, 0),
55
+ new Text(`${theme.fg("accent", "▐")} ${theme.fg("dim", details.question)}`, 0, 0),
56
56
  );
57
57
  card.addChild(new Spacer(1));
58
58
 
@@ -69,7 +69,7 @@ export function registerBtwRenderer(
69
69
  card.addChild(new Text(theme.fg("thinkingText", details.thinking), 0, 0));
70
70
  card.addChild(new Spacer(1));
71
71
  } else {
72
- card.addChild(new Text(theme.fg("dim", "› reasoning hidden — expand to view"), 0, 0));
72
+ card.addChild(new Text(theme.fg("muted", "› reasoning hidden — expand to view"), 0, 0));
73
73
  card.addChild(new Spacer(1));
74
74
  }
75
75
  }
@@ -49,6 +49,26 @@ describe("BTW widget layout", () => {
49
49
  expect(out).toContain("[GPT]");
50
50
  });
51
51
 
52
+ test("uses primary identity, secondary activity, and tertiary metadata", () => {
53
+ const taggedTheme: WidgetTheme = {
54
+ fg: (color, text) => `<${color}>${text}</${color}>`,
55
+ bold: (text) => text,
56
+ };
57
+ const output = renderBtwWidget(
58
+ [job({ id: 7, model: "GPT", text: "Reading auth.ts", toolUses: 2 })],
59
+ taggedTheme,
60
+ 0,
61
+ 1_000,
62
+ 500,
63
+ ).join("\n");
64
+ expect(output).toContain("<accent>BTW</accent><muted> (1)</muted>");
65
+ expect(output).toContain("<toolTitle>#7</toolTitle>");
66
+ expect(output).toContain("<muted>[GPT]</muted>");
67
+ expect(output).toMatch(/<muted>[^<]*2 · 1\.0s<\/muted>/);
68
+ expect(output).toContain("<dim>Reading auth.ts</dim>");
69
+ expect(output).toContain("<muted>└─</muted>");
70
+ });
71
+
52
72
  test("finished jobs linger with a check, then drop after the window", () => {
53
73
  const done = job({ status: "completed", completedAt: 1_000, toolUses: 2, turnCount: 1 });
54
74
  // Default base 10s × 3 = 30s ok-window.
package/src/btw/widget.ts CHANGED
@@ -108,23 +108,23 @@ function finishedLine(job: BtwWidgetJob, theme: WidgetTheme): string {
108
108
  if (job.status === "completed") {
109
109
  mark = theme.fg("success", "\u2713");
110
110
  } else if (job.status === "stopped") {
111
- mark = theme.fg("dim", "\u25a0");
112
- suffix = theme.fg("dim", " stopped");
111
+ mark = theme.fg("muted", "\u25a0");
112
+ suffix = theme.fg("muted", " stopped");
113
113
  } else {
114
114
  mark = theme.fg("error", "\u2717");
115
115
  suffix = theme.fg("error", job.error ? ` ${job.error.slice(0, 60)}` : " error");
116
116
  }
117
117
  const model = theme.fg("muted", `[${job.model}]`);
118
- const stats = theme.fg("dim", statsFor(job, end));
119
- return `${mark} ${theme.fg("dim", `#${job.id}`)} ${model} ${theme.fg("dim", "\u00b7")} ${stats}${suffix}`;
118
+ const stats = theme.fg("muted", statsFor(job, end));
119
+ return `${mark} ${theme.fg("dim", `#${job.id}`)} ${model} ${theme.fg("muted", "\u00b7")} ${stats}${suffix}`;
120
120
  }
121
121
 
122
122
  function runningLine(job: BtwWidgetJob, theme: WidgetTheme, frame: string, now: number): string {
123
123
  const model = theme.fg("muted", `[${job.model}]`);
124
- const stats = theme.fg("dim", statsFor(job, now));
124
+ const stats = theme.fg("muted", statsFor(job, now));
125
125
  const activeMap = new Map<string, string>(job.activeTools.map((name, i) => [String(i), name]));
126
126
  const activity = theme.fg("dim", describeActivity(activeMap, job.text));
127
- const dot = theme.fg("dim", "\u00b7");
127
+ const dot = theme.fg("muted", "\u00b7");
128
128
  return `${theme.fg("accent", frame)} ${theme.fg("toolTitle", theme.bold(`#${job.id}`))} ${model} ${dot} ${stats} ${dot} ${activity}`;
129
129
  }
130
130
 
@@ -152,15 +152,15 @@ export function renderBtwWidget(
152
152
  const spinner = SPINNER[frame % SPINNER.length] ?? "";
153
153
 
154
154
  const runningLines = running.map((j) =>
155
- truncate(`${theme.fg("dim", "\u251c\u2500")} ${runningLine(j, theme, spinner, now)}`),
155
+ truncate(`${theme.fg("muted", "\u251c\u2500")} ${runningLine(j, theme, spinner, now)}`),
156
156
  );
157
157
  const finishedLines = finished.map((j) =>
158
- truncate(`${theme.fg("dim", "\u251c\u2500")} ${finishedLine(j, theme)}`),
158
+ truncate(`${theme.fg("muted", "\u251c\u2500")} ${finishedLine(j, theme)}`),
159
159
  );
160
160
 
161
161
  const lines: string[] = [
162
162
  truncate(
163
- `${theme.fg(headingColor, headingIcon)} ${theme.fg(headingColor, `BTW (${running.length})`)}`,
163
+ `${theme.fg(headingColor, headingIcon)} ${theme.fg(headingColor, "BTW")}${theme.fg("muted", ` (${running.length})`)}`,
164
164
  ),
165
165
  ];
166
166
 
@@ -173,7 +173,7 @@ export function renderBtwWidget(
173
173
  const hidden = body.length - shown.length;
174
174
  lines.push(...shown);
175
175
  lines.push(
176
- truncate(`${theme.fg("dim", "\u251c\u2500")} ${theme.fg("dim", `+${hidden} more`)}`),
176
+ truncate(`${theme.fg("muted", "\u251c\u2500")} ${theme.fg("muted", `+${hidden} more`)}`),
177
177
  );
178
178
  }
179
179
 
package/src/clear.ts CHANGED
@@ -1,13 +1,15 @@
1
+ import { rm } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
1
4
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
5
 
3
- async function clearCache(pi: ExtensionAPI, ctx: ExtensionCommandContext) {
6
+ async function clearCache(_pi: ExtensionAPI, ctx: ExtensionCommandContext) {
4
7
  ctx.ui.notify("Clearing ~/.cache/pi", "info");
5
- const result = await pi.exec("/bin/sh", ["-lc", 'rm -rf "$HOME/.cache/pi"'], {
6
- timeout: 10_000,
7
- });
8
- const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
9
- if ((result.code ?? 0) !== 0) {
10
- ctx.ui.notify(`Cache clear failed. ${output || "No output."}`, "error");
8
+ try {
9
+ await rm(join(homedir(), ".cache", "pi"), { recursive: true, force: true });
10
+ } catch (err) {
11
+ const msg = err instanceof Error ? err.message : String(err);
12
+ ctx.ui.notify(`Cache clear failed. ${msg}`, "error");
11
13
  return;
12
14
  }
13
15
  ctx.ui.notify("~/.cache/pi cleared. Run /reload to apply changes.", "warning");