@steipete/oracle 0.8.6 → 0.10.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/LICENSE +1 -1
- package/README.md +130 -45
- package/dist/bin/oracle-cli.js +613 -379
- package/dist/bin/oracle-mcp.js +2 -2
- package/dist/bin/oracle.js +165 -279
- package/dist/scripts/agent-send.js +31 -31
- package/dist/scripts/check.js +6 -6
- package/dist/scripts/debug/extract-chatgpt-response.js +10 -10
- package/dist/scripts/docs-list.js +30 -30
- package/dist/scripts/git-policy.js +25 -23
- package/dist/scripts/run-cli.js +8 -8
- package/dist/scripts/runner.js +203 -195
- package/dist/scripts/test-browser.js +21 -18
- package/dist/scripts/test-remote-chrome.js +20 -20
- package/dist/src/bridge/connection.js +18 -18
- package/dist/src/bridge/userConfigFile.js +7 -7
- package/dist/src/browser/actions/assistantResponse.js +149 -101
- package/dist/src/browser/actions/attachmentDataTransfer.js +49 -47
- package/dist/src/browser/actions/attachments.js +246 -150
- package/dist/src/browser/actions/domEvents.js +2 -2
- package/dist/src/browser/actions/modelSelection.js +314 -104
- package/dist/src/browser/actions/navigation.js +161 -136
- package/dist/src/browser/actions/promptComposer.js +100 -64
- package/dist/src/browser/actions/remoteFileTransfer.js +10 -10
- package/dist/src/browser/actions/thinkingTime.js +207 -110
- package/dist/src/browser/chromeLifecycle.js +62 -60
- package/dist/src/browser/config.js +34 -15
- package/dist/src/browser/constants.js +17 -12
- package/dist/src/browser/cookies.js +19 -19
- package/dist/src/browser/detect.js +62 -62
- package/dist/src/browser/domDebug.js +1 -1
- package/dist/src/browser/index.js +452 -303
- package/dist/src/browser/modelStrategy.js +1 -1
- package/dist/src/browser/pageActions.js +5 -5
- package/dist/src/browser/policies.js +16 -13
- package/dist/src/browser/profileState.js +44 -39
- package/dist/src/browser/prompt.js +72 -42
- package/dist/src/browser/promptSummary.js +5 -5
- package/dist/src/browser/providerDomFlow.js +17 -0
- package/dist/src/browser/providers/chatgptDomProvider.js +49 -0
- package/dist/src/browser/providers/geminiDeepThinkDomProvider.js +254 -0
- package/dist/src/browser/providers/index.js +2 -0
- package/dist/src/browser/reattach.js +67 -34
- package/dist/src/browser/reattachHelpers.js +31 -26
- package/dist/src/browser/sessionRunner.js +37 -25
- package/dist/src/browser/utils.js +9 -9
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/bridge/claudeConfig.js +16 -16
- package/dist/src/cli/bridge/client.js +28 -20
- package/dist/src/cli/bridge/codexConfig.js +16 -16
- package/dist/src/cli/bridge/doctor.js +47 -39
- package/dist/src/cli/bridge/host.js +58 -56
- package/dist/src/cli/browserConfig.js +65 -45
- package/dist/src/cli/browserDefaults.js +27 -26
- package/dist/src/cli/bundleWarnings.js +1 -1
- package/dist/src/cli/clipboard.js +11 -2
- package/dist/src/cli/detach.js +7 -4
- package/dist/src/cli/dryRun.js +29 -25
- package/dist/src/cli/duplicatePromptGuard.js +3 -3
- package/dist/src/cli/engine.js +9 -9
- package/dist/src/cli/errorUtils.js +1 -1
- package/dist/src/cli/fileSize.js +11 -0
- package/dist/src/cli/format.js +2 -2
- package/dist/src/cli/help.js +28 -28
- package/dist/src/cli/hiddenAliases.js +3 -3
- package/dist/src/cli/markdownBundle.js +12 -8
- package/dist/src/cli/markdownRenderer.js +15 -15
- package/dist/src/cli/notifier.js +77 -67
- package/dist/src/cli/options.js +145 -87
- package/dist/src/cli/oscUtils.js +1 -1
- package/dist/src/cli/promptRequirement.js +2 -2
- package/dist/src/cli/renderOutput.js +1 -1
- package/dist/src/cli/rootAlias.js +1 -1
- package/dist/src/cli/runOptions.js +37 -25
- package/dist/src/cli/sessionCommand.js +31 -21
- package/dist/src/cli/sessionDisplay.js +182 -79
- package/dist/src/cli/sessionLineage.js +60 -0
- package/dist/src/cli/sessionRunner.js +118 -90
- package/dist/src/cli/sessionTable.js +28 -24
- package/dist/src/cli/stdin.js +22 -0
- package/dist/src/cli/tagline.js +121 -124
- package/dist/src/cli/tui/index.js +140 -127
- package/dist/src/cli/writeOutputPath.js +5 -5
- package/dist/src/config.js +7 -7
- package/dist/src/gemini-web/browserSessionManager.js +80 -0
- package/dist/src/gemini-web/client.js +81 -64
- package/dist/src/gemini-web/executionMode.js +16 -0
- package/dist/src/gemini-web/executor.js +327 -169
- package/dist/src/gemini-web/index.js +1 -1
- package/dist/src/mcp/server.js +16 -12
- package/dist/src/mcp/tools/consult.js +81 -64
- package/dist/src/mcp/tools/sessionResources.js +12 -12
- package/dist/src/mcp/tools/sessions.js +26 -17
- package/dist/src/mcp/types.js +5 -5
- package/dist/src/mcp/utils.js +15 -7
- package/dist/src/oracle/background.js +15 -15
- package/dist/src/oracle/claude.js +53 -25
- package/dist/src/oracle/client.js +84 -46
- package/dist/src/oracle/config.js +124 -58
- package/dist/src/oracle/errors.js +38 -38
- package/dist/src/oracle/files.js +69 -45
- package/dist/src/oracle/finishLine.js +10 -8
- package/dist/src/oracle/format.js +3 -3
- package/dist/src/oracle/gemini.js +37 -30
- package/dist/src/oracle/logging.js +7 -7
- package/dist/src/oracle/markdown.js +28 -28
- package/dist/src/oracle/modelResolver.js +16 -16
- package/dist/src/oracle/multiModelRunner.js +12 -12
- package/dist/src/oracle/oscProgress.js +8 -8
- package/dist/src/oracle/promptAssembly.js +6 -3
- package/dist/src/oracle/request.js +23 -15
- package/dist/src/oracle/run.js +172 -140
- package/dist/src/oracle/runUtils.js +8 -5
- package/dist/src/oracle/tokenEstimate.js +6 -6
- package/dist/src/oracle/tokenStats.js +5 -5
- package/dist/src/oracle/tokenStringifier.js +5 -5
- package/dist/src/oracle.js +12 -12
- package/dist/src/oracleHome.js +3 -3
- package/dist/src/remote/client.js +25 -25
- package/dist/src/remote/health.js +20 -20
- package/dist/src/remote/remoteServiceConfig.js +9 -9
- package/dist/src/remote/server.js +129 -118
- package/dist/src/sessionManager.js +81 -75
- package/dist/src/sessionStore.js +3 -3
- package/dist/src/version.js +10 -10
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/dist/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/dist/vendor/oracle-notifier/README.md +2 -0
- package/package.json +69 -65
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/CodeResources +0 -0
- package/vendor/oracle-notifier/OracleNotifier.app/Contents/MacOS/OracleNotifier +0 -0
- package/vendor/oracle-notifier/README.md +2 -0
- package/dist/markdansi/types/index.js +0 -4
- package/dist/oracle/bin/oracle-cli.js +0 -472
- package/dist/oracle/src/browser/actions/assistantResponse.js +0 -471
- package/dist/oracle/src/browser/actions/attachments.js +0 -82
- package/dist/oracle/src/browser/actions/modelSelection.js +0 -190
- package/dist/oracle/src/browser/actions/navigation.js +0 -75
- package/dist/oracle/src/browser/actions/promptComposer.js +0 -167
- package/dist/oracle/src/browser/chromeLifecycle.js +0 -104
- package/dist/oracle/src/browser/config.js +0 -33
- package/dist/oracle/src/browser/constants.js +0 -40
- package/dist/oracle/src/browser/cookies.js +0 -210
- package/dist/oracle/src/browser/domDebug.js +0 -36
- package/dist/oracle/src/browser/index.js +0 -331
- package/dist/oracle/src/browser/pageActions.js +0 -5
- package/dist/oracle/src/browser/prompt.js +0 -88
- package/dist/oracle/src/browser/promptSummary.js +0 -20
- package/dist/oracle/src/browser/sessionRunner.js +0 -80
- package/dist/oracle/src/browser/utils.js +0 -62
- package/dist/oracle/src/browserMode.js +0 -1
- package/dist/oracle/src/cli/browserConfig.js +0 -44
- package/dist/oracle/src/cli/dryRun.js +0 -59
- package/dist/oracle/src/cli/engine.js +0 -17
- package/dist/oracle/src/cli/errorUtils.js +0 -9
- package/dist/oracle/src/cli/help.js +0 -70
- package/dist/oracle/src/cli/markdownRenderer.js +0 -15
- package/dist/oracle/src/cli/options.js +0 -103
- package/dist/oracle/src/cli/promptRequirement.js +0 -14
- package/dist/oracle/src/cli/rootAlias.js +0 -30
- package/dist/oracle/src/cli/sessionCommand.js +0 -77
- package/dist/oracle/src/cli/sessionDisplay.js +0 -270
- package/dist/oracle/src/cli/sessionRunner.js +0 -94
- package/dist/oracle/src/heartbeat.js +0 -43
- package/dist/oracle/src/oracle/client.js +0 -48
- package/dist/oracle/src/oracle/config.js +0 -29
- package/dist/oracle/src/oracle/errors.js +0 -101
- package/dist/oracle/src/oracle/files.js +0 -220
- package/dist/oracle/src/oracle/format.js +0 -33
- package/dist/oracle/src/oracle/fsAdapter.js +0 -7
- package/dist/oracle/src/oracle/oscProgress.js +0 -60
- package/dist/oracle/src/oracle/request.js +0 -48
- package/dist/oracle/src/oracle/run.js +0 -444
- package/dist/oracle/src/oracle/tokenStats.js +0 -39
- package/dist/oracle/src/oracle/types.js +0 -1
- package/dist/oracle/src/oracle.js +0 -9
- package/dist/oracle/src/sessionManager.js +0 -205
- package/dist/oracle/src/version.js +0 -39
- package/dist/scripts/chrome/browser-tools.js +0 -295
- package/dist/src/browser/profileSync.js +0 -141
- /package/dist/{oracle/src/browser/types.js → src/gemini-web/executionClients.js} +0 -0
package/dist/src/cli/options.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { InvalidArgumentError } from
|
|
2
|
-
import { parseDuration } from
|
|
3
|
-
import path from
|
|
4
|
-
import fg from
|
|
5
|
-
import { DEFAULT_MODEL, MODEL_CONFIGS } from
|
|
1
|
+
import { InvalidArgumentError } from "commander";
|
|
2
|
+
import { parseDuration } from "../browserMode.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fg from "fast-glob";
|
|
5
|
+
import { DEFAULT_MODEL, MODEL_CONFIGS } from "../oracle.js";
|
|
6
6
|
export function collectPaths(value, previous = []) {
|
|
7
7
|
if (!value) {
|
|
8
8
|
return previous;
|
|
9
9
|
}
|
|
10
10
|
const nextValues = Array.isArray(value) ? value : [value];
|
|
11
|
-
return previous.concat(nextValues
|
|
11
|
+
return previous.concat(nextValues
|
|
12
|
+
.flatMap((entry) => entry.split(","))
|
|
13
|
+
.map((entry) => entry.trim())
|
|
14
|
+
.filter(Boolean));
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* Merge all path-like CLI inputs (file/include aliases) into a single list, preserving order.
|
|
@@ -29,7 +32,7 @@ export function dedupePathInputs(inputs, { cwd = process.cwd() } = {}) {
|
|
|
29
32
|
if (!raw)
|
|
30
33
|
continue;
|
|
31
34
|
let key = raw;
|
|
32
|
-
if (!raw.startsWith(
|
|
35
|
+
if (!raw.startsWith("!") && !fg.isDynamicPattern(raw)) {
|
|
33
36
|
const absolute = path.isAbsolute(raw) ? raw : path.resolve(cwd, raw);
|
|
34
37
|
key = `path:${path.normalize(absolute)}`;
|
|
35
38
|
}
|
|
@@ -50,7 +53,7 @@ export function collectModelList(value, previous = []) {
|
|
|
50
53
|
return previous;
|
|
51
54
|
}
|
|
52
55
|
const entries = value
|
|
53
|
-
.split(
|
|
56
|
+
.split(",")
|
|
54
57
|
.map((entry) => entry.trim())
|
|
55
58
|
.filter((entry) => entry.length > 0);
|
|
56
59
|
return previous.concat(entries);
|
|
@@ -58,7 +61,7 @@ export function collectModelList(value, previous = []) {
|
|
|
58
61
|
export function parseFloatOption(value) {
|
|
59
62
|
const parsed = Number.parseFloat(value);
|
|
60
63
|
if (Number.isNaN(parsed)) {
|
|
61
|
-
throw new InvalidArgumentError(
|
|
64
|
+
throw new InvalidArgumentError("Value must be a number.");
|
|
62
65
|
}
|
|
63
66
|
return parsed;
|
|
64
67
|
}
|
|
@@ -68,7 +71,7 @@ export function parseIntOption(value) {
|
|
|
68
71
|
}
|
|
69
72
|
const parsed = Number.parseInt(value, 10);
|
|
70
73
|
if (Number.isNaN(parsed)) {
|
|
71
|
-
throw new InvalidArgumentError(
|
|
74
|
+
throw new InvalidArgumentError("Value must be an integer.");
|
|
72
75
|
}
|
|
73
76
|
return parsed;
|
|
74
77
|
}
|
|
@@ -76,9 +79,9 @@ export function parseHeartbeatOption(value) {
|
|
|
76
79
|
if (value == null) {
|
|
77
80
|
return 30;
|
|
78
81
|
}
|
|
79
|
-
if (typeof value ===
|
|
82
|
+
if (typeof value === "number") {
|
|
80
83
|
if (Number.isNaN(value) || value < 0) {
|
|
81
|
-
throw new InvalidArgumentError(
|
|
84
|
+
throw new InvalidArgumentError("Heartbeat interval must be zero or a positive number.");
|
|
82
85
|
}
|
|
83
86
|
return value;
|
|
84
87
|
}
|
|
@@ -86,42 +89,42 @@ export function parseHeartbeatOption(value) {
|
|
|
86
89
|
if (normalized.length === 0) {
|
|
87
90
|
return 30;
|
|
88
91
|
}
|
|
89
|
-
if (normalized ===
|
|
92
|
+
if (normalized === "false" || normalized === "off") {
|
|
90
93
|
return 0;
|
|
91
94
|
}
|
|
92
95
|
const parsed = Number.parseFloat(normalized);
|
|
93
96
|
if (Number.isNaN(parsed) || parsed < 0) {
|
|
94
|
-
throw new InvalidArgumentError(
|
|
97
|
+
throw new InvalidArgumentError("Heartbeat interval must be zero or a positive number.");
|
|
95
98
|
}
|
|
96
99
|
return parsed;
|
|
97
100
|
}
|
|
98
101
|
export function usesDefaultStatusFilters(cmd) {
|
|
99
|
-
const hoursSource = cmd.getOptionValueSource?.(
|
|
100
|
-
const limitSource = cmd.getOptionValueSource?.(
|
|
101
|
-
const allSource = cmd.getOptionValueSource?.(
|
|
102
|
-
return hoursSource ===
|
|
102
|
+
const hoursSource = cmd.getOptionValueSource?.("hours") ?? "default";
|
|
103
|
+
const limitSource = cmd.getOptionValueSource?.("limit") ?? "default";
|
|
104
|
+
const allSource = cmd.getOptionValueSource?.("all") ?? "default";
|
|
105
|
+
return hoursSource === "default" && limitSource === "default" && allSource === "default";
|
|
103
106
|
}
|
|
104
107
|
export function resolvePreviewMode(value) {
|
|
105
|
-
if (typeof value ===
|
|
108
|
+
if (typeof value === "string" && value.length > 0) {
|
|
106
109
|
return value;
|
|
107
110
|
}
|
|
108
111
|
if (value === true) {
|
|
109
|
-
return
|
|
112
|
+
return "summary";
|
|
110
113
|
}
|
|
111
114
|
return undefined;
|
|
112
115
|
}
|
|
113
116
|
export function parseSearchOption(value) {
|
|
114
117
|
const normalized = value.trim().toLowerCase();
|
|
115
|
-
if ([
|
|
118
|
+
if (["on", "true", "1", "yes"].includes(normalized)) {
|
|
116
119
|
return true;
|
|
117
120
|
}
|
|
118
|
-
if ([
|
|
121
|
+
if (["off", "false", "0", "no"].includes(normalized)) {
|
|
119
122
|
return false;
|
|
120
123
|
}
|
|
121
124
|
throw new InvalidArgumentError('Search mode must be "on" or "off".');
|
|
122
125
|
}
|
|
123
126
|
export function normalizeModelOption(value) {
|
|
124
|
-
return (value ??
|
|
127
|
+
return (value ?? "").trim();
|
|
125
128
|
}
|
|
126
129
|
export function normalizeBaseUrl(value) {
|
|
127
130
|
const trimmed = value?.trim();
|
|
@@ -131,8 +134,8 @@ export function parseTimeoutOption(value) {
|
|
|
131
134
|
if (value == null)
|
|
132
135
|
return undefined;
|
|
133
136
|
const normalized = value.trim().toLowerCase();
|
|
134
|
-
if (normalized ===
|
|
135
|
-
return
|
|
137
|
+
if (normalized === "auto")
|
|
138
|
+
return "auto";
|
|
136
139
|
const parsed = Number.parseFloat(normalized);
|
|
137
140
|
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
138
141
|
throw new InvalidArgumentError('Timeout must be a positive number of seconds or "auto".');
|
|
@@ -152,49 +155,76 @@ export function parseDurationOption(value, label) {
|
|
|
152
155
|
}
|
|
153
156
|
return parsed;
|
|
154
157
|
}
|
|
158
|
+
function isGeminiDeepThinkAlias(normalized) {
|
|
159
|
+
return ((normalized.includes("gemini") && normalized.includes("deep")) ||
|
|
160
|
+
normalized.includes("deep-think") ||
|
|
161
|
+
normalized.includes("deep_think") ||
|
|
162
|
+
normalized.includes("deepthink"));
|
|
163
|
+
}
|
|
155
164
|
export function resolveApiModel(modelValue) {
|
|
156
165
|
const normalized = normalizeModelOption(modelValue).toLowerCase();
|
|
157
166
|
if (normalized in MODEL_CONFIGS) {
|
|
158
167
|
return normalized;
|
|
159
168
|
}
|
|
160
|
-
if (normalized.includes(
|
|
161
|
-
return
|
|
169
|
+
if (normalized.includes("/")) {
|
|
170
|
+
return normalized;
|
|
171
|
+
}
|
|
172
|
+
if (normalized.includes("grok")) {
|
|
173
|
+
return "grok-4.1";
|
|
174
|
+
}
|
|
175
|
+
if (normalized.includes("claude") && normalized.includes("sonnet")) {
|
|
176
|
+
return "claude-4.6-sonnet";
|
|
177
|
+
}
|
|
178
|
+
if (normalized.includes("claude") && normalized.includes("opus")) {
|
|
179
|
+
return "claude-4.1-opus";
|
|
162
180
|
}
|
|
163
|
-
if (normalized.includes(
|
|
164
|
-
return
|
|
181
|
+
if (normalized.includes("5.5") && normalized.includes("pro")) {
|
|
182
|
+
return "gpt-5.5-pro";
|
|
165
183
|
}
|
|
166
|
-
if (normalized.includes(
|
|
167
|
-
return
|
|
184
|
+
if (normalized.includes("5.5")) {
|
|
185
|
+
return "gpt-5.5";
|
|
168
186
|
}
|
|
169
|
-
if (normalized
|
|
170
|
-
return
|
|
187
|
+
if (normalized.includes("5.4") && normalized.includes("pro")) {
|
|
188
|
+
return "gpt-5.4-pro";
|
|
171
189
|
}
|
|
172
|
-
if (normalized
|
|
173
|
-
return
|
|
190
|
+
if (normalized.includes("5.4")) {
|
|
191
|
+
return "gpt-5.4";
|
|
174
192
|
}
|
|
175
|
-
if (normalized
|
|
176
|
-
return
|
|
193
|
+
if (normalized === "claude" || normalized === "sonnet" || /(^|\b)sonnet(\b|$)/.test(normalized)) {
|
|
194
|
+
return "claude-4.6-sonnet";
|
|
177
195
|
}
|
|
178
|
-
if (normalized
|
|
179
|
-
return
|
|
196
|
+
if (normalized === "opus" || normalized === "claude-4.1") {
|
|
197
|
+
return "claude-4.1-opus";
|
|
180
198
|
}
|
|
181
|
-
if (normalized.includes(
|
|
182
|
-
return
|
|
199
|
+
if (normalized.includes("5.0") || normalized === "gpt-5-pro" || normalized === "gpt-5") {
|
|
200
|
+
return "gpt-5-pro";
|
|
183
201
|
}
|
|
184
|
-
if (normalized.includes(
|
|
185
|
-
return
|
|
202
|
+
if (normalized.includes("5-pro") && !normalized.includes("5.1")) {
|
|
203
|
+
return "gpt-5-pro";
|
|
186
204
|
}
|
|
187
|
-
if (normalized.includes(
|
|
188
|
-
|
|
189
|
-
|
|
205
|
+
if (normalized.includes("5.2") && normalized.includes("pro")) {
|
|
206
|
+
return "gpt-5.2-pro";
|
|
207
|
+
}
|
|
208
|
+
if (normalized.includes("5.1") && normalized.includes("pro")) {
|
|
209
|
+
return "gpt-5.1-pro";
|
|
210
|
+
}
|
|
211
|
+
if (normalized.includes("codex")) {
|
|
212
|
+
if (normalized.includes("max")) {
|
|
213
|
+
throw new InvalidArgumentError("gpt-5.1-codex-max is not available yet. OpenAI has not released the API.");
|
|
190
214
|
}
|
|
191
|
-
return
|
|
215
|
+
return "gpt-5.1-codex";
|
|
192
216
|
}
|
|
193
|
-
if (normalized
|
|
194
|
-
|
|
217
|
+
if (isGeminiDeepThinkAlias(normalized)) {
|
|
218
|
+
throw new InvalidArgumentError("Gemini Deep Think is browser-only today. Use --engine browser --model gemini-3-deep-think.");
|
|
195
219
|
}
|
|
196
|
-
if (normalized.includes(
|
|
197
|
-
|
|
220
|
+
if (normalized.includes("gemini")) {
|
|
221
|
+
if (normalized.includes("3.1") || normalized.includes("3_1")) {
|
|
222
|
+
return "gemini-3.1-pro";
|
|
223
|
+
}
|
|
224
|
+
return "gemini-3-pro";
|
|
225
|
+
}
|
|
226
|
+
if (normalized.includes("pro")) {
|
|
227
|
+
return DEFAULT_MODEL;
|
|
198
228
|
}
|
|
199
229
|
// Passthrough for custom/OpenRouter model IDs.
|
|
200
230
|
return normalized;
|
|
@@ -207,57 +237,85 @@ export function inferModelFromLabel(modelValue) {
|
|
|
207
237
|
if (normalized in MODEL_CONFIGS) {
|
|
208
238
|
return normalized;
|
|
209
239
|
}
|
|
210
|
-
if (normalized.includes(
|
|
211
|
-
return
|
|
240
|
+
if (normalized.includes("/")) {
|
|
241
|
+
return normalized;
|
|
242
|
+
}
|
|
243
|
+
if (normalized.includes("grok")) {
|
|
244
|
+
return "grok-4.1";
|
|
245
|
+
}
|
|
246
|
+
if (normalized.includes("claude") && normalized.includes("sonnet")) {
|
|
247
|
+
return "claude-4.6-sonnet";
|
|
248
|
+
}
|
|
249
|
+
if (normalized.includes("claude") && normalized.includes("opus")) {
|
|
250
|
+
return "claude-4.1-opus";
|
|
251
|
+
}
|
|
252
|
+
if (normalized.includes("codex")) {
|
|
253
|
+
return "gpt-5.1-codex";
|
|
212
254
|
}
|
|
213
|
-
if (
|
|
214
|
-
return
|
|
255
|
+
if (isGeminiDeepThinkAlias(normalized)) {
|
|
256
|
+
return "gemini-3-pro-deep-think";
|
|
215
257
|
}
|
|
216
|
-
if (normalized.includes(
|
|
217
|
-
|
|
258
|
+
if (normalized.includes("gemini")) {
|
|
259
|
+
if (normalized.includes("3.1") || normalized.includes("3_1")) {
|
|
260
|
+
return "gemini-3.1-pro";
|
|
261
|
+
}
|
|
262
|
+
return "gemini-3-pro";
|
|
263
|
+
}
|
|
264
|
+
if (normalized.includes("classic")) {
|
|
265
|
+
return "gpt-5-pro";
|
|
266
|
+
}
|
|
267
|
+
if (normalized.includes("thinking") && normalized.includes("heavy")) {
|
|
268
|
+
return "gpt-5.5";
|
|
218
269
|
}
|
|
219
|
-
if (normalized.includes(
|
|
220
|
-
return
|
|
270
|
+
if ((normalized.includes("5.5") || normalized.includes("5_5")) && normalized.includes("pro")) {
|
|
271
|
+
return "gpt-5.5-pro";
|
|
221
272
|
}
|
|
222
|
-
if (normalized.includes(
|
|
223
|
-
return
|
|
273
|
+
if (normalized.includes("5.5") || normalized.includes("5_5")) {
|
|
274
|
+
return "gpt-5.5";
|
|
224
275
|
}
|
|
225
|
-
if (normalized.includes(
|
|
226
|
-
return
|
|
276
|
+
if ((normalized.includes("5.4") || normalized.includes("5_4")) && normalized.includes("pro")) {
|
|
277
|
+
return "gpt-5.4-pro";
|
|
227
278
|
}
|
|
228
|
-
if (
|
|
229
|
-
return
|
|
279
|
+
if (normalized.includes("5.4") || normalized.includes("5_4")) {
|
|
280
|
+
return "gpt-5.4";
|
|
281
|
+
}
|
|
282
|
+
if ((normalized.includes("5.2") || normalized.includes("5_2")) && normalized.includes("pro")) {
|
|
283
|
+
return "gpt-5.2-pro";
|
|
230
284
|
}
|
|
231
285
|
// Browser-only: pass through 5.2 thinking/instant variants for browser label mapping
|
|
232
|
-
if ((normalized.includes(
|
|
233
|
-
|
|
286
|
+
if ((normalized.includes("5.2") || normalized.includes("5_2")) &&
|
|
287
|
+
normalized.includes("thinking")) {
|
|
288
|
+
return "gpt-5.2-thinking";
|
|
234
289
|
}
|
|
235
|
-
if ((normalized.includes(
|
|
236
|
-
|
|
290
|
+
if ((normalized.includes("5.2") || normalized.includes("5_2")) &&
|
|
291
|
+
normalized.includes("instant")) {
|
|
292
|
+
return "gpt-5.2-instant";
|
|
237
293
|
}
|
|
238
|
-
if (normalized.includes(
|
|
239
|
-
return
|
|
294
|
+
if (normalized.includes("5.0") || normalized.includes("5-pro")) {
|
|
295
|
+
return "gpt-5-pro";
|
|
240
296
|
}
|
|
241
|
-
if (normalized.includes(
|
|
242
|
-
normalized.includes(
|
|
243
|
-
!normalized.includes(
|
|
244
|
-
!normalized.includes(
|
|
245
|
-
|
|
297
|
+
if (normalized.includes("gpt-5") &&
|
|
298
|
+
normalized.includes("pro") &&
|
|
299
|
+
!normalized.includes("5.1") &&
|
|
300
|
+
!normalized.includes("5.2") &&
|
|
301
|
+
!normalized.includes("5.5") &&
|
|
302
|
+
!normalized.includes("5.4")) {
|
|
303
|
+
return "gpt-5-pro";
|
|
246
304
|
}
|
|
247
|
-
if ((normalized.includes(
|
|
248
|
-
return
|
|
305
|
+
if ((normalized.includes("5.1") || normalized.includes("5_1")) && normalized.includes("pro")) {
|
|
306
|
+
return "gpt-5.1-pro";
|
|
249
307
|
}
|
|
250
|
-
if (normalized.includes(
|
|
251
|
-
return
|
|
308
|
+
if (normalized.includes("pro")) {
|
|
309
|
+
return DEFAULT_MODEL;
|
|
252
310
|
}
|
|
253
|
-
if (normalized.includes(
|
|
254
|
-
return
|
|
311
|
+
if (normalized.includes("5.1") || normalized.includes("5_1")) {
|
|
312
|
+
return "gpt-5.1";
|
|
255
313
|
}
|
|
256
|
-
if (normalized.includes(
|
|
257
|
-
return
|
|
314
|
+
if (normalized.includes("thinking")) {
|
|
315
|
+
return "gpt-5.2-thinking";
|
|
258
316
|
}
|
|
259
|
-
if (normalized.includes(
|
|
260
|
-
return
|
|
317
|
+
if (normalized.includes("instant") || normalized.includes("fast")) {
|
|
318
|
+
return "gpt-5.2-instant";
|
|
261
319
|
}
|
|
262
|
-
return
|
|
320
|
+
return "gpt-5.2";
|
|
263
321
|
}
|
package/dist/src/cli/oscUtils.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Utilities for handling OSC progress codes embedded in stored logs.
|
|
2
|
-
export { sanitizeOscProgress } from
|
|
2
|
+
export { sanitizeOscProgress } from "osc-progress";
|
|
@@ -10,8 +10,8 @@ export function shouldRequirePrompt(rawArgs, options) {
|
|
|
10
10
|
options.execSession ||
|
|
11
11
|
options.status ||
|
|
12
12
|
options.debugHelp ||
|
|
13
|
-
firstArg ===
|
|
14
|
-
firstArg ===
|
|
13
|
+
firstArg === "status" ||
|
|
14
|
+
firstArg === "session");
|
|
15
15
|
const requiresPrompt = options.renderMarkdown || Boolean(options.preview) || Boolean(options.dryRun) || !bypassPrompt;
|
|
16
16
|
return requiresPrompt && !options.prompt;
|
|
17
17
|
}
|
|
@@ -1,44 +1,55 @@
|
|
|
1
|
-
import { DEFAULT_MODEL, MODEL_CONFIGS } from
|
|
2
|
-
import { resolveEngine } from
|
|
3
|
-
import { normalizeModelOption, inferModelFromLabel, resolveApiModel, normalizeBaseUrl } from
|
|
4
|
-
import { resolveGeminiModelId } from
|
|
5
|
-
import { PromptValidationError } from
|
|
6
|
-
import { normalizeChatGptModelForBrowser } from
|
|
1
|
+
import { DEFAULT_MODEL, MODEL_CONFIGS } from "../oracle.js";
|
|
2
|
+
import { resolveEngine } from "./engine.js";
|
|
3
|
+
import { normalizeModelOption, inferModelFromLabel, resolveApiModel, normalizeBaseUrl, } from "./options.js";
|
|
4
|
+
import { resolveGeminiModelId } from "../oracle/gemini.js";
|
|
5
|
+
import { PromptValidationError } from "../oracle/errors.js";
|
|
6
|
+
import { normalizeChatGptModelForBrowser } from "./browserConfig.js";
|
|
7
|
+
import { resolveConfiguredMaxFileSizeBytes } from "./fileSize.js";
|
|
7
8
|
export function resolveRunOptionsFromConfig({ prompt, files = [], model, models, engine, userConfig, env = process.env, }) {
|
|
8
9
|
const resolvedEngine = resolveEngineWithConfig({ engine, configEngine: userConfig?.engine, env });
|
|
9
|
-
const browserRequested = engine ===
|
|
10
|
-
const browserConfigured = userConfig?.engine ===
|
|
10
|
+
const browserRequested = engine === "browser";
|
|
11
|
+
const browserConfigured = userConfig?.engine === "browser";
|
|
11
12
|
const requestedModelList = Array.isArray(models) ? models : [];
|
|
12
|
-
const normalizedRequestedModels = requestedModelList
|
|
13
|
+
const normalizedRequestedModels = requestedModelList
|
|
14
|
+
.map((entry) => normalizeModelOption(entry))
|
|
15
|
+
.filter(Boolean);
|
|
13
16
|
const cliModelArg = normalizeModelOption(model ?? userConfig?.model) || DEFAULT_MODEL;
|
|
14
|
-
const inferredModel = resolvedEngine ===
|
|
17
|
+
const inferredModel = resolvedEngine === "browser" && normalizedRequestedModels.length === 0
|
|
15
18
|
? inferModelFromLabel(cliModelArg)
|
|
16
19
|
: resolveApiModel(cliModelArg);
|
|
17
|
-
// Browser engine maps Pro/legacy aliases to the latest ChatGPT picker targets
|
|
18
|
-
const resolvedModel = resolvedEngine ===
|
|
19
|
-
const isCodex = resolvedModel.startsWith(
|
|
20
|
-
const isClaude = resolvedModel.startsWith(
|
|
21
|
-
const isGrok = resolvedModel.startsWith(
|
|
22
|
-
const
|
|
20
|
+
// Browser engine maps Pro/legacy aliases to the latest ChatGPT picker targets.
|
|
21
|
+
const resolvedModel = resolvedEngine === "browser" ? normalizeChatGptModelForBrowser(inferredModel) : inferredModel;
|
|
22
|
+
const isCodex = resolvedModel.startsWith("gpt-5.1-codex");
|
|
23
|
+
const isClaude = resolvedModel.startsWith("claude");
|
|
24
|
+
const isGrok = resolvedModel.startsWith("grok");
|
|
25
|
+
const isGeminiApiOnly = resolvedModel === "gemini-3.1-pro";
|
|
26
|
+
const engineWasBrowser = resolvedEngine === "browser";
|
|
23
27
|
const allModels = normalizedRequestedModels.length > 0
|
|
24
28
|
? Array.from(new Set(normalizedRequestedModels.map((entry) => resolveApiModel(entry))))
|
|
25
29
|
: [resolvedModel];
|
|
26
|
-
const
|
|
30
|
+
const includesGeminiApiOnly = allModels.some((m) => m === "gemini-3.1-pro");
|
|
31
|
+
if ((browserRequested || browserConfigured) && includesGeminiApiOnly) {
|
|
32
|
+
throw new PromptValidationError("gemini-3.1-pro is API-only today. Use --engine api or switch to gemini-3-pro for Gemini web.", { engine: "browser", models: allModels });
|
|
33
|
+
}
|
|
34
|
+
const isBrowserCompatible = (m) => m.startsWith("gpt-") || m.startsWith("gemini");
|
|
27
35
|
const hasNonBrowserCompatibleTarget = (browserRequested || browserConfigured) && allModels.some((m) => !isBrowserCompatible(m));
|
|
28
36
|
if (hasNonBrowserCompatibleTarget) {
|
|
29
|
-
throw new PromptValidationError(
|
|
37
|
+
throw new PromptValidationError("Browser engine only supports GPT and Gemini models. Re-run with --engine api for Grok, Claude, or other models.", { engine: "browser", models: allModels });
|
|
30
38
|
}
|
|
31
|
-
const engineCoercedToApi = engineWasBrowser && (isCodex || isClaude || isGrok);
|
|
32
|
-
const fixedEngine = isCodex || isClaude || isGrok || normalizedRequestedModels.length > 0
|
|
39
|
+
const engineCoercedToApi = engineWasBrowser && (isCodex || isClaude || isGrok || isGeminiApiOnly);
|
|
40
|
+
const fixedEngine = isCodex || isClaude || isGrok || isGeminiApiOnly || normalizedRequestedModels.length > 0
|
|
41
|
+
? "api"
|
|
42
|
+
: resolvedEngine;
|
|
33
43
|
const promptWithSuffix = userConfig?.promptSuffix && userConfig.promptSuffix.trim().length > 0
|
|
34
44
|
? `${prompt.trim()}\n${userConfig.promptSuffix}`
|
|
35
45
|
: prompt;
|
|
36
|
-
const search = userConfig?.search !==
|
|
46
|
+
const search = userConfig?.search !== "off";
|
|
37
47
|
const heartbeatIntervalMs = userConfig?.heartbeatSeconds !== undefined ? userConfig.heartbeatSeconds * 1000 : 30_000;
|
|
48
|
+
const maxFileSizeBytes = resolveConfiguredMaxFileSizeBytes(userConfig, env);
|
|
38
49
|
const baseUrl = normalizeBaseUrl(userConfig?.apiBaseUrl ??
|
|
39
50
|
(isClaude ? env.ANTHROPIC_BASE_URL : isGrok ? env.XAI_BASE_URL : env.OPENAI_BASE_URL));
|
|
40
51
|
const uniqueMultiModels = normalizedRequestedModels.length > 0 ? allModels : [];
|
|
41
|
-
const includesCodexMultiModel = uniqueMultiModels.some((entry) => entry.startsWith(
|
|
52
|
+
const includesCodexMultiModel = uniqueMultiModels.some((entry) => entry.startsWith("gpt-5.1-codex"));
|
|
42
53
|
if (includesCodexMultiModel && browserRequested) {
|
|
43
54
|
// Silent coerce; multi-model still forces API.
|
|
44
55
|
}
|
|
@@ -49,6 +60,7 @@ export function resolveRunOptionsFromConfig({ prompt, files = [], model, models,
|
|
|
49
60
|
model: chosenModel,
|
|
50
61
|
models: uniqueMultiModels.length > 0 ? uniqueMultiModels : undefined,
|
|
51
62
|
file: files ?? [],
|
|
63
|
+
maxFileSizeBytes,
|
|
52
64
|
search,
|
|
53
65
|
heartbeatIntervalMs,
|
|
54
66
|
filesReport: userConfig?.filesReport,
|
|
@@ -61,8 +73,8 @@ export function resolveRunOptionsFromConfig({ prompt, files = [], model, models,
|
|
|
61
73
|
function resolveEngineWithConfig({ engine, configEngine, env, }) {
|
|
62
74
|
if (engine)
|
|
63
75
|
return engine;
|
|
64
|
-
const envOverride = (env.ORACLE_ENGINE ??
|
|
65
|
-
if (envOverride ===
|
|
76
|
+
const envOverride = (env.ORACLE_ENGINE ?? "").trim().toLowerCase();
|
|
77
|
+
if (envOverride === "api" || envOverride === "browser") {
|
|
66
78
|
return envOverride;
|
|
67
79
|
}
|
|
68
80
|
if (configEngine)
|
|
@@ -70,7 +82,7 @@ function resolveEngineWithConfig({ engine, configEngine, env, }) {
|
|
|
70
82
|
return resolveEngine({ engine: undefined, env });
|
|
71
83
|
}
|
|
72
84
|
function resolveEffectiveModelId(model) {
|
|
73
|
-
if (typeof model ===
|
|
85
|
+
if (typeof model === "string" && model.startsWith("gemini")) {
|
|
74
86
|
return resolveGeminiModelId(model);
|
|
75
87
|
}
|
|
76
88
|
const config = MODEL_CONFIGS[model];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import { usesDefaultStatusFilters } from
|
|
3
|
-
import { attachSession, showStatus } from
|
|
4
|
-
import { sessionStore } from
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { usesDefaultStatusFilters } from "./options.js";
|
|
3
|
+
import { attachSession, showStatus, } from "./sessionDisplay.js";
|
|
4
|
+
import { sessionStore } from "../sessionStore.js";
|
|
5
5
|
const defaultDependencies = {
|
|
6
6
|
showStatus,
|
|
7
7
|
attachSession,
|
|
@@ -9,39 +9,49 @@ const defaultDependencies = {
|
|
|
9
9
|
deleteSessionsOlderThan: (options) => sessionStore.deleteOlderThan(options),
|
|
10
10
|
getSessionPaths: (sessionId) => sessionStore.getPaths(sessionId),
|
|
11
11
|
};
|
|
12
|
-
const SESSION_OPTION_KEYS = new Set([
|
|
12
|
+
const SESSION_OPTION_KEYS = new Set([
|
|
13
|
+
"hours",
|
|
14
|
+
"limit",
|
|
15
|
+
"all",
|
|
16
|
+
"clear",
|
|
17
|
+
"clean",
|
|
18
|
+
"render",
|
|
19
|
+
"renderMarkdown",
|
|
20
|
+
"path",
|
|
21
|
+
"model",
|
|
22
|
+
]);
|
|
13
23
|
export async function handleSessionCommand(sessionId, command, deps = defaultDependencies) {
|
|
14
24
|
const sessionOptions = command.opts();
|
|
15
25
|
if (sessionOptions.verboseRender) {
|
|
16
|
-
process.env.ORACLE_VERBOSE_RENDER =
|
|
26
|
+
process.env.ORACLE_VERBOSE_RENDER = "1";
|
|
17
27
|
}
|
|
18
|
-
const renderSource = command.getOptionValueSource?.(
|
|
19
|
-
const renderMarkdownSource = command.getOptionValueSource?.(
|
|
20
|
-
const renderExplicit = renderSource ===
|
|
28
|
+
const renderSource = command.getOptionValueSource?.("render");
|
|
29
|
+
const renderMarkdownSource = command.getOptionValueSource?.("renderMarkdown");
|
|
30
|
+
const renderExplicit = renderSource === "cli" || renderMarkdownSource === "cli";
|
|
21
31
|
const autoRender = !renderExplicit && process.stdout.isTTY;
|
|
22
32
|
const pathRequested = Boolean(sessionOptions.path);
|
|
23
33
|
const clearRequested = Boolean(sessionOptions.clear || sessionOptions.clean);
|
|
24
34
|
if (clearRequested) {
|
|
25
35
|
if (sessionId) {
|
|
26
|
-
console.error(
|
|
36
|
+
console.error("Cannot combine a session ID with --clear. Remove the ID to delete cached sessions.");
|
|
27
37
|
process.exitCode = 1;
|
|
28
38
|
return;
|
|
29
39
|
}
|
|
30
40
|
const hours = sessionOptions.hours;
|
|
31
41
|
const includeAll = sessionOptions.all;
|
|
32
42
|
const result = await deps.deleteSessionsOlderThan({ hours, includeAll });
|
|
33
|
-
const scope = includeAll ?
|
|
43
|
+
const scope = includeAll ? "all stored sessions" : `sessions older than ${hours}h`;
|
|
34
44
|
console.log(formatSessionCleanupMessage(result, scope));
|
|
35
45
|
return;
|
|
36
46
|
}
|
|
37
|
-
if (sessionId ===
|
|
47
|
+
if (sessionId === "clear" || sessionId === "clean") {
|
|
38
48
|
console.error('Session cleanup now uses --clear. Run "oracle session --clear --hours <n>" instead.');
|
|
39
49
|
process.exitCode = 1;
|
|
40
50
|
return;
|
|
41
51
|
}
|
|
42
52
|
if (pathRequested) {
|
|
43
53
|
if (!sessionId) {
|
|
44
|
-
console.error(
|
|
54
|
+
console.error("The --path flag requires a session ID.");
|
|
45
55
|
process.exitCode = 1;
|
|
46
56
|
return;
|
|
47
57
|
}
|
|
@@ -50,10 +60,10 @@ export async function handleSessionCommand(sessionId, command, deps = defaultDep
|
|
|
50
60
|
const richTty = Boolean(process.stdout.isTTY && chalk.level > 0);
|
|
51
61
|
const label = (text) => (richTty ? chalk.cyan(text) : text);
|
|
52
62
|
const value = (text) => (richTty ? chalk.dim(text) : text);
|
|
53
|
-
console.log(`${label(
|
|
54
|
-
console.log(`${label(
|
|
55
|
-
console.log(`${label(
|
|
56
|
-
console.log(`${label(
|
|
63
|
+
console.log(`${label("Session dir:")} ${value(paths.dir)}`);
|
|
64
|
+
console.log(`${label("Metadata:")} ${value(paths.metadata)}`);
|
|
65
|
+
console.log(`${label("Request:")} ${value(paths.request)}`);
|
|
66
|
+
console.log(`${label("Log:")} ${value(paths.log)}`);
|
|
57
67
|
}
|
|
58
68
|
catch (error) {
|
|
59
69
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -75,7 +85,7 @@ export async function handleSessionCommand(sessionId, command, deps = defaultDep
|
|
|
75
85
|
// Surface any root-level flags that were provided but are ignored when attaching to a session.
|
|
76
86
|
const ignoredFlags = listIgnoredFlags(command);
|
|
77
87
|
if (ignoredFlags.length > 0) {
|
|
78
|
-
console.log(`Ignoring flags on session attach: ${ignoredFlags.join(
|
|
88
|
+
console.log(`Ignoring flags on session attach: ${ignoredFlags.join(", ")}`);
|
|
79
89
|
}
|
|
80
90
|
const renderMarkdown = Boolean(sessionOptions.render || sessionOptions.renderMarkdown || autoRender);
|
|
81
91
|
await deps.attachSession(sessionId, {
|
|
@@ -85,8 +95,8 @@ export async function handleSessionCommand(sessionId, command, deps = defaultDep
|
|
|
85
95
|
});
|
|
86
96
|
}
|
|
87
97
|
export function formatSessionCleanupMessage(result, scope) {
|
|
88
|
-
const deletedLabel = `${result.deleted} ${result.deleted === 1 ?
|
|
89
|
-
const remainingLabel = `${result.remaining} ${result.remaining === 1 ?
|
|
98
|
+
const deletedLabel = `${result.deleted} ${result.deleted === 1 ? "session" : "sessions"}`;
|
|
99
|
+
const remainingLabel = `${result.remaining} ${result.remaining === 1 ? "session" : "sessions"} remain`;
|
|
90
100
|
const hint = 'Run "oracle session --clear --all" to delete everything.';
|
|
91
101
|
return `Deleted ${deletedLabel} (${scope}). ${remainingLabel}.\n${hint}`;
|
|
92
102
|
}
|
|
@@ -98,7 +108,7 @@ function listIgnoredFlags(command) {
|
|
|
98
108
|
continue;
|
|
99
109
|
}
|
|
100
110
|
const source = command.getOptionValueSource?.(key);
|
|
101
|
-
if (source !==
|
|
111
|
+
if (source !== "cli" && source !== "env") {
|
|
102
112
|
continue;
|
|
103
113
|
}
|
|
104
114
|
const value = opts[key];
|