Skip to content

Commit 075bdde

Browse files
committed
Drop bridge message envelope
1 parent 41af855 commit 075bdde

7 files changed

Lines changed: 16 additions & 100 deletions

File tree

src/loop/bridge-message-format.ts

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,18 @@
11
import type { Agent } from "./types";
22

3-
const BRIDGE_TAG_RE = /<\/?loop-bridge(?:\s+[^>]*)?>/gi;
43
const BRIDGE_PREFIX_RE =
54
/^(?:Message from (?:Claude|Codex) via the loop bridge:|(?:Claude|Codex):)\s*/i;
65

7-
const bridgeSourceLabel = (source: Agent): string =>
8-
source === "claude" ? "Claude" : "Codex";
9-
106
export const formatCodexBridgeMessage = (
117
source: Agent,
12-
message: string,
13-
messageId?: string
8+
message: string
149
): string => {
1510
const trimmed = message.trim();
1611
if (!trimmed) {
1712
return "";
1813
}
19-
const messageIdAttr = messageId ? ` message_id="${messageId}"` : "";
20-
return [
21-
`<loop-bridge source="${source}"${messageIdAttr}>`,
22-
`${bridgeSourceLabel(source)}: ${trimmed}`,
23-
"</loop-bridge>",
24-
].join("\n");
14+
return source === "claude" ? `Claude: ${trimmed}` : trimmed;
2515
};
2616

2717
export const normalizeBridgeMessage = (message: string): string =>
28-
message
29-
.trim()
30-
.replace(BRIDGE_TAG_RE, " ")
31-
.trim()
32-
.replace(BRIDGE_PREFIX_RE, "")
33-
.replace(/\s+/g, " ")
34-
.trim();
18+
message.trim().replace(BRIDGE_PREFIX_RE, "").replace(/\s+/g, " ").trim();

src/loop/bridge-runtime.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ export const deliverCodexBridgeMessage = async (
329329
const delivered = await injectCodexMessage(
330330
status.codexRemoteUrl,
331331
status.codexThreadId,
332-
formatCodexBridgeMessage(message.source, message.message, message.id)
332+
formatCodexBridgeMessage(message.source, message.message)
333333
);
334334
if (delivered) {
335335
acknowledgeBridgeDelivery(
@@ -361,7 +361,7 @@ export const drainCodexTmuxMessages = async (
361361
}
362362
const delivered = await injectCodexTmuxMessage(
363363
status.tmuxSession,
364-
formatCodexBridgeMessage(message.source, message.message, message.id)
364+
formatCodexBridgeMessage(message.source, message.message)
365365
);
366366
if (!delivered) {
367367
return false;

src/loop/codex-tmux-proxy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ const buildBridgeInjectionFrame = (
235235
params: {
236236
expectedTurnId: activeTurnId,
237237
input: buildInput(
238-
formatCodexBridgeMessage(message.source, message.message, message.id)
238+
formatCodexBridgeMessage(message.source, message.message)
239239
),
240240
threadId,
241241
},
@@ -246,7 +246,7 @@ const buildBridgeInjectionFrame = (
246246
method: TURN_START_METHOD,
247247
params: {
248248
input: buildInput(
249-
formatCodexBridgeMessage(message.source, message.message, message.id)
249+
formatCodexBridgeMessage(message.source, message.message)
250250
),
251251
threadId,
252252
},

src/loop/paired-loop.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,15 @@ const reviewBridgePrompt = (
153153
.join("\n\n");
154154

155155
const forwardBridgePrompt = ({
156-
id,
157156
message,
158157
source,
159158
}: {
160-
id: string;
161159
message: string;
162160
source: Agent;
163161
}): string =>
164162
(source === "claude"
165163
? [
166-
formatCodexBridgeMessage(source, message, id),
164+
formatCodexBridgeMessage(source, message),
167165
"Treat this as direct agent-to-agent coordination. Do not reply to the human.",
168166
'Send a message to the other agent with "send_message" only when you have something useful for them to act on.',
169167
"Do not acknowledge receipt without new information.",

tests/loop/bridge.test.ts

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,6 @@ const toolText = (stdout: string, id: number): string => {
7575
)?.content;
7676
return content?.[0]?.text ?? "";
7777
};
78-
const codexBridgeEnvelope = (
79-
id: string,
80-
message: string,
81-
source: "claude" | "codex" = "claude"
82-
): string =>
83-
[
84-
`<loop-bridge source="${source}" message_id="${id}">`,
85-
`${source === "claude" ? "Claude" : "Codex"}: ${message}`,
86-
"</loop-bridge>",
87-
].join("\n");
8878

8979
const runBridgeProcess = async (
9080
runDir: string,
@@ -481,15 +471,6 @@ test("bridge normalization treats short and legacy Claude prefixes as equivalent
481471
"Claude: Please verify the final diff."
482472
)
483473
).toBe(true);
484-
expect(
485-
bridge.blocksBridgeBounce(
486-
runDir,
487-
"codex",
488-
"claude",
489-
codexBridgeEnvelope("msg-2", "Please verify the final diff.")
490-
)
491-
).toBe(true);
492-
493474
rmSync(root, { recursive: true, force: true });
494475
});
495476

@@ -1181,7 +1162,7 @@ test("bridge delivers Claude replies directly to Codex when app-server state is
11811162
expect(injectCodexMessage).toHaveBeenCalledWith(
11821163
"ws://127.0.0.1:4500",
11831164
"codex-thread-1",
1184-
codexBridgeEnvelope("msg-1", "The files look good to me.")
1165+
"Claude: The files look good to me."
11851166
);
11861167
expect(bridge.readPendingBridgeMessages(runDir)).toEqual([]);
11871168
expect(
@@ -1239,7 +1220,7 @@ test("bridge prefers Codex app-server delivery even when tmux is live", async ()
12391220
expect(injectCodexMessage).toHaveBeenCalledWith(
12401221
"ws://127.0.0.1:4500",
12411222
"codex-thread-1",
1242-
codexBridgeEnvelope("msg-live", "Please steer this into the active turn.")
1223+
"Claude: Please steer this into the active turn."
12431224
);
12441225
expect(bridge.readPendingBridgeMessages(runDir)).toEqual([]);
12451226
expect(
@@ -1300,7 +1281,7 @@ test("bridge falls back to direct Codex delivery when the stored tmux session is
13001281
expect(injectCodexMessage).toHaveBeenCalledWith(
13011282
"ws://127.0.0.1:4500",
13021283
"codex-thread-1",
1303-
'<loop-bridge source="claude" message_id="msg-2">\nClaude: Please review the final state.\n</loop-bridge>'
1284+
"Claude: Please review the final state."
13041285
);
13051286
expect(readRunManifest(join(runDir, "manifest.json"))?.tmuxSession).toBe(
13061287
undefined
@@ -1385,22 +1366,6 @@ test("bridge drains pending codex tmux messages through the injected command dep
13851366
["tmux", "capture-pane", "-p", "-t", "repo-loop-8:0.1"],
13861367
{ stderr: "ignore", stdout: "pipe" },
13871368
],
1388-
[
1389-
[
1390-
"tmux",
1391-
"send-keys",
1392-
"-t",
1393-
"repo-loop-8:0.1",
1394-
"-l",
1395-
"--",
1396-
'<loop-bridge source="claude" message_id="msg-3">',
1397-
],
1398-
{ stderr: "ignore" },
1399-
],
1400-
[
1401-
["tmux", "send-keys", "-t", "repo-loop-8:0.1", "C-j"],
1402-
{ stderr: "ignore" },
1403-
],
14041369
[
14051370
[
14061371
"tmux",
@@ -1413,22 +1378,6 @@ test("bridge drains pending codex tmux messages through the injected command dep
14131378
],
14141379
{ stderr: "ignore" },
14151380
],
1416-
[
1417-
["tmux", "send-keys", "-t", "repo-loop-8:0.1", "C-j"],
1418-
{ stderr: "ignore" },
1419-
],
1420-
[
1421-
[
1422-
"tmux",
1423-
"send-keys",
1424-
"-t",
1425-
"repo-loop-8:0.1",
1426-
"-l",
1427-
"--",
1428-
"</loop-bridge>",
1429-
],
1430-
{ stderr: "ignore" },
1431-
],
14321381
[
14331382
["tmux", "send-keys", "-t", "repo-loop-8:0.1", "Enter"],
14341383
{ stderr: "ignore" },
@@ -1732,10 +1681,7 @@ test("runBridgeWorker falls back to app-server delivery after stale tmux cleanup
17321681
expect(injectCodexMessage).toHaveBeenCalledWith(
17331682
"ws://127.0.0.1:4500",
17341683
"codex-thread-1",
1735-
codexBridgeEnvelope(
1736-
"msg-stale-fallback",
1737-
"Please deliver this after tmux cleanup."
1738-
)
1684+
"Claude: Please deliver this after tmux cleanup."
17391685
);
17401686
expect(readRunManifest(join(runDir, "manifest.json"))?.tmuxSession).toBe(
17411687
undefined
@@ -1847,12 +1793,12 @@ test("runBridgeWorker retries queued codex app-server messages", async () => {
18471793
[
18481794
"ws://127.0.0.1:4500",
18491795
"codex-thread-1",
1850-
codexBridgeEnvelope("msg-4", "Please review the final diff."),
1796+
"Claude: Please review the final diff.",
18511797
],
18521798
[
18531799
"ws://127.0.0.1:4500",
18541800
"codex-thread-1",
1855-
codexBridgeEnvelope("msg-4", "Please review the final diff."),
1801+
"Claude: Please review the final diff.",
18561802
],
18571803
]);
18581804
expect(bridge.readPendingBridgeMessages(runDir)).toEqual([]);

tests/loop/codex-tmux-proxy.test.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ const bridgeMessage = {
2828
source: "claude" as const,
2929
target: "codex" as const,
3030
};
31-
const codexBridgeEnvelope = (id: string, message: string): string =>
32-
[
33-
`<loop-bridge source="claude" message_id="${id}">`,
34-
`Claude: ${message}`,
35-
"</loop-bridge>",
36-
].join("\n");
3731

3832
const TEST_PORT_RANGE = 200;
3933
const TEST_PORT_RETRY_LIMIT = 5;
@@ -221,7 +215,7 @@ test("codex tmux proxy steers bridge messages into an active turn", () => {
221215
expectedTurnId: "turn-active",
222216
input: [
223217
{
224-
text: codexBridgeEnvelope("msg-1", "Please review the latest diff."),
218+
text: "Claude: Please review the latest diff.",
225219
text_elements: [],
226220
type: "text",
227221
},
@@ -244,7 +238,7 @@ test("codex tmux proxy starts a new turn when no active turn exists", () => {
244238
params: {
245239
input: [
246240
{
247-
text: codexBridgeEnvelope("msg-1", "Please review the latest diff."),
241+
text: "Claude: Please review the latest diff.",
248242
text_elements: [],
249243
type: "text",
250244
},

tests/loop/paired-loop.test.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -772,9 +772,6 @@ test("runPairedLoop delivers peer messages back to the primary agent", async ()
772772
expect(calls).toHaveLength(3);
773773
expect(calls[0]?.agent).toBe("claude");
774774
expect(calls[1]?.agent).toBe("codex");
775-
expect(calls[1]?.prompt).toContain(
776-
'<loop-bridge source="claude" message_id="msg-1">'
777-
);
778775
expect(calls[1]?.prompt).toContain("Claude: Please verify");
779776
expect(calls[1]?.prompt).toContain(
780777
"Please verify the implementation details."
@@ -817,9 +814,6 @@ test("runPairedLoop skips the default work turn after draining input for the pri
817814

818815
expect(calls).toHaveLength(1);
819816
expect(calls[0]?.agent).toBe("codex");
820-
expect(calls[0]?.prompt).toContain(
821-
'<loop-bridge source="claude" message_id="msg-1">'
822-
);
823817
expect(calls[0]?.prompt).toContain("Claude: Please verify");
824818
expect(calls[0]?.prompt).toContain(
825819
"Please verify the implementation details."

0 commit comments

Comments
 (0)