From c1e3e3bf8df558e3d33ad7c1fb856490459fb4b0 Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 16 Sep 2026 05:38:11 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=20Direct=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B0=83=E7=94=A8=E6=97=B6=E9=97=B4=E6=88=B3=E4=B8=BA?= =?UTF-8?q?=E6=AF=AB=E7=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在前端模型入口兼容 Unix 秒时间戳并统一为毫秒 保持耗时展示使用秒和分钟 补充时间戳归一化回归测试 --- apps/ai-game-creator-shell/src/App.tsx | 3 +++ .../features/project-workspace/directTurnPresentation.ts | 5 ++++- .../tests/directTurnPresentation.test.ts | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index 2438d17f8..ee075cfa5 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -244,6 +244,7 @@ import { type DirectThreadSubscriptionBootstrap, isDirectTurnInProgress, } from './features/project-workspace/directThreadEvents'; +import { normalizeDirectTimestamp } from './features/project-workspace/directTurnPresentation'; import type { DirectCodexUserContentPart } from './features/project-workspace/generated'; import { appendMemoryContent, @@ -1010,6 +1011,8 @@ export function App({ const normalized: GameCreatorDirectToolCall = { ...call, id, + startedAt: normalizeDirectTimestamp(call.startedAt), + updatedAt: normalizeDirectTimestamp(call.updatedAt), detail: call.detail ?? { changes: [] }, }; // 起点时间取更早的那个:`completed` 事件不一定带 startedAt。 diff --git a/apps/ai-game-creator-shell/src/features/project-workspace/directTurnPresentation.ts b/apps/ai-game-creator-shell/src/features/project-workspace/directTurnPresentation.ts index 217646a9f..2449331d5 100644 --- a/apps/ai-game-creator-shell/src/features/project-workspace/directTurnPresentation.ts +++ b/apps/ai-game-creator-shell/src/features/project-workspace/directTurnPresentation.ts @@ -26,7 +26,8 @@ export type DirectTurnPresentation = { endedAt: number; }; -export function directMessageTimestamp(value: number | undefined) { +/** 统一 Direct 时间戳为 Unix 毫秒;历史/异常 payload 可能传 Unix 秒。 */ +export function normalizeDirectTimestamp(value: number | undefined) { const timestamp = value && Number.isFinite(value) && value > 0 ? value < 100_000_000_000 @@ -36,6 +37,8 @@ export function directMessageTimestamp(value: number | undefined) { return Number.isFinite(new Date(timestamp).getTime()) ? timestamp : 0; } +export const directMessageTimestamp = normalizeDirectTimestamp; + /** 从唯一呈现来源分区,完成后只把最终回复及失败提示留在过程折叠区之外。 */ export function splitDirectTurnContent(turn: DirectTurnPresentation) { const assistants = turn.messages.filter( diff --git a/apps/ai-game-creator-shell/tests/directTurnPresentation.test.ts b/apps/ai-game-creator-shell/tests/directTurnPresentation.test.ts index 74d8c8426..f47f263a2 100644 --- a/apps/ai-game-creator-shell/tests/directTurnPresentation.test.ts +++ b/apps/ai-game-creator-shell/tests/directTurnPresentation.test.ts @@ -8,6 +8,7 @@ import type { import { buildDirectTurnPresentations, directMessageTimestamp, + normalizeDirectTimestamp, splitDirectTurnContent, } from '../src/features/project-workspace/directTurnPresentation'; @@ -58,6 +59,12 @@ const build = ( }); describe('DirectProject 回合唯一呈现', () => { + it('把 Unix 秒时间戳归一化为毫秒,已有毫秒值保持不变', () => { + expect(normalizeDirectTimestamp(1_800_000_000)).toBe(1_800_000_000_000); + expect(normalizeDirectTimestamp(1_800_000_000_000)).toBe(1_800_000_000_000); + expect(directMessageTimestamp(1_800_000_000)).toBe(1_800_000_000_000); + }); + it('历史仍有未加载切片时,不把那些回合的工具流追加到当前页末尾', () => { const rows = build( [user('one')],