omnius 1.0.432 → 1.0.433

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
@@ -8216,6 +8216,7 @@ function runProcessBuffer(file, args = [], options2 = {}) {
8216
8216
  stdio: ["pipe", "pipe", "pipe"],
8217
8217
  windowsHide: true
8218
8218
  });
8219
+ options2.onSpawn?.(child);
8219
8220
  const stdoutChunks = [];
8220
8221
  const stderrChunks = [];
8221
8222
  const maxBuffer = options2.maxBuffer ?? 16 * 1024 * 1024;
@@ -8223,6 +8224,27 @@ function runProcessBuffer(file, args = [], options2 = {}) {
8223
8224
  let stderrBytes = 0;
8224
8225
  let settled = false;
8225
8226
  let timedOut = false;
8227
+ let aborted = false;
8228
+ let killTimer = null;
8229
+ const abortProcess = () => {
8230
+ aborted = true;
8231
+ try {
8232
+ child.kill("SIGTERM");
8233
+ } catch {
8234
+ }
8235
+ killTimer = setTimeout(() => {
8236
+ try {
8237
+ if (child.exitCode === null && child.signalCode === null)
8238
+ child.kill("SIGKILL");
8239
+ } catch {
8240
+ }
8241
+ }, 1500);
8242
+ killTimer.unref?.();
8243
+ };
8244
+ if (options2.signal?.aborted)
8245
+ abortProcess();
8246
+ else
8247
+ options2.signal?.addEventListener("abort", abortProcess, { once: true });
8226
8248
  const timer = options2.timeout ? setTimeout(() => {
8227
8249
  timedOut = true;
8228
8250
  try {
@@ -8237,6 +8259,9 @@ function runProcessBuffer(file, args = [], options2 = {}) {
8237
8259
  settled = true;
8238
8260
  if (timer)
8239
8261
  clearTimeout(timer);
8262
+ if (killTimer)
8263
+ clearTimeout(killTimer);
8264
+ options2.signal?.removeEventListener("abort", abortProcess);
8240
8265
  fn(value2);
8241
8266
  };
8242
8267
  child.stdout?.on("data", (chunk) => {
@@ -8273,6 +8298,10 @@ function runProcessBuffer(file, args = [], options2 = {}) {
8273
8298
  finish(reject, new AsyncProcessError(`Process timed out after ${options2.timeout}ms: ${file}`, result));
8274
8299
  return;
8275
8300
  }
8301
+ if (aborted) {
8302
+ finish(reject, new AsyncProcessError(`Process aborted: ${file}`, result));
8303
+ return;
8304
+ }
8276
8305
  if (stdoutBytes > maxBuffer || stderrBytes > maxBuffer) {
8277
8306
  finish(reject, new AsyncProcessError(`Process exceeded maxBuffer: ${file}`, result));
8278
8307
  return;
@@ -555784,6 +555813,9 @@ var init_visual_trigger = __esm({
555784
555813
  import { existsSync as existsSync78, mkdirSync as mkdirSync47, readFileSync as readFileSync57, rmSync as rmSync10, writeFileSync as writeFileSync39 } from "node:fs";
555785
555814
  import { homedir as homedir28, tmpdir as tmpdir20 } from "node:os";
555786
555815
  import { basename as basename19, isAbsolute as isAbsolute8, join as join92, resolve as resolve46 } from "node:path";
555816
+ function isAbortSignal(value2) {
555817
+ return Boolean(value2 && typeof value2 === "object" && "aborted" in value2 && typeof value2.addEventListener === "function");
555818
+ }
555787
555819
  function buildYolo26BootstrapPlan(model = DEFAULT_YOLO26_MODEL) {
555788
555820
  return {
555789
555821
  runtimeRoot: LIVE_MEDIA_ROOT,
@@ -556707,7 +556739,8 @@ var init_live_media_loop = __esm({
556707
556739
  const raw = await execFileText(runtime.python, [scriptPath2, cfgPath], {
556708
556740
  timeout: Math.max(12e4, Number(args["duration_sec"] ?? 8) * 1e3 + 9e5),
556709
556741
  maxBuffer: 64 * 1024 * 1024,
556710
- env: { ...process.env, PYTHONUNBUFFERED: "1" }
556742
+ env: { ...process.env, PYTHONUNBUFFERED: "1" },
556743
+ signal: isAbortSignal(args["abort_signal"]) ? args["abort_signal"] : void 0
556711
556744
  });
556712
556745
  const jsonLine2 = raw.trim().split("\n").reverse().find((line) => line.trim().startsWith("{") && line.trim().endsWith("}"));
556713
556746
  if (!jsonLine2)
@@ -604534,11 +604567,12 @@ var init_camera_streamer = __esm({
604534
604567
  }
604535
604568
  const killTimer = setTimeout(() => {
604536
604569
  try {
604537
- if (!child.killed) child.kill("SIGKILL");
604570
+ if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL");
604538
604571
  } catch {
604539
604572
  }
604540
604573
  }, 1500);
604541
604574
  killTimer.unref?.();
604575
+ child.once("exit", () => clearTimeout(killTimer));
604542
604576
  stream.process = null;
604543
604577
  }
604544
604578
  try {
@@ -604698,7 +604732,7 @@ var init_live_vlm = __esm({
604698
604732
  model: this.model,
604699
604733
  stream: false,
604700
604734
  format: "json",
604701
- keep_alive: String(process.env["OMNIUS_LIVE_VLM_KEEP_ALIVE"] ?? "30s"),
604735
+ keep_alive: String(process.env["OMNIUS_LIVE_VLM_KEEP_ALIVE"] ?? "5s"),
604702
604736
  options: { temperature: 0.1, num_predict: 260 },
604703
604737
  messages: [
604704
604738
  { role: "system", content: VLM_SYSTEM_PROMPT },
@@ -606851,6 +606885,7 @@ var init_live_sensors = __esm({
606851
606885
  videoGeneration = 0;
606852
606886
  liveGpuYieldUntil = 0;
606853
606887
  resourceArbiter = getLiveResourceArbiter();
606888
+ liveMediaAbortControllers = /* @__PURE__ */ new Set();
606854
606889
  videoInFlight = false;
606855
606890
  audioInFlight = false;
606856
606891
  audioActivityInFlight = false;
@@ -607187,7 +607222,7 @@ var init_live_sensors = __esm({
607187
607222
  const now2 = Date.now();
607188
607223
  if (now2 >= this.liveGpuYieldUntil) {
607189
607224
  this.liveGpuYieldUntil = Math.max(decision2.until ?? 0, now2 + 15e3);
607190
- void this.liveVlm.unloadModel().catch(() => false);
607225
+ void this.releaseLiveGpuMemory("live vision release", "vision").catch(() => false);
607191
607226
  this.emitFeedbackThrottled(`live-video-gpu-yield:${kind}`, {
607192
607227
  kind: "status",
607193
607228
  title: "Live video GPU yield",
@@ -607342,7 +607377,7 @@ var init_live_sensors = __esm({
607342
607377
  this.videoGeneration++;
607343
607378
  this.lastStreamFrameMtime.clear();
607344
607379
  this.cameraStreamers?.stopAll();
607345
- void this.liveVlm.unloadModel().catch(() => false);
607380
+ void this.releaseLiveGpuMemory("live vision release", "vision").catch(() => false);
607346
607381
  }
607347
607382
  this.persist();
607348
607383
  this.clearLoopTimers();
@@ -607375,8 +607410,10 @@ var init_live_sensors = __esm({
607375
607410
  this.lastInferenceAt.clear();
607376
607411
  this.autoOrientationInFlight.clear();
607377
607412
  this.liveSpeechInFlight.clear();
607413
+ for (const controller of this.liveMediaAbortControllers) controller.abort();
607414
+ this.liveMediaAbortControllers.clear();
607378
607415
  this.resourceArbiter.releaseOwnerPrefix("live-");
607379
- void this.liveVlm.unloadModel().catch(() => false);
607416
+ void this.releaseLiveGpuMemory("live stop", this.liveStopOllamaUnloadMode()).catch(() => false);
607380
607417
  this.snapshot = {
607381
607418
  version: 1,
607382
607419
  repoRoot: this.repoRoot,
@@ -607390,6 +607427,40 @@ var init_live_sensors = __esm({
607390
607427
  this.emitStatus();
607391
607428
  this.emitDashboard();
607392
607429
  }
607430
+ liveStopOllamaUnloadMode() {
607431
+ const raw = String(process.env["OMNIUS_LIVE_STOP_UNLOAD_OLLAMA"] ?? "").trim().toLowerCase();
607432
+ if (raw === "0" || raw === "off" || raw === "false" || raw === "none") return "off";
607433
+ if (raw === "vision" || raw === "vlm" || raw === "video") return "vision";
607434
+ if (raw === "all" || raw === "1" || raw === "true" || raw === "yes") return "all";
607435
+ return isJetsonUnifiedMemoryHost() ? "all" : "vision";
607436
+ }
607437
+ keptOllamaModels() {
607438
+ const keep = String(process.env["OMNIUS_LIVE_KEEP_OLLAMA_MODELS"] ?? "").split(",").map((entry) => entry.trim()).filter(Boolean);
607439
+ return new Set(keep);
607440
+ }
607441
+ shouldUnloadOllamaModelForLiveCleanup(modelName, mode, keep) {
607442
+ if (!modelName) return false;
607443
+ if (keep.has(modelName) || keep.has(modelName.split(":")[0] ?? modelName)) return false;
607444
+ if (mode === "all") return true;
607445
+ if (modelName === this.liveVlm.model) return true;
607446
+ return /(?:moondream|minicpm|llava|bakllava|vision|clip|florence|qwen.*vl|gemma.*vision)/i.test(modelName);
607447
+ }
607448
+ async releaseLiveGpuMemory(reason, mode = "vision") {
607449
+ await this.liveVlm.unloadModel().catch(() => false);
607450
+ if (mode === "off") return;
607451
+ const broker = getModelBroker();
607452
+ const snapshot = await broker.pollOnce().catch(() => broker.snapshot());
607453
+ const keep = this.keptOllamaModels();
607454
+ const targets = /* @__PURE__ */ new Set();
607455
+ for (const model of snapshot.loaded ?? []) {
607456
+ if (model.host !== "ollama") continue;
607457
+ if (this.shouldUnloadOllamaModelForLiveCleanup(model.name, mode, keep)) targets.add(model.name);
607458
+ }
607459
+ for (const modelName of targets) {
607460
+ await broker.unloadOllamaModel(modelName, reason).catch(() => false);
607461
+ }
607462
+ globalThis.gc?.();
607463
+ }
607393
607464
  startRunMode(options2 = {}) {
607394
607465
  this.agentActionEnabled = Boolean(options2.agent);
607395
607466
  this.liveSpeechEnabled = Boolean(options2.speech ?? options2.agent);
@@ -607677,8 +607748,11 @@ var init_live_sensors = __esm({
607677
607748
  this.lastInferenceAt.set(source, sampledAt);
607678
607749
  const loop = new LiveMediaLoopTool(this.repoRoot);
607679
607750
  const inferFromCapturedFrame = preview.ok && Boolean(preview.framePath);
607751
+ const mediaAbortController = new AbortController();
607752
+ this.liveMediaAbortControllers.add(mediaAbortController);
607680
607753
  const result = await loop.execute({
607681
607754
  action: "watch",
607755
+ abort_signal: mediaAbortController.signal,
607682
607756
  source_kind: inferFromCapturedFrame ? "file" : "camera",
607683
607757
  ...inferFromCapturedFrame ? { path: preview.framePath } : { camera: source },
607684
607758
  yolo_family: "yoloe-26",
@@ -607697,6 +607771,8 @@ var init_live_sensors = __esm({
607697
607771
  max_segments_per_frame: 8,
607698
607772
  crop_faces: true,
607699
607773
  recognize_faces: true
607774
+ }).finally(() => {
607775
+ this.liveMediaAbortControllers.delete(mediaAbortController);
607700
607776
  });
607701
607777
  if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607702
607778
  inference = result.success ? String(result.output || result.llmContent || "") : `Video inference failed: ${result.error || result.output || "unknown error"}`;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.432",
3
+ "version": "1.0.433",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.432",
9
+ "version": "1.0.433",
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.432",
3
+ "version": "1.0.433",
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",