omnius 1.0.863 → 1.0.864
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/tray/omnius-checking.ico +0 -0
- package/assets/tray/omnius-checking.png +0 -0
- package/assets/tray/omnius-checking.svg +7 -4
- package/assets/tray/omnius-offline.ico +0 -0
- package/assets/tray/omnius-offline.png +0 -0
- package/assets/tray/omnius-offline.svg +6 -4
- package/assets/tray/omnius-online.ico +0 -0
- package/assets/tray/omnius-online.png +0 -0
- package/assets/tray/omnius-online.svg +5 -4
- package/dist/index.js +2 -2
- package/dist/library.js +11 -11
- package/dist/tui/native/worker.js +2283 -119
- package/docs/DISCOVERY.json +913 -75
- package/docs/DISCOVERY.md +23 -0
- package/docs/work-orders/desktop-projects.md +42 -0
- package/docs/work-orders/evidence/desktop-indicator-registration-20261016.json +23 -0
- package/docs/work-orders/evidence/inference-device-policy-readonly-20261016.json +56 -0
- package/docs/work-orders/evidence/instrument-100x30.png +0 -0
- package/docs/work-orders/evidence/instrument-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-160x48.png +0 -0
- package/docs/work-orders/evidence/instrument-60x20.png +0 -0
- package/docs/work-orders/evidence/instrument-80x24.png +0 -0
- package/docs/work-orders/evidence/instrument-clean-transcript-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-collapse-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-devices-expanded-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-divider-collapsed-160x48.png +0 -0
- package/docs/work-orders/evidence/instrument-divider-resized-160x48.png +0 -0
- package/docs/work-orders/evidence/instrument-help-scroll-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-api-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-api-input-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-config-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-dark-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-dark-60x20.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-light-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-model-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-popup-network-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-production-terminal-live.json +7463 -1873
- package/docs/work-orders/evidence/instrument-report-broker-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-report-gpu-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-report-stats-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-semantic-components-20261016-updated.json +80 -0
- package/docs/work-orders/evidence/instrument-targeted-verification-20261016-updated.json +430 -0
- package/docs/work-orders/evidence/instrument-terminal-light-120x36.png +0 -0
- package/docs/work-orders/evidence/instrument-vim-composer-120x36.png +0 -0
- package/docs/work-orders/evidence/tray-native-host-checking.png +0 -0
- package/docs/work-orders/evidence/tray-native-host-dark.png +0 -0
- package/docs/work-orders/evidence/tray-native-host-offline.png +0 -0
- package/docs/work-orders/evidence/tray-native-host.png +0 -0
- package/docs/work-orders/evidence/tray-project-3.png +0 -0
- package/docs/work-orders/evidence/tray-project-4.png +0 -0
- package/docs/work-orders/evidence/tray-project-5.png +0 -0
- package/docs/work-orders/evidence/tray-projects-live.json +338 -0
- package/docs/work-orders/evidence/tray-projects-menu.png +0 -0
- package/docs/work-orders/instrument-command-surface-audit.md +215 -148
- package/docs/work-orders/instrument-tui.md +60 -12
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { createWriteStream } from "node:fs";
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
4
|
import { PassThrough } from "node:stream";
|
|
5
|
-
import { CliRenderEvents as
|
|
5
|
+
import { CliRenderEvents as CliRenderEvents5, NativeSession, RGBA as RGBA3, createCliRenderer } from "@opentui/core";
|
|
6
6
|
|
|
7
7
|
// packages/cli/src/tui/native/components/frontend.ts
|
|
8
8
|
import {
|
|
9
|
-
BoxRenderable as
|
|
10
|
-
CliRenderEvents as
|
|
9
|
+
BoxRenderable as BoxRenderable5,
|
|
10
|
+
CliRenderEvents as CliRenderEvents3,
|
|
11
11
|
EmbeddedTerminalRenderable as EmbeddedTerminalRenderable2,
|
|
12
12
|
ScrollBoxRenderable as ScrollBoxRenderable4,
|
|
13
13
|
SyntaxStyle as SyntaxStyle2,
|
|
@@ -171,6 +171,215 @@ function installDefaultSelectionContrast(renderer2) {
|
|
|
171
171
|
return dispose;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
// packages/cli/src/tui/native/components/code.ts
|
|
175
|
+
var aliases = {
|
|
176
|
+
js: "javascript",
|
|
177
|
+
jsx: "javascript",
|
|
178
|
+
ts: "typescript",
|
|
179
|
+
tsx: "typescriptreact",
|
|
180
|
+
py: "python",
|
|
181
|
+
sh: "bash",
|
|
182
|
+
shell: "bash",
|
|
183
|
+
yml: "yaml",
|
|
184
|
+
jsonl: "json",
|
|
185
|
+
json5: "json",
|
|
186
|
+
jsonc: "json"
|
|
187
|
+
};
|
|
188
|
+
function nativeCodeLanguage(language) {
|
|
189
|
+
const name = language?.trim().split(/\s+/)[0]?.toLowerCase();
|
|
190
|
+
return name ? aliases[name] ?? name : void 0;
|
|
191
|
+
}
|
|
192
|
+
function prettyNativeJson(source) {
|
|
193
|
+
try {
|
|
194
|
+
JSON.parse(source);
|
|
195
|
+
} catch {
|
|
196
|
+
return void 0;
|
|
197
|
+
}
|
|
198
|
+
let compact = "", quoted = false, escaped = false;
|
|
199
|
+
for (const char of source) {
|
|
200
|
+
if (quoted || !/[\t\r\n ]/.test(char)) compact += char;
|
|
201
|
+
if (quoted) {
|
|
202
|
+
if (escaped) escaped = false;
|
|
203
|
+
else if (char === "\\") escaped = true;
|
|
204
|
+
else if (char === '"') quoted = false;
|
|
205
|
+
} else if (char === '"') quoted = true;
|
|
206
|
+
}
|
|
207
|
+
let result = "", depth = 0;
|
|
208
|
+
quoted = escaped = false;
|
|
209
|
+
const newline = () => "\n" + " ".repeat(depth);
|
|
210
|
+
for (let index = 0; index < compact.length; index++) {
|
|
211
|
+
const char = compact[index];
|
|
212
|
+
if (quoted) {
|
|
213
|
+
result += char;
|
|
214
|
+
if (escaped) escaped = false;
|
|
215
|
+
else if (char === "\\") escaped = true;
|
|
216
|
+
else if (char === '"') quoted = false;
|
|
217
|
+
} else if (char === '"') {
|
|
218
|
+
quoted = true;
|
|
219
|
+
result += char;
|
|
220
|
+
} else if (char === "{" || char === "[") {
|
|
221
|
+
result += char;
|
|
222
|
+
depth++;
|
|
223
|
+
if (compact[index + 1] !== (char === "{" ? "}" : "]"))
|
|
224
|
+
result += newline();
|
|
225
|
+
} else if (char === "}" || char === "]") {
|
|
226
|
+
depth--;
|
|
227
|
+
if (compact[index - 1] !== (char === "}" ? "{" : "["))
|
|
228
|
+
result += newline();
|
|
229
|
+
result += char;
|
|
230
|
+
} else if (char === ",") result += char + newline();
|
|
231
|
+
else if (char === ":") result += ": ";
|
|
232
|
+
else result += char;
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
function nativeCodeContent(source, language) {
|
|
237
|
+
const selected = nativeCodeLanguage(language);
|
|
238
|
+
if (selected === "json" || !selected && /^[\s]*[\[{]/.test(source)) {
|
|
239
|
+
const pretty = prettyNativeJson(source);
|
|
240
|
+
if (pretty !== void 0) return { content: pretty, language: "json" };
|
|
241
|
+
}
|
|
242
|
+
return { content: source, language: selected };
|
|
243
|
+
}
|
|
244
|
+
function nativeCodeHighlights(source) {
|
|
245
|
+
const highlights = [];
|
|
246
|
+
const tokens = /("(?:\\.|[^"\\])*"?|'(?:\\.|[^'\\])*'?|`(?:\\.|[^`\\])*`?)|(\/\/[^\n]*|\/\*[\s\S]*?(?:\*\/|$)|\#[^\n]*)|\b(true|false|null|None|True|False|nil)\b|\b(const|let|var|function|class|def|return|if|else|elif|for|while|in|import|from|export|async|await|try|catch|except|throw|raise|new|public|private|static|void|int|bool|struct|enum|fn|pub|use|match|impl|package|func|select|switch|case|break|continue|end|do|then|fi|done)\b|(?<![\w])(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|([{}\[\](),:;])/g;
|
|
247
|
+
for (const match of source.matchAll(tokens)) {
|
|
248
|
+
const start = match.index, end = start + match[0].length;
|
|
249
|
+
const group = match[1] ? /^\s*:/.test(source.slice(end)) ? "property" : "string" : match[2] ? "comment" : match[3] ? "constant" : match[4] ? "keyword" : match[5] ? "number" : "punctuation";
|
|
250
|
+
highlights.push([start, end, group]);
|
|
251
|
+
}
|
|
252
|
+
return highlights;
|
|
253
|
+
}
|
|
254
|
+
function installNativeSyntax(syntax, colors) {
|
|
255
|
+
const base = { fg: colors.foreground, bg: colors.background };
|
|
256
|
+
for (const [name, attributes] of Object.entries({
|
|
257
|
+
default: {},
|
|
258
|
+
conceal: { dim: true },
|
|
259
|
+
"markup.heading": { bold: true },
|
|
260
|
+
"markup.strong": { bold: true },
|
|
261
|
+
"markup.italic": { italic: true },
|
|
262
|
+
"markup.link": { underline: true },
|
|
263
|
+
"markup.link.url": { dim: true },
|
|
264
|
+
"markup.raw": {},
|
|
265
|
+
"markup.list": { dim: true },
|
|
266
|
+
"markup.quote": { dim: true },
|
|
267
|
+
comment: { dim: true, italic: true },
|
|
268
|
+
keyword: { bold: true },
|
|
269
|
+
property: { bold: true },
|
|
270
|
+
"string.special.key": { bold: true },
|
|
271
|
+
string: { italic: true },
|
|
272
|
+
"string.escape": { bold: true },
|
|
273
|
+
number: { bold: true },
|
|
274
|
+
boolean: { bold: true },
|
|
275
|
+
constant: { bold: true },
|
|
276
|
+
function: { bold: true },
|
|
277
|
+
type: { underline: true },
|
|
278
|
+
punctuation: { dim: true },
|
|
279
|
+
operator: {},
|
|
280
|
+
variable: {},
|
|
281
|
+
tag: { bold: true },
|
|
282
|
+
attribute: { italic: true }
|
|
283
|
+
}))
|
|
284
|
+
syntax.registerStyle(name, { ...base, ...attributes });
|
|
285
|
+
}
|
|
286
|
+
function nativeMarkdownSections(owner, source, streaming = false) {
|
|
287
|
+
const bare = !source.includes("\n```") && !source.includes("\n~~~") && /^[\s]*[\[{]/.test(source) ? prettyNativeJson(source) : void 0;
|
|
288
|
+
if (bare !== void 0)
|
|
289
|
+
return [
|
|
290
|
+
{
|
|
291
|
+
id: `${owner}:json`,
|
|
292
|
+
kind: "code",
|
|
293
|
+
title: "JSON",
|
|
294
|
+
language: "json",
|
|
295
|
+
text: bare,
|
|
296
|
+
collapsible: true,
|
|
297
|
+
streaming
|
|
298
|
+
}
|
|
299
|
+
];
|
|
300
|
+
const rows = source.split("\n"), offsets = [];
|
|
301
|
+
let offset = 0;
|
|
302
|
+
for (const row of rows) {
|
|
303
|
+
offsets.push(offset);
|
|
304
|
+
offset += row.length + 1;
|
|
305
|
+
}
|
|
306
|
+
const output = [], stack = [
|
|
307
|
+
{ level: 0, children: output }
|
|
308
|
+
];
|
|
309
|
+
let prose = [], proseStart = 0, segmented = false;
|
|
310
|
+
const current = () => stack.at(-1).children;
|
|
311
|
+
const flush = () => {
|
|
312
|
+
if (prose.join("\n").trim())
|
|
313
|
+
current().push({
|
|
314
|
+
id: `${owner}:prose:${proseStart}`,
|
|
315
|
+
kind: "markdown",
|
|
316
|
+
text: prose.join("\n"),
|
|
317
|
+
streaming
|
|
318
|
+
});
|
|
319
|
+
prose = [];
|
|
320
|
+
};
|
|
321
|
+
for (let index = 0; index < rows.length; index++) {
|
|
322
|
+
const row = rows[index];
|
|
323
|
+
const fence = row.match(/^([ >]*)(`{3,}|~{3,})([^`]*)$/);
|
|
324
|
+
if (fence) {
|
|
325
|
+
flush();
|
|
326
|
+
segmented = true;
|
|
327
|
+
const start = offsets[index], contents = [], marker = fence[2];
|
|
328
|
+
const quoteDepth = (fence[1].match(/>/g) ?? []).length;
|
|
329
|
+
const indentation = Math.max(
|
|
330
|
+
0,
|
|
331
|
+
fence[1].split(">").at(-1).length - (quoteDepth ? 1 : 0)
|
|
332
|
+
);
|
|
333
|
+
const containerContent = (line) => {
|
|
334
|
+
for (let depth = 0; depth < quoteDepth; depth++)
|
|
335
|
+
line = line.replace(/^ {0,3}> ?/, "");
|
|
336
|
+
return line.replace(new RegExp(`^ {0,${indentation}}`), "");
|
|
337
|
+
};
|
|
338
|
+
while (++index < rows.length) {
|
|
339
|
+
const line = containerContent(rows[index]);
|
|
340
|
+
const closing = line.match(/^ {0,3}(`{3,}|~{3,})\s*$/);
|
|
341
|
+
if (closing && closing[1][0] === marker[0] && closing[1].length >= marker.length)
|
|
342
|
+
break;
|
|
343
|
+
contents.push(line);
|
|
344
|
+
}
|
|
345
|
+
const code = nativeCodeContent(contents.join("\n"), fence[3]);
|
|
346
|
+
current().push({
|
|
347
|
+
id: `${owner}:code:${start}`,
|
|
348
|
+
kind: "code",
|
|
349
|
+
title: code.language?.toUpperCase() ?? "CODE",
|
|
350
|
+
language: code.language,
|
|
351
|
+
text: code.content,
|
|
352
|
+
collapsible: true,
|
|
353
|
+
streaming: streaming && index >= rows.length
|
|
354
|
+
});
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
const atx = row.match(/^ {0,3}(#{1,6})(?:\s+(.*?)\s*#*\s*|\s*)$/);
|
|
358
|
+
const setext = row.trim() && rows[index + 1]?.match(/^ {0,3}(=+|-+)\s*$/);
|
|
359
|
+
if (atx || setext) {
|
|
360
|
+
flush();
|
|
361
|
+
segmented = true;
|
|
362
|
+
const level = atx ? atx[1].length : setext[1][0] === "=" ? 1 : 2;
|
|
363
|
+
while (stack.length > 1 && stack.at(-1).level >= level) stack.pop();
|
|
364
|
+
const section = {
|
|
365
|
+
id: `${owner}:section:${offsets[index]}`,
|
|
366
|
+
kind: "column",
|
|
367
|
+
title: atx ? atx[2] ?? "" : row.trim(),
|
|
368
|
+
collapsible: true,
|
|
369
|
+
children: []
|
|
370
|
+
};
|
|
371
|
+
current().push(section);
|
|
372
|
+
stack.push({ level, children: section.children });
|
|
373
|
+
if (!atx) index++;
|
|
374
|
+
} else {
|
|
375
|
+
if (!prose.length) proseStart = offsets[index];
|
|
376
|
+
prose.push(row);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
flush();
|
|
380
|
+
return segmented ? output : void 0;
|
|
381
|
+
}
|
|
382
|
+
|
|
174
383
|
// packages/cli/src/tui/native/components/blocks.ts
|
|
175
384
|
function nativeProgressText(value, working = false) {
|
|
176
385
|
if (value === void 0 || !Number.isFinite(value)) return `[············] ${working ? "working" : "pending"}`;
|
|
@@ -212,6 +421,7 @@ var NativeBlockView = class {
|
|
|
212
421
|
text;
|
|
213
422
|
body;
|
|
214
423
|
children;
|
|
424
|
+
markdownSections;
|
|
215
425
|
actions;
|
|
216
426
|
progress;
|
|
217
427
|
image;
|
|
@@ -314,14 +524,31 @@ var NativeBlockView = class {
|
|
|
314
524
|
flexShrink: 0,
|
|
315
525
|
internalBlockMode: "top-level",
|
|
316
526
|
conceal: true,
|
|
317
|
-
tableOptions: { style: "columns", widthMode: "full", wrapMode: "word", selectable: true }
|
|
527
|
+
tableOptions: { style: "columns", widthMode: "full", wrapMode: "word", selectable: true },
|
|
528
|
+
renderNode: (token) => {
|
|
529
|
+
if (token.type !== "code") return;
|
|
530
|
+
const value = nativeCodeContent(token.text, token.lang);
|
|
531
|
+
return new CodeRenderable(renderer2, {
|
|
532
|
+
content: value.content,
|
|
533
|
+
filetype: value.language ?? "text",
|
|
534
|
+
syntaxStyle: syntax,
|
|
535
|
+
fg: colors.foreground,
|
|
536
|
+
bg: colors.background,
|
|
537
|
+
width: "100%",
|
|
538
|
+
flexShrink: 0,
|
|
539
|
+
wrapMode: "word",
|
|
540
|
+
selectable: true,
|
|
541
|
+
streaming: this.spec.streaming ?? false,
|
|
542
|
+
onHighlight: (highlights, context) => highlights.length ? void 0 : nativeCodeHighlights(context.content)
|
|
543
|
+
});
|
|
544
|
+
}
|
|
318
545
|
});
|
|
319
546
|
this.body.add(this.text);
|
|
320
547
|
} else if (spec.kind === "code") {
|
|
321
548
|
this.text = new CodeRenderable(renderer2, {
|
|
322
549
|
id: `code:${spec.id}`,
|
|
323
550
|
content: "",
|
|
324
|
-
filetype: spec.language,
|
|
551
|
+
filetype: spec.language ?? "text",
|
|
325
552
|
syntaxStyle: syntax,
|
|
326
553
|
fg: colors.foreground,
|
|
327
554
|
bg: colors.background,
|
|
@@ -330,7 +557,8 @@ var NativeBlockView = class {
|
|
|
330
557
|
streaming: spec.streaming ?? false,
|
|
331
558
|
selectable: true,
|
|
332
559
|
wrapMode: "word",
|
|
333
|
-
drawUnstyledText: true
|
|
560
|
+
drawUnstyledText: true,
|
|
561
|
+
onHighlight: (highlights, context) => highlights.length ? void 0 : nativeCodeHighlights(context.content)
|
|
334
562
|
});
|
|
335
563
|
this.body.add(this.text);
|
|
336
564
|
} else if (spec.text !== void 0) {
|
|
@@ -371,6 +599,8 @@ var NativeBlockView = class {
|
|
|
371
599
|
}
|
|
372
600
|
reset() {
|
|
373
601
|
this.children?.destroy();
|
|
602
|
+
this.markdownSections?.destroy();
|
|
603
|
+
this.markdownSections = void 0;
|
|
374
604
|
if (this.terminal) this.context.terminals.delete(this.spec.id);
|
|
375
605
|
for (const child of [...this.root.getChildren()]) child.destroyRecursively();
|
|
376
606
|
this.title = this.text = this.body = this.actions = this.progress = this.image = this.terminal = void 0;
|
|
@@ -394,11 +624,21 @@ var NativeBlockView = class {
|
|
|
394
624
|
this.title.focusable = Boolean(spec.collapsible);
|
|
395
625
|
}
|
|
396
626
|
if (this.body) this.body.visible = !this.collapsed;
|
|
627
|
+
const sections = spec.kind === "markdown" ? nativeMarkdownSections(spec.id, plainText(spec.text), spec.streaming) : void 0;
|
|
628
|
+
if (this.text && spec.kind === "markdown") this.text.visible = !sections;
|
|
629
|
+
if (sections && this.body) {
|
|
630
|
+
this.markdownSections ??= new NativeBlockList(this.context, this.body);
|
|
631
|
+
this.markdownSections.replace(sections);
|
|
632
|
+
} else if (this.markdownSections) {
|
|
633
|
+
this.markdownSections.destroy();
|
|
634
|
+
this.markdownSections = void 0;
|
|
635
|
+
}
|
|
397
636
|
if (this.text instanceof TextRenderable) this.text.content = styledText(spec.kind === "image" ? spec.text ?? "Image unavailable" : spec.text);
|
|
398
637
|
else if (this.text instanceof MarkdownRenderable || this.text instanceof CodeRenderable) {
|
|
399
|
-
this.text
|
|
638
|
+
const code = this.text instanceof CodeRenderable ? nativeCodeContent(plainText(spec.text), spec.language) : void 0;
|
|
639
|
+
this.text.content = sections ? "" : code?.content ?? plainText(spec.text);
|
|
400
640
|
this.text.streaming = spec.streaming ?? false;
|
|
401
|
-
if (this.text instanceof CodeRenderable) this.text.filetype =
|
|
641
|
+
if (this.text instanceof CodeRenderable) this.text.filetype = code?.language ?? "text";
|
|
402
642
|
}
|
|
403
643
|
if (this.image && spec.imagePath && this.image.source !== spec.imagePath) this.image.source = spec.imagePath;
|
|
404
644
|
if (this.terminal) this.terminal.height = spec.height ?? 14;
|
|
@@ -470,9 +710,11 @@ var NativeBlockView = class {
|
|
|
470
710
|
action.bg = colors.background;
|
|
471
711
|
}
|
|
472
712
|
this.children?.applyTheme();
|
|
713
|
+
this.markdownSections?.applyTheme();
|
|
473
714
|
}
|
|
474
715
|
destroy() {
|
|
475
716
|
this.children?.destroy();
|
|
717
|
+
this.markdownSections?.destroy();
|
|
476
718
|
if (this.terminal) this.context.terminals.delete(this.spec.id);
|
|
477
719
|
this.root.destroyRecursively();
|
|
478
720
|
}
|
|
@@ -532,7 +774,7 @@ var NativeBlockList = class {
|
|
|
532
774
|
|
|
533
775
|
// packages/cli/src/tui/native/components/modals.ts
|
|
534
776
|
import {
|
|
535
|
-
BoxRenderable as
|
|
777
|
+
BoxRenderable as BoxRenderable3,
|
|
536
778
|
InputRenderable,
|
|
537
779
|
ScrollBoxRenderable as ScrollBoxRenderable2,
|
|
538
780
|
TextareaRenderable,
|
|
@@ -688,7 +930,7 @@ var NativeSelectRenderable = class extends SelectRenderable {
|
|
|
688
930
|
};
|
|
689
931
|
|
|
690
932
|
// packages/cli/src/tui/native/components/corner-frame.ts
|
|
691
|
-
import { RenderableEvents as RenderableEvents2, TextAttributes as TextAttributes3 } from "@opentui/core";
|
|
933
|
+
import { BoxRenderable as BoxRenderable2, CliRenderEvents as CliRenderEvents2, RenderableEvents as RenderableEvents2, TextAttributes as TextAttributes3 } from "@opentui/core";
|
|
692
934
|
function drawCornerFrame(buffer, panel, colors, progress = 1) {
|
|
693
935
|
const { x, y, width, height } = panel;
|
|
694
936
|
if (width <= 0 || height <= 0) return;
|
|
@@ -722,43 +964,122 @@ function drawCornerFrame(buffer, panel, colors, progress = 1) {
|
|
|
722
964
|
}
|
|
723
965
|
}
|
|
724
966
|
var NativeCornerFrame = class {
|
|
725
|
-
constructor(panel, colors, renderer2) {
|
|
967
|
+
constructor(panel, colors, renderer2, container = panel.parent) {
|
|
726
968
|
this.panel = panel;
|
|
727
969
|
this.colors = colors;
|
|
728
970
|
this.renderer = renderer2;
|
|
729
|
-
this.
|
|
730
|
-
this.
|
|
731
|
-
|
|
732
|
-
|
|
971
|
+
this.container = container;
|
|
972
|
+
this.chrome = new BoxRenderable2(renderer2, {
|
|
973
|
+
id: `${panel.id}:corners`,
|
|
974
|
+
position: "absolute",
|
|
975
|
+
left: 0,
|
|
976
|
+
top: 0,
|
|
977
|
+
width: 1,
|
|
978
|
+
height: 1,
|
|
979
|
+
backgroundColor: colors.background,
|
|
980
|
+
shouldFill: true,
|
|
981
|
+
zIndex: 0,
|
|
982
|
+
visible: false
|
|
983
|
+
});
|
|
984
|
+
this.chrome.renderAfter = (buffer) => {
|
|
985
|
+
drawCornerFrame(buffer, this.chrome, this.colors, this.progress);
|
|
986
|
+
if (this.progress < 0.1 && this.chrome.width >= 3 && this.chrome.height >= 3)
|
|
987
|
+
buffer.drawText("■", this.chrome.x + Math.floor(this.chrome.width / 2), this.chrome.y + Math.floor(this.chrome.height / 2), this.colors.foreground, this.colors.background);
|
|
988
|
+
this.painted = true;
|
|
733
989
|
};
|
|
734
|
-
|
|
990
|
+
(container ?? renderer2.root).add(this.chrome, 0);
|
|
991
|
+
panel.border = false;
|
|
992
|
+
panel.shouldFill = false;
|
|
993
|
+
panel.zIndex = 1;
|
|
994
|
+
panel.opacity = this.reduced ? 1 : 0;
|
|
735
995
|
panel.once(RenderableEvents2.DESTROYED, this.destroy);
|
|
736
|
-
if (
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
const advance = () => {
|
|
740
|
-
if (this.disposed) return;
|
|
741
|
-
this.progress = ++frame / 4;
|
|
742
|
-
renderer2.requestRender();
|
|
743
|
-
if (frame < 4) this.timer = setTimeout(advance, 32);
|
|
744
|
-
else this.timer = void 0;
|
|
745
|
-
};
|
|
746
|
-
this.timer = setTimeout(advance, 32);
|
|
996
|
+
if (this.reduced) {
|
|
997
|
+
this.progress = 1;
|
|
998
|
+
this.phase = "open";
|
|
747
999
|
}
|
|
1000
|
+
renderer2.on(CliRenderEvents2.FRAME, this.onFrame);
|
|
748
1001
|
}
|
|
749
1002
|
panel;
|
|
750
1003
|
colors;
|
|
751
1004
|
renderer;
|
|
1005
|
+
container;
|
|
1006
|
+
chrome;
|
|
752
1007
|
progress = 0;
|
|
753
1008
|
timer;
|
|
754
1009
|
disposed = false;
|
|
755
|
-
|
|
756
|
-
|
|
1010
|
+
phase = "opening";
|
|
1011
|
+
started = false;
|
|
1012
|
+
painted = false;
|
|
1013
|
+
geometry = "";
|
|
1014
|
+
reduced = process.env["OMNIUS_TUI_REDUCE_MOTION"] === "1" || process.env["REDUCE_MOTION"] === "1";
|
|
757
1015
|
get animating() {
|
|
758
|
-
return this.
|
|
1016
|
+
return !this.disposed && (this.phase === "opening" || this.phase === "closing");
|
|
1017
|
+
}
|
|
1018
|
+
get closing() {
|
|
1019
|
+
return this.phase === "closing" || this.phase === "closed";
|
|
1020
|
+
}
|
|
1021
|
+
get bounds() {
|
|
1022
|
+
return this.chrome;
|
|
759
1023
|
}
|
|
760
1024
|
setColors(colors) {
|
|
761
1025
|
this.colors = colors;
|
|
1026
|
+
this.chrome.backgroundColor = colors.background;
|
|
1027
|
+
}
|
|
1028
|
+
onFrame = () => {
|
|
1029
|
+
this.layout();
|
|
1030
|
+
if (!this.started && this.painted && this.panel.width > 0 && this.panel.height > 0) {
|
|
1031
|
+
this.started = true;
|
|
1032
|
+
if (this.phase === "opening") this.animate(1, 10);
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
layout() {
|
|
1036
|
+
if (this.disposed || this.panel.width < 1 || this.panel.height < 1) return;
|
|
1037
|
+
const target = this.panel;
|
|
1038
|
+
const width = Math.round(Math.min(5, target.width) + (target.width - Math.min(5, target.width)) * this.progress);
|
|
1039
|
+
const height = Math.round(Math.min(3, target.height) + (target.height - Math.min(3, target.height)) * this.progress);
|
|
1040
|
+
const left = target.x - (this.container?.x ?? 0) + Math.floor((target.width - width) / 2);
|
|
1041
|
+
const top = target.y - (this.container?.y ?? 0) + Math.floor((target.height - height) / 2);
|
|
1042
|
+
const geometry = `${left}:${top}:${width}:${height}`;
|
|
1043
|
+
if (this.geometry === geometry) return;
|
|
1044
|
+
this.geometry = geometry;
|
|
1045
|
+
this.chrome.left = left;
|
|
1046
|
+
this.chrome.top = top;
|
|
1047
|
+
this.chrome.width = width;
|
|
1048
|
+
this.chrome.height = height;
|
|
1049
|
+
this.chrome.visible = true;
|
|
1050
|
+
this.renderer.requestRender();
|
|
1051
|
+
}
|
|
1052
|
+
animate(to, steps, done) {
|
|
1053
|
+
if (this.timer) clearTimeout(this.timer);
|
|
1054
|
+
const from = this.progress;
|
|
1055
|
+
let step = 0;
|
|
1056
|
+
const advance = () => {
|
|
1057
|
+
if (this.disposed) return;
|
|
1058
|
+
const t = ++step / steps;
|
|
1059
|
+
this.progress = from + (to - from) * (t * t * (3 - 2 * t));
|
|
1060
|
+
this.layout();
|
|
1061
|
+
this.renderer.requestRender();
|
|
1062
|
+
if (step < steps) this.timer = setTimeout(advance, 16);
|
|
1063
|
+
else if (to === 1) {
|
|
1064
|
+
this.phase = "open";
|
|
1065
|
+
this.panel.opacity = 1;
|
|
1066
|
+
this.timer = void 0;
|
|
1067
|
+
} else this.timer = setTimeout(() => {
|
|
1068
|
+
this.timer = void 0;
|
|
1069
|
+
this.phase = "closed";
|
|
1070
|
+
done?.();
|
|
1071
|
+
}, 32);
|
|
1072
|
+
};
|
|
1073
|
+
this.timer = setTimeout(advance, 16);
|
|
1074
|
+
}
|
|
1075
|
+
close(done) {
|
|
1076
|
+
if (this.closing || this.disposed) return;
|
|
1077
|
+
this.phase = "closing";
|
|
1078
|
+
this.panel.opacity = 0;
|
|
1079
|
+
if (this.reduced) {
|
|
1080
|
+
this.phase = "closed";
|
|
1081
|
+
done();
|
|
1082
|
+
} else this.animate(0, 8, done);
|
|
762
1083
|
}
|
|
763
1084
|
destroy = () => {
|
|
764
1085
|
if (this.disposed) return;
|
|
@@ -766,7 +1087,8 @@ var NativeCornerFrame = class {
|
|
|
766
1087
|
if (this.timer !== void 0) clearTimeout(this.timer);
|
|
767
1088
|
this.timer = void 0;
|
|
768
1089
|
this.panel.off(RenderableEvents2.DESTROYED, this.destroy);
|
|
769
|
-
|
|
1090
|
+
this.renderer.off(CliRenderEvents2.FRAME, this.onFrame);
|
|
1091
|
+
this.chrome.destroyRecursively();
|
|
770
1092
|
};
|
|
771
1093
|
};
|
|
772
1094
|
|
|
@@ -777,7 +1099,7 @@ var NativeModalView = class {
|
|
|
777
1099
|
this.close = close2;
|
|
778
1100
|
this.spec = spec;
|
|
779
1101
|
const { renderer: renderer2, colors } = context;
|
|
780
|
-
this.root = new
|
|
1102
|
+
this.root = new BoxRenderable3(renderer2, {
|
|
781
1103
|
id: `modal:${spec.id}`,
|
|
782
1104
|
position: "absolute",
|
|
783
1105
|
top: 0,
|
|
@@ -789,24 +1111,31 @@ var NativeModalView = class {
|
|
|
789
1111
|
alignItems: "center",
|
|
790
1112
|
zIndex: 100,
|
|
791
1113
|
backgroundColor: "transparent",
|
|
792
|
-
shouldFill: false
|
|
1114
|
+
shouldFill: false,
|
|
1115
|
+
onMouseDown: (event) => {
|
|
1116
|
+
const bounds = this.frame.bounds;
|
|
1117
|
+
if (event.button === 0 && (event.x < bounds.x || event.x >= bounds.x + bounds.width || event.y < bounds.y || event.y >= bounds.y + bounds.height)) {
|
|
1118
|
+
this.cancel();
|
|
1119
|
+
event.preventDefault();
|
|
1120
|
+
event.stopPropagation();
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
793
1123
|
});
|
|
794
|
-
this.panel = new
|
|
1124
|
+
this.panel = new BoxRenderable3(renderer2, {
|
|
795
1125
|
id: `modal-panel:${spec.id}`,
|
|
796
1126
|
flexDirection: "column",
|
|
797
1127
|
width: "94%",
|
|
798
1128
|
maxHeight: "94%",
|
|
799
|
-
border:
|
|
800
|
-
borderStyle: "single",
|
|
801
|
-
borderColor: colors.border,
|
|
1129
|
+
border: false,
|
|
802
1130
|
backgroundColor: colors.background,
|
|
803
|
-
|
|
804
|
-
|
|
1131
|
+
shouldFill: false,
|
|
1132
|
+
paddingX: 2,
|
|
1133
|
+
paddingY: 1,
|
|
805
1134
|
focusable: true,
|
|
806
1135
|
onMouseDown: () => this.focus()
|
|
807
1136
|
});
|
|
808
|
-
this.frame = new NativeCornerFrame(this.panel, colors, renderer2);
|
|
809
1137
|
this.root.add(this.panel);
|
|
1138
|
+
this.frame = new NativeCornerFrame(this.panel, colors, renderer2, this.root);
|
|
810
1139
|
this.breadcrumb = this.addText(`modal-breadcrumb:${spec.id}`);
|
|
811
1140
|
this.heading = this.addText(`modal-title:${spec.id}`);
|
|
812
1141
|
this.description = this.addText(`modal-description:${spec.id}`);
|
|
@@ -838,13 +1167,13 @@ var NativeModalView = class {
|
|
|
838
1167
|
selectable: false
|
|
839
1168
|
});
|
|
840
1169
|
this.panel.add(this.progress);
|
|
841
|
-
const progressBlocks = new
|
|
1170
|
+
const progressBlocks = new BoxRenderable3(renderer2, { id: `modal-progress-blocks:${spec.id}`, flexDirection: "column", width: "100%" });
|
|
842
1171
|
this.panel.add(progressBlocks);
|
|
843
1172
|
this.blocks = new NativeBlockList(this.modalContext(), progressBlocks);
|
|
844
1173
|
}
|
|
845
1174
|
this.error = this.addText(`modal-error:${spec.id}`);
|
|
846
1175
|
this.hints = this.addText(`modal-hints:${spec.id}`);
|
|
847
|
-
this.actions = new
|
|
1176
|
+
this.actions = new BoxRenderable3(renderer2, { id: `modal-actions:${spec.id}`, flexDirection: "row", gap: 1, width: "100%", marginTop: 0 });
|
|
848
1177
|
this.panel.add(this.actions);
|
|
849
1178
|
this.update(spec);
|
|
850
1179
|
}
|
|
@@ -1045,6 +1374,7 @@ var NativeModalView = class {
|
|
|
1045
1374
|
this.context.emit({ type: "modal-action", id: this.spec.id, action, key: current?.item.key, index: current?.index, value });
|
|
1046
1375
|
}
|
|
1047
1376
|
confirm() {
|
|
1377
|
+
if (this.frame.closing) return;
|
|
1048
1378
|
if (this.spec.kind === "progress") {
|
|
1049
1379
|
this.emitAction("enter");
|
|
1050
1380
|
return;
|
|
@@ -1059,6 +1389,7 @@ var NativeModalView = class {
|
|
|
1059
1389
|
this.close(this.spec.id, { confirmed: true, key: current?.item.key ?? null, index: current?.index ?? -1, ...value === void 0 ? {} : { value } });
|
|
1060
1390
|
}
|
|
1061
1391
|
cancel(action = "cancel") {
|
|
1392
|
+
if (this.frame.closing) return;
|
|
1062
1393
|
if (this.spec.deferSelection) {
|
|
1063
1394
|
this.emitAction(action);
|
|
1064
1395
|
return;
|
|
@@ -1066,6 +1397,7 @@ var NativeModalView = class {
|
|
|
1066
1397
|
this.close(this.spec.id, { confirmed: false, key: this.spec.breadcrumbs?.length ? "__back__" : null, index: this.current()?.index ?? -1 });
|
|
1067
1398
|
}
|
|
1068
1399
|
focus() {
|
|
1400
|
+
if (this.frame.closing) return;
|
|
1069
1401
|
if (this.filterInput) this.filterInput.focus();
|
|
1070
1402
|
else if (this.editor && !this.spec.secret) this.editor.focus();
|
|
1071
1403
|
else if (this.document) this.document.focus();
|
|
@@ -1095,6 +1427,7 @@ var NativeModalView = class {
|
|
|
1095
1427
|
key.stopPropagation();
|
|
1096
1428
|
return true;
|
|
1097
1429
|
};
|
|
1430
|
+
if (this.frame.closing) return consume();
|
|
1098
1431
|
if (key.eventType === "release") return false;
|
|
1099
1432
|
if (key.name === "escape" || key.ctrl && key.name === "c") {
|
|
1100
1433
|
this.cancel();
|
|
@@ -1163,6 +1496,11 @@ var NativeModalView = class {
|
|
|
1163
1496
|
return false;
|
|
1164
1497
|
}
|
|
1165
1498
|
handlePaste(event) {
|
|
1499
|
+
if (this.frame.closing) {
|
|
1500
|
+
event.preventDefault();
|
|
1501
|
+
event.stopPropagation();
|
|
1502
|
+
return true;
|
|
1503
|
+
}
|
|
1166
1504
|
const text = new TextDecoder().decode(event.bytes);
|
|
1167
1505
|
if (this.overBudget(text, this.filterInput?.plainText ?? this.editor?.plainText ?? "")) {
|
|
1168
1506
|
event.preventDefault();
|
|
@@ -1188,7 +1526,6 @@ var NativeModalView = class {
|
|
|
1188
1526
|
applyTheme() {
|
|
1189
1527
|
const colors = this.context.colors;
|
|
1190
1528
|
this.panel.backgroundColor = colors.background;
|
|
1191
|
-
this.panel.borderColor = colors.border;
|
|
1192
1529
|
this.frame.setColors(colors);
|
|
1193
1530
|
this.heading.fg = colors.foreground;
|
|
1194
1531
|
this.heading.attributes = 1;
|
|
@@ -1247,7 +1584,7 @@ var NativeModalStack = class {
|
|
|
1247
1584
|
dimUnderlay = (buffer) => {
|
|
1248
1585
|
const panel = this.active?.panel;
|
|
1249
1586
|
if (!panel || panel.isDestroyed || !panel.visible) return;
|
|
1250
|
-
const { x, y, width, height } =
|
|
1587
|
+
const { x, y, width, height } = this.active.frame.bounds;
|
|
1251
1588
|
buffer.withBuffers((cells) => {
|
|
1252
1589
|
for (let row = 0; row < cells.height; row++) for (let column = 0; column < cells.width; column++) {
|
|
1253
1590
|
if (column < x || column >= x + width || row < y || row >= y + height)
|
|
@@ -1278,17 +1615,19 @@ var NativeModalStack = class {
|
|
|
1278
1615
|
close(id, result, notify = false) {
|
|
1279
1616
|
const view = this.byId.get(id);
|
|
1280
1617
|
if (!view) return;
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
if (
|
|
1287
|
-
this.active
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1618
|
+
view.frame.close(() => {
|
|
1619
|
+
const wasActive = view === this.active;
|
|
1620
|
+
view.destroy();
|
|
1621
|
+
this.byId.delete(id);
|
|
1622
|
+
this.views = this.views.filter((candidate) => candidate !== view);
|
|
1623
|
+
if (wasActive) {
|
|
1624
|
+
if (this.active) {
|
|
1625
|
+
this.active.root.visible = true;
|
|
1626
|
+
this.active.focus();
|
|
1627
|
+
} else this.restoreFocus();
|
|
1628
|
+
}
|
|
1629
|
+
if (notify) this.context.emit({ type: "modal-result", id, result });
|
|
1630
|
+
});
|
|
1292
1631
|
}
|
|
1293
1632
|
applyTheme() {
|
|
1294
1633
|
for (const view of this.views) view.applyTheme();
|
|
@@ -1303,7 +1642,7 @@ var NativeModalStack = class {
|
|
|
1303
1642
|
|
|
1304
1643
|
// packages/cli/src/tui/native/components/instruments.ts
|
|
1305
1644
|
import {
|
|
1306
|
-
BoxRenderable as
|
|
1645
|
+
BoxRenderable as BoxRenderable4,
|
|
1307
1646
|
RGBA as RGBA2,
|
|
1308
1647
|
RenderableEvents as RenderableEvents3,
|
|
1309
1648
|
ScrollBoxRenderable as ScrollBoxRenderable3,
|
|
@@ -1551,7 +1890,311 @@ var SignalMeter = class extends TelemetryRow {
|
|
|
1551
1890
|
this.update(formatSignalMeter(value, maximum));
|
|
1552
1891
|
}
|
|
1553
1892
|
};
|
|
1554
|
-
var
|
|
1893
|
+
var InstrumentDivider = class extends TextRenderable3 {
|
|
1894
|
+
constructor(renderer2, actions) {
|
|
1895
|
+
super(renderer2, {
|
|
1896
|
+
id: "omnius-instrument-divider",
|
|
1897
|
+
width: 1,
|
|
1898
|
+
minWidth: 1,
|
|
1899
|
+
maxWidth: 1,
|
|
1900
|
+
height: "100%",
|
|
1901
|
+
flexGrow: 0,
|
|
1902
|
+
flexShrink: 0,
|
|
1903
|
+
fg: foreground,
|
|
1904
|
+
bg: background,
|
|
1905
|
+
selectable: false,
|
|
1906
|
+
wrapMode: "none",
|
|
1907
|
+
attributes: TextAttributes5.DIM,
|
|
1908
|
+
onMouseDown: (event) => {
|
|
1909
|
+
if (event.button !== 0) return;
|
|
1910
|
+
this.held = true;
|
|
1911
|
+
this.moved = false;
|
|
1912
|
+
this.startX = event.x;
|
|
1913
|
+
this.actions.start?.();
|
|
1914
|
+
this.attributes = TextAttributes5.BOLD;
|
|
1915
|
+
event.preventDefault();
|
|
1916
|
+
event.stopPropagation();
|
|
1917
|
+
},
|
|
1918
|
+
onMouseDrag: (event) => {
|
|
1919
|
+
this.handleDrag(event);
|
|
1920
|
+
},
|
|
1921
|
+
onMouseUp: (event) => {
|
|
1922
|
+
this.handleRelease(event);
|
|
1923
|
+
},
|
|
1924
|
+
onMouseDragEnd: (event) => {
|
|
1925
|
+
this.handleRelease(event);
|
|
1926
|
+
},
|
|
1927
|
+
onMouseOver: () => {
|
|
1928
|
+
this.attributes = TextAttributes5.BOLD;
|
|
1929
|
+
},
|
|
1930
|
+
onMouseOut: () => {
|
|
1931
|
+
if (!this.held) this.attributes = this.focused ? TextAttributes5.INVERSE : TextAttributes5.DIM;
|
|
1932
|
+
},
|
|
1933
|
+
onKeyDown: (key) => {
|
|
1934
|
+
if (key.eventType === "release") return;
|
|
1935
|
+
if (key.name === "return" || key.sequence === " ") this.actions.toggle();
|
|
1936
|
+
else if (key.name === "left" || key.name === "right") this.actions.resize(this.x + (key.name === "left" ? -1 : 1) * (key.shift ? 8 : 2));
|
|
1937
|
+
else return;
|
|
1938
|
+
key.preventDefault();
|
|
1939
|
+
key.stopPropagation();
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
this.actions = actions;
|
|
1943
|
+
this.focusable = true;
|
|
1944
|
+
this.on(RenderableEvents3.FOCUSED, () => {
|
|
1945
|
+
this.attributes = TextAttributes5.INVERSE;
|
|
1946
|
+
});
|
|
1947
|
+
this.on(RenderableEvents3.BLURRED, () => {
|
|
1948
|
+
this.attributes = TextAttributes5.DIM;
|
|
1949
|
+
});
|
|
1950
|
+
}
|
|
1951
|
+
actions;
|
|
1952
|
+
collapsed = false;
|
|
1953
|
+
held = false;
|
|
1954
|
+
moved = false;
|
|
1955
|
+
startX = 0;
|
|
1956
|
+
setCollapsed(collapsed) {
|
|
1957
|
+
this.collapsed = collapsed;
|
|
1958
|
+
this.refresh();
|
|
1959
|
+
}
|
|
1960
|
+
handleDrag(event) {
|
|
1961
|
+
if (!this.held) return;
|
|
1962
|
+
if (event.x !== this.startX) this.moved = true;
|
|
1963
|
+
if (this.moved) this.actions.resize(event.x);
|
|
1964
|
+
event.preventDefault();
|
|
1965
|
+
event.stopPropagation();
|
|
1966
|
+
}
|
|
1967
|
+
handleRelease(event) {
|
|
1968
|
+
if (!this.held) return;
|
|
1969
|
+
this.release(event.x);
|
|
1970
|
+
event.preventDefault();
|
|
1971
|
+
event.stopPropagation();
|
|
1972
|
+
}
|
|
1973
|
+
onResize(width, height) {
|
|
1974
|
+
super.onResize(width, height);
|
|
1975
|
+
this.refresh();
|
|
1976
|
+
}
|
|
1977
|
+
refresh() {
|
|
1978
|
+
const rows = Array.from({ length: Math.max(0, this.height) }, (_, row) => row === Math.floor(this.height / 2) ? this.collapsed ? "‹" : "›" : "│");
|
|
1979
|
+
const text = rows.join("\n");
|
|
1980
|
+
if (this.plainText !== text) this.content = text;
|
|
1981
|
+
}
|
|
1982
|
+
release(column) {
|
|
1983
|
+
if (this.moved) this.actions.resize(column);
|
|
1984
|
+
else this.actions.toggle();
|
|
1985
|
+
this.held = false;
|
|
1986
|
+
this.actions.finish?.();
|
|
1987
|
+
this.attributes = this.focused ? TextAttributes5.INVERSE : TextAttributes5.DIM;
|
|
1988
|
+
}
|
|
1989
|
+
};
|
|
1990
|
+
var DeviceMonitor = class extends BoxRenderable4 {
|
|
1991
|
+
constructor(renderer2, action) {
|
|
1992
|
+
super(renderer2, { id: "omnius-devices", width: "100%", height: 3, minHeight: 3, maxHeight: "60%", flexShrink: 1, flexDirection: "column", visible: false });
|
|
1993
|
+
this.action = action;
|
|
1994
|
+
this.heading = new SectionBanner(renderer2, "DEVICES", "omnius-devices:heading", () => this.toggle());
|
|
1995
|
+
this.heading.update("DEVICES", false);
|
|
1996
|
+
this.add(this.heading);
|
|
1997
|
+
this.summary = new TextRenderable3(renderer2, { id: "omnius-devices:summary", content: "--", width: "100%", height: 1, flexShrink: 0, fg: foreground, bg: background, wrapMode: "none", truncate: true });
|
|
1998
|
+
this.add(this.summary);
|
|
1999
|
+
this.scroll = new ScrollBoxRenderable3(renderer2, {
|
|
2000
|
+
id: "omnius-devices:scroll",
|
|
2001
|
+
width: "100%",
|
|
2002
|
+
flexGrow: 1,
|
|
2003
|
+
flexShrink: 1,
|
|
2004
|
+
minHeight: 0,
|
|
2005
|
+
visible: false,
|
|
2006
|
+
scrollY: true,
|
|
2007
|
+
scrollX: false,
|
|
2008
|
+
viewportCulling: true,
|
|
2009
|
+
horizontalScrollbarOptions: { visible: false },
|
|
2010
|
+
verticalScrollbarOptions: { showArrows: false },
|
|
2011
|
+
contentOptions: { flexDirection: "column" }
|
|
2012
|
+
});
|
|
2013
|
+
this.add(this.scroll);
|
|
2014
|
+
this.notes = new TextRenderable3(renderer2, {
|
|
2015
|
+
id: "omnius-devices:notes",
|
|
2016
|
+
content: "",
|
|
2017
|
+
width: "100%",
|
|
2018
|
+
height: 1,
|
|
2019
|
+
flexShrink: 0,
|
|
2020
|
+
fg: foreground,
|
|
2021
|
+
bg: background,
|
|
2022
|
+
wrapMode: "none",
|
|
2023
|
+
truncate: true
|
|
2024
|
+
});
|
|
2025
|
+
this.scroll.add(this.notes);
|
|
2026
|
+
const controls = new BoxRenderable4(renderer2, { id: "omnius-devices:controls", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2 });
|
|
2027
|
+
this.add(controls);
|
|
2028
|
+
this.policy = this.button(renderer2, "omnius-devices:policy", "GPU POLICY", () => {
|
|
2029
|
+
if (this.canSelect()) this.action?.("/gpu");
|
|
2030
|
+
});
|
|
2031
|
+
this.status = this.button(renderer2, "omnius-devices:status", "STATUS", () => this.action?.("/gpu status"));
|
|
2032
|
+
controls.add(this.policy);
|
|
2033
|
+
controls.add(this.status);
|
|
2034
|
+
}
|
|
2035
|
+
action;
|
|
2036
|
+
heading;
|
|
2037
|
+
scroll;
|
|
2038
|
+
summary;
|
|
2039
|
+
policy;
|
|
2040
|
+
status;
|
|
2041
|
+
notes;
|
|
2042
|
+
expanded = false;
|
|
2043
|
+
snapshot;
|
|
2044
|
+
rows = /* @__PURE__ */ new Map();
|
|
2045
|
+
button(renderer2, id, label, activate) {
|
|
2046
|
+
const button = new TextRenderable3(renderer2, {
|
|
2047
|
+
id,
|
|
2048
|
+
content: label,
|
|
2049
|
+
height: 1,
|
|
2050
|
+
flexShrink: 0,
|
|
2051
|
+
fg: foreground,
|
|
2052
|
+
bg: background,
|
|
2053
|
+
selectable: false,
|
|
2054
|
+
wrapMode: "none",
|
|
2055
|
+
truncate: true,
|
|
2056
|
+
onMouseDown: (event) => {
|
|
2057
|
+
if (event.button === 0 && button.focusable) {
|
|
2058
|
+
button.focus();
|
|
2059
|
+
activate();
|
|
2060
|
+
event.preventDefault();
|
|
2061
|
+
event.stopPropagation();
|
|
2062
|
+
}
|
|
2063
|
+
},
|
|
2064
|
+
onKeyDown: (key) => {
|
|
2065
|
+
if (key.eventType !== "release" && (key.name === "return" || key.sequence === " ") && button.focusable) {
|
|
2066
|
+
activate();
|
|
2067
|
+
key.preventDefault();
|
|
2068
|
+
key.stopPropagation();
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
button.focusable = Boolean(this.action);
|
|
2073
|
+
button.on(RenderableEvents3.FOCUSED, () => {
|
|
2074
|
+
button.attributes = TextAttributes5.INVERSE;
|
|
2075
|
+
});
|
|
2076
|
+
button.on(RenderableEvents3.BLURRED, () => {
|
|
2077
|
+
button.attributes = button.focusable ? 0 : TextAttributes5.DIM;
|
|
2078
|
+
});
|
|
2079
|
+
return button;
|
|
2080
|
+
}
|
|
2081
|
+
canSelect() {
|
|
2082
|
+
return Boolean(this.action && this.snapshot?.selectionAvailable && !this.snapshot.selectionLocked);
|
|
2083
|
+
}
|
|
2084
|
+
canSelectDevice(device) {
|
|
2085
|
+
return this.canSelect() && device.eligible === true && !device.unifiedMemory && /^GPU-[\w-]+$/.test(device.uuid);
|
|
2086
|
+
}
|
|
2087
|
+
update(snapshot) {
|
|
2088
|
+
this.snapshot = snapshot;
|
|
2089
|
+
this.visible = Boolean(snapshot);
|
|
2090
|
+
const allowed = this.canSelect();
|
|
2091
|
+
if (this.policy.focused && !allowed) this.heading.focus();
|
|
2092
|
+
this.policy.focusable = allowed;
|
|
2093
|
+
this.policy.content = snapshot?.selectionLocked ? "POLICY LOCKED" : "GPU POLICY";
|
|
2094
|
+
this.policy.attributes = allowed ? this.policy.focused ? TextAttributes5.INVERSE : 0 : TextAttributes5.DIM;
|
|
2095
|
+
const keep = new Set(snapshot?.devices.map((device) => device.uuid) ?? []);
|
|
2096
|
+
for (const [uuid, row] of this.rows) if (!keep.has(uuid)) {
|
|
2097
|
+
if (row.title.focused) this.heading.focus();
|
|
2098
|
+
row.root.destroyRecursively();
|
|
2099
|
+
this.rows.delete(uuid);
|
|
2100
|
+
}
|
|
2101
|
+
for (const device of snapshot?.devices ?? []) {
|
|
2102
|
+
let row = this.rows.get(device.uuid);
|
|
2103
|
+
if (!row) {
|
|
2104
|
+
const root = new BoxRenderable4(this._ctx, {
|
|
2105
|
+
id: `omnius-device:${device.uuid}`,
|
|
2106
|
+
width: "100%",
|
|
2107
|
+
flexDirection: "column",
|
|
2108
|
+
flexShrink: 0,
|
|
2109
|
+
onSizeChange: () => {
|
|
2110
|
+
if (!row) return;
|
|
2111
|
+
for (const child of [row.title, row.load, row.memory, row.reason]) child.width = row.root.width;
|
|
2112
|
+
this.refresh();
|
|
2113
|
+
}
|
|
2114
|
+
});
|
|
2115
|
+
const title = this.button(this._ctx, `${root.id}:select`, "", () => {
|
|
2116
|
+
const current = this.snapshot?.devices.find((item) => item.uuid === device.uuid);
|
|
2117
|
+
if (current && this.canSelectDevice(current)) this.action?.(`/gpu select ${current.uuid}`);
|
|
2118
|
+
});
|
|
2119
|
+
title.width = "100%";
|
|
2120
|
+
title.on(RenderableEvents3.FOCUSED, () => this.scroll.scrollChildIntoView(root.id));
|
|
2121
|
+
const load = new TelemetryRow(this._ctx, "LOAD", `${root.id}:load`, 16);
|
|
2122
|
+
const memory = new TelemetryRow(this._ctx, "VRAM", `${root.id}:memory`, 16);
|
|
2123
|
+
const reason = new TextRenderable3(this._ctx, {
|
|
2124
|
+
id: `${root.id}:reason`,
|
|
2125
|
+
content: "",
|
|
2126
|
+
width: "100%",
|
|
2127
|
+
height: 1,
|
|
2128
|
+
fg: foreground,
|
|
2129
|
+
bg: background,
|
|
2130
|
+
attributes: TextAttributes5.DIM,
|
|
2131
|
+
wrapMode: "none",
|
|
2132
|
+
truncate: true,
|
|
2133
|
+
visible: false
|
|
2134
|
+
});
|
|
2135
|
+
root.add(title);
|
|
2136
|
+
root.add(load);
|
|
2137
|
+
root.add(memory);
|
|
2138
|
+
root.add(reason);
|
|
2139
|
+
this.scroll.add(root);
|
|
2140
|
+
row = { root, title, load, memory, reason };
|
|
2141
|
+
this.rows.set(device.uuid, row);
|
|
2142
|
+
}
|
|
2143
|
+
const selectable = this.canSelectDevice(device);
|
|
2144
|
+
if (row.title.focused && !selectable) this.heading.focus();
|
|
2145
|
+
row.title.focusable = selectable;
|
|
2146
|
+
row.title.attributes = row.title.focused ? TextAttributes5.INVERSE : device.preferred ? TextAttributes5.BOLD : selectable ? 0 : TextAttributes5.DIM;
|
|
2147
|
+
row.load.update(formatSignalMeter(device.utilization, 100, 6));
|
|
2148
|
+
const used = device.memoryUsedMB === void 0 ? "--" : instrumentNumber(device.memoryUsedMB / 1024, 1);
|
|
2149
|
+
const total = device.memoryTotalMB === void 0 || device.memoryTotalMB <= 0 ? "--" : instrumentNumber(device.memoryTotalMB / 1024, 1);
|
|
2150
|
+
row.memory.update(`${used}/${total} GiB`, device.unifiedMemory ? "UMA" : "VRAM");
|
|
2151
|
+
row.reason.content = device.policyReason ?? "";
|
|
2152
|
+
row.reason.visible = Boolean(device.policyReason);
|
|
2153
|
+
}
|
|
2154
|
+
this.refresh();
|
|
2155
|
+
}
|
|
2156
|
+
toggle() {
|
|
2157
|
+
this.expanded = !this.expanded;
|
|
2158
|
+
this.scroll.visible = this.expanded;
|
|
2159
|
+
this.minHeight = this.expanded ? 4 : 3;
|
|
2160
|
+
this.scroll.minHeight = this.expanded ? 1 : 0;
|
|
2161
|
+
this.height = this.expanded ? Math.min(12, Math.max(5, Math.floor(this._ctx.terminalHeight / 3))) : 3;
|
|
2162
|
+
this.refresh();
|
|
2163
|
+
}
|
|
2164
|
+
onResize(width, height) {
|
|
2165
|
+
super.onResize(width, height);
|
|
2166
|
+
this.refresh();
|
|
2167
|
+
}
|
|
2168
|
+
refresh() {
|
|
2169
|
+
if (!this.heading) return;
|
|
2170
|
+
const data = this.snapshot, devices = data?.devices ?? [];
|
|
2171
|
+
this.heading.update(data?.source === "jtop" ? "DEVICES / JETSON" : "DEVICES", this.expanded);
|
|
2172
|
+
const measured = devices.map((device) => device.utilization).filter((value) => value !== void 0 && Number.isFinite(value) && value >= 0);
|
|
2173
|
+
const on = devices.filter((device) => device.enabled === true).length;
|
|
2174
|
+
const policyKnown = devices.every((device) => device.enabled !== void 0);
|
|
2175
|
+
this.summary.content = !devices.length ? data?.source === "unavailable" ? "Telemetry unavailable" : "No local GPUs reported" : `${devices.length} GPU · ${policyKnown ? on : "--"} ON · ${measured.length === devices.length ? Math.round(Math.max(...measured)) : "--"}% PEAK`;
|
|
2176
|
+
this.notes.content = [
|
|
2177
|
+
data?.local === false ? "REMOTE" : void 0,
|
|
2178
|
+
data ? `${data.source.toUpperCase()} · ${data.policy.toUpperCase()} · ${data.broker.toUpperCase()}` : void 0,
|
|
2179
|
+
data?.warnings.length ? `${data.warnings.length} notices` : void 0
|
|
2180
|
+
].filter(Boolean).join(" · ");
|
|
2181
|
+
for (const device of devices) {
|
|
2182
|
+
const row = this.rows.get(device.uuid);
|
|
2183
|
+
if (!row) continue;
|
|
2184
|
+
const state = device.enabled === void 0 ? "--" : device.enabled ? "ON" : "OFF";
|
|
2185
|
+
row.title.content = formatTelemetryRow(`GPU ${device.index} ${device.name}`, `${state}${device.preferred ? " *" : ""}`, row.root.width, 6);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
focusTargets() {
|
|
2189
|
+
return !this.visible ? [] : [
|
|
2190
|
+
this.heading,
|
|
2191
|
+
...this.policy.focusable ? [this.policy] : [],
|
|
2192
|
+
...this.status.focusable ? [this.status] : [],
|
|
2193
|
+
...this.expanded ? [...this.rows.values()].map((row) => row.title).filter((title) => title.focusable) : []
|
|
2194
|
+
];
|
|
2195
|
+
}
|
|
2196
|
+
};
|
|
2197
|
+
var ChannelMap = class extends BoxRenderable4 {
|
|
1555
2198
|
constructor(renderer2, id, inspect, reveal) {
|
|
1556
2199
|
super(renderer2, {
|
|
1557
2200
|
id,
|
|
@@ -1649,16 +2292,19 @@ var ChannelMap = class extends BoxRenderable3 {
|
|
|
1649
2292
|
}
|
|
1650
2293
|
}
|
|
1651
2294
|
};
|
|
1652
|
-
var InstrumentRail = class extends
|
|
2295
|
+
var InstrumentRail = class extends BoxRenderable4 {
|
|
1653
2296
|
scroll;
|
|
1654
2297
|
inferenceHeader;
|
|
1655
2298
|
sessionHeader;
|
|
1656
2299
|
channels;
|
|
2300
|
+
devices;
|
|
1657
2301
|
inference;
|
|
1658
2302
|
session;
|
|
1659
2303
|
model;
|
|
1660
2304
|
rows = /* @__PURE__ */ new Map();
|
|
1661
2305
|
contextMeter;
|
|
2306
|
+
contextHeader;
|
|
2307
|
+
contextDetails;
|
|
1662
2308
|
constructor(renderer2, options = {}) {
|
|
1663
2309
|
const id = options.id ?? "omnius-instruments";
|
|
1664
2310
|
super(renderer2, {
|
|
@@ -1696,7 +2342,7 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1696
2342
|
() => this.reveal(this.inferenceHeader)
|
|
1697
2343
|
);
|
|
1698
2344
|
this.scroll.add(this.inferenceHeader);
|
|
1699
|
-
this.inference = new
|
|
2345
|
+
this.inference = new BoxRenderable4(renderer2, {
|
|
1700
2346
|
id: `${id}:inference-body`,
|
|
1701
2347
|
width: "100%",
|
|
1702
2348
|
flexDirection: "column",
|
|
@@ -1734,6 +2380,20 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1734
2380
|
);
|
|
1735
2381
|
this.inference.add(this.contextMeter);
|
|
1736
2382
|
addRow(this.inference, "state", "STATE");
|
|
2383
|
+
this.contextHeader = new SectionBanner(renderer2, "CONTEXT DETAILS", `${id}:context-details`, () => {
|
|
2384
|
+
this.contextDetails.visible = !this.contextDetails.visible;
|
|
2385
|
+
this.contextHeader.update("CONTEXT DETAILS", this.contextDetails.visible);
|
|
2386
|
+
});
|
|
2387
|
+
this.contextHeader.on(RenderableEvents3.FOCUSED, () => this.reveal(this.contextHeader));
|
|
2388
|
+
this.inference.add(this.contextHeader);
|
|
2389
|
+
this.contextDetails = new BoxRenderable4(renderer2, { id: `${id}:context-detail-body`, width: "100%", flexDirection: "column", flexShrink: 0, visible: false });
|
|
2390
|
+
this.inference.add(this.contextDetails);
|
|
2391
|
+
this.contextHeader.update("CONTEXT DETAILS", false);
|
|
2392
|
+
addRow(this.contextDetails, "messages", "MESSAGES");
|
|
2393
|
+
addRow(this.contextDetails, "headroom", "HEADROOM");
|
|
2394
|
+
addRow(this.contextDetails, "context-tools", "TOOL CALLS");
|
|
2395
|
+
addRow(this.contextDetails, "adversary", "ADVERSARY");
|
|
2396
|
+
addRow(this.contextDetails, "duration", "LAST GEN");
|
|
1737
2397
|
this.sessionHeader = new SectionBanner(
|
|
1738
2398
|
renderer2,
|
|
1739
2399
|
"SESSION / AGENTS",
|
|
@@ -1745,7 +2405,7 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1745
2405
|
() => this.reveal(this.sessionHeader)
|
|
1746
2406
|
);
|
|
1747
2407
|
this.scroll.add(this.sessionHeader);
|
|
1748
|
-
this.session = new
|
|
2408
|
+
this.session = new BoxRenderable4(renderer2, {
|
|
1749
2409
|
id: `${id}:session-body`,
|
|
1750
2410
|
width: "100%",
|
|
1751
2411
|
flexDirection: "column",
|
|
@@ -1767,6 +2427,8 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1767
2427
|
this.session.add(this.channels);
|
|
1768
2428
|
this.session.visible = false;
|
|
1769
2429
|
this.sessionHeader.update("SESSION / AGENTS", false);
|
|
2430
|
+
this.devices = new DeviceMonitor(renderer2, options.onAction);
|
|
2431
|
+
this.add(this.devices);
|
|
1770
2432
|
if (options.colors) this.applyTheme(options.colors);
|
|
1771
2433
|
}
|
|
1772
2434
|
update(state) {
|
|
@@ -1774,6 +2436,14 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1774
2436
|
const inference = data?.inference;
|
|
1775
2437
|
const session = data?.session;
|
|
1776
2438
|
const set = (id, value) => this.rows.get(id).update(value);
|
|
2439
|
+
set("messages", instrumentNumber(inference?.contextMessages));
|
|
2440
|
+
set("headroom", inference?.contextHeadroom !== void 0 && Number.isFinite(inference.contextHeadroom) ? String(Math.round(inference.contextHeadroom)) : "--");
|
|
2441
|
+
set("context-tools", instrumentNumber(inference?.contextToolCalls));
|
|
2442
|
+
set("adversary", instrumentNumber(inference?.contextAdversaryOutcomes));
|
|
2443
|
+
set("duration", inference?.generationDurationMs === void 0 ? "--" : instrumentNumber(inference.generationDurationMs / 1e3, 1, "s"));
|
|
2444
|
+
this.contextHeader.visible = [inference?.contextMessages, inference?.contextHeadroom, inference?.contextToolCalls, inference?.contextAdversaryOutcomes, inference?.generationDurationMs].some((value) => value !== void 0);
|
|
2445
|
+
this.contextDetails.visible = this.contextHeader.visible && this.contextHeader.expanded;
|
|
2446
|
+
this.devices.update(data?.devices);
|
|
1777
2447
|
set("route", (inference?.route || "UNKNOWN").toUpperCase());
|
|
1778
2448
|
set("backend", (inference?.backend || "--").toUpperCase());
|
|
1779
2449
|
const model = `MODEL ${inference?.model || "--"}`;
|
|
@@ -1826,6 +2496,7 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1826
2496
|
};
|
|
1827
2497
|
visit(this);
|
|
1828
2498
|
styleNativeScrollbars(this.scroll, colors);
|
|
2499
|
+
styleNativeScrollbars(this.devices.scroll, colors);
|
|
1829
2500
|
}
|
|
1830
2501
|
toggleSection(id) {
|
|
1831
2502
|
const header = id === "inference" ? this.inferenceHeader : this.sessionHeader;
|
|
@@ -1840,8 +2511,10 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1840
2511
|
if (!this.visible) return [];
|
|
1841
2512
|
return [
|
|
1842
2513
|
this.inferenceHeader,
|
|
2514
|
+
...this.inference.visible && this.contextHeader.visible ? [this.contextHeader] : [],
|
|
1843
2515
|
this.sessionHeader,
|
|
1844
|
-
...this.session.visible ? this.channels.focusTargets() : []
|
|
2516
|
+
...this.session.visible ? this.channels.focusTargets() : [],
|
|
2517
|
+
...this.devices.focusTargets()
|
|
1845
2518
|
];
|
|
1846
2519
|
}
|
|
1847
2520
|
focusSection(index = 0) {
|
|
@@ -1860,6 +2533,1437 @@ var InstrumentRail = class extends BoxRenderable3 {
|
|
|
1860
2533
|
}
|
|
1861
2534
|
};
|
|
1862
2535
|
|
|
2536
|
+
// packages/cli/src/tui/command-registry.ts
|
|
2537
|
+
var COMMAND_SIGNATURES = [
|
|
2538
|
+
["/model", "Select from available models"],
|
|
2539
|
+
["/model <name>", "Switch to a specific model"],
|
|
2540
|
+
["/models", "List all available models"],
|
|
2541
|
+
["/endpoint", "Show current endpoint"],
|
|
2542
|
+
["/endpoint <url>", "Set backend URL (auto-detects type)"],
|
|
2543
|
+
["/endpoint <url> --auth <t>", "Set endpoint with Bearer auth"],
|
|
2544
|
+
["/fallback", "Show remote inference fallback mode"],
|
|
2545
|
+
["/fallback status", "Show remote inference fallback mode"],
|
|
2546
|
+
["/fallback auto", "Automatically use remote inference after local failure (default)"],
|
|
2547
|
+
["/fallback manual", "Ask before remote inference after each local failure"],
|
|
2548
|
+
["/config", "Show current configuration"],
|
|
2549
|
+
["/color", "Use terminal colors and thin section rules"],
|
|
2550
|
+
["/color status", "Show terminal appearance preferences"],
|
|
2551
|
+
["/color frill on|off|toggle|status", "Legacy text ornament preference"],
|
|
2552
|
+
[
|
|
2553
|
+
"/color flow on|off|toggle|status",
|
|
2554
|
+
"Legacy border animation preference"
|
|
2555
|
+
],
|
|
2556
|
+
["/theme", "Alias for /color"],
|
|
2557
|
+
["/setup", "Open guided cloud setup; /setup local opens local model setup"],
|
|
2558
|
+
["/wizard", "Alias for /setup"],
|
|
2559
|
+
["/parallel", "Show current Ollama parallel inference slots"],
|
|
2560
|
+
["/parallel <1-15>", "Set parallel slots (restarts Ollama, max 15)"],
|
|
2561
|
+
["/gpu", "Select enabled GPUs with arrow keys and Space"],
|
|
2562
|
+
["/gpu status|reset", "Inspect or reset the host-local GPU policy"],
|
|
2563
|
+
["/gpu select <UUID>", "Open the GPU policy selector focused on a device"],
|
|
2564
|
+
[
|
|
2565
|
+
"/broker",
|
|
2566
|
+
"Show resource broker status — loaded models, in-flight loads, RAM/VRAM headroom"
|
|
2567
|
+
],
|
|
2568
|
+
[
|
|
2569
|
+
"/broker evict <host>:<name>",
|
|
2570
|
+
"Force eviction of a tracked model (e.g. /broker evict ollama:moondream)"
|
|
2571
|
+
],
|
|
2572
|
+
[
|
|
2573
|
+
"/broker threshold <ram|vram|idle> <v>",
|
|
2574
|
+
"Tune broker thresholds (RAM/VRAM in MB, idle in seconds)"
|
|
2575
|
+
],
|
|
2576
|
+
["/ollama cleanup", "Dry-run stale Ollama pool process cleanup"],
|
|
2577
|
+
["/ollama cleanup --execute", "Terminate guarded stale Ollama pool runners"],
|
|
2578
|
+
["/mcp", "Show MCP server/tool status and controls"],
|
|
2579
|
+
["/mcp reload", "Reload MCP servers and tools"],
|
|
2580
|
+
["/indicator", "Start the native system indicator and report readiness"],
|
|
2581
|
+
["/indicator start", "Start the native system indicator and report readiness"],
|
|
2582
|
+
["/indicator status", "Report native system indicator readiness and daemon health"],
|
|
2583
|
+
["/tray", "Alias for /indicator"],
|
|
2584
|
+
["/tray start", "Alias for /indicator start"],
|
|
2585
|
+
["/tray status", "Alias for /indicator status"],
|
|
2586
|
+
["/update", "Check for updates and auto-install"],
|
|
2587
|
+
["/upgrade", "Alias for /update"],
|
|
2588
|
+
["/update auto", "Auto-install updates, restart, and resume work (default)"],
|
|
2589
|
+
["/update manual", "Disable auto-update (only update on /update)"],
|
|
2590
|
+
["/agents", "Open the agent command center"],
|
|
2591
|
+
[
|
|
2592
|
+
"/update check",
|
|
2593
|
+
"Check for Omnius and Ollama updates without opening the menu"
|
|
2594
|
+
],
|
|
2595
|
+
["/update quick", "Install the latest Omnius package non-interactively"],
|
|
2596
|
+
[
|
|
2597
|
+
"/update full",
|
|
2598
|
+
"Run full non-interactive update: package, deps, rebuild, Python, cloudflared"
|
|
2599
|
+
],
|
|
2600
|
+
["/voice", "Toggle TTS voice feedback"],
|
|
2601
|
+
[
|
|
2602
|
+
"/voice <model>",
|
|
2603
|
+
"Set voice: glados, overwatch, luxtts:announcer-testchamber03, kokoro, luxtts, misotts, supertonic, or a selected voicebox_* model"
|
|
2604
|
+
],
|
|
2605
|
+
["/voice clone <file>", "Set voice clone reference audio (wav/mp3/ogg/flac)"],
|
|
2606
|
+
["/voice asr", "Open ASR system and model selection"],
|
|
2607
|
+
["/voice asr status", "Show selected ASR engine/model and activation state"],
|
|
2608
|
+
["/voice asr list", "List ASR engines, models, and live/file capabilities"],
|
|
2609
|
+
["/voice asr use <engine> [model]", "Select and activate an installed ASR engine/model"],
|
|
2610
|
+
["/voice asr setup <engine> [model] [device=N]", "Install pinned ASR runtime/weights and activate on an exact CUDA device"],
|
|
2611
|
+
[
|
|
2612
|
+
"/voice clone glados",
|
|
2613
|
+
"Generate clone ref from GLaDOS for LuxTTS/MisoTTS voice cloning"
|
|
2614
|
+
],
|
|
2615
|
+
[
|
|
2616
|
+
"/voice clone overwatch",
|
|
2617
|
+
"Generate clone ref from Overwatch for LuxTTS/MisoTTS voice cloning"
|
|
2618
|
+
],
|
|
2619
|
+
["/think", "Toggle thinking/reasoning mode (Qwen3, DeepSeek-R1, etc.)"],
|
|
2620
|
+
["/stream", "Toggle real-time token streaming (earth syntax highlighting)"],
|
|
2621
|
+
["/tree", "Switch between the action waterfall and an explorable action tree"],
|
|
2622
|
+
["/tree on|off|status", "Show, hide, or inspect the action-tree presentation"],
|
|
2623
|
+
["/realtime", "Toggle short spoken-dialogue mode for ASR/TTS-backed chat"],
|
|
2624
|
+
["/realtime on|off|status", "Set or inspect realtime conversation mode"],
|
|
2625
|
+
["/mouse", "Toggle terminal mouse tracking"],
|
|
2626
|
+
["/neovim", "Toggle embedded Neovim editor (Ctrl+N to switch focus)"],
|
|
2627
|
+
["/neovim <file>", "Open file in embedded Neovim editor"],
|
|
2628
|
+
["/nvim <file>", "Alias for /neovim <file>"],
|
|
2629
|
+
["/vim", "Toggle Vim composer editing (Esc normal; i insert)"],
|
|
2630
|
+
["/vim on|off|status", "Set or inspect Vim composer editing"],
|
|
2631
|
+
[
|
|
2632
|
+
"/dream",
|
|
2633
|
+
"Start dream mode - creative idle exploration (writes to .omnius/dreams/)"
|
|
2634
|
+
],
|
|
2635
|
+
[
|
|
2636
|
+
"/dream deep",
|
|
2637
|
+
"Deep dream - multi-cycle exploration with sleep architecture"
|
|
2638
|
+
],
|
|
2639
|
+
[
|
|
2640
|
+
"/dream lucid",
|
|
2641
|
+
"Lucid dream - implements proposals, tests, evaluates in cycles"
|
|
2642
|
+
],
|
|
2643
|
+
["/dream stop", "Wake up - stop dreaming"],
|
|
2644
|
+
["/listen", "Toggle live microphone transcription (Whisper)"],
|
|
2645
|
+
["/mic", "Alias for /listen"],
|
|
2646
|
+
["/listen <model>", "Set model: tiny, base, small, medium, large"],
|
|
2647
|
+
["/listen manual", "Manual mode - press Enter to submit (turns off auto)"],
|
|
2648
|
+
["/listen auto", "Auto-submit after 3s silence (blinking indicator)"],
|
|
2649
|
+
["/listen stop", "Stop listening"],
|
|
2650
|
+
["/live", "Open live sensor stream menu for video/audio context"],
|
|
2651
|
+
["/live status", "Show live sensor devices, selected streams, and latest snapshot"],
|
|
2652
|
+
["/live run [agent]", "Start low-latency video/audio feedback; agent enables background PFC review"],
|
|
2653
|
+
["/live chat", "Start low-latency voicechat with live audio/video context and async agent review"],
|
|
2654
|
+
["/livechat", "Alias for /live chat, used by the top live button"],
|
|
2655
|
+
["/live camera <device>", "Select a camera and render an ASCII preview"],
|
|
2656
|
+
["/live resolution [camera] 720p|1080p|1440p|4k|native", "Set per-camera live stream resolution (default 1080p)"],
|
|
2657
|
+
["/live fps [camera] 1|2|4|8|12|15|24|30", "Set per-camera live stream FPS (default 8)"],
|
|
2658
|
+
["/live camera-on|camera-off [camera]", "Enable or disable an individual live camera stream"],
|
|
2659
|
+
["/live rotate auto|cw|ccw|180|none [camera]", "Detect or set persistent camera orientation correction"],
|
|
2660
|
+
["/live infer [now|on|off]", "Toggle or run camera object/location inference"],
|
|
2661
|
+
["/live clip [on|off]", "Toggle CLIP visual-memory recognition on live frames"],
|
|
2662
|
+
["/live audio|asr|sounds on|off", "Toggle live audio context streams"],
|
|
2663
|
+
["/live stop", "Disable all live sensor streams"],
|
|
2664
|
+
["/camera", "Open compact camera preset menu shared with /live"],
|
|
2665
|
+
["/camera status", "Show selected camera and per-device presets"],
|
|
2666
|
+
["/camera select|preview|resolution|fps|rotate", "Manage camera source, preview, resolution, FPS, and orientation"],
|
|
2667
|
+
["/paste", "Attach clipboard image content to the current or next prompt"],
|
|
2668
|
+
["/image", "Open image-generation model/setup menu"],
|
|
2669
|
+
[
|
|
2670
|
+
"/image <prompt>",
|
|
2671
|
+
"Generate an image from a prompt and show an ASCII preview"
|
|
2672
|
+
],
|
|
2673
|
+
["/image --model <model> <prompt>", "Generate with an explicit image model"],
|
|
2674
|
+
[
|
|
2675
|
+
"/image setup <ollama|diffusers|sdcpp>",
|
|
2676
|
+
"Show setup commands for an image-generation backend"
|
|
2677
|
+
],
|
|
2678
|
+
[
|
|
2679
|
+
"/image list",
|
|
2680
|
+
"List image models by category, quality, size, and hardware fit"
|
|
2681
|
+
],
|
|
2682
|
+
["/sound", "Open sound-effect model/setup menu"],
|
|
2683
|
+
["/sound <prompt>", "Generate a sound effect or ambience clip from a prompt"],
|
|
2684
|
+
[
|
|
2685
|
+
"/sound --model <model> <prompt>",
|
|
2686
|
+
"Generate sound with an explicit audio model"
|
|
2687
|
+
],
|
|
2688
|
+
[
|
|
2689
|
+
"/sound setup <diffusers|audiocraft|stable-audio|tangoflux>",
|
|
2690
|
+
"Show setup commands for a sound-generation backend"
|
|
2691
|
+
],
|
|
2692
|
+
[
|
|
2693
|
+
"/sound list",
|
|
2694
|
+
"List sound models by category, quality, size, and hardware fit"
|
|
2695
|
+
],
|
|
2696
|
+
["/music", "Open music-generation model/setup menu"],
|
|
2697
|
+
["/music <prompt>", "Generate a music clip from a prompt"],
|
|
2698
|
+
[
|
|
2699
|
+
"/music --model <model> <prompt>",
|
|
2700
|
+
"Generate music with an explicit music model"
|
|
2701
|
+
],
|
|
2702
|
+
[
|
|
2703
|
+
"/music setup <transformers|audiocraft|stable-audio|diffusers>",
|
|
2704
|
+
"Show setup commands for a music-generation backend"
|
|
2705
|
+
],
|
|
2706
|
+
[
|
|
2707
|
+
"/music list",
|
|
2708
|
+
"List music models by category, quality, size, and hardware fit"
|
|
2709
|
+
],
|
|
2710
|
+
["/video", "Open video-generation model/setup menu"],
|
|
2711
|
+
[
|
|
2712
|
+
"/video <prompt>",
|
|
2713
|
+
"Generate a short video from a prompt and show an ASCII thumbnail"
|
|
2714
|
+
],
|
|
2715
|
+
["/video --model <model> <prompt>", "Generate video with an explicit model"],
|
|
2716
|
+
[
|
|
2717
|
+
"/video --image <path|url> <prompt>",
|
|
2718
|
+
"Image-to-video animation from a still"
|
|
2719
|
+
],
|
|
2720
|
+
[
|
|
2721
|
+
"/video setup <diffusers|comfyui>",
|
|
2722
|
+
"Show setup commands for a video-generation backend"
|
|
2723
|
+
],
|
|
2724
|
+
[
|
|
2725
|
+
"/video list",
|
|
2726
|
+
"List video models by category, quality, size, and hardware fit"
|
|
2727
|
+
],
|
|
2728
|
+
["/video prewarm", "Download and warm up the selected video model"],
|
|
2729
|
+
["/pointcloud", "Open point-cloud generation model/setup menu"],
|
|
2730
|
+
[
|
|
2731
|
+
"/pointcloud --image <path>",
|
|
2732
|
+
"Generate a 3D point cloud PLY from an image using depth estimation"
|
|
2733
|
+
],
|
|
2734
|
+
[
|
|
2735
|
+
"/pointcloud --image <path> --model <model>",
|
|
2736
|
+
"Generate with an explicit depth model (depth-anything-v3-* or mda-*)"
|
|
2737
|
+
],
|
|
2738
|
+
[
|
|
2739
|
+
"/pointcloud --image <path1,path2> --backend mda",
|
|
2740
|
+
"Multi-view depth fusion from comma-separated image paths"
|
|
2741
|
+
],
|
|
2742
|
+
[
|
|
2743
|
+
"/pointcloud setup <depth-anything|mda>",
|
|
2744
|
+
"Show setup commands for a point-cloud backend"
|
|
2745
|
+
],
|
|
2746
|
+
[
|
|
2747
|
+
"/pointcloud list",
|
|
2748
|
+
"List point-cloud models by backend, quality, and VRAM fit"
|
|
2749
|
+
],
|
|
2750
|
+
["/pointcloud prewarm", "Download and warm up the selected depth model"],
|
|
2751
|
+
["/points <args>", "Alias for /pointcloud"],
|
|
2752
|
+
["/pcl <args>", "Alias for /pointcloud"],
|
|
2753
|
+
["/call", "Start voice call session (cloudflared tunnel + ASR/TTS)"],
|
|
2754
|
+
["/hangup", "End active call session"],
|
|
2755
|
+
[
|
|
2756
|
+
"/queue <prompt>",
|
|
2757
|
+
"Queue a prompt for the next turn without interrupting the current run"
|
|
2758
|
+
],
|
|
2759
|
+
["/q <prompt>", "Alias for /queue <prompt>"],
|
|
2760
|
+
["/retry", "Retry the last submitted request"],
|
|
2761
|
+
["/undo", "Undo the last queued or saved exchange when available"],
|
|
2762
|
+
["/title [name]", "Show or set the current session title"],
|
|
2763
|
+
[
|
|
2764
|
+
"/rollback [checkpoint]",
|
|
2765
|
+
"List checkpoints or restore an explicit checkpoint when policy allows"
|
|
2766
|
+
],
|
|
2767
|
+
["/background <prompt>", "Run a prompt in an independent background session"],
|
|
2768
|
+
["/bg <prompt>", "Alias for /background <prompt>"],
|
|
2769
|
+
["/cost", "Show session token cost breakdown"],
|
|
2770
|
+
["/usage", "Show current session token count and cost"],
|
|
2771
|
+
["/insights", "Show historical session insights"],
|
|
2772
|
+
["/evaluate", "Evaluate last completed task (LLM quality scoring)"],
|
|
2773
|
+
[
|
|
2774
|
+
"/score",
|
|
2775
|
+
"Show inference capability scorecard (memory, compute, speed, models)"
|
|
2776
|
+
],
|
|
2777
|
+
[
|
|
2778
|
+
"/task-type",
|
|
2779
|
+
"Set task type (code, document, analysis, plan, general, auto)"
|
|
2780
|
+
],
|
|
2781
|
+
["/stats", "Show session dashboard (metrics, tool usage, task history)"],
|
|
2782
|
+
[
|
|
2783
|
+
"/metrics",
|
|
2784
|
+
"Show runtime metrics: tokens, context window, throughput, and tool usage"
|
|
2785
|
+
],
|
|
2786
|
+
["/sessions", "Browse saved sessions"],
|
|
2787
|
+
["/new", "Start a fresh chat in the current project"],
|
|
2788
|
+
[
|
|
2789
|
+
"/pause",
|
|
2790
|
+
"Pause after current turn finishes (gentle halt, /resume to continue)"
|
|
2791
|
+
],
|
|
2792
|
+
[
|
|
2793
|
+
"/stop",
|
|
2794
|
+
"Kill current inference immediately and save state (/resume to continue)"
|
|
2795
|
+
],
|
|
2796
|
+
[
|
|
2797
|
+
"/resume",
|
|
2798
|
+
"Resume a paused task or choose a saved project chat"
|
|
2799
|
+
],
|
|
2800
|
+
["/resume <session>", "Resume a saved project chat by id or title"],
|
|
2801
|
+
[
|
|
2802
|
+
"/destroy processes",
|
|
2803
|
+
"Find and kill orphaned Omnius child processes (this project)"
|
|
2804
|
+
],
|
|
2805
|
+
[
|
|
2806
|
+
"/destroy processes --global",
|
|
2807
|
+
"Kill ALL orphaned Omnius processes system-wide"
|
|
2808
|
+
],
|
|
2809
|
+
[
|
|
2810
|
+
"/destroy project",
|
|
2811
|
+
"Remove .omnius folder, kill all tasks, clear console, and exit"
|
|
2812
|
+
],
|
|
2813
|
+
["/context save", "Force-save session context to .omnius/context/"],
|
|
2814
|
+
["/context restore", "Restore context from previous sessions into next task"],
|
|
2815
|
+
["/context show", "Show saved session context status"],
|
|
2816
|
+
["/compact", "Force context compaction now (default strategy)"],
|
|
2817
|
+
["/compacted", "Review applied, held, rejected, and failed compaction attempts"],
|
|
2818
|
+
[
|
|
2819
|
+
"/compact <strategy>",
|
|
2820
|
+
"Compact with strategy: aggressive, decisions, errors, summary, structured"
|
|
2821
|
+
],
|
|
2822
|
+
["/bruteforce", "Toggle brute-force mode (auto re-engage on turn limit)"],
|
|
2823
|
+
[
|
|
2824
|
+
"/deep",
|
|
2825
|
+
"Toggle deep context - relaxes compaction so large models use 85% of context"
|
|
2826
|
+
],
|
|
2827
|
+
[
|
|
2828
|
+
"/flow",
|
|
2829
|
+
"Toggle FlowState protocol - immediate action, tight loops, goal clarity"
|
|
2830
|
+
],
|
|
2831
|
+
["/emojis", "Toggle emoji rendering in TUI messages"],
|
|
2832
|
+
["/tools", "List agent-created custom tools"],
|
|
2833
|
+
["/skills", "List available AIWG skills"],
|
|
2834
|
+
["/skill", "Alias for /skills"],
|
|
2835
|
+
["/skills <keyword>", "Filter skills by name or trigger"],
|
|
2836
|
+
["/skillify [request]", "Extract a reusable skill from the current session"],
|
|
2837
|
+
["/<skill-name> [args]", "Invoke an AIWG skill directly"],
|
|
2838
|
+
[
|
|
2839
|
+
"/full-send-bless",
|
|
2840
|
+
"Infinite warm loop - DMN self-reflection chains tasks autonomously"
|
|
2841
|
+
],
|
|
2842
|
+
["/bless stop", "End blessed mode + DMN"],
|
|
2843
|
+
[
|
|
2844
|
+
"/telegram --key <token>",
|
|
2845
|
+
"Save Telegram bot token (persisted to settings)"
|
|
2846
|
+
],
|
|
2847
|
+
[
|
|
2848
|
+
"/telegram --admin <userid>",
|
|
2849
|
+
"Set admin user filter (only this user can interact)"
|
|
2850
|
+
],
|
|
2851
|
+
["/telegram", "Toggle Telegram bridge on/off (uses saved key)"],
|
|
2852
|
+
["/telegram status", "Show Telegram bridge status"],
|
|
2853
|
+
["/telegram stop", "Disconnect Telegram bridge"],
|
|
2854
|
+
["/telegram disable", "Persistently disable Telegram long polling"],
|
|
2855
|
+
["/telegram enable", "Re-enable Telegram long polling"],
|
|
2856
|
+
[
|
|
2857
|
+
"/telegram mode auto|chat|action",
|
|
2858
|
+
"Set Telegram interaction routing: auto, fast chat, or action sub-agent"
|
|
2859
|
+
],
|
|
2860
|
+
[
|
|
2861
|
+
"/telegram subagents <1-5>",
|
|
2862
|
+
"Set global Telegram work-slot limit across all chats/groups"
|
|
2863
|
+
],
|
|
2864
|
+
[
|
|
2865
|
+
"/telegram model",
|
|
2866
|
+
"Pick the Telegram-isolated model (model list from the Telegram endpoint)"
|
|
2867
|
+
],
|
|
2868
|
+
[
|
|
2869
|
+
"/telegram model <name|reset>",
|
|
2870
|
+
"Set or clear the Telegram-isolated model (separate from main agent)"
|
|
2871
|
+
],
|
|
2872
|
+
[
|
|
2873
|
+
"/telegram endpoint",
|
|
2874
|
+
"Pick the Telegram-isolated backend endpoint (same menu as /endpoint, bot-scoped)"
|
|
2875
|
+
],
|
|
2876
|
+
[
|
|
2877
|
+
"/telegram endpoint <url|reset> [--auth <t>]",
|
|
2878
|
+
"Set or clear the Telegram-isolated endpoint"
|
|
2879
|
+
],
|
|
2880
|
+
[
|
|
2881
|
+
"/telegram auth",
|
|
2882
|
+
"Show a TUI-only one-time code for Telegram admin authentication"
|
|
2883
|
+
],
|
|
2884
|
+
[
|
|
2885
|
+
"/telegram auth cancel",
|
|
2886
|
+
"Cancel the pending Telegram admin authentication code"
|
|
2887
|
+
],
|
|
2888
|
+
[
|
|
2889
|
+
"/telegram bot <username> <text>",
|
|
2890
|
+
"Send a Bot API bot-to-bot message by @username"
|
|
2891
|
+
],
|
|
2892
|
+
[
|
|
2893
|
+
"/telegram poll <chat> <question> | <option> [| <option>]",
|
|
2894
|
+
"Send a Telegram poll"
|
|
2895
|
+
],
|
|
2896
|
+
[
|
|
2897
|
+
"/telegram live-photo <chat> <live_photo> <photo> [caption]",
|
|
2898
|
+
"Send a Telegram live photo"
|
|
2899
|
+
],
|
|
2900
|
+
[
|
|
2901
|
+
"/telegram draft <chat_id> <draft_id> [text]",
|
|
2902
|
+
"Set or clear a Telegram message draft"
|
|
2903
|
+
],
|
|
2904
|
+
[
|
|
2905
|
+
"/telegram admins <chat> [--bots]",
|
|
2906
|
+
"List chat administrators, optionally including bots"
|
|
2907
|
+
],
|
|
2908
|
+
[
|
|
2909
|
+
"/telegram personal <user_id> <limit>",
|
|
2910
|
+
"Fetch last messages from a user's profile personal chat"
|
|
2911
|
+
],
|
|
2912
|
+
[
|
|
2913
|
+
"/telegram access get <managed_bot_user_id>",
|
|
2914
|
+
"Show managed-bot access restriction settings"
|
|
2915
|
+
],
|
|
2916
|
+
[
|
|
2917
|
+
"/telegram access set <managed_bot_user_id> <restricted|open> [added_user_ids]",
|
|
2918
|
+
"Set managed-bot access restrictions"
|
|
2919
|
+
],
|
|
2920
|
+
[
|
|
2921
|
+
"/telegram tools [group <chat>|panel <chat> [policy_chat]]",
|
|
2922
|
+
"Show unified Telegram tool policy or send inline admin toggle buttons"
|
|
2923
|
+
],
|
|
2924
|
+
[
|
|
2925
|
+
"/telegram delete-message <chat> <message> [reason]",
|
|
2926
|
+
"Delete one Telegram message after policy and Bot API rights checks"
|
|
2927
|
+
],
|
|
2928
|
+
[
|
|
2929
|
+
"/telegram delete-messages <chat> <message,message> [reason]",
|
|
2930
|
+
"Delete multiple Telegram messages after policy and Bot API rights checks"
|
|
2931
|
+
],
|
|
2932
|
+
[
|
|
2933
|
+
"/telegram delete-reaction <chat> <message> [--user <id>|--actor <chat>]",
|
|
2934
|
+
"Delete a Telegram message reaction"
|
|
2935
|
+
],
|
|
2936
|
+
[
|
|
2937
|
+
"/telegram delete-reactions <chat> [--user <id>|--actor <chat>]",
|
|
2938
|
+
"Delete recent Telegram message reactions by user or chat"
|
|
2939
|
+
],
|
|
2940
|
+
["/platforms", "Show gateway platform state"],
|
|
2941
|
+
["/platforms status", "Show gateway platform state"],
|
|
2942
|
+
["/platforms menu", "Open interactive platform connectivity menu"],
|
|
2943
|
+
["/platforms setup", "Open platform onboarding menu"],
|
|
2944
|
+
["/platforms onboard", "Open platform onboarding menu"],
|
|
2945
|
+
["/platforms config", "Show redacted platform adapter configuration"],
|
|
2946
|
+
["/platforms enable <id>", "Enable a platform adapter"],
|
|
2947
|
+
["/platforms disable <id>", "Disable a platform adapter"],
|
|
2948
|
+
[
|
|
2949
|
+
"/platforms set <id> token-env <ENV>",
|
|
2950
|
+
"Set adapter token environment variable"
|
|
2951
|
+
],
|
|
2952
|
+
["/platforms set <id> base-url <url>", "Set adapter base URL or webhook URL"],
|
|
2953
|
+
[
|
|
2954
|
+
"/platforms set <id> target <target>",
|
|
2955
|
+
"Set adapter default channel, room, or target"
|
|
2956
|
+
],
|
|
2957
|
+
[
|
|
2958
|
+
"/platforms set <id> mode <polling|webhook>",
|
|
2959
|
+
"Set adapter polling or webhook mode"
|
|
2960
|
+
],
|
|
2961
|
+
[
|
|
2962
|
+
"/platforms clear <id> <key>",
|
|
2963
|
+
"Clear saved adapter token, token-env, base-url, or target"
|
|
2964
|
+
],
|
|
2965
|
+
["/gateway", "Alias for /platforms"],
|
|
2966
|
+
["/gateway menu", "Alias for /platforms menu"],
|
|
2967
|
+
[
|
|
2968
|
+
"/cohere",
|
|
2969
|
+
"Toggle COHERE cognitive commons - join distributed memory/identity mesh"
|
|
2970
|
+
],
|
|
2971
|
+
[
|
|
2972
|
+
"/cohere stats",
|
|
2973
|
+
"Show network stats - queries in/out, model usage, peer transparency"
|
|
2974
|
+
],
|
|
2975
|
+
["/cohere models", "List downloaded models with COHERE exposure status"],
|
|
2976
|
+
["/cohere allow <model>", "Allow a model for remote COHERE queries"],
|
|
2977
|
+
["/cohere deny <model>", "Hide a model from remote COHERE queries"],
|
|
2978
|
+
["/nexus", "Show nexus P2P network status"],
|
|
2979
|
+
["/nexus connect", "Connect to the agent mesh network"],
|
|
2980
|
+
[
|
|
2981
|
+
"/nexus name <name>",
|
|
2982
|
+
"Set custom agent name (persists globally across all Omnius instances)"
|
|
2983
|
+
],
|
|
2984
|
+
["/nexus name", "Show current agent name"],
|
|
2985
|
+
["/nexus restart", "Kill daemon and reconnect (picks up new version)"],
|
|
2986
|
+
["/nexus restart --clean", "Restart + clear metering data for fresh stats"],
|
|
2987
|
+
["/nexus disconnect", "Kill daemon without reconnecting"],
|
|
2988
|
+
["/nexus wallet", "Show wallet address and x402 payment status"],
|
|
2989
|
+
["/ipfs", "Show IPFS/Helia status"],
|
|
2990
|
+
["/ipfs pin <cid>", "Pin an IPFS CID"],
|
|
2991
|
+
["/ipfs publish", "Publish identity snapshot to IPFS"],
|
|
2992
|
+
["/ipfs share <tool|skill> <name>", "Share a tool or skill through IPFS"],
|
|
2993
|
+
["/ipfs import <cid>", "Import a shared IPFS tool or skill reference"],
|
|
2994
|
+
["/sponsor", "Sponsor inference - onboarding wizard or dashboard"],
|
|
2995
|
+
["/sponsor status", "Show sponsor dashboard with usage metrics"],
|
|
2996
|
+
["/sponsor image <prompt>", "Generate an image on a sponsored peer"],
|
|
2997
|
+
["/sponsor video <prompt>", "Generate a video on a sponsored peer"],
|
|
2998
|
+
["/sponsor sound <prompt>", "Generate a sound effect on a sponsored peer"],
|
|
2999
|
+
["/sponsor music <prompt>", "Generate music on a sponsored peer"],
|
|
3000
|
+
["/sponsor pause", "Pause active sponsorship"],
|
|
3001
|
+
["/sponsor remove", "Remove sponsorship entirely"],
|
|
3002
|
+
[
|
|
3003
|
+
"/endpoint sponsor",
|
|
3004
|
+
"Browse and connect to sponsored inference from the nexus mesh"
|
|
3005
|
+
],
|
|
3006
|
+
["/expose <backend>", "Expose local inference via libp2p (default)"],
|
|
3007
|
+
["/expose <backend> --tunnel", "Expose via cloudflared tunnel"],
|
|
3008
|
+
["/expose passthrough", "Forward configured /endpoint through libp2p P2P"],
|
|
3009
|
+
[
|
|
3010
|
+
"/expose forward --loadbalance",
|
|
3011
|
+
"Passthrough with distributed rate-limit budget"
|
|
3012
|
+
],
|
|
3013
|
+
["/expose config", "Interactive expose configuration menu"],
|
|
3014
|
+
["/expose status", "Show gateway stats (requests, models, budget)"],
|
|
3015
|
+
["/expose stop", "Stop all expose gateways"],
|
|
3016
|
+
["/expose stop --tunnel", "Stop tunnel gateway only"],
|
|
3017
|
+
["/expose stop --libp2p", "Stop libp2p gateway only"],
|
|
3018
|
+
["/access", "Show access policy and host binding"],
|
|
3019
|
+
[
|
|
3020
|
+
"/access <loopback|lan|any>",
|
|
3021
|
+
"Set access policy (OMNIUS_ACCESS) and restart daemon"
|
|
3022
|
+
],
|
|
3023
|
+
["/k <any|lan|loopback|config>", "Quick network access helper"],
|
|
3024
|
+
["/scheduler", "Scheduled tasks control panel (list/kill/toggle)"],
|
|
3025
|
+
["/cron", "Cron/scheduled job management"],
|
|
3026
|
+
["/cron list", "List cron jobs"],
|
|
3027
|
+
["/cron add <schedule> <prompt>", "Create a new cron job"],
|
|
3028
|
+
["/cron edit <id> <field> <val>", "Update a cron job field"],
|
|
3029
|
+
["/cron pause <id>", "Pause a cron job"],
|
|
3030
|
+
["/cron resume <id>", "Resume a paused cron job"],
|
|
3031
|
+
["/cron run <id>", "Execute a cron job immediately"],
|
|
3032
|
+
["/cron remove <id>", "Delete a cron job"],
|
|
3033
|
+
["/cron outputs <id>", "Show saved output files for a job"],
|
|
3034
|
+
["/cron tick", "Run scheduler tick"],
|
|
3035
|
+
["/scheduler menu", "Interactive scheduler menu (toggle/kill)"],
|
|
3036
|
+
["/scheduler list", "List all scheduled tasks and timers"],
|
|
3037
|
+
[
|
|
3038
|
+
"/scheduler kill",
|
|
3039
|
+
"Kill schedulers + active runs (with escalation if needed)"
|
|
3040
|
+
],
|
|
3041
|
+
["/reminder [list|all]", "List scoped TUI reminders"],
|
|
3042
|
+
[
|
|
3043
|
+
"/remind <when> <message>",
|
|
3044
|
+
"Set a scoped person notification; a due time is required"
|
|
3045
|
+
],
|
|
3046
|
+
[
|
|
3047
|
+
"/remind in 30m <message>",
|
|
3048
|
+
"Set a scoped person notification with a relative due time"
|
|
3049
|
+
],
|
|
3050
|
+
["/reminders", "Alias for /reminder"],
|
|
3051
|
+
["/daemon", "Show or manage the local API daemon"],
|
|
3052
|
+
["/daemon <start|stop|restart|takeover>", "Control the local API daemon"],
|
|
3053
|
+
["/apikey", "Show current API key (for pasting into Web UI / clients)"],
|
|
3054
|
+
["/apikey copy", "Copy the API key to clipboard"],
|
|
3055
|
+
["/apikey new", "Rotate to a new API key (regenerate)"],
|
|
3056
|
+
["/secrets", "List registered secrets"],
|
|
3057
|
+
["/secrets set <name> <value>", "Register a secret for redacted tool use"],
|
|
3058
|
+
["/secrets delete <name>", "Remove a registered secret"],
|
|
3059
|
+
["/key", "Alias for /apikey"],
|
|
3060
|
+
["/codegraph", "Code-graph snapshot: stats, top files, recent activity"],
|
|
3061
|
+
[
|
|
3062
|
+
"/codegraph watch [N]",
|
|
3063
|
+
"Subscribe to live code-graph events for N seconds (default 30)"
|
|
3064
|
+
],
|
|
3065
|
+
["/cg", "Alias for /codegraph"],
|
|
3066
|
+
["/storage", "Show .omnius storage usage and safety summary"],
|
|
3067
|
+
["/files", "Show searchable working-directory file overview"],
|
|
3068
|
+
["/files <query>", "Filter the working-directory file overview"],
|
|
3069
|
+
["/files menu", "Open searchable workspace file selector"],
|
|
3070
|
+
["/workspace", "Alias for /files"],
|
|
3071
|
+
["/workspace <query>", "Alias for /files <query>"],
|
|
3072
|
+
["/workspace menu", "Alias for /files menu"],
|
|
3073
|
+
["/ingest <file>", "Ingest an audio, PDF, or text file into memory"],
|
|
3074
|
+
["/transcribe <file>", "Alias for /ingest <file>"],
|
|
3075
|
+
["/fortemi", "Manage Fortemi React bridge integration"],
|
|
3076
|
+
[
|
|
3077
|
+
"/host <host[:port]>",
|
|
3078
|
+
"Set bind host:port (OMNIUS_HOST) and restart daemon"
|
|
3079
|
+
],
|
|
3080
|
+
["/network config", "Interactive network access menu"],
|
|
3081
|
+
["/p2p start", "Join the P2P agent mesh network"],
|
|
3082
|
+
["/p2p status", "Show mesh peers and rooms"],
|
|
3083
|
+
["/p2p stop", "Leave the mesh network"],
|
|
3084
|
+
["/style", "Show current response style"],
|
|
3085
|
+
["/style <preset>", "Set style: concise, balanced, verbose, pedagogical"],
|
|
3086
|
+
[
|
|
3087
|
+
"/personality <preset>",
|
|
3088
|
+
"Alias family for response style/personality controls"
|
|
3089
|
+
],
|
|
3090
|
+
["/commands auto", "Allow agent to invoke slash commands as tools"],
|
|
3091
|
+
["/cmds auto", "Alias for /commands auto"],
|
|
3092
|
+
["/commands manual", "Slash commands are user-only (default)"],
|
|
3093
|
+
[
|
|
3094
|
+
"/selfmodify",
|
|
3095
|
+
"Toggle agent self-modify mode for natural-language runtime commands"
|
|
3096
|
+
],
|
|
3097
|
+
[
|
|
3098
|
+
"/selfmodify on",
|
|
3099
|
+
"Allow the agent to decide when to invoke self-modifying slash commands"
|
|
3100
|
+
],
|
|
3101
|
+
[
|
|
3102
|
+
"/selfmodify off",
|
|
3103
|
+
"Disable agent self-modifying slash-command access (default)"
|
|
3104
|
+
],
|
|
3105
|
+
["/selfmodify status", "Show current self-modify mode"],
|
|
3106
|
+
[
|
|
3107
|
+
"/selfimprove status",
|
|
3108
|
+
"Show durable review/proposal backlog, leases, retries, and last error"
|
|
3109
|
+
],
|
|
3110
|
+
[
|
|
3111
|
+
"/selfimprove start",
|
|
3112
|
+
"Enable review mode and drain eligible work with the parent model"
|
|
3113
|
+
],
|
|
3114
|
+
["/selfimprove stop", "Disable processing while retaining the durable backlog"],
|
|
3115
|
+
["/selfimprove disable", "Alias for /selfimprove stop"],
|
|
3116
|
+
[
|
|
3117
|
+
"/selfimprove review",
|
|
3118
|
+
"Run evidence review and candidate generation without active promotion"
|
|
3119
|
+
],
|
|
3120
|
+
[
|
|
3121
|
+
"/selfimprove autonomous",
|
|
3122
|
+
"Opt in to downstream candidate experiment and promotion orchestration"
|
|
3123
|
+
],
|
|
3124
|
+
[
|
|
3125
|
+
"/selfimprove rollback <promotion-id> [reason]",
|
|
3126
|
+
"Restore the exact pre-promotion baseline and verify the rollback"
|
|
3127
|
+
],
|
|
3128
|
+
["/debug", "Toggle debug mode — show/hide trust_tier wrappers and REG fires"],
|
|
3129
|
+
["/debug on", "Show trust_tier wrappers and REG fires in terminal"],
|
|
3130
|
+
["/debug off", "Hide trust_tier wrappers and REG fires (default)"],
|
|
3131
|
+
["/debug", "Toggle debug mode — show/hide trust_tier wrappers and REG fires"],
|
|
3132
|
+
["/debug on", "Show trust_tier wrappers and REG fires in terminal"],
|
|
3133
|
+
["/debug off", "Hide trust_tier wrappers and REG fires (default)"],
|
|
3134
|
+
["/hf", "Show HF token status (set / not set)"],
|
|
3135
|
+
[
|
|
3136
|
+
"/hf <token>",
|
|
3137
|
+
"Save Hugging Face access token to ~/.omnius/hf_token and unblock the active gated download"
|
|
3138
|
+
],
|
|
3139
|
+
["/hf clear", "Remove the persisted HF token"],
|
|
3140
|
+
[
|
|
3141
|
+
"/hf cancel",
|
|
3142
|
+
"Cancel any pending HF token prompt and fall back immediately"
|
|
3143
|
+
],
|
|
3144
|
+
[
|
|
3145
|
+
"/models",
|
|
3146
|
+
"Show unified ~/.omnius model store: disk usage, cached repos, last-used"
|
|
3147
|
+
],
|
|
3148
|
+
["/models 3d", "Select CAD/3D generation and reconstruction model adapters"],
|
|
3149
|
+
["/models cad", "Select text-to-CAD model adapters such as cad0"],
|
|
3150
|
+
[
|
|
3151
|
+
"/models viewer [file]",
|
|
3152
|
+
"Start a temporary standalone CAD/3D viewer endpoint"
|
|
3153
|
+
],
|
|
3154
|
+
[
|
|
3155
|
+
"/models hf list --modality 3d",
|
|
3156
|
+
"List curated and installed Hugging Face CAD/3D adapters"
|
|
3157
|
+
],
|
|
3158
|
+
[
|
|
3159
|
+
"/models evict <repo>",
|
|
3160
|
+
"Remove a cached HF repo from the unified store to reclaim disk"
|
|
3161
|
+
],
|
|
3162
|
+
[
|
|
3163
|
+
"/models evict --free <GB>",
|
|
3164
|
+
"LRU-evict cached models until <GB> of free disk is available"
|
|
3165
|
+
],
|
|
3166
|
+
[
|
|
3167
|
+
"/models cleanup",
|
|
3168
|
+
"Migrate legacy per-repo .omnius/{image,video,audio}-gen caches into the unified store and delete the originals"
|
|
3169
|
+
],
|
|
3170
|
+
[
|
|
3171
|
+
"/models cleanup --dry-run",
|
|
3172
|
+
"Preview /models cleanup without touching disk"
|
|
3173
|
+
],
|
|
3174
|
+
["/voicechat", "Start voice chat session (async voice conversation)"],
|
|
3175
|
+
["/voicechat stop", "Stop voice chat session"],
|
|
3176
|
+
["/memory", "Open the interactive memory pixel map and provenance trace"],
|
|
3177
|
+
["/memory legacy", "Open the legacy list-based memory browser"],
|
|
3178
|
+
[
|
|
3179
|
+
"/metabolize [--dry-run] [--verbose] [--min-score <n>]",
|
|
3180
|
+
"Run memory maintenance: import deferred memory, prune episodes, compact graph stores"
|
|
3181
|
+
],
|
|
3182
|
+
[
|
|
3183
|
+
"/prune [now|dry|infer|aggressive|stats] [--target <n>]",
|
|
3184
|
+
"Shrink knowledge.db in the background: evict low-signal graph nodes (archived), then VACUUM. 'infer' = model-guided sleep consolidation. No arg shows stats + usage"
|
|
3185
|
+
],
|
|
3186
|
+
["/verbose", "Toggle verbose mode"],
|
|
3187
|
+
["/clear", "Clear the screen"],
|
|
3188
|
+
["/help", "Show this help"],
|
|
3189
|
+
["/quit", "Exit omnius"]
|
|
3190
|
+
].map(([signature, description]) => ({ signature, description }));
|
|
3191
|
+
var PLANNED_SIGNATURES = [
|
|
3192
|
+
["/provider", "Show or select provider profile"],
|
|
3193
|
+
["/prompt", "Show or edit the active prompt template"],
|
|
3194
|
+
["/reasoning", "Alias family for thinking/reasoning controls"],
|
|
3195
|
+
["/statusbar", "Configure the status bar"],
|
|
3196
|
+
["/sb", "Alias for /statusbar"],
|
|
3197
|
+
["/skin", "Configure the visual skin/theme bundle"],
|
|
3198
|
+
["/toolsets", "Show or select tool exposure sets"],
|
|
3199
|
+
["/browser connect|disconnect|status", "Manage browser-agent connectivity"],
|
|
3200
|
+
["/reload-mcp", "Reload MCP servers and tools"],
|
|
3201
|
+
["/plugins", "List or manage plugins"],
|
|
3202
|
+
["/status", "Show overall runtime status"],
|
|
3203
|
+
["/sethome", "Set the project home for gateway/session use"],
|
|
3204
|
+
["/approve", "Approve a pending gateway/admin action"],
|
|
3205
|
+
["/deny", "Deny a pending gateway/admin action"]
|
|
3206
|
+
].map(([signature, description]) => ({
|
|
3207
|
+
signature,
|
|
3208
|
+
description,
|
|
3209
|
+
implementationStatus: "planned"
|
|
3210
|
+
}));
|
|
3211
|
+
var CATEGORY_OVERRIDES = {
|
|
3212
|
+
model: "model",
|
|
3213
|
+
models: "model",
|
|
3214
|
+
endpoint: "network",
|
|
3215
|
+
fallback: "network",
|
|
3216
|
+
provider: "network",
|
|
3217
|
+
parallel: "runtime",
|
|
3218
|
+
gpu: "runtime",
|
|
3219
|
+
broker: "runtime",
|
|
3220
|
+
setup: "runtime",
|
|
3221
|
+
wizard: "runtime",
|
|
3222
|
+
mcp: "tools",
|
|
3223
|
+
mcps: "tools",
|
|
3224
|
+
update: "admin",
|
|
3225
|
+
upgrade: "admin",
|
|
3226
|
+
voice: "media",
|
|
3227
|
+
voicechat: "media",
|
|
3228
|
+
listen: "media",
|
|
3229
|
+
mic: "media",
|
|
3230
|
+
paste: "media",
|
|
3231
|
+
image: "media",
|
|
3232
|
+
video: "media",
|
|
3233
|
+
pointcloud: "media",
|
|
3234
|
+
points: "media",
|
|
3235
|
+
pcl: "media",
|
|
3236
|
+
ingest: "media",
|
|
3237
|
+
transcribe: "media",
|
|
3238
|
+
call: "media",
|
|
3239
|
+
hangup: "media",
|
|
3240
|
+
queue: "session",
|
|
3241
|
+
q: "session",
|
|
3242
|
+
retry: "session",
|
|
3243
|
+
undo: "session",
|
|
3244
|
+
title: "session",
|
|
3245
|
+
rollback: "session",
|
|
3246
|
+
background: "session",
|
|
3247
|
+
bg: "session",
|
|
3248
|
+
pause: "session",
|
|
3249
|
+
stop: "session",
|
|
3250
|
+
resume: "session",
|
|
3251
|
+
new: "session",
|
|
3252
|
+
context: "session",
|
|
3253
|
+
compact: "session",
|
|
3254
|
+
compacted: "session",
|
|
3255
|
+
gc: "session",
|
|
3256
|
+
sessions: "session",
|
|
3257
|
+
session: "session",
|
|
3258
|
+
dream: "runtime",
|
|
3259
|
+
"full-send-bless": "runtime",
|
|
3260
|
+
bless: "runtime",
|
|
3261
|
+
telegram: "gateway",
|
|
3262
|
+
cohere: "network",
|
|
3263
|
+
nexus: "network",
|
|
3264
|
+
ipfs: "network",
|
|
3265
|
+
storage: "admin",
|
|
3266
|
+
files: "tools",
|
|
3267
|
+
workspace: "tools",
|
|
3268
|
+
"task-type": "runtime",
|
|
3269
|
+
tasktype: "runtime",
|
|
3270
|
+
sponsor: "network",
|
|
3271
|
+
expose: "gateway",
|
|
3272
|
+
access: "network",
|
|
3273
|
+
host: "network",
|
|
3274
|
+
network: "network",
|
|
3275
|
+
k: "network",
|
|
3276
|
+
scheduler: "runtime",
|
|
3277
|
+
reminder: "runtime",
|
|
3278
|
+
daemon: "runtime",
|
|
3279
|
+
indicator: "ui",
|
|
3280
|
+
apikey: "secret",
|
|
3281
|
+
key: "secret",
|
|
3282
|
+
secrets: "secret",
|
|
3283
|
+
secret: "secret",
|
|
3284
|
+
vault: "secret",
|
|
3285
|
+
codegraph: "tools",
|
|
3286
|
+
cg: "tools",
|
|
3287
|
+
p2p: "network",
|
|
3288
|
+
tools: "tools",
|
|
3289
|
+
skills: "tools",
|
|
3290
|
+
skill: "tools",
|
|
3291
|
+
skillify: "tools",
|
|
3292
|
+
memory: "memory",
|
|
3293
|
+
mem: "memory",
|
|
3294
|
+
metabolize: "memory",
|
|
3295
|
+
prune: "memory",
|
|
3296
|
+
mouse: "ui",
|
|
3297
|
+
color: "ui",
|
|
3298
|
+
colors: "ui",
|
|
3299
|
+
theme: "ui",
|
|
3300
|
+
neovim: "ui",
|
|
3301
|
+
nvim: "ui",
|
|
3302
|
+
vim: "ui",
|
|
3303
|
+
emojis: "ui",
|
|
3304
|
+
emoji: "ui",
|
|
3305
|
+
statusbar: "ui",
|
|
3306
|
+
sb: "ui",
|
|
3307
|
+
skin: "ui",
|
|
3308
|
+
prompt: "ui",
|
|
3309
|
+
personality: "ui",
|
|
3310
|
+
reasoning: "ui",
|
|
3311
|
+
selfmodify: "runtime",
|
|
3312
|
+
selfimprove: "runtime",
|
|
3313
|
+
"self-improve": "runtime",
|
|
3314
|
+
debug: "runtime",
|
|
3315
|
+
selfmod: "runtime",
|
|
3316
|
+
"self-modify": "runtime",
|
|
3317
|
+
stats: "session",
|
|
3318
|
+
metrics: "session"
|
|
3319
|
+
};
|
|
3320
|
+
var ALIASES = {
|
|
3321
|
+
help: ["h", "?"],
|
|
3322
|
+
quit: ["exit"],
|
|
3323
|
+
queue: ["q"],
|
|
3324
|
+
background: ["bg"],
|
|
3325
|
+
clear: ["cls"],
|
|
3326
|
+
verbose: ["v"],
|
|
3327
|
+
config: ["cfg"],
|
|
3328
|
+
color: ["colors", "theme"],
|
|
3329
|
+
setup: ["wizard"],
|
|
3330
|
+
mcp: ["mcps"],
|
|
3331
|
+
update: ["upgrade"],
|
|
3332
|
+
indicator: ["tray"],
|
|
3333
|
+
listen: ["mic"],
|
|
3334
|
+
pointcloud: ["points", "pcl", "point"],
|
|
3335
|
+
neovim: ["nvim"],
|
|
3336
|
+
apikey: ["key"],
|
|
3337
|
+
secrets: ["secret", "vault"],
|
|
3338
|
+
sessions: ["session"],
|
|
3339
|
+
cost: ["costs"],
|
|
3340
|
+
evaluate: ["eval"],
|
|
3341
|
+
score: ["inference"],
|
|
3342
|
+
"task-type": ["tasktype", "tt"],
|
|
3343
|
+
stats: ["dashboard"],
|
|
3344
|
+
memory: ["mem"],
|
|
3345
|
+
metabolize: ["metab"],
|
|
3346
|
+
files: ["workspace"],
|
|
3347
|
+
skills: ["skill"],
|
|
3348
|
+
commands: ["cmds"],
|
|
3349
|
+
selfmodify: ["selfmod", "self-modify"],
|
|
3350
|
+
selfimprove: ["self-improve"],
|
|
3351
|
+
codegraph: ["cg"],
|
|
3352
|
+
endpoint: ["ep"],
|
|
3353
|
+
telegram: ["tg"],
|
|
3354
|
+
bruteforce: ["brute"],
|
|
3355
|
+
deep: ["deep-context"],
|
|
3356
|
+
flow: ["flowstate"],
|
|
3357
|
+
emojis: ["emoji"],
|
|
3358
|
+
compact: ["gc"],
|
|
3359
|
+
network: ["k"],
|
|
3360
|
+
scheduler: [],
|
|
3361
|
+
reminder: ["remind", "reminders"],
|
|
3362
|
+
statusbar: ["sb"],
|
|
3363
|
+
platforms: ["gateway"]
|
|
3364
|
+
};
|
|
3365
|
+
var USER_ONLY = /* @__PURE__ */ new Set([
|
|
3366
|
+
"fallback",
|
|
3367
|
+
"quit",
|
|
3368
|
+
"exit",
|
|
3369
|
+
"clear",
|
|
3370
|
+
"cls",
|
|
3371
|
+
"q",
|
|
3372
|
+
"queue",
|
|
3373
|
+
"model",
|
|
3374
|
+
"endpoint",
|
|
3375
|
+
"parallel",
|
|
3376
|
+
"gpu",
|
|
3377
|
+
"memory",
|
|
3378
|
+
"broker",
|
|
3379
|
+
"commands",
|
|
3380
|
+
"cmds",
|
|
3381
|
+
"selfmodify",
|
|
3382
|
+
"selfmod",
|
|
3383
|
+
"self-modify",
|
|
3384
|
+
"selfimprove",
|
|
3385
|
+
"self-improve",
|
|
3386
|
+
"debug",
|
|
3387
|
+
"dbg",
|
|
3388
|
+
"hf",
|
|
3389
|
+
"models",
|
|
3390
|
+
"mcp",
|
|
3391
|
+
"mcps",
|
|
3392
|
+
"update",
|
|
3393
|
+
"upgrade",
|
|
3394
|
+
"setup",
|
|
3395
|
+
"wizard",
|
|
3396
|
+
"telegram",
|
|
3397
|
+
"call",
|
|
3398
|
+
"hangup",
|
|
3399
|
+
"listen",
|
|
3400
|
+
"mic",
|
|
3401
|
+
"paste",
|
|
3402
|
+
"image",
|
|
3403
|
+
"video",
|
|
3404
|
+
"pointcloud",
|
|
3405
|
+
"points",
|
|
3406
|
+
"pcl",
|
|
3407
|
+
"ingest",
|
|
3408
|
+
"transcribe",
|
|
3409
|
+
"expose",
|
|
3410
|
+
"p2p",
|
|
3411
|
+
"ipfs",
|
|
3412
|
+
"storage",
|
|
3413
|
+
"files",
|
|
3414
|
+
"workspace",
|
|
3415
|
+
"secrets",
|
|
3416
|
+
"secret",
|
|
3417
|
+
"vault",
|
|
3418
|
+
"skillify",
|
|
3419
|
+
"dream",
|
|
3420
|
+
"bless",
|
|
3421
|
+
"full-send-bless",
|
|
3422
|
+
"pause",
|
|
3423
|
+
"stop",
|
|
3424
|
+
"resume",
|
|
3425
|
+
"new",
|
|
3426
|
+
"retry",
|
|
3427
|
+
"undo",
|
|
3428
|
+
"rollback",
|
|
3429
|
+
"background",
|
|
3430
|
+
"bg",
|
|
3431
|
+
"apikey",
|
|
3432
|
+
"key",
|
|
3433
|
+
"access",
|
|
3434
|
+
"host",
|
|
3435
|
+
"network",
|
|
3436
|
+
"k",
|
|
3437
|
+
"scheduler",
|
|
3438
|
+
"cron",
|
|
3439
|
+
"daemon",
|
|
3440
|
+
"indicator",
|
|
3441
|
+
"compacted",
|
|
3442
|
+
"fortemi",
|
|
3443
|
+
"mouse",
|
|
3444
|
+
"approve",
|
|
3445
|
+
"deny",
|
|
3446
|
+
"sethome"
|
|
3447
|
+
]);
|
|
3448
|
+
var DESTRUCTIVE = /* @__PURE__ */ new Set([
|
|
3449
|
+
"destroy",
|
|
3450
|
+
"stop",
|
|
3451
|
+
"rollback",
|
|
3452
|
+
"update",
|
|
3453
|
+
"upgrade",
|
|
3454
|
+
"deny",
|
|
3455
|
+
"daemon",
|
|
3456
|
+
"ollama"
|
|
3457
|
+
]);
|
|
3458
|
+
var NETWORKED = /* @__PURE__ */ new Set([
|
|
3459
|
+
"endpoint",
|
|
3460
|
+
"update",
|
|
3461
|
+
"upgrade",
|
|
3462
|
+
"telegram",
|
|
3463
|
+
"call",
|
|
3464
|
+
"listen",
|
|
3465
|
+
"mic",
|
|
3466
|
+
"image",
|
|
3467
|
+
"video",
|
|
3468
|
+
"pointcloud",
|
|
3469
|
+
"points",
|
|
3470
|
+
"pcl",
|
|
3471
|
+
"cohere",
|
|
3472
|
+
"nexus",
|
|
3473
|
+
"ipfs",
|
|
3474
|
+
"sponsor",
|
|
3475
|
+
"expose",
|
|
3476
|
+
"access",
|
|
3477
|
+
"host",
|
|
3478
|
+
"network",
|
|
3479
|
+
"k",
|
|
3480
|
+
"p2p",
|
|
3481
|
+
"daemon",
|
|
3482
|
+
"fortemi",
|
|
3483
|
+
"mcp",
|
|
3484
|
+
"mcps",
|
|
3485
|
+
"browser",
|
|
3486
|
+
"cron",
|
|
3487
|
+
"reload-mcp",
|
|
3488
|
+
"plugins",
|
|
3489
|
+
"platforms",
|
|
3490
|
+
"gateway"
|
|
3491
|
+
]);
|
|
3492
|
+
var SECRET_BEARING = /* @__PURE__ */ new Set([
|
|
3493
|
+
"endpoint",
|
|
3494
|
+
"apikey",
|
|
3495
|
+
"key",
|
|
3496
|
+
"telegram",
|
|
3497
|
+
"secrets",
|
|
3498
|
+
"secret",
|
|
3499
|
+
"vault",
|
|
3500
|
+
"hf"
|
|
3501
|
+
]);
|
|
3502
|
+
var PROFILE_GATED = /* @__PURE__ */ new Set([
|
|
3503
|
+
"destroy",
|
|
3504
|
+
"update",
|
|
3505
|
+
"upgrade",
|
|
3506
|
+
"telegram",
|
|
3507
|
+
"call",
|
|
3508
|
+
"listen",
|
|
3509
|
+
"mic",
|
|
3510
|
+
"expose",
|
|
3511
|
+
"access",
|
|
3512
|
+
"host",
|
|
3513
|
+
"network",
|
|
3514
|
+
"k",
|
|
3515
|
+
"p2p",
|
|
3516
|
+
"daemon",
|
|
3517
|
+
"fortemi",
|
|
3518
|
+
"mcp",
|
|
3519
|
+
"mcps",
|
|
3520
|
+
"ipfs",
|
|
3521
|
+
"approve",
|
|
3522
|
+
"deny",
|
|
3523
|
+
"sethome"
|
|
3524
|
+
]);
|
|
3525
|
+
var REST_BLOCKED = /* @__PURE__ */ new Set([
|
|
3526
|
+
"pause",
|
|
3527
|
+
"resume",
|
|
3528
|
+
"new",
|
|
3529
|
+
"retry",
|
|
3530
|
+
"undo",
|
|
3531
|
+
"rollback",
|
|
3532
|
+
"background",
|
|
3533
|
+
"bg",
|
|
3534
|
+
"paste",
|
|
3535
|
+
"indicator"
|
|
3536
|
+
]);
|
|
3537
|
+
var LOCAL_TUI_ONLY = /* @__PURE__ */ new Set(["indicator", "compacted", "gpu", "memory"]);
|
|
3538
|
+
var CANONICAL_BY_ALIAS = /* @__PURE__ */ new Map();
|
|
3539
|
+
for (const [canonical, aliases2] of Object.entries(ALIASES)) {
|
|
3540
|
+
for (const alias of aliases2) CANONICAL_BY_ALIAS.set(alias, canonical);
|
|
3541
|
+
}
|
|
3542
|
+
var DYNAMIC_COMMANDS = [];
|
|
3543
|
+
function getSlashHelpEntries(opts = {}) {
|
|
3544
|
+
const includePlanned = opts.includePlanned === true;
|
|
3545
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3546
|
+
const out = [];
|
|
3547
|
+
for (const item of [
|
|
3548
|
+
...DYNAMIC_COMMANDS,
|
|
3549
|
+
...COMMAND_SIGNATURES,
|
|
3550
|
+
...PLANNED_SIGNATURES
|
|
3551
|
+
]) {
|
|
3552
|
+
if (!includePlanned && item.implementationStatus === "planned") continue;
|
|
3553
|
+
if (seen.has(item.signature)) continue;
|
|
3554
|
+
seen.add(item.signature);
|
|
3555
|
+
out.push([item.signature, item.description]);
|
|
3556
|
+
}
|
|
3557
|
+
return out;
|
|
3558
|
+
}
|
|
3559
|
+
var SLASH_COMMANDS = getSlashHelpEntries();
|
|
3560
|
+
function listCommandRegistry(opts = {}) {
|
|
3561
|
+
const includePlanned = opts.includePlanned !== false;
|
|
3562
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
3563
|
+
for (const sig of [
|
|
3564
|
+
...COMMAND_SIGNATURES,
|
|
3565
|
+
...PLANNED_SIGNATURES,
|
|
3566
|
+
...DYNAMIC_COMMANDS
|
|
3567
|
+
]) {
|
|
3568
|
+
if (!includePlanned && sig.implementationStatus === "planned") continue;
|
|
3569
|
+
const name = commandNameFromSignature(sig.signature);
|
|
3570
|
+
if (!name || name.startsWith("<")) continue;
|
|
3571
|
+
if (!grouped.has(name)) grouped.set(name, []);
|
|
3572
|
+
grouped.get(name).push(sig);
|
|
3573
|
+
}
|
|
3574
|
+
return Array.from(grouped.entries()).map(
|
|
3575
|
+
([name, signatures]) => buildCommandDef(name, signatures)
|
|
3576
|
+
);
|
|
3577
|
+
}
|
|
3578
|
+
function findCommand(name) {
|
|
3579
|
+
const normalized = normalizeCommandName(name);
|
|
3580
|
+
const all = listCommandRegistry({ includePlanned: true });
|
|
3581
|
+
return all.find(
|
|
3582
|
+
(cmd) => cmd.name === normalized || cmd.aliases.includes(normalized)
|
|
3583
|
+
);
|
|
3584
|
+
}
|
|
3585
|
+
function buildCommandDef(name, signatures) {
|
|
3586
|
+
const status = signatures.every(
|
|
3587
|
+
(sig) => sig.implementationStatus === "planned"
|
|
3588
|
+
) ? "planned" : "implemented";
|
|
3589
|
+
const safety = {
|
|
3590
|
+
userOnly: USER_ONLY.has(name),
|
|
3591
|
+
destructive: DESTRUCTIVE.has(name),
|
|
3592
|
+
networked: NETWORKED.has(name),
|
|
3593
|
+
secretBearing: SECRET_BEARING.has(name),
|
|
3594
|
+
profileGated: PROFILE_GATED.has(name)
|
|
3595
|
+
};
|
|
3596
|
+
const aliases2 = Array.from(new Set(ALIASES[name] ?? []));
|
|
3597
|
+
const category = CATEGORY_OVERRIDES[name] ?? (status === "planned" ? "planned" : "core");
|
|
3598
|
+
const subcommands = Array.from(
|
|
3599
|
+
new Set(
|
|
3600
|
+
signatures.map((sig) => subcommandFromSignature(sig.signature)).filter((sub) => !!sub)
|
|
3601
|
+
)
|
|
3602
|
+
);
|
|
3603
|
+
const argsHint = inferArgsHint(signatures[0]?.signature ?? `/${name}`);
|
|
3604
|
+
const surfaces = {
|
|
3605
|
+
tui: true,
|
|
3606
|
+
rest: status === "implemented" && !["quit", "exit"].includes(name) && !safety.destructive && !safety.secretBearing && !REST_BLOCKED.has(name) && !LOCAL_TUI_ONLY.has(name),
|
|
3607
|
+
gateway: status === "implemented" && !safety.destructive && !safety.secretBearing && !LOCAL_TUI_ONLY.has(name),
|
|
3608
|
+
agentTool: status === "implemented" && !safety.userOnly && !safety.destructive && !safety.secretBearing && !safety.profileGated && !LOCAL_TUI_ONLY.has(name)
|
|
3609
|
+
};
|
|
3610
|
+
return {
|
|
3611
|
+
name,
|
|
3612
|
+
aliases: aliases2,
|
|
3613
|
+
description: signatures[0]?.description ?? "",
|
|
3614
|
+
category,
|
|
3615
|
+
argsHint,
|
|
3616
|
+
subcommands,
|
|
3617
|
+
signatures,
|
|
3618
|
+
surfaces,
|
|
3619
|
+
safety,
|
|
3620
|
+
implementationStatus: status
|
|
3621
|
+
};
|
|
3622
|
+
}
|
|
3623
|
+
function commandNameFromSignature(signature) {
|
|
3624
|
+
const raw = normalizeCommandName(
|
|
3625
|
+
(signature.trim().split(/\s+/)[0] ?? "").replace(/^\//, "")
|
|
3626
|
+
);
|
|
3627
|
+
return CANONICAL_BY_ALIAS.get(raw) ?? raw;
|
|
3628
|
+
}
|
|
3629
|
+
function subcommandFromSignature(signature) {
|
|
3630
|
+
const parts = signature.trim().split(/\s+/);
|
|
3631
|
+
if (parts.length < 2) return null;
|
|
3632
|
+
const sub = parts[1] ?? "";
|
|
3633
|
+
if (!sub || sub.startsWith("<") || sub.startsWith("[") || sub.includes("|"))
|
|
3634
|
+
return null;
|
|
3635
|
+
return sub.replace(/[|].*$/, "");
|
|
3636
|
+
}
|
|
3637
|
+
function inferArgsHint(signature) {
|
|
3638
|
+
return signature.trim().split(/\s+/).slice(1).join(" ");
|
|
3639
|
+
}
|
|
3640
|
+
function normalizeCommandName(name) {
|
|
3641
|
+
return name.replace(/^\//, "").trim().toLowerCase();
|
|
3642
|
+
}
|
|
3643
|
+
|
|
3644
|
+
// packages/cli/src/tui/native/components/vim-composer.ts
|
|
3645
|
+
var VimComposer = class {
|
|
3646
|
+
constructor(editor, changed) {
|
|
3647
|
+
this.editor = editor;
|
|
3648
|
+
this.changed = changed;
|
|
3649
|
+
}
|
|
3650
|
+
editor;
|
|
3651
|
+
changed;
|
|
3652
|
+
enabled = false;
|
|
3653
|
+
mode = "INSERT";
|
|
3654
|
+
count = "";
|
|
3655
|
+
operator = "";
|
|
3656
|
+
operatorCount = 1;
|
|
3657
|
+
anchor = 0;
|
|
3658
|
+
register = "";
|
|
3659
|
+
linewise = false;
|
|
3660
|
+
find = "";
|
|
3661
|
+
search;
|
|
3662
|
+
lastSearch;
|
|
3663
|
+
setEnabled(enabled) {
|
|
3664
|
+
if (enabled === this.enabled) return;
|
|
3665
|
+
this.enabled = enabled;
|
|
3666
|
+
this.mode = "INSERT";
|
|
3667
|
+
this.reset();
|
|
3668
|
+
this.editor.clearSelection();
|
|
3669
|
+
this.changed();
|
|
3670
|
+
}
|
|
3671
|
+
get label() {
|
|
3672
|
+
return this.search ? `${this.search.backward ? "?" : "/"}${this.search.value}` : this.mode;
|
|
3673
|
+
}
|
|
3674
|
+
reset() {
|
|
3675
|
+
this.count = "";
|
|
3676
|
+
this.operator = "";
|
|
3677
|
+
this.operatorCount = 1;
|
|
3678
|
+
this.find = "";
|
|
3679
|
+
this.search = void 0;
|
|
3680
|
+
}
|
|
3681
|
+
normal() {
|
|
3682
|
+
this.mode = "NORMAL";
|
|
3683
|
+
this.editor.clearSelection();
|
|
3684
|
+
this.reset();
|
|
3685
|
+
this.changed();
|
|
3686
|
+
}
|
|
3687
|
+
end() {
|
|
3688
|
+
return this.editor.editBuffer.measureText(this.editor.plainText);
|
|
3689
|
+
}
|
|
3690
|
+
takeCount() {
|
|
3691
|
+
const n = Math.max(1, Math.min(1e4, Number(this.count) || 1));
|
|
3692
|
+
this.count = "";
|
|
3693
|
+
return n;
|
|
3694
|
+
}
|
|
3695
|
+
select(start, end) {
|
|
3696
|
+
this.editor.setSelection(Math.min(start, end), Math.max(start, end));
|
|
3697
|
+
}
|
|
3698
|
+
operate(start, end, operation, linewise = false) {
|
|
3699
|
+
this.select(start, end);
|
|
3700
|
+
this.register = this.editor.getSelectedText();
|
|
3701
|
+
this.linewise = linewise;
|
|
3702
|
+
if (linewise && this.register && !this.register.endsWith("\n")) this.register += "\n";
|
|
3703
|
+
if (operation !== "y") this.editor.deleteSelection();
|
|
3704
|
+
else {
|
|
3705
|
+
this.editor.clearSelection();
|
|
3706
|
+
this.editor.cursorOffset = Math.min(start, end);
|
|
3707
|
+
}
|
|
3708
|
+
this.reset();
|
|
3709
|
+
this.mode = operation === "c" ? "INSERT" : "NORMAL";
|
|
3710
|
+
this.changed();
|
|
3711
|
+
}
|
|
3712
|
+
lineRange(count) {
|
|
3713
|
+
const row = this.editor.logicalCursor.row;
|
|
3714
|
+
const start = this.editor.editBuffer.getLineStartOffset(row);
|
|
3715
|
+
const next = row + count;
|
|
3716
|
+
let end = next < this.editor.lineCount ? this.editor.editBuffer.getLineStartOffset(next) : this.end();
|
|
3717
|
+
if (end === start && row > 0) return [start - 1, end];
|
|
3718
|
+
return [start, end];
|
|
3719
|
+
}
|
|
3720
|
+
motion(key, count) {
|
|
3721
|
+
const editor = this.editor;
|
|
3722
|
+
if (key === "0") editor.gotoLineHome();
|
|
3723
|
+
else if (key === "$") {
|
|
3724
|
+
if (count > 1) editor.gotoLine(Math.min(editor.lineCount - 1, editor.logicalCursor.row + count - 1));
|
|
3725
|
+
editor.gotoLineEnd();
|
|
3726
|
+
} else if (key === "^") {
|
|
3727
|
+
editor.gotoLineHome();
|
|
3728
|
+
const line = editor.getTextRange(editor.cursorOffset, this.end()).split("\n")[0];
|
|
3729
|
+
for (const char of line) {
|
|
3730
|
+
if (!/\s/.test(char)) break;
|
|
3731
|
+
editor.moveCursorRight();
|
|
3732
|
+
}
|
|
3733
|
+
} else if (key === "G") {
|
|
3734
|
+
editor.gotoLine(count > 1 ? Math.min(editor.lineCount - 1, count - 1) : editor.lineCount - 1);
|
|
3735
|
+
editor.gotoLineHome();
|
|
3736
|
+
} else if (key === "gg") {
|
|
3737
|
+
editor.gotoLine(Math.max(0, count - 1));
|
|
3738
|
+
editor.gotoLineHome();
|
|
3739
|
+
} else if (key === "e") {
|
|
3740
|
+
for (let i = 0; i < count; i++) {
|
|
3741
|
+
const start = editor.cursorOffset;
|
|
3742
|
+
const endWord = () => {
|
|
3743
|
+
editor.moveWordForward();
|
|
3744
|
+
const nextWord2 = editor.cursorOffset;
|
|
3745
|
+
editor.moveCursorLeft();
|
|
3746
|
+
while (editor.cursorOffset > start && /\s/u.test(editor.getTextRange(editor.cursorOffset, nextWord2).slice(0, 1))) editor.moveCursorLeft();
|
|
3747
|
+
return nextWord2;
|
|
3748
|
+
};
|
|
3749
|
+
const nextWord = endWord();
|
|
3750
|
+
if (editor.cursorOffset <= start && nextWord < this.end()) {
|
|
3751
|
+
editor.cursorOffset = nextWord;
|
|
3752
|
+
endWord();
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
} else if (["h", "l", "j", "k", "w", "b", "left", "right", "up", "down"].includes(key)) {
|
|
3756
|
+
for (let i = 0; i < count; i++) {
|
|
3757
|
+
if (key === "h" || key === "left") editor.moveCursorLeft();
|
|
3758
|
+
else if (key === "l" || key === "right") editor.moveCursorRight();
|
|
3759
|
+
else if (key === "j" || key === "down") editor.moveCursorDown();
|
|
3760
|
+
else if (key === "k" || key === "up") editor.moveCursorUp();
|
|
3761
|
+
else if (key === "w") editor.moveWordForward();
|
|
3762
|
+
else editor.moveWordBackward();
|
|
3763
|
+
}
|
|
3764
|
+
} else return false;
|
|
3765
|
+
return true;
|
|
3766
|
+
}
|
|
3767
|
+
searchFor(value, backward) {
|
|
3768
|
+
if (!value) return;
|
|
3769
|
+
const text = this.editor.plainText;
|
|
3770
|
+
const character = this.editor.getTextRange(0, this.editor.cursorOffset).length;
|
|
3771
|
+
const index = backward ? character > 0 ? text.lastIndexOf(value, character - 1) : -1 : text.indexOf(value, character + 1);
|
|
3772
|
+
const found = index >= 0 ? index : backward ? text.lastIndexOf(value) : text.indexOf(value);
|
|
3773
|
+
if (found >= 0) this.editor.cursorOffset = this.editor.editBuffer.measureText(text.slice(0, found));
|
|
3774
|
+
}
|
|
3775
|
+
handle(key) {
|
|
3776
|
+
if (!this.enabled || key.eventType === "release") return false;
|
|
3777
|
+
const consume = () => {
|
|
3778
|
+
key.preventDefault();
|
|
3779
|
+
key.stopPropagation();
|
|
3780
|
+
return true;
|
|
3781
|
+
};
|
|
3782
|
+
if (this.mode === "INSERT") {
|
|
3783
|
+
if (key.name !== "escape") return false;
|
|
3784
|
+
if (this.editor.logicalCursor.col > 0) this.editor.moveCursorLeft();
|
|
3785
|
+
this.normal();
|
|
3786
|
+
return consume();
|
|
3787
|
+
}
|
|
3788
|
+
if (key.name === "escape") {
|
|
3789
|
+
this.normal();
|
|
3790
|
+
return consume();
|
|
3791
|
+
}
|
|
3792
|
+
if (key.ctrl && key.name === "r") {
|
|
3793
|
+
this.editor.redo();
|
|
3794
|
+
return consume();
|
|
3795
|
+
}
|
|
3796
|
+
if (key.ctrl || key.meta || key.name === "return" && !this.search || key.name === "tab") return false;
|
|
3797
|
+
const char = key.sequence.length === 1 ? key.sequence : key.name;
|
|
3798
|
+
if (this.search) {
|
|
3799
|
+
if (key.name === "return") {
|
|
3800
|
+
this.lastSearch = this.search;
|
|
3801
|
+
this.searchFor(this.search.value, this.search.backward);
|
|
3802
|
+
this.search = void 0;
|
|
3803
|
+
} else if (key.name === "backspace") this.search.value = [...this.search.value].slice(0, -1).join("");
|
|
3804
|
+
else if (key.sequence.length === 1) this.search.value += key.sequence;
|
|
3805
|
+
this.changed();
|
|
3806
|
+
return consume();
|
|
3807
|
+
}
|
|
3808
|
+
if (this.find) {
|
|
3809
|
+
if (this.find === "r") {
|
|
3810
|
+
const start2 = this.editor.cursorOffset;
|
|
3811
|
+
this.editor.moveCursorRight();
|
|
3812
|
+
if (this.editor.cursorOffset !== start2) {
|
|
3813
|
+
this.select(start2, this.editor.cursorOffset);
|
|
3814
|
+
this.editor.insertText(char);
|
|
3815
|
+
this.editor.cursorOffset = start2;
|
|
3816
|
+
}
|
|
3817
|
+
this.find = "";
|
|
3818
|
+
return consume();
|
|
3819
|
+
}
|
|
3820
|
+
const forward = this.find === "f" || this.find === "t", till = this.find === "t" || this.find === "T";
|
|
3821
|
+
const start = this.editor.cursorOffset, row = this.editor.logicalCursor.row;
|
|
3822
|
+
for (let i = 0; i < this.editor.plainText.length; i++) {
|
|
3823
|
+
const previous = this.editor.cursorOffset;
|
|
3824
|
+
if (forward) this.editor.moveCursorRight();
|
|
3825
|
+
else this.editor.moveCursorLeft();
|
|
3826
|
+
const current = this.editor.cursorOffset;
|
|
3827
|
+
if (current === previous || this.editor.logicalCursor.row !== row) {
|
|
3828
|
+
this.editor.cursorOffset = start;
|
|
3829
|
+
break;
|
|
3830
|
+
}
|
|
3831
|
+
const end = current;
|
|
3832
|
+
this.editor.moveCursorRight();
|
|
3833
|
+
const next = this.editor.cursorOffset;
|
|
3834
|
+
this.editor.cursorOffset = end;
|
|
3835
|
+
if (this.editor.getTextRange(end, next) === char) {
|
|
3836
|
+
if (till) {
|
|
3837
|
+
if (forward) this.editor.moveCursorLeft();
|
|
3838
|
+
else this.editor.moveCursorRight();
|
|
3839
|
+
}
|
|
3840
|
+
break;
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
this.find = "";
|
|
3844
|
+
this.changed();
|
|
3845
|
+
return consume();
|
|
3846
|
+
}
|
|
3847
|
+
if (/^[1-9]$/.test(char) || char === "0" && this.count) {
|
|
3848
|
+
this.count = (this.count + char).slice(0, 5);
|
|
3849
|
+
return consume();
|
|
3850
|
+
}
|
|
3851
|
+
const count = this.takeCount();
|
|
3852
|
+
if (this.operator === "g") {
|
|
3853
|
+
this.operator = "";
|
|
3854
|
+
if (char === "g") {
|
|
3855
|
+
this.motion("gg", this.operatorCount);
|
|
3856
|
+
return consume();
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
if (this.operator && this.operator !== "g") {
|
|
3860
|
+
const op = this.operator, repeat = count * this.operatorCount, start = this.editor.cursorOffset;
|
|
3861
|
+
if (char === op) {
|
|
3862
|
+
const range = this.lineRange(repeat);
|
|
3863
|
+
this.operate(...range, op, true);
|
|
3864
|
+
return consume();
|
|
3865
|
+
}
|
|
3866
|
+
if (this.motion(char, Math.min(1e4, repeat))) this.operate(start, this.editor.cursorOffset, op);
|
|
3867
|
+
else this.reset();
|
|
3868
|
+
return consume();
|
|
3869
|
+
}
|
|
3870
|
+
if (this.mode === "VISUAL" && ["d", "x", "c", "y"].includes(char)) {
|
|
3871
|
+
const selection = this.editor.getSelection();
|
|
3872
|
+
if (selection) this.operate(selection.start, selection.end, char === "x" ? "d" : char);
|
|
3873
|
+
return consume();
|
|
3874
|
+
}
|
|
3875
|
+
if (this.motion(char, count)) {
|
|
3876
|
+
if (this.mode === "VISUAL") this.select(this.anchor, this.editor.cursorOffset);
|
|
3877
|
+
return consume();
|
|
3878
|
+
}
|
|
3879
|
+
if (char === "g") {
|
|
3880
|
+
this.operator = "g";
|
|
3881
|
+
this.operatorCount = count;
|
|
3882
|
+
return consume();
|
|
3883
|
+
}
|
|
3884
|
+
if (["d", "c", "y"].includes(char)) {
|
|
3885
|
+
this.operator = char;
|
|
3886
|
+
this.operatorCount = count;
|
|
3887
|
+
return consume();
|
|
3888
|
+
}
|
|
3889
|
+
if (char === "i" || char === "a" || char === "I" || char === "A") {
|
|
3890
|
+
if (char === "a" && this.editor.cursorOffset < this.end()) this.editor.moveCursorRight();
|
|
3891
|
+
if (char === "I") this.motion("^", 1);
|
|
3892
|
+
if (char === "A") this.editor.gotoLineEnd();
|
|
3893
|
+
this.mode = "INSERT";
|
|
3894
|
+
this.reset();
|
|
3895
|
+
this.changed();
|
|
3896
|
+
return consume();
|
|
3897
|
+
}
|
|
3898
|
+
if (char === "o" || char === "O") {
|
|
3899
|
+
if (char === "o") {
|
|
3900
|
+
this.editor.gotoLineEnd();
|
|
3901
|
+
this.editor.newLine();
|
|
3902
|
+
} else {
|
|
3903
|
+
this.editor.gotoLineHome();
|
|
3904
|
+
this.editor.insertText("\n");
|
|
3905
|
+
this.editor.moveCursorLeft();
|
|
3906
|
+
}
|
|
3907
|
+
this.mode = "INSERT";
|
|
3908
|
+
this.changed();
|
|
3909
|
+
return consume();
|
|
3910
|
+
}
|
|
3911
|
+
if (char === "v") {
|
|
3912
|
+
if (this.mode === "VISUAL") this.normal();
|
|
3913
|
+
else {
|
|
3914
|
+
this.mode = "VISUAL";
|
|
3915
|
+
this.anchor = this.editor.cursorOffset;
|
|
3916
|
+
this.changed();
|
|
3917
|
+
}
|
|
3918
|
+
return consume();
|
|
3919
|
+
}
|
|
3920
|
+
if (char === "x" || char === "X") {
|
|
3921
|
+
const start = this.editor.cursorOffset;
|
|
3922
|
+
for (let i = 0; i < count; i++) char === "x" ? this.editor.moveCursorRight() : this.editor.moveCursorLeft();
|
|
3923
|
+
this.operate(start, this.editor.cursorOffset, "d");
|
|
3924
|
+
return consume();
|
|
3925
|
+
}
|
|
3926
|
+
if (char === "D" || char === "C") {
|
|
3927
|
+
const start = this.editor.cursorOffset;
|
|
3928
|
+
this.editor.gotoLineEnd();
|
|
3929
|
+
this.operate(start, this.editor.cursorOffset, char === "C" ? "c" : "d");
|
|
3930
|
+
return consume();
|
|
3931
|
+
}
|
|
3932
|
+
if (char === "p" || char === "P") {
|
|
3933
|
+
if (this.register) {
|
|
3934
|
+
if (this.linewise) {
|
|
3935
|
+
if (char === "P") this.editor.gotoLineHome();
|
|
3936
|
+
else {
|
|
3937
|
+
this.editor.gotoLineEnd();
|
|
3938
|
+
if (this.editor.cursorOffset < this.end()) this.editor.moveCursorRight();
|
|
3939
|
+
else this.editor.insertText("\n");
|
|
3940
|
+
}
|
|
3941
|
+
} else if (char === "p") this.editor.moveCursorRight();
|
|
3942
|
+
this.editor.insertText(this.register.repeat(Math.min(1e3, count)));
|
|
3943
|
+
}
|
|
3944
|
+
return consume();
|
|
3945
|
+
}
|
|
3946
|
+
if (char === "u") {
|
|
3947
|
+
for (let i = 0; i < count; i++) this.editor.undo();
|
|
3948
|
+
return consume();
|
|
3949
|
+
}
|
|
3950
|
+
if (["f", "F", "t", "T", "r"].includes(char)) {
|
|
3951
|
+
this.find = char;
|
|
3952
|
+
return consume();
|
|
3953
|
+
}
|
|
3954
|
+
if (char === "/" || char === "?") {
|
|
3955
|
+
this.search = { value: "", backward: char === "?" };
|
|
3956
|
+
this.changed();
|
|
3957
|
+
return consume();
|
|
3958
|
+
}
|
|
3959
|
+
if ((char === "n" || char === "N") && this.lastSearch) {
|
|
3960
|
+
this.searchFor(this.lastSearch.value, this.lastSearch.backward !== (char === "N"));
|
|
3961
|
+
return consume();
|
|
3962
|
+
}
|
|
3963
|
+
return consume();
|
|
3964
|
+
}
|
|
3965
|
+
};
|
|
3966
|
+
|
|
1863
3967
|
// packages/cli/src/tui/native/components/frontend.ts
|
|
1864
3968
|
var initialTheme = { mode: "system", bg: -1, accent: -1, textPrimary: -1, textDim: -1, boxColor: -1 };
|
|
1865
3969
|
var NativeFrontend = class {
|
|
@@ -1870,7 +3974,7 @@ var NativeFrontend = class {
|
|
|
1870
3974
|
this.context = { renderer: renderer2, colors, syntax: SyntaxStyle2.fromStyles({}, renderer2.nativeScene), emit, terminals: /* @__PURE__ */ new Map() };
|
|
1871
3975
|
this.disposeSelectionContrast = installDefaultSelectionContrast(renderer2);
|
|
1872
3976
|
this.clipboard = createClipboard({ host: createHostClipboard({ timeoutMs: 1500 }), terminal: createRendererClipboardAdapter(renderer2) });
|
|
1873
|
-
this.root = new
|
|
3977
|
+
this.root = new BoxRenderable5(renderer2, {
|
|
1874
3978
|
id: "omnius-native",
|
|
1875
3979
|
width: "100%",
|
|
1876
3980
|
height: "100%",
|
|
@@ -1878,7 +3982,7 @@ var NativeFrontend = class {
|
|
|
1878
3982
|
backgroundColor: colors.background
|
|
1879
3983
|
});
|
|
1880
3984
|
renderer2.root.add(this.root);
|
|
1881
|
-
this.header = new
|
|
3985
|
+
this.header = new BoxRenderable5(renderer2, {
|
|
1882
3986
|
id: "omnius-header",
|
|
1883
3987
|
width: "100%",
|
|
1884
3988
|
minWidth: 0,
|
|
@@ -1889,7 +3993,7 @@ var NativeFrontend = class {
|
|
|
1889
3993
|
borderColor: colors.border
|
|
1890
3994
|
});
|
|
1891
3995
|
this.root.add(this.header);
|
|
1892
|
-
const headerRow = new
|
|
3996
|
+
const headerRow = new BoxRenderable5(renderer2, { id: "omnius-header-row", width: "100%", minWidth: 0, minHeight: 1, flexDirection: "row", gap: 1 });
|
|
1893
3997
|
this.header.add(headerRow);
|
|
1894
3998
|
this.identity = new TextRenderable4(renderer2, {
|
|
1895
3999
|
id: "omnius-identity",
|
|
@@ -2006,10 +4110,10 @@ var NativeFrontend = class {
|
|
|
2006
4110
|
buffer.drawText("─".repeat(Math.max(0, tabWidth)), (selected - start) * tabWidth, 1, colors2.foreground, colors2.background, TextAttributes6.DIM);
|
|
2007
4111
|
};
|
|
2008
4112
|
this.root.add(this.tabs);
|
|
2009
|
-
this.taskPane = new
|
|
4113
|
+
this.taskPane = new BoxRenderable5(renderer2, { id: "omnius-tasks", width: "100%", flexDirection: "column", maxHeight: 6, flexShrink: 0, overflow: "hidden", visible: false });
|
|
2010
4114
|
this.tasks = new NativeBlockList(this.context, this.taskPane);
|
|
2011
4115
|
this.root.add(this.taskPane);
|
|
2012
|
-
this.body = new
|
|
4116
|
+
this.body = new BoxRenderable5(renderer2, { id: "omnius-body", width: "100%", flexDirection: "row", flexGrow: 1, minHeight: 1 });
|
|
2013
4117
|
this.root.add(this.body);
|
|
2014
4118
|
this.scroll = new ScrollBoxRenderable4(renderer2, {
|
|
2015
4119
|
id: "omnius-conversation",
|
|
@@ -2047,9 +4151,23 @@ var NativeFrontend = class {
|
|
|
2047
4151
|
});
|
|
2048
4152
|
this.body.add(this.scroll);
|
|
2049
4153
|
this.content = new NativeBlockList(this.context, this.scroll);
|
|
2050
|
-
this.
|
|
4154
|
+
this.instrumentDivider = new InstrumentDivider(renderer2, {
|
|
4155
|
+
resize: (column) => this.resizeInstruments(column),
|
|
4156
|
+
toggle: () => this.toggleDetails(),
|
|
4157
|
+
start: () => {
|
|
4158
|
+
this.sidebarDragWidth = this.sidebarWidth ?? Math.floor(this.renderer.terminalWidth * 0.38);
|
|
4159
|
+
},
|
|
4160
|
+
finish: () => {
|
|
4161
|
+
this.sidebarDragWidth = void 0;
|
|
4162
|
+
}
|
|
4163
|
+
});
|
|
4164
|
+
this.body.add(this.instrumentDivider);
|
|
4165
|
+
this.root.onMouseDrag = (event) => this.instrumentDivider.handleDrag(event);
|
|
4166
|
+
this.root.onMouseDragEnd = (event) => this.instrumentDivider.handleRelease(event);
|
|
4167
|
+
this.root.onMouseUp = (event) => this.instrumentDivider.handleRelease(event);
|
|
4168
|
+
this.instruments = new InstrumentRail(renderer2, { colors, onInspectAgent: (id) => this.emitAction("view", id), onAction: (command2) => this.emitAction(command2) });
|
|
2051
4169
|
this.body.add(this.instruments);
|
|
2052
|
-
this.embeddedPane = new
|
|
4170
|
+
this.embeddedPane = new BoxRenderable5(renderer2, {
|
|
2053
4171
|
id: "omnius-editor-pane",
|
|
2054
4172
|
width: "50%",
|
|
2055
4173
|
flexShrink: 0,
|
|
@@ -2102,9 +4220,9 @@ var NativeFrontend = class {
|
|
|
2102
4220
|
this.suggestions.onActivate = () => this.acceptSuggestion();
|
|
2103
4221
|
this.suggestions.on("itemSelected", () => this.acceptSuggestion());
|
|
2104
4222
|
this.root.add(this.suggestions);
|
|
2105
|
-
this.status = new
|
|
4223
|
+
this.status = new BoxRenderable5(renderer2, { id: "omnius-live-status", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 2, visible: false });
|
|
2106
4224
|
this.root.add(this.status);
|
|
2107
|
-
this.footer = new
|
|
4225
|
+
this.footer = new BoxRenderable5(renderer2, {
|
|
2108
4226
|
id: "omnius-input-box",
|
|
2109
4227
|
width: "100%",
|
|
2110
4228
|
flexShrink: 0,
|
|
@@ -2114,7 +4232,7 @@ var NativeFrontend = class {
|
|
|
2114
4232
|
flexDirection: "column"
|
|
2115
4233
|
});
|
|
2116
4234
|
this.root.add(this.footer);
|
|
2117
|
-
const inputRow = new
|
|
4235
|
+
const inputRow = new BoxRenderable5(renderer2, { id: "omnius-input-row", width: "100%", flexDirection: "row", gap: 1 });
|
|
2118
4236
|
this.footer.add(inputRow);
|
|
2119
4237
|
this.prompt = new TextRenderable4(renderer2, { id: "omnius-prompt", content: "❯", fg: colors.accent, wrapMode: "none", selectable: false, flexShrink: 0 });
|
|
2120
4238
|
inputRow.add(this.prompt);
|
|
@@ -2136,32 +4254,52 @@ var NativeFrontend = class {
|
|
|
2136
4254
|
onCursorChange: () => this.editorChanged(),
|
|
2137
4255
|
onSubmit: () => this.submit()
|
|
2138
4256
|
});
|
|
4257
|
+
this.vimMode = new TextRenderable4(renderer2, {
|
|
4258
|
+
id: "omnius-vim-mode",
|
|
4259
|
+
content: "INSERT",
|
|
4260
|
+
height: 1,
|
|
4261
|
+
maxWidth: 12,
|
|
4262
|
+
flexShrink: 0,
|
|
4263
|
+
fg: colors.foreground,
|
|
4264
|
+
attributes: TextAttributes6.DIM,
|
|
4265
|
+
wrapMode: "none",
|
|
4266
|
+
truncate: true,
|
|
4267
|
+
visible: false,
|
|
4268
|
+
selectable: false
|
|
4269
|
+
});
|
|
4270
|
+
inputRow.add(this.vimMode);
|
|
4271
|
+
this.vimComposer = new VimComposer(this.editor, () => {
|
|
4272
|
+
this.vimMode.visible = this.vimComposer.enabled;
|
|
4273
|
+
this.vimMode.content = this.vimComposer.label;
|
|
4274
|
+
this.editorChanged();
|
|
4275
|
+
this.renderer.requestRender();
|
|
4276
|
+
});
|
|
2139
4277
|
inputRow.add(this.editor);
|
|
2140
|
-
this.enhance = new
|
|
4278
|
+
this.enhance = new BoxRenderable5(renderer2, { id: "omnius-enhance", flexDirection: "row", gap: 1, flexShrink: 0, visible: false });
|
|
2141
4279
|
inputRow.add(this.enhance);
|
|
2142
4280
|
this.activity = new TextRenderable4(renderer2, { id: "omnius-activity", content: "", flexGrow: 1, minWidth: 0, height: 1, wrapMode: "none", truncate: true, visible: false, fg: colors.accent });
|
|
2143
4281
|
this.status.add(this.activity);
|
|
2144
|
-
this.media = new
|
|
4282
|
+
this.media = new BoxRenderable5(renderer2, { id: "omnius-media", height: 1, minWidth: 0, flexShrink: 1, flexDirection: "row", gap: 1, visible: false });
|
|
2145
4283
|
this.mediaText = new TextRenderable4(renderer2, { id: "omnius-media-text", content: "", flexGrow: 1, minWidth: 0, wrapMode: "none", truncate: true, fg: colors.accent });
|
|
2146
4284
|
this.media.add(this.mediaText);
|
|
2147
4285
|
this.micTrack = new TextRenderable4(renderer2, { id: "omnius-mic-meter", width: 12, height: 1, flexShrink: 0, fg: colors.foreground, visible: false });
|
|
2148
4286
|
this.media.add(this.micTrack);
|
|
2149
4287
|
this.status.add(this.media);
|
|
2150
|
-
this.metricsRow = new
|
|
4288
|
+
this.metricsRow = new BoxRenderable5(renderer2, { id: "omnius-metrics-row", width: "100%", height: 1, flexShrink: 0, flexDirection: "row", gap: 1 });
|
|
2151
4289
|
this.keyHints = new TextRenderable4(renderer2, { id: "omnius-key-hints", content: "F1 HELP TAB FOCUS", height: 1, flexShrink: 0, attributes: TextAttributes6.DIM, fg: colors.foreground, selectable: false });
|
|
2152
4290
|
this.metricsRow.add(this.keyHints);
|
|
2153
|
-
this.metricsStartActions = new
|
|
4291
|
+
this.metricsStartActions = new BoxRenderable5(renderer2, { id: "omnius-metrics-start-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
|
|
2154
4292
|
this.metricsRow.add(this.metricsStartActions);
|
|
2155
4293
|
this.metrics = new TextRenderable4(renderer2, { id: "omnius-metrics", content: "", height: 1, wrapMode: "none", truncate: true, fg: colors.dim, flexShrink: 1, flexGrow: 1, minWidth: 0 });
|
|
2156
4294
|
this.metricsRow.add(this.metrics);
|
|
2157
|
-
this.metricsEndActions = new
|
|
4295
|
+
this.metricsEndActions = new BoxRenderable5(renderer2, { id: "omnius-metrics-end-actions", flexDirection: "row", gap: 1, flexShrink: 0 });
|
|
2158
4296
|
this.metricsRow.add(this.metricsEndActions);
|
|
2159
4297
|
this.root.add(this.metricsRow);
|
|
2160
4298
|
this.modals = new NativeModalStack(this.context, () => this.restoreFocus());
|
|
2161
4299
|
renderer2.keyInput.on("keypress", this.onKey);
|
|
2162
4300
|
renderer2.keyInput.on("paste", this.onPaste);
|
|
2163
|
-
renderer2.on(
|
|
2164
|
-
renderer2.on(
|
|
4301
|
+
renderer2.on(CliRenderEvents3.FRAME, this.onFrame);
|
|
4302
|
+
renderer2.on(CliRenderEvents3.RESIZE, this.onResize);
|
|
2165
4303
|
this.applyTheme(initialTheme);
|
|
2166
4304
|
this.editor.focus();
|
|
2167
4305
|
}
|
|
@@ -2170,6 +4308,7 @@ var NativeFrontend = class {
|
|
|
2170
4308
|
root;
|
|
2171
4309
|
scroll;
|
|
2172
4310
|
editor;
|
|
4311
|
+
vimComposer;
|
|
2173
4312
|
content;
|
|
2174
4313
|
modals;
|
|
2175
4314
|
context;
|
|
@@ -2183,6 +4322,7 @@ var NativeFrontend = class {
|
|
|
2183
4322
|
tasks;
|
|
2184
4323
|
body;
|
|
2185
4324
|
instruments;
|
|
4325
|
+
instrumentDivider;
|
|
2186
4326
|
detailButton;
|
|
2187
4327
|
embeddedPane;
|
|
2188
4328
|
liveButton;
|
|
@@ -2190,6 +4330,7 @@ var NativeFrontend = class {
|
|
|
2190
4330
|
suggestions;
|
|
2191
4331
|
footer;
|
|
2192
4332
|
prompt;
|
|
4333
|
+
vimMode;
|
|
2193
4334
|
enhance;
|
|
2194
4335
|
metrics;
|
|
2195
4336
|
keyHints;
|
|
@@ -2219,6 +4360,9 @@ var NativeFrontend = class {
|
|
|
2219
4360
|
disposeSelectionContrast;
|
|
2220
4361
|
actionSignatures = /* @__PURE__ */ new WeakMap();
|
|
2221
4362
|
detailsOpen;
|
|
4363
|
+
narrowDetailsOpen = false;
|
|
4364
|
+
sidebarWidth;
|
|
4365
|
+
sidebarDragWidth;
|
|
2222
4366
|
headerPanelCollapsed = false;
|
|
2223
4367
|
inputEventPending = false;
|
|
2224
4368
|
viewportSignature = "";
|
|
@@ -2366,8 +4510,9 @@ var NativeFrontend = class {
|
|
|
2366
4510
|
renderActivity() {
|
|
2367
4511
|
const activity = this.state?.activity;
|
|
2368
4512
|
const stage = activity?.stage === "idle" ? void 0 : activity?.stage;
|
|
2369
|
-
|
|
2370
|
-
this.activity.
|
|
4513
|
+
const reading = activity?.label || stage || this.state?.instruments?.runtimeStatus || "";
|
|
4514
|
+
this.activity.visible = Boolean(activity?.processing || reading);
|
|
4515
|
+
this.activity.content = `${activity?.processing ? "RUN · " : ""}${reading}`;
|
|
2371
4516
|
this.status.visible = this.activity.visible || this.media.visible;
|
|
2372
4517
|
}
|
|
2373
4518
|
renderMedia() {
|
|
@@ -2397,25 +4542,7 @@ var NativeFrontend = class {
|
|
|
2397
4542
|
this.headerSignature = "";
|
|
2398
4543
|
this.metricsActionsSignature = "";
|
|
2399
4544
|
const colors = this.context.colors = palette(theme);
|
|
2400
|
-
|
|
2401
|
-
default: { fg: colors.foreground },
|
|
2402
|
-
conceal: { fg: colors.foreground },
|
|
2403
|
-
"markup.heading": { fg: colors.accent, bold: true },
|
|
2404
|
-
"markup.strong": { fg: colors.foreground, bold: true },
|
|
2405
|
-
"markup.italic": { fg: colors.foreground, italic: true },
|
|
2406
|
-
"markup.link": { fg: colors.accent, underline: true },
|
|
2407
|
-
"markup.link.url": { fg: colors.dim },
|
|
2408
|
-
"markup.raw": { fg: colors.accent },
|
|
2409
|
-
"markup.list": { fg: colors.accent },
|
|
2410
|
-
"markup.quote": { fg: colors.dim },
|
|
2411
|
-
comment: { fg: colors.dim, italic: true },
|
|
2412
|
-
keyword: { fg: colors.accent, bold: true },
|
|
2413
|
-
string: { fg: colors.success },
|
|
2414
|
-
number: { fg: colors.warning },
|
|
2415
|
-
function: { fg: colors.foreground },
|
|
2416
|
-
type: { fg: colors.accent },
|
|
2417
|
-
punctuation: { fg: colors.dim }
|
|
2418
|
-
})) this.context.syntax.registerStyle(name, style);
|
|
4545
|
+
installNativeSyntax(this.context.syntax, colors);
|
|
2419
4546
|
this.root.backgroundColor = colors.background;
|
|
2420
4547
|
this.header.backgroundColor = this.footer.backgroundColor = colors.background;
|
|
2421
4548
|
this.header.borderColor = this.footer.borderColor = this.embeddedPane.borderColor = colors.border;
|
|
@@ -2423,6 +4550,7 @@ var NativeFrontend = class {
|
|
|
2423
4550
|
this.headerPanel.fg = colors.foreground;
|
|
2424
4551
|
this.routeWarning.fg = colors.warning;
|
|
2425
4552
|
this.prompt.fg = this.activity.fg = this.liveButton.fg = colors.accent;
|
|
4553
|
+
this.vimMode.fg = colors.foreground;
|
|
2426
4554
|
this.micTrack.fg = colors.foreground;
|
|
2427
4555
|
this.queue.fg = this.metrics.fg = colors.dim;
|
|
2428
4556
|
this.editor.backgroundColor = this.editor.focusedBackgroundColor = colors.background;
|
|
@@ -2439,6 +4567,8 @@ var NativeFrontend = class {
|
|
|
2439
4567
|
styleNativeScrollbars(this.headerActions, colors);
|
|
2440
4568
|
styleNativeScrollbars(this.scroll, colors);
|
|
2441
4569
|
this.instruments.applyTheme(colors);
|
|
4570
|
+
this.instrumentDivider.fg = colors.foreground;
|
|
4571
|
+
this.instrumentDivider.bg = colors.background;
|
|
2442
4572
|
this.content.applyTheme();
|
|
2443
4573
|
this.tasks.applyTheme();
|
|
2444
4574
|
this.modals?.applyTheme();
|
|
@@ -2450,23 +4580,47 @@ var NativeFrontend = class {
|
|
|
2450
4580
|
this.update(this.state);
|
|
2451
4581
|
}
|
|
2452
4582
|
toggleDetails() {
|
|
2453
|
-
this.detailsOpen = !(this.detailsOpen ??
|
|
4583
|
+
if (this.renderer.terminalWidth >= 110) this.detailsOpen = !(this.detailsOpen ?? true);
|
|
4584
|
+
else this.narrowDetailsOpen = !this.narrowDetailsOpen;
|
|
4585
|
+
this.layoutInstruments();
|
|
4586
|
+
this.renderer.requestRender();
|
|
4587
|
+
}
|
|
4588
|
+
resizeInstruments(column) {
|
|
4589
|
+
if (this.renderer.terminalWidth < 110 || this.embeddedPane.visible) return;
|
|
4590
|
+
const width = this.renderer.terminalWidth;
|
|
4591
|
+
const requested = Math.max(0, this.body.x + width - Math.round(column) - 1);
|
|
4592
|
+
if (requested <= 4) {
|
|
4593
|
+
this.detailsOpen = false;
|
|
4594
|
+
if (this.sidebarDragWidth !== void 0) this.sidebarWidth = this.sidebarDragWidth;
|
|
4595
|
+
} else {
|
|
4596
|
+
this.detailsOpen = true;
|
|
4597
|
+
this.sidebarWidth = Math.max(24, Math.min(width - 41, requested));
|
|
4598
|
+
}
|
|
2454
4599
|
this.layoutInstruments();
|
|
2455
4600
|
this.renderer.requestRender();
|
|
2456
4601
|
}
|
|
2457
4602
|
layoutInstruments() {
|
|
2458
4603
|
const width = this.renderer.terminalWidth;
|
|
4604
|
+
const focusedBeforeLayout = this.renderer.currentFocusedRenderable;
|
|
2459
4605
|
const wide = width >= 110;
|
|
2460
|
-
const shown = !this.embeddedPane.visible && (this.detailsOpen ??
|
|
2461
|
-
|
|
4606
|
+
const shown = !this.embeddedPane.visible && (wide ? this.detailsOpen ?? true : this.narrowDetailsOpen);
|
|
4607
|
+
const horizontal = wide || this.embeddedPane.visible && width >= 80;
|
|
4608
|
+
this.body.flexDirection = horizontal ? "row" : "column";
|
|
4609
|
+
this.scroll.height = horizontal ? "100%" : "auto";
|
|
4610
|
+
this.scroll.flexBasis = horizontal ? "auto" : 0;
|
|
2462
4611
|
this.instruments.visible = shown;
|
|
2463
|
-
|
|
4612
|
+
this.instrumentDivider.visible = wide && !this.embeddedPane.visible;
|
|
4613
|
+
this.instrumentDivider.setCollapsed(!shown);
|
|
4614
|
+
const railWidth = Math.max(24, Math.min(width - 41, this.sidebarWidth ?? Math.floor(width * 0.38)));
|
|
2464
4615
|
this.instruments.width = wide ? railWidth : "100%";
|
|
2465
|
-
this.scroll.width =
|
|
2466
|
-
|
|
4616
|
+
this.scroll.width = wide && this.instrumentDivider.visible ? width - (shown ? railWidth : 0) - 1 : this.embeddedPane.visible && width >= 80 ? "50%" : "100%";
|
|
4617
|
+
const inspectorHeight = Math.max(4, Math.min(9, Math.floor(this.renderer.terminalHeight / 3)));
|
|
4618
|
+
this.instruments.height = wide ? "100%" : inspectorHeight;
|
|
4619
|
+
this.instruments.maxHeight = wide ? "100%" : inspectorHeight;
|
|
4620
|
+
this.instruments.minHeight = wide ? 1 : inspectorHeight;
|
|
2467
4621
|
this.instruments.flexGrow = 0;
|
|
2468
|
-
this.instruments.flexShrink =
|
|
2469
|
-
this.instruments.border = wide ? [
|
|
4622
|
+
this.instruments.flexShrink = 0;
|
|
4623
|
+
this.instruments.border = wide ? [] : ["top"];
|
|
2470
4624
|
this.instruments.borderStyle = "single";
|
|
2471
4625
|
this.instruments.borderColor = this.context.colors.border;
|
|
2472
4626
|
this.instruments.paddingLeft = wide ? 1 : 0;
|
|
@@ -2484,8 +4638,8 @@ var NativeFrontend = class {
|
|
|
2484
4638
|
this.detailButton.width = detailWidth;
|
|
2485
4639
|
this.keyHints.content = width < 60 ? "F1 HELP" : "F1 HELP TAB FOCUS";
|
|
2486
4640
|
this.detailButton.content = `${shown ? "-" : "+"}${detailWidth > 1 ? " DETAILS" : ""}`;
|
|
2487
|
-
for (let focused =
|
|
2488
|
-
if (!shown && focused === this.instruments || !this.headerActions.visible && focused === this.headerActions) {
|
|
4641
|
+
for (let focused = focusedBeforeLayout; focused; focused = focused.parent) {
|
|
4642
|
+
if (!shown && focused === this.instruments || !this.instrumentDivider.visible && focused === this.instrumentDivider || !this.headerActions.visible && focused === this.headerActions) {
|
|
2489
4643
|
this.restoreFocus();
|
|
2490
4644
|
break;
|
|
2491
4645
|
}
|
|
@@ -2553,8 +4707,11 @@ var NativeFrontend = class {
|
|
|
2553
4707
|
}
|
|
2554
4708
|
submit() {
|
|
2555
4709
|
if (this.paused || this.state?.input.enabled === false) return;
|
|
2556
|
-
if (this.suggestions.visible && this.editor.plainText.startsWith("/") && this.acceptSuggestion()) return;
|
|
2557
4710
|
const text = this.editor.plainText;
|
|
4711
|
+
const command2 = /^\/([^\s]+)/.exec(text.trimStart())?.[1];
|
|
4712
|
+
const suggestion = String(this.suggestions.getSelectedOption()?.value ?? "");
|
|
4713
|
+
if (this.suggestions.visible && command2 && !findCommand(command2) && suggestion.startsWith(text.trimEnd()) && this.acceptSuggestion()) return;
|
|
4714
|
+
this.suggestions.visible = false;
|
|
2558
4715
|
if (text.trim() && this.history[0] !== text) {
|
|
2559
4716
|
this.history.unshift(text);
|
|
2560
4717
|
this.history.length = Math.min(this.history.length, 1e3);
|
|
@@ -2675,6 +4832,7 @@ var NativeFrontend = class {
|
|
|
2675
4832
|
this.shortcut("ctrl-u", key);
|
|
2676
4833
|
return;
|
|
2677
4834
|
}
|
|
4835
|
+
if (this.renderer.currentFocusedRenderable === this.editor && !this.paused && this.state?.input.enabled !== false && this.vimComposer.handle(key)) return;
|
|
2678
4836
|
if (key.name === "escape") {
|
|
2679
4837
|
if (this.renderer.currentFocusedRenderable !== this.editor) {
|
|
2680
4838
|
this.restoreFocus();
|
|
@@ -2816,6 +4974,10 @@ var NativeFrontend = class {
|
|
|
2816
4974
|
case "input-action":
|
|
2817
4975
|
this.inputAction(command2.action, command2.value);
|
|
2818
4976
|
break;
|
|
4977
|
+
case "composer-vim":
|
|
4978
|
+
this.vimComposer.setEnabled(command2.enabled);
|
|
4979
|
+
this.restoreFocus();
|
|
4980
|
+
break;
|
|
2819
4981
|
case "mouse":
|
|
2820
4982
|
this.renderer.useMouse = command2.enabled;
|
|
2821
4983
|
break;
|
|
@@ -2894,6 +5056,7 @@ var NativeFrontend = class {
|
|
|
2894
5056
|
this.embeddedPane.add(terminal);
|
|
2895
5057
|
}
|
|
2896
5058
|
terminal.focus();
|
|
5059
|
+
this.layoutInstruments();
|
|
2897
5060
|
}
|
|
2898
5061
|
closeEmbedded(id) {
|
|
2899
5062
|
this.context.terminals.get(id)?.destroy();
|
|
@@ -2901,6 +5064,7 @@ var NativeFrontend = class {
|
|
|
2901
5064
|
if (this.embeddedId === id) {
|
|
2902
5065
|
this.embeddedId = void 0;
|
|
2903
5066
|
this.embeddedPane.visible = false;
|
|
5067
|
+
this.layoutInstruments();
|
|
2904
5068
|
this.restoreFocus();
|
|
2905
5069
|
}
|
|
2906
5070
|
}
|
|
@@ -2910,8 +5074,8 @@ var NativeFrontend = class {
|
|
|
2910
5074
|
this.disposeSelectionContrast();
|
|
2911
5075
|
this.renderer.keyInput.off("keypress", this.onKey);
|
|
2912
5076
|
this.renderer.keyInput.off("paste", this.onPaste);
|
|
2913
|
-
this.renderer.off(
|
|
2914
|
-
this.renderer.off(
|
|
5077
|
+
this.renderer.off(CliRenderEvents3.FRAME, this.onFrame);
|
|
5078
|
+
this.renderer.off(CliRenderEvents3.RESIZE, this.onResize);
|
|
2915
5079
|
this.modals.destroy();
|
|
2916
5080
|
this.content.destroy();
|
|
2917
5081
|
this.tasks.destroy();
|
|
@@ -2922,7 +5086,7 @@ var NativeFrontend = class {
|
|
|
2922
5086
|
};
|
|
2923
5087
|
|
|
2924
5088
|
// packages/cli/src/tui/native/components/cursor.ts
|
|
2925
|
-
import { CliRenderEvents as
|
|
5089
|
+
import { CliRenderEvents as CliRenderEvents4 } from "@opentui/core";
|
|
2926
5090
|
function installTerminalCursorDefaults(renderer2, session) {
|
|
2927
5091
|
const reset = new TextEncoder().encode("\x1B]112\x07");
|
|
2928
5092
|
let disposed = false;
|
|
@@ -2972,11 +5136,11 @@ function installTerminalCursorDefaults(renderer2, session) {
|
|
|
2972
5136
|
const dispose = () => {
|
|
2973
5137
|
if (disposed) return;
|
|
2974
5138
|
disposed = true;
|
|
2975
|
-
renderer2.off(
|
|
2976
|
-
renderer2.off(
|
|
5139
|
+
renderer2.off(CliRenderEvents4.FRAME, afterFrame);
|
|
5140
|
+
renderer2.off(CliRenderEvents4.DESTROY, dispose);
|
|
2977
5141
|
};
|
|
2978
|
-
renderer2.on(
|
|
2979
|
-
renderer2.once(
|
|
5142
|
+
renderer2.on(CliRenderEvents4.FRAME, afterFrame);
|
|
5143
|
+
renderer2.once(CliRenderEvents4.DESTROY, dispose);
|
|
2980
5144
|
return { restore, dispose };
|
|
2981
5145
|
}
|
|
2982
5146
|
|
|
@@ -3052,10 +5216,10 @@ try {
|
|
|
3052
5216
|
maxFps: 60,
|
|
3053
5217
|
clearOnShutdown: false
|
|
3054
5218
|
});
|
|
3055
|
-
renderer.on(
|
|
5219
|
+
renderer.on(CliRenderEvents5.RENDER_ERROR, (event) => {
|
|
3056
5220
|
void fail(event.error);
|
|
3057
5221
|
});
|
|
3058
|
-
renderer.on(
|
|
5222
|
+
renderer.on(CliRenderEvents5.HANDLER_ERROR, (event) => {
|
|
3059
5223
|
void fail(event.error);
|
|
3060
5224
|
});
|
|
3061
5225
|
renderer.on("error", (event) => {
|