nolo-cli 0.90.0-alpha.1 → 0.91.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 (173) hide show
  1. package/README.md +1 -1
  2. package/{_executeModel-W26HVI75.js → _executeModel-H35GQ2XO.js} +61 -60
  3. package/{action-6DXQGJMX.js → action-3ZOODRBC.js} +11 -11
  4. package/{addContentAction-I7VX5SAC.js → addContentAction-IJHG2ZV7.js} +9 -9
  5. package/{addDialogAgentAction-OJSFV7DZ.js → addDialogAgentAction-IGFS2UBX.js} +11 -11
  6. package/{agentDeleteCommand-XNFWCKBH.js → agentDeleteCommand-XOFMXMHW.js} +43 -42
  7. package/{agentEmailCommands-W3X3EJ3V.js → agentEmailCommands-H2SEP6ZQ.js} +82 -78
  8. package/{agentGrantCommands-YW6PQAQ2.js → agentGrantCommands-M3XFO6EN.js} +2 -2
  9. package/{agentListCommands-DFWFU6XO.js → agentListCommands-RYGH6NUL.js} +72 -80
  10. package/{agentMachineCommands-LMFOAEL4.js → agentMachineCommands-XELOBZIP.js} +37 -36
  11. package/{agentProviderCommands-ZBYHGTGY.js → agentProviderCommands-JCRK6ST2.js} +1 -1
  12. package/{agentPullCommand-GLOOXJ2E.js → agentPullCommand-HF4A42D4.js} +3 -3
  13. package/agentRecordCommands-43HAXAZO.js +130 -0
  14. package/{agentRunCommand-HTBVIBGV.js → agentRunCommand-GIPN6DBO.js} +80 -75
  15. package/{agentRunControl-XLGD3UZ5.js → agentRunControl-AVJR4JW4.js} +2 -2
  16. package/{agentRuntimeLocal-2JFG4HDU.js → agentRuntimeLocal-SDOSSCLU.js} +38 -33
  17. package/{agentSlice-ZNLGFUB5.js → agentSlice-B2DLZMAC.js} +11 -11
  18. package/{appDeleteCommands-2UN4N2NR.js → appDeleteCommands-7OR5MAOR.js} +37 -36
  19. package/{appDeployCommands-37D74KRR.js → appDeployCommands-5GNI723H.js} +37 -36
  20. package/{appDeployStatusCommands-QBLWL2IA.js → appDeployStatusCommands-WL2NG3SG.js} +37 -36
  21. package/{appGetCommands-6KXIDF2T.js → appGetCommands-7BVKQS44.js} +37 -36
  22. package/{appListCommands-G2WFGEWQ.js → appListCommands-5VXFJOBU.js} +37 -36
  23. package/{authCommand-V2DJ7DB7.js → authCommand-N4Q6463J.js} +115 -23
  24. package/{authCommands-RGOGCPP6.js → authCommands-GBIFZWD3.js} +5 -5
  25. package/{builtinSkillRegistry-WBGYKIAZ.js → builtinSkillRegistry-JPY2DKRF.js} +7 -7
  26. package/{chatQueueReduxAdapter-XCJHIY3R.js → chatQueueReduxAdapter-3KDRKXTT.js} +29 -29
  27. package/{chromeCommands-VOIRNJBL.js → chromeCommands-NKU3OWKH.js} +36 -11
  28. package/{chromeOpsCommands-M7DPCX2T.js → chromeOpsCommands-OQDJGD4Y.js} +31 -1
  29. package/{chunk-4BYPU626.js → chunk-232453C2.js} +994 -1036
  30. package/{chunk-SMZSWB44.js → chunk-25GAGMRK.js} +6 -83
  31. package/{chunk-PH5J5VUY.js → chunk-3IYMTWYZ.js} +22 -22
  32. package/{chunk-NTW5GWDM.js → chunk-3VNWWVKB.js} +2 -0
  33. package/{chunk-TVNI5FLG.js → chunk-46CRK7XP.js} +7 -7
  34. package/{chunk-2ADBVBEM.js → chunk-55VQ4OPL.js} +4 -4
  35. package/{chunk-JPGCXHNM.js → chunk-5OA5HMTL.js} +1 -1
  36. package/{chunk-DWUCB2A3.js → chunk-62IL3KQV.js} +4 -34
  37. package/{chunk-3R5PH4IP.js → chunk-64TIEZHF.js} +1 -1
  38. package/{chunk-6YTOJY35.js → chunk-6D2JFXLY.js} +35 -0
  39. package/{chunk-3BMYXEUW.js → chunk-6O4IK4V2.js} +1 -1
  40. package/{chunk-WXPVOQD7.js → chunk-6PELJ3DS.js} +533 -236
  41. package/{chunk-NFMHIUY3.js → chunk-7EMJBGCA.js} +966 -218
  42. package/{chunk-HYZHJ5GW.js → chunk-7YMUSSHQ.js} +93 -93
  43. package/chunk-ACTMNVHM.js +93 -0
  44. package/{chunk-Q554LLSI.js → chunk-AUDNYVRC.js} +1 -1
  45. package/{chunk-UKWGR5SS.js → chunk-AUXHZ2M5.js} +186 -397
  46. package/{chunk-7MYYE7WX.js → chunk-B4PW6UAI.js} +61 -34
  47. package/{chunk-4DRWWIOL.js → chunk-B7ANJQWZ.js} +2 -2
  48. package/{chunk-XKQJJK4F.js → chunk-BAAKVSMZ.js} +4 -4
  49. package/{chunk-FQYMLZ6C.js → chunk-BFCXG6AJ.js} +16 -16
  50. package/{chunk-ZBT3WNBK.js → chunk-BJUDYFV5.js} +10 -2
  51. package/chunk-BMQ2MJUK.js +153 -0
  52. package/{chunk-TL6L5XUT.js → chunk-BNGW5ASC.js} +94 -16
  53. package/{chunk-JTK3TJYV.js → chunk-BTSYHR7J.js} +4 -4
  54. package/{chunk-LS2ZANRJ.js → chunk-CTUQJVQM.js} +1 -1
  55. package/{chunk-JEDZAO7L.js → chunk-D2W6WRHT.js} +13 -8
  56. package/{chunk-6BEA566T.js → chunk-D76D3RTR.js} +2 -2
  57. package/{chunk-HQCSU3DI.js → chunk-DCLMZ5TX.js} +4 -4
  58. package/{chunk-L2ICPOAL.js → chunk-EFZKILX6.js} +4 -4
  59. package/{chunk-JBBZ5KUM.js → chunk-EHO5EGU4.js} +23 -76
  60. package/{chunk-HVURBGF3.js → chunk-ESRMFY7G.js} +2 -2
  61. package/{chunk-ABQYVJBJ.js → chunk-ETZWFV6M.js} +1 -1
  62. package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
  63. package/{chunk-VHJLQHPQ.js → chunk-F64B2W3R.js} +110 -34
  64. package/{chunk-AQZRTHDZ.js → chunk-G4EMOUX3.js} +886 -154
  65. package/{chunk-XTUY5EL4.js → chunk-GJUKGFHG.js} +74 -16
  66. package/{chunk-XMGHGEN6.js → chunk-GMVELWJG.js} +3 -3
  67. package/chunk-GMZLP5DV.js +82 -0
  68. package/{chunk-CJCJF5XB.js → chunk-H6A6X4EK.js} +36 -3
  69. package/{chunk-N3OAPEZE.js → chunk-HBTA2SGQ.js} +97 -21
  70. package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
  71. package/{chunk-3CR2LC6X.js → chunk-HNRASX3X.js} +8 -8
  72. package/{chunk-CPH3W5A7.js → chunk-I3TQJXQ7.js} +94 -3
  73. package/{chunk-GRYGRGPS.js → chunk-IS5VEM2G.js} +140 -15
  74. package/{chunk-MJHQ3NRV.js → chunk-ISHYYQJC.js} +5 -3
  75. package/{chunk-ZAB3A45K.js → chunk-K7M4I3PF.js} +30 -7
  76. package/{chunk-2AYMFHUG.js → chunk-KQOD3G2X.js} +165 -15
  77. package/{chunk-YOXYA2GU.js → chunk-LNPYTNMG.js} +10 -5
  78. package/{chunk-F2CGG72C.js → chunk-LS2MI3B4.js} +45 -45
  79. package/{chunk-GII32WZW.js → chunk-M2EJHDJP.js} +3 -0
  80. package/{chunk-7S4YWN7P.js → chunk-MX574M24.js} +1 -1
  81. package/{chunk-DNQPPRHY.js → chunk-N3XA2O6O.js} +1 -1
  82. package/{chunk-5DFFKASO.js → chunk-NILSKYOE.js} +3 -3
  83. package/chunk-OCZKATRC.js +129 -0
  84. package/{chunk-K7M3MWCE.js → chunk-OOSVFT6S.js} +2 -2
  85. package/{chunk-QCZX4FTW.js → chunk-OY5IJI2N.js} +194 -21
  86. package/{chunk-HMEMJ7GH.js → chunk-PAYUVQ6P.js} +7749 -1320
  87. package/{chunk-ASGDO77C.js → chunk-Q67DOFOO.js} +92 -4
  88. package/{chunk-UA5S3LQQ.js → chunk-QALRKMHF.js} +11 -10
  89. package/{chunk-RZANZZL2.js → chunk-QDSINZM3.js} +1 -1
  90. package/{chunk-DPQ2WVBY.js → chunk-QJLEMM2V.js} +1 -1
  91. package/{chunk-IIKPWSPX.js → chunk-R4SQ3LGW.js} +1 -1
  92. package/{chunk-UTCCPWB2.js → chunk-RZ6CQZB2.js} +34 -20
  93. package/{chunk-SAFZABH7.js → chunk-SV5IJK6K.js} +1 -1
  94. package/{chunk-576IMUGH.js → chunk-T5V7HA3K.js} +1 -1
  95. package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
  96. package/chunk-UNYJU5L6.js +780 -0
  97. package/{chunk-QFMFJZLO.js → chunk-V7E4PXQD.js} +1 -1
  98. package/{chunk-QHETQ3KI.js → chunk-VBSVA6CB.js} +2 -2
  99. package/{chunk-A2C4AKKM.js → chunk-VETFWL5K.js} +1 -1
  100. package/chunk-VJVNU77E.js +83 -0
  101. package/{chunk-6D6VBVEW.js → chunk-VPFEPRME.js} +9 -9
  102. package/{chunk-3CMTBX3X.js → chunk-W2P25VGS.js} +25 -6
  103. package/{chunk-CLI4LFSM.js → chunk-WC6A2Q7S.js} +5 -3
  104. package/{chunk-Z33ARZCP.js → chunk-WT2IAJAJ.js} +4 -4
  105. package/chunk-X6YIXGPT.js +870 -0
  106. package/{chunk-5V4NJHRM.js → chunk-YMPTI7RZ.js} +9 -9
  107. package/{chunk-5NMZNPTN.js → chunk-YRIFJ6XQ.js} +13 -13
  108. package/{chunk-FZGV4FGK.js → chunk-YRRASA5Q.js} +268 -143
  109. package/{chunk-2F4VYGFW.js → chunk-Z5W7UMQV.js} +4 -3
  110. package/{chunk-ND2J3NRB.js → chunk-ZGJLSHER.js} +2 -2
  111. package/{chunk-VRLI2WNW.js → chunk-ZI2MEZMT.js} +314 -142
  112. package/{chunk-2F7RJC6L.js → chunk-ZOVKKMF6.js} +1 -1
  113. package/commandRegistry-BP5JLW24.js +822 -0
  114. package/{contentThunks-VURN3DFW.js → contentThunks-2HYFUXUM.js} +29 -29
  115. package/{cooldownCommands-BSCH2W7P.js → cooldownCommands-ZLEPIB4A.js} +2 -2
  116. package/{createAgentAutomationAction-QZAAY77R.js → createAgentAutomationAction-DCKUSJH7.js} +29 -29
  117. package/{createDialogAction-CHGXVTAC.js → createDialogAction-NRIAEH2A.js} +32 -32
  118. package/{createPageAction-IOGAFIN7.js → createPageAction-AUJHHXGG.js} +35 -35
  119. package/{dbSlice-YXQ6RYIH.js → dbSlice-HFPIJT5P.js} +8 -8
  120. package/{deleteFile-YG6QMJLU.js → deleteFile-UEAD5A5Z.js} +3 -3
  121. package/{dialogCommands-XREAP6WQ.js → dialogCommands-UJRGCRN6.js} +42 -39
  122. package/{dialogSlice-DOPGWGS4.js → dialogSlice-AHU4XXIW.js} +35 -29
  123. package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
  124. package/{docCreateCommands-3PYZGSCL.js → docCreateCommands-ZOV3ZBLW.js} +39 -38
  125. package/{docDeleteCommands-3Y6MU44Q.js → docDeleteCommands-G4KAXJYQ.js} +39 -38
  126. package/{docReadCommands-UBANMAFR.js → docReadCommands-B2MM3JIT.js} +38 -37
  127. package/{docStore-SYYFBENY.js → docStore-SITH63V3.js} +9 -9
  128. package/{docUpdateCommands-4GK2X6BN.js → docUpdateCommands-2QNF5CYN.js} +39 -38
  129. package/{fetchMessages-EIU7UFFK.js → fetchMessages-67MEFPZR.js} +2 -2
  130. package/{getPricing-F2C65RIX.js → getPricing-OX7B4R6B.js} +3 -3
  131. package/{handleSendMessageAction-NPVTY2GE.js → handleSendMessageAction-7ZMJMWLC.js} +72 -80
  132. package/index.js +74 -877
  133. package/{localDialogRead-BTFJ4V2I.js → localDialogRead-EBRS242U.js} +2 -2
  134. package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-5W6IJRAD.js} +6 -6
  135. package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-3LRMNLCM.js} +1 -1
  136. package/{machineCommands-I66X2XB7.js → machineCommands-YCTD5KOL.js} +75 -71
  137. package/{machineWsRunDispatch-W4FVBOUM.js → machineWsRunDispatch-JFMD4ZAW.js} +73 -69
  138. package/{memberThunks-5T4J6KXQ.js → memberThunks-SKFZ37VS.js} +9 -9
  139. package/{models-WW7VFNXB.js → models-T3SG6MJ5.js} +2 -2
  140. package/oauthTokenStore-ITEB663N.js +23 -0
  141. package/{offlineMarxistsAgentCommand-JEWCIAWM.js → offlineMarxistsAgentCommand-HGXZV4XJ.js} +1 -1
  142. package/package.json +1 -1
  143. package/pdf-U6KSUEZZ.js +26435 -0
  144. package/processSpawn-SOAV3FEV.js +11 -0
  145. package/profileConfig-ZGOFORWV.js +43 -0
  146. package/{providerPresetApply-OCWWKBSD.js → providerPresetApply-2QTBYN36.js} +7 -7
  147. package/{providerRegistry-ZJQU7AJ7.js → providerRegistry-SVXE4G4T.js} +7 -7
  148. package/{read-M2Q6WEKB.js → read-IEJLLUXY.js} +5 -5
  149. package/{readDocTool-T37P3YPB.js → readDocTool-4SPYCP2Y.js} +5 -3
  150. package/{readlineWorkspace-VY5AMOGR.js → readlineWorkspace-M3PLTBLD.js} +2396 -2018
  151. package/{removeDialogAgentAction-HB3JBVAI.js → removeDialogAgentAction-LILXTOQY.js} +14 -14
  152. package/{runAgentClientLoop-3NDADLVE.js → runAgentClientLoop-QMCXBOBH.js} +55 -55
  153. package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-3USD722U.js} +3 -3
  154. package/runtimeModeArgs-2Y7BALTO.js +31 -0
  155. package/{setDialogExtraReferencesAction-4XLHRV37.js → setDialogExtraReferencesAction-LVNHLNT5.js} +10 -10
  156. package/{setPrimaryDialogAgentAction-C3JOFC4W.js → setPrimaryDialogAgentAction-DCKO5NTW.js} +14 -14
  157. package/{settingSlice-CZRURSTH.js → settingSlice-CNE75ISY.js} +10 -10
  158. package/{spaceCommands-ENYCUUZH.js → spaceCommands-3U6OHM6O.js} +39 -38
  159. package/{streamAgentChatTurn-634OFUSR.js → streamAgentChatTurn-JPMJQSEE.js} +144 -84
  160. package/{switchDialogAgentAction-C6KVUKJP.js → switchDialogAgentAction-JSYUQ5CG.js} +11 -11
  161. package/{tableCommands-O6NWHFKV.js → tableCommands-G7RV3RU3.js} +4 -4
  162. package/{toolApiClient-7PSIFQPJ.js → toolApiClient-INIQCPGY.js} +3 -3
  163. package/{tools-ILBLCF7D.js → tools-XQ5GIH6P.js} +49 -49
  164. package/{tuiSummaryLlmCaller-LFUBZKXK.js → tuiSummaryLlmCaller-L63PDJUD.js} +16 -15
  165. package/{updateCommands-2M74UL7P.js → updateCommands-ECWKIWLQ.js} +3 -3
  166. package/{updateDialogTitleAction-RKFET73N.js → updateDialogTitleAction-EGAZMLUB.js} +32 -32
  167. package/agentRecordCommands-FVVVCQFM.js +0 -126
  168. package/chunk-Q5FJJ6XI.js +0 -103
  169. package/chunk-S7Z2HMCN.js +0 -25
  170. package/chunk-WS22FPWT.js +0 -79
  171. package/{chunk-VMFTFOWF.js → chunk-3AH7LNUB.js} +7 -7
  172. package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
  173. package/{db-WK5MDZVN.js → db-VQSAOWAO.js} +1 -1
@@ -6,19 +6,151 @@ import {
6
6
  } from "./chunk-KUG52IAP.js";
7
7
 
8
8
  // packages/desktop-chrome-connector/chromeConnector.ts
9
- import { existsSync, readFileSync } from "node:fs";
10
- import { resolve } from "node:path";
9
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
10
+ import { resolve as resolve2 } from "node:path";
11
+
12
+ // packages/desktop-chrome-connector/uploadSecurity.mjs
13
+ import { existsSync, realpathSync, statSync } from "node:fs";
14
+ import { isAbsolute, relative, resolve } from "node:path";
15
+ var DEFAULT_MAX_FILE_BYTES = 25 * 1024 * 1024;
16
+ var DEFAULT_MAX_FILES = 10;
17
+ var UploadSecurityError = class extends Error {
18
+ constructor(code, message) {
19
+ super(message);
20
+ this.name = "UploadSecurityError";
21
+ this.code = code;
22
+ }
23
+ };
24
+ function createUploadSecurityError(code, message) {
25
+ return new UploadSecurityError(code, message);
26
+ }
27
+ function isSubpath(parent, child) {
28
+ const rel = relative(parent, child);
29
+ return !rel.startsWith("..") && !isAbsolute(rel);
30
+ }
31
+ function parseAllowedRoots(env = process.env) {
32
+ const raw = env?.NOLO_CHROME_UPLOAD_ROOTS;
33
+ if (!raw || typeof raw !== "string") {
34
+ return [];
35
+ }
36
+ return raw.split(",").map((entry) => entry.trim()).filter(Boolean).filter((entry) => isAbsolute(entry)).map((entry) => {
37
+ const resolved = resolve(entry);
38
+ if (existsSync(resolved)) {
39
+ try {
40
+ return realpathSync(resolved);
41
+ } catch {
42
+ return resolved;
43
+ }
44
+ }
45
+ return resolved;
46
+ });
47
+ }
48
+ function validateUploadFiles(options = {}) {
49
+ const {
50
+ files,
51
+ env = process.env,
52
+ maxFiles = DEFAULT_MAX_FILES,
53
+ maxFileBytes = DEFAULT_MAX_FILE_BYTES
54
+ } = options;
55
+ if (!Array.isArray(files) || files.length === 0) {
56
+ throw createUploadSecurityError("no_files", "Provide at least one file to upload.");
57
+ }
58
+ if (files.length > maxFiles) {
59
+ throw createUploadSecurityError(
60
+ "too_many_files",
61
+ `Too many files: ${files.length} provided, maximum allowed is ${maxFiles}.`
62
+ );
63
+ }
64
+ const allowedRoots = parseAllowedRoots(env);
65
+ if (allowedRoots.length === 0) {
66
+ throw createUploadSecurityError(
67
+ "path_not_allowed",
68
+ "Upload roots not configured in NOLO_CHROME_UPLOAD_ROOTS; all uploads are refused."
69
+ );
70
+ }
71
+ const fileStats = [];
72
+ const canonicalFiles = [];
73
+ let totalBytes = 0;
74
+ for (const rawFile of files) {
75
+ if (typeof rawFile !== "string" || !rawFile.trim()) {
76
+ throw createUploadSecurityError("path_not_allowed", "File path must be a non-empty string.");
77
+ }
78
+ const trimmed = rawFile.trim();
79
+ const resolvedCandidate = resolve(trimmed);
80
+ if (!existsSync(resolvedCandidate)) {
81
+ throw createUploadSecurityError("path_not_allowed", `File not found or inaccessible: ${rawFile}`);
82
+ }
83
+ let real;
84
+ try {
85
+ real = realpathSync(resolvedCandidate);
86
+ } catch {
87
+ throw createUploadSecurityError("path_not_allowed", `Could not resolve canonical path for: ${rawFile}`);
88
+ }
89
+ let st;
90
+ try {
91
+ st = statSync(real);
92
+ } catch {
93
+ throw createUploadSecurityError("path_not_allowed", `Could not stat file: ${rawFile}`);
94
+ }
95
+ if (!st.isFile()) {
96
+ throw createUploadSecurityError("path_not_allowed", `Target path is not a regular file: ${rawFile}`);
97
+ }
98
+ if (st.size > maxFileBytes) {
99
+ throw createUploadSecurityError(
100
+ "too_large",
101
+ `File size ${st.size} bytes exceeds maximum allowed limit of ${maxFileBytes} bytes: ${rawFile}`
102
+ );
103
+ }
104
+ const realInside = allowedRoots.some((root) => isSubpath(root, real));
105
+ if (!realInside) {
106
+ throw createUploadSecurityError(
107
+ "path_not_allowed",
108
+ `Path '${rawFile}' (resolved: '${real}') is not within allowed upload roots.`
109
+ );
110
+ }
111
+ canonicalFiles.push(real);
112
+ fileStats.push({ path: real, bytes: st.size });
113
+ totalBytes += st.size;
114
+ }
115
+ return {
116
+ ok: true,
117
+ files: canonicalFiles,
118
+ fileStats,
119
+ totalBytes
120
+ };
121
+ }
122
+ function formatUploadAuditLog(entry = {}) {
123
+ const ts = entry.timestamp || (/* @__PURE__ */ new Date()).toISOString();
124
+ const safeTabId = String(entry.tabId ?? "").replace(/[\x00-\x1f\x7f-\x9f]+/g, " ");
125
+ const safeTarget = String(entry.target ?? "").replace(/[\x00-\x1f\x7f-\x9f]+/g, " ");
126
+ const files = Array.isArray(entry.files) ? entry.files : [];
127
+ const totalBytes = files.reduce((sum, f) => sum + (Number(f.bytes) || 0), 0);
128
+ const fileDetails = files.map((f) => `${String(f.path || "").replace(/[\x00-\x1f\x7f-\x9f]+/g, " ")}(${f.bytes || 0}B)`).join(", ");
129
+ return `[chrome-upload] ${ts} tabId=${safeTabId} target=${safeTarget} files=[${fileDetails}] totalBytes=${totalBytes}`;
130
+ }
131
+ function logUploadAudit(entry, logFn = console.warn) {
132
+ const line = formatUploadAuditLog(entry);
133
+ logFn(line);
134
+ return line;
135
+ }
136
+
137
+ // packages/desktop-chrome-connector/chromeConnector.ts
11
138
  var NOLO_CHROME_CONNECTOR_EXTENSION_ID = "ahpdoopadkamnglhlacfjdfnonpjdplg";
139
+ var NOLO_FIREFOX_CONNECTOR_EXTENSION_ID = "nolo-browser-connector@nolo.chat";
140
+ var NOLO_CONNECTOR_EXTENSION_IDS = [
141
+ NOLO_CHROME_CONNECTOR_EXTENSION_ID,
142
+ NOLO_FIREFOX_CONNECTOR_EXTENSION_ID
143
+ ];
12
144
  var NOLO_CHROME_CONNECTOR_PROTOCOL_VERSION = "2";
13
145
  function defaultTokenPath() {
14
- return resolve(
146
+ return resolve2(
15
147
  process.env.HOME || "",
16
148
  "Library/Application Support/Nolo/ChromeConnector/token"
17
149
  );
18
150
  }
19
151
  function readConnectorToken(tokenPath = defaultTokenPath()) {
20
152
  if (process.env.NOLO_CHROME_CONNECTOR_TOKEN) return process.env.NOLO_CHROME_CONNECTOR_TOKEN;
21
- if (!existsSync(tokenPath)) return "";
153
+ if (!existsSync2(tokenPath)) return "";
22
154
  return readFileSync(tokenPath, "utf8").trim();
23
155
  }
24
156
  var CHROME_TOOL_ACTIONS = {
@@ -32,7 +164,10 @@ var CHROME_TOOL_ACTIONS = {
32
164
  chrome_scroll: "scroll",
33
165
  chrome_screenshot: "screenshot",
34
166
  chrome_read_console: "read_console",
35
- chrome_read_network: "read_network"
167
+ chrome_read_network: "read_network",
168
+ chrome_set_files: "set_files",
169
+ chrome_upload_file: "set_files",
170
+ chrome_upload: "set_files"
36
171
  };
37
172
  function createConnectorError(code, message, details) {
38
173
  const error = new Error(message);
@@ -53,14 +188,18 @@ function parseArguments(raw) {
53
188
  }
54
189
  }
55
190
  function errorPayload(error) {
191
+ const code = error?.code ?? "CHROME_CONNECTOR_ERROR";
56
192
  return {
57
- code: error?.code ?? "CHROME_CONNECTOR_ERROR",
193
+ code,
58
194
  message: toErrorMessage(error),
195
+ ...code === "CHROME_CONNECTOR_UNAVAILABLE" ? {
196
+ 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."
197
+ } : {},
59
198
  ...error?.details !== void 0 ? { details: error.details } : {}
60
199
  };
61
200
  }
62
- var TARGET_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["click", "type"]);
63
- var TAB_ID_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["close_tab", "detach"]);
201
+ var TARGET_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["click", "type", "set_files"]);
202
+ var TAB_ID_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["close_tab", "detach", "set_files"]);
64
203
  function validateChromeConnectorPayload(action, payload) {
65
204
  if (TAB_ID_REQUIRED_ACTIONS.has(action)) {
66
205
  const raw = payload.tabId;
@@ -71,16 +210,42 @@ function validateChromeConnectorPayload(action, payload) {
71
210
  `Provide the tabId from chrome_list_tabs before calling ${action}.`
72
211
  );
73
212
  }
74
- return;
213
+ if (!TARGET_REQUIRED_ACTIONS.has(action)) return;
75
214
  }
76
215
  if (!TARGET_REQUIRED_ACTIONS.has(action)) return;
77
- const elementRef = typeof payload.elementRef === "string" ? payload.elementRef.trim() : "";
216
+ const rawRef = typeof payload.elementRef === "string" ? payload.elementRef : typeof payload.ref === "string" ? payload.ref : "";
217
+ const elementRef = rawRef.trim();
78
218
  const selector = typeof payload.selector === "string" ? payload.selector.trim() : "";
79
- if (elementRef || selector) return;
80
- throw createConnectorError(
81
- "ELEMENT_TARGET_REQUIRED",
82
- "Provide elementRef from chrome_read_page or a CSS selector."
83
- );
219
+ if (!elementRef && !selector) {
220
+ throw createConnectorError(
221
+ "ELEMENT_TARGET_REQUIRED",
222
+ "Provide elementRef from chrome_read_page or a CSS selector."
223
+ );
224
+ }
225
+ if (action === "set_files") {
226
+ if (!Array.isArray(payload.files) || payload.files.length === 0) {
227
+ throw createConnectorError(
228
+ "no_files",
229
+ "Provide at least one file path in files array."
230
+ );
231
+ }
232
+ try {
233
+ const validated = validateUploadFiles({
234
+ files: payload.files,
235
+ env: process.env
236
+ });
237
+ payload.files = validated.files;
238
+ const targetStr = elementRef ? `ref:${elementRef}` : `selector:${selector}`;
239
+ logUploadAudit({
240
+ tabId: String(payload.tabId),
241
+ target: targetStr,
242
+ files: validated.fileStats
243
+ });
244
+ } catch (err) {
245
+ const code = err?.code ?? "path_not_allowed";
246
+ throw createConnectorError(code, toErrorMessage(err));
247
+ }
248
+ }
84
249
  }
85
250
  function createChromeConnectorClient(args) {
86
251
  if (args?.request) return { request: args.request };
@@ -90,6 +255,7 @@ function createChromeConnectorClient(args) {
90
255
  const token = args?.token ?? readConnectorToken(args?.tokenPath);
91
256
  return {
92
257
  async request(action, payload) {
258
+ validateChromeConnectorPayload(action, payload);
93
259
  let response;
94
260
  try {
95
261
  response = await fetchImpl(endpoint, {
@@ -128,27 +294,34 @@ var REQUIRED_CHROME_CONNECTOR_FEATURES = {
128
294
  type: ["compact_observation_v2", "action_gate"],
129
295
  press: ["compact_observation_v2", "action_gate"],
130
296
  scroll: ["compact_observation_v2"],
131
- screenshot: ["browser_debug"],
297
+ // Both browsers advertise the dedicated `screenshot` feature: Chrome serves it through
298
+ // Page.captureScreenshot (browser_debug-adjacent) while Firefox falls back to
299
+ // tabs.captureVisibleTab, so gating on browser_debug would wrongly refuse Firefox.
300
+ screenshot: ["screenshot"],
132
301
  read_console: ["browser_debug"],
133
302
  read_network: ["browser_debug"],
134
- detach: ["browser_debug"]
303
+ detach: ["browser_debug"],
304
+ set_files: ["compact_observation_v2", "file_upload"]
135
305
  };
136
306
  function requiredFeaturesForConnectorAction(action) {
137
307
  return [...REQUIRED_CHROME_CONNECTOR_FEATURES[action] ?? []];
138
308
  }
139
309
  function createVerifiedChromeConnectorClient(args) {
140
310
  const client = args?.client ?? createChromeConnectorClient();
141
- const expectedExtensionId = args?.expectedExtensionId ?? NOLO_CHROME_CONNECTOR_EXTENSION_ID;
311
+ const expectedExtensionIds = new Set(
312
+ args?.expectedExtensionIds ?? (args?.expectedExtensionId ? [args.expectedExtensionId] : NOLO_CONNECTOR_EXTENSION_IDS)
313
+ );
142
314
  let verified = null;
143
315
  let negotiatedFeatures = [];
144
316
  const verify = async () => {
145
317
  const connectorInfo = await client.request("connector_info", {});
146
318
  const receivedExtensionId = connectorInfo?.extensionId;
147
- if (receivedExtensionId !== expectedExtensionId) {
319
+ if (typeof receivedExtensionId !== "string" || !expectedExtensionIds.has(receivedExtensionId)) {
320
+ const expectedList = [...expectedExtensionIds].join(", ");
148
321
  throw createConnectorError(
149
322
  "CHROME_CONNECTOR_EXTENSION_MISMATCH",
150
- `Chrome connector extension id mismatch: expected ${expectedExtensionId}, received ${typeof receivedExtensionId === "string" ? receivedExtensionId : "unknown"}.`,
151
- { expectedExtensionId, receivedExtensionId }
323
+ `Chrome connector extension id mismatch: expected one of ${expectedList}, received ${typeof receivedExtensionId === "string" ? receivedExtensionId : "unknown"}.`,
324
+ { expectedExtensionIds: [...expectedExtensionIds], receivedExtensionId }
152
325
  );
153
326
  }
154
327
  const receivedProtocolVersion = connectorInfo?.protocolVersion;