nolo-cli 0.107.0-alpha.4 → 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-AU5I4M4W.js → agentEmailCommands-YC2A4USQ.js} +99 -89
- package/agentListCommands-UDJELMYP.js +741 -0
- package/{agentMachineCommands-YMNME2L6.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-UVA7OYO3.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-IBOOZVVD.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-MS7TSPZR.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-FG3HKPQP.js → cursorProvider-YGGNMVWX.js} +2751 -10185
- 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-M2T2I5NF.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-XQRDGWRZ.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-G4KK4R7H.js +0 -128
- package/agentRunCommand-UTZJA23G.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-ISBKOOD7.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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
readSseFrames
|
|
3
|
+
} from "./chunk-GMZLP5DV.js";
|
|
4
4
|
import {
|
|
5
5
|
accumulateToolCallDelta,
|
|
6
6
|
createThinkParserState,
|
|
@@ -21,11 +21,19 @@ import {
|
|
|
21
21
|
extractToolCallsFromResponseOutput,
|
|
22
22
|
getUsageRequestOptions,
|
|
23
23
|
hasImageParts,
|
|
24
|
+
sanitizeForOutbound,
|
|
24
25
|
shouldStripReasoningContentForOutbound,
|
|
25
26
|
stablePromptCacheKey,
|
|
26
27
|
toOpenAiCompatibleMessages,
|
|
27
28
|
toResponsesTools
|
|
28
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-UM7TA3K4.js";
|
|
30
|
+
import {
|
|
31
|
+
isMeaningfulChatCompletionOutput,
|
|
32
|
+
isMeaningfulResponsesOutput
|
|
33
|
+
} from "./chunk-R6EBQEQE.js";
|
|
34
|
+
import {
|
|
35
|
+
clipCompactText
|
|
36
|
+
} from "./chunk-5MMAK75Q.js";
|
|
29
37
|
import {
|
|
30
38
|
buildProviderExecutionPlan,
|
|
31
39
|
canUsePlatformChatProvider,
|
|
@@ -35,16 +43,11 @@ import {
|
|
|
35
43
|
resolvePlatformAuthToken,
|
|
36
44
|
resolvePlatformServerUrl,
|
|
37
45
|
resolveProviderTransportDecision
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import {
|
|
40
|
-
clipCompactText,
|
|
41
|
-
isMeaningfulChatCompletionOutput,
|
|
42
|
-
isMeaningfulResponsesOutput
|
|
43
|
-
} from "./chunk-P5EVSOPA.js";
|
|
46
|
+
} from "./chunk-BIPGGSJS.js";
|
|
44
47
|
import {
|
|
45
48
|
NOLO_CLIENT_VERSION_HEADER,
|
|
46
49
|
isPlatformMimoProviderModel
|
|
47
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-SZC4REES.js";
|
|
48
51
|
import {
|
|
49
52
|
isRecord
|
|
50
53
|
} from "./chunk-KUG52IAP.js";
|
|
@@ -213,18 +216,58 @@ function createResponsesToolAccumulator() {
|
|
|
213
216
|
function keyOf(event) {
|
|
214
217
|
return typeof event?.item_id === "string" && event.item_id ? event.item_id : typeof event?.item?.id === "string" && event.item.id ? event.item.id : typeof event?.item?.call_id === "string" && event.item.call_id ? event.item.call_id : typeof event?.call_id === "string" && event.call_id ? event.call_id : "";
|
|
215
218
|
}
|
|
219
|
+
function shortFingerprint(value) {
|
|
220
|
+
let hash = 2166136261;
|
|
221
|
+
for (let i = 0; i < value.length; i++) {
|
|
222
|
+
hash ^= value.charCodeAt(i);
|
|
223
|
+
hash = Math.imul(hash, 16777619);
|
|
224
|
+
}
|
|
225
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
226
|
+
}
|
|
227
|
+
function parsesAsJsonObject(value) {
|
|
228
|
+
try {
|
|
229
|
+
const parsed = JSON.parse(value);
|
|
230
|
+
return parsed !== null && typeof parsed === "object";
|
|
231
|
+
} catch {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
216
235
|
function applyResponsesToolEvent(calls, event) {
|
|
217
236
|
const key = keyOf(event);
|
|
218
237
|
if (!key) return;
|
|
219
238
|
const item = event?.item;
|
|
220
239
|
const id = item?.call_id || item?.id || event?.call_id || key;
|
|
221
|
-
const current = calls.get(key) ?? { id, name: "", arguments: "" };
|
|
240
|
+
const current = calls.get(key) ?? { id, name: "", arguments: "", sawDelta: false };
|
|
222
241
|
if (typeof item?.name === "string" && item.name) current.name = item.name;
|
|
242
|
+
const applySnapshot = (next) => {
|
|
243
|
+
if (!current.sawDelta) {
|
|
244
|
+
current.arguments = next;
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (next.startsWith(current.arguments)) {
|
|
248
|
+
current.arguments = next;
|
|
249
|
+
} else if (current.arguments.startsWith(next)) {
|
|
250
|
+
} else {
|
|
251
|
+
if (!parsesAsJsonObject(current.arguments) && parsesAsJsonObject(next)) {
|
|
252
|
+
console.warn(
|
|
253
|
+
`[responses-tool-call] adopting parsable snapshot over unparsable accumulation (accumulated length=${current.arguments.length}, fingerprint=${shortFingerprint(current.arguments)}; snapshot length=${next.length}, fingerprint=${shortFingerprint(next)})`
|
|
254
|
+
);
|
|
255
|
+
current.arguments = next;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
console.warn(
|
|
259
|
+
`[responses-tool-call] conflicting arguments snapshot (accumulated length=${current.arguments.length}, fingerprint=${shortFingerprint(current.arguments)}; snapshot length=${next.length}, fingerprint=${shortFingerprint(next)})`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
223
263
|
const itemArguments = normalizeResponsesToolArguments(item?.arguments);
|
|
224
|
-
if (itemArguments !== void 0)
|
|
264
|
+
if (itemArguments !== void 0) applySnapshot(itemArguments);
|
|
225
265
|
const eventArguments = normalizeResponsesToolArguments(event?.arguments);
|
|
226
|
-
if (eventArguments !== void 0)
|
|
227
|
-
if (typeof event?.delta === "string")
|
|
266
|
+
if (eventArguments !== void 0) applySnapshot(eventArguments);
|
|
267
|
+
if (typeof event?.delta === "string") {
|
|
268
|
+
current.sawDelta = true;
|
|
269
|
+
current.arguments += event.delta;
|
|
270
|
+
}
|
|
228
271
|
calls.set(key, current);
|
|
229
272
|
}
|
|
230
273
|
function addResponsesToolCall(calls, call) {
|
|
@@ -232,7 +275,8 @@ function addResponsesToolCall(calls, call) {
|
|
|
232
275
|
calls.set(key, {
|
|
233
276
|
id: call.id,
|
|
234
277
|
name: call.function.name,
|
|
235
|
-
arguments: call.function.arguments
|
|
278
|
+
arguments: call.function.arguments,
|
|
279
|
+
sawDelta: false
|
|
236
280
|
});
|
|
237
281
|
}
|
|
238
282
|
function finalizeResponsesToolCalls(calls) {
|
|
@@ -347,83 +391,6 @@ function flushChatCompletionStream(state) {
|
|
|
347
391
|
}
|
|
348
392
|
}
|
|
349
393
|
|
|
350
|
-
// packages/agent-runtime/sseFrames.ts
|
|
351
|
-
async function* readSseFrames(response) {
|
|
352
|
-
const reader = response.body?.getReader();
|
|
353
|
-
if (!reader) {
|
|
354
|
-
throw new Error("SSE response did not include a readable body.");
|
|
355
|
-
}
|
|
356
|
-
const decoder = new TextDecoder();
|
|
357
|
-
let buffer = "";
|
|
358
|
-
while (true) {
|
|
359
|
-
const { done, value } = await reader.read();
|
|
360
|
-
if (done) break;
|
|
361
|
-
buffer += decoder.decode(value, { stream: true });
|
|
362
|
-
let boundary = findSseFrameBoundary(buffer);
|
|
363
|
-
while (boundary) {
|
|
364
|
-
yield buffer.slice(0, boundary.index);
|
|
365
|
-
buffer = buffer.slice(boundary.index + boundary.separatorLength);
|
|
366
|
-
boundary = findSseFrameBoundary(buffer);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
const remaining = decoder.decode();
|
|
370
|
-
if (remaining) {
|
|
371
|
-
buffer += remaining;
|
|
372
|
-
let boundary = findSseFrameBoundary(buffer);
|
|
373
|
-
while (boundary) {
|
|
374
|
-
yield buffer.slice(0, boundary.index);
|
|
375
|
-
buffer = buffer.slice(boundary.index + boundary.separatorLength);
|
|
376
|
-
boundary = findSseFrameBoundary(buffer);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
if (buffer.trim()) yield buffer;
|
|
380
|
-
}
|
|
381
|
-
function findSseFrameBoundary(buffer) {
|
|
382
|
-
const lfLf = buffer.indexOf("\n\n");
|
|
383
|
-
const crLfCrLf = buffer.indexOf("\r\n\r\n");
|
|
384
|
-
if (lfLf === -1 && crLfCrLf === -1) return null;
|
|
385
|
-
const useLf = lfLf !== -1 && (crLfCrLf === -1 || lfLf < crLfCrLf);
|
|
386
|
-
return useLf ? { index: lfLf, separatorLength: 2 } : { index: crLfCrLf, separatorLength: 4 };
|
|
387
|
-
}
|
|
388
|
-
async function* streamSseDataValues(response, parse) {
|
|
389
|
-
const reader = response.body?.getReader();
|
|
390
|
-
if (!reader) return;
|
|
391
|
-
const decoder = new TextDecoder();
|
|
392
|
-
let buffer = "";
|
|
393
|
-
while (true) {
|
|
394
|
-
const { done, value } = await reader.read();
|
|
395
|
-
if (done) break;
|
|
396
|
-
buffer += decoder.decode(value, { stream: true });
|
|
397
|
-
const lines = buffer.split("\n");
|
|
398
|
-
buffer = lines.pop() ?? "";
|
|
399
|
-
for (const line of lines) {
|
|
400
|
-
const parsed = parse(line);
|
|
401
|
-
if (parsed) yield parsed;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
const remaining = decoder.decode();
|
|
405
|
-
if (remaining) {
|
|
406
|
-
buffer += remaining;
|
|
407
|
-
const lines = buffer.split("\n");
|
|
408
|
-
buffer = lines.pop() ?? "";
|
|
409
|
-
for (const line of lines) {
|
|
410
|
-
const parsed = parse(line);
|
|
411
|
-
if (parsed) yield parsed;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
if (buffer.trim()) {
|
|
415
|
-
const parsed = parse(buffer);
|
|
416
|
-
if (parsed) yield parsed;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
async function readSseDataValues(response, parse) {
|
|
420
|
-
const values = [];
|
|
421
|
-
for await (const value of streamSseDataValues(response, parse)) {
|
|
422
|
-
values.push(value);
|
|
423
|
-
}
|
|
424
|
-
return values;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
394
|
// packages/agent-runtime/platformChatProvider.ts
|
|
428
395
|
var PlatformStreamInterruptedError = class extends Error {
|
|
429
396
|
code = "PLATFORM_STREAM_INTERRUPTED";
|
|
@@ -535,6 +502,12 @@ async function resolvePlatformChatProviderConfig(args) {
|
|
|
535
502
|
};
|
|
536
503
|
}
|
|
537
504
|
function buildPlatformChatCompletionRequest(args) {
|
|
505
|
+
if (!args.providerConfig.authToken?.trim()) {
|
|
506
|
+
throw Object.assign(
|
|
507
|
+
new Error("desktop platform provider failed: AUTH_NO_TOKEN"),
|
|
508
|
+
{ code: "AUTH_NO_TOKEN", authCode: "AUTH_NO_TOKEN", stage: "provider" }
|
|
509
|
+
);
|
|
510
|
+
}
|
|
538
511
|
const usesResponsesApi = isResponsesEndpoint(args.providerConfig.endpoint);
|
|
539
512
|
const requestOptions = usesResponsesApi ? toResponsesRequestOptions(args.providerConfig.requestOptions) : args.providerConfig.requestOptions;
|
|
540
513
|
const shouldStripReasoning = shouldStripReasoningContentForOutbound(
|
|
@@ -926,9 +899,6 @@ export {
|
|
|
926
899
|
applyChatCompletionDelta,
|
|
927
900
|
flushChatCompletionStream,
|
|
928
901
|
providerHttpFailure,
|
|
929
|
-
readSseFrames,
|
|
930
|
-
streamSseDataValues,
|
|
931
|
-
readSseDataValues,
|
|
932
902
|
createResponsesToolAccumulator,
|
|
933
903
|
applyResponsesToolEvent,
|
|
934
904
|
finalizeResponsesToolCalls,
|
|
@@ -14,7 +14,7 @@ function buildCliLocalRuntimeDbEnv(env = process.env) {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
async function getDefaultCliLocalRuntimeDb(options = {}) {
|
|
17
|
-
const { getDefaultCliLocalRuntimeDb: getAuthorityBackedDb } = await import("./localRuntimeAuthority-
|
|
17
|
+
const { getDefaultCliLocalRuntimeDb: getAuthorityBackedDb } = await import("./localRuntimeAuthority-TU6OBC76.js");
|
|
18
18
|
return getAuthorityBackedDb(options);
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -5,13 +5,10 @@ import {
|
|
|
5
5
|
isRecord
|
|
6
6
|
} from "./chunk-KUG52IAP.js";
|
|
7
7
|
|
|
8
|
-
// packages/desktop-chrome-connector/chromeConnector.ts
|
|
9
|
-
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
10
|
-
import { resolve as resolve2 } from "node:path";
|
|
11
|
-
|
|
12
8
|
// packages/desktop-chrome-connector/uploadSecurity.mjs
|
|
13
|
-
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
14
|
-
import {
|
|
9
|
+
import { existsSync, lstatSync, mkdirSync, realpathSync, statSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
15
12
|
var DEFAULT_MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
16
13
|
var DEFAULT_MAX_FILES = 10;
|
|
17
14
|
var UploadSecurityError = class extends Error {
|
|
@@ -28,22 +25,106 @@ function isSubpath(parent, child) {
|
|
|
28
25
|
const rel = relative(parent, child);
|
|
29
26
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
30
27
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
var DEFAULT_UPLOAD_ROOT_SUFFIX = join(".nolo", "uploads");
|
|
29
|
+
function resolveDefaultUploadRoot(env = process.env) {
|
|
30
|
+
let home;
|
|
31
|
+
try {
|
|
32
|
+
home = env?.HOME || homedir();
|
|
33
|
+
} catch (err) {
|
|
34
|
+
throw createUploadSecurityError(
|
|
35
|
+
"path_not_allowed",
|
|
36
|
+
`Could not determine the home directory for the default upload root: ${err instanceof Error ? err.message : String(err)}`
|
|
37
|
+
);
|
|
35
38
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
if (typeof home !== "string" || !isAbsolute(home)) {
|
|
40
|
+
throw createUploadSecurityError(
|
|
41
|
+
"path_not_allowed",
|
|
42
|
+
`Home directory '${String(home)}' must be an absolute path to derive the default upload root '${DEFAULT_UPLOAD_ROOT_SUFFIX}'.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return resolve(join(home, DEFAULT_UPLOAD_ROOT_SUFFIX));
|
|
46
|
+
}
|
|
47
|
+
function splitConfiguredRoots(raw) {
|
|
48
|
+
const entries = typeof raw === "string" ? raw.split(",").map((entry) => entry.trim()).filter(Boolean) : [];
|
|
49
|
+
const absolute = [];
|
|
50
|
+
const dropped = [];
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
(isAbsolute(entry) ? absolute : dropped).push(entry);
|
|
53
|
+
}
|
|
54
|
+
return { absolute, dropped };
|
|
55
|
+
}
|
|
56
|
+
function resolveUploadRoots(env = process.env) {
|
|
57
|
+
const raw = env?.NOLO_CHROME_UPLOAD_ROOTS;
|
|
58
|
+
if (raw !== void 0) {
|
|
59
|
+
const { absolute, dropped } = splitConfiguredRoots(raw);
|
|
60
|
+
const roots = absolute.map((entry) => {
|
|
61
|
+
const resolved = resolve(entry);
|
|
62
|
+
if (!existsSync(resolved)) {
|
|
63
|
+
return resolved;
|
|
64
|
+
}
|
|
39
65
|
try {
|
|
40
66
|
return realpathSync(resolved);
|
|
41
67
|
} catch {
|
|
42
68
|
return resolved;
|
|
43
69
|
}
|
|
70
|
+
});
|
|
71
|
+
return { configured: true, isDefault: false, roots, dropped };
|
|
72
|
+
}
|
|
73
|
+
const defaultDir = resolveDefaultUploadRoot(env);
|
|
74
|
+
return {
|
|
75
|
+
configured: false,
|
|
76
|
+
isDefault: true,
|
|
77
|
+
roots: [existsSync(defaultDir) ? inspectDefaultUploadRoot(defaultDir) : defaultDir],
|
|
78
|
+
dropped: []
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function ensureDefaultUploadRoot(env = process.env) {
|
|
82
|
+
if (env?.NOLO_CHROME_UPLOAD_ROOTS !== void 0) {
|
|
83
|
+
return resolveUploadRoots(env);
|
|
84
|
+
}
|
|
85
|
+
const defaultDir = resolveDefaultUploadRoot(env);
|
|
86
|
+
if (!existsSync(defaultDir)) {
|
|
87
|
+
try {
|
|
88
|
+
mkdirSync(defaultDir, { recursive: true, mode: 448 });
|
|
89
|
+
} catch (err) {
|
|
90
|
+
throw createUploadSecurityError(
|
|
91
|
+
"path_not_allowed",
|
|
92
|
+
`Default upload root '${defaultDir}' could not be created: ${err instanceof Error ? err.message : String(err)}`
|
|
93
|
+
);
|
|
44
94
|
}
|
|
45
|
-
|
|
46
|
-
}
|
|
95
|
+
}
|
|
96
|
+
return { configured: false, isDefault: true, roots: [inspectDefaultUploadRoot(defaultDir)], dropped: [] };
|
|
97
|
+
}
|
|
98
|
+
function inspectDefaultUploadRoot(defaultDir) {
|
|
99
|
+
let lst;
|
|
100
|
+
try {
|
|
101
|
+
lst = lstatSync(defaultDir);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
throw createUploadSecurityError(
|
|
104
|
+
"path_not_allowed",
|
|
105
|
+
`Default upload root '${defaultDir}' could not be inspected: ${err instanceof Error ? err.message : String(err)}`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (lst.isSymbolicLink()) {
|
|
109
|
+
throw createUploadSecurityError(
|
|
110
|
+
"path_not_allowed",
|
|
111
|
+
`Default upload root '${defaultDir}' is a symbolic link, which is not permitted. Set NOLO_CHROME_UPLOAD_ROOTS to the real directory if you need a custom location.`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
if (!lst.isDirectory()) {
|
|
115
|
+
throw createUploadSecurityError(
|
|
116
|
+
"path_not_allowed",
|
|
117
|
+
`Default upload root '${defaultDir}' is not a directory.`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
return realpathSync(defaultDir);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
throw createUploadSecurityError(
|
|
124
|
+
"path_not_allowed",
|
|
125
|
+
`Default upload root '${defaultDir}' canonical path could not be resolved: ${err instanceof Error ? err.message : String(err)}`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
47
128
|
}
|
|
48
129
|
function validateUploadFiles(options = {}) {
|
|
49
130
|
const {
|
|
@@ -61,11 +142,14 @@ function validateUploadFiles(options = {}) {
|
|
|
61
142
|
`Too many files: ${files.length} provided, maximum allowed is ${maxFiles}.`
|
|
62
143
|
);
|
|
63
144
|
}
|
|
64
|
-
const
|
|
145
|
+
const rootsInfo = ensureDefaultUploadRoot(env);
|
|
146
|
+
const allowedRoots = rootsInfo.roots;
|
|
65
147
|
if (allowedRoots.length === 0) {
|
|
148
|
+
const dropped = rootsInfo.dropped ?? [];
|
|
149
|
+
const droppedHint = dropped.length ? ` Ignored entries: ${dropped.map((entry) => `'${entry}'`).join(", ")} (only absolute paths are accepted; '~' and relative paths are never expanded).` : "";
|
|
66
150
|
throw createUploadSecurityError(
|
|
67
151
|
"path_not_allowed",
|
|
68
|
-
|
|
152
|
+
`NOLO_CHROME_UPLOAD_ROOTS is set but contains no usable absolute path; all uploads are refused.${droppedHint}`
|
|
69
153
|
);
|
|
70
154
|
}
|
|
71
155
|
const fileStats = [];
|
|
@@ -135,8 +219,29 @@ function logUploadAudit(entry, logFn = console.warn) {
|
|
|
135
219
|
}
|
|
136
220
|
|
|
137
221
|
// packages/desktop-chrome-connector/chromeConnector.ts
|
|
222
|
+
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
223
|
+
import { resolve as resolve2 } from "node:path";
|
|
138
224
|
var NOLO_CHROME_CONNECTOR_EXTENSION_ID = "ahpdoopadkamnglhlacfjdfnonpjdplg";
|
|
225
|
+
var NOLO_FIREFOX_CONNECTOR_EXTENSION_ID = "nolo-browser-connector@nolo.chat";
|
|
226
|
+
var NOLO_CONNECTOR_EXTENSION_IDS = [
|
|
227
|
+
NOLO_CHROME_CONNECTOR_EXTENSION_ID,
|
|
228
|
+
NOLO_FIREFOX_CONNECTOR_EXTENSION_ID
|
|
229
|
+
];
|
|
139
230
|
var NOLO_CHROME_CONNECTOR_PROTOCOL_VERSION = "2";
|
|
231
|
+
var NOLO_CHROME_CONNECTOR_DEFAULT_PORTS = {
|
|
232
|
+
chrome: 38947,
|
|
233
|
+
firefox: 38948
|
|
234
|
+
};
|
|
235
|
+
var CONNECTOR_BROWSER_EXTENSION_IDS = {
|
|
236
|
+
chrome: NOLO_CHROME_CONNECTOR_EXTENSION_ID,
|
|
237
|
+
firefox: NOLO_FIREFOX_CONNECTOR_EXTENSION_ID
|
|
238
|
+
};
|
|
239
|
+
function connectorEndpointForBrowser(browser, env = process.env) {
|
|
240
|
+
const explicitUrl = env.NOLO_CHROME_CONNECTOR_RPC_URL;
|
|
241
|
+
if (explicitUrl) return explicitUrl;
|
|
242
|
+
const port = browser === "firefox" ? env.NOLO_FIREFOX_CONNECTOR_PORT : env.NOLO_CHROME_CONNECTOR_PORT;
|
|
243
|
+
return `http://127.0.0.1:${port || NOLO_CHROME_CONNECTOR_DEFAULT_PORTS[browser]}/rpc`;
|
|
244
|
+
}
|
|
140
245
|
function defaultTokenPath() {
|
|
141
246
|
return resolve2(
|
|
142
247
|
process.env.HOME || "",
|
|
@@ -149,6 +254,18 @@ function readConnectorToken(tokenPath = defaultTokenPath()) {
|
|
|
149
254
|
return readFileSync(tokenPath, "utf8").trim();
|
|
150
255
|
}
|
|
151
256
|
var CHROME_TOOL_ACTIONS = {
|
|
257
|
+
browser_list_tabs: "list_tabs",
|
|
258
|
+
browser_open_tab: "open_tab",
|
|
259
|
+
browser_close_tab: "close_tab",
|
|
260
|
+
browser_read_page: "read_page",
|
|
261
|
+
browser_click_element: "click",
|
|
262
|
+
browser_type: "type",
|
|
263
|
+
browser_press: "press",
|
|
264
|
+
browser_scroll: "scroll",
|
|
265
|
+
browser_screenshot: "screenshot",
|
|
266
|
+
browser_read_console: "read_console",
|
|
267
|
+
browser_read_network: "read_network",
|
|
268
|
+
// Legacy aliases (kept for existing agents/tests).
|
|
152
269
|
chrome_list_tabs: "list_tabs",
|
|
153
270
|
chrome_open_tab: "open_tab",
|
|
154
271
|
chrome_close_tab: "close_tab",
|
|
@@ -164,6 +281,12 @@ var CHROME_TOOL_ACTIONS = {
|
|
|
164
281
|
chrome_upload_file: "set_files",
|
|
165
282
|
chrome_upload: "set_files"
|
|
166
283
|
};
|
|
284
|
+
for (const legacyName of ["chrome_set_files", "chrome_upload_file", "chrome_upload"]) {
|
|
285
|
+
const action = CHROME_TOOL_ACTIONS[legacyName];
|
|
286
|
+
if (action) {
|
|
287
|
+
CHROME_TOOL_ACTIONS[`browser_${legacyName.slice("chrome_".length)}`] = action;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
167
290
|
function createConnectorError(code, message, details) {
|
|
168
291
|
const error = new Error(message);
|
|
169
292
|
error.code = code;
|
|
@@ -183,9 +306,13 @@ function parseArguments(raw) {
|
|
|
183
306
|
}
|
|
184
307
|
}
|
|
185
308
|
function errorPayload(error) {
|
|
309
|
+
const code = error?.code ?? "CHROME_CONNECTOR_ERROR";
|
|
186
310
|
return {
|
|
187
|
-
code
|
|
311
|
+
code,
|
|
188
312
|
message: toErrorMessage(error),
|
|
313
|
+
...code === "CHROME_CONNECTOR_UNAVAILABLE" ? {
|
|
314
|
+
hint: "The Nolo Browser Connector is not reachable. It runs inside the user's own Chrome or Firefox \u2014 ask the user to open their browser with the Nolo Browser Connector extension enabled, or install it from https://nolo.chat/downloads (Firefox can install the signed .xpi directly), then retry."
|
|
315
|
+
} : {},
|
|
189
316
|
...error?.details !== void 0 ? { details: error.details } : {}
|
|
190
317
|
};
|
|
191
318
|
}
|
|
@@ -198,7 +325,7 @@ function validateChromeConnectorPayload(action, payload) {
|
|
|
198
325
|
if (!tabId) {
|
|
199
326
|
throw createConnectorError(
|
|
200
327
|
"TAB_ID_REQUIRED",
|
|
201
|
-
`Provide the tabId from
|
|
328
|
+
`Provide the tabId from browser_list_tabs before calling ${action}.`
|
|
202
329
|
);
|
|
203
330
|
}
|
|
204
331
|
if (!TARGET_REQUIRED_ACTIONS.has(action)) return;
|
|
@@ -210,7 +337,7 @@ function validateChromeConnectorPayload(action, payload) {
|
|
|
210
337
|
if (!elementRef && !selector) {
|
|
211
338
|
throw createConnectorError(
|
|
212
339
|
"ELEMENT_TARGET_REQUIRED",
|
|
213
|
-
"Provide elementRef from
|
|
340
|
+
"Provide elementRef from browser_read_page or a CSS selector."
|
|
214
341
|
);
|
|
215
342
|
}
|
|
216
343
|
if (action === "set_files") {
|
|
@@ -240,8 +367,8 @@ function validateChromeConnectorPayload(action, payload) {
|
|
|
240
367
|
}
|
|
241
368
|
function createChromeConnectorClient(args) {
|
|
242
369
|
if (args?.request) return { request: args.request };
|
|
243
|
-
const
|
|
244
|
-
const endpoint = args?.endpoint ??
|
|
370
|
+
const browser = args?.browser ?? "chrome";
|
|
371
|
+
const endpoint = args?.endpoint ?? connectorEndpointForBrowser(browser);
|
|
245
372
|
const fetchImpl = args?.fetchImpl ?? fetch;
|
|
246
373
|
const token = args?.token ?? readConnectorToken(args?.tokenPath);
|
|
247
374
|
return {
|
|
@@ -285,7 +412,10 @@ var REQUIRED_CHROME_CONNECTOR_FEATURES = {
|
|
|
285
412
|
type: ["compact_observation_v2", "action_gate"],
|
|
286
413
|
press: ["compact_observation_v2", "action_gate"],
|
|
287
414
|
scroll: ["compact_observation_v2"],
|
|
288
|
-
screenshot:
|
|
415
|
+
// Both browsers advertise the dedicated `screenshot` feature: Chrome serves it through
|
|
416
|
+
// Page.captureScreenshot (browser_debug-adjacent) while Firefox falls back to
|
|
417
|
+
// tabs.captureVisibleTab, so gating on browser_debug would wrongly refuse Firefox.
|
|
418
|
+
screenshot: ["screenshot"],
|
|
289
419
|
read_console: ["browser_debug"],
|
|
290
420
|
read_network: ["browser_debug"],
|
|
291
421
|
detach: ["browser_debug"],
|
|
@@ -294,19 +424,43 @@ var REQUIRED_CHROME_CONNECTOR_FEATURES = {
|
|
|
294
424
|
function requiredFeaturesForConnectorAction(action) {
|
|
295
425
|
return [...REQUIRED_CHROME_CONNECTOR_FEATURES[action] ?? []];
|
|
296
426
|
}
|
|
427
|
+
function createChromeConnectorClientResolver(args) {
|
|
428
|
+
const cache = /* @__PURE__ */ new Map();
|
|
429
|
+
const overrides = args?.clients;
|
|
430
|
+
const resolve3 = (selector) => {
|
|
431
|
+
const existing = cache.get(selector);
|
|
432
|
+
if (existing) return existing;
|
|
433
|
+
let client;
|
|
434
|
+
if (selector === "chrome" || selector === "firefox") {
|
|
435
|
+
const inner = overrides?.[selector] ?? createChromeConnectorClient({ browser: selector });
|
|
436
|
+
client = createVerifiedChromeConnectorClient({
|
|
437
|
+
client: inner,
|
|
438
|
+
expectedBrowser: selector
|
|
439
|
+
});
|
|
440
|
+
} else {
|
|
441
|
+
client = overrides?.default ?? createVerifiedChromeConnectorClient({ client: createChromeConnectorClient() });
|
|
442
|
+
}
|
|
443
|
+
cache.set(selector, client);
|
|
444
|
+
return client;
|
|
445
|
+
};
|
|
446
|
+
return resolve3;
|
|
447
|
+
}
|
|
297
448
|
function createVerifiedChromeConnectorClient(args) {
|
|
298
449
|
const client = args?.client ?? createChromeConnectorClient();
|
|
299
|
-
const
|
|
450
|
+
const expectedExtensionIds = new Set(
|
|
451
|
+
args?.expectedExtensionIds ?? (args?.expectedBrowser ? [CONNECTOR_BROWSER_EXTENSION_IDS[args.expectedBrowser]] : args?.expectedExtensionId ? [args.expectedExtensionId] : NOLO_CONNECTOR_EXTENSION_IDS)
|
|
452
|
+
);
|
|
300
453
|
let verified = null;
|
|
301
454
|
let negotiatedFeatures = [];
|
|
302
455
|
const verify = async () => {
|
|
303
456
|
const connectorInfo = await client.request("connector_info", {});
|
|
304
457
|
const receivedExtensionId = connectorInfo?.extensionId;
|
|
305
|
-
if (receivedExtensionId !==
|
|
458
|
+
if (typeof receivedExtensionId !== "string" || !expectedExtensionIds.has(receivedExtensionId)) {
|
|
459
|
+
const expectedList = [...expectedExtensionIds].join(", ");
|
|
306
460
|
throw createConnectorError(
|
|
307
461
|
"CHROME_CONNECTOR_EXTENSION_MISMATCH",
|
|
308
|
-
`Chrome connector extension id mismatch: expected ${
|
|
309
|
-
{
|
|
462
|
+
`Chrome connector extension id mismatch: expected one of ${expectedList}, received ${typeof receivedExtensionId === "string" ? receivedExtensionId : "unknown"}.`,
|
|
463
|
+
{ expectedExtensionIds: [...expectedExtensionIds], receivedExtensionId }
|
|
310
464
|
);
|
|
311
465
|
}
|
|
312
466
|
const receivedProtocolVersion = connectorInfo?.protocolVersion;
|
|
@@ -366,9 +520,21 @@ async function executeChromeConnectorTool(args) {
|
|
|
366
520
|
};
|
|
367
521
|
}
|
|
368
522
|
try {
|
|
369
|
-
const payload = parseArguments(args.call.arguments);
|
|
523
|
+
const { target: rawTarget, ...payload } = parseArguments(args.call.arguments);
|
|
524
|
+
const target = typeof rawTarget === "string" && rawTarget.trim().length > 0 ? rawTarget.trim().toLowerCase() : void 0;
|
|
525
|
+
if (target !== void 0 && target !== "chrome" && target !== "firefox") {
|
|
526
|
+
throw createConnectorError(
|
|
527
|
+
"INVALID_BROWSER_TARGET",
|
|
528
|
+
`browser target must be "chrome" or "firefox", received "${rawTarget}".`,
|
|
529
|
+
{ receivedTarget: rawTarget }
|
|
530
|
+
);
|
|
531
|
+
}
|
|
370
532
|
validateChromeConnectorPayload(action, payload);
|
|
371
|
-
const
|
|
533
|
+
const client = args.clientForTarget?.(target) ?? (target ? createVerifiedChromeConnectorClient({
|
|
534
|
+
client: createChromeConnectorClient({ browser: target }),
|
|
535
|
+
expectedBrowser: target
|
|
536
|
+
}) : args.client ?? createVerifiedChromeConnectorClient({ client: createChromeConnectorClient() }));
|
|
537
|
+
const result = await client.request(action, payload);
|
|
372
538
|
return {
|
|
373
539
|
content: JSON.stringify({ ok: true, result }),
|
|
374
540
|
metadata: {
|
|
@@ -391,10 +557,14 @@ async function executeChromeConnectorTool(args) {
|
|
|
391
557
|
var CHROME_CONNECTOR_TOOL_ACTIONS = { ...CHROME_TOOL_ACTIONS };
|
|
392
558
|
|
|
393
559
|
export {
|
|
560
|
+
resolveUploadRoots,
|
|
394
561
|
NOLO_CHROME_CONNECTOR_EXTENSION_ID,
|
|
562
|
+
NOLO_FIREFOX_CONNECTOR_EXTENSION_ID,
|
|
563
|
+
NOLO_CONNECTOR_EXTENSION_IDS,
|
|
395
564
|
NOLO_CHROME_CONNECTOR_PROTOCOL_VERSION,
|
|
396
565
|
createChromeConnectorClient,
|
|
397
566
|
REQUIRED_CHROME_CONNECTOR_FEATURES,
|
|
567
|
+
createChromeConnectorClientResolver,
|
|
398
568
|
createVerifiedChromeConnectorClient,
|
|
399
569
|
executeChromeConnectorTool
|
|
400
570
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// packages/agent-runtime/sseFrames.ts
|
|
2
|
+
async function* readSseFrames(response) {
|
|
3
|
+
const reader = response.body?.getReader();
|
|
4
|
+
if (!reader) {
|
|
5
|
+
throw new Error("SSE response did not include a readable body.");
|
|
6
|
+
}
|
|
7
|
+
const decoder = new TextDecoder();
|
|
8
|
+
let buffer = "";
|
|
9
|
+
while (true) {
|
|
10
|
+
const { done, value } = await reader.read();
|
|
11
|
+
if (done) break;
|
|
12
|
+
buffer += decoder.decode(value, { stream: true });
|
|
13
|
+
let boundary = findSseFrameBoundary(buffer);
|
|
14
|
+
while (boundary) {
|
|
15
|
+
yield buffer.slice(0, boundary.index);
|
|
16
|
+
buffer = buffer.slice(boundary.index + boundary.separatorLength);
|
|
17
|
+
boundary = findSseFrameBoundary(buffer);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const remaining = decoder.decode();
|
|
21
|
+
if (remaining) {
|
|
22
|
+
buffer += remaining;
|
|
23
|
+
let boundary = findSseFrameBoundary(buffer);
|
|
24
|
+
while (boundary) {
|
|
25
|
+
yield buffer.slice(0, boundary.index);
|
|
26
|
+
buffer = buffer.slice(boundary.index + boundary.separatorLength);
|
|
27
|
+
boundary = findSseFrameBoundary(buffer);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (buffer.trim()) yield buffer;
|
|
31
|
+
}
|
|
32
|
+
function findSseFrameBoundary(buffer) {
|
|
33
|
+
const lfLf = buffer.indexOf("\n\n");
|
|
34
|
+
const crLfCrLf = buffer.indexOf("\r\n\r\n");
|
|
35
|
+
if (lfLf === -1 && crLfCrLf === -1) return null;
|
|
36
|
+
const useLf = lfLf !== -1 && (crLfCrLf === -1 || lfLf < crLfCrLf);
|
|
37
|
+
return useLf ? { index: lfLf, separatorLength: 2 } : { index: crLfCrLf, separatorLength: 4 };
|
|
38
|
+
}
|
|
39
|
+
async function* streamSseDataValues(response, parse) {
|
|
40
|
+
const reader = response.body?.getReader();
|
|
41
|
+
if (!reader) return;
|
|
42
|
+
const decoder = new TextDecoder();
|
|
43
|
+
let buffer = "";
|
|
44
|
+
while (true) {
|
|
45
|
+
const { done, value } = await reader.read();
|
|
46
|
+
if (done) break;
|
|
47
|
+
buffer += decoder.decode(value, { stream: true });
|
|
48
|
+
const lines = buffer.split("\n");
|
|
49
|
+
buffer = lines.pop() ?? "";
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
const parsed = parse(line);
|
|
52
|
+
if (parsed) yield parsed;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const remaining = decoder.decode();
|
|
56
|
+
if (remaining) {
|
|
57
|
+
buffer += remaining;
|
|
58
|
+
const lines = buffer.split("\n");
|
|
59
|
+
buffer = lines.pop() ?? "";
|
|
60
|
+
for (const line of lines) {
|
|
61
|
+
const parsed = parse(line);
|
|
62
|
+
if (parsed) yield parsed;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (buffer.trim()) {
|
|
66
|
+
const parsed = parse(buffer);
|
|
67
|
+
if (parsed) yield parsed;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function readSseDataValues(response, parse) {
|
|
71
|
+
const values = [];
|
|
72
|
+
for await (const value of streamSseDataValues(response, parse)) {
|
|
73
|
+
values.push(value);
|
|
74
|
+
}
|
|
75
|
+
return values;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
readSseFrames,
|
|
80
|
+
streamSseDataValues,
|
|
81
|
+
readSseDataValues
|
|
82
|
+
};
|