omnius 1.0.866 → 1.0.868
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/fonts/DepartureMono-LICENSE.txt +93 -0
- package/assets/licenses/Prism-1.29.0-LICENSE.txt +21 -0
- package/dist/api/py-embed.js +32 -4
- package/dist/index.js +2 -2
- package/dist/library.js +1212 -1084
- package/dist/tui/native/worker.js +863 -159
- package/dist/update-worker.js +147 -81
- package/docs/DISCOVERY.json +10535 -8877
- package/docs/DISCOVERY.md +37 -7
- package/docs/design/dashboard-TODO.md +86 -0
- package/docs/design/dashboard-reconstruction-plan.md +58 -0
- package/docs/design/dashboard-styleguide.md +86 -0
- package/docs/design/media-unification-TODO.md +78 -0
- package/docs/design/media-unification-design.md +89 -0
- package/docs/design/update-operation-cancellation.md +40 -0
- package/docs/design/update-session-restoration-TODO.md +30 -0
- package/docs/work-orders/evidence/dashboard-browser-reconstruction-20261016.json +75 -0
- package/docs/work-orders/evidence/dashboard-media-management-20261016.json +145 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-audio-playing.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-image-100x30.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-image-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-image-160x48.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-image-60x20.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-image-80x24.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-progress-collapsed.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-video-frame-a.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-video-frame-b.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/media-voice-autocomplete-junction.png +0 -0
- package/docs/work-orders/evidence/instrument-media-live-20261016/report.json +813 -0
- package/docs/work-orders/evidence/instrument-media-verification-20261016.json +59 -0
- package/docs/work-orders/evidence/native-interface-state-verification-20261016.json +59 -0
- package/docs/work-orders/evidence/native-straight-boundaries-verification-20261016.json +36 -0
- package/docs/work-orders/evidence/project-media-unification-20261016.json +108 -0
- package/docs/work-orders/instrument-tui.md +17 -7
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -6,29 +6,70 @@ import { CliRenderEvents as CliRenderEvents7, NativeSession, RGBA as RGBA3, crea
|
|
|
6
6
|
|
|
7
7
|
// packages/cli/src/tui/native/components/frontend.ts
|
|
8
8
|
import {
|
|
9
|
-
BoxRenderable as
|
|
9
|
+
BoxRenderable as BoxRenderable8,
|
|
10
10
|
CliRenderEvents as CliRenderEvents5,
|
|
11
11
|
EmbeddedTerminalRenderable as EmbeddedTerminalRenderable2,
|
|
12
12
|
ScrollBoxRenderable as ScrollBoxRenderable5,
|
|
13
13
|
SyntaxStyle as SyntaxStyle2,
|
|
14
14
|
TextareaRenderable as TextareaRenderable2,
|
|
15
|
-
TextRenderable as
|
|
15
|
+
TextRenderable as TextRenderable7,
|
|
16
16
|
TextAttributes as TextAttributes8,
|
|
17
17
|
createClipboard,
|
|
18
18
|
createHostClipboard,
|
|
19
19
|
createRendererClipboardAdapter
|
|
20
20
|
} from "@opentui/core";
|
|
21
21
|
|
|
22
|
+
// packages/cli/src/tui/native/interface-state.ts
|
|
23
|
+
var record = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
var offset = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.min(1e7, Math.floor(value))) : 0;
|
|
25
|
+
function sanitizeNativeInterfaceState(value) {
|
|
26
|
+
if (!record(value) || value.version !== 1 || typeof value.activeViewId !== "string" || !record(value.input)) return void 0;
|
|
27
|
+
if (typeof value.input.text !== "string") return void 0;
|
|
28
|
+
const text = value.input.text.slice(0, 1e6), views = {};
|
|
29
|
+
if (record(value.views)) for (const [key, entry] of Object.entries(value.views).slice(0, 256)) {
|
|
30
|
+
if (key.length > 1024 || !record(entry)) continue;
|
|
31
|
+
const disclosures = {};
|
|
32
|
+
if (record(entry.disclosures)) for (const [id, collapsed] of Object.entries(entry.disclosures).slice(0, 1e4)) {
|
|
33
|
+
if (id.length <= 1024 && typeof collapsed === "boolean") Object.defineProperty(disclosures, id, { value: collapsed, enumerable: true, configurable: true, writable: true });
|
|
34
|
+
}
|
|
35
|
+
Object.defineProperty(views, key, { value: { top: offset(entry.top), live: entry.live === true, disclosures }, enumerable: true, configurable: true, writable: true });
|
|
36
|
+
}
|
|
37
|
+
const layout = record(value.layout) ? value.layout : {}, instruments = record(value.instruments) ? value.instruments : {}, tabs = record(value.tabs) ? value.tabs : {};
|
|
38
|
+
return {
|
|
39
|
+
version: 1,
|
|
40
|
+
...typeof value.sessionId === "string" ? { sessionId: value.sessionId.slice(0, 1024) } : {},
|
|
41
|
+
activeViewId: value.activeViewId.slice(0, 1024),
|
|
42
|
+
presentation: value.presentation === "tree" ? "tree" : "stack",
|
|
43
|
+
input: { text, cursor: Math.min(text.length, offset(value.input.cursor)) },
|
|
44
|
+
views,
|
|
45
|
+
layout: {
|
|
46
|
+
...typeof layout.sidebarWidth === "number" && Number.isFinite(layout.sidebarWidth) ? { sidebarWidth: Math.max(24, Math.min(1e4, Math.floor(layout.sidebarWidth))) } : {},
|
|
47
|
+
...typeof layout.detailsOpen === "boolean" ? { detailsOpen: layout.detailsOpen } : {},
|
|
48
|
+
narrowDetailsOpen: layout.narrowDetailsOpen === true,
|
|
49
|
+
headerPanelCollapsed: layout.headerPanelCollapsed === true
|
|
50
|
+
},
|
|
51
|
+
instruments: {
|
|
52
|
+
inference: instruments.inference !== false,
|
|
53
|
+
session: instruments.session === true,
|
|
54
|
+
context: instruments.context === true,
|
|
55
|
+
devices: instruments.devices === true,
|
|
56
|
+
scrollTop: offset(instruments.scrollTop),
|
|
57
|
+
deviceScrollTop: offset(instruments.deviceScrollTop)
|
|
58
|
+
},
|
|
59
|
+
tabs: { sessions: offset(tabs.sessions), agents: offset(tabs.agents) }
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
22
63
|
// packages/cli/src/tui/native/components/blocks.ts
|
|
23
64
|
import {
|
|
24
|
-
BoxRenderable,
|
|
65
|
+
BoxRenderable as BoxRenderable2,
|
|
25
66
|
CodeRenderable,
|
|
26
67
|
EmbeddedTerminalRenderable,
|
|
27
|
-
ImageRenderable,
|
|
68
|
+
ImageRenderable as ImageRenderable2,
|
|
28
69
|
MarkdownRenderable,
|
|
29
70
|
RenderableEvents,
|
|
30
71
|
ScrollBoxRenderable,
|
|
31
|
-
TextRenderable
|
|
72
|
+
TextRenderable as TextRenderable2
|
|
32
73
|
} from "@opentui/core";
|
|
33
74
|
|
|
34
75
|
// packages/cli/src/tui/native/components/text.ts
|
|
@@ -170,6 +211,505 @@ function installDefaultSelectionContrast(renderer2) {
|
|
|
170
211
|
return dispose;
|
|
171
212
|
}
|
|
172
213
|
|
|
214
|
+
// packages/cli/src/tui/native/components/media.ts
|
|
215
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
216
|
+
import { BoxRenderable, ImageRenderable, NativeImagePool, TextRenderable } from "@opentui/core";
|
|
217
|
+
|
|
218
|
+
// packages/cli/src/tui/native/components/media-playback.ts
|
|
219
|
+
import { spawn, execFile } from "node:child_process";
|
|
220
|
+
import { realpath, lstat } from "node:fs/promises";
|
|
221
|
+
import { extname, relative, resolve } from "node:path";
|
|
222
|
+
import { Audio } from "@opentui/core";
|
|
223
|
+
async function validateMediaFile(path, root) {
|
|
224
|
+
const info = await lstat(path);
|
|
225
|
+
if (!info.isFile() || info.isSymbolicLink()) throw new Error("Media must be a regular local file");
|
|
226
|
+
const canonical = await realpath(path), project = await realpath(root);
|
|
227
|
+
const local = relative(project, canonical);
|
|
228
|
+
if (local === ".." || local.startsWith("../") || resolve(project, local) !== canonical) throw new Error("Media is outside its project");
|
|
229
|
+
if (!/\.(png|jpe?g|webp|gif|mp4|webm|mov|mkv|wav|mp3|flac|ogg|m4a)$/i.test(extname(canonical))) throw new Error("Unsupported media file");
|
|
230
|
+
return canonical;
|
|
231
|
+
}
|
|
232
|
+
async function probeMedia(spec, signal) {
|
|
233
|
+
const path = await validateMediaFile(spec.path, spec.projectRoot);
|
|
234
|
+
const output = await new Promise((done, fail2) => execFile("ffprobe", ["-v", "error", "-show_entries", "stream=codec_type,width,height:format=duration", "-of", "json", path], { signal, timeout: 5e3, maxBuffer: 128e3 }, (error, stdout) => error ? fail2(error) : done(stdout)));
|
|
235
|
+
const data = JSON.parse(output), video = data.streams?.find((stream) => stream.codec_type === "video");
|
|
236
|
+
const durationSec = Number(data.format?.duration);
|
|
237
|
+
return { ...video?.width > 0 ? { width: video.width, height: video.height } : {}, ...Number.isFinite(durationSec) && durationSec > 0 ? { durationSec } : {}, hasAudio: data.streams?.some((stream) => stream.codec_type === "audio") };
|
|
238
|
+
}
|
|
239
|
+
var NativeMediaPlayback = class {
|
|
240
|
+
constructor(changed, silent = process.env["OMNIUS_MEDIA_TEST_SILENT"] === "1") {
|
|
241
|
+
this.changed = changed;
|
|
242
|
+
this.silent = silent;
|
|
243
|
+
}
|
|
244
|
+
changed;
|
|
245
|
+
silent;
|
|
246
|
+
positionSec = 0;
|
|
247
|
+
playing = false;
|
|
248
|
+
process;
|
|
249
|
+
controller;
|
|
250
|
+
audio;
|
|
251
|
+
stream;
|
|
252
|
+
ticker;
|
|
253
|
+
epoch = 0;
|
|
254
|
+
audioOffset = 0;
|
|
255
|
+
cleanup = Promise.resolve();
|
|
256
|
+
get closed() {
|
|
257
|
+
return this.cleanup;
|
|
258
|
+
}
|
|
259
|
+
async play(spec, size, frame) {
|
|
260
|
+
this.pause();
|
|
261
|
+
const epoch = ++this.epoch;
|
|
262
|
+
const controller = this.controller = new AbortController();
|
|
263
|
+
try {
|
|
264
|
+
await this.cleanup;
|
|
265
|
+
if (epoch !== this.epoch) return;
|
|
266
|
+
const path = await validateMediaFile(spec.path, spec.projectRoot);
|
|
267
|
+
if (epoch !== this.epoch) return;
|
|
268
|
+
const width = Math.max(2, Math.min(640, Math.floor(size.width / 2) * 2)), height = Math.max(2, Math.min(360, Math.floor(size.height / 2) * 2));
|
|
269
|
+
const info = spec.kind === "video" ? await probeMedia(spec, controller.signal) : {};
|
|
270
|
+
if (epoch !== this.epoch) return;
|
|
271
|
+
const input = ["-nostdin", "-loglevel", "error", "-hwaccel", "none", "-ss", String(this.positionSec), ...spec.kind === "video" ? ["-re"] : [], "-i", path];
|
|
272
|
+
const output = spec.kind === "video" ? ["-an", "-vf", `scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2,fps=8`, "-pix_fmt", "rgba", "-f", "rawvideo", "pipe:1"] : ["-vn", "-f", "f32le", "-ac", "2", "-ar", "48000", "pipe:1"];
|
|
273
|
+
const withAudio = spec.kind === "video" && info.hasAudio;
|
|
274
|
+
if (withAudio) output.push("-map", "0:a:0", "-vn", "-f", "f32le", "-ac", "2", "-ar", "48000", "pipe:3");
|
|
275
|
+
const child = this.process = spawn("ffmpeg", [...input, ...output], { stdio: withAudio ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"], windowsHide: true });
|
|
276
|
+
child.stdin.end();
|
|
277
|
+
let diagnostic = "";
|
|
278
|
+
child.stderr.on("data", (chunk) => {
|
|
279
|
+
diagnostic = (diagnostic + chunk.toString()).slice(-2e3);
|
|
280
|
+
});
|
|
281
|
+
const closed = new Promise((done, fail2) => {
|
|
282
|
+
child.once("error", fail2);
|
|
283
|
+
child.once("close", done);
|
|
284
|
+
});
|
|
285
|
+
this.cleanup = closed.catch(() => {
|
|
286
|
+
});
|
|
287
|
+
this.playing = true;
|
|
288
|
+
this.changed(spec.kind === "video" && !withAudio ? "Playing · no audio track" : "Playing");
|
|
289
|
+
const audioWork = withAudio ? this.consumeAudio(child.stdio[3], controller, epoch) : void 0;
|
|
290
|
+
if (audioWork) void audioWork.catch((error) => {
|
|
291
|
+
if (epoch === this.epoch) {
|
|
292
|
+
this.pause();
|
|
293
|
+
this.changed(error.message);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
if (spec.kind === "video") {
|
|
297
|
+
const bytes = width * height * 4;
|
|
298
|
+
let pending = Buffer.alloc(0), frames = 0;
|
|
299
|
+
const offset2 = this.positionSec;
|
|
300
|
+
for await (const chunk of child.stdout) {
|
|
301
|
+
if (epoch !== this.epoch) break;
|
|
302
|
+
pending = Buffer.concat([pending, chunk]);
|
|
303
|
+
while (pending.length >= bytes && epoch === this.epoch) {
|
|
304
|
+
frame(pending.subarray(0, bytes), width, height);
|
|
305
|
+
pending = pending.subarray(bytes);
|
|
306
|
+
frames++;
|
|
307
|
+
if (!withAudio) this.positionSec = offset2 + frames / 8;
|
|
308
|
+
this.changed();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
} else await this.consumeAudio(child.stdout, controller, epoch);
|
|
312
|
+
if (audioWork) await audioWork;
|
|
313
|
+
const code = await closed;
|
|
314
|
+
if (epoch !== this.epoch) return;
|
|
315
|
+
if (code !== 0) throw new Error(diagnostic.trim() || "Media decoder failed");
|
|
316
|
+
this.pause();
|
|
317
|
+
this.positionSec = 0;
|
|
318
|
+
this.changed("Playback complete");
|
|
319
|
+
} catch (error) {
|
|
320
|
+
if (epoch !== this.epoch) return;
|
|
321
|
+
this.pause();
|
|
322
|
+
this.changed(error instanceof Error ? error.message : String(error));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async consumeAudio(source, controller, epoch) {
|
|
326
|
+
const audio = this.audio = Audio.create({ autoStart: false, sampleRate: 48e3 });
|
|
327
|
+
audio.on("error", (error) => {
|
|
328
|
+
if (epoch === this.epoch) {
|
|
329
|
+
this.pause();
|
|
330
|
+
this.changed(error.message);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
if (!(this.silent ? audio.startMixer() : audio.start())) throw new Error("Audio output is unavailable");
|
|
334
|
+
this.audioOffset = this.positionSec;
|
|
335
|
+
const stream = this.stream = await audio.playStream(source, { format: "pcm", sampleFormat: "f32le", channels: 2, sampleRate: 48e3, buffer: { capacityMs: 500, startupMs: 50, resumeMs: 50 }, signal: controller.signal });
|
|
336
|
+
if (epoch !== this.epoch) {
|
|
337
|
+
stream.dispose();
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
stream.on("error", (error) => {
|
|
341
|
+
if (epoch === this.epoch) {
|
|
342
|
+
this.pause();
|
|
343
|
+
this.changed(error.message);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
this.ticker = setInterval(() => {
|
|
347
|
+
if (this.silent) audio.mixFrames(480, 2);
|
|
348
|
+
const stats = stream.getStats();
|
|
349
|
+
this.positionSec = this.audioOffset + Number(stats.framesPlayed) / stats.sampleRate;
|
|
350
|
+
this.changed();
|
|
351
|
+
}, this.silent ? 10 : 100);
|
|
352
|
+
await stream.closed;
|
|
353
|
+
}
|
|
354
|
+
pause() {
|
|
355
|
+
++this.epoch;
|
|
356
|
+
if (this.stream) {
|
|
357
|
+
try {
|
|
358
|
+
const stats = this.stream.getStats();
|
|
359
|
+
this.positionSec = this.audioOffset + Number(stats.framesPlayed) / stats.sampleRate;
|
|
360
|
+
} catch {
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
this.controller?.abort();
|
|
364
|
+
this.controller = void 0;
|
|
365
|
+
this.stream?.dispose();
|
|
366
|
+
this.stream = void 0;
|
|
367
|
+
this.audio?.dispose();
|
|
368
|
+
this.audio = void 0;
|
|
369
|
+
if (this.ticker) clearInterval(this.ticker);
|
|
370
|
+
this.ticker = void 0;
|
|
371
|
+
const child = this.process;
|
|
372
|
+
this.process = void 0;
|
|
373
|
+
if (child && child.exitCode === null) {
|
|
374
|
+
child.kill("SIGTERM");
|
|
375
|
+
const timer = setTimeout(() => {
|
|
376
|
+
if (child.exitCode === null) child.kill("SIGKILL");
|
|
377
|
+
}, 250);
|
|
378
|
+
timer.unref?.();
|
|
379
|
+
child.once("close", () => clearTimeout(timer));
|
|
380
|
+
}
|
|
381
|
+
const wasPlaying = this.playing;
|
|
382
|
+
this.playing = false;
|
|
383
|
+
if (wasPlaying) this.changed("Paused");
|
|
384
|
+
}
|
|
385
|
+
dispose() {
|
|
386
|
+
this.pause();
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// packages/cli/src/tui/native/components/media.ts
|
|
391
|
+
function mediaPreviewHeight(width, imageWidth, imageHeight, cellAspectRatio = 2) {
|
|
392
|
+
if (![width, imageWidth, imageHeight, cellAspectRatio].every((value) => Number.isFinite(value) && value > 0)) return 8;
|
|
393
|
+
return Math.max(1, Math.min(80, Math.round(width * imageHeight / imageWidth / cellAspectRatio)));
|
|
394
|
+
}
|
|
395
|
+
function audioWaveform(samples, width) {
|
|
396
|
+
const cells = Math.max(1, Math.min(240, Math.floor(width)));
|
|
397
|
+
const glyphs = "▁▂▃▄▅▆▇█";
|
|
398
|
+
return Array.from({ length: cells }, (_, column) => {
|
|
399
|
+
const begin = Math.floor(column * samples.length / cells), end = Math.max(begin + 1, Math.floor((column + 1) * samples.length / cells));
|
|
400
|
+
let peak = 0;
|
|
401
|
+
for (let index = begin; index < end && index < samples.length; index++) if (Number.isFinite(samples[index])) peak = Math.max(peak, Math.abs(samples[index]));
|
|
402
|
+
return glyphs[Math.min(7, Math.floor(Math.min(1, peak) * 7))];
|
|
403
|
+
}).join("");
|
|
404
|
+
}
|
|
405
|
+
var time = (seconds) => `${Math.floor(Math.max(0, seconds) / 60)}:${String(Math.floor(Math.max(0, seconds) % 60)).padStart(2, "0")}`;
|
|
406
|
+
var NativeMediaView = class extends BoxRenderable {
|
|
407
|
+
constructor(renderer2, mediaId, spec, colors, sendEvent) {
|
|
408
|
+
super(renderer2, { id: `media:${mediaId}`, width: "100%", flexDirection: "column", flexShrink: 0 });
|
|
409
|
+
this.renderer = renderer2;
|
|
410
|
+
this.mediaId = mediaId;
|
|
411
|
+
this.colors = colors;
|
|
412
|
+
this.sendEvent = sendEvent;
|
|
413
|
+
this.spec = spec;
|
|
414
|
+
this.location = new TextRenderable(renderer2, { id: `media-location:${mediaId}`, content: spec.path, width: "100%", wrapMode: "word", selectable: true, fg: colors.dim });
|
|
415
|
+
this.status = new TextRenderable(renderer2, { id: `media-status:${mediaId}`, content: "", width: "100%", wrapMode: "word", selectable: true, fg: colors.dim });
|
|
416
|
+
this.wave = new TextRenderable(renderer2, { id: `media-waveform:${mediaId}`, content: "", width: "100%", height: 1, wrapMode: "none", fg: colors.foreground, visible: false });
|
|
417
|
+
this.playheadLabel = new TextRenderable(renderer2, { id: `media-position:${mediaId}`, content: "", width: "100%", height: 1, wrapMode: "none", fg: colors.dim, visible: false });
|
|
418
|
+
this.controls = new BoxRenderable(renderer2, { id: `media-controls:${mediaId}`, flexDirection: "row", gap: 2, flexShrink: 0 });
|
|
419
|
+
this.playControl = this.control("play", "Play", () => this.togglePlayback());
|
|
420
|
+
this.controls.add(this.playControl);
|
|
421
|
+
this.controls.add(this.control("open", "Open ↗", () => {
|
|
422
|
+
void this.open();
|
|
423
|
+
}));
|
|
424
|
+
this.playback = new NativeMediaPlayback((message) => {
|
|
425
|
+
if (this.isDestroyed) return;
|
|
426
|
+
if (message) this.currentStatus = message;
|
|
427
|
+
this.refreshStatus();
|
|
428
|
+
});
|
|
429
|
+
this.add(this.location);
|
|
430
|
+
this.add(this.wave);
|
|
431
|
+
this.add(this.playheadLabel);
|
|
432
|
+
this.add(this.status);
|
|
433
|
+
this.add(this.controls);
|
|
434
|
+
this.update(spec);
|
|
435
|
+
}
|
|
436
|
+
renderer;
|
|
437
|
+
mediaId;
|
|
438
|
+
colors;
|
|
439
|
+
sendEvent;
|
|
440
|
+
spec;
|
|
441
|
+
location;
|
|
442
|
+
status;
|
|
443
|
+
wave;
|
|
444
|
+
playheadLabel;
|
|
445
|
+
controls;
|
|
446
|
+
playControl;
|
|
447
|
+
image;
|
|
448
|
+
pool;
|
|
449
|
+
playback;
|
|
450
|
+
probeController;
|
|
451
|
+
samples;
|
|
452
|
+
waveformText = "";
|
|
453
|
+
sourceWidth = 16;
|
|
454
|
+
sourceHeight = 9;
|
|
455
|
+
duration = 0;
|
|
456
|
+
hovered = false;
|
|
457
|
+
lastWidth = 0;
|
|
458
|
+
currentStatus = "";
|
|
459
|
+
sourceEpoch = 0;
|
|
460
|
+
needsProbe = true;
|
|
461
|
+
get closed() {
|
|
462
|
+
return this.playback.closed;
|
|
463
|
+
}
|
|
464
|
+
pausePlayback() {
|
|
465
|
+
this.playback.pause();
|
|
466
|
+
}
|
|
467
|
+
control(action, label, operation) {
|
|
468
|
+
const control = new TextRenderable(this.renderer, {
|
|
469
|
+
id: `media-control:${this.mediaId}:${action}`,
|
|
470
|
+
content: label,
|
|
471
|
+
fg: this.colors.foreground,
|
|
472
|
+
selectable: false,
|
|
473
|
+
onMouseDown: (event) => {
|
|
474
|
+
if (event.button === 0) {
|
|
475
|
+
operation();
|
|
476
|
+
event.stopPropagation();
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
onKeyDown: (event) => {
|
|
480
|
+
if (event.eventType !== "release" && (event.name === "return" || event.sequence === " ")) {
|
|
481
|
+
operation();
|
|
482
|
+
event.preventDefault();
|
|
483
|
+
event.stopPropagation();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
control.focusable = true;
|
|
488
|
+
control.on("focused", () => {
|
|
489
|
+
control.attributes = 32;
|
|
490
|
+
});
|
|
491
|
+
control.on("blurred", () => {
|
|
492
|
+
control.attributes = 0;
|
|
493
|
+
});
|
|
494
|
+
return control;
|
|
495
|
+
}
|
|
496
|
+
update(spec) {
|
|
497
|
+
const changed = spec.path !== this.spec.path || spec.kind !== this.spec.kind;
|
|
498
|
+
this.spec = spec;
|
|
499
|
+
this.location.content = spec.path;
|
|
500
|
+
this.playControl.visible = spec.kind !== "image";
|
|
501
|
+
if (changed) {
|
|
502
|
+
this.playback.pause();
|
|
503
|
+
this.playback.positionSec = 0;
|
|
504
|
+
this.probeController?.abort();
|
|
505
|
+
this.probeController = void 0;
|
|
506
|
+
this.needsProbe = true;
|
|
507
|
+
this.pool?.dispose();
|
|
508
|
+
this.pool = void 0;
|
|
509
|
+
this.samples = void 0;
|
|
510
|
+
this.sourceEpoch++;
|
|
511
|
+
}
|
|
512
|
+
if ((spec.kind === "image" || spec.kind === "video") && !this.image) {
|
|
513
|
+
this.image = new ImageRenderable(this.renderer, {
|
|
514
|
+
id: `media-preview:${this.mediaId}`,
|
|
515
|
+
width: "100%",
|
|
516
|
+
height: 8,
|
|
517
|
+
fit: "fit",
|
|
518
|
+
protocol: "auto",
|
|
519
|
+
onLoad: (image) => {
|
|
520
|
+
if (this.spec.kind === "image") {
|
|
521
|
+
this.sourceWidth = image.width;
|
|
522
|
+
this.sourceHeight = image.height;
|
|
523
|
+
}
|
|
524
|
+
this.refreshGeometry();
|
|
525
|
+
},
|
|
526
|
+
onError: () => {
|
|
527
|
+
this.currentStatus = "Preview unavailable · use Open";
|
|
528
|
+
this.refreshStatus();
|
|
529
|
+
},
|
|
530
|
+
onMouseOver: () => {
|
|
531
|
+
this.hovered = true;
|
|
532
|
+
this.refreshStatus();
|
|
533
|
+
},
|
|
534
|
+
onMouseOut: () => {
|
|
535
|
+
this.hovered = false;
|
|
536
|
+
this.refreshStatus();
|
|
537
|
+
},
|
|
538
|
+
onMouseUp: (event) => {
|
|
539
|
+
if (event.button === 0 && !event.isDragging) {
|
|
540
|
+
void this.open();
|
|
541
|
+
event.stopPropagation();
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
onKeyDown: (event) => {
|
|
545
|
+
if (event.eventType !== "release" && event.name === "return") {
|
|
546
|
+
void this.open();
|
|
547
|
+
event.preventDefault();
|
|
548
|
+
event.stopPropagation();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
this.image.focusable = true;
|
|
553
|
+
this.add(this.image, 1);
|
|
554
|
+
}
|
|
555
|
+
if (this.image) {
|
|
556
|
+
this.image.visible = spec.kind === "image" || spec.kind === "video";
|
|
557
|
+
const source = spec.kind === "image" ? spec.path : spec.previewPath;
|
|
558
|
+
if (source && this.image.source !== source && !this.playback.playing) {
|
|
559
|
+
const epoch = this.sourceEpoch;
|
|
560
|
+
void validateMediaFile(source, spec.projectRoot).then((path) => {
|
|
561
|
+
if (!this.isDestroyed && epoch === this.sourceEpoch && !this.playback.playing && this.image && this.image.source !== path) this.image.source = path;
|
|
562
|
+
}).catch((error) => {
|
|
563
|
+
if (!this.isDestroyed) {
|
|
564
|
+
this.currentStatus = `Preview unavailable · ${error.message}`;
|
|
565
|
+
this.refreshStatus();
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
this.wave.visible = spec.kind === "audio" || spec.kind === "music";
|
|
571
|
+
this.playheadLabel.visible = spec.kind !== "image";
|
|
572
|
+
this.refreshStatus();
|
|
573
|
+
}
|
|
574
|
+
startProbe() {
|
|
575
|
+
if (this.needsProbe && !this.probeController) {
|
|
576
|
+
this.needsProbe = false;
|
|
577
|
+
const spec = this.spec;
|
|
578
|
+
const controller = this.probeController = new AbortController(), epoch = this.sourceEpoch;
|
|
579
|
+
if (spec.kind !== "image") void probeMedia(spec, controller.signal).then((info) => {
|
|
580
|
+
if (controller.signal.aborted || epoch !== this.sourceEpoch || this.isDestroyed) return;
|
|
581
|
+
this.sourceWidth = info.width || 16;
|
|
582
|
+
this.sourceHeight = info.height || 9;
|
|
583
|
+
this.duration = info.durationSec || 0;
|
|
584
|
+
this.refreshGeometry();
|
|
585
|
+
if (spec.kind === "audio" || spec.kind === "music") this.loadWaveform(controller, epoch);
|
|
586
|
+
}).catch((error) => {
|
|
587
|
+
if (!controller.signal.aborted && !this.isDestroyed) {
|
|
588
|
+
this.currentStatus = `Media metadata unavailable · ${error.message}`;
|
|
589
|
+
this.refreshStatus();
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
this.refreshStatus();
|
|
594
|
+
}
|
|
595
|
+
loadWaveform(controller, epoch) {
|
|
596
|
+
execFile2("ffmpeg", ["-nostdin", "-loglevel", "error", "-hwaccel", "none", "-i", this.spec.path, "-t", "600", "-vn", "-ac", "1", "-ar", "1000", "-f", "f32le", "pipe:1"], { encoding: "buffer", signal: controller.signal, timeout: 1e4, maxBuffer: 25e5 }, (error, buffer) => {
|
|
597
|
+
if (controller.signal.aborted || epoch !== this.sourceEpoch || this.isDestroyed) return;
|
|
598
|
+
if (error) {
|
|
599
|
+
this.currentStatus = "Waveform unavailable · playback and Open remain available";
|
|
600
|
+
this.refreshStatus();
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const samples = new Float32Array(Math.floor(buffer.length / 4));
|
|
604
|
+
for (let index = 0; index < samples.length; index++) samples[index] = buffer.readFloatLE(index * 4);
|
|
605
|
+
this.samples = samples;
|
|
606
|
+
this.lastWidth = 0;
|
|
607
|
+
this.refreshGeometry();
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
reconcile(viewport, active = true) {
|
|
611
|
+
if (this.isDestroyed) return;
|
|
612
|
+
let ancestor = this;
|
|
613
|
+
while (ancestor && active) {
|
|
614
|
+
active = ancestor.visible;
|
|
615
|
+
ancestor = ancestor.parent;
|
|
616
|
+
}
|
|
617
|
+
const visible = active && this.y + this.height > viewport.y && this.y < viewport.y + viewport.height;
|
|
618
|
+
if (!visible && this.playback.playing) this.playback.pause();
|
|
619
|
+
if (!visible && this.probeController && !this.samples) {
|
|
620
|
+
this.probeController.abort();
|
|
621
|
+
this.probeController = void 0;
|
|
622
|
+
this.needsProbe = true;
|
|
623
|
+
}
|
|
624
|
+
if (visible) this.startProbe();
|
|
625
|
+
this.refreshGeometry();
|
|
626
|
+
}
|
|
627
|
+
refreshGeometry() {
|
|
628
|
+
if (this.isDestroyed) return;
|
|
629
|
+
const width = Math.max(1, this.width);
|
|
630
|
+
if (this.image) {
|
|
631
|
+
const height = mediaPreviewHeight(width, this.sourceWidth, this.sourceHeight, this.image.cellAspectRatio);
|
|
632
|
+
if (this.image.height !== height) this.image.height = height;
|
|
633
|
+
}
|
|
634
|
+
if (width !== this.lastWidth) {
|
|
635
|
+
this.lastWidth = width;
|
|
636
|
+
if (this.samples) this.waveformText = audioWaveform(this.samples, width);
|
|
637
|
+
}
|
|
638
|
+
this.refreshStatus();
|
|
639
|
+
}
|
|
640
|
+
refreshStatus() {
|
|
641
|
+
if (this.isDestroyed) return;
|
|
642
|
+
const text = `${this.hovered ? "Open ↗ · " : ""}${this.currentStatus}`;
|
|
643
|
+
if (this.status.plainText !== text) this.status.content = text;
|
|
644
|
+
const label = this.playback?.playing ? "Pause" : this.playback?.positionSec ? "Resume" : "Play";
|
|
645
|
+
if (this.playControl.plainText !== label) this.playControl.content = label;
|
|
646
|
+
if (this.waveformText) {
|
|
647
|
+
const cursor = this.duration > 0 ? Math.min(this.waveformText.length - 1, Math.floor(this.playback.positionSec / this.duration * this.waveformText.length)) : 0;
|
|
648
|
+
const waveform = this.playback.positionSec > 0 ? this.waveformText.slice(0, cursor) + "│" + this.waveformText.slice(cursor + 1) : this.waveformText;
|
|
649
|
+
if (this.wave.plainText !== waveform) this.wave.content = waveform;
|
|
650
|
+
}
|
|
651
|
+
const progress = `${time(this.playback?.positionSec ?? 0)} / ${this.duration ? time(this.duration) : "--:--"}${this.duration > 600 && this.samples ? " · waveform shows first 10 min" : ""}`;
|
|
652
|
+
if (this.playheadLabel.plainText !== progress) this.playheadLabel.content = progress;
|
|
653
|
+
}
|
|
654
|
+
togglePlayback() {
|
|
655
|
+
if (this.playback.playing) {
|
|
656
|
+
this.playback.pause();
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (this.spec.kind === "image") return;
|
|
660
|
+
void this.playback.play(this.spec, { width: Math.max(2, this.width * 4), height: Math.max(2, (this.image?.height ?? 24) * 8) }, (rgba, width, height) => {
|
|
661
|
+
if (!this.image || this.isDestroyed) return;
|
|
662
|
+
if (!this.pool || this.pool.width !== width || this.pool.height !== height) {
|
|
663
|
+
this.pool?.dispose();
|
|
664
|
+
this.pool = new NativeImagePool({ width, height, capacity: 3, owner: this.renderer.nativeScene.resourceContext });
|
|
665
|
+
}
|
|
666
|
+
const frame = this.pool.publishRgba(rgba);
|
|
667
|
+
if (frame) {
|
|
668
|
+
this.image.source = frame;
|
|
669
|
+
frame.dispose();
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
async open() {
|
|
674
|
+
try {
|
|
675
|
+
const path = await validateMediaFile(this.spec.path, this.spec.projectRoot);
|
|
676
|
+
if (this.isDestroyed) return;
|
|
677
|
+
this.sendEvent({ type: "action", action: "media-open", id: this.mediaId, text: path });
|
|
678
|
+
if (process.env["OMNIUS_MEDIA_TEST_NO_OPEN"] === "1") {
|
|
679
|
+
this.currentStatus = "Open requested (test fixture)";
|
|
680
|
+
this.refreshStatus();
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
const command2 = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer.exe" : "xdg-open";
|
|
684
|
+
execFile2(command2, [path], { timeout: 5e3 }, (error) => {
|
|
685
|
+
if (!this.isDestroyed) {
|
|
686
|
+
this.currentStatus = error ? `Open failed · ${error.message}` : "Opened in the system viewer";
|
|
687
|
+
this.refreshStatus();
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
} catch (error) {
|
|
691
|
+
if (!this.isDestroyed) {
|
|
692
|
+
this.currentStatus = `Open unavailable · ${error instanceof Error ? error.message : String(error)}`;
|
|
693
|
+
this.refreshStatus();
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
applyTheme(colors) {
|
|
698
|
+
this.colors = colors;
|
|
699
|
+
for (const view of [this.location, this.status, this.wave, this.playheadLabel, ...this.controls.getChildren()]) if (view instanceof TextRenderable) {
|
|
700
|
+
view.fg = view === this.wave ? colors.foreground : colors.dim;
|
|
701
|
+
view.bg = colors.background;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
destroy() {
|
|
705
|
+
this.playback.dispose();
|
|
706
|
+
this.probeController?.abort();
|
|
707
|
+
this.pool?.dispose();
|
|
708
|
+
this.pool = void 0;
|
|
709
|
+
super.destroy();
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
|
|
173
713
|
// packages/cli/src/tui/native/components/code.ts
|
|
174
714
|
var aliases = {
|
|
175
715
|
js: "javascript",
|
|
@@ -297,10 +837,10 @@ function nativeMarkdownSections(owner, source, streaming = false) {
|
|
|
297
837
|
}
|
|
298
838
|
];
|
|
299
839
|
const rows = source.split("\n"), offsets = [];
|
|
300
|
-
let
|
|
840
|
+
let offset2 = 0;
|
|
301
841
|
for (const row of rows) {
|
|
302
|
-
offsets.push(
|
|
303
|
-
|
|
842
|
+
offsets.push(offset2);
|
|
843
|
+
offset2 += row.length + 1;
|
|
304
844
|
}
|
|
305
845
|
const output = [], stack = [
|
|
306
846
|
{ level: 0, children: output }
|
|
@@ -400,7 +940,7 @@ var NativeBlockView = class {
|
|
|
400
940
|
this.inline = inline;
|
|
401
941
|
this.spec = spec;
|
|
402
942
|
this.pixel = inline && spec.kind === "text" && Boolean(spec.actions?.length) && spec.actions.every((action) => action.id.startsWith("pixel:"));
|
|
403
|
-
this.root = new
|
|
943
|
+
this.root = new BoxRenderable2(context.renderer, {
|
|
404
944
|
id: `block:${spec.id}`,
|
|
405
945
|
flexDirection: "column",
|
|
406
946
|
flexShrink: inline && !this.pixel ? 1 : 0,
|
|
@@ -424,6 +964,7 @@ var NativeBlockView = class {
|
|
|
424
964
|
actions;
|
|
425
965
|
progress;
|
|
426
966
|
image;
|
|
967
|
+
media;
|
|
427
968
|
terminal;
|
|
428
969
|
collapsed = false;
|
|
429
970
|
previousModelCollapsed;
|
|
@@ -443,7 +984,7 @@ var NativeBlockView = class {
|
|
|
443
984
|
this.root.marginBottom = 0;
|
|
444
985
|
this.root.flexDirection = spec.kind === "row" ? "row" : "column";
|
|
445
986
|
if (spec.title) {
|
|
446
|
-
this.title = new
|
|
987
|
+
this.title = new TextRenderable2(renderer2, {
|
|
447
988
|
id: `block-title:${spec.id}`,
|
|
448
989
|
content: "",
|
|
449
990
|
fg: colors.foreground,
|
|
@@ -467,7 +1008,7 @@ var NativeBlockView = class {
|
|
|
467
1008
|
nativeControlFocus(this.title, 1);
|
|
468
1009
|
this.root.add(this.title);
|
|
469
1010
|
}
|
|
470
|
-
this.body = new
|
|
1011
|
+
this.body = new BoxRenderable2(renderer2, {
|
|
471
1012
|
id: `block-body:${spec.id}`,
|
|
472
1013
|
flexDirection: spec.kind === "row" ? "row" : "column",
|
|
473
1014
|
width: this.pixel ? "auto" : "100%",
|
|
@@ -487,8 +1028,12 @@ var NativeBlockView = class {
|
|
|
487
1028
|
});
|
|
488
1029
|
this.context.terminals.set(spec.id, this.terminal);
|
|
489
1030
|
this.body.add(this.terminal);
|
|
1031
|
+
} else if (spec.kind === "media" && spec.media) {
|
|
1032
|
+
this.media = new NativeMediaView(renderer2, spec.id, spec.media, colors, this.context.emit);
|
|
1033
|
+
this.context.mediaViews?.add(this.media);
|
|
1034
|
+
this.body.add(this.media);
|
|
490
1035
|
} else if (spec.kind === "image" && spec.imagePath) {
|
|
491
|
-
this.image = new
|
|
1036
|
+
this.image = new ImageRenderable2(renderer2, {
|
|
492
1037
|
id: `image:${spec.id}`,
|
|
493
1038
|
source: spec.imagePath,
|
|
494
1039
|
width: "100%",
|
|
@@ -499,7 +1044,7 @@ var NativeBlockView = class {
|
|
|
499
1044
|
if (this.image) this.image.visible = false;
|
|
500
1045
|
if (this.text) {
|
|
501
1046
|
this.text.visible = true;
|
|
502
|
-
if (this.text instanceof
|
|
1047
|
+
if (this.text instanceof TextRenderable2) this.text.content = styledText(this.spec.text ?? "Image unavailable");
|
|
503
1048
|
}
|
|
504
1049
|
this.context.emit({ type: "action", action: "image-error", id: spec.id, text: String(error) });
|
|
505
1050
|
},
|
|
@@ -509,7 +1054,7 @@ var NativeBlockView = class {
|
|
|
509
1054
|
}
|
|
510
1055
|
});
|
|
511
1056
|
this.body.add(this.image);
|
|
512
|
-
this.text = new
|
|
1057
|
+
this.text = new TextRenderable2(renderer2, { id: `image-fallback:${spec.id}`, content: "", visible: false, width: "100%", wrapMode: "word", fg: colors.dim, selectable: true });
|
|
513
1058
|
this.body.add(this.text);
|
|
514
1059
|
} else if (spec.kind === "markdown") {
|
|
515
1060
|
this.text = new MarkdownRenderable(renderer2, {
|
|
@@ -561,7 +1106,7 @@ var NativeBlockView = class {
|
|
|
561
1106
|
});
|
|
562
1107
|
this.body.add(this.text);
|
|
563
1108
|
} else if (spec.text !== void 0) {
|
|
564
|
-
this.text = new
|
|
1109
|
+
this.text = new TextRenderable2(renderer2, {
|
|
565
1110
|
id: `text:${spec.id}`,
|
|
566
1111
|
content: "",
|
|
567
1112
|
width: this.pixel ? "auto" : "100%",
|
|
@@ -574,7 +1119,7 @@ var NativeBlockView = class {
|
|
|
574
1119
|
this.body.add(this.text);
|
|
575
1120
|
}
|
|
576
1121
|
if (spec.kind === "progress") {
|
|
577
|
-
this.progress = new
|
|
1122
|
+
this.progress = new TextRenderable2(renderer2, {
|
|
578
1123
|
id: `progress-track:${spec.id}`,
|
|
579
1124
|
width: "100%",
|
|
580
1125
|
height: 1,
|
|
@@ -588,7 +1133,7 @@ var NativeBlockView = class {
|
|
|
588
1133
|
this.body.add(this.progress);
|
|
589
1134
|
}
|
|
590
1135
|
this.children = new NativeBlockList(this.context, this.body);
|
|
591
|
-
this.actions = new
|
|
1136
|
+
this.actions = new BoxRenderable2(renderer2, {
|
|
592
1137
|
id: `block-actions:${spec.id}`,
|
|
593
1138
|
flexDirection: "row",
|
|
594
1139
|
gap: 1,
|
|
@@ -597,6 +1142,11 @@ var NativeBlockView = class {
|
|
|
597
1142
|
this.root.add(this.actions);
|
|
598
1143
|
}
|
|
599
1144
|
reset() {
|
|
1145
|
+
if (this.media) {
|
|
1146
|
+
this.context.mediaViews?.delete(this.media);
|
|
1147
|
+
this.media.destroy();
|
|
1148
|
+
this.media = void 0;
|
|
1149
|
+
}
|
|
600
1150
|
this.children?.destroy();
|
|
601
1151
|
this.markdownSections?.destroy();
|
|
602
1152
|
this.markdownSections = void 0;
|
|
@@ -632,13 +1182,14 @@ var NativeBlockView = class {
|
|
|
632
1182
|
this.markdownSections.destroy();
|
|
633
1183
|
this.markdownSections = void 0;
|
|
634
1184
|
}
|
|
635
|
-
if (this.text instanceof
|
|
1185
|
+
if (this.text instanceof TextRenderable2) this.text.content = styledText(spec.kind === "image" ? spec.text ?? "Image unavailable" : spec.text);
|
|
636
1186
|
else if (this.text instanceof MarkdownRenderable || this.text instanceof CodeRenderable) {
|
|
637
1187
|
const code = this.text instanceof CodeRenderable ? nativeCodeContent(plainText(spec.text), spec.language) : void 0;
|
|
638
1188
|
this.text.content = sections ? "" : code?.content ?? plainText(spec.text);
|
|
639
1189
|
this.text.streaming = spec.streaming ?? false;
|
|
640
1190
|
if (this.text instanceof CodeRenderable) this.text.filetype = code?.language ?? "text";
|
|
641
1191
|
}
|
|
1192
|
+
if (this.media && spec.media) this.media.update(spec.media);
|
|
642
1193
|
if (this.image && spec.imagePath && this.image.source !== spec.imagePath) this.image.source = spec.imagePath;
|
|
643
1194
|
if (this.terminal) this.terminal.height = spec.height ?? 14;
|
|
644
1195
|
if (this.image) this.image.height = spec.height ?? 12;
|
|
@@ -649,7 +1200,7 @@ var NativeBlockView = class {
|
|
|
649
1200
|
this.actionsSignature = actionsSignature;
|
|
650
1201
|
for (const child of [...this.actions.getChildren()]) child.destroy();
|
|
651
1202
|
for (const action of spec.actions ?? []) {
|
|
652
|
-
const button = new
|
|
1203
|
+
const button = new TextRenderable2(this.context.renderer, {
|
|
653
1204
|
id: `block-action:${spec.id}:${action.id}`,
|
|
654
1205
|
content: plainText(action.label),
|
|
655
1206
|
fg: this.context.colors.foreground,
|
|
@@ -686,6 +1237,20 @@ var NativeBlockView = class {
|
|
|
686
1237
|
if (this.title) this.title.content = `${this.collapsed ? "▸ " : "· "}${plainText(this.spec.title)}`;
|
|
687
1238
|
this.context.emit({ type: "action", action: "toggle-block", id: this.spec.id });
|
|
688
1239
|
}
|
|
1240
|
+
captureDisclosures(result) {
|
|
1241
|
+
if (this.spec.collapsible) Object.defineProperty(result, this.spec.id, { value: this.collapsed, enumerable: true, configurable: true, writable: true });
|
|
1242
|
+
this.children?.captureDisclosures(result);
|
|
1243
|
+
this.markdownSections?.captureDisclosures(result);
|
|
1244
|
+
}
|
|
1245
|
+
restoreDisclosures(state) {
|
|
1246
|
+
if (this.spec.collapsible && Object.hasOwn(state, this.spec.id)) {
|
|
1247
|
+
this.collapsed = state[this.spec.id];
|
|
1248
|
+
if (this.body) this.body.visible = !this.collapsed;
|
|
1249
|
+
if (this.title) this.title.content = `${this.collapsed ? "▸ " : "· "}${plainText(this.spec.title)}`;
|
|
1250
|
+
}
|
|
1251
|
+
this.children?.restoreDisclosures(state);
|
|
1252
|
+
this.markdownSections?.restoreDisclosures(state);
|
|
1253
|
+
}
|
|
689
1254
|
applyTheme() {
|
|
690
1255
|
const colors = this.context.colors;
|
|
691
1256
|
this.root.backgroundColor = colors.background;
|
|
@@ -704,14 +1269,20 @@ var NativeBlockView = class {
|
|
|
704
1269
|
this.progress.fg = colors.foreground;
|
|
705
1270
|
this.progress.bg = colors.background;
|
|
706
1271
|
}
|
|
707
|
-
for (const action of this.actions?.getChildren() ?? []) if (action instanceof
|
|
1272
|
+
for (const action of this.actions?.getChildren() ?? []) if (action instanceof TextRenderable2) {
|
|
708
1273
|
action.fg = colors.foreground;
|
|
709
1274
|
action.bg = colors.background;
|
|
710
1275
|
}
|
|
1276
|
+
this.media?.applyTheme(colors);
|
|
711
1277
|
this.children?.applyTheme();
|
|
712
1278
|
this.markdownSections?.applyTheme();
|
|
713
1279
|
}
|
|
714
1280
|
destroy() {
|
|
1281
|
+
if (this.media) {
|
|
1282
|
+
this.context.mediaViews?.delete(this.media);
|
|
1283
|
+
this.media.destroy();
|
|
1284
|
+
this.media = void 0;
|
|
1285
|
+
}
|
|
715
1286
|
this.children?.destroy();
|
|
716
1287
|
this.markdownSections?.destroy();
|
|
717
1288
|
if (this.terminal) this.context.terminals.delete(this.spec.id);
|
|
@@ -750,7 +1321,10 @@ var NativeBlockList = class {
|
|
|
750
1321
|
reorder(order) {
|
|
751
1322
|
const next = order.filter((id) => this.views.has(id));
|
|
752
1323
|
if (next.length === this.order.length && next.every((id, index) => this.order[index] === id)) return;
|
|
753
|
-
next.forEach((id, index) =>
|
|
1324
|
+
next.forEach((id, index) => {
|
|
1325
|
+
const view = this.views.get(id).root;
|
|
1326
|
+
if (this.parent.getChildren()[index] !== view) this.parent.add(view, index);
|
|
1327
|
+
});
|
|
754
1328
|
this.order = next;
|
|
755
1329
|
}
|
|
756
1330
|
remove(id) {
|
|
@@ -761,6 +1335,13 @@ var NativeBlockList = class {
|
|
|
761
1335
|
applyTheme() {
|
|
762
1336
|
for (const view of this.views.values()) view.applyTheme();
|
|
763
1337
|
}
|
|
1338
|
+
captureDisclosures(result = {}) {
|
|
1339
|
+
for (const view of this.views.values()) view.captureDisclosures(result);
|
|
1340
|
+
return result;
|
|
1341
|
+
}
|
|
1342
|
+
restoreDisclosures(state) {
|
|
1343
|
+
for (const view of this.views.values()) view.restoreDisclosures(state);
|
|
1344
|
+
}
|
|
764
1345
|
clear() {
|
|
765
1346
|
for (const view of this.views.values()) view.destroy();
|
|
766
1347
|
this.views.clear();
|
|
@@ -773,12 +1354,12 @@ var NativeBlockList = class {
|
|
|
773
1354
|
|
|
774
1355
|
// packages/cli/src/tui/native/components/modals.ts
|
|
775
1356
|
import {
|
|
776
|
-
BoxRenderable as
|
|
1357
|
+
BoxRenderable as BoxRenderable4,
|
|
777
1358
|
InputRenderable,
|
|
778
1359
|
ScrollBoxRenderable as ScrollBoxRenderable2,
|
|
779
1360
|
TextareaRenderable,
|
|
780
1361
|
TextAttributes as TextAttributes4,
|
|
781
|
-
TextRenderable as
|
|
1362
|
+
TextRenderable as TextRenderable3
|
|
782
1363
|
} from "@opentui/core";
|
|
783
1364
|
|
|
784
1365
|
// packages/cli/src/tui/native/components/select.ts
|
|
@@ -820,8 +1401,8 @@ function styleNativeSlider(slider, colors) {
|
|
|
820
1401
|
const seek = (event) => {
|
|
821
1402
|
const horizontal = slider.orientation === "horizontal";
|
|
822
1403
|
const length = horizontal ? slider.width : slider.height;
|
|
823
|
-
const
|
|
824
|
-
const progress = length > 1 ? Math.max(0, Math.min(1,
|
|
1404
|
+
const offset2 = horizontal ? event.x - slider.x : event.y - slider.y;
|
|
1405
|
+
const progress = length > 1 ? Math.max(0, Math.min(1, offset2 / (length - 1))) : 0;
|
|
825
1406
|
slider.value = slider.min + progress * (slider.max - slider.min);
|
|
826
1407
|
event.preventDefault();
|
|
827
1408
|
event.stopPropagation();
|
|
@@ -854,8 +1435,8 @@ var NativeSelectRenderable = class extends SelectRenderable {
|
|
|
854
1435
|
this.renderAfter = (buffer) => {
|
|
855
1436
|
const count = this.visibleCount();
|
|
856
1437
|
if (!this.showScrollIndicator || this.options.length <= count) return;
|
|
857
|
-
const
|
|
858
|
-
drawDotRail(buffer, this.width - 1, 0, this.height, false,
|
|
1438
|
+
const offset2 = Math.max(0, Math.min(this.getSelectedIndex() - Math.floor(count / 2), this.options.length - count));
|
|
1439
|
+
drawDotRail(buffer, this.width - 1, 0, this.height, false, offset2 / (this.options.length - count), colors);
|
|
859
1440
|
};
|
|
860
1441
|
}
|
|
861
1442
|
visibleCount() {
|
|
@@ -931,7 +1512,7 @@ var NativeSelectRenderable = class extends SelectRenderable {
|
|
|
931
1512
|
};
|
|
932
1513
|
|
|
933
1514
|
// packages/cli/src/tui/native/components/corner-frame.ts
|
|
934
|
-
import { BoxRenderable as
|
|
1515
|
+
import { BoxRenderable as BoxRenderable3, CliRenderEvents as CliRenderEvents2, RenderableEvents as RenderableEvents2, TextAttributes as TextAttributes3 } from "@opentui/core";
|
|
935
1516
|
function drawCornerFrame(buffer, panel, colors, progress = 1) {
|
|
936
1517
|
const { x, y, width, height } = panel;
|
|
937
1518
|
if (width <= 0 || height <= 0) return;
|
|
@@ -970,7 +1551,7 @@ var NativeCornerFrame = class {
|
|
|
970
1551
|
this.colors = colors;
|
|
971
1552
|
this.renderer = renderer2;
|
|
972
1553
|
this.container = container;
|
|
973
|
-
this.chrome = new
|
|
1554
|
+
this.chrome = new BoxRenderable3(renderer2, {
|
|
974
1555
|
id: `${panel.id}:corners`,
|
|
975
1556
|
position: "absolute",
|
|
976
1557
|
left: 0,
|
|
@@ -1100,7 +1681,7 @@ var NativeModalView = class {
|
|
|
1100
1681
|
this.close = close2;
|
|
1101
1682
|
this.spec = spec;
|
|
1102
1683
|
const { renderer: renderer2, colors } = context;
|
|
1103
|
-
this.root = new
|
|
1684
|
+
this.root = new BoxRenderable4(renderer2, {
|
|
1104
1685
|
id: `modal:${spec.id}`,
|
|
1105
1686
|
position: "absolute",
|
|
1106
1687
|
top: 0,
|
|
@@ -1122,7 +1703,7 @@ var NativeModalView = class {
|
|
|
1122
1703
|
}
|
|
1123
1704
|
}
|
|
1124
1705
|
});
|
|
1125
|
-
this.panel = new
|
|
1706
|
+
this.panel = new BoxRenderable4(renderer2, {
|
|
1126
1707
|
id: `modal-panel:${spec.id}`,
|
|
1127
1708
|
flexDirection: "column",
|
|
1128
1709
|
width: "94%",
|
|
@@ -1138,7 +1719,12 @@ var NativeModalView = class {
|
|
|
1138
1719
|
this.root.add(this.panel);
|
|
1139
1720
|
this.frame = new NativeCornerFrame(this.panel, colors, renderer2, this.root);
|
|
1140
1721
|
this.breadcrumb = this.addText(`modal-breadcrumb:${spec.id}`);
|
|
1141
|
-
|
|
1722
|
+
const header = new BoxRenderable4(renderer2, { id: `modal-heading:${spec.id}`, width: "100%", flexDirection: "row", gap: 1, flexShrink: 0 });
|
|
1723
|
+
this.heading = new TextRenderable3(renderer2, { id: `modal-title:${spec.id}`, content: "", width: 0, flexGrow: 1, flexShrink: 1, wrapMode: "word", fg: colors.foreground });
|
|
1724
|
+
this.headerActions = new BoxRenderable4(renderer2, { id: `modal-header-actions:${spec.id}`, flexDirection: "row", gap: 1, flexShrink: 0 });
|
|
1725
|
+
header.add(this.heading);
|
|
1726
|
+
header.add(this.headerActions);
|
|
1727
|
+
this.panel.add(header);
|
|
1142
1728
|
this.description = this.addText(`modal-description:${spec.id}`);
|
|
1143
1729
|
if (spec.kind === "select") this.buildSelect();
|
|
1144
1730
|
else if (spec.kind === "input") this.buildInput();
|
|
@@ -1156,7 +1742,7 @@ var NativeModalView = class {
|
|
|
1156
1742
|
this.blocks = new NativeBlockList(this.modalContext(), this.document);
|
|
1157
1743
|
this.panel.add(this.document);
|
|
1158
1744
|
} else {
|
|
1159
|
-
this.progress = new
|
|
1745
|
+
this.progress = new TextRenderable3(renderer2, {
|
|
1160
1746
|
id: `modal-progress:${spec.id}`,
|
|
1161
1747
|
width: "100%",
|
|
1162
1748
|
height: 1,
|
|
@@ -1168,13 +1754,13 @@ var NativeModalView = class {
|
|
|
1168
1754
|
selectable: false
|
|
1169
1755
|
});
|
|
1170
1756
|
this.panel.add(this.progress);
|
|
1171
|
-
const progressBlocks = new
|
|
1757
|
+
const progressBlocks = new BoxRenderable4(renderer2, { id: `modal-progress-blocks:${spec.id}`, flexDirection: "column", width: "100%" });
|
|
1172
1758
|
this.panel.add(progressBlocks);
|
|
1173
1759
|
this.blocks = new NativeBlockList(this.modalContext(), progressBlocks);
|
|
1174
1760
|
}
|
|
1175
1761
|
this.error = this.addText(`modal-error:${spec.id}`);
|
|
1176
1762
|
this.hints = this.addText(`modal-hints:${spec.id}`);
|
|
1177
|
-
this.actions = new
|
|
1763
|
+
this.actions = new BoxRenderable4(renderer2, { id: `modal-actions:${spec.id}`, flexDirection: "row", gap: 1, width: "100%", marginTop: 0 });
|
|
1178
1764
|
this.panel.add(this.actions);
|
|
1179
1765
|
this.update(spec);
|
|
1180
1766
|
}
|
|
@@ -1190,6 +1776,7 @@ var NativeModalView = class {
|
|
|
1190
1776
|
error;
|
|
1191
1777
|
hints;
|
|
1192
1778
|
actions;
|
|
1779
|
+
headerActions;
|
|
1193
1780
|
filterInput;
|
|
1194
1781
|
editor;
|
|
1195
1782
|
secretMask;
|
|
@@ -1201,11 +1788,39 @@ var NativeModalView = class {
|
|
|
1201
1788
|
filter = "";
|
|
1202
1789
|
changing = false;
|
|
1203
1790
|
actionsSignature = "";
|
|
1791
|
+
headerActionsSignature = "";
|
|
1204
1792
|
addText(id) {
|
|
1205
|
-
const text = new
|
|
1793
|
+
const text = new TextRenderable3(this.context.renderer, { id, content: "", width: "100%", wrapMode: "word", flexShrink: 0, fg: this.context.colors.foreground, selectable: true });
|
|
1206
1794
|
this.panel.add(text);
|
|
1207
1795
|
return text;
|
|
1208
1796
|
}
|
|
1797
|
+
replaceActions(container, actions, prefix = "") {
|
|
1798
|
+
for (const child of [...container.getChildren()]) child.destroy();
|
|
1799
|
+
for (const action of actions) {
|
|
1800
|
+
const button = new TextRenderable3(this.context.renderer, {
|
|
1801
|
+
id: `modal-action:${this.spec.id}:${prefix}${action.id}`,
|
|
1802
|
+
content: plainText(action.label),
|
|
1803
|
+
fg: this.context.colors.foreground,
|
|
1804
|
+
bg: this.context.colors.background,
|
|
1805
|
+
attributes: action.disabled ? 2 : action.active ? 1 : 0,
|
|
1806
|
+
selectable: false,
|
|
1807
|
+
onMouseDown: (event) => {
|
|
1808
|
+
if (event.button !== 0 || action.disabled) return;
|
|
1809
|
+
this.emitAction(action.command ?? action.id, this.editor?.plainText);
|
|
1810
|
+
event.stopPropagation();
|
|
1811
|
+
},
|
|
1812
|
+
onKeyDown: (key) => {
|
|
1813
|
+
if (key.eventType === "release" || key.name !== "return" && key.sequence !== " " || action.disabled) return;
|
|
1814
|
+
this.emitAction(action.command ?? action.id, this.editor?.plainText);
|
|
1815
|
+
key.preventDefault();
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
button.focusable = !action.disabled;
|
|
1819
|
+
nativeControlFocus(button, action.disabled ? 2 : action.active ? 1 : 0);
|
|
1820
|
+
container.add(button);
|
|
1821
|
+
}
|
|
1822
|
+
container.visible = actions.length > 0;
|
|
1823
|
+
}
|
|
1209
1824
|
buildSelect() {
|
|
1210
1825
|
const { renderer: renderer2, colors } = this.context;
|
|
1211
1826
|
this.filterInput = new InputRenderable(renderer2, {
|
|
@@ -1308,34 +1923,15 @@ var NativeModalView = class {
|
|
|
1308
1923
|
this.refreshOptions(patch.selectedIndex);
|
|
1309
1924
|
this.blocks?.replace(spec.blocks ?? []);
|
|
1310
1925
|
if (this.progress) this.progress.content = nativeProgressText(spec.progress, true);
|
|
1926
|
+
const headerActionsSignature = JSON.stringify(spec.headerActions ?? []);
|
|
1927
|
+
if (headerActionsSignature !== this.headerActionsSignature) {
|
|
1928
|
+
this.headerActionsSignature = headerActionsSignature;
|
|
1929
|
+
this.replaceActions(this.headerActions, spec.headerActions ?? [], "header:");
|
|
1930
|
+
}
|
|
1311
1931
|
const actionsSignature = JSON.stringify(spec.actions ?? []);
|
|
1312
1932
|
if (actionsSignature !== this.actionsSignature) {
|
|
1313
1933
|
this.actionsSignature = actionsSignature;
|
|
1314
|
-
|
|
1315
|
-
for (const action of spec.actions ?? []) {
|
|
1316
|
-
const button = new TextRenderable2(this.context.renderer, {
|
|
1317
|
-
id: `modal-action:${spec.id}:${action.id}`,
|
|
1318
|
-
content: plainText(action.label),
|
|
1319
|
-
fg: this.context.colors.foreground,
|
|
1320
|
-
bg: this.context.colors.background,
|
|
1321
|
-
attributes: action.disabled ? 2 : action.active ? 1 : 0,
|
|
1322
|
-
selectable: false,
|
|
1323
|
-
onMouseDown: (event) => {
|
|
1324
|
-
if (event.button !== 0 || action.disabled) return;
|
|
1325
|
-
this.emitAction(action.command ?? action.id, this.editor?.plainText);
|
|
1326
|
-
event.stopPropagation();
|
|
1327
|
-
},
|
|
1328
|
-
onKeyDown: (key) => {
|
|
1329
|
-
if (key.eventType === "release" || key.name !== "return" && key.sequence !== " " || action.disabled) return;
|
|
1330
|
-
this.emitAction(action.command ?? action.id, this.editor?.plainText);
|
|
1331
|
-
key.preventDefault();
|
|
1332
|
-
}
|
|
1333
|
-
});
|
|
1334
|
-
button.focusable = !action.disabled;
|
|
1335
|
-
nativeControlFocus(button, action.disabled ? 2 : action.active ? 1 : 0);
|
|
1336
|
-
this.actions.add(button);
|
|
1337
|
-
}
|
|
1338
|
-
this.actions.visible = (spec.actions?.length ?? 0) > 0;
|
|
1934
|
+
this.replaceActions(this.actions, spec.actions ?? []);
|
|
1339
1935
|
}
|
|
1340
1936
|
} finally {
|
|
1341
1937
|
this.changing = false;
|
|
@@ -1390,7 +1986,7 @@ var NativeModalView = class {
|
|
|
1390
1986
|
this.close(this.spec.id, { confirmed: true, key: current?.item.key ?? null, index: current?.index ?? -1, ...value === void 0 ? {} : { value } });
|
|
1391
1987
|
}
|
|
1392
1988
|
cancel(action = "cancel") {
|
|
1393
|
-
if (this.frame.closing) return;
|
|
1989
|
+
if (this.frame.closing || this.spec.nonDismissible) return;
|
|
1394
1990
|
if (this.spec.deferSelection) {
|
|
1395
1991
|
this.emitAction(action);
|
|
1396
1992
|
return;
|
|
@@ -1559,7 +2155,7 @@ var NativeModalView = class {
|
|
|
1559
2155
|
editor.placeholderColor = colors.foreground;
|
|
1560
2156
|
}
|
|
1561
2157
|
if (this.secretMask) this.secretMask.fg = colors.foreground;
|
|
1562
|
-
for (const action of this.actions.getChildren()) if (action instanceof
|
|
2158
|
+
for (const action of [...this.actions.getChildren(), ...this.headerActions.getChildren()]) if (action instanceof TextRenderable3) {
|
|
1563
2159
|
action.fg = colors.foreground;
|
|
1564
2160
|
action.bg = colors.background;
|
|
1565
2161
|
}
|
|
@@ -1643,12 +2239,12 @@ var NativeModalStack = class {
|
|
|
1643
2239
|
|
|
1644
2240
|
// packages/cli/src/tui/native/components/instruments.ts
|
|
1645
2241
|
import {
|
|
1646
|
-
BoxRenderable as
|
|
2242
|
+
BoxRenderable as BoxRenderable5,
|
|
1647
2243
|
RGBA as RGBA2,
|
|
1648
2244
|
RenderableEvents as RenderableEvents3,
|
|
1649
2245
|
ScrollBoxRenderable as ScrollBoxRenderable3,
|
|
1650
2246
|
TextAttributes as TextAttributes5,
|
|
1651
|
-
TextRenderable as
|
|
2247
|
+
TextRenderable as TextRenderable4
|
|
1652
2248
|
} from "@opentui/core";
|
|
1653
2249
|
|
|
1654
2250
|
// packages/cli/src/tui/native/components/device-history.ts
|
|
@@ -1784,17 +2380,9 @@ function terminalCellWidth(value) {
|
|
|
1784
2380
|
var graphemes2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
1785
2381
|
function formatSignalDivider(width, geometry = { direction: "top" }) {
|
|
1786
2382
|
const cells = Math.max(0, Math.floor(width));
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
const right = Math.max(4, Math.min(cells - 2, Math.floor(requestedRight)));
|
|
1791
|
-
const requestedLeft = Math.floor(geometry.leftTextEnd ?? 0) + buffer;
|
|
1792
|
-
if (geometry.direction === "top" && requestedLeft > right - 2) return "─".repeat(cells);
|
|
1793
|
-
const left = Math.max(1, Math.min(right - 2, requestedLeft));
|
|
1794
|
-
const outside = geometry.direction === "top" ? "▁" : "▔";
|
|
1795
|
-
const inside = geometry.direction === "top" ? "▔" : "▁";
|
|
1796
|
-
const fall = geometry.direction === "top" ? "╱" : "╲", rise = geometry.direction === "top" ? "╲" : "╱";
|
|
1797
|
-
return outside.repeat(left) + fall + inside.repeat(right - left - 1) + rise + outside.repeat(cells - right - 1);
|
|
2383
|
+
const column = Math.floor(geometry.sidebarColumn ?? -1);
|
|
2384
|
+
if (!Number.isFinite(column) || column < 0 || column >= cells) return "─".repeat(cells);
|
|
2385
|
+
return "─".repeat(column) + (geometry.direction === "top" ? "┬" : "┴") + "─".repeat(cells - column - 1);
|
|
1798
2386
|
}
|
|
1799
2387
|
function fitInstrumentText(value, cells, marker = "~") {
|
|
1800
2388
|
const text = stripTerminalSequences(normalizeTerminalLine(value));
|
|
@@ -1856,7 +2444,7 @@ function instrumentStatus(value) {
|
|
|
1856
2444
|
// packages/cli/src/tui/native/components/instruments.ts
|
|
1857
2445
|
var foreground = RGBA2.defaultForeground();
|
|
1858
2446
|
var background = RGBA2.defaultBackground();
|
|
1859
|
-
var SectionBanner = class extends
|
|
2447
|
+
var SectionBanner = class extends TextRenderable4 {
|
|
1860
2448
|
constructor(renderer2, title, id, activate) {
|
|
1861
2449
|
super(renderer2, {
|
|
1862
2450
|
id,
|
|
@@ -1911,7 +2499,7 @@ var SectionBanner = class extends TextRenderable3 {
|
|
|
1911
2499
|
if (this.plainText !== next) this.content = next;
|
|
1912
2500
|
}
|
|
1913
2501
|
};
|
|
1914
|
-
var TelemetryRow = class extends
|
|
2502
|
+
var TelemetryRow = class extends TextRenderable4 {
|
|
1915
2503
|
constructor(renderer2, label, id, reserved = 12) {
|
|
1916
2504
|
super(renderer2, {
|
|
1917
2505
|
id,
|
|
@@ -1957,7 +2545,7 @@ var SignalMeter = class extends TelemetryRow {
|
|
|
1957
2545
|
this.update(formatSignalMeter(value, maximum));
|
|
1958
2546
|
}
|
|
1959
2547
|
};
|
|
1960
|
-
var InstrumentDivider = class extends
|
|
2548
|
+
var InstrumentDivider = class extends TextRenderable4 {
|
|
1961
2549
|
constructor(renderer2, actions) {
|
|
1962
2550
|
super(renderer2, {
|
|
1963
2551
|
id: "omnius-instrument-divider",
|
|
@@ -2054,17 +2642,17 @@ var InstrumentDivider = class extends TextRenderable3 {
|
|
|
2054
2642
|
this.attributes = this.focused ? TextAttributes5.INVERSE : TextAttributes5.DIM;
|
|
2055
2643
|
}
|
|
2056
2644
|
};
|
|
2057
|
-
var DeviceMonitor = class extends
|
|
2645
|
+
var DeviceMonitor = class extends BoxRenderable5 {
|
|
2058
2646
|
constructor(renderer2, action) {
|
|
2059
2647
|
super(renderer2, { id: "omnius-devices", width: "100%", height: 5, minHeight: 5, maxHeight: "60%", flexShrink: 1, flexDirection: "column", visible: false });
|
|
2060
2648
|
this.action = action;
|
|
2061
2649
|
this.heading = new SectionBanner(renderer2, "DEVICES", "omnius-devices:heading", () => this.toggle());
|
|
2062
2650
|
this.heading.update("DEVICES", false);
|
|
2063
2651
|
this.add(this.heading);
|
|
2064
|
-
this.summary = new
|
|
2652
|
+
this.summary = new TextRenderable4(renderer2, { id: "omnius-devices:summary", content: "--", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
|
|
2065
2653
|
this.add(this.summary);
|
|
2066
|
-
this.compactLoad = new
|
|
2067
|
-
this.compactMemory = new
|
|
2654
|
+
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 });
|
|
2655
|
+
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 });
|
|
2068
2656
|
this.add(this.compactLoad);
|
|
2069
2657
|
this.add(this.compactMemory);
|
|
2070
2658
|
this.scroll = new ScrollBoxRenderable3(renderer2, {
|
|
@@ -2082,7 +2670,7 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2082
2670
|
contentOptions: { flexDirection: "column" }
|
|
2083
2671
|
});
|
|
2084
2672
|
this.add(this.scroll);
|
|
2085
|
-
this.notes = new
|
|
2673
|
+
this.notes = new TextRenderable4(renderer2, {
|
|
2086
2674
|
id: "omnius-devices:notes",
|
|
2087
2675
|
content: "",
|
|
2088
2676
|
width: "100%",
|
|
@@ -2094,7 +2682,7 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2094
2682
|
truncate: true
|
|
2095
2683
|
});
|
|
2096
2684
|
this.scroll.add(this.notes);
|
|
2097
|
-
const controls = new
|
|
2685
|
+
const controls = new BoxRenderable5(renderer2, { id: "omnius-devices:controls", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2 });
|
|
2098
2686
|
this.add(controls);
|
|
2099
2687
|
this.policy = this.button(renderer2, "omnius-devices:policy", "GPU POLICY", () => {
|
|
2100
2688
|
if (this.canSelect()) this.action?.("/gpu");
|
|
@@ -2118,7 +2706,7 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2118
2706
|
historySource = "";
|
|
2119
2707
|
rows = /* @__PURE__ */ new Map();
|
|
2120
2708
|
button(renderer2, id, label, activate) {
|
|
2121
|
-
const button = new
|
|
2709
|
+
const button = new TextRenderable4(renderer2, {
|
|
2122
2710
|
id,
|
|
2123
2711
|
content: label,
|
|
2124
2712
|
height: 1,
|
|
@@ -2181,7 +2769,7 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2181
2769
|
for (const device of snapshot?.devices ?? []) {
|
|
2182
2770
|
let row = this.rows.get(device.uuid);
|
|
2183
2771
|
if (!row) {
|
|
2184
|
-
const root = new
|
|
2772
|
+
const root = new BoxRenderable5(this._ctx, {
|
|
2185
2773
|
id: `omnius-device:${device.uuid}`,
|
|
2186
2774
|
width: "100%",
|
|
2187
2775
|
flexDirection: "column",
|
|
@@ -2200,9 +2788,9 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2200
2788
|
title.on(RenderableEvents3.FOCUSED, () => this.scroll.scrollChildIntoView(root.id));
|
|
2201
2789
|
const load = new TelemetryRow(this._ctx, "LOAD", `${root.id}:load`, 16);
|
|
2202
2790
|
const memory = new TelemetryRow(this._ctx, "VRAM", `${root.id}:memory`, 16);
|
|
2203
|
-
const plot = (name) => new
|
|
2791
|
+
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 });
|
|
2204
2792
|
const loadGraph = plot("load"), memoryGraph = plot("memory"), history = new DeviceHistory();
|
|
2205
|
-
const reason = new
|
|
2793
|
+
const reason = new TextRenderable4(this._ctx, {
|
|
2206
2794
|
id: `${root.id}:reason`,
|
|
2207
2795
|
content: "",
|
|
2208
2796
|
width: "100%",
|
|
@@ -2249,6 +2837,12 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2249
2837
|
this.fitHeight(this.availableRows + 2);
|
|
2250
2838
|
this.refresh();
|
|
2251
2839
|
}
|
|
2840
|
+
get isExpanded() {
|
|
2841
|
+
return this.expanded;
|
|
2842
|
+
}
|
|
2843
|
+
setExpanded(expanded) {
|
|
2844
|
+
if (this.expanded !== expanded) this.toggle();
|
|
2845
|
+
}
|
|
2252
2846
|
fitHeight(railRows) {
|
|
2253
2847
|
this.availableRows = Math.max(0, railRows - 2);
|
|
2254
2848
|
this.visible = Boolean(this.snapshot) && this.availableRows >= 3;
|
|
@@ -2307,7 +2901,7 @@ var DeviceMonitor = class extends BoxRenderable4 {
|
|
|
2307
2901
|
];
|
|
2308
2902
|
}
|
|
2309
2903
|
};
|
|
2310
|
-
var ChannelMap = class extends
|
|
2904
|
+
var ChannelMap = class extends BoxRenderable5 {
|
|
2311
2905
|
constructor(renderer2, id, inspect, reveal) {
|
|
2312
2906
|
super(renderer2, {
|
|
2313
2907
|
id,
|
|
@@ -2339,7 +2933,7 @@ var ChannelMap = class extends BoxRenderable4 {
|
|
|
2339
2933
|
if (!this.channels.has(agent.id))
|
|
2340
2934
|
this.channels.set(agent.id, this.channels.size + 1);
|
|
2341
2935
|
if (!this.rows.has(agent.id)) {
|
|
2342
|
-
const row = new
|
|
2936
|
+
const row = new TextRenderable4(this._ctx, {
|
|
2343
2937
|
id: `${this.id}:channel:${agent.id}`,
|
|
2344
2938
|
content: "",
|
|
2345
2939
|
width: "100%",
|
|
@@ -2405,7 +2999,7 @@ var ChannelMap = class extends BoxRenderable4 {
|
|
|
2405
2999
|
}
|
|
2406
3000
|
}
|
|
2407
3001
|
};
|
|
2408
|
-
var InstrumentRail = class extends
|
|
3002
|
+
var InstrumentRail = class extends BoxRenderable5 {
|
|
2409
3003
|
scroll;
|
|
2410
3004
|
inferenceHeader;
|
|
2411
3005
|
sessionHeader;
|
|
@@ -2459,7 +3053,7 @@ var InstrumentRail = class extends BoxRenderable4 {
|
|
|
2459
3053
|
() => this.reveal(this.inferenceHeader)
|
|
2460
3054
|
);
|
|
2461
3055
|
this.scroll.add(this.inferenceHeader);
|
|
2462
|
-
this.inference = new
|
|
3056
|
+
this.inference = new BoxRenderable5(renderer2, {
|
|
2463
3057
|
id: `${id}:inference-body`,
|
|
2464
3058
|
width: "100%",
|
|
2465
3059
|
flexDirection: "column",
|
|
@@ -2474,7 +3068,7 @@ var InstrumentRail = class extends BoxRenderable4 {
|
|
|
2474
3068
|
};
|
|
2475
3069
|
addRow(this.inference, "route", "ROUTE");
|
|
2476
3070
|
addRow(this.inference, "backend", "BACKEND");
|
|
2477
|
-
this.model = new
|
|
3071
|
+
this.model = new TextRenderable4(renderer2, {
|
|
2478
3072
|
id: `${id}:model`,
|
|
2479
3073
|
content: "MODEL --",
|
|
2480
3074
|
width: "100%",
|
|
@@ -2503,7 +3097,7 @@ var InstrumentRail = class extends BoxRenderable4 {
|
|
|
2503
3097
|
});
|
|
2504
3098
|
this.contextHeader.on(RenderableEvents3.FOCUSED, () => this.reveal(this.contextHeader));
|
|
2505
3099
|
this.inference.add(this.contextHeader);
|
|
2506
|
-
this.contextDetails = new
|
|
3100
|
+
this.contextDetails = new BoxRenderable5(renderer2, { id: `${id}:context-detail-body`, width: "100%", flexDirection: "column", flexShrink: 0, visible: false });
|
|
2507
3101
|
this.inference.add(this.contextDetails);
|
|
2508
3102
|
this.contextHeader.update("CONTEXT DETAILS", false);
|
|
2509
3103
|
addRow(this.contextDetails, "messages", "MESSAGES");
|
|
@@ -2522,7 +3116,7 @@ var InstrumentRail = class extends BoxRenderable4 {
|
|
|
2522
3116
|
() => this.reveal(this.sessionHeader)
|
|
2523
3117
|
);
|
|
2524
3118
|
this.scroll.add(this.sessionHeader);
|
|
2525
|
-
this.session = new
|
|
3119
|
+
this.session = new BoxRenderable5(renderer2, {
|
|
2526
3120
|
id: `${id}:session-body`,
|
|
2527
3121
|
width: "100%",
|
|
2528
3122
|
flexDirection: "column",
|
|
@@ -2605,7 +3199,7 @@ var InstrumentRail = class extends BoxRenderable4 {
|
|
|
2605
3199
|
applyTheme(colors) {
|
|
2606
3200
|
this.backgroundColor = colors.background;
|
|
2607
3201
|
const visit = (node) => {
|
|
2608
|
-
if (node instanceof
|
|
3202
|
+
if (node instanceof TextRenderable4) {
|
|
2609
3203
|
node.fg = colors.foreground;
|
|
2610
3204
|
node.bg = colors.background;
|
|
2611
3205
|
}
|
|
@@ -2624,6 +3218,25 @@ var InstrumentRail = class extends BoxRenderable4 {
|
|
|
2624
3218
|
body.visible
|
|
2625
3219
|
);
|
|
2626
3220
|
}
|
|
3221
|
+
capturePresentation() {
|
|
3222
|
+
return {
|
|
3223
|
+
inference: this.inference.visible,
|
|
3224
|
+
session: this.session.visible,
|
|
3225
|
+
context: this.contextHeader.expanded,
|
|
3226
|
+
devices: this.devices.isExpanded,
|
|
3227
|
+
scrollTop: this.scroll.scrollTop,
|
|
3228
|
+
deviceScrollTop: this.devices.scroll.scrollTop
|
|
3229
|
+
};
|
|
3230
|
+
}
|
|
3231
|
+
restorePresentation(state) {
|
|
3232
|
+
if (this.inference.visible !== state.inference) this.toggleSection("inference");
|
|
3233
|
+
if (this.session.visible !== state.session) this.toggleSection("session");
|
|
3234
|
+
this.contextHeader.update("CONTEXT DETAILS", state.context);
|
|
3235
|
+
this.contextDetails.visible = this.contextHeader.visible && state.context;
|
|
3236
|
+
this.devices.setExpanded(state.devices);
|
|
3237
|
+
this.scroll.scrollTo(state.scrollTop);
|
|
3238
|
+
this.devices.scroll.scrollTo(state.deviceScrollTop);
|
|
3239
|
+
}
|
|
2627
3240
|
focusTargets() {
|
|
2628
3241
|
if (!this.visible) return [];
|
|
2629
3242
|
return [
|
|
@@ -3448,6 +4061,7 @@ var ALIASES = {
|
|
|
3448
4061
|
update: ["upgrade"],
|
|
3449
4062
|
indicator: ["tray"],
|
|
3450
4063
|
listen: ["mic"],
|
|
4064
|
+
sound: ["audio"],
|
|
3451
4065
|
pointcloud: ["points", "pcl", "point"],
|
|
3452
4066
|
neovim: ["nvim"],
|
|
3453
4067
|
apikey: ["key"],
|
|
@@ -4082,7 +4696,7 @@ var VimComposer = class {
|
|
|
4082
4696
|
};
|
|
4083
4697
|
|
|
4084
4698
|
// packages/cli/src/tui/native/components/selection-menu.ts
|
|
4085
|
-
import { BoxRenderable as
|
|
4699
|
+
import { BoxRenderable as BoxRenderable6, CliRenderEvents as CliRenderEvents3, TextAttributes as TextAttributes6, TextRenderable as TextRenderable5 } from "@opentui/core";
|
|
4086
4700
|
var NativeSelectionMenu = class {
|
|
4087
4701
|
constructor(renderer2, colors, copy, restoreFocus) {
|
|
4088
4702
|
this.renderer = renderer2;
|
|
@@ -4110,7 +4724,7 @@ var NativeSelectionMenu = class {
|
|
|
4110
4724
|
this.selectedText = text;
|
|
4111
4725
|
this.anchor = { x, y };
|
|
4112
4726
|
this.previousFocus = this.renderer.currentFocusedRenderable;
|
|
4113
|
-
this.overlay = new
|
|
4727
|
+
this.overlay = new BoxRenderable6(this.renderer, {
|
|
4114
4728
|
id: "omnius-selection-menu",
|
|
4115
4729
|
position: "absolute",
|
|
4116
4730
|
left: 0,
|
|
@@ -4126,7 +4740,7 @@ var NativeSelectionMenu = class {
|
|
|
4126
4740
|
event.stopPropagation();
|
|
4127
4741
|
}
|
|
4128
4742
|
});
|
|
4129
|
-
this.panel = new
|
|
4743
|
+
this.panel = new BoxRenderable6(this.renderer, {
|
|
4130
4744
|
id: "omnius-selection-menu-panel",
|
|
4131
4745
|
position: "absolute",
|
|
4132
4746
|
width: 14,
|
|
@@ -4140,7 +4754,7 @@ var NativeSelectionMenu = class {
|
|
|
4140
4754
|
event.stopPropagation();
|
|
4141
4755
|
}
|
|
4142
4756
|
});
|
|
4143
|
-
const action = new
|
|
4757
|
+
const action = new TextRenderable5(this.renderer, {
|
|
4144
4758
|
id: "omnius-selection-copy",
|
|
4145
4759
|
content: "COPY",
|
|
4146
4760
|
height: 1,
|
|
@@ -4189,7 +4803,7 @@ var NativeSelectionMenu = class {
|
|
|
4189
4803
|
if (!this.panel) return;
|
|
4190
4804
|
this.panel.backgroundColor = colors.background;
|
|
4191
4805
|
this.frame?.setColors(colors);
|
|
4192
|
-
for (const child of this.panel.getChildren()) if (child instanceof
|
|
4806
|
+
for (const child of this.panel.getChildren()) if (child instanceof TextRenderable5) {
|
|
4193
4807
|
child.fg = colors.foreground;
|
|
4194
4808
|
child.bg = colors.background;
|
|
4195
4809
|
}
|
|
@@ -4215,8 +4829,8 @@ var NativeSelectionMenu = class {
|
|
|
4215
4829
|
};
|
|
4216
4830
|
|
|
4217
4831
|
// packages/cli/src/tui/native/components/tab-strip.ts
|
|
4218
|
-
import { BoxRenderable as
|
|
4219
|
-
var NativeTabStrip = class extends
|
|
4832
|
+
import { BoxRenderable as BoxRenderable7, CliRenderEvents as CliRenderEvents4, ScrollBoxRenderable as ScrollBoxRenderable4, SliderRenderable, TextAttributes as TextAttributes7, TextRenderable as TextRenderable6 } from "@opentui/core";
|
|
4833
|
+
var NativeTabStrip = class extends BoxRenderable7 {
|
|
4220
4834
|
constructor(renderer2, options) {
|
|
4221
4835
|
super(renderer2, {
|
|
4222
4836
|
id: options.id,
|
|
@@ -4295,7 +4909,7 @@ var NativeTabStrip = class extends BoxRenderable6 {
|
|
|
4295
4909
|
for (const [index, action] of items.entries()) {
|
|
4296
4910
|
let entry = this.buttons.get(action.id);
|
|
4297
4911
|
if (!entry) {
|
|
4298
|
-
const button = new
|
|
4912
|
+
const button = new TextRenderable6(this.renderer, {
|
|
4299
4913
|
id: `${this.options.prefix}:${action.id}`,
|
|
4300
4914
|
content: "",
|
|
4301
4915
|
height: 1,
|
|
@@ -4328,7 +4942,7 @@ var NativeTabStrip = class extends BoxRenderable6 {
|
|
|
4328
4942
|
entry.blocked = busy || Boolean(action.disabled);
|
|
4329
4943
|
entry.button.focusable = entry.active || !entry.blocked;
|
|
4330
4944
|
const label = plainText(action.label);
|
|
4331
|
-
const content =
|
|
4945
|
+
const content = ` ${label} `;
|
|
4332
4946
|
if (entry.button.plainText !== content) entry.button.content = content;
|
|
4333
4947
|
this.style(entry);
|
|
4334
4948
|
if (this.scroll.getChildren()[index] !== entry.button) this.scroll.add(entry.button, index);
|
|
@@ -4382,6 +4996,10 @@ var NativeTabStrip = class extends BoxRenderable6 {
|
|
|
4382
4996
|
styleNativeScrollbars(this.scroll, colors);
|
|
4383
4997
|
styleNativeSlider(this.rail, colors);
|
|
4384
4998
|
}
|
|
4999
|
+
restoreOffset(offset2) {
|
|
5000
|
+
this.reveal = void 0;
|
|
5001
|
+
this.scroll.scrollLeft = offset2;
|
|
5002
|
+
}
|
|
4385
5003
|
destroySelf() {
|
|
4386
5004
|
this.renderer.off(CliRenderEvents4.FRAME, this.syncScroll);
|
|
4387
5005
|
super.destroySelf();
|
|
@@ -4395,13 +5013,13 @@ var NativeFrontend = class {
|
|
|
4395
5013
|
this.renderer = renderer2;
|
|
4396
5014
|
this.emit = emit;
|
|
4397
5015
|
const colors = palette(initialTheme);
|
|
4398
|
-
this.context = { renderer: renderer2, colors, syntax: SyntaxStyle2.fromStyles({}, renderer2.nativeScene), emit, terminals: /* @__PURE__ */ new Map() };
|
|
5016
|
+
this.context = { renderer: renderer2, colors, syntax: SyntaxStyle2.fromStyles({}, renderer2.nativeScene), emit, terminals: /* @__PURE__ */ new Map(), mediaViews: /* @__PURE__ */ new Set() };
|
|
4399
5017
|
this.disposeSelectionContrast = installDefaultSelectionContrast(renderer2);
|
|
4400
5018
|
this.clipboard = options.clipboard ?? createClipboard({ host: createHostClipboard({ timeoutMs: 1500 }), terminal: createRendererClipboardAdapter(renderer2) });
|
|
4401
5019
|
this.selectionMenu = new NativeSelectionMenu(renderer2, colors, (text) => {
|
|
4402
5020
|
void this.copy(text);
|
|
4403
5021
|
}, () => this.restoreFocus());
|
|
4404
|
-
this.root = new
|
|
5022
|
+
this.root = new BoxRenderable8(renderer2, {
|
|
4405
5023
|
id: "omnius-native",
|
|
4406
5024
|
width: "100%",
|
|
4407
5025
|
height: "100%",
|
|
@@ -4409,7 +5027,7 @@ var NativeFrontend = class {
|
|
|
4409
5027
|
backgroundColor: colors.background
|
|
4410
5028
|
});
|
|
4411
5029
|
renderer2.root.add(this.root);
|
|
4412
|
-
this.header = new
|
|
5030
|
+
this.header = new BoxRenderable8(renderer2, {
|
|
4413
5031
|
id: "omnius-header",
|
|
4414
5032
|
width: "100%",
|
|
4415
5033
|
minWidth: 0,
|
|
@@ -4424,8 +5042,7 @@ var NativeFrontend = class {
|
|
|
4424
5042
|
if (this.header.height > 0) buffer.drawText(
|
|
4425
5043
|
formatSignalDivider(this.header.width, {
|
|
4426
5044
|
direction: "top",
|
|
4427
|
-
|
|
4428
|
-
rightTextStart: Math.min(this.detailButton.x, this.headerActions.visible ? this.headerActions.x : this.detailButton.x) - this.header.x
|
|
5045
|
+
sidebarColumn: this.instrumentDivider.visible ? this.instrumentDivider.x - this.header.x : void 0
|
|
4429
5046
|
}),
|
|
4430
5047
|
this.header.x,
|
|
4431
5048
|
this.header.y + this.header.height - 1,
|
|
@@ -4434,9 +5051,9 @@ var NativeFrontend = class {
|
|
|
4434
5051
|
TextAttributes8.DIM
|
|
4435
5052
|
);
|
|
4436
5053
|
};
|
|
4437
|
-
const headerRow = new
|
|
5054
|
+
const headerRow = new BoxRenderable8(renderer2, { id: "omnius-header-row", width: "100%", minWidth: 0, minHeight: 1, flexDirection: "row", gap: 1 });
|
|
4438
5055
|
this.header.add(headerRow);
|
|
4439
|
-
this.identity = new
|
|
5056
|
+
this.identity = new TextRenderable7(renderer2, {
|
|
4440
5057
|
id: "omnius-identity",
|
|
4441
5058
|
content: "Omnius",
|
|
4442
5059
|
fg: colors.foreground,
|
|
@@ -4474,9 +5091,9 @@ var NativeFrontend = class {
|
|
|
4474
5091
|
verticalScrollbarOptions: { visible: false }
|
|
4475
5092
|
});
|
|
4476
5093
|
headerRow.add(this.headerActions);
|
|
4477
|
-
this.headerPanel = new
|
|
5094
|
+
this.headerPanel = new TextRenderable7(renderer2, { id: "omnius-header-panel", content: "", width: "100%", wrapMode: "word", visible: false });
|
|
4478
5095
|
this.header.add(this.headerPanel);
|
|
4479
|
-
this.detailButton = new
|
|
5096
|
+
this.detailButton = new TextRenderable7(renderer2, {
|
|
4480
5097
|
id: "omnius-details-toggle",
|
|
4481
5098
|
content: "+ DETAILS",
|
|
4482
5099
|
height: 1,
|
|
@@ -4509,7 +5126,7 @@ var NativeFrontend = class {
|
|
|
4509
5126
|
control.attributes = attributes;
|
|
4510
5127
|
});
|
|
4511
5128
|
}
|
|
4512
|
-
this.sessionRow = new
|
|
5129
|
+
this.sessionRow = new BoxRenderable8(renderer2, {
|
|
4513
5130
|
id: "omnius-sessions-row",
|
|
4514
5131
|
width: "100%",
|
|
4515
5132
|
height: 1,
|
|
@@ -4527,7 +5144,7 @@ var NativeFrontend = class {
|
|
|
4527
5144
|
activate: (id) => this.emitAction("session", id)
|
|
4528
5145
|
});
|
|
4529
5146
|
this.sessionRow.add(this.sessions);
|
|
4530
|
-
this.newSession = new
|
|
5147
|
+
this.newSession = new TextRenderable7(renderer2, {
|
|
4531
5148
|
id: "omnius-session-new",
|
|
4532
5149
|
content: "+ NEW",
|
|
4533
5150
|
width: 5,
|
|
@@ -4556,13 +5173,15 @@ var NativeFrontend = class {
|
|
|
4556
5173
|
this.newSession.on("focused", styleNew);
|
|
4557
5174
|
this.newSession.on("blurred", styleNew);
|
|
4558
5175
|
this.sessionRow.add(this.newSession);
|
|
4559
|
-
this.routeWarning = new
|
|
5176
|
+
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 });
|
|
4560
5177
|
this.root.add(this.routeWarning);
|
|
4561
|
-
this.taskPane = new
|
|
5178
|
+
this.taskPane = new BoxRenderable8(renderer2, { id: "omnius-tasks", width: "100%", flexDirection: "column", maxHeight: 6, flexShrink: 0, overflow: "hidden", visible: false });
|
|
4562
5179
|
this.tasks = new NativeBlockList(this.context, this.taskPane);
|
|
4563
5180
|
this.root.add(this.taskPane);
|
|
4564
|
-
this.body = new
|
|
5181
|
+
this.body = new BoxRenderable8(renderer2, { id: "omnius-body", width: "100%", flexDirection: "row", flexGrow: 1, minHeight: 1 });
|
|
4565
5182
|
this.root.add(this.body);
|
|
5183
|
+
this.transcriptPane = new BoxRenderable8(renderer2, { id: "omnius-transcript-pane", flexDirection: "column", flexGrow: 1, flexShrink: 1, minWidth: 0, minHeight: 1 });
|
|
5184
|
+
this.body.add(this.transcriptPane);
|
|
4566
5185
|
this.scroll = new ScrollBoxRenderable5(renderer2, {
|
|
4567
5186
|
id: "omnius-conversation",
|
|
4568
5187
|
flexGrow: 1,
|
|
@@ -4618,7 +5237,7 @@ var NativeFrontend = class {
|
|
|
4618
5237
|
}
|
|
4619
5238
|
} }
|
|
4620
5239
|
});
|
|
4621
|
-
this.
|
|
5240
|
+
this.transcriptPane.add(this.scroll);
|
|
4622
5241
|
this.content = new NativeBlockList(this.context, this.scroll);
|
|
4623
5242
|
this.instrumentDivider = new InstrumentDivider(renderer2, {
|
|
4624
5243
|
resize: (column) => this.resizeInstruments(column),
|
|
@@ -4636,7 +5255,7 @@ var NativeFrontend = class {
|
|
|
4636
5255
|
this.root.onMouseUp = (event) => this.instrumentDivider.handleRelease(event);
|
|
4637
5256
|
this.instruments = new InstrumentRail(renderer2, { colors, onInspectAgent: (id) => this.emitAction("view", id), onAction: (command2) => this.emitAction(command2) });
|
|
4638
5257
|
this.body.add(this.instruments);
|
|
4639
|
-
this.embeddedPane = new
|
|
5258
|
+
this.embeddedPane = new BoxRenderable8(renderer2, {
|
|
4640
5259
|
id: "omnius-editor-pane",
|
|
4641
5260
|
width: "50%",
|
|
4642
5261
|
flexShrink: 0,
|
|
@@ -4647,7 +5266,7 @@ var NativeFrontend = class {
|
|
|
4647
5266
|
visible: false
|
|
4648
5267
|
});
|
|
4649
5268
|
this.body.add(this.embeddedPane);
|
|
4650
|
-
this.liveButton = new
|
|
5269
|
+
this.liveButton = new TextRenderable7(renderer2, {
|
|
4651
5270
|
id: "omnius-live-button",
|
|
4652
5271
|
content: "↓ Live",
|
|
4653
5272
|
width: "100%",
|
|
@@ -4669,9 +5288,9 @@ var NativeFrontend = class {
|
|
|
4669
5288
|
}
|
|
4670
5289
|
});
|
|
4671
5290
|
this.liveButton.focusable = true;
|
|
4672
|
-
this.
|
|
4673
|
-
this.queue = new
|
|
4674
|
-
this.
|
|
5291
|
+
this.transcriptPane.add(this.liveButton);
|
|
5292
|
+
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 });
|
|
5293
|
+
this.transcriptPane.add(this.queue);
|
|
4675
5294
|
this.suggestions = new NativeSelectRenderable(renderer2, {
|
|
4676
5295
|
id: "omnius-suggestions",
|
|
4677
5296
|
width: "100%",
|
|
@@ -4688,10 +5307,10 @@ var NativeFrontend = class {
|
|
|
4688
5307
|
});
|
|
4689
5308
|
this.suggestions.onActivate = () => this.acceptSuggestion();
|
|
4690
5309
|
this.suggestions.on("itemSelected", () => this.acceptSuggestion());
|
|
4691
|
-
this.
|
|
4692
|
-
this.status = new
|
|
4693
|
-
this.
|
|
4694
|
-
this.footer = new
|
|
5310
|
+
this.transcriptPane.add(this.suggestions);
|
|
5311
|
+
this.status = new BoxRenderable8(renderer2, { id: "omnius-live-status", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2, visible: false });
|
|
5312
|
+
this.transcriptPane.add(this.status);
|
|
5313
|
+
this.footer = new BoxRenderable8(renderer2, {
|
|
4695
5314
|
id: "omnius-input-box",
|
|
4696
5315
|
width: "100%",
|
|
4697
5316
|
flexShrink: 0,
|
|
@@ -4700,7 +5319,7 @@ var NativeFrontend = class {
|
|
|
4700
5319
|
flexDirection: "column"
|
|
4701
5320
|
});
|
|
4702
5321
|
this.root.add(this.footer);
|
|
4703
|
-
this.footerRule = new
|
|
5322
|
+
this.footerRule = new BoxRenderable8(renderer2, {
|
|
4704
5323
|
id: "omnius-input-rule",
|
|
4705
5324
|
width: "100%",
|
|
4706
5325
|
height: 1,
|
|
@@ -4725,13 +5344,12 @@ var NativeFrontend = class {
|
|
|
4725
5344
|
this.footerRule.renderBefore = (buffer) => {
|
|
4726
5345
|
buffer.drawText(formatSignalDivider(this.footerRule.width, {
|
|
4727
5346
|
direction: "bottom",
|
|
4728
|
-
|
|
4729
|
-
sidebarColumn: this.instrumentDivider.visible && this.instruments.visible ? this.instrumentDivider.x - this.footerRule.x : void 0
|
|
5347
|
+
sidebarColumn: this.instrumentDivider.visible ? this.instrumentDivider.x - this.footerRule.x : void 0
|
|
4730
5348
|
}), this.footerRule.x, this.footerRule.y, this.context.colors.foreground, this.context.colors.background, TextAttributes8.DIM);
|
|
4731
5349
|
};
|
|
4732
|
-
const inputRow = new
|
|
5350
|
+
const inputRow = new BoxRenderable8(renderer2, { id: "omnius-input-row", width: "100%", flexDirection: "row", gap: 1 });
|
|
4733
5351
|
this.footer.add(inputRow);
|
|
4734
|
-
this.prompt = new
|
|
5352
|
+
this.prompt = new TextRenderable7(renderer2, { id: "omnius-prompt", content: "❯", fg: colors.accent, wrapMode: "none", selectable: false, flexShrink: 0 });
|
|
4735
5353
|
inputRow.add(this.prompt);
|
|
4736
5354
|
this.editor = new TextareaRenderable2(renderer2, {
|
|
4737
5355
|
id: "omnius-input",
|
|
@@ -4751,7 +5369,7 @@ var NativeFrontend = class {
|
|
|
4751
5369
|
onCursorChange: () => this.editorChanged(),
|
|
4752
5370
|
onSubmit: () => this.submit()
|
|
4753
5371
|
});
|
|
4754
|
-
this.vimMode = new
|
|
5372
|
+
this.vimMode = new TextRenderable7(renderer2, {
|
|
4755
5373
|
id: "omnius-vim-mode",
|
|
4756
5374
|
content: "INSERT",
|
|
4757
5375
|
height: 1,
|
|
@@ -4772,17 +5390,17 @@ var NativeFrontend = class {
|
|
|
4772
5390
|
this.renderer.requestRender();
|
|
4773
5391
|
});
|
|
4774
5392
|
inputRow.add(this.editor);
|
|
4775
|
-
this.enhance = new
|
|
5393
|
+
this.enhance = new BoxRenderable8(renderer2, { id: "omnius-enhance", flexDirection: "row", gap: 1, flexShrink: 0, visible: false });
|
|
4776
5394
|
inputRow.add(this.enhance);
|
|
4777
|
-
this.activity = new
|
|
5395
|
+
this.activity = new TextRenderable7(renderer2, { id: "omnius-activity", content: "", flexGrow: 1, minWidth: 0, height: 1, wrapMode: "none", truncate: true, visible: false, fg: colors.accent });
|
|
4778
5396
|
this.status.add(this.activity);
|
|
4779
|
-
this.media = new
|
|
4780
|
-
this.mediaText = new
|
|
5397
|
+
this.media = new BoxRenderable8(renderer2, { id: "omnius-media", height: 1, minWidth: 0, flexShrink: 1, flexDirection: "row", gap: 1, visible: false });
|
|
5398
|
+
this.mediaText = new TextRenderable7(renderer2, { id: "omnius-media-text", content: "", flexGrow: 1, minWidth: 0, wrapMode: "none", truncate: true, fg: colors.accent });
|
|
4781
5399
|
this.media.add(this.mediaText);
|
|
4782
|
-
this.micTrack = new
|
|
5400
|
+
this.micTrack = new TextRenderable7(renderer2, { id: "omnius-mic-meter", width: 12, height: 1, flexShrink: 0, fg: colors.foreground, visible: false });
|
|
4783
5401
|
this.media.add(this.micTrack);
|
|
4784
5402
|
this.status.add(this.media);
|
|
4785
|
-
this.copyFeedback = new
|
|
5403
|
+
this.copyFeedback = new TextRenderable7(renderer2, {
|
|
4786
5404
|
id: "omnius-copy-feedback",
|
|
4787
5405
|
content: "",
|
|
4788
5406
|
height: 1,
|
|
@@ -4793,14 +5411,14 @@ var NativeFrontend = class {
|
|
|
4793
5411
|
visible: false
|
|
4794
5412
|
});
|
|
4795
5413
|
this.status.add(this.copyFeedback);
|
|
4796
|
-
this.metricsRow = new
|
|
4797
|
-
this.keyHints = new
|
|
5414
|
+
this.metricsRow = new BoxRenderable8(renderer2, { id: "omnius-metrics-row", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 1 });
|
|
5415
|
+
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 });
|
|
4798
5416
|
this.metricsRow.add(this.keyHints);
|
|
4799
|
-
this.metricsStartActions = new
|
|
5417
|
+
this.metricsStartActions = new BoxRenderable8(renderer2, { id: "omnius-metrics-start-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
|
|
4800
5418
|
this.metricsRow.add(this.metricsStartActions);
|
|
4801
|
-
this.metrics = new
|
|
5419
|
+
this.metrics = new TextRenderable7(renderer2, { id: "omnius-metrics", content: "", height: 1, wrapMode: "none", truncate: true, fg: colors.dim, flexShrink: 1, flexGrow: 1, minWidth: 0 });
|
|
4802
5420
|
this.metricsRow.add(this.metrics);
|
|
4803
|
-
this.metricsEndActions = new
|
|
5421
|
+
this.metricsEndActions = new BoxRenderable8(renderer2, { id: "omnius-metrics-end-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
|
|
4804
5422
|
this.metricsRow.add(this.metricsEndActions);
|
|
4805
5423
|
this.root.add(this.metricsRow);
|
|
4806
5424
|
this.modals = new NativeModalStack(this.context, () => this.restoreFocus());
|
|
@@ -4833,6 +5451,7 @@ var NativeFrontend = class {
|
|
|
4833
5451
|
taskPane;
|
|
4834
5452
|
tasks;
|
|
4835
5453
|
body;
|
|
5454
|
+
transcriptPane;
|
|
4836
5455
|
instruments;
|
|
4837
5456
|
instrumentDivider;
|
|
4838
5457
|
detailButton;
|
|
@@ -4884,6 +5503,9 @@ var NativeFrontend = class {
|
|
|
4884
5503
|
destroyed = false;
|
|
4885
5504
|
pendingScrollRestore;
|
|
4886
5505
|
viewScroll = /* @__PURE__ */ new Map();
|
|
5506
|
+
viewDisclosures = /* @__PURE__ */ new Map();
|
|
5507
|
+
pendingDisclosures;
|
|
5508
|
+
pendingInterface;
|
|
4887
5509
|
embeddedId;
|
|
4888
5510
|
selectionArmed = false;
|
|
4889
5511
|
update(state, patch) {
|
|
@@ -4893,7 +5515,9 @@ var NativeFrontend = class {
|
|
|
4893
5515
|
const viewChanged = previousView !== void 0 && previousView !== currentView;
|
|
4894
5516
|
if (viewChanged) {
|
|
4895
5517
|
this.viewScroll.set(previousView, { top: this.scroll.scrollTop, live: this.offset === 0 });
|
|
5518
|
+
this.viewDisclosures.set(previousView, this.content.captureDisclosures(this.tasks.captureDisclosures()));
|
|
4896
5519
|
this.pendingScrollRestore = this.viewScroll.get(currentView) ?? { top: 0, live: true };
|
|
5520
|
+
this.pendingDisclosures = this.viewDisclosures.get(currentView);
|
|
4897
5521
|
this.newEntries = 0;
|
|
4898
5522
|
}
|
|
4899
5523
|
this.state = state;
|
|
@@ -4928,6 +5552,11 @@ var NativeFrontend = class {
|
|
|
4928
5552
|
if (this.offset > 0 && !viewChanged && !patch.reset) this.newEntries += patch.upsert.filter((block) => !this.content.views.has(block.id)).length;
|
|
4929
5553
|
this.content.patch(patch);
|
|
4930
5554
|
}
|
|
5555
|
+
if (this.pendingDisclosures) {
|
|
5556
|
+
this.content.restoreDisclosures(this.pendingDisclosures);
|
|
5557
|
+
this.tasks.restoreDisclosures(this.pendingDisclosures);
|
|
5558
|
+
this.pendingDisclosures = void 0;
|
|
5559
|
+
}
|
|
4931
5560
|
this.queue.content = state.queued.length ? `Queued (${state.queued.length}) · ${state.queued.join(" · ")}` : "";
|
|
4932
5561
|
this.queue.visible = state.queued.length > 0;
|
|
4933
5562
|
const suggestionSignature = JSON.stringify(state.suggestions);
|
|
@@ -4976,7 +5605,7 @@ var NativeFrontend = class {
|
|
|
4976
5605
|
for (const action of actions) {
|
|
4977
5606
|
const colors = this.context.colors;
|
|
4978
5607
|
const attributes = action.disabled ? TextAttributes8.DIM : action.active ? TextAttributes8.BOLD | TextAttributes8.UNDERLINE : 0;
|
|
4979
|
-
const button = new
|
|
5608
|
+
const button = new TextRenderable7(this.renderer, {
|
|
4980
5609
|
id: `${prefix}:${action.id}`,
|
|
4981
5610
|
content: styledText(action.label),
|
|
4982
5611
|
flexShrink: 0,
|
|
@@ -5122,14 +5751,17 @@ var NativeFrontend = class {
|
|
|
5122
5751
|
const shown = !this.embeddedPane.visible && (wide ? this.detailsOpen ?? true : this.narrowDetailsOpen);
|
|
5123
5752
|
const horizontal = wide || this.embeddedPane.visible && width >= 80;
|
|
5124
5753
|
this.body.flexDirection = horizontal ? "row" : "column";
|
|
5125
|
-
this.
|
|
5126
|
-
this.
|
|
5754
|
+
this.transcriptPane.height = horizontal ? "100%" : "auto";
|
|
5755
|
+
this.transcriptPane.flexBasis = horizontal ? "auto" : 0;
|
|
5756
|
+
this.scroll.height = "auto";
|
|
5757
|
+
this.scroll.flexBasis = 0;
|
|
5127
5758
|
this.instruments.visible = shown;
|
|
5128
5759
|
this.instrumentDivider.visible = wide && !this.embeddedPane.visible;
|
|
5129
5760
|
this.instrumentDivider.setCollapsed(!shown);
|
|
5130
5761
|
const railWidth = Math.max(24, Math.min(width - 41, this.sidebarWidth ?? Math.floor(width * 0.38)));
|
|
5131
5762
|
this.instruments.width = wide ? railWidth : "100%";
|
|
5132
|
-
this.
|
|
5763
|
+
this.transcriptPane.width = wide && this.instrumentDivider.visible ? width - (shown ? railWidth : 0) - 1 : this.embeddedPane.visible && width >= 80 ? "50%" : "100%";
|
|
5764
|
+
this.scroll.width = "100%";
|
|
5133
5765
|
const inspectorHeight = Math.max(4, Math.min(9, Math.floor(this.renderer.terminalHeight / 3)));
|
|
5134
5766
|
this.instruments.height = wide ? "100%" : inspectorHeight;
|
|
5135
5767
|
this.instruments.maxHeight = wide ? "100%" : inspectorHeight;
|
|
@@ -5177,6 +5809,13 @@ var NativeFrontend = class {
|
|
|
5177
5809
|
}
|
|
5178
5810
|
onFrame = () => {
|
|
5179
5811
|
if (this.destroyed) return;
|
|
5812
|
+
if (this.pendingInterface) {
|
|
5813
|
+
const state = this.pendingInterface;
|
|
5814
|
+
this.pendingInterface = void 0;
|
|
5815
|
+
this.instruments.restorePresentation(state.instruments);
|
|
5816
|
+
this.sessions.restoreOffset(state.tabs.sessions);
|
|
5817
|
+
this.tabs.restoreOffset(state.tabs.agents);
|
|
5818
|
+
}
|
|
5180
5819
|
if (this.pendingScrollRestore) {
|
|
5181
5820
|
const restore = this.pendingScrollRestore;
|
|
5182
5821
|
this.pendingScrollRestore = void 0;
|
|
@@ -5186,10 +5825,11 @@ var NativeFrontend = class {
|
|
|
5186
5825
|
const height = Math.max(1, Math.min(8, this.editor.editorView.getTotalVirtualLineCount(), this.renderer.terminalHeight - 8));
|
|
5187
5826
|
if (height !== this.editor.height) this.editor.height = height;
|
|
5188
5827
|
this.layoutTabStrips();
|
|
5189
|
-
const
|
|
5190
|
-
|
|
5191
|
-
this.
|
|
5192
|
-
|
|
5828
|
+
for (const media of this.context.mediaViews ?? []) media.reconcile({ x: this.scroll.viewport.x, y: this.scroll.viewport.y, width: this.scroll.viewport.width, height: this.scroll.viewport.height }, !this.paused);
|
|
5829
|
+
const offset2 = this.offset;
|
|
5830
|
+
if (offset2 === 0) this.newEntries = 0;
|
|
5831
|
+
this.liveButton.visible = offset2 > 0;
|
|
5832
|
+
const liveLabel = offset2 > 0 ? `↓ Live${this.newEntries ? ` · ${this.newEntries} new` : ""}` : "↓ Live";
|
|
5193
5833
|
if (this.liveButton.plainText !== liveLabel) this.liveButton.content = liveLabel;
|
|
5194
5834
|
const event = { type: "viewport", offset: this.scroll.scrollTop, height: this.scroll.viewport.height, width: this.scroll.viewport.width, total: this.scroll.scrollHeight };
|
|
5195
5835
|
const signature = JSON.stringify(event);
|
|
@@ -5456,7 +6096,7 @@ var NativeFrontend = class {
|
|
|
5456
6096
|
const target = targets[(current + direction + targets.length) % targets.length];
|
|
5457
6097
|
target.focus();
|
|
5458
6098
|
if (target.id.startsWith("header:")) this.headerActions.scrollChildIntoView(target.id);
|
|
5459
|
-
else if (target.id.startsWith("block-title:") || target.id.startsWith("block-action:")) {
|
|
6099
|
+
else if (target.id.startsWith("block-title:") || target.id.startsWith("block-action:") || target.id.startsWith("media-control:") || target.id.startsWith("media-preview:")) {
|
|
5460
6100
|
let block = target;
|
|
5461
6101
|
while (block && !block.id.startsWith("block:")) block = block.parent;
|
|
5462
6102
|
if (block) this.scroll.scrollChildIntoView(block.id);
|
|
@@ -5628,6 +6268,52 @@ var NativeFrontend = class {
|
|
|
5628
6268
|
this.restoreFocus();
|
|
5629
6269
|
}
|
|
5630
6270
|
}
|
|
6271
|
+
pauseMedia() {
|
|
6272
|
+
for (const media of this.context.mediaViews ?? []) media.pausePlayback();
|
|
6273
|
+
}
|
|
6274
|
+
captureInterfaceState() {
|
|
6275
|
+
this.flushLatestInput();
|
|
6276
|
+
const key = `${this.state?.sessions?.activeId ?? ""}:${this.state?.activeViewId ?? "main"}:${this.state?.presentation ?? "stack"}`;
|
|
6277
|
+
this.viewScroll.set(key, { top: this.scroll.scrollTop, live: this.offset === 0 });
|
|
6278
|
+
this.viewDisclosures.set(key, this.content.captureDisclosures(this.tasks.captureDisclosures()));
|
|
6279
|
+
return {
|
|
6280
|
+
version: 1,
|
|
6281
|
+
sessionId: this.state?.sessions?.activeId,
|
|
6282
|
+
activeViewId: this.state?.activeViewId ?? "main",
|
|
6283
|
+
presentation: this.state?.presentation ?? "stack",
|
|
6284
|
+
input: { text: this.editor.plainText, cursor: this.inputCursor() },
|
|
6285
|
+
views: Object.fromEntries([...this.viewScroll].slice(-256).map(([id, view]) => [id, { ...view, disclosures: this.viewDisclosures.get(id) ?? {} }])),
|
|
6286
|
+
layout: { sidebarWidth: this.sidebarWidth, detailsOpen: this.detailsOpen, narrowDetailsOpen: this.narrowDetailsOpen, headerPanelCollapsed: this.headerPanelCollapsed },
|
|
6287
|
+
instruments: this.instruments.capturePresentation(),
|
|
6288
|
+
tabs: { sessions: this.sessions.scroll.scrollLeft, agents: this.tabs.scroll.scrollLeft }
|
|
6289
|
+
};
|
|
6290
|
+
}
|
|
6291
|
+
restoreInterfaceState(value) {
|
|
6292
|
+
const state = sanitizeNativeInterfaceState(value);
|
|
6293
|
+
if (!state) return;
|
|
6294
|
+
for (const [key2, view2] of Object.entries(state.views)) {
|
|
6295
|
+
this.viewScroll.set(key2, { top: view2.top, live: view2.live });
|
|
6296
|
+
this.viewDisclosures.set(key2, view2.disclosures);
|
|
6297
|
+
}
|
|
6298
|
+
this.sidebarWidth = state.layout.sidebarWidth;
|
|
6299
|
+
this.detailsOpen = state.layout.detailsOpen;
|
|
6300
|
+
this.narrowDetailsOpen = state.layout.narrowDetailsOpen;
|
|
6301
|
+
this.headerPanelCollapsed = state.layout.headerPanelCollapsed;
|
|
6302
|
+
this.headerSignature = "";
|
|
6303
|
+
this.setInput(state.input.text, state.input.cursor);
|
|
6304
|
+
const key = `${this.state?.sessions?.activeId ?? state.sessionId ?? ""}:${this.state?.activeViewId ?? state.activeViewId}:${this.state?.presentation ?? state.presentation}`;
|
|
6305
|
+
const view = this.viewScroll.get(key);
|
|
6306
|
+
if (view) {
|
|
6307
|
+
this.pendingScrollRestore = view;
|
|
6308
|
+
const disclosures = this.viewDisclosures.get(key) ?? {};
|
|
6309
|
+
this.content.restoreDisclosures(disclosures);
|
|
6310
|
+
this.tasks.restoreDisclosures(disclosures);
|
|
6311
|
+
}
|
|
6312
|
+
this.pendingInterface = state;
|
|
6313
|
+
if (this.state) this.update(this.state);
|
|
6314
|
+
this.layoutInstruments();
|
|
6315
|
+
this.renderer.requestRender();
|
|
6316
|
+
}
|
|
5631
6317
|
async dispose() {
|
|
5632
6318
|
if (this.destroyed) return;
|
|
5633
6319
|
this.destroyed = true;
|
|
@@ -5638,9 +6324,14 @@ var NativeFrontend = class {
|
|
|
5638
6324
|
this.renderer.keyInput.off("paste", this.onPaste);
|
|
5639
6325
|
this.renderer.off(CliRenderEvents5.FRAME, this.onFrame);
|
|
5640
6326
|
this.renderer.off(CliRenderEvents5.RESIZE, this.onResize);
|
|
6327
|
+
const mediaClosed = [...this.context.mediaViews ?? []].map((media) => {
|
|
6328
|
+
media.pausePlayback();
|
|
6329
|
+
return media.closed;
|
|
6330
|
+
});
|
|
5641
6331
|
this.modals.destroy();
|
|
5642
6332
|
this.content.destroy();
|
|
5643
6333
|
this.tasks.destroy();
|
|
6334
|
+
await Promise.allSettled(mediaClosed);
|
|
5644
6335
|
this.root.destroyRecursively();
|
|
5645
6336
|
this.context.syntax.destroy();
|
|
5646
6337
|
await this.clipboard.dispose();
|
|
@@ -5660,10 +6351,10 @@ function installTerminalCursorDefaults(renderer2, session) {
|
|
|
5660
6351
|
if (disposed || session.disposed) return Promise.resolve();
|
|
5661
6352
|
requested++;
|
|
5662
6353
|
if (pending) return pending;
|
|
5663
|
-
let
|
|
6354
|
+
let resolve2;
|
|
5664
6355
|
let reject;
|
|
5665
6356
|
const completion = new Promise((done, fail2) => {
|
|
5666
|
-
|
|
6357
|
+
resolve2 = done;
|
|
5667
6358
|
reject = fail2;
|
|
5668
6359
|
});
|
|
5669
6360
|
pending = completion;
|
|
@@ -5676,7 +6367,7 @@ function installTerminalCursorDefaults(renderer2, session) {
|
|
|
5676
6367
|
restored = generation;
|
|
5677
6368
|
}
|
|
5678
6369
|
pending = void 0;
|
|
5679
|
-
|
|
6370
|
+
resolve2();
|
|
5680
6371
|
} catch (error) {
|
|
5681
6372
|
pending = void 0;
|
|
5682
6373
|
reject(error);
|
|
@@ -5742,11 +6433,24 @@ async function command(message) {
|
|
|
5742
6433
|
frontend.command(message.command);
|
|
5743
6434
|
return;
|
|
5744
6435
|
}
|
|
6436
|
+
if (message.type === "interface-capture") {
|
|
6437
|
+
await renderer.idle();
|
|
6438
|
+
reply({ type: "interface-state", id: message.id, state: frontend.captureInterfaceState() });
|
|
6439
|
+
return;
|
|
6440
|
+
}
|
|
6441
|
+
if (message.type === "interface-restore") {
|
|
6442
|
+
frontend.restoreInterfaceState(message.state);
|
|
6443
|
+
renderer.requestRender();
|
|
6444
|
+
await renderer.idle();
|
|
6445
|
+
reply({ type: "ack", id: message.id });
|
|
6446
|
+
return;
|
|
6447
|
+
}
|
|
5745
6448
|
if (message.type === "state") {
|
|
5746
6449
|
frontend.update(message.snapshot, message.content);
|
|
5747
6450
|
renderer.requestRender();
|
|
5748
6451
|
await renderer.idle();
|
|
5749
6452
|
} else if (message.type === "suspend") {
|
|
6453
|
+
frontend.pauseMedia();
|
|
5750
6454
|
await cursorDefaults.restore();
|
|
5751
6455
|
await renderer.suspend();
|
|
5752
6456
|
} else if (message.type === "resume") {
|