turbollm 1.6.3 → 1.6.4

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 (88) hide show
  1. package/README.md +8 -5
  2. package/dist/cli.js +116 -13
  3. package/dist/webdist/assets/{AgentsScreen-DSJoisHr.js → AgentsScreen-z7V9yJTT.js} +1 -1
  4. package/dist/webdist/assets/ChatScreen-7b_l3eo1.js +29 -0
  5. package/dist/webdist/assets/CustomizeScreen-CAQemkBC.js +4 -0
  6. package/dist/webdist/assets/{DeveloperScreen-fnTDP0tf.js → DeveloperScreen-BfW2INcc.js} +1 -1
  7. package/dist/webdist/assets/{EnginesScreen-rlz0E1mk.js → EnginesScreen-DeVQWBY-.js} +1 -1
  8. package/dist/webdist/assets/{ModelDetailDialog-b1xxFqb8.js → ModelDetailDialog-CQxlHshX.js} +14 -14
  9. package/dist/webdist/assets/{ModelDirs-DPJoCOcI.js → ModelDirs-D_Pl9O4e.js} +1 -1
  10. package/dist/webdist/assets/{ModelsScreen-BQF-ZHhj.js → ModelsScreen-CVyA8shA.js} +2 -2
  11. package/dist/webdist/assets/SettingsScreen-DVJQTfi8.js +1 -0
  12. package/dist/webdist/assets/{arc-DJj3Lyu5.js → arc-BMLeTMlL.js} +1 -1
  13. package/dist/webdist/assets/{architectureDiagram-3BPJPVTR-BcgkjjsC.js → architectureDiagram-3BPJPVTR-CG46ZIfD.js} +1 -1
  14. package/dist/webdist/assets/{arrow-left-C8---sig.js → arrow-left-ClFIxfDf.js} +1 -1
  15. package/dist/webdist/assets/{blockDiagram-GPEHLZMM-C5iJ2c-N.js → blockDiagram-GPEHLZMM-Ct5vmWMX.js} +1 -1
  16. package/dist/webdist/assets/{c4Diagram-AAUBKEIU-BnsiE4U5.js → c4Diagram-AAUBKEIU-CAC8CrWx.js} +1 -1
  17. package/dist/webdist/assets/channel-3lZ_p1cA.js +1 -0
  18. package/dist/webdist/assets/check-DQ6z92nS.js +1 -0
  19. package/dist/webdist/assets/{chevron-right-C18nBpLx.js → chevron-right-DGMGRuqq.js} +1 -1
  20. package/dist/webdist/assets/{chunk-2J33WTMH-D_Hm4Lii.js → chunk-2J33WTMH-Boq1pvZ0.js} +1 -1
  21. package/dist/webdist/assets/{chunk-4BX2VUAB-Cooqn_zH.js → chunk-4BX2VUAB-BxOCNoyH.js} +1 -1
  22. package/dist/webdist/assets/{chunk-55IACEB6-C2XDZnC0.js → chunk-55IACEB6-xrXYZmka.js} +1 -1
  23. package/dist/webdist/assets/{chunk-727SXJPM-CCEeI48H.js → chunk-727SXJPM-BFEC_Ow4.js} +1 -1
  24. package/dist/webdist/assets/{chunk-AQP2D5EJ-7FdU3GXV.js → chunk-AQP2D5EJ-DFTdPrur.js} +1 -1
  25. package/dist/webdist/assets/{chunk-FMBD7UC4-Dpyt8woB.js → chunk-FMBD7UC4-D41UJ-1d.js} +1 -1
  26. package/dist/webdist/assets/{chunk-ND2GUHAM-ildY-Wx8.js → chunk-ND2GUHAM-BeavMz7M.js} +1 -1
  27. package/dist/webdist/assets/{chunk-QZHKN3VN-DfdDD-h6.js → chunk-QZHKN3VN-CUHX28cH.js} +1 -1
  28. package/dist/webdist/assets/{circle-check-C9nr7e7f.js → circle-check-B6TnDVnx.js} +1 -1
  29. package/dist/webdist/assets/{circle-x-CrulSiVz.js → circle-x-zQ-pYHWJ.js} +1 -1
  30. package/dist/webdist/assets/classDiagram-4FO5ZUOK-qxOwHzBq.js +1 -0
  31. package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-qxOwHzBq.js +1 -0
  32. package/dist/webdist/assets/{common-B6XHnwTG.js → common-stymjhMS.js} +1 -1
  33. package/dist/webdist/assets/{copy-button-Sp-U8ULJ.js → copy-button-CTWXbfiP.js} +1 -1
  34. package/dist/webdist/assets/{cose-bilkent-S5V4N54A-DggDgWVR.js → cose-bilkent-S5V4N54A-Bx_lty5d.js} +1 -1
  35. package/dist/webdist/assets/{dagre-BM42HDAG-C3owUH7E.js → dagre-BM42HDAG-0sn0yk1w.js} +1 -1
  36. package/dist/webdist/assets/{diagram-2AECGRRQ-Ch2E5js7.js → diagram-2AECGRRQ-B7dlDz_q.js} +1 -1
  37. package/dist/webdist/assets/{diagram-5GNKFQAL-DLeGX2xz.js → diagram-5GNKFQAL--tcSUKb3.js} +1 -1
  38. package/dist/webdist/assets/{diagram-KO2AKTUF-DpxkKgZH.js → diagram-KO2AKTUF-DWmLxntr.js} +1 -1
  39. package/dist/webdist/assets/{diagram-LMA3HP47-ia4luRgC.js → diagram-LMA3HP47-DBOpUcpv.js} +1 -1
  40. package/dist/webdist/assets/{diagram-OG6HWLK6-BMmkGNMK.js → diagram-OG6HWLK6-CdRckAFu.js} +1 -1
  41. package/dist/webdist/assets/{dialog-DLncpxeJ.js → dialog-D-C0Tc3g.js} +1 -1
  42. package/dist/webdist/assets/dropdown-menu-Co-guMgc.js +1 -0
  43. package/dist/webdist/assets/{erDiagram-TEJ5UH35-DkKBBG05.js → erDiagram-TEJ5UH35-Bg-nfhtr.js} +1 -1
  44. package/dist/webdist/assets/{flowDiagram-I6XJVG4X-kUtoUBI6.js → flowDiagram-I6XJVG4X-CghDUz8j.js} +1 -1
  45. package/dist/webdist/assets/{ganttDiagram-6RSMTGT7-DQReYR3Z.js → ganttDiagram-6RSMTGT7-B76rXmmo.js} +1 -1
  46. package/dist/webdist/assets/{gitGraphDiagram-PVQCEYII-B2kU7JBk.js → gitGraphDiagram-PVQCEYII-DYwR4vbe.js} +1 -1
  47. package/dist/webdist/assets/index-CT5lTdUf.css +1 -0
  48. package/dist/webdist/assets/{index-CjGc01NF.js → index-DxM70nEl.js} +3 -3
  49. package/dist/webdist/assets/{infoDiagram-5YYISTIA-k1S105HR.js → infoDiagram-5YYISTIA-BvoZYlup.js} +1 -1
  50. package/dist/webdist/assets/{ishikawaDiagram-YF4QCWOH-BgPQRD_p.js → ishikawaDiagram-YF4QCWOH-D5TRR4WP.js} +1 -1
  51. package/dist/webdist/assets/{journeyDiagram-JHISSGLW-_aNOepbu.js → journeyDiagram-JHISSGLW-2aK1csut.js} +1 -1
  52. package/dist/webdist/assets/{kanban-definition-UN3LZRKU-ooXgg2sY.js → kanban-definition-UN3LZRKU-CWEMWeUg.js} +1 -1
  53. package/dist/webdist/assets/{linear-B6ijN2hK.js → linear-D7FhiD9R.js} +1 -1
  54. package/dist/webdist/assets/{mermaid.core-C39fo6yP.js → mermaid.core-DQIxkS1K.js} +4 -4
  55. package/dist/webdist/assets/{mindmap-definition-RKZ34NQL-Ci1PW-rt.js → mindmap-definition-RKZ34NQL-DaZEBIU3.js} +1 -1
  56. package/dist/webdist/assets/{pencil-CvIU0pkN.js → pencil-zupSY7XP.js} +1 -1
  57. package/dist/webdist/assets/{personas-CIW1sEuT.js → personas-DbG2zH5T.js} +3 -3
  58. package/dist/webdist/assets/{pieDiagram-4H26LBE5-SVL4rTNg.js → pieDiagram-4H26LBE5-C6AqueQK.js} +1 -1
  59. package/dist/webdist/assets/{plus-3YM8ko_h.js → plus-Ct45XaAU.js} +1 -1
  60. package/dist/webdist/assets/{quadrantDiagram-W4KKPZXB-sTVWSdlQ.js → quadrantDiagram-W4KKPZXB-C3ufHf4n.js} +1 -1
  61. package/dist/webdist/assets/{radix-9WP-OkMY.js → radix-jAkiiept.js} +8 -8
  62. package/dist/webdist/assets/{refresh-cw-BrUDSVRs.js → refresh-cw-CUUblWFA.js} +1 -1
  63. package/dist/webdist/assets/{requirementDiagram-4Y6WPE33-3R4K8jZs.js → requirementDiagram-4Y6WPE33-DKjCoTy-.js} +1 -1
  64. package/dist/webdist/assets/{sankeyDiagram-5OEKKPKP-BMozn5XV.js → sankeyDiagram-5OEKKPKP-D3Lhx_3A.js} +1 -1
  65. package/dist/webdist/assets/{save-CeI7y6CK.js → save-Cu00OCua.js} +1 -1
  66. package/dist/webdist/assets/{sequenceDiagram-3UESZ5HK-B0bhq6qo.js → sequenceDiagram-3UESZ5HK-Bg7qUaiJ.js} +1 -1
  67. package/dist/webdist/assets/{skeleton-Dm2BPYbG.js → skeleton-DAp10ou3.js} +1 -1
  68. package/dist/webdist/assets/{stateDiagram-AJRCARHV-CXaf-H6k.js → stateDiagram-AJRCARHV-CEe0Lqmt.js} +1 -1
  69. package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-BSX42oue.js +1 -0
  70. package/dist/webdist/assets/{timeline-definition-PNZ67QCA-BUO22RTP.js → timeline-definition-PNZ67QCA-ILud0hYG.js} +1 -1
  71. package/dist/webdist/assets/{trash-2-D1fUAajM.js → trash-2-Dxm0bLnm.js} +1 -1
  72. package/dist/webdist/assets/{vennDiagram-CIIHVFJN-B6l8WK-i.js → vennDiagram-CIIHVFJN-UmbDOfzC.js} +1 -1
  73. package/dist/webdist/assets/{wardley-L42UT6IY-nBQZIDHO.js → wardley-L42UT6IY-CJPgfZGE.js} +1 -1
  74. package/dist/webdist/assets/{wardleyDiagram-YWT4CUSO-Bl5nA5Sj.js → wardleyDiagram-YWT4CUSO-COswOSfT.js} +1 -1
  75. package/dist/webdist/assets/{wrench-2q903Ji-.js → wrench-BtDcuPD1.js} +1 -1
  76. package/dist/webdist/assets/{xychartDiagram-2RQKCTM6-BfRB7FkA.js → xychartDiagram-2RQKCTM6-pBHtZvWZ.js} +1 -1
  77. package/dist/webdist/index.html +3 -3
  78. package/package.json +1 -1
  79. package/dist/webdist/assets/ChatScreen-CPTQTPDq.js +0 -29
  80. package/dist/webdist/assets/CustomizeScreen-CveMZwK6.js +0 -4
  81. package/dist/webdist/assets/SettingsScreen-Z4AoirUg.js +0 -1
  82. package/dist/webdist/assets/alert-dialog-DzOwQljM.js +0 -1
  83. package/dist/webdist/assets/channel-DidzH_JR.js +0 -1
  84. package/dist/webdist/assets/check-CRM4LOGX.js +0 -1
  85. package/dist/webdist/assets/classDiagram-4FO5ZUOK-DrgybMsY.js +0 -1
  86. package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-DrgybMsY.js +0 -1
  87. package/dist/webdist/assets/index-5NYGYU_t.css +0 -1
  88. package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-BYFRKnq-.js +0 -1
package/README.md CHANGED
@@ -148,7 +148,8 @@ the detail:
148
148
  picker so you can choose which one to download.
149
149
  - **Quant recommendation per GPU** and a **VRAM-fit verdict** so you pick a quant that
150
150
  actually fits before you commit.
151
- - **Primary download folder**, real-time **measured t/s per model**, and **delete-from-disk**.
151
+ - **Primary download folder**, real-time **measured t/s per model**, **delete-from-disk**, and
152
+ **pin your favourites to the top of the list**.
152
153
 
153
154
  </details>
154
155
 
@@ -158,15 +159,17 @@ the detail:
158
159
  <br/>
159
160
 
160
161
  - **Auto-benchmark on load** derives fast defaults for your exact GPU.
161
- - **Recommended sampling from the model card** — auto-tune reads the model's Hugging Face card
162
- (falling back to the original model behind a requant) and prefills the author's recommended
163
- `temperature / top_k / top_p / min_p`. No recommendation your sampling is left untouched.
162
+ - **Recommended sampling from Hugging Face** — auto-tune checks a repo's structured params /
163
+ `generation_config.json` sidecar first when the quantizer publishes one (exact values, no
164
+ guessing), then falls back to reading the model's card (and the original model behind a
165
+ requant) and prefills the author's recommended `temperature / top_k / top_p / min_p`. No
166
+ recommendation → your sampling is left untouched.
164
167
  - **Real measured tokens/sec** in the model list — **live** while generating, **last-session**
165
168
  when idle (never a synthetic estimate).
166
169
  - **Full load-parameter UI**, a superset of what other tools expose: context length, GPU offload
167
170
  (`-ngl`), **MoE CPU-offload (`--n-cpu-moe`)**, parallel slots, **KV-cache quant type** (incl.
168
171
  low-bit on supporting forks), CPU threads, flash attention, and **speculative decoding (NextN /
169
- MTP / draft)**.
172
+ MTP / draft, with a configurable draft min/max window)**.
170
173
  - **Fast by default:** flash attention on, NextN self-speculative decoding on for models that
171
174
  carry a draft head, threads auto — safely gated to what your engine actually accepts.
172
175
  - **Multi-GPU, per model** — split a model across cards (layer/row split + main-GPU pick on
package/dist/cli.js CHANGED
@@ -2649,7 +2649,10 @@ function detectGpus() {
2649
2649
  const [name, mb] = line.split(",");
2650
2650
  return { name: (name ?? "").trim(), vramMb: parseInt((mb ?? "").trim(), 10) || 0, vendor: "nvidia" };
2651
2651
  }).filter((g) => g.vramMb > 0);
2652
- if (gpus.length) return gpus;
2652
+ if (gpus.length) {
2653
+ console.log(`[sysinfo] nvidia-smi enumerated ${gpus.length} GPU(s): ${gpus.map((g) => `${g.name}=${g.vramMb}MB`).join(", ")}`);
2654
+ return gpus;
2655
+ }
2653
2656
  } catch {
2654
2657
  }
2655
2658
  if (process.platform === "darwin") {
@@ -2670,6 +2673,11 @@ function detectGpus() {
2670
2673
  return [];
2671
2674
  }
2672
2675
  function enumWindowsGpus() {
2676
+ try {
2677
+ const amd = rocmSmiGpus();
2678
+ if (amd.length) return amd;
2679
+ } catch {
2680
+ }
2673
2681
  const ps = 'Get-CimInstance Win32_VideoController | ForEach-Object { "$($_.Name)|$($_.AdapterRAM)" }';
2674
2682
  const out = execFileSync2("powershell", ["-NoProfile", "-NonInteractive", "-Command", ps], {
2675
2683
  timeout: 8e3,
@@ -2682,6 +2690,37 @@ function enumWindowsGpus() {
2682
2690
  return { name: nm, vramMb: bytes > 0 ? Math.round(bytes / 1e6) : 0, vendor: classifyVendor(nm) };
2683
2691
  }).filter((g) => g.name && g.vendor !== "unknown");
2684
2692
  }
2693
+ function rocmSmiGpus() {
2694
+ const memJson = execFileSync2("rocm-smi", ["--showmeminfo", "vram", "--json"], {
2695
+ timeout: 8e3,
2696
+ windowsHide: true
2697
+ }).toString();
2698
+ let nameJson = "";
2699
+ try {
2700
+ nameJson = execFileSync2("rocm-smi", ["--showproductname", "--json"], {
2701
+ timeout: 8e3,
2702
+ windowsHide: true
2703
+ }).toString();
2704
+ } catch {
2705
+ }
2706
+ return parseRocmSmi(memJson, nameJson);
2707
+ }
2708
+ function parseRocmSmi(memJson, nameJson = "") {
2709
+ const mem = JSON.parse(memJson);
2710
+ let names = {};
2711
+ if (nameJson.trim()) names = JSON.parse(nameJson);
2712
+ const gpus = [];
2713
+ for (const [card, fields] of Object.entries(mem)) {
2714
+ const totalKey = Object.keys(fields).find((k) => /VRAM Total Memory/i.test(k));
2715
+ const bytes = totalKey ? parseInt(String(fields[totalKey]).trim(), 10) || 0 : 0;
2716
+ if (bytes <= 0) continue;
2717
+ const nameFields = names[card] ?? {};
2718
+ const nameKey = Object.keys(nameFields).find((k) => /(Card Series|Card Model|Product Name|Device Name)/i.test(k));
2719
+ const name = (nameKey ? String(nameFields[nameKey]).trim() : "") || "AMD Radeon GPU";
2720
+ gpus.push({ name, vramMb: Math.round(bytes / 1e6), vendor: "amd" });
2721
+ }
2722
+ return gpus;
2723
+ }
2685
2724
  function enumLinuxGpus() {
2686
2725
  const out = execFileSync2("sh", ["-c", "lspci -mm 2>/dev/null | grep -iE 'VGA|3D|Display'"], {
2687
2726
  timeout: 8e3
@@ -3303,8 +3342,10 @@ var Scanner = class {
3303
3342
  const m = basename(f.path).match(SPLIT_RE);
3304
3343
  if (m) {
3305
3344
  const gkey = `${m[1]}|${m[3]}`;
3306
- const g = splits.get(gkey) ?? { shards: [], total: Number(m[3]) };
3307
- g.shards.push(f);
3345
+ const g = splits.get(gkey) ?? { shards: /* @__PURE__ */ new Map(), total: Number(m[3]) };
3346
+ const idx = Number(m[2]);
3347
+ const prev = g.shards.get(idx);
3348
+ if (!prev || f.path.localeCompare(prev.path) < 0) g.shards.set(idx, f);
3308
3349
  splits.set(gkey, g);
3309
3350
  } else {
3310
3351
  singles.push(f);
@@ -3315,10 +3356,17 @@ var Scanner = class {
3315
3356
  await tick();
3316
3357
  }
3317
3358
  for (const { shards, total } of splits.values()) {
3318
- shards.sort((a, b) => a.path.localeCompare(b.path));
3319
- const first = shards[0];
3320
- const totalSize = shards.reduce((s, x) => s + x.size, 0);
3321
- const incomplete = shards.length !== total;
3359
+ const present = [...shards.values()].sort((a, b) => a.path.localeCompare(b.path));
3360
+ const first = present[0];
3361
+ const totalSize = present.reduce((s, x) => s + x.size, 0);
3362
+ let incomplete = shards.size !== total;
3363
+ if (!incomplete) {
3364
+ for (let i = 1; i <= total; i++)
3365
+ if (!shards.has(i)) {
3366
+ incomplete = true;
3367
+ break;
3368
+ }
3369
+ }
3322
3370
  entries.push(await this.entryFor(first.path, totalSize, first.mtime, dir, mmprojPath, incomplete));
3323
3371
  await tick();
3324
3372
  }
@@ -3803,7 +3851,7 @@ function profileToArgs(p, m, caps, cores = 0) {
3803
3851
  if (nextnVal) a.push("--spec-type", nextnVal, "--model-draft", m.path);
3804
3852
  } else if (p.speculative === "draft" && p.draftModelPath && has("--model-draft")) {
3805
3853
  if (specType) a.push("--spec-type", "draft");
3806
- a.push("--model-draft", p.draftModelPath, "--draft-max", "16", "--draft-min", "1");
3854
+ a.push("--model-draft", p.draftModelPath, "--draft-max", String(p.draftMax ?? 16), "--draft-min", String(p.draftMin ?? 1));
3807
3855
  }
3808
3856
  if (p.sampling.temp !== 0.8 && has("--temp")) a.push("--temp", String(p.sampling.temp));
3809
3857
  if (p.sampling.topP !== 0.95 && has("--top-p")) a.push("--top-p", String(p.sampling.topP));
@@ -4303,6 +4351,31 @@ var HfClient = class {
4303
4351
  fetchModelCard(repo) {
4304
4352
  return this.getCard(repo, CARD_EXTRACT_MAX);
4305
4353
  }
4354
+ /** Fetch a repo's structured generation-params sidecar, if it has one — some quantizers
4355
+ * (e.g. unsloth) publish a root-level `params` JSON file with the exact recommended
4356
+ * sampling values (`{"temperature":1.0,"top_k":0,"top_p":1.0,"min_p":0.0,"stop":[…]}`)
4357
+ * alongside the GGUF shards. When present this is a strictly better signal than the
4358
+ * README heuristic/LLM extraction (exact values, no parsing/inference needed) — auto-tune
4359
+ * tries it first. Tries `params` then the more standard `generation_config.json` name.
4360
+ * Best-effort: '' when neither exists or the repo is unreachable, never throws. */
4361
+ async fetchGenerationParams(repo) {
4362
+ for (const name of ["params", "generation_config.json"]) {
4363
+ const url = `${BASE}/${repo}/raw/main/${name}`;
4364
+ const now = Date.now();
4365
+ const hit = this.cache.get(url);
4366
+ if (hit && now - hit.at < CACHE_TTL_MS) return hit.value;
4367
+ try {
4368
+ const res = await fetch(url, { headers: this.authHeaders(), redirect: "follow" });
4369
+ if (!res.ok) continue;
4370
+ const raw = await res.text();
4371
+ this.cache.set(url, { at: now, value: raw });
4372
+ return raw;
4373
+ } catch {
4374
+ continue;
4375
+ }
4376
+ }
4377
+ return "";
4378
+ }
4306
4379
  /** Resolve the upstream base model for a repo (ADR-099 base-model fallback): the `base_model`
4307
4380
  * declared in the repo's HF card metadata. Most local GGUFs are third-party requants
4308
4381
  * (lmstudio-community / unsloth / noctrex / …) whose card omits the author's recommended
@@ -4959,6 +5032,29 @@ function parseCardSampling(card) {
4959
5032
  function hasAnySampling(s) {
4960
5033
  return s.temp != null || s.topP != null || s.topK != null || s.minP != null;
4961
5034
  }
5035
+ function parseGenerationParams(raw) {
5036
+ if (!raw) return {};
5037
+ let obj;
5038
+ try {
5039
+ obj = JSON.parse(raw);
5040
+ } catch {
5041
+ return {};
5042
+ }
5043
+ if (typeof obj !== "object" || obj === null) return {};
5044
+ const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
5045
+ const out = {};
5046
+ const map = [
5047
+ ["temperature", "temp"],
5048
+ ["top_p", "topP"],
5049
+ ["top_k", "topK"],
5050
+ ["min_p", "minP"]
5051
+ ];
5052
+ for (const [jsonKey, field] of map) {
5053
+ const v = num(obj[jsonKey]);
5054
+ if (v !== null) out[field] = v;
5055
+ }
5056
+ return clampCardSampling(out);
5057
+ }
4962
5058
  function relevantCardExcerpt(card, maxLen = 8e3) {
4963
5059
  if (card.length <= maxLen) return card;
4964
5060
  const strong = /\b(?:recommended\s+(?:settings|sampling|parameters)|sampling\s+(?:settings|parameters|params)|best\s+practices?|generation\s+config)\b/i.exec(card);
@@ -5663,6 +5759,9 @@ var BenchRunner = class {
5663
5759
  const repo = inferRepoFromPath(entry.path, this.store.snapshot().modelDirs);
5664
5760
  if (!repo) return void 0;
5665
5761
  this.state = { ...this.state, step: "Reading model-card recommendations\u2026" };
5762
+ const genParams = await this.hf.fetchGenerationParams(repo).catch(() => "");
5763
+ const paramsH = parseGenerationParams(genParams);
5764
+ if (hasAnySampling(paramsH)) return paramsH;
5666
5765
  const localCard = await this.hf.fetchModelCard(repo).catch(() => "");
5667
5766
  const localH = parseCardSampling(localCard);
5668
5767
  if (hasAnySampling(localH)) return localH;
@@ -9561,10 +9660,11 @@ import { promisify as promisify5 } from "util";
9561
9660
  var execFileP5 = promisify5(execFile8);
9562
9661
  function buildEnv(toolchainDirs = []) {
9563
9662
  const dirs = toolchainDirs.map((d) => d.trim()).filter(Boolean);
9564
- if (dirs.length === 0) return { ...process.env };
9565
9663
  const env = { ...process.env };
9566
9664
  const key = Object.keys(env).find((k) => k.toLowerCase() === "path") ?? "PATH";
9567
- env[key] = [...dirs, env[key] ?? ""].filter(Boolean).join(delimiter);
9665
+ const existing = (env[key] ?? "").split(delimiter);
9666
+ const segments = [...dirs, ...existing].map((s) => s.trim()).filter(Boolean);
9667
+ if (env[key] !== void 0 || dirs.length > 0) env[key] = segments.join(delimiter);
9568
9668
  return env;
9569
9669
  }
9570
9670
  var INSTALL_URLS = {
@@ -9856,6 +9956,9 @@ async function findVcvarsall() {
9856
9956
  return null;
9857
9957
  }
9858
9958
  }
9959
+ function winComSpec() {
9960
+ return process.env.ComSpec || "cmd.exe";
9961
+ }
9859
9962
  function runStep(cmd, args, opts) {
9860
9963
  return new Promise((resolve2, reject) => {
9861
9964
  const child = spawn4(cmd, args, {
@@ -10006,7 +10109,7 @@ async function runBuild(req, hooks, signal) {
10006
10109
  if (isWindows) {
10007
10110
  const configureBat = join19(buildRoot, "_tllm_configure.bat");
10008
10111
  writeFileSync8(configureBat, vcvarsBatch(vcvars, configureArgs));
10009
- await runStep("cmd.exe", ["/c", configureBat], { cwd: buildRoot, env, signal, onLine: hooks.log });
10112
+ await runStep(winComSpec(), ["/c", configureBat], { cwd: buildRoot, env, signal, onLine: hooks.log });
10010
10113
  } else {
10011
10114
  await runStep("cmake", configureArgs, { cwd: buildRoot, env, signal, onLine: hooks.log });
10012
10115
  }
@@ -10015,7 +10118,7 @@ async function runBuild(req, hooks, signal) {
10015
10118
  if (isWindows) {
10016
10119
  const compileBat = join19(buildRoot, "_tllm_build.bat");
10017
10120
  writeFileSync8(compileBat, vcvarsBatch(vcvars, compileArgs));
10018
- await runStep("cmd.exe", ["/c", compileBat], { cwd: buildRoot, env, signal, onLine: hooks.log });
10121
+ await runStep(winComSpec(), ["/c", compileBat], { cwd: buildRoot, env, signal, onLine: hooks.log });
10019
10122
  } else {
10020
10123
  await runStep("cmake", compileArgs, { cwd: buildRoot, env, signal, onLine: hooks.log });
10021
10124
  }
@@ -10151,7 +10254,7 @@ function detectHardware(info = getSysInfo()) {
10151
10254
  (best, g) => !best || g.vramMb > best.vramMb ? g : best,
10152
10255
  void 0
10153
10256
  );
10154
- const vramMb = info.gpus.reduce((max, g) => g.vramMb > max ? g.vramMb : max, 0);
10257
+ const vramMb = ofVendor.reduce((sum, g) => sum + g.vramMb, 0);
10155
10258
  return {
10156
10259
  platform: process.platform,
10157
10260
  arch: arch2,
@@ -1,2 +1,2 @@
1
- import{j as e}from"./radix-9WP-OkMY.js";import{r as u}from"./vendor-W5GIuFcv.js";import{a as w,d as k,A as T,u as v,L as h,e as S,c as b,f as C,g as q,X as A}from"./index-CjGc01NF.js";import{P as N}from"./plus-3YM8ko_h.js";import{C as y}from"./circle-x-CrulSiVz.js";import{C as O}from"./circle-check-C9nr7e7f.js";import{W as E}from"./wrench-2q903Ji-.js";const _=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}]],D=w("circle-dot",_);const L=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 6v6l4 2",key:"mmk7yg"}]],P=w("clock",L),p={all:["agent-runs"],list:()=>[...p.all,"list"],detail:t=>[...p.all,"detail",t]};async function g(t,a){const l={Accept:"application/json",...k(),...a?.headers??{}},i=await fetch(t,{...a,headers:l});if(i.status===204)return;const r=await i.text(),o=r?JSON.parse(r):void 0;if(!i.ok){const d=o;throw new T(d?.error?.code??"http_error",d?.error?.message??`Request failed with status ${i.status}.`,i.status)}return o}async function $(){return g("/api/v1/agents/runs")}async function I(t){return g(`/api/v1/agents/runs/${t}`)}async function Q(t){return g("/api/v1/agents/runs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}async function K(t){await g(`/api/v1/agents/runs/${t}`,{method:"DELETE"})}async function*F(t,a=0,l){const i=`/api/v1/agents/runs/${t}/stream?fromSeq=${a}`,r=await fetch(i,{headers:{Accept:"text/event-stream",...k()},signal:l});if(!r.ok||!r.body)throw new Error(`Stream error: ${r.status}`);const o=r.body.getReader(),d=new TextDecoder;let m="";try{for(;;){const{done:s,value:x}=await o.read();if(s)break;m+=d.decode(x,{stream:!0});const c=m.split(`
1
+ import{j as e}from"./radix-jAkiiept.js";import{r as u}from"./vendor-W5GIuFcv.js";import{a as w,d as k,A as T,u as v,L as h,e as S,c as b,f as C,g as q,X as A}from"./index-DxM70nEl.js";import{P as N}from"./plus-Ct45XaAU.js";import{C as y}from"./circle-x-zQ-pYHWJ.js";import{C as O}from"./circle-check-B6TnDVnx.js";import{W as E}from"./wrench-BtDcuPD1.js";const _=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}]],D=w("circle-dot",_);const L=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 6v6l4 2",key:"mmk7yg"}]],P=w("clock",L),p={all:["agent-runs"],list:()=>[...p.all,"list"],detail:t=>[...p.all,"detail",t]};async function g(t,a){const l={Accept:"application/json",...k(),...a?.headers??{}},i=await fetch(t,{...a,headers:l});if(i.status===204)return;const r=await i.text(),o=r?JSON.parse(r):void 0;if(!i.ok){const d=o;throw new T(d?.error?.code??"http_error",d?.error?.message??`Request failed with status ${i.status}.`,i.status)}return o}async function $(){return g("/api/v1/agents/runs")}async function I(t){return g(`/api/v1/agents/runs/${t}`)}async function Q(t){return g("/api/v1/agents/runs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}async function K(t){await g(`/api/v1/agents/runs/${t}`,{method:"DELETE"})}async function*F(t,a=0,l){const i=`/api/v1/agents/runs/${t}/stream?fromSeq=${a}`,r=await fetch(i,{headers:{Accept:"text/event-stream",...k()},signal:l});if(!r.ok||!r.body)throw new Error(`Stream error: ${r.status}`);const o=r.body.getReader(),d=new TextDecoder;let m="";try{for(;;){const{done:s,value:x}=await o.read();if(s)break;m+=d.decode(x,{stream:!0});const c=m.split(`
2
2
  `);m=c.pop()??"";let n="message";for(const f of c){if(f.startsWith("event: ")){n=f.slice(7).trim();continue}if(f.startsWith("data: ")){const j=f.slice(6).trim();if(j==="[DONE]")return;try{const R=JSON.parse(j);if(yield{event:n,data:R},n==="done"||n==="error")return}catch{}n="message"}}}}finally{o.cancel()}}const J={queued:e.jsx(P,{size:12}),running:e.jsx(h,{size:12,className:"animate-spin"}),done:e.jsx(O,{size:12}),failed:e.jsx(y,{size:12}),cancelled:e.jsx(y,{size:12}),interrupted:e.jsx(y,{size:12})},M={queued:"text-muted",running:"text-accent",done:"text-green-500",failed:"text-red-500",cancelled:"text-muted",interrupted:"text-orange-500"};function z({status:t}){return e.jsxs("span",{className:b("flex items-center gap-1 text-[11px] capitalize",M[t]),children:[J[t],t]})}function W(t){const a=Date.now()-new Date(t).getTime();return a<6e4?"just now":a<36e5?`${Math.floor(a/6e4)}m ago`:a<864e5?`${Math.floor(a/36e5)}h ago`:new Date(t).toLocaleDateString()}const U=[{id:"web_search",label:"Web search",hint:"Search the web (needs a provider configured in Settings)"},{id:"fetch_url",label:"Fetch URL",hint:"Read the contents of a web page"},{id:"run_code",label:"Run code",hint:"Execute JS in a sandbox — no mid-run confirmation, opt in only if you trust the task"}];function B({onClose:t,onCreated:a}){const[l,i]=u.useState(""),[r,o]=u.useState(""),[d,m]=u.useState({web_search:!0,fetch_url:!0,run_code:!1}),s=C(),x=n=>m(f=>({...f,[n]:!f[n]})),c=q({mutationFn:()=>Q({title:l.slice(0,60)||"Agent run",systemPrompt:r||void 0,userMessage:l,allowedTools:Object.entries(d).filter(([,n])=>n).map(([n])=>n)}),onSuccess:n=>{s.invalidateQueries({queryKey:p.list()}),a(n.id),t()}});return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40",onClick:t,children:e.jsxs("div",{className:"w-full max-w-lg rounded-xl border border-border bg-panel p-5 shadow-xl",onClick:n=>n.stopPropagation(),children:[e.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[e.jsx("h2",{className:"text-[15px] font-semibold",children:"New agent run"}),e.jsx("button",{type:"button",onClick:t,className:"text-faint hover:text-ink",children:e.jsx(A,{size:16})})]}),e.jsx("label",{className:"mb-1 block text-[12px] text-muted",children:"Task"}),e.jsx("textarea",{autoFocus:!0,value:l,onChange:n=>i(n.target.value),placeholder:"Describe what the agent should do…",rows:4,className:"mb-3 w-full resize-none rounded-lg border border-border bg-input px-3 py-2 text-[13px] text-ink placeholder:text-faint focus:border-accent focus:outline-none"}),e.jsxs("label",{className:"mb-1 block text-[12px] text-muted",children:["System prompt ",e.jsx("span",{className:"text-faint",children:"(optional)"})]}),e.jsx("textarea",{value:r,onChange:n=>o(n.target.value),placeholder:"You are a helpful assistant…",rows:2,className:"mb-4 w-full resize-none rounded-lg border border-border bg-input px-3 py-2 text-[13px] text-ink placeholder:text-faint focus:border-accent focus:outline-none"}),e.jsx("label",{className:"mb-1.5 block text-[12px] text-muted",children:"Tools"}),e.jsx("div",{className:"mb-4 space-y-1.5",children:U.map(n=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 rounded-lg border border-border px-2.5 py-2 hover:bg-panel-2",children:[e.jsx("input",{type:"checkbox",checked:d[n.id],onChange:()=>x(n.id),className:"mt-0.5 accent-[var(--accent)]"}),e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block text-[13px] font-medium text-ink",children:n.label}),e.jsx("span",{className:"block text-[11px] leading-snug text-faint",children:n.hint})]})]},n.id))}),e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:t,className:"rounded-lg px-3 py-1.5 text-[13px] text-muted hover:text-ink",children:"Cancel"}),e.jsxs("button",{type:"button",disabled:!l.trim()||c.isPending,onClick:()=>c.mutate(),className:"flex items-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-[13px] font-medium text-white disabled:opacity-50",children:[c.isPending?e.jsx(h,{size:13,className:"animate-spin"}):e.jsx(S,{size:13}),"Run agent"]})]}),c.isError&&e.jsx("p",{className:"mt-2 text-[12px]",style:{color:"var(--err)"},children:c.error.message})]})})}function X({call:t}){const[a,l]=u.useState(!1),i=typeof t.args?.query=="string"?t.args.query:typeof t.args?.url=="string"?t.args.url:JSON.stringify(t.args??{});return e.jsxs("div",{className:"w-full max-w-[85%] rounded-lg border border-border bg-panel px-2.5 py-1.5 text-[12px]",children:[e.jsxs("button",{type:"button",onClick:()=>l(r=>!r),className:"flex w-full items-center gap-1.5 text-left text-muted hover:text-ink",children:[e.jsx(E,{size:12,className:"shrink-0 text-accent"}),e.jsx("span",{className:"font-medium text-ink",children:t.name}),e.jsx("span",{className:"truncate text-faint",children:i})]}),a&&e.jsx("pre",{className:"mt-1.5 max-h-48 overflow-auto whitespace-pre-wrap break-words rounded bg-panel-2 p-2 text-[11px] text-muted",children:t.result})]})}function H({run:t}){const a=C(),l=u.useRef(null),[i,r]=u.useState(""),o=u.useRef(null),d=q({mutationFn:()=>K(t.id),onSuccess:()=>{a.invalidateQueries({queryKey:p.list()})}});u.useEffect(()=>{if(t.status!=="running"&&t.status!=="queued")return;const s=new AbortController;l.current=s;let x="";return(async()=>{try{for await(const c of F(t.id,0,s.signal))if(c.event==="delta")x+=c.data.delta,r(x);else if(c.event==="done"||c.event==="error"){r(""),a.invalidateQueries({queryKey:p.detail(t.id)}),a.invalidateQueries({queryKey:p.list()});break}}catch{}})(),()=>{s.abort(),l.current=null}},[t.id,t.status,a]),u.useEffect(()=>{o.current?.scrollIntoView({behavior:"smooth"})},[i,t.messages?.length]);const m=t.messages??[];return e.jsxs("div",{className:"flex h-full flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-border px-4 py-2.5",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[14px] font-medium text-ink",children:t.title}),e.jsx(z,{status:t.status})]}),(t.status==="running"||t.status==="queued")&&e.jsx("button",{type:"button",onClick:()=>d.mutate(),className:"rounded-lg border border-border px-3 py-1 text-[12px] text-muted transition-colors hover:border-red-400 hover:text-red-500",children:d.isPending?e.jsx(h,{size:12,className:"inline animate-spin"}):"Cancel"})]}),e.jsxs("div",{className:"flex-1 space-y-3 overflow-y-auto p-4",children:[m.map(s=>e.jsxs("div",{className:b("flex flex-col gap-1.5",s.role==="user"?"items-end":"items-start"),children:[s.toolCalls?.map(x=>e.jsx(X,{call:x},x.id)),(s.content||s.role==="user"||t.status==="running")&&e.jsx("div",{className:b("max-w-[85%] rounded-xl px-3 py-2 text-[13px] leading-relaxed",s.role==="user"?"bg-accent/15 text-ink":"bg-panel-2 text-ink"),children:e.jsx("p",{className:"whitespace-pre-wrap break-words",children:s.content||(s.role==="assistant"&&t.status==="running"?"…":"")})})]},s.id)),i&&e.jsx("div",{className:"flex gap-2",children:e.jsx("div",{className:"max-w-[85%] rounded-xl bg-panel-2 px-3 py-2 text-[13px] leading-relaxed text-ink",children:e.jsx("p",{className:"whitespace-pre-wrap break-words",children:i})})}),t.error&&e.jsxs("div",{className:"rounded-lg bg-red-500/10 px-3 py-2 text-[12px] text-red-500",children:["Error: ",t.error]}),e.jsx("div",{ref:o})]})]})}function ne(){const[t,a]=u.useState(null),[l,i]=u.useState(!1),r=v({queryKey:p.list(),queryFn:$,refetchInterval:s=>(s.state.data??[]).some(n=>n.status==="queued"||n.status==="running")?3e3:!1}),o=v({queryKey:p.detail(t??""),queryFn:()=>I(t),enabled:!!t,refetchInterval:s=>{const x=s.state.data;return x?.status==="queued"||x?.status==="running"?5e3:!1}}),d=r.data??[],m=o.data;return e.jsxs("div",{className:"flex h-full",children:[e.jsxs("div",{className:"flex w-64 shrink-0 flex-col border-r border-border",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-border px-3 py-2.5",children:[e.jsx("span",{className:"text-[13px] font-semibold text-ink",children:"Agents"}),e.jsxs("button",{type:"button",title:"New agent run",onClick:()=>i(!0),className:"flex items-center gap-1 rounded-lg bg-accent px-2 py-1 text-[11px] font-medium text-white transition-opacity hover:opacity-90",children:[e.jsx(N,{size:11})," New"]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto",children:[r.isLoading&&e.jsx("div",{className:"flex h-20 items-center justify-center",children:e.jsx(h,{size:16,className:"animate-spin text-faint"})}),d.length===0&&!r.isLoading&&e.jsxs("div",{className:"px-4 py-8 text-center",children:[e.jsx(S,{size:28,className:"mx-auto mb-2 text-faint"}),e.jsx("p",{className:"text-[12px] text-muted",children:"No agent runs yet."}),e.jsx("p",{className:"mt-0.5 text-[11px] text-faint",children:"Click “New” to start one."})]}),d.map(s=>e.jsxs("button",{type:"button",onClick:()=>a(s.id),className:b("w-full border-b border-border px-3 py-2.5 text-left transition-colors hover:bg-panel-2",t===s.id&&"bg-panel-2"),children:[e.jsx("p",{className:"mb-0.5 truncate text-[13px] font-medium text-ink",children:s.title}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(z,{status:s.status}),e.jsx("span",{className:"text-[10px] text-faint",children:W(s.createdAt)})]})]},s.id))]})]}),e.jsx("div",{className:"flex min-w-0 flex-1 flex-col",children:t?o.isLoading?e.jsx("div",{className:"flex h-full items-center justify-center",children:e.jsx(h,{size:20,className:"animate-spin text-faint"})}):m?e.jsx(H,{run:m}):null:e.jsxs("div",{className:"flex h-full flex-col items-center justify-center text-center",children:[e.jsx(D,{size:32,className:"mb-3 text-faint"}),e.jsx("p",{className:"text-[14px] font-medium text-ink",children:"Select a run"}),e.jsx("p",{className:"mt-1 text-[12px] text-muted",children:"or create a new agent run to get started"}),e.jsxs("button",{type:"button",onClick:()=>i(!0),className:"mt-4 flex items-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-[13px] font-medium text-white hover:opacity-90",children:[e.jsx(N,{size:13})," New agent run"]})]})}),l&&e.jsx(B,{onClose:()=>i(!1),onCreated:s=>{a(s),r.refetch()}})]})}export{ne as AgentsScreen};