@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
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import os from
|
|
2
|
-
import chalk from
|
|
3
|
-
import { getCliVersion } from
|
|
4
|
-
import { loadUserConfig } from
|
|
5
|
-
import { resolveRemoteServiceConfig } from
|
|
6
|
-
import { checkTcpConnection, checkRemoteHealth } from
|
|
7
|
-
import { detectChromeBinary, detectChromeCookieDb } from
|
|
8
|
-
import { formatCodexMcpSnippet } from
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { getCliVersion } from "../../version.js";
|
|
4
|
+
import { loadUserConfig } from "../../config.js";
|
|
5
|
+
import { resolveRemoteServiceConfig } from "../../remote/remoteServiceConfig.js";
|
|
6
|
+
import { checkTcpConnection, checkRemoteHealth } from "../../remote/health.js";
|
|
7
|
+
import { detectChromeBinary, detectChromeCookieDb } from "../../browser/detect.js";
|
|
8
|
+
import { formatCodexMcpSnippet } from "./codexConfig.js";
|
|
9
9
|
export async function runBridgeDoctor(_options) {
|
|
10
10
|
const { config: userConfig, path: configPath, loaded } = await loadUserConfig();
|
|
11
11
|
const version = getCliVersion();
|
|
@@ -18,90 +18,98 @@ export async function runBridgeDoctor(_options) {
|
|
|
18
18
|
const lines = [];
|
|
19
19
|
const fail = [];
|
|
20
20
|
const warn = [];
|
|
21
|
-
lines.push(chalk.bold(
|
|
21
|
+
lines.push(chalk.bold("Bridge doctor"));
|
|
22
22
|
lines.push(chalk.dim(`OS: ${process.platform} ${os.release()} (${process.arch})`));
|
|
23
23
|
lines.push(chalk.dim(`Node: ${process.version}`));
|
|
24
24
|
lines.push(chalk.dim(`Oracle: ${version}`));
|
|
25
|
-
lines.push(chalk.dim(`Config: ${loaded ? configPath :
|
|
25
|
+
lines.push(chalk.dim(`Config: ${loaded ? configPath : "(missing)"}`));
|
|
26
26
|
if (userConfig.engine) {
|
|
27
27
|
lines.push(chalk.dim(`Default engine: ${userConfig.engine}`));
|
|
28
28
|
}
|
|
29
29
|
if (userConfig.model) {
|
|
30
30
|
lines.push(chalk.dim(`Default model: ${userConfig.model}`));
|
|
31
31
|
}
|
|
32
|
-
lines.push(
|
|
33
|
-
lines.push(chalk.bold(
|
|
32
|
+
lines.push("");
|
|
33
|
+
lines.push(chalk.bold("Browser mode"));
|
|
34
34
|
if (resolvedRemote.host) {
|
|
35
|
-
lines.push(`Remote service: ${chalk.green(
|
|
35
|
+
lines.push(`Remote service: ${chalk.green("configured")}`);
|
|
36
36
|
lines.push(chalk.dim(`remoteHost: ${resolvedRemote.host} (${resolvedRemote.sources.host})`));
|
|
37
|
-
lines.push(chalk.dim(`remoteToken: ${resolvedRemote.token ?
|
|
37
|
+
lines.push(chalk.dim(`remoteToken: ${resolvedRemote.token ? "set" : "missing"} (${resolvedRemote.sources.token})`));
|
|
38
38
|
const tcp = await checkTcpConnection(resolvedRemote.host, 2000);
|
|
39
39
|
if (tcp.ok) {
|
|
40
|
-
lines.push(chalk.dim(`TCP connect: ${chalk.green(
|
|
40
|
+
lines.push(chalk.dim(`TCP connect: ${chalk.green("ok")}`));
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
fail.push(`Cannot reach ${resolvedRemote.host} (${tcp.error ??
|
|
44
|
-
lines.push(chalk.dim(`TCP connect: ${chalk.red(`failed (${tcp.error ??
|
|
43
|
+
fail.push(`Cannot reach ${resolvedRemote.host} (${tcp.error ?? "unknown error"}).`);
|
|
44
|
+
lines.push(chalk.dim(`TCP connect: ${chalk.red(`failed (${tcp.error ?? "unknown error"})`)}`));
|
|
45
45
|
}
|
|
46
46
|
if (!resolvedRemote.token) {
|
|
47
|
-
fail.push(
|
|
47
|
+
fail.push("Remote token is missing. Run `oracle bridge client --connect <...> --write-config` or set ORACLE_REMOTE_TOKEN.");
|
|
48
48
|
}
|
|
49
49
|
else if (tcp.ok) {
|
|
50
|
-
const health = await checkRemoteHealth({
|
|
50
|
+
const health = await checkRemoteHealth({
|
|
51
|
+
host: resolvedRemote.host,
|
|
52
|
+
token: resolvedRemote.token,
|
|
53
|
+
timeoutMs: 5000,
|
|
54
|
+
});
|
|
51
55
|
if (health.ok) {
|
|
52
|
-
const meta = health.version ? `oracle ${health.version}` :
|
|
56
|
+
const meta = health.version ? `oracle ${health.version}` : "ok";
|
|
53
57
|
lines.push(chalk.dim(`Auth (/health): ${chalk.green(meta)}`));
|
|
54
58
|
}
|
|
55
59
|
else {
|
|
56
|
-
const detail = health.error ??
|
|
60
|
+
const detail = health.error ?? "unknown error";
|
|
57
61
|
fail.push(`Remote auth failed: ${detail}`);
|
|
58
|
-
const suffix = health.statusCode ? `HTTP ${health.statusCode}` :
|
|
62
|
+
const suffix = health.statusCode ? `HTTP ${health.statusCode}` : "network";
|
|
59
63
|
lines.push(chalk.dim(`Auth (/health): ${chalk.red(`${suffix} (${detail})`)}`));
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
else {
|
|
64
|
-
lines.push(`Remote service: ${chalk.yellow(
|
|
68
|
+
lines.push(`Remote service: ${chalk.yellow("not configured")}`);
|
|
65
69
|
const chrome = await detectChromeBinary();
|
|
66
70
|
if (chrome.path) {
|
|
67
71
|
lines.push(chalk.dim(`Chrome: ${chalk.green(chrome.path)}`));
|
|
68
72
|
}
|
|
69
73
|
else {
|
|
70
|
-
fail.push(
|
|
71
|
-
lines.push(chalk.dim(`Chrome: ${chalk.red(
|
|
74
|
+
fail.push("No Chrome installation detected. Install Chrome/Chromium or set --browser-chrome-path.");
|
|
75
|
+
lines.push(chalk.dim(`Chrome: ${chalk.red("not found")}`));
|
|
72
76
|
}
|
|
73
|
-
if (process.platform ===
|
|
74
|
-
warn.push(
|
|
75
|
-
lines.push(chalk.dim(
|
|
77
|
+
if (process.platform === "win32") {
|
|
78
|
+
warn.push("Cookie sync is disabled on Windows; use --browser-manual-login or run browser automation on another host.");
|
|
79
|
+
lines.push(chalk.dim("Cookies: (cookie sync disabled on Windows)"));
|
|
76
80
|
}
|
|
77
81
|
else {
|
|
78
|
-
const cookieDb = await detectChromeCookieDb({ profile:
|
|
82
|
+
const cookieDb = await detectChromeCookieDb({ profile: "Default" });
|
|
79
83
|
if (cookieDb) {
|
|
80
84
|
lines.push(chalk.dim(`Cookies DB: ${chalk.green(cookieDb)}`));
|
|
81
85
|
}
|
|
82
86
|
else {
|
|
83
|
-
warn.push(
|
|
84
|
-
lines.push(chalk.dim(`Cookies DB: ${chalk.yellow(
|
|
87
|
+
warn.push("Chrome cookies DB not detected. You may need --browser-cookie-path or --browser-manual-login.");
|
|
88
|
+
lines.push(chalk.dim(`Cookies DB: ${chalk.yellow("not found")}`));
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
91
|
}
|
|
88
|
-
lines.push(
|
|
89
|
-
lines.push(chalk.bold(
|
|
90
|
-
lines.push(formatCodexMcpSnippet({
|
|
92
|
+
lines.push("");
|
|
93
|
+
lines.push(chalk.bold("Codex MCP"));
|
|
94
|
+
lines.push(formatCodexMcpSnippet({
|
|
95
|
+
remoteHost: resolvedRemote.host,
|
|
96
|
+
remoteToken: resolvedRemote.token,
|
|
97
|
+
includeToken: false,
|
|
98
|
+
}));
|
|
91
99
|
if (warn.length) {
|
|
92
|
-
lines.push(
|
|
93
|
-
lines.push(chalk.yellowBright(
|
|
100
|
+
lines.push("");
|
|
101
|
+
lines.push(chalk.yellowBright("Warnings:"));
|
|
94
102
|
for (const message of warn) {
|
|
95
103
|
lines.push(chalk.yellow(`- ${message}`));
|
|
96
104
|
}
|
|
97
105
|
}
|
|
98
106
|
if (fail.length) {
|
|
99
|
-
lines.push(
|
|
100
|
-
lines.push(chalk.redBright(
|
|
107
|
+
lines.push("");
|
|
108
|
+
lines.push(chalk.redBright("Problems:"));
|
|
101
109
|
for (const message of fail) {
|
|
102
110
|
lines.push(chalk.red(`- ${message}`));
|
|
103
111
|
}
|
|
104
112
|
}
|
|
105
|
-
console.log(lines.join(
|
|
113
|
+
console.log(lines.join("\n"));
|
|
106
114
|
process.exitCode = fail.length ? 1 : 0;
|
|
107
115
|
}
|
|
@@ -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
|
}
|