agent-relay-server 0.4.10 → 0.4.11
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 +3 -0
- package/codex/README.md +5 -5
- package/codex/live-sidecar.test.ts +20 -0
- package/codex/live-sidecar.ts +31 -24
- package/codex/plugin/.codex-plugin/plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -224,6 +224,9 @@ time, it starts a new thread by default to avoid surprising cwd-based attachment
|
|
|
224
224
|
to an unrelated loaded session. Use `codex-relay --thread-mode auto` or
|
|
225
225
|
`AGENT_RELAY_CODEX_FALLBACK_THREAD_MODE=auto` when you deliberately want the
|
|
226
226
|
fallback sidecar to attach to the newest loaded thread for the current cwd.
|
|
227
|
+
The lower-level sidecar also defaults to `CODEX_THREAD_MODE=start`; `auto` is an
|
|
228
|
+
explicit opt-in because it may deliver relay messages into an already-open Codex
|
|
229
|
+
session for the same directory.
|
|
227
230
|
|
|
228
231
|
### Codex approval mode
|
|
229
232
|
|
package/codex/README.md
CHANGED
|
@@ -12,9 +12,9 @@ This sidecar connects to a Codex app-server session and to Agent Relay, then del
|
|
|
12
12
|
|
|
13
13
|
## Current behavior
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
15
|
+
- starts a new thread by default
|
|
16
|
+
- resumes the actual launched thread when the SessionStart hook provides a thread id
|
|
17
|
+
- only attaches to loaded/latest same-cwd threads when `CODEX_THREAD_MODE=auto`
|
|
18
18
|
- registers a relay agent with `client: codex-live`
|
|
19
19
|
- marks the relay agent `ready=true` once app-server + thread are attached
|
|
20
20
|
- polls relay inbox and delivers messages into the live thread
|
|
@@ -131,6 +131,6 @@ startup in time.
|
|
|
131
131
|
|
|
132
132
|
Current sidecar behavior is stable for live delivery. Remaining gaps are advanced policies such as batching by sender, message prioritization queues, and more nuanced retry/backoff behavior.
|
|
133
133
|
|
|
134
|
-
- `CODEX_THREAD_MODE=
|
|
135
|
-
-
|
|
134
|
+
- `CODEX_THREAD_MODE=start` is the safe default: the sidecar creates its own thread unless the hook supplied an explicit thread id.
|
|
135
|
+
- `CODEX_THREAD_MODE=auto` will attach to an already loaded thread for the same `cwd`. That can be useful for advanced live control, but it also means relay messages can enter your current interactive Codex session if one is already open.
|
|
136
136
|
- A brand-new thread is not materialized for `includeTurns` reads until the first turn starts. That is an app-server behavior, not a relay bug.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { loadConfig, parseThreadMode } from "./live-sidecar";
|
|
3
|
+
|
|
4
|
+
describe("codex live sidecar config", () => {
|
|
5
|
+
it("defaults to starting an isolated thread", () => {
|
|
6
|
+
const config = loadConfig({
|
|
7
|
+
CODEX_LIVE_CWD: "/tmp/agent-relay-test",
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
expect(config.threadMode).toBe("start");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("only accepts known thread attachment modes", () => {
|
|
14
|
+
expect(parseThreadMode("auto")).toBe("auto");
|
|
15
|
+
expect(parseThreadMode("resume")).toBe("resume");
|
|
16
|
+
expect(parseThreadMode("start")).toBe("start");
|
|
17
|
+
expect(parseThreadMode("latest")).toBe("start");
|
|
18
|
+
expect(parseThreadMode(undefined)).toBe("start");
|
|
19
|
+
});
|
|
20
|
+
});
|
package/codex/live-sidecar.ts
CHANGED
|
@@ -572,38 +572,43 @@ function describeError(error: unknown): string {
|
|
|
572
572
|
return error instanceof Error ? error.message : String(error);
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
-
function envNumber(name: string, fallback: number): number {
|
|
576
|
-
const raw =
|
|
575
|
+
function envNumber(env: NodeJS.ProcessEnv, name: string, fallback: number): number {
|
|
576
|
+
const raw = env[name];
|
|
577
577
|
if (!raw) return fallback;
|
|
578
578
|
const parsed = Number(raw);
|
|
579
579
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
580
580
|
}
|
|
581
581
|
|
|
582
|
-
function
|
|
583
|
-
|
|
584
|
-
|
|
582
|
+
export function parseThreadMode(raw: string | undefined): Config["threadMode"] {
|
|
583
|
+
if (raw === "auto" || raw === "resume" || raw === "start") return raw;
|
|
584
|
+
return "start";
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export function loadConfig(env: NodeJS.ProcessEnv = process.env): Config {
|
|
588
|
+
const cwd = env.CODEX_LIVE_CWD || process.cwd();
|
|
589
|
+
const capabilities = (env.AGENT_RELAY_CAPS || "chat")
|
|
585
590
|
.split(",")
|
|
586
591
|
.map((value) => value.trim())
|
|
587
592
|
.filter(Boolean);
|
|
588
593
|
|
|
589
594
|
return {
|
|
590
|
-
relayUrl:
|
|
591
|
-
appServerUrl:
|
|
595
|
+
relayUrl: env.AGENT_RELAY_URL || "http://127.0.0.1:4850",
|
|
596
|
+
appServerUrl: env.CODEX_APP_SERVER_URL || "ws://127.0.0.1:4501",
|
|
592
597
|
cwd,
|
|
593
|
-
rig:
|
|
598
|
+
rig: env.CODEX_LIVE_RIG || "codex-live",
|
|
594
599
|
capabilities,
|
|
595
|
-
tags: ["codex",
|
|
596
|
-
statePath:
|
|
597
|
-
pollIntervalMs: envNumber("CODEX_LIVE_POLL_INTERVAL_MS", 2000),
|
|
598
|
-
heartbeatIntervalMs: envNumber("CODEX_LIVE_HEARTBEAT_INTERVAL_MS", 30000),
|
|
599
|
-
coalesceWindowMs: envNumber("CODEX_LIVE_COALESCE_WINDOW_MS", 600),
|
|
600
|
-
reconnectInitialDelayMs: envNumber("CODEX_LIVE_RECONNECT_INITIAL_MS", 1000),
|
|
601
|
-
reconnectMaxDelayMs: envNumber("CODEX_LIVE_RECONNECT_MAX_MS", 10000),
|
|
602
|
-
threadMode: (
|
|
603
|
-
threadId:
|
|
604
|
-
model:
|
|
605
|
-
approvalPolicy:
|
|
606
|
-
sandbox:
|
|
600
|
+
tags: ["codex", env.CODEX_LIVE_RIG || "codex-live", cwd.split("/").filter(Boolean).at(-1) || "unknown"],
|
|
601
|
+
statePath: env.CODEX_LIVE_STATE_PATH || resolve(cwd, "codex/runtime/live-state.json"),
|
|
602
|
+
pollIntervalMs: envNumber(env, "CODEX_LIVE_POLL_INTERVAL_MS", 2000),
|
|
603
|
+
heartbeatIntervalMs: envNumber(env, "CODEX_LIVE_HEARTBEAT_INTERVAL_MS", 30000),
|
|
604
|
+
coalesceWindowMs: envNumber(env, "CODEX_LIVE_COALESCE_WINDOW_MS", 600),
|
|
605
|
+
reconnectInitialDelayMs: envNumber(env, "CODEX_LIVE_RECONNECT_INITIAL_MS", 1000),
|
|
606
|
+
reconnectMaxDelayMs: envNumber(env, "CODEX_LIVE_RECONNECT_MAX_MS", 10000),
|
|
607
|
+
threadMode: parseThreadMode(env.CODEX_THREAD_MODE),
|
|
608
|
+
threadId: env.CODEX_THREAD_ID || undefined,
|
|
609
|
+
model: env.CODEX_MODEL || undefined,
|
|
610
|
+
approvalPolicy: env.CODEX_LIVE_APPROVAL_POLICY || undefined,
|
|
611
|
+
sandbox: env.CODEX_LIVE_SANDBOX || undefined,
|
|
607
612
|
};
|
|
608
613
|
}
|
|
609
614
|
|
|
@@ -613,7 +618,9 @@ async function main(): Promise<void> {
|
|
|
613
618
|
await sidecar.run();
|
|
614
619
|
}
|
|
615
620
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
621
|
+
if (import.meta.main) {
|
|
622
|
+
main().catch((error) => {
|
|
623
|
+
console.error(error instanceof Error ? error.stack || error.message : String(error));
|
|
624
|
+
process.exit(1);
|
|
625
|
+
});
|
|
626
|
+
}
|