@steipete/oracle 0.9.0 → 0.10.0
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/LICENSE +1 -1
- package/README.md +61 -48
- package/dist/bin/oracle-cli.js +455 -402
- package/dist/bin/oracle-mcp.js +2 -2
- package/dist/bin/oracle.js +165 -279
- package/dist/scripts/agent-send.js +31 -31
- package/dist/scripts/check.js +6 -6
- package/dist/scripts/debug/extract-chatgpt-response.js +10 -10
- package/dist/scripts/docs-list.js +30 -30
- package/dist/scripts/git-policy.js +25 -23
- package/dist/scripts/run-cli.js +8 -8
- package/dist/scripts/runner.js +203 -195
- package/dist/scripts/test-browser.js +21 -18
- package/dist/scripts/test-remote-chrome.js +20 -20
- package/dist/src/bridge/connection.js +18 -18
- package/dist/src/bridge/userConfigFile.js +7 -7
- package/dist/src/browser/actions/assistantResponse.js +149 -101
- package/dist/src/browser/actions/attachmentDataTransfer.js +49 -47
- package/dist/src/browser/actions/attachments.js +246 -150
- package/dist/src/browser/actions/domEvents.js +2 -2
- package/dist/src/browser/actions/modelSelection.js +275 -117
- package/dist/src/browser/actions/navigation.js +161 -137
- package/dist/src/browser/actions/promptComposer.js +100 -64
- package/dist/src/browser/actions/remoteFileTransfer.js +10 -10
- package/dist/src/browser/actions/thinkingTime.js +207 -110
- package/dist/src/browser/chromeLifecycle.js +62 -60
- package/dist/src/browser/config.js +34 -15
- package/dist/src/browser/constants.js +17 -12
- package/dist/src/browser/cookies.js +19 -19
- package/dist/src/browser/detect.js +62 -62
- package/dist/src/browser/domDebug.js +1 -1
- package/dist/src/browser/index.js +390 -295
- package/dist/src/browser/modelStrategy.js +1 -1
- package/dist/src/browser/pageActions.js +5 -5
- package/dist/src/browser/policies.js +16 -13
- package/dist/src/browser/profileState.js +44 -39
- package/dist/src/browser/prompt.js +72 -42
- package/dist/src/browser/promptSummary.js +5 -5
- package/dist/src/browser/providerDomFlow.js +1 -1
- package/dist/src/browser/providers/chatgptDomProvider.js +9 -9
- package/dist/src/browser/providers/geminiDeepThinkDomProvider.js +51 -42
- package/dist/src/browser/providers/index.js +2 -2
- package/dist/src/browser/reattach.js +67 -34
- package/dist/src/browser/reattachHelpers.js +31 -26
- package/dist/src/browser/sessionRunner.js +37 -25
- package/dist/src/browser/utils.js +9 -9
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/bridge/claudeConfig.js +16 -16
- package/dist/src/cli/bridge/client.js +28 -20
- package/dist/src/cli/bridge/codexConfig.js +16 -16
- package/dist/src/cli/bridge/doctor.js +47 -39
- package/dist/src/cli/bridge/host.js +58 -56
- package/dist/src/cli/browserConfig.js +62 -48
- package/dist/src/cli/browserDefaults.js +27 -26
- package/dist/src/cli/bundleWarnings.js +1 -1
- package/dist/src/cli/clipboard.js +11 -2
- package/dist/src/cli/detach.js +2 -2
- package/dist/src/cli/dryRun.js +29 -25
- package/dist/src/cli/duplicatePromptGuard.js +3 -3
- package/dist/src/cli/engine.js +9 -9
- package/dist/src/cli/errorUtils.js +1 -1
- package/dist/src/cli/fileSize.js +3 -3
- package/dist/src/cli/format.js +2 -2
- package/dist/src/cli/help.js +28 -28
- package/dist/src/cli/hiddenAliases.js +3 -3
- package/dist/src/cli/markdownBundle.js +7 -7
- package/dist/src/cli/markdownRenderer.js +15 -15
- package/dist/src/cli/notifier.js +77 -67
- package/dist/src/cli/options.js +127 -106
- package/dist/src/cli/oscUtils.js +1 -1
- package/dist/src/cli/promptRequirement.js +2 -2
- package/dist/src/cli/renderOutput.js +1 -1
- package/dist/src/cli/rootAlias.js +1 -1
- package/dist/src/cli/runOptions.js +32 -28
- package/dist/src/cli/sessionCommand.js +31 -21
- package/dist/src/cli/sessionDisplay.js +95 -81
- package/dist/src/cli/sessionLineage.js +6 -2
- package/dist/src/cli/sessionRunner.js +103 -93
- package/dist/src/cli/sessionTable.js +26 -23
- package/dist/src/cli/stdin.js +22 -0
- package/dist/src/cli/tagline.js +121 -124
- package/dist/src/cli/tui/index.js +139 -128
- package/dist/src/cli/writeOutputPath.js +5 -5
- package/dist/src/config.js +7 -7
- package/dist/src/gemini-web/browserSessionManager.js +19 -15
- package/dist/src/gemini-web/client.js +76 -70
- package/dist/src/gemini-web/executionMode.js +6 -8
- package/dist/src/gemini-web/executor.js +98 -93
- package/dist/src/gemini-web/index.js +1 -1
- package/dist/src/mcp/server.js +16 -12
- package/dist/src/mcp/tools/consult.js +51 -47
- package/dist/src/mcp/tools/sessionResources.js +12 -12
- package/dist/src/mcp/tools/sessions.js +26 -17
- package/dist/src/mcp/types.js +5 -5
- package/dist/src/mcp/utils.js +15 -7
- package/dist/src/oracle/background.js +15 -15
- package/dist/src/oracle/claude.js +53 -25
- package/dist/src/oracle/client.js +50 -41
- package/dist/src/oracle/config.js +96 -66
- package/dist/src/oracle/errors.js +38 -38
- package/dist/src/oracle/files.js +55 -46
- package/dist/src/oracle/finishLine.js +10 -8
- package/dist/src/oracle/format.js +3 -3
- package/dist/src/oracle/gemini.js +37 -33
- package/dist/src/oracle/logging.js +7 -7
- package/dist/src/oracle/markdown.js +28 -28
- package/dist/src/oracle/modelResolver.js +16 -16
- package/dist/src/oracle/multiModelRunner.js +12 -12
- package/dist/src/oracle/oscProgress.js +8 -8
- package/dist/src/oracle/promptAssembly.js +6 -3
- package/dist/src/oracle/request.js +16 -13
- package/dist/src/oracle/run.js +156 -134
- package/dist/src/oracle/runUtils.js +8 -5
- package/dist/src/oracle/tokenEstimate.js +6 -6
- package/dist/src/oracle/tokenStats.js +5 -5
- package/dist/src/oracle/tokenStringifier.js +5 -5
- package/dist/src/oracle.js +12 -12
- package/dist/src/oracleHome.js +3 -3
- package/dist/src/remote/client.js +25 -25
- package/dist/src/remote/health.js +20 -20
- package/dist/src/remote/remoteServiceConfig.js +9 -9
- package/dist/src/remote/server.js +129 -118
- package/dist/src/sessionManager.js +77 -75
- package/dist/src/sessionStore.js +3 -3
- package/dist/src/version.js +10 -10
- package/dist/vendor/oracle-notifier/README.md +2 -0
- package/package.json +66 -62
- package/vendor/oracle-notifier/README.md +2 -0
- package/dist/markdansi/types/index.js +0 -4
- package/dist/oracle/bin/oracle-cli.js +0 -472
- package/dist/oracle/src/browser/actions/assistantResponse.js +0 -471
- package/dist/oracle/src/browser/actions/attachments.js +0 -82
- package/dist/oracle/src/browser/actions/modelSelection.js +0 -190
- package/dist/oracle/src/browser/actions/navigation.js +0 -75
- package/dist/oracle/src/browser/actions/promptComposer.js +0 -167
- package/dist/oracle/src/browser/chromeLifecycle.js +0 -104
- package/dist/oracle/src/browser/config.js +0 -33
- package/dist/oracle/src/browser/constants.js +0 -40
- package/dist/oracle/src/browser/cookies.js +0 -210
- package/dist/oracle/src/browser/domDebug.js +0 -36
- package/dist/oracle/src/browser/index.js +0 -331
- package/dist/oracle/src/browser/pageActions.js +0 -5
- package/dist/oracle/src/browser/prompt.js +0 -88
- package/dist/oracle/src/browser/promptSummary.js +0 -20
- package/dist/oracle/src/browser/sessionRunner.js +0 -80
- package/dist/oracle/src/browser/types.js +0 -1
- package/dist/oracle/src/browser/utils.js +0 -62
- package/dist/oracle/src/browserMode.js +0 -1
- package/dist/oracle/src/cli/browserConfig.js +0 -44
- package/dist/oracle/src/cli/dryRun.js +0 -59
- package/dist/oracle/src/cli/engine.js +0 -17
- package/dist/oracle/src/cli/errorUtils.js +0 -9
- package/dist/oracle/src/cli/help.js +0 -70
- package/dist/oracle/src/cli/markdownRenderer.js +0 -15
- package/dist/oracle/src/cli/options.js +0 -103
- package/dist/oracle/src/cli/promptRequirement.js +0 -14
- package/dist/oracle/src/cli/rootAlias.js +0 -30
- package/dist/oracle/src/cli/sessionCommand.js +0 -77
- package/dist/oracle/src/cli/sessionDisplay.js +0 -270
- package/dist/oracle/src/cli/sessionRunner.js +0 -94
- package/dist/oracle/src/heartbeat.js +0 -43
- package/dist/oracle/src/oracle/client.js +0 -48
- package/dist/oracle/src/oracle/config.js +0 -29
- package/dist/oracle/src/oracle/errors.js +0 -101
- package/dist/oracle/src/oracle/files.js +0 -220
- package/dist/oracle/src/oracle/format.js +0 -33
- package/dist/oracle/src/oracle/fsAdapter.js +0 -7
- package/dist/oracle/src/oracle/oscProgress.js +0 -60
- package/dist/oracle/src/oracle/request.js +0 -48
- package/dist/oracle/src/oracle/run.js +0 -444
- package/dist/oracle/src/oracle/tokenStats.js +0 -39
- package/dist/oracle/src/oracle/types.js +0 -1
- package/dist/oracle/src/oracle.js +0 -9
- package/dist/oracle/src/sessionManager.js +0 -205
- package/dist/oracle/src/version.js +0 -39
- package/dist/scripts/chrome/browser-tools.js +0 -295
- package/dist/src/browser/profileSync.js +0 -141
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import path from
|
|
2
|
-
import { getCookies } from
|
|
3
|
-
import { runProviderDomFlow } from
|
|
4
|
-
import { delay } from
|
|
5
|
-
import { runGeminiWebWithFallback, saveFirstGeminiImageFromOutput } from
|
|
6
|
-
import { geminiDeepThinkDomProvider } from
|
|
7
|
-
import { openGeminiBrowserSession } from
|
|
8
|
-
import { selectGeminiExecutionMode } from
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { getCookies } from "@steipete/sweet-cookie";
|
|
3
|
+
import { runProviderDomFlow } from "../browser/providerDomFlow.js";
|
|
4
|
+
import { delay } from "../browser/utils.js";
|
|
5
|
+
import { runGeminiWebWithFallback, saveFirstGeminiImageFromOutput } from "./client.js";
|
|
6
|
+
import { geminiDeepThinkDomProvider } from "../browser/providers/index.js";
|
|
7
|
+
import { openGeminiBrowserSession } from "./browserSessionManager.js";
|
|
8
|
+
import { selectGeminiExecutionMode } from "./executionMode.js";
|
|
9
9
|
const GEMINI_COOKIE_NAMES = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
10
|
+
"__Secure-1PSID",
|
|
11
|
+
"__Secure-1PSIDTS",
|
|
12
|
+
"__Secure-1PSIDCC",
|
|
13
|
+
"__Secure-1PAPISID",
|
|
14
|
+
"NID",
|
|
15
|
+
"AEC",
|
|
16
|
+
"SOCS",
|
|
17
|
+
"__Secure-BUCKET",
|
|
18
|
+
"__Secure-ENID",
|
|
19
|
+
"SID",
|
|
20
|
+
"HSID",
|
|
21
|
+
"SSID",
|
|
22
|
+
"APISID",
|
|
23
|
+
"SAPISID",
|
|
24
|
+
"__Secure-3PSID",
|
|
25
|
+
"__Secure-3PSIDTS",
|
|
26
|
+
"__Secure-3PAPISID",
|
|
27
|
+
"SIDCC",
|
|
28
28
|
];
|
|
29
|
-
const GEMINI_REQUIRED_COOKIES = [
|
|
29
|
+
const GEMINI_REQUIRED_COOKIES = ["__Secure-1PSID", "__Secure-1PSIDTS"];
|
|
30
30
|
function estimateTokenCount(text) {
|
|
31
31
|
return Math.ceil(text.length / 4);
|
|
32
32
|
}
|
|
@@ -39,33 +39,33 @@ function resolveInvocationPath(value) {
|
|
|
39
39
|
return path.isAbsolute(trimmed) ? trimmed : path.resolve(process.cwd(), trimmed);
|
|
40
40
|
}
|
|
41
41
|
function resolveGeminiWebModel(desiredModel, log) {
|
|
42
|
-
const desired = typeof desiredModel ===
|
|
42
|
+
const desired = typeof desiredModel === "string" ? desiredModel.trim() : "";
|
|
43
43
|
if (!desired)
|
|
44
|
-
return
|
|
45
|
-
const normalized = desired.toLowerCase().replace(/[_\s]+/g,
|
|
44
|
+
return "gemini-3-pro";
|
|
45
|
+
const normalized = desired.toLowerCase().replace(/[_\s]+/g, "-");
|
|
46
46
|
switch (normalized) {
|
|
47
|
-
case
|
|
48
|
-
case
|
|
49
|
-
return
|
|
50
|
-
case
|
|
51
|
-
case
|
|
52
|
-
case
|
|
53
|
-
return
|
|
54
|
-
case
|
|
55
|
-
return
|
|
56
|
-
case
|
|
57
|
-
return
|
|
47
|
+
case "gemini-3-pro":
|
|
48
|
+
case "gemini-3.0-pro":
|
|
49
|
+
return "gemini-3-pro";
|
|
50
|
+
case "gemini-3-deep-think":
|
|
51
|
+
case "gemini-3-pro-deep-think":
|
|
52
|
+
case "gemini-3-pro-deepthink":
|
|
53
|
+
return "gemini-3-pro-deep-think";
|
|
54
|
+
case "gemini-2.5-pro":
|
|
55
|
+
return "gemini-2.5-pro";
|
|
56
|
+
case "gemini-2.5-flash":
|
|
57
|
+
return "gemini-2.5-flash";
|
|
58
58
|
default:
|
|
59
|
-
if (normalized.startsWith(
|
|
59
|
+
if (normalized.startsWith("gemini-") || normalized.includes("gemini")) {
|
|
60
60
|
log?.(`[gemini-web] Unsupported Gemini web model "${desired}". Falling back to gemini-3-pro.`);
|
|
61
61
|
}
|
|
62
|
-
return
|
|
62
|
+
return "gemini-3-pro";
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
function resolveCookieDomain(cookie) {
|
|
66
66
|
const rawDomain = cookie.domain?.trim();
|
|
67
67
|
if (rawDomain) {
|
|
68
|
-
return rawDomain.startsWith(
|
|
68
|
+
return rawDomain.startsWith(".") ? rawDomain.slice(1) : rawDomain;
|
|
69
69
|
}
|
|
70
70
|
const rawUrl = cookie.url?.trim();
|
|
71
71
|
if (rawUrl) {
|
|
@@ -79,14 +79,14 @@ function resolveCookieDomain(cookie) {
|
|
|
79
79
|
return null;
|
|
80
80
|
}
|
|
81
81
|
function pickCookieValue(cookies, name) {
|
|
82
|
-
const matches = cookies.filter((cookie) => cookie.name === name && typeof cookie.value ===
|
|
82
|
+
const matches = cookies.filter((cookie) => cookie.name === name && typeof cookie.value === "string");
|
|
83
83
|
if (matches.length === 0)
|
|
84
84
|
return undefined;
|
|
85
85
|
const preferredDomain = matches.find((cookie) => {
|
|
86
86
|
const domain = resolveCookieDomain(cookie);
|
|
87
|
-
return domain ===
|
|
87
|
+
return domain === "google.com" && (cookie.path ?? "/") === "/";
|
|
88
88
|
});
|
|
89
|
-
const googleDomain = matches.find((cookie) => (resolveCookieDomain(cookie) ??
|
|
89
|
+
const googleDomain = matches.find((cookie) => (resolveCookieDomain(cookie) ?? "").endsWith("google.com"));
|
|
90
90
|
return (preferredDomain ?? googleDomain ?? matches[0])?.value;
|
|
91
91
|
}
|
|
92
92
|
function buildGeminiCookieMap(cookies) {
|
|
@@ -102,15 +102,15 @@ function hasRequiredGeminiCookies(cookieMap) {
|
|
|
102
102
|
return GEMINI_REQUIRED_COOKIES.every((name) => Boolean(cookieMap[name]));
|
|
103
103
|
}
|
|
104
104
|
const GEMINI_CDP_COOKIE_URLS = [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
"https://gemini.google.com",
|
|
106
|
+
"https://accounts.google.com",
|
|
107
|
+
"https://www.google.com",
|
|
108
108
|
];
|
|
109
109
|
async function loadGeminiCookiesFromCDP(browserConfig, log) {
|
|
110
110
|
const session = await openGeminiBrowserSession({
|
|
111
111
|
browserConfig,
|
|
112
112
|
keepBrowserDefault: false,
|
|
113
|
-
purpose:
|
|
113
|
+
purpose: "Gemini manual-login cookie extraction (no keychain)",
|
|
114
114
|
log,
|
|
115
115
|
});
|
|
116
116
|
try {
|
|
@@ -118,8 +118,8 @@ async function loadGeminiCookiesFromCDP(browserConfig, log) {
|
|
|
118
118
|
const { Network, Page } = client;
|
|
119
119
|
await Network.enable({});
|
|
120
120
|
await Page.enable();
|
|
121
|
-
log?.(
|
|
122
|
-
await Page.navigate({ url:
|
|
121
|
+
log?.("[gemini-web] Navigating to gemini.google.com for sign-in/cookie capture...");
|
|
122
|
+
await Page.navigate({ url: "https://gemini.google.com" });
|
|
123
123
|
await delay(2_000);
|
|
124
124
|
const pollTimeoutMs = 5 * 60_000;
|
|
125
125
|
const pollIntervalMs = 2_000;
|
|
@@ -135,12 +135,12 @@ async function loadGeminiCookiesFromCDP(browserConfig, log) {
|
|
|
135
135
|
}
|
|
136
136
|
const now = Date.now();
|
|
137
137
|
if (now - lastNotice > 10_000) {
|
|
138
|
-
log?.(
|
|
138
|
+
log?.("[gemini-web] Waiting for Google sign-in... please sign in in the opened Chrome window.");
|
|
139
139
|
lastNotice = now;
|
|
140
140
|
}
|
|
141
141
|
await delay(pollIntervalMs);
|
|
142
142
|
}
|
|
143
|
-
throw new Error(
|
|
143
|
+
throw new Error("Timed out waiting for Google sign-in (5 minutes). Please sign in and retry.");
|
|
144
144
|
}
|
|
145
145
|
finally {
|
|
146
146
|
await session.close();
|
|
@@ -150,17 +150,19 @@ async function runGeminiDeepThinkViaBrowser(prompt, browserConfig, log) {
|
|
|
150
150
|
const session = await openGeminiBrowserSession({
|
|
151
151
|
browserConfig,
|
|
152
152
|
keepBrowserDefault: true,
|
|
153
|
-
purpose:
|
|
153
|
+
purpose: "Gemini Deep Think",
|
|
154
154
|
log,
|
|
155
155
|
});
|
|
156
156
|
try {
|
|
157
157
|
const client = session.client;
|
|
158
158
|
const { Runtime, Page } = client;
|
|
159
|
-
if (!Runtime ||
|
|
160
|
-
|
|
159
|
+
if (!Runtime ||
|
|
160
|
+
typeof Runtime.enable !== "function" ||
|
|
161
|
+
typeof Runtime.evaluate !== "function") {
|
|
162
|
+
throw new Error("Chrome Runtime domain unavailable for Gemini Deep Think DOM automation.");
|
|
161
163
|
}
|
|
162
|
-
if (!Page || typeof Page.enable !==
|
|
163
|
-
throw new Error(
|
|
164
|
+
if (!Page || typeof Page.enable !== "function" || typeof Page.navigate !== "function") {
|
|
165
|
+
throw new Error("Chrome Page domain unavailable for Gemini Deep Think DOM automation.");
|
|
164
166
|
}
|
|
165
167
|
await Runtime.enable();
|
|
166
168
|
await Page.enable();
|
|
@@ -168,8 +170,8 @@ async function runGeminiDeepThinkViaBrowser(prompt, browserConfig, log) {
|
|
|
168
170
|
const { result } = await Runtime.evaluate({ expression, returnByValue: true });
|
|
169
171
|
return result?.value;
|
|
170
172
|
};
|
|
171
|
-
log?.(
|
|
172
|
-
await Page.navigate({ url:
|
|
173
|
+
log?.("[gemini-web] Navigating to gemini.google.com...");
|
|
174
|
+
await Page.navigate({ url: "https://gemini.google.com/app" });
|
|
173
175
|
await delay(3_000);
|
|
174
176
|
const domResult = await runProviderDomFlow(geminiDeepThinkDomProvider, {
|
|
175
177
|
prompt,
|
|
@@ -192,13 +194,13 @@ async function loadGeminiCookiesFromInline(browserConfig, log) {
|
|
|
192
194
|
const inline = browserConfig?.inlineCookies;
|
|
193
195
|
if (!inline || inline.length === 0)
|
|
194
196
|
return { cookieMap: {}, warnings: [] };
|
|
195
|
-
const cookieMap = buildGeminiCookieMap(inline.filter((cookie) => Boolean(cookie?.name && typeof cookie.value ===
|
|
197
|
+
const cookieMap = buildGeminiCookieMap(inline.filter((cookie) => Boolean(cookie?.name && typeof cookie.value === "string")));
|
|
196
198
|
if (Object.keys(cookieMap).length > 0) {
|
|
197
|
-
const source = browserConfig?.inlineCookiesSource ??
|
|
199
|
+
const source = browserConfig?.inlineCookiesSource ?? "inline";
|
|
198
200
|
log?.(`[gemini-web] Loaded Gemini cookies from inline payload (${source}): ${Object.keys(cookieMap).length} cookie(s).`);
|
|
199
201
|
}
|
|
200
202
|
else {
|
|
201
|
-
log?.(
|
|
203
|
+
log?.("[gemini-web] Inline cookie payload provided but no Gemini cookies matched.");
|
|
202
204
|
}
|
|
203
205
|
return { cookieMap, warnings: [] };
|
|
204
206
|
}
|
|
@@ -206,42 +208,42 @@ async function loadGeminiCookiesFromChrome(browserConfig, log) {
|
|
|
206
208
|
try {
|
|
207
209
|
// Learned: Gemini web relies on Google auth cookies in the *browser* profile, not API keys.
|
|
208
210
|
const profileCandidate = browserConfig?.chromeCookiePath ?? browserConfig?.chromeProfile ?? undefined;
|
|
209
|
-
const profile = typeof profileCandidate ===
|
|
211
|
+
const profile = typeof profileCandidate === "string" && profileCandidate.trim().length > 0
|
|
210
212
|
? profileCandidate.trim()
|
|
211
213
|
: undefined;
|
|
212
214
|
const sources = [
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
"https://gemini.google.com",
|
|
216
|
+
"https://accounts.google.com",
|
|
217
|
+
"https://www.google.com",
|
|
216
218
|
];
|
|
217
219
|
const { cookies, warnings } = await getCookies({
|
|
218
220
|
url: sources[0],
|
|
219
221
|
origins: sources,
|
|
220
222
|
names: [...GEMINI_COOKIE_NAMES],
|
|
221
|
-
browsers: [
|
|
222
|
-
mode:
|
|
223
|
+
browsers: ["chrome"],
|
|
224
|
+
mode: "merge",
|
|
223
225
|
chromeProfile: profile,
|
|
224
226
|
timeoutMs: 5_000,
|
|
225
227
|
});
|
|
226
228
|
if (warnings.length && log?.verbose) {
|
|
227
|
-
log(`[gemini-web] Cookie warnings:\n- ${warnings.join(
|
|
229
|
+
log(`[gemini-web] Cookie warnings:\n- ${warnings.join("\n- ")}`);
|
|
228
230
|
}
|
|
229
231
|
const cookieMap = buildGeminiCookieMap(cookies);
|
|
230
232
|
log?.(`[gemini-web] Loaded Gemini cookies from Chrome (node): ${Object.keys(cookieMap).length} cookie(s).`);
|
|
231
233
|
return { cookieMap, warnings };
|
|
232
234
|
}
|
|
233
235
|
catch (error) {
|
|
234
|
-
log?.(`[gemini-web] Failed to load Chrome cookies via node: ${error instanceof Error ? error.message : String(error ??
|
|
236
|
+
log?.(`[gemini-web] Failed to load Chrome cookies via node: ${error instanceof Error ? error.message : String(error ?? "")}`);
|
|
235
237
|
return { cookieMap: {}, warnings: [] };
|
|
236
238
|
}
|
|
237
239
|
}
|
|
238
240
|
function formatGeminiCookieError(warnings) {
|
|
239
|
-
const base =
|
|
240
|
-
const guidance =
|
|
241
|
+
const base = "Gemini browser mode requires Chrome cookies for google.com (missing __Secure-1PSID/__Secure-1PSIDTS).";
|
|
242
|
+
const guidance = "Try --browser-manual-login or --browser-inline-cookies-file if local cookie extraction is unavailable.";
|
|
241
243
|
if (warnings.length === 0) {
|
|
242
244
|
return `${base} ${guidance}`;
|
|
243
245
|
}
|
|
244
|
-
return `${base}\nCookie read warnings:\n- ${warnings.join(
|
|
246
|
+
return `${base}\nCookie read warnings:\n- ${warnings.join("\n- ")}\n${guidance}`;
|
|
245
247
|
}
|
|
246
248
|
async function loadGeminiCookies(browserConfig, log, options) {
|
|
247
249
|
const inlineResult = await loadGeminiCookiesFromInline(browserConfig, log);
|
|
@@ -251,7 +253,7 @@ async function loadGeminiCookies(browserConfig, log, options) {
|
|
|
251
253
|
}
|
|
252
254
|
const manualNoKeychain = Boolean(browserConfig?.manualLogin) || Boolean(options?.preferManualNoKeychain);
|
|
253
255
|
if (manualNoKeychain) {
|
|
254
|
-
log?.(
|
|
256
|
+
log?.("[gemini-web] Using manual-login cookie extraction path (no keychain cookie read).");
|
|
255
257
|
const cdpResult = await loadGeminiCookiesFromCDP(browserConfig, log);
|
|
256
258
|
return {
|
|
257
259
|
cookieMap: { ...cdpResult.cookieMap, ...inlineResult.cookieMap },
|
|
@@ -259,7 +261,7 @@ async function loadGeminiCookies(browserConfig, log, options) {
|
|
|
259
261
|
};
|
|
260
262
|
}
|
|
261
263
|
if (browserConfig?.cookieSync === false && !hasInlineRequired) {
|
|
262
|
-
log?.(
|
|
264
|
+
log?.("[gemini-web] Cookie sync disabled and inline cookies missing Gemini auth tokens.");
|
|
263
265
|
return inlineResult;
|
|
264
266
|
}
|
|
265
267
|
const chromeResult = await loadGeminiCookiesFromChrome(browserConfig, log);
|
|
@@ -272,7 +274,7 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
272
274
|
return async (runOptions) => {
|
|
273
275
|
const startTime = Date.now();
|
|
274
276
|
const log = runOptions.log;
|
|
275
|
-
log?.(
|
|
277
|
+
log?.("[gemini-web] Starting Gemini web executor (TypeScript)");
|
|
276
278
|
const model = resolveGeminiWebModel(runOptions.config?.desiredModel, log);
|
|
277
279
|
const generateImagePath = resolveInvocationPath(geminiOptions.generateImage);
|
|
278
280
|
const editImagePath = resolveInvocationPath(geminiOptions.editImage);
|
|
@@ -295,9 +297,9 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
295
297
|
editImagePath,
|
|
296
298
|
});
|
|
297
299
|
const domClient = {
|
|
298
|
-
mode:
|
|
300
|
+
mode: "dom",
|
|
299
301
|
execute: async () => {
|
|
300
|
-
log?.(
|
|
302
|
+
log?.("[gemini-web] Using browser DOM automation for Deep Think.");
|
|
301
303
|
const browserResult = await runGeminiDeepThinkViaBrowser(prompt, runOptions.config, log);
|
|
302
304
|
const tookMs = Date.now() - startTime;
|
|
303
305
|
let answerMarkdown = browserResult.text;
|
|
@@ -315,14 +317,17 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
315
317
|
},
|
|
316
318
|
};
|
|
317
319
|
const httpClient = {
|
|
318
|
-
mode:
|
|
320
|
+
mode: "http",
|
|
319
321
|
execute: async () => {
|
|
320
322
|
const useNoKeychainPath = Boolean(runOptions.config?.manualLogin);
|
|
321
|
-
const cookieResult = await loadGeminiCookies(runOptions.config, log, {
|
|
323
|
+
const cookieResult = await loadGeminiCookies(runOptions.config, log, {
|
|
324
|
+
preferManualNoKeychain: useNoKeychainPath,
|
|
325
|
+
});
|
|
322
326
|
if (!hasRequiredGeminiCookies(cookieResult.cookieMap)) {
|
|
323
327
|
throw new Error(formatGeminiCookieError(cookieResult.warnings));
|
|
324
328
|
}
|
|
325
|
-
const configTimeout = typeof runOptions.config?.timeoutMs ===
|
|
329
|
+
const configTimeout = typeof runOptions.config?.timeoutMs === "number" &&
|
|
330
|
+
Number.isFinite(runOptions.config.timeoutMs)
|
|
326
331
|
? Math.max(1_000, runOptions.config.timeoutMs)
|
|
327
332
|
: null;
|
|
328
333
|
const defaultTimeoutMs = geminiOptions.youtube
|
|
@@ -337,7 +342,7 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
337
342
|
try {
|
|
338
343
|
if (editImagePath) {
|
|
339
344
|
const intro = await runGeminiWebWithFallback({
|
|
340
|
-
prompt:
|
|
345
|
+
prompt: "Here is an image to edit",
|
|
341
346
|
files: [editImagePath],
|
|
342
347
|
model,
|
|
343
348
|
cookieMap: cookieResult.cookieMap,
|
|
@@ -359,12 +364,12 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
359
364
|
has_images: false,
|
|
360
365
|
image_count: 0,
|
|
361
366
|
};
|
|
362
|
-
const resolvedOutputPath = outputPath ?? generateImagePath ??
|
|
367
|
+
const resolvedOutputPath = outputPath ?? generateImagePath ?? "generated.png";
|
|
363
368
|
const imageSave = await saveFirstGeminiImageFromOutput(out, cookieResult.cookieMap, resolvedOutputPath, controller.signal);
|
|
364
369
|
response.has_images = imageSave.saved;
|
|
365
370
|
response.image_count = imageSave.imageCount;
|
|
366
371
|
if (!imageSave.saved) {
|
|
367
|
-
throw new Error(`No images generated. Response text:\n${out.text ||
|
|
372
|
+
throw new Error(`No images generated. Response text:\n${out.text || "(empty response)"}`);
|
|
368
373
|
}
|
|
369
374
|
}
|
|
370
375
|
else if (generateImagePath) {
|
|
@@ -386,7 +391,7 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
386
391
|
response.has_images = imageSave.saved;
|
|
387
392
|
response.image_count = imageSave.imageCount;
|
|
388
393
|
if (!imageSave.saved) {
|
|
389
|
-
throw new Error(`No images generated. Response text:\n${out.text ||
|
|
394
|
+
throw new Error(`No images generated. Response text:\n${out.text || "(empty response)"}`);
|
|
390
395
|
}
|
|
391
396
|
}
|
|
392
397
|
else {
|
|
@@ -409,13 +414,13 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
409
414
|
finally {
|
|
410
415
|
clearTimeout(timeout);
|
|
411
416
|
}
|
|
412
|
-
const answerText = response.text ??
|
|
417
|
+
const answerText = response.text ?? "";
|
|
413
418
|
let answerMarkdown = answerText;
|
|
414
419
|
if (geminiOptions.showThoughts && response.thoughts) {
|
|
415
420
|
answerMarkdown = `## Thinking\n\n${response.thoughts}\n\n## Response\n\n${answerText}`;
|
|
416
421
|
}
|
|
417
422
|
if (response.has_images && response.image_count > 0) {
|
|
418
|
-
const imagePath = generateImagePath || outputPath ||
|
|
423
|
+
const imagePath = generateImagePath || outputPath || "generated.png";
|
|
419
424
|
answerMarkdown += `\n\n*Generated ${response.image_count} image(s). Saved to: ${imagePath}*`;
|
|
420
425
|
}
|
|
421
426
|
const tookMs = Date.now() - startTime;
|
|
@@ -429,10 +434,10 @@ export function createGeminiWebExecutor(geminiOptions) {
|
|
|
429
434
|
};
|
|
430
435
|
},
|
|
431
436
|
};
|
|
432
|
-
if (model ===
|
|
433
|
-
log?.(`[gemini-web] Deep Think DOM path skipped (${modeSelection.reasons.join(
|
|
437
|
+
if (model === "gemini-3-pro-deep-think" && modeSelection.mode === "http") {
|
|
438
|
+
log?.(`[gemini-web] Deep Think DOM path skipped (${modeSelection.reasons.join(", ")} requested); using HTTP/header fallback path.`);
|
|
434
439
|
}
|
|
435
|
-
const executionClient = modeSelection.mode ===
|
|
440
|
+
const executionClient = modeSelection.mode === "dom" ? domClient : httpClient;
|
|
436
441
|
return executionClient.execute();
|
|
437
442
|
};
|
|
438
443
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { createGeminiWebExecutor } from
|
|
1
|
+
export { createGeminiWebExecutor } from "./executor.js";
|
package/dist/src/mcp/server.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import process from
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { getCliVersion } from "../version.js";
|
|
8
|
+
import { registerConsultTool } from "./tools/consult.js";
|
|
9
|
+
import { registerSessionsTool } from "./tools/sessions.js";
|
|
10
|
+
import { registerSessionResources } from "./tools/sessionResources.js";
|
|
10
11
|
export async function startMcpServer() {
|
|
11
12
|
const server = new McpServer({
|
|
12
|
-
name:
|
|
13
|
+
name: "oracle-mcp",
|
|
13
14
|
version: getCliVersion(),
|
|
14
15
|
}, {
|
|
15
16
|
capabilities: {
|
|
@@ -21,7 +22,7 @@ export async function startMcpServer() {
|
|
|
21
22
|
registerSessionResources(server);
|
|
22
23
|
const transport = new StdioServerTransport();
|
|
23
24
|
transport.onerror = (error) => {
|
|
24
|
-
console.error(
|
|
25
|
+
console.error("MCP transport error:", error);
|
|
25
26
|
};
|
|
26
27
|
const closed = new Promise((resolve) => {
|
|
27
28
|
transport.onclose = () => {
|
|
@@ -32,9 +33,12 @@ export async function startMcpServer() {
|
|
|
32
33
|
await server.connect(transport);
|
|
33
34
|
await closed;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
export function shouldStartMcpServerFromModule(moduleUrl = import.meta.url, argv1 = process.argv[1]) {
|
|
37
|
+
return argv1 ? moduleUrl === pathToFileURL(argv1).href : false;
|
|
38
|
+
}
|
|
39
|
+
if (shouldStartMcpServerFromModule()) {
|
|
36
40
|
startMcpServer().catch((error) => {
|
|
37
|
-
console.error(
|
|
41
|
+
console.error("Failed to start oracle-mcp:", error);
|
|
38
42
|
process.exitCode = 1;
|
|
39
43
|
});
|
|
40
44
|
}
|