nolo-cli 0.107.0-alpha.3 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/{_executeModel-UDCSOTD2.js → _executeModel-C4EH5TZG.js} +77 -69
- package/action-GVA5ARSJ.js +20 -0
- package/{addContentAction-MB2HHMDZ.js → addContentAction-M2WOWZCL.js} +13 -12
- package/{addDialogAgentAction-MCEABSBA.js → addDialogAgentAction-QMAQ5Z6N.js} +19 -20
- package/{agentDeleteCommand-OWYHN6D6.js → agentDeleteCommand-D3RICSHX.js} +118 -43
- package/{agentEmailCommands-BQFXQIHF.js → agentEmailCommands-YC2A4USQ.js} +99 -89
- package/agentListCommands-UDJELMYP.js +741 -0
- package/{agentMachineCommands-6DTI7YSG.js → agentMachineCommands-XH4IBGTO.js} +48 -44
- package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-CMVTBY5X.js} +97 -2
- package/{agentPullCommand-O5MPVJ5E.js → agentPullCommand-B4T2DJ5H.js} +1 -1
- package/agentRecordCommands-3EOC2QMN.js +138 -0
- package/agentRunCommand-BTHYOVVS.js +167 -0
- package/{agentRunControl-AVJR4JW4.js → agentRunControl-3HWA2LLQ.js} +2 -2
- package/{agentRuntimeLocal-KCMC2TBD.js → agentRuntimeLocal-N4YGKL7M.js} +44 -40
- package/{agentSlice-R7PR6KYM.js → agentSlice-NIN4T6CF.js} +15 -14
- package/{appDeleteCommands-JEPA3EWE.js → appDeleteCommands-7DAF33AM.js} +46 -42
- package/{appDeployCommands-UTB76XFM.js → appDeployCommands-ZPZSMFGZ.js} +46 -42
- package/{appDeployStatusCommands-LGHF2SBD.js → appDeployStatusCommands-FWBDSSS5.js} +46 -42
- package/{appGetCommands-PX2BFHOB.js → appGetCommands-SZZOHGEP.js} +46 -42
- package/{appListCommands-BSMPTWKC.js → appListCommands-FPMUBDPM.js} +46 -42
- package/{authCommand-YW42YZA4.js → authCommand-VL3G26NQ.js} +119 -25
- package/{authCommands-RGOGCPP6.js → authCommands-5RTUDYZW.js} +7 -5
- package/{builtinSkillRegistry-FUAVTRVZ.js → builtinSkillRegistry-ZK4K67Y5.js} +11 -9
- package/{chromeCommands-FZYAU75D.js → chromeCommands-AU5ZJXBG.js} +289 -37
- package/{chromeOpsCommands-62P2Q2YB.js → chromeOpsCommands-ZYTCMNHG.js} +156 -22
- package/{chunk-JDPFV2JV.js → chunk-2NNRWRM5.js} +20 -11
- package/{chunk-JEDZAO7L.js → chunk-2SYTUTLI.js} +257 -37
- package/{chunk-HVURBGF3.js → chunk-2U3NHADM.js} +6 -6
- package/{chunk-AVTT555J.js → chunk-2ZHBFX5R.js} +29 -9
- package/{chunk-QTGQ2LTL.js → chunk-3DQY5IFB.js} +6 -10
- package/chunk-4LCOCOR5.js +50 -0
- package/{chunk-JPGCXHNM.js → chunk-4LKMZ3RR.js} +1 -1
- package/{chunk-2GRGFCF6.js → chunk-4VJAC32I.js} +2 -1
- package/{chunk-6D6VBVEW.js → chunk-4W24JM32.js} +80 -14
- package/{chunk-MC4XLIJ7.js → chunk-523DITKR.js} +1 -1
- package/{chunk-E4MARS3Q.js → chunk-5GVBDNTO.js} +1 -1
- package/chunk-5MMAK75Q.js +15 -0
- package/{chunk-7S4YWN7P.js → chunk-5UUIGN6I.js} +4 -4
- package/{chunk-42V6BK2E.js → chunk-62IL3KQV.js} +4 -34
- package/{chunk-C63CN6KA.js → chunk-6IJDSYUA.js} +849 -279
- package/{chunk-4MK3I7Y4.js → chunk-6MAW4XOF.js} +5 -5
- package/chunk-76HO2DP6.js +15 -0
- package/chunk-7AY2H3GA.js +13692 -0
- package/{chunk-4CR5I7BD.js → chunk-7HYOPBUW.js} +47 -67
- package/{chunk-VLTIYV3X.js → chunk-7I25CBT5.js} +34 -8
- package/chunk-AGIM7IMJ.js +147 -0
- package/{chunk-5UTFL4QJ.js → chunk-AOTBKDRK.js} +7 -0
- package/{chunk-6OZ36FXI.js → chunk-BIPGGSJS.js} +22 -4
- package/{chunk-EYAQT56M.js → chunk-BNQMNUKZ.js} +9 -6
- package/{chunk-62CATUYY.js → chunk-CBUMFIFE.js} +834 -962
- package/{chunk-OIVSQH2O.js → chunk-CDEEFJXN.js} +308 -11
- package/chunk-CHOZJMJS.js +78 -0
- package/{chunk-ETI2NYVF.js → chunk-CIP3AAMT.js} +4 -4
- package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
- package/{chunk-IBOZNTG2.js → chunk-DGEUP3DK.js} +23 -28
- package/{chunk-Q554LLSI.js → chunk-DMXLXZKL.js} +1 -1
- package/{chunk-3VNWWVKB.js → chunk-E3YWHWCR.js} +50 -18
- package/{chunk-HKNXJGEC.js → chunk-ECFHBYUW.js} +85 -50
- package/{chunk-ACTMNVHM.js → chunk-EHSYSKXV.js} +1 -1
- package/{chunk-WV42OMV7.js → chunk-ELUDRSRD.js} +8 -8
- package/{chunk-ABQYVJBJ.js → chunk-EV235ILT.js} +5 -5
- package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
- package/{chunk-BFDFRLLQ.js → chunk-EZ4VZHAG.js} +5 -5
- package/{chunk-GO3Z72MT.js → chunk-FHLMQIU7.js} +65 -95
- package/{chunk-2F7RJC6L.js → chunk-FOXQ7BAB.js} +1 -1
- package/{chunk-SH43IESU.js → chunk-GGC55Q32.js} +199 -29
- package/chunk-GMZLP5DV.js +82 -0
- package/{chunk-FDTR4QJ6.js → chunk-H6A6X4EK.js} +32 -1
- package/{chunk-DVINR3PL.js → chunk-HDLLCBRF.js} +1 -1
- package/{chunk-QOKAKDPE.js → chunk-HIM3FCLF.js} +0 -1
- package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
- package/{chunk-BNGW5ASC.js → chunk-I2RGRVQ7.js} +22 -2
- package/{chunk-O6OSWFZQ.js → chunk-IHPDK6UD.js} +6 -0
- package/{chunk-QDSINZM3.js → chunk-IXH3HKY2.js} +1 -22
- package/{chunk-GQBOR3G6.js → chunk-JBKHQOYK.js} +8 -4
- package/{chunk-XD2MJFUG.js → chunk-JEFXP73H.js} +1 -1
- package/{chunk-PBA4UJBK.js → chunk-JIXGJTBU.js} +4 -4
- package/{chunk-AEOE4Z6Q.js → chunk-K6L5PNXK.js} +39 -15
- package/{chunk-Z77CRGTW.js → chunk-KA5O5KQL.js} +1 -1
- package/{chunk-GPCZ7UXG.js → chunk-KD6D6BLA.js} +1 -1
- package/{chunk-UZGQNTVW.js → chunk-KHKTDMYG.js} +8 -6
- package/{chunk-MRIHM22T.js → chunk-LBFL6RZG.js} +58 -9
- package/{chunk-C3M4465B.js → chunk-LKIVH2I2.js} +403 -658
- package/{chunk-LS2ZANRJ.js → chunk-LOCNXNOU.js} +1 -1
- package/{chunk-DHDMC6FO.js → chunk-LUBFABMJ.js} +15 -14
- package/{chunk-NA35QHCF.js → chunk-LVBFKW65.js} +1 -1
- package/chunk-LWLNLZC5.js +265 -0
- package/{chunk-EEGDMATE.js → chunk-M3NMHYRB.js} +86 -81
- package/chunk-N4NGJDT6.js +929 -0
- package/{chunk-GL3EHUR4.js → chunk-N7NLLRQQ.js} +68 -46
- package/{chunk-BFU6C242.js → chunk-NMFV26UG.js} +1 -1
- package/{chunk-FZGV4FGK.js → chunk-NUHHBEJC.js} +378 -187
- package/chunk-NWENLDMM.js +42 -0
- package/chunk-O7SVKKLY.js +875 -0
- package/chunk-OCZKATRC.js +129 -0
- package/{chunk-6Z7MY3V7.js → chunk-OEJLGVBL.js} +5 -5
- package/{chunk-VMFTFOWF.js → chunk-OKGVNZTL.js} +35 -8
- package/{chunk-GEPUP7OO.js → chunk-OR2UWD6X.js} +3 -3
- package/{chunk-KQHGZWSV.js → chunk-OXME3PEE.js} +1 -1
- package/{chunk-J4MOO56S.js → chunk-PNXHPLRU.js} +10 -2
- package/{chunk-3BMYXEUW.js → chunk-R5AJODNI.js} +1 -1
- package/{chunk-P5EVSOPA.js → chunk-R6EBQEQE.js} +22 -29
- package/{chunk-NOF3HDSN.js → chunk-RLSF5CSE.js} +11 -9
- package/chunk-RQ6CTX2E.js +164 -0
- package/{chunk-3UZPUAES.js → chunk-RSB4PWX4.js} +1 -1
- package/{chunk-KQ4ONNQD.js → chunk-RXA3HAVW.js} +190 -8
- package/{chunk-IIVGDG4I.js → chunk-SJKULPGX.js} +13 -7
- package/chunk-SQHMSDDU.js +8004 -0
- package/{chunk-Q67DOFOO.js → chunk-SZC4REES.js} +212 -105
- package/{chunk-JRQFUXY7.js → chunk-TBAXFWOS.js} +99 -22
- package/{chunk-PQFHGD77.js → chunk-TBM2RS3U.js} +161 -14
- package/{chunk-XT35TTFG.js → chunk-TCYU7L6V.js} +18 -20
- package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
- package/chunk-TY3TIUJK.js +89 -0
- package/{chunk-I3TQJXQ7.js → chunk-U3C3IA32.js} +9 -2
- package/{chunk-YYLHWIW6.js → chunk-UKZX3NHN.js} +1 -1
- package/chunk-UM7TA3K4.js +1008 -0
- package/{chunk-6YTOJY35.js → chunk-VBG7GWWR.js} +253 -8
- package/chunk-VIWDGTDA.js +8 -0
- package/chunk-VJVNU77E.js +83 -0
- package/{chunk-W7HLWAQ7.js → chunk-VPLUU4IX.js} +118 -90
- package/{chunk-UKWGR5SS.js → chunk-VY6VFGKR.js} +194 -1144
- package/chunk-VZLO4XJD.js +17 -0
- package/{chunk-AHAHBQMU.js → chunk-WDLSZMTA.js} +2 -2
- package/{chunk-53HEEOTT.js → chunk-WF5X57VW.js} +83 -16
- package/{chunk-VRTTFDBM.js → chunk-WPHY3VPF.js} +35 -22
- package/{chunk-ASIFZ2WY.js → chunk-YKZLFY5J.js} +66 -54
- package/chunk-YV25TM3R.js +780 -0
- package/{chunk-B2C6QTY4.js → chunk-YXKNBVYW.js} +19 -17
- package/chunk-ZRAU6T47.js +56 -0
- package/commandRegistry-UU6IOTHI.js +833 -0
- package/{contentThunks-IV2T3EJC.js → contentThunks-ARD56LKI.js} +39 -36
- package/{cooldownCommands-REAWYVTY.js → cooldownCommands-ZLEPIB4A.js} +2 -2
- package/{createAgentAutomationAction-JCOIEYY4.js → createAgentAutomationAction-HWJLU6DD.js} +40 -37
- package/createDialogAction-CHYA6PZE.js +70 -0
- package/{createPageAction-D2VOOLP3.js → createPageAction-TSCYNFX7.js} +47 -43
- package/{chunk-VFEJQMH4.js → cursorProvider-YGGNMVWX.js} +2751 -10172
- package/{dbSlice-A6C6H32X.js → dbSlice-TG4MZ5EB.js} +12 -11
- package/{deleteFile-YG6QMJLU.js → deleteFile-KESP65GC.js} +7 -6
- package/{dialogCommands-H7FPUYUQ.js → dialogCommands-IJYQAQMB.js} +49 -46
- package/{dialogSlice-6JZOOTDS.js → dialogSlice-H476I77R.js} +57 -37
- package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
- package/{docCreateCommands-WRG2JLGM.js → docCreateCommands-AZSK4NAG.js} +48 -44
- package/{docDeleteCommands-SHWJIBJS.js → docDeleteCommands-DDJMSMFZ.js} +49 -45
- package/{docReadCommands-WJN3WT6O.js → docReadCommands-5F5Q6EBZ.js} +47 -43
- package/{docStore-HUPQ2FSS.js → docStore-HW2RDZDM.js} +17 -13
- package/{docUpdateCommands-IE32IL6O.js → docUpdateCommands-XPNPVZOC.js} +48 -44
- package/{fetchMessages-EIU7UFFK.js → fetchMessages-3PXAHKCR.js} +5 -5
- package/{getPricing-LUSEABA6.js → getPricing-DOBBZLOK.js} +4 -4
- package/{handleSendMessageAction-DFPMQ7YM.js → handleSendMessageAction-IOXE7ILC.js} +109 -42
- package/index.js +87 -884
- package/{lib-FRRS27KN.js → lib-PU2G2MSO.js} +523 -191
- package/{localDialogRead-BTFJ4V2I.js → localDialogRead-UYCKO7YZ.js} +2 -2
- package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-TU6OBC76.js} +9 -6
- package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-VKWVOPPI.js} +1 -1
- package/{machineCommands-OL4NLMXG.js → machineCommands-Q7TDGM6P.js} +96 -86
- package/machineWsRunDispatch-T5VFOQ3R.js +154 -0
- package/{memberThunks-P2ECUJ56.js → memberThunks-5S5D3N4U.js} +20 -18
- package/{models-T3SG6MJ5.js → models-PQU25T6Q.js} +2 -2
- package/oauthTokenStore-ITEB663N.js +23 -0
- package/package.json +1 -1
- package/processSpawn-SOAV3FEV.js +11 -0
- package/profileConfig-ZGOFORWV.js +43 -0
- package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-HAQWVAQX.js} +7 -7
- package/{providerRegistry-757OWH3O.js → providerRegistry-5FGWB3X5.js} +11 -7
- package/{read-COE3ZYR6.js → read-LSYFLSIM.js} +8 -7
- package/{readDocTool-5USN4A6V.js → readDocTool-XWRXV3DR.js} +5 -3
- package/{readlineWorkspace-BOENUIW2.js → readlineWorkspace-25U6P3DG.js} +2595 -2031
- package/{removeDialogAgentAction-J6X5QMTA.js → removeDialogAgentAction-4TEFC3VL.js} +22 -26
- package/{runAgentClientLoop-5ZA62FBA.js → runAgentClientLoop-CZOYWHDN.js} +78 -71
- package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-PIVSBZRZ.js} +4 -4
- package/runtimeModeArgs-2Y7BALTO.js +31 -0
- package/{setDialogExtraReferencesAction-WX5VTY6O.js → setDialogExtraReferencesAction-LSEN44OY.js} +16 -14
- package/{setPrimaryDialogAgentAction-FN22THHT.js → setPrimaryDialogAgentAction-SR366X5A.js} +23 -27
- package/{chunk-GP5LKBUZ.js → settingThunks-CTVPPGIN.js} +226 -940
- package/{skillDiscovery-CYUCJMAG.js → skillDiscovery-ZBU76COE.js} +3 -3
- package/{slateUtils-RIZES3PV.js → slateUtils-NGV2NMKM.js} +1 -1
- package/{spaceCommands-5GLCWZPO.js → spaceCommands-3UK63WPE.js} +51 -47
- package/{streamAgentChatTurn-6UZJMYRB.js → streamAgentChatTurn-LV6ZWUD4.js} +214 -114
- package/{switchDialogAgentAction-LVTEV3FR.js → switchDialogAgentAction-M6NAFOOU.js} +19 -20
- package/{tableCommands-O6NWHFKV.js → tableCommands-6U4BMLRR.js} +10 -10
- package/{toolApiClient-QVJ6HDNN.js → toolApiClient-AD7CXTA4.js} +4 -3
- package/tools-UJOV6CQZ.js +117 -0
- package/{tuiSummaryLlmCaller-OHHFTHMG.js → tuiSummaryLlmCaller-DEH7ZEM6.js} +25 -23
- package/{updateCommands-2M74UL7P.js → updateCommands-4EHDLF5J.js} +3 -3
- package/{updateDialogTitleAction-QTKNIURB.js → updateDialogTitleAction-JYXKIBNJ.js} +84 -45
- package/action-P4TNFGAD.js +0 -31
- package/agentListCommands-B2V4YAC4.js +0 -410
- package/agentRecordCommands-UTHKMMJY.js +0 -128
- package/agentRunCommand-D4OBAOVW.js +0 -156
- package/browser-image-compression-MFDTD7K6.js +0 -1763
- package/chatQueueReduxAdapter-2P6NFX64.js +0 -186
- package/chunk-CQ3WA2NE.js +0 -299
- package/chunk-M76ECQRD.js +0 -13658
- package/chunk-MEYIRKDN.js +0 -8967
- package/chunk-PUOC4YRO.js +0 -394
- package/chunk-Q5FJJ6XI.js +0 -103
- package/chunk-S7Z2HMCN.js +0 -25
- package/chunk-T75QD6AB.js +0 -20923
- package/chunk-Y5GCAMGP.js +0 -9
- package/chunk-YPREESF4.js +0 -225
- package/createDialogAction-NGG7YVNU.js +0 -65
- package/machineWsRunDispatch-64SG2RUI.js +0 -144
- package/settingSlice-P4ZW7K5X.js +0 -204
- package/syncMapping-N6RGXGBW.js +0 -437
- package/tools-KMGFWO43.js +0 -110
- package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
- package/{db-WK5MDZVN.js → db-VQSAOWAO.js} +1 -1
|
@@ -0,0 +1,1008 @@
|
|
|
1
|
+
import {
|
|
2
|
+
asTrimmedLowercaseString
|
|
3
|
+
} from "./chunk-QSJ3HFEF.js";
|
|
4
|
+
import {
|
|
5
|
+
isRecord
|
|
6
|
+
} from "./chunk-KUG52IAP.js";
|
|
7
|
+
import {
|
|
8
|
+
asOptionalTrimmedString
|
|
9
|
+
} from "./chunk-G3SUCT4W.js";
|
|
10
|
+
|
|
11
|
+
// packages/agent-runtime/declaredToolNames.ts
|
|
12
|
+
function extractDeclaredToolNames(tools) {
|
|
13
|
+
if (!Array.isArray(tools)) return void 0;
|
|
14
|
+
const names = /* @__PURE__ */ new Set();
|
|
15
|
+
for (const t of tools) {
|
|
16
|
+
const fn = t?.function;
|
|
17
|
+
if (fn && typeof fn.name === "string" && fn.name) names.add(fn.name);
|
|
18
|
+
}
|
|
19
|
+
return names;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// packages/agent-runtime/toolArgsShape.ts
|
|
23
|
+
function scanRawToolArgs(input) {
|
|
24
|
+
const stack = [];
|
|
25
|
+
const commaAtDepth = [];
|
|
26
|
+
let inString = false;
|
|
27
|
+
let escaped = false;
|
|
28
|
+
const closersOf2 = () => stack.slice().reverse().map((ch) => ch === "{" ? "}" : "]").join("");
|
|
29
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
30
|
+
const ch = input[i];
|
|
31
|
+
if (inString) {
|
|
32
|
+
if (escaped) escaped = false;
|
|
33
|
+
else if (ch === "\\") escaped = true;
|
|
34
|
+
else if (ch === '"') inString = false;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (ch === '"') {
|
|
38
|
+
inString = true;
|
|
39
|
+
} else if (ch === "{" || ch === "[") {
|
|
40
|
+
stack.push(ch);
|
|
41
|
+
commaAtDepth[stack.length] = void 0;
|
|
42
|
+
} else if (ch === "}" || ch === "]") {
|
|
43
|
+
const open = stack.pop();
|
|
44
|
+
if (open !== (ch === "}" ? "{" : "[")) {
|
|
45
|
+
return {
|
|
46
|
+
inString,
|
|
47
|
+
mismatched: true,
|
|
48
|
+
unclosed: false,
|
|
49
|
+
// 结构已坏:与迁移前一致,不再给出尾部数组逗号坐标。
|
|
50
|
+
tailArrayComma: null
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
commaAtDepth[stack.length + 1] = void 0;
|
|
54
|
+
} else if (ch === "," && stack[stack.length - 1] === "[") {
|
|
55
|
+
commaAtDepth[stack.length] = { index: i, closers: closersOf2() };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let tailArrayComma = null;
|
|
59
|
+
for (let d = stack.length; d >= 1; d -= 1) {
|
|
60
|
+
const c = commaAtDepth[d];
|
|
61
|
+
if (c && stack[d - 1] === "[") {
|
|
62
|
+
tailArrayComma = c;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
inString,
|
|
68
|
+
mismatched: false,
|
|
69
|
+
unclosed: stack.length > 0,
|
|
70
|
+
tailArrayComma
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function classifyUnparsableToolArgs(raw) {
|
|
74
|
+
if (typeof raw !== "string") return "malformed";
|
|
75
|
+
const scan = scanRawToolArgs(raw);
|
|
76
|
+
if (scan.inString) return "truncated";
|
|
77
|
+
return scan.mismatched || scan.unclosed ? "truncated" : "malformed";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// packages/agent-runtime/outboundHistorySanitize.ts
|
|
81
|
+
var DOWNGRADED_TOOL_TURN_ORIGIN = Symbol(
|
|
82
|
+
"nolo.downgradedToolTurnOrigin"
|
|
83
|
+
);
|
|
84
|
+
function markDowngradedToolTurnOrigin(message) {
|
|
85
|
+
Object.defineProperty(message, DOWNGRADED_TOOL_TURN_ORIGIN, {
|
|
86
|
+
value: true,
|
|
87
|
+
enumerable: false,
|
|
88
|
+
writable: false,
|
|
89
|
+
configurable: true
|
|
90
|
+
});
|
|
91
|
+
return message;
|
|
92
|
+
}
|
|
93
|
+
function transferDowngradedToolTurnOrigin(source, rebuilt) {
|
|
94
|
+
if (hasDowngradedToolTurnOrigin(source)) markDowngradedToolTurnOrigin(rebuilt);
|
|
95
|
+
return rebuilt;
|
|
96
|
+
}
|
|
97
|
+
function hasDowngradedToolTurnOrigin(message) {
|
|
98
|
+
return typeof message === "object" && message !== null && message[DOWNGRADED_TOOL_TURN_ORIGIN] === true;
|
|
99
|
+
}
|
|
100
|
+
function emptyToolArgsProjectionStats() {
|
|
101
|
+
return {
|
|
102
|
+
badArguments: { truncated: 0, malformed: 0 },
|
|
103
|
+
rewrittenToolCalls: 0,
|
|
104
|
+
rewrittenAssistantMessages: 0,
|
|
105
|
+
rewrittenToolMessages: 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function sanitizeForOutbound(messages, tools) {
|
|
109
|
+
return sanitizeOutboundHistory(messages, {
|
|
110
|
+
declaredToolNames: extractDeclaredToolNames(tools)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function stableToolCallId(assistantIndex, callIndex) {
|
|
114
|
+
return `call_sanitize_${assistantIndex}_${callIndex}`;
|
|
115
|
+
}
|
|
116
|
+
function isString(v) {
|
|
117
|
+
return typeof v === "string";
|
|
118
|
+
}
|
|
119
|
+
function isNonEmptyString(v) {
|
|
120
|
+
return typeof v === "string" && v.length > 0;
|
|
121
|
+
}
|
|
122
|
+
function joinLines(...parts) {
|
|
123
|
+
return parts.filter(isNonEmptyString).join("\n");
|
|
124
|
+
}
|
|
125
|
+
function jsonStringifyArguments(args) {
|
|
126
|
+
if (typeof args === "string") return args;
|
|
127
|
+
try {
|
|
128
|
+
return JSON.stringify(args ?? "");
|
|
129
|
+
} catch {
|
|
130
|
+
return "";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function renderToolCallAsText(call) {
|
|
134
|
+
const c = call && typeof call === "object" ? call : {};
|
|
135
|
+
const name = isString(c.function?.name) && c.function.name.length > 0 ? c.function.name : "unknown";
|
|
136
|
+
const rawArgs = c.function?.arguments;
|
|
137
|
+
const args = jsonStringifyArguments(rawArgs);
|
|
138
|
+
return `[tool_call: ${name}(${args})]`;
|
|
139
|
+
}
|
|
140
|
+
function renderToolResultAsText(message) {
|
|
141
|
+
const name = isNonEmptyString(message.toolName) ? message.toolName : "tool";
|
|
142
|
+
const body = typeof message.content === "string" ? message.content : "";
|
|
143
|
+
return `[tool_result: ${name}: ${body}]`;
|
|
144
|
+
}
|
|
145
|
+
function normalizeToolCall(call, assistantIndex, callIndex) {
|
|
146
|
+
if (!call || typeof call !== "object") return null;
|
|
147
|
+
const c = call;
|
|
148
|
+
const fn = c.function;
|
|
149
|
+
if (!fn || typeof fn !== "object" || !isString(fn.name) || fn.name.length === 0) return null;
|
|
150
|
+
const id = isNonEmptyString(c.id) ? c.id : stableToolCallId(assistantIndex, callIndex);
|
|
151
|
+
return {
|
|
152
|
+
id,
|
|
153
|
+
type: isString(c.type) && c.type ? c.type : "function",
|
|
154
|
+
function: { name: fn.name, arguments: jsonStringifyArguments(fn.arguments) },
|
|
155
|
+
...typeof c.extra_content?.google?.thought_signature === "string" ? { extra_content: { google: { thought_signature: c.extra_content.google.thought_signature } } } : {},
|
|
156
|
+
...typeof c.thought_signature === "string" ? { thought_signature: c.thought_signature } : {}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function classifyAssistantCalls(toolCalls, assistantIndex) {
|
|
160
|
+
const callIds = [];
|
|
161
|
+
const idCounts = /* @__PURE__ */ new Map();
|
|
162
|
+
const unparsableIndices = /* @__PURE__ */ new Set();
|
|
163
|
+
const unparsableIds = /* @__PURE__ */ new Set();
|
|
164
|
+
toolCalls.forEach((rawCall, callIndex) => {
|
|
165
|
+
const c = rawCall && typeof rawCall === "object" ? rawCall : {};
|
|
166
|
+
const id = isNonEmptyString(c.id) ? c.id : stableToolCallId(assistantIndex, callIndex);
|
|
167
|
+
callIds.push(id);
|
|
168
|
+
idCounts.set(id, (idCounts.get(id) ?? 0) + 1);
|
|
169
|
+
if (!hasParsableObjectArguments(c.function?.arguments)) {
|
|
170
|
+
unparsableIndices.add(callIndex);
|
|
171
|
+
unparsableIds.add(id);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const duplicateIds = /* @__PURE__ */ new Set();
|
|
175
|
+
for (const [id, count] of idCounts) {
|
|
176
|
+
if (count > 1) duplicateIds.add(id);
|
|
177
|
+
}
|
|
178
|
+
return { callIds, duplicateIds, unparsableIndices, unparsableIds };
|
|
179
|
+
}
|
|
180
|
+
function sanitizeOutboundHistory(messages, options) {
|
|
181
|
+
if (!Array.isArray(messages) || messages.length === 0) return messages;
|
|
182
|
+
const declared = options?.declaredToolNames;
|
|
183
|
+
const keptCallIndicesPerAssistant = /* @__PURE__ */ new Map();
|
|
184
|
+
const keptToolIndices = /* @__PURE__ */ new Set();
|
|
185
|
+
let i = 0;
|
|
186
|
+
while (i < messages.length) {
|
|
187
|
+
const m = messages[i];
|
|
188
|
+
if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
189
|
+
const asstIdx = i;
|
|
190
|
+
const { callIds, duplicateIds, unparsableIndices } = classifyAssistantCalls(m.tool_calls, asstIdx);
|
|
191
|
+
const candidateCallMap = /* @__PURE__ */ new Map();
|
|
192
|
+
m.tool_calls.forEach((call, callIndex) => {
|
|
193
|
+
const id = callIds[callIndex];
|
|
194
|
+
if (duplicateIds.has(id)) return;
|
|
195
|
+
if (unparsableIndices.has(callIndex)) return;
|
|
196
|
+
const name = call?.function?.name;
|
|
197
|
+
if (!isString(name) || name.length === 0) return;
|
|
198
|
+
const declaredAllows = !declared || declared.has(name);
|
|
199
|
+
if (!declaredAllows) return;
|
|
200
|
+
candidateCallMap.set(id, callIndex);
|
|
201
|
+
});
|
|
202
|
+
let j = i + 1;
|
|
203
|
+
const matchedCallIndices = /* @__PURE__ */ new Set();
|
|
204
|
+
const matchedToolIds = /* @__PURE__ */ new Set();
|
|
205
|
+
while (j < messages.length && messages[j].role === "tool") {
|
|
206
|
+
const toolMsg = messages[j];
|
|
207
|
+
const toolCallId = isNonEmptyString(toolMsg.tool_call_id) ? toolMsg.tool_call_id : "";
|
|
208
|
+
if (toolCallId && candidateCallMap.has(toolCallId) && !matchedToolIds.has(toolCallId)) {
|
|
209
|
+
matchedToolIds.add(toolCallId);
|
|
210
|
+
matchedCallIndices.add(candidateCallMap.get(toolCallId));
|
|
211
|
+
keptToolIndices.add(j);
|
|
212
|
+
}
|
|
213
|
+
j++;
|
|
214
|
+
}
|
|
215
|
+
keptCallIndicesPerAssistant.set(asstIdx, matchedCallIndices);
|
|
216
|
+
i = j;
|
|
217
|
+
} else {
|
|
218
|
+
i++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const out = [];
|
|
222
|
+
let k = 0;
|
|
223
|
+
while (k < messages.length) {
|
|
224
|
+
const m = messages[k];
|
|
225
|
+
if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
226
|
+
const asstIdx = k;
|
|
227
|
+
const keptIndices = keptCallIndicesPerAssistant.get(asstIdx) ?? /* @__PURE__ */ new Set();
|
|
228
|
+
const keptToolCalls = [];
|
|
229
|
+
const downgradedCallLines = [];
|
|
230
|
+
m.tool_calls.forEach((call, callIndex) => {
|
|
231
|
+
const name = call?.function?.name;
|
|
232
|
+
const declaredAllows = !declared || isString(name) && declared.has(name);
|
|
233
|
+
const keep = keptIndices.has(callIndex) && declaredAllows && hasParsableObjectArguments(call?.function?.arguments);
|
|
234
|
+
if (keep) {
|
|
235
|
+
const normalized = normalizeToolCall(call, asstIdx, callIndex);
|
|
236
|
+
if (normalized) {
|
|
237
|
+
keptToolCalls.push(normalized);
|
|
238
|
+
} else {
|
|
239
|
+
downgradedCallLines.push(renderToolCallAsText(call));
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
downgradedCallLines.push(renderToolCallAsText(call));
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
if (keptToolCalls.length === 0) {
|
|
246
|
+
const downgradedText = joinLines(...downgradedCallLines);
|
|
247
|
+
const contentWithDowngrade = downgradedText.length > 0 ? combineContentWithText(m.content, downgradedText) : m.content;
|
|
248
|
+
const sanitizedAssistant2 = transferDowngradedToolTurnOrigin(m, {
|
|
249
|
+
...m,
|
|
250
|
+
content: contentWithDowngrade
|
|
251
|
+
});
|
|
252
|
+
delete sanitizedAssistant2.tool_calls;
|
|
253
|
+
markDowngradedToolTurnOrigin(sanitizedAssistant2);
|
|
254
|
+
out.push(sanitizedAssistant2);
|
|
255
|
+
let nextIdx2 = k + 1;
|
|
256
|
+
while (nextIdx2 < messages.length && messages[nextIdx2].role === "tool") {
|
|
257
|
+
const downgradedToolMsg = messages[nextIdx2];
|
|
258
|
+
out.push(
|
|
259
|
+
transferDowngradedToolTurnOrigin(downgradedToolMsg, {
|
|
260
|
+
role: "assistant",
|
|
261
|
+
content: renderToolResultAsText(downgradedToolMsg)
|
|
262
|
+
})
|
|
263
|
+
);
|
|
264
|
+
nextIdx2++;
|
|
265
|
+
}
|
|
266
|
+
k = nextIdx2;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const sanitizedAssistant = transferDowngradedToolTurnOrigin(m, {
|
|
270
|
+
...m,
|
|
271
|
+
tool_calls: keptToolCalls
|
|
272
|
+
});
|
|
273
|
+
out.push(sanitizedAssistant);
|
|
274
|
+
let nextIdx = k + 1;
|
|
275
|
+
const deferredResultLines = [];
|
|
276
|
+
while (nextIdx < messages.length && messages[nextIdx].role === "tool") {
|
|
277
|
+
if (keptToolIndices.has(nextIdx)) {
|
|
278
|
+
const toolMsg = messages[nextIdx];
|
|
279
|
+
out.push({
|
|
280
|
+
...toolMsg,
|
|
281
|
+
content: toolMsg.content ?? "",
|
|
282
|
+
tool_call_id: toolMsg.tool_call_id
|
|
283
|
+
});
|
|
284
|
+
} else {
|
|
285
|
+
deferredResultLines.push(renderToolResultAsText(messages[nextIdx]));
|
|
286
|
+
}
|
|
287
|
+
nextIdx++;
|
|
288
|
+
}
|
|
289
|
+
const deferredLines = [...downgradedCallLines, ...deferredResultLines];
|
|
290
|
+
if (deferredLines.length > 0) {
|
|
291
|
+
out.push({
|
|
292
|
+
role: "assistant",
|
|
293
|
+
content: joinLines(...deferredLines)
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
k = nextIdx;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (m.role === "tool") {
|
|
300
|
+
out.push(
|
|
301
|
+
transferDowngradedToolTurnOrigin(m, {
|
|
302
|
+
role: "assistant",
|
|
303
|
+
content: renderToolResultAsText(m)
|
|
304
|
+
})
|
|
305
|
+
);
|
|
306
|
+
k++;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
out.push(transferDowngradedToolTurnOrigin(m, { ...m }));
|
|
310
|
+
k++;
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
function combineContentWithText(base, extra) {
|
|
315
|
+
if (typeof base === "string") {
|
|
316
|
+
return base ? `${base}
|
|
317
|
+
${extra}` : extra;
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(base)) {
|
|
320
|
+
return [...base, { type: "text", text: extra }];
|
|
321
|
+
}
|
|
322
|
+
return extra;
|
|
323
|
+
}
|
|
324
|
+
function hasParsableObjectArguments(raw) {
|
|
325
|
+
if (raw === void 0) return true;
|
|
326
|
+
if (raw === null || typeof raw === "number" || typeof raw === "boolean") {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
if (typeof raw !== "string") return true;
|
|
330
|
+
if (raw.trim() === "") return true;
|
|
331
|
+
try {
|
|
332
|
+
const parsed = JSON.parse(raw);
|
|
333
|
+
return parsed !== null && typeof parsed === "object";
|
|
334
|
+
} catch {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
var STRICT_JSON_STRING_TOKEN = /^"(?:[^"\\\u0000-\u001F]|\\["\\/bfnrt]|\\u[0-9A-Fa-f]{4})*"$/;
|
|
339
|
+
function isStrictJsonStringToken(value) {
|
|
340
|
+
if (!STRICT_JSON_STRING_TOKEN.test(value)) return false;
|
|
341
|
+
try {
|
|
342
|
+
return typeof JSON.parse(value) === "string";
|
|
343
|
+
} catch {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function closersOf(openStack) {
|
|
348
|
+
return openStack.slice().reverse().map((ch) => ch === "{" ? "}" : "]").join("");
|
|
349
|
+
}
|
|
350
|
+
function scanJsonForTailRepair(input) {
|
|
351
|
+
const stack = [];
|
|
352
|
+
let inString = false;
|
|
353
|
+
let escaped = false;
|
|
354
|
+
let lastCommaOutsideString = null;
|
|
355
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
356
|
+
const ch = input[i];
|
|
357
|
+
if (inString) {
|
|
358
|
+
if (escaped) escaped = false;
|
|
359
|
+
else if (ch === "\\") escaped = true;
|
|
360
|
+
else if (ch === '"') inString = false;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (ch === '"') {
|
|
364
|
+
inString = true;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (ch === "{" || ch === "[") {
|
|
368
|
+
stack.push(ch);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
if (ch === "}" || ch === "]") {
|
|
372
|
+
const open = stack.pop();
|
|
373
|
+
if (open !== (ch === "}" ? "{" : "[")) return null;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (ch === ",") {
|
|
377
|
+
lastCommaOutsideString = { index: i, closers: closersOf(stack) };
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return { inString, closers: closersOf(stack), lastCommaOutsideString };
|
|
382
|
+
}
|
|
383
|
+
function repairTruncatedToolArguments(raw) {
|
|
384
|
+
if (typeof raw !== "string") return null;
|
|
385
|
+
const withoutTrailingSpace = raw.replace(/\s+$/, "");
|
|
386
|
+
const endsWithComma = withoutTrailingSpace.endsWith(",");
|
|
387
|
+
const trimmed = endsWithComma ? withoutTrailingSpace.slice(0, -1).replace(/\s+$/, "") : withoutTrailingSpace;
|
|
388
|
+
if (trimmed === "" || trimmed.endsWith(",")) return null;
|
|
389
|
+
const scan = scanJsonForTailRepair(trimmed);
|
|
390
|
+
if (!scan || scan.inString) return null;
|
|
391
|
+
const lastChar = trimmed[trimmed.length - 1];
|
|
392
|
+
const tailIsCompleteToken = endsWithComma || lastChar === '"' || lastChar === "}" || lastChar === "]";
|
|
393
|
+
if (!tailIsCompleteToken) return null;
|
|
394
|
+
const candidates = [trimmed + scan.closers];
|
|
395
|
+
const lastComma = scan.lastCommaOutsideString;
|
|
396
|
+
if (lastComma && lastComma.index > 0) {
|
|
397
|
+
const tailAfterComma = trimmed.slice(lastComma.index + 1).trim();
|
|
398
|
+
if (isStrictJsonStringToken(tailAfterComma)) {
|
|
399
|
+
const head = trimmed.slice(0, lastComma.index);
|
|
400
|
+
candidates.push(head + lastComma.closers);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
for (const candidate of candidates) {
|
|
404
|
+
try {
|
|
405
|
+
const parsed = JSON.parse(candidate);
|
|
406
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && Object.keys(parsed).length > 0) {
|
|
407
|
+
return candidate;
|
|
408
|
+
}
|
|
409
|
+
} catch {
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
function downgradeUnparsableToolCalls(messages) {
|
|
415
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
416
|
+
return { messages, downgraded: 0, stats: emptyToolArgsProjectionStats() };
|
|
417
|
+
}
|
|
418
|
+
let hasAnyPoison = false;
|
|
419
|
+
for (const m of messages) {
|
|
420
|
+
if (m.role === "assistant" && Array.isArray(m.tool_calls)) {
|
|
421
|
+
for (const call of m.tool_calls) {
|
|
422
|
+
if (!hasParsableObjectArguments(call?.function?.arguments)) {
|
|
423
|
+
hasAnyPoison = true;
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (hasAnyPoison) break;
|
|
429
|
+
}
|
|
430
|
+
if (!hasAnyPoison) return { messages, downgraded: 0, stats: emptyToolArgsProjectionStats() };
|
|
431
|
+
const poisonedCallsPerAssistant = /* @__PURE__ */ new Map();
|
|
432
|
+
const poisonedToolIndices = /* @__PURE__ */ new Set();
|
|
433
|
+
const badArguments = {
|
|
434
|
+
truncated: 0,
|
|
435
|
+
malformed: 0
|
|
436
|
+
};
|
|
437
|
+
let i = 0;
|
|
438
|
+
while (i < messages.length) {
|
|
439
|
+
const m = messages[i];
|
|
440
|
+
if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
441
|
+
const asstIdx = i;
|
|
442
|
+
const { unparsableIds, unparsableIndices } = classifyAssistantCalls(m.tool_calls, asstIdx);
|
|
443
|
+
for (const badIndex of unparsableIndices) {
|
|
444
|
+
const badCall = m.tool_calls[badIndex];
|
|
445
|
+
badArguments[classifyUnparsableToolArgs(badCall?.function?.arguments)] += 1;
|
|
446
|
+
}
|
|
447
|
+
let j = i + 1;
|
|
448
|
+
while (j < messages.length && messages[j].role === "tool") {
|
|
449
|
+
const toolMsg = messages[j];
|
|
450
|
+
const toolCallId = isNonEmptyString(toolMsg.tool_call_id) ? toolMsg.tool_call_id : "";
|
|
451
|
+
if (toolCallId && unparsableIds.has(toolCallId)) {
|
|
452
|
+
poisonedToolIndices.add(j);
|
|
453
|
+
}
|
|
454
|
+
j++;
|
|
455
|
+
}
|
|
456
|
+
if (unparsableIds.size > 0) {
|
|
457
|
+
poisonedCallsPerAssistant.set(asstIdx, unparsableIds);
|
|
458
|
+
}
|
|
459
|
+
i = j;
|
|
460
|
+
} else {
|
|
461
|
+
i++;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
let downgraded = 0;
|
|
465
|
+
let rewrittenAssistantMessages = 0;
|
|
466
|
+
let rewrittenToolMessages = 0;
|
|
467
|
+
const out = [];
|
|
468
|
+
let k = 0;
|
|
469
|
+
while (k < messages.length) {
|
|
470
|
+
const m = messages[k];
|
|
471
|
+
if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
472
|
+
const badIds = poisonedCallsPerAssistant.get(k);
|
|
473
|
+
if (!badIds || badIds.size === 0) {
|
|
474
|
+
out.push(m);
|
|
475
|
+
k++;
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
const kept = [];
|
|
479
|
+
const lines = [];
|
|
480
|
+
const { callIds } = classifyAssistantCalls(m.tool_calls, k);
|
|
481
|
+
rewrittenAssistantMessages += 1;
|
|
482
|
+
m.tool_calls.forEach((call, callIndex) => {
|
|
483
|
+
const id = callIds[callIndex];
|
|
484
|
+
if (badIds.has(id)) {
|
|
485
|
+
lines.push(renderToolCallAsText(call));
|
|
486
|
+
downgraded++;
|
|
487
|
+
} else {
|
|
488
|
+
kept.push(call);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
if (kept.length === 0) {
|
|
492
|
+
const sanitized2 = transferDowngradedToolTurnOrigin(m, {
|
|
493
|
+
...m,
|
|
494
|
+
content: combineContentWithText(m.content, joinLines(...lines))
|
|
495
|
+
});
|
|
496
|
+
delete sanitized2.tool_calls;
|
|
497
|
+
markDowngradedToolTurnOrigin(sanitized2);
|
|
498
|
+
out.push(sanitized2);
|
|
499
|
+
let nextIdx2 = k + 1;
|
|
500
|
+
while (nextIdx2 < messages.length && messages[nextIdx2].role === "tool") {
|
|
501
|
+
if (poisonedToolIndices.has(nextIdx2)) {
|
|
502
|
+
const poisonedToolMsg = messages[nextIdx2];
|
|
503
|
+
out.push(
|
|
504
|
+
transferDowngradedToolTurnOrigin(poisonedToolMsg, {
|
|
505
|
+
role: "assistant",
|
|
506
|
+
content: renderToolResultAsText(poisonedToolMsg)
|
|
507
|
+
})
|
|
508
|
+
);
|
|
509
|
+
rewrittenToolMessages += 1;
|
|
510
|
+
} else {
|
|
511
|
+
out.push(messages[nextIdx2]);
|
|
512
|
+
}
|
|
513
|
+
nextIdx2++;
|
|
514
|
+
}
|
|
515
|
+
k = nextIdx2;
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const sanitized = transferDowngradedToolTurnOrigin(m, {
|
|
519
|
+
...m,
|
|
520
|
+
content: lines.length > 0 ? combineContentWithText(m.content, joinLines(...lines)) : m.content,
|
|
521
|
+
tool_calls: kept
|
|
522
|
+
});
|
|
523
|
+
out.push(sanitized);
|
|
524
|
+
let nextIdx = k + 1;
|
|
525
|
+
const deferredResultLines = [];
|
|
526
|
+
while (nextIdx < messages.length && messages[nextIdx].role === "tool") {
|
|
527
|
+
if (poisonedToolIndices.has(nextIdx)) {
|
|
528
|
+
deferredResultLines.push(renderToolResultAsText(messages[nextIdx]));
|
|
529
|
+
rewrittenToolMessages += 1;
|
|
530
|
+
} else {
|
|
531
|
+
out.push(messages[nextIdx]);
|
|
532
|
+
}
|
|
533
|
+
nextIdx++;
|
|
534
|
+
}
|
|
535
|
+
if (deferredResultLines.length > 0) {
|
|
536
|
+
out.push({
|
|
537
|
+
role: "assistant",
|
|
538
|
+
content: joinLines(...deferredResultLines)
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
k = nextIdx;
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
if (m.role === "tool") {
|
|
545
|
+
if (poisonedToolIndices.has(k)) {
|
|
546
|
+
out.push(
|
|
547
|
+
transferDowngradedToolTurnOrigin(m, {
|
|
548
|
+
role: "assistant",
|
|
549
|
+
content: renderToolResultAsText(m)
|
|
550
|
+
})
|
|
551
|
+
);
|
|
552
|
+
rewrittenToolMessages += 1;
|
|
553
|
+
} else {
|
|
554
|
+
out.push(m);
|
|
555
|
+
}
|
|
556
|
+
k++;
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
out.push(m);
|
|
560
|
+
k++;
|
|
561
|
+
}
|
|
562
|
+
return {
|
|
563
|
+
messages: out,
|
|
564
|
+
downgraded,
|
|
565
|
+
stats: {
|
|
566
|
+
badArguments,
|
|
567
|
+
// 投影改写数与坏参数数是两套口径:rewrittenToolCalls 含同 ID 连带降级的
|
|
568
|
+
// 调用,二者允许不相等(同 ID 一坏一好 → 坏参数 1、改写调用 2)。
|
|
569
|
+
rewrittenToolCalls: downgraded,
|
|
570
|
+
rewrittenAssistantMessages,
|
|
571
|
+
rewrittenToolMessages
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// packages/core/ollamaEndpoint.ts
|
|
577
|
+
function isOllamaEndpoint(endpoint) {
|
|
578
|
+
if (!endpoint || typeof endpoint !== "string") return false;
|
|
579
|
+
try {
|
|
580
|
+
const url = new URL(endpoint.includes("://") ? endpoint : `http://${endpoint}`);
|
|
581
|
+
if (url.port === "11434") return true;
|
|
582
|
+
const host = url.hostname.toLowerCase();
|
|
583
|
+
return host === "ollama.com" || host.endsWith(".ollama.com") || host === "ollama.ai" || host.endsWith(".ollama.ai");
|
|
584
|
+
} catch {
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// packages/ai/llm/usageRequestOptions.ts
|
|
590
|
+
var STREAM_USAGE_PROVIDERS = /* @__PURE__ */ new Set([
|
|
591
|
+
"google",
|
|
592
|
+
"openrouter",
|
|
593
|
+
"xai",
|
|
594
|
+
"openai",
|
|
595
|
+
"fireworks",
|
|
596
|
+
"mistral",
|
|
597
|
+
"cloudflare",
|
|
598
|
+
"gmi",
|
|
599
|
+
// OpenAI-compatible hosted providers expose the terminal usage chunk when
|
|
600
|
+
// requested, including DeepInfra and Vultr. Keep this capability decision
|
|
601
|
+
// in the shared seam so proxy and local runtimes cannot drift.
|
|
602
|
+
"deepinfra",
|
|
603
|
+
"vultr",
|
|
604
|
+
// Explicit local-runtime providers with OpenAI-compatible streaming: both
|
|
605
|
+
// DeepSeek official and Ollama honor stream_options.include_usage on their
|
|
606
|
+
// chat.completions endpoints. Without them, locally-configured agents lose
|
|
607
|
+
// token statistics / local billing (the whitelist replaced the previous
|
|
608
|
+
// always-on include_usage). ollama-cloud is the Ollama Cloud subscription
|
|
609
|
+
// endpoint (https://ollama.com/v1), an OpenAI-compatible API that likewise
|
|
610
|
+
// honors stream_options.include_usage.
|
|
611
|
+
"deepseek",
|
|
612
|
+
"ollama",
|
|
613
|
+
"ollama-cloud",
|
|
614
|
+
// RunInfra hosted fallback channel: OpenAI-compatible chat.completions
|
|
615
|
+
// endpoint, supports stream_options.include_usage (measured to return
|
|
616
|
+
// prompt_tokens_details.cached_tokens).
|
|
617
|
+
"runinfra",
|
|
618
|
+
"baseten",
|
|
619
|
+
// Kimi For Coding subscription (api.kimi.com/coding/v1): OpenAI-compatible
|
|
620
|
+
// chat.completions streaming that only emits the terminal usage frame when
|
|
621
|
+
// stream_options.include_usage is requested (measured; the official
|
|
622
|
+
// kimi-code CLI also sends include_usage). Custom agents pointing at the
|
|
623
|
+
// same endpoint are covered by the endpoint check below, not here.
|
|
624
|
+
"kimi-code"
|
|
625
|
+
]);
|
|
626
|
+
var KIMI_CODE_ENDPOINT_MARKER = "api.kimi.com";
|
|
627
|
+
var isKimiCodeEndpoint = (endpoint) => typeof endpoint === "string" && endpoint.includes(KIMI_CODE_ENDPOINT_MARKER);
|
|
628
|
+
var EXTRA_USAGE_FIELD_PROVIDERS = /* @__PURE__ */ new Set(["openrouter"]);
|
|
629
|
+
var normalizeProviderName = (providerName) => asTrimmedLowercaseString(providerName);
|
|
630
|
+
var getUsageRequestOptions = (providerName, options) => {
|
|
631
|
+
const normalizedProvider = normalizeProviderName(providerName);
|
|
632
|
+
const api = options?.api ?? "chat-completions";
|
|
633
|
+
const shouldRequestStreamUsage = STREAM_USAGE_PROVIDERS.has(normalizedProvider) || normalizedProvider === "custom" && (isKimiCodeEndpoint(options?.endpoint) || isOllamaEndpoint(options?.endpoint));
|
|
634
|
+
if (api === "responses") {
|
|
635
|
+
return EXTRA_USAGE_FIELD_PROVIDERS.has(normalizedProvider) ? {
|
|
636
|
+
usage: {
|
|
637
|
+
include: true
|
|
638
|
+
}
|
|
639
|
+
} : {};
|
|
640
|
+
}
|
|
641
|
+
return {
|
|
642
|
+
...shouldRequestStreamUsage ? {
|
|
643
|
+
stream_options: {
|
|
644
|
+
include_usage: true
|
|
645
|
+
}
|
|
646
|
+
} : {},
|
|
647
|
+
...EXTRA_USAGE_FIELD_PROVIDERS.has(normalizedProvider) ? {
|
|
648
|
+
usage: {
|
|
649
|
+
include: true
|
|
650
|
+
}
|
|
651
|
+
} : {}
|
|
652
|
+
};
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
// packages/agent-runtime/openAiCompatibleMessages.ts
|
|
656
|
+
function isGeminiCompatibleTarget(provider, model) {
|
|
657
|
+
const p = (provider ?? "").trim().toLowerCase();
|
|
658
|
+
const m = (model ?? "").trim().toLowerCase();
|
|
659
|
+
return p === "google" || p === "google-antigravity" || p.startsWith("google-") || p.includes("gemini") || m.includes("gemini");
|
|
660
|
+
}
|
|
661
|
+
function preserveAgentStateFields(source, target, options) {
|
|
662
|
+
const mutableTarget = target;
|
|
663
|
+
if (source.role === "assistant") {
|
|
664
|
+
const shapingCounts = options?.shapingCounts;
|
|
665
|
+
if (!options?.stripReasoningContent && typeof source.reasoning_content === "string") {
|
|
666
|
+
mutableTarget.reasoning_content = source.reasoning_content;
|
|
667
|
+
}
|
|
668
|
+
if (Array.isArray(source.tool_calls)) {
|
|
669
|
+
if (shapingCounts && source.tool_calls.length > 0) {
|
|
670
|
+
shapingCounts.assistantToolTurns += 1;
|
|
671
|
+
const hadUsableReasoning = typeof source.reasoning_content === "string" && source.reasoning_content.length > 0;
|
|
672
|
+
if (options?.stripReasoningContent) {
|
|
673
|
+
if (hadUsableReasoning) shapingCounts.reasoningStrippedTurns += 1;
|
|
674
|
+
else shapingCounts.missingReasoningTurns += 1;
|
|
675
|
+
} else if (!hadUsableReasoning) {
|
|
676
|
+
shapingCounts.missingReasoningTurns += 1;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
const isExplicitTarget = Boolean(options?.targetProvider || options?.targetModel);
|
|
680
|
+
const allowSignature = options?.allowThoughtSignature ?? (isExplicitTarget ? isGeminiCompatibleTarget(options?.targetProvider, options?.targetModel) : true);
|
|
681
|
+
mutableTarget.tool_calls = source.tool_calls.map((call) => {
|
|
682
|
+
if (!call || typeof call !== "object") return call;
|
|
683
|
+
const cleaned = {
|
|
684
|
+
id: call.id,
|
|
685
|
+
type: call.type ?? "function",
|
|
686
|
+
function: call.function
|
|
687
|
+
};
|
|
688
|
+
if (allowSignature) {
|
|
689
|
+
if (call.extra_content !== void 0) cleaned.extra_content = call.extra_content;
|
|
690
|
+
if (call.thought_signature !== void 0) cleaned.thought_signature = call.thought_signature;
|
|
691
|
+
}
|
|
692
|
+
return cleaned;
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
const hasReplayableToolCalls = Array.isArray(mutableTarget.tool_calls) && mutableTarget.tool_calls.length > 0;
|
|
696
|
+
const replayPlaceholder = options?.replayReasoningPlaceholder;
|
|
697
|
+
if (typeof replayPlaceholder === "string" && replayPlaceholder.length > 0 && // strip 优先:拒 string reasoning_content 的 provider 也会拒这个占位。
|
|
698
|
+
!options?.stripReasoningContent && (hasReplayableToolCalls || hasDowngradedToolTurnOrigin(source)) && !// 真实 reasoning_content 优先,永不被占位覆盖。
|
|
699
|
+
(typeof mutableTarget.reasoning_content === "string" && mutableTarget.reasoning_content.length > 0)) {
|
|
700
|
+
mutableTarget.reasoning_content = replayPlaceholder;
|
|
701
|
+
if (shapingCounts) shapingCounts.placeholderInjectedTurns += 1;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (source.role === "tool") {
|
|
705
|
+
const toolCallId = typeof source.tool_call_id === "string" ? source.tool_call_id.trim() : typeof source.toolCallId === "string" ? source.toolCallId.trim() : "";
|
|
706
|
+
if (toolCallId) mutableTarget.tool_call_id = toolCallId;
|
|
707
|
+
}
|
|
708
|
+
return target;
|
|
709
|
+
}
|
|
710
|
+
function toOpenAiCompatibleMessages(messages, options) {
|
|
711
|
+
return messages.map(
|
|
712
|
+
(message) => preserveAgentStateFields(message, {
|
|
713
|
+
role: message.role,
|
|
714
|
+
content: message.content ?? ""
|
|
715
|
+
}, options)
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
function shouldStripReasoningContentForOutbound(provider, model) {
|
|
719
|
+
const p = provider?.trim().toLowerCase();
|
|
720
|
+
const m = model?.trim().toLowerCase();
|
|
721
|
+
if (!p || !m) return false;
|
|
722
|
+
if (p === "deepseek" || p === "nolo") {
|
|
723
|
+
return m === "deepseek-flash" || m === "deepseek-v4-flash" || m === "deepseek-v4-flash-vision-exp" || m === "deepseek-v4-pro";
|
|
724
|
+
}
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
727
|
+
function shouldReplayReasoningContentForOutbound(provider, model) {
|
|
728
|
+
const p = provider?.trim().toLowerCase();
|
|
729
|
+
const m = model?.trim().toLowerCase();
|
|
730
|
+
if (!p || !m) return false;
|
|
731
|
+
return (p === "opencode-go" || p === "opencode") && m.includes("deepseek");
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// packages/integrations/openai/responsesHelpers.ts
|
|
735
|
+
var RESPONSES_TOP_LEVEL_SCHEMA_KEYS = ["anyOf", "oneOf", "allOf", "enum", "not"];
|
|
736
|
+
var sanitizeResponsesParameters = (parameters) => {
|
|
737
|
+
if (!isRecord(parameters)) {
|
|
738
|
+
return parameters;
|
|
739
|
+
}
|
|
740
|
+
const next = { ...parameters };
|
|
741
|
+
for (const key of RESPONSES_TOP_LEVEL_SCHEMA_KEYS) {
|
|
742
|
+
delete next[key];
|
|
743
|
+
}
|
|
744
|
+
return next;
|
|
745
|
+
};
|
|
746
|
+
var appendTextPart = (parts, text, role) => {
|
|
747
|
+
if (!text) return;
|
|
748
|
+
const last = parts.at(-1);
|
|
749
|
+
const textType = role === "assistant" ? "output_text" : "input_text";
|
|
750
|
+
if (last?.type === textType) {
|
|
751
|
+
last.text += text;
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
parts.push({ type: textType, text });
|
|
755
|
+
};
|
|
756
|
+
var normalizeMessageParts = (content, role) => {
|
|
757
|
+
if (typeof content === "string") {
|
|
758
|
+
if (!content) return [];
|
|
759
|
+
return [
|
|
760
|
+
{
|
|
761
|
+
type: role === "assistant" ? "output_text" : "input_text",
|
|
762
|
+
text: content
|
|
763
|
+
}
|
|
764
|
+
];
|
|
765
|
+
}
|
|
766
|
+
const parts = [];
|
|
767
|
+
for (const part of content ?? []) {
|
|
768
|
+
const typedPart = part;
|
|
769
|
+
if (typedPart?.type === "text" && typeof typedPart.text === "string") {
|
|
770
|
+
appendTextPart(parts, typedPart.text, role);
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
if (typedPart?.type === "image_url" && typeof typedPart.image_url?.url === "string" && typedPart.image_url.url) {
|
|
774
|
+
if (role === "assistant") continue;
|
|
775
|
+
parts.push({
|
|
776
|
+
type: "input_image",
|
|
777
|
+
image_url: typedPart.image_url.url,
|
|
778
|
+
detail: typedPart.image_url.detail
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
return parts;
|
|
783
|
+
};
|
|
784
|
+
var normalizeToolOutput = (content) => {
|
|
785
|
+
if (typeof content === "string") return content;
|
|
786
|
+
return JSON.stringify(content ?? "");
|
|
787
|
+
};
|
|
788
|
+
var toResponsesTools = (tools) => {
|
|
789
|
+
if (!Array.isArray(tools) || tools.length === 0) return void 0;
|
|
790
|
+
const normalized = tools.map((tool) => {
|
|
791
|
+
const fn = tool?.function;
|
|
792
|
+
const name = fn?.name ?? tool?.name;
|
|
793
|
+
if (!name) return null;
|
|
794
|
+
const parameters = fn?.parameters ?? tool?.parameters;
|
|
795
|
+
return {
|
|
796
|
+
type: "function",
|
|
797
|
+
name,
|
|
798
|
+
...typeof (fn?.description ?? tool?.description) === "string" ? { description: fn?.description ?? tool?.description } : {},
|
|
799
|
+
parameters: sanitizeResponsesParameters(parameters),
|
|
800
|
+
...fn?.strict !== void 0 || tool?.strict !== void 0 ? { strict: fn?.strict ?? tool?.strict } : {}
|
|
801
|
+
};
|
|
802
|
+
}).filter(Boolean);
|
|
803
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
804
|
+
};
|
|
805
|
+
var convertMessagesToResponsesInput = (messages, options) => {
|
|
806
|
+
const input = [];
|
|
807
|
+
for (const message of messages) {
|
|
808
|
+
if (!message?.role) continue;
|
|
809
|
+
if (message.role === "tool") {
|
|
810
|
+
if (!message.tool_call_id) continue;
|
|
811
|
+
input.push({
|
|
812
|
+
type: "function_call_output",
|
|
813
|
+
call_id: message.tool_call_id,
|
|
814
|
+
output: normalizeToolOutput(message.content)
|
|
815
|
+
});
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
const role = message.role;
|
|
819
|
+
if (role === "assistant" && !options?.stripReasoningContent && typeof message.reasoning_content === "string" && message.reasoning_content) {
|
|
820
|
+
input.push({
|
|
821
|
+
type: "reasoning",
|
|
822
|
+
content: [
|
|
823
|
+
{ type: "reasoning_text", text: message.reasoning_content }
|
|
824
|
+
]
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
const contentParts = normalizeMessageParts(message.content, role);
|
|
828
|
+
if (contentParts.length > 0) {
|
|
829
|
+
input.push({
|
|
830
|
+
type: "message",
|
|
831
|
+
role,
|
|
832
|
+
content: contentParts
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
if (role === "assistant" && Array.isArray(message.content)) {
|
|
836
|
+
const replayImages = message.content.map((part) => part).filter(
|
|
837
|
+
(part) => part?.type === "image_url" && typeof part.image_url?.url === "string" && Boolean(part.image_url.url)
|
|
838
|
+
).map((part) => ({
|
|
839
|
+
type: "input_image",
|
|
840
|
+
image_url: part.image_url.url,
|
|
841
|
+
detail: part.image_url.detail
|
|
842
|
+
}));
|
|
843
|
+
if (replayImages.length > 0) {
|
|
844
|
+
input.push({
|
|
845
|
+
type: "message",
|
|
846
|
+
role: "user",
|
|
847
|
+
content: replayImages
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
if (role === "assistant" && Array.isArray(message.tool_calls)) {
|
|
852
|
+
for (const toolCall of message.tool_calls) {
|
|
853
|
+
if (!toolCall?.id || !toolCall.function?.name) continue;
|
|
854
|
+
input.push({
|
|
855
|
+
type: "function_call",
|
|
856
|
+
call_id: toolCall.id,
|
|
857
|
+
name: toolCall.function.name,
|
|
858
|
+
arguments: typeof toolCall.function.arguments === "string" ? toolCall.function.arguments : JSON.stringify(toolCall.function.arguments ?? {})
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
return input;
|
|
864
|
+
};
|
|
865
|
+
var extractTextFromResponseOutput = (response) => {
|
|
866
|
+
const parts = [];
|
|
867
|
+
for (const item of response?.output ?? []) {
|
|
868
|
+
if (item?.type !== "message") continue;
|
|
869
|
+
for (const content of item.content ?? []) {
|
|
870
|
+
if (content?.type === "output_text" && typeof content.text === "string") {
|
|
871
|
+
parts.push(content.text);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return parts.join("");
|
|
876
|
+
};
|
|
877
|
+
var extractReasoningFromResponseOutput = (response) => {
|
|
878
|
+
const parts = [];
|
|
879
|
+
for (const item of response?.output ?? []) {
|
|
880
|
+
if (item?.type !== "reasoning") continue;
|
|
881
|
+
if (typeof item.content === "string") {
|
|
882
|
+
parts.push(item.content);
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
for (const content of item.content ?? []) {
|
|
886
|
+
if (typeof content === "string") parts.push(content);
|
|
887
|
+
else if (typeof content?.text === "string") parts.push(content.text);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return parts.join("");
|
|
891
|
+
};
|
|
892
|
+
var toDataUrl = (base64Data, mimeType) => {
|
|
893
|
+
const normalizedMimeType = asOptionalTrimmedString(mimeType) ?? "image/png";
|
|
894
|
+
return `data:${normalizedMimeType};base64,${base64Data}`;
|
|
895
|
+
};
|
|
896
|
+
var extractImagePartsFromResponseOutput = (response) => {
|
|
897
|
+
const images = [];
|
|
898
|
+
for (const item of response?.output ?? []) {
|
|
899
|
+
if (item?.type === "image_generation_call") {
|
|
900
|
+
const result = asOptionalTrimmedString(item.result);
|
|
901
|
+
if (result) {
|
|
902
|
+
const outputFormat = asOptionalTrimmedString(item.output_format);
|
|
903
|
+
images.push({
|
|
904
|
+
type: "image_url",
|
|
905
|
+
image_url: {
|
|
906
|
+
url: toDataUrl(
|
|
907
|
+
result,
|
|
908
|
+
outputFormat ? `image/${outputFormat}` : void 0
|
|
909
|
+
)
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (item?.type !== "message") continue;
|
|
916
|
+
for (const content of item.content ?? []) {
|
|
917
|
+
const result = asOptionalTrimmedString(content?.result);
|
|
918
|
+
if (content?.type === "output_image" && result) {
|
|
919
|
+
images.push({
|
|
920
|
+
type: "image_url",
|
|
921
|
+
image_url: {
|
|
922
|
+
url: toDataUrl(
|
|
923
|
+
result,
|
|
924
|
+
content.mime_type ?? content.mimeType ?? null
|
|
925
|
+
)
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return images;
|
|
932
|
+
};
|
|
933
|
+
var extractToolCallsFromResponseOutput = (response) => {
|
|
934
|
+
const calls = [];
|
|
935
|
+
for (const item of response?.output ?? []) {
|
|
936
|
+
if (item?.type !== "function_call") continue;
|
|
937
|
+
if (!item.call_id || !item.name) continue;
|
|
938
|
+
calls.push({
|
|
939
|
+
id: item.call_id,
|
|
940
|
+
type: "function",
|
|
941
|
+
function: {
|
|
942
|
+
name: item.name,
|
|
943
|
+
arguments: typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {})
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
return calls;
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
// packages/agent-runtime/promptCacheKey.ts
|
|
951
|
+
function collectStablePromptPrefix(messages, fallbackPrompt) {
|
|
952
|
+
const systemTexts = [];
|
|
953
|
+
if (fallbackPrompt?.trim()) systemTexts.push(fallbackPrompt.trim());
|
|
954
|
+
for (const raw of messages) {
|
|
955
|
+
if (!raw || typeof raw !== "object") continue;
|
|
956
|
+
const message = raw;
|
|
957
|
+
const role = String(message.role ?? "");
|
|
958
|
+
if (role !== "system" && role !== "developer") continue;
|
|
959
|
+
if (typeof message.content === "string") {
|
|
960
|
+
const boundary = Number(message.stable_prefix_chars);
|
|
961
|
+
const text = Number.isFinite(boundary) && boundary > 0 ? message.content.slice(0, boundary) : message.content;
|
|
962
|
+
if (text.trim()) systemTexts.push(text.trim());
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return systemTexts.join("\n\n");
|
|
966
|
+
}
|
|
967
|
+
function stablePromptCacheKey(parts, namespace) {
|
|
968
|
+
const value = JSON.stringify(parts);
|
|
969
|
+
let hash = 2166136261;
|
|
970
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
971
|
+
hash ^= value.charCodeAt(index);
|
|
972
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
973
|
+
}
|
|
974
|
+
return `${namespace}-${hash.toString(16).padStart(8, "0")}`;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// packages/core/chat/imageParts.ts
|
|
978
|
+
function isImageUrlPart(part) {
|
|
979
|
+
return isRecord(part) && part.type === "image_url";
|
|
980
|
+
}
|
|
981
|
+
function hasImageParts(messages) {
|
|
982
|
+
return messages.some(
|
|
983
|
+
(message) => Array.isArray(message.content) && message.content.some(isImageUrlPart)
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
export {
|
|
988
|
+
sanitizeForOutbound,
|
|
989
|
+
hasParsableObjectArguments,
|
|
990
|
+
repairTruncatedToolArguments,
|
|
991
|
+
downgradeUnparsableToolCalls,
|
|
992
|
+
isOllamaEndpoint,
|
|
993
|
+
getUsageRequestOptions,
|
|
994
|
+
isImageUrlPart,
|
|
995
|
+
hasImageParts,
|
|
996
|
+
preserveAgentStateFields,
|
|
997
|
+
toOpenAiCompatibleMessages,
|
|
998
|
+
shouldStripReasoningContentForOutbound,
|
|
999
|
+
shouldReplayReasoningContentForOutbound,
|
|
1000
|
+
toResponsesTools,
|
|
1001
|
+
convertMessagesToResponsesInput,
|
|
1002
|
+
extractTextFromResponseOutput,
|
|
1003
|
+
extractReasoningFromResponseOutput,
|
|
1004
|
+
extractImagePartsFromResponseOutput,
|
|
1005
|
+
extractToolCallsFromResponseOutput,
|
|
1006
|
+
collectStablePromptPrefix,
|
|
1007
|
+
stablePromptCacheKey
|
|
1008
|
+
};
|