@xynogen/pix-todo 0.3.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-todo",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Pi tool — durable execution checklist (todo)",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@xynogen/pix-pretty": "^1.11.2",
37
+ "@xynogen/pix-pretty": "^1.19.0",
38
38
  "@xynogen/pix-runtime": "^0.8.0",
39
39
  "typebox": "^1.1.38"
40
40
  },
package/src/todo.test.ts CHANGED
@@ -886,6 +886,7 @@ describe("todo card layout", () => {
886
886
  expect(rendered).toContain("alpha");
887
887
  expect(rendered).toContain("[text]○ alpha"); // pending card, no id number
888
888
  expect(rendered).not.toContain("[success]✓ [/] [toolTitle]<b>todo</b>[/]");
889
+ expect(rendered.split("\n")[0]).toBe(`[success]${"─".repeat(80)}[/]`);
889
890
  });
890
891
 
891
892
  test("opening a new todo card collapses the previously open one", async () => {
@@ -931,7 +932,8 @@ describe("todo card layout", () => {
931
932
  .join("\n")
932
933
  .trimEnd();
933
934
 
934
- expect(rendered).toBe("No todo with id 99.");
935
+ expect(rendered.split("\n")[0]).toBe(`[error]${"─".repeat(80)}[/]`);
936
+ expect(rendered).toContain("No todo with id 99.");
935
937
  });
936
938
 
937
939
  test("a collapsed result is exactly one shared-style line", async () => {
@@ -954,8 +956,9 @@ describe("todo card layout", () => {
954
956
 
955
957
  expect(result.details).toBeDefined();
956
958
  expect(lines).toHaveLength(1);
959
+ expect(lines[0]).not.toContain("────");
957
960
  expect(lines[0]?.trimEnd()).toBe(
958
- "[success]✓ [/] [toolTitle]<b>todo</b>[/] [muted]#2 todo renderer[/] [dim]·[/] [dim]1/2 done[/]",
961
+ "[success]✓ [/] [toolTitle]<b>todo</b>[/] [dim]#2 todo renderer[/] [muted]·[/] [muted]1/2 done[/]",
959
962
  );
960
963
  });
961
964
  });
@@ -986,14 +989,14 @@ describe("renderResult snapshot isolation", () => {
986
989
  describe("renderTodoSummaryLine (collapsed one-liner)", () => {
987
990
  test("empty list renders a compact tool row", () => {
988
991
  expect(renderTodoSummaryLine([], tagTheme)).toBe(
989
- "[success]✓ [/] [toolTitle]<b>todo</b>[/] [muted]empty[/]",
992
+ "[success]✓ [/] [toolTitle]<b>todo</b>[/] [dim]empty[/]",
990
993
  );
991
994
  });
992
995
 
993
996
  test("uses warning status when work is blocked", () => {
994
997
  const items: TodoItem[] = [{ id: 1, text: "Need approval", status: "blocked" }];
995
998
  expect(renderTodoSummaryLine(items, tagTheme)).toBe(
996
- "[warning]⚠ [/] [toolTitle]<b>todo</b>[/] [muted]checklist[/] [dim]·[/] [dim]0/1 done · 1 blocked[/]",
999
+ "[warning]⚠ [/] [toolTitle]<b>todo</b>[/] [dim]checklist[/] [muted]·[/] [muted]0/1 done · 1 blocked[/]",
997
1000
  );
998
1001
  });
999
1002
 
@@ -1003,7 +1006,7 @@ describe("renderTodoSummaryLine (collapsed one-liner)", () => {
1003
1006
  { id: 2, text: "b", status: "in_progress" },
1004
1007
  ];
1005
1008
  expect(renderTodoSummaryLine(items, tagTheme)).toBe(
1006
- "[success]✓ [/] [toolTitle]<b>todo</b>[/] [muted]#2 b[/] [dim]·[/] [dim]1/2 done[/]",
1009
+ "[success]✓ [/] [toolTitle]<b>todo</b>[/] [dim]#2 b[/] [muted]·[/] [muted]1/2 done[/]",
1007
1010
  );
1008
1011
  });
1009
1012
  });
package/src/todo.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
13
13
  import { Text } from "@earendil-works/pi-tui";
14
14
  import { icon } from "@xynogen/pix-pretty/icon-catalog";
15
- import { dotJoin, formatCollapsedToolRow, termW } from "@xynogen/pix-pretty/utils";
15
+ import { dotJoin, formatCollapsedToolRow, frameToolResult, termW } from "@xynogen/pix-pretty/utils";
16
16
  import { type CollapseState, tickCollapse } from "@xynogen/pix-runtime/collapse";
17
17
  import { once } from "@xynogen/pix-runtime/once";
18
18
  import { Type } from "typebox";
@@ -271,7 +271,7 @@ export default function registerTodo(pi: ExtensionAPI): void {
271
271
  const t = theme as TodoTheme;
272
272
  const action = (args as { action?: string })?.action ?? "";
273
273
  const title = t.fg("toolTitle", t.bold("todo"));
274
- return new Text(action ? `${title} ${t.fg("muted", action)}` : title, 0, 0);
274
+ return new Text(action ? `${title} ${t.fg("dim", action)}` : title, 0, 0);
275
275
  },
276
276
  renderResult(result, options, theme, context) {
277
277
  const details = result.details as TodoResultDetails | undefined;
@@ -279,8 +279,10 @@ export default function registerTodo(pi: ExtensionAPI): void {
279
279
  .filter((part) => part.type === "text")
280
280
  .map((part) => part.text)
281
281
  .join("\n");
282
+ const isPartial = options.isPartial === true;
282
283
  if (context.isError || details?.outcome === "error" || !details) {
283
- return new Text(resultText, 0, 0);
284
+ const component = new Text(resultText, 0, 0);
285
+ return isPartial ? component : frameToolResult(component, theme, true);
284
286
  }
285
287
 
286
288
  const collapsed = tickCollapse(
@@ -292,7 +294,8 @@ export default function registerTodo(pi: ExtensionAPI): void {
292
294
  // An open card claims focus, collapsing any earlier open board.
293
295
  if (!collapsed) focusCard(context.state as CollapseState, context.invalidate);
294
296
  const render = collapsed ? renderTodoSummaryLine : renderTodoLines;
295
- return new Text(render(details.snapshot, theme as TodoTheme), 0, 0);
297
+ const component = new Text(render(details.snapshot, theme as TodoTheme), 0, 0);
298
+ return collapsed || isPartial ? component : frameToolResult(component, theme, false);
296
299
  },
297
300
 
298
301
  async execute(_id, params) {