agent-relay-codex 0.4.28 → 0.4.33

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/README.md CHANGED
@@ -80,6 +80,7 @@ Run with `AGENT_RELAY_PROFILE=frontend-developer agent-relay-codex start`.
80
80
  | `CODEX_THREAD_ID` | — | Pin to a specific thread |
81
81
  | `CODEX_APP_SERVER_URL` | `ws://127.0.0.1:4501` | App-server WebSocket URL |
82
82
  | `AGENT_RELAY_CODEX_HEADLESS` | — | Set to `1` to run without opening a TUI |
83
+ | `AGENT_RELAY_DISABLED` | — | Set to `1` to bypass Agent Relay hooks and launcher shims |
83
84
 
84
85
  ### Advanced tuning
85
86
 
@@ -259,6 +259,75 @@ function findCodexBinary(): string {
259
259
  return codex;
260
260
  }
261
261
 
262
+ function isRelayDisabled(env: Record<string, string | undefined> = process.env): boolean {
263
+ return env.AGENT_RELAY_DISABLED === "1";
264
+ }
265
+
266
+ const relayBypassSubcommands = new Set([
267
+ "a",
268
+ "app-server",
269
+ "apply",
270
+ "cloud",
271
+ "completion",
272
+ "debug",
273
+ "e",
274
+ "exec",
275
+ "exec-server",
276
+ "features",
277
+ "login",
278
+ "logout",
279
+ "mcp",
280
+ "mcp-server",
281
+ "plugin",
282
+ "remote-control",
283
+ "review",
284
+ "sandbox",
285
+ "update",
286
+ ]);
287
+
288
+ function codexSubcommand(args: string[]): string {
289
+ const optionsWithValues = new Set([
290
+ "-c",
291
+ "--config",
292
+ "-m",
293
+ "--model",
294
+ "-p",
295
+ "--profile",
296
+ "-s",
297
+ "--sandbox",
298
+ "-C",
299
+ "--cd",
300
+ "--add-dir",
301
+ ]);
302
+
303
+ for (let index = 0; index < args.length; index += 1) {
304
+ const arg = args[index]!;
305
+ if (arg === "--") return "";
306
+ if (optionsWithValues.has(arg)) {
307
+ index += 1;
308
+ continue;
309
+ }
310
+ if (arg.startsWith("-")) continue;
311
+ return arg;
312
+ }
313
+
314
+ return "";
315
+ }
316
+
317
+ export function shouldBypassRelay(args: string[], env: Record<string, string | undefined> = process.env): boolean {
318
+ return isRelayDisabled(env) || relayBypassSubcommands.has(codexSubcommand(args));
319
+ }
320
+
321
+ async function runCodexPassthrough(args: string[]): Promise<void> {
322
+ const codex = Bun.spawn([findCodexBinary(), ...args], {
323
+ env: { ...process.env, AGENT_RELAY_DISABLED: "1" },
324
+ stdin: "inherit",
325
+ stdout: "inherit",
326
+ stderr: "inherit",
327
+ });
328
+ process.exit(await codex.exited);
329
+ }
330
+
262
331
  function installMarketplace(quiet = false): void {
263
332
  syncInstalledPackage();
264
333
 
@@ -1061,6 +1130,7 @@ function uninstall(args: string[] = []): void {
1061
1130
 
1062
1131
  async function main(): Promise<void> {
1063
1132
  const [command, ...args] = process.argv.slice(2);
1133
+ const codexArgs = command ? [command, ...args] : [];
1064
1134
  if (command === "help" || command === "--help" || command === "-h") usage(0);
1065
1135
  if (command === "install") return install(args);
1066
1136
  if (command === "uninstall") return uninstall(args);
@@ -1072,7 +1142,8 @@ async function main(): Promise<void> {
1072
1142
  if (command === "doctor") return doctor();
1073
1143
  if (command === "upgrade") return upgrade(args);
1074
1144
  if (command === "start") return start(args);
1075
- return start(command ? [command, ...args] : []);
1145
+ if (shouldBypassRelay(codexArgs)) return runCodexPassthrough(codexArgs);
1146
+ return start(codexArgs);
1076
1147
  }
1077
1148
 
1078
1149
  if (import.meta.main) {
@@ -46,6 +46,11 @@ function outputContext(context: string): never {
46
46
  process.exit(0);
47
47
  }
48
48
 
49
+ function outputContinue(): never {
50
+ console.log(JSON.stringify({ continue: true }));
51
+ process.exit(0);
52
+ }
53
+
49
54
  function handshakePath(runtimeDir: string): string {
50
55
  return join(runtimeDir, "session-start-handshake.json");
51
56
  }
@@ -74,6 +79,10 @@ const project = cwd.split("/").filter(Boolean).at(-1) || "unknown";
74
79
  const profile = loadAgentRelayProfile(process.env, { provider: "codex", rig, project });
75
80
  const approvalMode = profile.approval ?? parseApprovalMode(process.env.AGENT_RELAY_APPROVAL);
76
81
 
82
+ if (process.env.AGENT_RELAY_DISABLED === "1") {
83
+ outputContinue();
84
+ }
85
+
77
86
  if (process.env.AGENT_RELAY_CODEX_MANAGED === "1") {
78
87
  outputContext("Agent Relay is managed by codex-relay for this session; the launcher attached Relay and TUI to the same Codex App Server thread.");
79
88
  process.exit(0);
package/live-sidecar.ts CHANGED
@@ -85,6 +85,7 @@ class CodexLiveSidecar {
85
85
  private draining = false;
86
86
  private drainDueAt = 0;
87
87
  private reconnecting: Promise<void> | null = null;
88
+ private relayPrimerDelivered = false;
88
89
  private readonly pendingMessages = new Map<number, RelayMessage>();
89
90
  private readonly activeClaimedMessageIds = new Set<number>();
90
91
 
@@ -529,7 +530,7 @@ class CodexLiveSidecar {
529
530
  }
530
531
 
531
532
  const delivery = this.pickDeliveryMode(batch.messages);
532
- const prompt = formatRelayPrompt(batch.messages);
533
+ const prompt = formatRelayPrompt(batch.messages, { includePrimer: !this.relayPrimerDelivered });
533
534
  const ids = batch.messages.map((message) => message.id).join(", ");
534
535
  this.log(`delivering message ${ids} via ${delivery}`);
535
536
 
@@ -548,6 +549,7 @@ class CodexLiveSidecar {
548
549
  try {
549
550
  await this.app.turnSteer(this.threadId, this.activeTurnId, prompt);
550
551
  for (const id of claimedMessageIds) this.activeClaimedMessageIds.add(id);
552
+ this.relayPrimerDelivered = true;
551
553
  await this.markBatchRead(batch.messages);
552
554
  this.advanceCursor(batch.messages);
553
555
  this.writeState();
@@ -559,6 +561,7 @@ class CodexLiveSidecar {
559
561
 
560
562
  await this.app.turnStart(this.threadId, prompt);
561
563
  for (const id of claimedMessageIds) this.activeClaimedMessageIds.add(id);
564
+ this.relayPrimerDelivered = true;
562
565
  await this.markBatchRead(batch.messages);
563
566
  this.advanceCursor(batch.messages);
564
567
  this.writeState();
@@ -654,10 +657,25 @@ function shouldIsolateMessage(message: RelayMessage): boolean {
654
657
  return delivery === "interrupt" || delivery === "start" || delivery === "steer" || priority === "urgent";
655
658
  }
656
659
 
657
- export function formatRelayPrompt(messages: RelayMessage[]): string {
660
+ export function formatRelayPrompt(
661
+ messages: RelayMessage[],
662
+ opts: { includePrimer?: boolean } = {},
663
+ ): string {
664
+ const includePrimer = opts.includePrimer === true;
665
+ const relayUrl = process.env.AGENT_RELAY_URL || "http://127.0.0.1:4850";
666
+ const primer = [
667
+ "Agent Relay live-message primer:",
668
+ "Treat Agent Relay deliveries as live incoming messages from other agents. Respond or act on them as appropriate.",
669
+ "When calling the relay API, include AGENT_RELAY_TOKEN as the X-Agent-Relay-Token header if that environment variable is set.",
670
+ `For normal replies, POST JSON to ${relayUrl}/api/messages with from set to your Agent Relay ID, to set to the sender Agent Relay ID, body set to your response, and replyTo set to the incoming message id.`,
671
+ `For pair chat replies, POST JSON to ${relayUrl}/api/pairs/{pairId}/messages with from set to your Agent Relay ID and body set to your response.`,
672
+ "",
673
+ ];
674
+
658
675
  if (messages.length === 1) {
659
676
  const message = messages[0]!;
660
677
  const lines = [
678
+ ...(includePrimer ? primer : []),
661
679
  "Agent Relay message received.",
662
680
  "",
663
681
  formatMessageSummary(message),
@@ -678,16 +696,15 @@ export function formatRelayPrompt(messages: RelayMessage[]): string {
678
696
  "Body:",
679
697
  message.body,
680
698
  "",
681
- "Treat this as a live incoming message from another agent. Respond or act on it as appropriate.",
682
- "If AGENT_RELAY_TOKEN is set, include it as the X-Agent-Relay-Token header when calling the relay API.",
683
699
  typeof message.meta?.pairId === "string"
684
- ? `For pair chat, POST JSON to ${process.env.AGENT_RELAY_URL || "http://127.0.0.1:4850"}/api/pairs/${message.meta.pairId}/messages with from set to your Agent Relay ID and body set to your response.`
685
- : `To reply, POST JSON to ${process.env.AGENT_RELAY_URL || "http://127.0.0.1:4850"}/api/messages with from set to your Agent Relay ID, to set to ${JSON.stringify(message.from)}, and replyTo set to ${message.id}.`,
700
+ ? `Reply routing: pairId=${JSON.stringify(message.meta.pairId)}.`
701
+ : `Reply routing: to=${JSON.stringify(message.from)}, replyTo=${message.id}.`,
686
702
  );
687
703
  return lines.join("\n");
688
704
  }
689
705
 
690
706
  const lines = [
707
+ ...(includePrimer ? primer : []),
691
708
  "Agent Relay message batch received.",
692
709
  "",
693
710
  `Count: ${messages.length}`,
@@ -705,13 +722,16 @@ export function formatRelayPrompt(messages: RelayMessage[]): string {
705
722
  if (message.subject) lines.push(`Subject: ${message.subject}`);
706
723
  if (message.replyTo) lines.push(`Reply To: ${message.replyTo}`);
707
724
  if (typeof message.meta?.pairId === "string") lines.push(`Pair ID: ${message.meta.pairId}`);
725
+ lines.push(
726
+ typeof message.meta?.pairId === "string"
727
+ ? `Reply routing: pairId=${JSON.stringify(message.meta.pairId)}.`
728
+ : `Reply routing: to=${JSON.stringify(message.from)}, replyTo=${message.id}.`,
729
+ );
708
730
  lines.push("Body:", message.body, "", "---", "");
709
731
  }
710
732
 
711
733
  lines.push(
712
- "Treat these as live incoming messages from other agents. Synthesize them into one coherent response or action.",
713
- "If AGENT_RELAY_TOKEN is set, include it as the X-Agent-Relay-Token header when calling the relay API.",
714
- `To reply, POST JSON to ${process.env.AGENT_RELAY_URL || "http://127.0.0.1:4850"}/api/messages with from set to your Agent Relay ID and replyTo set to the message you are answering.`,
734
+ "Synthesize these messages into one coherent response or action. Use each message's Reply routing line when replying.",
715
735
  );
716
736
  return lines.join("\n");
717
737
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay-codex",
3
- "version": "0.4.28",
3
+ "version": "0.4.33",
4
4
  "description": "Codex integration for Agent Relay — auto-registers sessions as agents and enables inter-agent messaging",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "0.4.28",
3
+ "version": "0.4.33",
4
4
  "description": "Agent Relay integration for Codex sessions",
5
5
  "author": {
6
6
  "name": "Edin Mujkanovic"