omnius 1.0.871 → 1.0.873

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.
@@ -2,18 +2,18 @@
2
2
  import { createWriteStream } from "node:fs";
3
3
  import { createInterface } from "node:readline";
4
4
  import { PassThrough } from "node:stream";
5
- import { CliRenderEvents as CliRenderEvents7, NativeSession, RGBA as RGBA3, createCliRenderer } from "@opentui/core";
5
+ import { CliRenderEvents as CliRenderEvents9, NativeSession, RGBA as RGBA3, createCliRenderer } from "@opentui/core";
6
6
 
7
7
  // packages/cli/src/tui/native/components/frontend.ts
8
8
  import {
9
- BoxRenderable as BoxRenderable8,
10
- CliRenderEvents as CliRenderEvents5,
9
+ BoxRenderable as BoxRenderable10,
10
+ CliRenderEvents as CliRenderEvents7,
11
11
  EmbeddedTerminalRenderable as EmbeddedTerminalRenderable2,
12
- ScrollBoxRenderable as ScrollBoxRenderable5,
12
+ ScrollBoxRenderable as ScrollBoxRenderable7,
13
13
  SyntaxStyle as SyntaxStyle2,
14
14
  TextareaRenderable as TextareaRenderable2,
15
- TextRenderable as TextRenderable7,
16
- TextAttributes as TextAttributes8,
15
+ TextRenderable as TextRenderable9,
16
+ TextAttributes as TextAttributes10,
17
17
  createClipboard,
18
18
  createHostClipboard,
19
19
  createRendererClipboardAdapter
@@ -35,6 +35,16 @@ function sanitizeNativeInterfaceState(value) {
35
35
  Object.defineProperty(views, key, { value: { top: offset(entry.top), live: entry.live === true, disclosures }, enumerable: true, configurable: true, writable: true });
36
36
  }
37
37
  const layout = record(value.layout) ? value.layout : {}, instruments = record(value.instruments) ? value.instruments : {}, tabs = record(value.tabs) ? value.tabs : {};
38
+ const taskNotes = record(instruments.taskNotes) ? instruments.taskNotes : void 0;
39
+ const workQueue = record(instruments.workQueue) ? instruments.workQueue : void 0;
40
+ const workDisclosures = {};
41
+ if (workQueue && record(workQueue.disclosures)) for (const [id, open] of Object.entries(workQueue.disclosures).slice(0, 2048)) {
42
+ if (id.length <= 1024 && typeof open === "boolean") Object.defineProperty(workDisclosures, id, { value: open, enumerable: true, configurable: true, writable: true });
43
+ }
44
+ const taskDisclosures = {};
45
+ if (taskNotes && record(taskNotes.disclosures)) for (const [id, open] of Object.entries(taskNotes.disclosures).slice(0, 2048)) {
46
+ if (id.length <= 1024 && typeof open === "boolean") Object.defineProperty(taskDisclosures, id, { value: open, enumerable: true, configurable: true, writable: true });
47
+ }
38
48
  return {
39
49
  version: 1,
40
50
  ...typeof value.sessionId === "string" ? { sessionId: value.sessionId.slice(0, 1024) } : {},
@@ -55,7 +65,9 @@ function sanitizeNativeInterfaceState(value) {
55
65
  context: instruments.context === true,
56
66
  devices: instruments.devices === true,
57
67
  scrollTop: offset(instruments.scrollTop),
58
- deviceScrollTop: offset(instruments.deviceScrollTop)
68
+ deviceScrollTop: offset(instruments.deviceScrollTop),
69
+ ...taskNotes ? { taskNotes: { open: taskNotes.open !== false, tasks: taskNotes.tasks !== false, notes: taskNotes.notes !== false, layers: taskNotes.layers !== false, disclosures: taskDisclosures } } : {},
70
+ ...workQueue ? { workQueue: { open: workQueue.open !== false, history: workQueue.history === true, disclosures: workDisclosures } } : {}
59
71
  },
60
72
  tabs: { sessions: offset(tabs.sessions), agents: offset(tabs.agents) }
61
73
  };
@@ -185,14 +197,14 @@ function installDefaultSelectionContrast(renderer2) {
185
197
  const foreground2 = RGBA.defaultForeground();
186
198
  const background2 = RGBA.defaultBackground();
187
199
  const paintSelection = (buffer) => {
188
- const lines = buffer.getSpanLines();
200
+ const lines2 = buffer.getSpanLines();
189
201
  buffer.withBuffers((cells) => {
190
- for (let y = 0; y < lines.length; y++) {
202
+ for (let y = 0; y < lines2.length; y++) {
191
203
  let x = 0;
192
- for (const span of lines[y].spans) {
204
+ for (const span of lines2[y].spans) {
193
205
  if (span.fg.intent === "default" && span.bg.intent === "default" && !(span.attributes & TextAttributes.INVERSE) && span.fg.equals(background2) && span.bg.equals(foreground2)) {
194
- for (let column = x; column < x + span.width; column++)
195
- cells.attributes[y * cells.width + column] |= TextAttributes.INVERSE;
206
+ for (let column3 = x; column3 < x + span.width; column3++)
207
+ cells.attributes[y * cells.width + column3] |= TextAttributes.INVERSE;
196
208
  }
197
209
  x += span.width;
198
210
  }
@@ -296,7 +308,7 @@ var NativeMediaPlayback = class {
296
308
  });
297
309
  if (spec.kind === "video") {
298
310
  const bytes = width * height * 4;
299
- let pending = Buffer.alloc(0), frames = 0;
311
+ let pending = Buffer.alloc(0), frames2 = 0;
300
312
  const offset2 = this.positionSec;
301
313
  for await (const chunk of child.stdout) {
302
314
  if (epoch !== this.epoch) break;
@@ -304,8 +316,8 @@ var NativeMediaPlayback = class {
304
316
  while (pending.length >= bytes && epoch === this.epoch) {
305
317
  frame(pending.subarray(0, bytes), width, height);
306
318
  pending = pending.subarray(bytes);
307
- frames++;
308
- if (!withAudio) this.positionSec = offset2 + frames / 8;
319
+ frames2++;
320
+ if (!withAudio) this.positionSec = offset2 + frames2 / 8;
309
321
  this.changed();
310
322
  }
311
323
  }
@@ -396,8 +408,8 @@ function mediaPreviewHeight(width, imageWidth, imageHeight, cellAspectRatio = 2)
396
408
  function audioWaveform(samples, width) {
397
409
  const cells = Math.max(1, Math.min(240, Math.floor(width)));
398
410
  const glyphs = "▁▂▃▄▅▆▇█";
399
- return Array.from({ length: cells }, (_, column) => {
400
- const begin = Math.floor(column * samples.length / cells), end = Math.max(begin + 1, Math.floor((column + 1) * samples.length / cells));
411
+ return Array.from({ length: cells }, (_, column3) => {
412
+ const begin = Math.floor(column3 * samples.length / cells), end = Math.max(begin + 1, Math.floor((column3 + 1) * samples.length / cells));
401
413
  let peak = 0;
402
414
  for (let index = begin; index < end && index < samples.length; index++) if (Number.isFinite(samples[index])) peak = Math.max(peak, Math.abs(samples[index]));
403
415
  return glyphs[Math.min(7, Math.floor(Math.min(1, peak) * 7))];
@@ -465,10 +477,10 @@ var NativeMediaView = class extends BoxRenderable {
465
477
  pausePlayback() {
466
478
  this.playback.pause();
467
479
  }
468
- control(action, label, operation) {
480
+ control(action, label2, operation) {
469
481
  const control = new TextRenderable(this.renderer, {
470
482
  id: `media-control:${this.mediaId}:${action}`,
471
- content: label,
483
+ content: label2,
472
484
  fg: this.colors.foreground,
473
485
  selectable: false,
474
486
  onMouseDown: (event) => {
@@ -615,14 +627,14 @@ var NativeMediaView = class extends BoxRenderable {
615
627
  active = ancestor.visible;
616
628
  ancestor = ancestor.parent;
617
629
  }
618
- const visible = active && this.y + this.height > viewport.y && this.y < viewport.y + viewport.height;
619
- if (!visible && this.playback.playing) this.playback.pause();
620
- if (!visible && this.probeController && !this.samples) {
630
+ const visible2 = active && this.y + this.height > viewport.y && this.y < viewport.y + viewport.height;
631
+ if (!visible2 && this.playback.playing) this.playback.pause();
632
+ if (!visible2 && this.probeController && !this.samples) {
621
633
  this.probeController.abort();
622
634
  this.probeController = void 0;
623
635
  this.needsProbe = true;
624
636
  }
625
- if (visible) this.startProbe();
637
+ if (visible2) this.startProbe();
626
638
  this.refreshGeometry();
627
639
  }
628
640
  refreshGeometry() {
@@ -642,8 +654,8 @@ var NativeMediaView = class extends BoxRenderable {
642
654
  if (this.isDestroyed) return;
643
655
  const text = `${this.hovered ? "Open ↗ · " : ""}${this.currentStatus}`;
644
656
  if (this.status.plainText !== text) this.status.content = text;
645
- const label = this.playback?.playing ? "Pause" : this.playback?.positionSec ? "Resume" : "Play";
646
- if (this.playControl.plainText !== label) this.playControl.content = label;
657
+ const label2 = this.playback?.playing ? "Pause" : this.playback?.positionSec ? "Resume" : "Play";
658
+ if (this.playControl.plainText !== label2) this.playControl.content = label2;
647
659
  if (this.waveformText) {
648
660
  const cursor = this.duration > 0 ? Math.min(this.waveformText.length - 1, Math.floor(this.playback.positionSec / this.duration * this.waveformText.length)) : 0;
649
661
  const waveform = this.playback.positionSec > 0 ? this.waveformText.slice(0, cursor) + "│" + this.waveformText.slice(cursor + 1) : this.waveformText;
@@ -925,7 +937,7 @@ function nativeProgressText(value, working = false) {
925
937
  if (value === void 0 || !Number.isFinite(value)) return `[············] ${working ? "working" : "pending"}`;
926
938
  const ratio = Math.max(0, Math.min(1, value));
927
939
  const filled = Math.round(ratio * 12);
928
- return `[${"•".repeat(filled)}${"·".repeat(12 - filled)}] ${Math.round(ratio * 100)}%`;
940
+ return `[${"▮".repeat(filled)}${"░".repeat(12 - filled)}] ${Math.round(ratio * 100)}%`;
929
941
  }
930
942
  function nativeControlFocus(control, baseAttributes = 0) {
931
943
  const update = () => {
@@ -1511,10 +1523,10 @@ var NativeSelectRenderable = class extends SelectRenderable {
1511
1523
  this.seekRail(event);
1512
1524
  return;
1513
1525
  }
1514
- const lines = this.showDescription ? 2 : 1;
1515
- const count = Math.max(1, Math.floor(this.height / lines));
1526
+ const lines2 = this.showDescription ? 2 : 1;
1527
+ const count = Math.max(1, Math.floor(this.height / lines2));
1516
1528
  const start = Math.max(0, Math.min(this.getSelectedIndex() - Math.floor(count / 2), this.options.length - count));
1517
- const index = start + Math.floor((event.y - this.y) / lines);
1529
+ const index = start + Math.floor((event.y - this.y) / lines2);
1518
1530
  if (index >= start && index < Math.min(start + count, this.options.length) && !this.disabled(index)) {
1519
1531
  this.setSelectedIndex(index);
1520
1532
  this.onActivate?.();
@@ -1528,7 +1540,7 @@ import { BoxRenderable as BoxRenderable3, CliRenderEvents as CliRenderEvents2, R
1528
1540
  function drawCornerFrame(buffer, panel, colors, progress = 1) {
1529
1541
  const { x, y, width, height } = panel;
1530
1542
  if (width <= 0 || height <= 0) return;
1531
- const draw = (text, column, row) => buffer.drawText(text, column, row, colors.foreground, colors.background, TextAttributes3.DIM);
1543
+ const draw = (text, column3, row) => buffer.drawText(text, column3, row, colors.foreground, colors.background, TextAttributes3.DIM);
1532
1544
  draw(" ".repeat(width), x, y);
1533
1545
  if (height > 1) draw(" ".repeat(width), x, y + height - 1);
1534
1546
  for (let row = 1; row < height - 1; row++) {
@@ -1551,9 +1563,9 @@ function drawCornerFrame(buffer, panel, colors, progress = 1) {
1551
1563
  draw(`└${"─".repeat(horizontal)}`, x, y + height - 1);
1552
1564
  draw(`${"─".repeat(horizontal)}┘`, x + width - horizontal - 1, y + height - 1);
1553
1565
  for (let arm = 1; arm <= vertical; arm++) {
1554
- for (const column of [x, x + width - 1]) {
1555
- draw("│", column, y + arm);
1556
- draw("│", column, y + height - arm - 1);
1566
+ for (const column3 of [x, x + width - 1]) {
1567
+ draw("│", column3, y + arm);
1568
+ draw("│", column3, y + height - arm - 1);
1557
1569
  }
1558
1570
  }
1559
1571
  }
@@ -2043,7 +2055,7 @@ var NativeModalView = class {
2043
2055
  return consume();
2044
2056
  }
2045
2057
  if (key.name === "tab") {
2046
- if (this.spec.deferSelection || this.spec.captureKeys) this.emitAction(key.shift ? "shift-tab" : "tab");
2058
+ if (!this.spec.nativeTabNavigation && (this.spec.deferSelection || this.spec.captureKeys)) this.emitAction(key.shift ? "shift-tab" : "tab");
2047
2059
  else this.nextControl(key.shift ? -1 : 1);
2048
2060
  return consume();
2049
2061
  }
@@ -2195,9 +2207,9 @@ var NativeModalStack = class {
2195
2207
  if (!panel || panel.isDestroyed || !panel.visible) return;
2196
2208
  const { x, y, width, height } = this.active.frame.bounds;
2197
2209
  buffer.withBuffers((cells) => {
2198
- for (let row = 0; row < cells.height; row++) for (let column = 0; column < cells.width; column++) {
2199
- if (column < x || column >= x + width || row < y || row >= y + height)
2200
- cells.attributes[row * cells.width + column] |= TextAttributes4.DIM;
2210
+ for (let row = 0; row < cells.height; row++) for (let column3 = 0; column3 < cells.width; column3++) {
2211
+ if (column3 < x || column3 >= x + width || row < y || row >= y + height)
2212
+ cells.attributes[row * cells.width + column3] |= TextAttributes4.DIM;
2201
2213
  }
2202
2214
  });
2203
2215
  };
@@ -2251,12 +2263,12 @@ var NativeModalStack = class {
2251
2263
 
2252
2264
  // packages/cli/src/tui/native/components/instruments.ts
2253
2265
  import {
2254
- BoxRenderable as BoxRenderable5,
2266
+ BoxRenderable as BoxRenderable7,
2255
2267
  RGBA as RGBA2,
2256
- RenderableEvents as RenderableEvents3,
2257
- ScrollBoxRenderable as ScrollBoxRenderable3,
2258
- TextAttributes as TextAttributes5,
2259
- TextRenderable as TextRenderable4
2268
+ RenderableEvents as RenderableEvents5,
2269
+ ScrollBoxRenderable as ScrollBoxRenderable5,
2270
+ TextAttributes as TextAttributes7,
2271
+ TextRenderable as TextRenderable6
2260
2272
  } from "@opentui/core";
2261
2273
 
2262
2274
  // packages/cli/src/tui/native/components/device-history.ts
@@ -2311,6 +2323,16 @@ function deviceHistoryGraph(samples, field, width) {
2311
2323
  return cells.map((row, y) => labels[y] + row.map((bits, x) => bits ? String.fromCodePoint(10240 + bits) : x % 4 === 0 ? "·" : " ").join("")).join("\n");
2312
2324
  }
2313
2325
 
2326
+ // packages/cli/src/tui/native/components/task-notes.ts
2327
+ import {
2328
+ BoxRenderable as BoxRenderable5,
2329
+ CliRenderEvents as CliRenderEvents3,
2330
+ RenderableEvents as RenderableEvents3,
2331
+ ScrollBoxRenderable as ScrollBoxRenderable3,
2332
+ TextAttributes as TextAttributes5,
2333
+ TextRenderable as TextRenderable4
2334
+ } from "@opentui/core";
2335
+
2314
2336
  // packages/cli/src/tui/terminal-cells.ts
2315
2337
  var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
2316
2338
  var extendedPictographic = /\p{Extended_Pictographic}/u;
@@ -2392,9 +2414,9 @@ function terminalCellWidth(value) {
2392
2414
  var graphemes2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
2393
2415
  function formatSignalDivider(width, geometry = { direction: "top" }) {
2394
2416
  const cells = Math.max(0, Math.floor(width));
2395
- const column = Math.floor(geometry.sidebarColumn ?? -1);
2396
- if (!Number.isFinite(column) || column < 0 || column >= cells) return "─".repeat(cells);
2397
- return "─".repeat(column) + (geometry.direction === "top" ? "┬" : "┴") + "─".repeat(cells - column - 1);
2417
+ const column3 = Math.floor(geometry.sidebarColumn ?? -1);
2418
+ if (!Number.isFinite(column3) || column3 < 0 || column3 >= cells) return "─".repeat(cells);
2419
+ return "─".repeat(column3) + (geometry.direction === "top" ? "┬" : "┴") + "─".repeat(cells - column3 - 1);
2398
2420
  }
2399
2421
  function fitInstrumentText(value, cells, marker = "~") {
2400
2422
  const text = stripTerminalSequences(normalizeTerminalLine(value));
@@ -2411,7 +2433,7 @@ function fitInstrumentText(value, cells, marker = "~") {
2411
2433
  }
2412
2434
  return result + suffix;
2413
2435
  }
2414
- function formatTelemetryRow(label, value, width, reserved = 12) {
2436
+ function formatTelemetryRow(label2, value, width, reserved = 12) {
2415
2437
  const cells = Math.max(0, Math.floor(width));
2416
2438
  if (!cells) return "";
2417
2439
  const reading = stripTerminalSequences(normalizeTerminalLine(value));
@@ -2419,7 +2441,7 @@ function formatTelemetryRow(label, value, width, reserved = 12) {
2419
2441
  if (readingCells >= cells) return fitInstrumentText(reading, cells);
2420
2442
  const field = Math.min(cells, Math.max(readingCells, Math.floor(reserved)));
2421
2443
  const labelCells = Math.max(0, cells - field - 1);
2422
- const left = fitInstrumentText(label.toUpperCase(), labelCells);
2444
+ const left = fitInstrumentText(label2.toUpperCase(), labelCells);
2423
2445
  const dots = ".".repeat(Math.max(0, cells - field - terminalCellWidth(left)));
2424
2446
  return left + dots + " ".repeat(Math.max(0, field - readingCells)) + reading;
2425
2447
  }
@@ -2432,15 +2454,15 @@ function formatSignalMeter(value, maximum, width = 8) {
2432
2454
  return `[${".".repeat(cells)}] --`;
2433
2455
  const ratio = Math.max(0, Math.min(1, value / maximum));
2434
2456
  const filled = Math.round(ratio * cells);
2435
- return `[${"●".repeat(filled)}${"○".repeat(cells - filled)}] ${Math.round(ratio * 100)}%`;
2457
+ return `[${"▮".repeat(filled)}${"░".repeat(cells - filled)}] ${Math.round(ratio * 100)}%`;
2436
2458
  }
2437
2459
  function formatSectionBanner(title, width, expanded = true) {
2438
2460
  const cells = Math.max(0, Math.floor(width));
2439
- const label = fitInstrumentText(
2461
+ const label2 = fitInstrumentText(
2440
2462
  `${expanded ? "-" : "+"} ${title.toUpperCase()} `,
2441
2463
  cells
2442
2464
  );
2443
- return label + "─".repeat(Math.max(0, cells - terminalCellWidth(label)));
2465
+ return label2 + "─".repeat(Math.max(0, cells - terminalCellWidth(label2)));
2444
2466
  }
2445
2467
  function instrumentStatus(value) {
2446
2468
  const status = (value || "unknown").toLowerCase();
@@ -2453,10 +2475,994 @@ function instrumentStatus(value) {
2453
2475
  return status.toUpperCase();
2454
2476
  }
2455
2477
 
2478
+ // packages/cli/src/tui/native/components/task-notes.ts
2479
+ var marks = ["▨", "▧", "▥", "▦"];
2480
+ var reducedMotion = () => process.env["OMNIUS_TUI_REDUCE_MOTION"] === "1" || process.env["REDUCE_MOTION"] === "1";
2481
+ var safe = (value) => typeof value === "string" ? plainText(value) : "";
2482
+ var lines = (values) => Array.isArray(values) ? values.filter((value) => typeof value === "string").map(safe) : [];
2483
+ var column = (renderer2, id) => new BoxRenderable5(renderer2, { id, width: "100%", flexDirection: "column", flexShrink: 0, minWidth: 0 });
2484
+ function visible(node, renderer2) {
2485
+ if (node.width < 1 || node.height < 1 || node.y >= renderer2.terminalHeight || node.y + node.height <= 0) return false;
2486
+ for (let current = node; current; current = current.parent) {
2487
+ if (!current.visible) return false;
2488
+ if (current instanceof ScrollBoxRenderable3 && (node.y + node.height <= current.viewport.y || node.y >= current.viewport.y + current.viewport.height || node.x + node.width <= current.viewport.x || node.x >= current.viewport.x + current.viewport.width)) return false;
2489
+ }
2490
+ return true;
2491
+ }
2492
+ var ActiveBlocks = class {
2493
+ constructor(renderer2, active, paint) {
2494
+ this.renderer = renderer2;
2495
+ this.active = active;
2496
+ this.paint = paint;
2497
+ renderer2.on(CliRenderEvents3.FRAME, this.sync);
2498
+ }
2499
+ renderer;
2500
+ active;
2501
+ paint;
2502
+ timer;
2503
+ frame = 0;
2504
+ destroyed = false;
2505
+ get running() {
2506
+ return this.timer !== void 0;
2507
+ }
2508
+ sync = () => {
2509
+ const animate = !this.destroyed && !reducedMotion() && this.active();
2510
+ if (animate && !this.timer) {
2511
+ this.timer = setInterval(() => {
2512
+ if (!this.active() || reducedMotion()) {
2513
+ this.sync();
2514
+ return;
2515
+ }
2516
+ this.paint(marks[++this.frame % marks.length]);
2517
+ }, 250);
2518
+ this.timer.unref?.();
2519
+ } else if (!animate && this.timer) {
2520
+ clearInterval(this.timer);
2521
+ this.timer = void 0;
2522
+ }
2523
+ };
2524
+ destroy() {
2525
+ this.destroyed = true;
2526
+ if (this.timer) clearInterval(this.timer);
2527
+ this.timer = void 0;
2528
+ this.renderer.off(CliRenderEvents3.FRAME, this.sync);
2529
+ }
2530
+ };
2531
+ var Disclosure = class extends TextRenderable4 {
2532
+ constructor(renderer2, id, activate, colors, ruled = false) {
2533
+ super(renderer2, {
2534
+ id,
2535
+ content: "",
2536
+ width: "100%",
2537
+ height: 1,
2538
+ minWidth: 0,
2539
+ flexShrink: 0,
2540
+ wrapMode: "none",
2541
+ truncate: true,
2542
+ fg: colors.foreground,
2543
+ bg: colors.background,
2544
+ selectable: false,
2545
+ onMouseDown: (event) => {
2546
+ if (event.button === 0) {
2547
+ this.focus();
2548
+ activate();
2549
+ event.preventDefault();
2550
+ event.stopPropagation();
2551
+ }
2552
+ },
2553
+ onKeyDown: (key) => {
2554
+ if (key.eventType === "release") return;
2555
+ if (key.name === "return" || key.sequence === " " || key.name === "right" && !this.open || key.name === "left" && this.open) {
2556
+ activate();
2557
+ key.preventDefault();
2558
+ key.stopPropagation();
2559
+ }
2560
+ }
2561
+ });
2562
+ this.activate = activate;
2563
+ this.colors = colors;
2564
+ this.ruled = ruled;
2565
+ this.focusable = true;
2566
+ this.on(RenderableEvents3.FOCUSED, this.style);
2567
+ this.on(RenderableEvents3.BLURRED, this.style);
2568
+ }
2569
+ activate;
2570
+ colors;
2571
+ ruled;
2572
+ open = true;
2573
+ label = "";
2574
+ base = TextAttributes5.BOLD;
2575
+ update(label2, open, attributes = TextAttributes5.BOLD) {
2576
+ this.label = label2;
2577
+ this.open = open;
2578
+ this.base = attributes;
2579
+ this.refresh();
2580
+ this.style();
2581
+ }
2582
+ applyTheme(colors) {
2583
+ this.colors = colors;
2584
+ this.fg = colors.foreground;
2585
+ this.bg = colors.background;
2586
+ }
2587
+ style = () => {
2588
+ this.attributes = this.base | (this.focused ? TextAttributes5.INVERSE : 0);
2589
+ };
2590
+ onResize(width, height) {
2591
+ super.onResize(width, height);
2592
+ this.refresh();
2593
+ }
2594
+ refresh() {
2595
+ const text = this.ruled ? formatSectionBanner(this.label, this.width, this.open) : fitInstrumentText(`${this.open ? "−" : "+"} ${this.label}`, this.width);
2596
+ if (this.plainText !== text) this.content = text;
2597
+ }
2598
+ };
2599
+ function metadata(item) {
2600
+ const rows = [item.workKind ? `KIND ${safe(item.workKind)}` : "", item.owner ? `OWNER ${safe(item.owner)}` : "", item.blocker ? `BLOCKED ${safe(item.blocker)}` : ""];
2601
+ for (const [label2, values] of [["DEPENDS ON", item.blockedBy], ["BLOCKS", item.blocks], ["REQUIREMENTS", item.requirementIds], ["ACCEPTANCE", item.acceptanceIds], ["SOURCES", item.sourceRefs]])
2602
+ if (lines(values).length) rows.push(`${label2} ${lines(values).join(", ")}`);
2603
+ for (const ref of item.targetRefs ?? []) if (ref && safe(ref.ref)) rows.push(`${safe(ref.kind).toUpperCase()} ${safe(ref.ref)}`);
2604
+ const contract = item.actionContract;
2605
+ if (contract) {
2606
+ for (const [label2, values] of [["PRECONDITIONS", contract.preconditions], ["MUTATIONS", contract.mutations], ["SIDE EFFECTS", contract.sideEffects]])
2607
+ if (lines(values).length) rows.push(`${label2} ${lines(values).join("; ")}`);
2608
+ for (const key of ["authority", "approval", "risk"]) if (safe(contract[key])) rows.push(`${key.toUpperCase()} ${safe(contract[key])}`);
2609
+ }
2610
+ return rows.filter(Boolean).join("\n");
2611
+ }
2612
+ function taskMark(item, frame = marks[0]) {
2613
+ return item.status === "in_progress" ? frame : item.status === "completed" ? "■" : item.status === "blocked" ? "▣" : "□";
2614
+ }
2615
+ function layerStatus(layer) {
2616
+ const status = safe(layer.status).toLowerCase();
2617
+ if (["verified", "integrated"].includes(status)) return `REPORTED ${status.toUpperCase()} · AUTHORITY NOT ATTESTED`;
2618
+ return ["bound", "recorded", "tool complete", "tool failed", "compact", "hold", "accepted", "requested", "held", "incomplete verification", "incomplete_verification", "incomplete", "awaiting_input", "not attached", "proposed", "specified", "ready", "pending", "waiting", "leased", "running", "candidate", "verifying", "blocked", "retryable", "completed", "failed", "rejected", "cancelled", "superseded", "received", "queued", "acknowledged", "visible_in_request", "reconciliation_required", "reconciled", "first_affected_action", "consumed"].includes(status) ? status.replace(/_/g, " ").toUpperCase() : "UNKNOWN";
2619
+ }
2620
+ var NativeTaskNotesView = class extends BoxRenderable5 {
2621
+ constructor(renderer2, colors, reveal) {
2622
+ super(renderer2, { id: "omnius-task-notes", width: "100%", minWidth: 0, flexShrink: 0, flexDirection: "column", visible: false });
2623
+ this.renderer = renderer2;
2624
+ this.colors = colors;
2625
+ this.reveal = reveal;
2626
+ const text = (id, attributes = 0) => new TextRenderable4(renderer2, { id, content: "", width: "100%", minWidth: 0, flexShrink: 0, fg: colors.foreground, bg: colors.background, attributes, wrapMode: "word" });
2627
+ const heading = (id, label2, key) => {
2628
+ const node = new Disclosure(renderer2, id, () => {
2629
+ this.presentation[key] = !this.presentation[key];
2630
+ this.applyPresentation();
2631
+ }, colors, true);
2632
+ node.update(label2, this.presentation[key]);
2633
+ node.on(RenderableEvents3.FOCUSED, () => this.reveal?.(node));
2634
+ return node;
2635
+ };
2636
+ this.header = heading("omnius-task-notes:heading", "TASKS / NOTES", "open");
2637
+ this.add(this.header);
2638
+ this.body = column(renderer2, "omnius-task-notes:body");
2639
+ this.add(this.body);
2640
+ this.scope = text("omnius-task-notes:scope", TextAttributes5.DIM);
2641
+ this.body.add(this.scope);
2642
+ this.warning = text("omnius-task-notes:warning", TextAttributes5.BOLD);
2643
+ this.body.add(this.warning);
2644
+ this.taskHeader = heading("omnius-task-notes:tasks", "TASKS", "tasks");
2645
+ this.body.add(this.taskHeader);
2646
+ this.taskBody = column(renderer2, "omnius-task-notes:task-body");
2647
+ this.body.add(this.taskBody);
2648
+ this.noteHeader = heading("omnius-task-notes:notes", "NOTES", "notes");
2649
+ this.body.add(this.noteHeader);
2650
+ this.noteBody = column(renderer2, "omnius-task-notes:note-body");
2651
+ this.body.add(this.noteBody);
2652
+ this.layerHeader = heading("omnius-task-notes:layers", "RECORDED ORCHESTRATION", "layers");
2653
+ this.body.add(this.layerHeader);
2654
+ this.layerBody = column(renderer2, "omnius-task-notes:layer-body");
2655
+ this.body.add(this.layerBody);
2656
+ this.omitted = text("omnius-task-notes:omitted", TextAttributes5.DIM);
2657
+ this.body.add(this.omitted);
2658
+ this.animation = new ActiveBlocks(renderer2, () => [...this.rows.values()].some((row) => row.item.status === "in_progress" && visible(row.title, renderer2)), (mark) => {
2659
+ this.frame = mark;
2660
+ for (const row of this.rows.values()) if (row.item.status === "in_progress" && visible(row.title, renderer2)) this.refreshRow(row);
2661
+ });
2662
+ renderer2.on(CliRenderEvents3.FRAME, this.finishInspect);
2663
+ }
2664
+ renderer;
2665
+ colors;
2666
+ reveal;
2667
+ header;
2668
+ body;
2669
+ scope;
2670
+ warning;
2671
+ taskHeader;
2672
+ taskBody;
2673
+ noteHeader;
2674
+ noteBody;
2675
+ layerHeader;
2676
+ layerBody;
2677
+ omitted;
2678
+ rows = /* @__PURE__ */ new Map();
2679
+ noteRows = /* @__PURE__ */ new Map();
2680
+ layerRows = /* @__PURE__ */ new Map();
2681
+ disclosures = /* @__PURE__ */ new Map();
2682
+ sessions = /* @__PURE__ */ new Map();
2683
+ state;
2684
+ signature = "";
2685
+ animation;
2686
+ frame = marks[0];
2687
+ taskLabel = "TASKS";
2688
+ pendingInspect;
2689
+ presentation = { open: true, tasks: true, notes: true, layers: true };
2690
+ get animating() {
2691
+ return this.animation.running;
2692
+ }
2693
+ update(state) {
2694
+ const signature = JSON.stringify(state);
2695
+ if (signature === this.signature) return;
2696
+ this.signature = signature;
2697
+ if (this.state?.sessionId !== state?.sessionId) {
2698
+ if (this.state?.sessionId) this.sessions.set(this.state.sessionId, this.capturePresentation());
2699
+ while (this.sessions.size > 64) this.sessions.delete(this.sessions.keys().next().value);
2700
+ const saved = state?.sessionId ? this.sessions.get(state.sessionId) : void 0;
2701
+ this.presentation = saved ? { open: saved.open, tasks: saved.tasks, notes: saved.notes, layers: saved.layers } : { open: true, tasks: true, notes: true, layers: true };
2702
+ this.disclosures.clear();
2703
+ if (saved) for (const [id, open] of Object.entries(saved.disclosures)) this.disclosures.set(id, open);
2704
+ }
2705
+ this.state = state;
2706
+ this.visible = !!state;
2707
+ const items = Array.isArray(state?.todos) ? state.todos.filter((item) => item && typeof item.id === "string" && typeof item.content === "string").slice(0, 512) : [];
2708
+ const byId = new Map(items.map((item) => [item.id, item]));
2709
+ const parents = /* @__PURE__ */ new Map();
2710
+ for (const item of items) if (item.parentId && byId.has(item.parentId) && item.parentId !== item.id) {
2711
+ let cursor = item.parentId;
2712
+ const seen = /* @__PURE__ */ new Set([item.id]);
2713
+ while (cursor && !seen.has(cursor)) {
2714
+ seen.add(cursor);
2715
+ cursor = byId.get(cursor)?.parentId;
2716
+ }
2717
+ if (!cursor) parents.set(item.id, item.parentId);
2718
+ }
2719
+ const ids = new Set(byId.keys());
2720
+ for (const [id, row] of this.rows) if (ids.has(id) && row.root.parent !== this.taskBody) this.taskBody.add(row.root);
2721
+ for (const [id, row] of this.rows) if (!ids.has(id)) {
2722
+ row.root.destroyRecursively();
2723
+ this.rows.delete(id);
2724
+ }
2725
+ for (const item of items) {
2726
+ let row = this.rows.get(item.id);
2727
+ if (!row) {
2728
+ const root = column(this.renderer, `task:${item.id}`), children = column(this.renderer, `task:${item.id}:children`);
2729
+ children.paddingLeft = 2;
2730
+ const title = new Disclosure(this.renderer, `task:${item.id}:title`, () => {
2731
+ const key = `task:${item.id}`;
2732
+ this.disclosures.set(key, !(this.disclosures.get(key) ?? row.hasChildren));
2733
+ this.refreshRow(row);
2734
+ }, this.colors);
2735
+ title.on(RenderableEvents3.FOCUSED, () => this.reveal?.(title));
2736
+ const details = new TextRenderable4(this.renderer, { id: `task:${item.id}:metadata`, content: "", width: "100%", minWidth: 0, wrapMode: "word", flexShrink: 0, fg: this.colors.foreground, bg: this.colors.background, attributes: TextAttributes5.DIM });
2737
+ const detailButton = new Disclosure(this.renderer, `task:${item.id}:details`, () => {
2738
+ const key = `meta:${item.id}`;
2739
+ this.disclosures.set(key, !this.disclosures.get(key));
2740
+ this.refreshRow(row);
2741
+ }, this.colors);
2742
+ detailButton.on(RenderableEvents3.FOCUSED, () => this.reveal?.(detailButton));
2743
+ root.add(title);
2744
+ root.add(detailButton);
2745
+ root.add(details);
2746
+ root.add(children);
2747
+ row = { item, root, title, detailButton, details, children, hasChildren: false };
2748
+ this.rows.set(item.id, row);
2749
+ }
2750
+ row.item = item;
2751
+ row.hasChildren = [...parents.values()].includes(item.id);
2752
+ const parent = parents.get(item.id);
2753
+ const target = parent ? this.rows.get(parent)?.children : this.taskBody;
2754
+ (target ?? this.taskBody).add(row.root);
2755
+ this.refreshRow(row);
2756
+ }
2757
+ for (const item of items) {
2758
+ const parent = parents.get(item.id);
2759
+ if (parent) this.rows.get(parent).children.add(this.rows.get(item.id).root);
2760
+ }
2761
+ const leaves = items.filter((item) => ![...parents.values()].includes(item.id));
2762
+ this.taskLabel = `TASKS ${leaves.filter((item) => item.status === "completed").length}/${leaves.length}`;
2763
+ this.scope.content = state ? `SESSION ${safe(state.sessionLabel || state.sessionId)}` : "";
2764
+ this.warning.content = safe(state?.unavailable);
2765
+ this.warning.visible = !!state?.unavailable;
2766
+ this.updateNotes(Array.isArray(state?.notes) ? state.notes.slice(0, 256) : []);
2767
+ this.updateLayers(Array.isArray(state?.layers) ? state.layers.slice(0, 64) : []);
2768
+ const missingTasks = Math.max(0, (state?.omittedTasks || 0) + (Array.isArray(state?.todos) ? state.todos.length - items.length : 0));
2769
+ const missingNotes = Math.max(0, (state?.omittedNotes || 0) + Math.max(0, (state?.notes?.length || 0) - 256));
2770
+ this.omitted.content = [missingTasks ? `${missingTasks} more tasks omitted` : "", missingNotes ? `${missingNotes} more notes omitted` : ""].filter(Boolean).join("\n");
2771
+ this.omitted.visible = missingTasks > 0 || missingNotes > 0;
2772
+ this.applyPresentation();
2773
+ }
2774
+ refreshRow(row) {
2775
+ const item = row.item, expanded = this.disclosures.get(`task:${item.id}`) ?? row.hasChildren;
2776
+ const state = item.status === "blocked" ? " BLOCKED" : !["pending", "in_progress", "completed"].includes(item.status) ? " UNKNOWN" : "";
2777
+ row.title.update(
2778
+ `${taskMark(item, this.frame)} ${safe(item.status === "in_progress" && item.activeForm ? item.activeForm : item.content)}${state}`,
2779
+ expanded,
2780
+ item.status === "in_progress" || item.status === "blocked" ? TextAttributes5.BOLD : item.status === "pending" || item.status === "completed" ? TextAttributes5.DIM : 0
2781
+ );
2782
+ const detail = metadata(item), metaOpen = row.hasChildren ? this.disclosures.get(`meta:${item.id}`) === true : expanded;
2783
+ row.details.content = detail;
2784
+ row.details.visible = !!detail && metaOpen;
2785
+ row.detailButton.visible = row.hasChildren && !!detail && expanded;
2786
+ row.detailButton.update("DETAILS", metaOpen, TextAttributes5.DIM);
2787
+ row.children.visible = expanded;
2788
+ this.animation?.sync();
2789
+ }
2790
+ updateNotes(notes) {
2791
+ const ids = new Set(notes.map((note) => String(note.id)));
2792
+ for (const [id, row] of this.noteRows) if (!ids.has(id)) {
2793
+ row.destroy();
2794
+ this.noteRows.delete(id);
2795
+ }
2796
+ for (const [index, note] of notes.entries()) {
2797
+ const id = String(note.id);
2798
+ let row = this.noteRows.get(id);
2799
+ if (!row) {
2800
+ row = new TextRenderable4(this.renderer, { id: `note:${id}`, content: "", width: "100%", minWidth: 0, wrapMode: "word", flexShrink: 0, fg: this.colors.foreground, bg: this.colors.background });
2801
+ this.noteRows.set(id, row);
2802
+ }
2803
+ const text = `□ ${safe(note.category).toUpperCase()} · ${safe(note.content)}${note.file ? `
2804
+ ${safe(note.file)}${note.line ? `:${note.line}` : ""}` : ""}`;
2805
+ if (row.plainText !== text) row.content = text;
2806
+ if (this.noteBody.getChildren()[index] !== row) this.noteBody.add(row, index);
2807
+ }
2808
+ this.noteHeader.update(`NOTES ${notes.length} · ADVISORY`, this.presentation.notes);
2809
+ this.noteHeader.visible = notes.length > 0;
2810
+ }
2811
+ updateLayers(layers) {
2812
+ const ids = new Set(layers.map((layer) => safe(layer.id)));
2813
+ for (const [id, row] of this.layerRows) if (!ids.has(id)) {
2814
+ row.destroy();
2815
+ this.layerRows.delete(id);
2816
+ }
2817
+ for (const [index, layer] of layers.entries()) {
2818
+ const id = safe(layer.id);
2819
+ let row = this.layerRows.get(id);
2820
+ if (!row) {
2821
+ row = new TextRenderable4(this.renderer, { id: `work-layer:${id}`, content: "", width: "100%", minWidth: 0, wrapMode: "word", flexShrink: 0, fg: this.colors.foreground, bg: this.colors.background });
2822
+ this.layerRows.set(id, row);
2823
+ }
2824
+ const progress = typeof layer.progress === "number" && Number.isFinite(layer.progress) && layer.progress >= 0 && layer.progress <= 1 ? ` · ${Math.round(layer.progress * 100)}%` : "";
2825
+ const text = `□ ${safe(layer.label)} · ${layerStatus(layer)}${progress}${layer.detail ? `
2826
+ ${safe(layer.detail)}` : ""}${lines(layer.references).length ? `
2827
+ REF ${lines(layer.references).join(", ")}` : ""}`;
2828
+ if (row.plainText !== text) row.content = text;
2829
+ if (this.layerBody.getChildren()[index] !== row) this.layerBody.add(row, index);
2830
+ }
2831
+ this.layerHeader.visible = layers.length > 0;
2832
+ }
2833
+ applyPresentation() {
2834
+ this.header.update("TASKS / NOTES", this.presentation.open);
2835
+ this.body.visible = this.presentation.open;
2836
+ this.taskBody.visible = this.presentation.tasks;
2837
+ this.taskHeader.update(this.taskLabel, this.presentation.tasks);
2838
+ this.noteBody.visible = this.presentation.notes;
2839
+ this.noteHeader.update(`NOTES ${this.noteRows.size} · ADVISORY`, this.presentation.notes);
2840
+ this.layerBody.visible = this.presentation.layers;
2841
+ this.layerHeader.update("RECORDED ORCHESTRATION", this.presentation.layers);
2842
+ this.animation.sync();
2843
+ }
2844
+ inspect(id) {
2845
+ this.presentation.open = this.presentation.tasks = true;
2846
+ if (id) {
2847
+ const row = this.rows.get(id);
2848
+ let parent = row?.item.parentId;
2849
+ const seen = /* @__PURE__ */ new Set();
2850
+ while (parent && !seen.has(parent)) {
2851
+ seen.add(parent);
2852
+ this.disclosures.set(`task:${parent}`, true);
2853
+ const ancestor = this.rows.get(parent);
2854
+ if (ancestor) this.refreshRow(ancestor);
2855
+ parent = ancestor?.item.parentId;
2856
+ }
2857
+ }
2858
+ this.applyPresentation();
2859
+ const target = id ? this.rows.get(id)?.title : this.header;
2860
+ target?.focus();
2861
+ this.pendingInspect = id ?? "";
2862
+ this.renderer.requestRender();
2863
+ }
2864
+ finishInspect = () => {
2865
+ if (this.pendingInspect === void 0) return;
2866
+ const target = this.pendingInspect ? this.rows.get(this.pendingInspect)?.title : this.header;
2867
+ this.pendingInspect = void 0;
2868
+ if (target) {
2869
+ this.reveal?.(target);
2870
+ this.renderer.requestRender();
2871
+ }
2872
+ };
2873
+ capturePresentation() {
2874
+ return { ...this.presentation, disclosures: Object.fromEntries([...this.disclosures].slice(-2048)) };
2875
+ }
2876
+ restorePresentation(state) {
2877
+ if (!state) return;
2878
+ this.presentation = { open: state.open, tasks: state.tasks, notes: state.notes, layers: state.layers };
2879
+ this.disclosures.clear();
2880
+ for (const [id, open] of Object.entries(state.disclosures)) this.disclosures.set(id, open);
2881
+ for (const row of this.rows.values()) this.refreshRow(row);
2882
+ this.applyPresentation();
2883
+ }
2884
+ focusTargets() {
2885
+ const targets = [];
2886
+ const visit = (node) => {
2887
+ if (!node.visible) return;
2888
+ if (node instanceof TextRenderable4 && node.focusable) targets.push(node);
2889
+ for (const child of node.getChildren()) visit(child);
2890
+ };
2891
+ if (this.visible) visit(this);
2892
+ return targets;
2893
+ }
2894
+ applyTheme(colors) {
2895
+ this.colors = colors;
2896
+ const visit = (node) => {
2897
+ if (node instanceof TextRenderable4) {
2898
+ node.fg = colors.foreground;
2899
+ node.bg = colors.background;
2900
+ }
2901
+ for (const child of node.getChildren()) visit(child);
2902
+ };
2903
+ visit(this);
2904
+ }
2905
+ destroySelf() {
2906
+ this.animation.destroy();
2907
+ this.renderer.off(CliRenderEvents3.FRAME, this.finishInspect);
2908
+ super.destroySelf();
2909
+ }
2910
+ };
2911
+ var NativeTaskStrip = class extends BoxRenderable5 {
2912
+ constructor(renderer2, colors, inspect) {
2913
+ super(renderer2, {
2914
+ id: "omnius-task-strip",
2915
+ width: "100%",
2916
+ minWidth: 0,
2917
+ height: 3,
2918
+ minHeight: 3,
2919
+ maxHeight: 3,
2920
+ flexShrink: 0,
2921
+ border: true,
2922
+ borderStyle: "single",
2923
+ borderColor: colors.border,
2924
+ flexDirection: "row",
2925
+ visible: false
2926
+ });
2927
+ this.renderer = renderer2;
2928
+ this.colors = colors;
2929
+ this.inspect = inspect;
2930
+ this.label = new TextRenderable4(renderer2, {
2931
+ id: "omnius-task-strip:heading",
2932
+ content: "TASKS ",
2933
+ height: 1,
2934
+ width: 6,
2935
+ flexShrink: 0,
2936
+ selectable: false,
2937
+ fg: colors.foreground,
2938
+ bg: colors.background,
2939
+ attributes: TextAttributes5.BOLD,
2940
+ onMouseDown: (event) => {
2941
+ if (event.button === 0) {
2942
+ inspect();
2943
+ event.preventDefault();
2944
+ event.stopPropagation();
2945
+ }
2946
+ },
2947
+ onKeyDown: (key) => {
2948
+ if (key.eventType !== "release" && (key.name === "return" || key.sequence === " ")) {
2949
+ inspect();
2950
+ key.preventDefault();
2951
+ key.stopPropagation();
2952
+ }
2953
+ }
2954
+ });
2955
+ this.label.focusable = true;
2956
+ this.add(this.label);
2957
+ this.scroll = new ScrollBoxRenderable3(renderer2, {
2958
+ id: "omnius-task-strip:scroll",
2959
+ height: 1,
2960
+ minHeight: 1,
2961
+ maxHeight: 1,
2962
+ minWidth: 0,
2963
+ flexGrow: 1,
2964
+ scrollX: true,
2965
+ scrollY: false,
2966
+ viewportOptions: { height: 1, minHeight: 1, maxHeight: 1, flexGrow: 0, flexShrink: 0 },
2967
+ contentOptions: { flexDirection: "row", gap: 3 },
2968
+ horizontalScrollbarOptions: { visible: false },
2969
+ verticalScrollbarOptions: { visible: false }
2970
+ });
2971
+ this.scroll.horizontalScrollBar.visible = this.scroll.verticalScrollBar.visible = false;
2972
+ this.add(this.scroll);
2973
+ styleNativeScrollbars(this.scroll, colors);
2974
+ this.animation = new ActiveBlocks(renderer2, () => [...this.chips.values()].some((chip) => chip.item.status === "in_progress" && visible(chip.label, renderer2)), (mark) => {
2975
+ this.frame = mark;
2976
+ for (const chip of this.chips.values()) if (chip.item.status === "in_progress" && visible(chip.label, renderer2)) this.refreshChip(chip);
2977
+ });
2978
+ }
2979
+ renderer;
2980
+ colors;
2981
+ inspect;
2982
+ scroll;
2983
+ label;
2984
+ chips = /* @__PURE__ */ new Map();
2985
+ animation;
2986
+ frame = marks[0];
2987
+ sessionId;
2988
+ signature = "";
2989
+ hasItems = false;
2990
+ get animating() {
2991
+ return this.animation.running;
2992
+ }
2993
+ update(state) {
2994
+ const signature = JSON.stringify(state);
2995
+ if (signature === this.signature) return;
2996
+ this.signature = signature;
2997
+ const source = Array.isArray(state?.todos) ? state.todos.filter((item) => item && typeof item.id === "string" && typeof item.content === "string").slice(0, 512) : [];
2998
+ const parents = new Set(source.map((item) => item.parentId).filter(Boolean));
2999
+ const children = /* @__PURE__ */ new Map();
3000
+ for (const item of source) if (item.parentId) {
3001
+ const list = children.get(item.parentId) ?? [];
3002
+ list.push(item);
3003
+ children.set(item.parentId, list);
3004
+ }
3005
+ const busy = (item) => item.status === "in_progress" || item.status === "blocked";
3006
+ const activeDescendant = (id) => {
3007
+ const seen = /* @__PURE__ */ new Set([id]), stack = [...children.get(id) ?? []];
3008
+ while (stack.length) {
3009
+ const item = stack.pop();
3010
+ if (seen.has(item.id)) continue;
3011
+ seen.add(item.id);
3012
+ if (busy(item)) return true;
3013
+ stack.push(...children.get(item.id) ?? []);
3014
+ }
3015
+ return false;
3016
+ };
3017
+ let leaves = source.filter((item) => item.status !== "completed" && (!parents.has(item.id) || busy(item) && !activeDescendant(item.id)));
3018
+ if (!leaves.length) leaves = source.filter((item) => item.status !== "completed");
3019
+ const items = [leaves.filter((item) => item.status === "in_progress"), leaves.filter((item) => item.status === "blocked"), leaves.filter((item) => item.status !== "in_progress" && item.status !== "blocked")].flat();
3020
+ const ids = new Set(items.map((item) => item.id));
3021
+ const wasFirst = this.scroll.getChildren()[0]?.id;
3022
+ for (const [id, chip] of this.chips) if (!ids.has(id)) {
3023
+ chip.label.destroy();
3024
+ this.chips.delete(id);
3025
+ }
3026
+ for (const [index, item] of items.entries()) {
3027
+ let chip = this.chips.get(item.id);
3028
+ if (!chip) {
3029
+ const label2 = new TextRenderable4(this.renderer, {
3030
+ id: `task-strip:${item.id}`,
3031
+ content: "",
3032
+ height: 1,
3033
+ flexShrink: 0,
3034
+ wrapMode: "none",
3035
+ selectable: false,
3036
+ fg: this.colors.foreground,
3037
+ bg: this.colors.background,
3038
+ onMouseDown: (event) => {
3039
+ if (event.button === 0) {
3040
+ label2.focus();
3041
+ this.inspect(item.id);
3042
+ event.preventDefault();
3043
+ event.stopPropagation();
3044
+ }
3045
+ },
3046
+ onKeyDown: (key) => {
3047
+ if (key.eventType === "release") return;
3048
+ if (key.name === "return" || key.sequence === " ") this.inspect(item.id);
3049
+ else if (["left", "right", "home", "end"].includes(key.name)) {
3050
+ const targets = this.scroll.getChildren();
3051
+ const index2 = targets.indexOf(label2);
3052
+ const next = key.name === "home" ? 0 : key.name === "end" ? targets.length - 1 : Math.max(0, Math.min(targets.length - 1, index2 + (key.name === "left" ? -1 : 1)));
3053
+ targets[next]?.focus();
3054
+ if (targets[next]) this.scroll.scrollChildIntoView(targets[next].id);
3055
+ } else return;
3056
+ key.preventDefault();
3057
+ key.stopPropagation();
3058
+ }
3059
+ });
3060
+ label2.focusable = true;
3061
+ chip = { item, label: label2 };
3062
+ this.chips.set(item.id, chip);
3063
+ label2.on(RenderableEvents3.FOCUSED, () => {
3064
+ this.refreshChip(chip);
3065
+ this.scroll.scrollChildIntoView(label2.id);
3066
+ });
3067
+ label2.on(RenderableEvents3.BLURRED, () => this.refreshChip(chip));
3068
+ }
3069
+ chip.item = item;
3070
+ this.refreshChip(chip);
3071
+ if (this.scroll.getChildren()[index] !== chip.label) this.scroll.add(chip.label, index);
3072
+ }
3073
+ this.label.content = state ? fitInstrumentText(safe(state.sessionLabel || state.sessionId).toUpperCase(), 12) + " TASKS " : "TASKS ";
3074
+ this.label.width = terminalCellWidth(this.label.plainText);
3075
+ if (this.sessionId !== state?.sessionId || wasFirst !== this.scroll.getChildren()[0]?.id) this.scroll.scrollTo({ x: 0, y: 0 });
3076
+ this.sessionId = state?.sessionId;
3077
+ this.visible = this.hasItems = items.length > 0;
3078
+ this.animation.sync();
3079
+ }
3080
+ refreshChip(chip) {
3081
+ const item = chip.item;
3082
+ const title = safe(item.status === "in_progress" && item.activeForm ? item.activeForm : item.content).replace(/\s+/g, " ");
3083
+ const content = `${taskMark(item, this.frame)} ${fitInstrumentText(title, 34)}${item.status === "blocked" ? " BLOCKED" : ""}`;
3084
+ if (chip.label.plainText !== content) chip.label.content = content;
3085
+ chip.label.attributes = (item.status === "in_progress" || item.status === "blocked" ? TextAttributes5.BOLD : TextAttributes5.DIM) | (chip.label.focused ? TextAttributes5.INVERSE : 0);
3086
+ }
3087
+ applyTheme(colors) {
3088
+ this.colors = colors;
3089
+ this.borderColor = colors.border;
3090
+ this.label.fg = colors.foreground;
3091
+ this.label.bg = colors.background;
3092
+ for (const chip of this.chips.values()) {
3093
+ chip.label.fg = colors.foreground;
3094
+ chip.label.bg = colors.background;
3095
+ }
3096
+ styleNativeScrollbars(this.scroll, colors);
3097
+ }
3098
+ reconcile() {
3099
+ this.animation.sync();
3100
+ }
3101
+ destroySelf() {
3102
+ this.animation.destroy();
3103
+ super.destroySelf();
3104
+ }
3105
+ };
3106
+
3107
+ // packages/cli/src/tui/native/components/work-queue.ts
3108
+ import {
3109
+ BoxRenderable as BoxRenderable6,
3110
+ CliRenderEvents as CliRenderEvents4,
3111
+ RenderableEvents as RenderableEvents4,
3112
+ ScrollBoxRenderable as ScrollBoxRenderable4,
3113
+ TextAttributes as TextAttributes6,
3114
+ TextRenderable as TextRenderable5
3115
+ } from "@opentui/core";
3116
+ var frames = ["▨", "▧", "▥", "▦"];
3117
+ var actionLabels = { queue: "QUEUE", apply: "APPLY", override: "OVERRIDE", cancel: "CANCEL", retry: "RETRY", up: "UP", down: "DOWN" };
3118
+ var safe2 = (value) => typeof value === "string" ? plainText(value) : "";
3119
+ var label = (value) => safe2(value).replace(/[\r\n\t]+/g, " ");
3120
+ var reducedMotion2 = () => process.env["OMNIUS_TUI_REDUCE_MOTION"] === "1" || process.env["REDUCE_MOTION"] === "1";
3121
+ var column2 = (renderer2, id) => new BoxRenderable6(renderer2, { id, width: "100%", minWidth: 0, flexDirection: "column", flexShrink: 0 });
3122
+ var historyStates = /* @__PURE__ */ new Set(["completed", "applied", "failed", "cancelled"]);
3123
+ var activeStates = /* @__PURE__ */ new Set(["claiming", "running", "admitted"]);
3124
+ var receiptTime = (at) => {
3125
+ const date = new Date(typeof at === "number" ? at : NaN);
3126
+ return Number.isFinite(date.getTime()) ? date.toISOString() : "";
3127
+ };
3128
+ var WorkControl = class extends TextRenderable5 {
3129
+ constructor(renderer2, id, activate, colors, disclosure = false, ruled = false, fixedWidth) {
3130
+ super(renderer2, {
3131
+ id,
3132
+ content: "",
3133
+ width: fixedWidth ?? "100%",
3134
+ minWidth: 0,
3135
+ height: 1,
3136
+ flexShrink: 0,
3137
+ wrapMode: "none",
3138
+ truncate: true,
3139
+ fg: colors.foreground,
3140
+ bg: colors.background,
3141
+ selectable: false,
3142
+ onMouseDown: (event) => {
3143
+ if (event.button === 0) {
3144
+ this.focus();
3145
+ activate();
3146
+ event.preventDefault();
3147
+ event.stopPropagation();
3148
+ }
3149
+ },
3150
+ onKeyDown: (key) => {
3151
+ if (key.eventType !== "release" && (key.name === "return" || key.sequence === " " || disclosure && (key.name === "right" && !this.open || key.name === "left" && this.open))) {
3152
+ activate();
3153
+ key.preventDefault();
3154
+ key.stopPropagation();
3155
+ }
3156
+ }
3157
+ });
3158
+ this.activate = activate;
3159
+ this.disclosure = disclosure;
3160
+ this.ruled = ruled;
3161
+ this.focusable = true;
3162
+ this.on(RenderableEvents4.FOCUSED, this.style);
3163
+ this.on(RenderableEvents4.BLURRED, this.style);
3164
+ }
3165
+ activate;
3166
+ disclosure;
3167
+ ruled;
3168
+ open = false;
3169
+ caption = "";
3170
+ base = 0;
3171
+ update(caption, open = false, attributes = 0) {
3172
+ this.caption = caption;
3173
+ this.open = open;
3174
+ this.base = attributes;
3175
+ this.refresh();
3176
+ this.style();
3177
+ }
3178
+ style = () => {
3179
+ this.attributes = this.base | (this.focused ? TextAttributes6.INVERSE : 0);
3180
+ };
3181
+ onResize(width, height) {
3182
+ super.onResize(width, height);
3183
+ this.refresh();
3184
+ }
3185
+ refresh() {
3186
+ const value = this.ruled ? formatSectionBanner(this.caption, this.width, this.open) : fitInstrumentText(`${this.disclosure ? this.open ? "− " : "+ " : ""}${this.caption}`, this.width);
3187
+ if (this.plainText !== value) this.content = value;
3188
+ }
3189
+ };
3190
+ var NativeWorkQueueView = class extends BoxRenderable6 {
3191
+ constructor(renderer2, colors, onAction, reveal) {
3192
+ super(renderer2, { id: "omnius-work-queue", width: "100%", minWidth: 0, flexDirection: "column", flexShrink: 0, visible: false });
3193
+ this.renderer = renderer2;
3194
+ this.colors = colors;
3195
+ this.onAction = onAction;
3196
+ this.reveal = reveal;
3197
+ this.header = this.control("omnius-work-queue:heading", () => {
3198
+ this.presentation.open = !this.presentation.open;
3199
+ this.applyPresentation();
3200
+ }, true, true);
3201
+ this.add(this.header);
3202
+ this.body = column2(renderer2, "omnius-work-queue:body");
3203
+ this.add(this.body);
3204
+ this.scope = this.text("omnius-work-queue:scope", TextAttributes6.DIM);
3205
+ this.body.add(this.scope);
3206
+ this.warning = this.text("omnius-work-queue:warning", TextAttributes6.BOLD);
3207
+ this.body.add(this.warning);
3208
+ for (const group of ["current", "intake", "upcoming", "held"]) {
3209
+ const heading = this.text(`omnius-work-queue:${group}:heading`, TextAttributes6.DIM | TextAttributes6.BOLD);
3210
+ const body = column2(renderer2, `omnius-work-queue:${group}`);
3211
+ this.groups.set(group, { heading, body });
3212
+ this.body.add(heading);
3213
+ this.body.add(body);
3214
+ }
3215
+ this.historyHeader = this.control("omnius-work-queue:history:heading", () => {
3216
+ this.presentation.history = !this.presentation.history;
3217
+ this.applyPresentation();
3218
+ }, true);
3219
+ const history = column2(renderer2, "omnius-work-queue:history");
3220
+ this.groups.set("history", { heading: this.historyHeader, body: history });
3221
+ this.body.add(this.historyHeader);
3222
+ this.body.add(history);
3223
+ this.empty = this.text("omnius-work-queue:empty", TextAttributes6.DIM);
3224
+ this.empty.content = "No pending work.";
3225
+ this.body.add(this.empty);
3226
+ this.omitted = this.text("omnius-work-queue:omitted", TextAttributes6.DIM);
3227
+ this.body.add(this.omitted);
3228
+ renderer2.on(CliRenderEvents4.FRAME, this.syncAnimation);
3229
+ }
3230
+ renderer;
3231
+ colors;
3232
+ onAction;
3233
+ reveal;
3234
+ header;
3235
+ body;
3236
+ historyHeader;
3237
+ scope;
3238
+ warning;
3239
+ empty;
3240
+ omitted;
3241
+ groups = /* @__PURE__ */ new Map();
3242
+ rows = /* @__PURE__ */ new Map();
3243
+ sessions = /* @__PURE__ */ new Map();
3244
+ state;
3245
+ signature = "";
3246
+ presentation = { open: true, history: false, disclosures: {} };
3247
+ timer;
3248
+ frame = 0;
3249
+ disposed = false;
3250
+ text(id, attributes = 0) {
3251
+ return new TextRenderable5(this.renderer, { id, content: "", width: "100%", minWidth: 0, flexShrink: 0, wrapMode: "word", fg: this.colors.foreground, bg: this.colors.background, attributes });
3252
+ }
3253
+ control(id, activate, disclosure = false, ruled = false, width) {
3254
+ const node = new WorkControl(this.renderer, id, activate, this.colors, disclosure, ruled, width);
3255
+ node.on(RenderableEvents4.FOCUSED, () => this.reveal?.(node));
3256
+ return node;
3257
+ }
3258
+ get animating() {
3259
+ return this.timer !== void 0;
3260
+ }
3261
+ update(state) {
3262
+ if (state && state === this.state) return;
3263
+ const signature = JSON.stringify(state);
3264
+ if (signature === this.signature) return;
3265
+ this.signature = signature;
3266
+ const scope = (value) => value ? `${value.projectRoot}\0${value.sessionId}` : "";
3267
+ if (scope(state) !== scope(this.state)) {
3268
+ if (this.state) this.sessions.set(scope(this.state), this.capturePresentation());
3269
+ while (this.sessions.size > 64) this.sessions.delete(this.sessions.keys().next().value);
3270
+ this.presentation = structuredClone(this.sessions.get(scope(state)) ?? { open: true, history: false, disclosures: {} });
3271
+ for (const row of this.rows.values()) row.root.destroy();
3272
+ this.rows.clear();
3273
+ }
3274
+ this.state = state;
3275
+ this.visible = Boolean(state);
3276
+ if (!state) {
3277
+ this.syncAnimation();
3278
+ return;
3279
+ }
3280
+ this.scope.content = `SESSION ${label(state.sessionLabel || state.sessionId)}`;
3281
+ this.warning.content = safe2(state.unavailable);
3282
+ this.warning.visible = Boolean(state.unavailable);
3283
+ const items = state.items.filter((item) => item && typeof item.id === "string"), ids = new Set(items.map((item) => item.id));
3284
+ for (const [id, row] of this.rows) if (!ids.has(id)) {
3285
+ row.root.destroy();
3286
+ this.rows.delete(id);
3287
+ delete this.presentation.disclosures[id];
3288
+ }
3289
+ const order = (a, b) => a.order - b.order || a.id.localeCompare(b.id);
3290
+ const groups = { current: [], intake: [], upcoming: [], held: [], history: [] };
3291
+ for (const item of items) {
3292
+ const group = item.id === state.activeId || activeStates.has(item.state) ? "current" : historyStates.has(item.state) ? "history" : item.state === "needs_review" || item.state === "interrupted" ? "held" : item.state === "reviewing" || item.state === "received" ? "intake" : "upcoming";
3293
+ groups[group].push(item);
3294
+ }
3295
+ groups.current.sort((a, b) => Number(b.id === state.activeId) - Number(a.id === state.activeId) || order(a, b));
3296
+ groups.intake.sort(order);
3297
+ groups.upcoming.sort(order);
3298
+ groups.held.sort(order);
3299
+ groups.history.sort((a, b) => (b.receivedAt ?? 0) - (a.receivedAt ?? 0) || order(a, b));
3300
+ const titles = { current: "CURRENT", intake: "INTAKE", upcoming: "QUEUED", held: "HELD / REVIEW", history: "HISTORY" };
3301
+ for (const group of ["current", "intake", "upcoming", "held", "history"]) {
3302
+ const target = this.groups.get(group);
3303
+ target.heading.visible = groups[group].length > 0;
3304
+ target.body.visible = groups[group].length > 0;
3305
+ if (group !== "history") target.heading.content = `${titles[group]} ${groups[group].length}`;
3306
+ for (const [index, item] of groups[group].entries()) {
3307
+ const row = this.rows.get(item.id) ?? this.createRow(item);
3308
+ row.item = item;
3309
+ row.position = group === "upcoming" ? index + 1 : void 0;
3310
+ this.refreshRow(row);
3311
+ if (row.root.parent !== target.body || target.body.getChildren()[index] !== row.root) target.body.add(row.root, index);
3312
+ }
3313
+ }
3314
+ this.empty.visible = items.length === 0 && !state.unavailable;
3315
+ this.omitted.content = state.omitted ? `${state.omitted} more work items omitted` : "";
3316
+ this.omitted.visible = Boolean(state.omitted);
3317
+ this.applyPresentation();
3318
+ }
3319
+ createRow(item) {
3320
+ const id = `work:${item.id}`, root = column2(this.renderer, id);
3321
+ const title = this.control(`${id}:title`, () => {
3322
+ this.presentation.disclosures[item.id] = !this.presentation.disclosures[item.id];
3323
+ this.refreshRow(this.rows.get(item.id));
3324
+ this.renderer.requestRender();
3325
+ }, true);
3326
+ root.add(title);
3327
+ const details = column2(this.renderer, `${id}:details`);
3328
+ details.paddingLeft = 2;
3329
+ root.add(details);
3330
+ const metadata2 = this.text(`${id}:metadata`, TextAttributes6.DIM), original = this.text(`${id}:original`);
3331
+ details.add(original);
3332
+ details.add(metadata2);
3333
+ const controls = new BoxRenderable6(this.renderer, { id: `${id}:actions`, width: "100%", minWidth: 0, flexDirection: "row", flexWrap: "wrap", flexShrink: 0 });
3334
+ details.add(controls);
3335
+ const row = { item, root, title, details, original, metadata: metadata2, controls, actions: /* @__PURE__ */ new Map() };
3336
+ this.rows.set(item.id, row);
3337
+ return row;
3338
+ }
3339
+ refreshRow(row) {
3340
+ const item = row.item, open = this.presentation.disclosures[item.id] === true;
3341
+ const state = label(item.state).replace(/_/g, " ").toUpperCase();
3342
+ const mark = item.state === "reviewing" || item.state === "claiming" ? frames[this.frame % frames.length] : item.state === "running" ? "▨" : item.state === "needs_review" || item.state === "interrupted" ? "▣" : historyStates.has(item.state) ? "■" : "□";
3343
+ row.title.update(
3344
+ `${mark} ${row.position === void 0 ? "" : `${row.position}. `}${state} · ${label(item.title) || "Untitled request"}`,
3345
+ open,
3346
+ item.state === "queued" ? TextAttributes6.DIM : item.state === "running" || item.state === "needs_review" ? TextAttributes6.BOLD : 0
3347
+ );
3348
+ row.details.visible = open;
3349
+ const original = `ORIGINAL
3350
+ ${safe2(item.originalText)}`;
3351
+ if (row.original.plainText !== original) row.original.content = original;
3352
+ const metadata2 = [
3353
+ item.source ? `SOURCE ${label(item.source)}` : "",
3354
+ `PROJECT ${safe2(this.state?.projectRoot)}`,
3355
+ item.parentWorkId ? `PARENT ${label(item.parentWorkId)}` : "",
3356
+ item.runId ? `RUN ${label(item.runId)}` : "",
3357
+ ...(item.attachments ?? []).map((attachment) => [`ATTACHMENT ${label(attachment.kind)} · ${label(attachment.label)}`, attachment.path ? `PATH ${safe2(attachment.path)}` : "", attachment.reference ? `REFERENCE ${safe2(attachment.reference)}` : "", attachment.mimeType ? `MIME ${label(attachment.mimeType)}` : ""].filter(Boolean).join("\n")),
3358
+ ...item.review ? [`RECOMMENDATION ${label(item.review.disposition).replace(/_/g, " ")}`, item.review.summary ? `SUMMARY ${safe2(item.review.summary)}` : "", item.review.rationale ? `RATIONALE ${safe2(item.review.rationale)}` : "", item.review.relationship ? `RELATIONSHIP ${safe2(item.review.relationship)}` : "", ...(item.review.questions ?? []).map((question) => `QUESTION ${safe2(question)}`)] : [],
3359
+ ...(item.receipts ?? []).map((receipt) => `RECEIPT ${label(receipt.kind).replace(/_/g, " ")}${receiptTime(receipt.at) ? ` · ${receiptTime(receipt.at)}` : ""}${receipt.message ? `
3360
+ ${safe2(receipt.message)}` : ""}${receipt.runId ? `
3361
+ RUN ${label(receipt.runId)}` : ""}`)
3362
+ ].filter(Boolean).join("\n");
3363
+ if (row.metadata.plainText !== metadata2) row.metadata.content = metadata2;
3364
+ const allowed = [...new Set(item.actions ?? [])].filter((action) => Object.hasOwn(actionLabels, action));
3365
+ for (const [action, button] of row.actions) if (!allowed.includes(action)) {
3366
+ button.destroy();
3367
+ row.actions.delete(action);
3368
+ }
3369
+ for (const [index, action] of allowed.entries()) {
3370
+ let button = row.actions.get(action);
3371
+ if (!button) {
3372
+ button = this.control(`work:${item.id}:action:${action}`, () => this.dispatch(item.id, action), false, false, terminalCellWidth(actionLabels[action]) + 2);
3373
+ button.update(`[${actionLabels[action]}]`);
3374
+ row.actions.set(action, button);
3375
+ }
3376
+ if (row.controls.getChildren()[index] !== button) row.controls.add(button, index);
3377
+ }
3378
+ row.controls.visible = allowed.length > 0;
3379
+ }
3380
+ dispatch(id, action) {
3381
+ const item = this.rows.get(id)?.item, state = this.state;
3382
+ if (!state || !item?.actions?.includes(action)) return;
3383
+ this.onAction?.({ type: "work-action", action, id, expectedRevision: item.revision, expectedQueueRevision: state.revision, sessionId: state.sessionId, projectRoot: state.projectRoot });
3384
+ }
3385
+ applyPresentation() {
3386
+ const count = this.state?.items.filter((item) => !historyStates.has(item.state)).length ?? 0;
3387
+ this.header.update(`WORK / QUEUE ${count}`, this.presentation.open, TextAttributes6.BOLD);
3388
+ this.body.visible = this.presentation.open;
3389
+ const history = this.groups.get("history");
3390
+ this.historyHeader.update(`HISTORY ${history.body.getChildren().length}`, this.presentation.history, TextAttributes6.DIM);
3391
+ history.body.visible = history.body.getChildren().length > 0 && this.presentation.history;
3392
+ this.syncAnimation();
3393
+ this.renderer.requestRender();
3394
+ }
3395
+ isVisible(node) {
3396
+ if (node.width < 1 || node.height < 1 || node.y >= this.renderer.terminalHeight || node.y + node.height <= 0) return false;
3397
+ for (let ancestor = node; ancestor; ancestor = ancestor.parent) {
3398
+ if (!ancestor.visible) return false;
3399
+ if (ancestor instanceof ScrollBoxRenderable4 && (node.y + node.height <= ancestor.viewport.y || node.y >= ancestor.viewport.y + ancestor.viewport.height)) return false;
3400
+ }
3401
+ return true;
3402
+ }
3403
+ syncAnimation = () => {
3404
+ const active = !this.disposed && !reducedMotion2() && [...this.rows.values()].some((row) => ["reviewing", "claiming"].includes(row.item.state) && this.isVisible(row.title));
3405
+ if (active && !this.timer) {
3406
+ this.timer = setInterval(() => {
3407
+ if (reducedMotion2() || ![...this.rows.values()].some((row) => ["reviewing", "claiming"].includes(row.item.state) && this.isVisible(row.title))) {
3408
+ this.syncAnimation();
3409
+ return;
3410
+ }
3411
+ this.frame++;
3412
+ for (const row of this.rows.values()) if (["reviewing", "claiming"].includes(row.item.state) && this.isVisible(row.title)) this.refreshTitle(row);
3413
+ }, 250);
3414
+ this.timer.unref?.();
3415
+ } else if (!active && this.timer) {
3416
+ clearInterval(this.timer);
3417
+ this.timer = void 0;
3418
+ }
3419
+ };
3420
+ refreshTitle(row) {
3421
+ row.title.update(`${frames[this.frame % frames.length]} ${row.position === void 0 ? "" : `${row.position}. `}${label(row.item.state).toUpperCase()} · ${label(row.item.title) || "Untitled request"}`, this.presentation.disclosures[row.item.id] === true);
3422
+ }
3423
+ capturePresentation() {
3424
+ return { open: this.presentation.open, history: this.presentation.history, disclosures: Object.fromEntries(Object.entries(this.presentation.disclosures).slice(-2048)) };
3425
+ }
3426
+ restorePresentation(state) {
3427
+ if (!state) return;
3428
+ this.presentation = { open: state.open, history: state.history, disclosures: { ...state.disclosures } };
3429
+ for (const row of this.rows.values()) this.refreshRow(row);
3430
+ this.applyPresentation();
3431
+ }
3432
+ focusTargets() {
3433
+ const targets = [];
3434
+ const visit = (node) => {
3435
+ if (!node.visible) return;
3436
+ if (node instanceof TextRenderable5 && node.focusable) targets.push(node);
3437
+ for (const child of node.getChildren()) visit(child);
3438
+ };
3439
+ if (this.visible) visit(this);
3440
+ return targets;
3441
+ }
3442
+ applyTheme(colors) {
3443
+ this.colors = colors;
3444
+ const visit = (node) => {
3445
+ if (node instanceof TextRenderable5) {
3446
+ node.fg = colors.foreground;
3447
+ node.bg = colors.background;
3448
+ }
3449
+ for (const child of node.getChildren()) visit(child);
3450
+ };
3451
+ visit(this);
3452
+ }
3453
+ destroySelf() {
3454
+ this.disposed = true;
3455
+ if (this.timer) clearInterval(this.timer);
3456
+ this.timer = void 0;
3457
+ this.renderer.off(CliRenderEvents4.FRAME, this.syncAnimation);
3458
+ super.destroySelf();
3459
+ }
3460
+ };
3461
+
2456
3462
  // packages/cli/src/tui/native/components/instruments.ts
2457
3463
  var foreground = RGBA2.defaultForeground();
2458
3464
  var background = RGBA2.defaultBackground();
2459
- var SectionBanner = class extends TextRenderable4 {
3465
+ var SectionBanner = class extends TextRenderable6 {
2460
3466
  constructor(renderer2, title, id, activate) {
2461
3467
  super(renderer2, {
2462
3468
  id,
@@ -2466,7 +3472,7 @@ var SectionBanner = class extends TextRenderable4 {
2466
3472
  flexShrink: 0,
2467
3473
  fg: foreground,
2468
3474
  bg: background,
2469
- attributes: TextAttributes5.BOLD,
3475
+ attributes: TextAttributes7.BOLD,
2470
3476
  selectable: false,
2471
3477
  wrapMode: "none",
2472
3478
  truncate: true,
@@ -2487,11 +3493,11 @@ var SectionBanner = class extends TextRenderable4 {
2487
3493
  this.activate = activate;
2488
3494
  this.heading = title;
2489
3495
  this.focusable = true;
2490
- this.on(RenderableEvents3.FOCUSED, () => {
2491
- this.attributes = TextAttributes5.BOLD | TextAttributes5.INVERSE;
3496
+ this.on(RenderableEvents5.FOCUSED, () => {
3497
+ this.attributes = TextAttributes7.BOLD | TextAttributes7.INVERSE;
2492
3498
  });
2493
- this.on(RenderableEvents3.BLURRED, () => {
2494
- this.attributes = TextAttributes5.BOLD;
3499
+ this.on(RenderableEvents5.BLURRED, () => {
3500
+ this.attributes = TextAttributes7.BOLD;
2495
3501
  });
2496
3502
  }
2497
3503
  activate;
@@ -2511,8 +3517,8 @@ var SectionBanner = class extends TextRenderable4 {
2511
3517
  if (this.plainText !== next) this.content = next;
2512
3518
  }
2513
3519
  };
2514
- var TelemetryRow = class extends TextRenderable4 {
2515
- constructor(renderer2, label, id, reserved = 12) {
3520
+ var TelemetryRow = class extends TextRenderable6 {
3521
+ constructor(renderer2, label2, id, reserved = 12) {
2516
3522
  super(renderer2, {
2517
3523
  id,
2518
3524
  content: "",
@@ -2525,7 +3531,7 @@ var TelemetryRow = class extends TextRenderable4 {
2525
3531
  truncate: true
2526
3532
  });
2527
3533
  this.reserved = reserved;
2528
- this.label = label;
3534
+ this.label = label2;
2529
3535
  }
2530
3536
  reserved;
2531
3537
  label;
@@ -2534,8 +3540,8 @@ var TelemetryRow = class extends TextRenderable4 {
2534
3540
  super.onResize(width, height);
2535
3541
  this.refresh();
2536
3542
  }
2537
- update(value, label = this.label) {
2538
- this.label = label;
3543
+ update(value, label2 = this.label) {
3544
+ this.label = label2;
2539
3545
  this.value = value;
2540
3546
  this.refresh();
2541
3547
  }
@@ -2550,14 +3556,14 @@ var TelemetryRow = class extends TextRenderable4 {
2550
3556
  }
2551
3557
  };
2552
3558
  var SignalMeter = class extends TelemetryRow {
2553
- constructor(renderer2, label, id) {
2554
- super(renderer2, label, id, 18);
3559
+ constructor(renderer2, label2, id) {
3560
+ super(renderer2, label2, id, 18);
2555
3561
  }
2556
3562
  updateReading(value, maximum) {
2557
3563
  this.update(formatSignalMeter(value, maximum));
2558
3564
  }
2559
3565
  };
2560
- var InstrumentDivider = class extends TextRenderable4 {
3566
+ var InstrumentDivider = class extends TextRenderable6 {
2561
3567
  constructor(renderer2, actions) {
2562
3568
  super(renderer2, {
2563
3569
  id: "omnius-instrument-divider",
@@ -2571,14 +3577,14 @@ var InstrumentDivider = class extends TextRenderable4 {
2571
3577
  bg: background,
2572
3578
  selectable: false,
2573
3579
  wrapMode: "none",
2574
- attributes: TextAttributes5.DIM,
3580
+ attributes: TextAttributes7.DIM,
2575
3581
  onMouseDown: (event) => {
2576
3582
  if (event.button !== 0) return;
2577
3583
  this.held = true;
2578
3584
  this.moved = false;
2579
3585
  this.startX = event.x;
2580
3586
  this.actions.start?.();
2581
- this.attributes = TextAttributes5.BOLD;
3587
+ this.attributes = TextAttributes7.BOLD;
2582
3588
  event.preventDefault();
2583
3589
  event.stopPropagation();
2584
3590
  },
@@ -2592,10 +3598,10 @@ var InstrumentDivider = class extends TextRenderable4 {
2592
3598
  this.handleRelease(event);
2593
3599
  },
2594
3600
  onMouseOver: () => {
2595
- this.attributes = TextAttributes5.BOLD;
3601
+ this.attributes = TextAttributes7.BOLD;
2596
3602
  },
2597
3603
  onMouseOut: () => {
2598
- if (!this.held) this.attributes = this.focused ? TextAttributes5.INVERSE : TextAttributes5.DIM;
3604
+ if (!this.held) this.attributes = this.focused ? TextAttributes7.INVERSE : TextAttributes7.DIM;
2599
3605
  },
2600
3606
  onKeyDown: (key) => {
2601
3607
  if (key.eventType === "release") return;
@@ -2608,11 +3614,11 @@ var InstrumentDivider = class extends TextRenderable4 {
2608
3614
  });
2609
3615
  this.actions = actions;
2610
3616
  this.focusable = true;
2611
- this.on(RenderableEvents3.FOCUSED, () => {
2612
- this.attributes = TextAttributes5.INVERSE;
3617
+ this.on(RenderableEvents5.FOCUSED, () => {
3618
+ this.attributes = TextAttributes7.INVERSE;
2613
3619
  });
2614
- this.on(RenderableEvents3.BLURRED, () => {
2615
- this.attributes = TextAttributes5.DIM;
3620
+ this.on(RenderableEvents5.BLURRED, () => {
3621
+ this.attributes = TextAttributes7.DIM;
2616
3622
  });
2617
3623
  }
2618
3624
  actions;
@@ -2646,28 +3652,28 @@ var InstrumentDivider = class extends TextRenderable4 {
2646
3652
  const text = rows.join("\n");
2647
3653
  if (this.plainText !== text) this.content = text;
2648
3654
  }
2649
- release(column) {
2650
- if (this.moved) this.actions.resize(column);
3655
+ release(column3) {
3656
+ if (this.moved) this.actions.resize(column3);
2651
3657
  else this.actions.toggle();
2652
3658
  this.held = false;
2653
3659
  this.actions.finish?.();
2654
- this.attributes = this.focused ? TextAttributes5.INVERSE : TextAttributes5.DIM;
3660
+ this.attributes = this.focused ? TextAttributes7.INVERSE : TextAttributes7.DIM;
2655
3661
  }
2656
3662
  };
2657
- var DeviceMonitor = class extends BoxRenderable5 {
3663
+ var DeviceMonitor = class extends BoxRenderable7 {
2658
3664
  constructor(renderer2, action) {
2659
3665
  super(renderer2, { id: "omnius-devices", width: "100%", height: 5, minHeight: 5, maxHeight: "60%", flexShrink: 1, flexDirection: "column", visible: false });
2660
3666
  this.action = action;
2661
3667
  this.heading = new SectionBanner(renderer2, "DEVICES", "omnius-devices:heading", () => this.toggle());
2662
3668
  this.heading.update("DEVICES", false);
2663
3669
  this.add(this.heading);
2664
- this.summary = new TextRenderable4(renderer2, { id: "omnius-devices:summary", content: "--", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
3670
+ this.summary = new TextRenderable6(renderer2, { id: "omnius-devices:summary", content: "--", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
2665
3671
  this.add(this.summary);
2666
- this.compactLoad = new TextRenderable4(renderer2, { id: "omnius-devices:load-history", content: "", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
2667
- this.compactMemory = new TextRenderable4(renderer2, { id: "omnius-devices:memory-history", content: "", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
3672
+ this.compactLoad = new TextRenderable6(renderer2, { id: "omnius-devices:load-history", content: "", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
3673
+ this.compactMemory = new TextRenderable6(renderer2, { id: "omnius-devices:memory-history", content: "", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
2668
3674
  this.add(this.compactLoad);
2669
3675
  this.add(this.compactMemory);
2670
- this.scroll = new ScrollBoxRenderable3(renderer2, {
3676
+ this.scroll = new ScrollBoxRenderable5(renderer2, {
2671
3677
  id: "omnius-devices:scroll",
2672
3678
  width: "100%",
2673
3679
  flexGrow: 1,
@@ -2682,7 +3688,7 @@ var DeviceMonitor = class extends BoxRenderable5 {
2682
3688
  contentOptions: { flexDirection: "column" }
2683
3689
  });
2684
3690
  this.add(this.scroll);
2685
- this.notes = new TextRenderable4(renderer2, {
3691
+ this.notes = new TextRenderable6(renderer2, {
2686
3692
  id: "omnius-devices:notes",
2687
3693
  content: "",
2688
3694
  width: "100%",
@@ -2694,7 +3700,7 @@ var DeviceMonitor = class extends BoxRenderable5 {
2694
3700
  truncate: true
2695
3701
  });
2696
3702
  this.scroll.add(this.notes);
2697
- const controls = new BoxRenderable5(renderer2, { id: "omnius-devices:controls", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2 });
3703
+ const controls = new BoxRenderable7(renderer2, { id: "omnius-devices:controls", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2 });
2698
3704
  this.add(controls);
2699
3705
  this.policy = this.button(renderer2, "omnius-devices:policy", "GPU POLICY", () => {
2700
3706
  if (this.canSelect()) this.action?.("/gpu");
@@ -2717,10 +3723,10 @@ var DeviceMonitor = class extends BoxRenderable5 {
2717
3723
  snapshot;
2718
3724
  historySource = "";
2719
3725
  rows = /* @__PURE__ */ new Map();
2720
- button(renderer2, id, label, activate) {
2721
- const button = new TextRenderable4(renderer2, {
3726
+ button(renderer2, id, label2, activate) {
3727
+ const button = new TextRenderable6(renderer2, {
2722
3728
  id,
2723
- content: label,
3729
+ content: label2,
2724
3730
  height: 1,
2725
3731
  flexShrink: 0,
2726
3732
  fg: foreground,
@@ -2745,11 +3751,11 @@ var DeviceMonitor = class extends BoxRenderable5 {
2745
3751
  }
2746
3752
  });
2747
3753
  button.focusable = Boolean(this.action);
2748
- button.on(RenderableEvents3.FOCUSED, () => {
2749
- button.attributes = TextAttributes5.INVERSE;
3754
+ button.on(RenderableEvents5.FOCUSED, () => {
3755
+ button.attributes = TextAttributes7.INVERSE;
2750
3756
  });
2751
- button.on(RenderableEvents3.BLURRED, () => {
2752
- button.attributes = button.focusable ? 0 : TextAttributes5.DIM;
3757
+ button.on(RenderableEvents5.BLURRED, () => {
3758
+ button.attributes = button.focusable ? 0 : TextAttributes7.DIM;
2753
3759
  });
2754
3760
  return button;
2755
3761
  }
@@ -2771,7 +3777,7 @@ var DeviceMonitor = class extends BoxRenderable5 {
2771
3777
  if (this.policy.focused && !allowed) this.heading.focus();
2772
3778
  this.policy.focusable = allowed;
2773
3779
  this.policy.content = snapshot?.selectionLocked ? "POLICY LOCKED" : "GPU POLICY";
2774
- this.policy.attributes = allowed ? this.policy.focused ? TextAttributes5.INVERSE : 0 : TextAttributes5.DIM;
3780
+ this.policy.attributes = allowed ? this.policy.focused ? TextAttributes7.INVERSE : 0 : TextAttributes7.DIM;
2775
3781
  const keep = new Set(snapshot?.devices.map((device) => device.uuid) ?? []);
2776
3782
  for (const [uuid, row] of this.rows) if (!keep.has(uuid)) {
2777
3783
  if (row.title.focused) this.heading.focus();
@@ -2781,7 +3787,7 @@ var DeviceMonitor = class extends BoxRenderable5 {
2781
3787
  for (const device of snapshot?.devices ?? []) {
2782
3788
  let row = this.rows.get(device.uuid);
2783
3789
  if (!row) {
2784
- const root = new BoxRenderable5(this._ctx, {
3790
+ const root = new BoxRenderable7(this._ctx, {
2785
3791
  id: `omnius-device:${device.uuid}`,
2786
3792
  width: "100%",
2787
3793
  flexDirection: "column",
@@ -2797,19 +3803,19 @@ var DeviceMonitor = class extends BoxRenderable5 {
2797
3803
  if (current && this.canSelectDevice(current)) this.action?.(`/gpu select ${current.uuid}`);
2798
3804
  });
2799
3805
  title.width = "100%";
2800
- title.on(RenderableEvents3.FOCUSED, () => this.scroll.scrollChildIntoView(root.id));
3806
+ title.on(RenderableEvents5.FOCUSED, () => this.scroll.scrollChildIntoView(root.id));
2801
3807
  const load = new TelemetryRow(this._ctx, "LOAD", `${root.id}:load`, 16);
2802
3808
  const memory = new TelemetryRow(this._ctx, "VRAM", `${root.id}:memory`, 16);
2803
- const plot = (name) => new TextRenderable4(this._ctx, { id: `${root.id}:${name}-history`, content: "", width: "100%", height: 3, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true, selectable: false });
3809
+ const plot = (name) => new TextRenderable6(this._ctx, { id: `${root.id}:${name}-history`, content: "", width: "100%", height: 3, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true, selectable: false });
2804
3810
  const loadGraph = plot("load"), memoryGraph = plot("memory"), history = new DeviceHistory();
2805
- const reason = new TextRenderable4(this._ctx, {
3811
+ const reason = new TextRenderable6(this._ctx, {
2806
3812
  id: `${root.id}:reason`,
2807
3813
  content: "",
2808
3814
  width: "100%",
2809
3815
  height: 1,
2810
3816
  fg: foreground,
2811
3817
  bg: background,
2812
- attributes: TextAttributes5.DIM,
3818
+ attributes: TextAttributes7.DIM,
2813
3819
  wrapMode: "none",
2814
3820
  truncate: true,
2815
3821
  visible: false
@@ -2832,7 +3838,7 @@ var DeviceMonitor = class extends BoxRenderable5 {
2832
3838
  const selectable = this.canSelectDevice(device);
2833
3839
  if (row.title.focused && !selectable) this.heading.focus();
2834
3840
  row.title.focusable = selectable;
2835
- row.title.attributes = row.title.focused ? TextAttributes5.INVERSE : device.preferred ? TextAttributes5.BOLD : selectable ? 0 : TextAttributes5.DIM;
3841
+ row.title.attributes = row.title.focused ? TextAttributes7.INVERSE : device.preferred ? TextAttributes7.BOLD : selectable ? 0 : TextAttributes7.DIM;
2836
3842
  row.load.update(formatSignalMeter(device.utilization, 100, 6));
2837
3843
  const used = device.memoryUsedMB === void 0 ? "--" : instrumentNumber(device.memoryUsedMB / 1024, 1);
2838
3844
  const total = device.memoryTotalMB === void 0 || device.memoryTotalMB <= 0 ? "--" : instrumentNumber(device.memoryTotalMB / 1024, 1);
@@ -2885,10 +3891,10 @@ var DeviceMonitor = class extends BoxRenderable5 {
2885
3891
  ].filter(Boolean).join(" · ");
2886
3892
  const primary = devices.find((device) => device.preferred) ?? devices.find((device) => device.enabled) ?? devices[0];
2887
3893
  const compactHistory = primary ? this.rows.get(primary.uuid)?.history.samples ?? [] : [];
2888
- for (const [element, field, label] of [[this.compactLoad, "load", "UTIL"], [this.compactMemory, "memory", primary?.unifiedMemory ? "UMA" : "VRAM"]]) {
3894
+ for (const [element, field, label2] of [[this.compactLoad, "load", "UTIL"], [this.compactMemory, "memory", primary?.unifiedMemory ? "UMA" : "VRAM"]]) {
2889
3895
  const current = primary ? field === "load" ? primary.utilization : primary.memoryUsedMB !== void 0 && primary.memoryTotalMB ? primary.memoryUsedMB / primary.memoryTotalMB * 100 : void 0 : void 0;
2890
3896
  const value = instrumentNumber(current, 0, "%");
2891
- const caption = `${label}${primary?.index ?? "-"}`;
3897
+ const caption = `${label2}${primary?.index ?? "-"}`;
2892
3898
  const plotWidth = Math.max(0, this.width - caption.length - value.length - 2);
2893
3899
  const next = `${caption} ${deviceHistorySparkline(compactHistory, field, plotWidth)} ${value}`;
2894
3900
  if (element.plainText !== next) element.content = next;
@@ -2913,7 +3919,7 @@ var DeviceMonitor = class extends BoxRenderable5 {
2913
3919
  ];
2914
3920
  }
2915
3921
  };
2916
- var ChannelMap = class extends BoxRenderable5 {
3922
+ var ChannelMap = class extends BoxRenderable7 {
2917
3923
  constructor(renderer2, id, inspect, reveal) {
2918
3924
  super(renderer2, {
2919
3925
  id,
@@ -2945,7 +3951,7 @@ var ChannelMap = class extends BoxRenderable5 {
2945
3951
  if (!this.channels.has(agent.id))
2946
3952
  this.channels.set(agent.id, this.channels.size + 1);
2947
3953
  if (!this.rows.has(agent.id)) {
2948
- const row = new TextRenderable4(this._ctx, {
3954
+ const row = new TextRenderable6(this._ctx, {
2949
3955
  id: `${this.id}:channel:${agent.id}`,
2950
3956
  content: "",
2951
3957
  width: "100%",
@@ -2977,11 +3983,11 @@ var ChannelMap = class extends BoxRenderable5 {
2977
3983
  }
2978
3984
  });
2979
3985
  row.focusable = !!this.inspect;
2980
- row.on(RenderableEvents3.FOCUSED, () => {
2981
- row.attributes = TextAttributes5.INVERSE;
3986
+ row.on(RenderableEvents5.FOCUSED, () => {
3987
+ row.attributes = TextAttributes7.INVERSE;
2982
3988
  this.reveal?.(row);
2983
3989
  });
2984
- row.on(RenderableEvents3.BLURRED, () => {
3990
+ row.on(RenderableEvents5.BLURRED, () => {
2985
3991
  row.attributes = 0;
2986
3992
  });
2987
3993
  this.rows.set(agent.id, row);
@@ -3011,7 +4017,9 @@ var ChannelMap = class extends BoxRenderable5 {
3011
4017
  }
3012
4018
  }
3013
4019
  };
3014
- var InstrumentRail = class extends BoxRenderable5 {
4020
+ var InstrumentRail = class extends BoxRenderable7 {
4021
+ workQueue;
4022
+ taskNotes;
3015
4023
  scroll;
3016
4024
  inferenceHeader;
3017
4025
  sessionHeader;
@@ -3040,7 +4048,7 @@ var InstrumentRail = class extends BoxRenderable5 {
3040
4048
  flexGrow: 1,
3041
4049
  flexShrink: 1
3042
4050
  });
3043
- this.scroll = new ScrollBoxRenderable3(renderer2, {
4051
+ this.scroll = new ScrollBoxRenderable5(renderer2, {
3044
4052
  id: `${id}:scroll`,
3045
4053
  width: "100%",
3046
4054
  flexGrow: 1,
@@ -3054,6 +4062,31 @@ var InstrumentRail = class extends BoxRenderable5 {
3054
4062
  contentOptions: { flexDirection: "column", paddingRight: 1 }
3055
4063
  });
3056
4064
  this.add(this.scroll);
4065
+ const colors = options.colors ?? {
4066
+ foreground,
4067
+ background,
4068
+ accent: foreground,
4069
+ dim: foreground,
4070
+ border: foreground,
4071
+ warning: foreground,
4072
+ error: foreground,
4073
+ success: foreground,
4074
+ selection: background
4075
+ };
4076
+ this.workQueue = new NativeWorkQueueView(renderer2, colors, options.onWorkQueueAction, (target) => this.reveal(target));
4077
+ this.scroll.add(this.workQueue);
4078
+ this.taskNotes = new NativeTaskNotesView(renderer2, options.colors ?? {
4079
+ foreground,
4080
+ background,
4081
+ accent: foreground,
4082
+ dim: foreground,
4083
+ border: foreground,
4084
+ warning: foreground,
4085
+ error: foreground,
4086
+ success: foreground,
4087
+ selection: background
4088
+ }, (target) => this.reveal(target));
4089
+ this.scroll.add(this.taskNotes);
3057
4090
  this.inferenceHeader = new SectionBanner(
3058
4091
  renderer2,
3059
4092
  "INFERENCE",
@@ -3061,26 +4094,26 @@ var InstrumentRail = class extends BoxRenderable5 {
3061
4094
  () => this.toggleSection("inference")
3062
4095
  );
3063
4096
  this.inferenceHeader.on(
3064
- RenderableEvents3.FOCUSED,
4097
+ RenderableEvents5.FOCUSED,
3065
4098
  () => this.reveal(this.inferenceHeader)
3066
4099
  );
3067
4100
  this.scroll.add(this.inferenceHeader);
3068
- this.inference = new BoxRenderable5(renderer2, {
4101
+ this.inference = new BoxRenderable7(renderer2, {
3069
4102
  id: `${id}:inference-body`,
3070
4103
  width: "100%",
3071
4104
  flexDirection: "column",
3072
4105
  flexShrink: 0
3073
4106
  });
3074
4107
  this.scroll.add(this.inference);
3075
- const addRow = (parent, key, label, reserved = 12) => {
3076
- const row = new TelemetryRow(renderer2, label, `${id}:${key}`, reserved);
4108
+ const addRow = (parent, key, label2, reserved = 12) => {
4109
+ const row = new TelemetryRow(renderer2, label2, `${id}:${key}`, reserved);
3077
4110
  this.rows.set(key, row);
3078
4111
  parent.add(row);
3079
4112
  return row;
3080
4113
  };
3081
4114
  addRow(this.inference, "route", "ROUTE");
3082
4115
  addRow(this.inference, "backend", "BACKEND");
3083
- this.model = new TextRenderable4(renderer2, {
4116
+ this.model = new TextRenderable6(renderer2, {
3084
4117
  id: `${id}:model`,
3085
4118
  content: "MODEL --",
3086
4119
  width: "100%",
@@ -3107,9 +4140,9 @@ var InstrumentRail = class extends BoxRenderable5 {
3107
4140
  this.contextDetails.visible = !this.contextDetails.visible;
3108
4141
  this.contextHeader.update("CONTEXT DETAILS", this.contextDetails.visible);
3109
4142
  });
3110
- this.contextHeader.on(RenderableEvents3.FOCUSED, () => this.reveal(this.contextHeader));
4143
+ this.contextHeader.on(RenderableEvents5.FOCUSED, () => this.reveal(this.contextHeader));
3111
4144
  this.inference.add(this.contextHeader);
3112
- this.contextDetails = new BoxRenderable5(renderer2, { id: `${id}:context-detail-body`, width: "100%", flexDirection: "column", flexShrink: 0, visible: false });
4145
+ this.contextDetails = new BoxRenderable7(renderer2, { id: `${id}:context-detail-body`, width: "100%", flexDirection: "column", flexShrink: 0, visible: false });
3113
4146
  this.inference.add(this.contextDetails);
3114
4147
  this.contextHeader.update("CONTEXT DETAILS", false);
3115
4148
  addRow(this.contextDetails, "messages", "MESSAGES");
@@ -3124,11 +4157,11 @@ var InstrumentRail = class extends BoxRenderable5 {
3124
4157
  () => this.toggleSection("session")
3125
4158
  );
3126
4159
  this.sessionHeader.on(
3127
- RenderableEvents3.FOCUSED,
4160
+ RenderableEvents5.FOCUSED,
3128
4161
  () => this.reveal(this.sessionHeader)
3129
4162
  );
3130
4163
  this.scroll.add(this.sessionHeader);
3131
- this.session = new BoxRenderable5(renderer2, {
4164
+ this.session = new BoxRenderable7(renderer2, {
3132
4165
  id: `${id}:session-body`,
3133
4166
  width: "100%",
3134
4167
  flexDirection: "column",
@@ -3155,6 +4188,8 @@ var InstrumentRail = class extends BoxRenderable5 {
3155
4188
  if (options.colors) this.applyTheme(options.colors);
3156
4189
  }
3157
4190
  update(state) {
4191
+ this.workQueue.update(state.workQueue);
4192
+ this.taskNotes.update(state.taskNotes);
3158
4193
  const data = state.instruments;
3159
4194
  const inference = data?.inference;
3160
4195
  const session = data?.session;
@@ -3211,13 +4246,15 @@ var InstrumentRail = class extends BoxRenderable5 {
3211
4246
  applyTheme(colors) {
3212
4247
  this.backgroundColor = colors.background;
3213
4248
  const visit = (node) => {
3214
- if (node instanceof TextRenderable4) {
4249
+ if (node instanceof TextRenderable6) {
3215
4250
  node.fg = colors.foreground;
3216
4251
  node.bg = colors.background;
3217
4252
  }
3218
4253
  for (const child of node.getChildren()) visit(child);
3219
4254
  };
3220
4255
  visit(this);
4256
+ this.workQueue.applyTheme(colors);
4257
+ this.taskNotes.applyTheme(colors);
3221
4258
  styleNativeScrollbars(this.scroll, colors);
3222
4259
  styleNativeScrollbars(this.devices.scroll, colors);
3223
4260
  }
@@ -3237,10 +4274,14 @@ var InstrumentRail = class extends BoxRenderable5 {
3237
4274
  context: this.contextHeader.expanded,
3238
4275
  devices: this.devices.isExpanded,
3239
4276
  scrollTop: this.scroll.scrollTop,
3240
- deviceScrollTop: this.devices.scroll.scrollTop
4277
+ deviceScrollTop: this.devices.scroll.scrollTop,
4278
+ taskNotes: this.taskNotes.capturePresentation(),
4279
+ workQueue: this.workQueue.capturePresentation()
3241
4280
  };
3242
4281
  }
3243
4282
  restorePresentation(state) {
4283
+ this.workQueue.restorePresentation(state.workQueue);
4284
+ this.taskNotes.restorePresentation(state.taskNotes);
3244
4285
  if (this.inference.visible !== state.inference) this.toggleSection("inference");
3245
4286
  if (this.session.visible !== state.session) this.toggleSection("session");
3246
4287
  this.contextHeader.update("CONTEXT DETAILS", state.context);
@@ -3252,6 +4293,8 @@ var InstrumentRail = class extends BoxRenderable5 {
3252
4293
  focusTargets() {
3253
4294
  if (!this.visible) return [];
3254
4295
  return [
4296
+ ...this.workQueue.focusTargets(),
4297
+ ...this.taskNotes.focusTargets(),
3255
4298
  this.inferenceHeader,
3256
4299
  ...this.inference.visible && this.contextHeader.visible ? [this.contextHeader] : [],
3257
4300
  this.sessionHeader,
@@ -4708,14 +5751,14 @@ var VimComposer = class {
4708
5751
  };
4709
5752
 
4710
5753
  // packages/cli/src/tui/native/components/selection-menu.ts
4711
- import { BoxRenderable as BoxRenderable6, CliRenderEvents as CliRenderEvents3, TextAttributes as TextAttributes6, TextRenderable as TextRenderable5 } from "@opentui/core";
5754
+ import { BoxRenderable as BoxRenderable8, CliRenderEvents as CliRenderEvents5, TextAttributes as TextAttributes8, TextRenderable as TextRenderable7 } from "@opentui/core";
4712
5755
  var NativeSelectionMenu = class {
4713
5756
  constructor(renderer2, colors, copy, restoreFocus) {
4714
5757
  this.renderer = renderer2;
4715
5758
  this.colors = colors;
4716
5759
  this.copy = copy;
4717
5760
  this.restoreFocus = restoreFocus;
4718
- renderer2.on(CliRenderEvents3.RESIZE, this.position);
5761
+ renderer2.on(CliRenderEvents5.RESIZE, this.position);
4719
5762
  }
4720
5763
  renderer;
4721
5764
  colors;
@@ -4736,7 +5779,7 @@ var NativeSelectionMenu = class {
4736
5779
  this.selectedText = text;
4737
5780
  this.anchor = { x, y };
4738
5781
  this.previousFocus = this.renderer.currentFocusedRenderable;
4739
- this.overlay = new BoxRenderable6(this.renderer, {
5782
+ this.overlay = new BoxRenderable8(this.renderer, {
4740
5783
  id: "omnius-selection-menu",
4741
5784
  position: "absolute",
4742
5785
  left: 0,
@@ -4752,7 +5795,7 @@ var NativeSelectionMenu = class {
4752
5795
  event.stopPropagation();
4753
5796
  }
4754
5797
  });
4755
- this.panel = new BoxRenderable6(this.renderer, {
5798
+ this.panel = new BoxRenderable8(this.renderer, {
4756
5799
  id: "omnius-selection-menu-panel",
4757
5800
  position: "absolute",
4758
5801
  width: 14,
@@ -4766,7 +5809,7 @@ var NativeSelectionMenu = class {
4766
5809
  event.stopPropagation();
4767
5810
  }
4768
5811
  });
4769
- const action = new TextRenderable5(this.renderer, {
5812
+ const action = new TextRenderable7(this.renderer, {
4770
5813
  id: "omnius-selection-copy",
4771
5814
  content: "COPY",
4772
5815
  height: 1,
@@ -4774,7 +5817,7 @@ var NativeSelectionMenu = class {
4774
5817
  selectable: false,
4775
5818
  fg: this.colors.foreground,
4776
5819
  bg: this.colors.background,
4777
- attributes: TextAttributes6.BOLD | TextAttributes6.INVERSE,
5820
+ attributes: TextAttributes8.BOLD | TextAttributes8.INVERSE,
4778
5821
  onMouseDown: (event) => {
4779
5822
  if (event.button === 0) this.confirm();
4780
5823
  event.preventDefault();
@@ -4815,7 +5858,7 @@ var NativeSelectionMenu = class {
4815
5858
  if (!this.panel) return;
4816
5859
  this.panel.backgroundColor = colors.background;
4817
5860
  this.frame?.setColors(colors);
4818
- for (const child of this.panel.getChildren()) if (child instanceof TextRenderable5) {
5861
+ for (const child of this.panel.getChildren()) if (child instanceof TextRenderable7) {
4819
5862
  child.fg = colors.foreground;
4820
5863
  child.bg = colors.background;
4821
5864
  }
@@ -4836,13 +5879,13 @@ var NativeSelectionMenu = class {
4836
5879
  }
4837
5880
  destroy() {
4838
5881
  this.close();
4839
- this.renderer.off(CliRenderEvents3.RESIZE, this.position);
5882
+ this.renderer.off(CliRenderEvents5.RESIZE, this.position);
4840
5883
  }
4841
5884
  };
4842
5885
 
4843
5886
  // packages/cli/src/tui/native/components/tab-strip.ts
4844
- import { BoxRenderable as BoxRenderable7, CliRenderEvents as CliRenderEvents4, ScrollBoxRenderable as ScrollBoxRenderable4, SliderRenderable, TextAttributes as TextAttributes7, TextRenderable as TextRenderable6 } from "@opentui/core";
4845
- var NativeTabStrip = class extends BoxRenderable7 {
5887
+ import { BoxRenderable as BoxRenderable9, CliRenderEvents as CliRenderEvents6, ScrollBoxRenderable as ScrollBoxRenderable6, SliderRenderable, TextAttributes as TextAttributes9, TextRenderable as TextRenderable8 } from "@opentui/core";
5888
+ var NativeTabStrip = class extends BoxRenderable9 {
4846
5889
  constructor(renderer2, options) {
4847
5890
  super(renderer2, {
4848
5891
  id: options.id,
@@ -4858,7 +5901,7 @@ var NativeTabStrip = class extends BoxRenderable7 {
4858
5901
  this.renderer = renderer2;
4859
5902
  this.options = options;
4860
5903
  this.colors = options.colors;
4861
- this.scroll = new ScrollBoxRenderable4(renderer2, {
5904
+ this.scroll = new ScrollBoxRenderable6(renderer2, {
4862
5905
  id: `${options.id}:scroll`,
4863
5906
  height: 1,
4864
5907
  minHeight: 1,
@@ -4896,7 +5939,7 @@ var NativeTabStrip = class extends BoxRenderable7 {
4896
5939
  this.rail.focusable = false;
4897
5940
  this.add(this.rail);
4898
5941
  styleNativeSlider(this.rail, this.colors);
4899
- renderer2.on(CliRenderEvents4.FRAME, this.syncScroll);
5942
+ renderer2.on(CliRenderEvents6.FRAME, this.syncScroll);
4900
5943
  }
4901
5944
  renderer;
4902
5945
  options;
@@ -4913,15 +5956,19 @@ var NativeTabStrip = class extends BoxRenderable7 {
4913
5956
  const signature = JSON.stringify([items, activeId, busy]);
4914
5957
  if (signature === this.signature) return;
4915
5958
  this.signature = signature;
5959
+ const previousFocus = this.renderer.currentFocusedRenderable;
5960
+ const ownedFocus = Boolean(previousFocus) && [...this.buttons.values()].some((entry) => previousFocus === entry.button || previousFocus === entry.close);
4916
5961
  const ids = new Set(items.map((item) => item.id));
4917
5962
  for (const [id, entry] of this.buttons) if (!ids.has(id)) {
4918
5963
  entry.button.destroy();
5964
+ entry.close?.destroy();
4919
5965
  this.buttons.delete(id);
4920
5966
  }
4921
- for (const [index, action] of items.entries()) {
5967
+ const controls = [];
5968
+ for (const action of items) {
4922
5969
  let entry = this.buttons.get(action.id);
4923
5970
  if (!entry) {
4924
- const button = new TextRenderable6(this.renderer, {
5971
+ const button = new TextRenderable8(this.renderer, {
4925
5972
  id: `${this.options.prefix}:${action.id}`,
4926
5973
  content: "",
4927
5974
  height: 1,
@@ -4948,35 +5995,73 @@ var NativeTabStrip = class extends BoxRenderable7 {
4948
5995
  this.reveal = button.id;
4949
5996
  });
4950
5997
  button.on("blurred", () => this.style(entry));
5998
+ if (this.options.close) {
5999
+ const close2 = new TextRenderable8(this.renderer, {
6000
+ id: `${this.options.prefix}-close:${action.id}`,
6001
+ content: "×",
6002
+ width: 1,
6003
+ height: 1,
6004
+ flexShrink: 0,
6005
+ wrapMode: "none",
6006
+ selectable: false,
6007
+ fg: this.colors.foreground,
6008
+ bg: this.colors.background,
6009
+ onMouseDown: (event) => {
6010
+ if (event.button === 0 && !entry.blocked) {
6011
+ close2.focus();
6012
+ this.options.close(entry.action.id);
6013
+ }
6014
+ event.preventDefault();
6015
+ event.stopPropagation();
6016
+ },
6017
+ onKeyDown: (key) => this.handleKey(entry, key, true)
6018
+ });
6019
+ entry.close = close2;
6020
+ close2.on("focused", () => {
6021
+ this.style(entry);
6022
+ this.scroll.scrollChildIntoView(close2.id);
6023
+ this.reveal = close2.id;
6024
+ });
6025
+ close2.on("blurred", () => this.style(entry));
6026
+ }
4951
6027
  }
4952
6028
  entry.action = action;
4953
6029
  entry.active = action.id === activeId;
4954
6030
  entry.blocked = busy || Boolean(action.disabled);
4955
6031
  entry.button.focusable = entry.active || !entry.blocked;
4956
- const label = plainText(action.label);
4957
- const content = ` ${label} `;
6032
+ if (entry.close) entry.close.focusable = !entry.blocked;
6033
+ const label2 = plainText(action.label);
6034
+ const content = ` ${label2} `;
4958
6035
  if (entry.button.plainText !== content) entry.button.content = content;
4959
6036
  this.style(entry);
4960
- if (this.scroll.getChildren()[index] !== entry.button) this.scroll.add(entry.button, index);
6037
+ controls.push(entry.button);
6038
+ if (entry.close) controls.push(entry.close);
4961
6039
  }
4962
- this.naturalWidth = Array.from(this.buttons.values()).reduce((width, entry) => width + terminalCellWidth(entry.button.plainText), 0) + Math.max(0, items.length - 1);
4963
- const focused = this.renderer.currentFocusedRenderable;
4964
- if (focused && !focused.focusable && Array.from(this.buttons.values()).some((entry) => entry.button === focused)) this.buttons.get(activeId)?.button.focus();
6040
+ for (const [index, control] of controls.entries()) if (this.scroll.getChildren()[index] !== control) this.scroll.add(control, index);
6041
+ this.naturalWidth = controls.reduce((width, control) => width + terminalCellWidth(control.plainText), 0) + Math.max(0, controls.length - 1);
6042
+ if (ownedFocus && (!previousFocus || previousFocus.isDestroyed || !previousFocus.focusable))
6043
+ (this.buttons.get(activeId)?.button ?? controls.find((control) => control.focusable))?.focus();
4965
6044
  if (activeId !== this.activeId) this.reveal = `${this.options.prefix}:${activeId}`;
4966
6045
  this.activeId = activeId;
4967
6046
  this.renderer.requestRender();
4968
6047
  }
4969
6048
  style(entry) {
4970
- entry.button.attributes = (entry.active ? TextAttributes7.BOLD | TextAttributes7.UNDERLINE : entry.blocked ? TextAttributes7.DIM : 0) | (entry.button.focused ? TextAttributes7.INVERSE : 0);
6049
+ entry.button.attributes = (entry.active ? TextAttributes9.BOLD | TextAttributes9.UNDERLINE : entry.blocked ? TextAttributes9.DIM : 0) | (entry.button.focused ? TextAttributes9.INVERSE : 0);
6050
+ if (entry.close) entry.close.attributes = (entry.blocked || !entry.close.focused ? TextAttributes9.DIM : 0) | (entry.close.focused ? TextAttributes9.INVERSE : 0);
4971
6051
  }
4972
- handleKey(entry, key) {
6052
+ handleKey(entry, key, close2 = false) {
4973
6053
  if (key.eventType === "release") return;
4974
6054
  if (key.name === "return" || key.sequence === " ") {
4975
- if (!entry.blocked) this.options.activate(entry.action.id);
6055
+ if (!entry.blocked) {
6056
+ if (close2) this.options.close?.(entry.action.id);
6057
+ else this.options.activate(entry.action.id);
6058
+ }
6059
+ } else if (this.options.close && (key.name === "delete" || key.ctrl && key.name.toLowerCase() === "w")) {
6060
+ if (!entry.blocked) this.options.close(entry.action.id);
4976
6061
  } else if (["left", "right", "home", "end"].includes(key.name)) {
4977
- const targets = this.scroll.getChildren().filter((button) => button.focusable);
6062
+ const targets = this.scroll.getChildren().filter((button) => button.focusable && button.id.startsWith(`${this.options.prefix}:`));
4978
6063
  const index = targets.indexOf(entry.button);
4979
- const next = key.name === "home" ? 0 : key.name === "end" ? targets.length - 1 : (index + (key.name === "left" ? -1 : 1) + targets.length) % targets.length;
6064
+ const next = key.name === "home" ? 0 : key.name === "end" ? targets.length - 1 : (index + (key.name === "left" ? close2 ? 0 : -1 : 1) + targets.length) % targets.length;
4980
6065
  targets[next]?.focus();
4981
6066
  } else return;
4982
6067
  key.preventDefault();
@@ -5001,9 +6086,13 @@ var NativeTabStrip = class extends BoxRenderable7 {
5001
6086
  };
5002
6087
  applyTheme(colors) {
5003
6088
  this.colors = colors;
5004
- for (const { button } of this.buttons.values()) {
6089
+ for (const { button, close: close2 } of this.buttons.values()) {
5005
6090
  button.fg = colors.foreground;
5006
6091
  button.bg = colors.background;
6092
+ if (close2) {
6093
+ close2.fg = colors.foreground;
6094
+ close2.bg = colors.background;
6095
+ }
5007
6096
  }
5008
6097
  styleNativeScrollbars(this.scroll, colors);
5009
6098
  styleNativeSlider(this.rail, colors);
@@ -5013,7 +6102,7 @@ var NativeTabStrip = class extends BoxRenderable7 {
5013
6102
  this.scroll.scrollLeft = offset2;
5014
6103
  }
5015
6104
  destroySelf() {
5016
- this.renderer.off(CliRenderEvents4.FRAME, this.syncScroll);
6105
+ this.renderer.off(CliRenderEvents6.FRAME, this.syncScroll);
5017
6106
  super.destroySelf();
5018
6107
  }
5019
6108
  };
@@ -5031,7 +6120,7 @@ var NativeFrontend = class {
5031
6120
  this.selectionMenu = new NativeSelectionMenu(renderer2, colors, (text) => {
5032
6121
  void this.copy(text);
5033
6122
  }, () => this.restoreFocus());
5034
- this.root = new BoxRenderable8(renderer2, {
6123
+ this.root = new BoxRenderable10(renderer2, {
5035
6124
  id: "omnius-native",
5036
6125
  width: "100%",
5037
6126
  height: "100%",
@@ -5039,7 +6128,7 @@ var NativeFrontend = class {
5039
6128
  backgroundColor: colors.background
5040
6129
  });
5041
6130
  renderer2.root.add(this.root);
5042
- this.header = new BoxRenderable8(renderer2, {
6131
+ this.header = new BoxRenderable10(renderer2, {
5043
6132
  id: "omnius-header",
5044
6133
  width: "100%",
5045
6134
  minWidth: 0,
@@ -5060,12 +6149,12 @@ var NativeFrontend = class {
5060
6149
  this.header.y + this.header.height - 1,
5061
6150
  this.context.colors.foreground,
5062
6151
  this.context.colors.background,
5063
- TextAttributes8.DIM
6152
+ TextAttributes10.DIM
5064
6153
  );
5065
6154
  };
5066
- const headerRow = new BoxRenderable8(renderer2, { id: "omnius-header-row", width: "100%", minWidth: 0, minHeight: 1, flexDirection: "row", gap: 1 });
6155
+ const headerRow = new BoxRenderable10(renderer2, { id: "omnius-header-row", width: "100%", minWidth: 0, minHeight: 1, flexDirection: "row", gap: 1 });
5067
6156
  this.header.add(headerRow);
5068
- this.identity = new TextRenderable7(renderer2, {
6157
+ this.identity = new TextRenderable9(renderer2, {
5069
6158
  id: "omnius-identity",
5070
6159
  content: "Omnius",
5071
6160
  fg: colors.foreground,
@@ -5075,7 +6164,7 @@ var NativeFrontend = class {
5075
6164
  truncate: true,
5076
6165
  minWidth: 18,
5077
6166
  selectable: false,
5078
- attributes: TextAttributes8.BOLD,
6167
+ attributes: TextAttributes10.BOLD,
5079
6168
  onMouseDown: (event) => {
5080
6169
  if (event.button === 0) {
5081
6170
  this.toggleHeaderPanel();
@@ -5090,7 +6179,7 @@ var NativeFrontend = class {
5090
6179
  }
5091
6180
  });
5092
6181
  headerRow.add(this.identity);
5093
- this.headerActions = new ScrollBoxRenderable5(renderer2, {
6182
+ this.headerActions = new ScrollBoxRenderable7(renderer2, {
5094
6183
  id: "omnius-header-actions",
5095
6184
  flexGrow: 0,
5096
6185
  flexShrink: 1,
@@ -5103,16 +6192,16 @@ var NativeFrontend = class {
5103
6192
  verticalScrollbarOptions: { visible: false }
5104
6193
  });
5105
6194
  headerRow.add(this.headerActions);
5106
- this.headerPanel = new TextRenderable7(renderer2, { id: "omnius-header-panel", content: "", width: "100%", wrapMode: "word", visible: false });
6195
+ this.headerPanel = new TextRenderable9(renderer2, { id: "omnius-header-panel", content: "", width: "100%", wrapMode: "word", visible: false });
5107
6196
  this.header.add(this.headerPanel);
5108
- this.detailButton = new TextRenderable7(renderer2, {
6197
+ this.detailButton = new TextRenderable9(renderer2, {
5109
6198
  id: "omnius-details-toggle",
5110
6199
  content: "+ DETAILS",
5111
6200
  height: 1,
5112
6201
  width: 9,
5113
6202
  flexShrink: 0,
5114
6203
  fg: colors.foreground,
5115
- attributes: TextAttributes8.DIM,
6204
+ attributes: TextAttributes10.DIM,
5116
6205
  selectable: false,
5117
6206
  onMouseDown: (event) => {
5118
6207
  if (event.button === 0) {
@@ -5132,13 +6221,13 @@ var NativeFrontend = class {
5132
6221
  for (const control of [this.identity, this.detailButton]) {
5133
6222
  const attributes = control.attributes;
5134
6223
  control.on("focused", () => {
5135
- control.attributes = attributes | TextAttributes8.INVERSE;
6224
+ control.attributes = attributes | TextAttributes10.INVERSE;
5136
6225
  });
5137
6226
  control.on("blurred", () => {
5138
6227
  control.attributes = attributes;
5139
6228
  });
5140
6229
  }
5141
- this.sessionRow = new BoxRenderable8(renderer2, {
6230
+ this.sessionRow = new BoxRenderable10(renderer2, {
5142
6231
  id: "omnius-sessions-row",
5143
6232
  width: "100%",
5144
6233
  height: 1,
@@ -5153,10 +6242,11 @@ var NativeFrontend = class {
5153
6242
  id: "omnius-session-tabs",
5154
6243
  prefix: "session",
5155
6244
  colors,
5156
- activate: (id) => this.emitAction("session", id)
6245
+ activate: (id) => this.emitAction("session", id),
6246
+ close: (id) => this.emitAction("session-close", id)
5157
6247
  });
5158
6248
  this.sessionRow.add(this.sessions);
5159
- this.newSession = new TextRenderable7(renderer2, {
6249
+ this.newSession = new TextRenderable9(renderer2, {
5160
6250
  id: "omnius-session-new",
5161
6251
  content: "+ NEW",
5162
6252
  width: 5,
@@ -5180,21 +6270,58 @@ var NativeFrontend = class {
5180
6270
  });
5181
6271
  this.newSession.focusable = true;
5182
6272
  const styleNew = () => {
5183
- this.newSession.attributes = (this.state?.sessions?.busy ? TextAttributes8.DIM : 0) | (this.newSession.focused ? TextAttributes8.INVERSE : 0);
6273
+ this.newSession.attributes = (this.state?.sessions?.busy ? TextAttributes10.DIM : 0) | (this.newSession.focused ? TextAttributes10.INVERSE : 0);
5184
6274
  };
5185
6275
  this.newSession.on("focused", styleNew);
5186
6276
  this.newSession.on("blurred", styleNew);
5187
6277
  this.sessionRow.add(this.newSession);
5188
- this.routeWarning = new TextRenderable7(renderer2, { id: "omnius-route-warning", content: "", width: "100%", wrapMode: "word", fg: colors.warning, attributes: TextAttributes8.BOLD | TextAttributes8.UNDERLINE, visible: false, flexShrink: 0 });
6278
+ this.sessionPicker = new TextRenderable9(renderer2, {
6279
+ id: "omnius-session-picker",
6280
+ content: "SESSIONS",
6281
+ width: 8,
6282
+ height: 1,
6283
+ flexShrink: 0,
6284
+ selectable: false,
6285
+ fg: colors.foreground,
6286
+ bg: colors.background,
6287
+ onMouseDown: (event) => {
6288
+ if (event.button === 0 && !this.state?.sessions?.busy) this.emitAction("session-picker");
6289
+ event.preventDefault();
6290
+ event.stopPropagation();
6291
+ },
6292
+ onKeyDown: (key) => {
6293
+ if (key.eventType !== "release" && (key.name === "return" || key.sequence === " ")) {
6294
+ if (!this.state?.sessions?.busy) this.emitAction("session-picker");
6295
+ key.preventDefault();
6296
+ key.stopPropagation();
6297
+ }
6298
+ }
6299
+ });
6300
+ this.sessionPicker.focusable = true;
6301
+ const stylePicker = () => {
6302
+ this.sessionPicker.attributes = (this.state?.sessions?.busy ? TextAttributes10.DIM : 0) | (this.sessionPicker.focused ? TextAttributes10.INVERSE : 0);
6303
+ };
6304
+ this.sessionPicker.on("focused", stylePicker);
6305
+ this.sessionPicker.on("blurred", stylePicker);
6306
+ this.sessionRow.add(this.sessionPicker);
6307
+ this.routeWarning = new TextRenderable9(renderer2, { id: "omnius-route-warning", content: "", width: "100%", wrapMode: "word", fg: colors.warning, attributes: TextAttributes10.BOLD | TextAttributes10.UNDERLINE, visible: false, flexShrink: 0 });
5189
6308
  this.root.add(this.routeWarning);
5190
- this.taskPane = new BoxRenderable8(renderer2, { id: "omnius-tasks", width: "100%", flexDirection: "column", maxHeight: 6, flexShrink: 0, overflow: "hidden", visible: false });
6309
+ this.taskPane = new BoxRenderable10(renderer2, { id: "omnius-tasks", width: "100%", flexDirection: "column", maxHeight: 6, flexShrink: 0, overflow: "hidden", visible: false });
5191
6310
  this.tasks = new NativeBlockList(this.context, this.taskPane);
5192
6311
  this.root.add(this.taskPane);
5193
- this.body = new BoxRenderable8(renderer2, { id: "omnius-body", width: "100%", flexDirection: "row", flexGrow: 1, minHeight: 1 });
6312
+ this.taskStrip = new NativeTaskStrip(renderer2, colors, (id) => {
6313
+ if (renderer2.terminalWidth >= 110) this.detailsOpen = true;
6314
+ else this.narrowDetailsOpen = true;
6315
+ this.layoutInstruments();
6316
+ this.instruments.taskNotes.inspect(id);
6317
+ renderer2.requestRender();
6318
+ });
6319
+ this.root.add(this.taskStrip);
6320
+ this.body = new BoxRenderable10(renderer2, { id: "omnius-body", width: "100%", flexDirection: "row", flexGrow: 1, minHeight: 1 });
5194
6321
  this.root.add(this.body);
5195
- this.transcriptPane = new BoxRenderable8(renderer2, { id: "omnius-transcript-pane", flexDirection: "column", flexGrow: 1, flexShrink: 1, minWidth: 0, minHeight: 1 });
6322
+ this.transcriptPane = new BoxRenderable10(renderer2, { id: "omnius-transcript-pane", flexDirection: "column", flexGrow: 1, flexShrink: 1, minWidth: 0, minHeight: 1 });
5196
6323
  this.body.add(this.transcriptPane);
5197
- this.scroll = new ScrollBoxRenderable5(renderer2, {
6324
+ this.scroll = new ScrollBoxRenderable7(renderer2, {
5198
6325
  id: "omnius-conversation",
5199
6326
  flexGrow: 1,
5200
6327
  flexShrink: 1,
@@ -5252,7 +6379,7 @@ var NativeFrontend = class {
5252
6379
  this.transcriptPane.add(this.scroll);
5253
6380
  this.content = new NativeBlockList(this.context, this.scroll);
5254
6381
  this.instrumentDivider = new InstrumentDivider(renderer2, {
5255
- resize: (column) => this.resizeInstruments(column),
6382
+ resize: (column3) => this.resizeInstruments(column3),
5256
6383
  toggle: () => this.toggleDetails(),
5257
6384
  start: () => {
5258
6385
  this.sidebarDragWidth = this.sidebarWidth ?? Math.floor(this.renderer.terminalWidth * 0.38);
@@ -5265,9 +6392,17 @@ var NativeFrontend = class {
5265
6392
  this.root.onMouseDrag = (event) => this.instrumentDivider.handleDrag(event);
5266
6393
  this.root.onMouseDragEnd = (event) => this.instrumentDivider.handleRelease(event);
5267
6394
  this.root.onMouseUp = (event) => this.instrumentDivider.handleRelease(event);
5268
- this.instruments = new InstrumentRail(renderer2, { colors, onInspectAgent: (id) => this.emitAction("view", id), onAction: (command2) => this.emitAction(command2) });
6395
+ this.instruments = new InstrumentRail(renderer2, {
6396
+ colors,
6397
+ onInspectAgent: (id) => this.emitAction("view", id),
6398
+ onAction: (command2) => this.emitAction(command2),
6399
+ onWorkQueueAction: (event) => {
6400
+ this.flushLatestInput();
6401
+ this.emit(event);
6402
+ }
6403
+ });
5269
6404
  this.body.add(this.instruments);
5270
- this.embeddedPane = new BoxRenderable8(renderer2, {
6405
+ this.embeddedPane = new BoxRenderable10(renderer2, {
5271
6406
  id: "omnius-editor-pane",
5272
6407
  width: "50%",
5273
6408
  flexShrink: 0,
@@ -5278,7 +6413,7 @@ var NativeFrontend = class {
5278
6413
  visible: false
5279
6414
  });
5280
6415
  this.body.add(this.embeddedPane);
5281
- this.liveButton = new TextRenderable7(renderer2, {
6416
+ this.liveButton = new TextRenderable9(renderer2, {
5282
6417
  id: "omnius-live-button",
5283
6418
  content: "↓ Live",
5284
6419
  width: "100%",
@@ -5301,7 +6436,7 @@ var NativeFrontend = class {
5301
6436
  });
5302
6437
  this.liveButton.focusable = true;
5303
6438
  this.transcriptPane.add(this.liveButton);
5304
- this.queue = new TextRenderable7(renderer2, { id: "omnius-steering-queue", content: "", width: "100%", height: 1, wrapMode: "none", truncate: true, fg: colors.dim, visible: false, flexShrink: 0 });
6439
+ this.queue = new TextRenderable9(renderer2, { id: "omnius-steering-queue", content: "", width: "100%", height: 1, wrapMode: "none", truncate: true, fg: colors.dim, visible: false, flexShrink: 0 });
5305
6440
  this.transcriptPane.add(this.queue);
5306
6441
  this.suggestions = new NativeSelectRenderable(renderer2, {
5307
6442
  id: "omnius-suggestions",
@@ -5320,9 +6455,9 @@ var NativeFrontend = class {
5320
6455
  this.suggestions.onActivate = () => this.acceptSuggestion();
5321
6456
  this.suggestions.on("itemSelected", () => this.acceptSuggestion());
5322
6457
  this.transcriptPane.add(this.suggestions);
5323
- this.status = new BoxRenderable8(renderer2, { id: "omnius-live-status", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2, visible: false });
6458
+ this.status = new BoxRenderable10(renderer2, { id: "omnius-live-status", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2, visible: false });
5324
6459
  this.transcriptPane.add(this.status);
5325
- this.footer = new BoxRenderable8(renderer2, {
6460
+ this.footer = new BoxRenderable10(renderer2, {
5326
6461
  id: "omnius-input-box",
5327
6462
  width: "100%",
5328
6463
  flexShrink: 0,
@@ -5331,7 +6466,7 @@ var NativeFrontend = class {
5331
6466
  flexDirection: "column"
5332
6467
  });
5333
6468
  this.root.add(this.footer);
5334
- this.footerRule = new BoxRenderable8(renderer2, {
6469
+ this.footerRule = new BoxRenderable10(renderer2, {
5335
6470
  id: "omnius-input-rule",
5336
6471
  width: "100%",
5337
6472
  height: 1,
@@ -5357,11 +6492,11 @@ var NativeFrontend = class {
5357
6492
  buffer.drawText(formatSignalDivider(this.footerRule.width, {
5358
6493
  direction: "bottom",
5359
6494
  sidebarColumn: this.instrumentDivider.visible ? this.instrumentDivider.x - this.footerRule.x : void 0
5360
- }), this.footerRule.x, this.footerRule.y, this.context.colors.foreground, this.context.colors.background, TextAttributes8.DIM);
6495
+ }), this.footerRule.x, this.footerRule.y, this.context.colors.foreground, this.context.colors.background, TextAttributes10.DIM);
5361
6496
  };
5362
- const inputRow = new BoxRenderable8(renderer2, { id: "omnius-input-row", width: "100%", flexDirection: "row", gap: 1 });
6497
+ const inputRow = new BoxRenderable10(renderer2, { id: "omnius-input-row", width: "100%", flexDirection: "row", gap: 1 });
5363
6498
  this.footer.add(inputRow);
5364
- this.prompt = new TextRenderable7(renderer2, { id: "omnius-prompt", content: "❯", fg: colors.accent, wrapMode: "none", selectable: false, flexShrink: 0 });
6499
+ this.prompt = new TextRenderable9(renderer2, { id: "omnius-prompt", content: "❯", fg: colors.accent, wrapMode: "none", selectable: false, flexShrink: 0 });
5365
6500
  inputRow.add(this.prompt);
5366
6501
  this.editor = new TextareaRenderable2(renderer2, {
5367
6502
  id: "omnius-input",
@@ -5381,14 +6516,14 @@ var NativeFrontend = class {
5381
6516
  onCursorChange: () => this.editorChanged(),
5382
6517
  onSubmit: () => this.submit()
5383
6518
  });
5384
- this.vimMode = new TextRenderable7(renderer2, {
6519
+ this.vimMode = new TextRenderable9(renderer2, {
5385
6520
  id: "omnius-vim-mode",
5386
6521
  content: "INSERT",
5387
6522
  height: 1,
5388
6523
  maxWidth: 12,
5389
6524
  flexShrink: 0,
5390
6525
  fg: colors.foreground,
5391
- attributes: TextAttributes8.DIM,
6526
+ attributes: TextAttributes10.DIM,
5392
6527
  wrapMode: "none",
5393
6528
  truncate: true,
5394
6529
  visible: false,
@@ -5402,42 +6537,42 @@ var NativeFrontend = class {
5402
6537
  this.renderer.requestRender();
5403
6538
  });
5404
6539
  inputRow.add(this.editor);
5405
- this.enhance = new BoxRenderable8(renderer2, { id: "omnius-enhance", flexDirection: "row", gap: 1, flexShrink: 0, visible: false });
6540
+ this.enhance = new BoxRenderable10(renderer2, { id: "omnius-enhance", flexDirection: "row", gap: 1, flexShrink: 0, visible: false });
5406
6541
  inputRow.add(this.enhance);
5407
- this.activity = new TextRenderable7(renderer2, { id: "omnius-activity", content: "", flexGrow: 1, minWidth: 0, height: 1, wrapMode: "none", truncate: true, visible: false, fg: colors.accent });
6542
+ this.activity = new TextRenderable9(renderer2, { id: "omnius-activity", content: "", flexGrow: 1, minWidth: 0, height: 1, wrapMode: "none", truncate: true, visible: false, fg: colors.accent });
5408
6543
  this.status.add(this.activity);
5409
- this.media = new BoxRenderable8(renderer2, { id: "omnius-media", height: 1, minWidth: 0, flexShrink: 1, flexDirection: "row", gap: 1, visible: false });
5410
- this.mediaText = new TextRenderable7(renderer2, { id: "omnius-media-text", content: "", flexGrow: 1, minWidth: 0, wrapMode: "none", truncate: true, fg: colors.accent });
6544
+ this.media = new BoxRenderable10(renderer2, { id: "omnius-media", height: 1, minWidth: 0, flexShrink: 1, flexDirection: "row", gap: 1, visible: false });
6545
+ this.mediaText = new TextRenderable9(renderer2, { id: "omnius-media-text", content: "", flexGrow: 1, minWidth: 0, wrapMode: "none", truncate: true, fg: colors.accent });
5411
6546
  this.media.add(this.mediaText);
5412
- this.micTrack = new TextRenderable7(renderer2, { id: "omnius-mic-meter", width: 12, height: 1, flexShrink: 0, fg: colors.foreground, visible: false });
6547
+ this.micTrack = new TextRenderable9(renderer2, { id: "omnius-mic-meter", width: 12, height: 1, flexShrink: 0, fg: colors.foreground, visible: false });
5413
6548
  this.media.add(this.micTrack);
5414
6549
  this.status.add(this.media);
5415
- this.copyFeedback = new TextRenderable7(renderer2, {
6550
+ this.copyFeedback = new TextRenderable9(renderer2, {
5416
6551
  id: "omnius-copy-feedback",
5417
6552
  content: "",
5418
6553
  height: 1,
5419
6554
  flexShrink: 0,
5420
6555
  fg: colors.foreground,
5421
- attributes: TextAttributes8.DIM,
6556
+ attributes: TextAttributes10.DIM,
5422
6557
  selectable: false,
5423
6558
  visible: false
5424
6559
  });
5425
6560
  this.status.add(this.copyFeedback);
5426
- this.metricsRow = new BoxRenderable8(renderer2, { id: "omnius-metrics-row", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 1 });
5427
- this.keyHints = new TextRenderable7(renderer2, { id: "omnius-key-hints", content: "F1 HELP TAB FOCUS", height: 1, flexShrink: 0, attributes: TextAttributes8.DIM, fg: colors.foreground, selectable: false });
6561
+ this.metricsRow = new BoxRenderable10(renderer2, { id: "omnius-metrics-row", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 1 });
6562
+ this.keyHints = new TextRenderable9(renderer2, { id: "omnius-key-hints", content: "F1 HELP TAB FOCUS", height: 1, flexShrink: 0, attributes: TextAttributes10.DIM, fg: colors.foreground, selectable: false });
5428
6563
  this.metricsRow.add(this.keyHints);
5429
- this.metricsStartActions = new BoxRenderable8(renderer2, { id: "omnius-metrics-start-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
6564
+ this.metricsStartActions = new BoxRenderable10(renderer2, { id: "omnius-metrics-start-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
5430
6565
  this.metricsRow.add(this.metricsStartActions);
5431
- this.metrics = new TextRenderable7(renderer2, { id: "omnius-metrics", content: "", height: 1, wrapMode: "none", truncate: true, fg: colors.dim, flexShrink: 1, flexGrow: 1, minWidth: 0 });
6566
+ this.metrics = new TextRenderable9(renderer2, { id: "omnius-metrics", content: "", height: 1, wrapMode: "none", truncate: true, fg: colors.dim, flexShrink: 1, flexGrow: 1, minWidth: 0 });
5432
6567
  this.metricsRow.add(this.metrics);
5433
- this.metricsEndActions = new BoxRenderable8(renderer2, { id: "omnius-metrics-end-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
6568
+ this.metricsEndActions = new BoxRenderable10(renderer2, { id: "omnius-metrics-end-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
5434
6569
  this.metricsRow.add(this.metricsEndActions);
5435
6570
  this.root.add(this.metricsRow);
5436
6571
  this.modals = new NativeModalStack(this.context, () => this.restoreFocus());
5437
6572
  renderer2.keyInput.on("keypress", this.onKey);
5438
6573
  renderer2.keyInput.on("paste", this.onPaste);
5439
- renderer2.on(CliRenderEvents5.FRAME, this.onFrame);
5440
- renderer2.on(CliRenderEvents5.RESIZE, this.onResize);
6574
+ renderer2.on(CliRenderEvents7.FRAME, this.onFrame);
6575
+ renderer2.on(CliRenderEvents7.RESIZE, this.onResize);
5441
6576
  this.applyTheme(initialTheme);
5442
6577
  this.editor.focus();
5443
6578
  }
@@ -5460,7 +6595,9 @@ var NativeFrontend = class {
5460
6595
  sessionRow;
5461
6596
  sessions;
5462
6597
  newSession;
6598
+ sessionPicker;
5463
6599
  taskPane;
6600
+ taskStrip;
5464
6601
  tasks;
5465
6602
  body;
5466
6603
  transcriptPane;
@@ -5520,7 +6657,8 @@ var NativeFrontend = class {
5520
6657
  pendingInterface;
5521
6658
  embeddedId;
5522
6659
  selectionArmed = false;
5523
- update(state, patch) {
6660
+ update(frame, patch) {
6661
+ const state = { ...frame, workQueue: Object.hasOwn(frame, "workQueue") ? frame.workQueue ?? void 0 : this.state?.workQueue };
5524
6662
  const inputWasEnabled = this.state?.input.enabled;
5525
6663
  const previousView = this.state ? `${this.state.sessions?.activeId ?? ""}:${this.state.activeViewId}:${this.state.presentation ?? "stack"}` : void 0;
5526
6664
  const currentView = `${state.sessions?.activeId ?? ""}:${state.activeViewId}:${state.presentation ?? "stack"}`;
@@ -5556,10 +6694,13 @@ var NativeFrontend = class {
5556
6694
  this.sessionRow.visible = Boolean(state.sessions);
5557
6695
  this.sessions.update(state.sessions?.items ?? [], state.sessions?.activeId ?? "", state.sessions?.busy);
5558
6696
  this.newSession.focusable = !state.sessions?.busy;
5559
- if (state.sessions?.busy && this.newSession.focused) this.getRenderable(`session:${state.sessions.activeId}`)?.focus();
5560
- this.newSession.attributes = state.sessions?.busy ? TextAttributes8.DIM : this.newSession.focused ? TextAttributes8.INVERSE : 0;
5561
- this.tasks.replace(state.tasks);
5562
- this.taskPane.visible = state.tasks.length > 0;
6697
+ this.sessionPicker.focusable = !state.sessions?.busy;
6698
+ if (state.sessions?.busy && (this.newSession.focused || this.sessionPicker.focused)) this.getRenderable(`session:${state.sessions.activeId}`)?.focus();
6699
+ this.newSession.attributes = state.sessions?.busy ? TextAttributes10.DIM : this.newSession.focused ? TextAttributes10.INVERSE : 0;
6700
+ this.sessionPicker.attributes = state.sessions?.busy ? TextAttributes10.DIM : this.sessionPicker.focused ? TextAttributes10.INVERSE : 0;
6701
+ this.tasks.replace(state.taskNotes ? [] : state.tasks);
6702
+ this.taskPane.visible = !state.taskNotes && state.tasks.length > 0;
6703
+ this.taskStrip.update(state.taskNotes);
5563
6704
  if (patch) {
5564
6705
  if (this.offset > 0 && !viewChanged && !patch.reset) this.newEntries += patch.upsert.filter((block) => !this.content.views.has(block.id)).length;
5565
6706
  this.content.patch(patch);
@@ -5570,7 +6711,7 @@ var NativeFrontend = class {
5570
6711
  this.pendingDisclosures = void 0;
5571
6712
  }
5572
6713
  this.queue.content = state.queued.length ? `Queued (${state.queued.length}) · ${state.queued.join(" · ")}` : "";
5573
- this.queue.visible = state.queued.length > 0;
6714
+ this.queue.visible = !state.workQueue && state.queued.length > 0;
5574
6715
  const suggestionSignature = JSON.stringify(state.suggestions);
5575
6716
  if (suggestionSignature !== this.suggestionSignature) {
5576
6717
  this.suggestionSignature = suggestionSignature;
@@ -5616,8 +6757,8 @@ var NativeFrontend = class {
5616
6757
  for (const child of [...parent.getChildren()]) child.destroy();
5617
6758
  for (const action of actions) {
5618
6759
  const colors = this.context.colors;
5619
- const attributes = action.disabled ? TextAttributes8.DIM : action.active ? TextAttributes8.BOLD | TextAttributes8.UNDERLINE : 0;
5620
- const button = new TextRenderable7(this.renderer, {
6760
+ const attributes = action.disabled ? TextAttributes10.DIM : action.active ? TextAttributes10.BOLD | TextAttributes10.UNDERLINE : 0;
6761
+ const button = new TextRenderable9(this.renderer, {
5621
6762
  id: `${prefix}:${action.id}`,
5622
6763
  content: styledText(action.label),
5623
6764
  flexShrink: 0,
@@ -5640,16 +6781,16 @@ var NativeFrontend = class {
5640
6781
  button.focusable = !action.disabled;
5641
6782
  if (!action.disabled) {
5642
6783
  button.on("focused", () => {
5643
- button.attributes = attributes | TextAttributes8.INVERSE;
6784
+ button.attributes = attributes | TextAttributes10.INVERSE;
5644
6785
  });
5645
6786
  button.on("blurred", () => {
5646
6787
  button.attributes = attributes;
5647
6788
  });
5648
6789
  button.onMouseOver = () => {
5649
- button.attributes = attributes | TextAttributes8.UNDERLINE | (button.focused ? TextAttributes8.INVERSE : 0);
6790
+ button.attributes = attributes | TextAttributes10.UNDERLINE | (button.focused ? TextAttributes10.INVERSE : 0);
5650
6791
  };
5651
6792
  button.onMouseOut = () => {
5652
- button.attributes = attributes | (button.focused ? TextAttributes8.INVERSE : 0);
6793
+ button.attributes = attributes | (button.focused ? TextAttributes10.INVERSE : 0);
5653
6794
  };
5654
6795
  }
5655
6796
  parent.add(button);
@@ -5665,10 +6806,10 @@ var NativeFrontend = class {
5665
6806
  renderActivity() {
5666
6807
  const activity = this.state?.activity;
5667
6808
  const stage = activity?.stage === "idle" ? void 0 : activity?.stage?.replace(/_/g, " ").toUpperCase();
5668
- const label = activity?.label && activity.label.toUpperCase() !== stage ? activity.label : void 0;
6809
+ const label2 = activity?.label && activity.label.toUpperCase() !== stage ? activity.label : void 0;
5669
6810
  const elapsed = activity?.elapsedMs === void 0 ? void 0 : `${Math.max(0, Math.floor(activity.elapsedMs / 1e3))}s`;
5670
6811
  const progress = activity?.progress === void 0 ? void 0 : `${Math.round(activity.progress * 100)}% source accounted`;
5671
- const reading = [stage, label, elapsed, progress].filter(Boolean).join(" · ") || this.state?.instruments?.runtimeStatus || "";
6812
+ const reading = [stage, label2, elapsed, progress].filter(Boolean).join(" · ") || this.state?.instruments?.runtimeStatus || "";
5672
6813
  this.activity.visible = Boolean(activity?.processing || reading);
5673
6814
  this.activity.content = `${activity?.processing ? "RUN · " : ""}${reading}`;
5674
6815
  this.status.visible = this.activity.visible || this.media.visible || this.copyFeedback.visible;
@@ -5691,7 +6832,7 @@ var NativeFrontend = class {
5691
6832
  this.mediaText.fg = media.recording ? this.context.colors.warning : this.context.colors.accent;
5692
6833
  this.micTrack.visible = media.recording && media.levelDb !== void 0;
5693
6834
  const level = Math.round(Math.max(0, Math.min(1, ((media.levelDb ?? -60) + 60) / 60)) * 8);
5694
- this.micTrack.content = `[${"●".repeat(level)}${"·".repeat(8 - level)}]`;
6835
+ this.micTrack.content = `[${"▮".repeat(level)}${"░".repeat(8 - level)}]`;
5695
6836
  }
5696
6837
  applyTheme(theme) {
5697
6838
  const signature = JSON.stringify(theme);
@@ -5725,6 +6866,7 @@ var NativeFrontend = class {
5725
6866
  styleNativeScrollbars(this.headerActions, colors);
5726
6867
  styleNativeScrollbars(this.scroll, colors);
5727
6868
  this.instruments.applyTheme(colors);
6869
+ this.taskStrip.applyTheme(colors);
5728
6870
  this.instrumentDivider.fg = colors.foreground;
5729
6871
  this.instrumentDivider.bg = colors.background;
5730
6872
  this.copyFeedback.fg = colors.foreground;
@@ -5745,10 +6887,10 @@ var NativeFrontend = class {
5745
6887
  this.layoutInstruments();
5746
6888
  this.renderer.requestRender();
5747
6889
  }
5748
- resizeInstruments(column) {
6890
+ resizeInstruments(column3) {
5749
6891
  if (this.renderer.terminalWidth < 110 || this.embeddedPane.visible) return;
5750
6892
  const width = this.renderer.terminalWidth;
5751
- const requested = Math.max(0, this.body.x + width - Math.round(column) - 1);
6893
+ const requested = Math.max(0, this.body.x + width - Math.round(column3) - 1);
5752
6894
  if (requested <= 4) {
5753
6895
  this.detailsOpen = false;
5754
6896
  if (this.sidebarDragWidth !== void 0) this.sidebarWidth = this.sidebarDragWidth;
@@ -5771,6 +6913,8 @@ var NativeFrontend = class {
5771
6913
  this.scroll.height = "auto";
5772
6914
  this.scroll.flexBasis = 0;
5773
6915
  this.instruments.visible = shown;
6916
+ this.taskStrip.visible = Boolean(this.state?.taskNotes && this.taskStrip.hasItems && (!wide || !shown) && !this.embeddedPane.visible);
6917
+ this.taskStrip.reconcile();
5774
6918
  this.instrumentDivider.visible = wide && !this.embeddedPane.visible;
5775
6919
  this.instrumentDivider.setCollapsed(!shown);
5776
6920
  const railWidth = Math.max(24, Math.min(width - 41, this.sidebarWidth ?? Math.floor(width * 0.38)));
@@ -5832,12 +6976,12 @@ var NativeFrontend = class {
5832
6976
  this.tabs.restoreOffset(state.tabs.agents);
5833
6977
  const focus = state.focusId && !this.modals.active ? this.getRenderable(state.focusId) : void 0;
5834
6978
  if (focus?.focusable) {
5835
- let ancestor = focus, visible = true;
6979
+ let ancestor = focus, visible2 = true;
5836
6980
  while (ancestor) {
5837
- visible &&= ancestor.visible;
6981
+ visible2 &&= ancestor.visible;
5838
6982
  ancestor = ancestor.parent;
5839
6983
  }
5840
- if (visible) focus.focus();
6984
+ if (visible2) focus.focus();
5841
6985
  }
5842
6986
  }
5843
6987
  if (this.pendingScrollRestore) {
@@ -6108,7 +7252,7 @@ var NativeFrontend = class {
6108
7252
  const targets = [];
6109
7253
  const visit = (node) => {
6110
7254
  if (!node.visible) return;
6111
- if (node.focusable && node !== this.scroll && !(node instanceof ScrollBoxRenderable5) && node.height > 0 && node.width > 0) targets.push(node);
7255
+ if (node.focusable && node !== this.scroll && !(node instanceof ScrollBoxRenderable7) && node.height > 0 && node.width > 0) targets.push(node);
6112
7256
  for (const child of node.getChildren()) visit(child);
6113
7257
  };
6114
7258
  visit(this.root);
@@ -6347,8 +7491,8 @@ var NativeFrontend = class {
6347
7491
  this.disposeSelectionContrast();
6348
7492
  this.renderer.keyInput.off("keypress", this.onKey);
6349
7493
  this.renderer.keyInput.off("paste", this.onPaste);
6350
- this.renderer.off(CliRenderEvents5.FRAME, this.onFrame);
6351
- this.renderer.off(CliRenderEvents5.RESIZE, this.onResize);
7494
+ this.renderer.off(CliRenderEvents7.FRAME, this.onFrame);
7495
+ this.renderer.off(CliRenderEvents7.RESIZE, this.onResize);
6352
7496
  const mediaClosed = [...this.context.mediaViews ?? []].map((media) => {
6353
7497
  media.pausePlayback();
6354
7498
  return media.closed;
@@ -6364,7 +7508,7 @@ var NativeFrontend = class {
6364
7508
  };
6365
7509
 
6366
7510
  // packages/cli/src/tui/native/components/cursor.ts
6367
- import { CliRenderEvents as CliRenderEvents6 } from "@opentui/core";
7511
+ import { CliRenderEvents as CliRenderEvents8 } from "@opentui/core";
6368
7512
  function installTerminalCursorDefaults(renderer2, session) {
6369
7513
  const reset = new TextEncoder().encode("\x1B]112\x07");
6370
7514
  let disposed = false;
@@ -6414,11 +7558,11 @@ function installTerminalCursorDefaults(renderer2, session) {
6414
7558
  const dispose = () => {
6415
7559
  if (disposed) return;
6416
7560
  disposed = true;
6417
- renderer2.off(CliRenderEvents6.FRAME, afterFrame);
6418
- renderer2.off(CliRenderEvents6.DESTROY, dispose);
7561
+ renderer2.off(CliRenderEvents8.FRAME, afterFrame);
7562
+ renderer2.off(CliRenderEvents8.DESTROY, dispose);
6419
7563
  };
6420
- renderer2.on(CliRenderEvents6.FRAME, afterFrame);
6421
- renderer2.once(CliRenderEvents6.DESTROY, dispose);
7564
+ renderer2.on(CliRenderEvents8.FRAME, afterFrame);
7565
+ renderer2.once(CliRenderEvents8.DESTROY, dispose);
6422
7566
  return { restore, dispose };
6423
7567
  }
6424
7568
 
@@ -6507,10 +7651,10 @@ try {
6507
7651
  maxFps: 60,
6508
7652
  clearOnShutdown: false
6509
7653
  });
6510
- renderer.on(CliRenderEvents7.RENDER_ERROR, (event) => {
7654
+ renderer.on(CliRenderEvents9.RENDER_ERROR, (event) => {
6511
7655
  void fail(event.error);
6512
7656
  });
6513
- renderer.on(CliRenderEvents7.HANDLER_ERROR, (event) => {
7657
+ renderer.on(CliRenderEvents9.HANDLER_ERROR, (event) => {
6514
7658
  void fail(event.error);
6515
7659
  });
6516
7660
  renderer.on("error", (event) => {