omnius 1.0.685 → 1.0.687

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
@@ -728029,6 +728029,135 @@ var init_overlay_lock = __esm({
728029
728029
  }
728030
728030
  });
728031
728031
 
728032
+ // packages/cli/src/tui/terminal-cells.ts
728033
+ function escapeEnd(value2, start2) {
728034
+ if (value2[start2] !== "\x1B") return start2 + 1;
728035
+ const kind = value2[start2 + 1];
728036
+ if (kind === "[") {
728037
+ for (let i2 = start2 + 2; i2 < value2.length; i2++) {
728038
+ const code8 = value2.charCodeAt(i2);
728039
+ if (code8 >= 64 && code8 <= 126) return i2 + 1;
728040
+ }
728041
+ return value2.length;
728042
+ }
728043
+ if (kind === "]") {
728044
+ for (let i2 = start2 + 2; i2 < value2.length; i2++) {
728045
+ if (value2[i2] === "\x07") return i2 + 1;
728046
+ if (value2[i2] === "\x1B" && value2[i2 + 1] === "\\") return i2 + 2;
728047
+ }
728048
+ return value2.length;
728049
+ }
728050
+ if (kind === "P" || kind === "X" || kind === "^" || kind === "_") {
728051
+ for (let i2 = start2 + 2; i2 < value2.length; i2++) {
728052
+ if (value2[i2] === "\x1B" && value2[i2 + 1] === "\\") return i2 + 2;
728053
+ }
728054
+ return value2.length;
728055
+ }
728056
+ return Math.min(value2.length, start2 + 2);
728057
+ }
728058
+ function stripTerminalSequences(value2) {
728059
+ let out = "";
728060
+ for (let i2 = 0; i2 < value2.length; ) {
728061
+ if (value2[i2] === "\x1B") {
728062
+ i2 = escapeEnd(value2, i2);
728063
+ continue;
728064
+ }
728065
+ const code8 = value2.charCodeAt(i2);
728066
+ if (code8 >= 0 && code8 < 32 || code8 === 127) {
728067
+ i2++;
728068
+ continue;
728069
+ }
728070
+ const cp2 = value2.codePointAt(i2);
728071
+ out += String.fromCodePoint(cp2);
728072
+ i2 += cp2 > 65535 ? 2 : 1;
728073
+ }
728074
+ return out;
728075
+ }
728076
+ function normalizeTerminalLine(value2) {
728077
+ return value2.replace(/\r\n|\r|\n/g, " ").replace(/\t/g, " ");
728078
+ }
728079
+ function isWideCodePoint(cp2) {
728080
+ return cp2 >= 4352 && cp2 <= 4447 || cp2 === 9001 || cp2 === 9002 || cp2 >= 11904 && cp2 <= 12350 || cp2 >= 12352 && cp2 <= 42191 || cp2 >= 44032 && cp2 <= 55203 || cp2 >= 63744 && cp2 <= 64255 || cp2 >= 65040 && cp2 <= 65049 || cp2 >= 65072 && cp2 <= 65135 || cp2 >= 65280 && cp2 <= 65376 || cp2 >= 65504 && cp2 <= 65510 || cp2 >= 110592 && cp2 <= 111359 || cp2 >= 131072 && cp2 <= 262141;
728081
+ }
728082
+ function graphemeCellWidth(value2) {
728083
+ if (!value2 || zeroWidthGrapheme.test(value2)) return 0;
728084
+ const cp2 = value2.codePointAt(0);
728085
+ if (cp2 < 32 || cp2 >= 127 && cp2 < 160) return 0;
728086
+ if (emojiPresentation.test(value2) || value2.includes("️") || value2.includes("‍") && extendedPictographic.test(value2) || cp2 >= 127462 && cp2 <= 127487) {
728087
+ return 2;
728088
+ }
728089
+ return isWideCodePoint(cp2) ? 2 : 1;
728090
+ }
728091
+ function plainGraphemes(value2) {
728092
+ return Array.from(
728093
+ graphemes.segment(stripTerminalSequences(value2)),
728094
+ (part) => part.segment
728095
+ );
728096
+ }
728097
+ function terminalCellWidth(value2) {
728098
+ let width = 0;
728099
+ for (const grapheme of plainGraphemes(normalizeTerminalLine(value2))) {
728100
+ width += graphemeCellWidth(grapheme);
728101
+ }
728102
+ return width;
728103
+ }
728104
+ function terminalContentSpan(value2) {
728105
+ const parts = plainGraphemes(normalizeTerminalLine(value2));
728106
+ let col = 1;
728107
+ let start2 = null;
728108
+ let end = null;
728109
+ for (const part of parts) {
728110
+ const width = graphemeCellWidth(part);
728111
+ const occupied = !/^\s+$/u.test(part) && width > 0;
728112
+ if (occupied) {
728113
+ if (start2 === null) start2 = col;
728114
+ end = col + width - 1;
728115
+ }
728116
+ col += width;
728117
+ }
728118
+ return start2 === null || end === null ? null : { start: start2, end };
728119
+ }
728120
+ function truncateTerminalCells(input, maxCells) {
728121
+ const value2 = normalizeTerminalLine(input);
728122
+ if (maxCells <= 0) return "";
728123
+ if (terminalCellWidth(value2) <= maxCells) return value2;
728124
+ const closeStyles = "\x1B]8;;\x07\x1B[0m";
728125
+ if (maxCells === 1) return `…${closeStyles}`;
728126
+ const target = maxCells - 1;
728127
+ let width = 0;
728128
+ let out = "";
728129
+ for (let i2 = 0; i2 < value2.length; ) {
728130
+ if (value2[i2] === "\x1B") {
728131
+ const end2 = escapeEnd(value2, i2);
728132
+ out += value2.slice(i2, end2);
728133
+ i2 = end2;
728134
+ continue;
728135
+ }
728136
+ const nextEscape = value2.indexOf("\x1B", i2);
728137
+ const end = nextEscape < 0 ? value2.length : nextEscape;
728138
+ const chunk = value2.slice(i2, end);
728139
+ for (const part of graphemes.segment(chunk)) {
728140
+ const cellWidth = graphemeCellWidth(part.segment);
728141
+ if (width + cellWidth > target) {
728142
+ return `${out}…${closeStyles}`;
728143
+ }
728144
+ out += part.segment;
728145
+ width += cellWidth;
728146
+ }
728147
+ i2 = end;
728148
+ }
728149
+ return `${out}${closeStyles}`;
728150
+ }
728151
+ var graphemes, extendedPictographic, emojiPresentation, zeroWidthGrapheme;
728152
+ var init_terminal_cells = __esm({
728153
+ "packages/cli/src/tui/terminal-cells.ts"() {
728154
+ graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
728155
+ extendedPictographic = new RegExp("\\p{Extended_Pictographic}", "u");
728156
+ emojiPresentation = new RegExp("\\p{Emoji_Presentation}", "u");
728157
+ zeroWidthGrapheme = /^[\p{Mark}\p{Cf}\u200c\u200d\ufe0e\ufe0f]+$/u;
728158
+ }
728159
+ });
728160
+
728032
728161
  // packages/cli/src/tui/status-bar.ts
728033
728162
  var status_bar_exports = {};
728034
728163
  __export(status_bar_exports, {
@@ -728157,7 +728286,7 @@ function setTerminalTitle(task, version5) {
728157
728286
  process.stdout.write(data);
728158
728287
  }
728159
728288
  }
728160
- 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, HEADER_BUTTON_GLYPH_FG, HEADER_BUTTON_BG, HEADER_BUTTON_FG, HEADER_ACCENT_BOLD_FG, HEADER_TELEGRAM_FG, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, BOX_BJ, BOX_TJ, ENHANCE_SEG_INNER, ENHANCE_SPIN_FRAMES, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, HEADER_BUTTON_LEFT, HEADER_BUTTON_RIGHT, HEADER_BUTTON_SQUARE_PAD, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
728289
+ 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, HEADER_BUTTON_GLYPH_FG, HEADER_BUTTON_BG, HEADER_BUTTON_FG, HEADER_ACCENT_BOLD_FG, HEADER_BUTTON_HOVER_BG, HEADER_BUTTON_HOVER_FG, HEADER_TELEGRAM_FG, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, BOX_BJ, BOX_TJ, ENHANCE_SEG_INNER, ENHANCE_SPIN_FRAMES, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, HEADER_BUTTON_LEFT, HEADER_BUTTON_RIGHT, HEADER_BUTTON_SQUARE_PAD, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
728161
728290
  var init_status_bar = __esm({
728162
728291
  "packages/cli/src/tui/status-bar.ts"() {
728163
728292
  init_render();
@@ -728173,6 +728302,7 @@ var init_status_bar = __esm({
728173
728302
  init_overlay_lock();
728174
728303
  init_dist5();
728175
728304
  init_terminal_capabilities();
728305
+ init_terminal_cells();
728176
728306
  init_theme();
728177
728307
  init_tool_collapse_store();
728178
728308
  init_layout2();
@@ -728347,6 +728477,8 @@ var init_status_bar = __esm({
728347
728477
  HEADER_BUTTON_BG = headerButtonBg();
728348
728478
  HEADER_BUTTON_FG = headerButtonFg();
728349
728479
  HEADER_ACCENT_BOLD_FG = headerAccentBoldFg();
728480
+ HEADER_BUTTON_HOVER_BG = "\x1B[48;5;255m";
728481
+ HEADER_BUTTON_HOVER_FG = "\x1B[38;5;16m";
728350
728482
  HEADER_TELEGRAM_FG = headerTelegramFg();
728351
728483
  BOX_TL3 = "╭";
728352
728484
  BOX_TR3 = "╮";
@@ -728591,6 +728723,8 @@ var init_status_bar = __esm({
728591
728723
  _suggestions = [];
728592
728724
  /** Currently highlighted suggestion index (-1 = none) */
728593
728725
  _suggestIndex = -1;
728726
+ /** Exact visible command spans from the last suggestion paint. */
728727
+ _suggestionHitZones = [];
728594
728728
  /** Sponsor label/link shown in the normal header identity slot */
728595
728729
  _sponsorHeader = null;
728596
728730
  /** Whether suggestions were triggered by direct typing (instant) vs history navigation (delayed) */
@@ -729013,7 +729147,7 @@ var init_status_bar = __esm({
729013
729147
  const parts = [
729014
729148
  {
729015
729149
  text: firstText,
729016
- width: stripAnsi(firstText).length,
729150
+ width: terminalCellWidth(firstText),
729017
729151
  ...sponsorLabel && sponsorLink ? { linkUrl: sponsorLink } : {}
729018
729152
  }
729019
729153
  ];
@@ -729097,6 +729231,8 @@ var init_status_bar = __esm({
729097
729231
  /** Index of the currently visible panel (0 = main) */
729098
729232
  _headerPanelIndex = 0;
729099
729233
  _headerCommandZones = [];
729234
+ /** Action under the pointer. The active panel renderer owns its visuals. */
729235
+ _headerHoveredAction = null;
729100
729236
  /** Sys panel separator column offset (for T-junction rendering) */
729101
729237
  _sysSeparatorOffset = null;
729102
729238
  /** Register a header panel. Returns its index. */
@@ -729114,23 +729250,28 @@ var init_status_bar = __esm({
729114
729250
  * - Category B: Systems (agents/voice status/nexus status)
729115
729251
  * Each category paginates independently across N pages. */
729116
729252
  /** Filled header button whose hue band follows the child agent's current action. */
729117
- paintAgentButton(content, stage2, active) {
729253
+ paintAgentButton(content, stage2, active, action) {
729118
729254
  const useTruecolor = supportsAnimatedTuiChrome();
729119
729255
  const ornamentalEdges = supportsOrnamentalTuiButtonEdges();
729256
+ const hovered = this._headerHoveredAction === action;
729120
729257
  const chars = Array.from(
729121
729258
  ornamentalEdges ? content : `${HEADER_BUTTON_SQUARE_PAD}${content}${HEADER_BUTTON_SQUARE_PAD}`
729122
729259
  );
729123
729260
  let body = "";
729124
- for (let i2 = 0; i2 < chars.length; i2++) {
729125
- const char = chars[i2];
729126
- if (useTruecolor) {
729127
- const [r2, g, b] = stageGradientRgb(stage2, i2, this._stagePhase);
729128
- const luma = 0.299 * r2 + 0.587 * g + 0.114 * b;
729129
- const fg2 = luma >= 140 ? "\x1B[38;2;16;16;16m" : "\x1B[38;2;255;255;255m";
729130
- body += `${active ? "\x1B[1m" : ""}${fg2}\x1B[48;2;${r2};${g};${b}m${char}\x1B[0m`;
729131
- } else {
729132
- const fallback = stageFallbackColor(stage2);
729133
- body += `${active ? "\x1B[1m" : ""}\x1B[38;5;${contrastTextColor(fallback)}m\x1B[48;5;${fallback}m${char}\x1B[0m`;
729261
+ if (hovered) {
729262
+ body = `${active ? "\x1B[1m" : ""}${HEADER_BUTTON_HOVER_FG}${HEADER_BUTTON_HOVER_BG}${chars.join("")}\x1B[0m`;
729263
+ } else {
729264
+ for (let i2 = 0; i2 < chars.length; i2++) {
729265
+ const char = chars[i2];
729266
+ if (useTruecolor) {
729267
+ const [r2, g, b] = stageGradientRgb(stage2, i2, this._stagePhase);
729268
+ const luma = 0.299 * r2 + 0.587 * g + 0.114 * b;
729269
+ const fg2 = luma >= 140 ? "\x1B[38;2;16;16;16m" : "\x1B[38;2;255;255;255m";
729270
+ body += `${active ? "\x1B[1m" : ""}${fg2}\x1B[48;2;${r2};${g};${b}m${char}\x1B[0m`;
729271
+ } else {
729272
+ const fallback = stageFallbackColor(stage2);
729273
+ body += `${active ? "\x1B[1m" : ""}\x1B[38;5;${contrastTextColor(fallback)}m\x1B[48;5;${fallback}m${char}\x1B[0m`;
729274
+ }
729134
729275
  }
729135
729276
  }
729136
729277
  if (!ornamentalEdges) return `${body}${RESET4}${PANEL_BG_SEQ}`;
@@ -729166,10 +729307,14 @@ var init_status_bar = __esm({
729166
729307
  return `\x1B]8;;${cmdPrefix}\x07${label}\x1B]8;;\x07`;
729167
729308
  };
729168
729309
  const decorateMenuButton = (cmd, label) => {
729310
+ const action = cmd.startsWith("view:") ? cmd : `/${cmd}`;
729311
+ const hovered = this._headerHoveredAction === action;
729312
+ const buttonBg = hovered ? HEADER_BUTTON_HOVER_BG : HEADER_BUTTON_BG;
729313
+ const buttonFg = hovered ? HEADER_BUTTON_HOVER_FG : HEADER_BUTTON_FG;
729169
729314
  if (!supportsOrnamentalTuiButtonEdges()) {
729170
- return `${HEADER_BUTTON_BG}${HEADER_BUTTON_FG}${HEADER_BUTTON_SQUARE_PAD}${label}${HEADER_BUTTON_SQUARE_PAD}\x1B[0m${PANEL_BG_SEQ}`;
729315
+ return `${buttonBg}${buttonFg}${HEADER_BUTTON_SQUARE_PAD}${label}${HEADER_BUTTON_SQUARE_PAD}\x1B[0m${PANEL_BG_SEQ}`;
729171
729316
  }
729172
- return `${HEADER_BUTTON_GLYPH_FG}${HEADER_BUTTON_LEFT}\x1B[0m${HEADER_BUTTON_BG}${HEADER_BUTTON_FG}${label}\x1B[0m${PANEL_BG_SEQ}${HEADER_BUTTON_GLYPH_FG}${HEADER_BUTTON_RIGHT}\x1B[0m${PANEL_BG_SEQ}`;
729317
+ return `${HEADER_BUTTON_GLYPH_FG}${HEADER_BUTTON_LEFT}\x1B[0m${buttonBg}${buttonFg}${label}\x1B[0m${PANEL_BG_SEQ}${HEADER_BUTTON_GLYPH_FG}${HEADER_BUTTON_RIGHT}\x1B[0m${PANEL_BG_SEQ}`;
729173
729318
  };
729174
729319
  const renderBtn = (cmd, label) => {
729175
729320
  return linkify(cmd, decorateMenuButton(cmd, label));
@@ -729181,20 +729326,25 @@ var init_status_bar = __esm({
729181
729326
  const headerLiveDot = headerLiveMediaActive ? Math.floor(Date.now() / 500) % 2 === 0 ? "●" : "○" : "";
729182
729327
  const headerLiveLabel = headerLiveMediaActive ? `${headerLiveDot}live` : "live";
729183
729328
  const menuBtns = [
729184
- { cmd: "help", label: "help", w: "help".length + 2 },
729185
- // +2 for spaces
729329
+ { cmd: "help", label: "help", w: terminalCellWidth("help") + 2 },
729186
729330
  {
729187
729331
  cmd: "voice",
729188
729332
  label: this._voiceActive ? this._voiceModelId || "voice" : "voice",
729189
- w: (this._voiceActive ? this._voiceModelId || "voice" : "voice").length + 2
729190
- },
729191
- // +2 for spaces
729192
- { cmd: "live", label: headerLiveLabel, w: headerLiveLabel.length + 2 },
729193
- // +2 for spaces
729194
- { cmd: "model", label: modelLabel, w: modelLabel.length + 2 },
729195
- // +2 for spaces
729196
- { cmd: "endpoint", label: endpointLabel, w: endpointLabel.length + 2 }
729197
- // +2 for spaces
729333
+ w: terminalCellWidth(
729334
+ this._voiceActive ? this._voiceModelId || "voice" : "voice"
729335
+ ) + 2
729336
+ },
729337
+ {
729338
+ cmd: "live",
729339
+ label: headerLiveLabel,
729340
+ w: terminalCellWidth(headerLiveLabel) + 2
729341
+ },
729342
+ { cmd: "model", label: modelLabel, w: terminalCellWidth(modelLabel) + 2 },
729343
+ {
729344
+ cmd: "endpoint",
729345
+ label: endpointLabel,
729346
+ w: terminalCellWidth(endpointLabel) + 2
729347
+ }
729198
729348
  ];
729199
729349
  const verW = identity3.width;
729200
729350
  let menuPages = [];
@@ -729250,7 +729400,7 @@ var init_status_bar = __esm({
729250
729400
  const mainLabel = ` ↩ main `;
729251
729401
  sysItems.push({
729252
729402
  render: () => linkify("view:main", decorateMenuButton("view:main", mainLabel)) + " ",
729253
- w: mainLabel.length + 2 + 1
729403
+ w: terminalCellWidth(mainLabel) + 2 + 1
729254
729404
  });
729255
729405
  }
729256
729406
  if (this._agentViews.size > 1) {
@@ -729259,17 +729409,25 @@ var init_status_bar = __esm({
729259
729409
  const icon = view.status === "running" ? "●" : view.status === "completed" ? "✓" : view.status === "failed" ? "✗" : "○";
729260
729410
  const content = ` ${trunc3(view.label)} ${icon} `;
729261
729411
  const active = view.id === this._activeViewId;
729262
- const btn = this.paintAgentButton(content, view.stage, active);
729263
729412
  sysItems.push({
729264
- render: () => linkify(`view:${view.id}`, btn) + " ",
729265
- w: content.length + 2 + 1
729266
- // 2 border glyphs + trailing space
729413
+ // Build this at paint time. Hover changes do not rebuild the panel;
729414
+ // a precomputed ANSI string would keep the old background forever.
729415
+ render: () => linkify(
729416
+ `view:${view.id}`,
729417
+ this.paintAgentButton(
729418
+ content,
729419
+ view.stage,
729420
+ active,
729421
+ `view:${view.id}`
729422
+ )
729423
+ ) + " ",
729424
+ w: terminalCellWidth(content) + 2 + 1
729267
729425
  });
729268
729426
  }
729269
729427
  } else {
729270
729428
  sysItems.push({
729271
729429
  render: () => `\x1B[38;5;${TEXT_DIM}m${NO_SUB_AGENTS_HEADER_LABEL}`,
729272
- w: NO_SUB_AGENTS_HEADER_LABEL.length
729430
+ w: terminalCellWidth(NO_SUB_AGENTS_HEADER_LABEL)
729273
729431
  });
729274
729432
  }
729275
729433
  const sysSeparatorOffset = sysItems.reduce((sum2, item) => sum2 + item.w, 0);
@@ -729282,25 +729440,25 @@ var init_status_bar = __esm({
729282
729440
  const voiceIcon = this._voiceActive ? "●" : "○";
729283
729441
  sysItems.push({
729284
729442
  render: () => renderBtn("voice", `${voiceIcon}${voiceLabel}`) + " ",
729285
- w: voiceLabel.length + 2
729443
+ w: terminalCellWidth(`${voiceIcon}${voiceLabel}`) + 2 + 1
729286
729444
  });
729287
729445
  const telegramDot = this._telegramStatus.active ? "●" : "○";
729288
729446
  const telegramLabel = this._telegramStatus.activeSubAgents > 0 ? ` ✈ tg ${this._telegramStatus.activeSubAgents} ` : " ✈ tg ";
729289
729447
  sysItems.push({
729290
729448
  render: () => renderBtn("telegram", `${telegramDot}${telegramLabel}`) + " ",
729291
- w: telegramLabel.length + 2
729449
+ w: terminalCellWidth(`${telegramDot}${telegramLabel}`) + 2 + 1
729292
729450
  });
729293
729451
  const liveMediaActive = this._liveMediaStatus.audio || this._liveMediaStatus.video;
729294
729452
  const liveMediaDot = liveMediaActive ? Math.floor(Date.now() / 500) % 2 === 0 ? "●" : "○" : "○";
729295
729453
  const liveMediaLabel = liveMediaActive ? ` ${this._liveMediaStatus.audio ? "aud" : ""}${this._liveMediaStatus.audio && this._liveMediaStatus.video ? "+" : ""}${this._liveMediaStatus.video ? "vid" : ""} ` : " av ";
729296
729454
  sysItems.push({
729297
729455
  render: () => renderBtn("live", `${liveMediaDot}${liveMediaLabel}`) + " ",
729298
- w: liveMediaLabel.length + 2
729456
+ w: terminalCellWidth(`${liveMediaDot}${liveMediaLabel}`) + 2 + 1
729299
729457
  });
729300
729458
  const nexusDot = this._nexusStatus === "connected" || this._nexusStatus === "connecting" ? "●" : "○";
729301
729459
  sysItems.push({
729302
729460
  render: () => renderBtn("nexus", `${nexusDot} nexus `) + " ",
729303
- w: 9
729461
+ w: terminalCellWidth(`${nexusDot} nexus `) + 2 + 1
729304
729462
  });
729305
729463
  let sysPages = [];
729306
729464
  let sCurPage = [];
@@ -729335,6 +729493,7 @@ var init_status_bar = __esm({
729335
729493
  /** Switch to the next header panel (wraps around) */
729336
729494
  nextHeaderPanel() {
729337
729495
  if (this._headerPanels.length <= 1) return;
729496
+ this._headerHoveredAction = null;
729338
729497
  this._headerPanelIndex = (this._headerPanelIndex + 1) % this._headerPanels.length;
729339
729498
  if (this._bannerRefresh) this._bannerRefresh();
729340
729499
  else this.refreshHeaderContent();
@@ -729342,6 +729501,7 @@ var init_status_bar = __esm({
729342
729501
  /** Switch to the previous header panel (wraps around) */
729343
729502
  prevHeaderPanel() {
729344
729503
  if (this._headerPanels.length <= 1) return;
729504
+ this._headerHoveredAction = null;
729345
729505
  this._headerPanelIndex = (this._headerPanelIndex - 1 + this._headerPanels.length) % this._headerPanels.length;
729346
729506
  if (this._bannerRefresh) this._bannerRefresh();
729347
729507
  else this.refreshHeaderContent();
@@ -729360,7 +729520,8 @@ var init_status_bar = __esm({
729360
729520
  }
729361
729521
  if (panel.meta.kind === "system" && this._sysSeparatorOffset !== null) {
729362
729522
  const rendered = stripAnsi(panel.render(chrome.innerWidth));
729363
- const renderedOffset = Array.from(rendered).indexOf("│");
729523
+ const separatorIndex = rendered.indexOf("│");
729524
+ const renderedOffset = separatorIndex >= 0 ? terminalCellWidth(rendered.slice(0, separatorIndex)) : -1;
729364
729525
  const offset = renderedOffset >= 0 ? renderedOffset : this._sysSeparatorOffset;
729365
729526
  const col = chrome.contentStartCol + offset;
729366
729527
  if (col > 1 && col < termWidth) return [col];
@@ -729390,6 +729551,12 @@ var init_status_bar = __esm({
729390
729551
  );
729391
729552
  return hit?.cmd ?? null;
729392
729553
  }
729554
+ /** Repaint the header only when pointer focus crosses an exact action zone. */
729555
+ setHeaderHoveredAction(action) {
729556
+ if (this._headerHoveredAction === action) return;
729557
+ this._headerHoveredAction = action;
729558
+ this.refreshHeaderContent();
729559
+ }
729393
729560
  /** Render the current header panel content onto terminal row 2 (inside box) */
729394
729561
  refreshHeaderContent() {
729395
729562
  if (!this.active) return;
@@ -729433,8 +729600,9 @@ var init_status_bar = __esm({
729433
729600
  if (this._activeViewId !== "main") {
729434
729601
  const mainLabel = ` ↩ main `;
729435
729602
  zones.push({
729436
- w: mainLabel.length + 2 + 1,
729603
+ w: terminalCellWidth(mainLabel) + 2 + 1,
729437
729604
  id: "main",
729605
+ action: "view:main",
729438
729606
  render: () => ""
729439
729607
  });
729440
729608
  }
@@ -729443,20 +729611,48 @@ var init_status_bar = __esm({
729443
729611
  if (view.id === "main" && this._activeViewId === "main") continue;
729444
729612
  const icon = view.status === "running" ? "●" : view.status === "completed" ? "✓" : view.status === "failed" ? "✗" : "○";
729445
729613
  const base3 = ` ${trunc3(view.label)} ${icon} `;
729446
- zones.push({ w: base3.length + 2 + 1, id: view.id, render: () => "" });
729614
+ zones.push({
729615
+ w: terminalCellWidth(base3) + 2 + 1,
729616
+ id: view.id,
729617
+ action: `view:${view.id}`,
729618
+ render: () => ""
729619
+ });
729447
729620
  }
729448
729621
  } else {
729449
- zones.push({ w: NO_SUB_AGENTS_HEADER_LABEL.length, render: () => "" });
729622
+ zones.push({
729623
+ w: terminalCellWidth(NO_SUB_AGENTS_HEADER_LABEL),
729624
+ render: () => ""
729625
+ });
729450
729626
  }
729451
729627
  zones.push({ w: 2, render: () => "" });
729452
729628
  const voiceLabel = this._voiceActive ? ` ${this._voiceModelId || "voice"} ` : " voice ";
729453
- zones.push({ w: voiceLabel.length + 2, render: () => "" });
729629
+ const voiceIcon = this._voiceActive ? "●" : "";
729630
+ zones.push({
729631
+ w: terminalCellWidth(`${voiceIcon}${voiceLabel}`) + 2 + 1,
729632
+ action: "/voice",
729633
+ render: () => ""
729634
+ });
729635
+ const telegramDot = this._telegramStatus.active ? "●" : "○";
729454
729636
  const telegramLabel = this._telegramStatus.activeSubAgents > 0 ? ` ✈ tg ${this._telegramStatus.activeSubAgents} ` : " ✈ tg ";
729455
- zones.push({ w: telegramLabel.length + 2, render: () => "" });
729637
+ zones.push({
729638
+ w: terminalCellWidth(`${telegramDot}${telegramLabel}`) + 2 + 1,
729639
+ action: "/telegram",
729640
+ render: () => ""
729641
+ });
729456
729642
  const liveMediaActive = this._liveMediaStatus.audio || this._liveMediaStatus.video;
729643
+ const liveMediaDot = liveMediaActive ? "●" : "○";
729457
729644
  const liveMediaLabel = liveMediaActive ? ` ${this._liveMediaStatus.audio ? "aud" : ""}${this._liveMediaStatus.audio && this._liveMediaStatus.video ? "+" : ""}${this._liveMediaStatus.video ? "vid" : ""} ` : " av ";
729458
- zones.push({ w: liveMediaLabel.length + 2, render: () => "" });
729459
- zones.push({ w: 9, render: () => "" });
729645
+ zones.push({
729646
+ w: terminalCellWidth(`${liveMediaDot}${liveMediaLabel}`) + 2 + 1,
729647
+ action: "/live",
729648
+ render: () => ""
729649
+ });
729650
+ const nexusDot = this._nexusStatus === "connected" || this._nexusStatus === "connecting" ? "●" : "○";
729651
+ zones.push({
729652
+ w: terminalCellWidth(`${nexusDot} nexus `) + 2 + 1,
729653
+ action: "/nexus",
729654
+ render: () => ""
729655
+ });
729460
729656
  let pages = [];
729461
729657
  let cur = [];
729462
729658
  let used = 0;
@@ -729475,22 +729671,36 @@ var init_status_bar = __esm({
729475
729671
  let col = chromeLayout.contentStartCol;
729476
729672
  const clickZones = [];
729477
729673
  for (const z21 of page2) {
729478
- if (z21.id) clickZones.push({ start: col, end: col + z21.w - 2, id: z21.id });
729674
+ if (z21.action) {
729675
+ clickZones.push({
729676
+ start: col,
729677
+ end: col + z21.w - 2,
729678
+ id: z21.id,
729679
+ action: z21.action
729680
+ });
729681
+ }
729479
729682
  col += z21.w;
729480
729683
  }
729481
729684
  this._sysClickZones = clickZones;
729685
+ this._headerCommandZones = clickZones.map((zone) => ({
729686
+ start: zone.start,
729687
+ end: zone.end,
729688
+ cmd: zone.action
729689
+ }));
729482
729690
  }
729483
729691
  const hdrRow = layout().headerContent;
729484
729692
  let buf = "\x1B7";
729485
729693
  buf += `\x1B[${hdrRow};1H${PANEL_BG_SEQ}\x1B[2K`;
729486
729694
  buf += `${BOX_FG}│${RESET4}${PANEL_BG_SEQ}`;
729487
729695
  if (chromeLayout.showPrev) {
729488
- buf += `${HEADER_BUTTON_FG}◀${RESET4}${PANEL_BG_SEQ} `;
729696
+ const prevStyle = this._headerHoveredAction === "header-prev" ? `${HEADER_BUTTON_HOVER_BG}${HEADER_BUTTON_HOVER_FG}` : HEADER_BUTTON_FG;
729697
+ buf += `${prevStyle}◀${RESET4}${PANEL_BG_SEQ} `;
729489
729698
  }
729490
729699
  buf += `\x1B[38;5;${TEXT_PRIMARY}m${PANEL_BG_SEQ}`;
729491
729700
  buf += content;
729492
729701
  if (chromeLayout.showNext) {
729493
- buf += `\x1B[${hdrRow};${w - 1}H${HEADER_BUTTON_FG}▶${RESET4}${PANEL_BG_SEQ}`;
729702
+ const nextStyle = this._headerHoveredAction === "header-next" ? `${HEADER_BUTTON_HOVER_BG}${HEADER_BUTTON_HOVER_FG}` : HEADER_BUTTON_FG;
729703
+ buf += `\x1B[${hdrRow};${w - 1}H${nextStyle}▶${RESET4}${PANEL_BG_SEQ}`;
729494
729704
  }
729495
729705
  buf += `\x1B[${hdrRow};${w}H${BOX_FG}│${RESET4}${PANEL_BG_SEQ}`;
729496
729706
  const scrollPct = this._contentScrollOffset > 0 ? `${Math.round(this._contentScrollOffset / this._contentMaxLines * 100)}%` : "live";
@@ -729546,7 +729756,13 @@ var init_status_bar = __esm({
729546
729756
  buf += `\x1B[38;5;${TEXT_DIM}m${PANEL_BG_SEQ}`;
729547
729757
  buf += `scroll: ${scrollPct}`.substring(0, w - 4);
729548
729758
  buf += `\x1B[${scrollRow};${w}H${BOX_FG}│${RESET4}${PANEL_BG_SEQ}`;
729549
- buf += `\x1B[${scrollRow};1H${BOX_FG}╰${"─".repeat(w - 2)}${BOX_FG}╯${RESET4}${PANEL_BG_SEQ}`;
729759
+ const collapsedBottomChars = Array.from(
729760
+ `${BOX_BL3}${BOX_H3.repeat(w - 2)}${BOX_BR3}`
729761
+ );
729762
+ for (const col of this.getHeaderBorderSeparatorColumns(w)) {
729763
+ if (col > 1 && col < w) collapsedBottomChars[col - 1] = BOX_BJ;
729764
+ }
729765
+ buf += `\x1B[${scrollRow};1H${BOX_FG}${collapsedBottomChars.join("")}${RESET4}${PANEL_BG_SEQ}`;
729550
729766
  }
729551
729767
  buf += "\x1B8";
729552
729768
  this.termWrite(buf);
@@ -730515,17 +730731,35 @@ var init_status_bar = __esm({
730515
730731
  }
730516
730732
  return false;
730517
730733
  }
730518
- /** Handle mouse click on a suggestion row */
730519
- suggestClickAt(row2) {
730520
- const pos = this.rowPositions(termRows());
730521
- if (pos.suggestStartRow <= 0 || this._suggestions.length === 0)
730522
- return false;
730523
- const idx = row2 - pos.suggestStartRow;
730524
- if (idx >= 0 && idx < this._suggestions.length) {
730525
- this._suggestIndex = idx;
730526
- return this.suggestAccept();
730734
+ rebuildSuggestionHitZones(suggestStartRow, width) {
730735
+ if (suggestStartRow <= 0 || this._suggestions.length === 0) {
730736
+ this._suggestionHitZones = [];
730737
+ return;
730527
730738
  }
730528
- return false;
730739
+ const startCol = 5;
730740
+ this._suggestionHitZones = this._suggestions.flatMap((command, index) => {
730741
+ const endCol = Math.min(
730742
+ width - 1,
730743
+ startCol + terminalCellWidth(command)
730744
+ );
730745
+ return endCol < startCol ? [] : [
730746
+ {
730747
+ row: suggestStartRow + index,
730748
+ startCol,
730749
+ endCol,
730750
+ index
730751
+ }
730752
+ ];
730753
+ });
730754
+ }
730755
+ /** Handle a click only when it lands on the visibly painted command text. */
730756
+ suggestClickAt(row2, col) {
730757
+ const zone = this._suggestionHitZones.find(
730758
+ (candidate) => candidate.row === row2 && col >= candidate.startCol && col <= candidate.endCol
730759
+ );
730760
+ if (!zone || zone.index >= this._suggestions.length) return false;
730761
+ this._suggestIndex = zone.index;
730762
+ return this.suggestAccept();
730529
730763
  }
730530
730764
  /** Update the suggestion list based on current input. Called on every render. */
730531
730765
  _updateSuggestions() {
@@ -730630,11 +730864,11 @@ var init_status_bar = __esm({
730630
730864
  return this._cohereActive;
730631
730865
  }
730632
730866
  // ── Mouse tracking management ──────────────────────────────────────
730633
- // Mouse reporting is required for header buttons and scroll-wheel routing.
730634
- // Use click-only reporting (?1000h) instead of drag-motion reporting (?1002h)
730635
- // so Omnius does not own click-drag selection or paint fake highlights while
730636
- // tokens are streaming. Overlay/select UIs may temporarily suspend mouse mode
730637
- // and then call restoreMouseTracking() on return.
730867
+ // Mouse reporting is required for header buttons, hover, and scroll routing.
730868
+ // Hover-capable reporting means terminals reserve unmodified pointer motion
730869
+ // for the application. Shift-drag remains the native terminal selection path.
730870
+ // Overlay/select UIs may temporarily suspend mouse mode and then call
730871
+ // restoreMouseTracking() on return.
730638
730872
  /** Callback to check if neovim has focus (set by interactive.ts to avoid circular import) */
730639
730873
  _isNeovimFocused = null;
730640
730874
  /** Register neovim focus checker — called from interactive.ts after neovim-mode imports */
@@ -730671,7 +730905,7 @@ var init_status_bar = __esm({
730671
730905
  if (this._isNeovimFocused?.()) return;
730672
730906
  this._mouseTrackingEnabled = true;
730673
730907
  if (process.stdout.isTTY) {
730674
- this._trueStdoutWrite.call(process.stdout, "\x1B[?1000h\x1B[?1006h");
730908
+ this._trueStdoutWrite.call(process.stdout, "\x1B[?1003h\x1B[?1006h");
730675
730909
  }
730676
730910
  }
730677
730911
  /** Disable mouse tracking entirely (overlay transitions + exit). */
@@ -730775,32 +731009,29 @@ var init_status_bar = __esm({
730775
731009
  handlePointerEvent(type, col, row2) {
730776
731010
  if (!this.active) return;
730777
731011
  const w = termCols();
731012
+ if (type === "drag") {
731013
+ this.setHeaderHoveredAction(
731014
+ this.hitTestCurrentHeaderAction(row2, col, w)
731015
+ );
731016
+ }
730778
731017
  if (type === "press" && row2 >= this.scrollRegionTop) {
730779
731018
  if (this.handleContentBlockClick(row2, col)) return;
730780
731019
  }
730781
731020
  if (type === "press" && this._suggestions.length > 0) {
730782
- if (this.suggestClickAt(row2)) return;
731021
+ if (this.suggestClickAt(row2, col)) return;
730783
731022
  }
730784
731023
  if (row2 < this.scrollRegionTop) {
730785
- const hdrRow = layout().headerContent;
730786
- if (type === "press" && row2 === hdrRow && String(this.currentHeaderPanel).startsWith("sys-")) {
730787
- const zones = this._sysClickZones ?? [];
730788
- const hit = zones.find((z21) => col >= z21.start && col <= z21.end);
730789
- if (hit) {
730790
- this.switchToView(hit.id);
730791
- return;
730792
- }
730793
- }
730794
731024
  if (type === "press" && this._updateLatest) {
730795
- const hdrRow2 = layout().headerContent;
731025
+ const hdrRow = layout().headerContent;
730796
731026
  const verZone = this._verClickZone;
730797
- if (row2 === hdrRow2 && verZone && col >= verZone.start && col <= verZone.end) {
731027
+ if (row2 === hdrRow && verZone && col >= verZone.start && col <= verZone.end) {
730798
731028
  if (this._headerButtonHandler) this._headerButtonHandler("/update");
730799
731029
  return;
730800
731030
  }
730801
731031
  }
730802
731032
  const cmd = this.hitTestCurrentHeaderAction(row2, col, w);
730803
731033
  if (type === "press" && cmd) {
731034
+ this.setHeaderHoveredAction(cmd);
730804
731035
  if (cmd === "header-prev") {
730805
731036
  this.prevHeaderPanel();
730806
731037
  return;
@@ -730820,8 +731051,11 @@ var init_status_bar = __esm({
730820
731051
  }
730821
731052
  return;
730822
731053
  }
731054
+ if (cmd.startsWith("view:")) {
731055
+ this.switchToView(cmd.slice("view:".length));
731056
+ return;
731057
+ }
730823
731058
  setPressedButton(cmd);
730824
- setHoveredButton(null);
730825
731059
  this.renderHeaderButtons();
730826
731060
  if (this._headerButtonHandler) this._headerButtonHandler(cmd);
730827
731061
  setTimeout(() => {
@@ -730832,7 +731066,6 @@ var init_status_bar = __esm({
730832
731066
  }
730833
731067
  if (type === "release") {
730834
731068
  setPressedButton(null);
730835
- setHoveredButton(null);
730836
731069
  this.renderHeaderButtons();
730837
731070
  return;
730838
731071
  }
@@ -731205,7 +731438,7 @@ var init_status_bar = __esm({
731205
731438
  if (view.id === "main" && this._activeViewId === "main") continue;
731206
731439
  const icon = view.status === "running" ? "●" : view.status === "completed" ? "✓" : view.status === "failed" ? "✗" : "○";
731207
731440
  const content = ` ${view.label} ${icon} `;
731208
- const visW = content.length + 2;
731441
+ const visW = terminalCellWidth(content) + 2;
731209
731442
  const endCol = testCol + visW - 1;
731210
731443
  if (col >= testCol && col <= endCol) return view.id;
731211
731444
  testCol = endCol + 2;
@@ -733094,6 +733327,7 @@ ${CONTENT_BG_SEQ}`);
733094
733327
  const oldFooterTop = Math.max(1, rows - this._currentFooterHeight + 1);
733095
733328
  const heightChanged = this.updateFooterHeight(w);
733096
733329
  const pos = this.rowPositions(rows);
733330
+ this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
733097
733331
  if (heightChanged) {
733098
733332
  this.applyScrollRegion();
733099
733333
  this.clearFooterTransitionRows(oldFooterTop, pos.inputStartRow);
@@ -733178,6 +733412,7 @@ ${CONTENT_BG_SEQ}`);
733178
733412
  }
733179
733413
  const w = getTermWidth();
733180
733414
  const pos = this.rowPositions(termRows());
733415
+ this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
733181
733416
  const inputWrap = this.wrapInput(w);
733182
733417
  let buf = "\x1B7\x1B[?7l";
733183
733418
  if (pos.tabBarRow > 0) {
@@ -733249,6 +733484,7 @@ ${CONTENT_BG_SEQ}`);
733249
733484
  const oldFooterTop = Math.max(1, rows - oldFooterHeight + 1);
733250
733485
  const heightChanged = this.updateFooterHeight(w);
733251
733486
  const pos = this.rowPositions(rows);
733487
+ this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
733252
733488
  const inputWrap = this.wrapInput(w);
733253
733489
  if (heightChanged) {
733254
733490
  const heightDelta = this._currentFooterHeight - oldFooterHeight;
@@ -733834,7 +734070,10 @@ function tuiSelect(opts) {
733834
734070
  }
733835
734071
  const hasCrumbs = opts.breadcrumbs && opts.breadcrumbs.length > 0;
733836
734072
  const selectChrome = (hasCrumbs ? 9 : 8) + 1;
733837
- let maxVisible = opts.maxVisible ?? Math.max(3, termRows() - selectChrome);
734073
+ let maxVisible = Math.min(
734074
+ opts.maxVisible ?? Number.POSITIVE_INFINITY,
734075
+ Math.max(3, termRows() - selectChrome)
734076
+ );
733838
734077
  let scrollOffset = 0;
733839
734078
  let lastRenderedLines = 0;
733840
734079
  return new Promise((resolve98) => {
@@ -733857,8 +734096,13 @@ function tuiSelect(opts) {
733857
734096
  stdin.resume();
733858
734097
  enterOverlay();
733859
734098
  overlayWrite(`\x1B[?1049h${tuiBgSeq()}\x1B[2J\x1B[H\x1B[?25l\x1B[?1003h\x1B[?1006h`);
733860
- let listRowOffset = 0;
734099
+ let hitZones = [];
734100
+ let hoveredItemIndex = null;
734101
+ let pointerFocus = false;
733861
734102
  let backBtnHovered = false;
734103
+ const hitZoneAt = (row2, col) => hitZones.find(
734104
+ (zone) => zone.row === row2 && col >= zone.startCol && col <= zone.endCol
734105
+ ) ?? null;
733862
734106
  function clampScroll(displayList) {
733863
734107
  const cursorPos = displayList.indexOf(cursor);
733864
734108
  if (cursorPos < 0) return;
@@ -733872,32 +734116,49 @@ function tuiSelect(opts) {
733872
734116
  }
733873
734117
  const hasBreadcrumbs = opts.breadcrumbs && opts.breadcrumbs.length > 0;
733874
734118
  function render2() {
733875
- const currentRows = termRows();
733876
- if (!opts.maxVisible) {
733877
- maxVisible = Math.max(3, currentRows - selectChrome);
733878
- }
733879
- overlayWrite(`${tuiBgSeq()}\x1B[H\x1B[2J`);
734119
+ const currentRows = process.stdout.rows ?? termRows();
734120
+ const currentCols = process.stdout.columns ?? termCols();
734121
+ maxVisible = Math.min(
734122
+ opts.maxVisible ?? Number.POSITIVE_INFINITY,
734123
+ Math.max(3, currentRows - selectChrome)
734124
+ );
734125
+ overlayWrite(`${tuiBgSeq()}\x1B[?7l\x1B[H\x1B[2J`);
733880
734126
  const lines = [];
734127
+ const nextHitZones = [];
734128
+ const maxLineCells = Math.max(1, currentCols - 1);
734129
+ const pushLine = (value2, target) => {
734130
+ const text3 = truncateTerminalCells(value2, maxLineCells);
734131
+ lines.push(text3);
734132
+ if (!target) return;
734133
+ const span = terminalContentSpan(text3);
734134
+ if (!span) return;
734135
+ nextHitZones.push({
734136
+ ...target,
734137
+ row: lines.length,
734138
+ startCol: span.start,
734139
+ endCol: span.end
734140
+ });
734141
+ };
733881
734142
  const backLabel = hasBreadcrumbs ? "← back" : "← close";
733882
734143
  const backHighlighted = backBtnHovered;
733883
734144
  const backStyle = backHighlighted ? `\x1B[7m\x1B[38;5;245m ${backLabel} \x1B[0m${tuiBgSeq()}` : `${selectColors.dim(` ${backLabel} `)}`;
733884
- lines.push(backStyle);
734145
+ pushLine(backStyle, { kind: "back" });
733885
734146
  if (hasBreadcrumbs) {
733886
734147
  const trail = opts.breadcrumbs.map((b) => selectColors.dim(b)).join(selectColors.dim(" › "));
733887
- lines.push(`
733888
- ${selectColors.cyan("←")} ${trail}`);
734148
+ pushLine("");
734149
+ pushLine(` ${selectColors.cyan("←")} ${trail}`);
733889
734150
  }
733890
734151
  if (currentTitle) {
733891
- if (!hasBreadcrumbs) lines.push("");
733892
- lines.push(` ${selectColors.bold(currentTitle)}`);
734152
+ if (!hasBreadcrumbs) pushLine("");
734153
+ pushLine(` ${selectColors.bold(currentTitle)}`);
733893
734154
  }
733894
734155
  if (filter2) {
733895
734156
  const count = matchSet.size;
733896
- lines.push(` ${selectColors.cyan("/")} ${selectColors.bold(filter2)} ${selectColors.dim(`(${count} match${count !== 1 ? "es" : ""})`)}`);
734157
+ pushLine(` ${selectColors.cyan("/")} ${selectColors.bold(filter2)} ${selectColors.dim(`(${count} match${count !== 1 ? "es" : ""})`)}`);
733897
734158
  } else {
733898
- lines.push(` ${selectColors.dim("Type to filter...")}`);
734159
+ pushLine(` ${selectColors.dim("Type to filter...")}`);
733899
734160
  }
733900
- lines.push("");
734161
+ pushLine("");
733901
734162
  let displayList;
733902
734163
  if (filter2) {
733903
734164
  displayList = [];
@@ -733921,44 +734182,54 @@ function tuiSelect(opts) {
733921
734182
  const visibleStart = scrollOffset;
733922
734183
  const visibleEnd = Math.min(displayList.length, scrollOffset + maxVisible);
733923
734184
  if (visibleStart > 0) {
733924
- lines.push(` ${selectColors.dim(` ▲ ${visibleStart} more`)}`);
734185
+ pushLine(` ${selectColors.dim(` ▲ ${visibleStart} more`)}`);
733925
734186
  }
733926
- listRowOffset = lines.length;
733927
734187
  for (let vi = visibleStart; vi < visibleEnd; vi++) {
733928
734188
  const idx = displayList[vi];
733929
734189
  const item = items[idx];
733930
734190
  if (isSkippable(idx)) {
733931
- lines.push(` ${item.label}`);
734191
+ pushLine(` ${item.label}`);
733932
734192
  continue;
733933
734193
  }
733934
- const focused = idx === cursor;
734194
+ const focused = pointerFocus ? idx === hoveredItemIndex : idx === cursor;
733935
734195
  const isActive = item.key === activeKey;
733936
734196
  if (deleteConfirmIdx === idx) {
733937
734197
  const yesLabel = deleteConfirmSel ? selectColors.bold(selectColors.green("[Yes]")) : selectColors.dim("[Yes]");
733938
734198
  const noLabel = !deleteConfirmSel ? selectColors.bold(selectColors.blue("[No]")) : selectColors.dim("[No]");
733939
- lines.push(` ${ansi3("31", "✕")} ${ansi3("31", stripAnsi4(item.label))} Delete? ${yesLabel} ${noLabel}`);
734199
+ pushLine(
734200
+ ` ${ansi3("31", "✕")} ${ansi3("31", stripAnsi4(item.label))} Delete? ${yesLabel} ${noLabel}`,
734201
+ { kind: "item", itemIndex: idx }
734202
+ );
733940
734203
  } else if (filter2) {
733941
- lines.push(matchRow(item, focused, isActive));
734204
+ pushLine(matchRow(item, focused, isActive), {
734205
+ kind: "item",
734206
+ itemIndex: idx
734207
+ });
733942
734208
  } else {
733943
- lines.push(renderRow(item, focused, isActive));
734209
+ pushLine(renderRow(item, focused, isActive), {
734210
+ kind: "item",
734211
+ itemIndex: idx
734212
+ });
733944
734213
  }
733945
734214
  }
733946
734215
  const remaining = displayList.length - visibleEnd;
733947
734216
  if (remaining > 0) {
733948
- lines.push(` ${selectColors.dim(` ▼ ${remaining} more`)}`);
734217
+ pushLine(` ${selectColors.dim(` ▼ ${remaining} more`)}`);
733949
734218
  }
733950
734219
  if (deleteConfirmIdx >= 0) {
733951
- lines.push(` ${selectColors.dim("←/→ select Enter confirm Esc cancel")}`);
734220
+ pushLine(` ${selectColors.dim("←/→ select Enter confirm Esc cancel")}`);
733952
734221
  } else {
733953
734222
  const actionHint = opts.onAction ? " ←/→/Space toggle" : "";
733954
734223
  const deleteHint = opts.onDelete ? " Del remove" : "";
733955
734224
  const customHint = opts.customKeyHint ?? "";
733956
734225
  const escLabel = filter2 ? "clear filter" : hasBreadcrumbs ? "← back" : "cancel";
733957
- lines.push(` ${selectColors.dim("↑/↓ navigate Enter/Click select" + actionHint + deleteHint + customHint + " Esc " + escLabel + " Type to filter")}`);
734226
+ pushLine(` ${selectColors.dim("↑/↓ navigate Enter/Click select" + actionHint + deleteHint + customHint + " Esc " + escLabel + " Type to filter")}`);
733958
734227
  }
733959
- let output2 = lines.join("\n").replace(/\x1B\[0m/g, `\x1B[0m${tuiBgSeq()}`).replace(/\n/g, `\x1B[K
733960
- ${tuiBgSeq()}`);
733961
- overlayWrite(tuiBgSeq() + output2 + "\x1B[K");
734228
+ const output2 = lines.map(
734229
+ (line, index) => `\x1B[${index + 1};1H${tuiBgSeq()}${line.replace(/\x1B\[0m/g, `\x1B[0m${tuiBgSeq()}`)}\x1B[K`
734230
+ ).join("");
734231
+ overlayWrite(`${output2}\x1B[?7h`);
734232
+ hitZones = nextHitZones;
733962
734233
  lastRenderedLines = lines.length;
733963
734234
  }
733964
734235
  let externalCleanup = null;
@@ -733969,7 +734240,7 @@ ${tuiBgSeq()}`);
733969
734240
  }
733970
734241
  stdin.removeListener("data", onData);
733971
734242
  process.stdout.removeListener("resize", onResize);
733972
- overlayWrite("\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?1049l\x1B[?25h");
734243
+ overlayWrite("\x1B[?7h\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?1049l\x1B[?25h");
733973
734244
  leaveOverlay();
733974
734245
  if (typeof stdin.setRawMode === "function") {
733975
734246
  stdin.setRawMode(hadRawMode ?? false);
@@ -733992,6 +734263,48 @@ ${tuiBgSeq()}`);
733992
734263
  currentTitle = title;
733993
734264
  render2();
733994
734265
  };
734266
+ const actionHelpers = () => ({
734267
+ done: () => render2(),
734268
+ resolve: (result) => {
734269
+ cleanup();
734270
+ resolve98(result);
734271
+ },
734272
+ getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
734273
+ render: () => render2(),
734274
+ updateItem
734275
+ });
734276
+ function activateItem(itemIndex) {
734277
+ if (itemIndex < 0 || itemIndex >= items.length || isSkippable(itemIndex) || !matchSet.has(itemIndex)) {
734278
+ return;
734279
+ }
734280
+ cursor = itemIndex;
734281
+ if (opts.onEnter && opts.onEnter(items[itemIndex], actionHelpers())) {
734282
+ return;
734283
+ }
734284
+ cleanup();
734285
+ resolve98({
734286
+ confirmed: true,
734287
+ key: items[itemIndex].key,
734288
+ index: itemIndex
734289
+ });
734290
+ }
734291
+ function activateBack() {
734292
+ if (filter2) {
734293
+ filter2 = "";
734294
+ updateFilter();
734295
+ const valid = findSelectable(cursor, 1);
734296
+ if (valid >= 0) cursor = valid;
734297
+ scrollOffset = 0;
734298
+ hoveredItemIndex = null;
734299
+ render2();
734300
+ } else if (hasBreadcrumbs) {
734301
+ cleanup();
734302
+ resolve98({ confirmed: false, key: "__back__", index: cursor });
734303
+ } else {
734304
+ cleanup();
734305
+ resolve98({ confirmed: false, key: null, index: cursor });
734306
+ }
734307
+ }
733995
734308
  function onData(chunk) {
733996
734309
  let seq = chunk.toString("utf8");
733997
734310
  const mouseRe = /\x1B\[<(\d+);(\d+);(\d+)([Mm])/g;
@@ -734003,106 +734316,52 @@ ${tuiBgSeq()}`);
734003
734316
  const mCol = parseInt(mouseM[2]);
734004
734317
  const mRow = parseInt(mouseM[3]);
734005
734318
  const suffix = mouseM[4];
734006
- if (btn === 0 && suffix === "M" && mRow === 1 && mCol <= 9) {
734007
- if (filter2) {
734008
- filter2 = "";
734009
- updateFilter();
734010
- const valid = findSelectable(cursor, 1);
734011
- if (valid >= 0) cursor = valid;
734012
- scrollOffset = 0;
734013
- render2();
734014
- } else if (hasBreadcrumbs) {
734015
- cleanup();
734016
- resolve98({ confirmed: false, key: "__back__", index: cursor });
734017
- } else {
734018
- cleanup();
734019
- resolve98({ confirmed: false, key: null, index: cursor });
734020
- }
734021
- return;
734022
- }
734023
- if (btn === 0 && suffix === "M") {
734024
- const listIdx = mRow - listRowOffset - 1;
734025
- if (listIdx >= 0 && listIdx < maxVisible) {
734026
- let displayList;
734027
- if (filter2) {
734028
- displayList = [];
734029
- for (let i2 = 0; i2 < items.length; i2++) {
734030
- if (matchSet.has(i2) || isSkippable(i2)) displayList.push(i2);
734031
- }
734032
- displayList = displayList.filter((idx, pos) => {
734033
- if (!isSkippable(idx)) return true;
734034
- for (let j = pos + 1; j < displayList.length; j++) {
734035
- if (!isSkippable(displayList[j])) return true;
734036
- break;
734037
- }
734038
- return false;
734039
- });
734040
- } else {
734041
- displayList = items.map((_, i2) => i2);
734042
- }
734043
- const vi = scrollOffset + listIdx;
734044
- if (vi < displayList.length) {
734045
- const itemIdx = displayList[vi];
734046
- if (!isSkippable(itemIdx) && matchSet.has(itemIdx)) {
734047
- cursor = itemIdx;
734048
- cleanup();
734049
- resolve98({ confirmed: true, key: items[cursor].key, index: cursor });
734050
- return;
734051
- } else if (!isSkippable(itemIdx)) {
734052
- cursor = itemIdx;
734053
- render2();
734054
- }
734055
- }
734319
+ const zone = hitZoneAt(mRow, mCol);
734320
+ const isPrimaryPress = suffix === "M" && (btn & 32) === 0 && (btn & 64) === 0 && (btn & 3) === 0;
734321
+ const isMotion = suffix === "M" && (btn & 32) !== 0 && (btn & 64) === 0;
734322
+ if (isPrimaryPress) {
734323
+ if (zone?.kind === "back") {
734324
+ activateBack();
734325
+ return;
734056
734326
  }
734057
- }
734058
- if ((btn === 35 || btn === 32 || btn === 67) && suffix === "M" && mRow === 1 && mCol <= 9) {
734059
- if (!backBtnHovered) {
734060
- backBtnHovered = true;
734061
- render2();
734327
+ if (zone?.kind === "item" && zone.itemIndex !== void 0) {
734328
+ pointerFocus = true;
734329
+ backBtnHovered = false;
734330
+ hoveredItemIndex = zone.itemIndex;
734331
+ activateItem(zone.itemIndex);
734332
+ return;
734062
734333
  }
734063
- continue;
734064
- }
734065
- if ((btn === 35 || btn === 32 || btn === 67) && suffix === "M" && backBtnHovered && (mRow !== 1 || mCol > 9)) {
734334
+ const changed = backBtnHovered || hoveredItemIndex !== null;
734335
+ pointerFocus = true;
734066
734336
  backBtnHovered = false;
734067
- render2();
734337
+ hoveredItemIndex = null;
734338
+ if (changed) render2();
734339
+ continue;
734068
734340
  }
734069
- if ((btn === 35 || btn === 32 || btn === 67) && suffix === "M") {
734070
- const listIdx = mRow - listRowOffset - 1;
734071
- if (listIdx >= 0 && listIdx < maxVisible) {
734072
- let displayList;
734073
- if (filter2) {
734074
- displayList = [];
734075
- for (let i2 = 0; i2 < items.length; i2++) {
734076
- if (matchSet.has(i2) || isSkippable(i2)) displayList.push(i2);
734077
- }
734078
- displayList = displayList.filter((idx, pos) => {
734079
- if (!isSkippable(idx)) return true;
734080
- for (let j = pos + 1; j < displayList.length; j++) {
734081
- if (!isSkippable(displayList[j])) return true;
734082
- break;
734083
- }
734084
- return false;
734085
- });
734086
- } else {
734087
- displayList = items.map((_, i2) => i2);
734088
- }
734089
- const vi = scrollOffset + listIdx;
734090
- if (vi < displayList.length) {
734091
- const itemIdx = displayList[vi];
734092
- if (!isSkippable(itemIdx) && itemIdx !== cursor) {
734093
- cursor = itemIdx;
734094
- render2();
734095
- }
734096
- }
734097
- }
734341
+ if (isMotion) {
734342
+ const nextBack = zone?.kind === "back";
734343
+ const nextHovered = zone?.kind === "item" ? zone.itemIndex ?? null : null;
734344
+ const changed = !pointerFocus || backBtnHovered !== nextBack || hoveredItemIndex !== nextHovered;
734345
+ pointerFocus = true;
734346
+ backBtnHovered = nextBack;
734347
+ hoveredItemIndex = nextHovered;
734348
+ if (nextHovered !== null) cursor = nextHovered;
734349
+ if (changed) render2();
734350
+ continue;
734098
734351
  }
734099
734352
  if (btn === 64) {
734353
+ pointerFocus = false;
734354
+ backBtnHovered = false;
734355
+ hoveredItemIndex = null;
734100
734356
  const next = findSelectable(cursor - 1, -1);
734101
734357
  if (next >= 0 && next !== cursor) {
734102
734358
  cursor = next;
734103
734359
  render2();
734104
734360
  }
734105
734361
  } else if (btn === 65) {
734362
+ pointerFocus = false;
734363
+ backBtnHovered = false;
734364
+ hoveredItemIndex = null;
734106
734365
  const next = findSelectable(cursor + 1, 1);
734107
734366
  if (next >= 0 && next !== cursor) {
734108
734367
  cursor = next;
@@ -734112,6 +734371,11 @@ ${tuiBgSeq()}`);
734112
734371
  }
734113
734372
  seq = seq.replace(mouseRe, "");
734114
734373
  if (!seq && mouseProcessed) return;
734374
+ if (seq) {
734375
+ pointerFocus = false;
734376
+ backBtnHovered = false;
734377
+ hoveredItemIndex = null;
734378
+ }
734115
734379
  if (deleteConfirmIdx >= 0) {
734116
734380
  if (seq === "\x1B[D") {
734117
734381
  deleteConfirmSel = true;
@@ -734209,23 +734473,7 @@ ${tuiBgSeq()}`);
734209
734473
  if (opts.onAction(items[cursor], "space")) render2();
734210
734474
  }
734211
734475
  } else if (seq === "\r" || seq === "\n") {
734212
- if (!isSkippable(cursor) && matchSet.has(cursor)) {
734213
- if (opts.onEnter) {
734214
- const consumed = opts.onEnter(items[cursor], {
734215
- done: () => render2(),
734216
- resolve: (result) => {
734217
- cleanup();
734218
- resolve98(result);
734219
- },
734220
- getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
734221
- render: () => render2(),
734222
- updateItem
734223
- });
734224
- if (consumed) return;
734225
- }
734226
- cleanup();
734227
- resolve98({ confirmed: true, key: items[cursor].key, index: cursor });
734228
- }
734476
+ activateItem(cursor);
734229
734477
  } else if (seq === "\x1B" || seq === "\x1B\x1B") {
734230
734478
  if (filter2) {
734231
734479
  filter2 = "";
@@ -734381,6 +734629,7 @@ var init_tui_select = __esm({
734381
734629
  init_overlay_lock();
734382
734630
  init_theme();
734383
734631
  init_layout2();
734632
+ init_terminal_cells();
734384
734633
  isTTY3 = process.stdout.isTTY ?? false;
734385
734634
  MENU_ACTIVE_GREEN_256 = 154;
734386
734635
  selectColors = {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.685",
3
+ "version": "1.0.687",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.685",
9
+ "version": "1.0.687",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.685",
3
+ "version": "1.0.687",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/library.js",