omnius 1.0.89 → 1.0.90

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.
package/dist/index.js CHANGED
@@ -3373,8 +3373,9 @@ function hashMismatchMessage(filePath, expectedHash, actualHash) {
3373
3373
  function fileContextHeader(filePath, content, range) {
3374
3374
  const totalLines = content.split("\n").length;
3375
3375
  const hash = contentHash(content);
3376
- const shown = range && (range.offset !== void 0 || range.limit !== void 0) ? ` showing=${range.offset ?? 1}-${range.limit ? (range.offset ?? 1) + range.limit - 1 : "end"}` : "";
3377
- return `[FILE CONTEXT path=${filePath} sha256=${hash} lines=${totalLines}${shown}]`;
3376
+ const shortHash2 = hash.slice(0, 12);
3377
+ const scope = range && (range.offset !== void 0 || range.limit !== void 0) ? `lines ${range.offset ?? 1}-${range.limit ? (range.offset ?? 1) + range.limit - 1 : totalLines} of ${totalLines}` : `${totalLines} lines`;
3378
+ return `[FILE CONTEXT | ${filePath} | ${scope} | sha256:${shortHash2}]`;
3378
3379
  }
3379
3380
  var init_edit_metadata = __esm({
3380
3381
  "packages/execution/dist/tools/edit-metadata.js"() {
@@ -548095,6 +548096,60 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
548095
548096
  fs11.appendFileSync(path12.join(trajDir, `trajectories.jsonl`), JSON.stringify(trajectory) + "\n", "utf-8");
548096
548097
  } catch {
548097
548098
  }
548099
+ let filesEdited;
548100
+ let testsRun;
548101
+ let provenanceAnchors;
548102
+ try {
548103
+ filesEdited = [...this._taskState.modifiedFiles.keys()].slice(0, 32);
548104
+ } catch {
548105
+ }
548106
+ try {
548107
+ const shellCommands = [];
548108
+ const provText = [];
548109
+ for (const entry of toolCallLog) {
548110
+ if (entry.name === "shell" || entry.name === "background_run") {
548111
+ const m2 = entry.argsKey.match(/(?:^|,)command=([^,]*)/);
548112
+ if (m2 && m2[1])
548113
+ shellCommands.push(m2[1]);
548114
+ }
548115
+ if (entry.outputPreview)
548116
+ provText.push(entry.outputPreview);
548117
+ }
548118
+ const testRunners = [
548119
+ /\b(?:pnpm|npm|yarn)\s+(?:run\s+)?(?:test|test:[\w-]+|typecheck|lint)\b[^&|;]*/,
548120
+ /\bvitest\s+(?:run\s+)?[\w\-/.@\s]*/,
548121
+ /\bjest\s+[\w\-/.@\s]*/,
548122
+ /\bpytest\s+[\w\-/.@\s]*/,
548123
+ /\bmocha\s+[\w\-/.@\s]*/,
548124
+ /\bgo\s+test\s+[\w./\s-]+/,
548125
+ /\bcargo\s+test\b[\w\s-]*/
548126
+ ];
548127
+ const tests = /* @__PURE__ */ new Set();
548128
+ for (const cmd of shellCommands) {
548129
+ for (const re of testRunners) {
548130
+ const m2 = cmd.match(re);
548131
+ if (m2) {
548132
+ const label = m2[0].replace(/\s+/g, " ").trim();
548133
+ if (label && label.length <= 80)
548134
+ tests.add(label);
548135
+ }
548136
+ }
548137
+ }
548138
+ if (tests.size > 0)
548139
+ testsRun = [...tests].slice(0, 16);
548140
+ const anchorRe = /(urn:omnius:[^\s"'<>)]+|aiwg-prov:[^\s"'<>)]+)/g;
548141
+ const anchors = /* @__PURE__ */ new Set();
548142
+ for (const text of provText) {
548143
+ for (const m2 of text.matchAll(anchorRe)) {
548144
+ const a2 = m2[0];
548145
+ if (a2.length <= 120)
548146
+ anchors.add(a2);
548147
+ }
548148
+ }
548149
+ if (anchors.size > 0)
548150
+ provenanceAnchors = [...anchors].slice(0, 16);
548151
+ } catch {
548152
+ }
548098
548153
  return {
548099
548154
  completed,
548100
548155
  turns: messages2.filter((m2) => m2.role === "assistant").length,
@@ -548104,7 +548159,10 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
548104
548159
  completionTokens,
548105
548160
  estimatedTokens,
548106
548161
  summary,
548107
- durationMs
548162
+ durationMs,
548163
+ filesEdited,
548164
+ testsRun,
548165
+ provenanceAnchors
548108
548166
  };
548109
548167
  }
548110
548168
  // -------------------------------------------------------------------------
@@ -562057,6 +562115,615 @@ var init_command_registry = __esm({
562057
562115
  }
562058
562116
  });
562059
562117
 
562118
+ // packages/cli/src/tui/text-selection.ts
562119
+ var text_selection_exports = {};
562120
+ __export(text_selection_exports, {
562121
+ SEL_END: () => SEL_END,
562122
+ SEL_START: () => SEL_START,
562123
+ TextSelection: () => TextSelection,
562124
+ computeHeaderButtons: () => computeHeaderButtons,
562125
+ copyText: () => copyText,
562126
+ hitTestHeaderButton: () => hitTestHeaderButton,
562127
+ pasteText: () => pasteText,
562128
+ renderHeaderButtons: () => renderHeaderButtons,
562129
+ setHoveredButton: () => setHoveredButton,
562130
+ setPressedButton: () => setPressedButton,
562131
+ setUpdateBadgeRegion: () => setUpdateBadgeRegion,
562132
+ stripAnsi: () => stripAnsi,
562133
+ visibleLength: () => visibleLength
562134
+ });
562135
+ import { execSync as execSync47 } from "node:child_process";
562136
+ function stripAnsi(s2) {
562137
+ return s2.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
562138
+ }
562139
+ function visibleLength(s2) {
562140
+ return stripAnsi(s2).length;
562141
+ }
562142
+ function copyText(text) {
562143
+ try {
562144
+ const platform7 = process.platform;
562145
+ if (platform7 === "darwin") {
562146
+ execSync47("pbcopy", { input: text, timeout: 3e3 });
562147
+ return true;
562148
+ }
562149
+ if (platform7 === "win32") {
562150
+ execSync47("clip", { input: text, timeout: 3e3 });
562151
+ return true;
562152
+ }
562153
+ for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
562154
+ try {
562155
+ execSync47(tool, { input: text, timeout: 3e3 });
562156
+ return true;
562157
+ } catch {
562158
+ continue;
562159
+ }
562160
+ }
562161
+ if (!_clipboardAutoInstallAttempted) {
562162
+ _clipboardAutoInstallAttempted = true;
562163
+ try {
562164
+ execSync47("which apt-get", { timeout: 2e3, stdio: "pipe" });
562165
+ try {
562166
+ execSync47("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
562167
+ execSync47("xclip -selection clipboard", { input: text, timeout: 3e3 });
562168
+ return true;
562169
+ } catch {
562170
+ }
562171
+ } catch {
562172
+ }
562173
+ }
562174
+ } catch {
562175
+ }
562176
+ try {
562177
+ const b64 = Buffer.from(text).toString("base64");
562178
+ process.stdout.write(`\x1B]52;c;${b64}\x07`);
562179
+ return true;
562180
+ } catch {
562181
+ }
562182
+ return false;
562183
+ }
562184
+ function pasteText() {
562185
+ try {
562186
+ const platform7 = process.platform;
562187
+ if (platform7 === "darwin") {
562188
+ return execSync47("pbpaste", { timeout: 3e3, encoding: "utf8" }).trimEnd();
562189
+ }
562190
+ if (platform7 === "win32") {
562191
+ return execSync47("powershell -command Get-Clipboard", { timeout: 3e3, encoding: "utf8" }).trimEnd();
562192
+ }
562193
+ for (const tool of [
562194
+ { cmd: "xclip", args: ["-selection", "clipboard", "-o"] },
562195
+ { cmd: "xsel", args: ["--clipboard", "--output"] },
562196
+ { cmd: "wl-paste", args: [] }
562197
+ ]) {
562198
+ try {
562199
+ const result = execSync47(`${tool.cmd} ${tool.args.join(" ")}`, { timeout: 3e3, encoding: "utf8" });
562200
+ return result.trimEnd();
562201
+ } catch {
562202
+ continue;
562203
+ }
562204
+ }
562205
+ } catch {
562206
+ }
562207
+ return null;
562208
+ }
562209
+ function computeHeaderButtons(_termWidth) {
562210
+ return [];
562211
+ }
562212
+ function setHoveredButton(cmd) {
562213
+ _hoveredButtonCmd = cmd;
562214
+ }
562215
+ function setPressedButton(cmd) {
562216
+ _pressedButtonCmd = cmd;
562217
+ }
562218
+ function renderHeaderButtons(_termWidth) {
562219
+ return "";
562220
+ }
562221
+ function setUpdateBadgeRegion(active, startCol, length4) {
562222
+ _updateBadgeActive = active;
562223
+ _updateBadgeCol = startCol;
562224
+ _updateBadgeLen = length4;
562225
+ }
562226
+ function hitTestHeaderButton(row, col, termWidth) {
562227
+ if (_updateBadgeActive && row === 1 && col >= _updateBadgeCol && col < _updateBadgeCol + _updateBadgeLen) {
562228
+ return "/update";
562229
+ }
562230
+ const hdrRow = layout().headerContent;
562231
+ if (row === hdrRow) {
562232
+ if (col <= 3) return "header-prev";
562233
+ if (col >= termWidth - 3) return "header-next";
562234
+ const btnDefs = [
562235
+ { cmd: "/help", label: " help " },
562236
+ { cmd: "/voice", label: " voice " },
562237
+ { cmd: "/model", label: " model " },
562238
+ { cmd: "/cohere", label: " cohere " }
562239
+ ];
562240
+ let btnEnd = termWidth - 4;
562241
+ for (let i2 = btnDefs.length - 1; i2 >= 0; i2--) {
562242
+ const btn = btnDefs[i2];
562243
+ const btnStart = btnEnd - btn.label.length;
562244
+ if (col >= btnStart && col <= btnEnd) return btn.cmd;
562245
+ btnEnd = btnStart - 1;
562246
+ }
562247
+ }
562248
+ return null;
562249
+ }
562250
+ var SEL_BG, SEL_FG, SEL_START, SEL_END, TextSelection, _clipboardAutoInstallAttempted, _hoveredButtonCmd, _pressedButtonCmd, _updateBadgeActive, _updateBadgeCol, _updateBadgeLen;
562251
+ var init_text_selection = __esm({
562252
+ "packages/cli/src/tui/text-selection.ts"() {
562253
+ "use strict";
562254
+ init_layout2();
562255
+ SEL_BG = 37;
562256
+ SEL_FG = 30;
562257
+ SEL_START = `\x1B[${SEL_FG}m\x1B[48;5;${SEL_BG}m`;
562258
+ SEL_END = `\x1B[0m`;
562259
+ TextSelection = class {
562260
+ _selection = null;
562261
+ _active = false;
562262
+ // true while mouse button is held
562263
+ _blockModeArmed = false;
562264
+ // Ctrl+Shift+B pressed, next click starts block select
562265
+ _provider;
562266
+ constructor(provider) {
562267
+ this._provider = provider;
562268
+ }
562269
+ /** Whether a selection currently exists */
562270
+ get hasSelection() {
562271
+ return this._selection !== null;
562272
+ }
562273
+ /** Whether we're actively dragging */
562274
+ get isDragging() {
562275
+ return this._active;
562276
+ }
562277
+ /** Get the current selection range (or null) */
562278
+ get selection() {
562279
+ return this._selection;
562280
+ }
562281
+ /** Arm block selection mode — next click starts rectangular select */
562282
+ armBlockMode() {
562283
+ this._blockModeArmed = true;
562284
+ }
562285
+ /** Clear the current selection */
562286
+ clear() {
562287
+ this._selection = null;
562288
+ this._active = false;
562289
+ this._blockModeArmed = false;
562290
+ }
562291
+ /**
562292
+ * Handle mouse press (button 0, M suffix in SGR).
562293
+ * Starts a new selection from the click position.
562294
+ */
562295
+ onMousePress(row, col) {
562296
+ const mode = this._blockModeArmed ? "block" : "line";
562297
+ this._blockModeArmed = false;
562298
+ this._selection = {
562299
+ anchor: { row, col },
562300
+ current: { row, col },
562301
+ mode
562302
+ };
562303
+ this._active = true;
562304
+ }
562305
+ /**
562306
+ * Handle mouse drag (button 32, M suffix in SGR).
562307
+ * Extends the selection to the current cursor position.
562308
+ */
562309
+ onMouseDrag(row, col) {
562310
+ if (!this._active || !this._selection) return;
562311
+ this._selection.current = { row, col };
562312
+ }
562313
+ /**
562314
+ * Handle mouse release (button 0, m suffix in SGR).
562315
+ * Finalizes the selection.
562316
+ */
562317
+ onMouseRelease(row, col) {
562318
+ if (!this._active || !this._selection) return;
562319
+ this._selection.current = { row, col };
562320
+ this._active = false;
562321
+ if (this._selection.anchor.row === this._selection.current.row && this._selection.anchor.col === this._selection.current.col) {
562322
+ this._selection = null;
562323
+ }
562324
+ }
562325
+ /**
562326
+ * Compute which content buffer indices and column ranges are selected.
562327
+ * Returns an array of { bufferIdx, startCol, endCol } for each selected line.
562328
+ * Columns are 0-based visible character positions.
562329
+ */
562330
+ getSelectedRanges() {
562331
+ if (!this._selection) return [];
562332
+ const { anchor, current, mode } = this._selection;
562333
+ const top = this._provider.getScrollRegionTop();
562334
+ const height = this._provider.getContentHeight();
562335
+ const offset = this._provider.getScrollOffset();
562336
+ const totalLines = this._provider.getContentLines().length;
562337
+ const startIdx = Math.max(0, totalLines - height - offset);
562338
+ const anchorBufIdx = startIdx + (anchor.row - top);
562339
+ const currentBufIdx = startIdx + (current.row - top);
562340
+ const minRow = Math.min(anchorBufIdx, currentBufIdx);
562341
+ const maxRow = Math.max(anchorBufIdx, currentBufIdx);
562342
+ const minCol = Math.min(anchor.col, current.col);
562343
+ const maxCol = Math.max(anchor.col, current.col);
562344
+ const ranges = [];
562345
+ if (mode === "block") {
562346
+ for (let idx = minRow; idx <= maxRow; idx++) {
562347
+ if (idx >= 0 && idx < totalLines) {
562348
+ ranges.push({ bufferIdx: idx, startCol: minCol - 1, endCol: maxCol - 1 });
562349
+ }
562350
+ }
562351
+ } else {
562352
+ const isForward = anchorBufIdx < currentBufIdx || anchorBufIdx === currentBufIdx && anchor.col <= current.col;
562353
+ const startR = isForward ? anchorBufIdx : currentBufIdx;
562354
+ const endR = isForward ? currentBufIdx : anchorBufIdx;
562355
+ const startC = isForward ? anchor.col - 1 : current.col - 1;
562356
+ const endC = isForward ? current.col - 1 : anchor.col - 1;
562357
+ for (let idx = startR; idx <= endR; idx++) {
562358
+ if (idx < 0 || idx >= totalLines) continue;
562359
+ const lineLen = visibleLength(this._provider.getContentLines()[idx] ?? "");
562360
+ if (idx === startR && idx === endR) {
562361
+ ranges.push({ bufferIdx: idx, startCol: startC, endCol: endC });
562362
+ } else if (idx === startR) {
562363
+ ranges.push({ bufferIdx: idx, startCol: startC, endCol: Math.max(lineLen, startC) });
562364
+ } else if (idx === endR) {
562365
+ ranges.push({ bufferIdx: idx, startCol: 0, endCol: endC });
562366
+ } else {
562367
+ ranges.push({ bufferIdx: idx, startCol: 0, endCol: lineLen });
562368
+ }
562369
+ }
562370
+ }
562371
+ return ranges;
562372
+ }
562373
+ /**
562374
+ * Apply selection highlighting to a content line for rendering.
562375
+ * Takes the original ANSI line and returns it with selection highlight applied.
562376
+ *
562377
+ * @param line Original content line (with ANSI codes)
562378
+ * @param startCol 0-based visible start column to highlight
562379
+ * @param endCol 0-based visible end column to highlight (inclusive)
562380
+ * @returns Line with selection highlight overlay
562381
+ */
562382
+ static applyHighlight(line, startCol, endCol) {
562383
+ const plain = stripAnsi(line);
562384
+ if (startCol > plain.length || endCol < 0 || startCol > endCol) return line;
562385
+ const sc = Math.max(0, startCol);
562386
+ const ec = Math.min(plain.length - 1, endCol);
562387
+ let result = "";
562388
+ let visPos = 0;
562389
+ let i2 = 0;
562390
+ let inHighlight = false;
562391
+ while (i2 < line.length) {
562392
+ const escMatch = line.slice(i2).match(/^(\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\))/);
562393
+ if (escMatch) {
562394
+ if (inHighlight) {
562395
+ result += SEL_END + escMatch[0] + SEL_START;
562396
+ } else {
562397
+ result += escMatch[0];
562398
+ }
562399
+ i2 += escMatch[0].length;
562400
+ continue;
562401
+ }
562402
+ if (visPos === sc && !inHighlight) {
562403
+ result += SEL_START;
562404
+ inHighlight = true;
562405
+ }
562406
+ result += line[i2];
562407
+ if (visPos === ec && inHighlight) {
562408
+ result += SEL_END;
562409
+ inHighlight = false;
562410
+ }
562411
+ visPos++;
562412
+ i2++;
562413
+ }
562414
+ if (inHighlight) result += SEL_END;
562415
+ return result;
562416
+ }
562417
+ /**
562418
+ * Get the selected text content (plain text, no ANSI codes).
562419
+ * For block mode, each line is joined with newline.
562420
+ * For line mode, text flows continuously with newlines between lines.
562421
+ */
562422
+ getSelectedText() {
562423
+ const ranges = this.getSelectedRanges();
562424
+ if (ranges.length === 0) return "";
562425
+ const lines = this._provider.getContentLines();
562426
+ const parts = [];
562427
+ for (const { bufferIdx, startCol, endCol } of ranges) {
562428
+ const raw = lines[bufferIdx] ?? "";
562429
+ const plain = stripAnsi(raw);
562430
+ const selected = plain.slice(
562431
+ Math.max(0, startCol),
562432
+ Math.min(plain.length, endCol + 1)
562433
+ );
562434
+ parts.push(selected);
562435
+ }
562436
+ return parts.join("\n");
562437
+ }
562438
+ /**
562439
+ * Copy current selection to system clipboard.
562440
+ * Tries platform commands first, falls back to OSC 52.
562441
+ * Returns true if copy succeeded.
562442
+ */
562443
+ copyToClipboard() {
562444
+ const text = this.getSelectedText();
562445
+ if (!text) return false;
562446
+ return copyText(text);
562447
+ }
562448
+ };
562449
+ _clipboardAutoInstallAttempted = false;
562450
+ _hoveredButtonCmd = null;
562451
+ _pressedButtonCmd = null;
562452
+ _updateBadgeActive = false;
562453
+ _updateBadgeCol = 0;
562454
+ _updateBadgeLen = 0;
562455
+ }
562456
+ });
562457
+
562458
+ // packages/cli/src/tui/task-complete-box.ts
562459
+ var task_complete_box_exports = {};
562460
+ __export(task_complete_box_exports, {
562461
+ buildBoxLines: () => buildBoxLines,
562462
+ deriveTitle: () => deriveTitle,
562463
+ detectProvenanceAnchors: () => detectProvenanceAnchors,
562464
+ detectTestRuns: () => detectTestRuns,
562465
+ renderTaskCompleteBox: () => renderTaskCompleteBox
562466
+ });
562467
+ function deriveTitle(task) {
562468
+ if (!task || !task.trim()) return "Task Complete";
562469
+ const cleaned = task.replace(/```[\s\S]*?```/g, " ").replace(/`[^`]+`/g, " ").replace(/\([^)]*\)/g, " ").replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
562470
+ if (!cleaned) return "Task Complete";
562471
+ const firstSentence = cleaned.split(/(?<=[.!?:])\s/)[0] ?? cleaned;
562472
+ const words = firstSentence.split(/\s+/).filter((w) => w.length > 0);
562473
+ if (words.length === 0) return "Task Complete";
562474
+ if (words.length <= 10) return words.join(" ");
562475
+ return words.slice(0, 10).join(" ") + "…";
562476
+ }
562477
+ function formatDuration2(ms) {
562478
+ if (ms < 1e3) return `${ms}ms`;
562479
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
562480
+ const m2 = Math.floor(ms / 6e4);
562481
+ const s2 = Math.floor(ms % 6e4 / 1e3);
562482
+ return `${m2}m${s2.toString().padStart(2, "0")}s`;
562483
+ }
562484
+ function formatTokenCount(t2) {
562485
+ const n2 = t2.total > 0 ? t2.total : t2.estimated;
562486
+ if (n2 <= 0) return "";
562487
+ if (n2 < 1e3) return `${n2} tok`;
562488
+ if (n2 < 1e6) return `${(n2 / 1e3).toFixed(1)}k tok`;
562489
+ return `${(n2 / 1e6).toFixed(2)}M tok`;
562490
+ }
562491
+ function buildMetricsChip(data) {
562492
+ const parts = [];
562493
+ parts.push(`${data.turns} turn${data.turns === 1 ? "" : "s"}`);
562494
+ parts.push(`${data.toolCalls} call${data.toolCalls === 1 ? "" : "s"}`);
562495
+ if (data.tokens && data.durationMs > 0) {
562496
+ const total = data.tokens.total > 0 ? data.tokens.total : data.tokens.estimated;
562497
+ if (total > 0) {
562498
+ const tps = total / (data.durationMs / 1e3);
562499
+ if (tps >= 1) parts.push(`${tps.toFixed(0)} tps`);
562500
+ }
562501
+ }
562502
+ parts.push(formatDuration2(data.durationMs));
562503
+ if (data.tokens) {
562504
+ const tok = formatTokenCount(data.tokens);
562505
+ if (tok) parts.push(tok);
562506
+ }
562507
+ return parts.join(" · ");
562508
+ }
562509
+ function wrapToWidth(text, width) {
562510
+ if (width <= 0) return [text];
562511
+ const out = [];
562512
+ for (const paragraph of text.split(/\n/)) {
562513
+ if (paragraph.length === 0) {
562514
+ out.push("");
562515
+ continue;
562516
+ }
562517
+ let remaining = paragraph;
562518
+ while (remaining.length > width) {
562519
+ let breakAt = remaining.lastIndexOf(" ", width);
562520
+ if (breakAt <= 0) breakAt = width;
562521
+ out.push(remaining.slice(0, breakAt).trimEnd());
562522
+ remaining = remaining.slice(breakAt).trimStart();
562523
+ }
562524
+ out.push(remaining);
562525
+ }
562526
+ return out;
562527
+ }
562528
+ function wrapListItems(items, width) {
562529
+ if (items.length === 0) return [];
562530
+ const sep4 = " · ";
562531
+ const lines = [];
562532
+ let current = "";
562533
+ for (const item of items) {
562534
+ const candidate = current === "" ? item : current + sep4 + item;
562535
+ if (stripAnsi(candidate).length <= width) {
562536
+ current = candidate;
562537
+ } else {
562538
+ if (current) lines.push(current);
562539
+ if (stripAnsi(item).length > width) {
562540
+ const chunks = wrapToWidth(item, width);
562541
+ lines.push(...chunks.slice(0, -1));
562542
+ current = chunks[chunks.length - 1] ?? "";
562543
+ } else {
562544
+ current = item;
562545
+ }
562546
+ }
562547
+ }
562548
+ if (current) lines.push(current);
562549
+ return lines;
562550
+ }
562551
+ function buildTopBorder(title, metrics2, width) {
562552
+ const inner = Math.max(4, width - 2);
562553
+ const titleVisible = stripAnsi(title);
562554
+ const metricsVisible = stripAnsi(metrics2);
562555
+ const titleChip = ` ${titleVisible} `;
562556
+ const titleSpan = titleChip.length + 2;
562557
+ const metricsChip = metricsVisible ? ` ${metricsVisible} ` : "";
562558
+ const metricsSpan = metricsChip.length > 0 ? metricsChip.length + 2 : 0;
562559
+ let titleSegment;
562560
+ let metricsSegment;
562561
+ let fillerWidth;
562562
+ if (titleSpan + metricsSpan + 4 <= inner) {
562563
+ titleSegment = `${FG_BORDER}[${FG_TITLE}${titleChip}${RESET}${FG_BORDER}]`;
562564
+ metricsSegment = metricsChip ? `${FG_BORDER}[${FG_METRIC}${metricsChip}${RESET}${FG_BORDER}]` : "";
562565
+ fillerWidth = inner - titleSpan - metricsSpan - 2;
562566
+ } else if (titleSpan + 4 <= inner) {
562567
+ titleSegment = `${FG_BORDER}[${FG_TITLE}${titleChip}${RESET}${FG_BORDER}]`;
562568
+ metricsSegment = "";
562569
+ fillerWidth = inner - titleSpan - 2;
562570
+ } else {
562571
+ const room = Math.max(3, inner - 8);
562572
+ const truncated = titleVisible.length > room ? titleVisible.slice(0, Math.max(1, room - 1)) + "…" : titleVisible;
562573
+ titleSegment = `${FG_BORDER}[${FG_TITLE} ${truncated} ${RESET}${FG_BORDER}]`;
562574
+ metricsSegment = "";
562575
+ fillerWidth = Math.max(0, inner - (truncated.length + 4) - 2);
562576
+ }
562577
+ const leadDash = `${FG_BORDER}${BOX_H}`;
562578
+ const trailDash = `${FG_BORDER}${BOX_H}${RESET}`;
562579
+ const filler = fillerWidth > 0 ? `${FG_BORDER}${BOX_H.repeat(fillerWidth)}` : "";
562580
+ return `${FG_BORDER}${BOX_TL}${leadDash}${titleSegment}${filler}${metricsSegment}${trailDash}${FG_BORDER}${BOX_TR}${RESET}`;
562581
+ }
562582
+ function buildBottomBorder(width) {
562583
+ const inner = Math.max(0, width - 2);
562584
+ return `${FG_BORDER}${BOX_BL}${BOX_H.repeat(inner)}${BOX_BR}${RESET}`;
562585
+ }
562586
+ function buildInnerDivider(width) {
562587
+ const inner = Math.max(0, width - 2);
562588
+ return `${FG_BORDER}${BOX_TJ_L}${BOX_H.repeat(inner)}${BOX_TJ_R}${RESET}`;
562589
+ }
562590
+ function buildContentRow(content, width) {
562591
+ const innerWidth = Math.max(1, width - 4);
562592
+ const visible = stripAnsi(content);
562593
+ let padded = content;
562594
+ if (visible.length < innerWidth) {
562595
+ padded = content + " ".repeat(innerWidth - visible.length);
562596
+ } else if (visible.length > innerWidth) {
562597
+ padded = content;
562598
+ }
562599
+ return `${FG_BORDER}${BOX_V}${RESET} ${padded} ${FG_BORDER}${BOX_V}${RESET}`;
562600
+ }
562601
+ function buildEmptyRow(width) {
562602
+ return buildContentRow("", width);
562603
+ }
562604
+ function buildLabeledFooterLines(label, items, width) {
562605
+ if (items.length === 0) return [];
562606
+ const innerWidth = Math.max(8, width - 4);
562607
+ const labelText = `${FG_LABEL}${label}:${RESET} `;
562608
+ const labelVisible = `${label}: `.length;
562609
+ const continuation = " ".repeat(labelVisible);
562610
+ const itemListWidth = Math.max(8, innerWidth - labelVisible);
562611
+ const wrapped = wrapListItems(items, itemListWidth);
562612
+ if (wrapped.length === 0) return [];
562613
+ const lines = [];
562614
+ lines.push(buildContentRow(`${labelText}${wrapped[0]}`, width));
562615
+ for (let i2 = 1; i2 < wrapped.length; i2++) {
562616
+ lines.push(buildContentRow(`${continuation}${wrapped[i2]}`, width));
562617
+ }
562618
+ return lines;
562619
+ }
562620
+ function buildBoxLines(data, width) {
562621
+ const w = Math.max(40, width);
562622
+ const title = deriveTitle(data.task);
562623
+ const metrics2 = buildMetricsChip(data);
562624
+ const lines = [];
562625
+ lines.push(buildTopBorder(`${GREEN}✔${RESET} ${title}`, metrics2, w));
562626
+ const innerWidth = Math.max(1, w - 4);
562627
+ const bodyText = (data.summary ?? "").trim();
562628
+ if (bodyText) {
562629
+ lines.push(buildEmptyRow(w));
562630
+ for (const para of bodyText.split(/\n/)) {
562631
+ const wrapped = wrapToWidth(para, innerWidth);
562632
+ for (const line of wrapped) {
562633
+ lines.push(buildContentRow(line, w));
562634
+ }
562635
+ }
562636
+ lines.push(buildEmptyRow(w));
562637
+ }
562638
+ const hasFooter = (data.testsRun?.length ?? 0) > 0 || (data.filesEdited?.length ?? 0) > 0 || (data.provenanceAnchors?.length ?? 0) > 0;
562639
+ if (hasFooter) {
562640
+ lines.push(buildInnerDivider(w));
562641
+ if (data.testsRun?.length) {
562642
+ lines.push(...buildLabeledFooterLines("Tests", data.testsRun, w));
562643
+ }
562644
+ if (data.filesEdited?.length) {
562645
+ lines.push(...buildLabeledFooterLines("Files", data.filesEdited, w));
562646
+ }
562647
+ if (data.provenanceAnchors?.length) {
562648
+ lines.push(...buildLabeledFooterLines("Provenance", data.provenanceAnchors, w));
562649
+ }
562650
+ }
562651
+ lines.push(buildBottomBorder(w));
562652
+ return lines;
562653
+ }
562654
+ function renderTaskCompleteBox(host, data) {
562655
+ const blockId = `task-complete-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
562656
+ const frozen = {
562657
+ task: data.task,
562658
+ summary: data.summary,
562659
+ turns: data.turns,
562660
+ toolCalls: data.toolCalls,
562661
+ durationMs: data.durationMs,
562662
+ tokens: data.tokens ?? null,
562663
+ filesEdited: data.filesEdited ? [...data.filesEdited] : [],
562664
+ testsRun: data.testsRun ? [...data.testsRun] : [],
562665
+ provenanceAnchors: data.provenanceAnchors ? [...data.provenanceAnchors] : []
562666
+ };
562667
+ host.registerDynamicBlock(blockId, (width) => buildBoxLines(frozen, width));
562668
+ host.appendDynamicBlock(blockId);
562669
+ return blockId;
562670
+ }
562671
+ function detectTestRuns(shellCommands) {
562672
+ const out = /* @__PURE__ */ new Set();
562673
+ const runners = [
562674
+ /\b(?:pnpm|npm|yarn)\s+(?:run\s+)?(test|test:[\w-]+|typecheck|lint)\b/,
562675
+ /\bvitest\s+(?:run\s+)?[\w-/.@]*/,
562676
+ /\bjest\s+[\w-/.@]*/,
562677
+ /\bpytest\s+[\w-/.@]*/,
562678
+ /\bmocha\s+[\w-/.@]*/,
562679
+ /\bgo\s+test\s+[\w./]+/,
562680
+ /\bcargo\s+test\b[\w\s-]*/
562681
+ ];
562682
+ for (const cmd of shellCommands) {
562683
+ for (const re of runners) {
562684
+ const m2 = cmd.match(re);
562685
+ if (m2) {
562686
+ const label = m2[0].replace(/\s+/g, " ").trim();
562687
+ if (label.length <= 80) out.add(label);
562688
+ }
562689
+ }
562690
+ }
562691
+ return [...out].slice(0, 16);
562692
+ }
562693
+ function detectProvenanceAnchors(toolOutputs) {
562694
+ const out = /* @__PURE__ */ new Set();
562695
+ const re = /(urn:omnius:[^\s"'<>)]+|aiwg-prov:[^\s"'<>)]+)/g;
562696
+ for (const out_ of toolOutputs) {
562697
+ if (!out_) continue;
562698
+ for (const match of out_.matchAll(re)) {
562699
+ const anchor = match[0];
562700
+ if (anchor.length <= 120) out.add(anchor);
562701
+ }
562702
+ }
562703
+ return [...out].slice(0, 16);
562704
+ }
562705
+ var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
562706
+ var init_task_complete_box = __esm({
562707
+ "packages/cli/src/tui/task-complete-box.ts"() {
562708
+ "use strict";
562709
+ init_text_selection();
562710
+ BOX_TL = "╭";
562711
+ BOX_TR = "╮";
562712
+ BOX_BL = "╰";
562713
+ BOX_BR = "╯";
562714
+ BOX_H = "─";
562715
+ BOX_V = "│";
562716
+ BOX_TJ_L = "├";
562717
+ BOX_TJ_R = "┤";
562718
+ RESET = "\x1B[0m";
562719
+ GREEN = "\x1B[38;5;114m";
562720
+ FG_BORDER = "\x1B[38;5;245m";
562721
+ FG_TITLE = "\x1B[1;38;5;117m";
562722
+ FG_METRIC = "\x1B[38;5;222m";
562723
+ FG_LABEL = "\x1B[38;5;147m";
562724
+ }
562725
+ });
562726
+
562060
562727
  // packages/cli/src/tui/render.ts
562061
562728
  var render_exports = {};
562062
562729
  __export(render_exports, {
@@ -562303,16 +562970,16 @@ function renderToolResult(toolName, success, output, verbose) {
562303
562970
  `);
562304
562971
  return;
562305
562972
  }
562306
- renderCodePreview(output, prefix, maxW, 6);
562973
+ renderCodePreview(output, prefix, maxW, 10);
562307
562974
  return;
562308
562975
  }
562309
562976
  case "shell":
562310
562977
  case "background_run": {
562311
- renderShellOutput(output, success, prefix, maxW, 8);
562978
+ renderShellOutput(output, success, prefix, maxW, 10);
562312
562979
  return;
562313
562980
  }
562314
562981
  case "grep_search": {
562315
- renderShellOutput(output, success, prefix, maxW, 6);
562982
+ renderShellOutput(output, success, prefix, maxW, 10);
562316
562983
  return;
562317
562984
  }
562318
562985
  case "task_complete": {
@@ -562461,18 +563128,40 @@ function highlightToolOutput(line) {
562461
563128
  if (formatted !== line) return formatted;
562462
563129
  return c3.dim(line);
562463
563130
  }
562464
- function renderTaskComplete(summary, turns, toolCalls, durationMs, tokens) {
562465
- const duration = formatDuration2(durationMs);
562466
- const tokenStr = tokens ? ` ${formatTokenCount(tokens)}` : "";
563131
+ function renderTaskComplete(arg1, turns, toolCalls, durationMs, tokens) {
563132
+ const opts = typeof arg1 === "string" ? {
563133
+ summary: arg1,
563134
+ turns: turns ?? 0,
563135
+ toolCalls: toolCalls ?? 0,
563136
+ durationMs: durationMs ?? 0,
563137
+ tokens
563138
+ } : arg1;
563139
+ if (opts.host) {
563140
+ const { renderTaskCompleteBox: renderTaskCompleteBox2 } = (init_task_complete_box(), __toCommonJS(task_complete_box_exports));
563141
+ renderTaskCompleteBox2(opts.host, {
563142
+ task: opts.task ?? "",
563143
+ summary: opts.summary,
563144
+ turns: opts.turns,
563145
+ toolCalls: opts.toolCalls,
563146
+ durationMs: opts.durationMs,
563147
+ tokens: opts.tokens ?? null,
563148
+ filesEdited: opts.filesEdited,
563149
+ testsRun: opts.testsRun,
563150
+ provenanceAnchors: opts.provenanceAnchors
563151
+ });
563152
+ return;
563153
+ }
563154
+ const duration = formatDuration3(opts.durationMs);
563155
+ const tokenStr = opts.tokens ? ` ${formatTokenCount2(opts.tokens)}` : "";
562467
563156
  process.stdout.write(`
562468
- ${c3.green("✔")} ${c3.bold("Task completed")} ${c3.dim(`(${turns} turns, ${toolCalls} tool calls, ${duration})`)}
563157
+ ${c3.green("✔")} ${c3.bold("Task completed")} ${c3.dim(`(${opts.turns} turns, ${opts.toolCalls} tool calls, ${duration})`)}
562469
563158
  `);
562470
563159
  if (tokenStr) {
562471
563160
  process.stdout.write(` ${c3.dim(tokenStr)}
562472
563161
  `);
562473
563162
  }
562474
- if (summary) {
562475
- const formatted = formatMarkdownBlock(wrapTaskCompleteSummary(summary));
563163
+ if (opts.summary) {
563164
+ const formatted = formatMarkdownBlock(wrapTaskCompleteSummary(opts.summary));
562476
563165
  const lines = formatted.split("\n");
562477
563166
  for (const line of lines) {
562478
563167
  process.stdout.write(` ${line}
@@ -562527,8 +563216,8 @@ function hangingIndentForPlainLine(line, width) {
562527
563216
  return capped(line.match(/^\s*/)?.[0].length ?? 0);
562528
563217
  }
562529
563218
  function renderTaskIncomplete(turns, toolCalls, durationMs, tokens) {
562530
- const duration = formatDuration2(durationMs);
562531
- const tokenStr = tokens ? ` ${formatTokenCount(tokens)}` : "";
563219
+ const duration = formatDuration3(durationMs);
563220
+ const tokenStr = tokens ? ` ${formatTokenCount2(tokens)}` : "";
562532
563221
  process.stdout.write(`
562533
563222
  ${c3.yellow("⚠")} ${c3.bold("Task incomplete")} ${c3.dim(`(${turns} turns, ${toolCalls} tool calls, ${duration})`)}
562534
563223
  `);
@@ -562538,7 +563227,7 @@ ${c3.yellow("⚠")} ${c3.bold("Task incomplete")} ${c3.dim(`(${turns} turns, ${t
562538
563227
  }
562539
563228
  process.stdout.write("\n");
562540
563229
  }
562541
- function formatTokenCount(tokens) {
563230
+ function formatTokenCount2(tokens) {
562542
563231
  if (tokens.total > 0) {
562543
563232
  return `Tokens: ${tokens.total.toLocaleString()}`;
562544
563233
  }
@@ -562838,7 +563527,7 @@ function formatToolArgs(toolName, args, verbose) {
562838
563527
  function truncStr(s2, max) {
562839
563528
  return s2.length > max ? s2.slice(0, max) + "..." : s2;
562840
563529
  }
562841
- function formatDuration2(ms) {
563530
+ function formatDuration3(ms) {
562842
563531
  if (ms < 1e3) return `${ms}ms`;
562843
563532
  const totalSecs = ms / 1e3;
562844
563533
  if (totalSecs < 60) return `${totalSecs.toFixed(1)}s`;
@@ -563112,7 +563801,7 @@ var init_render = __esm({
563112
563801
 
563113
563802
  // packages/cli/src/tui/voice-session.ts
563114
563803
  import { createServer as createServer4 } from "node:http";
563115
- import { spawn as spawn23, execSync as execSync47 } from "node:child_process";
563804
+ import { spawn as spawn23, execSync as execSync48 } from "node:child_process";
563116
563805
  import { EventEmitter as EventEmitter6 } from "node:events";
563117
563806
  function generateFrontendHTML() {
563118
563807
  return `<!DOCTYPE html>
@@ -570199,346 +570888,6 @@ var init_system_metrics = __esm({
570199
570888
  }
570200
570889
  });
570201
570890
 
570202
- // packages/cli/src/tui/text-selection.ts
570203
- var text_selection_exports = {};
570204
- __export(text_selection_exports, {
570205
- SEL_END: () => SEL_END,
570206
- SEL_START: () => SEL_START,
570207
- TextSelection: () => TextSelection,
570208
- computeHeaderButtons: () => computeHeaderButtons,
570209
- copyText: () => copyText,
570210
- hitTestHeaderButton: () => hitTestHeaderButton,
570211
- pasteText: () => pasteText,
570212
- renderHeaderButtons: () => renderHeaderButtons,
570213
- setHoveredButton: () => setHoveredButton,
570214
- setPressedButton: () => setPressedButton,
570215
- setUpdateBadgeRegion: () => setUpdateBadgeRegion,
570216
- stripAnsi: () => stripAnsi,
570217
- visibleLength: () => visibleLength
570218
- });
570219
- import { execSync as execSync48 } from "node:child_process";
570220
- function stripAnsi(s2) {
570221
- return s2.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
570222
- }
570223
- function visibleLength(s2) {
570224
- return stripAnsi(s2).length;
570225
- }
570226
- function copyText(text) {
570227
- try {
570228
- const platform7 = process.platform;
570229
- if (platform7 === "darwin") {
570230
- execSync48("pbcopy", { input: text, timeout: 3e3 });
570231
- return true;
570232
- }
570233
- if (platform7 === "win32") {
570234
- execSync48("clip", { input: text, timeout: 3e3 });
570235
- return true;
570236
- }
570237
- for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
570238
- try {
570239
- execSync48(tool, { input: text, timeout: 3e3 });
570240
- return true;
570241
- } catch {
570242
- continue;
570243
- }
570244
- }
570245
- if (!_clipboardAutoInstallAttempted) {
570246
- _clipboardAutoInstallAttempted = true;
570247
- try {
570248
- execSync48("which apt-get", { timeout: 2e3, stdio: "pipe" });
570249
- try {
570250
- execSync48("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
570251
- execSync48("xclip -selection clipboard", { input: text, timeout: 3e3 });
570252
- return true;
570253
- } catch {
570254
- }
570255
- } catch {
570256
- }
570257
- }
570258
- } catch {
570259
- }
570260
- try {
570261
- const b64 = Buffer.from(text).toString("base64");
570262
- process.stdout.write(`\x1B]52;c;${b64}\x07`);
570263
- return true;
570264
- } catch {
570265
- }
570266
- return false;
570267
- }
570268
- function pasteText() {
570269
- try {
570270
- const platform7 = process.platform;
570271
- if (platform7 === "darwin") {
570272
- return execSync48("pbpaste", { timeout: 3e3, encoding: "utf8" }).trimEnd();
570273
- }
570274
- if (platform7 === "win32") {
570275
- return execSync48("powershell -command Get-Clipboard", { timeout: 3e3, encoding: "utf8" }).trimEnd();
570276
- }
570277
- for (const tool of [
570278
- { cmd: "xclip", args: ["-selection", "clipboard", "-o"] },
570279
- { cmd: "xsel", args: ["--clipboard", "--output"] },
570280
- { cmd: "wl-paste", args: [] }
570281
- ]) {
570282
- try {
570283
- const result = execSync48(`${tool.cmd} ${tool.args.join(" ")}`, { timeout: 3e3, encoding: "utf8" });
570284
- return result.trimEnd();
570285
- } catch {
570286
- continue;
570287
- }
570288
- }
570289
- } catch {
570290
- }
570291
- return null;
570292
- }
570293
- function computeHeaderButtons(_termWidth) {
570294
- return [];
570295
- }
570296
- function setHoveredButton(cmd) {
570297
- _hoveredButtonCmd = cmd;
570298
- }
570299
- function setPressedButton(cmd) {
570300
- _pressedButtonCmd = cmd;
570301
- }
570302
- function renderHeaderButtons(_termWidth) {
570303
- return "";
570304
- }
570305
- function setUpdateBadgeRegion(active, startCol, length4) {
570306
- _updateBadgeActive = active;
570307
- _updateBadgeCol = startCol;
570308
- _updateBadgeLen = length4;
570309
- }
570310
- function hitTestHeaderButton(row, col, termWidth) {
570311
- if (_updateBadgeActive && row === 1 && col >= _updateBadgeCol && col < _updateBadgeCol + _updateBadgeLen) {
570312
- return "/update";
570313
- }
570314
- const hdrRow = layout().headerContent;
570315
- if (row === hdrRow) {
570316
- if (col <= 3) return "header-prev";
570317
- if (col >= termWidth - 3) return "header-next";
570318
- const btnDefs = [
570319
- { cmd: "/help", label: " help " },
570320
- { cmd: "/voice", label: " voice " },
570321
- { cmd: "/model", label: " model " },
570322
- { cmd: "/cohere", label: " cohere " }
570323
- ];
570324
- let btnEnd = termWidth - 4;
570325
- for (let i2 = btnDefs.length - 1; i2 >= 0; i2--) {
570326
- const btn = btnDefs[i2];
570327
- const btnStart = btnEnd - btn.label.length;
570328
- if (col >= btnStart && col <= btnEnd) return btn.cmd;
570329
- btnEnd = btnStart - 1;
570330
- }
570331
- }
570332
- return null;
570333
- }
570334
- var SEL_BG, SEL_FG, SEL_START, SEL_END, TextSelection, _clipboardAutoInstallAttempted, _hoveredButtonCmd, _pressedButtonCmd, _updateBadgeActive, _updateBadgeCol, _updateBadgeLen;
570335
- var init_text_selection = __esm({
570336
- "packages/cli/src/tui/text-selection.ts"() {
570337
- "use strict";
570338
- init_layout2();
570339
- SEL_BG = 37;
570340
- SEL_FG = 30;
570341
- SEL_START = `\x1B[${SEL_FG}m\x1B[48;5;${SEL_BG}m`;
570342
- SEL_END = `\x1B[0m`;
570343
- TextSelection = class {
570344
- _selection = null;
570345
- _active = false;
570346
- // true while mouse button is held
570347
- _blockModeArmed = false;
570348
- // Ctrl+Shift+B pressed, next click starts block select
570349
- _provider;
570350
- constructor(provider) {
570351
- this._provider = provider;
570352
- }
570353
- /** Whether a selection currently exists */
570354
- get hasSelection() {
570355
- return this._selection !== null;
570356
- }
570357
- /** Whether we're actively dragging */
570358
- get isDragging() {
570359
- return this._active;
570360
- }
570361
- /** Get the current selection range (or null) */
570362
- get selection() {
570363
- return this._selection;
570364
- }
570365
- /** Arm block selection mode — next click starts rectangular select */
570366
- armBlockMode() {
570367
- this._blockModeArmed = true;
570368
- }
570369
- /** Clear the current selection */
570370
- clear() {
570371
- this._selection = null;
570372
- this._active = false;
570373
- this._blockModeArmed = false;
570374
- }
570375
- /**
570376
- * Handle mouse press (button 0, M suffix in SGR).
570377
- * Starts a new selection from the click position.
570378
- */
570379
- onMousePress(row, col) {
570380
- const mode = this._blockModeArmed ? "block" : "line";
570381
- this._blockModeArmed = false;
570382
- this._selection = {
570383
- anchor: { row, col },
570384
- current: { row, col },
570385
- mode
570386
- };
570387
- this._active = true;
570388
- }
570389
- /**
570390
- * Handle mouse drag (button 32, M suffix in SGR).
570391
- * Extends the selection to the current cursor position.
570392
- */
570393
- onMouseDrag(row, col) {
570394
- if (!this._active || !this._selection) return;
570395
- this._selection.current = { row, col };
570396
- }
570397
- /**
570398
- * Handle mouse release (button 0, m suffix in SGR).
570399
- * Finalizes the selection.
570400
- */
570401
- onMouseRelease(row, col) {
570402
- if (!this._active || !this._selection) return;
570403
- this._selection.current = { row, col };
570404
- this._active = false;
570405
- if (this._selection.anchor.row === this._selection.current.row && this._selection.anchor.col === this._selection.current.col) {
570406
- this._selection = null;
570407
- }
570408
- }
570409
- /**
570410
- * Compute which content buffer indices and column ranges are selected.
570411
- * Returns an array of { bufferIdx, startCol, endCol } for each selected line.
570412
- * Columns are 0-based visible character positions.
570413
- */
570414
- getSelectedRanges() {
570415
- if (!this._selection) return [];
570416
- const { anchor, current, mode } = this._selection;
570417
- const top = this._provider.getScrollRegionTop();
570418
- const height = this._provider.getContentHeight();
570419
- const offset = this._provider.getScrollOffset();
570420
- const totalLines = this._provider.getContentLines().length;
570421
- const startIdx = Math.max(0, totalLines - height - offset);
570422
- const anchorBufIdx = startIdx + (anchor.row - top);
570423
- const currentBufIdx = startIdx + (current.row - top);
570424
- const minRow = Math.min(anchorBufIdx, currentBufIdx);
570425
- const maxRow = Math.max(anchorBufIdx, currentBufIdx);
570426
- const minCol = Math.min(anchor.col, current.col);
570427
- const maxCol = Math.max(anchor.col, current.col);
570428
- const ranges = [];
570429
- if (mode === "block") {
570430
- for (let idx = minRow; idx <= maxRow; idx++) {
570431
- if (idx >= 0 && idx < totalLines) {
570432
- ranges.push({ bufferIdx: idx, startCol: minCol - 1, endCol: maxCol - 1 });
570433
- }
570434
- }
570435
- } else {
570436
- const isForward = anchorBufIdx < currentBufIdx || anchorBufIdx === currentBufIdx && anchor.col <= current.col;
570437
- const startR = isForward ? anchorBufIdx : currentBufIdx;
570438
- const endR = isForward ? currentBufIdx : anchorBufIdx;
570439
- const startC = isForward ? anchor.col - 1 : current.col - 1;
570440
- const endC = isForward ? current.col - 1 : anchor.col - 1;
570441
- for (let idx = startR; idx <= endR; idx++) {
570442
- if (idx < 0 || idx >= totalLines) continue;
570443
- const lineLen = visibleLength(this._provider.getContentLines()[idx] ?? "");
570444
- if (idx === startR && idx === endR) {
570445
- ranges.push({ bufferIdx: idx, startCol: startC, endCol: endC });
570446
- } else if (idx === startR) {
570447
- ranges.push({ bufferIdx: idx, startCol: startC, endCol: Math.max(lineLen, startC) });
570448
- } else if (idx === endR) {
570449
- ranges.push({ bufferIdx: idx, startCol: 0, endCol: endC });
570450
- } else {
570451
- ranges.push({ bufferIdx: idx, startCol: 0, endCol: lineLen });
570452
- }
570453
- }
570454
- }
570455
- return ranges;
570456
- }
570457
- /**
570458
- * Apply selection highlighting to a content line for rendering.
570459
- * Takes the original ANSI line and returns it with selection highlight applied.
570460
- *
570461
- * @param line Original content line (with ANSI codes)
570462
- * @param startCol 0-based visible start column to highlight
570463
- * @param endCol 0-based visible end column to highlight (inclusive)
570464
- * @returns Line with selection highlight overlay
570465
- */
570466
- static applyHighlight(line, startCol, endCol) {
570467
- const plain = stripAnsi(line);
570468
- if (startCol > plain.length || endCol < 0 || startCol > endCol) return line;
570469
- const sc = Math.max(0, startCol);
570470
- const ec = Math.min(plain.length - 1, endCol);
570471
- let result = "";
570472
- let visPos = 0;
570473
- let i2 = 0;
570474
- let inHighlight = false;
570475
- while (i2 < line.length) {
570476
- const escMatch = line.slice(i2).match(/^(\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\))/);
570477
- if (escMatch) {
570478
- if (inHighlight) {
570479
- result += SEL_END + escMatch[0] + SEL_START;
570480
- } else {
570481
- result += escMatch[0];
570482
- }
570483
- i2 += escMatch[0].length;
570484
- continue;
570485
- }
570486
- if (visPos === sc && !inHighlight) {
570487
- result += SEL_START;
570488
- inHighlight = true;
570489
- }
570490
- result += line[i2];
570491
- if (visPos === ec && inHighlight) {
570492
- result += SEL_END;
570493
- inHighlight = false;
570494
- }
570495
- visPos++;
570496
- i2++;
570497
- }
570498
- if (inHighlight) result += SEL_END;
570499
- return result;
570500
- }
570501
- /**
570502
- * Get the selected text content (plain text, no ANSI codes).
570503
- * For block mode, each line is joined with newline.
570504
- * For line mode, text flows continuously with newlines between lines.
570505
- */
570506
- getSelectedText() {
570507
- const ranges = this.getSelectedRanges();
570508
- if (ranges.length === 0) return "";
570509
- const lines = this._provider.getContentLines();
570510
- const parts = [];
570511
- for (const { bufferIdx, startCol, endCol } of ranges) {
570512
- const raw = lines[bufferIdx] ?? "";
570513
- const plain = stripAnsi(raw);
570514
- const selected = plain.slice(
570515
- Math.max(0, startCol),
570516
- Math.min(plain.length, endCol + 1)
570517
- );
570518
- parts.push(selected);
570519
- }
570520
- return parts.join("\n");
570521
- }
570522
- /**
570523
- * Copy current selection to system clipboard.
570524
- * Tries platform commands first, falls back to OSC 52.
570525
- * Returns true if copy succeeded.
570526
- */
570527
- copyToClipboard() {
570528
- const text = this.getSelectedText();
570529
- if (!text) return false;
570530
- return copyText(text);
570531
- }
570532
- };
570533
- _clipboardAutoInstallAttempted = false;
570534
- _hoveredButtonCmd = null;
570535
- _pressedButtonCmd = null;
570536
- _updateBadgeActive = false;
570537
- _updateBadgeCol = 0;
570538
- _updateBadgeLen = 0;
570539
- }
570540
- });
570541
-
570542
570891
  // packages/cli/src/tui/daemon-registry.ts
570543
570892
  var DaemonRegistry, registry2;
570544
570893
  var init_daemon_registry = __esm({
@@ -570951,16 +571300,16 @@ function buildTodoProgressBar(todos, maxWidth) {
570951
571300
  for (let i2 = 0; i2 < cells; i2++) {
570952
571301
  const t2 = todos[i2];
570953
571302
  if (t2.status === "completed") {
570954
- out += `\x1B[1m${DONE_Y}█${RESET}`;
571303
+ out += `\x1B[1m${DONE_Y}█${RESET2}`;
570955
571304
  } else if (i2 === inIdx) {
570956
- out += `${INPROG}▒${RESET}`;
571305
+ out += `${INPROG}▒${RESET2}`;
570957
571306
  } else if (i2 === nextIdx && inIdx >= 0) {
570958
- out += `${NEXT}▒${RESET}`;
571307
+ out += `${NEXT}▒${RESET2}`;
570959
571308
  } else {
570960
- out += `${PEND}░${RESET}`;
571309
+ out += `${PEND}░${RESET2}`;
570961
571310
  }
570962
571311
  }
570963
- if (truncated && maxWidth > 0) out += `${DIM_LABEL}…${RESET}`;
571312
+ if (truncated && maxWidth > 0) out += `${DIM_LABEL}…${RESET2}`;
570964
571313
  return out;
570965
571314
  }
570966
571315
  function render() {
@@ -570982,7 +571331,7 @@ function render() {
570982
571331
  const total = _lastTodos.length;
570983
571332
  const headerColor = ACCENT;
570984
571333
  const lines = [];
570985
- const headerPrefix = `tasks ${headerColor}${completed}/${total}${RESET} `;
571334
+ const headerPrefix = `tasks ${headerColor}${completed}/${total}${RESET2} `;
570986
571335
  const headerPrefixWidth = visualLen(headerPrefix);
570987
571336
  const maxBarWidth = Math.max(0, cols - 2 - headerPrefixWidth);
570988
571337
  const progressBar = buildTodoProgressBar(_lastTodos, maxBarWidth);
@@ -570994,11 +571343,11 @@ function render() {
570994
571343
  const contentWidth = Math.max(4, cols - 8);
570995
571344
  const contentText = t2.content + (t2.blocker ? ` (blocked: ${t2.blocker})` : "");
570996
571345
  const truncated = truncate2(contentText, contentWidth);
570997
- lines.push(`${color}${mark}${RESET} ${color}${truncated}${RESET}`);
571346
+ lines.push(`${color}${mark}${RESET2} ${color}${truncated}${RESET2}`);
570998
571347
  }
570999
571348
  if (_lastTodos.length > visible.length) {
571000
571349
  const more = _lastTodos.length - visible.length;
571001
- lines[lines.length - 1] = `${DIM_LABEL}… +${more} more${RESET}`;
571350
+ lines[lines.length - 1] = `${DIM_LABEL}… +${more} more${RESET2}`;
571002
571351
  }
571003
571352
  let out = HIDE + SAVE;
571004
571353
  const newTop = L.tasksTop;
@@ -571015,7 +571364,7 @@ function render() {
571015
571364
  for (let i2 = 0; i2 < lines.length; i2++) {
571016
571365
  const row = L.tasksTop + i2;
571017
571366
  if (row > L.tasksBottom) break;
571018
- out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET}`;
571367
+ out += `\x1B[${row};1H${CLEAR_LINE}${BG}${" ".repeat(cols)}\x1B[${row};2H${lines[i2]}${RESET2}`;
571019
571368
  }
571020
571369
  out += RESTORE + SHOW;
571021
571370
  try {
@@ -571043,7 +571392,7 @@ function clearLastPaintedRows() {
571043
571392
  _lastPaintedTop = -1;
571044
571393
  _lastPaintedBottom = -1;
571045
571394
  }
571046
- var chromeWrite, _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, _scopeOverlayActive, _scopeMainViewActive, _scopeNeovimActive, _scopePagerActive, _lastPaintedTop, _lastPaintedBottom, MAX_VISIBLE_ROWS, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET, BG, DIM_LABEL, ACCENT, DONE2, PENDING, BLOCKED;
571395
+ var chromeWrite, _activeSessionId, _watcher, _lastTodos, _enabled, _redrawScheduled, _onResizeChange, _scopeOverlayActive, _scopeMainViewActive, _scopeNeovimActive, _scopePagerActive, _lastPaintedTop, _lastPaintedBottom, MAX_VISIBLE_ROWS, SAVE, RESTORE, HIDE, SHOW, CLEAR_LINE, RESET2, BG, DIM_LABEL, ACCENT, DONE2, PENDING, BLOCKED;
571047
571396
  var init_tui_tasks_renderer = __esm({
571048
571397
  "packages/cli/src/tui/tui-tasks-renderer.ts"() {
571049
571398
  "use strict";
@@ -571070,7 +571419,7 @@ var init_tui_tasks_renderer = __esm({
571070
571419
  HIDE = "\x1B[?25l";
571071
571420
  SHOW = "\x1B[?25h";
571072
571421
  CLEAR_LINE = "\x1B[2K";
571073
- RESET = "\x1B[0m";
571422
+ RESET2 = "\x1B[0m";
571074
571423
  BG = tuiBgSeq();
571075
571424
  DIM_LABEL = "";
571076
571425
  ACCENT = "";
@@ -571117,7 +571466,7 @@ function setTerminalTitle(task, version4) {
571117
571466
  const title = task ? `${task.slice(0, 60)} · ${ver}` : ver;
571118
571467
  process.stdout.write(`\x1B]2;${title}\x07`);
571119
571468
  }
571120
- var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock, RESET2, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
571469
+ var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, BOX_TL2, BOX_TR2, BOX_BL2, BOX_BR2, BOX_H2, BOX_V2, _globalFooterLock, RESET3, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
571121
571470
  var init_status_bar = __esm({
571122
571471
  "packages/cli/src/tui/status-bar.ts"() {
571123
571472
  "use strict";
@@ -571296,14 +571645,14 @@ var init_status_bar = __esm({
571296
571645
  TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
571297
571646
  TEXT_DIM = tuiTextDim();
571298
571647
  NO_SUB_AGENTS_HEADER_LABEL = " no sub-agents ";
571299
- BOX_TL = "╭";
571300
- BOX_TR = "╮";
571301
- BOX_BL = "╰";
571302
- BOX_BR = "╯";
571303
- BOX_H = "─";
571304
- BOX_V = "│";
571648
+ BOX_TL2 = "╭";
571649
+ BOX_TR2 = "╮";
571650
+ BOX_BL2 = "╰";
571651
+ BOX_BR2 = "╯";
571652
+ BOX_H2 = "─";
571653
+ BOX_V2 = "│";
571305
571654
  _globalFooterLock = false;
571306
- RESET2 = "\x1B[0m";
571655
+ RESET3 = "\x1B[0m";
571307
571656
  CURSOR_BLINK_BLOCK = "\x1B[1 q";
571308
571657
  _isWindows = process.platform === "win32";
571309
571658
  StatusBar = class _StatusBar {
@@ -571349,6 +571698,22 @@ var init_status_bar = __esm({
571349
571698
  _contentScrollOffset = 0;
571350
571699
  // 0 = live (bottom), >0 = scrolled back
571351
571700
  _contentMaxLines = 1e4;
571701
+ /**
571702
+ * Dynamic content blocks — width-aware regions that re-render themselves
571703
+ * when the terminal resizes. The renderer registered here is called from
571704
+ * the scrollback reflow path: when a sentinel line of the form
571705
+ * `\x01DYNBLOCK:<id>\x01` is encountered, the registered fn is invoked
571706
+ * with the current terminal width and its returned lines replace the
571707
+ * sentinel in the reflowed output. This is how the Task Complete box
571708
+ * stays geometrically correct under SIGWINCH-driven resize.
571709
+ *
571710
+ * Keep the renderer cheap (pure data → strings) — it runs every full
571711
+ * repaint, including selection updates and scroll events.
571712
+ */
571713
+ _dynamicBlocks = /* @__PURE__ */ new Map();
571714
+ /** Sentinel marker — used both for scrollback storage and reflow detection. */
571715
+ DYNAMIC_BLOCK_MARK_PREFIX = "DYNBLOCK:";
571716
+ DYNAMIC_BLOCK_MARK_SUFFIX = "";
571352
571717
  // Partial-line accumulator for the buffered-write layer. Stream output
571353
571718
  // arrives in chunks (one per syntax-highlighted token) and a single
571354
571719
  // logical line can span many writes. If we naively push each chunk to
@@ -571459,6 +571824,41 @@ var init_status_bar = __esm({
571459
571824
  syncEnd() {
571460
571825
  this.termWrite("\x1B[?2026l");
571461
571826
  }
571827
+ /**
571828
+ * Register (or replace) a dynamic content block. Returns the sentinel
571829
+ * line the caller should push into the scrollback to make the block
571830
+ * appear there. The block's renderer is invoked on every repaint and
571831
+ * given the current terminal width; its returned lines are spliced in
571832
+ * place of the sentinel during reflow. Callers MUST also call
571833
+ * `appendDynamicBlock(id)` to actually place the block in scrollback.
571834
+ *
571835
+ * The sentinel is opaque — never write it directly to stdout; route
571836
+ * through `appendDynamicBlock` which also triggers a repaint so the
571837
+ * block becomes visible immediately.
571838
+ */
571839
+ registerDynamicBlock(id, render2) {
571840
+ this._dynamicBlocks.set(id, render2);
571841
+ return `${this.DYNAMIC_BLOCK_MARK_PREFIX}${id}${this.DYNAMIC_BLOCK_MARK_SUFFIX}`;
571842
+ }
571843
+ /** Unregister a dynamic block. Existing sentinels in scrollback become inert (rendered as empty). */
571844
+ unregisterDynamicBlock(id) {
571845
+ this._dynamicBlocks.delete(id);
571846
+ }
571847
+ /**
571848
+ * Append a previously-registered dynamic block's sentinel to scrollback
571849
+ * and trigger a repaint. The block's renderer fires immediately at the
571850
+ * current terminal width and again on every subsequent SIGWINCH (because
571851
+ * `_handleResizeImmediate` already calls `repaintContent`).
571852
+ */
571853
+ appendDynamicBlock(id) {
571854
+ if (!this._dynamicBlocks.has(id)) return;
571855
+ const sentinel = `${this.DYNAMIC_BLOCK_MARK_PREFIX}${id}${this.DYNAMIC_BLOCK_MARK_SUFFIX}`;
571856
+ this._contentLines.push(sentinel);
571857
+ if (this._contentLines.length > this._contentMaxLines) {
571858
+ this._contentLines.splice(0, this._contentLines.length - this._contentMaxLines);
571859
+ }
571860
+ if (this.active) this.repaintContent();
571861
+ }
571462
571862
  /** Force a complete footer redraw (public wrapper for renderFooterAndPositionInput).
571463
571863
  *
571464
571864
  * IMPORTANT: do NOT call `updateFooterHeight()` here. The inner render
@@ -571595,7 +571995,7 @@ var init_status_bar = __esm({
571595
571995
  const segment = segments[i2];
571596
571996
  if (i2 > 0) {
571597
571997
  separatorOffsets.push(width);
571598
- text += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}`;
571998
+ text += `${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}`;
571599
571999
  width += 1;
571600
572000
  }
571601
572001
  text += `\x1B[1;38;5;${TEXT_PRIMARY}m${PANEL_BG_SEQ}${segment}`;
@@ -571777,7 +572177,7 @@ var init_status_bar = __esm({
571777
572177
  const sysSeparatorOffset = sysItems.reduce((sum, item) => sum + item.w, 0);
571778
572178
  this._sysSeparatorOffset = sysSeparatorOffset;
571779
572179
  sysItems.push({
571780
- render: () => `${BOX_FG}│${RESET2}${PANEL_BG_SEQ} `,
572180
+ render: () => `${BOX_FG}│${RESET3}${PANEL_BG_SEQ} `,
571781
572181
  w: 2
571782
572182
  });
571783
572183
  const voiceLabel = this._voiceActive ? ` ${this._voiceModelId || "voice"} ` : " voice ";
@@ -571974,7 +572374,7 @@ var init_status_bar = __esm({
571974
572374
  const hdrRow = layout().headerContent;
571975
572375
  let buf = "\x1B7";
571976
572376
  buf += `\x1B[${hdrRow};1H${PANEL_BG_SEQ}\x1B[2K`;
571977
- buf += `${BOX_FG}│${RESET2}${PANEL_BG_SEQ}`;
572377
+ buf += `${BOX_FG}│${RESET3}${PANEL_BG_SEQ}`;
571978
572378
  if (chrome.showPrev) {
571979
572379
  buf += leftArrow;
571980
572380
  buf += ` `;
@@ -571985,7 +572385,7 @@ var init_status_bar = __esm({
571985
572385
  buf += `\x1B[${hdrRow};${w - 1}H`;
571986
572386
  buf += rightArrow;
571987
572387
  }
571988
- buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${RESET2}${PANEL_BG_SEQ}`;
572388
+ buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${RESET3}${PANEL_BG_SEQ}`;
571989
572389
  buf += "\x1B8";
571990
572390
  this.termWrite(buf);
571991
572391
  }
@@ -573188,11 +573588,11 @@ var init_status_bar = __esm({
573188
573588
  for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
573189
573589
  const row = pos.inputStartRow + i2;
573190
573590
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
573191
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${RESET2}${PANEL_BG_SEQ}`;
573591
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${RESET3}${PANEL_BG_SEQ}`;
573192
573592
  }
573193
573593
  const boxInnerP = w - 2;
573194
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerP))}${BOX_BR}${RESET2}${PANEL_BG_SEQ}`;
573195
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}${PANEL_BG_SEQ}\x1B[?7h\x1B[${pos.inputStartRow};1H`;
573594
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL2}${BOX_H2.repeat(Math.max(0, boxInnerP))}${BOX_BR2}${RESET3}${PANEL_BG_SEQ}`;
573595
+ buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET3}${PANEL_BG_SEQ}\x1B[?7h\x1B[${pos.inputStartRow};1H`;
573196
573596
  this.termWrite(buf);
573197
573597
  if (this._bannerRefresh) this._bannerRefresh();
573198
573598
  } else {
@@ -573393,7 +573793,7 @@ ${CONTENT_BG_SEQ}`);
573393
573793
  process.stdout.write = this._origWrite;
573394
573794
  this._origWrite = null;
573395
573795
  }
573396
- process.stdout.write(RESET2);
573796
+ process.stdout.write(RESET3);
573397
573797
  this._brailleSpinner.setMetrics({ isStreaming: false });
573398
573798
  this.renderFooterAndPositionInput();
573399
573799
  this.parkCursorInInput();
@@ -573522,12 +573922,32 @@ ${CONTENT_BG_SEQ}`);
573522
573922
  reflowContentLines(livePartialLine, width) {
573523
573923
  const maxWidth = Math.max(16, width);
573524
573924
  const source = livePartialLine ? [...this._contentLines, livePartialLine] : this._contentLines;
573525
- return source.flatMap(
573526
- (line, idx) => this.reflowContentLine(line, maxWidth).map((segment) => ({
573925
+ return source.flatMap((line, idx) => {
573926
+ if (line.startsWith(this.DYNAMIC_BLOCK_MARK_PREFIX) && line.endsWith(this.DYNAMIC_BLOCK_MARK_SUFFIX)) {
573927
+ const id = line.slice(
573928
+ this.DYNAMIC_BLOCK_MARK_PREFIX.length,
573929
+ line.length - this.DYNAMIC_BLOCK_MARK_SUFFIX.length
573930
+ );
573931
+ const renderer = this._dynamicBlocks.get(id);
573932
+ if (!renderer) return [];
573933
+ let blockLines;
573934
+ try {
573935
+ blockLines = renderer(maxWidth);
573936
+ } catch {
573937
+ return [];
573938
+ }
573939
+ return blockLines.flatMap(
573940
+ (segment) => this.reflowContentLine(segment, maxWidth).map((s2) => ({
573941
+ line: s2,
573942
+ bufferIdx: idx
573943
+ }))
573944
+ );
573945
+ }
573946
+ return this.reflowContentLine(line, maxWidth).map((segment) => ({
573527
573947
  line: segment,
573528
573948
  bufferIdx: idx
573529
- }))
573530
- );
573949
+ }));
573950
+ });
573531
573951
  }
573532
573952
  reflowContentLine(line, width) {
573533
573953
  const visible = stripAnsi(line);
@@ -573587,7 +574007,7 @@ ${CONTENT_BG_SEQ}`);
573587
574007
  const endRaw = this.rawIndexForVisibleColumn(line, end);
573588
574008
  const activeStyle = this.activeSgrAt(line, startRaw);
573589
574009
  const raw = line.slice(startRaw, endRaw);
573590
- return activeStyle ? `${activeStyle}${raw}${RESET2}` : raw;
574010
+ return activeStyle ? `${activeStyle}${raw}${RESET3}` : raw;
573591
574011
  }
573592
574012
  rawIndexForVisibleColumn(line, target) {
573593
574013
  if (target <= 0) return 0;
@@ -573611,7 +574031,7 @@ ${CONTENT_BG_SEQ}`);
573611
574031
  let match;
573612
574032
  while ((match = sgr.exec(line)) && match.index < rawIndex) {
573613
574033
  const seq = match[0];
573614
- if (seq === RESET2 || /\x1B\[(?:0|39|49)(?:;0)?m/.test(seq)) {
574034
+ if (seq === RESET3 || /\x1B\[(?:0|39|49)(?:;0)?m/.test(seq)) {
573615
574035
  active = "";
573616
574036
  } else {
573617
574037
  active += seq;
@@ -574386,21 +574806,21 @@ ${CONTENT_BG_SEQ}`);
574386
574806
  const inputWrap = this.wrapInput(w);
574387
574807
  let buf = "\x1B[?7l";
574388
574808
  const boxInner = w - 2;
574389
- buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_TR}${RESET2}${PANEL_BG_SEQ}`;
574809
+ buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL2}${BOX_H2.repeat(Math.max(0, boxInner))}${BOX_TR2}${RESET3}${PANEL_BG_SEQ}`;
574390
574810
  const Lspacer = layout();
574391
574811
  const spacerRow = pos.inputStartRow - 1;
574392
574812
  const tasksOccupiesSpacer = Lspacer.tasksHeight > 0 && spacerRow >= Lspacer.tasksTop && spacerRow <= Lspacer.tasksBottom;
574393
574813
  if (spacerRow >= this.scrollRegionTop && !tasksOccupiesSpacer) {
574394
- buf += `\x1B[${spacerRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET2}`;
574814
+ buf += `\x1B[${spacerRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET3}`;
574395
574815
  }
574396
574816
  for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
574397
574817
  const row = pos.inputStartRow + 1 + i2;
574398
574818
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
574399
574819
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
574400
574820
  buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
574401
- buf += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}`;
574821
+ buf += `${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}${lineContent}`;
574402
574822
  buf += `${PANEL_BG_SEQ}\x1B[K`;
574403
- buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}`;
574823
+ buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}`;
574404
574824
  }
574405
574825
  const cursorTermRow = pos.inputStartRow + 1 + inputWrap.cursorRow;
574406
574826
  if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
@@ -574412,17 +574832,17 @@ ${CONTENT_BG_SEQ}`);
574412
574832
  const fg2 = isHighlighted ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
574413
574833
  const slash = isHighlighted ? `\x1B[38;5;245m` : `\x1B[38;5;${TEXT_DIM}m`;
574414
574834
  const marker = isHighlighted ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
574415
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}`;
574835
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}`;
574416
574836
  buf += `${bg} ${marker}${slash}/${fg2}${cmd}`;
574417
574837
  buf += `${PANEL_BG_SEQ}\x1B[K`;
574418
- buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}`;
574838
+ buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}`;
574419
574839
  }
574420
574840
  const suggestBottomRow = pos.suggestStartRow + this._suggestions.length;
574421
- buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${RESET2}${PANEL_BG_SEQ}`;
574841
+ buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL2}${BOX_H2.repeat(Math.max(0, boxInner))}${BOX_BR2}${RESET3}${PANEL_BG_SEQ}`;
574422
574842
  } else {
574423
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInner))}${BOX_BR}${RESET2}${PANEL_BG_SEQ}`;
574843
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL2}${BOX_H2.repeat(Math.max(0, boxInner))}${BOX_BR2}${RESET3}${PANEL_BG_SEQ}`;
574424
574844
  }
574425
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}${PANEL_BG_SEQ}`;
574845
+ buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET3}${PANEL_BG_SEQ}`;
574426
574846
  buf += "\x1B[?7h";
574427
574847
  if (this.writeDepth === 0) {
574428
574848
  buf += `\x1B[${cursorTermRow};${inputWrap.cursorCol}H${CURSOR_BLINK_BLOCK}\x1B[?25h`;
@@ -574455,7 +574875,7 @@ ${CONTENT_BG_SEQ}`);
574455
574875
  const pos = this.rowPositions(termRows());
574456
574876
  let buf = "\x1B7\x1B[?7l";
574457
574877
  if (pos.tabBarRow > 0) {
574458
- buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET2}`;
574878
+ buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET3}`;
574459
574879
  }
574460
574880
  const boxInnerR = w - 2;
574461
574881
  if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
@@ -574465,14 +574885,14 @@ ${CONTENT_BG_SEQ}`);
574465
574885
  const isHl = si === this._suggestIndex;
574466
574886
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
574467
574887
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
574468
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
574469
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
574888
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
574889
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V2}${RESET3}`;
574470
574890
  }
574471
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${RESET2}`;
574891
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL2}${BOX_H2.repeat(Math.max(0, boxInnerR))}${BOX_BR2}${RESET3}`;
574472
574892
  } else {
574473
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerR))}${BOX_BR}${RESET2}`;
574893
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL2}${BOX_H2.repeat(Math.max(0, boxInnerR))}${BOX_BR2}${RESET3}`;
574474
574894
  }
574475
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}${PANEL_BG_SEQ}\x1B[?7h\x1B8` + // DEC restore cursor
574895
+ buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET3}${PANEL_BG_SEQ}\x1B[?7h\x1B8` + // DEC restore cursor
574476
574896
  (this.writeDepth === 0 ? `${CURSOR_BLINK_BLOCK}\x1B[?25h` : "");
574477
574897
  this.termWrite(buf);
574478
574898
  if (pos.tabBarRow > 0) this.renderAgentTabs();
@@ -574516,12 +574936,12 @@ ${CONTENT_BG_SEQ}`);
574516
574936
  }
574517
574937
  buf += "\x1B[?7l";
574518
574938
  const boxInnerH = w - 2;
574519
- buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL}${BOX_H.repeat(Math.max(0, boxInnerH))}${BOX_TR}${RESET2}`;
574939
+ buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL2}${BOX_H2.repeat(Math.max(0, boxInnerH))}${BOX_TR2}${RESET3}`;
574520
574940
  for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
574521
574941
  const row = pos.inputStartRow + 1 + i2;
574522
574942
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
574523
574943
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
574524
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
574944
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V2}${RESET3}`;
574525
574945
  }
574526
574946
  if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
574527
574947
  for (let si = 0; si < this._suggestions.length; si++) {
@@ -574531,14 +574951,14 @@ ${CONTENT_BG_SEQ}`);
574531
574951
  const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
574532
574952
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
574533
574953
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
574534
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}`;
574954
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}`;
574535
574955
  buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
574536
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}`;
574956
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V2}${RESET3}`;
574537
574957
  }
574538
574958
  }
574539
574959
  const boxInnerS = w - 2;
574540
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL}${BOX_H.repeat(Math.max(0, boxInnerS))}${BOX_BR}${RESET2}`;
574541
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET2}`;
574960
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL2}${BOX_H2.repeat(Math.max(0, boxInnerS))}${BOX_BR2}${RESET3}`;
574961
+ buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET3}`;
574542
574962
  buf += "\x1B[?7h";
574543
574963
  buf += "\x1B8";
574544
574964
  if (heightDelta > 0) {
@@ -574556,9 +574976,9 @@ ${CONTENT_BG_SEQ}`);
574556
574976
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
574557
574977
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
574558
574978
  buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
574559
- buf += `${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}${lineContent}`;
574979
+ buf += `${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}${lineContent}`;
574560
574980
  buf += `${PANEL_BG_SEQ}\x1B[K`;
574561
- buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V}${RESET2}${PANEL_BG_SEQ}`;
574981
+ buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V2}${RESET3}${PANEL_BG_SEQ}`;
574562
574982
  }
574563
574983
  buf += "\x1B[?7h";
574564
574984
  this.termWrite(buf);
@@ -649733,13 +650153,24 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
649733
650153
  }
649734
650154
  contentWrite(() => {
649735
650155
  if (result.completed) {
649736
- renderTaskComplete(
649737
- result.summary,
649738
- result.turns,
649739
- result.toolCalls,
649740
- result.durationMs,
649741
- tokens
649742
- );
650156
+ renderTaskComplete({
650157
+ task: effectiveTask,
650158
+ summary: result.summary,
650159
+ turns: result.turns,
650160
+ toolCalls: result.toolCalls,
650161
+ durationMs: result.durationMs,
650162
+ tokens,
650163
+ filesEdited: result.filesEdited,
650164
+ testsRun: result.testsRun,
650165
+ provenanceAnchors: result.provenanceAnchors,
650166
+ // Hand the status bar so the box renders as a resize-aware
650167
+ // dynamic block. When the bar isn't active (tests, headless),
650168
+ // the legacy line-based banner fires instead.
650169
+ host: statusBar?.isActive ? {
650170
+ registerDynamicBlock: (id, render2) => statusBar.registerDynamicBlock(id, render2),
650171
+ appendDynamicBlock: (id) => statusBar.appendDynamicBlock(id)
650172
+ } : void 0
650173
+ });
649743
650174
  if (onComplete)
649744
650175
  onComplete(result.summary, {
649745
650176
  turns: result.turns,