@steipete/oracle 0.11.0 → 0.11.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/README.md +1 -1
- package/dist/src/browser/actions/archiveConversation.js +12 -0
- package/dist/src/browser/actions/modelSelection.js +9 -4
- package/dist/src/browser/config.js +1 -7
- package/dist/src/browser/index.js +24 -41
- package/dist/src/cli/browserConfig.js +1 -8
- package/dist/src/mcp/types.js +4 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -243,7 +243,7 @@ Browser automation can open or control Chrome, so dry-runs and live runs print a
|
|
|
243
243
|
| `--followup <sessionId\|responseId>` | Continue an OpenAI/Azure Responses API run from a stored oracle session or `resp_...` response id. |
|
|
244
244
|
| `--followup-model <model>` | For multi-model OpenAI/Azure parent sessions, choose which model response to continue from. |
|
|
245
245
|
| `--base-url <url>` | Point API runs at LiteLLM/Azure/OpenRouter/etc. |
|
|
246
|
-
| `--chatgpt-url <url>` | Target a ChatGPT workspace/folder (browser).
|
|
246
|
+
| `--chatgpt-url <url>` | Target a ChatGPT workspace/folder or Temporary Chat URL (browser). |
|
|
247
247
|
| `--browser-model-strategy <select\|current\|ignore>` | Control ChatGPT model selection in browser mode (current keeps the active model; ignore skips the picker). |
|
|
248
248
|
| `--browser-manual-login` | Skip cookie copy; reuse a persistent automation profile and wait for manual ChatGPT login. |
|
|
249
249
|
| `--browser-attach-running` | Reuse your current local browser session through local `DevToolsActivePort` discovery; Oracle opens a dedicated tab instead of launching Chrome (defaults to `127.0.0.1:9222`, or combine with `--remote-chrome <host:port>` to hint a different local endpoint). |
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export function isProjectChatgptUrl(url) {
|
|
2
2
|
return /\/project(?:[/?#]|$)/i.test(url ?? "");
|
|
3
3
|
}
|
|
4
|
+
export function isTemporaryChatgptUrl(url) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = new URL(url ?? "");
|
|
7
|
+
return (parsed.searchParams.get("temporary-chat") ?? "").trim().toLowerCase() === "true";
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
4
13
|
export function resolveBrowserArchiveDecision({ mode = "auto", chatgptUrl, conversationUrl, researchMode, followUpCount, }) {
|
|
5
14
|
if (mode === "never") {
|
|
6
15
|
return { mode, shouldArchive: false, reason: "disabled" };
|
|
@@ -8,6 +17,9 @@ export function resolveBrowserArchiveDecision({ mode = "auto", chatgptUrl, conve
|
|
|
8
17
|
if (!conversationUrl) {
|
|
9
18
|
return { mode, shouldArchive: false, reason: "missing-conversation-url" };
|
|
10
19
|
}
|
|
20
|
+
if (isTemporaryChatgptUrl(chatgptUrl) || isTemporaryChatgptUrl(conversationUrl)) {
|
|
21
|
+
return { mode, shouldArchive: false, reason: "temporary-chat" };
|
|
22
|
+
}
|
|
11
23
|
if (mode === "always") {
|
|
12
24
|
return { mode, shouldArchive: true, reason: "forced" };
|
|
13
25
|
}
|
|
@@ -25,7 +25,7 @@ export async function ensureModelSelection(Runtime, desiredModel, logger, strate
|
|
|
25
25
|
const available = (result.hint?.availableOptions ?? []).filter(Boolean);
|
|
26
26
|
const availableHint = available.length > 0 ? ` Available: ${available.join(", ")}.` : "";
|
|
27
27
|
const tempHint = isTemporary && /\bpro\b/i.test(desiredModel)
|
|
28
|
-
?
|
|
28
|
+
? " You are in Temporary Chat mode; model labels may differ there. If the current Temporary Chat already shows the desired Pro mode, retry with --browser-model-strategy current; otherwise choose an available model or turn Temporary Chat off."
|
|
29
29
|
: "";
|
|
30
30
|
throw new Error(`Unable to find model option matching "${desiredModel}" in the model switcher.${availableHint}${tempHint}`);
|
|
31
31
|
}
|
|
@@ -52,7 +52,7 @@ function assertResolvedModelSelection(desiredModel, resolvedLabel) {
|
|
|
52
52
|
resolved.includes("gpt-5.5-pro") ||
|
|
53
53
|
resolved.includes("gpt 5 5 pro");
|
|
54
54
|
if (!hasProSignal || (resolved.includes("thinking") && !resolved.includes("pro"))) {
|
|
55
|
-
throw new Error(`Model picker selected "${resolvedLabel}" while "${desiredModel}" requires GPT-5.5 Pro
|
|
55
|
+
throw new Error(`Model picker selected "${resolvedLabel}" while "${desiredModel}" requires GPT-5.5 Pro. Use model "gpt-5.5" with browser thinking time for the Thinking variant.`);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
export function assertResolvedModelSelectionForTest(desiredModel, resolvedLabel) {
|
|
@@ -125,10 +125,15 @@ function buildModelSelectionExpression(targetModel, strategy) {
|
|
|
125
125
|
if (desiredVersion !== '5-5') return false;
|
|
126
126
|
const label = normalizeText(value);
|
|
127
127
|
if (wantsPro) {
|
|
128
|
-
|
|
128
|
+
// ChatGPT UI as of 2026-05: the picker shows just "Pro" (no longer "Pro Extended").
|
|
129
|
+
// "Extended" is now a thinking-effort sub-setting, not part of the model label.
|
|
130
|
+
// Accept bare "pro", legacy "pro extended", and reversed "extended pro" (composer pill).
|
|
131
|
+
return (label === 'pro' || label === 'pro extended' || label === 'extended pro') && !label.includes('thinking');
|
|
129
132
|
}
|
|
130
133
|
if (wantsThinking) {
|
|
131
|
-
|
|
134
|
+
// ChatGPT UI as of 2026-05: the picker shows "Thinking" or "Thinking · Extended"
|
|
135
|
+
// (normalized to "thinking extended"). Accept both old "thinking heavy" and new labels.
|
|
136
|
+
return (label === 'thinking' || label === 'thinking extended' || label === 'thinking heavy') && !label.includes('pro');
|
|
132
137
|
}
|
|
133
138
|
return false;
|
|
134
139
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CHATGPT_URL, DEEP_RESEARCH_DEFAULT_TIMEOUT_MS, DEFAULT_MODEL_STRATEGY, DEFAULT_MODEL_TARGET, } from "./constants.js";
|
|
2
2
|
import { normalizeBrowserModelStrategy } from "./modelStrategy.js";
|
|
3
3
|
import { DEFAULT_MAX_CONCURRENT_CHATGPT_TABS, normalizeMaxConcurrentTabs, } from "./tabLeaseRegistry.js";
|
|
4
|
-
import {
|
|
4
|
+
import { normalizeChatgptUrl } from "./utils.js";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
export const DEFAULT_CHATGPT_COOKIE_NAMES = [
|
|
@@ -65,12 +65,6 @@ export function resolveBrowserConfig(config) {
|
|
|
65
65
|
const modelStrategy = normalizeBrowserModelStrategy(config?.modelStrategy) ??
|
|
66
66
|
DEFAULT_BROWSER_CONFIG.modelStrategy ??
|
|
67
67
|
DEFAULT_MODEL_STRATEGY;
|
|
68
|
-
if (modelStrategy === "select" &&
|
|
69
|
-
isTemporaryChatUrl(normalizedUrl) &&
|
|
70
|
-
/\bpro\b/i.test(desiredModel)) {
|
|
71
|
-
throw new Error("Temporary Chat mode does not expose Pro models in the ChatGPT model picker. " +
|
|
72
|
-
'Remove "temporary-chat=true" from your browser URL, or use a non-Pro model label (e.g. "GPT-5.2").');
|
|
73
|
-
}
|
|
74
68
|
const isWindows = process.platform === "win32";
|
|
75
69
|
const manualLogin = config?.manualLogin ?? (isWindows ? true : DEFAULT_BROWSER_CONFIG.manualLogin);
|
|
76
70
|
const cookieSyncDefault = isWindows ? false : DEFAULT_BROWSER_CONFIG.cookieSync;
|
|
@@ -70,19 +70,12 @@ export function shouldPreserveBrowserOnErrorForTest(error, headless) {
|
|
|
70
70
|
export function classifyPreservedBrowserErrorForTest(error, headless) {
|
|
71
71
|
return classifyPreservedBrowserError(error, headless);
|
|
72
72
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
normalized.includes("gpt-5.5 pro") ||
|
|
80
|
-
normalized.includes("gpt 5.5 pro") ||
|
|
81
|
-
normalized.includes("gpt 5 5 pro"));
|
|
82
|
-
}
|
|
83
|
-
export function shouldSkipThinkingTimeSelectionForTest(desiredModel, thinkingTime) {
|
|
84
|
-
return shouldSkipThinkingTimeSelection(desiredModel, thinkingTime);
|
|
85
|
-
}
|
|
73
|
+
// NOTE: Previously, shouldSkipThinkingTimeSelection() would skip the thinking
|
|
74
|
+
// time UI step when desiredModel was gpt-5.5-pro and thinkingTime was "extended",
|
|
75
|
+
// assuming that selecting "Pro Extended" in the old UI already implied Extended
|
|
76
|
+
// effort. This is wrong for lower-tier plans ($100/mo Pro) where selecting "Pro"
|
|
77
|
+
// defaults to Standard effort. ensureThinkingTime() already handles the
|
|
78
|
+
// "already-selected" case as a no-op, so always attempting it is safe.
|
|
86
79
|
function listIgnoredRemoteChromeFlags(config) {
|
|
87
80
|
return [
|
|
88
81
|
config.headless ? "--browser-headless" : null,
|
|
@@ -712,20 +705,15 @@ export async function runBrowserMode(options) {
|
|
|
712
705
|
// Handle thinking time selection if specified. Deep Research owns its own effort flow.
|
|
713
706
|
const thinkingTime = config.thinkingTime;
|
|
714
707
|
if (thinkingTime && !deepResearch) {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
logger(`[retry] Thinking time (${thinkingTime}) attempt ${attempt + 1}: ${error instanceof Error ? error.message : error}`);
|
|
725
|
-
}
|
|
726
|
-
},
|
|
727
|
-
}));
|
|
728
|
-
}
|
|
708
|
+
await raceWithDisconnect(withRetries(() => ensureThinkingTime(Runtime, thinkingTime, logger), {
|
|
709
|
+
retries: 2,
|
|
710
|
+
delayMs: 300,
|
|
711
|
+
onRetry: (attempt, error) => {
|
|
712
|
+
if (options.verbose) {
|
|
713
|
+
logger(`[retry] Thinking time (${thinkingTime}) attempt ${attempt + 1}: ${error instanceof Error ? error.message : error}`);
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
}));
|
|
729
717
|
}
|
|
730
718
|
if (deepResearch) {
|
|
731
719
|
await raceWithDisconnect(withRetries(() => activateDeepResearch(Runtime, Input, logger), {
|
|
@@ -1832,20 +1820,15 @@ async function runRemoteBrowserMode(promptText, attachments, config, logger, opt
|
|
|
1832
1820
|
// Handle thinking time selection if specified. Deep Research owns its own effort flow.
|
|
1833
1821
|
const thinkingTime = config.thinkingTime;
|
|
1834
1822
|
if (thinkingTime && !deepResearch) {
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
logger(`[retry] Thinking time (${thinkingTime}) attempt ${attempt + 1}: ${error instanceof Error ? error.message : error}`);
|
|
1845
|
-
}
|
|
1846
|
-
},
|
|
1847
|
-
});
|
|
1848
|
-
}
|
|
1823
|
+
await withRetries(() => ensureThinkingTime(Runtime, thinkingTime, logger), {
|
|
1824
|
+
retries: 2,
|
|
1825
|
+
delayMs: 300,
|
|
1826
|
+
onRetry: (attempt, error) => {
|
|
1827
|
+
if (options.verbose) {
|
|
1828
|
+
logger(`[retry] Thinking time (${thinkingTime}) attempt ${attempt + 1}: ${error instanceof Error ? error.message : error}`);
|
|
1829
|
+
}
|
|
1830
|
+
},
|
|
1831
|
+
});
|
|
1849
1832
|
}
|
|
1850
1833
|
if (deepResearch) {
|
|
1851
1834
|
await withRetries(() => activateDeepResearch(Runtime, Input, logger), {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { CHATGPT_URL, DEFAULT_MODEL_STRATEGY, DEFAULT_MODEL_TARGET,
|
|
3
|
+
import { CHATGPT_URL, DEFAULT_MODEL_STRATEGY, DEFAULT_MODEL_TARGET, normalizeChatgptUrl, parseDuration, } from "../browserMode.js";
|
|
4
4
|
import { normalizeBrowserModelStrategy } from "../browser/modelStrategy.js";
|
|
5
5
|
import { getOracleHomeDir } from "../oracleHome.js";
|
|
6
6
|
const DEFAULT_BROWSER_TIMEOUT_MS = 1_200_000;
|
|
@@ -86,13 +86,6 @@ export async function buildBrowserConfig(options) {
|
|
|
86
86
|
: shouldUseOverride
|
|
87
87
|
? desiredModelOverride
|
|
88
88
|
: mapModelToBrowserLabel(options.model);
|
|
89
|
-
if (modelStrategy === "select" &&
|
|
90
|
-
url &&
|
|
91
|
-
isTemporaryChatUrl(url) &&
|
|
92
|
-
/\bpro\b/i.test(desiredModel ?? "")) {
|
|
93
|
-
throw new Error("Temporary Chat mode does not expose Pro models in the ChatGPT model picker. " +
|
|
94
|
-
'Remove "temporary-chat=true" from --chatgpt-url (or omit --chatgpt-url), or use a non-Pro model (e.g. --model gpt-5.2).');
|
|
95
|
-
}
|
|
96
89
|
return {
|
|
97
90
|
chromeProfile: options.browserChromeProfile ?? DEFAULT_CHROME_PROFILE,
|
|
98
91
|
chromePath: options.browserChromePath ?? null,
|
package/dist/src/mcp/types.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export const CONSULT_PRESETS = ["chatgpt-pro-heavy"];
|
|
3
|
-
export const consultInputSchema = z
|
|
3
|
+
export const consultInputSchema = z
|
|
4
|
+
.object({
|
|
4
5
|
preset: z.enum(CONSULT_PRESETS).optional(),
|
|
5
6
|
prompt: z.string().min(1, "Prompt is required."),
|
|
6
7
|
files: z.array(z.string()).default([]),
|
|
@@ -19,7 +20,8 @@ export const consultInputSchema = z.object({
|
|
|
19
20
|
dryRun: z.boolean().optional(),
|
|
20
21
|
search: z.boolean().optional(),
|
|
21
22
|
slug: z.string().optional(),
|
|
22
|
-
})
|
|
23
|
+
})
|
|
24
|
+
.strict();
|
|
23
25
|
export const sessionsInputSchema = z.object({
|
|
24
26
|
id: z.string().optional(),
|
|
25
27
|
hours: z.number().optional(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steipete/oracle",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "CLI wrapper around OpenAI Responses API with 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://github.com/steipete/oracle#readme",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
59
|
-
"@google/genai": "^
|
|
59
|
+
"@google/genai": "^2.0.1",
|
|
60
60
|
"@google/generative-ai": "^0.24.1",
|
|
61
61
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
62
62
|
"@steipete/sweet-cookie": "^0.2.0",
|
|
@@ -85,12 +85,12 @@
|
|
|
85
85
|
"@types/chrome-remote-interface": "^0.33.0",
|
|
86
86
|
"@types/inquirer": "^9.0.9",
|
|
87
87
|
"@types/node": "^25.6.0",
|
|
88
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
88
|
+
"@typescript/native-preview": "7.0.0-dev.20260508.1",
|
|
89
89
|
"@vitest/coverage-v8": "4.1.5",
|
|
90
|
-
"devtools-protocol": "0.0.
|
|
90
|
+
"devtools-protocol": "0.0.1627472",
|
|
91
91
|
"es-toolkit": "^1.46.1",
|
|
92
92
|
"esbuild": "^0.28.0",
|
|
93
|
-
"oxfmt": "0.
|
|
93
|
+
"oxfmt": "0.48.0",
|
|
94
94
|
"oxlint": "^1.62.0",
|
|
95
95
|
"puppeteer-core": "^24.42.0",
|
|
96
96
|
"tsx": "^4.21.0",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"packageManager": "pnpm@10.33.2",
|
|
112
112
|
"pnpm": {
|
|
113
113
|
"overrides": {
|
|
114
|
-
"devtools-protocol": "0.0.
|
|
114
|
+
"devtools-protocol": "0.0.1627472"
|
|
115
115
|
},
|
|
116
116
|
"onlyBuiltDependencies": [
|
|
117
117
|
"esbuild"
|