@kenkaiiii/ggcoder 3.6.4 → 3.6.5

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 (89) hide show
  1. package/README.md +158 -0
  2. package/dist/config.d.ts +1 -1
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +1 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/core/socket-server.d.ts +15 -0
  7. package/dist/core/socket-server.d.ts.map +1 -0
  8. package/dist/core/socket-server.js +140 -0
  9. package/dist/core/socket-server.js.map +1 -0
  10. package/dist/system-prompt.d.ts.map +1 -1
  11. package/dist/system-prompt.js +4 -0
  12. package/dist/system-prompt.js.map +1 -1
  13. package/dist/tools/index.d.ts +1 -0
  14. package/dist/tools/index.d.ts.map +1 -1
  15. package/dist/tools/index.js +3 -0
  16. package/dist/tools/index.js.map +1 -1
  17. package/dist/tools/tasks.d.ts +16 -0
  18. package/dist/tools/tasks.d.ts.map +1 -0
  19. package/dist/tools/tasks.js +132 -0
  20. package/dist/tools/tasks.js.map +1 -0
  21. package/dist/ui/App.d.ts +6 -1
  22. package/dist/ui/App.d.ts.map +1 -1
  23. package/dist/ui/App.js +232 -39
  24. package/dist/ui/App.js.map +1 -1
  25. package/dist/ui/components/ActivityIndicator.d.ts +2 -1
  26. package/dist/ui/components/ActivityIndicator.d.ts.map +1 -1
  27. package/dist/ui/components/ActivityIndicator.js +81 -6
  28. package/dist/ui/components/ActivityIndicator.js.map +1 -1
  29. package/dist/ui/components/Banner.d.ts +2 -1
  30. package/dist/ui/components/Banner.d.ts.map +1 -1
  31. package/dist/ui/components/Banner.js +2 -2
  32. package/dist/ui/components/Banner.js.map +1 -1
  33. package/dist/ui/components/InputArea.d.ts +2 -1
  34. package/dist/ui/components/InputArea.d.ts.map +1 -1
  35. package/dist/ui/components/InputArea.js +6 -1
  36. package/dist/ui/components/InputArea.js.map +1 -1
  37. package/dist/ui/components/Markdown.d.ts +2 -0
  38. package/dist/ui/components/Markdown.d.ts.map +1 -1
  39. package/dist/ui/components/Markdown.js +70 -71
  40. package/dist/ui/components/Markdown.js.map +1 -1
  41. package/dist/ui/components/ShimmerLine.d.ts +1 -1
  42. package/dist/ui/components/ShimmerLine.d.ts.map +1 -1
  43. package/dist/ui/components/ShimmerLine.js +22 -34
  44. package/dist/ui/components/ShimmerLine.js.map +1 -1
  45. package/dist/ui/components/StreamingArea.d.ts.map +1 -1
  46. package/dist/ui/components/StreamingArea.js +40 -4
  47. package/dist/ui/components/StreamingArea.js.map +1 -1
  48. package/dist/ui/components/TaskOverlay.d.ts +10 -0
  49. package/dist/ui/components/TaskOverlay.d.ts.map +1 -0
  50. package/dist/ui/components/TaskOverlay.js +263 -0
  51. package/dist/ui/components/TaskOverlay.js.map +1 -0
  52. package/dist/ui/components/ToolExecution.js +38 -0
  53. package/dist/ui/components/ToolExecution.js.map +1 -1
  54. package/dist/ui/components/UserMessage.js +3 -3
  55. package/dist/ui/components/UserMessage.js.map +1 -1
  56. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  57. package/dist/ui/hooks/useAgentLoop.js +38 -11
  58. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  59. package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
  60. package/dist/ui/hooks/useTerminalSize.js +4 -8
  61. package/dist/ui/hooks/useTerminalSize.js.map +1 -1
  62. package/dist/ui/hooks/useTerminalTitle.js +2 -2
  63. package/dist/ui/hooks/useTerminalTitle.js.map +1 -1
  64. package/dist/ui/live-item-flush.d.ts +49 -0
  65. package/dist/ui/live-item-flush.d.ts.map +1 -0
  66. package/dist/ui/live-item-flush.js +56 -0
  67. package/dist/ui/live-item-flush.js.map +1 -0
  68. package/dist/ui/live-item-flush.test.d.ts +2 -0
  69. package/dist/ui/live-item-flush.test.d.ts.map +1 -0
  70. package/dist/ui/live-item-flush.test.js +307 -0
  71. package/dist/ui/live-item-flush.test.js.map +1 -0
  72. package/dist/ui/render.d.ts.map +1 -1
  73. package/dist/ui/render.js +3 -12
  74. package/dist/ui/render.js.map +1 -1
  75. package/dist/ui/utils/table-text.d.ts +25 -0
  76. package/dist/ui/utils/table-text.d.ts.map +1 -0
  77. package/dist/ui/utils/table-text.js +78 -0
  78. package/dist/ui/utils/table-text.js.map +1 -0
  79. package/dist/ui/utils/table-text.test.d.ts +2 -0
  80. package/dist/ui/utils/table-text.test.d.ts.map +1 -0
  81. package/dist/ui/utils/table-text.test.js +202 -0
  82. package/dist/ui/utils/table-text.test.js.map +1 -0
  83. package/dist/utils/format.js +1 -1
  84. package/dist/utils/format.js.map +1 -1
  85. package/dist/utils/sound.d.ts +2 -0
  86. package/dist/utils/sound.d.ts.map +1 -0
  87. package/dist/utils/sound.js +11 -0
  88. package/dist/utils/sound.js.map +1 -0
  89. package/package.json +7 -5
@@ -0,0 +1,307 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { pruneHistory, flushOnTurnText, flushOnTurnEnd, MAX_HISTORY_ITEMS, } from "./live-item-flush.js";
3
+ // ── Test helpers ──────────────────────────────────────────
4
+ let idCounter = 0;
5
+ function id() {
6
+ return `test-${++idCounter}`;
7
+ }
8
+ function userItem() {
9
+ return { kind: "user", id: id() };
10
+ }
11
+ function assistantItem() {
12
+ return { kind: "assistant", id: id() };
13
+ }
14
+ function toolStart(toolCallId) {
15
+ return { kind: "tool_start", id: id(), toolCallId: toolCallId ?? id() };
16
+ }
17
+ function toolDone() {
18
+ return { kind: "tool_done", id: id() };
19
+ }
20
+ function subagentGroup() {
21
+ return { kind: "subagent_group", id: id() };
22
+ }
23
+ function errorItem() {
24
+ return { kind: "error", id: id() };
25
+ }
26
+ // ── pruneHistory ──────────────────────────────────────────
27
+ describe("pruneHistory", () => {
28
+ it("returns items unchanged when under the limit", () => {
29
+ const items = [userItem(), assistantItem(), toolDone()];
30
+ const result = pruneHistory(items);
31
+ expect(result).toBe(items); // same reference, no copy
32
+ });
33
+ it("returns items unchanged at exactly the limit", () => {
34
+ const items = Array.from({ length: MAX_HISTORY_ITEMS }, () => userItem());
35
+ const result = pruneHistory(items);
36
+ expect(result).toBe(items);
37
+ });
38
+ it("drops oldest items when over the limit", () => {
39
+ const items = Array.from({ length: MAX_HISTORY_ITEMS + 50 }, (_, i) => ({
40
+ kind: "user",
41
+ id: `item-${i}`,
42
+ }));
43
+ const result = pruneHistory(items);
44
+ expect(result).toHaveLength(MAX_HISTORY_ITEMS);
45
+ // Should keep the LAST 500 items (newest)
46
+ expect(result[0].id).toBe("item-50");
47
+ expect(result[result.length - 1].id).toBe(`item-${MAX_HISTORY_ITEMS + 49}`);
48
+ });
49
+ it("handles empty array", () => {
50
+ const result = pruneHistory([]);
51
+ expect(result).toEqual([]);
52
+ });
53
+ it("handles single item", () => {
54
+ const items = [userItem()];
55
+ const result = pruneHistory(items);
56
+ expect(result).toBe(items);
57
+ });
58
+ });
59
+ // ── flushOnTurnText ───────────────────────────────────────
60
+ describe("flushOnTurnText", () => {
61
+ it("returns all items for flushing when liveItems is non-empty", () => {
62
+ const items = [assistantItem(), toolDone(), toolDone()];
63
+ const flushed = flushOnTurnText(items);
64
+ expect(flushed).toBe(items);
65
+ expect(flushed).toHaveLength(3);
66
+ });
67
+ it("returns empty array when liveItems is empty", () => {
68
+ const flushed = flushOnTurnText([]);
69
+ expect(flushed).toEqual([]);
70
+ });
71
+ it("flushes tool_start items (they are from a completed turn)", () => {
72
+ // When onTurnText fires, even stale tool_start items from the same turn
73
+ // are complete (tool_end already replaced them in the normal flow, but
74
+ // if somehow a tool_start remains, the turn is still over).
75
+ const items = [assistantItem(), toolStart(), toolDone()];
76
+ const flushed = flushOnTurnText(items);
77
+ expect(flushed).toHaveLength(3);
78
+ });
79
+ it("flushes mixed item types from multi-turn accumulation", () => {
80
+ // Simulates items accumulated across multiple turns before flush was added
81
+ const items = [
82
+ userItem(),
83
+ assistantItem(),
84
+ toolDone(),
85
+ toolDone(),
86
+ assistantItem(),
87
+ toolDone(),
88
+ toolDone(),
89
+ toolDone(),
90
+ assistantItem(),
91
+ ];
92
+ const flushed = flushOnTurnText(items);
93
+ expect(flushed).toHaveLength(9);
94
+ });
95
+ it("flushes subagent group items", () => {
96
+ const items = [assistantItem(), subagentGroup(), toolDone()];
97
+ const flushed = flushOnTurnText(items);
98
+ expect(flushed).toHaveLength(3);
99
+ });
100
+ it("flushes error items", () => {
101
+ const items = [errorItem(), assistantItem()];
102
+ const flushed = flushOnTurnText(items);
103
+ expect(flushed).toHaveLength(2);
104
+ });
105
+ });
106
+ // ── flushOnTurnEnd ────────────────────────────────────────
107
+ describe("flushOnTurnEnd", () => {
108
+ describe("with tool_use stop reason", () => {
109
+ it("flushes all items when no pending tool_start exists", () => {
110
+ const items = [assistantItem(), toolDone(), toolDone()];
111
+ const { flushed, remaining } = flushOnTurnEnd(items, "tool_use");
112
+ expect(flushed).toBe(items);
113
+ expect(flushed).toHaveLength(3);
114
+ expect(remaining).toEqual([]);
115
+ });
116
+ it("does NOT flush when a tool_start is still pending", () => {
117
+ const items = [assistantItem(), toolStart(), toolDone()];
118
+ const { flushed, remaining } = flushOnTurnEnd(items, "tool_use");
119
+ expect(flushed).toEqual([]);
120
+ expect(remaining).toBe(items);
121
+ expect(remaining).toHaveLength(3);
122
+ });
123
+ it("does NOT flush when liveItems is empty", () => {
124
+ const { flushed, remaining } = flushOnTurnEnd([], "tool_use");
125
+ expect(flushed).toEqual([]);
126
+ expect(remaining).toEqual([]);
127
+ });
128
+ it("does NOT flush when only tool_start items exist (all pending)", () => {
129
+ const items = [toolStart(), toolStart()];
130
+ const { flushed, remaining } = flushOnTurnEnd(items, "tool_use");
131
+ expect(flushed).toEqual([]);
132
+ expect(remaining).toBe(items);
133
+ });
134
+ it("flushes when items include subagent groups with no pending tool_start", () => {
135
+ const items = [subagentGroup(), toolDone()];
136
+ const { flushed, remaining } = flushOnTurnEnd(items, "tool_use");
137
+ expect(flushed).toHaveLength(2);
138
+ expect(remaining).toEqual([]);
139
+ });
140
+ });
141
+ describe("with non-tool_use stop reasons", () => {
142
+ it("does NOT flush for end_turn stop reason", () => {
143
+ const items = [assistantItem(), toolDone()];
144
+ const { flushed, remaining } = flushOnTurnEnd(items, "end_turn");
145
+ expect(flushed).toEqual([]);
146
+ expect(remaining).toBe(items);
147
+ });
148
+ it("does NOT flush for stop_sequence stop reason", () => {
149
+ const items = [assistantItem()];
150
+ const { flushed, remaining } = flushOnTurnEnd(items, "stop_sequence");
151
+ expect(flushed).toEqual([]);
152
+ expect(remaining).toBe(items);
153
+ });
154
+ it("does NOT flush for max_tokens stop reason", () => {
155
+ const items = [assistantItem(), toolDone(), toolDone()];
156
+ const { flushed, remaining } = flushOnTurnEnd(items, "max_tokens");
157
+ expect(flushed).toEqual([]);
158
+ expect(remaining).toBe(items);
159
+ });
160
+ });
161
+ });
162
+ // ── Integration: simulated agent run scenarios ────────────
163
+ describe("flush integration scenarios", () => {
164
+ /**
165
+ * Simulates the state management that App.tsx does with setLiveItems
166
+ * and setHistory, using the extracted pure functions.
167
+ */
168
+ function simulateRun(turns) {
169
+ let liveItems = [];
170
+ let history = [];
171
+ for (const turn of turns) {
172
+ // Simulate tool calls happening before turn_end
173
+ for (let i = 0; i < (turn.tools ?? 0); i++) {
174
+ liveItems = [...liveItems, toolStart()];
175
+ // Tool completes (replaces tool_start with tool_done in real code)
176
+ liveItems = liveItems.map((item) => item.kind === "tool_start" && liveItems.indexOf(item) === liveItems.length - 1
177
+ ? toolDone()
178
+ : item);
179
+ }
180
+ // onTurnEnd fires first
181
+ const turnEndResult = flushOnTurnEnd(liveItems, turn.stopReason);
182
+ if (turnEndResult.flushed.length > 0) {
183
+ history = pruneHistory([...history, ...turnEndResult.flushed]);
184
+ }
185
+ liveItems = turnEndResult.remaining;
186
+ // onTurnText fires second (only if text exists)
187
+ if (turn.text) {
188
+ const flushed = flushOnTurnText(liveItems);
189
+ if (flushed.length > 0) {
190
+ history = pruneHistory([...history, ...flushed]);
191
+ }
192
+ liveItems = [assistantItem()]; // new text item
193
+ }
194
+ }
195
+ return { liveItems, history };
196
+ }
197
+ it("scenario: simple text-only conversation stays bounded", () => {
198
+ const { liveItems, history } = simulateRun([
199
+ { text: "Hello!", stopReason: "end_turn" },
200
+ { text: "How can I help?", stopReason: "end_turn" },
201
+ { text: "Sure thing.", stopReason: "end_turn" },
202
+ ]);
203
+ // Only the last text item should be live
204
+ expect(liveItems).toHaveLength(1);
205
+ expect(liveItems[0].kind).toBe("assistant");
206
+ // Previous text items moved to history
207
+ expect(history).toHaveLength(2);
208
+ });
209
+ it("scenario: text + tools cycle stays bounded", () => {
210
+ const { liveItems, history } = simulateRun([
211
+ { text: "Let me check.", tools: 3, stopReason: "end_turn" },
212
+ { text: "Found it.", tools: 2, stopReason: "end_turn" },
213
+ { text: "Done.", stopReason: "end_turn" },
214
+ ]);
215
+ expect(liveItems).toHaveLength(1);
216
+ // 3 tool_done + 1 assistant + 2 tool_done + 1 assistant = 7
217
+ expect(history).toHaveLength(7);
218
+ });
219
+ it("scenario: tool-only turns flush correctly", () => {
220
+ const { liveItems, history } = simulateRun([
221
+ { tools: 3, stopReason: "tool_use" }, // tool-only, flushed by onTurnEnd
222
+ { tools: 2, stopReason: "tool_use" }, // tool-only, flushed by onTurnEnd
223
+ { text: "All done.", stopReason: "end_turn" },
224
+ ]);
225
+ expect(liveItems).toHaveLength(1);
226
+ expect(liveItems[0].kind).toBe("assistant");
227
+ expect(history).toHaveLength(5); // 3 + 2 tool_done items
228
+ });
229
+ it("scenario: many turns — liveItems never exceeds current turn size", () => {
230
+ const turns = Array.from({ length: 50 }, (_, i) => ({
231
+ text: `Turn ${i}`,
232
+ tools: 5,
233
+ stopReason: "end_turn",
234
+ }));
235
+ const { liveItems } = simulateRun(turns);
236
+ // Only the last text item should remain live
237
+ expect(liveItems).toHaveLength(1);
238
+ });
239
+ it("scenario: alternating text and tool-only turns", () => {
240
+ const { liveItems, history } = simulateRun([
241
+ { text: "Searching...", tools: 2, stopReason: "end_turn" },
242
+ { tools: 3, stopReason: "tool_use" }, // tool-only
243
+ { text: "Found results.", tools: 1, stopReason: "end_turn" },
244
+ { tools: 4, stopReason: "tool_use" }, // tool-only
245
+ { text: "Complete.", stopReason: "end_turn" },
246
+ ]);
247
+ expect(liveItems).toHaveLength(1);
248
+ // History: (2 tools + 1 text) + (3 tools) + (1 tool + 1 text) + (4 tools) = 12
249
+ expect(history).toHaveLength(12);
250
+ });
251
+ it("scenario: stress test — 100 turns with 10 tools each", () => {
252
+ const turns = Array.from({ length: 100 }, () => ({
253
+ text: "Working...",
254
+ tools: 10,
255
+ stopReason: "end_turn",
256
+ }));
257
+ const { liveItems, history } = simulateRun(turns);
258
+ expect(liveItems).toHaveLength(1);
259
+ // Total items: 100 turns * (10 tools + 1 text) - 1 (last text is live) = 1099
260
+ // But pruneHistory caps at 500
261
+ expect(history).toHaveLength(MAX_HISTORY_ITEMS);
262
+ });
263
+ it("REGRESSION: liveItems retained after agent finishes, flushed on next submit", () => {
264
+ // After the agent finishes its last turn, the final AssistantItem stays
265
+ // in liveItems (NOT moved to Static via useEffect). This prevents Ink
266
+ // cursor-math glitches that caused text to get cut off during the
267
+ // live→Static transition. Items are flushed when the user submits the
268
+ // next message (simulated here by flushing before adding a new userItem).
269
+ let liveItems = [];
270
+ let history = [];
271
+ // Agent produces a response (turn 1)
272
+ const flushed1 = flushOnTurnText(liveItems);
273
+ if (flushed1.length > 0)
274
+ history = pruneHistory([...history, ...flushed1]);
275
+ liveItems = [assistantItem()];
276
+ // Agent finishes — liveItems NOT cleared (no useEffect flush)
277
+ // The final response stays in liveItems
278
+ expect(liveItems).toHaveLength(1);
279
+ expect(liveItems[0].kind).toBe("assistant");
280
+ // User submits next message — NOW flush to Static
281
+ if (liveItems.length > 0) {
282
+ history = pruneHistory([...history, ...liveItems]);
283
+ }
284
+ liveItems = [userItem()];
285
+ // Previous AssistantItem is now in history
286
+ expect(history).toHaveLength(1);
287
+ expect(history[0].kind).toBe("assistant");
288
+ // New user message is in liveItems
289
+ expect(liveItems).toHaveLength(1);
290
+ expect(liveItems[0].kind).toBe("user");
291
+ });
292
+ it("REGRESSION: without flush, liveItems would grow unbounded", () => {
293
+ // This test documents the old behavior — liveItems would contain
294
+ // ALL items from ALL turns. With 20 turns of 5 tools each, that's
295
+ // 20 * (5 + 1) = 120 items re-rendered on every timer tick.
296
+ // With the fix, liveItems is always at most 1 item (current text).
297
+ const turns = Array.from({ length: 20 }, () => ({
298
+ text: "Working...",
299
+ tools: 5,
300
+ stopReason: "end_turn",
301
+ }));
302
+ const { liveItems } = simulateRun(turns);
303
+ // The whole point: liveItems MUST be bounded
304
+ expect(liveItems.length).toBeLessThanOrEqual(1);
305
+ });
306
+ });
307
+ //# sourceMappingURL=live-item-flush.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-item-flush.test.js","sourceRoot":"","sources":["../../src/ui/live-item-flush.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/ui/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAO,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAInD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACrC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3D,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpF,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGtE"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/ui/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAO,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAInD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACrC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3D,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpF,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAwFtE"}
package/dist/ui/render.js CHANGED
@@ -6,12 +6,8 @@ import { ThemeContext, loadTheme } from "./theme/theme.js";
6
6
  export async function renderApp(config) {
7
7
  const theme = loadTheme(config.theme ?? "dark");
8
8
  const isRestoredSession = config.initialHistory && config.initialHistory.length > 0;
9
- const rows = process.stdout.rows ?? 24;
10
- // Clear screen and set scroll region (DECSTBM) to pin row 1 for the shimmer line
11
- process.stdout.write("\x1b[2J" + // clear screen
12
- "\x1b[H" + // cursor to row 1, col 1
13
- `\x1b[2;${rows}r` + // scroll region: row 2 to bottom
14
- "\x1b[2;1H");
9
+ // Clear screen
10
+ process.stdout.write("\x1b[2J\x1b[H");
15
11
  // Show animated splash screen for new sessions only (skip for restored sessions)
16
12
  if (!isRestoredSession) {
17
13
  await new Promise((resolve) => {
@@ -24,10 +20,7 @@ export async function renderApp(config) {
24
20
  })));
25
21
  });
26
22
  // Clear screen for the main app
27
- process.stdout.write("\x1b[2J" + // clear screen
28
- "\x1b[H" + // cursor to row 1, col 1
29
- `\x1b[2;${rows}r` + // scroll region: row 2 to bottom
30
- "\x1b[2;1H");
23
+ process.stdout.write("\x1b[2J\x1b[H");
31
24
  }
32
25
  const { waitUntilExit, clear } = render(React.createElement(ThemeContext.Provider, { value: theme }, React.createElement(App, {
33
26
  provider: config.provider,
@@ -77,7 +70,5 @@ export async function renderApp(config) {
77
70
  process.stdout.on("resize", onResize);
78
71
  await waitUntilExit();
79
72
  process.stdout.off("resize", onResize);
80
- // Reset scroll region and clear the shimmer line on exit
81
- process.stdout.write("\x1b[r\x1b[1;1H\x1b[2K");
82
73
  }
83
74
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/ui/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/ui/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { Token } from "marked";
2
+ /** Extract all plain text from a token tree. */
3
+ export declare function extractPlainText(tokens: Token[]): string;
4
+ /** Measure the visual display width of a string (handles CJK, emoji, etc). */
5
+ export declare function visualWidth(str: string): number;
6
+ /**
7
+ * Force a string to exactly `width` visual columns.
8
+ * Truncates if too wide (char-by-char to avoid splitting wide chars),
9
+ * pads with spaces if too narrow.
10
+ */
11
+ export declare function fitToWidth(str: string, width: number): string;
12
+ /**
13
+ * Word-wrap plain text extracted from tokens into lines of at most `width`
14
+ * visual columns. Uses `wrap-ansi` for wrapping, then force-clamps each line
15
+ * to exactly `width` with `fitToWidth` to eliminate measurement mismatches.
16
+ */
17
+ export declare function wrapPlainTextLines(tokens: Token[], width: number): string[];
18
+ /**
19
+ * Center a string within `width` visual columns.
20
+ * Truncates if too wide, pads with spaces on both sides if too narrow.
21
+ */
22
+ export declare function centerToWidth(str: string, width: number): string;
23
+ /** Measure the visual display width of plain text in a token tree. */
24
+ export declare function plainTextLength(tokens: Token[]): number;
25
+ //# sourceMappingURL=table-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-text.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/table-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAIpC,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAaxD;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB7D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ3E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAEvD"}
@@ -0,0 +1,78 @@
1
+ import stringWidth from "string-width";
2
+ import wrapAnsi from "wrap-ansi";
3
+ /** Extract all plain text from a token tree. */
4
+ export function extractPlainText(tokens) {
5
+ let text = "";
6
+ for (const t of tokens) {
7
+ const tok = t;
8
+ if (tok.tokens && Array.isArray(tok.tokens)) {
9
+ text += extractPlainText(tok.tokens);
10
+ }
11
+ else if (typeof tok.text === "string") {
12
+ text += tok.text;
13
+ }
14
+ else if ("raw" in t && typeof t.raw === "string") {
15
+ text += t.raw;
16
+ }
17
+ }
18
+ return text;
19
+ }
20
+ /** Measure the visual display width of a string (handles CJK, emoji, etc). */
21
+ export function visualWidth(str) {
22
+ return stringWidth(str);
23
+ }
24
+ /**
25
+ * Force a string to exactly `width` visual columns.
26
+ * Truncates if too wide (char-by-char to avoid splitting wide chars),
27
+ * pads with spaces if too narrow.
28
+ */
29
+ export function fitToWidth(str, width) {
30
+ const w = visualWidth(str);
31
+ if (w === width)
32
+ return str;
33
+ if (w > width) {
34
+ // Truncate character by character to avoid splitting wide chars
35
+ let result = "";
36
+ let resultWidth = 0;
37
+ for (const ch of str) {
38
+ const chW = visualWidth(ch);
39
+ if (resultWidth + chW > width)
40
+ break;
41
+ result += ch;
42
+ resultWidth += chW;
43
+ }
44
+ // Fill any remaining gap (e.g. wide char didn't fit, left 1 col)
45
+ return result + " ".repeat(width - resultWidth);
46
+ }
47
+ return str + " ".repeat(width - w);
48
+ }
49
+ /**
50
+ * Word-wrap plain text extracted from tokens into lines of at most `width`
51
+ * visual columns. Uses `wrap-ansi` for wrapping, then force-clamps each line
52
+ * to exactly `width` with `fitToWidth` to eliminate measurement mismatches.
53
+ */
54
+ export function wrapPlainTextLines(tokens, width) {
55
+ // Collapse newlines/tabs to spaces — cell text should be a continuous paragraph
56
+ const full = extractPlainText(tokens).replace(/[\n\r\t]+/g, " ");
57
+ if (visualWidth(full) <= width)
58
+ return [full];
59
+ const wrapped = wrapAnsi(full, width, { hard: true, trim: true, wordWrap: true });
60
+ const lines = wrapped.split("\n").filter((l) => l.length > 0);
61
+ return lines.length > 0 ? lines : [""];
62
+ }
63
+ /**
64
+ * Center a string within `width` visual columns.
65
+ * Truncates if too wide, pads with spaces on both sides if too narrow.
66
+ */
67
+ export function centerToWidth(str, width) {
68
+ const w = visualWidth(str);
69
+ if (w >= width)
70
+ return fitToWidth(str, width);
71
+ const leftPad = Math.floor((width - w) / 2);
72
+ return fitToWidth(" ".repeat(leftPad) + str, width);
73
+ }
74
+ /** Measure the visual display width of plain text in a token tree. */
75
+ export function plainTextLength(tokens) {
76
+ return visualWidth(extractPlainText(tokens));
77
+ }
78
+ //# sourceMappingURL=table-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-text.js","sourceRoot":"","sources":["../../../src/ui/utils/table-text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=table-text.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-text.test.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/table-text.test.ts"],"names":[],"mappings":""}