open-agents-ai 0.185.30 → 0.185.31

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.
Files changed (2) hide show
  1. package/dist/index.js +115 -26
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -41270,6 +41270,8 @@ __export(personaplex_exports, {
41270
41270
  clonePersonaPlexVoice: () => clonePersonaPlexVoice,
41271
41271
  detectPersonaPlexCapability: () => detectPersonaPlexCapability,
41272
41272
  getPersonaPlexWSUrl: () => getPersonaPlexWSUrl,
41273
+ getWeightRepoInfo: () => getWeightRepoInfo,
41274
+ getWeightTier: () => getWeightTier,
41273
41275
  installPersonaPlex: () => installPersonaPlex,
41274
41276
  isPersonaPlexInstalled: () => isPersonaPlexInstalled,
41275
41277
  isPersonaPlexRunning: () => isPersonaPlexRunning,
@@ -41284,6 +41286,13 @@ import { join as join54, dirname as dirname18 } from "node:path";
41284
41286
  import { homedir as homedir13 } from "node:os";
41285
41287
  import { execSync as execSync27, spawn as spawn19 } from "node:child_process";
41286
41288
  import { fileURLToPath as fileURLToPath11 } from "node:url";
41289
+ function selectWeightTier(vramGB) {
41290
+ if (vramGB >= 48)
41291
+ return "original";
41292
+ if (vramGB >= 16)
41293
+ return "nf4";
41294
+ return "turbo2bit";
41295
+ }
41287
41296
  function detectPersonaPlexCapability() {
41288
41297
  try {
41289
41298
  const nvsmi = execSync27("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
@@ -41292,24 +41301,23 @@ function detectPersonaPlexCapability() {
41292
41301
  stdio: "pipe"
41293
41302
  }).trim();
41294
41303
  if (!nvsmi) {
41295
- return { supported: false, reason: "No NVIDIA GPU detected", gpuName: "", vramGB: 0 };
41304
+ return { supported: false, reason: "No NVIDIA GPU detected", gpuName: "", vramGB: 0, weightTier: "turbo2bit", needsHfToken: false };
41296
41305
  }
41297
41306
  const [gpuName, vramMB] = nvsmi.split("\n")[0].split(", ");
41298
- const vramGB = parseInt(vramMB ?? "0", 10) / 1024;
41299
- if (vramGB < 16) {
41300
- const isJetson = /orin|tegra|jetson/i.test(gpuName ?? "");
41301
- if (isJetson) {
41302
- try {
41303
- const memInfo = execSync27("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
41304
- const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
41305
- const totalGB = memKB / 1024 / 1024;
41306
- if (totalGB >= 32) {
41307
- return { supported: true, reason: `Jetson unified memory (${totalGB.toFixed(0)}GB total)`, gpuName: gpuName ?? "", vramGB: totalGB };
41308
- }
41309
- } catch {
41310
- }
41307
+ let vramGB = parseInt(vramMB ?? "0", 10) / 1024;
41308
+ const isJetson = /orin|tegra|jetson/i.test(gpuName ?? "");
41309
+ if (isJetson) {
41310
+ try {
41311
+ const memInfo = execSync27("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
41312
+ const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
41313
+ const totalGB = memKB / 1024 / 1024;
41314
+ if (totalGB > vramGB)
41315
+ vramGB = totalGB;
41316
+ } catch {
41311
41317
  }
41312
- return { supported: false, reason: `GPU has ${vramGB.toFixed(1)}GB VRAM (need \u226516GB)`, gpuName: gpuName ?? "", vramGB };
41318
+ }
41319
+ if (vramGB < 8) {
41320
+ return { supported: false, reason: `GPU has ${vramGB.toFixed(1)}GB VRAM (need \u22658GB for 2-bit weights)`, gpuName: gpuName ?? "", vramGB, weightTier: "turbo2bit", needsHfToken: false };
41313
41321
  }
41314
41322
  try {
41315
41323
  execSync27('python3 -c "import torch; assert torch.cuda.is_available()"', {
@@ -41317,11 +41325,22 @@ function detectPersonaPlexCapability() {
41317
41325
  stdio: "pipe"
41318
41326
  });
41319
41327
  } catch {
41320
- return { supported: false, reason: "PyTorch CUDA not available", gpuName: gpuName ?? "", vramGB };
41328
+ const tier2 = selectWeightTier(vramGB);
41329
+ return { supported: false, reason: "PyTorch CUDA not available", gpuName: gpuName ?? "", vramGB, weightTier: tier2, needsHfToken: WEIGHT_REPOS[tier2].needsToken };
41321
41330
  }
41322
- return { supported: true, reason: "OK", gpuName: gpuName ?? "", vramGB };
41331
+ const tier = selectWeightTier(vramGB);
41332
+ const hasHfToken = !!(process.env["HF_TOKEN"] || process.env["HUGGING_FACE_HUB_TOKEN"]);
41333
+ const effectiveTier = tier === "original" && !hasHfToken ? "nf4" : tier;
41334
+ return {
41335
+ supported: true,
41336
+ reason: `OK \u2014 ${effectiveTier} weights (${WEIGHT_REPOS[effectiveTier].sizeGB}GB)`,
41337
+ gpuName: gpuName ?? "",
41338
+ vramGB,
41339
+ weightTier: effectiveTier,
41340
+ needsHfToken: WEIGHT_REPOS[effectiveTier].needsToken
41341
+ };
41323
41342
  } catch {
41324
- return { supported: false, reason: "nvidia-smi not found", gpuName: "", vramGB: 0 };
41343
+ return { supported: false, reason: "nvidia-smi not found", gpuName: "", vramGB: 0, weightTier: "turbo2bit", needsHfToken: false };
41325
41344
  }
41326
41345
  }
41327
41346
  function isPersonaPlexRunning() {
@@ -41348,7 +41367,19 @@ function getPersonaPlexWSUrl() {
41348
41367
  function isPersonaPlexInstalled() {
41349
41368
  return existsSync37(join54(PERSONAPLEX_DIR, "model_ready"));
41350
41369
  }
41351
- async function installPersonaPlex(onInfo) {
41370
+ function getWeightTier() {
41371
+ const tierFile = join54(PERSONAPLEX_DIR, "weight_tier");
41372
+ if (existsSync37(tierFile)) {
41373
+ const saved = readFileSync28(tierFile, "utf8").trim();
41374
+ if (saved in WEIGHT_REPOS)
41375
+ return saved;
41376
+ }
41377
+ return detectPersonaPlexCapability().weightTier;
41378
+ }
41379
+ function getWeightRepoInfo(tier) {
41380
+ return WEIGHT_REPOS[tier];
41381
+ }
41382
+ async function installPersonaPlex(onInfo, weightTier) {
41352
41383
  const log = onInfo ?? (() => {
41353
41384
  });
41354
41385
  mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
@@ -41456,12 +41487,64 @@ async function installPersonaPlex(onInfo) {
41456
41487
  execSync27(`"${pip}" install --quiet pyloudnorm noisereduce torchaudio`, { timeout: 12e4, stdio: "pipe" });
41457
41488
  } catch {
41458
41489
  }
41459
- log("PersonaPlex installed. Model will download on first launch (~14GB).");
41460
- if (isAarch64) {
41461
- log("ARM64: On first run, weights will load in INT4 mode for real-time performance.");
41490
+ const tier = weightTier ?? detectPersonaPlexCapability().weightTier;
41491
+ const repoInfo = WEIGHT_REPOS[tier];
41492
+ log(`Weight tier: ${tier} (${repoInfo.sizeGB}GB) \u2014 ${repoInfo.needsToken ? "requires HF_TOKEN" : "public, no token needed"}`);
41493
+ log(`Downloading PersonaPlex weights (${repoInfo.sizeGB}GB)...`);
41494
+ try {
41495
+ const tokenArg = repoInfo.needsToken ? "" : "--token ''";
41496
+ const dlCmd = `"${python}" -c "from huggingface_hub import hf_hub_download; f=hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}); print(f)"`;
41497
+ const weightPath = execSync27(dlCmd, {
41498
+ encoding: "utf8",
41499
+ timeout: 6e5,
41500
+ stdio: "pipe",
41501
+ env: { ...process.env }
41502
+ }).trim();
41503
+ log(`Weights downloaded: ${repoInfo.file}`);
41504
+ if (tier !== "original") {
41505
+ log("Downloading Mimi codec and tokenizer...");
41506
+ try {
41507
+ const hasToken = !!(process.env["HF_TOKEN"] || process.env["HUGGING_FACE_HUB_TOKEN"]);
41508
+ if (hasToken) {
41509
+ execSync27(`"${python}" -c "from huggingface_hub import hf_hub_download; hf_hub_download('nvidia/personaplex-7b-v1', 'tokenizer_spm_32k_3.model'); hf_hub_download('nvidia/personaplex-7b-v1', 'tokenizer-e351c8d8-checkpoint125.safetensors')"`, {
41510
+ timeout: 3e5,
41511
+ stdio: "pipe"
41512
+ });
41513
+ log("Codec + tokenizer downloaded.");
41514
+ } else {
41515
+ log("Note: Mimi codec needs HF_TOKEN on first run (set HF_TOKEN env var).");
41516
+ log("Weights themselves are public \u2014 no token needed for the model.");
41517
+ }
41518
+ } catch {
41519
+ }
41520
+ }
41521
+ } catch (err) {
41522
+ const msg = err instanceof Error ? err.message : String(err);
41523
+ if (repoInfo.needsToken && /401|403|gated|unauthorized/i.test(msg)) {
41524
+ log(`HF_TOKEN required for ${tier} weights. Set HF_TOKEN or accept license at https://huggingface.co/${repoInfo.repo}`);
41525
+ if (tier === "original") {
41526
+ log("Auto-downgrading to INT4 weights (no token required)...");
41527
+ const nf4 = WEIGHT_REPOS["nf4"];
41528
+ try {
41529
+ execSync27(`"${python}" -c "from huggingface_hub import hf_hub_download; hf_hub_download('${nf4.repo}', '${nf4.file}', token=False)"`, {
41530
+ timeout: 6e5,
41531
+ stdio: "pipe"
41532
+ });
41533
+ writeFileSync16(join54(PERSONAPLEX_DIR, "weight_tier"), "nf4");
41534
+ log(`Downloaded INT4 weights instead (${nf4.sizeGB}GB, public).`);
41535
+ } catch {
41536
+ log("Weight download failed.");
41537
+ return false;
41538
+ }
41539
+ }
41540
+ } else {
41541
+ log(`Weight download failed: ${msg}`);
41542
+ log("Weights will download on first server launch.");
41543
+ }
41462
41544
  }
41545
+ writeFileSync16(join54(PERSONAPLEX_DIR, "weight_tier"), tier);
41463
41546
  writeFileSync16(join54(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
41464
- log("PersonaPlex installed successfully.");
41547
+ log(`PersonaPlex installed (${tier} tier). Use /call to start voice session.`);
41465
41548
  return true;
41466
41549
  }
41467
41550
  async function startPersonaPlexDaemon(onInfo) {
@@ -41784,10 +41867,11 @@ async function autoSetupPersonaPlex(onInfo) {
41784
41867
  log(`PersonaPlex not available: ${caps.reason}`);
41785
41868
  return null;
41786
41869
  }
41787
- log(`GPU: ${caps.gpuName} (${caps.vramGB.toFixed(0)}GB) \u2014 PersonaPlex compatible`);
41870
+ const tierInfo = WEIGHT_REPOS[caps.weightTier];
41871
+ log(`GPU: ${caps.gpuName} (${caps.vramGB.toFixed(0)}GB) \u2192 ${caps.weightTier} weights (${tierInfo.sizeGB}GB${caps.needsHfToken ? "" : ", no HF token needed"})`);
41788
41872
  if (!isPersonaPlexInstalled()) {
41789
41873
  log("Installing PersonaPlex (first time setup)...");
41790
- const ok = await installPersonaPlex(log);
41874
+ const ok = await installPersonaPlex(log, caps.weightTier);
41791
41875
  if (!ok) {
41792
41876
  log("PersonaPlex installation failed.");
41793
41877
  return null;
@@ -41807,11 +41891,16 @@ async function autoSetupPersonaPlex(onInfo) {
41807
41891
  }
41808
41892
  return await startPersonaPlexDaemon(log);
41809
41893
  }
41810
- var PERSONAPLEX_DIR, PID_FILE, PORT_FILE, LOG_FILE, CUSTOM_VOICES_DIR;
41894
+ var WEIGHT_REPOS, PERSONAPLEX_DIR, PID_FILE, PORT_FILE, LOG_FILE, CUSTOM_VOICES_DIR;
41811
41895
  var init_personaplex = __esm({
41812
41896
  "packages/cli/dist/tui/personaplex.js"() {
41813
41897
  "use strict";
41814
41898
  init_render();
41899
+ WEIGHT_REPOS = {
41900
+ original: { repo: "nvidia/personaplex-7b-v1", file: "model.safetensors", sizeGB: 15.6, needsToken: true },
41901
+ nf4: { repo: "cudabenchmarktest/personaplex-7b-nf4", file: "model-nf4.safetensors", sizeGB: 4.1, needsToken: false },
41902
+ turbo2bit: { repo: "cudabenchmarktest/personaplex-7b-turbo2bit", file: "model-turbo2bit.safetensors", sizeGB: 2.1, needsToken: false }
41903
+ };
41815
41904
  PERSONAPLEX_DIR = join54(homedir13(), ".open-agents", "voice", "personaplex");
41816
41905
  PID_FILE = join54(PERSONAPLEX_DIR, "daemon.pid");
41817
41906
  PORT_FILE = join54(PERSONAPLEX_DIR, "daemon.port");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.185.30",
3
+ "version": "0.185.31",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",