turbollm 1.7.6 → 1.7.7

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 (94) hide show
  1. package/README.md +8 -0
  2. package/dist/cli.js +20 -4
  3. package/dist/webdist/assets/{AgentEditPage-Biq01vi2.js → AgentEditPage-y0cZcIxD.js} +1 -1
  4. package/dist/webdist/assets/{ChatScreen-Dmt_qvDr.js → ChatScreen-N8xJshxm.js} +13 -13
  5. package/dist/webdist/assets/{CustomizeScreen-Dy4Cn3bT.js → CustomizeScreen-8x5UpMgo.js} +1 -1
  6. package/dist/webdist/assets/{DeveloperScreen-DFs3rx7C.js → DeveloperScreen-Bq2FNjtI.js} +1 -1
  7. package/dist/webdist/assets/EnginesScreen-BUUYSiw6.js +7 -0
  8. package/dist/webdist/assets/{FsBrowser-Dz4gWOWq.js → FsBrowser-BQd7_SH6.js} +1 -1
  9. package/dist/webdist/assets/{MessageBubble-BxDHn4od.js → MessageBubble-T4P9BnnR.js} +10 -10
  10. package/dist/webdist/assets/{ModelsScreen-DuUqlRGS.js → ModelsScreen-0yDp-U9Y.js} +1 -1
  11. package/dist/webdist/assets/{SettingsScreen-BfP75nuS.js → SettingsScreen-BsEt3HT4.js} +1 -1
  12. package/dist/webdist/assets/{SkillEditPage-D6OKcHNG.js → SkillEditPage-C947cp0W.js} +1 -1
  13. package/dist/webdist/assets/{TokensScreen-DblmY7_u.js → TokensScreen-ColA57XS.js} +1 -1
  14. package/dist/webdist/assets/WorkspaceScreen-B88cgpDr.js +1 -0
  15. package/dist/webdist/assets/{agent-api-DZqYdw7O.js → agent-api-DgdsmygN.js} +1 -1
  16. package/dist/webdist/assets/{arc-DV0DkONk.js → arc-CAcqzHUt.js} +1 -1
  17. package/dist/webdist/assets/{architectureDiagram-3BPJPVTR-CCklxbKw.js → architectureDiagram-3BPJPVTR-uesx4C2M.js} +1 -1
  18. package/dist/webdist/assets/{arrow-left-CGv_OXEs.js → arrow-left-CixSWWD6.js} +1 -1
  19. package/dist/webdist/assets/{badge-K_-MWGgP.js → badge-Bu2_JlLl.js} +1 -1
  20. package/dist/webdist/assets/{blockDiagram-GPEHLZMM-DxjGvSV7.js → blockDiagram-GPEHLZMM-DePQ91-U.js} +1 -1
  21. package/dist/webdist/assets/{bot-CD_BRtw9.js → bot-CLQbJ0hY.js} +1 -1
  22. package/dist/webdist/assets/{c4Diagram-AAUBKEIU-C9AuWiX4.js → c4Diagram-AAUBKEIU-Nx7n4BaG.js} +1 -1
  23. package/dist/webdist/assets/channel-Bl7LnSBM.js +1 -0
  24. package/dist/webdist/assets/{chat-api-B6AobDYd.js → chat-api-v2HtltwV.js} +1 -1
  25. package/dist/webdist/assets/check-DWNXHB4-.js +1 -0
  26. package/dist/webdist/assets/{chevron-left-B-1Bh1dK.js → chevron-left-ZSwpcWK4.js} +1 -1
  27. package/dist/webdist/assets/{chevron-right-By1T2-Hr.js → chevron-right-BX4x_YDg.js} +1 -1
  28. package/dist/webdist/assets/{chunk-2J33WTMH-jxkAgaR9.js → chunk-2J33WTMH-Li-0bh7s.js} +1 -1
  29. package/dist/webdist/assets/{chunk-4BX2VUAB-BNFzh5g5.js → chunk-4BX2VUAB-D3JCha2O.js} +1 -1
  30. package/dist/webdist/assets/{chunk-55IACEB6-DX5wR3Qq.js → chunk-55IACEB6-DtexA9w4.js} +1 -1
  31. package/dist/webdist/assets/{chunk-727SXJPM-CbrKMz1R.js → chunk-727SXJPM--FzMnyZQ.js} +1 -1
  32. package/dist/webdist/assets/{chunk-AQP2D5EJ-CNb3wWkL.js → chunk-AQP2D5EJ-DLjRb4q9.js} +1 -1
  33. package/dist/webdist/assets/{chunk-FMBD7UC4-DEhDwjoQ.js → chunk-FMBD7UC4--oSGiB90.js} +1 -1
  34. package/dist/webdist/assets/{chunk-ND2GUHAM-BHmlzliw.js → chunk-ND2GUHAM-DHrBgMDK.js} +1 -1
  35. package/dist/webdist/assets/{chunk-QZHKN3VN-uI16s_C7.js → chunk-QZHKN3VN-Czsg5U3B.js} +1 -1
  36. package/dist/webdist/assets/{circle-x-yVtiCsS-.js → circle-x-SeGmqGO2.js} +1 -1
  37. package/dist/webdist/assets/classDiagram-4FO5ZUOK-DPKa7mmC.js +1 -0
  38. package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-DPKa7mmC.js +1 -0
  39. package/dist/webdist/assets/{collapsible-D0c6B4Ip.js → collapsible-BxchjxT5.js} +1 -1
  40. package/dist/webdist/assets/{common-D_CzNUTa.js → common-BX2IDRWf.js} +1 -1
  41. package/dist/webdist/assets/{cose-bilkent-S5V4N54A-B1nfQjrr.js → cose-bilkent-S5V4N54A-BWS5BbS6.js} +1 -1
  42. package/dist/webdist/assets/{dagre-BM42HDAG-B6nBvZED.js → dagre-BM42HDAG-BPo4IktH.js} +1 -1
  43. package/dist/webdist/assets/{diagram-2AECGRRQ-4HWbpgy8.js → diagram-2AECGRRQ-bBunxDsg.js} +1 -1
  44. package/dist/webdist/assets/{diagram-5GNKFQAL-DYfcLJfD.js → diagram-5GNKFQAL-moM1dOLS.js} +1 -1
  45. package/dist/webdist/assets/{diagram-KO2AKTUF-BIqc86GH.js → diagram-KO2AKTUF-BwfV8JvH.js} +1 -1
  46. package/dist/webdist/assets/{diagram-LMA3HP47-CfsmrpTV.js → diagram-LMA3HP47-orftYm_u.js} +1 -1
  47. package/dist/webdist/assets/{diagram-OG6HWLK6-DdZxRjl2.js → diagram-OG6HWLK6-D3M14loM.js} +1 -1
  48. package/dist/webdist/assets/{dialog-C5rebm8b.js → dialog-dmjvLZWp.js} +1 -1
  49. package/dist/webdist/assets/{erDiagram-TEJ5UH35-BINxvowu.js → erDiagram-TEJ5UH35-CE0GXqcn.js} +1 -1
  50. package/dist/webdist/assets/{flowDiagram-I6XJVG4X-BphwX6XS.js → flowDiagram-I6XJVG4X-BPewPsNy.js} +1 -1
  51. package/dist/webdist/assets/{folder-input-DsjMa7S5.js → folder-input-C_YBaI_4.js} +1 -1
  52. package/dist/webdist/assets/{ganttDiagram-6RSMTGT7-C63SidXF.js → ganttDiagram-6RSMTGT7-D5yG5kD1.js} +1 -1
  53. package/dist/webdist/assets/{gitGraphDiagram-PVQCEYII-D9FpCno0.js → gitGraphDiagram-PVQCEYII-Cj6zpryV.js} +1 -1
  54. package/dist/webdist/assets/{index-Cl88q0Ki.js → index-61gQc5Xl.js} +2 -2
  55. package/dist/webdist/assets/{index-g6XC4RLK.js → index-DCrpX6kY.js} +1 -1
  56. package/dist/webdist/assets/{infoDiagram-5YYISTIA-BTrZQ4Wc.js → infoDiagram-5YYISTIA-NDkQABZh.js} +1 -1
  57. package/dist/webdist/assets/{ishikawaDiagram-YF4QCWOH-CtpkiMI3.js → ishikawaDiagram-YF4QCWOH-BOB3l-Kg.js} +1 -1
  58. package/dist/webdist/assets/{journeyDiagram-JHISSGLW-Cs5Ssisp.js → journeyDiagram-JHISSGLW-DVEE4D7Z.js} +1 -1
  59. package/dist/webdist/assets/{kanban-definition-UN3LZRKU-Bd2W5L9B.js → kanban-definition-UN3LZRKU-CNPvv9C-.js} +1 -1
  60. package/dist/webdist/assets/{linear-GlXwNR5R.js → linear-D7zDjIPx.js} +1 -1
  61. package/dist/webdist/assets/{mermaid.core-BmvPXnHB.js → mermaid.core-CFRc9zhD.js} +4 -4
  62. package/dist/webdist/assets/{mindmap-definition-RKZ34NQL-CuO5FwWr.js → mindmap-definition-RKZ34NQL-DZbmKw3G.js} +1 -1
  63. package/dist/webdist/assets/{pencil-C4EXnT_a.js → pencil-DLTfIEAv.js} +1 -1
  64. package/dist/webdist/assets/{personas-C_VMMyvv.js → personas-BoG0K2t1.js} +6 -5
  65. package/dist/webdist/assets/{pieDiagram-4H26LBE5-CLty44d5.js → pieDiagram-4H26LBE5-CSeor3k5.js} +1 -1
  66. package/dist/webdist/assets/{quadrantDiagram-W4KKPZXB-BK9u_S8e.js → quadrantDiagram-W4KKPZXB-C4wIuoO1.js} +1 -1
  67. package/dist/webdist/assets/{refresh-cw-ChBdLwHh.js → refresh-cw-8N7t89ea.js} +1 -1
  68. package/dist/webdist/assets/{requirementDiagram-4Y6WPE33-DaldyJn3.js → requirementDiagram-4Y6WPE33-DhUQacPK.js} +1 -1
  69. package/dist/webdist/assets/{rotate-ccw-xceH34T7.js → rotate-ccw-DCFomh67.js} +1 -1
  70. package/dist/webdist/assets/{sankeyDiagram-5OEKKPKP-ECm1YkbT.js → sankeyDiagram-5OEKKPKP-FRUJ6EB_.js} +1 -1
  71. package/dist/webdist/assets/{sequenceDiagram-3UESZ5HK-D_WQr7Ox.js → sequenceDiagram-3UESZ5HK-CdCLaBm7.js} +1 -1
  72. package/dist/webdist/assets/{skeleton-DK4wQNYn.js → skeleton-DgTrr_PQ.js} +1 -1
  73. package/dist/webdist/assets/{star-uW87WNRR.js → star-biRsiE3m.js} +1 -1
  74. package/dist/webdist/assets/{stateDiagram-AJRCARHV-Dc4nVZrV.js → stateDiagram-AJRCARHV-v5tGLSi5.js} +1 -1
  75. package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-v4thUmx4.js +1 -0
  76. package/dist/webdist/assets/{switch-4XvTVvk1.js → switch-BlL-WRhK.js} +1 -1
  77. package/dist/webdist/assets/{timeline-definition-PNZ67QCA-BLAoVxaR.js → timeline-definition-PNZ67QCA-HpDjURD-.js} +1 -1
  78. package/dist/webdist/assets/{trash-2-BazpB6Tv.js → trash-2-B0HcfuWA.js} +1 -1
  79. package/dist/webdist/assets/useIsDesktop-BedxotK0.js +1 -0
  80. package/dist/webdist/assets/{vennDiagram-CIIHVFJN-Dxiec1ZZ.js → vennDiagram-CIIHVFJN-BcjzVaAC.js} +1 -1
  81. package/dist/webdist/assets/{wardley-L42UT6IY-B6eLCEJg.js → wardley-L42UT6IY-DAXczRny.js} +1 -1
  82. package/dist/webdist/assets/{wardleyDiagram-YWT4CUSO-CZda0vR7.js → wardleyDiagram-YWT4CUSO-BHpd_gyW.js} +1 -1
  83. package/dist/webdist/assets/{wrench-DffxK2pt.js → wrench-B2_HvSp0.js} +1 -1
  84. package/dist/webdist/assets/{xychartDiagram-2RQKCTM6-B8xutv1Z.js → xychartDiagram-2RQKCTM6-C9tyViUt.js} +1 -1
  85. package/dist/webdist/index.html +1 -1
  86. package/package.json +1 -1
  87. package/dist/webdist/assets/EnginesScreen-RkTfEghZ.js +0 -7
  88. package/dist/webdist/assets/WorkspaceScreen-DLfMYwYA.js +0 -1
  89. package/dist/webdist/assets/channel-D8wWQ4tZ.js +0 -1
  90. package/dist/webdist/assets/check-Dwz6EU4N.js +0 -1
  91. package/dist/webdist/assets/classDiagram-4FO5ZUOK-BCecvXTJ.js +0 -1
  92. package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-BCecvXTJ.js +0 -1
  93. package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-b4uEiOn_.js +0 -1
  94. package/dist/webdist/assets/useIsDesktop-BRKlTjOF.js +0 -1
package/README.md CHANGED
@@ -170,6 +170,10 @@ the detail:
170
170
  (`-ngl`), **MoE CPU-offload (`--n-cpu-moe`)**, parallel slots, **KV-cache quant type** (incl.
171
171
  low-bit on supporting forks), CPU threads, flash attention, and **speculative decoding (NextN /
172
172
  MTP / draft, with a configurable draft min/max window)**.
173
+ - **Auto-fit GPU layers / MoE offload** — an optional toggle (off by default) that hands the
174
+ GPU/CPU split decision to llama.cpp's own memory-fitting logic at load time instead of a fixed
175
+ number, honored by Auto-tune too. Useful when a large context or model doesn't fit your usual
176
+ fixed setting.
173
177
  - **Fast by default:** flash attention on, NextN self-speculative decoding on for models that
174
178
  carry a draft head, threads auto — safely gated to what your engine actually accepts.
175
179
  - **Multi-GPU, per model** — split a model across cards (layer/row split + main-GPU pick on
@@ -363,6 +367,10 @@ CUDA / a compiler — MSVC on Windows, gcc/clang on Linux), hands you the exact
363
367
  (or a 1-click **"Build it for me"** on Windows and Linux), then drops you into the folder scan
364
368
  above.
365
369
 
370
+ **Or skip the manual clone entirely** — Engines screen → **Add via git repo**: paste any
371
+ llama.cpp-compatible fork's git URL (+ optional branch, defaults to the repo's own default) and
372
+ build it in-app with the same 1-click flow, no separate "point at a folder" step needed.
373
+
366
374
  **Auto-provisioned default.** Don't want to fetch anything? On first run TurboLLM downloads
367
375
  the right upstream prebuilt for your GPU automatically — and a **backend picker** lets you
368
376
  switch between CUDA / ROCm / Metal / SYCL / Vulkan / CPU at any time (it downloads the variant
package/dist/cli.js CHANGED
@@ -2883,6 +2883,14 @@ function classifyVendor(name) {
2883
2883
  if (/apple/.test(n)) return "apple";
2884
2884
  return "unknown";
2885
2885
  }
2886
+ function isIntegratedGpuName(name) {
2887
+ const n = name.toLowerCase();
2888
+ if (/iris|uhd graphics|hd graphics/.test(n)) return true;
2889
+ if (/\barc\b/.test(n) && !/\b(?:pro\s+)?[ab]\d{2,4}\b/.test(n)) return true;
2890
+ if (/radeon.*graphics/.test(n) && !/\b(rx|pro|instinct|vega\s*\d|firepro)\b/.test(n)) return true;
2891
+ if (/intel/.test(n) && /graphics/.test(n) && !/\barc\b/.test(n)) return true;
2892
+ return false;
2893
+ }
2886
2894
  function detectGpus() {
2887
2895
  try {
2888
2896
  const out = execFileSync2("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader,nounits"], {
@@ -2931,7 +2939,8 @@ function enumWindowsGpus() {
2931
2939
  const [name, ram] = line.split("|");
2932
2940
  const nm = (name ?? "").trim();
2933
2941
  const bytes = parseInt((ram ?? "").trim(), 10) || 0;
2934
- return { name: nm, vramMb: bytes > 0 ? Math.round(bytes / 1e6) : 0, vendor: classifyVendor(nm) };
2942
+ const vramMb = isIntegratedGpuName(nm) ? Math.round(os.totalmem() / 1e6 * 0.5) : bytes > 0 ? Math.round(bytes / 1e6) : 0;
2943
+ return { name: nm, vramMb, vendor: classifyVendor(nm) };
2935
2944
  }).filter((g) => g.name && g.vendor !== "unknown");
2936
2945
  }
2937
2946
  function rocmSmiGpus() {
@@ -2972,7 +2981,10 @@ function enumLinuxGpus() {
2972
2981
  return out.trim().split("\n").filter(Boolean).map((line) => {
2973
2982
  const vendor = classifyVendor(line);
2974
2983
  const slot = line.trim().split(/\s+/)[0] ?? "";
2975
- return { name: line.replace(/"/g, "").trim().slice(0, 80), vramMb: linuxVramMb(slot), vendor };
2984
+ const name = line.replace(/"/g, "").trim().slice(0, 80);
2985
+ const sysfsVramMb = linuxVramMb(slot);
2986
+ const vramMb = sysfsVramMb > 0 ? sysfsVramMb : isIntegratedGpuName(name) ? Math.round(os.totalmem() / 1e6 * 0.5) : 0;
2987
+ return { name, vramMb, vendor };
2976
2988
  }).filter((g) => g.vendor !== "unknown");
2977
2989
  }
2978
2990
  function linuxVramMb(pciSlot) {
@@ -4014,7 +4026,7 @@ function resolveProfile(m, sys, saved, overrides, defaults) {
4014
4026
  function profileToArgs(p, m, caps, cores = 0) {
4015
4027
  const has = (flag) => caps.flags.length === 0 || caps.flags.includes(flag);
4016
4028
  const a = ["-c", String(p.ctx)];
4017
- if (p.ngl > 0) a.push("-ngl", String(p.ngl));
4029
+ if ((!p.nglFit || m.moe) && p.ngl > 0) a.push("-ngl", String(p.ngl));
4018
4030
  const g = p.gpu;
4019
4031
  if (g) {
4020
4032
  if (g.splitMode !== "layer" && has("--split-mode")) a.push("--split-mode", g.splitMode);
@@ -4025,7 +4037,7 @@ function profileToArgs(p, m, caps, cores = 0) {
4025
4037
  }
4026
4038
  if (has("--parallel")) a.push("--parallel", String(p.parallel));
4027
4039
  if (p.parallel > 1 && p.kvUnified && has("--kv-unified")) a.push("--kv-unified");
4028
- if (m.moe && p.nCpuMoe > 0 && has("--n-cpu-moe")) a.push("--n-cpu-moe", String(p.nCpuMoe));
4040
+ if (m.moe && !p.nCpuMoeFit && p.nCpuMoe > 0 && has("--n-cpu-moe")) a.push("--n-cpu-moe", String(p.nCpuMoe));
4029
4041
  const kvOk = (t) => caps.kvTypes.includes(t);
4030
4042
  if (p.kvTypeK !== "f16" && has("--cache-type-k") && kvOk(p.kvTypeK)) a.push("--cache-type-k", p.kvTypeK);
4031
4043
  if (p.kvTypeV !== "f16" && has("--cache-type-v") && kvOk(p.kvTypeV)) a.push("--cache-type-v", p.kvTypeV);
@@ -6160,6 +6172,7 @@ var BenchRunner = class {
6160
6172
  * LOAD-time property, so we find that ngl with cheap load-and-read-VRAM probes (no generation),
6161
6173
  * and only measure t/s at the winner. CPU-only machines skip straight to ngl=0. */
6162
6174
  async denseSearch(entry, sys, base2, caps, results, headroomMb) {
6175
+ if (base2.nglFit) return this.benchAt(entry, sys, base2, caps, results, "auto-fit");
6163
6176
  let bestNgl = 0;
6164
6177
  if (sys.gpus.length > 0) {
6165
6178
  const hi0 = entry.blockCount > 0 ? entry.blockCount : 99;
@@ -6187,6 +6200,7 @@ var BenchRunner = class {
6187
6200
  * still leaves the configured headroom. Found with cheap load-and-read-VRAM probes (no generation);
6188
6201
  * t/s is measured only at the winner. */
6189
6202
  async moeSearch(entry, sys, base2, caps, results, headroomMb) {
6203
+ if (base2.nCpuMoeFit) return this.benchAt(entry, sys, base2, caps, results, "auto-fit");
6190
6204
  const derived = deriveDefault(entry, sys);
6191
6205
  const maxN = entry.blockCount > 0 ? entry.blockCount : derived.nCpuMoe || 0;
6192
6206
  let lo = 0, hi = maxN;
@@ -6310,7 +6324,9 @@ var BenchRunner = class {
6310
6324
  const params = {
6311
6325
  ctx: profile.ctx,
6312
6326
  ngl: profile.ngl,
6327
+ nglFit: profile.nglFit,
6313
6328
  nCpuMoe: profile.nCpuMoe,
6329
+ nCpuMoeFit: profile.nCpuMoeFit,
6314
6330
  parallel: profile.parallel,
6315
6331
  kvTypeK: profile.kvTypeK,
6316
6332
  flashAttn: profile.flashAttn
@@ -1 +1 @@
1
- import{j as e}from"./radix-krE_SGZJ.js";import{u as M,b as W,r as b}from"./vendor-BE0HADM8.js";import{u as $,b as G,c as H,d as Y,e as J,a as E,B as y,f as B,t as h,A as C}from"./index-Cl88q0Ki.js";import{f as U}from"./chat-api-B6AobDYd.js";import{f as V,a as X}from"./agent-api-DZqYdw7O.js";import{P as z}from"./personas-C_VMMyvv.js";import{C as Z}from"./chevron-left-B-1Bh1dK.js";import{R as ee}from"./rotate-ccw-xceH34T7.js";import{T as te}from"./trash-2-BazpB6Tv.js";import{C as se}from"./chevron-right-By1T2-Hr.js";const ne=()=>({name:"",description:"",systemPrompt:"",skillIds:[],tools:[]});function oe(s){const d=[],x=new Map;for(const n of s){const o=/^mcp__([^_]+(?:_[^_]+)*)__/.exec(n.name);if(!o){d.push(n);continue}const i=o[1],p=/^\[([^\]]+)\]/.exec(n.description),c=p?p[1]:i.replace(/_/g," ");x.has(i)||x.set(i,{key:i,label:c,tools:[]}),x.get(i).tools.push(n)}return{builtin:d,groups:[...x.values()].sort((n,o)=>n.label.localeCompare(o.label))}}function ae(s){return s.replace(/^mcp__[^_]+(?:_[^_]+)*__/,"")}function le(s){return s.replace(/^\[[^\]]+\]\s*/,"")}function q({tool:s,checked:d,onToggle:x}){return e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[12px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:d,onChange:x}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"font-mono text-ink",children:ae(s.name)}),s.description&&e.jsx("span",{className:"text-faint",children:le(s.description)})]})]})}function re({group:s,selected:d,onToggleAll:x,onToggleOne:n}){const[o,i]=b.useState(!1),p=s.tools.map(l=>l.name),c=p.filter(l=>d.has(l)).length,a=c===p.length,f=c>0&&!a,u=b.useRef(null);return b.useEffect(()=>{u.current&&(u.current.indeterminate=f)},[f]),e.jsxs("div",{className:"rounded-md border border-border",children:[e.jsxs("div",{className:"flex items-center gap-2 px-2.5 py-2",children:[e.jsx("input",{ref:u,type:"checkbox",checked:a,onChange:()=>x(p,!a)}),e.jsxs("button",{type:"button",onClick:()=>i(l=>!l),className:"flex flex-1 items-center gap-1.5 text-left text-[13px] text-ink",children:[e.jsx(se,{size:12,className:B("shrink-0 text-faint transition-transform",o&&"rotate-90")}),s.label,e.jsxs("span",{className:"text-[11px] text-faint",children:["(",c,"/",p.length,")"]})]})]}),o&&e.jsx("div",{className:"flex flex-col gap-1.5 border-t border-border px-3 py-2 pl-9",children:s.tools.map(l=>e.jsx(q,{tool:l,checked:d.has(l.name),onToggle:()=>n(l.name)},l.name))})]})}function ie({tools:s,selected:d,onChange:x}){const n=new Set(d),{builtin:o,groups:i}=oe(s),p=a=>x(n.has(a)?d.filter(f=>f!==a):[...d,a]),c=(a,f)=>{const u=d.filter(l=>!a.includes(l));x(f?[...u,...a]:u)};return s.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No tools available yet."}):e.jsxs("div",{className:"flex flex-col gap-2",children:[o.length>0&&e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:o.map(a=>e.jsx(q,{tool:a,checked:n.has(a.name),onToggle:()=>p(a.name)},a.name))}),i.map(a=>e.jsx(re,{group:a,selected:n,onToggleAll:c,onToggleOne:p},a.key))]})}function ke(){const{agentId:s="new"}=M(),d=W(),x=$(),n=s==="new",o=!n&&z.some(t=>t.id===s),i=o?z.find(t=>t.id===s):void 0,p=G(),c=!n&&!o?(p.data??[]).find(t=>t.id===s):void 0,a=H(),f=Y(),u=J(),l=o?f.data?.[s]:void 0,_=E({queryKey:X.list(),queryFn:V,staleTime:0}),k=_.data??[],I=E({queryKey:["available-tools"],queryFn:U}),j=I.data??[],[m,g]=b.useState(ne()),[S,T]=b.useState(!1),[A,P]=b.useState(!1),[D,w]=b.useState(!1),[R,L]=b.useState("skills");n&&!S&&(k.length||j.length)&&(g(t=>({...t,skillIds:k.map(r=>r.id),tools:j.map(r=>r.name)})),T(!0)),!n&&!o&&!S&&c&&(g({name:c.name,description:c.description,systemPrompt:c.systemPrompt,skillIds:c.skillIds,tools:c.tools}),T(!0)),o&&!S&&i&&f.isSuccess&&(k.length||j.length)&&(g({name:l?.name??i.name,description:l?.description??i.description,systemPrompt:l?.systemPrompt??i.systemPrompt,skillIds:l?.skillIds??k.map(t=>t.id),tools:l?.tools??j.map(t=>t.name)}),T(!0));const N=()=>d("/customize"),Q=t=>g(r=>({...r,skillIds:r.skillIds.includes(t)?r.skillIds.filter(v=>v!==t):[...r.skillIds,t]})),O=()=>{if(!m.name.trim()){h.error("Name is required.");return}P(!0);const t={name:m.name.trim(),description:m.description.trim(),systemPrompt:m.systemPrompt,skillIds:m.skillIds,tools:m.tools};if(o){u.save.mutate({id:s,override:t},{onSuccess:()=>{h.success("Agent saved."),N()},onError:v=>{h.error(v instanceof C?v.message:"Could not save agent."),P(!1)}});return}const r={onSuccess:()=>{x.invalidateQueries({queryKey:["chat-agents"]}),h.success(n?"Agent created.":"Agent saved."),N()},onError:v=>{h.error(v instanceof C?v.message:"Could not save agent."),P(!1)}};n?a.add.mutate(t,r):a.update.mutate({id:s,patch:t},r)},F=()=>{u.reset.mutate(s,{onSuccess:()=>{h.success("Reset to default."),i&&g({name:i.name,description:i.description,systemPrompt:i.systemPrompt,skillIds:k.map(t=>t.id),tools:j.map(t=>t.name)})},onError:t=>h.error(t instanceof C?t.message:"Could not reset agent.")})},K=()=>{a.remove.mutate(s,{onSuccess:()=>{h.success("Agent deleted."),N()},onError:t=>h.error(t instanceof C?t.message:"Could not delete agent.")})};return!n&&!o&&p.isSuccess&&!c?e.jsxs("div",{className:"flex w-full flex-col items-center gap-3 px-8 py-16",children:[e.jsx("p",{className:"text-[14px] text-muted",children:"That agent no longer exists."}),e.jsx(y,{size:"sm",variant:"outline",onClick:N,children:"Back to agents"})]}):e.jsxs("div",{className:"flex w-full max-w-4xl flex-col gap-5 px-4 py-6 md:px-8",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:N,className:"text-faint hover:text-ink",title:"Back to agents",children:e.jsx(Z,{size:18})}),e.jsx("span",{className:"text-[15px] font-medium text-ink",children:n?"New agent":o?l?"Edit agent (modified built-in)":"Edit agent (built-in)":"Edit agent"}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[o&&e.jsxs(y,{size:"sm",variant:"outline",onClick:F,disabled:u.reset.isPending,children:[e.jsx(ee,{size:13})," Reset to default"]}),e.jsx(y,{size:"sm",variant:"outline",onClick:N,children:"Cancel"}),e.jsx(y,{size:"sm",onClick:O,disabled:A||!m.name.trim(),children:A?"Saving…":"Save"})]})]}),o&&e.jsx("p",{className:"rounded-md border border-border bg-panel px-3 py-2 text-[12px] text-muted",children:"Built-in agents can be edited in place — Reset to default discards your changes and restores TurboLLM's original prompt and access."}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Name"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"Release Notes Writer",value:m.name,onChange:t=>g(r=>({...r,name:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Description"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"What this agent is for, in one line",value:m.description,onChange:t=>g(r=>({...r,description:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"System prompt"}),e.jsx("textarea",{className:"min-h-[160px] resize-y rounded-md border border-border bg-bg px-3 py-2 font-mono text-[12px] leading-relaxed text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"You are…",value:m.systemPrompt,onChange:t=>g(r=>({...r,systemPrompt:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-2.5",children:[e.jsx("div",{className:"inline-flex w-fit rounded-md border border-border p-0.5",children:["skills","tools"].map(t=>e.jsx("button",{type:"button",onClick:()=>L(t),className:B("rounded px-3 py-1.5 text-[13px] font-medium transition-colors",R===t?"bg-accent/12 text-accent":"text-muted hover:text-ink"),children:t==="skills"?`Skills (${m.skillIds.length})`:`Tools (${m.tools.length})`},t))}),R==="skills"?_.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):k.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No skills yet — create one under Customize → Skills."}):e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:k.map(t=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[13px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:m.skillIds.includes(t.id),onChange:()=>Q(t.id)}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"text-ink",children:t.name}),t.description&&e.jsx("span",{className:"text-[12px] text-muted",children:t.description})]})]},t.id))}):I.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):e.jsx(ie,{tools:j,selected:m.tools,onChange:t=>g(r=>({...r,tools:t}))})]}),!n&&!o&&(D?e.jsxs("div",{className:"flex items-center gap-2 self-start rounded-md border border-border bg-panel p-2 text-[12px]",children:[e.jsx("span",{className:"flex-1 text-muted",children:"Delete this agent?"}),e.jsx("button",{type:"button",onClick:K,className:"rounded px-2 py-1 text-[color:var(--err)] hover:bg-[color:color-mix(in_srgb,var(--err)_12%,transparent)]",children:"Delete"}),e.jsx("button",{type:"button",onClick:()=>w(!1),className:"rounded px-2 py-1 text-faint hover:text-ink",children:"Cancel"})]}):e.jsxs("button",{type:"button",onClick:()=>w(!0),className:"flex items-center gap-1.5 self-start text-[12px] text-faint hover:text-[color:var(--err)]",children:[e.jsx(te,{size:13})," Delete agent"]}))]})}export{ke as AgentEditPage};
1
+ import{j as e}from"./radix-krE_SGZJ.js";import{u as M,b as W,r as b}from"./vendor-BE0HADM8.js";import{u as $,b as G,c as H,d as Y,e as J,a as E,B as y,f as B,t as h,A as C}from"./index-61gQc5Xl.js";import{f as U}from"./chat-api-v2HtltwV.js";import{f as V,a as X}from"./agent-api-DgdsmygN.js";import{P as z}from"./personas-BoG0K2t1.js";import{C as Z}from"./chevron-left-ZSwpcWK4.js";import{R as ee}from"./rotate-ccw-DCFomh67.js";import{T as te}from"./trash-2-B0HcfuWA.js";import{C as se}from"./chevron-right-BX4x_YDg.js";const ne=()=>({name:"",description:"",systemPrompt:"",skillIds:[],tools:[]});function oe(s){const d=[],x=new Map;for(const n of s){const o=/^mcp__([^_]+(?:_[^_]+)*)__/.exec(n.name);if(!o){d.push(n);continue}const i=o[1],p=/^\[([^\]]+)\]/.exec(n.description),c=p?p[1]:i.replace(/_/g," ");x.has(i)||x.set(i,{key:i,label:c,tools:[]}),x.get(i).tools.push(n)}return{builtin:d,groups:[...x.values()].sort((n,o)=>n.label.localeCompare(o.label))}}function ae(s){return s.replace(/^mcp__[^_]+(?:_[^_]+)*__/,"")}function le(s){return s.replace(/^\[[^\]]+\]\s*/,"")}function q({tool:s,checked:d,onToggle:x}){return e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[12px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:d,onChange:x}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"font-mono text-ink",children:ae(s.name)}),s.description&&e.jsx("span",{className:"text-faint",children:le(s.description)})]})]})}function re({group:s,selected:d,onToggleAll:x,onToggleOne:n}){const[o,i]=b.useState(!1),p=s.tools.map(l=>l.name),c=p.filter(l=>d.has(l)).length,a=c===p.length,f=c>0&&!a,u=b.useRef(null);return b.useEffect(()=>{u.current&&(u.current.indeterminate=f)},[f]),e.jsxs("div",{className:"rounded-md border border-border",children:[e.jsxs("div",{className:"flex items-center gap-2 px-2.5 py-2",children:[e.jsx("input",{ref:u,type:"checkbox",checked:a,onChange:()=>x(p,!a)}),e.jsxs("button",{type:"button",onClick:()=>i(l=>!l),className:"flex flex-1 items-center gap-1.5 text-left text-[13px] text-ink",children:[e.jsx(se,{size:12,className:B("shrink-0 text-faint transition-transform",o&&"rotate-90")}),s.label,e.jsxs("span",{className:"text-[11px] text-faint",children:["(",c,"/",p.length,")"]})]})]}),o&&e.jsx("div",{className:"flex flex-col gap-1.5 border-t border-border px-3 py-2 pl-9",children:s.tools.map(l=>e.jsx(q,{tool:l,checked:d.has(l.name),onToggle:()=>n(l.name)},l.name))})]})}function ie({tools:s,selected:d,onChange:x}){const n=new Set(d),{builtin:o,groups:i}=oe(s),p=a=>x(n.has(a)?d.filter(f=>f!==a):[...d,a]),c=(a,f)=>{const u=d.filter(l=>!a.includes(l));x(f?[...u,...a]:u)};return s.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No tools available yet."}):e.jsxs("div",{className:"flex flex-col gap-2",children:[o.length>0&&e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:o.map(a=>e.jsx(q,{tool:a,checked:n.has(a.name),onToggle:()=>p(a.name)},a.name))}),i.map(a=>e.jsx(re,{group:a,selected:n,onToggleAll:c,onToggleOne:p},a.key))]})}function ke(){const{agentId:s="new"}=M(),d=W(),x=$(),n=s==="new",o=!n&&z.some(t=>t.id===s),i=o?z.find(t=>t.id===s):void 0,p=G(),c=!n&&!o?(p.data??[]).find(t=>t.id===s):void 0,a=H(),f=Y(),u=J(),l=o?f.data?.[s]:void 0,_=E({queryKey:X.list(),queryFn:V,staleTime:0}),k=_.data??[],I=E({queryKey:["available-tools"],queryFn:U}),j=I.data??[],[m,g]=b.useState(ne()),[S,T]=b.useState(!1),[A,P]=b.useState(!1),[D,w]=b.useState(!1),[R,L]=b.useState("skills");n&&!S&&(k.length||j.length)&&(g(t=>({...t,skillIds:k.map(r=>r.id),tools:j.map(r=>r.name)})),T(!0)),!n&&!o&&!S&&c&&(g({name:c.name,description:c.description,systemPrompt:c.systemPrompt,skillIds:c.skillIds,tools:c.tools}),T(!0)),o&&!S&&i&&f.isSuccess&&(k.length||j.length)&&(g({name:l?.name??i.name,description:l?.description??i.description,systemPrompt:l?.systemPrompt??i.systemPrompt,skillIds:l?.skillIds??k.map(t=>t.id),tools:l?.tools??j.map(t=>t.name)}),T(!0));const N=()=>d("/customize"),Q=t=>g(r=>({...r,skillIds:r.skillIds.includes(t)?r.skillIds.filter(v=>v!==t):[...r.skillIds,t]})),O=()=>{if(!m.name.trim()){h.error("Name is required.");return}P(!0);const t={name:m.name.trim(),description:m.description.trim(),systemPrompt:m.systemPrompt,skillIds:m.skillIds,tools:m.tools};if(o){u.save.mutate({id:s,override:t},{onSuccess:()=>{h.success("Agent saved."),N()},onError:v=>{h.error(v instanceof C?v.message:"Could not save agent."),P(!1)}});return}const r={onSuccess:()=>{x.invalidateQueries({queryKey:["chat-agents"]}),h.success(n?"Agent created.":"Agent saved."),N()},onError:v=>{h.error(v instanceof C?v.message:"Could not save agent."),P(!1)}};n?a.add.mutate(t,r):a.update.mutate({id:s,patch:t},r)},F=()=>{u.reset.mutate(s,{onSuccess:()=>{h.success("Reset to default."),i&&g({name:i.name,description:i.description,systemPrompt:i.systemPrompt,skillIds:k.map(t=>t.id),tools:j.map(t=>t.name)})},onError:t=>h.error(t instanceof C?t.message:"Could not reset agent.")})},K=()=>{a.remove.mutate(s,{onSuccess:()=>{h.success("Agent deleted."),N()},onError:t=>h.error(t instanceof C?t.message:"Could not delete agent.")})};return!n&&!o&&p.isSuccess&&!c?e.jsxs("div",{className:"flex w-full flex-col items-center gap-3 px-8 py-16",children:[e.jsx("p",{className:"text-[14px] text-muted",children:"That agent no longer exists."}),e.jsx(y,{size:"sm",variant:"outline",onClick:N,children:"Back to agents"})]}):e.jsxs("div",{className:"flex w-full max-w-4xl flex-col gap-5 px-4 py-6 md:px-8",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:N,className:"text-faint hover:text-ink",title:"Back to agents",children:e.jsx(Z,{size:18})}),e.jsx("span",{className:"text-[15px] font-medium text-ink",children:n?"New agent":o?l?"Edit agent (modified built-in)":"Edit agent (built-in)":"Edit agent"}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[o&&e.jsxs(y,{size:"sm",variant:"outline",onClick:F,disabled:u.reset.isPending,children:[e.jsx(ee,{size:13})," Reset to default"]}),e.jsx(y,{size:"sm",variant:"outline",onClick:N,children:"Cancel"}),e.jsx(y,{size:"sm",onClick:O,disabled:A||!m.name.trim(),children:A?"Saving…":"Save"})]})]}),o&&e.jsx("p",{className:"rounded-md border border-border bg-panel px-3 py-2 text-[12px] text-muted",children:"Built-in agents can be edited in place — Reset to default discards your changes and restores TurboLLM's original prompt and access."}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Name"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"Release Notes Writer",value:m.name,onChange:t=>g(r=>({...r,name:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Description"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"What this agent is for, in one line",value:m.description,onChange:t=>g(r=>({...r,description:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"System prompt"}),e.jsx("textarea",{className:"min-h-[160px] resize-y rounded-md border border-border bg-bg px-3 py-2 font-mono text-[12px] leading-relaxed text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"You are…",value:m.systemPrompt,onChange:t=>g(r=>({...r,systemPrompt:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-2.5",children:[e.jsx("div",{className:"inline-flex w-fit rounded-md border border-border p-0.5",children:["skills","tools"].map(t=>e.jsx("button",{type:"button",onClick:()=>L(t),className:B("rounded px-3 py-1.5 text-[13px] font-medium transition-colors",R===t?"bg-accent/12 text-accent":"text-muted hover:text-ink"),children:t==="skills"?`Skills (${m.skillIds.length})`:`Tools (${m.tools.length})`},t))}),R==="skills"?_.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):k.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No skills yet — create one under Customize → Skills."}):e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:k.map(t=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[13px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:m.skillIds.includes(t.id),onChange:()=>Q(t.id)}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"text-ink",children:t.name}),t.description&&e.jsx("span",{className:"text-[12px] text-muted",children:t.description})]})]},t.id))}):I.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):e.jsx(ie,{tools:j,selected:m.tools,onChange:t=>g(r=>({...r,tools:t}))})]}),!n&&!o&&(D?e.jsxs("div",{className:"flex items-center gap-2 self-start rounded-md border border-border bg-panel p-2 text-[12px]",children:[e.jsx("span",{className:"flex-1 text-muted",children:"Delete this agent?"}),e.jsx("button",{type:"button",onClick:K,className:"rounded px-2 py-1 text-[color:var(--err)] hover:bg-[color:color-mix(in_srgb,var(--err)_12%,transparent)]",children:"Delete"}),e.jsx("button",{type:"button",onClick:()=>w(!1),className:"rounded px-2 py-1 text-faint hover:text-ink",children:"Cancel"})]}):e.jsxs("button",{type:"button",onClick:()=>w(!0),className:"flex items-center gap-1.5 self-start text-[12px] text-faint hover:text-[color:var(--err)]",children:[e.jsx(te,{size:13})," Delete agent"]}))]})}export{ke as AgentEditPage};