turbollm 1.10.3 → 1.10.5
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 +275 -108
- package/dist/webdist/assets/{AgentEditPage-DZU5Ps30.js → AgentEditPage-Bq0To2Kn.js} +1 -1
- package/dist/webdist/assets/{ChatScreen-CWjg1zrs.js → ChatScreen-JfS4dp94.js} +9 -9
- package/dist/webdist/assets/{CodeComposer-C8c0eQe4.js → CodeComposer-BPcKbMuH.js} +1 -1
- package/dist/webdist/assets/CodeHomeScreen-CbY_UCs6.js +1 -0
- package/dist/webdist/assets/{CodeSessionScreen-DOVBiJIZ.js → CodeSessionScreen-nU50H3fR.js} +11 -11
- package/dist/webdist/assets/{CustomizeScreen-Dg69A2mU.js → CustomizeScreen-jI99vrYL.js} +1 -1
- package/dist/webdist/assets/{DeveloperScreen-CwW1Z3BJ.js → DeveloperScreen-BfYnTO7e.js} +1 -1
- package/dist/webdist/assets/{EnginesScreen-CiMymt2y.js → EnginesScreen-CU8ZNHcl.js} +1 -1
- package/dist/webdist/assets/{ModelDetailDialog-Ch1FFdDi.js → ModelDetailDialog-DKUMTU2w.js} +1 -1
- package/dist/webdist/assets/{ModelLoadMenu-DmJ6pW_S.js → ModelLoadMenu-CBj32oEE.js} +1 -1
- package/dist/webdist/assets/{ModelsScreen-Ch83Gnvx.js → ModelsScreen-CTYIbZyc.js} +1 -1
- package/dist/webdist/assets/RoutineEditPage-gqLu8cXv.js +1 -0
- package/dist/webdist/assets/RoutinesPanel-Dv9Shubg.js +1 -0
- package/dist/webdist/assets/{SettingsScreen-fWaRXbXZ.js → SettingsScreen-C7LQLNGe.js} +1 -1
- package/dist/webdist/assets/SidebarResizeHandle-Djhjx6qR.js +2 -0
- package/dist/webdist/assets/{SkillEditPage-Cpg3YkPw.js → SkillEditPage-ClBJXbC3.js} +1 -1
- package/dist/webdist/assets/{TokensScreen-CYGdXUbH.js → TokensScreen-gk_Mqi5g.js} +1 -1
- package/dist/webdist/assets/{ToolApprovalBar-Ba2BoF9X.js → ToolApprovalBar-B3WSFcyU.js} +3 -3
- package/dist/webdist/assets/WorkspaceScreen-jL5YURRX.js +1 -0
- package/dist/webdist/assets/{abnfDiagram-N423BO3Z-CxAZuY4F.js → abnfDiagram-N423BO3Z-QSevWJ37.js} +1 -1
- package/dist/webdist/assets/{agent-api-BdnGAV-Y.js → agent-api-CpgzOfg0.js} +1 -1
- package/dist/webdist/assets/{alert-dialog-CEf-XUyg.js → alert-dialog-CMvNzcK0.js} +1 -1
- package/dist/webdist/assets/{arc-DEU8Rl3Q.js → arc-BWbVGHju.js} +1 -1
- package/dist/webdist/assets/{architectureDiagram-T3A2C74G-DFWEfaYa.js → architectureDiagram-T3A2C74G-Boh67Blv.js} +1 -1
- package/dist/webdist/assets/{arrow-left-BHr6DbXW.js → arrow-left-CU7vJBtU.js} +1 -1
- package/dist/webdist/assets/{badge-DiZD__AA.js → badge-BOGctZvx.js} +1 -1
- package/dist/webdist/assets/{blockDiagram-VBNYF7ZC-BhTU3G_O.js → blockDiagram-VBNYF7ZC-BkIBotfv.js} +1 -1
- package/dist/webdist/assets/{bot-BR1o3u2z.js → bot-CwYS2B1G.js} +1 -1
- package/dist/webdist/assets/{c4Diagram-5PPSVZJV-CJNhzTh5.js → c4Diagram-5PPSVZJV-CWCZQHIc.js} +1 -1
- package/dist/webdist/assets/channel-Yxxa5Jtv.js +1 -0
- package/dist/webdist/assets/{chat-api-WdKnt_cR.js → chat-api-BTcC6kED.js} +1 -1
- package/dist/webdist/assets/{chat-queries--BKqKvZT.js → chat-queries-D9fFhHaQ.js} +1 -1
- package/dist/webdist/assets/{chevron-left-tBRMVkX5.js → chevron-left-BVxkM758.js} +1 -1
- package/dist/webdist/assets/{chevron-right-B16ur-An.js → chevron-right-BJZRbTUj.js} +1 -1
- package/dist/webdist/assets/{chunk-2GRJ4B5K-Y-VLx_rW.js → chunk-2GRJ4B5K-C5CXDrO_.js} +1 -1
- package/dist/webdist/assets/{chunk-2Q5K7J3B-BUKWb833.js → chunk-2Q5K7J3B-Bk_wrlB0.js} +1 -1
- package/dist/webdist/assets/{chunk-5RXB4S5H-BV3L2yyf.js → chunk-5RXB4S5H-BAT4FnUI.js} +1 -1
- package/dist/webdist/assets/{chunk-5VM5RSS4-xI1dTTCA.js → chunk-5VM5RSS4-C9eEV1Kl.js} +1 -1
- package/dist/webdist/assets/{chunk-6Q2QTUOP-C3F611uv.js → chunk-6Q2QTUOP-CJDFqmYe.js} +1 -1
- package/dist/webdist/assets/{chunk-GF5L2VYU-xzyWIvtP.js → chunk-GF5L2VYU-CsgBXjfk.js} +1 -1
- package/dist/webdist/assets/{chunk-JWPE2WC7-PCn1DNAq.js → chunk-JWPE2WC7-CRt7uW9O.js} +1 -1
- package/dist/webdist/assets/{chunk-KBJHAD2P-B2V4Qn1_.js → chunk-KBJHAD2P-CSsVpcf6.js} +1 -1
- package/dist/webdist/assets/{chunk-RYQCIY6F-BXnb7awQ.js → chunk-RYQCIY6F-eTll7wC1.js} +1 -1
- package/dist/webdist/assets/{chunk-XXDRQBXY-BjzDsMy6.js → chunk-XXDRQBXY-D2-Dj7EK.js} +1 -1
- package/dist/webdist/assets/{circle-check-BHQ4Ky5u.js → circle-check-g29PWBwU.js} +1 -1
- package/dist/webdist/assets/{circle-x-BbJarEnu.js → circle-x-BgFrKCxR.js} +1 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-Cr7eMrK7.js +1 -0
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-Cr7eMrK7.js +1 -0
- package/dist/webdist/assets/{common-B_Ugw5Ue.js → common-Fwu8t36v.js} +1 -1
- package/dist/webdist/assets/{cose-bilkent-JH36ORCC-8GVWCg2F.js → cose-bilkent-JH36ORCC-DXafCcEB.js} +1 -1
- package/dist/webdist/assets/{cynefin-VYW2F7L2-D4EwNxuN.js → cynefin-VYW2F7L2-CecX93d_.js} +1 -1
- package/dist/webdist/assets/{cynefinDiagram-MW4NZA55-BchWtjzK.js → cynefinDiagram-MW4NZA55-tu8xDmsR.js} +1 -1
- package/dist/webdist/assets/{dagre-VZM6K2ZE-C-tKBzor.js → dagre-VZM6K2ZE-UG2o94YJ.js} +1 -1
- package/dist/webdist/assets/{diagram-7IWD3JNH-CIzXwEou.js → diagram-7IWD3JNH-3DRTAZAF.js} +1 -1
- package/dist/webdist/assets/{diagram-B4RE2ZJO-B0-fu81p.js → diagram-B4RE2ZJO-CwH0bQ2A.js} +1 -1
- package/dist/webdist/assets/{diagram-LBJQPF4R-DKUCmHSn.js → diagram-LBJQPF4R-DuybxKFU.js} +1 -1
- package/dist/webdist/assets/{diagram-Q27KOJAE-BMVmaaBq.js → diagram-Q27KOJAE-BwoB84ui.js} +1 -1
- package/dist/webdist/assets/{diagram-UB23O5K3-C-GsMRNn.js → diagram-UB23O5K3-DEjbnHCQ.js} +1 -1
- package/dist/webdist/assets/{dropdown-menu-BHlT_PrH.js → dropdown-menu-D25-JVEy.js} +1 -1
- package/dist/webdist/assets/{ebnfDiagram-BXEA7PRR-D2cgRlFo.js → ebnfDiagram-BXEA7PRR-DG9Xbpyw.js} +1 -1
- package/dist/webdist/assets/{erDiagram-JOGREHBK-MG0Qt0Dc.js → erDiagram-JOGREHBK-eysaP8yv.js} +1 -1
- package/dist/webdist/assets/{external-link-BYsIzaRn.js → external-link-Xn8kJljc.js} +1 -1
- package/dist/webdist/assets/{file-text-D5LVQPdf.js → file-text-BmAkLphS.js} +1 -1
- package/dist/webdist/assets/{flowDiagram-UKHOOZJN-wAus-SqB.js → flowDiagram-UKHOOZJN-Bfha7bpG.js} +1 -1
- package/dist/webdist/assets/{folder-input-CPFYQQYm.js → folder-input-BRjaJam7.js} +1 -1
- package/dist/webdist/assets/{folder-plus-BS4MX3uc.js → folder-plus-DBJ9oQjK.js} +1 -1
- package/dist/webdist/assets/{ganttDiagram-PKOTCBZU-iFTGTcny.js → ganttDiagram-PKOTCBZU-CJotaSgm.js} +1 -1
- package/dist/webdist/assets/{git-branch-CH_JRbeH.js → git-branch-DerJ3eCK.js} +1 -1
- package/dist/webdist/assets/{gitGraphDiagram-DS77QQ5N-B3Lim-un.js → gitGraphDiagram-DS77QQ5N-C8za5q5H.js} +1 -1
- package/dist/webdist/assets/{index-m7O9h-cc.js → index-CRd__4R1.js} +6 -6
- package/dist/webdist/assets/{infoDiagram-6WML65LV-2U3_w76t.js → infoDiagram-6WML65LV-C95kKxPZ.js} +1 -1
- package/dist/webdist/assets/{ishikawaDiagram-WSZJBQD7-8qFZeY06.js → ishikawaDiagram-WSZJBQD7-DOIqcMyH.js} +1 -1
- package/dist/webdist/assets/{journeyDiagram-NVQOT4AX-BiQ4W5bp.js → journeyDiagram-NVQOT4AX-BBirkGE7.js} +1 -1
- package/dist/webdist/assets/{kanban-definition-27J2QSJJ-xUKbXLDF.js → kanban-definition-27J2QSJJ-CPhjxJyV.js} +1 -1
- package/dist/webdist/assets/{linear-Cfppb_KP.js → linear-BWhxZFqF.js} +1 -1
- package/dist/webdist/assets/{lock-_kPFqMMF.js → lock-CpPOIG8p.js} +1 -1
- package/dist/webdist/assets/{mermaid.core-Cqc4S48f.js → mermaid.core-DocKtbj4.js} +4 -4
- package/dist/webdist/assets/{mindmap-definition-FAOFIHXS-DfAXBfEp.js → mindmap-definition-FAOFIHXS-wL4xGOU_.js} +1 -1
- package/dist/webdist/assets/{pegDiagram-VL7TDLO6-BDnh7A9L.js → pegDiagram-VL7TDLO6-D19VvRVO.js} +1 -1
- package/dist/webdist/assets/{pencil-B65o2Xsj.js → pencil-c-PJkJes.js} +1 -1
- package/dist/webdist/assets/{pieDiagram-7S7Q4E2Y-BoEHVtTF.js → pieDiagram-7S7Q4E2Y-Doy7WZyw.js} +1 -1
- package/dist/webdist/assets/{plus-BCCJyhZC.js → plus-CP7d5krT.js} +1 -1
- package/dist/webdist/assets/{quadrantDiagram-CIZ2JOQS-BvKFv-w0.js → quadrantDiagram-CIZ2JOQS-BO535Mye.js} +1 -1
- package/dist/webdist/assets/{railroadDiagram-AXF67PYL-BLrX-HQS.js → railroadDiagram-AXF67PYL-C_F6C_-j.js} +1 -1
- package/dist/webdist/assets/{refresh-cw-BMe9yq9k.js → refresh-cw-CUFncOr4.js} +1 -1
- package/dist/webdist/assets/{requirementDiagram-LRYGKXZP-r4LjKdJa.js → requirementDiagram-LRYGKXZP-COStqNVI.js} +1 -1
- package/dist/webdist/assets/{rotate-ccw-QlaGmqOe.js → rotate-ccw-gR3mMTRM.js} +1 -1
- package/dist/webdist/assets/{sankeyDiagram-W5VNT64P-CbTbNO1R.js → sankeyDiagram-W5VNT64P-DrpcfTw1.js} +1 -1
- package/dist/webdist/assets/{sequenceDiagram-SI44F4Z6-C3cZYRGT.js → sequenceDiagram-SI44F4Z6-CQ1WUoj0.js} +1 -1
- package/dist/webdist/assets/{sizeCapture-X5ZJPWSS-CYYQ8wtn.js → sizeCapture-X5ZJPWSS-CExk2dPw.js} +1 -1
- package/dist/webdist/assets/{skeleton-CC9ODrk4.js → skeleton-CapS3LhZ.js} +1 -1
- package/dist/webdist/assets/{sliders-horizontal-BFSPlX5c.js → sliders-horizontal-VjLq-9i0.js} +1 -1
- package/dist/webdist/assets/{sparkles-CmEUYmzj.js → sparkles-BS98k72s.js} +1 -1
- package/dist/webdist/assets/{star-CyudL0Do.js → star-Ce5Pu8jP.js} +1 -1
- package/dist/webdist/assets/{stateDiagram-OKZ733FA-Bdj39Nof.js → stateDiagram-OKZ733FA-6IQ9pQNr.js} +1 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-D-qEGyyy.js +1 -0
- package/dist/webdist/assets/{swimlanes-SLNWSIFB-W3xWeGOJ.js → swimlanes-SLNWSIFB-0AoFXo4W.js} +2 -2
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-DJV5Gciz.js +8 -0
- package/dist/webdist/assets/{switch-BDarVW8W.js → switch-BVPOy4cS.js} +1 -1
- package/dist/webdist/assets/{terminal-Bvnu3OHJ.js → terminal-WfRPZiaW.js} +1 -1
- package/dist/webdist/assets/{timeline-definition-Z64GVDOM-DnavzBwI.js → timeline-definition-Z64GVDOM-LPqGGX5H.js} +1 -1
- package/dist/webdist/assets/{trash-2-C43ex79G.js → trash-2-DZYSgl2R.js} +1 -1
- package/dist/webdist/assets/{useIsDesktop-BC85xPnA.js → useIsDesktop-CjFyl6hu.js} +1 -1
- package/dist/webdist/assets/{vennDiagram-T6HMQDX7-DdJs_uLj.js → vennDiagram-T6HMQDX7--BcdXECz.js} +1 -1
- package/dist/webdist/assets/{vram-BWaHTGD0.js → vram-DlcIXX82.js} +1 -1
- package/dist/webdist/assets/{wardleyDiagram-T6FBY63Y-91gPbjKx.js → wardleyDiagram-T6FBY63Y-Cdki47W1.js} +1 -1
- package/dist/webdist/assets/{wrench-Dlm2fJiY.js → wrench-DOaBHWWN.js} +1 -1
- package/dist/webdist/assets/{xychartDiagram-ELKLHX3M-DDKDUQ8u.js → xychartDiagram-ELKLHX3M-3hkxEbMo.js} +1 -1
- package/dist/webdist/index.html +1 -1
- package/package.json +1 -1
- package/dist/webdist/assets/CodeHomeScreen-BbrTdGuL.js +0 -1
- package/dist/webdist/assets/RoutineEditPage-DqDEDN7O.js +0 -1
- package/dist/webdist/assets/RoutinesPanel-C0CgIiju.js +0 -1
- package/dist/webdist/assets/SidebarResizeHandle-eJlzaNXV.js +0 -2
- package/dist/webdist/assets/WorkspaceScreen-CLXpSocV.js +0 -1
- package/dist/webdist/assets/channel-D7Or72nc.js +0 -1
- package/dist/webdist/assets/classDiagram-JCYQIIEL-CoD8BgVw.js +0 -1
- package/dist/webdist/assets/classDiagram-v2-OCEON4UE-CoD8BgVw.js +0 -1
- package/dist/webdist/assets/stateDiagram-v2-UEYNNEHI-B3xKgUl_.js +0 -1
- package/dist/webdist/assets/swimlanesDiagram-ULZ7WXOC-DSpzEq_Q.js +0 -8
package/dist/cli.js
CHANGED
|
@@ -5753,6 +5753,12 @@ var SUPPORTED = {
|
|
|
5753
5753
|
hermes: { bin: "hermes", label: "Hermes Agent", install: "npm install -g hermes-agent", prepareConfig: prepareHermes },
|
|
5754
5754
|
pi: { bin: "pi", label: "pi", install: "npm install -g @earendil-works/pi-coding-agent", prepareConfig: preparePi }
|
|
5755
5755
|
};
|
|
5756
|
+
var CLAUDE_AUTO_COMPACT_WINDOW_MIN = 1e5;
|
|
5757
|
+
var CLAUDE_AUTO_COMPACT_WINDOW_MAX = 1e6;
|
|
5758
|
+
function clampAutoCompactWindow(ctx) {
|
|
5759
|
+
return Math.min(CLAUDE_AUTO_COMPACT_WINDOW_MAX, Math.max(CLAUDE_AUTO_COMPACT_WINDOW_MIN, Math.round(ctx)));
|
|
5760
|
+
}
|
|
5761
|
+
var CLAUDE_AUTOCOMPACT_PCT_OVERRIDE = "80";
|
|
5756
5762
|
var realSpawn = (cmd, args, opts) => {
|
|
5757
5763
|
if (!opts?.shell) return spawn4(cmd, args, opts);
|
|
5758
5764
|
const resolved = resolveExecutable(cmd);
|
|
@@ -6180,6 +6186,15 @@ Open ${base2} \u2192 Models \u2192 Load a model, then run this again.
|
|
|
6180
6186
|
// Opt into gateway model discovery: Claude Code queries our /v1/models at startup and
|
|
6181
6187
|
// populates the /model picker with the local library (gateway synthesises the entries).
|
|
6182
6188
|
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: "1",
|
|
6189
|
+
// Founder-reported: the ctx-fill display "jumps between full and empty" and the CLI "never
|
|
6190
|
+
// auto-compacts at 80%, always reaches 100% and fails". The second half is Claude Code
|
|
6191
|
+
// assuming a generic ~200K context window for our unrecognized model id and only compacting
|
|
6192
|
+
// near THAT — see clampAutoCompactWindow's own doc comment for the full root cause and its
|
|
6193
|
+
// documented [100_000, 1_000_000] floor/ceiling. Only set when the daemon actually reports a
|
|
6194
|
+
// real ctx (status.model.ctx) — an absent/zero value means "don't know", and guessing a
|
|
6195
|
+
// window here would be worse than leaving the CLI's own generic default in place.
|
|
6196
|
+
...status.model?.ctx ? { CLAUDE_CODE_AUTO_COMPACT_WINDOW: String(clampAutoCompactWindow(status.model.ctx)) } : {},
|
|
6197
|
+
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE,
|
|
6183
6198
|
// Cap background-agent fan-out at what the engine can actually run concurrently.
|
|
6184
6199
|
//
|
|
6185
6200
|
// Claude Code spawns subagents in parallel, and each is a full, independent request to the
|
|
@@ -7140,13 +7155,16 @@ var AUTO_MODE_ALLOWED_TOOLS = {
|
|
|
7140
7155
|
claude: ["WebSearch", "WebFetch"]
|
|
7141
7156
|
};
|
|
7142
7157
|
var MAX_SEEDED_MESSAGE_CHARS = 4e3;
|
|
7143
|
-
var UNSEEDABLE = /["\u0000-\u001f]/;
|
|
7158
|
+
var UNSEEDABLE = /["\u0000-\u0008\u000b\u000c\u000e-\u001f]/;
|
|
7159
|
+
function normalizeSeededMessage(message) {
|
|
7160
|
+
return message.replace(/[\r\n\t]+/g, " ").trim();
|
|
7161
|
+
}
|
|
7144
7162
|
function canSeedFirstMessage(message, agent) {
|
|
7145
7163
|
if (agent !== "claude") return false;
|
|
7146
|
-
const
|
|
7147
|
-
if (
|
|
7148
|
-
if (UNSEEDABLE.test(
|
|
7149
|
-
if (
|
|
7164
|
+
const normalized = normalizeSeededMessage(message);
|
|
7165
|
+
if (normalized.length === 0 || normalized.length > MAX_SEEDED_MESSAGE_CHARS) return false;
|
|
7166
|
+
if (UNSEEDABLE.test(normalized)) return false;
|
|
7167
|
+
if (normalized.endsWith("\\")) return false;
|
|
7150
7168
|
return true;
|
|
7151
7169
|
}
|
|
7152
7170
|
function buildTerminalLaunchCommand(agent, port2, token, sessionId, launchedOnce, permissionMode, mode, firstMessage) {
|
|
@@ -7155,7 +7173,7 @@ function buildTerminalLaunchCommand(agent, port2, token, sessionId, launchedOnce
|
|
|
7155
7173
|
const modeArg = permissionMode ? ` --permission-mode ${permissionMode}` : "";
|
|
7156
7174
|
const allowed = mode === "auto" ? AUTO_MODE_ALLOWED_TOOLS[agent] : void 0;
|
|
7157
7175
|
const allowedArg = allowed?.length ? ` --allowedTools ${allowed.join(",")}` : "";
|
|
7158
|
-
const promptArg = firstMessage && canSeedFirstMessage(firstMessage, agent) ? ` ${quotePtyShellArg(firstMessage
|
|
7176
|
+
const promptArg = firstMessage && canSeedFirstMessage(firstMessage, agent) ? ` ${quotePtyShellArg(normalizeSeededMessage(firstMessage))}` : "";
|
|
7159
7177
|
return `turbollm launch ${agent}${promptArg} --port ${port2} --token ${token}${sessionArg}${modeArg}${allowedArg}`;
|
|
7160
7178
|
}
|
|
7161
7179
|
function err(c, s, code, msg2) {
|
|
@@ -8188,7 +8206,7 @@ function profileToArgs(p, m, caps, cores = 0, sys, binPath) {
|
|
|
8188
8206
|
}
|
|
8189
8207
|
if (has("--parallel")) a.push("--parallel", String(p.parallel));
|
|
8190
8208
|
if (p.parallel > 1 && p.kvUnified && has("--kv-unified")) a.push("--kv-unified");
|
|
8191
|
-
if (m.moe && !p.nCpuMoeFit && p.
|
|
8209
|
+
if (m.moe && !p.nCpuMoeFit && p.ngl > 0 && has("--n-cpu-moe")) a.push("--n-cpu-moe", String(p.nCpuMoe));
|
|
8192
8210
|
const kvOk = (t) => caps.kvTypes.includes(t);
|
|
8193
8211
|
if (p.kvTypeK !== "f16" && has("--cache-type-k") && kvOk(p.kvTypeK)) a.push("--cache-type-k", p.kvTypeK);
|
|
8194
8212
|
if (p.kvTypeV !== "f16" && has("--cache-type-v") && kvOk(p.kvTypeV)) a.push("--cache-type-v", p.kvTypeV);
|
|
@@ -13488,6 +13506,10 @@ var ConversationStore = class {
|
|
|
13488
13506
|
if (!this.hasColumn("api_usage", "harness")) this.db.exec(`ALTER TABLE api_usage ADD COLUMN harness TEXT;`);
|
|
13489
13507
|
this.db.exec(`PRAGMA user_version = 43;`);
|
|
13490
13508
|
}
|
|
13509
|
+
if (v < 44) {
|
|
13510
|
+
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_api_usage_code_session_tokens ON api_usage(code_session_id, prompt_tokens);`);
|
|
13511
|
+
this.db.exec(`PRAGMA user_version = 44;`);
|
|
13512
|
+
}
|
|
13491
13513
|
}
|
|
13492
13514
|
listConversations(q, kind = "all") {
|
|
13493
13515
|
if (q) {
|
|
@@ -13874,10 +13896,37 @@ var ConversationStore = class {
|
|
|
13874
13896
|
$harness: rec.harness ?? null
|
|
13875
13897
|
});
|
|
13876
13898
|
}
|
|
13877
|
-
/**
|
|
13878
|
-
*
|
|
13879
|
-
*
|
|
13880
|
-
*
|
|
13899
|
+
/** The session's own gateway-request stats (ADR-284, revised twice — founder-reported "ctx
|
|
13900
|
+
* fill jumps between full and empty in the same session", then a review pass on that same fix
|
|
13901
|
+
* catching that it had gone on to freeze the LAST-TURN stats too). Two different questions,
|
|
13902
|
+
* two different rows:
|
|
13903
|
+
*
|
|
13904
|
+
* `ctxUsed` is the MAX prompt_tokens row, not literally the most-recently-INSERTED one. Every
|
|
13905
|
+
* request a real `claude` CLI process makes — the main conversation's own turn AND every
|
|
13906
|
+
* parallel Task-tool sub-agent it spawns — shares the SAME code_session_id: `resolveCodeSession`
|
|
13907
|
+
* (gateway.ts) derives it purely from the bearer token, and the CLI mints exactly one token
|
|
13908
|
+
* (ANTHROPIC_AUTH_TOKEN, set once at launch) for its whole process, sub-agents included. A
|
|
13909
|
+
* sub-agent's own prompt is a small, isolated sub-task — nothing like the full resent
|
|
13910
|
+
* conversation — so whichever of the two finishes last used to decide what the ring showed:
|
|
13911
|
+
* the real, large, ever-growing main-turn prompt one poll, a tiny sub-agent prompt the next,
|
|
13912
|
+
* with no change to the actual conversation in between. The MAX is the honest answer to "how
|
|
13913
|
+
* full has this session's context gotten" — a real Claude Code CLI resends the whole
|
|
13914
|
+
* conversation every turn, so its size only grows within one continuous conversation, and a
|
|
13915
|
+
* sub-agent (always smaller) can never legitimately raise that high-water mark. Trade-off,
|
|
13916
|
+
* accepted: after a real `/clear` inside the CLI (invisible to the daemon — a terminal-agent
|
|
13917
|
+
* session's turns are never persisted here, see ADR-297), this keeps reporting the pre-clear
|
|
13918
|
+
* high-water mark until the new conversation grows past it. A temporarily-stale-high ring
|
|
13919
|
+
* reading after a rare, deliberate user action beats an unpredictable full/empty flicker on
|
|
13920
|
+
* every ordinary agentic turn with sub-agents.
|
|
13921
|
+
*
|
|
13922
|
+
* `promptTokens`/`genTokens`/`promptTps`/`genTps` are the temporally-LAST row instead — these
|
|
13923
|
+
* power TerminalToolbar.tsx's composer-parity stats row, which reads as "your last turn", not
|
|
13924
|
+
* "session high-water mark". Sharing the MAX row here (the original version of this fix) meant
|
|
13925
|
+
* a sub-agent call landing after the real turn hid its own genTokens/tps behind the earlier,
|
|
13926
|
+
* larger turn's numbers, and after a `/clear` these froze at the pre-clear turn's numbers
|
|
13927
|
+
* forever, same failure shape as the ctxUsed bug this method was written to fix in the first
|
|
13928
|
+
* place. null when the session has made no gateway requests yet (fresh session, or a
|
|
13929
|
+
* non-terminal-agent one). */
|
|
13881
13930
|
getLastApiUsageForSession(codeSessionId) {
|
|
13882
13931
|
const row = this.db.prepare(`
|
|
13883
13932
|
SELECT prompt_tokens, gen_tokens, duration_ms, prompt_tps, gen_tps FROM api_usage
|
|
@@ -13885,8 +13934,12 @@ var ConversationStore = class {
|
|
|
13885
13934
|
ORDER BY created_at DESC LIMIT 1
|
|
13886
13935
|
`).get({ $codeSessionId: codeSessionId });
|
|
13887
13936
|
if (!row) return null;
|
|
13937
|
+
const ctxUsed = this.db.prepare(`
|
|
13938
|
+
SELECT MAX(prompt_tokens) as maxPromptTokens FROM api_usage WHERE code_session_id = $codeSessionId
|
|
13939
|
+
`).get({ $codeSessionId: codeSessionId }).maxPromptTokens;
|
|
13888
13940
|
const seconds = row.duration_ms != null && row.duration_ms > 0 ? row.duration_ms / 1e3 : null;
|
|
13889
13941
|
return {
|
|
13942
|
+
ctxUsed,
|
|
13890
13943
|
promptTokens: row.prompt_tokens,
|
|
13891
13944
|
genTokens: row.gen_tokens,
|
|
13892
13945
|
promptTps: row.prompt_tps ?? (seconds ? row.prompt_tokens / seconds : null),
|
|
@@ -22019,6 +22072,9 @@ function registerApi(app2, d) {
|
|
|
22019
22072
|
return err4(c, 400, "invalid_profile_value", "gpu.tensorParallelSize must be an integer \u2265 1.");
|
|
22020
22073
|
}
|
|
22021
22074
|
}
|
|
22075
|
+
if (p.nCpuMoe !== void 0 && (typeof p.nCpuMoe !== "number" || !Number.isFinite(p.nCpuMoe) || p.nCpuMoe < 0)) {
|
|
22076
|
+
return err4(c, 400, "invalid_profile_value", "nCpuMoe must be a non-negative number.");
|
|
22077
|
+
}
|
|
22022
22078
|
const engineId = c.req.query("engine") || d.registry.active()?.id || "*";
|
|
22023
22079
|
d.store.update((cfg2) => {
|
|
22024
22080
|
setModelProfile(cfg2, key, engineId, p);
|
|
@@ -24249,7 +24305,59 @@ function mapFromOpenAI(oai, modelName) {
|
|
|
24249
24305
|
usage: { input_tokens: usage?.prompt_tokens ?? 0, output_tokens: usage?.completion_tokens ?? 0 }
|
|
24250
24306
|
};
|
|
24251
24307
|
}
|
|
24252
|
-
|
|
24308
|
+
var DEFAULT_PING_INTERVAL_MS = 1e4;
|
|
24309
|
+
function waitOrPing(pending2, ms) {
|
|
24310
|
+
return new Promise((resolve5) => {
|
|
24311
|
+
const timer = setTimeout(() => resolve5("ping"), ms);
|
|
24312
|
+
pending2.then(
|
|
24313
|
+
() => {
|
|
24314
|
+
clearTimeout(timer);
|
|
24315
|
+
resolve5("data");
|
|
24316
|
+
},
|
|
24317
|
+
() => {
|
|
24318
|
+
clearTimeout(timer);
|
|
24319
|
+
resolve5("data");
|
|
24320
|
+
}
|
|
24321
|
+
);
|
|
24322
|
+
});
|
|
24323
|
+
}
|
|
24324
|
+
async function pingWhilePending(pending2, emitPing, pingIntervalMs = DEFAULT_PING_INTERVAL_MS, onOrphan) {
|
|
24325
|
+
pending2.catch(() => {
|
|
24326
|
+
});
|
|
24327
|
+
let nextPingAt = Date.now() + pingIntervalMs;
|
|
24328
|
+
while (true) {
|
|
24329
|
+
const remaining = Math.max(0, nextPingAt - Date.now());
|
|
24330
|
+
const outcome = remaining === 0 ? "ping" : await waitOrPing(pending2, remaining);
|
|
24331
|
+
if (outcome === "ping") {
|
|
24332
|
+
try {
|
|
24333
|
+
await emitPing();
|
|
24334
|
+
} catch (e) {
|
|
24335
|
+
if (onOrphan) pending2.then(onOrphan).catch(() => {
|
|
24336
|
+
});
|
|
24337
|
+
throw e;
|
|
24338
|
+
}
|
|
24339
|
+
nextPingAt = Date.now() + pingIntervalMs;
|
|
24340
|
+
continue;
|
|
24341
|
+
}
|
|
24342
|
+
return pending2;
|
|
24343
|
+
}
|
|
24344
|
+
}
|
|
24345
|
+
function messageStartEvent(msgId, modelName) {
|
|
24346
|
+
return sse("message_start", {
|
|
24347
|
+
message: {
|
|
24348
|
+
id: msgId,
|
|
24349
|
+
type: "message",
|
|
24350
|
+
role: "assistant",
|
|
24351
|
+
content: [],
|
|
24352
|
+
model: modelName,
|
|
24353
|
+
stop_reason: null,
|
|
24354
|
+
stop_sequence: null,
|
|
24355
|
+
usage: { input_tokens: 0, output_tokens: 1 }
|
|
24356
|
+
}
|
|
24357
|
+
});
|
|
24358
|
+
}
|
|
24359
|
+
async function* streamToAnthropic(oaiStream, modelName, msgId, opts = {}) {
|
|
24360
|
+
const { onUsage, onLive, onToolCalls, pingIntervalMs = DEFAULT_PING_INTERVAL_MS, skipMessageStart = false } = opts;
|
|
24253
24361
|
let blockIdx = 0;
|
|
24254
24362
|
let inThinking = false;
|
|
24255
24363
|
let inText = false;
|
|
@@ -24262,25 +24370,30 @@ async function* streamToAnthropic(oaiStream, modelName, msgId, onUsage, onLive,
|
|
|
24262
24370
|
let promptTps = 0;
|
|
24263
24371
|
let genTps = 0;
|
|
24264
24372
|
let liveOut = 0;
|
|
24265
|
-
yield
|
|
24266
|
-
message: {
|
|
24267
|
-
id: msgId,
|
|
24268
|
-
type: "message",
|
|
24269
|
-
role: "assistant",
|
|
24270
|
-
content: [],
|
|
24271
|
-
model: modelName,
|
|
24272
|
-
stop_reason: null,
|
|
24273
|
-
stop_sequence: null,
|
|
24274
|
-
usage: { input_tokens: 0, output_tokens: 1 }
|
|
24275
|
-
}
|
|
24276
|
-
});
|
|
24373
|
+
if (!skipMessageStart) yield messageStartEvent(msgId, modelName);
|
|
24277
24374
|
const reader = oaiStream.getReader();
|
|
24278
24375
|
const dec = new TextDecoder();
|
|
24279
24376
|
let buf = "";
|
|
24280
24377
|
let failed = false;
|
|
24378
|
+
let nextPingAt = Date.now() + pingIntervalMs;
|
|
24281
24379
|
try {
|
|
24282
24380
|
outer: while (true) {
|
|
24283
|
-
const
|
|
24381
|
+
const readPromise = reader.read();
|
|
24382
|
+
readPromise.catch(() => {
|
|
24383
|
+
});
|
|
24384
|
+
let result;
|
|
24385
|
+
while (true) {
|
|
24386
|
+
const remaining = Math.max(0, nextPingAt - Date.now());
|
|
24387
|
+
const outcome = remaining === 0 ? "ping" : await waitOrPing(readPromise, remaining);
|
|
24388
|
+
if (outcome === "ping") {
|
|
24389
|
+
yield sse("ping", {});
|
|
24390
|
+
nextPingAt = Date.now() + pingIntervalMs;
|
|
24391
|
+
continue;
|
|
24392
|
+
}
|
|
24393
|
+
result = await readPromise;
|
|
24394
|
+
break;
|
|
24395
|
+
}
|
|
24396
|
+
const { done, value } = result;
|
|
24284
24397
|
if (done) break;
|
|
24285
24398
|
buf += dec.decode(value, { stream: true });
|
|
24286
24399
|
const lines = buf.split("\n");
|
|
@@ -24825,7 +24938,23 @@ function anthropicErrorType(status) {
|
|
|
24825
24938
|
function asClientStatus(status) {
|
|
24826
24939
|
return status >= 400 && status <= 599 ? status : 500;
|
|
24827
24940
|
}
|
|
24828
|
-
function
|
|
24941
|
+
function classifyGateError(e) {
|
|
24942
|
+
const aborted = e.message === "gate_acquire_aborted";
|
|
24943
|
+
return aborted ? { status: 400, type: "invalid_request_error", message: "Client disconnected while queued for the engine." } : { status: 503, type: "overloaded_error", message: "Timed out waiting for a free engine slot." };
|
|
24944
|
+
}
|
|
24945
|
+
function classifyFetchError(e, ac) {
|
|
24946
|
+
const err8 = e;
|
|
24947
|
+
const isAbort = err8.name === "AbortError" || ac.signal.aborted;
|
|
24948
|
+
const cause = err8.cause instanceof Error ? `: ${err8.cause.message}` : "";
|
|
24949
|
+
return {
|
|
24950
|
+
status: 500,
|
|
24951
|
+
type: "api_error",
|
|
24952
|
+
message: isAbort ? "Client disconnected before the engine responded." : `${err8.message || "Engine unreachable."}${cause}`
|
|
24953
|
+
};
|
|
24954
|
+
}
|
|
24955
|
+
function registerGateway(app2, d, opts = {}) {
|
|
24956
|
+
const pingIntervalMs = opts.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS;
|
|
24957
|
+
const gateAcquireTimeoutMs = opts.gateAcquireTimeoutMs ?? 6e5;
|
|
24829
24958
|
app2.post("/v1/messages", async (c) => {
|
|
24830
24959
|
let req;
|
|
24831
24960
|
try {
|
|
@@ -24885,23 +25014,131 @@ function registerGateway(app2, d) {
|
|
|
24885
25014
|
if (guidance?.forceTextOnly) oaiBody.tool_choice = "none";
|
|
24886
25015
|
const oaiAlias = engineModelAlias(d.registry.active()?.kind ?? "");
|
|
24887
25016
|
if (oaiAlias) oaiBody.model = oaiAlias;
|
|
25017
|
+
const ac = clientAbort(c);
|
|
25018
|
+
if (req.stream) {
|
|
25019
|
+
const msgId = `msg_${randomUUID13().replace(/-/g, "")}`;
|
|
25020
|
+
return streamSSE4(c, async (stream) => {
|
|
25021
|
+
let gateRelease2 = null;
|
|
25022
|
+
let generationStarted = false;
|
|
25023
|
+
stream.onAbort(() => ac.abort());
|
|
25024
|
+
const ping = () => stream.writeSSE({ event: "ping", data: JSON.stringify({ type: "ping" }) });
|
|
25025
|
+
try {
|
|
25026
|
+
try {
|
|
25027
|
+
await stream.writeSSE(messageStartEvent(msgId, modelName));
|
|
25028
|
+
if (d.gate) {
|
|
25029
|
+
try {
|
|
25030
|
+
gateRelease2 = await pingWhilePending(
|
|
25031
|
+
d.gate.acquire("bg", { signal: c.req.raw.signal, timeoutMs: gateAcquireTimeoutMs }),
|
|
25032
|
+
ping,
|
|
25033
|
+
pingIntervalMs,
|
|
25034
|
+
(release) => release()
|
|
25035
|
+
);
|
|
25036
|
+
} catch (e) {
|
|
25037
|
+
const { type, message } = classifyGateError(e);
|
|
25038
|
+
await stream.writeSSE({ event: "error", data: JSON.stringify({ type: "error", error: { type, message } }) });
|
|
25039
|
+
return;
|
|
25040
|
+
}
|
|
25041
|
+
}
|
|
25042
|
+
d.manager.generationStart();
|
|
25043
|
+
generationStarted = true;
|
|
25044
|
+
const requestStart2 = Date.now();
|
|
25045
|
+
let res2;
|
|
25046
|
+
try {
|
|
25047
|
+
res2 = await pingWhilePending(
|
|
25048
|
+
fetch(`${target}/v1/chat/completions`, {
|
|
25049
|
+
method: "POST",
|
|
25050
|
+
headers: { "Content-Type": "application/json" },
|
|
25051
|
+
body: JSON.stringify(oaiBody),
|
|
25052
|
+
signal: ac.signal
|
|
25053
|
+
}),
|
|
25054
|
+
ping,
|
|
25055
|
+
pingIntervalMs
|
|
25056
|
+
// No onOrphan: an orphaned Response has nothing to release — its body is simply
|
|
25057
|
+
// never read and gets garbage-collected, unlike gate.acquire()'s grant above.
|
|
25058
|
+
);
|
|
25059
|
+
} catch (e) {
|
|
25060
|
+
const { type, message } = classifyFetchError(e, ac);
|
|
25061
|
+
await stream.writeSSE({ event: "error", data: JSON.stringify({ type: "error", error: { type, message } }) });
|
|
25062
|
+
return;
|
|
25063
|
+
}
|
|
25064
|
+
if (!res2.ok || !res2.body) {
|
|
25065
|
+
const { message, type } = await describeEngineError(res2);
|
|
25066
|
+
await stream.writeSSE({
|
|
25067
|
+
event: "error",
|
|
25068
|
+
data: JSON.stringify({ type: "error", error: { type: type ?? anthropicErrorType(res2.status), message } })
|
|
25069
|
+
});
|
|
25070
|
+
return;
|
|
25071
|
+
}
|
|
25072
|
+
const gen = streamToAnthropic(res2.body, modelName, msgId, {
|
|
25073
|
+
onUsage: (u) => {
|
|
25074
|
+
try {
|
|
25075
|
+
d.manager.recordCompletion({
|
|
25076
|
+
inputTokens: u.inputTokens,
|
|
25077
|
+
outputTokens: u.outputTokens,
|
|
25078
|
+
promptTps: u.promptTps,
|
|
25079
|
+
genTps: u.genTps
|
|
25080
|
+
});
|
|
25081
|
+
d.db.recordApiUsage({
|
|
25082
|
+
source: "anthropic",
|
|
25083
|
+
modelKey: req.model ?? null,
|
|
25084
|
+
promptTokens: u.inputTokens,
|
|
25085
|
+
genTokens: u.outputTokens,
|
|
25086
|
+
codeSessionId: anthropicCodeSessionId,
|
|
25087
|
+
durationMs: Date.now() - requestStart2,
|
|
25088
|
+
promptTps: u.promptTps,
|
|
25089
|
+
genTps: u.genTps,
|
|
25090
|
+
harness: anthropicHarness
|
|
25091
|
+
});
|
|
25092
|
+
} catch {
|
|
25093
|
+
}
|
|
25094
|
+
},
|
|
25095
|
+
// Live per-request progress for the engine card (prefill % + token count),
|
|
25096
|
+
// so Claude Code traffic shows the same live row as in-app chat.
|
|
25097
|
+
onLive: (live) => {
|
|
25098
|
+
try {
|
|
25099
|
+
d.manager.setLiveGen(live);
|
|
25100
|
+
} catch {
|
|
25101
|
+
}
|
|
25102
|
+
},
|
|
25103
|
+
// Coding-activity attribution for terminal-agent sessions — see
|
|
25104
|
+
// observeCodeSessionTurn. Nothing to attribute for any other client.
|
|
25105
|
+
onToolCalls: (calls) => {
|
|
25106
|
+
if (!anthropicCodeSessionId) return;
|
|
25107
|
+
try {
|
|
25108
|
+
observeCodeSessionTurn(d, anthropicCodeSessionId, calls);
|
|
25109
|
+
} catch {
|
|
25110
|
+
}
|
|
25111
|
+
},
|
|
25112
|
+
skipMessageStart: true
|
|
25113
|
+
// already sent above, before the queue wait
|
|
25114
|
+
});
|
|
25115
|
+
for await (const evt of gen) {
|
|
25116
|
+
await stream.writeSSE({ event: evt.event, data: evt.data });
|
|
25117
|
+
}
|
|
25118
|
+
} finally {
|
|
25119
|
+
ac.abort();
|
|
25120
|
+
if (generationStarted) d.manager.generationEnd();
|
|
25121
|
+
gateRelease2?.();
|
|
25122
|
+
}
|
|
25123
|
+
} catch (e) {
|
|
25124
|
+
await stream.writeSSE({
|
|
25125
|
+
event: "error",
|
|
25126
|
+
data: JSON.stringify({ type: "error", error: { type: "api_error", message: e?.message || "Internal gateway error." } })
|
|
25127
|
+
}).catch(() => {
|
|
25128
|
+
});
|
|
25129
|
+
}
|
|
25130
|
+
});
|
|
25131
|
+
}
|
|
24888
25132
|
let gateRelease = null;
|
|
24889
25133
|
if (d.gate) {
|
|
24890
25134
|
try {
|
|
24891
|
-
gateRelease = await d.gate.acquire("bg", { signal: c.req.raw.signal, timeoutMs:
|
|
25135
|
+
gateRelease = await d.gate.acquire("bg", { signal: c.req.raw.signal, timeoutMs: gateAcquireTimeoutMs });
|
|
24892
25136
|
} catch (e) {
|
|
24893
|
-
const
|
|
24894
|
-
return c.json(
|
|
24895
|
-
{
|
|
24896
|
-
type: "error",
|
|
24897
|
-
error: aborted ? { type: "invalid_request_error", message: "Client disconnected while queued for the engine." } : { type: "overloaded_error", message: "Timed out waiting for a free engine slot." }
|
|
24898
|
-
},
|
|
24899
|
-
aborted ? 400 : 503
|
|
24900
|
-
);
|
|
25137
|
+
const { status: status2, type, message } = classifyGateError(e);
|
|
25138
|
+
return c.json({ type: "error", error: { type, message } }, status2);
|
|
24901
25139
|
}
|
|
24902
25140
|
}
|
|
24903
25141
|
d.manager.generationStart();
|
|
24904
|
-
const ac = clientAbort(c);
|
|
24905
25142
|
const requestStart = Date.now();
|
|
24906
25143
|
let res;
|
|
24907
25144
|
try {
|
|
@@ -24914,19 +25151,8 @@ function registerGateway(app2, d) {
|
|
|
24914
25151
|
} catch (e) {
|
|
24915
25152
|
d.manager.generationEnd();
|
|
24916
25153
|
gateRelease?.();
|
|
24917
|
-
const
|
|
24918
|
-
|
|
24919
|
-
const cause = err8.cause instanceof Error ? `: ${err8.cause.message}` : "";
|
|
24920
|
-
return c.json(
|
|
24921
|
-
{
|
|
24922
|
-
type: "error",
|
|
24923
|
-
error: {
|
|
24924
|
-
type: "api_error",
|
|
24925
|
-
message: isAbort ? "Client disconnected before the engine responded." : `${err8.message || "Engine unreachable."}${cause}`
|
|
24926
|
-
}
|
|
24927
|
-
},
|
|
24928
|
-
500
|
|
24929
|
-
);
|
|
25154
|
+
const { status: status2, type, message } = classifyFetchError(e, ac);
|
|
25155
|
+
return c.json({ type: "error", error: { type, message } }, status2);
|
|
24930
25156
|
}
|
|
24931
25157
|
if (!res.ok || !res.body) {
|
|
24932
25158
|
d.manager.generationEnd();
|
|
@@ -24937,65 +25163,6 @@ function registerGateway(app2, d) {
|
|
|
24937
25163
|
asClientStatus(res.status)
|
|
24938
25164
|
);
|
|
24939
25165
|
}
|
|
24940
|
-
if (req.stream) {
|
|
24941
|
-
const msgId = `msg_${randomUUID13().replace(/-/g, "")}`;
|
|
24942
|
-
const gen = streamToAnthropic(
|
|
24943
|
-
res.body,
|
|
24944
|
-
modelName,
|
|
24945
|
-
msgId,
|
|
24946
|
-
(u) => {
|
|
24947
|
-
try {
|
|
24948
|
-
d.manager.recordCompletion({
|
|
24949
|
-
inputTokens: u.inputTokens,
|
|
24950
|
-
outputTokens: u.outputTokens,
|
|
24951
|
-
promptTps: u.promptTps,
|
|
24952
|
-
genTps: u.genTps
|
|
24953
|
-
});
|
|
24954
|
-
d.db.recordApiUsage({
|
|
24955
|
-
source: "anthropic",
|
|
24956
|
-
modelKey: req.model ?? null,
|
|
24957
|
-
promptTokens: u.inputTokens,
|
|
24958
|
-
genTokens: u.outputTokens,
|
|
24959
|
-
codeSessionId: anthropicCodeSessionId,
|
|
24960
|
-
durationMs: Date.now() - requestStart,
|
|
24961
|
-
promptTps: u.promptTps,
|
|
24962
|
-
genTps: u.genTps,
|
|
24963
|
-
harness: anthropicHarness
|
|
24964
|
-
});
|
|
24965
|
-
} catch {
|
|
24966
|
-
}
|
|
24967
|
-
},
|
|
24968
|
-
// Live per-request progress for the engine card (prefill % + token count),
|
|
24969
|
-
// so Claude Code traffic shows the same live row as in-app chat.
|
|
24970
|
-
(live) => {
|
|
24971
|
-
try {
|
|
24972
|
-
d.manager.setLiveGen(live);
|
|
24973
|
-
} catch {
|
|
24974
|
-
}
|
|
24975
|
-
},
|
|
24976
|
-
// Coding-activity attribution for terminal-agent sessions — see
|
|
24977
|
-
// observeCodeSessionTurn. Nothing to attribute for any other client.
|
|
24978
|
-
(calls) => {
|
|
24979
|
-
if (!anthropicCodeSessionId) return;
|
|
24980
|
-
try {
|
|
24981
|
-
observeCodeSessionTurn(d, anthropicCodeSessionId, calls);
|
|
24982
|
-
} catch {
|
|
24983
|
-
}
|
|
24984
|
-
}
|
|
24985
|
-
);
|
|
24986
|
-
return streamSSE4(c, async (stream) => {
|
|
24987
|
-
stream.onAbort(() => ac.abort());
|
|
24988
|
-
try {
|
|
24989
|
-
for await (const evt of gen) {
|
|
24990
|
-
await stream.writeSSE({ event: evt.event, data: evt.data });
|
|
24991
|
-
}
|
|
24992
|
-
} finally {
|
|
24993
|
-
ac.abort();
|
|
24994
|
-
d.manager.generationEnd();
|
|
24995
|
-
gateRelease?.();
|
|
24996
|
-
}
|
|
24997
|
-
});
|
|
24998
|
-
}
|
|
24999
25166
|
try {
|
|
25000
25167
|
const oaiRes = await res.json();
|
|
25001
25168
|
recordOpenAiUsage(d, oaiRes, "anthropic", req.model ?? null, anthropicCodeSessionId, Date.now() - requestStart, anthropicHarness);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./radix-B0YBjihE.js";import{b as W,u as $,r as b}from"./vendor-C1I6euDx.js";import{u as G,d as H,e as Y,f as J,g as U,a as z,B as C,t as j,c as q,b as h,A as _}from"./index-m7O9h-cc.js";import{f as V}from"./chat-api-WdKnt_cR.js";import{f as X,a as Z}from"./agent-api-BdnGAV-Y.js";import{P as B}from"./personas-B0p0BX69.js";import{C as ee}from"./chevron-left-tBRMVkX5.js";import{R as te}from"./rotate-ccw-QlaGmqOe.js";import{T as se}from"./trash-2-C43ex79G.js";import{C as ne}from"./chevron-right-B16ur-An.js";const ae=()=>({name:"",description:"",systemPrompt:"",skillIds:[],tools:[]});function oe(s){const d=[],x=new Map;for(const n of s){const a=/^mcp__([^_]+(?:_[^_]+)*)__/.exec(n.name);if(!a){d.push(n);continue}const i=a[1],p=/^\[([^\]]+)\]/.exec(n.description),c=p?p[1]:i.replace(/_/g," ");x.has(i)||x.set(i,{key:i,label:c,tools:[]}),x.get(i).tools.push(n)}return{builtin:d,groups:[...x.values()].sort((n,a)=>n.label.localeCompare(a.label))}}function le(s){return s.replace(/^mcp__[^_]+(?:_[^_]+)*__/,"")}function re(s){return s.replace(/^\[[^\]]+\]\s*/,"")}function D({tool:s,checked:d,onToggle:x}){return e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[12px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:d,onChange:x}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"font-mono text-ink",children:le(s.name)}),s.description&&e.jsx("span",{className:"text-faint",children:re(s.description)})]})]})}function ie({group:s,selected:d,onToggleAll:x,onToggleOne:n}){const[a,i]=b.useState(!1),p=s.tools.map(l=>l.name),c=p.filter(l=>d.has(l)).length,o=c===p.length,g=c>0&&!o,u=b.useRef(null);return b.useEffect(()=>{u.current&&(u.current.indeterminate=g)},[g]),e.jsxs("div",{className:"rounded-md border border-border",children:[e.jsxs("div",{className:"flex items-center gap-2 px-2.5 py-2",children:[e.jsx("input",{ref:u,type:"checkbox",checked:o,onChange:()=>x(p,!o)}),e.jsxs("button",{type:"button",onClick:()=>{j("agents","toggle_agent_tool_group"),i(l=>!l)},className:"flex flex-1 items-center gap-1.5 text-left text-[13px] text-ink",children:[e.jsx(ne,{size:12,className:q("shrink-0 text-faint transition-transform",a&&"rotate-90")}),s.label,e.jsxs("span",{className:"text-[11px] text-faint",children:["(",c,"/",p.length,")"]})]})]}),a&&e.jsx("div",{className:"flex flex-col gap-1.5 border-t border-border px-3 py-2 pl-9",children:s.tools.map(l=>e.jsx(D,{tool:l,checked:d.has(l.name),onToggle:()=>n(l.name)},l.name))})]})}function ce({tools:s,selected:d,onChange:x}){const n=new Set(d),{builtin:a,groups:i}=oe(s),p=o=>x(n.has(o)?d.filter(g=>g!==o):[...d,o]),c=(o,g)=>{const u=d.filter(l=>!o.includes(l));x(g?[...u,...o]:u)};return s.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No tools available yet."}):e.jsxs("div",{className:"flex flex-col gap-2",children:[a.length>0&&e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:a.map(o=>e.jsx(D,{tool:o,checked:n.has(o.name),onToggle:()=>p(o.name)},o.name))}),i.map(o=>e.jsx(ie,{group:o,selected:n,onToggleAll:c,onToggleOne:p},o.key))]})}function ve(){const{agentId:s="new"}=W(),d=$(),x=G(),n=s==="new",a=!n&&B.some(t=>t.id===s),i=a?B.find(t=>t.id===s):void 0,p=H(),c=!n&&!a?(p.data??[]).find(t=>t.id===s):void 0,o=Y(),g=J(),u=U(),l=a?g.data?.[s]:void 0,I=z({queryKey:Z.list(),queryFn:X,staleTime:0}),k=I.data??[],w=z({queryKey:["available-tools"],queryFn:V}),N=w.data??[],[m,f]=b.useState(ae()),[S,T]=b.useState(!1),[A,P]=b.useState(!1),[L,R]=b.useState(!1),[E,Q]=b.useState("skills");n&&!S&&(k.length||N.length)&&(f(t=>({...t,skillIds:k.map(r=>r.id),tools:N.map(r=>r.name)})),T(!0)),!n&&!a&&!S&&c&&(f({name:c.name,description:c.description,systemPrompt:c.systemPrompt,skillIds:c.skillIds,tools:c.tools}),T(!0)),a&&!S&&i&&g.isSuccess&&(k.length||N.length)&&(f({name:l?.name??i.name,description:l?.description??i.description,systemPrompt:l?.systemPrompt??i.systemPrompt,skillIds:l?.skillIds??k.map(t=>t.id),tools:l?.tools??N.map(t=>t.name)}),T(!0));const y=()=>{j("agents","back_to_agents"),d("/customize")},O=t=>f(r=>({...r,skillIds:r.skillIds.includes(t)?r.skillIds.filter(v=>v!==t):[...r.skillIds,t]})),F=()=>{if(!m.name.trim()){h.error("Name is required.");return}P(!0);const t={name:m.name.trim(),description:m.description.trim(),systemPrompt:m.systemPrompt,skillIds:m.skillIds,tools:m.tools};if(a){u.save.mutate({id:s,override:t},{onSuccess:()=>{h.success("Agent saved."),y()},onError:v=>{h.error(v instanceof _?v.message:"Could not save agent."),P(!1)}});return}const r={onSuccess:()=>{x.invalidateQueries({queryKey:["chat-agents"]}),h.success(n?"Agent created.":"Agent saved."),y()},onError:v=>{h.error(v instanceof _?v.message:"Could not save agent."),P(!1)}};n?o.add.mutate(t,r):o.update.mutate({id:s,patch:t},r)},K=()=>{u.reset.mutate(s,{onSuccess:()=>{h.success("Reset to default."),i&&f({name:i.name,description:i.description,systemPrompt:i.systemPrompt,skillIds:k.map(t=>t.id),tools:N.map(t=>t.name)})},onError:t=>h.error(t instanceof _?t.message:"Could not reset agent.")})},M=()=>{o.remove.mutate(s,{onSuccess:()=>{h.success("Agent deleted."),y()},onError:t=>h.error(t instanceof _?t.message:"Could not delete agent.")})};return!n&&!a&&p.isSuccess&&!c?e.jsxs("div",{className:"flex w-full flex-col items-center gap-3 px-8 py-16",children:[e.jsx("p",{className:"text-[14px] text-muted",children:"That agent no longer exists."}),e.jsx(C,{size:"sm",variant:"outline",onClick:y,children:"Back to agents"})]}):e.jsxs("div",{className:"flex w-full max-w-4xl flex-col gap-5 px-4 py-6 md:px-8",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:y,className:"text-faint hover:text-ink",title:"Back to agents",children:e.jsx(ee,{size:18})}),e.jsx("span",{className:"text-[15px] font-medium text-ink",children:n?"New agent":a?l?"Edit agent (modified built-in)":"Edit agent (built-in)":"Edit agent"}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[a&&e.jsxs(C,{size:"sm",variant:"outline",onClick:()=>{j("agents","reset_agent_to_default"),K()},disabled:u.reset.isPending,children:[e.jsx(te,{size:13})," Reset to default"]}),e.jsx(C,{size:"sm",variant:"outline",onClick:y,children:"Cancel"}),e.jsx(C,{size:"sm",onClick:()=>{j("agents","save_agent"),F()},disabled:A||!m.name.trim(),children:A?"Saving…":"Save"})]})]}),a&&e.jsx("p",{className:"rounded-md border border-border bg-panel px-3 py-2 text-[12px] text-muted",children:"Built-in agents can be edited in place — Reset to default discards your changes and restores TurboLLM's original prompt and access."}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Name"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"Release Notes Writer",value:m.name,onChange:t=>f(r=>({...r,name:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Description"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"What this agent is for, in one line",value:m.description,onChange:t=>f(r=>({...r,description:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"System prompt"}),e.jsx("textarea",{className:"min-h-[160px] resize-y rounded-md border border-border bg-bg px-3 py-2 font-mono text-[12px] leading-relaxed text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"You are…",value:m.systemPrompt,onChange:t=>f(r=>({...r,systemPrompt:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-2.5",children:[e.jsx("div",{className:"inline-flex w-fit rounded-md border border-border p-0.5",children:["skills","tools"].map(t=>e.jsx("button",{type:"button",onClick:()=>{j("agents","switch_agent_form_tab"),Q(t)},className:q("rounded px-3 py-1.5 text-[13px] font-medium transition-colors",E===t?"bg-accent/12 text-accent":"text-muted hover:text-ink"),children:t==="skills"?`Skills (${m.skillIds.length})`:`Tools (${m.tools.length})`},t))}),E==="skills"?I.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):k.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No skills yet — create one under Customize → Skills."}):e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:k.map(t=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[13px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:m.skillIds.includes(t.id),onChange:()=>O(t.id)}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"text-ink",children:t.name}),t.description&&e.jsx("span",{className:"text-[12px] text-muted",children:t.description})]})]},t.id))}):w.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):e.jsx(ce,{tools:N,selected:m.tools,onChange:t=>f(r=>({...r,tools:t}))})]}),!n&&!a&&(L?e.jsxs("div",{className:"flex items-center gap-2 self-start rounded-md border border-border bg-panel p-2 text-[12px]",children:[e.jsx("span",{className:"flex-1 text-muted",children:"Delete this agent?"}),e.jsx("button",{type:"button",onClick:()=>{j("agents","delete_agent"),M()},className:"rounded px-2 py-1 text-[color:var(--err)] hover:bg-[color:color-mix(in_srgb,var(--err)_12%,transparent)]",children:"Delete"}),e.jsx("button",{type:"button",onClick:()=>{j("agents","cancel_delete_agent"),R(!1)},className:"rounded px-2 py-1 text-faint hover:text-ink",children:"Cancel"})]}):e.jsxs("button",{type:"button",onClick:()=>R(!0),className:"flex items-center gap-1.5 self-start text-[12px] text-faint hover:text-[color:var(--err)]",children:[e.jsx(se,{size:13})," Delete agent"]}))]})}export{ve as AgentEditPage};
|
|
1
|
+
import{j as e}from"./radix-B0YBjihE.js";import{b as W,u as $,r as b}from"./vendor-C1I6euDx.js";import{u as G,d as H,e as Y,f as J,g as U,a as z,B as C,t as j,c as q,b as h,A as _}from"./index-CRd__4R1.js";import{f as V}from"./chat-api-BTcC6kED.js";import{f as X,a as Z}from"./agent-api-CpgzOfg0.js";import{P as B}from"./personas-B0p0BX69.js";import{C as ee}from"./chevron-left-BVxkM758.js";import{R as te}from"./rotate-ccw-gR3mMTRM.js";import{T as se}from"./trash-2-DZYSgl2R.js";import{C as ne}from"./chevron-right-BJZRbTUj.js";const ae=()=>({name:"",description:"",systemPrompt:"",skillIds:[],tools:[]});function oe(s){const d=[],x=new Map;for(const n of s){const a=/^mcp__([^_]+(?:_[^_]+)*)__/.exec(n.name);if(!a){d.push(n);continue}const i=a[1],p=/^\[([^\]]+)\]/.exec(n.description),c=p?p[1]:i.replace(/_/g," ");x.has(i)||x.set(i,{key:i,label:c,tools:[]}),x.get(i).tools.push(n)}return{builtin:d,groups:[...x.values()].sort((n,a)=>n.label.localeCompare(a.label))}}function le(s){return s.replace(/^mcp__[^_]+(?:_[^_]+)*__/,"")}function re(s){return s.replace(/^\[[^\]]+\]\s*/,"")}function D({tool:s,checked:d,onToggle:x}){return e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[12px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:d,onChange:x}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"font-mono text-ink",children:le(s.name)}),s.description&&e.jsx("span",{className:"text-faint",children:re(s.description)})]})]})}function ie({group:s,selected:d,onToggleAll:x,onToggleOne:n}){const[a,i]=b.useState(!1),p=s.tools.map(l=>l.name),c=p.filter(l=>d.has(l)).length,o=c===p.length,g=c>0&&!o,u=b.useRef(null);return b.useEffect(()=>{u.current&&(u.current.indeterminate=g)},[g]),e.jsxs("div",{className:"rounded-md border border-border",children:[e.jsxs("div",{className:"flex items-center gap-2 px-2.5 py-2",children:[e.jsx("input",{ref:u,type:"checkbox",checked:o,onChange:()=>x(p,!o)}),e.jsxs("button",{type:"button",onClick:()=>{j("agents","toggle_agent_tool_group"),i(l=>!l)},className:"flex flex-1 items-center gap-1.5 text-left text-[13px] text-ink",children:[e.jsx(ne,{size:12,className:q("shrink-0 text-faint transition-transform",a&&"rotate-90")}),s.label,e.jsxs("span",{className:"text-[11px] text-faint",children:["(",c,"/",p.length,")"]})]})]}),a&&e.jsx("div",{className:"flex flex-col gap-1.5 border-t border-border px-3 py-2 pl-9",children:s.tools.map(l=>e.jsx(D,{tool:l,checked:d.has(l.name),onToggle:()=>n(l.name)},l.name))})]})}function ce({tools:s,selected:d,onChange:x}){const n=new Set(d),{builtin:a,groups:i}=oe(s),p=o=>x(n.has(o)?d.filter(g=>g!==o):[...d,o]),c=(o,g)=>{const u=d.filter(l=>!o.includes(l));x(g?[...u,...o]:u)};return s.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No tools available yet."}):e.jsxs("div",{className:"flex flex-col gap-2",children:[a.length>0&&e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:a.map(o=>e.jsx(D,{tool:o,checked:n.has(o.name),onToggle:()=>p(o.name)},o.name))}),i.map(o=>e.jsx(ie,{group:o,selected:n,onToggleAll:c,onToggleOne:p},o.key))]})}function ve(){const{agentId:s="new"}=W(),d=$(),x=G(),n=s==="new",a=!n&&B.some(t=>t.id===s),i=a?B.find(t=>t.id===s):void 0,p=H(),c=!n&&!a?(p.data??[]).find(t=>t.id===s):void 0,o=Y(),g=J(),u=U(),l=a?g.data?.[s]:void 0,I=z({queryKey:Z.list(),queryFn:X,staleTime:0}),k=I.data??[],w=z({queryKey:["available-tools"],queryFn:V}),N=w.data??[],[m,f]=b.useState(ae()),[S,T]=b.useState(!1),[A,P]=b.useState(!1),[L,R]=b.useState(!1),[E,Q]=b.useState("skills");n&&!S&&(k.length||N.length)&&(f(t=>({...t,skillIds:k.map(r=>r.id),tools:N.map(r=>r.name)})),T(!0)),!n&&!a&&!S&&c&&(f({name:c.name,description:c.description,systemPrompt:c.systemPrompt,skillIds:c.skillIds,tools:c.tools}),T(!0)),a&&!S&&i&&g.isSuccess&&(k.length||N.length)&&(f({name:l?.name??i.name,description:l?.description??i.description,systemPrompt:l?.systemPrompt??i.systemPrompt,skillIds:l?.skillIds??k.map(t=>t.id),tools:l?.tools??N.map(t=>t.name)}),T(!0));const y=()=>{j("agents","back_to_agents"),d("/customize")},O=t=>f(r=>({...r,skillIds:r.skillIds.includes(t)?r.skillIds.filter(v=>v!==t):[...r.skillIds,t]})),F=()=>{if(!m.name.trim()){h.error("Name is required.");return}P(!0);const t={name:m.name.trim(),description:m.description.trim(),systemPrompt:m.systemPrompt,skillIds:m.skillIds,tools:m.tools};if(a){u.save.mutate({id:s,override:t},{onSuccess:()=>{h.success("Agent saved."),y()},onError:v=>{h.error(v instanceof _?v.message:"Could not save agent."),P(!1)}});return}const r={onSuccess:()=>{x.invalidateQueries({queryKey:["chat-agents"]}),h.success(n?"Agent created.":"Agent saved."),y()},onError:v=>{h.error(v instanceof _?v.message:"Could not save agent."),P(!1)}};n?o.add.mutate(t,r):o.update.mutate({id:s,patch:t},r)},K=()=>{u.reset.mutate(s,{onSuccess:()=>{h.success("Reset to default."),i&&f({name:i.name,description:i.description,systemPrompt:i.systemPrompt,skillIds:k.map(t=>t.id),tools:N.map(t=>t.name)})},onError:t=>h.error(t instanceof _?t.message:"Could not reset agent.")})},M=()=>{o.remove.mutate(s,{onSuccess:()=>{h.success("Agent deleted."),y()},onError:t=>h.error(t instanceof _?t.message:"Could not delete agent.")})};return!n&&!a&&p.isSuccess&&!c?e.jsxs("div",{className:"flex w-full flex-col items-center gap-3 px-8 py-16",children:[e.jsx("p",{className:"text-[14px] text-muted",children:"That agent no longer exists."}),e.jsx(C,{size:"sm",variant:"outline",onClick:y,children:"Back to agents"})]}):e.jsxs("div",{className:"flex w-full max-w-4xl flex-col gap-5 px-4 py-6 md:px-8",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:y,className:"text-faint hover:text-ink",title:"Back to agents",children:e.jsx(ee,{size:18})}),e.jsx("span",{className:"text-[15px] font-medium text-ink",children:n?"New agent":a?l?"Edit agent (modified built-in)":"Edit agent (built-in)":"Edit agent"}),e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[a&&e.jsxs(C,{size:"sm",variant:"outline",onClick:()=>{j("agents","reset_agent_to_default"),K()},disabled:u.reset.isPending,children:[e.jsx(te,{size:13})," Reset to default"]}),e.jsx(C,{size:"sm",variant:"outline",onClick:y,children:"Cancel"}),e.jsx(C,{size:"sm",onClick:()=>{j("agents","save_agent"),F()},disabled:A||!m.name.trim(),children:A?"Saving…":"Save"})]})]}),a&&e.jsx("p",{className:"rounded-md border border-border bg-panel px-3 py-2 text-[12px] text-muted",children:"Built-in agents can be edited in place — Reset to default discards your changes and restores TurboLLM's original prompt and access."}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Name"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"Release Notes Writer",value:m.name,onChange:t=>f(r=>({...r,name:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"Description"}),e.jsx("input",{className:"rounded-md border border-border bg-bg px-3 py-1.5 text-[13px] text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"What this agent is for, in one line",value:m.description,onChange:t=>f(r=>({...r,description:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx("label",{className:"text-[12px] font-medium text-muted",children:"System prompt"}),e.jsx("textarea",{className:"min-h-[160px] resize-y rounded-md border border-border bg-bg px-3 py-2 font-mono text-[12px] leading-relaxed text-ink outline-none focus:border-accent placeholder:text-faint",placeholder:"You are…",value:m.systemPrompt,onChange:t=>f(r=>({...r,systemPrompt:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-2.5",children:[e.jsx("div",{className:"inline-flex w-fit rounded-md border border-border p-0.5",children:["skills","tools"].map(t=>e.jsx("button",{type:"button",onClick:()=>{j("agents","switch_agent_form_tab"),Q(t)},className:q("rounded px-3 py-1.5 text-[13px] font-medium transition-colors",E===t?"bg-accent/12 text-accent":"text-muted hover:text-ink"),children:t==="skills"?`Skills (${m.skillIds.length})`:`Tools (${m.tools.length})`},t))}),E==="skills"?I.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):k.length===0?e.jsx("p",{className:"text-[12px] text-faint",children:"No skills yet — create one under Customize → Skills."}):e.jsx("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-panel-2 p-3",children:k.map(t=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-[13px]",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:m.skillIds.includes(t.id),onChange:()=>O(t.id)}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"text-ink",children:t.name}),t.description&&e.jsx("span",{className:"text-[12px] text-muted",children:t.description})]})]},t.id))}):w.isLoading?e.jsx("p",{className:"text-[12px] text-faint",children:"Loading…"}):e.jsx(ce,{tools:N,selected:m.tools,onChange:t=>f(r=>({...r,tools:t}))})]}),!n&&!a&&(L?e.jsxs("div",{className:"flex items-center gap-2 self-start rounded-md border border-border bg-panel p-2 text-[12px]",children:[e.jsx("span",{className:"flex-1 text-muted",children:"Delete this agent?"}),e.jsx("button",{type:"button",onClick:()=>{j("agents","delete_agent"),M()},className:"rounded px-2 py-1 text-[color:var(--err)] hover:bg-[color:color-mix(in_srgb,var(--err)_12%,transparent)]",children:"Delete"}),e.jsx("button",{type:"button",onClick:()=>{j("agents","cancel_delete_agent"),R(!1)},className:"rounded px-2 py-1 text-faint hover:text-ink",children:"Cancel"})]}):e.jsxs("button",{type:"button",onClick:()=>R(!0),className:"flex items-center gap-1.5 self-start text-[12px] text-faint hover:text-[color:var(--err)]",children:[e.jsx(se,{size:13})," Delete agent"]}))]})}export{ve as AgentEditPage};
|