@caupulican/pi-adaptative 0.93.18 → 0.93.19

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 (97) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/core/agent-session.d.ts +1 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +22 -12
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/compaction-controller.d.ts +21 -0
  7. package/dist/core/compaction-controller.d.ts.map +1 -1
  8. package/dist/core/compaction-controller.js +149 -26
  9. package/dist/core/compaction-controller.js.map +1 -1
  10. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  11. package/dist/core/delegation/worker-agent-control-coordinator.js +1 -0
  12. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  13. package/dist/core/delegation/worker-agent-control.d.ts +2 -0
  14. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  15. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  16. package/dist/core/foreground-lifecycle-adapter.d.ts +27 -0
  17. package/dist/core/foreground-lifecycle-adapter.d.ts.map +1 -0
  18. package/dist/core/foreground-lifecycle-adapter.js +61 -0
  19. package/dist/core/foreground-lifecycle-adapter.js.map +1 -0
  20. package/dist/core/foreground-lifecycle-controller.d.ts +48 -0
  21. package/dist/core/foreground-lifecycle-controller.d.ts.map +1 -0
  22. package/dist/core/foreground-lifecycle-controller.js +404 -0
  23. package/dist/core/foreground-lifecycle-controller.js.map +1 -0
  24. package/dist/core/foreground-recovery-controller.d.ts +3 -0
  25. package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
  26. package/dist/core/foreground-recovery-controller.js +15 -1
  27. package/dist/core/foreground-recovery-controller.js.map +1 -1
  28. package/dist/core/goals/goal-state.d.ts.map +1 -1
  29. package/dist/core/goals/goal-state.js +9 -2
  30. package/dist/core/goals/goal-state.js.map +1 -1
  31. package/dist/core/keybindings.d.ts +2 -2
  32. package/dist/core/keybindings.d.ts.map +1 -1
  33. package/dist/core/keybindings.js +2 -2
  34. package/dist/core/keybindings.js.map +1 -1
  35. package/dist/core/memory/memory-manager.d.ts +22 -0
  36. package/dist/core/memory/memory-manager.d.ts.map +1 -1
  37. package/dist/core/memory/memory-manager.js +108 -49
  38. package/dist/core/memory/memory-manager.js.map +1 -1
  39. package/dist/core/model-router/session-buffer.d.ts +10 -2
  40. package/dist/core/model-router/session-buffer.d.ts.map +1 -1
  41. package/dist/core/model-router/session-buffer.js +35 -9
  42. package/dist/core/model-router/session-buffer.js.map +1 -1
  43. package/dist/core/model-router-controller.d.ts +20 -2
  44. package/dist/core/model-router-controller.d.ts.map +1 -1
  45. package/dist/core/model-router-controller.js +70 -17
  46. package/dist/core/model-router-controller.js.map +1 -1
  47. package/dist/core/provider-request-runtime-controller.d.ts +12 -1
  48. package/dist/core/provider-request-runtime-controller.d.ts.map +1 -1
  49. package/dist/core/provider-request-runtime-controller.js +45 -2
  50. package/dist/core/provider-request-runtime-controller.js.map +1 -1
  51. package/dist/core/tools/delegate.d.ts.map +1 -1
  52. package/dist/core/tools/delegate.js +4 -2
  53. package/dist/core/tools/delegate.js.map +1 -1
  54. package/dist/modes/interactive/components/assistant-message.d.ts +1 -3
  55. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  56. package/dist/modes/interactive/components/assistant-message.js +10 -20
  57. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  58. package/dist/modes/interactive/components/tool-group.d.ts +3 -0
  59. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  60. package/dist/modes/interactive/components/tool-group.js +25 -0
  61. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  62. package/dist/modes/interactive/components/transcript-overlay.d.ts +13 -0
  63. package/dist/modes/interactive/components/transcript-overlay.d.ts.map +1 -0
  64. package/dist/modes/interactive/components/transcript-overlay.js +35 -0
  65. package/dist/modes/interactive/components/transcript-overlay.js.map +1 -0
  66. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  67. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  68. package/dist/modes/interactive/components/tree-selector.js +7 -4
  69. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  70. package/dist/modes/interactive/interactive-event-controller.d.ts +1 -1
  71. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -1
  72. package/dist/modes/interactive/interactive-event-controller.js +2 -1
  73. package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
  74. package/dist/modes/interactive/interactive-mode.d.ts +9 -7
  75. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  76. package/dist/modes/interactive/interactive-mode.js +70 -99
  77. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  78. package/dist/modes/interactive/runtime-status-controller.d.ts +40 -0
  79. package/dist/modes/interactive/runtime-status-controller.d.ts.map +1 -0
  80. package/dist/modes/interactive/runtime-status-controller.js +147 -0
  81. package/dist/modes/interactive/runtime-status-controller.js.map +1 -0
  82. package/dist/modes/interactive/runtime-status.d.ts +15 -0
  83. package/dist/modes/interactive/runtime-status.d.ts.map +1 -0
  84. package/dist/modes/interactive/runtime-status.js +18 -0
  85. package/dist/modes/interactive/runtime-status.js.map +1 -0
  86. package/docs/json.md +1 -1
  87. package/docs/keybindings.md +2 -1
  88. package/docs/session-format.md +59 -4
  89. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  90. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  91. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  92. package/examples/extensions/sandbox/package-lock.json +2 -2
  93. package/examples/extensions/sandbox/package.json +1 -1
  94. package/examples/extensions/with-deps/package-lock.json +2 -2
  95. package/examples/extensions/with-deps/package.json +1 -1
  96. package/npm-shrinkwrap.json +12 -12
  97. package/package.json +4 -4
@@ -7,13 +7,11 @@ export declare class AssistantMessageComponent extends Container {
7
7
  private contentContainer;
8
8
  private hideThinkingBlock;
9
9
  private markdownTheme;
10
- private hiddenThinkingLabel;
11
10
  private lastMessage?;
12
11
  private hasToolCalls;
13
- constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, markdownTheme?: MarkdownTheme, hiddenThinkingLabel?: string);
12
+ constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, markdownTheme?: MarkdownTheme);
14
13
  invalidate(): void;
15
14
  setHideThinkingBlock(hide: boolean): void;
16
- setHiddenThinkingLabel(label: string): void;
17
15
  render(width: number): string[];
18
16
  updateContent(message: AssistantMessage): void;
19
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AAO3F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EAenC;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAgF7C;CACD"}
1
+ {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AAO3F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EAcjD;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CA4E7C;CACD"}
@@ -7,12 +7,11 @@ const OSC133_ZONE_FINAL = "\x1b]133;C\x07";
7
7
  * Component that renders a complete assistant message
8
8
  */
9
9
  export class AssistantMessageComponent extends Container {
10
- constructor(message, hideThinkingBlock = false, markdownTheme = getMarkdownTheme(), hiddenThinkingLabel = "Thinking...") {
10
+ constructor(message, hideThinkingBlock = false, markdownTheme = getMarkdownTheme()) {
11
11
  super();
12
12
  this.hasToolCalls = false;
13
13
  this.hideThinkingBlock = hideThinkingBlock;
14
14
  this.markdownTheme = markdownTheme;
15
- this.hiddenThinkingLabel = hiddenThinkingLabel;
16
15
  // Container for text/thinking content
17
16
  this.contentContainer = new Container();
18
17
  this.addChild(this.contentContainer);
@@ -32,12 +31,6 @@ export class AssistantMessageComponent extends Container {
32
31
  this.updateContent(this.lastMessage);
33
32
  }
34
33
  }
35
- setHiddenThinkingLabel(label) {
36
- this.hiddenThinkingLabel = label;
37
- if (this.lastMessage) {
38
- this.updateContent(this.lastMessage);
39
- }
40
- }
41
34
  render(width) {
42
35
  const lines = super.render(width);
43
36
  if (this.hasToolCalls || lines.length === 0) {
@@ -51,7 +44,8 @@ export class AssistantMessageComponent extends Container {
51
44
  this.lastMessage = message;
52
45
  // Clear content container
53
46
  this.contentContainer.clear();
54
- const hasVisibleContent = message.content.some((c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()));
47
+ const hasVisibleContent = message.content.some((c) => (c.type === "text" && c.text.trim()) ||
48
+ (!this.hideThinkingBlock && c.type === "thinking" && c.thinking.trim()));
55
49
  if (hasVisibleContent) {
56
50
  this.contentContainer.addChild(new Spacer(1));
57
51
  }
@@ -78,22 +72,18 @@ export class AssistantMessageComponent extends Container {
78
72
  continue;
79
73
  // Add spacing only when another visible assistant content block follows.
80
74
  // This avoids a superfluous blank line before separately-rendered tool execution blocks.
81
- const hasVisibleContentAfter = message.content
82
- .slice(i + 1)
83
- .some((c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()));
84
- if (this.hideThinkingBlock) {
85
- // Show one static label for each adjacent run of thinking blocks.
86
- this.contentContainer.addChild(new Text(theme.italic(theme.fg("thinkingText", this.hiddenThinkingLabel)), 1, 0));
87
- }
88
- else {
75
+ if (!this.hideThinkingBlock) {
76
+ const hasVisibleContentAfter = message.content
77
+ .slice(i + 1)
78
+ .some((c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()));
89
79
  // Adjacent thinking blocks form one section instead of repeated visual chrome.
90
80
  this.contentContainer.addChild(new Markdown(thinkingBlocks.join("\n\n"), 1, 0, this.markdownTheme, {
91
81
  color: (text) => theme.fg("thinkingText", text),
92
82
  italic: true,
93
83
  }));
94
- }
95
- if (hasVisibleContentAfter) {
96
- this.contentContainer.addChild(new Spacer(1));
84
+ if (hasVisibleContentAfter) {
85
+ this.contentContainer.addChild(new Spacer(1));
86
+ }
97
87
  }
98
88
  }
99
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\") {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") break;\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) thinkingBlocks.push(thinking);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t\tif (thinkingBlocks.length === 0) continue;\n\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show one static label for each adjacent run of thinking blocks.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Adjacent thinking blocks form one section instead of repeated visual chrome.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(thinkingBlocks.join(\"\\n\\n\"), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) =>\n\t\t\t\t(c.type === \"text\" && c.text.trim()) ||\n\t\t\t\t(!this.hideThinkingBlock && c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\") {\n\t\t\t\tconst thinkingBlocks: string[] = [];\n\t\t\t\tfor (; i < message.content.length; i++) {\n\t\t\t\t\tconst thinkingContent = message.content[i];\n\t\t\t\t\tif (thinkingContent.type !== \"thinking\") break;\n\t\t\t\t\tconst thinking = thinkingContent.thinking.trim();\n\t\t\t\t\tif (thinking) thinkingBlocks.push(thinking);\n\t\t\t\t}\n\t\t\t\ti--;\n\t\t\t\tif (thinkingBlocks.length === 0) continue;\n\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tif (!this.hideThinkingBlock) {\n\t\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\t\t\t\t\t// Adjacent thinking blocks form one section instead of repeated visual chrome.\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(thinkingBlocks.join(\"\\n\\n\"), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -6,6 +6,7 @@ export declare class ToolGroupComponent implements Component {
6
6
  private expanded;
7
7
  constructor(toolGroup: string, tools?: ToolExecutionComponent[]);
8
8
  addTool(tool: ToolExecutionComponent): void;
9
+ canAccept(tool: ToolExecutionComponent): boolean;
9
10
  removeTool(tool: ToolExecutionComponent): boolean;
10
11
  getToolCount(): number;
11
12
  getOnlyTool(): ToolExecutionComponent | undefined;
@@ -14,6 +15,8 @@ export declare class ToolGroupComponent implements Component {
14
15
  setImageWidthCells(width: number): void;
15
16
  invalidate(): void;
16
17
  render(width: number): string[];
18
+ private isCommandGroup;
19
+ private renderCommandGroup;
17
20
  private renderCollapsed;
18
21
  private formatCountLine;
19
22
  private formatFileSnippet;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-group.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,SAAS,EAAiC,MAAM,oBAAoB,CAAC;AAIxF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA0ClE,qBAAa,kBAAmB,YAAW,SAAS;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,sBAAsB,EAAO,EAGlE;IAED,OAAO,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,CAG1C;IAED,UAAU,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAKhD;IAED,YAAY,IAAI,MAAM,CAErB;IAED,WAAW,IAAI,sBAAsB,GAAG,SAAS,CAEhD;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAED,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAEjC;IAED,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEtC;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAU9B;IAED,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,kBAAkB;CAM1B"}
1
+ {"version":3,"file":"tool-group.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,SAAS,EAAiC,MAAM,oBAAoB,CAAC;AAIxF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA2ClE,qBAAa,kBAAmB,YAAW,SAAS;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,sBAAsB,EAAO,EAGlE;IAED,OAAO,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,CAG1C;IAED,SAAS,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAI/C;IAED,UAAU,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAKhD;IAED,YAAY,IAAI,MAAM,CAErB;IAED,WAAW,IAAI,sBAAsB,GAAG,SAAS,CAEhD;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAED,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAEjC;IAED,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEtC;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAW9B;IAED,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,kBAAkB;CAM1B"}
@@ -3,6 +3,7 @@ import { shortenPath } from "../../../core/tools/render-utils.js";
3
3
  import { theme } from "../theme/theme.js";
4
4
  import { keyText } from "./keybinding-hints.js";
5
5
  const COLLAPSED_FILE_SNIPPET = 3;
6
+ const MAX_COMPACT_COMMANDS = 32;
6
7
  /** Human nouns for collapsed group headers. Keys are toolGroup ids, not raw tool names. */
7
8
  const GROUP_NOUNS = {
8
9
  task_steps: { singular: "Task Step", plural: "Task Steps" },
@@ -52,6 +53,13 @@ export class ToolGroupComponent {
52
53
  tool.setExpanded(this.expanded);
53
54
  this.tools.push(tool);
54
55
  }
56
+ canAccept(tool) {
57
+ if (tool.toolGroup?.trim() !== this.toolGroup)
58
+ return false;
59
+ if (!this.isCommandGroup(tool))
60
+ return true;
61
+ return this.tools.length < MAX_COMPACT_COMMANDS;
62
+ }
55
63
  removeTool(tool) {
56
64
  const index = this.tools.indexOf(tool);
57
65
  if (index === -1)
@@ -88,6 +96,8 @@ export class ToolGroupComponent {
88
96
  const safeWidth = Math.max(1, width);
89
97
  if (this.expanded)
90
98
  return this.tools.flatMap((tool) => tool.render(safeWidth));
99
+ if (this.isCommandGroup())
100
+ return this.renderCommandGroup(safeWidth);
91
101
  const collapsed = this.renderCollapsed(safeWidth);
92
102
  if (collapsed.length === 0)
93
103
  return [];
@@ -95,6 +105,21 @@ export class ToolGroupComponent {
95
105
  box.addChild({ render: (contentWidth) => this.renderCollapsed(contentWidth), invalidate: () => { } });
96
106
  return [" ".repeat(safeWidth), ...box.render(safeWidth)];
97
107
  }
108
+ isCommandGroup(candidate) {
109
+ return (this.toolGroup === "bash" &&
110
+ this.tools.every((tool) => tool.getToolName() === "bash") &&
111
+ (candidate === undefined || candidate.getToolName() === "bash"));
112
+ }
113
+ renderCommandGroup(width) {
114
+ const total = this.tools.length;
115
+ const pending = this.tools.filter((tool) => tool.isToolPartial()).length;
116
+ const failed = this.tools.filter((tool) => tool.isToolError()).length;
117
+ const status = pending > 0 ? "Running" : "Ran";
118
+ const noun = total === 1 ? "command" : "commands";
119
+ const failureSuffix = failed > 0 ? ` · ${failed} failed` : "";
120
+ const summary = `${theme.fg(failed > 0 ? "error" : pending > 0 ? "accent" : "success", "•")} ${theme.bold(`${status} ${total} ${noun}`)}${theme.fg("dim", `${failureSuffix} · ${keyText("app.transcript.open")} to view transcript`)}`;
121
+ return [truncateToWidth(summary, width, "...")];
122
+ }
98
123
  renderCollapsed(width) {
99
124
  const safeWidth = Math.max(1, width);
100
125
  const lines = [this.formatCountLine(), ...this.formatFileSnippet(), ...this.formatLastAction()].filter((line) => line.trim().length > 0);
@@ -1 +1 @@
1
- {"version":3,"file":"tool-group.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-group.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, truncateToWidth, visibleWidth } from \"@caupulican/pi-tui\";\nimport { shortenPath } from \"../../../core/tools/render-utils.ts\";\nimport { type ThemeBg, theme } from \"../theme/theme.ts\";\nimport { keyText } from \"./keybinding-hints.ts\";\nimport type { ToolExecutionComponent } from \"./tool-execution.ts\";\n\nconst COLLAPSED_FILE_SNIPPET = 3;\n\n/** Human nouns for collapsed group headers. Keys are toolGroup ids, not raw tool names. */\nconst GROUP_NOUNS: Record<string, { singular: string; plural: string }> = {\n\ttask_steps: { singular: \"Task Step\", plural: \"Task Steps\" },\n\tpipeline: { singular: \"Pipeline\", plural: \"Pipelines\" },\n\tskills: { singular: \"Skill\", plural: \"Skills\" },\n\tdelegate: { singular: \"Worker\", plural: \"Workers\" },\n\texplore: { singular: \"Search\", plural: \"Searches\" },\n};\n\nfunction plural(count: number, singular: string, pluralForm = `${singular}s`): string {\n\treturn `${count} ${count === 1 ? singular : pluralForm}`;\n}\n\nfunction humanizeGroupKey(raw: string): { singular: string; plural: string } {\n\tconst words = raw\n\t\t.replace(/[_-]+/g, \" \")\n\t\t.trim()\n\t\t.split(/\\s+/)\n\t\t.filter(Boolean)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n\tconst last = words.at(-1) ?? \"Tool\";\n\tconst lastSingular = last.endsWith(\"s\") && last.length > 1 ? last.slice(0, -1) : last;\n\tconst lastPlural = last.endsWith(\"s\") ? last : `${last}s`;\n\treturn {\n\t\tsingular: [...words.slice(0, -1), lastSingular].join(\" \"),\n\t\tplural: [...words.slice(0, -1), lastPlural].join(\" \"),\n\t};\n}\n\nfunction groupNoun(groupKey: string, tools: readonly ToolExecutionComponent[]): { singular: string; plural: string } {\n\tconst mapped = GROUP_NOUNS[groupKey];\n\tif (mapped) return mapped;\n\tconst labels = [...new Set(tools.map((tool) => tool.getDisplayLabel()).filter((label) => label.length > 0))];\n\tif (labels.length === 1) return humanizeGroupKey(labels[0]);\n\tif (groupKey) return humanizeGroupKey(groupKey);\n\treturn { singular: \"Tool\", plural: \"Tools\" };\n}\n\nexport class ToolGroupComponent implements Component {\n\treadonly toolGroup: string;\n\tprivate readonly tools: ToolExecutionComponent[] = [];\n\tprivate expanded = false;\n\n\tconstructor(toolGroup: string, tools: ToolExecutionComponent[] = []) {\n\t\tthis.toolGroup = toolGroup;\n\t\tfor (const tool of tools) this.addTool(tool);\n\t}\n\n\taddTool(tool: ToolExecutionComponent): void {\n\t\ttool.setExpanded(this.expanded);\n\t\tthis.tools.push(tool);\n\t}\n\n\tremoveTool(tool: ToolExecutionComponent): boolean {\n\t\tconst index = this.tools.indexOf(tool);\n\t\tif (index === -1) return false;\n\t\tthis.tools.splice(index, 1);\n\t\treturn true;\n\t}\n\n\tgetToolCount(): number {\n\t\treturn this.tools.length;\n\t}\n\n\tgetOnlyTool(): ToolExecutionComponent | undefined {\n\t\treturn this.tools.length === 1 ? this.tools[0] : undefined;\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tfor (const tool of this.tools) tool.setExpanded(expanded);\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tfor (const tool of this.tools) tool.setShowImages(show);\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tfor (const tool of this.tools) tool.setImageWidthCells(width);\n\t}\n\n\tinvalidate(): void {\n\t\tfor (const tool of this.tools) tool.invalidate();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.tools.length === 0) return [];\n\t\tconst safeWidth = Math.max(1, width);\n\t\tif (this.expanded) return this.tools.flatMap((tool) => tool.render(safeWidth));\n\n\t\tconst collapsed = this.renderCollapsed(safeWidth);\n\t\tif (collapsed.length === 0) return [];\n\t\tconst box = new Box(1, 1, (text) => theme.bg(this.getBackgroundColor(), text));\n\t\tbox.addChild({ render: (contentWidth) => this.renderCollapsed(contentWidth), invalidate: () => {} });\n\t\treturn [\" \".repeat(safeWidth), ...box.render(safeWidth)];\n\t}\n\n\tprivate renderCollapsed(width: number): string[] {\n\t\tconst safeWidth = Math.max(1, width);\n\t\tconst lines = [this.formatCountLine(), ...this.formatFileSnippet(), ...this.formatLastAction()].filter(\n\t\t\t(line) => line.trim().length > 0,\n\t\t);\n\t\tif (lines.length === 0) return [];\n\t\tlines[lines.length - 1] = this.appendExpandHint(lines[lines.length - 1], safeWidth);\n\t\treturn lines.map((line) => truncateToWidth(line, safeWidth, \"...\"));\n\t}\n\n\tprivate formatCountLine(): string {\n\t\tconst editCount = this.tools.filter((tool) => tool.getToolName() === \"edit\").length;\n\t\tconst writeCount = this.tools.filter((tool) => tool.getToolName() === \"write\").length;\n\t\tconst errorCount = this.tools.filter((tool) => tool.isToolError()).length;\n\t\tconst files = this.uniqueFiles();\n\t\tconst parts: string[] = [];\n\t\tif (editCount > 0) parts.push(plural(editCount, \"edit\"));\n\t\tif (writeCount > 0) parts.push(plural(writeCount, \"write\"));\n\t\tif (parts.length === 0) {\n\t\t\tconst noun = groupNoun(this.toolGroup, this.tools);\n\t\t\tparts.push(plural(this.tools.length, noun.singular, noun.plural));\n\t\t}\n\t\tif (files.length > 0) parts.push(plural(files.length, \"file\"));\n\t\tif (errorCount > 0) parts.push(plural(errorCount, \"error\"));\n\t\treturn theme.bold(parts.join(\" · \"));\n\t}\n\n\tprivate formatFileSnippet(): string[] {\n\t\tconst files = this.uniqueFiles();\n\t\tif (files.length === 0) return [];\n\t\tconst shown = files.slice(0, COLLAPSED_FILE_SNIPPET);\n\t\tconst extra = files.length - shown.length;\n\t\tconst list = shown.join(\", \") + (extra > 0 ? `, +${extra}` : \"\");\n\t\treturn [theme.fg(\"dim\", list)];\n\t}\n\n\tprivate formatLastAction(): string[] {\n\t\tconst last = [...this.tools].reverse().find((tool) => tool.isToolSuccess()) ?? this.tools[this.tools.length - 1];\n\t\tif (!last) return [];\n\t\tconst path = last.getDisplayPath();\n\t\tconst name = last.getDisplayLabel();\n\t\tconst label = path ? `${name} ${shortenPath(path)}` : name;\n\t\treturn [`${theme.fg(\"dim\", \"last: \")}${label}`];\n\t}\n\n\tprivate uniqueFiles(): string[] {\n\t\tconst seen = new Set<string>();\n\t\tconst files: string[] = [];\n\t\tfor (const tool of this.tools) {\n\t\t\tconst path = tool.getDisplayPath();\n\t\t\tif (!path) continue;\n\t\t\tconst display = shortenPath(path);\n\t\t\tif (seen.has(display)) continue;\n\t\t\tseen.add(display);\n\t\t\tfiles.push(display);\n\t\t}\n\t\treturn files;\n\t}\n\n\tprivate appendExpandHint(line: string, width: number): string {\n\t\tconst hint = theme.fg(\"dim\", ` (${keyText(\"app.tools.expand\")} to expand)`);\n\t\tconst hintWidth = visibleWidth(hint);\n\t\tif (hintWidth >= width) return truncateToWidth(hint, width, \"...\");\n\t\treturn truncateToWidth(line, width - hintWidth, \"\") + hint;\n\t}\n\n\tprivate getBackgroundColor(): ThemeBg {\n\t\tconst colors = this.tools.map((tool) => tool.getBackgroundColor());\n\t\tif (colors.includes(\"toolErrorBg\")) return \"toolErrorBg\";\n\t\tif (colors.includes(\"toolPendingBg\")) return \"toolPendingBg\";\n\t\treturn \"toolSuccessBg\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"tool-group.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-group.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, truncateToWidth, visibleWidth } from \"@caupulican/pi-tui\";\nimport { shortenPath } from \"../../../core/tools/render-utils.ts\";\nimport { type ThemeBg, theme } from \"../theme/theme.ts\";\nimport { keyText } from \"./keybinding-hints.ts\";\nimport type { ToolExecutionComponent } from \"./tool-execution.ts\";\n\nconst COLLAPSED_FILE_SNIPPET = 3;\nconst MAX_COMPACT_COMMANDS = 32;\n\n/** Human nouns for collapsed group headers. Keys are toolGroup ids, not raw tool names. */\nconst GROUP_NOUNS: Record<string, { singular: string; plural: string }> = {\n\ttask_steps: { singular: \"Task Step\", plural: \"Task Steps\" },\n\tpipeline: { singular: \"Pipeline\", plural: \"Pipelines\" },\n\tskills: { singular: \"Skill\", plural: \"Skills\" },\n\tdelegate: { singular: \"Worker\", plural: \"Workers\" },\n\texplore: { singular: \"Search\", plural: \"Searches\" },\n};\n\nfunction plural(count: number, singular: string, pluralForm = `${singular}s`): string {\n\treturn `${count} ${count === 1 ? singular : pluralForm}`;\n}\n\nfunction humanizeGroupKey(raw: string): { singular: string; plural: string } {\n\tconst words = raw\n\t\t.replace(/[_-]+/g, \" \")\n\t\t.trim()\n\t\t.split(/\\s+/)\n\t\t.filter(Boolean)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n\tconst last = words.at(-1) ?? \"Tool\";\n\tconst lastSingular = last.endsWith(\"s\") && last.length > 1 ? last.slice(0, -1) : last;\n\tconst lastPlural = last.endsWith(\"s\") ? last : `${last}s`;\n\treturn {\n\t\tsingular: [...words.slice(0, -1), lastSingular].join(\" \"),\n\t\tplural: [...words.slice(0, -1), lastPlural].join(\" \"),\n\t};\n}\n\nfunction groupNoun(groupKey: string, tools: readonly ToolExecutionComponent[]): { singular: string; plural: string } {\n\tconst mapped = GROUP_NOUNS[groupKey];\n\tif (mapped) return mapped;\n\tconst labels = [...new Set(tools.map((tool) => tool.getDisplayLabel()).filter((label) => label.length > 0))];\n\tif (labels.length === 1) return humanizeGroupKey(labels[0]);\n\tif (groupKey) return humanizeGroupKey(groupKey);\n\treturn { singular: \"Tool\", plural: \"Tools\" };\n}\n\nexport class ToolGroupComponent implements Component {\n\treadonly toolGroup: string;\n\tprivate readonly tools: ToolExecutionComponent[] = [];\n\tprivate expanded = false;\n\n\tconstructor(toolGroup: string, tools: ToolExecutionComponent[] = []) {\n\t\tthis.toolGroup = toolGroup;\n\t\tfor (const tool of tools) this.addTool(tool);\n\t}\n\n\taddTool(tool: ToolExecutionComponent): void {\n\t\ttool.setExpanded(this.expanded);\n\t\tthis.tools.push(tool);\n\t}\n\n\tcanAccept(tool: ToolExecutionComponent): boolean {\n\t\tif (tool.toolGroup?.trim() !== this.toolGroup) return false;\n\t\tif (!this.isCommandGroup(tool)) return true;\n\t\treturn this.tools.length < MAX_COMPACT_COMMANDS;\n\t}\n\n\tremoveTool(tool: ToolExecutionComponent): boolean {\n\t\tconst index = this.tools.indexOf(tool);\n\t\tif (index === -1) return false;\n\t\tthis.tools.splice(index, 1);\n\t\treturn true;\n\t}\n\n\tgetToolCount(): number {\n\t\treturn this.tools.length;\n\t}\n\n\tgetOnlyTool(): ToolExecutionComponent | undefined {\n\t\treturn this.tools.length === 1 ? this.tools[0] : undefined;\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tfor (const tool of this.tools) tool.setExpanded(expanded);\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tfor (const tool of this.tools) tool.setShowImages(show);\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tfor (const tool of this.tools) tool.setImageWidthCells(width);\n\t}\n\n\tinvalidate(): void {\n\t\tfor (const tool of this.tools) tool.invalidate();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.tools.length === 0) return [];\n\t\tconst safeWidth = Math.max(1, width);\n\t\tif (this.expanded) return this.tools.flatMap((tool) => tool.render(safeWidth));\n\t\tif (this.isCommandGroup()) return this.renderCommandGroup(safeWidth);\n\n\t\tconst collapsed = this.renderCollapsed(safeWidth);\n\t\tif (collapsed.length === 0) return [];\n\t\tconst box = new Box(1, 1, (text) => theme.bg(this.getBackgroundColor(), text));\n\t\tbox.addChild({ render: (contentWidth) => this.renderCollapsed(contentWidth), invalidate: () => {} });\n\t\treturn [\" \".repeat(safeWidth), ...box.render(safeWidth)];\n\t}\n\n\tprivate isCommandGroup(candidate?: ToolExecutionComponent): boolean {\n\t\treturn (\n\t\t\tthis.toolGroup === \"bash\" &&\n\t\t\tthis.tools.every((tool) => tool.getToolName() === \"bash\") &&\n\t\t\t(candidate === undefined || candidate.getToolName() === \"bash\")\n\t\t);\n\t}\n\n\tprivate renderCommandGroup(width: number): string[] {\n\t\tconst total = this.tools.length;\n\t\tconst pending = this.tools.filter((tool) => tool.isToolPartial()).length;\n\t\tconst failed = this.tools.filter((tool) => tool.isToolError()).length;\n\t\tconst status = pending > 0 ? \"Running\" : \"Ran\";\n\t\tconst noun = total === 1 ? \"command\" : \"commands\";\n\t\tconst failureSuffix = failed > 0 ? ` · ${failed} failed` : \"\";\n\t\tconst summary = `${theme.fg(failed > 0 ? \"error\" : pending > 0 ? \"accent\" : \"success\", \"•\")} ${theme.bold(`${status} ${total} ${noun}`)}${theme.fg(\"dim\", `${failureSuffix} · ${keyText(\"app.transcript.open\")} to view transcript`)}`;\n\t\treturn [truncateToWidth(summary, width, \"...\")];\n\t}\n\n\tprivate renderCollapsed(width: number): string[] {\n\t\tconst safeWidth = Math.max(1, width);\n\t\tconst lines = [this.formatCountLine(), ...this.formatFileSnippet(), ...this.formatLastAction()].filter(\n\t\t\t(line) => line.trim().length > 0,\n\t\t);\n\t\tif (lines.length === 0) return [];\n\t\tlines[lines.length - 1] = this.appendExpandHint(lines[lines.length - 1], safeWidth);\n\t\treturn lines.map((line) => truncateToWidth(line, safeWidth, \"...\"));\n\t}\n\n\tprivate formatCountLine(): string {\n\t\tconst editCount = this.tools.filter((tool) => tool.getToolName() === \"edit\").length;\n\t\tconst writeCount = this.tools.filter((tool) => tool.getToolName() === \"write\").length;\n\t\tconst errorCount = this.tools.filter((tool) => tool.isToolError()).length;\n\t\tconst files = this.uniqueFiles();\n\t\tconst parts: string[] = [];\n\t\tif (editCount > 0) parts.push(plural(editCount, \"edit\"));\n\t\tif (writeCount > 0) parts.push(plural(writeCount, \"write\"));\n\t\tif (parts.length === 0) {\n\t\t\tconst noun = groupNoun(this.toolGroup, this.tools);\n\t\t\tparts.push(plural(this.tools.length, noun.singular, noun.plural));\n\t\t}\n\t\tif (files.length > 0) parts.push(plural(files.length, \"file\"));\n\t\tif (errorCount > 0) parts.push(plural(errorCount, \"error\"));\n\t\treturn theme.bold(parts.join(\" · \"));\n\t}\n\n\tprivate formatFileSnippet(): string[] {\n\t\tconst files = this.uniqueFiles();\n\t\tif (files.length === 0) return [];\n\t\tconst shown = files.slice(0, COLLAPSED_FILE_SNIPPET);\n\t\tconst extra = files.length - shown.length;\n\t\tconst list = shown.join(\", \") + (extra > 0 ? `, +${extra}` : \"\");\n\t\treturn [theme.fg(\"dim\", list)];\n\t}\n\n\tprivate formatLastAction(): string[] {\n\t\tconst last = [...this.tools].reverse().find((tool) => tool.isToolSuccess()) ?? this.tools[this.tools.length - 1];\n\t\tif (!last) return [];\n\t\tconst path = last.getDisplayPath();\n\t\tconst name = last.getDisplayLabel();\n\t\tconst label = path ? `${name} ${shortenPath(path)}` : name;\n\t\treturn [`${theme.fg(\"dim\", \"last: \")}${label}`];\n\t}\n\n\tprivate uniqueFiles(): string[] {\n\t\tconst seen = new Set<string>();\n\t\tconst files: string[] = [];\n\t\tfor (const tool of this.tools) {\n\t\t\tconst path = tool.getDisplayPath();\n\t\t\tif (!path) continue;\n\t\t\tconst display = shortenPath(path);\n\t\t\tif (seen.has(display)) continue;\n\t\t\tseen.add(display);\n\t\t\tfiles.push(display);\n\t\t}\n\t\treturn files;\n\t}\n\n\tprivate appendExpandHint(line: string, width: number): string {\n\t\tconst hint = theme.fg(\"dim\", ` (${keyText(\"app.tools.expand\")} to expand)`);\n\t\tconst hintWidth = visibleWidth(hint);\n\t\tif (hintWidth >= width) return truncateToWidth(hint, width, \"...\");\n\t\treturn truncateToWidth(line, width - hintWidth, \"\") + hint;\n\t}\n\n\tprivate getBackgroundColor(): ThemeBg {\n\t\tconst colors = this.tools.map((tool) => tool.getBackgroundColor());\n\t\tif (colors.includes(\"toolErrorBg\")) return \"toolErrorBg\";\n\t\tif (colors.includes(\"toolPendingBg\")) return \"toolPendingBg\";\n\t\treturn \"toolSuccessBg\";\n\t}\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { Component, OverlayHandle, OverlayOptions } from "@caupulican/pi-tui";
2
+ import type { KeybindingsManager } from "../../../core/keybindings.ts";
3
+ export interface TranscriptOverlayOptions {
4
+ source: Component;
5
+ viewportRows: () => number;
6
+ keybindings: KeybindingsManager;
7
+ getToolsExpanded: () => boolean;
8
+ setToolsExpanded: (expanded: boolean) => void;
9
+ showOverlay: (component: Component, options: OverlayOptions) => OverlayHandle;
10
+ }
11
+ /** Owns the expanded transcript overlay and restores the caller's tool-detail state exactly once. */
12
+ export declare function openTranscriptOverlay(options: TranscriptOverlayOptions): OverlayHandle;
13
+ //# sourceMappingURL=transcript-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-overlay.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/transcript-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,WAAW,EAAE,kBAAkB,CAAC;IAChC,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,KAAK,aAAa,CAAC;CAC9E;AAED,qGAAqG;AACrG,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa,CA8BtF"}
@@ -0,0 +1,35 @@
1
+ import { TranscriptPager } from "./transcript-pager.js";
2
+ /** Owns the expanded transcript overlay and restores the caller's tool-detail state exactly once. */
3
+ export function openTranscriptOverlay(options) {
4
+ const previousToolsExpanded = options.getToolsExpanded();
5
+ let handle;
6
+ let restored = false;
7
+ const restoreToolState = () => {
8
+ if (restored)
9
+ return;
10
+ restored = true;
11
+ options.setToolsExpanded(previousToolsExpanded);
12
+ };
13
+ const pager = new TranscriptPager({
14
+ source: options.source,
15
+ viewportRows: options.viewportRows,
16
+ keybindings: options.keybindings,
17
+ onClose: () => handle?.hide(),
18
+ });
19
+ options.setToolsExpanded(true);
20
+ try {
21
+ handle = options.showOverlay(pager, {
22
+ width: "100%",
23
+ maxHeight: "100%",
24
+ row: 0,
25
+ col: 0,
26
+ onRemove: restoreToolState,
27
+ });
28
+ return handle;
29
+ }
30
+ catch (error) {
31
+ restoreToolState();
32
+ throw error;
33
+ }
34
+ }
35
+ //# sourceMappingURL=transcript-overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-overlay.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/transcript-overlay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAWxD,qGAAqG;AACrG,MAAM,UAAU,qBAAqB,CAAC,OAAiC;IACtE,MAAM,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACzD,IAAI,MAAiC,CAAC;IACtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,gBAAgB,GAAG,GAAG,EAAE;QAC7B,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;IACjD,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC;QACjC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE;KAC7B,CAAC,CAAC;IAEH,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC;QACJ,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE;YACnC,KAAK,EAAE,MAAM;YACb,SAAS,EAAE,MAAM;YACjB,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,CAAC;YACN,QAAQ,EAAE,gBAAgB;SAC1B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,gBAAgB,EAAE,CAAC;QACnB,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC","sourcesContent":["import type { Component, OverlayHandle, OverlayOptions } from \"@caupulican/pi-tui\";\nimport type { KeybindingsManager } from \"../../../core/keybindings.ts\";\nimport { TranscriptPager } from \"./transcript-pager.ts\";\n\nexport interface TranscriptOverlayOptions {\n\tsource: Component;\n\tviewportRows: () => number;\n\tkeybindings: KeybindingsManager;\n\tgetToolsExpanded: () => boolean;\n\tsetToolsExpanded: (expanded: boolean) => void;\n\tshowOverlay: (component: Component, options: OverlayOptions) => OverlayHandle;\n}\n\n/** Owns the expanded transcript overlay and restores the caller's tool-detail state exactly once. */\nexport function openTranscriptOverlay(options: TranscriptOverlayOptions): OverlayHandle {\n\tconst previousToolsExpanded = options.getToolsExpanded();\n\tlet handle: OverlayHandle | undefined;\n\tlet restored = false;\n\tconst restoreToolState = () => {\n\t\tif (restored) return;\n\t\trestored = true;\n\t\toptions.setToolsExpanded(previousToolsExpanded);\n\t};\n\tconst pager = new TranscriptPager({\n\t\tsource: options.source,\n\t\tviewportRows: options.viewportRows,\n\t\tkeybindings: options.keybindings,\n\t\tonClose: () => handle?.hide(),\n\t});\n\n\toptions.setToolsExpanded(true);\n\ttry {\n\t\thandle = options.showOverlay(pager, {\n\t\t\twidth: \"100%\",\n\t\t\tmaxHeight: \"100%\",\n\t\t\trow: 0,\n\t\t\tcol: 0,\n\t\t\tonRemove: restoreToolState,\n\t\t});\n\t\treturn handle;\n\t} catch (error) {\n\t\trestoreToolState();\n\t\tthrow error;\n\t}\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { SessionTreeNode } from "@caupulican/pi-agent-core/node";
1
+ import { type SessionTreeNode } from "@caupulican/pi-agent-core/node";
2
2
  import { type Component, Container, type Focusable } from "@caupulican/pi-tui";
3
3
  /** Filter mode for tree display */
4
4
  export type FilterMode = "default" | "no-tools" | "user-only" | "labeled-only" | "all";
@@ -1 +1 @@
1
- {"version":3,"file":"tree-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tree-selector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tree-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tree-selector.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { isSessionLifecycleEntry } from "@caupulican/pi-agent-core/node";
1
2
  import { Container, getKeybindings, Input, Spacer, Text, TruncatedText, truncateToWidth, } from "@caupulican/pi-tui";
2
3
  import { buildActivePathIds, buildTreePrefix, extractTextContent, flattenSessionTree, formatTreeToolCall, hasTextContent, recalculateVisibleTreeLayout, } from "../../../core/export-html/session-tree-foundations.mjs";
3
4
  import { theme } from "../theme/theme.js";
@@ -111,11 +112,13 @@ class TreeList {
111
112
  // Apply filter mode
112
113
  let passesFilter = true;
113
114
  // Entry types hidden in default view (settings/bookkeeping)
115
+ const isLifecycleEntry = isSessionLifecycleEntry(entry);
114
116
  const isSettingsEntry = entry.type === "label" ||
115
117
  entry.type === "custom" ||
116
118
  entry.type === "model_change" ||
117
119
  entry.type === "thinking_level_change" ||
118
- entry.type === "session_info";
120
+ entry.type === "session_info" ||
121
+ isLifecycleEntry;
119
122
  switch (this.filterMode) {
120
123
  case "user-only":
121
124
  // Just user messages
@@ -127,11 +130,11 @@ class TreeList {
127
130
  break;
128
131
  case "labeled-only":
129
132
  // Just labeled entries
130
- passesFilter = flatNode.node.label !== undefined;
133
+ passesFilter = !isLifecycleEntry && flatNode.node.label !== undefined;
131
134
  break;
132
135
  case "all":
133
- // Show everything
134
- passesFilter = true;
136
+ // Show all user-facing entries; lifecycle records remain internal bookkeeping.
137
+ passesFilter = !isLifecycleEntry;
135
138
  break;
136
139
  default:
137
140
  // Default mode: hide settings/bookkeeping entries