@youdie006/prodex 0.16.25 → 0.16.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chatgpt-browser.js +40 -5
- package/dist/cli-help.js +2 -2
- package/dist/cli-pro.js +10 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -240,7 +240,7 @@ prodex pro browser models
|
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
- `--model` picks the composer model by its exact menu label. `Pro` is verified end-to-end. Models whose menu entry opens a submenu of variants (for example GPT-5.5) are rejected with a clear error instead of silently keeping the previous model; direct variant selection is planned.
|
|
243
|
-
- `--pro-mode 기본|확장` selects the Pro sub-mode where the ChatGPT picker exposes one: sub-modes belong to the GPT-5.5 generation ("Pro Standard/Extended use GPT-5.5 Pro" per OpenAI docs), so with the GPT-5.6 generation selected the picker shows a single Pro and this flag fails with guidance. Any effective Pro selection (`--model Pro` or a sub-mode) raises the default `--timeout-ms` to
|
|
243
|
+
- `--pro-mode 기본|확장` selects the Pro sub-mode where the ChatGPT picker exposes one: sub-modes belong to the GPT-5.5 generation ("Pro Standard/Extended use GPT-5.5 Pro" per OpenAI docs), so with the GPT-5.6 generation selected the picker shows a single Pro and this flag fails with guidance. Any effective Pro selection (`--model Pro` or a sub-mode) raises the default `--timeout-ms` to 1200000 - Pro reasoning routinely runs for many minutes (an explicit `--timeout-ms` always wins).
|
|
244
244
|
- `--effort 즉시|중간|높음|"매우 높음"` sets the reasoning effort. English aliases `instant`/`medium`/`high`/`max` are accepted. The effort options and Pro share one radio group in ChatGPT, so picking an effort switches the composer to the standard reasoning model and deselects Pro; for the same reason `--pro-mode` and `--effort` cannot be combined.
|
|
245
245
|
- `--project "name"` enters an existing sidebar project before sending. `--project-new "name"` creates a new project (sidebar 새 프로젝트 popover, committed with Enter) and sends inside it. Neither can be combined with `--target-url` (the project step would navigate away from the confirmed tab), and `--project-new` never comes from saved defaults — creating a project is always an explicit per-ask choice.
|
|
246
246
|
|
package/dist/chatgpt-browser.js
CHANGED
|
@@ -229,8 +229,21 @@ export function hasFreshChatGptAnswer(previousAssistantMessageCount, state) {
|
|
|
229
229
|
// changed ChatGPT UI (moved/renamed composer or send control). Distinguish that
|
|
230
230
|
// from a genuinely clean-but-slow submit and point the user at an update/report
|
|
231
231
|
// instead of a misleading "raise --timeout-ms".
|
|
232
|
+
// Render a millisecond duration as a human-readable span for timeout guidance:
|
|
233
|
+
// 45000 -> "45s", 90000 -> "1m 30s", 1200000 -> "20 min". Messages keep the raw
|
|
234
|
+
// ms alongside ("20 min (1200000ms)") so the send_timeout blocker can still
|
|
235
|
+
// parse a budget to double.
|
|
236
|
+
export function formatDurationMs(ms) {
|
|
237
|
+
const totalSeconds = Math.max(0, Math.round(ms / 1000));
|
|
238
|
+
if (totalSeconds < 60)
|
|
239
|
+
return `${totalSeconds}s`;
|
|
240
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
241
|
+
const seconds = totalSeconds % 60;
|
|
242
|
+
return seconds ? `${minutes}m ${seconds}s` : `${minutes} min`;
|
|
243
|
+
}
|
|
232
244
|
export function acceptanceTimeoutError(ctx) {
|
|
233
245
|
const uiLikelyChanged = ctx.composerStillHasText || !ctx.submitButtonFound;
|
|
246
|
+
const took = `${formatDurationMs(ctx.timeoutMs)} (${ctx.timeoutMs}ms)`;
|
|
234
247
|
if (uiLikelyChanged) {
|
|
235
248
|
const detail = [
|
|
236
249
|
ctx.composerStillHasText ? "the composer still holds the prompt" : undefined,
|
|
@@ -238,12 +251,13 @@ export function acceptanceTimeoutError(ctx) {
|
|
|
238
251
|
]
|
|
239
252
|
.filter(Boolean)
|
|
240
253
|
.join(" and ");
|
|
241
|
-
return new Error(`Timed out after ${
|
|
254
|
+
return new Error(`Timed out after ${took} and ChatGPT never registered the prompt (${detail}). ` +
|
|
242
255
|
"The ChatGPT web UI may have changed, so prodex could not submit. Update prodex " +
|
|
243
256
|
"(npm i -g @youdie006/prodex@latest); if it persists, report it at " +
|
|
244
257
|
"https://github.com/youdie006/prodex/issues. You can also paste the prompt manually in the visible browser.");
|
|
245
258
|
}
|
|
246
|
-
return new Error(`Timed out after ${
|
|
259
|
+
return new Error(`Timed out after ${took} waiting for ChatGPT to accept the prompt. ` +
|
|
260
|
+
"Pro reasoning can run many minutes. Raise --timeout-ms and retry.");
|
|
247
261
|
}
|
|
248
262
|
export function hasPartialChatGptAnswer(previousAssistantMessageCount, state) {
|
|
249
263
|
return state.assistantMessageCount > previousAssistantMessageCount && isUsableChatGptAnswer(state.answer);
|
|
@@ -1415,7 +1429,7 @@ export async function sendChatGptPrompt(options) {
|
|
|
1415
1429
|
finally {
|
|
1416
1430
|
cdp.close();
|
|
1417
1431
|
}
|
|
1418
|
-
emitProgress("sent", `
|
|
1432
|
+
emitProgress("sent", `budget ${formatDurationMs(timeoutMs)}`);
|
|
1419
1433
|
const started = Date.now();
|
|
1420
1434
|
const acceptDeadline = computePromptAcceptanceDeadline(timeoutMs, started);
|
|
1421
1435
|
let accepted = false;
|
|
@@ -1441,6 +1455,26 @@ export async function sendChatGptPrompt(options) {
|
|
|
1441
1455
|
emitProgress("waiting", "prompt posting");
|
|
1442
1456
|
}
|
|
1443
1457
|
if (!accepted) {
|
|
1458
|
+
// The session can expire mid-send (logged out during a long Pro wait), which
|
|
1459
|
+
// otherwise surfaces as a cryptic "raise --timeout-ms" failure. Re-check the
|
|
1460
|
+
// login state first and, if the session is gone, say so clearly so the user
|
|
1461
|
+
// re-logs in instead of chasing a timeout.
|
|
1462
|
+
try {
|
|
1463
|
+
const status = await evaluateOnPage(page, statusExpression());
|
|
1464
|
+
if (!inferChatGptPageLoggedInLikely(status)) {
|
|
1465
|
+
throw new ChatGptBrowserBlockerError({
|
|
1466
|
+
code: "session_expired",
|
|
1467
|
+
message: "The ChatGPT session is no longer logged in - it likely expired during the send.",
|
|
1468
|
+
retryable: true,
|
|
1469
|
+
next_step: "Run `prodex pro browser login`, log in, then retry."
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
catch (error) {
|
|
1474
|
+
if (error instanceof ChatGptBrowserBlockerError)
|
|
1475
|
+
throw error;
|
|
1476
|
+
// best effort: a CDP eval failure here falls through to the generic timeout
|
|
1477
|
+
}
|
|
1444
1478
|
// A successful submit clears the composer, so text still sitting there means
|
|
1445
1479
|
// the send control did not register the prompt — the UI-changed signature.
|
|
1446
1480
|
let composerStillHasText = false;
|
|
@@ -1500,11 +1534,12 @@ export async function sendChatGptPrompt(options) {
|
|
|
1500
1534
|
answer: completed.answer.trim(),
|
|
1501
1535
|
modelHints: completed.modelHints,
|
|
1502
1536
|
warnings: [
|
|
1503
|
-
`answer_incomplete: ChatGPT was still generating after ${timeoutMs}ms, so the answer below may be truncated. Raise --timeout-ms and retry for the full response.`
|
|
1537
|
+
`answer_incomplete: ChatGPT was still generating after ${formatDurationMs(timeoutMs)} (${timeoutMs}ms), so the answer below may be truncated. Raise --timeout-ms and retry for the full response.`
|
|
1504
1538
|
]
|
|
1505
1539
|
};
|
|
1506
1540
|
}
|
|
1507
|
-
throw new Error(`Timed out after ${timeoutMs}ms waiting for ChatGPT to respond.
|
|
1541
|
+
throw new Error(`Timed out after ${formatDurationMs(timeoutMs)} (${timeoutMs}ms) waiting for ChatGPT to respond. ` +
|
|
1542
|
+
"Pro reasoning can run many minutes. Raise --timeout-ms and retry.");
|
|
1508
1543
|
}
|
|
1509
1544
|
export function modelMenuOptionsExpression() {
|
|
1510
1545
|
return `(() => {
|
package/dist/cli-help.js
CHANGED
|
@@ -174,7 +174,7 @@ Use \`prodex pro ask\` for dry-run/manual previews.
|
|
|
174
174
|
Use \`prodex pro browser ask\` only when you want an explicit visible-browser send.
|
|
175
175
|
Model/project selection (visible-browser send):
|
|
176
176
|
--model "label" Pick the composer model by its exact menu label (verified: Pro). Submenu models (e.g. the GPT-5.6 Sol variants) are rejected for now.
|
|
177
|
-
--pro-mode 기본 | 확장 Pro sub-mode (only when the model is Pro); a Pro selection raises the default timeout to
|
|
177
|
+
--pro-mode 기본 | 확장 Pro sub-mode (only when the model is Pro); a Pro selection raises the default timeout to 1200000 ms
|
|
178
178
|
--effort 즉시|중간|높음|매우 높음 Reasoning effort (aliases: instant/medium/high/max); picking one deselects Pro
|
|
179
179
|
--project "name" Enter an existing sidebar project first (cannot combine with --target-url)
|
|
180
180
|
Labels are matched in both the Korean and English (US) UI; run \`prodex pro browser models\` to list what your account shows.
|
|
@@ -268,7 +268,7 @@ Commands:
|
|
|
268
268
|
Visible-browser sends require a manual browser session and stop on login, captcha, Cloudflare, permission, rate-limit, or usage-limit blockers.
|
|
269
269
|
Model/project selection (ask):
|
|
270
270
|
--model Composer model to pick by its exact menu label (verified: Pro). Models whose menu entry opens a submenu of variants are rejected with a clear error for now.
|
|
271
|
-
--pro-mode Pro sub-mode: 기본 (standard) or 확장 (extended), used when the model is Pro. A Pro selection raises the default --timeout-ms to
|
|
271
|
+
--pro-mode Pro sub-mode: 기본 (standard) or 확장 (extended), used when the model is Pro. A Pro selection raises the default --timeout-ms to 1200000.
|
|
272
272
|
--effort Reasoning effort: 즉시 / 중간 / 높음 / 매우 높음 (aliases: instant/medium/high/max). Picking an effort switches the composer to the standard reasoning model, deselecting Pro.
|
|
273
273
|
--project Enter an existing sidebar project before sending. Cannot be combined with --target-url.
|
|
274
274
|
--pro-mode and --effort cannot be combined. Labels are matched in both the Korean and English (US) ChatGPT UI (e.g. 높음/High, Pro 확장/Pro Extended).
|
package/dist/cli-pro.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { buildDryRunBundle } from "./bundle.js";
|
|
4
|
-
import { DEFAULT_CDP_PORT, resolveCdpPort, chatGptVisibilityBlocker, defaultChatGptProfileDir, getChatGptBrowserStatus, listChatGptModelOptions, listChatGptSidebarProjects, normalizeChatGptTargetUrl, openChatGptBrowser, parseProMode, parseReasoningEffort, readLastBrowserLoginLaunch, recordBrowserLoginLaunch, sendChatGptPrompt } from "./chatgpt-browser.js";
|
|
4
|
+
import { DEFAULT_CDP_PORT, resolveCdpPort, chatGptVisibilityBlocker, defaultChatGptProfileDir, formatDurationMs, getChatGptBrowserStatus, listChatGptModelOptions, listChatGptSidebarProjects, normalizeChatGptTargetUrl, openChatGptBrowser, parseProMode, parseReasoningEffort, readLastBrowserLoginLaunch, recordBrowserLoginLaunch, sendChatGptPrompt } from "./chatgpt-browser.js";
|
|
5
5
|
import { ASK_PRO_BOOLEAN_FLAGS, ASK_PRO_PREVIEW_VALUE_FLAGS, ASK_PRO_VALUE_FLAGS, assertHelpRequestArgs, assertNoExtraArgs, assertOnlyOptions, findHelpFlagIndexBeforePromptDelimiter, formatCliCommand, hasAskProDryRunMode, hasAskProMode, hasAskProSendMode, isHelpSubcommand, parseAskProArgs, printHelpIfRequested, readFlag, readPortFlag, readPositionalsWithOptions, readPositiveIntegerFlag, readRepeatedFlag, resolveCwdFlag, resolveOptionalFileFlag, unknownSubcommandError } from "./cli-args.js";
|
|
6
6
|
import { printProBrowserHelp, printProHelp } from "./cli-help.js";
|
|
7
7
|
import { listRawResultsForInspection, listTasksForInspection } from "./cli-ledger.js";
|
|
@@ -520,11 +520,11 @@ export function createBrowserSendProgressPrinter(write, heartbeatMs = 10_000) {
|
|
|
520
520
|
if (lastWaitingElapsedMs !== undefined && event.elapsedMs - lastWaitingElapsedMs < heartbeatMs)
|
|
521
521
|
return;
|
|
522
522
|
lastWaitingElapsedMs = event.elapsedMs;
|
|
523
|
-
write(`progress: waiting ${
|
|
523
|
+
write(`progress: waiting ${formatDurationMs(event.elapsedMs)}${event.detail ? ` (${event.detail})` : ""}`);
|
|
524
524
|
return;
|
|
525
525
|
}
|
|
526
526
|
if (event.phase === "answered") {
|
|
527
|
-
write(`progress: answer received after ${
|
|
527
|
+
write(`progress: answer received after ${formatDurationMs(event.elapsedMs)}${event.detail ? ` (${event.detail})` : ""}`);
|
|
528
528
|
return;
|
|
529
529
|
}
|
|
530
530
|
write(`progress: ${PROGRESS_PHASE_LABELS[event.phase]}${event.detail ? ` (${event.detail})` : ""}`);
|
|
@@ -628,7 +628,9 @@ export async function runAskProCommand(rest, io) {
|
|
|
628
628
|
// --pro-mode, so --model Pro sends fell back to 90s and chronically timed
|
|
629
629
|
// out. Any effective Pro selection now defaults to 15 minutes.
|
|
630
630
|
const effectiveProSelection = selectionProMode !== undefined || (selectionModel !== undefined && /pro/i.test(selectionModel));
|
|
631
|
-
|
|
631
|
+
// Pro reasoning routinely runs 6-20 minutes; 15 min was still cutting long
|
|
632
|
+
// answers off (field report), so a Pro selection defaults to 20 minutes.
|
|
633
|
+
const defaultBrowserTimeoutMs = effectiveProSelection ? 1_200_000 : 90_000;
|
|
632
634
|
const browserTimeoutMs = hasSendMode
|
|
633
635
|
? (readPositiveIntegerFlag(parsedAskPro.optionArgs, "--timeout-ms") ?? defaultBrowserTimeoutMs)
|
|
634
636
|
: undefined;
|
|
@@ -1075,7 +1077,9 @@ export function browserSendBlockerFromError(error) {
|
|
|
1075
1077
|
next_step: "Update prodex (npm i -g @youdie006/prodex@latest); if it persists, report it at https://github.com/youdie006/prodex/issues or paste the prompt manually in the visible browser."
|
|
1076
1078
|
};
|
|
1077
1079
|
}
|
|
1078
|
-
|
|
1080
|
+
// Match the raw ms whether the message uses the old "after 90000ms" form or
|
|
1081
|
+
// the newer human-readable "after 20 min (1200000ms)" form.
|
|
1082
|
+
const timedOut = message.match(/Timed out after [\s\S]*?(\d+)\s*ms/);
|
|
1079
1083
|
if (timedOut) {
|
|
1080
1084
|
// Suggest a concrete doubled budget so the user can paste a rerun command
|
|
1081
1085
|
// instead of guessing what "raise --timeout-ms" means in milliseconds.
|
|
@@ -1085,7 +1089,7 @@ export function browserSendBlockerFromError(error) {
|
|
|
1085
1089
|
code: "send_timeout",
|
|
1086
1090
|
message,
|
|
1087
1091
|
retryable: true,
|
|
1088
|
-
next_step: `Rerun with a bigger budget: \`prodex pro browser ask --timeout-ms ${suggestedMs} "<same prompt>"\`.`
|
|
1092
|
+
next_step: `Rerun with a bigger budget (${formatDurationMs(suggestedMs)}): \`prodex pro browser ask --timeout-ms ${suggestedMs} "<same prompt>"\`.`
|
|
1089
1093
|
};
|
|
1090
1094
|
}
|
|
1091
1095
|
return {
|