omnius 1.0.104 → 1.0.106

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
@@ -578020,10 +578020,43 @@ async function needsTextToolMode(modelName, backendUrl2) {
578020
578020
  const hasTools = await checkToolSupport(modelName, backendUrl2);
578021
578021
  return !hasTools;
578022
578022
  }
578023
+ function parseNvidiaSmi(stdout) {
578024
+ let total = 0;
578025
+ let free = 0;
578026
+ let name10 = "";
578027
+ const lines = stdout.trim().split("\n").filter(Boolean);
578028
+ for (const line of lines) {
578029
+ const parts = line.split(",").map((s2) => s2.trim());
578030
+ const totMB = parseInt(parts[0] ?? "0", 10);
578031
+ const freeMB = parseInt(parts[1] ?? "0", 10);
578032
+ if (!isNaN(totMB)) total += totMB / 1024;
578033
+ if (!isNaN(freeMB)) free += freeMB / 1024;
578034
+ if (!name10 && parts[2]) name10 = parts[2];
578035
+ }
578036
+ return { total, free, name: name10 };
578037
+ }
578038
+ function parseRocmSmi(stdout) {
578039
+ let total = 0;
578040
+ let used = 0;
578041
+ let name10 = "";
578042
+ const lines = stdout.trim().split("\n").filter(Boolean);
578043
+ for (const line of lines) {
578044
+ if (line.toLowerCase().startsWith("device") || line.startsWith("=")) continue;
578045
+ const parts = line.split(",").map((s2) => s2.trim());
578046
+ if (parts.length < 3) continue;
578047
+ const usedBytes = parseInt(parts[1] ?? "0", 10);
578048
+ const totBytes = parseInt(parts[2] ?? "0", 10);
578049
+ if (!isNaN(usedBytes)) used += usedBytes / 1024 ** 3;
578050
+ if (!isNaN(totBytes)) total += totBytes / 1024 ** 3;
578051
+ if (!name10 && parts[0]) name10 = parts[0];
578052
+ }
578053
+ return { total, free: Math.max(0, total - used), name: name10 ? `AMD ${name10}` : "AMD GPU" };
578054
+ }
578023
578055
  function detectSystemSpecs() {
578024
578056
  let totalRamGB = 0;
578025
578057
  let availableRamGB = 0;
578026
578058
  let gpuVramGB = 0;
578059
+ let availableVramGB = 0;
578027
578060
  let gpuName = "";
578028
578061
  try {
578029
578062
  const memInfo = execSync50("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
@@ -578047,24 +578080,33 @@ function detectSystemSpecs() {
578047
578080
  }
578048
578081
  try {
578049
578082
  const nvidiaSmi = execSync50(
578050
- "nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null",
578083
+ "nvidia-smi --query-gpu=memory.total,memory.free,name --format=csv,noheader,nounits 2>/dev/null",
578051
578084
  { encoding: "utf8", timeout: 5e3 }
578052
578085
  );
578053
- const lines = nvidiaSmi.trim().split("\n");
578054
- if (lines.length > 0) {
578055
- for (const line of lines) {
578056
- const parts = line.split(",").map((s2) => s2.trim());
578057
- const vramMB = parseInt(parts[0] ?? "0", 10);
578058
- if (!isNaN(vramMB)) gpuVramGB += vramMB / 1024;
578059
- if (!gpuName && parts[1]) gpuName = parts[1];
578060
- }
578061
- }
578086
+ const r2 = parseNvidiaSmi(nvidiaSmi);
578087
+ gpuVramGB += r2.total;
578088
+ availableVramGB += r2.free;
578089
+ if (!gpuName && r2.name) gpuName = r2.name;
578062
578090
  } catch {
578063
578091
  }
578092
+ if (gpuVramGB === 0) {
578093
+ try {
578094
+ const rocmSmi = execSync50(
578095
+ "rocm-smi --showmeminfo vram --csv 2>/dev/null",
578096
+ { encoding: "utf8", timeout: 5e3 }
578097
+ );
578098
+ const r2 = parseRocmSmi(rocmSmi);
578099
+ gpuVramGB += r2.total;
578100
+ availableVramGB += r2.free;
578101
+ if (!gpuName && r2.name) gpuName = r2.name;
578102
+ } catch {
578103
+ }
578104
+ }
578064
578105
  return {
578065
578106
  totalRamGB: Math.round(totalRamGB * 10) / 10,
578066
578107
  availableRamGB: Math.round(availableRamGB * 10) / 10,
578067
578108
  gpuVramGB: Math.round(gpuVramGB * 10) / 10,
578109
+ availableVramGB: Math.round(availableVramGB * 10) / 10,
578068
578110
  gpuName
578069
578111
  };
578070
578112
  }
@@ -578072,6 +578114,7 @@ async function detectSystemSpecsAsync() {
578072
578114
  let totalRamGB = 0;
578073
578115
  let availableRamGB = 0;
578074
578116
  let gpuVramGB = 0;
578117
+ let availableVramGB = 0;
578075
578118
  let gpuName = "";
578076
578119
  try {
578077
578120
  const { stdout: memInfo } = await execAsync2(
@@ -578095,24 +578138,33 @@ async function detectSystemSpecsAsync() {
578095
578138
  }
578096
578139
  try {
578097
578140
  const { stdout: nvidiaSmi } = await execAsync2(
578098
- "nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null",
578141
+ "nvidia-smi --query-gpu=memory.total,memory.free,name --format=csv,noheader,nounits 2>/dev/null",
578099
578142
  { timeout: 5e3 }
578100
578143
  );
578101
- const lines = nvidiaSmi.trim().split("\n");
578102
- if (lines.length > 0) {
578103
- for (const line of lines) {
578104
- const parts = line.split(",").map((s2) => s2.trim());
578105
- const vramMB = parseInt(parts[0] ?? "0", 10);
578106
- if (!isNaN(vramMB)) gpuVramGB += vramMB / 1024;
578107
- if (!gpuName && parts[1]) gpuName = parts[1];
578108
- }
578109
- }
578144
+ const r2 = parseNvidiaSmi(nvidiaSmi);
578145
+ gpuVramGB += r2.total;
578146
+ availableVramGB += r2.free;
578147
+ if (!gpuName && r2.name) gpuName = r2.name;
578110
578148
  } catch {
578111
578149
  }
578150
+ if (gpuVramGB === 0) {
578151
+ try {
578152
+ const { stdout: rocmSmi } = await execAsync2(
578153
+ "rocm-smi --showmeminfo vram --csv 2>/dev/null",
578154
+ { timeout: 5e3 }
578155
+ );
578156
+ const r2 = parseRocmSmi(rocmSmi);
578157
+ gpuVramGB += r2.total;
578158
+ availableVramGB += r2.free;
578159
+ if (!gpuName && r2.name) gpuName = r2.name;
578160
+ } catch {
578161
+ }
578162
+ }
578112
578163
  return {
578113
578164
  totalRamGB: Math.round(totalRamGB * 10) / 10,
578114
578165
  availableRamGB: Math.round(availableRamGB * 10) / 10,
578115
578166
  gpuVramGB: Math.round(gpuVramGB * 10) / 10,
578167
+ availableVramGB: Math.round(availableVramGB * 10) / 10,
578116
578168
  gpuName
578117
578169
  };
578118
578170
  }
@@ -578128,7 +578180,9 @@ function recommendModel(specs) {
578128
578180
  return QWEN_VARIANTS.find((v) => v.tag === "qwen3.5:cloud");
578129
578181
  }
578130
578182
  function calculateContextWindow(specs, modelSizeGB2, kvBytesPerToken, archMax) {
578131
- const totalAvail = Math.max(specs.gpuVramGB, specs.totalRamGB);
578183
+ const ramBudget = specs.availableRamGB > 0 ? specs.availableRamGB : specs.totalRamGB;
578184
+ const vramBudget = specs.availableVramGB > 0 ? specs.availableVramGB : specs.gpuVramGB;
578185
+ const totalAvail = Math.max(vramBudget, ramBudget);
578132
578186
  const remaining = Math.max(0, totalAvail - modelSizeGB2);
578133
578187
  const usableGB = remaining * 0.85;
578134
578188
  let numCtx;
@@ -578155,11 +578209,18 @@ function formatContextLabel(numCtx) {
578155
578209
  return numCtx >= 1024 ? `${Math.floor(numCtx / 1024)}K` : String(numCtx);
578156
578210
  }
578157
578211
  function calculateExpandedVariantContextWindow(specs, modelSizeGB2, kvBytesPerToken, archMax) {
578212
+ const memoryBudget = calculateContextWindow(
578213
+ specs,
578214
+ modelSizeGB2,
578215
+ kvBytesPerToken,
578216
+ archMax
578217
+ );
578158
578218
  if (archMax && archMax > 0) {
578159
- const numCtx = Math.max(2048, Math.floor(archMax / 1024) * 1024);
578219
+ const archCtx = Math.max(2048, Math.floor(archMax / 1024) * 1024);
578220
+ const numCtx = Math.min(archCtx, memoryBudget.numCtx);
578160
578221
  return { numCtx, label: formatContextLabel(numCtx) };
578161
578222
  }
578162
- return calculateContextWindow(specs, modelSizeGB2, kvBytesPerToken, archMax);
578223
+ return memoryBudget;
578163
578224
  }
578164
578225
  function ask(rl, question) {
578165
578226
  return new Promise((resolve52) => {
@@ -579437,7 +579498,10 @@ function getVenvDir2() {
579437
579498
  }
579438
579499
  function hasVenvModule() {
579439
579500
  try {
579440
- execSync50("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
579501
+ execSync50('python3 -c "import ensurepip, venv"', {
579502
+ stdio: "pipe",
579503
+ timeout: 5e3
579504
+ });
579441
579505
  return true;
579442
579506
  } catch {
579443
579507
  return false;
@@ -579470,15 +579534,15 @@ function ensureVenv(log22) {
579470
579534
  }
579471
579535
  }
579472
579536
  }
579473
- log22("Creating Python venv for vision deps...");
579474
579537
  if (!hasCmd(pythonCmd) && !hasCmd("python3")) {
579475
579538
  log22(`${pythonCmd} not found — cannot create venv.`);
579476
579539
  return null;
579477
579540
  }
579478
579541
  if (!isWin2 && !hasVenvModule()) {
579479
- log22("python3 venv module not available — venv creation skipped.");
579542
+ log22("python3-venv is not installed — venv creation skipped. Install with: sudo apt-get install python3-venv");
579480
579543
  return null;
579481
579544
  }
579545
+ log22("Creating Python venv for vision deps...");
579482
579546
  try {
579483
579547
  mkdirSync52(join107(homedir34(), ".omnius"), { recursive: true });
579484
579548
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
@@ -580034,7 +580098,10 @@ async function repairExpandedVariantIfStale(variantModel, fallbackBaseModel, bac
580034
580098
  return { repaired: false, currentNumCtx: state.currentNumCtx, baseModel: null, resolvedModel: variantName };
580035
580099
  }
580036
580100
  const canonicalModel = expandedModelName(baseModel);
580037
- const needsCtxRepair = !(state.currentNumCtx > 0 && state.currentNumCtx >= targetNumCtx);
580101
+ const hasCtx = state.currentNumCtx > 0;
580102
+ const tooSmall = hasCtx && state.currentNumCtx < targetNumCtx;
580103
+ const tooLarge = hasCtx && state.currentNumCtx > Math.floor(targetNumCtx * 1.1);
580104
+ const needsCtxRepair = !hasCtx || tooSmall || tooLarge;
580038
580105
  const needsCanonicalVariant = variantName !== canonicalModel;
580039
580106
  let repaired = false;
580040
580107
  if (needsCtxRepair) {
@@ -652800,15 +652867,41 @@ ${result.summary}`
652800
652867
  },
652801
652868
  () => new Promise((resolve52) => {
652802
652869
  depSudoPromptPending = true;
652870
+ if (process.stdout.isTTY) {
652871
+ process.stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1006l");
652872
+ }
652873
+ const origProvider = statusBar.inputStateProvider;
652874
+ if (statusBar?.isActive) {
652875
+ statusBar.inputStateProvider = () => {
652876
+ const state = origProvider?.() ?? { line: "", cursor: 0 };
652877
+ return { line: "●".repeat(state.line.length), cursor: state.cursor };
652878
+ };
652879
+ }
652880
+ const footerPwPrompt = `\x1B[38;5;198m● password:\x1B[0m `;
652881
+ const prevPromptText = statusBar.promptText;
652882
+ const prevPromptWidth = statusBar.promptWidth;
652883
+ if (statusBar?.isActive) {
652884
+ statusBar.setPromptText(footerPwPrompt, 12);
652885
+ }
652803
652886
  depSudoResolver = (pw2) => {
652804
652887
  depSudoPromptPending = false;
652805
652888
  depSudoResolver = null;
652889
+ if (statusBar?.isActive) {
652890
+ statusBar.inputStateProvider = origProvider ?? (() => ({ line: rl.line ?? "", cursor: rl.cursor ?? 0 }));
652891
+ if (prevPromptText !== void 0 && prevPromptWidth !== void 0) {
652892
+ statusBar.setPromptText(prevPromptText, prevPromptWidth);
652893
+ }
652894
+ }
652895
+ if (process.stdout.isTTY) {
652896
+ process.stdout.write("\x1B[?1002h\x1B[?1006h");
652897
+ }
652806
652898
  if (pw2) sessionSudoPassword = pw2;
652807
652899
  resolve52(pw2);
652808
652900
  };
652809
652901
  const pwPrompt = `
652810
- ${c3.bold(c3.yellow("🔑 Password needed for dependency install:"))}
652811
- ${c3.dim("Type your sudo password below and press Enter.")}
652902
+ \x1B[5;38;5;198m⚠ Password needed for dependency install\x1B[0m
652903
+ ${c3.dim("Type your sudo password below and press Enter. Input is hidden.")}
652904
+
652812
652905
  `;
652813
652906
  if (isNeovimActive()) {
652814
652907
  writeToNeovimOutput(pwPrompt);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.104",
3
+ "version": "1.0.106",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.104",
9
+ "version": "1.0.106",
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.104",
3
+ "version": "1.0.106",
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",