



















@@ -1770,6 +1770,7 @@ describe("gateway agent handler", () => {
17701770updatedAt: now,
17711771sessionStartedAt: now - 25 * 60 * 60_000,
17721772lastInteractionAt: now - 25 * 60 * 60_000,
1773+sessionFile: "/tmp/stale-session-id.jsonl",
17731774},
17741775{
17751776session: {
@@ -1813,6 +1814,137 @@ describe("gateway agent handler", () => {
18131814expect(call.sessionId).not.toBe("stale-session-id");
18141815expect(capturedEntry?.sessionStartedAt).toBe(now);
18151816expect(capturedEntry?.lastInteractionAt).toBe(now);
1817+expect(capturedEntry?.sessionFile).toBeTruthy();
1818+expect(capturedEntry?.sessionFile).not.toBe("/tmp/stale-session-id.jsonl");
1819+expect(String(capturedEntry?.sessionFile)).toContain(
1820+`${String(capturedEntry?.sessionId)}.jsonl`,
1821+);
1822+} finally {
1823+vi.useRealTimers();
1824+}
1825+});
1826+1827+it("preserves custom transcript paths when stale gateway agent sessions roll", async () => {
1828+const now = Date.parse("2026-04-25T12:00:00.000Z");
1829+const customSessionFile = "/tmp/custom-owned-child-transcript.jsonl";
1830+vi.useFakeTimers();
1831+vi.setSystemTime(now);
1832+try {
1833+mocks.resolveExplicitAgentSessionKey.mockReturnValue("agent:main:main");
1834+mockMainSessionEntry(
1835+{
1836+sessionId: "stale-session-id",
1837+updatedAt: now,
1838+sessionStartedAt: now - 25 * 60 * 60_000,
1839+lastInteractionAt: now - 25 * 60 * 60_000,
1840+sessionFile: customSessionFile,
1841+},
1842+{
1843+session: {
1844+reset: {
1845+mode: "daily",
1846+atHour: 4,
1847+},
1848+},
1849+},
1850+);
1851+const loaded = mocks.loadSessionEntry();
1852+let capturedEntry: Record<string, unknown> | undefined;
1853+mocks.updateSessionStore.mockImplementation(async (_path, updater) => {
1854+const store: Record<string, unknown> = {
1855+[loaded.canonicalKey]: structuredClone(loaded.entry),
1856+};
1857+const result = await updater(store);
1858+capturedEntry = result as Record<string, unknown>;
1859+return result;
1860+});
1861+mocks.agentCommand.mockResolvedValue({
1862+payloads: [{ text: "ok" }],
1863+meta: { durationMs: 100 },
1864+});
1865+1866+await invokeAgent(
1867+{
1868+message: "daily rollover",
1869+agentId: "main",
1870+sessionKey: "agent:main:main",
1871+idempotencyKey: "daily-rollover-custom-session-file",
1872+},
1873+{ reqId: "daily-rollover-custom-session-file" },
1874+);
1875+1876+const call = await waitForAgentCommandCall<{
1877+sessionId?: string;
1878+sessionKey?: string;
1879+}>();
1880+expect(call.sessionKey).toBe("agent:main:main");
1881+expect(call.sessionId).not.toBe("stale-session-id");
1882+expect(capturedEntry?.sessionFile).toBe(customSessionFile);
1883+} finally {
1884+vi.useRealTimers();
1885+}
1886+});
1887+1888+it("repairs already-stale generated transcript paths when gateway agent sessions roll", async () => {
1889+const now = Date.parse("2026-05-06T12:00:00.000Z");
1890+const alreadyStaleSessionFile = "/tmp/685a51f7-7adf-48b1-89ca-d3ab86dd6e0f.jsonl";
1891+vi.useFakeTimers();
1892+vi.setSystemTime(now);
1893+try {
1894+mocks.resolveExplicitAgentSessionKey.mockReturnValue("agent:main:main");
1895+mockMainSessionEntry(
1896+{
1897+sessionId: "63b16647-ea0c-4a22-808b-ce616326b445",
1898+updatedAt: now,
1899+sessionStartedAt: now - 25 * 60 * 60_000,
1900+lastInteractionAt: now - 25 * 60 * 60_000,
1901+sessionFile: alreadyStaleSessionFile,
1902+},
1903+{
1904+session: {
1905+reset: {
1906+mode: "daily",
1907+atHour: 4,
1908+},
1909+},
1910+},
1911+);
1912+const loaded = mocks.loadSessionEntry();
1913+let capturedEntry: Record<string, unknown> | undefined;
1914+mocks.updateSessionStore.mockImplementation(async (_path, updater) => {
1915+const store: Record<string, unknown> = {
1916+[loaded.canonicalKey]: structuredClone(loaded.entry),
1917+};
1918+const result = await updater(store);
1919+capturedEntry = result as Record<string, unknown>;
1920+return result;
1921+});
1922+mocks.agentCommand.mockResolvedValue({
1923+payloads: [{ text: "ok" }],
1924+meta: { durationMs: 100 },
1925+});
1926+1927+await invokeAgent(
1928+{
1929+message: "daily rollover",
1930+agentId: "main",
1931+sessionKey: "agent:main:main",
1932+idempotencyKey: "daily-rollover-already-stale-session-file",
1933+},
1934+{ reqId: "daily-rollover-already-stale-session-file" },
1935+);
1936+1937+const call = await waitForAgentCommandCall<{
1938+sessionId?: string;
1939+sessionKey?: string;
1940+}>();
1941+expect(call.sessionKey).toBe("agent:main:main");
1942+expect(call.sessionId).not.toBe("63b16647-ea0c-4a22-808b-ce616326b445");
1943+expect(capturedEntry?.sessionFile).toBeTruthy();
1944+expect(capturedEntry?.sessionFile).not.toBe(alreadyStaleSessionFile);
1945+expect(String(capturedEntry?.sessionFile)).toContain(
1946+`${String(capturedEntry?.sessionId)}.jsonl`,
1947+);
18161948} finally {
18171949vi.useRealTimers();
18181950}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。