turbollm 1.11.8 → 1.12.0
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.
- package/README.md +1 -1
- package/dist/cli.js +188 -26
- package/dist/webdist/assets/{AgentEditPage-BEYv2dqk.js → AgentEditPage-Cl9VgfYt.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-Be3s4Apt.js → ChatScreen-D0JIgp7C.js} +1 -1
- package/dist/webdist/assets/{CodeComposer-UXWorvxM.js → CodeComposer-Cqtowy4i.js} +1 -1
- package/dist/webdist/assets/{CodeHomeScreen-DoLM7wZ7.js → CodeHomeScreen-fGeu4-IS.js} +1 -1
- package/dist/webdist/assets/{CodeSessionScreen-B2_E1nGk.js → CodeSessionScreen-CqBDC3e4.js} +1 -1
- package/dist/webdist/assets/{CustomizeScreen-oXSoHBmc.js → CustomizeScreen-BTzZdj7z.js} +1 -1
- package/dist/webdist/assets/{DeveloperScreen-XtW_r1xe.js → DeveloperScreen-D40_GOxu.js} +1 -1
- package/dist/webdist/assets/{EnginesScreen-DFPKVQmY.js → EnginesScreen-CPKMB1MS.js} +1 -1
- package/dist/webdist/assets/ModelDetailDialog-PySMSzRc.js +1 -0
- package/dist/webdist/assets/{ModelLoadMenu-DIsk-jZz.js → ModelLoadMenu-BgkEIVli.js} +1 -1
- package/dist/webdist/assets/{ModelsScreen-CaPBgqJn.js → ModelsScreen-Bi_cdOOR.js} +1 -1
- package/dist/webdist/assets/{OnboardingScreen-DKB8rxlq.js → OnboardingScreen-BVyp58am.js} +1 -1
- package/dist/webdist/assets/{RoutineEditPage-HxYBqm4v.js → RoutineEditPage-BtL6uHNS.js} +1 -1
- package/dist/webdist/assets/{RoutinesPanel-DG2Sxz7g.js → RoutinesPanel-Bb0LP98-.js} +1 -1
- package/dist/webdist/assets/{SettingsScreen-CXP_EZLC.js → SettingsScreen-Dsz1JZPU.js} +1 -1
- package/dist/webdist/assets/{SidebarResizeHandle-BEjYiHxx.js → SidebarResizeHandle-B9IvMWnc.js} +1 -1
- package/dist/webdist/assets/{SkillEditPage-CFLxX-PG.js → SkillEditPage-zPuoTSEK.js} +1 -1
- package/dist/webdist/assets/{TokensScreen-EAg6SpPg.js → TokensScreen-DGfd8Z_h.js} +1 -1
- package/dist/webdist/assets/ToolApprovalBar-CjF6OSEN.js +21 -0
- package/dist/webdist/assets/WorkspaceScreen-BvQS-6fo.js +1 -0
- package/dist/webdist/assets/{abnfDiagram-N423BO3Z-Com8iOkP.js → abnfDiagram-N423BO3Z-BHtFnGEG.js} +1 -1
- package/dist/webdist/assets/{agent-api-Bbbnu920.js → agent-api-C-qZrrYO.js} +1 -1
- package/dist/webdist/assets/{alert-dialog-DBTMGpVB.js → alert-dialog-CjxDGiZR.js} +1 -1
- package/dist/webdist/assets/{arc-CxAPh_XT.js → arc-CxTBdZ4R.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-T3A2C74G-cmEV3ecV.js → architectureDiagram-T3A2C74G-7PcBBjT5.js} +1 -1
- package/dist/webdist/assets/{arrow-left-CqNHa_nR.js → arrow-left-B6hlnKUy.js} +1 -1
- package/dist/webdist/assets/{badge-DLVv8YlA.js → badge-DUS8w956.js} +1 -1
- package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-Dzszoo8X.js → blockDiagram-VBNYF7ZC-yJQM294Z.js} +1 -1
- package/dist/webdist/assets/{bot-DFV9NaDI.js → bot-92SGv3lK.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-5PPSVZJV-CT06LjAB.js → c4Diagram-5PPSVZJV-DGo_IrnA.js} +1 -1
- package/dist/webdist/assets/channel-B6B2Q5Vd.js +1 -0
- package/dist/webdist/assets/{chat-api-CmDwSCUy.js → chat-api-DUobixOH.js} +1 -1
- package/dist/webdist/assets/{chat-queries-opwsCDIy.js → chat-queries-DIGUy3mB.js} +1 -1
- package/dist/webdist/assets/{chevron-down-DiyKHxC-.js → chevron-down-Cg4gkXkY.js} +1 -1
- package/dist/webdist/assets/{chevron-left-CwO2nWWZ.js → chevron-left-CRkSrIuw.js} +1 -1
- package/dist/webdist/assets/{chevron-right-Ck02yYBx.js → chevron-right-D6YKa1nw.js} +1 -1
- package/dist/webdist/assets/{chunk-2GRJ4B5K-Blj1u1OW.js → chunk-2GRJ4B5K-4BRNCKh4.js} +1 -1
- package/dist/webdist/assets/{chunk-2Q5K7J3B-VRS9aN4X.js → chunk-2Q5K7J3B-VVErlkzz.js} +1 -1
- package/dist/webdist/assets/{chunk-5RXB4S5H-CoTOA-QY.js → chunk-5RXB4S5H-BdrEcHfH.js} +1 -1
- package/dist/webdist/assets/{chunk-5VM5RSS4-DigOrHns.js → chunk-5VM5RSS4-B7ZoD7jT.js} +1 -1
- package/dist/webdist/assets/{chunk-6Q2QTUOP-MsJl24GT.js → chunk-6Q2QTUOP-CZboDQFa.js} +1 -1
- package/dist/webdist/assets/{chunk-GF5L2VYU-xgSZn13t.js → chunk-GF5L2VYU-Bxfejn_T.js} +1 -1
- package/dist/webdist/assets/{chunk-JWPE2WC7-DJ7ETxvg.js → chunk-JWPE2WC7-CR53ctin.js} +1 -1
- package/dist/webdist/assets/{chunk-KBJHAD2P-DypQCgcq.js → chunk-KBJHAD2P-CI9fYV8V.js} +1 -1
- package/dist/webdist/assets/{chunk-RYQCIY6F-0xN4i17N.js → chunk-RYQCIY6F-CEka5LWj.js} +1 -1
- package/dist/webdist/assets/{chunk-XXDRQBXY-CLumzVtu.js → chunk-XXDRQBXY-B6ToGKiT.js} +1 -1
- package/dist/webdist/assets/{circle-check-CM_EzD0B.js → circle-check-NUkbKKsX.js} +1 -1
- package/dist/webdist/assets/{circle-x-DDCTEjWL.js → circle-x-BI2C2Gpz.js} +1 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-Nr9H5qaY.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-Nr9H5qaY.js +1 -0
- package/dist/webdist/assets/{common-BmIDcygp.js → common-BDUb2Jp_.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-JH36ORCC-CctbomzF.js → cose-bilkent-JH36ORCC-n-mMCinT.js} +1 -1
- package/dist/webdist/assets/{cynefin-VYW2F7L2-CAOiUD35.js → cynefin-VYW2F7L2--M6hM_u0.js} +1 -1
- package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-BmenpAyg.js → cynefinDiagram-MW4NZA55-C1WV5_wf.js} +1 -1
- package/dist/webdist/assets/{dagre-VZM6K2ZE-CUSeYeIs.js → dagre-VZM6K2ZE-BrvE8li2.js} +1 -1
- package/dist/webdist/assets/{diagram-7IWD3JNH-CTmJsE0m.js → diagram-7IWD3JNH-BAtvwqyn.js} +1 -1
- package/dist/webdist/assets/{diagram-B4RE2ZJO-D5tXNWQT.js → diagram-B4RE2ZJO-DIvlrS5g.js} +1 -1
- package/dist/webdist/assets/{diagram-LBJQPF4R-5tR892LO.js → diagram-LBJQPF4R-BzTddnYn.js} +1 -1
- package/dist/webdist/assets/{diagram-Q27KOJAE-BgZg9KkM.js → diagram-Q27KOJAE-U-iZs4DE.js} +1 -1
- package/dist/webdist/assets/{diagram-UB23O5K3-DzD2EEfH.js → diagram-UB23O5K3-CaFGOdAj.js} +1 -1
- package/dist/webdist/assets/{dropdown-menu-CaMJbKX5.js → dropdown-menu-D5Vf7U3W.js} +1 -1
- package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-BsE4pbuB.js → ebnfDiagram-BXEA7PRR-WEkh8Cpp.js} +1 -1
- package/dist/webdist/assets/{erDiagram-JOGREHBK-BSNniK5W.js → erDiagram-JOGREHBK-DIPsvu0C.js} +1 -1
- package/dist/webdist/assets/{external-link-B73_NSLw.js → external-link-DuVH0_sU.js} +1 -1
- package/dist/webdist/assets/{file-text-SkW8GJLf.js → file-text-B8I_V3Ev.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-UKHOOZJN-LTHTwtbo.js → flowDiagram-UKHOOZJN-D0Il5rli.js} +1 -1
- package/dist/webdist/assets/{folder-input-DdDYio8z.js → folder-input-n_yC89H9.js} +1 -1
- package/dist/webdist/assets/{folder-plus-By4aZIqn.js → folder-plus-CC1f-3oh.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-DhWk0fZI.js → ganttDiagram-PKOTCBZU-8KyY9Pa4.js} +1 -1
- package/dist/webdist/assets/{git-branch-C6MWgM1t.js → git-branch-CQA2JECJ.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-Cnp_ieRP.js → gitGraphDiagram-DS77QQ5N-DnwR5_g_.js} +1 -1
- package/dist/webdist/assets/index-D44YD6EJ.css +1 -0
- package/dist/webdist/assets/{index-DDdTmEU4.js → index-hEBbEVm0.js} +2 -2
- package/dist/webdist/assets/{infoDiagram-6WML65LV-BfVAgcHy.js → infoDiagram-6WML65LV-B4Ao9xBO.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-rRt3dfj6.js → ishikawaDiagram-WSZJBQD7-BIH-3xyR.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-BSy-shCM.js → journeyDiagram-NVQOT4AX-CB7VA190.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-27J2QSJJ-DGOAYCO1.js → kanban-definition-27J2QSJJ-t0MLGJxS.js} +1 -1
- package/dist/webdist/assets/{linear-CS_iPZyK.js → linear-C2UcHtLH.js} +1 -1
- package/dist/webdist/assets/{link-queries-DvYdzQm8.js → link-queries-Dd_UY0A-.js} +1 -1
- package/dist/webdist/assets/{lock-_paqX_bJ.js → lock-BaRe3TFE.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-CPhj_3A-.js → mermaid.core-Do_AkPs7.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-CZbX1tkX.js → mindmap-definition-FAOFIHXS-C0FjLEZb.js} +1 -1
- package/dist/webdist/assets/{monitor-Buq_3Xsq.js → monitor-nPLFkAL-.js} +1 -1
- package/dist/webdist/assets/{pegDiagram-VL7TDLO6-PpIZIssA.js → pegDiagram-VL7TDLO6-DMP_1SBp.js} +1 -1
- package/dist/webdist/assets/{pencil-D9a-4tCA.js → pencil-DIAK3lkm.js} +1 -1
- package/dist/webdist/assets/personas-Dkq9JD72.js +109 -0
- package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-vt-POtMx.js → pieDiagram-7S7Q4E2Y-RG_slaJ2.js} +1 -1
- package/dist/webdist/assets/{plus-DP3JYEma.js → plus-Cd2hb3vG.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-Yr9F3dX4.js → quadrantDiagram-CIZ2JOQS-6wV3EG0F.js} +1 -1
- package/dist/webdist/assets/{railroadDiagram-AXF67PYL-CZ7FpINV.js → railroadDiagram-AXF67PYL-flgltuTY.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-bRtvR0Iv.js → refresh-cw-MAW86aWv.js} +1 -1
- package/dist/webdist/assets/{remote-failure-agE6nknQ.js → remote-failure-DTP9EDi2.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-BUmCzzYZ.js → requirementDiagram-LRYGKXZP-CXpi-87D.js} +1 -1
- package/dist/webdist/assets/{rocket-BFudVOBf.js → rocket-B5uDLuGn.js} +1 -1
- package/dist/webdist/assets/{rotate-ccw-CTfSFG3x.js → rotate-ccw-DVWlxS6M.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-BuLGkmEP.js → sankeyDiagram-W5VNT64P-C50KvAmS.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-D8vmzIyW.js → sequenceDiagram-SI44F4Z6-CsT039Tm.js} +1 -1
- package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-DYgUs44t.js → sizeCapture-X5ZJPWSS-BImTTCUc.js} +1 -1
- package/dist/webdist/assets/{skeleton-kNhR6J5G.js → skeleton-DnvNxbj8.js} +1 -1
- package/dist/webdist/assets/{sliders-horizontal-GlSfzSwu.js → sliders-horizontal-DsS2Uee5.js} +1 -1
- package/dist/webdist/assets/{sparkles-CJPHP-dp.js → sparkles-BU19nV47.js} +1 -1
- package/dist/webdist/assets/{star-BDNzpKYY.js → star-DcvDKUjt.js} +1 -1
- package/dist/webdist/assets/{stateDiagram-OKZ733FA-Sztzkc4z.js → stateDiagram-OKZ733FA-Go1nImaV.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-CNOImueL.js +1 -0
- package/dist/webdist/assets/{swimlanes-SLNWSIFB-CWR36cS5.js → swimlanes-SLNWSIFB-D8aYBeg_.js} +2 -2
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-u93o-5nq.js +8 -0
- package/dist/webdist/assets/{switch-CJAukDSs.js → switch-DRDUQUBQ.js} +1 -1
- package/dist/webdist/assets/{terminal-5a1B-6y4.js → terminal-BaGcFc0D.js} +1 -1
- package/dist/webdist/assets/{timeline-definition-Z64GVDOM-Bs1ZNlGU.js → timeline-definition-Z64GVDOM-BCYicvUs.js} +1 -1
- package/dist/webdist/assets/{trash-2-BNNKBgll.js → trash-2-dTSieVsH.js} +1 -1
- package/dist/webdist/assets/{triangle-alert-vMymArLW.js → triangle-alert-BQok4bN-.js} +1 -1
- package/dist/webdist/assets/{useIsDesktop-BWN1ktaj.js → useIsDesktop-D7McLbCu.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-T6HMQDX7-bfP-4l5-.js → vennDiagram-T6HMQDX7-BvWE6mUb.js} +1 -1
- package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y-CT_Drudb.js → wardleyDiagram-T6FBY63Y-DId8SDFX.js} +1 -1
- package/dist/webdist/assets/{wrench-BleM5jpH.js → wrench-wnE0c5Ir.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-BeJSlb68.js → xychartDiagram-ELKLHX3M-DAFHE1Oy.js} +1 -1
- package/dist/webdist/index.html +2 -2
- package/package.json +1 -1
- package/dist/webdist/assets/ModelDetailDialog-Bf99Dj9I.js +0 -1
- package/dist/webdist/assets/ToolApprovalBar-BdNLuB0r.js +0 -21
- package/dist/webdist/assets/WorkspaceScreen-C2X82u27.js +0 -1
- package/dist/webdist/assets/channel-C1ooZeJ8.js +0 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-c_ApQIjk.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-c_ApQIjk.js +0 -1
- package/dist/webdist/assets/index-rQri1Mzm.css +0 -1
- package/dist/webdist/assets/personas-B7q-7L3z.js +0 -109
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-CaotCWUJ.js +0 -1
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-BwXNVqW3.js +0 -8
package/README.md
CHANGED
|
@@ -208,7 +208,7 @@ the detail:
|
|
|
208
208
|
- **Full load-parameter UI**, a superset of what other tools expose: context length, GPU offload
|
|
209
209
|
(`-ngl`), **MoE CPU-offload (`--n-cpu-moe`)**, parallel slots, **independent K and V cache-quant
|
|
210
210
|
type** (incl. low-bit on supporting forks), CPU threads, flash attention, **speculative decoding
|
|
211
|
-
(NextN / MTP / draft, with a configurable draft min/max window)**, a **pinned engine port** per
|
|
211
|
+
(NextN / MTP / draft / DFlash, with a configurable draft min/max window)**, a **pinned engine port** per
|
|
212
212
|
model, and a **custom/raw flags** field for anything not exposed as its own control.
|
|
213
213
|
- **Copy the exact launch command** for a loaded model — runs the same config standalone with
|
|
214
214
|
llama.cpp/the fork directly, no TurboLLM required.
|
package/dist/cli.js
CHANGED
|
@@ -2637,9 +2637,12 @@ function detectKvTypes(helpText, hasCacheTypeFlag) {
|
|
|
2637
2637
|
return kvTypes;
|
|
2638
2638
|
}
|
|
2639
2639
|
function parseEnumList(blockText) {
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2640
|
+
let raw = /allowed values:\s*([\s\S]+)/i.exec(blockText)?.[1] ?? /(?:^|[ \t])\[([^\]\n]+)\]/.exec(blockText)?.[1];
|
|
2641
|
+
if (!raw) {
|
|
2642
|
+
const braceMatch = /(?:^|[ \t])\{([^}]+)\}/.exec(blockText);
|
|
2643
|
+
const parenMatch = /(?:^|[ \t])\(([^)|]+)\)/.exec(blockText);
|
|
2644
|
+
raw = braceMatch?.[1] ?? parenMatch?.[1];
|
|
2645
|
+
}
|
|
2643
2646
|
if (!raw) return [];
|
|
2644
2647
|
const values = raw.split(/[,|]/).map((s) => s.trim()).filter((s) => /^[a-z][a-z0-9_-]*$/i.test(s));
|
|
2645
2648
|
return values.length >= 2 ? values : [];
|
|
@@ -2648,7 +2651,7 @@ function classifyFlag(flagName, helpText) {
|
|
|
2648
2651
|
const escaped = flagName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2649
2652
|
const ALIAS = "-{1,2}[a-zA-Z][a-zA-Z0-9-]*";
|
|
2650
2653
|
const re = new RegExp(
|
|
2651
|
-
`(?:^|\\n)[ \\t]*(?:${ALIAS}[ \\t]*,[ \\t]*)*${escaped}(?![-a-zA-Z0-9])(?:[ \\t]*,[ \\t]*${ALIAS})*( *)(\\S+)?([\\s\\S]
|
|
2654
|
+
`(?:^|\\n)[ \\t]*(?:${ALIAS}[ \\t]*,[ \\t]*)*${escaped}(?![-a-zA-Z0-9])(?:[ \\t]*,[ \\t]*${ALIAS})*( *)(\\S+)?([\\s\\S]+?)(?=\\n\\s*\\(default|\\n[ \\t]*${ALIAS}|\\n\\n|$)`,
|
|
2652
2655
|
"i"
|
|
2653
2656
|
);
|
|
2654
2657
|
const m = re.exec(helpText);
|
|
@@ -2656,11 +2659,24 @@ function classifyFlag(flagName, helpText) {
|
|
|
2656
2659
|
const gap = m[1] ?? "";
|
|
2657
2660
|
const placeholder = m[2] ?? "";
|
|
2658
2661
|
const block = m[3] ?? "";
|
|
2659
|
-
const
|
|
2662
|
+
const nextFlagLine = block.match(/\n[ \t]*-{1,2}[a-zA-Z][a-zA-Z0-9-]*/);
|
|
2663
|
+
const ownBlock = nextFlagLine ? block.slice(0, nextFlagLine.index) : block;
|
|
2664
|
+
const scanText = placeholder + "\n" + ownBlock;
|
|
2665
|
+
const enumValues = parseEnumList(scanText);
|
|
2660
2666
|
if (enumValues.length > 0) return { name: flagName, kind: "enum", enumValues };
|
|
2667
|
+
const bracket = parseEnumBrackets(scanText);
|
|
2668
|
+
if (bracket.length > 0) return { name: flagName, kind: "enum", enumValues: bracket };
|
|
2661
2669
|
if (gap.length !== 1 || !placeholder) return { name: flagName, kind: "boolean" };
|
|
2662
2670
|
return { name: flagName, kind: "valued" };
|
|
2663
2671
|
}
|
|
2672
|
+
function parseEnumBrackets(blockText) {
|
|
2673
|
+
const braceMatch = /(?:^|[ \t])\{([^}]+)\}/.exec(blockText);
|
|
2674
|
+
const parenMatch = /(?:^|[ \t])\(([^)|]+)\)/.exec(blockText);
|
|
2675
|
+
const raw = braceMatch?.[1] ?? parenMatch?.[1];
|
|
2676
|
+
if (!raw) return [];
|
|
2677
|
+
const values = raw.split(/[|,]/).map((s) => s.trim()).filter((s) => /^[a-z][a-z0-9_-]*$/i.test(s));
|
|
2678
|
+
return values.length >= 2 ? values : [];
|
|
2679
|
+
}
|
|
2664
2680
|
function firstNonEmptyLine(s) {
|
|
2665
2681
|
for (const ln of s.split("\n")) {
|
|
2666
2682
|
const t = ln.trim();
|
|
@@ -2887,9 +2903,11 @@ function suggestEngineName(binPath, version2) {
|
|
|
2887
2903
|
|
|
2888
2904
|
// src/engines/build-runner.ts
|
|
2889
2905
|
var execFileP8 = promisify8(execFile10);
|
|
2906
|
+
function chooseEngineName(name, priorName) {
|
|
2907
|
+
return name ?? priorName ?? "";
|
|
2908
|
+
}
|
|
2890
2909
|
function buildDirName(repoUrl, branch, commit) {
|
|
2891
|
-
const
|
|
2892
|
-
const repo = last.replace(/\.git$/i, "").trim() || "engine";
|
|
2910
|
+
const repo = normRepoUrl(repoUrl) || "engine";
|
|
2893
2911
|
const b = (branch ?? "").trim();
|
|
2894
2912
|
const sha = (commit ?? "").trim();
|
|
2895
2913
|
const raw = sha ? `${repo}-${sha.slice(0, 12)}` : b ? `${repo}-${b}` : repo;
|
|
@@ -2900,7 +2918,7 @@ function sameRepo(a, b) {
|
|
|
2900
2918
|
return na !== "" && na === normRepoUrl(b);
|
|
2901
2919
|
}
|
|
2902
2920
|
function normRepoUrl(s) {
|
|
2903
|
-
return (s ?? "").trim().toLowerCase().replace(/^https?:\/\//, "").replace(/^github\.com\//, "").replace(
|
|
2921
|
+
return (s ?? "").trim().toLowerCase().replace(/^https?:\/\//, "").replace(/^github\.com\//, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
2904
2922
|
}
|
|
2905
2923
|
function sourceBuildBinary(enginesRoot, repoUrl, branch, commit) {
|
|
2906
2924
|
const root = join13(enginesRoot, "build", buildDirName(repoUrl, branch, commit));
|
|
@@ -3662,7 +3680,11 @@ function customSourceKey(s) {
|
|
|
3662
3680
|
}
|
|
3663
3681
|
function isStaleCapabilities(flags, flagInfo) {
|
|
3664
3682
|
if (flags.includes("--spec-type") && !flags.some((f2) => f2.startsWith("spec-type:"))) return true;
|
|
3665
|
-
|
|
3683
|
+
const removed = ["--draft-max", "--draft-min", "--draft", "--draft-n", "--draft-n-min"];
|
|
3684
|
+
const successor = ["--spec-draft-n-max", "--spec-draft-n-min"];
|
|
3685
|
+
const hasRemoved = removed.some((f2) => flags.includes(f2));
|
|
3686
|
+
const hasSuccessor = successor.some((f2) => flags.includes(f2));
|
|
3687
|
+
if (hasRemoved && hasSuccessor) return true;
|
|
3666
3688
|
if (flagInfo === void 0) return true;
|
|
3667
3689
|
return false;
|
|
3668
3690
|
}
|
|
@@ -3830,7 +3852,7 @@ var modelLoad = defineEvent({
|
|
|
3830
3852
|
batchSize: f.int({ optional: true }),
|
|
3831
3853
|
uBatchSize: f.int({ optional: true }),
|
|
3832
3854
|
cacheReuse: f.int(),
|
|
3833
|
-
speculative: f.enum(["off", "mtp", "nextn", "draft"]),
|
|
3855
|
+
speculative: f.enum(["off", "mtp", "nextn", "draft", "dflash"]),
|
|
3834
3856
|
contextOverflow: f.enum(["shift", "keep"]),
|
|
3835
3857
|
nKeep: f.int(),
|
|
3836
3858
|
ropeScalingType: f.enum(["none", "linear", "yarn"]),
|
|
@@ -5617,7 +5639,11 @@ async function withPinnedModel(deps2, pinnedModel, fn) {
|
|
|
5617
5639
|
return { outcome: "ran" };
|
|
5618
5640
|
}
|
|
5619
5641
|
const swapResult = await deps2.modelRouter.loadExplicit(pinnedModel);
|
|
5620
|
-
if ("status" in swapResult)
|
|
5642
|
+
if ("status" in swapResult) {
|
|
5643
|
+
if (swapResult.message.includes("ComfyUI is rendering"))
|
|
5644
|
+
return { outcome: "skip-comfyui-busy" };
|
|
5645
|
+
return { outcome: "skip-load-failed", message: swapResult.message };
|
|
5646
|
+
}
|
|
5621
5647
|
try {
|
|
5622
5648
|
await fn();
|
|
5623
5649
|
} finally {
|
|
@@ -6412,6 +6438,27 @@ function isQualifiedId(id) {
|
|
|
6412
6438
|
|
|
6413
6439
|
// src/cli-launch.ts
|
|
6414
6440
|
var AUTH_TOKEN = "turbollm-local";
|
|
6441
|
+
var PI_SEARCH_PACKAGE_NAME = "@heyhuynhgiabuu/pi-search";
|
|
6442
|
+
var PI_SEARCH_PACKAGE_SPEC = `${PI_SEARCH_PACKAGE_NAME}@0.3.0`;
|
|
6443
|
+
var PI_SEARCH_INSTALL_DISABLED = () => ["1", "true", "yes"].includes(process.env.TOBOLLM_PI_DISABLE_SEARCH_INSTALL?.toLowerCase() ?? "");
|
|
6444
|
+
var PI_SEARCH_PACKAGES_PREFIX = `npm:${PI_SEARCH_PACKAGE_NAME}@`;
|
|
6445
|
+
var PI_SEARCH_INSTALL_TIMEOUT_MS = 3e4;
|
|
6446
|
+
async function piSearchPackagePresent(fs2) {
|
|
6447
|
+
const path = join17(fs2.home, ".pi", "agent", "settings.json");
|
|
6448
|
+
let raw;
|
|
6449
|
+
try {
|
|
6450
|
+
raw = await fs2.readFile(path);
|
|
6451
|
+
} catch {
|
|
6452
|
+
return false;
|
|
6453
|
+
}
|
|
6454
|
+
let cfg2;
|
|
6455
|
+
try {
|
|
6456
|
+
cfg2 = JSON.parse(stripJsonComments(raw));
|
|
6457
|
+
} catch {
|
|
6458
|
+
return false;
|
|
6459
|
+
}
|
|
6460
|
+
return Array.isArray(cfg2.packages) && cfg2.packages.some((p) => typeof p === "string" && p.startsWith(PI_SEARCH_PACKAGES_PREFIX));
|
|
6461
|
+
}
|
|
6415
6462
|
var SUPPORTED = {
|
|
6416
6463
|
claude: {
|
|
6417
6464
|
bin: "claude",
|
|
@@ -6495,6 +6542,18 @@ var realSpawn = (cmd, args, opts) => {
|
|
|
6495
6542
|
}
|
|
6496
6543
|
return spawn4(buildShellCommand(cmd, args), opts);
|
|
6497
6544
|
};
|
|
6545
|
+
function runWithTimeout(spawnImpl, bin, args, timeoutMs) {
|
|
6546
|
+
return new Promise((resolve6) => {
|
|
6547
|
+
const timer2 = setTimeout(() => resolve6(false), timeoutMs);
|
|
6548
|
+
const child = spawnImpl(bin, args, { stdio: "ignore", shell: process.platform === "win32" });
|
|
6549
|
+
const settle = (code) => {
|
|
6550
|
+
clearTimeout(timer2);
|
|
6551
|
+
resolve6(code === 0);
|
|
6552
|
+
};
|
|
6553
|
+
child.on("error", () => settle(null));
|
|
6554
|
+
child.on("exit", (code) => settle(code));
|
|
6555
|
+
});
|
|
6556
|
+
}
|
|
6498
6557
|
async function fetchStatus(base2, _fetch = fetch) {
|
|
6499
6558
|
try {
|
|
6500
6559
|
const res = await _fetch(`${base2}/api/v1/status`, { signal: AbortSignal.timeout(3e3) });
|
|
@@ -6975,6 +7034,27 @@ async function syncHarnessModelConfig(target, opts, fs2 = realFs) {
|
|
|
6975
7034
|
AUTH_TOKEN
|
|
6976
7035
|
);
|
|
6977
7036
|
}
|
|
7037
|
+
async function ensurePiSearchPackage(run2 = realRunCommand, fs2 = realFs) {
|
|
7038
|
+
if (PI_SEARCH_INSTALL_DISABLED()) return;
|
|
7039
|
+
if (await piSearchPackagePresent(fs2)) return;
|
|
7040
|
+
let ok = false;
|
|
7041
|
+
try {
|
|
7042
|
+
ok = await run2("pi", ["install", `npm:${PI_SEARCH_PACKAGE_SPEC}`]);
|
|
7043
|
+
} catch {
|
|
7044
|
+
ok = false;
|
|
7045
|
+
}
|
|
7046
|
+
if (ok) {
|
|
7047
|
+
process.stderr.write(
|
|
7048
|
+
`Note: installed pi research tools (${PI_SEARCH_PACKAGE_SPEC}); web search is now available. Opt out any time with TOBOLLM_PI_DISABLE_SEARCH_INSTALL=1.
|
|
7049
|
+
`
|
|
7050
|
+
);
|
|
7051
|
+
} else {
|
|
7052
|
+
process.stderr.write(
|
|
7053
|
+
`Note: could not auto-install pi research tools (${PI_SEARCH_PACKAGE_SPEC}); web search will be unavailable until you run: pi install npm:${PI_SEARCH_PACKAGE_SPEC}.
|
|
7054
|
+
`
|
|
7055
|
+
);
|
|
7056
|
+
}
|
|
7057
|
+
}
|
|
6978
7058
|
async function launchCli(target, port2, passthrough, _spawn = realSpawn, modelKey, _fetch = fetch, authToken, _mcpFs = realFs) {
|
|
6979
7059
|
const spec = SUPPORTED[target];
|
|
6980
7060
|
if (!target || !spec) {
|
|
@@ -7120,6 +7200,10 @@ Open ${base2} \u2192 Models \u2192 Load a model, then run this again.
|
|
|
7120
7200
|
return 1;
|
|
7121
7201
|
}
|
|
7122
7202
|
}
|
|
7203
|
+
if (target === "pi") {
|
|
7204
|
+
const piSearchRun = (bin, args2) => runWithTimeout(_spawn, bin, args2, PI_SEARCH_INSTALL_TIMEOUT_MS);
|
|
7205
|
+
await ensurePiSearchPackage(piSearchRun, _mcpFs);
|
|
7206
|
+
}
|
|
7123
7207
|
const env = {
|
|
7124
7208
|
...inheritedEnv(process.env, spec.parentEnvMarkers),
|
|
7125
7209
|
...await spec.env?.(launchCtx) ?? {}
|
|
@@ -8416,6 +8500,10 @@ function finalizeSwapOutcome(d, runId, swap, ranStatus) {
|
|
|
8416
8500
|
d.db.updateRoutineRun(runId, { status: "skipped", skipReason: "model_busy", endedAt });
|
|
8417
8501
|
return "skipped";
|
|
8418
8502
|
}
|
|
8503
|
+
if (swap.outcome === "skip-comfyui-busy") {
|
|
8504
|
+
d.db.updateRoutineRun(runId, { status: "skipped", skipReason: "comfyui_busy", endedAt });
|
|
8505
|
+
return "skipped";
|
|
8506
|
+
}
|
|
8419
8507
|
d.db.updateRoutineRun(runId, { status: "errored", error: swap.message, endedAt });
|
|
8420
8508
|
return "errored";
|
|
8421
8509
|
}
|
|
@@ -9040,7 +9128,7 @@ function estimateVramPerGpu(p, m, sys) {
|
|
|
9040
9128
|
const blocks = m.blockCount > 0 ? m.blockCount : 1;
|
|
9041
9129
|
const sizeMb = m.sizeBytes / 1e6;
|
|
9042
9130
|
const perLayerMb = sizeMb * GPU_WEIGHT_FRACTION / blocks;
|
|
9043
|
-
const residentLayers =
|
|
9131
|
+
const residentLayers = Math.max(0, Math.min(p.ngl, blocks));
|
|
9044
9132
|
const nCpuMoe = m.moe ? Math.max(0, Math.min(p.nCpuMoe, blocks)) : 0;
|
|
9045
9133
|
const layers = new Array(n).fill(0);
|
|
9046
9134
|
if (p.gpu?.splitMode === "none" || n === 1) {
|
|
@@ -9247,6 +9335,10 @@ function profileToArgs(p, m, caps, cores = 0, sys, binPath) {
|
|
|
9247
9335
|
if (specType) a.push("--spec-type", "draft");
|
|
9248
9336
|
a.push("--model-draft", p.draftModelPath);
|
|
9249
9337
|
specActive = true;
|
|
9338
|
+
} else if (p.speculative === "dflash" && p.draftModelPath && specType && specAccepts("draft-dflash") && has("--spec-draft-model")) {
|
|
9339
|
+
a.push("--spec-type", "draft-dflash");
|
|
9340
|
+
a.push("--spec-draft-model", p.draftModelPath);
|
|
9341
|
+
specActive = true;
|
|
9250
9342
|
}
|
|
9251
9343
|
if (specActive) {
|
|
9252
9344
|
if (has("--draft-max")) a.push("--draft-max", String(p.draftMax ?? 16));
|
|
@@ -10758,6 +10850,7 @@ import {
|
|
|
10758
10850
|
SettingsManager,
|
|
10759
10851
|
isEditToolResult
|
|
10760
10852
|
} from "@earendil-works/pi-coding-agent";
|
|
10853
|
+
import { estimateTokens, calculateContextTokens } from "@earendil-works/pi-coding-agent";
|
|
10761
10854
|
|
|
10762
10855
|
// src/code/robust-bash.ts
|
|
10763
10856
|
import { access as fsAccess } from "fs/promises";
|
|
@@ -12516,7 +12609,35 @@ ${lines.join("\n")}${more}]`
|
|
|
12516
12609
|
}
|
|
12517
12610
|
const finalText = session.getLastAssistantText() ?? "";
|
|
12518
12611
|
const stats = session.getSessionStats();
|
|
12519
|
-
|
|
12612
|
+
let contextUsed;
|
|
12613
|
+
if (stats.contextUsage?.tokens != null) {
|
|
12614
|
+
contextUsed = stats.contextUsage.tokens;
|
|
12615
|
+
} else {
|
|
12616
|
+
let lastUsage;
|
|
12617
|
+
let lastUsageIdx = -1;
|
|
12618
|
+
for (let i = session.messages.length - 1; i >= 0; i--) {
|
|
12619
|
+
const m = session.messages[i];
|
|
12620
|
+
if (m.role === "assistant" && "usage" in m) {
|
|
12621
|
+
const u = m.usage;
|
|
12622
|
+
if (u && calculateContextTokens(u) > 0) {
|
|
12623
|
+
lastUsage = u;
|
|
12624
|
+
lastUsageIdx = i;
|
|
12625
|
+
break;
|
|
12626
|
+
}
|
|
12627
|
+
}
|
|
12628
|
+
}
|
|
12629
|
+
if (lastUsage) {
|
|
12630
|
+
contextUsed = calculateContextTokens(lastUsage);
|
|
12631
|
+
for (let i = lastUsageIdx + 1; i < session.messages.length; i++) {
|
|
12632
|
+
contextUsed += estimateTokens(session.messages[i]);
|
|
12633
|
+
}
|
|
12634
|
+
} else {
|
|
12635
|
+
contextUsed = 0;
|
|
12636
|
+
for (const m of session.messages) {
|
|
12637
|
+
contextUsed += estimateTokens(m);
|
|
12638
|
+
}
|
|
12639
|
+
}
|
|
12640
|
+
}
|
|
12520
12641
|
const contextMax = stats.contextUsage?.contextWindow ?? contextWindow;
|
|
12521
12642
|
const usage = foldTurnUsage(stats.tokens, { promptMsTotal, genMsTotal, ttftMs, totalMs: Date.now() - turnStartedAt });
|
|
12522
12643
|
session.dispose();
|
|
@@ -12616,7 +12737,10 @@ async function compactCodeSession(params) {
|
|
|
12616
12737
|
compactionUpToMessageId: upToMessageId,
|
|
12617
12738
|
compactionTokensBefore: result.tokensBefore
|
|
12618
12739
|
});
|
|
12619
|
-
|
|
12740
|
+
const summaryTokens = Math.ceil(result.summary.length / 4);
|
|
12741
|
+
const ctxUsed = compactionSettings.keepRecentTokens + summaryTokens;
|
|
12742
|
+
d.db.setCodeSessionCtxUsed(sessionId, ctxUsed);
|
|
12743
|
+
return { summary: result.summary, upToMessageId, tokensBefore: result.tokensBefore, ctxUsed };
|
|
12620
12744
|
}
|
|
12621
12745
|
async function lookbackPreCompactionHistory(params) {
|
|
12622
12746
|
const { d, convId, sessionId, repoRoot, question, signal } = params;
|
|
@@ -15260,6 +15384,10 @@ var ConversationStore = class {
|
|
|
15260
15384
|
`);
|
|
15261
15385
|
this.db.exec(`PRAGMA user_version = 48;`);
|
|
15262
15386
|
}
|
|
15387
|
+
if (v < 49) {
|
|
15388
|
+
if (!this.hasColumn("api_usage", "ctx_used")) this.db.exec(`ALTER TABLE api_usage ADD COLUMN ctx_used INTEGER DEFAULT 0;`);
|
|
15389
|
+
this.db.exec(`PRAGMA user_version = 49;`);
|
|
15390
|
+
}
|
|
15263
15391
|
}
|
|
15264
15392
|
listConversations(q, kind = "all") {
|
|
15265
15393
|
if (q) {
|
|
@@ -15630,8 +15758,8 @@ var ConversationStore = class {
|
|
|
15630
15758
|
recordApiUsage(rec) {
|
|
15631
15759
|
const rate = (v) => v != null && Number.isFinite(v) && v > 0 ? v : null;
|
|
15632
15760
|
this.db.prepare(`
|
|
15633
|
-
INSERT INTO api_usage (id, created_at, source, model_key, prompt_tokens, gen_tokens, code_session_id, duration_ms, prompt_tps, gen_tps, harness)
|
|
15634
|
-
VALUES ($id, $createdAt, $source, $modelKey, $promptTokens, $genTokens, $codeSessionId, $durationMs, $promptTps, $genTps, $harness)
|
|
15761
|
+
INSERT INTO api_usage (id, created_at, source, model_key, prompt_tokens, gen_tokens, code_session_id, duration_ms, prompt_tps, gen_tps, harness, ctx_used)
|
|
15762
|
+
VALUES ($id, $createdAt, $source, $modelKey, $promptTokens, $genTokens, $codeSessionId, $durationMs, $promptTps, $genTps, $harness, $ctxUsed)
|
|
15635
15763
|
`).run({
|
|
15636
15764
|
$id: randomUUID6(),
|
|
15637
15765
|
$createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -15643,9 +15771,40 @@ var ConversationStore = class {
|
|
|
15643
15771
|
$durationMs: rec.durationMs != null && Number.isFinite(rec.durationMs) ? Math.max(0, Math.floor(rec.durationMs)) : null,
|
|
15644
15772
|
$promptTps: rate(rec.promptTps),
|
|
15645
15773
|
$genTps: rate(rec.genTps),
|
|
15646
|
-
$harness: rec.harness ?? null
|
|
15774
|
+
$harness: rec.harness ?? null,
|
|
15775
|
+
$ctxUsed: Math.max(0, Math.floor(rec.promptTokens) || 0)
|
|
15647
15776
|
});
|
|
15648
15777
|
}
|
|
15778
|
+
/** Lower the current context size for a Code session after /compact, so the ctx gauge
|
|
15779
|
+
* reflects post-compaction reality (ADR-386). Updates the row with the MAX ctx_used
|
|
15780
|
+
* to the new value — this is what allows /compact to lower the ring's frozen ceiling.
|
|
15781
|
+
* If no row exists yet (fresh session compacted before first gateway request), creates one. */
|
|
15782
|
+
setCodeSessionCtxUsed(codeSessionId, ctxUsed) {
|
|
15783
|
+
const maxRow = this.db.prepare(`
|
|
15784
|
+
SELECT id FROM api_usage
|
|
15785
|
+
WHERE code_session_id = $codeSessionId AND ctx_used = (
|
|
15786
|
+
SELECT MAX(ctx_used) FROM api_usage WHERE code_session_id = $codeSessionId
|
|
15787
|
+
)
|
|
15788
|
+
LIMIT 1
|
|
15789
|
+
`).get({ $codeSessionId: codeSessionId });
|
|
15790
|
+
if (maxRow) {
|
|
15791
|
+
this.db.prepare(`
|
|
15792
|
+
UPDATE api_usage SET ctx_used = $ctxUsed, prompt_tokens = $promptTokens, created_at = $createdAt
|
|
15793
|
+
WHERE id = $id
|
|
15794
|
+
`).run({ $ctxUsed: ctxUsed, $promptTokens: ctxUsed, $createdAt: (/* @__PURE__ */ new Date()).toISOString(), $id: maxRow.id });
|
|
15795
|
+
} else {
|
|
15796
|
+
this.db.prepare(`
|
|
15797
|
+
INSERT INTO api_usage (id, created_at, source, prompt_tokens, gen_tokens, code_session_id, ctx_used)
|
|
15798
|
+
VALUES ($id, $createdAt, 'compact', $promptTokens, 0, $codeSessionId, $ctxUsed)
|
|
15799
|
+
`).run({
|
|
15800
|
+
$id: randomUUID6(),
|
|
15801
|
+
$createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15802
|
+
$promptTokens: ctxUsed,
|
|
15803
|
+
$codeSessionId: codeSessionId,
|
|
15804
|
+
$ctxUsed: ctxUsed
|
|
15805
|
+
});
|
|
15806
|
+
}
|
|
15807
|
+
}
|
|
15649
15808
|
/** The session's own gateway-request stats (ADR-284, revised twice — founder-reported "ctx
|
|
15650
15809
|
* fill jumps between full and empty in the same session", then a review pass on that same fix
|
|
15651
15810
|
* catching that it had gone on to freeze the LAST-TURN stats too). Two different questions,
|
|
@@ -15679,14 +15838,14 @@ var ConversationStore = class {
|
|
|
15679
15838
|
* non-terminal-agent one). */
|
|
15680
15839
|
getLastApiUsageForSession(codeSessionId) {
|
|
15681
15840
|
const row = this.db.prepare(`
|
|
15682
|
-
SELECT prompt_tokens, gen_tokens, duration_ms, prompt_tps, gen_tps FROM api_usage
|
|
15841
|
+
SELECT prompt_tokens, gen_tokens, duration_ms, prompt_tps, gen_tps, ctx_used FROM api_usage
|
|
15683
15842
|
WHERE code_session_id = $codeSessionId
|
|
15684
15843
|
ORDER BY created_at DESC LIMIT 1
|
|
15685
15844
|
`).get({ $codeSessionId: codeSessionId });
|
|
15686
15845
|
if (!row) return null;
|
|
15687
15846
|
const ctxUsed = this.db.prepare(`
|
|
15688
|
-
SELECT MAX(
|
|
15689
|
-
`).get({ $codeSessionId: codeSessionId }).
|
|
15847
|
+
SELECT MAX(ctx_used) as maxCtxUsed FROM api_usage WHERE code_session_id = $codeSessionId
|
|
15848
|
+
`).get({ $codeSessionId: codeSessionId }).maxCtxUsed;
|
|
15690
15849
|
const seconds = row.duration_ms != null && row.duration_ms > 0 ? row.duration_ms / 1e3 : null;
|
|
15691
15850
|
return {
|
|
15692
15851
|
ctxUsed,
|
|
@@ -22448,7 +22607,10 @@ var ALL = [
|
|
|
22448
22607
|
support: "stable",
|
|
22449
22608
|
// llama.cpp expands into the backend sub-picker (existing UI); it has no single
|
|
22450
22609
|
// install endpoint of its own.
|
|
22451
|
-
installEndpoint: ""
|
|
22610
|
+
installEndpoint: "",
|
|
22611
|
+
// Its installed state comes from the separate backend-build detection (LlamaCppBackendRows),
|
|
22612
|
+
// not the generic sourceRepo match below — see the field's own doc comment (ADR-388).
|
|
22613
|
+
excludeFromSourceMatch: true
|
|
22452
22614
|
},
|
|
22453
22615
|
{
|
|
22454
22616
|
// Upstream publishes NO Linux CUDA prebuilt (download.ts availableBackends() — Linux
|
|
@@ -24443,11 +24605,11 @@ function registerApi(app2, d) {
|
|
|
24443
24605
|
installed2 = existsSync26(llamafileBinPath(enginesRoot));
|
|
24444
24606
|
enabled = regEngines.some((x) => x.kind === "llamafile");
|
|
24445
24607
|
}
|
|
24446
|
-
const srcEng = regEngines.find(
|
|
24608
|
+
const srcEng = e.excludeFromSourceMatch ? void 0 : regEngines.find(
|
|
24447
24609
|
(x) => sameRepo(x.sourceRepo, e.homepage) && (x.sourceCommit ?? "") === (e.sourceCommit ?? "") && (x.sourcePatchUrl ?? "") === (e.patchUrl ?? "")
|
|
24448
24610
|
);
|
|
24449
24611
|
let sourceBinPath = srcEng?.binPath;
|
|
24450
|
-
if (!srcEng) sourceBinPath = sourceBuildBinary(enginesRoot, e.homepage, void 0, e.sourceCommit) ?? void 0;
|
|
24612
|
+
if (!srcEng && !e.excludeFromSourceMatch) sourceBinPath = sourceBuildBinary(enginesRoot, e.homepage, void 0, e.sourceCommit) ?? void 0;
|
|
24451
24613
|
const sourceBuilt = !!srcEng || !!sourceBinPath;
|
|
24452
24614
|
if (srcEng) {
|
|
24453
24615
|
installed2 = true;
|
|
@@ -24546,7 +24708,7 @@ function registerApi(app2, d) {
|
|
|
24546
24708
|
} catch {
|
|
24547
24709
|
}
|
|
24548
24710
|
}
|
|
24549
|
-
const eng = (await d.registry.add(prior?.name
|
|
24711
|
+
const eng = (await d.registry.add(chooseEngineName(name, prior?.name), out.binPath, {
|
|
24550
24712
|
sourceRepo: repoUrl,
|
|
24551
24713
|
sourceBranch: branch,
|
|
24552
24714
|
sourceCommit: commit,
|
|
@@ -31090,14 +31252,14 @@ import { streamSSE as streamSSE5 } from "hono/streaming";
|
|
|
31090
31252
|
// src/ext/context-limit.ts
|
|
31091
31253
|
var CHARS_PER_TOKEN2 = 3.5;
|
|
31092
31254
|
var REPLY_HEADROOM = 512;
|
|
31093
|
-
function
|
|
31255
|
+
function estimateTokens2(messages) {
|
|
31094
31256
|
let chars = 0;
|
|
31095
31257
|
for (const m of messages) chars += m.content.length + m.role.length + 4;
|
|
31096
31258
|
return Math.ceil(chars / CHARS_PER_TOKEN2);
|
|
31097
31259
|
}
|
|
31098
31260
|
function checkContextFits(d, messages) {
|
|
31099
31261
|
const limit = d.manager.status().model?.ctx ?? 0;
|
|
31100
|
-
const estimated =
|
|
31262
|
+
const estimated = estimateTokens2(messages);
|
|
31101
31263
|
if (!limit) return { fits: true, estimated, limit: 0 };
|
|
31102
31264
|
return { fits: estimated + REPLY_HEADROOM <= limit, estimated, limit };
|
|
31103
31265
|
}
|
|
@@ -1 +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-DDdTmEU4.js";import{f as V}from"./chat-api-CmDwSCUy.js";import{f as X,a as Z}from"./agent-api-Bbbnu920.js";import{P as B}from"./personas-B7q-7L3z.js";import{C as ee}from"./chevron-left-CwO2nWWZ.js";import{R as te}from"./rotate-ccw-CTfSFG3x.js";import{T as se}from"./trash-2-BNNKBgll.js";import{C as ne}from"./chevron-right-Ck02yYBx.js";import"./dropdown-menu-CaMJbKX5.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};
|
|
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-hEBbEVm0.js";import{f as V}from"./chat-api-DUobixOH.js";import{f as X,a as Z}from"./agent-api-C-qZrrYO.js";import{P as B}from"./personas-Dkq9JD72.js";import{C as ee}from"./chevron-left-CRkSrIuw.js";import{R as te}from"./rotate-ccw-DVWlxS6M.js";import{T as se}from"./trash-2-dTSieVsH.js";import{C as ne}from"./chevron-right-D6YKa1nw.js";import"./dropdown-menu-D5Vf7U3W.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};
|