@esso0428/pi-subagents 0.15.6 → 0.15.8

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 (217) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/agent-history-list.d.ts +1 -0
  3. package/dist/agent-history-list.d.ts.map +1 -0
  4. package/dist/agent-history-list.js +1 -0
  5. package/dist/agent-history-list.js.map +1 -0
  6. package/dist/agent-history.d.ts +1 -0
  7. package/dist/agent-history.d.ts.map +1 -0
  8. package/dist/agent-history.js +1 -0
  9. package/dist/agent-history.js.map +1 -0
  10. package/dist/agent-manager.d.ts +2 -0
  11. package/dist/agent-manager.d.ts.map +1 -0
  12. package/dist/agent-manager.js +71 -0
  13. package/dist/agent-manager.js.map +1 -0
  14. package/dist/agent-runner.d.ts +1 -0
  15. package/dist/agent-runner.d.ts.map +1 -0
  16. package/dist/agent-runner.js +8 -0
  17. package/dist/agent-runner.js.map +1 -0
  18. package/dist/agent-types.d.ts +1 -0
  19. package/dist/agent-types.d.ts.map +1 -0
  20. package/dist/agent-types.js +1 -0
  21. package/dist/agent-types.js.map +1 -0
  22. package/dist/context.d.ts +1 -0
  23. package/dist/context.d.ts.map +1 -0
  24. package/dist/context.js +1 -0
  25. package/dist/context.js.map +1 -0
  26. package/dist/cross-extension-rpc.d.ts +1 -0
  27. package/dist/cross-extension-rpc.d.ts.map +1 -0
  28. package/dist/cross-extension-rpc.js +1 -0
  29. package/dist/cross-extension-rpc.js.map +1 -0
  30. package/dist/custom-agents.d.ts +1 -0
  31. package/dist/custom-agents.d.ts.map +1 -0
  32. package/dist/custom-agents.js +1 -0
  33. package/dist/custom-agents.js.map +1 -0
  34. package/dist/default-agents.d.ts +1 -0
  35. package/dist/default-agents.d.ts.map +1 -0
  36. package/dist/default-agents.js +1 -0
  37. package/dist/default-agents.js.map +1 -0
  38. package/dist/enabled-models.d.ts +1 -0
  39. package/dist/enabled-models.d.ts.map +1 -0
  40. package/dist/enabled-models.js +1 -0
  41. package/dist/enabled-models.js.map +1 -0
  42. package/dist/env.d.ts +1 -0
  43. package/dist/env.d.ts.map +1 -0
  44. package/dist/env.js +1 -0
  45. package/dist/env.js.map +1 -0
  46. package/dist/group-join.d.ts +1 -0
  47. package/dist/group-join.d.ts.map +1 -0
  48. package/dist/group-join.js +1 -0
  49. package/dist/group-join.js.map +1 -0
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +37 -10
  53. package/dist/index.js.map +1 -0
  54. package/dist/invocation-config.d.ts +1 -0
  55. package/dist/invocation-config.d.ts.map +1 -0
  56. package/dist/invocation-config.js +1 -0
  57. package/dist/invocation-config.js.map +1 -0
  58. package/dist/memory.d.ts +1 -0
  59. package/dist/memory.d.ts.map +1 -0
  60. package/dist/memory.js +1 -0
  61. package/dist/memory.js.map +1 -0
  62. package/dist/model-resolver.d.ts +1 -0
  63. package/dist/model-resolver.d.ts.map +1 -0
  64. package/dist/model-resolver.js +1 -0
  65. package/dist/model-resolver.js.map +1 -0
  66. package/dist/nico-overrides.d.ts +1 -0
  67. package/dist/nico-overrides.d.ts.map +1 -0
  68. package/dist/nico-overrides.js +1 -0
  69. package/dist/nico-overrides.js.map +1 -0
  70. package/dist/output-file.d.ts +1 -0
  71. package/dist/output-file.d.ts.map +1 -0
  72. package/dist/output-file.js +1 -0
  73. package/dist/output-file.js.map +1 -0
  74. package/dist/prompts.d.ts +1 -0
  75. package/dist/prompts.d.ts.map +1 -0
  76. package/dist/prompts.js +1 -0
  77. package/dist/prompts.js.map +1 -0
  78. package/dist/schedule-store.d.ts +1 -0
  79. package/dist/schedule-store.d.ts.map +1 -0
  80. package/dist/schedule-store.js +1 -0
  81. package/dist/schedule-store.js.map +1 -0
  82. package/dist/schedule.d.ts +1 -0
  83. package/dist/schedule.d.ts.map +1 -0
  84. package/dist/schedule.js +1 -0
  85. package/dist/schedule.js.map +1 -0
  86. package/dist/settings.d.ts +1 -0
  87. package/dist/settings.d.ts.map +1 -0
  88. package/dist/settings.js +1 -0
  89. package/dist/settings.js.map +1 -0
  90. package/dist/skill-loader.d.ts +1 -0
  91. package/dist/skill-loader.d.ts.map +1 -0
  92. package/dist/skill-loader.js +1 -0
  93. package/dist/skill-loader.js.map +1 -0
  94. package/dist/status-note.d.ts +1 -0
  95. package/dist/status-note.d.ts.map +1 -0
  96. package/dist/status-note.js +1 -0
  97. package/dist/status-note.js.map +1 -0
  98. package/dist/types.d.ts +5 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +1 -0
  101. package/dist/types.js.map +1 -0
  102. package/dist/ui/agent-widget.d.ts +1 -0
  103. package/dist/ui/agent-widget.d.ts.map +1 -0
  104. package/dist/ui/agent-widget.js +4 -2
  105. package/dist/ui/agent-widget.js.map +1 -0
  106. package/dist/ui/ccstyle/diff/ansi-utils.d.ts +11 -0
  107. package/dist/ui/ccstyle/diff/ansi-utils.d.ts.map +1 -0
  108. package/dist/ui/ccstyle/diff/ansi-utils.js +145 -0
  109. package/dist/ui/ccstyle/diff/ansi-utils.js.map +1 -0
  110. package/dist/ui/ccstyle/diff/diff-presentation.d.ts +12 -0
  111. package/dist/ui/ccstyle/diff/diff-presentation.d.ts.map +1 -0
  112. package/dist/ui/ccstyle/diff/diff-presentation.js +49 -0
  113. package/dist/ui/ccstyle/diff/diff-presentation.js.map +1 -0
  114. package/dist/ui/ccstyle/diff/diff-renderer.d.ts +46 -0
  115. package/dist/ui/ccstyle/diff/diff-renderer.d.ts.map +1 -0
  116. package/dist/ui/ccstyle/diff/diff-renderer.js +2044 -0
  117. package/dist/ui/ccstyle/diff/diff-renderer.js.map +1 -0
  118. package/dist/ui/ccstyle/diff/line-width-safety.d.ts +12 -0
  119. package/dist/ui/ccstyle/diff/line-width-safety.d.ts.map +1 -0
  120. package/dist/ui/ccstyle/diff/line-width-safety.js +59 -0
  121. package/dist/ui/ccstyle/diff/line-width-safety.js.map +1 -0
  122. package/dist/ui/ccstyle/diff/render-utils.d.ts +6 -0
  123. package/dist/ui/ccstyle/diff/render-utils.d.ts.map +1 -0
  124. package/dist/ui/ccstyle/diff/render-utils.js +25 -0
  125. package/dist/ui/ccstyle/diff/render-utils.js.map +1 -0
  126. package/dist/ui/ccstyle/diff/types.d.ts +22 -0
  127. package/dist/ui/ccstyle/diff/types.d.ts.map +1 -0
  128. package/dist/ui/ccstyle/diff/types.js +10 -0
  129. package/dist/ui/ccstyle/diff/types.js.map +1 -0
  130. package/dist/ui/ccstyle/diff/write-display-utils.d.ts +2 -0
  131. package/dist/ui/ccstyle/diff/write-display-utils.d.ts.map +1 -0
  132. package/dist/ui/ccstyle/diff/write-display-utils.js +12 -0
  133. package/dist/ui/ccstyle/diff/write-display-utils.js.map +1 -0
  134. package/dist/ui/ccstyle/tool-renderer.d.ts +17 -0
  135. package/dist/ui/ccstyle/tool-renderer.d.ts.map +1 -0
  136. package/dist/ui/ccstyle/tool-renderer.js +58 -0
  137. package/dist/ui/ccstyle/tool-renderer.js.map +1 -0
  138. package/dist/ui/ccstyle/tool-result.d.ts +24 -0
  139. package/dist/ui/ccstyle/tool-result.d.ts.map +1 -0
  140. package/dist/ui/ccstyle/tool-result.js +193 -0
  141. package/dist/ui/ccstyle/tool-result.js.map +1 -0
  142. package/dist/ui/conversation-blocks.d.ts +28 -0
  143. package/dist/ui/conversation-blocks.d.ts.map +1 -0
  144. package/dist/ui/conversation-blocks.js +119 -27
  145. package/dist/ui/conversation-blocks.js.map +1 -0
  146. package/dist/ui/conversation-nvim.d.ts +1 -0
  147. package/dist/ui/conversation-nvim.d.ts.map +1 -0
  148. package/dist/ui/conversation-nvim.js +1 -0
  149. package/dist/ui/conversation-nvim.js.map +1 -0
  150. package/dist/ui/conversation-role.d.ts +13 -0
  151. package/dist/ui/conversation-role.d.ts.map +1 -0
  152. package/dist/ui/conversation-role.js +39 -0
  153. package/dist/ui/conversation-role.js.map +1 -0
  154. package/dist/ui/conversation-search.d.ts +1 -0
  155. package/dist/ui/conversation-search.d.ts.map +1 -0
  156. package/dist/ui/conversation-search.js +1 -0
  157. package/dist/ui/conversation-search.js.map +1 -0
  158. package/dist/ui/conversation-timeline.d.ts +62 -0
  159. package/dist/ui/conversation-timeline.d.ts.map +1 -0
  160. package/dist/ui/conversation-timeline.js +266 -0
  161. package/dist/ui/conversation-timeline.js.map +1 -0
  162. package/dist/ui/conversation-viewer.d.ts +7 -1
  163. package/dist/ui/conversation-viewer.d.ts.map +1 -0
  164. package/dist/ui/conversation-viewer.js +96 -54
  165. package/dist/ui/conversation-viewer.js.map +1 -0
  166. package/dist/ui/fleet-list.d.ts +1 -0
  167. package/dist/ui/fleet-list.d.ts.map +1 -0
  168. package/dist/ui/fleet-list.js +1 -0
  169. package/dist/ui/fleet-list.js.map +1 -0
  170. package/dist/ui/schedule-menu.d.ts +1 -0
  171. package/dist/ui/schedule-menu.d.ts.map +1 -0
  172. package/dist/ui/schedule-menu.js +1 -0
  173. package/dist/ui/schedule-menu.js.map +1 -0
  174. package/dist/ui/viewer-keys.d.ts +1 -0
  175. package/dist/ui/viewer-keys.d.ts.map +1 -0
  176. package/dist/ui/viewer-keys.js +1 -0
  177. package/dist/ui/viewer-keys.js.map +1 -0
  178. package/dist/usage.d.ts +1 -0
  179. package/dist/usage.d.ts.map +1 -0
  180. package/dist/usage.js +1 -0
  181. package/dist/usage.js.map +1 -0
  182. package/dist/worktree.d.ts +1 -0
  183. package/dist/worktree.d.ts.map +1 -0
  184. package/dist/worktree.js +1 -0
  185. package/dist/worktree.js.map +1 -0
  186. package/dist/write-execution.d.ts +42 -0
  187. package/dist/write-execution.d.ts.map +1 -0
  188. package/dist/write-execution.js +138 -0
  189. package/dist/write-execution.js.map +1 -0
  190. package/package.json +1 -1
  191. package/src/agent-manager.ts +61 -0
  192. package/src/agent-runner.ts +7 -0
  193. package/src/index.ts +35 -11
  194. package/src/types.ts +4 -0
  195. package/src/ui/agent-widget.ts +2 -1
  196. package/src/ui/ccstyle/ATTRIBUTION.md +37 -0
  197. package/src/ui/ccstyle/diff/ansi-utils.ts +168 -0
  198. package/src/ui/ccstyle/diff/diff-presentation.ts +70 -0
  199. package/src/ui/ccstyle/diff/diff-renderer.ts +3148 -0
  200. package/src/ui/ccstyle/diff/line-width-safety.ts +92 -0
  201. package/src/ui/ccstyle/diff/render-utils.ts +32 -0
  202. package/src/ui/ccstyle/diff/types.ts +33 -0
  203. package/src/ui/ccstyle/diff/write-display-utils.ts +12 -0
  204. package/src/ui/ccstyle/tool-renderer.ts +71 -0
  205. package/src/ui/ccstyle/tool-result.ts +238 -0
  206. package/src/ui/conversation-blocks.ts +160 -26
  207. package/src/ui/conversation-role.ts +45 -0
  208. package/src/ui/conversation-timeline.ts +318 -0
  209. package/src/ui/conversation-viewer.ts +91 -54
  210. package/src/write-execution.ts +180 -0
  211. package/test/output-file-history.test.ts +50 -0
  212. package/test/ui/conversation-blocks.test.ts +31 -0
  213. package/test/ui/conversation-diff.test.ts +91 -0
  214. package/test/ui/conversation-viewer.test.ts +70 -0
  215. package/test/write-execution.test.ts +83 -0
  216. package/tsconfig.json +16 -0
  217. package/vitest.temp.config.mts +6 -0
@@ -121,3 +121,4 @@ export function nearestConversationMatchBefore(matches, lineIdx) {
121
121
  }
122
122
  /** ANSI CSI/OSC sequences emitted by the TUI renderer. */
123
123
  const ANSI_ESCAPE_RE = /^(?:\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]))/;
124
+ //# sourceMappingURL=conversation-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-search.js","sourceRoot":"","sources":["../../src/ui/conversation-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { type Component, type TUI, type TuiMouseEvent } from "@earendil-works/pi-tui";
2
+ import type { AgentRecord } from "../types.js";
3
+ import type { Theme } from "./agent-widget.js";
4
+ import { type ConversationBlock } from "./conversation-blocks.js";
5
+ export interface TimelineRenderLine {
6
+ text: string;
7
+ plain: string;
8
+ blockIndex: number;
9
+ railable?: boolean;
10
+ }
11
+ export interface TimelineToolSpan {
12
+ toolCallId: string;
13
+ startLine: number;
14
+ height: number;
15
+ }
16
+ export interface ConversationTimelineSnapshot {
17
+ lines: TimelineRenderLine[];
18
+ messageStarts: number[];
19
+ messageBlocks: ConversationBlock[];
20
+ interactiveToolIds: string[];
21
+ toolSpans: TimelineToolSpan[];
22
+ }
23
+ export interface ConversationTimelineOptions {
24
+ cwd?: string;
25
+ record?: AgentRecord;
26
+ onChange?: () => void;
27
+ }
28
+ /**
29
+ * Component-aware, snapshot-driven conversation timeline.
30
+ * ToolExecutionComponent state is rebuilt from normalized blocks when a call id
31
+ * first appears and then reused; history never needs a live session, spinner,
32
+ * stream, or process handle.
33
+ */
34
+ export declare class ConversationTimeline implements Component {
35
+ private readonly tui;
36
+ private readonly theme;
37
+ private readonly options;
38
+ private blocks;
39
+ private showTools;
40
+ private focusedToolCallId;
41
+ private expandedTools;
42
+ private toolComponents;
43
+ private snapshot;
44
+ private lastWidth;
45
+ constructor(tui: TUI, theme: Theme, options?: ConversationTimelineOptions);
46
+ setBlocks(blocks: readonly ConversationBlock[]): void;
47
+ setShowTools(show: boolean): void;
48
+ getShowTools(): boolean;
49
+ setFocusedToolCallId(id: string | undefined): void;
50
+ getFocusedToolCallId(): string | undefined;
51
+ getSnapshot(): ConversationTimelineSnapshot;
52
+ moveFocus(direction: 1 | -1): boolean;
53
+ toggleFocusedTool(): boolean;
54
+ isToolFocused(): boolean;
55
+ render(width: number): string[];
56
+ handleMouse(event: TuiMouseEvent): {
57
+ handled?: boolean;
58
+ render?: boolean;
59
+ } | undefined;
60
+ invalidate(): void;
61
+ }
62
+ //# sourceMappingURL=conversation-timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-timeline.d.ts","sourceRoot":"","sources":["../../src/ui/conversation-timeline.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,GAAG,EACR,KAAK,aAAa,EAEnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EACL,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,2BAA2B;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAwED;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IAgBlD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAjB1B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,cAAc,CAAsF;IAC5G,OAAO,CAAC,QAAQ,CAMd;IACF,OAAO,CAAC,SAAS,CAAK;gBAGH,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE,2BAAgC;IAG5D,SAAS,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI;IASrD,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAOjC,YAAY,IAAI,OAAO;IAIvB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKlD,oBAAoB,IAAI,MAAM,GAAG,SAAS;IAI1C,WAAW,IAAI,4BAA4B;IAK3C,SAAS,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO;IAarC,iBAAiB,IAAI,OAAO;IAU5B,aAAa,IAAI,OAAO;IAIxB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAgF/B,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS;IAyBtF,UAAU,IAAI,IAAI;CAInB"}
@@ -0,0 +1,266 @@
1
+ import * as CodingAgent from "@earendil-works/pi-coding-agent";
2
+ import { Markdown, Text, truncateToWidth, } from "@earendil-works/pi-tui";
3
+ import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
4
+ import { renderConversationRoleHeader } from "./conversation-role.js";
5
+ import { stripAnsi } from "./conversation-search.js";
6
+ import { createViewerCcstyleTool, } from "./ccstyle/tool-renderer.js";
7
+ function safeWidth(width) {
8
+ return Math.max(1, Math.floor(Number.isFinite(width) ? width : 1));
9
+ }
10
+ function resultContent(result) {
11
+ if (Array.isArray(result.content))
12
+ return result.content;
13
+ if (typeof result.content === "string")
14
+ return [{ type: "text", text: result.content }];
15
+ return [];
16
+ }
17
+ function fallbackToolLines(block, width, expanded = false) {
18
+ const summary = block.toolLine || block.fullText || block.toolName || "tool";
19
+ const output = block.toolResult
20
+ ? block.toolResult.content
21
+ : undefined;
22
+ const outputText = typeof output === "string"
23
+ ? output
24
+ : Array.isArray(output)
25
+ ? output.filter((item) => item?.type === "text").map((item) => String(item.text ?? "")).join("\n")
26
+ : "";
27
+ const outputLines = outputText.split(/\r?\n/);
28
+ const displayOutput = expanded || outputLines.length <= 4
29
+ ? outputLines
30
+ : [...outputLines.slice(0, 4), `… (${outputLines.length - 4} more lines · Enter to expand)`];
31
+ const body = outputText ? [summary, ...displayOutput].join("\n") : summary;
32
+ return body.split(/\r?\n/).map((line) => truncateToWidth(line, width, ""));
33
+ }
34
+ function applyToolComponentState(component, block, expanded) {
35
+ component.updateArgs?.(block.args ?? block.toolArguments ?? {});
36
+ component.setArgsComplete?.();
37
+ if (block.result ?? block.toolResult) {
38
+ const result = (block.result ?? block.toolResult);
39
+ component.updateResult?.({
40
+ content: resultContent(result),
41
+ details: result.details,
42
+ isError: result.isError === true,
43
+ }, false);
44
+ }
45
+ component.setExpanded?.(expanded);
46
+ }
47
+ function createToolComponent(block, tui, cwd, expanded) {
48
+ const Constructor = CodingAgent.ToolExecutionComponent;
49
+ if (typeof Constructor !== "function" || !block.toolName || !block.toolCallId)
50
+ return undefined;
51
+ try {
52
+ const renderer = createViewerCcstyleTool(block.toolName);
53
+ const component = new Constructor(block.toolName, block.toolCallId, block.args ?? block.toolArguments ?? {}, { showImages: false }, renderer, tui, cwd);
54
+ component.markExecutionStarted?.();
55
+ applyToolComponentState(component, block, expanded);
56
+ return component;
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ }
62
+ /**
63
+ * Component-aware, snapshot-driven conversation timeline.
64
+ * ToolExecutionComponent state is rebuilt from normalized blocks when a call id
65
+ * first appears and then reused; history never needs a live session, spinner,
66
+ * stream, or process handle.
67
+ */
68
+ export class ConversationTimeline {
69
+ tui;
70
+ theme;
71
+ options;
72
+ blocks = [];
73
+ showTools = true;
74
+ focusedToolCallId;
75
+ expandedTools = new Set();
76
+ toolComponents = new Map();
77
+ snapshot = {
78
+ lines: [],
79
+ messageStarts: [],
80
+ messageBlocks: [],
81
+ interactiveToolIds: [],
82
+ toolSpans: [],
83
+ };
84
+ lastWidth = 0;
85
+ constructor(tui, theme, options = {}) {
86
+ this.tui = tui;
87
+ this.theme = theme;
88
+ this.options = options;
89
+ }
90
+ setBlocks(blocks) {
91
+ this.blocks = [...blocks];
92
+ const ids = new Set(this.blocks.filter((block) => block.kind === "tool" && block.toolCallId).map((block) => block.toolCallId));
93
+ if (this.focusedToolCallId && !ids.has(this.focusedToolCallId))
94
+ this.focusedToolCallId = undefined;
95
+ for (const id of this.expandedTools)
96
+ if (!ids.has(id))
97
+ this.expandedTools.delete(id);
98
+ for (const id of this.toolComponents.keys())
99
+ if (!ids.has(id))
100
+ this.toolComponents.delete(id);
101
+ this.invalidate();
102
+ }
103
+ setShowTools(show) {
104
+ if (this.showTools === show)
105
+ return;
106
+ this.showTools = show;
107
+ if (!show)
108
+ this.focusedToolCallId = undefined;
109
+ this.invalidate();
110
+ }
111
+ getShowTools() {
112
+ return this.showTools;
113
+ }
114
+ setFocusedToolCallId(id) {
115
+ this.focusedToolCallId = id;
116
+ this.invalidate();
117
+ }
118
+ getFocusedToolCallId() {
119
+ return this.focusedToolCallId;
120
+ }
121
+ getSnapshot() {
122
+ if (this.lastWidth <= 0)
123
+ this.render(80);
124
+ return this.snapshot;
125
+ }
126
+ moveFocus(direction) {
127
+ const ids = this.getSnapshot().interactiveToolIds;
128
+ if (ids.length === 0)
129
+ return false;
130
+ const current = this.focusedToolCallId ? ids.indexOf(this.focusedToolCallId) : -1;
131
+ const next = current < 0
132
+ ? direction > 0 ? 0 : ids.length - 1
133
+ : (current + direction + ids.length) % ids.length;
134
+ this.focusedToolCallId = ids[next];
135
+ this.invalidate();
136
+ this.options.onChange?.();
137
+ return true;
138
+ }
139
+ toggleFocusedTool() {
140
+ const id = this.focusedToolCallId;
141
+ if (!id)
142
+ return false;
143
+ if (this.expandedTools.has(id))
144
+ this.expandedTools.delete(id);
145
+ else
146
+ this.expandedTools.add(id);
147
+ this.invalidate();
148
+ this.options.onChange?.();
149
+ return true;
150
+ }
151
+ isToolFocused() {
152
+ return this.focusedToolCallId !== undefined;
153
+ }
154
+ render(width) {
155
+ const requestedWidth = safeWidth(width);
156
+ const lines = [];
157
+ const messageStarts = [];
158
+ const messageBlocks = [];
159
+ const interactiveToolIds = [];
160
+ const toolSpans = [];
161
+ const visibleBlocks = this.blocks.filter((block) => this.showTools || block.kind !== "tool");
162
+ if (visibleBlocks.length === 0) {
163
+ const text = this.blocks.length === 0 ? "(waiting for first message...)" : "(tools hidden)";
164
+ lines.push({ text: this.theme.fg("dim", text), plain: text, blockIndex: -1 });
165
+ }
166
+ for (const block of visibleBlocks) {
167
+ const blockIndex = this.blocks.indexOf(block);
168
+ if (lines.length > 0) {
169
+ const separator = this.theme.fg("border", " " + "─ ".repeat(Math.max(1, Math.floor((requestedWidth - 6) / 2))).trimEnd());
170
+ lines.push({ text: truncateToWidth(separator, requestedWidth), plain: stripAnsi(separator), blockIndex });
171
+ }
172
+ const headerLine = ` ${renderConversationRoleHeader(block, this.theme)}`;
173
+ messageStarts.push(lines.length);
174
+ messageBlocks.push(block);
175
+ lines.push({ text: truncateToWidth(headerLine, requestedWidth), plain: stripAnsi(headerLine), blockIndex, railable: true });
176
+ if (block.kind === "tool") {
177
+ const id = block.toolCallId;
178
+ if (id)
179
+ interactiveToolIds.push(id);
180
+ let component;
181
+ if (id) {
182
+ const existing = this.toolComponents.get(id);
183
+ if (existing) {
184
+ applyToolComponentState(existing, block, this.expandedTools.has(id));
185
+ component = existing;
186
+ }
187
+ else {
188
+ component = createToolComponent(block, this.tui, this.options.cwd ?? process.cwd(), this.expandedTools.has(id));
189
+ if (component)
190
+ this.toolComponents.set(id, component);
191
+ }
192
+ }
193
+ let rendered;
194
+ try {
195
+ rendered = component?.render(requestedWidth) ?? fallbackToolLines(block, requestedWidth, id ? this.expandedTools.has(id) : false);
196
+ }
197
+ catch {
198
+ // Pi's interactive theme is a capability, not a viewer dependency;
199
+ // test hosts and older Pi versions can lack its initialized theme.
200
+ rendered = fallbackToolLines(block, requestedWidth, id ? this.expandedTools.has(id) : false);
201
+ }
202
+ for (const line of rendered) {
203
+ lines.push({ text: truncateToWidth(line, requestedWidth), plain: stripAnsi(line), blockIndex, railable: true });
204
+ }
205
+ if (id)
206
+ toolSpans.push({ toolCallId: id, startLine: messageStarts[messageStarts.length - 1], height: lines.length - messageStarts[messageStarts.length - 1] });
207
+ continue;
208
+ }
209
+ try {
210
+ const markdown = new Markdown(block.markdown || "∅", 2, 0, getMarkdownTheme(), {
211
+ color: (text) => this.theme.fg(block.role === "meta" ? "muted" : "text", text),
212
+ });
213
+ for (const line of markdown.render(requestedWidth)) {
214
+ lines.push({ text: truncateToWidth(line, requestedWidth), plain: stripAnsi(line), blockIndex, railable: true });
215
+ }
216
+ }
217
+ catch {
218
+ try {
219
+ for (const line of new Text(block.markdown || "∅").render(requestedWidth)) {
220
+ lines.push({ text: truncateToWidth(line, requestedWidth), plain: stripAnsi(line), blockIndex, railable: true });
221
+ }
222
+ }
223
+ catch {
224
+ for (const line of (block.markdown || "∅").split("\n")) {
225
+ lines.push({ text: truncateToWidth(line, requestedWidth), plain: line, blockIndex, railable: true });
226
+ }
227
+ }
228
+ }
229
+ }
230
+ this.lastWidth = requestedWidth;
231
+ this.snapshot = { lines, messageStarts, messageBlocks, interactiveToolIds, toolSpans };
232
+ return lines.map((line) => line.text);
233
+ }
234
+ handleMouse(event) {
235
+ // A normalized mouse interaction emits press/release/click. Toggle only
236
+ // on the terminal click; handling press as well causes one user click to
237
+ // expand and immediately collapse the same card.
238
+ if (event.type !== "click" || event.button !== "left")
239
+ return undefined;
240
+ const span = this.snapshot.toolSpans.find((candidate) => event.y >= candidate.startLine && event.y < candidate.startLine + candidate.height);
241
+ if (!span)
242
+ return undefined;
243
+ this.focusedToolCallId = span.toolCallId;
244
+ const component = this.toolComponents.get(span.toolCallId);
245
+ try {
246
+ // Keep Pi's normalized mouse contract in the component tree. The local
247
+ // role header occupies the first row; ToolExecutionComponent receives
248
+ // the remaining card-relative coordinate.
249
+ component?.handleMouse?.({ ...event, y: event.y - span.startLine, height: span.height });
250
+ }
251
+ catch {
252
+ // A missing/older Pi mouse implementation must not break the viewer.
253
+ }
254
+ this.expandedTools.has(span.toolCallId)
255
+ ? this.expandedTools.delete(span.toolCallId)
256
+ : this.expandedTools.add(span.toolCallId);
257
+ this.invalidate();
258
+ this.options.onChange?.();
259
+ return { handled: true, render: true };
260
+ }
261
+ invalidate() {
262
+ this.lastWidth = 0;
263
+ this.snapshot = { lines: [], messageStarts: [], messageBlocks: [], interactiveToolIds: [], toolSpans: [] };
264
+ }
265
+ }
266
+ //# sourceMappingURL=conversation-timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-timeline.js","sourceRoot":"","sources":["../../src/ui/conversation-timeline.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  * blocks are formatted data, while Markdown/ANSI lines are a bounded cache.
6
6
  */
7
7
  import type { ExtensionAPI, ExtensionContext, AgentSession } from "@earendil-works/pi-coding-agent";
8
- import { type Component, type TUI } from "@earendil-works/pi-tui";
8
+ import { type Component, type TUI, type TuiMouseEvent } from "@earendil-works/pi-tui";
9
9
  import type { AgentRecord } from "../types.js";
10
10
  import type { Theme } from "./agent-widget.js";
11
11
  import { type AgentActivity } from "./agent-widget.js";
@@ -54,6 +54,7 @@ export declare class ConversationViewer implements Component {
54
54
  private searchQuery;
55
55
  private searchMatches;
56
56
  private currentMatchIdx;
57
+ private timeline;
57
58
  constructor(tui: TUI, session: ConversationSource, record: AgentRecord, activity: AgentActivity | undefined, theme: Theme, done: (result: undefined) => void,
58
59
  /** Abort the agent shown here. Omitted means read-only history. */
59
60
  onStop?: (() => void) | undefined,
@@ -64,6 +65,10 @@ export declare class ConversationViewer implements Component {
64
65
  /** Optional clipboard/nvim operation context, appended for compatibility. */
65
66
  operations?: ConversationViewerOperations | undefined);
66
67
  handleInput(data: string): void;
68
+ handleMouse(event: TuiMouseEvent): {
69
+ handled?: boolean;
70
+ render?: boolean;
71
+ } | undefined;
67
72
  render(width: number): string[];
68
73
  invalidate(): void;
69
74
  dispose(): void;
@@ -94,3 +99,4 @@ export declare class ConversationViewer implements Component {
94
99
  private canSteer;
95
100
  private openComposer;
96
101
  }
102
+ //# sourceMappingURL=conversation-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-viewer.d.ts","sourceRoot":"","sources":["../../src/ui/conversation-viewer.ts"],"names":[],"mappings":"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"}
@@ -4,11 +4,13 @@
4
4
  * The viewer deliberately keeps rendering state separate from the transcript:
5
5
  * blocks are formatted data, while Markdown/ANSI lines are a bounded cache.
6
6
  */
7
- import { copyToClipboard, getMarkdownTheme } from "@earendil-works/pi-coding-agent";
8
- import { Input, Key, Markdown, matchesKey, Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
7
+ import { copyToClipboard } from "@earendil-works/pi-coding-agent";
8
+ import { Input, Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
9
9
  import { getLifetimeTotal, getSessionContextPercent } from "../usage.js";
10
10
  import { buildInvocationTags, describeActivity, fgPreservingNestedStyles, formatDuration, formatSessionTokens, getDisplayName, getPromptModeLabel } from "./agent-widget.js";
11
11
  import { formatConversationMessages } from "./conversation-blocks.js";
12
+ import { ConversationTimeline } from "./conversation-timeline.js";
13
+ import { renderConversationRoleHeader } from "./conversation-role.js";
12
14
  import { editLiveAssistantBlockInNvim, viewConversationBlockInNvim } from "./conversation-nvim.js";
13
15
  import { findConversationMatches, highlightConversationLine, nearestConversationMatchAfter, nearestConversationMatchBefore, stripAnsi } from "./conversation-search.js";
14
16
  import { createViewerKeys } from "./viewer-keys.js";
@@ -54,6 +56,7 @@ export class ConversationViewer {
54
56
  searchQuery = "";
55
57
  searchMatches = [];
56
58
  currentMatchIdx = -1;
59
+ timeline;
57
60
  constructor(tui, session, record, activity, theme, done,
58
61
  /** Abort the agent shown here. Omitted means read-only history. */
59
62
  onStop,
@@ -74,10 +77,21 @@ export class ConversationViewer {
74
77
  this.operations = operations;
75
78
  this.keys = createViewerKeys(keybindings);
76
79
  this.blocks = formatConversationMessages(session.messages);
80
+ this.timeline = new ConversationTimeline(tui, theme, {
81
+ cwd: operations?.ctx.cwd,
82
+ record,
83
+ onChange: () => {
84
+ this.cacheVersion++;
85
+ this.invalidate();
86
+ this.tui.requestRender();
87
+ },
88
+ });
89
+ this.timeline.setBlocks(this.blocks);
77
90
  this.unsubscribe = session.subscribe(() => {
78
91
  if (this.closed)
79
92
  return;
80
93
  this.blocks = formatConversationMessages(this.session.messages);
94
+ this.timeline.setBlocks(this.blocks);
81
95
  this.cacheVersion++;
82
96
  this.invalidate();
83
97
  this.tui.requestRender();
@@ -98,10 +112,17 @@ export class ConversationViewer {
98
112
  this.done(undefined);
99
113
  return;
100
114
  }
101
- if (matchesKey(data, "enter") && this.canSteer()) {
102
- this.stopArmed = false;
103
- this.openComposer();
104
- return;
115
+ if (matchesKey(data, "enter")) {
116
+ this.buildContentLines(this.lastInnerW || 80);
117
+ if (this.timeline.isToolFocused()) {
118
+ this.timeline.toggleFocusedTool();
119
+ return;
120
+ }
121
+ if (this.canSteer()) {
122
+ this.stopArmed = false;
123
+ this.openComposer();
124
+ return;
125
+ }
105
126
  }
106
127
  if (matchesKey(data, "x")) {
107
128
  if (this.isStoppable()) {
@@ -124,6 +145,17 @@ export class ConversationViewer {
124
145
  const maxScroll = Math.max(0, this.cachedLines.length - viewportHeight);
125
146
  if (data === "t") {
126
147
  this.showTools = !this.showTools;
148
+ this.timeline.setShowTools(this.showTools);
149
+ this.invalidate();
150
+ this.tui.requestRender();
151
+ }
152
+ else if (data === "\t") {
153
+ this.timeline.moveFocus(1);
154
+ this.invalidate();
155
+ this.tui.requestRender();
156
+ }
157
+ else if (matchesKey(data, Key.shift("tab"))) {
158
+ this.timeline.moveFocus(-1);
127
159
  this.invalidate();
128
160
  this.tui.requestRender();
129
161
  }
@@ -181,6 +213,26 @@ export class ConversationViewer {
181
213
  // Keep the computed max alive for the key path even when the cache is empty.
182
214
  void maxScroll;
183
215
  }
216
+ handleMouse(event) {
217
+ if (this.composer || this.searchMode)
218
+ return undefined;
219
+ const innerW = Math.max(1, this.lastInnerW || event.width - 4);
220
+ const contentLines = this.buildContentLines(innerW);
221
+ const viewportHeight = this.viewportHeight();
222
+ const maxScroll = Math.max(0, contentLines.length - viewportHeight);
223
+ const visibleStart = Math.min(this.scrollOffset, maxScroll);
224
+ const contentOrigin = 3 + (this.invocationLine() ? 1 : 0);
225
+ const contentY = event.y - contentOrigin + visibleStart;
226
+ if (contentY < 0 || contentY >= contentLines.length)
227
+ return undefined;
228
+ const result = this.timeline.handleMouse({ ...event, y: contentY });
229
+ if (result?.handled) {
230
+ this.cacheVersion++;
231
+ this.invalidate();
232
+ this.tui.requestRender();
233
+ }
234
+ return result;
235
+ }
184
236
  render(width) {
185
237
  if (width < 6)
186
238
  return [];
@@ -226,8 +278,10 @@ export class ConversationViewer {
226
278
  const displayed = visible.slice();
227
279
  if (showSticky) {
228
280
  const block = this.cachedMessageBlocks[this.currentMessageIndex()];
229
- if (block)
230
- displayed[0] = { text: ` ${block.header}`, plain: block.header, blockIndex: currentBlockIdx, railable: true };
281
+ if (block) {
282
+ const header = renderConversationRoleHeader(block, this.theme);
283
+ displayed[0] = { text: ` ${header}`, plain: header, blockIndex: currentBlockIdx, railable: true };
284
+ }
231
285
  }
232
286
  for (let i = 0; i < displayed.length; i++) {
233
287
  const line = displayed[i];
@@ -251,6 +305,14 @@ export class ConversationViewer {
251
305
  const label = th.fg("accent", "✎ steer");
252
306
  lines.push(row(label + " ".repeat(Math.max(1, innerW - visibleWidth(label) - visibleWidth(hint))) + hint));
253
307
  }
308
+ else if (this.searchMode) {
309
+ const query = `/${this.searchQuery}`;
310
+ const matchCount = this.searchMatches.length > 0
311
+ ? ` · ${this.searchMatches.length} match${this.searchMatches.length === 1 ? "" : "es"}`
312
+ : "";
313
+ const hints = th.fg("dim", " · Enter apply · Esc cancel");
314
+ lines.push(row(truncateToWidth(th.fg("accent", query) + th.fg("dim", matchCount) + hints, innerW, "...", true)));
315
+ }
254
316
  else {
255
317
  const actions = [];
256
318
  if (this.canSteer())
@@ -308,58 +370,37 @@ export class ConversationViewer {
308
370
  return CHROME_LINES_BASE + (this.invocationLine() ? 1 : 0) + (this.composer ? 1 : 0);
309
371
  }
310
372
  invocationLine() {
311
- const { modelName, tags } = buildInvocationTags(this.record.invocation);
312
- const parts = modelName ? [modelName, ...tags] : tags;
313
- return parts.length === 0 ? undefined : this.theme.fg("dim", ` ↳ ${parts.join(" · ")}`);
373
+ const liveModel = this.isLive() ? this.record.session?.model : undefined;
374
+ const invocation = this.record.invocation
375
+ ? {
376
+ ...this.record.invocation,
377
+ ...(liveModel && { effectiveModelName: liveModel.name ?? liveModel.id }),
378
+ ...(this.isLive() && { effectiveThinking: this.record.session?.thinkingLevel }),
379
+ }
380
+ : liveModel || (this.isLive() && this.record.session?.thinkingLevel)
381
+ ? {
382
+ effectiveModelName: liveModel?.name ?? liveModel?.id,
383
+ effectiveThinking: this.record.session?.thinkingLevel,
384
+ }
385
+ : undefined;
386
+ if (!invocation)
387
+ return this.theme.fg("dim", " ↳ model: unknown · thinking: unknown");
388
+ const { modelName, tags } = buildInvocationTags(invocation);
389
+ const effectiveModelName = invocation.effectiveModelName ?? modelName;
390
+ const parts = effectiveModelName ? [`model: ${effectiveModelName}`, ...tags] : ["model: inherit", ...tags];
391
+ return this.theme.fg("dim", ` ↳ ${parts.join(" · ")}`);
314
392
  }
315
393
  buildContentLines(width) {
316
394
  if (width <= 0)
317
395
  return [];
318
396
  if (this.cachedVersion === this.cacheVersion && this.cachedWidth === width)
319
397
  return this.cachedLines;
320
- const visibleBlocks = this.blocks.filter((block) => this.showTools || block.kind !== "tool");
321
- const lines = [];
322
- this.cachedMessageStarts = [];
323
- this.cachedMessageBlocks = [];
324
- if (visibleBlocks.length === 0) {
325
- const empty = this.blocks.length === 0 ? "(waiting for first message...)" : "(tools hidden)";
326
- lines.push({ text: this.theme.fg("dim", empty), plain: empty, blockIndex: -1 });
327
- }
328
- for (const block of visibleBlocks) {
329
- const blockIndex = this.blocks.indexOf(block);
330
- if (block.kind === "tool") {
331
- const raw = (block.toolLine ?? block.copyText).replace(/^·\s*/, "");
332
- const line = this.theme.fg("dim", ` └─ ${raw}`);
333
- lines.push({ text: truncateToWidth(line, width), plain: stripAnsi(line), blockIndex });
334
- continue;
335
- }
336
- if (lines.length > 0) {
337
- const separator = this.theme.fg("border", ` ${"─ ".repeat(Math.max(1, Math.floor((width - 6) / 2)))}`.trimEnd());
338
- lines.push({ text: truncateToWidth(separator, width), plain: stripAnsi(separator), blockIndex });
339
- }
340
- this.cachedMessageStarts.push(lines.length);
341
- this.cachedMessageBlocks.push(block);
342
- const header = ` ${block.header}`;
343
- lines.push({ text: truncateToWidth(header, width), plain: block.header, blockIndex, railable: true });
344
- try {
345
- const markdown = new Markdown(block.markdown || "∅", 2, 0, getMarkdownTheme(), {
346
- color: (text) => this.theme.fg(block.role === "meta" ? "muted" : "text", text),
347
- });
348
- for (const text of markdown.render(Math.max(1, width)))
349
- lines.push({ text: truncateToWidth(text, width), plain: stripAnsi(text), blockIndex, railable: true });
350
- }
351
- catch {
352
- try {
353
- for (const text of new Text(block.markdown || "∅").render(Math.max(1, width)))
354
- lines.push({ text: truncateToWidth(text, width), plain: stripAnsi(text), blockIndex, railable: true });
355
- }
356
- catch {
357
- const text = block.markdown || "∅";
358
- for (const line of text.split("\n"))
359
- lines.push({ text: truncateToWidth(line, width), plain: line, blockIndex, railable: true });
360
- }
361
- }
362
- }
398
+ this.timeline.setShowTools(this.showTools);
399
+ this.timeline.render(width);
400
+ const timelineSnapshot = this.timeline.getSnapshot();
401
+ const lines = timelineSnapshot.lines.map((line) => ({ ...line }));
402
+ this.cachedMessageStarts = [...timelineSnapshot.messageStarts];
403
+ this.cachedMessageBlocks = [...timelineSnapshot.messageBlocks];
363
404
  if (this.record.status === "running" && this.activity) {
364
405
  const act = describeActivity(this.activity.activeTools, this.activity.responseText);
365
406
  const text = `▍ ${act}`;
@@ -543,3 +584,4 @@ export class ConversationViewer {
543
584
  this.tui.requestRender();
544
585
  }
545
586
  }
587
+ //# sourceMappingURL=conversation-viewer.js.map