promethios-bridge 1.7.6 → 1.7.7
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/package.json +2 -3
- package/src/bridge.js +52 -8
- package/src/overlay/launcher.js +50 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "promethios-bridge",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.7",
|
|
4
4
|
"description": "Run Promethios agent frameworks locally on your computer with full file, terminal, browser access, ambient context capture, and the always-on-top floating chat overlay. Native Framework Mode supports OpenClaw and other frameworks via the bridge.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -49,8 +49,7 @@
|
|
|
49
49
|
"express": "^4.18.2",
|
|
50
50
|
"open": "^8.4.2",
|
|
51
51
|
"ora": "^5.4.1",
|
|
52
|
-
"node-fetch": "^2.7.0"
|
|
53
|
-
"playwright": "^1.42.0"
|
|
52
|
+
"node-fetch": "^2.7.0"
|
|
54
53
|
},
|
|
55
54
|
"optionalDependencies": {
|
|
56
55
|
"playwright": "^1.42.0",
|
package/src/bridge.js
CHANGED
|
@@ -72,6 +72,52 @@ async function checkForUpdates(currentVersion, log) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Open a URL in the user's default browser.
|
|
77
|
+
* Uses platform-native commands for maximum reliability:
|
|
78
|
+
* Windows: cmd /c start "" "<url>"
|
|
79
|
+
* macOS: open <url>
|
|
80
|
+
* Linux: xdg-open <url>
|
|
81
|
+
* Falls back to the `open` npm package if the native command fails.
|
|
82
|
+
* Returns true if the browser was successfully opened, false otherwise.
|
|
83
|
+
*/
|
|
84
|
+
async function openInBrowser(url, log) {
|
|
85
|
+
const { exec } = require('child_process');
|
|
86
|
+
const platform = process.platform;
|
|
87
|
+
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
let cmd;
|
|
90
|
+
if (platform === 'win32') {
|
|
91
|
+
// On Windows, `start` requires an empty title arg before the URL
|
|
92
|
+
// to prevent issues with URLs containing special characters.
|
|
93
|
+
cmd = `cmd /c start "" "${url}"`;
|
|
94
|
+
} else if (platform === 'darwin') {
|
|
95
|
+
cmd = `open "${url}"`;
|
|
96
|
+
} else {
|
|
97
|
+
cmd = `xdg-open "${url}"`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
exec(cmd, { timeout: 5000 }, (err) => {
|
|
101
|
+
if (!err) {
|
|
102
|
+
resolve(true);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Native command failed — try the `open` npm package as fallback
|
|
106
|
+
log('Native browser open failed, trying open package:', err.message);
|
|
107
|
+
try {
|
|
108
|
+
const openModule = require('open');
|
|
109
|
+
openModule(url).then(() => resolve(true)).catch((e) => {
|
|
110
|
+
log('open package also failed:', e.message);
|
|
111
|
+
resolve(false);
|
|
112
|
+
});
|
|
113
|
+
} catch (e) {
|
|
114
|
+
log('open package not available:', e.message);
|
|
115
|
+
resolve(false);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
75
121
|
async function startBridge({ setupToken, apiBase, port, dev }) {
|
|
76
122
|
const log = dev
|
|
77
123
|
? (...args) => console.log(chalk.gray(' [debug]'), ...args)
|
|
@@ -366,17 +412,15 @@ async function startBridge({ setupToken, apiBase, port, dev }) {
|
|
|
366
412
|
// Electron not available — open the lightweight browser overlay instead.
|
|
367
413
|
// This is a small chat UI served by the bridge's own Express server.
|
|
368
414
|
const overlayUrl = `http://127.0.0.1:${port}/overlay`;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
await openModule(overlayUrl);
|
|
415
|
+
const openedInBrowser = await openInBrowser(overlayUrl, log);
|
|
416
|
+
if (openedInBrowser) {
|
|
372
417
|
console.log(chalk.cyan(' ⬡ Promethios overlay opened in your browser'));
|
|
373
418
|
console.log(chalk.gray(` URL: ${overlayUrl}`));
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
log(
|
|
377
|
-
console.log(chalk.gray(` ℹ Open ${overlayUrl} in your browser for the chat overlay`));
|
|
378
|
-
console.log('');
|
|
419
|
+
} else {
|
|
420
|
+
console.log(chalk.gray(` ℹ Open this URL in your browser for the chat overlay:`));
|
|
421
|
+
console.log(chalk.cyan(` ${overlayUrl}`));
|
|
379
422
|
}
|
|
423
|
+
console.log('');
|
|
380
424
|
}
|
|
381
425
|
|
|
382
426
|
// Heartbeat loop
|
package/src/overlay/launcher.js
CHANGED
|
@@ -2,56 +2,74 @@
|
|
|
2
2
|
* launcher.js
|
|
3
3
|
*
|
|
4
4
|
* Called by the bridge CLI after successful authentication.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Attempts to launch the Electron overlay window. Returns null if Electron
|
|
6
|
+
* is not available (which is the case when running via `npx`, since optional
|
|
7
|
+
* dependencies are not installed in the npx cache).
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* IMPORTANT: We check for the actual Electron binary on disk, NOT just whether
|
|
10
|
+
* the `electron` npm package is present. When running via `npx`, the electron
|
|
11
|
+
* package IS downloaded (it's a listed optionalDependency), but its postinstall
|
|
12
|
+
* script downloads the real binary separately — that binary may not exist yet.
|
|
13
|
+
* Using require.resolve('electron') would return true even without the binary,
|
|
14
|
+
* causing spawn() to fail silently and the browser fallback to never be reached.
|
|
11
15
|
*/
|
|
12
16
|
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
13
19
|
const { spawn } = require('child_process');
|
|
14
20
|
const path = require('path');
|
|
15
21
|
const fs = require('fs');
|
|
16
22
|
|
|
17
23
|
/**
|
|
18
|
-
*
|
|
19
|
-
* Returns the
|
|
20
|
-
*
|
|
21
|
-
* IMPORTANT: When running via `npx`, optional dependencies (including electron)
|
|
22
|
-
* are NOT installed in the npx cache. The spawn() call may therefore fail with
|
|
23
|
-
* ENOENT. We attach an 'error' handler before unref() to silently absorb this
|
|
24
|
-
* instead of crashing the bridge process with an unhandled error event.
|
|
24
|
+
* Find the actual Electron binary on disk.
|
|
25
|
+
* Returns the path string if found and executable, or null if not available.
|
|
25
26
|
*/
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
let electronBin = null;
|
|
27
|
+
function findElectronBinary() {
|
|
28
|
+
const isWin = process.platform === 'win32';
|
|
29
29
|
|
|
30
|
+
// Candidate paths for the real Electron binary (not just the npm package stub)
|
|
30
31
|
const candidates = [
|
|
31
|
-
// Installed inside promethios-bridge's own node_modules (
|
|
32
|
-
path.join(__dirname, '..', '..', 'node_modules', '
|
|
33
|
-
|
|
34
|
-
//
|
|
35
|
-
'electron',
|
|
32
|
+
// 1. Installed inside promethios-bridge's own node_modules (full npm install, not npx)
|
|
33
|
+
path.join(__dirname, '..', '..', 'node_modules', 'electron', 'dist',
|
|
34
|
+
isWin ? 'electron.exe' : process.platform === 'darwin' ? 'Electron.app/Contents/MacOS/Electron' : 'electron'),
|
|
35
|
+
// 2. .bin shim (only works if the real binary was downloaded by postinstall)
|
|
36
|
+
path.join(__dirname, '..', '..', 'node_modules', '.bin', isWin ? 'electron.cmd' : 'electron'),
|
|
37
|
+
// 3. Global electron install
|
|
38
|
+
path.join(require('os').homedir(), '.npm', '_npx', '**', 'node_modules', 'electron', 'dist', isWin ? 'electron.exe' : 'electron'),
|
|
36
39
|
];
|
|
37
40
|
|
|
38
41
|
for (const candidate of candidates) {
|
|
42
|
+
// Skip glob-style paths (we can't expand them here)
|
|
43
|
+
if (candidate.includes('**')) continue;
|
|
39
44
|
try {
|
|
40
|
-
if (candidate === 'electron') {
|
|
41
|
-
// Try to resolve globally — throws if not installed
|
|
42
|
-
require.resolve('electron');
|
|
43
|
-
electronBin = candidate;
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
45
|
if (fs.existsSync(candidate)) {
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// Extra check: the .bin shim always exists even without the real binary.
|
|
47
|
+
// For the .bin shim, also verify the actual dist binary exists.
|
|
48
|
+
if (candidate.includes('.bin')) {
|
|
49
|
+
const distBin = path.join(
|
|
50
|
+
path.dirname(candidate), '..', 'electron', 'dist',
|
|
51
|
+
isWin ? 'electron.exe' : process.platform === 'darwin'
|
|
52
|
+
? 'Electron.app/Contents/MacOS/Electron' : 'electron'
|
|
53
|
+
);
|
|
54
|
+
if (!fs.existsSync(distBin)) continue;
|
|
55
|
+
}
|
|
56
|
+
return candidate;
|
|
49
57
|
}
|
|
50
|
-
} catch { /*
|
|
58
|
+
} catch { /* ignore */ }
|
|
51
59
|
}
|
|
52
60
|
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Launch the Promethios overlay Electron window.
|
|
66
|
+
* Returns the child process if Electron was found and launched, or null otherwise.
|
|
67
|
+
*/
|
|
68
|
+
function launchOverlay({ authToken, apiBase = 'https://api.promethios.ai', threadId = '', dev = false } = {}) {
|
|
69
|
+
const electronBin = findElectronBinary();
|
|
70
|
+
|
|
53
71
|
if (!electronBin) {
|
|
54
|
-
if (dev) console.log('[overlay] Electron not found —
|
|
72
|
+
if (dev) console.log('[overlay] Electron binary not found on disk — skipping Electron overlay.');
|
|
55
73
|
return null;
|
|
56
74
|
}
|
|
57
75
|
|
|
@@ -70,16 +88,13 @@ function launchOverlay({ authToken, apiBase = 'https://api.promethios.ai', threa
|
|
|
70
88
|
});
|
|
71
89
|
|
|
72
90
|
// Attach error handler BEFORE unref() to prevent unhandled 'error' event crashes.
|
|
73
|
-
// When running via npx, optional deps like electron are not installed, so spawn
|
|
74
|
-
// may emit ENOENT. We catch it silently — the bridge works fine without the overlay.
|
|
75
91
|
child.on('error', (err) => {
|
|
76
92
|
if (dev) console.log(`[overlay] Spawn error (non-critical): ${err.message}`);
|
|
77
|
-
// No-op: overlay is optional, bridge continues running normally
|
|
78
93
|
});
|
|
79
94
|
|
|
80
|
-
child.unref();
|
|
95
|
+
child.unref();
|
|
81
96
|
|
|
82
|
-
if (dev) console.log(`[overlay] Launched (pid ${child.pid})`);
|
|
97
|
+
if (dev) console.log(`[overlay] Launched Electron (pid ${child.pid})`);
|
|
83
98
|
|
|
84
99
|
return child;
|
|
85
100
|
}
|