@chatpanel/bridge 0.10.37 → 0.10.39
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/engines/custom.js +45 -5
- package/src/server.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/bridge",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.39",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local bridge that exposes the AI coding agents installed on your machine \u2014 Claude Code (CLI), Codex (CLI), and Antigravity CLI (formerly Gemini CLI, which remains available for business/enterprise) \u2014 to the ChatPanel Chrome extension over a localhost SSE endpoint. Bring your own agent.",
|
|
6
6
|
"keywords": [
|
package/src/engines/custom.js
CHANGED
|
@@ -333,24 +333,43 @@ async function runStableMcpSetup(plan, cwd) {
|
|
|
333
333
|
let child;
|
|
334
334
|
try { child = spawn(bin, argv, opts); } catch (e) { return reject(new Error(`Failed to start ${plan.command}: ${e.message}`)); }
|
|
335
335
|
let stderr = '';
|
|
336
|
+
// The CLI often reports WHY it couldn't register on stdout while still exiting 0 (Hermes
|
|
337
|
+
// prints "requires the 'mcp' Python SDK" and saves nothing). Capturing it is what lets
|
|
338
|
+
// the caller turn a silent no-op into an actionable message.
|
|
339
|
+
let stdout = '';
|
|
336
340
|
const timer = setTimeout(() => {
|
|
337
341
|
child.kill('SIGKILL');
|
|
338
342
|
reject(new Error(`${plan.command} MCP setup timed out.`));
|
|
339
343
|
}, 20_000);
|
|
340
344
|
child.stderr.on('data', (d) => (stderr += d.toString()));
|
|
345
|
+
child.stdout?.on('data', (d) => (stdout += d.toString()));
|
|
341
346
|
child.on('error', (e) => {
|
|
342
347
|
clearTimeout(timer);
|
|
343
348
|
reject(new Error(`Failed to start ${plan.command}: ${e.message}`));
|
|
344
349
|
});
|
|
345
350
|
child.on('close', (code) => {
|
|
346
351
|
clearTimeout(timer);
|
|
347
|
-
if (code === 0) return resolve();
|
|
352
|
+
if (code === 0) return resolve(`${stdout}\n${stderr}`.trim());
|
|
348
353
|
reject(new Error(`${plan.command} MCP setup exited ${code}: ${stderr.trim().split('\n').pop() || 'failed'}`));
|
|
349
354
|
});
|
|
350
355
|
try { child.stdin.end(); } catch { /* ignore */ }
|
|
351
356
|
});
|
|
352
357
|
}
|
|
353
358
|
|
|
359
|
+
// Turn a browser-tool setup failure into something the user can act on. The CLI's own words
|
|
360
|
+
// are the most accurate signal available, so we forward them — but when they name a missing
|
|
361
|
+
// SDK we say the fix, rather than repeating an `mcp add` that will fail identically.
|
|
362
|
+
export function mcpSetupHint(label, err) {
|
|
363
|
+
const msg = String(err?.message || err || '');
|
|
364
|
+
if (/mcp['" ]* Python SDK|No module named ['"]?mcp|MCP support/i.test(msg)) {
|
|
365
|
+
return `${label} has no MCP support installed. Run \`hermes setup\` (or install the \`mcp\` package in its environment), then retry.`;
|
|
366
|
+
}
|
|
367
|
+
if (/streamable_http|HTTP transport/i.test(msg)) {
|
|
368
|
+
return `${label}'s MCP client has no HTTP transport; ChatPanel registers a stdio server instead. Upgrade its \`mcp\` package if this persists.`;
|
|
369
|
+
}
|
|
370
|
+
return msg.slice(0, 200) || 'the CLI could not register the tools';
|
|
371
|
+
}
|
|
372
|
+
|
|
354
373
|
export async function ensureStableMcpConfig(spec, cwd, label, emit, deps = {}) {
|
|
355
374
|
if (!spec.requiresStableMcp) return true;
|
|
356
375
|
const hasConfig = deps.hasConfig || hasStableMcpConfig;
|
|
@@ -372,9 +391,15 @@ export async function ensureStableMcpConfig(spec, cwd, label, emit, deps = {}) {
|
|
|
372
391
|
}
|
|
373
392
|
|
|
374
393
|
emit({ type: 'status', text: `${label} is setting up one-time browser tools...` });
|
|
375
|
-
|
|
394
|
+
// Keep what the CLI said: it commonly exits 0 while refusing to register (no MCP SDK, no
|
|
395
|
+
// HTTP transport), and that sentence is the only accurate explanation available.
|
|
396
|
+
const setupOutput = String((await runSetup(plan, cwd)) || '').trim();
|
|
376
397
|
if (await hasConfig(spec, cwd)) return true;
|
|
377
|
-
throw new Error(
|
|
398
|
+
throw new Error(
|
|
399
|
+
`${label} browser-tool setup did not register the server.`
|
|
400
|
+
+ (setupOutput ? ` ${setupOutput.split('\n').filter(Boolean).slice(-3).join(' ')}` : '')
|
|
401
|
+
+ ` Run: ${setupCommand}`,
|
|
402
|
+
);
|
|
378
403
|
}
|
|
379
404
|
|
|
380
405
|
export async function chat({ messages, system, options, images }, emit, { signal } = {}) {
|
|
@@ -474,10 +499,25 @@ export async function runSpec(spec, { messages, system, options = {}, images },
|
|
|
474
499
|
: [...tmpl.split(/\s+/).filter(Boolean), cfgFile];
|
|
475
500
|
args = [...tokens, ...args];
|
|
476
501
|
}
|
|
477
|
-
if (options.mcp?.url) args.push(...mcpTrustArgs(spec, options.mcp));
|
|
478
502
|
// Some CLIs only load MCP from their persistent config, so ensure that stable
|
|
479
503
|
// /mcp endpoint is present before letting the agent answer with no tools.
|
|
480
|
-
|
|
504
|
+
//
|
|
505
|
+
// DEGRADE, DON'T FAIL. Browser tools are an ENHANCEMENT on top of a CLI that already has
|
|
506
|
+
// its own; a turn that could have been answered should not die because they couldn't be
|
|
507
|
+
// registered. (Hermes ships without the `mcp` Python SDK unless `hermes setup` installed
|
|
508
|
+
// it, so every tool-armed turn failed — and the error told the user to run a command that
|
|
509
|
+
// fails the same way.) We now say what happened, drop the browser tools, and answer.
|
|
510
|
+
if (options.mcp?.url) {
|
|
511
|
+
try {
|
|
512
|
+
await ensureStableMcpConfig(spec, cwd, label, emit);
|
|
513
|
+
} catch (e) {
|
|
514
|
+
emit({ type: 'status', text: `${label}: continuing without ChatPanel's browser tools — ${mcpSetupHint(label, e)}` });
|
|
515
|
+
options = { ...options, mcp: null };
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// Trust flags only make sense once the server is actually registered — pushing them for
|
|
519
|
+
// tools we then dropped would widen the CLI's permissions for nothing.
|
|
520
|
+
if (options.mcp?.url) args.push(...mcpTrustArgs(spec, options.mcp));
|
|
481
521
|
|
|
482
522
|
// Model via a CONFIG-PATCH FILE, for agents with no --model flag (dsh takes the
|
|
483
523
|
// model as a Cordis config overlay: `--patch <file>` replacing one row by id).
|
package/src/server.js
CHANGED
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
// Hardcoded (not read from package.json) so it survives Bun's single-file
|
|
68
68
|
// --compile, where package.json isn't on a readable FS. CI fails the publish if
|
|
69
69
|
// this drifts from package.json, so the two can't silently diverge.
|
|
70
|
-
const VERSION = '0.10.
|
|
70
|
+
const VERSION = '0.10.39';
|
|
71
71
|
const HOST = process.env.CHATPANEL_BRIDGE_HOST || '127.0.0.1';
|
|
72
72
|
const PORT = Number(process.env.CHATPANEL_BRIDGE_PORT) || 4319;
|
|
73
73
|
|