@steipete/oracle 0.9.0 → 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 +61 -48
- package/dist/bin/oracle-cli.js +455 -402
- 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 +275 -117
- package/dist/src/browser/actions/navigation.js +161 -137
- 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 +390 -295
- 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 +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 +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 +62 -48
- 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 +2 -2
- 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 +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 +127 -106
- 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 +32 -28
- package/dist/src/cli/sessionCommand.js +31 -21
- package/dist/src/cli/sessionDisplay.js +95 -81
- package/dist/src/cli/sessionLineage.js +6 -2
- package/dist/src/cli/sessionRunner.js +103 -93
- 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/server.js +16 -12
- package/dist/src/mcp/tools/consult.js +51 -47
- 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 +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 +156 -134
- 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 +77 -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 +66 -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/types.js +0 -1
- 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
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
import { spawn } from
|
|
2
|
-
import fs from
|
|
3
|
-
import path from
|
|
4
|
-
import { randomBytes } from
|
|
5
|
-
import chalk from
|
|
6
|
-
import { getOracleHomeDir } from
|
|
7
|
-
import { parseHostPort, normalizeHostPort, formatBridgeConnectionString } from
|
|
8
|
-
import { serveRemote } from
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { randomBytes } from "node:crypto";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { getOracleHomeDir } from "../../oracleHome.js";
|
|
7
|
+
import { parseHostPort, normalizeHostPort, formatBridgeConnectionString, } from "../../bridge/connection.js";
|
|
8
|
+
import { serveRemote } from "../../remote/server.js";
|
|
9
9
|
export async function runBridgeHost(options) {
|
|
10
|
-
const bindRaw = options.bind?.trim() ||
|
|
10
|
+
const bindRaw = options.bind?.trim() || "127.0.0.1:9473";
|
|
11
11
|
const { hostname: bindHost, port: bindPort } = parseHostPort(bindRaw);
|
|
12
|
-
const tokenRaw = options.token?.trim() ||
|
|
13
|
-
const token = tokenRaw ===
|
|
12
|
+
const tokenRaw = options.token?.trim() || "auto";
|
|
13
|
+
const token = tokenRaw === "auto" ? randomBytes(16).toString("hex") : tokenRaw;
|
|
14
14
|
if (!token.trim()) {
|
|
15
|
-
throw new Error(
|
|
15
|
+
throw new Error("Token is required (use --token auto to generate one).");
|
|
16
16
|
}
|
|
17
|
-
const writeConnectionPath = options.writeConnection?.trim() || path.join(getOracleHomeDir(),
|
|
17
|
+
const writeConnectionPath = options.writeConnection?.trim() || path.join(getOracleHomeDir(), "bridge-connection.json");
|
|
18
18
|
const sshTarget = options.ssh?.trim();
|
|
19
|
-
const sshRemotePort = typeof options.sshRemotePort ===
|
|
19
|
+
const sshRemotePort = typeof options.sshRemotePort === "number" ? options.sshRemotePort : bindPort;
|
|
20
20
|
if (sshRemotePort <= 0 || sshRemotePort > 65_535) {
|
|
21
21
|
throw new Error(`Invalid --ssh-remote-port: ${sshRemotePort}. Expected 1-65535.`);
|
|
22
22
|
}
|
|
23
|
-
const connectionHostForClient = sshTarget
|
|
23
|
+
const connectionHostForClient = sshTarget
|
|
24
|
+
? normalizeHostPort("127.0.0.1", sshRemotePort)
|
|
25
|
+
: normalizeHostPort(bindHost === "0.0.0.0" || bindHost === "::" ? "127.0.0.1" : bindHost, bindPort);
|
|
24
26
|
const artifact = await upsertConnectionArtifact(writeConnectionPath, {
|
|
25
27
|
remoteHost: connectionHostForClient,
|
|
26
28
|
remoteToken: token,
|
|
@@ -52,11 +54,11 @@ export async function runBridgeHost(options) {
|
|
|
52
54
|
});
|
|
53
55
|
return;
|
|
54
56
|
}
|
|
55
|
-
console.log(chalk.cyanBright(
|
|
57
|
+
console.log(chalk.cyanBright("Bridge host starting..."));
|
|
56
58
|
console.log(chalk.dim(`- Local bind: ${normalizeHostPort(bindHost, bindPort)}`));
|
|
57
59
|
console.log(chalk.dim(`- Connection artifact: ${writeConnectionPath}`));
|
|
58
60
|
console.log(chalk.dim(`- Client remoteHost: ${artifact.remoteHost}`));
|
|
59
|
-
console.log(chalk.dim(
|
|
61
|
+
console.log(chalk.dim("Token stored in connection artifact (not printed). Use --print or --print-token if needed."));
|
|
60
62
|
let tunnel = null;
|
|
61
63
|
if (sshTarget) {
|
|
62
64
|
tunnel = startReverseTunnel({
|
|
@@ -70,7 +72,7 @@ export async function runBridgeHost(options) {
|
|
|
70
72
|
console.log(chalk.dim(`Reverse SSH tunnel active (remote 127.0.0.1:${sshRemotePort} -> local 127.0.0.1:${bindPort})`));
|
|
71
73
|
}
|
|
72
74
|
const filteredServeLogger = (message) => {
|
|
73
|
-
if (message.includes(
|
|
75
|
+
if (message.includes("Access token:")) {
|
|
74
76
|
return;
|
|
75
77
|
}
|
|
76
78
|
console.log(message);
|
|
@@ -91,12 +93,12 @@ async function upsertConnectionArtifact(filePath, input) {
|
|
|
91
93
|
const dir = path.dirname(filePath);
|
|
92
94
|
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
93
95
|
const now = new Date().toISOString();
|
|
94
|
-
const existing = await fs.readFile(filePath,
|
|
96
|
+
const existing = await fs.readFile(filePath, "utf8").catch(() => null);
|
|
95
97
|
let createdAt = now;
|
|
96
98
|
if (existing) {
|
|
97
99
|
try {
|
|
98
100
|
const parsed = JSON.parse(existing);
|
|
99
|
-
if (typeof parsed.createdAt ===
|
|
101
|
+
if (typeof parsed.createdAt === "string" && parsed.createdAt.trim().length > 0) {
|
|
100
102
|
createdAt = parsed.createdAt;
|
|
101
103
|
}
|
|
102
104
|
}
|
|
@@ -113,9 +115,9 @@ async function upsertConnectionArtifact(filePath, input) {
|
|
|
113
115
|
};
|
|
114
116
|
const contents = `${JSON.stringify(artifact, null, 2)}\n`;
|
|
115
117
|
const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
116
|
-
await fs.writeFile(tempPath, contents, { encoding:
|
|
118
|
+
await fs.writeFile(tempPath, contents, { encoding: "utf8", mode: 0o600 });
|
|
117
119
|
await fs.rename(tempPath, filePath);
|
|
118
|
-
if (process.platform !==
|
|
120
|
+
if (process.platform !== "win32") {
|
|
119
121
|
await fs.chmod(filePath, 0o600).catch(() => undefined);
|
|
120
122
|
}
|
|
121
123
|
return artifact;
|
|
@@ -129,27 +131,27 @@ function startReverseTunnel({ sshTarget, remotePort, localPort, identity, extraA
|
|
|
129
131
|
if (stopped)
|
|
130
132
|
return;
|
|
131
133
|
const args = [
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
"-N",
|
|
135
|
+
"-R",
|
|
134
136
|
`${remotePort}:127.0.0.1:${localPort}`,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
"-o",
|
|
138
|
+
"ExitOnForwardFailure=yes",
|
|
139
|
+
"-o",
|
|
140
|
+
"ServerAliveInterval=30",
|
|
141
|
+
"-o",
|
|
142
|
+
"ServerAliveCountMax=3",
|
|
141
143
|
];
|
|
142
144
|
if (identity) {
|
|
143
|
-
args.push(
|
|
145
|
+
args.push("-i", identity);
|
|
144
146
|
}
|
|
145
147
|
if (extraArgs) {
|
|
146
148
|
args.push(...splitArgs(extraArgs));
|
|
147
149
|
}
|
|
148
150
|
args.push(sshTarget);
|
|
149
|
-
child = spawn(
|
|
151
|
+
child = spawn("ssh", args, { stdio: "ignore" });
|
|
150
152
|
const pid = child.pid;
|
|
151
|
-
log(`[bridge host] ssh tunnel started${pid ? ` (pid ${pid})` :
|
|
152
|
-
child.once(
|
|
153
|
+
log(`[bridge host] ssh tunnel started${pid ? ` (pid ${pid})` : ""}: ${sshTarget}`);
|
|
154
|
+
child.once("exit", (code, signal) => {
|
|
153
155
|
child = null;
|
|
154
156
|
if (stopped)
|
|
155
157
|
return;
|
|
@@ -179,16 +181,16 @@ function startReverseTunnel({ sshTarget, remotePort, localPort, identity, extraA
|
|
|
179
181
|
}
|
|
180
182
|
function splitArgs(input) {
|
|
181
183
|
const args = [];
|
|
182
|
-
let current =
|
|
184
|
+
let current = "";
|
|
183
185
|
let quote = null;
|
|
184
186
|
const push = () => {
|
|
185
187
|
const trimmed = current.trim();
|
|
186
188
|
if (trimmed.length)
|
|
187
189
|
args.push(trimmed);
|
|
188
|
-
current =
|
|
190
|
+
current = "";
|
|
189
191
|
};
|
|
190
192
|
for (let i = 0; i < input.length; i += 1) {
|
|
191
|
-
const ch = input[i] ??
|
|
193
|
+
const ch = input[i] ?? "";
|
|
192
194
|
if (quote) {
|
|
193
195
|
if (ch === quote) {
|
|
194
196
|
quote = null;
|
|
@@ -214,46 +216,46 @@ function splitArgs(input) {
|
|
|
214
216
|
async function spawnBridgeHostInBackground({ bind, token, writeConnectionPath, sshTarget, sshRemotePort, sshIdentity, sshExtraArgs, }) {
|
|
215
217
|
const oracleHome = getOracleHomeDir();
|
|
216
218
|
await fs.mkdir(oracleHome, { recursive: true, mode: 0o700 });
|
|
217
|
-
const logPath = path.join(oracleHome,
|
|
218
|
-
const pidPath = path.join(oracleHome,
|
|
219
|
-
const logHandle = await fs.open(logPath,
|
|
220
|
-
const stdio = [
|
|
219
|
+
const logPath = path.join(oracleHome, "bridge-host.log");
|
|
220
|
+
const pidPath = path.join(oracleHome, "bridge-host.pid");
|
|
221
|
+
const logHandle = await fs.open(logPath, "a");
|
|
222
|
+
const stdio = ["ignore", logHandle.fd, logHandle.fd];
|
|
221
223
|
const scriptPath = process.argv[1];
|
|
222
224
|
if (!scriptPath) {
|
|
223
|
-
throw new Error(
|
|
225
|
+
throw new Error("Unable to determine CLI entrypoint for background mode.");
|
|
224
226
|
}
|
|
225
227
|
const args = [
|
|
226
228
|
scriptPath,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
"bridge",
|
|
230
|
+
"host",
|
|
231
|
+
"--foreground",
|
|
232
|
+
"--bind",
|
|
231
233
|
bind,
|
|
232
|
-
|
|
234
|
+
"--token",
|
|
233
235
|
token,
|
|
234
|
-
|
|
236
|
+
"--write-connection",
|
|
235
237
|
writeConnectionPath,
|
|
236
238
|
];
|
|
237
239
|
if (sshTarget) {
|
|
238
|
-
args.push(
|
|
240
|
+
args.push("--ssh", sshTarget);
|
|
239
241
|
}
|
|
240
|
-
if (typeof sshRemotePort ===
|
|
241
|
-
args.push(
|
|
242
|
+
if (typeof sshRemotePort === "number") {
|
|
243
|
+
args.push("--ssh-remote-port", String(sshRemotePort));
|
|
242
244
|
}
|
|
243
245
|
if (sshIdentity) {
|
|
244
|
-
args.push(
|
|
246
|
+
args.push("--ssh-identity", sshIdentity);
|
|
245
247
|
}
|
|
246
248
|
if (sshExtraArgs) {
|
|
247
|
-
args.push(
|
|
249
|
+
args.push("--ssh-extra-args", sshExtraArgs);
|
|
248
250
|
}
|
|
249
251
|
const child = spawn(process.execPath, args, { detached: true, stdio });
|
|
250
252
|
child.unref();
|
|
251
|
-
await fs.writeFile(pidPath, `${child.pid ??
|
|
252
|
-
if (process.platform !==
|
|
253
|
+
await fs.writeFile(pidPath, `${child.pid ?? ""}\n`, { encoding: "utf8", mode: 0o600 });
|
|
254
|
+
if (process.platform !== "win32") {
|
|
253
255
|
await fs.chmod(pidPath, 0o600).catch(() => undefined);
|
|
254
256
|
}
|
|
255
257
|
await logHandle.close();
|
|
256
|
-
console.log(chalk.green(`Bridge host running in background (pid ${child.pid ??
|
|
258
|
+
console.log(chalk.green(`Bridge host running in background (pid ${child.pid ?? "?"})`));
|
|
257
259
|
console.log(chalk.dim(`- Log: ${logPath}`));
|
|
258
260
|
console.log(chalk.dim(`- PID: ${pidPath}`));
|
|
259
261
|
}
|
|
@@ -1,57 +1,62 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from
|
|
3
|
-
import { CHATGPT_URL, DEFAULT_MODEL_STRATEGY, DEFAULT_MODEL_TARGET, isTemporaryChatUrl, normalizeChatgptUrl, parseDuration } from
|
|
4
|
-
import { normalizeBrowserModelStrategy } from
|
|
5
|
-
import { getOracleHomeDir } from
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { CHATGPT_URL, DEFAULT_MODEL_STRATEGY, DEFAULT_MODEL_TARGET, isTemporaryChatUrl, normalizeChatgptUrl, parseDuration, } from "../browserMode.js";
|
|
4
|
+
import { normalizeBrowserModelStrategy } from "../browser/modelStrategy.js";
|
|
5
|
+
import { getOracleHomeDir } from "../oracleHome.js";
|
|
6
6
|
const DEFAULT_BROWSER_TIMEOUT_MS = 1_200_000;
|
|
7
7
|
const DEFAULT_BROWSER_INPUT_TIMEOUT_MS = 60_000;
|
|
8
8
|
const DEFAULT_BROWSER_RECHECK_TIMEOUT_MS = 120_000;
|
|
9
9
|
const DEFAULT_BROWSER_AUTO_REATTACH_TIMEOUT_MS = 120_000;
|
|
10
|
-
const DEFAULT_CHROME_PROFILE =
|
|
10
|
+
const DEFAULT_CHROME_PROFILE = "Default";
|
|
11
11
|
// Ordered array: most specific models first to ensure correct selection.
|
|
12
12
|
// The browser label is passed to the model picker which fuzzy-matches against ChatGPT's UI.
|
|
13
13
|
const BROWSER_MODEL_LABELS = [
|
|
14
14
|
// Most specific first (e.g., "gpt-5.2-thinking" before "gpt-5.2")
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
19
|
-
[
|
|
20
|
-
[
|
|
15
|
+
["gpt-5.5-pro", "GPT-5.5 Pro"],
|
|
16
|
+
["gpt-5.5", "Thinking 5.5"],
|
|
17
|
+
["gpt-5.4-pro", "GPT-5.4 Pro"],
|
|
18
|
+
["gpt-5.2-thinking", "GPT-5.2 Thinking"],
|
|
19
|
+
["gpt-5.2-instant", "GPT-5.2 Instant"],
|
|
20
|
+
["gpt-5.2-pro", "GPT-5.5 Pro"],
|
|
21
|
+
["gpt-5.1-pro", "GPT-5.5 Pro"],
|
|
22
|
+
["gpt-5-pro", "GPT-5.5 Pro"],
|
|
21
23
|
// Base models last (least specific)
|
|
22
|
-
[
|
|
23
|
-
[
|
|
24
|
-
[
|
|
25
|
-
[
|
|
26
|
-
[
|
|
24
|
+
["gpt-5.4", "Thinking 5.4"],
|
|
25
|
+
["gpt-5.2", "GPT-5.2"], // Selects "Auto" in ChatGPT UI
|
|
26
|
+
["gpt-5.1", "GPT-5.2"], // Legacy alias → Auto
|
|
27
|
+
["gemini-3-pro", "Gemini 3 Pro"],
|
|
28
|
+
["gemini-3-pro-deep-think", "gemini-3-deep-think"],
|
|
27
29
|
];
|
|
28
30
|
export function normalizeChatGptModelForBrowser(model) {
|
|
29
31
|
const normalized = model.toLowerCase();
|
|
30
|
-
if (!normalized.startsWith(
|
|
32
|
+
if (!normalized.startsWith("gpt-") || normalized.includes("codex")) {
|
|
31
33
|
return model;
|
|
32
34
|
}
|
|
33
|
-
if (normalized ===
|
|
35
|
+
if (normalized === "gpt-5.5-pro" ||
|
|
36
|
+
normalized === "gpt-5.5" ||
|
|
37
|
+
normalized === "gpt-5.4-pro" ||
|
|
38
|
+
normalized === "gpt-5.4") {
|
|
34
39
|
return normalized;
|
|
35
40
|
}
|
|
36
41
|
// Pro variants: resolve to the latest Pro model in ChatGPT.
|
|
37
|
-
if (normalized ===
|
|
38
|
-
return
|
|
42
|
+
if (normalized === "gpt-5-pro" || normalized === "gpt-5.1-pro" || normalized === "gpt-5.2-pro") {
|
|
43
|
+
return "gpt-5.5-pro";
|
|
39
44
|
}
|
|
40
45
|
// Explicit model variants: keep as-is (they have their own browser labels)
|
|
41
|
-
if (normalized ===
|
|
46
|
+
if (normalized === "gpt-5.2-thinking" || normalized === "gpt-5.2-instant") {
|
|
42
47
|
return normalized;
|
|
43
48
|
}
|
|
44
49
|
// Legacy aliases: map to base GPT-5.2 (Auto)
|
|
45
|
-
if (normalized ===
|
|
46
|
-
return
|
|
50
|
+
if (normalized === "gpt-5.1") {
|
|
51
|
+
return "gpt-5.2";
|
|
47
52
|
}
|
|
48
53
|
return model;
|
|
49
54
|
}
|
|
50
55
|
export async function buildBrowserConfig(options) {
|
|
51
56
|
const desiredModelOverride = options.browserModelLabel?.trim();
|
|
52
|
-
const normalizedOverride = desiredModelOverride?.toLowerCase() ??
|
|
57
|
+
const normalizedOverride = desiredModelOverride?.toLowerCase() ?? "";
|
|
53
58
|
const baseModel = options.model.toLowerCase();
|
|
54
|
-
const isChatGptModel = baseModel.startsWith(
|
|
59
|
+
const isChatGptModel = baseModel.startsWith("gpt-") && !baseModel.includes("codex");
|
|
55
60
|
const shouldUseOverride = !isChatGptModel && normalizedOverride.length > 0 && normalizedOverride !== baseModel;
|
|
56
61
|
const modelStrategy = normalizeBrowserModelStrategy(options.browserModelStrategy) ?? DEFAULT_MODEL_STRATEGY;
|
|
57
62
|
const cookieNames = parseCookieNames(options.browserCookieNames ?? process.env.ORACLE_BROWSER_COOKIE_NAMES);
|
|
@@ -62,7 +67,7 @@ export async function buildBrowserConfig(options) {
|
|
|
62
67
|
envFile: process.env.ORACLE_BROWSER_COOKIES_FILE,
|
|
63
68
|
cwd: process.cwd(),
|
|
64
69
|
});
|
|
65
|
-
if (inline?.source?.startsWith(
|
|
70
|
+
if (inline?.source?.startsWith("home:") && options.browserNoCookieSync !== true) {
|
|
66
71
|
inline = undefined;
|
|
67
72
|
}
|
|
68
73
|
let remoteChrome;
|
|
@@ -76,8 +81,11 @@ export async function buildBrowserConfig(options) {
|
|
|
76
81
|
: shouldUseOverride
|
|
77
82
|
? desiredModelOverride
|
|
78
83
|
: mapModelToBrowserLabel(options.model);
|
|
79
|
-
if (modelStrategy ===
|
|
80
|
-
|
|
84
|
+
if (modelStrategy === "select" &&
|
|
85
|
+
url &&
|
|
86
|
+
isTemporaryChatUrl(url) &&
|
|
87
|
+
/\bpro\b/i.test(desiredModel ?? "")) {
|
|
88
|
+
throw new Error("Temporary Chat mode does not expose Pro models in the ChatGPT model picker. " +
|
|
81
89
|
'Remove "temporary-chat=true" from --chatgpt-url (or omit --chatgpt-url), or use a non-Pro model (e.g. --model gpt-5.2).');
|
|
82
90
|
}
|
|
83
91
|
return {
|
|
@@ -86,7 +94,9 @@ export async function buildBrowserConfig(options) {
|
|
|
86
94
|
chromeCookiePath: options.browserCookiePath ?? null,
|
|
87
95
|
url,
|
|
88
96
|
debugPort: selectBrowserPort(options),
|
|
89
|
-
timeoutMs: options.browserTimeout
|
|
97
|
+
timeoutMs: options.browserTimeout
|
|
98
|
+
? parseDuration(options.browserTimeout, DEFAULT_BROWSER_TIMEOUT_MS)
|
|
99
|
+
: undefined,
|
|
90
100
|
inputTimeoutMs: options.browserInputTimeout
|
|
91
101
|
? parseDuration(options.browserInputTimeout, DEFAULT_BROWSER_INPUT_TIMEOUT_MS)
|
|
92
102
|
: undefined,
|
|
@@ -96,7 +106,9 @@ export async function buildBrowserConfig(options) {
|
|
|
96
106
|
assistantRecheckTimeoutMs: options.browserRecheckTimeout
|
|
97
107
|
? parseDuration(options.browserRecheckTimeout, DEFAULT_BROWSER_RECHECK_TIMEOUT_MS)
|
|
98
108
|
: undefined,
|
|
99
|
-
reuseChromeWaitMs: options.browserReuseWait
|
|
109
|
+
reuseChromeWaitMs: options.browserReuseWait
|
|
110
|
+
? parseDuration(options.browserReuseWait, 0)
|
|
111
|
+
: undefined,
|
|
100
112
|
profileLockTimeoutMs: options.browserProfileLockTimeout
|
|
101
113
|
? parseDuration(options.browserProfileLockTimeout, 0)
|
|
102
114
|
: undefined,
|
|
@@ -109,7 +121,9 @@ export async function buildBrowserConfig(options) {
|
|
|
109
121
|
autoReattachTimeoutMs: options.browserAutoReattachTimeout
|
|
110
122
|
? parseDuration(options.browserAutoReattachTimeout, DEFAULT_BROWSER_AUTO_REATTACH_TIMEOUT_MS)
|
|
111
123
|
: undefined,
|
|
112
|
-
cookieSyncWaitMs: options.browserCookieWait
|
|
124
|
+
cookieSyncWaitMs: options.browserCookieWait
|
|
125
|
+
? parseDuration(options.browserCookieWait, 0)
|
|
126
|
+
: undefined,
|
|
113
127
|
cookieSync: options.browserNoCookieSync ? false : undefined,
|
|
114
128
|
cookieNames,
|
|
115
129
|
inlineCookies: inline?.cookies,
|
|
@@ -148,7 +162,7 @@ export function mapModelToBrowserLabel(model) {
|
|
|
148
162
|
return DEFAULT_MODEL_TARGET;
|
|
149
163
|
}
|
|
150
164
|
export function resolveBrowserModelLabel(input, model) {
|
|
151
|
-
const trimmed = input?.trim?.() ??
|
|
165
|
+
const trimmed = input?.trim?.() ?? "";
|
|
152
166
|
if (!trimmed) {
|
|
153
167
|
return mapModelToBrowserLabel(model);
|
|
154
168
|
}
|
|
@@ -161,7 +175,7 @@ export function resolveBrowserModelLabel(input, model) {
|
|
|
161
175
|
function parseRemoteChromeTarget(raw) {
|
|
162
176
|
const target = raw.trim();
|
|
163
177
|
if (!target) {
|
|
164
|
-
throw new Error(
|
|
178
|
+
throw new Error("Invalid remote-chrome value: expected host:port but received an empty string.");
|
|
165
179
|
}
|
|
166
180
|
const ipv6Match = target.match(/^\[(.+)]:(\d+)$/);
|
|
167
181
|
let host;
|
|
@@ -171,22 +185,22 @@ function parseRemoteChromeTarget(raw) {
|
|
|
171
185
|
portSegment = ipv6Match[2]?.trim();
|
|
172
186
|
}
|
|
173
187
|
else {
|
|
174
|
-
const lastColon = target.lastIndexOf(
|
|
188
|
+
const lastColon = target.lastIndexOf(":");
|
|
175
189
|
if (lastColon === -1) {
|
|
176
190
|
throw new Error(`Invalid remote-chrome format: ${target}. Expected host:port (IPv6 must use [host]:port notation).`);
|
|
177
191
|
}
|
|
178
192
|
host = target.slice(0, lastColon).trim();
|
|
179
193
|
portSegment = target.slice(lastColon + 1).trim();
|
|
180
|
-
if (host.includes(
|
|
194
|
+
if (host.includes(":")) {
|
|
181
195
|
throw new Error(`Invalid remote-chrome format: ${target}. Wrap IPv6 addresses in brackets, e.g. --remote-chrome "[2001:db8::1]:9222".`);
|
|
182
196
|
}
|
|
183
197
|
}
|
|
184
198
|
if (!host) {
|
|
185
199
|
throw new Error(`Invalid remote-chrome format: ${target}. Host portion is missing; expected host:port.`);
|
|
186
200
|
}
|
|
187
|
-
const port = Number.parseInt(portSegment ??
|
|
201
|
+
const port = Number.parseInt(portSegment ?? "", 10);
|
|
188
202
|
if (!Number.isFinite(port) || port <= 0 || port > 65_535) {
|
|
189
|
-
throw new Error(`Invalid remote-chrome port: "${portSegment ??
|
|
203
|
+
throw new Error(`Invalid remote-chrome port: "${portSegment ?? ""}". Expected a number between 1 and 65535.`);
|
|
190
204
|
}
|
|
191
205
|
return { host, port };
|
|
192
206
|
}
|
|
@@ -194,7 +208,7 @@ function parseCookieNames(raw) {
|
|
|
194
208
|
if (!raw)
|
|
195
209
|
return undefined;
|
|
196
210
|
const names = raw
|
|
197
|
-
.split(
|
|
211
|
+
.split(",")
|
|
198
212
|
.map((entry) => entry.trim())
|
|
199
213
|
.filter(Boolean);
|
|
200
214
|
return names.length ? names : undefined;
|
|
@@ -211,7 +225,7 @@ async function resolveInlineCookies({ inlineArg, inlineFileArg, envPayload, envF
|
|
|
211
225
|
try {
|
|
212
226
|
const stat = await fs.stat(resolved);
|
|
213
227
|
if (stat.isFile()) {
|
|
214
|
-
const fileContent = await fs.readFile(resolved,
|
|
228
|
+
const fileContent = await fs.readFile(resolved, "utf8");
|
|
215
229
|
const parsed = parseInlineCookiesPayload(fileContent);
|
|
216
230
|
if (parsed)
|
|
217
231
|
return parsed;
|
|
@@ -224,10 +238,10 @@ async function resolveInlineCookies({ inlineArg, inlineFileArg, envPayload, envF
|
|
|
224
238
|
return parseInlineCookiesPayload(trimmed);
|
|
225
239
|
};
|
|
226
240
|
const sources = [
|
|
227
|
-
{ value: inlineFileArg, allowPath: true, source:
|
|
228
|
-
{ value: inlineArg, allowPath: true, source:
|
|
229
|
-
{ value: envFile, allowPath: true, source:
|
|
230
|
-
{ value: envPayload, allowPath: false, source:
|
|
241
|
+
{ value: inlineFileArg, allowPath: true, source: "inline-file" },
|
|
242
|
+
{ value: inlineArg, allowPath: true, source: "inline-arg" },
|
|
243
|
+
{ value: envFile, allowPath: true, source: "env-file" },
|
|
244
|
+
{ value: envPayload, allowPath: false, source: "env-payload" },
|
|
231
245
|
];
|
|
232
246
|
for (const { value, allowPath, source } of sources) {
|
|
233
247
|
const parsed = await tryLoad(value, allowPath);
|
|
@@ -236,14 +250,14 @@ async function resolveInlineCookies({ inlineArg, inlineFileArg, envPayload, envF
|
|
|
236
250
|
}
|
|
237
251
|
// fallback: ~/.oracle/cookies.{json,base64}
|
|
238
252
|
const oracleHome = getOracleHomeDir();
|
|
239
|
-
const candidates = [
|
|
253
|
+
const candidates = ["cookies.json", "cookies.base64"];
|
|
240
254
|
for (const file of candidates) {
|
|
241
255
|
const fullPath = path.join(oracleHome, file);
|
|
242
256
|
try {
|
|
243
257
|
const stat = await fs.stat(fullPath);
|
|
244
258
|
if (!stat.isFile())
|
|
245
259
|
continue;
|
|
246
|
-
const content = await fs.readFile(fullPath,
|
|
260
|
+
const content = await fs.readFile(fullPath, "utf8");
|
|
247
261
|
const parsed = parseInlineCookiesPayload(content);
|
|
248
262
|
if (parsed)
|
|
249
263
|
return { cookies: parsed, source: `home:${file}` };
|
|
@@ -263,8 +277,8 @@ function parseInlineCookiesPayload(raw) {
|
|
|
263
277
|
let jsonPayload = text;
|
|
264
278
|
// Attempt base64 decode first; fall back to raw text on failure.
|
|
265
279
|
try {
|
|
266
|
-
const decoded = Buffer.from(text,
|
|
267
|
-
if (decoded.trim().startsWith(
|
|
280
|
+
const decoded = Buffer.from(text, "base64").toString("utf8");
|
|
281
|
+
if (decoded.trim().startsWith("[")) {
|
|
268
282
|
jsonPayload = decoded;
|
|
269
283
|
}
|
|
270
284
|
}
|
|
@@ -1,81 +1,82 @@
|
|
|
1
|
-
import { normalizeChatgptUrl, CHATGPT_URL } from
|
|
1
|
+
import { normalizeChatgptUrl, CHATGPT_URL } from "../browserMode.js";
|
|
2
2
|
export function applyBrowserDefaultsFromConfig(options, config, getSource) {
|
|
3
3
|
const browser = config.browser;
|
|
4
4
|
if (!browser)
|
|
5
5
|
return;
|
|
6
6
|
const isUnset = (key) => {
|
|
7
7
|
const source = getSource(key);
|
|
8
|
-
return source === undefined || source ===
|
|
8
|
+
return source === undefined || source === "default";
|
|
9
9
|
};
|
|
10
10
|
const configuredChatgptUrl = browser.chatgptUrl ?? browser.url;
|
|
11
11
|
const cliChatgptSet = options.chatgptUrl !== undefined || options.browserUrl !== undefined;
|
|
12
|
-
if (isUnset(
|
|
13
|
-
options.chatgptUrl = normalizeChatgptUrl(configuredChatgptUrl ??
|
|
12
|
+
if (isUnset("chatgptUrl") && !cliChatgptSet && configuredChatgptUrl !== undefined) {
|
|
13
|
+
options.chatgptUrl = normalizeChatgptUrl(configuredChatgptUrl ?? "", CHATGPT_URL);
|
|
14
14
|
}
|
|
15
|
-
if (isUnset(
|
|
15
|
+
if (isUnset("browserChromeProfile") && browser.chromeProfile !== undefined) {
|
|
16
16
|
options.browserChromeProfile = browser.chromeProfile ?? undefined;
|
|
17
17
|
}
|
|
18
|
-
if (isUnset(
|
|
18
|
+
if (isUnset("browserChromePath") && browser.chromePath !== undefined) {
|
|
19
19
|
options.browserChromePath = browser.chromePath ?? undefined;
|
|
20
20
|
}
|
|
21
|
-
if (isUnset(
|
|
21
|
+
if (isUnset("browserCookiePath") && browser.chromeCookiePath !== undefined) {
|
|
22
22
|
options.browserCookiePath = browser.chromeCookiePath ?? undefined;
|
|
23
23
|
}
|
|
24
|
-
if (isUnset(
|
|
24
|
+
if (isUnset("browserUrl") && options.browserUrl === undefined && browser.url !== undefined) {
|
|
25
25
|
options.browserUrl = browser.url;
|
|
26
26
|
}
|
|
27
|
-
if (isUnset(
|
|
27
|
+
if (isUnset("browserTimeout") && typeof browser.timeoutMs === "number") {
|
|
28
28
|
options.browserTimeout = String(browser.timeoutMs);
|
|
29
29
|
}
|
|
30
|
-
if (isUnset(
|
|
30
|
+
if (isUnset("browserPort") && typeof browser.debugPort === "number") {
|
|
31
31
|
options.browserPort = browser.debugPort;
|
|
32
32
|
}
|
|
33
|
-
if (isUnset(
|
|
33
|
+
if (isUnset("browserInputTimeout") && typeof browser.inputTimeoutMs === "number") {
|
|
34
34
|
options.browserInputTimeout = String(browser.inputTimeoutMs);
|
|
35
35
|
}
|
|
36
|
-
if (isUnset(
|
|
36
|
+
if (isUnset("browserRecheckDelay") && typeof browser.assistantRecheckDelayMs === "number") {
|
|
37
37
|
options.browserRecheckDelay = String(browser.assistantRecheckDelayMs);
|
|
38
38
|
}
|
|
39
|
-
if (isUnset(
|
|
39
|
+
if (isUnset("browserRecheckTimeout") && typeof browser.assistantRecheckTimeoutMs === "number") {
|
|
40
40
|
options.browserRecheckTimeout = String(browser.assistantRecheckTimeoutMs);
|
|
41
41
|
}
|
|
42
|
-
if (isUnset(
|
|
42
|
+
if (isUnset("browserReuseWait") && typeof browser.reuseChromeWaitMs === "number") {
|
|
43
43
|
options.browserReuseWait = String(browser.reuseChromeWaitMs);
|
|
44
44
|
}
|
|
45
|
-
if (isUnset(
|
|
45
|
+
if (isUnset("browserProfileLockTimeout") && typeof browser.profileLockTimeoutMs === "number") {
|
|
46
46
|
options.browserProfileLockTimeout = String(browser.profileLockTimeoutMs);
|
|
47
47
|
}
|
|
48
|
-
if (isUnset(
|
|
48
|
+
if (isUnset("browserAutoReattachDelay") && typeof browser.autoReattachDelayMs === "number") {
|
|
49
49
|
options.browserAutoReattachDelay = String(browser.autoReattachDelayMs);
|
|
50
50
|
}
|
|
51
|
-
if (isUnset(
|
|
51
|
+
if (isUnset("browserAutoReattachInterval") &&
|
|
52
|
+
typeof browser.autoReattachIntervalMs === "number") {
|
|
52
53
|
options.browserAutoReattachInterval = String(browser.autoReattachIntervalMs);
|
|
53
54
|
}
|
|
54
|
-
if (isUnset(
|
|
55
|
+
if (isUnset("browserAutoReattachTimeout") && typeof browser.autoReattachTimeoutMs === "number") {
|
|
55
56
|
options.browserAutoReattachTimeout = String(browser.autoReattachTimeoutMs);
|
|
56
57
|
}
|
|
57
|
-
if (isUnset(
|
|
58
|
+
if (isUnset("browserCookieWait") && typeof browser.cookieSyncWaitMs === "number") {
|
|
58
59
|
options.browserCookieWait = String(browser.cookieSyncWaitMs);
|
|
59
60
|
}
|
|
60
|
-
if (isUnset(
|
|
61
|
+
if (isUnset("browserHeadless") && browser.headless !== undefined) {
|
|
61
62
|
options.browserHeadless = browser.headless;
|
|
62
63
|
}
|
|
63
|
-
if (isUnset(
|
|
64
|
+
if (isUnset("browserHideWindow") && browser.hideWindow !== undefined) {
|
|
64
65
|
options.browserHideWindow = browser.hideWindow;
|
|
65
66
|
}
|
|
66
|
-
if (isUnset(
|
|
67
|
+
if (isUnset("browserKeepBrowser") && browser.keepBrowser !== undefined) {
|
|
67
68
|
options.browserKeepBrowser = browser.keepBrowser;
|
|
68
69
|
}
|
|
69
|
-
if (isUnset(
|
|
70
|
+
if (isUnset("browserModelStrategy") && browser.modelStrategy !== undefined) {
|
|
70
71
|
options.browserModelStrategy = browser.modelStrategy;
|
|
71
72
|
}
|
|
72
|
-
if (isUnset(
|
|
73
|
+
if (isUnset("browserThinkingTime") && browser.thinkingTime !== undefined) {
|
|
73
74
|
options.browserThinkingTime = browser.thinkingTime;
|
|
74
75
|
}
|
|
75
|
-
if (isUnset(
|
|
76
|
+
if (isUnset("browserManualLogin") && browser.manualLogin !== undefined) {
|
|
76
77
|
options.browserManualLogin = browser.manualLogin;
|
|
77
78
|
}
|
|
78
|
-
if (isUnset(
|
|
79
|
+
if (isUnset("browserManualLoginProfileDir") && browser.manualLoginProfileDir !== undefined) {
|
|
79
80
|
options.browserManualLoginProfileDir = browser.manualLoginProfileDir;
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
async function loadClipboard() {
|
|
2
|
+
if (process.platform === "darwin" && process.arch === "x64") {
|
|
3
|
+
const paths = (process.env.PATH ?? "").split(":").filter(Boolean);
|
|
4
|
+
if (!paths.includes("/usr/sbin")) {
|
|
5
|
+
process.env.PATH = ["/usr/sbin", ...paths].join(":");
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return (await import("clipboardy")).default;
|
|
9
|
+
}
|
|
2
10
|
export async function copyToClipboard(text) {
|
|
3
11
|
try {
|
|
12
|
+
const clipboard = await loadClipboard();
|
|
4
13
|
await clipboard.write(text);
|
|
5
|
-
return { success: true, command:
|
|
14
|
+
return { success: true, command: "clipboardy" };
|
|
6
15
|
}
|
|
7
16
|
catch (error) {
|
|
8
17
|
return { success: false, error };
|
package/dist/src/cli/detach.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isProModel } from
|
|
1
|
+
import { isProModel } from "../oracle/modelResolver.js";
|
|
2
2
|
export function shouldDetachSession({
|
|
3
3
|
// Params kept for policy tweaks.
|
|
4
4
|
engine, model, waitPreference, disableDetachEnv, }) {
|
|
@@ -8,7 +8,7 @@ engine, model, waitPreference, disableDetachEnv, }) {
|
|
|
8
8
|
if (waitPreference)
|
|
9
9
|
return false;
|
|
10
10
|
// Only Pro-tier API runs should start detached by default; browser runs stay inline so failures surface.
|
|
11
|
-
if (isProModel(model) && engine ===
|
|
11
|
+
if (isProModel(model) && engine === "api")
|
|
12
12
|
return true;
|
|
13
13
|
return false;
|
|
14
14
|
}
|