turbollm 1.13.6 → 1.13.7
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 +229 -122
- package/dist/webdist/assets/{AgentEditPage-BzG20IJo.js → AgentEditPage-E7HtOsup.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-CGTfgk6t.js → ChatScreen-dEouSpAv.js} +1 -1
- package/dist/webdist/assets/{CodeComposer-DkaX0aou.js → CodeComposer-CkqctDdp.js} +1 -1
- package/dist/webdist/assets/{CodeHomeScreen-C6Mx3KKG.js → CodeHomeScreen-W_lZHAT2.js} +1 -1
- package/dist/webdist/assets/{CodeSessionScreen-BF_ck2zI.js → CodeSessionScreen-BX1Eaqga.js} +1 -1
- package/dist/webdist/assets/{CustomizeScreen-BB4hjJHh.js → CustomizeScreen-BszOveS0.js} +1 -1
- package/dist/webdist/assets/EnginesScreen-C3Tr39oE.js +10 -0
- package/dist/webdist/assets/{HardwareSection-CHCi45EV.js → HardwareSection-Cvzgs-RM.js} +1 -1
- package/dist/webdist/assets/{ModelDetailDialog-C3tk_RxR.js → ModelDetailDialog-CQ_x0n0p.js} +1 -1
- package/dist/webdist/assets/{ModelLoadMenu-FcRnPBLY.js → ModelLoadMenu-Lir_ZeaD.js} +1 -1
- package/dist/webdist/assets/{ModelsScreen-C4X4NjE2.js → ModelsScreen-BwzqukhW.js} +1 -1
- package/dist/webdist/assets/{OnboardingScreen-CaM7ExyF.js → OnboardingScreen-Df_1EYOW.js} +1 -1
- package/dist/webdist/assets/{RoutineEditPage-BAfZYpYu.js → RoutineEditPage-CdZnyBEw.js} +1 -1
- package/dist/webdist/assets/{RoutinesPanel-B3iJfoD3.js → RoutinesPanel-CBOpHq9E.js} +1 -1
- package/dist/webdist/assets/{SettingsScreen-DBwDO8TR.js → SettingsScreen-Bhih9go0.js} +1 -1
- package/dist/webdist/assets/{SidebarResizeHandle-CJUpye8c.js → SidebarResizeHandle-CNnIPZEp.js} +1 -1
- package/dist/webdist/assets/{SkillEditPage-CHhkakhI.js → SkillEditPage-CCtOQTmq.js} +1 -1
- package/dist/webdist/assets/{ToolApprovalBar-C6_ZJDzC.js → ToolApprovalBar-PlYgG25-.js} +3 -3
- package/dist/webdist/assets/WorkspaceScreen-CqmBBbxz.js +1 -0
- package/dist/webdist/assets/{abnfDiagram-N423BO3Z-CjZCDJJe.js → abnfDiagram-N423BO3Z-DsZ93mAM.js} +1 -1
- package/dist/webdist/assets/{agent-api-Q07TJf7T.js → agent-api-BQn5nZNX.js} +1 -1
- package/dist/webdist/assets/{alert-dialog-fWVjIQYe.js → alert-dialog-D9Z7ppH_.js} +1 -1
- package/dist/webdist/assets/{arc-DEmyGdWp.js → arc-BGrHHnrw.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-T3A2C74G-BuR_LXcC.js → architectureDiagram-T3A2C74G-Ey1UrzU-.js} +1 -1
- package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-uBPjcCWa.js → blockDiagram-VBNYF7ZC-D78LM23z.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-5PPSVZJV-B2N1IXTa.js → c4Diagram-5PPSVZJV-CvPfXzDr.js} +1 -1
- package/dist/webdist/assets/channel-DCuz_wdC.js +1 -0
- package/dist/webdist/assets/{chat-api-CP-1zHWH.js → chat-api-BKO4BTWe.js} +1 -1
- package/dist/webdist/assets/{chat-queries-C19981zO.js → chat-queries-CqiPDqGV.js} +1 -1
- package/dist/webdist/assets/{chevron-down-Be9un6T0.js → chevron-down-SLGilXKT.js} +1 -1
- package/dist/webdist/assets/{chevron-left-8-aTOHPO.js → chevron-left-CU5U4gIb.js} +1 -1
- package/dist/webdist/assets/{chevron-right-DQlioXo8.js → chevron-right-BY4anLEq.js} +1 -1
- package/dist/webdist/assets/{chunk-2GRJ4B5K-TlR5T4Vi.js → chunk-2GRJ4B5K-P3cu6Bc0.js} +1 -1
- package/dist/webdist/assets/{chunk-2Q5K7J3B-5kezfKDh.js → chunk-2Q5K7J3B-BgP7AimG.js} +1 -1
- package/dist/webdist/assets/{chunk-5RXB4S5H-C8ItBvcB.js → chunk-5RXB4S5H-B-FXWALA.js} +1 -1
- package/dist/webdist/assets/{chunk-5VM5RSS4-BXvuKQZV.js → chunk-5VM5RSS4-C-lQ75_C.js} +1 -1
- package/dist/webdist/assets/{chunk-6Q2QTUOP-Cbta8vGG.js → chunk-6Q2QTUOP-Cv-tXjKv.js} +1 -1
- package/dist/webdist/assets/{chunk-GF5L2VYU-CIuHLncz.js → chunk-GF5L2VYU-C3sxcn3E.js} +1 -1
- package/dist/webdist/assets/{chunk-JWPE2WC7-8rGGjIyo.js → chunk-JWPE2WC7-C-AvRcoC.js} +1 -1
- package/dist/webdist/assets/{chunk-KBJHAD2P-DFvvwuKz.js → chunk-KBJHAD2P-DMDEB7Sy.js} +1 -1
- package/dist/webdist/assets/{chunk-RYQCIY6F-B3c_vHIM.js → chunk-RYQCIY6F-DX_4YbYG.js} +1 -1
- package/dist/webdist/assets/{chunk-XXDRQBXY-DFBG-ven.js → chunk-XXDRQBXY-C-C12qlP.js} +1 -1
- package/dist/webdist/assets/{circle-check-DWL-BNw2.js → circle-check-D0IMfrYq.js} +1 -1
- package/dist/webdist/assets/{circle-x-CCKv4SGG.js → circle-x-pqL2JhJm.js} +1 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-DFsr_nh-.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-DFsr_nh-.js +1 -0
- package/dist/webdist/assets/{collapsible-B09fxy0d.js → collapsible-Bwm3DfUf.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-JH36ORCC-xnHX_e1i.js → cose-bilkent-JH36ORCC-0_jV9L5K.js} +1 -1
- package/dist/webdist/assets/{cynefin-VYW2F7L2-DqLKYsq-.js → cynefin-VYW2F7L2-D-cQNJqC.js} +1 -1
- package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-B_QMRv50.js → cynefinDiagram-MW4NZA55-QRp_3yKa.js} +1 -1
- package/dist/webdist/assets/{dagre-VZM6K2ZE-DCFGMRws.js → dagre-VZM6K2ZE-DYHS_FuW.js} +1 -1
- package/dist/webdist/assets/{diagram-7IWD3JNH-1ct9pPXF.js → diagram-7IWD3JNH-js1EUUk6.js} +1 -1
- package/dist/webdist/assets/{diagram-B4RE2ZJO-DqYEblJb.js → diagram-B4RE2ZJO-BHVEhFez.js} +1 -1
- package/dist/webdist/assets/{diagram-LBJQPF4R-CT-3lsOW.js → diagram-LBJQPF4R-Cc-5wAwq.js} +1 -1
- package/dist/webdist/assets/{diagram-Q27KOJAE-Bspp2eCN.js → diagram-Q27KOJAE-jTxFyyeN.js} +1 -1
- package/dist/webdist/assets/{diagram-UB23O5K3-DB_Hg65f.js → diagram-UB23O5K3-LP8zrNnQ.js} +1 -1
- package/dist/webdist/assets/{dropdown-menu-dzMJR6N9.js → dropdown-menu-IOTY3_-B.js} +1 -1
- package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-kk9-pxcN.js → ebnfDiagram-BXEA7PRR-qDNqlger.js} +1 -1
- package/dist/webdist/assets/{erDiagram-JOGREHBK-BCI0nybn.js → erDiagram-JOGREHBK-owRtaAi_.js} +1 -1
- package/dist/webdist/assets/{file-text-B94KmADS.js → file-text-BotUNsIW.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-UKHOOZJN-CPzxY-LP.js → flowDiagram-UKHOOZJN-D26LSAka.js} +1 -1
- package/dist/webdist/assets/{folder-input-DL3mQB2F.js → folder-input-D3qEcRaK.js} +1 -1
- package/dist/webdist/assets/{folder-plus-Wpcb9ENt.js → folder-plus-4hzyN--0.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-DozbuEKD.js → ganttDiagram-PKOTCBZU-FOBYQpFD.js} +1 -1
- package/dist/webdist/assets/{git-branch-yfPP244o.js → git-branch-CSkwfOC2.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-CA_nEHp7.js → gitGraphDiagram-DS77QQ5N-D1pwlyQx.js} +1 -1
- package/dist/webdist/assets/{globe-DnAghWjQ.js → globe-BvQjzBKb.js} +1 -1
- package/dist/webdist/assets/{index-C14bv39c.js → index-CXLOA4-7.js} +2 -2
- package/dist/webdist/assets/{infoDiagram-6WML65LV-EBvusVlh.js → infoDiagram-6WML65LV-DAxebGLC.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-VEUjJ6iO.js → ishikawaDiagram-WSZJBQD7-DIdOYDDr.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-DNV1VMnS.js → journeyDiagram-NVQOT4AX-BLvkNn5k.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-27J2QSJJ-B7bGb4hd.js → kanban-definition-27J2QSJJ-DKyJQb6a.js} +1 -1
- package/dist/webdist/assets/{linear-C5BAUlj1.js → linear-sR1aOS-1.js} +1 -1
- package/dist/webdist/assets/{lock-B4ECw-T0.js → lock-K-a91AFa.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-BGxUfnBa.js → mermaid.core-sVxlfu4j.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-BcuS9e3b.js → mindmap-definition-FAOFIHXS-Yo_cYEEu.js} +1 -1
- package/dist/webdist/assets/{monitor-o9jnBqQh.js → monitor-_13VL1du.js} +1 -1
- package/dist/webdist/assets/{pegDiagram-VL7TDLO6-B8r_GRtJ.js → pegDiagram-VL7TDLO6-BSAx7r44.js} +1 -1
- package/dist/webdist/assets/{pencil-MwR3RvUZ.js → pencil-CshqlsN6.js} +1 -1
- package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-VlB8e0KH.js → pieDiagram-7S7Q4E2Y-DJDpIi_G.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-BMvoitnW.js → quadrantDiagram-CIZ2JOQS-BYUOd1Ld.js} +1 -1
- package/dist/webdist/assets/{railroadDiagram-AXF67PYL-CnDluqgH.js → railroadDiagram-AXF67PYL-Cp7ActLQ.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-BzGTCNVs.js → refresh-cw-BgvgHNs_.js} +1 -1
- package/dist/webdist/assets/{remote-failure-Bc9jLh0G.js → remote-failure-CU6FQAv2.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-Cf_bcWKz.js → requirementDiagram-LRYGKXZP-BRIn9Bao.js} +1 -1
- package/dist/webdist/assets/{rocket-3zkwetoN.js → rocket-Bdyspsau.js} +1 -1
- package/dist/webdist/assets/{rotate-ccw-fyN6mgMa.js → rotate-ccw-CXchjxoU.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-abjcXFrR.js → sankeyDiagram-W5VNT64P-DrfFnEda.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-BAzSl86z.js → sequenceDiagram-SI44F4Z6-BRvCwGTa.js} +1 -1
- package/dist/webdist/assets/{sheet-E29qj5H3.js → sheet-BEHvWodM.js} +1 -1
- package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-X6FTXo_P.js → sizeCapture-X5ZJPWSS-BLSbFiEe.js} +1 -1
- package/dist/webdist/assets/{skeleton-BOHWHwm6.js → skeleton-_WE_l7Ss.js} +1 -1
- package/dist/webdist/assets/{sliders-horizontal-CUBfMzM4.js → sliders-horizontal-X0H751ey.js} +1 -1
- package/dist/webdist/assets/{sparkles-B_nFb4N9.js → sparkles-B57ip_p2.js} +1 -1
- package/dist/webdist/assets/{star-DQIcK5P8.js → star-DFChWJ1H.js} +1 -1
- package/dist/webdist/assets/{stateDiagram-OKZ733FA-BhH_WS-y.js → stateDiagram-OKZ733FA-dWf7zqCN.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-CQPsdlPu.js +1 -0
- package/dist/webdist/assets/{swimlanes-SLNWSIFB-BvuBhRif.js → swimlanes-SLNWSIFB-lCDiXKRw.js} +2 -2
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-CzicNSYv.js +8 -0
- package/dist/webdist/assets/{switch-D-bpf0ou.js → switch-1qn4bGLW.js} +1 -1
- package/dist/webdist/assets/{terminal-Bi_kg8jX.js → terminal-BiLS4W9p.js} +1 -1
- package/dist/webdist/assets/{timeline-definition-Z64GVDOM-CT4o3tCm.js → timeline-definition-Z64GVDOM-DSxynxhf.js} +1 -1
- package/dist/webdist/assets/{trash-2-BXeiMvg8.js → trash-2-JXgZx0Gm.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-T6HMQDX7-D7hteJww.js → vennDiagram-T6HMQDX7-AFtVyBx_.js} +1 -1
- package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y-C6kQIV_N.js → wardleyDiagram-T6FBY63Y-Bi_TjYlH.js} +1 -1
- package/dist/webdist/assets/{wrench-CcGmlTUS.js → wrench-C6y9CDpZ.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-DPy3Pkbw.js → xychartDiagram-ELKLHX3M-BaREW8xI.js} +1 -1
- package/dist/webdist/index.html +1 -1
- package/package.json +1 -1
- package/dist/webdist/assets/EnginesScreen-DlfORHsE.js +0 -10
- package/dist/webdist/assets/WorkspaceScreen-B6mjHG3v.js +0 -1
- package/dist/webdist/assets/channel-CzDLlXHw.js +0 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-xDdy69O-.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-xDdy69O-.js +0 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-BXZstPHr.js +0 -1
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-B75QTfBv.js +0 -8
package/dist/cli.js
CHANGED
|
@@ -788,7 +788,7 @@ function clampMaxTokens(requested, limit) {
|
|
|
788
788
|
}
|
|
789
789
|
|
|
790
790
|
// src/engines/manager.ts
|
|
791
|
-
import { execFile as
|
|
791
|
+
import { execFile as execFile7, spawn, spawnSync } from "child_process";
|
|
792
792
|
import { createWriteStream, existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync as rmSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
793
793
|
import { createConnection, createServer } from "net";
|
|
794
794
|
import { dirname as dirname2, join as join10 } from "path";
|
|
@@ -1213,10 +1213,99 @@ async function restoreSlot(p) {
|
|
|
1213
1213
|
|
|
1214
1214
|
// src/engines/vllm.ts
|
|
1215
1215
|
import { existsSync as existsSync8 } from "fs";
|
|
1216
|
-
import { execFile as
|
|
1216
|
+
import { execFile as execFile5 } from "child_process";
|
|
1217
1217
|
import { join as join8 } from "path";
|
|
1218
|
+
import { promisify as promisify5 } from "util";
|
|
1219
|
+
|
|
1220
|
+
// src/engines/py-engine-blocker.ts
|
|
1221
|
+
import { execFile as execFile4 } from "child_process";
|
|
1222
|
+
import { homedir as homedir2 } from "os";
|
|
1218
1223
|
import { promisify as promisify4 } from "util";
|
|
1219
1224
|
var execFileP4 = promisify4(execFile4);
|
|
1225
|
+
var DETAIL_LIMIT = 200;
|
|
1226
|
+
var UvloopPreflight = class {
|
|
1227
|
+
constructor(engine, homeDirectory = homedir2) {
|
|
1228
|
+
this.engine = engine;
|
|
1229
|
+
this.homeDirectory = homeDirectory;
|
|
1230
|
+
}
|
|
1231
|
+
engine;
|
|
1232
|
+
homeDirectory;
|
|
1233
|
+
async blockerFor(python) {
|
|
1234
|
+
try {
|
|
1235
|
+
await execFileP4(python, ["-c", "import uvloop"], { timeout: 2e4 });
|
|
1236
|
+
return null;
|
|
1237
|
+
} catch (error) {
|
|
1238
|
+
return this.classify(process.platform, error);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
// uvloop publishes manylinux *and* macOS wheels, so only Windows is a real platform wall —
|
|
1242
|
+
// anywhere else a failed import is a broken local environment the user can reinstall.
|
|
1243
|
+
classify(platform, error) {
|
|
1244
|
+
if (platform === "win32") return this.unsupportedPlatform();
|
|
1245
|
+
const failure = error;
|
|
1246
|
+
if (failure?.code === "ENOENT") return this.missingInterpreter();
|
|
1247
|
+
return this.brokenEnvironment(platform, failure);
|
|
1248
|
+
}
|
|
1249
|
+
unsupportedPlatform() {
|
|
1250
|
+
return `${this.engine} cannot run on Windows: its server requires uvloop (and other Linux-only components such as NCCL/Triton), which have no Windows build. Use the llama.cpp / TurboQuant engine for GGUF models here, or run ${this.engine} under WSL2 / Linux.`;
|
|
1251
|
+
}
|
|
1252
|
+
missingInterpreter() {
|
|
1253
|
+
return `${this.engine}'s environment looks missing or broken (interpreter not found). Reinstall the ${this.engine} engine from the Engines page.`;
|
|
1254
|
+
}
|
|
1255
|
+
brokenEnvironment(platform, failure) {
|
|
1256
|
+
return `${this.engine}'s environment looks broken or incomplete (uvloop failed to import: ${failureDetail(failure, this.homeOrEmpty())}). ${this.platformStanding(platform)}`;
|
|
1257
|
+
}
|
|
1258
|
+
// homedir() throws (uv_os_homedir ENOENT) for a uid with no passwd entry and no HOME, e.g. a container.
|
|
1259
|
+
homeOrEmpty() {
|
|
1260
|
+
try {
|
|
1261
|
+
return this.homeDirectory();
|
|
1262
|
+
} catch {
|
|
1263
|
+
return "";
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
// Only what is true is claimed: Linux is where these engines are officially supported, while on
|
|
1267
|
+
// macOS the catalog rates them experimental / unsupported upstream, so only uvloop's own support
|
|
1268
|
+
// may be asserted there.
|
|
1269
|
+
platformStanding(platform) {
|
|
1270
|
+
const plat = platformDisplay(platform);
|
|
1271
|
+
if (platform === "linux") {
|
|
1272
|
+
return `${plat} is a supported platform for ${this.engine} \u2014 reinstall the ${this.engine} engine from the Engines page rather than switching engines.`;
|
|
1273
|
+
}
|
|
1274
|
+
if (platform === "darwin") {
|
|
1275
|
+
return `uvloop itself supports ${plat}, so reinstall the ${this.engine} engine from the Engines page first \u2014 though ${plat} is not a first-class platform for ${this.engine} upstream.`;
|
|
1276
|
+
}
|
|
1277
|
+
return `${this.engine} support on ${plat} is unverified \u2014 reinstall the ${this.engine} engine from the Engines page; if the import keeps failing, ${this.engine} may have no working build here.`;
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
function platformDisplay(platform) {
|
|
1281
|
+
if (platform === "win32") return "Windows";
|
|
1282
|
+
if (platform === "darwin") return "macOS";
|
|
1283
|
+
if (platform === "linux") return "Linux";
|
|
1284
|
+
return platform;
|
|
1285
|
+
}
|
|
1286
|
+
function failureDetail(failure, home) {
|
|
1287
|
+
const raw = failure?.stderr ? String(failure.stderr) : failure?.message ?? "";
|
|
1288
|
+
return capped(redactHome(lastMeaningfulLine(raw), home));
|
|
1289
|
+
}
|
|
1290
|
+
function lastMeaningfulLine(text) {
|
|
1291
|
+
const lines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1292
|
+
return lines.at(-1) ?? "unknown error";
|
|
1293
|
+
}
|
|
1294
|
+
function redactHome(text, home) {
|
|
1295
|
+
if (home.length < 2) return text;
|
|
1296
|
+
const spellings = /* @__PURE__ */ new Set([home, home.split("\\").join("/"), home.split("/").join("\\")]);
|
|
1297
|
+
const anySpelling = new RegExp([...spellings].map(escapeRegExp).join("|"), "gi");
|
|
1298
|
+
return text.replace(anySpelling, "~");
|
|
1299
|
+
}
|
|
1300
|
+
function escapeRegExp(text) {
|
|
1301
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1302
|
+
}
|
|
1303
|
+
function capped(detail) {
|
|
1304
|
+
return detail.length <= DETAIL_LIMIT ? detail : `${detail.slice(0, DETAIL_LIMIT)}\u2026`;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// src/engines/vllm.ts
|
|
1308
|
+
var execFileP5 = promisify5(execFile5);
|
|
1220
1309
|
var VLLM_PYTHON = "3.12";
|
|
1221
1310
|
function venvPython4(envDir) {
|
|
1222
1311
|
return process.platform === "win32" ? join8(envDir, "Scripts", "python.exe") : join8(envDir, "bin", "python");
|
|
@@ -1227,43 +1316,23 @@ async function ensureVllmEnv(root, onProgress, upgrade = false) {
|
|
|
1227
1316
|
const py = venvPython4(envDir);
|
|
1228
1317
|
if (!existsSync8(py)) {
|
|
1229
1318
|
onProgress?.({ phase: "extracting", pct: -1 });
|
|
1230
|
-
await
|
|
1319
|
+
await execFileP5(uv, ["venv", "--python", VLLM_PYTHON, envDir], { cwd: root });
|
|
1231
1320
|
}
|
|
1232
1321
|
onProgress?.({ phase: "extracting", pct: -1 });
|
|
1233
1322
|
const installArgs = ["pip", "install", "--python", py, ...upgrade ? ["-U"] : [], "vllm"];
|
|
1234
|
-
await
|
|
1323
|
+
await execFileP5(uv, installArgs, {
|
|
1235
1324
|
cwd: root,
|
|
1236
1325
|
maxBuffer: 64 * 1024 * 1024
|
|
1237
1326
|
});
|
|
1238
1327
|
const version2 = await probeVllm(py);
|
|
1239
1328
|
return { python: py, version: version2 };
|
|
1240
1329
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
function classifyVllmBlocker(platform, error) {
|
|
1245
|
-
const plat = platformDisplay(platform);
|
|
1246
|
-
if (platform === "win32" || platform === "darwin") {
|
|
1247
|
-
return `vLLM cannot run on ${plat}: its OpenAI server requires uvloop (and other Linux-only components such as NCCL/Triton), which have no ${plat} build. Use the llama.cpp / TurboQuant engine for GGUF models here, or run vLLM under WSL2 / Linux.`;
|
|
1248
|
-
}
|
|
1249
|
-
const err9 = error;
|
|
1250
|
-
if (err9?.code === "ENOENT") {
|
|
1251
|
-
return `vLLM's environment looks missing or broken (interpreter not found). Reinstall the vLLM engine from the Engines page.`;
|
|
1252
|
-
}
|
|
1253
|
-
const raw = err9?.stderr ? String(err9.stderr) : err9?.message ?? "unknown error";
|
|
1254
|
-
const detail = raw.trim().split("\n").filter(Boolean).slice(-1)[0] ?? raw.trim();
|
|
1255
|
-
return `vLLM's environment looks broken or incomplete (uvloop failed to import: ${detail}). ${plat} is a supported platform for vLLM \u2014 reinstall the vLLM engine from the Engines page rather than switching engines.`;
|
|
1256
|
-
}
|
|
1257
|
-
async function vllmServeBlocker(python) {
|
|
1258
|
-
try {
|
|
1259
|
-
await execFileP4(python, ["-c", "import uvloop"], { timeout: 2e4 });
|
|
1260
|
-
return null;
|
|
1261
|
-
} catch (error) {
|
|
1262
|
-
return classifyVllmBlocker(process.platform, error);
|
|
1263
|
-
}
|
|
1330
|
+
var uvloopPreflight = new UvloopPreflight("vLLM");
|
|
1331
|
+
function vllmServeBlocker(python) {
|
|
1332
|
+
return uvloopPreflight.blockerFor(python);
|
|
1264
1333
|
}
|
|
1265
1334
|
async function probeVllm(python) {
|
|
1266
|
-
const { stdout } = await
|
|
1335
|
+
const { stdout } = await execFileP5(
|
|
1267
1336
|
python,
|
|
1268
1337
|
["-c", 'import importlib.metadata as m; print(m.version("vllm"))'],
|
|
1269
1338
|
{ timeout: 3e4 }
|
|
@@ -1293,10 +1362,10 @@ function vllmServerCommand(python, model, port2, host2, tensorParallelSize = 1,
|
|
|
1293
1362
|
|
|
1294
1363
|
// src/engines/sglang.ts
|
|
1295
1364
|
import { existsSync as existsSync9 } from "fs";
|
|
1296
|
-
import { execFile as
|
|
1365
|
+
import { execFile as execFile6 } from "child_process";
|
|
1297
1366
|
import { join as join9 } from "path";
|
|
1298
|
-
import { promisify as
|
|
1299
|
-
var
|
|
1367
|
+
import { promisify as promisify6 } from "util";
|
|
1368
|
+
var execFileP6 = promisify6(execFile6);
|
|
1300
1369
|
var SGLANG_PYTHON = "3.12";
|
|
1301
1370
|
function venvPython5(envDir) {
|
|
1302
1371
|
return process.platform === "win32" ? join9(envDir, "Scripts", "python.exe") : join9(envDir, "bin", "python");
|
|
@@ -1307,40 +1376,20 @@ async function ensureSglangEnv(root, onProgress, upgrade = false) {
|
|
|
1307
1376
|
const py = venvPython5(envDir);
|
|
1308
1377
|
if (!existsSync9(py)) {
|
|
1309
1378
|
onProgress?.({ phase: "extracting", pct: -1 });
|
|
1310
|
-
await
|
|
1379
|
+
await execFileP6(uv, ["venv", "--python", SGLANG_PYTHON, envDir], { cwd: root });
|
|
1311
1380
|
}
|
|
1312
1381
|
onProgress?.({ phase: "extracting", pct: -1 });
|
|
1313
1382
|
const installArgs = ["pip", "install", "--python", py, ...upgrade ? ["-U"] : [], "sglang[all]"];
|
|
1314
|
-
await
|
|
1383
|
+
await execFileP6(uv, installArgs, { cwd: root, maxBuffer: 64 * 1024 * 1024 });
|
|
1315
1384
|
const version2 = await probeSglang(py);
|
|
1316
1385
|
return { python: py, version: version2 };
|
|
1317
1386
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
function classifySglangBlocker(platform, error) {
|
|
1322
|
-
const plat = platformDisplay2(platform);
|
|
1323
|
-
if (platform === "win32" || platform === "darwin") {
|
|
1324
|
-
return `SGLang cannot run on ${plat}: its server requires uvloop (and other Linux-only components), which have no ${plat} build. Use the llama.cpp / TurboQuant engine for GGUF models here, or run SGLang under WSL2 / Linux.`;
|
|
1325
|
-
}
|
|
1326
|
-
const err9 = error;
|
|
1327
|
-
if (err9?.code === "ENOENT") {
|
|
1328
|
-
return `SGLang's environment looks missing or broken (interpreter not found). Reinstall the SGLang engine from the Engines page.`;
|
|
1329
|
-
}
|
|
1330
|
-
const raw = err9?.stderr ? String(err9.stderr) : err9?.message ?? "unknown error";
|
|
1331
|
-
const detail = raw.trim().split("\n").filter(Boolean).slice(-1)[0] ?? raw.trim();
|
|
1332
|
-
return `SGLang's environment looks broken or incomplete (uvloop failed to import: ${detail}). ${plat} is a supported platform for SGLang \u2014 reinstall the SGLang engine from the Engines page rather than switching engines.`;
|
|
1333
|
-
}
|
|
1334
|
-
async function sgLangServeBlocker(python) {
|
|
1335
|
-
try {
|
|
1336
|
-
await execFileP5(python, ["-c", "import uvloop"], { timeout: 2e4 });
|
|
1337
|
-
return null;
|
|
1338
|
-
} catch (error) {
|
|
1339
|
-
return classifySglangBlocker(process.platform, error);
|
|
1340
|
-
}
|
|
1387
|
+
var uvloopPreflight2 = new UvloopPreflight("SGLang");
|
|
1388
|
+
function sgLangServeBlocker(python) {
|
|
1389
|
+
return uvloopPreflight2.blockerFor(python);
|
|
1341
1390
|
}
|
|
1342
1391
|
async function probeSglang(python) {
|
|
1343
|
-
const { stdout } = await
|
|
1392
|
+
const { stdout } = await execFileP6(
|
|
1344
1393
|
python,
|
|
1345
1394
|
["-c", 'import importlib.metadata as m; print(m.version("sglang"))'],
|
|
1346
1395
|
{ timeout: 3e4 }
|
|
@@ -1952,7 +2001,7 @@ async function gracefulStop(child, exited) {
|
|
|
1952
2001
|
function signalTerm(child) {
|
|
1953
2002
|
if (!child.pid) return;
|
|
1954
2003
|
if (process.platform === "win32") {
|
|
1955
|
-
|
|
2004
|
+
execFile7("taskkill", ["/PID", String(child.pid), "/T"], () => {
|
|
1956
2005
|
});
|
|
1957
2006
|
} else {
|
|
1958
2007
|
child.kill("SIGTERM");
|
|
@@ -1961,7 +2010,7 @@ function signalTerm(child) {
|
|
|
1961
2010
|
function forceKill(child) {
|
|
1962
2011
|
if (!child.pid) return;
|
|
1963
2012
|
if (process.platform === "win32") {
|
|
1964
|
-
|
|
2013
|
+
execFile7("taskkill", ["/PID", String(child.pid), "/F", "/T"], () => {
|
|
1965
2014
|
});
|
|
1966
2015
|
} else {
|
|
1967
2016
|
child.kill("SIGKILL");
|
|
@@ -2066,7 +2115,7 @@ function killTrackedEnginesSync(dataDir) {
|
|
|
2066
2115
|
}
|
|
2067
2116
|
function killPidTree(pid) {
|
|
2068
2117
|
if (process.platform === "win32") {
|
|
2069
|
-
|
|
2118
|
+
execFile7("taskkill", ["/PID", String(pid), "/F", "/T"], () => {
|
|
2070
2119
|
});
|
|
2071
2120
|
} else {
|
|
2072
2121
|
try {
|
|
@@ -2321,7 +2370,7 @@ import { existsSync as existsSync14 } from "fs";
|
|
|
2321
2370
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2322
2371
|
|
|
2323
2372
|
// src/engines/probe.ts
|
|
2324
|
-
import { execFile as
|
|
2373
|
+
import { execFile as execFile8 } from "child_process";
|
|
2325
2374
|
import { closeSync, existsSync as existsSync11, openSync, readSync, statSync as statSync2 } from "fs";
|
|
2326
2375
|
import { dirname as dirname3 } from "path";
|
|
2327
2376
|
function probeEnv(bin) {
|
|
@@ -2350,7 +2399,7 @@ function runCaptured(bin, arg) {
|
|
|
2350
2399
|
return new Promise((resolve6) => {
|
|
2351
2400
|
try {
|
|
2352
2401
|
const timeoutMs = process.platform === "darwin" ? 6e4 : 15e3;
|
|
2353
|
-
|
|
2402
|
+
execFile8(bin, [arg], { cwd: dirname3(bin), env: probeEnv(bin), timeout: timeoutMs, windowsHide: true, maxBuffer: 4 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
2354
2403
|
resolve6({ out: (stdout || "") + (stderr || ""), err: error });
|
|
2355
2404
|
});
|
|
2356
2405
|
} catch (e) {
|
|
@@ -2507,17 +2556,17 @@ function trimLen(s, n) {
|
|
|
2507
2556
|
}
|
|
2508
2557
|
|
|
2509
2558
|
// src/engines/build-runner.ts
|
|
2510
|
-
import { execFile as
|
|
2559
|
+
import { execFile as execFile10, spawn as spawn2 } from "child_process";
|
|
2511
2560
|
import { createHash as createHash2 } from "crypto";
|
|
2512
2561
|
import { copyFileSync, existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync3, readdirSync as readdirSync3, rmSync as rmSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
2513
2562
|
import { delimiter as delimiter2, dirname as dirname5, join as join12 } from "path";
|
|
2514
|
-
import { promisify as
|
|
2563
|
+
import { promisify as promisify8 } from "util";
|
|
2515
2564
|
|
|
2516
2565
|
// src/engines/build-prereqs.ts
|
|
2517
|
-
import { execFile as
|
|
2566
|
+
import { execFile as execFile9 } from "child_process";
|
|
2518
2567
|
import { delimiter, join as join11 } from "path";
|
|
2519
|
-
import { promisify as
|
|
2520
|
-
var
|
|
2568
|
+
import { promisify as promisify7 } from "util";
|
|
2569
|
+
var execFileP7 = promisify7(execFile9);
|
|
2521
2570
|
function buildEnv(toolchainDirs = []) {
|
|
2522
2571
|
const dirs = toolchainDirs.map((d) => d.trim()).filter(Boolean);
|
|
2523
2572
|
const env = { ...process.env };
|
|
@@ -2579,7 +2628,7 @@ var INSTALL_URLS = {
|
|
|
2579
2628
|
gcc: "https://gcc.gnu.org/install/"
|
|
2580
2629
|
};
|
|
2581
2630
|
async function runVersion(cmd, args, env) {
|
|
2582
|
-
const { stdout, stderr } = await
|
|
2631
|
+
const { stdout, stderr } = await execFileP7(cmd, args, {
|
|
2583
2632
|
timeout: 8e3,
|
|
2584
2633
|
windowsHide: true,
|
|
2585
2634
|
maxBuffer: 1024 * 1024,
|
|
@@ -2777,10 +2826,10 @@ function suggestEngineName(binPath, version2) {
|
|
|
2777
2826
|
}
|
|
2778
2827
|
|
|
2779
2828
|
// src/engines/build-runner.ts
|
|
2780
|
-
var
|
|
2829
|
+
var execFileP8 = promisify8(execFile10);
|
|
2781
2830
|
async function findLibcudaDir(signal) {
|
|
2782
2831
|
try {
|
|
2783
|
-
const { stdout } = await
|
|
2832
|
+
const { stdout } = await execFileP8("ldconfig", ["-p"], {
|
|
2784
2833
|
timeout: 5e3,
|
|
2785
2834
|
maxBuffer: 4 * 1024 * 1024,
|
|
2786
2835
|
signal
|
|
@@ -2801,13 +2850,14 @@ function findPriorEngine(engines, build2) {
|
|
|
2801
2850
|
const sameTarget = engines.filter(
|
|
2802
2851
|
(e) => sameRepo(e.sourceRepo, build2.sourceRepo) && (e.sourceCommit ?? "") === (build2.sourceCommit ?? "")
|
|
2803
2852
|
);
|
|
2804
|
-
|
|
2805
|
-
const wantedBranch = effectiveBranch(build2.sourceBranch, build2.defaultBranch);
|
|
2806
|
-
return sameTarget.find((e) => (e.sourceBranch ?? "").trim() === storedBranch) ?? sameTarget.find((e) => effectiveBranch(e.sourceBranch, build2.defaultBranch) === wantedBranch);
|
|
2853
|
+
return pickByBranch(sameTarget, (build2.sourceBranch ?? "").trim(), effectiveBranch(build2.sourceBranch, build2.defaultBranch), build2.defaultBranch);
|
|
2807
2854
|
}
|
|
2808
2855
|
function effectiveBranch(branch, defaultBranch) {
|
|
2809
2856
|
return (branch ?? "").trim() || (defaultBranch ?? "").trim();
|
|
2810
2857
|
}
|
|
2858
|
+
function pickByBranch(candidates, exactBranch, effective, defaultBranch) {
|
|
2859
|
+
return candidates.find((e) => (e.sourceBranch ?? "").trim() === exactBranch) ?? candidates.find((e) => effectiveBranch(e.sourceBranch, defaultBranch) === effective);
|
|
2860
|
+
}
|
|
2811
2861
|
var isPinnedEntry = (entry) => !!(entry.sourceCommit || entry.patchUrl);
|
|
2812
2862
|
function findEngineForCatalogEntry(engines, entry, requestedBranch) {
|
|
2813
2863
|
const sameBuild = engines.filter(
|
|
@@ -2815,7 +2865,7 @@ function findEngineForCatalogEntry(engines, entry, requestedBranch) {
|
|
|
2815
2865
|
);
|
|
2816
2866
|
if (isPinnedEntry(entry)) return sameBuild[0];
|
|
2817
2867
|
const wanted = effectiveBranch(requestedBranch, entry.defaultBranch);
|
|
2818
|
-
return sameBuild
|
|
2868
|
+
return pickByBranch(sameBuild, wanted, wanted, entry.defaultBranch);
|
|
2819
2869
|
}
|
|
2820
2870
|
function catalogBranchesToScan(entry, requestedBranch) {
|
|
2821
2871
|
if (isPinnedEntry(entry)) return [void 0];
|
|
@@ -2823,6 +2873,43 @@ function catalogBranchesToScan(entry, requestedBranch) {
|
|
|
2823
2873
|
if (!wanted) return [void 0];
|
|
2824
2874
|
return wanted === (entry.defaultBranch ?? "").trim() ? [wanted, void 0] : [wanted];
|
|
2825
2875
|
}
|
|
2876
|
+
function legacyBuildDirName(repoUrl, branch, commit) {
|
|
2877
|
+
const last = repoUrl.trim().replace(/\/+$/, "").split(/[\\/]/).pop() ?? "";
|
|
2878
|
+
const repo = last.replace(/\.git$/i, "").trim() || "engine";
|
|
2879
|
+
const b = (branch ?? "").trim();
|
|
2880
|
+
const sha = (commit ?? "").trim();
|
|
2881
|
+
return asDirName(sha ? `${repo}-${sha.slice(0, 12)}` : b ? `${repo}-${b}` : repo);
|
|
2882
|
+
}
|
|
2883
|
+
function serverBinaryIn(enginesRoot, dirName) {
|
|
2884
|
+
const root = join12(enginesRoot, "build", dirName);
|
|
2885
|
+
return resolveServerBinary(join12(root, "build")) ?? resolveServerBinary(root);
|
|
2886
|
+
}
|
|
2887
|
+
function findCatalogBuildOnDisk(enginesRoot, entry, requestedBranch) {
|
|
2888
|
+
for (const branch of catalogBranchesToScan(entry, requestedBranch)) {
|
|
2889
|
+
const binPath = sourceBuildBinary(enginesRoot, entry.homepage, branch, entry.sourceCommit);
|
|
2890
|
+
if (binPath) return { binPath, branch: branch ?? "" };
|
|
2891
|
+
}
|
|
2892
|
+
if (!entry.sourceCommit) return void 0;
|
|
2893
|
+
const legacy = serverBinaryIn(enginesRoot, legacyBuildDirName(entry.homepage, void 0, entry.sourceCommit));
|
|
2894
|
+
return legacy ? { binPath: legacy, branch: "" } : void 0;
|
|
2895
|
+
}
|
|
2896
|
+
var slashed = (path) => path.replace(/\\/g, "/").toLowerCase();
|
|
2897
|
+
function isEngineInBuildDir(binPath, buildRoot) {
|
|
2898
|
+
return slashed(binPath).startsWith(`${slashed(buildRoot).replace(/\/+$/, "")}/`);
|
|
2899
|
+
}
|
|
2900
|
+
var branchesProvablyDiffer = (a, b) => {
|
|
2901
|
+
const x = (a ?? "").trim();
|
|
2902
|
+
const y = (b ?? "").trim();
|
|
2903
|
+
return !!x && !!y && x !== y;
|
|
2904
|
+
};
|
|
2905
|
+
function findNameConflict(engines, name, build2) {
|
|
2906
|
+
const wanted = (name ?? "").trim().toLowerCase();
|
|
2907
|
+
if (!wanted) return void 0;
|
|
2908
|
+
const holder = engines.find((e) => e.name.trim().toLowerCase() === wanted);
|
|
2909
|
+
if (!holder) return void 0;
|
|
2910
|
+
const replaced = isEngineInBuildDir(holder.binPath, build2.buildRoot) || sameRepo(holder.sourceRepo, build2.sourceRepo) && (holder.sourceCommit ?? "") === (build2.sourceCommit ?? "") && !branchesProvablyDiffer(holder.sourceBranch, build2.sourceBranch);
|
|
2911
|
+
return replaced ? void 0 : holder;
|
|
2912
|
+
}
|
|
2826
2913
|
function parseDefaultBranch(lsRemoteOutput) {
|
|
2827
2914
|
return /^ref:\s+refs\/heads\/(\S+)\s+HEAD\s*$/m.exec(lsRemoteOutput)?.[1];
|
|
2828
2915
|
}
|
|
@@ -2830,8 +2917,14 @@ function buildDirName(repoUrl, branch, commit) {
|
|
|
2830
2917
|
const repo = normRepoUrl(repoUrl) || "engine";
|
|
2831
2918
|
const b = (branch ?? "").trim();
|
|
2832
2919
|
const sha = (commit ?? "").trim();
|
|
2833
|
-
|
|
2834
|
-
|
|
2920
|
+
return asDirName(sha ? `${repo}-${sha.slice(0, 12)}` : b ? `${repo}-${b}` : repo);
|
|
2921
|
+
}
|
|
2922
|
+
function asDirName(raw) {
|
|
2923
|
+
const slug = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2924
|
+
return isPathStep(slug) ? "engine" : slug;
|
|
2925
|
+
}
|
|
2926
|
+
function isPathStep(name) {
|
|
2927
|
+
return /^\.*$/.test(name);
|
|
2835
2928
|
}
|
|
2836
2929
|
function sameRepo(a, b) {
|
|
2837
2930
|
const na = normRepoUrl(a);
|
|
@@ -2841,12 +2934,11 @@ function normRepoUrl(s) {
|
|
|
2841
2934
|
return (s ?? "").trim().toLowerCase().replace(/^https?:\/\//, "").replace(/^github\.com\//, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
2842
2935
|
}
|
|
2843
2936
|
function sourceBuildBinary(enginesRoot, repoUrl, branch, commit) {
|
|
2844
|
-
|
|
2845
|
-
return resolveServerBinary(join12(root, "build")) ?? resolveServerBinary(root);
|
|
2937
|
+
return serverBinaryIn(enginesRoot, buildDirName(repoUrl, branch, commit));
|
|
2846
2938
|
}
|
|
2847
2939
|
function sourceBuildDirOf(binPath, enginesRoot) {
|
|
2848
2940
|
const m = binPath.replace(/\\/g, "/").match(/\/engines\/build\/([^/]+)(?:\/|$)/i);
|
|
2849
|
-
if (!m) return null;
|
|
2941
|
+
if (!m || isPathStep(m[1])) return null;
|
|
2850
2942
|
return join12(enginesRoot, "build", m[1]);
|
|
2851
2943
|
}
|
|
2852
2944
|
function pickGenerator(hasNinja, isWindows) {
|
|
@@ -2998,7 +3090,7 @@ async function findVcvarsall() {
|
|
|
2998
3090
|
try {
|
|
2999
3091
|
const programFilesX86 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
|
|
3000
3092
|
const vswhere = join12(programFilesX86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
|
3001
|
-
const { stdout } = await
|
|
3093
|
+
const { stdout } = await execFileP8(
|
|
3002
3094
|
vswhere,
|
|
3003
3095
|
["-latest", "-products", "*", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-find", "VC\\Auxiliary\\Build\\vcvarsall.bat"],
|
|
3004
3096
|
{ timeout: 8e3, windowsHide: true, maxBuffer: 1024 * 1024 }
|
|
@@ -3300,11 +3392,19 @@ var NotFoundError = class extends Error {
|
|
|
3300
3392
|
}
|
|
3301
3393
|
};
|
|
3302
3394
|
var NameTakenError = class extends Error {
|
|
3303
|
-
constructor() {
|
|
3304
|
-
super(
|
|
3395
|
+
constructor(holder, incoming) {
|
|
3396
|
+
super(nameTakenMessage(holder, incoming));
|
|
3305
3397
|
this.name = "NameTakenError";
|
|
3306
3398
|
}
|
|
3307
3399
|
};
|
|
3400
|
+
function nameTakenMessage(holder, incoming) {
|
|
3401
|
+
if (!holder) return "Name already in use \u2014 choose a different name.";
|
|
3402
|
+
const base2 = `Name already in use by "${holder.name}" \u2014 choose a different name.`;
|
|
3403
|
+
const held = holder.sourceBranch?.trim();
|
|
3404
|
+
const wanted = incoming?.sourceBranch?.trim();
|
|
3405
|
+
const anotherBranchOfTheSameRepo = !!held && !!wanted && held !== wanted && sameRepo(holder.sourceRepo, incoming?.sourceRepo);
|
|
3406
|
+
return anotherBranchOfTheSameRepo ? `${base2} It is a build of branch "${held}"; a build of "${wanted}" is a separate engine and needs its own name.` : base2;
|
|
3407
|
+
}
|
|
3308
3408
|
var Registry = class {
|
|
3309
3409
|
constructor(store2) {
|
|
3310
3410
|
this.store = store2;
|
|
@@ -3323,7 +3423,7 @@ var Registry = class {
|
|
|
3323
3423
|
}
|
|
3324
3424
|
async add(name, binPath, source) {
|
|
3325
3425
|
const finalName = name.trim() || "llama-server";
|
|
3326
|
-
this.assertNameFree(finalName);
|
|
3426
|
+
this.assertNameFree(finalName, source);
|
|
3327
3427
|
const pr = await probe(binPath);
|
|
3328
3428
|
const sourceRepo = source?.sourceRepo?.trim() || void 0;
|
|
3329
3429
|
const sourceBranch = source?.sourceBranch?.trim() || void 0;
|
|
@@ -3343,19 +3443,21 @@ var Registry = class {
|
|
|
3343
3443
|
...sourcePatchUrl ? { sourcePatchUrl } : {}
|
|
3344
3444
|
};
|
|
3345
3445
|
this.store.update((c) => {
|
|
3346
|
-
|
|
3446
|
+
const holder = this.nameHolder(c.engines, finalName);
|
|
3447
|
+
if (holder) throw new NameTakenError(holder, source);
|
|
3347
3448
|
c.engines.push(eng);
|
|
3348
3449
|
if (!c.activeEngineId) c.activeEngineId = eng.id;
|
|
3349
3450
|
});
|
|
3350
3451
|
return { engine: eng, warning: pr.version === "unknown" ? "no_version" : void 0 };
|
|
3351
3452
|
}
|
|
3352
|
-
/**
|
|
3353
|
-
|
|
3453
|
+
/** The registered engine that already uses `name` (case-insensitive, trimmed), if any. */
|
|
3454
|
+
nameHolder(engines, name) {
|
|
3354
3455
|
const n = name.trim().toLowerCase();
|
|
3355
|
-
return engines.
|
|
3456
|
+
return engines.find((e) => e.name.trim().toLowerCase() === n);
|
|
3356
3457
|
}
|
|
3357
|
-
assertNameFree(name) {
|
|
3358
|
-
|
|
3458
|
+
assertNameFree(name, incoming) {
|
|
3459
|
+
const holder = this.nameHolder(this.store.snapshot().engines, name);
|
|
3460
|
+
if (holder) throw new NameTakenError(holder, incoming);
|
|
3359
3461
|
}
|
|
3360
3462
|
/** Register an MLX engine (kind='mlx'). No llama-server probe — the binPath is
|
|
3361
3463
|
* a venv python, not a llama-server, so capabilities/flags don't apply. */
|
|
@@ -5177,9 +5279,9 @@ ${e.message}`, timedOut });
|
|
|
5177
5279
|
resolve6({ exitCode, stdout, stderr, timedOut });
|
|
5178
5280
|
};
|
|
5179
5281
|
const armGrace = (ms) => {
|
|
5180
|
-
const
|
|
5282
|
+
const capped2 = hardDeadlineAt === void 0 ? ms : Math.max(0, Math.min(ms, hardDeadlineAt - Date.now()));
|
|
5181
5283
|
if (graceTimer) clearTimeout(graceTimer);
|
|
5182
|
-
graceTimer = setTimeout(finish,
|
|
5284
|
+
graceTimer = setTimeout(finish, capped2);
|
|
5183
5285
|
};
|
|
5184
5286
|
const finishIfDrained = () => {
|
|
5185
5287
|
if (!exited || settled) return;
|
|
@@ -5292,7 +5394,7 @@ function parseClaudeCliStreamJson(stdout) {
|
|
|
5292
5394
|
|
|
5293
5395
|
// src/cli-launch.ts
|
|
5294
5396
|
import { spawn as spawn4 } from "child_process";
|
|
5295
|
-
import { homedir as
|
|
5397
|
+
import { homedir as homedir3 } from "os";
|
|
5296
5398
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
5297
5399
|
import { join as join15, dirname as dirname7 } from "path";
|
|
5298
5400
|
|
|
@@ -5465,7 +5567,7 @@ function resolveModelKey(models, input) {
|
|
|
5465
5567
|
return null;
|
|
5466
5568
|
}
|
|
5467
5569
|
var realFs = {
|
|
5468
|
-
home:
|
|
5570
|
+
home: homedir3(),
|
|
5469
5571
|
readFile: (p) => readFile(p, "utf8"),
|
|
5470
5572
|
writeFile: (p, data) => writeFile(p, data, "utf8"),
|
|
5471
5573
|
mkdir: async (p) => {
|
|
@@ -7875,7 +7977,7 @@ var AppUpdateChecker = class {
|
|
|
7875
7977
|
};
|
|
7876
7978
|
|
|
7877
7979
|
// src/app-update-apply.ts
|
|
7878
|
-
import { execFile as
|
|
7980
|
+
import { execFile as execFile11, spawn as spawn6 } from "child_process";
|
|
7879
7981
|
import { existsSync as existsSync17, openSync as openSync2, readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
|
|
7880
7982
|
import { dirname as dirname8, join as join18, resolve as resolve2 } from "path";
|
|
7881
7983
|
import { fileURLToPath } from "url";
|
|
@@ -7972,7 +8074,7 @@ async function npmGlobalRoot() {
|
|
|
7972
8074
|
if (npmRootCache) return npmRootCache.value;
|
|
7973
8075
|
const value = await new Promise((res) => {
|
|
7974
8076
|
const cmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
7975
|
-
|
|
8077
|
+
execFile11(cmd, ["root", "-g"], { timeout: 1e4, windowsHide: true }, (e, stdout) => {
|
|
7976
8078
|
if (e) return res(null);
|
|
7977
8079
|
const out = String(stdout).trim();
|
|
7978
8080
|
res(out || null);
|
|
@@ -10168,9 +10270,9 @@ async function loadPrimaryModel(opts, { manager: manager2, comfy: comfy2, modelR
|
|
|
10168
10270
|
|
|
10169
10271
|
// src/models/hf-cache.ts
|
|
10170
10272
|
import { existsSync as existsSync20, mkdirSync as mkdirSync8 } from "fs";
|
|
10171
|
-
import { homedir as
|
|
10273
|
+
import { homedir as homedir4 } from "os";
|
|
10172
10274
|
import { join as join22 } from "path";
|
|
10173
|
-
function hfHubCacheDir(env = process.env, home =
|
|
10275
|
+
function hfHubCacheDir(env = process.env, home = homedir4()) {
|
|
10174
10276
|
const explicit = env.HUGGINGFACE_HUB_CACHE;
|
|
10175
10277
|
if (explicit && explicit.trim()) return explicit;
|
|
10176
10278
|
const hfHome = env.HF_HOME;
|
|
@@ -13703,7 +13805,7 @@ function repoSubdir(repo) {
|
|
|
13703
13805
|
}
|
|
13704
13806
|
|
|
13705
13807
|
// src/bench/bench.ts
|
|
13706
|
-
import { execFile as
|
|
13808
|
+
import { execFile as execFile12 } from "child_process";
|
|
13707
13809
|
import { readFileSync as readFileSync11 } from "fs";
|
|
13708
13810
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
13709
13811
|
|
|
@@ -16012,7 +16114,7 @@ function kvSpeedAdvisory(tps, currentKv, supportedKvTypes) {
|
|
|
16012
16114
|
function readNvidiaVramMb() {
|
|
16013
16115
|
return new Promise((resolve6) => {
|
|
16014
16116
|
try {
|
|
16015
|
-
|
|
16117
|
+
execFile12(
|
|
16016
16118
|
"nvidia-smi",
|
|
16017
16119
|
["--query-gpu=memory.used", "--format=csv,noheader,nounits"],
|
|
16018
16120
|
{ timeout: 8e3, windowsHide: true },
|
|
@@ -16045,7 +16147,7 @@ function parseRocmVramUsed(memJson) {
|
|
|
16045
16147
|
function readRocmVramMb() {
|
|
16046
16148
|
return new Promise((resolve6) => {
|
|
16047
16149
|
try {
|
|
16048
|
-
|
|
16150
|
+
execFile12("rocm-smi", ["--showmeminfo", "vram", "--json"], { timeout: 8e3, windowsHide: true }, (err9, stdout) => {
|
|
16049
16151
|
resolve6(err9 || !stdout ? null : parseRocmVramUsed(stdout));
|
|
16050
16152
|
});
|
|
16051
16153
|
} catch {
|
|
@@ -16065,7 +16167,7 @@ function readWddmSharedMb() {
|
|
|
16065
16167
|
if (process.platform !== "win32" || wddmSharedUnsupported) return Promise.resolve(null);
|
|
16066
16168
|
return new Promise((resolve6) => {
|
|
16067
16169
|
try {
|
|
16068
|
-
|
|
16170
|
+
execFile12(
|
|
16069
16171
|
"powershell",
|
|
16070
16172
|
["-NoProfile", "-NonInteractive", "-Command", WDDM_SHARED_PS],
|
|
16071
16173
|
{ timeout: 1e4, windowsHide: true },
|
|
@@ -16104,7 +16206,7 @@ function parseRocmGttUsed(memJson) {
|
|
|
16104
16206
|
function readRocmGttMb() {
|
|
16105
16207
|
return new Promise((resolve6) => {
|
|
16106
16208
|
try {
|
|
16107
|
-
|
|
16209
|
+
execFile12("rocm-smi", ["--showmeminfo", "gtt", "--json"], { timeout: 8e3, windowsHide: true }, (err9, stdout) => {
|
|
16108
16210
|
if (err9 || !stdout) return resolve6(null);
|
|
16109
16211
|
resolve6(parseRocmGttUsed(stdout));
|
|
16110
16212
|
});
|
|
@@ -19362,7 +19464,7 @@ __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
|
|
19362
19464
|
|
|
19363
19465
|
// src/api/routes.ts
|
|
19364
19466
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
19365
|
-
import { homedir as
|
|
19467
|
+
import { homedir as homedir5 } from "os";
|
|
19366
19468
|
|
|
19367
19469
|
// src/config/config-bounds.ts
|
|
19368
19470
|
var CONFIG_BOUNDS = {
|
|
@@ -22100,12 +22202,12 @@ function catalogEngine(id) {
|
|
|
22100
22202
|
}
|
|
22101
22203
|
|
|
22102
22204
|
// src/engines/cuda-provision.ts
|
|
22103
|
-
import { execFile as
|
|
22205
|
+
import { execFile as execFile13 } from "child_process";
|
|
22104
22206
|
import { cpSync as cpSync2, existsSync as existsSync24, mkdirSync as mkdirSync14, readdirSync as readdirSync8, rmSync as rmSync13 } from "fs";
|
|
22105
22207
|
import { tmpdir } from "os";
|
|
22106
22208
|
import { join as join30 } from "path";
|
|
22107
|
-
import { promisify as
|
|
22108
|
-
var
|
|
22209
|
+
import { promisify as promisify9 } from "util";
|
|
22210
|
+
var execFileP9 = promisify9(execFile13);
|
|
22109
22211
|
var REDIST_BASE = "https://developer.download.nvidia.com/compute/cuda/redist/";
|
|
22110
22212
|
var CUDA_REQUIRED_COMPONENTS = ["cuda_nvcc", "cuda_cudart", "libcublas", "cuda_cccl"];
|
|
22111
22213
|
var CUDA_OPTIONAL_COMPONENTS = ["libnvvm", "cuda_crt"];
|
|
@@ -22121,7 +22223,7 @@ function cmpMajorMinor(a, b) {
|
|
|
22121
22223
|
}
|
|
22122
22224
|
async function driverMaxCuda() {
|
|
22123
22225
|
try {
|
|
22124
|
-
const { stdout } = await
|
|
22226
|
+
const { stdout } = await execFileP9("nvidia-smi", [], { timeout: 8e3, windowsHide: true, maxBuffer: 1024 * 1024 });
|
|
22125
22227
|
const m = stdout.match(/CUDA Version:\s*([\d.]+)/i);
|
|
22126
22228
|
return m ? m[1] : null;
|
|
22127
22229
|
} catch {
|
|
@@ -22283,7 +22385,7 @@ function recommendEngines(p, engines) {
|
|
|
22283
22385
|
}
|
|
22284
22386
|
|
|
22285
22387
|
// src/sysinfo/usage.ts
|
|
22286
|
-
import { execFile as
|
|
22388
|
+
import { execFile as execFile14, spawn as spawn8 } from "child_process";
|
|
22287
22389
|
import { existsSync as existsSync25, readFileSync as readFileSync15, readdirSync as readdirSync9 } from "fs";
|
|
22288
22390
|
import os2 from "os";
|
|
22289
22391
|
|
|
@@ -22533,7 +22635,7 @@ var MAX_CONSECUTIVE_FAILURES = 3;
|
|
|
22533
22635
|
function run(cmd, args) {
|
|
22534
22636
|
return new Promise((resolve6, reject) => {
|
|
22535
22637
|
try {
|
|
22536
|
-
|
|
22638
|
+
execFile14(cmd, args, { timeout: READER_TIMEOUT_MS, windowsHide: true, maxBuffer: 4 * 1024 * 1024 }, (err9, stdout) => {
|
|
22537
22639
|
if (err9) reject(err9);
|
|
22538
22640
|
else resolve6(String(stdout ?? ""));
|
|
22539
22641
|
});
|
|
@@ -23851,10 +23953,8 @@ function registerApi(app2, d) {
|
|
|
23851
23953
|
enabled = regEngines.some((x) => x.kind === "llamafile");
|
|
23852
23954
|
}
|
|
23853
23955
|
const srcEng = e.excludeFromSourceMatch ? void 0 : findEngineForCatalogEntry(regEngines, e, branchParam);
|
|
23854
|
-
|
|
23855
|
-
|
|
23856
|
-
sourceBinPath = catalogBranchesToScan(e, branchParam).map((branch) => sourceBuildBinary(enginesRoot, e.homepage, branch, e.sourceCommit)).find((bin) => bin !== null) ?? void 0;
|
|
23857
|
-
}
|
|
23956
|
+
const onDisk = !srcEng && !e.excludeFromSourceMatch ? findCatalogBuildOnDisk(enginesRoot, e, branchParam) : void 0;
|
|
23957
|
+
const sourceBinPath = srcEng?.binPath ?? onDisk?.binPath;
|
|
23858
23958
|
const sourceBuilt = !!srcEng || !!sourceBinPath;
|
|
23859
23959
|
if (srcEng) {
|
|
23860
23960
|
installed2 = true;
|
|
@@ -23869,7 +23969,7 @@ function registerApi(app2, d) {
|
|
|
23869
23969
|
enabled,
|
|
23870
23970
|
sourceBuilt,
|
|
23871
23971
|
sourceEngineId: srcEng?.id,
|
|
23872
|
-
sourceBranch: srcEng?.sourceBranch ?? "",
|
|
23972
|
+
sourceBranch: srcEng?.sourceBranch ?? onDisk?.branch ?? "",
|
|
23873
23973
|
sourceBinPath: sourceBinPath ?? ""
|
|
23874
23974
|
};
|
|
23875
23975
|
});
|
|
@@ -23954,6 +24054,12 @@ function registerApi(app2, d) {
|
|
|
23954
24054
|
const enginesRoot = join34(d.store.dir(), "engines");
|
|
23955
24055
|
const toolchainDirs = d.store.snapshot().build.toolchainDirs;
|
|
23956
24056
|
const buildRoot = join34(enginesRoot, "build", buildDirName(repoUrl, branch, commit));
|
|
24057
|
+
const engines = d.registry.list().engines;
|
|
24058
|
+
const conflict = findNameConflict(engines, name, { buildRoot, sourceRepo: repoUrl, sourceBranch: branch, sourceCommit: commit });
|
|
24059
|
+
if (conflict) return err5(c, 400, "name_already_taken", nameTakenMessage(conflict, { sourceRepo: repoUrl, sourceBranch: branch }));
|
|
24060
|
+
const running2 = d.registry.active();
|
|
24061
|
+
if (running2 && engineBusy(d) && isEngineInBuildDir(running2.binPath, buildRoot))
|
|
24062
|
+
return err5(c, 409, "engine_in_use", `Stop "${running2.name}" before rebuilding it \u2014 the rebuild replaces its files.`);
|
|
23957
24063
|
const ac = new AbortController();
|
|
23958
24064
|
buildAbort = ac;
|
|
23959
24065
|
d.build.start(name ?? repoUrl);
|
|
@@ -24239,10 +24345,11 @@ function registerApi(app2, d) {
|
|
|
24239
24345
|
const { engine, warning } = await d.registry.add(b.name ?? "", b.binPath, {
|
|
24240
24346
|
sourceRepo: b.sourceRepo,
|
|
24241
24347
|
sourceBranch: b.sourceBranch,
|
|
24242
|
-
sourceCommit: b.sourceCommit
|
|
24348
|
+
sourceCommit: b.sourceCommit,
|
|
24349
|
+
sourcePatchUrl: b.sourcePatchUrl
|
|
24243
24350
|
});
|
|
24244
24351
|
if (!isCatalogRepo(b.sourceRepo)) {
|
|
24245
|
-
d.registry.recordCustomSource({ name: engine.name, binPath: engine.binPath, kind: engine.kind, sourceRepo: b.sourceRepo, sourceBranch: b.sourceBranch, sourceCommit: b.sourceCommit });
|
|
24352
|
+
d.registry.recordCustomSource({ name: engine.name, binPath: engine.binPath, kind: engine.kind, sourceRepo: b.sourceRepo, sourceBranch: b.sourceBranch, sourceCommit: b.sourceCommit, sourcePatchUrl: b.sourcePatchUrl });
|
|
24246
24353
|
}
|
|
24247
24354
|
return c.json({ ...engine, warning: warning ?? null }, 201);
|
|
24248
24355
|
} catch (e) {
|
|
@@ -24470,7 +24577,7 @@ function registerApi(app2, d) {
|
|
|
24470
24577
|
if (raw === FS_DRIVES_ROOT && process.platform === "win32") {
|
|
24471
24578
|
return c.json({ path: FS_DRIVES_ROOT, parent: null, entries: listWindowsDrives() });
|
|
24472
24579
|
}
|
|
24473
|
-
const target = raw ? resolve5(raw) :
|
|
24580
|
+
const target = raw ? resolve5(raw) : homedir5();
|
|
24474
24581
|
let real;
|
|
24475
24582
|
try {
|
|
24476
24583
|
real = realpathSync3(target);
|
|
@@ -25011,7 +25118,7 @@ function registerApi(app2, d) {
|
|
|
25011
25118
|
};
|
|
25012
25119
|
const isMemoryServer = server2.transport === "stdio" && (server2.command?.includes("server-memory") || server2.args?.some((a) => a.includes("server-memory")));
|
|
25013
25120
|
if (isMemoryServer && !server2.env?.MEMORY_FILE_PATH) {
|
|
25014
|
-
server2.env = { ...server2.env, MEMORY_FILE_PATH: join34(
|
|
25121
|
+
server2.env = { ...server2.env, MEMORY_FILE_PATH: join34(homedir5(), ".turbollm", "mcp-memory.jsonl") };
|
|
25015
25122
|
}
|
|
25016
25123
|
d.store.update((cfg2) => {
|
|
25017
25124
|
cfg2.mcp.servers.push(server2);
|
|
@@ -25820,8 +25927,8 @@ function isValidMachineName(name) {
|
|
|
25820
25927
|
}
|
|
25821
25928
|
function sanitizeMachineName(raw) {
|
|
25822
25929
|
const collapsed = (raw ?? "").replace(/[\\/]+/g, "-").replace(/\s+/g, " ").trim();
|
|
25823
|
-
const
|
|
25824
|
-
return /[^\s-]/.test(
|
|
25930
|
+
const capped2 = collapsed.slice(0, MAX_NAME_LEN).trim();
|
|
25931
|
+
return /[^\s-]/.test(capped2) ? capped2 : FALLBACK_MACHINE_NAME;
|
|
25825
25932
|
}
|
|
25826
25933
|
function uniqueMachineName(desired, taken) {
|
|
25827
25934
|
const used = /* @__PURE__ */ new Set();
|
|
@@ -25911,7 +26018,7 @@ function redactDownload(rec) {
|
|
|
25911
26018
|
// src/link/link-client.ts
|
|
25912
26019
|
var DEFAULT_TIMEOUT_MS = 8e3;
|
|
25913
26020
|
var ERROR_CODE = /^[a-z][a-z0-9_]{0,63}$/i;
|
|
25914
|
-
async function
|
|
26021
|
+
async function failureDetail2(res) {
|
|
25915
26022
|
if (!(res.headers.get("content-type") ?? "").includes("application/json")) return {};
|
|
25916
26023
|
try {
|
|
25917
26024
|
const body10 = await res.json();
|
|
@@ -26136,7 +26243,7 @@ var LinkClient = class {
|
|
|
26136
26243
|
...json === void 0 ? {} : { body: JSON.stringify(json) },
|
|
26137
26244
|
signal: AbortSignal.timeout(this.timeoutMs)
|
|
26138
26245
|
});
|
|
26139
|
-
if (!res.ok) return { kind: "http", status: res.status, ...await
|
|
26246
|
+
if (!res.ok) return { kind: "http", status: res.status, ...await failureDetail2(res) };
|
|
26140
26247
|
const ct = res.headers.get("content-type") ?? "";
|
|
26141
26248
|
if (!ct.includes("application/json")) return { kind: "network" };
|
|
26142
26249
|
const parsed = await res.json();
|