omnius 1.0.267 → 1.0.268
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +311 -246
- package/docs/operations/delay-analysis.md +230 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -557292,7 +557292,7 @@ var init_ollama_pool = __esm({
|
|
|
557292
557292
|
elasticSpawnCap(gpus) {
|
|
557293
557293
|
return this.config.maxSpawnedInstances > 0 ? this.config.maxSpawnedInstances : Math.max(0, gpus.length - 1);
|
|
557294
557294
|
}
|
|
557295
|
-
async getGpusForPlacement(maxAgeMs =
|
|
557295
|
+
async getGpusForPlacement(maxAgeMs = 3e4) {
|
|
557296
557296
|
const now2 = Date.now();
|
|
557297
557297
|
if (this.gpuCache && now2 - this.gpuCache.takenAtMs <= maxAgeMs) {
|
|
557298
557298
|
return this.gpuCache.gpus;
|
|
@@ -557366,7 +557366,12 @@ var init_ollama_pool = __esm({
|
|
|
557366
557366
|
}
|
|
557367
557367
|
const gpuUuid = gpu?.uuid || null;
|
|
557368
557368
|
const gpuIndex = gpu?.index ?? null;
|
|
557369
|
-
const { proc, ready } = await this.spawner({
|
|
557369
|
+
const { proc, ready } = await this.spawner({
|
|
557370
|
+
port,
|
|
557371
|
+
gpuUuid,
|
|
557372
|
+
gpuIndex,
|
|
557373
|
+
config: this.config
|
|
557374
|
+
});
|
|
557370
557375
|
try {
|
|
557371
557376
|
await ready;
|
|
557372
557377
|
} catch (err) {
|
|
@@ -562511,6 +562516,8 @@ var init_streaming_executor = __esm({
|
|
|
562511
562516
|
insertionOrder = [];
|
|
562512
562517
|
config;
|
|
562513
562518
|
executeFn = null;
|
|
562519
|
+
/** Resolver for notification-based wait (delay-1: replaces 1ms spin loop) */
|
|
562520
|
+
_notifyResolve = null;
|
|
562514
562521
|
constructor(config) {
|
|
562515
562522
|
this.config = {
|
|
562516
562523
|
maxConcurrent: config?.maxConcurrent ?? 5,
|
|
@@ -562588,6 +562595,18 @@ var init_streaming_executor = __esm({
|
|
|
562588
562595
|
}
|
|
562589
562596
|
return results;
|
|
562590
562597
|
}
|
|
562598
|
+
/** Signal the notification promise (wake waitAll if sleeping) */
|
|
562599
|
+
_signalChange() {
|
|
562600
|
+
const r2 = this._notifyResolve;
|
|
562601
|
+
this._notifyResolve = null;
|
|
562602
|
+
r2?.();
|
|
562603
|
+
}
|
|
562604
|
+
/** Create a new notification promise for waitAll to await */
|
|
562605
|
+
_waitForChange() {
|
|
562606
|
+
return new Promise((resolve70) => {
|
|
562607
|
+
this._notifyResolve = resolve70;
|
|
562608
|
+
});
|
|
562609
|
+
}
|
|
562591
562610
|
/**
|
|
562592
562611
|
* Wait for all queued/executing tools to complete.
|
|
562593
562612
|
*/
|
|
@@ -562603,7 +562622,7 @@ var init_streaming_executor = __esm({
|
|
|
562603
562622
|
this.processQueue();
|
|
562604
562623
|
} else {
|
|
562605
562624
|
this.processQueue();
|
|
562606
|
-
await
|
|
562625
|
+
await this._waitForChange();
|
|
562607
562626
|
}
|
|
562608
562627
|
}
|
|
562609
562628
|
}
|
|
@@ -562740,6 +562759,7 @@ var init_streaming_executor = __esm({
|
|
|
562740
562759
|
break;
|
|
562741
562760
|
}
|
|
562742
562761
|
}
|
|
562762
|
+
this._signalChange();
|
|
562743
562763
|
}
|
|
562744
562764
|
startExecution(entry) {
|
|
562745
562765
|
entry.state = "executing";
|
|
@@ -563908,7 +563928,11 @@ function captureToolchainVersions() {
|
|
|
563908
563928
|
const out = {};
|
|
563909
563929
|
for (const probe of TOOLCHAIN_PROBES) {
|
|
563910
563930
|
try {
|
|
563911
|
-
const v = execSync47(probe.cmd, {
|
|
563931
|
+
const v = execSync47(probe.cmd, {
|
|
563932
|
+
encoding: "utf8",
|
|
563933
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
563934
|
+
timeout: 500
|
|
563935
|
+
}).trim();
|
|
563912
563936
|
out[probe.name] = v.split(/\r?\n/)[0].slice(0, 200);
|
|
563913
563937
|
} catch {
|
|
563914
563938
|
out[probe.name] = null;
|
|
@@ -563929,7 +563953,10 @@ function freeDiskBytes(path12 = "/tmp") {
|
|
|
563929
563953
|
const st = statSync35(path12);
|
|
563930
563954
|
if (!st.isDirectory())
|
|
563931
563955
|
return -1;
|
|
563932
|
-
const out = execSync47(`df -P -k ${JSON.stringify(path12)} | tail -1`, {
|
|
563956
|
+
const out = execSync47(`df -P -k ${JSON.stringify(path12)} | tail -1`, {
|
|
563957
|
+
encoding: "utf8",
|
|
563958
|
+
timeout: 500
|
|
563959
|
+
});
|
|
563933
563960
|
const cols = out.trim().split(/\s+/);
|
|
563934
563961
|
const availKb = parseInt(cols[3] ?? "0", 10);
|
|
563935
563962
|
if (!Number.isFinite(availKb))
|
|
@@ -581407,21 +581434,30 @@ var init_cascadeBackend = __esm({
|
|
|
581407
581434
|
} catch (err) {
|
|
581408
581435
|
this.consecutiveFailures++;
|
|
581409
581436
|
if (this.isTransientError(err) && this.consecutiveFailures >= this.maxFailures) {
|
|
581410
|
-
const
|
|
581411
|
-
if (
|
|
581437
|
+
const candidates = this.endpoints.filter((_ep, i2) => i2 !== this.activeIndex && _ep.modelAvailable !== false);
|
|
581438
|
+
if (candidates.length > 0) {
|
|
581412
581439
|
const from3 = this.endpoints[this.activeIndex];
|
|
581413
|
-
const to = this.endpoints[nextIdx];
|
|
581414
581440
|
const reason = `${this.consecutiveFailures} consecutive failures: ${err instanceof Error ? err.message : String(err)}`;
|
|
581415
|
-
|
|
581416
|
-
|
|
581417
|
-
|
|
581418
|
-
|
|
581441
|
+
const promises = candidates.map((ep) => {
|
|
581442
|
+
const bk = this.backends.get(ep.url);
|
|
581443
|
+
return bk.chatCompletion(request).then((result) => ({ result, from: ep }));
|
|
581444
|
+
});
|
|
581419
581445
|
try {
|
|
581420
|
-
const result = await
|
|
581446
|
+
const { result, from: from4 } = await Promise.race(promises);
|
|
581447
|
+
const winnerIdx = this.endpoints.indexOf(from4);
|
|
581448
|
+
if (winnerIdx >= 0) {
|
|
581449
|
+
this.activeIndex = winnerIdx;
|
|
581450
|
+
this.onSwitch?.(from4, from4, reason);
|
|
581451
|
+
}
|
|
581452
|
+
this.consecutiveFailures = 0;
|
|
581421
581453
|
return result;
|
|
581422
|
-
} catch
|
|
581423
|
-
this.consecutiveFailures
|
|
581424
|
-
throw
|
|
581454
|
+
} catch {
|
|
581455
|
+
this.consecutiveFailures += candidates.length;
|
|
581456
|
+
throw err;
|
|
581457
|
+
} finally {
|
|
581458
|
+
for (const p2 of promises)
|
|
581459
|
+
p2.catch(() => {
|
|
581460
|
+
});
|
|
581425
581461
|
}
|
|
581426
581462
|
}
|
|
581427
581463
|
}
|
|
@@ -581636,7 +581672,7 @@ function createSteeringIngress(input) {
|
|
|
581636
581672
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
581637
581673
|
};
|
|
581638
581674
|
}
|
|
581639
|
-
async function interpretSteeringIngress(backend, ingress, timeoutMs =
|
|
581675
|
+
async function interpretSteeringIngress(backend, ingress, timeoutMs = 8e3) {
|
|
581640
581676
|
const first2 = await backend.chatCompletion({
|
|
581641
581677
|
messages: [
|
|
581642
581678
|
{
|
|
@@ -594350,6 +594386,175 @@ var init_task_complete_box = __esm({
|
|
|
594350
594386
|
}
|
|
594351
594387
|
});
|
|
594352
594388
|
|
|
594389
|
+
// packages/cli/src/tui/syntax-highlight.ts
|
|
594390
|
+
var syntax_highlight_exports = {};
|
|
594391
|
+
__export(syntax_highlight_exports, {
|
|
594392
|
+
detectLanguage: () => detectLanguage2,
|
|
594393
|
+
getHighlightStatus: () => getHighlightStatus,
|
|
594394
|
+
highlightBlock: () => highlightBlock,
|
|
594395
|
+
highlightCode: () => highlightCode,
|
|
594396
|
+
isAvailable: () => isAvailable,
|
|
594397
|
+
prewarm: () => prewarm
|
|
594398
|
+
});
|
|
594399
|
+
function highlightingDisabled() {
|
|
594400
|
+
return !isTTY2 || noColorEnv || disableEnv;
|
|
594401
|
+
}
|
|
594402
|
+
async function loadHighlighter() {
|
|
594403
|
+
if (_state.attempted) return _state.fn;
|
|
594404
|
+
_state.attempted = true;
|
|
594405
|
+
if (highlightingDisabled()) {
|
|
594406
|
+
_state.reason = !isTTY2 ? "non-tty" : noColorEnv ? "NO_COLOR set" : "OMNIUS_TUI_HIGHLIGHT=0";
|
|
594407
|
+
return null;
|
|
594408
|
+
}
|
|
594409
|
+
try {
|
|
594410
|
+
const { createRequire: createRequire10 } = await import("node:module");
|
|
594411
|
+
const req3 = createRequire10(import.meta.url);
|
|
594412
|
+
let resolved = null;
|
|
594413
|
+
try {
|
|
594414
|
+
resolved = req3.resolve("cli-highlight");
|
|
594415
|
+
} catch {
|
|
594416
|
+
_state.reason = "cli-highlight not installed";
|
|
594417
|
+
return null;
|
|
594418
|
+
}
|
|
594419
|
+
const mod3 = await import(resolved).catch(() => null);
|
|
594420
|
+
if (!mod3) {
|
|
594421
|
+
_state.reason = "cli-highlight failed to load";
|
|
594422
|
+
return null;
|
|
594423
|
+
}
|
|
594424
|
+
const m2 = mod3;
|
|
594425
|
+
const candidate = m2.highlight ?? m2.default ?? null;
|
|
594426
|
+
if (typeof candidate !== "function") {
|
|
594427
|
+
_state.reason = "cli-highlight export shape unrecognized";
|
|
594428
|
+
return null;
|
|
594429
|
+
}
|
|
594430
|
+
_state.fn = candidate;
|
|
594431
|
+
return candidate;
|
|
594432
|
+
} catch (err) {
|
|
594433
|
+
_state.reason = `import threw: ${err?.message ?? String(err)}`;
|
|
594434
|
+
return null;
|
|
594435
|
+
}
|
|
594436
|
+
}
|
|
594437
|
+
function loadHighlighterSync() {
|
|
594438
|
+
if (highlightingDisabled()) return null;
|
|
594439
|
+
return _state.fn;
|
|
594440
|
+
}
|
|
594441
|
+
async function prewarm() {
|
|
594442
|
+
await loadHighlighter();
|
|
594443
|
+
}
|
|
594444
|
+
function isAvailable() {
|
|
594445
|
+
if (highlightingDisabled()) return false;
|
|
594446
|
+
return _state.attempted && _state.fn !== null;
|
|
594447
|
+
}
|
|
594448
|
+
function getHighlightStatus() {
|
|
594449
|
+
return {
|
|
594450
|
+
available: isAvailable(),
|
|
594451
|
+
attempted: _state.attempted,
|
|
594452
|
+
reason: _state.reason,
|
|
594453
|
+
isTTY: isTTY2,
|
|
594454
|
+
noColor: noColorEnv,
|
|
594455
|
+
disabledByEnv: disableEnv
|
|
594456
|
+
};
|
|
594457
|
+
}
|
|
594458
|
+
function highlightCode(code8, language) {
|
|
594459
|
+
if (!code8) return code8;
|
|
594460
|
+
const fn = loadHighlighterSync();
|
|
594461
|
+
if (!fn) return code8;
|
|
594462
|
+
const lang = (language ?? detectLanguage2(code8) ?? "").trim();
|
|
594463
|
+
try {
|
|
594464
|
+
if (lang) {
|
|
594465
|
+
return fn(code8, { language: lang, ignoreIllegals: true });
|
|
594466
|
+
}
|
|
594467
|
+
return fn(code8, { ignoreIllegals: true });
|
|
594468
|
+
} catch {
|
|
594469
|
+
return code8;
|
|
594470
|
+
}
|
|
594471
|
+
}
|
|
594472
|
+
function detectLanguage2(text2) {
|
|
594473
|
+
if (!text2) return null;
|
|
594474
|
+
const trimmed = text2.trimStart();
|
|
594475
|
+
const shebang = trimmed.match(/^#!\s*\/[^\n]+/);
|
|
594476
|
+
if (shebang) {
|
|
594477
|
+
const sb = shebang[0];
|
|
594478
|
+
if (/python/.test(sb)) return "python";
|
|
594479
|
+
if (/(?:^|[\s/])(?:bash|sh|zsh)\b/.test(sb)) return "bash";
|
|
594480
|
+
if (/node/.test(sb)) return "javascript";
|
|
594481
|
+
if (/ruby/.test(sb)) return "ruby";
|
|
594482
|
+
if (/perl/.test(sb)) return "perl";
|
|
594483
|
+
}
|
|
594484
|
+
if (/^[\s\n]*[{[]/.test(trimmed)) {
|
|
594485
|
+
try {
|
|
594486
|
+
JSON.parse(trimmed);
|
|
594487
|
+
return "json";
|
|
594488
|
+
} catch {
|
|
594489
|
+
}
|
|
594490
|
+
}
|
|
594491
|
+
if (/^[-a-zA-Z_][\w-]*:\s/.test(trimmed) && /\n[-a-zA-Z_][\w-]*:\s/.test(trimmed)) {
|
|
594492
|
+
return "yaml";
|
|
594493
|
+
}
|
|
594494
|
+
if (/^(?:async def |def |class |import |from )/.test(trimmed) && /(?::\s*$|->|self\b)/m.test(trimmed)) {
|
|
594495
|
+
return "python";
|
|
594496
|
+
}
|
|
594497
|
+
if (/^(?:import |export |const |let |var |function |class |interface |type |async )/.test(trimmed)) {
|
|
594498
|
+
if (/(:\s*(?:string|number|boolean|any|unknown|void)\b|\binterface\b|\btype\s+\w+\s*=)/.test(trimmed)) {
|
|
594499
|
+
return "typescript";
|
|
594500
|
+
}
|
|
594501
|
+
return "javascript";
|
|
594502
|
+
}
|
|
594503
|
+
if (/(?:^|\n)\s*(?:fn |use |let mut |impl |struct |enum |trait )/.test(trimmed)) {
|
|
594504
|
+
return "rust";
|
|
594505
|
+
}
|
|
594506
|
+
if (/(?:^package \w+|\nfunc \w+\s*\()/.test(trimmed)) {
|
|
594507
|
+
return "go";
|
|
594508
|
+
}
|
|
594509
|
+
if (/^\s*(?:SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\b/i.test(trimmed)) {
|
|
594510
|
+
return "sql";
|
|
594511
|
+
}
|
|
594512
|
+
if (/^[\s\n]*<(?:!DOCTYPE|html|\?xml|\w+)/i.test(trimmed)) {
|
|
594513
|
+
return "html";
|
|
594514
|
+
}
|
|
594515
|
+
if (/^(?:---|\+\+\+|@@|diff )/.test(trimmed)) {
|
|
594516
|
+
return "diff";
|
|
594517
|
+
}
|
|
594518
|
+
if (/^\s*(?:\$\s|sudo |apt |brew |npm |pnpm |yarn |git |docker |kubectl |curl |wget )/.test(trimmed)) {
|
|
594519
|
+
return "bash";
|
|
594520
|
+
}
|
|
594521
|
+
return null;
|
|
594522
|
+
}
|
|
594523
|
+
function highlightBlock(code8, language) {
|
|
594524
|
+
if (!code8) return [""];
|
|
594525
|
+
const fn = loadHighlighterSync();
|
|
594526
|
+
if (!fn) return code8.split("\n");
|
|
594527
|
+
const lang = (language ?? detectLanguage2(code8) ?? "").trim();
|
|
594528
|
+
try {
|
|
594529
|
+
const out = lang ? fn(code8, { language: lang, ignoreIllegals: true }) : fn(code8, { ignoreIllegals: true });
|
|
594530
|
+
const lines = out.split("\n");
|
|
594531
|
+
const inputLines = code8.split("\n");
|
|
594532
|
+
if (lines.length === inputLines.length) return lines;
|
|
594533
|
+
if (lines.length < inputLines.length) {
|
|
594534
|
+
while (lines.length < inputLines.length) lines.push("");
|
|
594535
|
+
} else {
|
|
594536
|
+
lines.length = inputLines.length;
|
|
594537
|
+
}
|
|
594538
|
+
return lines;
|
|
594539
|
+
} catch {
|
|
594540
|
+
return code8.split("\n");
|
|
594541
|
+
}
|
|
594542
|
+
}
|
|
594543
|
+
var isTTY2, noColorEnv, disableEnv, _state;
|
|
594544
|
+
var init_syntax_highlight = __esm({
|
|
594545
|
+
"packages/cli/src/tui/syntax-highlight.ts"() {
|
|
594546
|
+
"use strict";
|
|
594547
|
+
isTTY2 = process.stdout?.isTTY ?? false;
|
|
594548
|
+
noColorEnv = process.env["NO_COLOR"] !== void 0 && process.env["NO_COLOR"] !== "";
|
|
594549
|
+
disableEnv = process.env["OMNIUS_TUI_HIGHLIGHT"] === "0";
|
|
594550
|
+
_state = {
|
|
594551
|
+
attempted: false,
|
|
594552
|
+
fn: null,
|
|
594553
|
+
reason: ""
|
|
594554
|
+
};
|
|
594555
|
+
}
|
|
594556
|
+
});
|
|
594557
|
+
|
|
594353
594558
|
// packages/cli/src/tui/model-picker.ts
|
|
594354
594559
|
import { totalmem as totalmem4 } from "node:os";
|
|
594355
594560
|
function isImageGenModel(name10, family) {
|
|
@@ -596058,10 +596263,29 @@ function diffBodyLines(output, verbose) {
|
|
|
596058
596263
|
for (const line of lines.slice(0, maxLines)) {
|
|
596059
596264
|
const m2 = line.match(DIFF_LINE_RE);
|
|
596060
596265
|
if (m2) {
|
|
596061
|
-
const
|
|
596266
|
+
const marker = m2[1];
|
|
596267
|
+
const codeStart = m2.index + m2[0].length;
|
|
596268
|
+
const prefix = line.slice(0, codeStart);
|
|
596269
|
+
const code8 = line.slice(codeStart);
|
|
596270
|
+
let hlCode = code8;
|
|
596271
|
+
if (isAvailable() && code8.trim()) {
|
|
596272
|
+
const hl = highlightCode(code8);
|
|
596273
|
+
if (hl !== code8) hlCode = hl;
|
|
596274
|
+
}
|
|
596275
|
+
const colorSeq = marker === "+" ? "\x1B[32m" : "\x1B[31m";
|
|
596276
|
+
const resetRe = /\x1B\[0m/g;
|
|
596277
|
+
const adjusted = hlCode.replace(resetRe, `\x1B[0m${colorSeq}`);
|
|
596278
|
+
const colored = `${colorSeq}${prefix}${adjusted}\x1B[0m`;
|
|
596062
596279
|
body.push({ text: colored, mode: "truncate", kind: "plain" });
|
|
596063
596280
|
} else {
|
|
596064
|
-
|
|
596281
|
+
let formatted = line;
|
|
596282
|
+
if (isAvailable() && line.trim()) {
|
|
596283
|
+
const hl = highlightCode(line);
|
|
596284
|
+
formatted = hl !== line ? hl : c3.dim(line);
|
|
596285
|
+
} else {
|
|
596286
|
+
formatted = c3.dim(line);
|
|
596287
|
+
}
|
|
596288
|
+
body.push({ text: formatted, mode: "wrap", kind: "plain" });
|
|
596065
596289
|
}
|
|
596066
596290
|
}
|
|
596067
596291
|
if (lines.length > maxLines) {
|
|
@@ -596081,11 +596305,16 @@ function codePreviewLines(output, maxLines) {
|
|
|
596081
596305
|
const shown = lines.slice(start2, start2 + maxLines);
|
|
596082
596306
|
if (shown.length === 0)
|
|
596083
596307
|
return [{ text: "(empty file)", mode: "wrap", kind: "dim" }];
|
|
596084
|
-
|
|
596085
|
-
|
|
596308
|
+
let hlLines = null;
|
|
596309
|
+
if (isAvailable()) {
|
|
596310
|
+
const codeBlock = shown.join("\n");
|
|
596311
|
+
const hl = highlightBlock(codeBlock);
|
|
596312
|
+
if (hl.length === shown.length) hlLines = hl;
|
|
596313
|
+
}
|
|
596314
|
+
const body = shown.map((line, i2) => ({
|
|
596315
|
+
text: hlLines ? hlLines[i2] ?? line : line,
|
|
596086
596316
|
mode: "truncate",
|
|
596087
596317
|
kind: "plain"
|
|
596088
|
-
// show content in default terminal color, not dim
|
|
596089
596318
|
}));
|
|
596090
596319
|
const remaining = lines.length - start2 - shown.length;
|
|
596091
596320
|
if (remaining > 0) {
|
|
@@ -596580,6 +596809,7 @@ var init_render = __esm({
|
|
|
596580
596809
|
init_config();
|
|
596581
596810
|
init_text_selection();
|
|
596582
596811
|
init_task_complete_box();
|
|
596812
|
+
init_syntax_highlight();
|
|
596583
596813
|
init_model_picker();
|
|
596584
596814
|
init_secret_redactor();
|
|
596585
596815
|
c3 = {
|
|
@@ -610028,10 +610258,10 @@ ${CONTENT_BG_SEQ}`);
|
|
|
610028
610258
|
// packages/cli/src/tui/tui-select.ts
|
|
610029
610259
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
610030
610260
|
function ansi3(code8, text2) {
|
|
610031
|
-
return
|
|
610261
|
+
return isTTY3 ? `\x1B[${code8}m${text2}\x1B[0m` : text2;
|
|
610032
610262
|
}
|
|
610033
610263
|
function fg2563(code8, text2) {
|
|
610034
|
-
return
|
|
610264
|
+
return isTTY3 ? `\x1B[38;5;${code8}m${text2}\x1B[0m` : text2;
|
|
610035
610265
|
}
|
|
610036
610266
|
function stripAnsi3(s2) {
|
|
610037
610267
|
return s2.replace(/\x1B\[[0-9;]*m/g, "");
|
|
@@ -610684,14 +610914,14 @@ ${tuiBgSeq()}`);
|
|
|
610684
610914
|
}
|
|
610685
610915
|
});
|
|
610686
610916
|
}
|
|
610687
|
-
var
|
|
610917
|
+
var isTTY3, MENU_ACTIVE_GREEN_256, selectColors, nonInteractiveSelectSurface;
|
|
610688
610918
|
var init_tui_select = __esm({
|
|
610689
610919
|
"packages/cli/src/tui/tui-select.ts"() {
|
|
610690
610920
|
"use strict";
|
|
610691
610921
|
init_overlay_lock();
|
|
610692
610922
|
init_theme();
|
|
610693
610923
|
init_layout2();
|
|
610694
|
-
|
|
610924
|
+
isTTY3 = process.stdout.isTTY ?? false;
|
|
610695
610925
|
MENU_ACTIVE_GREEN_256 = 154;
|
|
610696
610926
|
selectColors = {
|
|
610697
610927
|
blue: (t2) => fg2563(39, t2),
|
|
@@ -616167,7 +616397,7 @@ var init_format = __esm({
|
|
|
616167
616397
|
import { existsSync as existsSync116 } from "node:fs";
|
|
616168
616398
|
import { extname as extname17, resolve as resolve55 } from "node:path";
|
|
616169
616399
|
function ansi4(code8, text2) {
|
|
616170
|
-
return
|
|
616400
|
+
return isTTY4 ? `\x1B[${code8}m${text2}\x1B[0m` : text2;
|
|
616171
616401
|
}
|
|
616172
616402
|
function stripAnsi4(s2) {
|
|
616173
616403
|
return s2.replace(/\x1B\[[0-9;]*m/g, "");
|
|
@@ -616338,13 +616568,13 @@ function showDropPanel(opts) {
|
|
|
616338
616568
|
render2();
|
|
616339
616569
|
});
|
|
616340
616570
|
}
|
|
616341
|
-
var
|
|
616571
|
+
var isTTY4, dc;
|
|
616342
616572
|
var init_drop_panel = __esm({
|
|
616343
616573
|
"packages/cli/src/tui/drop-panel.ts"() {
|
|
616344
616574
|
"use strict";
|
|
616345
616575
|
init_overlay_lock();
|
|
616346
616576
|
init_layout2();
|
|
616347
|
-
|
|
616577
|
+
isTTY4 = process.stdout.isTTY ?? false;
|
|
616348
616578
|
dc = {
|
|
616349
616579
|
bold: (t2) => ansi4("1", t2),
|
|
616350
616580
|
dim: (t2) => ansi4("38;5;250", t2),
|
|
@@ -618643,17 +618873,17 @@ import { tmpdir as tmpdir20 } from "node:os";
|
|
|
618643
618873
|
import { join as join131 } from "node:path";
|
|
618644
618874
|
import { execSync as execSync54 } from "node:child_process";
|
|
618645
618875
|
function isNeovimActive() {
|
|
618646
|
-
return
|
|
618876
|
+
return _state2 !== null && !_state2.cleanedUp;
|
|
618647
618877
|
}
|
|
618648
618878
|
function isNeovimFocused() {
|
|
618649
|
-
return
|
|
618879
|
+
return _state2?.focused ?? false;
|
|
618650
618880
|
}
|
|
618651
618881
|
function refocusNeovim() {
|
|
618652
|
-
if (!
|
|
618653
|
-
toggleFocus(
|
|
618882
|
+
if (!_state2 || _state2.cleanedUp || _state2.focused) return;
|
|
618883
|
+
toggleFocus(_state2);
|
|
618654
618884
|
}
|
|
618655
618885
|
async function startNeovimMode(opts) {
|
|
618656
|
-
if (
|
|
618886
|
+
if (_state2 && !_state2.cleanedUp) {
|
|
618657
618887
|
return "Neovim mode is already active. Use /neovim to exit first.";
|
|
618658
618888
|
}
|
|
618659
618889
|
let nvimPath;
|
|
@@ -618694,7 +618924,7 @@ async function startNeovimMode(opts) {
|
|
|
618694
618924
|
const ptyCols = opts.cols;
|
|
618695
618925
|
const topOffset = opts.topOffset ?? 0;
|
|
618696
618926
|
const ptyRows = Math.max(5, opts.contentRows);
|
|
618697
|
-
if (
|
|
618927
|
+
if (isTTY5) {
|
|
618698
618928
|
const L = layout();
|
|
618699
618929
|
const bottomBound = L.contentBottom;
|
|
618700
618930
|
process.stdout.write(
|
|
@@ -618743,7 +618973,7 @@ async function startNeovimMode(opts) {
|
|
|
618743
618973
|
installedFilteredListeners: [],
|
|
618744
618974
|
cleanedUp: false
|
|
618745
618975
|
};
|
|
618746
|
-
|
|
618976
|
+
_state2 = state;
|
|
618747
618977
|
const toolbarBtns = [];
|
|
618748
618978
|
{
|
|
618749
618979
|
const btns = [
|
|
@@ -618763,7 +618993,7 @@ async function startNeovimMode(opts) {
|
|
|
618763
618993
|
}
|
|
618764
618994
|
}
|
|
618765
618995
|
function renderToolbar() {
|
|
618766
|
-
if (!
|
|
618996
|
+
if (!isTTY5) return;
|
|
618767
618997
|
const L = layout();
|
|
618768
618998
|
const hdrRow = L.headerContent;
|
|
618769
618999
|
const fg2 = 252;
|
|
@@ -618824,7 +619054,7 @@ async function startNeovimMode(opts) {
|
|
|
618824
619054
|
stdin.setRawMode(true);
|
|
618825
619055
|
}
|
|
618826
619056
|
stdin.resume();
|
|
618827
|
-
if (
|
|
619057
|
+
if (isTTY5) {
|
|
618828
619058
|
process.stdout.write("\x1B[?1002h\x1B[?1006h");
|
|
618829
619059
|
}
|
|
618830
619060
|
state.stdinHandler = (data) => {
|
|
@@ -618891,12 +619121,12 @@ async function startNeovimMode(opts) {
|
|
|
618891
619121
|
return null;
|
|
618892
619122
|
}
|
|
618893
619123
|
function stopNeovimMode() {
|
|
618894
|
-
if (!
|
|
619124
|
+
if (!_state2 || _state2.cleanedUp) return Promise.resolve();
|
|
618895
619125
|
try {
|
|
618896
|
-
|
|
619126
|
+
_state2.pty?.write("\x1B:qa!\r");
|
|
618897
619127
|
} catch {
|
|
618898
619128
|
}
|
|
618899
|
-
const s2 =
|
|
619129
|
+
const s2 = _state2;
|
|
618900
619130
|
return new Promise((resolve70) => {
|
|
618901
619131
|
setTimeout(() => {
|
|
618902
619132
|
if (s2 && !s2.cleanedUp) {
|
|
@@ -618907,18 +619137,18 @@ function stopNeovimMode() {
|
|
|
618907
619137
|
});
|
|
618908
619138
|
}
|
|
618909
619139
|
function writeToNeovimOutput(text2) {
|
|
618910
|
-
if (!
|
|
619140
|
+
if (!_state2 || _state2.cleanedUp || !_state2.nvim || !_state2.outputChanId) return;
|
|
618911
619141
|
const normalized = text2.replace(/(?<!\r)\n/g, "\r\n");
|
|
618912
|
-
|
|
619142
|
+
_state2.nvim.request("nvim_chan_send", [_state2.outputChanId, normalized]).catch(() => {
|
|
618913
619143
|
});
|
|
618914
619144
|
}
|
|
618915
619145
|
async function notifyNeovimFileChange(filePath) {
|
|
618916
|
-
if (!
|
|
619146
|
+
if (!_state2 || _state2.cleanedUp || !_state2.nvim) return;
|
|
618917
619147
|
try {
|
|
618918
|
-
await
|
|
619148
|
+
await _state2.nvim.command("checktime");
|
|
618919
619149
|
if (filePath) {
|
|
618920
619150
|
const escaped = filePath.replace(/'/g, "''");
|
|
618921
|
-
await
|
|
619151
|
+
await _state2.nvim.command(
|
|
618922
619152
|
`if bufexists('${escaped}') | execute 'buffer ' . bufnr('${escaped}') | endif`
|
|
618923
619153
|
);
|
|
618924
619154
|
}
|
|
@@ -618926,10 +619156,10 @@ async function notifyNeovimFileChange(filePath) {
|
|
|
618926
619156
|
}
|
|
618927
619157
|
}
|
|
618928
619158
|
function resizeNeovim(cols, contentRows) {
|
|
618929
|
-
if (!
|
|
619159
|
+
if (!_state2 || _state2.cleanedUp || !_state2.pty) return;
|
|
618930
619160
|
const rows = Math.max(5, contentRows);
|
|
618931
619161
|
try {
|
|
618932
|
-
|
|
619162
|
+
_state2.pty.resize(cols, rows);
|
|
618933
619163
|
} catch {
|
|
618934
619164
|
}
|
|
618935
619165
|
}
|
|
@@ -619104,7 +619334,7 @@ function doCleanup(state) {
|
|
|
619104
619334
|
} catch {
|
|
619105
619335
|
}
|
|
619106
619336
|
}
|
|
619107
|
-
|
|
619337
|
+
_state2 = null;
|
|
619108
619338
|
process.stdout.write(
|
|
619109
619339
|
`\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?1015l\x1B[?1004l\x1B[?2004l\x1B[1;${termRows()}r`
|
|
619110
619340
|
// reset scroll region to full terminal
|
|
@@ -619123,16 +619353,16 @@ function doCleanup(state) {
|
|
|
619123
619353
|
}
|
|
619124
619354
|
state.opts.onExit?.();
|
|
619125
619355
|
}
|
|
619126
|
-
var
|
|
619356
|
+
var isTTY5, PTY_MODE_ENABLE_RE, STDIN_MOUSE_FOCUS_RE, _state2;
|
|
619127
619357
|
var init_neovim_mode = __esm({
|
|
619128
619358
|
"packages/cli/src/tui/neovim-mode.ts"() {
|
|
619129
619359
|
"use strict";
|
|
619130
619360
|
init_setup();
|
|
619131
619361
|
init_layout2();
|
|
619132
|
-
|
|
619362
|
+
isTTY5 = process.stdout.isTTY ?? false;
|
|
619133
619363
|
PTY_MODE_ENABLE_RE = /\x1B\[\?(?:1004|2004)h/g;
|
|
619134
619364
|
STDIN_MOUSE_FOCUS_RE = /\x1B\[<[\d;]+[Mm]|\x1B\[M[\s\S]{3}|\x1B\[[IO]|\x1BO[ABCD]/g;
|
|
619135
|
-
|
|
619365
|
+
_state2 = null;
|
|
619136
619366
|
}
|
|
619137
619367
|
});
|
|
619138
619368
|
|
|
@@ -644066,7 +644296,7 @@ function setCarouselWriter(writer) {
|
|
|
644066
644296
|
chromeWrite2 = writer;
|
|
644067
644297
|
}
|
|
644068
644298
|
function fg(code8, text2) {
|
|
644069
|
-
return
|
|
644299
|
+
return isTTY6 ? `\x1B[38;5;${code8}m${text2}\x1B[0m` : text2;
|
|
644070
644300
|
}
|
|
644071
644301
|
function displayWidth(str) {
|
|
644072
644302
|
let w = 0;
|
|
@@ -644104,12 +644334,12 @@ function createRow(phraseIndices, speed, direction, bank2) {
|
|
|
644104
644334
|
const phrases = phraseIndices.map((i2) => bank2[i2 % bank2.length]);
|
|
644105
644335
|
return { phrases, offset: 0, speed, direction, renderedPlain: "" };
|
|
644106
644336
|
}
|
|
644107
|
-
var
|
|
644337
|
+
var isTTY6, chromeWrite2, PHRASES, Carousel;
|
|
644108
644338
|
var init_carousel = __esm({
|
|
644109
644339
|
"packages/cli/src/tui/carousel.ts"() {
|
|
644110
644340
|
"use strict";
|
|
644111
644341
|
init_layout2();
|
|
644112
|
-
|
|
644342
|
+
isTTY6 = process.stdout.isTTY ?? false;
|
|
644113
644343
|
chromeWrite2 = ((data) => {
|
|
644114
644344
|
process.stdout.write(data);
|
|
644115
644345
|
});
|
|
@@ -644221,7 +644451,7 @@ var init_carousel = __esm({
|
|
|
644221
644451
|
* Sets scroll region to row 5+ for all content/readline.
|
|
644222
644452
|
*/
|
|
644223
644453
|
start() {
|
|
644224
|
-
if (!
|
|
644454
|
+
if (!isTTY6) return 0;
|
|
644225
644455
|
this.started = true;
|
|
644226
644456
|
setHeaderHeight(this.reservedRows);
|
|
644227
644457
|
const L = layout();
|
|
@@ -644253,7 +644483,7 @@ var init_carousel = __esm({
|
|
|
644253
644483
|
* Row 4 is left blank as a separator.
|
|
644254
644484
|
*/
|
|
644255
644485
|
renderFrame() {
|
|
644256
|
-
if (!
|
|
644486
|
+
if (!isTTY6) return;
|
|
644257
644487
|
const L = layout();
|
|
644258
644488
|
let buf = "\x1B7";
|
|
644259
644489
|
buf += "\x1B[?7l";
|
|
@@ -644330,7 +644560,7 @@ var init_carousel = __esm({
|
|
|
644330
644560
|
process.stdout.removeListener("resize", this.resizeHandler);
|
|
644331
644561
|
this.resizeHandler = null;
|
|
644332
644562
|
}
|
|
644333
|
-
if (!
|
|
644563
|
+
if (!isTTY6 || !this.started) return;
|
|
644334
644564
|
const L = layout();
|
|
644335
644565
|
let buf = "\x1B7";
|
|
644336
644566
|
for (let i2 = 0; i2 < this.reservedRows; i2++) {
|
|
@@ -644566,13 +644796,13 @@ function createAnimatedBanner(id, name10, frameBuilders, frameDurationMs, author
|
|
|
644566
644796
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
644567
644797
|
};
|
|
644568
644798
|
}
|
|
644569
|
-
var
|
|
644799
|
+
var isTTY7, chromeWrite3, MNEMONIC_ADJECTIVES, MNEMONIC_NOUNS, BannerRenderer;
|
|
644570
644800
|
var init_banner = __esm({
|
|
644571
644801
|
"packages/cli/src/tui/banner.ts"() {
|
|
644572
644802
|
"use strict";
|
|
644573
644803
|
init_theme();
|
|
644574
644804
|
init_layout2();
|
|
644575
|
-
|
|
644805
|
+
isTTY7 = process.stdout.isTTY ?? false;
|
|
644576
644806
|
chromeWrite3 = ((data) => {
|
|
644577
644807
|
process.stdout.write(data);
|
|
644578
644808
|
});
|
|
@@ -644734,7 +644964,7 @@ var init_banner = __esm({
|
|
|
644734
644964
|
* Returns the number of rows reserved (3 banner + 1 separator = 4).
|
|
644735
644965
|
*/
|
|
644736
644966
|
start() {
|
|
644737
|
-
if (!
|
|
644967
|
+
if (!isTTY7 || !this.currentDesign) return 0;
|
|
644738
644968
|
this.renderCurrentFrame();
|
|
644739
644969
|
this._resizeHandler = () => {
|
|
644740
644970
|
setTermSize(process.stdout.rows ?? 24, process.stdout.columns ?? 80);
|
|
@@ -644775,7 +645005,7 @@ var init_banner = __esm({
|
|
|
644775
645005
|
}
|
|
644776
645006
|
/** Render the current frame into the top 3 rows (public for refresh callbacks) */
|
|
644777
645007
|
renderCurrentFrame() {
|
|
644778
|
-
if (!
|
|
645008
|
+
if (!isTTY7 || !this.currentDesign) return;
|
|
644779
645009
|
const frame = this.currentDesign.frames[this.currentFrame];
|
|
644780
645010
|
if (!frame) return;
|
|
644781
645011
|
this.width = termCols();
|
|
@@ -645179,175 +645409,6 @@ var init_carousel_descriptors = __esm({
|
|
|
645179
645409
|
}
|
|
645180
645410
|
});
|
|
645181
645411
|
|
|
645182
|
-
// packages/cli/src/tui/syntax-highlight.ts
|
|
645183
|
-
var syntax_highlight_exports = {};
|
|
645184
|
-
__export(syntax_highlight_exports, {
|
|
645185
|
-
detectLanguage: () => detectLanguage2,
|
|
645186
|
-
getHighlightStatus: () => getHighlightStatus,
|
|
645187
|
-
highlightBlock: () => highlightBlock,
|
|
645188
|
-
highlightCode: () => highlightCode,
|
|
645189
|
-
isAvailable: () => isAvailable,
|
|
645190
|
-
prewarm: () => prewarm
|
|
645191
|
-
});
|
|
645192
|
-
function highlightingDisabled() {
|
|
645193
|
-
return !isTTY7 || noColorEnv || disableEnv;
|
|
645194
|
-
}
|
|
645195
|
-
async function loadHighlighter() {
|
|
645196
|
-
if (_state2.attempted) return _state2.fn;
|
|
645197
|
-
_state2.attempted = true;
|
|
645198
|
-
if (highlightingDisabled()) {
|
|
645199
|
-
_state2.reason = !isTTY7 ? "non-tty" : noColorEnv ? "NO_COLOR set" : "OMNIUS_TUI_HIGHLIGHT=0";
|
|
645200
|
-
return null;
|
|
645201
|
-
}
|
|
645202
|
-
try {
|
|
645203
|
-
const { createRequire: createRequire10 } = await import("node:module");
|
|
645204
|
-
const req3 = createRequire10(import.meta.url);
|
|
645205
|
-
let resolved = null;
|
|
645206
|
-
try {
|
|
645207
|
-
resolved = req3.resolve("cli-highlight");
|
|
645208
|
-
} catch {
|
|
645209
|
-
_state2.reason = "cli-highlight not installed";
|
|
645210
|
-
return null;
|
|
645211
|
-
}
|
|
645212
|
-
const mod3 = await import(resolved).catch(() => null);
|
|
645213
|
-
if (!mod3) {
|
|
645214
|
-
_state2.reason = "cli-highlight failed to load";
|
|
645215
|
-
return null;
|
|
645216
|
-
}
|
|
645217
|
-
const m2 = mod3;
|
|
645218
|
-
const candidate = m2.highlight ?? m2.default ?? null;
|
|
645219
|
-
if (typeof candidate !== "function") {
|
|
645220
|
-
_state2.reason = "cli-highlight export shape unrecognized";
|
|
645221
|
-
return null;
|
|
645222
|
-
}
|
|
645223
|
-
_state2.fn = candidate;
|
|
645224
|
-
return candidate;
|
|
645225
|
-
} catch (err) {
|
|
645226
|
-
_state2.reason = `import threw: ${err?.message ?? String(err)}`;
|
|
645227
|
-
return null;
|
|
645228
|
-
}
|
|
645229
|
-
}
|
|
645230
|
-
function loadHighlighterSync() {
|
|
645231
|
-
if (highlightingDisabled()) return null;
|
|
645232
|
-
return _state2.fn;
|
|
645233
|
-
}
|
|
645234
|
-
async function prewarm() {
|
|
645235
|
-
await loadHighlighter();
|
|
645236
|
-
}
|
|
645237
|
-
function isAvailable() {
|
|
645238
|
-
if (highlightingDisabled()) return false;
|
|
645239
|
-
return _state2.attempted && _state2.fn !== null;
|
|
645240
|
-
}
|
|
645241
|
-
function getHighlightStatus() {
|
|
645242
|
-
return {
|
|
645243
|
-
available: isAvailable(),
|
|
645244
|
-
attempted: _state2.attempted,
|
|
645245
|
-
reason: _state2.reason,
|
|
645246
|
-
isTTY: isTTY7,
|
|
645247
|
-
noColor: noColorEnv,
|
|
645248
|
-
disabledByEnv: disableEnv
|
|
645249
|
-
};
|
|
645250
|
-
}
|
|
645251
|
-
function highlightCode(code8, language) {
|
|
645252
|
-
if (!code8) return code8;
|
|
645253
|
-
const fn = loadHighlighterSync();
|
|
645254
|
-
if (!fn) return code8;
|
|
645255
|
-
const lang = (language ?? detectLanguage2(code8) ?? "").trim();
|
|
645256
|
-
try {
|
|
645257
|
-
if (lang) {
|
|
645258
|
-
return fn(code8, { language: lang, ignoreIllegals: true });
|
|
645259
|
-
}
|
|
645260
|
-
return fn(code8, { ignoreIllegals: true });
|
|
645261
|
-
} catch {
|
|
645262
|
-
return code8;
|
|
645263
|
-
}
|
|
645264
|
-
}
|
|
645265
|
-
function detectLanguage2(text2) {
|
|
645266
|
-
if (!text2) return null;
|
|
645267
|
-
const trimmed = text2.trimStart();
|
|
645268
|
-
const shebang = trimmed.match(/^#!\s*\/[^\n]+/);
|
|
645269
|
-
if (shebang) {
|
|
645270
|
-
const sb = shebang[0];
|
|
645271
|
-
if (/python/.test(sb)) return "python";
|
|
645272
|
-
if (/(?:^|[\s/])(?:bash|sh|zsh)\b/.test(sb)) return "bash";
|
|
645273
|
-
if (/node/.test(sb)) return "javascript";
|
|
645274
|
-
if (/ruby/.test(sb)) return "ruby";
|
|
645275
|
-
if (/perl/.test(sb)) return "perl";
|
|
645276
|
-
}
|
|
645277
|
-
if (/^[\s\n]*[{[]/.test(trimmed)) {
|
|
645278
|
-
try {
|
|
645279
|
-
JSON.parse(trimmed);
|
|
645280
|
-
return "json";
|
|
645281
|
-
} catch {
|
|
645282
|
-
}
|
|
645283
|
-
}
|
|
645284
|
-
if (/^[-a-zA-Z_][\w-]*:\s/.test(trimmed) && /\n[-a-zA-Z_][\w-]*:\s/.test(trimmed)) {
|
|
645285
|
-
return "yaml";
|
|
645286
|
-
}
|
|
645287
|
-
if (/^(?:async def |def |class |import |from )/.test(trimmed) && /(?::\s*$|->|self\b)/m.test(trimmed)) {
|
|
645288
|
-
return "python";
|
|
645289
|
-
}
|
|
645290
|
-
if (/^(?:import |export |const |let |var |function |class |interface |type |async )/.test(trimmed)) {
|
|
645291
|
-
if (/(:\s*(?:string|number|boolean|any|unknown|void)\b|\binterface\b|\btype\s+\w+\s*=)/.test(trimmed)) {
|
|
645292
|
-
return "typescript";
|
|
645293
|
-
}
|
|
645294
|
-
return "javascript";
|
|
645295
|
-
}
|
|
645296
|
-
if (/(?:^|\n)\s*(?:fn |use |let mut |impl |struct |enum |trait )/.test(trimmed)) {
|
|
645297
|
-
return "rust";
|
|
645298
|
-
}
|
|
645299
|
-
if (/(?:^package \w+|\nfunc \w+\s*\()/.test(trimmed)) {
|
|
645300
|
-
return "go";
|
|
645301
|
-
}
|
|
645302
|
-
if (/^\s*(?:SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\b/i.test(trimmed)) {
|
|
645303
|
-
return "sql";
|
|
645304
|
-
}
|
|
645305
|
-
if (/^[\s\n]*<(?:!DOCTYPE|html|\?xml|\w+)/i.test(trimmed)) {
|
|
645306
|
-
return "html";
|
|
645307
|
-
}
|
|
645308
|
-
if (/^(?:---|\+\+\+|@@|diff )/.test(trimmed)) {
|
|
645309
|
-
return "diff";
|
|
645310
|
-
}
|
|
645311
|
-
if (/^\s*(?:\$\s|sudo |apt |brew |npm |pnpm |yarn |git |docker |kubectl |curl |wget )/.test(trimmed)) {
|
|
645312
|
-
return "bash";
|
|
645313
|
-
}
|
|
645314
|
-
return null;
|
|
645315
|
-
}
|
|
645316
|
-
function highlightBlock(code8, language) {
|
|
645317
|
-
if (!code8) return [""];
|
|
645318
|
-
const fn = loadHighlighterSync();
|
|
645319
|
-
if (!fn) return code8.split("\n");
|
|
645320
|
-
const lang = (language ?? detectLanguage2(code8) ?? "").trim();
|
|
645321
|
-
try {
|
|
645322
|
-
const out = lang ? fn(code8, { language: lang, ignoreIllegals: true }) : fn(code8, { ignoreIllegals: true });
|
|
645323
|
-
const lines = out.split("\n");
|
|
645324
|
-
const inputLines = code8.split("\n");
|
|
645325
|
-
if (lines.length === inputLines.length) return lines;
|
|
645326
|
-
if (lines.length < inputLines.length) {
|
|
645327
|
-
while (lines.length < inputLines.length) lines.push("");
|
|
645328
|
-
} else {
|
|
645329
|
-
lines.length = inputLines.length;
|
|
645330
|
-
}
|
|
645331
|
-
return lines;
|
|
645332
|
-
} catch {
|
|
645333
|
-
return code8.split("\n");
|
|
645334
|
-
}
|
|
645335
|
-
}
|
|
645336
|
-
var isTTY7, noColorEnv, disableEnv, _state2;
|
|
645337
|
-
var init_syntax_highlight = __esm({
|
|
645338
|
-
"packages/cli/src/tui/syntax-highlight.ts"() {
|
|
645339
|
-
"use strict";
|
|
645340
|
-
isTTY7 = process.stdout?.isTTY ?? false;
|
|
645341
|
-
noColorEnv = process.env["NO_COLOR"] !== void 0 && process.env["NO_COLOR"] !== "";
|
|
645342
|
-
disableEnv = process.env["OMNIUS_TUI_HIGHLIGHT"] === "0";
|
|
645343
|
-
_state2 = {
|
|
645344
|
-
attempted: false,
|
|
645345
|
-
fn: null,
|
|
645346
|
-
reason: ""
|
|
645347
|
-
};
|
|
645348
|
-
}
|
|
645349
|
-
});
|
|
645350
|
-
|
|
645351
645412
|
// packages/cli/src/tui/stream-renderer.ts
|
|
645352
645413
|
function fg2564(code8, text2) {
|
|
645353
645414
|
return isTTY8 ? `\x1B[38;5;${code8}m${text2}\x1B[0m` : text2;
|
|
@@ -704325,28 +704386,32 @@ ${entry.fullContent}`
|
|
|
704325
704386
|
}
|
|
704326
704387
|
if (lm.intervention) {
|
|
704327
704388
|
contentWrite(() => {
|
|
704328
|
-
|
|
704329
|
-
if (lm.details && showAdversary) {
|
|
704330
|
-
const det = String(lm.details);
|
|
704331
|
-
lines.push(...det.split("\n").filter(Boolean));
|
|
704332
|
-
}
|
|
704333
|
-
renderBoxedBlock({
|
|
704334
|
-
title: "Adversary",
|
|
704335
|
-
lines,
|
|
704336
|
-
kind: "plain"
|
|
704337
|
-
});
|
|
704389
|
+
renderWarning(`Adversary: ${lm.intervention}`);
|
|
704338
704390
|
});
|
|
704339
704391
|
} else if (lm.details && showAdversary) {
|
|
704340
704392
|
contentWrite(() => {
|
|
704341
|
-
|
|
704342
|
-
|
|
704343
|
-
|
|
704344
|
-
kind: "dim"
|
|
704345
|
-
});
|
|
704393
|
+
renderInfo(
|
|
704394
|
+
`Adversary details: ${String(lm.details).split("\n").filter(Boolean).join(" | ")}`
|
|
704395
|
+
);
|
|
704346
704396
|
});
|
|
704347
704397
|
}
|
|
704348
704398
|
}
|
|
704349
704399
|
break;
|
|
704400
|
+
case "adversary_reaction":
|
|
704401
|
+
if (event.adversary) {
|
|
704402
|
+
const adv = event.adversary;
|
|
704403
|
+
const conf = adv.confidence != null ? ` (${Math.round(adv.confidence * 100)}%)` : "";
|
|
704404
|
+
const text2 = adv.shortText + conf;
|
|
704405
|
+
contentWrite(() => {
|
|
704406
|
+
renderWarning(`Adversary ${adv.class}: ${text2}`);
|
|
704407
|
+
});
|
|
704408
|
+
if (adv.details) {
|
|
704409
|
+
adversaryBuffer.push(adv.details);
|
|
704410
|
+
if (adversaryBuffer.length > 50)
|
|
704411
|
+
adversaryBuffer.splice(0, adversaryBuffer.length - 50);
|
|
704412
|
+
}
|
|
704413
|
+
}
|
|
704414
|
+
break;
|
|
704350
704415
|
}
|
|
704351
704416
|
});
|
|
704352
704417
|
try {
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Unnecessary Causes of Delays Between Agent Actions
|
|
2
|
+
|
|
3
|
+
Analysis of `packages/orchestrator/src/` (95 files) — identified delay sources ranked by impact.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## HIGH IMPACT
|
|
8
|
+
|
|
9
|
+
### 1. `streaming-executor.ts:171-192` — `waitAll()` busy-poll loop
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
async waitAll(): Promise<void> {
|
|
13
|
+
while (true) {
|
|
14
|
+
const pending = Array.from(this.tools.values()).filter(
|
|
15
|
+
e => e.state === "queued" || e.state === "executing"
|
|
16
|
+
);
|
|
17
|
+
if (pending.length === 0) break;
|
|
18
|
+
const executing = pending.filter(e => e.promise);
|
|
19
|
+
if (executing.length > 0) {
|
|
20
|
+
await Promise.allSettled(executing.map(e => e.promise!));
|
|
21
|
+
this.processQueue();
|
|
22
|
+
} else {
|
|
23
|
+
this.processQueue();
|
|
24
|
+
await new Promise(r => setTimeout(r, 1)); // ← 1ms spin loop
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Problem:** When tools are queued but none have started (no `promise`), the loop spins with 1ms `setTimeout` between `processQueue()` calls. Each iteration costs at least 1ms of wall-clock delay. With many queued-but-blocked tools, this adds up.
|
|
31
|
+
|
|
32
|
+
**Fix:** Replace with Promise-based notification (event emitter or `AbortController`-based wait) so the loop yields until a tool completes or a new tool is enqueued.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### 2. `ollama-pool.ts:850-869` — Instance readiness probe loop
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
await new Promise((r) => setTimeout(r, 500)); // ← 500ms between probes
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Problem:** When spawning a new Ollama instance, the code polls `/api/version` every **500ms** with a 2-second abort timeout. This adds **500-2000ms** of delay per new model instance. If the pool is empty and a model isn't loaded, every first request pays this cost.
|
|
43
|
+
|
|
44
|
+
**Fix:** Use exponential backoff (100ms → 200ms → 400ms) or a readiness event emitter instead of fixed polling.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### 3. `cascadeBackend.ts:105-156` — Sequential fallback chain
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const result = await backend.chatCompletion(request);
|
|
52
|
+
// On failure → try newBackend.chatCompletion(request);
|
|
53
|
+
// On failure → try primaryBackend.chatCompletion({ timeoutMs: 10_000 });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Problem:** The cascade backend tries multiple backends in sequence. Each failure triggers a retry on the next backend. If the first backend is slow to fail (not crash), the full timeout (10s+) is paid before the fallback activates.
|
|
57
|
+
|
|
58
|
+
**Fix:** Start all backends simultaneously with `Promise.race()` and cancel losers on first success.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## MEDIUM IMPACT
|
|
63
|
+
|
|
64
|
+
### 4. `ollama-pool.ts:1190` — Unbounded slot waiter queue
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
await new Promise<void>((resolve) => this.slotWaiters.push(resolve));
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Problem:** When all GPU slots are occupied, new requests queue as promises in `slotWaiters`. They only resolve when a slot frees up — but there's no timeout or progress feedback. Under heavy load, this can stall indefinitely.
|
|
71
|
+
|
|
72
|
+
**Fix:** Add a configurable timeout (e.g., 30s) and reject with a clear "no GPU available" error.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### 5. `ollama-pool.ts:1336` — GPU detection on every acquire
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const rawGpus = await this.gpuDetector();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Problem:** GPU detection runs on every placement decision. If `gpuDetector()` calls `nvidia-smi` or similar system commands, this adds **10-100ms** per request.
|
|
83
|
+
|
|
84
|
+
**Fix:** Cache GPU detection results with a TTL (e.g., 30s). GPU topology rarely changes at runtime.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### 6. `tool-batching.ts:247-253` — Forced serial execution of non-concurrent tools
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
for (const call of batch.calls) {
|
|
92
|
+
results.push(await executeFn(call));
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Problem:** Write/shell tools are forced to run serially. If the agent produces 3+ write tools in one turn, they queue sequentially. No parallelism for independent writes.
|
|
97
|
+
|
|
98
|
+
**Fix:** Add a write-conflict analyzer (e.g., file-level locking) to allow parallel writes to different files.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
### 7. `steeringIntake.ts:97` — 15s steering timeout
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
timeoutMs = 15_000,
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Problem:** Steering intake has a 15-second timeout. If the model is slow or the prompt is large, this adds a full 15s delay before the steering response arrives.
|
|
109
|
+
|
|
110
|
+
**Fix:** Reduce to 5-8s for steering (which is advisory, not critical) or make it non-blocking with a best-effort result.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 8. `verifierRunner.ts:161` — 60s test timeout
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
timeout: 60_000,
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Problem:** Test execution has a 60-second timeout. If tests hang or are slow, this blocks the entire agent loop.
|
|
121
|
+
|
|
122
|
+
**Fix:** Add a per-test timeout and a total timeout with early termination on repeated failures.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## LOW-MEDIUM IMPACT
|
|
127
|
+
|
|
128
|
+
### 9. `ollama-pool.ts:1236,1257` — VRAM estimation per model
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const vramNeededMB = await this.estimateModelVramMB(model);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Problem:** VRAM estimation runs before every spawn/placement. If it involves model metadata lookups or API calls, this adds latency.
|
|
135
|
+
|
|
136
|
+
**Fix:** Cache VRAM estimates keyed by model name with a TTL.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
### 10. `streaming-executor.ts:21-26` — `stableValueKey` deep serialization
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
function stableValueKey(value: unknown): string {
|
|
144
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
145
|
+
if (Array.isArray(value)) return `[${value.map(stableValueKey).join(",")}]`;
|
|
146
|
+
const record = value as Record<string, unknown>;
|
|
147
|
+
return `{${Object.keys(record).sort().map((key) => ...).join(",")}}`;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Problem:** Deep serialization of tool arguments for deduplication. For large args (e.g., file contents), this adds O(n) serialization cost per tool call.
|
|
152
|
+
|
|
153
|
+
**Fix:** Add a size cap (e.g., 10KB) — if the value exceeds it, use a hash instead of deep serialization.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### 11. `streaming-executor.ts:263-291` — Duplicate detection overhead
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
private findPriorEquivalent(entry: StreamingToolEntry): StreamingToolEntry | null
|
|
161
|
+
private cloneDuplicateResult(entry: StreamingToolEntry): boolean
|
|
162
|
+
private mirrorPriorEquivalent(entry: StreamingToolEntry): boolean
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Problem:** Every tool call is checked against all prior calls for equivalence. This is O(n²) in the number of tools per turn.
|
|
166
|
+
|
|
167
|
+
**Fix:** Use a hash-based index (tool name + arg hash) for O(1) lookup instead of linear scan.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### 12. `ollama-pool.ts:1697` — Stale process cleanup timer
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const handle = setTimeout(async () => {
|
|
175
|
+
const { cleanupStaleOllamaProcesses } = await import("./ollama-pool-cleanup.js");
|
|
176
|
+
const report = await cleanupStaleOllamaProcesses({ ... });
|
|
177
|
+
}, ...);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Problem:** Cleanup runs as a deferred `setTimeout` — adds latency before stale processes are actually cleaned up.
|
|
181
|
+
|
|
182
|
+
**Fix:** Run cleanup eagerly when a slot is freed, not on a timer.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### 13. `ollama-pool.ts:298,304` — `execSync` with 3s timeout
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
{ encoding: "utf8", timeout: 3_000 },
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Problem:** Synchronous child processes block the event loop. If the command takes the full 3s, the entire process stalls.
|
|
193
|
+
|
|
194
|
+
**Fix:** Use `execFile` with `Promise` wrapper or `spawn` with timeout signal.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### 14. `preflightSnapshot.ts:284,311` — Multiple 1.5s probe timeouts
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
timeout: 1500
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Problem:** Preflight checks run multiple probes, each with 1.5s timeout. If multiple probes fail, this adds 3-6s of startup delay.
|
|
205
|
+
|
|
206
|
+
**Fix:** Run probes in parallel with `Promise.allSettled()` and use the first success.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### 15. `tool-batching.ts:212-240` — Concurrency limit on reads
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
export async function withConcurrencyLimit<T>(...) {
|
|
214
|
+
// Uses a limiter to cap parallel reads
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Problem:** Concurrent-safe tools (reads) are limited by a concurrency cap. If the limit is too low, parallel reads are serialized unnecessarily.
|
|
219
|
+
|
|
220
|
+
**Fix:** Make the concurrency limit configurable and increase the default (e.g., from 2 to 8).
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Summary: Top 3 Fixes for Immediate Impact
|
|
225
|
+
|
|
226
|
+
| Priority | File | Change | Expected Savings |
|
|
227
|
+
|----------|------|--------|------------------|
|
|
228
|
+
| 1 | `streaming-executor.ts` | Replace 1ms spin loop with Promise notification | Eliminates busy-poll latency entirely |
|
|
229
|
+
| 2 | `ollama-pool.ts` | Cache GPU detection with 30s TTL | Eliminates 10-100ms per request |
|
|
230
|
+
| 3 | `cascadeBackend.ts` | Parallelize backend fallbacks with `Promise.race()` | Eliminates cascading timeout accumulation |
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.268",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.268",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED