@steipete/oracle 0.17.0 → 0.17.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/bin/oracle-cli.js +1 -1
- package/dist/docs-site/browser-mode.html +3 -3
- package/dist/docs-site/cli-reference.html +1 -1
- package/dist/docs-site/configuration.html +1 -1
- package/dist/docs-site/mcp.html +2 -2
- package/dist/docs-site/mythical-pro-agents.html +1 -1
- package/dist/src/browser/actions/thinkingTime.js +90 -75
- package/dist/src/browser/chromeLifecycle.js +6 -0
- package/dist/src/cli/options.js +1 -1
- package/dist/src/oracle/thinkingTime.js +9 -3
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/package.json +10 -10
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
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, heavy, or ChatGPT UI aliases.")
|
|
342
|
+
.addOption(new Option("--browser-thinking-time <level>", "Thinking time intensity for Thinking/Pro models: light, standard, extended, extra-high (Extra High), heavy (Pro), 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"]))
|
|
@@ -327,7 +327,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
327
327
|
<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
328
|
<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
329
|
<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|heavy></code>: set the ChatGPT thinking-time intensity (Thinking/Pro models only). You can also set a default in <code>~/.oracle/config.json</code> via <code>browser.thinkingTime</code>.</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>
|
|
331
331
|
<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
332
|
<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
333
|
<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>
|
|
@@ -364,7 +364,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
364
364
|
<span class="line"><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Research the current browser support for WebGPU in enterprise-managed Chrome and cite sources."</span></span></code></pre>
|
|
365
365
|
<p>Oracle activates ChatGPT Deep Research through the composer tools menu, recognizing both the <code>Deep research</code> label and current <code>Get a detailed report</code> menu variants. It waits for the research plan to auto-confirm, logs high-level progress, then captures the final report from the Deep Research report surface instead of trusting the assistant tool-call wrapper.</p>
|
|
366
366
|
<p>If ChatGPT initially exposes only <code>Called tool</code> / <code>Used tool</code>, Oracle treats that as an incomplete capture for Deep Research rather than a final answer. Reattach the existing session with <code>oracle session <id> --render</code> so Oracle can recover the lazy-loaded report from the existing Chrome tab; do not rerun the research unless the browser session is unrecoverable.</p>
|
|
367
|
-
<p>Deep Research is browser-only. It does not use connected apps in v1; give it public-web scope, uploaded files, and any domain/source guidance in the prompt. For deep thinking over code or architecture without web search, prefer a normal browser run with a Pro
|
|
367
|
+
<p>Deep Research is browser-only. It does not use connected apps in v1; give it public-web scope, uploaded files, and any domain/source guidance in the prompt. For deep thinking over code or architecture without web search, prefer a normal browser run with GPT-5.6 Sol and <code>--browser-thinking-time extra-high</code>, or a Pro model with <code>--browser-thinking-time extended</code>.</p>
|
|
368
368
|
<p>Completed browser sessions also save durable artifacts under <code>~/.oracle/sessions/<id>/artifacts/</code>. Deep Research writes the extracted report to <code>deep-research-report.md</code>, and every browser run writes <code>transcript.md</code> with the prompt, final answer, conversation URL, and saved artifact references. Use <code>--write-output <path></code> when you also need a copy of just the final answer at a specific path.</p>
|
|
369
369
|
<p>When ChatGPT generates downloadable files in the assistant response (for example a ZIP, wheel, source distribution, CSV, or PDF), Oracle saves those files beside the transcript before any archive attempt. The downloader is intentionally narrow: it only follows ChatGPT-owned file/download URLs from the assistant response and uses <code>sandbox:/mnt/data/...</code> links as source metadata and filename hints, not as arbitrary fetch targets. External links in the response are left in the transcript but are not downloaded. In bridge mode, a patched Windows host advertises artifact-transfer capability through <code>/health</code>; the Linux client then pulls each saved file over the authenticated bridge endpoint, stores it under the Linux session <code>artifacts/</code> directory, and verifies safe filename, byte size, SHA-256, and ZIP structure where applicable. If either side is older or transfer validation fails, the text response still completes and Oracle prints a manual-copy fallback instead of leaking host paths or signed download URLs.</p>
|
|
370
370
|
<h3 id="conversation-archiving"><a class="anchor" href="#conversation-archiving" aria-label="Anchor link">#</a>Conversation archiving</h3>
|
|
@@ -395,7 +395,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
395
395
|
<p>Use browser follow-ups when a one-shot review would be too easy for the model to answer shallowly. Oracle keeps the same ChatGPT conversation open, waits for each answer, then submits the next follow-up:</p>
|
|
396
396
|
<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>
|
|
397
397
|
<span class="line"><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.5-pro</span><span style="color:#F47067"> \</span></span>
|
|
398
|
-
<span class="line"><span style="color:#6CB6FF"> --browser-thinking-time</span><span style="color:#96D0FF">
|
|
398
|
+
<span class="line"><span style="color:#6CB6FF"> --browser-thinking-time</span><span style="color:#96D0FF"> extended</span><span style="color:#F47067"> \</span></span>
|
|
399
399
|
<span class="line"><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Review this migration plan and identify the top risks."</span><span style="color:#F47067"> \</span></span>
|
|
400
400
|
<span class="line"><span style="color:#6CB6FF"> --file</span><span style="color:#96D0FF"> docs/migration-plan.md</span><span style="color:#F47067"> \</span></span>
|
|
401
401
|
<span class="line"><span style="color:#6CB6FF"> --browser-follow-up</span><span style="color:#96D0FF"> "Challenge your previous recommendation. What would fail in production?"</span><span style="color:#F47067"> \</span></span>
|
|
@@ -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|heavy></code></td><td>
|
|
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>
|
|
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 | 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 | 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>
|
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"|"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"|"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,
|
|
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:"heavy"</code> when you explicitly want Pro.</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>
|
|
@@ -278,7 +278,7 @@ body:not(.home) .doc>h1:first-child{display:none}
|
|
|
278
278
|
<p>The captured report lands at <code>~/.oracle/sessions/<id>/artifacts/deep-research-report.md</code>. Deep Research can run for an hour or more — Oracle stores the session and reattaches.</p>
|
|
279
279
|
<h2 id="thinking-time"><a class="anchor" href="#thinking-time" aria-label="Anchor link">#</a>Thinking time</h2>
|
|
280
280
|
<p>Pro / Thinking models in browser mode accept a <code>--browser-thinking-time</code> knob:</p>
|
|
281
|
-
<table><thead><tr><th>Level</th><th>What it maps to in ChatGPT</th></tr></thead><tbody><tr><td><code>light</code></td><td>Quick</td></tr><tr><td><code>standard</code></td><td>
|
|
281
|
+
<table><thead><tr><th>Level</th><th>What it maps to in ChatGPT</th></tr></thead><tbody><tr><td><code>light</code></td><td>Instant / Quick</td></tr><tr><td><code>standard</code></td><td>Medium / Standard</td></tr><tr><td><code>extended</code></td><td>High / Pro Extended / Thinking Extended</td></tr><tr><td><code>extra-high</code></td><td>Extra High (GPT-5.6 Sol non-Pro max)</td></tr><tr><td><code>heavy</code></td><td>Matching Heavy row; otherwise keep the current tier</td></tr></tbody></table>
|
|
282
282
|
<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:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.5-pro</span><span style="color:#F47067"> \</span></span>
|
|
283
283
|
<span class="line"><span style="color:#6CB6FF"> --browser-thinking-time</span><span style="color:#96D0FF"> extended</span><span style="color:#F47067"> \</span></span>
|
|
284
284
|
<span class="line"><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Refactor this hot path"</span><span style="color:#6CB6FF"> --file</span><span style="color:#96D0FF"> "src/render/**"</span></span></code></pre>
|
|
@@ -55,7 +55,9 @@ export async function ensureThinkingTime(Runtime, level, logger, desiredModel) {
|
|
|
55
55
|
if (strictProEffort) {
|
|
56
56
|
throw new Error(`${message}; refusing to submit without confirmed Pro Extended.`);
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
// Nothing was clicked, so the tab keeps whatever effort it already had —
|
|
59
|
+
// which is not necessarily ChatGPT's default.
|
|
60
|
+
logger(formatBrowserThinkingLog(`${message}; keeping the effort already selected in ChatGPT.`));
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
61
63
|
default: {
|
|
@@ -72,7 +74,7 @@ export async function ensureThinkingTime(Runtime, level, logger, desiredModel) {
|
|
|
72
74
|
/**
|
|
73
75
|
* Best-effort selection of a thinking time level in ChatGPT's composer pill menu.
|
|
74
76
|
* Safe by default: if the pill/menu/option isn't present, we continue without throwing.
|
|
75
|
-
* @param level - The thinking time intensity: 'light', 'standard', 'extended', or 'heavy'
|
|
77
|
+
* @param level - The thinking time intensity: 'light', 'standard', 'extended', 'extra-high', or 'heavy'
|
|
76
78
|
*/
|
|
77
79
|
export async function ensureThinkingTimeIfAvailable(Runtime, level, logger, desiredModel) {
|
|
78
80
|
try {
|
|
@@ -135,12 +137,13 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
135
137
|
const TARGET_MODEL_KIND = ${targetModelKindLiteral};
|
|
136
138
|
const TARGET_IS_GPT56_MODEL = ${targetIsGpt56ModelLiteral};
|
|
137
139
|
|
|
138
|
-
//
|
|
140
|
+
// Multilingual matchers: English level token + observed German/Chinese variants.
|
|
139
141
|
const LEVEL_TOKENS = {
|
|
140
|
-
light: ['light', 'instant', '轻', '极速'],
|
|
141
|
-
standard: ['standard', 'medium', '标准', '中'],
|
|
142
|
-
extended: ['extended', 'high', '扩展', '深度', '加强', '高'],
|
|
143
|
-
|
|
142
|
+
light: ['light', 'instant', 'sofort', 'leicht', '轻', '极速'],
|
|
143
|
+
standard: ['standard', 'medium', 'mittel', '标准', '中'],
|
|
144
|
+
extended: ['extended', 'high', 'hoch', 'erweitert', '扩展', '深度', '加强', '高'],
|
|
145
|
+
'extra-high': ['extra high', 'sehr hoch', '极高'],
|
|
146
|
+
heavy: ['heavy', 'schwer', '重度', '加重'],
|
|
144
147
|
};
|
|
145
148
|
const targetTokens = LEVEL_TOKENS[TARGET_LEVEL] || [TARGET_LEVEL];
|
|
146
149
|
|
|
@@ -155,19 +158,43 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
155
158
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
156
159
|
// Keep CJK characters so we can match Chinese labels against LEVEL_TOKENS.
|
|
157
160
|
const normalize = (value) => (value || '')
|
|
161
|
+
// Compose first so NFD umlauts fold too, then map them onto ASCII before
|
|
162
|
+
// the strip below would drop them (and split the token in half).
|
|
163
|
+
.normalize('NFC')
|
|
158
164
|
.toLowerCase()
|
|
165
|
+
.replace(/ä/g, 'a')
|
|
166
|
+
.replace(/ö/g, 'o')
|
|
167
|
+
.replace(/ü/g, 'u')
|
|
168
|
+
.replace(/ß/g, 'ss')
|
|
159
169
|
.replace(/[^a-z0-9\\u4e00-\\u9fa5]+/g, ' ')
|
|
160
170
|
.replace(/\\s+/g, ' ')
|
|
161
171
|
.trim();
|
|
162
172
|
const hasToken = (text, token) => normalize(text).split(' ').includes(token);
|
|
163
|
-
|
|
173
|
+
// Whole-word/phrase containment. Latin effort labels are short words that also
|
|
174
|
+
// occur inside unrelated UI text ("Hochladen", "Ermitteln") and inside their own
|
|
175
|
+
// row descriptions ("Hoch – für sehr komplexe Aufgaben"), so plain substring
|
|
176
|
+
// matching misclassifies rows. CJK labels have no word separators, so they keep
|
|
177
|
+
// substring semantics.
|
|
178
|
+
const hasPhrase = (text, phrase) => {
|
|
179
|
+
const haystack = ' ' + normalize(text) + ' ';
|
|
180
|
+
const needle = normalize(phrase);
|
|
181
|
+
if (!needle) return false;
|
|
182
|
+
return /^[a-z0-9 ]+$/.test(needle)
|
|
183
|
+
? haystack.includes(' ' + needle + ' ')
|
|
184
|
+
: haystack.includes(needle);
|
|
185
|
+
};
|
|
186
|
+
// ChatGPT's Pro effort tiers are "Pro Extended"/"Pro Erweitert" per UI language.
|
|
187
|
+
const hasExtendedWord = (text) => hasPhrase(text, 'extended') || hasPhrase(text, 'erweitert');
|
|
188
|
+
const matchesTokens = (text, tokens) => {
|
|
164
189
|
const t = normalize(text);
|
|
165
190
|
if (!t) return false;
|
|
166
|
-
return
|
|
191
|
+
return tokens.some((tok) => {
|
|
167
192
|
const token = normalize(tok);
|
|
168
193
|
if (!token) return false;
|
|
169
|
-
if (token === 'high') return
|
|
170
|
-
if (token === 'extra high') return
|
|
194
|
+
if (token === 'high') return hasPhrase(t, 'high') && !hasPhrase(t, 'extra high');
|
|
195
|
+
if (token === 'extra high') return hasPhrase(t, 'extra high');
|
|
196
|
+
if (token === 'hoch') return hasPhrase(t, 'hoch') && !hasPhrase(t, 'sehr hoch');
|
|
197
|
+
if (token === 'sehr hoch') return hasPhrase(t, 'sehr hoch');
|
|
171
198
|
if (token === '极速') {
|
|
172
199
|
const suffix = t.slice(token.length);
|
|
173
200
|
return t === token || hasToken(t, token) || /^[0-9]/.test(suffix);
|
|
@@ -175,27 +202,15 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
175
202
|
if (['中', '高', '极高'].includes(token)) {
|
|
176
203
|
return t === token || hasToken(t, token);
|
|
177
204
|
}
|
|
205
|
+
if (/^[a-z0-9 ]+$/.test(token)) {
|
|
206
|
+
return hasPhrase(t, token);
|
|
207
|
+
}
|
|
178
208
|
return t === token || hasToken(t, token) || t.includes(token);
|
|
179
209
|
});
|
|
180
210
|
};
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
for (const tokens of Object.values(LEVEL_TOKENS)) {
|
|
185
|
-
for (const rawToken of tokens) {
|
|
186
|
-
const token = normalize(rawToken);
|
|
187
|
-
if (!token) continue;
|
|
188
|
-
if (token.includes(' ')) {
|
|
189
|
-
if (token.split(' ').every((part) => hasToken(normalizedText, part))) return true;
|
|
190
|
-
} else if (/^[a-z0-9]+$/.test(token)) {
|
|
191
|
-
if (hasToken(normalizedText, token)) return true;
|
|
192
|
-
} else if (normalizedText.includes(token)) {
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return false;
|
|
198
|
-
};
|
|
211
|
+
const matchesLevel = (text) => matchesTokens(text, targetTokens);
|
|
212
|
+
const matchesAnyEffortLevel = (text) =>
|
|
213
|
+
Object.values(LEVEL_TOKENS).some((tokens) => matchesTokens(text, tokens));
|
|
199
214
|
const optionIsSelected = (node) => {
|
|
200
215
|
if (!(node instanceof HTMLElement)) return false;
|
|
201
216
|
const ariaChecked = node.getAttribute('aria-checked');
|
|
@@ -347,7 +362,8 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
347
362
|
return true;
|
|
348
363
|
}
|
|
349
364
|
const label = menu?.querySelector?.('.__menu-label, [class*="menu-label"]');
|
|
350
|
-
|
|
365
|
+
// 'intelligen' matches both "Intelligence" and German "Intelligenz".
|
|
366
|
+
return normalize(label?.textContent ?? '').includes('intelligen');
|
|
351
367
|
};
|
|
352
368
|
const failure = (status, extra = {}) => ({
|
|
353
369
|
status,
|
|
@@ -390,24 +406,10 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
390
406
|
return null;
|
|
391
407
|
}
|
|
392
408
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
) {
|
|
398
|
-
for (const item of items) {
|
|
399
|
-
const itemText = normalize(
|
|
400
|
-
(item.textContent ?? '') + ' ' + (item.getAttribute?.('aria-label') ?? ''),
|
|
401
|
-
);
|
|
402
|
-
if (
|
|
403
|
-
hasToken(itemText, 'pro') &&
|
|
404
|
-
!itemText.includes('gpt') &&
|
|
405
|
-
!/(?:^|\\s)5[ .-]?6(?:\\s|$)/.test(itemText)
|
|
406
|
-
) {
|
|
407
|
-
return item;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
409
|
+
// Generic effort-label match for every model/level. GPT-5.6 heavy used to
|
|
410
|
+
// short-circuit to the Pro row before reaching here; it no longer does, so
|
|
411
|
+
// a UI without a matching tier (e.g. German, which has no "heavy") falls
|
|
412
|
+
// through to null and the caller keeps the current selection.
|
|
411
413
|
for (const item of items) {
|
|
412
414
|
const itemText = normalize(
|
|
413
415
|
(item.textContent ?? '') + ' ' + (item.getAttribute?.('aria-label') ?? ''),
|
|
@@ -422,10 +424,10 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
422
424
|
return item;
|
|
423
425
|
}
|
|
424
426
|
}
|
|
425
|
-
if (TARGET_LEVEL === '
|
|
426
|
-
// Older Chinese layouts used bare 高 for the highest effort.
|
|
427
|
-
// only as a second-pass exact fallback so a current 高 row can
|
|
428
|
-
// win before the primary 极高 row.
|
|
427
|
+
if (TARGET_LEVEL === 'extra-high') {
|
|
428
|
+
// Older Chinese layouts used bare 高 for the highest non-Pro effort.
|
|
429
|
+
// Keep it only as a second-pass exact fallback so a current 高 row can
|
|
430
|
+
// never win before the primary 极高 row.
|
|
429
431
|
for (const item of items) {
|
|
430
432
|
const itemText = normalize(item.textContent ?? '');
|
|
431
433
|
const ariaLabel = normalize(item.getAttribute?.('aria-label') ?? '');
|
|
@@ -434,11 +436,15 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
434
436
|
}
|
|
435
437
|
return null;
|
|
436
438
|
};
|
|
439
|
+
// Menu-shape heuristic only. This reads the whole menu's textContent, where
|
|
440
|
+
// adjacent row labels concatenate without a separator ("Pro StandardPro
|
|
441
|
+
// Extended"), so word-boundary matching does not apply here — substring is
|
|
442
|
+
// deliberate. Row-level classification uses matchesLevel/matchesTokens.
|
|
437
443
|
const countEffortLevels = (menu) => {
|
|
438
444
|
const text = normalize(menu?.textContent ?? '');
|
|
439
445
|
let hits = 0;
|
|
440
446
|
for (const tokens of Object.values(LEVEL_TOKENS)) {
|
|
441
|
-
if (tokens.some((token) => text.includes(
|
|
447
|
+
if (tokens.some((token) => text.includes(normalize(token)))) hits += 1;
|
|
442
448
|
}
|
|
443
449
|
return hits;
|
|
444
450
|
};
|
|
@@ -449,16 +455,22 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
449
455
|
const label = menu.querySelector?.('.__menu-label, [class*="menu-label"]');
|
|
450
456
|
const labelText = normalize(label?.textContent ?? '');
|
|
451
457
|
return (
|
|
452
|
-
labelText.includes('
|
|
458
|
+
labelText.includes('intelligen') ||
|
|
453
459
|
labelText.includes('thinking time') ||
|
|
454
460
|
labelText.includes('thinking effort') ||
|
|
461
|
+
labelText.includes('denkdauer') ||
|
|
462
|
+
labelText.includes('denkzeit') ||
|
|
455
463
|
countEffortLevels(menu) >= 2
|
|
456
464
|
);
|
|
457
465
|
};
|
|
458
466
|
const isProEffortMenu = (menu) => {
|
|
459
467
|
if (!isVisible(menu)) return false;
|
|
460
468
|
const text = normalize(menu?.textContent ?? '');
|
|
461
|
-
|
|
469
|
+
// Aggregate menu text, so plain substring only (see countEffortLevels).
|
|
470
|
+
return (
|
|
471
|
+
text.includes('pro standard') &&
|
|
472
|
+
(text.includes('pro extended') || text.includes('pro erweitert'))
|
|
473
|
+
);
|
|
462
474
|
};
|
|
463
475
|
const controlledMenu = (trigger) => {
|
|
464
476
|
const id = trigger?.getAttribute?.('aria-controls');
|
|
@@ -493,10 +505,10 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
493
505
|
(node?.textContent ?? '') + ' ' + (node?.getAttribute?.('aria-label') ?? ''),
|
|
494
506
|
);
|
|
495
507
|
if (TARGET_LEVEL === 'standard') {
|
|
496
|
-
return text
|
|
508
|
+
return hasPhrase(text, 'pro') && hasPhrase(text, 'standard');
|
|
497
509
|
}
|
|
498
510
|
if (TARGET_LEVEL === 'extended') {
|
|
499
|
-
return text
|
|
511
|
+
return hasPhrase(text, 'pro') && hasExtendedWord(text);
|
|
500
512
|
}
|
|
501
513
|
return false;
|
|
502
514
|
};
|
|
@@ -521,10 +533,10 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
521
533
|
}
|
|
522
534
|
const label = normalize(button?.textContent ?? '');
|
|
523
535
|
if (TARGET_LEVEL === 'standard') {
|
|
524
|
-
return hasToken(label, 'pro') && !
|
|
536
|
+
return hasToken(label, 'pro') && !hasExtendedWord(label);
|
|
525
537
|
}
|
|
526
538
|
if (TARGET_LEVEL === 'extended') {
|
|
527
|
-
return hasToken(label, 'pro') &&
|
|
539
|
+
return hasToken(label, 'pro') && hasExtendedWord(label);
|
|
528
540
|
}
|
|
529
541
|
return false;
|
|
530
542
|
};
|
|
@@ -534,13 +546,9 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
534
546
|
const normalizedLabel = normalize(
|
|
535
547
|
(button?.textContent ?? '') + ' ' + (button?.getAttribute?.('aria-label') ?? ''),
|
|
536
548
|
);
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
hasToken(normalizedLabel, 'pro')
|
|
541
|
-
) {
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
549
|
+
// No 5.6-heavy "a Pro pill counts as heavy" shortcut here: that would also
|
|
550
|
+
// make post-click verification pass on an unchanged Pro pill. selectAndVerify
|
|
551
|
+
// handles the already-on-Pro case explicitly before any click.
|
|
544
552
|
if ((modelKindOverride || TARGET_MODEL_KIND || modelKindFromNode(button)) === 'pro') {
|
|
545
553
|
return false;
|
|
546
554
|
}
|
|
@@ -553,14 +561,21 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
553
561
|
modelKindFromNode(trigger) ||
|
|
554
562
|
effectiveTargetModelKind();
|
|
555
563
|
const option = findOption();
|
|
556
|
-
if (
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
+
if (!option && TARGET_IS_GPT56_MODEL && TARGET_LEVEL === 'heavy') {
|
|
565
|
+
// GPT-5.6 has no "heavy" tier: Pro is the closest thing. Accept a pill that
|
|
566
|
+
// is already on Pro as satisfying the request, but never click Pro to get
|
|
567
|
+
// there, and never let this stand in for post-click verification.
|
|
568
|
+
const pill = freshComposerTrigger(trigger) || findModelButton();
|
|
569
|
+
const pillLabel = normalize(
|
|
570
|
+
(pill?.textContent ?? '') + ' ' + (pill?.getAttribute?.('aria-label') ?? ''),
|
|
571
|
+
);
|
|
572
|
+
if (
|
|
573
|
+
hasToken(pillLabel, 'pro') ||
|
|
574
|
+
currentEffortPillMatchesTarget(trigger, triggerModelKind)
|
|
575
|
+
) {
|
|
576
|
+
closeOpenMenus();
|
|
577
|
+
return { status: 'already-selected', label: trigger.textContent?.trim?.() || null };
|
|
578
|
+
}
|
|
564
579
|
}
|
|
565
580
|
if (!option) return failure('option-not-found', { modelKind: triggerModelKind });
|
|
566
581
|
const label = option.textContent?.trim?.() || null;
|
|
@@ -857,7 +872,7 @@ function buildThinkingTimeExpression(level, desiredModel) {
|
|
|
857
872
|
const text = normalize(
|
|
858
873
|
(node?.textContent ?? '') + ' ' + (node?.getAttribute?.('aria-label') ?? ''),
|
|
859
874
|
);
|
|
860
|
-
return text
|
|
875
|
+
return hasPhrase(text, 'pro') && hasExtendedWord(text);
|
|
861
876
|
};
|
|
862
877
|
const findProExtendedOption = () => {
|
|
863
878
|
const menu = document.querySelector(INTELLIGENCE_MENU_SELECTOR);
|
|
@@ -542,6 +542,12 @@ function buildChromeFlags(headless, debugBindAddress, hideWindow = false) {
|
|
|
542
542
|
"--disable-features=TranslateUI,AutomationControlled",
|
|
543
543
|
"--mute-audio",
|
|
544
544
|
"--window-size=1280,720",
|
|
545
|
+
// Chrome that *we* launch is pinned to English, so ChatGPT renders the labels
|
|
546
|
+
// our selectors were written against. This does not make English the only case
|
|
547
|
+
// to handle: --browser-attach-running and --remote-chrome never build these
|
|
548
|
+
// flags (see controlPlan.ts), so those runs inherit the user's own Chrome
|
|
549
|
+
// locale, and a ChatGPT account language setting can localize the UI even here.
|
|
550
|
+
// That is why the model/effort matchers must stay language-tolerant.
|
|
545
551
|
"--lang=en-US",
|
|
546
552
|
"--accept-lang=en-US,en",
|
|
547
553
|
];
|
package/dist/src/cli/options.js
CHANGED
|
@@ -133,7 +133,7 @@ export function parseThinkingTimeOption(value) {
|
|
|
133
133
|
if (normalized) {
|
|
134
134
|
return normalized;
|
|
135
135
|
}
|
|
136
|
-
throw new InvalidArgumentError('Thinking time must be one of "light", "standard", "extended", "heavy", or a ChatGPT UI alias like "instant", "medium", "high", or "
|
|
136
|
+
throw new InvalidArgumentError('Thinking time must be one of "light", "standard", "extended", "extra-high", "heavy", or a ChatGPT UI alias like "instant", "medium", "high", or "xhigh".');
|
|
137
137
|
}
|
|
138
138
|
export function normalizeModelOption(value) {
|
|
139
139
|
return (value ?? "").trim();
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export const THINKING_TIME_LEVELS = [
|
|
1
|
+
export const THINKING_TIME_LEVELS = [
|
|
2
|
+
"light",
|
|
3
|
+
"standard",
|
|
4
|
+
"extended",
|
|
5
|
+
"extra-high",
|
|
6
|
+
"heavy",
|
|
7
|
+
];
|
|
2
8
|
export const THINKING_TIME_ALIASES = [
|
|
3
9
|
"instant",
|
|
4
10
|
"low",
|
|
5
11
|
"medium",
|
|
6
12
|
"high",
|
|
7
|
-
"extra-high",
|
|
8
13
|
"extra high",
|
|
9
14
|
"extrahigh",
|
|
10
15
|
"xhigh",
|
|
@@ -29,10 +34,11 @@ export function normalizeThinkingTimeLevel(value) {
|
|
|
29
34
|
case "extended":
|
|
30
35
|
case "high":
|
|
31
36
|
return "extended";
|
|
32
|
-
case "heavy":
|
|
33
37
|
case "extra-high":
|
|
34
38
|
case "extrahigh":
|
|
35
39
|
case "xhigh":
|
|
40
|
+
return "extra-high";
|
|
41
|
+
case "heavy":
|
|
36
42
|
return "heavy";
|
|
37
43
|
default:
|
|
38
44
|
return null;
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steipete/oracle",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "CLI wrapper around OpenAI Responses API with GPT-5.6 Sol, GPT-5.6, GPT-5.5 Pro, GPT-5.5, GPT-5.4, GPT-5.2, GPT-5.1, and GPT-5.1 Codex high reasoning modes.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://askoracle.sh",
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
"inquirer": "14.0.2",
|
|
74
74
|
"json5": "^2.2.3",
|
|
75
75
|
"kleur": "^4.1.5",
|
|
76
|
-
"markdansi": "0.3.
|
|
77
|
-
"openai": "^7.
|
|
76
|
+
"markdansi": "0.3.3",
|
|
77
|
+
"openai": "^7.4.0",
|
|
78
78
|
"osc-progress": "^0.3.2",
|
|
79
79
|
"qs": "^6.15.3",
|
|
80
|
-
"shiki": "^4.4.
|
|
80
|
+
"shiki": "^4.4.2",
|
|
81
81
|
"toasted-notifier": "^10.1.0",
|
|
82
82
|
"tokentally": "^0.1.3",
|
|
83
83
|
"zod": "^4.4.3"
|
|
@@ -88,13 +88,13 @@
|
|
|
88
88
|
"@types/inquirer": "^9.0.10",
|
|
89
89
|
"@types/node": "^26.1.2",
|
|
90
90
|
"@vitest/coverage-v8": "4.1.10",
|
|
91
|
-
"devtools-protocol": "0.0.
|
|
91
|
+
"devtools-protocol": "0.0.1673900",
|
|
92
92
|
"es-toolkit": "^1.50.0",
|
|
93
93
|
"esbuild": "^0.28.1",
|
|
94
|
-
"oxfmt": "0.
|
|
95
|
-
"oxlint": "^1.
|
|
96
|
-
"puppeteer-core": "^25.
|
|
97
|
-
"tsx": "^4.23.
|
|
94
|
+
"oxfmt": "0.62.0",
|
|
95
|
+
"oxlint": "^1.77.0",
|
|
96
|
+
"puppeteer-core": "^25.5.0",
|
|
97
|
+
"tsx": "^4.23.7",
|
|
98
98
|
"typescript": "^7.0.2",
|
|
99
99
|
"vitest": "^4.1.10"
|
|
100
100
|
},
|
|
@@ -109,5 +109,5 @@
|
|
|
109
109
|
"engines": {
|
|
110
110
|
"node": ">=24"
|
|
111
111
|
},
|
|
112
|
-
"packageManager": "pnpm@10.
|
|
112
|
+
"packageManager": "pnpm@10.34.5"
|
|
113
113
|
}
|
|
Binary file
|
|
Binary file
|