turbollm 1.11.6 → 1.11.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 +200 -89
- package/dist/webdist/assets/{AgentEditPage-Dx-o_9xV.js → AgentEditPage-BGvwitPD.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-CJyYbKoe.js → ChatScreen-DiX11uki.js} +14 -14
- package/dist/webdist/assets/CodeComposer-AES4owAQ.js +1 -0
- package/dist/webdist/assets/CodeHomeScreen-QfpFwCzB.js +1 -0
- package/dist/webdist/assets/{CodeSessionScreen-aXt0wkYo.js → CodeSessionScreen-DAlhPGXm.js} +13 -13
- package/dist/webdist/assets/CustomizeScreen-CZX_h6dR.js +4 -0
- package/dist/webdist/assets/DeveloperScreen-CnkH0DEh.js +1 -0
- package/dist/webdist/assets/EnginesScreen-BiMepnbQ.js +7 -0
- package/dist/webdist/assets/ModelDetailDialog-D4QR8T4-.js +1 -0
- package/dist/webdist/assets/ModelLoadMenu-BkDAFDCi.js +1 -0
- package/dist/webdist/assets/{ModelsScreen-dgX9WkCc.js → ModelsScreen-DD3hbiQV.js} +2 -2
- package/dist/webdist/assets/OnboardingScreen-B0uzd0eM.js +1 -0
- package/dist/webdist/assets/RoutineEditPage-CpIh_EbV.js +1 -0
- package/dist/webdist/assets/{RoutinesPanel-BLkW0xEt.js → RoutinesPanel-CH_PGsVT.js} +1 -1
- package/dist/webdist/assets/SettingsScreen-Bg065mfp.js +2 -0
- package/dist/webdist/assets/{SidebarResizeHandle-D4vXg1kG.js → SidebarResizeHandle-C6S5ad6l.js} +1 -1
- package/dist/webdist/assets/{SkillEditPage-LIPltIRO.js → SkillEditPage-DRPrL9O8.js} +1 -1
- package/dist/webdist/assets/TokensScreen--lhCAkGZ.js +1 -0
- package/dist/webdist/assets/{ToolApprovalBar-DQMujhi2.js → ToolApprovalBar-CM2lIUU_.js} +17 -17
- package/dist/webdist/assets/WorkspaceScreen-n1cWfmM_.js +1 -0
- package/dist/webdist/assets/{abnfDiagram-N423BO3Z-BYrN5G9N.js → abnfDiagram-N423BO3Z-BYVO4f28.js} +1 -1
- package/dist/webdist/assets/agent-api-C89aA4D7.js +1 -0
- package/dist/webdist/assets/{alert-dialog-HmXAwXqa.js → alert-dialog-UMvxymh4.js} +1 -1
- package/dist/webdist/assets/{arc-ldMwjnRq.js → arc-D7irs2Hk.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-T3A2C74G-BIhygyZB.js → architectureDiagram-T3A2C74G-gAwEl_Xi.js} +1 -1
- package/dist/webdist/assets/{arrow-left-C8VmnG_w.js → arrow-left-_wC4KLqk.js} +1 -1
- package/dist/webdist/assets/{badge-0BCEwa1g.js → badge-BuAx7koW.js} +1 -1
- package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-B2kPcqcg.js → blockDiagram-VBNYF7ZC-Bblt20tw.js} +1 -1
- package/dist/webdist/assets/{bot-Brhq4CvP.js → bot-fcj_aHyQ.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-5PPSVZJV-Bg3UFvsz.js → c4Diagram-5PPSVZJV-D7Q3ec48.js} +1 -1
- package/dist/webdist/assets/channel-gSV75kzz.js +1 -0
- package/dist/webdist/assets/{chat-api-0uk0Mc_u.js → chat-api-BVCm_8Ks.js} +1 -1
- package/dist/webdist/assets/{chat-queries-DsoI-ftK.js → chat-queries-BUgnyIUd.js} +1 -1
- package/dist/webdist/assets/{chevron-down-BASbdbtb.js → chevron-down-BkddYg28.js} +1 -1
- package/dist/webdist/assets/{chevron-left-Cv4jCFYH.js → chevron-left-SDuXwrOI.js} +1 -1
- package/dist/webdist/assets/{chevron-right-CAxvc8lx.js → chevron-right-DKBPXPzE.js} +1 -1
- package/dist/webdist/assets/{chunk-2GRJ4B5K-HOJ-zI2K.js → chunk-2GRJ4B5K-EtPZMHzO.js} +1 -1
- package/dist/webdist/assets/{chunk-2Q5K7J3B-CWYUQKvA.js → chunk-2Q5K7J3B-Ik0PEYmG.js} +1 -1
- package/dist/webdist/assets/{chunk-5RXB4S5H-C54g8FMc.js → chunk-5RXB4S5H-9KSz7Ttl.js} +1 -1
- package/dist/webdist/assets/{chunk-5VM5RSS4-UEjBIEh6.js → chunk-5VM5RSS4-BHe_3qZi.js} +1 -1
- package/dist/webdist/assets/{chunk-6Q2QTUOP-D76HUQ1c.js → chunk-6Q2QTUOP-XLnKgWIO.js} +1 -1
- package/dist/webdist/assets/{chunk-GF5L2VYU-C7bGhXb0.js → chunk-GF5L2VYU-lC5PVZgQ.js} +1 -1
- package/dist/webdist/assets/{chunk-JWPE2WC7-CoIEx4c2.js → chunk-JWPE2WC7-KW-ZUP6l.js} +1 -1
- package/dist/webdist/assets/{chunk-KBJHAD2P-BK5xyuR5.js → chunk-KBJHAD2P-BC9bhV7z.js} +1 -1
- package/dist/webdist/assets/{chunk-RYQCIY6F-ItoWBj7A.js → chunk-RYQCIY6F-YBRb11_w.js} +1 -1
- package/dist/webdist/assets/{chunk-XXDRQBXY-B8gm-Cx5.js → chunk-XXDRQBXY-CXAuPG1B.js} +1 -1
- package/dist/webdist/assets/{circle-check-fNp1-B5t.js → circle-check-shiw4etQ.js} +1 -1
- package/dist/webdist/assets/{circle-x-CuhNJ5mD.js → circle-x-C2YPDVGQ.js} +1 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-D8qDQO4q.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-D8qDQO4q.js +1 -0
- package/dist/webdist/assets/{common-DULL4Ra-.js → common-CjiQLhkZ.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-JH36ORCC-BKFiRS6Q.js → cose-bilkent-JH36ORCC-DIz6ZCkR.js} +1 -1
- package/dist/webdist/assets/{cynefin-VYW2F7L2-Ds6Re-sx.js → cynefin-VYW2F7L2-DYWxEAiP.js} +1 -1
- package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-BEKMr9S7.js → cynefinDiagram-MW4NZA55-C5Ia81Zp.js} +1 -1
- package/dist/webdist/assets/{dagre-VZM6K2ZE-Dg5dqY0j.js → dagre-VZM6K2ZE-Cq0KzAuY.js} +1 -1
- package/dist/webdist/assets/{diagram-7IWD3JNH-CzaTqrpm.js → diagram-7IWD3JNH-CvG1y9p-.js} +1 -1
- package/dist/webdist/assets/{diagram-B4RE2ZJO-_k3SLxsm.js → diagram-B4RE2ZJO-B-ULHQ0_.js} +1 -1
- package/dist/webdist/assets/{diagram-LBJQPF4R-CkDl750w.js → diagram-LBJQPF4R-CR3L5Nh8.js} +1 -1
- package/dist/webdist/assets/{diagram-Q27KOJAE-BOSwNYKq.js → diagram-Q27KOJAE-BQOTyQGi.js} +1 -1
- package/dist/webdist/assets/{diagram-UB23O5K3-BzxlhiFN.js → diagram-UB23O5K3-DQ2KgLSn.js} +1 -1
- package/dist/webdist/assets/{dropdown-menu-gf83Mrmq.js → dropdown-menu-DOmXZgfx.js} +1 -1
- package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-DY3DNIyj.js → ebnfDiagram-BXEA7PRR-CFALT3Zl.js} +1 -1
- package/dist/webdist/assets/{erDiagram-JOGREHBK-Dfj3TSix.js → erDiagram-JOGREHBK-VjNsvocf.js} +1 -1
- package/dist/webdist/assets/{external-link-COQ5Bvdu.js → external-link-ByGxbl7O.js} +1 -1
- package/dist/webdist/assets/{file-text-DSqIarKD.js → file-text-C6vO4199.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-UKHOOZJN-BrgYXyS3.js → flowDiagram-UKHOOZJN-Beyki8d9.js} +1 -1
- package/dist/webdist/assets/{folder-input-CzY2E0mX.js → folder-input-y0fUY1f7.js} +1 -1
- package/dist/webdist/assets/{folder-plus-k0yyudVG.js → folder-plus-DkfhYtyz.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-cVx7lSJ0.js → ganttDiagram-PKOTCBZU-B2_peWgr.js} +1 -1
- package/dist/webdist/assets/{git-branch-BZs6d67V.js → git-branch-DuR9np_b.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-DL40w8Lh.js → gitGraphDiagram-DS77QQ5N-Qa2BuwG1.js} +1 -1
- package/dist/webdist/assets/index-CW8WcIQU.js +13 -0
- package/dist/webdist/assets/index-re3p5oWG.css +1 -0
- package/dist/webdist/assets/{infoDiagram-6WML65LV-BR0gJe4Y.js → infoDiagram-6WML65LV-Dnf7bkp-.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-DsfBW9fY.js → ishikawaDiagram-WSZJBQD7-DbYuKfij.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-DWGKgSV9.js → journeyDiagram-NVQOT4AX-BsgYXqIT.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-27J2QSJJ-DwYsMcKD.js → kanban-definition-27J2QSJJ-hthkisM6.js} +1 -1
- package/dist/webdist/assets/{linear-CVvnTc0p.js → linear-CrK5bkNK.js} +1 -1
- package/dist/webdist/assets/link-queries-BsEGbH_i.js +1 -0
- package/dist/webdist/assets/{lock-Br_GtUc9.js → lock-CT7BjvBa.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-Bcb-KMMg.js → mermaid.core-B4SxlakL.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-B2mkpjay.js → mindmap-definition-FAOFIHXS-3V4M8m1v.js} +1 -1
- package/dist/webdist/assets/{monitor-D2MJSfbb.js → monitor-DxHM879o.js} +1 -1
- package/dist/webdist/assets/{pegDiagram-VL7TDLO6-BmRtrO9J.js → pegDiagram-VL7TDLO6-CwgscHdz.js} +1 -1
- package/dist/webdist/assets/{pencil-B-DJIZK4.js → pencil-Dw_K95nc.js} +1 -1
- package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-nc7aZNlT.js → pieDiagram-7S7Q4E2Y-CTqLPafl.js} +1 -1
- package/dist/webdist/assets/{plus-CGMFwNIS.js → plus-BJaMtjpS.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-pKkPYA7l.js → quadrantDiagram-CIZ2JOQS-LbPp1RsB.js} +1 -1
- package/dist/webdist/assets/{railroadDiagram-AXF67PYL-CAx7_Jhl.js → railroadDiagram-AXF67PYL-D_lHoKD_.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-CSKOgioB.js → refresh-cw-DCeVBFDX.js} +1 -1
- package/dist/webdist/assets/{remote-failure-B8pqD92H.js → remote-failure-MrvEI723.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-DXIG1oxz.js → requirementDiagram-LRYGKXZP-BY8tESBS.js} +1 -1
- package/dist/webdist/assets/{rocket-Ceqz17Tf.js → rocket--8UI8L0H.js} +1 -1
- package/dist/webdist/assets/{rotate-ccw-Cv5TSXuQ.js → rotate-ccw-DDrREh1t.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-DYy_y13W.js → sankeyDiagram-W5VNT64P-CaqTeTzq.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-uJNlTfiz.js → sequenceDiagram-SI44F4Z6-QcHtlcPm.js} +1 -1
- package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-C5IPisNr.js → sizeCapture-X5ZJPWSS-yeiugSLg.js} +1 -1
- package/dist/webdist/assets/{skeleton-B6OINYhc.js → skeleton-CQ7NgTrJ.js} +1 -1
- package/dist/webdist/assets/{sliders-horizontal-CM38hmNN.js → sliders-horizontal-C3TczbRD.js} +1 -1
- package/dist/webdist/assets/{sparkles-Z-pONu31.js → sparkles-DfqpHE7U.js} +1 -1
- package/dist/webdist/assets/{star-DMVePf7b.js → star-C6ne6wrl.js} +1 -1
- package/dist/webdist/assets/{stateDiagram-OKZ733FA-Da9REfgi.js → stateDiagram-OKZ733FA-Blw0P-6b.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-CQ6A1wj6.js +1 -0
- package/dist/webdist/assets/{swimlanes-SLNWSIFB-DdoEQTQk.js → swimlanes-SLNWSIFB-C1R-sQ9k.js} +2 -2
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-DhsOFzrR.js +8 -0
- package/dist/webdist/assets/{switch-DPFLAHpN.js → switch-D6oHCJqM.js} +1 -1
- package/dist/webdist/assets/{terminal-DFhvh4k1.js → terminal-Dm1JH1oE.js} +1 -1
- package/dist/webdist/assets/{timeline-definition-Z64GVDOM-D2oRIsdl.js → timeline-definition-Z64GVDOM-BH0_p5Yt.js} +1 -1
- package/dist/webdist/assets/{trash-2-D1G8EUUf.js → trash-2-wMkmxUa8.js} +1 -1
- package/dist/webdist/assets/{triangle-alert-ChRtySvU.js → triangle-alert-D_2cm9oo.js} +1 -1
- package/dist/webdist/assets/{useIsDesktop-BAU4oGSf.js → useIsDesktop-CO17oT9c.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-T6HMQDX7-tDiJA0Ny.js → vennDiagram-T6HMQDX7-Bo_z3tkW.js} +1 -1
- package/dist/webdist/assets/vram-CyjPY3u5.js +1 -0
- package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y-CM3_MwtW.js → wardleyDiagram-T6FBY63Y-CcwefiuP.js} +1 -1
- package/dist/webdist/assets/{wrench-CTkAByRe.js → wrench-Bhfk5lOr.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-BbPp91bK.js → xychartDiagram-ELKLHX3M-DO2mBi4s.js} +1 -1
- package/dist/webdist/index.html +2 -2
- package/package.json +1 -1
- package/dist/webdist/assets/CodeComposer-DxV-5HZh.js +0 -1
- package/dist/webdist/assets/CodeHomeScreen-CM_cnOH6.js +0 -1
- package/dist/webdist/assets/CustomizeScreen-CuzDUaab.js +0 -4
- package/dist/webdist/assets/DeveloperScreen-Dxd3Z-e3.js +0 -1
- package/dist/webdist/assets/EnginesScreen-BhiM2yFz.js +0 -7
- package/dist/webdist/assets/ModelDetailDialog-BoSJpfRl.js +0 -1
- package/dist/webdist/assets/ModelLoadMenu-ETcY6o29.js +0 -1
- package/dist/webdist/assets/OnboardingScreen-k7JIbQnG.js +0 -1
- package/dist/webdist/assets/RoutineEditPage-LfAmG_ti.js +0 -1
- package/dist/webdist/assets/SettingsScreen-_UB8piYj.js +0 -2
- package/dist/webdist/assets/TokensScreen-TGdk-Q_d.js +0 -1
- package/dist/webdist/assets/WorkspaceScreen-X8nfASH9.js +0 -1
- package/dist/webdist/assets/agent-api-LPVSxusw.js +0 -1
- package/dist/webdist/assets/channel-DxXBs2vE.js +0 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-DVemFTdO.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-DVemFTdO.js +0 -1
- package/dist/webdist/assets/index-Bf0TXA7a.css +0 -1
- package/dist/webdist/assets/index-C6HXxZFI.js +0 -13
- package/dist/webdist/assets/link-api-Dr2NcVl2.js +0 -1
- package/dist/webdist/assets/link-queries-CKJKivJv.js +0 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-CxJUIzH9.js +0 -1
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-CstzYf1d.js +0 -8
- package/dist/webdist/assets/vram-Bc_Twhr0.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -127,6 +127,7 @@ function defaultConfig() {
|
|
|
127
127
|
benchResults: {},
|
|
128
128
|
vramHeadroomMb: VRAM_HEADROOM_DEFAULT_MB,
|
|
129
129
|
lastLoaded: { modelKey: "", engineId: "" },
|
|
130
|
+
selectedRemoteModel: "",
|
|
130
131
|
autoLoadOnStart: false,
|
|
131
132
|
hf: { token: "" },
|
|
132
133
|
modelDefaults: { ctx: 8192, ngl: 99, imageMaxTokens: 0, maxTokens: 0 },
|
|
@@ -262,6 +263,7 @@ function normalize(c) {
|
|
|
262
263
|
c.hf = { ...d.hf, ...c.hf ?? {} };
|
|
263
264
|
c.modelDefaults = { ...d.modelDefaults, ...c.modelDefaults ?? {} };
|
|
264
265
|
c.lastLoaded = { ...d.lastLoaded, ...c.lastLoaded ?? {} };
|
|
266
|
+
if (typeof c.selectedRemoteModel !== "string") c.selectedRemoteModel = "";
|
|
265
267
|
c.apiKeys ??= [];
|
|
266
268
|
c.links ??= [];
|
|
267
269
|
c.engines ??= [];
|
|
@@ -7042,6 +7044,8 @@ ${list}
|
|
|
7042
7044
|
const refreshed = await fetchStatus(base2, _fetch);
|
|
7043
7045
|
if (refreshed) status = refreshed;
|
|
7044
7046
|
}
|
|
7047
|
+
} else if (status?.selectedRemoteModel && (await fetchGatewayModelIds(base2, _fetch)).includes(status.selectedRemoteModel)) {
|
|
7048
|
+
remoteModel = status.selectedRemoteModel;
|
|
7045
7049
|
} else if (!alreadyRunning) {
|
|
7046
7050
|
const models = await fetchModels(base2, _fetch);
|
|
7047
7051
|
if (models.length === 0) {
|
|
@@ -7085,7 +7089,7 @@ Open ${base2} \u2192 Models \u2192 Load a model, then run this again.
|
|
|
7085
7089
|
pinnedModel = status.model.key ?? model;
|
|
7086
7090
|
}
|
|
7087
7091
|
const parallelSlots = status.engine?.parallelSlots;
|
|
7088
|
-
const modelNote = modelKey ? `model: ${model}` : `using loaded model: ${model}`;
|
|
7092
|
+
const modelNote = modelKey ? `model: ${model}` : remoteModel ? `using selected remote model: ${model}` : `using loaded model: ${model}`;
|
|
7089
7093
|
process.stdout.write(`\u25B8 Launching ${spec.label} \u2192 TurboLLM (${modelNote}, ${base2})
|
|
7090
7094
|
`);
|
|
7091
7095
|
const libraryModels = spec.prepareConfig ? await fetchModels(base2, _fetch) : [];
|
|
@@ -9315,6 +9319,9 @@ function amdApuOnly(info = getSysInfo()) {
|
|
|
9315
9319
|
const amd = info.gpus.filter((g) => g.vendor === "amd");
|
|
9316
9320
|
return amd.length > 0 && amd.every((g) => g.unified);
|
|
9317
9321
|
}
|
|
9322
|
+
function unifiedMemoryOnly(info = getSysInfo()) {
|
|
9323
|
+
return info.gpus.length > 0 && info.gpus.every((g) => g.unified === true);
|
|
9324
|
+
}
|
|
9318
9325
|
function classifyVendor(name) {
|
|
9319
9326
|
const n = name.toLowerCase();
|
|
9320
9327
|
if (/nvidia|geforce|rtx|gtx|quadro|tesla/.test(n)) return "nvidia";
|
|
@@ -9450,7 +9457,8 @@ function parseRocmSmi(memJson, nameJson = "") {
|
|
|
9450
9457
|
const nameFields = names[card] ?? {};
|
|
9451
9458
|
const nameKey = Object.keys(nameFields).find((k) => /(Card Series|Card Model|Product Name|Device Name)/i.test(k));
|
|
9452
9459
|
const name = (nameKey ? String(nameFields[nameKey]).trim() : "") || "AMD Radeon GPU";
|
|
9453
|
-
|
|
9460
|
+
const integrated = isIntegratedGpuName(name);
|
|
9461
|
+
gpus.push({ name, vramMb: Math.round(bytes / 1e6), vendor: "amd", ...integrated ? { unified: true } : {} });
|
|
9454
9462
|
}
|
|
9455
9463
|
return gpus;
|
|
9456
9464
|
}
|
|
@@ -10112,9 +10120,22 @@ function reportChatBenchResult(d, ms, stats) {
|
|
|
10112
10120
|
} catch {
|
|
10113
10121
|
}
|
|
10114
10122
|
}
|
|
10115
|
-
|
|
10123
|
+
function resilientSink(sink) {
|
|
10124
|
+
let gone = false;
|
|
10125
|
+
const wrapped = async (ev) => {
|
|
10126
|
+
if (gone) return;
|
|
10127
|
+
try {
|
|
10128
|
+
await sink(ev);
|
|
10129
|
+
} catch {
|
|
10130
|
+
gone = true;
|
|
10131
|
+
}
|
|
10132
|
+
};
|
|
10133
|
+
return Object.assign(wrapped, { clientGone: () => gone });
|
|
10134
|
+
}
|
|
10135
|
+
async function runGeneration(d, rawEmit, ctx) {
|
|
10116
10136
|
const { db: db2 } = d;
|
|
10117
10137
|
const { convId, conv, assistantMsg, upstream, ac, thinkingBudget, reasoningEffort } = ctx;
|
|
10138
|
+
const emit2 = resilientSink(rawEmit);
|
|
10118
10139
|
const localAccounting = !upstream.remote;
|
|
10119
10140
|
const convS = conv.sampling ?? {};
|
|
10120
10141
|
const engineKind = d.registry.active()?.kind ?? "";
|
|
@@ -10190,6 +10211,8 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10190
10211
|
let aborted = false;
|
|
10191
10212
|
let engineFailed = false;
|
|
10192
10213
|
let liveOut = 0;
|
|
10214
|
+
let pendingParse = null;
|
|
10215
|
+
let lastPromptTotal = 0;
|
|
10193
10216
|
noteLocalActivity();
|
|
10194
10217
|
if (localAccounting) d.manager.generationStart();
|
|
10195
10218
|
try {
|
|
@@ -10242,7 +10265,10 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10242
10265
|
const reader = res.body.getReader();
|
|
10243
10266
|
const decoder = new TextDecoder();
|
|
10244
10267
|
let buf = "";
|
|
10245
|
-
const cancelReader = () =>
|
|
10268
|
+
const cancelReader = () => {
|
|
10269
|
+
void reader.cancel().catch(() => {
|
|
10270
|
+
});
|
|
10271
|
+
};
|
|
10246
10272
|
if (ac.signal.aborted) {
|
|
10247
10273
|
cancelReader();
|
|
10248
10274
|
} else {
|
|
@@ -10250,6 +10276,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10250
10276
|
}
|
|
10251
10277
|
let roundContent = "";
|
|
10252
10278
|
let parseState = initParseState();
|
|
10279
|
+
pendingParse = parseState;
|
|
10253
10280
|
let finishReason = "";
|
|
10254
10281
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
10255
10282
|
const announcedToolCalls = /* @__PURE__ */ new Set();
|
|
@@ -10271,6 +10298,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10271
10298
|
}
|
|
10272
10299
|
const pp = chunk.prompt_progress;
|
|
10273
10300
|
if (pp && pp.total) {
|
|
10301
|
+
lastPromptTotal = pp.total;
|
|
10274
10302
|
const pct = Math.round((pp.processed ?? 0) / pp.total * 100);
|
|
10275
10303
|
if (localAccounting) d.manager.setLiveGen({ phase: "prompt", pct, outputTokens: 0 });
|
|
10276
10304
|
await emit2({ event: "progress", data: { phase: "prompt", processed: pp.processed, total: pp.total, pct, tps: pp.tps ?? 0 } });
|
|
@@ -10310,6 +10338,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10310
10338
|
if (!raw_content) continue;
|
|
10311
10339
|
const { state: nextState, events: parseEvents } = feedChunk(parseState, raw_content);
|
|
10312
10340
|
parseState = nextState;
|
|
10341
|
+
pendingParse = parseState;
|
|
10313
10342
|
for (const ev of parseEvents) {
|
|
10314
10343
|
if (ev.type === "reasoning") {
|
|
10315
10344
|
if (!thinkStart) thinkStart = Date.now();
|
|
@@ -10328,6 +10357,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10328
10357
|
}
|
|
10329
10358
|
}
|
|
10330
10359
|
ac.signal.removeEventListener("abort", cancelReader);
|
|
10360
|
+
pendingParse = null;
|
|
10331
10361
|
for (const ev of flushState(parseState)) {
|
|
10332
10362
|
if (ev.type === "reasoning") {
|
|
10333
10363
|
fullReasoning += ev.text;
|
|
@@ -10480,13 +10510,17 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10480
10510
|
const reader = res.body.getReader();
|
|
10481
10511
|
const decoder = new TextDecoder();
|
|
10482
10512
|
let buf = "";
|
|
10483
|
-
const cancelReader = () =>
|
|
10513
|
+
const cancelReader = () => {
|
|
10514
|
+
void reader.cancel().catch(() => {
|
|
10515
|
+
});
|
|
10516
|
+
};
|
|
10484
10517
|
if (ac.signal.aborted) {
|
|
10485
10518
|
cancelReader();
|
|
10486
10519
|
} else {
|
|
10487
10520
|
ac.signal.addEventListener("abort", cancelReader, { once: true });
|
|
10488
10521
|
}
|
|
10489
10522
|
let parseState = initParseState();
|
|
10523
|
+
pendingParse = parseState;
|
|
10490
10524
|
roundLoop: while (true) {
|
|
10491
10525
|
const { done, value } = await reader.read();
|
|
10492
10526
|
if (done) break;
|
|
@@ -10505,6 +10539,8 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10505
10539
|
}
|
|
10506
10540
|
if (chunk.usage) finalUsage = chunk.usage;
|
|
10507
10541
|
if (chunk.timings) finalTimings = chunk.timings;
|
|
10542
|
+
const pp2 = chunk.prompt_progress;
|
|
10543
|
+
if (pp2?.total) lastPromptTotal = pp2.total;
|
|
10508
10544
|
const choices = chunk.choices;
|
|
10509
10545
|
if (!choices?.length) continue;
|
|
10510
10546
|
const delta = choices[0].delta ?? {};
|
|
@@ -10518,6 +10554,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10518
10554
|
if (!raw_content) continue;
|
|
10519
10555
|
const { state: nextState, events: parseEvents } = feedChunk(parseState, raw_content);
|
|
10520
10556
|
parseState = nextState;
|
|
10557
|
+
pendingParse = parseState;
|
|
10521
10558
|
for (const ev of parseEvents) {
|
|
10522
10559
|
if (ev.type === "reasoning") {
|
|
10523
10560
|
fullReasoning += ev.text;
|
|
@@ -10533,6 +10570,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10533
10570
|
}
|
|
10534
10571
|
}
|
|
10535
10572
|
ac.signal.removeEventListener("abort", cancelReader);
|
|
10573
|
+
pendingParse = null;
|
|
10536
10574
|
for (const ev of flushState(parseState)) {
|
|
10537
10575
|
if (ev.type === "reasoning") {
|
|
10538
10576
|
fullReasoning += ev.text;
|
|
@@ -10549,23 +10587,38 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10549
10587
|
aborted = isAbort;
|
|
10550
10588
|
if (!isAbort) {
|
|
10551
10589
|
engineFailed = true;
|
|
10552
|
-
|
|
10590
|
+
try {
|
|
10591
|
+
await emit2({ event: "error", data: { code: "engine_stopped", message: e.message } });
|
|
10592
|
+
} catch {
|
|
10593
|
+
}
|
|
10553
10594
|
}
|
|
10554
10595
|
} finally {
|
|
10555
10596
|
if (localAccounting) d.manager.generationEnd();
|
|
10556
10597
|
inflight.delete(convId);
|
|
10557
10598
|
}
|
|
10599
|
+
if (pendingParse) {
|
|
10600
|
+
for (const ev of flushState(pendingParse)) {
|
|
10601
|
+
if (ev.type === "reasoning") {
|
|
10602
|
+
fullReasoning += ev.text;
|
|
10603
|
+
} else {
|
|
10604
|
+
fullContent += ev.text;
|
|
10605
|
+
liveOut++;
|
|
10606
|
+
}
|
|
10607
|
+
}
|
|
10608
|
+
pendingParse = null;
|
|
10609
|
+
}
|
|
10558
10610
|
const totalMs = Date.now() - requestStart;
|
|
10559
10611
|
const thinkMs = thinkStart && thinkEnd ? thinkEnd - thinkStart : 0;
|
|
10560
10612
|
const ctxMax = upstream.ctxMax;
|
|
10561
10613
|
const genTokensFallback = finalUsage.completion_tokens || liveOut;
|
|
10614
|
+
const promptTokensFallback = finalUsage.prompt_tokens || lastPromptTotal;
|
|
10562
10615
|
const stats = {
|
|
10563
10616
|
ttftMs,
|
|
10564
10617
|
totalMs,
|
|
10565
10618
|
thinkMs,
|
|
10566
10619
|
// Full context occupancy: cache-reused prompt tokens still sit in the KV cache / context
|
|
10567
10620
|
// window (they're skipped only for recomputation), so they must stay counted here.
|
|
10568
|
-
ctxUsed:
|
|
10621
|
+
ctxUsed: promptTokensFallback + genTokensFallback,
|
|
10569
10622
|
ctxMax,
|
|
10570
10623
|
model: upstream.modelName,
|
|
10571
10624
|
aborted
|
|
@@ -10582,7 +10635,7 @@ After reviewing the search results, include a confidence assessment on a line by
|
|
|
10582
10635
|
stats.tps = finalTimings.predicted_per_second;
|
|
10583
10636
|
stats.cachedTokens = cachedExplicit ?? Math.max(0, (fullPrompt || processed) - processed);
|
|
10584
10637
|
} else {
|
|
10585
|
-
stats.promptTokens =
|
|
10638
|
+
stats.promptTokens = promptTokensFallback;
|
|
10586
10639
|
stats.genTokens = genTokensFallback;
|
|
10587
10640
|
stats.genMs = totalMs - ttftMs;
|
|
10588
10641
|
stats.tps = stats.genMs > 0 ? Math.round(stats.genTokens / stats.genMs * 1e3 * 10) / 10 : 0;
|
|
@@ -10919,6 +10972,41 @@ Cannot execute bash commands.`);
|
|
|
10919
10972
|
};
|
|
10920
10973
|
}
|
|
10921
10974
|
|
|
10975
|
+
// src/code/code-upstream.ts
|
|
10976
|
+
var FALLBACK_CTX = 8192;
|
|
10977
|
+
function resolveCodeUpstream(d, requestedModel) {
|
|
10978
|
+
const res = resolveChatUpstream(d, requestedModel);
|
|
10979
|
+
if (!res.ok) throw new Error(res.code === "model_not_loaded" ? "model_not_loaded" : res.message);
|
|
10980
|
+
const u = res.upstream;
|
|
10981
|
+
const contextWindow = u.ctxMax > 0 ? u.ctxMax : FALLBACK_CTX;
|
|
10982
|
+
if (u.remote) {
|
|
10983
|
+
return {
|
|
10984
|
+
modelId: u.modelField,
|
|
10985
|
+
modelName: u.modelName || "Remote Model",
|
|
10986
|
+
contextWindow,
|
|
10987
|
+
remote: u.remote,
|
|
10988
|
+
target: "",
|
|
10989
|
+
provider: {
|
|
10990
|
+
baseUrl: `${u.remote.baseUrl}/v1`,
|
|
10991
|
+
apiKey: u.remote.token,
|
|
10992
|
+
// The link token travels as X-TurboLLM-Auth (linkHeaders, link-proxy.ts) and NOT as
|
|
10993
|
+
// a bearer: `Authorization` on the host is its own API-key credential, a different
|
|
10994
|
+
// secret with different scope, and presenting a link token there would either be
|
|
10995
|
+
// rejected or — worse — accepted as something it is not.
|
|
10996
|
+
authHeader: false,
|
|
10997
|
+
headers: { "X-TurboLLM-Auth": u.remote.token }
|
|
10998
|
+
}
|
|
10999
|
+
};
|
|
11000
|
+
}
|
|
11001
|
+
return {
|
|
11002
|
+
modelId: u.modelField,
|
|
11003
|
+
modelName: u.modelName || "Local Model",
|
|
11004
|
+
contextWindow,
|
|
11005
|
+
target: u.target,
|
|
11006
|
+
provider: { baseUrl: `${u.target}/v1`, apiKey: "agent-key", authHeader: true }
|
|
11007
|
+
};
|
|
11008
|
+
}
|
|
11009
|
+
|
|
10922
11010
|
// src/routines/routine-tools.ts
|
|
10923
11011
|
var SCHEDULE_RULE_SCHEMA = {
|
|
10924
11012
|
type: "object",
|
|
@@ -11553,14 +11641,12 @@ function pickPrefillProgress(slots) {
|
|
|
11553
11641
|
}
|
|
11554
11642
|
async function runCodeSession(params) {
|
|
11555
11643
|
const { d, convId, sessionId, repoRoot, mode, thinkingBudget, reasoningEffort, task: rawTask, signal, sink } = params;
|
|
11556
|
-
const
|
|
11557
|
-
|
|
11558
|
-
const target =
|
|
11559
|
-
|
|
11560
|
-
const
|
|
11561
|
-
const
|
|
11562
|
-
const contextWindow = ms.model.ctx > 0 ? ms.model.ctx : 8192;
|
|
11563
|
-
const modelDisplayName = ms.model.name || "Local Model";
|
|
11644
|
+
const requestedModel = params.model;
|
|
11645
|
+
const upstream = resolveCodeUpstream(d, requestedModel);
|
|
11646
|
+
const target = upstream.target;
|
|
11647
|
+
const modelId = upstream.modelId;
|
|
11648
|
+
const contextWindow = upstream.contextWindow;
|
|
11649
|
+
const modelDisplayName = upstream.modelName;
|
|
11564
11650
|
const skills = new SkillStore(d.store.dir()).list();
|
|
11565
11651
|
const authStorage = AuthStorage.inMemory();
|
|
11566
11652
|
const modelRegistry = ModelRegistry.inMemory(authStorage);
|
|
@@ -11584,9 +11670,7 @@ async function runCodeSession(params) {
|
|
|
11584
11670
|
}
|
|
11585
11671
|
const agentDir = join21(d.store.dir(), "pi-agent");
|
|
11586
11672
|
modelRegistry.registerProvider("local", {
|
|
11587
|
-
|
|
11588
|
-
apiKey: "agent-key",
|
|
11589
|
-
authHeader: true,
|
|
11673
|
+
...upstream.provider,
|
|
11590
11674
|
api: "openai-completions",
|
|
11591
11675
|
models: [
|
|
11592
11676
|
{
|
|
@@ -11630,9 +11714,7 @@ async function runCodeSession(params) {
|
|
|
11630
11714
|
const skillAuth = AuthStorage.inMemory();
|
|
11631
11715
|
const skillRegistry = ModelRegistry.inMemory(skillAuth);
|
|
11632
11716
|
skillRegistry.registerProvider("local", {
|
|
11633
|
-
|
|
11634
|
-
apiKey: "agent-key",
|
|
11635
|
-
authHeader: true,
|
|
11717
|
+
...upstream.provider,
|
|
11636
11718
|
api: "openai-completions",
|
|
11637
11719
|
models: [{
|
|
11638
11720
|
id: modelId,
|
|
@@ -11656,7 +11738,7 @@ async function runCodeSession(params) {
|
|
|
11656
11738
|
const skillExtension = (pi) => {
|
|
11657
11739
|
pi.on("before_provider_request", async (event) => {
|
|
11658
11740
|
releaseSkillGate();
|
|
11659
|
-
if (d.gate) skillHeldGate = await d.gate.acquire("bg", { signal, timeoutMs: GATE_QUEUE_TIMEOUT_MS });
|
|
11741
|
+
if (d.gate && !upstream.remote) skillHeldGate = await d.gate.acquire("bg", { signal, timeoutMs: GATE_QUEUE_TIMEOUT_MS });
|
|
11660
11742
|
const payload = { ...event.payload };
|
|
11661
11743
|
delete payload.max_tokens;
|
|
11662
11744
|
delete payload.max_completion_tokens;
|
|
@@ -11764,9 +11846,7 @@ async function runCodeSession(params) {
|
|
|
11764
11846
|
const subAuth = AuthStorage.inMemory();
|
|
11765
11847
|
const subRegistry = ModelRegistry.inMemory(subAuth);
|
|
11766
11848
|
subRegistry.registerProvider("local", {
|
|
11767
|
-
|
|
11768
|
-
apiKey: "agent-key",
|
|
11769
|
-
authHeader: true,
|
|
11849
|
+
...upstream.provider,
|
|
11770
11850
|
api: "openai-completions",
|
|
11771
11851
|
models: [{
|
|
11772
11852
|
id: modelId,
|
|
@@ -11799,7 +11879,7 @@ async function runCodeSession(params) {
|
|
|
11799
11879
|
const subExtension = (pi) => {
|
|
11800
11880
|
pi.on("before_provider_request", async (event) => {
|
|
11801
11881
|
releaseSubGate();
|
|
11802
|
-
if (d.gate) subHeldGate = await d.gate.acquire("bg", { signal: subAc.signal, timeoutMs: GATE_QUEUE_TIMEOUT_MS });
|
|
11882
|
+
if (d.gate && !upstream.remote) subHeldGate = await d.gate.acquire("bg", { signal: subAc.signal, timeoutMs: GATE_QUEUE_TIMEOUT_MS });
|
|
11803
11883
|
const payload = { ...event.payload };
|
|
11804
11884
|
delete payload.max_tokens;
|
|
11805
11885
|
delete payload.max_completion_tokens;
|
|
@@ -11958,8 +12038,8 @@ async function runCodeSession(params) {
|
|
|
11958
12038
|
const extension = (pi) => {
|
|
11959
12039
|
pi.on("before_provider_request", async (event) => {
|
|
11960
12040
|
releaseGate();
|
|
11961
|
-
if (d.gate) heldGate = await d.gate.acquire("fg", { signal, timeoutMs: GATE_QUEUE_TIMEOUT_MS });
|
|
11962
|
-
startPrefillPoll();
|
|
12041
|
+
if (d.gate && !upstream.remote) heldGate = await d.gate.acquire("fg", { signal, timeoutMs: GATE_QUEUE_TIMEOUT_MS });
|
|
12042
|
+
if (!upstream.remote) startPrefillPoll();
|
|
11963
12043
|
roundStartedAt = Date.now();
|
|
11964
12044
|
roundFirstTokenAt = void 0;
|
|
11965
12045
|
const payload = { ...event.payload };
|
|
@@ -12173,7 +12253,7 @@ ${lines.join("\n")}${more}]`
|
|
|
12173
12253
|
const q = (params2.question ?? "").trim();
|
|
12174
12254
|
if (!q) return { content: [{ type: "text", text: "lookback_history: `question` must be non-empty." }], details: {} };
|
|
12175
12255
|
try {
|
|
12176
|
-
const { answer } = await lookbackPreCompactionHistory({ d, convId, sessionId, repoRoot, question: q, signal });
|
|
12256
|
+
const { answer } = await lookbackPreCompactionHistory({ d, convId, sessionId, repoRoot, question: q, signal, model: requestedModel });
|
|
12177
12257
|
return { content: [{ type: "text", text: answer }], details: {} };
|
|
12178
12258
|
} catch (e) {
|
|
12179
12259
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -12445,13 +12525,9 @@ ${lines.join("\n")}${more}]`
|
|
|
12445
12525
|
async function compactCodeSession(params) {
|
|
12446
12526
|
const { d, convId, sessionId, repoRoot, customInstructions } = params;
|
|
12447
12527
|
if (d.db.getAgentRun(sessionId)?.clearedUpToMessageId) throw new Error("session_cleared");
|
|
12448
|
-
const
|
|
12449
|
-
|
|
12450
|
-
const
|
|
12451
|
-
if (!target) throw new Error("model_not_loaded");
|
|
12452
|
-
const engineKind = d.registry.active()?.kind ?? "";
|
|
12453
|
-
const modelId = engineModelAlias(engineKind, d.manager.currentOpts()?.modelPath) ?? ms.model.key;
|
|
12454
|
-
const contextWindow = ms.model.ctx > 0 ? ms.model.ctx : 8192;
|
|
12528
|
+
const upstream = resolveCodeUpstream(d, params.model);
|
|
12529
|
+
const modelId = upstream.modelId;
|
|
12530
|
+
const contextWindow = upstream.contextWindow;
|
|
12455
12531
|
const { summaryText, messages: effectiveMessages } = resolveEffectiveHistory(d, convId, sessionId);
|
|
12456
12532
|
if (effectiveMessages.length === 0) throw new Error("nothing_to_compact");
|
|
12457
12533
|
const compactionSettings = compactionSettingsFor(contextWindow);
|
|
@@ -12459,13 +12535,11 @@ async function compactCodeSession(params) {
|
|
|
12459
12535
|
const authStorage = AuthStorage.inMemory();
|
|
12460
12536
|
const modelRegistry = ModelRegistry.inMemory(authStorage);
|
|
12461
12537
|
modelRegistry.registerProvider("local", {
|
|
12462
|
-
|
|
12463
|
-
apiKey: "agent-key",
|
|
12464
|
-
authHeader: true,
|
|
12538
|
+
...upstream.provider,
|
|
12465
12539
|
api: "openai-completions",
|
|
12466
12540
|
models: [{
|
|
12467
12541
|
id: modelId,
|
|
12468
|
-
name:
|
|
12542
|
+
name: upstream.modelName,
|
|
12469
12543
|
reasoning: false,
|
|
12470
12544
|
input: ["text"],
|
|
12471
12545
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
@@ -12548,13 +12622,9 @@ async function lookbackPreCompactionHistory(params) {
|
|
|
12548
12622
|
const { d, convId, sessionId, repoRoot, question, signal } = params;
|
|
12549
12623
|
const run = d.db.getAgentRun(sessionId);
|
|
12550
12624
|
if (!run?.compactionUpToMessageId) throw new Error("nothing_compacted");
|
|
12551
|
-
const
|
|
12552
|
-
|
|
12553
|
-
const
|
|
12554
|
-
if (!target) throw new Error("model_not_loaded");
|
|
12555
|
-
const engineKind = d.registry.active()?.kind ?? "";
|
|
12556
|
-
const modelId = engineModelAlias(engineKind, d.manager.currentOpts()?.modelPath) ?? ms.model.key;
|
|
12557
|
-
const contextWindow = ms.model.ctx > 0 ? ms.model.ctx : 8192;
|
|
12625
|
+
const upstream = resolveCodeUpstream(d, params.model);
|
|
12626
|
+
const modelId = upstream.modelId;
|
|
12627
|
+
const contextWindow = upstream.contextWindow;
|
|
12558
12628
|
const all = d.db.getConversation(convId, true)?.messages ?? [];
|
|
12559
12629
|
const cutIdx = all.findIndex((m) => m.id === run.compactionUpToMessageId);
|
|
12560
12630
|
const preCompaction = cutIdx === -1 ? all : all.slice(0, cutIdx + 1);
|
|
@@ -12562,13 +12632,11 @@ async function lookbackPreCompactionHistory(params) {
|
|
|
12562
12632
|
const authStorage = AuthStorage.inMemory();
|
|
12563
12633
|
const modelRegistry = ModelRegistry.inMemory(authStorage);
|
|
12564
12634
|
modelRegistry.registerProvider("local", {
|
|
12565
|
-
|
|
12566
|
-
apiKey: "agent-key",
|
|
12567
|
-
authHeader: true,
|
|
12635
|
+
...upstream.provider,
|
|
12568
12636
|
api: "openai-completions",
|
|
12569
12637
|
models: [{
|
|
12570
12638
|
id: modelId,
|
|
12571
|
-
name:
|
|
12639
|
+
name: upstream.modelName,
|
|
12572
12640
|
reasoning: false,
|
|
12573
12641
|
input: ["text"],
|
|
12574
12642
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
@@ -12730,7 +12798,7 @@ var CodeRunManager = class {
|
|
|
12730
12798
|
enqueue(sessionId, params) {
|
|
12731
12799
|
const s = this.ensure(sessionId, params.convId, params.repoRoot);
|
|
12732
12800
|
const willQueue = s.active !== null;
|
|
12733
|
-
s.queue.push({ task: params.task, userMsgId: params.userMsgId, thinkingBudget: params.thinkingBudget ?? -1, reasoningEffort: params.reasoningEffort, kind: params.kind ?? "followUp" });
|
|
12801
|
+
s.queue.push({ task: params.task, userMsgId: params.userMsgId, thinkingBudget: params.thinkingBudget ?? -1, reasoningEffort: params.reasoningEffort, kind: params.kind ?? "followUp", model: params.model });
|
|
12734
12802
|
this.emitQueue(sessionId);
|
|
12735
12803
|
void this.pump(sessionId);
|
|
12736
12804
|
return { queued: willQueue };
|
|
@@ -12850,8 +12918,7 @@ var CodeRunManager = class {
|
|
|
12850
12918
|
push(ev.event, ev.data);
|
|
12851
12919
|
};
|
|
12852
12920
|
try {
|
|
12853
|
-
const
|
|
12854
|
-
const model = ms.model;
|
|
12921
|
+
const statsModelKey = turn.model ?? this.d.manager.status().model?.key;
|
|
12855
12922
|
const mode = this.d.db.getConversation(s.convId)?.agentMode ?? "auto";
|
|
12856
12923
|
const result = await this.runner({
|
|
12857
12924
|
d: this.d,
|
|
@@ -12862,6 +12929,7 @@ var CodeRunManager = class {
|
|
|
12862
12929
|
thinkingBudget: turn.thinkingBudget,
|
|
12863
12930
|
reasoningEffort: turn.reasoningEffort,
|
|
12864
12931
|
task: turn.task,
|
|
12932
|
+
model: turn.model,
|
|
12865
12933
|
signal: ac.signal,
|
|
12866
12934
|
sink,
|
|
12867
12935
|
// Publish/withdraw the live turn's steer handle so steer() can inject into THIS turn.
|
|
@@ -12883,7 +12951,7 @@ var CodeRunManager = class {
|
|
|
12883
12951
|
stats: {
|
|
12884
12952
|
ctxUsed: ctxStats.ctxUsed,
|
|
12885
12953
|
ctxMax: ctxStats.ctxMax,
|
|
12886
|
-
model:
|
|
12954
|
+
model: statsModelKey,
|
|
12887
12955
|
aborted: result.aborted,
|
|
12888
12956
|
// Real per-turn token/timing stats (foldTurnUsage, code-session.ts) — omitted by
|
|
12889
12957
|
// runCodeSession (not zeroed) when the engine returned no usable usage at all.
|
|
@@ -17479,7 +17547,8 @@ function spillMb(baselineSharedMb, loadedSharedMb) {
|
|
|
17479
17547
|
}
|
|
17480
17548
|
var SPILL_PROXIMITY_MB = 1024;
|
|
17481
17549
|
var SPILL_FLOOR_CAP_MB = 2048;
|
|
17482
|
-
function isSpilling(spill, vramAbsMb, budgetMb, floorMb = null, pooled = false) {
|
|
17550
|
+
function isSpilling(spill, vramAbsMb, budgetMb, floorMb = null, pooled = false, unified = false) {
|
|
17551
|
+
if (unified) return false;
|
|
17483
17552
|
if (spill === null) return false;
|
|
17484
17553
|
const floor = pooled ? 0 : Math.min(floorMb ?? 0, SPILL_FLOOR_CAP_MB);
|
|
17485
17554
|
if (spill - floor <= SPILL_TOLERANCE_MB) return false;
|
|
@@ -18492,7 +18561,6 @@ var PER_TEST_TIMEOUT_MS = 10 * 6e4;
|
|
|
18492
18561
|
var PREFILL_GRACE_MS = 8e3;
|
|
18493
18562
|
var TOTAL_BUDGET_MS = 45 * 6e4;
|
|
18494
18563
|
var OOM_RE = /out of memory|cudaMalloc|failed to allocate|unable to allocate|device not ready|CUDA error/i;
|
|
18495
|
-
var QUALITY_KV = ["f16", "q8_0", "turbo4"];
|
|
18496
18564
|
var KV_BYTES = {
|
|
18497
18565
|
f32: 4,
|
|
18498
18566
|
f16: 2,
|
|
@@ -18757,6 +18825,7 @@ var BenchRunner = class {
|
|
|
18757
18825
|
const budgetMb = gpuBudgetMb(sys, base2);
|
|
18758
18826
|
let spillFloorMb = null;
|
|
18759
18827
|
const pooled = sys.gpus.length > 1 && base2.gpu.splitMode !== "none";
|
|
18828
|
+
const unified = unifiedMemoryOnly(sys);
|
|
18760
18829
|
if (sys.gpus.length > 0) {
|
|
18761
18830
|
const hi0 = entry.blockCount > 0 ? entry.blockCount : 99;
|
|
18762
18831
|
let lo = 0, hi = hi0;
|
|
@@ -18768,7 +18837,7 @@ var BenchRunner = class {
|
|
|
18768
18837
|
this.pushProbe(results, base2, "ngl", mid, probe2);
|
|
18769
18838
|
await this.settleGpu(sys);
|
|
18770
18839
|
spillFloorMb = spillFloor(spillFloorMb, probe2.spillMb, probe2.vramAbsMb, budgetMb, pooled);
|
|
18771
|
-
const verdict = probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb, pooled);
|
|
18840
|
+
const verdict = probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb, pooled, unified);
|
|
18772
18841
|
if (verdict.decision === "fits") {
|
|
18773
18842
|
bestNgl = mid;
|
|
18774
18843
|
lo = mid + 1;
|
|
@@ -18782,7 +18851,7 @@ var BenchRunner = class {
|
|
|
18782
18851
|
}
|
|
18783
18852
|
if (bestNgl === null) return null;
|
|
18784
18853
|
let found = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl }, caps, results, `ngl=${bestNgl}`);
|
|
18785
|
-
if (found && isSpilling(found.cand.spillMb, found.cand.vramAbsMb, budgetMb, spillFloorMb, pooled) && bestNgl > 0) {
|
|
18854
|
+
if (found && isSpilling(found.cand.spillMb, found.cand.vramAbsMb, budgetMb, spillFloorMb, pooled, unified) && bestNgl > 0) {
|
|
18786
18855
|
this.emit(`ngl=${bestNgl} spilled ${Math.round(found.cand.spillMb)} MB once actually generating (the load-only probe could not see this) \u2014 retrying at ngl=${bestNgl - 1}`);
|
|
18787
18856
|
const safer = await this.benchAt(entry, sys, { ...base2, ngl: bestNgl - 1 }, caps, results, `ngl=${bestNgl - 1} (spill backoff)`);
|
|
18788
18857
|
if (safer) {
|
|
@@ -18819,6 +18888,7 @@ var BenchRunner = class {
|
|
|
18819
18888
|
let bestN = null;
|
|
18820
18889
|
let spillFloorMb = null;
|
|
18821
18890
|
const pooled = sys.gpus.length > 1 && base2.gpu.splitMode !== "none";
|
|
18891
|
+
const unified = unifiedMemoryOnly(sys);
|
|
18822
18892
|
while (lo <= hi && !this.cancelled && Date.now() <= this.deadline) {
|
|
18823
18893
|
const mid = Math.floor((lo + hi) / 2);
|
|
18824
18894
|
this.state = { ...this.state, step: `KV ${base2.kvTypeK}: probing nCpuMoe=${mid} (range ${lo}\u2013${hi})\u2026`, candidates: results };
|
|
@@ -18826,7 +18896,7 @@ var BenchRunner = class {
|
|
|
18826
18896
|
this.pushProbe(results, base2, "nCpuMoe", mid, probe2);
|
|
18827
18897
|
await this.settleGpu(sys);
|
|
18828
18898
|
spillFloorMb = spillFloor(spillFloorMb, probe2.spillMb, probe2.vramAbsMb, budgetMb, pooled);
|
|
18829
|
-
const verdict = probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb, pooled);
|
|
18899
|
+
const verdict = probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb, pooled, unified);
|
|
18830
18900
|
if (verdict.decision === "fits") {
|
|
18831
18901
|
bestN = mid;
|
|
18832
18902
|
hi = mid - 1;
|
|
@@ -18854,7 +18924,7 @@ var BenchRunner = class {
|
|
|
18854
18924
|
}
|
|
18855
18925
|
if (n < maxN) this.emit(`nCpuMoe=${n} failed to bench (${results[results.length - 1]?.outcome ?? "crash"}) \u2014 retrying at nCpuMoe=${n + 1}`);
|
|
18856
18926
|
}
|
|
18857
|
-
if (found && isSpilling(found.cand.spillMb, found.cand.vramAbsMb, budgetMb, spillFloorMb, pooled) && foundN < maxN) {
|
|
18927
|
+
if (found && isSpilling(found.cand.spillMb, found.cand.vramAbsMb, budgetMb, spillFloorMb, pooled, unified) && foundN < maxN) {
|
|
18858
18928
|
this.emit(`nCpuMoe=${foundN} spilled ${Math.round(found.cand.spillMb)} MB once actually generating (the load-only probe could not see this) \u2014 retrying at nCpuMoe=${foundN + 1}`);
|
|
18859
18929
|
const safer = await this.benchAt(entry, sys, { ...base2, nCpuMoe: foundN + 1 }, caps, results, `nCpuMoe=${foundN + 1} (spill backoff)`);
|
|
18860
18930
|
if (safer) {
|
|
@@ -19487,17 +19557,20 @@ function overHeadroom(vramAbsMb, budgetMb, headroomMb) {
|
|
|
19487
19557
|
if (!vramAbsMb || budgetMb <= 0) return false;
|
|
19488
19558
|
return vramAbsMb > budgetMb - headroomMb;
|
|
19489
19559
|
}
|
|
19560
|
+
var MIN_SINGLE_GPU_FRACTION_MOE = 0.5;
|
|
19561
|
+
var MIN_SINGLE_GPU_FRACTION_DENSE = 0.6;
|
|
19490
19562
|
function pickSplitStrategies(entry, sys, base2, caps) {
|
|
19491
19563
|
const has = (flag) => caps.flags.length === 0 || caps.flags.includes(flag);
|
|
19492
19564
|
if (sys.gpus.length <= 1 || !has("--split-mode") || !has("--main-gpu")) return [base2.gpu];
|
|
19493
19565
|
const strategies = [];
|
|
19494
|
-
const kvOpts = pickKvQuants(base2.kvTypeK, caps.kvTypes);
|
|
19495
|
-
const bestFitKv = kvOpts.reduce((a, b) => kvBytes(b) < kvBytes(a) ? b : a, kvOpts[0] ?? base2.kvTypeK);
|
|
19496
19566
|
const mainGpu = base2.gpu.mainGpu >= 0 ? base2.gpu.mainGpu : 0;
|
|
19497
19567
|
const single = { ...base2.gpu, splitMode: "none", mainGpu, tensorSplit: [] };
|
|
19498
|
-
const singleFrac = maxGpuFraction(entry, sys, { ...base2, gpu: single
|
|
19499
|
-
if (singleFrac >=
|
|
19568
|
+
const singleFrac = maxGpuFraction(entry, sys, { ...base2, gpu: single });
|
|
19569
|
+
if (singleFrac >= (entry.moe ? MIN_SINGLE_GPU_FRACTION_MOE : MIN_SINGLE_GPU_FRACTION_DENSE)) {
|
|
19570
|
+
strategies.push(single);
|
|
19571
|
+
}
|
|
19500
19572
|
strategies.push(base2.gpu);
|
|
19573
|
+
if (base2.gpu.splitMode !== "none") strategies.push({ ...base2.gpu, splitMode: "row", tensorSplit: [] });
|
|
19501
19574
|
const seen = /* @__PURE__ */ new Set();
|
|
19502
19575
|
return strategies.filter((g) => {
|
|
19503
19576
|
const key = `${g.splitMode}|${g.mainGpu >= 0 ? g.mainGpu : 0}|${g.tensorSplit.join(",")}`;
|
|
@@ -19550,15 +19623,9 @@ function splitLabel(g, gpuCount) {
|
|
|
19550
19623
|
if (g.splitMode === "row") return `row-split across ${gpuCount} GPUs`;
|
|
19551
19624
|
return `layer-split across ${gpuCount} GPUs`;
|
|
19552
19625
|
}
|
|
19553
|
-
function
|
|
19554
|
-
const supported = (t) => kvTypes.length === 0 ? t === baseKv : kvTypes.includes(t);
|
|
19555
|
-
const out = [];
|
|
19556
|
-
for (const t of [baseKv, ...QUALITY_KV]) if (supported(t) && !out.includes(t)) out.push(t);
|
|
19557
|
-
return out;
|
|
19558
|
-
}
|
|
19559
|
-
function probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb = null, pooled = false) {
|
|
19626
|
+
function probeVerdict(probe2, budgetMb, headroomMb, spillFloorMb = null, pooled = false, unified = false) {
|
|
19560
19627
|
if (probe2.outcome === "oom") return { decision: "offload-more", reason: "oom" };
|
|
19561
|
-
if (isSpilling(probe2.spillMb, probe2.vramAbsMb, budgetMb, spillFloorMb, pooled)) {
|
|
19628
|
+
if (isSpilling(probe2.spillMb, probe2.vramAbsMb, budgetMb, spillFloorMb, pooled, unified)) {
|
|
19562
19629
|
return { decision: "offload-more", reason: "spill", shortfallMb: probe2.spillMb };
|
|
19563
19630
|
}
|
|
19564
19631
|
if (overHeadroom(probe2.vramAbsMb, budgetMb, headroomMb)) {
|
|
@@ -22907,13 +22974,15 @@ function detectHardware(info = getSysInfo()) {
|
|
|
22907
22974
|
void 0
|
|
22908
22975
|
);
|
|
22909
22976
|
const vramMb = ofVendor.reduce((sum, g) => sum + g.vramMb, 0);
|
|
22977
|
+
const unifiedMemory = ofVendor.length > 0 && ofVendor.every((g) => g.unified === true);
|
|
22910
22978
|
return {
|
|
22911
22979
|
platform: process.platform,
|
|
22912
22980
|
arch: arch2,
|
|
22913
22981
|
gpuVendor,
|
|
22914
22982
|
hasGpu,
|
|
22915
22983
|
vramMb,
|
|
22916
|
-
gpuName: headline?.name
|
|
22984
|
+
gpuName: headline?.name,
|
|
22985
|
+
unifiedMemory
|
|
22917
22986
|
};
|
|
22918
22987
|
}
|
|
22919
22988
|
|
|
@@ -23316,10 +23385,15 @@ function roleFor(profile) {
|
|
|
23316
23385
|
}
|
|
23317
23386
|
|
|
23318
23387
|
// src/onboarding/recommend.ts
|
|
23388
|
+
function jointMemoryOk(e, hw) {
|
|
23389
|
+
if (!hw.unifiedMemory) return true;
|
|
23390
|
+
return (e.minVramMb ?? 0) + (e.minSystemRamMb ?? 0) <= hw.systemRamMb;
|
|
23391
|
+
}
|
|
23319
23392
|
function fits(e, hw) {
|
|
23320
23393
|
if (e.minVramMb !== null && hw.usableVramMb < e.minVramMb) return false;
|
|
23321
23394
|
if (e.maxVramMb !== null && hw.usableVramMb >= e.maxVramMb) return false;
|
|
23322
23395
|
if (e.minSystemRamMb !== null && hw.systemRamMb < e.minSystemRamMb) return false;
|
|
23396
|
+
if (!jointMemoryOk(e, hw)) return false;
|
|
23323
23397
|
return true;
|
|
23324
23398
|
}
|
|
23325
23399
|
function recommend(profile, hw) {
|
|
@@ -23328,7 +23402,7 @@ function recommend(profile, hw) {
|
|
|
23328
23402
|
let candidates = BLESSED.filter((e) => e.role === role && fits(e, hw));
|
|
23329
23403
|
if (candidates.length === 0) {
|
|
23330
23404
|
candidates = BLESSED.filter(
|
|
23331
|
-
(e) => e.role === role && (e.minVramMb === null || hw.usableVramMb >= e.minVramMb) && (e.minSystemRamMb === null || hw.systemRamMb >= e.minSystemRamMb)
|
|
23405
|
+
(e) => e.role === role && (e.minVramMb === null || hw.usableVramMb >= e.minVramMb) && (e.minSystemRamMb === null || hw.systemRamMb >= e.minSystemRamMb) && jointMemoryOk(e, hw)
|
|
23332
23406
|
);
|
|
23333
23407
|
}
|
|
23334
23408
|
if (candidates.length === 0) return { kind: "hf-search", reason: "no-fit" };
|
|
@@ -23345,11 +23419,9 @@ function recommend(profile, hw) {
|
|
|
23345
23419
|
function isT0(hw) {
|
|
23346
23420
|
return hw.usableVramMb < 4096;
|
|
23347
23421
|
}
|
|
23348
|
-
function hardwareFactsFromSysInfo() {
|
|
23349
|
-
const
|
|
23350
|
-
|
|
23351
|
-
const unifiedMemory = info.gpus.some((g) => g.unified === true);
|
|
23352
|
-
return { usableVramMb: primaryVramMb, systemRamMb: info.ramMB, unifiedMemory };
|
|
23422
|
+
function hardwareFactsFromSysInfo(info = getSysInfo()) {
|
|
23423
|
+
const { vramMb, unifiedMemory } = detectHardware(info);
|
|
23424
|
+
return { usableVramMb: vramMb, systemRamMb: info.ramMB, unifiedMemory };
|
|
23353
23425
|
}
|
|
23354
23426
|
function applyOnboardingPatch(current, patch, now) {
|
|
23355
23427
|
const next = { ...current };
|
|
@@ -23587,7 +23659,7 @@ function registerApi(app2, d) {
|
|
|
23587
23659
|
const ms = d.manager.status();
|
|
23588
23660
|
const launchCommand = d.manager.launchCommand();
|
|
23589
23661
|
const engine = { ...core.engine };
|
|
23590
|
-
if (ms.err) engine.error = ms.err;
|
|
23662
|
+
if (ms.err) engine.error = { ...ms.err, failReason: classifyLoadFailure(ms.err) };
|
|
23591
23663
|
if (launchCommand) engine.launchCommand = launchCommand;
|
|
23592
23664
|
return c.json({
|
|
23593
23665
|
version: d.version,
|
|
@@ -23596,6 +23668,11 @@ function registerApi(app2, d) {
|
|
|
23596
23668
|
// Last model the user loaded (config-tracked) — lets `turbollm launch` auto-load the
|
|
23597
23669
|
// true last-used model instead of guessing the first library entry (F-034).
|
|
23598
23670
|
lastLoaded: d.store.snapshot().lastLoaded,
|
|
23671
|
+
// Turbo Link (ADR-382): the linked-machine model this install is pointed at, or '' for
|
|
23672
|
+
// local. On /status because every surface reads it here — the web app hydrates its picker
|
|
23673
|
+
// from it, and `turbollm launch <cli>` (which has no access to browser state) uses it
|
|
23674
|
+
// instead of auto-loading a local model the user did not ask for.
|
|
23675
|
+
selectedRemoteModel: d.store.snapshot().selectedRemoteModel ?? "",
|
|
23599
23676
|
engineStats: core.engineStats,
|
|
23600
23677
|
liveGeneration: core.liveGeneration,
|
|
23601
23678
|
// Auto-tune runner state (spec 09 §1): real progress while a sweep runs, then
|
|
@@ -26258,6 +26335,29 @@ function registerLinkAdminRoutes(app2, d, opts) {
|
|
|
26258
26335
|
if (denied) return denied;
|
|
26259
26336
|
return c.json({ models: d.remoteCatalog?.models() ?? [] });
|
|
26260
26337
|
});
|
|
26338
|
+
app2.put("/api/v1/links/selected-model", async (c) => {
|
|
26339
|
+
const denied = gate(c, MANAGE);
|
|
26340
|
+
if (denied) return denied;
|
|
26341
|
+
const body10 = await c.req.json().catch(() => null);
|
|
26342
|
+
const wanted = (body10?.model ?? "").trim();
|
|
26343
|
+
if (!wanted) {
|
|
26344
|
+
d.store.update((cfg2) => {
|
|
26345
|
+
cfg2.selectedRemoteModel = "";
|
|
26346
|
+
});
|
|
26347
|
+
return c.json({ ok: true, selectedRemoteModel: "" });
|
|
26348
|
+
}
|
|
26349
|
+
const route = d.modelRouter?.resolveRemoteTarget?.(wanted);
|
|
26350
|
+
if (!route) {
|
|
26351
|
+
return c.json({ error: { code: "not_remote", message: `'${wanted}' does not name a model on a linked machine.` } }, 400);
|
|
26352
|
+
}
|
|
26353
|
+
if ("status" in route) {
|
|
26354
|
+
return c.json({ error: { code: "remote_unavailable", message: route.message } }, 503);
|
|
26355
|
+
}
|
|
26356
|
+
d.store.update((cfg2) => {
|
|
26357
|
+
cfg2.selectedRemoteModel = wanted;
|
|
26358
|
+
});
|
|
26359
|
+
return c.json({ ok: true, selectedRemoteModel: wanted });
|
|
26360
|
+
});
|
|
26261
26361
|
app2.post("/api/v1/links", async (c) => {
|
|
26262
26362
|
const denied = gate(c, MANAGE);
|
|
26263
26363
|
if (denied) return denied;
|
|
@@ -27572,16 +27672,22 @@ function registerCodeRoutes(app2, d, codeRuns) {
|
|
|
27572
27672
|
if (!run.repoRoot) return err9(c, 400, "invalid_input", "Session has no repo root.");
|
|
27573
27673
|
if (runs.isActive(id)) return err9(c, 409, "run_active", "Stop or wait for the current run before compacting.");
|
|
27574
27674
|
if (run.clearedUpToMessageId) return err9(c, 409, "session_cleared", "Resume this session before compacting \u2014 compacting a cleared session would lose the hidden history.");
|
|
27575
|
-
const ms = d.manager.status();
|
|
27576
|
-
if (ms.state !== "running" || !ms.model) return err9(c, 409, "model_not_loaded", "Load a model first.");
|
|
27577
27675
|
const b = await body8(c);
|
|
27676
|
+
const requestedModel = (b.model ?? "").trim() || void 0;
|
|
27677
|
+
const remoteRoute = requestedModel ? d.modelRouter.resolveRemoteTarget(requestedModel) : void 0;
|
|
27678
|
+
if (remoteRoute && "status" in remoteRoute) return err9(c, 503, "remote_unavailable", remoteRoute.message);
|
|
27679
|
+
if (!remoteRoute) {
|
|
27680
|
+
const ms = d.manager.status();
|
|
27681
|
+
if (ms.state !== "running" || !ms.model) return err9(c, 409, "model_not_loaded", "Load a model first.");
|
|
27682
|
+
}
|
|
27578
27683
|
try {
|
|
27579
27684
|
const result = await compactCodeSession({
|
|
27580
27685
|
d,
|
|
27581
27686
|
convId: run.convId,
|
|
27582
27687
|
sessionId: id,
|
|
27583
27688
|
repoRoot: agentCwd(run),
|
|
27584
|
-
customInstructions: b.instructions?.trim() || void 0
|
|
27689
|
+
customInstructions: b.instructions?.trim() || void 0,
|
|
27690
|
+
model: requestedModel
|
|
27585
27691
|
});
|
|
27586
27692
|
return c.json({ ok: true, ...result });
|
|
27587
27693
|
} catch (e) {
|
|
@@ -27758,9 +27864,14 @@ function registerCodeRoutes(app2, d, codeRuns) {
|
|
|
27758
27864
|
const conv = db2.getConversation(run.convId, true);
|
|
27759
27865
|
if (!conv) return err9(c, 404, "not_found", "Session conversation not found.");
|
|
27760
27866
|
if (!run.repoRoot) return err9(c, 400, "invalid_input", "Session has no repo root.");
|
|
27761
|
-
const
|
|
27762
|
-
|
|
27763
|
-
if (
|
|
27867
|
+
const requestedModel = (b.model ?? "").trim() || void 0;
|
|
27868
|
+
const remoteRoute = requestedModel ? d.modelRouter.resolveRemoteTarget(requestedModel) : void 0;
|
|
27869
|
+
if (remoteRoute && "status" in remoteRoute) return err9(c, 503, "remote_unavailable", remoteRoute.message);
|
|
27870
|
+
if (!remoteRoute) {
|
|
27871
|
+
const ms = d.manager.status();
|
|
27872
|
+
if (ms.state !== "running" || !ms.model) return err9(c, 409, "model_not_loaded", "Load a model first.");
|
|
27873
|
+
if (!d.manager.target()) return err9(c, 409, "model_not_loaded", "Engine not running.");
|
|
27874
|
+
}
|
|
27764
27875
|
const newContent = (b.content ?? "").trim();
|
|
27765
27876
|
let userMsgId;
|
|
27766
27877
|
let task;
|
|
@@ -27773,7 +27884,7 @@ function registerCodeRoutes(app2, d, codeRuns) {
|
|
|
27773
27884
|
userMsgId = lastUser.id;
|
|
27774
27885
|
task = contextFilesBlock(lastUser.textAttachments) + lastUser.content;
|
|
27775
27886
|
}
|
|
27776
|
-
const enqueueParams = { convId: run.convId, repoRoot: agentCwd(run), task, userMsgId, thinkingBudget: b.thinkingBudget, reasoningEffort: parseReasoningEffort(b.reasoningEffort) };
|
|
27887
|
+
const enqueueParams = { convId: run.convId, repoRoot: agentCwd(run), task, userMsgId, thinkingBudget: b.thinkingBudget, reasoningEffort: parseReasoningEffort(b.reasoningEffort), model: requestedModel };
|
|
27777
27888
|
if (kind === "steer") {
|
|
27778
27889
|
const { steered, queued: queued2 } = await runs.steer(id, enqueueParams);
|
|
27779
27890
|
return c.json({ ok: true, queued: queued2, steered, userMessageId: userMsgId }, 202);
|