


























@@ -6170,6 +6170,205 @@ describe("runCodexAppServerAttempt", () => {
61706170expect(savedBinding?.threadId).toBe("thread-existing");
61716171});
617261726173+it("honors shorthand byte units for native rollout limits", async () => {
6174+const sessionFile = path.join(tempDir, "session.jsonl");
6175+const workspaceDir = path.join(tempDir, "workspace");
6176+const agentDir = path.join(tempDir, "agent");
6177+await writeExistingBinding(sessionFile, workspaceDir, { dynamicToolsFingerprint: "[]" });
6178+await fs.writeFile(
6179+path.join(path.dirname(sessionFile), "sessions.json"),
6180+JSON.stringify({
6181+"agent:main:session-1": {
6182+ sessionFile,
6183+totalTokens: 12_000,
6184+},
6185+}),
6186+);
6187+const rolloutDir = path.join(agentDir, "codex-home", "sessions");
6188+await fs.mkdir(rolloutDir, { recursive: true });
6189+await fs.writeFile(path.join(rolloutDir, "rollout-thread-existing.jsonl"), "x".repeat(2_000));
6190+6191+const binding = await __testing.rotateOversizedCodexAppServerStartupBinding({
6192+binding: { threadId: "thread-existing", workspaceDir },
6193+ sessionFile,
6194+ agentDir,
6195+config: {
6196+agents: {
6197+defaults: {
6198+compaction: {
6199+truncateAfterCompaction: true,
6200+maxActiveTranscriptBytes: "1k",
6201+},
6202+},
6203+},
6204+} as never,
6205+});
6206+6207+expect(binding).toBeUndefined();
6208+const savedBinding = await readCodexAppServerBinding(sessionFile);
6209+expect(savedBinding).toBeUndefined();
6210+});
6211+6212+it("uses current rollout token usage before cumulative usage", async () => {
6213+const sessionFile = path.join(tempDir, "session.jsonl");
6214+const workspaceDir = path.join(tempDir, "workspace");
6215+const agentDir = path.join(tempDir, "agent");
6216+await writeExistingBinding(sessionFile, workspaceDir, { dynamicToolsFingerprint: "[]" });
6217+await fs.writeFile(
6218+path.join(path.dirname(sessionFile), "sessions.json"),
6219+JSON.stringify({
6220+"agent:main:session-1": {
6221+ sessionFile,
6222+totalTokens: 12_000,
6223+},
6224+}),
6225+);
6226+const rolloutDir = path.join(agentDir, "codex-home", "sessions");
6227+await fs.mkdir(rolloutDir, { recursive: true });
6228+await fs.writeFile(
6229+path.join(rolloutDir, "rollout-thread-existing.jsonl"),
6230+`${JSON.stringify({
6231+ payload: {
6232+ type: "token_count",
6233+ info: {
6234+ total_token_usage: {
6235+ total_tokens: 70_000,
6236+ },
6237+ last_token_usage: {
6238+ total_tokens: 12_000,
6239+ },
6240+ },
6241+ },
6242+ })}\n`,
6243+);
6244+6245+const binding = await __testing.rotateOversizedCodexAppServerStartupBinding({
6246+binding: { threadId: "thread-existing", workspaceDir },
6247+ sessionFile,
6248+ agentDir,
6249+config: {
6250+agents: {
6251+defaults: {
6252+compaction: {
6253+truncateAfterCompaction: true,
6254+maxActiveTranscriptBytes: "1mb",
6255+},
6256+},
6257+},
6258+} as never,
6259+});
6260+6261+expect(binding?.threadId).toBe("thread-existing");
6262+const savedBinding = await readCodexAppServerBinding(sessionFile);
6263+expect(savedBinding?.threadId).toBe("thread-existing");
6264+});
6265+6266+it("ignores stale session token totals for native rollout rotation", async () => {
6267+const sessionFile = path.join(tempDir, "session.jsonl");
6268+const workspaceDir = path.join(tempDir, "workspace");
6269+const agentDir = path.join(tempDir, "agent");
6270+await writeExistingBinding(sessionFile, workspaceDir, { dynamicToolsFingerprint: "[]" });
6271+await fs.writeFile(
6272+path.join(path.dirname(sessionFile), "sessions.json"),
6273+JSON.stringify({
6274+"agent:main:session-1": {
6275+ sessionFile,
6276+totalTokens: 70_000,
6277+totalTokensFresh: false,
6278+},
6279+}),
6280+);
6281+const rolloutDir = path.join(agentDir, "codex-home", "sessions");
6282+await fs.mkdir(rolloutDir, { recursive: true });
6283+await fs.writeFile(
6284+path.join(rolloutDir, "rollout-thread-existing.jsonl"),
6285+`${JSON.stringify({
6286+ payload: {
6287+ type: "token_count",
6288+ info: {
6289+ last_token_usage: {
6290+ total_tokens: 12_000,
6291+ },
6292+ },
6293+ },
6294+ })}\n`,
6295+);
6296+6297+const binding = await __testing.rotateOversizedCodexAppServerStartupBinding({
6298+binding: { threadId: "thread-existing", workspaceDir },
6299+ sessionFile,
6300+ agentDir,
6301+config: {
6302+agents: {
6303+defaults: {
6304+compaction: {
6305+truncateAfterCompaction: true,
6306+maxActiveTranscriptBytes: "1mb",
6307+},
6308+},
6309+},
6310+} as never,
6311+});
6312+6313+expect(binding?.threadId).toBe("thread-existing");
6314+const savedBinding = await readCodexAppServerBinding(sessionFile);
6315+expect(savedBinding?.threadId).toBe("thread-existing");
6316+});
6317+6318+it("streams rollout token scans without reading the whole file", async () => {
6319+const sessionFile = path.join(tempDir, "session.jsonl");
6320+const workspaceDir = path.join(tempDir, "workspace");
6321+const agentDir = path.join(tempDir, "agent");
6322+await writeExistingBinding(sessionFile, workspaceDir, { dynamicToolsFingerprint: "[]" });
6323+await fs.writeFile(
6324+path.join(path.dirname(sessionFile), "sessions.json"),
6325+JSON.stringify({
6326+"agent:main:session-1": {
6327+ sessionFile,
6328+totalTokens: 12_000,
6329+},
6330+}),
6331+);
6332+const rolloutDir = path.join(agentDir, "codex-home", "sessions");
6333+await fs.mkdir(rolloutDir, { recursive: true });
6334+const rolloutFile = path.join(rolloutDir, "rollout-thread-existing.jsonl");
6335+await fs.writeFile(
6336+rolloutFile,
6337+`${JSON.stringify({
6338+ payload: {
6339+ type: "token_count",
6340+ info: {
6341+ last_token_usage: {
6342+ total_tokens: 70_000,
6343+ },
6344+ },
6345+ },
6346+ })}\n`,
6347+);
6348+const readFileSpy = vi.spyOn(fs, "readFile");
6349+6350+const binding = await __testing.rotateOversizedCodexAppServerStartupBinding({
6351+binding: { threadId: "thread-existing", workspaceDir },
6352+ sessionFile,
6353+ agentDir,
6354+config: {
6355+agents: {
6356+defaults: {
6357+compaction: {
6358+truncateAfterCompaction: true,
6359+maxActiveTranscriptBytes: "1mb",
6360+},
6361+},
6362+},
6363+} as never,
6364+});
6365+6366+expect(binding).toBeUndefined();
6367+expect(readFileSpy.mock.calls.some(([file]) => file === rolloutFile)).toBe(false);
6368+const savedBinding = await readCodexAppServerBinding(sessionFile);
6369+expect(savedBinding).toBeUndefined();
6370+});
6371+61736372it("clears byte-oversized rollouts before reading their contents", async () => {
61746373const sessionFile = path.join(tempDir, "session.jsonl");
61756374const workspaceDir = path.join(tempDir, "workspace");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。