binary-collections 2.0.10 → 2.0.11

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 (165) hide show
  1. package/.puppeterrc.cjs +25 -0
  2. package/binaries/binary-executor.cjs +138 -3
  3. package/binaries/clean-nodemodule.cjs +138 -3
  4. package/binaries/clean-nodemodules.cjs +138 -3
  5. package/binaries/dev.cjs +138 -3
  6. package/binaries/empty.cjs +138 -3
  7. package/binaries/git-reduce-size.cjs +138 -3
  8. package/binaries/javakill.cjs +138 -3
  9. package/binaries/kill-night-crows.bat +7 -0
  10. package/binaries/kill-night-crows.ps1 +172 -0
  11. package/binaries/kill-process.cjs +138 -3
  12. package/binaries/nodekill.cjs +138 -3
  13. package/binaries/prod.cjs +138 -3
  14. package/binaries/py +111 -0
  15. package/binaries/py.cjs +178 -0
  16. package/binaries/py.cmd +49 -0
  17. package/binaries/rmfind.cjs +138 -3
  18. package/binaries/rmx.cjs +138 -3
  19. package/binaries/submodule-token.cjs +138 -3
  20. package/binaries/test-cjs +10 -0
  21. package/binaries/test-cjs.cjs +178 -0
  22. package/binaries/test-cjs.cmd +11 -0
  23. package/binaries/yarn-clean +32 -0
  24. package/binaries/yarn-clean.cjs +178 -0
  25. package/binaries/yarn-clean.cmd +30 -0
  26. package/binaries/yarn-clean.py +148 -0
  27. package/lib/binary-collections-config.cjs +1 -1
  28. package/lib/binary-collections-config.mjs +1 -1
  29. package/lib/binary-collections.cjs +167 -106
  30. package/lib/binary-collections.mjs +108 -94
  31. package/lib/changelog.cjs +61 -13
  32. package/lib/changelog.mjs +1 -1
  33. package/lib/{chunk-AI4CVPJ7.mjs → chunk-2CBJCW7E.mjs} +4 -4
  34. package/lib/chunk-34IQDTLZ.mjs +27 -0
  35. package/lib/chunk-3HFFECCI.mjs +27 -0
  36. package/lib/{chunk-SBNDSKG5.mjs → chunk-4UHL4WVN.mjs} +1 -1
  37. package/lib/chunk-7XTEJHOE.mjs +193 -0
  38. package/lib/chunk-AJDD5DZM.mjs +109 -0
  39. package/lib/chunk-BZWVHODJ.mjs +62 -0
  40. package/lib/{chunk-BEZKJ25G.mjs → chunk-FCDQGYBF.mjs} +5 -9
  41. package/lib/chunk-GEYA2USY.mjs +207 -0
  42. package/lib/chunk-ID2WBTE2.mjs +80 -0
  43. package/lib/chunk-JXFOHKDM.mjs +239 -0
  44. package/lib/{chunk-DI5MDPSN.mjs → chunk-N436BNBK.mjs} +192 -64
  45. package/lib/chunk-NCXAP7AA.mjs +31 -0
  46. package/lib/chunk-PDN26I7O.mjs +188 -0
  47. package/lib/{chunk-E6FDDAOO.mjs → chunk-RWLXRTYP.mjs} +1 -1
  48. package/lib/{chunk-BDCHCWHD.mjs → chunk-TOIVAQF7.mjs} +4 -4
  49. package/lib/chunk-V5SKYJUB.mjs +136 -0
  50. package/lib/{chunk-HMRMTYZM.mjs → chunk-WSRETQCA.mjs} +21 -2
  51. package/lib/chunk-XA3SNBPA.mjs +184 -0
  52. package/lib/chunk-YYLIQQKF.mjs +31 -0
  53. package/lib/{chunk-V3N3JEUF.mjs → chunk-Z6JLYU2J.mjs} +60 -13
  54. package/lib/{chunk-O6SWBEOQ.mjs → chunk-ZDMWBSYF.mjs} +2 -2
  55. package/lib/clean-github-actions-caches.cjs +63 -15
  56. package/lib/clean-github-actions-caches.mjs +3 -3
  57. package/lib/del-gradle.cjs +61 -13
  58. package/lib/del-gradle.js +1 -0
  59. package/lib/del-gradle.mjs +1 -1
  60. package/lib/del-node-modules.cjs +143 -148
  61. package/lib/del-node-modules.js +210 -14
  62. package/lib/del-node-modules.mjs +148 -17
  63. package/lib/del-ps.cjs +61 -13
  64. package/lib/del-ps.js +1 -0
  65. package/lib/del-ps.mjs +1 -1
  66. package/lib/del-yarn-caches.cjs +61 -13
  67. package/lib/del-yarn-caches.mjs +1 -1
  68. package/lib/find-node-modules-cli.js +1 -0
  69. package/lib/free-chatgpt.cjs +253 -47
  70. package/lib/free-chatgpt.mjs +2 -2
  71. package/lib/git/gitattributes.cjs +1 -0
  72. package/lib/git/gitattributes.d.cts +7 -2
  73. package/lib/git/gitattributes.mjs +1 -1
  74. package/lib/git/line-endings.cjs +2 -1
  75. package/lib/git/line-endings.mjs +2 -2
  76. package/lib/git/undo-commit-cli.cjs +110 -0
  77. package/lib/git/undo-commit-cli.d.ts +1 -0
  78. package/lib/git/undo-commit-cli.js +4 -0
  79. package/lib/git/undo-commit-cli.mjs +14 -0
  80. package/lib/git/undo-commit.cjs +81 -0
  81. package/lib/git/undo-commit.d.cts +1 -0
  82. package/lib/git/undo-commit.mjs +7 -0
  83. package/lib/git/undo-staged-cli.cjs +110 -0
  84. package/lib/git/undo-staged-cli.d.ts +1 -0
  85. package/lib/git/undo-staged-cli.js +4 -0
  86. package/lib/git/undo-staged-cli.mjs +14 -0
  87. package/lib/git/undo-staged.cjs +81 -0
  88. package/lib/git/undo-staged.d.cts +1 -0
  89. package/lib/git/undo-staged.mjs +7 -0
  90. package/lib/git/user-config.cjs +61 -14
  91. package/lib/git/user-config.mjs +2 -2
  92. package/lib/git-diff-cli.cjs +255 -49
  93. package/lib/git-diff-cli.d.ts +1 -0
  94. package/lib/git-diff-cli.js +1 -0
  95. package/lib/git-diff-cli.mjs +5 -4
  96. package/lib/git-diff.cjs +254 -49
  97. package/lib/git-diff.mjs +4 -4
  98. package/lib/git-fix.cjs +64 -16
  99. package/lib/git-fix.mjs +10 -10
  100. package/lib/git-purge.cjs +61 -13
  101. package/lib/git-purge.mjs +1 -1
  102. package/lib/kill-night-crows.cjs +87 -0
  103. package/lib/kill-night-crows.d.mts +1 -0
  104. package/lib/kill-night-crows.mjs +65 -0
  105. package/lib/npm-run-series.cjs +60 -13
  106. package/lib/npm-run-series.mjs +1 -1
  107. package/lib/package-resolutions-updater-cli.cjs +560 -0
  108. package/lib/package-resolutions-updater-cli.d.mts +1 -0
  109. package/lib/package-resolutions-updater-cli.mjs +124 -0
  110. package/lib/package-resolutions-updater.cjs +174 -154
  111. package/lib/package-resolutions-updater.d.mts +32 -1
  112. package/lib/package-resolutions-updater.mjs +16 -294
  113. package/lib/php-cs-fixer-staged.cjs +105 -0
  114. package/lib/php-cs-fixer-staged.d.cts +2 -0
  115. package/lib/php-cs-fixer-staged.mjs +117 -0
  116. package/lib/print-directory-tree.cjs +62 -14
  117. package/lib/print-directory-tree.mjs +2 -2
  118. package/lib/ps/connected-domain.d.ts +1 -1
  119. package/lib/ps/index.js +1 -0
  120. package/lib/remove-module.cjs +61 -13
  121. package/lib/remove-module.mjs +1 -1
  122. package/lib/rmpath.cjs +63 -15
  123. package/lib/rmpath.mjs +2 -2
  124. package/lib/submodule-install.cjs +62 -15
  125. package/lib/submodule-install.mjs +3 -3
  126. package/lib/submodule-remove-cli.cjs +5 -1
  127. package/lib/submodule-remove-cli.mjs +1 -1
  128. package/lib/submodule-remove.cjs +4 -1
  129. package/lib/submodule-remove.mjs +1 -1
  130. package/lib/utils/chatgpt.cjs +192 -34
  131. package/lib/utils/chatgpt.js +210 -43
  132. package/lib/utils/chatgpt.mjs +1 -1
  133. package/lib/utils/findEnvFiles.cjs +107 -0
  134. package/lib/utils/findEnvFiles.d.ts +8 -0
  135. package/lib/utils/findEnvFiles.js +121 -0
  136. package/lib/utils/findEnvFiles.mjs +8 -0
  137. package/lib/utils/findWorkspaceRoot.cjs +70 -0
  138. package/lib/utils/findWorkspaceRoot.d.ts +9 -0
  139. package/lib/utils/findWorkspaceRoot.js +57 -0
  140. package/lib/utils/findWorkspaceRoot.mjs +40 -0
  141. package/lib/utils/index.cjs +60 -13
  142. package/lib/utils/index.mjs +1 -1
  143. package/lib/utils/isGithubTokenValid.cjs +64 -0
  144. package/lib/utils/isGithubTokenValid.d.ts +7 -0
  145. package/lib/utils/isGithubTokenValid.js +48 -0
  146. package/lib/utils/isGithubTokenValid.mjs +36 -0
  147. package/lib/yarn-reinstall.cjs +61 -13
  148. package/lib/yarn-reinstall.mjs +1 -1
  149. package/package.json +107 -93
  150. package/readme.md +33 -34
  151. package/releases/readme.md +1 -1
  152. package/requirements.txt +1 -0
  153. package/lib/chunk-4EWQC6GZ.mjs +0 -382
  154. package/lib/chunk-4ZI7BQKQ.mjs +0 -381
  155. package/lib/chunk-5J2BEPY5.mjs +0 -83
  156. package/lib/chunk-AGZYRDC2.mjs +0 -323
  157. package/lib/chunk-HN52G2YL.mjs +0 -305
  158. package/lib/chunk-HO6GHCOB.mjs +0 -385
  159. package/lib/chunk-LEM5OMRP.mjs +0 -384
  160. package/lib/chunk-RCP7DHVY.mjs +0 -190
  161. package/lib/chunk-U6SO4QEV.mjs +0 -320
  162. package/lib/chunk-XD6BJK6Q.mjs +0 -351
  163. package/lib/chunk-YXSFGA2D.mjs +0 -383
  164. package/lib/git/gitattributes.d.ts +0 -33
  165. package/lib/git/gitattributes.js +0 -223
@@ -38,7 +38,17 @@ var import_puppeteer_extra_plugin_stealth = __toESM(require("puppeteer-extra-plu
38
38
  var import_upath = __toESM(require("upath"), 1);
39
39
  var COOKIE_DIR = import_upath.default.join(process.cwd(), "tmp", "cookies");
40
40
  var DEFAULT_COOKIE_PATH = import_upath.default.join(COOKIE_DIR, "cookies.json");
41
+ var NAVIGATION_TIMEOUT_MS = 9e4;
42
+ var NETWORK_IDLE_TIMEOUT_MS = 15e3;
43
+ var MAX_INLINE_QUESTION_FILE_BYTES = 2 * 1024;
41
44
  import_fs_extra.default.ensureDirSync(COOKIE_DIR);
45
+ async function gotoWithFallback(page, url) {
46
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout: NAVIGATION_TIMEOUT_MS });
47
+ try {
48
+ await page.waitForNetworkIdle({ idleTime: 1e3, timeout: NETWORK_IDLE_TIMEOUT_MS });
49
+ } catch {
50
+ }
51
+ }
42
52
  async function saveCookies(page, path2 = DEFAULT_COOKIE_PATH) {
43
53
  const cookies = await page.cookies();
44
54
  import_fs_extra.default.writeFileSync(path2, JSON.stringify(cookies, null, 2));
@@ -57,7 +67,7 @@ async function navigatePage(page, url) {
57
67
  if (cookies) {
58
68
  await page.setCookie(...cookies);
59
69
  }
60
- await page.goto(url, { waitUntil: "networkidle0" });
70
+ await gotoWithFallback(page, url);
61
71
  await page.evaluate(() => {
62
72
  window.__domStillUpdating = true;
63
73
  if (window.__domObserver) {
@@ -97,46 +107,151 @@ function loadCookies(cookieFilePath = DEFAULT_COOKIE_PATH) {
97
107
  return JSON.parse(import_fs_extra.default.readFileSync(cookieFilePath));
98
108
  }
99
109
  async function writeQuestion(page, question) {
100
- const questions = question.split("\n");
101
110
  const promptTextarea = await page.waitForSelector("#prompt-textarea", { timeout: 3e4 });
102
111
  if (!promptTextarea) {
103
112
  console.log(
104
113
  "Cannot find the prompt input on the webpage. Please check whether you have access to chat.openai.com without logging in via your browser."
105
114
  );
106
- }
107
- await page.evaluate(() => {
108
- document.querySelector("#prompt-textarea").innerHTML = `<p></p>`;
109
- });
110
- if (questions.length === 1) {
111
- await page.type("#prompt-textarea", questions[0], { delay: 100 });
112
115
  return;
113
116
  }
114
- for (const q of questions) {
115
- await page.type("#prompt-textarea", q, { delay: 100 });
116
- if (q !== questions[questions.length - 1]) {
117
- await page.keyboard.down("Shift");
118
- await page.keyboard.press("Enter");
119
- await page.keyboard.up("Shift");
117
+ await page.evaluate((text) => {
118
+ const promptEl = document.querySelector("#prompt-textarea");
119
+ if (!promptEl) {
120
+ return;
121
+ }
122
+ promptEl.focus();
123
+ promptEl.innerHTML = "";
124
+ const lines = String(text).split("\n");
125
+ for (const line of lines) {
126
+ const p = document.createElement("p");
127
+ p.textContent = line;
128
+ promptEl.appendChild(p);
120
129
  }
130
+ promptEl.dispatchEvent(new InputEvent("beforeinput", { bubbles: true, inputType: "insertFromPaste", data: text }));
131
+ promptEl.dispatchEvent(new InputEvent("input", { bubbles: true, inputType: "insertFromPaste", data: text }));
132
+ promptEl.dispatchEvent(new Event("change", { bubbles: true }));
133
+ }, question);
134
+ const hasPromptText = await page.evaluate(() => {
135
+ const promptEl = document.querySelector("#prompt-textarea");
136
+ return Boolean(promptEl && promptEl.textContent && promptEl.textContent.trim().length > 0);
137
+ });
138
+ if (!hasPromptText) {
139
+ console.log("Prompt state not updated by DOM injection. Falling back to keyboard insertText.");
140
+ await promptTextarea.click({ clickCount: 1 });
141
+ await page.keyboard.down("Control");
142
+ await page.keyboard.press("KeyA");
143
+ await page.keyboard.up("Control");
144
+ await page.keyboard.insertText(question);
121
145
  }
122
146
  }
123
147
  async function clickSubmitButton(page) {
148
+ console.log("Attempting to click the submit button...");
124
149
  try {
125
- const fruitjuiceSendButton = await page.evaluate(() => {
126
- return document.querySelector('[data-testid="fruitjuice-send-button"]') !== null;
150
+ const userMessageCountBefore = await page.$$eval('[data-message-author-role="user"]', (elements) => elements.length);
151
+ const waitForSubmit = async (timeout = 5e3) => {
152
+ try {
153
+ await page.waitForFunction(
154
+ (previousCount) => {
155
+ const currentCount = document.querySelectorAll('[data-message-author-role="user"]').length;
156
+ return currentCount > previousCount;
157
+ },
158
+ { timeout },
159
+ userMessageCountBefore
160
+ );
161
+ return true;
162
+ } catch {
163
+ return false;
164
+ }
165
+ };
166
+ await page.waitForFunction(() => {
167
+ const candidates = [
168
+ document.querySelector('[data-testid="fruitjuice-send-button"]'),
169
+ document.querySelector("#composer-submit-button"),
170
+ document.querySelector('[data-testid="send-button"]')
171
+ ].filter(Boolean);
172
+ return candidates.some((button) => {
173
+ const isDisabled = button.disabled || button.getAttribute("aria-disabled") === "true";
174
+ const isVisible = button.offsetParent !== null;
175
+ return !isDisabled && isVisible;
176
+ });
177
+ }, { timeout: 5e3 }).catch(() => {
178
+ });
179
+ const buttonDetails = await page.evaluate(() => {
180
+ const selectors = [
181
+ '[data-testid="fruitjuice-send-button"]',
182
+ "#composer-submit-button",
183
+ '[data-testid="send-button"]'
184
+ ];
185
+ const details = selectors.map((selector) => {
186
+ const el = document.querySelector(selector);
187
+ const exists = Boolean(el);
188
+ const disabled = exists ? Boolean(el.disabled || el.getAttribute("aria-disabled") === "true") : null;
189
+ const visible = exists ? el.offsetParent !== null : null;
190
+ return { selector, exists, disabled, visible };
191
+ });
192
+ return details;
127
193
  });
128
- const sendButton = await page.evaluate(() => {
129
- return document.querySelector('[data-testid="send-button"]') !== null;
194
+ console.log(`Submit button details: ${JSON.stringify(buttonDetails)}`);
195
+ const clickable = buttonDetails.find((item) => item.exists && item.visible && item.disabled === false);
196
+ const selectedSelector = clickable ? clickable.selector : null;
197
+ if (selectedSelector) {
198
+ await page.click(selectedSelector);
199
+ console.log(`Clicked submit button selector: ${selectedSelector}`);
200
+ if (await waitForSubmit(5e3)) {
201
+ console.log("Submission detected after selector click.");
202
+ return true;
203
+ }
204
+ const forcedClickWorked = await page.evaluate((selector) => {
205
+ const el = document.querySelector(selector);
206
+ if (!el) {
207
+ return false;
208
+ }
209
+ el.click();
210
+ return true;
211
+ }, selectedSelector);
212
+ if (forcedClickWorked) {
213
+ console.log(`Forced DOM click on selector: ${selectedSelector}`);
214
+ if (await waitForSubmit(5e3)) {
215
+ console.log("Submission detected after forced DOM click.");
216
+ return true;
217
+ }
218
+ }
219
+ }
220
+ console.log("Submit button path did not submit. Trying Enter key fallback on prompt.");
221
+ await page.focus("#prompt-textarea");
222
+ await page.keyboard.press("Enter");
223
+ if (await waitForSubmit(5e3)) {
224
+ console.log("Submission detected after Enter key fallback.");
225
+ return true;
226
+ }
227
+ const didRequestSubmit = await page.evaluate(() => {
228
+ const prompt = document.querySelector("#prompt-textarea");
229
+ if (!prompt) {
230
+ return false;
231
+ }
232
+ const form = prompt.closest("form");
233
+ if (!form) {
234
+ return false;
235
+ }
236
+ if (typeof form.requestSubmit === "function") {
237
+ form.requestSubmit();
238
+ } else {
239
+ form.submit();
240
+ }
241
+ return true;
130
242
  });
131
- if (fruitjuiceSendButton) {
132
- await page.click('[data-testid="fruitjuice-send-button"]');
133
- } else if (sendButton) {
134
- await page.click('[data-testid="send-button"]');
135
- } else {
136
- console.log("Neither send button is present");
243
+ if (didRequestSubmit) {
244
+ console.log("Triggered form submit fallback.");
245
+ if (await waitForSubmit(5e3)) {
246
+ console.log("Submission detected after form submit fallback.");
247
+ return true;
248
+ }
137
249
  }
250
+ console.log("Failed to submit prompt after all strategies.");
251
+ return false;
138
252
  } catch (e) {
139
253
  console.log(`Failed to click the send button: ${e}`);
254
+ return false;
140
255
  }
141
256
  }
142
257
  var lastMessageId = null;
@@ -209,11 +324,15 @@ async function isLoggedIn(page) {
209
324
  return result === true;
210
325
  }
211
326
  async function createBrowser(browserOptions = {}) {
327
+ const windowsChromeExecutable = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
328
+ const hasWindowsChrome = process.platform === "win32" && import_fs_extra.default.existsSync(windowsChromeExecutable);
212
329
  const defaultOptions = {
213
330
  headless: false,
331
+ defaultViewport: null,
214
332
  userDataDir: import_upath.default.join(process.cwd(), "tmp/puppeteer-profile"),
215
333
  // Windows-specific options to handle browser launch issues
216
334
  args: [
335
+ "--start-maximized",
217
336
  "--no-sandbox",
218
337
  "--disable-setuid-sandbox",
219
338
  "--disable-dev-shm-usage",
@@ -226,10 +345,9 @@ async function createBrowser(browserOptions = {}) {
226
345
  "--disable-renderer-backgrounding"
227
346
  ],
228
347
  ignoreDefaultArgs: ["--disable-extensions"],
229
- ...process.platform === "win32" && {
230
- // Additional Windows-specific options
231
- executablePath: void 0
232
- // Let Puppeteer find Chrome automatically
348
+ ...hasWindowsChrome && {
349
+ // Prefer local Chrome installation when present on Windows.
350
+ executablePath: windowsChromeExecutable
233
351
  }
234
352
  };
235
353
  try {
@@ -239,8 +357,12 @@ async function createBrowser(browserOptions = {}) {
239
357
  try {
240
358
  return await import_puppeteer_extra.default.use((0, import_puppeteer_extra_plugin_stealth.default)()).launch({
241
359
  headless: browserOptions.headless || false,
242
- args: ["--no-sandbox", "--disable-setuid-sandbox"],
360
+ defaultViewport: null,
361
+ args: ["--start-maximized", "--no-sandbox", "--disable-setuid-sandbox"],
243
362
  ignoreDefaultArgs: false,
363
+ ...hasWindowsChrome && {
364
+ executablePath: windowsChromeExecutable
365
+ },
244
366
  ...browserOptions
245
367
  });
246
368
  } catch (fallbackError) {
@@ -265,7 +387,11 @@ async function loginToChatGpt() {
265
387
  if (loginButtonExists) {
266
388
  console.log("Login button found, clicking to log in...");
267
389
  await page.click('[data-testid="login-button"]');
268
- await page.waitForNavigation({ waitUntil: "networkidle0" });
390
+ await page.waitForNavigation({ waitUntil: "domcontentloaded", timeout: NAVIGATION_TIMEOUT_MS });
391
+ try {
392
+ await page.waitForNetworkIdle({ idleTime: 1e3, timeout: NETWORK_IDLE_TIMEOUT_MS });
393
+ } catch {
394
+ }
269
395
  console.log("Login process completed.");
270
396
  } else {
271
397
  console.log("No login required - user appears to be already logged in.");
@@ -275,6 +401,7 @@ async function runChatGpt(chatgptOptions = {}) {
275
401
  const headless = chatgptOptions.headless !== void 0 ? chatgptOptions.headless : true;
276
402
  const questionFile = chatgptOptions.questionFile;
277
403
  let question = chatgptOptions.question;
404
+ let shouldUploadQuestionFile = Boolean(questionFile);
278
405
  const responseFile = chatgptOptions.responseFile || import_upath.default.join(process.cwd(), "tmp", "response.txt");
279
406
  const noInputProvided = !question && !questionFile;
280
407
  const questionIsEmpty = question && question.trim().length === 0;
@@ -282,6 +409,22 @@ async function runChatGpt(chatgptOptions = {}) {
282
409
  if (noInputProvided || questionIsEmpty || questionFileIsEmpty) {
283
410
  throw new Error("You must provide a question or a question file.");
284
411
  }
412
+ if (!question && questionFile) {
413
+ if (!import_fs_extra.default.existsSync(questionFile)) {
414
+ throw new Error(`Question file does not exist: ${questionFile}`);
415
+ }
416
+ const questionFileStats = import_fs_extra.default.statSync(questionFile);
417
+ if (questionFileStats.size <= MAX_INLINE_QUESTION_FILE_BYTES) {
418
+ question = import_fs_extra.default.readFileSync(questionFile, "utf8").trim();
419
+ if (!question) {
420
+ throw new Error("Question file is empty.");
421
+ }
422
+ shouldUploadQuestionFile = false;
423
+ console.log(
424
+ `Question file is ${questionFileStats.size} bytes (<= ${MAX_INLINE_QUESTION_FILE_BYTES}). Sending as text prompt.`
425
+ );
426
+ }
427
+ }
285
428
  let browser;
286
429
  try {
287
430
  browser = await createBrowser({ headless });
@@ -294,7 +437,16 @@ async function runChatGpt(chatgptOptions = {}) {
294
437
  console.error("4. Close any running Chrome instances and try again");
295
438
  throw error;
296
439
  }
297
- const page = (await browser.pages()).length > 0 ? (await browser.pages())[0] : await browser.newPage();
440
+ const allPages = await browser.pages();
441
+ const page = allPages.length > 0 ? allPages[0] : await browser.newPage();
442
+ await page.bringToFront();
443
+ if (allPages.length > 1) {
444
+ for (const p of allPages) {
445
+ if (p !== page) {
446
+ await p.close();
447
+ }
448
+ }
449
+ }
298
450
  try {
299
451
  const url = "https://chat.openai.com";
300
452
  const navigate = await navigatePage(page, url);
@@ -313,12 +465,15 @@ async function runChatGpt(chatgptOptions = {}) {
313
465
  }
314
466
  if (question) {
315
467
  await writeQuestion(page, question);
316
- await clickSubmitButton(page);
468
+ const didSubmit = await clickSubmitButton(page);
469
+ if (!didSubmit) {
470
+ throw new Error("Prompt was not submitted. The composer button may be disabled or blocked.");
471
+ }
317
472
  await navigate.waitForDomIdle(1e3, 3e4);
318
473
  await waitForInitialResponse(page);
319
474
  await handleStreamingResponse(page, responseFile);
320
475
  await saveCookies(page, getCookiePathForUrl(url));
321
- } else if (questionFile) {
476
+ } else if (shouldUploadQuestionFile && questionFile) {
322
477
  await navigate.waitForDomIdle(2e3, 1e4);
323
478
  const isUserLoggedIn = await isLoggedIn(page);
324
479
  console.log(`Login status: ${isUserLoggedIn ? "Logged in" : "Not logged in"}`);
@@ -357,7 +512,10 @@ async function runChatGpt(chatgptOptions = {}) {
357
512
  await fileInput.uploadFile(questionFile);
358
513
  await navigate.waitForDomIdle(2e3, 15e3);
359
514
  console.log("File uploaded successfully");
360
- await clickSubmitButton(page);
515
+ const didSubmit = await clickSubmitButton(page);
516
+ if (!didSubmit) {
517
+ throw new Error("Prompt was not submitted after file upload.");
518
+ }
361
519
  await navigate.waitForDomIdle(1e3, 3e4);
362
520
  await waitForInitialResponse(page);
363
521
  await handleStreamingResponse(page, responseFile);