omnius 1.0.430 → 1.0.432
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 +1133 -250
- package/dist/scripts/live-whisper.py +78 -11
- package/npm-shrinkwrap.json +5 -5
- package/package.json +1 -1
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
|
|
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 (
|
|
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 (
|
|
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) {
|
|
@@ -37242,11 +37242,11 @@ function deleteCustomToolDefinition(name10, scope, repoRoot) {
|
|
|
37242
37242
|
const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
|
|
37243
37243
|
const filePath = join35(dir, `${name10}.json`);
|
|
37244
37244
|
if (existsSync33(filePath)) {
|
|
37245
|
-
const { unlinkSync:
|
|
37246
|
-
|
|
37245
|
+
const { unlinkSync: unlinkSync38 } = __require("node:fs");
|
|
37246
|
+
unlinkSync38(filePath);
|
|
37247
37247
|
const docsPath = toolDocsPath(name10, scope, repoRoot);
|
|
37248
37248
|
if (existsSync33(docsPath))
|
|
37249
|
-
|
|
37249
|
+
unlinkSync38(docsPath);
|
|
37250
37250
|
if (scope === "project" && repoRoot)
|
|
37251
37251
|
writeCustomToolRegistry(repoRoot);
|
|
37252
37252
|
return true;
|
|
@@ -96067,13 +96067,13 @@ var require_singleton = __commonJS({
|
|
|
96067
96067
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
96068
96068
|
var injectable_1 = require_injectable();
|
|
96069
96069
|
var dependency_container_1 = require_dependency_container();
|
|
96070
|
-
function
|
|
96070
|
+
function singleton2() {
|
|
96071
96071
|
return function(target) {
|
|
96072
96072
|
injectable_1.default()(target);
|
|
96073
96073
|
dependency_container_1.instance.registerSingleton(target);
|
|
96074
96074
|
};
|
|
96075
96075
|
}
|
|
96076
|
-
exports.default =
|
|
96076
|
+
exports.default = singleton2;
|
|
96077
96077
|
}
|
|
96078
96078
|
});
|
|
96079
96079
|
|
|
@@ -330392,7 +330392,7 @@ ${lanes.join("\n")}
|
|
|
330392
330392
|
}
|
|
330393
330393
|
return false;
|
|
330394
330394
|
}
|
|
330395
|
-
function createPropertyDescriptor(attributes,
|
|
330395
|
+
function createPropertyDescriptor(attributes, singleLine2) {
|
|
330396
330396
|
const properties = [];
|
|
330397
330397
|
tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable));
|
|
330398
330398
|
tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable));
|
|
@@ -330401,7 +330401,7 @@ ${lanes.join("\n")}
|
|
|
330401
330401
|
let isAccessor2 = tryAddPropertyAssignment(properties, "get", attributes.get);
|
|
330402
330402
|
isAccessor2 = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor2;
|
|
330403
330403
|
Debug.assert(!(isData && isAccessor2), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor.");
|
|
330404
|
-
return createObjectLiteralExpression(properties, !
|
|
330404
|
+
return createObjectLiteralExpression(properties, !singleLine2);
|
|
330405
330405
|
}
|
|
330406
330406
|
function updateOuterExpression(outerExpression, expression) {
|
|
330407
330407
|
switch (outerExpression.kind) {
|
|
@@ -343871,9 +343871,9 @@ ${lanes.join("\n")}
|
|
|
343871
343871
|
}
|
|
343872
343872
|
return;
|
|
343873
343873
|
}
|
|
343874
|
-
const
|
|
343875
|
-
if (
|
|
343876
|
-
return addPragmaForMatch(pragmas, range, 2,
|
|
343874
|
+
const singleLine2 = range.kind === 2 && singleLinePragmaRegEx.exec(text2);
|
|
343875
|
+
if (singleLine2) {
|
|
343876
|
+
return addPragmaForMatch(pragmas, range, 2, singleLine2);
|
|
343877
343877
|
}
|
|
343878
343878
|
if (range.kind === 3) {
|
|
343879
343879
|
const multiLinePragmaRegEx = /@(\S+)(\s+(?:\S.*)?)?$/gm;
|
|
@@ -419394,7 +419394,7 @@ ${lanes.join("\n")}
|
|
|
419394
419394
|
}
|
|
419395
419395
|
function transformFunctionBody2(node) {
|
|
419396
419396
|
let multiLine = false;
|
|
419397
|
-
let
|
|
419397
|
+
let singleLine2 = false;
|
|
419398
419398
|
let statementsLocation;
|
|
419399
419399
|
let closeBraceLocation;
|
|
419400
419400
|
const prologue = [];
|
|
@@ -419436,7 +419436,7 @@ ${lanes.join("\n")}
|
|
|
419436
419436
|
const equalsGreaterThanToken = node.equalsGreaterThanToken;
|
|
419437
419437
|
if (!nodeIsSynthesized(equalsGreaterThanToken) && !nodeIsSynthesized(body)) {
|
|
419438
419438
|
if (rangeEndIsOnSameLineAsRangeStart(equalsGreaterThanToken, body, currentSourceFile)) {
|
|
419439
|
-
|
|
419439
|
+
singleLine2 = true;
|
|
419440
419440
|
} else {
|
|
419441
419441
|
multiLine = true;
|
|
419442
419442
|
}
|
|
@@ -419465,7 +419465,7 @@ ${lanes.join("\n")}
|
|
|
419465
419465
|
}
|
|
419466
419466
|
const block = factory2.createBlock(setTextRange(factory2.createNodeArray(statements), statementsLocation), multiLine);
|
|
419467
419467
|
setTextRange(block, node.body);
|
|
419468
|
-
if (!multiLine &&
|
|
419468
|
+
if (!multiLine && singleLine2) {
|
|
419469
419469
|
setEmitFlags(
|
|
419470
419470
|
block,
|
|
419471
419471
|
1
|
|
@@ -554463,10 +554463,10 @@ function collectSnapshot(workingDir) {
|
|
|
554463
554463
|
const freeRAM = freemem2();
|
|
554464
554464
|
let load1 = 0, load5 = 0, load15 = 0;
|
|
554465
554465
|
try {
|
|
554466
|
-
const
|
|
554467
|
-
load1 =
|
|
554468
|
-
load5 =
|
|
554469
|
-
load15 =
|
|
554466
|
+
const loadavg5 = __require("node:os").loadavg();
|
|
554467
|
+
load1 = loadavg5[0];
|
|
554468
|
+
load5 = loadavg5[1];
|
|
554469
|
+
load15 = loadavg5[2];
|
|
554470
554470
|
} catch {
|
|
554471
554471
|
}
|
|
554472
554472
|
let gpu = void 0;
|
|
@@ -564504,16 +564504,16 @@ function recommendMaxParallelFromVram(minFreeMB) {
|
|
|
564504
564504
|
return 1;
|
|
564505
564505
|
}
|
|
564506
564506
|
async function getHardwareSnapshot() {
|
|
564507
|
-
const { totalmem:
|
|
564507
|
+
const { totalmem: totalmem11, freemem: freemem10, cpus: cpus7 } = await import("node:os");
|
|
564508
564508
|
const gpus = await detectGpus();
|
|
564509
564509
|
const diskPath = discoverSystemOllamaModelStore() ?? homedir33();
|
|
564510
564510
|
const disk = snapshotDisk(diskPath);
|
|
564511
564511
|
const network = snapshotNetwork();
|
|
564512
564512
|
return {
|
|
564513
564513
|
gpus,
|
|
564514
|
-
cpuCores:
|
|
564515
|
-
ramTotalMB: Math.round(
|
|
564516
|
-
ramFreeMB: Math.round(
|
|
564514
|
+
cpuCores: cpus7().length,
|
|
564515
|
+
ramTotalMB: Math.round(totalmem11() / (1024 * 1024)),
|
|
564516
|
+
ramFreeMB: Math.round(freemem10() / (1024 * 1024)),
|
|
564517
564517
|
disk,
|
|
564518
564518
|
network,
|
|
564519
564519
|
takenAtMs: Date.now()
|
|
@@ -578990,7 +578990,7 @@ ${context2 ?? ""}`;
|
|
|
578990
578990
|
}
|
|
578991
578991
|
}
|
|
578992
578992
|
_applyTaskAffectFromResult(result, events) {
|
|
578993
|
-
const
|
|
578993
|
+
const clamp11 = (n2) => Math.max(0, Math.min(1, n2));
|
|
578994
578994
|
let uncertainty = this._taskAffectState.uncertainty * 0.94;
|
|
578995
578995
|
let frustration = this._taskAffectState.frustration * 0.94;
|
|
578996
578996
|
let confidence2 = this._taskAffectState.confidence * 0.94;
|
|
@@ -579023,11 +579023,11 @@ ${context2 ?? ""}`;
|
|
|
579023
579023
|
}
|
|
579024
579024
|
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
579025
|
this._taskAffectState = {
|
|
579026
|
-
uncertainty:
|
|
579027
|
-
frustration:
|
|
579028
|
-
confidence:
|
|
579029
|
-
novelty:
|
|
579030
|
-
momentum:
|
|
579026
|
+
uncertainty: clamp11(uncertainty),
|
|
579027
|
+
frustration: clamp11(frustration),
|
|
579028
|
+
confidence: clamp11(confidence2),
|
|
579029
|
+
novelty: clamp11(novelty),
|
|
579030
|
+
momentum: clamp11(momentum),
|
|
579031
579031
|
adversaryLevel: level,
|
|
579032
579032
|
lastUpdatedIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
579033
579033
|
};
|
|
@@ -593827,7 +593827,7 @@ ${result}`
|
|
|
593827
593827
|
const buffer2 = Buffer.from(rawBase64, "base64");
|
|
593828
593828
|
let resizedBase64 = null;
|
|
593829
593829
|
try {
|
|
593830
|
-
const { writeFileSync: writeFileSync95, readFileSync: readFileSync140, unlinkSync:
|
|
593830
|
+
const { writeFileSync: writeFileSync95, readFileSync: readFileSync140, unlinkSync: unlinkSync38 } = await import("node:fs");
|
|
593831
593831
|
const { join: join188 } = await import("node:path");
|
|
593832
593832
|
const { tmpdir: tmpdir26 } = await import("node:os");
|
|
593833
593833
|
const tmpIn = join188(tmpdir26(), `omnius_img_in_${Date.now()}.png`);
|
|
@@ -593845,11 +593845,11 @@ ${result}`
|
|
|
593845
593845
|
const resizedBuf = readFileSync140(tmpOut);
|
|
593846
593846
|
resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
|
|
593847
593847
|
try {
|
|
593848
|
-
|
|
593848
|
+
unlinkSync38(tmpIn);
|
|
593849
593849
|
} catch {
|
|
593850
593850
|
}
|
|
593851
593851
|
try {
|
|
593852
|
-
|
|
593852
|
+
unlinkSync38(tmpOut);
|
|
593853
593853
|
} catch {
|
|
593854
593854
|
}
|
|
593855
593855
|
} catch {
|
|
@@ -603393,6 +603393,10 @@ function defaultConsensusModel(primaryModel) {
|
|
|
603393
603393
|
if (model === "large-v3" || model === "large") return "small";
|
|
603394
603394
|
return "base";
|
|
603395
603395
|
}
|
|
603396
|
+
function asrConsensusEnabled() {
|
|
603397
|
+
const consensusEnv = String(process.env["OMNIUS_ASR_CONSENSUS"] ?? "").trim().toLowerCase();
|
|
603398
|
+
return !(consensusEnv === "0" || consensusEnv === "off" || consensusEnv === "false");
|
|
603399
|
+
}
|
|
603396
603400
|
async function ensureVenvForTranscribeCli() {
|
|
603397
603401
|
const bin = process.platform === "win32" ? "Scripts" : "bin";
|
|
603398
603402
|
const exe = process.platform === "win32" ? "python.exe" : "python3";
|
|
@@ -603895,8 +603899,19 @@ var init_listen = __esm({
|
|
|
603895
603899
|
updateListenLiveState({ phase: "error", lastStatus: "no mic capture tool (arecord/sox/ffmpeg)" });
|
|
603896
603900
|
return "No microphone capture tool found. Install arecord (Linux), sox (macOS), or ffmpeg.";
|
|
603897
603901
|
}
|
|
603898
|
-
|
|
603899
|
-
if (
|
|
603902
|
+
const preferWhisperFallback = asrConsensusEnabled();
|
|
603903
|
+
if (preferWhisperFallback) {
|
|
603904
|
+
this.emit(
|
|
603905
|
+
"info",
|
|
603906
|
+
"ASR consensus enabled — using live-whisper.py (CUDA when available)."
|
|
603907
|
+
);
|
|
603908
|
+
updateListenLiveState({
|
|
603909
|
+
backend: "openai-whisper",
|
|
603910
|
+
lastStatus: "starting consensus Whisper backend..."
|
|
603911
|
+
});
|
|
603912
|
+
}
|
|
603913
|
+
let tc = preferWhisperFallback ? null : await this.loadTranscribeCli();
|
|
603914
|
+
if (!preferWhisperFallback && !tc) {
|
|
603900
603915
|
if (_bgInstallPromise) {
|
|
603901
603916
|
this.emit("info", "Waiting for transcribe-cli install...");
|
|
603902
603917
|
await _bgInstallPromise;
|
|
@@ -604174,13 +604189,14 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
604174
604189
|
* Caller is responsible for calling .stop() when done.
|
|
604175
604190
|
*/
|
|
604176
604191
|
async createCallTranscriber() {
|
|
604177
|
-
|
|
604178
|
-
|
|
604192
|
+
const requireConsensus = asrConsensusEnabled();
|
|
604193
|
+
let tc = requireConsensus ? null : await this.loadTranscribeCli();
|
|
604194
|
+
if (!requireConsensus && !tc && _bgInstallPromise) {
|
|
604179
604195
|
await _bgInstallPromise;
|
|
604180
604196
|
this.transcribeCliAvailable = null;
|
|
604181
604197
|
tc = await this.loadTranscribeCli();
|
|
604182
604198
|
}
|
|
604183
|
-
if (!tc) {
|
|
604199
|
+
if (!requireConsensus && !tc) {
|
|
604184
604200
|
try {
|
|
604185
604201
|
await ensureManagedTranscribeCliNode();
|
|
604186
604202
|
this.transcribeCliAvailable = null;
|
|
@@ -604188,7 +604204,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
604188
604204
|
} catch {
|
|
604189
604205
|
}
|
|
604190
604206
|
}
|
|
604191
|
-
if (tc?.TranscribeLive && await ensureVenvForTranscribeCli()) {
|
|
604207
|
+
if (!requireConsensus && tc?.TranscribeLive && await ensureVenvForTranscribeCli()) {
|
|
604192
604208
|
try {
|
|
604193
604209
|
const transcriber = new tc.TranscribeLive({
|
|
604194
604210
|
model: this.config.model,
|
|
@@ -604326,13 +604342,36 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
604326
604342
|
|
|
604327
604343
|
// packages/cli/src/tui/camera-streamer.ts
|
|
604328
604344
|
import { spawn as spawn30 } from "node:child_process";
|
|
604329
|
-
import { existsSync as existsSync111, mkdirSync as mkdirSync69, statSync as statSync43 } from "node:fs";
|
|
604345
|
+
import { existsSync as existsSync111, mkdirSync as mkdirSync69, statSync as statSync43, unlinkSync as unlinkSync20 } from "node:fs";
|
|
604330
604346
|
import { join as join127 } from "node:path";
|
|
604331
604347
|
function streamFps() {
|
|
604332
604348
|
const raw = Number(process.env["OMNIUS_LIVE_STREAM_FPS"] ?? "");
|
|
604333
604349
|
if (Number.isFinite(raw) && raw > 0) return Math.max(1, Math.min(30, Math.round(raw)));
|
|
604334
604350
|
return 8;
|
|
604335
604351
|
}
|
|
604352
|
+
function parseResolution(value2) {
|
|
604353
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
604354
|
+
if (!raw || raw === "native" || raw === "auto") return null;
|
|
604355
|
+
const alias = {
|
|
604356
|
+
"480p": "640x480",
|
|
604357
|
+
"720p": "1280x720",
|
|
604358
|
+
"1080p": "1920x1080",
|
|
604359
|
+
"1440p": "2560x1440",
|
|
604360
|
+
"4k": "3840x2160",
|
|
604361
|
+
"2160p": "3840x2160"
|
|
604362
|
+
};
|
|
604363
|
+
const normalized = alias[raw] ?? raw;
|
|
604364
|
+
const match = normalized.match(/^(\d{3,5})x(\d{3,5})$/);
|
|
604365
|
+
if (!match) return null;
|
|
604366
|
+
const width = Number(match[1]);
|
|
604367
|
+
const height = Number(match[2]);
|
|
604368
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;
|
|
604369
|
+
return { label: `${width}x${height}`, width, height };
|
|
604370
|
+
}
|
|
604371
|
+
function scaleFilter(resolution) {
|
|
604372
|
+
if (!resolution) return null;
|
|
604373
|
+
return `scale=w='min(${resolution.width}\\,iw)':h='min(${resolution.height}\\,ih)':force_original_aspect_ratio=decrease`;
|
|
604374
|
+
}
|
|
604336
604375
|
function rotateFilter(rotation) {
|
|
604337
604376
|
switch ((rotation % 360 + 360) % 360) {
|
|
604338
604377
|
case 90:
|
|
@@ -604352,7 +604391,7 @@ var MAX_ATTEMPT, FAST_EXIT_MS, RESTART_DELAY_MS, MAX_CONSECUTIVE_FAILURES, Camer
|
|
|
604352
604391
|
var init_camera_streamer = __esm({
|
|
604353
604392
|
"packages/cli/src/tui/camera-streamer.ts"() {
|
|
604354
604393
|
"use strict";
|
|
604355
|
-
MAX_ATTEMPT =
|
|
604394
|
+
MAX_ATTEMPT = 4;
|
|
604356
604395
|
FAST_EXIT_MS = 3e3;
|
|
604357
604396
|
RESTART_DELAY_MS = 1500;
|
|
604358
604397
|
MAX_CONSECUTIVE_FAILURES = 10;
|
|
@@ -604387,7 +604426,7 @@ var init_camera_streamer = __esm({
|
|
|
604387
604426
|
* Only v4l2 device paths are streamable; other backends (OSC/WiFi cams)
|
|
604388
604427
|
* keep the one-shot capture path.
|
|
604389
604428
|
*/
|
|
604390
|
-
sync(sources, rotationFor) {
|
|
604429
|
+
sync(sources, rotationFor, resolutionFor) {
|
|
604391
604430
|
const wanted = new Set(sources.filter((source) => source.startsWith("/dev/video")));
|
|
604392
604431
|
for (const [source, stream] of this.streams) {
|
|
604393
604432
|
if (!wanted.has(source)) {
|
|
@@ -604397,20 +604436,21 @@ var init_camera_streamer = __esm({
|
|
|
604397
604436
|
}
|
|
604398
604437
|
for (const source of wanted) {
|
|
604399
604438
|
const rotation = rotationFor(source);
|
|
604439
|
+
const resolution = resolutionFor(source);
|
|
604400
604440
|
const existing = this.streams.get(source);
|
|
604401
|
-
if (existing && existing.rotation === rotation && !existing.stopped) continue;
|
|
604441
|
+
if (existing && existing.rotation === rotation && existing.resolution === resolution && !existing.stopped) continue;
|
|
604402
604442
|
if (existing) {
|
|
604403
604443
|
this.stopStream(existing);
|
|
604404
604444
|
this.streams.delete(source);
|
|
604405
604445
|
}
|
|
604406
|
-
this.startStream(source, rotation);
|
|
604446
|
+
this.startStream(source, rotation, resolution);
|
|
604407
604447
|
}
|
|
604408
604448
|
}
|
|
604409
604449
|
stopAll() {
|
|
604410
604450
|
for (const stream of this.streams.values()) this.stopStream(stream);
|
|
604411
604451
|
this.streams.clear();
|
|
604412
604452
|
}
|
|
604413
|
-
startStream(source, rotation) {
|
|
604453
|
+
startStream(source, rotation, resolution) {
|
|
604414
604454
|
try {
|
|
604415
604455
|
mkdirSync69(this.streamDir, { recursive: true });
|
|
604416
604456
|
} catch {
|
|
@@ -604419,6 +604459,7 @@ var init_camera_streamer = __esm({
|
|
|
604419
604459
|
source,
|
|
604420
604460
|
framePath: join127(this.streamDir, `${slugForSource(source)}.jpg`),
|
|
604421
604461
|
rotation,
|
|
604462
|
+
resolution,
|
|
604422
604463
|
process: null,
|
|
604423
604464
|
attempt: 0,
|
|
604424
604465
|
consecutiveFailures: 0,
|
|
@@ -604433,13 +604474,17 @@ var init_camera_streamer = __esm({
|
|
|
604433
604474
|
spawnStream(stream) {
|
|
604434
604475
|
if (stream.stopped) return;
|
|
604435
604476
|
const fps = streamFps();
|
|
604477
|
+
const resolution = parseResolution(stream.resolution);
|
|
604436
604478
|
const filters = [`fps=${fps}`];
|
|
604479
|
+
const scale = scaleFilter(resolution);
|
|
604480
|
+
if (scale) filters.push(scale);
|
|
604437
604481
|
const rotate = rotateFilter(stream.rotation);
|
|
604438
604482
|
if (rotate) filters.push(rotate);
|
|
604439
604483
|
const args = ["-hide_banner", "-loglevel", "error", "-f", "v4l2"];
|
|
604440
|
-
if (stream.attempt === 0) args.push("-input_format", "mjpeg");
|
|
604484
|
+
if (stream.attempt === 0 || stream.attempt === 2) args.push("-input_format", "mjpeg");
|
|
604485
|
+
if (resolution && stream.attempt <= 1) args.push("-video_size", resolution.label);
|
|
604441
604486
|
args.push("-i", stream.source, "-vf", filters.join(","), "-q:v", "6", "-f", "image2", "-update", "1");
|
|
604442
|
-
if (stream.attempt <=
|
|
604487
|
+
if (stream.attempt <= 3) args.push("-atomic_writing", "1");
|
|
604443
604488
|
args.push("-y", stream.framePath);
|
|
604444
604489
|
const child = spawn30(process.env["OMNIUS_FFMPEG"] || "ffmpeg", args, {
|
|
604445
604490
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -604482,12 +604527,24 @@ var init_camera_streamer = __esm({
|
|
|
604482
604527
|
stream.restartTimer = null;
|
|
604483
604528
|
}
|
|
604484
604529
|
if (stream.process) {
|
|
604530
|
+
const child = stream.process;
|
|
604485
604531
|
try {
|
|
604486
|
-
|
|
604532
|
+
child.kill("SIGTERM");
|
|
604487
604533
|
} catch {
|
|
604488
604534
|
}
|
|
604535
|
+
const killTimer = setTimeout(() => {
|
|
604536
|
+
try {
|
|
604537
|
+
if (!child.killed) child.kill("SIGKILL");
|
|
604538
|
+
} catch {
|
|
604539
|
+
}
|
|
604540
|
+
}, 1500);
|
|
604541
|
+
killTimer.unref?.();
|
|
604489
604542
|
stream.process = null;
|
|
604490
604543
|
}
|
|
604544
|
+
try {
|
|
604545
|
+
if (existsSync111(stream.framePath)) unlinkSync20(stream.framePath);
|
|
604546
|
+
} catch {
|
|
604547
|
+
}
|
|
604491
604548
|
}
|
|
604492
604549
|
};
|
|
604493
604550
|
}
|
|
@@ -604703,9 +604760,230 @@ var init_live_vlm = __esm({
|
|
|
604703
604760
|
}
|
|
604704
604761
|
});
|
|
604705
604762
|
|
|
604763
|
+
// packages/cli/src/tui/live-resource-arbiter.ts
|
|
604764
|
+
import { cpus as cpus3, freemem as freemem4, loadavg, totalmem as totalmem5 } from "node:os";
|
|
604765
|
+
function getLiveResourceArbiter() {
|
|
604766
|
+
if (!singleton) singleton = new LiveResourceArbiter();
|
|
604767
|
+
return singleton;
|
|
604768
|
+
}
|
|
604769
|
+
function formatLiveResourceBudgetLines(width = 100) {
|
|
604770
|
+
const snap = getLiveResourceArbiter().snapshot();
|
|
604771
|
+
const inner = Math.max(24, width - 2);
|
|
604772
|
+
const memoryColor = pressureColor(snap.memoryPressure, snap.target);
|
|
604773
|
+
const totalGB = snap.totalMemMB / 1024;
|
|
604774
|
+
const usedGB = snap.usedMemMB / 1024;
|
|
604775
|
+
const freeGB = snap.freeMemMB / 1024;
|
|
604776
|
+
const deferMs = Math.max(0, snap.deferUntil - Date.now());
|
|
604777
|
+
const status = deferMs > 0 ? colorText("deferring vision", 208) : colorText("vision allowed", 82);
|
|
604778
|
+
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";
|
|
604779
|
+
return [
|
|
604780
|
+
colorText(" resource budget", 45),
|
|
604781
|
+
`├─ memory: ${memoryColor(`${usedGB.toFixed(1)}/${totalGB.toFixed(1)}GB used`)} free=${freeGB.toFixed(1)}GB target<=${Math.round(snap.target * 100)}%`,
|
|
604782
|
+
`├─ 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}`,
|
|
604783
|
+
`└─ leases: ${truncateAnsi(leaseText, inner - 12)}`
|
|
604784
|
+
];
|
|
604785
|
+
}
|
|
604786
|
+
function readBudget() {
|
|
604787
|
+
const raw = String(process.env["OMNIUS_LIVE_RESOURCE_BUDGET"] ?? "").trim().toLowerCase();
|
|
604788
|
+
if (raw === "low" || raw === "conserve" || raw === "conservative" || raw === "battery") return "conserve";
|
|
604789
|
+
if (raw === "high" || raw === "generous") return "high";
|
|
604790
|
+
if (raw === "aggressive" || raw === "max" || raw === "unlimited") return "aggressive";
|
|
604791
|
+
return "balanced";
|
|
604792
|
+
}
|
|
604793
|
+
function budgetTarget(budget) {
|
|
604794
|
+
const override = Number(process.env["OMNIUS_LIVE_RESOURCE_TARGET"] ?? "");
|
|
604795
|
+
if (Number.isFinite(override) && override > 0 && override < 1) return override;
|
|
604796
|
+
if (budget === "conserve") return 0.55;
|
|
604797
|
+
if (budget === "high") return 0.82;
|
|
604798
|
+
if (budget === "aggressive") return 0.92;
|
|
604799
|
+
return 0.7;
|
|
604800
|
+
}
|
|
604801
|
+
function numberEnv(name10, fallback) {
|
|
604802
|
+
const value2 = Number(process.env[name10] ?? "");
|
|
604803
|
+
return Number.isFinite(value2) ? value2 : fallback;
|
|
604804
|
+
}
|
|
604805
|
+
function clamp8(value2, min, max) {
|
|
604806
|
+
return Math.max(min, Math.min(max, value2));
|
|
604807
|
+
}
|
|
604808
|
+
function pressureColor(pressure, target) {
|
|
604809
|
+
if (pressure <= target) return (text2) => colorText(text2, 82);
|
|
604810
|
+
if (pressure <= target + 0.12) return (text2) => colorText(text2, 220);
|
|
604811
|
+
return (text2) => colorText(text2, 196);
|
|
604812
|
+
}
|
|
604813
|
+
function colorText(text2, color) {
|
|
604814
|
+
return `\x1B[38;5;${color}m${text2}\x1B[0m`;
|
|
604815
|
+
}
|
|
604816
|
+
function truncateAnsi(text2, max) {
|
|
604817
|
+
const plain = text2.replace(/\x1b\[[0-9;]*m/g, "");
|
|
604818
|
+
if (plain.length <= max) return text2;
|
|
604819
|
+
return `${plain.slice(0, Math.max(0, max - 3))}...`;
|
|
604820
|
+
}
|
|
604821
|
+
var LiveResourceArbiter, singleton;
|
|
604822
|
+
var init_live_resource_arbiter = __esm({
|
|
604823
|
+
"packages/cli/src/tui/live-resource-arbiter.ts"() {
|
|
604824
|
+
"use strict";
|
|
604825
|
+
LiveResourceArbiter = class {
|
|
604826
|
+
leases = /* @__PURE__ */ new Map();
|
|
604827
|
+
seq = 0;
|
|
604828
|
+
integral = 0;
|
|
604829
|
+
lastError = 0;
|
|
604830
|
+
lastAt = 0;
|
|
604831
|
+
pidDeferUntil = 0;
|
|
604832
|
+
lastPid = 0;
|
|
604833
|
+
lastPressure = 0;
|
|
604834
|
+
claim(args) {
|
|
604835
|
+
const now2 = Date.now();
|
|
604836
|
+
this.cleanup(now2);
|
|
604837
|
+
const id2 = `${now2}-${++this.seq}-${args.owner.replace(/[^a-z0-9_.:-]+/gi, "_")}`;
|
|
604838
|
+
const record = {
|
|
604839
|
+
id: id2,
|
|
604840
|
+
owner: args.owner,
|
|
604841
|
+
priority: clamp8(args.priority, 0, 100),
|
|
604842
|
+
reason: args.reason,
|
|
604843
|
+
suppress: args.suppress?.length ? args.suppress : ["vision"],
|
|
604844
|
+
createdAt: now2,
|
|
604845
|
+
expiresAt: now2 + Math.max(250, args.ttlMs)
|
|
604846
|
+
};
|
|
604847
|
+
this.leases.set(id2, record);
|
|
604848
|
+
return {
|
|
604849
|
+
id: id2,
|
|
604850
|
+
owner: record.owner,
|
|
604851
|
+
priority: record.priority,
|
|
604852
|
+
get expiresAt() {
|
|
604853
|
+
return record.expiresAt;
|
|
604854
|
+
},
|
|
604855
|
+
release: () => {
|
|
604856
|
+
this.leases.delete(id2);
|
|
604857
|
+
},
|
|
604858
|
+
extend: (ttlMs, reason) => {
|
|
604859
|
+
const current = this.leases.get(id2);
|
|
604860
|
+
if (!current) return;
|
|
604861
|
+
current.expiresAt = Math.max(current.expiresAt, Date.now() + Math.max(250, ttlMs));
|
|
604862
|
+
if (reason) current.reason = reason;
|
|
604863
|
+
}
|
|
604864
|
+
};
|
|
604865
|
+
}
|
|
604866
|
+
shouldDefer(kind, options2 = {}) {
|
|
604867
|
+
const now2 = Date.now();
|
|
604868
|
+
this.cleanup(now2);
|
|
604869
|
+
const budget = readBudget();
|
|
604870
|
+
if (String(process.env["OMNIUS_LIVE_RESOURCE_ARBITER"] ?? "").toLowerCase() === "off") {
|
|
604871
|
+
return this.decision(false, "", now2, 0, budget);
|
|
604872
|
+
}
|
|
604873
|
+
const minPriority = clamp8(options2.minPriority ?? 50, 0, 100);
|
|
604874
|
+
const token = kind.toLowerCase();
|
|
604875
|
+
let strongest = null;
|
|
604876
|
+
for (const lease of this.leases.values()) {
|
|
604877
|
+
if (lease.priority < minPriority) continue;
|
|
604878
|
+
if (!lease.suppress.some((entry) => entry === "*" || token.includes(entry.toLowerCase()))) continue;
|
|
604879
|
+
if (!strongest || lease.priority > strongest.priority || lease.expiresAt > strongest.expiresAt) strongest = lease;
|
|
604880
|
+
}
|
|
604881
|
+
if (strongest) {
|
|
604882
|
+
return this.decision(
|
|
604883
|
+
true,
|
|
604884
|
+
`live resource priority ${strongest.priority} from ${strongest.owner}: ${strongest.reason}`,
|
|
604885
|
+
strongest.expiresAt,
|
|
604886
|
+
strongest.priority,
|
|
604887
|
+
budget
|
|
604888
|
+
);
|
|
604889
|
+
}
|
|
604890
|
+
const pid = this.samplePid(now2, budget);
|
|
604891
|
+
if (pid.deferUntil > now2) {
|
|
604892
|
+
return this.decision(
|
|
604893
|
+
true,
|
|
604894
|
+
`resource PID pressure budget=${budget} pressure=${pid.pressure.toFixed(2)} target=${pid.target.toFixed(2)} output=${pid.output.toFixed(2)}`,
|
|
604895
|
+
pid.deferUntil,
|
|
604896
|
+
45,
|
|
604897
|
+
budget
|
|
604898
|
+
);
|
|
604899
|
+
}
|
|
604900
|
+
return this.decision(false, "", now2, 0, budget);
|
|
604901
|
+
}
|
|
604902
|
+
snapshot(now2 = Date.now()) {
|
|
604903
|
+
this.cleanup(now2);
|
|
604904
|
+
const budget = readBudget();
|
|
604905
|
+
const pid = this.samplePid(now2, budget);
|
|
604906
|
+
const total = Math.max(1, totalmem5());
|
|
604907
|
+
const free = Math.max(0, freemem4());
|
|
604908
|
+
const cpuCount = Math.max(1, cpus3().length);
|
|
604909
|
+
const cpuLoad1m = loadavg()[0] ?? 0;
|
|
604910
|
+
return {
|
|
604911
|
+
budget,
|
|
604912
|
+
totalMemMB: Math.round(total / 1024 / 1024),
|
|
604913
|
+
freeMemMB: Math.round(free / 1024 / 1024),
|
|
604914
|
+
usedMemMB: Math.round((total - free) / 1024 / 1024),
|
|
604915
|
+
memoryPressure: clamp8(1 - free / total, 0, 1),
|
|
604916
|
+
cpuLoad1m,
|
|
604917
|
+
cpuPressure: clamp8(cpuLoad1m / cpuCount, 0, 2) / 2,
|
|
604918
|
+
pressure: pid.pressure,
|
|
604919
|
+
target: pid.target,
|
|
604920
|
+
pid: pid.output,
|
|
604921
|
+
deferUntil: pid.deferUntil,
|
|
604922
|
+
leases: [...this.leases.values()].sort((a2, b) => b.priority - a2.priority).map((lease) => ({
|
|
604923
|
+
owner: lease.owner,
|
|
604924
|
+
priority: lease.priority,
|
|
604925
|
+
reason: lease.reason,
|
|
604926
|
+
expiresInMs: Math.max(0, lease.expiresAt - now2)
|
|
604927
|
+
}))
|
|
604928
|
+
};
|
|
604929
|
+
}
|
|
604930
|
+
releaseOwnerPrefix(prefix) {
|
|
604931
|
+
for (const [id2, lease] of this.leases) {
|
|
604932
|
+
if (lease.owner.startsWith(prefix)) this.leases.delete(id2);
|
|
604933
|
+
}
|
|
604934
|
+
}
|
|
604935
|
+
decision(defer, reason, until, priority, budget) {
|
|
604936
|
+
return {
|
|
604937
|
+
defer,
|
|
604938
|
+
reason,
|
|
604939
|
+
until,
|
|
604940
|
+
priority,
|
|
604941
|
+
budget,
|
|
604942
|
+
pressure: this.lastPressure,
|
|
604943
|
+
pid: this.lastPid
|
|
604944
|
+
};
|
|
604945
|
+
}
|
|
604946
|
+
cleanup(now2) {
|
|
604947
|
+
for (const [id2, lease] of this.leases) {
|
|
604948
|
+
if (lease.expiresAt <= now2) this.leases.delete(id2);
|
|
604949
|
+
}
|
|
604950
|
+
}
|
|
604951
|
+
samplePid(now2, budget) {
|
|
604952
|
+
const target = budgetTarget(budget);
|
|
604953
|
+
const cpuCount = Math.max(1, cpus3().length);
|
|
604954
|
+
const cpuPressure = clamp8((loadavg()[0] ?? 0) / cpuCount, 0, 2) / 2;
|
|
604955
|
+
const total = Math.max(1, totalmem5());
|
|
604956
|
+
const free = Math.max(0, freemem4());
|
|
604957
|
+
const memoryPressure = clamp8(1 - free / total, 0, 1);
|
|
604958
|
+
const pressure = clamp8(Math.max(memoryPressure, cpuPressure * 0.65 + memoryPressure * 0.35), 0, 1);
|
|
604959
|
+
const dt = this.lastAt > 0 ? clamp8((now2 - this.lastAt) / 1e3, 0.1, 10) : 1;
|
|
604960
|
+
const error = pressure - target;
|
|
604961
|
+
this.integral = clamp8(this.integral + error * dt, -2, 2);
|
|
604962
|
+
const derivative = (error - this.lastError) / dt;
|
|
604963
|
+
const kp = numberEnv("OMNIUS_LIVE_PID_KP", 0.9);
|
|
604964
|
+
const ki = numberEnv("OMNIUS_LIVE_PID_KI", 0.18);
|
|
604965
|
+
const kd = numberEnv("OMNIUS_LIVE_PID_KD", 0.12);
|
|
604966
|
+
const output = clamp8(kp * error + ki * this.integral + kd * derivative, 0, 1);
|
|
604967
|
+
this.lastAt = now2;
|
|
604968
|
+
this.lastError = error;
|
|
604969
|
+
this.lastPressure = pressure;
|
|
604970
|
+
this.lastPid = output;
|
|
604971
|
+
if (output > 0.08) {
|
|
604972
|
+
const maxMs = numberEnv("OMNIUS_LIVE_PID_MAX_DEFER_MS", 3e4);
|
|
604973
|
+
this.pidDeferUntil = Math.max(this.pidDeferUntil, now2 + clamp8(750 + output * maxMs, 1e3, maxMs));
|
|
604974
|
+
} else if (pressure < target - 0.08) {
|
|
604975
|
+
this.pidDeferUntil = Math.min(this.pidDeferUntil, now2);
|
|
604976
|
+
}
|
|
604977
|
+
return { output, pressure, target, deferUntil: this.pidDeferUntil };
|
|
604978
|
+
}
|
|
604979
|
+
};
|
|
604980
|
+
singleton = null;
|
|
604981
|
+
}
|
|
604982
|
+
});
|
|
604983
|
+
|
|
604706
604984
|
// packages/cli/src/tui/live-sensors.ts
|
|
604707
604985
|
import { existsSync as existsSync113, mkdirSync as mkdirSync70, readFileSync as readFileSync91, writeFileSync as writeFileSync58 } from "node:fs";
|
|
604708
|
-
import { arch as arch3, freemem as
|
|
604986
|
+
import { arch as arch3, freemem as freemem5 } from "node:os";
|
|
604709
604987
|
import { basename as basename23, join as join128, relative as relative11 } from "node:path";
|
|
604710
604988
|
function liveDir(repoRoot) {
|
|
604711
604989
|
return join128(repoRoot, ".omnius", "live");
|
|
@@ -604857,6 +605135,52 @@ function describeCameraOrientation(orientation) {
|
|
|
604857
605135
|
if (!orientation) return "upright/no correction (default)";
|
|
604858
605136
|
return `${formatCameraRotation(orientation.rotation)} (${orientation.source}${orientation.confidence !== void 0 ? ` confidence=${orientation.confidence.toFixed(2)}` : ""}, updated=${nowIso3(orientation.updatedAt)})`;
|
|
604859
605137
|
}
|
|
605138
|
+
function normalizeLiveCameraResolution(value2) {
|
|
605139
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
605140
|
+
if (!raw || raw === "default" || raw === "1080" || raw === "1080p") return "1920x1080";
|
|
605141
|
+
if (raw === "native" || raw === "auto" || raw === "max") return "native";
|
|
605142
|
+
if (raw === "480" || raw === "480p" || raw === "vga") return "640x480";
|
|
605143
|
+
if (raw === "720" || raw === "720p" || raw === "hd") return "1280x720";
|
|
605144
|
+
if (raw === "1440" || raw === "1440p" || raw === "2k") return "2560x1440";
|
|
605145
|
+
if (raw === "2160" || raw === "2160p" || raw === "4k" || raw === "uhd") return "3840x2160";
|
|
605146
|
+
if (["640x480", "1280x720", "1920x1080", "2560x1440", "3840x2160"].includes(raw)) return raw;
|
|
605147
|
+
throw new Error(`Unsupported live camera resolution: ${String(value2)}. Use native, 480p, 720p, 1080p, 1440p, 4k, or WxH.`);
|
|
605148
|
+
}
|
|
605149
|
+
function formatLiveCameraResolution(value2) {
|
|
605150
|
+
const res = value2 ?? DEFAULT_CAMERA_RESOLUTION;
|
|
605151
|
+
if (res === "native") return "native";
|
|
605152
|
+
if (res === "640x480") return "480p (640x480)";
|
|
605153
|
+
if (res === "1280x720") return "720p (1280x720)";
|
|
605154
|
+
if (res === "1920x1080") return "1080p (1920x1080)";
|
|
605155
|
+
if (res === "2560x1440") return "1440p (2560x1440)";
|
|
605156
|
+
if (res === "3840x2160") return "4K (3840x2160)";
|
|
605157
|
+
return res;
|
|
605158
|
+
}
|
|
605159
|
+
function liveCameraResolutionSize(value2) {
|
|
605160
|
+
const res = value2 ?? DEFAULT_CAMERA_RESOLUTION;
|
|
605161
|
+
if (res === "native") return null;
|
|
605162
|
+
const [widthRaw, heightRaw] = res.split("x");
|
|
605163
|
+
const width = Number(widthRaw);
|
|
605164
|
+
const height = Number(heightRaw);
|
|
605165
|
+
return Number.isFinite(width) && Number.isFinite(height) ? { width, height } : null;
|
|
605166
|
+
}
|
|
605167
|
+
function sanitizeCameraStreams(value2) {
|
|
605168
|
+
if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return {};
|
|
605169
|
+
const out = {};
|
|
605170
|
+
for (const [device, raw] of Object.entries(value2)) {
|
|
605171
|
+
if (!device || typeof raw !== "object" || raw === null || Array.isArray(raw)) continue;
|
|
605172
|
+
const entry = raw;
|
|
605173
|
+
try {
|
|
605174
|
+
out[device] = {
|
|
605175
|
+
enabled: entry["enabled"] !== false,
|
|
605176
|
+
resolution: normalizeLiveCameraResolution(entry["resolution"] ?? DEFAULT_CAMERA_RESOLUTION)
|
|
605177
|
+
};
|
|
605178
|
+
} catch {
|
|
605179
|
+
out[device] = { enabled: entry["enabled"] !== false, resolution: DEFAULT_CAMERA_RESOLUTION };
|
|
605180
|
+
}
|
|
605181
|
+
}
|
|
605182
|
+
return out;
|
|
605183
|
+
}
|
|
604860
605184
|
function chooseCameraOrientationFromScores(scores) {
|
|
604861
605185
|
const sorted = [...scores].filter((score) => Number.isFinite(score.score)).sort((a2, b) => b.score - a2.score);
|
|
604862
605186
|
const best = sorted[0];
|
|
@@ -605616,6 +605940,13 @@ function formatLiveDashboardFromSnapshot(snapshot, opts = {}) {
|
|
|
605616
605940
|
const horizontal = "─".repeat(Math.max(0, width - 2));
|
|
605617
605941
|
const lines = [`╭${horizontal}╮`];
|
|
605618
605942
|
lines.push(`│${truncateCell(` ${title}`, width - 2)}│`);
|
|
605943
|
+
lines.push(`├${horizontal}┤`);
|
|
605944
|
+
for (const budgetLine of formatLiveResourceBudgetLines(width - 2)) {
|
|
605945
|
+
lines.push(`│${truncateAnsiCell(budgetLine, width - 2)}│`);
|
|
605946
|
+
}
|
|
605947
|
+
const enabledStreams = Object.entries(snapshot.config.cameraStreams ?? {}).filter(([, stream]) => stream.enabled !== false);
|
|
605948
|
+
const selectedResolution = snapshot.config.selectedCamera ? formatLiveCameraResolution(snapshot.config.cameraStreams?.[snapshot.config.selectedCamera]?.resolution) : "none";
|
|
605949
|
+
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)}│`);
|
|
605619
605950
|
if (cameras.length === 0) {
|
|
605620
605951
|
lines.push(`│${truncateCell(" no camera frames captured yet", width - 2)}│`);
|
|
605621
605952
|
}
|
|
@@ -605942,6 +606273,7 @@ function loadLiveSensorConfig(repoRoot) {
|
|
|
605942
606273
|
...DEFAULT_CONFIG7,
|
|
605943
606274
|
...parsed,
|
|
605944
606275
|
cameraOrientation: sanitizeCameraOrientation(parsed.cameraOrientation),
|
|
606276
|
+
cameraStreams: sanitizeCameraStreams(parsed.cameraStreams),
|
|
605945
606277
|
videoIntervalMs: Math.max(MIN_VIDEO_INTERVAL_MS, Number(parsed.videoIntervalMs ?? DEFAULT_CONFIG7.videoIntervalMs)),
|
|
605946
606278
|
audioIntervalMs: Math.max(MIN_AUDIO_INTERVAL_MS, Number(parsed.audioIntervalMs ?? DEFAULT_CONFIG7.audioIntervalMs))
|
|
605947
606279
|
};
|
|
@@ -605981,7 +606313,9 @@ function formatLiveSensorContextFromSnapshot(snapshot, opts = {}) {
|
|
|
605981
606313
|
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"}`);
|
|
605982
606314
|
if (snapshot.config.selectedCamera) {
|
|
605983
606315
|
const orientation = snapshot.config.cameraOrientation?.[snapshot.config.selectedCamera];
|
|
606316
|
+
const stream = snapshot.config.cameraStreams?.[snapshot.config.selectedCamera];
|
|
605984
606317
|
lines.push(`Selected camera: ${snapshot.config.selectedCamera}`);
|
|
606318
|
+
lines.push(`Selected camera stream: ${stream?.enabled !== false ? "enabled" : "disabled"} ${formatLiveCameraResolution(stream?.resolution)}`);
|
|
605985
606319
|
lines.push(`Camera orientation correction: ${describeCameraOrientation(orientation)}`);
|
|
605986
606320
|
}
|
|
605987
606321
|
const cameraSnapshots = Object.values(snapshot.cameras ?? (snapshot.video ? { [snapshot.video.source]: snapshot.video } : {})).sort((a2, b) => {
|
|
@@ -606438,6 +606772,7 @@ function formatLiveStatus(snapshot) {
|
|
|
606438
606772
|
const lines = [
|
|
606439
606773
|
`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"}`,
|
|
606440
606774
|
`Camera: ${cfg.selectedCamera || "none"}`,
|
|
606775
|
+
`Camera stream: ${cfg.selectedCamera ? `${cfg.cameraStreams?.[cfg.selectedCamera]?.enabled !== false ? "enabled" : "disabled"} ${formatLiveCameraResolution(cfg.cameraStreams?.[cfg.selectedCamera]?.resolution)}` : "none"}`,
|
|
606441
606776
|
`Camera orientation: ${cfg.selectedCamera ? describeCameraOrientation(cfg.cameraOrientation?.[cfg.selectedCamera]) : "none"}`,
|
|
606442
606777
|
`Audio input: ${cfg.selectedAudioInput || "none"}`,
|
|
606443
606778
|
`Audio output: ${cfg.selectedAudioOutput || "none"}`,
|
|
@@ -606451,7 +606786,7 @@ function formatLiveStatus(snapshot) {
|
|
|
606451
606786
|
}
|
|
606452
606787
|
return lines.join("\n");
|
|
606453
606788
|
}
|
|
606454
|
-
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;
|
|
606789
|
+
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;
|
|
606455
606790
|
var init_live_sensors = __esm({
|
|
606456
606791
|
"packages/cli/src/tui/live-sensors.ts"() {
|
|
606457
606792
|
"use strict";
|
|
@@ -606461,12 +606796,14 @@ var init_live_sensors = __esm({
|
|
|
606461
606796
|
init_listen();
|
|
606462
606797
|
init_camera_streamer();
|
|
606463
606798
|
init_live_vlm();
|
|
606799
|
+
init_live_resource_arbiter();
|
|
606464
606800
|
MIN_VIDEO_INTERVAL_MS = 250;
|
|
606465
606801
|
LOW_LATENCY_VIDEO_INTERVAL_MS = 250;
|
|
606466
606802
|
MIN_AUDIO_INTERVAL_MS = 1500;
|
|
606467
606803
|
LOW_LATENCY_AUDIO_INTERVAL_MS = 2e3;
|
|
606468
606804
|
AUDIO_ACTIVITY_INTERVAL_MS = 200;
|
|
606469
606805
|
AUDIO_ACTIVITY_SAMPLE_SEC = 0.2;
|
|
606806
|
+
DEFAULT_CAMERA_RESOLUTION = "1920x1080";
|
|
606470
606807
|
DEFAULT_CONFIG7 = {
|
|
606471
606808
|
videoEnabled: false,
|
|
606472
606809
|
audioEnabled: false,
|
|
@@ -606476,6 +606813,7 @@ var init_live_sensors = __esm({
|
|
|
606476
606813
|
asrEnabled: false,
|
|
606477
606814
|
audioAnalysisEnabled: false,
|
|
606478
606815
|
cameraOrientation: {},
|
|
606816
|
+
cameraStreams: {},
|
|
606479
606817
|
videoIntervalMs: 1e3,
|
|
606480
606818
|
audioIntervalMs: 6e3
|
|
606481
606819
|
};
|
|
@@ -606512,6 +606850,7 @@ var init_live_sensors = __esm({
|
|
|
606512
606850
|
lastStreamPersistAt = 0;
|
|
606513
606851
|
videoGeneration = 0;
|
|
606514
606852
|
liveGpuYieldUntil = 0;
|
|
606853
|
+
resourceArbiter = getLiveResourceArbiter();
|
|
606515
606854
|
videoInFlight = false;
|
|
606516
606855
|
audioInFlight = false;
|
|
606517
606856
|
audioActivityInFlight = false;
|
|
@@ -606656,12 +606995,85 @@ var init_live_sensors = __esm({
|
|
|
606656
606995
|
if (!clean5 || ordered.includes(clean5)) return;
|
|
606657
606996
|
const device = this.devices.video.find((entry) => entry.id === clean5);
|
|
606658
606997
|
if (device && /metadata\/non-capture/i.test(device.detail ?? "")) return;
|
|
606998
|
+
if (!this.isCameraStreamEnabled(clean5)) return;
|
|
606659
606999
|
ordered.push(clean5);
|
|
606660
607000
|
};
|
|
606661
607001
|
add3(this.config.selectedCamera);
|
|
606662
607002
|
for (const device of this.devices.video) add3(device.id);
|
|
606663
|
-
|
|
606664
|
-
|
|
607003
|
+
const hasExplicitStreamConfig = Object.keys(this.config.cameraStreams ?? {}).length > 0;
|
|
607004
|
+
if (ordered.length === 0 && !hasExplicitStreamConfig) {
|
|
607005
|
+
const fallback = this.config.selectedCamera || firstDeviceId(this.devices.video);
|
|
607006
|
+
if (fallback) {
|
|
607007
|
+
this.config = {
|
|
607008
|
+
...this.config,
|
|
607009
|
+
selectedCamera: fallback,
|
|
607010
|
+
cameraStreams: {
|
|
607011
|
+
...this.config.cameraStreams ?? {},
|
|
607012
|
+
[fallback]: {
|
|
607013
|
+
enabled: true,
|
|
607014
|
+
resolution: this.config.cameraStreams?.[fallback]?.resolution ?? DEFAULT_CAMERA_RESOLUTION
|
|
607015
|
+
}
|
|
607016
|
+
}
|
|
607017
|
+
};
|
|
607018
|
+
add3(fallback);
|
|
607019
|
+
}
|
|
607020
|
+
}
|
|
607021
|
+
const maxStreams = Math.max(1, Math.min(8, Number(process.env["OMNIUS_LIVE_MAX_CAMERA_STREAMS"] ?? 4) || 4));
|
|
607022
|
+
return ordered.slice(0, maxStreams);
|
|
607023
|
+
}
|
|
607024
|
+
isCameraStreamEnabled(device = this.config.selectedCamera) {
|
|
607025
|
+
const target = device || this.config.selectedCamera;
|
|
607026
|
+
if (!target) return false;
|
|
607027
|
+
const configured = this.config.cameraStreams?.[target];
|
|
607028
|
+
if (configured) return configured.enabled !== false;
|
|
607029
|
+
return target === this.config.selectedCamera;
|
|
607030
|
+
}
|
|
607031
|
+
getCameraStreamResolution(device = this.config.selectedCamera) {
|
|
607032
|
+
const target = device || this.config.selectedCamera;
|
|
607033
|
+
return target ? this.config.cameraStreams?.[target]?.resolution ?? DEFAULT_CAMERA_RESOLUTION : DEFAULT_CAMERA_RESOLUTION;
|
|
607034
|
+
}
|
|
607035
|
+
setCameraStreamEnabled(device, enabled2) {
|
|
607036
|
+
const target = device || this.config.selectedCamera;
|
|
607037
|
+
if (!target) return null;
|
|
607038
|
+
const current = this.config.cameraStreams?.[target];
|
|
607039
|
+
const next = {
|
|
607040
|
+
enabled: enabled2,
|
|
607041
|
+
resolution: current?.resolution ?? DEFAULT_CAMERA_RESOLUTION
|
|
607042
|
+
};
|
|
607043
|
+
this.config = {
|
|
607044
|
+
...this.config,
|
|
607045
|
+
selectedCamera: enabled2 ? target : this.config.selectedCamera,
|
|
607046
|
+
cameraStreams: {
|
|
607047
|
+
...this.config.cameraStreams ?? {},
|
|
607048
|
+
[target]: next
|
|
607049
|
+
}
|
|
607050
|
+
};
|
|
607051
|
+
this.videoGeneration++;
|
|
607052
|
+
this.lastStreamFrameMtime.delete(target);
|
|
607053
|
+
this.persist();
|
|
607054
|
+
this.ensureLoops();
|
|
607055
|
+
return next;
|
|
607056
|
+
}
|
|
607057
|
+
setCameraStreamResolution(device, resolution) {
|
|
607058
|
+
const target = device || this.config.selectedCamera;
|
|
607059
|
+
if (!target) return null;
|
|
607060
|
+
const current = this.config.cameraStreams?.[target];
|
|
607061
|
+
const next = {
|
|
607062
|
+
enabled: current?.enabled ?? target === this.config.selectedCamera,
|
|
607063
|
+
resolution: normalizeLiveCameraResolution(resolution)
|
|
607064
|
+
};
|
|
607065
|
+
this.config = {
|
|
607066
|
+
...this.config,
|
|
607067
|
+
cameraStreams: {
|
|
607068
|
+
...this.config.cameraStreams ?? {},
|
|
607069
|
+
[target]: next
|
|
607070
|
+
}
|
|
607071
|
+
};
|
|
607072
|
+
this.videoGeneration++;
|
|
607073
|
+
this.lastStreamFrameMtime.delete(target);
|
|
607074
|
+
this.persist();
|
|
607075
|
+
this.ensureLoops();
|
|
607076
|
+
return next;
|
|
606665
607077
|
}
|
|
606666
607078
|
getCameraOrientation(device = this.config.selectedCamera) {
|
|
606667
607079
|
return device ? this.config.cameraOrientation?.[device] : void 0;
|
|
@@ -606732,6 +607144,14 @@ var init_live_sensors = __esm({
|
|
|
606732
607144
|
return isJetsonUnifiedMemoryHost() ? "yield" : "balanced";
|
|
606733
607145
|
}
|
|
606734
607146
|
async shouldYieldLiveGpuVideo(kind) {
|
|
607147
|
+
const resourceDecision = this.resourceArbiter.shouldDefer(`vision:${kind}`, { minPriority: 45 });
|
|
607148
|
+
if (resourceDecision.defer) {
|
|
607149
|
+
return {
|
|
607150
|
+
yield: true,
|
|
607151
|
+
reason: resourceDecision.reason,
|
|
607152
|
+
until: resourceDecision.until
|
|
607153
|
+
};
|
|
607154
|
+
}
|
|
606735
607155
|
const policy = this.liveVideoGpuPolicy();
|
|
606736
607156
|
if (policy === "aggressive") return { yield: false, reason: "" };
|
|
606737
607157
|
if (policy === "yield") {
|
|
@@ -606755,7 +607175,7 @@ var init_live_sensors = __esm({
|
|
|
606755
607175
|
};
|
|
606756
607176
|
}
|
|
606757
607177
|
} catch {
|
|
606758
|
-
if (isJetsonUnifiedMemoryHost() ||
|
|
607178
|
+
if (isJetsonUnifiedMemoryHost() || freemem5() < 6 * 1024 * 1024 * 1024) {
|
|
606759
607179
|
return { yield: true, reason: `live video ${kind} yielded: memory pressure unknown` };
|
|
606760
607180
|
}
|
|
606761
607181
|
}
|
|
@@ -606766,7 +607186,7 @@ var init_live_sensors = __esm({
|
|
|
606766
607186
|
if (!decision2.yield) return false;
|
|
606767
607187
|
const now2 = Date.now();
|
|
606768
607188
|
if (now2 >= this.liveGpuYieldUntil) {
|
|
606769
|
-
this.liveGpuYieldUntil = now2 + 15e3;
|
|
607189
|
+
this.liveGpuYieldUntil = Math.max(decision2.until ?? 0, now2 + 15e3);
|
|
606770
607190
|
void this.liveVlm.unloadModel().catch(() => false);
|
|
606771
607191
|
this.emitFeedbackThrottled(`live-video-gpu-yield:${kind}`, {
|
|
606772
607192
|
kind: "status",
|
|
@@ -606774,6 +607194,8 @@ var init_live_sensors = __esm({
|
|
|
606774
607194
|
observedAt: now2,
|
|
606775
607195
|
message: `${decision2.reason}. Camera capture/ASCII preview stays active; GPU video inference is skipped. Set OMNIUS_LIVE_VIDEO_GPU_POLICY=aggressive to override.`
|
|
606776
607196
|
}, 3e4);
|
|
607197
|
+
} else if (decision2.until) {
|
|
607198
|
+
this.liveGpuYieldUntil = Math.max(this.liveGpuYieldUntil, decision2.until);
|
|
606777
607199
|
}
|
|
606778
607200
|
return true;
|
|
606779
607201
|
}
|
|
@@ -606798,10 +607220,12 @@ var init_live_sensors = __esm({
|
|
|
606798
607220
|
}
|
|
606799
607221
|
if (!framePath) {
|
|
606800
607222
|
if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
|
|
607223
|
+
const captureSize = liveCameraResolutionSize(this.getCameraStreamResolution(target));
|
|
606801
607224
|
const captured = await new CameraCaptureTool().execute({
|
|
606802
607225
|
action: "capture",
|
|
606803
607226
|
device: target,
|
|
606804
|
-
rotate_degrees: 0
|
|
607227
|
+
rotate_degrees: 0,
|
|
607228
|
+
...captureSize ? { width: captureSize.width, height: captureSize.height } : {}
|
|
606805
607229
|
});
|
|
606806
607230
|
if (!this.isVideoWorkCurrent(generation)) return "Video context is disabled.";
|
|
606807
607231
|
if (!captured.success) {
|
|
@@ -606876,11 +607300,25 @@ var init_live_sensors = __esm({
|
|
|
606876
607300
|
errors
|
|
606877
607301
|
};
|
|
606878
607302
|
if (!this.config.selectedCamera) this.config.selectedCamera = firstDeviceId(video);
|
|
607303
|
+
this.config.cameraStreams = this.reconcileCameraStreams(video);
|
|
606879
607304
|
if (!this.config.selectedAudioInput) this.config.selectedAudioInput = preferredLiveAudioInputId(inputs.devices);
|
|
606880
607305
|
if (!this.config.selectedAudioOutput) this.config.selectedAudioOutput = firstDeviceId(outputs.devices);
|
|
606881
607306
|
this.persist();
|
|
606882
607307
|
return this.devices;
|
|
606883
607308
|
}
|
|
607309
|
+
reconcileCameraStreams(video) {
|
|
607310
|
+
const current = this.config.cameraStreams ?? {};
|
|
607311
|
+
const selected = this.config.selectedCamera || firstDeviceId(video);
|
|
607312
|
+
const next = {};
|
|
607313
|
+
for (const device of video) {
|
|
607314
|
+
if (!device.id || /metadata\/non-capture/i.test(device.detail ?? "")) continue;
|
|
607315
|
+
next[device.id] = {
|
|
607316
|
+
enabled: current[device.id]?.enabled ?? device.id === selected,
|
|
607317
|
+
resolution: current[device.id]?.resolution ?? DEFAULT_CAMERA_RESOLUTION
|
|
607318
|
+
};
|
|
607319
|
+
}
|
|
607320
|
+
return next;
|
|
607321
|
+
}
|
|
606884
607322
|
configure(patch) {
|
|
606885
607323
|
const wasVideoEnabled = this.config.videoEnabled;
|
|
606886
607324
|
this.config = {
|
|
@@ -606889,6 +607327,17 @@ var init_live_sensors = __esm({
|
|
|
606889
607327
|
videoIntervalMs: Math.max(MIN_VIDEO_INTERVAL_MS, Number(patch.videoIntervalMs ?? this.config.videoIntervalMs)),
|
|
606890
607328
|
audioIntervalMs: Math.max(MIN_AUDIO_INTERVAL_MS, Number(patch.audioIntervalMs ?? this.config.audioIntervalMs))
|
|
606891
607329
|
};
|
|
607330
|
+
this.config.cameraStreams = sanitizeCameraStreams(this.config.cameraStreams);
|
|
607331
|
+
if (patch.selectedCamera) {
|
|
607332
|
+
const selected = String(patch.selectedCamera);
|
|
607333
|
+
this.config.cameraStreams = {
|
|
607334
|
+
...this.config.cameraStreams ?? {},
|
|
607335
|
+
[selected]: {
|
|
607336
|
+
enabled: true,
|
|
607337
|
+
resolution: this.config.cameraStreams?.[selected]?.resolution ?? DEFAULT_CAMERA_RESOLUTION
|
|
607338
|
+
}
|
|
607339
|
+
};
|
|
607340
|
+
}
|
|
606892
607341
|
if (wasVideoEnabled && !this.config.videoEnabled) {
|
|
606893
607342
|
this.videoGeneration++;
|
|
606894
607343
|
this.lastStreamFrameMtime.clear();
|
|
@@ -606913,6 +607362,33 @@ var init_live_sensors = __esm({
|
|
|
606913
607362
|
asrEnabled: false,
|
|
606914
607363
|
audioAnalysisEnabled: false
|
|
606915
607364
|
});
|
|
607365
|
+
this.cleanupLiveResources();
|
|
607366
|
+
}
|
|
607367
|
+
cleanupLiveResources() {
|
|
607368
|
+
this.clearLoopTimers();
|
|
607369
|
+
this.videoGeneration++;
|
|
607370
|
+
this.cameraStreamers?.stopAll();
|
|
607371
|
+
this.cameraStreamers = null;
|
|
607372
|
+
this.lastStreamFrameMtime.clear();
|
|
607373
|
+
this.lastVlmAt.clear();
|
|
607374
|
+
this.lastClipAt.clear();
|
|
607375
|
+
this.lastInferenceAt.clear();
|
|
607376
|
+
this.autoOrientationInFlight.clear();
|
|
607377
|
+
this.liveSpeechInFlight.clear();
|
|
607378
|
+
this.resourceArbiter.releaseOwnerPrefix("live-");
|
|
607379
|
+
void this.liveVlm.unloadModel().catch(() => false);
|
|
607380
|
+
this.snapshot = {
|
|
607381
|
+
version: 1,
|
|
607382
|
+
repoRoot: this.repoRoot,
|
|
607383
|
+
config: this.config,
|
|
607384
|
+
devices: this.devices,
|
|
607385
|
+
events: [],
|
|
607386
|
+
people: [],
|
|
607387
|
+
cameras: {}
|
|
607388
|
+
};
|
|
607389
|
+
this.persist();
|
|
607390
|
+
this.emitStatus();
|
|
607391
|
+
this.emitDashboard();
|
|
606916
607392
|
}
|
|
606917
607393
|
startRunMode(options2 = {}) {
|
|
606918
607394
|
this.agentActionEnabled = Boolean(options2.agent);
|
|
@@ -607023,10 +607499,12 @@ var init_live_sensors = __esm({
|
|
|
607023
607499
|
};
|
|
607024
607500
|
}
|
|
607025
607501
|
}
|
|
607502
|
+
const captureSize = liveCameraResolutionSize(this.getCameraStreamResolution(source));
|
|
607026
607503
|
const result = await new CameraCaptureTool().execute({
|
|
607027
607504
|
action: "capture",
|
|
607028
607505
|
device: source,
|
|
607029
|
-
rotate_degrees: rotation
|
|
607506
|
+
rotate_degrees: rotation,
|
|
607507
|
+
...captureSize ? { width: captureSize.width, height: captureSize.height } : {}
|
|
607030
607508
|
});
|
|
607031
607509
|
if (!this.isVideoWorkCurrent(generation)) return { ok: false, message: "Video context is disabled." };
|
|
607032
607510
|
if (!result.success) {
|
|
@@ -607431,6 +607909,8 @@ ${output}`).join("\n\n");
|
|
|
607431
607909
|
async sampleAudioNow() {
|
|
607432
607910
|
if (this.audioInFlight) return "Audio sampler is already running.";
|
|
607433
607911
|
this.audioInFlight = true;
|
|
607912
|
+
let asrLease = null;
|
|
607913
|
+
let keepAsrLease = false;
|
|
607434
607914
|
try {
|
|
607435
607915
|
const input = this.resolveAudioInput();
|
|
607436
607916
|
if (this.isLiveAudioMutedForTts()) {
|
|
@@ -607481,6 +607961,13 @@ ${output}`).join("\n\n");
|
|
|
607481
607961
|
audioErrors.push(`No live input signal detected from selected input ${capture.device}; keeping the explicit selection.`);
|
|
607482
607962
|
}
|
|
607483
607963
|
if (this.config.asrEnabled) {
|
|
607964
|
+
asrLease = this.resourceArbiter.claim({
|
|
607965
|
+
owner: "live-asr",
|
|
607966
|
+
priority: 88,
|
|
607967
|
+
ttlMs: 18e3,
|
|
607968
|
+
reason: "live audio ASR capture/transcription",
|
|
607969
|
+
suppress: ["vision"]
|
|
607970
|
+
});
|
|
607484
607971
|
try {
|
|
607485
607972
|
const asr = await new TranscribeFileTool(this.repoRoot).execute({
|
|
607486
607973
|
path: recordingPath,
|
|
@@ -607517,6 +608004,11 @@ ${output}`).join("\n\n");
|
|
|
607517
608004
|
}
|
|
607518
608005
|
if (transcript) {
|
|
607519
608006
|
intake = await classifyLiveAudioIntake(transcript, this.intakeAgentConfig);
|
|
608007
|
+
keepAsrLease = true;
|
|
608008
|
+
asrLease?.extend(
|
|
608009
|
+
intake?.intendedForAgent ? 35e3 : 18e3,
|
|
608010
|
+
intake?.intendedForAgent ? "live ASR addressed Omnius; reserving compute for response inference" : "live ASR transcript accepted; briefly yielding vision"
|
|
608011
|
+
);
|
|
607520
608012
|
}
|
|
607521
608013
|
this.snapshot.audio = {
|
|
607522
608014
|
updatedAt: Date.now(),
|
|
@@ -607584,6 +608076,7 @@ Sound analysis:
|
|
|
607584
608076
|
${analysis}` : ""
|
|
607585
608077
|
].filter(Boolean).join("\n");
|
|
607586
608078
|
} finally {
|
|
608079
|
+
if (!keepAsrLease) asrLease?.release();
|
|
607587
608080
|
this.audioInFlight = false;
|
|
607588
608081
|
}
|
|
607589
608082
|
}
|
|
@@ -607624,7 +608117,8 @@ ${analysis}` : ""
|
|
|
607624
608117
|
}
|
|
607625
608118
|
this.cameraStreamers.sync(
|
|
607626
608119
|
this.activeVideoSources(),
|
|
607627
|
-
(source) => this.getCameraOrientation(source)?.rotation ?? 0
|
|
608120
|
+
(source) => this.getCameraOrientation(source)?.rotation ?? 0,
|
|
608121
|
+
(source) => this.getCameraStreamResolution(source)
|
|
607628
608122
|
);
|
|
607629
608123
|
}
|
|
607630
608124
|
previewTickIntervalMs() {
|
|
@@ -612426,6 +612920,8 @@ var init_command_registry = __esm({
|
|
|
612426
612920
|
["/live chat", "Start low-latency voicechat with live audio/video context and async agent review"],
|
|
612427
612921
|
["/livechat", "Alias for /live chat, used by the top live button"],
|
|
612428
612922
|
["/live camera <device>", "Select a camera and render an ASCII preview"],
|
|
612923
|
+
["/live resolution [camera] 720p|1080p|1440p|4k|native", "Set per-camera live stream resolution (default 1080p)"],
|
|
612924
|
+
["/live camera-on|camera-off [camera]", "Enable or disable an individual live camera stream"],
|
|
612429
612925
|
["/live rotate auto|cw|ccw|180|none [camera]", "Detect or set persistent camera orientation correction"],
|
|
612430
612926
|
["/live infer [now|on|off]", "Toggle or run camera object/location inference"],
|
|
612431
612927
|
["/live clip [on|off]", "Toggle CLIP visual-memory recognition on live frames"],
|
|
@@ -614314,7 +614810,7 @@ var init_syntax_highlight = __esm({
|
|
|
614314
614810
|
});
|
|
614315
614811
|
|
|
614316
614812
|
// packages/cli/src/tui/model-picker.ts
|
|
614317
|
-
import { totalmem as
|
|
614813
|
+
import { totalmem as totalmem6 } from "node:os";
|
|
614318
614814
|
function isImageGenModel(name10, family) {
|
|
614319
614815
|
return IMAGE_GEN_PATTERNS.some((p2) => p2.test(name10) || family && p2.test(family));
|
|
614320
614816
|
}
|
|
@@ -614703,7 +615199,7 @@ async function queryModelContextSize(baseUrl2, modelName) {
|
|
|
614703
615199
|
}
|
|
614704
615200
|
}
|
|
614705
615201
|
function estimateRealisticContext(kvBytesPerToken, archMax, modelSizeGB2) {
|
|
614706
|
-
const totalMemGB =
|
|
615202
|
+
const totalMemGB = totalmem6() / 1024 ** 3;
|
|
614707
615203
|
const usableBytes = totalMemGB * 0.7 * 1024 ** 3;
|
|
614708
615204
|
const maxTokens = Math.floor(usableBytes / kvBytesPerToken);
|
|
614709
615205
|
let numCtx = Math.max(2048, Math.floor(maxTokens / 1024) * 1024);
|
|
@@ -617275,6 +617771,7 @@ let micStream = null;
|
|
|
617275
617771
|
let scriptProcessor = null;
|
|
617276
617772
|
let micActive = false;
|
|
617277
617773
|
let playbackQueue = [];
|
|
617774
|
+
let pendingTtsHeader = null;
|
|
617278
617775
|
let isPlaying = false;
|
|
617279
617776
|
let reconnectDelay = 1000;
|
|
617280
617777
|
let reconnectTimer = null;
|
|
@@ -617334,10 +617831,14 @@ function connect() {
|
|
|
617334
617831
|
waveState = 'speaking';
|
|
617335
617832
|
} else if (msg.type === 'speaking_end') {
|
|
617336
617833
|
waveState = micActive ? 'listening' : 'idle';
|
|
617834
|
+
} else if (msg.type === 'tts_header') {
|
|
617835
|
+
pendingTtsHeader = { sampleRate: msg.sampleRate || 22050 };
|
|
617337
617836
|
}
|
|
617338
617837
|
} catch {}
|
|
617339
617838
|
} else {
|
|
617340
|
-
|
|
617839
|
+
const sampleRate = (pendingTtsHeader && pendingTtsHeader.sampleRate) || 22050;
|
|
617840
|
+
pendingTtsHeader = null;
|
|
617841
|
+
playbackQueue.push({ pcm: new Int16Array(evt.data), sampleRate });
|
|
617341
617842
|
if (!isPlaying) drainPlayback();
|
|
617342
617843
|
}
|
|
617343
617844
|
};
|
|
@@ -617356,15 +617857,17 @@ function escapeHtml(s) {
|
|
|
617356
617857
|
}
|
|
617357
617858
|
|
|
617358
617859
|
async function drainPlayback() {
|
|
617359
|
-
if (!playbackCtx) playbackCtx = new AudioContext(
|
|
617860
|
+
if (!playbackCtx) playbackCtx = new AudioContext();
|
|
617360
617861
|
isPlaying = true;
|
|
617361
617862
|
while (playbackQueue.length > 0) {
|
|
617362
|
-
const
|
|
617863
|
+
const frame = playbackQueue.shift();
|
|
617864
|
+
const int16 = frame.pcm || frame;
|
|
617865
|
+
const sampleRate = frame.sampleRate || 22050;
|
|
617363
617866
|
const float32 = new Float32Array(int16.length);
|
|
617364
617867
|
for (let i = 0; i < int16.length; i++) {
|
|
617365
617868
|
float32[i] = int16[i] < 0 ? int16[i] / 0x8000 : int16[i] / 0x7FFF;
|
|
617366
617869
|
}
|
|
617367
|
-
const buf = playbackCtx.createBuffer(1, float32.length,
|
|
617870
|
+
const buf = playbackCtx.createBuffer(1, float32.length, sampleRate);
|
|
617368
617871
|
buf.getChannelData(0).set(float32);
|
|
617369
617872
|
const src = playbackCtx.createBufferSource();
|
|
617370
617873
|
src.buffer = buf;
|
|
@@ -618013,11 +618516,15 @@ var init_voice_session = __esm({
|
|
|
618013
618516
|
/**
|
|
618014
618517
|
* Send TTS audio (PCM Int16 @ model sample rate) to all connected clients.
|
|
618015
618518
|
*/
|
|
618016
|
-
sendAudioToClients(pcmInt16) {
|
|
618519
|
+
sendAudioToClients(pcmInt16, sampleRate = 22050) {
|
|
618017
618520
|
this.ttsSpeaking = true;
|
|
618521
|
+
const header = JSON.stringify({ type: "tts_header", sampleRate, bytes: pcmInt16.length });
|
|
618018
618522
|
for (const ws of this.wsClients.values()) {
|
|
618019
618523
|
try {
|
|
618020
|
-
if (ws.readyState === import_websocket5.default.OPEN)
|
|
618524
|
+
if (ws.readyState === import_websocket5.default.OPEN) {
|
|
618525
|
+
ws.send(header);
|
|
618526
|
+
ws.send(pcmInt16);
|
|
618527
|
+
}
|
|
618021
618528
|
} catch {
|
|
618022
618529
|
}
|
|
618023
618530
|
}
|
|
@@ -618025,11 +618532,15 @@ var init_voice_session = __esm({
|
|
|
618025
618532
|
/**
|
|
618026
618533
|
* Send TTS audio to a specific client by clientId.
|
|
618027
618534
|
*/
|
|
618028
|
-
sendAudioToClient(clientId, pcmInt16) {
|
|
618535
|
+
sendAudioToClient(clientId, pcmInt16, sampleRate = 22050) {
|
|
618536
|
+
this.ttsSpeaking = true;
|
|
618029
618537
|
const ws = this.wsClients.get(clientId);
|
|
618030
618538
|
if (ws) {
|
|
618031
618539
|
try {
|
|
618032
|
-
if (ws.readyState === import_websocket5.default.OPEN)
|
|
618540
|
+
if (ws.readyState === import_websocket5.default.OPEN) {
|
|
618541
|
+
ws.send(JSON.stringify({ type: "tts_header", sampleRate, bytes: pcmInt16.length }));
|
|
618542
|
+
ws.send(pcmInt16);
|
|
618543
|
+
}
|
|
618033
618544
|
} catch {
|
|
618034
618545
|
}
|
|
618035
618546
|
}
|
|
@@ -618038,6 +618549,7 @@ var init_voice_session = __esm({
|
|
|
618038
618549
|
* Send speaking state change to a specific client.
|
|
618039
618550
|
*/
|
|
618040
618551
|
sendSpeakingStateToClient(clientId, speaking) {
|
|
618552
|
+
this.ttsSpeaking = speaking;
|
|
618041
618553
|
const ws = this.wsClients.get(clientId);
|
|
618042
618554
|
if (ws) {
|
|
618043
618555
|
const msg = JSON.stringify({ type: speaking ? "speaking_start" : "speaking_end" });
|
|
@@ -619058,8 +619570,8 @@ import { spawn as spawn32, exec as exec3 } from "node:child_process";
|
|
|
619058
619570
|
import { EventEmitter as EventEmitter8 } from "node:events";
|
|
619059
619571
|
import { randomBytes as randomBytes22, timingSafeEqual } from "node:crypto";
|
|
619060
619572
|
import { URL as URL2 } from "node:url";
|
|
619061
|
-
import { loadavg, cpus as
|
|
619062
|
-
import { existsSync as existsSync117, readFileSync as readFileSync95, writeFileSync as writeFileSync60, unlinkSync as
|
|
619573
|
+
import { loadavg as loadavg2, cpus as cpus4, totalmem as totalmem7, freemem as freemem6 } from "node:os";
|
|
619574
|
+
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";
|
|
619063
619575
|
import { join as join132 } from "node:path";
|
|
619064
619576
|
function cleanForwardHeaders(raw, targetHost) {
|
|
619065
619577
|
const out = {};
|
|
@@ -619272,7 +619784,7 @@ function writeExposeState(stateDir, state) {
|
|
|
619272
619784
|
}
|
|
619273
619785
|
function removeExposeState(stateDir) {
|
|
619274
619786
|
try {
|
|
619275
|
-
|
|
619787
|
+
unlinkSync21(join132(stateDir, STATE_FILE_NAME));
|
|
619276
619788
|
} catch {
|
|
619277
619789
|
}
|
|
619278
619790
|
}
|
|
@@ -619316,10 +619828,10 @@ function parseRateLimitHeaders(headers) {
|
|
|
619316
619828
|
};
|
|
619317
619829
|
}
|
|
619318
619830
|
async function collectSystemMetricsAsync() {
|
|
619319
|
-
const [l1, l5, l15] =
|
|
619320
|
-
const cores =
|
|
619321
|
-
const totalMem =
|
|
619322
|
-
const freeMem =
|
|
619831
|
+
const [l1, l5, l15] = loadavg2();
|
|
619832
|
+
const cores = cpus4().length;
|
|
619833
|
+
const totalMem = totalmem7();
|
|
619834
|
+
const freeMem = freemem6();
|
|
619323
619835
|
const usedMem = totalMem - freeMem;
|
|
619324
619836
|
let disk = {
|
|
619325
619837
|
path: process.cwd(),
|
|
@@ -619410,7 +619922,7 @@ function writeP2PExposeState(stateDir, state) {
|
|
|
619410
619922
|
}
|
|
619411
619923
|
function removeP2PExposeState(stateDir) {
|
|
619412
619924
|
try {
|
|
619413
|
-
|
|
619925
|
+
unlinkSync21(join132(stateDir, P2P_STATE_FILE_NAME));
|
|
619414
619926
|
} catch {
|
|
619415
619927
|
}
|
|
619416
619928
|
}
|
|
@@ -622545,7 +623057,7 @@ ${activitySummary}
|
|
|
622545
623057
|
});
|
|
622546
623058
|
|
|
622547
623059
|
// packages/cli/src/api/profiles.ts
|
|
622548
|
-
import { existsSync as existsSync119, readFileSync as readFileSync97, writeFileSync as writeFileSync62, mkdirSync as mkdirSync74, readdirSync as readdirSync39, unlinkSync as
|
|
623060
|
+
import { existsSync as existsSync119, readFileSync as readFileSync97, writeFileSync as writeFileSync62, mkdirSync as mkdirSync74, readdirSync as readdirSync39, unlinkSync as unlinkSync22 } from "node:fs";
|
|
622549
623061
|
import { join as join134 } from "node:path";
|
|
622550
623062
|
import { homedir as homedir41 } from "node:os";
|
|
622551
623063
|
import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes25, scryptSync as scryptSync3 } from "node:crypto";
|
|
@@ -622649,7 +623161,7 @@ function deleteProfile(name10, scope = "global", projectDir2) {
|
|
|
622649
623161
|
const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
|
|
622650
623162
|
const filePath = join134(dir, `${sanitized}.json`);
|
|
622651
623163
|
if (existsSync119(filePath)) {
|
|
622652
|
-
|
|
623164
|
+
unlinkSync22(filePath);
|
|
622653
623165
|
return true;
|
|
622654
623166
|
}
|
|
622655
623167
|
return false;
|
|
@@ -622927,7 +623439,7 @@ __export(omnius_directory_exports, {
|
|
|
622927
623439
|
writeIndexMeta: () => writeIndexMeta,
|
|
622928
623440
|
writeTaskHandoff: () => writeTaskHandoff2
|
|
622929
623441
|
});
|
|
622930
|
-
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
|
|
623442
|
+
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";
|
|
622931
623443
|
import { join as join135, relative as relative13, basename as basename25, dirname as dirname40, resolve as resolve57 } from "node:path";
|
|
622932
623444
|
import { homedir as homedir42 } from "node:os";
|
|
622933
623445
|
import { createHash as createHash37 } from "node:crypto";
|
|
@@ -623318,7 +623830,7 @@ function loadPendingTask(repoRoot) {
|
|
|
623318
623830
|
if (!existsSync120(filePath)) return null;
|
|
623319
623831
|
const data = JSON.parse(readFileSync98(filePath, "utf-8"));
|
|
623320
623832
|
try {
|
|
623321
|
-
|
|
623833
|
+
unlinkSync23(filePath);
|
|
623322
623834
|
} catch {
|
|
623323
623835
|
}
|
|
623324
623836
|
return data;
|
|
@@ -623337,7 +623849,7 @@ function writeTaskHandoff2(repoRoot, handoff) {
|
|
|
623337
623849
|
} catch {
|
|
623338
623850
|
writeFileSync63(filePath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
|
|
623339
623851
|
try {
|
|
623340
|
-
|
|
623852
|
+
unlinkSync23(tempPath);
|
|
623341
623853
|
} catch {
|
|
623342
623854
|
}
|
|
623343
623855
|
}
|
|
@@ -623363,7 +623875,7 @@ function clearTaskHandoff(repoRoot) {
|
|
|
623363
623875
|
const filePath = join135(repoRoot, OMNIUS_DIR, "context", HANDOFF_FILE);
|
|
623364
623876
|
try {
|
|
623365
623877
|
if (existsSync120(filePath)) {
|
|
623366
|
-
|
|
623878
|
+
unlinkSync23(filePath);
|
|
623367
623879
|
}
|
|
623368
623880
|
} catch {
|
|
623369
623881
|
}
|
|
@@ -623437,13 +623949,13 @@ function acquireLock(lockPath) {
|
|
|
623437
623949
|
const lockAge = Date.now() - lock.acquiredAt;
|
|
623438
623950
|
if (lockAge > LOCK_TIMEOUT_MS) {
|
|
623439
623951
|
try {
|
|
623440
|
-
|
|
623952
|
+
unlinkSync23(lockPath);
|
|
623441
623953
|
} catch {
|
|
623442
623954
|
}
|
|
623443
623955
|
}
|
|
623444
623956
|
} catch {
|
|
623445
623957
|
try {
|
|
623446
|
-
|
|
623958
|
+
unlinkSync23(lockPath);
|
|
623447
623959
|
} catch {
|
|
623448
623960
|
}
|
|
623449
623961
|
}
|
|
@@ -623461,7 +623973,7 @@ function releaseLock(lockPath) {
|
|
|
623461
623973
|
const lockContent = readFileSync98(lockPath, "utf-8");
|
|
623462
623974
|
const lock = JSON.parse(lockContent);
|
|
623463
623975
|
if (lock.pid === process.pid) {
|
|
623464
|
-
|
|
623976
|
+
unlinkSync23(lockPath);
|
|
623465
623977
|
}
|
|
623466
623978
|
}
|
|
623467
623979
|
} catch {
|
|
@@ -623647,7 +624159,7 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
623647
624159
|
} catch {
|
|
623648
624160
|
writeFileSync63(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
|
|
623649
624161
|
try {
|
|
623650
|
-
|
|
624162
|
+
unlinkSync23(tempFilePath);
|
|
623651
624163
|
} catch {
|
|
623652
624164
|
}
|
|
623653
624165
|
}
|
|
@@ -624030,7 +624542,7 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
|
624030
624542
|
if (index.length > 50) {
|
|
624031
624543
|
const removed = index.shift();
|
|
624032
624544
|
try {
|
|
624033
|
-
|
|
624545
|
+
unlinkSync23(join135(sessDir, `${removed.id}.jsonl`));
|
|
624034
624546
|
} catch {
|
|
624035
624547
|
}
|
|
624036
624548
|
}
|
|
@@ -624060,7 +624572,7 @@ function deleteSession(repoRoot, sessionId) {
|
|
|
624060
624572
|
const indexPath = join135(sessDir, SESSIONS_INDEX);
|
|
624061
624573
|
try {
|
|
624062
624574
|
const contentPath = join135(sessDir, `${sessionId}.jsonl`);
|
|
624063
|
-
if (existsSync120(contentPath))
|
|
624575
|
+
if (existsSync120(contentPath)) unlinkSync23(contentPath);
|
|
624064
624576
|
if (existsSync120(indexPath)) {
|
|
624065
624577
|
let index = JSON.parse(readFileSync98(indexPath, "utf-8"));
|
|
624066
624578
|
index = index.filter((s2) => s2.id !== sessionId);
|
|
@@ -624398,7 +624910,7 @@ function firstMeaningfulLine(transcript) {
|
|
|
624398
624910
|
}
|
|
624399
624911
|
return "";
|
|
624400
624912
|
}
|
|
624401
|
-
function
|
|
624913
|
+
function clamp9(value2, max) {
|
|
624402
624914
|
const v = value2.replace(/\s+/g, " ").trim();
|
|
624403
624915
|
return v.length > max ? v.slice(0, max - 1).trimEnd() + "…" : v;
|
|
624404
624916
|
}
|
|
@@ -624406,8 +624918,8 @@ function deterministicSummary(transcript) {
|
|
|
624406
624918
|
const first2 = firstMeaningfulLine(transcript);
|
|
624407
624919
|
if (!first2) return { title: "Untitled session", summary: "Empty session." };
|
|
624408
624920
|
const cleaned = first2.replace(TUI_MARKER_PREFIX, "").replace(/^[>›$#\s]+/, "").trim();
|
|
624409
|
-
const title =
|
|
624410
|
-
return { title: title || "Untitled session", summary:
|
|
624921
|
+
const title = clamp9(cleaned, TITLE_MAX);
|
|
624922
|
+
return { title: title || "Untitled session", summary: clamp9(cleaned || first2, SUMMARY_MAX) };
|
|
624411
624923
|
}
|
|
624412
624924
|
function parseSummaryReply(content) {
|
|
624413
624925
|
if (!content) return null;
|
|
@@ -624459,8 +624971,8 @@ async function generateSessionSummary(args) {
|
|
|
624459
624971
|
const parsed = parseSummaryReply(content);
|
|
624460
624972
|
if (!parsed) return fallback;
|
|
624461
624973
|
return {
|
|
624462
|
-
title:
|
|
624463
|
-
summary:
|
|
624974
|
+
title: clamp9(parsed.title, TITLE_MAX) || fallback.title,
|
|
624975
|
+
summary: clamp9(parsed.summary, SUMMARY_MAX) || fallback.summary
|
|
624464
624976
|
};
|
|
624465
624977
|
} catch {
|
|
624466
624978
|
return fallback;
|
|
@@ -625490,7 +626002,7 @@ __export(system_metrics_exports, {
|
|
|
625490
626002
|
getInstantSnapshot: () => getInstantSnapshot,
|
|
625491
626003
|
instantaneousCpuPct: () => instantaneousCpuPct
|
|
625492
626004
|
});
|
|
625493
|
-
import { loadavg as
|
|
626005
|
+
import { loadavg as loadavg3, cpus as cpus5, totalmem as totalmem8, freemem as freemem7, platform as platform4 } from "node:os";
|
|
625494
626006
|
import { exec as exec4 } from "node:child_process";
|
|
625495
626007
|
import { readFile as readFile24 } from "node:fs/promises";
|
|
625496
626008
|
function formatRate(bytesPerSec) {
|
|
@@ -625659,7 +626171,7 @@ function getInstantSnapshot() {
|
|
|
625659
626171
|
function readCpuTimes() {
|
|
625660
626172
|
let idle = 0;
|
|
625661
626173
|
let total = 0;
|
|
625662
|
-
for (const cpu of
|
|
626174
|
+
for (const cpu of cpus5()) {
|
|
625663
626175
|
const t2 = cpu.times;
|
|
625664
626176
|
idle += t2.idle;
|
|
625665
626177
|
total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
|
|
@@ -625678,13 +626190,13 @@ function instantaneousCpuPct() {
|
|
|
625678
626190
|
return Math.max(0, Math.min(100, Math.round(usage * 100)));
|
|
625679
626191
|
}
|
|
625680
626192
|
function collectCpuRam() {
|
|
625681
|
-
const cores =
|
|
625682
|
-
const cpuModel =
|
|
625683
|
-
const totalMem =
|
|
625684
|
-
const usedMem = totalMem -
|
|
626193
|
+
const cores = cpus5().length;
|
|
626194
|
+
const cpuModel = cpus5()[0]?.model ?? "";
|
|
626195
|
+
const totalMem = totalmem8();
|
|
626196
|
+
const usedMem = totalMem - freemem7();
|
|
625685
626197
|
let cpuUtil = instantaneousCpuPct();
|
|
625686
626198
|
if (cpuUtil < 0) {
|
|
625687
|
-
const [l1] =
|
|
626199
|
+
const [l1] = loadavg3();
|
|
625688
626200
|
cpuUtil = Math.max(0, Math.min(100, Math.round(l1 / cores * 100)));
|
|
625689
626201
|
}
|
|
625690
626202
|
return {
|
|
@@ -633100,7 +633612,7 @@ import { spawn as spawn34, exec as exec5 } from "node:child_process";
|
|
|
633100
633612
|
import { promisify as promisify7 } from "node:util";
|
|
633101
633613
|
import { existsSync as existsSync126, writeFileSync as writeFileSync66, readFileSync as readFileSync104, appendFileSync as appendFileSync14, mkdirSync as mkdirSync78, chmodSync as chmodSync3 } from "node:fs";
|
|
633102
633614
|
import { delimiter as pathDelimiter, join as join141 } from "node:path";
|
|
633103
|
-
import { freemem as
|
|
633615
|
+
import { freemem as freemem8, homedir as homedir46, platform as platform5, totalmem as totalmem9 } from "node:os";
|
|
633104
633616
|
function wrapText2(value2, width) {
|
|
633105
633617
|
const words = value2.split(/\s+/).filter(Boolean);
|
|
633106
633618
|
const lines = [];
|
|
@@ -633213,8 +633725,8 @@ function parseRocmSmi(stdout) {
|
|
|
633213
633725
|
return { total, free: Math.max(0, total - used), name: name10 ? `AMD ${name10}` : "AMD GPU" };
|
|
633214
633726
|
}
|
|
633215
633727
|
function detectSystemSpecs() {
|
|
633216
|
-
let totalRamGB =
|
|
633217
|
-
let availableRamGB =
|
|
633728
|
+
let totalRamGB = totalmem9() / 1024 ** 3;
|
|
633729
|
+
let availableRamGB = freemem8() / 1024 ** 3;
|
|
633218
633730
|
let gpuVramGB = 0;
|
|
633219
633731
|
let availableVramGB = 0;
|
|
633220
633732
|
const gpuName = "";
|
|
@@ -639995,7 +640507,7 @@ var init_audio_waveform = __esm({
|
|
|
639995
640507
|
});
|
|
639996
640508
|
|
|
639997
640509
|
// packages/cli/src/tui/neovim-mode.ts
|
|
639998
|
-
import { existsSync as existsSync132, unlinkSync as
|
|
640510
|
+
import { existsSync as existsSync132, unlinkSync as unlinkSync25 } from "node:fs";
|
|
639999
640511
|
import { tmpdir as tmpdir22 } from "node:os";
|
|
640000
640512
|
import { join as join145 } from "node:path";
|
|
640001
640513
|
function isNeovimActive() {
|
|
@@ -640044,7 +640556,7 @@ async function startNeovimMode(opts) {
|
|
|
640044
640556
|
}
|
|
640045
640557
|
const socketPath = join145(tmpdir22(), `omnius-nvim-${process.pid}-${Date.now()}.sock`);
|
|
640046
640558
|
try {
|
|
640047
|
-
if (existsSync132(socketPath))
|
|
640559
|
+
if (existsSync132(socketPath)) unlinkSync25(socketPath);
|
|
640048
640560
|
} catch {
|
|
640049
640561
|
}
|
|
640050
640562
|
const ptyCols = opts.cols;
|
|
@@ -640433,7 +640945,7 @@ function doCleanup(state) {
|
|
|
640433
640945
|
state.pty = null;
|
|
640434
640946
|
}
|
|
640435
640947
|
try {
|
|
640436
|
-
if (existsSync132(state.socketPath))
|
|
640948
|
+
if (existsSync132(state.socketPath)) unlinkSync25(state.socketPath);
|
|
640437
640949
|
} catch {
|
|
640438
640950
|
}
|
|
640439
640951
|
if (state.stdinHandler) {
|
|
@@ -640508,7 +641020,7 @@ __export(daemon_exports, {
|
|
|
640508
641020
|
stopDaemon: () => stopDaemon
|
|
640509
641021
|
});
|
|
640510
641022
|
import { spawn as spawn35 } from "node:child_process";
|
|
640511
|
-
import { existsSync as existsSync133, readFileSync as readFileSync108, writeFileSync as writeFileSync67, mkdirSync as mkdirSync79, unlinkSync as
|
|
641023
|
+
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";
|
|
640512
641024
|
import { join as join146 } from "node:path";
|
|
640513
641025
|
import { homedir as homedir48 } from "node:os";
|
|
640514
641026
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
@@ -640584,7 +641096,7 @@ function getDaemonPid() {
|
|
|
640584
641096
|
return pid;
|
|
640585
641097
|
} catch {
|
|
640586
641098
|
try {
|
|
640587
|
-
|
|
641099
|
+
unlinkSync26(PID_FILE2);
|
|
640588
641100
|
} catch {
|
|
640589
641101
|
}
|
|
640590
641102
|
return null;
|
|
@@ -640700,13 +641212,13 @@ function stopDaemon() {
|
|
|
640700
641212
|
}
|
|
640701
641213
|
process.kill(pid, "SIGTERM");
|
|
640702
641214
|
try {
|
|
640703
|
-
|
|
641215
|
+
unlinkSync26(PID_FILE2);
|
|
640704
641216
|
} catch {
|
|
640705
641217
|
}
|
|
640706
641218
|
return true;
|
|
640707
641219
|
} catch {
|
|
640708
641220
|
try {
|
|
640709
|
-
|
|
641221
|
+
unlinkSync26(PID_FILE2);
|
|
640710
641222
|
} catch {
|
|
640711
641223
|
}
|
|
640712
641224
|
return false;
|
|
@@ -640737,7 +641249,7 @@ async function forceKillDaemon(port) {
|
|
|
640737
641249
|
} catch {
|
|
640738
641250
|
}
|
|
640739
641251
|
try {
|
|
640740
|
-
|
|
641252
|
+
unlinkSync26(PID_FILE2);
|
|
640741
641253
|
} catch {
|
|
640742
641254
|
}
|
|
640743
641255
|
}
|
|
@@ -640792,7 +641304,7 @@ async function ensureDaemon() {
|
|
|
640792
641304
|
} catch {
|
|
640793
641305
|
}
|
|
640794
641306
|
try {
|
|
640795
|
-
|
|
641307
|
+
unlinkSync26(PID_FILE2);
|
|
640796
641308
|
} catch {
|
|
640797
641309
|
}
|
|
640798
641310
|
}
|
|
@@ -640809,7 +641321,7 @@ async function ensureDaemon() {
|
|
|
640809
641321
|
} catch {
|
|
640810
641322
|
}
|
|
640811
641323
|
try {
|
|
640812
|
-
|
|
641324
|
+
unlinkSync26(PID_FILE2);
|
|
640813
641325
|
} catch {
|
|
640814
641326
|
}
|
|
640815
641327
|
return false;
|
|
@@ -641272,7 +641784,7 @@ import {
|
|
|
641272
641784
|
mkdirSync as mkdirSync80,
|
|
641273
641785
|
chmodSync as chmodSync4,
|
|
641274
641786
|
existsSync as existsSync136,
|
|
641275
|
-
unlinkSync as
|
|
641787
|
+
unlinkSync as unlinkSync27,
|
|
641276
641788
|
readdirSync as readdirSync44
|
|
641277
641789
|
} from "node:fs";
|
|
641278
641790
|
import { join as join149 } from "node:path";
|
|
@@ -641467,12 +641979,12 @@ function saveJobs(jobs) {
|
|
|
641467
641979
|
const tmp = path12 + ".tmp";
|
|
641468
641980
|
writeFileSync68(tmp, content, "utf-8");
|
|
641469
641981
|
try {
|
|
641470
|
-
|
|
641982
|
+
unlinkSync27(path12);
|
|
641471
641983
|
} catch {
|
|
641472
641984
|
}
|
|
641473
641985
|
writeFileSync68(path12, content, "utf-8");
|
|
641474
641986
|
try {
|
|
641475
|
-
|
|
641987
|
+
unlinkSync27(tmp);
|
|
641476
641988
|
} catch {
|
|
641477
641989
|
}
|
|
641478
641990
|
secureFile(path12);
|
|
@@ -641821,7 +642333,7 @@ import {
|
|
|
641821
642333
|
openSync as openSync5,
|
|
641822
642334
|
closeSync as closeSync5,
|
|
641823
642335
|
writeFileSync as writeFileSync69,
|
|
641824
|
-
unlinkSync as
|
|
642336
|
+
unlinkSync as unlinkSync28,
|
|
641825
642337
|
readFileSync as readFileSync110
|
|
641826
642338
|
} from "node:fs";
|
|
641827
642339
|
import { join as join150 } from "node:path";
|
|
@@ -641846,7 +642358,7 @@ function acquireTickLock() {
|
|
|
641846
642358
|
if (age < 3e5) return false;
|
|
641847
642359
|
}
|
|
641848
642360
|
try {
|
|
641849
|
-
|
|
642361
|
+
unlinkSync28(lockPath);
|
|
641850
642362
|
} catch {
|
|
641851
642363
|
}
|
|
641852
642364
|
}
|
|
@@ -641863,7 +642375,7 @@ function acquireTickLock() {
|
|
|
641863
642375
|
}
|
|
641864
642376
|
function releaseTickLock() {
|
|
641865
642377
|
try {
|
|
641866
|
-
|
|
642378
|
+
unlinkSync28(lockFilePath());
|
|
641867
642379
|
} catch {
|
|
641868
642380
|
}
|
|
641869
642381
|
}
|
|
@@ -643576,7 +644088,7 @@ import {
|
|
|
643576
644088
|
mkdirSync as mkdirSync83,
|
|
643577
644089
|
writeFileSync as writeFileSync71,
|
|
643578
644090
|
readFileSync as readFileSync112,
|
|
643579
|
-
unlinkSync as
|
|
644091
|
+
unlinkSync as unlinkSync29,
|
|
643580
644092
|
readdirSync as readdirSync45,
|
|
643581
644093
|
statSync as statSync52,
|
|
643582
644094
|
copyFileSync as copyFileSync6,
|
|
@@ -645214,7 +645726,7 @@ except Exception as exc:
|
|
|
645214
645726
|
const p2 = join152(luxttsCloneRefsDir(), filename);
|
|
645215
645727
|
if (!existsSync139(p2)) return false;
|
|
645216
645728
|
try {
|
|
645217
|
-
|
|
645729
|
+
unlinkSync29(p2);
|
|
645218
645730
|
const meta = this.loadCloneMeta();
|
|
645219
645731
|
delete meta[filename];
|
|
645220
645732
|
this.saveCloneMeta(meta);
|
|
@@ -645589,7 +646101,7 @@ except Exception as exc:
|
|
|
645589
646101
|
}
|
|
645590
646102
|
if (prefetchedWav) {
|
|
645591
646103
|
try {
|
|
645592
|
-
|
|
646104
|
+
unlinkSync29(prefetchedWav.path);
|
|
645593
646105
|
} catch {
|
|
645594
646106
|
}
|
|
645595
646107
|
}
|
|
@@ -645683,7 +646195,7 @@ except Exception as exc:
|
|
|
645683
646195
|
this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
|
|
645684
646196
|
await this.playWav(wavPath);
|
|
645685
646197
|
try {
|
|
645686
|
-
|
|
646198
|
+
unlinkSync29(wavPath);
|
|
645687
646199
|
} catch {
|
|
645688
646200
|
}
|
|
645689
646201
|
}
|
|
@@ -646229,7 +646741,7 @@ except Exception as exc:
|
|
|
646229
646741
|
if (!wavPath) return null;
|
|
646230
646742
|
try {
|
|
646231
646743
|
const data = readFileSync112(wavPath);
|
|
646232
|
-
|
|
646744
|
+
unlinkSync29(wavPath);
|
|
646233
646745
|
return data;
|
|
646234
646746
|
} catch {
|
|
646235
646747
|
return null;
|
|
@@ -646413,7 +646925,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
646413
646925
|
}
|
|
646414
646926
|
await this.playWav(wavPath);
|
|
646415
646927
|
try {
|
|
646416
|
-
|
|
646928
|
+
unlinkSync29(wavPath);
|
|
646417
646929
|
} catch {
|
|
646418
646930
|
}
|
|
646419
646931
|
}
|
|
@@ -646457,7 +646969,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
646457
646969
|
if (!existsSync139(wavPath)) return null;
|
|
646458
646970
|
try {
|
|
646459
646971
|
const data = readFileSync112(wavPath);
|
|
646460
|
-
|
|
646972
|
+
unlinkSync29(wavPath);
|
|
646461
646973
|
return data;
|
|
646462
646974
|
} catch {
|
|
646463
646975
|
return null;
|
|
@@ -647413,7 +647925,7 @@ if __name__ == '__main__':
|
|
|
647413
647925
|
await this.playWav(wavPath);
|
|
647414
647926
|
await this.sleep(150);
|
|
647415
647927
|
try {
|
|
647416
|
-
|
|
647928
|
+
unlinkSync29(wavPath);
|
|
647417
647929
|
} catch {
|
|
647418
647930
|
}
|
|
647419
647931
|
}
|
|
@@ -647453,7 +647965,7 @@ if __name__ == '__main__':
|
|
|
647453
647965
|
if (!existsSync139(wavPath)) return null;
|
|
647454
647966
|
try {
|
|
647455
647967
|
const data = readFileSync112(wavPath);
|
|
647456
|
-
|
|
647968
|
+
unlinkSync29(wavPath);
|
|
647457
647969
|
return data;
|
|
647458
647970
|
} catch {
|
|
647459
647971
|
return null;
|
|
@@ -647780,7 +648292,7 @@ if __name__ == "__main__":
|
|
|
647780
648292
|
await this.playWav(wavPath);
|
|
647781
648293
|
await this.sleep(150);
|
|
647782
648294
|
try {
|
|
647783
|
-
|
|
648295
|
+
unlinkSync29(wavPath);
|
|
647784
648296
|
} catch {
|
|
647785
648297
|
}
|
|
647786
648298
|
}
|
|
@@ -647829,7 +648341,7 @@ if __name__ == "__main__":
|
|
|
647829
648341
|
if (!existsSync139(wavPath)) return null;
|
|
647830
648342
|
try {
|
|
647831
648343
|
const data = readFileSync112(wavPath);
|
|
647832
|
-
|
|
648344
|
+
unlinkSync29(wavPath);
|
|
647833
648345
|
return data;
|
|
647834
648346
|
} catch {
|
|
647835
648347
|
return null;
|
|
@@ -658674,6 +659186,134 @@ async function chooseLiveDevice(ctx3, title, devices, activeKey) {
|
|
|
658674
659186
|
if (!result.confirmed || !result.key) return null;
|
|
658675
659187
|
return devices.find((device) => device.id === result.key) ?? null;
|
|
658676
659188
|
}
|
|
659189
|
+
function liveCameraStreamSummary(manager, deviceId) {
|
|
659190
|
+
return `${manager.isCameraStreamEnabled(deviceId) ? liveEnabled(true) : liveEnabled(false)} · ${formatLiveCameraResolution(manager.getCameraStreamResolution(deviceId))} · ${formatCameraRotation(manager.getCameraRotation(deviceId))}`;
|
|
659191
|
+
}
|
|
659192
|
+
async function chooseLiveCameraResolution(ctx3, manager, deviceId) {
|
|
659193
|
+
const current = manager.getCameraStreamResolution(deviceId);
|
|
659194
|
+
const choices = ["640x480", "1280x720", "1920x1080", "2560x1440", "3840x2160", "native"];
|
|
659195
|
+
const result = await tuiSelect({
|
|
659196
|
+
items: choices.map((resolution) => ({
|
|
659197
|
+
key: resolution,
|
|
659198
|
+
label: formatLiveCameraResolution(resolution),
|
|
659199
|
+
detail: resolution === "native" ? "use camera native format; highest burden" : resolution === "1920x1080" ? "default balanced stream size" : "downscaled camera stream"
|
|
659200
|
+
})),
|
|
659201
|
+
title: `Camera Resolution — ${deviceId}`,
|
|
659202
|
+
activeKey: current,
|
|
659203
|
+
rl: ctx3.rl,
|
|
659204
|
+
availableRows: ctx3.availableContentRows?.()
|
|
659205
|
+
});
|
|
659206
|
+
if (!result.confirmed || !result.key) return null;
|
|
659207
|
+
return normalizeLiveCameraResolution(result.key);
|
|
659208
|
+
}
|
|
659209
|
+
async function showLiveCameraMenu(ctx3, manager, device) {
|
|
659210
|
+
while (true) {
|
|
659211
|
+
const selected = manager.getConfig().selectedCamera === device.id;
|
|
659212
|
+
const enabled2 = manager.isCameraStreamEnabled(device.id);
|
|
659213
|
+
const resolution = manager.getCameraStreamResolution(device.id);
|
|
659214
|
+
const items = [
|
|
659215
|
+
{ key: "hdr:camera", label: selectColors.dim(`─── Camera ${device.id} ───`) },
|
|
659216
|
+
{
|
|
659217
|
+
key: "info:camera",
|
|
659218
|
+
label: selectColors.dim(` ${device.label}${device.detail ? ` · ${device.detail}` : ""}`)
|
|
659219
|
+
},
|
|
659220
|
+
{
|
|
659221
|
+
key: "select",
|
|
659222
|
+
label: selected ? "Selected Camera" : "Select Camera",
|
|
659223
|
+
detail: "make this the primary live camera"
|
|
659224
|
+
},
|
|
659225
|
+
{
|
|
659226
|
+
key: "toggle",
|
|
659227
|
+
label: enabled2 ? "Disable This Camera Stream" : "Enable This Camera Stream",
|
|
659228
|
+
detail: "disabled cameras stay available but do not consume ffmpeg/vision resources"
|
|
659229
|
+
},
|
|
659230
|
+
{
|
|
659231
|
+
key: "resolution",
|
|
659232
|
+
label: "Set Stream Resolution",
|
|
659233
|
+
detail: formatLiveCameraResolution(resolution)
|
|
659234
|
+
},
|
|
659235
|
+
{
|
|
659236
|
+
key: "preview",
|
|
659237
|
+
label: "Preview Camera",
|
|
659238
|
+
detail: "capture frame + ASCII preview"
|
|
659239
|
+
},
|
|
659240
|
+
{
|
|
659241
|
+
key: "infer",
|
|
659242
|
+
label: "Infer Camera Now",
|
|
659243
|
+
detail: "run bounded vision inference on this camera"
|
|
659244
|
+
},
|
|
659245
|
+
{
|
|
659246
|
+
key: "auto-orient",
|
|
659247
|
+
label: "Auto-Orient Camera",
|
|
659248
|
+
detail: "detect persistent rotation correction"
|
|
659249
|
+
},
|
|
659250
|
+
{
|
|
659251
|
+
key: "cycle-rotation",
|
|
659252
|
+
label: "Cycle Rotation",
|
|
659253
|
+
detail: formatCameraRotation(manager.getCameraRotation(device.id))
|
|
659254
|
+
},
|
|
659255
|
+
{ key: "rotate-0", label: "Rotation: Upright", detail: "0 degrees" },
|
|
659256
|
+
{ key: "rotate-90", label: "Rotation: Clockwise", detail: "90 degrees" },
|
|
659257
|
+
{ key: "rotate-180", label: "Rotation: 180", detail: "upside down correction" },
|
|
659258
|
+
{ key: "rotate-270", label: "Rotation: Counter-clockwise", detail: "270 degrees" }
|
|
659259
|
+
];
|
|
659260
|
+
const result = await tuiSelect({
|
|
659261
|
+
items,
|
|
659262
|
+
title: `Live Camera — ${device.id}`,
|
|
659263
|
+
activeKey: selected ? "select" : enabled2 ? "toggle" : void 0,
|
|
659264
|
+
rl: ctx3.rl,
|
|
659265
|
+
availableRows: ctx3.availableContentRows?.(),
|
|
659266
|
+
skipKeys: liveSkipKeys(items)
|
|
659267
|
+
});
|
|
659268
|
+
if (!result.confirmed || !result.key) return;
|
|
659269
|
+
switch (result.key) {
|
|
659270
|
+
case "select":
|
|
659271
|
+
manager.configure({ selectedCamera: device.id, videoEnabled: true });
|
|
659272
|
+
manager.setCameraStreamEnabled(device.id, true);
|
|
659273
|
+
renderInfo(`Selected camera ${device.id}.`);
|
|
659274
|
+
continue;
|
|
659275
|
+
case "toggle":
|
|
659276
|
+
manager.setCameraStreamEnabled(device.id, !enabled2);
|
|
659277
|
+
renderInfo(`${!enabled2 ? "Enabled" : "Disabled"} camera stream ${device.id}.`);
|
|
659278
|
+
continue;
|
|
659279
|
+
case "resolution": {
|
|
659280
|
+
const next = await chooseLiveCameraResolution(ctx3, manager, device.id);
|
|
659281
|
+
if (next) {
|
|
659282
|
+
manager.setCameraStreamResolution(device.id, next);
|
|
659283
|
+
renderInfo(`Camera ${device.id} stream resolution set to ${formatLiveCameraResolution(next)}.`);
|
|
659284
|
+
}
|
|
659285
|
+
continue;
|
|
659286
|
+
}
|
|
659287
|
+
case "preview":
|
|
659288
|
+
renderLivePreview(await manager.previewCamera(device.id));
|
|
659289
|
+
continue;
|
|
659290
|
+
case "infer":
|
|
659291
|
+
manager.setCameraStreamEnabled(device.id, true);
|
|
659292
|
+
renderInfo(await manager.sampleCameraNow(device.id, true, { forceInferenceNow: true }));
|
|
659293
|
+
continue;
|
|
659294
|
+
case "auto-orient":
|
|
659295
|
+
renderInfo("Detecting camera orientation...");
|
|
659296
|
+
renderInfo(await manager.autoOrientCamera(device.id));
|
|
659297
|
+
continue;
|
|
659298
|
+
case "cycle-rotation": {
|
|
659299
|
+
const orientation = manager.cycleCameraRotation(device.id);
|
|
659300
|
+
renderInfo(orientation ? `Camera rotation set to ${formatCameraRotation(orientation.rotation)} for ${device.id}.` : "No camera selected.");
|
|
659301
|
+
continue;
|
|
659302
|
+
}
|
|
659303
|
+
case "rotate-0":
|
|
659304
|
+
case "rotate-90":
|
|
659305
|
+
case "rotate-180":
|
|
659306
|
+
case "rotate-270": {
|
|
659307
|
+
const rotation = normalizeLiveCameraRotation(result.key.replace("rotate-", ""));
|
|
659308
|
+
const orientation = manager.setCameraRotation(device.id, rotation, "manual", `/live camera menu ${result.key}`);
|
|
659309
|
+
renderInfo(orientation ? `Camera rotation set to ${formatCameraRotation(orientation.rotation)} for ${device.id}.` : "No camera selected.");
|
|
659310
|
+
continue;
|
|
659311
|
+
}
|
|
659312
|
+
default:
|
|
659313
|
+
return;
|
|
659314
|
+
}
|
|
659315
|
+
}
|
|
659316
|
+
}
|
|
658677
659317
|
async function handleLiveCommand(ctx3, arg) {
|
|
658678
659318
|
const manager = getLiveSensorManager(ctx3.repoRoot);
|
|
658679
659319
|
attachLiveSinks(ctx3, manager);
|
|
@@ -658745,6 +659385,40 @@ async function handleLiveCommand(ctx3, arg) {
|
|
|
658745
659385
|
}
|
|
658746
659386
|
return;
|
|
658747
659387
|
}
|
|
659388
|
+
if (sub2 === "resolution" || sub2 === "res" || sub2 === "size") {
|
|
659389
|
+
await ensureLiveInventory(manager);
|
|
659390
|
+
const tokens = parts.slice(1);
|
|
659391
|
+
const rawResolution = tokens.pop();
|
|
659392
|
+
if (!rawResolution) {
|
|
659393
|
+
renderWarning("Usage: /live resolution [camera] 720p|1080p|1440p|4k|native");
|
|
659394
|
+
return;
|
|
659395
|
+
}
|
|
659396
|
+
const device = tokens.join(" ") || manager.getConfig().selectedCamera;
|
|
659397
|
+
if (!device) {
|
|
659398
|
+
renderWarning("No camera selected. Use /live camera <device> first.");
|
|
659399
|
+
return;
|
|
659400
|
+
}
|
|
659401
|
+
try {
|
|
659402
|
+
const resolution = normalizeLiveCameraResolution(rawResolution);
|
|
659403
|
+
manager.setCameraStreamResolution(device, resolution);
|
|
659404
|
+
renderInfo(`Camera ${device} stream resolution set to ${formatLiveCameraResolution(resolution)}.`);
|
|
659405
|
+
} catch (err) {
|
|
659406
|
+
renderWarning(err instanceof Error ? err.message : String(err));
|
|
659407
|
+
}
|
|
659408
|
+
return;
|
|
659409
|
+
}
|
|
659410
|
+
if (sub2 === "camera-on" || sub2 === "camera-off" || sub2 === "camera-enable" || sub2 === "camera-disable") {
|
|
659411
|
+
await ensureLiveInventory(manager);
|
|
659412
|
+
const device = value2 || manager.getConfig().selectedCamera;
|
|
659413
|
+
if (!device) {
|
|
659414
|
+
renderWarning("No camera selected. Use /live camera <device> first.");
|
|
659415
|
+
return;
|
|
659416
|
+
}
|
|
659417
|
+
const enabled2 = sub2 === "camera-on" || sub2 === "camera-enable";
|
|
659418
|
+
manager.setCameraStreamEnabled(device, enabled2);
|
|
659419
|
+
renderInfo(`${enabled2 ? "Enabled" : "Disabled"} camera stream ${device}.`);
|
|
659420
|
+
return;
|
|
659421
|
+
}
|
|
658748
659422
|
if (sub2 === "video") {
|
|
658749
659423
|
const cfg = manager.getConfig();
|
|
658750
659424
|
manager.configure({ videoEnabled: setBool(value2, !cfg.videoEnabled) });
|
|
@@ -658870,6 +659544,11 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
658870
659544
|
label: "Select Camera",
|
|
658871
659545
|
detail: `${devices.video.length} device(s)`
|
|
658872
659546
|
},
|
|
659547
|
+
...devices.video.map((device, index) => ({
|
|
659548
|
+
key: `camera-device:${index}`,
|
|
659549
|
+
label: `Camera: ${device.id}`,
|
|
659550
|
+
detail: `${liveCameraStreamSummary(manager, device.id)} — ${device.label}${device.detail ? ` — ${device.detail}` : ""}`
|
|
659551
|
+
})),
|
|
658873
659552
|
{
|
|
658874
659553
|
key: "preview-camera",
|
|
658875
659554
|
label: "View Selected Camera",
|
|
@@ -658964,6 +659643,12 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
658964
659643
|
}
|
|
658965
659644
|
});
|
|
658966
659645
|
if (!result.confirmed || !result.key) return;
|
|
659646
|
+
if (result.key.startsWith("camera-device:")) {
|
|
659647
|
+
const index = Number(result.key.slice("camera-device:".length));
|
|
659648
|
+
const device = devices.video[index];
|
|
659649
|
+
if (device) await showLiveCameraMenu(ctx3, manager, device);
|
|
659650
|
+
continue;
|
|
659651
|
+
}
|
|
658967
659652
|
switch (result.key) {
|
|
658968
659653
|
case "toggle-video":
|
|
658969
659654
|
manager.configure({ videoEnabled: !cfg.videoEnabled });
|
|
@@ -663817,15 +664502,15 @@ function refreshLocalGpuMetricsIfStale() {
|
|
|
663817
664502
|
});
|
|
663818
664503
|
}
|
|
663819
664504
|
function getLocalSystemMetrics() {
|
|
663820
|
-
const
|
|
664505
|
+
const cpus7 = nodeOs.cpus();
|
|
663821
664506
|
const loads = nodeOs.loadavg();
|
|
663822
664507
|
const totalMem = nodeOs.totalmem();
|
|
663823
664508
|
const freeMem = nodeOs.freemem();
|
|
663824
664509
|
const usedMem = totalMem - freeMem;
|
|
663825
664510
|
const result = {
|
|
663826
|
-
cpuModel:
|
|
663827
|
-
cpuCores:
|
|
663828
|
-
cpuUtil: Math.min(100, Math.round(loads[0] /
|
|
664511
|
+
cpuModel: cpus7[0]?.model?.trim() ?? "unknown",
|
|
664512
|
+
cpuCores: cpus7.length,
|
|
664513
|
+
cpuUtil: Math.min(100, Math.round(loads[0] / cpus7.length * 100)),
|
|
663829
664514
|
memTotalGB: Math.round(totalMem / (1024 * 1024 * 1024) * 10) / 10,
|
|
663830
664515
|
memUsedGB: Math.round(usedMem / (1024 * 1024 * 1024) * 10) / 10,
|
|
663831
664516
|
memUtil: Math.round(usedMem / totalMem * 100),
|
|
@@ -665690,7 +666375,7 @@ import {
|
|
|
665690
666375
|
writeFileSync as writeFileSync74,
|
|
665691
666376
|
renameSync as renameSync13,
|
|
665692
666377
|
mkdirSync as mkdirSync86,
|
|
665693
|
-
unlinkSync as
|
|
666378
|
+
unlinkSync as unlinkSync30,
|
|
665694
666379
|
appendFileSync as appendFileSync16
|
|
665695
666380
|
} from "node:fs";
|
|
665696
666381
|
import { join as join156, resolve as resolve64 } from "node:path";
|
|
@@ -665729,7 +666414,7 @@ function persistInFlight(j) {
|
|
|
665729
666414
|
function deleteInFlightFile(id2) {
|
|
665730
666415
|
try {
|
|
665731
666416
|
const p2 = inFlightPath(id2);
|
|
665732
|
-
if (existsSync143(p2))
|
|
666417
|
+
if (existsSync143(p2)) unlinkSync30(p2);
|
|
665733
666418
|
} catch {
|
|
665734
666419
|
}
|
|
665735
666420
|
}
|
|
@@ -666115,7 +666800,7 @@ function drainCheckins(sessionId) {
|
|
|
666115
666800
|
try {
|
|
666116
666801
|
const raw = readFileSync116(fp, "utf-8");
|
|
666117
666802
|
try {
|
|
666118
|
-
|
|
666803
|
+
unlinkSync30(fp);
|
|
666119
666804
|
} catch {
|
|
666120
666805
|
}
|
|
666121
666806
|
if (!raw.trim()) return [];
|
|
@@ -666163,7 +666848,7 @@ function deleteSession2(id2) {
|
|
|
666163
666848
|
try {
|
|
666164
666849
|
const p2 = sessionPath(id2);
|
|
666165
666850
|
if (existsSync143(p2)) {
|
|
666166
|
-
|
|
666851
|
+
unlinkSync30(p2);
|
|
666167
666852
|
removed = true;
|
|
666168
666853
|
}
|
|
666169
666854
|
} catch {
|
|
@@ -671795,7 +672480,7 @@ var init_bless_engine = __esm({
|
|
|
671795
672480
|
});
|
|
671796
672481
|
|
|
671797
672482
|
// packages/cli/src/tui/dmn-engine.ts
|
|
671798
|
-
import { existsSync as existsSync150, readFileSync as readFileSync122, writeFileSync as writeFileSync79, mkdirSync as mkdirSync92, readdirSync as readdirSync53, unlinkSync as
|
|
672483
|
+
import { existsSync as existsSync150, readFileSync as readFileSync122, writeFileSync as writeFileSync79, mkdirSync as mkdirSync92, readdirSync as readdirSync53, unlinkSync as unlinkSync31 } from "node:fs";
|
|
671799
672484
|
import { join as join163, basename as basename36 } from "node:path";
|
|
671800
672485
|
import { exec as exec6 } from "node:child_process";
|
|
671801
672486
|
import { promisify as promisify8 } from "node:util";
|
|
@@ -672732,7 +673417,7 @@ If decision is GO, selectedTask MUST be a fully-populated object (NEVER null)
|
|
|
672732
673417
|
for (const file of files) {
|
|
672733
673418
|
if (!keep.has(file)) {
|
|
672734
673419
|
try {
|
|
672735
|
-
|
|
673420
|
+
unlinkSync31(join163(this.historyDir, file));
|
|
672736
673421
|
} catch {
|
|
672737
673422
|
}
|
|
672738
673423
|
}
|
|
@@ -672810,7 +673495,7 @@ function appraiseEvent(event) {
|
|
|
672810
673495
|
return null;
|
|
672811
673496
|
}
|
|
672812
673497
|
}
|
|
672813
|
-
function
|
|
673498
|
+
function clamp10(value2, min, max) {
|
|
672814
673499
|
return Math.max(min, Math.min(max, value2));
|
|
672815
673500
|
}
|
|
672816
673501
|
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;
|
|
@@ -672949,8 +673634,8 @@ var init_emotion_engine = __esm({
|
|
|
672949
673634
|
if (this.consecutiveFailures >= 2) {
|
|
672950
673635
|
momentum = 1 + (this.consecutiveFailures - 1) * 0.25;
|
|
672951
673636
|
}
|
|
672952
|
-
this.state.valence =
|
|
672953
|
-
this.state.arousal =
|
|
673637
|
+
this.state.valence = clamp10(this.state.valence + delta.valence * momentum, -1, 1);
|
|
673638
|
+
this.state.arousal = clamp10(this.state.arousal + delta.arousal * momentum, 0, 1);
|
|
672954
673639
|
this.state.updatedAt = Date.now();
|
|
672955
673640
|
const deterministicLabel = labelFromCoordinates(this.state.valence, this.state.arousal);
|
|
672956
673641
|
this.state.label = deterministicLabel.label;
|
|
@@ -673216,6 +673901,147 @@ var init_emotion_engine = __esm({
|
|
|
673216
673901
|
}
|
|
673217
673902
|
});
|
|
673218
673903
|
|
|
673904
|
+
// packages/cli/src/tui/conversation-context.ts
|
|
673905
|
+
import { statfsSync as statfsSync8 } from "node:fs";
|
|
673906
|
+
function buildConversationRuntimeContext(now2 = /* @__PURE__ */ new Date(), repoRoot) {
|
|
673907
|
+
const date = new Intl.DateTimeFormat("en-US", {
|
|
673908
|
+
weekday: "long",
|
|
673909
|
+
year: "numeric",
|
|
673910
|
+
month: "long",
|
|
673911
|
+
day: "numeric"
|
|
673912
|
+
}).format(now2);
|
|
673913
|
+
const time = new Intl.DateTimeFormat("en-US", {
|
|
673914
|
+
hour: "numeric",
|
|
673915
|
+
minute: "2-digit",
|
|
673916
|
+
second: "2-digit",
|
|
673917
|
+
timeZoneName: "short"
|
|
673918
|
+
}).format(now2);
|
|
673919
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env["TZ"] || "system";
|
|
673920
|
+
let diskLine = "";
|
|
673921
|
+
if (repoRoot) {
|
|
673922
|
+
try {
|
|
673923
|
+
const stats = statfsSync8(repoRoot);
|
|
673924
|
+
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
673925
|
+
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
673926
|
+
const usedBytes = totalBytes - freeBytes;
|
|
673927
|
+
const totalGB = Math.round(totalBytes / 1024 ** 3);
|
|
673928
|
+
const freeGB = Math.round(freeBytes / 1024 ** 3);
|
|
673929
|
+
const usedGB = Math.round(usedBytes / 1024 ** 3);
|
|
673930
|
+
const usedPct = totalBytes > 0 ? Math.round(usedBytes / totalBytes * 100) : 0;
|
|
673931
|
+
diskLine = `Disk: disk_available_gb=${freeGB} disk_used_gb=${usedGB} disk_total_gb=${totalGB} disk_used_pct=${usedPct} path=${repoRoot}`;
|
|
673932
|
+
} catch {
|
|
673933
|
+
}
|
|
673934
|
+
}
|
|
673935
|
+
return [
|
|
673936
|
+
`Current date: ${date}`,
|
|
673937
|
+
`Current time: ${time}`,
|
|
673938
|
+
`Current ISO timestamp: ${now2.toISOString()}`,
|
|
673939
|
+
`Timezone: ${timezone}`,
|
|
673940
|
+
repoRoot ? `Working directory: ${repoRoot}` : "",
|
|
673941
|
+
diskLine
|
|
673942
|
+
].filter(Boolean).join("\n");
|
|
673943
|
+
}
|
|
673944
|
+
function quoteConversationBlock(value2, maxChars = 2400) {
|
|
673945
|
+
const text2 = String(value2 ?? "").replace(/\r\n/g, "\n").trim();
|
|
673946
|
+
if (!text2) return "> (empty)";
|
|
673947
|
+
const clipped = text2.length > maxChars ? `${text2.slice(0, Math.max(0, maxChars - 1))}...` : text2;
|
|
673948
|
+
return clipped.split("\n").map((line) => `> ${line}`).join("\n");
|
|
673949
|
+
}
|
|
673950
|
+
function buildScopedConversationMessages(turns, options2) {
|
|
673951
|
+
const pinned = [];
|
|
673952
|
+
const dynamic = [];
|
|
673953
|
+
let latestContextFrame = null;
|
|
673954
|
+
for (const turn of turns) {
|
|
673955
|
+
if (options2.isPinnedSystemTurn(turn) && !pinned.some((p2) => p2.content === turn.content)) {
|
|
673956
|
+
pinned.push(turn);
|
|
673957
|
+
} else if (options2.isContextFrameTurn?.(turn)) {
|
|
673958
|
+
latestContextFrame = turn;
|
|
673959
|
+
} else {
|
|
673960
|
+
dynamic.push(turn);
|
|
673961
|
+
}
|
|
673962
|
+
}
|
|
673963
|
+
if (latestContextFrame) {
|
|
673964
|
+
if (options2.placeContextFrameBeforeLastUser !== false) {
|
|
673965
|
+
let lastUserIdx = -1;
|
|
673966
|
+
for (let i2 = dynamic.length - 1; i2 >= 0; i2--) {
|
|
673967
|
+
if (dynamic[i2].role === "user") {
|
|
673968
|
+
lastUserIdx = i2;
|
|
673969
|
+
break;
|
|
673970
|
+
}
|
|
673971
|
+
}
|
|
673972
|
+
if (lastUserIdx >= 0) dynamic.splice(lastUserIdx, 0, latestContextFrame);
|
|
673973
|
+
else dynamic.push(latestContextFrame);
|
|
673974
|
+
} else {
|
|
673975
|
+
dynamic.push(latestContextFrame);
|
|
673976
|
+
}
|
|
673977
|
+
}
|
|
673978
|
+
const available = Math.max(0, options2.maxMessages - pinned.length);
|
|
673979
|
+
let windowed = dynamic.slice(-available);
|
|
673980
|
+
if (latestContextFrame && available > 0 && !windowed.includes(latestContextFrame)) {
|
|
673981
|
+
windowed = [latestContextFrame, ...windowed.slice(-(available - 1))];
|
|
673982
|
+
}
|
|
673983
|
+
return [...pinned, ...windowed];
|
|
673984
|
+
}
|
|
673985
|
+
function buildVoiceSessionContext(args) {
|
|
673986
|
+
const maxTranscriptTurns = Math.max(1, args.maxTranscriptTurns ?? 8);
|
|
673987
|
+
const voiceLines = (args.voiceTranscript ?? []).slice(-maxTranscriptTurns).map((turn) => `${formatClock(turn.ts)} ${turn.role}: ${singleLine(turn.content, 360)}`);
|
|
673988
|
+
const relayLines = (args.relayTranscript ?? []).slice(-maxTranscriptTurns).map((turn) => {
|
|
673989
|
+
const dir = turn.dir === "toMain" ? "voice->main" : "main->voice";
|
|
673990
|
+
return `${formatClock(turn.ts)} ${dir}: ${singleLine(turn.content, 360)}`;
|
|
673991
|
+
});
|
|
673992
|
+
const taskLine = args.activeTask ? `active=${args.activeTask.active ? "yes" : "no"} tool_calls=${args.activeTask.toolCalls ?? 0} files_touched=${args.activeTask.filesTouched ?? 0}` : "active=unknown";
|
|
673993
|
+
const sections = [
|
|
673994
|
+
`## Runtime Context
|
|
673995
|
+
|
|
673996
|
+
${buildConversationRuntimeContext(/* @__PURE__ */ new Date(), args.repoRoot)}`,
|
|
673997
|
+
[
|
|
673998
|
+
"## Voice/Live Session Contract",
|
|
673999
|
+
"",
|
|
674000
|
+
`surface=voicechat session_id=${args.sessionId} turn=${args.turnCount}`,
|
|
674001
|
+
`main_agent_task=${taskLine}`,
|
|
674002
|
+
"Latest user utterance remains the active request. Earlier ASR transcript turns are conversational history, not new instructions.",
|
|
674003
|
+
"ASR text can be noisy. Prefer consensus-filtered final turns, resolve pronouns from recent context, and ask for clarification rather than filling gaps.",
|
|
674004
|
+
"Live perception is evidence for the current reply, not a topic to narrate unless the user asks about it."
|
|
674005
|
+
].join("\n")
|
|
674006
|
+
];
|
|
674007
|
+
if (voiceLines.length > 0) {
|
|
674008
|
+
sections.push(`## Recent Voice Conversation
|
|
674009
|
+
|
|
674010
|
+
${quoteConversationBlock(voiceLines.join("\n"))}`);
|
|
674011
|
+
}
|
|
674012
|
+
if (relayLines.length > 0) {
|
|
674013
|
+
sections.push(`## Main Agent Relay Stream
|
|
674014
|
+
|
|
674015
|
+
${quoteConversationBlock(relayLines.join("\n"))}`);
|
|
674016
|
+
}
|
|
674017
|
+
if (args.liveContext?.trim()) {
|
|
674018
|
+
sections.push(`## Live Context Frame
|
|
674019
|
+
|
|
674020
|
+
${args.liveContext.trim()}`);
|
|
674021
|
+
}
|
|
674022
|
+
return sections.join("\n\n");
|
|
674023
|
+
}
|
|
674024
|
+
function singleLine(value2, maxChars) {
|
|
674025
|
+
const clean5 = value2.replace(/\s+/g, " ").trim();
|
|
674026
|
+
return clean5.length > maxChars ? `${clean5.slice(0, Math.max(0, maxChars - 1))}...` : clean5;
|
|
674027
|
+
}
|
|
674028
|
+
function formatClock(ts) {
|
|
674029
|
+
try {
|
|
674030
|
+
return new Date(ts).toLocaleTimeString("en-US", {
|
|
674031
|
+
hour: "2-digit",
|
|
674032
|
+
minute: "2-digit",
|
|
674033
|
+
second: "2-digit"
|
|
674034
|
+
});
|
|
674035
|
+
} catch {
|
|
674036
|
+
return "unknown-time";
|
|
674037
|
+
}
|
|
674038
|
+
}
|
|
674039
|
+
var init_conversation_context = __esm({
|
|
674040
|
+
"packages/cli/src/tui/conversation-context.ts"() {
|
|
674041
|
+
"use strict";
|
|
674042
|
+
}
|
|
674043
|
+
});
|
|
674044
|
+
|
|
673219
674045
|
// packages/cli/src/tui/telegram-format.ts
|
|
673220
674046
|
function escapeHtml2(text2) {
|
|
673221
674047
|
return String(text2 ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -674394,7 +675220,7 @@ import {
|
|
|
674394
675220
|
mkdirSync as mkdirSync93,
|
|
674395
675221
|
readFileSync as readFileSync123,
|
|
674396
675222
|
statSync as statSync55,
|
|
674397
|
-
unlinkSync as
|
|
675223
|
+
unlinkSync as unlinkSync32,
|
|
674398
675224
|
writeFileSync as writeFileSync80
|
|
674399
675225
|
} from "node:fs";
|
|
674400
675226
|
import { mkdir as mkdir22 } from "node:fs/promises";
|
|
@@ -674647,7 +675473,7 @@ function scopedTool(base3, root, mode) {
|
|
|
674647
675473
|
}
|
|
674648
675474
|
} else if (restoredEditPath) {
|
|
674649
675475
|
try {
|
|
674650
|
-
|
|
675476
|
+
unlinkSync32(restoredEditPath);
|
|
674651
675477
|
} catch {
|
|
674652
675478
|
}
|
|
674653
675479
|
}
|
|
@@ -674792,7 +675618,7 @@ function rememberCreated(root, absPath) {
|
|
|
674792
675618
|
const previousPath = resolve66(root, previous.storedRel);
|
|
674793
675619
|
if (isInside(resolve66(root), previousPath) && existsSync151(previousPath)) {
|
|
674794
675620
|
try {
|
|
674795
|
-
|
|
675621
|
+
unlinkSync32(previousPath);
|
|
674796
675622
|
} catch {
|
|
674797
675623
|
}
|
|
674798
675624
|
}
|
|
@@ -674812,7 +675638,7 @@ function rememberCreated(root, absPath) {
|
|
|
674812
675638
|
const storedAbs = join164(root, storedRel);
|
|
674813
675639
|
writeFileSync80(storedAbs, Buffer.concat([prefix, encrypted]));
|
|
674814
675640
|
try {
|
|
674815
|
-
|
|
675641
|
+
unlinkSync32(guarded.path.abs);
|
|
674816
675642
|
} catch {
|
|
674817
675643
|
}
|
|
674818
675644
|
manifest.objects = manifest.objects || {};
|
|
@@ -674890,7 +675716,7 @@ function materializeTelegramCreativeArtifactForSend(root, rawPath) {
|
|
|
674890
675716
|
path: staged,
|
|
674891
675717
|
cleanup: () => {
|
|
674892
675718
|
try {
|
|
674893
|
-
|
|
675719
|
+
unlinkSync32(staged);
|
|
674894
675720
|
} catch {
|
|
674895
675721
|
}
|
|
674896
675722
|
}
|
|
@@ -675827,7 +676653,7 @@ import {
|
|
|
675827
676653
|
readdirSync as readdirSync54,
|
|
675828
676654
|
readFileSync as readFileSync124,
|
|
675829
676655
|
writeFileSync as writeFileSync81,
|
|
675830
|
-
unlinkSync as
|
|
676656
|
+
unlinkSync as unlinkSync33
|
|
675831
676657
|
} from "node:fs";
|
|
675832
676658
|
import { join as join165 } from "node:path";
|
|
675833
676659
|
import { createHash as createHash39 } from "node:crypto";
|
|
@@ -676565,7 +677391,7 @@ function pruneTelegramChannelDaydreams(repoRoot, sessionKey, keep = DAYDREAM_ART
|
|
|
676565
677391
|
let removed = 0;
|
|
676566
677392
|
for (const file of toRemove) {
|
|
676567
677393
|
try {
|
|
676568
|
-
|
|
677394
|
+
unlinkSync33(join165(dir, file));
|
|
676569
677395
|
removed++;
|
|
676570
677396
|
} catch {
|
|
676571
677397
|
}
|
|
@@ -678332,7 +679158,7 @@ __export(vision_ingress_exports, {
|
|
|
678332
679158
|
resolveVisionModel: () => resolveVisionModel,
|
|
678333
679159
|
runVisionIngress: () => runVisionIngress
|
|
678334
679160
|
});
|
|
678335
|
-
import { existsSync as existsSync153, readFileSync as readFileSync125, unlinkSync as
|
|
679161
|
+
import { existsSync as existsSync153, readFileSync as readFileSync125, unlinkSync as unlinkSync34 } from "node:fs";
|
|
678336
679162
|
import { join as join166 } from "node:path";
|
|
678337
679163
|
async function isTesseractAvailable() {
|
|
678338
679164
|
try {
|
|
@@ -678390,7 +679216,7 @@ async function advancedOcr(imagePath) {
|
|
|
678390
679216
|
const text2 = readFileSync125(txtFile, "utf-8").trim();
|
|
678391
679217
|
if (text2.length > 0) results.push(text2);
|
|
678392
679218
|
try {
|
|
678393
|
-
|
|
679219
|
+
unlinkSync34(txtFile);
|
|
678394
679220
|
} catch {
|
|
678395
679221
|
}
|
|
678396
679222
|
}
|
|
@@ -678569,10 +679395,9 @@ var init_vision_ingress = __esm({
|
|
|
678569
679395
|
import {
|
|
678570
679396
|
mkdirSync as mkdirSync95,
|
|
678571
679397
|
existsSync as existsSync154,
|
|
678572
|
-
unlinkSync as
|
|
679398
|
+
unlinkSync as unlinkSync35,
|
|
678573
679399
|
readdirSync as readdirSync55,
|
|
678574
679400
|
statSync as statSync56,
|
|
678575
|
-
statfsSync as statfsSync8,
|
|
678576
679401
|
readFileSync as readFileSync126,
|
|
678577
679402
|
writeFileSync as writeFileSync82,
|
|
678578
679403
|
appendFileSync as appendFileSync18
|
|
@@ -679829,42 +680654,7 @@ function telegramMemoryTags(text2, mediaSummary) {
|
|
|
679829
680654
|
return tokens.filter((token) => !/^\d+$/.test(token)).slice(0, 10);
|
|
679830
680655
|
}
|
|
679831
680656
|
function buildTelegramRuntimeContext(now2 = /* @__PURE__ */ new Date(), repoRoot) {
|
|
679832
|
-
|
|
679833
|
-
weekday: "long",
|
|
679834
|
-
year: "numeric",
|
|
679835
|
-
month: "long",
|
|
679836
|
-
day: "numeric"
|
|
679837
|
-
}).format(now2);
|
|
679838
|
-
const time = new Intl.DateTimeFormat("en-US", {
|
|
679839
|
-
hour: "numeric",
|
|
679840
|
-
minute: "2-digit",
|
|
679841
|
-
second: "2-digit",
|
|
679842
|
-
timeZoneName: "short"
|
|
679843
|
-
}).format(now2);
|
|
679844
|
-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env["TZ"] || "system";
|
|
679845
|
-
let diskLine = "";
|
|
679846
|
-
if (repoRoot) {
|
|
679847
|
-
try {
|
|
679848
|
-
const stats = statfsSync8(repoRoot);
|
|
679849
|
-
const totalBytes = stats.blocks * stats.bsize;
|
|
679850
|
-
const freeBytes = stats.bavail * stats.bsize;
|
|
679851
|
-
const usedBytes = totalBytes - freeBytes;
|
|
679852
|
-
const totalGB = Math.round(totalBytes / 1024 ** 3);
|
|
679853
|
-
const freeGB = Math.round(freeBytes / 1024 ** 3);
|
|
679854
|
-
const usedGB = Math.round(usedBytes / 1024 ** 3);
|
|
679855
|
-
const usedPct = totalBytes > 0 ? Math.round(usedBytes / totalBytes * 100) : 0;
|
|
679856
|
-
diskLine = `Disk: disk_available_gb=${freeGB} disk_used_gb=${usedGB} disk_total_gb=${totalGB} disk_used_pct=${usedPct} path=${repoRoot}`;
|
|
679857
|
-
} catch {
|
|
679858
|
-
}
|
|
679859
|
-
}
|
|
679860
|
-
return [
|
|
679861
|
-
`Current date: ${date}`,
|
|
679862
|
-
`Current time: ${time}`,
|
|
679863
|
-
`Current ISO timestamp: ${now2.toISOString()}`,
|
|
679864
|
-
`Timezone: ${timezone}`,
|
|
679865
|
-
repoRoot ? `Working directory: ${repoRoot}` : "",
|
|
679866
|
-
diskLine
|
|
679867
|
-
].filter(Boolean).join("\n");
|
|
680657
|
+
return buildConversationRuntimeContext(now2, repoRoot);
|
|
679868
680658
|
}
|
|
679869
680659
|
function telegramSessionIdFromKey(sessionKey) {
|
|
679870
680660
|
return `telegram-${createHash42("sha1").update(sessionKey).digest("hex").slice(0, 16)}`;
|
|
@@ -681026,6 +681816,7 @@ var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTAT
|
|
|
681026
681816
|
var init_telegram_bridge = __esm({
|
|
681027
681817
|
"packages/cli/src/tui/telegram-bridge.ts"() {
|
|
681028
681818
|
"use strict";
|
|
681819
|
+
init_conversation_context();
|
|
681029
681820
|
init_telegram_format();
|
|
681030
681821
|
init_async_process();
|
|
681031
681822
|
init_dist8();
|
|
@@ -689657,7 +690448,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
689657
690448
|
if (prior.pid !== process.pid) return;
|
|
689658
690449
|
} catch {
|
|
689659
690450
|
}
|
|
689660
|
-
|
|
690451
|
+
unlinkSync35(lockFile);
|
|
689661
690452
|
} catch {
|
|
689662
690453
|
}
|
|
689663
690454
|
}
|
|
@@ -696213,7 +697004,7 @@ ${text2}`.trim()
|
|
|
696213
697004
|
for (const [key, entry] of this.mediaCache) {
|
|
696214
697005
|
if (now2 - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
|
|
696215
697006
|
try {
|
|
696216
|
-
|
|
697007
|
+
unlinkSync35(entry.localPath);
|
|
696217
697008
|
} catch {
|
|
696218
697009
|
}
|
|
696219
697010
|
this.mediaCache.delete(key);
|
|
@@ -697648,43 +698439,22 @@ function isContextSnapshotTurn(turn) {
|
|
|
697648
698439
|
return turn.role === "system" && turn.content.startsWith(CONTEXT_SNAPSHOT_PREFIX);
|
|
697649
698440
|
}
|
|
697650
698441
|
function isPinnedSystemTurn(turn) {
|
|
697651
|
-
return turn.role === "system" && (turn.content === SYSTEM_PROMPT2 || turn.content.startsWith("Available tools
|
|
698442
|
+
return turn.role === "system" && (turn.content === SYSTEM_PROMPT2 || turn.content.startsWith("Available tools."));
|
|
697652
698443
|
}
|
|
697653
698444
|
function buildRealtimeVoiceMessages(turns, maxMessages = MAX_REALTIME_MODEL_MESSAGES) {
|
|
697654
|
-
|
|
697655
|
-
|
|
697656
|
-
|
|
697657
|
-
|
|
697658
|
-
|
|
697659
|
-
|
|
697660
|
-
} else if (isContextSnapshotTurn(turn)) {
|
|
697661
|
-
latestSnapshot = turn;
|
|
697662
|
-
} else {
|
|
697663
|
-
dynamic.push(turn);
|
|
697664
|
-
}
|
|
697665
|
-
}
|
|
697666
|
-
if (latestSnapshot) {
|
|
697667
|
-
let lastUserIdx = -1;
|
|
697668
|
-
for (let i2 = dynamic.length - 1; i2 >= 0; i2--) {
|
|
697669
|
-
if (dynamic[i2].role === "user") {
|
|
697670
|
-
lastUserIdx = i2;
|
|
697671
|
-
break;
|
|
697672
|
-
}
|
|
697673
|
-
}
|
|
697674
|
-
if (lastUserIdx >= 0) dynamic.splice(lastUserIdx, 0, latestSnapshot);
|
|
697675
|
-
else dynamic.push(latestSnapshot);
|
|
697676
|
-
}
|
|
697677
|
-
const available = Math.max(0, maxMessages - pinned.length);
|
|
697678
|
-
let windowed = dynamic.slice(-available);
|
|
697679
|
-
if (latestSnapshot && available > 0 && !windowed.includes(latestSnapshot)) {
|
|
697680
|
-
windowed = [latestSnapshot, ...windowed.slice(-(available - 1))];
|
|
697681
|
-
}
|
|
697682
|
-
return [...pinned, ...windowed];
|
|
698445
|
+
return buildScopedConversationMessages(turns, {
|
|
698446
|
+
maxMessages,
|
|
698447
|
+
isPinnedSystemTurn,
|
|
698448
|
+
isContextFrameTurn: isContextSnapshotTurn,
|
|
698449
|
+
placeContextFrameBeforeLastUser: true
|
|
698450
|
+
});
|
|
697683
698451
|
}
|
|
697684
698452
|
var VAD_SILENCE_MS, MAX_SEGMENT_MS, SUMMARY_INJECTION_INTERVAL, MAX_CONTEXT_TURNS, MAX_REALTIME_MODEL_MESSAGES, CONTEXT_SNAPSHOT_PREFIX, CONTEXT_SNAPSHOT_SCOPE, MAX_VOICE_REPLY_CHARS, AGENT_ECHO_WINDOW_MS, AGENT_ECHO_SIMILARITY, SYSTEM_PROMPT2, MIN_SIGNAL_SCORE, NOISE_ONLY_RE, VoiceChatSession;
|
|
697685
698453
|
var init_voicechat = __esm({
|
|
697686
698454
|
"packages/cli/src/tui/voicechat.ts"() {
|
|
697687
698455
|
"use strict";
|
|
698456
|
+
init_conversation_context();
|
|
698457
|
+
init_live_resource_arbiter();
|
|
697688
698458
|
VAD_SILENCE_MS = 3e3;
|
|
697689
698459
|
MAX_SEGMENT_MS = 6500;
|
|
697690
698460
|
SUMMARY_INJECTION_INTERVAL = 4;
|
|
@@ -697699,6 +698469,7 @@ var init_voicechat = __esm({
|
|
|
697699
698469
|
|
|
697700
698470
|
Rules:
|
|
697701
698471
|
- ALWAYS answer the user's most recent message directly. The live context snapshot is background perception — never the topic. Do not describe cameras, feeds, or surroundings unless the user's latest message asks about them.
|
|
698472
|
+
- Treat this as one continuous conversation thread. Resolve pronouns from recent voice turns and main-agent relay context, but let the latest user utterance override earlier transcript noise.
|
|
697702
698473
|
- Never repeat your previous answer. If you already described the scene, don't describe it again unless explicitly asked again — respond to what the user just said.
|
|
697703
698474
|
- Live perception: each turn you may receive a read-only "[ACTIVE CONTEXT FRAME]" system message containing what the camera currently sees (objects, people, classifications, recent visual events) and what is currently heard (sound scene, recent sounds, transcripts). Treat it as your own live sight and hearing. When the user asks what you SEE, answer from the camera fields; when the user asks what you HEAR, answer from the audio/sound fields. If the snapshot is missing or stale, say you can't see/hear clearly right now — do not invent observations.
|
|
697704
698475
|
- Never invent environment facts (cwd, OS, specs, repo state). If you need a precise fact from the main agent, request a tool by outputting on a single line EXACTLY one JSON object: {"tool": string, "args": object} and nothing else. Then wait for the tool result before answering.
|
|
@@ -697739,6 +698510,7 @@ Rules:
|
|
|
697739
698510
|
lastSignalScore = null;
|
|
697740
698511
|
listenPausedForResponse = false;
|
|
697741
698512
|
lastAgentSpeech = null;
|
|
698513
|
+
liveResourceLease = null;
|
|
697742
698514
|
// Abort control for inference
|
|
697743
698515
|
abortController = null;
|
|
697744
698516
|
// Callbacks
|
|
@@ -697790,9 +698562,45 @@ Rules:
|
|
|
697790
698562
|
if (this._state === next) return;
|
|
697791
698563
|
const prev = this._state;
|
|
697792
698564
|
this._state = next;
|
|
698565
|
+
this.updateLiveResourceLease(next);
|
|
697793
698566
|
this.onStateChange(next);
|
|
697794
698567
|
this.emit("stateChange", { from: prev, to: next });
|
|
697795
698568
|
}
|
|
698569
|
+
updateLiveResourceLease(state) {
|
|
698570
|
+
if (state === "CAPTURING") {
|
|
698571
|
+
this.holdLiveResources("asr-capture", 92, 1e4, "voicechat ASR capture");
|
|
698572
|
+
return;
|
|
698573
|
+
}
|
|
698574
|
+
if (state === "TRANSCRIBING") {
|
|
698575
|
+
this.holdLiveResources("asr-final", 94, 18e3, "voicechat final ASR/transcript handoff");
|
|
698576
|
+
return;
|
|
698577
|
+
}
|
|
698578
|
+
if (state === "THINKING") {
|
|
698579
|
+
this.holdLiveResources("voice-llm", 100, 6e4, "voicechat live LLM inference");
|
|
698580
|
+
return;
|
|
698581
|
+
}
|
|
698582
|
+
if (state === "SPEAKING") {
|
|
698583
|
+
this.holdLiveResources("tts", 84, 24e3, "voicechat TTS playback/echo guard");
|
|
698584
|
+
return;
|
|
698585
|
+
}
|
|
698586
|
+
if (state === "IDLE" || state === "LISTENING") {
|
|
698587
|
+
this.releaseLiveResources();
|
|
698588
|
+
}
|
|
698589
|
+
}
|
|
698590
|
+
holdLiveResources(owner, priority, ttlMs, reason) {
|
|
698591
|
+
this.liveResourceLease?.release();
|
|
698592
|
+
this.liveResourceLease = getLiveResourceArbiter().claim({
|
|
698593
|
+
owner: `voicechat:${owner}`,
|
|
698594
|
+
priority,
|
|
698595
|
+
ttlMs,
|
|
698596
|
+
reason,
|
|
698597
|
+
suppress: ["vision"]
|
|
698598
|
+
});
|
|
698599
|
+
}
|
|
698600
|
+
releaseLiveResources() {
|
|
698601
|
+
this.liveResourceLease?.release();
|
|
698602
|
+
this.liveResourceLease = null;
|
|
698603
|
+
}
|
|
697796
698604
|
// ---------------------------------------------------------------------------
|
|
697797
698605
|
// Start / Stop
|
|
697798
698606
|
// ---------------------------------------------------------------------------
|
|
@@ -697902,6 +698710,7 @@ Rules:
|
|
|
697902
698710
|
await this.listen.stop();
|
|
697903
698711
|
} catch {
|
|
697904
698712
|
}
|
|
698713
|
+
this.releaseLiveResources();
|
|
697905
698714
|
this.setState("IDLE");
|
|
697906
698715
|
if (this.verbose) this.onStatus("VoiceChat ended");
|
|
697907
698716
|
this.emit("stopped");
|
|
@@ -697920,6 +698729,12 @@ Rules:
|
|
|
697920
698729
|
this.emit("voiceEchoFiltered", echo);
|
|
697921
698730
|
return;
|
|
697922
698731
|
}
|
|
698732
|
+
this.holdLiveResources(
|
|
698733
|
+
isFinal ? "asr-final" : "asr-capture",
|
|
698734
|
+
isFinal ? 94 : 92,
|
|
698735
|
+
isFinal ? 18e3 : 1e4,
|
|
698736
|
+
isFinal ? "voicechat final ASR incoming" : "voicechat partial ASR incoming"
|
|
698737
|
+
);
|
|
697923
698738
|
if (this._state === "LISTENING") {
|
|
697924
698739
|
this.setState("CAPTURING");
|
|
697925
698740
|
this.resetCaptureState();
|
|
@@ -698022,13 +698837,19 @@ Rules:
|
|
|
698022
698837
|
const snap = await Promise.resolve(this.toolRelay.contextSnapshot());
|
|
698023
698838
|
if (snap && snap.trim()) {
|
|
698024
698839
|
this.dropTransientSystemTurns();
|
|
698840
|
+
const contextFrame = buildVoiceSessionContext({
|
|
698841
|
+
sessionId: "voicechat",
|
|
698842
|
+
turnCount: this.turnCount,
|
|
698843
|
+
voiceTranscript: this.voiceTranscript,
|
|
698844
|
+
relayTranscript: this.relayTranscript,
|
|
698845
|
+
liveContext: `${CONTEXT_SNAPSHOT_SCOPE}
|
|
698846
|
+
|
|
698847
|
+
${snap.trim()}`
|
|
698848
|
+
});
|
|
698025
698849
|
this.context.push({
|
|
698026
698850
|
role: "system",
|
|
698027
698851
|
content: `${CONTEXT_SNAPSHOT_PREFIX}
|
|
698028
|
-
|
|
698029
|
-
${CONTEXT_SNAPSHOT_SCOPE}
|
|
698030
|
-
|
|
698031
|
-
${snap.trim()}`
|
|
698852
|
+
${contextFrame}`
|
|
698032
698853
|
});
|
|
698033
698854
|
this.trimContext();
|
|
698034
698855
|
}
|
|
@@ -699834,7 +700655,7 @@ var init_access_policy = __esm({
|
|
|
699834
700655
|
|
|
699835
700656
|
// packages/cli/src/api/project-preferences.ts
|
|
699836
700657
|
import { createHash as createHash43 } from "node:crypto";
|
|
699837
|
-
import { existsSync as existsSync156, mkdirSync as mkdirSync97, readFileSync as readFileSync128, renameSync as renameSync15, writeFileSync as writeFileSync84, unlinkSync as
|
|
700658
|
+
import { existsSync as existsSync156, mkdirSync as mkdirSync97, readFileSync as readFileSync128, renameSync as renameSync15, writeFileSync as writeFileSync84, unlinkSync as unlinkSync36 } from "node:fs";
|
|
699838
700659
|
import { homedir as homedir57 } from "node:os";
|
|
699839
700660
|
import { join as join169, resolve as resolve69 } from "node:path";
|
|
699840
700661
|
import { randomUUID as randomUUID20 } from "node:crypto";
|
|
@@ -699895,7 +700716,7 @@ function writeProjectPreferences(root, partial) {
|
|
|
699895
700716
|
} catch {
|
|
699896
700717
|
}
|
|
699897
700718
|
try {
|
|
699898
|
-
|
|
700719
|
+
unlinkSync36(tmp);
|
|
699899
700720
|
} catch {
|
|
699900
700721
|
}
|
|
699901
700722
|
throw err;
|
|
@@ -699906,7 +700727,7 @@ function deleteProjectPreferences(root) {
|
|
|
699906
700727
|
try {
|
|
699907
700728
|
const file = prefsPath(root);
|
|
699908
700729
|
if (!existsSync156(file)) return false;
|
|
699909
|
-
|
|
700730
|
+
unlinkSync36(file);
|
|
699910
700731
|
return true;
|
|
699911
700732
|
} catch {
|
|
699912
700733
|
return false;
|
|
@@ -718857,7 +719678,7 @@ import {
|
|
|
718857
719678
|
existsSync as existsSync168,
|
|
718858
719679
|
watch as fsWatch4,
|
|
718859
719680
|
renameSync as renameSync17,
|
|
718860
|
-
unlinkSync as
|
|
719681
|
+
unlinkSync as unlinkSync37,
|
|
718861
719682
|
statSync as statSync62,
|
|
718862
719683
|
openSync as openSync6,
|
|
718863
719684
|
readSync as readSync2,
|
|
@@ -720192,13 +721013,13 @@ function pruneOldJobs() {
|
|
|
720192
721013
|
const ts = ageRef ? Date.parse(ageRef) : NaN;
|
|
720193
721014
|
if (Number.isFinite(ts) && ts < cutoffMs) {
|
|
720194
721015
|
try {
|
|
720195
|
-
|
|
721016
|
+
unlinkSync37(path12);
|
|
720196
721017
|
} catch {
|
|
720197
721018
|
}
|
|
720198
721019
|
const outFile = path12.replace(/\.json$/, ".output");
|
|
720199
721020
|
if (existsSync168(outFile)) {
|
|
720200
721021
|
try {
|
|
720201
|
-
|
|
721022
|
+
unlinkSync37(outFile);
|
|
720202
721023
|
} catch {
|
|
720203
721024
|
}
|
|
720204
721025
|
}
|
|
@@ -720208,7 +721029,7 @@ function pruneOldJobs() {
|
|
|
720208
721029
|
}
|
|
720209
721030
|
} catch {
|
|
720210
721031
|
try {
|
|
720211
|
-
|
|
721032
|
+
unlinkSync37(path12);
|
|
720212
721033
|
pruned++;
|
|
720213
721034
|
} catch {
|
|
720214
721035
|
}
|
|
@@ -720520,7 +721341,7 @@ function atomicJobWrite(dir, id2, job) {
|
|
|
720520
721341
|
} catch {
|
|
720521
721342
|
}
|
|
720522
721343
|
try {
|
|
720523
|
-
|
|
721344
|
+
unlinkSync37(tmpPath);
|
|
720524
721345
|
} catch {
|
|
720525
721346
|
}
|
|
720526
721347
|
}
|
|
@@ -724701,7 +725522,7 @@ async function handleRequest(req3, res, ollamaUrl, verbose, runtimeDefaults = {}
|
|
|
724701
725522
|
return;
|
|
724702
725523
|
}
|
|
724703
725524
|
const { tmpdir: tmpdir26 } = await import("node:os");
|
|
724704
|
-
const { writeFileSync: writeFileSync95, unlinkSync:
|
|
725525
|
+
const { writeFileSync: writeFileSync95, unlinkSync: unlinkSync38 } = await import("node:fs");
|
|
724705
725526
|
const { join: pjoin } = await import("node:path");
|
|
724706
725527
|
const tmpPath = pjoin(
|
|
724707
725528
|
tmpdir26(),
|
|
@@ -724719,7 +725540,7 @@ async function handleRequest(req3, res, ollamaUrl, verbose, runtimeDefaults = {}
|
|
|
724719
725540
|
});
|
|
724720
725541
|
} finally {
|
|
724721
725542
|
try {
|
|
724722
|
-
|
|
725543
|
+
unlinkSync38(tmpPath);
|
|
724723
725544
|
} catch {
|
|
724724
725545
|
}
|
|
724725
725546
|
}
|
|
@@ -727962,8 +728783,8 @@ function startApiServer(options2 = {}) {
|
|
|
727962
728783
|
job.startedAt ?? job.completedAt ?? 0
|
|
727963
728784
|
).getTime();
|
|
727964
728785
|
if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
|
|
727965
|
-
const { unlinkSync:
|
|
727966
|
-
|
|
728786
|
+
const { unlinkSync: unlinkSync38 } = require4("node:fs");
|
|
728787
|
+
unlinkSync38(jobPath);
|
|
727967
728788
|
}
|
|
727968
728789
|
} catch {
|
|
727969
728790
|
}
|
|
@@ -737112,6 +737933,32 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
737112
737933
|
sharedTranscriber: null
|
|
737113
737934
|
};
|
|
737114
737935
|
const engine = getListenEngine();
|
|
737936
|
+
const callConsensusRequired = (() => {
|
|
737937
|
+
const env2 = String(process.env["OMNIUS_ASR_CONSENSUS"] ?? "").trim().toLowerCase();
|
|
737938
|
+
return !(env2 === "0" || env2 === "off" || env2 === "false");
|
|
737939
|
+
})();
|
|
737940
|
+
const recentCallFinals = [];
|
|
737941
|
+
const normalizeCallTranscript = (value2) => value2.toLowerCase().replace(/[^\p{L}\p{N}\s']/gu, " ").replace(/\s+/g, " ").trim();
|
|
737942
|
+
const isLikelyCallAsrHallucination = (normalized) => /^(thanks|thank you) for watching(?: this video)?$/.test(normalized) || /^thanks for watching and/.test(normalized) || /\bdon't forget to (like|subscribe)\b/.test(normalized);
|
|
737943
|
+
const shouldDropCallFinalTranscript = (text2, evt) => {
|
|
737944
|
+
if (callConsensusRequired && evt.consensus !== true) {
|
|
737945
|
+
return evt.consensus === false ? "consensus rejected" : "missing consensus metadata";
|
|
737946
|
+
}
|
|
737947
|
+
const normalized = normalizeCallTranscript(text2);
|
|
737948
|
+
if (!normalized) return "empty transcript";
|
|
737949
|
+
if (isLikelyCallAsrHallucination(normalized)) {
|
|
737950
|
+
return "known whisper outro hallucination";
|
|
737951
|
+
}
|
|
737952
|
+
const now2 = Date.now();
|
|
737953
|
+
while (recentCallFinals.length > 0 && now2 - recentCallFinals[0].ts > 15e3) {
|
|
737954
|
+
recentCallFinals.shift();
|
|
737955
|
+
}
|
|
737956
|
+
if (recentCallFinals.some((entry) => entry.normalized === normalized)) {
|
|
737957
|
+
return "duplicate final transcript";
|
|
737958
|
+
}
|
|
737959
|
+
recentCallFinals.push({ normalized, ts: now2 });
|
|
737960
|
+
return null;
|
|
737961
|
+
};
|
|
737115
737962
|
voiceSession.onUserAudio = (pcmChunk, userId) => {
|
|
737116
737963
|
if (callState.sharedTranscriber)
|
|
737117
737964
|
callState.sharedTranscriber.write(pcmChunk);
|
|
@@ -737141,11 +737988,21 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
737141
737988
|
voiceEngine.synthesizeToPCM(text2).then((result) => {
|
|
737142
737989
|
if (result && session?.isActive) {
|
|
737143
737990
|
const { pcm, sampleRate } = result;
|
|
737144
|
-
session.sendSpeakingStateToClient(id2, true);
|
|
737145
|
-
session.sendAudioToClient(id2, pcm);
|
|
737146
737991
|
const durationMs = pcm.length / 2 / sampleRate * 1e3;
|
|
737992
|
+
const ttsLease = getLiveResourceArbiter().claim({
|
|
737993
|
+
owner: `call-tts:${id2}`,
|
|
737994
|
+
priority: 84,
|
|
737995
|
+
ttlMs: Math.min(45e3, durationMs + 3e3),
|
|
737996
|
+
reason: "cloud call TTS playback/echo guard",
|
|
737997
|
+
suppress: ["vision"]
|
|
737998
|
+
});
|
|
737999
|
+
session.sendSpeakingStateToClient(id2, true);
|
|
738000
|
+
session.sendAudioToClient(id2, pcm, sampleRate);
|
|
737147
738001
|
setTimeout(
|
|
737148
|
-
() =>
|
|
738002
|
+
() => {
|
|
738003
|
+
session.sendSpeakingStateToClient(id2, false);
|
|
738004
|
+
ttsLease.release();
|
|
738005
|
+
},
|
|
737149
738006
|
durationMs
|
|
737150
738007
|
);
|
|
737151
738008
|
}
|
|
@@ -737177,17 +738034,32 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
737177
738034
|
(evt) => {
|
|
737178
738035
|
if (!evt.text?.trim() || !voiceSession?.isActive) return;
|
|
737179
738036
|
const text2 = evt.text.trim();
|
|
738037
|
+
if (!evt.isFinal) return;
|
|
738038
|
+
const dropReason = shouldDropCallFinalTranscript(text2, evt);
|
|
738039
|
+
if (dropReason) {
|
|
738040
|
+
writeContent(
|
|
738041
|
+
() => renderInfo(
|
|
738042
|
+
`[call/asr] dropped ${dropReason}: "${text2.slice(0, 80)}"`
|
|
738043
|
+
)
|
|
738044
|
+
);
|
|
738045
|
+
return;
|
|
738046
|
+
}
|
|
737180
738047
|
writeContent(
|
|
737181
738048
|
() => renderVoiceSessionTranscript("user", text2)
|
|
737182
738049
|
);
|
|
737183
738050
|
voiceSession?.sendTranscript("user", text2);
|
|
737184
|
-
|
|
737185
|
-
|
|
737186
|
-
|
|
737187
|
-
|
|
737188
|
-
|
|
737189
|
-
|
|
737190
|
-
|
|
738051
|
+
getLiveResourceArbiter().claim({
|
|
738052
|
+
owner: "call-asr",
|
|
738053
|
+
priority: 92,
|
|
738054
|
+
ttlMs: 35e3,
|
|
738055
|
+
reason: "cloud call ASR accepted; reserving compute for call-agent inference",
|
|
738056
|
+
suppress: ["vision"]
|
|
738057
|
+
});
|
|
738058
|
+
for (const [clientId, agent] of callSubAgents) {
|
|
738059
|
+
agent.handleTranscript(text2);
|
|
738060
|
+
}
|
|
738061
|
+
if (callSubAgents.size === 0) {
|
|
738062
|
+
rl.feed(text2 + "\n");
|
|
737191
738063
|
}
|
|
737192
738064
|
}
|
|
737193
738065
|
);
|
|
@@ -737249,10 +738121,20 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
737249
738121
|
const session = voiceSession;
|
|
737250
738122
|
voiceEngine.onPCMOutput = (pcm, sampleRate) => {
|
|
737251
738123
|
if (session?.isActive) {
|
|
737252
|
-
session.sendSpeakingState(true);
|
|
737253
|
-
session.sendAudioToClients(pcm);
|
|
737254
738124
|
const durationMs = pcm.length / 2 / sampleRate * 1e3;
|
|
737255
|
-
|
|
738125
|
+
const ttsLease = getLiveResourceArbiter().claim({
|
|
738126
|
+
owner: "call-broadcast-tts",
|
|
738127
|
+
priority: 84,
|
|
738128
|
+
ttlMs: Math.min(45e3, durationMs + 3e3),
|
|
738129
|
+
reason: "cloud call broadcast TTS playback/echo guard",
|
|
738130
|
+
suppress: ["vision"]
|
|
738131
|
+
});
|
|
738132
|
+
session.sendSpeakingState(true);
|
|
738133
|
+
session.sendAudioToClients(pcm, sampleRate);
|
|
738134
|
+
setTimeout(() => {
|
|
738135
|
+
session.sendSpeakingState(false);
|
|
738136
|
+
ttsLease.release();
|
|
738137
|
+
}, durationMs);
|
|
737256
738138
|
}
|
|
737257
738139
|
};
|
|
737258
738140
|
}
|
|
@@ -739849,6 +740731,7 @@ var init_interactive = __esm({
|
|
|
739849
740731
|
init_expose();
|
|
739850
740732
|
init_p2p();
|
|
739851
740733
|
init_call_agent();
|
|
740734
|
+
init_live_resource_arbiter();
|
|
739852
740735
|
init_config();
|
|
739853
740736
|
init_secret_redactor();
|
|
739854
740737
|
init_profiles();
|