@chatpanel/bridge 0.10.34 → 0.10.36
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/cli-agents.js +46 -0
- package/src/engines/custom.js +8 -0
- package/src/server.js +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/bridge",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.36",
|
|
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": [
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// pi — pi -p "<prompt>" · --model · @{path} images · --list-models
|
|
7
7
|
// opencode — opencode run "<prompt>" · -m provider/model · -f {path} images · models
|
|
8
8
|
// kiro — kiro-cli chat --no-interactive "<prompt>" · --model · --list-models
|
|
9
|
+
// hermes — hermes -z "<prompt>" · -m model · config get model (no list command)
|
|
9
10
|
|
|
10
11
|
import { runSpec, listSpecModels, runForStdout } from './custom.js';
|
|
11
12
|
import { findAgentBin } from '../env.js';
|
|
@@ -248,3 +249,48 @@ export async function listDshModels(command = 'dsh', workingDir) {
|
|
|
248
249
|
}
|
|
249
250
|
return [...DSH_KNOWN_MODELS];
|
|
250
251
|
}
|
|
252
|
+
|
|
253
|
+
// Hermes Agent (Nous Research). `-z/--oneshot` prints ONLY the final response text — no
|
|
254
|
+
// banner, no spinner, no tool previews — which is exactly the contract the shared runner
|
|
255
|
+
// wants, and it auto-bypasses approvals so a headless turn never blocks on a prompt.
|
|
256
|
+
//
|
|
257
|
+
// Its own tools and skills (82 of them here) stay ACTIVE: Hermes loads them itself, and the
|
|
258
|
+
// bridge's browser tools arrive over the stable /mcp endpoint like opencode and kiro, since
|
|
259
|
+
// Hermes only reads MCP servers from its own config rather than a per-run file.
|
|
260
|
+
//
|
|
261
|
+
// `hermes model` is interactive with no --list flag, so model discovery goes through
|
|
262
|
+
// `hermes config get model`, which prints the resolved default + provider as `key: value`
|
|
263
|
+
// lines. That yields the one model the user has actually configured — honest, if short.
|
|
264
|
+
export const hermes = makeCliAgent(
|
|
265
|
+
'hermes',
|
|
266
|
+
{
|
|
267
|
+
// `-z {prompt}`, NOT a bare `-z`: Hermes takes the prompt as the VALUE of -z (Python
|
|
268
|
+
// argparse), and the runner appends a trailing prompt only when no {prompt} placeholder
|
|
269
|
+
// exists — after the model flag. That produced `hermes -z -m <model> "<prompt>"`, where
|
|
270
|
+
// argparse saw -z followed by another flag: "expected one argument". The placeholder
|
|
271
|
+
// binds the prompt to the flag, so the model flag can sit anywhere after it.
|
|
272
|
+
args: '-z {prompt}',
|
|
273
|
+
promptVia: 'arg',
|
|
274
|
+
modelArg: '-m {model}',
|
|
275
|
+
requiresStableMcp: true,
|
|
276
|
+
autoSetupStableMcp: true,
|
|
277
|
+
stableMcpConfigCheck: 'hermes',
|
|
278
|
+
stableMcpSetupArgs: ['mcp', 'add', 'chatpanel_browser', '--url', 'http://127.0.0.1:4319/mcp'],
|
|
279
|
+
stableMcpSetupCommand: 'hermes mcp add chatpanel_browser --url http://127.0.0.1:4319/mcp',
|
|
280
|
+
label: 'Hermes',
|
|
281
|
+
},
|
|
282
|
+
'hermes not found on PATH. Install Hermes Agent, then run `hermes setup` to sign in.',
|
|
283
|
+
{
|
|
284
|
+
// `config get model` prints resolved settings as `key: value`; we want the default model
|
|
285
|
+
// id, not the provider or base_url lines around it.
|
|
286
|
+
listModels: async (command, options = {}) => {
|
|
287
|
+
try {
|
|
288
|
+
const out = await runForStdout(command, ['config', 'get', 'model'], options.workingDir);
|
|
289
|
+
const m = /^\s*default:\s*(\S+)/m.exec(out || '');
|
|
290
|
+
return m ? [m[1]] : [];
|
|
291
|
+
} catch {
|
|
292
|
+
return []; // not configured yet — the picker still accepts a typed id
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
);
|
package/src/engines/custom.js
CHANGED
|
@@ -307,9 +307,17 @@ async function kiroHasStableMcpConfig(command, cwd) {
|
|
|
307
307
|
return false;
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
+
// Hermes keeps MCP servers in its own config; `hermes mcp list` is the one honest way to ask
|
|
311
|
+
// whether ours is already registered (no scopes, unlike kiro).
|
|
312
|
+
async function hermesHasStableMcpConfig(command, cwd) {
|
|
313
|
+
const out = await commandOutput(command, ['mcp', 'list'], cwd);
|
|
314
|
+
return out.includes(CHATPANEL_STABLE_MCP_URL) || /chatpanel_browser/i.test(out);
|
|
315
|
+
}
|
|
316
|
+
|
|
310
317
|
async function hasStableMcpConfig(spec, cwd) {
|
|
311
318
|
if (spec.stableMcpConfigCheck === 'kiro') return kiroHasStableMcpConfig(spec.command || 'kiro-cli', cwd);
|
|
312
319
|
if (spec.stableMcpConfigCheck === 'opencode') return opencodeHasStableMcpConfig();
|
|
320
|
+
if (spec.stableMcpConfigCheck === 'hermes') return hermesHasStableMcpConfig(spec.command || 'hermes', cwd);
|
|
313
321
|
return false;
|
|
314
322
|
}
|
|
315
323
|
|
package/src/server.js
CHANGED
|
@@ -33,7 +33,7 @@ import { join } from 'node:path';
|
|
|
33
33
|
import * as claude from './engines/claude.js';
|
|
34
34
|
import * as codex from './engines/codex.js';
|
|
35
35
|
import * as antigravity from './engines/antigravity.js';
|
|
36
|
-
import { pi, opencode, kiro, copilot, deepseek } from './engines/cli-agents.js';
|
|
36
|
+
import { pi, opencode, kiro, copilot, deepseek , hermes } from './engines/cli-agents.js';
|
|
37
37
|
import { connectorsFor } from './connectors.js';
|
|
38
38
|
import * as custom from './engines/custom.js';
|
|
39
39
|
import { installService, uninstallService, serviceStatus, restartService } from './service.js';
|
|
@@ -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.36';
|
|
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
|
|
|
@@ -77,6 +77,7 @@ const ENGINES = {
|
|
|
77
77
|
antigravity: { engine: antigravity, label: 'Antigravity' },
|
|
78
78
|
pi: { engine: pi, label: 'Pi' },
|
|
79
79
|
opencode: { engine: opencode, label: 'OpenCode' },
|
|
80
|
+
hermes: { engine: hermes, label: 'Hermes' },
|
|
80
81
|
kiro: { engine: kiro, label: 'Kiro' },
|
|
81
82
|
copilot: { engine: copilot, label: 'GitHub Copilot' },
|
|
82
83
|
deepseek: { engine: deepseek, label: 'DeepSeek Harness' },
|