@steipete/oracle 0.5.1 → 0.5.2
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/.DS_Store +0 -0
- package/dist/src/browser/actions/assistantResponse.js +7 -3
- package/dist/src/browser/actions/attachments.js +24 -0
- package/dist/src/browser/actions/domEvents.js +19 -0
- package/dist/src/browser/actions/modelSelection.js +6 -9
- package/dist/src/browser/actions/promptComposer.js +10 -15
- package/dist/src/browser/actions/remoteFileTransfer.js +2 -0
- package/dist/src/cli/browserDefaults.js +15 -11
- package/dist/src/cli/tui/index.js +11 -7
- package/package.json +15 -16
package/dist/.DS_Store
CHANGED
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ANSWER_SELECTORS, ASSISTANT_ROLE_SELECTOR, CONVERSATION_TURN_SELECTOR, COPY_BUTTON_SELECTOR, FINISHED_ACTIONS_SELECTOR, STOP_BUTTON_SELECTOR, } from '../constants.js';
|
|
2
2
|
import { delay } from '../utils.js';
|
|
3
3
|
import { logDomFailure, logConversationSnapshot, buildConversationDebugExpression } from '../domDebug.js';
|
|
4
|
+
import { buildClickDispatcher } from './domEvents.js';
|
|
4
5
|
const ASSISTANT_POLL_TIMEOUT_ERROR = 'assistant-response-watchdog-timeout';
|
|
5
6
|
export async function waitForAssistantResponse(Runtime, timeoutMs, logger) {
|
|
6
7
|
logger('Waiting for ChatGPT response');
|
|
@@ -257,6 +258,7 @@ function buildAssistantSnapshotExpression() {
|
|
|
257
258
|
function buildResponseObserverExpression(timeoutMs) {
|
|
258
259
|
const selectorsLiteral = JSON.stringify(ANSWER_SELECTORS);
|
|
259
260
|
return `(() => {
|
|
261
|
+
${buildClickDispatcher()}
|
|
260
262
|
const SELECTORS = ${selectorsLiteral};
|
|
261
263
|
const STOP_SELECTOR = '${STOP_BUTTON_SELECTOR}';
|
|
262
264
|
const FINISHED_SELECTOR = '${FINISHED_ACTIONS_SELECTOR}';
|
|
@@ -293,7 +295,7 @@ function buildResponseObserverExpression(timeoutMs) {
|
|
|
293
295
|
if (ariaLabel.toLowerCase().includes('stop')) {
|
|
294
296
|
return;
|
|
295
297
|
}
|
|
296
|
-
stop
|
|
298
|
+
dispatchClickSequence(stop);
|
|
297
299
|
}, 500);
|
|
298
300
|
setTimeout(() => {
|
|
299
301
|
if (stopInterval) {
|
|
@@ -340,6 +342,7 @@ function buildAssistantExtractor(functionName) {
|
|
|
340
342
|
const conversationLiteral = JSON.stringify(CONVERSATION_TURN_SELECTOR);
|
|
341
343
|
const assistantLiteral = JSON.stringify(ASSISTANT_ROLE_SELECTOR);
|
|
342
344
|
return `const ${functionName} = () => {
|
|
345
|
+
${buildClickDispatcher()}
|
|
343
346
|
const CONVERSATION_SELECTOR = ${conversationLiteral};
|
|
344
347
|
const ASSISTANT_SELECTOR = ${assistantLiteral};
|
|
345
348
|
const isAssistantTurn = (node) => {
|
|
@@ -367,7 +370,7 @@ function buildAssistantExtractor(functionName) {
|
|
|
367
370
|
testid.includes('markdown') ||
|
|
368
371
|
testid.includes('toggle')
|
|
369
372
|
) {
|
|
370
|
-
button
|
|
373
|
+
dispatchClickSequence(button);
|
|
371
374
|
}
|
|
372
375
|
}
|
|
373
376
|
};
|
|
@@ -397,6 +400,7 @@ function buildAssistantExtractor(functionName) {
|
|
|
397
400
|
}
|
|
398
401
|
function buildCopyExpression(meta) {
|
|
399
402
|
return `(() => {
|
|
403
|
+
${buildClickDispatcher()}
|
|
400
404
|
const BUTTON_SELECTOR = '${COPY_BUTTON_SELECTOR}';
|
|
401
405
|
const TIMEOUT_MS = 5000;
|
|
402
406
|
|
|
@@ -498,7 +502,7 @@ function buildCopyExpression(meta) {
|
|
|
498
502
|
|
|
499
503
|
button.addEventListener('copy', handleCopy, true);
|
|
500
504
|
button.scrollIntoView({ block: 'center', behavior: 'instant' });
|
|
501
|
-
button
|
|
505
|
+
dispatchClickSequence(button);
|
|
502
506
|
pollId = setInterval(() => {
|
|
503
507
|
const payload = readIntercepted();
|
|
504
508
|
if (payload.success) {
|
|
@@ -28,6 +28,7 @@ export async function uploadAttachmentFile(deps, attachment, logger) {
|
|
|
28
28
|
await logDomFailure(runtime, logger, 'file-upload');
|
|
29
29
|
throw new Error('Attachment did not register with the ChatGPT composer in time.');
|
|
30
30
|
}
|
|
31
|
+
await waitForAttachmentVisible(runtime, expectedName, 10_000, logger);
|
|
31
32
|
logger('Attachment queued');
|
|
32
33
|
}
|
|
33
34
|
export async function waitForAttachmentCompletion(Runtime, timeoutMs, logger) {
|
|
@@ -83,6 +84,29 @@ export async function waitForAttachmentCompletion(Runtime, timeoutMs, logger) {
|
|
|
83
84
|
await logDomFailure(Runtime, logger ?? (() => { }), 'file-upload-timeout');
|
|
84
85
|
throw new Error('Attachments did not finish uploading before timeout.');
|
|
85
86
|
}
|
|
87
|
+
export async function waitForAttachmentVisible(Runtime, expectedName, timeoutMs, logger) {
|
|
88
|
+
const deadline = Date.now() + Math.min(timeoutMs, 2_000);
|
|
89
|
+
const expression = `(() => {
|
|
90
|
+
const expected = ${JSON.stringify(expectedName)};
|
|
91
|
+
const turns = Array.from(document.querySelectorAll('article[data-testid^="conversation-turn"]'));
|
|
92
|
+
const userTurns = turns.filter((node) => node.querySelector('[data-message-author-role="user"]'));
|
|
93
|
+
const lastUser = userTurns[userTurns.length - 1];
|
|
94
|
+
if (!lastUser) return { found: false, userTurns: userTurns.length };
|
|
95
|
+
const chips = Array.from(lastUser.querySelectorAll('a, div')).some((el) => (el.textContent || '').includes(expected));
|
|
96
|
+
return { found: chips, userTurns: userTurns.length };
|
|
97
|
+
})()`;
|
|
98
|
+
while (Date.now() < deadline) {
|
|
99
|
+
const { result } = await Runtime.evaluate({ expression, returnByValue: true });
|
|
100
|
+
const value = result?.value;
|
|
101
|
+
if (value?.found) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
await delay(200);
|
|
105
|
+
}
|
|
106
|
+
logger?.('Attachment not visible in composer; giving up.');
|
|
107
|
+
await logDomFailure(Runtime, logger ?? (() => { }), 'attachment-visible');
|
|
108
|
+
throw new Error('Attachment did not appear in ChatGPT composer.');
|
|
109
|
+
}
|
|
86
110
|
async function waitForAttachmentSelection(Runtime, expectedName, timeoutMs) {
|
|
87
111
|
const deadline = Date.now() + timeoutMs;
|
|
88
112
|
const expression = `(() => {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const CLICK_TYPES = ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click'];
|
|
2
|
+
export function buildClickDispatcher(functionName = 'dispatchClickSequence') {
|
|
3
|
+
const typesLiteral = JSON.stringify(CLICK_TYPES);
|
|
4
|
+
return `function ${functionName}(target){
|
|
5
|
+
if(!target || !(target instanceof EventTarget)) return false;
|
|
6
|
+
const types = ${typesLiteral};
|
|
7
|
+
for (const type of types) {
|
|
8
|
+
const common = { bubbles: true, cancelable: true, view: window };
|
|
9
|
+
let event;
|
|
10
|
+
if (type.startsWith('pointer') && 'PointerEvent' in window) {
|
|
11
|
+
event = new PointerEvent(type, { ...common, pointerId: 1, pointerType: 'mouse' });
|
|
12
|
+
} else {
|
|
13
|
+
event = new MouseEvent(type, common);
|
|
14
|
+
}
|
|
15
|
+
target.dispatchEvent(event);
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}`;
|
|
19
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MENU_CONTAINER_SELECTOR, MENU_ITEM_SELECTOR, MODEL_BUTTON_SELECTOR, } from '../constants.js';
|
|
2
2
|
import { logDomFailure } from '../domDebug.js';
|
|
3
|
+
import { buildClickDispatcher } from './domEvents.js';
|
|
3
4
|
export async function ensureModelSelection(Runtime, desiredModel, logger) {
|
|
4
5
|
const outcome = await Runtime.evaluate({
|
|
5
6
|
expression: buildModelSelectionExpression(desiredModel),
|
|
@@ -37,6 +38,7 @@ function buildModelSelectionExpression(targetModel) {
|
|
|
37
38
|
const menuContainerLiteral = JSON.stringify(MENU_CONTAINER_SELECTOR);
|
|
38
39
|
const menuItemLiteral = JSON.stringify(MENU_ITEM_SELECTOR);
|
|
39
40
|
return `(() => {
|
|
41
|
+
${buildClickDispatcher()}
|
|
40
42
|
// Capture the selectors and matcher literals up front so the browser expression stays pure.
|
|
41
43
|
const BUTTON_SELECTOR = '${MODEL_BUTTON_SELECTOR}';
|
|
42
44
|
const LABEL_TOKENS = ${labelLiteral};
|
|
@@ -69,14 +71,9 @@ function buildModelSelectionExpression(targetModel) {
|
|
|
69
71
|
|
|
70
72
|
let lastPointerClick = 0;
|
|
71
73
|
const pointerClick = () => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const click = new MouseEvent('click', { bubbles: true });
|
|
76
|
-
button.dispatchEvent(down);
|
|
77
|
-
button.dispatchEvent(up);
|
|
78
|
-
button.dispatchEvent(click);
|
|
79
|
-
lastPointerClick = performance.now();
|
|
74
|
+
if (dispatchClickSequence(button)) {
|
|
75
|
+
lastPointerClick = performance.now();
|
|
76
|
+
}
|
|
80
77
|
};
|
|
81
78
|
|
|
82
79
|
const getOptionLabel = (node) => node?.textContent?.trim() ?? '';
|
|
@@ -188,7 +185,7 @@ function buildModelSelectionExpression(targetModel) {
|
|
|
188
185
|
resolve({ status: 'already-selected', label: match.label });
|
|
189
186
|
return;
|
|
190
187
|
}
|
|
191
|
-
match.node
|
|
188
|
+
dispatchClickSequence(match.node);
|
|
192
189
|
resolve({ status: 'switched', label: match.label });
|
|
193
190
|
return;
|
|
194
191
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { INPUT_SELECTORS, PROMPT_PRIMARY_SELECTOR, PROMPT_FALLBACK_SELECTOR, SEND_BUTTON_SELECTORS, CONVERSATION_TURN_SELECTOR, } from '../constants.js';
|
|
2
2
|
import { delay } from '../utils.js';
|
|
3
3
|
import { logDomFailure } from '../domDebug.js';
|
|
4
|
+
import { buildClickDispatcher } from './domEvents.js';
|
|
4
5
|
const ENTER_KEY_EVENT = {
|
|
5
6
|
key: 'Enter',
|
|
6
7
|
code: 'Enter',
|
|
@@ -13,20 +14,13 @@ export async function submitPrompt(deps, prompt, logger) {
|
|
|
13
14
|
const encodedPrompt = JSON.stringify(prompt);
|
|
14
15
|
const focusResult = await runtime.evaluate({
|
|
15
16
|
expression: `(() => {
|
|
17
|
+
${buildClickDispatcher()}
|
|
16
18
|
const SELECTORS = ${JSON.stringify(INPUT_SELECTORS)};
|
|
17
|
-
const dispatchPointer = (target) => {
|
|
18
|
-
if (!(target instanceof HTMLElement)) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
for (const type of ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click']) {
|
|
22
|
-
target.dispatchEvent(new MouseEvent(type, { bubbles: true, cancelable: true, view: window }));
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
19
|
const focusNode = (node) => {
|
|
26
20
|
if (!node) {
|
|
27
21
|
return false;
|
|
28
22
|
}
|
|
29
|
-
|
|
23
|
+
dispatchClickSequence(node);
|
|
30
24
|
if (typeof node.focus === 'function') {
|
|
31
25
|
node.focus();
|
|
32
26
|
}
|
|
@@ -89,6 +83,8 @@ export async function submitPrompt(deps, prompt, logger) {
|
|
|
89
83
|
const editor = document.querySelector(${primarySelectorLiteral});
|
|
90
84
|
if (editor) {
|
|
91
85
|
editor.textContent = ${encodedPrompt};
|
|
86
|
+
// Nudge ProseMirror to register the textContent write so its state/send-button updates
|
|
87
|
+
editor.dispatchEvent(new InputEvent('input', { bubbles: true, data: ${encodedPrompt}, inputType: 'insertFromPaste' }));
|
|
92
88
|
}
|
|
93
89
|
})()`,
|
|
94
90
|
});
|
|
@@ -115,6 +111,7 @@ export async function submitPrompt(deps, prompt, logger) {
|
|
|
115
111
|
}
|
|
116
112
|
async function attemptSendButton(Runtime) {
|
|
117
113
|
const script = `(() => {
|
|
114
|
+
${buildClickDispatcher()}
|
|
118
115
|
const selectors = ${JSON.stringify(SEND_BUTTON_SELECTORS)};
|
|
119
116
|
let button = null;
|
|
120
117
|
for (const selector of selectors) {
|
|
@@ -132,7 +129,8 @@ async function attemptSendButton(Runtime) {
|
|
|
132
129
|
style.pointerEvents === 'none' ||
|
|
133
130
|
style.display === 'none';
|
|
134
131
|
if (disabled) return 'disabled';
|
|
135
|
-
|
|
132
|
+
// Use unified pointer/mouse sequence to satisfy React handlers.
|
|
133
|
+
dispatchClickSequence(button);
|
|
136
134
|
return 'clicked';
|
|
137
135
|
})()`;
|
|
138
136
|
const deadline = Date.now() + 2_000;
|
|
@@ -150,6 +148,7 @@ async function attemptSendButton(Runtime) {
|
|
|
150
148
|
}
|
|
151
149
|
async function clickAnswerNowIfPresent(Runtime, logger) {
|
|
152
150
|
const script = `(() => {
|
|
151
|
+
${buildClickDispatcher()}
|
|
153
152
|
const matchesText = (el) => (el?.textContent || '').trim().toLowerCase() === 'answer now';
|
|
154
153
|
const candidate = Array.from(document.querySelectorAll('button,span')).find(matchesText);
|
|
155
154
|
if (!candidate) return 'missing';
|
|
@@ -161,11 +160,7 @@ async function clickAnswerNowIfPresent(Runtime, logger) {
|
|
|
161
160
|
style.pointerEvents === 'none' ||
|
|
162
161
|
style.display === 'none';
|
|
163
162
|
if (disabled) return 'disabled';
|
|
164
|
-
(button)
|
|
165
|
-
(button).dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }));
|
|
166
|
-
(button).dispatchEvent(new MouseEvent('pointerup', { bubbles: true, cancelable: true }));
|
|
167
|
-
(button).dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true }));
|
|
168
|
-
(button).dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
|
|
163
|
+
dispatchClickSequence(button);
|
|
169
164
|
return 'clicked';
|
|
170
165
|
})()`;
|
|
171
166
|
const deadline = Date.now() + 3_000;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { FILE_INPUT_SELECTORS } from '../constants.js';
|
|
4
|
+
import { waitForAttachmentVisible } from './attachments.js';
|
|
4
5
|
import { delay } from '../utils.js';
|
|
5
6
|
import { logDomFailure } from '../domDebug.js';
|
|
6
7
|
/**
|
|
@@ -132,6 +133,7 @@ export async function uploadAttachmentViaDataTransfer(deps, attachment, logger)
|
|
|
132
133
|
logger(`File transferred: ${uploadResult.fileName} (${uploadResult.size} bytes)`);
|
|
133
134
|
// Give ChatGPT a moment to process the file
|
|
134
135
|
await delay(500);
|
|
136
|
+
await waitForAttachmentVisible(runtime, fileName, 10_000, logger);
|
|
135
137
|
logger('Attachment queued');
|
|
136
138
|
}
|
|
137
139
|
function guessMimeType(fileName) {
|
|
@@ -3,39 +3,43 @@ export function applyBrowserDefaultsFromConfig(options, config, getSource) {
|
|
|
3
3
|
const browser = config.browser;
|
|
4
4
|
if (!browser)
|
|
5
5
|
return;
|
|
6
|
+
const isUnset = (key) => {
|
|
7
|
+
const source = getSource(key);
|
|
8
|
+
return source === undefined || source === 'default';
|
|
9
|
+
};
|
|
6
10
|
const configuredChatgptUrl = browser.chatgptUrl ?? browser.url;
|
|
7
11
|
const cliChatgptSet = options.chatgptUrl !== undefined || options.browserUrl !== undefined;
|
|
8
|
-
if ((
|
|
12
|
+
if (isUnset('chatgptUrl') && !cliChatgptSet && configuredChatgptUrl !== undefined) {
|
|
9
13
|
options.chatgptUrl = normalizeChatgptUrl(configuredChatgptUrl ?? '', CHATGPT_URL);
|
|
10
14
|
}
|
|
11
|
-
if (
|
|
15
|
+
if (isUnset('browserChromeProfile') && browser.chromeProfile !== undefined) {
|
|
12
16
|
options.browserChromeProfile = browser.chromeProfile ?? undefined;
|
|
13
17
|
}
|
|
14
|
-
if (
|
|
18
|
+
if (isUnset('browserChromePath') && browser.chromePath !== undefined) {
|
|
15
19
|
options.browserChromePath = browser.chromePath ?? undefined;
|
|
16
20
|
}
|
|
17
|
-
if (
|
|
21
|
+
if (isUnset('browserCookiePath') && browser.chromeCookiePath !== undefined) {
|
|
18
22
|
options.browserCookiePath = browser.chromeCookiePath ?? undefined;
|
|
19
23
|
}
|
|
20
|
-
if ((
|
|
24
|
+
if (isUnset('browserUrl') && options.browserUrl === undefined && browser.url !== undefined) {
|
|
21
25
|
options.browserUrl = browser.url;
|
|
22
26
|
}
|
|
23
|
-
if (
|
|
27
|
+
if (isUnset('browserTimeout') && typeof browser.timeoutMs === 'number') {
|
|
24
28
|
options.browserTimeout = String(browser.timeoutMs);
|
|
25
29
|
}
|
|
26
|
-
if (
|
|
30
|
+
if (isUnset('browserPort') && typeof browser.debugPort === 'number') {
|
|
27
31
|
options.browserPort = browser.debugPort;
|
|
28
32
|
}
|
|
29
|
-
if (
|
|
33
|
+
if (isUnset('browserInputTimeout') && typeof browser.inputTimeoutMs === 'number') {
|
|
30
34
|
options.browserInputTimeout = String(browser.inputTimeoutMs);
|
|
31
35
|
}
|
|
32
|
-
if (
|
|
36
|
+
if (isUnset('browserHeadless') && browser.headless !== undefined) {
|
|
33
37
|
options.browserHeadless = browser.headless;
|
|
34
38
|
}
|
|
35
|
-
if (
|
|
39
|
+
if (isUnset('browserHideWindow') && browser.hideWindow !== undefined) {
|
|
36
40
|
options.browserHideWindow = browser.hideWindow;
|
|
37
41
|
}
|
|
38
|
-
if (
|
|
42
|
+
if (isUnset('browserKeepBrowser') && browser.keepBrowser !== undefined) {
|
|
39
43
|
options.browserKeepBrowser = browser.keepBrowser;
|
|
40
44
|
}
|
|
41
45
|
}
|
|
@@ -66,7 +66,7 @@ export async function launchTui({ version, printIntro = true }) {
|
|
|
66
66
|
const prompt = inquirer.prompt([
|
|
67
67
|
{
|
|
68
68
|
name: 'selection',
|
|
69
|
-
type: '
|
|
69
|
+
type: 'select',
|
|
70
70
|
message: 'Select a session or action',
|
|
71
71
|
choices,
|
|
72
72
|
pageSize: 16,
|
|
@@ -80,6 +80,9 @@ export async function launchTui({ version, printIntro = true }) {
|
|
|
80
80
|
resolve('__reset__');
|
|
81
81
|
});
|
|
82
82
|
});
|
|
83
|
+
if (process.env.ORACLE_DEBUG_TUI === '1') {
|
|
84
|
+
console.error(`[tui] selection=${JSON.stringify(selection)}`);
|
|
85
|
+
}
|
|
83
86
|
if (selection === '__exit__') {
|
|
84
87
|
console.log(chalk.green('🧿 Closing the book. See you next prompt.'));
|
|
85
88
|
return;
|
|
@@ -156,7 +159,7 @@ async function showSessionDetail(sessionId) {
|
|
|
156
159
|
const { next } = await inquirer.prompt([
|
|
157
160
|
{
|
|
158
161
|
name: 'next',
|
|
159
|
-
type: '
|
|
162
|
+
type: 'select',
|
|
160
163
|
message: 'Actions',
|
|
161
164
|
choices: actions,
|
|
162
165
|
},
|
|
@@ -235,7 +238,7 @@ async function askOracleFlow(version, userConfig) {
|
|
|
235
238
|
const hasApiKey = Boolean(process.env.OPENAI_API_KEY);
|
|
236
239
|
const initialMode = hasApiKey ? 'api' : 'browser';
|
|
237
240
|
const preferredMode = userConfig.engine ?? initialMode;
|
|
238
|
-
const
|
|
241
|
+
const wizardQuestions = [
|
|
239
242
|
{
|
|
240
243
|
name: 'promptInput',
|
|
241
244
|
type: 'input',
|
|
@@ -245,7 +248,7 @@ async function askOracleFlow(version, userConfig) {
|
|
|
245
248
|
? [
|
|
246
249
|
{
|
|
247
250
|
name: 'mode',
|
|
248
|
-
type: '
|
|
251
|
+
type: 'select',
|
|
249
252
|
message: 'Engine',
|
|
250
253
|
default: preferredMode,
|
|
251
254
|
choices: [
|
|
@@ -257,7 +260,7 @@ async function askOracleFlow(version, userConfig) {
|
|
|
257
260
|
: [
|
|
258
261
|
{
|
|
259
262
|
name: 'mode',
|
|
260
|
-
type: '
|
|
263
|
+
type: 'select',
|
|
261
264
|
message: 'Engine',
|
|
262
265
|
default: preferredMode,
|
|
263
266
|
choices: [{ name: 'Browser', value: 'browser' }],
|
|
@@ -270,7 +273,7 @@ async function askOracleFlow(version, userConfig) {
|
|
|
270
273
|
},
|
|
271
274
|
{
|
|
272
275
|
name: 'model',
|
|
273
|
-
type: '
|
|
276
|
+
type: 'select',
|
|
274
277
|
message: 'Model',
|
|
275
278
|
default: DEFAULT_MODEL,
|
|
276
279
|
choices: modelChoices,
|
|
@@ -323,7 +326,8 @@ async function askOracleFlow(version, userConfig) {
|
|
|
323
326
|
default: false,
|
|
324
327
|
when: (ans) => ans.mode === 'browser',
|
|
325
328
|
},
|
|
326
|
-
]
|
|
329
|
+
];
|
|
330
|
+
const answers = await inquirer.prompt(wizardQuestions);
|
|
327
331
|
const mode = (answers.mode ?? initialMode);
|
|
328
332
|
const prompt = await resolvePromptInput(answers.promptInput);
|
|
329
333
|
if (!prompt.trim()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steipete/oracle",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
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",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"homepage": "https://github.com/steipete/oracle#readme",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
48
|
-
"@google/genai": "^1.
|
|
48
|
+
"@google/genai": "^1.31.0",
|
|
49
49
|
"@google/generative-ai": "^0.24.1",
|
|
50
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
51
51
|
"chalk": "^5.6.2",
|
|
52
52
|
"chrome-cookies-secure": "3.0.0",
|
|
53
53
|
"chrome-launcher": "^1.2.1",
|
|
@@ -57,33 +57,32 @@
|
|
|
57
57
|
"dotenv": "^17.2.3",
|
|
58
58
|
"fast-glob": "^3.3.3",
|
|
59
59
|
"gpt-tokenizer": "^3.4.0",
|
|
60
|
-
"inquirer": "
|
|
60
|
+
"inquirer": "13.0.2",
|
|
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.
|
|
66
|
-
"shiki": "^3.
|
|
65
|
+
"openai": "^6.10.0",
|
|
66
|
+
"shiki": "^3.19.0",
|
|
67
67
|
"sqlite3": "^5.1.7",
|
|
68
68
|
"toasted-notifier": "^10.1.0",
|
|
69
|
-
"zod": "
|
|
69
|
+
"zod": "^4.1.13"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
73
|
-
"@biomejs/biome": "^2.3.
|
|
73
|
+
"@biomejs/biome": "^2.3.8",
|
|
74
74
|
"@cdktf/node-pty-prebuilt-multiarch": "0.10.2",
|
|
75
|
-
"@types/chrome-remote-interface": "^0.
|
|
75
|
+
"@types/chrome-remote-interface": "^0.33.0",
|
|
76
76
|
"@types/inquirer": "^9.0.9",
|
|
77
|
-
"@types/json5": "^2.2.0",
|
|
78
77
|
"@types/node": "^24.10.1",
|
|
79
|
-
"@vitest/coverage-v8": "4.0.
|
|
80
|
-
"devtools-protocol": "^0.0.
|
|
78
|
+
"@vitest/coverage-v8": "4.0.15",
|
|
79
|
+
"devtools-protocol": "^0.0.1551306",
|
|
81
80
|
"es-toolkit": "^1.42.0",
|
|
82
|
-
"esbuild": "^0.27.
|
|
83
|
-
"puppeteer-core": "^24.
|
|
84
|
-
"tsx": "^4.
|
|
81
|
+
"esbuild": "^0.27.1",
|
|
82
|
+
"puppeteer-core": "^24.32.0",
|
|
83
|
+
"tsx": "^4.21.0",
|
|
85
84
|
"typescript": "^5.9.3",
|
|
86
|
-
"vitest": "^4.0.
|
|
85
|
+
"vitest": "^4.0.15"
|
|
87
86
|
},
|
|
88
87
|
"optionalDependencies": {
|
|
89
88
|
"win-dpapi": "npm:@primno/dpapi@2.0.1"
|