open-agents-ai 0.187.563 → 0.187.565

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -533020,99 +533020,50 @@ ${memoryLines.join("\n")}`
533020
533020
  ]);
533021
533021
  const REG61_BYPASS_TOOLS = /* @__PURE__ */ new Set([
533022
533022
  ...REG61_EDIT_TOOLS,
533023
- // Escape hatches: explicitly allowed while gate is active so
533024
- // the agent can exit cleanly (task_complete), escalate to human
533025
- // (ask_user), or complete an explicit web task without deadlock.
533026
- // shell, file_read, todo_*, grep_search, list_directory are
533027
- // NOT in bypass — those are the exact patterns batch528/529
533028
- // agents used to ignore REG-61.
533029
533023
  "web_search",
533030
533024
  "task_complete",
533031
533025
  "ask_user",
533032
- // DECOMP-1: sub-agent dispatch is productive work (it spawns
533033
- // a focused-context implementation worker). Block-listing
533034
- // sub_agent here would defeat the spec-decomposition pattern
533035
- // — agents would be forced into main-context edits even when
533036
- // delegation is the right move. sub_agent calls do NOT clear
533037
- // the gate (we want the agent to also produce direct edits
533038
- // for orchestration glue / integration), but they're allowed
533039
- // through.
533040
533026
  "sub_agent",
533041
533027
  "priority_delegate",
533042
533028
  "background_run"
533043
533029
  ]);
533044
533030
  if (this._reg61PerpetualGateActive && !REG61_BYPASS_TOOLS.has(tc.name) && process.env["OA_DISABLE_REG61_COERCE"] !== "1") {
533045
- this.emit({
533046
- type: "tool_call",
533047
- toolName: tc.name,
533048
- toolArgs: tc.arguments,
533049
- turn,
533050
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
533051
- });
533052
533031
  const _dbgLoop = this._detectDebugLoop(toolCallLog);
533053
533032
  const _debugLoopSampleSafe = (_dbgLoop.repeatedSample ?? "").slice(0, 120);
533054
533033
  const _localFailureNudge = this._renderLocalFailureNudge(turn);
533055
- const reg61BlockMsg = _dbgLoop.detected ? [
533056
- `[BLOCKED — REG-61 directive in effect — REG-66 DEBUG-LOOP detected]`,
533034
+ const reg61SteerMsg = _dbgLoop.detected ? [
533035
+ `[REG-61 directive active — REG-66 DEBUG-LOOP detected]`,
533057
533036
  ``,
533058
- `Pattern: ${_dbgLoop.kind === "shell" ? "shell command" : "file"} "${_debugLoopSampleSafe}" was used ${_dbgLoop.count}× in the trailing window with ZERO creative edits landing. You are stuck in a debug loop where re-running / re-reading is producing no new information.`,
533037
+ `Pattern: ${_dbgLoop.kind === "shell" ? "shell command" : "file"} "${_debugLoopSampleSafe}" was used ${_dbgLoop.count}× in the trailing window with ZERO creative edits landing. You appear stuck in a debug loop where re-running / re-reading is producing no new information.`,
533059
533038
  ``,
533060
- `STOP DEBUGGING. PERTURB.`,
533039
+ `Consider PERTURBING: make a speculative edit to get a NEW error signal.`,
533061
533040
  ``,
533062
- `Strategy when stuck like this (real human debuggers do this):`,
533063
- ` 1. Pick the source file most likely implicated by the recurring failure (probably in src/, the one most-imported by failing tests).`,
533041
+ `Strategy:`,
533042
+ ` 1. Pick the source file most likely implicated by the recurring failure.`,
533064
533043
  ` 2. Pick ONE plausible cause — most-recently-modified line, most-complex function, most-likely-misnamed import, most-likely off-by-one.`,
533065
533044
  ` 3. Make a SPECULATIVE edit that changes that thing — even if you are NOT certain it'll fix the bug. The point is to get a NEW error signal that disambiguates.`,
533066
- ` 4. Re-run the failing command. If the error CHANGED, you've learned something. If it's identical, you've ruled out one hypothesis.`,
533045
+ ` 4. Re-run the failing command. If the error CHANGED, you've learned something.`,
533067
533046
  ``,
533068
- `This is NOT random guessing it's targeted hypothesis falsification. Reading the same files 5+ times has already proven uninformative; only a state change will move the system.`,
533069
- ``,
533070
- `Issue EXACTLY ONE of: file_write / file_edit / batch_edit / file_patch on a single concrete change. The edit must actually change disk state; dry-runs and no-ops do not clear this directive.`,
533071
- ``,
533072
- _localFailureNudge,
533073
- ``,
533074
- `Allowed exits (will not be blocked but will not clear the directive either):`,
533075
- ` * task_complete - exit if you genuinely cannot identify any plausible local perturbation`,
533076
- ` * ask_user - escalate to human (if available)`,
533077
- ``,
533078
- `Once you make a real edit, the directive clears and you'll see the new test result.`
533047
+ `This tool call was ALLOWED through, but the edit directive remains active.`
533079
533048
  ].join("\n") : [
533080
- `[BLOCKED — REG-61 directive in effect]`,
533049
+ `[REG-61 directive active]`,
533081
533050
  ``,
533082
- `A REG-61 FIRST-EDIT NUDGE was issued earlier and has not yet been satisfied. The directive: your next tool call MUST be a creative edit. You issued '${tc.name}' instead, which is a read/explore/shell call. This call has been BLOCKED.`,
533051
+ `A REG-61 FIRST-EDIT NUDGE was issued earlier and has not yet been satisfied. The directive asks you to prioritize a creative edit. You issued '${tc.name}' instead, which is a read/explore/shell call.`,
533083
533052
  ``,
533084
- `Issue EXACTLY ONE of these to clear the directive:`,
533053
+ `This call was ALLOWED through (needed context should never be blocked), but try to make a creative edit next:`,
533085
533054
  ` • file_write — create a new file`,
533086
533055
  ` • file_edit — modify an existing file (find/replace)`,
533087
533056
  ` • batch_edit — multiple find/replace edits in one call`,
533088
533057
  ` • file_patch — apply a version-checked line-range patch`,
533089
533058
  ``,
533090
- _localFailureNudge,
533091
- ``,
533092
- `These exits are also allowed while the directive is active (will not be blocked, will not clear the gate):`,
533093
- ` * task_complete - to exit if you cannot make any local progress`,
533094
- ` * ask_user - to escalate to human (if available)`,
533095
- ``,
533096
- `Until you issue a creative edit that actually changes disk, ALL of these will be BLOCKED again on every turn: file_read, file_explore, list_directory, grep_search, shell, todo_write, todo_read, memory_read, memory_write, etc. Pick the smallest concrete change that moves work forward.`
533059
+ _localFailureNudge
533097
533060
  ].join("\n");
533098
- this.emit({
533099
- type: "tool_result",
533100
- toolName: tc.name,
533101
- success: false,
533102
- content: reg61BlockMsg.slice(0, 120),
533103
- turn,
533104
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
533105
- });
533061
+ pushSoftInjection("system", reg61SteerMsg);
533106
533062
  this.emit({
533107
533063
  type: "status",
533108
- content: `REG-61 COERCION BLOCK rejected '${tc.name}' at turn ${turn}; gate stays active until creative edit dispatches${_dbgLoop.detected ? `; REG-66 debug-loop variant (${_dbgLoop.kind} "${_debugLoopSampleSafe.slice(0, 60)}" ${_dbgLoop.count}×)` : ""}`,
533064
+ content: `REG-61 STEERnudge injected for '${tc.name}' at turn ${turn}; tool ALLOWED; gate stays active${_dbgLoop.detected ? `; REG-66 debug-loop variant (${_dbgLoop.kind} "${_debugLoopSampleSafe.slice(0, 60)}" ${_dbgLoop.count}×)` : ""}`,
533109
533065
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
533110
533066
  });
533111
- this._tagSyntheticFailure({
533112
- mode: "step_repetition",
533113
- rationale: `REG-61 perpetual coercion block on '${tc.name}' — agent ignored FIRST-EDIT NUDGE${_dbgLoop.detected ? " (debug-loop variant)" : ""}`
533114
- });
533115
- return { tc, output: reg61BlockMsg };
533116
533067
  }
533117
533068
  {
533118
533069
  const _decomp2Block = this._maybeDecomp2Block(tc, turn);
@@ -563875,10 +563826,21 @@ __export(voice_exports, {
563875
563826
  registerCustomOnnxModel: () => registerCustomOnnxModel,
563876
563827
  resetNarrationContext: () => resetNarrationContext
563877
563828
  });
563878
- import { existsSync as existsSync87, mkdirSync as mkdirSync49, writeFileSync as writeFileSync46, readFileSync as readFileSync71, unlinkSync as unlinkSync17, readdirSync as readdirSync25, statSync as statSync28 } from "node:fs";
563829
+ import {
563830
+ existsSync as existsSync87,
563831
+ mkdirSync as mkdirSync49,
563832
+ writeFileSync as writeFileSync46,
563833
+ readFileSync as readFileSync71,
563834
+ unlinkSync as unlinkSync17,
563835
+ readdirSync as readdirSync25,
563836
+ statSync as statSync28
563837
+ } from "node:fs";
563879
563838
  import { join as join104, dirname as dirname30 } from "node:path";
563880
563839
  import { homedir as homedir32, tmpdir as tmpdir20, platform as platform5 } from "node:os";
563881
- import { execSync as execSync51, spawn as nodeSpawn } from "node:child_process";
563840
+ import {
563841
+ execSync as execSync51,
563842
+ spawn as nodeSpawn
563843
+ } from "node:child_process";
563882
563844
  import { createRequire as createRequire4 } from "node:module";
563883
563845
  function sanitizeForTTS(text) {
563884
563846
  return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
@@ -563951,7 +563913,12 @@ function normalizeSupertonicSettings(value2) {
563951
563913
  voiceName: SUPERTONIC_VOICES.includes(String(v.voiceName ?? "")) ? String(v.voiceName) : DEFAULT_SUPERTONIC_SETTINGS.voiceName,
563952
563914
  lang: SUPERTONIC_LANGS.includes(String(v.lang ?? "")) ? String(v.lang) : DEFAULT_SUPERTONIC_SETTINGS.lang,
563953
563915
  speed: clampFloat(v.speed, DEFAULT_SUPERTONIC_SETTINGS.speed, 0.7, 1.8),
563954
- totalStep: clampInt(v.totalStep, DEFAULT_SUPERTONIC_SETTINGS.totalStep, 4, 16),
563916
+ totalStep: clampInt(
563917
+ v.totalStep,
563918
+ DEFAULT_SUPERTONIC_SETTINGS.totalStep,
563919
+ 4,
563920
+ 16
563921
+ ),
563955
563922
  expression: isSupertonicExpression(v.expression) ? v.expression : DEFAULT_SUPERTONIC_SETTINGS.expression
563956
563923
  };
563957
563924
  }
@@ -564149,7 +564116,9 @@ function extractToolObject(toolName, args) {
564149
564116
  case "sub_agent": {
564150
564117
  const topic = extractSubAgentTopic(args);
564151
564118
  if (topic) return topic;
564152
- const agentType = String(args["subagent_type"] ?? args["type"] ?? "").replace(/-/g, " ");
564119
+ const agentType = String(
564120
+ args["subagent_type"] ?? args["type"] ?? ""
564121
+ ).replace(/-/g, " ");
564153
564122
  return agentType || "sub agent";
564154
564123
  }
564155
564124
  case "batch_edit":
@@ -564225,7 +564194,11 @@ function extractToolVerb(toolName, args) {
564225
564194
  return ["examining", "looking at", "examined"];
564226
564195
  default: {
564227
564196
  const readable = toolName.replace(/[_-]/g, " ");
564228
- return [`invoking ${readable}`, `calling ${readable}`, `invoked ${readable}`];
564197
+ return [
564198
+ `invoking ${readable}`,
564199
+ `calling ${readable}`,
564200
+ `invoked ${readable}`
564201
+ ];
564229
564202
  }
564230
564203
  }
564231
564204
  }
@@ -564321,13 +564294,16 @@ function extractShellEssence(cmd) {
564321
564294
  if (npmTest) return "running tests";
564322
564295
  const npmBuild = cmd.match(/npm\s+run\s+(\S+)/);
564323
564296
  if (npmBuild) return `running ${npmBuild[1]}`;
564324
- const gitCmd = cmd.match(/git\s+(commit|push|pull|merge|rebase|checkout|diff|status|log|stash|add)\b/);
564297
+ const gitCmd = cmd.match(
564298
+ /git\s+(commit|push|pull|merge|rebase|checkout|diff|status|log|stash|add)\b/
564299
+ );
564325
564300
  if (gitCmd) return `git ${gitCmd[1]}`;
564326
564301
  if (/npm\s+publish/.test(cmd)) return "publishing to npm";
564327
564302
  const nodeScript = cmd.match(/(?:node|tsx?)\s+(\S+)/);
564328
564303
  if (nodeScript) return `running ${nodeScript[1].split("/").pop()}`;
564329
564304
  const curlUrl = cmd.match(/curl\s+.*?(https?:\/\/\S{10,40})/);
564330
- if (curlUrl) return `fetching ${curlUrl[1].replace(/https?:\/\//, "").split("/")[0]}`;
564305
+ if (curlUrl)
564306
+ return `fetching ${curlUrl[1].replace(/https?:\/\//, "").split("/")[0]}`;
564331
564307
  const pnpm = cmd.match(/pnpm\s+(-r\s+)?(\S+)/);
564332
564308
  if (pnpm) return `pnpm ${pnpm[1] || ""}${pnpm[2]}`.trim();
564333
564309
  return "";
@@ -564385,10 +564361,8 @@ function computeStateInterjection(quadrant, stark) {
564385
564361
  return "";
564386
564362
  }
564387
564363
  case 2: {
564388
- if (errCount >= 3)
564389
- return `${errCount} consecutive errors now. `;
564390
- if (errCount === 2)
564391
- return `Second failure in a row. `;
564364
+ if (errCount >= 3) return `${errCount} consecutive errors now. `;
564365
+ if (errCount === 2) return `Second failure in a row. `;
564392
564366
  if (totalErrors >= 5)
564393
564367
  return `${totalErrors} errors this session, pushing through. `;
564394
564368
  if (totalErrors >= 2 && totalCalls > 5)
@@ -564400,21 +564374,17 @@ function computeStateInterjection(quadrant, stark) {
564400
564374
  return `${totalCalls} operations, zero errors. `;
564401
564375
  if (uniqueFiles >= 4 && totalErrors === 0)
564402
564376
  return `${uniqueFiles} files, all clean. `;
564403
- if (streak >= 5)
564404
- return `Steady, ${streak} clean operations. `;
564377
+ if (streak >= 5) return `Steady, ${streak} clean operations. `;
564405
564378
  if (totalCalls > 8 && errCount === 0)
564406
564379
  return `Smooth at step ${totalCalls}. `;
564407
564380
  return "";
564408
564381
  }
564409
564382
  case 4: {
564410
- if (uniqueFiles >= 6)
564411
- return `${uniqueFiles} files in play. `;
564383
+ if (uniqueFiles >= 6) return `${uniqueFiles} files in play. `;
564412
564384
  if (totalErrors > 0 && errCount === 0)
564413
564385
  return `Past ${totalErrors} error${totalErrors > 1 ? "s" : ""}, being careful. `;
564414
- if (sameToolCount >= 4)
564415
- return `Pass ${sameToolCount} on this file. `;
564416
- if (totalCalls > 10)
564417
- return `Step ${totalCalls}, measured pace. `;
564386
+ if (sameToolCount >= 4) return `Pass ${sameToolCount} on this file. `;
564387
+ if (totalCalls > 10) return `Step ${totalCalls}, measured pace. `;
564418
564388
  return "";
564419
564389
  }
564420
564390
  default:
@@ -564471,8 +564441,11 @@ function extractResultDigest(toolName, content) {
564471
564441
  const nuggets = [];
564472
564442
  const ethMatch = text.match(/([\d.]+)\s*ETH/i);
564473
564443
  if (ethMatch) nuggets.push(`${ethMatch[1]} ETH`);
564474
- const tokenMatch = text.match(/([\d,.]+)\s*(USDC|USDT|DAI|BTC|SOL|MATIC|tokens?)\b/i);
564475
- if (tokenMatch && !nuggets.length) nuggets.push(`${tokenMatch[1]} ${tokenMatch[2]}`);
564444
+ const tokenMatch = text.match(
564445
+ /([\d,.]+)\s*(USDC|USDT|DAI|BTC|SOL|MATIC|tokens?)\b/i
564446
+ );
564447
+ if (tokenMatch && !nuggets.length)
564448
+ nuggets.push(`${tokenMatch[1]} ${tokenMatch[2]}`);
564476
564449
  const addrMatch = text.match(/(0x[0-9a-fA-F]{8})[0-9a-fA-F]+/);
564477
564450
  if (addrMatch) nuggets.push(`address ${addrMatch[1]}...`);
564478
564451
  const httpMatch = text.match(/(?:status|code)[:\s]*(\d{3})\b/i);
@@ -564487,7 +564460,9 @@ function extractResultDigest(toolName, content) {
564487
564460
  }
564488
564461
  const errMatch = text.match(/(?:error|Error|ERROR)[:\s]+(.{5,50}?)(?:\n|$)/);
564489
564462
  if (errMatch) nuggets.push(`error: ${errMatch[1].trim()}`);
564490
- const statusMatch = text.match(/\[(running|complete|completed|failed|pending|success|stopped|error)\]/i);
564463
+ const statusMatch = text.match(
564464
+ /\[(running|complete|completed|failed|pending|success|stopped|error)\]/i
564465
+ );
564491
564466
  if (statusMatch) nuggets.push(statusMatch[1].toLowerCase());
564492
564467
  const versionMatch = text.match(/\bv?(\d+\.\d+\.\d+)\b/);
564493
564468
  if (versionMatch && !nuggets.some((n2) => n2.includes(versionMatch[1]))) {
@@ -564500,7 +564475,8 @@ function extractResultDigest(toolName, content) {
564500
564475
  const gasMatch = text.match(/gas[:\s]*([\d,]+)/i);
564501
564476
  if (gasMatch) nuggets.push(`gas ${gasMatch[1]}`);
564502
564477
  const exitMatch = text.match(/exit\s*(?:code)?[:\s]*(\d+)/i);
564503
- if (exitMatch && exitMatch[1] !== "0") nuggets.push(`exit code ${exitMatch[1]}`);
564478
+ if (exitMatch && exitMatch[1] !== "0")
564479
+ nuggets.push(`exit code ${exitMatch[1]}`);
564504
564480
  if (nuggets.length === 0) {
564505
564481
  const contentDigest = extractContentSummary(text, toolName);
564506
564482
  if (contentDigest) nuggets.push(contentDigest);
@@ -564509,7 +564485,10 @@ function extractResultDigest(toolName, content) {
564509
564485
  return digest3.length > 100 ? digest3.slice(0, 97) + "..." : digest3;
564510
564486
  }
564511
564487
  function extractContentSummary(text, toolName) {
564512
- let cleaned = text.replace(/^\s*\d+[│|:→]\s*/gm, "").replace(/\d{4}-\d{2}-\d{2}T[\d:.]+Z?\s*/g, "").replace(/^[\s*#=-]+$/gm, "").replace(/```[\s\S]*?```/g, "").replace(/^\s*(import|export|const|let|var|function|class|interface|type)\s/gm, "").replace(/[{}()\[\];]/g, "").trim();
564488
+ let cleaned = text.replace(/^\s*\d+[│|:→]\s*/gm, "").replace(/\d{4}-\d{2}-\d{2}T[\d:.]+Z?\s*/g, "").replace(/^[\s*#=-]+$/gm, "").replace(/```[\s\S]*?```/g, "").replace(
564489
+ /^\s*(import|export|const|let|var|function|class|interface|type)\s/gm,
564490
+ ""
564491
+ ).replace(/[{}()\[\];]/g, "").trim();
564513
564492
  const lines = cleaned.split("\n").map((l2) => l2.trim()).filter((l2) => l2.length > 10);
564514
564493
  for (const line of lines) {
564515
564494
  const wordChars = line.replace(/[^a-zA-Z\s]/g, "").trim();
@@ -564528,7 +564507,9 @@ function extractContentSummary(text, toolName) {
564528
564507
  return summary;
564529
564508
  }
564530
564509
  if (toolName === "sub_agent") {
564531
- const summaryMatch = text.match(/(?:summary|created|completed|result)[:\s]+(.{10,80}?)(?:\n|$)/i);
564510
+ const summaryMatch = text.match(
564511
+ /(?:summary|created|completed|result)[:\s]+(.{10,80}?)(?:\n|$)/i
564512
+ );
564532
564513
  if (summaryMatch) {
564533
564514
  let s2 = summaryMatch[1].trim();
564534
564515
  if (s2.length > 0) s2 = s2.charAt(0).toLowerCase() + s2.slice(1);
@@ -564709,8 +564690,51 @@ var init_voice = __esm({
564709
564690
  supertonicLang: "en"
564710
564691
  }
564711
564692
  };
564712
- SUPERTONIC_LANGS = ["en", "ko", "ja", "ar", "bg", "cs", "da", "de", "el", "es", "et", "fi", "fr", "hi", "hr", "hu", "id", "it", "lt", "lv", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sv", "tr", "uk", "vi"];
564713
- SUPERTONIC_VOICES = ["M1", "M2", "M3", "M4", "M5", "F1", "F2", "F3", "F4", "F5"];
564693
+ SUPERTONIC_LANGS = [
564694
+ "en",
564695
+ "ko",
564696
+ "ja",
564697
+ "ar",
564698
+ "bg",
564699
+ "cs",
564700
+ "da",
564701
+ "de",
564702
+ "el",
564703
+ "es",
564704
+ "et",
564705
+ "fi",
564706
+ "fr",
564707
+ "hi",
564708
+ "hr",
564709
+ "hu",
564710
+ "id",
564711
+ "it",
564712
+ "lt",
564713
+ "lv",
564714
+ "nl",
564715
+ "pl",
564716
+ "pt",
564717
+ "ro",
564718
+ "ru",
564719
+ "sk",
564720
+ "sl",
564721
+ "sv",
564722
+ "tr",
564723
+ "uk",
564724
+ "vi"
564725
+ ];
564726
+ SUPERTONIC_VOICES = [
564727
+ "M1",
564728
+ "M2",
564729
+ "M3",
564730
+ "M4",
564731
+ "M5",
564732
+ "F1",
564733
+ "F2",
564734
+ "F3",
564735
+ "F4",
564736
+ "F5"
564737
+ ];
564714
564738
  DEFAULT_SUPERTONIC_SETTINGS = {
564715
564739
  voiceName: "M4",
564716
564740
  lang: "en",
@@ -564803,7 +564827,9 @@ except Exception as exc:
564803
564827
  /** True when current model uses Supertonic3 backend */
564804
564828
  supertonicActive = false;
564805
564829
  supertonicInstalled = null;
564806
- supertonicSettings = { ...DEFAULT_SUPERTONIC_SETTINGS };
564830
+ supertonicSettings = {
564831
+ ...DEFAULT_SUPERTONIC_SETTINGS
564832
+ };
564807
564833
  /** Whether LuxTTS voice-clone backend is currently active */
564808
564834
  get isLuxtts() {
564809
564835
  return this.luxttsActive;
@@ -564884,17 +564910,25 @@ except Exception as exc:
564884
564910
  const b = VOICE_MODELS[k].backend;
564885
564911
  return !b || b === "onnx";
564886
564912
  });
564887
- const mlxModels = Object.keys(VOICE_MODELS).filter((k) => VOICE_MODELS[k].backend === "mlx");
564888
- const luxttsModels = Object.keys(VOICE_MODELS).filter((k) => VOICE_MODELS[k].backend === "luxtts");
564889
- const supertonicModels = Object.keys(VOICE_MODELS).filter((k) => VOICE_MODELS[k].backend === "supertonic");
564913
+ const mlxModels = Object.keys(VOICE_MODELS).filter(
564914
+ (k) => VOICE_MODELS[k].backend === "mlx"
564915
+ );
564916
+ const luxttsModels = Object.keys(VOICE_MODELS).filter(
564917
+ (k) => VOICE_MODELS[k].backend === "luxtts"
564918
+ );
564919
+ const supertonicModels = Object.keys(VOICE_MODELS).filter(
564920
+ (k) => VOICE_MODELS[k].backend === "supertonic"
564921
+ );
564890
564922
  let msg = `Unknown voice model: "${id}". Available:`;
564891
564923
  msg += `
564892
564924
  ONNX: ${onnxModels.join(", ")}`;
564893
564925
  if (mlxModels.length) msg += `
564894
564926
  MLX (macOS): ${mlxModels.join(", ")}`;
564895
- if (luxttsModels.length) msg += `
564927
+ if (luxttsModels.length)
564928
+ msg += `
564896
564929
  LuxTTS (voice clone): ${luxttsModels.join(", ")}`;
564897
- if (supertonicModels.length) msg += `
564930
+ if (supertonicModels.length)
564931
+ msg += `
564898
564932
  Supertonic3: ${supertonicModels.join(", ")}`;
564899
564933
  return msg;
564900
564934
  }
@@ -565045,7 +565079,15 @@ except Exception as exc:
565045
565079
  writeFileSync46(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
565046
565080
  }
565047
565081
  /** Audio file extensions recognized as clone references */
565048
- static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
565082
+ static AUDIO_EXTS = /* @__PURE__ */ new Set([
565083
+ "wav",
565084
+ "mp3",
565085
+ "ogg",
565086
+ "flac",
565087
+ "m4a",
565088
+ "opus",
565089
+ "aac"
565090
+ ]);
565049
565091
  /**
565050
565092
  * List all clone reference audio files with metadata.
565051
565093
  * Returns array of { filename, path, name, size, isActive }.
@@ -565148,7 +565190,13 @@ except Exception as exc:
565148
565190
  return;
565149
565191
  }
565150
565192
  for (const chunk of chunks) {
565151
- this.speakQueue.push({ text: chunk, volume, pitchFactor, speedFactor, stereoDelayMs });
565193
+ this.speakQueue.push({
565194
+ text: chunk,
565195
+ volume,
565196
+ pitchFactor,
565197
+ speedFactor,
565198
+ stereoDelayMs
565199
+ });
565152
565200
  }
565153
565201
  if (!this.speaking) {
565154
565202
  this.drainQueue().catch(() => {
@@ -565378,10 +565426,18 @@ except Exception as exc:
565378
565426
  );
565379
565427
  }
565380
565428
  if (!wavPath) {
565381
- wavPath = await this.synthesizeLuxttsWav(item.text, item.speedFactor);
565429
+ wavPath = await this.synthesizeLuxttsWav(
565430
+ item.text,
565431
+ item.speedFactor
565432
+ );
565382
565433
  }
565383
565434
  if (wavPath) {
565384
- await this.postProcessAndPlayLuxtts(wavPath, item.volume, item.pitchFactor, item.stereoDelayMs);
565435
+ await this.postProcessAndPlayLuxtts(
565436
+ wavPath,
565437
+ item.volume,
565438
+ item.pitchFactor,
565439
+ item.stereoDelayMs
565440
+ );
565385
565441
  }
565386
565442
  if (prefetchPromise && nextItem) {
565387
565443
  try {
@@ -565393,7 +565449,13 @@ except Exception as exc:
565393
565449
  }
565394
565450
  }
565395
565451
  } else {
565396
- await this.synthesizeAndPlay(item.text, item.volume, item.pitchFactor, item.speedFactor, item.stereoDelayMs);
565452
+ await this.synthesizeAndPlay(
565453
+ item.text,
565454
+ item.volume,
565455
+ item.pitchFactor,
565456
+ item.speedFactor,
565457
+ item.stereoDelayMs
565458
+ );
565397
565459
  }
565398
565460
  } catch {
565399
565461
  }
@@ -565422,11 +565484,23 @@ except Exception as exc:
565422
565484
  // -------------------------------------------------------------------------
565423
565485
  async synthesizeAndPlay(text, volume = 1, pitchFactor = 1, speedFactor = 1, stereoDelayMs = 0.6) {
565424
565486
  if (this.luxttsActive) {
565425
- await this.synthesizeWithLuxtts(text, volume, pitchFactor, speedFactor, stereoDelayMs);
565487
+ await this.synthesizeWithLuxtts(
565488
+ text,
565489
+ volume,
565490
+ pitchFactor,
565491
+ speedFactor,
565492
+ stereoDelayMs
565493
+ );
565426
565494
  return;
565427
565495
  }
565428
565496
  if (this.supertonicActive) {
565429
- await this.synthesizeWithSupertonic(text, volume, pitchFactor, speedFactor, stereoDelayMs);
565497
+ await this.synthesizeWithSupertonic(
565498
+ text,
565499
+ volume,
565500
+ pitchFactor,
565501
+ speedFactor,
565502
+ stereoDelayMs
565503
+ );
565430
565504
  return;
565431
565505
  }
565432
565506
  if (this.mlxActive) {
@@ -565601,9 +565675,15 @@ except Exception as exc:
565601
565675
  for (let i2 = 0; i2 < numSamples; i2++) {
565602
565676
  const lSample = Math.max(-1, Math.min(1, left[i2]));
565603
565677
  const rSample = Math.max(-1, Math.min(1, right[i2]));
565604
- buffer2.writeInt16LE(lSample < 0 ? lSample * 32768 : lSample * 32767, pos);
565678
+ buffer2.writeInt16LE(
565679
+ lSample < 0 ? lSample * 32768 : lSample * 32767,
565680
+ pos
565681
+ );
565605
565682
  pos += 2;
565606
- buffer2.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
565683
+ buffer2.writeInt16LE(
565684
+ rSample < 0 ? rSample * 32768 : rSample * 32767,
565685
+ pos
565686
+ );
565607
565687
  pos += 2;
565608
565688
  }
565609
565689
  writeFileSync46(path11, buffer2);
@@ -565624,7 +565704,9 @@ except Exception as exc:
565624
565704
  const phonemes = await this.phonemizeFn(text, voice);
565625
565705
  const phonemeText = Array.isArray(phonemes) ? phonemes.join(" ") : String(phonemes || text);
565626
565706
  const sentences = phonemeText.split(/[.!?]+/).filter((s2) => s2.trim().length > 0);
565627
- return sentences.map((sentence) => Array.from(sentence.trim().normalize("NFD")));
565707
+ return sentences.map(
565708
+ (sentence) => Array.from(sentence.trim().normalize("NFD"))
565709
+ );
565628
565710
  }
565629
565711
  /**
565630
565712
  * Convert phoneme character arrays to integer IDs using the model's phoneme_id_map.
@@ -565676,7 +565758,10 @@ except Exception as exc:
565676
565758
  buffer2.writeUInt16LE(bitsPerSample, 34);
565677
565759
  buffer2.write("data", 36);
565678
565760
  buffer2.writeUInt32LE(dataSize, 40);
565679
- Buffer.from(int16.buffer, int16.byteOffset, int16.byteLength).copy(buffer2, 44);
565761
+ Buffer.from(int16.buffer, int16.byteOffset, int16.byteLength).copy(
565762
+ buffer2,
565763
+ 44
565764
+ );
565680
565765
  return buffer2;
565681
565766
  }
565682
565767
  writeWav(samples, sampleRate, path11) {
@@ -565752,7 +565837,9 @@ except Exception as exc:
565752
565837
  setSupertonicSettings(patch) {
565753
565838
  const current = this.getSupertonicSettings();
565754
565839
  const next = {
565755
- voiceName: SUPERTONIC_VOICES.includes(String(patch.voiceName ?? current.voiceName)) ? String(patch.voiceName ?? current.voiceName) : current.voiceName,
565840
+ voiceName: SUPERTONIC_VOICES.includes(
565841
+ String(patch.voiceName ?? current.voiceName)
565842
+ ) ? String(patch.voiceName ?? current.voiceName) : current.voiceName,
565756
565843
  lang: SUPERTONIC_LANGS.includes(String(patch.lang ?? current.lang)) ? String(patch.lang ?? current.lang) : current.lang,
565757
565844
  speed: clampFloat(patch.speed, current.speed, 0.7, 1.8),
565758
565845
  totalStep: clampInt(patch.totalStep, current.totalStep, 4, 16),
@@ -565766,7 +565853,10 @@ except Exception as exc:
565766
565853
  }
565767
565854
  listSupertonicProfiles() {
565768
565855
  const store2 = this.loadSupertonicStore();
565769
- return Object.entries(store2.profiles).map(([name10, settings]) => ({ name: name10, settings }));
565856
+ return Object.entries(store2.profiles).map(([name10, settings]) => ({
565857
+ name: name10,
565858
+ settings
565859
+ }));
565770
565860
  }
565771
565861
  saveSupertonicProfile(name10) {
565772
565862
  const clean3 = name10.trim().replace(/[^a-zA-Z0-9_.-]/g, "-");
@@ -565793,7 +565883,9 @@ except Exception as exc:
565793
565883
  }
565794
565884
  loadSupertonicStore() {
565795
565885
  try {
565796
- const raw = JSON.parse(readFileSync71(supertonicProfilesFile(), "utf-8"));
565886
+ const raw = JSON.parse(
565887
+ readFileSync71(supertonicProfilesFile(), "utf-8")
565888
+ );
565797
565889
  const profiles = {};
565798
565890
  for (const [name10, settings] of Object.entries(raw.profiles ?? {})) {
565799
565891
  profiles[name10] = normalizeSupertonicSettings(settings);
@@ -565808,12 +565900,18 @@ except Exception as exc:
565808
565900
  }
565809
565901
  saveSupertonicStore(store2) {
565810
565902
  mkdirSync49(voiceDir(), { recursive: true });
565811
- writeFileSync46(supertonicProfilesFile(), JSON.stringify(store2, null, 2), "utf-8");
565903
+ writeFileSync46(
565904
+ supertonicProfilesFile(),
565905
+ JSON.stringify(store2, null, 2),
565906
+ "utf-8"
565907
+ );
565812
565908
  }
565813
565909
  async ensureSupertonic() {
565814
565910
  const py = await this.findPython3Async();
565815
565911
  if (!py) {
565816
- throw new Error("python3 not found. Install Python 3.10+ to use Supertonic3.");
565912
+ throw new Error(
565913
+ "python3 not found. Install Python 3.10+ to use Supertonic3."
565914
+ );
565817
565915
  }
565818
565916
  const venvDir = supertonicVenvDir();
565819
565917
  const venvPy = supertonicVenvPy();
@@ -565823,8 +565921,14 @@ except Exception as exc:
565823
565921
  }
565824
565922
  if (!this.checkSupertonicInstalled()) {
565825
565923
  renderInfo2("Installing Supertonic3 TTS (first-time setup)...");
565826
- await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet --upgrade pip`, 12e4);
565827
- await this.asyncShell(`${JSON.stringify(venvPy)} -m pip install --quiet supertonic`, 6e5);
565924
+ await this.asyncShell(
565925
+ `${JSON.stringify(venvPy)} -m pip install --quiet --upgrade pip`,
565926
+ 12e4
565927
+ );
565928
+ await this.asyncShell(
565929
+ `${JSON.stringify(venvPy)} -m pip install --quiet supertonic`,
565930
+ 6e5
565931
+ );
565828
565932
  this.supertonicInstalled = true;
565829
565933
  }
565830
565934
  this.writeSupertonicInferScript();
@@ -565837,7 +565941,10 @@ except Exception as exc:
565837
565941
  return false;
565838
565942
  }
565839
565943
  try {
565840
- execSync51(`${JSON.stringify(venvPy)} -c "import supertonic"`, { stdio: "pipe", timeout: 1e4 });
565944
+ execSync51(`${JSON.stringify(venvPy)} -c "import supertonic"`, {
565945
+ stdio: "pipe",
565946
+ timeout: 1e4
565947
+ });
565841
565948
  this.supertonicInstalled = true;
565842
565949
  return true;
565843
565950
  } catch {
@@ -565862,7 +565969,11 @@ except Exception as exc:
565862
565969
  child.kill("SIGKILL");
565863
565970
  } catch {
565864
565971
  }
565865
- reject(new Error(`Supertonic3 synthesis timed out after ${Math.round(timeoutMs / 1e3)}s`));
565972
+ reject(
565973
+ new Error(
565974
+ `Supertonic3 synthesis timed out after ${Math.round(timeoutMs / 1e3)}s`
565975
+ )
565976
+ );
565866
565977
  }, timeoutMs);
565867
565978
  child.stdout?.on("data", (d2) => {
565868
565979
  stdout += d2.toString();
@@ -565879,10 +565990,22 @@ except Exception as exc:
565879
565990
  const line = stdout.trim().split("\n").pop() ?? "";
565880
565991
  try {
565881
565992
  const parsed = JSON.parse(line);
565882
- if (parsed.ok === false) reject(new Error(String(parsed.error ?? (stderr || "Supertonic3 failed"))));
565993
+ if (parsed.ok === false)
565994
+ reject(
565995
+ new Error(
565996
+ String(parsed.error ?? (stderr || "Supertonic3 failed"))
565997
+ )
565998
+ );
565883
565999
  else resolve43(parsed);
565884
566000
  } catch {
565885
- reject(new Error((stderr || stdout || "Supertonic3 returned no JSON").slice(0, 500)));
566001
+ reject(
566002
+ new Error(
566003
+ (stderr || stdout || "Supertonic3 returned no JSON").slice(
566004
+ 0,
566005
+ 500
566006
+ )
566007
+ )
566008
+ );
565886
566009
  }
565887
566010
  });
565888
566011
  child.stdin?.end(JSON.stringify(req2));
@@ -565891,9 +566014,15 @@ except Exception as exc:
565891
566014
  async synthesizeSupertonicWav(text, speedFactor = 1) {
565892
566015
  await this.ensureSupertonic();
565893
566016
  const settings = this.getSupertonicSettings();
565894
- const cleaned = applySupertonicExpression(text.replace(/\*/g, "").trim(), settings.expression);
566017
+ const cleaned = applySupertonicExpression(
566018
+ text.replace(/\*/g, "").trim(),
566019
+ settings.expression
566020
+ );
565895
566021
  if (!cleaned) return null;
565896
- const wavPath = join104(tmpdir20(), `oa-supertonic3-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
566022
+ const wavPath = join104(
566023
+ tmpdir20(),
566024
+ `oa-supertonic3-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`
566025
+ );
565897
566026
  try {
565898
566027
  await this.supertonicRequest({
565899
566028
  text: cleaned,
@@ -565911,7 +566040,12 @@ except Exception as exc:
565911
566040
  async synthesizeWithSupertonic(text, volume = 1, pitchFactor = 1, speedFactor = 1, stereoDelayMs = 0.6) {
565912
566041
  const wavPath = await this.synthesizeSupertonicWav(text, speedFactor);
565913
566042
  if (!wavPath) return;
565914
- await this.postProcessAndPlayLuxtts(wavPath, volume, pitchFactor, stereoDelayMs);
566043
+ await this.postProcessAndPlayLuxtts(
566044
+ wavPath,
566045
+ volume,
566046
+ pitchFactor,
566047
+ stereoDelayMs
566048
+ );
565915
566049
  }
565916
566050
  async synthesizeSupertonicToBuffer(text) {
565917
566051
  const wavPath = await this.synthesizeSupertonicWav(text, 1);
@@ -565999,7 +566133,10 @@ except Exception as exc:
565999
566133
  return false;
566000
566134
  }
566001
566135
  try {
566002
- execSync51(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
566136
+ execSync51(`${py} -c "import mlx_audio"`, {
566137
+ stdio: "pipe",
566138
+ timeout: 1e4
566139
+ });
566003
566140
  this.mlxInstalled = true;
566004
566141
  return true;
566005
566142
  } catch {
@@ -566030,7 +566167,10 @@ except Exception as exc:
566030
566167
  this.mlxInstalled = true;
566031
566168
  } catch (err) {
566032
566169
  try {
566033
- await this.asyncShell(`${py} -m pip install mlx-audio --user --quiet`, 3e5);
566170
+ await this.asyncShell(
566171
+ `${py} -m pip install mlx-audio --user --quiet`,
566172
+ 3e5
566173
+ );
566034
566174
  this.mlxInstalled = true;
566035
566175
  } catch (err2) {
566036
566176
  throw new Error(
@@ -566091,7 +566231,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566091
566231
  for (let i2 = 0; i2 < samples.length; i2++) {
566092
566232
  samples[i2] = Math.round(samples[i2] * volume);
566093
566233
  }
566094
- const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
566234
+ const scaled = Buffer.concat([
566235
+ header,
566236
+ Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)
566237
+ ]);
566095
566238
  writeFileSync46(wavPath, scaled);
566096
566239
  }
566097
566240
  } catch {
@@ -566101,7 +566244,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566101
566244
  try {
566102
566245
  const wavData = readFileSync71(wavPath);
566103
566246
  if (wavData.length > 44) {
566104
- const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
566247
+ const pcm = Buffer.from(
566248
+ wavData.buffer,
566249
+ wavData.byteOffset + 44,
566250
+ wavData.length - 44
566251
+ );
566105
566252
  const sampleRate = wavData.readUInt32LE(24);
566106
566253
  this.onPCMOutput(pcm, sampleRate);
566107
566254
  }
@@ -566198,13 +566345,18 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566198
566345
  15e3
566199
566346
  ).then(async (torchCheck) => {
566200
566347
  if (torchCheck === "cpu") {
566201
- renderWarning2("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
566348
+ renderWarning2(
566349
+ "GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background..."
566350
+ );
566202
566351
  try {
566203
566352
  const detectScript = join104(voiceDir(), "detect-torch.py");
566204
566353
  writeDetectTorchScript(detectScript);
566205
566354
  let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
566206
566355
  try {
566207
- const args = await this.asyncShell(`python3 ${JSON.stringify(detectScript)} --pip-args`, 1e4);
566356
+ const args = await this.asyncShell(
566357
+ `python3 ${JSON.stringify(detectScript)} --pip-args`,
566358
+ 1e4
566359
+ );
566208
566360
  if (args.trim()) pipArgs = args.trim();
566209
566361
  } catch {
566210
566362
  }
@@ -566226,11 +566378,16 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566226
566378
  renderWarning2("LuxTTS venv found but import failed. Reinstalling...");
566227
566379
  }
566228
566380
  }
566229
- renderInfo2("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
566381
+ renderInfo2(
566382
+ "Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)..."
566383
+ );
566230
566384
  if (!existsSync87(venvDir)) {
566231
566385
  renderInfo2(" Creating Python virtual environment...");
566232
566386
  try {
566233
- await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
566387
+ await this.asyncShell(
566388
+ `${py} -m venv ${JSON.stringify(venvDir)}`,
566389
+ 6e4
566390
+ );
566234
566391
  } catch (err) {
566235
566392
  throw new Error(
566236
566393
  `Failed to create venv: ${err instanceof Error ? err.message : String(err)}`
@@ -566243,7 +566400,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566243
566400
  let pipArgsStr = "torch torchaudio";
566244
566401
  let torchDesc = "unknown platform";
566245
566402
  try {
566246
- const detectResult = await this.asyncShell(`${py} ${JSON.stringify(detectScript)} --json`, 15e3);
566403
+ const detectResult = await this.asyncShell(
566404
+ `${py} ${JSON.stringify(detectScript)} --json`,
566405
+ 15e3
566406
+ );
566247
566407
  const spec = JSON.parse(detectResult.trim());
566248
566408
  pipArgsStr = spec.pip_args_str || "torch torchaudio";
566249
566409
  torchDesc = spec.description || `${spec.platform} ${spec.arch} ${spec.accelerator}`;
@@ -566304,7 +566464,9 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566304
566464
  const pipCmd = JSON.stringify(venvPy);
566305
566465
  const isArm = process.arch === "arm64" || process.arch === "arm";
566306
566466
  if (isArm) {
566307
- renderInfo2(" ARM device detected — installing build prerequisites then deps individually.");
566467
+ renderInfo2(
566468
+ " ARM device detected — installing build prerequisites then deps individually."
566469
+ );
566308
566470
  const isMac = process.platform === "darwin";
566309
566471
  try {
566310
566472
  const { spawnSync: spawnSync7 } = await import("node:child_process");
@@ -566312,23 +566474,38 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566312
566474
  process.stdout.write("\x1B[?1002l\x1B[?1003l\x1B[?1006l");
566313
566475
  }
566314
566476
  if (isMac) {
566315
- renderInfo2(" macOS ARM detected — installing build deps via Homebrew...");
566316
- const brewCheck = spawnSync7("which", ["brew"], { stdio: "pipe", timeout: 5e3 });
566477
+ renderInfo2(
566478
+ " macOS ARM detected installing build deps via Homebrew..."
566479
+ );
566480
+ const brewCheck = spawnSync7("which", ["brew"], {
566481
+ stdio: "pipe",
566482
+ timeout: 5e3
566483
+ });
566317
566484
  if (brewCheck.status === 0) {
566318
- const brewResult = spawnSync7("brew", ["install", "llvm", "gcc", "openblas", "libsndfile"], {
566319
- stdio: "pipe",
566320
- timeout: 3e5
566321
- });
566485
+ const brewResult = spawnSync7(
566486
+ "brew",
566487
+ ["install", "llvm", "gcc", "openblas", "libsndfile"],
566488
+ {
566489
+ stdio: "pipe",
566490
+ timeout: 3e5
566491
+ }
566492
+ );
566322
566493
  if (brewResult.stdout) process.stdout.write(brewResult.stdout);
566323
566494
  if (brewResult.stderr) {
566324
566495
  const { renderVerbose: renderVerbose2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
566325
566496
  renderVerbose2(brewResult.stderr.toString());
566326
566497
  }
566327
- const llvmPrefix = spawnSync7("brew", ["--prefix", "llvm"], { stdio: "pipe", timeout: 5e3 });
566498
+ const llvmPrefix = spawnSync7("brew", ["--prefix", "llvm"], {
566499
+ stdio: "pipe",
566500
+ timeout: 5e3
566501
+ });
566328
566502
  if (llvmPrefix.stdout) {
566329
566503
  const prefix = llvmPrefix.stdout.toString().trim();
566330
566504
  process.env.LLVM_CONFIG = `${prefix}/bin/llvm-config`;
566331
- const openblas = spawnSync7("brew", ["--prefix", "openblas"], { stdio: "pipe", timeout: 5e3 });
566505
+ const openblas = spawnSync7("brew", ["--prefix", "openblas"], {
566506
+ stdio: "pipe",
566507
+ timeout: 5e3
566508
+ });
566332
566509
  if (openblas.stdout) {
566333
566510
  const obPrefix = openblas.stdout.toString().trim();
566334
566511
  process.env.LDFLAGS = `${process.env.LDFLAGS ?? ""} -L${obPrefix}/lib`.trim();
@@ -566337,32 +566514,47 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566337
566514
  }
566338
566515
  } else {
566339
566516
  renderWarning2(" Homebrew not found. Install it: https://brew.sh");
566340
- renderWarning2(" Then run: brew install llvm gcc openblas libsndfile");
566517
+ renderWarning2(
566518
+ " Then run: brew install llvm gcc openblas libsndfile"
566519
+ );
566341
566520
  }
566342
566521
  } else {
566343
- renderInfo2(" System build tools needed (llvm, gcc). Requesting sudo access...");
566344
- const sudoCheck = spawnSync7("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
566522
+ renderInfo2(
566523
+ " System build tools needed (llvm, gcc). Requesting sudo access..."
566524
+ );
566525
+ const sudoCheck = spawnSync7("sudo", ["-v"], {
566526
+ stdio: "inherit",
566527
+ timeout: 6e4
566528
+ });
566345
566529
  if (sudoCheck.status === 0) {
566346
- renderInfo2(" Installing system build dependencies (this may take a minute)...");
566347
- const aptResult = spawnSync7("sudo", [
566348
- "apt-get",
566349
- "install",
566350
- "-y",
566351
- "--no-install-recommends",
566352
- "llvm-dev",
566353
- "gcc",
566354
- "g++",
566355
- "gfortran",
566356
- "libopenblas-dev",
566357
- "libsndfile1-dev"
566358
- ], { stdio: "pipe", timeout: 12e4 });
566530
+ renderInfo2(
566531
+ " Installing system build dependencies (this may take a minute)..."
566532
+ );
566533
+ const aptResult = spawnSync7(
566534
+ "sudo",
566535
+ [
566536
+ "apt-get",
566537
+ "install",
566538
+ "-y",
566539
+ "--no-install-recommends",
566540
+ "llvm-dev",
566541
+ "gcc",
566542
+ "g++",
566543
+ "gfortran",
566544
+ "libopenblas-dev",
566545
+ "libsndfile1-dev"
566546
+ ],
566547
+ { stdio: "pipe", timeout: 12e4 }
566548
+ );
566359
566549
  if (aptResult.stdout) process.stdout.write(aptResult.stdout);
566360
566550
  if (aptResult.stderr) {
566361
566551
  const { renderVerbose: renderVerbose2 } = await Promise.resolve().then(() => (init_render2(), render_exports));
566362
566552
  renderVerbose2(aptResult.stderr.toString());
566363
566553
  }
566364
566554
  } else {
566365
- renderWarning2(" sudo not available — skipping system build deps. librosa/lhotse may fail to compile.");
566555
+ renderWarning2(
566556
+ " sudo not available — skipping system build deps. librosa/lhotse may fail to compile."
566557
+ );
566366
566558
  }
566367
566559
  }
566368
566560
  if (process.stdout.isTTY) {
@@ -566372,14 +566564,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566372
566564
  process.stdout.write("\x1B[?1002l\x1B[?1003l");
566373
566565
  }
566374
566566
  } catch (err) {
566375
- renderWarning2(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
566567
+ renderWarning2(
566568
+ ` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`
566569
+ );
566376
566570
  }
566377
566571
  }
566378
566572
  const isJetson = isArm && (existsSync87("/etc/nv_tegra_release") || existsSync87("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
566379
566573
  const installSteps = isArm ? [
566380
566574
  // ARM: install individually so we get clear error messages per package.
566381
566575
  // ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
566382
- { cmd: `${pipCmd} -m pip install --quiet "setuptools<81" wheel`, fatal: true, label: "setuptools" },
566576
+ {
566577
+ cmd: `${pipCmd} -m pip install --quiet "setuptools<81" wheel`,
566578
+ fatal: true,
566579
+ label: "setuptools"
566580
+ },
566383
566581
  // Jetson: try NVIDIA's prebuilt PyTorch wheel for detected JetPack version.
566384
566582
  // JetPack versions have different PyTorch wheel URLs:
566385
566583
  // JP6.x: https://developer.download.nvidia.com/compute/redist/jp/v60/pytorch/
@@ -566388,46 +566586,119 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566388
566586
  ...isJetson ? (() => {
566389
566587
  let jpVer = "v60";
566390
566588
  try {
566391
- const tegra = existsSync87("/etc/nv_tegra_release") ? execSync51("cat /etc/nv_tegra_release 2>/dev/null", { encoding: "utf8", timeout: 3e3 }).trim() : "";
566392
- const dpkg = execSync51("dpkg -l nvidia-jetpack 2>/dev/null | grep nvidia-jetpack | awk '{print $3}'", { encoding: "utf8", timeout: 5e3 }).trim();
566589
+ const tegra = existsSync87("/etc/nv_tegra_release") ? execSync51("cat /etc/nv_tegra_release 2>/dev/null", {
566590
+ encoding: "utf8",
566591
+ timeout: 3e3
566592
+ }).trim() : "";
566593
+ const dpkg = execSync51(
566594
+ "dpkg -l nvidia-jetpack 2>/dev/null | grep nvidia-jetpack | awk '{print $3}'",
566595
+ { encoding: "utf8", timeout: 5e3 }
566596
+ ).trim();
566393
566597
  const ver = dpkg || process.env.JETSON_L4T_VERSION || "";
566394
- if (ver.startsWith("5.") || tegra.includes("R35") || tegra.includes("R34")) jpVer = "v51";
566395
- else if (ver.startsWith("6.1") || tegra.includes("R36.4")) jpVer = "v61";
566396
- else if (ver.startsWith("6.") || tegra.includes("R36")) jpVer = "v60";
566598
+ if (ver.startsWith("5.") || tegra.includes("R35") || tegra.includes("R34"))
566599
+ jpVer = "v51";
566600
+ else if (ver.startsWith("6.1") || tegra.includes("R36.4"))
566601
+ jpVer = "v61";
566602
+ else if (ver.startsWith("6.") || tegra.includes("R36"))
566603
+ jpVer = "v60";
566397
566604
  } catch {
566398
566605
  }
566399
566606
  return [
566400
- { cmd: `${pipCmd} -m pip install --quiet torch torchvision torchaudio --index-url https://developer.download.nvidia.com/compute/redist/jp/${jpVer}/pytorch/ 2>/dev/null || ${pipCmd} -m pip install --quiet torch torchaudio`, fatal: true, label: `PyTorch (Jetson JP ${jpVer})` },
566401
- { cmd: `${pipCmd} -m pip install --quiet onnxruntime-gpu 2>/dev/null || true`, fatal: false, label: "onnxruntime-gpu (Jetson, optional)" }
566607
+ {
566608
+ cmd: `${pipCmd} -m pip install --quiet torch torchvision torchaudio --index-url https://developer.download.nvidia.com/compute/redist/jp/${jpVer}/pytorch/ 2>/dev/null || ${pipCmd} -m pip install --quiet torch torchaudio`,
566609
+ fatal: true,
566610
+ label: `PyTorch (Jetson JP ${jpVer})`
566611
+ },
566612
+ {
566613
+ cmd: `${pipCmd} -m pip install --quiet onnxruntime-gpu 2>/dev/null || true`,
566614
+ fatal: false,
566615
+ label: "onnxruntime-gpu (Jetson, optional)"
566616
+ }
566402
566617
  ];
566403
566618
  })() : [
566404
566619
  // Non-Jetson ARM: use default PyPI (has aarch64 wheels).
566405
566620
  // DO NOT use --index-url https://download.pytorch.org/whl/cpu — that index
566406
566621
  // only has x86_64 wheels. ARM needs the standard PyPI torch package.
566407
- { cmd: `${pipCmd} -m pip install --quiet torch torchaudio`, fatal: true, label: "PyTorch (ARM aarch64 from PyPI)" }
566622
+ {
566623
+ cmd: `${pipCmd} -m pip install --quiet torch torchaudio`,
566624
+ fatal: true,
566625
+ label: "PyTorch (ARM aarch64 from PyPI)"
566626
+ }
566408
566627
  ],
566409
- { cmd: `${pipCmd} -m pip install --quiet numpy`, fatal: true, label: "numpy" },
566410
- { cmd: `${pipCmd} -m pip install --quiet huggingface_hub safetensors`, fatal: true, label: "huggingface_hub + safetensors" },
566411
- { cmd: `${pipCmd} -m pip install --quiet "transformers<=4.57.6"`, fatal: true, label: "transformers" },
566412
- { cmd: `${pipCmd} -m pip install --quiet pydub inflect`, fatal: true, label: "pydub + inflect" },
566628
+ {
566629
+ cmd: `${pipCmd} -m pip install --quiet numpy`,
566630
+ fatal: true,
566631
+ label: "numpy"
566632
+ },
566633
+ {
566634
+ cmd: `${pipCmd} -m pip install --quiet huggingface_hub safetensors`,
566635
+ fatal: true,
566636
+ label: "huggingface_hub + safetensors"
566637
+ },
566638
+ {
566639
+ cmd: `${pipCmd} -m pip install --quiet "transformers<=4.57.6"`,
566640
+ fatal: true,
566641
+ label: "transformers"
566642
+ },
566643
+ {
566644
+ cmd: `${pipCmd} -m pip install --quiet pydub inflect`,
566645
+ fatal: true,
566646
+ label: "pydub + inflect"
566647
+ },
566413
566648
  // llvmlite (needed by numba, needed by librosa): try prebuilt first, then compile
566414
- { cmd: `${pipCmd} -m pip install --quiet llvmlite 2>/dev/null || LLVM_CONFIG=$(which llvm-config || which llvm-config-14 || echo llvm-config) ${pipCmd} -m pip install --quiet llvmlite`, fatal: false, label: "llvmlite (ARM — trying prebuilt, then compiling)" },
566415
- { cmd: `${pipCmd} -m pip install --quiet numba`, fatal: false, label: "numba" },
566649
+ {
566650
+ cmd: `${pipCmd} -m pip install --quiet llvmlite 2>/dev/null || LLVM_CONFIG=$(which llvm-config || which llvm-config-14 || echo llvm-config) ${pipCmd} -m pip install --quiet llvmlite`,
566651
+ fatal: false,
566652
+ label: "llvmlite (ARM — trying prebuilt, then compiling)"
566653
+ },
566654
+ {
566655
+ cmd: `${pipCmd} -m pip install --quiet numba`,
566656
+ fatal: false,
566657
+ label: "numba"
566658
+ },
566416
566659
  // librosa: if numba/llvmlite failed, librosa degrades but still works for basic audio loading
566417
- { cmd: `${pipCmd} -m pip install --quiet librosa`, fatal: true, label: "librosa" },
566418
- { cmd: `${pipCmd} -m pip install --quiet lhotse`, fatal: true, label: "lhotse" },
566660
+ {
566661
+ cmd: `${pipCmd} -m pip install --quiet librosa`,
566662
+ fatal: true,
566663
+ label: "librosa"
566664
+ },
566665
+ {
566666
+ cmd: `${pipCmd} -m pip install --quiet lhotse`,
566667
+ fatal: true,
566668
+ label: "lhotse"
566669
+ },
566419
566670
  // vocos: try pip, fallback to building from source if wheels missing
566420
- { cmd: `${pipCmd} -m pip install --quiet vocos 2>/dev/null || ${pipCmd} -m pip install --quiet --no-build-isolation vocos`, fatal: true, label: "vocos" },
566671
+ {
566672
+ cmd: `${pipCmd} -m pip install --quiet vocos 2>/dev/null || ${pipCmd} -m pip install --quiet --no-build-isolation vocos`,
566673
+ fatal: true,
566674
+ label: "vocos"
566675
+ },
566421
566676
  // LinaCodec: needs C++ build tools on ARM. Install with --no-build-isolation
566422
566677
  // and fallback to CPU-only if CUDA compilation fails.
566423
- { cmd: `${pipCmd} -m pip install --quiet "git+https://github.com/ysharma3501/LinaCodec.git" 2>/dev/null || ${pipCmd} -m pip install --quiet --no-build-isolation "git+https://github.com/ysharma3501/LinaCodec.git"`, fatal: true, label: "LinaCodec (voice cloning codec)" },
566678
+ {
566679
+ cmd: `${pipCmd} -m pip install --quiet "git+https://github.com/ysharma3501/LinaCodec.git" 2>/dev/null || ${pipCmd} -m pip install --quiet --no-build-isolation "git+https://github.com/ysharma3501/LinaCodec.git"`,
566680
+ fatal: true,
566681
+ label: "LinaCodec (voice cloning codec)"
566682
+ },
566424
566683
  // Non-fatal (not hard-imported by LuxTTS):
566425
- { cmd: `${pipCmd} -m pip install --quiet piper-phonemize --find-links https://k2-fsa.github.io/icefall/piper_phonemize.html`, fatal: false, label: "piper-phonemize (optional)" },
566426
- { cmd: `${pipCmd} -m pip install --quiet jieba pypinyin cn2an`, fatal: true, label: "Chinese text processing" },
566684
+ {
566685
+ cmd: `${pipCmd} -m pip install --quiet piper-phonemize --find-links https://k2-fsa.github.io/icefall/piper_phonemize.html`,
566686
+ fatal: false,
566687
+ label: "piper-phonemize (optional)"
566688
+ },
566689
+ {
566690
+ cmd: `${pipCmd} -m pip install --quiet jieba pypinyin cn2an`,
566691
+ fatal: true,
566692
+ label: "Chinese text processing"
566693
+ },
566427
566694
  // LuxTTS itself: use --no-deps on ARM because we installed deps individually above.
566428
566695
  // Without --no-deps, pip tries to resolve zipvoice's full dependency tree which
566429
566696
  // includes piper-phonemize — and that has no macOS ARM wheel, causing fatal failure.
566430
- { cmd: `${pipCmd} -m pip install --quiet --no-deps -e ${JSON.stringify(repoDir)}`, fatal: true, label: "LuxTTS (editable install)" }
566697
+ {
566698
+ cmd: `${pipCmd} -m pip install --quiet --no-deps -e ${JSON.stringify(repoDir)}`,
566699
+ fatal: true,
566700
+ label: "LuxTTS (editable install)"
566701
+ }
566431
566702
  ] : [
566432
566703
  // x86_64: all-in-one (fast, all wheels available)
566433
566704
  {
@@ -566435,10 +566706,26 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566435
566706
  fatal: true,
566436
566707
  label: "core LuxTTS deps"
566437
566708
  },
566438
- { cmd: `${pipCmd} -m pip install --quiet piper-phonemize --find-links https://k2-fsa.github.io/icefall/piper_phonemize.html`, fatal: false, label: "piper-phonemize" },
566439
- { cmd: `${pipCmd} -m pip install --quiet jieba pypinyin cn2an`, fatal: true, label: "Chinese text processing" },
566440
- { cmd: `${pipCmd} -m pip install --quiet "git+https://github.com/ysharma3501/LinaCodec.git"`, fatal: false, label: "LinaCodec" },
566441
- { cmd: `${pipCmd} -m pip install --quiet -e ${JSON.stringify(repoDir)}`, fatal: true, label: "LuxTTS (editable install)" }
566709
+ {
566710
+ cmd: `${pipCmd} -m pip install --quiet piper-phonemize --find-links https://k2-fsa.github.io/icefall/piper_phonemize.html`,
566711
+ fatal: false,
566712
+ label: "piper-phonemize"
566713
+ },
566714
+ {
566715
+ cmd: `${pipCmd} -m pip install --quiet jieba pypinyin cn2an`,
566716
+ fatal: true,
566717
+ label: "Chinese text processing"
566718
+ },
566719
+ {
566720
+ cmd: `${pipCmd} -m pip install --quiet "git+https://github.com/ysharma3501/LinaCodec.git"`,
566721
+ fatal: false,
566722
+ label: "LinaCodec"
566723
+ },
566724
+ {
566725
+ cmd: `${pipCmd} -m pip install --quiet -e ${JSON.stringify(repoDir)}`,
566726
+ fatal: true,
566727
+ label: "LuxTTS (editable install)"
566728
+ }
566442
566729
  ];
566443
566730
  for (const step of installSteps) {
566444
566731
  try {
@@ -566448,7 +566735,9 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566448
566735
  if (!step.fatal) {
566449
566736
  renderWarning2(` Skipped (${step.label}): ${msg.slice(0, 150)}`);
566450
566737
  } else {
566451
- throw new Error(`Failed to install LuxTTS dependencies (${step.label}): ${msg}`);
566738
+ throw new Error(
566739
+ `Failed to install LuxTTS dependencies (${step.label}): ${msg}`
566740
+ );
566452
566741
  }
566453
566742
  }
566454
566743
  }
@@ -566471,7 +566760,12 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
566471
566760
  if (this.luxttsCloneRef && existsSync87(this.luxttsCloneRef)) return;
566472
566761
  const refsDir = luxttsCloneRefsDir();
566473
566762
  if (!existsSync87(refsDir)) return;
566474
- for (const name10 of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
566763
+ for (const name10 of [
566764
+ "custom-clone.wav",
566765
+ "custom-clone.mp3",
566766
+ "glados-ref.wav",
566767
+ "overwatch-ref.wav"
566768
+ ]) {
566475
566769
  const p2 = join104(refsDir, name10);
566476
566770
  if (existsSync87(p2)) {
566477
566771
  this.luxttsCloneRef = p2;
@@ -566674,7 +566968,10 @@ if __name__ == '__main__':
566674
566968
  if (!cleaned) return null;
566675
566969
  const ready = await this.ensureLuxttsDaemon();
566676
566970
  if (!ready) return null;
566677
- const wavPath = join104(tmpdir20(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
566971
+ const wavPath = join104(
566972
+ tmpdir20(),
566973
+ `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`
566974
+ );
566678
566975
  try {
566679
566976
  await this.luxttsRequest({
566680
566977
  action: "synthesize",
@@ -566703,7 +567000,10 @@ if __name__ == '__main__':
566703
567000
  wavData.byteOffset + 44,
566704
567001
  (wavData.length - 44) / 2
566705
567002
  );
566706
- const fadeInSamples = Math.min(Math.round(sampleRate * 0.35), samples.length);
567003
+ const fadeInSamples = Math.min(
567004
+ Math.round(sampleRate * 0.35),
567005
+ samples.length
567006
+ );
566707
567007
  for (let i2 = 0; i2 < fadeInSamples; i2++) {
566708
567008
  samples[i2] = Math.round(samples[i2] * (i2 / fadeInSamples));
566709
567009
  }
@@ -566713,7 +567013,10 @@ if __name__ == '__main__':
566713
567013
  }
566714
567014
  }
566715
567015
  const header = wavData.subarray(0, 44);
566716
- const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
567016
+ const scaled = Buffer.concat([
567017
+ header,
567018
+ Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)
567019
+ ]);
566717
567020
  writeFileSync46(wavPath, scaled);
566718
567021
  }
566719
567022
  } catch {
@@ -566741,7 +567044,11 @@ if __name__ == '__main__':
566741
567044
  try {
566742
567045
  const wavData = readFileSync71(wavPath);
566743
567046
  if (wavData.length > 44) {
566744
- const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
567047
+ const pcm = Buffer.from(
567048
+ wavData.buffer,
567049
+ wavData.byteOffset + 44,
567050
+ wavData.length - 44
567051
+ );
566745
567052
  const sampleRate = wavData.readUInt32LE(24);
566746
567053
  this.onPCMOutput(pcm, sampleRate);
566747
567054
  }
@@ -566764,7 +567071,11 @@ if __name__ == '__main__':
566764
567071
  for (let i2 = 0; i2 < int16.length; i2++) {
566765
567072
  float32[i2] = int16[i2] / 32768;
566766
567073
  }
566767
- const stereo = this.applyStereoDelay(float32, sampleRate, stereoDelayMs);
567074
+ const stereo = this.applyStereoDelay(
567075
+ float32,
567076
+ sampleRate,
567077
+ stereoDelayMs
567078
+ );
566768
567079
  this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
566769
567080
  }
566770
567081
  }
@@ -566782,7 +567093,12 @@ if __name__ == '__main__':
566782
567093
  async synthesizeWithLuxtts(text, volume = 1, pitchFactor = 1, speedFactor = 1, stereoDelayMs = 0.6) {
566783
567094
  const wavPath = await this.synthesizeLuxttsWav(text, speedFactor);
566784
567095
  if (!wavPath) return;
566785
- await this.postProcessAndPlayLuxtts(wavPath, volume, pitchFactor, stereoDelayMs);
567096
+ await this.postProcessAndPlayLuxtts(
567097
+ wavPath,
567098
+ volume,
567099
+ pitchFactor,
567100
+ stereoDelayMs
567101
+ );
566786
567102
  }
566787
567103
  /**
566788
567104
  * Synthesize text to WAV buffer using LuxTTS (no playback).
@@ -566825,7 +567141,7 @@ if __name__ == '__main__':
566825
567141
  const pkgPath = join104(voiceDir(), "package.json");
566826
567142
  const expectedDeps = {
566827
567143
  "onnxruntime-node": "^1.21.0",
566828
- "phonemizer": "^1.2.1"
567144
+ phonemizer: "^1.2.1"
566829
567145
  };
566830
567146
  if (existsSync87(pkgPath)) {
566831
567147
  try {
@@ -566838,11 +567154,18 @@ if __name__ == '__main__':
566838
567154
  }
566839
567155
  }
566840
567156
  if (!existsSync87(pkgPath)) {
566841
- writeFileSync46(pkgPath, JSON.stringify({
566842
- name: "open-agents-voice",
566843
- private: true,
566844
- dependencies: expectedDeps
566845
- }, null, 2));
567157
+ writeFileSync46(
567158
+ pkgPath,
567159
+ JSON.stringify(
567160
+ {
567161
+ name: "open-agents-voice",
567162
+ private: true,
567163
+ dependencies: expectedDeps
567164
+ },
567165
+ null,
567166
+ 2
567167
+ )
567168
+ );
566846
567169
  }
566847
567170
  const voiceRequire = createRequire4(join104(voiceDir(), "index.js"));
566848
567171
  const probeOnnx = async () => {
@@ -566856,7 +567179,11 @@ if __name__ == '__main__':
566856
567179
  return false;
566857
567180
  }
566858
567181
  };
566859
- const onnxNodeModules = join104(voiceDir(), "node_modules", "onnxruntime-node");
567182
+ const onnxNodeModules = join104(
567183
+ voiceDir(),
567184
+ "node_modules",
567185
+ "onnxruntime-node"
567186
+ );
566860
567187
  const onnxInstalled = existsSync87(onnxNodeModules);
566861
567188
  if (onnxInstalled && !await probeOnnx()) {
566862
567189
  throw new Error(
@@ -566868,7 +567195,10 @@ if __name__ == '__main__':
566868
567195
  } catch {
566869
567196
  renderInfo2("Installing ONNX runtime for voice synthesis (background)...");
566870
567197
  try {
566871
- await this.asyncShell(`cd "${voiceDir()}" && npm install --no-audit --no-fund`, 12e4);
567198
+ await this.asyncShell(
567199
+ `cd "${voiceDir()}" && npm install --no-audit --no-fund`,
567200
+ 12e4
567201
+ );
566872
567202
  } catch (err) {
566873
567203
  const archHint = arch3 !== "x64" ? ` onnxruntime-node may not have prebuilt binaries for ${process.platform}-${arch3}.` : "";
566874
567204
  throw new Error(
@@ -566895,7 +567225,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`
566895
567225
  } catch {
566896
567226
  renderInfo2("Installing phonemizer for voice synthesis (background)...");
566897
567227
  try {
566898
- await this.asyncShell(`cd "${voiceDir()}" && npm install --no-audit --no-fund`, 12e4);
567228
+ await this.asyncShell(
567229
+ `cd "${voiceDir()}" && npm install --no-audit --no-fund`,
567230
+ 12e4
567231
+ );
566899
567232
  const phonemizerMod = voiceRequire("phonemizer");
566900
567233
  this.phonemizeFn = phonemizerMod.phonemize ?? phonemizerMod.default?.phonemize ?? phonemizerMod;
566901
567234
  } catch (err) {
@@ -566921,17 +567254,24 @@ Error: ${err instanceof Error ? err.message : String(err)}`
566921
567254
  if (!existsSync87(configPath2)) {
566922
567255
  renderInfo2(`Downloading ${model.label} voice config...`);
566923
567256
  const configResp = await fetch(model.configUrl);
566924
- if (!configResp.ok) throw new Error(`Failed to download config: HTTP ${configResp.status}`);
567257
+ if (!configResp.ok)
567258
+ throw new Error(`Failed to download config: HTTP ${configResp.status}`);
566925
567259
  const configText = await configResp.text();
566926
567260
  writeFileSync46(configPath2, configText);
566927
567261
  }
566928
567262
  if (!existsSync87(onnxPath)) {
566929
- renderInfo2(`Downloading ${model.label} voice model (this may take a minute)...`);
567263
+ renderInfo2(
567264
+ `Downloading ${model.label} voice model (this may take a minute)...`
567265
+ );
566930
567266
  const onnxResp = await fetch(model.onnxUrl);
566931
- if (!onnxResp.ok) throw new Error(`Failed to download model: HTTP ${onnxResp.status}`);
567267
+ if (!onnxResp.ok)
567268
+ throw new Error(`Failed to download model: HTTP ${onnxResp.status}`);
566932
567269
  const reader = onnxResp.body?.getReader();
566933
567270
  if (!reader) throw new Error("No response body");
566934
- const contentLength = parseInt(onnxResp.headers.get("content-length") || "0", 10);
567271
+ const contentLength = parseInt(
567272
+ onnxResp.headers.get("content-length") || "0",
567273
+ 10
567274
+ );
566935
567275
  const chunks = [];
566936
567276
  let received = 0;
566937
567277
  while (true) {
@@ -566942,13 +567282,17 @@ Error: ${err instanceof Error ? err.message : String(err)}`
566942
567282
  if (contentLength > 0) {
566943
567283
  const pct = Math.round(received / contentLength * 100);
566944
567284
  if (pct === 25 || pct === 50 || pct === 75 || pct === 100) {
566945
- renderInfo2(` ${pct}% (${formatBytes2(received)} / ${formatBytes2(contentLength)})`);
567285
+ renderInfo2(
567286
+ ` ${pct}% (${formatBytes2(received)} / ${formatBytes2(contentLength)})`
567287
+ );
566946
567288
  }
566947
567289
  }
566948
567290
  }
566949
567291
  const fullBuffer = Buffer.concat(chunks);
566950
567292
  writeFileSync46(onnxPath, fullBuffer);
566951
- renderInfo2(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
567293
+ renderInfo2(
567294
+ `${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`
567295
+ );
566952
567296
  }
566953
567297
  }
566954
567298
  // -------------------------------------------------------------------------