xiaotime 0.5.12 → 0.6.1

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 (54) 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.js +164 -201
  10. package/dist/display.js.map +1 -1
  11. package/dist/index.js +29 -25
  12. package/dist/index.js.map +1 -1
  13. package/dist/ink/App.d.ts +9 -0
  14. package/dist/ink/App.d.ts.map +1 -0
  15. package/dist/ink/App.js +152 -0
  16. package/dist/ink/App.js.map +1 -0
  17. package/dist/ink/execToolInk.d.ts +13 -0
  18. package/dist/ink/execToolInk.d.ts.map +1 -0
  19. package/dist/ink/execToolInk.js +239 -0
  20. package/dist/ink/execToolInk.js.map +1 -0
  21. package/dist/ink/runSessionInk.d.ts +2 -0
  22. package/dist/ink/runSessionInk.d.ts.map +1 -0
  23. package/dist/ink/runSessionInk.js +184 -0
  24. package/dist/ink/runSessionInk.js.map +1 -0
  25. package/dist/ink/store.d.ts +102 -0
  26. package/dist/ink/store.d.ts.map +1 -0
  27. package/dist/ink/store.js +144 -0
  28. package/dist/ink/store.js.map +1 -0
  29. package/dist/input_box.js +9 -16
  30. package/dist/input_box.js.map +1 -1
  31. package/dist/projectContext.d.ts +38 -0
  32. package/dist/projectContext.d.ts.map +1 -0
  33. package/dist/projectContext.js +135 -0
  34. package/dist/projectContext.js.map +1 -0
  35. package/dist/session.js +8 -14
  36. package/dist/session.js.map +1 -1
  37. package/dist/session_match.js +1 -4
  38. package/dist/session_match.js.map +1 -1
  39. package/dist/settings.js +8 -48
  40. package/dist/settings.js.map +1 -1
  41. package/dist/sidebar.js +13 -20
  42. package/dist/sidebar.js.map +1 -1
  43. package/dist/tool_result_client.js +6 -11
  44. package/dist/tool_result_client.js.map +1 -1
  45. package/dist/tools.d.ts +5 -0
  46. package/dist/tools.d.ts.map +1 -1
  47. package/dist/tools.js +33 -71
  48. package/dist/tools.js.map +1 -1
  49. package/dist/ui_state.js +22 -63
  50. package/dist/ui_state.js.map +1 -1
  51. package/dist/ws.d.ts.map +1 -1
  52. package/dist/ws.js +77 -111
  53. package/dist/ws.js.map +1 -1
  54. 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,18 +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) {
530
+ export function printPrompt(_showHint = false) {
568
531
  // No-op. The bordered input box (input_box.ts, installed on readline in
569
532
  // ui_state.ts) draws the whole prompt — borders, side walls, and the "you ›"
570
533
  // prefix — live, with the cursor inside it. Now safe because stdin is in raw
571
534
  // mode (the cooked-echo bug that made the box leak ^[[200~/arrows is fixed).
572
535
  }
573
- function printPromptEnd() {
536
+ export function printPromptEnd() {
574
537
  // No-op. The input box (input_box.ts) erases itself on submit via its end()
575
538
  // hook; the committed "you › …" line is then printed by the prompt loop. A
576
539
  // bottom border here would draw over the cleared box.
@@ -578,37 +541,37 @@ function printPromptEnd() {
578
541
  // ---------------------------------------------------------------------------
579
542
  // Welcome + session list
580
543
  // ---------------------------------------------------------------------------
581
- function printWelcome(sessionId, sessionName, resumed, messageCount, lastMessagePreview) {
544
+ export function printWelcome(sessionId, sessionName, resumed, messageCount, lastMessagePreview) {
582
545
  initStatusBar(sessionId, sessionName);
583
546
  const name = sessionName || sessionId.slice(0, 8);
584
547
  // Shortcut bar — shown ONCE on welcome only
585
548
  const w = termWidth();
586
549
  const shortcuts = [
587
- chalk_1.default.dim("ctrl+c") + " " + chalk_1.default.hex("#6c7086")("exit"),
588
- chalk_1.default.dim("ctrl+r") + " " + chalk_1.default.hex("#6c7086")("sessions"),
589
- chalk_1.default.dim("ctrl+l") + " " + chalk_1.default.hex("#6c7086")("clear"),
590
- chalk_1.default.dim("↑↓") + " " + chalk_1.default.hex("#6c7086")("history"),
591
- ].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(" · "));
592
555
  const shortcutRaw = stripAnsi(shortcuts);
593
556
  const shortcutPad = Math.max(0, Math.floor((w - shortcutRaw.length) / 2));
594
557
  if (resumed) {
595
558
  process.stdout.write("\n" +
596
- chalk_1.default.hex("#89b4fa")("↩ " + name) +
597
- chalk_1.default.dim(` ${messageCount} turns`) +
559
+ chalk.hex("#89b4fa")("↩ " + name) +
560
+ chalk.dim(` ${messageCount} turns`) +
598
561
  "\n");
599
562
  if (lastMessagePreview) {
600
563
  const truncated = lastMessagePreview.length > 60
601
564
  ? lastMessagePreview.slice(0, 60) + "…"
602
565
  : lastMessagePreview;
603
- process.stdout.write(chalk_1.default.dim(' last: "' + truncated + '"') + "\n");
566
+ process.stdout.write(chalk.dim(' last: "' + truncated + '"') + "\n");
604
567
  }
605
568
  process.stdout.write("\n" +
606
569
  " ".repeat(shortcutPad) + shortcuts + "\n\n");
607
570
  }
608
571
  else {
609
572
  process.stdout.write("\n" +
610
- chalk_1.default.hex("#c0384b").bold(`✦ ${_botName}`) +
611
- chalk_1.default.dim(` ${name}`) +
573
+ chalk.hex("#c0384b").bold(`✦ ${_botName}`) +
574
+ chalk.dim(` ${name}`) +
612
575
  "\n\n" +
613
576
  " ".repeat(shortcutPad) + shortcuts + "\n\n");
614
577
  }
@@ -621,47 +584,47 @@ function printWelcome(sessionId, sessionName, resumed, messageCount, lastMessage
621
584
  */
622
585
  function _writeIntroBanner() {
623
586
  const accent = "#f9e2af";
624
- const stripe = chalk_1.default.hex(accent)("│");
587
+ const stripe = chalk.hex(accent)("│");
625
588
  const lines = [
626
- chalk_1.default.bold.hex(accent)("How to use"),
627
- chalk_1.default.dim(`Just talk to ${getBotName()} like a teammate — ask a question, request a`),
628
- chalk_1.default.dim("draft, or say what you need done. It asks before changing files or"),
629
- 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.'),
630
593
  ];
631
594
  process.stdout.write(lines.map((l) => ` ${stripe} ${l}`).join("\n") + "\n\n");
632
595
  }
633
- function printError(message) {
634
- process.stderr.write(chalk_1.default.red("\n✗ ") +
635
- chalk_1.default.bold.red("Error: ") +
636
- 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) +
637
600
  "\n\n");
638
601
  }
639
- function printSessionList(sessions) {
602
+ export function printSessionList(sessions) {
640
603
  if (sessions.length === 0) {
641
- console.log(chalk_1.default.dim("No sessions found."));
604
+ console.log(chalk.dim("No sessions found."));
642
605
  return;
643
606
  }
644
607
  const w = termWidth();
645
608
  process.stdout.write("\n" +
646
- chalk_1.default.bold.hex("#c0384b")("Sessions") +
609
+ chalk.bold.hex("#c0384b")("Sessions") +
647
610
  "\n" +
648
- chalk_1.default.dim("─".repeat(w)) +
611
+ chalk.dim("─".repeat(w)) +
649
612
  "\n");
650
613
  for (const s of sessions) {
651
614
  const name = s.session_name
652
- ? chalk_1.default.hex("#89b4fa")(s.session_name)
653
- : chalk_1.default.dim("(unnamed)");
615
+ ? chalk.hex("#89b4fa")(s.session_name)
616
+ : chalk.dim("(unnamed)");
654
617
  // Session ID hidden — not useful to non-technical users
655
- const turns = chalk_1.default.dim(`${s.message_count} turns`);
656
- const cost = chalk_1.default.dim(`$${Number(s.total_cost_usd).toFixed(4)}`);
657
- 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());
658
621
  const status = s.status === "active"
659
- ? chalk_1.default.hex("#a6e3a1")("●")
660
- : chalk_1.default.dim("○");
622
+ ? chalk.hex("#a6e3a1")("●")
623
+ : chalk.dim("○");
661
624
  process.stdout.write(` ${status} ${name}\n`);
662
625
  process.stdout.write(` ${turns} ${cost} ${lastActive}\n\n`);
663
626
  }
664
- 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"));
665
628
  }
666
629
  // ---------------------------------------------------------------------------
667
630
  // Tool call indicators
@@ -728,7 +691,7 @@ const TOOL_FRIENDLY_NAMES = {
728
691
  summarize_url: "reading that page...",
729
692
  fetch_url: "fetching that page...",
730
693
  };
731
- function friendlyToolLabel(name) {
694
+ export function friendlyToolLabel(name) {
732
695
  return TOOL_FRIENDLY_NAMES[name] ?? `working on it...`;
733
696
  }
734
697
  // ---------------------------------------------------------------------------
@@ -745,7 +708,7 @@ const ERROR_PATTERNS = [
745
708
  [/EPIPE/i, "Connection was interrupted. Reconnect and try again."],
746
709
  [/WEBSOCKET|ws error/i, "Lost the live connection. Reconnecting..."],
747
710
  ];
748
- function friendlyError(raw) {
711
+ export function friendlyError(raw) {
749
712
  for (const [pattern, friendly] of ERROR_PATTERNS) {
750
713
  if (pattern.test(raw))
751
714
  return friendly;
@@ -757,31 +720,31 @@ function friendlyError(raw) {
757
720
  // ---------------------------------------------------------------------------
758
721
  // Help panel
759
722
  // ---------------------------------------------------------------------------
760
- function printHelp() {
723
+ export function printHelp() {
761
724
  const w = termWidth();
762
- const top = chalk_1.default.hex("#f9e2af")("╭") +
763
- chalk_1.default.hex("#f9e2af")("─".repeat(w - 2)) +
764
- chalk_1.default.hex("#f9e2af")("╮");
765
- const bottom = chalk_1.default.hex("#f9e2af")("╰") +
766
- chalk_1.default.hex("#f9e2af")("─".repeat(w - 2)) +
767
- 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")("╯");
768
731
  const lines = [
769
- chalk_1.default.bold.hex("#f9e2af")(` ${_botName} — your AI chief of staff`),
732
+ chalk.bold.hex("#f9e2af")(` ${_botName} — your AI chief of staff`),
770
733
  "",
771
- chalk_1.default.dim(" Just type naturally. Some examples:"),
734
+ chalk.dim(" Just type naturally. Some examples:"),
772
735
  "",
773
- ` ${chalk_1.default.hex("#89b4fa")("what's on my calendar today")}`,
774
- ` ${chalk_1.default.hex("#89b4fa")("draft a follow-up email to Acme")}`,
775
- ` ${chalk_1.default.hex("#89b4fa")("look up Banner Health")}`,
776
- ` ${chalk_1.default.hex("#89b4fa")("what signals do I have this week")}`,
777
- ` ${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")}`,
778
741
  "",
779
- chalk_1.default.dim(" Keyboard shortcuts:"),
780
- ` ${chalk_1.default.dim("ctrl+c")} exit ${chalk_1.default.dim("ctrl+r")} switch sessions`,
781
- ` ${chalk_1.default.dim("ctrl+l")} clear screen ${chalk_1.default.dim("ctrl+u")} scroll history`,
782
- ` ${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`,
783
746
  "",
784
- 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.`),
785
748
  ];
786
749
  process.stdout.write("\n" + top + "\n");
787
750
  for (const l of lines) {
@@ -792,31 +755,31 @@ function printHelp() {
792
755
  // ---------------------------------------------------------------------------
793
756
  // Disconnect banner
794
757
  // ---------------------------------------------------------------------------
795
- function printDisconnectBanner(reconnecting = true) {
758
+ export function printDisconnectBanner(reconnecting = true) {
796
759
  const msg = reconnecting
797
760
  ? " Lost connection — trying to reconnect..."
798
761
  : " Disconnected. Resume with: xiaotime dev";
799
- process.stdout.write("\n" + chalk_1.default.dim(msg) + "\n");
762
+ process.stdout.write("\n" + chalk.dim(msg) + "\n");
800
763
  }
801
764
  // ---------------------------------------------------------------------------
802
765
  // Exit confirmation
803
766
  // ---------------------------------------------------------------------------
804
- function printExitConfirmation() {
805
- process.stdout.write("\n" + chalk_1.default.hex("#f9e2af")(" Session paused. Your conversation is saved.") + "\n");
806
- 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");
807
770
  }
808
- function printToolCallLine(name, detail, durationMs, success = true) {
771
+ export function printToolCallLine(name, detail, durationMs, success = true) {
809
772
  setLastTool(name);
810
- const icon = success ? chalk_1.default.hex("#a6e3a1")("✓") : chalk_1.default.hex("#f38ba8")("✗");
811
- const dur = durationMs !== undefined ? chalk_1.default.dim(` ${durationMs}ms`) : "";
812
- const detailStr = detail ? chalk_1.default.dim(` ${detail}`) : "";
813
- 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`);
814
777
  }
815
- function printServerToolCall(name, inputSummary, durationMs) {
778
+ export function printServerToolCall(name, inputSummary, durationMs) {
816
779
  setLastTool(name);
817
- const icon = chalk_1.default.hex("#a6e3a1")("✓");
818
- const tail = inputSummary ? chalk_1.default.dim(` ${inputSummary}`) : "";
819
- const dur = durationMs !== undefined ? chalk_1.default.dim(` ${durationMs}ms`) : "";
820
- 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`);
821
784
  }
822
785
  //# sourceMappingURL=display.js.map