@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
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
* - Verifies the DevTools /json/version endpoint responds.
|
|
6
6
|
* - Prints a WSL-friendly firewall hint if the port is unreachable.
|
|
7
7
|
*/
|
|
8
|
-
import { setTimeout as sleep } from
|
|
9
|
-
import { launch } from
|
|
10
|
-
import os from
|
|
11
|
-
import { readFileSync } from
|
|
8
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
9
|
+
import { launch } from "chrome-launcher";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
12
|
const DEFAULT_PORT = 45871;
|
|
13
|
-
const port = normalizePort(process.env.ORACLE_BROWSER_PORT ?? process.env.ORACLE_BROWSER_DEBUG_PORT) ??
|
|
13
|
+
const port = normalizePort(process.env.ORACLE_BROWSER_PORT ?? process.env.ORACLE_BROWSER_DEBUG_PORT) ??
|
|
14
|
+
DEFAULT_PORT;
|
|
14
15
|
const hostHint = resolveWslHost();
|
|
15
|
-
const targetHost = hostHint ??
|
|
16
|
+
const targetHost = hostHint ?? "127.0.0.1";
|
|
16
17
|
function normalizePort(raw) {
|
|
17
18
|
if (!raw)
|
|
18
19
|
return null;
|
|
@@ -22,18 +23,18 @@ function normalizePort(raw) {
|
|
|
22
23
|
return value;
|
|
23
24
|
}
|
|
24
25
|
function isWsl() {
|
|
25
|
-
if (process.platform !==
|
|
26
|
+
if (process.platform !== "linux")
|
|
26
27
|
return false;
|
|
27
28
|
if (process.env.WSL_DISTRO_NAME)
|
|
28
29
|
return true;
|
|
29
|
-
return os.release().toLowerCase().includes(
|
|
30
|
+
return os.release().toLowerCase().includes("microsoft");
|
|
30
31
|
}
|
|
31
32
|
function resolveWslHost() {
|
|
32
33
|
if (!isWsl())
|
|
33
34
|
return null;
|
|
34
35
|
try {
|
|
35
|
-
const resolv = readFileSync(
|
|
36
|
-
for (const line of resolv.split(
|
|
36
|
+
const resolv = readFileSync("/etc/resolv.conf", "utf8");
|
|
37
|
+
for (const line of resolv.split("\n")) {
|
|
37
38
|
const match = line.match(/^nameserver\s+([0-9.]+)/);
|
|
38
39
|
if (match?.[1])
|
|
39
40
|
return match[1];
|
|
@@ -49,19 +50,21 @@ function firewallHint(host, devtoolsPort) {
|
|
|
49
50
|
return null;
|
|
50
51
|
return [
|
|
51
52
|
`DevTools port ${host}:${devtoolsPort} is blocked from WSL.`,
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
"",
|
|
54
|
+
"PowerShell (admin):",
|
|
54
55
|
`New-NetFirewallRule -DisplayName 'Chrome DevTools ${devtoolsPort}' -Direction Inbound -Action Allow -Protocol TCP -LocalPort ${devtoolsPort}`,
|
|
55
56
|
"New-NetFirewallRule -DisplayName 'Chrome DevTools (chrome.exe)' -Direction Inbound -Action Allow -Program 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' -Protocol TCP",
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
].join(
|
|
57
|
+
"",
|
|
58
|
+
"Re-run ./runner pnpm test:browser after adding the rule.",
|
|
59
|
+
].join("\n");
|
|
59
60
|
}
|
|
60
61
|
async function fetchVersion(host, devtoolsPort) {
|
|
61
62
|
const controller = new AbortController();
|
|
62
63
|
const timer = setTimeout(() => controller.abort(), 5000);
|
|
63
64
|
try {
|
|
64
|
-
const res = await fetch(`http://${host}:${devtoolsPort}/json/version`, {
|
|
65
|
+
const res = await fetch(`http://${host}:${devtoolsPort}/json/version`, {
|
|
66
|
+
signal: controller.signal,
|
|
67
|
+
});
|
|
65
68
|
if (!res.ok)
|
|
66
69
|
return false;
|
|
67
70
|
const json = (await res.json());
|
|
@@ -78,7 +81,7 @@ async function main() {
|
|
|
78
81
|
console.log(`[browser-test] launching Chrome on ${targetHost}:${port} (headful)…`);
|
|
79
82
|
const chrome = await launch({
|
|
80
83
|
port,
|
|
81
|
-
chromeFlags: [
|
|
84
|
+
chromeFlags: ["--remote-debugging-address=0.0.0.0"],
|
|
82
85
|
});
|
|
83
86
|
let ok = await fetchVersion(targetHost, chrome.port);
|
|
84
87
|
if (!ok) {
|
|
@@ -98,6 +101,6 @@ async function main() {
|
|
|
98
101
|
process.exit(1);
|
|
99
102
|
}
|
|
100
103
|
main().catch((error) => {
|
|
101
|
-
console.error(
|
|
104
|
+
console.error("[browser-test] Unexpected failure:", error instanceof Error ? error.message : String(error));
|
|
102
105
|
process.exit(1);
|
|
103
106
|
});
|
|
@@ -8,30 +8,30 @@
|
|
|
8
8
|
* Then run this script:
|
|
9
9
|
* npx tsx scripts/test-remote-chrome.ts <remote-host> [port]
|
|
10
10
|
*/
|
|
11
|
-
import CDP from
|
|
11
|
+
import CDP from "chrome-remote-interface";
|
|
12
12
|
async function main() {
|
|
13
|
-
const host = process.argv[2] ||
|
|
14
|
-
const port = parseInt(process.argv[3] ||
|
|
13
|
+
const host = process.argv[2] || "localhost";
|
|
14
|
+
const port = parseInt(process.argv[3] || "9222", 10);
|
|
15
15
|
console.log(`Attempting to connect to Chrome at ${host}:${port}...`);
|
|
16
16
|
try {
|
|
17
17
|
// Test connection
|
|
18
18
|
const client = await CDP({ host, port });
|
|
19
|
-
console.log(
|
|
19
|
+
console.log("✓ Connected to Chrome DevTools Protocol");
|
|
20
20
|
const { Network, Page, Runtime } = client;
|
|
21
21
|
// Enable domains
|
|
22
22
|
await Promise.all([Network.enable(), Page.enable()]);
|
|
23
|
-
console.log(
|
|
23
|
+
console.log("✓ Enabled Network and Page domains");
|
|
24
24
|
// Get browser version info
|
|
25
25
|
const version = await CDP.Version({ host, port });
|
|
26
26
|
console.log(`✓ Browser: ${version.Browser}`);
|
|
27
|
-
console.log(`✓ Protocol: ${version[
|
|
27
|
+
console.log(`✓ Protocol: ${version["Protocol-Version"]}`);
|
|
28
28
|
// Navigate to ChatGPT
|
|
29
|
-
console.log(
|
|
30
|
-
await Page.navigate({ url:
|
|
29
|
+
console.log("\nNavigating to ChatGPT...");
|
|
30
|
+
await Page.navigate({ url: "https://chatgpt.com/" });
|
|
31
31
|
await Page.loadEventFired();
|
|
32
|
-
console.log(
|
|
32
|
+
console.log("✓ Page loaded");
|
|
33
33
|
// Check current URL
|
|
34
|
-
const evalResult = await Runtime.evaluate({ expression:
|
|
34
|
+
const evalResult = await Runtime.evaluate({ expression: "window.location.href" });
|
|
35
35
|
console.log(`✓ Current URL: ${evalResult.result.value}`);
|
|
36
36
|
// Check if logged in (look for specific elements)
|
|
37
37
|
const checkLogin = await Runtime.evaluate({
|
|
@@ -49,19 +49,19 @@ async function main() {
|
|
|
49
49
|
});
|
|
50
50
|
console.log(`✓ Login status: ${JSON.stringify(checkLogin.result.value)}`);
|
|
51
51
|
await client.close();
|
|
52
|
-
console.log(
|
|
53
|
-
console.log(
|
|
54
|
-
console.log(
|
|
55
|
-
console.log(
|
|
56
|
-
console.log(
|
|
52
|
+
console.log("\n✓ POC successful! Remote Chrome connection works.");
|
|
53
|
+
console.log("\nTo use Oracle with remote Chrome, you would need to:");
|
|
54
|
+
console.log("1. Ensure cookies are loaded in remote Chrome");
|
|
55
|
+
console.log("2. Configure Oracle with --remote-chrome <host:port> to use this instance");
|
|
56
|
+
console.log("3. Ensure Oracle skips local Chrome launch when --remote-chrome is specified");
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
|
-
console.error(
|
|
60
|
-
console.log(
|
|
61
|
-
console.log(
|
|
59
|
+
console.error("✗ Connection failed:", error instanceof Error ? error.message : error);
|
|
60
|
+
console.log("\nTroubleshooting:");
|
|
61
|
+
console.log("1. Ensure Chrome is running on remote machine with:");
|
|
62
62
|
console.log(` google-chrome --remote-debugging-port=${port} --remote-debugging-address=0.0.0.0`);
|
|
63
|
-
console.log(
|
|
64
|
-
console.log(
|
|
63
|
+
console.log("2. Check firewall allows connections to port", port);
|
|
64
|
+
console.log("3. Verify network connectivity to", host);
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
3
|
export function normalizeHostPort(hostname, port) {
|
|
4
4
|
const trimmed = hostname.trim();
|
|
5
|
-
const unwrapped = trimmed.startsWith(
|
|
6
|
-
if (unwrapped.includes(
|
|
5
|
+
const unwrapped = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed;
|
|
6
|
+
if (unwrapped.includes(":")) {
|
|
7
7
|
return `[${unwrapped}]:${port}`;
|
|
8
8
|
}
|
|
9
9
|
return `${unwrapped}:${port}`;
|
|
@@ -11,7 +11,7 @@ export function normalizeHostPort(hostname, port) {
|
|
|
11
11
|
export function parseHostPort(raw) {
|
|
12
12
|
const target = raw.trim();
|
|
13
13
|
if (!target) {
|
|
14
|
-
throw new Error(
|
|
14
|
+
throw new Error("Expected host:port but received an empty value.");
|
|
15
15
|
}
|
|
16
16
|
const ipv6Match = target.match(/^\[(.+)]:(\d+)$/);
|
|
17
17
|
let hostname;
|
|
@@ -21,43 +21,43 @@ export function parseHostPort(raw) {
|
|
|
21
21
|
portSegment = ipv6Match[2]?.trim();
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
24
|
-
const lastColon = target.lastIndexOf(
|
|
24
|
+
const lastColon = target.lastIndexOf(":");
|
|
25
25
|
if (lastColon === -1) {
|
|
26
26
|
throw new Error(`Invalid host:port format: ${target}. Expected host:port (IPv6 must use [host]:port notation).`);
|
|
27
27
|
}
|
|
28
28
|
hostname = target.slice(0, lastColon).trim();
|
|
29
29
|
portSegment = target.slice(lastColon + 1).trim();
|
|
30
|
-
if (hostname.includes(
|
|
30
|
+
if (hostname.includes(":")) {
|
|
31
31
|
throw new Error(`Invalid host:port format: ${target}. Wrap IPv6 addresses in brackets, e.g. "[2001:db8::1]:9473".`);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
if (!hostname) {
|
|
35
35
|
throw new Error(`Invalid host:port format: ${target}. Host portion is missing.`);
|
|
36
36
|
}
|
|
37
|
-
const port = Number.parseInt(portSegment ??
|
|
37
|
+
const port = Number.parseInt(portSegment ?? "", 10);
|
|
38
38
|
if (!Number.isFinite(port) || port <= 0 || port > 65_535) {
|
|
39
|
-
throw new Error(`Invalid port: "${portSegment ??
|
|
39
|
+
throw new Error(`Invalid port: "${portSegment ?? ""}". Expected a number between 1 and 65535.`);
|
|
40
40
|
}
|
|
41
41
|
return { hostname, port };
|
|
42
42
|
}
|
|
43
43
|
export function parseBridgeConnectionString(input) {
|
|
44
44
|
const raw = input.trim();
|
|
45
45
|
if (!raw) {
|
|
46
|
-
throw new Error(
|
|
46
|
+
throw new Error("Missing connection string.");
|
|
47
47
|
}
|
|
48
48
|
let url;
|
|
49
49
|
try {
|
|
50
|
-
url = raw.includes(
|
|
50
|
+
url = raw.includes("://") ? new URL(raw) : new URL(`oracle+tcp://${raw}`);
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
53
53
|
throw new Error(`Invalid connection string: ${error instanceof Error ? error.message : String(error)}`);
|
|
54
54
|
}
|
|
55
55
|
const hostname = url.hostname?.trim();
|
|
56
|
-
const port = Number.parseInt(url.port ??
|
|
56
|
+
const port = Number.parseInt(url.port ?? "", 10);
|
|
57
57
|
if (!hostname || !Number.isFinite(port) || port <= 0 || port > 65_535) {
|
|
58
58
|
throw new Error(`Invalid connection string host: ${raw}. Expected host:port.`);
|
|
59
59
|
}
|
|
60
|
-
const token = url.searchParams.get(
|
|
60
|
+
const token = url.searchParams.get("token")?.trim() ?? "";
|
|
61
61
|
if (!token) {
|
|
62
62
|
throw new Error('Connection string is missing token. Expected "?token=...".');
|
|
63
63
|
}
|
|
@@ -74,11 +74,11 @@ export function formatBridgeConnectionString(connection, options = {}) {
|
|
|
74
74
|
return `${base}?${params.toString()}`;
|
|
75
75
|
}
|
|
76
76
|
export function looksLikePath(value) {
|
|
77
|
-
return value.includes(
|
|
77
|
+
return value.includes("/") || value.includes("\\") || value.endsWith(".json");
|
|
78
78
|
}
|
|
79
79
|
export async function readBridgeConnectionArtifact(filePath) {
|
|
80
80
|
const resolved = path.resolve(process.cwd(), filePath);
|
|
81
|
-
const raw = await fs.readFile(resolved,
|
|
81
|
+
const raw = await fs.readFile(resolved, "utf8");
|
|
82
82
|
let parsed;
|
|
83
83
|
try {
|
|
84
84
|
parsed = JSON.parse(raw);
|
|
@@ -86,15 +86,15 @@ export async function readBridgeConnectionArtifact(filePath) {
|
|
|
86
86
|
catch (error) {
|
|
87
87
|
throw new Error(`Failed to parse connection artifact JSON at ${resolved}: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
88
|
}
|
|
89
|
-
if (!parsed || typeof parsed !==
|
|
89
|
+
if (!parsed || typeof parsed !== "object") {
|
|
90
90
|
throw new Error(`Invalid connection artifact at ${resolved}: expected an object.`);
|
|
91
91
|
}
|
|
92
92
|
const remoteHost = parsed.remoteHost;
|
|
93
93
|
const remoteToken = parsed.remoteToken;
|
|
94
|
-
if (typeof remoteHost !==
|
|
94
|
+
if (typeof remoteHost !== "string" || remoteHost.trim().length === 0) {
|
|
95
95
|
throw new Error(`Invalid connection artifact at ${resolved}: remoteHost is missing.`);
|
|
96
96
|
}
|
|
97
|
-
if (typeof remoteToken !==
|
|
97
|
+
if (typeof remoteToken !== "string" || remoteToken.trim().length === 0) {
|
|
98
98
|
throw new Error(`Invalid connection artifact at ${resolved}: remoteToken is missing.`);
|
|
99
99
|
}
|
|
100
100
|
// Validate host formatting early so downstream checks don't crash.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from
|
|
3
|
-
import JSON5 from
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import JSON5 from "json5";
|
|
4
4
|
export async function readUserConfigFile(configPath) {
|
|
5
5
|
try {
|
|
6
|
-
const raw = await fs.readFile(configPath,
|
|
6
|
+
const raw = await fs.readFile(configPath, "utf8");
|
|
7
7
|
const parsed = JSON5.parse(raw);
|
|
8
8
|
return { config: parsed ?? {}, loaded: true };
|
|
9
9
|
}
|
|
10
10
|
catch (error) {
|
|
11
11
|
const code = error.code;
|
|
12
|
-
if (code ===
|
|
12
|
+
if (code === "ENOENT") {
|
|
13
13
|
return { config: {}, loaded: false };
|
|
14
14
|
}
|
|
15
15
|
throw new Error(`Failed to read ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -20,9 +20,9 @@ export async function writeUserConfigFile(configPath, config) {
|
|
|
20
20
|
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
21
21
|
const contents = `${JSON.stringify(config, null, 2)}\n`;
|
|
22
22
|
const tempPath = `${configPath}.tmp-${process.pid}-${Date.now()}`;
|
|
23
|
-
await fs.writeFile(tempPath, contents, { encoding:
|
|
23
|
+
await fs.writeFile(tempPath, contents, { encoding: "utf8", mode: 0o600 });
|
|
24
24
|
await fs.rename(tempPath, configPath);
|
|
25
|
-
if (process.platform !==
|
|
25
|
+
if (process.platform !== "win32") {
|
|
26
26
|
await fs.chmod(configPath, 0o600).catch(() => undefined);
|
|
27
27
|
}
|
|
28
28
|
}
|