turbollm 1.10.5 → 1.10.6
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/dist/cli.js +162 -30
- package/dist/webdist/assets/{AgentEditPage-Bq0To2Kn.js → AgentEditPage-Cjrahm7d.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-JfS4dp94.js → ChatScreen-BE2j_M7n.js} +1 -1
- package/dist/webdist/assets/{CodeComposer-BPcKbMuH.js → CodeComposer-CB0nORiZ.js} +1 -1
- package/dist/webdist/assets/{CodeHomeScreen-CbY_UCs6.js → CodeHomeScreen-Bh0BY6aY.js} +1 -1
- package/dist/webdist/assets/{CodeSessionScreen-nU50H3fR.js → CodeSessionScreen-MM4gt_kH.js} +1 -1
- package/dist/webdist/assets/{CustomizeScreen-jI99vrYL.js → CustomizeScreen-zvF_dtiC.js} +1 -1
- package/dist/webdist/assets/{DeveloperScreen-BfYnTO7e.js → DeveloperScreen-DXzdDB5X.js} +1 -1
- package/dist/webdist/assets/{EnginesScreen-CU8ZNHcl.js → EnginesScreen-CLkBmRVD.js} +1 -1
- package/dist/webdist/assets/{ModelDetailDialog-DKUMTU2w.js → ModelDetailDialog-CL8_8e9a.js} +1 -1
- package/dist/webdist/assets/{ModelLoadMenu-CBj32oEE.js → ModelLoadMenu-C6W2D_HT.js} +1 -1
- package/dist/webdist/assets/{ModelsScreen-CTYIbZyc.js → ModelsScreen-CMEUd2XW.js} +1 -1
- package/dist/webdist/assets/{RoutineEditPage-gqLu8cXv.js → RoutineEditPage-DNt9jwLQ.js} +1 -1
- package/dist/webdist/assets/{RoutinesPanel-Dv9Shubg.js → RoutinesPanel-APLk8zAj.js} +1 -1
- package/dist/webdist/assets/{SettingsScreen-C7LQLNGe.js → SettingsScreen-CNEhuloT.js} +1 -1
- package/dist/webdist/assets/{SidebarResizeHandle-Djhjx6qR.js → SidebarResizeHandle-BGh24zM4.js} +1 -1
- package/dist/webdist/assets/{SkillEditPage-ClBJXbC3.js → SkillEditPage-QktxVVZP.js} +1 -1
- package/dist/webdist/assets/{TokensScreen-gk_Mqi5g.js → TokensScreen-BQu-wJ5j.js} +1 -1
- package/dist/webdist/assets/{ToolApprovalBar-B3WSFcyU.js → ToolApprovalBar-WuURxg64.js} +3 -3
- package/dist/webdist/assets/WorkspaceScreen-DR9iCevI.js +1 -0
- package/dist/webdist/assets/{abnfDiagram-N423BO3Z-QSevWJ37.js → abnfDiagram-N423BO3Z-Xdm1Ge5Z.js} +1 -1
- package/dist/webdist/assets/{agent-api-CpgzOfg0.js → agent-api-Dsb2M3gT.js} +1 -1
- package/dist/webdist/assets/{alert-dialog-CMvNzcK0.js → alert-dialog-CLYOFUQB.js} +1 -1
- package/dist/webdist/assets/{arc-BWbVGHju.js → arc-D2e7_fvj.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-T3A2C74G-Boh67Blv.js → architectureDiagram-T3A2C74G-NOGk06k9.js} +1 -1
- package/dist/webdist/assets/{arrow-left-CU7vJBtU.js → arrow-left-Be5kJCK_.js} +1 -1
- package/dist/webdist/assets/{badge-BOGctZvx.js → badge-ZKEdg9KY.js} +1 -1
- package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-BkIBotfv.js → blockDiagram-VBNYF7ZC-DmcFoOYB.js} +1 -1
- package/dist/webdist/assets/{bot-CwYS2B1G.js → bot-oaBq4kgz.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-5PPSVZJV-CWCZQHIc.js → c4Diagram-5PPSVZJV-zzYM53Qc.js} +1 -1
- package/dist/webdist/assets/channel-BdTqTBNl.js +1 -0
- package/dist/webdist/assets/{chat-api-BTcC6kED.js → chat-api-D7WunS4X.js} +1 -1
- package/dist/webdist/assets/{chat-queries-D9fFhHaQ.js → chat-queries-DfV_X46e.js} +1 -1
- package/dist/webdist/assets/{chevron-left-BVxkM758.js → chevron-left-DqcpOb9h.js} +1 -1
- package/dist/webdist/assets/{chevron-right-BJZRbTUj.js → chevron-right-D7i8peZR.js} +1 -1
- package/dist/webdist/assets/{chunk-2GRJ4B5K-C5CXDrO_.js → chunk-2GRJ4B5K-tWNhRyV6.js} +1 -1
- package/dist/webdist/assets/{chunk-2Q5K7J3B-Bk_wrlB0.js → chunk-2Q5K7J3B-jT4PFPv5.js} +1 -1
- package/dist/webdist/assets/{chunk-5RXB4S5H-BAT4FnUI.js → chunk-5RXB4S5H-CBgg6cvO.js} +1 -1
- package/dist/webdist/assets/{chunk-5VM5RSS4-C9eEV1Kl.js → chunk-5VM5RSS4-Do3-h3Xi.js} +1 -1
- package/dist/webdist/assets/{chunk-6Q2QTUOP-CJDFqmYe.js → chunk-6Q2QTUOP-Y4iDp1I8.js} +1 -1
- package/dist/webdist/assets/{chunk-GF5L2VYU-CsgBXjfk.js → chunk-GF5L2VYU-Bj41431x.js} +1 -1
- package/dist/webdist/assets/{chunk-JWPE2WC7-CRt7uW9O.js → chunk-JWPE2WC7-CufywS1e.js} +1 -1
- package/dist/webdist/assets/{chunk-KBJHAD2P-CSsVpcf6.js → chunk-KBJHAD2P-BPLIKhbV.js} +1 -1
- package/dist/webdist/assets/{chunk-RYQCIY6F-eTll7wC1.js → chunk-RYQCIY6F-CmcnhnsQ.js} +1 -1
- package/dist/webdist/assets/{chunk-XXDRQBXY-D2-Dj7EK.js → chunk-XXDRQBXY-onzm5o_Q.js} +1 -1
- package/dist/webdist/assets/{circle-check-g29PWBwU.js → circle-check-BY8jczPf.js} +1 -1
- package/dist/webdist/assets/{circle-x-BgFrKCxR.js → circle-x-BUlKg2cZ.js} +1 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-R1cuP_Pr.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-R1cuP_Pr.js +1 -0
- package/dist/webdist/assets/{common-Fwu8t36v.js → common-BsHtz98M.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-JH36ORCC-DXafCcEB.js → cose-bilkent-JH36ORCC-8JLhJahr.js} +1 -1
- package/dist/webdist/assets/{cynefin-VYW2F7L2-CecX93d_.js → cynefin-VYW2F7L2-CBL5ANhm.js} +1 -1
- package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-tu8xDmsR.js → cynefinDiagram-MW4NZA55-Cmwj48UP.js} +1 -1
- package/dist/webdist/assets/{dagre-VZM6K2ZE-UG2o94YJ.js → dagre-VZM6K2ZE-DngjyEsb.js} +1 -1
- package/dist/webdist/assets/{diagram-7IWD3JNH-3DRTAZAF.js → diagram-7IWD3JNH-OQyUakUJ.js} +1 -1
- package/dist/webdist/assets/{diagram-B4RE2ZJO-CwH0bQ2A.js → diagram-B4RE2ZJO-uWCxDSmb.js} +1 -1
- package/dist/webdist/assets/{diagram-LBJQPF4R-DuybxKFU.js → diagram-LBJQPF4R-BYhk_VPg.js} +1 -1
- package/dist/webdist/assets/{diagram-Q27KOJAE-BwoB84ui.js → diagram-Q27KOJAE-CzML3pPm.js} +1 -1
- package/dist/webdist/assets/{diagram-UB23O5K3-DEjbnHCQ.js → diagram-UB23O5K3-DIL750-6.js} +1 -1
- package/dist/webdist/assets/{dropdown-menu-D25-JVEy.js → dropdown-menu-CCRmjOB8.js} +1 -1
- package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-DG9Xbpyw.js → ebnfDiagram-BXEA7PRR-IOFFHUjP.js} +1 -1
- package/dist/webdist/assets/{erDiagram-JOGREHBK-eysaP8yv.js → erDiagram-JOGREHBK-CsYREjU2.js} +1 -1
- package/dist/webdist/assets/{external-link-Xn8kJljc.js → external-link-CwcqLXeC.js} +1 -1
- package/dist/webdist/assets/{file-text-BmAkLphS.js → file-text-CfktJNKt.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-UKHOOZJN-Bfha7bpG.js → flowDiagram-UKHOOZJN-D8V23snk.js} +1 -1
- package/dist/webdist/assets/{folder-input-BRjaJam7.js → folder-input-CAX7jGqy.js} +1 -1
- package/dist/webdist/assets/{folder-plus-DBJ9oQjK.js → folder-plus-DRH9A_nf.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-CJotaSgm.js → ganttDiagram-PKOTCBZU-BNFLscau.js} +1 -1
- package/dist/webdist/assets/{git-branch-DerJ3eCK.js → git-branch-D3SWa_HB.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-C8za5q5H.js → gitGraphDiagram-DS77QQ5N-CACE08jS.js} +1 -1
- package/dist/webdist/assets/{index-CRd__4R1.js → index-C3DcPrhr.js} +2 -2
- package/dist/webdist/assets/{infoDiagram-6WML65LV-C95kKxPZ.js → infoDiagram-6WML65LV-Bgac4fco.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-DOIqcMyH.js → ishikawaDiagram-WSZJBQD7-B-Gx-xHY.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-BBirkGE7.js → journeyDiagram-NVQOT4AX-HkIDa9gF.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-27J2QSJJ-CPhjxJyV.js → kanban-definition-27J2QSJJ-D9fCO--l.js} +1 -1
- package/dist/webdist/assets/{linear-BWhxZFqF.js → linear-BCzUyXir.js} +1 -1
- package/dist/webdist/assets/{lock-CpPOIG8p.js → lock-DU6baFK9.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-DocKtbj4.js → mermaid.core-DKhj1zV1.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-wL4xGOU_.js → mindmap-definition-FAOFIHXS-DStYIFGn.js} +1 -1
- package/dist/webdist/assets/{pegDiagram-VL7TDLO6-D19VvRVO.js → pegDiagram-VL7TDLO6-CMkk8HUV.js} +1 -1
- package/dist/webdist/assets/{pencil-c-PJkJes.js → pencil-Bt-RSZUH.js} +1 -1
- package/dist/webdist/assets/{personas-B0p0BX69.js → personas-DLa9ZPoi.js} +4 -4
- package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-Doy7WZyw.js → pieDiagram-7S7Q4E2Y-BaK0uEYv.js} +1 -1
- package/dist/webdist/assets/{plus-CP7d5krT.js → plus-CFBywfW5.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-BO535Mye.js → quadrantDiagram-CIZ2JOQS-C34UZIt1.js} +1 -1
- package/dist/webdist/assets/{railroadDiagram-AXF67PYL-C_F6C_-j.js → railroadDiagram-AXF67PYL-Ckb23iRj.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-CUFncOr4.js → refresh-cw-BjYW1yib.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-COStqNVI.js → requirementDiagram-LRYGKXZP-CG2IfNZ8.js} +1 -1
- package/dist/webdist/assets/{rotate-ccw-gR3mMTRM.js → rotate-ccw-CDrolPd6.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-DrpcfTw1.js → sankeyDiagram-W5VNT64P-C37_2Ghs.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-CQ1WUoj0.js → sequenceDiagram-SI44F4Z6-Cbd9Ydzi.js} +1 -1
- package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-CExk2dPw.js → sizeCapture-X5ZJPWSS-Db4VW9lY.js} +1 -1
- package/dist/webdist/assets/{skeleton-CapS3LhZ.js → skeleton-C8GLzn0j.js} +1 -1
- package/dist/webdist/assets/{sliders-horizontal-VjLq-9i0.js → sliders-horizontal-ChT1DRyQ.js} +1 -1
- package/dist/webdist/assets/{sparkles-BS98k72s.js → sparkles-BgaRXk3Z.js} +1 -1
- package/dist/webdist/assets/{star-Ce5Pu8jP.js → star-CVPXfTy4.js} +1 -1
- package/dist/webdist/assets/{stateDiagram-OKZ733FA-6IQ9pQNr.js → stateDiagram-OKZ733FA-RgxA3rS_.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-DW4K46xR.js +1 -0
- package/dist/webdist/assets/{swimlanes-SLNWSIFB-0AoFXo4W.js → swimlanes-SLNWSIFB-PmBwCiF3.js} +2 -2
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC--nEBdjnh.js +8 -0
- package/dist/webdist/assets/{switch-BVPOy4cS.js → switch-CjDd4avM.js} +1 -1
- package/dist/webdist/assets/{terminal-WfRPZiaW.js → terminal-z7vkSxg1.js} +1 -1
- package/dist/webdist/assets/{timeline-definition-Z64GVDOM-LPqGGX5H.js → timeline-definition-Z64GVDOM-vxaLdkHH.js} +1 -1
- package/dist/webdist/assets/{trash-2-DZYSgl2R.js → trash-2-BNqXKVdk.js} +1 -1
- package/dist/webdist/assets/{useIsDesktop-CjFyl6hu.js → useIsDesktop-CRP_qB3o.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-T6HMQDX7--BcdXECz.js → vennDiagram-T6HMQDX7-CY5Ha4JW.js} +1 -1
- package/dist/webdist/assets/{vram-DlcIXX82.js → vram-C6uGfhzc.js} +1 -1
- package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y-Cdki47W1.js → wardleyDiagram-T6FBY63Y-DQzV926_.js} +1 -1
- package/dist/webdist/assets/{wrench-DOaBHWWN.js → wrench-Db816rX1.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-3hkxEbMo.js → xychartDiagram-ELKLHX3M-B7OfhEpC.js} +1 -1
- package/dist/webdist/index.html +1 -1
- package/package.json +1 -1
- package/dist/webdist/assets/WorkspaceScreen-jL5YURRX.js +0 -1
- package/dist/webdist/assets/channel-Yxxa5Jtv.js +0 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-Cr7eMrK7.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-Cr7eMrK7.js +0 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-D-qEGyyy.js +0 -1
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-DJV5Gciz.js +0 -8
package/dist/cli.js
CHANGED
|
@@ -15602,6 +15602,17 @@ import { execFile as execFile10 } from "child_process";
|
|
|
15602
15602
|
import { readFileSync as readFileSync12 } from "fs";
|
|
15603
15603
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
15604
15604
|
|
|
15605
|
+
// src/bench/spill.ts
|
|
15606
|
+
var SPILL_TOLERANCE_MB = 512;
|
|
15607
|
+
function spillMb(baselineSharedMb, loadedSharedMb) {
|
|
15608
|
+
if (baselineSharedMb === null || loadedSharedMb === null) return null;
|
|
15609
|
+
return Math.max(0, loadedSharedMb - baselineSharedMb);
|
|
15610
|
+
}
|
|
15611
|
+
function isSpilling(spill) {
|
|
15612
|
+
if (spill === null) return false;
|
|
15613
|
+
return spill > SPILL_TOLERANCE_MB;
|
|
15614
|
+
}
|
|
15615
|
+
|
|
15605
15616
|
// src/api/path-utils.ts
|
|
15606
15617
|
function inferRepoFromPath(filePath, modelDirs) {
|
|
15607
15618
|
const norm = (p) => p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
@@ -16529,7 +16540,6 @@ var PREFILL_GRACE_MS = 8e3;
|
|
|
16529
16540
|
var TOTAL_BUDGET_MS = 45 * 6e4;
|
|
16530
16541
|
var OOM_RE = /out of memory|cudaMalloc|failed to allocate|unable to allocate|device not ready|CUDA error/i;
|
|
16531
16542
|
var QUALITY_KV = ["f16", "q8_0", "turbo4"];
|
|
16532
|
-
var OUTPUT_TIE = 0.05;
|
|
16533
16543
|
var KV_BYTES = {
|
|
16534
16544
|
f32: 4,
|
|
16535
16545
|
f16: 2,
|
|
@@ -16802,16 +16812,28 @@ var BenchRunner = class {
|
|
|
16802
16812
|
const probe2 = await this.probeVram(entry, sys, { ...base2, ngl: mid }, caps);
|
|
16803
16813
|
this.pushProbe(results, base2, "ngl", mid, probe2);
|
|
16804
16814
|
await this.settleGpu(sys);
|
|
16805
|
-
|
|
16815
|
+
const verdict = probeVerdict(probe2, budgetMb, headroomMb);
|
|
16816
|
+
if (verdict.decision === "fits") {
|
|
16806
16817
|
bestNgl = mid;
|
|
16807
16818
|
lo = mid + 1;
|
|
16808
16819
|
} else {
|
|
16820
|
+
if (verdict.reason === "spill") {
|
|
16821
|
+
this.emit(`ngl=${mid} spilling ${Math.round(verdict.shortfallMb ?? 0)} MB to system RAM \u2014 using fewer GPU layers`);
|
|
16822
|
+
}
|
|
16809
16823
|
hi = mid - 1;
|
|
16810
16824
|
}
|
|
16811
16825
|
}
|
|
16812
16826
|
}
|
|
16813
16827
|
if (bestNgl === null) return null;
|
|
16814
16828
|
let found = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl }, caps, results, `ngl=${bestNgl}`);
|
|
16829
|
+
if (found && isSpilling(found.cand.spillMb) && bestNgl > 0) {
|
|
16830
|
+
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}`);
|
|
16831
|
+
const safer = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl - 1 }, caps, results, `ngl=${bestNgl - 1} (spill backoff)`);
|
|
16832
|
+
if (safer) {
|
|
16833
|
+
found = safer;
|
|
16834
|
+
bestNgl = bestNgl - 1;
|
|
16835
|
+
}
|
|
16836
|
+
}
|
|
16815
16837
|
if (found && overHeadroom(found.cand.vramAbsMb, budgetMb, headroomMb) && bestNgl > 0) {
|
|
16816
16838
|
this.emit(`ngl=${bestNgl} exceeded headroom after generation (${found.cand.vramAbsMb} MB) \u2014 retrying at ngl=${bestNgl - 1}`);
|
|
16817
16839
|
const safer = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl - 1 }, caps, results, `ngl=${bestNgl - 1} (headroom backoff)`);
|
|
@@ -16845,32 +16867,61 @@ var BenchRunner = class {
|
|
|
16845
16867
|
const probe2 = await this.probeVram(entry, sys, { ...base2, nCpuMoe: mid }, caps);
|
|
16846
16868
|
this.pushProbe(results, base2, "nCpuMoe", mid, probe2);
|
|
16847
16869
|
await this.settleGpu(sys);
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
} else if (probe2.outcome === "ok") {
|
|
16870
|
+
const verdict = probeVerdict(probe2, budgetMb, headroomMb);
|
|
16871
|
+
if (verdict.decision === "fits") {
|
|
16851
16872
|
bestN = mid;
|
|
16852
16873
|
hi = mid - 1;
|
|
16853
16874
|
} else {
|
|
16875
|
+
if (verdict.reason === "spill") {
|
|
16876
|
+
this.emit(`nCpuMoe=${mid} spilling ${Math.round(verdict.shortfallMb ?? 0)} MB to system RAM \u2014 offloading more`);
|
|
16877
|
+
}
|
|
16854
16878
|
lo = mid + 1;
|
|
16855
16879
|
}
|
|
16856
16880
|
}
|
|
16857
16881
|
if (bestN === null) return null;
|
|
16858
|
-
let found =
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
const
|
|
16862
|
-
|
|
16882
|
+
let found = null;
|
|
16883
|
+
let foundN = bestN;
|
|
16884
|
+
for (let n = bestN; n <= maxN; n++) {
|
|
16885
|
+
const label = n === bestN ? `nCpuMoe=${n}` : `nCpuMoe=${n} (crash backoff)`;
|
|
16886
|
+
found = await this.benchAt(entry, sys, { ...base2, nCpuMoe: n }, caps, results, label);
|
|
16887
|
+
if (found) {
|
|
16888
|
+
foundN = n;
|
|
16889
|
+
break;
|
|
16890
|
+
}
|
|
16891
|
+
const stopped = this.cancelled || Date.now() > this.deadline;
|
|
16892
|
+
if (stopped) {
|
|
16893
|
+
this.emit(`nCpuMoe=${n} failed to bench (${results[results.length - 1]?.outcome ?? "crash"}) \u2014 run ${this.cancelled ? "cancelled" : "out of time budget"}, stopping`);
|
|
16894
|
+
break;
|
|
16895
|
+
}
|
|
16896
|
+
if (n < maxN) this.emit(`nCpuMoe=${n} failed to bench (${results[results.length - 1]?.outcome ?? "crash"}) \u2014 retrying at nCpuMoe=${n + 1}`);
|
|
16897
|
+
}
|
|
16898
|
+
if (found && isSpilling(found.cand.spillMb) && foundN < maxN) {
|
|
16899
|
+
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}`);
|
|
16900
|
+
const safer = await this.benchAt(entry, sys, { ...base2, nCpuMoe: foundN + 1 }, caps, results, `nCpuMoe=${foundN + 1} (spill backoff)`);
|
|
16901
|
+
if (safer) {
|
|
16902
|
+
found = safer;
|
|
16903
|
+
foundN = foundN + 1;
|
|
16904
|
+
}
|
|
16905
|
+
}
|
|
16906
|
+
if (found && overHeadroom(found.cand.vramAbsMb, budgetMb, headroomMb) && foundN < maxN) {
|
|
16907
|
+
this.emit(`nCpuMoe=${foundN} exceeded headroom after generation (${found.cand.vramAbsMb} MB) \u2014 retrying at nCpuMoe=${foundN + 1}`);
|
|
16908
|
+
const safer = await this.benchAt(entry, sys, { ...base2, nCpuMoe: foundN + 1 }, caps, results, `nCpuMoe=${foundN + 1} (headroom backoff)`);
|
|
16909
|
+
if (safer) {
|
|
16910
|
+
found = safer;
|
|
16911
|
+
foundN = foundN + 1;
|
|
16912
|
+
}
|
|
16863
16913
|
}
|
|
16864
16914
|
if (headroomMb === VRAM_HEADROOM_SPILL_MB && found && found.cand.tps !== null) {
|
|
16865
16915
|
let current = found;
|
|
16866
16916
|
while (current.cand.params.nCpuMoe > 0 && !this.cancelled && Date.now() <= this.deadline) {
|
|
16867
16917
|
const spillN = current.cand.params.nCpuMoe - 1;
|
|
16868
|
-
const prev = {
|
|
16869
|
-
const
|
|
16918
|
+
const prev = { ttftMs: current.cand.ttftMs, tps: current.cand.tps };
|
|
16919
|
+
const prevTtf = ttfMs(prev);
|
|
16920
|
+
const prevLabel = prevTtf !== null ? `${(prevTtf / 1e3).toFixed(1)}s to ${TTF_OUTPUT_TOKENS} tokens` : "an unmeasurable result";
|
|
16870
16921
|
this.emit(`nCpuMoe=${current.cand.params.nCpuMoe} measured ${prevLabel} \u2014 trying VRAM-spill nCpuMoe=${spillN}`);
|
|
16871
16922
|
const spillFound = await this.benchAt(entry, sys, { ...base2, nCpuMoe: spillN }, caps, results, `nCpuMoe=${spillN} (VRAM-spill hill-climb)`);
|
|
16872
16923
|
if (!spillImproves(prev, spillFound?.cand ?? null)) {
|
|
16873
|
-
this.emit(`nCpuMoe=${spillN}
|
|
16924
|
+
this.emit(`nCpuMoe=${spillN} did not beat ${prevLabel} \u2014 stopping climb, keeping nCpuMoe=${current.cand.params.nCpuMoe}`);
|
|
16874
16925
|
break;
|
|
16875
16926
|
}
|
|
16876
16927
|
current = spillFound;
|
|
@@ -16887,7 +16938,7 @@ var BenchRunner = class {
|
|
|
16887
16938
|
* measuring t/s at every search step would be wasted — we bench ONCE, at the chosen config. */
|
|
16888
16939
|
async probeVram(entry, sys, profile, caps) {
|
|
16889
16940
|
const active = this.registry.active();
|
|
16890
|
-
if (!active) return { outcome: "crash", vramAbsMb: null };
|
|
16941
|
+
if (!active) return { outcome: "crash", vramAbsMb: null, spillMb: null };
|
|
16891
16942
|
const testDeadline = Math.min(Date.now() + READY_TIMEOUT_MS + 5e3, this.deadline);
|
|
16892
16943
|
const opts = {
|
|
16893
16944
|
engine: active,
|
|
@@ -16895,19 +16946,22 @@ var BenchRunner = class {
|
|
|
16895
16946
|
modelPath: entry.path,
|
|
16896
16947
|
extraArgs: profileToArgs(profile, entry, caps, sys.cores, sys, active.binPath)
|
|
16897
16948
|
};
|
|
16949
|
+
const sharedBefore = await readGpuSharedMb(sys);
|
|
16898
16950
|
try {
|
|
16899
16951
|
await this.manager.start(opts);
|
|
16900
16952
|
} catch {
|
|
16901
|
-
return { outcome: "crash", vramAbsMb: null };
|
|
16953
|
+
return { outcome: "crash", vramAbsMb: null, spillMb: null };
|
|
16902
16954
|
}
|
|
16903
16955
|
const outcome = await this.awaitReady(testDeadline);
|
|
16904
16956
|
let vramAbsMb = null;
|
|
16957
|
+
let spill = null;
|
|
16905
16958
|
if (outcome === "ok") {
|
|
16906
16959
|
await sleep3(800);
|
|
16907
16960
|
vramAbsMb = await readGpuVramMb(sys);
|
|
16961
|
+
spill = spillMb(sharedBefore, await readGpuSharedMb(sys));
|
|
16908
16962
|
}
|
|
16909
16963
|
await this.stopEngine();
|
|
16910
|
-
return { outcome, vramAbsMb };
|
|
16964
|
+
return { outcome, vramAbsMb, spillMb: spill };
|
|
16911
16965
|
}
|
|
16912
16966
|
/** Record a VRAM-probe trial in the candidate list (tps/prefill are null — nothing was generated;
|
|
16913
16967
|
* only the load outcome and absolute VRAM are known). */
|
|
@@ -16927,7 +16981,8 @@ var BenchRunner = class {
|
|
|
16927
16981
|
prefillTps: null,
|
|
16928
16982
|
ttftMs: null,
|
|
16929
16983
|
vramMb: null,
|
|
16930
|
-
vramAbsMb: probe2.vramAbsMb
|
|
16984
|
+
vramAbsMb: probe2.vramAbsMb,
|
|
16985
|
+
spillMb: probe2.spillMb
|
|
16931
16986
|
};
|
|
16932
16987
|
results.push(probeCand);
|
|
16933
16988
|
this.emit(`${probeCand.label} \u2192 ${probe2.outcome}${probe2.vramAbsMb != null ? ` (${probe2.vramAbsMb} MB)` : ""}`, probeCand);
|
|
@@ -16958,7 +17013,7 @@ var BenchRunner = class {
|
|
|
16958
17013
|
kvTypeK: profile.kvTypeK,
|
|
16959
17014
|
flashAttn: profile.flashAttn
|
|
16960
17015
|
};
|
|
16961
|
-
const fail = (outcome2) => ({ label, params, outcome: outcome2, tps: null, prefillTps: null, ttftMs: null, vramMb: null, vramAbsMb: null });
|
|
17016
|
+
const fail = (outcome2) => ({ label, params, outcome: outcome2, tps: null, prefillTps: null, ttftMs: null, vramMb: null, vramAbsMb: null, spillMb: null });
|
|
16962
17017
|
const phase = (p) => {
|
|
16963
17018
|
this.state = { ...this.state, step: `${stepPrefix} \u2014 ${p}` };
|
|
16964
17019
|
};
|
|
@@ -16973,6 +17028,7 @@ var BenchRunner = class {
|
|
|
16973
17028
|
extraArgs: profileToArgs(profile, entry, caps, sys.cores, sys, active.binPath)
|
|
16974
17029
|
};
|
|
16975
17030
|
const vramBefore = await readGpuVramMb(sys);
|
|
17031
|
+
const sharedBefore = await readGpuSharedMb(sys);
|
|
16976
17032
|
phase("loading model\u2026");
|
|
16977
17033
|
try {
|
|
16978
17034
|
await this.manager.start(opts);
|
|
@@ -17000,10 +17056,11 @@ var BenchRunner = class {
|
|
|
17000
17056
|
phase("measuring t/s\u2026");
|
|
17001
17057
|
const measured = await this.runChatWatched(target, benchMessages, 128, remaining(), logPath);
|
|
17002
17058
|
const vramAfter = await readGpuVramMb(sys);
|
|
17059
|
+
const sharedAfter = await readGpuSharedMb(sys);
|
|
17003
17060
|
await this.stopEngine();
|
|
17004
17061
|
if ("fault" in measured) return fail(measured.fault);
|
|
17005
17062
|
const vramMb = vramBefore !== null && vramAfter !== null ? Math.max(0, vramAfter - vramBefore) : vramAfter;
|
|
17006
|
-
return { label, params, outcome: "ok", tps: measured.tps, prefillTps: measured.prefillTps, ttftMs: measured.ttftMs, vramMb, vramAbsMb: vramAfter };
|
|
17063
|
+
return { label, params, outcome: "ok", tps: measured.tps, prefillTps: measured.prefillTps, ttftMs: measured.ttftMs, vramMb, vramAbsMb: vramAfter, spillMb: spillMb(sharedBefore, sharedAfter) };
|
|
17007
17064
|
}
|
|
17008
17065
|
/** Poll the manager state until the engine is running, the readiness window
|
|
17009
17066
|
* elapses (timeout), the process exits (crash), or an OOM line appears in the
|
|
@@ -17512,20 +17569,35 @@ function pickKvQuants(baseKv, kvTypes) {
|
|
|
17512
17569
|
for (const t of [baseKv, ...QUALITY_KV]) if (supported(t) && !out.includes(t)) out.push(t);
|
|
17513
17570
|
return out;
|
|
17514
17571
|
}
|
|
17572
|
+
function probeVerdict(probe2, budgetMb, headroomMb) {
|
|
17573
|
+
if (probe2.outcome === "oom") return { decision: "offload-more", reason: "oom" };
|
|
17574
|
+
if (isSpilling(probe2.spillMb)) {
|
|
17575
|
+
return { decision: "offload-more", reason: "spill", shortfallMb: probe2.spillMb };
|
|
17576
|
+
}
|
|
17577
|
+
if (overHeadroom(probe2.vramAbsMb, budgetMb, headroomMb)) {
|
|
17578
|
+
return { decision: "offload-more", reason: "headroom" };
|
|
17579
|
+
}
|
|
17580
|
+
if (probe2.outcome === "ok") return { decision: "fits" };
|
|
17581
|
+
return { decision: "offload-more", reason: "failed" };
|
|
17582
|
+
}
|
|
17583
|
+
var TTF_OUTPUT_TOKENS = 1e3;
|
|
17584
|
+
function ttfMs(c, outputTokens = TTF_OUTPUT_TOKENS) {
|
|
17585
|
+
if (c.ttftMs === null || c.tps === null || c.tps <= 0) return null;
|
|
17586
|
+
return c.ttftMs + outputTokens / c.tps * 1e3;
|
|
17587
|
+
}
|
|
17515
17588
|
function betterBySpeed(a, b) {
|
|
17516
|
-
const at = a
|
|
17517
|
-
const bt = b
|
|
17518
|
-
if (
|
|
17519
|
-
|
|
17520
|
-
|
|
17521
|
-
if (rel < -OUTPUT_TIE) return false;
|
|
17522
|
-
return (a.prefillTps ?? 0) > (b.prefillTps ?? 0);
|
|
17589
|
+
const at = ttfMs(a);
|
|
17590
|
+
const bt = ttfMs(b);
|
|
17591
|
+
if (at === null) return false;
|
|
17592
|
+
if (bt === null) return true;
|
|
17593
|
+
return at < bt;
|
|
17523
17594
|
}
|
|
17524
17595
|
function spillImproves(previous, candidate) {
|
|
17525
|
-
if (!candidate || candidate.outcome !== "ok"
|
|
17526
|
-
|
|
17527
|
-
|
|
17528
|
-
return
|
|
17596
|
+
if (!candidate || candidate.outcome !== "ok") return false;
|
|
17597
|
+
const next = ttfMs(candidate);
|
|
17598
|
+
const prev = ttfMs(previous);
|
|
17599
|
+
if (next === null || prev === null) return false;
|
|
17600
|
+
return next < prev;
|
|
17529
17601
|
}
|
|
17530
17602
|
function kvBytes(t) {
|
|
17531
17603
|
return KV_BYTES[t] ?? 2;
|
|
@@ -17591,6 +17663,66 @@ async function readGpuVramMb(sys) {
|
|
|
17591
17663
|
if (sys.gpus.some((g) => g.vendor === "amd")) return readRocmVramMb();
|
|
17592
17664
|
return null;
|
|
17593
17665
|
}
|
|
17666
|
+
var WDDM_SHARED_PS = "$s=(Get-Counter '\\GPU Adapter Memory(*)\\Shared Usage' -ErrorAction SilentlyContinue).CounterSamples;if(-not $s){exit 1};[math]::Round((($s|Measure-Object CookedValue -Sum).Sum)/1MB,1)";
|
|
17667
|
+
var wddmSharedUnsupported = false;
|
|
17668
|
+
function readWddmSharedMb() {
|
|
17669
|
+
if (process.platform !== "win32" || wddmSharedUnsupported) return Promise.resolve(null);
|
|
17670
|
+
return new Promise((resolve5) => {
|
|
17671
|
+
try {
|
|
17672
|
+
execFile10(
|
|
17673
|
+
"powershell",
|
|
17674
|
+
["-NoProfile", "-NonInteractive", "-Command", WDDM_SHARED_PS],
|
|
17675
|
+
{ timeout: 1e4, windowsHide: true },
|
|
17676
|
+
(err8, stdout) => {
|
|
17677
|
+
if (err8) {
|
|
17678
|
+
if (!err8.killed) wddmSharedUnsupported = true;
|
|
17679
|
+
return resolve5(null);
|
|
17680
|
+
}
|
|
17681
|
+
const mb = parseFloat((stdout || "").trim());
|
|
17682
|
+
if (!Number.isFinite(mb) || mb < 0) {
|
|
17683
|
+
wddmSharedUnsupported = true;
|
|
17684
|
+
return resolve5(null);
|
|
17685
|
+
}
|
|
17686
|
+
resolve5(Math.round(mb));
|
|
17687
|
+
}
|
|
17688
|
+
);
|
|
17689
|
+
} catch {
|
|
17690
|
+
wddmSharedUnsupported = true;
|
|
17691
|
+
resolve5(null);
|
|
17692
|
+
}
|
|
17693
|
+
});
|
|
17694
|
+
}
|
|
17695
|
+
function parseRocmGttUsed(memJson) {
|
|
17696
|
+
try {
|
|
17697
|
+
const mem = JSON.parse(memJson);
|
|
17698
|
+
let total = 0;
|
|
17699
|
+
for (const fields of Object.values(mem)) {
|
|
17700
|
+
const usedKey = Object.keys(fields).find((k) => /GTT Total Used Memory/i.test(k));
|
|
17701
|
+
total += usedKey ? parseInt(String(fields[usedKey]).trim(), 10) || 0 : 0;
|
|
17702
|
+
}
|
|
17703
|
+
return Number.isFinite(total) ? Math.round(total / 1e6) : null;
|
|
17704
|
+
} catch {
|
|
17705
|
+
return null;
|
|
17706
|
+
}
|
|
17707
|
+
}
|
|
17708
|
+
function readRocmGttMb() {
|
|
17709
|
+
return new Promise((resolve5) => {
|
|
17710
|
+
try {
|
|
17711
|
+
execFile10("rocm-smi", ["--showmeminfo", "gtt", "--json"], { timeout: 8e3, windowsHide: true }, (err8, stdout) => {
|
|
17712
|
+
if (err8 || !stdout) return resolve5(null);
|
|
17713
|
+
resolve5(parseRocmGttUsed(stdout));
|
|
17714
|
+
});
|
|
17715
|
+
} catch {
|
|
17716
|
+
resolve5(null);
|
|
17717
|
+
}
|
|
17718
|
+
});
|
|
17719
|
+
}
|
|
17720
|
+
async function readGpuSharedMb(sys) {
|
|
17721
|
+
const win = await readWddmSharedMb();
|
|
17722
|
+
if (win !== null) return win;
|
|
17723
|
+
if (sys.gpus.some((g) => g.vendor === "amd")) return readRocmGttMb();
|
|
17724
|
+
return null;
|
|
17725
|
+
}
|
|
17594
17726
|
function sleep3(ms) {
|
|
17595
17727
|
return new Promise((r) => setTimeout(r, ms));
|
|
17596
17728
|
}
|
|
@@ -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-CRd__4R1.js";import{f as V}from"./chat-api-BTcC6kED.js";import{f as X,a as Z}from"./agent-api-CpgzOfg0.js";import{P as B}from"./personas-B0p0BX69.js";import{C as ee}from"./chevron-left-BVxkM758.js";import{R as te}from"./rotate-ccw-gR3mMTRM.js";import{T as se}from"./trash-2-DZYSgl2R.js";import{C as ne}from"./chevron-right-BJZRbTUj.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 ve(){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{ve 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-C3DcPrhr.js";import{f as V}from"./chat-api-D7WunS4X.js";import{f as X,a as Z}from"./agent-api-Dsb2M3gT.js";import{P as B}from"./personas-DLa9ZPoi.js";import{C as ee}from"./chevron-left-DqcpOb9h.js";import{R as te}from"./rotate-ccw-CDrolPd6.js";import{T as se}from"./trash-2-BNqXKVdk.js";import{C as ne}from"./chevron-right-D7i8peZR.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 ve(){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{ve as AgentEditPage};
|