@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.
Files changed (177) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +61 -48
  3. package/dist/bin/oracle-cli.js +455 -402
  4. package/dist/bin/oracle-mcp.js +2 -2
  5. package/dist/bin/oracle.js +165 -279
  6. package/dist/scripts/agent-send.js +31 -31
  7. package/dist/scripts/check.js +6 -6
  8. package/dist/scripts/debug/extract-chatgpt-response.js +10 -10
  9. package/dist/scripts/docs-list.js +30 -30
  10. package/dist/scripts/git-policy.js +25 -23
  11. package/dist/scripts/run-cli.js +8 -8
  12. package/dist/scripts/runner.js +203 -195
  13. package/dist/scripts/test-browser.js +21 -18
  14. package/dist/scripts/test-remote-chrome.js +20 -20
  15. package/dist/src/bridge/connection.js +18 -18
  16. package/dist/src/bridge/userConfigFile.js +7 -7
  17. package/dist/src/browser/actions/assistantResponse.js +149 -101
  18. package/dist/src/browser/actions/attachmentDataTransfer.js +49 -47
  19. package/dist/src/browser/actions/attachments.js +246 -150
  20. package/dist/src/browser/actions/domEvents.js +2 -2
  21. package/dist/src/browser/actions/modelSelection.js +275 -117
  22. package/dist/src/browser/actions/navigation.js +161 -137
  23. package/dist/src/browser/actions/promptComposer.js +100 -64
  24. package/dist/src/browser/actions/remoteFileTransfer.js +10 -10
  25. package/dist/src/browser/actions/thinkingTime.js +207 -110
  26. package/dist/src/browser/chromeLifecycle.js +62 -60
  27. package/dist/src/browser/config.js +34 -15
  28. package/dist/src/browser/constants.js +17 -12
  29. package/dist/src/browser/cookies.js +19 -19
  30. package/dist/src/browser/detect.js +62 -62
  31. package/dist/src/browser/domDebug.js +1 -1
  32. package/dist/src/browser/index.js +390 -295
  33. package/dist/src/browser/modelStrategy.js +1 -1
  34. package/dist/src/browser/pageActions.js +5 -5
  35. package/dist/src/browser/policies.js +16 -13
  36. package/dist/src/browser/profileState.js +44 -39
  37. package/dist/src/browser/prompt.js +72 -42
  38. package/dist/src/browser/promptSummary.js +5 -5
  39. package/dist/src/browser/providerDomFlow.js +1 -1
  40. package/dist/src/browser/providers/chatgptDomProvider.js +9 -9
  41. package/dist/src/browser/providers/geminiDeepThinkDomProvider.js +51 -42
  42. package/dist/src/browser/providers/index.js +2 -2
  43. package/dist/src/browser/reattach.js +67 -34
  44. package/dist/src/browser/reattachHelpers.js +31 -26
  45. package/dist/src/browser/sessionRunner.js +37 -25
  46. package/dist/src/browser/utils.js +9 -9
  47. package/dist/src/browserMode.js +1 -1
  48. package/dist/src/cli/bridge/claudeConfig.js +16 -16
  49. package/dist/src/cli/bridge/client.js +28 -20
  50. package/dist/src/cli/bridge/codexConfig.js +16 -16
  51. package/dist/src/cli/bridge/doctor.js +47 -39
  52. package/dist/src/cli/bridge/host.js +58 -56
  53. package/dist/src/cli/browserConfig.js +62 -48
  54. package/dist/src/cli/browserDefaults.js +27 -26
  55. package/dist/src/cli/bundleWarnings.js +1 -1
  56. package/dist/src/cli/clipboard.js +11 -2
  57. package/dist/src/cli/detach.js +2 -2
  58. package/dist/src/cli/dryRun.js +29 -25
  59. package/dist/src/cli/duplicatePromptGuard.js +3 -3
  60. package/dist/src/cli/engine.js +9 -9
  61. package/dist/src/cli/errorUtils.js +1 -1
  62. package/dist/src/cli/fileSize.js +3 -3
  63. package/dist/src/cli/format.js +2 -2
  64. package/dist/src/cli/help.js +28 -28
  65. package/dist/src/cli/hiddenAliases.js +3 -3
  66. package/dist/src/cli/markdownBundle.js +7 -7
  67. package/dist/src/cli/markdownRenderer.js +15 -15
  68. package/dist/src/cli/notifier.js +77 -67
  69. package/dist/src/cli/options.js +127 -106
  70. package/dist/src/cli/oscUtils.js +1 -1
  71. package/dist/src/cli/promptRequirement.js +2 -2
  72. package/dist/src/cli/renderOutput.js +1 -1
  73. package/dist/src/cli/rootAlias.js +1 -1
  74. package/dist/src/cli/runOptions.js +32 -28
  75. package/dist/src/cli/sessionCommand.js +31 -21
  76. package/dist/src/cli/sessionDisplay.js +95 -81
  77. package/dist/src/cli/sessionLineage.js +6 -2
  78. package/dist/src/cli/sessionRunner.js +103 -93
  79. package/dist/src/cli/sessionTable.js +26 -23
  80. package/dist/src/cli/stdin.js +22 -0
  81. package/dist/src/cli/tagline.js +121 -124
  82. package/dist/src/cli/tui/index.js +139 -128
  83. package/dist/src/cli/writeOutputPath.js +5 -5
  84. package/dist/src/config.js +7 -7
  85. package/dist/src/gemini-web/browserSessionManager.js +19 -15
  86. package/dist/src/gemini-web/client.js +76 -70
  87. package/dist/src/gemini-web/executionMode.js +6 -8
  88. package/dist/src/gemini-web/executor.js +98 -93
  89. package/dist/src/gemini-web/index.js +1 -1
  90. package/dist/src/mcp/server.js +16 -12
  91. package/dist/src/mcp/tools/consult.js +51 -47
  92. package/dist/src/mcp/tools/sessionResources.js +12 -12
  93. package/dist/src/mcp/tools/sessions.js +26 -17
  94. package/dist/src/mcp/types.js +5 -5
  95. package/dist/src/mcp/utils.js +15 -7
  96. package/dist/src/oracle/background.js +15 -15
  97. package/dist/src/oracle/claude.js +53 -25
  98. package/dist/src/oracle/client.js +50 -41
  99. package/dist/src/oracle/config.js +96 -66
  100. package/dist/src/oracle/errors.js +38 -38
  101. package/dist/src/oracle/files.js +55 -46
  102. package/dist/src/oracle/finishLine.js +10 -8
  103. package/dist/src/oracle/format.js +3 -3
  104. package/dist/src/oracle/gemini.js +37 -33
  105. package/dist/src/oracle/logging.js +7 -7
  106. package/dist/src/oracle/markdown.js +28 -28
  107. package/dist/src/oracle/modelResolver.js +16 -16
  108. package/dist/src/oracle/multiModelRunner.js +12 -12
  109. package/dist/src/oracle/oscProgress.js +8 -8
  110. package/dist/src/oracle/promptAssembly.js +6 -3
  111. package/dist/src/oracle/request.js +16 -13
  112. package/dist/src/oracle/run.js +156 -134
  113. package/dist/src/oracle/runUtils.js +8 -5
  114. package/dist/src/oracle/tokenEstimate.js +6 -6
  115. package/dist/src/oracle/tokenStats.js +5 -5
  116. package/dist/src/oracle/tokenStringifier.js +5 -5
  117. package/dist/src/oracle.js +12 -12
  118. package/dist/src/oracleHome.js +3 -3
  119. package/dist/src/remote/client.js +25 -25
  120. package/dist/src/remote/health.js +20 -20
  121. package/dist/src/remote/remoteServiceConfig.js +9 -9
  122. package/dist/src/remote/server.js +129 -118
  123. package/dist/src/sessionManager.js +77 -75
  124. package/dist/src/sessionStore.js +3 -3
  125. package/dist/src/version.js +10 -10
  126. package/dist/vendor/oracle-notifier/README.md +2 -0
  127. package/package.json +66 -62
  128. package/vendor/oracle-notifier/README.md +2 -0
  129. package/dist/markdansi/types/index.js +0 -4
  130. package/dist/oracle/bin/oracle-cli.js +0 -472
  131. package/dist/oracle/src/browser/actions/assistantResponse.js +0 -471
  132. package/dist/oracle/src/browser/actions/attachments.js +0 -82
  133. package/dist/oracle/src/browser/actions/modelSelection.js +0 -190
  134. package/dist/oracle/src/browser/actions/navigation.js +0 -75
  135. package/dist/oracle/src/browser/actions/promptComposer.js +0 -167
  136. package/dist/oracle/src/browser/chromeLifecycle.js +0 -104
  137. package/dist/oracle/src/browser/config.js +0 -33
  138. package/dist/oracle/src/browser/constants.js +0 -40
  139. package/dist/oracle/src/browser/cookies.js +0 -210
  140. package/dist/oracle/src/browser/domDebug.js +0 -36
  141. package/dist/oracle/src/browser/index.js +0 -331
  142. package/dist/oracle/src/browser/pageActions.js +0 -5
  143. package/dist/oracle/src/browser/prompt.js +0 -88
  144. package/dist/oracle/src/browser/promptSummary.js +0 -20
  145. package/dist/oracle/src/browser/sessionRunner.js +0 -80
  146. package/dist/oracle/src/browser/types.js +0 -1
  147. package/dist/oracle/src/browser/utils.js +0 -62
  148. package/dist/oracle/src/browserMode.js +0 -1
  149. package/dist/oracle/src/cli/browserConfig.js +0 -44
  150. package/dist/oracle/src/cli/dryRun.js +0 -59
  151. package/dist/oracle/src/cli/engine.js +0 -17
  152. package/dist/oracle/src/cli/errorUtils.js +0 -9
  153. package/dist/oracle/src/cli/help.js +0 -70
  154. package/dist/oracle/src/cli/markdownRenderer.js +0 -15
  155. package/dist/oracle/src/cli/options.js +0 -103
  156. package/dist/oracle/src/cli/promptRequirement.js +0 -14
  157. package/dist/oracle/src/cli/rootAlias.js +0 -30
  158. package/dist/oracle/src/cli/sessionCommand.js +0 -77
  159. package/dist/oracle/src/cli/sessionDisplay.js +0 -270
  160. package/dist/oracle/src/cli/sessionRunner.js +0 -94
  161. package/dist/oracle/src/heartbeat.js +0 -43
  162. package/dist/oracle/src/oracle/client.js +0 -48
  163. package/dist/oracle/src/oracle/config.js +0 -29
  164. package/dist/oracle/src/oracle/errors.js +0 -101
  165. package/dist/oracle/src/oracle/files.js +0 -220
  166. package/dist/oracle/src/oracle/format.js +0 -33
  167. package/dist/oracle/src/oracle/fsAdapter.js +0 -7
  168. package/dist/oracle/src/oracle/oscProgress.js +0 -60
  169. package/dist/oracle/src/oracle/request.js +0 -48
  170. package/dist/oracle/src/oracle/run.js +0 -444
  171. package/dist/oracle/src/oracle/tokenStats.js +0 -39
  172. package/dist/oracle/src/oracle/types.js +0 -1
  173. package/dist/oracle/src/oracle.js +0 -9
  174. package/dist/oracle/src/sessionManager.js +0 -205
  175. package/dist/oracle/src/version.js +0 -39
  176. package/dist/scripts/chrome/browser-tools.js +0 -295
  177. package/dist/src/browser/profileSync.js +0 -141
@@ -1,32 +1,32 @@
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';
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
- '__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',
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 = ['__Secure-1PSID', '__Secure-1PSIDTS'];
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 === 'string' ? desiredModel.trim() : '';
42
+ const desired = typeof desiredModel === "string" ? desiredModel.trim() : "";
43
43
  if (!desired)
44
- return 'gemini-3-pro';
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 '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';
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('gemini-') || normalized.includes('gemini')) {
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 'gemini-3-pro';
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('.') ? rawDomain.slice(1) : rawDomain;
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 === 'string');
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 === 'google.com' && (cookie.path ?? '/') === '/';
87
+ return domain === "google.com" && (cookie.path ?? "/") === "/";
88
88
  });
89
- const googleDomain = matches.find((cookie) => (resolveCookieDomain(cookie) ?? '').endsWith('google.com'));
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
- 'https://gemini.google.com',
106
- 'https://accounts.google.com',
107
- 'https://www.google.com',
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: 'Gemini manual-login cookie extraction (no keychain)',
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?.('[gemini-web] Navigating to gemini.google.com for sign-in/cookie capture...');
122
- await Page.navigate({ url: 'https://gemini.google.com' });
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?.('[gemini-web] Waiting for Google sign-in... please sign in in the opened Chrome window.');
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('Timed out waiting for Google sign-in (5 minutes). Please sign in and retry.');
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: 'Gemini Deep Think',
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 || typeof Runtime.enable !== 'function' || typeof Runtime.evaluate !== 'function') {
160
- throw new Error('Chrome Runtime domain unavailable for Gemini Deep Think DOM automation.');
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 !== 'function' || typeof Page.navigate !== 'function') {
163
- throw new Error('Chrome Page domain unavailable for Gemini Deep Think DOM automation.');
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?.('[gemini-web] Navigating to gemini.google.com...');
172
- await Page.navigate({ url: 'https://gemini.google.com/app' });
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 === 'string')));
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 ?? 'inline';
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?.('[gemini-web] Inline cookie payload provided but no Gemini cookies matched.');
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 === 'string' && profileCandidate.trim().length > 0
211
+ const profile = typeof profileCandidate === "string" && profileCandidate.trim().length > 0
210
212
  ? profileCandidate.trim()
211
213
  : undefined;
212
214
  const sources = [
213
- 'https://gemini.google.com',
214
- 'https://accounts.google.com',
215
- 'https://www.google.com',
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: ['chrome'],
222
- mode: 'merge',
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('\n- ')}`);
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 = 'Gemini browser mode requires Chrome cookies for google.com (missing __Secure-1PSID/__Secure-1PSIDTS).';
240
- const guidance = 'Try --browser-manual-login or --browser-inline-cookies-file if local cookie extraction is unavailable.';
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('\n- ')}\n${guidance}`;
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?.('[gemini-web] Using manual-login cookie extraction path (no keychain cookie read).');
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?.('[gemini-web] Cookie sync disabled and inline cookies missing Gemini auth tokens.');
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?.('[gemini-web] Starting Gemini web executor (TypeScript)');
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: 'dom',
300
+ mode: "dom",
299
301
  execute: async () => {
300
- log?.('[gemini-web] Using browser DOM automation for Deep Think.');
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: 'http',
320
+ mode: "http",
319
321
  execute: async () => {
320
322
  const useNoKeychainPath = Boolean(runOptions.config?.manualLogin);
321
- const cookieResult = await loadGeminiCookies(runOptions.config, log, { preferManualNoKeychain: useNoKeychainPath });
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 === 'number' && Number.isFinite(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: 'Here is an image to edit',
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 ?? 'generated.png';
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 || '(empty response)'}`);
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 || '(empty response)'}`);
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 || 'generated.png';
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 === 'gemini-3-pro-deep-think' && modeSelection.mode === 'http') {
433
- log?.(`[gemini-web] Deep Think DOM path skipped (${modeSelection.reasons.join(', ')} requested); using HTTP/header fallback path.`);
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 === 'dom' ? domClient : httpClient;
440
+ const executionClient = modeSelection.mode === "dom" ? domClient : httpClient;
436
441
  return executionClient.execute();
437
442
  };
438
443
  }
@@ -1 +1 @@
1
- export { createGeminiWebExecutor } from './executor.js';
1
+ export { createGeminiWebExecutor } from "./executor.js";
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import 'dotenv/config';
3
- import process from 'node:process';
4
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
- import { getCliVersion } from '../version.js';
7
- import { registerConsultTool } from './tools/consult.js';
8
- import { registerSessionsTool } from './tools/sessions.js';
9
- import { registerSessionResources } from './tools/sessionResources.js';
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: 'oracle-mcp',
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('MCP transport error:', 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
- if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith('oracle-mcp')) {
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('Failed to start oracle-mcp:', error);
41
+ console.error("Failed to start oracle-mcp:", error);
38
42
  process.exitCode = 1;
39
43
  });
40
44
  }