omnius 1.0.685 → 1.0.686

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";
@@ -730515,17 +730725,35 @@ var init_status_bar = __esm({
730515
730725
  }
730516
730726
  return false;
730517
730727
  }
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();
730728
+ rebuildSuggestionHitZones(suggestStartRow, width) {
730729
+ if (suggestStartRow <= 0 || this._suggestions.length === 0) {
730730
+ this._suggestionHitZones = [];
730731
+ return;
730527
730732
  }
730528
- return false;
730733
+ const startCol = 5;
730734
+ this._suggestionHitZones = this._suggestions.flatMap((command, index) => {
730735
+ const endCol = Math.min(
730736
+ width - 1,
730737
+ startCol + terminalCellWidth(command)
730738
+ );
730739
+ return endCol < startCol ? [] : [
730740
+ {
730741
+ row: suggestStartRow + index,
730742
+ startCol,
730743
+ endCol,
730744
+ index
730745
+ }
730746
+ ];
730747
+ });
730748
+ }
730749
+ /** Handle a click only when it lands on the visibly painted command text. */
730750
+ suggestClickAt(row2, col) {
730751
+ const zone = this._suggestionHitZones.find(
730752
+ (candidate) => candidate.row === row2 && col >= candidate.startCol && col <= candidate.endCol
730753
+ );
730754
+ if (!zone || zone.index >= this._suggestions.length) return false;
730755
+ this._suggestIndex = zone.index;
730756
+ return this.suggestAccept();
730529
730757
  }
730530
730758
  /** Update the suggestion list based on current input. Called on every render. */
730531
730759
  _updateSuggestions() {
@@ -730630,11 +730858,11 @@ var init_status_bar = __esm({
730630
730858
  return this._cohereActive;
730631
730859
  }
730632
730860
  // ── 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.
730861
+ // Mouse reporting is required for header buttons, hover, and scroll routing.
730862
+ // Hover-capable reporting means terminals reserve unmodified pointer motion
730863
+ // for the application. Shift-drag remains the native terminal selection path.
730864
+ // Overlay/select UIs may temporarily suspend mouse mode and then call
730865
+ // restoreMouseTracking() on return.
730638
730866
  /** Callback to check if neovim has focus (set by interactive.ts to avoid circular import) */
730639
730867
  _isNeovimFocused = null;
730640
730868
  /** Register neovim focus checker — called from interactive.ts after neovim-mode imports */
@@ -730671,7 +730899,7 @@ var init_status_bar = __esm({
730671
730899
  if (this._isNeovimFocused?.()) return;
730672
730900
  this._mouseTrackingEnabled = true;
730673
730901
  if (process.stdout.isTTY) {
730674
- this._trueStdoutWrite.call(process.stdout, "\x1B[?1000h\x1B[?1006h");
730902
+ this._trueStdoutWrite.call(process.stdout, "\x1B[?1003h\x1B[?1006h");
730675
730903
  }
730676
730904
  }
730677
730905
  /** Disable mouse tracking entirely (overlay transitions + exit). */
@@ -730775,32 +731003,29 @@ var init_status_bar = __esm({
730775
731003
  handlePointerEvent(type, col, row2) {
730776
731004
  if (!this.active) return;
730777
731005
  const w = termCols();
731006
+ if (type === "drag") {
731007
+ this.setHeaderHoveredAction(
731008
+ this.hitTestCurrentHeaderAction(row2, col, w)
731009
+ );
731010
+ }
730778
731011
  if (type === "press" && row2 >= this.scrollRegionTop) {
730779
731012
  if (this.handleContentBlockClick(row2, col)) return;
730780
731013
  }
730781
731014
  if (type === "press" && this._suggestions.length > 0) {
730782
- if (this.suggestClickAt(row2)) return;
731015
+ if (this.suggestClickAt(row2, col)) return;
730783
731016
  }
730784
731017
  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
731018
  if (type === "press" && this._updateLatest) {
730795
- const hdrRow2 = layout().headerContent;
731019
+ const hdrRow = layout().headerContent;
730796
731020
  const verZone = this._verClickZone;
730797
- if (row2 === hdrRow2 && verZone && col >= verZone.start && col <= verZone.end) {
731021
+ if (row2 === hdrRow && verZone && col >= verZone.start && col <= verZone.end) {
730798
731022
  if (this._headerButtonHandler) this._headerButtonHandler("/update");
730799
731023
  return;
730800
731024
  }
730801
731025
  }
730802
731026
  const cmd = this.hitTestCurrentHeaderAction(row2, col, w);
730803
731027
  if (type === "press" && cmd) {
731028
+ this.setHeaderHoveredAction(cmd);
730804
731029
  if (cmd === "header-prev") {
730805
731030
  this.prevHeaderPanel();
730806
731031
  return;
@@ -730820,8 +731045,11 @@ var init_status_bar = __esm({
730820
731045
  }
730821
731046
  return;
730822
731047
  }
731048
+ if (cmd.startsWith("view:")) {
731049
+ this.switchToView(cmd.slice("view:".length));
731050
+ return;
731051
+ }
730823
731052
  setPressedButton(cmd);
730824
- setHoveredButton(null);
730825
731053
  this.renderHeaderButtons();
730826
731054
  if (this._headerButtonHandler) this._headerButtonHandler(cmd);
730827
731055
  setTimeout(() => {
@@ -730832,7 +731060,6 @@ var init_status_bar = __esm({
730832
731060
  }
730833
731061
  if (type === "release") {
730834
731062
  setPressedButton(null);
730835
- setHoveredButton(null);
730836
731063
  this.renderHeaderButtons();
730837
731064
  return;
730838
731065
  }
@@ -731205,7 +731432,7 @@ var init_status_bar = __esm({
731205
731432
  if (view.id === "main" && this._activeViewId === "main") continue;
731206
731433
  const icon = view.status === "running" ? "●" : view.status === "completed" ? "✓" : view.status === "failed" ? "✗" : "○";
731207
731434
  const content = ` ${view.label} ${icon} `;
731208
- const visW = content.length + 2;
731435
+ const visW = terminalCellWidth(content) + 2;
731209
731436
  const endCol = testCol + visW - 1;
731210
731437
  if (col >= testCol && col <= endCol) return view.id;
731211
731438
  testCol = endCol + 2;
@@ -733094,6 +733321,7 @@ ${CONTENT_BG_SEQ}`);
733094
733321
  const oldFooterTop = Math.max(1, rows - this._currentFooterHeight + 1);
733095
733322
  const heightChanged = this.updateFooterHeight(w);
733096
733323
  const pos = this.rowPositions(rows);
733324
+ this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
733097
733325
  if (heightChanged) {
733098
733326
  this.applyScrollRegion();
733099
733327
  this.clearFooterTransitionRows(oldFooterTop, pos.inputStartRow);
@@ -733178,6 +733406,7 @@ ${CONTENT_BG_SEQ}`);
733178
733406
  }
733179
733407
  const w = getTermWidth();
733180
733408
  const pos = this.rowPositions(termRows());
733409
+ this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
733181
733410
  const inputWrap = this.wrapInput(w);
733182
733411
  let buf = "\x1B7\x1B[?7l";
733183
733412
  if (pos.tabBarRow > 0) {
@@ -733249,6 +733478,7 @@ ${CONTENT_BG_SEQ}`);
733249
733478
  const oldFooterTop = Math.max(1, rows - oldFooterHeight + 1);
733250
733479
  const heightChanged = this.updateFooterHeight(w);
733251
733480
  const pos = this.rowPositions(rows);
733481
+ this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
733252
733482
  const inputWrap = this.wrapInput(w);
733253
733483
  if (heightChanged) {
733254
733484
  const heightDelta = this._currentFooterHeight - oldFooterHeight;
@@ -733834,7 +734064,10 @@ function tuiSelect(opts) {
733834
734064
  }
733835
734065
  const hasCrumbs = opts.breadcrumbs && opts.breadcrumbs.length > 0;
733836
734066
  const selectChrome = (hasCrumbs ? 9 : 8) + 1;
733837
- let maxVisible = opts.maxVisible ?? Math.max(3, termRows() - selectChrome);
734067
+ let maxVisible = Math.min(
734068
+ opts.maxVisible ?? Number.POSITIVE_INFINITY,
734069
+ Math.max(3, termRows() - selectChrome)
734070
+ );
733838
734071
  let scrollOffset = 0;
733839
734072
  let lastRenderedLines = 0;
733840
734073
  return new Promise((resolve98) => {
@@ -733857,8 +734090,13 @@ function tuiSelect(opts) {
733857
734090
  stdin.resume();
733858
734091
  enterOverlay();
733859
734092
  overlayWrite(`\x1B[?1049h${tuiBgSeq()}\x1B[2J\x1B[H\x1B[?25l\x1B[?1003h\x1B[?1006h`);
733860
- let listRowOffset = 0;
734093
+ let hitZones = [];
734094
+ let hoveredItemIndex = null;
734095
+ let pointerFocus = false;
733861
734096
  let backBtnHovered = false;
734097
+ const hitZoneAt = (row2, col) => hitZones.find(
734098
+ (zone) => zone.row === row2 && col >= zone.startCol && col <= zone.endCol
734099
+ ) ?? null;
733862
734100
  function clampScroll(displayList) {
733863
734101
  const cursorPos = displayList.indexOf(cursor);
733864
734102
  if (cursorPos < 0) return;
@@ -733872,32 +734110,49 @@ function tuiSelect(opts) {
733872
734110
  }
733873
734111
  const hasBreadcrumbs = opts.breadcrumbs && opts.breadcrumbs.length > 0;
733874
734112
  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`);
734113
+ const currentRows = process.stdout.rows ?? termRows();
734114
+ const currentCols = process.stdout.columns ?? termCols();
734115
+ maxVisible = Math.min(
734116
+ opts.maxVisible ?? Number.POSITIVE_INFINITY,
734117
+ Math.max(3, currentRows - selectChrome)
734118
+ );
734119
+ overlayWrite(`${tuiBgSeq()}\x1B[?7l\x1B[H\x1B[2J`);
733880
734120
  const lines = [];
734121
+ const nextHitZones = [];
734122
+ const maxLineCells = Math.max(1, currentCols - 1);
734123
+ const pushLine = (value2, target) => {
734124
+ const text3 = truncateTerminalCells(value2, maxLineCells);
734125
+ lines.push(text3);
734126
+ if (!target) return;
734127
+ const span = terminalContentSpan(text3);
734128
+ if (!span) return;
734129
+ nextHitZones.push({
734130
+ ...target,
734131
+ row: lines.length,
734132
+ startCol: span.start,
734133
+ endCol: span.end
734134
+ });
734135
+ };
733881
734136
  const backLabel = hasBreadcrumbs ? "← back" : "← close";
733882
734137
  const backHighlighted = backBtnHovered;
733883
734138
  const backStyle = backHighlighted ? `\x1B[7m\x1B[38;5;245m ${backLabel} \x1B[0m${tuiBgSeq()}` : `${selectColors.dim(` ${backLabel} `)}`;
733884
- lines.push(backStyle);
734139
+ pushLine(backStyle, { kind: "back" });
733885
734140
  if (hasBreadcrumbs) {
733886
734141
  const trail = opts.breadcrumbs.map((b) => selectColors.dim(b)).join(selectColors.dim(" › "));
733887
- lines.push(`
733888
- ${selectColors.cyan("←")} ${trail}`);
734142
+ pushLine("");
734143
+ pushLine(` ${selectColors.cyan("←")} ${trail}`);
733889
734144
  }
733890
734145
  if (currentTitle) {
733891
- if (!hasBreadcrumbs) lines.push("");
733892
- lines.push(` ${selectColors.bold(currentTitle)}`);
734146
+ if (!hasBreadcrumbs) pushLine("");
734147
+ pushLine(` ${selectColors.bold(currentTitle)}`);
733893
734148
  }
733894
734149
  if (filter2) {
733895
734150
  const count = matchSet.size;
733896
- lines.push(` ${selectColors.cyan("/")} ${selectColors.bold(filter2)} ${selectColors.dim(`(${count} match${count !== 1 ? "es" : ""})`)}`);
734151
+ pushLine(` ${selectColors.cyan("/")} ${selectColors.bold(filter2)} ${selectColors.dim(`(${count} match${count !== 1 ? "es" : ""})`)}`);
733897
734152
  } else {
733898
- lines.push(` ${selectColors.dim("Type to filter...")}`);
734153
+ pushLine(` ${selectColors.dim("Type to filter...")}`);
733899
734154
  }
733900
- lines.push("");
734155
+ pushLine("");
733901
734156
  let displayList;
733902
734157
  if (filter2) {
733903
734158
  displayList = [];
@@ -733921,44 +734176,54 @@ function tuiSelect(opts) {
733921
734176
  const visibleStart = scrollOffset;
733922
734177
  const visibleEnd = Math.min(displayList.length, scrollOffset + maxVisible);
733923
734178
  if (visibleStart > 0) {
733924
- lines.push(` ${selectColors.dim(` ▲ ${visibleStart} more`)}`);
734179
+ pushLine(` ${selectColors.dim(` ▲ ${visibleStart} more`)}`);
733925
734180
  }
733926
- listRowOffset = lines.length;
733927
734181
  for (let vi = visibleStart; vi < visibleEnd; vi++) {
733928
734182
  const idx = displayList[vi];
733929
734183
  const item = items[idx];
733930
734184
  if (isSkippable(idx)) {
733931
- lines.push(` ${item.label}`);
734185
+ pushLine(` ${item.label}`);
733932
734186
  continue;
733933
734187
  }
733934
- const focused = idx === cursor;
734188
+ const focused = pointerFocus ? idx === hoveredItemIndex : idx === cursor;
733935
734189
  const isActive = item.key === activeKey;
733936
734190
  if (deleteConfirmIdx === idx) {
733937
734191
  const yesLabel = deleteConfirmSel ? selectColors.bold(selectColors.green("[Yes]")) : selectColors.dim("[Yes]");
733938
734192
  const noLabel = !deleteConfirmSel ? selectColors.bold(selectColors.blue("[No]")) : selectColors.dim("[No]");
733939
- lines.push(` ${ansi3("31", "✕")} ${ansi3("31", stripAnsi4(item.label))} Delete? ${yesLabel} ${noLabel}`);
734193
+ pushLine(
734194
+ ` ${ansi3("31", "✕")} ${ansi3("31", stripAnsi4(item.label))} Delete? ${yesLabel} ${noLabel}`,
734195
+ { kind: "item", itemIndex: idx }
734196
+ );
733940
734197
  } else if (filter2) {
733941
- lines.push(matchRow(item, focused, isActive));
734198
+ pushLine(matchRow(item, focused, isActive), {
734199
+ kind: "item",
734200
+ itemIndex: idx
734201
+ });
733942
734202
  } else {
733943
- lines.push(renderRow(item, focused, isActive));
734203
+ pushLine(renderRow(item, focused, isActive), {
734204
+ kind: "item",
734205
+ itemIndex: idx
734206
+ });
733944
734207
  }
733945
734208
  }
733946
734209
  const remaining = displayList.length - visibleEnd;
733947
734210
  if (remaining > 0) {
733948
- lines.push(` ${selectColors.dim(` ▼ ${remaining} more`)}`);
734211
+ pushLine(` ${selectColors.dim(` ▼ ${remaining} more`)}`);
733949
734212
  }
733950
734213
  if (deleteConfirmIdx >= 0) {
733951
- lines.push(` ${selectColors.dim("←/→ select Enter confirm Esc cancel")}`);
734214
+ pushLine(` ${selectColors.dim("←/→ select Enter confirm Esc cancel")}`);
733952
734215
  } else {
733953
734216
  const actionHint = opts.onAction ? " ←/→/Space toggle" : "";
733954
734217
  const deleteHint = opts.onDelete ? " Del remove" : "";
733955
734218
  const customHint = opts.customKeyHint ?? "";
733956
734219
  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")}`);
734220
+ pushLine(` ${selectColors.dim("↑/↓ navigate Enter/Click select" + actionHint + deleteHint + customHint + " Esc " + escLabel + " Type to filter")}`);
733958
734221
  }
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");
734222
+ const output2 = lines.map(
734223
+ (line, index) => `\x1B[${index + 1};1H${tuiBgSeq()}${line.replace(/\x1B\[0m/g, `\x1B[0m${tuiBgSeq()}`)}\x1B[K`
734224
+ ).join("");
734225
+ overlayWrite(`${output2}\x1B[?7h`);
734226
+ hitZones = nextHitZones;
733962
734227
  lastRenderedLines = lines.length;
733963
734228
  }
733964
734229
  let externalCleanup = null;
@@ -733969,7 +734234,7 @@ ${tuiBgSeq()}`);
733969
734234
  }
733970
734235
  stdin.removeListener("data", onData);
733971
734236
  process.stdout.removeListener("resize", onResize);
733972
- overlayWrite("\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?1049l\x1B[?25h");
734237
+ overlayWrite("\x1B[?7h\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?1049l\x1B[?25h");
733973
734238
  leaveOverlay();
733974
734239
  if (typeof stdin.setRawMode === "function") {
733975
734240
  stdin.setRawMode(hadRawMode ?? false);
@@ -733992,6 +734257,48 @@ ${tuiBgSeq()}`);
733992
734257
  currentTitle = title;
733993
734258
  render2();
733994
734259
  };
734260
+ const actionHelpers = () => ({
734261
+ done: () => render2(),
734262
+ resolve: (result) => {
734263
+ cleanup();
734264
+ resolve98(result);
734265
+ },
734266
+ getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
734267
+ render: () => render2(),
734268
+ updateItem
734269
+ });
734270
+ function activateItem(itemIndex) {
734271
+ if (itemIndex < 0 || itemIndex >= items.length || isSkippable(itemIndex) || !matchSet.has(itemIndex)) {
734272
+ return;
734273
+ }
734274
+ cursor = itemIndex;
734275
+ if (opts.onEnter && opts.onEnter(items[itemIndex], actionHelpers())) {
734276
+ return;
734277
+ }
734278
+ cleanup();
734279
+ resolve98({
734280
+ confirmed: true,
734281
+ key: items[itemIndex].key,
734282
+ index: itemIndex
734283
+ });
734284
+ }
734285
+ function activateBack() {
734286
+ if (filter2) {
734287
+ filter2 = "";
734288
+ updateFilter();
734289
+ const valid = findSelectable(cursor, 1);
734290
+ if (valid >= 0) cursor = valid;
734291
+ scrollOffset = 0;
734292
+ hoveredItemIndex = null;
734293
+ render2();
734294
+ } else if (hasBreadcrumbs) {
734295
+ cleanup();
734296
+ resolve98({ confirmed: false, key: "__back__", index: cursor });
734297
+ } else {
734298
+ cleanup();
734299
+ resolve98({ confirmed: false, key: null, index: cursor });
734300
+ }
734301
+ }
733995
734302
  function onData(chunk) {
733996
734303
  let seq = chunk.toString("utf8");
733997
734304
  const mouseRe = /\x1B\[<(\d+);(\d+);(\d+)([Mm])/g;
@@ -734003,106 +734310,52 @@ ${tuiBgSeq()}`);
734003
734310
  const mCol = parseInt(mouseM[2]);
734004
734311
  const mRow = parseInt(mouseM[3]);
734005
734312
  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
- }
734313
+ const zone = hitZoneAt(mRow, mCol);
734314
+ const isPrimaryPress = suffix === "M" && (btn & 32) === 0 && (btn & 64) === 0 && (btn & 3) === 0;
734315
+ const isMotion = suffix === "M" && (btn & 32) !== 0 && (btn & 64) === 0;
734316
+ if (isPrimaryPress) {
734317
+ if (zone?.kind === "back") {
734318
+ activateBack();
734319
+ return;
734056
734320
  }
734057
- }
734058
- if ((btn === 35 || btn === 32 || btn === 67) && suffix === "M" && mRow === 1 && mCol <= 9) {
734059
- if (!backBtnHovered) {
734060
- backBtnHovered = true;
734061
- render2();
734321
+ if (zone?.kind === "item" && zone.itemIndex !== void 0) {
734322
+ pointerFocus = true;
734323
+ backBtnHovered = false;
734324
+ hoveredItemIndex = zone.itemIndex;
734325
+ activateItem(zone.itemIndex);
734326
+ return;
734062
734327
  }
734063
- continue;
734064
- }
734065
- if ((btn === 35 || btn === 32 || btn === 67) && suffix === "M" && backBtnHovered && (mRow !== 1 || mCol > 9)) {
734328
+ const changed = backBtnHovered || hoveredItemIndex !== null;
734329
+ pointerFocus = true;
734066
734330
  backBtnHovered = false;
734067
- render2();
734331
+ hoveredItemIndex = null;
734332
+ if (changed) render2();
734333
+ continue;
734068
734334
  }
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
- }
734335
+ if (isMotion) {
734336
+ const nextBack = zone?.kind === "back";
734337
+ const nextHovered = zone?.kind === "item" ? zone.itemIndex ?? null : null;
734338
+ const changed = !pointerFocus || backBtnHovered !== nextBack || hoveredItemIndex !== nextHovered;
734339
+ pointerFocus = true;
734340
+ backBtnHovered = nextBack;
734341
+ hoveredItemIndex = nextHovered;
734342
+ if (nextHovered !== null) cursor = nextHovered;
734343
+ if (changed) render2();
734344
+ continue;
734098
734345
  }
734099
734346
  if (btn === 64) {
734347
+ pointerFocus = false;
734348
+ backBtnHovered = false;
734349
+ hoveredItemIndex = null;
734100
734350
  const next = findSelectable(cursor - 1, -1);
734101
734351
  if (next >= 0 && next !== cursor) {
734102
734352
  cursor = next;
734103
734353
  render2();
734104
734354
  }
734105
734355
  } else if (btn === 65) {
734356
+ pointerFocus = false;
734357
+ backBtnHovered = false;
734358
+ hoveredItemIndex = null;
734106
734359
  const next = findSelectable(cursor + 1, 1);
734107
734360
  if (next >= 0 && next !== cursor) {
734108
734361
  cursor = next;
@@ -734112,6 +734365,11 @@ ${tuiBgSeq()}`);
734112
734365
  }
734113
734366
  seq = seq.replace(mouseRe, "");
734114
734367
  if (!seq && mouseProcessed) return;
734368
+ if (seq) {
734369
+ pointerFocus = false;
734370
+ backBtnHovered = false;
734371
+ hoveredItemIndex = null;
734372
+ }
734115
734373
  if (deleteConfirmIdx >= 0) {
734116
734374
  if (seq === "\x1B[D") {
734117
734375
  deleteConfirmSel = true;
@@ -734209,23 +734467,7 @@ ${tuiBgSeq()}`);
734209
734467
  if (opts.onAction(items[cursor], "space")) render2();
734210
734468
  }
734211
734469
  } 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
- }
734470
+ activateItem(cursor);
734229
734471
  } else if (seq === "\x1B" || seq === "\x1B\x1B") {
734230
734472
  if (filter2) {
734231
734473
  filter2 = "";
@@ -734381,6 +734623,7 @@ var init_tui_select = __esm({
734381
734623
  init_overlay_lock();
734382
734624
  init_theme();
734383
734625
  init_layout2();
734626
+ init_terminal_cells();
734384
734627
  isTTY3 = process.stdout.isTTY ?? false;
734385
734628
  MENU_ACTIVE_GREEN_256 = 154;
734386
734629
  selectColors = {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.685",
3
+ "version": "1.0.686",
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.686",
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.686",
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",