turbollm 1.5.4 → 1.6.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 +4 -2
- package/dist/cli.js +96 -77
- package/dist/webdist/assets/{AgentsScreen-8OttuI7h.js → AgentsScreen-qd7_yqju.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-CfBmxIt8.js → ChatScreen-DYeJQoLV.js} +5 -5
- package/dist/webdist/assets/CustomizeScreen-DBXBuQPm.js +4 -0
- package/dist/webdist/assets/DeveloperScreen-CCWBQQ4y.js +1 -0
- package/dist/webdist/assets/{EnginesScreen-CRI2LrjT.js → EnginesScreen-DQQLI0Qv.js} +6 -6
- package/dist/webdist/assets/{ModelDetailDialog-C4BsJs7p.js → ModelDetailDialog-C-dRTp-J.js} +1 -1
- package/dist/webdist/assets/{ModelDirs-DCeaDz1y.js → ModelDirs-E_tFMIjS.js} +1 -1
- package/dist/webdist/assets/ModelsScreen-JeCIZIdr.js +1 -0
- package/dist/webdist/assets/{SettingsScreen-CSlU6sWv.js → SettingsScreen-BFhQBO1d.js} +1 -1
- package/dist/webdist/assets/{arc-DjTUhjoA.js → arc-820YYJ1l.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-3BPJPVTR-DwDhf7SF.js → architectureDiagram-3BPJPVTR-BTSJZjgr.js} +1 -1
- package/dist/webdist/assets/arrow-left-BJXqu8NS.js +1 -0
- package/dist/webdist/assets/{blockDiagram-GPEHLZMM-Bu71X43M.js → blockDiagram-GPEHLZMM-E_gowUIA.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-AAUBKEIU-BXcC49Vg.js → c4Diagram-AAUBKEIU-DwJcumW7.js} +1 -1
- package/dist/webdist/assets/channel-6NEG4b4S.js +1 -0
- package/dist/webdist/assets/check-GYT4Bnhm.js +1 -0
- package/dist/webdist/assets/chevron-right-BTg0-ylt.js +1 -0
- package/dist/webdist/assets/{chunk-2J33WTMH-Nh_29xmy.js → chunk-2J33WTMH-DWJ9qmM_.js} +1 -1
- package/dist/webdist/assets/{chunk-4BX2VUAB-BfUMrwIP.js → chunk-4BX2VUAB-DgyEqU31.js} +1 -1
- package/dist/webdist/assets/{chunk-55IACEB6-BxCAqEO_.js → chunk-55IACEB6-CsI85v4r.js} +1 -1
- package/dist/webdist/assets/{chunk-727SXJPM-Bc6NhPVZ.js → chunk-727SXJPM-YRdSK3U3.js} +1 -1
- package/dist/webdist/assets/{chunk-AQP2D5EJ-ClNqClqF.js → chunk-AQP2D5EJ-BnTfokPI.js} +1 -1
- package/dist/webdist/assets/{chunk-FMBD7UC4-ICYO5OUp.js → chunk-FMBD7UC4-Dt8O7iM6.js} +1 -1
- package/dist/webdist/assets/{chunk-ND2GUHAM-DxZN4K23.js → chunk-ND2GUHAM-OsM9VDgQ.js} +1 -1
- package/dist/webdist/assets/{chunk-QZHKN3VN-CtQVNvJX.js → chunk-QZHKN3VN-CW3L84fX.js} +1 -1
- package/dist/webdist/assets/{circle-check-CR9l1s2L.js → circle-check-iwGQW5-3.js} +1 -1
- package/dist/webdist/assets/{circle-x-ED1-1ibi.js → circle-x-CDfcuELr.js} +1 -1
- package/dist/webdist/assets/classDiagram-4FO5ZUOK-jpAzq28n.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-jpAzq28n.js +1 -0
- package/dist/webdist/assets/{common-CaH63tS-.js → common-BstanhE0.js} +1 -1
- package/dist/webdist/assets/{copy-button-C5VRk_o-.js → copy-button-DrRexlJn.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-S5V4N54A-CORAJAXp.js → cose-bilkent-S5V4N54A-cNqjZyGk.js} +1 -1
- package/dist/webdist/assets/{dagre-BM42HDAG-BtWY5mpY.js → dagre-BM42HDAG-zr_aSu4P.js} +1 -1
- package/dist/webdist/assets/{diagram-2AECGRRQ-DsQUpPv-.js → diagram-2AECGRRQ-D8fYvWd0.js} +1 -1
- package/dist/webdist/assets/{diagram-5GNKFQAL-DgtsKEO_.js → diagram-5GNKFQAL-Cp2jBV3j.js} +1 -1
- package/dist/webdist/assets/{diagram-KO2AKTUF-CiNG347O.js → diagram-KO2AKTUF-SdWp_DPO.js} +1 -1
- package/dist/webdist/assets/{diagram-LMA3HP47-Br0x0kkW.js → diagram-LMA3HP47-DHwQz9MP.js} +1 -1
- package/dist/webdist/assets/{diagram-OG6HWLK6-aTkPDelf.js → diagram-OG6HWLK6-FGejDPqJ.js} +1 -1
- package/dist/webdist/assets/dialog-Cpwjl0SL.js +1 -0
- package/dist/webdist/assets/{erDiagram-TEJ5UH35-ByL7kkdh.js → erDiagram-TEJ5UH35-Ci0ArYoY.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-I6XJVG4X-C7jVJZbe.js → flowDiagram-I6XJVG4X-g96T9cRZ.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-6RSMTGT7-kahXGkyv.js → ganttDiagram-6RSMTGT7-CFGWWtss.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-PVQCEYII-CtKjbqTV.js → gitGraphDiagram-PVQCEYII-FFeX8xGw.js} +1 -1
- package/dist/webdist/assets/{index-DQgAgJpy.css → index-CJj8sGhF.css} +1 -1
- package/dist/webdist/assets/{index-aRpf26fA.js → index-CM4wnT7v.js} +2 -2
- package/dist/webdist/assets/{infoDiagram-5YYISTIA-KG2oeaMN.js → infoDiagram-5YYISTIA-CTuVSOzN.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-YF4QCWOH-CH0hIyAm.js → ishikawaDiagram-YF4QCWOH-BMyIM99h.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-JHISSGLW-DHcRpFXW.js → journeyDiagram-JHISSGLW-CcKLWYl8.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-UN3LZRKU-BwNZnCjT.js → kanban-definition-UN3LZRKU-CuzVk9Q_.js} +1 -1
- package/dist/webdist/assets/{linear-CFNabJkq.js → linear-DvYrxcXL.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-D_XNYY97.js → mermaid.core-DIGvaW9x.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-RKZ34NQL-5Frzs0Fa.js → mindmap-definition-RKZ34NQL-Dh_7fzN2.js} +1 -1
- package/dist/webdist/assets/{pencil-C9dBz8-u.js → pencil-veezqsms.js} +1 -1
- package/dist/webdist/assets/{personas-BRFNty6U.js → personas-DdUgL1dH.js} +3 -2
- package/dist/webdist/assets/{pieDiagram-4H26LBE5-DfjGFU8f.js → pieDiagram-4H26LBE5-G_BsYb0k.js} +1 -1
- package/dist/webdist/assets/{plus-CBiMXB28.js → plus-BLEwDzPR.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-W4KKPZXB-BVmu899Y.js → quadrantDiagram-W4KKPZXB-B1DekSy3.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-DzuecN3W.js → refresh-cw-ByeAabM7.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-4Y6WPE33-BqBVvvpq.js → requirementDiagram-4Y6WPE33-DPYkFc77.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-5OEKKPKP-ieJbgOGC.js → sankeyDiagram-5OEKKPKP-HfCQTOkK.js} +1 -1
- package/dist/webdist/assets/{save-EjedjVdP.js → save-CuyovDOw.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-3UESZ5HK-C_ciRbLo.js → sequenceDiagram-3UESZ5HK-C71xQD9L.js} +1 -1
- package/dist/webdist/assets/{skeleton-DRSPFN2X.js → skeleton-XeFkC2WF.js} +1 -1
- package/dist/webdist/assets/{stateDiagram-AJRCARHV-BdPdoXlm.js → stateDiagram-AJRCARHV-C0m1fR_s.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-C1sHKz6d.js +1 -0
- package/dist/webdist/assets/{timeline-definition-PNZ67QCA-CR9Y6hB5.js → timeline-definition-PNZ67QCA-B5SB89Kk.js} +1 -1
- package/dist/webdist/assets/{trash-2-DGDj2PvU.js → trash-2-MMGQet84.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-CIIHVFJN-DtGAe7_y.js → vennDiagram-CIIHVFJN-Bs3E_UnU.js} +1 -1
- package/dist/webdist/assets/{wardley-L42UT6IY-42TAPuTN.js → wardley-L42UT6IY-D-lZEV6Q.js} +1 -1
- package/dist/webdist/assets/{wardleyDiagram-YWT4CUSO-BGz-N75m.js → wardleyDiagram-YWT4CUSO-DIiAQmgm.js} +1 -1
- package/dist/webdist/assets/{wrench-TCdFNEP4.js → wrench-C7hemMKG.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-2RQKCTM6-st1-aHMk.js → xychartDiagram-2RQKCTM6-DViSTAkf.js} +1 -1
- package/dist/webdist/index.html +2 -2
- package/package.json +1 -1
- package/dist/webdist/assets/CustomizeScreen-B6ZmStT4.js +0 -4
- package/dist/webdist/assets/DeveloperScreen-K4D_3xic.js +0 -1
- package/dist/webdist/assets/ModelsScreen-AuNKEh06.js +0 -1
- package/dist/webdist/assets/channel-CPA4-Zpk.js +0 -1
- package/dist/webdist/assets/check-DYBCD2_I.js +0 -1
- package/dist/webdist/assets/classDiagram-4FO5ZUOK-Dkqtv6MY.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-Q7XG4LA2-Dkqtv6MY.js +0 -1
- package/dist/webdist/assets/dialog-XV4KKoeX.js +0 -1
- package/dist/webdist/assets/stateDiagram-v2-BHNVJYJU-DVgN1d61.js +0 -1
package/README.md
CHANGED
|
@@ -194,8 +194,10 @@ the detail:
|
|
|
194
194
|
- **Image input** for vision models, and **TurboLLM Expert** — a built-in assistant that knows
|
|
195
195
|
the app and your hardware for onboarding and troubleshooting without leaving the UI.
|
|
196
196
|
- **Agentic tools** — built-in `web_search` (Tavily), `fetch_url`, and sandboxed `run_code`, plus
|
|
197
|
-
**MCP
|
|
198
|
-
|
|
197
|
+
an **MCP marketplace** in Customize: one-click connect for hosted MCPs (GitHub, Linear, Stripe,
|
|
198
|
+
Atlassian, Neon, Supabase, Cloudflare, Zapier, Apify, Mixpanel) and open-source local MCPs
|
|
199
|
+
(filesystem, git, postgres, playwright, …), plus your own custom servers. Connected tools appear
|
|
200
|
+
in every chat with no restart. A **Research** persona forces multi-step web search and cites sources inline.
|
|
199
201
|
|
|
200
202
|
</details>
|
|
201
203
|
|
package/dist/cli.js
CHANGED
|
@@ -6412,7 +6412,6 @@ function execRunCode(args, requireConfirmation = false) {
|
|
|
6412
6412
|
|
|
6413
6413
|
// src/tools/mcp-client.ts
|
|
6414
6414
|
import { spawn as spawn2 } from "child_process";
|
|
6415
|
-
import { EventEmitter } from "events";
|
|
6416
6415
|
var StdioMcpClient = class {
|
|
6417
6416
|
serverId;
|
|
6418
6417
|
serverName;
|
|
@@ -6433,7 +6432,10 @@ var StdioMcpClient = class {
|
|
|
6433
6432
|
}
|
|
6434
6433
|
async connect() {
|
|
6435
6434
|
if (this.proc) return;
|
|
6436
|
-
|
|
6435
|
+
const isWin = process.platform === "win32";
|
|
6436
|
+
const file = isWin ? "cmd.exe" : this.command;
|
|
6437
|
+
const args = isWin ? ["/c", this.command, ...this.args] : this.args;
|
|
6438
|
+
this.proc = spawn2(file, args, {
|
|
6437
6439
|
env: { ...process.env, ...this.env },
|
|
6438
6440
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6439
6441
|
});
|
|
@@ -6527,70 +6529,28 @@ var SseMcpClient = class {
|
|
|
6527
6529
|
serverId;
|
|
6528
6530
|
serverName;
|
|
6529
6531
|
baseUrl;
|
|
6532
|
+
headers;
|
|
6530
6533
|
msgId = 0;
|
|
6531
|
-
|
|
6532
|
-
sseAbort = null;
|
|
6533
|
-
emitter = new EventEmitter();
|
|
6534
|
+
sessionId = null;
|
|
6534
6535
|
initialized = false;
|
|
6535
6536
|
constructor(opts) {
|
|
6536
6537
|
this.serverId = opts.id;
|
|
6537
6538
|
this.serverName = opts.name;
|
|
6538
6539
|
this.baseUrl = opts.url.replace(/\/$/, "");
|
|
6540
|
+
this.headers = opts.headers ?? {};
|
|
6539
6541
|
}
|
|
6540
6542
|
async connect() {
|
|
6541
6543
|
if (this.initialized) return;
|
|
6542
|
-
this.sseAbort = new AbortController();
|
|
6543
|
-
const endpoint = await new Promise((resolve2, reject) => {
|
|
6544
|
-
const timer = setTimeout(() => reject(new Error("SSE connect timeout")), 15e3);
|
|
6545
|
-
fetch(`${this.baseUrl}/sse`, { signal: this.sseAbort.signal }).then(async (resp) => {
|
|
6546
|
-
if (!resp.ok || !resp.body) {
|
|
6547
|
-
clearTimeout(timer);
|
|
6548
|
-
reject(new Error(`SSE connect failed: ${resp.status}`));
|
|
6549
|
-
return;
|
|
6550
|
-
}
|
|
6551
|
-
const reader = resp.body.getReader();
|
|
6552
|
-
const decoder = new TextDecoder();
|
|
6553
|
-
let buf = "";
|
|
6554
|
-
let resolved = false;
|
|
6555
|
-
while (true) {
|
|
6556
|
-
const { done, value } = await reader.read();
|
|
6557
|
-
if (done) break;
|
|
6558
|
-
buf += decoder.decode(value, { stream: true });
|
|
6559
|
-
const lines = buf.split("\n");
|
|
6560
|
-
buf = lines.pop() ?? "";
|
|
6561
|
-
for (const line of lines) {
|
|
6562
|
-
if (line.startsWith("data:")) {
|
|
6563
|
-
const data = line.slice(5).trim();
|
|
6564
|
-
if (!resolved) {
|
|
6565
|
-
resolved = true;
|
|
6566
|
-
clearTimeout(timer);
|
|
6567
|
-
resolve2(data);
|
|
6568
|
-
}
|
|
6569
|
-
try {
|
|
6570
|
-
const msg2 = JSON.parse(data);
|
|
6571
|
-
if (msg2.id != null) this.emitter.emit(`rpc:${msg2.id}`, msg2);
|
|
6572
|
-
} catch {
|
|
6573
|
-
}
|
|
6574
|
-
}
|
|
6575
|
-
}
|
|
6576
|
-
}
|
|
6577
|
-
}).catch((e) => {
|
|
6578
|
-
clearTimeout(timer);
|
|
6579
|
-
if (!this.sseAbort?.signal.aborted) reject(e);
|
|
6580
|
-
});
|
|
6581
|
-
});
|
|
6582
|
-
this.sseEndpoint = endpoint.startsWith("http") ? endpoint : `${this.baseUrl}${endpoint}`;
|
|
6583
6544
|
await this.sendRequest("initialize", {
|
|
6584
6545
|
protocolVersion: "2024-11-05",
|
|
6585
6546
|
capabilities: { tools: {} },
|
|
6586
6547
|
clientInfo: { name: "turbollm", version: "0.7.0" }
|
|
6587
6548
|
});
|
|
6588
|
-
|
|
6549
|
+
void this.postNotification({ jsonrpc: "2.0", method: "notifications/initialized", params: {} });
|
|
6589
6550
|
this.initialized = true;
|
|
6590
6551
|
}
|
|
6591
6552
|
disconnect() {
|
|
6592
|
-
this.
|
|
6593
|
-
this.sseAbort = null;
|
|
6553
|
+
this.sessionId = null;
|
|
6594
6554
|
this.initialized = false;
|
|
6595
6555
|
}
|
|
6596
6556
|
async listTools() {
|
|
@@ -6607,36 +6567,79 @@ var SseMcpClient = class {
|
|
|
6607
6567
|
async sendRequest(method, params) {
|
|
6608
6568
|
const id = ++this.msgId;
|
|
6609
6569
|
const req = { jsonrpc: "2.0", id, method, params };
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
clearTimeout(timer);
|
|
6622
|
-
reject(e);
|
|
6623
|
-
});
|
|
6570
|
+
const reqHeaders = {
|
|
6571
|
+
"Content-Type": "application/json",
|
|
6572
|
+
"Accept": "application/json, text/event-stream",
|
|
6573
|
+
...this.headers
|
|
6574
|
+
};
|
|
6575
|
+
if (this.sessionId) reqHeaders["Mcp-Session-Id"] = this.sessionId;
|
|
6576
|
+
const resp = await fetch(this.baseUrl, {
|
|
6577
|
+
method: "POST",
|
|
6578
|
+
headers: reqHeaders,
|
|
6579
|
+
body: JSON.stringify(req),
|
|
6580
|
+
signal: AbortSignal.timeout(3e4)
|
|
6624
6581
|
});
|
|
6582
|
+
if (!resp.ok) {
|
|
6583
|
+
const txt = await resp.text().catch(() => "");
|
|
6584
|
+
throw new Error(`MCP HTTP ${resp.status}: ${txt.slice(0, 200)}`);
|
|
6585
|
+
}
|
|
6586
|
+
const newSession = resp.headers.get("mcp-session-id");
|
|
6587
|
+
if (newSession) this.sessionId = newSession;
|
|
6588
|
+
const ct = resp.headers.get("content-type") ?? "";
|
|
6589
|
+
if (ct.includes("text/event-stream")) return this.readSSEResult(resp, id);
|
|
6590
|
+
const json = await resp.json();
|
|
6591
|
+
if (json.error) throw new Error(json.error.message);
|
|
6592
|
+
return json.result;
|
|
6593
|
+
}
|
|
6594
|
+
async readSSEResult(resp, targetId) {
|
|
6595
|
+
if (!resp.body) throw new Error("SSE response body is null");
|
|
6596
|
+
const reader = resp.body.getReader();
|
|
6597
|
+
const dec = new TextDecoder();
|
|
6598
|
+
let buf = "";
|
|
6599
|
+
try {
|
|
6600
|
+
while (true) {
|
|
6601
|
+
const { done, value } = await reader.read();
|
|
6602
|
+
if (done) break;
|
|
6603
|
+
buf += dec.decode(value, { stream: true });
|
|
6604
|
+
const lines = buf.split("\n");
|
|
6605
|
+
buf = lines.pop() ?? "";
|
|
6606
|
+
for (const line of lines) {
|
|
6607
|
+
if (!line.startsWith("data:")) continue;
|
|
6608
|
+
let msg2;
|
|
6609
|
+
try {
|
|
6610
|
+
msg2 = JSON.parse(line.slice(5).trim());
|
|
6611
|
+
} catch {
|
|
6612
|
+
continue;
|
|
6613
|
+
}
|
|
6614
|
+
if (msg2.id === targetId) {
|
|
6615
|
+
if (msg2.error) throw new Error(msg2.error.message);
|
|
6616
|
+
return msg2.result;
|
|
6617
|
+
}
|
|
6618
|
+
}
|
|
6619
|
+
}
|
|
6620
|
+
} finally {
|
|
6621
|
+
await reader.cancel().catch(() => {
|
|
6622
|
+
});
|
|
6623
|
+
}
|
|
6624
|
+
throw new Error(`SSE stream ended without response for id ${targetId}`);
|
|
6625
6625
|
}
|
|
6626
|
-
async
|
|
6627
|
-
const
|
|
6628
|
-
|
|
6626
|
+
async postNotification(msg2) {
|
|
6627
|
+
const headers = { "Content-Type": "application/json", ...this.headers };
|
|
6628
|
+
if (this.sessionId) headers["Mcp-Session-Id"] = this.sessionId;
|
|
6629
|
+
await fetch(this.baseUrl, {
|
|
6629
6630
|
method: "POST",
|
|
6630
|
-
headers
|
|
6631
|
+
headers,
|
|
6631
6632
|
body: JSON.stringify(msg2),
|
|
6632
6633
|
signal: AbortSignal.timeout(1e4)
|
|
6634
|
+
}).catch(() => {
|
|
6633
6635
|
});
|
|
6634
6636
|
}
|
|
6635
6637
|
};
|
|
6636
6638
|
function createMcpClient(server2) {
|
|
6637
6639
|
if (server2.transport === "sse") {
|
|
6638
6640
|
if (!server2.url) throw new Error(`MCP server "${server2.name}" has transport=sse but no url`);
|
|
6639
|
-
|
|
6641
|
+
const headers = server2.apiKey ? { Authorization: `Bearer ${server2.apiKey}` } : void 0;
|
|
6642
|
+
return new SseMcpClient({ id: server2.id, name: server2.name, url: server2.url, headers });
|
|
6640
6643
|
}
|
|
6641
6644
|
if (!server2.command) throw new Error(`MCP server "${server2.name}" has transport=stdio but no command`);
|
|
6642
6645
|
return new StdioMcpClient({
|
|
@@ -6776,7 +6779,7 @@ var GenerationGate = class {
|
|
|
6776
6779
|
};
|
|
6777
6780
|
|
|
6778
6781
|
// src/agents/runner.ts
|
|
6779
|
-
import { EventEmitter
|
|
6782
|
+
import { EventEmitter } from "events";
|
|
6780
6783
|
|
|
6781
6784
|
// src/chat/parser.ts
|
|
6782
6785
|
var THINK_OPEN = "<think>";
|
|
@@ -7551,7 +7554,7 @@ var AgentRunner = class {
|
|
|
7551
7554
|
const pending = this.queue.shift();
|
|
7552
7555
|
this.active = pending.id;
|
|
7553
7556
|
const buffer = new RunBuffer();
|
|
7554
|
-
const emitter = new
|
|
7557
|
+
const emitter = new EventEmitter();
|
|
7555
7558
|
emitter.setMaxListeners(50);
|
|
7556
7559
|
const ac = new AbortController();
|
|
7557
7560
|
this.buffers.set(pending.id, buffer);
|
|
@@ -11131,6 +11134,7 @@ function registerApi(app2, d) {
|
|
|
11131
11134
|
});
|
|
11132
11135
|
if (b.tavilyApiKey !== void 0 || b.search !== void 0) {
|
|
11133
11136
|
d.tools?.updateConfig(d.store.snapshot().tools);
|
|
11137
|
+
await d.tools?.buildToolDefinitions();
|
|
11134
11138
|
}
|
|
11135
11139
|
const after = d.store.snapshot().daemon;
|
|
11136
11140
|
const lanChanged = after.lanBind !== before.lanBind;
|
|
@@ -11156,14 +11160,22 @@ function registerApi(app2, d) {
|
|
|
11156
11160
|
name: b.name.trim(),
|
|
11157
11161
|
transport,
|
|
11158
11162
|
enabled: b.enabled !== false,
|
|
11159
|
-
...transport === "stdio" ? { command: b.command.trim(), args: b.args ?? [], env: b.env ?? {} } : { url: b.url.trim() }
|
|
11163
|
+
...transport === "stdio" ? { command: b.command.trim(), args: b.args ?? [], env: b.env ?? {} } : { url: b.url.trim(), ...b.apiKey ? { apiKey: b.apiKey } : {} }
|
|
11160
11164
|
};
|
|
11165
|
+
const isMemoryServer = server2.transport === "stdio" && (server2.command?.includes("server-memory") || server2.args?.some((a) => a.includes("server-memory")));
|
|
11166
|
+
if (isMemoryServer && !server2.env?.MEMORY_FILE_PATH) {
|
|
11167
|
+
server2.env = { ...server2.env, MEMORY_FILE_PATH: join22(homedir3(), ".turbollm", "mcp-memory.jsonl") };
|
|
11168
|
+
}
|
|
11161
11169
|
d.store.update((cfg2) => {
|
|
11162
11170
|
cfg2.mcp.servers.push(server2);
|
|
11163
11171
|
});
|
|
11164
|
-
if (server2.enabled)
|
|
11165
|
-
|
|
11166
|
-
|
|
11172
|
+
if (server2.enabled) {
|
|
11173
|
+
await d.tools?.syncMcpServers(d.store.snapshot().mcp.servers).catch(() => {
|
|
11174
|
+
});
|
|
11175
|
+
await d.tools?.buildToolDefinitions();
|
|
11176
|
+
}
|
|
11177
|
+
const { apiKey: _created, ...safeServer } = server2;
|
|
11178
|
+
return c.json(safeServer, 201);
|
|
11167
11179
|
});
|
|
11168
11180
|
app2.put("/api/v1/mcp/servers/:id", async (c) => {
|
|
11169
11181
|
const id = c.req.param("id");
|
|
@@ -11181,12 +11193,16 @@ function registerApi(app2, d) {
|
|
|
11181
11193
|
if (b.args !== void 0) s.args = b.args;
|
|
11182
11194
|
if (b.env !== void 0) s.env = b.env;
|
|
11183
11195
|
if (b.url !== void 0) s.url = b.url;
|
|
11196
|
+
if (b.apiKey !== void 0) s.apiKey = b.apiKey || void 0;
|
|
11184
11197
|
});
|
|
11185
11198
|
await d.tools?.syncMcpServers(d.store.snapshot().mcp.servers).catch(() => {
|
|
11186
11199
|
});
|
|
11187
|
-
|
|
11200
|
+
await d.tools?.buildToolDefinitions();
|
|
11201
|
+
const updated = d.store.snapshot().mcp.servers.find((s) => s.id === id);
|
|
11202
|
+
const { apiKey: _updated, ...safeUpdated } = updated;
|
|
11203
|
+
return c.json(safeUpdated);
|
|
11188
11204
|
});
|
|
11189
|
-
app2.delete("/api/v1/mcp/servers/:id", (c) => {
|
|
11205
|
+
app2.delete("/api/v1/mcp/servers/:id", async (c) => {
|
|
11190
11206
|
const id = c.req.param("id");
|
|
11191
11207
|
const cfg2 = d.store.snapshot();
|
|
11192
11208
|
if (!cfg2.mcp.servers.some((s) => s.id === id)) return err2(c, 404, "not_found", "MCP server not found.");
|
|
@@ -11194,6 +11210,7 @@ function registerApi(app2, d) {
|
|
|
11194
11210
|
c2.mcp.servers = c2.mcp.servers.filter((s) => s.id !== id);
|
|
11195
11211
|
});
|
|
11196
11212
|
void d.tools?.syncMcpServers(d.store.snapshot().mcp.servers);
|
|
11213
|
+
await d.tools?.buildToolDefinitions();
|
|
11197
11214
|
return c.json({ ok: true });
|
|
11198
11215
|
});
|
|
11199
11216
|
app2.get("/api/v1/telemetry/preview", (c) => {
|
|
@@ -11446,7 +11463,8 @@ function settingsPayload(d) {
|
|
|
11446
11463
|
kagiKeySet: !!cfg2.tools.search?.kagiApiKey,
|
|
11447
11464
|
searxngUrl: cfg2.tools.search?.searxngUrl ?? ""
|
|
11448
11465
|
},
|
|
11449
|
-
|
|
11466
|
+
// apiKey is write-only: strip before echoing so Bearer tokens never reach the frontend.
|
|
11467
|
+
mcp: { ...cfg2.mcp, servers: cfg2.mcp.servers.map(({ apiKey: _k, ...s }) => s) },
|
|
11450
11468
|
// Build environment (ADR-100): folders prepended to PATH for compile-from-source so a
|
|
11451
11469
|
// conda-env / custom-path CUDA Toolkit + compiler are found. Not secret — echoed back.
|
|
11452
11470
|
build: { toolchainDirs: cfg2.build.toolchainDirs }
|
|
@@ -12525,6 +12543,7 @@ var toolRegistry = new ToolRegistry(store.snapshot().tools);
|
|
|
12525
12543
|
void (async () => {
|
|
12526
12544
|
const cfg2 = store.snapshot();
|
|
12527
12545
|
await toolRegistry.syncMcpServers(cfg2.mcp.servers);
|
|
12546
|
+
void toolRegistry.buildToolDefinitions();
|
|
12528
12547
|
})();
|
|
12529
12548
|
var startedAt = Date.now();
|
|
12530
12549
|
var appUpdates = new AppUpdateChecker(version);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./radix-4XwKfE88.js";import{r as u}from"./vendor-CKtmMAvG.js";import{c as w,
|
|
1
|
+
import{j as e}from"./radix-4XwKfE88.js";import{r as u}from"./vendor-CKtmMAvG.js";import{c as w,b as k,A as T,u as v,L as h,d as S,a as b,e as C,f as q,X as A}from"./index-CM4wnT7v.js";import{P as N}from"./plus-BLEwDzPR.js";import{C as y}from"./circle-x-CDfcuELr.js";import{C as O}from"./circle-check-iwGQW5-3.js";import{W as E}from"./wrench-C7hemMKG.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??{}},i=await fetch(t,{...a,headers:l});if(i.status===204)return;const r=await i.text(),o=r?JSON.parse(r):void 0;if(!i.ok){const d=o;throw new T(d?.error?.code??"http_error",d?.error?.message??`Request failed with status ${i.status}.`,i.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 i=`/api/v1/agents/runs/${t}/stream?fromSeq=${a}`,r=await fetch(i,{headers:{Accept:"text/event-stream",...k()},signal:l});if(!r.ok||!r.body)throw new Error(`Stream error: ${r.status}`);const o=r.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,i]=u.useState(""),[r,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:r||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=>i(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:r,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),i=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(r=>!r),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:i})]}),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),[i,r]=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,r(x);else if(c.event==="done"||c.event==="error"){r(""),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"})},[i,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)),i&&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:i})})}),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,i]=u.useState(!1),r=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=r.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:()=>i(!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:[r.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&&!r.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:()=>i(!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:()=>i(!1),onCreated:s=>{a(s),r.refetch()}})]})}export{ne as AgentsScreen};
|