omnius 1.0.120 → 1.0.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -553442,14 +553442,29 @@ ${description}`
553442
553442
  poolSlot.release(success);
553443
553443
  poolSlot = null;
553444
553444
  };
553445
+ const streamTimeoutMs = Number.isFinite(request.timeoutMs) && request.timeoutMs > 0 ? Math.max(request.timeoutMs, 1e4) : 3e5;
553446
+ const streamAbort = new AbortController();
553447
+ const streamTimeoutHandle = setTimeout(() => {
553448
+ streamAbort.abort(new Error(`stream timeout: no response or chunk within ${(streamTimeoutMs / 1e3).toFixed(0)}s`));
553449
+ }, streamTimeoutMs);
553450
+ if (typeof streamTimeoutHandle.unref === "function") {
553451
+ streamTimeoutHandle.unref();
553452
+ }
553453
+ const externalAbortListener = this._abortSignal ? () => streamAbort.abort(this._abortSignal?.reason ?? new Error("external abort")) : null;
553454
+ if (this._abortSignal && externalAbortListener) {
553455
+ if (this._abortSignal.aborted) {
553456
+ externalAbortListener();
553457
+ } else {
553458
+ this._abortSignal.addEventListener("abort", externalAbortListener, { once: true });
553459
+ }
553460
+ }
553445
553461
  try {
553446
553462
  const streamFetchOpts = {
553447
553463
  method: "POST",
553448
553464
  headers: this.authHeaders(),
553449
- body: JSON.stringify(body)
553465
+ body: JSON.stringify(body),
553466
+ signal: streamAbort.signal
553450
553467
  };
553451
- if (this._abortSignal)
553452
- streamFetchOpts.signal = this._abortSignal;
553453
553468
  let resp = await fetch(`${requestBaseUrl}/v1/chat/completions`, streamFetchOpts);
553454
553469
  if (!resp.ok) {
553455
553470
  const text = await resp.text().catch(() => "");
@@ -553548,6 +553563,13 @@ ${description}`
553548
553563
  this._finalizeStreamGuard(effectiveThink, accumulatedContent, accumulatedThinking, sawReasoningTokens);
553549
553564
  poolSuccess = true;
553550
553565
  } finally {
553566
+ clearTimeout(streamTimeoutHandle);
553567
+ if (this._abortSignal && externalAbortListener) {
553568
+ try {
553569
+ this._abortSignal.removeEventListener("abort", externalAbortListener);
553570
+ } catch {
553571
+ }
553572
+ }
553551
553573
  releasePoolSlot(poolSuccess);
553552
553574
  }
553553
553575
  }
@@ -558131,7 +558153,7 @@ function ensureVenvForTranscribeCli() {
558131
558153
  }
558132
558154
  }
558133
558155
  function ensureTranscribeCliBackground() {
558134
- if (_bgInstallPromise) return;
558156
+ if (_bgInstallPromise) return _bgInstallPromise;
558135
558157
  _bgInstallPromise = (async () => {
558136
558158
  try {
558137
558159
  const globalRoot = execSync46("npm root -g", {
@@ -558155,6 +558177,7 @@ function ensureTranscribeCliBackground() {
558155
558177
  return false;
558156
558178
  }
558157
558179
  })();
558180
+ return _bgInstallPromise;
558158
558181
  }
558159
558182
  async function waitForTranscribeCli() {
558160
558183
  if (_bgInstallPromise) {
@@ -579896,6 +579919,158 @@ function ensurePythonVenv() {
579896
579919
  }
579897
579920
  process.stdout.write(` ${c3.cyan("⚠")} Could not install python3-venv. Install manually: sudo apt install python3-venv
579898
579921
 
579922
+ `);
579923
+ }
579924
+ async function pretuiSudoPasswordCallback(rl) {
579925
+ process.stdout.write(` ${c3.dim("Some dependencies need administrator access to install system packages.")}
579926
+ `);
579927
+ const pw2 = await askSecret(rl, ` ${c3.bold("sudo password")} ${c3.dim("(empty to skip this dep)")}: `);
579928
+ if (!pw2) {
579929
+ process.stdout.write(` ${c3.dim("Skipped — install can be re-attempted later via /vision-status or by re-running omnius setup.")}
579930
+
579931
+ `);
579932
+ return null;
579933
+ }
579934
+ return pw2;
579935
+ }
579936
+ async function runOptionalDepsSetup(rl) {
579937
+ const canPrompt = process.stdout.isTTY && process.stdin.isTTY && process.env["CI"] !== "true" && process.env["OMNIUS_SETUP_AUTO_CONTINUE"] !== "1";
579938
+ if (!canPrompt) {
579939
+ process.stdout.write(` ${c3.dim("Non-interactive mode — skipping optional dependency prompts.")}
579940
+
579941
+ `);
579942
+ return;
579943
+ }
579944
+ const logTo = (label) => (msg) => {
579945
+ process.stdout.write(` ${c3.dim(`[${label}]`)} ${msg}
579946
+ `);
579947
+ };
579948
+ process.stdout.write(` ${c3.bold("Optional dependencies")}
579949
+ `);
579950
+ process.stdout.write(` ${c3.dim("These add features (vision/OCR, voice tunnel, live transcription). You can install them now or later via the in-TUI commands.")}
579951
+
579952
+ `);
579953
+ const askVision = await ask(rl, ` ${c3.bold("Install vision / OCR deps?")} (Y/n) `);
579954
+ if (askVision.toLowerCase() !== "n") {
579955
+ process.stdout.write(` ${c3.cyan("●")} Installing vision + OCR deps...
579956
+ `);
579957
+ try {
579958
+ await ensureVisionDeps(
579959
+ logTo("vision"),
579960
+ () => pretuiSudoPasswordCallback(rl)
579961
+ );
579962
+ process.stdout.write(` ${c3.green("✔")} Vision deps complete.
579963
+
579964
+ `);
579965
+ } catch (err) {
579966
+ process.stdout.write(` ${c3.cyan("⚠")} Vision deps install hit an error: ${err instanceof Error ? err.message : String(err)}
579967
+ `);
579968
+ process.stdout.write(` ${c3.dim("Continuing — vision features may be limited.")}
579969
+
579970
+ `);
579971
+ }
579972
+ } else {
579973
+ process.stdout.write(` ${c3.dim("Skipped vision deps.")}
579974
+
579975
+ `);
579976
+ }
579977
+ const askCloudflared = await ask(rl, ` ${c3.bold("Install cloudflared for voice tunnel?")} (Y/n) `);
579978
+ if (askCloudflared.toLowerCase() !== "n") {
579979
+ process.stdout.write(` ${c3.cyan("●")} Installing cloudflared...
579980
+ `);
579981
+ const ok3 = await ensureCloudflaredBackground((msg) => {
579982
+ process.stdout.write(` ${c3.dim("[cloudflared]")} ${msg}
579983
+ `);
579984
+ });
579985
+ if (ok3) {
579986
+ process.stdout.write(` ${c3.green("✔")} Cloudflared ready.
579987
+
579988
+ `);
579989
+ } else {
579990
+ process.stdout.write(` ${c3.cyan("⚠")} Cloudflared install did not complete — voice tunnel will be unavailable.
579991
+
579992
+ `);
579993
+ }
579994
+ } else {
579995
+ process.stdout.write(` ${c3.dim("Skipped cloudflared.")}
579996
+
579997
+ `);
579998
+ }
579999
+ const askTranscribe = await ask(rl, ` ${c3.bold("Install transcribe-cli for live transcription?")} (Y/n) `);
580000
+ if (askTranscribe.toLowerCase() !== "n") {
580001
+ process.stdout.write(` ${c3.cyan("●")} Installing transcribe-cli (npm i -g transcribe-cli)...
580002
+ `);
580003
+ try {
580004
+ const ok3 = await ensureTranscribeCliBackground();
580005
+ if (ok3) {
580006
+ process.stdout.write(` ${c3.green("✔")} Transcribe-CLI installed.
580007
+
580008
+ `);
580009
+ } else {
580010
+ process.stdout.write(` ${c3.cyan("⚠")} transcribe-cli install did not complete — live transcription will be unavailable.
580011
+
580012
+ `);
580013
+ }
580014
+ } catch (err) {
580015
+ process.stdout.write(` ${c3.cyan("⚠")} transcribe-cli install hit an error: ${err instanceof Error ? err.message : String(err)}
580016
+
580017
+ `);
580018
+ }
580019
+ } else {
580020
+ process.stdout.write(` ${c3.dim("Skipped transcribe-cli.")}
580021
+
580022
+ `);
580023
+ }
580024
+ }
580025
+ function writeSetupIncompleteWalkthrough(cc) {
580026
+ process.stdout.write(`
580027
+ ${cc.bold("Setup incomplete — no model configured.")}
580028
+ `);
580029
+ process.stdout.write(` ${cc.dim("Nothing was saved. The primary TUI was NOT started so you can finish setup on your terms.")}
580030
+
580031
+ `);
580032
+ process.stdout.write(` ${cc.bold("To finish setup, pick one of:")}
580033
+
580034
+ `);
580035
+ process.stdout.write(` ${cc.cyan("1.")} ${cc.bold("Use a local Ollama model")}
580036
+ `);
580037
+ process.stdout.write(` ${cc.dim("# install / start Ollama")}
580038
+ `);
580039
+ process.stdout.write(` curl -fsSL https://ollama.com/install.sh | sh
580040
+ `);
580041
+ process.stdout.write(` ollama serve &
580042
+ `);
580043
+ process.stdout.write(` ${cc.dim("# pull a tool-capable model (any of these works)")}
580044
+ `);
580045
+ process.stdout.write(` ollama pull qwen3.6:35b ${cc.dim("# recommended on a 32GB+ VRAM rig")}
580046
+ `);
580047
+ process.stdout.write(` ollama pull qwen3.5:9b ${cc.dim("# smaller fallback")}
580048
+ `);
580049
+ process.stdout.write(` ${cc.dim("# then re-run setup")}
580050
+ `);
580051
+ process.stdout.write(` omnius
580052
+
580053
+ `);
580054
+ process.stdout.write(` ${cc.cyan("2.")} ${cc.bold("Use a remote OpenAI-compatible endpoint")}
580055
+ `);
580056
+ process.stdout.write(` omnius config set backendUrl https://api.example.com/v1
580057
+ `);
580058
+ process.stdout.write(` omnius config set model your-model-name
580059
+ `);
580060
+ process.stdout.write(` omnius config set apiKey sk-...
580061
+ `);
580062
+ process.stdout.write(` omnius config set backendType vllm
580063
+ `);
580064
+ process.stdout.write(` omnius
580065
+
580066
+ `);
580067
+ process.stdout.write(` ${cc.cyan("3.")} ${cc.bold("Open the setup wizard again")}
580068
+ `);
580069
+ process.stdout.write(` omnius setup ${cc.dim("# explicit re-entry")}
580070
+
580071
+ `);
580072
+ process.stdout.write(` ${cc.dim("Docs: ")}${cc.bold("https://github.com/<repo>/blob/main/README.md")}${cc.dim(' — "Quickstart"')}
580073
+
579899
580074
  `);
579900
580075
  }
579901
580076
  async function runSetupWizard(config) {
@@ -580108,6 +580283,13 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580108
580283
  }
580109
580284
  process.stdout.write(hLine("└"));
580110
580285
  process.stdout.write("\n");
580286
+ const canPause = process.stdout.isTTY && process.stdin.isTTY && process.env["CI"] !== "true" && process.env["OMNIUS_SETUP_AUTO_CONTINUE"] !== "1";
580287
+ if (canPause) {
580288
+ process.stdout.write(` ${c3.dim("Review the capability summary above. ")}${c3.bold("Press Enter to continue")}${c3.dim(", or Ctrl+C to exit.")}
580289
+ `);
580290
+ await ask(rl, " > ");
580291
+ process.stdout.write("\n");
580292
+ }
580111
580293
  let hasPython = hasCmd("python3") || hasCmd("python");
580112
580294
  if (!hasPython) {
580113
580295
  process.stdout.write(` ${c3.cyan("⚠")} Python3 not found (needed for vision, OCR, browser automation).
@@ -580223,6 +580405,21 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580223
580405
  process.stdout.write(` ${c3.cyan("⚠")} Default model ${c3.bold(config.model)} is not available.
580224
580406
 
580225
580407
  `);
580408
+ if (canPause) {
580409
+ process.stdout.write(` ${c3.bold("Next step:")} ${c3.dim("choose a model.")}
580410
+ `);
580411
+ process.stdout.write(` ${c3.dim("[Enter] open model picker / [s] skip + configure later / [c] custom endpoint")}
580412
+ `);
580413
+ const next = (await ask(rl, " > ")).trim().toLowerCase();
580414
+ if (next === "s" || next === "skip") {
580415
+ writeSetupIncompleteWalkthrough(c3);
580416
+ process.exit(0);
580417
+ }
580418
+ if (next === "c" || next === "custom") {
580419
+ const endpointResult = await promptForCustomEndpoint(config, rl);
580420
+ if (endpointResult) return endpointResult;
580421
+ }
580422
+ }
580226
580423
  if (models.length > 0) {
580227
580424
  const backendUrl2 = config.backendUrl || "http://localhost:11434";
580228
580425
  const modelChecks = await Promise.all(
@@ -580249,8 +580446,13 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580249
580446
  ${c3.green("✔")} Selected ${c3.bold(selected.name)} — ${mode}. Saved to config.
580250
580447
 
580251
580448
  `);
580449
+ await runOptionalDepsSetup(rl);
580252
580450
  return selected.name;
580253
580451
  }
580452
+ if (!modelResult.confirmed) {
580453
+ writeSetupIncompleteWalkthrough(c3);
580454
+ process.exit(0);
580455
+ }
580254
580456
  } else {
580255
580457
  process.stdout.write(` ${c3.cyan("⚠")} No models found on this system.
580256
580458
 
@@ -580274,11 +580476,8 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580274
580476
  });
580275
580477
  let selectedVariant;
580276
580478
  if (!pullResult.confirmed || !pullResult.key) {
580277
- process.stdout.write(`
580278
- ${c3.dim("Skipping model pull. You can pull manually with: ollama pull <model>")}
580279
-
580280
- `);
580281
- return config.model;
580479
+ writeSetupIncompleteWalkthrough(c3);
580480
+ process.exit(0);
580282
580481
  }
580283
580482
  selectedVariant = QWEN_VARIANTS.find((v) => v.tag === pullResult.key) ?? recommended;
580284
580483
  process.stdout.write(`
@@ -580332,6 +580531,7 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580332
580531
  process.stdout.write(` ${c3.green("✔")} Saved as default model in config.
580333
580532
 
580334
580533
  `);
580534
+ await runOptionalDepsSetup(rl);
580335
580535
  return customName;
580336
580536
  } catch (err) {
580337
580537
  renderWarning(`Could not create custom model: ${err instanceof Error ? err.message : String(err)}`);
@@ -580343,6 +580543,7 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580343
580543
  ${c3.green("✔")} Saved ${c3.bold(selectedVariant.tag)} as default model.
580344
580544
 
580345
580545
  `);
580546
+ await runOptionalDepsSetup(rl);
580346
580547
  return selectedVariant.tag;
580347
580548
  }
580348
580549
  setConfigValue("model", selectedVariant.tag);
@@ -580350,6 +580551,7 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
580350
580551
  ${c3.green("✔")} Saved ${c3.bold(selectedVariant.tag)} as default model.
580351
580552
 
580352
580553
  `);
580554
+ await runOptionalDepsSetup(rl);
580353
580555
  return selectedVariant.tag;
580354
580556
  }
580355
580557
  async function isModelAvailable(config) {
@@ -580802,10 +581004,10 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
580802
581004
  }
580803
581005
  }
580804
581006
  function ensureCloudflaredBackground(onInfo) {
580805
- if (_cloudflaredInstallPromise) return;
581007
+ if (_cloudflaredInstallPromise) return _cloudflaredInstallPromise;
580806
581008
  if (hasCmd("cloudflared")) {
580807
581009
  _cloudflaredInstallPromise = Promise.resolve(true);
580808
- return;
581010
+ return _cloudflaredInstallPromise;
580809
581011
  }
580810
581012
  const log22 = onInfo ?? (() => {
580811
581013
  });
@@ -580858,6 +581060,7 @@ function ensureCloudflaredBackground(onInfo) {
580858
581060
  log22("cloudflared not available — live voice sessions disabled.");
580859
581061
  return false;
580860
581062
  })();
581063
+ return _cloudflaredInstallPromise;
580861
581064
  }
580862
581065
  async function isCloudflaredReady() {
580863
581066
  if (hasCmd("cloudflared")) return true;
@@ -581367,6 +581570,7 @@ var init_setup = __esm({
581367
581570
  init_config();
581368
581571
  init_dist();
581369
581572
  init_tui_select();
581573
+ init_listen();
581370
581574
  execAsync2 = promisify6(exec4);
581371
581575
  OMNIUS_FIRST_RUN_BANNER = [
581372
581576
  " ░▒▓██████▓▒░░▒▓██████████████▓▒░░▒▓███████▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓███████▓▒░ ",
@@ -603033,13 +603237,13 @@ async function handleUpdate(subcommand, ctx3) {
603033
603237
  }
603034
603238
  if (!hasCf) {
603035
603239
  installOverlay.setStatus("Installing cloudflared...");
603036
- ensureCloudflaredBackground(() => {
603240
+ void ensureCloudflaredBackground(() => {
603037
603241
  });
603038
603242
  await new Promise((r2) => setTimeout(r2, 1e3));
603039
603243
  } else {
603040
603244
  installOverlay.setStatus("cloudflared ready");
603041
603245
  }
603042
- ensureTranscribeCliBackground();
603246
+ void ensureTranscribeCliBackground();
603043
603247
  }
603044
603248
  if (!primaryUpdated) {
603045
603249
  installOverlay.stop("Done — no restart needed");
@@ -619882,24 +620086,57 @@ ${lines.join("\n")}`);
619882
620086
  `inference ${inferenceId} [${entry.kind}] ${elapsed}s content=${entry.contentTokens}t thinking=${entry.thinkingTokens}t (${thinkRatio}% think) live=${JSON.stringify(preview)}`
619883
620087
  ));
619884
620088
  };
619885
- for await (const chunk of streamFn(request)) {
619886
- if (chunk.type === "content" && chunk.content) {
619887
- if (chunk.thinking) {
619888
- thinkingBuf += chunk.content;
619889
- this.bumpTelegramInferenceTokens(inferenceId, 0, 1);
619890
- } else {
619891
- contentBuf += chunk.content;
619892
- this.bumpTelegramInferenceTokens(inferenceId, 1, 0);
619893
- }
619894
- flushPreview(false);
619895
- } else if (chunk.type === "finish") {
619896
- finishReason = chunk.finishReason;
619897
- } else if (chunk.type === "usage") {
619898
- usage = {
619899
- prompt_tokens: chunk.promptTokens,
619900
- completion_tokens: chunk.completionTokens,
619901
- total_tokens: chunk.totalTokens
619902
- };
620089
+ const inactivityMs = this.telegramStreamInactivityMs();
620090
+ const iter = streamFn(request)[Symbol.asyncIterator]();
620091
+ try {
620092
+ while (true) {
620093
+ let timeoutHandle = null;
620094
+ const inactivityPromise = new Promise((_, reject) => {
620095
+ timeoutHandle = setTimeout(
620096
+ () => reject(new Error(
620097
+ `stream-inactivity: no chunks for ${(inactivityMs / 1e3).toFixed(0)}s (content=${contentBuf.length}c thinking=${thinkingBuf.length}c so far) — Ollama likely cold-loading the model or wedged; falling back to non-stream`
620098
+ )),
620099
+ inactivityMs
620100
+ );
620101
+ if (typeof timeoutHandle.unref === "function") {
620102
+ timeoutHandle.unref();
620103
+ }
620104
+ });
620105
+ let next;
620106
+ try {
620107
+ next = await Promise.race([iter.next(), inactivityPromise]);
620108
+ } finally {
620109
+ if (timeoutHandle) clearTimeout(timeoutHandle);
620110
+ }
620111
+ if (next.done) break;
620112
+ const chunk = next.value;
620113
+ if (chunk.type === "content" && chunk.content) {
620114
+ const entry = this.telegramActiveInferences.get(inferenceId);
620115
+ if (entry && entry.firstChunkAt === void 0) {
620116
+ entry.firstChunkAt = performance.now();
620117
+ }
620118
+ if (chunk.thinking) {
620119
+ thinkingBuf += chunk.content;
620120
+ this.bumpTelegramInferenceTokens(inferenceId, 0, 1);
620121
+ } else {
620122
+ contentBuf += chunk.content;
620123
+ this.bumpTelegramInferenceTokens(inferenceId, 1, 0);
620124
+ }
620125
+ flushPreview(false);
620126
+ } else if (chunk.type === "finish") {
620127
+ finishReason = chunk.finishReason;
620128
+ } else if (chunk.type === "usage") {
620129
+ usage = {
620130
+ prompt_tokens: chunk.promptTokens,
620131
+ completion_tokens: chunk.completionTokens,
620132
+ total_tokens: chunk.totalTokens
620133
+ };
620134
+ }
620135
+ }
620136
+ } finally {
620137
+ try {
620138
+ await iter.return?.(void 0);
620139
+ } catch {
619903
620140
  }
619904
620141
  }
619905
620142
  flushPreview(true);
@@ -619970,9 +620207,10 @@ ${lines.join("\n")}`);
619970
620207
  const dur = ((performance.now() - entry.startTs) / 1e3).toFixed(1);
619971
620208
  const totalTokens = entry.contentTokens + entry.thinkingTokens;
619972
620209
  const ratio = totalTokens > 0 ? Math.round(entry.thinkingTokens * 100 / totalTokens) : 0;
620210
+ const ttfb = entry.firstChunkAt !== void 0 ? `${((entry.firstChunkAt - entry.startTs) / 1e3).toFixed(1)}s` : "never";
619973
620211
  this.tuiWrite(() => renderTelegramSubAgentEvent(
619974
620212
  entry.sessionKey,
619975
- `inference ${id} [${entry.kind}] done in ${dur}s — ${entry.contentTokens}t content / ${entry.thinkingTokens}t thinking (${ratio}% think)`
620213
+ `inference ${id} [${entry.kind}] done in ${dur}s (ttfb=${ttfb}) — ${entry.contentTokens}t content / ${entry.thinkingTokens}t thinking (${ratio}% think)`
619976
620214
  ));
619977
620215
  }
619978
620216
  }
@@ -619988,7 +620226,10 @@ ${lines.join("\n")}`);
619988
620226
  return Array.from(this.telegramActiveInferences.values()).map((e2) => ({
619989
620227
  ...e2,
619990
620228
  elapsedSec: (now - e2.startTs) / 1e3,
619991
- idleSec: (now - e2.lastTokenAt) / 1e3
620229
+ idleSec: (now - e2.lastTokenAt) / 1e3,
620230
+ // Undefined when no chunk has arrived yet (still cold-loading or wedged).
620231
+ // A dashboard renderer should display "—" or "waiting" in that case.
620232
+ ttfbSec: e2.firstChunkAt !== void 0 ? (e2.firstChunkAt - e2.startTs) / 1e3 : void 0
619992
620233
  }));
619993
620234
  }
619994
620235
  /**
@@ -620260,6 +620501,25 @@ ${retryText}`,
620260
620501
  telegramSubAgentWatchdogIntervalMs() {
620261
620502
  return 3e4;
620262
620503
  }
620504
+ /**
620505
+ * Per-chunk inactivity window for the bridge's stream consumer. If no
620506
+ * chunk arrives within this window, the streaming consumer in
620507
+ * streamTelegramInferenceToCompletion aborts via Promise.race + clears
620508
+ * the iterator, and telegramObservableInference falls back to the
620509
+ * non-streaming chatCompletion path. This gives operators a clean
620510
+ * "stream silent for 60s, falling back" signal instead of the opaque
620511
+ * 180s coalescer hard-deadline.
620512
+ *
620513
+ * Default 60s — comfortably longer than a healthy cold-load of a 35B
620514
+ * model on a warm VRAM cache (typically <30s) but short enough to
620515
+ * surface a real wedge before the 180s coalescer fires. Override via
620516
+ * OMNIUS_TG_STREAM_INACTIVITY_MS (clamped to [10s, 5min]).
620517
+ */
620518
+ telegramStreamInactivityMs() {
620519
+ const raw = Number.parseInt(process.env["OMNIUS_TG_STREAM_INACTIVITY_MS"] ?? "", 10);
620520
+ if (Number.isFinite(raw) && raw >= 1e4 && raw <= 3e5) return raw;
620521
+ return 6e4;
620522
+ }
620263
620523
  /**
620264
620524
  * Start the periodic stale-sub-agent reaper. Idempotent — safe to call
620265
620525
  * multiple times (no-op if already running). Stopped by stop() and on
@@ -654316,75 +654576,6 @@ ${result.summary}`
654316
654576
  const workEvaluator = new WorkEvaluator();
654317
654577
  let setupReady = false;
654318
654578
  const setupTasks = [];
654319
- ensureTranscribeCliBackground();
654320
- ensureCloudflaredBackground((msg) => {
654321
- if (statusBar?.isActive) {
654322
- statusBar.beginContentWrite();
654323
- renderInfo(msg);
654324
- statusBar.endContentWrite();
654325
- }
654326
- });
654327
- let depSudoResolver = null;
654328
- let depSudoPromptPending = false;
654329
- const visionDepsPromise = ensureVisionDeps(
654330
- (msg) => {
654331
- if (statusBar?.isActive) {
654332
- statusBar.beginContentWrite();
654333
- renderInfo(msg);
654334
- statusBar.endContentWrite();
654335
- }
654336
- },
654337
- () => new Promise((resolve52) => {
654338
- depSudoPromptPending = true;
654339
- if (process.stdout.isTTY) {
654340
- process.stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1006l");
654341
- }
654342
- const origProvider = statusBar.inputStateProvider;
654343
- if (statusBar?.isActive) {
654344
- statusBar.inputStateProvider = () => {
654345
- const state = origProvider?.() ?? { line: "", cursor: 0 };
654346
- return { line: "●".repeat(state.line.length), cursor: state.cursor };
654347
- };
654348
- }
654349
- const footerPwPrompt = `\x1B[38;5;198m● password:\x1B[0m `;
654350
- const prevPromptText = statusBar.promptText;
654351
- const prevPromptWidth = statusBar.promptWidth;
654352
- if (statusBar?.isActive) {
654353
- statusBar.setPromptText(footerPwPrompt, 12);
654354
- }
654355
- depSudoResolver = (pw2) => {
654356
- depSudoPromptPending = false;
654357
- depSudoResolver = null;
654358
- if (statusBar?.isActive) {
654359
- statusBar.inputStateProvider = origProvider ?? (() => ({ line: rl.line ?? "", cursor: rl.cursor ?? 0 }));
654360
- if (prevPromptText !== void 0 && prevPromptWidth !== void 0) {
654361
- statusBar.setPromptText(prevPromptText, prevPromptWidth);
654362
- }
654363
- }
654364
- if (process.stdout.isTTY) {
654365
- process.stdout.write("\x1B[?1002h\x1B[?1006h");
654366
- }
654367
- if (pw2) sessionSudoPassword = pw2;
654368
- resolve52(pw2);
654369
- };
654370
- const pwPrompt = `
654371
- \x1B[5;38;5;198m⚠ Password needed for dependency install\x1B[0m
654372
- ${c3.dim("Type your sudo password below and press Enter. Input is hidden.")}
654373
-
654374
- `;
654375
- if (isNeovimActive()) {
654376
- writeToNeovimOutput(pwPrompt);
654377
- } else {
654378
- if (statusBar?.isActive) statusBar.beginContentWrite();
654379
- process.stdout.write(pwPrompt);
654380
- if (statusBar?.isActive) statusBar.endContentWrite();
654381
- if (statusBar?.isActive) statusBar.handleResize();
654382
- }
654383
- })
654384
- ).catch(() => {
654385
- });
654386
- setupTasks.push(visionDepsPromise.catch(() => {
654387
- }));
654388
654579
  let updateNotified = false;
654389
654580
  checkForUpdate(version4).then((updateInfo) => {
654390
654581
  if (updateInfo) {
@@ -658074,20 +658265,6 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
658074
658265
  };
658075
658266
  };
658076
658267
  rl.on("line", (line) => {
658077
- if (depSudoPromptPending && depSudoResolver) {
658078
- const pw2 = line.trim();
658079
- depSudoPromptPending = false;
658080
- const resolver = depSudoResolver;
658081
- depSudoResolver = null;
658082
- if (pw2) sessionSudoPassword = pw2;
658083
- if (statusBar?.isActive) {
658084
- statusBar.beginContentWrite();
658085
- renderInfo("🔑 Password received");
658086
- statusBar.endContentWrite();
658087
- }
658088
- resolver(pw2 || null);
658089
- return;
658090
- }
658091
658268
  if (!setupReady) return;
658092
658269
  persistHistoryLine(line);
658093
658270
  const input = line.trim();
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.120",
3
+ "version": "1.0.127",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.120",
9
+ "version": "1.0.127",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.120",
3
+ "version": "1.0.127",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",