

























@@ -1817,6 +1817,101 @@ describe("initSessionState reset policy", () => {
18171817expect(result.sessionId).not.toBe(existingSessionId);
18181818});
181918191820+it("preserves idle rollover when an ordinary send asserts the current session id", async () => {
1821+vi.setSystemTime(new Date(2026, 0, 18, 5, 30, 0));
1822+const root = await makeCaseDir("openclaw-reset-idle-requested-session-ordinary-");
1823+const storePath = path.join(root, "sessions.json");
1824+const sessionKey = "agent:main:main";
1825+const existingSessionId = "webchat-ordinary-session-id";
1826+1827+await writeSessionStoreFast(storePath, {
1828+[sessionKey]: {
1829+sessionId: existingSessionId,
1830+updatedAt: new Date(2026, 0, 18, 4, 45, 0).getTime(),
1831+},
1832+});
1833+1834+const cfg = {
1835+session: {
1836+store: storePath,
1837+reset: { mode: "daily", atHour: 4, idleMinutes: 30 },
1838+},
1839+} as OpenClawConfig;
1840+const result = await initSessionState({
1841+ctx: { Body: "hello", SessionKey: sessionKey, Provider: "internal", Surface: "internal" },
1842+ cfg,
1843+commandAuthorized: true,
1844+requestedSessionId: existingSessionId,
1845+});
1846+1847+expect(result.isNewSession).toBe(true);
1848+expect(result.sessionId).not.toBe(existingSessionId);
1849+});
1850+1851+it("reuses an idle-expired session when a reconnecting client requests current session resume", async () => {
1852+vi.setSystemTime(new Date(2026, 0, 18, 5, 30, 0));
1853+const root = await makeCaseDir("openclaw-reset-idle-requested-session-");
1854+const storePath = path.join(root, "sessions.json");
1855+const sessionKey = "agent:main:main";
1856+const existingSessionId = "webchat-reconnect-session-id";
1857+1858+await writeSessionStoreFast(storePath, {
1859+[sessionKey]: {
1860+sessionId: existingSessionId,
1861+updatedAt: new Date(2026, 0, 18, 4, 45, 0).getTime(),
1862+},
1863+});
1864+1865+const cfg = {
1866+session: {
1867+store: storePath,
1868+reset: { mode: "daily", atHour: 4, idleMinutes: 30 },
1869+},
1870+} as OpenClawConfig;
1871+const result = await initSessionState({
1872+ctx: { Body: "hello", SessionKey: sessionKey, Provider: "internal", Surface: "internal" },
1873+ cfg,
1874+commandAuthorized: true,
1875+requestedSessionId: existingSessionId,
1876+resumeRequestedSession: true,
1877+});
1878+1879+expect(result.isNewSession).toBe(false);
1880+expect(result.sessionId).toBe(existingSessionId);
1881+});
1882+1883+it("does not reuse an idle-expired session for a stale asserted session id", async () => {
1884+vi.setSystemTime(new Date(2026, 0, 18, 5, 30, 0));
1885+const root = await makeCaseDir("openclaw-reset-idle-stale-requested-session-");
1886+const storePath = path.join(root, "sessions.json");
1887+const sessionKey = "agent:main:main";
1888+const existingSessionId = "webchat-current-session-id";
1889+1890+await writeSessionStoreFast(storePath, {
1891+[sessionKey]: {
1892+sessionId: existingSessionId,
1893+updatedAt: new Date(2026, 0, 18, 4, 45, 0).getTime(),
1894+},
1895+});
1896+1897+const cfg = {
1898+session: {
1899+store: storePath,
1900+reset: { mode: "daily", atHour: 4, idleMinutes: 30 },
1901+},
1902+} as OpenClawConfig;
1903+const result = await initSessionState({
1904+ctx: { Body: "hello", SessionKey: sessionKey, Provider: "internal", Surface: "internal" },
1905+ cfg,
1906+commandAuthorized: true,
1907+requestedSessionId: "webchat-stale-session-id",
1908+resumeRequestedSession: true,
1909+});
1910+1911+expect(result.isNewSession).toBe(true);
1912+expect(result.sessionId).not.toBe(existingSessionId);
1913+});
1914+18201915it("drains stale system events when idle rollover creates a new session", async () => {
18211916vi.setSystemTime(new Date(2026, 0, 18, 5, 30, 0));
18221917const root = await makeCaseDir("openclaw-reset-idle-system-events-");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。