promethios-bridge 2.1.1 → 2.1.4
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 +1 -1
- package/src/bridge.js +26 -0
- package/src/overlay/renderer/index.html +13 -47
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "promethios-bridge",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
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": {
|
package/src/bridge.js
CHANGED
|
@@ -210,6 +210,32 @@ async function startBridge({ setupToken, apiBase, port, dev }) {
|
|
|
210
210
|
// Health check
|
|
211
211
|
app.get('/health', (req, res) => res.json({ ok: true, version: require('../package.json').version }));
|
|
212
212
|
|
|
213
|
+
// ── /open-external ─────────────────────────────────────────────────────────
|
|
214
|
+
// POST /open-external?url=<encoded-url>
|
|
215
|
+
// Called by the Promethios web app when the user clicks "Open [Provider] ↗"
|
|
216
|
+
// in a provider thread. Opens the URL in the user's real default browser.
|
|
217
|
+
// No auth required — only accessible from localhost.
|
|
218
|
+
app.post('/open-external', (req, res) => {
|
|
219
|
+
const url = (req.query.url || req.body?.url || '').trim();
|
|
220
|
+
if (!url || !/^https?:\/\//.test(url)) {
|
|
221
|
+
return res.status(400).json({ error: 'Invalid or missing url parameter' });
|
|
222
|
+
}
|
|
223
|
+
const { exec } = require('child_process');
|
|
224
|
+
const platform = process.platform;
|
|
225
|
+
let cmd;
|
|
226
|
+
if (platform === 'win32') {
|
|
227
|
+
cmd = `start "" "${url.replace(/"/g, '')}"`;
|
|
228
|
+
} else if (platform === 'darwin') {
|
|
229
|
+
cmd = `open "${url.replace(/"/g, '')}"`;
|
|
230
|
+
} else {
|
|
231
|
+
cmd = `xdg-open "${url.replace(/"/g, '')}"`;
|
|
232
|
+
}
|
|
233
|
+
exec(cmd, (err) => {
|
|
234
|
+
if (err) console.error('[open-external] Failed to open URL:', err.message);
|
|
235
|
+
});
|
|
236
|
+
res.json({ status: 'ok', url });
|
|
237
|
+
});
|
|
238
|
+
|
|
213
239
|
// ── /status: used by the Electron overlay to auto-connect without manual token entry ──
|
|
214
240
|
// Only accessible from localhost (127.0.0.1 or ::1) for security.
|
|
215
241
|
let bridgeUsername = null; // set after registerBridge resolves
|
|
@@ -1250,7 +1250,7 @@
|
|
|
1250
1250
|
if (hint) hint.style.display = 'none';
|
|
1251
1251
|
}
|
|
1252
1252
|
|
|
1253
|
-
|
|
1253
|
+
function startOAuthFlow(provider) {
|
|
1254
1254
|
hideProviderLoginHint();
|
|
1255
1255
|
|
|
1256
1256
|
if (!authToken) {
|
|
@@ -1262,56 +1262,22 @@
|
|
|
1262
1262
|
return;
|
|
1263
1263
|
}
|
|
1264
1264
|
|
|
1265
|
-
const info = PROVIDER_LABELS[provider] || { name: provider, color: 'rgba(255,255,255,0.1)', text: '#e2e8f0' };
|
|
1266
1265
|
const btn = document.querySelector(`.btn-connect[data-provider="${provider}"]`);
|
|
1267
|
-
if (btn) { btn.textContent = '
|
|
1266
|
+
if (btn) { btn.textContent = 'Opening…'; btn.disabled = true; }
|
|
1268
1267
|
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
});
|
|
1275
|
-
const data = await res.json();
|
|
1268
|
+
// Open OAuth consent page in the user's REAL system browser (Chrome/Edge/Firefox).
|
|
1269
|
+
// shell.openExternal() is the only way that passes Google/Meta's "secure browser" check.
|
|
1270
|
+
// The main process starts a localhost callback server, opens the system browser with the
|
|
1271
|
+
// Promethios OAuth URL, and fires 'oauth-complete' back to us when the token arrives.
|
|
1272
|
+
window.promethios.openOAuth(provider);
|
|
1276
1273
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
if (isLoginRequired) {
|
|
1284
|
-
const loginUrl = PROVIDER_LOGIN_URLS[provider] || `https://${provider}.com`;
|
|
1285
|
-
showProviderLoginHint(provider,
|
|
1286
|
-
`<strong>Sign in to ${info.name} first.</strong><br>` +
|
|
1287
|
-
`Click <strong>Open ↗</strong> next to ${info.name} to sign in, then click <strong>Connect</strong> again.`
|
|
1288
|
-
);
|
|
1289
|
-
window.promethios.openExternal(loginUrl);
|
|
1290
|
-
} else {
|
|
1291
|
-
showToast(`Connect failed: ${data.error || 'Unknown error'}`);
|
|
1292
|
-
}
|
|
1293
|
-
if (btn) { btn.textContent = 'Connect'; btn.disabled = false; }
|
|
1294
|
-
return;
|
|
1274
|
+
// Re-enable the button after a short delay so the user can retry if needed
|
|
1275
|
+
setTimeout(() => {
|
|
1276
|
+
if (btn && btn.disabled) {
|
|
1277
|
+
btn.textContent = 'Connect';
|
|
1278
|
+
btn.disabled = false;
|
|
1295
1279
|
}
|
|
1296
|
-
|
|
1297
|
-
connectedProviders[provider] = { token: data.token, clientId: provider, ts: Date.now() };
|
|
1298
|
-
updateProviderButtons();
|
|
1299
|
-
hideProviderLoginHint();
|
|
1300
|
-
|
|
1301
|
-
modalProviderName.textContent = info.name;
|
|
1302
|
-
modalProviderBadge.textContent = info.name;
|
|
1303
|
-
modalProviderBadge.style.background = info.color;
|
|
1304
|
-
modalProviderBadge.style.color = info.text;
|
|
1305
|
-
modalPromptText.textContent = data.prompt || buildPromptText(provider, data.token);
|
|
1306
|
-
modalCopyBtn.textContent = '⌘ Copy Prompt';
|
|
1307
|
-
modalCopyBtn.classList.remove('copied');
|
|
1308
|
-
promptModal.classList.add('open');
|
|
1309
|
-
showToast(`✓ ${info.name} connected!`);
|
|
1310
|
-
|
|
1311
|
-
} catch (err) {
|
|
1312
|
-
showToast('Network error — check your connection and try again.');
|
|
1313
|
-
if (btn) { btn.textContent = 'Connect'; btn.disabled = false; }
|
|
1314
|
-
}
|
|
1280
|
+
}, 8000);
|
|
1315
1281
|
}
|
|
1316
1282
|
|
|
1317
1283
|
// Called by main process after OAuth completes successfully
|