@steipete/oracle 0.16.1 → 0.17.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 +72 -337
- package/dist/bin/oracle-cli.js +185 -56
- 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 +410 -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 +389 -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 +324 -0
- package/dist/docs-site/windows.html +320 -0
- package/dist/scripts/test-browser.js +1 -25
- package/dist/src/browser/actions/modelSelection.js +36 -34
- package/dist/src/browser/actions/navigation.js +8 -3
- package/dist/src/browser/actions/thinkingTime.js +96 -45
- package/dist/src/browser/chromeLifecycle.js +8 -37
- package/dist/src/browser/index.js +23 -8
- package/dist/src/browser/modelDisplay.js +67 -0
- package/dist/src/browser/reattach.js +14 -1
- package/dist/src/browser/recoverConversation.js +2 -1
- package/dist/src/browser/sessionRunner.js +9 -10
- package/dist/src/browser/wslHost.js +50 -0
- package/dist/src/cli/browserConfig.js +31 -11
- package/dist/src/cli/detach.js +21 -4
- package/dist/src/cli/dryRun.js +13 -2
- package/dist/src/cli/engine.js +2 -2
- package/dist/src/cli/options.js +5 -1
- package/dist/src/cli/sessionDisplay.js +60 -8
- package/dist/src/cli/sessionLifecycle.js +2 -1
- package/dist/src/cli/sessionRunner.js +110 -60
- package/dist/src/cli/sessionTable.js +5 -1
- package/dist/src/cli/tui/index.js +12 -4
- package/dist/src/duration.js +3 -0
- package/dist/src/gemini-web/client.js +19 -1
- package/dist/src/oracle/modelResolver.js +8 -1
- package/dist/src/oracle/request.js +9 -2
- package/dist/src/oracle/run.js +43 -3
- package/dist/src/oracle/thinkingTime.js +9 -3
- package/dist/src/sessionManager.js +41 -12
- 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 +17 -17
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
package/dist/src/duration.js
CHANGED
|
@@ -21,6 +21,9 @@ export function parseDuration(input, fallback) {
|
|
|
21
21
|
let lastIndex = 0;
|
|
22
22
|
let match = multiDuration.exec(normalized);
|
|
23
23
|
while (match !== null) {
|
|
24
|
+
if (match.index !== lastIndex) {
|
|
25
|
+
return fallback;
|
|
26
|
+
}
|
|
24
27
|
total += convertUnit(Number(match[1]), match[2]);
|
|
25
28
|
lastIndex = multiDuration.lastIndex;
|
|
26
29
|
match = multiDuration.exec(normalized);
|
|
@@ -12,11 +12,29 @@ const GEMINI_UPLOAD_MIME_TYPES = {
|
|
|
12
12
|
".gif": "image/gif",
|
|
13
13
|
".jpeg": "image/jpeg",
|
|
14
14
|
".jpg": "image/jpeg",
|
|
15
|
+
".mov": "video/quicktime",
|
|
16
|
+
".mp4": "video/mp4",
|
|
15
17
|
".pdf": "application/pdf",
|
|
16
18
|
".png": "image/png",
|
|
17
19
|
".svg": "image/svg+xml",
|
|
20
|
+
".webm": "video/webm",
|
|
18
21
|
".webp": "image/webp",
|
|
19
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the MIME type Gemini should be told an upload carries.
|
|
25
|
+
*
|
|
26
|
+
* Gemini silently discards uploads it cannot type: the run still reports the file as
|
|
27
|
+
* attached, but the model never receives it and answers as though nothing was sent.
|
|
28
|
+
* Anything falling back to `application/octet-stream` is therefore invisible to the model.
|
|
29
|
+
*
|
|
30
|
+
* Only formats confirmed to work against the Gemini web upload endpoint are listed. The
|
|
31
|
+
* endpoint also gates on the file extension, not just the declared type — an `.m4v` byte
|
|
32
|
+
* for byte identical to a working `.mp4`, and declared `video/mp4`, is still dropped — so
|
|
33
|
+
* entries here cannot be extrapolated from what the Gemini API documents.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveGeminiUploadMimeType(filePath) {
|
|
36
|
+
return (GEMINI_UPLOAD_MIME_TYPES[path.extname(filePath).toLowerCase()] ?? "application/octet-stream");
|
|
37
|
+
}
|
|
20
38
|
function getNestedValue(value, pathParts, fallback) {
|
|
21
39
|
let current = value;
|
|
22
40
|
for (const part of pathParts) {
|
|
@@ -125,7 +143,7 @@ async function uploadGeminiFile(filePath, signal) {
|
|
|
125
143
|
const absPath = path.resolve(process.cwd(), filePath);
|
|
126
144
|
const data = await readFile(absPath);
|
|
127
145
|
const fileName = path.basename(absPath);
|
|
128
|
-
const mimeType =
|
|
146
|
+
const mimeType = resolveGeminiUploadMimeType(absPath);
|
|
129
147
|
const form = new FormData();
|
|
130
148
|
form.append("file", new Blob([data], { type: mimeType }), fileName);
|
|
131
149
|
const res = await fetch(GEMINI_UPLOAD_URL, {
|
|
@@ -192,7 +192,14 @@ async function resolveBaseModelConfig(model, options = {}) {
|
|
|
192
192
|
export function isProModel(model) {
|
|
193
193
|
return isKnownModel(model) && PRO_MODELS.has(model);
|
|
194
194
|
}
|
|
195
|
-
const VALID_REASONING_EFFORTS = [
|
|
195
|
+
const VALID_REASONING_EFFORTS = [
|
|
196
|
+
"none",
|
|
197
|
+
"low",
|
|
198
|
+
"medium",
|
|
199
|
+
"high",
|
|
200
|
+
"xhigh",
|
|
201
|
+
"max",
|
|
202
|
+
];
|
|
196
203
|
function isRecord(value) {
|
|
197
204
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
198
205
|
}
|
|
@@ -11,8 +11,15 @@ export function buildPrompt(basePrompt, files, cwd = process.cwd()) {
|
|
|
11
11
|
const sectionText = formatFileSections(sections, { includeFileIndex: true });
|
|
12
12
|
return `${basePrompt.trim()}\n\n${sectionText}`;
|
|
13
13
|
}
|
|
14
|
-
export function buildRequestBody({ modelConfig, systemPrompt, userPrompt, searchEnabled, maxOutputTokens, background, storeResponse, previousResponseId, }) {
|
|
14
|
+
export function buildRequestBody({ modelConfig, reasoningEffort, reasoningMode, systemPrompt, userPrompt, searchEnabled, maxOutputTokens, background, storeResponse, previousResponseId, }) {
|
|
15
15
|
const searchToolType = modelConfig.searchToolType ?? "web_search_preview";
|
|
16
|
+
const reasoning = modelConfig.reasoning || reasoningEffort || reasoningMode
|
|
17
|
+
? {
|
|
18
|
+
...(modelConfig.reasoning ?? {}),
|
|
19
|
+
...(reasoningEffort ? { effort: reasoningEffort } : {}),
|
|
20
|
+
...(reasoningMode ? { mode: reasoningMode } : {}),
|
|
21
|
+
}
|
|
22
|
+
: undefined;
|
|
16
23
|
return {
|
|
17
24
|
model: modelConfig.apiModel ?? modelConfig.model,
|
|
18
25
|
previous_response_id: previousResponseId ? previousResponseId : undefined,
|
|
@@ -29,7 +36,7 @@ export function buildRequestBody({ modelConfig, systemPrompt, userPrompt, search
|
|
|
29
36
|
},
|
|
30
37
|
],
|
|
31
38
|
tools: searchEnabled ? [{ type: searchToolType }] : undefined,
|
|
32
|
-
reasoning
|
|
39
|
+
reasoning,
|
|
33
40
|
max_output_tokens: maxOutputTokens,
|
|
34
41
|
background: background ? true : undefined,
|
|
35
42
|
store: storeResponse ? true : undefined,
|
package/dist/src/oracle/run.js
CHANGED
|
@@ -33,6 +33,9 @@ const dim = (text) => (isStdoutTty ? kleur.dim(text) : text);
|
|
|
33
33
|
// Default timeout for non-pro API runs (fast models) — give them up to 120s.
|
|
34
34
|
const DEFAULT_TIMEOUT_NON_PRO_MS = 120_000;
|
|
35
35
|
const DEFAULT_TIMEOUT_PRO_MS = 60 * 60 * 1000;
|
|
36
|
+
const GPT_5_6_API_MODELS = new Set(["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]);
|
|
37
|
+
const REASONING_EFFORTS = new Set(["none", "low", "medium", "high", "xhigh", "max"]);
|
|
38
|
+
const REASONING_MODES = new Set(["standard", "pro"]);
|
|
36
39
|
const defaultWait = (ms) => new Promise((resolve) => {
|
|
37
40
|
setTimeout(resolve, ms);
|
|
38
41
|
});
|
|
@@ -69,6 +72,33 @@ function runtimeKeySource({ route, providerMode, optionsApiKey, }) {
|
|
|
69
72
|
return "XAI_API_KEY";
|
|
70
73
|
return optionsApiKey ? "apiKey option" : route.keySource;
|
|
71
74
|
}
|
|
75
|
+
function validateReasoningOptions(options, route) {
|
|
76
|
+
const { reasoningEffort, reasoningMode } = options;
|
|
77
|
+
if (!reasoningEffort && !reasoningMode)
|
|
78
|
+
return;
|
|
79
|
+
if (reasoningEffort && !REASONING_EFFORTS.has(reasoningEffort)) {
|
|
80
|
+
throw new PromptValidationError(`Invalid reasoning effort "${reasoningEffort}". Expected none, low, medium, high, xhigh, or max.`, { model: options.model, reasoningEffort });
|
|
81
|
+
}
|
|
82
|
+
if (reasoningMode && !REASONING_MODES.has(reasoningMode)) {
|
|
83
|
+
throw new PromptValidationError(`Invalid reasoning mode "${reasoningMode}". Expected standard or pro.`, { model: options.model, reasoningMode });
|
|
84
|
+
}
|
|
85
|
+
if (!GPT_5_6_API_MODELS.has(options.model)) {
|
|
86
|
+
const option = reasoningMode
|
|
87
|
+
? `Reasoning mode "${reasoningMode}"`
|
|
88
|
+
: `Reasoning effort "${reasoningEffort}"`;
|
|
89
|
+
const guidance = reasoningMode
|
|
90
|
+
? `Use --model gpt-5.6-sol --reasoning-mode ${reasoningMode}.`
|
|
91
|
+
: `Use --model gpt-5.6-sol --reasoning-effort ${reasoningEffort}.`;
|
|
92
|
+
throw new PromptValidationError(`${option} is available only for GPT-5.6 API models. ${guidance}`, { model: options.model, reasoningEffort, reasoningMode });
|
|
93
|
+
}
|
|
94
|
+
if (reasoningMode &&
|
|
95
|
+
!route.isAzureOpenAI &&
|
|
96
|
+
(route.openRouterFallback ||
|
|
97
|
+
isOpenRouterBaseUrl(route.baseUrl) ||
|
|
98
|
+
isCustomBaseUrl(route.baseUrl))) {
|
|
99
|
+
throw new PromptValidationError("--reasoning-mode requires the OpenAI or Azure OpenAI Responses API; OpenRouter and custom --base-url routes use the Chat Completions adapter.", { model: options.model, reasoningMode });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
72
102
|
export async function runOracle(options, deps = {}) {
|
|
73
103
|
const { apiKey: optionsApiKey = options.apiKey, cwd = process.cwd(), fs: fsModule = createFsAdapter(fs), log = console.log, write: sinkWrite = (_text) => true, allowStdout = true, stdoutWrite: stdoutWriteDep, now = () => performance.now(), clientFactory = createDefaultClientFactory(), client, wait = defaultWait, } = deps;
|
|
74
104
|
const stdoutWrite = allowStdout
|
|
@@ -100,6 +130,7 @@ export async function runOracle(options, deps = {}) {
|
|
|
100
130
|
const { isAzureOpenAI, azureDeploymentName } = route;
|
|
101
131
|
const baseUrl = route.baseUrl;
|
|
102
132
|
const openRouterFallback = route.openRouterFallback;
|
|
133
|
+
validateReasoningOptions(options, route);
|
|
103
134
|
const logVerbose = (message) => {
|
|
104
135
|
if (options.verbose) {
|
|
105
136
|
log(dim(`[verbose] ${message}`));
|
|
@@ -125,7 +156,7 @@ export async function runOracle(options, deps = {}) {
|
|
|
125
156
|
const minPromptLength = Number.parseInt(process.env.ORACLE_MIN_PROMPT_CHARS ?? "10", 10);
|
|
126
157
|
const promptLength = options.prompt?.trim().length ?? 0;
|
|
127
158
|
// Enforce the short-prompt guardrail on pro-tier models because they're costly; cheaper models can run short prompts without blocking.
|
|
128
|
-
const isProTierModel = isProModel(options.model);
|
|
159
|
+
const isProTierModel = isProModel(options.model) || options.reasoningMode === "pro";
|
|
129
160
|
if (isProTierModel && !Number.isNaN(minPromptLength) && promptLength < minPromptLength) {
|
|
130
161
|
throw new PromptValidationError(`Prompt is too short (<${minPromptLength} chars). This was likely accidental; please provide more detail.`, { minPromptLength, promptLength });
|
|
131
162
|
}
|
|
@@ -205,6 +236,8 @@ export async function runOracle(options, deps = {}) {
|
|
|
205
236
|
}
|
|
206
237
|
const requestBody = buildRequestBody({
|
|
207
238
|
modelConfig,
|
|
239
|
+
reasoningEffort: options.reasoningEffort,
|
|
240
|
+
reasoningMode: options.reasoningMode,
|
|
208
241
|
systemPrompt,
|
|
209
242
|
userPrompt: promptWithFiles,
|
|
210
243
|
searchEnabled,
|
|
@@ -249,6 +282,12 @@ export async function runOracle(options, deps = {}) {
|
|
|
249
282
|
if (options.background && !supportsBackground) {
|
|
250
283
|
log(dim("Background runs are not supported for this model; streaming in foreground instead."));
|
|
251
284
|
}
|
|
285
|
+
if (options.reasoningMode) {
|
|
286
|
+
log(dim(`Reasoning mode: ${options.reasoningMode}`));
|
|
287
|
+
}
|
|
288
|
+
if (options.reasoningEffort) {
|
|
289
|
+
log(dim(`Reasoning effort: ${options.reasoningEffort}`));
|
|
290
|
+
}
|
|
252
291
|
if (!options.suppressTips) {
|
|
253
292
|
if (pendingNoFilesTip) {
|
|
254
293
|
log(dim(pendingNoFilesTip));
|
|
@@ -547,8 +586,9 @@ export async function runOracle(options, deps = {}) {
|
|
|
547
586
|
},
|
|
548
587
|
})?.totalUsd
|
|
549
588
|
: undefined;
|
|
550
|
-
const effortLabel = modelConfig.reasoning?.effort;
|
|
551
|
-
const
|
|
589
|
+
const effortLabel = options.reasoningEffort ?? modelConfig.reasoning?.effort;
|
|
590
|
+
const reasoningLabel = [options.reasoningMode, effortLabel].filter(Boolean).join("/");
|
|
591
|
+
const modelLabel = reasoningLabel ? `${modelConfig.model}[${reasoningLabel}]` : modelConfig.model;
|
|
552
592
|
const sessionIdContainsModel = typeof options.sessionId === "string" &&
|
|
553
593
|
options.sessionId.toLowerCase().includes(modelConfig.model.toLowerCase());
|
|
554
594
|
const tokensDisplay = [inputTokens, outputTokens, reasoningTokens, totalTokens]
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export const THINKING_TIME_LEVELS = [
|
|
1
|
+
export const THINKING_TIME_LEVELS = [
|
|
2
|
+
"light",
|
|
3
|
+
"standard",
|
|
4
|
+
"extended",
|
|
5
|
+
"extra-high",
|
|
6
|
+
"heavy",
|
|
7
|
+
];
|
|
2
8
|
export const THINKING_TIME_ALIASES = [
|
|
3
9
|
"instant",
|
|
4
10
|
"low",
|
|
5
11
|
"medium",
|
|
6
12
|
"high",
|
|
7
|
-
"extra-high",
|
|
8
13
|
"extra high",
|
|
9
14
|
"extrahigh",
|
|
10
15
|
"xhigh",
|
|
@@ -29,10 +34,11 @@ export function normalizeThinkingTimeLevel(value) {
|
|
|
29
34
|
case "extended":
|
|
30
35
|
case "high":
|
|
31
36
|
return "extended";
|
|
32
|
-
case "heavy":
|
|
33
37
|
case "extra-high":
|
|
34
38
|
case "extrahigh":
|
|
35
39
|
case "xhigh":
|
|
40
|
+
return "extra-high";
|
|
41
|
+
case "heavy":
|
|
36
42
|
return "heavy";
|
|
37
43
|
default:
|
|
38
44
|
return null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import { createWriteStream, mkdirSync } from "node:fs";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
4
5
|
import net from "node:net";
|
|
5
6
|
import { DEFAULT_MODEL } from "./oracle/config.js";
|
|
6
7
|
import { formatElapsed } from "./oracle/format.js";
|
|
@@ -57,6 +58,20 @@ function sessionDir(id) {
|
|
|
57
58
|
function metaPath(id) {
|
|
58
59
|
return path.join(sessionDir(id), METADATA_FILENAME);
|
|
59
60
|
}
|
|
61
|
+
async function writeSessionMetadataFile(sessionId, metadata) {
|
|
62
|
+
const targetPath = metaPath(sessionId);
|
|
63
|
+
const temporaryPath = `${targetPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
64
|
+
try {
|
|
65
|
+
await fs.writeFile(temporaryPath, JSON.stringify(metadata, null, 2), {
|
|
66
|
+
encoding: "utf8",
|
|
67
|
+
mode: 0o600,
|
|
68
|
+
});
|
|
69
|
+
await fs.rename(temporaryPath, targetPath);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await fs.rm(temporaryPath, { force: true }).catch(() => undefined);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
60
75
|
function requestPath(id) {
|
|
61
76
|
return path.join(sessionDir(id), LEGACY_REQUEST_FILENAME);
|
|
62
77
|
}
|
|
@@ -193,6 +208,8 @@ export async function initializeSession(options, cwd, notifications, baseSlugOve
|
|
|
193
208
|
maxFileSizeBytes: options.maxFileSizeBytes,
|
|
194
209
|
model: options.model,
|
|
195
210
|
models: modelList,
|
|
211
|
+
reasoningEffort: options.reasoningEffort,
|
|
212
|
+
reasoningMode: options.reasoningMode,
|
|
196
213
|
previousResponseId: options.previousResponseId,
|
|
197
214
|
followupSessionId: options.followupSessionId,
|
|
198
215
|
followupModel: options.followupModel,
|
|
@@ -235,7 +252,7 @@ export async function initializeSession(options, cwd, notifications, baseSlugOve
|
|
|
235
252
|
},
|
|
236
253
|
};
|
|
237
254
|
await ensureDir(modelsDir(sessionId));
|
|
238
|
-
await
|
|
255
|
+
await writeSessionMetadataFile(sessionId, metadata);
|
|
239
256
|
await Promise.all((modelList.length > 0 ? modelList : [metadata.model ?? DEFAULT_MODEL]).map(async (modelName) => {
|
|
240
257
|
const jsonPath = modelJsonPath(sessionId, modelName);
|
|
241
258
|
const logFilePath = modelLogPath(sessionId, modelName);
|
|
@@ -266,7 +283,7 @@ export async function updateSessionMetadata(sessionId, updates) {
|
|
|
266
283
|
(await readLegacySessionMetadata(sessionId, { reconcile: false, persist: false })) ??
|
|
267
284
|
{ id: sessionId };
|
|
268
285
|
const next = { ...existing, ...updates };
|
|
269
|
-
await
|
|
286
|
+
await writeSessionMetadataFile(sessionId, next);
|
|
270
287
|
return next;
|
|
271
288
|
}
|
|
272
289
|
async function readModernSessionMetadata(sessionId, options) {
|
|
@@ -299,8 +316,26 @@ async function readRawSessionMetadata(sessionId) {
|
|
|
299
316
|
(await readLegacySessionMetadata(sessionId, { reconcile: false, persist: false })));
|
|
300
317
|
}
|
|
301
318
|
async function reconcileSessionMetadata(meta, { persist }) {
|
|
302
|
-
|
|
303
|
-
|
|
319
|
+
let current = meta;
|
|
320
|
+
const workerPid = current.lifecycle?.workerPid;
|
|
321
|
+
if (workerPid) {
|
|
322
|
+
if (isProcessAlive(workerPid)) {
|
|
323
|
+
return current;
|
|
324
|
+
}
|
|
325
|
+
current = (await readRawSessionMetadata(current.id)) ?? current;
|
|
326
|
+
if (current.status !== "running") {
|
|
327
|
+
return current;
|
|
328
|
+
}
|
|
329
|
+
if (current.lifecycle?.workerPid && isProcessAlive(current.lifecycle.workerPid)) {
|
|
330
|
+
return current;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const runtimeChecked = await markDeadBrowser(current);
|
|
334
|
+
const reconciled = await markZombie(runtimeChecked);
|
|
335
|
+
if (persist && reconciled !== current) {
|
|
336
|
+
await writeSessionMetadataFile(current.id, reconciled);
|
|
337
|
+
}
|
|
338
|
+
return reconciled;
|
|
304
339
|
}
|
|
305
340
|
function isSessionMetadataRecord(value) {
|
|
306
341
|
return Boolean(value && typeof value.id === "string" && value.status);
|
|
@@ -479,7 +514,7 @@ export async function getSessionPaths(sessionId) {
|
|
|
479
514
|
}
|
|
480
515
|
return { dir, metadata, log, request };
|
|
481
516
|
}
|
|
482
|
-
async function markZombie(meta
|
|
517
|
+
async function markZombie(meta) {
|
|
483
518
|
if (!(await isZombie(meta))) {
|
|
484
519
|
return meta;
|
|
485
520
|
}
|
|
@@ -506,12 +541,9 @@ async function markZombie(meta, { persist }) {
|
|
|
506
541
|
errorMessage: `Session marked as zombie (> ${formatElapsed(maxAgeMs)} stale)`,
|
|
507
542
|
completedAt: new Date().toISOString(),
|
|
508
543
|
};
|
|
509
|
-
if (persist) {
|
|
510
|
-
await fs.writeFile(metaPath(meta.id), JSON.stringify(updated, null, 2), "utf8");
|
|
511
|
-
}
|
|
512
544
|
return updated;
|
|
513
545
|
}
|
|
514
|
-
async function markDeadBrowser(meta
|
|
546
|
+
async function markDeadBrowser(meta) {
|
|
515
547
|
if (meta.status !== "running" || meta.mode !== "browser") {
|
|
516
548
|
return meta;
|
|
517
549
|
}
|
|
@@ -544,9 +576,6 @@ async function markDeadBrowser(meta, { persist }) {
|
|
|
544
576
|
completedAt: new Date().toISOString(),
|
|
545
577
|
response,
|
|
546
578
|
};
|
|
547
|
-
if (persist) {
|
|
548
|
-
await fs.writeFile(metaPath(meta.id), JSON.stringify(updated, null, 2), "utf8");
|
|
549
|
-
}
|
|
550
579
|
return updated;
|
|
551
580
|
}
|
|
552
581
|
async function isZombie(meta) {
|
|
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.17.1",
|
|
4
4
|
"description": "CLI wrapper around OpenAI Responses API with GPT-5.6 Sol, GPT-5.6, 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",
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
61
|
-
"@google/genai": "^2.
|
|
61
|
+
"@google/genai": "^2.15.0",
|
|
62
62
|
"@google/generative-ai": "^0.24.1",
|
|
63
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
64
|
-
"@steipete/sweet-cookie": "^0.4.
|
|
65
|
-
"chalk": "^
|
|
63
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
64
|
+
"@steipete/sweet-cookie": "^0.4.1",
|
|
65
|
+
"chalk": "^6.0.0",
|
|
66
66
|
"chrome-launcher": "^1.2.1",
|
|
67
67
|
"chrome-remote-interface": "^0.34.0",
|
|
68
68
|
"clipboardy": "^5.3.2",
|
|
@@ -73,28 +73,28 @@
|
|
|
73
73
|
"inquirer": "14.0.2",
|
|
74
74
|
"json5": "^2.2.3",
|
|
75
75
|
"kleur": "^4.1.5",
|
|
76
|
-
"markdansi": "0.3.
|
|
77
|
-
"openai": "^
|
|
76
|
+
"markdansi": "0.3.3",
|
|
77
|
+
"openai": "^7.4.0",
|
|
78
78
|
"osc-progress": "^0.3.2",
|
|
79
79
|
"qs": "^6.15.3",
|
|
80
|
-
"shiki": "^4.
|
|
80
|
+
"shiki": "^4.4.2",
|
|
81
81
|
"toasted-notifier": "^10.1.0",
|
|
82
|
-
"tokentally": "^0.1.
|
|
82
|
+
"tokentally": "^0.1.3",
|
|
83
83
|
"zod": "^4.4.3"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
87
87
|
"@types/chrome-remote-interface": "^0.34.0",
|
|
88
88
|
"@types/inquirer": "^9.0.10",
|
|
89
|
-
"@types/node": "^26.1.
|
|
89
|
+
"@types/node": "^26.1.2",
|
|
90
90
|
"@vitest/coverage-v8": "4.1.10",
|
|
91
|
-
"devtools-protocol": "0.0.
|
|
92
|
-
"es-toolkit": "^1.
|
|
91
|
+
"devtools-protocol": "0.0.1673900",
|
|
92
|
+
"es-toolkit": "^1.50.0",
|
|
93
93
|
"esbuild": "^0.28.1",
|
|
94
|
-
"oxfmt": "0.
|
|
95
|
-
"oxlint": "^1.
|
|
96
|
-
"puppeteer-core": "^25.
|
|
97
|
-
"tsx": "^4.23.
|
|
94
|
+
"oxfmt": "0.62.0",
|
|
95
|
+
"oxlint": "^1.77.0",
|
|
96
|
+
"puppeteer-core": "^25.5.0",
|
|
97
|
+
"tsx": "^4.23.7",
|
|
98
98
|
"typescript": "^7.0.2",
|
|
99
99
|
"vitest": "^4.1.10"
|
|
100
100
|
},
|
|
@@ -109,5 +109,5 @@
|
|
|
109
109
|
"engines": {
|
|
110
110
|
"node": ">=24"
|
|
111
111
|
},
|
|
112
|
-
"packageManager": "pnpm@10.
|
|
112
|
+
"packageManager": "pnpm@10.34.5"
|
|
113
113
|
}
|
|
Binary file
|
|
Binary file
|