@steipete/oracle 0.9.0 → 0.11.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 +107 -49
- package/dist/bin/oracle-cli.js +551 -410
- 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/archiveConversation.js +224 -0
- package/dist/src/browser/actions/assistantResponse.js +175 -101
- package/dist/src/browser/actions/attachmentDataTransfer.js +49 -47
- package/dist/src/browser/actions/attachments.js +246 -150
- package/dist/src/browser/actions/deepResearch.js +662 -0
- package/dist/src/browser/actions/domEvents.js +2 -2
- package/dist/src/browser/actions/modelSelection.js +342 -119
- package/dist/src/browser/actions/navigation.js +183 -137
- package/dist/src/browser/actions/projectSources.js +491 -0
- package/dist/src/browser/actions/promptComposer.js +152 -91
- package/dist/src/browser/actions/remoteFileTransfer.js +10 -10
- package/dist/src/browser/actions/thinkingStatus.js +391 -0
- package/dist/src/browser/actions/thinkingTime.js +207 -110
- package/dist/src/browser/artifacts.js +150 -0
- package/dist/src/browser/attachRunning.js +31 -0
- package/dist/src/browser/chatgptImages.js +315 -0
- package/dist/src/browser/chromeLifecycle.js +276 -63
- package/dist/src/browser/config.js +59 -16
- package/dist/src/browser/constants.js +25 -12
- package/dist/src/browser/controlPlan.js +81 -0
- package/dist/src/browser/cookies.js +19 -19
- package/dist/src/browser/detect.js +250 -77
- package/dist/src/browser/domDebug.js +50 -1
- package/dist/src/browser/index.js +1559 -692
- package/dist/src/browser/liveTabs.js +434 -0
- 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 +127 -42
- package/dist/src/browser/projectSourcesRunner.js +366 -0
- package/dist/src/browser/prompt.js +72 -42
- package/dist/src/browser/promptSummary.js +5 -5
- package/dist/src/browser/providerDomFlow.js +1 -1
- package/dist/src/browser/providers/chatgptDomProvider.js +9 -9
- package/dist/src/browser/providers/geminiDeepThinkDomProvider.js +51 -42
- package/dist/src/browser/providers/index.js +2 -2
- package/dist/src/browser/reattach.js +178 -73
- package/dist/src/browser/reattachHelpers.js +32 -27
- package/dist/src/browser/sessionRunner.js +89 -25
- package/dist/src/browser/tabLeaseRegistry.js +182 -0
- package/dist/src/browser/utils.js +9 -9
- package/dist/src/browserMode.js +1 -1
- package/dist/src/cli/bridge/claudeConfig.js +24 -20
- 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 +102 -48
- package/dist/src/cli/browserDefaults.js +51 -26
- package/dist/src/cli/browserTabs.js +228 -0
- package/dist/src/cli/bundleWarnings.js +1 -1
- package/dist/src/cli/clipboard.js +11 -2
- package/dist/src/cli/detach.js +2 -2
- package/dist/src/cli/dryRun.js +62 -26
- package/dist/src/cli/duplicatePromptGuard.js +12 -4
- package/dist/src/cli/engine.js +9 -9
- package/dist/src/cli/errorUtils.js +1 -1
- package/dist/src/cli/fileSize.js +3 -3
- 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 +7 -7
- package/dist/src/cli/markdownRenderer.js +15 -15
- package/dist/src/cli/notifier.js +77 -67
- package/dist/src/cli/options.js +131 -106
- package/dist/src/cli/oscUtils.js +1 -1
- package/dist/src/cli/projectSources.js +116 -0
- 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 +32 -28
- package/dist/src/cli/sessionCommand.js +82 -21
- package/dist/src/cli/sessionDisplay.js +213 -87
- package/dist/src/cli/sessionLineage.js +6 -2
- package/dist/src/cli/sessionRunner.js +149 -95
- package/dist/src/cli/sessionTable.js +26 -23
- package/dist/src/cli/stdin.js +22 -0
- package/dist/src/cli/tagline.js +121 -124
- package/dist/src/cli/tui/index.js +139 -128
- package/dist/src/cli/writeOutputPath.js +5 -5
- package/dist/src/config.js +7 -7
- package/dist/src/gemini-web/browserSessionManager.js +19 -15
- package/dist/src/gemini-web/client.js +76 -70
- package/dist/src/gemini-web/executionMode.js +6 -8
- package/dist/src/gemini-web/executor.js +98 -93
- package/dist/src/gemini-web/index.js +1 -1
- package/dist/src/mcp/consultPresets.js +19 -0
- package/dist/src/mcp/server.js +18 -12
- package/dist/src/mcp/tools/consult.js +246 -67
- package/dist/src/mcp/tools/projectSources.js +123 -0
- package/dist/src/mcp/tools/sessionResources.js +12 -12
- package/dist/src/mcp/tools/sessions.js +26 -17
- package/dist/src/mcp/types.js +12 -5
- package/dist/src/mcp/utils.js +21 -8
- package/dist/src/oracle/background.js +15 -15
- package/dist/src/oracle/claude.js +53 -25
- package/dist/src/oracle/client.js +50 -41
- package/dist/src/oracle/config.js +96 -66
- package/dist/src/oracle/errors.js +38 -38
- package/dist/src/oracle/files.js +55 -46
- package/dist/src/oracle/finishLine.js +10 -8
- package/dist/src/oracle/format.js +3 -3
- package/dist/src/oracle/gemini.js +37 -33
- 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 +16 -13
- package/dist/src/oracle/run.js +160 -135
- 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/projectSources/plan.js +27 -0
- package/dist/src/projectSources/url.js +23 -0
- 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 +78 -75
- package/dist/src/sessionStore.js +3 -3
- package/dist/src/version.js +10 -10
- package/dist/vendor/oracle-notifier/README.md +2 -0
- package/package.json +67 -62
- 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 → src/projectSources}/types.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,15 +53,19 @@ 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);
|
|
57
60
|
}
|
|
61
|
+
export function collectTextValues(value, previous = []) {
|
|
62
|
+
const trimmed = value.trim();
|
|
63
|
+
return trimmed ? previous.concat(trimmed) : previous;
|
|
64
|
+
}
|
|
58
65
|
export function parseFloatOption(value) {
|
|
59
66
|
const parsed = Number.parseFloat(value);
|
|
60
67
|
if (Number.isNaN(parsed)) {
|
|
61
|
-
throw new InvalidArgumentError(
|
|
68
|
+
throw new InvalidArgumentError("Value must be a number.");
|
|
62
69
|
}
|
|
63
70
|
return parsed;
|
|
64
71
|
}
|
|
@@ -68,7 +75,7 @@ export function parseIntOption(value) {
|
|
|
68
75
|
}
|
|
69
76
|
const parsed = Number.parseInt(value, 10);
|
|
70
77
|
if (Number.isNaN(parsed)) {
|
|
71
|
-
throw new InvalidArgumentError(
|
|
78
|
+
throw new InvalidArgumentError("Value must be an integer.");
|
|
72
79
|
}
|
|
73
80
|
return parsed;
|
|
74
81
|
}
|
|
@@ -76,9 +83,9 @@ export function parseHeartbeatOption(value) {
|
|
|
76
83
|
if (value == null) {
|
|
77
84
|
return 30;
|
|
78
85
|
}
|
|
79
|
-
if (typeof value ===
|
|
86
|
+
if (typeof value === "number") {
|
|
80
87
|
if (Number.isNaN(value) || value < 0) {
|
|
81
|
-
throw new InvalidArgumentError(
|
|
88
|
+
throw new InvalidArgumentError("Heartbeat interval must be zero or a positive number.");
|
|
82
89
|
}
|
|
83
90
|
return value;
|
|
84
91
|
}
|
|
@@ -86,42 +93,42 @@ export function parseHeartbeatOption(value) {
|
|
|
86
93
|
if (normalized.length === 0) {
|
|
87
94
|
return 30;
|
|
88
95
|
}
|
|
89
|
-
if (normalized ===
|
|
96
|
+
if (normalized === "false" || normalized === "off") {
|
|
90
97
|
return 0;
|
|
91
98
|
}
|
|
92
99
|
const parsed = Number.parseFloat(normalized);
|
|
93
100
|
if (Number.isNaN(parsed) || parsed < 0) {
|
|
94
|
-
throw new InvalidArgumentError(
|
|
101
|
+
throw new InvalidArgumentError("Heartbeat interval must be zero or a positive number.");
|
|
95
102
|
}
|
|
96
103
|
return parsed;
|
|
97
104
|
}
|
|
98
105
|
export function usesDefaultStatusFilters(cmd) {
|
|
99
|
-
const hoursSource = cmd.getOptionValueSource?.(
|
|
100
|
-
const limitSource = cmd.getOptionValueSource?.(
|
|
101
|
-
const allSource = cmd.getOptionValueSource?.(
|
|
102
|
-
return hoursSource ===
|
|
106
|
+
const hoursSource = cmd.getOptionValueSource?.("hours") ?? "default";
|
|
107
|
+
const limitSource = cmd.getOptionValueSource?.("limit") ?? "default";
|
|
108
|
+
const allSource = cmd.getOptionValueSource?.("all") ?? "default";
|
|
109
|
+
return hoursSource === "default" && limitSource === "default" && allSource === "default";
|
|
103
110
|
}
|
|
104
111
|
export function resolvePreviewMode(value) {
|
|
105
|
-
if (typeof value ===
|
|
112
|
+
if (typeof value === "string" && value.length > 0) {
|
|
106
113
|
return value;
|
|
107
114
|
}
|
|
108
115
|
if (value === true) {
|
|
109
|
-
return
|
|
116
|
+
return "summary";
|
|
110
117
|
}
|
|
111
118
|
return undefined;
|
|
112
119
|
}
|
|
113
120
|
export function parseSearchOption(value) {
|
|
114
121
|
const normalized = value.trim().toLowerCase();
|
|
115
|
-
if ([
|
|
122
|
+
if (["on", "true", "1", "yes"].includes(normalized)) {
|
|
116
123
|
return true;
|
|
117
124
|
}
|
|
118
|
-
if ([
|
|
125
|
+
if (["off", "false", "0", "no"].includes(normalized)) {
|
|
119
126
|
return false;
|
|
120
127
|
}
|
|
121
128
|
throw new InvalidArgumentError('Search mode must be "on" or "off".');
|
|
122
129
|
}
|
|
123
130
|
export function normalizeModelOption(value) {
|
|
124
|
-
return (value ??
|
|
131
|
+
return (value ?? "").trim();
|
|
125
132
|
}
|
|
126
133
|
export function normalizeBaseUrl(value) {
|
|
127
134
|
const trimmed = value?.trim();
|
|
@@ -131,8 +138,8 @@ export function parseTimeoutOption(value) {
|
|
|
131
138
|
if (value == null)
|
|
132
139
|
return undefined;
|
|
133
140
|
const normalized = value.trim().toLowerCase();
|
|
134
|
-
if (normalized ===
|
|
135
|
-
return
|
|
141
|
+
if (normalized === "auto")
|
|
142
|
+
return "auto";
|
|
136
143
|
const parsed = Number.parseFloat(normalized);
|
|
137
144
|
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
138
145
|
throw new InvalidArgumentError('Timeout must be a positive number of seconds or "auto".');
|
|
@@ -153,68 +160,74 @@ export function parseDurationOption(value, label) {
|
|
|
153
160
|
return parsed;
|
|
154
161
|
}
|
|
155
162
|
function isGeminiDeepThinkAlias(normalized) {
|
|
156
|
-
return ((normalized.includes(
|
|
157
|
-
normalized.includes(
|
|
158
|
-
normalized.includes(
|
|
159
|
-
normalized.includes(
|
|
163
|
+
return ((normalized.includes("gemini") && normalized.includes("deep")) ||
|
|
164
|
+
normalized.includes("deep-think") ||
|
|
165
|
+
normalized.includes("deep_think") ||
|
|
166
|
+
normalized.includes("deepthink"));
|
|
160
167
|
}
|
|
161
168
|
export function resolveApiModel(modelValue) {
|
|
162
169
|
const normalized = normalizeModelOption(modelValue).toLowerCase();
|
|
163
170
|
if (normalized in MODEL_CONFIGS) {
|
|
164
171
|
return normalized;
|
|
165
172
|
}
|
|
166
|
-
if (normalized.includes(
|
|
173
|
+
if (normalized.includes("/")) {
|
|
167
174
|
return normalized;
|
|
168
175
|
}
|
|
169
|
-
if (normalized.includes(
|
|
170
|
-
return
|
|
176
|
+
if (normalized.includes("grok")) {
|
|
177
|
+
return "grok-4.1";
|
|
178
|
+
}
|
|
179
|
+
if (normalized.includes("claude") && normalized.includes("sonnet")) {
|
|
180
|
+
return "claude-4.6-sonnet";
|
|
171
181
|
}
|
|
172
|
-
if (normalized.includes(
|
|
173
|
-
return
|
|
182
|
+
if (normalized.includes("claude") && normalized.includes("opus")) {
|
|
183
|
+
return "claude-4.1-opus";
|
|
174
184
|
}
|
|
175
|
-
if (normalized.includes(
|
|
176
|
-
return
|
|
185
|
+
if (normalized.includes("5.5") && normalized.includes("pro")) {
|
|
186
|
+
return "gpt-5.5-pro";
|
|
177
187
|
}
|
|
178
|
-
if (normalized.includes(
|
|
179
|
-
return
|
|
188
|
+
if (normalized.includes("5.5")) {
|
|
189
|
+
return "gpt-5.5";
|
|
180
190
|
}
|
|
181
|
-
if (normalized.includes(
|
|
182
|
-
return
|
|
191
|
+
if (normalized.includes("5.4") && normalized.includes("pro")) {
|
|
192
|
+
return "gpt-5.4-pro";
|
|
183
193
|
}
|
|
184
|
-
if (normalized
|
|
185
|
-
return
|
|
194
|
+
if (normalized.includes("5.4")) {
|
|
195
|
+
return "gpt-5.4";
|
|
186
196
|
}
|
|
187
|
-
if (normalized ===
|
|
188
|
-
return
|
|
197
|
+
if (normalized === "claude" || normalized === "sonnet" || /(^|\b)sonnet(\b|$)/.test(normalized)) {
|
|
198
|
+
return "claude-4.6-sonnet";
|
|
189
199
|
}
|
|
190
|
-
if (normalized
|
|
191
|
-
return
|
|
200
|
+
if (normalized === "opus" || normalized === "claude-4.1") {
|
|
201
|
+
return "claude-4.1-opus";
|
|
192
202
|
}
|
|
193
|
-
if (normalized.includes(
|
|
194
|
-
return
|
|
203
|
+
if (normalized.includes("5.0") || normalized === "gpt-5-pro" || normalized === "gpt-5") {
|
|
204
|
+
return "gpt-5-pro";
|
|
195
205
|
}
|
|
196
|
-
if (normalized.includes(
|
|
197
|
-
return
|
|
206
|
+
if (normalized.includes("5-pro") && !normalized.includes("5.1")) {
|
|
207
|
+
return "gpt-5-pro";
|
|
198
208
|
}
|
|
199
|
-
if (normalized.includes(
|
|
200
|
-
return
|
|
209
|
+
if (normalized.includes("5.2") && normalized.includes("pro")) {
|
|
210
|
+
return "gpt-5.2-pro";
|
|
201
211
|
}
|
|
202
|
-
if (normalized.includes(
|
|
203
|
-
|
|
204
|
-
|
|
212
|
+
if (normalized.includes("5.1") && normalized.includes("pro")) {
|
|
213
|
+
return "gpt-5.1-pro";
|
|
214
|
+
}
|
|
215
|
+
if (normalized.includes("codex")) {
|
|
216
|
+
if (normalized.includes("max")) {
|
|
217
|
+
throw new InvalidArgumentError("gpt-5.1-codex-max is not available yet. OpenAI has not released the API.");
|
|
205
218
|
}
|
|
206
|
-
return
|
|
219
|
+
return "gpt-5.1-codex";
|
|
207
220
|
}
|
|
208
221
|
if (isGeminiDeepThinkAlias(normalized)) {
|
|
209
|
-
throw new InvalidArgumentError(
|
|
222
|
+
throw new InvalidArgumentError("Gemini Deep Think is browser-only today. Use --engine browser --model gemini-3-deep-think.");
|
|
210
223
|
}
|
|
211
|
-
if (normalized.includes(
|
|
212
|
-
if (normalized.includes(
|
|
213
|
-
return
|
|
224
|
+
if (normalized.includes("gemini")) {
|
|
225
|
+
if (normalized.includes("3.1") || normalized.includes("3_1")) {
|
|
226
|
+
return "gemini-3.1-pro";
|
|
214
227
|
}
|
|
215
|
-
return
|
|
228
|
+
return "gemini-3-pro";
|
|
216
229
|
}
|
|
217
|
-
if (normalized.includes(
|
|
230
|
+
if (normalized.includes("pro")) {
|
|
218
231
|
return DEFAULT_MODEL;
|
|
219
232
|
}
|
|
220
233
|
// Passthrough for custom/OpenRouter model IDs.
|
|
@@ -228,73 +241,85 @@ export function inferModelFromLabel(modelValue) {
|
|
|
228
241
|
if (normalized in MODEL_CONFIGS) {
|
|
229
242
|
return normalized;
|
|
230
243
|
}
|
|
231
|
-
if (normalized.includes(
|
|
244
|
+
if (normalized.includes("/")) {
|
|
232
245
|
return normalized;
|
|
233
246
|
}
|
|
234
|
-
if (normalized.includes(
|
|
235
|
-
return
|
|
247
|
+
if (normalized.includes("grok")) {
|
|
248
|
+
return "grok-4.1";
|
|
236
249
|
}
|
|
237
|
-
if (normalized.includes(
|
|
238
|
-
return
|
|
250
|
+
if (normalized.includes("claude") && normalized.includes("sonnet")) {
|
|
251
|
+
return "claude-4.6-sonnet";
|
|
239
252
|
}
|
|
240
|
-
if (normalized.includes(
|
|
241
|
-
return
|
|
253
|
+
if (normalized.includes("claude") && normalized.includes("opus")) {
|
|
254
|
+
return "claude-4.1-opus";
|
|
242
255
|
}
|
|
243
|
-
if (normalized.includes(
|
|
244
|
-
return
|
|
256
|
+
if (normalized.includes("codex")) {
|
|
257
|
+
return "gpt-5.1-codex";
|
|
245
258
|
}
|
|
246
259
|
if (isGeminiDeepThinkAlias(normalized)) {
|
|
247
|
-
return
|
|
260
|
+
return "gemini-3-pro-deep-think";
|
|
248
261
|
}
|
|
249
|
-
if (normalized.includes(
|
|
250
|
-
if (normalized.includes(
|
|
251
|
-
return
|
|
262
|
+
if (normalized.includes("gemini")) {
|
|
263
|
+
if (normalized.includes("3.1") || normalized.includes("3_1")) {
|
|
264
|
+
return "gemini-3.1-pro";
|
|
252
265
|
}
|
|
253
|
-
return
|
|
266
|
+
return "gemini-3-pro";
|
|
267
|
+
}
|
|
268
|
+
if (normalized.includes("classic")) {
|
|
269
|
+
return "gpt-5-pro";
|
|
270
|
+
}
|
|
271
|
+
if (normalized.includes("thinking") && normalized.includes("heavy")) {
|
|
272
|
+
return "gpt-5.5";
|
|
273
|
+
}
|
|
274
|
+
if ((normalized.includes("5.5") || normalized.includes("5_5")) && normalized.includes("pro")) {
|
|
275
|
+
return "gpt-5.5-pro";
|
|
254
276
|
}
|
|
255
|
-
if (normalized.includes(
|
|
256
|
-
return
|
|
277
|
+
if (normalized.includes("5.5") || normalized.includes("5_5")) {
|
|
278
|
+
return "gpt-5.5";
|
|
257
279
|
}
|
|
258
|
-
if ((normalized.includes(
|
|
259
|
-
return
|
|
280
|
+
if ((normalized.includes("5.4") || normalized.includes("5_4")) && normalized.includes("pro")) {
|
|
281
|
+
return "gpt-5.4-pro";
|
|
260
282
|
}
|
|
261
|
-
if (normalized.includes(
|
|
262
|
-
return
|
|
283
|
+
if (normalized.includes("5.4") || normalized.includes("5_4")) {
|
|
284
|
+
return "gpt-5.4";
|
|
263
285
|
}
|
|
264
|
-
if ((normalized.includes(
|
|
265
|
-
return
|
|
286
|
+
if ((normalized.includes("5.2") || normalized.includes("5_2")) && normalized.includes("pro")) {
|
|
287
|
+
return "gpt-5.2-pro";
|
|
266
288
|
}
|
|
267
289
|
// Browser-only: pass through 5.2 thinking/instant variants for browser label mapping
|
|
268
|
-
if ((normalized.includes(
|
|
269
|
-
|
|
290
|
+
if ((normalized.includes("5.2") || normalized.includes("5_2")) &&
|
|
291
|
+
normalized.includes("thinking")) {
|
|
292
|
+
return "gpt-5.2-thinking";
|
|
270
293
|
}
|
|
271
|
-
if ((normalized.includes(
|
|
272
|
-
|
|
294
|
+
if ((normalized.includes("5.2") || normalized.includes("5_2")) &&
|
|
295
|
+
normalized.includes("instant")) {
|
|
296
|
+
return "gpt-5.2-instant";
|
|
273
297
|
}
|
|
274
|
-
if (normalized.includes(
|
|
275
|
-
return
|
|
298
|
+
if (normalized.includes("5.0") || normalized.includes("5-pro")) {
|
|
299
|
+
return "gpt-5-pro";
|
|
276
300
|
}
|
|
277
|
-
if (normalized.includes(
|
|
278
|
-
normalized.includes(
|
|
279
|
-
!normalized.includes(
|
|
280
|
-
!normalized.includes(
|
|
281
|
-
!normalized.includes(
|
|
282
|
-
|
|
301
|
+
if (normalized.includes("gpt-5") &&
|
|
302
|
+
normalized.includes("pro") &&
|
|
303
|
+
!normalized.includes("5.1") &&
|
|
304
|
+
!normalized.includes("5.2") &&
|
|
305
|
+
!normalized.includes("5.5") &&
|
|
306
|
+
!normalized.includes("5.4")) {
|
|
307
|
+
return "gpt-5-pro";
|
|
283
308
|
}
|
|
284
|
-
if ((normalized.includes(
|
|
285
|
-
return
|
|
309
|
+
if ((normalized.includes("5.1") || normalized.includes("5_1")) && normalized.includes("pro")) {
|
|
310
|
+
return "gpt-5.1-pro";
|
|
286
311
|
}
|
|
287
|
-
if (normalized.includes(
|
|
312
|
+
if (normalized.includes("pro")) {
|
|
288
313
|
return DEFAULT_MODEL;
|
|
289
314
|
}
|
|
290
|
-
if (normalized.includes(
|
|
291
|
-
return
|
|
315
|
+
if (normalized.includes("5.1") || normalized.includes("5_1")) {
|
|
316
|
+
return "gpt-5.1";
|
|
292
317
|
}
|
|
293
|
-
if (normalized.includes(
|
|
294
|
-
return
|
|
318
|
+
if (normalized.includes("thinking")) {
|
|
319
|
+
return "gpt-5.2-thinking";
|
|
295
320
|
}
|
|
296
|
-
if (normalized.includes(
|
|
297
|
-
return
|
|
321
|
+
if (normalized.includes("instant") || normalized.includes("fast")) {
|
|
322
|
+
return "gpt-5.2-instant";
|
|
298
323
|
}
|
|
299
|
-
return
|
|
324
|
+
return "gpt-5.2";
|
|
300
325
|
}
|
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";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { buildBrowserConfig } from "./browserConfig.js";
|
|
5
|
+
import { readFiles } from "../oracle/files.js";
|
|
6
|
+
import { loadUserConfig } from "../config.js";
|
|
7
|
+
import { resolveConfiguredMaxFileSizeBytes } from "./fileSize.js";
|
|
8
|
+
import { runBrowserProjectSources } from "../browser/projectSourcesRunner.js";
|
|
9
|
+
import { normalizeProjectSourcesUrl } from "../projectSources/url.js";
|
|
10
|
+
export async function runProjectSourcesCliCommand(operation, options) {
|
|
11
|
+
const { config: userConfig } = await loadUserConfig();
|
|
12
|
+
const configuredUrl = userConfig.browser?.chatgptUrl ?? userConfig.browser?.url;
|
|
13
|
+
const projectUrl = normalizeProjectSourcesUrl(options.chatgptUrl ?? configuredUrl ?? "");
|
|
14
|
+
const maxFileSizeBytes = options.maxFileSizeBytes ?? resolveConfiguredMaxFileSizeBytes(userConfig, process.env);
|
|
15
|
+
const files = operation === "add"
|
|
16
|
+
? await resolveProjectSourceFiles(options.file ?? [], {
|
|
17
|
+
cwd: process.cwd(),
|
|
18
|
+
maxFileSizeBytes,
|
|
19
|
+
})
|
|
20
|
+
: [];
|
|
21
|
+
if (operation === "add" && files.length === 0) {
|
|
22
|
+
throw new Error("project-sources add requires at least one --file.");
|
|
23
|
+
}
|
|
24
|
+
const browserConfig = await buildProjectSourcesBrowserConfig({
|
|
25
|
+
options,
|
|
26
|
+
projectUrl,
|
|
27
|
+
configuredBrowser: userConfig.browser ?? {},
|
|
28
|
+
});
|
|
29
|
+
const result = await runBrowserProjectSources({
|
|
30
|
+
operation,
|
|
31
|
+
chatgptUrl: projectUrl,
|
|
32
|
+
files,
|
|
33
|
+
dryRun: options.dryRun,
|
|
34
|
+
config: browserConfig,
|
|
35
|
+
log: (message) => {
|
|
36
|
+
if (options.verbose || !message.startsWith("[debug]")) {
|
|
37
|
+
console.log(chalk.dim(message));
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
printProjectSourcesResult(result, Boolean(options.json));
|
|
42
|
+
}
|
|
43
|
+
export async function resolveProjectSourceFiles(fileInputs, options) {
|
|
44
|
+
const files = await readFiles(fileInputs, {
|
|
45
|
+
cwd: options.cwd,
|
|
46
|
+
maxFileSizeBytes: options.maxFileSizeBytes,
|
|
47
|
+
readContents: false,
|
|
48
|
+
});
|
|
49
|
+
const attachments = [];
|
|
50
|
+
for (const file of files) {
|
|
51
|
+
const stats = await fs.stat(file.path);
|
|
52
|
+
attachments.push({
|
|
53
|
+
path: file.path,
|
|
54
|
+
displayPath: path.relative(options.cwd, file.path) || path.basename(file.path),
|
|
55
|
+
sizeBytes: stats.size,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return attachments;
|
|
59
|
+
}
|
|
60
|
+
export async function buildProjectSourcesBrowserConfig({ options, projectUrl, configuredBrowser, }) {
|
|
61
|
+
const flagConfig = removeUndefined(await buildBrowserConfig({
|
|
62
|
+
...options,
|
|
63
|
+
model: "gpt-5.5-pro",
|
|
64
|
+
chatgptUrl: projectUrl,
|
|
65
|
+
}));
|
|
66
|
+
const envProfileDir = process.env.ORACLE_BROWSER_PROFILE_DIR?.trim();
|
|
67
|
+
const manualLogin = flagConfig.manualLogin ?? configuredBrowser.manualLogin ?? (envProfileDir ? true : undefined);
|
|
68
|
+
const manualLoginProfileDir = manualLogin === true
|
|
69
|
+
? (flagConfig.manualLoginProfileDir ??
|
|
70
|
+
configuredBrowser.manualLoginProfileDir ??
|
|
71
|
+
envProfileDir ??
|
|
72
|
+
null)
|
|
73
|
+
: null;
|
|
74
|
+
return {
|
|
75
|
+
...configuredBrowser,
|
|
76
|
+
...flagConfig,
|
|
77
|
+
url: projectUrl,
|
|
78
|
+
chatgptUrl: projectUrl,
|
|
79
|
+
cookieSync: manualLogin ? false : (flagConfig.cookieSync ?? configuredBrowser.cookieSync),
|
|
80
|
+
manualLogin,
|
|
81
|
+
manualLoginProfileDir,
|
|
82
|
+
desiredModel: null,
|
|
83
|
+
modelStrategy: "ignore",
|
|
84
|
+
researchMode: "off",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function removeUndefined(value) {
|
|
88
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
89
|
+
}
|
|
90
|
+
function printProjectSourcesResult(result, json) {
|
|
91
|
+
if (json) {
|
|
92
|
+
console.log(JSON.stringify(result, null, 2));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (result.status === "dry-run") {
|
|
96
|
+
console.log(chalk.bold(`Project Sources ${result.operation} dry run`));
|
|
97
|
+
console.log(`Project: ${result.projectUrl}`);
|
|
98
|
+
const plan = result.plannedUploads ?? [];
|
|
99
|
+
if (plan.length > 0) {
|
|
100
|
+
console.log(`Planned uploads: ${plan.length}`);
|
|
101
|
+
for (const upload of plan) {
|
|
102
|
+
console.log(` batch ${upload.batch}: ${upload.displayPath}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log(chalk.bold(`Project Sources ${result.operation} completed`));
|
|
108
|
+
console.log(`Project: ${result.projectUrl}`);
|
|
109
|
+
const before = result.sourcesBefore?.length ?? 0;
|
|
110
|
+
const after = result.sourcesAfter?.length ?? 0;
|
|
111
|
+
console.log(`Before: ${before}`);
|
|
112
|
+
console.log(`After: ${after}`);
|
|
113
|
+
if (result.added && result.added.length > 0) {
|
|
114
|
+
console.log(`Added: ${result.added.map((source) => source.name).join(", ")}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -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,51 +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
|
|
7
|
-
import { resolveConfiguredMaxFileSizeBytes } 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";
|
|
8
8
|
export function resolveRunOptionsFromConfig({ prompt, files = [], model, models, engine, userConfig, env = process.env, }) {
|
|
9
9
|
const resolvedEngine = resolveEngineWithConfig({ engine, configEngine: userConfig?.engine, env });
|
|
10
|
-
const browserRequested = engine ===
|
|
11
|
-
const browserConfigured = userConfig?.engine ===
|
|
10
|
+
const browserRequested = engine === "browser";
|
|
11
|
+
const browserConfigured = userConfig?.engine === "browser";
|
|
12
12
|
const requestedModelList = Array.isArray(models) ? models : [];
|
|
13
|
-
const normalizedRequestedModels = requestedModelList
|
|
13
|
+
const normalizedRequestedModels = requestedModelList
|
|
14
|
+
.map((entry) => normalizeModelOption(entry))
|
|
15
|
+
.filter(Boolean);
|
|
14
16
|
const cliModelArg = normalizeModelOption(model ?? userConfig?.model) || DEFAULT_MODEL;
|
|
15
|
-
const inferredModel = resolvedEngine ===
|
|
17
|
+
const inferredModel = resolvedEngine === "browser" && normalizedRequestedModels.length === 0
|
|
16
18
|
? inferModelFromLabel(cliModelArg)
|
|
17
19
|
: resolveApiModel(cliModelArg);
|
|
18
|
-
// Browser engine maps Pro/legacy aliases to the latest ChatGPT picker targets
|
|
19
|
-
const resolvedModel = resolvedEngine ===
|
|
20
|
-
const isCodex = resolvedModel.startsWith(
|
|
21
|
-
const isClaude = resolvedModel.startsWith(
|
|
22
|
-
const isGrok = resolvedModel.startsWith(
|
|
23
|
-
const isGeminiApiOnly = resolvedModel ===
|
|
24
|
-
const engineWasBrowser = resolvedEngine ===
|
|
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";
|
|
25
27
|
const allModels = normalizedRequestedModels.length > 0
|
|
26
28
|
? Array.from(new Set(normalizedRequestedModels.map((entry) => resolveApiModel(entry))))
|
|
27
29
|
: [resolvedModel];
|
|
28
|
-
const includesGeminiApiOnly = allModels.some((m) => m ===
|
|
30
|
+
const includesGeminiApiOnly = allModels.some((m) => m === "gemini-3.1-pro");
|
|
29
31
|
if ((browserRequested || browserConfigured) && includesGeminiApiOnly) {
|
|
30
|
-
throw new PromptValidationError(
|
|
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 });
|
|
31
33
|
}
|
|
32
|
-
const isBrowserCompatible = (m) => m.startsWith(
|
|
34
|
+
const isBrowserCompatible = (m) => m.startsWith("gpt-") || m.startsWith("gemini");
|
|
33
35
|
const hasNonBrowserCompatibleTarget = (browserRequested || browserConfigured) && allModels.some((m) => !isBrowserCompatible(m));
|
|
34
36
|
if (hasNonBrowserCompatibleTarget) {
|
|
35
|
-
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 });
|
|
36
38
|
}
|
|
37
39
|
const engineCoercedToApi = engineWasBrowser && (isCodex || isClaude || isGrok || isGeminiApiOnly);
|
|
38
|
-
const fixedEngine = isCodex || isClaude || isGrok || isGeminiApiOnly || normalizedRequestedModels.length > 0
|
|
40
|
+
const fixedEngine = isCodex || isClaude || isGrok || isGeminiApiOnly || normalizedRequestedModels.length > 0
|
|
41
|
+
? "api"
|
|
42
|
+
: resolvedEngine;
|
|
39
43
|
const promptWithSuffix = userConfig?.promptSuffix && userConfig.promptSuffix.trim().length > 0
|
|
40
44
|
? `${prompt.trim()}\n${userConfig.promptSuffix}`
|
|
41
45
|
: prompt;
|
|
42
|
-
const search = userConfig?.search !==
|
|
46
|
+
const search = userConfig?.search !== "off";
|
|
43
47
|
const heartbeatIntervalMs = userConfig?.heartbeatSeconds !== undefined ? userConfig.heartbeatSeconds * 1000 : 30_000;
|
|
44
48
|
const maxFileSizeBytes = resolveConfiguredMaxFileSizeBytes(userConfig, env);
|
|
45
49
|
const baseUrl = normalizeBaseUrl(userConfig?.apiBaseUrl ??
|
|
46
50
|
(isClaude ? env.ANTHROPIC_BASE_URL : isGrok ? env.XAI_BASE_URL : env.OPENAI_BASE_URL));
|
|
47
51
|
const uniqueMultiModels = normalizedRequestedModels.length > 0 ? allModels : [];
|
|
48
|
-
const includesCodexMultiModel = uniqueMultiModels.some((entry) => entry.startsWith(
|
|
52
|
+
const includesCodexMultiModel = uniqueMultiModels.some((entry) => entry.startsWith("gpt-5.1-codex"));
|
|
49
53
|
if (includesCodexMultiModel && browserRequested) {
|
|
50
54
|
// Silent coerce; multi-model still forces API.
|
|
51
55
|
}
|
|
@@ -69,8 +73,8 @@ export function resolveRunOptionsFromConfig({ prompt, files = [], model, models,
|
|
|
69
73
|
function resolveEngineWithConfig({ engine, configEngine, env, }) {
|
|
70
74
|
if (engine)
|
|
71
75
|
return engine;
|
|
72
|
-
const envOverride = (env.ORACLE_ENGINE ??
|
|
73
|
-
if (envOverride ===
|
|
76
|
+
const envOverride = (env.ORACLE_ENGINE ?? "").trim().toLowerCase();
|
|
77
|
+
if (envOverride === "api" || envOverride === "browser") {
|
|
74
78
|
return envOverride;
|
|
75
79
|
}
|
|
76
80
|
if (configEngine)
|
|
@@ -78,7 +82,7 @@ function resolveEngineWithConfig({ engine, configEngine, env, }) {
|
|
|
78
82
|
return resolveEngine({ engine: undefined, env });
|
|
79
83
|
}
|
|
80
84
|
function resolveEffectiveModelId(model) {
|
|
81
|
-
if (typeof model ===
|
|
85
|
+
if (typeof model === "string" && model.startsWith("gemini")) {
|
|
82
86
|
return resolveGeminiModelId(model);
|
|
83
87
|
}
|
|
84
88
|
const config = MODEL_CONFIGS[model];
|