@steipete/oracle 0.14.1 → 0.15.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/dist/bin/oracle-cli.js +16 -6
- package/dist/bin/oracle.js +569 -0
- package/dist/docs-site/.nojekyll +0 -0
- package/dist/docs-site/CNAME +1 -0
- package/dist/docs-site/RELEASING.html +410 -0
- package/dist/docs-site/agents.html +374 -0
- package/dist/docs-site/anthropic.html +368 -0
- package/dist/docs-site/bridge.html +416 -0
- package/dist/docs-site/browser-mode.html +594 -0
- package/dist/docs-site/chromium-forks.html +347 -0
- package/dist/docs-site/cli-reference.html +346 -0
- package/dist/docs-site/configuration.html +462 -0
- package/dist/docs-site/favicon.svg +14 -0
- package/dist/docs-site/followup.html +375 -0
- package/dist/docs-site/gemini.html +383 -0
- package/dist/docs-site/grok.html +325 -0
- package/dist/docs-site/index.html +360 -0
- package/dist/docs-site/install.html +335 -0
- package/dist/docs-site/linux.html +321 -0
- package/dist/docs-site/llms.txt +43 -0
- package/dist/docs-site/manual-tests.html +596 -0
- package/dist/docs-site/mcp.html +391 -0
- package/dist/docs-site/multimodel.html +364 -0
- package/dist/docs-site/mythical-pro-agents.html +360 -0
- package/dist/docs-site/notifier.html +338 -0
- package/dist/docs-site/openai-endpoints.html +399 -0
- package/dist/docs-site/openrouter.html +344 -0
- package/dist/docs-site/quickstart.html +369 -0
- package/dist/docs-site/refactor/ux.html +532 -0
- package/dist/docs-site/sessions.html +388 -0
- package/dist/docs-site/social-card.png +0 -0
- package/dist/docs-site/social-card.svg +79 -0
- package/dist/docs-site/spec.html +363 -0
- package/dist/docs-site/testing.html +320 -0
- package/dist/docs-site/tui-debug.html +326 -0
- package/dist/docs-site/windows-work.html +323 -0
- package/dist/docs-site/windows.html +320 -0
- package/dist/src/browser/actions/assistantResponse.js +40 -31
- package/dist/src/browser/actions/attachments.js +28 -1
- package/dist/src/browser/actions/deepResearch.js +344 -128
- package/dist/src/browser/actions/modelSelection.js +75 -9
- package/dist/src/browser/actions/promptComposer.js +71 -14
- package/dist/src/browser/actions/thinkingStatus.js +19 -1
- package/dist/src/browser/actions/thinkingTime.js +65 -20
- package/dist/src/browser/artifacts.js +193 -14
- package/dist/src/browser/chatgptFiles.js +674 -91
- package/dist/src/browser/chromeCookies.js +312 -0
- package/dist/src/browser/chromeLifecycle.js +35 -4
- package/dist/src/browser/constants.js +5 -0
- package/dist/src/browser/deepResearchResult.js +23 -0
- package/dist/src/browser/index.js +112 -41
- package/dist/src/browser/keytarShim.js +56 -0
- package/dist/src/browser/profileCopy.js +93 -0
- package/dist/src/browser/sessionRunner.js +9 -3
- package/dist/src/browser/windowsCookies.js +219 -0
- package/dist/src/cli/bridge/client.js +4 -1
- package/dist/src/cli/bridge/doctor.js +19 -0
- package/dist/src/cli/browserConfig.js +17 -1
- package/dist/src/cli/runOptions.js +11 -2
- package/dist/src/cli/sessionDisplay.js +6 -1
- package/dist/src/cli/sessionRunner.js +41 -17
- package/dist/src/config.js +3 -0
- package/dist/src/oracle/client.js +2 -0
- package/dist/src/oracle/modelResolver.js +85 -0
- package/dist/src/oracle/multiModelRunner.js +4 -1
- package/dist/src/oracle/run.js +4 -1
- package/dist/src/remote/client.js +253 -22
- package/dist/src/remote/health.js +27 -0
- package/dist/src/remote/server.js +239 -4
- package/dist/src/remote/types.js +1 -1
- package/dist/src/sessionManager.js +1 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/Info.plist +20 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/Resources/OracleIcon.icns +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/_CodeSignature/CodeResources +128 -0
- package/dist/vendor/oracle-notifier/build-notifier.sh +0 -0
- package/package.json +45 -43
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/Info.plist +20 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/Resources/OracleIcon.icns +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/_CodeSignature/CodeResources +128 -0
- package/vendor/oracle-notifier/README.md +26 -0
- package/vendor/oracle-notifier/build-notifier.sh +0 -0
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import http from "node:http";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { pipeline } from "node:stream/promises";
|
|
2
4
|
import os from "node:os";
|
|
3
5
|
import path from "node:path";
|
|
4
6
|
import net from "node:net";
|
|
5
7
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
6
8
|
import { spawn, spawnSync } from "node:child_process";
|
|
7
|
-
import { mkdtemp, rm, mkdir, writeFile } from "node:fs/promises";
|
|
9
|
+
import { mkdtemp, rm, mkdir, writeFile, stat, realpath } from "node:fs/promises";
|
|
8
10
|
import chalk from "chalk";
|
|
9
11
|
import { runBrowserMode } from "../browserMode.js";
|
|
12
|
+
import { MAX_REMOTE_ARTIFACT_BYTES } from "./types.js";
|
|
10
13
|
import { getCookies } from "@steipete/sweet-cookie";
|
|
11
14
|
import { CHATGPT_URL } from "../browser/constants.js";
|
|
12
15
|
import { getCliVersion } from "../version.js";
|
|
16
|
+
import { getOracleHomeDir } from "../oracleHome.js";
|
|
13
17
|
import { cleanupStaleProfileState, readDevToolsPort, verifyDevToolsReachable, writeChromePid, writeDevToolsActivePort, } from "../browser/profileState.js";
|
|
14
18
|
import { normalizeChatgptUrl } from "../browser/utils.js";
|
|
19
|
+
import { computeFileSha256, sanitizeArtifactFilename, sanitizeArtifactMimeType, validateArtifactFile, } from "../browser/artifacts.js";
|
|
20
|
+
const ARTIFACT_PROTOCOL_VERSION = 1;
|
|
21
|
+
const REMOTE_ARTIFACT_TTL_MS = 30 * 60 * 1000;
|
|
22
|
+
const ARTIFACT_CAPABILITIES = {
|
|
23
|
+
artifactTransfer: true,
|
|
24
|
+
artifactProtocolVersion: ARTIFACT_PROTOCOL_VERSION,
|
|
25
|
+
maxArtifactBytes: MAX_REMOTE_ARTIFACT_BYTES,
|
|
26
|
+
};
|
|
15
27
|
async function findAvailablePort() {
|
|
16
28
|
return await new Promise((resolve, reject) => {
|
|
17
29
|
const srv = net.createServer();
|
|
@@ -40,6 +52,7 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
40
52
|
: (_formatter, msg) => msg;
|
|
41
53
|
// Single-flight guard: remote Chrome can only host one run at a time, so we serialize requests.
|
|
42
54
|
let busy = false;
|
|
55
|
+
const artifactRegistry = new Map();
|
|
43
56
|
if (!process.listenerCount("unhandledRejection")) {
|
|
44
57
|
process.on("unhandledRejection", (reason) => {
|
|
45
58
|
logger(`Unhandled promise rejection in remote server: ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
@@ -67,9 +80,24 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
67
80
|
ok: true,
|
|
68
81
|
version: getCliVersion(),
|
|
69
82
|
uptimeSeconds: Math.round((Date.now() - startedAt) / 1000),
|
|
83
|
+
capabilities: ARTIFACT_CAPABILITIES,
|
|
70
84
|
}));
|
|
71
85
|
return;
|
|
72
86
|
}
|
|
87
|
+
const artifactMatch = matchArtifactRequest(req);
|
|
88
|
+
if (artifactMatch) {
|
|
89
|
+
await serveRemoteArtifact({
|
|
90
|
+
req,
|
|
91
|
+
res,
|
|
92
|
+
authToken,
|
|
93
|
+
artifactRegistry,
|
|
94
|
+
logger,
|
|
95
|
+
verbose,
|
|
96
|
+
runId: artifactMatch.runId,
|
|
97
|
+
artifactId: artifactMatch.artifactId,
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
73
101
|
if (req.method !== "POST" || req.url !== "/runs") {
|
|
74
102
|
res.statusCode = 404;
|
|
75
103
|
res.end();
|
|
@@ -190,8 +218,30 @@ export async function createRemoteServer(options = {}, deps = {}) {
|
|
|
190
218
|
sessionId: payload.options.sessionId,
|
|
191
219
|
followUpPrompts: payload.options.followUpPrompts,
|
|
192
220
|
});
|
|
193
|
-
|
|
194
|
-
|
|
221
|
+
const artifactRegistration = await registerRemoteArtifacts({
|
|
222
|
+
runId,
|
|
223
|
+
result,
|
|
224
|
+
artifactRegistry,
|
|
225
|
+
logger,
|
|
226
|
+
});
|
|
227
|
+
const artifactDescriptors = artifactRegistration.descriptors;
|
|
228
|
+
if (artifactDescriptors.length > 0) {
|
|
229
|
+
sendEvent({
|
|
230
|
+
type: "log",
|
|
231
|
+
message: `[browser] ${artifactDescriptors.length} artifact(s) ready for bridge transfer. ` +
|
|
232
|
+
"If no cloud-local artifact path appears, upgrade both Oracle bridge endpoints or copy the file manually from the Windows browser host.",
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
for (const artifact of artifactDescriptors) {
|
|
236
|
+
sendEvent({ type: "artifact-ready", runId, artifact });
|
|
237
|
+
}
|
|
238
|
+
sendEvent({
|
|
239
|
+
type: "result",
|
|
240
|
+
result: sanitizeResult(result, artifactRegistration.warnings),
|
|
241
|
+
});
|
|
242
|
+
logger(`[serve] Run ${runId} completed in ${Date.now() - runStartedAt}ms${artifactDescriptors.length > 0
|
|
243
|
+
? `; ${artifactDescriptors.length} artifact(s) ready for bridge transfer`
|
|
244
|
+
: ""}`);
|
|
195
245
|
}
|
|
196
246
|
catch (error) {
|
|
197
247
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -303,6 +353,190 @@ export async function serveRemote(options = {}) {
|
|
|
303
353
|
process.on("SIGTERM", shutdown);
|
|
304
354
|
});
|
|
305
355
|
}
|
|
356
|
+
function matchArtifactRequest(req) {
|
|
357
|
+
if (req.method !== "GET" || !req.url) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
let url;
|
|
361
|
+
try {
|
|
362
|
+
url = new URL(req.url, "http://oracle.local");
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
const match = /^\/runs\/([^/]+)\/artifacts\/([^/]+)$/.exec(url.pathname);
|
|
368
|
+
if (!match) {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
return {
|
|
373
|
+
runId: decodeURIComponent(match[1] ?? ""),
|
|
374
|
+
artifactId: decodeURIComponent(match[2] ?? ""),
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async function serveRemoteArtifact(params) {
|
|
382
|
+
const authHeader = params.req.headers.authorization ?? "";
|
|
383
|
+
if (authHeader !== `Bearer ${params.authToken}`) {
|
|
384
|
+
if (params.verbose) {
|
|
385
|
+
params.logger(`[serve] Unauthorized artifact transfer attempt from ${formatSocket(params.req)} (missing/invalid token)`);
|
|
386
|
+
}
|
|
387
|
+
params.res.writeHead(401, { "Content-Type": "application/json" });
|
|
388
|
+
params.res.end(JSON.stringify({ error: "unauthorized" }));
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
pruneExpiredArtifacts(params.artifactRegistry);
|
|
392
|
+
const key = remoteArtifactKey(params.runId, params.artifactId);
|
|
393
|
+
const artifact = params.artifactRegistry.get(key);
|
|
394
|
+
if (!artifact) {
|
|
395
|
+
params.res.writeHead(404, { "Content-Type": "application/json" });
|
|
396
|
+
params.res.end(JSON.stringify({ error: "artifact_not_found" }));
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (Date.now() > artifact.expiresAt) {
|
|
400
|
+
params.artifactRegistry.delete(key);
|
|
401
|
+
params.res.writeHead(410, { "Content-Type": "application/json" });
|
|
402
|
+
params.res.end(JSON.stringify({ error: "artifact_expired" }));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const fileStat = await stat(artifact.filePath).catch(() => null);
|
|
406
|
+
if (!fileStat?.isFile() || fileStat.size <= 0) {
|
|
407
|
+
params.res.writeHead(410, { "Content-Type": "application/json" });
|
|
408
|
+
params.res.end(JSON.stringify({ error: "artifact_unavailable" }));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (fileStat.size > MAX_REMOTE_ARTIFACT_BYTES) {
|
|
412
|
+
params.res.writeHead(413, { "Content-Type": "application/json" });
|
|
413
|
+
params.res.end(JSON.stringify({ error: "artifact_too_large" }));
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const filename = sanitizeArtifactFilename(artifact.descriptor.filename, "artifact.bin");
|
|
417
|
+
params.res.writeHead(200, {
|
|
418
|
+
"Content-Type": sanitizeArtifactMimeType(artifact.descriptor.mimeType) ?? "application/octet-stream",
|
|
419
|
+
"Content-Length": fileStat.size,
|
|
420
|
+
"Content-Disposition": `attachment; filename="${filename.replace(/"/g, "")}"`,
|
|
421
|
+
"Cache-Control": "no-store",
|
|
422
|
+
"X-Content-Type-Options": "nosniff",
|
|
423
|
+
"X-Oracle-Artifact-Id": artifact.descriptor.artifactId,
|
|
424
|
+
"X-Oracle-Artifact-Sha256": artifact.descriptor.sha256,
|
|
425
|
+
});
|
|
426
|
+
await pipeline(createReadStream(artifact.filePath), params.res).catch((error) => {
|
|
427
|
+
params.logger(`[serve] Artifact transfer failed for ${artifact.descriptor.artifactId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
function pruneExpiredArtifacts(artifactRegistry) {
|
|
431
|
+
const now = Date.now();
|
|
432
|
+
for (const [key, artifact] of artifactRegistry) {
|
|
433
|
+
if (artifact.expiresAt <= now) {
|
|
434
|
+
artifactRegistry.delete(key);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function remoteArtifactKey(runId, artifactId) {
|
|
439
|
+
return `${runId}:${artifactId}`;
|
|
440
|
+
}
|
|
441
|
+
async function registerRemoteArtifacts(params) {
|
|
442
|
+
pruneExpiredArtifacts(params.artifactRegistry);
|
|
443
|
+
const seen = new Set();
|
|
444
|
+
const fileArtifacts = [
|
|
445
|
+
...(params.result.savedFiles ?? []),
|
|
446
|
+
...(params.result.artifacts ?? []).filter((artifact) => artifact.kind === "file"),
|
|
447
|
+
];
|
|
448
|
+
const descriptors = [];
|
|
449
|
+
const warnings = [];
|
|
450
|
+
for (const artifact of fileArtifacts) {
|
|
451
|
+
if (!artifact?.path || seen.has(artifact.path)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
seen.add(artifact.path);
|
|
455
|
+
const registration = await buildRemoteArtifactRegistration(params.runId, artifact).catch((error) => {
|
|
456
|
+
const filename = sanitizeArtifactFilename(path.basename(artifact.path), "artifact.bin");
|
|
457
|
+
params.logger(`[serve] Skipping remote artifact descriptor: ${error instanceof Error ? error.message : String(error)}`);
|
|
458
|
+
warnings.push({
|
|
459
|
+
code: "remote-artifact-registration-failed",
|
|
460
|
+
severity: "warning",
|
|
461
|
+
message: `Oracle captured the browser text response, but the bridge host could not prepare ${filename} for transfer. ` +
|
|
462
|
+
"Open the ChatGPT browser on the bridge host, download the ZIP/file shown in the current response, and copy it to a cloud-readable path.",
|
|
463
|
+
});
|
|
464
|
+
return null;
|
|
465
|
+
});
|
|
466
|
+
if (!registration) {
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
params.artifactRegistry.set(remoteArtifactKey(params.runId, registration.descriptor.artifactId), {
|
|
470
|
+
descriptor: registration.descriptor,
|
|
471
|
+
filePath: registration.filePath,
|
|
472
|
+
expiresAt: Date.now() + REMOTE_ARTIFACT_TTL_MS,
|
|
473
|
+
});
|
|
474
|
+
descriptors.push(registration.descriptor);
|
|
475
|
+
}
|
|
476
|
+
return { descriptors, warnings };
|
|
477
|
+
}
|
|
478
|
+
async function buildRemoteArtifactRegistration(runId, artifact) {
|
|
479
|
+
if (artifact.path.endsWith(".crdownload")) {
|
|
480
|
+
throw new Error("artifact is still a Chrome partial download");
|
|
481
|
+
}
|
|
482
|
+
const filePath = await resolveRegisteredArtifactPath(artifact.path);
|
|
483
|
+
const fileStat = await stat(filePath);
|
|
484
|
+
if (!fileStat.isFile() || fileStat.size <= 0) {
|
|
485
|
+
throw new Error("artifact is not a completed non-empty file");
|
|
486
|
+
}
|
|
487
|
+
if (fileStat.size > MAX_REMOTE_ARTIFACT_BYTES) {
|
|
488
|
+
throw new Error("artifact exceeds bridge transfer size limit");
|
|
489
|
+
}
|
|
490
|
+
const filename = sanitizeArtifactFilename(path.basename(filePath), "artifact.bin");
|
|
491
|
+
const mimeType = sanitizeArtifactMimeType(artifact.mimeType);
|
|
492
|
+
// Recompute security metadata from the exact file registered for transfer.
|
|
493
|
+
const validation = await validateArtifactFile({
|
|
494
|
+
path: filePath,
|
|
495
|
+
filename,
|
|
496
|
+
mimeType,
|
|
497
|
+
});
|
|
498
|
+
const sha256 = await computeFileSha256(filePath);
|
|
499
|
+
return {
|
|
500
|
+
filePath,
|
|
501
|
+
descriptor: {
|
|
502
|
+
artifactId: randomUUID(),
|
|
503
|
+
runId,
|
|
504
|
+
kind: "file",
|
|
505
|
+
filename,
|
|
506
|
+
mimeType,
|
|
507
|
+
byteSize: fileStat.size,
|
|
508
|
+
sha256,
|
|
509
|
+
validation,
|
|
510
|
+
sourceUrlKind: classifySourceUrlKind(artifact.sourceUrl),
|
|
511
|
+
transferStatus: "ready",
|
|
512
|
+
},
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
async function resolveRegisteredArtifactPath(filePath) {
|
|
516
|
+
const [resolvedFile, sessionsRoot] = await Promise.all([
|
|
517
|
+
realpath(filePath),
|
|
518
|
+
realpath(path.join(getOracleHomeDir(), "sessions")),
|
|
519
|
+
]);
|
|
520
|
+
const relative = path.relative(sessionsRoot, resolvedFile);
|
|
521
|
+
const segments = relative.split(path.sep);
|
|
522
|
+
if (!relative ||
|
|
523
|
+
relative.startsWith(`..${path.sep}`) ||
|
|
524
|
+
path.isAbsolute(relative) ||
|
|
525
|
+
segments.length < 3 ||
|
|
526
|
+
segments[1] !== "artifacts") {
|
|
527
|
+
throw new Error("artifact is outside Oracle's session artifact boundary");
|
|
528
|
+
}
|
|
529
|
+
return resolvedFile;
|
|
530
|
+
}
|
|
531
|
+
function classifySourceUrlKind(sourceUrl) {
|
|
532
|
+
if (sourceUrl?.startsWith("sandbox:")) {
|
|
533
|
+
return "sandbox";
|
|
534
|
+
}
|
|
535
|
+
if (sourceUrl === "browser-download") {
|
|
536
|
+
return "browser-download";
|
|
537
|
+
}
|
|
538
|
+
return "chatgpt-file-endpoint";
|
|
539
|
+
}
|
|
306
540
|
async function readRequestBody(req) {
|
|
307
541
|
const chunks = [];
|
|
308
542
|
for await (const chunk of req) {
|
|
@@ -313,7 +547,7 @@ async function readRequestBody(req) {
|
|
|
313
547
|
function sanitizeName(raw) {
|
|
314
548
|
return raw.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
315
549
|
}
|
|
316
|
-
function sanitizeResult(result) {
|
|
550
|
+
function sanitizeResult(result, warnings = []) {
|
|
317
551
|
return {
|
|
318
552
|
answerText: result.answerText,
|
|
319
553
|
answerMarkdown: result.answerMarkdown,
|
|
@@ -321,6 +555,7 @@ function sanitizeResult(result) {
|
|
|
321
555
|
tookMs: result.tookMs,
|
|
322
556
|
answerTokens: result.answerTokens,
|
|
323
557
|
answerChars: result.answerChars,
|
|
558
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
324
559
|
chromePid: undefined,
|
|
325
560
|
chromePort: undefined,
|
|
326
561
|
userDataDir: undefined,
|
package/dist/src/remote/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export const MAX_REMOTE_ARTIFACT_BYTES = 512 * 1024 * 1024;
|
|
@@ -197,6 +197,7 @@ export async function initializeSession(options, cwd, notifications, baseSlugOve
|
|
|
197
197
|
followupSessionId: options.followupSessionId,
|
|
198
198
|
followupModel: options.followupModel,
|
|
199
199
|
effectiveModelId: options.effectiveModelId,
|
|
200
|
+
modelOverrides: options.modelOverrides,
|
|
200
201
|
maxInput: options.maxInput,
|
|
201
202
|
system: options.system,
|
|
202
203
|
maxOutput: options.maxOutput,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleIdentifier</key>
|
|
6
|
+
<string>com.steipete.oracle.notifier</string>
|
|
7
|
+
<key>CFBundleName</key>
|
|
8
|
+
<string>OracleNotifier</string>
|
|
9
|
+
<key>CFBundleDisplayName</key>
|
|
10
|
+
<string>Oracle Notifier</string>
|
|
11
|
+
<key>CFBundleExecutable</key>
|
|
12
|
+
<string>OracleNotifier</string>
|
|
13
|
+
<key>CFBundleIconFile</key>
|
|
14
|
+
<string>OracleIcon</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>APPL</string>
|
|
17
|
+
<key>LSMinimumSystemVersion</key>
|
|
18
|
+
<string>13.0</string>
|
|
19
|
+
</dict>
|
|
20
|
+
</plist>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>files</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Resources/OracleIcon.icns</key>
|
|
8
|
+
<data>
|
|
9
|
+
edUHAMetayIv3xtc3Vb92VXRLfM=
|
|
10
|
+
</data>
|
|
11
|
+
</dict>
|
|
12
|
+
<key>files2</key>
|
|
13
|
+
<dict>
|
|
14
|
+
<key>Resources/OracleIcon.icns</key>
|
|
15
|
+
<dict>
|
|
16
|
+
<key>hash2</key>
|
|
17
|
+
<data>
|
|
18
|
+
AVPJK/6w6IOsDLmZTW4hL+Za+/4wHMxZiIp0t6m3NRA=
|
|
19
|
+
</data>
|
|
20
|
+
</dict>
|
|
21
|
+
</dict>
|
|
22
|
+
<key>rules</key>
|
|
23
|
+
<dict>
|
|
24
|
+
<key>^Resources/</key>
|
|
25
|
+
<true/>
|
|
26
|
+
<key>^Resources/.*\.lproj/</key>
|
|
27
|
+
<dict>
|
|
28
|
+
<key>optional</key>
|
|
29
|
+
<true/>
|
|
30
|
+
<key>weight</key>
|
|
31
|
+
<real>1000</real>
|
|
32
|
+
</dict>
|
|
33
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
34
|
+
<dict>
|
|
35
|
+
<key>omit</key>
|
|
36
|
+
<true/>
|
|
37
|
+
<key>weight</key>
|
|
38
|
+
<real>1100</real>
|
|
39
|
+
</dict>
|
|
40
|
+
<key>^Resources/Base\.lproj/</key>
|
|
41
|
+
<dict>
|
|
42
|
+
<key>weight</key>
|
|
43
|
+
<real>1010</real>
|
|
44
|
+
</dict>
|
|
45
|
+
<key>^version.plist$</key>
|
|
46
|
+
<true/>
|
|
47
|
+
</dict>
|
|
48
|
+
<key>rules2</key>
|
|
49
|
+
<dict>
|
|
50
|
+
<key>.*\.dSYM($|/)</key>
|
|
51
|
+
<dict>
|
|
52
|
+
<key>weight</key>
|
|
53
|
+
<real>11</real>
|
|
54
|
+
</dict>
|
|
55
|
+
<key>^(.*/)?\.DS_Store$</key>
|
|
56
|
+
<dict>
|
|
57
|
+
<key>omit</key>
|
|
58
|
+
<true/>
|
|
59
|
+
<key>weight</key>
|
|
60
|
+
<real>2000</real>
|
|
61
|
+
</dict>
|
|
62
|
+
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
|
63
|
+
<dict>
|
|
64
|
+
<key>nested</key>
|
|
65
|
+
<true/>
|
|
66
|
+
<key>weight</key>
|
|
67
|
+
<real>10</real>
|
|
68
|
+
</dict>
|
|
69
|
+
<key>^.*</key>
|
|
70
|
+
<true/>
|
|
71
|
+
<key>^Info\.plist$</key>
|
|
72
|
+
<dict>
|
|
73
|
+
<key>omit</key>
|
|
74
|
+
<true/>
|
|
75
|
+
<key>weight</key>
|
|
76
|
+
<real>20</real>
|
|
77
|
+
</dict>
|
|
78
|
+
<key>^PkgInfo$</key>
|
|
79
|
+
<dict>
|
|
80
|
+
<key>omit</key>
|
|
81
|
+
<true/>
|
|
82
|
+
<key>weight</key>
|
|
83
|
+
<real>20</real>
|
|
84
|
+
</dict>
|
|
85
|
+
<key>^Resources/</key>
|
|
86
|
+
<dict>
|
|
87
|
+
<key>weight</key>
|
|
88
|
+
<real>20</real>
|
|
89
|
+
</dict>
|
|
90
|
+
<key>^Resources/.*\.lproj/</key>
|
|
91
|
+
<dict>
|
|
92
|
+
<key>optional</key>
|
|
93
|
+
<true/>
|
|
94
|
+
<key>weight</key>
|
|
95
|
+
<real>1000</real>
|
|
96
|
+
</dict>
|
|
97
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
98
|
+
<dict>
|
|
99
|
+
<key>omit</key>
|
|
100
|
+
<true/>
|
|
101
|
+
<key>weight</key>
|
|
102
|
+
<real>1100</real>
|
|
103
|
+
</dict>
|
|
104
|
+
<key>^Resources/Base\.lproj/</key>
|
|
105
|
+
<dict>
|
|
106
|
+
<key>weight</key>
|
|
107
|
+
<real>1010</real>
|
|
108
|
+
</dict>
|
|
109
|
+
<key>^[^/]+$</key>
|
|
110
|
+
<dict>
|
|
111
|
+
<key>nested</key>
|
|
112
|
+
<true/>
|
|
113
|
+
<key>weight</key>
|
|
114
|
+
<real>10</real>
|
|
115
|
+
</dict>
|
|
116
|
+
<key>^embedded\.provisionprofile$</key>
|
|
117
|
+
<dict>
|
|
118
|
+
<key>weight</key>
|
|
119
|
+
<real>20</real>
|
|
120
|
+
</dict>
|
|
121
|
+
<key>^version\.plist$</key>
|
|
122
|
+
<dict>
|
|
123
|
+
<key>weight</key>
|
|
124
|
+
<real>20</real>
|
|
125
|
+
</dict>
|
|
126
|
+
</dict>
|
|
127
|
+
</dict>
|
|
128
|
+
</plist>
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steipete/oracle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "CLI wrapper around OpenAI Responses API with GPT-5.5 Pro, GPT-5.5, GPT-5.4, GPT-5.2, GPT-5.1, and GPT-5.1 Codex high reasoning modes.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://askoracle.sh",
|
|
@@ -28,9 +28,37 @@
|
|
|
28
28
|
],
|
|
29
29
|
"type": "module",
|
|
30
30
|
"main": "dist/bin/oracle-cli.js",
|
|
31
|
+
"scripts": {
|
|
32
|
+
"docs:list": "tsx scripts/docs-list.ts",
|
|
33
|
+
"docs:check": "node --no-deprecation --import tsx bin/oracle-cli.ts docs check",
|
|
34
|
+
"docs:site": "node scripts/build-docs-site.mjs",
|
|
35
|
+
"build": "tsgo -p tsconfig.build.json && pnpm run build:vendor",
|
|
36
|
+
"build:vendor": "node -e \"const fs=require('fs'); const path=require('path'); const vendorRoot=path.join('dist','vendor'); fs.rmSync(vendorRoot,{recursive:true,force:true}); const vendors=[['oracle-notifier']]; vendors.forEach(([name])=>{const src=path.join('vendor',name); const dest=path.join(vendorRoot,name); fs.mkdirSync(dest,{recursive:true}); if(fs.existsSync(src)){fs.cpSync(src,dest,{recursive:true,force:true});}});\"",
|
|
37
|
+
"start": "pnpm run build && node ./dist/scripts/run-cli.js",
|
|
38
|
+
"oracle": "pnpm start",
|
|
39
|
+
"check": "pnpm run format:check && pnpm run lint",
|
|
40
|
+
"typecheck": "tsgo --noEmit",
|
|
41
|
+
"format": "oxfmt --write .",
|
|
42
|
+
"format:check": "oxfmt --check .",
|
|
43
|
+
"format:diff": "oxfmt --write . && git --no-pager diff",
|
|
44
|
+
"lint": "pnpm run typecheck && oxlint",
|
|
45
|
+
"lint:fix": "oxlint --fix && pnpm run format",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:mcp": "pnpm run build && pnpm run test:mcp:unit && pnpm run test:mcp:mcporter",
|
|
48
|
+
"test:mcp:unit": "vitest run tests/mcp*.test.ts tests/mcp/**/*.test.ts",
|
|
49
|
+
"test:mcp:mcporter": "CHROME_DEVTOOLS_URL=http://127.0.0.1:0 pnpm dlx mcporter list oracle-local --schema --config config/mcporter.json && CHROME_DEVTOOLS_URL=http://127.0.0.1:0 pnpm dlx mcporter call oracle-local.sessions limit:1 --config config/mcporter.json",
|
|
50
|
+
"test:browser": "pnpm run build && tsx scripts/test-browser.ts && ./scripts/browser-smoke.sh",
|
|
51
|
+
"test:packed-cli": "node scripts/packed-cli-smoke.mjs",
|
|
52
|
+
"test:live": "ORACLE_LIVE_TEST=1 vitest run tests/live --exclude tests/live/openai-live.test.ts",
|
|
53
|
+
"test:live:fast": "ORACLE_LIVE_TEST=1 ORACLE_LIVE_TEST_FAST=1 vitest run tests/live/browser-fast-live.test.ts",
|
|
54
|
+
"test:pro": "ORACLE_LIVE_TEST=1 vitest run tests/live/openai-live.test.ts",
|
|
55
|
+
"test:coverage": "vitest run --coverage",
|
|
56
|
+
"prepare": "pnpm run build",
|
|
57
|
+
"mcp": "pnpm run build && node ./dist/bin/oracle-mcp.js"
|
|
58
|
+
},
|
|
31
59
|
"dependencies": {
|
|
32
60
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
33
|
-
"@google/genai": "^2.
|
|
61
|
+
"@google/genai": "^2.9.0",
|
|
34
62
|
"@google/generative-ai": "^0.24.1",
|
|
35
63
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
36
64
|
"@steipete/sweet-cookie": "^0.4.0",
|
|
@@ -46,8 +74,8 @@
|
|
|
46
74
|
"json5": "^2.2.3",
|
|
47
75
|
"kleur": "^4.1.5",
|
|
48
76
|
"markdansi": "0.3.1",
|
|
49
|
-
"openai": "^6.
|
|
50
|
-
"osc-progress": "^0.3.
|
|
77
|
+
"openai": "^6.44.0",
|
|
78
|
+
"osc-progress": "^0.3.1",
|
|
51
79
|
"qs": "^6.15.2",
|
|
52
80
|
"shiki": "^4.2.0",
|
|
53
81
|
"toasted-notifier": "^10.1.0",
|
|
@@ -57,19 +85,19 @@
|
|
|
57
85
|
"devDependencies": {
|
|
58
86
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
59
87
|
"@types/chrome-remote-interface": "^0.34.0",
|
|
60
|
-
"@types/inquirer": "^9.0.
|
|
61
|
-
"@types/node": "^
|
|
62
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
63
|
-
"@vitest/coverage-v8": "4.1.
|
|
64
|
-
"devtools-protocol": "0.0.
|
|
65
|
-
"es-toolkit": "^1.
|
|
66
|
-
"esbuild": "^0.28.
|
|
67
|
-
"oxfmt": "0.
|
|
68
|
-
"oxlint": "^1.
|
|
69
|
-
"puppeteer-core": "^25.
|
|
88
|
+
"@types/inquirer": "^9.0.10",
|
|
89
|
+
"@types/node": "^26.0.0",
|
|
90
|
+
"@typescript/native-preview": "7.0.0-dev.20260623.1",
|
|
91
|
+
"@vitest/coverage-v8": "4.1.9",
|
|
92
|
+
"devtools-protocol": "0.0.1648812",
|
|
93
|
+
"es-toolkit": "^1.48.1",
|
|
94
|
+
"esbuild": "^0.28.1",
|
|
95
|
+
"oxfmt": "0.56.0",
|
|
96
|
+
"oxlint": "^1.71.0",
|
|
97
|
+
"puppeteer-core": "^25.2.0",
|
|
70
98
|
"tsx": "^4.22.4",
|
|
71
99
|
"typescript": "^6.0.3",
|
|
72
|
-
"vitest": "^4.1.
|
|
100
|
+
"vitest": "^4.1.9"
|
|
73
101
|
},
|
|
74
102
|
"devEngines": {
|
|
75
103
|
"runtime": [
|
|
@@ -82,31 +110,5 @@
|
|
|
82
110
|
"engines": {
|
|
83
111
|
"node": ">=24"
|
|
84
112
|
},
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
"docs:check": "node --no-deprecation --import tsx bin/oracle-cli.ts docs check",
|
|
88
|
-
"docs:site": "node scripts/build-docs-site.mjs",
|
|
89
|
-
"build": "tsgo -p tsconfig.build.json && pnpm run build:vendor",
|
|
90
|
-
"build:vendor": "node -e \"const fs=require('fs'); const path=require('path'); const vendorRoot=path.join('dist','vendor'); fs.rmSync(vendorRoot,{recursive:true,force:true}); const vendors=[['oracle-notifier']]; vendors.forEach(([name])=>{const src=path.join('vendor',name); const dest=path.join(vendorRoot,name); fs.mkdirSync(dest,{recursive:true}); if(fs.existsSync(src)){fs.cpSync(src,dest,{recursive:true,force:true});}});\"",
|
|
91
|
-
"start": "pnpm run build && node ./dist/scripts/run-cli.js",
|
|
92
|
-
"oracle": "pnpm start",
|
|
93
|
-
"check": "pnpm run format:check && pnpm run lint",
|
|
94
|
-
"typecheck": "tsgo --noEmit",
|
|
95
|
-
"format": "oxfmt --write .",
|
|
96
|
-
"format:check": "oxfmt --check .",
|
|
97
|
-
"format:diff": "oxfmt --write . && git --no-pager diff",
|
|
98
|
-
"lint": "pnpm run typecheck && oxlint",
|
|
99
|
-
"lint:fix": "oxlint --fix && pnpm run format",
|
|
100
|
-
"test": "vitest run",
|
|
101
|
-
"test:mcp": "pnpm run build && pnpm run test:mcp:unit && pnpm run test:mcp:mcporter",
|
|
102
|
-
"test:mcp:unit": "vitest run tests/mcp*.test.ts tests/mcp/**/*.test.ts",
|
|
103
|
-
"test:mcp:mcporter": "CHROME_DEVTOOLS_URL=http://127.0.0.1:0 pnpm dlx mcporter list oracle-local --schema --config config/mcporter.json && CHROME_DEVTOOLS_URL=http://127.0.0.1:0 pnpm dlx mcporter call oracle-local.sessions limit:1 --config config/mcporter.json",
|
|
104
|
-
"test:browser": "pnpm run build && tsx scripts/test-browser.ts && ./scripts/browser-smoke.sh",
|
|
105
|
-
"test:packed-cli": "node scripts/packed-cli-smoke.mjs",
|
|
106
|
-
"test:live": "ORACLE_LIVE_TEST=1 vitest run tests/live --exclude tests/live/openai-live.test.ts",
|
|
107
|
-
"test:live:fast": "ORACLE_LIVE_TEST=1 ORACLE_LIVE_TEST_FAST=1 vitest run tests/live/browser-fast-live.test.ts",
|
|
108
|
-
"test:pro": "ORACLE_LIVE_TEST=1 vitest run tests/live/openai-live.test.ts",
|
|
109
|
-
"test:coverage": "vitest run --coverage",
|
|
110
|
-
"mcp": "pnpm run build && node ./dist/bin/oracle-mcp.js"
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
+
"packageManager": "pnpm@10.33.2"
|
|
114
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleIdentifier</key>
|
|
6
|
+
<string>com.steipete.oracle.notifier</string>
|
|
7
|
+
<key>CFBundleName</key>
|
|
8
|
+
<string>OracleNotifier</string>
|
|
9
|
+
<key>CFBundleDisplayName</key>
|
|
10
|
+
<string>Oracle Notifier</string>
|
|
11
|
+
<key>CFBundleExecutable</key>
|
|
12
|
+
<string>OracleNotifier</string>
|
|
13
|
+
<key>CFBundleIconFile</key>
|
|
14
|
+
<string>OracleIcon</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>APPL</string>
|
|
17
|
+
<key>LSMinimumSystemVersion</key>
|
|
18
|
+
<string>13.0</string>
|
|
19
|
+
</dict>
|
|
20
|
+
</plist>
|