omnius 1.0.187 → 1.0.189
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 +812 -194
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1412,6 +1412,18 @@ var init_tool_executor = __esm({
|
|
|
1412
1412
|
import { EventEmitter } from "node:events";
|
|
1413
1413
|
import { totalmem, freemem } from "node:os";
|
|
1414
1414
|
import { exec } from "node:child_process";
|
|
1415
|
+
function dedupeLoadedModels(models) {
|
|
1416
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1417
|
+
const out = [];
|
|
1418
|
+
for (const model of models) {
|
|
1419
|
+
const key = `${model.host}:${model.name}`;
|
|
1420
|
+
if (seen.has(key))
|
|
1421
|
+
continue;
|
|
1422
|
+
seen.add(key);
|
|
1423
|
+
out.push(model);
|
|
1424
|
+
}
|
|
1425
|
+
return out;
|
|
1426
|
+
}
|
|
1415
1427
|
function ramSnapshotMB() {
|
|
1416
1428
|
const total = Math.round(totalmem() / (1024 * 1024));
|
|
1417
1429
|
const free = Math.round(freemem() / (1024 * 1024));
|
|
@@ -1690,6 +1702,104 @@ var init_model_broker = __esm({
|
|
|
1690
1702
|
this.emit("rejected", spec, reason);
|
|
1691
1703
|
return { kind: "reject", reason };
|
|
1692
1704
|
}
|
|
1705
|
+
/**
|
|
1706
|
+
* Acquire a short-lived load lease for media/subprocess generation.
|
|
1707
|
+
*
|
|
1708
|
+
* Media generation often needs to temporarily free VRAM occupied by Ollama
|
|
1709
|
+
* chat models. This helper refreshes Ollama state, asks the broker what must
|
|
1710
|
+
* be evicted, unloads those Ollama models with keep_alive=0, and returns a
|
|
1711
|
+
* lease whose release() clears transient inflight state, unloads any
|
|
1712
|
+
* Ollama-hosted requested model, and warms the evicted Ollama models again.
|
|
1713
|
+
*/
|
|
1714
|
+
async acquireTransientModelLoad(spec, options2 = {}) {
|
|
1715
|
+
const reason = options2.reason ?? `${spec.domain}-transient-load`;
|
|
1716
|
+
const evictedModels = [];
|
|
1717
|
+
let gpuIndex = null;
|
|
1718
|
+
let admitted = false;
|
|
1719
|
+
await this.pollOnce().catch(() => {
|
|
1720
|
+
});
|
|
1721
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
1722
|
+
const decision2 = await this.ensureModelLoadable(spec);
|
|
1723
|
+
if (decision2.kind === "wait-for-inflight") {
|
|
1724
|
+
const waited = await decision2.promise.catch((err) => ({
|
|
1725
|
+
kind: "reject",
|
|
1726
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
1727
|
+
}));
|
|
1728
|
+
if (waited.kind === "ok") {
|
|
1729
|
+
gpuIndex = waited.gpuIndex ?? null;
|
|
1730
|
+
admitted = true;
|
|
1731
|
+
break;
|
|
1732
|
+
}
|
|
1733
|
+
if (waited.kind === "evict") {
|
|
1734
|
+
for (const target of waited.evictTargets) {
|
|
1735
|
+
if (await this.evict(target.host, target.name, reason))
|
|
1736
|
+
evictedModels.push(target);
|
|
1737
|
+
}
|
|
1738
|
+
await this.pollOnce().catch(() => {
|
|
1739
|
+
});
|
|
1740
|
+
continue;
|
|
1741
|
+
}
|
|
1742
|
+
if (waited.kind === "degrade")
|
|
1743
|
+
return waited;
|
|
1744
|
+
if (waited.kind === "reject")
|
|
1745
|
+
return waited;
|
|
1746
|
+
continue;
|
|
1747
|
+
}
|
|
1748
|
+
if (decision2.kind === "ok") {
|
|
1749
|
+
gpuIndex = decision2.gpuIndex ?? null;
|
|
1750
|
+
admitted = true;
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1753
|
+
if (decision2.kind === "evict") {
|
|
1754
|
+
for (const target of decision2.evictTargets) {
|
|
1755
|
+
const before = this._loaded.get(`${target.host}:${target.name}`) ?? target;
|
|
1756
|
+
if (await this.evict(target.host, target.name, reason)) {
|
|
1757
|
+
evictedModels.push(before);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
await this.pollOnce().catch(() => {
|
|
1761
|
+
});
|
|
1762
|
+
continue;
|
|
1763
|
+
}
|
|
1764
|
+
if (decision2.kind === "degrade")
|
|
1765
|
+
return decision2;
|
|
1766
|
+
return decision2;
|
|
1767
|
+
}
|
|
1768
|
+
if (!admitted) {
|
|
1769
|
+
return {
|
|
1770
|
+
kind: "reject",
|
|
1771
|
+
reason: `could not acquire transient load lease for ${spec.host}:${spec.name} after repeated evictions`
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
const evictedOllamaModels = dedupeLoadedModels(evictedModels.filter((m2) => m2.host === "ollama"));
|
|
1775
|
+
const broker = this;
|
|
1776
|
+
let released = false;
|
|
1777
|
+
return {
|
|
1778
|
+
kind: "ok",
|
|
1779
|
+
lease: {
|
|
1780
|
+
spec,
|
|
1781
|
+
gpuIndex,
|
|
1782
|
+
evictedModels: dedupeLoadedModels(evictedModels),
|
|
1783
|
+
evictedOllamaModels,
|
|
1784
|
+
async release() {
|
|
1785
|
+
if (released)
|
|
1786
|
+
return;
|
|
1787
|
+
released = true;
|
|
1788
|
+
broker.clearInflight(spec.host, spec.name);
|
|
1789
|
+
if ((options2.unloadRequestedOllama ?? true) && spec.host === "ollama") {
|
|
1790
|
+
await broker.unloadOllamaModel(spec.name, `${reason}-complete`).catch(() => false);
|
|
1791
|
+
}
|
|
1792
|
+
if (options2.restoreOllama !== false && evictedOllamaModels.length > 0) {
|
|
1793
|
+
await broker.restoreOllamaModels(evictedOllamaModels, {
|
|
1794
|
+
keepAlive: options2.restoreKeepAlive ?? "30m"
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
await broker.pollOnce().catch(() => {
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1693
1803
|
/**
|
|
1694
1804
|
* Register a model that has been successfully loaded.
|
|
1695
1805
|
* Callers MUST call this after a successful load so the broker can track LRU.
|
|
@@ -1743,6 +1853,66 @@ var init_model_broker = __esm({
|
|
|
1743
1853
|
this.emit("evicted", m2, reason);
|
|
1744
1854
|
return actively;
|
|
1745
1855
|
}
|
|
1856
|
+
/** Force-unload an Ollama model even when it is not currently tracked. */
|
|
1857
|
+
async unloadOllamaModel(modelName, reason = "ollama-unload") {
|
|
1858
|
+
const key = `ollama:${modelName}`;
|
|
1859
|
+
const existing = this._loaded.get(key);
|
|
1860
|
+
const ok3 = await this.ollamaUnload(modelName).catch(() => false);
|
|
1861
|
+
if (existing) {
|
|
1862
|
+
this._loaded.delete(key);
|
|
1863
|
+
this.emit("evicted", existing, reason);
|
|
1864
|
+
}
|
|
1865
|
+
return ok3;
|
|
1866
|
+
}
|
|
1867
|
+
/** Best-effort warm/reload of an Ollama model after temporary eviction. */
|
|
1868
|
+
async warmOllamaModel(modelName, keepAlive = "30m") {
|
|
1869
|
+
const bodies = [
|
|
1870
|
+
{ model: modelName, prompt: "", stream: false, keep_alive: keepAlive, options: { num_predict: 0 } },
|
|
1871
|
+
{ model: modelName, prompt: "", stream: false, keep_alive: keepAlive, options: { num_predict: 1 } }
|
|
1872
|
+
];
|
|
1873
|
+
for (const body of bodies) {
|
|
1874
|
+
try {
|
|
1875
|
+
const res = await fetch(`${this._ollamaBaseUrl}/api/generate`, {
|
|
1876
|
+
method: "POST",
|
|
1877
|
+
headers: { "Content-Type": "application/json" },
|
|
1878
|
+
body: JSON.stringify(body),
|
|
1879
|
+
signal: AbortSignal.timeout(12e4)
|
|
1880
|
+
});
|
|
1881
|
+
if (!res.ok)
|
|
1882
|
+
continue;
|
|
1883
|
+
await this.refreshOllamaPs().catch(() => {
|
|
1884
|
+
});
|
|
1885
|
+
return true;
|
|
1886
|
+
} catch {
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
try {
|
|
1890
|
+
const res = await fetch(`${this._ollamaBaseUrl}/api/generate`, {
|
|
1891
|
+
method: "POST",
|
|
1892
|
+
headers: { "Content-Type": "application/json" },
|
|
1893
|
+
body: JSON.stringify({
|
|
1894
|
+
model: modelName,
|
|
1895
|
+
stream: false,
|
|
1896
|
+
keep_alive: keepAlive
|
|
1897
|
+
}),
|
|
1898
|
+
signal: AbortSignal.timeout(12e4)
|
|
1899
|
+
});
|
|
1900
|
+
if (!res.ok)
|
|
1901
|
+
return false;
|
|
1902
|
+
await this.refreshOllamaPs().catch(() => {
|
|
1903
|
+
});
|
|
1904
|
+
return true;
|
|
1905
|
+
} catch {
|
|
1906
|
+
return false;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
/** Restore a set of previously evicted Ollama models, oldest first. */
|
|
1910
|
+
async restoreOllamaModels(models, options2 = {}) {
|
|
1911
|
+
const unique2 = dedupeLoadedModels(models.filter((m2) => m2.host === "ollama")).sort((a2, b) => a2.lastUsedAt - b.lastUsedAt);
|
|
1912
|
+
for (const model of unique2) {
|
|
1913
|
+
await this.warmOllamaModel(model.name, options2.keepAlive ?? "30m").catch(() => false);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1746
1916
|
// ------------------------------------------------------------------
|
|
1747
1917
|
// Internal — Ollama
|
|
1748
1918
|
// ------------------------------------------------------------------
|
|
@@ -1885,7 +2055,7 @@ var init_model_broker = __esm({
|
|
|
1885
2055
|
);
|
|
1886
2056
|
const idle = (m2) => now - m2.lastUsedAt > this.idleEvictMs;
|
|
1887
2057
|
const onTargetGpu = (m2) => req2.targetGpu === void 0 || req2.targetGpu === null ? true : m2.gpuIndex === req2.targetGpu;
|
|
1888
|
-
const evictable = [...this._loaded.values()].filter((m2) => m2.priority <= req2.requestingPriority).filter(sameDomainOk).filter(onTargetGpu).sort((a2, b) => {
|
|
2058
|
+
const evictable = [...this._loaded.values()].filter((m2) => m2.priority <= req2.requestingPriority).filter(sameDomainOk).filter(onTargetGpu).filter((m2) => !this.hasActiveSlotForModel(m2)).sort((a2, b) => {
|
|
1889
2059
|
const aIdle = idle(a2) ? 0 : 1;
|
|
1890
2060
|
const bIdle = idle(b) ? 0 : 1;
|
|
1891
2061
|
if (aIdle !== bIdle)
|
|
@@ -1931,6 +2101,13 @@ var init_model_broker = __esm({
|
|
|
1931
2101
|
n2++;
|
|
1932
2102
|
return n2;
|
|
1933
2103
|
}
|
|
2104
|
+
hasActiveSlotForModel(model) {
|
|
2105
|
+
for (const slot of this._activeSlots.values()) {
|
|
2106
|
+
if (slot.model === model.name)
|
|
2107
|
+
return true;
|
|
2108
|
+
}
|
|
2109
|
+
return false;
|
|
2110
|
+
}
|
|
1934
2111
|
// ------------------------------------------------------------------
|
|
1935
2112
|
// Internal — fallback resolution
|
|
1936
2113
|
// ------------------------------------------------------------------
|
|
@@ -22761,6 +22938,17 @@ function evictModelsToFreeSpace(args) {
|
|
|
22761
22938
|
writeMeta(meta);
|
|
22762
22939
|
return { evicted, bytesFreed, finalFreeBytes: disk.freeBytes };
|
|
22763
22940
|
}
|
|
22941
|
+
function estimateReclaimableCacheBytes(keepRepos) {
|
|
22942
|
+
const keep = new Set(keepRepos ?? []);
|
|
22943
|
+
let total = 0;
|
|
22944
|
+
for (const entry of readMeta().entries) {
|
|
22945
|
+
if (keep.has(entry.repo))
|
|
22946
|
+
continue;
|
|
22947
|
+
const measured = measureRepoCacheBytes(entry.repo);
|
|
22948
|
+
total += Math.max(0, measured || entry.sizeBytes || 0);
|
|
22949
|
+
}
|
|
22950
|
+
return total;
|
|
22951
|
+
}
|
|
22764
22952
|
function ensureDiskSpaceForDownload(args) {
|
|
22765
22953
|
ensureUnifiedCacheDirs();
|
|
22766
22954
|
const safetyMargin = args.safetyMarginBytes ?? 1 * 1024 ** 3;
|
|
@@ -22769,6 +22957,10 @@ function ensureDiskSpaceForDownload(args) {
|
|
|
22769
22957
|
if (disk.freeBytes >= target) {
|
|
22770
22958
|
return { ok: true, evicted: [], freeBytes: disk.freeBytes };
|
|
22771
22959
|
}
|
|
22960
|
+
const reclaimableBytes = estimateReclaimableCacheBytes(args.keepRepos);
|
|
22961
|
+
if (disk.freeBytes + reclaimableBytes < target) {
|
|
22962
|
+
throw new InsufficientDiskSpaceError(args.approxDownloadBytes, disk.freeBytes, disk.totalBytes, []);
|
|
22963
|
+
}
|
|
22772
22964
|
const evictionResult = evictModelsToFreeSpace({
|
|
22773
22965
|
neededBytes: args.approxDownloadBytes,
|
|
22774
22966
|
keepRepos: args.keepRepos,
|
|
@@ -259208,6 +259400,12 @@ function imageCandidateFor(model, requestedBackend) {
|
|
|
259208
259400
|
preset: getImageGenerationPreset(resolved)
|
|
259209
259401
|
};
|
|
259210
259402
|
}
|
|
259403
|
+
function imageCandidateHost(candidate) {
|
|
259404
|
+
return candidate.backend === "ollama" ? "ollama" : "diffusers-py";
|
|
259405
|
+
}
|
|
259406
|
+
function imageCandidateEstimatedVramMB(candidate) {
|
|
259407
|
+
return candidate.preset?.minVramGB !== void 0 ? Math.ceil(candidate.preset.minVramGB * 1024) : void 0;
|
|
259408
|
+
}
|
|
259211
259409
|
function imageGenerationFallbackCandidates(requestedModel, requestedBackend, allowFallback = true) {
|
|
259212
259410
|
const ladder = imageGenerationQualityLadder();
|
|
259213
259411
|
const candidates = [];
|
|
@@ -259511,9 +259709,15 @@ function annotateImageFallbackSuccess(result, failed, winner) {
|
|
|
259511
259709
|
...failed.map((attempt, index) => ` ${formatImageAttempt(attempt.candidate, attempt.reason, index)}`),
|
|
259512
259710
|
""
|
|
259513
259711
|
].join("\n");
|
|
259712
|
+
const llmPrefix = [
|
|
259713
|
+
`Fallback ladder used ${winner.model} [${winner.backend}] after ${failed.length} failed attempt(s).`,
|
|
259714
|
+
...failed.map((attempt, index) => formatImageAttempt(attempt.candidate, attempt.reason, index))
|
|
259715
|
+
].join("\n");
|
|
259514
259716
|
return {
|
|
259515
259717
|
...result,
|
|
259516
|
-
output: prefix + result.output
|
|
259718
|
+
output: prefix + result.output,
|
|
259719
|
+
llmContent: result.llmContent ? `${llmPrefix}
|
|
259720
|
+
${result.llmContent}` : result.llmContent
|
|
259517
259721
|
};
|
|
259518
259722
|
}
|
|
259519
259723
|
function parseRunnerJson(stdout) {
|
|
@@ -260321,6 +260525,45 @@ if __name__ == "__main__":
|
|
|
260321
260525
|
this.lastProgressAt = now;
|
|
260322
260526
|
this.progressHandler(event);
|
|
260323
260527
|
}
|
|
260528
|
+
async acquireTransientLoadLease(args) {
|
|
260529
|
+
if (!args.candidate)
|
|
260530
|
+
return null;
|
|
260531
|
+
const broker = getModelBroker();
|
|
260532
|
+
const decision2 = await broker.acquireTransientModelLoad({
|
|
260533
|
+
name: args.candidate.model,
|
|
260534
|
+
domain: "image-gen",
|
|
260535
|
+
host: imageCandidateHost(args.candidate),
|
|
260536
|
+
owner: "image-generate-tool",
|
|
260537
|
+
estimatedVramMB: imageCandidateEstimatedVramMB(args.candidate)
|
|
260538
|
+
}, {
|
|
260539
|
+
reason: args.reason,
|
|
260540
|
+
restoreOllama: true,
|
|
260541
|
+
unloadRequestedOllama: true
|
|
260542
|
+
});
|
|
260543
|
+
if (decision2.kind === "reject") {
|
|
260544
|
+
return {
|
|
260545
|
+
success: false,
|
|
260546
|
+
output: "",
|
|
260547
|
+
error: `Image generation blocked by resource broker: ${decision2.reason}`,
|
|
260548
|
+
durationMs: performance.now() - args.start
|
|
260549
|
+
};
|
|
260550
|
+
}
|
|
260551
|
+
if (decision2.kind === "degrade") {
|
|
260552
|
+
return {
|
|
260553
|
+
success: false,
|
|
260554
|
+
output: "",
|
|
260555
|
+
error: `Image generation needs a broker fallback (${decision2.fallback.name}), but image candidate fallback must be selected by the image ladder: ${decision2.reason}`,
|
|
260556
|
+
durationMs: performance.now() - args.start
|
|
260557
|
+
};
|
|
260558
|
+
}
|
|
260559
|
+
if (decision2.lease.evictedOllamaModels.length > 0) {
|
|
260560
|
+
this.emitProgress({
|
|
260561
|
+
stage: "setup",
|
|
260562
|
+
message: `Temporarily unloaded ${decision2.lease.evictedOllamaModels.length} Ollama inference model(s) to free VRAM for image generation`
|
|
260563
|
+
});
|
|
260564
|
+
}
|
|
260565
|
+
return { lease: decision2.lease, gpuIndex: decision2.lease.gpuIndex };
|
|
260566
|
+
}
|
|
260324
260567
|
async execute(args) {
|
|
260325
260568
|
const start2 = performance.now();
|
|
260326
260569
|
const action = String(args["action"] ?? "generate");
|
|
@@ -260363,33 +260606,6 @@ if __name__ == "__main__":
|
|
|
260363
260606
|
const requestedBackend = args["backend"] ? String(args["backend"]) : this.defaultBackend;
|
|
260364
260607
|
const seed = optionalNumberArg(args["seed"]);
|
|
260365
260608
|
const candidates = imageGenerationFallbackCandidates(requestedModel, requestedBackend, generationFallbackEnabled(args));
|
|
260366
|
-
const broker = getModelBroker();
|
|
260367
|
-
const firstCandidate = candidates[0];
|
|
260368
|
-
let brokerGpuIndex = null;
|
|
260369
|
-
if (firstCandidate) {
|
|
260370
|
-
const decision2 = await broker.ensureModelLoadable({
|
|
260371
|
-
name: firstCandidate.model,
|
|
260372
|
-
domain: "image-gen",
|
|
260373
|
-
host: firstCandidate.backend === "ollama" ? "ollama" : "diffusers-py",
|
|
260374
|
-
owner: "image-generate-tool"
|
|
260375
|
-
});
|
|
260376
|
-
if (decision2.kind === "evict") {
|
|
260377
|
-
for (const target of decision2.evictTargets) {
|
|
260378
|
-
await broker.evict(target.host, target.name, "image-gen-needs-room");
|
|
260379
|
-
}
|
|
260380
|
-
brokerGpuIndex = decision2.gpuIndex ?? null;
|
|
260381
|
-
} else if (decision2.kind === "ok") {
|
|
260382
|
-
brokerGpuIndex = decision2.gpuIndex ?? null;
|
|
260383
|
-
} else if (decision2.kind === "reject") {
|
|
260384
|
-
return {
|
|
260385
|
-
success: false,
|
|
260386
|
-
output: "",
|
|
260387
|
-
error: `Image generation blocked by resource broker: ${decision2.reason}`,
|
|
260388
|
-
durationMs: performance.now() - start2
|
|
260389
|
-
};
|
|
260390
|
-
}
|
|
260391
|
-
}
|
|
260392
|
-
this._brokerGpuIndex = brokerGpuIndex;
|
|
260393
260609
|
try {
|
|
260394
260610
|
return await this.generateCandidateLadder({ candidates, prompt, args, seed, start: start2 });
|
|
260395
260611
|
} catch (err) {
|
|
@@ -260408,7 +260624,30 @@ if __name__ == "__main__":
|
|
|
260408
260624
|
stage: "setup",
|
|
260409
260625
|
message: `Preparing image model ${candidate.model} (${candidate.backend}) [${index + 1}/${args.candidates.length}]`
|
|
260410
260626
|
});
|
|
260411
|
-
const
|
|
260627
|
+
const leaseDecision = await this.acquireTransientLoadLease({
|
|
260628
|
+
candidate,
|
|
260629
|
+
reason: "image-prewarm-needs-room",
|
|
260630
|
+
start: args.start
|
|
260631
|
+
});
|
|
260632
|
+
if (leaseDecision && "success" in leaseDecision) {
|
|
260633
|
+
failed.push({ candidate, reason: summarizeToolResult(leaseDecision) });
|
|
260634
|
+
if (index < args.candidates.length - 1) {
|
|
260635
|
+
this.emitProgress({
|
|
260636
|
+
stage: "setup",
|
|
260637
|
+
message: `${candidate.model} did not fit current resources; trying ${args.candidates[index + 1].model}`
|
|
260638
|
+
});
|
|
260639
|
+
}
|
|
260640
|
+
continue;
|
|
260641
|
+
}
|
|
260642
|
+
const lease = leaseDecision?.lease;
|
|
260643
|
+
this._brokerGpuIndex = leaseDecision?.gpuIndex ?? null;
|
|
260644
|
+
let result;
|
|
260645
|
+
try {
|
|
260646
|
+
result = candidate.backend === "ollama" ? await this.prewarmOllama({ model: candidate.model, start: args.start }) : candidate.backend === "sdcpp" ? await this.prewarmSdCpp({ model: candidate.model, start: args.start, python: args.args["python"] }) : await this.prewarmDiffusers({ model: candidate.model, start: args.start, python: args.args["python"] });
|
|
260647
|
+
} finally {
|
|
260648
|
+
await lease?.release();
|
|
260649
|
+
this._brokerGpuIndex = null;
|
|
260650
|
+
}
|
|
260412
260651
|
if (result.success)
|
|
260413
260652
|
return annotateImageFallbackSuccess(result, failed, candidate);
|
|
260414
260653
|
failed.push({ candidate, reason: summarizeToolResult(result) });
|
|
@@ -260447,7 +260686,30 @@ if __name__ == "__main__":
|
|
|
260447
260686
|
message: `Using image model ${candidate.model} (${candidate.backend}) [${index + 1}/${args.candidates.length}]`
|
|
260448
260687
|
});
|
|
260449
260688
|
const promptForCandidate = expansionEnabled ? await this.expandPromptForCandidate(args.prompt, candidate, index, args.candidates.length) : args.prompt;
|
|
260450
|
-
const
|
|
260689
|
+
const leaseDecision = await this.acquireTransientLoadLease({
|
|
260690
|
+
candidate,
|
|
260691
|
+
reason: "image-gen-needs-room",
|
|
260692
|
+
start: args.start
|
|
260693
|
+
});
|
|
260694
|
+
if (leaseDecision && "success" in leaseDecision) {
|
|
260695
|
+
failed.push({ candidate, reason: summarizeToolResult(leaseDecision) });
|
|
260696
|
+
if (index < args.candidates.length - 1) {
|
|
260697
|
+
this.emitProgress({
|
|
260698
|
+
stage: "setup",
|
|
260699
|
+
message: `${candidate.model} did not fit current resources; falling back to ${args.candidates[index + 1].model}`
|
|
260700
|
+
});
|
|
260701
|
+
}
|
|
260702
|
+
continue;
|
|
260703
|
+
}
|
|
260704
|
+
const lease = leaseDecision?.lease;
|
|
260705
|
+
this._brokerGpuIndex = leaseDecision?.gpuIndex ?? null;
|
|
260706
|
+
let result;
|
|
260707
|
+
try {
|
|
260708
|
+
result = candidate.backend === "ollama" ? await this.generateWithOllama({ prompt: promptForCandidate, model: candidate.model, width, height, steps, start: args.start }) : candidate.backend === "sdcpp" ? await this.generateWithSdCpp({ prompt: promptForCandidate, model: candidate.model, width, height, steps, seed: args.seed, start: args.start, python: args.args["python"] }) : await this.generateWithDiffusers({ prompt: promptForCandidate, model: candidate.model, width, height, steps, guidance, seed: args.seed, start: args.start, python: args.args["python"] });
|
|
260709
|
+
} finally {
|
|
260710
|
+
await lease?.release();
|
|
260711
|
+
this._brokerGpuIndex = null;
|
|
260712
|
+
}
|
|
260451
260713
|
if (result.success) {
|
|
260452
260714
|
await this.writeImageSidecar(result, {
|
|
260453
260715
|
originalPrompt: args.prompt,
|
|
@@ -260671,6 +260933,17 @@ ${errText.slice(0, 1200)}`,
|
|
|
260671
260933
|
}
|
|
260672
260934
|
ensureUnifiedCacheDirs();
|
|
260673
260935
|
this.emitProgress({ stage: "load", message: `Downloading/loading image model ${args.model}` });
|
|
260936
|
+
const runnerEnv = { ...python.env };
|
|
260937
|
+
if (this._brokerGpuIndex !== null) {
|
|
260938
|
+
if (mediaBrokerGpuIndexIsCompatible(this._brokerGpuIndex, "image", runnerEnv)) {
|
|
260939
|
+
runnerEnv["OMNIUS_GPU_INDEX"] = String(this._brokerGpuIndex);
|
|
260940
|
+
} else {
|
|
260941
|
+
this.emitProgress({
|
|
260942
|
+
stage: "setup",
|
|
260943
|
+
message: `Broker selected CUDA GPU ${this._brokerGpuIndex}, but image CUDA filtering excluded it; using CUDA_VISIBLE_DEVICES=${runnerEnv["CUDA_VISIBLE_DEVICES"] ?? "default"}`
|
|
260944
|
+
});
|
|
260945
|
+
}
|
|
260946
|
+
}
|
|
260674
260947
|
const result = await runProcess2(python.command, [
|
|
260675
260948
|
runner,
|
|
260676
260949
|
"--model",
|
|
@@ -260683,7 +260956,7 @@ ${errText.slice(0, 1200)}`,
|
|
|
260683
260956
|
], {
|
|
260684
260957
|
cwd: this.cwd,
|
|
260685
260958
|
timeoutMs: 18e5,
|
|
260686
|
-
env:
|
|
260959
|
+
env: runnerEnv,
|
|
260687
260960
|
progressLabel: `Downloading/loading ${args.model}`,
|
|
260688
260961
|
onProgress: (event) => this.emitProgress(event)
|
|
260689
260962
|
});
|
|
@@ -261735,6 +262008,18 @@ function audioCandidateFor(kind, model, requestedBackend) {
|
|
|
261735
262008
|
preset: getAudioGenerationPreset(model, kind)
|
|
261736
262009
|
};
|
|
261737
262010
|
}
|
|
262011
|
+
function audioCandidateHost(candidate) {
|
|
262012
|
+
if (candidate.backend === "project")
|
|
262013
|
+
return null;
|
|
262014
|
+
if (candidate.backend === "audiocraft")
|
|
262015
|
+
return "audiocraft";
|
|
262016
|
+
if (candidate.backend === "tangoflux")
|
|
262017
|
+
return "tangoflux";
|
|
262018
|
+
return "diffusers-py";
|
|
262019
|
+
}
|
|
262020
|
+
function audioCandidateEstimatedVramMB(candidate) {
|
|
262021
|
+
return candidate.preset ? Math.ceil(candidate.preset.minVramGB * 1024) : void 0;
|
|
262022
|
+
}
|
|
261738
262023
|
function audioGenerationFallbackCandidates(kind, requestedModel, requestedBackend, allowFallback = true) {
|
|
261739
262024
|
const ladder = audioGenerationQualityLadder(kind);
|
|
261740
262025
|
const candidates = [];
|
|
@@ -261891,9 +262176,15 @@ function annotateAudioFallbackSuccess(result, failed, winner) {
|
|
|
261891
262176
|
...failed.map((attempt, index) => ` ${formatAudioAttempt(attempt.candidate, attempt.reason, index)}`),
|
|
261892
262177
|
""
|
|
261893
262178
|
].join("\n");
|
|
262179
|
+
const llmPrefix = [
|
|
262180
|
+
`Fallback ladder used ${winner.model} [${winner.backend}] after ${failed.length} failed attempt(s).`,
|
|
262181
|
+
...failed.map((attempt, index) => formatAudioAttempt(attempt.candidate, attempt.reason, index))
|
|
262182
|
+
].join("\n");
|
|
261894
262183
|
return {
|
|
261895
262184
|
...result,
|
|
261896
|
-
output: prefix + result.output
|
|
262185
|
+
output: prefix + result.output,
|
|
262186
|
+
llmContent: result.llmContent ? `${llmPrefix}
|
|
262187
|
+
${result.llmContent}` : result.llmContent
|
|
261897
262188
|
};
|
|
261898
262189
|
}
|
|
261899
262190
|
var DEFAULT_SOUND_MODEL, DEFAULT_MUSIC_MODEL, DIFFUSERS_AUDIO_PACKAGES, TRANSFORMERS_AUDIO_PACKAGES, AUDIOCRAFT_PACKAGES, STABLE_AUDIO_PACKAGES, TANGOFLUX_PACKAGES, AUDIO_GENERATION_MODEL_PRESETS, SOUND_GENERATION_QUALITY_LADDER, MUSIC_GENERATION_QUALITY_LADDER, DIFFUSERS_AUDIO_RUNNER, AUDIOCRAFT_RUNNER, TRANSFORMERS_AUDIO_RUNNER, TANGOFLUX_RUNNER, AudioGenerateTool;
|
|
@@ -262730,6 +263021,48 @@ if __name__ == "__main__":
|
|
|
262730
263021
|
this.lastProgressAt = now;
|
|
262731
263022
|
this.progressHandler(event);
|
|
262732
263023
|
}
|
|
263024
|
+
async acquireTransientLoadLease(args) {
|
|
263025
|
+
if (!args.candidate)
|
|
263026
|
+
return null;
|
|
263027
|
+
const host = audioCandidateHost(args.candidate);
|
|
263028
|
+
if (!host)
|
|
263029
|
+
return null;
|
|
263030
|
+
const broker = getModelBroker();
|
|
263031
|
+
const decision2 = await broker.acquireTransientModelLoad({
|
|
263032
|
+
name: args.candidate.model,
|
|
263033
|
+
domain: args.kind,
|
|
263034
|
+
host,
|
|
263035
|
+
owner: `audio-generate-tool/${args.kind}`,
|
|
263036
|
+
estimatedVramMB: audioCandidateEstimatedVramMB(args.candidate)
|
|
263037
|
+
}, {
|
|
263038
|
+
reason: args.reason,
|
|
263039
|
+
restoreOllama: true,
|
|
263040
|
+
unloadRequestedOllama: false
|
|
263041
|
+
});
|
|
263042
|
+
if (decision2.kind === "reject") {
|
|
263043
|
+
return {
|
|
263044
|
+
success: false,
|
|
263045
|
+
output: "",
|
|
263046
|
+
error: `${args.kind === "music" ? "Music" : "Sound"} generation blocked by resource broker: ${decision2.reason}`,
|
|
263047
|
+
durationMs: performance.now() - args.start
|
|
263048
|
+
};
|
|
263049
|
+
}
|
|
263050
|
+
if (decision2.kind === "degrade") {
|
|
263051
|
+
return {
|
|
263052
|
+
success: false,
|
|
263053
|
+
output: "",
|
|
263054
|
+
error: `${args.kind === "music" ? "Music" : "Sound"} generation needs a broker fallback (${decision2.fallback.name}), but audio candidate fallback must be selected by the audio ladder: ${decision2.reason}`,
|
|
263055
|
+
durationMs: performance.now() - args.start
|
|
263056
|
+
};
|
|
263057
|
+
}
|
|
263058
|
+
if (decision2.lease.evictedOllamaModels.length > 0) {
|
|
263059
|
+
this.emitProgress({
|
|
263060
|
+
stage: "setup",
|
|
263061
|
+
message: `Temporarily unloaded ${decision2.lease.evictedOllamaModels.length} Ollama inference model(s) to free VRAM for ${args.kind} generation`
|
|
263062
|
+
});
|
|
263063
|
+
}
|
|
263064
|
+
return { lease: decision2.lease, gpuIndex: decision2.lease.gpuIndex };
|
|
263065
|
+
}
|
|
262733
263066
|
async prewarmPythonBackend(args) {
|
|
262734
263067
|
const runner = await ensureAudioRunner(this.cwd, args.runnerBackend);
|
|
262735
263068
|
let python;
|
|
@@ -262776,6 +263109,17 @@ if __name__ == "__main__":
|
|
|
262776
263109
|
}
|
|
262777
263110
|
ensureUnifiedCacheDirs();
|
|
262778
263111
|
this.emitProgress({ stage: "load", message: `Downloading/loading ${args.kind} model ${args.model}` });
|
|
263112
|
+
const runnerEnv = { ...python.env };
|
|
263113
|
+
if (this._brokerGpuIndex !== null) {
|
|
263114
|
+
if (audioBrokerGpuIndexIsCompatible(this._brokerGpuIndex, runnerEnv)) {
|
|
263115
|
+
runnerEnv["OMNIUS_GPU_INDEX"] = String(this._brokerGpuIndex);
|
|
263116
|
+
} else {
|
|
263117
|
+
this.emitProgress({
|
|
263118
|
+
stage: "setup",
|
|
263119
|
+
message: `Broker selected CUDA GPU ${this._brokerGpuIndex}, but audio CUDA filtering excluded it; using CUDA_VISIBLE_DEVICES=${runnerEnv["CUDA_VISIBLE_DEVICES"] ?? "default"}`
|
|
263120
|
+
});
|
|
263121
|
+
}
|
|
263122
|
+
}
|
|
262779
263123
|
const result = await runProcess3(python.command, [
|
|
262780
263124
|
runner,
|
|
262781
263125
|
"--kind",
|
|
@@ -262792,7 +263136,7 @@ if __name__ == "__main__":
|
|
|
262792
263136
|
], {
|
|
262793
263137
|
cwd: this.cwd,
|
|
262794
263138
|
timeoutMs: 18e5,
|
|
262795
|
-
env:
|
|
263139
|
+
env: runnerEnv,
|
|
262796
263140
|
progressLabel: `Downloading/loading ${args.model}`,
|
|
262797
263141
|
onProgress: (event) => this.emitProgress(event)
|
|
262798
263142
|
});
|
|
@@ -262872,33 +263216,6 @@ if __name__ == "__main__":
|
|
|
262872
263216
|
const candidates = audioGenerationFallbackCandidates(kind, requestedModel, requestedBackend, generationFallbackEnabled2(args));
|
|
262873
263217
|
const seed = optionalNumberArg2(args["seed"]);
|
|
262874
263218
|
const playback = playbackRequested(args);
|
|
262875
|
-
const broker = getModelBroker();
|
|
262876
|
-
const firstCandidate = candidates[0];
|
|
262877
|
-
let brokerGpuIndex = null;
|
|
262878
|
-
if (firstCandidate) {
|
|
262879
|
-
const decision2 = await broker.ensureModelLoadable({
|
|
262880
|
-
name: firstCandidate.model,
|
|
262881
|
-
domain: kind === "music" ? "music" : "sound",
|
|
262882
|
-
host: firstCandidate.backend === "audiocraft" ? "audiocraft" : firstCandidate.backend === "tangoflux" ? "tangoflux" : firstCandidate.backend === "transformers" ? "diffusers-py" : "diffusers-py",
|
|
262883
|
-
owner: `audio-generate-tool/${kind}`
|
|
262884
|
-
});
|
|
262885
|
-
if (decision2.kind === "evict") {
|
|
262886
|
-
for (const target of decision2.evictTargets) {
|
|
262887
|
-
await broker.evict(target.host, target.name, `${kind}-gen-needs-room`);
|
|
262888
|
-
}
|
|
262889
|
-
brokerGpuIndex = decision2.gpuIndex ?? null;
|
|
262890
|
-
} else if (decision2.kind === "ok") {
|
|
262891
|
-
brokerGpuIndex = decision2.gpuIndex ?? null;
|
|
262892
|
-
} else if (decision2.kind === "reject") {
|
|
262893
|
-
return {
|
|
262894
|
-
success: false,
|
|
262895
|
-
output: "",
|
|
262896
|
-
error: `${kind === "music" ? "Music" : "Sound"} generation blocked by resource broker: ${decision2.reason}`,
|
|
262897
|
-
durationMs: performance.now() - start2
|
|
262898
|
-
};
|
|
262899
|
-
}
|
|
262900
|
-
}
|
|
262901
|
-
this._brokerGpuIndex = brokerGpuIndex;
|
|
262902
263219
|
try {
|
|
262903
263220
|
return await this.generateCandidateLadder({ kind, candidates, prompt, args, seed, playback, start: start2 });
|
|
262904
263221
|
} catch (err) {
|
|
@@ -262918,15 +263235,39 @@ if __name__ == "__main__":
|
|
|
262918
263235
|
stage: "setup",
|
|
262919
263236
|
message: `Preparing ${args.kind} model ${candidate.model} (${candidate.backend}) [${index + 1}/${args.candidates.length}]`
|
|
262920
263237
|
});
|
|
262921
|
-
const
|
|
263238
|
+
const leaseDecision = await this.acquireTransientLoadLease({
|
|
262922
263239
|
kind: args.kind,
|
|
262923
|
-
|
|
262924
|
-
|
|
262925
|
-
|
|
262926
|
-
|
|
262927
|
-
|
|
262928
|
-
|
|
262929
|
-
|
|
263240
|
+
candidate,
|
|
263241
|
+
reason: `${args.kind}-prewarm-needs-room`,
|
|
263242
|
+
start: args.start
|
|
263243
|
+
});
|
|
263244
|
+
if (leaseDecision && "success" in leaseDecision) {
|
|
263245
|
+
failed.push({ candidate, reason: summarizeToolResult2(leaseDecision) });
|
|
263246
|
+
if (index < args.candidates.length - 1) {
|
|
263247
|
+
this.emitProgress({
|
|
263248
|
+
stage: "setup",
|
|
263249
|
+
message: `${candidate.model} did not fit current resources; trying ${args.candidates[index + 1].model}`
|
|
263250
|
+
});
|
|
263251
|
+
}
|
|
263252
|
+
continue;
|
|
263253
|
+
}
|
|
263254
|
+
const lease = leaseDecision?.lease;
|
|
263255
|
+
this._brokerGpuIndex = leaseDecision?.gpuIndex ?? null;
|
|
263256
|
+
let result;
|
|
263257
|
+
try {
|
|
263258
|
+
result = candidate.backend === "project" ? this.projectProfileResult(args.kind, candidate, args.start) : await this.prewarmPythonBackend({
|
|
263259
|
+
kind: args.kind,
|
|
263260
|
+
backend: candidate.backend,
|
|
263261
|
+
runnerBackend: candidate.backend,
|
|
263262
|
+
model: candidate.model,
|
|
263263
|
+
duration,
|
|
263264
|
+
start: args.start,
|
|
263265
|
+
python: args.args["python"]
|
|
263266
|
+
});
|
|
263267
|
+
} finally {
|
|
263268
|
+
await lease?.release();
|
|
263269
|
+
this._brokerGpuIndex = null;
|
|
263270
|
+
}
|
|
262930
263271
|
if (result.success)
|
|
262931
263272
|
return annotateAudioFallbackSuccess(result, failed, candidate);
|
|
262932
263273
|
failed.push({ candidate, reason: summarizeToolResult2(result) });
|
|
@@ -262954,19 +263295,43 @@ if __name__ == "__main__":
|
|
|
262954
263295
|
stage: "setup",
|
|
262955
263296
|
message: `Using ${args.kind} model ${candidate.model} (${candidate.backend}) [${index + 1}/${args.candidates.length}]`
|
|
262956
263297
|
});
|
|
262957
|
-
const
|
|
263298
|
+
const leaseDecision = await this.acquireTransientLoadLease({
|
|
262958
263299
|
kind: args.kind,
|
|
262959
|
-
|
|
262960
|
-
|
|
262961
|
-
|
|
262962
|
-
|
|
262963
|
-
|
|
262964
|
-
|
|
262965
|
-
|
|
262966
|
-
|
|
262967
|
-
|
|
262968
|
-
|
|
262969
|
-
|
|
263300
|
+
candidate,
|
|
263301
|
+
reason: `${args.kind}-gen-needs-room`,
|
|
263302
|
+
start: args.start
|
|
263303
|
+
});
|
|
263304
|
+
if (leaseDecision && "success" in leaseDecision) {
|
|
263305
|
+
failed.push({ candidate, reason: summarizeToolResult2(leaseDecision) });
|
|
263306
|
+
if (index < args.candidates.length - 1) {
|
|
263307
|
+
this.emitProgress({
|
|
263308
|
+
stage: "setup",
|
|
263309
|
+
message: `${candidate.model} did not fit current resources; falling back to ${args.candidates[index + 1].model}`
|
|
263310
|
+
});
|
|
263311
|
+
}
|
|
263312
|
+
continue;
|
|
263313
|
+
}
|
|
263314
|
+
const lease = leaseDecision?.lease;
|
|
263315
|
+
this._brokerGpuIndex = leaseDecision?.gpuIndex ?? null;
|
|
263316
|
+
let result;
|
|
263317
|
+
try {
|
|
263318
|
+
result = candidate.backend === "project" ? this.projectProfileResult(args.kind, candidate, args.start) : await this.generateWithPythonBackend({
|
|
263319
|
+
kind: args.kind,
|
|
263320
|
+
backend: candidate.backend,
|
|
263321
|
+
runnerBackend: candidate.backend,
|
|
263322
|
+
prompt: args.prompt,
|
|
263323
|
+
model: candidate.model,
|
|
263324
|
+
duration,
|
|
263325
|
+
steps,
|
|
263326
|
+
seed: args.seed,
|
|
263327
|
+
playback: args.playback,
|
|
263328
|
+
start: args.start,
|
|
263329
|
+
python: args.args["python"]
|
|
263330
|
+
});
|
|
263331
|
+
} finally {
|
|
263332
|
+
await lease?.release();
|
|
263333
|
+
this._brokerGpuIndex = null;
|
|
263334
|
+
}
|
|
262970
263335
|
if (result.success)
|
|
262971
263336
|
return annotateAudioFallbackSuccess(result, failed, candidate);
|
|
262972
263337
|
failed.push({ candidate, reason: summarizeToolResult2(result) });
|
|
@@ -263306,6 +263671,12 @@ function videoCandidateFor(model, requestedBackend, requestedKind) {
|
|
|
263306
263671
|
}
|
|
263307
263672
|
return { model, backend, preset };
|
|
263308
263673
|
}
|
|
263674
|
+
function videoCandidateHost(candidate) {
|
|
263675
|
+
return candidate.backend === "comfyui" ? "comfyui" : "diffusers-py";
|
|
263676
|
+
}
|
|
263677
|
+
function videoCandidateEstimatedVramMB(candidate) {
|
|
263678
|
+
return candidate.preset ? Math.ceil(candidate.preset.minVramGB * 1024) : void 0;
|
|
263679
|
+
}
|
|
263309
263680
|
function videoGenerationFallbackCandidates(requestedModel, requestedBackend, requestedKind, allowFallback = true, options2 = {}) {
|
|
263310
263681
|
const preferAudioVideo = Boolean(options2.preferNativeAudioVideo);
|
|
263311
263682
|
const baseLadderIds = preferAudioVideo ? [...VIDEO_AUDIO_QUALITY_LADDER, ...VIDEO_GENERATION_QUALITY_LADDER] : VIDEO_GENERATION_QUALITY_LADDER;
|
|
@@ -263871,9 +264242,15 @@ function annotateVideoFallbackSuccess(result, failed, winner) {
|
|
|
263871
264242
|
...failed.map((attempt, index) => ` ${formatVideoAttempt(attempt.candidate, attempt.reason, index)}`),
|
|
263872
264243
|
""
|
|
263873
264244
|
].join("\n");
|
|
264245
|
+
const llmPrefix = [
|
|
264246
|
+
`Fallback ladder used ${winner.model} [${winner.backend}] after ${failed.length} failed attempt(s).`,
|
|
264247
|
+
...failed.map((attempt, index) => formatVideoAttempt(attempt.candidate, attempt.reason, index))
|
|
264248
|
+
].join("\n");
|
|
263874
264249
|
return {
|
|
263875
264250
|
...result,
|
|
263876
|
-
output: prefix + result.output
|
|
264251
|
+
output: prefix + result.output,
|
|
264252
|
+
llmContent: result.llmContent ? `${llmPrefix}
|
|
264253
|
+
${result.llmContent}` : result.llmContent
|
|
263877
264254
|
};
|
|
263878
264255
|
}
|
|
263879
264256
|
function parseRunnerJson3(stdout) {
|
|
@@ -265240,6 +265617,45 @@ if __name__ == "__main__":
|
|
|
265240
265617
|
this.lastProgressAt = now;
|
|
265241
265618
|
this.progressHandler(event);
|
|
265242
265619
|
}
|
|
265620
|
+
async acquireTransientLoadLease(args) {
|
|
265621
|
+
if (!args.candidate)
|
|
265622
|
+
return null;
|
|
265623
|
+
const broker = getModelBroker();
|
|
265624
|
+
const decision2 = await broker.acquireTransientModelLoad({
|
|
265625
|
+
name: args.candidate.model,
|
|
265626
|
+
domain: "video-gen",
|
|
265627
|
+
host: videoCandidateHost(args.candidate),
|
|
265628
|
+
owner: "video-generate-tool",
|
|
265629
|
+
estimatedVramMB: videoCandidateEstimatedVramMB(args.candidate)
|
|
265630
|
+
}, {
|
|
265631
|
+
reason: args.reason,
|
|
265632
|
+
restoreOllama: true,
|
|
265633
|
+
unloadRequestedOllama: false
|
|
265634
|
+
});
|
|
265635
|
+
if (decision2.kind === "reject") {
|
|
265636
|
+
return {
|
|
265637
|
+
success: false,
|
|
265638
|
+
output: "",
|
|
265639
|
+
error: `Video generation blocked by resource broker: ${decision2.reason}`,
|
|
265640
|
+
durationMs: performance.now() - args.start
|
|
265641
|
+
};
|
|
265642
|
+
}
|
|
265643
|
+
if (decision2.kind === "degrade") {
|
|
265644
|
+
return {
|
|
265645
|
+
success: false,
|
|
265646
|
+
output: "",
|
|
265647
|
+
error: `Video generation needs a broker fallback (${decision2.fallback.name}), but video candidate fallback must be selected by the video ladder: ${decision2.reason}`,
|
|
265648
|
+
durationMs: performance.now() - args.start
|
|
265649
|
+
};
|
|
265650
|
+
}
|
|
265651
|
+
if (decision2.lease.evictedOllamaModels.length > 0) {
|
|
265652
|
+
this.emitProgress({
|
|
265653
|
+
stage: "setup",
|
|
265654
|
+
message: `Temporarily unloaded ${decision2.lease.evictedOllamaModels.length} Ollama inference model(s) to free VRAM for video generation`
|
|
265655
|
+
});
|
|
265656
|
+
}
|
|
265657
|
+
return { lease: decision2.lease, gpuIndex: decision2.lease.gpuIndex };
|
|
265658
|
+
}
|
|
265243
265659
|
async execute(args) {
|
|
265244
265660
|
const start2 = performance.now();
|
|
265245
265661
|
const action = String(args["action"] ?? "generate");
|
|
@@ -265295,35 +265711,6 @@ if __name__ == "__main__":
|
|
|
265295
265711
|
const withAudio = booleanArg3(args["with_audio"], false);
|
|
265296
265712
|
const audioInput = typeof args["audio_input"] === "string" && args["audio_input"].trim() ? String(args["audio_input"]).trim() : void 0;
|
|
265297
265713
|
const candidates = videoGenerationFallbackCandidates(requestedModel, requestedBackend, inferredKind, generationFallbackEnabled3(args), { preferNativeAudioVideo: withAudio || Boolean(audioInput) });
|
|
265298
|
-
const broker = getModelBroker();
|
|
265299
|
-
const firstCandidate = candidates[0];
|
|
265300
|
-
let brokerGpuIndex = null;
|
|
265301
|
-
if (firstCandidate) {
|
|
265302
|
-
const preset = firstCandidate.preset;
|
|
265303
|
-
const decision2 = await broker.ensureModelLoadable({
|
|
265304
|
-
name: firstCandidate.model,
|
|
265305
|
-
domain: "video-gen",
|
|
265306
|
-
host: firstCandidate.backend === "comfyui" ? "comfyui" : "diffusers-py",
|
|
265307
|
-
owner: "video-generate-tool",
|
|
265308
|
-
estimatedVramMB: preset ? preset.minVramGB * 1024 : void 0
|
|
265309
|
-
});
|
|
265310
|
-
if (decision2.kind === "evict") {
|
|
265311
|
-
for (const target of decision2.evictTargets) {
|
|
265312
|
-
await broker.evict(target.host, target.name, "video-gen-needs-room");
|
|
265313
|
-
}
|
|
265314
|
-
brokerGpuIndex = decision2.gpuIndex ?? null;
|
|
265315
|
-
} else if (decision2.kind === "ok") {
|
|
265316
|
-
brokerGpuIndex = decision2.gpuIndex ?? null;
|
|
265317
|
-
} else if (decision2.kind === "reject") {
|
|
265318
|
-
return {
|
|
265319
|
-
success: false,
|
|
265320
|
-
output: "",
|
|
265321
|
-
error: `Video generation blocked by resource broker: ${decision2.reason}`,
|
|
265322
|
-
durationMs: performance.now() - start2
|
|
265323
|
-
};
|
|
265324
|
-
}
|
|
265325
|
-
}
|
|
265326
|
-
this._brokerGpuIndex = brokerGpuIndex;
|
|
265327
265714
|
if (candidates.length === 0) {
|
|
265328
265715
|
return {
|
|
265329
265716
|
success: false,
|
|
@@ -265373,7 +265760,30 @@ if __name__ == "__main__":
|
|
|
265373
265760
|
failed.push({ candidate, reason: "ComfyUI backend not yet implemented." });
|
|
265374
265761
|
continue;
|
|
265375
265762
|
}
|
|
265376
|
-
const
|
|
265763
|
+
const leaseDecision = await this.acquireTransientLoadLease({
|
|
265764
|
+
candidate,
|
|
265765
|
+
reason: "video-prewarm-needs-room",
|
|
265766
|
+
start: args.start
|
|
265767
|
+
});
|
|
265768
|
+
if (leaseDecision && "success" in leaseDecision) {
|
|
265769
|
+
failed.push({ candidate, reason: summarizeToolResult3(leaseDecision) });
|
|
265770
|
+
if (index < args.candidates.length - 1) {
|
|
265771
|
+
this.emitProgress({
|
|
265772
|
+
stage: "setup",
|
|
265773
|
+
message: `${candidate.model} did not fit current resources; trying ${args.candidates[index + 1].model}`
|
|
265774
|
+
});
|
|
265775
|
+
}
|
|
265776
|
+
continue;
|
|
265777
|
+
}
|
|
265778
|
+
const lease = leaseDecision?.lease;
|
|
265779
|
+
this._brokerGpuIndex = leaseDecision?.gpuIndex ?? null;
|
|
265780
|
+
let result;
|
|
265781
|
+
try {
|
|
265782
|
+
result = await this.prewarmDiffusers({ candidate, start: args.start, python: args.args["python"] });
|
|
265783
|
+
} finally {
|
|
265784
|
+
await lease?.release();
|
|
265785
|
+
this._brokerGpuIndex = null;
|
|
265786
|
+
}
|
|
265377
265787
|
if (result.success)
|
|
265378
265788
|
return annotateVideoFallbackSuccess(result, failed, candidate);
|
|
265379
265789
|
failed.push({ candidate, reason: summarizeToolResult3(result) });
|
|
@@ -265459,26 +265869,48 @@ if __name__ == "__main__":
|
|
|
265459
265869
|
start: args.start
|
|
265460
265870
|
});
|
|
265461
265871
|
} else {
|
|
265462
|
-
|
|
265463
|
-
|
|
265464
|
-
|
|
265465
|
-
|
|
265466
|
-
kind: args.kind,
|
|
265467
|
-
imageArg: args.imageArg,
|
|
265468
|
-
audioInput: args.audioInput,
|
|
265469
|
-
width,
|
|
265470
|
-
height,
|
|
265471
|
-
numFrames,
|
|
265472
|
-
fps,
|
|
265473
|
-
steps,
|
|
265474
|
-
guidance,
|
|
265475
|
-
negativePrompt,
|
|
265476
|
-
seed: args.seed,
|
|
265477
|
-
hfToken: hfTokenOverride,
|
|
265478
|
-
autoAcceptLicense,
|
|
265479
|
-
start: args.start,
|
|
265480
|
-
python: args.args["python"]
|
|
265872
|
+
const leaseDecision = await this.acquireTransientLoadLease({
|
|
265873
|
+
candidate,
|
|
265874
|
+
reason: "video-gen-needs-room",
|
|
265875
|
+
start: args.start
|
|
265481
265876
|
});
|
|
265877
|
+
if (leaseDecision && "success" in leaseDecision) {
|
|
265878
|
+
failed.push({ candidate, reason: summarizeToolResult3(leaseDecision) });
|
|
265879
|
+
if (index < args.candidates.length - 1) {
|
|
265880
|
+
this.emitProgress({
|
|
265881
|
+
stage: "setup",
|
|
265882
|
+
message: `${candidate.model} did not fit current resources; falling back to ${args.candidates[index + 1].model}`
|
|
265883
|
+
});
|
|
265884
|
+
}
|
|
265885
|
+
continue;
|
|
265886
|
+
}
|
|
265887
|
+
const lease = leaseDecision?.lease;
|
|
265888
|
+
this._brokerGpuIndex = leaseDecision?.gpuIndex ?? null;
|
|
265889
|
+
try {
|
|
265890
|
+
result = await this.generateWithDiffusers({
|
|
265891
|
+
prompt: promptForCandidate,
|
|
265892
|
+
model: candidate.model,
|
|
265893
|
+
preset,
|
|
265894
|
+
kind: args.kind,
|
|
265895
|
+
imageArg: args.imageArg,
|
|
265896
|
+
audioInput: args.audioInput,
|
|
265897
|
+
width,
|
|
265898
|
+
height,
|
|
265899
|
+
numFrames,
|
|
265900
|
+
fps,
|
|
265901
|
+
steps,
|
|
265902
|
+
guidance,
|
|
265903
|
+
negativePrompt,
|
|
265904
|
+
seed: args.seed,
|
|
265905
|
+
hfToken: hfTokenOverride,
|
|
265906
|
+
autoAcceptLicense,
|
|
265907
|
+
start: args.start,
|
|
265908
|
+
python: args.args["python"]
|
|
265909
|
+
});
|
|
265910
|
+
} finally {
|
|
265911
|
+
await lease?.release();
|
|
265912
|
+
this._brokerGpuIndex = null;
|
|
265913
|
+
}
|
|
265482
265914
|
}
|
|
265483
265915
|
let nativeAudio = preset.nativeAudioVideo === true;
|
|
265484
265916
|
let audioPath;
|
|
@@ -265670,6 +266102,17 @@ ${llmAnnotation}` : result.llmContent;
|
|
|
265670
266102
|
}
|
|
265671
266103
|
ensureUnifiedCacheDirs();
|
|
265672
266104
|
this.emitProgress({ stage: "load", message: `Downloading/loading video model ${args.candidate.model}` });
|
|
266105
|
+
const runnerEnv = { ...python.env };
|
|
266106
|
+
if (this._brokerGpuIndex !== null) {
|
|
266107
|
+
if (mediaBrokerGpuIndexIsCompatible(this._brokerGpuIndex, "video", runnerEnv)) {
|
|
266108
|
+
runnerEnv["OMNIUS_GPU_INDEX"] = String(this._brokerGpuIndex);
|
|
266109
|
+
} else {
|
|
266110
|
+
this.emitProgress({
|
|
266111
|
+
stage: "setup",
|
|
266112
|
+
message: `Broker selected CUDA GPU ${this._brokerGpuIndex}, but video CUDA filtering excluded it; using CUDA_VISIBLE_DEVICES=${runnerEnv["CUDA_VISIBLE_DEVICES"] ?? "default"}`
|
|
266113
|
+
});
|
|
266114
|
+
}
|
|
266115
|
+
}
|
|
265673
266116
|
const result = await runProcess4(python.command, [
|
|
265674
266117
|
runner,
|
|
265675
266118
|
"--model",
|
|
@@ -265685,7 +266128,7 @@ ${llmAnnotation}` : result.llmContent;
|
|
|
265685
266128
|
], {
|
|
265686
266129
|
cwd: this.cwd,
|
|
265687
266130
|
timeoutMs: 18e5,
|
|
265688
|
-
env:
|
|
266131
|
+
env: runnerEnv,
|
|
265689
266132
|
progressLabel: `Downloading/loading ${args.candidate.model}`,
|
|
265690
266133
|
onProgress: (event) => this.emitProgress(event)
|
|
265691
266134
|
});
|
|
@@ -568924,6 +569367,78 @@ var init_spinner = __esm({
|
|
|
568924
569367
|
}
|
|
568925
569368
|
});
|
|
568926
569369
|
|
|
569370
|
+
// packages/cli/src/tui/generative-progress.ts
|
|
569371
|
+
function generationKindForToolName(toolName) {
|
|
569372
|
+
if (toolName === "generate_image") return "image";
|
|
569373
|
+
if (toolName === "generate_audio") return "audio";
|
|
569374
|
+
if (toolName === "generate_video") return "video";
|
|
569375
|
+
if (toolName === "generate_tts" || toolName === "create_audio_file") return "tts";
|
|
569376
|
+
return null;
|
|
569377
|
+
}
|
|
569378
|
+
function formatGenerativeProgress(kind, event, options2 = {}) {
|
|
569379
|
+
const width = Math.max(8, Math.min(32, options2.width ?? (options2.surface === "telegram" ? 12 : 20)));
|
|
569380
|
+
const label = kindLabel(kind);
|
|
569381
|
+
const stage = stageLabel(event.stage);
|
|
569382
|
+
const pct = finitePercent(event.percent);
|
|
569383
|
+
const bytes = formatProgressBytes(event);
|
|
569384
|
+
const elapsed = formatElapsed(event.elapsedMs);
|
|
569385
|
+
const message2 = compactProgressMessage(event.message);
|
|
569386
|
+
if (typeof pct === "number") {
|
|
569387
|
+
const filled = Math.max(0, Math.min(width, Math.round(pct / 100 * width)));
|
|
569388
|
+
const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
569389
|
+
return `${label} ${stage}: [${bar}] ${pct}% ${message2}${bytes}${elapsed}`;
|
|
569390
|
+
}
|
|
569391
|
+
return `${label} ${stage}: ${message2}${bytes}${elapsed}`;
|
|
569392
|
+
}
|
|
569393
|
+
function kindLabel(kind) {
|
|
569394
|
+
if (kind === "tts") return "TTS";
|
|
569395
|
+
return kind.slice(0, 1).toUpperCase() + kind.slice(1);
|
|
569396
|
+
}
|
|
569397
|
+
function stageLabel(stage) {
|
|
569398
|
+
const normalized = String(stage || "process").trim().toLowerCase();
|
|
569399
|
+
if (normalized === "setup") return "setup";
|
|
569400
|
+
if (normalized === "download") return "download";
|
|
569401
|
+
if (normalized === "load") return "load";
|
|
569402
|
+
if (normalized === "generate") return "infer";
|
|
569403
|
+
if (normalized === "save") return "save";
|
|
569404
|
+
if (normalized === "thumbnail") return "thumbnail";
|
|
569405
|
+
if (normalized === "hf_token_required") return "auth";
|
|
569406
|
+
return "process";
|
|
569407
|
+
}
|
|
569408
|
+
function finitePercent(value2) {
|
|
569409
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return void 0;
|
|
569410
|
+
return Math.max(0, Math.min(100, Math.round(value2)));
|
|
569411
|
+
}
|
|
569412
|
+
function formatProgressBytes(event) {
|
|
569413
|
+
if (typeof event.totalBytes !== "number" || !Number.isFinite(event.totalBytes) || event.totalBytes <= 0) {
|
|
569414
|
+
return "";
|
|
569415
|
+
}
|
|
569416
|
+
const downloaded = typeof event.downloadedBytes === "number" && Number.isFinite(event.downloadedBytes) ? Math.max(0, event.downloadedBytes) : 0;
|
|
569417
|
+
return ` (${formatBytes3(downloaded)} / ${formatBytes3(event.totalBytes)})`;
|
|
569418
|
+
}
|
|
569419
|
+
function formatElapsed(elapsedMs2) {
|
|
569420
|
+
if (typeof elapsedMs2 !== "number" || !Number.isFinite(elapsedMs2) || elapsedMs2 <= 1500) return "";
|
|
569421
|
+
return ` ${Math.round(elapsedMs2 / 1e3)}s`;
|
|
569422
|
+
}
|
|
569423
|
+
function compactProgressMessage(message2) {
|
|
569424
|
+
return String(message2 || "working").replace(/\s+/g, " ").trim().slice(0, 220);
|
|
569425
|
+
}
|
|
569426
|
+
function formatBytes3(value2) {
|
|
569427
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
569428
|
+
let amount = Math.max(0, value2);
|
|
569429
|
+
let idx = 0;
|
|
569430
|
+
while (amount >= 1024 && idx < units.length - 1) {
|
|
569431
|
+
amount /= 1024;
|
|
569432
|
+
idx++;
|
|
569433
|
+
}
|
|
569434
|
+
return idx === 0 ? `${Math.round(amount)}B` : `${amount.toFixed(1)}${units[idx]}`;
|
|
569435
|
+
}
|
|
569436
|
+
var init_generative_progress = __esm({
|
|
569437
|
+
"packages/cli/src/tui/generative-progress.ts"() {
|
|
569438
|
+
"use strict";
|
|
569439
|
+
}
|
|
569440
|
+
});
|
|
569441
|
+
|
|
568927
569442
|
// packages/cli/src/api/py-embed.ts
|
|
568928
569443
|
var py_embed_exports = {};
|
|
568929
569444
|
__export(py_embed_exports, {
|
|
@@ -575515,7 +576030,7 @@ async function fetchOllamaModels(baseUrl) {
|
|
|
575515
576030
|
const family = m2.details?.family;
|
|
575516
576031
|
return {
|
|
575517
576032
|
name: m2.name,
|
|
575518
|
-
size:
|
|
576033
|
+
size: formatBytes4(m2.size),
|
|
575519
576034
|
sizeBytes: m2.size,
|
|
575520
576035
|
modified: formatRelativeTime(m2.modified_at),
|
|
575521
576036
|
parameterSize: m2.details?.parameter_size,
|
|
@@ -575961,7 +576476,7 @@ async function queryModelCapabilities(baseUrl, modelName) {
|
|
|
575961
576476
|
return caps;
|
|
575962
576477
|
}
|
|
575963
576478
|
}
|
|
575964
|
-
function
|
|
576479
|
+
function formatBytes4(bytes) {
|
|
575965
576480
|
if (bytes < 1024) return `${bytes} B`;
|
|
575966
576481
|
const units = ["KB", "MB", "GB", "TB"];
|
|
575967
576482
|
let size = bytes;
|
|
@@ -595166,7 +595681,7 @@ function formatWorkspaceExplorer(result) {
|
|
|
595166
595681
|
const width = Math.max(12, ...result.entries.map((entry) => entry.path.length));
|
|
595167
595682
|
for (const entry of result.entries) {
|
|
595168
595683
|
lines.push(
|
|
595169
|
-
` ${entry.path.padEnd(Math.min(width, 70)).slice(0, 70)} ${entry.kind.padEnd(6)} ${
|
|
595684
|
+
` ${entry.path.padEnd(Math.min(width, 70)).slice(0, 70)} ${entry.kind.padEnd(6)} ${formatBytes5(entry.sizeBytes).padStart(8)}`
|
|
595170
595685
|
);
|
|
595171
595686
|
}
|
|
595172
595687
|
lines.push("");
|
|
@@ -595188,7 +595703,7 @@ function previewWorkspaceFile(root, relPath, options2 = {}) {
|
|
|
595188
595703
|
return [
|
|
595189
595704
|
"",
|
|
595190
595705
|
` File Preview: ${relPath}`,
|
|
595191
|
-
` Size: ${
|
|
595706
|
+
` Size: ${formatBytes5(st.size)} (too large for inline preview)`,
|
|
595192
595707
|
""
|
|
595193
595708
|
].join("\n");
|
|
595194
595709
|
}
|
|
@@ -595199,7 +595714,7 @@ function previewWorkspaceFile(root, relPath, options2 = {}) {
|
|
|
595199
595714
|
return [
|
|
595200
595715
|
"",
|
|
595201
595716
|
` File Preview: ${relPath}`,
|
|
595202
|
-
` Size: ${
|
|
595717
|
+
` Size: ${formatBytes5(st.size)} Lines: ${rawLines.length}${rawLines.length > maxLines ? " (truncated)" : ""}`,
|
|
595203
595718
|
"",
|
|
595204
595719
|
...visible.map((line, idx) => ` ${String(idx + 1).padStart(gutter)} | ${line}`),
|
|
595205
595720
|
""
|
|
@@ -595230,7 +595745,7 @@ function scoreWorkspaceFile(entry, query) {
|
|
|
595230
595745
|
}
|
|
595231
595746
|
return score;
|
|
595232
595747
|
}
|
|
595233
|
-
function
|
|
595748
|
+
function formatBytes5(bytes) {
|
|
595234
595749
|
if (bytes < 1024) return `${bytes} B`;
|
|
595235
595750
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
595236
595751
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
@@ -600895,7 +601410,7 @@ function describeTaskComplete(summary, completed, personality = 2, _stark = fals
|
|
|
600895
601410
|
}
|
|
600896
601411
|
return `Task completed, but no summary was generated to describe the outcome`;
|
|
600897
601412
|
}
|
|
600898
|
-
function
|
|
601413
|
+
function formatBytes6(bytes) {
|
|
600899
601414
|
if (bytes < 1024) return `${bytes}B`;
|
|
600900
601415
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}KB`;
|
|
600901
601416
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
@@ -603605,7 +604120,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
603605
604120
|
const pct = Math.round(received / contentLength * 100);
|
|
603606
604121
|
if (pct === 25 || pct === 50 || pct === 75 || pct === 100) {
|
|
603607
604122
|
renderInfo(
|
|
603608
|
-
` ${pct}% (${
|
|
604123
|
+
` ${pct}% (${formatBytes6(received)} / ${formatBytes6(contentLength)})`
|
|
603609
604124
|
);
|
|
603610
604125
|
}
|
|
603611
604126
|
}
|
|
@@ -603613,7 +604128,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`
|
|
|
603613
604128
|
const fullBuffer = Buffer.concat(chunks);
|
|
603614
604129
|
writeFileSync54(onnxPath, fullBuffer);
|
|
603615
604130
|
renderInfo(
|
|
603616
|
-
`${model.label} model downloaded (${
|
|
604131
|
+
`${model.label} model downloaded (${formatBytes6(fullBuffer.length)}).`
|
|
603617
604132
|
);
|
|
603618
604133
|
}
|
|
603619
604134
|
}
|
|
@@ -611742,15 +612257,7 @@ async function handleImageCommand(ctx3, arg, hasLocal) {
|
|
|
611742
612257
|
return "handled";
|
|
611743
612258
|
}
|
|
611744
612259
|
function formatImageGenerationProgress(event) {
|
|
611745
|
-
|
|
611746
|
-
const elapsed = event.elapsedMs && event.elapsedMs > 1500 ? ` ${Math.round(event.elapsedMs / 1e3)}s` : "";
|
|
611747
|
-
if (typeof pct === "number") {
|
|
611748
|
-
const width = 20;
|
|
611749
|
-
const filled = Math.max(0, Math.min(width, Math.round(pct / 100 * width)));
|
|
611750
|
-
const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
611751
|
-
return `Image ${event.stage}: [${bar}] ${pct}% ${event.message}${elapsed}`;
|
|
611752
|
-
}
|
|
611753
|
-
return `Image ${event.stage}: ${event.message}${elapsed}`;
|
|
612260
|
+
return formatGenerativeProgress("image", event);
|
|
611754
612261
|
}
|
|
611755
612262
|
function rateVideoPresetForHardware(preset, specs) {
|
|
611756
612263
|
const min = preset.minVramGB;
|
|
@@ -612030,15 +612537,7 @@ async function handleVideoCommand(ctx3, arg, hasLocal) {
|
|
|
612030
612537
|
return "handled";
|
|
612031
612538
|
}
|
|
612032
612539
|
function formatVideoGenerationProgress(event) {
|
|
612033
|
-
|
|
612034
|
-
const elapsed = event.elapsedMs && event.elapsedMs > 1500 ? ` ${Math.round(event.elapsedMs / 1e3)}s` : "";
|
|
612035
|
-
if (typeof pct === "number") {
|
|
612036
|
-
const width = 20;
|
|
612037
|
-
const filled = Math.max(0, Math.min(width, Math.round(pct / 100 * width)));
|
|
612038
|
-
const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
612039
|
-
return `Video ${event.stage}: [${bar}] ${pct}% ${event.message}${elapsed}`;
|
|
612040
|
-
}
|
|
612041
|
-
return `Video ${event.stage}: ${event.message}${elapsed}`;
|
|
612540
|
+
return formatGenerativeProgress("video", event);
|
|
612042
612541
|
}
|
|
612043
612542
|
function activeAudioModel(settings, kind) {
|
|
612044
612543
|
return kind === "music" ? settings.musicModel : settings.soundModel;
|
|
@@ -612346,16 +612845,7 @@ async function handleAudioGenerationCommand(ctx3, arg, hasLocal, kind) {
|
|
|
612346
612845
|
return "handled";
|
|
612347
612846
|
}
|
|
612348
612847
|
function formatAudioGenerationProgress(event) {
|
|
612349
|
-
|
|
612350
|
-
const elapsed = event.elapsedMs && event.elapsedMs > 1500 ? ` ${Math.round(event.elapsedMs / 1e3)}s` : "";
|
|
612351
|
-
const bytes = typeof event.totalBytes === "number" && event.totalBytes > 0 ? ` (${formatFileSize(event.downloadedBytes ?? 0)} / ${formatFileSize(event.totalBytes)})` : "";
|
|
612352
|
-
if (typeof pct === "number") {
|
|
612353
|
-
const width = 20;
|
|
612354
|
-
const filled = Math.max(0, Math.min(width, Math.round(pct / 100 * width)));
|
|
612355
|
-
const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
612356
|
-
return `Audio ${event.stage}: [${bar}] ${pct}% ${event.message}${bytes}${elapsed}`;
|
|
612357
|
-
}
|
|
612358
|
-
return `Audio ${event.stage}: ${event.message}${bytes}${elapsed}`;
|
|
612848
|
+
return formatGenerativeProgress("audio", event);
|
|
612359
612849
|
}
|
|
612360
612850
|
async function showHelpMenu(ctx3) {
|
|
612361
612851
|
const slashCommands = getSlashHelpEntries();
|
|
@@ -617504,6 +617994,7 @@ var init_commands = __esm({
|
|
|
617504
617994
|
"use strict";
|
|
617505
617995
|
init_model_picker();
|
|
617506
617996
|
init_render();
|
|
617997
|
+
init_generative_progress();
|
|
617507
617998
|
init_command_registry();
|
|
617508
617999
|
init_hf_token_prompt();
|
|
617509
618000
|
init_dist5();
|
|
@@ -626249,6 +626740,10 @@ function scopedTool(base3, root, mode) {
|
|
|
626249
626740
|
if (typeof baseSetExpander === "function") {
|
|
626250
626741
|
wrapper.setPromptExpander = (expander) => baseSetExpander.call(base3, expander);
|
|
626251
626742
|
}
|
|
626743
|
+
const baseSetProgress = base3.setProgressCallback;
|
|
626744
|
+
if (typeof baseSetProgress === "function") {
|
|
626745
|
+
wrapper.setProgressCallback = (handler) => baseSetProgress.call(base3, handler);
|
|
626746
|
+
}
|
|
626252
626747
|
return wrapper;
|
|
626253
626748
|
}
|
|
626254
626749
|
function withTelegramAutoAttachmentNotice(result, artifactCount) {
|
|
@@ -626557,6 +627052,16 @@ var init_telegram_creative_tools = __esm({
|
|
|
626557
627052
|
},
|
|
626558
627053
|
required: []
|
|
626559
627054
|
};
|
|
627055
|
+
progressHandler = null;
|
|
627056
|
+
setProgressCallback(handler) {
|
|
627057
|
+
this.progressHandler = handler;
|
|
627058
|
+
}
|
|
627059
|
+
emitProgress(start2, event) {
|
|
627060
|
+
try {
|
|
627061
|
+
this.progressHandler?.({ ...event, elapsedMs: performance.now() - start2 });
|
|
627062
|
+
} catch {
|
|
627063
|
+
}
|
|
627064
|
+
}
|
|
626560
627065
|
async execute(args) {
|
|
626561
627066
|
const start2 = performance.now();
|
|
626562
627067
|
const text = typeof args["text"] === "string" && args["text"].trim() ? args["text"].trim() : typeof args["input"] === "string" && args["input"].trim() ? args["input"].trim() : typeof args["prompt"] === "string" && args["prompt"].trim() ? args["prompt"].trim() : "";
|
|
@@ -626590,8 +627095,10 @@ var init_telegram_creative_tools = __esm({
|
|
|
626590
627095
|
}
|
|
626591
627096
|
let result;
|
|
626592
627097
|
try {
|
|
627098
|
+
this.emitProgress(start2, { stage: "setup", message: "Preparing scoped TTS audio file" });
|
|
626593
627099
|
await mkdir19(dirname37(guarded.path.abs), { recursive: true });
|
|
626594
627100
|
const tts = new TtsGenerateTool();
|
|
627101
|
+
this.emitProgress(start2, { stage: "load", message: "Starting TTS backend" });
|
|
626595
627102
|
result = await tts.execute({
|
|
626596
627103
|
text,
|
|
626597
627104
|
output: guarded.path.abs,
|
|
@@ -626624,6 +627131,7 @@ ${(result.error || result.output || "").slice(0, 1200)}`,
|
|
|
626624
627131
|
}
|
|
626625
627132
|
rememberCreated(this.root, guarded.path.abs);
|
|
626626
627133
|
const sizeKB = Math.round(statSync43(guarded.path.abs).size / 1024);
|
|
627134
|
+
this.emitProgress(start2, { stage: "save", message: `Saved scoped audio file (${sizeKB}KB)` });
|
|
626627
627135
|
return withTelegramAutoAttachmentNotice({
|
|
626628
627136
|
success: true,
|
|
626629
627137
|
output: `Created audio file: ${guarded.path.abs} (${sizeKB}KB WAV)
|
|
@@ -631246,7 +631754,13 @@ function normalizeTelegramCallbackQuery(update2) {
|
|
|
631246
631754
|
data
|
|
631247
631755
|
};
|
|
631248
631756
|
}
|
|
631249
|
-
function adaptTool5(tool, todoSessionId) {
|
|
631757
|
+
function adaptTool5(tool, todoSessionId, progress) {
|
|
631758
|
+
const progressTool = tool;
|
|
631759
|
+
if (generationKindForToolName(tool.name) && typeof progressTool.setProgressCallback === "function") {
|
|
631760
|
+
progressTool.setProgressCallback((event) => {
|
|
631761
|
+
progress?.onProgress(tool.name, event);
|
|
631762
|
+
});
|
|
631763
|
+
}
|
|
631250
631764
|
return {
|
|
631251
631765
|
name: tool.name,
|
|
631252
631766
|
description: tool.description,
|
|
@@ -631258,7 +631772,15 @@ function adaptTool5(tool, todoSessionId) {
|
|
|
631258
631772
|
}
|
|
631259
631773
|
try {
|
|
631260
631774
|
const result = await tool.execute(args);
|
|
631775
|
+
progress?.complete(tool.name, result);
|
|
631261
631776
|
return { success: result.success, output: result.output, error: result.error, llmContent: result.llmContent };
|
|
631777
|
+
} catch (err) {
|
|
631778
|
+
progress?.complete(tool.name, {
|
|
631779
|
+
success: false,
|
|
631780
|
+
output: "",
|
|
631781
|
+
error: err instanceof Error ? err.message : String(err)
|
|
631782
|
+
});
|
|
631783
|
+
throw err;
|
|
631262
631784
|
} finally {
|
|
631263
631785
|
if (todoSessionId && (tool.name === "todo_write" || tool.name === "todo_read")) {
|
|
631264
631786
|
setTodoSessionId(previousTodoSession);
|
|
@@ -631429,6 +631951,7 @@ var init_telegram_bridge = __esm({
|
|
|
631429
631951
|
init_scoped_personality();
|
|
631430
631952
|
init_voice_soul();
|
|
631431
631953
|
init_telegram_creative_tools();
|
|
631954
|
+
init_generative_progress();
|
|
631432
631955
|
init_omnius_directory();
|
|
631433
631956
|
init_stimulation();
|
|
631434
631957
|
init_pid_controller();
|
|
@@ -637910,6 +638433,91 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
637910
638433
|
async sendChatAction(chatId, action) {
|
|
637911
638434
|
await this.apiCall("sendChatAction", { chat_id: chatId, action });
|
|
637912
638435
|
}
|
|
638436
|
+
createTelegramGenerativeProgressBridge(chatId, msg) {
|
|
638437
|
+
if (chatId === void 0) return void 0;
|
|
638438
|
+
const states = /* @__PURE__ */ new Map();
|
|
638439
|
+
const stateFor = (toolName) => {
|
|
638440
|
+
let state = states.get(toolName);
|
|
638441
|
+
if (!state) {
|
|
638442
|
+
state = {
|
|
638443
|
+
messageId: null,
|
|
638444
|
+
pump: null,
|
|
638445
|
+
queuedHtml: null,
|
|
638446
|
+
lastRenderedAt: 0
|
|
638447
|
+
};
|
|
638448
|
+
states.set(toolName, state);
|
|
638449
|
+
}
|
|
638450
|
+
return state;
|
|
638451
|
+
};
|
|
638452
|
+
const kindTitle = (toolName) => {
|
|
638453
|
+
const kind = generationKindForToolName(toolName);
|
|
638454
|
+
if (!kind) return "Generation";
|
|
638455
|
+
if (kind === "tts") return "TTS audio";
|
|
638456
|
+
return `${kind.slice(0, 1).toUpperCase()}${kind.slice(1)}`;
|
|
638457
|
+
};
|
|
638458
|
+
const enqueue = (state, html) => {
|
|
638459
|
+
state.queuedHtml = html;
|
|
638460
|
+
if (state.pump) return;
|
|
638461
|
+
state.pump = (async () => {
|
|
638462
|
+
while (state.queuedHtml) {
|
|
638463
|
+
const nextHtml = state.queuedHtml;
|
|
638464
|
+
state.queuedHtml = null;
|
|
638465
|
+
if (state.messageId === null) {
|
|
638466
|
+
const messageId = await this.sendLiveMessage(chatId, nextHtml, msg?.messageId);
|
|
638467
|
+
if (!messageId) return;
|
|
638468
|
+
state.messageId = messageId;
|
|
638469
|
+
} else {
|
|
638470
|
+
await this.editLiveMessage(chatId, state.messageId, nextHtml);
|
|
638471
|
+
}
|
|
638472
|
+
}
|
|
638473
|
+
})().catch(() => {
|
|
638474
|
+
}).finally(() => {
|
|
638475
|
+
state.pump = null;
|
|
638476
|
+
if (state.queuedHtml) enqueue(state, state.queuedHtml);
|
|
638477
|
+
});
|
|
638478
|
+
};
|
|
638479
|
+
const progressHtml = (toolName, event) => {
|
|
638480
|
+
const kind = generationKindForToolName(toolName);
|
|
638481
|
+
if (!kind) return null;
|
|
638482
|
+
const rendered = redactTelegramLocalPaths(formatGenerativeProgress(kind, event, { surface: "telegram" }));
|
|
638483
|
+
return `<b>${escapeTelegramHTML(kindTitle(toolName))} generation</b>
|
|
638484
|
+
<code>${escapeTelegramHTML(rendered)}</code>`;
|
|
638485
|
+
};
|
|
638486
|
+
const completeHtml = (toolName, result) => {
|
|
638487
|
+
if (!generationKindForToolName(toolName)) return null;
|
|
638488
|
+
if (result.success) {
|
|
638489
|
+
return `<b>${escapeTelegramHTML(kindTitle(toolName))} generation complete</b>`;
|
|
638490
|
+
}
|
|
638491
|
+
const reason = redactTelegramLocalPaths((result.error || result.output || "Generation failed").slice(0, 900));
|
|
638492
|
+
return `<b>${escapeTelegramHTML(kindTitle(toolName))} generation failed</b>
|
|
638493
|
+
<code>${escapeTelegramHTML(reason)}</code>`;
|
|
638494
|
+
};
|
|
638495
|
+
return {
|
|
638496
|
+
onProgress: (toolName, event) => {
|
|
638497
|
+
const html = progressHtml(toolName, event);
|
|
638498
|
+
if (!html) return;
|
|
638499
|
+
const state = stateFor(toolName);
|
|
638500
|
+
const now = Date.now();
|
|
638501
|
+
const stage = String(event.stage || "process");
|
|
638502
|
+
const percent = typeof event.percent === "number" && Number.isFinite(event.percent) ? Math.round(event.percent) : void 0;
|
|
638503
|
+
const terminalStage = stage === "save" || stage === "thumbnail" || stage === "hf_token_required";
|
|
638504
|
+
const shouldRender = state.lastRenderedAt === 0 || stage !== state.lastStage || typeof percent === "number" && (state.lastPercent === void 0 || Math.abs(percent - state.lastPercent) >= 5) || now - state.lastRenderedAt >= 3500 || terminalStage;
|
|
638505
|
+
if (!shouldRender) return;
|
|
638506
|
+
state.lastRenderedAt = now;
|
|
638507
|
+
state.lastStage = stage;
|
|
638508
|
+
state.lastPercent = percent;
|
|
638509
|
+
enqueue(state, html);
|
|
638510
|
+
},
|
|
638511
|
+
complete: (toolName, result) => {
|
|
638512
|
+
if (!generationKindForToolName(toolName)) return;
|
|
638513
|
+
const state = states.get(toolName);
|
|
638514
|
+
if (!state && result.success) return;
|
|
638515
|
+
const html = completeHtml(toolName, result);
|
|
638516
|
+
if (!html) return;
|
|
638517
|
+
enqueue(state ?? stateFor(toolName), html);
|
|
638518
|
+
}
|
|
638519
|
+
};
|
|
638520
|
+
}
|
|
637913
638521
|
// ── Live message streaming (editMessageText pattern) ─────────────────
|
|
637914
638522
|
/**
|
|
637915
638523
|
* Send a placeholder message that will be progressively edited with
|
|
@@ -639942,6 +640550,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
639942
640550
|
const imageDefaults = this.imageGenerationDefaultsForRepo(repoRoot);
|
|
639943
640551
|
const audioDefaults = this.audioGenerationDefaultsForRepo(repoRoot);
|
|
639944
640552
|
const videoDefaults = this.videoGenerationDefaultsForRepo(repoRoot);
|
|
640553
|
+
const generativeProgress = this.createTelegramGenerativeProgressBridge(chatId, msg);
|
|
639945
640554
|
const taskComplete = {
|
|
639946
640555
|
name: "task_complete",
|
|
639947
640556
|
description: "Internal completion signal for Telegram runs. Put the actual user-facing reply in assistant text before calling this. Use summary 'no_reply' only to silently skip responding; never write that sentinel as assistant text.",
|
|
@@ -640088,7 +640697,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
640088
640697
|
}
|
|
640089
640698
|
}
|
|
640090
640699
|
}
|
|
640091
|
-
const unfilteredAdaptedTools = allTools.map((tool) => adaptTool5(tool, todoSessionId));
|
|
640700
|
+
const unfilteredAdaptedTools = allTools.map((tool) => adaptTool5(tool, todoSessionId, generativeProgress));
|
|
640092
640701
|
let adaptedTools = unfilteredAdaptedTools;
|
|
640093
640702
|
adaptedTools = applyToolPolicy(adaptedTools, context2, this.toolPolicyConfig);
|
|
640094
640703
|
if (context2 === "telegram-admin-dm") {
|
|
@@ -640103,9 +640712,9 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
640103
640712
|
imageDefaults,
|
|
640104
640713
|
audioDefaults,
|
|
640105
640714
|
videoDefaults
|
|
640106
|
-
).map((tool) => adaptTool5(tool, todoSessionId));
|
|
640715
|
+
).map((tool) => adaptTool5(tool, todoSessionId, generativeProgress));
|
|
640107
640716
|
adaptedTools.push(...creativeTools);
|
|
640108
|
-
adaptedTools.push(adaptTool5(this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg), todoSessionId));
|
|
640717
|
+
adaptedTools.push(adaptTool5(this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg), todoSessionId, generativeProgress));
|
|
640109
640718
|
adaptedTools = this.filterNonAdminTelegramTools(adaptedTools);
|
|
640110
640719
|
adaptedTools = adaptedTools.map((tool) => this.applyTelegramPublicQuota(tool, context2, chatId, msg));
|
|
640111
640720
|
}
|
|
@@ -642850,7 +643459,7 @@ function buildShellLiveBlockLines(state, width) {
|
|
|
642850
643459
|
const w = Math.max(36, width);
|
|
642851
643460
|
const inner = Math.max(1, w - 4);
|
|
642852
643461
|
const elapsed = Math.max(0, Date.now() - state.startedAt);
|
|
642853
|
-
const status = state.status === "running" ? `live ${
|
|
643462
|
+
const status = state.status === "running" ? `live ${formatElapsed2(elapsed)}` : state.status;
|
|
642854
643463
|
const title = ` Shell ${status} `;
|
|
642855
643464
|
const top = `╭${fitWithFill(`─${title}`, w - 2, "─")}╮`;
|
|
642856
643465
|
const bottom = `╰${"─".repeat(w - 2)}╯`;
|
|
@@ -642895,7 +643504,7 @@ function fitWithFill(value2, width, fill) {
|
|
|
642895
643504
|
if (chars.length > width) return chars.slice(0, width).join("");
|
|
642896
643505
|
return value2 + fill.repeat(width - chars.length);
|
|
642897
643506
|
}
|
|
642898
|
-
function
|
|
643507
|
+
function formatElapsed2(ms) {
|
|
642899
643508
|
const seconds = Math.floor(ms / 1e3);
|
|
642900
643509
|
if (seconds < 60) return `${seconds}s`;
|
|
642901
643510
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -668394,6 +669003,12 @@ function getVersion4() {
|
|
|
668394
669003
|
return "0.0.0";
|
|
668395
669004
|
}
|
|
668396
669005
|
function adaptTool6(tool) {
|
|
669006
|
+
const progressTool = tool;
|
|
669007
|
+
if (generationKindForToolName(tool.name) && typeof progressTool.setProgressCallback === "function") {
|
|
669008
|
+
progressTool.setProgressCallback((event) => {
|
|
669009
|
+
_generativeProgressSink?.(tool.name, event);
|
|
669010
|
+
});
|
|
669011
|
+
}
|
|
668397
669012
|
return {
|
|
668398
669013
|
name: tool.name,
|
|
668399
669014
|
description: tool.description,
|
|
@@ -668704,6 +669319,17 @@ function audioGenerationDefaultsForRepo(repoRoot) {
|
|
|
668704
669319
|
function createConfiguredAudioGenerateTool(repoRoot) {
|
|
668705
669320
|
return new AudioGenerateTool(repoRoot, audioGenerationDefaultsForRepo(repoRoot));
|
|
668706
669321
|
}
|
|
669322
|
+
function videoGenerationDefaultsForRepo(repoRoot) {
|
|
669323
|
+
const settings = resolveSettings(repoRoot);
|
|
669324
|
+
return {
|
|
669325
|
+
model: typeof settings.videoModel === "string" && settings.videoModel.trim() ? settings.videoModel : void 0,
|
|
669326
|
+
backend: settings.videoBackend,
|
|
669327
|
+
defaultKind: settings.videoKind
|
|
669328
|
+
};
|
|
669329
|
+
}
|
|
669330
|
+
function createConfiguredVideoGenerateTool(repoRoot) {
|
|
669331
|
+
return new VideoGenerateTool(repoRoot, videoGenerationDefaultsForRepo(repoRoot));
|
|
669332
|
+
}
|
|
668707
669333
|
function buildSubAgentTools(repoRoot, config) {
|
|
668708
669334
|
return [
|
|
668709
669335
|
// File + search
|
|
@@ -668802,6 +669428,7 @@ function buildSubAgentTools(repoRoot, config) {
|
|
|
668802
669428
|
new CameraCaptureTool(),
|
|
668803
669429
|
createConfiguredImageGenerateTool(repoRoot, config.backendUrl),
|
|
668804
669430
|
createConfiguredAudioGenerateTool(repoRoot),
|
|
669431
|
+
createConfiguredVideoGenerateTool(repoRoot),
|
|
668805
669432
|
// Hardware sensors + radios (read-only scans)
|
|
668806
669433
|
new GpsLocationTool(),
|
|
668807
669434
|
new WifiControlTool(),
|
|
@@ -668889,6 +669516,8 @@ function buildTools(repoRoot, config, contextWindowSize, modelTier) {
|
|
|
668889
669516
|
createConfiguredImageGenerateTool(repoRoot, config.backendUrl),
|
|
668890
669517
|
// Sound/music Generation — local Diffusers/AudioCraft/Stable Audio paths
|
|
668891
669518
|
createConfiguredAudioGenerateTool(repoRoot),
|
|
669519
|
+
// Video Generation — local Diffusers/ComfyUI video pipelines
|
|
669520
|
+
createConfiguredVideoGenerateTool(repoRoot),
|
|
668892
669521
|
// Structured file reading (CSV, JSON, Markdown, binary detection)
|
|
668893
669522
|
new StructuredReadTool(repoRoot),
|
|
668894
669523
|
// Vision tools (Moondream — desktop awareness + point-and-click)
|
|
@@ -669551,16 +670180,6 @@ async function renderAsciiPreviewForImage(imagePath, displayPath, title, writer)
|
|
|
669551
670180
|
return "";
|
|
669552
670181
|
}
|
|
669553
670182
|
}
|
|
669554
|
-
function formatImageGenerationProgress2(event) {
|
|
669555
|
-
const elapsed = event.elapsedMs && event.elapsedMs > 1500 ? ` ${Math.round(event.elapsedMs / 1e3)}s` : "";
|
|
669556
|
-
if (typeof event.percent === "number") {
|
|
669557
|
-
const width = 20;
|
|
669558
|
-
const filled = Math.max(0, Math.min(width, Math.round(event.percent / 100 * width)));
|
|
669559
|
-
const bar = `${"#".repeat(filled)}${"-".repeat(width - filled)}`;
|
|
669560
|
-
return `Image ${event.stage}: [${bar}] ${event.percent}% ${event.message}${elapsed}`;
|
|
669561
|
-
}
|
|
669562
|
-
return `Image ${event.stage}: ${event.message}${elapsed}`;
|
|
669563
|
-
}
|
|
669564
670183
|
async function renderAsciiPreviewForToolResult(toolName, output, repoRoot, writer) {
|
|
669565
670184
|
if (!output) return;
|
|
669566
670185
|
try {
|
|
@@ -670701,14 +671320,11 @@ ${entry.fullContent}`
|
|
|
670701
671320
|
fn();
|
|
670702
671321
|
}
|
|
670703
671322
|
};
|
|
670704
|
-
|
|
670705
|
-
const
|
|
670706
|
-
if (
|
|
670707
|
-
|
|
670708
|
-
|
|
670709
|
-
});
|
|
670710
|
-
}
|
|
670711
|
-
}
|
|
671323
|
+
_generativeProgressSink = (toolName, event) => {
|
|
671324
|
+
const kind = generationKindForToolName(toolName);
|
|
671325
|
+
if (!kind) return;
|
|
671326
|
+
contentWrite(() => renderInfo(formatGenerativeProgress(kind, event, { surface: "tui" })));
|
|
671327
|
+
};
|
|
670712
671328
|
let liveShellBlock = null;
|
|
670713
671329
|
const scheduleLiveShellRepaint = () => {
|
|
670714
671330
|
if (!liveShellBlock || liveShellBlock.repaintTimer || !statusBar?.isActive)
|
|
@@ -677484,7 +678100,7 @@ Rules:
|
|
|
677484
678100
|
process.exit(1);
|
|
677485
678101
|
}
|
|
677486
678102
|
}
|
|
677487
|
-
var NEXUS_DIRECTORY_ORIGIN3, NEXUS_AGENT_DIRECTORY_URL, NEXUS_SPONSORS_URL3, _interactiveSessionActive, _interactiveSessionReason, _voiceChatSession2, taskManager, _apiCallbacks, _shellToolRef, _replToolRef, _fullSubAgentToolRef, _agentToolRef, _sendMessageToolRef, _agentLifecycleMgr, _activeRunnerRef, _parentRunnerForArchive, _wireSubAgentCallbacks, _wireAgentToolCallbacks, _wireSubAgentToolCallbacks, _autoUpdatedThisSession, _mcpManager, _pluginManager, _mcpTools, SELF_IMPROVE_INTERVAL, _tasksSinceImprove;
|
|
678103
|
+
var NEXUS_DIRECTORY_ORIGIN3, NEXUS_AGENT_DIRECTORY_URL, NEXUS_SPONSORS_URL3, _generativeProgressSink, _interactiveSessionActive, _interactiveSessionReason, _voiceChatSession2, taskManager, _apiCallbacks, _shellToolRef, _replToolRef, _fullSubAgentToolRef, _agentToolRef, _sendMessageToolRef, _agentLifecycleMgr, _activeRunnerRef, _parentRunnerForArchive, _wireSubAgentCallbacks, _wireAgentToolCallbacks, _wireSubAgentToolCallbacks, _autoUpdatedThisSession, _mcpManager, _pluginManager, _mcpTools, SELF_IMPROVE_INTERVAL, _tasksSinceImprove;
|
|
677488
678104
|
var init_interactive = __esm({
|
|
677489
678105
|
"packages/cli/src/tui/interactive.ts"() {
|
|
677490
678106
|
"use strict";
|
|
@@ -677493,6 +678109,7 @@ var init_interactive = __esm({
|
|
|
677493
678109
|
init_dist8();
|
|
677494
678110
|
init_dist8();
|
|
677495
678111
|
init_dist5();
|
|
678112
|
+
init_generative_progress();
|
|
677496
678113
|
init_dist();
|
|
677497
678114
|
init_listen();
|
|
677498
678115
|
init_voice_session();
|
|
@@ -677543,6 +678160,7 @@ var init_interactive = __esm({
|
|
|
677543
678160
|
NEXUS_DIRECTORY_ORIGIN3 = (process.env["OMNIUS_NEXUS_DIRECTORY_ORIGIN"] || process.env["OMNIUS_NEXUS_SIGNALING_SERVER"] || "https://openagents.nexus").replace(/\/+$/, "");
|
|
677544
678161
|
NEXUS_AGENT_DIRECTORY_URL = `${NEXUS_DIRECTORY_ORIGIN3}/api/v1/directory`;
|
|
677545
678162
|
NEXUS_SPONSORS_URL3 = `${NEXUS_DIRECTORY_ORIGIN3}/api/v1/sponsors`;
|
|
678163
|
+
_generativeProgressSink = null;
|
|
677546
678164
|
_interactiveSessionActive = false;
|
|
677547
678165
|
_interactiveSessionReason = "";
|
|
677548
678166
|
_voiceChatSession2 = null;
|