turbollm 1.11.0 → 1.11.1

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 (136) hide show
  1. package/README.md +3 -0
  2. package/dist/cli.js +163 -21
  3. package/dist/webdist/assets/AgentEditPage-D5ccnu5s.js +1 -0
  4. package/dist/webdist/assets/{ChatScreen-DWR0twnC.js → ChatScreen-BygO8zb3.js} +15 -15
  5. package/dist/webdist/assets/CodeComposer-BTpMVTCA.js +1 -0
  6. package/dist/webdist/assets/CodeHomeScreen-Cz7tsGIS.js +1 -0
  7. package/dist/webdist/assets/{CodeSessionScreen-CwBa11Jt.js → CodeSessionScreen-CFIAgEJ7.js} +12 -12
  8. package/dist/webdist/assets/{CustomizeScreen-CD-WTBXb.js → CustomizeScreen-7zLa19h5.js} +1 -1
  9. package/dist/webdist/assets/{DeveloperScreen-CESuUPIA.js → DeveloperScreen-e8_tLsWt.js} +1 -1
  10. package/dist/webdist/assets/{EnginesScreen-BhdKIPyX.js → EnginesScreen-hn6IM67U.js} +2 -2
  11. package/dist/webdist/assets/ModelDetailDialog-DN-kl63r.js +1 -0
  12. package/dist/webdist/assets/ModelLoadMenu-Dgy2n0qW.js +1 -0
  13. package/dist/webdist/assets/{ModelsScreen-m-cbkQfg.js → ModelsScreen-COQU83v_.js} +2 -2
  14. package/dist/webdist/assets/OnboardingScreen-BcjUSBAv.js +1 -0
  15. package/dist/webdist/assets/RoutineEditPage-BtYITioy.js +1 -0
  16. package/dist/webdist/assets/RoutinesPanel-DnnVr9g2.js +1 -0
  17. package/dist/webdist/assets/SettingsScreen-0NoDCta7.js +2 -0
  18. package/dist/webdist/assets/SidebarResizeHandle-DCZXIwhU.js +2 -0
  19. package/dist/webdist/assets/{SkillEditPage-BPMWlPxr.js → SkillEditPage-B157ySq9.js} +1 -1
  20. package/dist/webdist/assets/{TokensScreen-C78YBwfC.js → TokensScreen-DoYPjv6Y.js} +1 -1
  21. package/dist/webdist/assets/{ToolApprovalBar-D6Usabbc.js → ToolApprovalBar-ChYJChYS.js} +4 -4
  22. package/dist/webdist/assets/WorkspaceScreen-BrA4DSov.js +1 -0
  23. package/dist/webdist/assets/{abnfDiagram-N423BO3Z-EMmaHj8K.js → abnfDiagram-N423BO3Z-YE0PLBtD.js} +1 -1
  24. package/dist/webdist/assets/{agent-api-Vpc7M2SN.js → agent-api-DyPUCnyd.js} +1 -1
  25. package/dist/webdist/assets/{alert-dialog-RuoeJJC-.js → alert-dialog-mb66t64A.js} +1 -1
  26. package/dist/webdist/assets/{arc-BHeddvY-.js → arc-D6tB7EyD.js} +1 -1
  27. package/dist/webdist/assets/{architectureDiagram-T3A2C74G-B9vPWlm9.js → architectureDiagram-T3A2C74G-CC_g3uHG.js} +1 -1
  28. package/dist/webdist/assets/{arrow-left-QxWpxvpD.js → arrow-left-B0kOOTXf.js} +1 -1
  29. package/dist/webdist/assets/{badge-WQ1wLWtz.js → badge-BaPl3cu1.js} +1 -1
  30. package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-DF9hv8Mn.js → blockDiagram-VBNYF7ZC-CDFisfPP.js} +1 -1
  31. package/dist/webdist/assets/{bot-BkUld4bs.js → bot-DQc34hdo.js} +1 -1
  32. package/dist/webdist/assets/{c4Diagram-5PPSVZJV-DiyHHtjq.js → c4Diagram-5PPSVZJV-Df9WlHJi.js} +1 -1
  33. package/dist/webdist/assets/channel-rIJvIL9_.js +1 -0
  34. package/dist/webdist/assets/chat-api-B7cm_Kjj.js +3 -0
  35. package/dist/webdist/assets/{chat-queries-RLSOlOWo.js → chat-queries-vBDT6raC.js} +1 -1
  36. package/dist/webdist/assets/chevron-down-D3qQII2-.js +1 -0
  37. package/dist/webdist/assets/{chevron-left-CP9IFIJY.js → chevron-left-BQ3TyvUR.js} +1 -1
  38. package/dist/webdist/assets/{chevron-right-DrIMoQSz.js → chevron-right-C1TzfDRc.js} +1 -1
  39. package/dist/webdist/assets/{chunk-2GRJ4B5K-CCSTGpfU.js → chunk-2GRJ4B5K--fTNBTKb.js} +1 -1
  40. package/dist/webdist/assets/{chunk-2Q5K7J3B-DhLcfa9a.js → chunk-2Q5K7J3B-BE2H2UHk.js} +1 -1
  41. package/dist/webdist/assets/{chunk-5RXB4S5H-DS_Jjker.js → chunk-5RXB4S5H-C-ps6IJo.js} +1 -1
  42. package/dist/webdist/assets/{chunk-5VM5RSS4-DR8jriPd.js → chunk-5VM5RSS4-Dr6Y-wsq.js} +1 -1
  43. package/dist/webdist/assets/{chunk-6Q2QTUOP-CvvshdRt.js → chunk-6Q2QTUOP-CFP_W3le.js} +1 -1
  44. package/dist/webdist/assets/{chunk-GF5L2VYU-Bn_W4FqO.js → chunk-GF5L2VYU-eS8r3XDQ.js} +1 -1
  45. package/dist/webdist/assets/{chunk-JWPE2WC7-BbyR5jPI.js → chunk-JWPE2WC7-CnHOI6Vb.js} +1 -1
  46. package/dist/webdist/assets/{chunk-KBJHAD2P-CapiPaai.js → chunk-KBJHAD2P-DjKuoeJv.js} +1 -1
  47. package/dist/webdist/assets/{chunk-RYQCIY6F-o0Eobs4I.js → chunk-RYQCIY6F-BCZSATDq.js} +1 -1
  48. package/dist/webdist/assets/{chunk-XXDRQBXY-DnfM_6_z.js → chunk-XXDRQBXY-6vDQpKbX.js} +1 -1
  49. package/dist/webdist/assets/{circle-check-Dfy4urT3.js → circle-check-CayQ1Kmr.js} +1 -1
  50. package/dist/webdist/assets/{circle-x-CTrNBFyk.js → circle-x-DBL77ehg.js} +1 -1
  51. package/dist/webdist/assets/classDiagram-JCYQIIEL-CKHNwlA2.js +1 -0
  52. package/dist/webdist/assets/classDiagram-v2-OCEON4UE-CKHNwlA2.js +1 -0
  53. package/dist/webdist/assets/{common-D3KIhI5Z.js → common-COkt_JGo.js} +1 -1
  54. package/dist/webdist/assets/{cose-bilkent-JH36ORCC-CVGwTg6K.js → cose-bilkent-JH36ORCC-CPMWY99B.js} +1 -1
  55. package/dist/webdist/assets/{cynefin-VYW2F7L2-B_cdEt0j.js → cynefin-VYW2F7L2-DCemwV3Z.js} +1 -1
  56. package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-D6Bq1Hb9.js → cynefinDiagram-MW4NZA55-B8HcUCjZ.js} +1 -1
  57. package/dist/webdist/assets/{dagre-VZM6K2ZE-BZBXLl5P.js → dagre-VZM6K2ZE-BC6lGXyw.js} +1 -1
  58. package/dist/webdist/assets/{diagram-7IWD3JNH-CfaI5HQ5.js → diagram-7IWD3JNH-CQSNxirf.js} +1 -1
  59. package/dist/webdist/assets/{diagram-B4RE2ZJO-CHTmK73T.js → diagram-B4RE2ZJO-D6Ot6ZYA.js} +1 -1
  60. package/dist/webdist/assets/{diagram-LBJQPF4R-Cv1djbM6.js → diagram-LBJQPF4R-D775f1Jb.js} +1 -1
  61. package/dist/webdist/assets/{diagram-Q27KOJAE-wH1umxXP.js → diagram-Q27KOJAE-aedYX_I3.js} +1 -1
  62. package/dist/webdist/assets/{diagram-UB23O5K3-DjVjVgky.js → diagram-UB23O5K3-DyKXvxFs.js} +1 -1
  63. package/dist/webdist/assets/dropdown-menu-Co-9JBK7.js +1 -0
  64. package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-CnP6v0OA.js → ebnfDiagram-BXEA7PRR-Dmyl6hgX.js} +1 -1
  65. package/dist/webdist/assets/{erDiagram-JOGREHBK-Bxvus2yH.js → erDiagram-JOGREHBK-DQ61Ftq2.js} +1 -1
  66. package/dist/webdist/assets/{external-link-BYxejPiV.js → external-link-DeGazJd7.js} +1 -1
  67. package/dist/webdist/assets/file-text-BqSocdvg.js +1 -0
  68. package/dist/webdist/assets/{flowDiagram-UKHOOZJN-Cs1rV3tb.js → flowDiagram-UKHOOZJN-DpF0SMmj.js} +1 -1
  69. package/dist/webdist/assets/{folder-input-BtJHHiyW.js → folder-input-fLAI3sbE.js} +1 -1
  70. package/dist/webdist/assets/{folder-plus-Ch-KIy_j.js → folder-plus-kUhRq8Qs.js} +1 -1
  71. package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-DbKmBS-m.js → ganttDiagram-PKOTCBZU-C9hM2RtH.js} +1 -1
  72. package/dist/webdist/assets/{git-branch-C0tnpEBn.js → git-branch-BLvbsQlx.js} +1 -1
  73. package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-XiTtBrMy.js → gitGraphDiagram-DS77QQ5N-F-m07GU8.js} +1 -1
  74. package/dist/webdist/assets/{index-DgjAtL-b.js → index-Djd745uq.js} +2 -2
  75. package/dist/webdist/assets/{infoDiagram-6WML65LV-VAFHBPFv.js → infoDiagram-6WML65LV-SU_VZ3kP.js} +1 -1
  76. package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-CltvpCC_.js → ishikawaDiagram-WSZJBQD7-CPGrHUJl.js} +1 -1
  77. package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-B8O_4rAi.js → journeyDiagram-NVQOT4AX-xSn5t7m_.js} +1 -1
  78. package/dist/webdist/assets/{kanban-definition-27J2QSJJ-PuuqAhDK.js → kanban-definition-27J2QSJJ-BP6v9V-b.js} +1 -1
  79. package/dist/webdist/assets/{linear-BzcDsYCl.js → linear-CrWjOgAX.js} +1 -1
  80. package/dist/webdist/assets/{lock-NjhtB3l7.js → lock-CMnk_C6j.js} +1 -1
  81. package/dist/webdist/assets/{mermaid.core--ItM_Tuo.js → mermaid.core-Daad9FCu.js} +4 -4
  82. package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-DA4CwvE8.js → mindmap-definition-FAOFIHXS-BdQNGzcB.js} +1 -1
  83. package/dist/webdist/assets/{pegDiagram-VL7TDLO6-pcbWVCJ3.js → pegDiagram-VL7TDLO6-BVO3lisg.js} +1 -1
  84. package/dist/webdist/assets/{pencil-C7Mm5Xtr.js → pencil-CLqNgcwe.js} +1 -1
  85. package/dist/webdist/assets/{personas-DUC47oth.js → personas-Bdrl3tL6.js} +2 -1
  86. package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-BY35jaW3.js → pieDiagram-7S7Q4E2Y-I0avJ0HP.js} +1 -1
  87. package/dist/webdist/assets/{plus-DvEO8E95.js → plus-CZ50K8Az.js} +1 -1
  88. package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-C5mpyBRe.js → quadrantDiagram-CIZ2JOQS-BoKPRmFq.js} +1 -1
  89. package/dist/webdist/assets/{railroadDiagram-AXF67PYL-DWTf-dRS.js → railroadDiagram-AXF67PYL-nuYQFWlg.js} +1 -1
  90. package/dist/webdist/assets/{refresh-cw-BATeQPJY.js → refresh-cw-ZKuYnoI-.js} +1 -1
  91. package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-DBow0Bqr.js → requirementDiagram-LRYGKXZP-BdsVsDe6.js} +1 -1
  92. package/dist/webdist/assets/{rocket-90T43z1Z.js → rocket-DWM7Gy7e.js} +1 -1
  93. package/dist/webdist/assets/{rotate-ccw-C7pm2Mke.js → rotate-ccw-Dl2CDY8F.js} +1 -1
  94. package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-Y3Ppkoun.js → sankeyDiagram-W5VNT64P-oCUC-z0Q.js} +1 -1
  95. package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-CHYIu9uX.js → sequenceDiagram-SI44F4Z6-E17XGC6k.js} +1 -1
  96. package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-B2aHWrTS.js → sizeCapture-X5ZJPWSS-B3ZZ8soS.js} +1 -1
  97. package/dist/webdist/assets/{skeleton-BvAwq7sP.js → skeleton-B2R1iGLZ.js} +1 -1
  98. package/dist/webdist/assets/{sliders-horizontal-DfmwaGs9.js → sliders-horizontal-S1QDbdoj.js} +1 -1
  99. package/dist/webdist/assets/{sparkles-CLTAYDRV.js → sparkles-C1UduBZm.js} +1 -1
  100. package/dist/webdist/assets/{star-CGSbYOmP.js → star-6fg60gkG.js} +1 -1
  101. package/dist/webdist/assets/{stateDiagram-OKZ733FA-COcaEWBl.js → stateDiagram-OKZ733FA-uJ7BcjMS.js} +1 -1
  102. package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-C03mcgmI.js +1 -0
  103. package/dist/webdist/assets/{swimlanes-SLNWSIFB-B5uq0ZSN.js → swimlanes-SLNWSIFB-C5Rg25iw.js} +2 -2
  104. package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-Cnm-o6w8.js +8 -0
  105. package/dist/webdist/assets/{switch-CndaFrl5.js → switch-_T-NWlJj.js} +1 -1
  106. package/dist/webdist/assets/{terminal-C6Twoyfk.js → terminal-jZn2njs8.js} +1 -1
  107. package/dist/webdist/assets/{timeline-definition-Z64GVDOM-CfEDs9k-.js → timeline-definition-Z64GVDOM-DCgYtPRm.js} +1 -1
  108. package/dist/webdist/assets/{trash-2-CtpXI0P6.js → trash-2-C5UxcfNn.js} +1 -1
  109. package/dist/webdist/assets/{triangle-alert-wgQzTmmK.js → triangle-alert-BLYFYhrL.js} +1 -1
  110. package/dist/webdist/assets/{useIsDesktop-C28eAfaZ.js → useIsDesktop-Db8d_FwF.js} +1 -1
  111. package/dist/webdist/assets/{vennDiagram-T6HMQDX7-CjjfGXNg.js → vennDiagram-T6HMQDX7-Bu0txarq.js} +1 -1
  112. package/dist/webdist/assets/{vram-Bz1RMnmc.js → vram-BW-GKnZ2.js} +1 -1
  113. package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y--seBEPmq.js → wardleyDiagram-T6FBY63Y-LfdOSJGM.js} +1 -1
  114. package/dist/webdist/assets/{wrench-CLtGGoX0.js → wrench-R5NYyfgk.js} +1 -1
  115. package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-CbkgQrTE.js → xychartDiagram-ELKLHX3M-CQSLgZgd.js} +1 -1
  116. package/dist/webdist/index.html +1 -1
  117. package/package.json +1 -1
  118. package/dist/webdist/assets/AgentEditPage-Crb8pCTs.js +0 -1
  119. package/dist/webdist/assets/CodeComposer-DTUjWlAE.js +0 -1
  120. package/dist/webdist/assets/CodeHomeScreen-CXfPIHBq.js +0 -1
  121. package/dist/webdist/assets/ModelDetailDialog-D5TNFKk6.js +0 -1
  122. package/dist/webdist/assets/ModelLoadMenu-BbBx7ruU.js +0 -1
  123. package/dist/webdist/assets/OnboardingScreen-CloBv6v8.js +0 -1
  124. package/dist/webdist/assets/RoutineEditPage-CIFrprR0.js +0 -1
  125. package/dist/webdist/assets/RoutinesPanel-DuCSvkpH.js +0 -1
  126. package/dist/webdist/assets/SettingsScreen-CSHExY0c.js +0 -2
  127. package/dist/webdist/assets/SidebarResizeHandle-DPHLGOYS.js +0 -2
  128. package/dist/webdist/assets/WorkspaceScreen-D4VRoaRA.js +0 -1
  129. package/dist/webdist/assets/channel-Dp-qf202.js +0 -1
  130. package/dist/webdist/assets/chat-api-DgmaYhDI.js +0 -3
  131. package/dist/webdist/assets/classDiagram-JCYQIIEL-7lq6N49Q.js +0 -1
  132. package/dist/webdist/assets/classDiagram-v2-OCEON4UE-7lq6N49Q.js +0 -1
  133. package/dist/webdist/assets/dropdown-menu-DtzQnzDC.js +0 -1
  134. package/dist/webdist/assets/file-text-BFFqF1Q-.js +0 -1
  135. package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-DuyS45WN.js +0 -1
  136. package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-C4aR5PY8.js +0 -8
package/README.md CHANGED
@@ -293,6 +293,9 @@ the detail:
293
293
  from Settings → Memory, and turning the toggle off stops new chats from seeing it immediately.
294
294
  - **Thinking-budget control** — a graduated slider, not just on/off: cap reasoning to a specific
295
295
  token count, disable it entirely, or leave it unlimited. Works in Chat and Code alike.
296
+ - **Reasoning-effort control** for models whose own chat template supports it (e.g. Qwen3.8) —
297
+ an Off/Low/Medium/xhigh slider swaps in automatically in place of the thinking-budget one,
298
+ detected per model.
296
299
 
297
300
  </details>
298
301
 
package/dist/cli.js CHANGED
@@ -626,6 +626,35 @@ function setModelProfile(cfg2, modelKey, engineId, profile) {
626
626
  ;
627
627
  (cfg2.modelProfiles[modelKey] ??= {})[engineId] = { profile, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
628
628
  }
629
+ function migrateModelKey(cfg2, oldKey, newKey) {
630
+ if (oldKey === newKey) return false;
631
+ let moved = false;
632
+ if (cfg2.modelProfiles[oldKey] && !cfg2.modelProfiles[newKey]) {
633
+ cfg2.modelProfiles[newKey] = cfg2.modelProfiles[oldKey];
634
+ delete cfg2.modelProfiles[oldKey];
635
+ moved = true;
636
+ }
637
+ if (cfg2.modelPresets[oldKey] && !cfg2.modelPresets[newKey]) {
638
+ cfg2.modelPresets[newKey] = cfg2.modelPresets[oldKey];
639
+ delete cfg2.modelPresets[oldKey];
640
+ moved = true;
641
+ }
642
+ if (cfg2.lastPresetId[oldKey] && !cfg2.lastPresetId[newKey]) {
643
+ cfg2.lastPresetId[newKey] = cfg2.lastPresetId[oldKey];
644
+ delete cfg2.lastPresetId[oldKey];
645
+ moved = true;
646
+ }
647
+ if (cfg2.benchResults[oldKey] && !cfg2.benchResults[newKey]) {
648
+ cfg2.benchResults[newKey] = { ...cfg2.benchResults[oldKey], modelKey: newKey };
649
+ delete cfg2.benchResults[oldKey];
650
+ moved = true;
651
+ }
652
+ if (cfg2.lastLoaded.modelKey === oldKey) {
653
+ cfg2.lastLoaded = { ...cfg2.lastLoaded, modelKey: newKey };
654
+ moved = true;
655
+ }
656
+ return moved;
657
+ }
629
658
  function deleteModelProfile(cfg2, modelKey, engineId) {
630
659
  const byEngine = cfg2.modelProfiles[modelKey];
631
660
  if (!byEngine) return;
@@ -4405,6 +4434,12 @@ function needsExtraPass(content) {
4405
4434
  return stripThinkingBlocks(content).trim() === "";
4406
4435
  }
4407
4436
 
4437
+ // src/chat/reasoning-effort.ts
4438
+ var VALID = /* @__PURE__ */ new Set(["off", "low", "medium", "xhigh"]);
4439
+ function parseReasoningEffort(value) {
4440
+ return typeof value === "string" && VALID.has(value) ? value : void 0;
4441
+ }
4442
+
4408
4443
  // src/tools/research-referee.ts
4409
4444
  var STOP_WORDS = /* @__PURE__ */ new Set([
4410
4445
  "a",
@@ -6509,6 +6544,7 @@ var SessionAuthRegistry = class {
6509
6544
  sessionToToken = /* @__PURE__ */ new Map();
6510
6545
  tokenToSession = /* @__PURE__ */ new Map();
6511
6546
  sessionThinkingBudget = /* @__PURE__ */ new Map();
6547
+ sessionReasoningEffort = /* @__PURE__ */ new Map();
6512
6548
  /** Mint a token for a Code session — idempotent: returns the SAME token on every call for a
6513
6549
  * given session (a reconnect/remount must never invalidate the CLI's already-running auth). */
6514
6550
  mint(codeSessionId) {
@@ -6547,6 +6583,20 @@ var SessionAuthRegistry = class {
6547
6583
  if (!sessionId) return null;
6548
6584
  return this.sessionThinkingBudget.get(sessionId) ?? null;
6549
6585
  }
6586
+ /** Same override mechanism as setThinkingBudget, for reasoning_effort — see that method's
6587
+ * doc comment. Already validated by the caller (parseReasoningEffort); this registry never
6588
+ * re-validates, same as setThinkingBudget trusts its own caller's int coercion. */
6589
+ setReasoningEffort(codeSessionId, effort) {
6590
+ if (effort === null) this.sessionReasoningEffort.delete(codeSessionId);
6591
+ else this.sessionReasoningEffort.set(codeSessionId, effort);
6592
+ }
6593
+ /** The reasoning-effort override for whichever session `token` belongs to, or null when the
6594
+ * token is unrecognized or no override has been set. */
6595
+ getReasoningEffortForToken(token) {
6596
+ const sessionId = this.tokenToSession.get(token);
6597
+ if (!sessionId) return null;
6598
+ return this.sessionReasoningEffort.get(sessionId) ?? null;
6599
+ }
6550
6600
  };
6551
6601
  var sessionAuth = new SessionAuthRegistry();
6552
6602
 
@@ -9063,7 +9113,7 @@ ${content}` : b.docContext : content;
9063
9113
  ...images.map((url) => ({ type: "image_url", image_url: { url } }))
9064
9114
  ] : fullContent;
9065
9115
  engineMessages.push({ role: "user", content: userContent });
9066
- await runGeneration(d, stream, { convId, conv, engineMessages, assistantMsg, ms, target, ac, thinkingBudget: b.thinkingBudget ?? -1, userText: content, isCodeAuthorized });
9116
+ await runGeneration(d, stream, { convId, conv, engineMessages, assistantMsg, ms, target, ac, thinkingBudget: b.thinkingBudget ?? -1, reasoningEffort: parseReasoningEffort(b.reasoningEffort), userText: content, isCodeAuthorized });
9067
9117
  });
9068
9118
  });
9069
9119
  app2.post("/api/v1/conversations/:id/continue", async (c) => {
@@ -9102,7 +9152,7 @@ ${m.reasoning}
9102
9152
  ${m.content}` : m.content;
9103
9153
  engineMessages.push({ role: m.role, content });
9104
9154
  }
9105
- await runGeneration(d, stream, { convId, conv, engineMessages, assistantMsg, ms, target, ac, thinkingBudget: b.thinkingBudget ?? -1, isCodeAuthorized });
9155
+ await runGeneration(d, stream, { convId, conv, engineMessages, assistantMsg, ms, target, ac, thinkingBudget: b.thinkingBudget ?? -1, reasoningEffort: parseReasoningEffort(b.reasoningEffort), isCodeAuthorized });
9106
9156
  });
9107
9157
  });
9108
9158
  app2.post("/api/v1/chat/stop", async (c) => {
@@ -9321,7 +9371,7 @@ function reportChatBenchResult(d, ms, stats) {
9321
9371
  }
9322
9372
  async function runGeneration(d, stream, ctx) {
9323
9373
  const { db: db2 } = d;
9324
- const { convId, conv, assistantMsg, ms, target, ac, thinkingBudget } = ctx;
9374
+ const { convId, conv, assistantMsg, ms, target, ac, thinkingBudget, reasoningEffort } = ctx;
9325
9375
  const convS = conv.sampling ?? {};
9326
9376
  const engineKind = d.registry.active()?.kind ?? "";
9327
9377
  const repeatPenaltyKey = engineKind === "vllm" || engineKind === "sglang" || engineKind === "mlx-vlm" ? "repetition_penalty" : "repeat_penalty";
@@ -9427,6 +9477,12 @@ After reviewing the search results, include a confidence assessment on a line by
9427
9477
  reqBody.thinking_budget_tokens = thinkingBudget;
9428
9478
  }
9429
9479
  if (conv.preserveThinking) templateKwargs.preserve_thinking = true;
9480
+ if (reasoningEffort === "off") {
9481
+ reqBody.thinking_budget_tokens = 0;
9482
+ templateKwargs.enable_thinking = false;
9483
+ } else if (reasoningEffort) {
9484
+ templateKwargs.reasoning_effort = reasoningEffort;
9485
+ }
9430
9486
  if (Object.keys(templateKwargs).length) reqBody.chat_template_kwargs = templateKwargs;
9431
9487
  const toolsSupported = engineKind !== "vllm" && engineKind !== "sglang" && toolDefs.length > 0;
9432
9488
  if (toolsSupported) reqBody.tools = toolDefs;
@@ -9672,6 +9728,12 @@ After reviewing the search results, include a confidence assessment on a line by
9672
9728
  reqBody.thinking_budget_tokens = thinkingBudget;
9673
9729
  }
9674
9730
  if (conv.preserveThinking) templateKwargs.preserve_thinking = true;
9731
+ if (reasoningEffort === "off") {
9732
+ reqBody.thinking_budget_tokens = 0;
9733
+ templateKwargs.enable_thinking = false;
9734
+ } else if (reasoningEffort) {
9735
+ templateKwargs.reasoning_effort = reasoningEffort;
9736
+ }
9675
9737
  if (Object.keys(templateKwargs).length) reqBody.chat_template_kwargs = templateKwargs;
9676
9738
  const res = await fetch(`${target}/v1/chat/completions`, {
9677
9739
  method: "POST",
@@ -10755,7 +10817,7 @@ function pickPrefillProgress(slots) {
10755
10817
  return { processed, total, pct };
10756
10818
  }
10757
10819
  async function runCodeSession(params) {
10758
- const { d, convId, sessionId, repoRoot, mode, thinkingBudget, task: rawTask, signal, sink } = params;
10820
+ const { d, convId, sessionId, repoRoot, mode, thinkingBudget, reasoningEffort, task: rawTask, signal, sink } = params;
10759
10821
  const ms = d.manager.status();
10760
10822
  if (ms.state !== "running" || !ms.model) throw new Error("model_not_loaded");
10761
10823
  const target = d.manager.target();
@@ -11175,6 +11237,20 @@ async function runCodeSession(params) {
11175
11237
  chat_template_kwargs: { ...payload.chat_template_kwargs ?? {}, enable_thinking: false }
11176
11238
  };
11177
11239
  }
11240
+ if (reasoningEffort === "off") {
11241
+ return {
11242
+ ...payload,
11243
+ thinking_budget_tokens: 0,
11244
+ chat_template_kwargs: { ...payload.chat_template_kwargs ?? {}, enable_thinking: false }
11245
+ };
11246
+ }
11247
+ if (reasoningEffort) {
11248
+ return {
11249
+ ...payload,
11250
+ ...thinkingBudget > 0 ? { thinking_budget_tokens: thinkingBudget } : {},
11251
+ chat_template_kwargs: { ...payload.chat_template_kwargs ?? {}, reasoning_effort: reasoningEffort }
11252
+ };
11253
+ }
11178
11254
  if (thinkingBudget > 0) {
11179
11255
  return { ...payload, thinking_budget_tokens: thinkingBudget };
11180
11256
  }
@@ -11913,7 +11989,7 @@ var CodeRunManager = class {
11913
11989
  enqueue(sessionId, params) {
11914
11990
  const s = this.ensure(sessionId, params.convId, params.repoRoot);
11915
11991
  const willQueue = s.active !== null;
11916
- s.queue.push({ task: params.task, userMsgId: params.userMsgId, thinkingBudget: params.thinkingBudget ?? -1, kind: params.kind ?? "followUp" });
11992
+ s.queue.push({ task: params.task, userMsgId: params.userMsgId, thinkingBudget: params.thinkingBudget ?? -1, reasoningEffort: params.reasoningEffort, kind: params.kind ?? "followUp" });
11917
11993
  this.emitQueue(sessionId);
11918
11994
  void this.pump(sessionId);
11919
11995
  return { queued: willQueue };
@@ -12043,6 +12119,7 @@ var CodeRunManager = class {
12043
12119
  repoRoot: s.repoRoot,
12044
12120
  mode,
12045
12121
  thinkingBudget: turn.thinkingBudget,
12122
+ reasoningEffort: turn.reasoningEffort,
12046
12123
  task: turn.task,
12047
12124
  signal: ac.signal,
12048
12125
  sink,
@@ -12747,7 +12824,8 @@ function parseGguf(path) {
12747
12824
  else if (key.endsWith(".nextn_predict_layers")) m.nextnLayers = readNumberOrMax(r, t);
12748
12825
  else if (key === "tokenizer.chat_template") {
12749
12826
  m.hasChatTemplate = true;
12750
- skipValue(r, t);
12827
+ const template = t === T_STRING ? String(readScalar(r, t)) : (skipValue(r, t), "");
12828
+ if (template.includes("reasoning_effort")) m.reasoningEffort = true;
12751
12829
  } else {
12752
12830
  skipValue(r, t);
12753
12831
  }
@@ -12765,6 +12843,7 @@ function parseGguf(path) {
12765
12843
  expertCount: m.expertCount ?? 0,
12766
12844
  nextnLayers: m.nextnLayers ?? 0,
12767
12845
  hasChatTemplate: m.hasChatTemplate ?? false,
12846
+ reasoningEffort: m.reasoningEffort ?? false,
12768
12847
  slidingWindow: m.slidingWindow ?? 0,
12769
12848
  slidingWindowPattern: m.slidingWindowPattern ?? [],
12770
12849
  headDimSwa: keyLengthSwa ?? valueLengthSwa ?? 0,
@@ -12779,15 +12858,15 @@ function parseGguf(path) {
12779
12858
  }
12780
12859
  }
12781
12860
  function quantFromName(filename) {
12782
- const m = filename.match(/(I?Q\d[A-Z0-9_]*|BF16|F16|F32)/i);
12783
- if (m) return m[1].toUpperCase();
12861
+ const matches = [...filename.matchAll(/(?:^|[-_. ])(I?Q\d(?:_[A-Za-z0-9]+)*|BF16|F16|F32)(?=$|[-_. ])/gi)];
12862
+ if (matches.length > 0) return matches[matches.length - 1][1].toUpperCase();
12784
12863
  const apex = filename.match(/APEX(?:-[A-Za-z0-9]+){0,3}?-(I-)?(NANO|MINI|COMPACT|BALANCED|QUALITY)(?=\.|$|-)/i);
12785
12864
  if (apex) return `APEX-${apex[1] ? "I-" : ""}${apex[2].toUpperCase()}`;
12786
12865
  return "?";
12787
12866
  }
12788
12867
 
12789
12868
  // src/models/scanner.ts
12790
- var CACHE_VERSION = 5;
12869
+ var CACHE_VERSION = 6;
12791
12870
  function attentionLayoutOf(meta) {
12792
12871
  const a = meta ?? {};
12793
12872
  const out = {};
@@ -12854,6 +12933,9 @@ var Scanner = class {
12854
12933
  lastScanAt = "";
12855
12934
  cache = /* @__PURE__ */ new Map();
12856
12935
  cachePath;
12936
+ // [legacyKey, key] pairs discovered during the CURRENT rescan — see the comment in `entryFor`
12937
+ // for why these are batched into one config write instead of applied as they're found.
12938
+ pendingKeyMigrations = [];
12857
12939
  list() {
12858
12940
  return { models: this.entries, scanning: this.scanning, lastScanAt: this.lastScanAt };
12859
12941
  }
@@ -12912,11 +12994,18 @@ var Scanner = class {
12912
12994
  if (existsSync19(d)) walk(d, scan);
12913
12995
  await tick();
12914
12996
  }
12997
+ this.pendingKeyMigrations = [];
12915
12998
  const gguf = await this.build(scan.ggufs);
12916
12999
  const mlx = scan.mlxDirs.map((dir) => mlxEntryFor(dir));
12917
13000
  this.entries = [...gguf, ...mlx].sort((a, b) => a.name.localeCompare(b.name));
12918
13001
  this.lastScanAt = (/* @__PURE__ */ new Date()).toISOString();
12919
13002
  this.saveCache();
13003
+ if (this.pendingKeyMigrations.length > 0) {
13004
+ const pairs = this.pendingKeyMigrations;
13005
+ this.store.update((cfg2) => {
13006
+ for (const [oldKey, newKey] of pairs) migrateModelKey(cfg2, oldKey, newKey);
13007
+ });
13008
+ }
12920
13009
  } finally {
12921
13010
  this.scanning = false;
12922
13011
  }
@@ -12986,12 +13075,16 @@ var Scanner = class {
12986
13075
  }
12987
13076
  }
12988
13077
  const fileName = basename2(path);
12989
- const quant = meta?.quant || quantFromName(fileName);
13078
+ const quant = quantFromName(fileName) !== "?" ? quantFromName(fileName) : meta?.quant || "?";
12990
13079
  const name = meta?.name || cleanName(fileName);
12991
13080
  const vision = mmprojPath !== null;
12992
13081
  const arch2 = meta?.arch ?? "unknown";
13082
+ const key = `${name.toLowerCase()}|${quant}|${sizeBytes}`;
13083
+ const legacyQuant = meta?.quant || quantFromName(fileName);
13084
+ const legacyKey = `${name.toLowerCase()}|${legacyQuant}|${sizeBytes}`;
13085
+ if (legacyKey !== key) this.pendingKeyMigrations.push([legacyKey, key]);
12993
13086
  return {
12994
- key: `${name.toLowerCase()}|${quant}|${sizeBytes}`,
13087
+ key,
12995
13088
  name,
12996
13089
  path,
12997
13090
  dir,
@@ -13015,6 +13108,7 @@ var Scanner = class {
13015
13108
  mmprojPath: vision ? mmprojPath : null,
13016
13109
  mmprojSizeBytes: vision ? mmprojSizeBytes : 0,
13017
13110
  hasChatTemplate: meta?.hasChatTemplate ?? false,
13111
+ reasoningEffort: meta?.reasoningEffort ?? false,
13018
13112
  embedding: isEmbeddingModel(arch2, fileName),
13019
13113
  incomplete,
13020
13114
  parseError,
@@ -13107,6 +13201,7 @@ function mlxEntryFor(dir) {
13107
13201
  let sizeBytes = 0;
13108
13202
  let mtimeMs = 0;
13109
13203
  let hasChatTemplate = false;
13204
+ let reasoningEffort = false;
13110
13205
  try {
13111
13206
  for (const n of readdirSync7(dir)) {
13112
13207
  const lower = n.toLowerCase();
@@ -13117,7 +13212,11 @@ function mlxEntryFor(dir) {
13117
13212
  }
13118
13213
  }
13119
13214
  const tc = join23(dir, "tokenizer_config.json");
13120
- hasChatTemplate = existsSync19(tc) && readFileSync8(tc, "utf8").includes("chat_template") || existsSync19(join23(dir, "chat_template.jinja"));
13215
+ const tcText = existsSync19(tc) ? readFileSync8(tc, "utf8") : "";
13216
+ const jinjaPath = join23(dir, "chat_template.jinja");
13217
+ const jinjaText = existsSync19(jinjaPath) ? readFileSync8(jinjaPath, "utf8") : "";
13218
+ hasChatTemplate = tcText.includes("chat_template") || jinjaText !== "";
13219
+ reasoningEffort = tcText.includes("reasoning_effort") || jinjaText.includes("reasoning_effort");
13121
13220
  } catch {
13122
13221
  }
13123
13222
  let incomplete = false;
@@ -13162,6 +13261,7 @@ function mlxEntryFor(dir) {
13162
13261
  mmprojPath: null,
13163
13262
  mmprojSizeBytes: 0,
13164
13263
  hasChatTemplate,
13264
+ reasoningEffort,
13165
13265
  embedding: isEmbeddingModel(arch2, basename2(dir)),
13166
13266
  incomplete,
13167
13267
  parseError,
@@ -15868,9 +15968,20 @@ function spillMb(baselineSharedMb, loadedSharedMb) {
15868
15968
  if (baselineSharedMb === null || loadedSharedMb === null) return null;
15869
15969
  return Math.max(0, loadedSharedMb - baselineSharedMb);
15870
15970
  }
15871
- function isSpilling(spill) {
15971
+ var SPILL_PROXIMITY_MB = 1024;
15972
+ var SPILL_FLOOR_CAP_MB = 2048;
15973
+ function isSpilling(spill, vramAbsMb, budgetMb, floorMb = null, pooled = false) {
15872
15974
  if (spill === null) return false;
15873
- return spill > SPILL_TOLERANCE_MB;
15975
+ const floor = pooled ? 0 : Math.min(floorMb ?? 0, SPILL_FLOOR_CAP_MB);
15976
+ if (spill - floor <= SPILL_TOLERANCE_MB) return false;
15977
+ if (!pooled && vramAbsMb !== null && budgetMb > 0 && vramAbsMb < budgetMb - SPILL_PROXIMITY_MB) return false;
15978
+ return true;
15979
+ }
15980
+ function spillFloor(floorMb, spill, vramAbsMb, budgetMb, pooled = false) {
15981
+ if (pooled || spill === null || vramAbsMb === null || budgetMb <= 0) return floorMb;
15982
+ if (vramAbsMb >= budgetMb - SPILL_PROXIMITY_MB) return floorMb;
15983
+ const learned = floorMb === null ? spill : Math.min(floorMb, spill);
15984
+ return Math.min(learned, SPILL_FLOOR_CAP_MB);
15874
15985
  }
15875
15986
 
15876
15987
  // src/api/path-utils.ts
@@ -17145,6 +17256,8 @@ var BenchRunner = class {
17145
17256
  if (base2.nglFit) return this.benchAt(entry, sys, base2, caps, results, "auto-fit");
17146
17257
  let bestNgl = 0;
17147
17258
  const budgetMb = gpuBudgetMb(sys, base2);
17259
+ let spillFloorMb = null;
17260
+ const pooled = sys.gpus.length > 1 && base2.gpu.splitMode !== "none";
17148
17261
  if (sys.gpus.length > 0) {
17149
17262
  const hi0 = entry.blockCount > 0 ? entry.blockCount : 99;
17150
17263
  let lo = 0, hi = hi0;
@@ -17155,7 +17268,8 @@ var BenchRunner = class {
17155
17268
  const probe2 = await this.probeVram(entry, sys, { ...base2, ngl: mid }, caps);
17156
17269
  this.pushProbe(results, base2, "ngl", mid, probe2);
17157
17270
  await this.settleGpu(sys);
17158
- const verdict = probeVerdict(probe2, budgetMb, headroomMb);
17271
+ spillFloorMb = spillFloor(spillFloorMb, probe2.spillMb, probe2.vramAbsMb, budgetMb, pooled);
17272
+ const verdict = probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb, pooled);
17159
17273
  if (verdict.decision === "fits") {
17160
17274
  bestNgl = mid;
17161
17275
  lo = mid + 1;
@@ -17169,7 +17283,7 @@ var BenchRunner = class {
17169
17283
  }
17170
17284
  if (bestNgl === null) return null;
17171
17285
  let found = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl }, caps, results, `ngl=${bestNgl}`);
17172
- if (found && isSpilling(found.cand.spillMb) && bestNgl > 0) {
17286
+ if (found && isSpilling(found.cand.spillMb, found.cand.vramAbsMb, budgetMb, spillFloorMb, pooled) && bestNgl > 0) {
17173
17287
  this.emit(`ngl=${bestNgl} spilled ${Math.round(found.cand.spillMb)} MB once actually generating (the load-only probe could not see this) \u2014 retrying at ngl=${bestNgl - 1}`);
17174
17288
  const safer = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl - 1 }, caps, results, `ngl=${bestNgl - 1} (spill backoff)`);
17175
17289
  if (safer) {
@@ -17204,13 +17318,16 @@ var BenchRunner = class {
17204
17318
  const budgetMb = gpuBudgetMb(sys, base2);
17205
17319
  let lo = 0, hi = maxN;
17206
17320
  let bestN = null;
17321
+ let spillFloorMb = null;
17322
+ const pooled = sys.gpus.length > 1 && base2.gpu.splitMode !== "none";
17207
17323
  while (lo <= hi && !this.cancelled && Date.now() <= this.deadline) {
17208
17324
  const mid = Math.floor((lo + hi) / 2);
17209
17325
  this.state = { ...this.state, step: `KV ${base2.kvTypeK}: probing nCpuMoe=${mid} (range ${lo}\u2013${hi})\u2026`, candidates: results };
17210
17326
  const probe2 = await this.probeVram(entry, sys, { ...base2, nCpuMoe: mid }, caps);
17211
17327
  this.pushProbe(results, base2, "nCpuMoe", mid, probe2);
17212
17328
  await this.settleGpu(sys);
17213
- const verdict = probeVerdict(probe2, budgetMb, headroomMb);
17329
+ spillFloorMb = spillFloor(spillFloorMb, probe2.spillMb, probe2.vramAbsMb, budgetMb, pooled);
17330
+ const verdict = probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb, pooled);
17214
17331
  if (verdict.decision === "fits") {
17215
17332
  bestN = mid;
17216
17333
  hi = mid - 1;
@@ -17238,7 +17355,7 @@ var BenchRunner = class {
17238
17355
  }
17239
17356
  if (n < maxN) this.emit(`nCpuMoe=${n} failed to bench (${results[results.length - 1]?.outcome ?? "crash"}) \u2014 retrying at nCpuMoe=${n + 1}`);
17240
17357
  }
17241
- if (found && isSpilling(found.cand.spillMb) && foundN < maxN) {
17358
+ if (found && isSpilling(found.cand.spillMb, found.cand.vramAbsMb, budgetMb, spillFloorMb, pooled) && foundN < maxN) {
17242
17359
  this.emit(`nCpuMoe=${foundN} spilled ${Math.round(found.cand.spillMb)} MB once actually generating (the load-only probe could not see this) \u2014 retrying at nCpuMoe=${foundN + 1}`);
17243
17360
  const safer = await this.benchAt(entry, sys, { ...base2, nCpuMoe: foundN + 1 }, caps, results, `nCpuMoe=${foundN + 1} (spill backoff)`);
17244
17361
  if (safer) {
@@ -17929,9 +18046,9 @@ function pickKvQuants(baseKv, kvTypes) {
17929
18046
  for (const t of [baseKv, ...QUALITY_KV]) if (supported(t) && !out.includes(t)) out.push(t);
17930
18047
  return out;
17931
18048
  }
17932
- function probeVerdict(probe2, budgetMb, headroomMb) {
18049
+ function probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb = null, pooled = false) {
17933
18050
  if (probe2.outcome === "oom") return { decision: "offload-more", reason: "oom" };
17934
- if (isSpilling(probe2.spillMb)) {
18051
+ if (isSpilling(probe2.spillMb, probe2.vramAbsMb, budgetMb, spillFloorMb, pooled)) {
17935
18052
  return { decision: "offload-more", reason: "spill", shortfallMb: probe2.spillMb };
17936
18053
  }
17937
18054
  if (overHeadroom(probe2.vramAbsMb, budgetMb, headroomMb)) {
@@ -24682,6 +24799,15 @@ function registerCodeRoutes(app2, d, codeRuns) {
24682
24799
  sessionAuth.setThinkingBudget(run.id, tokens === -1 ? null : tokens);
24683
24800
  return c.json({ ok: true, tokens });
24684
24801
  });
24802
+ app2.patch("/api/v1/code/sessions/:id/reasoning-effort", async (c) => {
24803
+ const id = c.req.param("id");
24804
+ const run = db2.getAgentRun(id);
24805
+ if (!run) return err8(c, 404, "not_found", "Session not found.");
24806
+ const b = await body8(c);
24807
+ const effort = parseReasoningEffort(b.effort) ?? null;
24808
+ sessionAuth.setReasoningEffort(run.id, effort);
24809
+ return c.json({ ok: true, effort });
24810
+ });
24685
24811
  app2.get("/api/v1/code/sessions/:id/last-usage", (c) => {
24686
24812
  const id = c.req.param("id");
24687
24813
  const run = db2.getAgentRun(id);
@@ -24930,7 +25056,7 @@ function registerCodeRoutes(app2, d, codeRuns) {
24930
25056
  userMsgId = lastUser.id;
24931
25057
  task = contextFilesBlock(lastUser.textAttachments) + lastUser.content;
24932
25058
  }
24933
- const enqueueParams = { convId: run.convId, repoRoot: agentCwd(run), task, userMsgId, thinkingBudget: b.thinkingBudget };
25059
+ const enqueueParams = { convId: run.convId, repoRoot: agentCwd(run), task, userMsgId, thinkingBudget: b.thinkingBudget, reasoningEffort: parseReasoningEffort(b.reasoningEffort) };
24934
25060
  if (kind === "steer") {
24935
25061
  const { steered, queued: queued2 } = await runs.steer(id, enqueueParams);
24936
25062
  return c.json({ ok: true, queued: queued2, steered, userMessageId: userMsgId }, 202);
@@ -25856,6 +25982,15 @@ function registerGateway(app2, d, opts = {}) {
25856
25982
  const requestOrigin = new URL(c.req.url).origin;
25857
25983
  const guidance = req.tools?.length ? applyAgentGuidance(req, requestOrigin) : null;
25858
25984
  const oaiBody = mapToOpenAI(req);
25985
+ if (anthropicCodeSessionId) {
25986
+ const effortOverride = sessionAuth.getReasoningEffortForToken(anthropicToken);
25987
+ if (effortOverride === "off") {
25988
+ oaiBody.thinking_budget_tokens = 0;
25989
+ oaiBody.chat_template_kwargs = { ...oaiBody.chat_template_kwargs ?? {}, enable_thinking: false };
25990
+ } else if (effortOverride !== null) {
25991
+ oaiBody.chat_template_kwargs = { ...oaiBody.chat_template_kwargs ?? {}, reasoning_effort: effortOverride };
25992
+ }
25993
+ }
25859
25994
  if (guidance?.forceTextOnly) oaiBody.tool_choice = "none";
25860
25995
  const oaiAlias = engineModelAlias(d.registry.active()?.kind ?? "", d.manager.currentOpts()?.modelPath);
25861
25996
  if (oaiAlias) oaiBody.model = oaiAlias;
@@ -26102,6 +26237,13 @@ function registerGateway(app2, d, opts = {}) {
26102
26237
  if (override > 0) parsedBody.thinking_budget_tokens = override;
26103
26238
  else delete parsedBody.thinking_budget_tokens;
26104
26239
  }
26240
+ const effortOverride = sessionAuth.getReasoningEffortForToken(chatToken);
26241
+ if (effortOverride === "off") {
26242
+ parsedBody.thinking_budget_tokens = 0;
26243
+ parsedBody.chat_template_kwargs = { ...parsedBody.chat_template_kwargs ?? {}, enable_thinking: false };
26244
+ } else if (effortOverride !== null) {
26245
+ parsedBody.chat_template_kwargs = { ...parsedBody.chat_template_kwargs ?? {}, reasoning_effort: effortOverride };
26246
+ }
26105
26247
  }
26106
26248
  if (parsedBody?.stream === true && parsedBody.stream_options === void 0) {
26107
26249
  parsedBody.stream_options = { include_usage: true };
@@ -0,0 +1 @@
1
+ import{j as e}from"./radix-B0YBjihE.js";import{b as W,u as $,r as b}from"./vendor-C1I6euDx.js";import{u as G,d as H,e as Y,f as J,g as U,a as z,B as C,t as j,c as q,b as h,A as _}from"./index-Djd745uq.js";import{f as V}from"./chat-api-B7cm_Kjj.js";import{f as X,a as Z}from"./agent-api-DyPUCnyd.js";import{P as B}from"./personas-Bdrl3tL6.js";import{C as ee}from"./chevron-left-BQ3TyvUR.js";import{R as te}from"./rotate-ccw-Dl2CDY8F.js";import{T as se}from"./trash-2-C5UxcfNn.js";import{C as ne}from"./chevron-right-C1TzfDRc.js";import"./dropdown-menu-Co-9JBK7.js";const ae=()=>({name:"",description:"",systemPrompt:"",skillIds:[],tools:[]});function oe(s){const d=[],x=new Map;for(const n of s){const a=/^mcp__([^_]+(?:_[^_]+)*)__/.exec(n.name);if(!a){d.push(n);continue}const i=a[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,a)=>n.label.localeCompare(a.label))}}function le(s){return s.replace(/^mcp__[^_]+(?:_[^_]+)*__/,"")}function re(s){return s.replace(/^\[[^\]]+\]\s*/,"")}function D({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:le(s.name)}),s.description&&e.jsx("span",{className:"text-faint",children:re(s.description)})]})]})}function ie({group:s,selected:d,onToggleAll:x,onToggleOne:n}){const[a,i]=b.useState(!1),p=s.tools.map(l=>l.name),c=p.filter(l=>d.has(l)).length,o=c===p.length,g=c>0&&!o,u=b.useRef(null);return b.useEffect(()=>{u.current&&(u.current.indeterminate=g)},[g]),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:o,onChange:()=>x(p,!o)}),e.jsxs("button",{type:"button",onClick:()=>{j("agents","toggle_agent_tool_group"),i(l=>!l)},className:"flex flex-1 items-center gap-1.5 text-left text-[13px] text-ink",children:[e.jsx(ne,{size:12,className:q("shrink-0 text-faint transition-transform",a&&"rotate-90")}),s.label,e.jsxs("span",{className:"text-[11px] text-faint",children:["(",c,"/",p.length,")"]})]})]}),a&&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(D,{tool:l,checked:d.has(l.name),onToggle:()=>n(l.name)},l.name))})]})}function ce({tools:s,selected:d,onChange:x}){const n=new Set(d),{builtin:a,groups:i}=oe(s),p=o=>x(n.has(o)?d.filter(g=>g!==o):[...d,o]),c=(o,g)=>{const u=d.filter(l=>!o.includes(l));x(g?[...u,...o]: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:[a.length>0&&e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:a.map(o=>e.jsx(D,{tool:o,checked:n.has(o.name),onToggle:()=>p(o.name)},o.name))}),i.map(o=>e.jsx(ie,{group:o,selected:n,onToggleAll:c,onToggleOne:p},o.key))]})}function je(){const{agentId:s="new"}=W(),d=$(),x=G(),n=s==="new",a=!n&&B.some(t=>t.id===s),i=a?B.find(t=>t.id===s):void 0,p=H(),c=!n&&!a?(p.data??[]).find(t=>t.id===s):void 0,o=Y(),g=J(),u=U(),l=a?g.data?.[s]:void 0,I=z({queryKey:Z.list(),queryFn:X,staleTime:0}),k=I.data??[],w=z({queryKey:["available-tools"],queryFn:V}),N=w.data??[],[m,f]=b.useState(ae()),[S,T]=b.useState(!1),[A,P]=b.useState(!1),[L,R]=b.useState(!1),[E,Q]=b.useState("skills");n&&!S&&(k.length||N.length)&&(f(t=>({...t,skillIds:k.map(r=>r.id),tools:N.map(r=>r.name)})),T(!0)),!n&&!a&&!S&&c&&(f({name:c.name,description:c.description,systemPrompt:c.systemPrompt,skillIds:c.skillIds,tools:c.tools}),T(!0)),a&&!S&&i&&g.isSuccess&&(k.length||N.length)&&(f({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??N.map(t=>t.name)}),T(!0));const y=()=>{j("agents","back_to_agents"),d("/customize")},O=t=>f(r=>({...r,skillIds:r.skillIds.includes(t)?r.skillIds.filter(v=>v!==t):[...r.skillIds,t]})),F=()=>{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(a){u.save.mutate({id:s,override:t},{onSuccess:()=>{h.success("Agent saved."),y()},onError:v=>{h.error(v instanceof _?v.message:"Could not save agent."),P(!1)}});return}const r={onSuccess:()=>{x.invalidateQueries({queryKey:["chat-agents"]}),h.success(n?"Agent created.":"Agent saved."),y()},onError:v=>{h.error(v instanceof _?v.message:"Could not save agent."),P(!1)}};n?o.add.mutate(t,r):o.update.mutate({id:s,patch:t},r)},K=()=>{u.reset.mutate(s,{onSuccess:()=>{h.success("Reset to default."),i&&f({name:i.name,description:i.description,systemPrompt:i.systemPrompt,skillIds:k.map(t=>t.id),tools:N.map(t=>t.name)})},onError:t=>h.error(t instanceof _?t.message:"Could not reset agent.")})},M=()=>{o.remove.mutate(s,{onSuccess:()=>{h.success("Agent deleted."),y()},onError:t=>h.error(t instanceof _?t.message:"Could not delete agent.")})};return!n&&!a&&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(C,{size:"sm",variant:"outline",onClick:y,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:y,className:"text-faint hover:text-ink",title:"Back to agents",children:e.jsx(ee,{size:18})}),e.jsx("span",{className:"text-[15px] font-medium text-ink",children:n?"New agent":a?l?"Edit agent (modified built-in)":"Edit agent (built-in)":"Edit agent"}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[a&&e.jsxs(C,{size:"sm",variant:"outline",onClick:()=>{j("agents","reset_agent_to_default"),K()},disabled:u.reset.isPending,children:[e.jsx(te,{size:13})," Reset to default"]}),e.jsx(C,{size:"sm",variant:"outline",onClick:y,children:"Cancel"}),e.jsx(C,{size:"sm",onClick:()=>{j("agents","save_agent"),F()},disabled:A||!m.name.trim(),children:A?"Saving…":"Save"})]})]}),a&&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=>f(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=>f(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=>f(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:()=>{j("agents","switch_agent_form_tab"),Q(t)},className:q("rounded px-3 py-1.5 text-[13px] font-medium transition-colors",E===t?"bg-accent/12 text-accent":"text-muted hover:text-ink"),children:t==="skills"?`Skills (${m.skillIds.length})`:`Tools (${m.tools.length})`},t))}),E==="skills"?I.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:()=>O(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))}):w.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):e.jsx(ce,{tools:N,selected:m.tools,onChange:t=>f(r=>({...r,tools:t}))})]}),!n&&!a&&(L?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:()=>{j("agents","delete_agent"),M()},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:()=>{j("agents","cancel_delete_agent"),R(!1)},className:"rounded px-2 py-1 text-faint hover:text-ink",children:"Cancel"})]}):e.jsxs("button",{type:"button",onClick:()=>R(!0),className:"flex items-center gap-1.5 self-start text-[12px] text-faint hover:text-[color:var(--err)]",children:[e.jsx(se,{size:13})," Delete agent"]}))]})}export{je as AgentEditPage};