@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,39 +1,39 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from
|
|
2
|
-
import path from
|
|
3
|
-
const USER_AGENT =
|
|
4
|
-
const MODEL_HEADER_NAME =
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
4
|
+
const MODEL_HEADER_NAME = "x-goog-ext-525001261-jspb";
|
|
5
5
|
const MODEL_HEADERS = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
"gemini-3-pro": '[1,null,null,null,"9d8ca3786ebdfbea",null,null,0,[4]]',
|
|
7
|
+
"gemini-3-pro-deep-think": '[1,null,null,null,"e6fa609c3fa255c0",null,null,0,[4],null,null,3]',
|
|
8
|
+
"gemini-2.5-pro": '[1,null,null,null,"4af6c7f5da75d65d",null,null,0,[4]]',
|
|
9
|
+
"gemini-2.5-flash": '[1,null,null,null,"9ec249fc9ad08861",null,null,0,[4]]',
|
|
10
10
|
};
|
|
11
|
-
const GEMINI_APP_URL =
|
|
12
|
-
const GEMINI_STREAM_GENERATE_URL =
|
|
13
|
-
const GEMINI_UPLOAD_URL =
|
|
14
|
-
const GEMINI_UPLOAD_PUSH_ID =
|
|
11
|
+
const GEMINI_APP_URL = "https://gemini.google.com/app";
|
|
12
|
+
const GEMINI_STREAM_GENERATE_URL = "https://gemini.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate";
|
|
13
|
+
const GEMINI_UPLOAD_URL = "https://content-push.googleapis.com/upload";
|
|
14
|
+
const GEMINI_UPLOAD_PUSH_ID = "feeds/mcudyrk2a4khkz";
|
|
15
15
|
const GEMINI_UPLOAD_MIME_TYPES = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
".bmp": "image/bmp",
|
|
17
|
+
".gif": "image/gif",
|
|
18
|
+
".jpeg": "image/jpeg",
|
|
19
|
+
".jpg": "image/jpeg",
|
|
20
|
+
".pdf": "application/pdf",
|
|
21
|
+
".png": "image/png",
|
|
22
|
+
".svg": "image/svg+xml",
|
|
23
|
+
".webp": "image/webp",
|
|
24
24
|
};
|
|
25
25
|
function getNestedValue(value, pathParts, fallback) {
|
|
26
26
|
let current = value;
|
|
27
27
|
for (const part of pathParts) {
|
|
28
28
|
if (current == null)
|
|
29
29
|
return fallback;
|
|
30
|
-
if (typeof part ===
|
|
30
|
+
if (typeof part === "number") {
|
|
31
31
|
if (!Array.isArray(current))
|
|
32
32
|
return fallback;
|
|
33
33
|
current = current[part];
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
|
-
if (typeof current !==
|
|
36
|
+
if (typeof current !== "object")
|
|
37
37
|
return fallback;
|
|
38
38
|
current = current[part];
|
|
39
39
|
}
|
|
@@ -42,40 +42,40 @@ function getNestedValue(value, pathParts, fallback) {
|
|
|
42
42
|
}
|
|
43
43
|
function buildCookieHeader(cookieMap) {
|
|
44
44
|
return Object.entries(cookieMap)
|
|
45
|
-
.filter(([, value]) => typeof value ===
|
|
45
|
+
.filter(([, value]) => typeof value === "string" && value.length > 0)
|
|
46
46
|
.map(([name, value]) => `${name}=${value}`)
|
|
47
|
-
.join(
|
|
47
|
+
.join("; ");
|
|
48
48
|
}
|
|
49
49
|
export async function fetchGeminiAccessToken(cookieMap, signal) {
|
|
50
50
|
const cookieHeader = buildCookieHeader(cookieMap);
|
|
51
51
|
const res = await fetch(GEMINI_APP_URL, {
|
|
52
|
-
redirect:
|
|
52
|
+
redirect: "follow",
|
|
53
53
|
signal,
|
|
54
54
|
headers: {
|
|
55
55
|
cookie: cookieHeader,
|
|
56
|
-
|
|
56
|
+
"user-agent": USER_AGENT,
|
|
57
57
|
},
|
|
58
58
|
});
|
|
59
59
|
const html = await res.text();
|
|
60
|
-
const tokens = [
|
|
60
|
+
const tokens = ["SNlM0e", "thykhd"];
|
|
61
61
|
for (const key of tokens) {
|
|
62
62
|
const match = html.match(new RegExp(`"${key}":"(.*?)"`));
|
|
63
63
|
if (match?.[1])
|
|
64
64
|
return match[1];
|
|
65
65
|
}
|
|
66
|
-
throw new Error(
|
|
66
|
+
throw new Error("Unable to locate Gemini access token on gemini.google.com/app (missing SNlM0e/thykhd).");
|
|
67
67
|
}
|
|
68
68
|
function trimGeminiJsonEnvelope(text) {
|
|
69
|
-
const start = text.indexOf(
|
|
70
|
-
const end = text.lastIndexOf(
|
|
69
|
+
const start = text.indexOf("[");
|
|
70
|
+
const end = text.lastIndexOf("]");
|
|
71
71
|
if (start === -1 || end === -1 || end <= start) {
|
|
72
|
-
throw new Error(
|
|
72
|
+
throw new Error("Gemini response did not contain a JSON payload.");
|
|
73
73
|
}
|
|
74
74
|
return text.slice(start, end + 1);
|
|
75
75
|
}
|
|
76
76
|
function extractErrorCode(responseJson) {
|
|
77
77
|
const code = getNestedValue(responseJson, [0, 5, 2, 0, 1, 0], -1);
|
|
78
|
-
return typeof code ===
|
|
78
|
+
return typeof code === "number" && code >= 0 ? code : undefined;
|
|
79
79
|
}
|
|
80
80
|
function extractGgdlUrls(rawText) {
|
|
81
81
|
const matches = rawText.match(/https:\/\/lh3\.googleusercontent\.com\/gg-dl\/[^\s"']+/g) ?? [];
|
|
@@ -90,18 +90,18 @@ function extractGgdlUrls(rawText) {
|
|
|
90
90
|
return urls;
|
|
91
91
|
}
|
|
92
92
|
function ensureFullSizeImageUrl(url) {
|
|
93
|
-
if (url.includes(
|
|
93
|
+
if (url.includes("=s2048"))
|
|
94
94
|
return url;
|
|
95
|
-
if (url.includes(
|
|
95
|
+
if (url.includes("=s"))
|
|
96
96
|
return url;
|
|
97
97
|
return `${url}=s2048`;
|
|
98
98
|
}
|
|
99
99
|
async function fetchWithCookiePreservingRedirects(url, init, signal, maxRedirects = 10) {
|
|
100
100
|
let current = url;
|
|
101
101
|
for (let i = 0; i <= maxRedirects; i += 1) {
|
|
102
|
-
const res = await fetch(current, { ...init, redirect:
|
|
102
|
+
const res = await fetch(current, { ...init, redirect: "manual", signal });
|
|
103
103
|
if (res.status >= 300 && res.status < 400) {
|
|
104
|
-
const location = res.headers.get(
|
|
104
|
+
const location = res.headers.get("location");
|
|
105
105
|
if (!location)
|
|
106
106
|
return res;
|
|
107
107
|
current = new URL(location, current).toString();
|
|
@@ -116,7 +116,7 @@ async function downloadGeminiImage(url, cookieMap, outputPath, signal) {
|
|
|
116
116
|
const res = await fetchWithCookiePreservingRedirects(ensureFullSizeImageUrl(url), {
|
|
117
117
|
headers: {
|
|
118
118
|
cookie: cookieHeader,
|
|
119
|
-
|
|
119
|
+
"user-agent": USER_AGENT,
|
|
120
120
|
},
|
|
121
121
|
}, signal);
|
|
122
122
|
if (!res.ok) {
|
|
@@ -130,16 +130,16 @@ async function uploadGeminiFile(filePath, signal) {
|
|
|
130
130
|
const absPath = path.resolve(process.cwd(), filePath);
|
|
131
131
|
const data = await readFile(absPath);
|
|
132
132
|
const fileName = path.basename(absPath);
|
|
133
|
-
const mimeType = GEMINI_UPLOAD_MIME_TYPES[path.extname(absPath).toLowerCase()] ??
|
|
133
|
+
const mimeType = GEMINI_UPLOAD_MIME_TYPES[path.extname(absPath).toLowerCase()] ?? "application/octet-stream";
|
|
134
134
|
const form = new FormData();
|
|
135
|
-
form.append(
|
|
135
|
+
form.append("file", new Blob([data], { type: mimeType }), fileName);
|
|
136
136
|
const res = await fetch(GEMINI_UPLOAD_URL, {
|
|
137
|
-
method:
|
|
138
|
-
redirect:
|
|
137
|
+
method: "POST",
|
|
138
|
+
redirect: "follow",
|
|
139
139
|
signal,
|
|
140
140
|
headers: {
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
"push-id": GEMINI_UPLOAD_PUSH_ID,
|
|
142
|
+
"user-agent": USER_AGENT,
|
|
143
143
|
},
|
|
144
144
|
body: form,
|
|
145
145
|
});
|
|
@@ -176,9 +176,15 @@ export function parseGeminiStreamGenerateResponse(rawText) {
|
|
|
176
176
|
const parsed = JSON.parse(partBody);
|
|
177
177
|
const candidateList = getNestedValue(parsed, [4], []);
|
|
178
178
|
if (Array.isArray(candidateList) && candidateList.length > 0) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
const candidateText = getNestedValue(candidateList[0], [1, 0], "");
|
|
180
|
+
const hasText = typeof candidateText === "string" && candidateText.length > 0;
|
|
181
|
+
if (body === null) {
|
|
182
|
+
bodyIndex = i;
|
|
183
|
+
body = parsed;
|
|
184
|
+
}
|
|
185
|
+
else if (hasText) {
|
|
186
|
+
body = parsed;
|
|
187
|
+
}
|
|
182
188
|
}
|
|
183
189
|
}
|
|
184
190
|
catch {
|
|
@@ -187,7 +193,7 @@ export function parseGeminiStreamGenerateResponse(rawText) {
|
|
|
187
193
|
}
|
|
188
194
|
const candidateList = getNestedValue(body, [4], []);
|
|
189
195
|
const firstCandidate = candidateList[0];
|
|
190
|
-
const textRaw = getNestedValue(firstCandidate, [1, 0],
|
|
196
|
+
const textRaw = getNestedValue(firstCandidate, [1, 0], "");
|
|
191
197
|
const cardContent = /^http:\/\/googleusercontent\.com\/card_content\/\d+/.test(textRaw);
|
|
192
198
|
const text = cardContent
|
|
193
199
|
? (getNestedValue(firstCandidate, [22, 0], null) ?? textRaw)
|
|
@@ -201,7 +207,7 @@ export function parseGeminiStreamGenerateResponse(rawText) {
|
|
|
201
207
|
if (!url)
|
|
202
208
|
continue;
|
|
203
209
|
images.push({
|
|
204
|
-
kind:
|
|
210
|
+
kind: "web",
|
|
205
211
|
url,
|
|
206
212
|
title: getNestedValue(webImage, [7, 0], undefined),
|
|
207
213
|
alt: getNestedValue(webImage, [0, 4], undefined),
|
|
@@ -233,10 +239,10 @@ export function parseGeminiStreamGenerateResponse(rawText) {
|
|
|
233
239
|
if (!url)
|
|
234
240
|
continue;
|
|
235
241
|
images.push({
|
|
236
|
-
kind:
|
|
242
|
+
kind: "generated",
|
|
237
243
|
url,
|
|
238
|
-
title:
|
|
239
|
-
alt:
|
|
244
|
+
title: "[Generated Image]",
|
|
245
|
+
alt: "",
|
|
240
246
|
});
|
|
241
247
|
}
|
|
242
248
|
}
|
|
@@ -251,24 +257,24 @@ export async function runGeminiWebOnce(input) {
|
|
|
251
257
|
const uploaded = [];
|
|
252
258
|
for (const file of input.files ?? []) {
|
|
253
259
|
if (input.signal?.aborted) {
|
|
254
|
-
throw new Error(
|
|
260
|
+
throw new Error("Gemini web run aborted before upload.");
|
|
255
261
|
}
|
|
256
262
|
uploaded.push(await uploadGeminiFile(file, input.signal));
|
|
257
263
|
}
|
|
258
264
|
const fReq = buildGeminiFReqPayload(input.prompt, uploaded, input.chatMetadata ?? null);
|
|
259
265
|
const params = new URLSearchParams();
|
|
260
|
-
params.set(
|
|
261
|
-
params.set(
|
|
266
|
+
params.set("at", at);
|
|
267
|
+
params.set("f.req", fReq);
|
|
262
268
|
const res = await fetch(GEMINI_STREAM_GENERATE_URL, {
|
|
263
|
-
method:
|
|
264
|
-
redirect:
|
|
269
|
+
method: "POST",
|
|
270
|
+
redirect: "follow",
|
|
265
271
|
signal: input.signal,
|
|
266
272
|
headers: {
|
|
267
|
-
|
|
268
|
-
origin:
|
|
269
|
-
referer:
|
|
270
|
-
|
|
271
|
-
|
|
273
|
+
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
|
|
274
|
+
origin: "https://gemini.google.com",
|
|
275
|
+
referer: "https://gemini.google.com/",
|
|
276
|
+
"x-same-domain": "1",
|
|
277
|
+
"user-agent": USER_AGENT,
|
|
272
278
|
cookie: cookieHeader,
|
|
273
279
|
[MODEL_HEADER_NAME]: MODEL_HEADERS[input.model],
|
|
274
280
|
},
|
|
@@ -278,7 +284,7 @@ export async function runGeminiWebOnce(input) {
|
|
|
278
284
|
if (!res.ok) {
|
|
279
285
|
return {
|
|
280
286
|
rawResponseText,
|
|
281
|
-
text:
|
|
287
|
+
text: "",
|
|
282
288
|
thoughts: null,
|
|
283
289
|
metadata: input.chatMetadata ?? null,
|
|
284
290
|
images: [],
|
|
@@ -289,7 +295,7 @@ export async function runGeminiWebOnce(input) {
|
|
|
289
295
|
const parsed = parseGeminiStreamGenerateResponse(rawResponseText);
|
|
290
296
|
return {
|
|
291
297
|
rawResponseText,
|
|
292
|
-
text: parsed.text ??
|
|
298
|
+
text: parsed.text ?? "",
|
|
293
299
|
thoughts: parsed.thoughts,
|
|
294
300
|
metadata: parsed.metadata,
|
|
295
301
|
images: parsed.images,
|
|
@@ -307,25 +313,25 @@ export async function runGeminiWebOnce(input) {
|
|
|
307
313
|
const errorCode = extractErrorCode(responseJson);
|
|
308
314
|
return {
|
|
309
315
|
rawResponseText,
|
|
310
|
-
text:
|
|
316
|
+
text: "",
|
|
311
317
|
thoughts: null,
|
|
312
318
|
metadata: input.chatMetadata ?? null,
|
|
313
319
|
images: [],
|
|
314
|
-
errorCode: typeof errorCode ===
|
|
315
|
-
errorMessage: error instanceof Error ? error.message : String(error ??
|
|
320
|
+
errorCode: typeof errorCode === "number" ? errorCode : undefined,
|
|
321
|
+
errorMessage: error instanceof Error ? error.message : String(error ?? ""),
|
|
316
322
|
};
|
|
317
323
|
}
|
|
318
324
|
}
|
|
319
325
|
export async function runGeminiWebWithFallback(input) {
|
|
320
326
|
const attempt = await runGeminiWebOnce(input);
|
|
321
|
-
if (isGeminiModelUnavailable(attempt.errorCode) && input.model !==
|
|
322
|
-
const fallback = await runGeminiWebOnce({ ...input, model:
|
|
323
|
-
return { ...fallback, effectiveModel:
|
|
327
|
+
if (isGeminiModelUnavailable(attempt.errorCode) && input.model !== "gemini-2.5-flash") {
|
|
328
|
+
const fallback = await runGeminiWebOnce({ ...input, model: "gemini-2.5-flash" });
|
|
329
|
+
return { ...fallback, effectiveModel: "gemini-2.5-flash" };
|
|
324
330
|
}
|
|
325
331
|
return { ...attempt, effectiveModel: input.model };
|
|
326
332
|
}
|
|
327
333
|
export async function saveFirstGeminiImageFromOutput(output, cookieMap, outputPath, signal) {
|
|
328
|
-
const generatedOrWeb = output.images.find((img) => img.kind ===
|
|
334
|
+
const generatedOrWeb = output.images.find((img) => img.kind === "generated") ?? output.images[0];
|
|
329
335
|
if (generatedOrWeb?.url) {
|
|
330
336
|
await downloadGeminiImage(generatedOrWeb.url, cookieMap, outputPath, signal);
|
|
331
337
|
return { saved: true, imageCount: output.images.length };
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
export function selectGeminiExecutionMode(input) {
|
|
2
2
|
const reasons = [];
|
|
3
|
-
if (input.model !==
|
|
4
|
-
return { mode:
|
|
3
|
+
if (input.model !== "gemini-3-pro-deep-think") {
|
|
4
|
+
return { mode: "http", reasons: ["model"] };
|
|
5
5
|
}
|
|
6
6
|
if (input.attachmentPaths.length > 0) {
|
|
7
|
-
reasons.push(
|
|
7
|
+
reasons.push("attachments");
|
|
8
8
|
}
|
|
9
9
|
if (input.generateImagePath) {
|
|
10
|
-
reasons.push(
|
|
10
|
+
reasons.push("image-generation");
|
|
11
11
|
}
|
|
12
12
|
if (input.editImagePath) {
|
|
13
|
-
reasons.push(
|
|
13
|
+
reasons.push("image-edit");
|
|
14
14
|
}
|
|
15
|
-
return reasons.length === 0
|
|
16
|
-
? { mode: 'dom', reasons: [] }
|
|
17
|
-
: { mode: 'http', reasons };
|
|
15
|
+
return reasons.length === 0 ? { mode: "dom", reasons: [] } : { mode: "http", reasons };
|
|
18
16
|
}
|