turbollm 1.9.8 → 1.9.9

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 (103) hide show
  1. package/dist/chunk-QIEQAXY4.js +84 -0
  2. package/dist/cli.js +106 -52
  3. package/dist/run-code-sandbox.js +11 -0
  4. package/dist/run-code-worker.js +12 -0
  5. package/dist/webdist/assets/{AgentEditPage-D2MKlhC4.js → AgentEditPage-D98txd16.js} +1 -1
  6. package/dist/webdist/assets/{ChatScreen-BT8jCGTN.js → ChatScreen-CS71asgl.js} +1 -1
  7. package/dist/webdist/assets/{CodeComposer-BCwZMgGI.js → CodeComposer-dytP0NgH.js} +1 -1
  8. package/dist/webdist/assets/{CodeHomeScreen-Wcb_8M4g.js → CodeHomeScreen-CRhUj3Qd.js} +1 -1
  9. package/dist/webdist/assets/{CodeSessionScreen-CgANva49.js → CodeSessionScreen-BCeskSxK.js} +1 -1
  10. package/dist/webdist/assets/{CustomizeScreen-DV9OIXsG.js → CustomizeScreen-CSsGEHs5.js} +1 -1
  11. package/dist/webdist/assets/{DeveloperScreen-vndr1xLZ.js → DeveloperScreen-BFyl9QrF.js} +1 -1
  12. package/dist/webdist/assets/{EnginesScreen-DZ20QyGt.js → EnginesScreen-A02RlkGn.js} +1 -1
  13. package/dist/webdist/assets/{FsBrowser-BVRCuSAt.js → FsBrowser-D3HBvjhq.js} +1 -1
  14. package/dist/webdist/assets/{ModelLoadMenu-DHeG2IT7.js → ModelLoadMenu-3JALli7v.js} +1 -1
  15. package/dist/webdist/assets/{ModelsScreen-BxpUJPoo.js → ModelsScreen-CoNDjkps.js} +1 -1
  16. package/dist/webdist/assets/{SettingsScreen-DxbU7U2g.js → SettingsScreen-CBcxNXHq.js} +1 -1
  17. package/dist/webdist/assets/{SkillEditPage-C8z0asiI.js → SkillEditPage-CL9RVeFz.js} +1 -1
  18. package/dist/webdist/assets/{TokensScreen-27qcX_mG.js → TokensScreen-ClJXGUYf.js} +1 -1
  19. package/dist/webdist/assets/{ToolApprovalBar-qM2wqtNL.js → ToolApprovalBar-C7fFuTzD.js} +3 -3
  20. package/dist/webdist/assets/WorkspaceScreen-DbsMngnG.js +1 -0
  21. package/dist/webdist/assets/{agent-api-B8x62EvQ.js → agent-api-D3ifA1i1.js} +1 -1
  22. package/dist/webdist/assets/{arc-BW8F_BQA.js → arc-BEsD84sD.js} +1 -1
  23. package/dist/webdist/assets/{architectureDiagram-3BPJPVTR-zfH49ZGf.js → architectureDiagram-3BPJPVTR-Bcf3Oh3C.js} +1 -1
  24. package/dist/webdist/assets/{arrow-left-A509Fetv.js → arrow-left-1uw3q1aI.js} +1 -1
  25. package/dist/webdist/assets/{badge-BEGHN2Gs.js → badge-CEz4LJ_u.js} +1 -1
  26. package/dist/webdist/assets/{blockDiagram-GPEHLZMM-B36qo5WU.js → blockDiagram-GPEHLZMM-sG48Bt1S.js} +1 -1
  27. package/dist/webdist/assets/{bot-DmS4yJ_3.js → bot-CXTtjLX9.js} +1 -1
  28. package/dist/webdist/assets/{c4Diagram-AAUBKEIU-DAnyJ1zY.js → c4Diagram-AAUBKEIU-DgkFtTQT.js} +1 -1
  29. package/dist/webdist/assets/channel-DecIRu9A.js +1 -0
  30. package/dist/webdist/assets/{chat-api-D8Zk6kRh.js → chat-api-4_WMcoaf.js} +1 -1
  31. package/dist/webdist/assets/{chat-queries-M23Lkm4X.js → chat-queries-Bbch8wOy.js} +1 -1
  32. package/dist/webdist/assets/{chevron-left-BwGlXiTi.js → chevron-left-MKKbFVwZ.js} +1 -1
  33. package/dist/webdist/assets/{chevron-right-B8nbhuzl.js → chevron-right-Dyu5POuN.js} +1 -1
  34. package/dist/webdist/assets/{chunk-2J33WTMH-CKSa-SWg.js → chunk-2J33WTMH-gfRLbNiG.js} +1 -1
  35. package/dist/webdist/assets/{chunk-4BX2VUAB-BJ5ORVQz.js → chunk-4BX2VUAB-D2VRHIgk.js} +1 -1
  36. package/dist/webdist/assets/{chunk-55IACEB6-Cg3bYYac.js → chunk-55IACEB6-BRYNAaJo.js} +1 -1
  37. package/dist/webdist/assets/{chunk-727SXJPM-uerTg8Pr.js → chunk-727SXJPM-C6mybpYg.js} +1 -1
  38. package/dist/webdist/assets/{chunk-AQP2D5EJ-DqdFefiE.js → chunk-AQP2D5EJ-BMyIGFUk.js} +1 -1
  39. package/dist/webdist/assets/{chunk-FMBD7UC4-DHVbvOSl.js → chunk-FMBD7UC4-BEFQKdfY.js} +1 -1
  40. package/dist/webdist/assets/{chunk-ND2GUHAM-Bd_Jx54f.js → chunk-ND2GUHAM-DC-MjDMo.js} +1 -1
  41. package/dist/webdist/assets/{chunk-QZHKN3VN-iIS0rOO4.js → chunk-QZHKN3VN-BM6ZrNKX.js} +1 -1
  42. package/dist/webdist/assets/{circle-check-CxTKIoUQ.js → circle-check-54SBQ-If.js} +1 -1
  43. package/dist/webdist/assets/{circle-x-DtTsKVOs.js → circle-x-D5W-ObbJ.js} +1 -1
  44. package/dist/webdist/assets/classDiagram-4FO5ZUOK-DUa0EfwD.js +1 -0
  45. package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-DUa0EfwD.js +1 -0
  46. package/dist/webdist/assets/{common-BLhKAx-E.js → common-CTIDSADV.js} +1 -1
  47. package/dist/webdist/assets/{cose-bilkent-S5V4N54A-Q0XTfDW4.js → cose-bilkent-S5V4N54A-CBx5wmgg.js} +1 -1
  48. package/dist/webdist/assets/{dagre-BM42HDAG-BpEjp0Mo.js → dagre-BM42HDAG-DwhlmSV2.js} +1 -1
  49. package/dist/webdist/assets/{diagram-2AECGRRQ-CQgcaxwM.js → diagram-2AECGRRQ-D1sU9aIT.js} +1 -1
  50. package/dist/webdist/assets/{diagram-5GNKFQAL-BAXLYnn8.js → diagram-5GNKFQAL-C-2sy29e.js} +1 -1
  51. package/dist/webdist/assets/{diagram-KO2AKTUF-hS4UiX21.js → diagram-KO2AKTUF-LKVsai41.js} +1 -1
  52. package/dist/webdist/assets/{diagram-LMA3HP47-BSH8Svf2.js → diagram-LMA3HP47-Q_B9eOzv.js} +1 -1
  53. package/dist/webdist/assets/{diagram-OG6HWLK6-ChkrDAcn.js → diagram-OG6HWLK6-D9djKZl1.js} +1 -1
  54. package/dist/webdist/assets/{dialog-Cif52qlh.js → dialog-iNC9lX0K.js} +1 -1
  55. package/dist/webdist/assets/{dropdown-menu-CEXJQu9r.js → dropdown-menu-Uai4Q-jo.js} +1 -1
  56. package/dist/webdist/assets/{erDiagram-TEJ5UH35-CoSbJaoh.js → erDiagram-TEJ5UH35-abr482jW.js} +1 -1
  57. package/dist/webdist/assets/{flowDiagram-I6XJVG4X-CxmlDLjH.js → flowDiagram-I6XJVG4X-9BtpVx9T.js} +1 -1
  58. package/dist/webdist/assets/{ganttDiagram-6RSMTGT7-D9DcHOHi.js → ganttDiagram-6RSMTGT7-CzqQxSlF.js} +1 -1
  59. package/dist/webdist/assets/{git-branch-wVIAC1y2.js → git-branch-B3MohlrH.js} +1 -1
  60. package/dist/webdist/assets/{gitGraphDiagram-PVQCEYII-PZXq-NT0.js → gitGraphDiagram-PVQCEYII-DbZ7jYIC.js} +1 -1
  61. package/dist/webdist/assets/{index-BQecSQnE.js → index-C0Cl7zDd.js} +2 -2
  62. package/dist/webdist/assets/{infoDiagram-5YYISTIA-OdiZto4C.js → infoDiagram-5YYISTIA-kyar53vB.js} +1 -1
  63. package/dist/webdist/assets/{ishikawaDiagram-YF4QCWOH-ByqCES2J.js → ishikawaDiagram-YF4QCWOH-4IqCyHAp.js} +1 -1
  64. package/dist/webdist/assets/{journeyDiagram-JHISSGLW-iAvir64R.js → journeyDiagram-JHISSGLW-DerlUKQD.js} +1 -1
  65. package/dist/webdist/assets/{kanban-definition-UN3LZRKU-Coq1b_4K.js → kanban-definition-UN3LZRKU-mi-xAMmA.js} +1 -1
  66. package/dist/webdist/assets/{linear-CFHN7GNP.js → linear-De9KbfAq.js} +1 -1
  67. package/dist/webdist/assets/{lock-C-qBN6Je.js → lock-DWktYpDU.js} +1 -1
  68. package/dist/webdist/assets/{mermaid.core-BbE5ZQQb.js → mermaid.core-Dad36Keh.js} +4 -4
  69. package/dist/webdist/assets/{mindmap-definition-RKZ34NQL-BJI67qBG.js → mindmap-definition-RKZ34NQL-CKTmOJug.js} +1 -1
  70. package/dist/webdist/assets/{pencil-CLrsEWvO.js → pencil-D0deyQM7.js} +1 -1
  71. package/dist/webdist/assets/{personas-DjECKK03.js → personas-DhDGxLXM.js} +2 -0
  72. package/dist/webdist/assets/{pieDiagram-4H26LBE5-ClFRQd-P.js → pieDiagram-4H26LBE5-DRhTqzut.js} +1 -1
  73. package/dist/webdist/assets/{plus-CnpqRmY0.js → plus-DsnJhGIz.js} +1 -1
  74. package/dist/webdist/assets/{quadrantDiagram-W4KKPZXB-C6h_Xp8y.js → quadrantDiagram-W4KKPZXB-W8pNw5Bc.js} +1 -1
  75. package/dist/webdist/assets/{refresh-cw-C92HxozQ.js → refresh-cw-B98TV0bF.js} +1 -1
  76. package/dist/webdist/assets/{requirementDiagram-4Y6WPE33-otwWbKYv.js → requirementDiagram-4Y6WPE33-B-CDzRMO.js} +1 -1
  77. package/dist/webdist/assets/{rotate-ccw-CTVQYcfd.js → rotate-ccw-DR_KW7ek.js} +1 -1
  78. package/dist/webdist/assets/{sankeyDiagram-5OEKKPKP-DbXQbMGj.js → sankeyDiagram-5OEKKPKP-6vfu1mj9.js} +1 -1
  79. package/dist/webdist/assets/{sequenceDiagram-3UESZ5HK-DVeUokYb.js → sequenceDiagram-3UESZ5HK-DVUQwTLx.js} +1 -1
  80. package/dist/webdist/assets/{skeleton-Bgx_ejYi.js → skeleton-4viE5ylU.js} +1 -1
  81. package/dist/webdist/assets/{sliders-horizontal-kCZOXks3.js → sliders-horizontal-DwHi7-vM.js} +1 -1
  82. package/dist/webdist/assets/{sparkles-CK3xY-de.js → sparkles-BceJsnLM.js} +1 -1
  83. package/dist/webdist/assets/{star-Bl6Mcr3J.js → star-DQsSvwR9.js} +1 -1
  84. package/dist/webdist/assets/{stateDiagram-AJRCARHV-BTTdXeL2.js → stateDiagram-AJRCARHV-CE7i5Wu8.js} +1 -1
  85. package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-D9xP3EIM.js +1 -0
  86. package/dist/webdist/assets/{switch-_1we_sIC.js → switch-D17DCz5F.js} +1 -1
  87. package/dist/webdist/assets/{terminal-BITU7jD3.js → terminal-DvNOGYu-.js} +1 -1
  88. package/dist/webdist/assets/{timeline-definition-PNZ67QCA-DloHmMh_.js → timeline-definition-PNZ67QCA-D3duw3PV.js} +1 -1
  89. package/dist/webdist/assets/{trash-2-D0azs_Tt.js → trash-2-Dbm39wTN.js} +1 -1
  90. package/dist/webdist/assets/useIsDesktop-Bk0ls7zx.js +1 -0
  91. package/dist/webdist/assets/{vennDiagram-CIIHVFJN-Ccv3ZcVV.js → vennDiagram-CIIHVFJN-1EeE9_my.js} +1 -1
  92. package/dist/webdist/assets/{wardley-L42UT6IY-DpBTXmML.js → wardley-L42UT6IY-D7H3ENt0.js} +1 -1
  93. package/dist/webdist/assets/{wardleyDiagram-YWT4CUSO-CNQLbvwQ.js → wardleyDiagram-YWT4CUSO-L41fDeY9.js} +1 -1
  94. package/dist/webdist/assets/{wrench-B_ypp0gU.js → wrench-CQJSn13Q.js} +1 -1
  95. package/dist/webdist/assets/{xychartDiagram-2RQKCTM6-Dkv0G4Ag.js → xychartDiagram-2RQKCTM6-BKSosY_R.js} +1 -1
  96. package/dist/webdist/index.html +1 -1
  97. package/package.json +1 -1
  98. package/dist/webdist/assets/WorkspaceScreen-BVZ7QWkL.js +0 -1
  99. package/dist/webdist/assets/channel-6n-J43t-.js +0 -1
  100. package/dist/webdist/assets/classDiagram-4FO5ZUOK-aMec4COx.js +0 -1
  101. package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-aMec4COx.js +0 -1
  102. package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-PhwvulL3.js +0 -1
  103. package/dist/webdist/assets/useIsDesktop-DaHDDrDA.js +0 -1
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/tools/run-code-sandbox.ts
4
+ import { createContext, runInContext } from "vm";
5
+ var RUN_CODE_TIMEOUT_MS = 5e3;
6
+ var RUN_CODE_SETUP_TIMEOUT_MS = 1e3;
7
+ var RUN_CODE_CONSOLE_SETUP = `
8
+ globalThis.__out = [];
9
+ globalThis.console = {
10
+ log: function () { globalThis.__out.push(Array.prototype.map.call(arguments, String).join(' ')) },
11
+ error: function () { globalThis.__out.push('ERROR: ' + Array.prototype.map.call(arguments, String).join(' ')) },
12
+ warn: function () { globalThis.__out.push('WARN: ' + Array.prototype.map.call(arguments, String).join(' ')) },
13
+ };
14
+ `;
15
+ var RUN_CODE_JOIN_OUTPUT = `
16
+ Array.isArray(globalThis.__out)
17
+ ? Array.prototype.join.call(Array.prototype.map.call(globalThis.__out, String), '\\n')
18
+ : ''
19
+ `;
20
+ var RUN_CODE_DENY_EXTERNAL_MEMORY = `
21
+ (function () {
22
+ var g = globalThis, TypedArrayProto = null, names = Object.getOwnPropertyNames(g);
23
+ for (var i = 0; i < names.length; i++) {
24
+ var v; try { v = g[names[i]] } catch (e) { continue }
25
+ if (typeof v === 'function' && /Array$/.test(names[i]) && v !== Array) {
26
+ var p = Object.getPrototypeOf(v);
27
+ if (typeof p === 'function' && p.name === 'TypedArray') { TypedArrayProto = p; break }
28
+ }
29
+ }
30
+ for (var j = 0; j < names.length; j++) {
31
+ var n = names[j], val; try { val = g[n] } catch (e) { continue }
32
+ if (n === 'ArrayBuffer' || n === 'SharedArrayBuffer' || n === 'DataView' || n === 'WebAssembly' || n === 'Atomics'
33
+ || (typeof val === 'function' && TypedArrayProto && Object.getPrototypeOf(val) === TypedArrayProto)) {
34
+ delete g[n]
35
+ }
36
+ }
37
+ })();
38
+ `;
39
+ var RUN_CODE_SANITIZE_STACK_TRACES = `
40
+ Error.prepareStackTrace = function (err) { return err.name + ': ' + err.message };
41
+ `;
42
+ function runCodeInSandbox(code) {
43
+ const context = createContext(/* @__PURE__ */ Object.create(null));
44
+ let result;
45
+ try {
46
+ runInContext(RUN_CODE_CONSOLE_SETUP, context, { timeout: RUN_CODE_SETUP_TIMEOUT_MS });
47
+ runInContext(RUN_CODE_DENY_EXTERNAL_MEMORY, context, { timeout: RUN_CODE_SETUP_TIMEOUT_MS });
48
+ runInContext(RUN_CODE_SANITIZE_STACK_TRACES, context, { timeout: RUN_CODE_SETUP_TIMEOUT_MS });
49
+ result = runInContext(
50
+ `(function(){
51
+ const __result = (function(){${code}})();
52
+ if (__result === undefined) return undefined;
53
+ if (typeof __result === 'string') return __result;
54
+ try { return JSON.stringify(__result, null, 2); }
55
+ catch (e) { try { return String(__result); } catch (e2) { return '[unstringifiable result]'; } }
56
+ })()`,
57
+ context,
58
+ { timeout: RUN_CODE_TIMEOUT_MS }
59
+ );
60
+ } catch (e) {
61
+ let message = "unknown error";
62
+ try {
63
+ message = String(e?.message ?? e);
64
+ } catch {
65
+ }
66
+ return `Error: ${message}`;
67
+ }
68
+ let output = "";
69
+ try {
70
+ const joined = runInContext(RUN_CODE_JOIN_OUTPUT, context, { timeout: RUN_CODE_SETUP_TIMEOUT_MS });
71
+ if (typeof joined === "string") output = joined;
72
+ } catch {
73
+ }
74
+ const parts = [];
75
+ if (output) parts.push(output);
76
+ if (typeof result === "string") parts.push(result);
77
+ return parts.join("\n") || "(no output)";
78
+ }
79
+
80
+ export {
81
+ RUN_CODE_TIMEOUT_MS,
82
+ RUN_CODE_SETUP_TIMEOUT_MS,
83
+ runCodeInSandbox
84
+ };
package/dist/cli.js CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ RUN_CODE_TIMEOUT_MS
4
+ } from "./chunk-QIEQAXY4.js";
2
5
  import {
3
6
  buildShellCommand,
4
7
  quotePtyShellArg
@@ -3475,6 +3478,10 @@ function tagFromManagedBinPath(binPath) {
3475
3478
  const m = /[\\/]engines[\\/]llama\.cpp-([^\\/]+?)-(?:cuda|rocm|sycl|vulkan|metal|cpu)[\\/]/.exec(binPath);
3476
3479
  return m ? m[1] : "";
3477
3480
  }
3481
+ function backendIdFromBinPath(binPath) {
3482
+ const m = /[\\/]engines[\\/]llama\.cpp-[^\\/]+?-(cuda|rocm|sycl|vulkan|metal|cpu)[\\/]/.exec(binPath);
3483
+ return m ? m[1] : "";
3484
+ }
3478
3485
  function tagFromVersionString(version2) {
3479
3486
  const m = /\bb\d+\b/i.exec(version2);
3480
3487
  return m ? m[0] : "";
@@ -4107,7 +4114,7 @@ async function applyEngineUpdate(d, engine, signal) {
4107
4114
  throw new Error("This engine has no automatic update source.");
4108
4115
  }
4109
4116
  async function applyLlamaCppUpdate(d, engine, root, signal) {
4110
- const backendId = backendIdOf(engine.binPath);
4117
+ const backendId = backendIdFromBinPath(engine.binPath);
4111
4118
  if (!backendId) throw new Error("Could not determine the GPU backend of this build.");
4112
4119
  const installedTag = tagFromManagedBinPath(engine.binPath);
4113
4120
  const latestTag = await latestReleaseTag(OFFICIAL_LLAMA_REPO2, signal);
@@ -4220,10 +4227,6 @@ async function applyPipUpdate(d, kind, engine, root) {
4220
4227
  throw e;
4221
4228
  }
4222
4229
  }
4223
- function backendIdOf(binPath) {
4224
- const m = /[\\/]engines[\\/]llama\.cpp-[^\\/]+?-(cuda|rocm|sycl|vulkan|metal|cpu)[\\/]/.exec(binPath);
4225
- return m ? m[1] : null;
4226
- }
4227
4230
  function msg(e) {
4228
4231
  return e instanceof Error ? e.message : String(e);
4229
4232
  }
@@ -5252,10 +5255,18 @@ function resolveProfile(m, sys, saved, overrides, defaults) {
5252
5255
  useMmproj: m.vision
5253
5256
  };
5254
5257
  }
5255
- function profileToArgs(p, m, caps, cores = 0) {
5258
+ var ROCM_APU_NOMMAP_MIN_BYTES = 30 * 1024 ** 3;
5259
+ function isRocmUnifiedApuLoad(m, sys, binPath) {
5260
+ if (!sys || !binPath) return false;
5261
+ if (m.sizeBytes < ROCM_APU_NOMMAP_MIN_BYTES) return false;
5262
+ if (backendIdFromBinPath(binPath) !== "rocm") return false;
5263
+ return sys.gpus.some((g) => g.vendor === "amd" && g.unified);
5264
+ }
5265
+ function profileToArgs(p, m, caps, cores = 0, sys, binPath) {
5256
5266
  const has = (flag) => caps.flags.length === 0 || caps.flags.includes(flag);
5257
5267
  const a = ["-c", String(p.ctx)];
5258
- if ((!p.nglFit || m.moe) && p.ngl > 0) a.push("-ngl", String(p.ngl));
5268
+ const moeAutoFit = m.moe && p.nCpuMoeFit;
5269
+ if (!moeAutoFit && (!p.nglFit || m.moe) && p.ngl > 0) a.push("-ngl", String(p.ngl));
5259
5270
  const g = p.gpu;
5260
5271
  if (g) {
5261
5272
  if (g.splitMode !== "layer" && has("--split-mode")) a.push("--split-mode", g.splitMode);
@@ -5325,6 +5336,9 @@ function profileToArgs(p, m, caps, cores = 0) {
5325
5336
  }
5326
5337
  if (m.embedding && has("--embeddings")) a.push("--embeddings");
5327
5338
  if (p.grammar && has("--grammar")) a.push("--grammar", p.grammar);
5339
+ if (isRocmUnifiedApuLoad(m, sys, binPath) && has("--no-mmap") && !p.extraArgs.includes("--no-mmap") && !p.extraArgs.includes("-dio")) {
5340
+ a.push("--no-mmap");
5341
+ }
5328
5342
  a.push(...p.extraArgs);
5329
5343
  return a;
5330
5344
  }
@@ -7566,7 +7580,7 @@ var FEATURES = [
7566
7580
  "skills",
7567
7581
  "image"
7568
7582
  ];
7569
- var ONBOARDING_STEPS = ["engine_install", "engine_build", "model_download", "first_load"];
7583
+ var ONBOARDING_STEPS = ["engine_install", "model_download", "first_load", "first_chat"];
7570
7584
  var OUTCOMES = ["ok", "fail", "cancelled"];
7571
7585
  var FAIL_REASONS = [
7572
7586
  "oom",
@@ -8346,7 +8360,7 @@ var BenchRunner = class {
8346
8360
  engine: active,
8347
8361
  model: { key: entry.key, name: entry.name, quant: entry.quant, ctx: profile.ctx, vision: entry.vision },
8348
8362
  modelPath: entry.path,
8349
- extraArgs: profileToArgs(profile, entry, caps, sys.cores)
8363
+ extraArgs: profileToArgs(profile, entry, caps, sys.cores, sys, active.binPath)
8350
8364
  };
8351
8365
  try {
8352
8366
  await this.manager.start(opts);
@@ -8423,7 +8437,7 @@ var BenchRunner = class {
8423
8437
  engine: active,
8424
8438
  model: { key: entry.key, name: entry.name, quant: entry.quant, ctx: profile.ctx, vision: entry.vision },
8425
8439
  modelPath: entry.path,
8426
- extraArgs: profileToArgs(profile, entry, caps, sys.cores)
8440
+ extraArgs: profileToArgs(profile, entry, caps, sys.cores, sys, active.binPath)
8427
8441
  };
8428
8442
  const vramBefore = await readGpuVramMb(sys);
8429
8443
  phase("loading model\u2026");
@@ -8714,7 +8728,7 @@ var BenchRunner = class {
8714
8728
  engine: active,
8715
8729
  model: { key: entry.key, name: entry.name, quant: entry.quant, ctx: profile.ctx, vision: entry.vision },
8716
8730
  modelPath: entry.path,
8717
- extraArgs: profileToArgs(profile, entry, caps, sys.cores)
8731
+ extraArgs: profileToArgs(profile, entry, caps, sys.cores, sys, active.binPath)
8718
8732
  };
8719
8733
  try {
8720
8734
  await this.manager.start(opts);
@@ -9305,7 +9319,7 @@ var ModelRouter = class {
9305
9319
  }
9306
9320
  const saved = getModelProfile(cfg2, entry.key, engine.id);
9307
9321
  const profile = resolveProfile(entry, sys, saved, void 0, cfg2.modelDefaults);
9308
- const extraArgs = engine.kind === "koboldcpp" ? koboldcppProfileToArgs(profile, sys.gpus[0]?.vendor ?? "unknown", sys.gpus.length > 0) : profileToArgs(profile, entry, engine.capabilities, sys.cores);
9322
+ const extraArgs = engine.kind === "koboldcpp" ? koboldcppProfileToArgs(profile, sys.gpus[0]?.vendor ?? "unknown", sys.gpus.length > 0) : profileToArgs(profile, entry, engine.capabilities, sys.cores, sys, engine.binPath);
9309
9323
  return {
9310
9324
  engine,
9311
9325
  model: { key: entry.key, name: entry.name, quant: entry.quant, ctx: profile.ctx, vision: entry.vision },
@@ -9316,7 +9330,7 @@ var ModelRouter = class {
9316
9330
  };
9317
9331
 
9318
9332
  // src/tools/builtin.ts
9319
- import { runInNewContext } from "vm";
9333
+ import { Worker } from "worker_threads";
9320
9334
 
9321
9335
  // src/tools/security.ts
9322
9336
  import { lookup } from "dns/promises";
@@ -10275,48 +10289,79 @@ async function execFetchUrl(args) {
10275
10289
  return `${header}
10276
10290
  ${content || "(empty response)"}`;
10277
10291
  }
10278
- function execRunCode(args) {
10292
+ var WORKER_EXT = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
10293
+ var WORKER_PATH = new URL(`./run-code-worker${WORKER_EXT}`, import.meta.url);
10294
+ var RUN_CODE_WATCHDOG_MS = RUN_CODE_TIMEOUT_MS + 1e3;
10295
+ var RUN_CODE_MAX_CONCURRENT_WORKERS = 4;
10296
+ var activeRunCodeWorkers = 0;
10297
+ var runCodeWaiters = [];
10298
+ function acquireRunCodeSlot() {
10299
+ if (activeRunCodeWorkers < RUN_CODE_MAX_CONCURRENT_WORKERS) {
10300
+ activeRunCodeWorkers++;
10301
+ return Promise.resolve();
10302
+ }
10303
+ return new Promise((resolve5) => {
10304
+ runCodeWaiters.push(() => {
10305
+ activeRunCodeWorkers++;
10306
+ resolve5();
10307
+ });
10308
+ });
10309
+ }
10310
+ function releaseRunCodeSlot() {
10311
+ activeRunCodeWorkers--;
10312
+ runCodeWaiters.shift()?.();
10313
+ }
10314
+ async function execRunCode(args) {
10279
10315
  const code = String(args.code ?? "").trim();
10280
10316
  if (!code) return "Error: code is required.";
10281
- const output = [];
10282
- const sandbox = {
10283
- console: {
10284
- log: (...a) => output.push(a.map(String).join(" ")),
10285
- error: (...a) => output.push("ERROR: " + a.map(String).join(" ")),
10286
- warn: (...a) => output.push("WARN: " + a.map(String).join(" "))
10287
- },
10288
- Math,
10289
- JSON,
10290
- Array,
10291
- Object,
10292
- String,
10293
- Number,
10294
- Boolean,
10295
- Date,
10296
- RegExp,
10297
- parseInt,
10298
- parseFloat,
10299
- isNaN,
10300
- isFinite,
10301
- encodeURIComponent,
10302
- decodeURIComponent
10303
- };
10304
- let result;
10317
+ await acquireRunCodeSlot();
10318
+ let worker;
10305
10319
  try {
10306
- result = runInNewContext(`(function(){${code}})()`, sandbox, { timeout: 5e3 });
10320
+ worker = new Worker(WORKER_PATH, {
10321
+ workerData: { code },
10322
+ // No environment/argv leak into the worker: the vm sandbox (run-code-sandbox.ts) is what
10323
+ // actually keeps sandboxed code from ever seeing `process`, but if that boundary were ever
10324
+ // defeated by a V8/Node bug, the worker's OWN real `process.env` — every secret/API key the
10325
+ // daemon can see — would otherwise sit right there. Costs nothing legitimate: the sandboxed
10326
+ // script never has ambient `process` access to read `env`/`argv` either way.
10327
+ env: {},
10328
+ argv: [],
10329
+ // Bounds the V8 JS heap THIS script's vm context can allocate (vm.createContext shares the
10330
+ // worker's own isolate, so these limits cover it) to a crash of just this worker, not the
10331
+ // daemon process — confirmed for arrays/strings/objects, the allocation shapes the deleted
10332
+ // ArrayBuffer/typed-array constructors (run-code-sandbox.ts) would otherwise let bypass this
10333
+ // entirely as unbounded external memory. A BigInt-heavy allocation pattern can still exceed
10334
+ // this nominal cap, since V8 doesn't charge all BigInt scratch space against the generational
10335
+ // heap limits the same way; not a realm escape (still contained to this one worker), just a
10336
+ // softer memory ceiling than the numbers imply.
10337
+ resourceLimits: { maxOldGenerationSizeMb: 128, maxYoungGenerationSizeMb: 16 }
10338
+ });
10307
10339
  } catch (e) {
10340
+ releaseRunCodeSlot();
10308
10341
  return `Error: ${e.message}`;
10309
10342
  }
10310
- const parts = [];
10311
- if (output.length > 0) parts.push(output.join("\n"));
10312
- if (result !== void 0) {
10313
- try {
10314
- parts.push(typeof result === "string" ? result : JSON.stringify(result, null, 2));
10315
- } catch {
10316
- parts.push(String(result));
10317
- }
10318
- }
10319
- return parts.join("\n") || "(no output)";
10343
+ return new Promise((resolve5) => {
10344
+ let settled = false;
10345
+ const finish = (value) => {
10346
+ if (settled) return;
10347
+ settled = true;
10348
+ clearTimeout(watchdog);
10349
+ resolve5(value);
10350
+ releaseRunCodeSlot();
10351
+ void worker.terminate().catch(() => {
10352
+ });
10353
+ };
10354
+ const watchdog = setTimeout(() => finish("Error: execution timed out"), RUN_CODE_WATCHDOG_MS);
10355
+ worker.once("message", (msg2) => {
10356
+ finish(typeof msg2 === "string" ? msg2 : "Error: worker returned a non-string result");
10357
+ });
10358
+ worker.once("error", (err7) => {
10359
+ finish(`Error: ${err7.message}`);
10360
+ });
10361
+ worker.once("exit", (exitCode) => {
10362
+ if (!settled) finish(exitCode === 0 ? "Error: worker exited unexpectedly" : `Error: worker exited with code ${exitCode}`);
10363
+ });
10364
+ });
10320
10365
  }
10321
10366
 
10322
10367
  // src/tools/mcp-client.ts
@@ -12932,6 +12977,12 @@ function getLanIpForShare() {
12932
12977
  }
12933
12978
  return "127.0.0.1";
12934
12979
  }
12980
+ function reportFirstChat(dataDir, emitter, outcome) {
12981
+ if (!emitter) return;
12982
+ if (!emitter.canSend("onboarding_step")) return;
12983
+ if (!claimOnce(dataDir, "once:onboarding_step:first_chat")) return;
12984
+ emitter.emit("onboarding_step", { step: "first_chat", outcome });
12985
+ }
12935
12986
  async function runGeneration(d, stream, ctx) {
12936
12987
  const { db: db2 } = d;
12937
12988
  const { convId, conv, assistantMsg, ms, target, ac, thinkingBudget } = ctx;
@@ -13007,6 +13058,7 @@ After reviewing the search results, include a confidence assessment on a line by
13007
13058
  let finalUsage = {};
13008
13059
  let finalTimings = {};
13009
13060
  let aborted = false;
13061
+ let engineFailed = false;
13010
13062
  let liveOut = 0;
13011
13063
  d.manager.generationStart();
13012
13064
  try {
@@ -13054,6 +13106,7 @@ After reviewing the search results, include a confidence assessment on a line by
13054
13106
  });
13055
13107
  if (!res.ok || !res.body) {
13056
13108
  await stream.writeSSE({ event: "error", data: JSON.stringify({ code: "engine_error", message: `Engine returned ${res.status}` }) });
13109
+ reportFirstChat(d.store.dir(), d.telemetry, "fail");
13057
13110
  return;
13058
13111
  }
13059
13112
  const reader = res.body.getReader();
@@ -13360,6 +13413,7 @@ After reviewing the search results, include a confidence assessment on a line by
13360
13413
  const isAbort = e?.name === "AbortError";
13361
13414
  aborted = isAbort;
13362
13415
  if (!isAbort) {
13416
+ engineFailed = true;
13363
13417
  await stream.writeSSE({ event: "error", data: JSON.stringify({ code: "engine_stopped", message: e.message }) });
13364
13418
  }
13365
13419
  } finally {
@@ -13413,6 +13467,7 @@ After reviewing the search results, include a confidence assessment on a line by
13413
13467
  } : void 0;
13414
13468
  db2.updateMessage(assistantMsg.id, { content: fullContent, reasoning: fullReasoning, toolCalls: allToolCalls, stats, researchMeta });
13415
13469
  db2.touchConversation(convId);
13470
+ reportFirstChat(d.store.dir(), d.telemetry, aborted ? "cancelled" : engineFailed ? "fail" : "ok");
13416
13471
  try {
13417
13472
  d.manager.recordCompletion({
13418
13473
  inputTokens: stats.promptTokens,
@@ -16215,7 +16270,7 @@ function registerApi(app2, d) {
16215
16270
  } else {
16216
16271
  const saved = getModelProfile(cfg2, entry.key, active.id);
16217
16272
  const profile = resolveProfile(entry, sys, saved, b.profileOverrides, cfg2.modelDefaults);
16218
- const extraArgs = active.kind === "koboldcpp" ? koboldcppProfileToArgs(profile, primaryVendor(sys), sys.gpus.length > 0) : profileToArgs(profile, entry, active.capabilities, sys.cores);
16273
+ const extraArgs = active.kind === "koboldcpp" ? koboldcppProfileToArgs(profile, primaryVendor(sys), sys.gpus.length > 0) : profileToArgs(profile, entry, active.capabilities, sys.cores, sys, active.binPath);
16219
16274
  opts2 = {
16220
16275
  engine: active,
16221
16276
  model: { key: entry.key, name: entry.name, quant: entry.quant, ctx: profile.ctx, vision: entry.vision },
@@ -22614,7 +22669,6 @@ manager.onLoadSettled = (ok, err7) => {
22614
22669
  reportModelLoad(store.dir(), telemetry, outcome, ok ? void 0 : classifyLoadFailure(err7));
22615
22670
  };
22616
22671
  bench.telemetry = telemetry;
22617
- build.onSettled = (ok) => telemetry.emit("onboarding_step", { step: "engine_build", outcome: ok ? "ok" : "fail" });
22618
22672
  provision.onSettled = (ok) => telemetry.emit("onboarding_step", { step: "engine_install", outcome: ok ? "ok" : "fail" });
22619
22673
  downloads.onSettled = (outcome) => telemetry.emit("onboarding_step", { step: "model_download", outcome });
22620
22674
  setTimeout(() => {
@@ -22842,7 +22896,7 @@ void (async () => {
22842
22896
  engine: active,
22843
22897
  model: { key: entry.key, name: entry.name, quant: entry.quant, ctx: profile.ctx, vision: entry.vision },
22844
22898
  modelPath: entry.path,
22845
- extraArgs: profileToArgs(profile, entry, active.capabilities, sys.cores)
22899
+ extraArgs: profileToArgs(profile, entry, active.capabilities, sys.cores, sys, active.binPath)
22846
22900
  };
22847
22901
  }
22848
22902
  } else if (cfg.devModel) {
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ RUN_CODE_SETUP_TIMEOUT_MS,
4
+ RUN_CODE_TIMEOUT_MS,
5
+ runCodeInSandbox
6
+ } from "./chunk-QIEQAXY4.js";
7
+ export {
8
+ RUN_CODE_SETUP_TIMEOUT_MS,
9
+ RUN_CODE_TIMEOUT_MS,
10
+ runCodeInSandbox
11
+ };
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/tools/run-code-worker.ts
4
+ import { parentPort, workerData } from "worker_threads";
5
+ var SANDBOX_EXT = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
6
+ var SANDBOX_URL = new URL(`./run-code-sandbox${SANDBOX_EXT}`, import.meta.url);
7
+ var { runCodeInSandbox } = await import(SANDBOX_URL.href);
8
+ if (!parentPort) {
9
+ throw new Error("run-code-worker.ts must be run as a worker_threads Worker, not imported directly.");
10
+ }
11
+ var code = String(workerData?.code ?? "");
12
+ parentPort.postMessage(runCodeInSandbox(code));
@@ -1 +1 @@
1
- import{j as e}from"./radix-j_81dozL.js";import{u as M,b as W,r as b}from"./vendor-BFom-Mq6.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-BQecSQnE.js";import{f as U}from"./chat-api-D8Zk6kRh.js";import{f as V,a as X}from"./agent-api-B8x62EvQ.js";import{P as z}from"./personas-DjECKK03.js";import{C as Z}from"./chevron-left-BwGlXiTi.js";import{R as ee}from"./rotate-ccw-CTVQYcfd.js";import{T as te}from"./trash-2-D0azs_Tt.js";import{C as se}from"./chevron-right-B8nbhuzl.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-j_81dozL.js";import{u as M,b as W,r as b}from"./vendor-BFom-Mq6.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-C0Cl7zDd.js";import{f as U}from"./chat-api-4_WMcoaf.js";import{f as V,a as X}from"./agent-api-D3ifA1i1.js";import{P as z}from"./personas-DhDGxLXM.js";import{C as Z}from"./chevron-left-MKKbFVwZ.js";import{R as ee}from"./rotate-ccw-DR_KW7ek.js";import{T as te}from"./trash-2-Dbm39wTN.js";import{C as se}from"./chevron-right-Dyu5POuN.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};