agent-relay-runner 0.10.5 → 0.10.7
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/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/disconnect/SKILL.md +16 -0
- package/plugins/claude/skills/label/SKILL.md +23 -0
- package/plugins/claude/skills/message/SKILL.md +24 -0
- package/plugins/claude/skills/pair/SKILL.md +26 -0
- package/plugins/claude/skills/reply/SKILL.md +25 -0
- package/plugins/claude/skills/send-claimable/SKILL.md +24 -0
- package/plugins/claude/skills/status/SKILL.md +16 -0
- package/plugins/claude/skills/tags/SKILL.md +25 -0
- package/src/adapter.ts +1 -0
- package/src/adapters/claude.ts +3 -0
- package/src/config.ts +1 -1
- package/src/index.ts +32 -4
- package/src/runner.ts +7 -1
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: disconnect
|
|
3
|
+
description: End the current Agent Relay pair session. Use when the user invokes /disconnect or asks to hang up, unpair, or disconnect from a paired agent.
|
|
4
|
+
argument-hint: "[PAIR_ID]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Disconnect
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /disconnect $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If no pair id is supplied, the CLI ends the active pair for this session. Report the result briefly.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: label
|
|
3
|
+
description: Read, set, or clear the current Agent Relay agent label. Use when the user invokes /label or asks to rename this relay agent.
|
|
4
|
+
argument-hint: "[LABEL|--clear]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Label
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /label $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-relay /label backend-fixer
|
|
20
|
+
agent-relay /label --clear
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Report the new label or current label briefly.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: message
|
|
3
|
+
description: Send a normal Agent Relay message to another agent, label, tag, capability, or broadcast target. Use when the user invokes /message or asks to send a one-off relay message.
|
|
4
|
+
argument-hint: "<target> <message> [--subject TEXT] [--channel NAME]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Message
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /message $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-relay /message codex "Can you look at that failing action?"
|
|
20
|
+
agent-relay /message tag:backend "Does anyone see the regression?"
|
|
21
|
+
agent-relay /message broadcast "Standup in five minutes"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Report the sent message id briefly.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pair
|
|
3
|
+
description: Start, inspect, accept, reject, or send messages in an Agent Relay two-agent pair session. Use when the user invokes /pair or asks to pair this agent with Codex, Claude, or another relay agent.
|
|
4
|
+
argument-hint: "<target|status|accept|reject|send> [args]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Pair
|
|
9
|
+
|
|
10
|
+
Run the Agent Relay CLI with the user's arguments:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /pair $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Use this for pair-session commands such as:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-relay /pair codex "Debug flaky tests"
|
|
20
|
+
agent-relay /pair status
|
|
21
|
+
agent-relay /pair accept PAIR_ID
|
|
22
|
+
agent-relay /pair reject PAIR_ID
|
|
23
|
+
agent-relay /pair send PAIR_ID "What do you see?"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Report the command output briefly. If the CLI cannot detect this session's agent id, rerun with `--agent AGENT_ID` or `--from AGENT_ID` using the Agent Relay ID shown in session context.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reply
|
|
3
|
+
description: Reply to an Agent Relay message by ID. Auto-routes to the sender and inherits channel context — no target needed. Use when the user invokes /reply or asks to reply to a specific relay message.
|
|
4
|
+
argument-hint: "<messageId> <message>"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Reply
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /reply $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The server auto-routes the reply to the original sender and inherits the channel (Telegram, Slack, etc.) if applicable. No target or channel ID needed.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
agent-relay /reply 206 "Sounds good, I'll take a look"
|
|
22
|
+
agent-relay /reply 42 "Done — the fix is in commit abc123"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Report the sent message id and resolved target briefly.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: send-claimable
|
|
3
|
+
description: Send a claimable Agent Relay work item so one matching agent can claim and handle it. Use when the user invokes /send-claimable or wants to enqueue work for another agent.
|
|
4
|
+
argument-hint: "<target> <message> [--subject TEXT] [--channel NAME]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Send Claimable
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /send-claimable $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-relay /send-claimable codex "Claim this and inspect the failing action"
|
|
20
|
+
agent-relay /send-claimable tag:backend "Fix the failing API test"
|
|
21
|
+
agent-relay /send-claimable cap:review "Review the migration patch"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Report the sent claimable message id briefly.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: status
|
|
3
|
+
description: Show Agent Relay status for this session, including relay health, current agent id, label, tags, readiness, and active pair state. Use when the user invokes /status or asks for relay connection status.
|
|
4
|
+
argument-hint: "[--json]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Status
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /status $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Summarize the current relay connection, agent identity, label, tags, and active pair state.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tags
|
|
3
|
+
description: List or update Agent Relay tags for the current session. Use when the user invokes /tags or asks to set, add, remove, or inspect relay tags.
|
|
4
|
+
argument-hint: "[TAG ...|--list|--add TAGS|--remove TAGS]"
|
|
5
|
+
allowed-tools: [Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Relay Tags
|
|
9
|
+
|
|
10
|
+
Run:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
agent-relay /tags $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-relay /tags
|
|
20
|
+
agent-relay /tags backend tests urgent
|
|
21
|
+
agent-relay /tags --add backend,tests
|
|
22
|
+
agent-relay /tags --remove urgent
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Report the resulting tags briefly.
|
package/src/adapter.ts
CHANGED
package/src/adapters/claude.ts
CHANGED
|
@@ -36,7 +36,10 @@ export class ClaudeAdapter implements ProviderAdapter {
|
|
|
36
36
|
buildSpawnArgs(config: RunnerSpawnConfig, providerConfig: ProviderConfig): SpawnArgs {
|
|
37
37
|
const pluginRoot = resolve(import.meta.dir, "../../plugins/claude");
|
|
38
38
|
const pluginDirs = [...new Set([pluginRoot, ...providerConfig.pluginDirs])];
|
|
39
|
+
const isClaudeRig = /claude-rig/.test(providerConfig.command);
|
|
40
|
+
const rigPrefix = isClaudeRig && config.rig ? ["launch", config.rig] : [];
|
|
39
41
|
const args = [
|
|
42
|
+
...rigPrefix,
|
|
40
43
|
...pluginDirs.flatMap((dir) => ["--plugin-dir", dir]),
|
|
41
44
|
...providerConfig.defaultArgs,
|
|
42
45
|
...config.providerArgs,
|
package/src/config.ts
CHANGED
|
@@ -24,7 +24,7 @@ function providersDir(home = agentRelayHome()): string {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function defaultProviderConfig(provider: string): ProviderConfig {
|
|
27
|
-
const command = provider === "claude" ? "claude
|
|
27
|
+
const command = provider === "claude" ? "claude" : provider;
|
|
28
28
|
return {
|
|
29
29
|
command,
|
|
30
30
|
defaultArgs: provider === "claude" ? ["--dangerously-skip-permissions"] : [],
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { basename } from "node:path";
|
|
3
|
+
import { isatty } from "node:tty";
|
|
3
4
|
import { ClaudeAdapter } from "./adapters/claude";
|
|
4
5
|
import { CodexAdapter } from "./adapters/codex";
|
|
5
6
|
import { AgentRunner } from "./runner";
|
|
@@ -8,7 +9,9 @@ import { loadGlobalConfig, loadProviderConfig, resolveCwd, runnerId } from "./co
|
|
|
8
9
|
interface CliOptions {
|
|
9
10
|
provider: "claude" | "codex";
|
|
10
11
|
headless: boolean;
|
|
12
|
+
interactive: boolean;
|
|
11
13
|
cwd?: string;
|
|
14
|
+
rig?: string;
|
|
12
15
|
relayUrl?: string;
|
|
13
16
|
token?: string;
|
|
14
17
|
approvalMode?: string;
|
|
@@ -25,6 +28,12 @@ export async function main(argv = process.argv): Promise<void> {
|
|
|
25
28
|
const cwd = resolveCwd(opts.cwd, globalConfig.defaultCwd);
|
|
26
29
|
const id = runnerId(opts.provider, cwd, opts.label);
|
|
27
30
|
const adapter = opts.provider === "claude" ? new ClaudeAdapter() : new CodexAdapter();
|
|
31
|
+
|
|
32
|
+
let exitResolve: ((code: number) => void) | undefined;
|
|
33
|
+
const exitPromise = opts.interactive
|
|
34
|
+
? new Promise<number>((resolve) => { exitResolve = resolve; })
|
|
35
|
+
: undefined;
|
|
36
|
+
|
|
28
37
|
const runner = new AgentRunner({
|
|
29
38
|
provider: opts.provider,
|
|
30
39
|
runnerId: id,
|
|
@@ -36,17 +45,26 @@ export async function main(argv = process.argv): Promise<void> {
|
|
|
36
45
|
headless: opts.headless,
|
|
37
46
|
approvalMode: opts.approvalMode ?? providerConfig.defaultApprovalMode,
|
|
38
47
|
label: opts.label,
|
|
48
|
+
rig: opts.rig,
|
|
39
49
|
prompt: opts.prompt,
|
|
40
50
|
providerArgs: opts.providerArgs,
|
|
41
51
|
providerConfig,
|
|
42
52
|
adapter,
|
|
53
|
+
onProviderExit: exitResolve ? (code) => exitResolve!(code ?? 1) : undefined,
|
|
43
54
|
});
|
|
44
55
|
await runner.run();
|
|
45
|
-
|
|
56
|
+
|
|
57
|
+
if (opts.interactive && exitPromise) {
|
|
58
|
+
const code = await Promise.race([exitPromise, signalPromise()]);
|
|
59
|
+
await runner.stop();
|
|
60
|
+
process.exit(code);
|
|
61
|
+
} else {
|
|
62
|
+
await waitForShutdown(() => runner.stop());
|
|
63
|
+
}
|
|
46
64
|
}
|
|
47
65
|
|
|
48
66
|
function parseArgs(argv: string[]): CliOptions {
|
|
49
|
-
const bin =
|
|
67
|
+
const bin = [argv[1], process.env._].map((s) => basename(s || "")).join(" ");
|
|
50
68
|
let provider: "claude" | "codex" = bin.includes("claude") ? "claude" : "codex";
|
|
51
69
|
const relayArgs = argv.slice(2);
|
|
52
70
|
const providerSep = relayArgs.indexOf("--");
|
|
@@ -54,6 +72,7 @@ function parseArgs(argv: string[]): CliOptions {
|
|
|
54
72
|
const providerArgs = providerSep >= 0 ? relayArgs.slice(providerSep + 1) : [];
|
|
55
73
|
let headless = false;
|
|
56
74
|
let cwd: string | undefined;
|
|
75
|
+
let rig: string | undefined;
|
|
57
76
|
let relayUrl: string | undefined;
|
|
58
77
|
let token: string | undefined;
|
|
59
78
|
let approvalMode: string | undefined;
|
|
@@ -66,6 +85,7 @@ function parseArgs(argv: string[]): CliOptions {
|
|
|
66
85
|
if (arg === "claude" || arg === "codex") provider = arg;
|
|
67
86
|
else if (arg === "--headless") headless = true;
|
|
68
87
|
else if (arg === "--cwd" && ownArgs[i + 1]) cwd = ownArgs[++i];
|
|
88
|
+
else if (arg === "--rig" && ownArgs[i + 1]) rig = ownArgs[++i];
|
|
69
89
|
else if (arg === "--relay-url" && ownArgs[i + 1]) relayUrl = ownArgs[++i];
|
|
70
90
|
else if (arg === "--token" && ownArgs[i + 1]) token = ownArgs[++i];
|
|
71
91
|
else if ((arg === "--approval" || arg === "--approval-mode") && ownArgs[i + 1]) approvalMode = ownArgs[++i];
|
|
@@ -80,11 +100,19 @@ function parseArgs(argv: string[]): CliOptions {
|
|
|
80
100
|
}
|
|
81
101
|
}
|
|
82
102
|
|
|
83
|
-
|
|
103
|
+
const interactive = !headless && isatty(0);
|
|
104
|
+
return { provider, headless, interactive, cwd, rig, relayUrl, token, approvalMode, label, agentId, prompt, providerArgs };
|
|
84
105
|
}
|
|
85
106
|
|
|
86
107
|
function printHelp(provider: string): void {
|
|
87
|
-
console.log(`${provider}-relay [--headless] [--cwd PATH] [--relay-url URL] [--approval MODE] [--label NAME] [--agent-id ID] [-- provider-args...]`);
|
|
108
|
+
console.log(`${provider}-relay [--headless] [--rig NAME] [--cwd PATH] [--relay-url URL] [--approval MODE] [--label NAME] [--agent-id ID] [-- provider-args...]`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function signalPromise(): Promise<number> {
|
|
112
|
+
return new Promise<number>((resolve) => {
|
|
113
|
+
process.on("SIGINT", () => resolve(130));
|
|
114
|
+
process.on("SIGTERM", () => resolve(143));
|
|
115
|
+
});
|
|
88
116
|
}
|
|
89
117
|
|
|
90
118
|
async function waitForShutdown(stop: () => Promise<void>): Promise<void> {
|
package/src/runner.ts
CHANGED
|
@@ -16,10 +16,12 @@ interface RunnerOptions {
|
|
|
16
16
|
headless: boolean;
|
|
17
17
|
approvalMode: string;
|
|
18
18
|
label?: string;
|
|
19
|
+
rig?: string;
|
|
19
20
|
prompt?: string;
|
|
20
21
|
providerArgs: string[];
|
|
21
22
|
providerConfig: ProviderConfig;
|
|
22
23
|
adapter: ProviderAdapter;
|
|
24
|
+
onProviderExit?: (code: number | null) => void;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export class AgentRunner {
|
|
@@ -77,7 +79,10 @@ export class AgentRunner {
|
|
|
77
79
|
|
|
78
80
|
async run(): Promise<void> {
|
|
79
81
|
this.control = startControlServer({ onStatus: (status) => this.setProviderStatus(status) });
|
|
80
|
-
this.options.adapter.onStatusChange((status) =>
|
|
82
|
+
this.options.adapter.onStatusChange((status) => {
|
|
83
|
+
this.setProviderStatus(status);
|
|
84
|
+
if (status === "offline" || status === "error") this.options.onProviderExit?.(status === "offline" ? 0 : 1);
|
|
85
|
+
});
|
|
81
86
|
this.bus.on("message.new", (message) => this.enqueueMessage(message as Message));
|
|
82
87
|
this.bus.on("command", (type, params, commandId, command) => {
|
|
83
88
|
void this.handleCommand(type, params, commandId, command);
|
|
@@ -123,6 +128,7 @@ export class AgentRunner {
|
|
|
123
128
|
headless: this.options.headless,
|
|
124
129
|
approvalMode: this.options.approvalMode,
|
|
125
130
|
...(this.options.label ? { label: this.options.label } : {}),
|
|
131
|
+
...(this.options.rig ? { rig: this.options.rig } : {}),
|
|
126
132
|
...(this.options.prompt ? { prompt: this.options.prompt } : {}),
|
|
127
133
|
providerArgs: this.options.providerArgs,
|
|
128
134
|
providerConfig: this.options.providerConfig,
|