turbollm 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/cli.js +39 -36
- package/dist/webdist/assets/{AgentsScreen-C8ijrgPm.js → AgentsScreen-oDn4ZkM1.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-BLAaAAkO.js → ChatScreen-CX4ra3WN.js} +37 -30
- package/dist/webdist/assets/{CustomizeScreen-BvwLXcaF.js → CustomizeScreen-uhKz3ulx.js} +1 -1
- package/dist/webdist/assets/{DeveloperScreen-Cf_BjtjZ.js → DeveloperScreen-C2117jSw.js} +1 -1
- package/dist/webdist/assets/{EnginesScreen-C-ny7PFc.js → EnginesScreen-Dl1lF8qJ.js} +3 -3
- package/dist/webdist/assets/ModelDetailDialog-Da2p6itL.js +1 -0
- package/dist/webdist/assets/{ModelDirs-V6R_2wmI.js → ModelDirs-iqZFpRga.js} +1 -1
- package/dist/webdist/assets/ModelsScreen-BsS0TO6W.js +1 -0
- package/dist/webdist/assets/SettingsScreen-QwzKX1gb.js +1 -0
- package/dist/webdist/assets/{arc-C-BB3uXs.js → arc-BPL4VCUo.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-3BPJPVTR-CcJ0ZOqZ.js → architectureDiagram-3BPJPVTR-V8Zd2JHr.js} +1 -1
- package/dist/webdist/assets/{blockDiagram-GPEHLZMM-ALJWfOwg.js → blockDiagram-GPEHLZMM-C6pGJDrs.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-AAUBKEIU-BaIxyDOO.js → c4Diagram-AAUBKEIU-_hXk5ziz.js} +1 -1
- package/dist/webdist/assets/channel-YTLuIsBj.js +1 -0
- package/dist/webdist/assets/check-BwuGRwaM.js +1 -0
- package/dist/webdist/assets/{chunk-2J33WTMH-EWXF5El7.js → chunk-2J33WTMH-CGL1puVz.js} +1 -1
- package/dist/webdist/assets/{chunk-4BX2VUAB-B01XIIl5.js → chunk-4BX2VUAB-DrYe7x90.js} +1 -1
- package/dist/webdist/assets/{chunk-55IACEB6-CAORK4LB.js → chunk-55IACEB6-CGuQ4vHT.js} +1 -1
- package/dist/webdist/assets/{chunk-727SXJPM-Bow98gCW.js → chunk-727SXJPM-B8Wrrhxb.js} +1 -1
- package/dist/webdist/assets/{chunk-AQP2D5EJ-D3ihkUfL.js → chunk-AQP2D5EJ-BbTLSwHS.js} +1 -1
- package/dist/webdist/assets/{chunk-FMBD7UC4-B3pZV5W8.js → chunk-FMBD7UC4-CRaaHdZE.js} +1 -1
- package/dist/webdist/assets/{chunk-ND2GUHAM-Bpfzzi3w.js → chunk-ND2GUHAM-EDheV6SO.js} +1 -1
- package/dist/webdist/assets/{chunk-QZHKN3VN-BAr49pW1.js → chunk-QZHKN3VN-TQwy40rm.js} +1 -1
- package/dist/webdist/assets/{circle-check-Bxq6YJMS.js → circle-check-DW1zSzW1.js} +1 -1
- package/dist/webdist/assets/{circle-x-DEBqweG-.js → circle-x-BVCygJX_.js} +1 -1
- package/dist/webdist/assets/classDiagram-4FO5ZUOK-CK-He-ZA.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-CK-He-ZA.js +1 -0
- package/dist/webdist/assets/{common-BSLr1MvR.js → common-BajDwLu1.js} +1 -1
- package/dist/webdist/assets/{copy-button-SltJUQtH.js → copy-button-CcOL_21W.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-S5V4N54A-BEX523vE.js → cose-bilkent-S5V4N54A-BDrO96pv.js} +1 -1
- package/dist/webdist/assets/{dagre-BM42HDAG-De5xizkB.js → dagre-BM42HDAG-CPU31zPQ.js} +1 -1
- package/dist/webdist/assets/{diagram-2AECGRRQ-Dlcd7uUE.js → diagram-2AECGRRQ-Bx8fkRjV.js} +1 -1
- package/dist/webdist/assets/{diagram-5GNKFQAL-CflK9di5.js → diagram-5GNKFQAL-BBYjy9Zt.js} +1 -1
- package/dist/webdist/assets/{diagram-KO2AKTUF-Fbl7G2bU.js → diagram-KO2AKTUF-Dos-X-ZR.js} +1 -1
- package/dist/webdist/assets/{diagram-LMA3HP47-BC3FH92a.js → diagram-LMA3HP47-wkj6OULt.js} +1 -1
- package/dist/webdist/assets/{diagram-OG6HWLK6-DkL3gfhn.js → diagram-OG6HWLK6-CmYjdk0L.js} +1 -1
- package/dist/webdist/assets/{dialog-D1-Zlj1l.js → dialog-hJPYu2Ov.js} +1 -1
- package/dist/webdist/assets/{erDiagram-TEJ5UH35-DGD3ClXg.js → erDiagram-TEJ5UH35-CsbNDTPD.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-I6XJVG4X-CHzMVGFr.js → flowDiagram-I6XJVG4X-BsFFxJiw.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-6RSMTGT7-CAB-ravM.js → ganttDiagram-6RSMTGT7-U9sAiXNQ.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-PVQCEYII-DmhgBW8a.js → gitGraphDiagram-PVQCEYII-CxJIMHUV.js} +1 -1
- package/dist/webdist/assets/index-B52Brf0-.css +1 -0
- package/dist/webdist/assets/{index-B7LTDUDR.js → index-Cj_l2rh0.js} +3 -3
- package/dist/webdist/assets/{infoDiagram-5YYISTIA-BswUlelU.js → infoDiagram-5YYISTIA-D4lI1s8i.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-YF4QCWOH-DZENhuS5.js → ishikawaDiagram-YF4QCWOH-D4mglNig.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-JHISSGLW-D4BKn3fd.js → journeyDiagram-JHISSGLW-CdEi7F6r.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-UN3LZRKU-C4uVyQVS.js → kanban-definition-UN3LZRKU-DVLhy_z6.js} +1 -1
- package/dist/webdist/assets/{linear-BwE47XoP.js → linear-d5BrNoO6.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-DdEuSeXx.js → mermaid.core-fgLyIScK.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-RKZ34NQL-DxPkmqjP.js → mindmap-definition-RKZ34NQL-D8Ucx5YR.js} +1 -1
- package/dist/webdist/assets/{pencil-BavbRBL9.js → pencil-IA-fj275.js} +1 -1
- package/dist/webdist/assets/personas-fLJwmnEe.js +278 -0
- package/dist/webdist/assets/{pieDiagram-4H26LBE5-CUdk_VXR.js → pieDiagram-4H26LBE5-BBnuZwji.js} +1 -1
- package/dist/webdist/assets/{plus-BEY4GU1K.js → plus-Ct3egKtH.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-W4KKPZXB-MT8mFTQj.js → quadrantDiagram-W4KKPZXB-5_Ip_nW9.js} +1 -1
- package/dist/webdist/assets/{radix-DX0vbZxT.js → radix-4XwKfE88.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-B2qwQZOz.js → refresh-cw-BBcxwtP-.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-4Y6WPE33-C5lcbiaL.js → requirementDiagram-4Y6WPE33-XC0l0R7d.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-5OEKKPKP-gCtNl8Ay.js → sankeyDiagram-5OEKKPKP-DJ-RNVjW.js} +1 -1
- package/dist/webdist/assets/{save-B5yXIJpT.js → save-BhQrytFt.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-3UESZ5HK-CZm2Qqlo.js → sequenceDiagram-3UESZ5HK-CNvMsl4g.js} +1 -1
- package/dist/webdist/assets/skeleton-CW1R2F_M.js +1 -0
- package/dist/webdist/assets/{stateDiagram-AJRCARHV-BBf-D1_B.js → stateDiagram-AJRCARHV-CN9hLd2j.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-CQwepdnn.js +1 -0
- package/dist/webdist/assets/{timeline-definition-PNZ67QCA-pZHclsB5.js → timeline-definition-PNZ67QCA-D64WOfwg.js} +1 -1
- package/dist/webdist/assets/{trash-2-BOk5wJqV.js → trash-2-BY2m3pE3.js} +1 -1
- package/dist/webdist/assets/{vendor-Bhj2wMgn.js → vendor-CKtmMAvG.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-CIIHVFJN-D0G0bNDg.js → vennDiagram-CIIHVFJN-FYpgKg2e.js} +1 -1
- package/dist/webdist/assets/{wardley-L42UT6IY-CVfbre9P.js → wardley-L42UT6IY-B4qclGl3.js} +1 -1
- package/dist/webdist/assets/{wardleyDiagram-YWT4CUSO-DpJ-M6Rq.js → wardleyDiagram-YWT4CUSO-CdYxwShW.js} +1 -1
- package/dist/webdist/assets/{wrench-B_UtGGtF.js → wrench-_vB8fZmT.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-2RQKCTM6-D1Ye9Jsh.js → xychartDiagram-2RQKCTM6-bI3ZqIAG.js} +1 -1
- package/dist/webdist/index.html +4 -4
- package/package.json +1 -1
- package/dist/webdist/assets/ModelDetailDialog-64XpCDO6.js +0 -1
- package/dist/webdist/assets/ModelsScreen-D8EkblWt.js +0 -1
- package/dist/webdist/assets/SettingsScreen-khqKELRg.js +0 -1
- package/dist/webdist/assets/channel-xWwBhwfN.js +0 -1
- package/dist/webdist/assets/check-Dg0H4Og5.js +0 -1
- package/dist/webdist/assets/classDiagram-4FO5ZUOK-CWFRccJj.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-CWFRccJj.js +0 -1
- package/dist/webdist/assets/index-DnCwNfT4.css +0 -1
- package/dist/webdist/assets/personas-uLVxW5Bm.js +0 -77
- package/dist/webdist/assets/skeleton-CrqR3g7t.js +0 -1
- package/dist/webdist/assets/sparkles-DlKKkTEa.js +0 -1
- package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-DG-bUrT1.js +0 -1
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
<img src="https://img.shields.io/badge/node-%E2%89%A522-3c873a.svg" alt="node >= 22" />
|
|
18
18
|
<img src="https://img.shields.io/badge/license-FSL--1.1--ALv2-blue.svg" alt="license" />
|
|
19
19
|
<img src="https://img.shields.io/badge/platform-Windows%20%C2%B7%20macOS%20%C2%B7%20Linux-555.svg" alt="platforms" />
|
|
20
|
+
<a href="https://ko-fi.com/mohitsoni"><img src="https://img.shields.io/badge/Ko--fi-support%20us-FF5E5B?logo=kofi&logoColor=white" alt="Ko-fi" /></a>
|
|
21
|
+
<a href="https://discord.gg/v6kRbV7nC"><img src="https://img.shields.io/badge/Discord-join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord" /></a>
|
|
20
22
|
</p>
|
|
21
23
|
|
|
22
24
|
<!-- Brand: shipped app icon web/public/brand/turbollm-icon-512.jpeg · high-res masters web/brand-assets/ (unshipped) · in-app mark web/src/components/Logo.tsx · favicon web/public/favicon.svg -->
|
|
@@ -51,6 +53,7 @@ LLMs** — built for people who today hand-compile forks and hunt forums for the
|
|
|
51
53
|
- [How TurboLLM compares](#how-turbollm-compares)
|
|
52
54
|
- [Troubleshooting](#troubleshooting)
|
|
53
55
|
- [Develop from source](#develop-from-source)
|
|
56
|
+
- [Community](#community)
|
|
54
57
|
- [License](#license)
|
|
55
58
|
|
|
56
59
|
---
|
|
@@ -482,6 +485,12 @@ shadcn/ui frontend. One TypeScript codebase, shipped as an npm package.
|
|
|
482
485
|
|
|
483
486
|
---
|
|
484
487
|
|
|
488
|
+
## Community
|
|
489
|
+
|
|
490
|
+
Questions, ideas, and show-and-tell — join the [Discord](https://discord.gg/v6kRbV7nC).
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
485
494
|
## License
|
|
486
495
|
|
|
487
496
|
Source-available under the **Functional Source License 1.1 (Apache-2.0 future grant)** — SPDX
|
package/dist/cli.js
CHANGED
|
@@ -4767,6 +4767,9 @@ var BenchRunner = class {
|
|
|
4767
4767
|
// stop/restart/load (kill switches) interrupts auto-tune immediately rather than
|
|
4768
4768
|
// waiting out the current candidate's request.
|
|
4769
4769
|
abort = null;
|
|
4770
|
+
runLog = [];
|
|
4771
|
+
runLogMeta = null;
|
|
4772
|
+
logWinner = null;
|
|
4770
4773
|
// The finished run's winning candidate, held (not persisted) until the user clicks Save.
|
|
4771
4774
|
winning = null;
|
|
4772
4775
|
/** Live state for GET /status. */
|
|
@@ -4805,6 +4808,24 @@ var BenchRunner = class {
|
|
|
4805
4808
|
const deadline = Date.now() + timeoutMs;
|
|
4806
4809
|
while (this.state.running && Date.now() < deadline) await sleep2(150);
|
|
4807
4810
|
}
|
|
4811
|
+
getLog() {
|
|
4812
|
+
if (!this.runLogMeta) return null;
|
|
4813
|
+
const { modelKey, startedAt: startedAt2, sys } = this.runLogMeta;
|
|
4814
|
+
return {
|
|
4815
|
+
modelKey,
|
|
4816
|
+
startedAt: startedAt2,
|
|
4817
|
+
hardware: {
|
|
4818
|
+
gpus: sys.gpus.map((g) => ({ name: g.name, vramMb: g.vramMb })),
|
|
4819
|
+
ramMb: sys.ramMB,
|
|
4820
|
+
os: sys.os
|
|
4821
|
+
},
|
|
4822
|
+
entries: [...this.runLog],
|
|
4823
|
+
winner: this.logWinner
|
|
4824
|
+
};
|
|
4825
|
+
}
|
|
4826
|
+
emit(step, candidate) {
|
|
4827
|
+
this.runLog.push({ ts: (/* @__PURE__ */ new Date()).toISOString(), step, ...candidate ? { candidate } : {} });
|
|
4828
|
+
}
|
|
4808
4829
|
/** Start a run for `modelKey`. Rejects (throws BenchError) when a run is already
|
|
4809
4830
|
* active, the engine is busy, or the model isn't a benchmarkable GGUF. The run
|
|
4810
4831
|
* itself proceeds in the background; callers get 202 + poll /status. */
|
|
@@ -4826,6 +4847,9 @@ var BenchRunner = class {
|
|
|
4826
4847
|
this.cancelled = false;
|
|
4827
4848
|
this.abort = new AbortController();
|
|
4828
4849
|
this.winning = null;
|
|
4850
|
+
this.runLog = [];
|
|
4851
|
+
this.runLogMeta = null;
|
|
4852
|
+
this.logWinner = null;
|
|
4829
4853
|
this.deadline = Date.now() + TOTAL_BUDGET_MS;
|
|
4830
4854
|
this.state = { running: true, modelKey, step: "Preparing\u2026", candidates: [] };
|
|
4831
4855
|
void this.run(modelKey, entry, base2).catch((e) => {
|
|
@@ -4837,6 +4861,7 @@ var BenchRunner = class {
|
|
|
4837
4861
|
// ---- the run ------------------------------------------------------------
|
|
4838
4862
|
async run(modelKey, entry, base2) {
|
|
4839
4863
|
const sys = getSysInfo();
|
|
4864
|
+
this.runLogMeta = { modelKey, startedAt: (/* @__PURE__ */ new Date()).toISOString(), sys };
|
|
4840
4865
|
const active = this.registry.active();
|
|
4841
4866
|
const caps = active?.capabilities ?? { flags: [], kvTypes: [] };
|
|
4842
4867
|
const saved = this.store.snapshot().modelProfiles[modelKey];
|
|
@@ -4852,6 +4877,7 @@ var BenchRunner = class {
|
|
|
4852
4877
|
kvToTune = decideKvToBench(spread, kvCandidates);
|
|
4853
4878
|
const swing = spread < 0 ? "unknown" : spread >= Number.MAX_SAFE_INTEGER ? "huge" : `${Math.round(spread)} MB`;
|
|
4854
4879
|
this.state = { ...this.state, step: `KV cache swing ${swing} \u2192 tuning ${kvToTune.join(" + ")}`, candidates: results };
|
|
4880
|
+
this.emit(`KV spread ${swing} \u2192 tuning ${kvToTune.join(" + ")}`);
|
|
4855
4881
|
}
|
|
4856
4882
|
for (let i = 0; i < kvToTune.length && !this.cancelled && Date.now() <= this.deadline; i++) {
|
|
4857
4883
|
const kv = kvToTune[i];
|
|
@@ -4875,6 +4901,7 @@ var BenchRunner = class {
|
|
|
4875
4901
|
}
|
|
4876
4902
|
const profile = recommended && hasAnySampling(recommended) ? { ...best.profile, sampling: { ...best.profile.sampling, ...recommended } } : best.profile;
|
|
4877
4903
|
this.winning = { modelKey, profile, cand: best.cand, entry, sys, engineVersion: active?.version ?? "" };
|
|
4904
|
+
this.logWinner = { params: best.cand.params, tps: best.cand.tps ?? 0, prefillTps: best.cand.prefillTps, ttftMs: best.cand.ttftMs ?? 0, vramMb: best.cand.vramMb };
|
|
4878
4905
|
this.state = {
|
|
4879
4906
|
running: false,
|
|
4880
4907
|
modelKey,
|
|
@@ -5021,7 +5048,7 @@ var BenchRunner = class {
|
|
|
5021
5048
|
/** Record a VRAM-probe trial in the candidate list (tps/prefill are null — nothing was generated;
|
|
5022
5049
|
* only the load outcome and absolute VRAM are known). */
|
|
5023
5050
|
pushProbe(results, base2, knob, value, probe2) {
|
|
5024
|
-
|
|
5051
|
+
const probeCand = {
|
|
5025
5052
|
label: `probe ${knob}=${value}`,
|
|
5026
5053
|
params: {
|
|
5027
5054
|
ctx: base2.ctx,
|
|
@@ -5037,7 +5064,9 @@ var BenchRunner = class {
|
|
|
5037
5064
|
ttftMs: null,
|
|
5038
5065
|
vramMb: null,
|
|
5039
5066
|
vramAbsMb: probe2.vramAbsMb
|
|
5040
|
-
}
|
|
5067
|
+
};
|
|
5068
|
+
results.push(probeCand);
|
|
5069
|
+
this.emit(`${probeCand.label} \u2192 ${probe2.outcome}${probe2.vramAbsMb != null ? ` (${probe2.vramAbsMb} MB)` : ""}`, probeCand);
|
|
5041
5070
|
this.state = { ...this.state, candidates: results };
|
|
5042
5071
|
}
|
|
5043
5072
|
/** Phase 2: the single full prefill + t/s benchmark, at the offload the VRAM probe chose. Pushes
|
|
@@ -5046,6 +5075,7 @@ var BenchRunner = class {
|
|
|
5046
5075
|
this.state = { ...this.state, step: `KV ${profile.kvTypeK}: measuring best (${label})\u2026`, candidates: results };
|
|
5047
5076
|
const cand = await this.measure(entry, sys, profile, caps, label, `Measuring ${label}`);
|
|
5048
5077
|
results.push(cand);
|
|
5078
|
+
this.emit(`bench ${label} \u2192 ${cand.outcome}${cand.tps != null ? ` (${cand.tps.toFixed(1)} tok/s)` : ""}`, cand);
|
|
5049
5079
|
this.state = { ...this.state, candidates: results, bestTps: cand.tps ?? this.state.bestTps };
|
|
5050
5080
|
await this.settleGpu();
|
|
5051
5081
|
return cand.outcome === "ok" && cand.tps !== null ? { cand, profile } : null;
|
|
@@ -8021,30 +8051,6 @@ function abortAllInFlightChats() {
|
|
|
8021
8051
|
inflight.clear();
|
|
8022
8052
|
return n;
|
|
8023
8053
|
}
|
|
8024
|
-
var EXPERT_SYSTEM_PROMPT = `You are the TurboLLM in-app expert assistant \u2014 a knowledgeable, friendly guide built into TurboLLM, a local-first desktop app for running large language models on the user's own machine.
|
|
8025
|
-
|
|
8026
|
-
Your job is to help the user get the most out of TurboLLM:
|
|
8027
|
-
- Explain what TurboLLM features do and how to use them: chatting with local models, the Models screen (discover, download, load, and tune models), the Engines screen (install and manage inference backends like llama.cpp), and Settings (idle timeout, model defaults such as context length and GPU layers, auto-load, theme, network/LAN exposure, and privacy/telemetry).
|
|
8028
|
-
- Help the user configure things: picking and loading a model, adjusting sampling (temperature, top-p, top-k, min-p), setting context length and GPU offload, and managing per-thread system prompts and sampling overrides.
|
|
8029
|
-
- Troubleshoot common problems: a model that won't load, slow generation, running out of context, missing or failed engine installs, and GPU/CPU offload questions. Reason from the symptoms the user describes and the hardware they mention.
|
|
8030
|
-
|
|
8031
|
-
Guidelines:
|
|
8032
|
-
- Keep answers practical, concise, and actionable. Prefer concrete steps ("Open the Models screen, click \u2026") over abstract advice.
|
|
8033
|
-
- When something depends on the user's hardware or which model is loaded, say so and ask a brief clarifying question if needed.
|
|
8034
|
-
- Everything runs locally and offline; never suggest sending the user's data to external services.
|
|
8035
|
-
- If you are unsure or a feature may not exist, say so honestly rather than inventing details.`;
|
|
8036
|
-
function buildExpertPrompt() {
|
|
8037
|
-
const sys = getSysInfo();
|
|
8038
|
-
const ramGb = Math.round(sys.ramMB / 1024);
|
|
8039
|
-
const gpuLines = sys.gpus.length ? sys.gpus.map((g) => `- GPU: ${g.name}${g.vramMb ? ` (${Math.round(g.vramMb / 1024)} GB VRAM)` : ""}`).join("\n") : "- GPU: none detected";
|
|
8040
|
-
const hw = [
|
|
8041
|
-
"\n\n## User's hardware",
|
|
8042
|
-
`- CPU: ${sys.cpu}${sys.cores ? ` (${sys.cores} cores)` : ""}`,
|
|
8043
|
-
`- RAM: ${ramGb} GB`,
|
|
8044
|
-
gpuLines
|
|
8045
|
-
].join("\n");
|
|
8046
|
-
return EXPERT_SYSTEM_PROMPT + hw;
|
|
8047
|
-
}
|
|
8048
8054
|
function err(c, s, code, msg2) {
|
|
8049
8055
|
return c.json({ error: { code, message: msg2 } }, s);
|
|
8050
8056
|
}
|
|
@@ -8066,16 +8072,6 @@ function registerChatRoutes(app2, d) {
|
|
|
8066
8072
|
const conv = db2.createConversation({ title: b.title, systemPrompt: b.systemPrompt, modelKey: b.modelKey, toolPolicy: b.toolPolicy });
|
|
8067
8073
|
return c.json(conv, 201);
|
|
8068
8074
|
});
|
|
8069
|
-
app2.post("/api/v1/conversations/expert", async (c) => {
|
|
8070
|
-
const ms = d.manager.status();
|
|
8071
|
-
const conv = db2.createConversation({
|
|
8072
|
-
title: "TurboLLM Expert",
|
|
8073
|
-
systemPrompt: buildExpertPrompt(),
|
|
8074
|
-
modelKey: ms.model?.key ?? "",
|
|
8075
|
-
expertMode: true
|
|
8076
|
-
});
|
|
8077
|
-
return c.json(conv, 201);
|
|
8078
|
-
});
|
|
8079
8075
|
app2.get("/api/v1/conversations/:id", (c) => {
|
|
8080
8076
|
const conv = db2.getConversation(c.req.param("id"), true);
|
|
8081
8077
|
if (!conv) return err(c, 404, "not_found", "Conversation not found.");
|
|
@@ -10650,6 +10646,13 @@ function registerApi(app2, d) {
|
|
|
10650
10646
|
if (!saved) return err2(c, 409, "no_bench_result", "No auto-tune result to save.");
|
|
10651
10647
|
return c.json({ ok: true });
|
|
10652
10648
|
});
|
|
10649
|
+
app2.get("/api/v1/bench/log", (c) => {
|
|
10650
|
+
const log = d.bench.getLog();
|
|
10651
|
+
if (!log) return err2(c, 404, "no_bench_log", "No auto-tune log available.");
|
|
10652
|
+
const slug = log.modelKey.replace(/[^a-z0-9]/gi, "-").replace(/-+/g, "-").slice(0, 60);
|
|
10653
|
+
c.header("Content-Disposition", `attachment; filename="autotune-${slug}-${log.startedAt.slice(0, 10)}.json"`);
|
|
10654
|
+
return c.json(log);
|
|
10655
|
+
});
|
|
10653
10656
|
app2.get("/api/v1/models", (c) => {
|
|
10654
10657
|
const { models, scanning, lastScanAt } = d.scanner.list();
|
|
10655
10658
|
const lastTps = d.db.lastGenTpsByModel();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./radix-
|
|
1
|
+
import{j as e}from"./radix-4XwKfE88.js";import{r as u}from"./vendor-CKtmMAvG.js";import{c as w,d as k,A as T,e as v,L as h,f as S,b,g as C,h as q,X as A}from"./index-Cj_l2rh0.js";import{P as N}from"./plus-Ct3egKtH.js";import{C as y}from"./circle-x-BVCygJX_.js";import{C as O}from"./circle-check-DW1zSzW1.js";import{W as E}from"./wrench-_vB8fZmT.js";const _=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}]],D=w("circle-dot",_);const L=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 6v6l4 2",key:"mmk7yg"}]],P=w("clock",L),p={all:["agent-runs"],list:()=>[...p.all,"list"],detail:t=>[...p.all,"detail",t]};async function g(t,a){const l={Accept:"application/json",...k(),...a?.headers??{}},r=await fetch(t,{...a,headers:l});if(r.status===204)return;const i=await r.text(),o=i?JSON.parse(i):void 0;if(!r.ok){const d=o;throw new T(d?.error?.code??"http_error",d?.error?.message??`Request failed with status ${r.status}.`,r.status)}return o}async function $(){return g("/api/v1/agents/runs")}async function I(t){return g(`/api/v1/agents/runs/${t}`)}async function Q(t){return g("/api/v1/agents/runs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}async function K(t){await g(`/api/v1/agents/runs/${t}`,{method:"DELETE"})}async function*F(t,a=0,l){const r=`/api/v1/agents/runs/${t}/stream?fromSeq=${a}`,i=await fetch(r,{headers:{Accept:"text/event-stream",...k()},signal:l});if(!i.ok||!i.body)throw new Error(`Stream error: ${i.status}`);const o=i.body.getReader(),d=new TextDecoder;let m="";try{for(;;){const{done:s,value:x}=await o.read();if(s)break;m+=d.decode(x,{stream:!0});const c=m.split(`
|
|
2
2
|
`);m=c.pop()??"";let n="message";for(const f of c){if(f.startsWith("event: ")){n=f.slice(7).trim();continue}if(f.startsWith("data: ")){const j=f.slice(6).trim();if(j==="[DONE]")return;try{const R=JSON.parse(j);if(yield{event:n,data:R},n==="done"||n==="error")return}catch{}n="message"}}}}finally{o.cancel()}}const J={queued:e.jsx(P,{size:12}),running:e.jsx(h,{size:12,className:"animate-spin"}),done:e.jsx(O,{size:12}),failed:e.jsx(y,{size:12}),cancelled:e.jsx(y,{size:12}),interrupted:e.jsx(y,{size:12})},M={queued:"text-muted",running:"text-accent",done:"text-green-500",failed:"text-red-500",cancelled:"text-muted",interrupted:"text-orange-500"};function z({status:t}){return e.jsxs("span",{className:b("flex items-center gap-1 text-[11px] capitalize",M[t]),children:[J[t],t]})}function W(t){const a=Date.now()-new Date(t).getTime();return a<6e4?"just now":a<36e5?`${Math.floor(a/6e4)}m ago`:a<864e5?`${Math.floor(a/36e5)}h ago`:new Date(t).toLocaleDateString()}const U=[{id:"web_search",label:"Web search",hint:"Search the web (needs a provider configured in Settings)"},{id:"fetch_url",label:"Fetch URL",hint:"Read the contents of a web page"},{id:"run_code",label:"Run code",hint:"Execute JS in a sandbox — no mid-run confirmation, opt in only if you trust the task"}];function B({onClose:t,onCreated:a}){const[l,r]=u.useState(""),[i,o]=u.useState(""),[d,m]=u.useState({web_search:!0,fetch_url:!0,run_code:!1}),s=C(),x=n=>m(f=>({...f,[n]:!f[n]})),c=q({mutationFn:()=>Q({title:l.slice(0,60)||"Agent run",systemPrompt:i||void 0,userMessage:l,allowedTools:Object.entries(d).filter(([,n])=>n).map(([n])=>n)}),onSuccess:n=>{s.invalidateQueries({queryKey:p.list()}),a(n.id),t()}});return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40",onClick:t,children:e.jsxs("div",{className:"w-full max-w-lg rounded-xl border border-border bg-panel p-5 shadow-xl",onClick:n=>n.stopPropagation(),children:[e.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[e.jsx("h2",{className:"text-[15px] font-semibold",children:"New agent run"}),e.jsx("button",{type:"button",onClick:t,className:"text-faint hover:text-ink",children:e.jsx(A,{size:16})})]}),e.jsx("label",{className:"mb-1 block text-[12px] text-muted",children:"Task"}),e.jsx("textarea",{autoFocus:!0,value:l,onChange:n=>r(n.target.value),placeholder:"Describe what the agent should do…",rows:4,className:"mb-3 w-full resize-none rounded-lg border border-border bg-input px-3 py-2 text-[13px] text-ink placeholder:text-faint focus:border-accent focus:outline-none"}),e.jsxs("label",{className:"mb-1 block text-[12px] text-muted",children:["System prompt ",e.jsx("span",{className:"text-faint",children:"(optional)"})]}),e.jsx("textarea",{value:i,onChange:n=>o(n.target.value),placeholder:"You are a helpful assistant…",rows:2,className:"mb-4 w-full resize-none rounded-lg border border-border bg-input px-3 py-2 text-[13px] text-ink placeholder:text-faint focus:border-accent focus:outline-none"}),e.jsx("label",{className:"mb-1.5 block text-[12px] text-muted",children:"Tools"}),e.jsx("div",{className:"mb-4 space-y-1.5",children:U.map(n=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 rounded-lg border border-border px-2.5 py-2 hover:bg-panel-2",children:[e.jsx("input",{type:"checkbox",checked:d[n.id],onChange:()=>x(n.id),className:"mt-0.5 accent-[var(--accent)]"}),e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block text-[13px] font-medium text-ink",children:n.label}),e.jsx("span",{className:"block text-[11px] leading-snug text-faint",children:n.hint})]})]},n.id))}),e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:t,className:"rounded-lg px-3 py-1.5 text-[13px] text-muted hover:text-ink",children:"Cancel"}),e.jsxs("button",{type:"button",disabled:!l.trim()||c.isPending,onClick:()=>c.mutate(),className:"flex items-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-[13px] font-medium text-white disabled:opacity-50",children:[c.isPending?e.jsx(h,{size:13,className:"animate-spin"}):e.jsx(S,{size:13}),"Run agent"]})]}),c.isError&&e.jsx("p",{className:"mt-2 text-[12px]",style:{color:"var(--err)"},children:c.error.message})]})})}function X({call:t}){const[a,l]=u.useState(!1),r=typeof t.args?.query=="string"?t.args.query:typeof t.args?.url=="string"?t.args.url:JSON.stringify(t.args??{});return e.jsxs("div",{className:"w-full max-w-[85%] rounded-lg border border-border bg-panel px-2.5 py-1.5 text-[12px]",children:[e.jsxs("button",{type:"button",onClick:()=>l(i=>!i),className:"flex w-full items-center gap-1.5 text-left text-muted hover:text-ink",children:[e.jsx(E,{size:12,className:"shrink-0 text-accent"}),e.jsx("span",{className:"font-medium text-ink",children:t.name}),e.jsx("span",{className:"truncate text-faint",children:r})]}),a&&e.jsx("pre",{className:"mt-1.5 max-h-48 overflow-auto whitespace-pre-wrap break-words rounded bg-panel-2 p-2 text-[11px] text-muted",children:t.result})]})}function H({run:t}){const a=C(),l=u.useRef(null),[r,i]=u.useState(""),o=u.useRef(null),d=q({mutationFn:()=>K(t.id),onSuccess:()=>{a.invalidateQueries({queryKey:p.list()})}});u.useEffect(()=>{if(t.status!=="running"&&t.status!=="queued")return;const s=new AbortController;l.current=s;let x="";return(async()=>{try{for await(const c of F(t.id,0,s.signal))if(c.event==="delta")x+=c.data.delta,i(x);else if(c.event==="done"||c.event==="error"){a.invalidateQueries({queryKey:p.detail(t.id)}),a.invalidateQueries({queryKey:p.list()});break}}catch{}})(),()=>{s.abort(),l.current=null}},[t.id,t.status,a]),u.useEffect(()=>{o.current?.scrollIntoView({behavior:"smooth"})},[r,t.messages?.length]);const m=t.messages??[];return e.jsxs("div",{className:"flex h-full flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-border px-4 py-2.5",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[14px] font-medium text-ink",children:t.title}),e.jsx(z,{status:t.status})]}),(t.status==="running"||t.status==="queued")&&e.jsx("button",{type:"button",onClick:()=>d.mutate(),className:"rounded-lg border border-border px-3 py-1 text-[12px] text-muted transition-colors hover:border-red-400 hover:text-red-500",children:d.isPending?e.jsx(h,{size:12,className:"inline animate-spin"}):"Cancel"})]}),e.jsxs("div",{className:"flex-1 space-y-3 overflow-y-auto p-4",children:[m.map(s=>e.jsxs("div",{className:b("flex flex-col gap-1.5",s.role==="user"?"items-end":"items-start"),children:[s.toolCalls?.map(x=>e.jsx(X,{call:x},x.id)),(s.content||s.role==="user"||t.status==="running")&&e.jsx("div",{className:b("max-w-[85%] rounded-xl px-3 py-2 text-[13px] leading-relaxed",s.role==="user"?"bg-accent/15 text-ink":"bg-panel-2 text-ink"),children:e.jsx("p",{className:"whitespace-pre-wrap break-words",children:s.content||(s.role==="assistant"&&t.status==="running"?"…":"")})})]},s.id)),r&&e.jsx("div",{className:"flex gap-2",children:e.jsx("div",{className:"max-w-[85%] rounded-xl bg-panel-2 px-3 py-2 text-[13px] leading-relaxed text-ink",children:e.jsx("p",{className:"whitespace-pre-wrap break-words",children:r})})}),t.error&&e.jsxs("div",{className:"rounded-lg bg-red-500/10 px-3 py-2 text-[12px] text-red-500",children:["Error: ",t.error]}),e.jsx("div",{ref:o})]})]})}function ne(){const[t,a]=u.useState(null),[l,r]=u.useState(!1),i=v({queryKey:p.list(),queryFn:$,refetchInterval:s=>(s.state.data??[]).some(n=>n.status==="queued"||n.status==="running")?3e3:!1}),o=v({queryKey:p.detail(t??""),queryFn:()=>I(t),enabled:!!t,refetchInterval:s=>{const x=s.state.data;return x?.status==="queued"||x?.status==="running"?5e3:!1}}),d=i.data??[],m=o.data;return e.jsxs("div",{className:"flex h-full",children:[e.jsxs("div",{className:"flex w-64 shrink-0 flex-col border-r border-border",children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-border px-3 py-2.5",children:[e.jsx("span",{className:"text-[13px] font-semibold text-ink",children:"Agents"}),e.jsxs("button",{type:"button",title:"New agent run",onClick:()=>r(!0),className:"flex items-center gap-1 rounded-lg bg-accent px-2 py-1 text-[11px] font-medium text-white transition-opacity hover:opacity-90",children:[e.jsx(N,{size:11})," New"]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto",children:[i.isLoading&&e.jsx("div",{className:"flex h-20 items-center justify-center",children:e.jsx(h,{size:16,className:"animate-spin text-faint"})}),d.length===0&&!i.isLoading&&e.jsxs("div",{className:"px-4 py-8 text-center",children:[e.jsx(S,{size:28,className:"mx-auto mb-2 text-faint"}),e.jsx("p",{className:"text-[12px] text-muted",children:"No agent runs yet."}),e.jsx("p",{className:"mt-0.5 text-[11px] text-faint",children:"Click “New” to start one."})]}),d.map(s=>e.jsxs("button",{type:"button",onClick:()=>a(s.id),className:b("w-full border-b border-border px-3 py-2.5 text-left transition-colors hover:bg-panel-2",t===s.id&&"bg-panel-2"),children:[e.jsx("p",{className:"mb-0.5 truncate text-[13px] font-medium text-ink",children:s.title}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(z,{status:s.status}),e.jsx("span",{className:"text-[10px] text-faint",children:W(s.createdAt)})]})]},s.id))]})]}),e.jsx("div",{className:"flex min-w-0 flex-1 flex-col",children:t?o.isLoading?e.jsx("div",{className:"flex h-full items-center justify-center",children:e.jsx(h,{size:20,className:"animate-spin text-faint"})}):m?e.jsx(H,{run:m}):null:e.jsxs("div",{className:"flex h-full flex-col items-center justify-center text-center",children:[e.jsx(D,{size:32,className:"mb-3 text-faint"}),e.jsx("p",{className:"text-[14px] font-medium text-ink",children:"Select a run"}),e.jsx("p",{className:"mt-1 text-[12px] text-muted",children:"or create a new agent run to get started"}),e.jsxs("button",{type:"button",onClick:()=>r(!0),className:"mt-4 flex items-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-[13px] font-medium text-white hover:opacity-90",children:[e.jsx(N,{size:13})," New agent run"]})]})}),l&&e.jsx(B,{onClose:()=>r(!1),onCreated:s=>{a(s),i.refetch()}})]})}export{ne as AgentsScreen};
|