@steipete/oracle 0.7.6 → 0.8.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/README.md +3 -2
- package/dist/bin/oracle-cli.js +4 -0
- package/dist/src/browser/actions/assistantResponse.js +437 -84
- package/dist/src/browser/actions/attachmentDataTransfer.js +138 -0
- package/dist/src/browser/actions/attachments.js +1300 -132
- package/dist/src/browser/actions/modelSelection.js +9 -4
- package/dist/src/browser/actions/navigation.js +160 -5
- package/dist/src/browser/actions/promptComposer.js +54 -11
- package/dist/src/browser/actions/remoteFileTransfer.js +5 -156
- package/dist/src/browser/config.js +9 -3
- package/dist/src/browser/constants.js +4 -1
- package/dist/src/browser/cookies.js +55 -21
- package/dist/src/browser/index.js +321 -65
- package/dist/src/browser/modelStrategy.js +13 -0
- package/dist/src/browser/pageActions.js +2 -2
- package/dist/src/browser/reattach.js +21 -179
- package/dist/src/browser/reattachHelpers.js +382 -0
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/browserConfig.js +10 -4
- package/dist/src/cli/browserDefaults.js +3 -0
- package/dist/src/cli/sessionDisplay.js +7 -0
- package/dist/src/gemini-web/executor.js +107 -46
- package/dist/src/oracle/run.js +23 -32
- package/dist/src/remote/server.js +30 -15
- package/package.json +8 -17
|
@@ -42,4 +42,7 @@ export function applyBrowserDefaultsFromConfig(options, config, getSource) {
|
|
|
42
42
|
if (isUnset('browserKeepBrowser') && browser.keepBrowser !== undefined) {
|
|
43
43
|
options.browserKeepBrowser = browser.keepBrowser;
|
|
44
44
|
}
|
|
45
|
+
if (isUnset('browserModelStrategy') && browser.modelStrategy !== undefined) {
|
|
46
|
+
options.browserModelStrategy = browser.modelStrategy;
|
|
47
|
+
}
|
|
45
48
|
}
|
|
@@ -61,6 +61,13 @@ export async function attachSession(sessionId, options) {
|
|
|
61
61
|
process.exitCode = 1;
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
|
+
if (metadata.mode === 'browser' && metadata.status === 'running' && !metadata.browser?.runtime) {
|
|
65
|
+
await wait(250);
|
|
66
|
+
const refreshed = await sessionStore.readSession(sessionId);
|
|
67
|
+
if (refreshed) {
|
|
68
|
+
metadata = refreshed;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
64
71
|
const normalizedModelFilter = options?.model?.trim().toLowerCase();
|
|
65
72
|
if (normalizedModelFilter) {
|
|
66
73
|
const availableModels = metadata.models?.map((model) => model.model.toLowerCase()) ??
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { getCookies } from '@steipete/sweet-cookie';
|
|
2
3
|
import { runGeminiWebWithFallback, saveFirstGeminiImageFromOutput } from './client.js';
|
|
4
|
+
const GEMINI_COOKIE_NAMES = [
|
|
5
|
+
'__Secure-1PSID',
|
|
6
|
+
'__Secure-1PSIDTS',
|
|
7
|
+
'__Secure-1PSIDCC',
|
|
8
|
+
'__Secure-1PAPISID',
|
|
9
|
+
'NID',
|
|
10
|
+
'AEC',
|
|
11
|
+
'SOCS',
|
|
12
|
+
'__Secure-BUCKET',
|
|
13
|
+
'__Secure-ENID',
|
|
14
|
+
'SID',
|
|
15
|
+
'HSID',
|
|
16
|
+
'SSID',
|
|
17
|
+
'APISID',
|
|
18
|
+
'SAPISID',
|
|
19
|
+
'__Secure-3PSID',
|
|
20
|
+
'__Secure-3PSIDTS',
|
|
21
|
+
'__Secure-3PAPISID',
|
|
22
|
+
'SIDCC',
|
|
23
|
+
];
|
|
24
|
+
const GEMINI_REQUIRED_COOKIES = ['__Secure-1PSID', '__Secure-1PSIDTS'];
|
|
3
25
|
function estimateTokenCount(text) {
|
|
4
26
|
return Math.ceil(text.length / 4);
|
|
5
27
|
}
|
|
@@ -30,59 +52,84 @@ function resolveGeminiWebModel(desiredModel, log) {
|
|
|
30
52
|
return 'gemini-3-pro';
|
|
31
53
|
}
|
|
32
54
|
}
|
|
55
|
+
function resolveCookieDomain(cookie) {
|
|
56
|
+
const rawDomain = cookie.domain?.trim();
|
|
57
|
+
if (rawDomain) {
|
|
58
|
+
return rawDomain.startsWith('.') ? rawDomain.slice(1) : rawDomain;
|
|
59
|
+
}
|
|
60
|
+
const rawUrl = cookie.url?.trim();
|
|
61
|
+
if (rawUrl) {
|
|
62
|
+
try {
|
|
63
|
+
return new URL(rawUrl).hostname;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
function pickCookieValue(cookies, name) {
|
|
72
|
+
const matches = cookies.filter((cookie) => cookie.name === name && typeof cookie.value === 'string');
|
|
73
|
+
if (matches.length === 0)
|
|
74
|
+
return undefined;
|
|
75
|
+
const preferredDomain = matches.find((cookie) => {
|
|
76
|
+
const domain = resolveCookieDomain(cookie);
|
|
77
|
+
return domain === 'google.com' && (cookie.path ?? '/') === '/';
|
|
78
|
+
});
|
|
79
|
+
const googleDomain = matches.find((cookie) => (resolveCookieDomain(cookie) ?? '').endsWith('google.com'));
|
|
80
|
+
return (preferredDomain ?? googleDomain ?? matches[0])?.value;
|
|
81
|
+
}
|
|
82
|
+
function buildGeminiCookieMap(cookies) {
|
|
83
|
+
const cookieMap = {};
|
|
84
|
+
for (const name of GEMINI_COOKIE_NAMES) {
|
|
85
|
+
const value = pickCookieValue(cookies, name);
|
|
86
|
+
if (value)
|
|
87
|
+
cookieMap[name] = value;
|
|
88
|
+
}
|
|
89
|
+
return cookieMap;
|
|
90
|
+
}
|
|
91
|
+
function hasRequiredGeminiCookies(cookieMap) {
|
|
92
|
+
return GEMINI_REQUIRED_COOKIES.every((name) => Boolean(cookieMap[name]));
|
|
93
|
+
}
|
|
94
|
+
async function loadGeminiCookiesFromInline(browserConfig, log) {
|
|
95
|
+
const inline = browserConfig?.inlineCookies;
|
|
96
|
+
if (!inline || inline.length === 0)
|
|
97
|
+
return {};
|
|
98
|
+
const cookieMap = buildGeminiCookieMap(inline.filter((cookie) => Boolean(cookie?.name && typeof cookie.value === 'string')));
|
|
99
|
+
if (Object.keys(cookieMap).length > 0) {
|
|
100
|
+
const source = browserConfig?.inlineCookiesSource ?? 'inline';
|
|
101
|
+
log?.(`[gemini-web] Loaded Gemini cookies from inline payload (${source}): ${Object.keys(cookieMap).length} cookie(s).`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
log?.('[gemini-web] Inline cookie payload provided but no Gemini cookies matched.');
|
|
105
|
+
}
|
|
106
|
+
return cookieMap;
|
|
107
|
+
}
|
|
33
108
|
async function loadGeminiCookiesFromChrome(browserConfig, log) {
|
|
34
109
|
try {
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
browserConfig.chromeProfile.trim().length > 0
|
|
40
|
-
? browserConfig.chromeProfile.trim()
|
|
110
|
+
// Learned: Gemini web relies on Google auth cookies in the *browser* profile, not API keys.
|
|
111
|
+
const profileCandidate = browserConfig?.chromeCookiePath ?? browserConfig?.chromeProfile ?? undefined;
|
|
112
|
+
const profile = typeof profileCandidate === 'string' && profileCandidate.trim().length > 0
|
|
113
|
+
? profileCandidate.trim()
|
|
41
114
|
: undefined;
|
|
42
115
|
const sources = [
|
|
43
116
|
'https://gemini.google.com',
|
|
44
117
|
'https://accounts.google.com',
|
|
45
118
|
'https://www.google.com',
|
|
46
119
|
];
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
'
|
|
58
|
-
'HSID',
|
|
59
|
-
'SSID',
|
|
60
|
-
'APISID',
|
|
61
|
-
'SAPISID',
|
|
62
|
-
'__Secure-3PSID',
|
|
63
|
-
'__Secure-3PSIDTS',
|
|
64
|
-
'__Secure-3PAPISID',
|
|
65
|
-
'SIDCC',
|
|
66
|
-
];
|
|
67
|
-
const cookieMap = {};
|
|
68
|
-
for (const url of sources) {
|
|
69
|
-
const cookies = (await chromeCookies.getCookiesPromised(url, 'puppeteer', profile));
|
|
70
|
-
for (const name of wantNames) {
|
|
71
|
-
if (cookieMap[name])
|
|
72
|
-
continue;
|
|
73
|
-
const matches = cookies.filter((cookie) => cookie.name === name);
|
|
74
|
-
if (matches.length === 0)
|
|
75
|
-
continue;
|
|
76
|
-
const preferredDomain = matches.find((cookie) => cookie.domain === '.google.com' && (cookie.path ?? '/') === '/');
|
|
77
|
-
const googleDomain = matches.find((cookie) => (cookie.domain ?? '').endsWith('google.com'));
|
|
78
|
-
const value = (preferredDomain ?? googleDomain ?? matches[0])?.value;
|
|
79
|
-
if (value)
|
|
80
|
-
cookieMap[name] = value;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (!cookieMap['__Secure-1PSID'] || !cookieMap['__Secure-1PSIDTS']) {
|
|
84
|
-
return {};
|
|
120
|
+
const { cookies, warnings } = await getCookies({
|
|
121
|
+
url: sources[0],
|
|
122
|
+
origins: sources,
|
|
123
|
+
names: [...GEMINI_COOKIE_NAMES],
|
|
124
|
+
browsers: ['chrome'],
|
|
125
|
+
mode: 'merge',
|
|
126
|
+
chromeProfile: profile,
|
|
127
|
+
timeoutMs: 5_000,
|
|
128
|
+
});
|
|
129
|
+
if (warnings.length && log?.verbose) {
|
|
130
|
+
log(`[gemini-web] Cookie warnings:\n- ${warnings.join('\n- ')}`);
|
|
85
131
|
}
|
|
132
|
+
const cookieMap = buildGeminiCookieMap(cookies);
|
|
86
133
|
log?.(`[gemini-web] Loaded Gemini cookies from Chrome (node): ${Object.keys(cookieMap).length} cookie(s).`);
|
|
87
134
|
return cookieMap;
|
|
88
135
|
}
|
|
@@ -91,13 +138,27 @@ async function loadGeminiCookiesFromChrome(browserConfig, log) {
|
|
|
91
138
|
return {};
|
|
92
139
|
}
|
|
93
140
|
}
|
|
141
|
+
async function loadGeminiCookies(browserConfig, log) {
|
|
142
|
+
const inlineMap = await loadGeminiCookiesFromInline(browserConfig, log);
|
|
143
|
+
const hasInlineRequired = hasRequiredGeminiCookies(inlineMap);
|
|
144
|
+
if (hasInlineRequired && browserConfig?.cookieSync === false) {
|
|
145
|
+
return inlineMap;
|
|
146
|
+
}
|
|
147
|
+
if (browserConfig?.cookieSync === false && !hasInlineRequired) {
|
|
148
|
+
log?.('[gemini-web] Cookie sync disabled and inline cookies missing Gemini auth tokens.');
|
|
149
|
+
return inlineMap;
|
|
150
|
+
}
|
|
151
|
+
const chromeMap = await loadGeminiCookiesFromChrome(browserConfig, log);
|
|
152
|
+
const merged = { ...chromeMap, ...inlineMap };
|
|
153
|
+
return merged;
|
|
154
|
+
}
|
|
94
155
|
export function createGeminiWebExecutor(geminiOptions) {
|
|
95
156
|
return async (runOptions) => {
|
|
96
157
|
const startTime = Date.now();
|
|
97
158
|
const log = runOptions.log;
|
|
98
159
|
log?.('[gemini-web] Starting Gemini web executor (TypeScript)');
|
|
99
|
-
const cookieMap = await
|
|
100
|
-
if (!cookieMap
|
|
160
|
+
const cookieMap = await loadGeminiCookies(runOptions.config, log);
|
|
161
|
+
if (!hasRequiredGeminiCookies(cookieMap)) {
|
|
101
162
|
throw new Error('Gemini browser mode requires Chrome cookies for google.com (missing __Secure-1PSID/__Secure-1PSIDTS).');
|
|
102
163
|
}
|
|
103
164
|
const configTimeout = typeof runOptions.config?.timeoutMs === 'number' && Number.isFinite(runOptions.config.timeoutMs)
|
package/dist/src/oracle/run.js
CHANGED
|
@@ -20,7 +20,7 @@ import { createFsAdapter } from './fsAdapter.js';
|
|
|
20
20
|
import { resolveGeminiModelId } from './gemini.js';
|
|
21
21
|
import { resolveClaudeModelId } from './claude.js';
|
|
22
22
|
import { renderMarkdownAnsi } from '../cli/markdownRenderer.js';
|
|
23
|
-
import {
|
|
23
|
+
import { createMarkdownStreamer } from 'markdansi';
|
|
24
24
|
import { executeBackgroundResponse } from './background.js';
|
|
25
25
|
import { formatTokenEstimate, formatTokenValue, resolvePreviewMode } from './runUtils.js';
|
|
26
26
|
import { estimateUsdCost } from 'tokentally';
|
|
@@ -312,8 +312,6 @@ export async function runOracle(options, deps = {}) {
|
|
|
312
312
|
let response = null;
|
|
313
313
|
let elapsedMs = 0;
|
|
314
314
|
let sawTextDelta = false;
|
|
315
|
-
let streamedText = '';
|
|
316
|
-
let lastLiveFrameAtMs = 0;
|
|
317
315
|
let answerHeaderPrinted = false;
|
|
318
316
|
const allowAnswerHeader = options.suppressAnswerHeader !== true;
|
|
319
317
|
const timeoutExceeded = () => now() - runStart >= timeoutMs;
|
|
@@ -381,14 +379,23 @@ export async function runOracle(options, deps = {}) {
|
|
|
381
379
|
},
|
|
382
380
|
});
|
|
383
381
|
}
|
|
384
|
-
let
|
|
382
|
+
let markdownStreamer = null;
|
|
383
|
+
const flushMarkdownStreamer = () => {
|
|
384
|
+
if (!markdownStreamer)
|
|
385
|
+
return;
|
|
386
|
+
const rendered = markdownStreamer.finish();
|
|
387
|
+
markdownStreamer = null;
|
|
388
|
+
if (rendered) {
|
|
389
|
+
stdoutWrite(rendered);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
385
392
|
try {
|
|
386
|
-
|
|
393
|
+
markdownStreamer =
|
|
387
394
|
isTty && !renderPlain
|
|
388
|
-
?
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
395
|
+
? createMarkdownStreamer({
|
|
396
|
+
render: renderMarkdownAnsi,
|
|
397
|
+
spacing: 'single',
|
|
398
|
+
mode: 'hybrid',
|
|
392
399
|
})
|
|
393
400
|
: null;
|
|
394
401
|
for await (const event of stream) {
|
|
@@ -409,38 +416,27 @@ export async function runOracle(options, deps = {}) {
|
|
|
409
416
|
stdoutWrite(event.delta);
|
|
410
417
|
continue;
|
|
411
418
|
}
|
|
412
|
-
if (
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const hasNewline = event.delta.includes('\n');
|
|
417
|
-
if (hasNewline || due) {
|
|
418
|
-
liveRenderer.render(streamedText);
|
|
419
|
-
lastLiveFrameAtMs = currentMs;
|
|
419
|
+
if (markdownStreamer) {
|
|
420
|
+
const rendered = markdownStreamer.push(event.delta);
|
|
421
|
+
if (rendered) {
|
|
422
|
+
stdoutWrite(rendered);
|
|
420
423
|
}
|
|
421
424
|
continue;
|
|
422
425
|
}
|
|
423
426
|
// Non-TTY streams should still surface output; fall back to raw stdout.
|
|
424
427
|
stdoutWrite(event.delta);
|
|
425
428
|
}
|
|
426
|
-
|
|
427
|
-
streamedText = streamedText.trim();
|
|
428
|
-
if (streamedText.length > 0) {
|
|
429
|
-
liveRenderer.render(streamedText);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
429
|
+
flushMarkdownStreamer();
|
|
432
430
|
throwIfTimedOut();
|
|
433
431
|
}
|
|
434
432
|
catch (streamError) {
|
|
435
433
|
// stream.abort() is not available on the interface
|
|
434
|
+
flushMarkdownStreamer();
|
|
436
435
|
stopHeartbeatNow();
|
|
437
436
|
const transportError = toTransportError(streamError, requestBody.model);
|
|
438
437
|
log(chalk.yellow(describeTransportError(transportError, timeoutMs)));
|
|
439
438
|
throw transportError;
|
|
440
439
|
}
|
|
441
|
-
finally {
|
|
442
|
-
liveRenderer?.finish();
|
|
443
|
-
}
|
|
444
440
|
response = await stream.finalResponse();
|
|
445
441
|
throwIfTimedOut();
|
|
446
442
|
stopHeartbeatNow();
|
|
@@ -455,17 +451,12 @@ export async function runOracle(options, deps = {}) {
|
|
|
455
451
|
}
|
|
456
452
|
// We only add spacing when streamed text was printed.
|
|
457
453
|
if (sawTextDelta && !options.silent) {
|
|
458
|
-
const shouldRenderAfterStream = isTty && !renderPlain && streamedText.length > 0;
|
|
459
454
|
if (renderPlain) {
|
|
460
455
|
// Plain streaming already wrote chunks; ensure clean separation.
|
|
461
456
|
stdoutWrite('\n');
|
|
462
457
|
}
|
|
463
|
-
else if (!shouldRenderAfterStream) {
|
|
464
|
-
// Non-TTY streams should still surface output; ensure separation.
|
|
465
|
-
log('');
|
|
466
|
-
}
|
|
467
458
|
else {
|
|
468
|
-
//
|
|
459
|
+
// Separate streamed output from logs.
|
|
469
460
|
log('');
|
|
470
461
|
}
|
|
471
462
|
}
|
|
@@ -7,7 +7,7 @@ import { spawn, spawnSync } from 'node:child_process';
|
|
|
7
7
|
import { mkdtemp, rm, mkdir, writeFile } from 'node:fs/promises';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import { runBrowserMode } from '../browserMode.js';
|
|
10
|
-
import {
|
|
10
|
+
import { getCookies } from '@steipete/sweet-cookie';
|
|
11
11
|
import { CHATGPT_URL } from '../browser/constants.js';
|
|
12
12
|
import { cleanupStaleProfileState, readDevToolsPort, verifyDevToolsReachable, writeChromePid, writeDevToolsActivePort, } from '../browser/profileState.js';
|
|
13
13
|
import { normalizeChatgptUrl } from '../browser/utils.js';
|
|
@@ -331,13 +331,17 @@ function formatReachableAddresses(bindAddress, port) {
|
|
|
331
331
|
async function loadLocalChatgptCookies(logger, targetUrl) {
|
|
332
332
|
try {
|
|
333
333
|
logger('Loading ChatGPT cookies from this host\'s Chrome profile...');
|
|
334
|
-
const cookies = await
|
|
335
|
-
targetUrl,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
334
|
+
const { cookies: rawCookies, warnings } = await getCookies({
|
|
335
|
+
url: targetUrl,
|
|
336
|
+
browsers: ['chrome'],
|
|
337
|
+
mode: 'merge',
|
|
338
|
+
chromeProfile: 'Default',
|
|
339
|
+
timeoutMs: 5_000,
|
|
340
340
|
});
|
|
341
|
+
if (warnings.length) {
|
|
342
|
+
logger(`Cookie warnings:\n- ${warnings.join('\n- ')}`);
|
|
343
|
+
}
|
|
344
|
+
const cookies = rawCookies.map(toCdpCookie).filter((c) => Boolean(c));
|
|
341
345
|
if (!cookies || cookies.length === 0) {
|
|
342
346
|
logger('No local ChatGPT cookies found on this host. Please log in once; opening ChatGPT...');
|
|
343
347
|
const opened = triggerLocalLoginPrompt(logger, targetUrl);
|
|
@@ -348,14 +352,7 @@ async function loadLocalChatgptCookies(logger, targetUrl) {
|
|
|
348
352
|
}
|
|
349
353
|
catch (error) {
|
|
350
354
|
const message = error instanceof Error ? error.message : String(error);
|
|
351
|
-
|
|
352
|
-
if (missingDbMatch) {
|
|
353
|
-
const lookedPath = missingDbMatch[1];
|
|
354
|
-
logger(`Chrome cookies not found at ${lookedPath}. Set --browser-cookie-path to your Chrome profile or log in manually.`);
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
logger(`Unable to load local ChatGPT cookies on this host: ${message}`);
|
|
358
|
-
}
|
|
355
|
+
logger(`Unable to load local ChatGPT cookies on this host: ${message}`);
|
|
359
356
|
if (process.platform === 'linux' && isWsl()) {
|
|
360
357
|
logger('WSL hint: Chrome lives under /mnt/c/Users/<you>/AppData/Local/Google/Chrome/User Data/Default; pass --browser-cookie-path to that directory if auto-detect fails.');
|
|
361
358
|
}
|
|
@@ -363,6 +360,24 @@ async function loadLocalChatgptCookies(logger, targetUrl) {
|
|
|
363
360
|
return { cookies: null, opened };
|
|
364
361
|
}
|
|
365
362
|
}
|
|
363
|
+
function toCdpCookie(cookie) {
|
|
364
|
+
if (!cookie?.name)
|
|
365
|
+
return null;
|
|
366
|
+
const out = {
|
|
367
|
+
name: cookie.name,
|
|
368
|
+
value: cookie.value,
|
|
369
|
+
domain: cookie.domain,
|
|
370
|
+
path: cookie.path ?? '/',
|
|
371
|
+
secure: cookie.secure ?? true,
|
|
372
|
+
httpOnly: cookie.httpOnly ?? false,
|
|
373
|
+
};
|
|
374
|
+
if (typeof cookie.expires === 'number')
|
|
375
|
+
out.expires = cookie.expires;
|
|
376
|
+
if (cookie.sameSite === 'Lax' || cookie.sameSite === 'Strict' || cookie.sameSite === 'None') {
|
|
377
|
+
out.sameSite = cookie.sameSite;
|
|
378
|
+
}
|
|
379
|
+
return out;
|
|
380
|
+
}
|
|
366
381
|
function triggerLocalLoginPrompt(logger, url) {
|
|
367
382
|
const verbose = process.argv.includes('--verbose') || process.env.ORACLE_SERVE_VERBOSE === '1';
|
|
368
383
|
const openers = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steipete/oracle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "CLI wrapper around OpenAI Responses API with GPT-5.2 Pro (via gpt-5.1-pro alias), GPT-5.2, GPT-5.1, and GPT-5.1 Codex high reasoning modes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/bin/oracle-cli.js",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"url": "git+https://github.com/steipete/oracle.git"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
|
-
"node": ">=
|
|
45
|
+
"node": ">=22"
|
|
46
46
|
},
|
|
47
47
|
"devEngines": {
|
|
48
48
|
"runtime": [
|
|
49
49
|
{
|
|
50
50
|
"name": "node",
|
|
51
|
-
"version": ">=
|
|
51
|
+
"version": ">=22"
|
|
52
52
|
}
|
|
53
53
|
]
|
|
54
54
|
},
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"@google/genai": "^1.34.0",
|
|
65
65
|
"@google/generative-ai": "^0.24.1",
|
|
66
66
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
67
|
+
"@steipete/sweet-cookie": "^0.1.0",
|
|
67
68
|
"chalk": "^5.6.2",
|
|
68
|
-
"chrome-cookies-secure": "3.0.0",
|
|
69
69
|
"chrome-launcher": "^1.2.1",
|
|
70
70
|
"chrome-remote-interface": "^0.33.3",
|
|
71
71
|
"clipboardy": "^5.0.2",
|
|
@@ -75,13 +75,11 @@
|
|
|
75
75
|
"gpt-tokenizer": "^3.4.0",
|
|
76
76
|
"inquirer": "13.1.0",
|
|
77
77
|
"json5": "^2.2.3",
|
|
78
|
-
"keytar": "^7.9.0",
|
|
79
78
|
"kleur": "^4.1.5",
|
|
80
|
-
"markdansi": "0.
|
|
79
|
+
"markdansi": "0.2.0",
|
|
81
80
|
"openai": "^6.15.0",
|
|
82
|
-
"osc-progress": "^0.
|
|
81
|
+
"osc-progress": "^0.2.0",
|
|
83
82
|
"shiki": "^3.20.0",
|
|
84
|
-
"sqlite3": "^5.1.7",
|
|
85
83
|
"toasted-notifier": "^10.1.0",
|
|
86
84
|
"tokentally": "^0.1.1",
|
|
87
85
|
"zod": "^4.2.1"
|
|
@@ -102,20 +100,13 @@
|
|
|
102
100
|
"typescript": "^5.9.3",
|
|
103
101
|
"vitest": "^4.0.16"
|
|
104
102
|
},
|
|
105
|
-
"optionalDependencies": {
|
|
106
|
-
"win-dpapi": "npm:@primno/dpapi@2.0.1"
|
|
107
|
-
},
|
|
108
103
|
"pnpm": {
|
|
109
104
|
"overrides": {
|
|
110
|
-
"devtools-protocol": "0.0.1561482"
|
|
111
|
-
"win-dpapi": "npm:@primno/dpapi@2.0.1"
|
|
105
|
+
"devtools-protocol": "0.0.1561482"
|
|
112
106
|
},
|
|
113
107
|
"onlyBuiltDependencies": [
|
|
114
108
|
"@cdktf/node-pty-prebuilt-multiarch",
|
|
115
|
-
"esbuild"
|
|
116
|
-
"keytar",
|
|
117
|
-
"sqlite3",
|
|
118
|
-
"win-dpapi"
|
|
109
|
+
"esbuild"
|
|
119
110
|
]
|
|
120
111
|
},
|
|
121
112
|
"packageManager": "pnpm@10.23.0+sha512.21c4e5698002ade97e4efe8b8b4a89a8de3c85a37919f957e7a0f30f38fbc5bbdd05980ffe29179b2fb6e6e691242e098d945d1601772cad0fef5fb6411e2a4b"
|