@steipete/oracle 0.17.1 → 0.17.2
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/bin/oracle-cli.js +1 -1
- package/dist/docs-site/browser-mode.html +7 -5
- package/dist/docs-site/cli-reference.html +1 -1
- package/dist/docs-site/configuration.html +1 -1
- package/dist/docs-site/manual-tests.html +2 -1
- package/dist/docs-site/mcp.html +2 -2
- package/dist/docs-site/windows-work.html +1 -1
- package/dist/docs-site/windows.html +1 -1
- package/dist/scripts/git-policy.js +0 -8
- package/dist/scripts/runner.js +1 -5
- package/dist/src/browser/actions/modelSelection.js +164 -5
- package/dist/src/browser/actions/thinkingTime.js +181 -11
- package/dist/src/cli/browserConfig.js +5 -2
- package/dist/src/cli/options.js +1 -1
- package/dist/src/oracle/thinkingTime.js +6 -0
- package/dist/src/sessionManager.js +90 -9
- package/package.json +10 -10
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/Info.plist +0 -20
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/Resources/OracleIcon.icns +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/_CodeSignature/CodeResources +0 -128
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/Info.plist +0 -20
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/Resources/OracleIcon.icns +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/_CodeSignature/CodeResources +0 -128
package/dist/bin/oracle-cli.js
CHANGED
|
@@ -339,7 +339,7 @@ program
|
|
|
339
339
|
.addOption(new Option("--browser-hide-window", "Hide the Chrome window after launch (macOS headful only).").hideHelp())
|
|
340
340
|
.addOption(new Option("--browser-keep-browser", "Keep Chrome running after completion.").hideHelp())
|
|
341
341
|
.addOption(new Option("--browser-model-strategy <mode>", "ChatGPT model picker strategy: select (default) switches to the requested model, current keeps the active model, ignore skips the picker entirely.").choices(["select", "current", "ignore"]))
|
|
342
|
-
.addOption(new Option("--browser-thinking-time <level>", "Thinking time intensity for Thinking/Pro models: light, standard, extended, extra-high (Extra High),
|
|
342
|
+
.addOption(new Option("--browser-thinking-time <level>", "Thinking time intensity for Thinking/Pro models: light, standard, extended, extra-high (Extra High), pro (Pro tier of the active model), heavy, or ChatGPT UI aliases.")
|
|
343
343
|
.argParser(parseThinkingTimeOption)
|
|
344
344
|
.hideHelp())
|
|
345
345
|
.addOption(new Option("--browser-research <mode>", "Browser research mode: deep activates ChatGPT Deep Research.").choices(["off", "deep"]))
|
|
@@ -259,7 +259,8 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
259
259
|
<span class="line"><span style="color:#F69D50">jq</span><span style="color:#96D0FF"> '.'</span><span style="color:#96D0FF"> ~/.oracle/cookies.json</span><span style="color:#768390"> # file must contain CookieParam[]</span></span>
|
|
260
260
|
<span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --engine</span><span style="color:#96D0FF"> browser</span><span style="color:#F47067"> \</span></span>
|
|
261
261
|
<span class="line"><span style="color:#6CB6FF"> --browser-inline-cookies-file</span><span style="color:#96D0FF"> ~/.oracle/cookies.json</span><span style="color:#F47067"> \</span></span>
|
|
262
|
-
<span class="line"><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF">
|
|
262
|
+
<span class="line"><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.5</span><span style="color:#F47067"> \</span></span>
|
|
263
|
+
<span class="line"><span style="color:#6CB6FF"> --browser-thinking-time</span><span style="color:#96D0FF"> pro</span><span style="color:#F47067"> \</span></span>
|
|
263
264
|
<span class="line"><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Run the UI smoke"</span><span style="color:#F47067"> \</span></span>
|
|
264
265
|
<span class="line"><span style="color:#6CB6FF"> --file</span><span style="color:#96D0FF"> "src/**/*.ts"</span><span style="color:#6CB6FF"> --file</span><span style="color:#96D0FF"> "!src/**/*.test.ts"</span></span></code></pre>
|
|
265
266
|
<p><code>~/.oracle/cookies.json</code> should be a JSON array shaped like:</p>
|
|
@@ -279,13 +280,14 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
279
280
|
<p>Use this when you already have a signed-in Chrome session running with DevTools access enabled and want Oracle to reuse that browser instead of launching its own copy.</p>
|
|
280
281
|
<pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --engine</span><span style="color:#96D0FF"> browser</span><span style="color:#F47067"> \</span></span>
|
|
281
282
|
<span class="line"><span style="color:#6CB6FF"> --browser-attach-running</span><span style="color:#F47067"> \</span></span>
|
|
282
|
-
<span class="line"><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF">
|
|
283
|
+
<span class="line"><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.5</span><span style="color:#F47067"> \</span></span>
|
|
284
|
+
<span class="line"><span style="color:#6CB6FF"> --browser-thinking-time</span><span style="color:#96D0FF"> pro</span><span style="color:#F47067"> \</span></span>
|
|
283
285
|
<span class="line"><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Summarize the last assistant response in one paragraph"</span></span></code></pre>
|
|
284
286
|
<p>Notes:</p>
|
|
285
287
|
<ul>
|
|
286
288
|
<li><code>--browser-attach-running</code> defaults to local attach discovery at <code>127.0.0.1:9222</code>.</li>
|
|
287
289
|
<li>If the browser UI shows a different local endpoint, you can point Oracle at it explicitly:</li>
|
|
288
|
-
<p>``<code>bash oracle --engine browser \ --browser-attach-running \ --remote-chrome 127.0.0.1:63332 \ --model
|
|
290
|
+
<p>``<code>bash oracle --engine browser \ --browser-attach-running \ --remote-chrome 127.0.0.1:63332 \ --model gpt-5.5 \ --browser-thinking-time pro \ -p "Summarize the last assistant response in one paragraph" </code>``</p>
|
|
289
291
|
<li>Oracle reads local <code>DevToolsActivePort</code> metadata, connects to the browser websocket directly, and then reuses the normal CDP automation flow.</li>
|
|
290
292
|
<li>If Chrome shows a remote-debugging approval prompt on first attach, Oracle issues one attach request and waits briefly for you to allow it before failing.</li>
|
|
291
293
|
<li>Attach mode always opens a fresh Oracle-owned tab and closes only that tab after a successful run.</li>
|
|
@@ -301,7 +303,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
301
303
|
<li>Launcher mode starts Chrome via <code>chrome-launcher</code> and connects with <code>chrome-remote-interface</code>.</li>
|
|
302
304
|
<li>Attach-running mode reads local <code>DevToolsActivePort</code> metadata for the selected local port, connects to the browser websocket, opens a dedicated tab, and reuses the same DOM automation/capture flow against that attached browser.</li>
|
|
303
305
|
<li>Launcher mode can optionally copy cookies from the requested browser profile via Oracle’s built-in cookie reader (Keychain/DPAPI aware) so you stay signed in.</li>
|
|
304
|
-
<li>Navigates to <code>chatgpt.com</code>, switches the model to the requested GPT-5.5 / GPT-5.4 / GPT-5.2 variant, optionally activates Deep Research, pastes the prompt, waits for completion, and copies the markdown via the built-in “copy turn” button.</li>
|
|
306
|
+
<li>Navigates to <code>chatgpt.com</code>, switches the model to the requested GPT-5.5 / GPT-5.4 / GPT-5.2 variant (including <code>Advanced</code> → <code>Model</code> in the unified picker), optionally activates Deep Research, pastes the prompt, waits for completion, and copies the markdown via the built-in “copy turn” button.</li>
|
|
305
307
|
<li>Immediately probes the cookie-authenticated <code>/api/auth/session</code> endpoint in the ChatGPT tab and checks only whether it contains a user; returned tokens are never logged. If that endpoint is unavailable, Oracle falls back to the legacy <code>/backend-api/me</code> probe and a visible composer plus profile or chat-history authentication signals. Auth pages, visible login controls, resolved sessions without a user, composer-only shells, and pages without profile/history signals still fail with login guidance.</li>
|
|
306
308
|
<li>When <code>--file</code> inputs would push the pasted composer content over ~60k characters, we switch to uploading attachments (optionally bundled) and wait for ChatGPT to re-enable the send button before submitting the combined system+user prompt.</li>
|
|
307
309
|
<li>Launcher mode cleans up the temporary profile unless <code>--browser-keep-browser</code> is passed.</li>
|
|
@@ -327,7 +329,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
327
329
|
<li>If an assistant response still times out (common with long Pro runs), Oracle marks the session as an incomplete capture, stores reattach/runtime diagnostics, and keeps enough browser metadata for <code>oracle session <id></code> to recover the final answer. Visible ChatGPT rate-limit, temporary-unavailable, and authentication/challenge warnings are included in the error and session metadata instead of being reduced to a generic timeout. Increase <code>--browser-timeout</code> only when the browser session is truly unrecoverable.</li>
|
|
328
330
|
<li><code>--browser-model-strategy <select|current|ignore></code>: control ChatGPT model selection. <code>select</code> (default) switches to the requested model; <code>current</code> keeps the active model and logs its label; <code>ignore</code> skips the picker entirely. (Ignored for Gemini web runs.)</li>
|
|
329
331
|
<li>Temporary Chat can reduce account-sidebar clutter for one-shot browser consults, but it is a different ChatGPT workflow: Oracle skips archive attempts there and the local transcript/artifacts are the durable record. Verify live behavior before relying on Project Sources, Deep Research reports, or multi-turn persistence.</li>
|
|
330
|
-
<li><code>--browser-thinking-time <light|standard|extended|extra-high|heavy></code>: set the ChatGPT thinking-time intensity (Thinking/Pro models only). On GPT-5.6 Sol, <code>extra-high</code> selects Extra High; a <code>heavy</code> request accepts an already-selected Pro pill but otherwise selects only a matching Heavy row. Effort rows are matched in English, German (<code>Sofort</code>/<code>Mittel</code>/<code>Hoch</code>/<code>Sehr hoch</code>), and Chinese; when the requested tier has no row in the current UI language, Oracle keeps the effort already selected in the tab instead of switching the model. You can also set a default in <code>~/.oracle/config.json</code> via <code>browser.thinkingTime</code>.</li>
|
|
332
|
+
<li><code>--browser-thinking-time <light|standard|extended|extra-high|pro|heavy></code>: set the ChatGPT thinking-time intensity (Thinking/Pro models only). On GPT-5.6 Sol, <code>extra-high</code> selects Extra High; a <code>heavy</code> request accepts an already-selected Pro pill but otherwise selects only a matching Heavy row. <code>--model gpt-5.5-pro</code> and older Pro aliases select GPT-5.5 with Pro effort automatically; use <code>--model gpt-5.5 --browser-thinking-time pro</code> for the equivalent explicit form, or pass another thinking-time value to override the alias default. Because Pro is expensive and rate-limited, <code>pro</code> fails closed: an unconfirmed selection aborts the run rather than quietly submitting at a cheaper tier. Effort rows are matched in English, German (<code>Sofort</code>/<code>Mittel</code>/<code>Hoch</code>/<code>Sehr hoch</code>), and Chinese; when the requested tier has no row in the current UI language, Oracle keeps the effort already selected in the tab instead of switching the model. In ChatGPT's unified Intelligence picker Oracle opens <code>Advanced</code> → <code>Model</code> first, verifies the requested version, then opens <code>Advanced</code> → <code>Effort</code>; if either opener label is not recognized it declines to guess which control to use. You can also set a default in <code>~/.oracle/config.json</code> via <code>browser.thinkingTime</code>.</li>
|
|
331
333
|
<li>GPT-5.5 Pro Extended is verified from the selected item in ChatGPT's standalone Pro/Thinking effort pill or compatible Intelligence/model-picker menu. A run <strong>fails closed</strong> if Extended cannot be confirmed rather than silently submitting at a weaker effort. Detection failures write a bounded, redacted model-picker diagnostic to the normal session log.</li>
|
|
332
334
|
<li><code>--browser-research deep</code>: activate ChatGPT Deep Research before submitting the prompt. Use this for broad public-web research and final cited reports, not as a replacement for GPT-5.x Pro Heavy code review or pure reasoning.</li>
|
|
333
335
|
<li><code>--browser-follow-up <prompt></code>: submit another prompt in the same ChatGPT conversation after the initial answer. Repeat the flag for multi-turn reviews such as “challenge your recommendation”, “compare against this constraint”, then “give the final decision”. Deep Research has its own report lifecycle, so browser follow-ups are rejected when <code>--browser-research deep</code> is enabled.</li>
|
|
@@ -264,7 +264,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
264
264
|
<table><thead><tr><th>Flag</th><th>Purpose</th></tr></thead><tbody><tr><td><code>--base-url <url></code></td><td>LiteLLM / Azure / OpenRouter / proxy.</td></tr><tr><td><code>--provider <mode></code></td><td>API route: <code>auto</code>, <code>openai</code>, or <code>azure</code>.</td></tr><tr><td><code>--no-azure</code></td><td>Ignore Azure env/config for this run.</td></tr><tr><td><code>--route</code></td><td>Print redacted API route plan, then exit.</td></tr><tr><td><code>--azure-endpoint</code></td><td>Azure OpenAI endpoint.</td></tr><tr><td><code>--azure-deployment</code></td><td>Azure deployment name.</td></tr><tr><td><code>--azure-api-version</code></td><td>Azure API version.</td></tr></tbody></table>
|
|
265
265
|
<p>See <a href="openai-endpoints.html">OpenAI / Azure / OpenRouter</a> and <a href="openrouter.html">OpenRouter</a>.</p>
|
|
266
266
|
<h2 id="browser-mode"><a class="anchor" href="#browser-mode" aria-label="Anchor link">#</a>Browser mode</h2>
|
|
267
|
-
<table><thead><tr><th>Flag</th><th>Purpose</th></tr></thead><tbody><tr><td><code>--chatgpt-url <url></code></td><td>Target a ChatGPT workspace / project folder.</td></tr><tr><td><code>--browser-model-strategy <select|current|ignore></code></td><td>Control ChatGPT model picker.</td></tr><tr><td><code>--browser-manual-login</code></td><td>Use persistent profile + manual login (no Keychain).</td></tr><tr><td><code>--browser-attach-running</code></td><td>Attach to your already-running Chrome via DevTools.</td></tr><tr><td><code>--browser-tab <ref></code></td><td>Reuse an existing tab (<code>current</code>, id, URL, title substring).</td></tr><tr><td><code>--browser-thinking-time <light|standard|extended|extra-high|heavy></code></td><td>Effort intensity; unmatched tiers keep the current effort.</td></tr><tr><td><code>--browser-research deep</code></td><td>Activate Deep Research mode.</td></tr><tr><td><code>--browser-follow-up <prompt></code></td><td>Multi-turn in the same ChatGPT conversation.</td></tr><tr><td><code>--browser-port <port></code></td><td>Pin Chrome DevTools port.</td></tr><tr><td><code>--browser-inline-cookies[(-file)] <…></code></td><td>Supply cookies inline (no Keychain / Chrome).</td></tr><tr><td><code>--browser-timeout</code>, <code>--browser-input-timeout</code>, <code>--browser-attachment-timeout</code></td><td>Overall / input / attachment readiness timeouts (h/m/s/ms).</td></tr><tr><td><code>--browser-recheck-delay</code>, <code>--browser-recheck-timeout</code></td><td>Delayed retry after a timeout.</td></tr><tr><td><code>--browser-auto-reattach-delay/-interval/-timeout</code></td><td>Poll the existing tab when ChatGPT redirects mid-load.</td></tr><tr><td><code>--browser-reuse-wait</code></td><td>Wait for shared Chrome profile before launching.</td></tr><tr><td><code>--browser-profile-lock-timeout</code></td><td>Wait for the manual-login profile lock.</td></tr><tr><td><code>--browser-max-concurrent-tabs</code></td><td>Soft limit for shared-profile parallel runs (default 3).</td></tr><tr><td><code>--browser-keep-browser</code></td><td>Keep the browser open after the run.</td></tr><tr><td><code>--browser-headless</code>, <code>--browser-hide-window</code></td><td>Visibility controls.</td></tr><tr><td><code>--browser-attachments <auto|never|always></code></td><td>Attach files inline vs upload.</td></tr><tr><td><code>--browser-bundle-files</code>, <code>--browser-bundle-format <auto|text|zip></code></td><td>Bundle browser uploads as text or byte-preserving ZIP.</td></tr><tr><td><code>--browser-chrome-path</code>, <code>--browser-cookie-path</code></td><td>Override Chrome / cookie store discovery (Linux / Windows).</td></tr></tbody></table>
|
|
267
|
+
<table><thead><tr><th>Flag</th><th>Purpose</th></tr></thead><tbody><tr><td><code>--chatgpt-url <url></code></td><td>Target a ChatGPT workspace / project folder.</td></tr><tr><td><code>--browser-model-strategy <select|current|ignore></code></td><td>Control ChatGPT model picker.</td></tr><tr><td><code>--browser-manual-login</code></td><td>Use persistent profile + manual login (no Keychain).</td></tr><tr><td><code>--browser-attach-running</code></td><td>Attach to your already-running Chrome via DevTools.</td></tr><tr><td><code>--browser-tab <ref></code></td><td>Reuse an existing tab (<code>current</code>, id, URL, title substring).</td></tr><tr><td><code>--browser-thinking-time <light|standard|extended|extra-high|pro|heavy></code></td><td>Effort intensity; <code>pro</code> selects the Pro tier and fails closed if unconfirmed, other unmatched tiers keep the current effort.</td></tr><tr><td><code>--browser-research deep</code></td><td>Activate Deep Research mode.</td></tr><tr><td><code>--browser-follow-up <prompt></code></td><td>Multi-turn in the same ChatGPT conversation.</td></tr><tr><td><code>--browser-port <port></code></td><td>Pin Chrome DevTools port.</td></tr><tr><td><code>--browser-inline-cookies[(-file)] <…></code></td><td>Supply cookies inline (no Keychain / Chrome).</td></tr><tr><td><code>--browser-timeout</code>, <code>--browser-input-timeout</code>, <code>--browser-attachment-timeout</code></td><td>Overall / input / attachment readiness timeouts (h/m/s/ms).</td></tr><tr><td><code>--browser-recheck-delay</code>, <code>--browser-recheck-timeout</code></td><td>Delayed retry after a timeout.</td></tr><tr><td><code>--browser-auto-reattach-delay/-interval/-timeout</code></td><td>Poll the existing tab when ChatGPT redirects mid-load.</td></tr><tr><td><code>--browser-reuse-wait</code></td><td>Wait for shared Chrome profile before launching.</td></tr><tr><td><code>--browser-profile-lock-timeout</code></td><td>Wait for the manual-login profile lock.</td></tr><tr><td><code>--browser-max-concurrent-tabs</code></td><td>Soft limit for shared-profile parallel runs (default 3).</td></tr><tr><td><code>--browser-keep-browser</code></td><td>Keep the browser open after the run.</td></tr><tr><td><code>--browser-headless</code>, <code>--browser-hide-window</code></td><td>Visibility controls.</td></tr><tr><td><code>--browser-attachments <auto|never|always></code></td><td>Attach files inline vs upload.</td></tr><tr><td><code>--browser-bundle-files</code>, <code>--browser-bundle-format <auto|text|zip></code></td><td>Bundle browser uploads as text or byte-preserving ZIP.</td></tr><tr><td><code>--browser-chrome-path</code>, <code>--browser-cookie-path</code></td><td>Override Chrome / cookie store discovery (Linux / Windows).</td></tr></tbody></table>
|
|
268
268
|
<p>See <a href="browser-mode.html">Browser Mode</a> for usage.</p>
|
|
269
269
|
<h2 id="remote-browser"><a class="anchor" href="#remote-browser" aria-label="Anchor link">#</a>Remote browser</h2>
|
|
270
270
|
<table><thead><tr><th>Flag</th><th>Purpose</th></tr></thead><tbody><tr><td><code>--remote-host <host:port></code></td><td>Use a remote <code>oracle serve</code> host.</td></tr><tr><td><code>--remote-token <secret></code></td><td>Auth for the remote host.</td></tr><tr><td><code>--remote-chrome <host:port></code></td><td>Attach to an existing remote Chrome session.</td></tr></tbody></table>
|
|
@@ -283,7 +283,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
283
283
|
<span class="line"><span style="color:#96D0FF"> autoReattachIntervalMs</span><span style="color:#ADBAC7">: </span><span style="color:#6CB6FF">0</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// interval between auto-reattach attempts (0 = disabled)</span></span>
|
|
284
284
|
<span class="line"><span style="color:#96D0FF"> autoReattachTimeoutMs</span><span style="color:#ADBAC7">: </span><span style="color:#6CB6FF">120000</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// time budget per auto-reattach attempt (default: 2m)</span></span>
|
|
285
285
|
<span class="line"><span style="color:#96D0FF"> modelStrategy</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"select"</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// select | current | ignore (ChatGPT only; ignored for Gemini web)</span></span>
|
|
286
|
-
<span class="line"><span style="color:#96D0FF"> thinkingTime</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"extended"</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// light | standard | extended | extra-high | heavy (ChatGPT Thinking/Pro models)</span></span>
|
|
286
|
+
<span class="line"><span style="color:#96D0FF"> thinkingTime</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"extended"</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// light | standard | extended | extra-high | pro | heavy (ChatGPT Thinking/Pro models)</span></span>
|
|
287
287
|
<span class="line"><span style="color:#96D0FF"> researchMode</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"off"</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// off | deep (ChatGPT Deep Research; browser only)</span></span>
|
|
288
288
|
<span class="line"><span style="color:#96D0FF"> manualLogin</span><span style="color:#ADBAC7">: </span><span style="color:#6CB6FF">false</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// set true to reuse a persistent automation profile and sign in once (Windows defaults to true when unset)</span></span>
|
|
289
289
|
<span class="line"><span style="color:#96D0FF"> manualLoginProfileDir</span><span style="color:#ADBAC7">: </span><span style="color:#6CB6FF">null</span><span style="color:#ADBAC7">, </span><span style="color:#768390">// override profile dir (or set ORACLE_BROWSER_PROFILE_DIR)</span></span>
|
|
@@ -434,6 +434,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
434
434
|
<p><code>pnpm run oracle -- --engine browser --model gpt-5.5 --prompt "List two reasons Markdown is handy"</code> Confirm the answer arrives (and only once) even if it takes ~2–3 minutes.</p>
|
|
435
435
|
</ol>
|
|
436
436
|
<p>2b. <strong>GPT-5.5 Instant smoke</strong> <code>pnpm run oracle -- --engine browser --model gpt-5.5-instant --prompt "Give me two short markdown bullet points about tables"</code> Expect a near-instant response (no Thinking spinner) and confirm the composer pill shows the "Instant" row, not "Thinking 5.5" or "Pro". Run after any change to the 5.5 picker tokens.</p>
|
|
437
|
+
<p>2c. <strong>GPT-5.5 Pro effort through the unified picker</strong> <code>pnpm run oracle -- --engine browser --browser-manual-login --model gpt-5.5-pro --write-output response.txt --prompt "Say Hi!"</code> Confirm the logs report a verified GPT-5.5 model followed by <code>Thinking time: Pro</code>, and <code>response.txt</code> contains the captured answer. Exercise both a tab starting on another model and a retained tab where GPT-5.5 is already selected. Never click ChatGPT's "Answer now" shortcut while the Pro response is thinking.</p>
|
|
437
438
|
<ol>
|
|
438
439
|
<li><strong>GPT-5.5 + attachment</strong></li>
|
|
439
440
|
<p>Prepare <code>/tmp/browser-md.txt</code> with a short note, then run <code>pnpm run oracle -- --engine browser --model gpt-5.5 --prompt "Summarize the key idea from the attached note" --file /tmp/browser-md.txt</code> Ensure upload logs show “Attachment queued” and the answer references the file contents explicitly.</p>
|
|
@@ -484,7 +485,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
484
485
|
<ol>
|
|
485
486
|
<li><strong>Launch within tmux</strong></li>
|
|
486
487
|
</ol>
|
|
487
|
-
<p>``<code>bash tmux new -d -s oracle-browser \\ "pnpm run oracle -- --engine browser --browser-keep-browser \\ --model
|
|
488
|
+
<p>``<code>bash tmux new -d -s oracle-browser \\ "pnpm run oracle -- --engine browser --browser-keep-browser \\ --model gpt-5.5 --browser-thinking-time pro --prompt 'Debug via DevTools.'" </code>``</p>
|
|
488
489
|
<p>Keeping the run in tmux prevents your shell from blocking and ensures Chrome stays open afterward.</p>
|
|
489
490
|
<ol>
|
|
490
491
|
<li><strong>Grab the DevTools port</strong></li>
|
package/dist/docs-site/mcp.html
CHANGED
|
@@ -266,11 +266,11 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
266
266
|
<ul>
|
|
267
267
|
<li>Inputs: <code>prompt</code> (required), <code>files?: string[]</code> (globs), <code>model?: string</code> (defaults to CLI), <code>engine?: "api" | "browser"</code> (optional; Oracle follows CLI defaults: <code>ORACLE_ENGINE</code> and the effective config first, then API when <code>OPENAI_API_KEY</code> is set, otherwise browser), <code>slug?: string</code>.</li>
|
|
268
268
|
<li>Presets: <code>preset?: "chatgpt-pro-heavy"</code> applies browser mode + current Pro model alias + extended thinking, unless the request overrides those fields.</li>
|
|
269
|
-
<li>Browser-only extras: <code>browserAttachments?: "auto"|"never"|"always"</code>, <code>browserBundleFiles?: boolean</code>, <code>browserBundleFormat?: "auto"|"text"|"zip"</code>, <code>browserThinkingTime?: "light"|"standard"|"extended"|"extra-high"|"heavy"</code>, <code>browserResearchMode?: "deep"</code>, <code>browserFollowUps?: string[]</code>, <code>browserArchive?: "auto"|"always"|"never"</code>, <code>browserKeepBrowser?: boolean</code>, <code>browserModelLabel?: string</code>, <code>browserModelStrategy?: "select"|"current"|"ignore"</code>, <code>generateImage?: string</code>, <code>outputPath?: string</code>.</li>
|
|
269
|
+
<li>Browser-only extras: <code>browserAttachments?: "auto"|"never"|"always"</code>, <code>browserBundleFiles?: boolean</code>, <code>browserBundleFormat?: "auto"|"text"|"zip"</code>, <code>browserThinkingTime?: "light"|"standard"|"extended"|"extra-high"|"pro"|"heavy"</code>, <code>browserResearchMode?: "deep"</code>, <code>browserFollowUps?: string[]</code>, <code>browserArchive?: "auto"|"always"|"never"</code>, <code>browserKeepBrowser?: boolean</code>, <code>browserModelLabel?: string</code>, <code>browserModelStrategy?: "select"|"current"|"ignore"</code>, <code>generateImage?: string</code>, <code>outputPath?: string</code>.</li>
|
|
270
270
|
<li>Dry runs: set <code>dryRun: true</code> to preview the resolved request without creating a session or touching the browser.</li>
|
|
271
271
|
<li>Behavior: starts a session, runs it with the chosen engine, returns final output + metadata. Background/foreground follows the CLI (e.g., GPT‑5 Pro detaches by default). If API mode fails because <code>OPENAI_API_KEY</code> is missing and you have ChatGPT Pro, retry with <code>engine: "browser"</code> or <code>preset: "chatgpt-pro-heavy"</code> to use your signed-in ChatGPT session instead of an API key.</li>
|
|
272
272
|
<li>Logging: emits MCP logs (<code>info</code> per line, <code>debug</code> for streamed chunks with byte sizes). If browser prerequisites are missing, returns an error payload instead of running.</li>
|
|
273
|
-
<li>Research mode: set <code>browserResearchMode:"deep"</code> for broad public-web research and cited reports. Use normal browser runs with <code>gpt-5.5-pro</code> + <code>browserThinkingTime:"extended"</code> for Pro Extended code review, <code>gpt-5.6-sol</code> + <code>browserThinkingTime:"extra-high"</code> for Extra High, or <code>browserThinkingTime:"
|
|
273
|
+
<li>Research mode: set <code>browserResearchMode:"deep"</code> for broad public-web research and cited reports. Use normal browser runs with <code>gpt-5.5-pro</code> + <code>browserThinkingTime:"extended"</code> for legacy Pro Extended code review, <code>gpt-5.6-sol</code> + <code>browserThinkingTime:"extra-high"</code> for Extra High, or <code>gpt-5.6-sol</code> + <code>browserThinkingTime:"pro"</code> when you explicitly want the current Pro effort tier.</li>
|
|
274
274
|
<li>Multi-turn consults: set <code>browserFollowUps:["Challenge your recommendation", "Give the final decision"]</code> to keep one ChatGPT browser conversation open and ask sequential follow-up prompts. Use one-shot calls for narrow bugs and exact file-set reviews; use multi-turn for ambiguous architecture/product decisions where a challenge pass and final recommendation are useful; use Deep Research for broad public-web work with citations. Oracle never invents follow-ups automatically.</li>
|
|
275
275
|
<li>Archiving: set <code>browserArchive:"auto"|"always"|"never"</code> to control ChatGPT conversation cleanup. <code>auto</code> archives only successful browser one-shots after local artifacts are saved, and skips project, Deep Research, multi-turn, failed, and incomplete sessions.</li>
|
|
276
276
|
<li>ChatGPT image generation: set <code>engine:"browser"</code> and <code>generateImage</code> to a path under <code>ORACLE_HOME_DIR/generated</code> to use the same image-aware wait/download path as CLI <code>--generate-image</code>. Saved files are returned in <code>structuredContent.images</code> and recorded as session artifacts; multiple images save as numbered siblings. Agent-supplied <code>generateImage</code> / <code>outputPath</code> are constrained to that generated-output directory by default (set <code>ORACLE_MCP_ALLOW_EXTERNAL_OUTPUT=1</code> to allow external paths).</li>
|
|
@@ -249,7 +249,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
249
249
|
<ul>
|
|
250
250
|
<li>Browser engine now allowed on Windows; expect more flakiness. If automation fails, rerun with <code>--engine api --wait</code> or point <code>--remote-chrome</code> to a running Chrome with remote debugging.</li>
|
|
251
251
|
<li>Chrome DevTools via mcporter: <code>chrome-devtools</code> server needs <code>CHROME_DEVTOOLS_URL</code> from a live session; without it <code>mcporter call chrome-devtools.*</code> fails. Expect this to be unset on Windows unless you bring your own Chrome session/URL.</li>
|
|
252
|
-
<li>agent-scripts
|
|
252
|
+
<li>The agent-scripts <code>runner</code> helper can fail under PowerShell/CMD because of CRLF and bash expectations. If it explodes, run commands directly (<code>pnpm ...</code>, <code>git add/commit</code>) instead.</li>
|
|
253
253
|
<li>browser-tools binary: not built in <code>agent-scripts/bin</code> on Windows; <code>pnpm tsx scripts/browser-tools.ts</code> also fails there (no package manifest). Use a macOS-built binary or run from macOS if you need it.</li>
|
|
254
254
|
<li>Prefer PowerShell + pnpm directly; watch for CRLF warnings when touching tracked files.</li>
|
|
255
255
|
<li>WSL browser launch host detection: a systemd-resolved stub such as <code>nameserver 127.0.0.53</code> is guest loopback, not the Windows host. Keep resolver-derived non-loopback hosts for Windows Chrome compatibility, but route resolver-derived <code>127/8</code> values to the standard local Chrome launcher.</li>
|
|
@@ -252,7 +252,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
252
252
|
<li>Manual login flow: run with <code>--browser-manual-login</code> and sign into chatgpt.com in the opened Chrome; Oracle waits until the session is active. For initial login/setup or debugging, add <code>--browser-keep-browser</code> to keep the window open after the run; otherwise Oracle closes Chrome but preserves the profile at <code>~/.oracle/browser-profile</code> (override with <code>ORACLE_BROWSER_PROFILE_DIR</code> or <code>browser.manualLoginProfileDir</code> in <code>~/.oracle/config.json</code>). If that automation Chrome is already running with remote debugging enabled (DevToolsActivePort present), reuse it instead of relaunching by pointing Oracle at it via <code>--remote-chrome <host:port></code>.</li>
|
|
253
253
|
<li>Cookie paths: preferred path is <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\<Profile>\\Network\\Cookies</code>. If that errors, try the top-level <code>Cookies</code> file or supply the exact path via <code>--browser-cookie-path</code>.</li>
|
|
254
254
|
<li>mcporter chrome-devtools: requires a valid <code>CHROME_DEVTOOLS_URL</code> from a live session; otherwise calls will fail.</li>
|
|
255
|
-
<li>agent-scripts
|
|
255
|
+
<li>The agent-scripts <code>runner</code> helper is bash-based and may fail under PowerShell/CMD; run commands directly if it misbehaves.</li>
|
|
256
256
|
</ul><nav class="page-nav" aria-label="Pager"><a class="page-nav-prev" href="linux.html"><small>Previous</small><span>Linux Notes</span></a><a class="page-nav-next" href="windows-work.html"><small>Next</small><span>Windows Work</span></a></nav></article>
|
|
257
257
|
|
|
258
258
|
</div>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
-
const COMMIT_HELPER_SUBCOMMANDS = new Set(["add", "commit"]);
|
|
3
2
|
const GUARDED_SUBCOMMANDS = new Set(["push", "pull", "merge", "rebase", "cherry-pick"]);
|
|
4
3
|
const DESTRUCTIVE_SUBCOMMANDS = new Set([
|
|
5
4
|
"reset",
|
|
@@ -90,12 +89,6 @@ export function analyzeGitExecution(commandArgs, workspaceDir) {
|
|
|
90
89
|
workDir,
|
|
91
90
|
};
|
|
92
91
|
}
|
|
93
|
-
export function requiresCommitHelper(subcommand) {
|
|
94
|
-
if (!subcommand) {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
return COMMIT_HELPER_SUBCOMMANDS.has(subcommand);
|
|
98
|
-
}
|
|
99
92
|
export function requiresExplicitGitConsent(subcommand) {
|
|
100
93
|
if (!subcommand) {
|
|
101
94
|
return false;
|
|
@@ -120,7 +113,6 @@ export function evaluateGitPolicies(context) {
|
|
|
120
113
|
const invocationArgv = context.invocation?.argv;
|
|
121
114
|
const normalizedArgv = Array.isArray(invocationArgv) ? invocationArgv : [];
|
|
122
115
|
return {
|
|
123
|
-
requiresCommitHelper: requiresCommitHelper(context.subcommand),
|
|
124
116
|
requiresExplicitConsent: requiresExplicitGitConsent(context.subcommand),
|
|
125
117
|
isDestructive: isDestructiveGitSubcommand(context.command, normalizedArgv),
|
|
126
118
|
};
|
package/dist/scripts/runner.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
3
|
* Sweetistics runner wrapper: enforces timeouts, git policy, and trash-safe deletes before dispatching any repo command.
|
|
4
|
-
* When you tweak its behavior, add a short note to AGENTS.md
|
|
4
|
+
* When you tweak its behavior, add a short note to AGENTS.md so other agents know the new expectations.
|
|
5
5
|
*/
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
7
7
|
import { cpSync, existsSync, renameSync, rmSync } from "node:fs";
|
|
@@ -670,10 +670,6 @@ function enforceGitPolicies(gitContext) {
|
|
|
670
670
|
console.error('git rebase requires the user to explicitly type "rebase" in chat. Once they do, rerun with RUNNER_THE_USER_GAVE_ME_CONSENT=1 in the same command (e.g. RUNNER_THE_USER_GAVE_ME_CONSENT=1 ./runner git rebase --continue).');
|
|
671
671
|
process.exit(1);
|
|
672
672
|
}
|
|
673
|
-
if (evaluation.requiresCommitHelper) {
|
|
674
|
-
console.error('Direct git add/commit is disabled. Use ./scripts/committer "chore(runner): describe change" "scripts/runner.ts" instead—see AGENTS.md and ./scripts/committer for details. The helper auto-stashes unrelated files before committing.');
|
|
675
|
-
process.exit(1);
|
|
676
|
-
}
|
|
677
673
|
if (evaluation.requiresExplicitConsent || evaluation.isDestructive) {
|
|
678
674
|
if (hasConsentOverride) {
|
|
679
675
|
if (ENABLE_DEBUG_LOGS) {
|
|
@@ -224,10 +224,24 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
224
224
|
);
|
|
225
225
|
|
|
226
226
|
const isVisibleElement = (node) => {
|
|
227
|
+
if (typeof HTMLElement === 'undefined') return false;
|
|
227
228
|
if (!(node instanceof HTMLElement)) return false;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
try {
|
|
230
|
+
const rect = node.getBoundingClientRect?.();
|
|
231
|
+
const style = window.getComputedStyle?.(node);
|
|
232
|
+
if (!rect) return true;
|
|
233
|
+
return (
|
|
234
|
+
rect.width > 0 &&
|
|
235
|
+
rect.height > 0 &&
|
|
236
|
+
style?.display !== 'none' &&
|
|
237
|
+
style?.visibility !== 'hidden'
|
|
238
|
+
);
|
|
239
|
+
} catch {
|
|
240
|
+
// DOM test doubles and older Chromium nodes can omit one of these APIs.
|
|
241
|
+
// Treat them as visible; real hidden picker rows still report a zero rect
|
|
242
|
+
// or display:none and are filtered above.
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
231
245
|
};
|
|
232
246
|
const looksLikeModelPill = (node) => {
|
|
233
247
|
if (!(node instanceof HTMLElement) || !node.matches('button.__composer-pill')) return false;
|
|
@@ -383,6 +397,103 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
383
397
|
}
|
|
384
398
|
return true;
|
|
385
399
|
};
|
|
400
|
+
|
|
401
|
+
// ---------- Unified Intelligence picker: Advanced -> Model submenu ----------
|
|
402
|
+
// The slider picker exposes only the current effort in the composer pill. Its
|
|
403
|
+
// model versions live behind Advanced -> Model, next to an identically-shaped
|
|
404
|
+
// Effort submenu. Identify the Model opener positively so a Pro effort label can
|
|
405
|
+
// never be mistaken for a model target.
|
|
406
|
+
const ADVANCED_VIEW_SELECTOR = '[data-testid="composer-model-picker-slider-advanced-view"]';
|
|
407
|
+
const INTELLIGENCE_PICKER_SELECTOR = '[data-testid="composer-intelligence-picker-content"]';
|
|
408
|
+
const SUBMENU_OPENER_SELECTOR = '[role="menuitem"][aria-haspopup="menu"]';
|
|
409
|
+
const ADVANCED_WORDS = ['advanced', 'erweitert', '高级', 'avanzado', 'avancado', 'avance'];
|
|
410
|
+
const MODEL_WORDS = ['model', 'modell', '模型', 'modelo', 'modello', 'modele'];
|
|
411
|
+
const EFFORT_WORDS = [
|
|
412
|
+
'effort', 'aufwand', '强度', '努力',
|
|
413
|
+
'esfuerzo', 'esforco', 'sforzo', 'inspanning', 'wysilek',
|
|
414
|
+
];
|
|
415
|
+
const pickerNodeLabel = (node) => {
|
|
416
|
+
const value =
|
|
417
|
+
(node?.getAttribute?.('aria-label') ?? '') + ' ' + (node?.textContent ?? '');
|
|
418
|
+
try {
|
|
419
|
+
return value
|
|
420
|
+
.toLowerCase()
|
|
421
|
+
.normalize('NFD')
|
|
422
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
423
|
+
.replace(/\\s+/g, ' ')
|
|
424
|
+
.trim();
|
|
425
|
+
} catch {
|
|
426
|
+
return value.toLowerCase().replace(/\\s+/g, ' ').trim();
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const containsPickerWord = (label, words) =>
|
|
430
|
+
words.some((word) => label.includes(word));
|
|
431
|
+
const isSubmenuOpener = (node) =>
|
|
432
|
+
node?.getAttribute?.('role') === 'menuitem' &&
|
|
433
|
+
node?.getAttribute?.('aria-haspopup') === 'menu';
|
|
434
|
+
const isUnifiedPickerMenu = (menu) =>
|
|
435
|
+
Boolean(
|
|
436
|
+
menu?.getAttribute?.('data-testid') === 'composer-intelligence-picker-content' ||
|
|
437
|
+
menu?.querySelector?.(INTELLIGENCE_PICKER_SELECTOR) ||
|
|
438
|
+
menu?.querySelector?.(ADVANCED_VIEW_SELECTOR),
|
|
439
|
+
);
|
|
440
|
+
const findUnifiedPickerMenu = () =>
|
|
441
|
+
Array.from(document.querySelectorAll(${menuContainerLiteral})).find(isUnifiedPickerMenu) ??
|
|
442
|
+
null;
|
|
443
|
+
const findAdvancedToggle = (menu) => {
|
|
444
|
+
for (const item of (menu || document).querySelectorAll('[role="menuitem"]')) {
|
|
445
|
+
if (!isVisibleElement(item)) continue;
|
|
446
|
+
if (containsPickerWord(pickerNodeLabel(item), ADVANCED_WORDS)) return item;
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
};
|
|
450
|
+
const findModelSubmenuOpener = (menu) => {
|
|
451
|
+
const scope = menu?.querySelector?.(ADVANCED_VIEW_SELECTOR) || menu || document;
|
|
452
|
+
for (const item of scope.querySelectorAll(SUBMENU_OPENER_SELECTOR)) {
|
|
453
|
+
if (!isVisibleElement(item) || !isSubmenuOpener(item)) continue;
|
|
454
|
+
const label = pickerNodeLabel(item);
|
|
455
|
+
if (
|
|
456
|
+
containsPickerWord(label, MODEL_WORDS) &&
|
|
457
|
+
!containsPickerWord(label, EFFORT_WORDS)
|
|
458
|
+
) {
|
|
459
|
+
return item;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return null;
|
|
463
|
+
};
|
|
464
|
+
const advancedModelSignalMatchesTarget = (menu = null) => {
|
|
465
|
+
const parentMenu = menu || findUnifiedPickerMenu();
|
|
466
|
+
const opener = findModelSubmenuOpener(parentMenu);
|
|
467
|
+
if (!opener) return false;
|
|
468
|
+
const label = normalizeText(pickerNodeLabel(opener));
|
|
469
|
+
const version = versionFromLabel(label);
|
|
470
|
+
if (desiredVersion && version !== desiredVersion) return false;
|
|
471
|
+
if (desiredModelVariant && !label.split(' ').includes(desiredModelVariant)) return false;
|
|
472
|
+
if (wantsPro) return labelHasProWord(label) && !labelHasLegacyProVersion(label);
|
|
473
|
+
if (wantsInstant) return label.includes('instant');
|
|
474
|
+
if (wantsThinking) return Boolean(desiredVersion) && !labelHasProWord(label);
|
|
475
|
+
if (desiredVersion) return true;
|
|
476
|
+
return normalizedTokens.some((token) => token && label.includes(token));
|
|
477
|
+
};
|
|
478
|
+
const getAdvancedModelLabel = () => {
|
|
479
|
+
const opener = findModelSubmenuOpener(findUnifiedPickerMenu());
|
|
480
|
+
if (!opener) return '';
|
|
481
|
+
const raw = (opener.textContent ?? '').trim();
|
|
482
|
+
const normalized = normalizeText(pickerNodeLabel(opener));
|
|
483
|
+
const version = versionFromLabel(normalized);
|
|
484
|
+
if (!version) return raw;
|
|
485
|
+
const [major, minor] = version.split('-');
|
|
486
|
+
const suffix = normalized.split(' ').includes('sol') ? ' Sol' : '';
|
|
487
|
+
return 'GPT-' + major + '.' + minor + suffix;
|
|
488
|
+
};
|
|
489
|
+
const isLegacyFlatIntelligencePickerOpen = () => {
|
|
490
|
+
const menu = findUnifiedPickerMenu();
|
|
491
|
+
return Boolean(
|
|
492
|
+
menu &&
|
|
493
|
+
!menu.querySelector?.(ADVANCED_VIEW_SELECTOR) &&
|
|
494
|
+
!findAdvancedToggle(menu),
|
|
495
|
+
);
|
|
496
|
+
};
|
|
386
497
|
const getResolvedLabel = (observedOptionLabel = '') => {
|
|
387
498
|
if (configuredSelectionMatchesTarget()) {
|
|
388
499
|
const variant = getConfiguredVariantLabel();
|
|
@@ -390,6 +501,9 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
390
501
|
if (desiredModelVariant === 'sol' && labelHasProWord(normalizeText(variant))) return version;
|
|
391
502
|
return [variant, version].filter(Boolean).join(' ');
|
|
392
503
|
}
|
|
504
|
+
if (advancedModelSignalMatchesTarget()) {
|
|
505
|
+
return getAdvancedModelLabel();
|
|
506
|
+
}
|
|
393
507
|
const composerLabel = getComposerModelLabel();
|
|
394
508
|
const normalizedComposerLabel = normalizeText(composerLabel);
|
|
395
509
|
if (
|
|
@@ -448,8 +562,9 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
448
562
|
desiredVersion === '5-5' &&
|
|
449
563
|
!hasProComposerPill() &&
|
|
450
564
|
isThinkingEffortLabel(normalizedLabel) &&
|
|
451
|
-
(
|
|
452
|
-
|
|
565
|
+
(isTargetGpt55VisibleAlias(readComposerModelSignal()) ||
|
|
566
|
+
(isNonProIntelligenceThinkingLabel(normalizedLabel) &&
|
|
567
|
+
isLegacyFlatIntelligencePickerOpen()))
|
|
453
568
|
) {
|
|
454
569
|
return true;
|
|
455
570
|
}
|
|
@@ -521,6 +636,9 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
521
636
|
return COMPOSER_SIGNAL_INCLUDES.some((token) => token && signal.includes(token));
|
|
522
637
|
};
|
|
523
638
|
const activeSelectionMatchesTarget = () => {
|
|
639
|
+
if (advancedModelSignalMatchesTarget()) {
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
524
642
|
if (buttonMatchesTarget()) {
|
|
525
643
|
return true;
|
|
526
644
|
}
|
|
@@ -952,6 +1070,9 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
952
1070
|
for (const menu of menus) {
|
|
953
1071
|
const buttons = Array.from(menu.querySelectorAll(${menuItemLiteral}));
|
|
954
1072
|
for (const option of buttons) {
|
|
1073
|
+
if (!isVisibleElement(option)) {
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
955
1076
|
if (isNestedEffortControl(option, menu)) {
|
|
956
1077
|
continue;
|
|
957
1078
|
}
|
|
@@ -1038,6 +1159,33 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
1038
1159
|
dispatchHoverSequence(node);
|
|
1039
1160
|
dispatchClickSequence(node);
|
|
1040
1161
|
};
|
|
1162
|
+
const descendIntoAdvancedModelPicker = () => {
|
|
1163
|
+
const parentMenu = findUnifiedPickerMenu();
|
|
1164
|
+
if (!parentMenu) return 'unavailable';
|
|
1165
|
+
|
|
1166
|
+
const opener = findModelSubmenuOpener(parentMenu);
|
|
1167
|
+
if (opener) {
|
|
1168
|
+
if (advancedModelSignalMatchesTarget(parentMenu)) {
|
|
1169
|
+
return 'already-selected';
|
|
1170
|
+
}
|
|
1171
|
+
const key = submenuKey(
|
|
1172
|
+
normalizeText(opener.textContent ?? ''),
|
|
1173
|
+
opener.getAttribute?.('data-testid') ?? '',
|
|
1174
|
+
);
|
|
1175
|
+
openedSubmenuKeys.add(key);
|
|
1176
|
+
if (opener.getAttribute?.('aria-expanded') !== 'true') {
|
|
1177
|
+
openSubmenuOption(opener);
|
|
1178
|
+
}
|
|
1179
|
+
return 'opened';
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
const advancedToggle = findAdvancedToggle(parentMenu);
|
|
1183
|
+
if (!advancedToggle) return 'unavailable';
|
|
1184
|
+
if (advancedToggle.getAttribute?.('aria-expanded') !== 'true') {
|
|
1185
|
+
dispatchClickSequence(advancedToggle);
|
|
1186
|
+
}
|
|
1187
|
+
return 'expanded';
|
|
1188
|
+
};
|
|
1041
1189
|
|
|
1042
1190
|
return new Promise((resolve) => {
|
|
1043
1191
|
const start = performance.now();
|
|
@@ -1124,6 +1272,17 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
1124
1272
|
});
|
|
1125
1273
|
return;
|
|
1126
1274
|
}
|
|
1275
|
+
const advancedState = descendIntoAdvancedModelPicker();
|
|
1276
|
+
if (advancedState === 'already-selected') {
|
|
1277
|
+
const resolvedLabel = getResolvedLabel();
|
|
1278
|
+
closeMenu();
|
|
1279
|
+
resolve({ status: 'already-selected', label: resolvedLabel });
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
if (advancedState === 'expanded' || advancedState === 'opened') {
|
|
1283
|
+
setTimeout(attempt, REOPEN_INTERVAL_MS / 2);
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1127
1286
|
if (performance.now() - start > MAX_WAIT_MS) {
|
|
1128
1287
|
resolve({
|
|
1129
1288
|
status: 'option-not-found',
|