diff --git a/packages/core/src/__tests__/session-manager/restore.test.ts b/packages/core/src/__tests__/session-manager/restore.test.ts index e3f68c34d..b21f4d8cc 100644 --- a/packages/core/src/__tests__/session-manager/restore.test.ts +++ b/packages/core/src/__tests__/session-manager/restore.test.ts @@ -86,6 +86,39 @@ describe("restore", () => { expect(meta!["createdAt"]).toBe("2025-01-01T00:00:00.000Z"); }); + it("forwards AO_AGENT_GH_TRACE into restored agent runtime env when configured", async () => { + const wsPath = join(tmpDir, "ws-app-1-trace"); + mkdirSync(wsPath, { recursive: true }); + + writeMetadata(sessionsDir, "app-1", { + worktree: wsPath, + branch: "feat/TEST-1", + status: "killed", + project: "my-app", + runtimeHandle: JSON.stringify(makeHandle("rt-old")), + }); + + const previousTrace = process.env["AO_AGENT_GH_TRACE"]; + process.env["AO_AGENT_GH_TRACE"] = "/tmp/restored-agent-gh-trace-test.jsonl"; + + try { + const sm = createSessionManager({ config, registry: mockRegistry }); + await sm.restore("app-1"); + + expect(mockRuntime.create).toHaveBeenCalledWith( + expect.objectContaining({ + environment: expect.objectContaining({ + AO_AGENT_GH_TRACE: "/tmp/restored-agent-gh-trace-test.jsonl", + AO_CALLER_TYPE: "agent", + }), + }), + ); + } finally { + if (previousTrace === undefined) delete process.env["AO_AGENT_GH_TRACE"]; + else process.env["AO_AGENT_GH_TRACE"] = previousTrace; + } + }); + it("continues restore even if old runtime destroy fails", async () => { const wsPath = join(tmpDir, "ws-app-1"); mkdirSync(wsPath, { recursive: true }); diff --git a/packages/core/src/__tests__/session-manager/spawn.test.ts b/packages/core/src/__tests__/session-manager/spawn.test.ts index 968ce9149..19c7c3742 100644 --- a/packages/core/src/__tests__/session-manager/spawn.test.ts +++ b/packages/core/src/__tests__/session-manager/spawn.test.ts @@ -72,6 +72,27 @@ describe("spawn", () => { expect(mockRuntime.create).toHaveBeenCalled(); }); + it("forwards AO_AGENT_GH_TRACE into spawned agent runtime env when configured", async () => { + const previousTrace = process.env["AO_AGENT_GH_TRACE"]; + process.env["AO_AGENT_GH_TRACE"] = "/tmp/agent-gh-trace-test.jsonl"; + + try { + const sm = createSessionManager({ config, registry: mockRegistry }); + await sm.spawn({ projectId: "my-app" }); + + expect(mockRuntime.create).toHaveBeenCalledWith( + expect.objectContaining({ + environment: expect.objectContaining({ + AO_AGENT_GH_TRACE: "/tmp/agent-gh-trace-test.jsonl", + }), + }), + ); + } finally { + if (previousTrace === undefined) delete process.env["AO_AGENT_GH_TRACE"]; + else process.env["AO_AGENT_GH_TRACE"] = previousTrace; + } + }); + it("uses issue ID to derive branch name", async () => { const sm = createSessionManager({ config, registry: mockRegistry }); @@ -1547,6 +1568,28 @@ describe("spawn", () => { ); }); + it("forwards AO_AGENT_GH_TRACE into orchestrator runtime env when configured", async () => { + const previousTrace = process.env["AO_AGENT_GH_TRACE"]; + process.env["AO_AGENT_GH_TRACE"] = "/tmp/orchestrator-gh-trace-test.jsonl"; + + try { + const sm = createSessionManager({ config, registry: mockRegistry }); + await sm.spawnOrchestrator({ projectId: "my-app" }); + + expect(mockRuntime.create).toHaveBeenCalledWith( + expect.objectContaining({ + environment: expect.objectContaining({ + AO_AGENT_GH_TRACE: "/tmp/orchestrator-gh-trace-test.jsonl", + AO_CALLER_TYPE: "orchestrator", + }), + }), + ); + } finally { + if (previousTrace === undefined) delete process.env["AO_AGENT_GH_TRACE"]; + else process.env["AO_AGENT_GH_TRACE"] = previousTrace; + } + }); + it("does not persist orchestratorSessionReused metadata on newly created sessions", async () => { const sm = createSessionManager({ config, registry: mockRegistry }); diff --git a/packages/core/src/session-manager.ts b/packages/core/src/session-manager.ts index e9ef18d30..5d4da0cdb 100644 --- a/packages/core/src/session-manager.ts +++ b/packages/core/src/session-manager.ts @@ -1263,6 +1263,9 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM ...environment, PATH: buildAgentPath(environment["PATH"] ?? process.env["PATH"]), GH_PATH: PREFERRED_GH_PATH, + ...(process.env["AO_AGENT_GH_TRACE"] && { + AO_AGENT_GH_TRACE: process.env["AO_AGENT_GH_TRACE"], + }), AO_SESSION: sessionId, AO_DATA_DIR: sessionsDir, // Pass sessions directory (not root dataDir) AO_SESSION_NAME: sessionId, // User-facing session name @@ -1618,6 +1621,9 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM ...environment, PATH: buildAgentPath(environment["PATH"] ?? process.env["PATH"]), GH_PATH: PREFERRED_GH_PATH, + ...(process.env["AO_AGENT_GH_TRACE"] && { + AO_AGENT_GH_TRACE: process.env["AO_AGENT_GH_TRACE"], + }), AO_SESSION: sessionId, AO_DATA_DIR: sessionsDir, AO_SESSION_NAME: sessionId, @@ -2709,6 +2715,9 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM ...environment, PATH: buildAgentPath(environment["PATH"] ?? process.env["PATH"]), GH_PATH: PREFERRED_GH_PATH, + ...(process.env["AO_AGENT_GH_TRACE"] && { + AO_AGENT_GH_TRACE: process.env["AO_AGENT_GH_TRACE"], + }), AO_SESSION: sessionId, AO_DATA_DIR: sessionsDir, AO_SESSION_NAME: sessionId,