ask-pro 0.1.44 → 0.1.48
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/src/browser/actions/assistantResponse.js +17 -5
- package/dist/src/browser/actions/thinkingTime.js +11 -11
- package/dist/src/browser/constants.js +2 -2
- package/dist/src/browser/index.js +10 -14
- package/dist/src/browser/reattach.js +3 -0
- package/dist/src/browser/reattachHelpers.js +2 -2
- package/package.json +1 -1
|
@@ -100,6 +100,8 @@ async function waitForAssistantResponseOnce(Runtime, timeoutMs, logger, minTurnI
|
|
|
100
100
|
const winner = await Promise.race([raceReadyEvaluation, pollerPromise]);
|
|
101
101
|
if (winner.kind === "poll") {
|
|
102
102
|
if (!winner.value) {
|
|
103
|
+
evaluationPromise.catch(() => undefined);
|
|
104
|
+
await terminateRuntimeExecution(Runtime);
|
|
103
105
|
throw { source: "poll", error: new Error(ASSISTANT_POLL_TIMEOUT_ERROR) };
|
|
104
106
|
}
|
|
105
107
|
logger("Captured assistant response via snapshot watchdog");
|
|
@@ -120,7 +122,7 @@ async function waitForAssistantResponseOnce(Runtime, timeoutMs, logger, minTurnI
|
|
|
120
122
|
if (source === "poll" &&
|
|
121
123
|
error instanceof Error &&
|
|
122
124
|
error.message === ASSISTANT_POLL_TIMEOUT_ERROR) {
|
|
123
|
-
|
|
125
|
+
throw new Error("Timed out waiting for assistant response");
|
|
124
126
|
}
|
|
125
127
|
else if (source === "poll") {
|
|
126
128
|
pollerAbort.abort();
|
|
@@ -385,7 +387,7 @@ async function pollAssistantCompletion(Runtime, timeoutMs, minTurnIndex, expecte
|
|
|
385
387
|
async function isStopButtonVisible(Runtime) {
|
|
386
388
|
try {
|
|
387
389
|
const { result } = await Runtime.evaluate({
|
|
388
|
-
expression:
|
|
390
|
+
expression: visibleStopButtonExpression(JSON.stringify(STOP_BUTTON_SELECTOR)),
|
|
389
391
|
returnByValue: true,
|
|
390
392
|
});
|
|
391
393
|
return Boolean(result?.value);
|
|
@@ -394,6 +396,13 @@ async function isStopButtonVisible(Runtime) {
|
|
|
394
396
|
return false;
|
|
395
397
|
}
|
|
396
398
|
}
|
|
399
|
+
function visibleStopButtonExpression(selector) {
|
|
400
|
+
return `Array.from(document.querySelectorAll(${selector})).some((node) => {
|
|
401
|
+
const style = getComputedStyle(node);
|
|
402
|
+
const rect = node.getBoundingClientRect();
|
|
403
|
+
return rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none' && style.opacity !== '0';
|
|
404
|
+
})`;
|
|
405
|
+
}
|
|
397
406
|
async function isCompletionVisible(Runtime) {
|
|
398
407
|
try {
|
|
399
408
|
const { result } = await Runtime.evaluate({
|
|
@@ -676,7 +685,7 @@ function buildResponseObserverExpression(timeoutMs, minTurnIndex, expectedConver
|
|
|
676
685
|
} else {
|
|
677
686
|
stableCycles += 1;
|
|
678
687
|
}
|
|
679
|
-
const stopVisible =
|
|
688
|
+
const stopVisible = ${visibleStopButtonExpression("STOP_SELECTOR")};
|
|
680
689
|
const finishedVisible = isLastAssistantTurnFinished();
|
|
681
690
|
|
|
682
691
|
if (finishedVisible || (!stopVisible && stableCycles >= stableTarget)) {
|
|
@@ -772,7 +781,7 @@ function buildAssistantExtractor(functionName) {
|
|
|
772
781
|
button => (button.textContent || '').trim().toLowerCase() === 'stopped thinking',
|
|
773
782
|
);
|
|
774
783
|
if (index === turns.length - 1 && stopped && turnText.toLowerCase() === 'stopped thinking' &&
|
|
775
|
-
!
|
|
784
|
+
!(${visibleStopButtonExpression(JSON.stringify(STOP_BUTTON_SELECTOR))})) {
|
|
776
785
|
return { text: '', stoppedWithoutAnswer: true, turnIndex: index };
|
|
777
786
|
}
|
|
778
787
|
expandCollapsibles(messageRoot);
|
|
@@ -868,7 +877,7 @@ function buildMarkdownFallbackExtractor(minTurnLiteral) {
|
|
|
868
877
|
document.querySelector('[role="main"]'),
|
|
869
878
|
].filter(Boolean);
|
|
870
879
|
if (roots.length === 0) return null;
|
|
871
|
-
const markdownSelector = '
|
|
880
|
+
const markdownSelector = 'div[class*="MarkdownRoot-"],.markdown,[data-message-content],[data-testid*="message"],.prose,[class*="markdown"]';
|
|
872
881
|
const isExcluded = (node) =>
|
|
873
882
|
Boolean(
|
|
874
883
|
node?.querySelector?.('[data-streaming-response-status]') || node?.closest?.(
|
|
@@ -923,6 +932,7 @@ function buildMarkdownFallbackExtractor(minTurnLiteral) {
|
|
|
923
932
|
};
|
|
924
933
|
const markdowns = Array.from(root.querySelectorAll(markdownSelector))
|
|
925
934
|
.filter((node) => !isExcluded(node))
|
|
935
|
+
.filter((node) => !node.closest('div[class*="MarkdownRoot-"]') || node.matches('div[class*="MarkdownRoot-"]'))
|
|
926
936
|
.filter((node) => {
|
|
927
937
|
const container = node.closest('[data-message-author-role], [data-turn]');
|
|
928
938
|
if (!container) return true;
|
|
@@ -942,6 +952,7 @@ function buildMarkdownFallbackExtractor(minTurnLiteral) {
|
|
|
942
952
|
if (!container || container === root || container === document.body) continue;
|
|
943
953
|
const scoped = Array.from(container.querySelectorAll(markdownSelector))
|
|
944
954
|
.filter((node) => !isExcluded(node))
|
|
955
|
+
.filter((node) => !node.closest('div[class*="MarkdownRoot-"]') || node.matches('div[class*="MarkdownRoot-"]'))
|
|
945
956
|
.filter((node) => {
|
|
946
957
|
const roleNode = node.closest('[data-message-author-role], [data-turn]');
|
|
947
958
|
if (!roleNode) return true;
|
|
@@ -1242,4 +1253,5 @@ function cleanAssistantText(text) {
|
|
|
1242
1253
|
export const __test__ = {
|
|
1243
1254
|
buildResponseObserverExpression,
|
|
1244
1255
|
recoverAssistantResponse,
|
|
1256
|
+
visibleStopButtonExpression,
|
|
1245
1257
|
};
|
|
@@ -281,6 +281,7 @@ function buildThinkingTimeExpression(level) {
|
|
|
281
281
|
const text = normalize(menu.textContent ?? '');
|
|
282
282
|
const testId = normalize(menu.getAttribute?.('data-testid') ?? '');
|
|
283
283
|
return (
|
|
284
|
+
Boolean(menu.querySelector('[data-reasoning-slider="true"] [role="slider"][aria-valuemax]')) ||
|
|
284
285
|
testId.includes('composer intelligence picker content') ||
|
|
285
286
|
(
|
|
286
287
|
text.includes('intelligence') &&
|
|
@@ -297,22 +298,21 @@ function buildThinkingTimeExpression(level) {
|
|
|
297
298
|
if (!menu) return null;
|
|
298
299
|
const target = findOptionInMenu(menu, { currentIntelligence: true });
|
|
299
300
|
if (!target) {
|
|
300
|
-
const slider = menu.querySelector(
|
|
301
|
-
'[data-model-reasoning-effort-slider] [role="slider"][aria-valuemax]'
|
|
302
|
-
);
|
|
301
|
+
const slider = menu.querySelector('[role="slider"][aria-valuemax]');
|
|
303
302
|
if (TARGET_LEVEL !== 'pro' || !slider) return null;
|
|
304
303
|
const max = Number(slider.getAttribute('aria-valuemax'));
|
|
305
304
|
const before = Number(slider.getAttribute('aria-valuenow'));
|
|
306
305
|
if (!Number.isFinite(max) || !Number.isFinite(before)) return null;
|
|
307
306
|
if (before < max) {
|
|
308
|
-
slider.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
'
|
|
314
|
-
|
|
315
|
-
|
|
307
|
+
const control = slider.closest?.('[data-reasoning-slider="true"]') ?? slider;
|
|
308
|
+
control.focus?.();
|
|
309
|
+
for (let step = 0; step < 5; step++) {
|
|
310
|
+
if (Number(menu.querySelector('[role="slider"][aria-valuemax]')?.getAttribute('aria-valuenow')) >= max) break;
|
|
311
|
+
control.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', code: 'ArrowRight', bubbles: true }));
|
|
312
|
+
control.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowRight', code: 'ArrowRight', bubbles: true }));
|
|
313
|
+
await sleep(STEP_WAIT_MS);
|
|
314
|
+
}
|
|
315
|
+
if (Number(menu.querySelector('[role="slider"][aria-valuemax]')?.getAttribute('aria-valuenow')) < max) return null;
|
|
316
316
|
}
|
|
317
317
|
return { status: before >= max ? 'already-selected' : 'switched', label: 'Pro' };
|
|
318
318
|
}
|
|
@@ -63,7 +63,7 @@ export const UPLOAD_STATUS_SELECTORS = [
|
|
|
63
63
|
'[aria-live="polite"]',
|
|
64
64
|
'[aria-live="assertive"]',
|
|
65
65
|
];
|
|
66
|
-
export const STOP_BUTTON_SELECTOR = '[data-testid="stop-button"]';
|
|
66
|
+
export const STOP_BUTTON_SELECTOR = '[data-testid="stop-button"], button[aria-label="Stop"]';
|
|
67
67
|
export const SEND_BUTTON_SELECTORS = [
|
|
68
68
|
'button[data-testid="send-button"]',
|
|
69
69
|
'button[data-testid*="composer-send"]',
|
|
@@ -72,7 +72,7 @@ export const SEND_BUTTON_SELECTORS = [
|
|
|
72
72
|
'button[aria-label*="Send"]',
|
|
73
73
|
];
|
|
74
74
|
export const SEND_BUTTON_SELECTOR = SEND_BUTTON_SELECTORS[0];
|
|
75
|
-
export const MODEL_BUTTON_SELECTOR = '[data-testid="model-switcher-dropdown-button"], button.__composer-pill[aria-haspopup="menu"], button.__composer-pill';
|
|
75
|
+
export const MODEL_BUTTON_SELECTOR = 'button[aria-label="Select ChatGPT model"], [data-testid="model-switcher-dropdown-button"], button.__composer-pill[aria-haspopup="menu"], button.__composer-pill';
|
|
76
76
|
export const COPY_BUTTON_SELECTORS = [
|
|
77
77
|
'button[data-testid="copy-turn-action-button"]',
|
|
78
78
|
'button[aria-label="Copy response"]',
|
|
@@ -20,7 +20,7 @@ import { CHATGPT_URL, CONVERSATION_TURN_SELECTOR, DEFAULT_MODEL_STRATEGY } from
|
|
|
20
20
|
import { AssistantStoppedError, BrowserAutomationError } from "./errors.js";
|
|
21
21
|
import { defaultAskProBrowserProfileDir } from "./profilePaths.js";
|
|
22
22
|
import { applyPageLanguageOverrides, seedChromeProfileLanguage } from "./language.js";
|
|
23
|
-
import { alignPromptEchoPair, buildPromptEchoMatcher, withTimeout } from "./reattachHelpers.js";
|
|
23
|
+
import { alignPromptEchoPair, buildPromptEchoMatcher, extractConversationIdFromUrl, withTimeout, } from "./reattachHelpers.js";
|
|
24
24
|
import { cleanupStaleProfileState, acquireProfileRunLock, createManagedChromeRunLease, releaseManagedChromeRunLeaseAndCountPeers, readDevToolsPort, shouldCleanupManualLoginProfileState, verifyDevToolsReachable, writeChromePid, writeDevToolsActivePort, } from "./profileState.js";
|
|
25
25
|
import { runProviderSubmissionFlow } from "./providerDomFlow.js";
|
|
26
26
|
import { chatgptDomProvider } from "./providers/chatgptDomProvider.js";
|
|
@@ -851,13 +851,7 @@ export async function runBrowserMode(options) {
|
|
|
851
851
|
logger(`[retry] Model picker attempt ${attempt + 1}: ${error instanceof Error ? error.message : error}`);
|
|
852
852
|
}
|
|
853
853
|
},
|
|
854
|
-
}))
|
|
855
|
-
const base = error instanceof Error ? error.message : String(error);
|
|
856
|
-
const hint = appliedCookies === 0
|
|
857
|
-
? " No cookies were applied; sign in to ChatGPT in the opened browser, then resume."
|
|
858
|
-
: "";
|
|
859
|
-
throw new Error(`${base}${hint}`);
|
|
860
|
-
});
|
|
854
|
+
}));
|
|
861
855
|
await raceWithDisconnect(ensurePromptReady(Runtime, config.inputTimeoutMs, logger));
|
|
862
856
|
logger(`Prompt textarea ready (after model switch, ${promptText.length.toLocaleString()} chars queued)`);
|
|
863
857
|
}
|
|
@@ -2375,7 +2369,9 @@ export const __test__ = {
|
|
|
2375
2369
|
isLoginRecoveryUrl,
|
|
2376
2370
|
isEligibleManualLoginRecoveryTarget,
|
|
2377
2371
|
isRecoveredTargetOwned,
|
|
2372
|
+
isConversationUrl,
|
|
2378
2373
|
waitForLogin,
|
|
2374
|
+
waitForAssistantResponseWithReload,
|
|
2379
2375
|
};
|
|
2380
2376
|
export { syncCookies } from "./cookies.js";
|
|
2381
2377
|
export { navigateToChatGPT, ensureNotBlocked, ensurePromptReady, ensureModelSelection, submitPrompt, waitForAssistantResponse, captureAssistantMarkdown, uploadAttachmentFile, waitForAttachmentCompletion, } from "./pageActions.js";
|
|
@@ -2388,6 +2384,7 @@ export function isWebSocketClosureError(error) {
|
|
|
2388
2384
|
message.includes("target closed"));
|
|
2389
2385
|
}
|
|
2390
2386
|
async function waitForAssistantResponseWithReload(Runtime, Page, timeoutMs, logger, minTurnIndex, expectedConversationUrl, expectedConversationId, continueResponse) {
|
|
2387
|
+
const deadline = Date.now() + timeoutMs;
|
|
2391
2388
|
try {
|
|
2392
2389
|
return await waitForAssistantResponse(Runtime, timeoutMs, logger, minTurnIndex, expectedConversationId, continueResponse);
|
|
2393
2390
|
}
|
|
@@ -2399,10 +2396,13 @@ async function waitForAssistantResponseWithReload(Runtime, Page, timeoutMs, logg
|
|
|
2399
2396
|
if (!conversationUrl || !isConversationUrl(conversationUrl)) {
|
|
2400
2397
|
throw error;
|
|
2401
2398
|
}
|
|
2399
|
+
const remainingMs = deadline - Date.now();
|
|
2400
|
+
if (remainingMs <= 0)
|
|
2401
|
+
throw error;
|
|
2402
2402
|
logger("Assistant response stalled; reloading conversation and retrying once");
|
|
2403
2403
|
await Page.navigate({ url: conversationUrl });
|
|
2404
2404
|
await delay(1000);
|
|
2405
|
-
return await waitForAssistantResponse(Runtime,
|
|
2405
|
+
return await waitForAssistantResponse(Runtime, Math.max(1, deadline - Date.now()), logger, minTurnIndex, expectedConversationId, continueResponse);
|
|
2406
2406
|
}
|
|
2407
2407
|
}
|
|
2408
2408
|
function shouldReloadAfterAssistantError(error) {
|
|
@@ -2567,7 +2567,7 @@ async function readConversationTurnCount(Runtime, logger) {
|
|
|
2567
2567
|
return null;
|
|
2568
2568
|
}
|
|
2569
2569
|
function isConversationUrl(url) {
|
|
2570
|
-
return
|
|
2570
|
+
return Boolean(extractConversationIdFromUrl(url));
|
|
2571
2571
|
}
|
|
2572
2572
|
function describeDevtoolsFirewallHint(host, port) {
|
|
2573
2573
|
if (!isWsl())
|
|
@@ -2589,10 +2589,6 @@ function isWsl() {
|
|
|
2589
2589
|
return true;
|
|
2590
2590
|
return os.release().toLowerCase().includes("microsoft");
|
|
2591
2591
|
}
|
|
2592
|
-
function extractConversationIdFromUrl(url) {
|
|
2593
|
-
const match = url.match(/\/c\/([a-zA-Z0-9-]+)/);
|
|
2594
|
-
return match?.[1];
|
|
2595
|
-
}
|
|
2596
2592
|
async function resolveUserDataBaseDir() {
|
|
2597
2593
|
// On WSL, Chrome launched via Windows can choke on UNC paths; prefer a Windows-backed temp folder.
|
|
2598
2594
|
if (isWsl()) {
|
|
@@ -89,6 +89,9 @@ async function closeManagedChromeIfUnused(chrome, userDataDir, inspectRemainingP
|
|
|
89
89
|
await cleanupStaleProfileState(userDataDir, logger, { lockRemovalMode: "never" }).catch(() => undefined);
|
|
90
90
|
}
|
|
91
91
|
export async function resumeBrowserSession(runtime, config, logger, deps = {}) {
|
|
92
|
+
if (runtime.conversationId === "WEB" && runtime.tabUrl?.includes("/c/WEB:")) {
|
|
93
|
+
runtime = { ...runtime, conversationId: undefined, tabUrl: undefined };
|
|
94
|
+
}
|
|
92
95
|
deps = { ...deps, continuationState: deps.continuationState ?? { used: false } };
|
|
93
96
|
const recoverSession = deps.recoverSession ??
|
|
94
97
|
(async (runtimeMeta, configMeta) => resumeBrowserSessionViaNewChrome(runtimeMeta, configMeta, logger, deps));
|
|
@@ -21,12 +21,12 @@ export function pickTarget(targets, runtime) {
|
|
|
21
21
|
export function extractConversationIdFromUrl(url) {
|
|
22
22
|
if (!url)
|
|
23
23
|
return undefined;
|
|
24
|
-
const match = url.match(/\/c\/([a-zA-Z0-9-]+)/);
|
|
24
|
+
const match = url.match(/\/c\/([a-zA-Z0-9-]+)(?:[/?#]|$)/);
|
|
25
25
|
return match?.[1];
|
|
26
26
|
}
|
|
27
27
|
export function buildConversationUrl(runtime, baseUrl) {
|
|
28
28
|
if (runtime.tabUrl) {
|
|
29
|
-
if (runtime.tabUrl
|
|
29
|
+
if (extractConversationIdFromUrl(runtime.tabUrl)) {
|
|
30
30
|
return runtime.tabUrl;
|
|
31
31
|
}
|
|
32
32
|
return null;
|