@steipete/oracle 0.4.5 → 0.5.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 +11 -9
- package/dist/bin/oracle-cli.js +16 -48
- package/dist/scripts/agent-send.js +147 -0
- package/dist/scripts/docs-list.js +110 -0
- package/dist/scripts/git-policy.js +125 -0
- package/dist/scripts/runner.js +1378 -0
- package/dist/scripts/test-browser.js +103 -0
- package/dist/scripts/test-remote-chrome.js +68 -0
- package/dist/src/browser/actions/attachments.js +47 -16
- package/dist/src/browser/actions/promptComposer.js +29 -18
- package/dist/src/browser/actions/remoteFileTransfer.js +36 -4
- package/dist/src/browser/chromeCookies.js +37 -6
- package/dist/src/browser/chromeLifecycle.js +166 -25
- package/dist/src/browser/config.js +25 -1
- package/dist/src/browser/constants.js +22 -3
- package/dist/src/browser/index.js +301 -21
- package/dist/src/browser/prompt.js +3 -1
- package/dist/src/browser/reattach.js +59 -0
- package/dist/src/browser/sessionRunner.js +15 -1
- package/dist/src/browser/windowsCookies.js +2 -1
- package/dist/src/cli/browserConfig.js +11 -0
- package/dist/src/cli/browserDefaults.js +41 -0
- package/dist/src/cli/detach.js +2 -2
- package/dist/src/cli/dryRun.js +4 -2
- package/dist/src/cli/engine.js +2 -2
- package/dist/src/cli/help.js +2 -2
- package/dist/src/cli/options.js +2 -1
- package/dist/src/cli/runOptions.js +1 -1
- package/dist/src/cli/sessionDisplay.js +98 -5
- package/dist/src/cli/sessionRunner.js +39 -6
- package/dist/src/cli/tui/index.js +15 -18
- package/dist/src/heartbeat.js +2 -2
- package/dist/src/oracle/background.js +10 -2
- package/dist/src/oracle/client.js +17 -0
- package/dist/src/oracle/config.js +10 -2
- package/dist/src/oracle/errors.js +24 -4
- package/dist/src/oracle/modelResolver.js +144 -0
- package/dist/src/oracle/oscProgress.js +1 -1
- package/dist/src/oracle/run.js +82 -34
- package/dist/src/oracle/runUtils.js +12 -8
- package/dist/src/remote/server.js +214 -23
- package/dist/src/sessionManager.js +5 -2
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/package.json +14 -14
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import net from 'node:net';
|
|
4
5
|
import { randomBytes, randomUUID } from 'node:crypto';
|
|
6
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
5
8
|
import { mkdtemp, rm, mkdir, writeFile } from 'node:fs/promises';
|
|
6
9
|
import chalk from 'chalk';
|
|
7
10
|
import { runBrowserMode } from '../browserMode.js';
|
|
8
11
|
import { loadChromeCookies } from '../browser/chromeCookies.js';
|
|
9
12
|
import { CHATGPT_URL } from '../browser/constants.js';
|
|
10
13
|
import { normalizeChatgptUrl } from '../browser/utils.js';
|
|
14
|
+
async function findAvailablePort() {
|
|
15
|
+
return await new Promise((resolve, reject) => {
|
|
16
|
+
const srv = net.createServer();
|
|
17
|
+
srv.on('error', (err) => reject(err));
|
|
18
|
+
srv.listen(0, () => {
|
|
19
|
+
const address = srv.address();
|
|
20
|
+
if (typeof address === 'object' && address?.port) {
|
|
21
|
+
const port = address.port;
|
|
22
|
+
srv.close(() => resolve(port));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
srv.close(() => reject(new Error('Unable to allocate port')));
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
11
30
|
export async function createRemoteServer(options = {}, deps = {}) {
|
|
12
31
|
const runBrowser = deps.runBrowser ?? runBrowserMode;
|
|
13
32
|
const server = http.createServer();
|
|
@@ -45,7 +64,6 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
45
64
|
res.end(JSON.stringify({ error: 'unauthorized' }));
|
|
46
65
|
return;
|
|
47
66
|
}
|
|
48
|
-
// biome-ignore lint/nursery/noUnnecessaryConditions: busy guard protects single-run host
|
|
49
67
|
if (busy) {
|
|
50
68
|
if (verbose) {
|
|
51
69
|
logger(`[serve] Busy: rejecting new run from ${formatSocket(req)} while another run is active`);
|
|
@@ -106,6 +124,18 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
106
124
|
payload.browserConfig.inlineCookiesSource = null;
|
|
107
125
|
payload.browserConfig.cookieSync = true;
|
|
108
126
|
}
|
|
127
|
+
else {
|
|
128
|
+
payload.browserConfig = {};
|
|
129
|
+
}
|
|
130
|
+
// Enforce manual-login profile when cookie sync is unavailable (e.g., Windows/WSL).
|
|
131
|
+
if (options.manualLoginDefault) {
|
|
132
|
+
payload.browserConfig.manualLogin = true;
|
|
133
|
+
payload.browserConfig.manualLoginProfileDir = options.manualLoginProfileDir;
|
|
134
|
+
payload.browserConfig.keepBrowser = true;
|
|
135
|
+
if (verbose) {
|
|
136
|
+
logger(`[serve] Enforcing manual-login profile at ${options.manualLoginProfileDir ?? 'default'} for remote run ${runId}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
109
139
|
const result = await runBrowser({
|
|
110
140
|
prompt: payload.prompt,
|
|
111
141
|
attachments,
|
|
@@ -146,6 +176,7 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
146
176
|
const also = extras.length ? `, also [${extras.join(', ')}]` : '';
|
|
147
177
|
logger(color(chalk.cyanBright.bold, `Listening at ${primary}${also}`));
|
|
148
178
|
logger(color(chalk.yellowBright, `Access token: ${authToken}`));
|
|
179
|
+
logger('Leave this terminal running; press Ctrl+C to stop oracle serve.');
|
|
149
180
|
return {
|
|
150
181
|
port: address.port,
|
|
151
182
|
token: authToken,
|
|
@@ -157,15 +188,54 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
157
188
|
};
|
|
158
189
|
}
|
|
159
190
|
export async function serveRemote(options = {}) {
|
|
160
|
-
|
|
161
|
-
const
|
|
191
|
+
const manualProfileDir = options.manualLoginProfileDir ?? path.join(os.homedir(), '.oracle', 'browser-profile');
|
|
192
|
+
const preferManualLogin = options.manualLoginDefault || process.platform === 'win32' || isWsl();
|
|
193
|
+
let cookies = null;
|
|
194
|
+
let opened = false;
|
|
195
|
+
if (isWsl() && process.env.ORACLE_ALLOW_WSL_SERVE !== '1') {
|
|
196
|
+
console.log('WSL detected. For reliable browser automation, run `oracle serve` from Windows PowerShell/Command Prompt so we can use your Windows Chrome profile.');
|
|
197
|
+
console.log('If you want to stay in WSL anyway, set ORACLE_ALLOW_WSL_SERVE=1 and ensure a Linux Chrome is installed, then rerun.');
|
|
198
|
+
console.log('Alternatively, start Windows Chrome with --remote-debugging-port=9222 and use `--remote-chrome <windows-ip>:9222`.');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (!preferManualLogin) {
|
|
202
|
+
// Warm-up: ensure this host has a ChatGPT login before accepting runs.
|
|
203
|
+
const result = await loadLocalChatgptCookies(console.log, CHATGPT_URL);
|
|
204
|
+
cookies = result.cookies;
|
|
205
|
+
opened = result.opened;
|
|
206
|
+
}
|
|
162
207
|
if (!cookies || cookies.length === 0) {
|
|
163
208
|
console.log('No ChatGPT cookies detected on this host.');
|
|
164
|
-
|
|
165
|
-
|
|
209
|
+
if (preferManualLogin) {
|
|
210
|
+
await mkdir(manualProfileDir, { recursive: true });
|
|
211
|
+
console.log(`Cookie extraction is unavailable on this platform. Using manual-login Chrome profile at ${manualProfileDir}. Remote runs will reuse this profile; sign in once when the browser opens.`);
|
|
212
|
+
const devtoolsPortFile = path.join(manualProfileDir, 'DevToolsActivePort');
|
|
213
|
+
const alreadyRunning = existsSync(devtoolsPortFile);
|
|
214
|
+
if (alreadyRunning) {
|
|
215
|
+
console.log('Detected an existing automation Chrome session; will reuse it for manual login.');
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
void launchManualLoginChrome(manualProfileDir, CHATGPT_URL, console.log);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (opened) {
|
|
222
|
+
console.log('Opened chatgpt.com for login. Sign in, then restart `oracle serve` to continue.');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
console.log('Please open https://chatgpt.com/ in this host\'s browser and sign in; then rerun.');
|
|
227
|
+
console.log('Tip: install xdg-utils (xdg-open) to enable automatic browser opening on Linux/WSL.');
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
console.log(`Detected ${cookies.length} ChatGPT cookies on this host; runs will reuse this session.`);
|
|
166
233
|
}
|
|
167
|
-
|
|
168
|
-
|
|
234
|
+
const server = await createRemoteServer({
|
|
235
|
+
...options,
|
|
236
|
+
manualLoginDefault: preferManualLogin,
|
|
237
|
+
manualLoginProfileDir: manualProfileDir,
|
|
238
|
+
});
|
|
169
239
|
await new Promise((resolve) => {
|
|
170
240
|
const shutdown = () => {
|
|
171
241
|
console.log('Shutting down remote service...');
|
|
@@ -263,32 +333,153 @@ async function loadLocalChatgptCookies(logger, targetUrl) {
|
|
|
263
333
|
});
|
|
264
334
|
if (!cookies || cookies.length === 0) {
|
|
265
335
|
logger('No local ChatGPT cookies found on this host. Please log in once; opening ChatGPT...');
|
|
266
|
-
triggerLocalLoginPrompt(logger, targetUrl);
|
|
267
|
-
return null;
|
|
336
|
+
const opened = triggerLocalLoginPrompt(logger, targetUrl);
|
|
337
|
+
return { cookies: null, opened };
|
|
268
338
|
}
|
|
269
339
|
logger(`Loaded ${cookies.length} local ChatGPT cookies on this host.`);
|
|
270
|
-
return cookies;
|
|
340
|
+
return { cookies, opened: false };
|
|
271
341
|
}
|
|
272
342
|
catch (error) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
343
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
344
|
+
const missingDbMatch = message.match(/Unable to locate Chrome cookie DB at (.+)/);
|
|
345
|
+
if (missingDbMatch) {
|
|
346
|
+
const lookedPath = missingDbMatch[1];
|
|
347
|
+
logger(`Chrome cookies not found at ${lookedPath}. Set --browser-cookie-path to your Chrome profile or log in manually.`);
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
logger(`Unable to load local ChatGPT cookies on this host: ${message}`);
|
|
351
|
+
}
|
|
352
|
+
if (process.platform === 'linux' && isWsl()) {
|
|
353
|
+
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.');
|
|
354
|
+
}
|
|
355
|
+
const opened = triggerLocalLoginPrompt(logger, targetUrl);
|
|
356
|
+
return { cookies: null, opened };
|
|
276
357
|
}
|
|
277
358
|
}
|
|
278
359
|
function triggerLocalLoginPrompt(logger, url) {
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
360
|
+
const verbose = process.argv.includes('--verbose') || process.env.ORACLE_SERVE_VERBOSE === '1';
|
|
361
|
+
const openers = [];
|
|
362
|
+
if (process.platform === 'darwin') {
|
|
363
|
+
openers.push({ cmd: 'open' });
|
|
364
|
+
}
|
|
365
|
+
else if (process.platform === 'win32') {
|
|
366
|
+
openers.push({ cmd: 'start' });
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
if (isWsl()) {
|
|
370
|
+
// Prefer wslview when available, then fall back to Windows start.exe to open in the host browser.
|
|
371
|
+
openers.push({ cmd: 'wslview' });
|
|
372
|
+
openers.push({ cmd: 'cmd.exe', args: ['/c', 'start', '', url] });
|
|
373
|
+
}
|
|
374
|
+
openers.push({ cmd: 'xdg-open' });
|
|
375
|
+
}
|
|
376
|
+
// Add a cross-platform, low-friction fallback when nothing above is available.
|
|
377
|
+
openers.push({ cmd: 'sensible-browser' });
|
|
284
378
|
try {
|
|
285
379
|
// Fire and forget; user completes login in the opened browser window.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
380
|
+
if (verbose) {
|
|
381
|
+
logger(`[serve] Login opener candidates: ${openers.map((o) => o.cmd).join(', ')}`);
|
|
382
|
+
}
|
|
383
|
+
const candidate = openers.find((opener) => canSpawn(opener.cmd));
|
|
384
|
+
if (candidate) {
|
|
385
|
+
const child = spawn(candidate.cmd, candidate.args ?? [url], { stdio: 'ignore', detached: true });
|
|
386
|
+
child.unref();
|
|
387
|
+
child.once('error', (error) => {
|
|
388
|
+
if (verbose) {
|
|
389
|
+
logger(`[serve] Opener ${candidate.cmd} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
390
|
+
}
|
|
391
|
+
logger(`Please open ${url} in this host's browser and sign in; then rerun.`);
|
|
392
|
+
});
|
|
393
|
+
logger(`Opened ${url} locally via ${candidate.cmd}. Please sign in; subsequent runs will reuse the session.`);
|
|
394
|
+
if (verbose && candidate.args) {
|
|
395
|
+
logger(`[serve] Opener args: ${candidate.args.join(' ')}`);
|
|
396
|
+
}
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
if (verbose) {
|
|
400
|
+
logger('[serve] No available opener found; prompting manual login.');
|
|
401
|
+
}
|
|
402
|
+
return false;
|
|
290
403
|
}
|
|
291
404
|
catch {
|
|
292
|
-
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function isWsl() {
|
|
409
|
+
if (process.platform !== 'linux')
|
|
410
|
+
return false;
|
|
411
|
+
return Boolean(process.env.WSL_DISTRO_NAME || os.release().toLowerCase().includes('microsoft'));
|
|
412
|
+
}
|
|
413
|
+
function canSpawn(cmd) {
|
|
414
|
+
if (!cmd)
|
|
415
|
+
return false;
|
|
416
|
+
try {
|
|
417
|
+
if (process.platform === 'win32') {
|
|
418
|
+
// `where` returns non-zero when the command is not found.
|
|
419
|
+
const result = spawnSync('where', [cmd], { stdio: 'ignore' });
|
|
420
|
+
return result.status === 0;
|
|
421
|
+
}
|
|
422
|
+
// `command -v` is a shell builtin; run through sh. Fallback to `which`.
|
|
423
|
+
const shResult = spawnSync('sh', ['-c', `command -v ${cmd}`], { stdio: 'ignore' });
|
|
424
|
+
if (shResult.status === 0)
|
|
425
|
+
return true;
|
|
426
|
+
const whichResult = spawnSync('which', [cmd], { stdio: 'ignore' });
|
|
427
|
+
return whichResult.status === 0;
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
async function launchManualLoginChrome(profileDir, url, logger) {
|
|
434
|
+
const timeoutMs = 7000;
|
|
435
|
+
let finished = false;
|
|
436
|
+
const timeout = setTimeout(() => {
|
|
437
|
+
if (!finished) {
|
|
438
|
+
logger(`Timed out launching Chrome for manual login. Launch Chrome manually with --user-data-dir=${profileDir} and log in to ${url}.`);
|
|
439
|
+
}
|
|
440
|
+
}, timeoutMs);
|
|
441
|
+
try {
|
|
442
|
+
const chromeLauncher = await import('chrome-launcher');
|
|
443
|
+
const { launch } = chromeLauncher;
|
|
444
|
+
const debugPort = await findAvailablePort();
|
|
445
|
+
logger(`Planned manual-login Chrome DevTools port: ${debugPort}`);
|
|
446
|
+
const chrome = await launch({
|
|
447
|
+
// Expose DevTools so later runs can attach instead of spawning a second Chrome.
|
|
448
|
+
// Use a per-serve free port so the login window stays stable for all runs.
|
|
449
|
+
port: debugPort,
|
|
450
|
+
userDataDir: profileDir,
|
|
451
|
+
startingUrl: url,
|
|
452
|
+
chromeFlags: [
|
|
453
|
+
'--no-first-run',
|
|
454
|
+
'--no-default-browser-check',
|
|
455
|
+
`--user-data-dir=${profileDir}`,
|
|
456
|
+
'--remote-allow-origins=*',
|
|
457
|
+
`--remote-debugging-port=${debugPort}`, // ensure DevToolsActivePort is written even on Windows
|
|
458
|
+
],
|
|
459
|
+
});
|
|
460
|
+
const chosenPort = chrome?.port ?? debugPort ?? null;
|
|
461
|
+
if (chosenPort) {
|
|
462
|
+
// Write DevToolsActivePort eagerly so maybeReuseRunningChrome can attach on the next run
|
|
463
|
+
const devtoolsFile = path.join(profileDir, 'DevToolsActivePort');
|
|
464
|
+
const devtoolsFileDefault = path.join(profileDir, 'Default', 'DevToolsActivePort');
|
|
465
|
+
const contents = `${chosenPort}\n/devtools/browser`;
|
|
466
|
+
await writeFile(devtoolsFile, contents).catch(() => undefined);
|
|
467
|
+
await writeFile(devtoolsFileDefault, contents).catch(() => undefined);
|
|
468
|
+
logger(`Manual-login Chrome DevTools port: ${chosenPort}`);
|
|
469
|
+
logger(`If needed, DevTools JSON at http://127.0.0.1:${chosenPort}/json/version`);
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
logger('Warning: unable to determine manual-login Chrome DevTools port. Remote runs may fail to attach.');
|
|
473
|
+
}
|
|
474
|
+
finished = true;
|
|
475
|
+
clearTimeout(timeout);
|
|
476
|
+
const portInfo = chosenPort ? ` (DevTools port ${chosenPort})` : '';
|
|
477
|
+
logger(`Opened Chrome with manual-login profile at ${profileDir}${portInfo}. Complete login, then rerun remote sessions.`);
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
finished = true;
|
|
481
|
+
clearTimeout(timeout);
|
|
482
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
483
|
+
logger(`Unable to open Chrome for manual login (${message}). Launch Chrome manually with --user-data-dir=${profileDir} and log in to ${url}.`);
|
|
293
484
|
}
|
|
294
485
|
}
|
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import { createWriteStream } from 'node:fs';
|
|
5
5
|
import { DEFAULT_MODEL } from './oracle.js';
|
|
6
|
+
import { safeModelSlug } from './oracle/modelResolver.js';
|
|
6
7
|
const ORACLE_HOME = process.env.ORACLE_HOME_DIR ?? path.join(os.homedir(), '.oracle');
|
|
7
8
|
const SESSIONS_DIR = path.join(ORACLE_HOME, 'sessions');
|
|
8
9
|
const METADATA_FILENAME = 'meta.json';
|
|
@@ -67,10 +68,12 @@ function modelsDir(id) {
|
|
|
67
68
|
return path.join(sessionDir(id), MODELS_DIRNAME);
|
|
68
69
|
}
|
|
69
70
|
function modelJsonPath(id, model) {
|
|
70
|
-
|
|
71
|
+
const slug = safeModelSlug(model);
|
|
72
|
+
return path.join(modelsDir(id), `${slug}${MODEL_JSON_EXTENSION}`);
|
|
71
73
|
}
|
|
72
74
|
function modelLogPath(id, model) {
|
|
73
|
-
|
|
75
|
+
const slug = safeModelSlug(model);
|
|
76
|
+
return path.join(modelsDir(id), `${slug}${MODEL_LOG_EXTENSION}`);
|
|
74
77
|
}
|
|
75
78
|
async function fileExists(targetPath) {
|
|
76
79
|
try {
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steipete/oracle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "CLI wrapper around OpenAI Responses API with GPT-5.1 Pro, GPT-5.1, and GPT-5.1 Codex high reasoning modes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/bin/oracle-cli.js",
|
|
@@ -52,46 +52,46 @@
|
|
|
52
52
|
"chrome-cookies-secure": "3.0.0",
|
|
53
53
|
"chrome-launcher": "^1.2.1",
|
|
54
54
|
"chrome-remote-interface": "^0.33.3",
|
|
55
|
-
"clipboardy": "^
|
|
55
|
+
"clipboardy": "^5.0.1",
|
|
56
56
|
"commander": "^14.0.2",
|
|
57
57
|
"dotenv": "^17.2.3",
|
|
58
58
|
"fast-glob": "^3.3.3",
|
|
59
59
|
"gpt-tokenizer": "^3.4.0",
|
|
60
|
-
"inquirer": "
|
|
60
|
+
"inquirer": "9.3.8",
|
|
61
61
|
"json5": "^2.2.3",
|
|
62
62
|
"keytar": "^7.9.0",
|
|
63
63
|
"kleur": "^4.1.5",
|
|
64
64
|
"markdansi": "^0.1.3",
|
|
65
|
-
"openai": "^6.9.
|
|
65
|
+
"openai": "^6.9.1",
|
|
66
66
|
"shiki": "^3.15.0",
|
|
67
67
|
"sqlite3": "^5.1.7",
|
|
68
68
|
"toasted-notifier": "^10.1.0",
|
|
69
|
-
"zod": "
|
|
69
|
+
"zod": "3.24.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
73
|
-
"@biomejs/biome": "^2.3.
|
|
73
|
+
"@biomejs/biome": "^2.3.7",
|
|
74
74
|
"@cdktf/node-pty-prebuilt-multiarch": "0.10.2",
|
|
75
75
|
"@types/chrome-remote-interface": "^0.31.14",
|
|
76
76
|
"@types/inquirer": "^9.0.9",
|
|
77
|
-
"@types/json5": "^
|
|
77
|
+
"@types/json5": "^2.2.0",
|
|
78
78
|
"@types/node": "^24.10.1",
|
|
79
|
-
"@vitest/coverage-v8": "4.0.
|
|
80
|
-
"devtools-protocol": "^0.0.
|
|
79
|
+
"@vitest/coverage-v8": "4.0.13",
|
|
80
|
+
"devtools-protocol": "^0.0.1548823",
|
|
81
81
|
"es-toolkit": "^1.42.0",
|
|
82
82
|
"esbuild": "^0.27.0",
|
|
83
|
-
"puppeteer-core": "^24.
|
|
83
|
+
"puppeteer-core": "^24.31.0",
|
|
84
84
|
"tsx": "^4.20.6",
|
|
85
85
|
"typescript": "^5.9.3",
|
|
86
|
-
"vitest": "^4.0.
|
|
86
|
+
"vitest": "^4.0.13"
|
|
87
87
|
},
|
|
88
88
|
"optionalDependencies": {
|
|
89
|
-
"win-dpapi": "
|
|
89
|
+
"win-dpapi": "npm:@primno/dpapi@2.0.1"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"docs:list": "tsx scripts/docs-list.ts",
|
|
93
93
|
"build": "tsc -p tsconfig.build.json && pnpm run build:vendor",
|
|
94
|
-
"build:vendor": "
|
|
94
|
+
"build:vendor": "node -e \"const fs=require('fs'); const path=require('path'); const src=path.join('vendor','oracle-notifier'); const dest=path.join('dist','vendor','oracle-notifier'); fs.mkdirSync(dest,{recursive:true}); if(fs.existsSync(src)){ fs.cpSync(src,dest,{recursive:true,force:true}); }\"",
|
|
95
95
|
"start": "pnpm run build && node ./dist/scripts/run-cli.js",
|
|
96
96
|
"oracle": "pnpm start",
|
|
97
97
|
"check": "pnpm run typecheck",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"test:mcp": "pnpm run build && pnpm run test:mcp:unit && pnpm run test:mcp:mcporter",
|
|
102
102
|
"test:mcp:unit": "vitest run tests/mcp*.test.ts tests/mcp/**/*.test.ts",
|
|
103
103
|
"test:mcp:mcporter": "npx -y mcporter list oracle-local --schema --config config/mcporter.json && npx -y mcporter call oracle-local.sessions limit:1 --config config/mcporter.json",
|
|
104
|
-
"test:browser": "pnpm run build && ./scripts/browser-smoke.sh",
|
|
104
|
+
"test:browser": "pnpm run build && tsx scripts/test-browser.ts && ./scripts/browser-smoke.sh",
|
|
105
105
|
"test:live": "ORACLE_LIVE_TEST=1 vitest run tests/live --exclude tests/live/openai-live.test.ts",
|
|
106
106
|
"test:pro": "ORACLE_LIVE_TEST=1 vitest run tests/live/openai-live.test.ts",
|
|
107
107
|
"test:coverage": "vitest run --coverage",
|