nolo-cli 0.107.0-alpha.4 → 0.107.1

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.
Files changed (211) hide show
  1. package/README.md +1 -1
  2. package/{_executeModel-UDCSOTD2.js → _executeModel-M573MKVE.js} +78 -70
  3. package/action-GVA5ARSJ.js +20 -0
  4. package/{addContentAction-MB2HHMDZ.js → addContentAction-M2WOWZCL.js} +13 -12
  5. package/{addDialogAgentAction-MCEABSBA.js → addDialogAgentAction-QMAQ5Z6N.js} +19 -20
  6. package/{agentDeleteCommand-OWYHN6D6.js → agentDeleteCommand-ZFHYRHBS.js} +118 -43
  7. package/{agentEmailCommands-AU5I4M4W.js → agentEmailCommands-X6AVPIVQ.js} +100 -90
  8. package/agentListCommands-PAD2CI2I.js +741 -0
  9. package/{agentMachineCommands-YMNME2L6.js → agentMachineCommands-UPH6RJCC.js} +50 -46
  10. package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-CMVTBY5X.js} +97 -2
  11. package/{agentPullCommand-O5MPVJ5E.js → agentPullCommand-B4T2DJ5H.js} +1 -1
  12. package/agentRecordCommands-UMACPRAF.js +138 -0
  13. package/agentRunCommand-H6KKHHMU.js +167 -0
  14. package/{agentRunControl-AVJR4JW4.js → agentRunControl-3HWA2LLQ.js} +2 -2
  15. package/{agentRuntimeLocal-KCMC2TBD.js → agentRuntimeLocal-N4YGKL7M.js} +44 -40
  16. package/{agentSlice-R7PR6KYM.js → agentSlice-2LPP43XH.js} +15 -14
  17. package/{appDeleteCommands-JEPA3EWE.js → appDeleteCommands-7DAF33AM.js} +46 -42
  18. package/{appDeployCommands-UTB76XFM.js → appDeployCommands-ZPZSMFGZ.js} +46 -42
  19. package/{appDeployStatusCommands-LGHF2SBD.js → appDeployStatusCommands-FWBDSSS5.js} +46 -42
  20. package/{appGetCommands-PX2BFHOB.js → appGetCommands-SZZOHGEP.js} +46 -42
  21. package/{appListCommands-BSMPTWKC.js → appListCommands-FPMUBDPM.js} +46 -42
  22. package/{authCommand-YW42YZA4.js → authCommand-VL3G26NQ.js} +119 -25
  23. package/{authCommands-RGOGCPP6.js → authCommands-5RTUDYZW.js} +7 -5
  24. package/{builtinSkillRegistry-FUAVTRVZ.js → builtinSkillRegistry-ZK4K67Y5.js} +11 -9
  25. package/{chromeCommands-FZYAU75D.js → chromeCommands-AU5ZJXBG.js} +289 -37
  26. package/{chromeOpsCommands-62P2Q2YB.js → chromeOpsCommands-ZYTCMNHG.js} +156 -22
  27. package/{chunk-JEDZAO7L.js → chunk-2SYTUTLI.js} +257 -37
  28. package/{chunk-HVURBGF3.js → chunk-2U3NHADM.js} +6 -6
  29. package/{chunk-QTGQ2LTL.js → chunk-3DQY5IFB.js} +6 -10
  30. package/{chunk-XT35TTFG.js → chunk-3IXAHOJS.js} +19 -21
  31. package/{chunk-UVA7OYO3.js → chunk-3W67RV75.js} +29 -9
  32. package/chunk-4LCOCOR5.js +50 -0
  33. package/{chunk-JPGCXHNM.js → chunk-4LKMZ3RR.js} +1 -1
  34. package/{chunk-2GRGFCF6.js → chunk-4VJAC32I.js} +2 -1
  35. package/{chunk-6D6VBVEW.js → chunk-4W24JM32.js} +80 -14
  36. package/{chunk-MC4XLIJ7.js → chunk-523DITKR.js} +1 -1
  37. package/{chunk-E4MARS3Q.js → chunk-5GVBDNTO.js} +1 -1
  38. package/{chunk-C3M4465B.js → chunk-5HYJ3DSZ.js} +404 -659
  39. package/chunk-5MMAK75Q.js +15 -0
  40. package/{chunk-7S4YWN7P.js → chunk-5UUIGN6I.js} +4 -4
  41. package/{chunk-42V6BK2E.js → chunk-62IL3KQV.js} +4 -34
  42. package/{chunk-4MK3I7Y4.js → chunk-6MAW4XOF.js} +5 -5
  43. package/{chunk-3UZPUAES.js → chunk-74PPKIY2.js} +1 -1
  44. package/chunk-76HO2DP6.js +15 -0
  45. package/{chunk-ASIFZ2WY.js → chunk-7BBP7ZX3.js} +66 -54
  46. package/{chunk-VLTIYV3X.js → chunk-7I25CBT5.js} +34 -8
  47. package/{chunk-IBOZNTG2.js → chunk-7X5XZ34C.js} +23 -28
  48. package/chunk-AGIM7IMJ.js +147 -0
  49. package/{chunk-5UTFL4QJ.js → chunk-APO5TOXO.js} +1 -1
  50. package/{chunk-EEGDMATE.js → chunk-AZOVPTL6.js} +91 -81
  51. package/{chunk-6OZ36FXI.js → chunk-BIPGGSJS.js} +22 -4
  52. package/{chunk-EYAQT56M.js → chunk-BNQMNUKZ.js} +9 -6
  53. package/{chunk-62CATUYY.js → chunk-CBUMFIFE.js} +834 -962
  54. package/{chunk-OIVSQH2O.js → chunk-CDEEFJXN.js} +308 -11
  55. package/chunk-CHOZJMJS.js +78 -0
  56. package/{chunk-ETI2NYVF.js → chunk-CIP3AAMT.js} +4 -4
  57. package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
  58. package/{chunk-W7HLWAQ7.js → chunk-DE45KZNH.js} +118 -90
  59. package/{chunk-Q554LLSI.js → chunk-DMXLXZKL.js} +1 -1
  60. package/{chunk-3VNWWVKB.js → chunk-E3YWHWCR.js} +50 -18
  61. package/{chunk-HKNXJGEC.js → chunk-ECFHBYUW.js} +85 -50
  62. package/{chunk-ACTMNVHM.js → chunk-EHSYSKXV.js} +1 -1
  63. package/{chunk-WV42OMV7.js → chunk-ELUDRSRD.js} +8 -8
  64. package/{chunk-ABQYVJBJ.js → chunk-EV235ILT.js} +5 -5
  65. package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
  66. package/{chunk-BFDFRLLQ.js → chunk-EZ4VZHAG.js} +5 -5
  67. package/{chunk-GO3Z72MT.js → chunk-FHLMQIU7.js} +65 -95
  68. package/{chunk-2F7RJC6L.js → chunk-FOXQ7BAB.js} +1 -1
  69. package/{chunk-SH43IESU.js → chunk-GGC55Q32.js} +199 -29
  70. package/chunk-GMZLP5DV.js +82 -0
  71. package/{chunk-FDTR4QJ6.js → chunk-H6A6X4EK.js} +32 -1
  72. package/{chunk-DVINR3PL.js → chunk-HDLLCBRF.js} +1 -1
  73. package/{chunk-QOKAKDPE.js → chunk-HIM3FCLF.js} +0 -1
  74. package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
  75. package/{chunk-BNGW5ASC.js → chunk-I2RGRVQ7.js} +22 -2
  76. package/{chunk-O6OSWFZQ.js → chunk-IHPDK6UD.js} +6 -0
  77. package/{chunk-QDSINZM3.js → chunk-IXH3HKY2.js} +1 -22
  78. package/{chunk-GQBOR3G6.js → chunk-JBKHQOYK.js} +8 -4
  79. package/{chunk-XD2MJFUG.js → chunk-JEFXP73H.js} +1 -1
  80. package/{chunk-PBA4UJBK.js → chunk-JIXGJTBU.js} +4 -4
  81. package/{chunk-AEOE4Z6Q.js → chunk-K6L5PNXK.js} +39 -15
  82. package/{chunk-Z77CRGTW.js → chunk-KA5O5KQL.js} +1 -1
  83. package/{chunk-GPCZ7UXG.js → chunk-KD6D6BLA.js} +1 -1
  84. package/{chunk-4CR5I7BD.js → chunk-KFWDYYSS.js} +47 -67
  85. package/{chunk-UZGQNTVW.js → chunk-KHKTDMYG.js} +8 -6
  86. package/{chunk-JDPFV2JV.js → chunk-KWUKOQM2.js} +20 -11
  87. package/{chunk-MRIHM22T.js → chunk-LBFL6RZG.js} +58 -9
  88. package/{chunk-LS2ZANRJ.js → chunk-LOCNXNOU.js} +1 -1
  89. package/{chunk-DHDMC6FO.js → chunk-LUBFABMJ.js} +15 -14
  90. package/{chunk-NA35QHCF.js → chunk-LVBFKW65.js} +1 -1
  91. package/chunk-LWLNLZC5.js +265 -0
  92. package/chunk-N4NGJDT6.js +929 -0
  93. package/{chunk-BFU6C242.js → chunk-NMFV26UG.js} +1 -1
  94. package/{chunk-FZGV4FGK.js → chunk-NUHHBEJC.js} +378 -187
  95. package/chunk-NWENLDMM.js +42 -0
  96. package/chunk-O7SVKKLY.js +875 -0
  97. package/chunk-OCZKATRC.js +129 -0
  98. package/{chunk-6Z7MY3V7.js → chunk-OEJLGVBL.js} +5 -5
  99. package/{chunk-VMFTFOWF.js → chunk-OKGVNZTL.js} +35 -8
  100. package/{chunk-GEPUP7OO.js → chunk-OR2UWD6X.js} +3 -3
  101. package/{chunk-KQHGZWSV.js → chunk-OXME3PEE.js} +1 -1
  102. package/{chunk-J4MOO56S.js → chunk-PNXHPLRU.js} +10 -2
  103. package/{chunk-3BMYXEUW.js → chunk-R5AJODNI.js} +1 -1
  104. package/{chunk-P5EVSOPA.js → chunk-R6EBQEQE.js} +22 -29
  105. package/chunk-RQ6CTX2E.js +164 -0
  106. package/{chunk-MS7TSPZR.js → chunk-RU36ZYSG.js} +19 -17
  107. package/{chunk-ALXHV7NK.js → chunk-RWXLPUKI.js} +40 -4
  108. package/{chunk-KQ4ONNQD.js → chunk-RXA3HAVW.js} +190 -8
  109. package/{chunk-IIVGDG4I.js → chunk-SJKULPGX.js} +13 -7
  110. package/{chunk-Q67DOFOO.js → chunk-SZC4REES.js} +212 -105
  111. package/{chunk-JRQFUXY7.js → chunk-TBAXFWOS.js} +99 -22
  112. package/{chunk-PQFHGD77.js → chunk-TBM2RS3U.js} +161 -14
  113. package/{chunk-NOF3HDSN.js → chunk-TFOIJFCM.js} +11 -9
  114. package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
  115. package/chunk-TY3TIUJK.js +89 -0
  116. package/{chunk-I3TQJXQ7.js → chunk-U3C3IA32.js} +9 -2
  117. package/{chunk-YYLHWIW6.js → chunk-UKZX3NHN.js} +1 -1
  118. package/chunk-UM7TA3K4.js +1008 -0
  119. package/{chunk-6YTOJY35.js → chunk-VBG7GWWR.js} +253 -8
  120. package/{chunk-GL3EHUR4.js → chunk-VHGYUYQ3.js} +69 -47
  121. package/chunk-VIWDGTDA.js +8 -0
  122. package/chunk-VJVNU77E.js +83 -0
  123. package/chunk-VM6IE2GN.js +8004 -0
  124. package/{chunk-UKWGR5SS.js → chunk-VY6VFGKR.js} +194 -1144
  125. package/chunk-VZLO4XJD.js +17 -0
  126. package/chunk-W32HPLTL.js +13692 -0
  127. package/{chunk-AHAHBQMU.js → chunk-WDLSZMTA.js} +2 -2
  128. package/{chunk-53HEEOTT.js → chunk-WF5X57VW.js} +83 -16
  129. package/{chunk-VRTTFDBM.js → chunk-WPHY3VPF.js} +35 -22
  130. package/{chunk-3L2WKC3W.js → chunk-XPWGOTBQ.js} +8 -1
  131. package/chunk-YV25TM3R.js +780 -0
  132. package/chunk-ZRAU6T47.js +56 -0
  133. package/{chunk-IBOOZVVD.js → chunk-ZTKZZY2A.js} +851 -279
  134. package/commandRegistry-ASW6IVZ3.js +833 -0
  135. package/{contentThunks-IV2T3EJC.js → contentThunks-4XNVOIR7.js} +39 -36
  136. package/{cooldownCommands-REAWYVTY.js → cooldownCommands-ZLEPIB4A.js} +2 -2
  137. package/{createAgentAutomationAction-JCOIEYY4.js → createAgentAutomationAction-NHHTCJMC.js} +40 -37
  138. package/createDialogAction-XEBTHDB3.js +70 -0
  139. package/{createPageAction-D2VOOLP3.js → createPageAction-VR3WW2AQ.js} +47 -43
  140. package/{chunk-FG3HKPQP.js → cursorProvider-YGGNMVWX.js} +2751 -10185
  141. package/{dbSlice-A6C6H32X.js → dbSlice-TG4MZ5EB.js} +12 -11
  142. package/{deleteFile-YG6QMJLU.js → deleteFile-KESP65GC.js} +7 -6
  143. package/{dialogCommands-H7FPUYUQ.js → dialogCommands-FJWQG3MX.js} +50 -47
  144. package/{dialogSlice-6JZOOTDS.js → dialogSlice-GVRDGCRG.js} +57 -37
  145. package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
  146. package/{docCreateCommands-WRG2JLGM.js → docCreateCommands-AZSK4NAG.js} +48 -44
  147. package/{docDeleteCommands-SHWJIBJS.js → docDeleteCommands-DDJMSMFZ.js} +49 -45
  148. package/{docReadCommands-WJN3WT6O.js → docReadCommands-5F5Q6EBZ.js} +47 -43
  149. package/{docStore-HUPQ2FSS.js → docStore-SUZUUWDI.js} +17 -13
  150. package/{docUpdateCommands-IE32IL6O.js → docUpdateCommands-XPNPVZOC.js} +48 -44
  151. package/{fetchMessages-EIU7UFFK.js → fetchMessages-3PXAHKCR.js} +5 -5
  152. package/{getPricing-LUSEABA6.js → getPricing-DOBBZLOK.js} +4 -4
  153. package/{handleSendMessageAction-DFPMQ7YM.js → handleSendMessageAction-VC6VTFKS.js} +109 -42
  154. package/index.js +87 -884
  155. package/{lib-FRRS27KN.js → lib-PU2G2MSO.js} +523 -191
  156. package/{localDialogRead-BTFJ4V2I.js → localDialogRead-UYCKO7YZ.js} +2 -2
  157. package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-TU6OBC76.js} +9 -6
  158. package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-VKWVOPPI.js} +1 -1
  159. package/{machineCommands-M2T2I5NF.js → machineCommands-M634V2L3.js} +98 -89
  160. package/machineWsRunDispatch-Z3HUSTFI.js +154 -0
  161. package/{memberThunks-P2ECUJ56.js → memberThunks-5S5D3N4U.js} +20 -18
  162. package/{models-T3SG6MJ5.js → models-PQU25T6Q.js} +2 -2
  163. package/oauthTokenStore-ITEB663N.js +23 -0
  164. package/package.json +1 -1
  165. package/processSpawn-SOAV3FEV.js +11 -0
  166. package/profileConfig-ZGOFORWV.js +43 -0
  167. package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-HAQWVAQX.js} +7 -7
  168. package/{providerRegistry-757OWH3O.js → providerRegistry-5FGWB3X5.js} +11 -7
  169. package/{read-COE3ZYR6.js → read-LSYFLSIM.js} +8 -7
  170. package/{readDocTool-5USN4A6V.js → readDocTool-XWRXV3DR.js} +5 -3
  171. package/{readlineWorkspace-XQRDGWRZ.js → readlineWorkspace-J3YD3DNW.js} +2596 -2032
  172. package/{removeDialogAgentAction-J6X5QMTA.js → removeDialogAgentAction-4TEFC3VL.js} +22 -26
  173. package/{runAgentClientLoop-5ZA62FBA.js → runAgentClientLoop-APSMCLAF.js} +79 -72
  174. package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-PIVSBZRZ.js} +4 -4
  175. package/runtimeModeArgs-2Y7BALTO.js +31 -0
  176. package/{setDialogExtraReferencesAction-WX5VTY6O.js → setDialogExtraReferencesAction-LSEN44OY.js} +16 -14
  177. package/{setPrimaryDialogAgentAction-FN22THHT.js → setPrimaryDialogAgentAction-SR366X5A.js} +23 -27
  178. package/{chunk-GP5LKBUZ.js → settingThunks-CTVPPGIN.js} +226 -940
  179. package/{skillDiscovery-CYUCJMAG.js → skillDiscovery-ZBU76COE.js} +3 -3
  180. package/{slateUtils-RIZES3PV.js → slateUtils-NGV2NMKM.js} +1 -1
  181. package/{spaceCommands-5GLCWZPO.js → spaceCommands-3UK63WPE.js} +51 -47
  182. package/{streamAgentChatTurn-6UZJMYRB.js → streamAgentChatTurn-DNY2PSRW.js} +215 -115
  183. package/{switchDialogAgentAction-LVTEV3FR.js → switchDialogAgentAction-M6NAFOOU.js} +19 -20
  184. package/{tableCommands-O6NWHFKV.js → tableCommands-6U4BMLRR.js} +10 -10
  185. package/{toolApiClient-QVJ6HDNN.js → toolApiClient-AD7CXTA4.js} +4 -3
  186. package/tools-X5UWATZK.js +117 -0
  187. package/{tuiSummaryLlmCaller-OHHFTHMG.js → tuiSummaryLlmCaller-DEH7ZEM6.js} +25 -23
  188. package/{updateCommands-2M74UL7P.js → updateCommands-4EHDLF5J.js} +3 -3
  189. package/{updateDialogTitleAction-QTKNIURB.js → updateDialogTitleAction-YSY5BF5A.js} +84 -45
  190. package/action-P4TNFGAD.js +0 -31
  191. package/agentListCommands-B2V4YAC4.js +0 -410
  192. package/agentRecordCommands-G4KK4R7H.js +0 -128
  193. package/agentRunCommand-UTZJA23G.js +0 -156
  194. package/browser-image-compression-MFDTD7K6.js +0 -1763
  195. package/chatQueueReduxAdapter-2P6NFX64.js +0 -186
  196. package/chunk-CQ3WA2NE.js +0 -299
  197. package/chunk-M76ECQRD.js +0 -13658
  198. package/chunk-MEYIRKDN.js +0 -8967
  199. package/chunk-PUOC4YRO.js +0 -394
  200. package/chunk-Q5FJJ6XI.js +0 -103
  201. package/chunk-S7Z2HMCN.js +0 -25
  202. package/chunk-T75QD6AB.js +0 -20923
  203. package/chunk-Y5GCAMGP.js +0 -9
  204. package/chunk-YPREESF4.js +0 -225
  205. package/createDialogAction-NGG7YVNU.js +0 -65
  206. package/machineWsRunDispatch-ISBKOOD7.js +0 -144
  207. package/settingSlice-P4ZW7K5X.js +0 -204
  208. package/syncMapping-N6RGXGBW.js +0 -437
  209. package/tools-KMGFWO43.js +0 -110
  210. package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
  211. package/{db-WK5MDZVN.js → db-VQSAOWAO.js} +1 -1
@@ -1,6 +1,7 @@
1
1
  import {
2
- createChromeConnectorClient
3
- } from "./chunk-SH43IESU.js";
2
+ createChromeConnectorClient,
3
+ createVerifiedChromeConnectorClient
4
+ } from "./chunk-GGC55Q32.js";
4
5
  import {
5
6
  toErrorMessage
6
7
  } from "./chunk-HNMXYYJR.js";
@@ -23,6 +24,14 @@ function wantsHelp(args) {
23
24
  function readTrimmedOption(args, flag) {
24
25
  return (readOption(args, flag) ?? "").trim();
25
26
  }
27
+ function readBrowserFlag(args) {
28
+ const equalsForm = args.find((arg) => arg.startsWith("--browser="));
29
+ const raw = equalsForm !== void 0 ? equalsForm.slice("--browser=".length) : readOption(args, "--browser");
30
+ if (raw === void 0) return void 0;
31
+ const value = raw.trim();
32
+ if (value === "chrome" || value === "firefox") return value;
33
+ return null;
34
+ }
26
35
  function readAllOptions(args, flag) {
27
36
  const values = [];
28
37
  for (let i = 0; i < args.length; i++) {
@@ -44,6 +53,25 @@ function readIntOption(args, flag, usage) {
44
53
  }
45
54
  return value;
46
55
  }
56
+ function readNonNegativeIntOption(args, flag, usage) {
57
+ const equalsForm = args.find((arg) => arg.startsWith(`${flag}=`));
58
+ const raw = equalsForm !== void 0 ? equalsForm.slice(`${flag}=`.length) : readOption(args, flag);
59
+ if (raw === void 0) {
60
+ if (args.includes(flag)) {
61
+ throw new Error(`Invalid ${flag} <N>. Usage: ${usage}`);
62
+ }
63
+ return void 0;
64
+ }
65
+ const trimmed = raw.trim();
66
+ if (!/^\d+$/.test(trimmed)) {
67
+ throw new Error(`Invalid ${flag} <N>. Usage: ${usage}`);
68
+ }
69
+ const value = Number.parseInt(trimmed, 10);
70
+ if (!Number.isFinite(value) || value < 0) {
71
+ throw new Error(`Invalid ${flag} <N>. Usage: ${usage}`);
72
+ }
73
+ return value;
74
+ }
47
75
  function requireTabId(args, usage) {
48
76
  const tabId = readTrimmedOption(args, "--tab");
49
77
  if (!tabId) {
@@ -67,12 +95,12 @@ function requireTarget(args, usage) {
67
95
  var CHROME_OPS_SUBCOMMANDS = {
68
96
  "list-tabs": {
69
97
  action: "list_tabs",
70
- usage: "nolo chrome list-tabs",
98
+ usage: "nolo browser list-tabs",
71
99
  payload: () => ({})
72
100
  },
73
101
  "open-tab": {
74
102
  action: "open_tab",
75
- usage: "nolo chrome open-tab --url <url> [--active]",
103
+ usage: "nolo browser open-tab --url <url> [--active]",
76
104
  payload: (args, usage) => {
77
105
  const url = readTrimmedOption(args, "--url");
78
106
  if (!url) {
@@ -83,12 +111,12 @@ var CHROME_OPS_SUBCOMMANDS = {
83
111
  },
84
112
  "close-tab": {
85
113
  action: "close_tab",
86
- usage: "nolo chrome close-tab --tab <id>",
114
+ usage: "nolo browser close-tab --tab <id>",
87
115
  payload: (args, usage) => ({ tabId: requireTabId(args, usage) })
88
116
  },
89
117
  "read-page": {
90
118
  action: "read_page",
91
- usage: "nolo chrome read-page --tab <id> [--selector <css>] [--detail compact|full] [--max-elements N]",
119
+ usage: "nolo browser read-page --tab <id> [--selector <css>] [--detail compact|full] [--max-elements N] [--offset N] [--viewport]",
92
120
  payload: (args, usage) => {
93
121
  const payload = { tabId: requireTabId(args, usage) };
94
122
  const selector = readTrimmedOption(args, "--selector");
@@ -97,12 +125,15 @@ var CHROME_OPS_SUBCOMMANDS = {
97
125
  if (detail) payload.detail = detail;
98
126
  const maxElements = readIntOption(args, "--max-elements", usage);
99
127
  if (maxElements !== void 0) payload.maxElements = maxElements;
128
+ const offset = readNonNegativeIntOption(args, "--offset", usage);
129
+ if (offset !== void 0) payload.offset = offset;
130
+ if (args.includes("--viewport")) payload.viewportOnly = true;
100
131
  return payload;
101
132
  }
102
133
  },
103
134
  click: {
104
135
  action: "click",
105
- usage: "nolo chrome click --tab <id> (--ref <elementRef> | --selector <css>)",
136
+ usage: "nolo browser click --tab <id> (--ref <elementRef> | --selector <css>)",
106
137
  payload: (args, usage) => ({
107
138
  tabId: requireTabId(args, usage),
108
139
  ...requireTarget(args, usage)
@@ -110,7 +141,7 @@ var CHROME_OPS_SUBCOMMANDS = {
110
141
  },
111
142
  type: {
112
143
  action: "type",
113
- usage: "nolo chrome type --tab <id> (--ref <elementRef> | --selector <css>) --text <text> [--append]",
144
+ usage: "nolo browser type --tab <id> (--ref <elementRef> | --selector <css>) --text <text> [--append]",
114
145
  payload: (args, usage) => {
115
146
  const text = readOption(args, "--text");
116
147
  if (text === void 0 || text.startsWith("--")) {
@@ -126,7 +157,7 @@ var CHROME_OPS_SUBCOMMANDS = {
126
157
  },
127
158
  upload: {
128
159
  action: "set_files",
129
- usage: "nolo chrome upload --tab <id> (--ref <elementRef> | --selector <css>) --file <path> [--file <path>...]",
160
+ usage: "nolo browser upload --tab <id> (--ref <elementRef> | --selector <css>) --file <path> [--file <path>...]",
130
161
  payload: (args, usage) => {
131
162
  const files = readAllOptions(args, "--file");
132
163
  if (files.length === 0) {
@@ -144,7 +175,7 @@ var CHROME_OPS_SUBCOMMANDS = {
144
175
  },
145
176
  press: {
146
177
  action: "press",
147
- usage: "nolo chrome press --tab <id> --key <key>",
178
+ usage: "nolo browser press --tab <id> --key <key>",
148
179
  payload: (args, usage) => {
149
180
  const key = readTrimmedOption(args, "--key");
150
181
  if (!key) {
@@ -155,7 +186,7 @@ var CHROME_OPS_SUBCOMMANDS = {
155
186
  },
156
187
  scroll: {
157
188
  action: "scroll",
158
- usage: "nolo chrome scroll --tab <id> [--delta-x N] [--delta-y N]",
189
+ usage: "nolo browser scroll --tab <id> [--delta-x N] [--delta-y N]",
159
190
  payload: (args, usage) => {
160
191
  const payload = { tabId: requireTabId(args, usage) };
161
192
  const deltaX = readIntOption(args, "--delta-x", usage);
@@ -167,7 +198,7 @@ var CHROME_OPS_SUBCOMMANDS = {
167
198
  },
168
199
  screenshot: {
169
200
  action: "screenshot",
170
- usage: "nolo chrome screenshot --tab <id> [--out <path>] [--full-page]",
201
+ usage: "nolo browser screenshot --tab <id> [--out <path>] [--full-page]",
171
202
  payload: (args, usage) => ({
172
203
  tabId: requireTabId(args, usage),
173
204
  ...args.includes("--full-page") ? { fullPage: true } : {}
@@ -175,7 +206,7 @@ var CHROME_OPS_SUBCOMMANDS = {
175
206
  },
176
207
  "read-console": {
177
208
  action: "read_console",
178
- usage: "nolo chrome read-console --tab <id> [--limit N]",
209
+ usage: "nolo browser read-console --tab <id> [--limit N]",
179
210
  payload: (args, usage) => {
180
211
  const payload = { tabId: requireTabId(args, usage) };
181
212
  const limit = readIntOption(args, "--limit", usage);
@@ -185,7 +216,7 @@ var CHROME_OPS_SUBCOMMANDS = {
185
216
  },
186
217
  "read-network": {
187
218
  action: "read_network",
188
- usage: "nolo chrome read-network --tab <id> [--limit N] [--include-assets]",
219
+ usage: "nolo browser read-network --tab <id> [--limit N] [--include-assets]",
189
220
  payload: (args, usage) => {
190
221
  const payload = { tabId: requireTabId(args, usage) };
191
222
  const limit = readIntOption(args, "--limit", usage);
@@ -197,28 +228,59 @@ var CHROME_OPS_SUBCOMMANDS = {
197
228
  };
198
229
  function renderChromeOpsHelp() {
199
230
  const lines = [
200
- "Operate the user's Chrome through the Nolo Chrome connector (the desktop bridge;",
201
- "the same RPC the chrome_* agent tools use).",
231
+ "Operate the user's browser (Chrome or Firefox) through the Nolo Browser Connector",
232
+ "(the desktop bridge; the same RPC the browser_* agent tools use \u2014 legacy `chrome_*` names still work).",
202
233
  "",
203
234
  "Usage:",
204
- " nolo chrome <subcommand> [flags]",
235
+ " nolo browser <subcommand> [flags]",
236
+ " nolo chrome <subcommand> [flags] # compatibility alias",
205
237
  "",
206
238
  "Subcommands:",
207
239
  ...Object.values(CHROME_OPS_SUBCOMMANDS).map(
208
- (spec) => ` ${spec.usage.replace(/^nolo chrome /, "")}`
240
+ (spec) => ` ${spec.usage.replace(/^nolo browser /, "")}`
209
241
  ),
210
242
  "",
211
243
  "Notes:",
212
- " --ref takes an elementRef copied from `nolo chrome read-page` (revision-scoped,",
244
+ " --ref takes an elementRef copied from `nolo browser read-page` (revision-scoped,",
213
245
  " preferred over --selector); --selector takes a CSS selector.",
214
246
  " Actions the connector classifies as irreversible (Submit / Delete / Pay ...)",
215
247
  " are refused with CONFIRMATION_REQUIRED \u2014 ask the user to perform them.",
248
+ " read-console / read-network / upload work on Chrome only (Firefox lacks chrome.debugger).",
249
+ " --browser chrome|firefox selects which connector endpoint serves the call (default",
250
+ " auto-detects single online browser: chrome = 127.0.0.1:38947, firefox = 127.0.0.1:38948);",
251
+ " the wrong browser is refused.",
216
252
  " Every subcommand prints the connector's raw JSON result; failures exit 1.",
217
- " Endpoint: NOLO_CHROME_CONNECTOR_RPC_URL or http://127.0.0.1:38947/rpc."
253
+ " Endpoint: NOLO_CHROME_CONNECTOR_RPC_URL or per-browser NOLO_CHROME_CONNECTOR_PORT /",
254
+ " NOLO_FIREFOX_CONNECTOR_PORT (default http://127.0.0.1:38947/rpc)."
218
255
  ];
219
256
  return lines.join("\n");
220
257
  }
221
258
  var CHROME_OPS_HELP_TEXT = renderChromeOpsHelp();
259
+ async function defaultProbeBrowser(browser) {
260
+ try {
261
+ const client = createChromeConnectorClient({
262
+ browser,
263
+ fetchImpl: (input, init) => {
264
+ return fetch(input, {
265
+ ...init,
266
+ signal: AbortSignal.timeout(400)
267
+ });
268
+ }
269
+ });
270
+ const info = await client.request("connector_info", {});
271
+ return typeof info?.extensionId === "string";
272
+ } catch (error) {
273
+ if (error?.code === "CHROME_CONNECTOR_UNAVAILABLE") {
274
+ return false;
275
+ }
276
+ const handshakeError = new Error(
277
+ `\u63A2\u6D4B\u5230\u7AEF\u70B9\u4F46\u63E1\u624B\u5931\u8D25\uFF1A${toErrorMessage(error)}`
278
+ );
279
+ handshakeError.code = error?.code || "CHROME_CONNECTOR_HANDSHAKE_FAILED";
280
+ handshakeError.details = error?.details;
281
+ throw handshakeError;
282
+ }
283
+ }
222
284
  async function runChromeOpsCommand(subcommand, args, deps = {}) {
223
285
  const io = {
224
286
  stdout: (text) => console.log(text),
@@ -227,7 +289,7 @@ async function runChromeOpsCommand(subcommand, args, deps = {}) {
227
289
  };
228
290
  const spec = CHROME_OPS_SUBCOMMANDS[subcommand];
229
291
  if (!spec) {
230
- io.stderr(`Unknown chrome subcommand: ${subcommand}
292
+ io.stderr(`Unknown browser subcommand "${subcommand}".
231
293
 
232
294
  ${CHROME_OPS_HELP_TEXT}`);
233
295
  return 1;
@@ -236,6 +298,13 @@ ${CHROME_OPS_HELP_TEXT}`);
236
298
  io.stdout(CHROME_OPS_HELP_TEXT);
237
299
  return 0;
238
300
  }
301
+ const browserFlag = readBrowserFlag(args);
302
+ if (browserFlag === null) {
303
+ io.stderr(
304
+ `Invalid --browser value: expected "chrome" or "firefox". Usage: ${spec.usage}`
305
+ );
306
+ return 1;
307
+ }
239
308
  let payload;
240
309
  try {
241
310
  payload = spec.payload(args, spec.usage);
@@ -245,7 +314,72 @@ ${CHROME_OPS_HELP_TEXT}`);
245
314
  }
246
315
  let result;
247
316
  try {
248
- const client = deps.client ?? createChromeConnectorClient();
317
+ const env = deps.env ?? process.env;
318
+ let client;
319
+ if (deps.client) {
320
+ client = deps.client;
321
+ } else {
322
+ let targetBrowser = browserFlag;
323
+ if (!targetBrowser && !env.NOLO_CHROME_CONNECTOR_RPC_URL) {
324
+ const probe = deps.probeBrowser ?? defaultProbeBrowser;
325
+ const [chromeResult, firefoxResult] = await Promise.allSettled([
326
+ probe("chrome"),
327
+ probe("firefox")
328
+ ]);
329
+ const chromeOnline = chromeResult.status === "fulfilled" && chromeResult.value === true;
330
+ const firefoxOnline = firefoxResult.status === "fulfilled" && firefoxResult.value === true;
331
+ if (chromeOnline && firefoxOnline) {
332
+ const error = new Error(
333
+ "Both Chrome and Firefox connectors are online. Specify --browser chrome or --browser firefox."
334
+ );
335
+ error.code = "MULTIPLE_BROWSERS_AVAILABLE";
336
+ throw error;
337
+ }
338
+ if (chromeOnline) {
339
+ targetBrowser = "chrome";
340
+ } else if (firefoxOnline) {
341
+ targetBrowser = "firefox";
342
+ } else {
343
+ if (chromeResult.status === "rejected") {
344
+ const reason = toErrorMessage(chromeResult.reason);
345
+ const err = new Error(
346
+ reason.startsWith("\u63A2\u6D4B\u5230\u7AEF\u70B9\u4F46\u63E1\u624B\u5931\u8D25\uFF1A") ? reason : `\u63A2\u6D4B\u5230\u7AEF\u70B9\u4F46\u63E1\u624B\u5931\u8D25\uFF1A${reason}`
347
+ );
348
+ err.code = chromeResult.reason?.code || "CHROME_CONNECTOR_HANDSHAKE_FAILED";
349
+ err.details = chromeResult.reason?.details;
350
+ throw err;
351
+ }
352
+ if (firefoxResult.status === "rejected") {
353
+ const reason = toErrorMessage(firefoxResult.reason);
354
+ const err = new Error(
355
+ reason.startsWith("\u63A2\u6D4B\u5230\u7AEF\u70B9\u4F46\u63E1\u624B\u5931\u8D25\uFF1A") ? reason : `\u63A2\u6D4B\u5230\u7AEF\u70B9\u4F46\u63E1\u624B\u5931\u8D25\uFF1A${reason}`
356
+ );
357
+ err.code = firefoxResult.reason?.code || "CHROME_CONNECTOR_HANDSHAKE_FAILED";
358
+ err.details = firefoxResult.reason?.details;
359
+ throw err;
360
+ }
361
+ const chromePort = env.NOLO_CHROME_CONNECTOR_PORT || 38947;
362
+ const firefoxPort = env.NOLO_FIREFOX_CONNECTOR_PORT || 38948;
363
+ const chromeEndpoint = `http://127.0.0.1:${chromePort}/rpc`;
364
+ const firefoxEndpoint = `http://127.0.0.1:${firefoxPort}/rpc`;
365
+ const error = new Error(
366
+ `Chrome connector RPC endpoint is unavailable at ${chromeEndpoint} or ${firefoxEndpoint}.`
367
+ );
368
+ error.code = "CHROME_CONNECTOR_UNAVAILABLE";
369
+ throw error;
370
+ }
371
+ }
372
+ if (deps.createClient) {
373
+ client = deps.createClient(targetBrowser);
374
+ } else if (targetBrowser) {
375
+ client = createVerifiedChromeConnectorClient({
376
+ client: createChromeConnectorClient({ browser: targetBrowser }),
377
+ expectedBrowser: targetBrowser
378
+ });
379
+ } else {
380
+ client = createChromeConnectorClient();
381
+ }
382
+ }
249
383
  result = await client.request(spec.action, payload);
250
384
  } catch (error) {
251
385
  const code = typeof error?.code === "string" ? error.code : "CHROME_COMMAND_FAILED";