xiaotime 0.5.11 → 0.6.0

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 (57) hide show
  1. package/dist/ansi_tags.js +1 -4
  2. package/dist/ansi_tags.js.map +1 -1
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +11 -50
  5. package/dist/auth.js.map +1 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +9 -11
  8. package/dist/config.js.map +1 -1
  9. package/dist/display.d.ts.map +1 -1
  10. package/dist/display.js +168 -210
  11. package/dist/display.js.map +1 -1
  12. package/dist/index.js +27 -25
  13. package/dist/index.js.map +1 -1
  14. package/dist/ink/App.d.ts +9 -0
  15. package/dist/ink/App.d.ts.map +1 -0
  16. package/dist/ink/App.js +152 -0
  17. package/dist/ink/App.js.map +1 -0
  18. package/dist/ink/execToolInk.d.ts +13 -0
  19. package/dist/ink/execToolInk.d.ts.map +1 -0
  20. package/dist/ink/execToolInk.js +239 -0
  21. package/dist/ink/execToolInk.js.map +1 -0
  22. package/dist/ink/runSessionInk.d.ts +2 -0
  23. package/dist/ink/runSessionInk.d.ts.map +1 -0
  24. package/dist/ink/runSessionInk.js +184 -0
  25. package/dist/ink/runSessionInk.js.map +1 -0
  26. package/dist/ink/store.d.ts +102 -0
  27. package/dist/ink/store.d.ts.map +1 -0
  28. package/dist/ink/store.js +144 -0
  29. package/dist/ink/store.js.map +1 -0
  30. package/dist/input_box.js +9 -16
  31. package/dist/input_box.js.map +1 -1
  32. package/dist/projectContext.d.ts +38 -0
  33. package/dist/projectContext.d.ts.map +1 -0
  34. package/dist/projectContext.js +135 -0
  35. package/dist/projectContext.js.map +1 -0
  36. package/dist/session.js +8 -14
  37. package/dist/session.js.map +1 -1
  38. package/dist/session_match.js +1 -4
  39. package/dist/session_match.js.map +1 -1
  40. package/dist/settings.js +8 -48
  41. package/dist/settings.js.map +1 -1
  42. package/dist/sidebar.js +13 -20
  43. package/dist/sidebar.js.map +1 -1
  44. package/dist/tool_result_client.js +6 -11
  45. package/dist/tool_result_client.js.map +1 -1
  46. package/dist/tools.d.ts +5 -0
  47. package/dist/tools.d.ts.map +1 -1
  48. package/dist/tools.js +33 -71
  49. package/dist/tools.js.map +1 -1
  50. package/dist/ui_state.d.ts +1 -0
  51. package/dist/ui_state.d.ts.map +1 -1
  52. package/dist/ui_state.js +33 -61
  53. package/dist/ui_state.js.map +1 -1
  54. package/dist/ws.d.ts.map +1 -1
  55. package/dist/ws.js +77 -111
  56. package/dist/ws.js.map +1 -1
  57. package/package.json +8 -2
package/dist/display.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Output formatting — streaming text, session list, status bar, tool lines.
4
3
  *
@@ -28,44 +27,8 @@
28
27
  * - Tool call errors render as red-bordered box instead of inline text
29
28
  * - Removed "Junior is thinking..." spinner label
30
29
  */
31
- var __importDefault = (this && this.__importDefault) || function (mod) {
32
- return (mod && mod.__esModule) ? mod : { "default": mod };
33
- };
34
- Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.setBotName = setBotName;
36
- exports.getBotName = getBotName;
37
- exports.initStatusBar = initStatusBar;
38
- exports.setConnected = setConnected;
39
- exports.incrementTurn = incrementTurn;
40
- exports.setLastTool = setLastTool;
41
- exports.updateStatusBarCost = updateStatusBarCost;
42
- exports.startSpinner = startSpinner;
43
- exports.stopSpinner = stopSpinner;
44
- exports.startToolLine = startToolLine;
45
- exports.finishToolLine = finishToolLine;
46
- exports.printToolError = printToolError;
47
- exports.printFileDiff = printFileDiff;
48
- exports.printApprovalPrompt = printApprovalPrompt;
49
- exports.printTextDelta = printTextDelta;
50
- exports.printTurnStart = printTurnStart;
51
- exports.printThinkingStart = printThinkingStart;
52
- exports.printThinkingStop = printThinkingStop;
53
- exports.printTurnEnd = printTurnEnd;
54
- exports.consumeFirstPrompt = consumeFirstPrompt;
55
- exports.printPrompt = printPrompt;
56
- exports.printPromptEnd = printPromptEnd;
57
- exports.printWelcome = printWelcome;
58
- exports.printError = printError;
59
- exports.printSessionList = printSessionList;
60
- exports.friendlyToolLabel = friendlyToolLabel;
61
- exports.friendlyError = friendlyError;
62
- exports.printHelp = printHelp;
63
- exports.printDisconnectBanner = printDisconnectBanner;
64
- exports.printExitConfirmation = printExitConfirmation;
65
- exports.printToolCallLine = printToolCallLine;
66
- exports.printServerToolCall = printServerToolCall;
67
- const chalk_1 = __importDefault(require("chalk"));
68
- const cli_highlight_1 = require("cli-highlight");
30
+ import chalk from "chalk";
31
+ import { highlight, supportsLanguage } from "cli-highlight";
69
32
  // Assistant display name. NEVER hardcode "Junior" — DoctorWhiskers/Harvey and
70
33
  // every other tenant render their own assistant name in the same UI. Sourced
71
34
  // from XIAOTIME_BOT_NAME, with a neutral fallback, and overridable at runtime
@@ -86,22 +49,22 @@ function _sanitizeName(raw) {
86
49
  .slice(0, 40);
87
50
  }
88
51
  let _botName = _sanitizeName(process.env.XIAOTIME_BOT_NAME) || "Assistant";
89
- function setBotName(name) {
52
+ export function setBotName(name) {
90
53
  const n = _sanitizeName(name);
91
54
  if (n)
92
55
  _botName = n;
93
56
  }
94
- function getBotName() {
57
+ export function getBotName() {
95
58
  return _botName;
96
59
  }
97
60
  // Force color output — Termius and some SSH clients report level 0
98
61
  // even when the terminal supports 256 colors.
99
- if (chalk_1.default.level === 0 &&
62
+ if (chalk.level === 0 &&
100
63
  (process.env.TERM?.includes("256color") ||
101
64
  process.env.TERM?.includes("xterm") ||
102
65
  process.env.COLORTERM ||
103
66
  process.env.FORCE_COLOR)) {
104
- chalk_1.default.level = 2;
67
+ chalk.level = 2;
105
68
  }
106
69
  // ---------------------------------------------------------------------------
107
70
  // Terminal geometry helpers
@@ -155,7 +118,7 @@ const FILE_PATH_RE = /(?<![`\w])((?:\/[\w.\-]+)+(?:\/[\w.\-]+)?|\.{1,2}\/[\w.\-/
155
118
  function _linkifyPaths(text) {
156
119
  return text.replace(FILE_PATH_RE, (match) => {
157
120
  const url = match.startsWith("/") ? `file://${match}` : `file://${process.cwd()}/${match}`;
158
- return chalk_1.default.underline(osc8Link(url, match));
121
+ return chalk.underline(osc8Link(url, match));
159
122
  });
160
123
  }
161
124
  // ---------------------------------------------------------------------------
@@ -164,37 +127,37 @@ function _linkifyPaths(text) {
164
127
  function renderMarkdownLine(line) {
165
128
  const h3 = line.match(/^### (.+)$/);
166
129
  if (h3)
167
- return chalk_1.default.bold.hex("#94e2d5")(h3[1]);
130
+ return chalk.bold.hex("#94e2d5")(h3[1]);
168
131
  const h2 = line.match(/^## (.+)$/);
169
132
  if (h2)
170
- return chalk_1.default.bold.hex("#89b4fa")(h2[1]);
133
+ return chalk.bold.hex("#89b4fa")(h2[1]);
171
134
  const h1 = line.match(/^# (.+)$/);
172
135
  if (h1)
173
- return chalk_1.default.bold.hex("#c0384b")(h1[1]);
136
+ return chalk.bold.hex("#c0384b")(h1[1]);
174
137
  if (/^---+$/.test(line) || /^\*\*\*+$/.test(line)) {
175
- return chalk_1.default.dim("─".repeat(termWidth()));
138
+ return chalk.dim("─".repeat(termWidth()));
176
139
  }
177
140
  if (line.startsWith("> ")) {
178
- return chalk_1.default.dim.italic(" │ " + line.slice(2));
141
+ return chalk.dim.italic(" │ " + line.slice(2));
179
142
  }
180
143
  const bullet = line.match(/^(\s*)[*\-+] (.+)$/);
181
144
  if (bullet) {
182
- return `${bullet[1]}${chalk_1.default.hex("#f38ba8")("•")} ${_renderInline(bullet[2])}`;
145
+ return `${bullet[1]}${chalk.hex("#f38ba8")("•")} ${_renderInline(bullet[2])}`;
183
146
  }
184
147
  const numbered = line.match(/^(\s*)(\d+)\. (.+)$/);
185
148
  if (numbered) {
186
- return `${numbered[1]}${chalk_1.default.dim(numbered[2] + ".")} ${_renderInline(numbered[3])}`;
149
+ return `${numbered[1]}${chalk.dim(numbered[2] + ".")} ${_renderInline(numbered[3])}`;
187
150
  }
188
151
  return _renderInline(line);
189
152
  }
190
153
  function _renderInline(text) {
191
- text = text.replace(/\*\*\*(.+?)\*\*\*/g, (_m, t) => chalk_1.default.bold.italic(t));
192
- text = text.replace(/\*\*(.+?)\*\*/g, (_m, t) => chalk_1.default.bold(t));
193
- text = text.replace(/\*(.+?)\*/g, (_m, t) => chalk_1.default.italic(t));
194
- text = text.replace(/_(.+?)_/g, (_m, t) => chalk_1.default.italic(t));
154
+ text = text.replace(/\*\*\*(.+?)\*\*\*/g, (_m, t) => chalk.bold.italic(t));
155
+ text = text.replace(/\*\*(.+?)\*\*/g, (_m, t) => chalk.bold(t));
156
+ text = text.replace(/\*(.+?)\*/g, (_m, t) => chalk.italic(t));
157
+ text = text.replace(/_(.+?)_/g, (_m, t) => chalk.italic(t));
195
158
  // Inline code — subtle background tint (#313244 = Catppuccin surface0, text stays readable)
196
- text = text.replace(/`([^`]+)`/g, (_m, t) => chalk_1.default.bgHex("#313244").hex("#cdd6f4")(` ${t} `));
197
- text = text.replace(/\[(.+?)\]\((.+?)\)/g, (_m, label, url) => `${chalk_1.default.hex("#89b4fa")(label)} ${chalk_1.default.dim(`(${url})`)}`);
159
+ text = text.replace(/`([^`]+)`/g, (_m, t) => chalk.bgHex("#313244").hex("#cdd6f4")(` ${t} `));
160
+ text = text.replace(/\[(.+?)\]\((.+?)\)/g, (_m, label, url) => `${chalk.hex("#89b4fa")(label)} ${chalk.dim(`(${url})`)}`);
198
161
  // Linkify file paths (only outside code spans — already consumed above)
199
162
  text = _linkifyPaths(text);
200
163
  return text;
@@ -221,19 +184,19 @@ function stripAnsi(s) {
221
184
  function _renderStatusBarLine() {
222
185
  const w = termWidth();
223
186
  const dot = _statusBar.connected
224
- ? chalk_1.default.hex("#a6e3a1")("●")
225
- : chalk_1.default.dim("○");
226
- const tenant = chalk_1.default.hex("#c0384b")(_statusBar.tenant);
187
+ ? chalk.hex("#a6e3a1")("●")
188
+ : chalk.dim("○");
189
+ const tenant = chalk.hex("#c0384b")(_statusBar.tenant);
227
190
  const session = _statusBar.sessionName
228
- ? chalk_1.default.hex("#89b4fa")(_statusBar.sessionName)
229
- : chalk_1.default.dim(_statusBar.sessionId.slice(0, 8) || "…");
230
- const turns = chalk_1.default.dim(`${_statusBar.turnCount} turns`);
191
+ ? chalk.hex("#89b4fa")(_statusBar.sessionName)
192
+ : chalk.dim(_statusBar.sessionId.slice(0, 8) || "…");
193
+ const turns = chalk.dim(`${_statusBar.turnCount} turns`);
231
194
  const lastTool = _statusBar.lastTool
232
- ? chalk_1.default.dim(`↳ ${_statusBar.lastTool}`)
233
- : chalk_1.default.dim("ready");
234
- const sep = chalk_1.default.dim(" · ");
195
+ ? chalk.dim(`↳ ${_statusBar.lastTool}`)
196
+ : chalk.dim("ready");
197
+ const sep = chalk.dim(" · ");
235
198
  const left = ` ${dot} ${tenant}${sep}${session}${sep}${turns}${sep}${lastTool}`;
236
- const right = chalk_1.default.hex("#c0384b")("Xiaotime Labs") + " ";
199
+ const right = chalk.hex("#c0384b")("Xiaotime Labs") + " ";
237
200
  const leftRaw = stripAnsi(left);
238
201
  const rightRaw = stripAnsi(right);
239
202
  const pad = Math.max(0, w - leftRaw.length - rightRaw.length);
@@ -254,7 +217,7 @@ function _renderStatusBarLine() {
254
217
  function _drawStickyBar() {
255
218
  // no-op — see note above. Status state is tracked; nothing is painted.
256
219
  }
257
- function initStatusBar(sessionId, sessionName, tenant) {
220
+ export function initStatusBar(sessionId, sessionName, tenant) {
258
221
  _statusBar.sessionId = sessionId;
259
222
  _statusBar.sessionName = sessionName;
260
223
  if (tenant)
@@ -262,19 +225,19 @@ function initStatusBar(sessionId, sessionName, tenant) {
262
225
  _statusBar.connected = false;
263
226
  _drawStickyBar();
264
227
  }
265
- function setConnected(connected) {
228
+ export function setConnected(connected) {
266
229
  _statusBar.connected = connected;
267
230
  _drawStickyBar();
268
231
  }
269
- function incrementTurn() {
232
+ export function incrementTurn() {
270
233
  _statusBar.turnCount += 1;
271
234
  _drawStickyBar();
272
235
  }
273
- function setLastTool(toolName) {
236
+ export function setLastTool(toolName) {
274
237
  _statusBar.lastTool = toolName;
275
238
  _drawStickyBar();
276
239
  }
277
- function updateStatusBarCost(_turnCostUsd) {
240
+ export function updateStatusBarCost(_turnCostUsd) {
278
241
  // no-op — cost not shown in bar
279
242
  }
280
243
  // ---------------------------------------------------------------------------
@@ -288,7 +251,7 @@ let _spinnerActive = false;
288
251
  function _clearSpinnerLine() {
289
252
  process.stdout.write("\x1b[2K\r");
290
253
  }
291
- function startSpinner(label) {
254
+ export function startSpinner(label) {
292
255
  if (_spinnerActive)
293
256
  stopSpinner();
294
257
  _spinnerLabel = label;
@@ -297,13 +260,13 @@ function startSpinner(label) {
297
260
  _spinnerInterval = setInterval(() => {
298
261
  if (!_spinnerActive)
299
262
  return;
300
- const frame = chalk_1.default.hex("#c0384b")(SPINNER_FRAMES[_spinnerFrame % SPINNER_FRAMES.length]);
263
+ const frame = chalk.hex("#c0384b")(SPINNER_FRAMES[_spinnerFrame % SPINNER_FRAMES.length]);
301
264
  _spinnerFrame++;
302
- const labelPart = _spinnerLabel ? ` ${chalk_1.default.dim(_spinnerLabel)}` : "";
265
+ const labelPart = _spinnerLabel ? ` ${chalk.dim(_spinnerLabel)}` : "";
303
266
  process.stdout.write(`\r ${frame}${labelPart}`);
304
267
  }, 80);
305
268
  }
306
- function stopSpinner(finalLabel, success = true) {
269
+ export function stopSpinner(finalLabel, success = true) {
307
270
  if (_spinnerInterval) {
308
271
  clearInterval(_spinnerInterval);
309
272
  _spinnerInterval = null;
@@ -311,21 +274,21 @@ function stopSpinner(finalLabel, success = true) {
311
274
  _spinnerActive = false;
312
275
  _clearSpinnerLine();
313
276
  if (finalLabel) {
314
- const icon = success ? chalk_1.default.hex("#a6e3a1")("✓") : chalk_1.default.hex("#f38ba8")("✗");
315
- process.stdout.write(` ${icon} ${chalk_1.default.dim(finalLabel)}\n`);
277
+ const icon = success ? chalk.hex("#a6e3a1")("✓") : chalk.hex("#f38ba8")("✗");
278
+ process.stdout.write(` ${icon} ${chalk.dim(finalLabel)}\n`);
316
279
  }
317
280
  }
318
281
  let _activeTool = null;
319
- function startToolLine(name, detail) {
282
+ export function startToolLine(name, detail) {
320
283
  if (_activeTool)
321
284
  finishToolLine(true);
322
285
  setLastTool(name);
323
286
  let frame = 0;
324
287
  const spinnerInterval = setInterval(() => {
325
- const f = chalk_1.default.hex("#89b4fa")(SPINNER_FRAMES[frame % SPINNER_FRAMES.length]);
288
+ const f = chalk.hex("#89b4fa")(SPINNER_FRAMES[frame % SPINNER_FRAMES.length]);
326
289
  const friendly = friendlyToolLabel(name);
327
- const detailStr = detail ? chalk_1.default.dim(` ${detail}`) : "";
328
- process.stdout.write(`\r ${f} ${chalk_1.default.dim(friendly)}${detailStr}`);
290
+ const detailStr = detail ? chalk.dim(` ${detail}`) : "";
291
+ process.stdout.write(`\r ${f} ${chalk.dim(friendly)}${detailStr}`);
329
292
  frame++;
330
293
  }, 80);
331
294
  _activeTool = {
@@ -336,7 +299,7 @@ function startToolLine(name, detail) {
336
299
  frame: 0,
337
300
  };
338
301
  }
339
- function finishToolLine(success = true, errorMessage) {
302
+ export function finishToolLine(success = true, errorMessage) {
340
303
  if (!_activeTool)
341
304
  return;
342
305
  clearInterval(_activeTool.spinnerInterval);
@@ -347,28 +310,28 @@ function finishToolLine(success = true, errorMessage) {
347
310
  printToolError(_activeTool.name, errorMessage, elapsed);
348
311
  }
349
312
  else {
350
- const icon = success ? chalk_1.default.hex("#a6e3a1")("✓") : chalk_1.default.hex("#f38ba8")("✗");
351
- const detailStr = _activeTool.detail ? chalk_1.default.dim(` ${_activeTool.detail}`) : "";
352
- const dur = chalk_1.default.dim(` ${elapsed}ms`);
313
+ const icon = success ? chalk.hex("#a6e3a1")("✓") : chalk.hex("#f38ba8")("✗");
314
+ const detailStr = _activeTool.detail ? chalk.dim(` ${_activeTool.detail}`) : "";
315
+ const dur = chalk.dim(` ${elapsed}ms`);
353
316
  const friendlyLabel = friendlyToolLabel(_activeTool.name);
354
- process.stdout.write(`\r\x1b[2K ${icon} ${chalk_1.default.dim(friendlyLabel)}${detailStr}${dur}\n`);
317
+ process.stdout.write(`\r\x1b[2K ${icon} ${chalk.dim(friendlyLabel)}${detailStr}${dur}\n`);
355
318
  }
356
319
  _activeTool = null;
357
320
  }
358
321
  // ---------------------------------------------------------------------------
359
322
  // Tool error — red bordered box
360
323
  // ---------------------------------------------------------------------------
361
- function printToolError(toolName, errorMessage, durationMs) {
324
+ export function printToolError(toolName, errorMessage, durationMs) {
362
325
  const w = termWidth();
363
- const top = chalk_1.default.hex("#f38ba8")("╭") +
364
- chalk_1.default.hex("#f38ba8")("─".repeat(w - 2)) +
365
- chalk_1.default.hex("#f38ba8")("╮");
366
- const bottom = chalk_1.default.hex("#f38ba8")("╰") +
367
- chalk_1.default.hex("#f38ba8")("─".repeat(w - 2)) +
368
- chalk_1.default.hex("#f38ba8")("╯");
369
- const dur = durationMs !== undefined ? chalk_1.default.dim(` ${durationMs}ms`) : "";
370
- const titleLine = chalk_1.default.bold.hex("#f38ba8")(` ✗ ${toolName}${dur}`);
371
- const bodyLines = wordWrap(errorMessage, w - 4).map((l) => chalk_1.default.hex("#f38ba8")(" " + l));
326
+ const top = chalk.hex("#f38ba8")("╭") +
327
+ chalk.hex("#f38ba8")("─".repeat(w - 2)) +
328
+ chalk.hex("#f38ba8")("╮");
329
+ const bottom = chalk.hex("#f38ba8")("╰") +
330
+ chalk.hex("#f38ba8")("─".repeat(w - 2)) +
331
+ chalk.hex("#f38ba8")("╯");
332
+ const dur = durationMs !== undefined ? chalk.dim(` ${durationMs}ms`) : "";
333
+ const titleLine = chalk.bold.hex("#f38ba8")(` ✗ ${toolName}${dur}`);
334
+ const bodyLines = wordWrap(errorMessage, w - 4).map((l) => chalk.hex("#f38ba8")(" " + l));
372
335
  process.stdout.write("\n" + top + "\n");
373
336
  process.stdout.write(titleLine + "\n");
374
337
  for (const l of bodyLines) {
@@ -379,20 +342,20 @@ function printToolError(toolName, errorMessage, durationMs) {
379
342
  // ---------------------------------------------------------------------------
380
343
  // Diff view for write_file
381
344
  // ---------------------------------------------------------------------------
382
- function printFileDiff(path, before, after) {
345
+ export function printFileDiff(path, before, after) {
383
346
  const w = termWidth();
384
- const label = chalk_1.default.dim(` write_file ${path} `);
347
+ const label = chalk.dim(` write_file ${path} `);
385
348
  const labelRaw = ` write_file ${path} `;
386
- const rule = chalk_1.default.dim("─".repeat(Math.max(0, w - labelRaw.length)));
349
+ const rule = chalk.dim("─".repeat(Math.max(0, w - labelRaw.length)));
387
350
  process.stdout.write("\n" + rule + label + "\n");
388
351
  if (!before) {
389
352
  // New file — show all lines as added
390
353
  const lines = after.split("\n").slice(0, 20);
391
354
  for (const line of lines) {
392
- process.stdout.write(chalk_1.default.hex("#a6e3a1")("+ " + line) + "\n");
355
+ process.stdout.write(chalk.hex("#a6e3a1")("+ " + line) + "\n");
393
356
  }
394
357
  if (after.split("\n").length > 20) {
395
- process.stdout.write(chalk_1.default.dim(` … ${after.split("\n").length - 20} more lines\n`));
358
+ process.stdout.write(chalk.dim(` … ${after.split("\n").length - 20} more lines\n`));
396
359
  }
397
360
  }
398
361
  else {
@@ -404,39 +367,39 @@ function printFileDiff(path, before, after) {
404
367
  const b = beforeLines[i];
405
368
  const a = afterLines[i];
406
369
  if (b === undefined) {
407
- process.stdout.write(chalk_1.default.hex("#a6e3a1")("+ " + a) + "\n");
370
+ process.stdout.write(chalk.hex("#a6e3a1")("+ " + a) + "\n");
408
371
  shown++;
409
372
  }
410
373
  else if (a === undefined) {
411
- process.stdout.write(chalk_1.default.hex("#f38ba8")("- " + b) + "\n");
374
+ process.stdout.write(chalk.hex("#f38ba8")("- " + b) + "\n");
412
375
  shown++;
413
376
  }
414
377
  else if (b !== a) {
415
- process.stdout.write(chalk_1.default.hex("#f38ba8")("- " + b) + "\n");
416
- process.stdout.write(chalk_1.default.hex("#a6e3a1")("+ " + a) + "\n");
378
+ process.stdout.write(chalk.hex("#f38ba8")("- " + b) + "\n");
379
+ process.stdout.write(chalk.hex("#a6e3a1")("+ " + a) + "\n");
417
380
  shown += 2;
418
381
  }
419
382
  }
420
383
  const totalDiff = Math.abs(afterLines.length - beforeLines.length);
421
384
  if (totalDiff > maxLines) {
422
- process.stdout.write(chalk_1.default.dim(` … ${totalDiff - maxLines} more changes\n`));
385
+ process.stdout.write(chalk.dim(` … ${totalDiff - maxLines} more changes\n`));
423
386
  }
424
387
  }
425
- process.stdout.write(chalk_1.default.dim("─".repeat(w)) + "\n\n");
388
+ process.stdout.write(chalk.dim("─".repeat(w)) + "\n\n");
426
389
  }
427
390
  // ---------------------------------------------------------------------------
428
391
  // Approval prompt — yellow bordered box
429
392
  // ---------------------------------------------------------------------------
430
- function printApprovalPrompt(title, body) {
393
+ export function printApprovalPrompt(title, body) {
431
394
  const w = termWidth();
432
- const top = chalk_1.default.hex("#f9e2af")("╭") +
433
- chalk_1.default.hex("#f9e2af")("─".repeat(w - 2)) +
434
- chalk_1.default.hex("#f9e2af")("╮");
435
- const bottom = chalk_1.default.hex("#f9e2af")("╰") +
436
- chalk_1.default.hex("#f9e2af")("─".repeat(w - 2)) +
437
- chalk_1.default.hex("#f9e2af")("╯");
438
- const titleLine = chalk_1.default.bold.hex("#f9e2af")(" " + title);
439
- const bodyLines = wordWrap(body, w - 4).map((l) => chalk_1.default.hex("#f9e2af")(" " + l));
395
+ const top = chalk.hex("#f9e2af")("╭") +
396
+ chalk.hex("#f9e2af")("─".repeat(w - 2)) +
397
+ chalk.hex("#f9e2af")("╮");
398
+ const bottom = chalk.hex("#f9e2af")("╰") +
399
+ chalk.hex("#f9e2af")("─".repeat(w - 2)) +
400
+ chalk.hex("#f9e2af")("╯");
401
+ const titleLine = chalk.bold.hex("#f9e2af")(" " + title);
402
+ const bodyLines = wordWrap(body, w - 4).map((l) => chalk.hex("#f9e2af")(" " + l));
440
403
  process.stdout.write("\n" + top + "\n");
441
404
  process.stdout.write(titleLine + "\n");
442
405
  for (const l of bodyLines) {
@@ -452,7 +415,7 @@ let _inCodeFence = false;
452
415
  let _codeFenceLang = "";
453
416
  let _codeFenceBuffer = [];
454
417
  let _turnHasContent = false;
455
- function printTextDelta(text) {
418
+ export function printTextDelta(text) {
456
419
  // Stop spinner on first token
457
420
  if (_spinnerActive)
458
421
  stopSpinner();
@@ -476,9 +439,9 @@ function _writeLine(line) {
476
439
  _codeFenceBuffer = [];
477
440
  const w = termWidth();
478
441
  const lang = _codeFenceLang !== "plaintext" ? _codeFenceLang : "";
479
- const label = lang ? chalk_1.default.dim(` ${lang} `) : "";
442
+ const label = lang ? chalk.dim(` ${lang} `) : "";
480
443
  const labelRaw = lang ? ` ${lang} ` : "";
481
- const rule = chalk_1.default.dim("─".repeat(Math.max(0, w - labelRaw.length)));
444
+ const rule = chalk.dim("─".repeat(Math.max(0, w - labelRaw.length)));
482
445
  process.stdout.write(rule + label + "\n");
483
446
  return;
484
447
  }
@@ -498,16 +461,16 @@ function _writeLine(line) {
498
461
  else {
499
462
  if (line === "```") {
500
463
  const code = _codeFenceBuffer.join("\n");
501
- const language = _codeFenceLang && (0, cli_highlight_1.supportsLanguage)(_codeFenceLang)
464
+ const language = _codeFenceLang && supportsLanguage(_codeFenceLang)
502
465
  ? _codeFenceLang
503
466
  : "plaintext";
504
467
  try {
505
- process.stdout.write((0, cli_highlight_1.highlight)(code, { language, ignoreIllegals: true }) + "\n");
468
+ process.stdout.write(highlight(code, { language, ignoreIllegals: true }) + "\n");
506
469
  }
507
470
  catch {
508
- process.stdout.write(chalk_1.default.dim(code) + "\n");
471
+ process.stdout.write(chalk.dim(code) + "\n");
509
472
  }
510
- process.stdout.write(chalk_1.default.dim("─".repeat(termWidth())) + "\n");
473
+ process.stdout.write(chalk.dim("─".repeat(termWidth())) + "\n");
511
474
  _inCodeFence = false;
512
475
  _codeFenceLang = "";
513
476
  _codeFenceBuffer = [];
@@ -520,21 +483,21 @@ function _writeLine(line) {
520
483
  // ---------------------------------------------------------------------------
521
484
  // Turn lifecycle
522
485
  // ---------------------------------------------------------------------------
523
- function printTurnStart() {
486
+ export function printTurnStart() {
524
487
  process.stdout.write("\x1b[?25l"); // hide cursor
525
488
  process.stdout.write("\n" +
526
- chalk_1.default.hex("#c0384b")(_botName) +
527
- chalk_1.default.dim(" › ") +
489
+ chalk.hex("#c0384b")(_botName) +
490
+ chalk.dim(" › ") +
528
491
  "\n");
529
492
  _turnHasContent = false;
530
493
  }
531
- function printThinkingStart() {
494
+ export function printThinkingStart() {
532
495
  startSpinner("");
533
496
  }
534
- function printThinkingStop() {
497
+ export function printThinkingStop() {
535
498
  stopSpinner();
536
499
  }
537
- function printTurnEnd(costUsd) {
500
+ export function printTurnEnd(costUsd) {
538
501
  process.stdout.write("\x1b[?25h"); // restore cursor
539
502
  // Stop any lingering spinner or tool line
540
503
  if (_spinnerActive)
@@ -559,23 +522,18 @@ function printTurnEnd(costUsd) {
559
522
  // First-launch state — show placeholder hint on very first prompt
560
523
  // ---------------------------------------------------------------------------
561
524
  let _isFirstPrompt = true;
562
- function consumeFirstPrompt() {
525
+ export function consumeFirstPrompt() {
563
526
  const was = _isFirstPrompt;
564
527
  _isFirstPrompt = false;
565
528
  return was;
566
529
  }
567
- function printPrompt(_showHint = false) {
568
- // Clean prompt prefix; readline renders the typed line after it (paste, arrow
569
- // keys, backspace, history all handled natively). No box/border: the bordered
570
- // input-box experiment (input_box.ts) overrode readline's renderer and broke
571
- // keypress decoding paste markers + arrow keys leaked in as literal text —
572
- // so it was reverted. A real Claude-Code-style input (paste/image/multiline)
573
- // needs a proper TUI input layer, not a readline override; that's the rebuild.
574
- process.stdout.write("\n" +
575
- chalk_1.default.bold.hex("#c0384b")("you") +
576
- chalk_1.default.dim(" › "));
530
+ export function printPrompt(_showHint = false) {
531
+ // No-op. The bordered input box (input_box.ts, installed on readline in
532
+ // ui_state.ts) draws the whole prompt borders, side walls, and the "you ›"
533
+ // prefix live, with the cursor inside it. Now safe because stdin is in raw
534
+ // mode (the cooked-echo bug that made the box leak ^[[200~/arrows is fixed).
577
535
  }
578
- function printPromptEnd() {
536
+ export function printPromptEnd() {
579
537
  // No-op. The input box (input_box.ts) erases itself on submit via its end()
580
538
  // hook; the committed "you › …" line is then printed by the prompt loop. A
581
539
  // bottom border here would draw over the cleared box.
@@ -583,37 +541,37 @@ function printPromptEnd() {
583
541
  // ---------------------------------------------------------------------------
584
542
  // Welcome + session list
585
543
  // ---------------------------------------------------------------------------
586
- function printWelcome(sessionId, sessionName, resumed, messageCount, lastMessagePreview) {
544
+ export function printWelcome(sessionId, sessionName, resumed, messageCount, lastMessagePreview) {
587
545
  initStatusBar(sessionId, sessionName);
588
546
  const name = sessionName || sessionId.slice(0, 8);
589
547
  // Shortcut bar — shown ONCE on welcome only
590
548
  const w = termWidth();
591
549
  const shortcuts = [
592
- chalk_1.default.dim("ctrl+c") + " " + chalk_1.default.hex("#6c7086")("exit"),
593
- chalk_1.default.dim("ctrl+r") + " " + chalk_1.default.hex("#6c7086")("sessions"),
594
- chalk_1.default.dim("ctrl+l") + " " + chalk_1.default.hex("#6c7086")("clear"),
595
- chalk_1.default.dim("↑↓") + " " + chalk_1.default.hex("#6c7086")("history"),
596
- ].join(chalk_1.default.dim(" · "));
550
+ chalk.dim("ctrl+c") + " " + chalk.hex("#6c7086")("exit"),
551
+ chalk.dim("ctrl+r") + " " + chalk.hex("#6c7086")("sessions"),
552
+ chalk.dim("ctrl+l") + " " + chalk.hex("#6c7086")("clear"),
553
+ chalk.dim("↑↓") + " " + chalk.hex("#6c7086")("history"),
554
+ ].join(chalk.dim(" · "));
597
555
  const shortcutRaw = stripAnsi(shortcuts);
598
556
  const shortcutPad = Math.max(0, Math.floor((w - shortcutRaw.length) / 2));
599
557
  if (resumed) {
600
558
  process.stdout.write("\n" +
601
- chalk_1.default.hex("#89b4fa")("↩ " + name) +
602
- chalk_1.default.dim(` ${messageCount} turns`) +
559
+ chalk.hex("#89b4fa")("↩ " + name) +
560
+ chalk.dim(` ${messageCount} turns`) +
603
561
  "\n");
604
562
  if (lastMessagePreview) {
605
563
  const truncated = lastMessagePreview.length > 60
606
564
  ? lastMessagePreview.slice(0, 60) + "…"
607
565
  : lastMessagePreview;
608
- process.stdout.write(chalk_1.default.dim(' last: "' + truncated + '"') + "\n");
566
+ process.stdout.write(chalk.dim(' last: "' + truncated + '"') + "\n");
609
567
  }
610
568
  process.stdout.write("\n" +
611
569
  " ".repeat(shortcutPad) + shortcuts + "\n\n");
612
570
  }
613
571
  else {
614
572
  process.stdout.write("\n" +
615
- chalk_1.default.hex("#c0384b").bold(`✦ ${_botName}`) +
616
- chalk_1.default.dim(` ${name}`) +
573
+ chalk.hex("#c0384b").bold(`✦ ${_botName}`) +
574
+ chalk.dim(` ${name}`) +
617
575
  "\n\n" +
618
576
  " ".repeat(shortcutPad) + shortcuts + "\n\n");
619
577
  }
@@ -626,47 +584,47 @@ function printWelcome(sessionId, sessionName, resumed, messageCount, lastMessage
626
584
  */
627
585
  function _writeIntroBanner() {
628
586
  const accent = "#f9e2af";
629
- const stripe = chalk_1.default.hex(accent)("│");
587
+ const stripe = chalk.hex(accent)("│");
630
588
  const lines = [
631
- chalk_1.default.bold.hex(accent)("How to use"),
632
- chalk_1.default.dim(`Just talk to ${getBotName()} like a teammate — ask a question, request a`),
633
- chalk_1.default.dim("draft, or say what you need done. It asks before changing files or"),
634
- chalk_1.default.dim('sending anything. Type "help" for examples.'),
589
+ chalk.bold.hex(accent)("How to use"),
590
+ chalk.dim(`Just talk to ${getBotName()} like a teammate — ask a question, request a`),
591
+ chalk.dim("draft, or say what you need done. It asks before changing files or"),
592
+ chalk.dim('sending anything. Type "help" for examples.'),
635
593
  ];
636
594
  process.stdout.write(lines.map((l) => ` ${stripe} ${l}`).join("\n") + "\n\n");
637
595
  }
638
- function printError(message) {
639
- process.stderr.write(chalk_1.default.red("\n✗ ") +
640
- chalk_1.default.bold.red("Error: ") +
641
- chalk_1.default.red(message) +
596
+ export function printError(message) {
597
+ process.stderr.write(chalk.red("\n✗ ") +
598
+ chalk.bold.red("Error: ") +
599
+ chalk.red(message) +
642
600
  "\n\n");
643
601
  }
644
- function printSessionList(sessions) {
602
+ export function printSessionList(sessions) {
645
603
  if (sessions.length === 0) {
646
- console.log(chalk_1.default.dim("No sessions found."));
604
+ console.log(chalk.dim("No sessions found."));
647
605
  return;
648
606
  }
649
607
  const w = termWidth();
650
608
  process.stdout.write("\n" +
651
- chalk_1.default.bold.hex("#c0384b")("Sessions") +
609
+ chalk.bold.hex("#c0384b")("Sessions") +
652
610
  "\n" +
653
- chalk_1.default.dim("─".repeat(w)) +
611
+ chalk.dim("─".repeat(w)) +
654
612
  "\n");
655
613
  for (const s of sessions) {
656
614
  const name = s.session_name
657
- ? chalk_1.default.hex("#89b4fa")(s.session_name)
658
- : chalk_1.default.dim("(unnamed)");
615
+ ? chalk.hex("#89b4fa")(s.session_name)
616
+ : chalk.dim("(unnamed)");
659
617
  // Session ID hidden — not useful to non-technical users
660
- const turns = chalk_1.default.dim(`${s.message_count} turns`);
661
- const cost = chalk_1.default.dim(`$${Number(s.total_cost_usd).toFixed(4)}`);
662
- const lastActive = chalk_1.default.dim(new Date(s.last_active_at).toLocaleString());
618
+ const turns = chalk.dim(`${s.message_count} turns`);
619
+ const cost = chalk.dim(`$${Number(s.total_cost_usd).toFixed(4)}`);
620
+ const lastActive = chalk.dim(new Date(s.last_active_at).toLocaleString());
663
621
  const status = s.status === "active"
664
- ? chalk_1.default.hex("#a6e3a1")("●")
665
- : chalk_1.default.dim("○");
622
+ ? chalk.hex("#a6e3a1")("●")
623
+ : chalk.dim("○");
666
624
  process.stdout.write(` ${status} ${name}\n`);
667
625
  process.stdout.write(` ${turns} ${cost} ${lastActive}\n\n`);
668
626
  }
669
- process.stdout.write(chalk_1.default.dim("Resume: xiaotime dev --session <id>\n\n"));
627
+ process.stdout.write(chalk.dim("Resume: xiaotime dev --session <id>\n\n"));
670
628
  }
671
629
  // ---------------------------------------------------------------------------
672
630
  // Tool call indicators
@@ -733,7 +691,7 @@ const TOOL_FRIENDLY_NAMES = {
733
691
  summarize_url: "reading that page...",
734
692
  fetch_url: "fetching that page...",
735
693
  };
736
- function friendlyToolLabel(name) {
694
+ export function friendlyToolLabel(name) {
737
695
  return TOOL_FRIENDLY_NAMES[name] ?? `working on it...`;
738
696
  }
739
697
  // ---------------------------------------------------------------------------
@@ -750,7 +708,7 @@ const ERROR_PATTERNS = [
750
708
  [/EPIPE/i, "Connection was interrupted. Reconnect and try again."],
751
709
  [/WEBSOCKET|ws error/i, "Lost the live connection. Reconnecting..."],
752
710
  ];
753
- function friendlyError(raw) {
711
+ export function friendlyError(raw) {
754
712
  for (const [pattern, friendly] of ERROR_PATTERNS) {
755
713
  if (pattern.test(raw))
756
714
  return friendly;
@@ -762,31 +720,31 @@ function friendlyError(raw) {
762
720
  // ---------------------------------------------------------------------------
763
721
  // Help panel
764
722
  // ---------------------------------------------------------------------------
765
- function printHelp() {
723
+ export function printHelp() {
766
724
  const w = termWidth();
767
- const top = chalk_1.default.hex("#f9e2af")("╭") +
768
- chalk_1.default.hex("#f9e2af")("─".repeat(w - 2)) +
769
- chalk_1.default.hex("#f9e2af")("╮");
770
- const bottom = chalk_1.default.hex("#f9e2af")("╰") +
771
- chalk_1.default.hex("#f9e2af")("─".repeat(w - 2)) +
772
- chalk_1.default.hex("#f9e2af")("╯");
725
+ const top = chalk.hex("#f9e2af")("╭") +
726
+ chalk.hex("#f9e2af")("─".repeat(w - 2)) +
727
+ chalk.hex("#f9e2af")("╮");
728
+ const bottom = chalk.hex("#f9e2af")("╰") +
729
+ chalk.hex("#f9e2af")("─".repeat(w - 2)) +
730
+ chalk.hex("#f9e2af")("╯");
773
731
  const lines = [
774
- chalk_1.default.bold.hex("#f9e2af")(` ${_botName} — your AI chief of staff`),
732
+ chalk.bold.hex("#f9e2af")(` ${_botName} — your AI chief of staff`),
775
733
  "",
776
- chalk_1.default.dim(" Just type naturally. Some examples:"),
734
+ chalk.dim(" Just type naturally. Some examples:"),
777
735
  "",
778
- ` ${chalk_1.default.hex("#89b4fa")("what's on my calendar today")}`,
779
- ` ${chalk_1.default.hex("#89b4fa")("draft a follow-up email to Acme")}`,
780
- ` ${chalk_1.default.hex("#89b4fa")("look up Banner Health")}`,
781
- ` ${chalk_1.default.hex("#89b4fa")("what signals do I have this week")}`,
782
- ` ${chalk_1.default.hex("#89b4fa")("research CrowdStrike")}`,
736
+ ` ${chalk.hex("#89b4fa")("what's on my calendar today")}`,
737
+ ` ${chalk.hex("#89b4fa")("draft a follow-up email to Acme")}`,
738
+ ` ${chalk.hex("#89b4fa")("look up Banner Health")}`,
739
+ ` ${chalk.hex("#89b4fa")("what signals do I have this week")}`,
740
+ ` ${chalk.hex("#89b4fa")("research CrowdStrike")}`,
783
741
  "",
784
- chalk_1.default.dim(" Keyboard shortcuts:"),
785
- ` ${chalk_1.default.dim("ctrl+c")} exit ${chalk_1.default.dim("ctrl+r")} switch sessions`,
786
- ` ${chalk_1.default.dim("ctrl+l")} clear screen ${chalk_1.default.dim("ctrl+u")} scroll history`,
787
- ` ${chalk_1.default.dim("↑ ↓")} message history`,
742
+ chalk.dim(" Keyboard shortcuts:"),
743
+ ` ${chalk.dim("ctrl+c")} exit ${chalk.dim("ctrl+r")} switch sessions`,
744
+ ` ${chalk.dim("ctrl+l")} clear screen ${chalk.dim("ctrl+u")} scroll history`,
745
+ ` ${chalk.dim("↑ ↓")} message history`,
788
746
  "",
789
- chalk_1.default.dim(` Type anything to get started. ${_botName} will figure out the rest.`),
747
+ chalk.dim(` Type anything to get started. ${_botName} will figure out the rest.`),
790
748
  ];
791
749
  process.stdout.write("\n" + top + "\n");
792
750
  for (const l of lines) {
@@ -797,31 +755,31 @@ function printHelp() {
797
755
  // ---------------------------------------------------------------------------
798
756
  // Disconnect banner
799
757
  // ---------------------------------------------------------------------------
800
- function printDisconnectBanner(reconnecting = true) {
758
+ export function printDisconnectBanner(reconnecting = true) {
801
759
  const msg = reconnecting
802
760
  ? " Lost connection — trying to reconnect..."
803
761
  : " Disconnected. Resume with: xiaotime dev";
804
- process.stdout.write("\n" + chalk_1.default.dim(msg) + "\n");
762
+ process.stdout.write("\n" + chalk.dim(msg) + "\n");
805
763
  }
806
764
  // ---------------------------------------------------------------------------
807
765
  // Exit confirmation
808
766
  // ---------------------------------------------------------------------------
809
- function printExitConfirmation() {
810
- process.stdout.write("\n" + chalk_1.default.hex("#f9e2af")(" Session paused. Your conversation is saved.") + "\n");
811
- process.stdout.write(chalk_1.default.dim(" Resume anytime with: xiaotime dev") + "\n\n");
767
+ export function printExitConfirmation() {
768
+ process.stdout.write("\n" + chalk.hex("#f9e2af")(" Session paused. Your conversation is saved.") + "\n");
769
+ process.stdout.write(chalk.dim(" Resume anytime with: xiaotime dev") + "\n\n");
812
770
  }
813
- function printToolCallLine(name, detail, durationMs, success = true) {
771
+ export function printToolCallLine(name, detail, durationMs, success = true) {
814
772
  setLastTool(name);
815
- const icon = success ? chalk_1.default.hex("#a6e3a1")("✓") : chalk_1.default.hex("#f38ba8")("✗");
816
- const dur = durationMs !== undefined ? chalk_1.default.dim(` ${durationMs}ms`) : "";
817
- const detailStr = detail ? chalk_1.default.dim(` ${detail}`) : "";
818
- process.stdout.write(` ${icon} ${chalk_1.default.dim(name)}${detailStr}${dur}\n`);
773
+ const icon = success ? chalk.hex("#a6e3a1")("✓") : chalk.hex("#f38ba8")("✗");
774
+ const dur = durationMs !== undefined ? chalk.dim(` ${durationMs}ms`) : "";
775
+ const detailStr = detail ? chalk.dim(` ${detail}`) : "";
776
+ process.stdout.write(` ${icon} ${chalk.dim(name)}${detailStr}${dur}\n`);
819
777
  }
820
- function printServerToolCall(name, inputSummary, durationMs) {
778
+ export function printServerToolCall(name, inputSummary, durationMs) {
821
779
  setLastTool(name);
822
- const icon = chalk_1.default.hex("#a6e3a1")("✓");
823
- const tail = inputSummary ? chalk_1.default.dim(` ${inputSummary}`) : "";
824
- const dur = durationMs !== undefined ? chalk_1.default.dim(` ${durationMs}ms`) : "";
825
- process.stdout.write(` ${icon} ${chalk_1.default.dim(name)}${tail}${dur}\n`);
780
+ const icon = chalk.hex("#a6e3a1")("✓");
781
+ const tail = inputSummary ? chalk.dim(` ${inputSummary}`) : "";
782
+ const dur = durationMs !== undefined ? chalk.dim(` ${durationMs}ms`) : "";
783
+ process.stdout.write(` ${icon} ${chalk.dim(name)}${tail}${dur}\n`);
826
784
  }
827
785
  //# sourceMappingURL=display.js.map