agent-relay-server 0.32.4 → 0.33.1
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 +2 -2
- package/public/assets/{activity-DT1JGHnp.js → activity-B0_uE6Yh.js} +2 -2
- package/public/assets/{activity-DT1JGHnp.js.map → activity-B0_uE6Yh.js.map} +1 -1
- package/public/assets/{agent-profiles-CrMemMkZ.js → agent-profiles-Rwxrcf9F.js} +2 -2
- package/public/assets/{agent-profiles-CrMemMkZ.js.map → agent-profiles-Rwxrcf9F.js.map} +1 -1
- package/public/assets/{agents-Bl-rrgOy.js → agents-Dp1EXJc8.js} +2 -2
- package/public/assets/{agents-Bl-rrgOy.js.map → agents-Dp1EXJc8.js.map} +1 -1
- package/public/assets/{analytics-a663ak56.js → analytics-D5OT5ajj.js} +2 -2
- package/public/assets/{analytics-a663ak56.js.map → analytics-D5OT5ajj.js.map} +1 -1
- package/public/assets/automation-Dm6rXNxK.js +2 -0
- package/public/assets/{automation-CiaLThdO.js.map → automation-Dm6rXNxK.js.map} +1 -1
- package/public/assets/{branch-state-badge-D4ur3m3_.js → branch-state-badge-FX5Yww2s.js} +2 -2
- package/public/assets/{branch-state-badge-D4ur3m3_.js.map → branch-state-badge-FX5Yww2s.js.map} +1 -1
- package/public/assets/{channels-o9KLTHoK.js → channels--rdAiX17.js} +2 -2
- package/public/assets/{channels-o9KLTHoK.js.map → channels--rdAiX17.js.map} +1 -1
- package/public/assets/chat-JZAEDGfX.js +2 -0
- package/public/assets/chat-JZAEDGfX.js.map +1 -0
- package/public/assets/{connectors-CdC806mA.js → connectors-Bx4gzvNf.js} +2 -2
- package/public/assets/{connectors-CdC806mA.js.map → connectors-Bx4gzvNf.js.map} +1 -1
- package/public/assets/display-Bebqs1qu.js +3 -0
- package/public/assets/display-Bebqs1qu.js.map +1 -0
- package/public/assets/{formatted-body-impl-Ca74OAEH.js → formatted-body-impl-CVq4qHix.js} +2 -2
- package/public/assets/{formatted-body-impl-Ca74OAEH.js.map → formatted-body-impl-CVq4qHix.js.map} +1 -1
- package/public/assets/{index-C_33ymaw.js → index-BHRtR4q7.js} +8 -8
- package/public/assets/{index-C_33ymaw.js.map → index-BHRtR4q7.js.map} +1 -1
- package/public/assets/{insights-ClI68s39.js → insights-yJFgCa3o.js} +2 -2
- package/public/assets/{insights-ClI68s39.js.map → insights-yJFgCa3o.js.map} +1 -1
- package/public/assets/{integrations-1nxMizDY.js → integrations-k1HIONjo.js} +2 -2
- package/public/assets/{integrations-1nxMizDY.js.map → integrations-k1HIONjo.js.map} +1 -1
- package/public/assets/maintenance-CsoOFBXx.js +2 -0
- package/public/assets/{maintenance-DiFNzNPN.js.map → maintenance-CsoOFBXx.js.map} +1 -1
- package/public/assets/{managed-agents-Do3dKvfj.js → managed-agents-Q3HuVjGg.js} +2 -2
- package/public/assets/{managed-agents-Do3dKvfj.js.map → managed-agents-Q3HuVjGg.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-CLA0J255.js → markdown-preview-impl-CnsMjrnu.js} +2 -2
- package/public/assets/{markdown-preview-impl-CLA0J255.js.map → markdown-preview-impl-CnsMjrnu.js.map} +1 -1
- package/public/assets/{memory-IjwqFzBd.js → memory-D3-K5eJS.js} +2 -2
- package/public/assets/{memory-IjwqFzBd.js.map → memory-D3-K5eJS.js.map} +1 -1
- package/public/assets/{messages-DjvWqHyn.js → messages-B4lCP5rS.js} +2 -2
- package/public/assets/{messages-DjvWqHyn.js.map → messages-B4lCP5rS.js.map} +1 -1
- package/public/assets/{orchestrators-D2IqDxDT.js → orchestrators-CRoZtLeQ.js} +2 -2
- package/public/assets/{orchestrators-D2IqDxDT.js.map → orchestrators-CRoZtLeQ.js.map} +1 -1
- package/public/assets/{overview-DKC3TbAh.js → overview-CxCU2fOF.js} +2 -2
- package/public/assets/{overview-DKC3TbAh.js.map → overview-CxCU2fOF.js.map} +1 -1
- package/public/assets/pairs-unqjPlmq.js +2 -0
- package/public/assets/{pairs-WpKCPE1n.js.map → pairs-unqjPlmq.js.map} +1 -1
- package/public/assets/{security-BF7ZtPQe.js → security-B7HhSYNy.js} +2 -2
- package/public/assets/{security-BF7ZtPQe.js.map → security-B7HhSYNy.js.map} +1 -1
- package/public/assets/{settings-CQnjrTa-.js → settings-B9NDhsAb.js} +2 -2
- package/public/assets/{settings-CQnjrTa-.js.map → settings-B9NDhsAb.js.map} +1 -1
- package/public/assets/store-DiSzYHj9.js +9 -0
- package/public/assets/{store-C9VcSo05.js.map → store-DiSzYHj9.js.map} +1 -1
- package/public/assets/{tasks-CbN_GSSb.js → tasks-CIQolvNm.js} +2 -2
- package/public/assets/{tasks-CbN_GSSb.js.map → tasks-CIQolvNm.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-BJRohThT.js → terminal-viewer-impl-DCifVqFR.js} +2 -2
- package/public/assets/{terminal-viewer-impl-BJRohThT.js.map → terminal-viewer-impl-DCifVqFR.js.map} +1 -1
- package/public/assets/{work-queue-C5xLBLmm.js → work-queue-Dr3c1V6O.js} +2 -2
- package/public/assets/{work-queue-C5xLBLmm.js.map → work-queue-Dr3c1V6O.js.map} +1 -1
- package/public/assets/{workspaces-D91H3wDX.js → workspaces-B1Jxop7h.js} +3 -3
- package/public/assets/{workspaces-D91H3wDX.js.map → workspaces-B1Jxop7h.js.map} +1 -1
- package/public/index.html +3 -3
- package/runner/src/adapter.ts +1 -1
- package/src/agent-lifecycle-events.ts +137 -0
- package/src/artifact-storage.ts +3 -5
- package/src/channel-target.ts +24 -0
- package/src/cli/_shared.ts +80 -0
- package/src/cli/agent-detect.ts +188 -0
- package/src/cli/agent-meta.ts +95 -0
- package/src/cli/context-probe.ts +88 -0
- package/src/cli/daemon.ts +111 -0
- package/src/cli/dev.ts +173 -0
- package/src/cli/index.ts +361 -0
- package/src/cli/introspect.ts +73 -0
- package/src/cli/memory.ts +37 -0
- package/src/cli/message.ts +201 -0
- package/src/cli/orchestrator.ts +227 -0
- package/src/cli/pair.ts +125 -0
- package/src/cli/provider.ts +209 -0
- package/src/cli/recipe.ts +110 -0
- package/src/cli/reply.ts +141 -0
- package/src/cli/setup.ts +57 -0
- package/src/cli/steward.ts +59 -0
- package/src/cli/token.ts +81 -0
- package/src/cli/upgrade.ts +193 -0
- package/src/cli/workspace.ts +215 -0
- package/src/cli.ts +4 -2718
- package/src/config-store.ts +10 -6
- package/src/db/activity.ts +194 -0
- package/src/db/agent-search.ts +174 -0
- package/src/db/agents.ts +551 -0
- package/src/db/artifacts.ts +342 -0
- package/src/db/channels.ts +576 -0
- package/src/db/connection.ts +71 -0
- package/src/db/delivery.ts +395 -0
- package/src/db/inbox.ts +249 -0
- package/src/db/index.ts +23 -0
- package/src/db/integrations.ts +339 -0
- package/src/db/mappers.ts +397 -0
- package/src/db/merge-lease.ts +160 -0
- package/src/db/message-reads.ts +304 -0
- package/src/db/messages.ts +434 -0
- package/src/db/migrations.ts +431 -0
- package/src/db/orchestrators.ts +358 -0
- package/src/db/pairs.ts +324 -0
- package/src/db/schema.ts +758 -0
- package/src/db/stats.ts +337 -0
- package/src/db/tasks.ts +407 -0
- package/src/db/workspaces.ts +440 -0
- package/src/db.ts +4 -5721
- package/src/maintenance.ts +4 -0
- package/src/mcp-errors.ts +7 -0
- package/src/mcp.ts +32 -34
- package/src/routes/agents-spawn.ts +9 -1
- package/src/routes/agents.ts +5 -0
- package/src/routes/commands.ts +15 -0
- package/src/routes/integrations.ts +6 -8
- package/src/spawn-targets.ts +159 -0
- package/src/utils.ts +16 -1
- package/public/assets/automation-CiaLThdO.js +0 -2
- package/public/assets/chat-5hvHZcAe.js +0 -2
- package/public/assets/chat-5hvHZcAe.js.map +0 -1
- package/public/assets/display-JI19Vc7L.js +0 -3
- package/public/assets/display-JI19Vc7L.js.map +0 -1
- package/public/assets/maintenance-DiFNzNPN.js +0 -2
- package/public/assets/pairs-WpKCPE1n.js +0 -2
- package/public/assets/store-C9VcSo05.js +0 -9
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Daemon command — auto-split from cli.ts (#294). Installs/manages the relay
|
|
2
|
+
// server as a user/system service.
|
|
3
|
+
import {
|
|
4
|
+
createDaemonPlan,
|
|
5
|
+
detectDaemonEnvironment,
|
|
6
|
+
executeDaemonPlan,
|
|
7
|
+
formatDaemonPlan,
|
|
8
|
+
type DaemonAction,
|
|
9
|
+
type DaemonScope,
|
|
10
|
+
} from "../daemon";
|
|
11
|
+
import { createSetupPlan, executeSetupPlan, pathExists } from "../setup";
|
|
12
|
+
import { confirm } from "./_shared";
|
|
13
|
+
|
|
14
|
+
const DAEMON_ACTIONS = new Set<DaemonAction>([
|
|
15
|
+
"install",
|
|
16
|
+
"uninstall",
|
|
17
|
+
"start",
|
|
18
|
+
"stop",
|
|
19
|
+
"restart",
|
|
20
|
+
"enable",
|
|
21
|
+
"disable",
|
|
22
|
+
"status",
|
|
23
|
+
"logs",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
export async function handleDaemonCommand(args: string[]): Promise<void> {
|
|
27
|
+
const action = parseDaemonAction(args[0]);
|
|
28
|
+
let name: string | undefined;
|
|
29
|
+
let envFile: string | undefined;
|
|
30
|
+
let port: number | undefined;
|
|
31
|
+
let host: string | undefined;
|
|
32
|
+
let scope: DaemonScope | undefined;
|
|
33
|
+
let binaryPath: string | undefined;
|
|
34
|
+
let runtimePrefix: string | undefined;
|
|
35
|
+
const pathPrefix: string[] = [];
|
|
36
|
+
let start = false;
|
|
37
|
+
let enable = false;
|
|
38
|
+
let dryRun = false;
|
|
39
|
+
let force = false;
|
|
40
|
+
let yes = false;
|
|
41
|
+
let json = false;
|
|
42
|
+
|
|
43
|
+
for (let i = 1; i < args.length; i++) {
|
|
44
|
+
const arg = args[i];
|
|
45
|
+
if (arg === "--name" && i + 1 < args.length) name = args[++i];
|
|
46
|
+
else if (arg === "--env-file" && i + 1 < args.length) envFile = args[++i];
|
|
47
|
+
else if (arg === "--port" && i + 1 < args.length) port = parseInt(args[++i]!, 10);
|
|
48
|
+
else if (arg === "--host" && i + 1 < args.length) host = args[++i];
|
|
49
|
+
else if (arg === "--user") scope = "user";
|
|
50
|
+
else if (arg === "--system") scope = "system";
|
|
51
|
+
else if (arg === "--binary" && i + 1 < args.length) binaryPath = args[++i];
|
|
52
|
+
else if (arg === "--runtime-prefix" && i + 1 < args.length) runtimePrefix = args[++i];
|
|
53
|
+
else if (arg === "--path-prefix" && i + 1 < args.length) pathPrefix.push(args[++i]!);
|
|
54
|
+
else if (arg === "--start") start = true;
|
|
55
|
+
else if (arg === "--enable") enable = true;
|
|
56
|
+
else if (arg === "--dry-run") dryRun = true;
|
|
57
|
+
else if (arg === "--force") force = true;
|
|
58
|
+
else if (arg === "--yes") yes = true;
|
|
59
|
+
else if (arg === "--json") json = true;
|
|
60
|
+
else throw new Error(`Unknown daemon option "${arg}"`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (action === "install" && !dryRun && !envFile && !(await pathExists(createSetupPlan().envFile))) {
|
|
64
|
+
const setupPlan = createSetupPlan({
|
|
65
|
+
...(host ? { host } : {}),
|
|
66
|
+
...(port !== undefined ? { port } : {}),
|
|
67
|
+
...(runtimePrefix ? { runtimePrefix } : {}),
|
|
68
|
+
});
|
|
69
|
+
const ok = yes || await confirm(`Create daemon env file at ${setupPlan.envFile}?`);
|
|
70
|
+
if (!ok) throw new Error("Daemon install needs an env file. Run `agent-relay setup` first.");
|
|
71
|
+
console.log(await executeSetupPlan(setupPlan, { force }));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const env = await detectDaemonEnvironment();
|
|
75
|
+
const plan = createDaemonPlan({
|
|
76
|
+
action,
|
|
77
|
+
...(name ? { name } : {}),
|
|
78
|
+
...(envFile ? { envFile } : {}),
|
|
79
|
+
...(port !== undefined ? { port } : {}),
|
|
80
|
+
...(host ? { host } : {}),
|
|
81
|
+
...(scope ? { scope } : {}),
|
|
82
|
+
...(binaryPath ? { binaryPath } : {}),
|
|
83
|
+
...(runtimePrefix ? { runtimePrefix } : {}),
|
|
84
|
+
...(pathPrefix.length ? { pathPrefix } : {}),
|
|
85
|
+
start,
|
|
86
|
+
enable,
|
|
87
|
+
}, env);
|
|
88
|
+
|
|
89
|
+
if (!dryRun && !json && (action === "install" || action === "uninstall") && !yes) {
|
|
90
|
+
const ok = await confirm(
|
|
91
|
+
action === "install"
|
|
92
|
+
? `Install ${plan.kind} ${plan.scope} daemon "${plan.name}"?`
|
|
93
|
+
: `Uninstall daemon "${plan.name}"?`,
|
|
94
|
+
);
|
|
95
|
+
if (!ok) {
|
|
96
|
+
console.log("Daemon command cancelled.");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const result = await executeDaemonPlan(plan, { dryRun, force });
|
|
102
|
+
if (json) console.log(JSON.stringify({ plan: result.plan, output: result.output }, null, 2));
|
|
103
|
+
else console.log(dryRun ? formatDaemonPlan(plan) : result.output);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function parseDaemonAction(value: string | undefined): DaemonAction {
|
|
107
|
+
if (!value || !DAEMON_ACTIONS.has(value as DaemonAction)) {
|
|
108
|
+
throw new Error("Usage: agent-relay daemon <install|uninstall|start|stop|restart|enable|disable|status|logs> [options]");
|
|
109
|
+
}
|
|
110
|
+
return value as DaemonAction;
|
|
111
|
+
}
|
package/src/cli/dev.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// Dev commands — auto-split from cli.ts (#294). Local pack/install/service/smoke
|
|
2
|
+
// harness for testing relay packages without an npm publish.
|
|
3
|
+
import {
|
|
4
|
+
createDevInstallPlan,
|
|
5
|
+
createDevPackPlan,
|
|
6
|
+
createDevServicePlan,
|
|
7
|
+
defaultDevRoot,
|
|
8
|
+
executeDevInstallPlan,
|
|
9
|
+
executeDevPackPlan,
|
|
10
|
+
executeDevServicePlan,
|
|
11
|
+
executeDevSmoke,
|
|
12
|
+
formatDevInstallPlan,
|
|
13
|
+
formatDevPackPlan,
|
|
14
|
+
formatDevServicePlan,
|
|
15
|
+
parseDevPackages,
|
|
16
|
+
type DevServiceAction,
|
|
17
|
+
} from "../dev";
|
|
18
|
+
import { confirm } from "./_shared";
|
|
19
|
+
|
|
20
|
+
export async function handleDevCommand(args: string[]): Promise<void> {
|
|
21
|
+
const action = args[0];
|
|
22
|
+
if (!action) throw new Error("Usage: agent-relay dev <pack|install|service|smoke> [options]");
|
|
23
|
+
if (action === "pack") {
|
|
24
|
+
let packages: string | undefined;
|
|
25
|
+
let outDir: string | undefined;
|
|
26
|
+
let dryRun = false;
|
|
27
|
+
let json = false;
|
|
28
|
+
for (let i = 1; i < args.length; i++) {
|
|
29
|
+
const arg = args[i];
|
|
30
|
+
if (arg === "--packages" && i + 1 < args.length) packages = args[++i];
|
|
31
|
+
else if (arg === "--out" && i + 1 < args.length) outDir = args[++i];
|
|
32
|
+
else if (arg === "--dry-run") dryRun = true;
|
|
33
|
+
else if (arg === "--json") json = true;
|
|
34
|
+
else throw new Error(`Unknown dev pack option "${arg}"`);
|
|
35
|
+
}
|
|
36
|
+
const plan = createDevPackPlan({
|
|
37
|
+
...(packages ? { packages: parseDevPackages(packages) } : {}),
|
|
38
|
+
...(outDir ? { outDir } : {}),
|
|
39
|
+
});
|
|
40
|
+
const result = await executeDevPackPlan(plan, { dryRun });
|
|
41
|
+
if (json) console.log(JSON.stringify(result, null, 2));
|
|
42
|
+
else console.log(dryRun ? formatDevPackPlan(plan) : result.output);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (action === "install") {
|
|
47
|
+
let packages: string | undefined;
|
|
48
|
+
let outDir: string | undefined;
|
|
49
|
+
let prefix: string | undefined;
|
|
50
|
+
let dryRun = false;
|
|
51
|
+
let json = false;
|
|
52
|
+
for (let i = 1; i < args.length; i++) {
|
|
53
|
+
const arg = args[i];
|
|
54
|
+
if (arg === "--packages" && i + 1 < args.length) packages = args[++i];
|
|
55
|
+
else if (arg === "--out" && i + 1 < args.length) outDir = args[++i];
|
|
56
|
+
else if (arg === "--prefix" && i + 1 < args.length) prefix = args[++i];
|
|
57
|
+
else if (arg === "--dry-run") dryRun = true;
|
|
58
|
+
else if (arg === "--json") json = true;
|
|
59
|
+
else throw new Error(`Unknown dev install option "${arg}"`);
|
|
60
|
+
}
|
|
61
|
+
const plan = createDevInstallPlan({
|
|
62
|
+
...(packages ? { packages: parseDevPackages(packages) } : {}),
|
|
63
|
+
...(outDir ? { outDir } : {}),
|
|
64
|
+
...(prefix ? { prefix } : {}),
|
|
65
|
+
});
|
|
66
|
+
const result = await executeDevInstallPlan(plan, { dryRun });
|
|
67
|
+
if (json) console.log(JSON.stringify(result, null, 2));
|
|
68
|
+
else console.log(dryRun ? formatDevInstallPlan(plan) : result.output);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (action === "service") {
|
|
73
|
+
await handleDevServiceCommand(args.slice(1));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (action === "smoke") {
|
|
78
|
+
let rootDir: string | undefined;
|
|
79
|
+
let providers: string | undefined;
|
|
80
|
+
let cwd: string | undefined;
|
|
81
|
+
let orchestratorId: string | undefined;
|
|
82
|
+
let timeoutMs: number | undefined;
|
|
83
|
+
for (let i = 1; i < args.length; i++) {
|
|
84
|
+
const arg = args[i];
|
|
85
|
+
if (arg === "--root" && i + 1 < args.length) rootDir = args[++i];
|
|
86
|
+
else if (arg === "--providers" && i + 1 < args.length) providers = args[++i];
|
|
87
|
+
else if (arg === "--cwd" && i + 1 < args.length) cwd = args[++i];
|
|
88
|
+
else if (arg === "--orchestrator" && i + 1 < args.length) orchestratorId = args[++i];
|
|
89
|
+
else if (arg === "--timeout" && i + 1 < args.length) timeoutMs = parseInt(args[++i]!, 10);
|
|
90
|
+
else throw new Error(`Unknown dev smoke option "${arg}"`);
|
|
91
|
+
}
|
|
92
|
+
const result = await executeDevSmoke({
|
|
93
|
+
...(rootDir ? { rootDir } : {}),
|
|
94
|
+
...(providers ? { providers } : {}),
|
|
95
|
+
...(cwd ? { cwd } : {}),
|
|
96
|
+
...(orchestratorId ? { orchestratorId } : {}),
|
|
97
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
98
|
+
});
|
|
99
|
+
console.log(result.output);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
throw new Error("Usage: agent-relay dev <pack|install|service|smoke> [options]");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function handleDevServiceCommand(args: string[]): Promise<void> {
|
|
107
|
+
const action = parseDevServiceAction(args[0]);
|
|
108
|
+
let prefix: string | undefined;
|
|
109
|
+
let rootDir: string | undefined;
|
|
110
|
+
let port: number | undefined;
|
|
111
|
+
let apiPort: number | undefined;
|
|
112
|
+
let baseDir: string | undefined;
|
|
113
|
+
let orchestratorId: string | undefined;
|
|
114
|
+
let token: string | undefined;
|
|
115
|
+
let start = false;
|
|
116
|
+
let enable = false;
|
|
117
|
+
let dryRun = false;
|
|
118
|
+
let force = false;
|
|
119
|
+
let yes = false;
|
|
120
|
+
let json = false;
|
|
121
|
+
|
|
122
|
+
for (let i = 1; i < args.length; i++) {
|
|
123
|
+
const arg = args[i];
|
|
124
|
+
if (arg === "--prefix" && i + 1 < args.length) prefix = args[++i];
|
|
125
|
+
else if (arg === "--root" && i + 1 < args.length) rootDir = args[++i];
|
|
126
|
+
else if (arg === "--port" && i + 1 < args.length) port = parseInt(args[++i]!, 10);
|
|
127
|
+
else if (arg === "--api-port" && i + 1 < args.length) apiPort = parseInt(args[++i]!, 10);
|
|
128
|
+
else if (arg === "--base-dir" && i + 1 < args.length) baseDir = args[++i];
|
|
129
|
+
else if (arg === "--orchestrator-id" && i + 1 < args.length) orchestratorId = args[++i];
|
|
130
|
+
else if (arg === "--token" && i + 1 < args.length) token = args[++i];
|
|
131
|
+
else if (arg === "--start") start = true;
|
|
132
|
+
else if (arg === "--enable") enable = true;
|
|
133
|
+
else if (arg === "--dry-run") dryRun = true;
|
|
134
|
+
else if (arg === "--force") force = true;
|
|
135
|
+
else if (arg === "--yes") yes = true;
|
|
136
|
+
else if (arg === "--json") json = true;
|
|
137
|
+
else throw new Error(`Unknown dev service option "${arg}"`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const root = rootDir ?? defaultDevRoot();
|
|
141
|
+
const plan = createDevServicePlan({
|
|
142
|
+
action,
|
|
143
|
+
...(prefix ? { prefix } : {}),
|
|
144
|
+
rootDir: root,
|
|
145
|
+
...(port !== undefined ? { port } : {}),
|
|
146
|
+
...(apiPort !== undefined ? { apiPort } : {}),
|
|
147
|
+
...(baseDir ? { baseDir } : {}),
|
|
148
|
+
...(orchestratorId ? { orchestratorId } : {}),
|
|
149
|
+
...(token ? { token } : {}),
|
|
150
|
+
start,
|
|
151
|
+
enable,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!dryRun && !json && (action === "install" || action === "uninstall") && !yes) {
|
|
155
|
+
const ok = await confirm(action === "install" ? `Install dev service profile under ${root}?` : `Uninstall dev service profile under ${root}?`);
|
|
156
|
+
if (!ok) {
|
|
157
|
+
console.log("Dev service command cancelled.");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const result = await executeDevServicePlan(plan, { dryRun, force });
|
|
163
|
+
if (json) console.log(JSON.stringify({ plan: result.plan, output: result.output }, null, 2));
|
|
164
|
+
else console.log(dryRun ? formatDevServicePlan(plan) : result.output);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function parseDevServiceAction(value: string | undefined): DevServiceAction {
|
|
168
|
+
const allowed = new Set<DevServiceAction>(["install", "uninstall", "start", "stop", "restart", "status", "logs"]);
|
|
169
|
+
if (!value || !allowed.has(value as DevServiceAction)) {
|
|
170
|
+
throw new Error("Usage: agent-relay dev service <install|uninstall|start|stop|restart|status|logs> [options]");
|
|
171
|
+
}
|
|
172
|
+
return value as DevServiceAction;
|
|
173
|
+
}
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
// CLI dispatcher — auto-split from cli.ts (#294). handleCli() is a thin switch
|
|
2
|
+
// over the per-domain command modules in this directory; the usage/guide strings
|
|
3
|
+
// live here too. Each command's logic lives in its own module (upgrade.ts,
|
|
4
|
+
// message.ts, workspace.ts, …). Re-exports WORKSPACE_USAGE and
|
|
5
|
+
// removeLegacyCodexSessionStartHookToml for the legacy "./cli" import surface.
|
|
6
|
+
import { VERSION } from "../config";
|
|
7
|
+
import { handleUpgradeCommand } from "./upgrade";
|
|
8
|
+
import { handleProviderCommand } from "./provider";
|
|
9
|
+
import { handleContextProbeCommand } from "./context-probe";
|
|
10
|
+
import { handleSetupCommand } from "./setup";
|
|
11
|
+
import { handleDaemonCommand } from "./daemon";
|
|
12
|
+
import { handleOrchestratorCommand } from "./orchestrator";
|
|
13
|
+
import { handleDevCommand } from "./dev";
|
|
14
|
+
import { handleMemoryCommand } from "./memory";
|
|
15
|
+
import { handleSlashOrPairCommand } from "./pair";
|
|
16
|
+
import { handleWorkspaceCommand } from "./workspace";
|
|
17
|
+
import { handleStewardCommand } from "./steward";
|
|
18
|
+
import { handleMessageCommand, handleGetMessageCommand, handleReactCommand } from "./message";
|
|
19
|
+
import { handleReplyCommand } from "./reply";
|
|
20
|
+
import { handleIntrospectCommand } from "./introspect";
|
|
21
|
+
import { handleStatusCommand, handleLabelCommand, handleTagsCommand } from "./agent-meta";
|
|
22
|
+
import { handleRecipeCommand } from "./recipe";
|
|
23
|
+
import { handleTokenCommand } from "./token";
|
|
24
|
+
|
|
25
|
+
export { WORKSPACE_USAGE } from "./workspace";
|
|
26
|
+
export { removeLegacyCodexSessionStartHookToml } from "./provider";
|
|
27
|
+
|
|
28
|
+
const HELP = `
|
|
29
|
+
agent-relay ${VERSION}
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
agent-relay [start]
|
|
33
|
+
agent-relay setup [--yes] [--dry-run] [--force] [--env-file PATH] [--runtime-prefix DIR] [--host HOST] [--port PORT] [--db-path PATH] [--token TOKEN|--no-token]
|
|
34
|
+
agent-relay upgrade [--dry-run] [--version VERSION] [--runtime-prefix DIR] [--providers auto|all|codex|claude|orchestrator] [--no-restart] [--yes]
|
|
35
|
+
agent-relay upgrade --host ID [--host ID2 ...] [--version VERSION] [--providers ...] (upgrade remote orchestrator hosts over the relay)
|
|
36
|
+
agent-relay upgrade --all-hosts [...] (upgrade this host, then every behind remote host)
|
|
37
|
+
agent-relay setup upgrade [same options as upgrade]
|
|
38
|
+
agent-relay daemon <install|uninstall|start|stop|restart|enable|disable|status|logs> [options]
|
|
39
|
+
agent-relay orchestrator install [options]
|
|
40
|
+
agent-relay dev <pack|install|service|smoke> [options]
|
|
41
|
+
agent-relay memory broker smoke [options]
|
|
42
|
+
agent-relay recipe <list|show|start|stop|status> [options]
|
|
43
|
+
agent-relay provider <wrap|unwrap> <claude|codex>
|
|
44
|
+
agent-relay context-probe [print-status-line] [--wrap COMMAND] [--agent-id ID] [--state-dir DIR] [--standalone]
|
|
45
|
+
agent-relay token <create|list|revoke|verify> [options]
|
|
46
|
+
agent-relay pair <target|create|status|accept|reject|hangup|send> [options]
|
|
47
|
+
agent-relay workspace <status|diagnostics|ready|land|claim|release|list|cleanup-stale|deps> [--id ID] [--strategy ...] [--purpose TEXT] [--repo PATH] [--wait] [--timeout SECONDS] [--check] [--execute] [--json]
|
|
48
|
+
agent-relay steward <queue|inspect|checks> [WORKSPACE_ID] [--repo PATH] [--json]
|
|
49
|
+
agent-relay message <target> <body> [options]
|
|
50
|
+
agent-relay get-message <messageId> [--json|--body]
|
|
51
|
+
agent-relay /pair <target|accept|reject|send|status> [...]
|
|
52
|
+
agent-relay /message <target> <body>
|
|
53
|
+
agent-relay /reply <messageId> <body|--stdin|--body-file PATH> [--format text|markdown|markdownv2]
|
|
54
|
+
agent-relay /react <messageId> <emoji> [--remove]
|
|
55
|
+
agent-relay /send-claimable <target> <body>
|
|
56
|
+
agent-relay /disconnect [PAIR_ID]
|
|
57
|
+
agent-relay /status
|
|
58
|
+
agent-relay /guide
|
|
59
|
+
agent-relay /label [LABEL]
|
|
60
|
+
agent-relay /tags [TAG ...]
|
|
61
|
+
agent-relay /introspect [--thin TEXT] [--worked-around TEXT] [--would-have-helped TEXT] [--stdin]
|
|
62
|
+
agent-relay --help
|
|
63
|
+
|
|
64
|
+
Pair examples:
|
|
65
|
+
agent-relay pair codex --objective "Debug flaky tests"
|
|
66
|
+
agent-relay /pair codex "Debug flaky tests"
|
|
67
|
+
agent-relay pair status
|
|
68
|
+
agent-relay pair accept PAIR_ID --agent AGENT_ID
|
|
69
|
+
agent-relay pair send PAIR_ID --from AGENT_ID --body "What do you see?"
|
|
70
|
+
agent-relay /message codex "Can you look at that failing action?"
|
|
71
|
+
agent-relay /reply 206 "Sounds good, I'll take a look"
|
|
72
|
+
agent-relay /react 206 👍
|
|
73
|
+
agent-relay /reply 206 --stdin < result.md
|
|
74
|
+
agent-relay get-message 206 --json
|
|
75
|
+
agent-relay /reply 206 --format markdown "Here is **formatted** text"
|
|
76
|
+
agent-relay /send-claimable tag:backend "Please claim and fix the failing API test"
|
|
77
|
+
agent-relay /disconnect
|
|
78
|
+
agent-relay /status
|
|
79
|
+
agent-relay /guide
|
|
80
|
+
agent-relay /label backend-fixer
|
|
81
|
+
agent-relay /tags backend tests urgent
|
|
82
|
+
|
|
83
|
+
Daemon options:
|
|
84
|
+
--env-file PATH Env file sourced by the daemon (default: platform user config dir)
|
|
85
|
+
--runtime-prefix DIR Isolated Agent Relay npm prefix (default: ~/.agent-relay/runtime)
|
|
86
|
+
--binary PATH Stable agent-relay binary/script path for the service
|
|
87
|
+
--path-prefix DIR Prepend a directory to daemon PATH; repeatable
|
|
88
|
+
--name NAME Service name (default: agent-relay)
|
|
89
|
+
--host HOST Display/listen host for generated plan (default: 127.0.0.1)
|
|
90
|
+
--port PORT Display/listen port for generated plan (default: 4850)
|
|
91
|
+
--user|--system User service by default, system service when explicitly requested
|
|
92
|
+
--enable Enable service at login/boot during install
|
|
93
|
+
--start Start service after install
|
|
94
|
+
--dry-run Print the plan without writing files or running service commands
|
|
95
|
+
--yes Skip confirmation prompts
|
|
96
|
+
--force Overwrite/remove managed-file guardrails
|
|
97
|
+
--json Print structured output
|
|
98
|
+
|
|
99
|
+
Orchestrator install options:
|
|
100
|
+
--relay-url URL Agent Relay server URL reachable from this host
|
|
101
|
+
--token TOKEN Scoped runtime orchestrator token
|
|
102
|
+
--bootstrap-token TOKEN Short-lived dashboard bootstrap token to exchange during install
|
|
103
|
+
--id ID Orchestrator id (default: sanitized hostname)
|
|
104
|
+
--base-dir PATH Base directory for agent working directories (default: ~/projects)
|
|
105
|
+
--providers LIST Providers to probe/enable (default: claude,codex)
|
|
106
|
+
--api-port PORT Orchestrator local API port (default: 4860)
|
|
107
|
+
--runtime-prefix DIR Isolated npm prefix (default: ~/.agent-relay/runtime)
|
|
108
|
+
--path-prefix DIR Prepend a directory to daemon PATH; repeatable
|
|
109
|
+
--version VERSION Package version to install (default: this CLI version)
|
|
110
|
+
--dry-run Print the plan without writing files, installing, or starting
|
|
111
|
+
--yes Skip confirmation prompts
|
|
112
|
+
|
|
113
|
+
Upgrade options:
|
|
114
|
+
--version VERSION Target version (default: latest published server version)
|
|
115
|
+
--runtime-prefix DIR Isolated Agent Relay npm prefix (default: ~/.agent-relay/runtime)
|
|
116
|
+
--providers LIST Provider integrations to upgrade: auto, all, codex, claude, orchestrator
|
|
117
|
+
--host ID Upgrade a remote orchestrator host over the relay (repeatable). Skips the local upgrade
|
|
118
|
+
--all-hosts Upgrade this host, then fan out to every connected remote host that is behind
|
|
119
|
+
--no-restart Do not restart agent-relay.service (warns you to restart it manually)
|
|
120
|
+
--restart-deferred Like --no-restart, but the caller restarts the services itself; suppresses the manual-restart warning (used by the release script)
|
|
121
|
+
--dry-run Print detected state and planned commands
|
|
122
|
+
--yes Skip confirmation prompts
|
|
123
|
+
|
|
124
|
+
Dev options:
|
|
125
|
+
agent-relay dev pack [--packages LIST] [--out DIR]
|
|
126
|
+
agent-relay dev install [--packages LIST] [--prefix DIR] [--out DIR] [--dry-run] [--json]
|
|
127
|
+
agent-relay dev service <install|uninstall|start|stop|restart|status|logs> [--prefix DIR] [--root DIR] [--port PORT] [--api-port PORT] [--base-dir DIR] [--enable] [--start] [--dry-run] [--yes] [--force] [--json]
|
|
128
|
+
agent-relay dev smoke [--root DIR] [--providers LIST] [--cwd DIR] [--timeout MS]
|
|
129
|
+
|
|
130
|
+
Memory options:
|
|
131
|
+
agent-relay memory broker smoke [--relay-url URL] [--token TOKEN] [--agent-id ID] [--scope SCOPE] [--tag TAG] [--no-cleanup] [--json]
|
|
132
|
+
|
|
133
|
+
Recipe examples:
|
|
134
|
+
agent-relay recipe list
|
|
135
|
+
agent-relay recipe start code-review --cwd /repo --orchestrator local
|
|
136
|
+
agent-relay recipe status
|
|
137
|
+
agent-relay recipe stop INSTANCE_ID
|
|
138
|
+
|
|
139
|
+
Token examples:
|
|
140
|
+
agent-relay token create --role orchestrator --sub macmini --ttl 86400
|
|
141
|
+
agent-relay token list
|
|
142
|
+
agent-relay token revoke JTI
|
|
143
|
+
|
|
144
|
+
Context probe examples:
|
|
145
|
+
agent-relay context-probe print-status-line --wrap 'ccstatusline'
|
|
146
|
+
agent-relay context-probe --wrap 'ccstatusline'
|
|
147
|
+
agent-relay context-probe --standalone
|
|
148
|
+
`.trim();
|
|
149
|
+
|
|
150
|
+
const AGENT_GUIDE = `
|
|
151
|
+
Agent Relay guide for coding agents
|
|
152
|
+
|
|
153
|
+
Agent Relay is a message bus between local or managed agents. Use the
|
|
154
|
+
agent-relay CLI for relay communication.
|
|
155
|
+
|
|
156
|
+
Current session
|
|
157
|
+
agent-relay /status --json
|
|
158
|
+
Shows your relay agent id, label, tags, health, and active pair state.
|
|
159
|
+
|
|
160
|
+
Replying
|
|
161
|
+
agent-relay /reply <messageId> "<response>"
|
|
162
|
+
agent-relay /reply <messageId> --stdin < response.md
|
|
163
|
+
agent-relay /reply <messageId> --body-file response.md
|
|
164
|
+
Reply to the sender of a relay message. Prefer this over /message when
|
|
165
|
+
handling an incoming relay message because the server keeps the routing
|
|
166
|
+
and channel context. Large replies are uploaded as an artifact
|
|
167
|
+
automatically and sent as a concise attached reply.
|
|
168
|
+
|
|
169
|
+
Reactions
|
|
170
|
+
agent-relay /react <messageId> <emoji>
|
|
171
|
+
agent-relay /react <messageId> <emoji> --remove
|
|
172
|
+
Use reactions for lightweight acknowledgement, approval, thanks, or
|
|
173
|
+
"good job" when no text response is needed. Do not use reactions when the
|
|
174
|
+
sender asked a question, gave a new task, or needs a result in text.
|
|
175
|
+
|
|
176
|
+
Reading full messages
|
|
177
|
+
agent-relay get-message <messageId>
|
|
178
|
+
agent-relay read-message <messageId> --json
|
|
179
|
+
agent-relay get-message <messageId> --body
|
|
180
|
+
Fetch the full message body, attachments, metadata, and thread context.
|
|
181
|
+
|
|
182
|
+
Sending messages
|
|
183
|
+
agent-relay /message <target> "<message>"
|
|
184
|
+
Send a direct one-off relay message.
|
|
185
|
+
|
|
186
|
+
agent-relay /send-claimable <target> "<work item>"
|
|
187
|
+
Queue work that one matching agent can claim and handle.
|
|
188
|
+
|
|
189
|
+
Targets
|
|
190
|
+
<agent-id> A specific live agent id.
|
|
191
|
+
<label> A registered agent label.
|
|
192
|
+
tag:<tag> Any agent with that tag.
|
|
193
|
+
cap:<capability> Any agent with that capability.
|
|
194
|
+
policy:<name> A managed policy target that can survive restarts.
|
|
195
|
+
broadcast All reachable agents.
|
|
196
|
+
|
|
197
|
+
Pair sessions
|
|
198
|
+
agent-relay /pair <target> "<objective>"
|
|
199
|
+
agent-relay /pair status
|
|
200
|
+
agent-relay /pair accept <pairId>
|
|
201
|
+
agent-relay /pair reject <pairId>
|
|
202
|
+
agent-relay /pair send <pairId> "<message>"
|
|
203
|
+
agent-relay /disconnect [pairId]
|
|
204
|
+
|
|
205
|
+
Labels and tags
|
|
206
|
+
agent-relay /label [LABEL]
|
|
207
|
+
agent-relay /tags [TAG ...]
|
|
208
|
+
|
|
209
|
+
Isolated workspaces
|
|
210
|
+
If you are working in an isolated workspace (a git worktree on an agent
|
|
211
|
+
branch, not the main checkout), you do NOT rebase, merge, or push yourself —
|
|
212
|
+
Relay does. Just commit your work in the worktree, then:
|
|
213
|
+
agent-relay workspace ready Hand off: Relay rebases onto the latest base,
|
|
214
|
+
lands your work, and pushes.
|
|
215
|
+
agent-relay workspace status Show your workspace's state + what to do next.
|
|
216
|
+
agent-relay workspace status --wait
|
|
217
|
+
Block until your branch lands (returns the
|
|
218
|
+
moment the auto-merge completes).
|
|
219
|
+
After "ready", status is "review_requested" — this is NORMAL, not an
|
|
220
|
+
escalation. Relay auto-merges clean rebases ~every 2 min; a steward agent is
|
|
221
|
+
spawned only if it can't land deterministically, so no steward = healthy. On
|
|
222
|
+
landing you move onto a fresh rebased branch (name gains a "--N" suffix).
|
|
223
|
+
The base branch will move as other agents land in parallel — that is normal,
|
|
224
|
+
let the merge handle it. Never push, merge, resolve conflicts, or touch the
|
|
225
|
+
main checkout yourself; it is local-only and Relay (and the steward) own that.
|
|
226
|
+
If typecheck/build fails on a missing module (a dep added to the base after
|
|
227
|
+
your worktree was created), do NOT run a clean install — it mutates the shared
|
|
228
|
+
node_modules. Instead refresh your worktree's deps in isolation:
|
|
229
|
+
agent-relay workspace deps Re-provision deps that have gone stale.
|
|
230
|
+
agent-relay workspace deps --check Report staleness without installing.
|
|
231
|
+
|
|
232
|
+
Rules of thumb
|
|
233
|
+
If you are handling relay message #123, reply with:
|
|
234
|
+
agent-relay /reply 123 "<response>"
|
|
235
|
+
|
|
236
|
+
If the delivered preview says it was truncated, fetch the full message with:
|
|
237
|
+
agent-relay get-message 123
|
|
238
|
+
|
|
239
|
+
If your reply is long, avoid shell quoting and use:
|
|
240
|
+
agent-relay /reply 123 --stdin < response.md
|
|
241
|
+
|
|
242
|
+
If you need to know who you are in Relay, run:
|
|
243
|
+
agent-relay /status --json
|
|
244
|
+
|
|
245
|
+
Recording session friction (optional, helps improve your standing context)
|
|
246
|
+
agent-relay /introspect --thin "..." --worked-around "..." --would-have-helped "..."
|
|
247
|
+
When a session involved real work, you can record a short 3-field note about
|
|
248
|
+
where context was thin, what tooling/instruction gaps you routed around, and
|
|
249
|
+
what would have saved the read-up. Keep each field to a sentence or two. This
|
|
250
|
+
feeds the relay's self-improvement signal so the operator can close the gaps —
|
|
251
|
+
it is not a reply and needs no message id. Skip it for trivial sessions.
|
|
252
|
+
|
|
253
|
+
Use the HTTP API for integrations and debugging. For normal agent-to-agent
|
|
254
|
+
communication, use the CLI commands above.
|
|
255
|
+
`.trim();
|
|
256
|
+
|
|
257
|
+
export async function handleCli(args: string[]): Promise<"start" | "handled"> {
|
|
258
|
+
const command = args[0];
|
|
259
|
+
if (!command || command === "start") return "start";
|
|
260
|
+
if (command === "--help" || command === "-h" || command === "help") {
|
|
261
|
+
console.log(HELP);
|
|
262
|
+
return "handled";
|
|
263
|
+
}
|
|
264
|
+
if (command === "--version" || command === "-v") {
|
|
265
|
+
console.log(VERSION);
|
|
266
|
+
return "handled";
|
|
267
|
+
}
|
|
268
|
+
if (command === "guide" || command === "/guide" || command === "agent-guide" || command === "/agent-guide") {
|
|
269
|
+
console.log(AGENT_GUIDE);
|
|
270
|
+
return "handled";
|
|
271
|
+
}
|
|
272
|
+
if (command === "upgrade" || (command === "setup" && args[1] === "upgrade")) {
|
|
273
|
+
await handleUpgradeCommand(command === "setup" ? args.slice(2) : args.slice(1));
|
|
274
|
+
return "handled";
|
|
275
|
+
}
|
|
276
|
+
if (command === "setup" || command === "init") {
|
|
277
|
+
await handleSetupCommand(args.slice(1));
|
|
278
|
+
return "handled";
|
|
279
|
+
}
|
|
280
|
+
if (command === "daemon") {
|
|
281
|
+
await handleDaemonCommand(args.slice(1));
|
|
282
|
+
return "handled";
|
|
283
|
+
}
|
|
284
|
+
if (command === "orchestrator" || command === "orchestrators") {
|
|
285
|
+
await handleOrchestratorCommand(args.slice(1));
|
|
286
|
+
return "handled";
|
|
287
|
+
}
|
|
288
|
+
if (command === "dev") {
|
|
289
|
+
await handleDevCommand(args.slice(1));
|
|
290
|
+
return "handled";
|
|
291
|
+
}
|
|
292
|
+
if (command === "memory") {
|
|
293
|
+
await handleMemoryCommand(args.slice(1));
|
|
294
|
+
return "handled";
|
|
295
|
+
}
|
|
296
|
+
if (command === "recipe" || command === "recipes") {
|
|
297
|
+
await handleRecipeCommand(args.slice(1));
|
|
298
|
+
return "handled";
|
|
299
|
+
}
|
|
300
|
+
if (command === "provider" || command === "providers") {
|
|
301
|
+
await handleProviderCommand(args.slice(1));
|
|
302
|
+
return "handled";
|
|
303
|
+
}
|
|
304
|
+
if (command === "context-probe") {
|
|
305
|
+
await handleContextProbeCommand(args.slice(1));
|
|
306
|
+
return "handled";
|
|
307
|
+
}
|
|
308
|
+
if (command === "token" || command === "tokens") {
|
|
309
|
+
await handleTokenCommand(args.slice(1));
|
|
310
|
+
return "handled";
|
|
311
|
+
}
|
|
312
|
+
if (command === "pair" || command === "/pair" || command === "/disconnect") {
|
|
313
|
+
await handleSlashOrPairCommand(command, args.slice(1));
|
|
314
|
+
return "handled";
|
|
315
|
+
}
|
|
316
|
+
if (command === "message" || command === "send" || command === "/message" || command === "/send" || command === "/send-claimable") {
|
|
317
|
+
await handleMessageCommand(args.slice(1), { claimable: command === "/send-claimable" });
|
|
318
|
+
return "handled";
|
|
319
|
+
}
|
|
320
|
+
if (command === "get-message" || command === "read-message" || command === "/get-message" || command === "/read-message") {
|
|
321
|
+
await handleGetMessageCommand(args.slice(1));
|
|
322
|
+
return "handled";
|
|
323
|
+
}
|
|
324
|
+
if (command === "reply" || command === "/reply") {
|
|
325
|
+
await handleReplyCommand(args.slice(1));
|
|
326
|
+
return "handled";
|
|
327
|
+
}
|
|
328
|
+
if (command === "react" || command === "/react" || command === "reaction" || command === "/reaction") {
|
|
329
|
+
await handleReactCommand(args.slice(1));
|
|
330
|
+
return "handled";
|
|
331
|
+
}
|
|
332
|
+
if (command === "introspect" || command === "/introspect") {
|
|
333
|
+
await handleIntrospectCommand(args.slice(1));
|
|
334
|
+
return "handled";
|
|
335
|
+
}
|
|
336
|
+
if (command === "/status" || command === "status") {
|
|
337
|
+
await handleStatusCommand(args.slice(1));
|
|
338
|
+
return "handled";
|
|
339
|
+
}
|
|
340
|
+
if (command === "/label" || command === "label") {
|
|
341
|
+
await handleLabelCommand(args.slice(1));
|
|
342
|
+
return "handled";
|
|
343
|
+
}
|
|
344
|
+
if (command === "/tags" || command === "tags") {
|
|
345
|
+
await handleTagsCommand(args.slice(1));
|
|
346
|
+
return "handled";
|
|
347
|
+
}
|
|
348
|
+
if (command === "workspace" || command === "workspaces") {
|
|
349
|
+
await handleWorkspaceCommand(args.slice(1));
|
|
350
|
+
return "handled";
|
|
351
|
+
}
|
|
352
|
+
if (command === "steward" || command === "stewards") {
|
|
353
|
+
await handleStewardCommand(args.slice(1));
|
|
354
|
+
return "handled";
|
|
355
|
+
}
|
|
356
|
+
if (command === "/reconnect") {
|
|
357
|
+
console.log("Reconnect is handled automatically by provider runners; use `agent-relay pair status` to inspect current pair state.");
|
|
358
|
+
return "handled";
|
|
359
|
+
}
|
|
360
|
+
throw new Error(`Unknown command "${command}". Run agent-relay --help.`);
|
|
361
|
+
}
|