omnius 1.0.428 → 1.0.429

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
@@ -603651,6 +603651,7 @@ var init_listen = __esm({
603651
603651
  case "vad": {
603652
603652
  lastHardwareVadAt = Date.now();
603653
603653
  const doa = Number(evt.doa);
603654
+ this.emit("status", `Whisper VAD: ${evt.speech === true ? "speech" : "silence"}`);
603654
603655
  updateListenLiveState({
603655
603656
  speechActive: evt.speech === true,
603656
603657
  doa: Number.isFinite(doa) ? doa : null
@@ -606474,6 +606475,7 @@ var init_live_sensors = __esm({
606474
606475
  previewTickInFlight = false;
606475
606476
  lastStreamFrameMtime = /* @__PURE__ */ new Map();
606476
606477
  lastStreamPersistAt = 0;
606478
+ videoGeneration = 0;
606477
606479
  videoInFlight = false;
606478
606480
  audioInFlight = false;
606479
606481
  audioActivityInFlight = false;
@@ -606676,7 +606678,12 @@ var init_live_sensors = __esm({
606676
606678
  const next = (current + delta) % 360;
606677
606679
  return this.setCameraRotation(device, next, "manual", `manual ${direction === "cw" ? "clockwise" : "counter-clockwise"} dashboard override`);
606678
606680
  }
606681
+ isVideoWorkCurrent(generation) {
606682
+ return this.config.videoEnabled && generation === this.videoGeneration;
606683
+ }
606679
606684
  async autoOrientCamera(device = this.config.selectedCamera, options2 = {}) {
606685
+ const generation = this.videoGeneration;
606686
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
606680
606687
  const target = device || this.config.selectedCamera || firstDeviceId(this.devices.video);
606681
606688
  if (!target) return "No camera selected. Use /live camera <device> or select a camera in /live.";
606682
606689
  if (options2.onlyIfUnset && this.getCameraOrientation(target)) {
@@ -606693,17 +606700,20 @@ var init_live_sensors = __esm({
606693
606700
  framePath = streamFrame.path;
606694
606701
  }
606695
606702
  if (!framePath) {
606703
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
606696
606704
  const captured = await new CameraCaptureTool().execute({
606697
606705
  action: "capture",
606698
606706
  device: target,
606699
606707
  rotate_degrees: 0
606700
606708
  });
606709
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
606701
606710
  if (!captured.success) {
606702
606711
  return `Camera orientation detection could not capture ${target}: ${captured.error || captured.output || "unknown error"}`;
606703
606712
  }
606704
606713
  framePath = extractSavedImagePath(captured.output, this.repoRoot);
606705
606714
  }
606706
606715
  if (!framePath) return `Camera orientation detection captured ${target}, but no frame path was returned.`;
606716
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
606707
606717
  const cvScores = await scoreCameraOrientationWithOpenCv(framePath);
606708
606718
  const cvDecision = cvScores ? chooseCameraOrientationFromScores(cvScores) : null;
606709
606719
  const prompt = [
@@ -606721,6 +606731,7 @@ var init_live_sensors = __esm({
606721
606731
  prompt,
606722
606732
  model: "moondream3-preview"
606723
606733
  });
606734
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
606724
606735
  if (!vision.success) {
606725
606736
  if (cvDecision) {
606726
606737
  const orientation2 = this.setCameraRotation(target, cvDecision.rotation, "auto", cvDecision.reason, cvDecision.confidence);
@@ -606774,12 +606785,18 @@ var init_live_sensors = __esm({
606774
606785
  return this.devices;
606775
606786
  }
606776
606787
  configure(patch) {
606788
+ const wasVideoEnabled = this.config.videoEnabled;
606777
606789
  this.config = {
606778
606790
  ...this.config,
606779
606791
  ...patch,
606780
606792
  videoIntervalMs: Math.max(MIN_VIDEO_INTERVAL_MS, Number(patch.videoIntervalMs ?? this.config.videoIntervalMs)),
606781
606793
  audioIntervalMs: Math.max(MIN_AUDIO_INTERVAL_MS, Number(patch.audioIntervalMs ?? this.config.audioIntervalMs))
606782
606794
  };
606795
+ if (wasVideoEnabled && !this.config.videoEnabled) {
606796
+ this.videoGeneration++;
606797
+ this.lastStreamFrameMtime.clear();
606798
+ this.cameraStreamers?.stopAll();
606799
+ }
606783
606800
  this.persist();
606784
606801
  this.clearLoopTimers();
606785
606802
  this.ensureLoops();
@@ -606858,6 +606875,8 @@ var init_live_sensors = __esm({
606858
606875
  return options2.agent ? "Live PFC run enabled: visual/audio feedback is active and significant events can launch background agent review." : "Live run enabled: visual/audio feedback is active and live context will update each turn.";
606859
606876
  }
606860
606877
  async previewCamera(device = this.config.selectedCamera, options2 = {}) {
606878
+ const generation = options2.generation ?? this.videoGeneration;
606879
+ if (!this.isVideoWorkCurrent(generation)) return { ok: false, message: "Video context is disabled." };
606861
606880
  const source = device || firstDeviceId(this.devices.video);
606862
606881
  if (!source) return { ok: false, message: "No camera selected. Use /live to select a camera after device discovery." };
606863
606882
  const orientation = this.getCameraOrientation(source);
@@ -606867,6 +606886,7 @@ var init_live_sensors = __esm({
606867
606886
  const displayPath2 = relative11(this.repoRoot, streamFrame.path).startsWith("..") ? streamFrame.path : relative11(this.repoRoot, streamFrame.path);
606868
606887
  const previewWidth2 = Math.max(42, Math.min(120, Math.floor(Number(options2.previewWidth ?? (process.stdout.columns || 100) - 14))));
606869
606888
  const preview2 = await buildImageAsciiPreview(streamFrame.path, { width: previewWidth2 });
606889
+ if (!this.isVideoWorkCurrent(generation)) return { ok: false, message: "Video context is disabled." };
606870
606890
  if (preview2?.ascii || preview2?.plainAscii) {
606871
606891
  const observedAt2 = Date.now();
606872
606892
  const cameraView2 = {
@@ -606909,6 +606929,7 @@ var init_live_sensors = __esm({
606909
606929
  device: source,
606910
606930
  rotate_degrees: rotation
606911
606931
  });
606932
+ if (!this.isVideoWorkCurrent(generation)) return { ok: false, message: "Video context is disabled." };
606912
606933
  if (!result.success) {
606913
606934
  const error = result.error || result.output || "camera capture failed";
606914
606935
  const observedAt2 = Date.now();
@@ -606953,6 +606974,7 @@ var init_live_sensors = __esm({
606953
606974
  const displayPath = relative11(this.repoRoot, framePath).startsWith("..") ? framePath : relative11(this.repoRoot, framePath);
606954
606975
  const previewWidth = Math.max(42, Math.min(120, Math.floor(Number(options2.previewWidth ?? (process.stdout.columns || 100) - 14))));
606955
606976
  const preview = await buildImageAsciiPreview(framePath, { width: previewWidth });
606977
+ if (!this.isVideoWorkCurrent(generation)) return { ok: false, message: "Video context is disabled." };
606956
606978
  const asciiContext = preview ? formatImageAsciiContext(preview, displayPath) : void 0;
606957
606979
  const observedAt = Date.now();
606958
606980
  const cameraView = {
@@ -607061,7 +607083,10 @@ var init_live_sensors = __esm({
607061
607083
  }
607062
607084
  }
607063
607085
  async sampleSingleVideoNow(source, forceInfer, previewWidth, options2 = {}) {
607064
- const preview = await this.previewCamera(source, { emit: false, previewWidth });
607086
+ const generation = options2.generation ?? this.videoGeneration;
607087
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607088
+ const preview = await this.previewCamera(source, { emit: false, previewWidth, generation });
607089
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607065
607090
  void this.runLiveVlm(source, preview.ok ? preview.framePath : void 0).catch(() => {
607066
607091
  });
607067
607092
  let inference = "";
@@ -607096,6 +607121,7 @@ var init_live_sensors = __esm({
607096
607121
  crop_faces: true,
607097
607122
  recognize_faces: true
607098
607123
  });
607124
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607099
607125
  inference = result.success ? String(result.output || result.llmContent || "") : `Video inference failed: ${result.error || result.output || "unknown error"}`;
607100
607126
  const livePayload = result.success ? parseLiveMediaPayload(result.llmContent || result.output) : null;
607101
607127
  if (livePayload) livePayload.source = source;
@@ -607168,6 +607194,7 @@ var init_live_sensors = __esm({
607168
607194
  if (this.config.clipEnabled && preview.ok && preview.framePath && source && sampledAt - lastClip >= 5e3) {
607169
607195
  this.lastClipAt.set(source, sampledAt);
607170
607196
  clipSummary = await this.recognizeFrameObjects(preview.framePath, source, sampledAt, { emit: false });
607197
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607171
607198
  const current = this.snapshot.cameras?.[source];
607172
607199
  if (current) {
607173
607200
  const clipLine = formatClipDashboardSummary(clipSummary);
@@ -607196,9 +607223,12 @@ ${clipSummary}` : ""].filter(Boolean).join("\n");
607196
607223
  return result;
607197
607224
  }
607198
607225
  async sampleVideoNow(forceInfer = this.config.inferEnabled, options2 = {}) {
607226
+ const generation = options2.generation ?? this.videoGeneration;
607227
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607199
607228
  if (this.videoInFlight) return "Video sampler is already running.";
607200
607229
  this.videoInFlight = true;
607201
607230
  try {
607231
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607202
607232
  const allSources = this.activeVideoSources();
607203
607233
  if (allSources.length === 0) return "No camera selected. Use /live refresh after connecting hardware.";
607204
607234
  const sources = options2.mode === "round-robin" ? [allSources[this.nextVideoSourceIndex++ % allSources.length]] : allSources;
@@ -607206,8 +607236,10 @@ ${clipSummary}` : ""].filter(Boolean).join("\n");
607206
607236
  const outputs = [];
607207
607237
  const previewWidth = liveDashboardPreviewWidthForSources(allSources.length);
607208
607238
  for (const source of sources) {
607209
- outputs.push(await this.sampleSingleVideoNow(source, forceInfer, previewWidth, options2));
607239
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607240
+ outputs.push(await this.sampleSingleVideoNow(source, forceInfer, previewWidth, { ...options2, generation }));
607210
607241
  }
607242
+ if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
607211
607243
  this.emitDashboard();
607212
607244
  return outputs.map((output, index) => `## Camera ${sources[index]}
607213
607245
  ${output}`).join("\n\n");
@@ -737161,7 +737193,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
737161
737193
  statusBar.setMicActivity(evt.speechActive, evt.levelDb);
737162
737194
  });
737163
737195
  listenEng.on("info", (msg) => {
737164
- if (/consensus rejected|loading whisper|whisper model loaded/i.test(msg)) {
737196
+ if (/consensus rejected|loading whisper|whisper model loaded|Whisper VAD|no accepted speech text|very short utterance/i.test(msg)) {
737165
737197
  writeContent(() => renderInfo(`[voicechat/asr] ${msg}`));
737166
737198
  }
737167
737199
  });
@@ -443,13 +443,18 @@ def main():
443
443
  result = run_transcribe(model, amplify(samples))
444
444
  text = _segment_filtered_text(result)
445
445
  if text:
446
- emit_transcript(text, is_final=False, consensus=False)
446
+ emit_transcript(
447
+ text,
448
+ is_final=False,
449
+ consensus=False if consensus_model is not None else None,
450
+ )
447
451
  except Exception as e:
448
452
  emit_error(f"Transcription error: {e}")
449
453
 
450
454
  def transcribe_final(samples):
451
455
  nonlocal last_final_text
452
456
  if len(samples) < int(0.4 * SAMPLE_RATE):
457
+ emit_status("Whisper ignored very short utterance.")
453
458
  return
454
459
  samples = amplify(samples)
455
460
  try:
@@ -466,6 +471,7 @@ def main():
466
471
 
467
472
  text = _segment_filtered_text(result)
468
473
  if not text:
474
+ emit_status("Whisper final produced no accepted speech text.")
469
475
  return
470
476
  if secondary is not None:
471
477
  secondary_text = _segment_filtered_text(secondary)
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.428",
3
+ "version": "1.0.429",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.428",
9
+ "version": "1.0.429",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.428",
3
+ "version": "1.0.429",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",