Fix agent turn timing persistence

This commit is contained in:
Mohamed Boudra
2026-05-15 17:38:28 +07:00
parent 6cbe4e6a14
commit 160d861534
13 changed files with 443 additions and 233 deletions
@@ -1418,6 +1418,68 @@ describe("Codex app-server provider", () => {
]);
});
test("uses Codex turn timestamps for timestamp-less persisted history items", async () => {
const session = createSession();
session.client = {
request: vi.fn(async (method: string) => {
if (method !== "thread/read") {
return {};
}
return {
thread: {
turns: [
{
startedAt: 1_778_832_941,
completedAt: 1_778_833_094,
items: [
{
type: "userMessage",
id: "user-history",
content: [{ type: "text", text: "Check OpenCode timestamps." }],
},
{
type: "agentMessage",
id: "message-history",
text: "History loaded.",
},
],
},
],
},
};
}),
};
await asInternals(session).loadPersistedHistory();
const history: AgentStreamEvent[] = [];
for await (const event of session.streamHistory()) {
history.push(event);
}
expect(history).toEqual([
{
type: "timeline",
provider: "codex",
timestamp: "2026-05-15T08:15:41.000Z",
item: {
type: "user_message",
text: "Check OpenCode timestamps.",
},
},
{
type: "timeline",
provider: "codex",
timestamp: "2026-05-15T08:18:14.000Z",
item: {
type: "assistant_message",
text: "History loaded.",
messageId: "message-history",
},
},
]);
});
test("preserves Codex app-server assistant item ids in persisted history", async () => {
const session = createSession();
session.client = {
@@ -1462,6 +1462,28 @@ function readCodexHistoryTimestamp(item: unknown): string | null {
);
}
function readCodexTurnHistoryTimestamp(
turn: unknown,
timelineItem: AgentTimelineItem,
): string | null {
const record = toObjectRecord(turn);
if (!record) {
return null;
}
const startedAt =
normalizeProviderReplayTimestamp(record.startedAt) ??
normalizeProviderReplayTimestamp(record.started_at);
const completedAt =
normalizeProviderReplayTimestamp(record.completedAt) ??
normalizeProviderReplayTimestamp(record.completed_at);
if (timelineItem.type === "user_message") {
return startedAt ?? completedAt;
}
return completedAt ?? startedAt;
}
function codexImageOutputFromResult(result: unknown): ProviderImageOutput | null {
if (typeof result === "string") {
const trimmed = result.trim();
@@ -1616,7 +1638,8 @@ async function loadCodexThreadHistoryTimeline(params: {
for (const item of turn.items) {
const timelineItem = threadItemToTimeline(item, { cwd: params.cwd });
if (timelineItem) {
const timestamp = readCodexHistoryTimestamp(item);
const timestamp =
readCodexHistoryTimestamp(item) ?? readCodexTurnHistoryTimestamp(turn, timelineItem);
timeline.push({
item: timelineItem,
timestamp: timestamp ?? undefined,