binary-collections 2.0.10 → 2.0.12
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/.opencode/package.json +5 -0
- package/.puppeterrc.cjs +25 -0
- package/binaries/binary-executor.cjs +138 -3
- package/binaries/clean-nodemodule.cjs +138 -3
- package/binaries/clean-nodemodules.cjs +138 -3
- package/binaries/dev.cjs +138 -3
- package/binaries/empty.cjs +138 -3
- package/binaries/git-reduce-size.cjs +138 -3
- package/binaries/javakill.cjs +138 -3
- package/binaries/kill-night-crows.bat +7 -0
- package/binaries/kill-night-crows.ps1 +172 -0
- package/binaries/kill-process.cjs +138 -3
- package/binaries/nodekill.cjs +138 -3
- package/binaries/prod.cjs +138 -3
- package/binaries/py +111 -0
- package/binaries/py.cjs +178 -0
- package/binaries/py.cmd +49 -0
- package/binaries/rmfind.cjs +138 -3
- package/binaries/rmx +15 -1
- package/binaries/rmx.cjs +138 -3
- package/binaries/rmx.cmd +12 -0
- package/binaries/submodule-token.cjs +138 -3
- package/binaries/test-cjs +18 -0
- package/binaries/test-cjs.cjs +178 -0
- package/binaries/test-cjs.cmd +26 -0
- package/binaries/test-esm +16 -0
- package/binaries/test-esm.cjs +178 -0
- package/binaries/test-esm.cmd +23 -0
- package/binaries/yarn-clean +32 -0
- package/binaries/yarn-clean.cjs +178 -0
- package/binaries/yarn-clean.cmd +30 -0
- package/binaries/yarn-clean.py +166 -0
- package/binaries/yc +110 -0
- package/binaries/yc.cjs +178 -0
- package/lib/binary-collections/config.cjs +126 -0
- package/lib/binary-collections/config.mjs +7 -0
- package/lib/binary-collections/executeScript.cjs +19 -0
- package/lib/binary-collections/executeScript.d.cts +12 -0
- package/lib/binary-collections/executeScript.mjs +6 -0
- package/lib/binary-collections/findScript.cjs +284 -0
- package/lib/binary-collections/findScript.d.cts +12 -0
- package/lib/binary-collections/findScript.mjs +7 -0
- package/lib/binary-collections/listScript.cjs +266 -0
- package/lib/binary-collections/listScript.d.cts +19 -0
- package/lib/binary-collections/listScript.mjs +7 -0
- package/lib/binary-collections.cjs +342 -194
- package/lib/binary-collections.mjs +22 -268
- package/lib/changelog.cjs +61 -13
- package/lib/changelog.mjs +1 -1
- package/lib/{chunk-E6FDDAOO.mjs → chunk-2LSRSEXF.mjs} +2 -2
- package/lib/chunk-34IQDTLZ.mjs +27 -0
- package/lib/chunk-3HFFECCI.mjs +27 -0
- package/lib/{chunk-V3N3JEUF.mjs → chunk-5RTXZVCW.mjs} +60 -13
- package/lib/chunk-66KDU4TX.mjs +268 -0
- package/lib/chunk-6PU7BAHB.mjs +61 -0
- package/lib/{chunk-6HHJRKFB.mjs → chunk-BZWVHODJ.mjs} +4 -1
- package/lib/chunk-C6D2TTYU.mjs +32 -0
- package/lib/chunk-FB2WKVJD.mjs +158 -0
- package/lib/{chunk-66PAU5PS.mjs → chunk-G5UUEWUO.mjs} +9 -5
- package/lib/{chunk-HO6GHCOB.mjs → chunk-GAGABICI.mjs} +198 -63
- package/lib/chunk-H44UWUFY.mjs +105 -0
- package/lib/chunk-NCZPTKDV.mjs +79 -0
- package/lib/chunk-NGFK3EYW.mjs +28 -0
- package/lib/chunk-NVEG3LEZ.mjs +143 -0
- package/lib/chunk-OGXVGBRI.mjs +29 -0
- package/lib/chunk-OXV52GD5.mjs +62 -0
- package/lib/{chunk-PDSXF5HY.mjs → chunk-PDN26I7O.mjs} +1 -0
- package/lib/chunk-PXBMHE7O.mjs +35 -0
- package/lib/chunk-R5FJOR63.mjs +47 -0
- package/lib/chunk-SPTECFE5.mjs +180 -0
- package/lib/chunk-UXCFNAR6.mjs +55 -0
- package/lib/chunk-V2IBPCEV.mjs +39 -0
- package/lib/chunk-XPJGCDOD.mjs +14 -0
- package/lib/{chunk-AI4CVPJ7.mjs → chunk-ZDMWBSYF.mjs} +4 -4
- package/lib/chunk-ZOWVMII3.mjs +228 -0
- package/lib/clean-github-actions-caches-cli.cjs +465 -0
- package/lib/clean-github-actions-caches-cli.d.cts +1 -0
- package/lib/clean-github-actions-caches-cli.mjs +56 -0
- package/lib/clean-github-actions-caches.cjs +152 -160
- package/lib/clean-github-actions-caches.d.cts +15 -1
- package/lib/clean-github-actions-caches.mjs +4 -130
- package/lib/cross-env/command.cjs +63 -0
- package/lib/cross-env/command.d.ts +8 -0
- package/lib/cross-env/command.js +45 -0
- package/lib/cross-env/command.mjs +9 -0
- package/lib/cross-env/index.cjs +178 -0
- package/lib/cross-env/index.d.ts +8 -0
- package/lib/cross-env/index.js +102 -0
- package/lib/cross-env/index.mjs +101 -0
- package/lib/cross-env/variable.cjs +60 -0
- package/lib/cross-env/variable.d.ts +7 -0
- package/lib/cross-env/variable.js +59 -0
- package/lib/cross-env/variable.mjs +9 -0
- package/lib/del-gradle.cjs +61 -13
- package/lib/del-gradle.js +9 -8
- package/lib/del-gradle.mjs +1 -1
- package/lib/del-node-modules.cjs +143 -148
- package/lib/del-node-modules.js +210 -14
- package/lib/del-node-modules.mjs +148 -17
- package/lib/del-ps.cjs +61 -13
- package/lib/del-ps.js +9 -8
- package/lib/del-ps.mjs +1 -1
- package/lib/del-yarn-caches.cjs +61 -13
- package/lib/del-yarn-caches.js +2 -2
- package/lib/del-yarn-caches.mjs +1 -1
- package/lib/file/copy-cli.cjs +92 -0
- package/lib/file/copy-cli.d.mts +1 -0
- package/lib/file/copy-cli.mjs +55 -0
- package/lib/file/copy.cjs +56 -0
- package/lib/file/copy.d.mts +1 -0
- package/lib/file/copy.mjs +8 -0
- package/lib/file/move-cli.cjs +91 -0
- package/lib/file/move-cli.d.mts +1 -0
- package/lib/file/move-cli.mjs +55 -0
- package/lib/file/move.cjs +55 -0
- package/lib/file/move.d.mts +1 -0
- package/lib/file/move.mjs +8 -0
- package/lib/find-node-modules-cli.js +2 -1
- package/lib/free-chatgpt.cjs +259 -47
- package/lib/free-chatgpt.js +10 -10
- package/lib/free-chatgpt.mjs +2 -2
- package/lib/git/gitattributes.cjs +1 -0
- package/lib/git/gitattributes.d.cts +7 -2
- package/lib/git/gitattributes.mjs +1 -1
- package/lib/git/line-endings.cjs +2 -1
- package/lib/git/line-endings.mjs +2 -2
- package/lib/git/undo-commit-cli.cjs +110 -0
- package/lib/git/undo-commit-cli.d.ts +1 -0
- package/lib/git/undo-commit-cli.js +4 -0
- package/lib/git/undo-commit-cli.mjs +14 -0
- package/lib/git/undo-commit.cjs +81 -0
- package/lib/git/undo-commit.d.cts +1 -0
- package/lib/git/undo-commit.mjs +7 -0
- package/lib/git/undo-staged-cli.cjs +110 -0
- package/lib/git/undo-staged-cli.d.ts +1 -0
- package/lib/git/undo-staged-cli.js +4 -0
- package/lib/git/undo-staged-cli.mjs +14 -0
- package/lib/git/undo-staged.cjs +81 -0
- package/lib/git/undo-staged.d.cts +1 -0
- package/lib/git/undo-staged.mjs +7 -0
- package/lib/git/user-config.cjs +61 -14
- package/lib/git/user-config.mjs +2 -2
- package/lib/git-diff-cli.cjs +427 -75
- package/lib/git-diff-cli.d.ts +1 -0
- package/lib/git-diff-cli.js +1 -0
- package/lib/git-diff-cli.mjs +6 -4
- package/lib/git-diff.cjs +426 -75
- package/lib/git-diff.d.ts +2 -1
- package/lib/git-diff.js +91 -34
- package/lib/git-diff.mjs +5 -4
- package/lib/git-fix.cjs +64 -16
- package/lib/git-fix.mjs +10 -10
- package/lib/git-purge.cjs +61 -13
- package/lib/git-purge.mjs +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/kill-night-crows.cjs +87 -0
- package/lib/kill-night-crows.d.mts +1 -0
- package/lib/kill-night-crows.mjs +65 -0
- package/lib/node-cache-cleaner/npm.cjs +65 -0
- package/lib/node-cache-cleaner/npm.d.ts +2 -0
- package/lib/node-cache-cleaner/npm.js +41 -0
- package/lib/node-cache-cleaner/npm.mjs +10 -0
- package/lib/node-cache-cleaner/npx.cjs +89 -0
- package/lib/node-cache-cleaner/npx.d.ts +4 -0
- package/lib/node-cache-cleaner/npx.js +82 -0
- package/lib/{ps/index.d.mjs → node-cache-cleaner/npx.mjs} +6 -5
- package/lib/node-cache-cleaner/yarn.cjs +73 -0
- package/lib/node-cache-cleaner/yarn.d.ts +2 -0
- package/lib/node-cache-cleaner/yarn.js +62 -0
- package/lib/node-cache-cleaner/yarn.mjs +10 -0
- package/lib/node-cache-cleaner-cli.cjs +182 -0
- package/lib/node-cache-cleaner-cli.d.ts +2 -0
- package/lib/node-cache-cleaner-cli.js +60 -0
- package/lib/node-cache-cleaner-cli.mjs +56 -0
- package/lib/node-executor.cjs +91 -0
- package/lib/node-executor.d.cts +2 -0
- package/lib/node-executor.mjs +103 -0
- package/lib/npm-run-series.cjs +79 -39
- package/lib/npm-run-series.mjs +20 -6
- package/lib/package-resolutions-updater-cli.cjs +645 -0
- package/lib/package-resolutions-updater-cli.d.mts +1 -0
- package/lib/package-resolutions-updater-cli.mjs +102 -0
- package/lib/package-resolutions-updater.cjs +259 -133
- package/lib/package-resolutions-updater.d.mts +51 -1
- package/lib/package-resolutions-updater.mjs +18 -294
- package/lib/php-cs-fixer-staged.cjs +105 -0
- package/lib/php-cs-fixer-staged.d.cts +2 -0
- package/lib/php-cs-fixer-staged.mjs +117 -0
- package/lib/print-directory-tree.cjs +62 -14
- package/lib/print-directory-tree.mjs +2 -2
- package/lib/ps/connected-domain.d.ts +1 -1
- package/lib/ps/connected-domain.js +10 -10
- package/lib/ps/index.cjs +1 -1
- package/lib/ps/index.mjs +177 -171
- package/lib/ps/isWin.js +1 -1
- package/lib/ps/table-parser.js +6 -6
- package/lib/remove-module.cjs +61 -13
- package/lib/remove-module.mjs +1 -1
- package/lib/rm-node-module-cli.cjs +222 -0
- package/lib/rm-node-module-cli.d.cts +1 -0
- package/lib/rm-node-module-cli.mjs +89 -0
- package/lib/rm-node-modules.cjs +127 -0
- package/lib/rm-node-modules.d.cts +35 -0
- package/lib/{binary-collections-config.mjs → rm-node-modules.mjs} +3 -3
- package/lib/rmpath.cjs +63 -15
- package/lib/rmpath.mjs +2 -2
- package/lib/submodule-install.cjs +107 -47
- package/lib/submodule-install.mjs +48 -35
- package/lib/submodule-remove-cli.cjs +6 -3
- package/lib/submodule-remove-cli.js +3 -3
- package/lib/submodule-remove-cli.mjs +2 -3
- package/lib/submodule-remove.cjs +4 -1
- package/lib/submodule-remove.mjs +1 -1
- package/lib/utils/chatgpt.cjs +198 -34
- package/lib/utils/chatgpt.js +260 -93
- package/lib/utils/chatgpt.mjs +1 -1
- package/lib/utils/findEnvFiles.cjs +89 -0
- package/lib/utils/findEnvFiles.d.cts +19 -0
- package/lib/utils/findEnvFiles.mjs +6 -0
- package/lib/utils/findWorkspaceRoot.cjs +70 -0
- package/lib/utils/findWorkspaceRoot.d.ts +9 -0
- package/lib/utils/findWorkspaceRoot.js +57 -0
- package/lib/utils/findWorkspaceRoot.mjs +40 -0
- package/lib/utils/index.cjs +60 -13
- package/lib/utils/index.mjs +1 -1
- package/lib/utils/isGithubTokenValid.cjs +64 -0
- package/lib/utils/isGithubTokenValid.d.ts +7 -0
- package/lib/utils/isGithubTokenValid.js +48 -0
- package/lib/utils/isGithubTokenValid.mjs +36 -0
- package/lib/{ps/index.d.cjs → utils/isWindows.cjs} +17 -3
- package/lib/utils/isWindows.d.ts +5 -0
- package/lib/utils/isWindows.js +10 -0
- package/lib/utils/isWindows.mjs +8 -0
- package/lib/utils/runBash.cjs +53 -0
- package/lib/utils/runBash.d.cts +12 -0
- package/lib/utils/runBash.mjs +66 -0
- package/lib/yarn-per-branch-lock-installer.cjs +97 -0
- package/lib/yarn-per-branch-lock-installer.d.cts +2 -0
- package/lib/yarn-per-branch-lock-installer.mjs +109 -0
- package/lib/yarn-reinstall.cjs +61 -13
- package/lib/yarn-reinstall.mjs +1 -1
- package/package.json +133 -110
- package/readme.html +784 -0
- package/readme.md +116 -229
- package/releases/readme.md +1 -1
- package/requirements.txt +1 -0
- package/test/README.md +2 -2
- package/test-project/package.json +8 -2
- package/test-project/workspaces/workspace-a/package.json +135 -0
- package/test-project/workspaces/workspace-a/readme.md +20 -0
- package/test-project/workspaces/workspace-a/release/readme.md +42 -0
- package/test-project/workspaces/workspace-a/test/demo/package.json +25 -0
- package/test-project/workspaces/workspace-a/test/readme.md +12 -0
- package/test-project/workspaces/workspace-b/package.json +139 -0
- package/test-project/workspaces/workspace-b/readme.md +94 -0
- package/test-project/workspaces/workspace-b/requirements.txt +1 -0
- package/test-project/workspaces/workspace-b/test/sample-project/package.json +7 -0
- package/test-project/workspaces/workspace-b/themes/hexo-theme-flowbite/package.json +96 -0
- package/test-project/workspaces/workspace-b/themes/hexo-theme-flowbite/readme.md +156 -0
- package/tmp/rm-node-modules-test-project/package.json +17 -0
- package/tmp/rm-node-modules-test-project/packages/workspace-a/package.json +16 -0
- package/tmp/rm-node-modules-test-project/packages/workspace-b/package.json +16 -0
- package/tmp/test-repo/README.md +2 -35
- package/tmp/test-repo/package.json +13 -3
- package/docs-src/clean-github-actions-caches.md +0 -26
- package/docs-src/free-chatgpt.md +0 -26
- package/lib/binary-collections-config.cjs +0 -15
- package/lib/chunk-4EWQC6GZ.mjs +0 -382
- package/lib/chunk-4ZI7BQKQ.mjs +0 -381
- package/lib/chunk-5J2BEPY5.mjs +0 -83
- package/lib/chunk-AGZYRDC2.mjs +0 -323
- package/lib/chunk-BDCHCWHD.mjs +0 -136
- package/lib/chunk-BEZKJ25G.mjs +0 -140
- package/lib/chunk-DI5MDPSN.mjs +0 -386
- package/lib/chunk-GJTGHXRA.mjs +0 -356
- package/lib/chunk-HMRMTYZM.mjs +0 -40
- package/lib/chunk-HN52G2YL.mjs +0 -305
- package/lib/chunk-LEM5OMRP.mjs +0 -384
- package/lib/chunk-O6SWBEOQ.mjs +0 -81
- package/lib/chunk-RCP7DHVY.mjs +0 -190
- package/lib/chunk-SBNDSKG5.mjs +0 -136
- package/lib/chunk-U6SO4QEV.mjs +0 -320
- package/lib/chunk-XD6BJK6Q.mjs +0 -351
- package/lib/chunk-YXSFGA2D.mjs +0 -383
- package/lib/git/gitattributes.d.ts +0 -33
- package/lib/git/gitattributes.js +0 -223
- package/lib/ps/index.d.ts +0 -2
- package/lib/ps/index.js +0 -253
- package/tmp/typedoc/readme.md +0 -320
- /package/lib/{binary-collections-config.d.cts → binary-collections/config.d.cts} +0 -0
package/lib/utils/chatgpt.js
CHANGED
|
@@ -17,9 +17,31 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
17
17
|
const puppeteer_extra_1 = __importDefault(require("puppeteer-extra"));
|
|
18
18
|
const puppeteer_extra_plugin_stealth_1 = __importDefault(require("puppeteer-extra-plugin-stealth"));
|
|
19
19
|
const upath_1 = __importDefault(require("upath"));
|
|
20
|
-
const COOKIE_DIR = upath_1.default.join(process.cwd(),
|
|
21
|
-
const DEFAULT_COOKIE_PATH = upath_1.default.join(COOKIE_DIR,
|
|
20
|
+
const COOKIE_DIR = upath_1.default.join(process.cwd(), 'tmp', 'cookies');
|
|
21
|
+
const DEFAULT_COOKIE_PATH = upath_1.default.join(COOKIE_DIR, 'cookies.json');
|
|
22
|
+
const NAVIGATION_TIMEOUT_MS = 90000;
|
|
23
|
+
const NETWORK_IDLE_TIMEOUT_MS = 15000;
|
|
24
|
+
const MAX_INLINE_QUESTION_FILE_BYTES = 2 * 1024;
|
|
22
25
|
fs_extra_1.default.ensureDirSync(COOKIE_DIR);
|
|
26
|
+
/**
|
|
27
|
+
* Navigates to a page with a resilient strategy for apps that keep long-lived network connections.
|
|
28
|
+
*
|
|
29
|
+
* @param {import('puppeteer').Page} page - Puppeteer page instance.
|
|
30
|
+
* @param {string} url - URL to navigate to.
|
|
31
|
+
* @returns {Promise<void>} Resolves when the page is at least DOM-ready.
|
|
32
|
+
*/
|
|
33
|
+
function gotoWithFallback(page, url) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
yield page.goto(url, { waitUntil: 'domcontentloaded', timeout: NAVIGATION_TIMEOUT_MS });
|
|
36
|
+
// Best effort: settle initial bursty requests without hard-failing on persistent streams.
|
|
37
|
+
try {
|
|
38
|
+
yield page.waitForNetworkIdle({ idleTime: 1000, timeout: NETWORK_IDLE_TIMEOUT_MS });
|
|
39
|
+
}
|
|
40
|
+
catch (_a) {
|
|
41
|
+
// Ignore network-idle timeouts because ChatGPT keeps active connections open.
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
23
45
|
/**
|
|
24
46
|
* Saves cookies from a Puppeteer page to a specified file path.
|
|
25
47
|
*
|
|
@@ -63,8 +85,8 @@ function navigatePage(page, url) {
|
|
|
63
85
|
if (cookies) {
|
|
64
86
|
yield page.setCookie(...cookies);
|
|
65
87
|
}
|
|
66
|
-
// Navigate
|
|
67
|
-
yield page
|
|
88
|
+
// Navigate with fallback for pages that keep persistent network connections.
|
|
89
|
+
yield gotoWithFallback(page, url);
|
|
68
90
|
// Inject DOM mutation observer to handle dynamic content
|
|
69
91
|
yield page.evaluate(() => {
|
|
70
92
|
window.__domStillUpdating = true;
|
|
@@ -104,7 +126,7 @@ function navigatePage(page, url) {
|
|
|
104
126
|
}
|
|
105
127
|
yield new Promise((r) => setTimeout(r, 200)); // poll every 200ms
|
|
106
128
|
}
|
|
107
|
-
throw new Error(
|
|
129
|
+
throw new Error('DOM did not stabilize within timeout');
|
|
108
130
|
});
|
|
109
131
|
return { waitForDomIdle };
|
|
110
132
|
});
|
|
@@ -144,31 +166,41 @@ function _restoreCookies(page_1) {
|
|
|
144
166
|
*/
|
|
145
167
|
function writeQuestion(page, question) {
|
|
146
168
|
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
-
const
|
|
148
|
-
const promptTextarea = yield page.waitForSelector("#prompt-textarea", { timeout: 30000 });
|
|
169
|
+
const promptTextarea = yield page.waitForSelector('#prompt-textarea', { timeout: 30000 });
|
|
149
170
|
if (!promptTextarea) {
|
|
150
|
-
console.log(
|
|
151
|
-
}
|
|
152
|
-
// Clear the prompt textarea
|
|
153
|
-
yield page.evaluate(() => {
|
|
154
|
-
document.querySelector("#prompt-textarea").innerHTML = `<p></p>`;
|
|
155
|
-
});
|
|
156
|
-
// Check if the question has newlines
|
|
157
|
-
if (questions.length === 1) {
|
|
158
|
-
// If there's only one line, type it directly
|
|
159
|
-
yield page.type("#prompt-textarea", questions[0], { delay: 100 });
|
|
171
|
+
console.log('Cannot find the prompt input on the webpage. Please check whether you have access to chat.openai.com without logging in via your browser.');
|
|
160
172
|
return;
|
|
161
173
|
}
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
// Inject the full prompt instantly and emit input-like events so the UI reacts.
|
|
175
|
+
yield page.evaluate((text) => {
|
|
176
|
+
const promptEl = document.querySelector('#prompt-textarea');
|
|
177
|
+
if (!promptEl) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
promptEl.focus();
|
|
181
|
+
promptEl.innerHTML = '';
|
|
182
|
+
const lines = String(text).split('\n');
|
|
183
|
+
for (const line of lines) {
|
|
184
|
+
const p = document.createElement('p');
|
|
185
|
+
p.textContent = line;
|
|
186
|
+
promptEl.appendChild(p);
|
|
171
187
|
}
|
|
188
|
+
promptEl.dispatchEvent(new InputEvent('beforeinput', { bubbles: true, inputType: 'insertFromPaste', data: text }));
|
|
189
|
+
promptEl.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste', data: text }));
|
|
190
|
+
promptEl.dispatchEvent(new Event('change', { bubbles: true }));
|
|
191
|
+
}, question);
|
|
192
|
+
// If the app state did not pick up the DOM injection, use keyboard insertion as a reliable fallback.
|
|
193
|
+
const hasPromptText = yield page.evaluate(() => {
|
|
194
|
+
const promptEl = document.querySelector('#prompt-textarea');
|
|
195
|
+
return Boolean(promptEl && promptEl.textContent && promptEl.textContent.trim().length > 0);
|
|
196
|
+
});
|
|
197
|
+
if (!hasPromptText) {
|
|
198
|
+
console.log('Prompt state not updated by DOM injection. Falling back to keyboard insertText.');
|
|
199
|
+
yield promptTextarea.click({ clickCount: 1 });
|
|
200
|
+
yield page.keyboard.down('Control');
|
|
201
|
+
yield page.keyboard.press('KeyA');
|
|
202
|
+
yield page.keyboard.up('Control');
|
|
203
|
+
yield page.keyboard.insertText(question);
|
|
172
204
|
}
|
|
173
205
|
});
|
|
174
206
|
}
|
|
@@ -176,29 +208,121 @@ function writeQuestion(page, question) {
|
|
|
176
208
|
* Clicks the submit button in ChatGPT interface, trying different button variants.
|
|
177
209
|
*
|
|
178
210
|
* @param {import('puppeteer').Page} page - Puppeteer page instance.
|
|
179
|
-
* @returns {Promise<
|
|
211
|
+
* @returns {Promise<boolean>} Resolves to true when submission is detected, otherwise false.
|
|
180
212
|
*/
|
|
181
213
|
function clickSubmitButton(page) {
|
|
182
214
|
return __awaiter(this, void 0, void 0, function* () {
|
|
215
|
+
console.log('Attempting to click the submit button...');
|
|
183
216
|
try {
|
|
184
|
-
const
|
|
185
|
-
|
|
217
|
+
const userMessageCountBefore = yield page.$$eval('[data-message-author-role="user"]', (elements) => elements.length);
|
|
218
|
+
const waitForSubmit = (...args_1) => __awaiter(this, [...args_1], void 0, function* (timeout = 5000) {
|
|
219
|
+
try {
|
|
220
|
+
yield page.waitForFunction((previousCount) => {
|
|
221
|
+
const currentCount = document.querySelectorAll('[data-message-author-role="user"]').length;
|
|
222
|
+
return currentCount > previousCount;
|
|
223
|
+
}, { timeout }, userMessageCountBefore);
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
catch (_a) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
186
229
|
});
|
|
187
|
-
|
|
188
|
-
|
|
230
|
+
yield page
|
|
231
|
+
.waitForFunction(() => {
|
|
232
|
+
const candidates = [
|
|
233
|
+
document.querySelector('[data-testid="fruitjuice-send-button"]'),
|
|
234
|
+
document.querySelector('#composer-submit-button'),
|
|
235
|
+
document.querySelector('[data-testid="send-button"]')
|
|
236
|
+
].filter(Boolean);
|
|
237
|
+
return candidates.some((button) => {
|
|
238
|
+
const isDisabled = button.disabled || button.getAttribute('aria-disabled') === 'true';
|
|
239
|
+
const isVisible = button.offsetParent !== null;
|
|
240
|
+
return !isDisabled && isVisible;
|
|
241
|
+
});
|
|
242
|
+
}, { timeout: 5000 })
|
|
243
|
+
.catch(() => {
|
|
244
|
+
// Continue to diagnostics below even if no enabled button was found within timeout.
|
|
245
|
+
});
|
|
246
|
+
const buttonDetails = yield page.evaluate(() => {
|
|
247
|
+
const selectors = [
|
|
248
|
+
'[data-testid="fruitjuice-send-button"]',
|
|
249
|
+
'#composer-submit-button',
|
|
250
|
+
'[data-testid="send-button"]'
|
|
251
|
+
];
|
|
252
|
+
const details = selectors.map((selector) => {
|
|
253
|
+
const el = document.querySelector(selector);
|
|
254
|
+
const exists = Boolean(el);
|
|
255
|
+
const disabled = exists ? Boolean(el.disabled || el.getAttribute('aria-disabled') === 'true') : null;
|
|
256
|
+
const visible = exists ? el.offsetParent !== null : null;
|
|
257
|
+
return { selector, exists, disabled, visible };
|
|
258
|
+
});
|
|
259
|
+
return details;
|
|
189
260
|
});
|
|
190
|
-
|
|
191
|
-
|
|
261
|
+
console.log(`Submit button details: ${JSON.stringify(buttonDetails)}`);
|
|
262
|
+
const clickable = buttonDetails.find((item) => item.exists && item.visible && item.disabled === false);
|
|
263
|
+
const selectedSelector = clickable ? clickable.selector : null;
|
|
264
|
+
if (selectedSelector) {
|
|
265
|
+
yield page.click(selectedSelector);
|
|
266
|
+
console.log(`Clicked submit button selector: ${selectedSelector}`);
|
|
267
|
+
if (yield waitForSubmit(5000)) {
|
|
268
|
+
console.log('Submission detected after selector click.');
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
// Fallback: force a DOM click in case pointer-interception blocked page.click.
|
|
272
|
+
const forcedClickWorked = yield page.evaluate((selector) => {
|
|
273
|
+
const el = document.querySelector(selector);
|
|
274
|
+
if (!el) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
el.click();
|
|
278
|
+
return true;
|
|
279
|
+
}, selectedSelector);
|
|
280
|
+
if (forcedClickWorked) {
|
|
281
|
+
console.log(`Forced DOM click on selector: ${selectedSelector}`);
|
|
282
|
+
if (yield waitForSubmit(5000)) {
|
|
283
|
+
console.log('Submission detected after forced DOM click.');
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
192
287
|
}
|
|
193
|
-
|
|
194
|
-
|
|
288
|
+
console.log('Submit button path did not submit. Trying Enter key fallback on prompt.');
|
|
289
|
+
yield page.focus('#prompt-textarea');
|
|
290
|
+
yield page.keyboard.press('Enter');
|
|
291
|
+
if (yield waitForSubmit(5000)) {
|
|
292
|
+
console.log('Submission detected after Enter key fallback.');
|
|
293
|
+
return true;
|
|
195
294
|
}
|
|
196
|
-
|
|
197
|
-
|
|
295
|
+
// Final fallback: submit the nearest composer form.
|
|
296
|
+
const didRequestSubmit = yield page.evaluate(() => {
|
|
297
|
+
const prompt = document.querySelector('#prompt-textarea');
|
|
298
|
+
if (!prompt) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
const form = prompt.closest('form');
|
|
302
|
+
if (!form) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
if (typeof form.requestSubmit === 'function') {
|
|
306
|
+
form.requestSubmit();
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
form.submit();
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
});
|
|
313
|
+
if (didRequestSubmit) {
|
|
314
|
+
console.log('Triggered form submit fallback.');
|
|
315
|
+
if (yield waitForSubmit(5000)) {
|
|
316
|
+
console.log('Submission detected after form submit fallback.');
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
198
319
|
}
|
|
320
|
+
console.log('Failed to submit prompt after all strategies.');
|
|
321
|
+
return false;
|
|
199
322
|
}
|
|
200
323
|
catch (e) {
|
|
201
324
|
console.log(`Failed to click the send button: ${e}`);
|
|
325
|
+
return false;
|
|
202
326
|
}
|
|
203
327
|
});
|
|
204
328
|
}
|
|
@@ -229,16 +353,16 @@ function waitForInitialResponse(page_1) {
|
|
|
229
353
|
const currentMessageCount = assistantMessages.length;
|
|
230
354
|
if (currentMessageCount > messageCount) {
|
|
231
355
|
const lastMessage = assistantMessages[assistantMessages.length - 1];
|
|
232
|
-
const isThinking = yield lastMessage.$(
|
|
356
|
+
const isThinking = yield lastMessage.$('.result-thinking');
|
|
233
357
|
if (!isThinking) {
|
|
234
|
-
lastMessageId = yield page.evaluate((element) => element.getAttribute(
|
|
358
|
+
lastMessageId = yield page.evaluate((element) => element.getAttribute('data-message-id'), lastMessage);
|
|
235
359
|
messageCount = currentMessageCount;
|
|
236
360
|
return;
|
|
237
361
|
}
|
|
238
362
|
}
|
|
239
363
|
yield sleep(100);
|
|
240
364
|
}
|
|
241
|
-
console.log(
|
|
365
|
+
console.log('Timed out waiting for the initial response.');
|
|
242
366
|
});
|
|
243
367
|
}
|
|
244
368
|
/**
|
|
@@ -249,15 +373,15 @@ function waitForInitialResponse(page_1) {
|
|
|
249
373
|
* @returns {Promise<void>} Resolves when streaming is complete.
|
|
250
374
|
*/
|
|
251
375
|
function handleStreamingResponse(page_1) {
|
|
252
|
-
return __awaiter(this, arguments, void 0, function* (page, outputFile = upath_1.default.join(process.cwd(),
|
|
253
|
-
let previousText =
|
|
254
|
-
let completeResponse =
|
|
376
|
+
return __awaiter(this, arguments, void 0, function* (page, outputFile = upath_1.default.join(process.cwd(), 'tmp/response.txt')) {
|
|
377
|
+
let previousText = '';
|
|
378
|
+
let completeResponse = '';
|
|
255
379
|
let newContentDetected = false;
|
|
256
380
|
while (!newContentDetected) {
|
|
257
381
|
const assistantMessages = yield page.$$('[data-message-author-role="assistant"]');
|
|
258
382
|
if (assistantMessages.length > 0) {
|
|
259
383
|
const lastMessage = assistantMessages[assistantMessages.length - 1];
|
|
260
|
-
const currentMessageId = yield page.evaluate((element) => element.getAttribute(
|
|
384
|
+
const currentMessageId = yield page.evaluate((element) => element.getAttribute('data-message-id'), lastMessage);
|
|
261
385
|
if (currentMessageId === lastMessageId) {
|
|
262
386
|
const currentText = yield page.evaluate((element) => element.textContent, lastMessage);
|
|
263
387
|
console.log(`Current text: ${currentText}`);
|
|
@@ -270,7 +394,7 @@ function handleStreamingResponse(page_1) {
|
|
|
270
394
|
}
|
|
271
395
|
}
|
|
272
396
|
previousText = currentText;
|
|
273
|
-
const isStreaming = yield lastMessage.$(
|
|
397
|
+
const isStreaming = yield lastMessage.$('.result-streaming');
|
|
274
398
|
if (!isStreaming) {
|
|
275
399
|
newContentDetected = true;
|
|
276
400
|
}
|
|
@@ -283,7 +407,7 @@ function handleStreamingResponse(page_1) {
|
|
|
283
407
|
}
|
|
284
408
|
if (!is_streaming) {
|
|
285
409
|
console.log(completeResponse.trim());
|
|
286
|
-
console.log(
|
|
410
|
+
console.log('\n\n');
|
|
287
411
|
fs_extra_1.default.ensureDirSync(upath_1.default.dirname(outputFile));
|
|
288
412
|
fs_extra_1.default.writeFileSync(outputFile, completeResponse.trim());
|
|
289
413
|
console.log(`Response saved to ${outputFile}`);
|
|
@@ -315,41 +439,46 @@ function isLoggedIn(page) {
|
|
|
315
439
|
*/
|
|
316
440
|
function createBrowser() {
|
|
317
441
|
return __awaiter(this, arguments, void 0, function* (browserOptions = {}) {
|
|
442
|
+
const windowsChromeExecutable = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
|
|
443
|
+
const hasWindowsChrome = process.platform === 'win32' && fs_extra_1.default.existsSync(windowsChromeExecutable);
|
|
318
444
|
/**
|
|
319
445
|
* @type {Parameters<import("puppeteer-extra").VanillaPuppeteer["launch"]>[0]}
|
|
320
446
|
*/
|
|
321
|
-
const defaultOptions = Object.assign({ headless: false, userDataDir: upath_1.default.join(process.cwd(),
|
|
447
|
+
const defaultOptions = Object.assign({ headless: false, defaultViewport: null, userDataDir: upath_1.default.join(process.cwd(), 'tmp/puppeteer-profile'),
|
|
322
448
|
// Windows-specific options to handle browser launch issues
|
|
323
449
|
args: [
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
450
|
+
'--start-maximized',
|
|
451
|
+
'--no-sandbox',
|
|
452
|
+
'--disable-setuid-sandbox',
|
|
453
|
+
'--disable-dev-shm-usage',
|
|
454
|
+
'--disable-accelerated-2d-canvas',
|
|
455
|
+
'--no-first-run',
|
|
456
|
+
'--no-zygote',
|
|
457
|
+
'--disable-gpu',
|
|
458
|
+
'--disable-background-timer-throttling',
|
|
459
|
+
'--disable-backgrounding-occluded-windows',
|
|
460
|
+
'--disable-renderer-backgrounding'
|
|
461
|
+
], ignoreDefaultArgs: ['--disable-extensions'] }, (hasWindowsChrome && {
|
|
462
|
+
// Prefer local Chrome installation when present on Windows.
|
|
463
|
+
executablePath: windowsChromeExecutable
|
|
337
464
|
}));
|
|
338
465
|
try {
|
|
339
466
|
return yield puppeteer_extra_1.default.use((0, puppeteer_extra_plugin_stealth_1.default)()).launch(Object.assign(Object.assign({}, defaultOptions), browserOptions));
|
|
340
467
|
}
|
|
341
468
|
catch (_error) {
|
|
342
|
-
console.error(
|
|
469
|
+
console.error('Failed to launch browser with default options. Trying fallback options...');
|
|
343
470
|
// Fallback: Try with minimal options
|
|
344
471
|
try {
|
|
345
|
-
return yield puppeteer_extra_1.default.use((0, puppeteer_extra_plugin_stealth_1.default)()).launch(Object.assign({ headless: browserOptions.headless || false, args: [
|
|
472
|
+
return yield puppeteer_extra_1.default.use((0, puppeteer_extra_plugin_stealth_1.default)()).launch(Object.assign(Object.assign({ headless: browserOptions.headless || false, defaultViewport: null, args: ['--start-maximized', '--no-sandbox', '--disable-setuid-sandbox'], ignoreDefaultArgs: false }, (hasWindowsChrome && {
|
|
473
|
+
executablePath: windowsChromeExecutable
|
|
474
|
+
})), browserOptions));
|
|
346
475
|
}
|
|
347
476
|
catch (fallbackError) {
|
|
348
|
-
console.error(
|
|
349
|
-
console.error(
|
|
350
|
-
console.error(
|
|
351
|
-
console.error(
|
|
352
|
-
console.error(
|
|
477
|
+
console.error('Browser launch failed completely. Common solutions:');
|
|
478
|
+
console.error('1. Install Google Chrome if not installed');
|
|
479
|
+
console.error('2. Update Node.js to the latest version');
|
|
480
|
+
console.error('3. Try running: npm install puppeteer --force');
|
|
481
|
+
console.error('4. Check if antivirus is blocking browser launch');
|
|
353
482
|
throw new Error(`Browser launch failed: ${fallbackError.message}`);
|
|
354
483
|
}
|
|
355
484
|
}
|
|
@@ -364,7 +493,7 @@ function loginToChatGpt() {
|
|
|
364
493
|
return __awaiter(this, void 0, void 0, function* () {
|
|
365
494
|
const browser = yield createBrowser({ headless: false });
|
|
366
495
|
const page = (yield browser.pages()).length > 0 ? (yield browser.pages())[0] : yield browser.newPage();
|
|
367
|
-
const url =
|
|
496
|
+
const url = 'https://chat.openai.com';
|
|
368
497
|
const navigate = yield navigatePage(page, url);
|
|
369
498
|
// Wait for page to fully load before checking login status
|
|
370
499
|
yield navigate.waitForDomIdle(2000, 10000);
|
|
@@ -373,14 +502,20 @@ function loginToChatGpt() {
|
|
|
373
502
|
return document.querySelector('[data-testid="login-button"]') !== null;
|
|
374
503
|
});
|
|
375
504
|
if (loginButtonExists) {
|
|
376
|
-
console.log(
|
|
505
|
+
console.log('Login button found, clicking to log in...');
|
|
377
506
|
yield page.click('[data-testid="login-button"]');
|
|
378
|
-
// Wait for the login process to complete
|
|
379
|
-
yield page.waitForNavigation({ waitUntil:
|
|
380
|
-
|
|
507
|
+
// Wait for the login process to complete without requiring full network idleness.
|
|
508
|
+
yield page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: NAVIGATION_TIMEOUT_MS });
|
|
509
|
+
try {
|
|
510
|
+
yield page.waitForNetworkIdle({ idleTime: 1000, timeout: NETWORK_IDLE_TIMEOUT_MS });
|
|
511
|
+
}
|
|
512
|
+
catch (_a) {
|
|
513
|
+
// Ignore: authentication pages can keep background connections active.
|
|
514
|
+
}
|
|
515
|
+
console.log('Login process completed.');
|
|
381
516
|
}
|
|
382
517
|
else {
|
|
383
|
-
console.log(
|
|
518
|
+
console.log('No login required - user appears to be already logged in.');
|
|
384
519
|
}
|
|
385
520
|
});
|
|
386
521
|
}
|
|
@@ -414,31 +549,57 @@ function runChatGpt() {
|
|
|
414
549
|
const headless = chatgptOptions.headless !== undefined ? chatgptOptions.headless : true;
|
|
415
550
|
const questionFile = chatgptOptions.questionFile;
|
|
416
551
|
let question = chatgptOptions.question;
|
|
417
|
-
|
|
552
|
+
let shouldUploadQuestionFile = Boolean(questionFile);
|
|
553
|
+
const responseFile = chatgptOptions.responseFile || upath_1.default.join(process.cwd(), 'tmp', 'response.txt');
|
|
418
554
|
// Validate input parameters
|
|
419
555
|
const noInputProvided = !question && !questionFile;
|
|
420
556
|
const questionIsEmpty = question && question.trim().length === 0;
|
|
421
557
|
const questionFileIsEmpty = questionFile && questionFile.trim().length === 0;
|
|
422
558
|
if (noInputProvided || questionIsEmpty || questionFileIsEmpty) {
|
|
423
|
-
throw new Error(
|
|
559
|
+
throw new Error('You must provide a question or a question file.');
|
|
560
|
+
}
|
|
561
|
+
// For small files, send content as plain text to avoid file-upload login requirements.
|
|
562
|
+
if (!question && questionFile) {
|
|
563
|
+
if (!fs_extra_1.default.existsSync(questionFile)) {
|
|
564
|
+
throw new Error(`Question file does not exist: ${questionFile}`);
|
|
565
|
+
}
|
|
566
|
+
const questionFileStats = fs_extra_1.default.statSync(questionFile);
|
|
567
|
+
if (questionFileStats.size <= MAX_INLINE_QUESTION_FILE_BYTES) {
|
|
568
|
+
question = fs_extra_1.default.readFileSync(questionFile, 'utf8').trim();
|
|
569
|
+
if (!question) {
|
|
570
|
+
throw new Error('Question file is empty.');
|
|
571
|
+
}
|
|
572
|
+
shouldUploadQuestionFile = false;
|
|
573
|
+
console.log(`Question file is ${questionFileStats.size} bytes (<= ${MAX_INLINE_QUESTION_FILE_BYTES}). Sending as text prompt.`);
|
|
574
|
+
}
|
|
424
575
|
}
|
|
425
576
|
let browser;
|
|
426
577
|
try {
|
|
427
578
|
browser = yield createBrowser({ headless });
|
|
428
579
|
}
|
|
429
580
|
catch (error) {
|
|
430
|
-
console.error(
|
|
431
|
-
console.error(
|
|
432
|
-
console.error(
|
|
433
|
-
console.error(
|
|
434
|
-
console.error(
|
|
435
|
-
console.error(
|
|
581
|
+
console.error('Error running ChatGPT:', error);
|
|
582
|
+
console.error('\nTroubleshooting steps:');
|
|
583
|
+
console.error('1. Make sure Google Chrome is installed');
|
|
584
|
+
console.error('2. Try running: yarn add puppeteer --force');
|
|
585
|
+
console.error('3. Check if your antivirus is blocking the browser');
|
|
586
|
+
console.error('4. Close any running Chrome instances and try again');
|
|
436
587
|
throw error;
|
|
437
588
|
}
|
|
589
|
+
const allPages = yield browser.pages();
|
|
438
590
|
/** @type {import('puppeteer').Page} */
|
|
439
|
-
const page =
|
|
591
|
+
const page = allPages.length > 0 ? allPages[0] : yield browser.newPage();
|
|
592
|
+
yield page.bringToFront();
|
|
593
|
+
// Close other pages if more than one page is open.
|
|
594
|
+
if (allPages.length > 1) {
|
|
595
|
+
for (const p of allPages) {
|
|
596
|
+
if (p !== page) {
|
|
597
|
+
yield p.close();
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
440
601
|
try {
|
|
441
|
-
const url =
|
|
602
|
+
const url = 'https://chat.openai.com';
|
|
442
603
|
const navigate = yield navigatePage(page, url);
|
|
443
604
|
// Check temporary chat - wait for page to load and try to click temporary chat button
|
|
444
605
|
yield navigate.waitForDomIdle(2000, 15000);
|
|
@@ -446,11 +607,11 @@ function runChatGpt() {
|
|
|
446
607
|
const tempChatButton = yield page.$('button[aria-label="Turn on temporary chat"]');
|
|
447
608
|
if (tempChatButton) {
|
|
448
609
|
yield page.evaluate((el) => el.click(), tempChatButton);
|
|
449
|
-
console.log(
|
|
610
|
+
console.log('Successfully clicked temporary chat button');
|
|
450
611
|
yield navigate.waitForDomIdle(1000, 10000);
|
|
451
612
|
}
|
|
452
613
|
else {
|
|
453
|
-
console.log(
|
|
614
|
+
console.log('Temporary chat button not found, proceeding without it.');
|
|
454
615
|
}
|
|
455
616
|
}
|
|
456
617
|
catch (error) {
|
|
@@ -459,7 +620,10 @@ function runChatGpt() {
|
|
|
459
620
|
if (question) {
|
|
460
621
|
yield writeQuestion(page, question);
|
|
461
622
|
// Submit the question
|
|
462
|
-
yield clickSubmitButton(page);
|
|
623
|
+
const didSubmit = yield clickSubmitButton(page);
|
|
624
|
+
if (!didSubmit) {
|
|
625
|
+
throw new Error('Prompt was not submitted. The composer button may be disabled or blocked.');
|
|
626
|
+
}
|
|
463
627
|
yield navigate.waitForDomIdle(1000, 30000); // Wait for DOM to stabilize
|
|
464
628
|
// Wait for the initial response
|
|
465
629
|
yield waitForInitialResponse(page);
|
|
@@ -468,14 +632,14 @@ function runChatGpt() {
|
|
|
468
632
|
// Save cookies for this host at the end
|
|
469
633
|
yield saveCookies(page, getCookiePathForUrl(url));
|
|
470
634
|
}
|
|
471
|
-
else if (questionFile) {
|
|
635
|
+
else if (shouldUploadQuestionFile && questionFile) {
|
|
472
636
|
// Wait for page to fully load before checking login status
|
|
473
637
|
yield navigate.waitForDomIdle(2000, 10000);
|
|
474
638
|
// Check if logged in
|
|
475
639
|
const isUserLoggedIn = yield isLoggedIn(page);
|
|
476
|
-
console.log(`Login status: ${isUserLoggedIn ?
|
|
640
|
+
console.log(`Login status: ${isUserLoggedIn ? 'Logged in' : 'Not logged in'}`);
|
|
477
641
|
if (!isUserLoggedIn) {
|
|
478
|
-
console.log(
|
|
642
|
+
console.log('Not logged in. Please log in to ChatGPT in the browser window, then close it and run the command again.');
|
|
479
643
|
return loginToChatGpt();
|
|
480
644
|
}
|
|
481
645
|
// Upload the question file
|
|
@@ -490,7 +654,7 @@ function runChatGpt() {
|
|
|
490
654
|
let clicked = false;
|
|
491
655
|
for (const item of menuItems) {
|
|
492
656
|
const text = yield page.evaluate((el) => el.innerText, item);
|
|
493
|
-
if (text && text.includes(
|
|
657
|
+
if (text && text.includes('Add photos') && text.includes('files')) {
|
|
494
658
|
yield item.hover();
|
|
495
659
|
clicked = true;
|
|
496
660
|
break;
|
|
@@ -510,16 +674,19 @@ function runChatGpt() {
|
|
|
510
674
|
yield fileInput.uploadFile(questionFile);
|
|
511
675
|
// Wait for the file to be processed
|
|
512
676
|
yield navigate.waitForDomIdle(2000, 15000);
|
|
513
|
-
console.log(
|
|
677
|
+
console.log('File uploaded successfully');
|
|
514
678
|
// Optionally submit after file upload
|
|
515
|
-
yield clickSubmitButton(page);
|
|
679
|
+
const didSubmit = yield clickSubmitButton(page);
|
|
680
|
+
if (!didSubmit) {
|
|
681
|
+
throw new Error('Prompt was not submitted after file upload.');
|
|
682
|
+
}
|
|
516
683
|
yield navigate.waitForDomIdle(1000, 30000);
|
|
517
684
|
// Wait for and handle response
|
|
518
685
|
yield waitForInitialResponse(page);
|
|
519
686
|
yield handleStreamingResponse(page, responseFile);
|
|
520
687
|
}
|
|
521
688
|
else {
|
|
522
|
-
console.log(
|
|
689
|
+
console.log('Could not find file input element');
|
|
523
690
|
}
|
|
524
691
|
}
|
|
525
692
|
catch (error) {
|
package/lib/utils/chatgpt.mjs
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/utils/findEnvFiles.cjs
|
|
2
|
+
var fs = require("fs");
|
|
3
|
+
var path = require("path");
|
|
4
|
+
var glob = require("glob");
|
|
5
|
+
var DEFAULT_IGNORES = [
|
|
6
|
+
"**/node_modules/**",
|
|
7
|
+
"**/.git/**",
|
|
8
|
+
"**/.yarn/**",
|
|
9
|
+
"**/.pnpm/**",
|
|
10
|
+
"**/dist/**",
|
|
11
|
+
"**/build/**",
|
|
12
|
+
"**/coverage/**",
|
|
13
|
+
"**/vendor/**",
|
|
14
|
+
"**/tmp/**",
|
|
15
|
+
"**/.cache/**",
|
|
16
|
+
"**/assets/**",
|
|
17
|
+
"**/logs/**",
|
|
18
|
+
"**/output/**",
|
|
19
|
+
"**/public/**",
|
|
20
|
+
"**/static/**",
|
|
21
|
+
"**/temp/**",
|
|
22
|
+
"**/backup/**",
|
|
23
|
+
"**/backups/**",
|
|
24
|
+
"**/examples/**",
|
|
25
|
+
"**/docs/**",
|
|
26
|
+
"**/tests/**",
|
|
27
|
+
"**/__tests__/**",
|
|
28
|
+
"**/spec/**",
|
|
29
|
+
"**/__specs__/**",
|
|
30
|
+
"**/scripts/**",
|
|
31
|
+
"**/bin/**",
|
|
32
|
+
"**/hooks/**",
|
|
33
|
+
"**/config/**",
|
|
34
|
+
"**/configs/**",
|
|
35
|
+
"**/settings/**",
|
|
36
|
+
"**/.vscode/**",
|
|
37
|
+
"**/.idea/**"
|
|
38
|
+
];
|
|
39
|
+
function findEnvFiles(startDir = process.cwd(), filter) {
|
|
40
|
+
const found = /* @__PURE__ */ new Set();
|
|
41
|
+
function addFile(file) {
|
|
42
|
+
const normalized = path.normalize(file);
|
|
43
|
+
if (typeof filter === "function" && !filter(normalized)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
found.add(normalized);
|
|
47
|
+
}
|
|
48
|
+
let current = path.resolve(startDir);
|
|
49
|
+
while (true) {
|
|
50
|
+
const envPath = path.join(current, ".env");
|
|
51
|
+
if (fs.existsSync(envPath)) {
|
|
52
|
+
addFile(envPath);
|
|
53
|
+
}
|
|
54
|
+
const parent = path.dirname(current);
|
|
55
|
+
if (parent === current) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
current = parent;
|
|
59
|
+
}
|
|
60
|
+
const files = glob.globSync("**/.env*", {
|
|
61
|
+
cwd: startDir,
|
|
62
|
+
absolute: true,
|
|
63
|
+
nodir: true,
|
|
64
|
+
ignore: DEFAULT_IGNORES
|
|
65
|
+
});
|
|
66
|
+
for (const file of files) {
|
|
67
|
+
addFile(file);
|
|
68
|
+
}
|
|
69
|
+
return [...found];
|
|
70
|
+
}
|
|
71
|
+
function findEnvWithToken(startDir = process.cwd(), tokenName = "GITHUB_TOKEN") {
|
|
72
|
+
const envFiles = findEnvFiles(startDir);
|
|
73
|
+
return envFiles.find((file) => {
|
|
74
|
+
try {
|
|
75
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
76
|
+
const regex = new RegExp(`^\\s*${tokenName}\\s*=`, "m");
|
|
77
|
+
return regex.test(content);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.warn(`Failed to read ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
module.exports = {
|
|
85
|
+
DEFAULT_IGNORES,
|
|
86
|
+
findEnvFiles,
|
|
87
|
+
findEnvWithToken,
|
|
88
|
+
default: findEnvFiles
|
|
89
|
+
};
|