@bastani/atomic 0.8.22 → 0.8.23

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 (36) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +12 -0
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/CHANGELOG.md +12 -0
  5. package/dist/builtin/mcp/package.json +1 -1
  6. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  7. package/dist/builtin/subagents/package.json +1 -1
  8. package/dist/builtin/web-access/CHANGELOG.md +12 -0
  9. package/dist/builtin/web-access/package.json +1 -1
  10. package/dist/builtin/workflows/CHANGELOG.md +23 -0
  11. package/dist/builtin/workflows/README.md +31 -12
  12. package/dist/builtin/workflows/builtin/goal.ts +139 -100
  13. package/dist/builtin/workflows/builtin/ralph.ts +137 -182
  14. package/dist/builtin/workflows/package.json +1 -1
  15. package/dist/builtin/workflows/src/extension/index.ts +2 -4
  16. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +110 -13
  17. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +2 -2
  18. package/dist/core/system-prompt.d.ts.map +1 -1
  19. package/dist/core/system-prompt.js +8 -4
  20. package/dist/core/system-prompt.js.map +1 -1
  21. package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
  22. package/dist/core/tools/ask-user-question/ask-user-question.js +31 -11
  23. package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
  24. package/dist/modes/interactive/components/chat-session-host.d.ts +8 -0
  25. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  26. package/dist/modes/interactive/components/chat-session-host.js +83 -2
  27. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  28. package/dist/modes/interactive/components/chat-transcript.d.ts +12 -1
  29. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  30. package/dist/modes/interactive/components/chat-transcript.js +140 -13
  31. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  32. package/dist/modes/interactive/components/index.d.ts +1 -1
  33. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  34. package/dist/modes/interactive/components/index.js.map +1 -1
  35. package/docs/workflows.md +66 -17
  36. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { matchesKey, Container, Spacer, } from "@earendil-works/pi-tui";
1
+ import { matchesKey, Spacer, } from "@earendil-works/pi-tui";
2
2
  export function addChatTranscriptEntry(container, component, role) {
3
3
  if (needsLeadingSpacer(role) && container.children.length > 0) {
4
4
  container.addChild(new Spacer(1));
@@ -21,18 +21,99 @@ function needsLeadingSpacer(role) {
21
21
  * as the main chat.
22
22
  */
23
23
  export class ChatTranscriptComponent {
24
- constructor(entries, renderEntry) {
24
+ constructor(entries, renderEntry, cacheKey) {
25
+ this.blockCache = [];
25
26
  this.entries = entries;
26
27
  this.renderEntry = renderEntry;
28
+ this.cacheKey = cacheKey;
29
+ this.supportsRowWindow = cacheKey !== undefined;
27
30
  }
28
31
  render(width) {
29
- const container = new Container();
30
- for (const entry of this.entries) {
31
- addChatTranscriptEntry(container, this.renderEntry(entry), entry.role);
32
+ if (!this.supportsRowWindow)
33
+ return this.renderAllRows(width);
34
+ return this.renderRows(width, 0, this.rowCount(width));
35
+ }
36
+ rowCount(width) {
37
+ if (!this.supportsRowWindow)
38
+ return this.renderAllRows(width).length;
39
+ this.ensureBlockCache(width);
40
+ let count = 0;
41
+ for (const block of this.blockCache) {
42
+ if (block !== undefined)
43
+ count += block.lines.length;
44
+ }
45
+ return count;
46
+ }
47
+ renderRows(width, startRow, endRow) {
48
+ const start = Math.max(0, Math.floor(startRow));
49
+ const end = Math.max(start, Math.floor(endRow));
50
+ if (end <= start)
51
+ return [];
52
+ if (!this.supportsRowWindow)
53
+ return this.renderAllRows(width).slice(start, end);
54
+ this.ensureBlockCache(width);
55
+ const lines = [];
56
+ let cursor = 0;
57
+ for (let index = 0; index < this.entries.length; index += 1) {
58
+ const block = this.blockCache[index];
59
+ if (block === undefined)
60
+ continue;
61
+ const blockStart = cursor;
62
+ const blockEnd = blockStart + block.lines.length;
63
+ if (blockEnd > start && blockStart < end) {
64
+ const localStart = Math.max(0, start - blockStart);
65
+ const localEnd = Math.min(block.lines.length, end - blockStart);
66
+ lines.push(...block.lines.slice(localStart, localEnd));
67
+ }
68
+ cursor = blockEnd;
69
+ if (cursor >= end)
70
+ break;
71
+ }
72
+ return lines;
73
+ }
74
+ invalidate() {
75
+ this.blockCache = [];
76
+ }
77
+ ensureBlockCache(width) {
78
+ if (this.blockCache.length > this.entries.length) {
79
+ this.blockCache.length = this.entries.length;
32
80
  }
33
- return container.render(width);
81
+ for (let index = 0; index < this.entries.length; index += 1) {
82
+ const entry = this.entries[index];
83
+ if (entry === undefined)
84
+ continue;
85
+ const key = this.cacheKey?.(entry, index) ?? `${index}:${entry.role}`;
86
+ const cached = this.blockCache[index];
87
+ if (cached !== undefined &&
88
+ cached.entry === entry &&
89
+ cached.key === key &&
90
+ cached.width === width) {
91
+ continue;
92
+ }
93
+ this.blockCache[index] = {
94
+ entry,
95
+ key,
96
+ width,
97
+ lines: this.renderEntryBlock(entry, index, width),
98
+ };
99
+ }
100
+ }
101
+ renderAllRows(width) {
102
+ const lines = [];
103
+ for (let index = 0; index < this.entries.length; index += 1) {
104
+ const entry = this.entries[index];
105
+ if (entry !== undefined)
106
+ lines.push(...this.renderEntryBlock(entry, index, width));
107
+ }
108
+ return lines;
109
+ }
110
+ renderEntryBlock(entry, index, width) {
111
+ const lines = [];
112
+ if (index > 0 && needsLeadingSpacer(entry.role))
113
+ lines.push("");
114
+ lines.push(...this.renderEntry(entry).render(width));
115
+ return lines;
34
116
  }
35
- invalidate() { }
36
117
  }
37
118
  const DEFAULT_SCROLL_STEP_ROWS = 4;
38
119
  /**
@@ -104,17 +185,18 @@ export class ScrollableComponentViewport {
104
185
  return false;
105
186
  }
106
187
  render(width) {
107
- const allLines = this.components.flatMap((component) => component.render(width));
108
- const maxScroll = Math.max(0, allLines.length - this.visibleRows);
109
- if (this.scrollFromBottom > 0 && this.lastWidth === width && allLines.length > this.lastLineCount) {
110
- this.scrollFromBottom += allLines.length - this.lastLineCount;
188
+ const componentRows = this.measureComponentRows(width);
189
+ const lineCount = componentRows.reduce((sum, rows) => sum + rows.rowCount, 0);
190
+ const maxScroll = Math.max(0, lineCount - this.visibleRows);
191
+ if (this.scrollFromBottom > 0 && this.lastWidth === width && lineCount > this.lastLineCount) {
192
+ this.scrollFromBottom += lineCount - this.lastLineCount;
111
193
  }
112
- this.lastLineCount = allLines.length;
194
+ this.lastLineCount = lineCount;
113
195
  this.lastWidth = width;
114
196
  this.maxScroll = maxScroll;
115
197
  this.clampScroll();
116
198
  const start = Math.max(0, maxScroll - this.scrollFromBottom);
117
- const visible = allLines.slice(start, start + this.visibleRows);
199
+ const visible = this.renderVisibleRows(componentRows, width, start, start + this.visibleRows);
118
200
  while (visible.length < this.visibleRows)
119
201
  visible.push(" ".repeat(width));
120
202
  return visible;
@@ -123,6 +205,45 @@ export class ScrollableComponentViewport {
123
205
  for (const component of this.components)
124
206
  component.invalidate();
125
207
  }
208
+ measureComponentRows(width) {
209
+ return this.components.map((component) => {
210
+ if (isRowWindowComponent(component)) {
211
+ return {
212
+ kind: "windowed",
213
+ component,
214
+ rowCount: component.rowCount(width),
215
+ };
216
+ }
217
+ const lines = component.render(width);
218
+ return {
219
+ kind: "static",
220
+ lines,
221
+ rowCount: lines.length,
222
+ };
223
+ });
224
+ }
225
+ renderVisibleRows(componentRows, width, startRow, endRow) {
226
+ const lines = [];
227
+ let cursor = 0;
228
+ for (const rows of componentRows) {
229
+ const componentStart = cursor;
230
+ const componentEnd = componentStart + rows.rowCount;
231
+ if (componentEnd > startRow && componentStart < endRow) {
232
+ const localStart = Math.max(0, startRow - componentStart);
233
+ const localEnd = Math.min(rows.rowCount, endRow - componentStart);
234
+ if (rows.kind === "windowed") {
235
+ lines.push(...rows.component.renderRows(width, localStart, localEnd));
236
+ }
237
+ else {
238
+ lines.push(...rows.lines.slice(localStart, localEnd));
239
+ }
240
+ }
241
+ cursor = componentEnd;
242
+ if (cursor >= endRow)
243
+ break;
244
+ }
245
+ return lines;
246
+ }
126
247
  pageSize() {
127
248
  return Math.max(4, this.visibleRows - 2);
128
249
  }
@@ -130,6 +251,12 @@ export class ScrollableComponentViewport {
130
251
  this.scrollFromBottom = Math.max(0, Math.min(this.maxScroll, this.scrollFromBottom));
131
252
  }
132
253
  }
254
+ function isRowWindowComponent(component) {
255
+ const candidate = component;
256
+ return candidate.supportsRowWindow === true &&
257
+ typeof candidate.rowCount === "function" &&
258
+ typeof candidate.renderRows === "function";
259
+ }
133
260
  export class ScrollableChatTranscriptComponent {
134
261
  constructor(entries, renderEntry) {
135
262
  this.viewport = new ScrollableComponentViewport();
@@ -1 +1 @@
1
- {"version":3,"file":"chat-transcript.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-transcript.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n matchesKey,\n type Component,\n Container,\n Spacer,\n} from \"@earendil-works/pi-tui\";\n\n/**\n * Roles that participate in pi's chat spacing contract.\n *\n * Assistant turns own their leading whitespace internally, and tool rows attach\n * directly under the assistant/tool-call row they belong to. User-like rows get\n * one blank line when they are not the first row in the transcript.\n */\nexport type ChatTranscriptRole =\n | \"assistant\"\n | \"thinking\"\n | \"tool\"\n | \"user\"\n | \"custom\"\n | \"notice\"\n | \"system\"\n | \"summary\";\n\nexport interface ChatTranscriptEntryLike {\n readonly role: ChatTranscriptRole;\n}\n\nexport type ChatTranscriptRenderer<TEntry extends ChatTranscriptEntryLike> = (\n entry: TEntry,\n) => Component;\n\nexport function addChatTranscriptEntry(\n container: Container,\n component: Component,\n role: ChatTranscriptRole,\n): void {\n if (needsLeadingSpacer(role) && container.children.length > 0) {\n container.addChild(new Spacer(1));\n }\n container.addChild(component);\n}\n\nfunction needsLeadingSpacer(role: ChatTranscriptRole): boolean {\n return (\n role === \"user\" ||\n role === \"custom\" ||\n role === \"notice\" ||\n role === \"system\" ||\n role === \"summary\"\n );\n}\n\n/**\n * Reusable pi chat transcript scaffold for extension surfaces.\n *\n * This intentionally mirrors InteractiveMode.addMessageToChat spacing without\n * coupling consumers to a full AgentSession. Extension UIs can bring their own\n * message model while still rendering inside the same Container/Spacer rhythm\n * as the main chat.\n */\nexport class ChatTranscriptComponent<TEntry extends ChatTranscriptEntryLike>\n implements Component\n{\n declare private readonly entries: readonly TEntry[];\n declare private readonly renderEntry: ChatTranscriptRenderer<TEntry>;\n\n constructor(\n entries: readonly TEntry[],\n renderEntry: ChatTranscriptRenderer<TEntry>,\n ) {\n this.entries = entries;\n this.renderEntry = renderEntry;\n\t}\n\n render(width: number): string[] {\n const container = new Container();\n for (const entry of this.entries) {\n addChatTranscriptEntry(container, this.renderEntry(entry), entry.role);\n }\n return container.render(width);\n }\n\n invalidate(): void {}\n}\n\nconst DEFAULT_SCROLL_STEP_ROWS = 4;\n\n/**\n * Sticky-bottom, scrollable viewport for chat-like component stacks.\n *\n * Pi's main interactive chat gets terminal scrollback for free. Extension\n * overlays render into a fixed rectangle, so they need an explicit viewport\n * with the same sticky-bottom default plus keyboard and mouse history controls.\n */\nexport class ScrollableComponentViewport implements Component {\n private components: readonly Component[] = [];\n private visibleRows = 1;\n private scrollFromBottom = 0;\n private lastLineCount = 0;\n private lastWidth = 0;\n private maxScroll = 0;\n\n setComponents(components: readonly Component[]): void {\n this.components = components;\n }\n\n setVisibleRows(rows: number): void {\n this.visibleRows = Math.max(1, Math.floor(rows));\n this.clampScroll();\n }\n\n getScrollFromBottom(): number {\n return this.scrollFromBottom;\n }\n\n getMaxScroll(): number {\n return this.maxScroll;\n }\n\n scrollToBottom(): void {\n this.scrollFromBottom = 0;\n }\n\n scrollToTop(): void {\n this.scrollFromBottom = this.maxScroll;\n }\n\n scrollBy(deltaRows: number): void {\n // Positive deltas move toward newer content; negative deltas move up\n // into older history. Store the offset from the sticky bottom so new\n // streaming output can keep following when the offset is zero.\n this.scrollFromBottom -= deltaRows;\n this.clampScroll();\n }\n\n handleInput(data: string): boolean {\n const wheelDeltaRows = mouseWheelDeltaRows(data);\n if (wheelDeltaRows !== 0) {\n this.scrollBy(wheelDeltaRows);\n return true;\n }\n if (isMouseSequence(data)) return true;\n if (matchesKey(data, \"pageUp\")) {\n this.scrollBy(-this.pageSize());\n return true;\n }\n if (matchesKey(data, \"pageDown\")) {\n this.scrollBy(this.pageSize());\n return true;\n }\n if (matchesKey(data, \"home\")) {\n this.scrollToTop();\n return true;\n }\n if (matchesKey(data, \"end\")) {\n this.scrollToBottom();\n return true;\n }\n return false;\n }\n\n render(width: number): string[] {\n const allLines = this.components.flatMap((component) => component.render(width));\n const maxScroll = Math.max(0, allLines.length - this.visibleRows);\n if (this.scrollFromBottom > 0 && this.lastWidth === width && allLines.length > this.lastLineCount) {\n this.scrollFromBottom += allLines.length - this.lastLineCount;\n }\n this.lastLineCount = allLines.length;\n this.lastWidth = width;\n this.maxScroll = maxScroll;\n this.clampScroll();\n\n const start = Math.max(0, maxScroll - this.scrollFromBottom);\n const visible = allLines.slice(start, start + this.visibleRows);\n while (visible.length < this.visibleRows) visible.push(\" \".repeat(width));\n return visible;\n }\n\n invalidate(): void {\n for (const component of this.components) component.invalidate();\n }\n\n private pageSize(): number {\n return Math.max(4, this.visibleRows - 2);\n }\n\n private clampScroll(): void {\n this.scrollFromBottom = Math.max(0, Math.min(this.maxScroll, this.scrollFromBottom));\n }\n}\n\nexport class ScrollableChatTranscriptComponent<TEntry extends ChatTranscriptEntryLike>\n implements Component\n{\n private readonly viewport = new ScrollableComponentViewport();\n private readonly transcript: ChatTranscriptComponent<TEntry>;\n\n constructor(\n entries: readonly TEntry[],\n renderEntry: ChatTranscriptRenderer<TEntry>,\n ) {\n this.transcript = new ChatTranscriptComponent(entries, renderEntry);\n this.viewport.setComponents([this.transcript]);\n }\n\n setVisibleRows(rows: number): void {\n this.viewport.setVisibleRows(rows);\n }\n\n handleInput(data: string): boolean {\n return this.viewport.handleInput(data);\n }\n\n render(width: number): string[] {\n return this.viewport.render(width);\n }\n\n invalidate(): void {\n this.viewport.invalidate();\n }\n\n getScrollFromBottom(): number {\n return this.viewport.getScrollFromBottom();\n }\n\n getMaxScroll(): number {\n return this.viewport.getMaxScroll();\n }\n\n scrollToBottom(): void {\n this.viewport.scrollToBottom();\n }\n}\n\nfunction mouseWheelDeltaRows(data: string): number {\n const sgr = data.match(/^\\x1b\\[<(\\d+);\\d+;\\d+M$/);\n if (sgr) return wheelDeltaForButtonCode(Number.parseInt(sgr[1]!, 10));\n if (data.startsWith(\"\\x1b[M\") && data.length >= 6) {\n return wheelDeltaForButtonCode(data.charCodeAt(3) - 32);\n }\n return 0;\n}\n\nfunction wheelDeltaForButtonCode(code: number): number {\n if ((code & 64) === 0) return 0;\n const direction = code & 3;\n if (direction === 0) return -DEFAULT_SCROLL_STEP_ROWS;\n if (direction === 1) return DEFAULT_SCROLL_STEP_ROWS;\n return 0;\n}\n\nfunction isMouseSequence(data: string): boolean {\n return /^\\x1b\\[<\\d+;\\d+;\\d+[mM]$/.test(data) || data.startsWith(\"\\x1b[M\");\n}\n"]}
1
+ {"version":3,"file":"chat-transcript.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-transcript.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n matchesKey,\n type Component,\n Container,\n Spacer,\n} from \"@earendil-works/pi-tui\";\n\n/**\n * Roles that participate in pi's chat spacing contract.\n *\n * Assistant turns own their leading whitespace internally, and tool rows attach\n * directly under the assistant/tool-call row they belong to. User-like rows get\n * one blank line when they are not the first row in the transcript.\n */\nexport type ChatTranscriptRole =\n | \"assistant\"\n | \"thinking\"\n | \"tool\"\n | \"user\"\n | \"custom\"\n | \"notice\"\n | \"system\"\n | \"summary\";\n\nexport interface ChatTranscriptEntryLike {\n readonly role: ChatTranscriptRole;\n}\n\nexport type ChatTranscriptRenderer<TEntry extends ChatTranscriptEntryLike> = (\n entry: TEntry,\n) => Component;\n\nexport type ChatTranscriptCacheKey<TEntry extends ChatTranscriptEntryLike> = (\n entry: TEntry,\n index: number,\n) => string;\n\ninterface CachedChatTranscriptBlock<TEntry extends ChatTranscriptEntryLike> {\n readonly entry: TEntry;\n readonly key: string;\n readonly width: number;\n readonly lines: readonly string[];\n}\n\ninterface RowWindowComponent extends Component {\n readonly supportsRowWindow: true;\n rowCount(width: number): number;\n renderRows(width: number, startRow: number, endRow: number): string[];\n}\n\ninterface WindowedComponentRows {\n readonly kind: \"windowed\";\n readonly component: RowWindowComponent;\n readonly rowCount: number;\n}\n\ninterface StaticComponentRows {\n readonly kind: \"static\";\n readonly lines: readonly string[];\n readonly rowCount: number;\n}\n\ntype ComponentRows = WindowedComponentRows | StaticComponentRows;\n\nexport function addChatTranscriptEntry(\n container: Container,\n component: Component,\n role: ChatTranscriptRole,\n): void {\n if (needsLeadingSpacer(role) && container.children.length > 0) {\n container.addChild(new Spacer(1));\n }\n container.addChild(component);\n}\n\nfunction needsLeadingSpacer(role: ChatTranscriptRole): boolean {\n return (\n role === \"user\" ||\n role === \"custom\" ||\n role === \"notice\" ||\n role === \"system\" ||\n role === \"summary\"\n );\n}\n\n/**\n * Reusable pi chat transcript scaffold for extension surfaces.\n *\n * This intentionally mirrors InteractiveMode.addMessageToChat spacing without\n * coupling consumers to a full AgentSession. Extension UIs can bring their own\n * message model while still rendering inside the same Container/Spacer rhythm\n * as the main chat.\n */\nexport class ChatTranscriptComponent<TEntry extends ChatTranscriptEntryLike>\n implements Component\n{\n private readonly entries: readonly TEntry[];\n private readonly renderEntry: ChatTranscriptRenderer<TEntry>;\n readonly supportsRowWindow: boolean;\n\n private readonly cacheKey: ChatTranscriptCacheKey<TEntry> | undefined;\n private blockCache: Array<CachedChatTranscriptBlock<TEntry> | undefined> = [];\n\n constructor(\n entries: readonly TEntry[],\n renderEntry: ChatTranscriptRenderer<TEntry>,\n cacheKey?: ChatTranscriptCacheKey<TEntry>,\n ) {\n this.entries = entries;\n this.renderEntry = renderEntry;\n this.cacheKey = cacheKey;\n this.supportsRowWindow = cacheKey !== undefined;\n }\n\n render(width: number): string[] {\n if (!this.supportsRowWindow) return this.renderAllRows(width);\n return this.renderRows(width, 0, this.rowCount(width));\n }\n\n rowCount(width: number): number {\n if (!this.supportsRowWindow) return this.renderAllRows(width).length;\n this.ensureBlockCache(width);\n let count = 0;\n for (const block of this.blockCache) {\n if (block !== undefined) count += block.lines.length;\n }\n return count;\n }\n\n renderRows(width: number, startRow: number, endRow: number): string[] {\n const start = Math.max(0, Math.floor(startRow));\n const end = Math.max(start, Math.floor(endRow));\n if (end <= start) return [];\n if (!this.supportsRowWindow) return this.renderAllRows(width).slice(start, end);\n\n this.ensureBlockCache(width);\n const lines: string[] = [];\n let cursor = 0;\n for (let index = 0; index < this.entries.length; index += 1) {\n const block = this.blockCache[index];\n if (block === undefined) continue;\n const blockStart = cursor;\n const blockEnd = blockStart + block.lines.length;\n if (blockEnd > start && blockStart < end) {\n const localStart = Math.max(0, start - blockStart);\n const localEnd = Math.min(block.lines.length, end - blockStart);\n lines.push(...block.lines.slice(localStart, localEnd));\n }\n cursor = blockEnd;\n if (cursor >= end) break;\n }\n return lines;\n }\n\n invalidate(): void {\n this.blockCache = [];\n }\n\n private ensureBlockCache(width: number): void {\n if (this.blockCache.length > this.entries.length) {\n this.blockCache.length = this.entries.length;\n }\n for (let index = 0; index < this.entries.length; index += 1) {\n const entry = this.entries[index];\n if (entry === undefined) continue;\n const key = this.cacheKey?.(entry, index) ?? `${index}:${entry.role}`;\n const cached = this.blockCache[index];\n if (\n cached !== undefined &&\n cached.entry === entry &&\n cached.key === key &&\n cached.width === width\n ) {\n continue;\n }\n this.blockCache[index] = {\n entry,\n key,\n width,\n lines: this.renderEntryBlock(entry, index, width),\n };\n }\n }\n\n private renderAllRows(width: number): string[] {\n const lines: string[] = [];\n for (let index = 0; index < this.entries.length; index += 1) {\n const entry = this.entries[index];\n if (entry !== undefined) lines.push(...this.renderEntryBlock(entry, index, width));\n }\n return lines;\n }\n\n private renderEntryBlock(entry: TEntry, index: number, width: number): string[] {\n const lines: string[] = [];\n if (index > 0 && needsLeadingSpacer(entry.role)) lines.push(\"\");\n lines.push(...this.renderEntry(entry).render(width));\n return lines;\n }\n}\n\nconst DEFAULT_SCROLL_STEP_ROWS = 4;\n\n/**\n * Sticky-bottom, scrollable viewport for chat-like component stacks.\n *\n * Pi's main interactive chat gets terminal scrollback for free. Extension\n * overlays render into a fixed rectangle, so they need an explicit viewport\n * with the same sticky-bottom default plus keyboard and mouse history controls.\n */\nexport class ScrollableComponentViewport implements Component {\n private components: readonly Component[] = [];\n private visibleRows = 1;\n private scrollFromBottom = 0;\n private lastLineCount = 0;\n private lastWidth = 0;\n private maxScroll = 0;\n\n setComponents(components: readonly Component[]): void {\n this.components = components;\n }\n\n setVisibleRows(rows: number): void {\n this.visibleRows = Math.max(1, Math.floor(rows));\n this.clampScroll();\n }\n\n getScrollFromBottom(): number {\n return this.scrollFromBottom;\n }\n\n getMaxScroll(): number {\n return this.maxScroll;\n }\n\n scrollToBottom(): void {\n this.scrollFromBottom = 0;\n }\n\n scrollToTop(): void {\n this.scrollFromBottom = this.maxScroll;\n }\n\n scrollBy(deltaRows: number): void {\n // Positive deltas move toward newer content; negative deltas move up\n // into older history. Store the offset from the sticky bottom so new\n // streaming output can keep following when the offset is zero.\n this.scrollFromBottom -= deltaRows;\n this.clampScroll();\n }\n\n handleInput(data: string): boolean {\n const wheelDeltaRows = mouseWheelDeltaRows(data);\n if (wheelDeltaRows !== 0) {\n this.scrollBy(wheelDeltaRows);\n return true;\n }\n if (isMouseSequence(data)) return true;\n if (matchesKey(data, \"pageUp\")) {\n this.scrollBy(-this.pageSize());\n return true;\n }\n if (matchesKey(data, \"pageDown\")) {\n this.scrollBy(this.pageSize());\n return true;\n }\n if (matchesKey(data, \"home\")) {\n this.scrollToTop();\n return true;\n }\n if (matchesKey(data, \"end\")) {\n this.scrollToBottom();\n return true;\n }\n return false;\n }\n\n render(width: number): string[] {\n const componentRows = this.measureComponentRows(width);\n const lineCount = componentRows.reduce((sum, rows) => sum + rows.rowCount, 0);\n const maxScroll = Math.max(0, lineCount - this.visibleRows);\n if (this.scrollFromBottom > 0 && this.lastWidth === width && lineCount > this.lastLineCount) {\n this.scrollFromBottom += lineCount - this.lastLineCount;\n }\n this.lastLineCount = lineCount;\n this.lastWidth = width;\n this.maxScroll = maxScroll;\n this.clampScroll();\n\n const start = Math.max(0, maxScroll - this.scrollFromBottom);\n const visible = this.renderVisibleRows(\n componentRows,\n width,\n start,\n start + this.visibleRows,\n );\n while (visible.length < this.visibleRows) visible.push(\" \".repeat(width));\n return visible;\n }\n\n invalidate(): void {\n for (const component of this.components) component.invalidate();\n }\n\n private measureComponentRows(width: number): ComponentRows[] {\n return this.components.map((component) => {\n if (isRowWindowComponent(component)) {\n return {\n kind: \"windowed\",\n component,\n rowCount: component.rowCount(width),\n };\n }\n const lines = component.render(width);\n return {\n kind: \"static\",\n lines,\n rowCount: lines.length,\n };\n });\n }\n\n private renderVisibleRows(\n componentRows: readonly ComponentRows[],\n width: number,\n startRow: number,\n endRow: number,\n ): string[] {\n const lines: string[] = [];\n let cursor = 0;\n for (const rows of componentRows) {\n const componentStart = cursor;\n const componentEnd = componentStart + rows.rowCount;\n if (componentEnd > startRow && componentStart < endRow) {\n const localStart = Math.max(0, startRow - componentStart);\n const localEnd = Math.min(rows.rowCount, endRow - componentStart);\n if (rows.kind === \"windowed\") {\n lines.push(...rows.component.renderRows(width, localStart, localEnd));\n } else {\n lines.push(...rows.lines.slice(localStart, localEnd));\n }\n }\n cursor = componentEnd;\n if (cursor >= endRow) break;\n }\n return lines;\n }\n\n private pageSize(): number {\n return Math.max(4, this.visibleRows - 2);\n }\n\n private clampScroll(): void {\n this.scrollFromBottom = Math.max(0, Math.min(this.maxScroll, this.scrollFromBottom));\n }\n}\n\nfunction isRowWindowComponent(component: Component): component is RowWindowComponent {\n const candidate = component as Partial<RowWindowComponent>;\n return candidate.supportsRowWindow === true &&\n typeof candidate.rowCount === \"function\" &&\n typeof candidate.renderRows === \"function\";\n}\n\nexport class ScrollableChatTranscriptComponent<TEntry extends ChatTranscriptEntryLike>\n implements Component\n{\n private readonly viewport = new ScrollableComponentViewport();\n private readonly transcript: ChatTranscriptComponent<TEntry>;\n\n constructor(\n entries: readonly TEntry[],\n renderEntry: ChatTranscriptRenderer<TEntry>,\n ) {\n this.transcript = new ChatTranscriptComponent(entries, renderEntry);\n this.viewport.setComponents([this.transcript]);\n }\n\n setVisibleRows(rows: number): void {\n this.viewport.setVisibleRows(rows);\n }\n\n handleInput(data: string): boolean {\n return this.viewport.handleInput(data);\n }\n\n render(width: number): string[] {\n return this.viewport.render(width);\n }\n\n invalidate(): void {\n this.viewport.invalidate();\n }\n\n getScrollFromBottom(): number {\n return this.viewport.getScrollFromBottom();\n }\n\n getMaxScroll(): number {\n return this.viewport.getMaxScroll();\n }\n\n scrollToBottom(): void {\n this.viewport.scrollToBottom();\n }\n}\n\nfunction mouseWheelDeltaRows(data: string): number {\n const sgr = data.match(/^\\x1b\\[<(\\d+);\\d+;\\d+M$/);\n if (sgr) return wheelDeltaForButtonCode(Number.parseInt(sgr[1]!, 10));\n if (data.startsWith(\"\\x1b[M\") && data.length >= 6) {\n return wheelDeltaForButtonCode(data.charCodeAt(3) - 32);\n }\n return 0;\n}\n\nfunction wheelDeltaForButtonCode(code: number): number {\n if ((code & 64) === 0) return 0;\n const direction = code & 3;\n if (direction === 0) return -DEFAULT_SCROLL_STEP_ROWS;\n if (direction === 1) return DEFAULT_SCROLL_STEP_ROWS;\n return 0;\n}\n\nfunction isMouseSequence(data: string): boolean {\n return /^\\x1b\\[<\\d+;\\d+;\\d+[mM]$/.test(data) || data.startsWith(\"\\x1b[M\");\n}\n"]}
@@ -4,7 +4,7 @@ export { BashExecutionComponent } from "./bash-execution.ts";
4
4
  export { BorderedLoader } from "./bordered-loader.ts";
5
5
  export { chatEntriesFromAgentMessages, LiveChatEntriesController, renderChatMessageEntry, type ChatMessageEntry, type ChatMessageRenderOptions, } from "./chat-message-renderer.ts";
6
6
  export { ChatSessionHost, type ChatSessionHostBashRequest, type ChatSessionHostCommands, type ChatSessionHostEntry, type ChatSessionHostOpts, type ChatSessionHostStyle, } from "./chat-session-host.ts";
7
- export { addChatTranscriptEntry, ChatTranscriptComponent, ScrollableChatTranscriptComponent, ScrollableComponentViewport, type ChatTranscriptEntryLike, type ChatTranscriptRenderer, type ChatTranscriptRole, } from "./chat-transcript.ts";
7
+ export { addChatTranscriptEntry, ChatTranscriptComponent, ScrollableChatTranscriptComponent, ScrollableComponentViewport, type ChatTranscriptCacheKey, type ChatTranscriptEntryLike, type ChatTranscriptRenderer, type ChatTranscriptRole, } from "./chat-transcript.ts";
8
8
  export { BranchSummaryMessageComponent } from "./branch-summary-message.ts";
9
9
  export { CompactionSummaryMessageComponent } from "./compaction-summary-message.ts";
10
10
  export { CustomEditor } from "./custom-editor.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/index.ts"],"names":[],"mappings":"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","sourcesContent":["// UI Components for extensions\nexport { ArminComponent } from \"./armin.ts\";\nexport { AssistantMessageComponent } from \"./assistant-message.ts\";\nexport { BashExecutionComponent } from \"./bash-execution.ts\";\nexport { BorderedLoader } from \"./bordered-loader.ts\";\nexport {\n chatEntriesFromAgentMessages,\n LiveChatEntriesController,\n renderChatMessageEntry,\n type ChatMessageEntry,\n type ChatMessageRenderOptions,\n} from \"./chat-message-renderer.ts\";\nexport {\n ChatSessionHost,\n type ChatSessionHostBashRequest,\n type ChatSessionHostCommands,\n type ChatSessionHostEntry,\n type ChatSessionHostOpts,\n type ChatSessionHostStyle,\n} from \"./chat-session-host.ts\";\nexport {\n addChatTranscriptEntry,\n ChatTranscriptComponent,\n ScrollableChatTranscriptComponent,\n ScrollableComponentViewport,\n type ChatTranscriptEntryLike,\n type ChatTranscriptRenderer,\n type ChatTranscriptRole,\n} from \"./chat-transcript.ts\";\nexport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nexport { CompactionSummaryMessageComponent } from \"./compaction-summary-message.ts\";\nexport { CustomEditor } from \"./custom-editor.ts\";\nexport { CustomMessageComponent } from \"./custom-message.ts\";\nexport { DaxnutsComponent } from \"./daxnuts.ts\";\nexport { type RenderDiffOptions, renderDiff } from \"./diff.ts\";\nexport { DynamicBorder } from \"./dynamic-border.ts\";\nexport { ExtensionEditorComponent } from \"./extension-editor.ts\";\nexport { ExtensionInputComponent } from \"./extension-input.ts\";\nexport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\nexport {\n FastModeSelectorComponent,\n type FastModeSelectorCallbacks,\n type FastModeSelectorConfig,\n} from \"./fast-mode-selector.ts\";\nexport { FooterComponent, UsageMeterComponent } from \"./footer.ts\";\nexport { keyHint, keyText, rawKeyHint } from \"./keybinding-hints.ts\";\nexport { LoginDialogComponent } from \"./login-dialog.ts\";\nexport { ModelSelectorComponent } from \"./model-selector.ts\";\nexport { OAuthSelectorComponent } from \"./oauth-selector.ts\";\nexport { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from \"./scoped-models-selector.ts\";\nexport { SessionSelectorComponent } from \"./session-selector.ts\";\nexport { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from \"./settings-selector.ts\";\nexport { ShowImagesSelectorComponent } from \"./show-images-selector.ts\";\nexport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nexport { ThemeSelectorComponent } from \"./theme-selector.ts\";\nexport { ThinkingSelectorComponent } from \"./thinking-selector.ts\";\nexport { ToolExecutionComponent, type ToolExecutionOptions } from \"./tool-execution.ts\";\nexport { TreeSelectorComponent } from \"./tree-selector.ts\";\nexport { UserMessageComponent } from \"./user-message.ts\";\nexport { UserMessageSelectorComponent } from \"./user-message-selector.ts\";\nexport { WorkingStatusComponent, type WorkingStatusComponentOptions } from \"./working-status.ts\";\nexport { truncateToVisualLines, type VisualTruncateResult } from \"./visual-truncate.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/index.ts"],"names":[],"mappings":"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","sourcesContent":["// UI Components for extensions\nexport { ArminComponent } from \"./armin.ts\";\nexport { AssistantMessageComponent } from \"./assistant-message.ts\";\nexport { BashExecutionComponent } from \"./bash-execution.ts\";\nexport { BorderedLoader } from \"./bordered-loader.ts\";\nexport {\n chatEntriesFromAgentMessages,\n LiveChatEntriesController,\n renderChatMessageEntry,\n type ChatMessageEntry,\n type ChatMessageRenderOptions,\n} from \"./chat-message-renderer.ts\";\nexport {\n ChatSessionHost,\n type ChatSessionHostBashRequest,\n type ChatSessionHostCommands,\n type ChatSessionHostEntry,\n type ChatSessionHostOpts,\n type ChatSessionHostStyle,\n} from \"./chat-session-host.ts\";\nexport {\n addChatTranscriptEntry,\n ChatTranscriptComponent,\n ScrollableChatTranscriptComponent,\n ScrollableComponentViewport,\n type ChatTranscriptCacheKey,\n type ChatTranscriptEntryLike,\n type ChatTranscriptRenderer,\n type ChatTranscriptRole,\n} from \"./chat-transcript.ts\";\nexport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nexport { CompactionSummaryMessageComponent } from \"./compaction-summary-message.ts\";\nexport { CustomEditor } from \"./custom-editor.ts\";\nexport { CustomMessageComponent } from \"./custom-message.ts\";\nexport { DaxnutsComponent } from \"./daxnuts.ts\";\nexport { type RenderDiffOptions, renderDiff } from \"./diff.ts\";\nexport { DynamicBorder } from \"./dynamic-border.ts\";\nexport { ExtensionEditorComponent } from \"./extension-editor.ts\";\nexport { ExtensionInputComponent } from \"./extension-input.ts\";\nexport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\nexport {\n FastModeSelectorComponent,\n type FastModeSelectorCallbacks,\n type FastModeSelectorConfig,\n} from \"./fast-mode-selector.ts\";\nexport { FooterComponent, UsageMeterComponent } from \"./footer.ts\";\nexport { keyHint, keyText, rawKeyHint } from \"./keybinding-hints.ts\";\nexport { LoginDialogComponent } from \"./login-dialog.ts\";\nexport { ModelSelectorComponent } from \"./model-selector.ts\";\nexport { OAuthSelectorComponent } from \"./oauth-selector.ts\";\nexport { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from \"./scoped-models-selector.ts\";\nexport { SessionSelectorComponent } from \"./session-selector.ts\";\nexport { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from \"./settings-selector.ts\";\nexport { ShowImagesSelectorComponent } from \"./show-images-selector.ts\";\nexport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nexport { ThemeSelectorComponent } from \"./theme-selector.ts\";\nexport { ThinkingSelectorComponent } from \"./thinking-selector.ts\";\nexport { ToolExecutionComponent, type ToolExecutionOptions } from \"./tool-execution.ts\";\nexport { TreeSelectorComponent } from \"./tree-selector.ts\";\nexport { UserMessageComponent } from \"./user-message.ts\";\nexport { UserMessageSelectorComponent } from \"./user-message-selector.ts\";\nexport { WorkingStatusComponent, type WorkingStatusComponentOptions } from \"./working-status.ts\";\nexport { truncateToVisualLines, type VisualTruncateResult } from \"./visual-truncate.ts\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,GAGvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,GAMhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,iCAAiC,EACjC,2BAA2B,GAI5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAA0B,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EACL,yBAAyB,GAG1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAA2C,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAA+C,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAChH,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAA6B,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAsC,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAA6B,MAAM,sBAAsB,CAAC","sourcesContent":["// UI Components for extensions\nexport { ArminComponent } from \"./armin.ts\";\nexport { AssistantMessageComponent } from \"./assistant-message.ts\";\nexport { BashExecutionComponent } from \"./bash-execution.ts\";\nexport { BorderedLoader } from \"./bordered-loader.ts\";\nexport {\n chatEntriesFromAgentMessages,\n LiveChatEntriesController,\n renderChatMessageEntry,\n type ChatMessageEntry,\n type ChatMessageRenderOptions,\n} from \"./chat-message-renderer.ts\";\nexport {\n ChatSessionHost,\n type ChatSessionHostBashRequest,\n type ChatSessionHostCommands,\n type ChatSessionHostEntry,\n type ChatSessionHostOpts,\n type ChatSessionHostStyle,\n} from \"./chat-session-host.ts\";\nexport {\n addChatTranscriptEntry,\n ChatTranscriptComponent,\n ScrollableChatTranscriptComponent,\n ScrollableComponentViewport,\n type ChatTranscriptEntryLike,\n type ChatTranscriptRenderer,\n type ChatTranscriptRole,\n} from \"./chat-transcript.ts\";\nexport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nexport { CompactionSummaryMessageComponent } from \"./compaction-summary-message.ts\";\nexport { CustomEditor } from \"./custom-editor.ts\";\nexport { CustomMessageComponent } from \"./custom-message.ts\";\nexport { DaxnutsComponent } from \"./daxnuts.ts\";\nexport { type RenderDiffOptions, renderDiff } from \"./diff.ts\";\nexport { DynamicBorder } from \"./dynamic-border.ts\";\nexport { ExtensionEditorComponent } from \"./extension-editor.ts\";\nexport { ExtensionInputComponent } from \"./extension-input.ts\";\nexport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\nexport {\n FastModeSelectorComponent,\n type FastModeSelectorCallbacks,\n type FastModeSelectorConfig,\n} from \"./fast-mode-selector.ts\";\nexport { FooterComponent, UsageMeterComponent } from \"./footer.ts\";\nexport { keyHint, keyText, rawKeyHint } from \"./keybinding-hints.ts\";\nexport { LoginDialogComponent } from \"./login-dialog.ts\";\nexport { ModelSelectorComponent } from \"./model-selector.ts\";\nexport { OAuthSelectorComponent } from \"./oauth-selector.ts\";\nexport { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from \"./scoped-models-selector.ts\";\nexport { SessionSelectorComponent } from \"./session-selector.ts\";\nexport { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from \"./settings-selector.ts\";\nexport { ShowImagesSelectorComponent } from \"./show-images-selector.ts\";\nexport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nexport { ThemeSelectorComponent } from \"./theme-selector.ts\";\nexport { ThinkingSelectorComponent } from \"./thinking-selector.ts\";\nexport { ToolExecutionComponent, type ToolExecutionOptions } from \"./tool-execution.ts\";\nexport { TreeSelectorComponent } from \"./tree-selector.ts\";\nexport { UserMessageComponent } from \"./user-message.ts\";\nexport { UserMessageSelectorComponent } from \"./user-message-selector.ts\";\nexport { WorkingStatusComponent, type WorkingStatusComponentOptions } from \"./working-status.ts\";\nexport { truncateToVisualLines, type VisualTruncateResult } from \"./visual-truncate.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,GAGvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,GAMhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,iCAAiC,EACjC,2BAA2B,GAK5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAA0B,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EACL,yBAAyB,GAG1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAA2C,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAA+C,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAChH,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAA6B,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAsC,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAA6B,MAAM,sBAAsB,CAAC","sourcesContent":["// UI Components for extensions\nexport { ArminComponent } from \"./armin.ts\";\nexport { AssistantMessageComponent } from \"./assistant-message.ts\";\nexport { BashExecutionComponent } from \"./bash-execution.ts\";\nexport { BorderedLoader } from \"./bordered-loader.ts\";\nexport {\n chatEntriesFromAgentMessages,\n LiveChatEntriesController,\n renderChatMessageEntry,\n type ChatMessageEntry,\n type ChatMessageRenderOptions,\n} from \"./chat-message-renderer.ts\";\nexport {\n ChatSessionHost,\n type ChatSessionHostBashRequest,\n type ChatSessionHostCommands,\n type ChatSessionHostEntry,\n type ChatSessionHostOpts,\n type ChatSessionHostStyle,\n} from \"./chat-session-host.ts\";\nexport {\n addChatTranscriptEntry,\n ChatTranscriptComponent,\n ScrollableChatTranscriptComponent,\n ScrollableComponentViewport,\n type ChatTranscriptCacheKey,\n type ChatTranscriptEntryLike,\n type ChatTranscriptRenderer,\n type ChatTranscriptRole,\n} from \"./chat-transcript.ts\";\nexport { BranchSummaryMessageComponent } from \"./branch-summary-message.ts\";\nexport { CompactionSummaryMessageComponent } from \"./compaction-summary-message.ts\";\nexport { CustomEditor } from \"./custom-editor.ts\";\nexport { CustomMessageComponent } from \"./custom-message.ts\";\nexport { DaxnutsComponent } from \"./daxnuts.ts\";\nexport { type RenderDiffOptions, renderDiff } from \"./diff.ts\";\nexport { DynamicBorder } from \"./dynamic-border.ts\";\nexport { ExtensionEditorComponent } from \"./extension-editor.ts\";\nexport { ExtensionInputComponent } from \"./extension-input.ts\";\nexport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\nexport {\n FastModeSelectorComponent,\n type FastModeSelectorCallbacks,\n type FastModeSelectorConfig,\n} from \"./fast-mode-selector.ts\";\nexport { FooterComponent, UsageMeterComponent } from \"./footer.ts\";\nexport { keyHint, keyText, rawKeyHint } from \"./keybinding-hints.ts\";\nexport { LoginDialogComponent } from \"./login-dialog.ts\";\nexport { ModelSelectorComponent } from \"./model-selector.ts\";\nexport { OAuthSelectorComponent } from \"./oauth-selector.ts\";\nexport { type ModelsCallbacks, type ModelsConfig, ScopedModelsSelectorComponent } from \"./scoped-models-selector.ts\";\nexport { SessionSelectorComponent } from \"./session-selector.ts\";\nexport { type SettingsCallbacks, type SettingsConfig, SettingsSelectorComponent } from \"./settings-selector.ts\";\nexport { ShowImagesSelectorComponent } from \"./show-images-selector.ts\";\nexport { SkillInvocationMessageComponent } from \"./skill-invocation-message.ts\";\nexport { ThemeSelectorComponent } from \"./theme-selector.ts\";\nexport { ThinkingSelectorComponent } from \"./thinking-selector.ts\";\nexport { ToolExecutionComponent, type ToolExecutionOptions } from \"./tool-execution.ts\";\nexport { TreeSelectorComponent } from \"./tree-selector.ts\";\nexport { UserMessageComponent } from \"./user-message.ts\";\nexport { UserMessageSelectorComponent } from \"./user-message-selector.ts\";\nexport { WorkingStatusComponent, type WorkingStatusComponentOptions } from \"./working-status.ts\";\nexport { truncateToVisualLines, type VisualTruncateResult } from \"./visual-truncate.ts\";\n"]}
package/docs/workflows.md CHANGED
@@ -152,7 +152,7 @@ For the builtin result tables below, `deep-research-codebase`, `goal`, and `ralp
152
152
  |---|---|---|
153
153
  | `deep-research-codebase` | Scout + research-history chain → parallel specialist waves → aggregator. Indexes the whole repo and synthesizes findings. | Broad or cross-cutting research before you decide what to change. Prefer `/skill:research-codebase` for one subsystem. |
154
154
  | `goal` | Persisted goal ledger → bounded worker turns → receipts → three-reviewer gate → deterministic reducer → final report. | Small-to-medium scope changes when you can identify the work surface, state the exact outcome, and name the validation that proves it is done — for example tests, lint/typecheck, docs builds, or observable behavior. |
155
- | `ralph` | RFC planning → sub-agent orchestration → simplification → infrastructure discovery → parallel review → PR handoff. | Larger migrations, broad refactors, multi-package changes, and spec-to-PR work where you want Atomic to plan the approach, delegate implementation through sub-agents, simplify, review, iterate, and prepare a pull-request report. |
155
+ | `ralph` | RFC planning → sub-agent orchestration → simplification → parallel review → PR handoff. | Larger migrations, broad refactors, multi-package changes, and spec-to-PR work where you want Atomic to plan the approach, delegate implementation through sub-agents, simplify, review, iterate, and prepare a pull-request report. |
156
156
  | `open-claude-design` | Design-system onboarding → reference import → HTML generation → impeccable-driven refinement → quality gate → rich HTML handoff. Renders a live `preview.html` you can iterate against (opens through `browser-use` when available). | UI, page, component, theme, or design-token work that benefits from generation + critique loops. |
157
157
 
158
158
  ### `deep-research-codebase`
@@ -260,7 +260,7 @@ Run examples:
260
260
  /workflow ralph prompt="Safely implement the API refactor" git_worktree_dir=../atomic-ralph-api-wt base_branch=main
261
261
  ```
262
262
 
263
- Each `ralph` iteration writes an RFC-style technical design document under `specs/`, initializes an OS-temp implementation notes file, delegates implementation through sub-agents, runs a behavior-preserving code simplifier, discovers review infrastructure, and asks two reviewers to inspect the patch against `base_branch`. The loop stops when every reviewer approves or `max_loops` is reached, then runs a pull-request preparation stage.
263
+ Each `ralph` iteration writes an RFC-style technical design document under `specs/`, initializes an OS-temp implementation notes file, delegates implementation through sub-agents, runs a behavior-preserving code simplifier, and asks two reviewers to inspect the patch directly against `base_branch`. Reviewers discover any needed repository infrastructure themselves while inspecting the actual diff; Ralph no longer runs separate `infra-*` discovery stages. The loop stops when every reviewer approves or `max_loops` is reached, then runs a pull-request preparation stage.
264
264
 
265
265
  Set `git_worktree_dir` when you want Ralph's worker stages isolated in a reusable Git worktree. Relative paths resolve from the invoking repository root, existing same-repository worktree roots are reused, and missing paths are created from `base_branch`. Ralph preserves the invoking repo-relative cwd inside the worktree, so launching from `repo/packages/api` with `git_worktree_dir=../repo-wt` runs stages from `../repo-wt/packages/api`.
266
266
 
@@ -275,7 +275,8 @@ Result fields:
275
275
  | `pr_report` | Pull-request preparation report: diff review, PR status, commands, and follow-up steps. |
276
276
  | `approved` | Whether the reviewer loop approved before PR handoff. |
277
277
  | `iterations_completed` | Number of plan/orchestrate/review loops completed. |
278
- | `review_report` | Markdown report containing the latest reviewer payloads. |
278
+ | `review_report` | Compact reference to the latest reviewer payload artifact. |
279
+ | `review_report_path` | JSON artifact path for the latest Ralph review round. |
279
280
 
280
281
  A typical end-to-end flow is `/skill:research-codebase` → `/skill:create-spec` → `/workflow goal objective="Implement the researched rate-limit behavior, run the focused tests, and finish when the documented burst behavior is validated"` when you can identify the work surface, state the exact outcome, and name the validation that proves it is done. Keep using `/workflow ralph` for larger migrations, broad refactors, multi-package changes, and spec-to-PR work where you want Atomic to plan, delegate through sub-agents, simplify, review, iterate, and prepare a pull-request report.
281
282
 
@@ -780,22 +781,46 @@ export default defineWorkflow("my-workflow")
780
781
  .run(async (ctx) => {
781
782
  const prompt = String(ctx.inputs.prompt);
782
783
 
783
- const scout = await ctx.task("scout", {
784
+ const scoutPath = ".atomic/workflows/runs/my-workflow/scout.md";
785
+ const reviewPaths = {
786
+ quality: ".atomic/workflows/runs/my-workflow/quality.md",
787
+ runtime: ".atomic/workflows/runs/my-workflow/runtime.md",
788
+ } as const;
789
+
790
+ await ctx.task("scout", {
784
791
  prompt: `Map the relevant context for: ${prompt}`,
785
792
  context: "fresh",
793
+ output: scoutPath,
794
+ outputMode: "file-only",
786
795
  });
787
796
 
788
797
  const reviews = await ctx.parallel(
789
798
  [
790
- { name: "quality", prompt: "Inspect quality risks using this context: {previous}", previous: scout },
791
- { name: "runtime", prompt: "Inspect runtime concerns using this context: {previous}", previous: scout },
799
+ {
800
+ name: "quality",
801
+ prompt: `Scout artifact: ${scoutPath}\nRead the file at ${scoutPath} and inspect only sections needed for this quality review.`,
802
+ reads: [scoutPath],
803
+ output: reviewPaths.quality,
804
+ outputMode: "file-only",
805
+ },
806
+ {
807
+ name: "runtime",
808
+ prompt: `Scout artifact: ${scoutPath}\nRead the file at ${scoutPath} and inspect only sections needed for this runtime review.`,
809
+ reads: [scoutPath],
810
+ output: reviewPaths.runtime,
811
+ outputMode: "file-only",
812
+ },
792
813
  ],
793
814
  { concurrency: 2 },
794
815
  );
795
816
 
796
817
  const final = await ctx.task("synthesis", {
797
- prompt: "Synthesize findings and recommend next steps.",
798
- previous: reviews,
818
+ prompt: [
819
+ `Quality review: ${reviewPaths.quality}`,
820
+ `Runtime review: ${reviewPaths.runtime}`,
821
+ "Read the files at the paths above incrementally, then synthesize findings and recommend next steps.",
822
+ ].join("\n"),
823
+ reads: Object.values(reviewPaths),
799
824
  });
800
825
 
801
826
  return { summary: final.text, reviewer_count: reviews.length };
@@ -846,17 +871,22 @@ Workflow outputs are runtime contracts for completed workflow runs and for paren
846
871
 
847
872
  ```ts
848
873
  export default defineWorkflow("review-with-summary")
849
- .output("research_summary", Type.String())
874
+ .output("research_artifact", Type.String())
850
875
  .output("review", Type.String())
851
876
  .run(async (ctx) => {
852
- const research = await ctx.task("research", { prompt: "Research the target." });
877
+ const researchPath = ".atomic/workflows/runs/review-with-summary/research.md";
878
+ await ctx.task("research", {
879
+ prompt: "Research the target.",
880
+ output: researchPath,
881
+ outputMode: "file-only",
882
+ });
853
883
  const review = await ctx.task("review", {
854
- prompt: "Review using this research:\n\n{previous}",
855
- previous: research,
884
+ prompt: `Research artifact: ${researchPath}\nRead the file at ${researchPath} incrementally and summarize risks.`,
885
+ reads: [researchPath],
856
886
  });
857
887
 
858
888
  return {
859
- research_summary: research.text,
889
+ research_artifact: researchPath,
860
890
  review: review.text,
861
891
  };
862
892
  })
@@ -1124,13 +1154,13 @@ Prefer high-level primitives because they create tracked graph nodes, provide co
1124
1154
  | Pure deterministic computation, parsing, or file I/O | Plain TypeScript in `.run()` or helpers |
1125
1155
  | Fine-grained session control | `ctx.stage(name, options?)` |
1126
1156
 
1127
- Use `previous` and `{previous}` for context handoff. If no placeholder is present, the runtime appends context. Chain defaults are:
1157
+ Use `previous` and `{previous}` for compact handoffs only. If no placeholder is present, the runtime appends context, so a large `previous` payload can silently bloat the next model prompt. Chain defaults are:
1128
1158
 
1129
1159
  - first missing task uses `{task}` from chain options or the root direct task
1130
1160
  - later missing tasks use `{previous}`
1131
1161
  - missing tasks in chain-parallel groups use `{previous}`
1132
1162
 
1133
- For large handoffs, save artifacts and pass file references instead of full transcripts.
1163
+ For large handoffs, write artifacts to files, pass their paths with `reads`, and tell downstream stages to read those files incrementally. Put the instruction in the downstream prompt explicitly, e.g. `Read the file at ${artifactPath} and use only the sections needed for this stage.` Prefer `outputMode: "file-only"` when the parent only needs the artifact path.
1134
1164
 
1135
1165
  ### Fine-Grained Stages
1136
1166
 
@@ -1149,7 +1179,7 @@ Use `ctx.stage(name, options?)` when `ctx.task` is too coarse and you need direc
1149
1179
  Common task/stage options include:
1150
1180
 
1151
1181
  - `prompt` or `task`
1152
- - `previous` for handoff context
1182
+ - `previous` for small handoff context; use artifact paths plus `reads` for large outputs, logs, research bundles, or reviewer payloads
1153
1183
  - `context: "fresh" | "fork"`, `forkFromSessionFile`
1154
1184
  - `model`, `fallbackModels`, `thinkingLevel`, `scopedModels`, `modelRegistry`
1155
1185
  - `tools`, `noTools`, `customTools`, `mcp: { allow?: string[], deny?: string[] }`
@@ -1272,7 +1302,24 @@ A good compressed handoff includes:
1272
1302
  - rejected alternatives when they matter
1273
1303
  - next action expected from the downstream stage
1274
1304
 
1275
- Use `output`, `outputMode: "file-only"`, `reads`, and `chainDir` for large research bundles, logs, or reviewer outputs. Keep summaries compact and let downstream stages read full artifacts only when needed.
1305
+ Use `output`, `outputMode: "file-only"`, `reads`, and `chainDir` for large research bundles, logs, or reviewer outputs. Keep summaries compact and let downstream stages read full artifacts only when needed. In the downstream stage prompt, explicitly say something like `Read the file at ${artifactPath} before continuing.` Do not inject full session tails, all previous stage outputs, or every prior review round into later prompts by default; pass the latest relevant artifact paths and make older history discoverable from a ledger or index file.
1306
+
1307
+ ```ts
1308
+ const researchPath = ".atomic/workflows/runs/context-demo/research.md";
1309
+ await ctx.task("researcher", {
1310
+ task: "Map the subsystem and save the report.",
1311
+ output: researchPath,
1312
+ outputMode: "file-only",
1313
+ });
1314
+
1315
+ const review = await ctx.task("reviewer", {
1316
+ task: [
1317
+ `Research artifact: ${researchPath}`,
1318
+ `Read the file at ${researchPath} incrementally and inspect only the sections needed for this review.`,
1319
+ ].join("\n"),
1320
+ reads: [researchPath],
1321
+ });
1322
+ ```
1276
1323
 
1277
1324
  ### Multi-Agent and Parallel Patterns
1278
1325
 
@@ -1305,6 +1352,8 @@ Recommended patterns:
1305
1352
 
1306
1353
  - write large tool outputs to files and return concise references
1307
1354
  - store plans, state, and reviewer findings in structured markdown or JSON
1355
+ - pass artifact paths via `reads`; prompt agents with `Read the file at <path>...` rather than pasting artifacts into `{previous}`
1356
+ - for review loops, pass the latest review-round artifact first and let a ledger/index point to older rounds only when needed
1308
1357
  - give parallel branches separate output paths to avoid write conflicts
1309
1358
  - use `grep`, globbing, and line-range reads instead of loading entire logs
1310
1359
  - clean scratch files or keep them under run-specific directories
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.8.22",
3
+ "version": "0.8.23",
4
4
  "description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "atomicConfig": {