Skip to content

feat(cli): add optional [HH:MM:SS] timestamp before each assistant turn - #5001

Merged
yiliang114 merged 1 commit into
QwenLM:mainfrom
ZijianZhang989:feat/response-timestamps
Jun 22, 2026
Merged

feat(cli): add optional [HH:MM:SS] timestamp before each assistant turn#5001
yiliang114 merged 1 commit into
QwenLM:mainfrom
ZijianZhang989:feat/response-timestamps

Conversation

@ZijianZhang989

@ZijianZhang989 ZijianZhang989 commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds an optional output.showTimestamps setting that renders a [HH:MM:SS] timestamp before each assistant response in the CLI. The timestamp appears immediately when the model starts outputting, not after the response completes. The implementation uses a commitItem wrapper around addItem in useGeminiStream to attach Date.now() to gemini type items, including the split-code path that previously bypassed timestamp assignment. Only the first item of each assistant turn gets a timestamp; gemini_content items (performance-split continuations) do not, preventing duplicate timestamps within the same turn.

Why it's needed

Users requested the ability to see when each assistant response was generated, similar to Claude Code's turn duration display. This helps with debugging, logging, and understanding the temporal flow of conversations. The feature is opt-in (default off) to avoid cluttering the UI for users who don't need it.

Reviewer Test Plan

How to verify

  1. Run npm run dev
  2. Open settings: /settings
  3. Navigate to outputshowTimestamps and enable it
  4. Ask a simple question — should see [HH:MM:SS] appear immediately when the model starts responding
  5. Ask a question that triggers tool calls — should see one timestamp per assistant turn
  6. Disable showTimestamps in settings — next response should not have timestamp, no restart needed

Evidence (Before & After)

Will provide video recording.

Tested on

OS Status
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

Tested with npm run dev on macOS 14.5, Node.js v22.

Risk & Scope

  • Main risk or tradeoff: Adds a new UI element that may clutter the display for users who enable it. The commitItem wrapper adds minimal overhead (~1 function call per item commit).
  • Not validated / out of scope: Windows and Linux testing. Subagent responses (they use a different rendering path). Non-interactive output modes.
  • Breaking changes / migration notes: None. The setting defaults to false, so existing users see no change. Settings are automatically persisted to ~/.qwen/settings.json.

Linked Issues

Refs #4899

中文说明

这个 PR 做了什么

添加了一个可选的 output.showTimestamps 设置,在 CLI 的每个助手回复前渲染一个 [HH:MM:SS] 时间戳。时间戳在模型开始输出时立即显示,而不是在响应完成后才显示。实现在 useGeminiStream 中使用 commitItem 包装器来包装 addItem,将 Date.now() 附加到 gemini 类型的 item 上,包括之前会绕过时间戳分配的 split 代码路径。只有每个助手 turn 的第一个 item 会获得时间戳;gemini_content items(性能分割的延续)不会,防止同一个 turn 内出现重复的时间戳。

为什么需要它

用户希望看到每个助手响应的生成时间,类似于 Claude Code 的 turn duration 显示。这有助于调试、记录日志和理解对话的时间流动。该功能是可选的(默认关闭),避免给不需要的用户造成 UI 混乱。

审阅者测试计划

如何验证

  1. 打开设置:/settings
  2. 导航到 outputshowTimestamps 并启用它
  3. 问一个简单的问题 — 应该看到 [HH:MM:SS] 在模型开始响应时立即出现
  4. 问一个会触发工具调用的问题 — 应该看到每个助手 turn 一个时间戳
  5. 在设置中禁用 showTimestamps — 下次回复时间戳应该消失,无需重启

证据(前后对比)

见视频

已测试平台

操作系统 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

在 macOS 14.5, Node.js v22 测试。

风险与范围

  • 主要风险或权衡: 添加了一个新的 UI 元素,可能会给启用它的用户造成显示混乱。commitItem 包装器增加了最小的开销(每个 item 提交约 1 次函数调用)。
  • 未验证 / 超出范围: Windows 和 Linux 测试。子代理响应(它们使用不同的渲染路径)。非交互式输出模式。
  • 破坏性更改 / 迁移说明: 无。设置默认为 false,所以现有用户看不到任何变化。设置会自动持久化到 ~/.qwen/settings.json

关联的 Issues

Refs #4899

Comment thread packages/cli/src/ui/components/HistoryItemDisplay.tsx
Comment thread packages/cli/src/ui/hooks/useGeminiStream.ts
@ZijianZhang989

Copy link
Copy Markdown
Collaborator Author
_2026-06-11.193125.mp4

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Review (qwen3-coder-plus)

Verdict: COMMENT — CI is broken due to a TypeScript type error. One high-confidence finding below.

Previously reported issues — status

  1. Timestamp overwrite bugFixed in commit 32fe709. The commitItem guard now checks !(item as HistoryItemGemini).timestamp before assigning Date.now(), preserving the turn-start time set by setPendingHistoryItem.

  2. isPending guardResolved by design decision in commit 32fe709. The test was updated to expect timestamps during streaming (isPending=true). This is intentional — the timestamp marks when the turn started, visible immediately as the model streams.

New finding

See inline comment below.

Comment thread packages/cli/src/ui/hooks/useGeminiStream.ts Outdated
const afterText = newGeminiMessageBuffer.substring(splitPoint);
addItem(
commitItem(
{

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The split path constructs {type, text: beforeText} without propagating the timestamp from pendingHistoryItemRef.current. Since commitItem only stamps when !timestamp, the split chunk gets Date.now() at split time rather than the original turn-start time.

The no-split path correctly preserves the timestamp via:

...(item && 'timestamp' in item ? { timestamp: item.timestamp } : {})

For long streaming responses that trigger splits, the displayed [HH:MM:SS] will reflect the split time, not when the assistant began responding.

Suggested change
{
commitItem(
{
type: pendingHistoryItemRef.current?.type as
| 'gemini'
| 'gemini_content',
text: beforeText,
...(pendingHistoryItemRef.current && 'timestamp' in pendingHistoryItemRef.current
? { timestamp: (pendingHistoryItemRef.current as HistoryItemGemini).timestamp }
: {}),
},
userMessageTimestamp,
);

— qwen3.7-max via Qwen Code /review

DragonnZhang
DragonnZhang previously approved these changes Jun 11, 2026

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review after fix for TS2345 type error (previously reported at 9eebd50).

Summary

The previously reported TypeScript type error in setPendingHistoryItem updater has been fixed in commit d9fc397. The fix uses explicit type assertion (HistoryItemWithoutId base with as HistoryItemGemini for timestamp propagation) instead of object spread, avoiding the incompatible return type.

Verification

  • TypeScript: No type errors in the changed files. tsc --noEmit passes cleanly (only pre-existing TS6305 build-artifact warnings).
  • Tests: All 18 HistoryItemDisplay tests and all 103 useGeminiStream tests pass on CI.
  • CI note: The ubuntu-latest SessionPreview.test.tsx failures (5/6 tests) are unrelated to this PR -- that component is not touched by the diff.

Code review

  • commitItem wrapper correctly attaches Date.now() only to gemini items without an existing timestamp, preserving the turn-start time from setPendingHistoryItem.
  • setPendingHistoryItem updater correctly carries forward the timestamp field during content accumulation.
  • Dependency arrays in all useCallback hooks that use commitItem are properly maintained.
  • The gemini_content split path correctly excludes timestamps to prevent duplicate display within a single turn.
  • HistoryItemDisplay rendering logic correctly guards on both showTimestamps setting and non-null timestamp.

No high-confidence issues found.

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅ — qwen3.7-max via Qwen Code /review

wenshao
wenshao previously approved these changes Jun 13, 2026

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅ — qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

@ZijianZhang989 heads up — this PR currently has merge conflicts with main and can't be merged as-is. Could you merge main in (or rebase) and resolve them when you get a chance?

Conflicting files:

  • packages/cli/src/ui/components/HistoryItemDisplay.tsx

The rest merges cleanly. Thanks!

中文

@ZijianZhang989 提个醒 —— 这个 PR 目前和 main 有合并冲突,暂时没法直接合入。方便的时候麻烦把最新的 main merge 进来(或 rebase)解决一下冲突。

冲突文件:

  • packages/cli/src/ui/components/HistoryItemDisplay.tsx

其余文件可以自动合并。谢谢!

@ZijianZhang989
ZijianZhang989 dismissed stale reviews from wenshao and qwen-code-ci-bot via 84decbd June 15, 2026 02:30
@ZijianZhang989
ZijianZhang989 force-pushed the feat/response-timestamps branch from e5e0826 to 84decbd Compare June 15, 2026 02:30
@ZijianZhang989

Copy link
Copy Markdown
Collaborator Author

Rebased onto latest main. Resolved one conflict in HistoryItemDisplay.tsx — the upstream removed the isHiddenInCompact intermediate variable, so I followed upstream semantics and only kept the new useSettings / showTimestamps additions.

E2E verified:

  • showTimestamps: true[10:18:11] timestamp appears before assistant turn
  • showTimestamps: false (default) → no timestamp shown

No functional changes to the feature itself.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Qwen Code review did not complete successfully: Qwen review aborted with an API error before posting comments. See workflow logs.

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean timestamp feature: showTimestamps setting (default false) renders [HH:MM:SS] before assistant responses using toLocaleTimeString('en-US', {hour12: false}). Good test coverage (4 tests: disabled, enabled, streaming, missing timestamp). useSettings integration is correct. SessionPreview tests refactored to use renderWithProviders. CI green on tests, but review-pr workflow check is failing. Downgraded from Approve to Comment: CI review-pr check failing. — claude-opus-4-6 via Qwen Code /review

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] convertToHistoryItems in resumeHistoryUtils.ts:385 creates gemini items as { type: 'gemini', text } without propagating record.timestamp. When showTimestamps is enabled, resumed sessions will show timestamps only on new messages — historical assistant turns render without timestamps, creating an inconsistent experience within the same conversation view.

Suggested fix: propagate the persisted timestamp:

items.push({
  type: 'gemini',
  text,
  timestamp: new Date(record.timestamp).getTime(),
});

— qwen3.7-max via Qwen Code /review

@@ -2673,10 +2673,10 @@ describe('useGeminiStream', () => {
});

expect(mockAddItem).toHaveBeenCalledWith(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The only test changes for commitItem are relaxed assertions (expect.objectContaining) to accommodate the new timestamp field. There are no positive tests verifying that commitItem actually attaches a timestamp to gemini items, leaves non-gemini items (gemini_content, info, tool_group) untouched, or preserves a pre-existing timestamp via the !timestamp guard.

Consider adding dedicated tests that drive the stream through a gemini text event and assert mockAddItem was called with an item containing a numeric timestamp, and a test that commits a non-gemini item and asserts no timestamp was added.

— qwen3.7-max via Qwen Code /review

const commitItem = useCallback(
(item: HistoryItemWithoutId, userMessageTimestamp: number): number => {
if (item.type === 'gemini' && !(item as HistoryItemGemini).timestamp) {
(item as HistoryItemGemini).timestamp = Date.now();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] commitItem mutates item in place ((item as HistoryItemGemini).timestamp = Date.now()) before passing it to addItem. Since the argument is pendingHistoryItemRef.current — a shared ref object — this is a side-effect on a React-managed object outside the state setter. While benign today (callers null the ref immediately after), it creates a hidden mutation contract that future refactors could break.

Consider cloning before augmenting:

if (item.type === 'gemini' && !(item as HistoryItemGemini).timestamp) {
  return addItem({ ...item, timestamp: Date.now() }, userMessageTimestamp);
}
return addItem(item, userMessageTimestamp);

— qwen3.7-max via Qwen Code /review

@yiliang114

Copy link
Copy Markdown
Collaborator

The feature itself looks good and the earlier review rounds already cleaned up the timestamp-overwrite and TS2345 issues, so no code concerns from me.

One blocker before this can merge: the conflict has moved. HistoryItemDisplay.tsx merges cleanly now after your rebase, but main advanced again and the current conflict is in packages/cli/src/ui/hooks/useGeminiStream.ts (mergeable: CONFLICTING still). Could you rebase onto latest main once more and resolve that file?

Non-blocking — Closes #4899 will auto-close the issue, but #4899 also asks for optionally feeding the timestamp to the model for elapsed-time reasoning, which this PR doesn't cover. Might be worth switching to Refs #4899 and leaving the model-awareness part as a follow-up, so that half doesn't get lost.

@ZijianZhang989
ZijianZhang989 force-pushed the feat/response-timestamps branch 2 times, most recently from 20a7e15 to f8abb5d Compare June 17, 2026 09:20
@yiliang114

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

On direction: Showing when each assistant turn was generated is a real user need — debugging, logging, understanding temporal flow. Claude Code's changelog has related timestamp features (transcript timestamps, Ctrl-r timestamps, memory file timestamps), so this area is well-aligned with CLI assistant tooling. No concerns here.

On approach: The scope is tight and focused. commitItem as a wrapper around addItem is a clean way to centralize timestamp attachment without touching addItem's generic signature. The SessionPreview.test.tsx migration from render + KeypressProvider to renderWithProviders is necessary (not drive-by refactoring) — SessionPreview renders HistoryItemDisplay, which now calls useSettings() (requiring SettingsProvider). All 7 tests have been migrated, including the one that was missed in the prior triage. ✅

Merge status: MERGEABLE, no conflicts. CI all green (9 passing, 4 skipped).

中文说明

感谢贡献!

模板完整 ✓

方向:在每个助手 turn 前显示生成时间是一个真实的用户需求——调试、日志记录、理解时间流。Claude Code 的 CHANGELOG 里有相关的 timestamp 功能(transcript 时间戳、Ctrl-r 时间戳、memory 文件时间戳),所以这个方向跟 CLI 助手工具的发展路线一致。没有顾虑。

方案:范围紧凑聚焦。commitItem 作为 addItem 的包装器是集中 timestamp 附加逻辑的干净方式,不需要修改 addItem 的通用签名。SessionPreview.test.tsxrender + KeypressProvider 迁移到 renderWithProviders 是必要的(不是顺手重构)——SessionPreview 渲染了 HistoryItemDisplay,后者现在调用了 useSettings()(需要 SettingsProvider)。全部 7 个测试已迁移完成,包括上次 triage 遗漏的那个。✅

合并状态:可合并 (MERGEABLE),无冲突。CI 全绿(9 通过,4 跳过)。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

qwen-code-ci-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal: To add per-turn timestamps, I'd add an optional timestamp field to HistoryItemGemini, a showTimestamps setting in the schema, capture Date.now() when creating each assistant turn in useGeminiStream, and render the timestamp in HistoryItemDisplay when the setting is on.

Comparison: The PR's approach matches this exactly. The commitItem wrapper is a clean interception point for all addItem calls without modifying the shared function. The guard !(item as HistoryItemGemini).timestamp prevents overwriting pre-existing timestamps (important for the cancel-flush path where an item may already carry one). Test assertion updates (expect.objectContaining) are necessary and correct.

The setPendingHistoryItem functional update that preserves the timestamp across state updates is the right pattern — avoids the stale-closure pitfall of reading timestamp from a non-functional update.

No correctness, security, or convention issues found.

Testing

Unit Tests

  • HistoryItemDisplay.test.tsx: 24/24 ✅ (including 4 new timestamp tests)
  • SessionPreview.test.tsx: 7/7 ✅ (all migrated to renderWithProviders — previous blocker resolved)

TUI Test (tmux interactive, fake OpenAI server)

showTimestamps enabled (settings.json: {"output":{"showTimestamps":true}}):

  > Say hello in one word
  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

  [06:24:08]
  ✦ Hello! This is a test response for timestamp triage.

Timestamp [06:24:08] renders correctly before the assistant response, exactly as described. Appears immediately when the model starts outputting.

showTimestamps disabled (settings.json: {"output":{"showTimestamps":false}}):

  > Say hello in one word
  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

  ✦ Hello! This is a test response for timestamp triage.

No timestamp — confirms the setting works correctly in both directions.

中文说明

代码审查

独立方案: 要添加每个 turn 的时间戳,我会在 HistoryItemGemini 上加一个可选的 timestamp 字段,在 schema 里加 showTimestamps 设置,在 useGeminiStream 创建每个助手 turn 时捕获 Date.now(),然后在 HistoryItemDisplay 里根据设置渲染时间戳。

对比: PR 的方案完全匹配。commitItem 包装器是拦截所有 addItem 调用的干净方式。!(item as HistoryItemGemini).timestamp 的守卫防止覆盖已有的时间戳(这在 cancel-flush 路径中很重要,因为 item 可能已携带时间戳)。测试断言更新(expect.objectContaining)是必要且正确的。

setPendingHistoryItem 的函数式更新保留了跨状态更新的时间戳——避免了非函数式更新中的过时闭包陷阱。

没有发现正确性、安全性或规范问题。

测试

单元测试

  • HistoryItemDisplay.test.tsx:24/24 ✅(包括 4 个新的 timestamp 测试)
  • SessionPreview.test.tsx7/7 ✅(全部迁移到 renderWithProviders——之前的阻塞项已解决)

TUI 测试(tmux 交互模式,fake OpenAI 服务器)

showTimestamps 启用 (settings.json: {"output":{"showTimestamps":true}}):

  > Say hello in one word

  [06:24:08]
  ✦ Hello! This is a test response for timestamp triage.

时间戳 [06:24:08] 在助手回复前正确渲染,与 PR 描述完全一致。模型开始输出时立即出现。

showTimestamps 禁用 (settings.json: {"output":{"showTimestamps":false}}):

  > Say hello in one word

  ✦ Hello! This is a test response for timestamp triage.

没有时间戳——确认设置在两个方向都正确工作。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

qwen-code-ci-bot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Reflection

Stepping back: this PR does one thing well — adds optional [HH:MM:SS] timestamps before assistant turns. The implementation matches what I'd have done independently. The commitItem wrapper is the right level of indirection, the setting is opt-in with a sensible default, and both the unit tests and tmux interactive tests confirm it works correctly in both directions.

The one blocker from the prior triage — the unmigrated SessionPreview.test.tsx test — has been fixed. All 7 tests now use renderWithProviders. CI is green across the board (9 passing, 4 skipped). The merge conflicts that blocked earlier reviews are resolved; the PR is MERGEABLE.

The diff is minimal and focused: 8 files changed, 240 additions, 111 deletions. Every change serves the stated goal. The SessionPreview.test.tsx migration is a necessary side-effect (not scope creep), the VS Code schema update keeps settings in sync, and the type/test changes are exactly what the feature requires.

Verdict: Approve — the previous blocker is resolved, all tests pass, the TUI behavior matches the description. Ready to ship. ✅ @ZijianZhang989

中文说明

总结

退一步看:这个 PR 把一件事做好了——在助手 turn 前添加可选的 [HH:MM:SS] 时间戳。实现方式跟我的独立方案一致。commitItem 包装器是正确层次的间接调用,设置项是 opt-in 且有合理默认值,单元测试和 tmux 交互测试都确认两个方向能正常工作。

上次 triage 的阻塞项——未迁移的 SessionPreview.test.tsx 测试——已修复。全部 7 个测试现在使用 renderWithProviders。CI 全绿(9 通过,4 跳过)。之前阻塞的合并冲突已解决;PR 可以合并 (MERGEABLE)。

diff 精简且聚焦:8 个文件变更,240 行增加,111 行删除。每个变更都服务于目标。SessionPreview.test.tsx 迁移是必要的副作用(不是范围蔓延),VS Code schema 更新保持设置同步,类型/测试变更正好满足功能需求。

结论: 批准——之前的阻塞项已解决,所有测试通过,TUI 行为与描述一致。可以合入。✅ @ZijianZhang989

Qwen Code · qwen3.7-max

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — feature works as described, tests pass, tmux confirms timestamp rendering. One minor ask: consider splitting the SessionPreview.test.tsx refactoring into a separate PR to keep this one focused. ✅

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No review findings. Downgraded from Approve to Comment: CI failing: Lint. — qwen3.7-max via Qwen Code /review

@ZijianZhang989
ZijianZhang989 force-pushed the feat/response-timestamps branch from 33d9a8a to 85fae9a Compare June 17, 2026 11:28

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] convertToHistoryItems in resumeHistoryUtils.ts:384 pushes { type: 'gemini', text } without a timestamp field. With showTimestamps enabled, resumed sessions will silently have no timestamps on historical turns. Consider documenting this limitation in the setting's description.

[Suggestion] restoreHistoryItem in resumeHistoryUtils.ts:119 converts timestamps to Date objects (clone['timestamp'] = new Date(ts)) but HistoryItemGemini.timestamp is typed as number. Currently works because new Date(dateObj) handles both, but any future arithmetic on timestamp would produce wrong results. Consider normalizing to number: clone['timestamp'] = typeof ts === 'string' ? new Date(ts).getTime() : ts;

— qwen3.7-max via Qwen Code /review

<>
{showTimestamps && itemForDisplay.timestamp != null && (
<Text dimColor>
[

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] toLocaleTimeString('en-US', { hour12: false }) doesn't guarantee the HH:MM:SS format across all Node.js/ICU builds. Some ICU versions produce 9:05:30 instead of 09:05:30 for single-digit hours.

The codebase already has the correct pattern at demo.ts:202:

Suggested change
[
{new Date(itemForDisplay.timestamp).toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})}

— qwen3.7-max via Qwen Code /review

{ settings: makeTimestampSettings() },
);
expect(lastFrame()).toMatch(/\[\d{2}:\d{2}:\d{2}\]/);
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The test fixture hardcodes timestamp: new Date('2026-01-15T14:30:45').getTime() but the regex \[\d{2}:\d{2}:\d{2}\] only asserts format, not value. A bug rendering the wrong time (e.g., Date.now() instead of item.timestamp) would pass undetected.

Pin the assertion to the expected value:

// Using UTC timestamp for deterministic assertion:
expect(lastFrame()).toContain('[14:30:45]');
// Or derive from fixture:
const expected = new Date('2026-01-15T14:30:45').toLocaleTimeString('en-US', { hour12: false });
expect(lastFrame()).toContain(`[${expected}]`);

— qwen3.7-max via Qwen Code /review

export type HistoryItemGemini = HistoryItemBase & {
type: 'gemini';
text: string;
timestamp?: number;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Placing timestamp?: number only on HistoryItemGemini forces 'timestamp' in item checks and as HistoryItemGemini casts in the setPendingHistoryItem updater and split path. Moving it to HistoryItemBase would simplify those call sites — the updater becomes { type, text, timestamp: item?.timestamp } with no casts.

— qwen3.7-max via Qwen Code /review

yiliang114
yiliang114 previously approved these changes Jun 17, 2026

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The earlier timestamp-overwrite and TS2345 fixes hold up, the conflict is resolved, and the current head passes the full CI matrix (lint + tests on all three OS + CodeQL).

@wenshao
wenshao requested a review from chiga0 June 17, 2026 19:39
@wenshao

wenshao commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts in this pull request

@ZijianZhang989
ZijianZhang989 force-pushed the feat/response-timestamps branch 2 times, most recently from b697240 to bbf0095 Compare June 22, 2026 03:24
@yiliang114

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reflection

Stepping back: this PR does one thing well — adds optional [HH:MM:SS] timestamps before assistant turns. The implementation matches what I'd have done independently. The commitItem wrapper is the right level of indirection, the setting is opt-in with a sensible default, and the tmux tests confirm it works in both directions.

The one issue from the prior triage has been corrected: the SessionPreview.test.tsx migration is necessary (not drive-by refactoring), but it's incomplete — one test was missed and now fails. The fix is a one-line change: wrap that test in renderWithProviders instead of render + KeypressProvider.

The merge conflicts that blocked the prior triage are now resolved. The PR is MERGEABLE from a git perspective, just needs this test fix.

Verdict: Request changes — fix the one unmigrated test in SessionPreview.test.tsx (line 116–137), then this is ready to ship. @ZijianZhang989

中文说明

总结

退一步看:这个 PR 把一件事做好了——在助手 turn 前添加可选的 [HH:MM:SS] 时间戳。实现方式跟我的独立方案一致。commitItem 包装器是正确层次的间接调用,设置项是 opt-in 且有合理默认值,tmux 测试确认两个方向都能正常工作。

上次 triage 的一个判断已纠正:SessionPreview.test.tsx 迁移是必要的(不是顺手重构),但不完整——有一个测试被遗漏了,现在会失败。修复很简单:把那个测试用 renderWithProviders 包装替代 render + KeypressProvider

上次 triage 的合并冲突已经解决。从 git 角度看 PR 已经可以合并 (MERGEABLE),只需要修复这个测试。

结论: 请求修改——修复 SessionPreview.test.tsx 中一个未迁移的测试(第 116–137 行),然后就可以合入了。@ZijianZhang989

Qwen Code · qwen3.7-max

@ZijianZhang989
ZijianZhang989 force-pushed the feat/response-timestamps branch from 6cf50a5 to 78555df Compare June 22, 2026 04:46
@ZijianZhang989
ZijianZhang989 force-pushed the feat/response-timestamps branch from 78555df to 076071e Compare June 22, 2026 04:48
@yiliang114

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new review findings on this pass — the split-path timestamp propagation concern was already captured in prior bot comments on this PR. Downgraded from Approve to Comment: CI still running. Two additional low-confidence observations surfaced for human review: (1) useGeminiStream.test.tsx has no positive test verifying commitItem attaches a timestamp to gemini items (assertions were relaxed to expect.objectContaining without a corresponding positive assertion), and (2) convertToHistoryItems in resumeHistoryUtils.ts omits timestamp on resumed gemini items even though record.timestamp is in scope — resumed sessions will silently show no timestamps on historical turns when showTimestamps is enabled. Lint, typecheck, and 159/159 tests pass locally. — qwen3.7-max via Qwen Code /review

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — previous blocker (unmigrated SessionPreview test) is resolved, all tests pass (7/7 SessionPreview, 24/24 HistoryItemDisplay), and tmux interactive testing confirms timestamps render correctly when enabled and are absent when disabled. Ready to ship. ✅

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@yiliang114
yiliang114 merged commit 78a7b40 into QwenLM:main Jun 22, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants