@steipete/oracle 0.7.6 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- 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/actions/thinkingTime.js +5 -0
- package/dist/src/browser/chromeLifecycle.js +9 -1
- package/dist/src/browser/config.js +11 -3
- package/dist/src/browser/constants.js +4 -1
- package/dist/src/browser/cookies.js +55 -21
- package/dist/src/browser/index.js +342 -69
- package/dist/src/browser/modelStrategy.js +13 -0
- package/dist/src/browser/pageActions.js +2 -2
- package/dist/src/browser/profileState.js +16 -0
- package/dist/src/browser/reattach.js +27 -179
- package/dist/src/browser/reattachHelpers.js +382 -0
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/browserConfig.js +12 -5
- package/dist/src/cli/browserDefaults.js +12 -0
- package/dist/src/cli/sessionDisplay.js +7 -0
- package/dist/src/gemini-web/executor.js +107 -46
- package/dist/src/oracle/oscProgress.js +7 -0
- package/dist/src/oracle/run.js +23 -32
- package/dist/src/remote/server.js +30 -15
- package/package.json +8 -17
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.1",
|
|
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"
|