agent-relay 2.1.11 → 2.1.12
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/dist/index.cjs +64 -6
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +395 -1
- package/dist/src/cli/index.js.map +1 -1
- package/package.json +18 -18
- package/packages/acp-bridge/README.md +171 -0
- package/packages/acp-bridge/dist/acp-agent.d.ts +118 -0
- package/packages/acp-bridge/dist/acp-agent.d.ts.map +1 -0
- package/packages/acp-bridge/dist/acp-agent.js +713 -0
- package/packages/acp-bridge/dist/acp-agent.js.map +1 -0
- package/packages/acp-bridge/dist/cli.d.ts +18 -0
- package/packages/acp-bridge/dist/cli.d.ts.map +1 -0
- package/packages/acp-bridge/dist/cli.js +125 -0
- package/packages/acp-bridge/dist/cli.js.map +1 -0
- package/packages/acp-bridge/dist/index.d.ts +24 -0
- package/packages/acp-bridge/dist/index.d.ts.map +1 -0
- package/packages/acp-bridge/dist/index.js +22 -0
- package/packages/acp-bridge/dist/index.js.map +1 -0
- package/packages/acp-bridge/dist/types.d.ts +144 -0
- package/packages/acp-bridge/dist/types.d.ts.map +1 -0
- package/packages/acp-bridge/dist/types.js +6 -0
- package/packages/acp-bridge/dist/types.js.map +1 -0
- package/packages/acp-bridge/package.json +60 -0
- package/packages/acp-bridge/src/acp-agent.ts +826 -0
- package/packages/acp-bridge/src/cli.ts +137 -0
- package/packages/acp-bridge/src/index.ts +34 -0
- package/packages/acp-bridge/src/types.ts +142 -0
- package/packages/acp-bridge/tsconfig.json +11 -0
- package/packages/api-types/package.json +1 -1
- package/packages/benchmark/package.json +4 -4
- package/packages/bridge/package.json +8 -8
- package/packages/cli-tester/package.json +1 -1
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +2 -2
- package/packages/daemon/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/dist/client.d.ts.map +1 -1
- package/packages/mcp/dist/client.js +10 -2
- package/packages/mcp/dist/client.js.map +1 -1
- package/packages/mcp/dist/install.d.ts.map +1 -1
- package/packages/mcp/dist/install.js +75 -9
- package/packages/mcp/dist/install.js.map +1 -1
- package/packages/mcp/dist/tools/relay-connected.d.ts.map +1 -1
- package/packages/mcp/dist/tools/relay-connected.js +15 -1
- package/packages/mcp/dist/tools/relay-connected.js.map +1 -1
- package/packages/mcp/dist/tools/relay-who.d.ts.map +1 -1
- package/packages/mcp/dist/tools/relay-who.js +17 -2
- package/packages/mcp/dist/tools/relay-who.js.map +1 -1
- package/packages/mcp/package.json +4 -4
- package/packages/mcp/src/client.ts +10 -2
- package/packages/mcp/src/install.ts +85 -9
- package/packages/mcp/src/tools/relay-connected.ts +16 -1
- package/packages/mcp/src/tools/relay-who.ts +18 -2
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/package.json +3 -3
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +3 -3
- package/packages/wrapper/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -64724,8 +64724,59 @@ function getEditorConfig(editorKey) {
|
|
|
64724
64724
|
return editors[editorKey];
|
|
64725
64725
|
}
|
|
64726
64726
|
function stripJsonComments(content) {
|
|
64727
|
-
let result =
|
|
64728
|
-
|
|
64727
|
+
let result = "";
|
|
64728
|
+
let inString = false;
|
|
64729
|
+
let inSingleLineComment = false;
|
|
64730
|
+
let inMultiLineComment = false;
|
|
64731
|
+
let i = 0;
|
|
64732
|
+
while (i < content.length) {
|
|
64733
|
+
const char = content[i];
|
|
64734
|
+
const nextChar = content[i + 1];
|
|
64735
|
+
if (!inSingleLineComment && !inMultiLineComment) {
|
|
64736
|
+
if (char === '"' && (i === 0 || content[i - 1] !== "\\")) {
|
|
64737
|
+
inString = !inString;
|
|
64738
|
+
result += char;
|
|
64739
|
+
i++;
|
|
64740
|
+
continue;
|
|
64741
|
+
}
|
|
64742
|
+
if (inString) {
|
|
64743
|
+
result += char;
|
|
64744
|
+
i++;
|
|
64745
|
+
continue;
|
|
64746
|
+
}
|
|
64747
|
+
if (char === "/" && nextChar === "/") {
|
|
64748
|
+
inSingleLineComment = true;
|
|
64749
|
+
i += 2;
|
|
64750
|
+
continue;
|
|
64751
|
+
}
|
|
64752
|
+
if (char === "/" && nextChar === "*") {
|
|
64753
|
+
inMultiLineComment = true;
|
|
64754
|
+
i += 2;
|
|
64755
|
+
continue;
|
|
64756
|
+
}
|
|
64757
|
+
result += char;
|
|
64758
|
+
i++;
|
|
64759
|
+
continue;
|
|
64760
|
+
}
|
|
64761
|
+
if (inSingleLineComment) {
|
|
64762
|
+
if (char === "\n") {
|
|
64763
|
+
inSingleLineComment = false;
|
|
64764
|
+
result += char;
|
|
64765
|
+
}
|
|
64766
|
+
i++;
|
|
64767
|
+
continue;
|
|
64768
|
+
}
|
|
64769
|
+
if (inMultiLineComment) {
|
|
64770
|
+
if (char === "*" && nextChar === "/") {
|
|
64771
|
+
inMultiLineComment = false;
|
|
64772
|
+
i += 2;
|
|
64773
|
+
continue;
|
|
64774
|
+
}
|
|
64775
|
+
i++;
|
|
64776
|
+
continue;
|
|
64777
|
+
}
|
|
64778
|
+
i++;
|
|
64779
|
+
}
|
|
64729
64780
|
return result;
|
|
64730
64781
|
}
|
|
64731
64782
|
function readConfigFile(configPath, format) {
|
|
@@ -64823,12 +64874,19 @@ function installForEditor(editorKey, options = {}) {
|
|
|
64823
64874
|
const defaultConfig = buildServerConfig();
|
|
64824
64875
|
const serverConfig = {
|
|
64825
64876
|
command: options.command || defaultConfig.command,
|
|
64826
|
-
args: options.args || [...defaultConfig.args]
|
|
64877
|
+
args: options.args || [...defaultConfig.args],
|
|
64878
|
+
env: options.env ? { ...options.env } : void 0
|
|
64827
64879
|
};
|
|
64828
|
-
if (options.env) {
|
|
64829
|
-
serverConfig.env = { ...options.env };
|
|
64830
|
-
}
|
|
64831
64880
|
const isProjectLocal = !options.global && options.projectDir;
|
|
64881
|
+
if (isProjectLocal) {
|
|
64882
|
+
const projectSocket = (0, import_node_path16.join)(options.projectDir, ".agent-relay", "relay.sock");
|
|
64883
|
+
serverConfig.env = {
|
|
64884
|
+
...serverConfig.env || {},
|
|
64885
|
+
RELAY_SOCKET: serverConfig.env?.RELAY_SOCKET || projectSocket,
|
|
64886
|
+
RELAY_PROJECT: serverConfig.env?.RELAY_PROJECT || options.projectDir,
|
|
64887
|
+
AGENT_RELAY_PROJECT: serverConfig.env?.AGENT_RELAY_PROJECT || options.projectDir
|
|
64888
|
+
};
|
|
64889
|
+
}
|
|
64832
64890
|
if (isProjectLocal) {
|
|
64833
64891
|
serverConfig.args = [...serverConfig.args, "--project", options.projectDir];
|
|
64834
64892
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AA8VH;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqC7H"}
|
package/dist/src/cli/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import { initTelemetry, track, enableTelemetry, disableTelemetry, getStatus, isD
|
|
|
28
28
|
import { installMcpConfig } from '@agent-relay/mcp';
|
|
29
29
|
import fs from 'node:fs';
|
|
30
30
|
import path from 'node:path';
|
|
31
|
+
import { homedir } from 'node:os';
|
|
31
32
|
import readline from 'node:readline';
|
|
32
33
|
import { promisify } from 'node:util';
|
|
33
34
|
import { exec, execSync, spawn as spawnProcess } from 'node:child_process';
|
|
@@ -145,6 +146,163 @@ function startDashboardViaNpx(options) {
|
|
|
145
146
|
});
|
|
146
147
|
return { process: dashboardProcess, port: options.port, ready };
|
|
147
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Strip JSONC comments while preserving strings that contain // or /* sequences.
|
|
151
|
+
* Uses a state machine to track whether we're inside a string literal.
|
|
152
|
+
*/
|
|
153
|
+
function stripJsonComments(content) {
|
|
154
|
+
let result = '';
|
|
155
|
+
let inString = false;
|
|
156
|
+
let inSingleLineComment = false;
|
|
157
|
+
let inMultiLineComment = false;
|
|
158
|
+
let i = 0;
|
|
159
|
+
while (i < content.length) {
|
|
160
|
+
const char = content[i];
|
|
161
|
+
const nextChar = content[i + 1];
|
|
162
|
+
// Handle string state (only when not in a comment)
|
|
163
|
+
if (!inSingleLineComment && !inMultiLineComment) {
|
|
164
|
+
if (char === '"' && (i === 0 || content[i - 1] !== '\\')) {
|
|
165
|
+
inString = !inString;
|
|
166
|
+
result += char;
|
|
167
|
+
i++;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// If in string, just copy the character
|
|
171
|
+
if (inString) {
|
|
172
|
+
result += char;
|
|
173
|
+
i++;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
// Check for single-line comment start
|
|
177
|
+
if (char === '/' && nextChar === '/') {
|
|
178
|
+
inSingleLineComment = true;
|
|
179
|
+
i += 2;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// Check for multi-line comment start
|
|
183
|
+
if (char === '/' && nextChar === '*') {
|
|
184
|
+
inMultiLineComment = true;
|
|
185
|
+
i += 2;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
// Not in any comment or string, copy the character
|
|
189
|
+
result += char;
|
|
190
|
+
i++;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
// Handle single-line comment end
|
|
194
|
+
if (inSingleLineComment) {
|
|
195
|
+
if (char === '\n') {
|
|
196
|
+
inSingleLineComment = false;
|
|
197
|
+
result += char; // Preserve newline
|
|
198
|
+
}
|
|
199
|
+
i++;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
// Handle multi-line comment end
|
|
203
|
+
if (inMultiLineComment) {
|
|
204
|
+
if (char === '*' && nextChar === '/') {
|
|
205
|
+
inMultiLineComment = false;
|
|
206
|
+
i += 2;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
i++;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
i++;
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
function readJsonWithComments(filePath) {
|
|
217
|
+
if (!fs.existsSync(filePath))
|
|
218
|
+
return {};
|
|
219
|
+
try {
|
|
220
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
221
|
+
const sanitized = stripJsonComments(raw).trim();
|
|
222
|
+
if (!sanitized)
|
|
223
|
+
return {};
|
|
224
|
+
return JSON.parse(sanitized);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
throw new Error(`Failed to read ${filePath}: ${err.message}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function writeJson(filePath, data) {
|
|
231
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
232
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
233
|
+
}
|
|
234
|
+
function getZedSettingsPath(customPath) {
|
|
235
|
+
if (customPath)
|
|
236
|
+
return path.resolve(customPath);
|
|
237
|
+
const configDir = process.env.ZED_CONFIG_DIR || process.env.ZED_HOME || path.join(homedir(), '.config', 'zed');
|
|
238
|
+
return path.join(configDir, 'settings.json');
|
|
239
|
+
}
|
|
240
|
+
function findLocalAcpBridge(projectRoot) {
|
|
241
|
+
const candidates = [
|
|
242
|
+
path.join(projectRoot, 'packages', 'acp-bridge', 'dist', 'cli.js'),
|
|
243
|
+
path.join(projectRoot, 'node_modules', '@agent-relay', 'acp-bridge', 'dist', 'cli.js'),
|
|
244
|
+
];
|
|
245
|
+
for (const candidate of candidates) {
|
|
246
|
+
if (fs.existsSync(candidate)) {
|
|
247
|
+
return candidate;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
function buildZedAgentServerConfig(options) {
|
|
253
|
+
const bridgeName = options.bridgeName || 'zed-bridge';
|
|
254
|
+
const baseArgs = ['--name', bridgeName, '--socket', options.socketPath];
|
|
255
|
+
if (options.enableDebug)
|
|
256
|
+
baseArgs.push('--debug');
|
|
257
|
+
const localCli = findLocalAcpBridge(options.projectRoot);
|
|
258
|
+
if (localCli) {
|
|
259
|
+
return {
|
|
260
|
+
command: process.execPath,
|
|
261
|
+
args: [localCli, ...baseArgs],
|
|
262
|
+
env: {},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
command: 'relay-acp',
|
|
267
|
+
args: baseArgs,
|
|
268
|
+
env: {},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function configureZedAgentServer(options) {
|
|
272
|
+
const key = options.agentServerName || 'Agent Relay';
|
|
273
|
+
const config = readJsonWithComments(options.settingsPath);
|
|
274
|
+
const created = !fs.existsSync(options.settingsPath);
|
|
275
|
+
// Ensure root object
|
|
276
|
+
const normalizedConfig = typeof config === 'object' && config !== null ? { ...config } : {};
|
|
277
|
+
const agentServers = (normalizedConfig.agent_servers && typeof normalizedConfig.agent_servers === 'object'
|
|
278
|
+
? { ...normalizedConfig.agent_servers }
|
|
279
|
+
: {});
|
|
280
|
+
normalizedConfig.agent_servers = agentServers;
|
|
281
|
+
const serverConfig = buildZedAgentServerConfig({
|
|
282
|
+
projectRoot: options.projectRoot,
|
|
283
|
+
socketPath: options.socketPath,
|
|
284
|
+
bridgeName: 'zed-bridge',
|
|
285
|
+
enableDebug: options.enableDebug,
|
|
286
|
+
});
|
|
287
|
+
const targetEntry = {
|
|
288
|
+
type: 'custom',
|
|
289
|
+
command: serverConfig.command,
|
|
290
|
+
args: serverConfig.args,
|
|
291
|
+
env: serverConfig.env,
|
|
292
|
+
};
|
|
293
|
+
const existingEntry = agentServers[key];
|
|
294
|
+
const unchanged = existingEntry && JSON.stringify(existingEntry) === JSON.stringify(targetEntry);
|
|
295
|
+
if (!unchanged) {
|
|
296
|
+
agentServers[key] = targetEntry;
|
|
297
|
+
writeJson(options.settingsPath, normalizedConfig);
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
updated: !unchanged,
|
|
301
|
+
created,
|
|
302
|
+
path: options.settingsPath,
|
|
303
|
+
key,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
148
306
|
/**
|
|
149
307
|
* Install agent-relay-snippet to markdown files using prpm.
|
|
150
308
|
* Installs to CLAUDE.md, GEMINI.md, and AGENTS.md.
|
|
@@ -470,6 +628,9 @@ program
|
|
|
470
628
|
.option('--watch', 'Auto-restart daemon on crash (supervisor mode)')
|
|
471
629
|
.option('--max-restarts <n>', 'Max restarts in 60s before giving up (default: 5)', '5')
|
|
472
630
|
.option('--verbose', 'Enable verbose logging (show debug output in console)')
|
|
631
|
+
.option('--zed', 'Add Agent Relay entry to Zed agent_servers for this workspace')
|
|
632
|
+
.option('--zed-config <path>', 'Custom path to Zed settings.json (defaults to ~/.config/zed/settings.json)')
|
|
633
|
+
.option('--zed-name <name>', 'Display name for the Zed agent server (default: Agent Relay)')
|
|
473
634
|
.action(async (options) => {
|
|
474
635
|
// If --watch is specified, run in supervisor mode
|
|
475
636
|
if (options.watch) {
|
|
@@ -494,6 +655,12 @@ program
|
|
|
494
655
|
args.push('--no-spawn');
|
|
495
656
|
if (options.verbose)
|
|
496
657
|
args.push('--verbose');
|
|
658
|
+
if (options.zed)
|
|
659
|
+
args.push('--zed');
|
|
660
|
+
if (options.zedConfig)
|
|
661
|
+
args.push('--zed-config', options.zedConfig);
|
|
662
|
+
if (options.zedName)
|
|
663
|
+
args.push('--zed-name', options.zedName);
|
|
497
664
|
console.log(`[supervisor] Starting daemon...`);
|
|
498
665
|
child = spawnProcess(process.execPath, [process.argv[1], ...args], {
|
|
499
666
|
stdio: 'inherit',
|
|
@@ -569,6 +736,25 @@ program
|
|
|
569
736
|
}
|
|
570
737
|
console.log('');
|
|
571
738
|
}
|
|
739
|
+
// Optionally configure Zed agent_servers with the ACP bridge
|
|
740
|
+
if (options.zed) {
|
|
741
|
+
try {
|
|
742
|
+
const zedSettingsPath = getZedSettingsPath(options.zedConfig);
|
|
743
|
+
const zedDebug = options.verbose === undefined ? true : Boolean(options.verbose);
|
|
744
|
+
const result = configureZedAgentServer({
|
|
745
|
+
settingsPath: zedSettingsPath,
|
|
746
|
+
socketPath,
|
|
747
|
+
projectRoot: paths.projectRoot,
|
|
748
|
+
agentServerName: options.zedName,
|
|
749
|
+
enableDebug: zedDebug,
|
|
750
|
+
});
|
|
751
|
+
const status = result.updated ? (result.created ? 'created' : 'updated') : 'already configured';
|
|
752
|
+
console.log(`[zed] ${status}: ${result.path} (${result.key})`);
|
|
753
|
+
}
|
|
754
|
+
catch (err) {
|
|
755
|
+
console.log(`[zed] Failed to configure Zed agent_servers: ${err.message}`);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
572
758
|
// Set up log file to avoid console output polluting TUI terminals
|
|
573
759
|
// Only set if not already configured via environment
|
|
574
760
|
// Skip if --verbose is set (logs go to console in verbose mode)
|
|
@@ -956,6 +1142,214 @@ program
|
|
|
956
1142
|
}
|
|
957
1143
|
}
|
|
958
1144
|
});
|
|
1145
|
+
// uninstall - Remove agent-relay from the current project
|
|
1146
|
+
program
|
|
1147
|
+
.command('uninstall')
|
|
1148
|
+
.description('Remove agent-relay data and configuration from the current project')
|
|
1149
|
+
.option('--keep-data', 'Keep message history and database (only remove runtime files)')
|
|
1150
|
+
.option('--zed', 'Also remove Zed editor configuration')
|
|
1151
|
+
.option('--zed-name <name>', 'Name of the Zed agent server entry to remove (default: Agent Relay)')
|
|
1152
|
+
.option('--snippets', 'Also remove agent-relay snippets from CLAUDE.md, GEMINI.md, AGENTS.md')
|
|
1153
|
+
.option('--force', 'Skip confirmation prompt')
|
|
1154
|
+
.option('--dry-run', 'Show what would be removed without actually removing')
|
|
1155
|
+
.action(async (options) => {
|
|
1156
|
+
const paths = getProjectPaths();
|
|
1157
|
+
const readline = await import('node:readline');
|
|
1158
|
+
const filesToRemove = [];
|
|
1159
|
+
const dirsToRemove = [];
|
|
1160
|
+
const actions = [];
|
|
1161
|
+
// Check if .agent-relay directory exists
|
|
1162
|
+
if (!fs.existsSync(paths.dataDir)) {
|
|
1163
|
+
console.log('Agent Relay is not installed in this project.');
|
|
1164
|
+
console.log(`(No ${paths.dataDir} directory found)`);
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
// Stop daemon if running
|
|
1168
|
+
const pidPath = pidFilePathForSocket(paths.socketPath);
|
|
1169
|
+
if (fs.existsSync(pidPath)) {
|
|
1170
|
+
const pid = Number(fs.readFileSync(pidPath, 'utf-8').trim());
|
|
1171
|
+
try {
|
|
1172
|
+
process.kill(pid, 0); // Check if running
|
|
1173
|
+
actions.push(`Stop daemon (pid: ${pid})`);
|
|
1174
|
+
if (!options.dryRun) {
|
|
1175
|
+
try {
|
|
1176
|
+
process.kill(pid, 'SIGTERM');
|
|
1177
|
+
// Wait briefly for graceful shutdown
|
|
1178
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
1179
|
+
}
|
|
1180
|
+
catch { /* ignore */ }
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
catch { /* not running */ }
|
|
1184
|
+
}
|
|
1185
|
+
// Collect files to remove
|
|
1186
|
+
if (options.keepData) {
|
|
1187
|
+
// Only remove runtime files, keep database
|
|
1188
|
+
const runtimeFiles = ['relay.sock', 'runtime.json', 'daemon.pid', '.project'];
|
|
1189
|
+
for (const file of runtimeFiles) {
|
|
1190
|
+
const filePath = path.join(paths.dataDir, file);
|
|
1191
|
+
if (fs.existsSync(filePath)) {
|
|
1192
|
+
filesToRemove.push(filePath);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
// Remove mcp-identity-* files
|
|
1196
|
+
try {
|
|
1197
|
+
const files = fs.readdirSync(paths.dataDir);
|
|
1198
|
+
for (const file of files) {
|
|
1199
|
+
if (file.startsWith('mcp-identity')) {
|
|
1200
|
+
filesToRemove.push(path.join(paths.dataDir, file));
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
catch { /* ignore */ }
|
|
1205
|
+
actions.push('Remove runtime files (keeping database and message history)');
|
|
1206
|
+
}
|
|
1207
|
+
else {
|
|
1208
|
+
// Remove entire .agent-relay directory
|
|
1209
|
+
dirsToRemove.push(paths.dataDir);
|
|
1210
|
+
actions.push(`Remove ${paths.dataDir}/ directory (including message history)`);
|
|
1211
|
+
}
|
|
1212
|
+
// Zed configuration
|
|
1213
|
+
if (options.zed) {
|
|
1214
|
+
const zedSettingsPath = getZedSettingsPath();
|
|
1215
|
+
if (fs.existsSync(zedSettingsPath)) {
|
|
1216
|
+
const zedNameToRemove = options.zedName || 'Agent Relay';
|
|
1217
|
+
actions.push(`Remove "${zedNameToRemove}" (and any relay-acp entries) from Zed settings`);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
// Snippets
|
|
1221
|
+
if (options.snippets) {
|
|
1222
|
+
const snippetFiles = ['CLAUDE.md', 'GEMINI.md', 'AGENTS.md'];
|
|
1223
|
+
for (const file of snippetFiles) {
|
|
1224
|
+
const filePath = path.join(paths.projectRoot, file);
|
|
1225
|
+
if (fs.existsSync(filePath)) {
|
|
1226
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
1227
|
+
if (content.includes('agent-relay-snippet') || content.includes('agent-relay-protocol')) {
|
|
1228
|
+
actions.push(`Remove agent-relay snippets from ${file}`);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
// Show what will be done
|
|
1234
|
+
console.log('');
|
|
1235
|
+
console.log('Agent Relay Uninstall');
|
|
1236
|
+
console.log('=====================');
|
|
1237
|
+
console.log('');
|
|
1238
|
+
console.log('The following actions will be performed:');
|
|
1239
|
+
console.log('');
|
|
1240
|
+
for (const action of actions) {
|
|
1241
|
+
console.log(` • ${action}`);
|
|
1242
|
+
}
|
|
1243
|
+
console.log('');
|
|
1244
|
+
if (options.dryRun) {
|
|
1245
|
+
console.log('[dry-run] No changes made.');
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
// Confirm unless --force
|
|
1249
|
+
if (!options.force) {
|
|
1250
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1251
|
+
const answer = await new Promise(resolve => {
|
|
1252
|
+
rl.question('Continue? [y/N] ', resolve);
|
|
1253
|
+
});
|
|
1254
|
+
rl.close();
|
|
1255
|
+
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
1256
|
+
console.log('Aborted.');
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
// Perform removal
|
|
1261
|
+
console.log('');
|
|
1262
|
+
// Remove files
|
|
1263
|
+
for (const file of filesToRemove) {
|
|
1264
|
+
try {
|
|
1265
|
+
fs.unlinkSync(file);
|
|
1266
|
+
console.log(` ✓ Removed ${path.relative(paths.projectRoot, file)}`);
|
|
1267
|
+
}
|
|
1268
|
+
catch (err) {
|
|
1269
|
+
console.log(` ✗ Failed to remove ${path.relative(paths.projectRoot, file)}: ${err.message}`);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
// Remove directories
|
|
1273
|
+
for (const dir of dirsToRemove) {
|
|
1274
|
+
try {
|
|
1275
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
1276
|
+
console.log(` ✓ Removed ${path.relative(paths.projectRoot, dir)}/`);
|
|
1277
|
+
}
|
|
1278
|
+
catch (err) {
|
|
1279
|
+
console.log(` ✗ Failed to remove ${path.relative(paths.projectRoot, dir)}/: ${err.message}`);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
// Remove Zed config
|
|
1283
|
+
if (options.zed) {
|
|
1284
|
+
const zedSettingsPath = getZedSettingsPath();
|
|
1285
|
+
if (fs.existsSync(zedSettingsPath)) {
|
|
1286
|
+
try {
|
|
1287
|
+
const config = readJsonWithComments(zedSettingsPath);
|
|
1288
|
+
const agentServers = config.agent_servers;
|
|
1289
|
+
if (agentServers) {
|
|
1290
|
+
const removedEntries = [];
|
|
1291
|
+
const zedNameToRemove = options.zedName || 'Agent Relay';
|
|
1292
|
+
// Remove the specified entry by name
|
|
1293
|
+
if (agentServers[zedNameToRemove]) {
|
|
1294
|
+
delete agentServers[zedNameToRemove];
|
|
1295
|
+
removedEntries.push(zedNameToRemove);
|
|
1296
|
+
}
|
|
1297
|
+
// Also scan for any entries that look like relay-acp bridge
|
|
1298
|
+
// (command/args contain 'acp-bridge' or 'relay-acp')
|
|
1299
|
+
for (const [key, value] of Object.entries(agentServers)) {
|
|
1300
|
+
if (key === zedNameToRemove)
|
|
1301
|
+
continue; // Already handled
|
|
1302
|
+
if (typeof value === 'object' && value !== null) {
|
|
1303
|
+
const entry = value;
|
|
1304
|
+
const command = entry.command;
|
|
1305
|
+
const args = entry.args;
|
|
1306
|
+
const isRelayAcp = (command && (command.includes('acp-bridge') || command.includes('relay-acp'))) ||
|
|
1307
|
+
(args && args.some(arg => arg.includes('acp-bridge') || arg.includes('relay-acp')));
|
|
1308
|
+
if (isRelayAcp) {
|
|
1309
|
+
delete agentServers[key];
|
|
1310
|
+
removedEntries.push(key);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
if (removedEntries.length > 0) {
|
|
1315
|
+
writeJson(zedSettingsPath, config);
|
|
1316
|
+
for (const entry of removedEntries) {
|
|
1317
|
+
console.log(` ✓ Removed "${entry}" from Zed settings`);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
catch (err) {
|
|
1323
|
+
console.log(` ✗ Failed to update Zed settings: ${err.message}`);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
// Remove snippets
|
|
1328
|
+
if (options.snippets) {
|
|
1329
|
+
const snippetFiles = ['CLAUDE.md', 'GEMINI.md', 'AGENTS.md'];
|
|
1330
|
+
for (const file of snippetFiles) {
|
|
1331
|
+
const filePath = path.join(paths.projectRoot, file);
|
|
1332
|
+
if (fs.existsSync(filePath)) {
|
|
1333
|
+
try {
|
|
1334
|
+
let content = fs.readFileSync(filePath, 'utf-8');
|
|
1335
|
+
const originalLength = content.length;
|
|
1336
|
+
// Remove prpm snippet blocks
|
|
1337
|
+
content = content.replace(/<!-- prpm:snippet:start @agent-relay\/agent-relay-snippet.*?<!-- prpm:snippet:end @agent-relay\/agent-relay-snippet[^\n]*\n?/gs, '');
|
|
1338
|
+
content = content.replace(/<!-- prpm:snippet:start @agent-relay\/agent-relay-protocol.*?<!-- prpm:snippet:end @agent-relay\/agent-relay-protocol[^\n]*\n?/gs, '');
|
|
1339
|
+
if (content.length !== originalLength) {
|
|
1340
|
+
fs.writeFileSync(filePath, content);
|
|
1341
|
+
console.log(` ✓ Removed agent-relay snippets from ${file}`);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
catch (err) {
|
|
1345
|
+
console.log(` ✗ Failed to update ${file}: ${err.message}`);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
console.log('');
|
|
1351
|
+
console.log('Uninstall complete.');
|
|
1352
|
+
});
|
|
959
1353
|
program
|
|
960
1354
|
.command('status')
|
|
961
1355
|
.description('Check daemon status')
|
|
@@ -1794,7 +2188,7 @@ function loadAgents(agentsPath) {
|
|
|
1794
2188
|
}
|
|
1795
2189
|
const STALE_THRESHOLD_MS = 30_000;
|
|
1796
2190
|
// Internal agents that should be hidden from `agents` and `who` by default
|
|
1797
|
-
const INTERNAL_AGENTS = new Set(['cli', 'Dashboard']);
|
|
2191
|
+
const INTERNAL_AGENTS = new Set(['cli', 'Dashboard', 'zed-bridge']);
|
|
1798
2192
|
function isInternalAgent(name) {
|
|
1799
2193
|
if (!name)
|
|
1800
2194
|
return true;
|