@youdie006/prodex 0.37.0 → 0.38.0
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 +41 -0
- package/dist/chatgpt-browser.js +99 -5
- package/dist/cli-help.js +7 -5
- package/dist/cli-pro.js +11 -1
- package/dist/cli.js +3 -1
- package/dist/config.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -424,6 +424,47 @@ During local development, you can run the TypeScript source directly:
|
|
|
424
424
|
npm run dev -- tasks list
|
|
425
425
|
```
|
|
426
426
|
|
|
427
|
+
## When a send breaks
|
|
428
|
+
|
|
429
|
+
prodex drives a web UI that changes underneath it, so the interesting question is what you have when that happens.
|
|
430
|
+
|
|
431
|
+
**Report it from the receipt, not from memory.** A blocked consult already records the blocker, the version and the platform, so `prodex pro report-issue` builds the report out of that:
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
prodex pro report-issue # prints it, files nothing
|
|
435
|
+
prodex pro report-issue --confirm # opens it as a GitHub issue, through `gh`
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
The prompt, the answer and the summary never travel - a public issue is not where a private consult should leak - and filing is deduplicated by blocker code, so something that stays broken adds to one issue instead of opening a new one every time.
|
|
439
|
+
|
|
440
|
+
**Capture what the page looked like.** With diagnostics on, a failing send leaves a screenshot and a snapshot of the picker and composer next to each other:
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
PRODEX_BROWSER_DIAGNOSTICS=1 prodex ask "..."
|
|
444
|
+
# .bridge/diagnostics/<when>/{screen.png,page-shape.json}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
The snapshot carries roles, testids, rects, `aria-value*` and `pointer-events`. Those last two are what identified a model row that no coordinate could click and a slider step prodex could not read. Captures stay on your machine and are never attached to a report; a screenshot of ChatGPT shows the conversation.
|
|
448
|
+
|
|
449
|
+
**Notice before a person does.** `scripts/ui-watchdog.mjs` sends a token and checks the reply - a real round trip rather than a guess from the page's shape - and can file what it finds:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
node scripts/ui-watchdog.mjs # says ok or broken
|
|
453
|
+
node scripts/ui-watchdog.mjs --file-issue # and reports it
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
It needs the logged-in browser, so it belongs on a machine that has one rather than in CI. A daily cron entry is enough.
|
|
457
|
+
|
|
458
|
+
## Sending without leaving a trace
|
|
459
|
+
|
|
460
|
+
`--temporary` sends into a ChatGPT Temporary Chat, which leaves your chat list untouched:
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
prodex ask --new-chat --temporary "..."
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
It costs something, and prodex says so on every such send: an unsaved chat is not in the transcript API, so the answer is read off the page, where tables and citation links can be lost - and neither `pro browser recover` nor `--target-url` can reach it afterwards. It requires `--new-chat`, because a throwaway chat cannot be continued.
|
|
467
|
+
|
|
427
468
|
## FAQ
|
|
428
469
|
|
|
429
470
|
**A send failed with `send_ui_changed` / "the ChatGPT web UI may have changed".** prodex drives the visible ChatGPT web UI, so an OpenAI redesign of the composer or send control can break sends. When a send times out without the prompt ever posting (the composer still holds the text, or no send button was found), prodex reports this as a likely UI change instead of a misleading "slow model" timeout. Fix: update prodex (`npm i -g @youdie006/prodex@latest`); if it persists, open an issue at https://github.com/youdie006/prodex/issues, and paste the prompt manually in the visible browser in the meantime.
|
package/dist/chatgpt-browser.js
CHANGED
|
@@ -15,7 +15,12 @@ export class ChatGptBrowserBlockerError extends Error {
|
|
|
15
15
|
this.blocker = blocker;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
// Five steps, not four. Measured at both ends of the live slider: position 0 of
|
|
19
|
+
// 4 reads "Instant, 1 of 5" and position 4 reads "Pro, 5 of 5", so Pro is a step
|
|
20
|
+
// of this control rather than a model. Leaving it out meant --effort could not
|
|
21
|
+
// reach the top of the slider at all, and the only route there - --model Pro -
|
|
22
|
+
// answered with advice to "say --effort Pro", which then failed.
|
|
23
|
+
const REASONING_EFFORTS = ["즉시", "중간", "높음", "매우 높음", "Pro"];
|
|
19
24
|
const PRO_MODES = ["기본", "확장"];
|
|
20
25
|
// Aliases map friendly CLI input onto the exact Korean menu labels the picker
|
|
21
26
|
// clicks by text. Keys are lowercased and space-stripped before lookup.
|
|
@@ -25,7 +30,9 @@ const REASONING_EFFORT_ALIASES = {
|
|
|
25
30
|
medium: "중간",
|
|
26
31
|
high: "높음",
|
|
27
32
|
max: "매우 높음",
|
|
28
|
-
extrahigh: "매우 높음"
|
|
33
|
+
extrahigh: "매우 높음",
|
|
34
|
+
pro: "Pro",
|
|
35
|
+
"프로": "Pro"
|
|
29
36
|
};
|
|
30
37
|
// Menu labels per canonical value, verified live in both the Korean and the
|
|
31
38
|
// English (US) ChatGPT UI. Matching tries every candidate so either UI works.
|
|
@@ -33,7 +40,8 @@ const EFFORT_MENU_LABELS = {
|
|
|
33
40
|
"즉시": ["즉시", "Instant"],
|
|
34
41
|
"중간": ["중간", "Medium"],
|
|
35
42
|
"높음": ["높음", "High"],
|
|
36
|
-
"매우 높음": ["매우 높음", "Extra High"]
|
|
43
|
+
"매우 높음": ["매우 높음", "Extra High"],
|
|
44
|
+
Pro: ["Pro", "프로"]
|
|
37
45
|
};
|
|
38
46
|
const PRO_MODE_SUBMENU_LABELS = {
|
|
39
47
|
"기본": ["Pro 기본", "Pro Standard", "Standard", "기본"],
|
|
@@ -1637,7 +1645,21 @@ export function pinnedSelectionWarning(pinned, offered) {
|
|
|
1637
1645
|
if (offered.length === 0)
|
|
1638
1646
|
return undefined;
|
|
1639
1647
|
const has = (wanted) => offered.some((label) => label.trim().toLowerCase() === wanted.trim().toLowerCase());
|
|
1640
|
-
|
|
1648
|
+
// A value prodex already knows to be a slider step needs no listing to
|
|
1649
|
+
// vouch for it: the slider shows one step at a time, so a listing that
|
|
1650
|
+
// happens to read "Extra High" says nothing about Pro. Warning there was a
|
|
1651
|
+
// false alarm about a setting the very next send used successfully, and an
|
|
1652
|
+
// alarm that cries about known-good settings is one people learn to skip.
|
|
1653
|
+
const knownStep = (wanted) => {
|
|
1654
|
+
try {
|
|
1655
|
+
parseReasoningEffort(wanted);
|
|
1656
|
+
return true;
|
|
1657
|
+
}
|
|
1658
|
+
catch {
|
|
1659
|
+
return false;
|
|
1660
|
+
}
|
|
1661
|
+
};
|
|
1662
|
+
const missing = [pinned.model, pinned.effort].find((wanted) => wanted !== undefined && !has(wanted) && !knownStep(wanted));
|
|
1641
1663
|
if (missing === undefined)
|
|
1642
1664
|
return undefined;
|
|
1643
1665
|
// Say only what was seen. The picker lists its models, but the effort slider
|
|
@@ -1714,6 +1736,31 @@ async function dispatchArrowKey(cdp, key) {
|
|
|
1714
1736
|
await cdp.send("Input.dispatchKeyEvent", { type: "rawKeyDown", key, code, windowsVirtualKeyCode: virtualKey });
|
|
1715
1737
|
await cdp.send("Input.dispatchKeyEvent", { type: "keyUp", key, code, windowsVirtualKeyCode: virtualKey });
|
|
1716
1738
|
}
|
|
1739
|
+
/**
|
|
1740
|
+
* How to read every step of the slider and leave it as it was.
|
|
1741
|
+
*
|
|
1742
|
+
* The control shows one step at a time, and that single visible label was all
|
|
1743
|
+
* `pro browser models` ever reported - which is how a machine on this same
|
|
1744
|
+
* account concluded "Pro does not exist here" from five listings that each read
|
|
1745
|
+
* Instant / GPT-5.6 Sol / GPT-5.5, with the slider parked on Instant every
|
|
1746
|
+
* time. Seeing the rest means walking it, and walking someone's setting is only
|
|
1747
|
+
* acceptable if it is put back, so the plan always ends where it started.
|
|
1748
|
+
*
|
|
1749
|
+
* Refuses bounds that do not look like this control, so a misread never becomes
|
|
1750
|
+
* thousands of keystrokes in someone's browser.
|
|
1751
|
+
*/
|
|
1752
|
+
export function sliderWalkPlan(state) {
|
|
1753
|
+
const { position, min, max } = state;
|
|
1754
|
+
if (!Number.isInteger(position) || !Number.isInteger(min) || !Number.isInteger(max))
|
|
1755
|
+
return undefined;
|
|
1756
|
+
const steps = max - min;
|
|
1757
|
+
if (steps < 1 || steps > 12)
|
|
1758
|
+
return undefined;
|
|
1759
|
+
if (position < min || position > max)
|
|
1760
|
+
return undefined;
|
|
1761
|
+
const offset = position - min;
|
|
1762
|
+
return { toBottom: offset, climb: steps, back: offset };
|
|
1763
|
+
}
|
|
1717
1764
|
async function selectModelReasoning(cdp, options, selectionWarnings = []) {
|
|
1718
1765
|
if (!options.model && !options.proMode && !options.effort)
|
|
1719
1766
|
return;
|
|
@@ -3206,6 +3253,52 @@ export async function listChatGptSidebarProjects(input = {}) {
|
|
|
3206
3253
|
}
|
|
3207
3254
|
return { url: status.url, projects };
|
|
3208
3255
|
}
|
|
3256
|
+
/**
|
|
3257
|
+
* Every step of the effort slider, read by walking it and putting it back.
|
|
3258
|
+
*
|
|
3259
|
+
* Best effort: a slider that cannot be focused, read or walked leaves the
|
|
3260
|
+
* listing exactly as it was rather than failing a read-only command.
|
|
3261
|
+
*/
|
|
3262
|
+
async function readEffortSteps(cdp) {
|
|
3263
|
+
try {
|
|
3264
|
+
const focused = await cdp.evaluate(focusPowerSliderExpression());
|
|
3265
|
+
if (!focused?.ok)
|
|
3266
|
+
return undefined;
|
|
3267
|
+
const start = await cdp.evaluate(powerSliderStateExpression());
|
|
3268
|
+
if (!start?.ok)
|
|
3269
|
+
return undefined;
|
|
3270
|
+
const plan = sliderWalkPlan({ position: start.position, min: start.min, max: start.max });
|
|
3271
|
+
if (!plan)
|
|
3272
|
+
return undefined;
|
|
3273
|
+
const current = start.effort ?? null;
|
|
3274
|
+
for (let i = 0; i < plan.toBottom; i += 1) {
|
|
3275
|
+
await dispatchArrowKey(cdp, "ArrowLeft");
|
|
3276
|
+
await sleep(120);
|
|
3277
|
+
}
|
|
3278
|
+
const labels = [];
|
|
3279
|
+
const record = async () => {
|
|
3280
|
+
const state = await cdp.evaluate(powerSliderStateExpression());
|
|
3281
|
+
const label = state?.effort?.trim();
|
|
3282
|
+
if (label && !labels.includes(label))
|
|
3283
|
+
labels.push(label);
|
|
3284
|
+
};
|
|
3285
|
+
await record();
|
|
3286
|
+
for (let i = 0; i < plan.climb; i += 1) {
|
|
3287
|
+
await dispatchArrowKey(cdp, "ArrowRight");
|
|
3288
|
+
await sleep(120);
|
|
3289
|
+
await record();
|
|
3290
|
+
}
|
|
3291
|
+
// Put it back. Reading someone's setting must not change it.
|
|
3292
|
+
for (let i = 0; i < plan.climb - plan.back; i += 1) {
|
|
3293
|
+
await dispatchArrowKey(cdp, "ArrowLeft");
|
|
3294
|
+
await sleep(120);
|
|
3295
|
+
}
|
|
3296
|
+
return labels.length > 0 ? { labels, current } : undefined;
|
|
3297
|
+
}
|
|
3298
|
+
catch {
|
|
3299
|
+
return undefined;
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3209
3302
|
export async function listChatGptModelOptions(input = {}) {
|
|
3210
3303
|
const port = resolveCdpPort(input.port);
|
|
3211
3304
|
const timeoutMs = input.timeoutMs ?? 15_000;
|
|
@@ -3239,7 +3332,8 @@ export async function listChatGptModelOptions(input = {}) {
|
|
|
3239
3332
|
if (!opened)
|
|
3240
3333
|
throw new Error("ChatGPT model menu did not open after clicking the selector");
|
|
3241
3334
|
const options = await cdp.evaluate(modelMenuOptionsExpression());
|
|
3242
|
-
|
|
3335
|
+
const effortSteps = await readEffortSteps(cdp);
|
|
3336
|
+
return { url: status.url, options, ...(effortSteps ? { effortSteps } : {}) };
|
|
3243
3337
|
}
|
|
3244
3338
|
finally {
|
|
3245
3339
|
try {
|
package/dist/cli-help.js
CHANGED
|
@@ -26,10 +26,11 @@ Ask / consult commands:
|
|
|
26
26
|
prodex pro browser models [--source-cli /absolute/path/to/dist/cli.js] [--port 9333] [--timeout-ms 15000] # read-only list of model menu options
|
|
27
27
|
prodex pro browser projects [--source-cli /absolute/path/to/dist/cli.js] [--port 9333] [--timeout-ms 15000] # read-only list of sidebar project names (for --project)
|
|
28
28
|
prodex pro browser recover [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--port 9333] --target-url <thread-url> [--timeout-ms 60000] # recover a finished answer from a thread whose send timed out
|
|
29
|
-
prodex pro browser ask [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--port 9333] [--timeout-ms 300000] [--busy-wait-ms 600000] [--target-url url --confirm-target] [--new-chat] [--temporary] [--stdin] [--json] [--auto-login|--no-auto-login] [--file path] [--attach path] [--tool deep-research|web-search|create-image] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"] [--project "name" | --project-new "name"] "prompt" # explicit visible-browser send
|
|
29
|
+
prodex pro browser ask [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--port 9333] [--timeout-ms 300000] [--busy-wait-ms 600000] [--target-url url --confirm-target] [--new-chat] [--temporary] [--stdin] [--json] [--auto-login|--no-auto-login] [--file path] [--attach path] [--tool deep-research|web-search|create-image] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"|Pro] [--project "name" | --project-new "name"] "prompt" # explicit visible-browser send
|
|
30
30
|
prodex pro latest [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--json]
|
|
31
31
|
prodex pro list [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--json]
|
|
32
32
|
prodex pro show <task-id|latest> [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--json]
|
|
33
|
+
prodex pro report-issue [--cwd /absolute/path/to/repo] [--task <task-id>] [--repo owner/name] [--confirm] # bug report from a failed consult's receipt; previews unless --confirm, never carries the prompt or the answer
|
|
33
34
|
|
|
34
35
|
Bridge ledger (durable tasks/results/receipts/sessions under .bridge/):
|
|
35
36
|
prodex init [--cwd /absolute/path/to/repo]
|
|
@@ -51,7 +52,7 @@ Bridge ledger (durable tasks/results/receipts/sessions under .bridge/):
|
|
|
51
52
|
|
|
52
53
|
Agent / MCP integration:
|
|
53
54
|
prodex mcp [--cwd /absolute/path/to/repo]
|
|
54
|
-
prodex setup [--cwd /absolute/path/to/repo] [--host 127.0.0.1] [--port 8787] [--token-ttl-hours <hours>] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"] [--project "name"] [--clear-model|--clear-pro-mode|--clear-effort|--clear-project] [--interactive]
|
|
55
|
+
prodex setup [--cwd /absolute/path/to/repo] [--host 127.0.0.1] [--port 8787] [--token-ttl-hours <hours>] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"|Pro] [--project "name"] [--clear-model|--clear-pro-mode|--clear-effort|--clear-project] [--interactive]
|
|
55
56
|
prodex start [--cwd /absolute/path/to/repo] [--source-cli /absolute/path/to/dist/cli.js]
|
|
56
57
|
prodex status [--cwd /absolute/path/to/repo] [--source-cli /absolute/path/to/dist/cli.js] [--show-token] [--url-only] [--unsafe-show-non-expiring-token]
|
|
57
58
|
prodex tunnel url [--cwd /absolute/path/to/repo] [--source-cli /absolute/path/to/dist/cli.js] --public-url https://... [--show-token] [--url-only]
|
|
@@ -79,7 +80,7 @@ export function printSetupHelp(stdout) {
|
|
|
79
80
|
stdout(`prodex setup
|
|
80
81
|
|
|
81
82
|
Commands:
|
|
82
|
-
prodex setup [--cwd /absolute/path/to/repo] [--host 127.0.0.1] [--port 8787] [--token-ttl-hours <hours>] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"] [--project "name"] [--clear-model|--clear-pro-mode|--clear-effort|--clear-project] [--interactive]
|
|
83
|
+
prodex setup [--cwd /absolute/path/to/repo] [--host 127.0.0.1] [--port 8787] [--token-ttl-hours <hours>] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"|Pro] [--project "name"] [--clear-model|--clear-pro-mode|--clear-effort|--clear-project] [--interactive]
|
|
83
84
|
|
|
84
85
|
Save a loopback-only HTTP MCP profile in .bridge/config.local.json. Use --token-ttl-hours before tunnels or ChatGPT Project use.
|
|
85
86
|
|
|
@@ -167,10 +168,11 @@ Commands:
|
|
|
167
168
|
prodex pro browser check [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo]
|
|
168
169
|
prodex pro browser smoke [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo]
|
|
169
170
|
prodex pro browser models [--source-cli /absolute/path/to/dist/cli.js]
|
|
170
|
-
prodex pro browser ask [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--target-url url --confirm-target] [--new-chat] [--temporary] [--stdin] [--json] [--auto-login|--no-auto-login] [--file path] [--attach path] [--tool deep-research|web-search|create-image] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"] [--project "name" | --project-new "name"] "prompt"
|
|
171
|
+
prodex pro browser ask [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--target-url url --confirm-target] [--new-chat] [--temporary] [--stdin] [--json] [--auto-login|--no-auto-login] [--file path] [--attach path] [--tool deep-research|web-search|create-image] [--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"|Pro] [--project "name" | --project-new "name"] "prompt"
|
|
171
172
|
prodex pro latest [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--json]
|
|
172
173
|
prodex pro list [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--json]
|
|
173
174
|
prodex pro show <task-id|latest> [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--json]
|
|
175
|
+
prodex pro report-issue [--cwd /absolute/path/to/repo] [--task <task-id>] [--repo owner/name] [--confirm] # bug report from a failed consult's receipt; previews unless --confirm, never carries the prompt or the answer
|
|
174
176
|
|
|
175
177
|
Use \`prodex pro ask\` for dry-run/manual previews.
|
|
176
178
|
Use \`prodex pro browser ask\` only when you want an explicit visible-browser send.
|
|
@@ -251,7 +253,7 @@ export function printProBrowserHelp(stdout, sourceCli) {
|
|
|
251
253
|
const smokeUsage = sourceCli
|
|
252
254
|
? `${cli} pro browser smoke${sourceCliOption} [--cwd /absolute/path/to/repo] [--port 9333] [--timeout-ms 90000]`
|
|
253
255
|
: "prodex pro browser smoke [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--port 9333] [--timeout-ms 90000]";
|
|
254
|
-
const selectionUsage = '[--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"] [--project "name" | --project-new "name"]';
|
|
256
|
+
const selectionUsage = '[--model Pro] [--pro-mode 기본|확장] [--effort 즉시|중간|높음|"매우 높음"|Pro] [--project "name" | --project-new "name"]';
|
|
255
257
|
const askUsage = sourceCli
|
|
256
258
|
? `${cli} pro browser ask${sourceCliOption} [--cwd /absolute/path/to/repo] [--port 9333] [--timeout-ms 300000] [--busy-wait-ms 600000] [--target-url url --confirm-target] [--new-chat] [--temporary] [--stdin] [--json] [--auto-login|--no-auto-login] [--file path] [--attach path] [--tool deep-research|web-search|create-image] ${selectionUsage} "prompt"`
|
|
257
259
|
: `prodex pro browser ask [--source-cli /absolute/path/to/dist/cli.js] [--cwd /absolute/path/to/repo] [--port 9333] [--timeout-ms 300000] [--busy-wait-ms 600000] [--target-url url --confirm-target] [--new-chat] [--temporary] [--stdin] [--json] [--auto-login|--no-auto-login] [--file path] [--attach path] [--tool deep-research|web-search|create-image] ${selectionUsage} "prompt"`;
|
package/dist/cli-pro.js
CHANGED
|
@@ -447,7 +447,17 @@ export async function runProCommand(rest, io, runCliFn) {
|
|
|
447
447
|
for (const option of listed.options) {
|
|
448
448
|
io.stdout(formatModelMenuOption(option));
|
|
449
449
|
}
|
|
450
|
-
|
|
450
|
+
if (listed.effortSteps) {
|
|
451
|
+
io.stdout("");
|
|
452
|
+
io.stdout("Effort steps on this account (the slider was walked and put back):");
|
|
453
|
+
for (const label of listed.effortSteps.labels) {
|
|
454
|
+
io.stdout(`${label === listed.effortSteps.current ? "*" : " "} ${label}`);
|
|
455
|
+
}
|
|
456
|
+
io.stdout("Pass any of these to --effort. The list is complete: the slider shows one step at a time, so reading it any other way sees only the current one.");
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
io.stdout("An arrow shows what that row is set to now; --model / --effort reach into those submenus (e.g. --model Pro).");
|
|
460
|
+
}
|
|
451
461
|
return 0;
|
|
452
462
|
}
|
|
453
463
|
if (browserSubcommand === "projects") {
|
package/dist/cli.js
CHANGED
|
@@ -436,7 +436,9 @@ repo: ${cwd}
|
|
|
436
436
|
|
|
437
437
|
Safety notes:
|
|
438
438
|
- This command only prints commands; it does not start servers, open browsers, or write files.
|
|
439
|
-
- Visible-browser sends require a manual, visible browser session and stop on login, captcha, Cloudflare, permission, rate-limit, or usage-limit blockers, plus response_choice_pending when ChatGPT is waiting for you to pick which of two answers you prefer
|
|
439
|
+
- Visible-browser sends require a manual, visible browser session and stop on login, captcha, Cloudflare, permission, rate-limit, or usage-limit blockers, plus response_choice_pending when ChatGPT is waiting for you to pick which of two answers you prefer.
|
|
440
|
+
- When a send is blocked, \`prodex pro report-issue\` turns that receipt into a bug report (prints it; --confirm files it). It carries the blocker, version and platform, never the prompt or the answer.
|
|
441
|
+
- PRODEX_BROWSER_DIAGNOSTICS=1 makes a failing send leave a screenshot and a page snapshot under .bridge/diagnostics for whoever debugs it. They stay local.`;
|
|
440
442
|
}
|
|
441
443
|
async function hasOnboardingReadme(cwd) {
|
|
442
444
|
try {
|
package/dist/config.js
CHANGED
|
@@ -10,7 +10,8 @@ const BRIDGE_DIRECTORY_MODE = 0o700;
|
|
|
10
10
|
const BrowserDefaultsSchema = z.object({
|
|
11
11
|
model: z.string().min(1).optional(),
|
|
12
12
|
pro_mode: z.enum(["기본", "확장"]).optional(),
|
|
13
|
-
|
|
13
|
+
// Pro is the slider's fifth step, so a saved default may name it.
|
|
14
|
+
effort: z.enum(["즉시", "중간", "높음", "매우 높음", "Pro"]).optional(),
|
|
14
15
|
project: z.string().min(1).optional()
|
|
15
16
|
});
|
|
16
17
|
const LocalConfigSchema = z.object({
|