nolo-cli 0.33.0-alpha.20 → 0.33.0-alpha.22

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.
@@ -7,7 +7,7 @@ import {
7
7
  prependSubjectDialogMarker,
8
8
  resolveWorkflowReference,
9
9
  runAgentRunCommand
10
- } from "./chunk-FR2AIV4Q.js";
10
+ } from "./chunk-AEYCNMJI.js";
11
11
  import {
12
12
  parseAgentRunArgs
13
13
  } from "./chunk-ZHYK3N56.js";
@@ -318,10 +318,241 @@ function dimCliText(text, enabled = resolveCliColorEnabled()) {
318
318
  return styleCliText(text, "dim", enabled);
319
319
  }
320
320
 
321
+ // node_modules/strip-ansi/node_modules/ansi-regex/index.js
322
+ function ansiRegex({ onlyFirst = false } = {}) {
323
+ const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
324
+ const osc = `(?:\\u001B\\][^\\u0007\\u001B\\u009C]*${ST})`;
325
+ const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
326
+ const pattern = `${osc}|${csi}`;
327
+ return new RegExp(pattern, onlyFirst ? void 0 : "g");
328
+ }
329
+
330
+ // node_modules/strip-ansi/index.js
331
+ var regex = ansiRegex();
332
+ function stripAnsi(string) {
333
+ if (typeof string !== "string") {
334
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
335
+ }
336
+ if (!string.includes("\x1B") && !string.includes("\x9B")) {
337
+ return string;
338
+ }
339
+ return string.replace(regex, "");
340
+ }
341
+
342
+ // node_modules/get-east-asian-width/lookup-data.js
343
+ var ambiguousMinimalCodePoint = 161;
344
+ var ambiguousMaximumCodePoint = 1114109;
345
+ var ambiguousRanges = [161, 161, 164, 164, 167, 168, 170, 170, 173, 174, 176, 180, 182, 186, 188, 191, 198, 198, 208, 208, 215, 216, 222, 225, 230, 230, 232, 234, 236, 237, 240, 240, 242, 243, 247, 250, 252, 252, 254, 254, 257, 257, 273, 273, 275, 275, 283, 283, 294, 295, 299, 299, 305, 307, 312, 312, 319, 322, 324, 324, 328, 331, 333, 333, 338, 339, 358, 359, 363, 363, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, 476, 476, 593, 593, 609, 609, 708, 708, 711, 711, 713, 715, 717, 717, 720, 720, 728, 731, 733, 733, 735, 735, 768, 879, 913, 929, 931, 937, 945, 961, 963, 969, 1025, 1025, 1040, 1103, 1105, 1105, 8208, 8208, 8211, 8214, 8216, 8217, 8220, 8221, 8224, 8226, 8228, 8231, 8240, 8240, 8242, 8243, 8245, 8245, 8251, 8251, 8254, 8254, 8308, 8308, 8319, 8319, 8321, 8324, 8364, 8364, 8451, 8451, 8453, 8453, 8457, 8457, 8467, 8467, 8470, 8470, 8481, 8482, 8486, 8486, 8491, 8491, 8531, 8532, 8539, 8542, 8544, 8555, 8560, 8569, 8585, 8585, 8592, 8601, 8632, 8633, 8658, 8658, 8660, 8660, 8679, 8679, 8704, 8704, 8706, 8707, 8711, 8712, 8715, 8715, 8719, 8719, 8721, 8721, 8725, 8725, 8730, 8730, 8733, 8736, 8739, 8739, 8741, 8741, 8743, 8748, 8750, 8750, 8756, 8759, 8764, 8765, 8776, 8776, 8780, 8780, 8786, 8786, 8800, 8801, 8804, 8807, 8810, 8811, 8814, 8815, 8834, 8835, 8838, 8839, 8853, 8853, 8857, 8857, 8869, 8869, 8895, 8895, 8978, 8978, 9312, 9449, 9451, 9547, 9552, 9587, 9600, 9615, 9618, 9621, 9632, 9633, 9635, 9641, 9650, 9651, 9654, 9655, 9660, 9661, 9664, 9665, 9670, 9672, 9675, 9675, 9678, 9681, 9698, 9701, 9711, 9711, 9733, 9734, 9737, 9737, 9742, 9743, 9756, 9756, 9758, 9758, 9792, 9792, 9794, 9794, 9824, 9825, 9827, 9829, 9831, 9834, 9836, 9837, 9839, 9839, 9886, 9887, 9919, 9919, 9926, 9933, 9935, 9939, 9941, 9953, 9955, 9955, 9960, 9961, 9963, 9969, 9972, 9972, 9974, 9977, 9979, 9980, 9982, 9983, 10045, 10045, 10102, 10111, 11094, 11097, 12872, 12879, 57344, 63743, 65024, 65039, 65533, 65533, 127232, 127242, 127248, 127277, 127280, 127337, 127344, 127373, 127375, 127376, 127387, 127404, 917760, 917999, 983040, 1048573, 1048576, 1114109];
346
+ var fullwidthMinimalCodePoint = 12288;
347
+ var fullwidthMaximumCodePoint = 65510;
348
+ var fullwidthRanges = [12288, 12288, 65281, 65376, 65504, 65510];
349
+ var wideMinimalCodePoint = 4352;
350
+ var wideMaximumCodePoint = 262141;
351
+ var wideRanges = [4352, 4447, 8986, 8987, 9001, 9002, 9193, 9196, 9200, 9200, 9203, 9203, 9725, 9726, 9748, 9749, 9776, 9783, 9800, 9811, 9855, 9855, 9866, 9871, 9875, 9875, 9889, 9889, 9898, 9899, 9917, 9918, 9924, 9925, 9934, 9934, 9940, 9940, 9962, 9962, 9970, 9971, 9973, 9973, 9978, 9978, 9981, 9981, 9989, 9989, 9994, 9995, 10024, 10024, 10060, 10060, 10062, 10062, 10067, 10069, 10071, 10071, 10133, 10135, 10160, 10160, 10175, 10175, 11035, 11036, 11088, 11088, 11093, 11093, 11904, 11929, 11931, 12019, 12032, 12245, 12272, 12287, 12289, 12350, 12353, 12438, 12441, 12543, 12549, 12591, 12593, 12686, 12688, 12773, 12783, 12830, 12832, 12871, 12880, 42124, 42128, 42182, 43360, 43388, 44032, 55203, 63744, 64255, 65040, 65049, 65072, 65106, 65108, 65126, 65128, 65131, 94176, 94180, 94192, 94198, 94208, 101589, 101631, 101662, 101760, 101874, 110576, 110579, 110581, 110587, 110589, 110590, 110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948, 110951, 110960, 111355, 119552, 119638, 119648, 119670, 126980, 126980, 127183, 127183, 127374, 127374, 127377, 127386, 127488, 127490, 127504, 127547, 127552, 127560, 127568, 127569, 127584, 127589, 127744, 127776, 127789, 127797, 127799, 127868, 127870, 127891, 127904, 127946, 127951, 127955, 127968, 127984, 127988, 127988, 127992, 128062, 128064, 128064, 128066, 128252, 128255, 128317, 128331, 128334, 128336, 128359, 128378, 128378, 128405, 128406, 128420, 128420, 128507, 128591, 128640, 128709, 128716, 128716, 128720, 128722, 128725, 128728, 128732, 128735, 128747, 128748, 128756, 128764, 128992, 129003, 129008, 129008, 129292, 129338, 129340, 129349, 129351, 129535, 129648, 129660, 129664, 129674, 129678, 129734, 129736, 129736, 129741, 129756, 129759, 129770, 129775, 129784, 131072, 196605, 196608, 262141];
352
+
353
+ // node_modules/get-east-asian-width/utilities.js
354
+ var isInRange = (ranges, codePoint) => {
355
+ let low = 0;
356
+ let high = Math.floor(ranges.length / 2) - 1;
357
+ while (low <= high) {
358
+ const mid = Math.floor((low + high) / 2);
359
+ const i = mid * 2;
360
+ if (codePoint < ranges[i]) {
361
+ high = mid - 1;
362
+ } else if (codePoint > ranges[i + 1]) {
363
+ low = mid + 1;
364
+ } else {
365
+ return true;
366
+ }
367
+ }
368
+ return false;
369
+ };
370
+
371
+ // node_modules/get-east-asian-width/lookup.js
372
+ var commonCjkCodePoint = 19968;
373
+ var [wideFastPathStart, wideFastPathEnd] = /* @__PURE__ */ findWideFastPathRange(wideRanges);
374
+ function findWideFastPathRange(ranges) {
375
+ let fastPathStart = ranges[0];
376
+ let fastPathEnd = ranges[1];
377
+ for (let index = 0; index < ranges.length; index += 2) {
378
+ const start = ranges[index];
379
+ const end = ranges[index + 1];
380
+ if (commonCjkCodePoint >= start && commonCjkCodePoint <= end) {
381
+ return [start, end];
382
+ }
383
+ if (end - start > fastPathEnd - fastPathStart) {
384
+ fastPathStart = start;
385
+ fastPathEnd = end;
386
+ }
387
+ }
388
+ return [fastPathStart, fastPathEnd];
389
+ }
390
+ var isAmbiguous = (codePoint) => {
391
+ if (codePoint < ambiguousMinimalCodePoint || codePoint > ambiguousMaximumCodePoint) {
392
+ return false;
393
+ }
394
+ return isInRange(ambiguousRanges, codePoint);
395
+ };
396
+ var isFullWidth = (codePoint) => {
397
+ if (codePoint < fullwidthMinimalCodePoint || codePoint > fullwidthMaximumCodePoint) {
398
+ return false;
399
+ }
400
+ return isInRange(fullwidthRanges, codePoint);
401
+ };
402
+ var isWide = (codePoint) => {
403
+ if (codePoint >= wideFastPathStart && codePoint <= wideFastPathEnd) {
404
+ return true;
405
+ }
406
+ if (codePoint < wideMinimalCodePoint || codePoint > wideMaximumCodePoint) {
407
+ return false;
408
+ }
409
+ return isInRange(wideRanges, codePoint);
410
+ };
411
+
412
+ // node_modules/get-east-asian-width/index.js
413
+ function validate(codePoint) {
414
+ if (!Number.isSafeInteger(codePoint)) {
415
+ throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
416
+ }
417
+ }
418
+ function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) {
419
+ validate(codePoint);
420
+ if (isFullWidth(codePoint) || isWide(codePoint) || ambiguousAsWide && isAmbiguous(codePoint)) {
421
+ return 2;
422
+ }
423
+ return 1;
424
+ }
425
+
426
+ // node_modules/string-width/index.js
427
+ var segmenter = new Intl.Segmenter();
428
+ var zeroWidthClusterRegex = new RegExp("^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Nonspacing_Mark}|\\p{Enclosing_Mark}|\\p{Surrogate})+$", "v");
429
+ var leadingNonPrintingRegex = new RegExp("^[\\p{Default_Ignorable_Code_Point}\\p{Control}\\p{Format}\\p{Nonspacing_Mark}\\p{Enclosing_Mark}\\p{Surrogate}]+", "v");
430
+ var spacingMarkRegex = new RegExp("\\p{Spacing_Mark}", "v");
431
+ var rgiEmojiRegex = new RegExp("^\\p{RGI_Emoji}$", "v");
432
+ var unqualifiedKeycapRegex = /^[\d#*]\u20E3$/;
433
+ var extendedPictographicRegex = new RegExp("\\p{Extended_Pictographic}", "gu");
434
+ function isDoubleWidthNonRgiEmojiSequence(segment) {
435
+ if (segment.length > 50) {
436
+ return false;
437
+ }
438
+ if (unqualifiedKeycapRegex.test(segment)) {
439
+ return true;
440
+ }
441
+ if (segment.includes("\u200D")) {
442
+ const pictographics = segment.match(extendedPictographicRegex);
443
+ return pictographics !== null && pictographics.length >= 2;
444
+ }
445
+ return false;
446
+ }
447
+ function baseVisible(segment) {
448
+ return segment.replace(leadingNonPrintingRegex, "");
449
+ }
450
+ function isZeroWidthCluster(segment) {
451
+ return zeroWidthClusterRegex.test(segment);
452
+ }
453
+ function isHangulLeadingJamo(codePoint) {
454
+ return codePoint >= 4352 && codePoint <= 4447 || codePoint >= 43360 && codePoint <= 43388;
455
+ }
456
+ function isHangulVowelJamo(codePoint) {
457
+ return codePoint >= 4448 && codePoint <= 4519 || codePoint >= 55216 && codePoint <= 55238;
458
+ }
459
+ function isHangulTrailingJamo(codePoint) {
460
+ return codePoint >= 4520 && codePoint <= 4607 || codePoint >= 55243 && codePoint <= 55291;
461
+ }
462
+ function isHangulJamo(codePoint) {
463
+ return isHangulLeadingJamo(codePoint) || isHangulVowelJamo(codePoint) || isHangulTrailingJamo(codePoint);
464
+ }
465
+ function hangulClusterWidth(visibleSegment, eastAsianWidthOptions) {
466
+ const codePoints = [];
467
+ for (const character of visibleSegment) {
468
+ if (zeroWidthClusterRegex.test(character)) {
469
+ continue;
470
+ }
471
+ codePoints.push(character.codePointAt(0));
472
+ }
473
+ if (codePoints.length === 0) {
474
+ return void 0;
475
+ }
476
+ let width = 0;
477
+ for (let index = 0; index < codePoints.length; index++) {
478
+ const codePoint = codePoints[index];
479
+ if (!isHangulJamo(codePoint)) {
480
+ if (width === 0) {
481
+ return void 0;
482
+ }
483
+ for (let remaining = index; remaining < codePoints.length; remaining++) {
484
+ width += eastAsianWidth(codePoints[remaining], eastAsianWidthOptions);
485
+ }
486
+ return width;
487
+ }
488
+ if (isHangulLeadingJamo(codePoint) && isHangulVowelJamo(codePoints[index + 1])) {
489
+ width += 2;
490
+ index += isHangulTrailingJamo(codePoints[index + 2]) ? 2 : 1;
491
+ continue;
492
+ }
493
+ width += eastAsianWidth(codePoint, eastAsianWidthOptions);
494
+ }
495
+ return width;
496
+ }
497
+ function trailingWidth(visibleSegment, eastAsianWidthOptions) {
498
+ let extra = 0;
499
+ let first = true;
500
+ for (const character of visibleSegment) {
501
+ if (first) {
502
+ first = false;
503
+ continue;
504
+ }
505
+ if (spacingMarkRegex.test(character) || character >= "\uFF00" && character <= "\uFFEF") {
506
+ extra += eastAsianWidth(character.codePointAt(0), eastAsianWidthOptions);
507
+ }
508
+ }
509
+ return extra;
510
+ }
511
+ function stringWidth(input, options = {}) {
512
+ if (typeof input !== "string" || input.length === 0) {
513
+ return 0;
514
+ }
515
+ const {
516
+ ambiguousIsNarrow = true,
517
+ countAnsiEscapeCodes = false
518
+ } = options;
519
+ let string = input;
520
+ if (!countAnsiEscapeCodes && (string.includes("\x1B") || string.includes("\x9B"))) {
521
+ string = stripAnsi(string);
522
+ }
523
+ if (string.length === 0) {
524
+ return 0;
525
+ }
526
+ if (/^[\u0020-\u007E]*$/.test(string)) {
527
+ return string.length;
528
+ }
529
+ let width = 0;
530
+ const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
531
+ for (const { segment } of segmenter.segment(string)) {
532
+ if (isZeroWidthCluster(segment)) {
533
+ continue;
534
+ }
535
+ if (rgiEmojiRegex.test(segment) || isDoubleWidthNonRgiEmojiSequence(segment)) {
536
+ width += 2;
537
+ continue;
538
+ }
539
+ const visibleSegment = baseVisible(segment);
540
+ const hangulWidth = hangulClusterWidth(visibleSegment, eastAsianWidthOptions);
541
+ if (hangulWidth !== void 0) {
542
+ width += hangulWidth;
543
+ continue;
544
+ }
545
+ const codePoint = visibleSegment.codePointAt(0);
546
+ width += eastAsianWidth(codePoint, eastAsianWidthOptions);
547
+ width += trailingWidth(visibleSegment, eastAsianWidthOptions);
548
+ }
549
+ return width;
550
+ }
551
+
321
552
  // packages/cli/tui/tuiAnsi.ts
322
553
  var ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
323
554
  var OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
324
- function stripAnsi(text) {
555
+ function stripAnsi2(text) {
325
556
  return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
326
557
  }
327
558
  var SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
@@ -384,29 +615,19 @@ function applyTerminalOutputToText(existing, chunk) {
384
615
  return text;
385
616
  }
386
617
  function displayWidth(str) {
387
- let width = 0;
388
- for (const char of str) {
389
- const code = char.codePointAt(0) ?? 0;
390
- if (code < 32 || code === 127) continue;
391
- if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
392
- // render narrow in terminals; counting them wide drifts the cursor.
393
- code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
394
- // status-line agent icon) render double-wide in common monospace fonts;
395
- // counting ⬢ as width 1 drifts the whole status line right of the icon.
396
- code >= 11008 && code <= 11263 || code >= 11904 && code <= 12350 || code >= 12352 && code <= 13247 || code >= 13312 && code <= 19903 || code >= 19968 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129791 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141 || // East Asian Ambiguous CJK quotation marks (U+201C/D “ ”, U+2018/9 ‘ ’).
397
- // In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
398
- // in English fonts they stay width 1. Follow the active locale so Chinese
399
- // replies align correctly without breaking English terminal output.
400
- getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
401
- width += 2;
402
- } else {
403
- width += 1;
404
- }
618
+ const plain = stripAnsi2(str);
619
+ let width = stringWidth(plain);
620
+ for (const { segment } of graphemeSegmenter.segment(plain)) {
621
+ if (stringWidth(segment) !== 1) continue;
622
+ const code = segment.codePointAt(0) ?? 0;
623
+ const forceWideSymbol = code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || code >= 11008 && code <= 11263 || code >= 127744 && code <= 129791;
624
+ const cjkQuote = getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217);
625
+ if (forceWideSymbol || cjkQuote) width += 1;
405
626
  }
406
627
  return width;
407
628
  }
408
629
  function visibleWidth(str) {
409
- return displayWidth(stripAnsi(str));
630
+ return displayWidth(stripAnsi2(str));
410
631
  }
411
632
  function truncateAnsi(text, maxWidth) {
412
633
  if (maxWidth <= 0) return "";
@@ -474,6 +695,7 @@ function padOrTruncateToWidth(text, width) {
474
695
  return `${text}${" ".repeat(width - textWidth)}`;
475
696
  }
476
697
  var SGR_RESET_REGEX = /^\x1b\[0?m$/;
698
+ var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
477
699
  function tokenizeAnsiLine(line) {
478
700
  const tokens = [];
479
701
  let index = 0;
@@ -481,28 +703,119 @@ function tokenizeAnsiLine(line) {
481
703
  if (line[index] === "\x1B") {
482
704
  const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
483
705
  if (osc) {
484
- tokens.push({ kind: "sgr", value: osc[0], width: 0 });
706
+ tokens.push({ kind: "sgr", value: osc[0], width: 0, charIndex: index });
485
707
  index += osc[0].length;
486
708
  continue;
487
709
  }
488
710
  const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
489
711
  if (sgr) {
490
- tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
712
+ tokens.push({ kind: "sgr", value: sgr[0], width: 0, charIndex: index });
491
713
  index += sgr[0].length;
492
714
  continue;
493
715
  }
716
+ const csi = line.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
717
+ if (csi) {
718
+ tokens.push({ kind: "sgr", value: csi[0], width: 0, charIndex: index });
719
+ index += csi[0].length;
720
+ continue;
721
+ }
494
722
  }
495
- const codePoint = line.codePointAt(index) ?? 0;
496
- const value = String.fromCodePoint(codePoint);
497
- tokens.push({ kind: "char", value, width: displayWidth(value) });
498
- index += value.length;
723
+ let nextEsc = line.indexOf("\x1B", index);
724
+ if (nextEsc === -1) nextEsc = line.length;
725
+ const chunk = line.slice(index, nextEsc);
726
+ for (const item of graphemeSegmenter.segment(chunk)) {
727
+ tokens.push({
728
+ kind: "char",
729
+ value: item.segment,
730
+ width: displayWidth(item.segment),
731
+ charIndex: index + item.index
732
+ });
733
+ }
734
+ index = nextEsc;
499
735
  }
500
736
  return tokens;
501
737
  }
502
- function wrapTranscriptLine(line, columns, hangingIndent = "") {
503
- if (line === "") return [""];
738
+ function buildSourceMapping(rawLine, styledLine, prefixCharCount) {
739
+ let contentStart = 0;
740
+ const headingMatch = rawLine.match(/^(#{1,3})\s+(.+)$/);
741
+ let lineToParse = rawLine;
742
+ if (headingMatch) {
743
+ contentStart = headingMatch[1].length + 1;
744
+ while (contentStart < rawLine.length && rawLine[contentStart] === " ") contentStart++;
745
+ lineToParse = rawLine.slice(contentStart);
746
+ }
747
+ const INLINE_RE = /(\[([^\]]+)\]\(([^)\s]+)\)|`([^`]+)`|\*\*(.+?)\*\*|(?<!\*)\*([^*]+?)\*(?!\*)|~~([^~]+?)~~)/g;
748
+ const mapping = [];
749
+ let lastIdx = 0;
750
+ let match;
751
+ while ((match = INLINE_RE.exec(lineToParse)) !== null) {
752
+ const plainBefore = lineToParse.slice(lastIdx, match.index);
753
+ for (let c = 0; c < plainBefore.length; c++) {
754
+ mapping.push(contentStart + lastIdx + c);
755
+ }
756
+ const fullMatch = match[0];
757
+ if (match[2] !== void 0 && match[3] !== void 0) {
758
+ const linkText = match[2];
759
+ const linkUrl = match[3];
760
+ const textOffset = contentStart + match.index + 1;
761
+ for (let c = 0; c < linkText.length; c++) {
762
+ mapping.push(textOffset + c);
763
+ }
764
+ const parenOffset = textOffset + linkText.length;
765
+ mapping.push(parenOffset);
766
+ mapping.push(parenOffset + 1);
767
+ const urlOffset = parenOffset + 2;
768
+ for (let c = 0; c < linkUrl.length; c++) {
769
+ mapping.push(urlOffset + c);
770
+ }
771
+ mapping.push(urlOffset + linkUrl.length);
772
+ } else if (match[4] !== void 0) {
773
+ const codeText = match[4];
774
+ const codeOffset = contentStart + match.index + 1;
775
+ for (let c = 0; c < codeText.length; c++) {
776
+ mapping.push(codeOffset + c);
777
+ }
778
+ } else if (match[5] !== void 0) {
779
+ const boldText = match[5];
780
+ const boldOffset = contentStart + match.index + 2;
781
+ for (let c = 0; c < boldText.length; c++) {
782
+ mapping.push(boldOffset + c);
783
+ }
784
+ } else if (match[6] !== void 0) {
785
+ const italicText = match[6];
786
+ const italicOffset = contentStart + match.index + 1;
787
+ for (let c = 0; c < italicText.length; c++) {
788
+ mapping.push(italicOffset + c);
789
+ }
790
+ } else if (match[7] !== void 0) {
791
+ const strikeText = match[7];
792
+ const strikeOffset = contentStart + match.index + 2;
793
+ for (let c = 0; c < strikeText.length; c++) {
794
+ mapping.push(strikeOffset + c);
795
+ }
796
+ }
797
+ lastIdx = match.index + fullMatch.length;
798
+ }
799
+ const plainRest = lineToParse.slice(lastIdx);
800
+ for (let c = 0; c < plainRest.length; c++) {
801
+ mapping.push(contentStart + lastIdx + c);
802
+ }
803
+ return mapping;
804
+ }
805
+ function wrapTranscriptLineWithLayout(line, columns, hangingIndent = "", lineSourceStart = 0, prefixWidth = 0, prefixCharCount = 0, sourceMapping, rawLineLength) {
806
+ if (line === "") {
807
+ const rawLen = rawLineLength ?? 0;
808
+ return [
809
+ {
810
+ rendered: "",
811
+ sourceStart: lineSourceStart,
812
+ sourceEnd: lineSourceStart + rawLen,
813
+ prefixWidth
814
+ }
815
+ ];
816
+ }
504
817
  const tokens = tokenizeAnsiLine(line);
505
- const result = [];
818
+ const rows = [];
506
819
  let activeStyles = [];
507
820
  const applyStyleToken = (value) => {
508
821
  if (SGR_RESET_REGEX.test(value)) {
@@ -514,10 +827,11 @@ function wrapTranscriptLine(line, columns, hangingIndent = "") {
514
827
  let start = 0;
515
828
  while (start < tokens.length) {
516
829
  if (tokens.slice(start).every((token) => token.kind === "sgr")) {
517
- if (result.length > 0) break;
830
+ if (rows.length > 0) break;
518
831
  }
519
832
  const openingStyles = [...activeStyles];
520
- const isContinuation = result.length > 0 && hangingIndent.length > 0;
833
+ const isContinuation = rows.length > 0;
834
+ const currentPrefixWidth = isContinuation ? visibleWidth(hangingIndent) : prefixWidth;
521
835
  const indentWidth = isContinuation ? visibleWidth(hangingIndent) : 0;
522
836
  const maxSegmentWidth = Math.max(1, columns - indentWidth);
523
837
  let width = 0;
@@ -532,7 +846,7 @@ function wrapTranscriptLine(line, columns, hangingIndent = "") {
532
846
  if (width + token.width > maxSegmentWidth && width > 0) break;
533
847
  width += token.width;
534
848
  end += 1;
535
- if (token.value === " " || token.value === " ") {
849
+ if ((token.value === " " || token.value === " ") && token.charIndex >= prefixCharCount) {
536
850
  lastBreak = end;
537
851
  }
538
852
  }
@@ -557,21 +871,78 @@ function wrapTranscriptLine(line, columns, hangingIndent = "") {
557
871
  const prefix = openingStyles.join("");
558
872
  const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
559
873
  const lineContent = `${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`;
560
- result.push(isContinuation ? `${hangingIndent}${lineContent}` : lineContent);
874
+ const rowRendered = isContinuation && hangingIndent.length > 0 ? `${hangingIndent}${lineContent}` : lineContent;
875
+ let segSourceStart = lineSourceStart;
876
+ let segSourceEnd = lineSourceStart;
877
+ let foundFirst = false;
878
+ const rowMapping = [];
879
+ let plainCharIndex = 0;
880
+ for (let i = 0; i < start; i++) {
881
+ const tok = tokens[i];
882
+ if (tok.kind === "char" && tok.charIndex >= prefixCharCount) {
883
+ plainCharIndex += tok.value.length;
884
+ }
885
+ }
886
+ for (let i = start; i < segmentEnd; i++) {
887
+ const tok = tokens[i];
888
+ if (tok.kind === "char" && tok.charIndex >= prefixCharCount) {
889
+ const mappedOffset = sourceMapping && sourceMapping[plainCharIndex] !== void 0 ? sourceMapping[plainCharIndex] : plainCharIndex;
890
+ if (!foundFirst) {
891
+ segSourceStart = lineSourceStart + mappedOffset;
892
+ foundFirst = true;
893
+ }
894
+ for (let c = 0; c < tok.value.length; c++) {
895
+ const idx = plainCharIndex + c;
896
+ const mapped = sourceMapping && sourceMapping[idx] !== void 0 ? sourceMapping[idx] : idx;
897
+ rowMapping.push(lineSourceStart + mapped);
898
+ }
899
+ const lastCharIdx = plainCharIndex + tok.value.length - 1;
900
+ const mappedEndOffset = sourceMapping && sourceMapping[lastCharIdx] !== void 0 ? sourceMapping[lastCharIdx] + 1 : plainCharIndex + tok.value.length;
901
+ segSourceEnd = lineSourceStart + mappedEndOffset;
902
+ plainCharIndex += tok.value.length;
903
+ }
904
+ }
561
905
  start = segmentEnd;
906
+ let softWrapJoiner = "";
562
907
  while (start < tokens.length) {
563
908
  const token = tokens[start];
564
- if (token.kind === "char" && token.value === " ") {
909
+ if (token.kind === "char" && token.value === " " && token.charIndex >= prefixCharCount) {
910
+ softWrapJoiner += token.value;
911
+ const mappedOffset = sourceMapping && sourceMapping[plainCharIndex] !== void 0 ? sourceMapping[plainCharIndex] + 1 : plainCharIndex + 1;
912
+ segSourceEnd = lineSourceStart + mappedOffset;
913
+ plainCharIndex += token.value.length;
565
914
  start += 1;
566
915
  continue;
567
916
  }
568
917
  break;
569
918
  }
919
+ if (start >= tokens.length && rawLineLength !== void 0) {
920
+ segSourceEnd = lineSourceStart + rawLineLength;
921
+ }
922
+ rows.push({
923
+ rendered: rowRendered,
924
+ sourceStart: segSourceStart,
925
+ sourceEnd: segSourceEnd,
926
+ prefixWidth: currentPrefixWidth,
927
+ sourceMapping: rowMapping.length > 0 ? rowMapping : void 0,
928
+ softWrapped: start < tokens.length,
929
+ softWrapJoiner
930
+ });
570
931
  }
571
- return result.length > 0 ? result : [""];
932
+ return rows.length > 0 ? rows : [
933
+ {
934
+ rendered: "",
935
+ sourceStart: lineSourceStart,
936
+ sourceEnd: lineSourceStart + (rawLineLength ?? 0),
937
+ prefixWidth
938
+ }
939
+ ];
940
+ }
941
+ function wrapTranscriptLine(line, columns, hangingIndent = "") {
942
+ return wrapTranscriptLineWithLayout(line, columns, hangingIndent).map((r) => r.rendered);
572
943
  }
573
944
  function buildWindowTitle(title) {
574
- const plain = stripAnsi(title).replace(/[\x00-\x1f\x7f]+/g, " ");
945
+ const plain = stripAnsi2(title).replace(/[\x00-\x1f\x7f]+/g, " ");
575
946
  let truncated = "";
576
947
  let width = 0;
577
948
  const maxCols = 80;
@@ -5362,7 +5733,7 @@ export {
5362
5733
  resolveCliColorEnabled,
5363
5734
  dimCliText,
5364
5735
  ANSI_ESCAPE_REGEX,
5365
- stripAnsi,
5736
+ stripAnsi2 as stripAnsi,
5366
5737
  applyTerminalOutputToText,
5367
5738
  displayWidth,
5368
5739
  visibleWidth,
@@ -5371,6 +5742,9 @@ export {
5371
5742
  countPhysicalLines,
5372
5743
  takeDisplayWidth,
5373
5744
  padOrTruncateToWidth,
5745
+ tokenizeAnsiLine,
5746
+ buildSourceMapping,
5747
+ wrapTranscriptLineWithLayout,
5374
5748
  wrapTranscriptLine,
5375
5749
  buildWindowTitle,
5376
5750
  wrapTextToLines,
package/index.js CHANGED
@@ -126,7 +126,7 @@ function createDaemonShortcutCommand(path, description, command2) {
126
126
  // packages/cli/agentInternalCommandEntries.ts
127
127
  function getAgentInternalCommandEntries() {
128
128
  const createAgentRunCommand = (path, description) => createContextCommand(path, description, async (args2, ctx) => {
129
- const { runAgentRunCommand } = await import("./agentRunCommand-IWXLTYGK.js");
129
+ const { runAgentRunCommand } = await import("./agentRunCommand-LEBZ6PNB.js");
130
130
  return runAgentRunCommand(args2, {
131
131
  env: ctx.env,
132
132
  scriptDir: ctx.scriptDir,
@@ -796,7 +796,7 @@ async function runScript(script, forwardedArgs, env) {
796
796
  return proc.exited;
797
797
  }
798
798
  async function launchTuiWorkspace(args2) {
799
- const { startTuiWorkspace } = await import("./readlineWorkspace-EH77JVMA.js");
799
+ const { startTuiWorkspace } = await import("./readlineWorkspace-R6QZRAIA.js");
800
800
  const { createTuiSummaryLlmCaller } = await import("./tuiSummaryLlmCaller-WUVAOIYU.js");
801
801
  return startTuiWorkspace({
802
802
  ...args2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nolo-cli",
3
- "version": "0.33.0-alpha.20",
3
+ "version": "0.33.0-alpha.22",
4
4
  "type": "module",
5
5
  "description": "Agent-first terminal workspace for Nolo",
6
6
  "bin": {