omnius 1.0.431 → 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
@@ -1699,12 +1699,12 @@ var init_model_broker = __esm({
1699
1699
  // packages/execution/dist/broker-mediated-backend.js
1700
1700
  function wrapWithBroker(backend, options2) {
1701
1701
  const broker = getModelBroker();
1702
- const clamp10 = options2.clampNumCtx !== false;
1702
+ const clamp11 = options2.clampNumCtx !== false;
1703
1703
  const wrapped = Object.create(backend);
1704
1704
  wrapped.chatCompletion = async (request) => {
1705
1705
  const model = backend.model || request.model || "unknown";
1706
1706
  let effectiveRequest = request;
1707
- if (clamp10) {
1707
+ if (clamp11) {
1708
1708
  const trainCtx = await broker.getNctxTrain(model).catch(() => null);
1709
1709
  const requestedNumCtx = request.numCtx;
1710
1710
  if (trainCtx && trainCtx > 0) {
@@ -1738,7 +1738,7 @@ function wrapWithBroker(backend, options2) {
1738
1738
  wrapped.chatCompletionStream = async function* (request) {
1739
1739
  const model = backend.model || request.model || "unknown";
1740
1740
  let effectiveRequest = request;
1741
- if (clamp10) {
1741
+ if (clamp11) {
1742
1742
  const trainCtx = await broker.getNctxTrain(model).catch(() => null);
1743
1743
  const requestedNumCtx = request.numCtx;
1744
1744
  if (trainCtx && trainCtx > 0) {
@@ -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;
@@ -37242,11 +37271,11 @@ function deleteCustomToolDefinition(name10, scope, repoRoot) {
37242
37271
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
37243
37272
  const filePath = join35(dir, `${name10}.json`);
37244
37273
  if (existsSync33(filePath)) {
37245
- const { unlinkSync: unlinkSync37 } = __require("node:fs");
37246
- unlinkSync37(filePath);
37274
+ const { unlinkSync: unlinkSync38 } = __require("node:fs");
37275
+ unlinkSync38(filePath);
37247
37276
  const docsPath = toolDocsPath(name10, scope, repoRoot);
37248
37277
  if (existsSync33(docsPath))
37249
- unlinkSync37(docsPath);
37278
+ unlinkSync38(docsPath);
37250
37279
  if (scope === "project" && repoRoot)
37251
37280
  writeCustomToolRegistry(repoRoot);
37252
37281
  return true;
@@ -96067,13 +96096,13 @@ var require_singleton = __commonJS({
96067
96096
  Object.defineProperty(exports, "__esModule", { value: true });
96068
96097
  var injectable_1 = require_injectable();
96069
96098
  var dependency_container_1 = require_dependency_container();
96070
- function singleton() {
96099
+ function singleton2() {
96071
96100
  return function(target) {
96072
96101
  injectable_1.default()(target);
96073
96102
  dependency_container_1.instance.registerSingleton(target);
96074
96103
  };
96075
96104
  }
96076
- exports.default = singleton;
96105
+ exports.default = singleton2;
96077
96106
  }
96078
96107
  });
96079
96108
 
@@ -554463,10 +554492,10 @@ function collectSnapshot(workingDir) {
554463
554492
  const freeRAM = freemem2();
554464
554493
  let load1 = 0, load5 = 0, load15 = 0;
554465
554494
  try {
554466
- const loadavg4 = __require("node:os").loadavg();
554467
- load1 = loadavg4[0];
554468
- load5 = loadavg4[1];
554469
- load15 = loadavg4[2];
554495
+ const loadavg5 = __require("node:os").loadavg();
554496
+ load1 = loadavg5[0];
554497
+ load5 = loadavg5[1];
554498
+ load15 = loadavg5[2];
554470
554499
  } catch {
554471
554500
  }
554472
554501
  let gpu = void 0;
@@ -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)
@@ -564504,16 +564537,16 @@ function recommendMaxParallelFromVram(minFreeMB) {
564504
564537
  return 1;
564505
564538
  }
564506
564539
  async function getHardwareSnapshot() {
564507
- const { totalmem: totalmem10, freemem: freemem9, cpus: cpus6 } = await import("node:os");
564540
+ const { totalmem: totalmem11, freemem: freemem10, cpus: cpus7 } = await import("node:os");
564508
564541
  const gpus = await detectGpus();
564509
564542
  const diskPath = discoverSystemOllamaModelStore() ?? homedir33();
564510
564543
  const disk = snapshotDisk(diskPath);
564511
564544
  const network = snapshotNetwork();
564512
564545
  return {
564513
564546
  gpus,
564514
- cpuCores: cpus6().length,
564515
- ramTotalMB: Math.round(totalmem10() / (1024 * 1024)),
564516
- ramFreeMB: Math.round(freemem9() / (1024 * 1024)),
564547
+ cpuCores: cpus7().length,
564548
+ ramTotalMB: Math.round(totalmem11() / (1024 * 1024)),
564549
+ ramFreeMB: Math.round(freemem10() / (1024 * 1024)),
564517
564550
  disk,
564518
564551
  network,
564519
564552
  takenAtMs: Date.now()
@@ -578990,7 +579023,7 @@ ${context2 ?? ""}`;
578990
579023
  }
578991
579024
  }
578992
579025
  _applyTaskAffectFromResult(result, events) {
578993
- const clamp10 = (n2) => Math.max(0, Math.min(1, n2));
579026
+ const clamp11 = (n2) => Math.max(0, Math.min(1, n2));
578994
579027
  let uncertainty = this._taskAffectState.uncertainty * 0.94;
578995
579028
  let frustration = this._taskAffectState.frustration * 0.94;
578996
579029
  let confidence2 = this._taskAffectState.confidence * 0.94;
@@ -579023,11 +579056,11 @@ ${context2 ?? ""}`;
579023
579056
  }
579024
579057
  const level = frustration >= 0.72 || uncertainty >= 0.78 ? 4 : frustration >= 0.52 || uncertainty >= 0.58 ? 3 : frustration >= 0.32 || uncertainty >= 0.38 ? 2 : frustration >= 0.18 || uncertainty >= 0.22 ? 1 : 0;
579025
579058
  this._taskAffectState = {
579026
- uncertainty: clamp10(uncertainty),
579027
- frustration: clamp10(frustration),
579028
- confidence: clamp10(confidence2),
579029
- novelty: clamp10(novelty),
579030
- momentum: clamp10(momentum),
579059
+ uncertainty: clamp11(uncertainty),
579060
+ frustration: clamp11(frustration),
579061
+ confidence: clamp11(confidence2),
579062
+ novelty: clamp11(novelty),
579063
+ momentum: clamp11(momentum),
579031
579064
  adversaryLevel: level,
579032
579065
  lastUpdatedIso: (/* @__PURE__ */ new Date()).toISOString()
579033
579066
  };
@@ -593827,7 +593860,7 @@ ${result}`
593827
593860
  const buffer2 = Buffer.from(rawBase64, "base64");
593828
593861
  let resizedBase64 = null;
593829
593862
  try {
593830
- const { writeFileSync: writeFileSync95, readFileSync: readFileSync140, unlinkSync: unlinkSync37 } = await import("node:fs");
593863
+ const { writeFileSync: writeFileSync95, readFileSync: readFileSync140, unlinkSync: unlinkSync38 } = await import("node:fs");
593831
593864
  const { join: join188 } = await import("node:path");
593832
593865
  const { tmpdir: tmpdir26 } = await import("node:os");
593833
593866
  const tmpIn = join188(tmpdir26(), `omnius_img_in_${Date.now()}.png`);
@@ -593845,11 +593878,11 @@ ${result}`
593845
593878
  const resizedBuf = readFileSync140(tmpOut);
593846
593879
  resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
593847
593880
  try {
593848
- unlinkSync37(tmpIn);
593881
+ unlinkSync38(tmpIn);
593849
593882
  } catch {
593850
593883
  }
593851
593884
  try {
593852
- unlinkSync37(tmpOut);
593885
+ unlinkSync38(tmpOut);
593853
593886
  } catch {
593854
593887
  }
593855
593888
  } catch {
@@ -604342,13 +604375,36 @@ transcribe-cli error: ${transcribeCliError}` : "";
604342
604375
 
604343
604376
  // packages/cli/src/tui/camera-streamer.ts
604344
604377
  import { spawn as spawn30 } from "node:child_process";
604345
- import { existsSync as existsSync111, mkdirSync as mkdirSync69, statSync as statSync43 } from "node:fs";
604378
+ import { existsSync as existsSync111, mkdirSync as mkdirSync69, statSync as statSync43, unlinkSync as unlinkSync20 } from "node:fs";
604346
604379
  import { join as join127 } from "node:path";
604347
604380
  function streamFps() {
604348
604381
  const raw = Number(process.env["OMNIUS_LIVE_STREAM_FPS"] ?? "");
604349
604382
  if (Number.isFinite(raw) && raw > 0) return Math.max(1, Math.min(30, Math.round(raw)));
604350
604383
  return 8;
604351
604384
  }
604385
+ function parseResolution(value2) {
604386
+ const raw = String(value2 ?? "").trim().toLowerCase();
604387
+ if (!raw || raw === "native" || raw === "auto") return null;
604388
+ const alias = {
604389
+ "480p": "640x480",
604390
+ "720p": "1280x720",
604391
+ "1080p": "1920x1080",
604392
+ "1440p": "2560x1440",
604393
+ "4k": "3840x2160",
604394
+ "2160p": "3840x2160"
604395
+ };
604396
+ const normalized = alias[raw] ?? raw;
604397
+ const match = normalized.match(/^(\d{3,5})x(\d{3,5})$/);
604398
+ if (!match) return null;
604399
+ const width = Number(match[1]);
604400
+ const height = Number(match[2]);
604401
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;
604402
+ return { label: `${width}x${height}`, width, height };
604403
+ }
604404
+ function scaleFilter(resolution) {
604405
+ if (!resolution) return null;
604406
+ return `scale=w='min(${resolution.width}\\,iw)':h='min(${resolution.height}\\,ih)':force_original_aspect_ratio=decrease`;
604407
+ }
604352
604408
  function rotateFilter(rotation) {
604353
604409
  switch ((rotation % 360 + 360) % 360) {
604354
604410
  case 90:
@@ -604368,7 +604424,7 @@ var MAX_ATTEMPT, FAST_EXIT_MS, RESTART_DELAY_MS, MAX_CONSECUTIVE_FAILURES, Camer
604368
604424
  var init_camera_streamer = __esm({
604369
604425
  "packages/cli/src/tui/camera-streamer.ts"() {
604370
604426
  "use strict";
604371
- MAX_ATTEMPT = 2;
604427
+ MAX_ATTEMPT = 4;
604372
604428
  FAST_EXIT_MS = 3e3;
604373
604429
  RESTART_DELAY_MS = 1500;
604374
604430
  MAX_CONSECUTIVE_FAILURES = 10;
@@ -604403,7 +604459,7 @@ var init_camera_streamer = __esm({
604403
604459
  * Only v4l2 device paths are streamable; other backends (OSC/WiFi cams)
604404
604460
  * keep the one-shot capture path.
604405
604461
  */
604406
- sync(sources, rotationFor) {
604462
+ sync(sources, rotationFor, resolutionFor) {
604407
604463
  const wanted = new Set(sources.filter((source) => source.startsWith("/dev/video")));
604408
604464
  for (const [source, stream] of this.streams) {
604409
604465
  if (!wanted.has(source)) {
@@ -604413,20 +604469,21 @@ var init_camera_streamer = __esm({
604413
604469
  }
604414
604470
  for (const source of wanted) {
604415
604471
  const rotation = rotationFor(source);
604472
+ const resolution = resolutionFor(source);
604416
604473
  const existing = this.streams.get(source);
604417
- if (existing && existing.rotation === rotation && !existing.stopped) continue;
604474
+ if (existing && existing.rotation === rotation && existing.resolution === resolution && !existing.stopped) continue;
604418
604475
  if (existing) {
604419
604476
  this.stopStream(existing);
604420
604477
  this.streams.delete(source);
604421
604478
  }
604422
- this.startStream(source, rotation);
604479
+ this.startStream(source, rotation, resolution);
604423
604480
  }
604424
604481
  }
604425
604482
  stopAll() {
604426
604483
  for (const stream of this.streams.values()) this.stopStream(stream);
604427
604484
  this.streams.clear();
604428
604485
  }
604429
- startStream(source, rotation) {
604486
+ startStream(source, rotation, resolution) {
604430
604487
  try {
604431
604488
  mkdirSync69(this.streamDir, { recursive: true });
604432
604489
  } catch {
@@ -604435,6 +604492,7 @@ var init_camera_streamer = __esm({
604435
604492
  source,
604436
604493
  framePath: join127(this.streamDir, `${slugForSource(source)}.jpg`),
604437
604494
  rotation,
604495
+ resolution,
604438
604496
  process: null,
604439
604497
  attempt: 0,
604440
604498
  consecutiveFailures: 0,
@@ -604449,13 +604507,17 @@ var init_camera_streamer = __esm({
604449
604507
  spawnStream(stream) {
604450
604508
  if (stream.stopped) return;
604451
604509
  const fps = streamFps();
604510
+ const resolution = parseResolution(stream.resolution);
604452
604511
  const filters = [`fps=${fps}`];
604512
+ const scale = scaleFilter(resolution);
604513
+ if (scale) filters.push(scale);
604453
604514
  const rotate = rotateFilter(stream.rotation);
604454
604515
  if (rotate) filters.push(rotate);
604455
604516
  const args = ["-hide_banner", "-loglevel", "error", "-f", "v4l2"];
604456
- if (stream.attempt === 0) args.push("-input_format", "mjpeg");
604517
+ if (stream.attempt === 0 || stream.attempt === 2) args.push("-input_format", "mjpeg");
604518
+ if (resolution && stream.attempt <= 1) args.push("-video_size", resolution.label);
604457
604519
  args.push("-i", stream.source, "-vf", filters.join(","), "-q:v", "6", "-f", "image2", "-update", "1");
604458
- if (stream.attempt <= 1) args.push("-atomic_writing", "1");
604520
+ if (stream.attempt <= 3) args.push("-atomic_writing", "1");
604459
604521
  args.push("-y", stream.framePath);
604460
604522
  const child = spawn30(process.env["OMNIUS_FFMPEG"] || "ffmpeg", args, {
604461
604523
  stdio: ["ignore", "ignore", "pipe"]
@@ -604498,12 +604560,25 @@ var init_camera_streamer = __esm({
604498
604560
  stream.restartTimer = null;
604499
604561
  }
604500
604562
  if (stream.process) {
604563
+ const child = stream.process;
604501
604564
  try {
604502
- stream.process.kill("SIGTERM");
604565
+ child.kill("SIGTERM");
604503
604566
  } catch {
604504
604567
  }
604568
+ const killTimer = setTimeout(() => {
604569
+ try {
604570
+ if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL");
604571
+ } catch {
604572
+ }
604573
+ }, 1500);
604574
+ killTimer.unref?.();
604575
+ child.once("exit", () => clearTimeout(killTimer));
604505
604576
  stream.process = null;
604506
604577
  }
604578
+ try {
604579
+ if (existsSync111(stream.framePath)) unlinkSync20(stream.framePath);
604580
+ } catch {
604581
+ }
604507
604582
  }
604508
604583
  };
604509
604584
  }
@@ -604657,7 +604732,7 @@ var init_live_vlm = __esm({
604657
604732
  model: this.model,
604658
604733
  stream: false,
604659
604734
  format: "json",
604660
- keep_alive: String(process.env["OMNIUS_LIVE_VLM_KEEP_ALIVE"] ?? "30s"),
604735
+ keep_alive: String(process.env["OMNIUS_LIVE_VLM_KEEP_ALIVE"] ?? "5s"),
604661
604736
  options: { temperature: 0.1, num_predict: 260 },
604662
604737
  messages: [
604663
604738
  { role: "system", content: VLM_SYSTEM_PROMPT },
@@ -604719,9 +604794,230 @@ var init_live_vlm = __esm({
604719
604794
  }
604720
604795
  });
604721
604796
 
604797
+ // packages/cli/src/tui/live-resource-arbiter.ts
604798
+ import { cpus as cpus3, freemem as freemem4, loadavg, totalmem as totalmem5 } from "node:os";
604799
+ function getLiveResourceArbiter() {
604800
+ if (!singleton) singleton = new LiveResourceArbiter();
604801
+ return singleton;
604802
+ }
604803
+ function formatLiveResourceBudgetLines(width = 100) {
604804
+ const snap = getLiveResourceArbiter().snapshot();
604805
+ const inner = Math.max(24, width - 2);
604806
+ const memoryColor = pressureColor(snap.memoryPressure, snap.target);
604807
+ const totalGB = snap.totalMemMB / 1024;
604808
+ const usedGB = snap.usedMemMB / 1024;
604809
+ const freeGB = snap.freeMemMB / 1024;
604810
+ const deferMs = Math.max(0, snap.deferUntil - Date.now());
604811
+ const status = deferMs > 0 ? colorText("deferring vision", 208) : colorText("vision allowed", 82);
604812
+ const leaseText = snap.leases.length > 0 ? snap.leases.slice(0, 3).map((lease) => `${lease.owner} p${lease.priority} ${Math.ceil(lease.expiresInMs / 1e3)}s`).join("; ") : "none";
604813
+ return [
604814
+ colorText(" resource budget", 45),
604815
+ `├─ memory: ${memoryColor(`${usedGB.toFixed(1)}/${totalGB.toFixed(1)}GB used`)} free=${freeGB.toFixed(1)}GB target<=${Math.round(snap.target * 100)}%`,
604816
+ `├─ pressure: ${pressureColor(snap.pressure, snap.target)(`${Math.round(snap.pressure * 100)}%`)} pid=${Math.round(snap.pid * 100)}% cpuLoad=${snap.cpuLoad1m.toFixed(2)} budget=${snap.budget} ${status}`,
604817
+ `└─ leases: ${truncateAnsi(leaseText, inner - 12)}`
604818
+ ];
604819
+ }
604820
+ function readBudget() {
604821
+ const raw = String(process.env["OMNIUS_LIVE_RESOURCE_BUDGET"] ?? "").trim().toLowerCase();
604822
+ if (raw === "low" || raw === "conserve" || raw === "conservative" || raw === "battery") return "conserve";
604823
+ if (raw === "high" || raw === "generous") return "high";
604824
+ if (raw === "aggressive" || raw === "max" || raw === "unlimited") return "aggressive";
604825
+ return "balanced";
604826
+ }
604827
+ function budgetTarget(budget) {
604828
+ const override = Number(process.env["OMNIUS_LIVE_RESOURCE_TARGET"] ?? "");
604829
+ if (Number.isFinite(override) && override > 0 && override < 1) return override;
604830
+ if (budget === "conserve") return 0.55;
604831
+ if (budget === "high") return 0.82;
604832
+ if (budget === "aggressive") return 0.92;
604833
+ return 0.7;
604834
+ }
604835
+ function numberEnv(name10, fallback) {
604836
+ const value2 = Number(process.env[name10] ?? "");
604837
+ return Number.isFinite(value2) ? value2 : fallback;
604838
+ }
604839
+ function clamp8(value2, min, max) {
604840
+ return Math.max(min, Math.min(max, value2));
604841
+ }
604842
+ function pressureColor(pressure, target) {
604843
+ if (pressure <= target) return (text2) => colorText(text2, 82);
604844
+ if (pressure <= target + 0.12) return (text2) => colorText(text2, 220);
604845
+ return (text2) => colorText(text2, 196);
604846
+ }
604847
+ function colorText(text2, color) {
604848
+ return `\x1B[38;5;${color}m${text2}\x1B[0m`;
604849
+ }
604850
+ function truncateAnsi(text2, max) {
604851
+ const plain = text2.replace(/\x1b\[[0-9;]*m/g, "");
604852
+ if (plain.length <= max) return text2;
604853
+ return `${plain.slice(0, Math.max(0, max - 3))}...`;
604854
+ }
604855
+ var LiveResourceArbiter, singleton;
604856
+ var init_live_resource_arbiter = __esm({
604857
+ "packages/cli/src/tui/live-resource-arbiter.ts"() {
604858
+ "use strict";
604859
+ LiveResourceArbiter = class {
604860
+ leases = /* @__PURE__ */ new Map();
604861
+ seq = 0;
604862
+ integral = 0;
604863
+ lastError = 0;
604864
+ lastAt = 0;
604865
+ pidDeferUntil = 0;
604866
+ lastPid = 0;
604867
+ lastPressure = 0;
604868
+ claim(args) {
604869
+ const now2 = Date.now();
604870
+ this.cleanup(now2);
604871
+ const id2 = `${now2}-${++this.seq}-${args.owner.replace(/[^a-z0-9_.:-]+/gi, "_")}`;
604872
+ const record = {
604873
+ id: id2,
604874
+ owner: args.owner,
604875
+ priority: clamp8(args.priority, 0, 100),
604876
+ reason: args.reason,
604877
+ suppress: args.suppress?.length ? args.suppress : ["vision"],
604878
+ createdAt: now2,
604879
+ expiresAt: now2 + Math.max(250, args.ttlMs)
604880
+ };
604881
+ this.leases.set(id2, record);
604882
+ return {
604883
+ id: id2,
604884
+ owner: record.owner,
604885
+ priority: record.priority,
604886
+ get expiresAt() {
604887
+ return record.expiresAt;
604888
+ },
604889
+ release: () => {
604890
+ this.leases.delete(id2);
604891
+ },
604892
+ extend: (ttlMs, reason) => {
604893
+ const current = this.leases.get(id2);
604894
+ if (!current) return;
604895
+ current.expiresAt = Math.max(current.expiresAt, Date.now() + Math.max(250, ttlMs));
604896
+ if (reason) current.reason = reason;
604897
+ }
604898
+ };
604899
+ }
604900
+ shouldDefer(kind, options2 = {}) {
604901
+ const now2 = Date.now();
604902
+ this.cleanup(now2);
604903
+ const budget = readBudget();
604904
+ if (String(process.env["OMNIUS_LIVE_RESOURCE_ARBITER"] ?? "").toLowerCase() === "off") {
604905
+ return this.decision(false, "", now2, 0, budget);
604906
+ }
604907
+ const minPriority = clamp8(options2.minPriority ?? 50, 0, 100);
604908
+ const token = kind.toLowerCase();
604909
+ let strongest = null;
604910
+ for (const lease of this.leases.values()) {
604911
+ if (lease.priority < minPriority) continue;
604912
+ if (!lease.suppress.some((entry) => entry === "*" || token.includes(entry.toLowerCase()))) continue;
604913
+ if (!strongest || lease.priority > strongest.priority || lease.expiresAt > strongest.expiresAt) strongest = lease;
604914
+ }
604915
+ if (strongest) {
604916
+ return this.decision(
604917
+ true,
604918
+ `live resource priority ${strongest.priority} from ${strongest.owner}: ${strongest.reason}`,
604919
+ strongest.expiresAt,
604920
+ strongest.priority,
604921
+ budget
604922
+ );
604923
+ }
604924
+ const pid = this.samplePid(now2, budget);
604925
+ if (pid.deferUntil > now2) {
604926
+ return this.decision(
604927
+ true,
604928
+ `resource PID pressure budget=${budget} pressure=${pid.pressure.toFixed(2)} target=${pid.target.toFixed(2)} output=${pid.output.toFixed(2)}`,
604929
+ pid.deferUntil,
604930
+ 45,
604931
+ budget
604932
+ );
604933
+ }
604934
+ return this.decision(false, "", now2, 0, budget);
604935
+ }
604936
+ snapshot(now2 = Date.now()) {
604937
+ this.cleanup(now2);
604938
+ const budget = readBudget();
604939
+ const pid = this.samplePid(now2, budget);
604940
+ const total = Math.max(1, totalmem5());
604941
+ const free = Math.max(0, freemem4());
604942
+ const cpuCount = Math.max(1, cpus3().length);
604943
+ const cpuLoad1m = loadavg()[0] ?? 0;
604944
+ return {
604945
+ budget,
604946
+ totalMemMB: Math.round(total / 1024 / 1024),
604947
+ freeMemMB: Math.round(free / 1024 / 1024),
604948
+ usedMemMB: Math.round((total - free) / 1024 / 1024),
604949
+ memoryPressure: clamp8(1 - free / total, 0, 1),
604950
+ cpuLoad1m,
604951
+ cpuPressure: clamp8(cpuLoad1m / cpuCount, 0, 2) / 2,
604952
+ pressure: pid.pressure,
604953
+ target: pid.target,
604954
+ pid: pid.output,
604955
+ deferUntil: pid.deferUntil,
604956
+ leases: [...this.leases.values()].sort((a2, b) => b.priority - a2.priority).map((lease) => ({
604957
+ owner: lease.owner,
604958
+ priority: lease.priority,
604959
+ reason: lease.reason,
604960
+ expiresInMs: Math.max(0, lease.expiresAt - now2)
604961
+ }))
604962
+ };
604963
+ }
604964
+ releaseOwnerPrefix(prefix) {
604965
+ for (const [id2, lease] of this.leases) {
604966
+ if (lease.owner.startsWith(prefix)) this.leases.delete(id2);
604967
+ }
604968
+ }
604969
+ decision(defer, reason, until, priority, budget) {
604970
+ return {
604971
+ defer,
604972
+ reason,
604973
+ until,
604974
+ priority,
604975
+ budget,
604976
+ pressure: this.lastPressure,
604977
+ pid: this.lastPid
604978
+ };
604979
+ }
604980
+ cleanup(now2) {
604981
+ for (const [id2, lease] of this.leases) {
604982
+ if (lease.expiresAt <= now2) this.leases.delete(id2);
604983
+ }
604984
+ }
604985
+ samplePid(now2, budget) {
604986
+ const target = budgetTarget(budget);
604987
+ const cpuCount = Math.max(1, cpus3().length);
604988
+ const cpuPressure = clamp8((loadavg()[0] ?? 0) / cpuCount, 0, 2) / 2;
604989
+ const total = Math.max(1, totalmem5());
604990
+ const free = Math.max(0, freemem4());
604991
+ const memoryPressure = clamp8(1 - free / total, 0, 1);
604992
+ const pressure = clamp8(Math.max(memoryPressure, cpuPressure * 0.65 + memoryPressure * 0.35), 0, 1);
604993
+ const dt = this.lastAt > 0 ? clamp8((now2 - this.lastAt) / 1e3, 0.1, 10) : 1;
604994
+ const error = pressure - target;
604995
+ this.integral = clamp8(this.integral + error * dt, -2, 2);
604996
+ const derivative = (error - this.lastError) / dt;
604997
+ const kp = numberEnv("OMNIUS_LIVE_PID_KP", 0.9);
604998
+ const ki = numberEnv("OMNIUS_LIVE_PID_KI", 0.18);
604999
+ const kd = numberEnv("OMNIUS_LIVE_PID_KD", 0.12);
605000
+ const output = clamp8(kp * error + ki * this.integral + kd * derivative, 0, 1);
605001
+ this.lastAt = now2;
605002
+ this.lastError = error;
605003
+ this.lastPressure = pressure;
605004
+ this.lastPid = output;
605005
+ if (output > 0.08) {
605006
+ const maxMs = numberEnv("OMNIUS_LIVE_PID_MAX_DEFER_MS", 3e4);
605007
+ this.pidDeferUntil = Math.max(this.pidDeferUntil, now2 + clamp8(750 + output * maxMs, 1e3, maxMs));
605008
+ } else if (pressure < target - 0.08) {
605009
+ this.pidDeferUntil = Math.min(this.pidDeferUntil, now2);
605010
+ }
605011
+ return { output, pressure, target, deferUntil: this.pidDeferUntil };
605012
+ }
605013
+ };
605014
+ singleton = null;
605015
+ }
605016
+ });
605017
+
604722
605018
  // packages/cli/src/tui/live-sensors.ts
604723
605019
  import { existsSync as existsSync113, mkdirSync as mkdirSync70, readFileSync as readFileSync91, writeFileSync as writeFileSync58 } from "node:fs";
604724
- import { arch as arch3, freemem as freemem4 } from "node:os";
605020
+ import { arch as arch3, freemem as freemem5 } from "node:os";
604725
605021
  import { basename as basename23, join as join128, relative as relative11 } from "node:path";
604726
605022
  function liveDir(repoRoot) {
604727
605023
  return join128(repoRoot, ".omnius", "live");
@@ -604873,6 +605169,52 @@ function describeCameraOrientation(orientation) {
604873
605169
  if (!orientation) return "upright/no correction (default)";
604874
605170
  return `${formatCameraRotation(orientation.rotation)} (${orientation.source}${orientation.confidence !== void 0 ? ` confidence=${orientation.confidence.toFixed(2)}` : ""}, updated=${nowIso3(orientation.updatedAt)})`;
604875
605171
  }
605172
+ function normalizeLiveCameraResolution(value2) {
605173
+ const raw = String(value2 ?? "").trim().toLowerCase();
605174
+ if (!raw || raw === "default" || raw === "1080" || raw === "1080p") return "1920x1080";
605175
+ if (raw === "native" || raw === "auto" || raw === "max") return "native";
605176
+ if (raw === "480" || raw === "480p" || raw === "vga") return "640x480";
605177
+ if (raw === "720" || raw === "720p" || raw === "hd") return "1280x720";
605178
+ if (raw === "1440" || raw === "1440p" || raw === "2k") return "2560x1440";
605179
+ if (raw === "2160" || raw === "2160p" || raw === "4k" || raw === "uhd") return "3840x2160";
605180
+ if (["640x480", "1280x720", "1920x1080", "2560x1440", "3840x2160"].includes(raw)) return raw;
605181
+ throw new Error(`Unsupported live camera resolution: ${String(value2)}. Use native, 480p, 720p, 1080p, 1440p, 4k, or WxH.`);
605182
+ }
605183
+ function formatLiveCameraResolution(value2) {
605184
+ const res = value2 ?? DEFAULT_CAMERA_RESOLUTION;
605185
+ if (res === "native") return "native";
605186
+ if (res === "640x480") return "480p (640x480)";
605187
+ if (res === "1280x720") return "720p (1280x720)";
605188
+ if (res === "1920x1080") return "1080p (1920x1080)";
605189
+ if (res === "2560x1440") return "1440p (2560x1440)";
605190
+ if (res === "3840x2160") return "4K (3840x2160)";
605191
+ return res;
605192
+ }
605193
+ function liveCameraResolutionSize(value2) {
605194
+ const res = value2 ?? DEFAULT_CAMERA_RESOLUTION;
605195
+ if (res === "native") return null;
605196
+ const [widthRaw, heightRaw] = res.split("x");
605197
+ const width = Number(widthRaw);
605198
+ const height = Number(heightRaw);
605199
+ return Number.isFinite(width) && Number.isFinite(height) ? { width, height } : null;
605200
+ }
605201
+ function sanitizeCameraStreams(value2) {
605202
+ if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return {};
605203
+ const out = {};
605204
+ for (const [device, raw] of Object.entries(value2)) {
605205
+ if (!device || typeof raw !== "object" || raw === null || Array.isArray(raw)) continue;
605206
+ const entry = raw;
605207
+ try {
605208
+ out[device] = {
605209
+ enabled: entry["enabled"] !== false,
605210
+ resolution: normalizeLiveCameraResolution(entry["resolution"] ?? DEFAULT_CAMERA_RESOLUTION)
605211
+ };
605212
+ } catch {
605213
+ out[device] = { enabled: entry["enabled"] !== false, resolution: DEFAULT_CAMERA_RESOLUTION };
605214
+ }
605215
+ }
605216
+ return out;
605217
+ }
604876
605218
  function chooseCameraOrientationFromScores(scores) {
604877
605219
  const sorted = [...scores].filter((score) => Number.isFinite(score.score)).sort((a2, b) => b.score - a2.score);
604878
605220
  const best = sorted[0];
@@ -605632,6 +605974,13 @@ function formatLiveDashboardFromSnapshot(snapshot, opts = {}) {
605632
605974
  const horizontal = "─".repeat(Math.max(0, width - 2));
605633
605975
  const lines = [`╭${horizontal}╮`];
605634
605976
  lines.push(`│${truncateCell(` ${title}`, width - 2)}│`);
605977
+ lines.push(`├${horizontal}┤`);
605978
+ for (const budgetLine of formatLiveResourceBudgetLines(width - 2)) {
605979
+ lines.push(`│${truncateAnsiCell(budgetLine, width - 2)}│`);
605980
+ }
605981
+ const enabledStreams = Object.entries(snapshot.config.cameraStreams ?? {}).filter(([, stream]) => stream.enabled !== false);
605982
+ const selectedResolution = snapshot.config.selectedCamera ? formatLiveCameraResolution(snapshot.config.cameraStreams?.[snapshot.config.selectedCamera]?.resolution) : "none";
605983
+ lines.push(`│${truncateCell(` systems: camera-streams=${enabledStreams.length}/${snapshot.devices.video.length} selected-res=${selectedResolution} yolo=${snapshot.config.inferEnabled ? "on" : "off"} clip=${snapshot.config.clipEnabled ? "on" : "off"} asr=${snapshot.config.asrEnabled ? "on" : "off"} sounds=${snapshot.config.audioAnalysisEnabled ? "on" : "off"}`, width - 2)}│`);
605635
605984
  if (cameras.length === 0) {
605636
605985
  lines.push(`│${truncateCell(" no camera frames captured yet", width - 2)}│`);
605637
605986
  }
@@ -605958,6 +606307,7 @@ function loadLiveSensorConfig(repoRoot) {
605958
606307
  ...DEFAULT_CONFIG7,
605959
606308
  ...parsed,
605960
606309
  cameraOrientation: sanitizeCameraOrientation(parsed.cameraOrientation),
606310
+ cameraStreams: sanitizeCameraStreams(parsed.cameraStreams),
605961
606311
  videoIntervalMs: Math.max(MIN_VIDEO_INTERVAL_MS, Number(parsed.videoIntervalMs ?? DEFAULT_CONFIG7.videoIntervalMs)),
605962
606312
  audioIntervalMs: Math.max(MIN_AUDIO_INTERVAL_MS, Number(parsed.audioIntervalMs ?? DEFAULT_CONFIG7.audioIntervalMs))
605963
606313
  };
@@ -605997,7 +606347,9 @@ function formatLiveSensorContextFromSnapshot(snapshot, opts = {}) {
605997
606347
  lines.push(`Streams: video=${snapshot.config.videoEnabled ? "on" : "off"} infer=${snapshot.config.inferEnabled ? "on" : "off"} clip=${snapshot.config.clipEnabled ? "on" : "off"} audio=${snapshot.config.audioEnabled ? "on" : "off"} asr=${snapshot.config.asrEnabled ? "on" : "off"} sounds=${snapshot.config.audioAnalysisEnabled ? "on" : "off"} output-monitor=${snapshot.config.audioOutputEnabled ? "on" : "off"}`);
605998
606348
  if (snapshot.config.selectedCamera) {
605999
606349
  const orientation = snapshot.config.cameraOrientation?.[snapshot.config.selectedCamera];
606350
+ const stream = snapshot.config.cameraStreams?.[snapshot.config.selectedCamera];
606000
606351
  lines.push(`Selected camera: ${snapshot.config.selectedCamera}`);
606352
+ lines.push(`Selected camera stream: ${stream?.enabled !== false ? "enabled" : "disabled"} ${formatLiveCameraResolution(stream?.resolution)}`);
606001
606353
  lines.push(`Camera orientation correction: ${describeCameraOrientation(orientation)}`);
606002
606354
  }
606003
606355
  const cameraSnapshots = Object.values(snapshot.cameras ?? (snapshot.video ? { [snapshot.video.source]: snapshot.video } : {})).sort((a2, b) => {
@@ -606454,6 +606806,7 @@ function formatLiveStatus(snapshot) {
606454
606806
  const lines = [
606455
606807
  `Live streams: video=${cfg.videoEnabled ? "on" : "off"} infer=${cfg.inferEnabled ? "on" : "off"} clip=${cfg.clipEnabled ? "on" : "off"} audio=${cfg.audioEnabled ? "on" : "off"} asr=${cfg.asrEnabled ? "on" : "off"} sounds=${cfg.audioAnalysisEnabled ? "on" : "off"} output=${cfg.audioOutputEnabled ? "on" : "off"}`,
606456
606808
  `Camera: ${cfg.selectedCamera || "none"}`,
606809
+ `Camera stream: ${cfg.selectedCamera ? `${cfg.cameraStreams?.[cfg.selectedCamera]?.enabled !== false ? "enabled" : "disabled"} ${formatLiveCameraResolution(cfg.cameraStreams?.[cfg.selectedCamera]?.resolution)}` : "none"}`,
606457
606810
  `Camera orientation: ${cfg.selectedCamera ? describeCameraOrientation(cfg.cameraOrientation?.[cfg.selectedCamera]) : "none"}`,
606458
606811
  `Audio input: ${cfg.selectedAudioInput || "none"}`,
606459
606812
  `Audio output: ${cfg.selectedAudioOutput || "none"}`,
@@ -606467,7 +606820,7 @@ function formatLiveStatus(snapshot) {
606467
606820
  }
606468
606821
  return lines.join("\n");
606469
606822
  }
606470
- var MIN_VIDEO_INTERVAL_MS, LOW_LATENCY_VIDEO_INTERVAL_MS, MIN_AUDIO_INTERVAL_MS, LOW_LATENCY_AUDIO_INTERVAL_MS, AUDIO_ACTIVITY_INTERVAL_MS, AUDIO_ACTIVITY_SAMPLE_SEC, DEFAULT_CONFIG7, managers, DASHBOARD_ANSI_STICKY_PATTERN, _liveDashboardMaximizedCamera, LiveSensorManager;
606823
+ var MIN_VIDEO_INTERVAL_MS, LOW_LATENCY_VIDEO_INTERVAL_MS, MIN_AUDIO_INTERVAL_MS, LOW_LATENCY_AUDIO_INTERVAL_MS, AUDIO_ACTIVITY_INTERVAL_MS, AUDIO_ACTIVITY_SAMPLE_SEC, DEFAULT_CAMERA_RESOLUTION, DEFAULT_CONFIG7, managers, DASHBOARD_ANSI_STICKY_PATTERN, _liveDashboardMaximizedCamera, LiveSensorManager;
606471
606824
  var init_live_sensors = __esm({
606472
606825
  "packages/cli/src/tui/live-sensors.ts"() {
606473
606826
  "use strict";
@@ -606477,12 +606830,14 @@ var init_live_sensors = __esm({
606477
606830
  init_listen();
606478
606831
  init_camera_streamer();
606479
606832
  init_live_vlm();
606833
+ init_live_resource_arbiter();
606480
606834
  MIN_VIDEO_INTERVAL_MS = 250;
606481
606835
  LOW_LATENCY_VIDEO_INTERVAL_MS = 250;
606482
606836
  MIN_AUDIO_INTERVAL_MS = 1500;
606483
606837
  LOW_LATENCY_AUDIO_INTERVAL_MS = 2e3;
606484
606838
  AUDIO_ACTIVITY_INTERVAL_MS = 200;
606485
606839
  AUDIO_ACTIVITY_SAMPLE_SEC = 0.2;
606840
+ DEFAULT_CAMERA_RESOLUTION = "1920x1080";
606486
606841
  DEFAULT_CONFIG7 = {
606487
606842
  videoEnabled: false,
606488
606843
  audioEnabled: false,
@@ -606492,6 +606847,7 @@ var init_live_sensors = __esm({
606492
606847
  asrEnabled: false,
606493
606848
  audioAnalysisEnabled: false,
606494
606849
  cameraOrientation: {},
606850
+ cameraStreams: {},
606495
606851
  videoIntervalMs: 1e3,
606496
606852
  audioIntervalMs: 6e3
606497
606853
  };
@@ -606528,6 +606884,8 @@ var init_live_sensors = __esm({
606528
606884
  lastStreamPersistAt = 0;
606529
606885
  videoGeneration = 0;
606530
606886
  liveGpuYieldUntil = 0;
606887
+ resourceArbiter = getLiveResourceArbiter();
606888
+ liveMediaAbortControllers = /* @__PURE__ */ new Set();
606531
606889
  videoInFlight = false;
606532
606890
  audioInFlight = false;
606533
606891
  audioActivityInFlight = false;
@@ -606672,12 +607030,85 @@ var init_live_sensors = __esm({
606672
607030
  if (!clean5 || ordered.includes(clean5)) return;
606673
607031
  const device = this.devices.video.find((entry) => entry.id === clean5);
606674
607032
  if (device && /metadata\/non-capture/i.test(device.detail ?? "")) return;
607033
+ if (!this.isCameraStreamEnabled(clean5)) return;
606675
607034
  ordered.push(clean5);
606676
607035
  };
606677
607036
  add3(this.config.selectedCamera);
606678
607037
  for (const device of this.devices.video) add3(device.id);
606679
- if (ordered.length === 0) add3(firstDeviceId(this.devices.video));
606680
- return ordered.slice(0, 4);
607038
+ const hasExplicitStreamConfig = Object.keys(this.config.cameraStreams ?? {}).length > 0;
607039
+ if (ordered.length === 0 && !hasExplicitStreamConfig) {
607040
+ const fallback = this.config.selectedCamera || firstDeviceId(this.devices.video);
607041
+ if (fallback) {
607042
+ this.config = {
607043
+ ...this.config,
607044
+ selectedCamera: fallback,
607045
+ cameraStreams: {
607046
+ ...this.config.cameraStreams ?? {},
607047
+ [fallback]: {
607048
+ enabled: true,
607049
+ resolution: this.config.cameraStreams?.[fallback]?.resolution ?? DEFAULT_CAMERA_RESOLUTION
607050
+ }
607051
+ }
607052
+ };
607053
+ add3(fallback);
607054
+ }
607055
+ }
607056
+ const maxStreams = Math.max(1, Math.min(8, Number(process.env["OMNIUS_LIVE_MAX_CAMERA_STREAMS"] ?? 4) || 4));
607057
+ return ordered.slice(0, maxStreams);
607058
+ }
607059
+ isCameraStreamEnabled(device = this.config.selectedCamera) {
607060
+ const target = device || this.config.selectedCamera;
607061
+ if (!target) return false;
607062
+ const configured = this.config.cameraStreams?.[target];
607063
+ if (configured) return configured.enabled !== false;
607064
+ return target === this.config.selectedCamera;
607065
+ }
607066
+ getCameraStreamResolution(device = this.config.selectedCamera) {
607067
+ const target = device || this.config.selectedCamera;
607068
+ return target ? this.config.cameraStreams?.[target]?.resolution ?? DEFAULT_CAMERA_RESOLUTION : DEFAULT_CAMERA_RESOLUTION;
607069
+ }
607070
+ setCameraStreamEnabled(device, enabled2) {
607071
+ const target = device || this.config.selectedCamera;
607072
+ if (!target) return null;
607073
+ const current = this.config.cameraStreams?.[target];
607074
+ const next = {
607075
+ enabled: enabled2,
607076
+ resolution: current?.resolution ?? DEFAULT_CAMERA_RESOLUTION
607077
+ };
607078
+ this.config = {
607079
+ ...this.config,
607080
+ selectedCamera: enabled2 ? target : this.config.selectedCamera,
607081
+ cameraStreams: {
607082
+ ...this.config.cameraStreams ?? {},
607083
+ [target]: next
607084
+ }
607085
+ };
607086
+ this.videoGeneration++;
607087
+ this.lastStreamFrameMtime.delete(target);
607088
+ this.persist();
607089
+ this.ensureLoops();
607090
+ return next;
607091
+ }
607092
+ setCameraStreamResolution(device, resolution) {
607093
+ const target = device || this.config.selectedCamera;
607094
+ if (!target) return null;
607095
+ const current = this.config.cameraStreams?.[target];
607096
+ const next = {
607097
+ enabled: current?.enabled ?? target === this.config.selectedCamera,
607098
+ resolution: normalizeLiveCameraResolution(resolution)
607099
+ };
607100
+ this.config = {
607101
+ ...this.config,
607102
+ cameraStreams: {
607103
+ ...this.config.cameraStreams ?? {},
607104
+ [target]: next
607105
+ }
607106
+ };
607107
+ this.videoGeneration++;
607108
+ this.lastStreamFrameMtime.delete(target);
607109
+ this.persist();
607110
+ this.ensureLoops();
607111
+ return next;
606681
607112
  }
606682
607113
  getCameraOrientation(device = this.config.selectedCamera) {
606683
607114
  return device ? this.config.cameraOrientation?.[device] : void 0;
@@ -606748,6 +607179,14 @@ var init_live_sensors = __esm({
606748
607179
  return isJetsonUnifiedMemoryHost() ? "yield" : "balanced";
606749
607180
  }
606750
607181
  async shouldYieldLiveGpuVideo(kind) {
607182
+ const resourceDecision = this.resourceArbiter.shouldDefer(`vision:${kind}`, { minPriority: 45 });
607183
+ if (resourceDecision.defer) {
607184
+ return {
607185
+ yield: true,
607186
+ reason: resourceDecision.reason,
607187
+ until: resourceDecision.until
607188
+ };
607189
+ }
606751
607190
  const policy = this.liveVideoGpuPolicy();
606752
607191
  if (policy === "aggressive") return { yield: false, reason: "" };
606753
607192
  if (policy === "yield") {
@@ -606771,7 +607210,7 @@ var init_live_sensors = __esm({
606771
607210
  };
606772
607211
  }
606773
607212
  } catch {
606774
- if (isJetsonUnifiedMemoryHost() || freemem4() < 6 * 1024 * 1024 * 1024) {
607213
+ if (isJetsonUnifiedMemoryHost() || freemem5() < 6 * 1024 * 1024 * 1024) {
606775
607214
  return { yield: true, reason: `live video ${kind} yielded: memory pressure unknown` };
606776
607215
  }
606777
607216
  }
@@ -606782,14 +607221,16 @@ var init_live_sensors = __esm({
606782
607221
  if (!decision2.yield) return false;
606783
607222
  const now2 = Date.now();
606784
607223
  if (now2 >= this.liveGpuYieldUntil) {
606785
- this.liveGpuYieldUntil = now2 + 15e3;
606786
- void this.liveVlm.unloadModel().catch(() => false);
607224
+ this.liveGpuYieldUntil = Math.max(decision2.until ?? 0, now2 + 15e3);
607225
+ void this.releaseLiveGpuMemory("live vision release", "vision").catch(() => false);
606787
607226
  this.emitFeedbackThrottled(`live-video-gpu-yield:${kind}`, {
606788
607227
  kind: "status",
606789
607228
  title: "Live video GPU yield",
606790
607229
  observedAt: now2,
606791
607230
  message: `${decision2.reason}. Camera capture/ASCII preview stays active; GPU video inference is skipped. Set OMNIUS_LIVE_VIDEO_GPU_POLICY=aggressive to override.`
606792
607231
  }, 3e4);
607232
+ } else if (decision2.until) {
607233
+ this.liveGpuYieldUntil = Math.max(this.liveGpuYieldUntil, decision2.until);
606793
607234
  }
606794
607235
  return true;
606795
607236
  }
@@ -606814,10 +607255,12 @@ var init_live_sensors = __esm({
606814
607255
  }
606815
607256
  if (!framePath) {
606816
607257
  if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607258
+ const captureSize = liveCameraResolutionSize(this.getCameraStreamResolution(target));
606817
607259
  const captured = await new CameraCaptureTool().execute({
606818
607260
  action: "capture",
606819
607261
  device: target,
606820
- rotate_degrees: 0
607262
+ rotate_degrees: 0,
607263
+ ...captureSize ? { width: captureSize.width, height: captureSize.height } : {}
606821
607264
  });
606822
607265
  if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
606823
607266
  if (!captured.success) {
@@ -606892,11 +607335,25 @@ var init_live_sensors = __esm({
606892
607335
  errors
606893
607336
  };
606894
607337
  if (!this.config.selectedCamera) this.config.selectedCamera = firstDeviceId(video);
607338
+ this.config.cameraStreams = this.reconcileCameraStreams(video);
606895
607339
  if (!this.config.selectedAudioInput) this.config.selectedAudioInput = preferredLiveAudioInputId(inputs.devices);
606896
607340
  if (!this.config.selectedAudioOutput) this.config.selectedAudioOutput = firstDeviceId(outputs.devices);
606897
607341
  this.persist();
606898
607342
  return this.devices;
606899
607343
  }
607344
+ reconcileCameraStreams(video) {
607345
+ const current = this.config.cameraStreams ?? {};
607346
+ const selected = this.config.selectedCamera || firstDeviceId(video);
607347
+ const next = {};
607348
+ for (const device of video) {
607349
+ if (!device.id || /metadata\/non-capture/i.test(device.detail ?? "")) continue;
607350
+ next[device.id] = {
607351
+ enabled: current[device.id]?.enabled ?? device.id === selected,
607352
+ resolution: current[device.id]?.resolution ?? DEFAULT_CAMERA_RESOLUTION
607353
+ };
607354
+ }
607355
+ return next;
607356
+ }
606900
607357
  configure(patch) {
606901
607358
  const wasVideoEnabled = this.config.videoEnabled;
606902
607359
  this.config = {
@@ -606905,11 +607362,22 @@ var init_live_sensors = __esm({
606905
607362
  videoIntervalMs: Math.max(MIN_VIDEO_INTERVAL_MS, Number(patch.videoIntervalMs ?? this.config.videoIntervalMs)),
606906
607363
  audioIntervalMs: Math.max(MIN_AUDIO_INTERVAL_MS, Number(patch.audioIntervalMs ?? this.config.audioIntervalMs))
606907
607364
  };
607365
+ this.config.cameraStreams = sanitizeCameraStreams(this.config.cameraStreams);
607366
+ if (patch.selectedCamera) {
607367
+ const selected = String(patch.selectedCamera);
607368
+ this.config.cameraStreams = {
607369
+ ...this.config.cameraStreams ?? {},
607370
+ [selected]: {
607371
+ enabled: true,
607372
+ resolution: this.config.cameraStreams?.[selected]?.resolution ?? DEFAULT_CAMERA_RESOLUTION
607373
+ }
607374
+ };
607375
+ }
606908
607376
  if (wasVideoEnabled && !this.config.videoEnabled) {
606909
607377
  this.videoGeneration++;
606910
607378
  this.lastStreamFrameMtime.clear();
606911
607379
  this.cameraStreamers?.stopAll();
606912
- void this.liveVlm.unloadModel().catch(() => false);
607380
+ void this.releaseLiveGpuMemory("live vision release", "vision").catch(() => false);
606913
607381
  }
606914
607382
  this.persist();
606915
607383
  this.clearLoopTimers();
@@ -606929,6 +607397,69 @@ var init_live_sensors = __esm({
606929
607397
  asrEnabled: false,
606930
607398
  audioAnalysisEnabled: false
606931
607399
  });
607400
+ this.cleanupLiveResources();
607401
+ }
607402
+ cleanupLiveResources() {
607403
+ this.clearLoopTimers();
607404
+ this.videoGeneration++;
607405
+ this.cameraStreamers?.stopAll();
607406
+ this.cameraStreamers = null;
607407
+ this.lastStreamFrameMtime.clear();
607408
+ this.lastVlmAt.clear();
607409
+ this.lastClipAt.clear();
607410
+ this.lastInferenceAt.clear();
607411
+ this.autoOrientationInFlight.clear();
607412
+ this.liveSpeechInFlight.clear();
607413
+ for (const controller of this.liveMediaAbortControllers) controller.abort();
607414
+ this.liveMediaAbortControllers.clear();
607415
+ this.resourceArbiter.releaseOwnerPrefix("live-");
607416
+ void this.releaseLiveGpuMemory("live stop", this.liveStopOllamaUnloadMode()).catch(() => false);
607417
+ this.snapshot = {
607418
+ version: 1,
607419
+ repoRoot: this.repoRoot,
607420
+ config: this.config,
607421
+ devices: this.devices,
607422
+ events: [],
607423
+ people: [],
607424
+ cameras: {}
607425
+ };
607426
+ this.persist();
607427
+ this.emitStatus();
607428
+ this.emitDashboard();
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?.();
606932
607463
  }
606933
607464
  startRunMode(options2 = {}) {
606934
607465
  this.agentActionEnabled = Boolean(options2.agent);
@@ -607039,10 +607570,12 @@ var init_live_sensors = __esm({
607039
607570
  };
607040
607571
  }
607041
607572
  }
607573
+ const captureSize = liveCameraResolutionSize(this.getCameraStreamResolution(source));
607042
607574
  const result = await new CameraCaptureTool().execute({
607043
607575
  action: "capture",
607044
607576
  device: source,
607045
- rotate_degrees: rotation
607577
+ rotate_degrees: rotation,
607578
+ ...captureSize ? { width: captureSize.width, height: captureSize.height } : {}
607046
607579
  });
607047
607580
  if (!this.isVideoWorkCurrent(generation)) return { ok: false, message: "Video context is disabled." };
607048
607581
  if (!result.success) {
@@ -607215,8 +607748,11 @@ var init_live_sensors = __esm({
607215
607748
  this.lastInferenceAt.set(source, sampledAt);
607216
607749
  const loop = new LiveMediaLoopTool(this.repoRoot);
607217
607750
  const inferFromCapturedFrame = preview.ok && Boolean(preview.framePath);
607751
+ const mediaAbortController = new AbortController();
607752
+ this.liveMediaAbortControllers.add(mediaAbortController);
607218
607753
  const result = await loop.execute({
607219
607754
  action: "watch",
607755
+ abort_signal: mediaAbortController.signal,
607220
607756
  source_kind: inferFromCapturedFrame ? "file" : "camera",
607221
607757
  ...inferFromCapturedFrame ? { path: preview.framePath } : { camera: source },
607222
607758
  yolo_family: "yoloe-26",
@@ -607235,6 +607771,8 @@ var init_live_sensors = __esm({
607235
607771
  max_segments_per_frame: 8,
607236
607772
  crop_faces: true,
607237
607773
  recognize_faces: true
607774
+ }).finally(() => {
607775
+ this.liveMediaAbortControllers.delete(mediaAbortController);
607238
607776
  });
607239
607777
  if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607240
607778
  inference = result.success ? String(result.output || result.llmContent || "") : `Video inference failed: ${result.error || result.output || "unknown error"}`;
@@ -607447,6 +607985,8 @@ ${output}`).join("\n\n");
607447
607985
  async sampleAudioNow() {
607448
607986
  if (this.audioInFlight) return "Audio sampler is already running.";
607449
607987
  this.audioInFlight = true;
607988
+ let asrLease = null;
607989
+ let keepAsrLease = false;
607450
607990
  try {
607451
607991
  const input = this.resolveAudioInput();
607452
607992
  if (this.isLiveAudioMutedForTts()) {
@@ -607497,6 +608037,13 @@ ${output}`).join("\n\n");
607497
608037
  audioErrors.push(`No live input signal detected from selected input ${capture.device}; keeping the explicit selection.`);
607498
608038
  }
607499
608039
  if (this.config.asrEnabled) {
608040
+ asrLease = this.resourceArbiter.claim({
608041
+ owner: "live-asr",
608042
+ priority: 88,
608043
+ ttlMs: 18e3,
608044
+ reason: "live audio ASR capture/transcription",
608045
+ suppress: ["vision"]
608046
+ });
607500
608047
  try {
607501
608048
  const asr = await new TranscribeFileTool(this.repoRoot).execute({
607502
608049
  path: recordingPath,
@@ -607533,6 +608080,11 @@ ${output}`).join("\n\n");
607533
608080
  }
607534
608081
  if (transcript) {
607535
608082
  intake = await classifyLiveAudioIntake(transcript, this.intakeAgentConfig);
608083
+ keepAsrLease = true;
608084
+ asrLease?.extend(
608085
+ intake?.intendedForAgent ? 35e3 : 18e3,
608086
+ intake?.intendedForAgent ? "live ASR addressed Omnius; reserving compute for response inference" : "live ASR transcript accepted; briefly yielding vision"
608087
+ );
607536
608088
  }
607537
608089
  this.snapshot.audio = {
607538
608090
  updatedAt: Date.now(),
@@ -607600,6 +608152,7 @@ Sound analysis:
607600
608152
  ${analysis}` : ""
607601
608153
  ].filter(Boolean).join("\n");
607602
608154
  } finally {
608155
+ if (!keepAsrLease) asrLease?.release();
607603
608156
  this.audioInFlight = false;
607604
608157
  }
607605
608158
  }
@@ -607640,7 +608193,8 @@ ${analysis}` : ""
607640
608193
  }
607641
608194
  this.cameraStreamers.sync(
607642
608195
  this.activeVideoSources(),
607643
- (source) => this.getCameraOrientation(source)?.rotation ?? 0
608196
+ (source) => this.getCameraOrientation(source)?.rotation ?? 0,
608197
+ (source) => this.getCameraStreamResolution(source)
607644
608198
  );
607645
608199
  }
607646
608200
  previewTickIntervalMs() {
@@ -612442,6 +612996,8 @@ var init_command_registry = __esm({
612442
612996
  ["/live chat", "Start low-latency voicechat with live audio/video context and async agent review"],
612443
612997
  ["/livechat", "Alias for /live chat, used by the top live button"],
612444
612998
  ["/live camera <device>", "Select a camera and render an ASCII preview"],
612999
+ ["/live resolution [camera] 720p|1080p|1440p|4k|native", "Set per-camera live stream resolution (default 1080p)"],
613000
+ ["/live camera-on|camera-off [camera]", "Enable or disable an individual live camera stream"],
612445
613001
  ["/live rotate auto|cw|ccw|180|none [camera]", "Detect or set persistent camera orientation correction"],
612446
613002
  ["/live infer [now|on|off]", "Toggle or run camera object/location inference"],
612447
613003
  ["/live clip [on|off]", "Toggle CLIP visual-memory recognition on live frames"],
@@ -614330,7 +614886,7 @@ var init_syntax_highlight = __esm({
614330
614886
  });
614331
614887
 
614332
614888
  // packages/cli/src/tui/model-picker.ts
614333
- import { totalmem as totalmem5 } from "node:os";
614889
+ import { totalmem as totalmem6 } from "node:os";
614334
614890
  function isImageGenModel(name10, family) {
614335
614891
  return IMAGE_GEN_PATTERNS.some((p2) => p2.test(name10) || family && p2.test(family));
614336
614892
  }
@@ -614719,7 +615275,7 @@ async function queryModelContextSize(baseUrl2, modelName) {
614719
615275
  }
614720
615276
  }
614721
615277
  function estimateRealisticContext(kvBytesPerToken, archMax, modelSizeGB2) {
614722
- const totalMemGB = totalmem5() / 1024 ** 3;
615278
+ const totalMemGB = totalmem6() / 1024 ** 3;
614723
615279
  const usableBytes = totalMemGB * 0.7 * 1024 ** 3;
614724
615280
  const maxTokens = Math.floor(usableBytes / kvBytesPerToken);
614725
615281
  let numCtx = Math.max(2048, Math.floor(maxTokens / 1024) * 1024);
@@ -619090,8 +619646,8 @@ import { spawn as spawn32, exec as exec3 } from "node:child_process";
619090
619646
  import { EventEmitter as EventEmitter8 } from "node:events";
619091
619647
  import { randomBytes as randomBytes22, timingSafeEqual } from "node:crypto";
619092
619648
  import { URL as URL2 } from "node:url";
619093
- import { loadavg, cpus as cpus3, totalmem as totalmem6, freemem as freemem5 } from "node:os";
619094
- import { existsSync as existsSync117, readFileSync as readFileSync95, writeFileSync as writeFileSync60, unlinkSync as unlinkSync20, mkdirSync as mkdirSync72, readdirSync as readdirSync38, statSync as statSync45, statfsSync as statfsSync7 } from "node:fs";
619649
+ import { loadavg as loadavg2, cpus as cpus4, totalmem as totalmem7, freemem as freemem6 } from "node:os";
619650
+ import { existsSync as existsSync117, readFileSync as readFileSync95, writeFileSync as writeFileSync60, unlinkSync as unlinkSync21, mkdirSync as mkdirSync72, readdirSync as readdirSync38, statSync as statSync45, statfsSync as statfsSync7 } from "node:fs";
619095
619651
  import { join as join132 } from "node:path";
619096
619652
  function cleanForwardHeaders(raw, targetHost) {
619097
619653
  const out = {};
@@ -619304,7 +619860,7 @@ function writeExposeState(stateDir, state) {
619304
619860
  }
619305
619861
  function removeExposeState(stateDir) {
619306
619862
  try {
619307
- unlinkSync20(join132(stateDir, STATE_FILE_NAME));
619863
+ unlinkSync21(join132(stateDir, STATE_FILE_NAME));
619308
619864
  } catch {
619309
619865
  }
619310
619866
  }
@@ -619348,10 +619904,10 @@ function parseRateLimitHeaders(headers) {
619348
619904
  };
619349
619905
  }
619350
619906
  async function collectSystemMetricsAsync() {
619351
- const [l1, l5, l15] = loadavg();
619352
- const cores = cpus3().length;
619353
- const totalMem = totalmem6();
619354
- const freeMem = freemem5();
619907
+ const [l1, l5, l15] = loadavg2();
619908
+ const cores = cpus4().length;
619909
+ const totalMem = totalmem7();
619910
+ const freeMem = freemem6();
619355
619911
  const usedMem = totalMem - freeMem;
619356
619912
  let disk = {
619357
619913
  path: process.cwd(),
@@ -619442,7 +619998,7 @@ function writeP2PExposeState(stateDir, state) {
619442
619998
  }
619443
619999
  function removeP2PExposeState(stateDir) {
619444
620000
  try {
619445
- unlinkSync20(join132(stateDir, P2P_STATE_FILE_NAME));
620001
+ unlinkSync21(join132(stateDir, P2P_STATE_FILE_NAME));
619446
620002
  } catch {
619447
620003
  }
619448
620004
  }
@@ -622577,7 +623133,7 @@ ${activitySummary}
622577
623133
  });
622578
623134
 
622579
623135
  // packages/cli/src/api/profiles.ts
622580
- import { existsSync as existsSync119, readFileSync as readFileSync97, writeFileSync as writeFileSync62, mkdirSync as mkdirSync74, readdirSync as readdirSync39, unlinkSync as unlinkSync21 } from "node:fs";
623136
+ import { existsSync as existsSync119, readFileSync as readFileSync97, writeFileSync as writeFileSync62, mkdirSync as mkdirSync74, readdirSync as readdirSync39, unlinkSync as unlinkSync22 } from "node:fs";
622581
623137
  import { join as join134 } from "node:path";
622582
623138
  import { homedir as homedir41 } from "node:os";
622583
623139
  import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes25, scryptSync as scryptSync3 } from "node:crypto";
@@ -622681,7 +623237,7 @@ function deleteProfile(name10, scope = "global", projectDir2) {
622681
623237
  const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
622682
623238
  const filePath = join134(dir, `${sanitized}.json`);
622683
623239
  if (existsSync119(filePath)) {
622684
- unlinkSync21(filePath);
623240
+ unlinkSync22(filePath);
622685
623241
  return true;
622686
623242
  }
622687
623243
  return false;
@@ -622959,7 +623515,7 @@ __export(omnius_directory_exports, {
622959
623515
  writeIndexMeta: () => writeIndexMeta,
622960
623516
  writeTaskHandoff: () => writeTaskHandoff2
622961
623517
  });
622962
- import { appendFileSync as appendFileSync13, cpSync as cpSync2, existsSync as existsSync120, mkdirSync as mkdirSync75, readFileSync as readFileSync98, writeFileSync as writeFileSync63, readdirSync as readdirSync40, statSync as statSync46, unlinkSync as unlinkSync22, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync11, watch as fsWatch2 } from "node:fs";
623518
+ import { appendFileSync as appendFileSync13, cpSync as cpSync2, existsSync as existsSync120, mkdirSync as mkdirSync75, readFileSync as readFileSync98, writeFileSync as writeFileSync63, readdirSync as readdirSync40, statSync as statSync46, unlinkSync as unlinkSync23, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync11, watch as fsWatch2 } from "node:fs";
622963
623519
  import { join as join135, relative as relative13, basename as basename25, dirname as dirname40, resolve as resolve57 } from "node:path";
622964
623520
  import { homedir as homedir42 } from "node:os";
622965
623521
  import { createHash as createHash37 } from "node:crypto";
@@ -623350,7 +623906,7 @@ function loadPendingTask(repoRoot) {
623350
623906
  if (!existsSync120(filePath)) return null;
623351
623907
  const data = JSON.parse(readFileSync98(filePath, "utf-8"));
623352
623908
  try {
623353
- unlinkSync22(filePath);
623909
+ unlinkSync23(filePath);
623354
623910
  } catch {
623355
623911
  }
623356
623912
  return data;
@@ -623369,7 +623925,7 @@ function writeTaskHandoff2(repoRoot, handoff) {
623369
623925
  } catch {
623370
623926
  writeFileSync63(filePath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
623371
623927
  try {
623372
- unlinkSync22(tempPath);
623928
+ unlinkSync23(tempPath);
623373
623929
  } catch {
623374
623930
  }
623375
623931
  }
@@ -623395,7 +623951,7 @@ function clearTaskHandoff(repoRoot) {
623395
623951
  const filePath = join135(repoRoot, OMNIUS_DIR, "context", HANDOFF_FILE);
623396
623952
  try {
623397
623953
  if (existsSync120(filePath)) {
623398
- unlinkSync22(filePath);
623954
+ unlinkSync23(filePath);
623399
623955
  }
623400
623956
  } catch {
623401
623957
  }
@@ -623469,13 +624025,13 @@ function acquireLock(lockPath) {
623469
624025
  const lockAge = Date.now() - lock.acquiredAt;
623470
624026
  if (lockAge > LOCK_TIMEOUT_MS) {
623471
624027
  try {
623472
- unlinkSync22(lockPath);
624028
+ unlinkSync23(lockPath);
623473
624029
  } catch {
623474
624030
  }
623475
624031
  }
623476
624032
  } catch {
623477
624033
  try {
623478
- unlinkSync22(lockPath);
624034
+ unlinkSync23(lockPath);
623479
624035
  } catch {
623480
624036
  }
623481
624037
  }
@@ -623493,7 +624049,7 @@ function releaseLock(lockPath) {
623493
624049
  const lockContent = readFileSync98(lockPath, "utf-8");
623494
624050
  const lock = JSON.parse(lockContent);
623495
624051
  if (lock.pid === process.pid) {
623496
- unlinkSync22(lockPath);
624052
+ unlinkSync23(lockPath);
623497
624053
  }
623498
624054
  }
623499
624055
  } catch {
@@ -623679,7 +624235,7 @@ function saveSessionContext(repoRoot, entry) {
623679
624235
  } catch {
623680
624236
  writeFileSync63(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
623681
624237
  try {
623682
- unlinkSync22(tempFilePath);
624238
+ unlinkSync23(tempFilePath);
623683
624239
  } catch {
623684
624240
  }
623685
624241
  }
@@ -624062,7 +624618,7 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
624062
624618
  if (index.length > 50) {
624063
624619
  const removed = index.shift();
624064
624620
  try {
624065
- unlinkSync22(join135(sessDir, `${removed.id}.jsonl`));
624621
+ unlinkSync23(join135(sessDir, `${removed.id}.jsonl`));
624066
624622
  } catch {
624067
624623
  }
624068
624624
  }
@@ -624092,7 +624648,7 @@ function deleteSession(repoRoot, sessionId) {
624092
624648
  const indexPath = join135(sessDir, SESSIONS_INDEX);
624093
624649
  try {
624094
624650
  const contentPath = join135(sessDir, `${sessionId}.jsonl`);
624095
- if (existsSync120(contentPath)) unlinkSync22(contentPath);
624651
+ if (existsSync120(contentPath)) unlinkSync23(contentPath);
624096
624652
  if (existsSync120(indexPath)) {
624097
624653
  let index = JSON.parse(readFileSync98(indexPath, "utf-8"));
624098
624654
  index = index.filter((s2) => s2.id !== sessionId);
@@ -624430,7 +624986,7 @@ function firstMeaningfulLine(transcript) {
624430
624986
  }
624431
624987
  return "";
624432
624988
  }
624433
- function clamp8(value2, max) {
624989
+ function clamp9(value2, max) {
624434
624990
  const v = value2.replace(/\s+/g, " ").trim();
624435
624991
  return v.length > max ? v.slice(0, max - 1).trimEnd() + "…" : v;
624436
624992
  }
@@ -624438,8 +624994,8 @@ function deterministicSummary(transcript) {
624438
624994
  const first2 = firstMeaningfulLine(transcript);
624439
624995
  if (!first2) return { title: "Untitled session", summary: "Empty session." };
624440
624996
  const cleaned = first2.replace(TUI_MARKER_PREFIX, "").replace(/^[>›$#\s]+/, "").trim();
624441
- const title = clamp8(cleaned, TITLE_MAX);
624442
- return { title: title || "Untitled session", summary: clamp8(cleaned || first2, SUMMARY_MAX) };
624997
+ const title = clamp9(cleaned, TITLE_MAX);
624998
+ return { title: title || "Untitled session", summary: clamp9(cleaned || first2, SUMMARY_MAX) };
624443
624999
  }
624444
625000
  function parseSummaryReply(content) {
624445
625001
  if (!content) return null;
@@ -624491,8 +625047,8 @@ async function generateSessionSummary(args) {
624491
625047
  const parsed = parseSummaryReply(content);
624492
625048
  if (!parsed) return fallback;
624493
625049
  return {
624494
- title: clamp8(parsed.title, TITLE_MAX) || fallback.title,
624495
- summary: clamp8(parsed.summary, SUMMARY_MAX) || fallback.summary
625050
+ title: clamp9(parsed.title, TITLE_MAX) || fallback.title,
625051
+ summary: clamp9(parsed.summary, SUMMARY_MAX) || fallback.summary
624496
625052
  };
624497
625053
  } catch {
624498
625054
  return fallback;
@@ -625522,7 +626078,7 @@ __export(system_metrics_exports, {
625522
626078
  getInstantSnapshot: () => getInstantSnapshot,
625523
626079
  instantaneousCpuPct: () => instantaneousCpuPct
625524
626080
  });
625525
- import { loadavg as loadavg2, cpus as cpus4, totalmem as totalmem7, freemem as freemem6, platform as platform4 } from "node:os";
626081
+ import { loadavg as loadavg3, cpus as cpus5, totalmem as totalmem8, freemem as freemem7, platform as platform4 } from "node:os";
625526
626082
  import { exec as exec4 } from "node:child_process";
625527
626083
  import { readFile as readFile24 } from "node:fs/promises";
625528
626084
  function formatRate(bytesPerSec) {
@@ -625691,7 +626247,7 @@ function getInstantSnapshot() {
625691
626247
  function readCpuTimes() {
625692
626248
  let idle = 0;
625693
626249
  let total = 0;
625694
- for (const cpu of cpus4()) {
626250
+ for (const cpu of cpus5()) {
625695
626251
  const t2 = cpu.times;
625696
626252
  idle += t2.idle;
625697
626253
  total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
@@ -625710,13 +626266,13 @@ function instantaneousCpuPct() {
625710
626266
  return Math.max(0, Math.min(100, Math.round(usage * 100)));
625711
626267
  }
625712
626268
  function collectCpuRam() {
625713
- const cores = cpus4().length;
625714
- const cpuModel = cpus4()[0]?.model ?? "";
625715
- const totalMem = totalmem7();
625716
- const usedMem = totalMem - freemem6();
626269
+ const cores = cpus5().length;
626270
+ const cpuModel = cpus5()[0]?.model ?? "";
626271
+ const totalMem = totalmem8();
626272
+ const usedMem = totalMem - freemem7();
625717
626273
  let cpuUtil = instantaneousCpuPct();
625718
626274
  if (cpuUtil < 0) {
625719
- const [l1] = loadavg2();
626275
+ const [l1] = loadavg3();
625720
626276
  cpuUtil = Math.max(0, Math.min(100, Math.round(l1 / cores * 100)));
625721
626277
  }
625722
626278
  return {
@@ -633132,7 +633688,7 @@ import { spawn as spawn34, exec as exec5 } from "node:child_process";
633132
633688
  import { promisify as promisify7 } from "node:util";
633133
633689
  import { existsSync as existsSync126, writeFileSync as writeFileSync66, readFileSync as readFileSync104, appendFileSync as appendFileSync14, mkdirSync as mkdirSync78, chmodSync as chmodSync3 } from "node:fs";
633134
633690
  import { delimiter as pathDelimiter, join as join141 } from "node:path";
633135
- import { freemem as freemem7, homedir as homedir46, platform as platform5, totalmem as totalmem8 } from "node:os";
633691
+ import { freemem as freemem8, homedir as homedir46, platform as platform5, totalmem as totalmem9 } from "node:os";
633136
633692
  function wrapText2(value2, width) {
633137
633693
  const words = value2.split(/\s+/).filter(Boolean);
633138
633694
  const lines = [];
@@ -633245,8 +633801,8 @@ function parseRocmSmi(stdout) {
633245
633801
  return { total, free: Math.max(0, total - used), name: name10 ? `AMD ${name10}` : "AMD GPU" };
633246
633802
  }
633247
633803
  function detectSystemSpecs() {
633248
- let totalRamGB = totalmem8() / 1024 ** 3;
633249
- let availableRamGB = freemem7() / 1024 ** 3;
633804
+ let totalRamGB = totalmem9() / 1024 ** 3;
633805
+ let availableRamGB = freemem8() / 1024 ** 3;
633250
633806
  let gpuVramGB = 0;
633251
633807
  let availableVramGB = 0;
633252
633808
  const gpuName = "";
@@ -640027,7 +640583,7 @@ var init_audio_waveform = __esm({
640027
640583
  });
640028
640584
 
640029
640585
  // packages/cli/src/tui/neovim-mode.ts
640030
- import { existsSync as existsSync132, unlinkSync as unlinkSync24 } from "node:fs";
640586
+ import { existsSync as existsSync132, unlinkSync as unlinkSync25 } from "node:fs";
640031
640587
  import { tmpdir as tmpdir22 } from "node:os";
640032
640588
  import { join as join145 } from "node:path";
640033
640589
  function isNeovimActive() {
@@ -640076,7 +640632,7 @@ async function startNeovimMode(opts) {
640076
640632
  }
640077
640633
  const socketPath = join145(tmpdir22(), `omnius-nvim-${process.pid}-${Date.now()}.sock`);
640078
640634
  try {
640079
- if (existsSync132(socketPath)) unlinkSync24(socketPath);
640635
+ if (existsSync132(socketPath)) unlinkSync25(socketPath);
640080
640636
  } catch {
640081
640637
  }
640082
640638
  const ptyCols = opts.cols;
@@ -640465,7 +641021,7 @@ function doCleanup(state) {
640465
641021
  state.pty = null;
640466
641022
  }
640467
641023
  try {
640468
- if (existsSync132(state.socketPath)) unlinkSync24(state.socketPath);
641024
+ if (existsSync132(state.socketPath)) unlinkSync25(state.socketPath);
640469
641025
  } catch {
640470
641026
  }
640471
641027
  if (state.stdinHandler) {
@@ -640540,7 +641096,7 @@ __export(daemon_exports, {
640540
641096
  stopDaemon: () => stopDaemon
640541
641097
  });
640542
641098
  import { spawn as spawn35 } from "node:child_process";
640543
- import { existsSync as existsSync133, readFileSync as readFileSync108, writeFileSync as writeFileSync67, mkdirSync as mkdirSync79, unlinkSync as unlinkSync25, openSync as openSync3, closeSync as closeSync3 } from "node:fs";
641099
+ import { existsSync as existsSync133, readFileSync as readFileSync108, writeFileSync as writeFileSync67, mkdirSync as mkdirSync79, unlinkSync as unlinkSync26, openSync as openSync3, closeSync as closeSync3 } from "node:fs";
640544
641100
  import { join as join146 } from "node:path";
640545
641101
  import { homedir as homedir48 } from "node:os";
640546
641102
  import { fileURLToPath as fileURLToPath20 } from "node:url";
@@ -640616,7 +641172,7 @@ function getDaemonPid() {
640616
641172
  return pid;
640617
641173
  } catch {
640618
641174
  try {
640619
- unlinkSync25(PID_FILE2);
641175
+ unlinkSync26(PID_FILE2);
640620
641176
  } catch {
640621
641177
  }
640622
641178
  return null;
@@ -640732,13 +641288,13 @@ function stopDaemon() {
640732
641288
  }
640733
641289
  process.kill(pid, "SIGTERM");
640734
641290
  try {
640735
- unlinkSync25(PID_FILE2);
641291
+ unlinkSync26(PID_FILE2);
640736
641292
  } catch {
640737
641293
  }
640738
641294
  return true;
640739
641295
  } catch {
640740
641296
  try {
640741
- unlinkSync25(PID_FILE2);
641297
+ unlinkSync26(PID_FILE2);
640742
641298
  } catch {
640743
641299
  }
640744
641300
  return false;
@@ -640769,7 +641325,7 @@ async function forceKillDaemon(port) {
640769
641325
  } catch {
640770
641326
  }
640771
641327
  try {
640772
- unlinkSync25(PID_FILE2);
641328
+ unlinkSync26(PID_FILE2);
640773
641329
  } catch {
640774
641330
  }
640775
641331
  }
@@ -640824,7 +641380,7 @@ async function ensureDaemon() {
640824
641380
  } catch {
640825
641381
  }
640826
641382
  try {
640827
- unlinkSync25(PID_FILE2);
641383
+ unlinkSync26(PID_FILE2);
640828
641384
  } catch {
640829
641385
  }
640830
641386
  }
@@ -640841,7 +641397,7 @@ async function ensureDaemon() {
640841
641397
  } catch {
640842
641398
  }
640843
641399
  try {
640844
- unlinkSync25(PID_FILE2);
641400
+ unlinkSync26(PID_FILE2);
640845
641401
  } catch {
640846
641402
  }
640847
641403
  return false;
@@ -641304,7 +641860,7 @@ import {
641304
641860
  mkdirSync as mkdirSync80,
641305
641861
  chmodSync as chmodSync4,
641306
641862
  existsSync as existsSync136,
641307
- unlinkSync as unlinkSync26,
641863
+ unlinkSync as unlinkSync27,
641308
641864
  readdirSync as readdirSync44
641309
641865
  } from "node:fs";
641310
641866
  import { join as join149 } from "node:path";
@@ -641499,12 +642055,12 @@ function saveJobs(jobs) {
641499
642055
  const tmp = path12 + ".tmp";
641500
642056
  writeFileSync68(tmp, content, "utf-8");
641501
642057
  try {
641502
- unlinkSync26(path12);
642058
+ unlinkSync27(path12);
641503
642059
  } catch {
641504
642060
  }
641505
642061
  writeFileSync68(path12, content, "utf-8");
641506
642062
  try {
641507
- unlinkSync26(tmp);
642063
+ unlinkSync27(tmp);
641508
642064
  } catch {
641509
642065
  }
641510
642066
  secureFile(path12);
@@ -641853,7 +642409,7 @@ import {
641853
642409
  openSync as openSync5,
641854
642410
  closeSync as closeSync5,
641855
642411
  writeFileSync as writeFileSync69,
641856
- unlinkSync as unlinkSync27,
642412
+ unlinkSync as unlinkSync28,
641857
642413
  readFileSync as readFileSync110
641858
642414
  } from "node:fs";
641859
642415
  import { join as join150 } from "node:path";
@@ -641878,7 +642434,7 @@ function acquireTickLock() {
641878
642434
  if (age < 3e5) return false;
641879
642435
  }
641880
642436
  try {
641881
- unlinkSync27(lockPath);
642437
+ unlinkSync28(lockPath);
641882
642438
  } catch {
641883
642439
  }
641884
642440
  }
@@ -641895,7 +642451,7 @@ function acquireTickLock() {
641895
642451
  }
641896
642452
  function releaseTickLock() {
641897
642453
  try {
641898
- unlinkSync27(lockFilePath());
642454
+ unlinkSync28(lockFilePath());
641899
642455
  } catch {
641900
642456
  }
641901
642457
  }
@@ -643608,7 +644164,7 @@ import {
643608
644164
  mkdirSync as mkdirSync83,
643609
644165
  writeFileSync as writeFileSync71,
643610
644166
  readFileSync as readFileSync112,
643611
- unlinkSync as unlinkSync28,
644167
+ unlinkSync as unlinkSync29,
643612
644168
  readdirSync as readdirSync45,
643613
644169
  statSync as statSync52,
643614
644170
  copyFileSync as copyFileSync6,
@@ -645246,7 +645802,7 @@ except Exception as exc:
645246
645802
  const p2 = join152(luxttsCloneRefsDir(), filename);
645247
645803
  if (!existsSync139(p2)) return false;
645248
645804
  try {
645249
- unlinkSync28(p2);
645805
+ unlinkSync29(p2);
645250
645806
  const meta = this.loadCloneMeta();
645251
645807
  delete meta[filename];
645252
645808
  this.saveCloneMeta(meta);
@@ -645621,7 +646177,7 @@ except Exception as exc:
645621
646177
  }
645622
646178
  if (prefetchedWav) {
645623
646179
  try {
645624
- unlinkSync28(prefetchedWav.path);
646180
+ unlinkSync29(prefetchedWav.path);
645625
646181
  } catch {
645626
646182
  }
645627
646183
  }
@@ -645715,7 +646271,7 @@ except Exception as exc:
645715
646271
  this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
645716
646272
  await this.playWav(wavPath);
645717
646273
  try {
645718
- unlinkSync28(wavPath);
646274
+ unlinkSync29(wavPath);
645719
646275
  } catch {
645720
646276
  }
645721
646277
  }
@@ -646261,7 +646817,7 @@ except Exception as exc:
646261
646817
  if (!wavPath) return null;
646262
646818
  try {
646263
646819
  const data = readFileSync112(wavPath);
646264
- unlinkSync28(wavPath);
646820
+ unlinkSync29(wavPath);
646265
646821
  return data;
646266
646822
  } catch {
646267
646823
  return null;
@@ -646445,7 +647001,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
646445
647001
  }
646446
647002
  await this.playWav(wavPath);
646447
647003
  try {
646448
- unlinkSync28(wavPath);
647004
+ unlinkSync29(wavPath);
646449
647005
  } catch {
646450
647006
  }
646451
647007
  }
@@ -646489,7 +647045,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
646489
647045
  if (!existsSync139(wavPath)) return null;
646490
647046
  try {
646491
647047
  const data = readFileSync112(wavPath);
646492
- unlinkSync28(wavPath);
647048
+ unlinkSync29(wavPath);
646493
647049
  return data;
646494
647050
  } catch {
646495
647051
  return null;
@@ -647445,7 +648001,7 @@ if __name__ == '__main__':
647445
648001
  await this.playWav(wavPath);
647446
648002
  await this.sleep(150);
647447
648003
  try {
647448
- unlinkSync28(wavPath);
648004
+ unlinkSync29(wavPath);
647449
648005
  } catch {
647450
648006
  }
647451
648007
  }
@@ -647485,7 +648041,7 @@ if __name__ == '__main__':
647485
648041
  if (!existsSync139(wavPath)) return null;
647486
648042
  try {
647487
648043
  const data = readFileSync112(wavPath);
647488
- unlinkSync28(wavPath);
648044
+ unlinkSync29(wavPath);
647489
648045
  return data;
647490
648046
  } catch {
647491
648047
  return null;
@@ -647812,7 +648368,7 @@ if __name__ == "__main__":
647812
648368
  await this.playWav(wavPath);
647813
648369
  await this.sleep(150);
647814
648370
  try {
647815
- unlinkSync28(wavPath);
648371
+ unlinkSync29(wavPath);
647816
648372
  } catch {
647817
648373
  }
647818
648374
  }
@@ -647861,7 +648417,7 @@ if __name__ == "__main__":
647861
648417
  if (!existsSync139(wavPath)) return null;
647862
648418
  try {
647863
648419
  const data = readFileSync112(wavPath);
647864
- unlinkSync28(wavPath);
648420
+ unlinkSync29(wavPath);
647865
648421
  return data;
647866
648422
  } catch {
647867
648423
  return null;
@@ -658706,6 +659262,134 @@ async function chooseLiveDevice(ctx3, title, devices, activeKey) {
658706
659262
  if (!result.confirmed || !result.key) return null;
658707
659263
  return devices.find((device) => device.id === result.key) ?? null;
658708
659264
  }
659265
+ function liveCameraStreamSummary(manager, deviceId) {
659266
+ return `${manager.isCameraStreamEnabled(deviceId) ? liveEnabled(true) : liveEnabled(false)} · ${formatLiveCameraResolution(manager.getCameraStreamResolution(deviceId))} · ${formatCameraRotation(manager.getCameraRotation(deviceId))}`;
659267
+ }
659268
+ async function chooseLiveCameraResolution(ctx3, manager, deviceId) {
659269
+ const current = manager.getCameraStreamResolution(deviceId);
659270
+ const choices = ["640x480", "1280x720", "1920x1080", "2560x1440", "3840x2160", "native"];
659271
+ const result = await tuiSelect({
659272
+ items: choices.map((resolution) => ({
659273
+ key: resolution,
659274
+ label: formatLiveCameraResolution(resolution),
659275
+ detail: resolution === "native" ? "use camera native format; highest burden" : resolution === "1920x1080" ? "default balanced stream size" : "downscaled camera stream"
659276
+ })),
659277
+ title: `Camera Resolution — ${deviceId}`,
659278
+ activeKey: current,
659279
+ rl: ctx3.rl,
659280
+ availableRows: ctx3.availableContentRows?.()
659281
+ });
659282
+ if (!result.confirmed || !result.key) return null;
659283
+ return normalizeLiveCameraResolution(result.key);
659284
+ }
659285
+ async function showLiveCameraMenu(ctx3, manager, device) {
659286
+ while (true) {
659287
+ const selected = manager.getConfig().selectedCamera === device.id;
659288
+ const enabled2 = manager.isCameraStreamEnabled(device.id);
659289
+ const resolution = manager.getCameraStreamResolution(device.id);
659290
+ const items = [
659291
+ { key: "hdr:camera", label: selectColors.dim(`─── Camera ${device.id} ───`) },
659292
+ {
659293
+ key: "info:camera",
659294
+ label: selectColors.dim(` ${device.label}${device.detail ? ` · ${device.detail}` : ""}`)
659295
+ },
659296
+ {
659297
+ key: "select",
659298
+ label: selected ? "Selected Camera" : "Select Camera",
659299
+ detail: "make this the primary live camera"
659300
+ },
659301
+ {
659302
+ key: "toggle",
659303
+ label: enabled2 ? "Disable This Camera Stream" : "Enable This Camera Stream",
659304
+ detail: "disabled cameras stay available but do not consume ffmpeg/vision resources"
659305
+ },
659306
+ {
659307
+ key: "resolution",
659308
+ label: "Set Stream Resolution",
659309
+ detail: formatLiveCameraResolution(resolution)
659310
+ },
659311
+ {
659312
+ key: "preview",
659313
+ label: "Preview Camera",
659314
+ detail: "capture frame + ASCII preview"
659315
+ },
659316
+ {
659317
+ key: "infer",
659318
+ label: "Infer Camera Now",
659319
+ detail: "run bounded vision inference on this camera"
659320
+ },
659321
+ {
659322
+ key: "auto-orient",
659323
+ label: "Auto-Orient Camera",
659324
+ detail: "detect persistent rotation correction"
659325
+ },
659326
+ {
659327
+ key: "cycle-rotation",
659328
+ label: "Cycle Rotation",
659329
+ detail: formatCameraRotation(manager.getCameraRotation(device.id))
659330
+ },
659331
+ { key: "rotate-0", label: "Rotation: Upright", detail: "0 degrees" },
659332
+ { key: "rotate-90", label: "Rotation: Clockwise", detail: "90 degrees" },
659333
+ { key: "rotate-180", label: "Rotation: 180", detail: "upside down correction" },
659334
+ { key: "rotate-270", label: "Rotation: Counter-clockwise", detail: "270 degrees" }
659335
+ ];
659336
+ const result = await tuiSelect({
659337
+ items,
659338
+ title: `Live Camera — ${device.id}`,
659339
+ activeKey: selected ? "select" : enabled2 ? "toggle" : void 0,
659340
+ rl: ctx3.rl,
659341
+ availableRows: ctx3.availableContentRows?.(),
659342
+ skipKeys: liveSkipKeys(items)
659343
+ });
659344
+ if (!result.confirmed || !result.key) return;
659345
+ switch (result.key) {
659346
+ case "select":
659347
+ manager.configure({ selectedCamera: device.id, videoEnabled: true });
659348
+ manager.setCameraStreamEnabled(device.id, true);
659349
+ renderInfo(`Selected camera ${device.id}.`);
659350
+ continue;
659351
+ case "toggle":
659352
+ manager.setCameraStreamEnabled(device.id, !enabled2);
659353
+ renderInfo(`${!enabled2 ? "Enabled" : "Disabled"} camera stream ${device.id}.`);
659354
+ continue;
659355
+ case "resolution": {
659356
+ const next = await chooseLiveCameraResolution(ctx3, manager, device.id);
659357
+ if (next) {
659358
+ manager.setCameraStreamResolution(device.id, next);
659359
+ renderInfo(`Camera ${device.id} stream resolution set to ${formatLiveCameraResolution(next)}.`);
659360
+ }
659361
+ continue;
659362
+ }
659363
+ case "preview":
659364
+ renderLivePreview(await manager.previewCamera(device.id));
659365
+ continue;
659366
+ case "infer":
659367
+ manager.setCameraStreamEnabled(device.id, true);
659368
+ renderInfo(await manager.sampleCameraNow(device.id, true, { forceInferenceNow: true }));
659369
+ continue;
659370
+ case "auto-orient":
659371
+ renderInfo("Detecting camera orientation...");
659372
+ renderInfo(await manager.autoOrientCamera(device.id));
659373
+ continue;
659374
+ case "cycle-rotation": {
659375
+ const orientation = manager.cycleCameraRotation(device.id);
659376
+ renderInfo(orientation ? `Camera rotation set to ${formatCameraRotation(orientation.rotation)} for ${device.id}.` : "No camera selected.");
659377
+ continue;
659378
+ }
659379
+ case "rotate-0":
659380
+ case "rotate-90":
659381
+ case "rotate-180":
659382
+ case "rotate-270": {
659383
+ const rotation = normalizeLiveCameraRotation(result.key.replace("rotate-", ""));
659384
+ const orientation = manager.setCameraRotation(device.id, rotation, "manual", `/live camera menu ${result.key}`);
659385
+ renderInfo(orientation ? `Camera rotation set to ${formatCameraRotation(orientation.rotation)} for ${device.id}.` : "No camera selected.");
659386
+ continue;
659387
+ }
659388
+ default:
659389
+ return;
659390
+ }
659391
+ }
659392
+ }
658709
659393
  async function handleLiveCommand(ctx3, arg) {
658710
659394
  const manager = getLiveSensorManager(ctx3.repoRoot);
658711
659395
  attachLiveSinks(ctx3, manager);
@@ -658777,6 +659461,40 @@ async function handleLiveCommand(ctx3, arg) {
658777
659461
  }
658778
659462
  return;
658779
659463
  }
659464
+ if (sub2 === "resolution" || sub2 === "res" || sub2 === "size") {
659465
+ await ensureLiveInventory(manager);
659466
+ const tokens = parts.slice(1);
659467
+ const rawResolution = tokens.pop();
659468
+ if (!rawResolution) {
659469
+ renderWarning("Usage: /live resolution [camera] 720p|1080p|1440p|4k|native");
659470
+ return;
659471
+ }
659472
+ const device = tokens.join(" ") || manager.getConfig().selectedCamera;
659473
+ if (!device) {
659474
+ renderWarning("No camera selected. Use /live camera <device> first.");
659475
+ return;
659476
+ }
659477
+ try {
659478
+ const resolution = normalizeLiveCameraResolution(rawResolution);
659479
+ manager.setCameraStreamResolution(device, resolution);
659480
+ renderInfo(`Camera ${device} stream resolution set to ${formatLiveCameraResolution(resolution)}.`);
659481
+ } catch (err) {
659482
+ renderWarning(err instanceof Error ? err.message : String(err));
659483
+ }
659484
+ return;
659485
+ }
659486
+ if (sub2 === "camera-on" || sub2 === "camera-off" || sub2 === "camera-enable" || sub2 === "camera-disable") {
659487
+ await ensureLiveInventory(manager);
659488
+ const device = value2 || manager.getConfig().selectedCamera;
659489
+ if (!device) {
659490
+ renderWarning("No camera selected. Use /live camera <device> first.");
659491
+ return;
659492
+ }
659493
+ const enabled2 = sub2 === "camera-on" || sub2 === "camera-enable";
659494
+ manager.setCameraStreamEnabled(device, enabled2);
659495
+ renderInfo(`${enabled2 ? "Enabled" : "Disabled"} camera stream ${device}.`);
659496
+ return;
659497
+ }
658780
659498
  if (sub2 === "video") {
658781
659499
  const cfg = manager.getConfig();
658782
659500
  manager.configure({ videoEnabled: setBool(value2, !cfg.videoEnabled) });
@@ -658902,6 +659620,11 @@ async function showLiveMenu(ctx3, manager) {
658902
659620
  label: "Select Camera",
658903
659621
  detail: `${devices.video.length} device(s)`
658904
659622
  },
659623
+ ...devices.video.map((device, index) => ({
659624
+ key: `camera-device:${index}`,
659625
+ label: `Camera: ${device.id}`,
659626
+ detail: `${liveCameraStreamSummary(manager, device.id)} — ${device.label}${device.detail ? ` — ${device.detail}` : ""}`
659627
+ })),
658905
659628
  {
658906
659629
  key: "preview-camera",
658907
659630
  label: "View Selected Camera",
@@ -658996,6 +659719,12 @@ async function showLiveMenu(ctx3, manager) {
658996
659719
  }
658997
659720
  });
658998
659721
  if (!result.confirmed || !result.key) return;
659722
+ if (result.key.startsWith("camera-device:")) {
659723
+ const index = Number(result.key.slice("camera-device:".length));
659724
+ const device = devices.video[index];
659725
+ if (device) await showLiveCameraMenu(ctx3, manager, device);
659726
+ continue;
659727
+ }
658999
659728
  switch (result.key) {
659000
659729
  case "toggle-video":
659001
659730
  manager.configure({ videoEnabled: !cfg.videoEnabled });
@@ -663849,15 +664578,15 @@ function refreshLocalGpuMetricsIfStale() {
663849
664578
  });
663850
664579
  }
663851
664580
  function getLocalSystemMetrics() {
663852
- const cpus6 = nodeOs.cpus();
664581
+ const cpus7 = nodeOs.cpus();
663853
664582
  const loads = nodeOs.loadavg();
663854
664583
  const totalMem = nodeOs.totalmem();
663855
664584
  const freeMem = nodeOs.freemem();
663856
664585
  const usedMem = totalMem - freeMem;
663857
664586
  const result = {
663858
- cpuModel: cpus6[0]?.model?.trim() ?? "unknown",
663859
- cpuCores: cpus6.length,
663860
- cpuUtil: Math.min(100, Math.round(loads[0] / cpus6.length * 100)),
664587
+ cpuModel: cpus7[0]?.model?.trim() ?? "unknown",
664588
+ cpuCores: cpus7.length,
664589
+ cpuUtil: Math.min(100, Math.round(loads[0] / cpus7.length * 100)),
663861
664590
  memTotalGB: Math.round(totalMem / (1024 * 1024 * 1024) * 10) / 10,
663862
664591
  memUsedGB: Math.round(usedMem / (1024 * 1024 * 1024) * 10) / 10,
663863
664592
  memUtil: Math.round(usedMem / totalMem * 100),
@@ -665722,7 +666451,7 @@ import {
665722
666451
  writeFileSync as writeFileSync74,
665723
666452
  renameSync as renameSync13,
665724
666453
  mkdirSync as mkdirSync86,
665725
- unlinkSync as unlinkSync29,
666454
+ unlinkSync as unlinkSync30,
665726
666455
  appendFileSync as appendFileSync16
665727
666456
  } from "node:fs";
665728
666457
  import { join as join156, resolve as resolve64 } from "node:path";
@@ -665761,7 +666490,7 @@ function persistInFlight(j) {
665761
666490
  function deleteInFlightFile(id2) {
665762
666491
  try {
665763
666492
  const p2 = inFlightPath(id2);
665764
- if (existsSync143(p2)) unlinkSync29(p2);
666493
+ if (existsSync143(p2)) unlinkSync30(p2);
665765
666494
  } catch {
665766
666495
  }
665767
666496
  }
@@ -666147,7 +666876,7 @@ function drainCheckins(sessionId) {
666147
666876
  try {
666148
666877
  const raw = readFileSync116(fp, "utf-8");
666149
666878
  try {
666150
- unlinkSync29(fp);
666879
+ unlinkSync30(fp);
666151
666880
  } catch {
666152
666881
  }
666153
666882
  if (!raw.trim()) return [];
@@ -666195,7 +666924,7 @@ function deleteSession2(id2) {
666195
666924
  try {
666196
666925
  const p2 = sessionPath(id2);
666197
666926
  if (existsSync143(p2)) {
666198
- unlinkSync29(p2);
666927
+ unlinkSync30(p2);
666199
666928
  removed = true;
666200
666929
  }
666201
666930
  } catch {
@@ -671827,7 +672556,7 @@ var init_bless_engine = __esm({
671827
672556
  });
671828
672557
 
671829
672558
  // packages/cli/src/tui/dmn-engine.ts
671830
- import { existsSync as existsSync150, readFileSync as readFileSync122, writeFileSync as writeFileSync79, mkdirSync as mkdirSync92, readdirSync as readdirSync53, unlinkSync as unlinkSync30 } from "node:fs";
672559
+ import { existsSync as existsSync150, readFileSync as readFileSync122, writeFileSync as writeFileSync79, mkdirSync as mkdirSync92, readdirSync as readdirSync53, unlinkSync as unlinkSync31 } from "node:fs";
671831
672560
  import { join as join163, basename as basename36 } from "node:path";
671832
672561
  import { exec as exec6 } from "node:child_process";
671833
672562
  import { promisify as promisify8 } from "node:util";
@@ -672764,7 +673493,7 @@ If decision is GO, selectedTask MUST be a fully-populated object (NEVER null)
672764
673493
  for (const file of files) {
672765
673494
  if (!keep.has(file)) {
672766
673495
  try {
672767
- unlinkSync30(join163(this.historyDir, file));
673496
+ unlinkSync31(join163(this.historyDir, file));
672768
673497
  } catch {
672769
673498
  }
672770
673499
  }
@@ -672842,7 +673571,7 @@ function appraiseEvent(event) {
672842
673571
  return null;
672843
673572
  }
672844
673573
  }
672845
- function clamp9(value2, min, max) {
673574
+ function clamp10(value2, min, max) {
672846
673575
  return Math.max(min, Math.min(max, value2));
672847
673576
  }
672848
673577
  var BASELINE_VALENCE, BASELINE_AROUSAL, DECAY_HALF_LIFE_MS, LABEL_UPDATE_INTERVAL_MS, DISTRESS_THRESHOLD, REFLECTION_COOLDOWN_MS, REFLECTION_MIN_EVENTS, LABEL_REGEN_THRESHOLD, EmotionEngine;
@@ -672981,8 +673710,8 @@ var init_emotion_engine = __esm({
672981
673710
  if (this.consecutiveFailures >= 2) {
672982
673711
  momentum = 1 + (this.consecutiveFailures - 1) * 0.25;
672983
673712
  }
672984
- this.state.valence = clamp9(this.state.valence + delta.valence * momentum, -1, 1);
672985
- this.state.arousal = clamp9(this.state.arousal + delta.arousal * momentum, 0, 1);
673713
+ this.state.valence = clamp10(this.state.valence + delta.valence * momentum, -1, 1);
673714
+ this.state.arousal = clamp10(this.state.arousal + delta.arousal * momentum, 0, 1);
672986
673715
  this.state.updatedAt = Date.now();
672987
673716
  const deterministicLabel = labelFromCoordinates(this.state.valence, this.state.arousal);
672988
673717
  this.state.label = deterministicLabel.label;
@@ -674567,7 +675296,7 @@ import {
674567
675296
  mkdirSync as mkdirSync93,
674568
675297
  readFileSync as readFileSync123,
674569
675298
  statSync as statSync55,
674570
- unlinkSync as unlinkSync31,
675299
+ unlinkSync as unlinkSync32,
674571
675300
  writeFileSync as writeFileSync80
674572
675301
  } from "node:fs";
674573
675302
  import { mkdir as mkdir22 } from "node:fs/promises";
@@ -674820,7 +675549,7 @@ function scopedTool(base3, root, mode) {
674820
675549
  }
674821
675550
  } else if (restoredEditPath) {
674822
675551
  try {
674823
- unlinkSync31(restoredEditPath);
675552
+ unlinkSync32(restoredEditPath);
674824
675553
  } catch {
674825
675554
  }
674826
675555
  }
@@ -674965,7 +675694,7 @@ function rememberCreated(root, absPath) {
674965
675694
  const previousPath = resolve66(root, previous.storedRel);
674966
675695
  if (isInside(resolve66(root), previousPath) && existsSync151(previousPath)) {
674967
675696
  try {
674968
- unlinkSync31(previousPath);
675697
+ unlinkSync32(previousPath);
674969
675698
  } catch {
674970
675699
  }
674971
675700
  }
@@ -674985,7 +675714,7 @@ function rememberCreated(root, absPath) {
674985
675714
  const storedAbs = join164(root, storedRel);
674986
675715
  writeFileSync80(storedAbs, Buffer.concat([prefix, encrypted]));
674987
675716
  try {
674988
- unlinkSync31(guarded.path.abs);
675717
+ unlinkSync32(guarded.path.abs);
674989
675718
  } catch {
674990
675719
  }
674991
675720
  manifest.objects = manifest.objects || {};
@@ -675063,7 +675792,7 @@ function materializeTelegramCreativeArtifactForSend(root, rawPath) {
675063
675792
  path: staged,
675064
675793
  cleanup: () => {
675065
675794
  try {
675066
- unlinkSync31(staged);
675795
+ unlinkSync32(staged);
675067
675796
  } catch {
675068
675797
  }
675069
675798
  }
@@ -676000,7 +676729,7 @@ import {
676000
676729
  readdirSync as readdirSync54,
676001
676730
  readFileSync as readFileSync124,
676002
676731
  writeFileSync as writeFileSync81,
676003
- unlinkSync as unlinkSync32
676732
+ unlinkSync as unlinkSync33
676004
676733
  } from "node:fs";
676005
676734
  import { join as join165 } from "node:path";
676006
676735
  import { createHash as createHash39 } from "node:crypto";
@@ -676738,7 +677467,7 @@ function pruneTelegramChannelDaydreams(repoRoot, sessionKey, keep = DAYDREAM_ART
676738
677467
  let removed = 0;
676739
677468
  for (const file of toRemove) {
676740
677469
  try {
676741
- unlinkSync32(join165(dir, file));
677470
+ unlinkSync33(join165(dir, file));
676742
677471
  removed++;
676743
677472
  } catch {
676744
677473
  }
@@ -678505,7 +679234,7 @@ __export(vision_ingress_exports, {
678505
679234
  resolveVisionModel: () => resolveVisionModel,
678506
679235
  runVisionIngress: () => runVisionIngress
678507
679236
  });
678508
- import { existsSync as existsSync153, readFileSync as readFileSync125, unlinkSync as unlinkSync33 } from "node:fs";
679237
+ import { existsSync as existsSync153, readFileSync as readFileSync125, unlinkSync as unlinkSync34 } from "node:fs";
678509
679238
  import { join as join166 } from "node:path";
678510
679239
  async function isTesseractAvailable() {
678511
679240
  try {
@@ -678563,7 +679292,7 @@ async function advancedOcr(imagePath) {
678563
679292
  const text2 = readFileSync125(txtFile, "utf-8").trim();
678564
679293
  if (text2.length > 0) results.push(text2);
678565
679294
  try {
678566
- unlinkSync33(txtFile);
679295
+ unlinkSync34(txtFile);
678567
679296
  } catch {
678568
679297
  }
678569
679298
  }
@@ -678742,7 +679471,7 @@ var init_vision_ingress = __esm({
678742
679471
  import {
678743
679472
  mkdirSync as mkdirSync95,
678744
679473
  existsSync as existsSync154,
678745
- unlinkSync as unlinkSync34,
679474
+ unlinkSync as unlinkSync35,
678746
679475
  readdirSync as readdirSync55,
678747
679476
  statSync as statSync56,
678748
679477
  readFileSync as readFileSync126,
@@ -689795,7 +690524,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
689795
690524
  if (prior.pid !== process.pid) return;
689796
690525
  } catch {
689797
690526
  }
689798
- unlinkSync34(lockFile);
690527
+ unlinkSync35(lockFile);
689799
690528
  } catch {
689800
690529
  }
689801
690530
  }
@@ -696351,7 +697080,7 @@ ${text2}`.trim()
696351
697080
  for (const [key, entry] of this.mediaCache) {
696352
697081
  if (now2 - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
696353
697082
  try {
696354
- unlinkSync34(entry.localPath);
697083
+ unlinkSync35(entry.localPath);
696355
697084
  } catch {
696356
697085
  }
696357
697086
  this.mediaCache.delete(key);
@@ -697801,6 +698530,7 @@ var init_voicechat = __esm({
697801
698530
  "packages/cli/src/tui/voicechat.ts"() {
697802
698531
  "use strict";
697803
698532
  init_conversation_context();
698533
+ init_live_resource_arbiter();
697804
698534
  VAD_SILENCE_MS = 3e3;
697805
698535
  MAX_SEGMENT_MS = 6500;
697806
698536
  SUMMARY_INJECTION_INTERVAL = 4;
@@ -697856,6 +698586,7 @@ Rules:
697856
698586
  lastSignalScore = null;
697857
698587
  listenPausedForResponse = false;
697858
698588
  lastAgentSpeech = null;
698589
+ liveResourceLease = null;
697859
698590
  // Abort control for inference
697860
698591
  abortController = null;
697861
698592
  // Callbacks
@@ -697907,9 +698638,45 @@ Rules:
697907
698638
  if (this._state === next) return;
697908
698639
  const prev = this._state;
697909
698640
  this._state = next;
698641
+ this.updateLiveResourceLease(next);
697910
698642
  this.onStateChange(next);
697911
698643
  this.emit("stateChange", { from: prev, to: next });
697912
698644
  }
698645
+ updateLiveResourceLease(state) {
698646
+ if (state === "CAPTURING") {
698647
+ this.holdLiveResources("asr-capture", 92, 1e4, "voicechat ASR capture");
698648
+ return;
698649
+ }
698650
+ if (state === "TRANSCRIBING") {
698651
+ this.holdLiveResources("asr-final", 94, 18e3, "voicechat final ASR/transcript handoff");
698652
+ return;
698653
+ }
698654
+ if (state === "THINKING") {
698655
+ this.holdLiveResources("voice-llm", 100, 6e4, "voicechat live LLM inference");
698656
+ return;
698657
+ }
698658
+ if (state === "SPEAKING") {
698659
+ this.holdLiveResources("tts", 84, 24e3, "voicechat TTS playback/echo guard");
698660
+ return;
698661
+ }
698662
+ if (state === "IDLE" || state === "LISTENING") {
698663
+ this.releaseLiveResources();
698664
+ }
698665
+ }
698666
+ holdLiveResources(owner, priority, ttlMs, reason) {
698667
+ this.liveResourceLease?.release();
698668
+ this.liveResourceLease = getLiveResourceArbiter().claim({
698669
+ owner: `voicechat:${owner}`,
698670
+ priority,
698671
+ ttlMs,
698672
+ reason,
698673
+ suppress: ["vision"]
698674
+ });
698675
+ }
698676
+ releaseLiveResources() {
698677
+ this.liveResourceLease?.release();
698678
+ this.liveResourceLease = null;
698679
+ }
697913
698680
  // ---------------------------------------------------------------------------
697914
698681
  // Start / Stop
697915
698682
  // ---------------------------------------------------------------------------
@@ -698019,6 +698786,7 @@ Rules:
698019
698786
  await this.listen.stop();
698020
698787
  } catch {
698021
698788
  }
698789
+ this.releaseLiveResources();
698022
698790
  this.setState("IDLE");
698023
698791
  if (this.verbose) this.onStatus("VoiceChat ended");
698024
698792
  this.emit("stopped");
@@ -698037,6 +698805,12 @@ Rules:
698037
698805
  this.emit("voiceEchoFiltered", echo);
698038
698806
  return;
698039
698807
  }
698808
+ this.holdLiveResources(
698809
+ isFinal ? "asr-final" : "asr-capture",
698810
+ isFinal ? 94 : 92,
698811
+ isFinal ? 18e3 : 1e4,
698812
+ isFinal ? "voicechat final ASR incoming" : "voicechat partial ASR incoming"
698813
+ );
698040
698814
  if (this._state === "LISTENING") {
698041
698815
  this.setState("CAPTURING");
698042
698816
  this.resetCaptureState();
@@ -699957,7 +700731,7 @@ var init_access_policy = __esm({
699957
700731
 
699958
700732
  // packages/cli/src/api/project-preferences.ts
699959
700733
  import { createHash as createHash43 } from "node:crypto";
699960
- import { existsSync as existsSync156, mkdirSync as mkdirSync97, readFileSync as readFileSync128, renameSync as renameSync15, writeFileSync as writeFileSync84, unlinkSync as unlinkSync35 } from "node:fs";
700734
+ import { existsSync as existsSync156, mkdirSync as mkdirSync97, readFileSync as readFileSync128, renameSync as renameSync15, writeFileSync as writeFileSync84, unlinkSync as unlinkSync36 } from "node:fs";
699961
700735
  import { homedir as homedir57 } from "node:os";
699962
700736
  import { join as join169, resolve as resolve69 } from "node:path";
699963
700737
  import { randomUUID as randomUUID20 } from "node:crypto";
@@ -700018,7 +700792,7 @@ function writeProjectPreferences(root, partial) {
700018
700792
  } catch {
700019
700793
  }
700020
700794
  try {
700021
- unlinkSync35(tmp);
700795
+ unlinkSync36(tmp);
700022
700796
  } catch {
700023
700797
  }
700024
700798
  throw err;
@@ -700029,7 +700803,7 @@ function deleteProjectPreferences(root) {
700029
700803
  try {
700030
700804
  const file = prefsPath(root);
700031
700805
  if (!existsSync156(file)) return false;
700032
- unlinkSync35(file);
700806
+ unlinkSync36(file);
700033
700807
  return true;
700034
700808
  } catch {
700035
700809
  return false;
@@ -718980,7 +719754,7 @@ import {
718980
719754
  existsSync as existsSync168,
718981
719755
  watch as fsWatch4,
718982
719756
  renameSync as renameSync17,
718983
- unlinkSync as unlinkSync36,
719757
+ unlinkSync as unlinkSync37,
718984
719758
  statSync as statSync62,
718985
719759
  openSync as openSync6,
718986
719760
  readSync as readSync2,
@@ -720315,13 +721089,13 @@ function pruneOldJobs() {
720315
721089
  const ts = ageRef ? Date.parse(ageRef) : NaN;
720316
721090
  if (Number.isFinite(ts) && ts < cutoffMs) {
720317
721091
  try {
720318
- unlinkSync36(path12);
721092
+ unlinkSync37(path12);
720319
721093
  } catch {
720320
721094
  }
720321
721095
  const outFile = path12.replace(/\.json$/, ".output");
720322
721096
  if (existsSync168(outFile)) {
720323
721097
  try {
720324
- unlinkSync36(outFile);
721098
+ unlinkSync37(outFile);
720325
721099
  } catch {
720326
721100
  }
720327
721101
  }
@@ -720331,7 +721105,7 @@ function pruneOldJobs() {
720331
721105
  }
720332
721106
  } catch {
720333
721107
  try {
720334
- unlinkSync36(path12);
721108
+ unlinkSync37(path12);
720335
721109
  pruned++;
720336
721110
  } catch {
720337
721111
  }
@@ -720643,7 +721417,7 @@ function atomicJobWrite(dir, id2, job) {
720643
721417
  } catch {
720644
721418
  }
720645
721419
  try {
720646
- unlinkSync36(tmpPath);
721420
+ unlinkSync37(tmpPath);
720647
721421
  } catch {
720648
721422
  }
720649
721423
  }
@@ -724824,7 +725598,7 @@ async function handleRequest(req3, res, ollamaUrl, verbose, runtimeDefaults = {}
724824
725598
  return;
724825
725599
  }
724826
725600
  const { tmpdir: tmpdir26 } = await import("node:os");
724827
- const { writeFileSync: writeFileSync95, unlinkSync: unlinkSync37 } = await import("node:fs");
725601
+ const { writeFileSync: writeFileSync95, unlinkSync: unlinkSync38 } = await import("node:fs");
724828
725602
  const { join: pjoin } = await import("node:path");
724829
725603
  const tmpPath = pjoin(
724830
725604
  tmpdir26(),
@@ -724842,7 +725616,7 @@ async function handleRequest(req3, res, ollamaUrl, verbose, runtimeDefaults = {}
724842
725616
  });
724843
725617
  } finally {
724844
725618
  try {
724845
- unlinkSync37(tmpPath);
725619
+ unlinkSync38(tmpPath);
724846
725620
  } catch {
724847
725621
  }
724848
725622
  }
@@ -728085,8 +728859,8 @@ function startApiServer(options2 = {}) {
728085
728859
  job.startedAt ?? job.completedAt ?? 0
728086
728860
  ).getTime();
728087
728861
  if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
728088
- const { unlinkSync: unlinkSync37 } = require4("node:fs");
728089
- unlinkSync37(jobPath);
728862
+ const { unlinkSync: unlinkSync38 } = require4("node:fs");
728863
+ unlinkSync38(jobPath);
728090
728864
  }
728091
728865
  } catch {
728092
728866
  }
@@ -737290,11 +738064,21 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
737290
738064
  voiceEngine.synthesizeToPCM(text2).then((result) => {
737291
738065
  if (result && session?.isActive) {
737292
738066
  const { pcm, sampleRate } = result;
738067
+ const durationMs = pcm.length / 2 / sampleRate * 1e3;
738068
+ const ttsLease = getLiveResourceArbiter().claim({
738069
+ owner: `call-tts:${id2}`,
738070
+ priority: 84,
738071
+ ttlMs: Math.min(45e3, durationMs + 3e3),
738072
+ reason: "cloud call TTS playback/echo guard",
738073
+ suppress: ["vision"]
738074
+ });
737293
738075
  session.sendSpeakingStateToClient(id2, true);
737294
738076
  session.sendAudioToClient(id2, pcm, sampleRate);
737295
- const durationMs = pcm.length / 2 / sampleRate * 1e3;
737296
738077
  setTimeout(
737297
- () => session.sendSpeakingStateToClient(id2, false),
738078
+ () => {
738079
+ session.sendSpeakingStateToClient(id2, false);
738080
+ ttsLease.release();
738081
+ },
737298
738082
  durationMs
737299
738083
  );
737300
738084
  }
@@ -737340,6 +738124,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
737340
738124
  () => renderVoiceSessionTranscript("user", text2)
737341
738125
  );
737342
738126
  voiceSession?.sendTranscript("user", text2);
738127
+ getLiveResourceArbiter().claim({
738128
+ owner: "call-asr",
738129
+ priority: 92,
738130
+ ttlMs: 35e3,
738131
+ reason: "cloud call ASR accepted; reserving compute for call-agent inference",
738132
+ suppress: ["vision"]
738133
+ });
737343
738134
  for (const [clientId, agent] of callSubAgents) {
737344
738135
  agent.handleTranscript(text2);
737345
738136
  }
@@ -737406,10 +738197,20 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
737406
738197
  const session = voiceSession;
737407
738198
  voiceEngine.onPCMOutput = (pcm, sampleRate) => {
737408
738199
  if (session?.isActive) {
738200
+ const durationMs = pcm.length / 2 / sampleRate * 1e3;
738201
+ const ttsLease = getLiveResourceArbiter().claim({
738202
+ owner: "call-broadcast-tts",
738203
+ priority: 84,
738204
+ ttlMs: Math.min(45e3, durationMs + 3e3),
738205
+ reason: "cloud call broadcast TTS playback/echo guard",
738206
+ suppress: ["vision"]
738207
+ });
737409
738208
  session.sendSpeakingState(true);
737410
738209
  session.sendAudioToClients(pcm, sampleRate);
737411
- const durationMs = pcm.length / 2 / sampleRate * 1e3;
737412
- setTimeout(() => session.sendSpeakingState(false), durationMs);
738210
+ setTimeout(() => {
738211
+ session.sendSpeakingState(false);
738212
+ ttsLease.release();
738213
+ }, durationMs);
737413
738214
  }
737414
738215
  };
737415
738216
  }
@@ -740006,6 +740807,7 @@ var init_interactive = __esm({
740006
740807
  init_expose();
740007
740808
  init_p2p();
740008
740809
  init_call_agent();
740810
+ init_live_resource_arbiter();
740009
740811
  init_config();
740010
740812
  init_secret_redactor();
740011
740813
  init_profiles();