@chatpanel/bridge 0.10.15 → 0.10.16
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/antigravity.js +5 -67
- 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.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local bridge that exposes the AI coding agents installed on your machine — Claude Code (CLI), Codex (CLI), and Antigravity CLI (formerly Gemini CLI, which remains available for business/enterprise) — to the ChatPanel Chrome extension over a localhost SSE endpoint. Bring your own agent.",
|
|
6
6
|
"keywords": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// path so the model opens it.
|
|
12
12
|
|
|
13
13
|
import { spawn, spawnSync } from 'node:child_process';
|
|
14
|
-
import { mkdirSync, writeFileSync, unlinkSync
|
|
14
|
+
import { mkdirSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
15
15
|
import os from 'node:os';
|
|
16
16
|
import path from 'node:path';
|
|
17
17
|
import { findAgentBin } from '../env.js';
|
|
@@ -78,57 +78,6 @@ function writeImages(images, dir) {
|
|
|
78
78
|
return files;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
// Antigravity has no per-run MCP flag (`agy --help` shows none). The CLI only
|
|
82
|
-
// discovers MCP servers from config files: <cwd>/.agents/mcp_config.json
|
|
83
|
-
// (workspace) or ~/.gemini/config/mcp_config.json (global). To give a headless
|
|
84
|
-
// `agy -p` run our page/MCP tools, write the workspace file pointing at the
|
|
85
|
-
// bridge's per-session HTTP MCP server. Remote servers MUST use `serverUrl`
|
|
86
|
-
// (Antigravity rejects the legacy `url`/`httpUrl` fields). This is the agy
|
|
87
|
-
// equivalent of what claude.js/codex.js do via --mcp-config / -c mcp_servers.
|
|
88
|
-
//
|
|
89
|
-
// Non-destructive: an existing .agents/mcp_config.json is parsed, our one server
|
|
90
|
-
// merged in, and the original restored on cleanup. If the file exists but isn't
|
|
91
|
-
// JSON we recognize, we leave it untouched (and tools simply won't attach) rather
|
|
92
|
-
// than risk corrupting the user's config. Returns a cleanup fn (always callable).
|
|
93
|
-
function setupMcpConfig(mcp, cwd) {
|
|
94
|
-
if (!mcp?.url) return () => {};
|
|
95
|
-
const dir = path.join(cwd, '.agents');
|
|
96
|
-
const file = path.join(dir, 'mcp_config.json');
|
|
97
|
-
const serverName = mcp.serverName || 'chatpanel_browser';
|
|
98
|
-
const hadDir = existsSync(dir);
|
|
99
|
-
let prev = null; // original file contents (null = file did not exist)
|
|
100
|
-
|
|
101
|
-
let config = { mcpServers: {} };
|
|
102
|
-
if (existsSync(file)) {
|
|
103
|
-
try {
|
|
104
|
-
prev = readFileSync(file, 'utf8');
|
|
105
|
-
const parsed = JSON.parse(prev);
|
|
106
|
-
if (!parsed || typeof parsed !== 'object') return () => {};
|
|
107
|
-
config = parsed;
|
|
108
|
-
if (!config.mcpServers || typeof config.mcpServers !== 'object') config.mcpServers = {};
|
|
109
|
-
} catch {
|
|
110
|
-
return () => {}; // unreadable / not JSON — don't clobber it
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
config.mcpServers[serverName] = { serverUrl: mcp.url };
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
mkdirSync(dir, { recursive: true });
|
|
117
|
-
writeFileSync(file, JSON.stringify(config, null, 2));
|
|
118
|
-
} catch {
|
|
119
|
-
return () => {};
|
|
120
|
-
}
|
|
121
|
-
return () => {
|
|
122
|
-
try {
|
|
123
|
-
if (prev !== null) writeFileSync(file, prev); // restore original contents
|
|
124
|
-
else if (hadDir) rmSync(file, { force: true }); // remove just the file we added
|
|
125
|
-
else rmSync(dir, { recursive: true, force: true }); // remove the dir we created
|
|
126
|
-
} catch {
|
|
127
|
-
/* best effort */
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
81
|
export async function chat({ messages, system, options, images }, emit) {
|
|
133
82
|
try {
|
|
134
83
|
mkdirSync(SCRATCH, { recursive: true });
|
|
@@ -141,29 +90,18 @@ export async function chat({ messages, system, options, images }, emit) {
|
|
|
141
90
|
// reads @-referenced files (incl. images) inline as multimodal input, so no
|
|
142
91
|
// read-tool approval is needed in headless `-p` mode. (Confirmed working.)
|
|
143
92
|
const imageFiles = writeImages(images, cwd);
|
|
144
|
-
|
|
145
|
-
// per-run MCP flag). Tools then route: agy → bridge /mcp/<session> → extension.
|
|
146
|
-
const cleanupMcp = setupMcpConfig(options.mcp, cwd);
|
|
147
|
-
const cleanup = () => {
|
|
148
|
-
imageFiles.forEach((f) => { try { unlinkSync(f); } catch { /* gone */ } });
|
|
149
|
-
cleanupMcp();
|
|
150
|
-
};
|
|
93
|
+
const cleanup = () => imageFiles.forEach((f) => { try { unlinkSync(f); } catch { /* gone */ } });
|
|
151
94
|
let prompt = buildCliPrompt(messages, system);
|
|
152
95
|
if (imageFiles.length) {
|
|
153
96
|
prompt += `\n\nThe user attached image(s): ${imageFiles.map((f) => '@' + path.basename(f)).join(' ')}`;
|
|
154
97
|
}
|
|
155
98
|
|
|
156
99
|
// `-p` runs one prompt non-interactively. --model picks the model.
|
|
100
|
+
// --dangerously-skip-permissions auto-approves tool use (headless has no human
|
|
101
|
+
// approver) only when the user opted into bypassPermissions.
|
|
157
102
|
const args = ['-p', prompt];
|
|
158
103
|
if (options.model) args.push('--model', options.model);
|
|
159
|
-
|
|
160
|
-
// tool call just times out (it never reaches the server). So skip agy's own
|
|
161
|
-
// approval whenever the user opted into bypass OR we've attached page/MCP tools.
|
|
162
|
-
// The real gate stays on the ChatPanel side: each relayed call goes back to the
|
|
163
|
-
// extension, which applies its per-action confirmation for risky page actions.
|
|
164
|
-
if (options.permissionMode === 'bypassPermissions' || options.mcp?.url) {
|
|
165
|
-
args.push('--dangerously-skip-permissions');
|
|
166
|
-
}
|
|
104
|
+
if (options.permissionMode === 'bypassPermissions') args.push('--dangerously-skip-permissions');
|
|
167
105
|
if (options.extraArgs) args.push(...String(options.extraArgs).split(/\s+/).filter(Boolean));
|
|
168
106
|
|
|
169
107
|
await new Promise((resolve, reject) => {
|
package/src/server.js
CHANGED
|
@@ -37,7 +37,7 @@ import { assertPublicHttpUrl } from './ssrf.js';
|
|
|
37
37
|
// Hardcoded (not read from package.json) so it survives Bun's single-file
|
|
38
38
|
// --compile, where package.json isn't on a readable FS. CI fails the publish if
|
|
39
39
|
// this drifts from package.json, so the two can't silently diverge.
|
|
40
|
-
const VERSION = '0.10.
|
|
40
|
+
const VERSION = '0.10.16';
|
|
41
41
|
const HOST = process.env.CHATPANEL_BRIDGE_HOST || '127.0.0.1';
|
|
42
42
|
const PORT = Number(process.env.CHATPANEL_BRIDGE_PORT) || 4319;
|
|
43
43
|
|