@youdie006/prodex 0.40.0 → 0.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chatgpt-browser.js +27 -2
- package/dist/cli-pro.js +29 -2
- package/package.json +1 -1
package/dist/chatgpt-browser.js
CHANGED
|
@@ -1602,6 +1602,18 @@ async function reloadPageAndAwaitComposer(page) {
|
|
|
1602
1602
|
cdp.close();
|
|
1603
1603
|
}
|
|
1604
1604
|
}
|
|
1605
|
+
/**
|
|
1606
|
+
* The project a ChatGPT URL belongs to, as its `g-p-<id>` segment.
|
|
1607
|
+
*
|
|
1608
|
+
* The rebind check used to compare whole URLs, which also carry mode in a
|
|
1609
|
+
* query string - and mode is exactly what differs across the reload this
|
|
1610
|
+
* failure showed up in. Identity is the thing the check actually cares about:
|
|
1611
|
+
* that the composer came back bound to THIS project rather than the one the
|
|
1612
|
+
* tab came from.
|
|
1613
|
+
*/
|
|
1614
|
+
export function projectIdentity(url) {
|
|
1615
|
+
return /\/g\/(g-p-[^/?#]+)/.exec(url)?.[1];
|
|
1616
|
+
}
|
|
1605
1617
|
export function powerSliderPresentExpression() {
|
|
1606
1618
|
return `Boolean(document.querySelector('[data-testid="composer-intelligence-picker-content"] [role="slider"]'))`;
|
|
1607
1619
|
}
|
|
@@ -2524,12 +2536,25 @@ async function selectProject(cdp, options) {
|
|
|
2524
2536
|
// prompt posted into the project the tab came from). A hard reload of the
|
|
2525
2537
|
// project home rebinds the composer to THIS project before we send.
|
|
2526
2538
|
const projectHome = await cdp.evaluate("location.href");
|
|
2539
|
+
const home = projectIdentity(projectHome);
|
|
2527
2540
|
// Polled with no delay, the first check could run before the reload had
|
|
2528
2541
|
// committed, on the old document, whose composer and URL both still
|
|
2529
2542
|
// matched. The stamp keeps that document from passing as the new one.
|
|
2530
|
-
|
|
2543
|
+
//
|
|
2544
|
+
// Identity, not the whole URL: the href also carries mode in a query
|
|
2545
|
+
// string, and comparing it byte-for-byte failed a reload that had landed
|
|
2546
|
+
// exactly where it was asked to.
|
|
2547
|
+
const rebound = await reloadAndAwaitComposer(cdp, RELOAD_SETTLE_TIMEOUT_MS, home ? `/\\/g\\/${home.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![^/?#])/.test(location.href)` : "true");
|
|
2531
2548
|
if (!rebound) {
|
|
2532
|
-
|
|
2549
|
+
// Say what it saw. This failure is rare and was previously reported as
|
|
2550
|
+
// four words, which named neither the cause nor anything to try.
|
|
2551
|
+
const landed = await cdp.evaluate("location.href").catch(() => "unknown");
|
|
2552
|
+
const hasComposer = await cdp
|
|
2553
|
+
.evaluate(`Boolean(document.querySelector('#prompt-textarea,[contenteditable="true"],textarea'))`)
|
|
2554
|
+
.catch(() => false);
|
|
2555
|
+
throw new Error(`ChatGPT composer did not rebind after entering project "${options.project}": after reloading, the tab was on ` +
|
|
2556
|
+
`${projectIdentity(landed) ?? "no project"} (expected ${home ?? "that project"}) and the composer was ` +
|
|
2557
|
+
`${hasComposer ? "present but the page never settled" : "still missing"}.`);
|
|
2533
2558
|
}
|
|
2534
2559
|
}
|
|
2535
2560
|
const composerReady = await waitForExpressionTrue(cdp, `Boolean(document.querySelector('#prompt-textarea,[contenteditable="true"],textarea'))`, PROJECT_NAVIGATION_TIMEOUT_MS);
|
package/dist/cli-pro.js
CHANGED
|
@@ -1110,6 +1110,12 @@ export async function runAskProCommand(rest, io) {
|
|
|
1110
1110
|
// Requiring --new-chat keeps that explicit rather than quietly turning a
|
|
1111
1111
|
// continuation into a throwaway.
|
|
1112
1112
|
const temporary = parsedAskPro.optionArgs.includes("--temporary");
|
|
1113
|
+
const temporaryConflict = temporaryProjectConflict({
|
|
1114
|
+
temporary,
|
|
1115
|
+
...(explicitProject !== undefined ? { explicitProject } : {})
|
|
1116
|
+
});
|
|
1117
|
+
if (temporaryConflict)
|
|
1118
|
+
throw new Error(temporaryConflict);
|
|
1113
1119
|
if (temporary && !newChat) {
|
|
1114
1120
|
throw new Error("--temporary starts a throwaway chat, so it needs --new-chat. A temporary chat cannot be continued or recovered later.");
|
|
1115
1121
|
}
|
|
@@ -1141,9 +1147,17 @@ export async function runAskProCommand(rest, io) {
|
|
|
1141
1147
|
// fresh chat inside the project is exactly what "--new-chat + project"
|
|
1142
1148
|
// produces, and the whole point of pinning a default project is that
|
|
1143
1149
|
// consults stop landing in the general chat list. Only --target-url
|
|
1144
|
-
// (pinned tab)
|
|
1150
|
+
// (pinned tab), --project-new, and --temporary suppress it.
|
|
1151
|
+
//
|
|
1152
|
+
// --temporary suppresses rather than conflicts: a pinned project must not
|
|
1153
|
+
// turn every throwaway send into an error, and attempting both is what
|
|
1154
|
+
// produced "composer did not rebind after entering project" - a temporary
|
|
1155
|
+
// chat is never saved, a project chat is, and entering a project leaves
|
|
1156
|
+
// temporary mode.
|
|
1145
1157
|
const selectionProject = explicitProject ??
|
|
1146
|
-
(normalizedTargetUrl || selectionProjectNew !== undefined || suppressProject
|
|
1158
|
+
(normalizedTargetUrl || selectionProjectNew !== undefined || suppressProject || temporary
|
|
1159
|
+
? undefined
|
|
1160
|
+
: browserDefaults?.project);
|
|
1147
1161
|
const reasoningAxisChosen = explicitProMode !== undefined || explicitEffort !== undefined;
|
|
1148
1162
|
const selectionProMode = explicitProMode ?? (reasoningAxisChosen ? undefined : browserDefaults?.pro_mode);
|
|
1149
1163
|
const selectionEffort = explicitEffort ?? (reasoningAxisChosen ? undefined : browserDefaults?.effort);
|
|
@@ -1796,6 +1810,19 @@ export function proSelectionVerified(selection) {
|
|
|
1796
1810
|
return undefined;
|
|
1797
1811
|
return /pro/i.test(selection.modelSlug);
|
|
1798
1812
|
}
|
|
1813
|
+
/**
|
|
1814
|
+
* A temporary chat is not saved; a project chat is. Entering a project leaves
|
|
1815
|
+
* temporary mode, so asking for both is asking for two different things, and
|
|
1816
|
+
* prodex used to attempt both and die inside the project step with "composer
|
|
1817
|
+
* did not rebind". A pinned default project is suppressed instead of refused:
|
|
1818
|
+
* the per-call flag is the more specific instruction.
|
|
1819
|
+
*/
|
|
1820
|
+
export function temporaryProjectConflict(input) {
|
|
1821
|
+
if (!input.temporary || input.explicitProject === undefined)
|
|
1822
|
+
return undefined;
|
|
1823
|
+
return (`--temporary and --project cannot be combined: a temporary chat is never saved, and a chat inside a project is. ` +
|
|
1824
|
+
`Drop --temporary to send into "${input.explicitProject}", or drop --project to send a throwaway chat.`);
|
|
1825
|
+
}
|
|
1799
1826
|
export function browserSendBlockerFromError(error) {
|
|
1800
1827
|
const blocker = typeof error === "object" && error !== null && "blocker" in error ? error.blocker : undefined;
|
|
1801
1828
|
if (typeof blocker === "object" &&
|