open-agents-ai 0.72.1 → 0.73.1
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 +294 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15097,6 +15097,23 @@ These tools use OS cron (survives process death) and persist state to .oa/ for c
|
|
|
15097
15097
|
Use cron_agent for recurring autonomous tasks, scheduler for simple repeating commands,
|
|
15098
15098
|
reminder for deferred attention, and agenda for strategic focus tracking.
|
|
15099
15099
|
|
|
15100
|
+
## Priority Ingress \u2014 Task Classification & Delegation
|
|
15101
|
+
|
|
15102
|
+
When multiple tasks arrive (Telegram, reminders, updates), classify and route them:
|
|
15103
|
+
- priority_classify: Determine a task's priority (critical/high/moderate/normal/low/salient)
|
|
15104
|
+
priority_classify(message='...', source='external', origin='telegram')
|
|
15105
|
+
Returns: priority, weight, delegable flag, handling policy
|
|
15106
|
+
- priority_delegate: Send normal/low/salient tasks to a sub-agent
|
|
15107
|
+
priority_delegate(task_prompt='...', priority='normal')
|
|
15108
|
+
|
|
15109
|
+
Priority handling policies:
|
|
15110
|
+
CRITICAL (100): Interrupt immediately. Handle now.
|
|
15111
|
+
HIGH (80): Interrupt at turn boundary. Handle next.
|
|
15112
|
+
MODERATE (60): Queue, run after current task.
|
|
15113
|
+
NORMAL (40): Can delegate to sub-agent.
|
|
15114
|
+
LOW (20): Should delegate to sub-agent.
|
|
15115
|
+
SALIENT (5): Note for later, delegate if possible.
|
|
15116
|
+
|
|
15100
15117
|
## Context Efficiency
|
|
15101
15118
|
|
|
15102
15119
|
- Use grep_search to find specific code instead of reading many files
|
|
@@ -31308,6 +31325,30 @@ var init_voice = __esm({
|
|
|
31308
31325
|
}, null, 2));
|
|
31309
31326
|
}
|
|
31310
31327
|
const voiceRequire = createRequire(join38(voiceDir(), "index.js"));
|
|
31328
|
+
const probeOnnx = () => {
|
|
31329
|
+
try {
|
|
31330
|
+
const result = execSync26(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join38(voiceDir(), "node_modules") } });
|
|
31331
|
+
const output = result.toString().trim();
|
|
31332
|
+
if (output === "OK")
|
|
31333
|
+
return true;
|
|
31334
|
+
if (output.startsWith("FAIL:")) {
|
|
31335
|
+
renderWarning(`ONNX runtime probe failed: ${output.slice(5)}`);
|
|
31336
|
+
return false;
|
|
31337
|
+
}
|
|
31338
|
+
return false;
|
|
31339
|
+
} catch (err) {
|
|
31340
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
31341
|
+
if (msg.includes("CPUID") || msg.includes("unknown cpu") || msg.includes("signal")) {
|
|
31342
|
+
renderWarning(`ONNX runtime is not compatible with this CPU (${process.platform}-${arch}).`);
|
|
31343
|
+
}
|
|
31344
|
+
return false;
|
|
31345
|
+
}
|
|
31346
|
+
};
|
|
31347
|
+
const onnxNodeModules = join38(voiceDir(), "node_modules", "onnxruntime-node");
|
|
31348
|
+
const onnxInstalled = existsSync28(onnxNodeModules);
|
|
31349
|
+
if (onnxInstalled && !probeOnnx()) {
|
|
31350
|
+
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
|
|
31351
|
+
}
|
|
31311
31352
|
try {
|
|
31312
31353
|
this.ort = voiceRequire("onnxruntime-node");
|
|
31313
31354
|
} catch {
|
|
@@ -31318,12 +31359,19 @@ var init_voice = __esm({
|
|
|
31318
31359
|
stdio: "pipe",
|
|
31319
31360
|
timeout: 12e4
|
|
31320
31361
|
});
|
|
31321
|
-
this.ort = voiceRequire("onnxruntime-node");
|
|
31322
31362
|
} catch (err) {
|
|
31323
31363
|
const archHint = arch !== "x64" ? ` onnxruntime-node may not have prebuilt binaries for ${process.platform}-${arch}.` : "";
|
|
31324
31364
|
throw new Error(`Failed to install voice dependencies.${archHint} Try manually: cd ${voiceDir()} && npm install
|
|
31325
31365
|
Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
31326
31366
|
}
|
|
31367
|
+
if (!probeOnnx()) {
|
|
31368
|
+
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
|
|
31369
|
+
}
|
|
31370
|
+
try {
|
|
31371
|
+
this.ort = voiceRequire("onnxruntime-node");
|
|
31372
|
+
} catch (err) {
|
|
31373
|
+
throw new Error(`Failed to load ONNX runtime after install. Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
31374
|
+
}
|
|
31327
31375
|
}
|
|
31328
31376
|
try {
|
|
31329
31377
|
const phonemizerMod = voiceRequire("phonemizer");
|
|
@@ -33655,6 +33703,216 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
33655
33703
|
}
|
|
33656
33704
|
});
|
|
33657
33705
|
|
|
33706
|
+
// packages/cli/dist/tui/priority-ingress.js
|
|
33707
|
+
function classifyPriority(prompt, source, origin) {
|
|
33708
|
+
for (const rule of CLASSIFICATION_RULES) {
|
|
33709
|
+
if (rule.sourceType !== "any" && rule.sourceType !== source)
|
|
33710
|
+
continue;
|
|
33711
|
+
if (rule.pattern.test(prompt)) {
|
|
33712
|
+
return { priority: rule.priority, confidence: rule.confidence };
|
|
33713
|
+
}
|
|
33714
|
+
}
|
|
33715
|
+
if (origin === "attention" || origin === "reminder") {
|
|
33716
|
+
return { priority: "moderate", confidence: 0.6 };
|
|
33717
|
+
}
|
|
33718
|
+
if (source === "external" && origin === "telegram") {
|
|
33719
|
+
return { priority: "normal", confidence: 0.65 };
|
|
33720
|
+
}
|
|
33721
|
+
if (origin === "dmn") {
|
|
33722
|
+
return { priority: "low", confidence: 0.7 };
|
|
33723
|
+
}
|
|
33724
|
+
if (origin === "update") {
|
|
33725
|
+
return { priority: "moderate", confidence: 0.85 };
|
|
33726
|
+
}
|
|
33727
|
+
return { priority: "normal", confidence: 0.5 };
|
|
33728
|
+
}
|
|
33729
|
+
var PRIORITY_WEIGHT, PRIORITY_POLICIES, CLASSIFICATION_RULES, PriorityIngressEngine;
|
|
33730
|
+
var init_priority_ingress = __esm({
|
|
33731
|
+
"packages/cli/dist/tui/priority-ingress.js"() {
|
|
33732
|
+
"use strict";
|
|
33733
|
+
PRIORITY_WEIGHT = {
|
|
33734
|
+
critical: 100,
|
|
33735
|
+
high: 80,
|
|
33736
|
+
moderate: 60,
|
|
33737
|
+
normal: 40,
|
|
33738
|
+
low: 20,
|
|
33739
|
+
salient: 5
|
|
33740
|
+
};
|
|
33741
|
+
PRIORITY_POLICIES = {
|
|
33742
|
+
critical: { canInterrupt: true, canDelegate: false, maxWaitMs: 0, notifyAdmin: true },
|
|
33743
|
+
high: { canInterrupt: true, canDelegate: false, maxWaitMs: 0, notifyAdmin: true },
|
|
33744
|
+
moderate: { canInterrupt: false, canDelegate: false, maxWaitMs: 3e4, notifyAdmin: false },
|
|
33745
|
+
normal: { canInterrupt: false, canDelegate: true, maxWaitMs: 6e4, notifyAdmin: false },
|
|
33746
|
+
low: { canInterrupt: false, canDelegate: true, maxWaitMs: 3e5, notifyAdmin: false },
|
|
33747
|
+
salient: { canInterrupt: false, canDelegate: true, maxWaitMs: 9e5, notifyAdmin: false }
|
|
33748
|
+
};
|
|
33749
|
+
CLASSIFICATION_RULES = [
|
|
33750
|
+
// CRITICAL — show-stoppers
|
|
33751
|
+
{ pattern: /\b(security breach|data loss|compromised|urgent.*fix|production down|critical.*failure)\b/i, sourceType: "any", priority: "critical", confidence: 0.95 },
|
|
33752
|
+
{ pattern: /\bCRITICAL\b/, sourceType: "any", priority: "critical", confidence: 0.9 },
|
|
33753
|
+
// HIGH — important interrupts
|
|
33754
|
+
{ pattern: /\b(failing ci|build broken|tests? failing|deployment failed|regression)\b/i, sourceType: "any", priority: "high", confidence: 0.85 },
|
|
33755
|
+
{ pattern: /\b(URGENT|ASAP|immediately|right now)\b/i, sourceType: "external", priority: "high", confidence: 0.8 },
|
|
33756
|
+
// MODERATE — significant but non-interrupt
|
|
33757
|
+
{ pattern: /\b(update available|new version|upgrade)\b/i, sourceType: "any", priority: "moderate", confidence: 0.85 },
|
|
33758
|
+
{ pattern: /\b(admin|owner)\b/i, sourceType: "external", priority: "moderate", confidence: 0.7 },
|
|
33759
|
+
// LOW — background tasks
|
|
33760
|
+
{ pattern: /\b(routine|check|status|health)\b/i, sourceType: "internal", priority: "low", confidence: 0.75 },
|
|
33761
|
+
{ pattern: /\b(FYI|notice|info|heads up)\b/i, sourceType: "any", priority: "salient", confidence: 0.8 }
|
|
33762
|
+
];
|
|
33763
|
+
PriorityIngressEngine = class {
|
|
33764
|
+
queue = [];
|
|
33765
|
+
completedTasks = [];
|
|
33766
|
+
taskCounter = 0;
|
|
33767
|
+
/** Callback: notify admin about high-priority tasks */
|
|
33768
|
+
adminNotify;
|
|
33769
|
+
/** Callback: request attention switch from current task */
|
|
33770
|
+
requestInterrupt;
|
|
33771
|
+
/** Callback: delegate task to sub-agent */
|
|
33772
|
+
delegateToSubAgent;
|
|
33773
|
+
constructor() {
|
|
33774
|
+
}
|
|
33775
|
+
/** Wire callbacks after construction (Telegram/agent may not be ready at construction time) */
|
|
33776
|
+
setAdminNotify(cb) {
|
|
33777
|
+
this.adminNotify = cb;
|
|
33778
|
+
}
|
|
33779
|
+
setInterruptHandler(cb) {
|
|
33780
|
+
this.requestInterrupt = cb;
|
|
33781
|
+
}
|
|
33782
|
+
setDelegationHandler(cb) {
|
|
33783
|
+
this.delegateToSubAgent = cb;
|
|
33784
|
+
}
|
|
33785
|
+
/**
|
|
33786
|
+
* Ingest a new task from any source.
|
|
33787
|
+
* Classifies priority, applies handling policy, and routes accordingly.
|
|
33788
|
+
*/
|
|
33789
|
+
ingest(prompt, source, origin, metadata, overridePriority) {
|
|
33790
|
+
const classification = overridePriority ? { priority: overridePriority, confidence: 1 } : classifyPriority(prompt, source, origin);
|
|
33791
|
+
const policy = PRIORITY_POLICIES[classification.priority];
|
|
33792
|
+
const task = {
|
|
33793
|
+
id: `task-${++this.taskCounter}-${Date.now()}`,
|
|
33794
|
+
source,
|
|
33795
|
+
origin,
|
|
33796
|
+
priority: classification.priority,
|
|
33797
|
+
prompt,
|
|
33798
|
+
metadata,
|
|
33799
|
+
ingressAt: Date.now(),
|
|
33800
|
+
delegable: policy.canDelegate,
|
|
33801
|
+
confidence: classification.confidence,
|
|
33802
|
+
status: "pending"
|
|
33803
|
+
};
|
|
33804
|
+
if (policy.notifyAdmin && this.adminNotify) {
|
|
33805
|
+
const priorityLabel = classification.priority.toUpperCase();
|
|
33806
|
+
const preview = prompt.length > 120 ? prompt.slice(0, 120) + "..." : prompt;
|
|
33807
|
+
this.adminNotify(`[${priorityLabel}] ${origin}: ${preview}`);
|
|
33808
|
+
}
|
|
33809
|
+
if (policy.canInterrupt && this.requestInterrupt) {
|
|
33810
|
+
this.requestInterrupt(task);
|
|
33811
|
+
task.status = "active";
|
|
33812
|
+
} else if (policy.canDelegate && this.delegateToSubAgent) {
|
|
33813
|
+
task.status = "delegated";
|
|
33814
|
+
this.delegateToSubAgent(task).then((summary) => {
|
|
33815
|
+
task.status = "completed";
|
|
33816
|
+
task.completionSummary = summary;
|
|
33817
|
+
this.completedTasks.push(task);
|
|
33818
|
+
}).catch(() => {
|
|
33819
|
+
task.status = "pending";
|
|
33820
|
+
task.priority = "moderate";
|
|
33821
|
+
task.delegable = false;
|
|
33822
|
+
this.queue.push(task);
|
|
33823
|
+
this.sortQueue();
|
|
33824
|
+
});
|
|
33825
|
+
} else {
|
|
33826
|
+
this.queue.push(task);
|
|
33827
|
+
this.sortQueue();
|
|
33828
|
+
}
|
|
33829
|
+
return task;
|
|
33830
|
+
}
|
|
33831
|
+
/**
|
|
33832
|
+
* Get the next task from the priority queue.
|
|
33833
|
+
* Returns null if queue is empty.
|
|
33834
|
+
* Implements weighted scoring: priority_weight + recency_bonus
|
|
33835
|
+
* (REF: Generative Agents scoring — importance + recency)
|
|
33836
|
+
*/
|
|
33837
|
+
dequeue() {
|
|
33838
|
+
if (this.queue.length === 0)
|
|
33839
|
+
return null;
|
|
33840
|
+
const task = this.queue.shift();
|
|
33841
|
+
task.status = "active";
|
|
33842
|
+
return task;
|
|
33843
|
+
}
|
|
33844
|
+
/** Mark a task as completed */
|
|
33845
|
+
complete(taskId, summary) {
|
|
33846
|
+
const idx = this.queue.findIndex((t) => t.id === taskId);
|
|
33847
|
+
if (idx >= 0) {
|
|
33848
|
+
const task = this.queue.splice(idx, 1)[0];
|
|
33849
|
+
task.status = "completed";
|
|
33850
|
+
task.completionSummary = summary;
|
|
33851
|
+
this.completedTasks.push(task);
|
|
33852
|
+
}
|
|
33853
|
+
}
|
|
33854
|
+
/** Mark active task as completed (when we don't track by ID) */
|
|
33855
|
+
completeActive(summary) {
|
|
33856
|
+
this.completedTasks.push({
|
|
33857
|
+
id: `completed-${Date.now()}`,
|
|
33858
|
+
source: "internal",
|
|
33859
|
+
origin: "main",
|
|
33860
|
+
priority: "normal",
|
|
33861
|
+
prompt: "",
|
|
33862
|
+
ingressAt: Date.now(),
|
|
33863
|
+
delegable: false,
|
|
33864
|
+
confidence: 1,
|
|
33865
|
+
status: "completed",
|
|
33866
|
+
completionSummary: summary
|
|
33867
|
+
});
|
|
33868
|
+
}
|
|
33869
|
+
/** Check if there are pending tasks that can interrupt */
|
|
33870
|
+
hasInterruptibleTask() {
|
|
33871
|
+
return this.queue.some((t) => {
|
|
33872
|
+
const policy = PRIORITY_POLICIES[t.priority];
|
|
33873
|
+
return policy.canInterrupt;
|
|
33874
|
+
});
|
|
33875
|
+
}
|
|
33876
|
+
/** Get queue length */
|
|
33877
|
+
get pending() {
|
|
33878
|
+
return this.queue.length;
|
|
33879
|
+
}
|
|
33880
|
+
/** Get stats */
|
|
33881
|
+
getStats() {
|
|
33882
|
+
const byPriority = {
|
|
33883
|
+
critical: 0,
|
|
33884
|
+
high: 0,
|
|
33885
|
+
moderate: 0,
|
|
33886
|
+
normal: 0,
|
|
33887
|
+
low: 0,
|
|
33888
|
+
salient: 0
|
|
33889
|
+
};
|
|
33890
|
+
const bySources = {};
|
|
33891
|
+
for (const t of [...this.queue, ...this.completedTasks]) {
|
|
33892
|
+
byPriority[t.priority]++;
|
|
33893
|
+
bySources[t.origin] = (bySources[t.origin] ?? 0) + 1;
|
|
33894
|
+
}
|
|
33895
|
+
return {
|
|
33896
|
+
pending: this.queue.length,
|
|
33897
|
+
completed: this.completedTasks.length,
|
|
33898
|
+
byPriority,
|
|
33899
|
+
bySources
|
|
33900
|
+
};
|
|
33901
|
+
}
|
|
33902
|
+
/** Sort queue by priority weight (descending), then by recency (FIFO within priority) */
|
|
33903
|
+
sortQueue() {
|
|
33904
|
+
this.queue.sort((a, b) => {
|
|
33905
|
+
const wa = PRIORITY_WEIGHT[a.priority];
|
|
33906
|
+
const wb = PRIORITY_WEIGHT[b.priority];
|
|
33907
|
+
if (wa !== wb)
|
|
33908
|
+
return wb - wa;
|
|
33909
|
+
return a.ingressAt - b.ingressAt;
|
|
33910
|
+
});
|
|
33911
|
+
}
|
|
33912
|
+
};
|
|
33913
|
+
}
|
|
33914
|
+
});
|
|
33915
|
+
|
|
33658
33916
|
// packages/cli/dist/tui/bless-engine.js
|
|
33659
33917
|
function renderBlessStart() {
|
|
33660
33918
|
process.stdout.write(`
|
|
@@ -33683,6 +33941,7 @@ var init_bless_engine = __esm({
|
|
|
33683
33941
|
"use strict";
|
|
33684
33942
|
init_render();
|
|
33685
33943
|
init_dist2();
|
|
33944
|
+
init_priority_ingress();
|
|
33686
33945
|
BlessEngine = class {
|
|
33687
33946
|
config;
|
|
33688
33947
|
repoRoot;
|
|
@@ -33696,6 +33955,8 @@ var init_bless_engine = __esm({
|
|
|
33696
33955
|
};
|
|
33697
33956
|
/** Pending tasks from external sources (telegram, reminders, etc.) */
|
|
33698
33957
|
pendingQueue = [];
|
|
33958
|
+
/** Priority-aware ingress engine */
|
|
33959
|
+
priorityEngine = new PriorityIngressEngine();
|
|
33699
33960
|
constructor(config, repoRoot) {
|
|
33700
33961
|
this.config = config;
|
|
33701
33962
|
this.repoRoot = repoRoot;
|
|
@@ -33739,36 +34000,44 @@ var init_bless_engine = __esm({
|
|
|
33739
34000
|
/** Enqueue a task from an external source (e.g., Telegram) */
|
|
33740
34001
|
enqueueTask(source, prompt, chatId) {
|
|
33741
34002
|
this.pendingQueue.push({ source, prompt, chatId });
|
|
34003
|
+
const taskSource = source === "telegram" || source === "webhook" ? "external" : "internal";
|
|
34004
|
+
this.priorityEngine.ingest(prompt, taskSource, source, chatId != null ? { chatId } : void 0);
|
|
33742
34005
|
}
|
|
33743
|
-
/** Check for pending tasks from any source. Returns next task or null.
|
|
34006
|
+
/** Check for pending tasks from any source. Returns next task or null.
|
|
34007
|
+
* Uses priority-weighted ordering (REF: Nalar arXiv:2601.05109 two-level control).
|
|
34008
|
+
* Priority queue is checked first, then reminders/attention items are ingested. */
|
|
33744
34009
|
async getNextTask() {
|
|
33745
|
-
if (this.pendingQueue.length > 0) {
|
|
33746
|
-
return this.pendingQueue.shift();
|
|
33747
|
-
}
|
|
33748
34010
|
try {
|
|
33749
34011
|
const dueReminders = await getDueReminders(this.repoRoot);
|
|
33750
|
-
const
|
|
33751
|
-
|
|
33752
|
-
const
|
|
33753
|
-
|
|
33754
|
-
source: "reminder",
|
|
33755
|
-
prompt: `URGENT REMINDER: ${r.message}${r.tags?.length ? ` [tags: ${r.tags.join(", ")}]` : ""}. Check the agenda for full context and take appropriate action.`
|
|
33756
|
-
};
|
|
34012
|
+
for (const r of dueReminders.filter((r2) => r2.status === "pending")) {
|
|
34013
|
+
const priority = r.priority === "critical" ? "critical" : r.priority === "high" ? "high" : "moderate";
|
|
34014
|
+
const prompt = `${priority === "critical" ? "URGENT " : ""}REMINDER: ${r.message}${r.tags?.length ? ` [tags: ${r.tags.join(", ")}]` : ""}. Check the agenda for full context and take appropriate action.`;
|
|
34015
|
+
this.priorityEngine.ingest(prompt, "internal", "reminder", { reminderId: r.id }, priority);
|
|
33757
34016
|
}
|
|
33758
34017
|
} catch {
|
|
33759
34018
|
}
|
|
33760
34019
|
try {
|
|
33761
34020
|
const items = await getActiveAttentionItems(this.repoRoot);
|
|
33762
|
-
const
|
|
33763
|
-
|
|
33764
|
-
|
|
33765
|
-
return {
|
|
33766
|
-
source: "attention",
|
|
33767
|
-
prompt: `CRITICAL ATTENTION ITEM: [${a.category}] ${a.title}${a.description ? ": " + a.description : ""}. Investigate and take action.`
|
|
33768
|
-
};
|
|
34021
|
+
for (const a of items.filter((a2) => a2.priority === "critical")) {
|
|
34022
|
+
const prompt = `CRITICAL ATTENTION ITEM: [${a.category}] ${a.title}${a.description ? ": " + a.description : ""}. Investigate and take action.`;
|
|
34023
|
+
this.priorityEngine.ingest(prompt, "internal", "attention", void 0, "critical");
|
|
33769
34024
|
}
|
|
33770
34025
|
} catch {
|
|
33771
34026
|
}
|
|
34027
|
+
if (this.pendingQueue.length > 0) {
|
|
34028
|
+
const item = this.pendingQueue.shift();
|
|
34029
|
+
const classification = classifyPriority(item.prompt, "external", item.source);
|
|
34030
|
+
return { ...item, priority: classification.priority };
|
|
34031
|
+
}
|
|
34032
|
+
const task = this.priorityEngine.dequeue();
|
|
34033
|
+
if (task) {
|
|
34034
|
+
return {
|
|
34035
|
+
source: task.origin,
|
|
34036
|
+
prompt: task.prompt,
|
|
34037
|
+
chatId: task.metadata?.chatId,
|
|
34038
|
+
priority: task.priority
|
|
34039
|
+
};
|
|
34040
|
+
}
|
|
33772
34041
|
return null;
|
|
33773
34042
|
}
|
|
33774
34043
|
/** Record that a task was processed */
|
|
@@ -38842,7 +39111,12 @@ async function startInteractive(config, repoPath) {
|
|
|
38842
39111
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
38843
39112
|
const streamRenderer = new StreamRenderer();
|
|
38844
39113
|
if (savedSettings.voice) {
|
|
38845
|
-
voiceEngine.toggle().catch(() => {
|
|
39114
|
+
voiceEngine.toggle().catch((err) => {
|
|
39115
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
39116
|
+
if (msg.includes("ONNX runtime crashes") || msg.includes("unavailable")) {
|
|
39117
|
+
renderWarning(`Voice disabled: ${msg}`);
|
|
39118
|
+
renderInfo("All other features work normally. Use /voice to retry later.");
|
|
39119
|
+
}
|
|
38846
39120
|
});
|
|
38847
39121
|
if (savedSettings.voiceModel) {
|
|
38848
39122
|
voiceEngine.setModel(savedSettings.voiceModel).catch(() => {
|
package/package.json
CHANGED