Skip to content

fix: Session Messages 提升内容阈值并导出完整请求#537

Merged
ding113 merged 2 commits intodevfrom
fix/session-messages-content-limit
Jan 4, 2026
Merged

fix: Session Messages 提升内容阈值并导出完整请求#537
ding113 merged 2 commits intodevfrom
fix/session-messages-content-limit

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Jan 4, 2026

Summary

Enhance the Session Messages details page by raising the content display threshold and improving the request export functionality to include complete request headers and body.

Problem

Related PRs:

The previous implementation had limitations:

  1. Too aggressive content limit: The 1MB / 10,000 line threshold was too strict for debugging larger requests common in Claude Code sessions with extensive tool use
  2. Incomplete export: The copy/download buttons only exported messages field, missing valuable debugging context like request headers and full request body
  3. No recovery for large content: When content exceeded the hard limit, users couldn't download the actual content

Solution

1. Increased Content Threshold

  • Session detail tabs now allow content up to 5MB / 30,000 lines (configurable via maxContentBytes and maxLines props)
  • Default CodeDisplay limit remains 1MB / 10,000 lines for other use cases

2. Complete Request Export

  • Copy/download buttons now export full request JSON including:
    • sessionId - Session identifier
    • sequence - Request sequence number
    • meta - Request metadata (clientUrl, upstreamUrl, method)
    • headers - Complete request headers
    • body - Full request body
  • Filename format changed: session-{id}-seq-{n}-request.json

3. In-Panel Download for Hard-Limited Content

  • Added download button in "Content too large" warning panel
  • Users can download oversized content directly without external tools

4. UI/UX Improvements

  • Button labels updated across 5 locales (en, ja, ru, zh-CN, zh-TW)
  • Export buttons only shown when request data is available
  • Proper state reset on error conditions

Changes

Core Changes

File Description
session-details-tabs.tsx Pass 5MB/30k threshold to CodeDisplay components
session-messages-client.tsx Refactor export to include headers + body, fix state reset
code-display.tsx Add configurable limits, download button in hard-limit panel

Supporting Changes

File Description
messages/*/dashboard.json Update button labels (5 locales)
session-messages-client-actions.test.tsx New: 431 lines of action/export tests
session-messages-client.test.tsx Add threshold and download tests
code-display.test.tsx Add hard-limit download test

Technical Details

  • CodeDisplay now accepts optional maxContentBytes and maxLines props
  • Default limits (DEFAULT_MAX_CONTENT_BYTES, DEFAULT_MAX_LINES) preserved for backward compatibility
  • Content byte size calculated via new Blob([content]).size for accurate UTF-8 measurement
  • Export JSON structure designed for easy CLI debugging and issue reporting

Testing

Automated Tests

  • New session-messages-client-actions.test.tsx with comprehensive export flow tests
  • Extended session-messages-client.test.tsx for threshold validation
  • Extended code-display.test.tsx for download functionality
  • Target: >= 80% statement coverage for session-messages module

Verification Commands

bun run lint
bun run typecheck
DSN=... ADMIN_TOKEN=... REDIS_URL=... bun run test:coverage
bun run build

Manual Testing

  1. Send a request with large messages array (>10,000 items)
  2. Open Session details page
  3. Verify content displays without "Content too large" warning (up to 30,000 lines)
  4. Click "Copy Request" → verify JSON includes headers and body
  5. Click "Download Request" → verify file contains complete request
  6. For content >30,000 lines, verify in-panel download button works

Breaking Changes

None. Changes are backward compatible:

  • Default CodeDisplay limits unchanged
  • New props are optional with sensible defaults

Checklist

  • Code follows project conventions
  • Self-review completed
  • Tests pass locally
  • i18n translations updated (5 locales)

Description enhanced by Claude AI

Greptile Summary

This PR increases content handling thresholds and improves request export functionality for session messages.

Key Changes

  • Content thresholds increased: From 1MB/10k lines to 5MB/30k lines for session detail views
  • Export functionality enhanced: Top-level copy/download buttons now export complete request data (headers + body + meta + sequence) instead of just messages
  • Download capability added: Hard-limited content (exceeding thresholds) now provides an in-panel download button
  • Code improvements: Made CodeDisplay thresholds configurable via props, improved state cleanup in error paths, added auto-fallback from pretty to raw mode for very large JSON

Code Quality

  • Comprehensive test coverage added for all new features
  • Tests verify: threshold behavior, export JSON structure, sequence-based filenames, download functionality, and conditional button rendering
  • Proper resource cleanup in download handlers (URL revocation, DOM element removal)
  • All translations updated across 5 languages

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are well-tested with comprehensive unit tests achieving >= 80% coverage. The implementation follows established patterns, includes proper error handling and resource cleanup, and doesn't introduce breaking changes. All edge cases (missing data, oversized content, error states) are handled correctly.
  • No files require special attention

Important Files Changed

Filename Overview
src/components/ui/code-display.tsx Added configurable content thresholds (maxContentBytes/maxLines), improved pretty mode handling for large content, added download button for hard-limited content with proper cleanup
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx Increased content thresholds to 5MB/30000 lines for all CodeDisplay instances to handle larger session data
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx Refactored export buttons to export complete request (headers + body + meta), improved state cleanup in error paths, renamed variables for clarity

Sequence Diagram

sequenceDiagram
    participant User
    participant SessionMessagesClient
    participant getSessionDetails
    participant CodeDisplay
    participant Browser

    User->>SessionMessagesClient: Load session page
    SessionMessagesClient->>getSessionDetails: Fetch session data (sessionId, selectedSeq)
    getSessionDetails-->>SessionMessagesClient: Return requestBody, headers, messages, response, meta
    
    alt Export Request
        User->>SessionMessagesClient: Click Copy/Download Request button
        SessionMessagesClient->>SessionMessagesClient: Build request JSON (headers + body + meta + sequence)
        alt Copy
            SessionMessagesClient->>Browser: navigator.clipboard.writeText(JSON)
            Browser-->>User: Request copied to clipboard
        else Download
            SessionMessagesClient->>Browser: Create blob & trigger download
            Browser-->>User: Download request.json file
        end
    end

    alt View Content
        SessionMessagesClient->>CodeDisplay: Render content (maxContentBytes: 5MB, maxLines: 30000)
        alt Content within limits
            CodeDisplay->>CodeDisplay: Show pretty/raw mode with search
            CodeDisplay-->>User: Display formatted content
        else Content exceeds limits
            CodeDisplay->>CodeDisplay: Show "Content too large" message
            CodeDisplay-->>User: Display error with download button
            User->>CodeDisplay: Click download button
            CodeDisplay->>Browser: Create blob & trigger download
            Browser-->>User: Download content file
        end
    end
Loading

- Session Messages 详情页 Content too large 阈值调整为 5MB / 30000 行\n- 下载/复制按钮改为导出完整请求头 + 请求体\n- Content too large 提示框支持直接下载请求体 JSON(request.json)\n- 补齐 CodeDisplay 与 Session Messages 相关单元测试(模块语句覆盖率 >= 80%)
@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

更新了多语言本地化文本以明确“复制/下载请求(含头与体)”,在 CodeDisplay 中引入可配置的内容大小/行数限制并提供超限下载,重构会话消息导出为请求导出,并添加/扩展相关单元测试覆盖。

Changes

内容分组 / 文件(s) 变更摘要
本地化(操作标签与硬限制文案)
messages/en/dashboard.json, messages/ja/dashboard.json, messages/ru/dashboard.json, messages/zh-CN/dashboard.json, messages/zh-TW/dashboard.json
更新 copyMessages / downloadMessages 文本以明确为“请求(头 + 体)”,并在 codeDisplay/sseData 中新增 hardLimit 对象(包含 title, size, maximum, hint, download)用于超大内容提示与下载文案。
会话详情标签组件
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
新增常量 SESSION_DETAILS_MAX_CONTENT_BYTESSESSION_DETAILS_MAX_LINES,并将 maxContentBytesmaxLines 传入所有 CodeDisplay 实例以应用限制。
会话消息客户端逻辑
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
将导出/复制流从“消息”重命名为“请求”:替换 copiedMessagescopiedRequest,新增 resetDetailsStatecanExportRequestgetRequestExportJsonhandleCopyRequesthandleDownloadRequest 等,导出文件名包含 session-{id}-seq-{n}-request.json,并据条件控制导出按钮显示。
客户端测试(行为与导出覆盖)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx, src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
新增/扩展大量测试,覆盖导出(包含 headers/body)、URL seq 覆盖、blob 创建与下载锚点、剪贴板、错误路径、导航与终止流程,以及大载荷硬限制与面内下载行为。
CodeDisplay 组件与测试
src/components/ui/code-display.tsx, src/components/ui/__tests__/code-display.test.tsx
CodeDisplayProps 添加可选 maxContentBytes?maxLines?,引入默认限制常量、使用 Blob 计算字节数、按限值决定 pretty/raw 模式与 SSE/格式化渲染;超限时显示大小/上限信息并提供下载按钮。测试增加对超大内容下载、URL.createObjectURL/ revoke 与锚点点击的断言。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 标题清晰总结了主要变更:提升内容阈值和导出完整请求,与代码变更内容相符。
Description check ✅ Passed 描述详细阐述了问题、解决方案、变更内容和测试验证,与代码变更高度相关。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/session-messages-content-limit

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between bd98cce and 3c0e216.

📒 Files selected for processing (10)
  • messages/en/dashboard.json
  • messages/ja/dashboard.json
  • messages/ru/dashboard.json
  • messages/zh-CN/dashboard.json
  • messages/zh-TW/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/__tests__/code-display.test.tsx
  • src/components/ui/code-display.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • messages/ja/dashboard.json
  • messages/zh-TW/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use 2-space indentation in all code files

Files:

  • messages/ru/dashboard.json
  • messages/zh-CN/dashboard.json
  • src/components/ui/code-display.tsx
  • messages/en/dashboard.json
  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
messages/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in messages/{locale}/*.json

Store message translations in messages/{locale}/*.json files

Files:

  • messages/ru/dashboard.json
  • messages/zh-CN/dashboard.json
  • messages/en/dashboard.json
**/*.{tsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW

Files:

  • messages/ru/dashboard.json
  • messages/zh-CN/dashboard.json
  • src/components/ui/code-display.tsx
  • messages/en/dashboard.json
  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use double quotes for strings instead of single quotes
Use trailing commas in multi-line structures
Enforce maximum line length of 100 characters
Use path alias @/* to reference files from ./src/* directory

**/*.{ts,tsx,js,jsx}: Use Biome for linting and formatting with 2-space indent, double quotes, trailing commas, and 100 character max line length
Use path alias @/* to reference files in ./src/* directory

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use lucide-react for icons instead of custom SVGs

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
src/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{tsx,jsx}: Use lucide-react for icons, no custom SVGs
Use React's automatic escaping to prevent XSS vulnerabilities

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
src/components/ui/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place UI components in src/components/ui/ directory (excluded from typecheck)

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript strict mode for type safety
Use readonly or const assertions for immutable data structures

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
src/components/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/components/**/*.{tsx,jsx}: Use Tailwind CSS for styling, place utility classes close to JSX
Use shadcn/ui component library for high-quality, accessible UI components

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Vitest for unit testing with Node environment, coverage thresholds: 50% lines/functions, 40% branches

Files:

  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to messages/**/*.json : Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in `messages/{locale}/*.json`
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to messages/**/*.json : Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in `messages/{locale}/*.json`

Applied to files:

  • messages/zh-CN/dashboard.json
  • src/components/ui/__tests__/code-display.test.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Enforce maximum line length of 100 characters

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Biome for linting and formatting with 2-space indent, double quotes, trailing commas, and 100 character max line length

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/components/**/*.{ts,tsx} : Use `lucide-react` for icons instead of custom SVGs

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/**/*.{tsx,jsx} : Use `lucide-react` for icons, no custom SVGs

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/components/**/*.{tsx,jsx} : Use shadcn/ui component library for high-quality, accessible UI components

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit testing with Node environment, coverage thresholds: 50% lines/functions, 40% branches

Applied to files:

  • src/components/ui/__tests__/code-display.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.{tsx,json} : Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW

Applied to files:

  • src/components/ui/__tests__/code-display.test.tsx
🧬 Code graph analysis (1)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx (1)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx (1)
  • SessionMessagesClient (40-655)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 🌐 API Tests
  • GitHub Check: Docker Build Test
  • GitHub Check: dev-build-deploy
🔇 Additional comments (24)
messages/ru/dashboard.json (2)

395-397: LGTM:操作按钮标签更新准确

俄语翻译正确地反映了导出功能包含请求头和请求体的事实。翻译质量良好,与其他语言区域的更新保持一致。


439-446: LGTM:硬限制 UI 文本添加完整

新增的 hardLimit 对象结构完整,包含了所有必需的字段(title、size、maximum、hint、download)。俄语翻译清晰准确,与其他语言区域的实现保持一致。

src/components/ui/__tests__/code-display.test.tsx (3)

9-9: LGTM:导入更新正确

添加 vi 导入以支持新测试中的 spy 功能,符合 Vitest 的标准使用模式。


32-38: LGTM:测试 mock 数据结构完整

新增的 hardLimit 对象与本地化文件中的结构保持一致,包含了所有必需的字段,为硬限制 UI 功能提供了正确的测试数据。


303-347: LGTM:硬限制下载功能测试覆盖全面

新增测试用例全面验证了超大内容的下载流程:

  • 正确 mock 了 URL.createObjectURL、URL.revokeObjectURL 和锚点元素的点击行为
  • 验证了 blob 创建、文件名格式、href 属性和 blob 内容
  • 确保了资源的正确清理(revokeObjectURL 调用)
  • 测试结构清晰,遵循了现有的测试模式
messages/en/dashboard.json (2)

396-397: LGTM:英文标签清晰明确

更新后的操作标签明确指出导出内容包含请求头和请求体,提升了用户体验。作为参考语言区域,这些标签为其他语言的翻译提供了良好的基准。


440-446: LGTM:硬限制 UI 文本结构完整且表述清晰

新增的 hardLimit 对象提供了完整的 UI 文本支持,包括标题、大小显示、上限说明、提示信息和下载按钮标签。英文表述专业清晰,为用户提供了友好的超限内容处理指引。

messages/zh-CN/dashboard.json (2)

396-397: LGTM:中文标签翻译准确清晰

简体中文翻译准确地传达了导出功能包含请求头和请求体的含义,使用了恰当的技术术语,表述清晰明了。


440-446: LGTM:中文硬限制 UI 文本翻译自然准确

新增的 hardLimit 对象的简体中文翻译准确自然,技术术语使用恰当:

  • "内容过大" 清晰表达了超限状态
  • 大小和上限信息的格式化字符串正确
  • 提示信息友好且易于理解
  • 结构与其他语言区域保持一致
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx (5)

1-138: LGTM:测试文件设置完整且结构良好

测试文件的设置非常全面:

  • 正确使用 happy-dom 环境用于 DOM 测试
  • 完整 mock 了所有外部依赖(路由、翻译、API、UI 组件等)
  • 提供了实用的测试工具函数(renderClient、click、clickAsync、flushEffects)
  • flushEffects 函数正确处理了 React 19 中异步 useEffect 的多次 setState 更新
  • afterEach 中进行了彻底的清理,避免测试间干扰

140-202: LGTM:URL 序列号覆盖测试实现正确

测试用例正确验证了 URL 参数中的序列号会覆盖 currentSequence 的行为:

  • 设置 seqParamValue = "3" 并 mock currentSequence = 7
  • 验证下载文件名使用了 URL 参数的序列号(seq-3)
  • 完整测试了下载流程:blob 创建、锚点属性、清理操作
  • Spy 的设置和清理都很规范

204-301: LGTM:导出内容结构验证全面

测试用例全面验证了导出功能的正确性:

  • 验证导出的 JSON 结构包含所有必需字段(sessionId、sequence、meta、headers、body)
  • 同时测试了复制和下载两个操作
  • 正确使用 fake timers 处理复制按钮的 2 秒超时,避免 act 警告
  • 通过读取 blob 内容验证了导出数据的完整性
  • JSON 格式化参数(null, 2)的验证确保了输出的可读性

303-359: LGTM:缺失数据场景测试覆盖完整

两个测试用例正确验证了导出按钮的显示条件:

  • 第一个测试验证了请求头和请求体都缺失时不显示导出按钮
  • 第二个测试验证了仅有请求头但缺少请求体时也不显示导出按钮
  • 与 PR 目标一致:仅在请求头和请求体都存在时才显示导出功能
  • 边界情况覆盖充分

361-461: LGTM:错误处理和综合功能测试覆盖全面

测试用例全面覆盖了组件的各种场景:

  • 错误场景测试简洁有效,验证了 API 失败时的错误消息显示
  • 综合测试覆盖了完整的用户工作流:
    • 会话统计信息的渲染
    • 上一个/下一个请求的导航(验证 router.replace 调用)
    • 复制响应体功能(使用 fake timers 处理超时)
    • 终止会话的完整流程(打开对话框 → 确认 → API 调用 → 重定向)
  • 正确使用了 clickAsync 和 flushEffects 处理异步操作
  • 测试断言精确且全面
src/components/ui/code-display.tsx (10)

3-3: LGTM!

lucide-react 导入 Download 图标符合项目编码规范。


16-18: LGTM!

默认阈值设定合理(1MB / 10,000 行),并使用数字分隔符提升可读性。根据 PR 目标,会话消息详情视图将通过 props 传入更高的限制值(5MB / 30,000 行),确保了灵活性。


27-28: LGTM!

新增的可选 props maxContentBytesmaxLines 设计合理,支持按需自定义限制,且向后兼容。


75-78: LGTM!

使用 Blob 计算字节大小能准确处理 UTF-8 编码的多字节字符,useMemo 优化避免了不必要的重复计算。


80-86: LGTM!

模式初始化逻辑正确,对超大内容自动降级为 "raw" 模式,避免初次渲染性能问题。使用函数式初始化器也是正确的做法。


107-112: LGTM!

useEffect 确保动态内容场景下自动切换回 "raw" 模式,依赖项正确,守卫条件避免了不必要的状态更新。


114-117: LGTM!

行数计算逻辑正确,当字节已超限时短路返回 0,避免不必要的行数统计开销。


120-120: LGTM!

硬限制检查同时考虑字节大小和行数,逻辑正确且高效。


122-136: LGTM!

formattedJsonsseEvents 的计算都增加了 isHardLimited 检查,避免对超限内容进行昂贵的解析和格式化操作,是正确的性能优化。


216-263: LGTM!

硬限制 UI 实现良好:

  • 正确使用 i18n 翻译键
  • 使用 lucide-react 图标符合规范
  • 按钮具有适当的 data-testid 便于测试
  • 使用 toLocaleString() 格式化数字提升用户体验
  • 消息清晰展示了大小、限制和操作提示

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ding113, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在优化 Session Messages 详情页的用户体验,特别是针对大型数据内容的显示和导出。通过提高内容显示阈值、提供完整的请求数据导出功能以及在内容受限时提供便捷的下载选项,用户现在可以更有效地处理和分析会话消息。同时,通过增加单元测试,确保了这些新功能的稳定性和代码质量。

Highlights

  • 内容阈值提升: Session Messages 详情页的“内容过大”阈值已调整为 5MB / 30000 行,以更好地处理大型请求和响应数据。
  • 完整请求导出功能: 顶部的下载/复制按钮现在可以导出完整的请求头和请求体(JSON 格式),提供更全面的数据导出能力。
  • 大内容面板内下载: 当内容因过大而受限时,现在在“内容过大”提示框内提供了直接下载 request.json 的功能。
  • 单元测试覆盖率提升: 已补齐相关单元测试,并确保该模块的语句覆盖率达到或超过 80%。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 4, 2026

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@github-actions github-actions bot added the size/L Large PR (< 1000 lines) label Jan 4, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces significant enhancements to the session message display and export functionality. The 'Copy Messages' and 'Download Messages' actions have been updated across multiple internationalization files (English, Japanese, Russian, Simplified Chinese, Traditional Chinese) to clarify that they now export 'Request (Headers + Body)'.

The CodeDisplay component has been refactored to support configurable content size and line limits (maxContentBytes and maxLines), with new default limits of 5MB and 30,000 lines respectively for session details. It now includes an in-panel download button for hard-limited content, allowing users to download the full content when it exceeds display limits. The component also intelligently switches to 'raw' display mode for very large content to prevent performance issues.

In the SessionMessagesClient, the state management for copying and downloading requests has been updated to handle both headers and body. A new getRequestExportJson function was introduced to format the request data for export, and the download filename now includes the sequence number. New test files (session-messages-client-actions.test.tsx) were added to cover these export actions, including scenarios for sequence overriding, header/body inclusion, and missing data. Existing tests for session-messages-client.test.tsx and code-display.test.tsx were expanded to cover the new hard-limit and download functionalities.

Review comments suggest refactoring duplicated state reset logic in SessionMessagesClient into a helper function, and wrapping getRequestExportJson and the CodeDisplay's handleDownload function with useCallback for performance optimization. Additionally, the handleDownload cleanup in CodeDisplay is advised to be delayed using setTimeout to prevent potential race conditions with browser downloads.

Comment on lines 130 to 156
setMessages(null);
setRequestBody(null);
setResponse(null);
setRequestHeaders(null);
setResponseHeaders(null);
setRequestMeta({ clientUrl: null, upstreamUrl: null, method: null });
setResponseMeta({ upstreamUrl: null, statusCode: null });
setSessionStats(null);
setCurrentSequence(null);
setPrevSequence(null);
setNextSequence(null);
setError(result.error || t("status.fetchFailed"));
}
} catch (err) {
if (cancelled) return;
setMessages(null);
setRequestBody(null);
setResponse(null);
setRequestHeaders(null);
setResponseHeaders(null);
setRequestMeta({ clientUrl: null, upstreamUrl: null, method: null });
setResponseMeta({ upstreamUrl: null, statusCode: null });
setSessionStats(null);
setCurrentSequence(null);
setPrevSequence(null);
setNextSequence(null);
setError(err instanceof Error ? err.message : t("status.unknownError"));
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

elsecatch 代码块中,重置状态的逻辑是重复的。为了提高代码的可维护性和减少重复,建议将这部分逻辑提取到一个单独的辅助函数中。

例如,您可以创建一个函数:

const resetStateOnError = () => {
  setMessages(null);
  setRequestBody(null);
  setResponse(null);
  setRequestHeaders(null);
  setResponseHeaders(null);
  setRequestMeta({ clientUrl: null, upstreamUrl: null, method: null });
  setResponseMeta({ upstreamUrl: null, statusCode: null });
  setSessionStats(null);
  setCurrentSequence(null);
  setPrevSequence(null);
  setNextSequence(null);
};

然后在 elsecatch 块中调用它:

// ...
} else {
  resetStateOnError();
  setError(result.error || t("status.fetchFailed"));
}
// ...
} catch (err) {
  if (cancelled) return;
  resetStateOnError();
  setError(err instanceof Error ? err.message : t("status.unknownError"));
}
// ...

Comment on lines +174 to +186
const getRequestExportJson = () => {
return JSON.stringify(
{
sessionId,
sequence: exportSequence,
meta: requestMeta,
headers: requestHeaders,
body: requestBody,
},
null,
2
);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

此函数在每次组件渲染时都会被重新创建。为了优化性能,建议使用 useCallback 将其包裹起来,并提供正确的依赖项数组。

Suggested change
const getRequestExportJson = () => {
return JSON.stringify(
{
sessionId,
sequence: exportSequence,
meta: requestMeta,
headers: requestHeaders,
body: requestBody,
},
null,
2
);
};
const getRequestExportJson = useCallback(() => {
return JSON.stringify(
{
sessionId,
sequence: exportSequence,
meta: requestMeta,
headers: requestHeaders,
body: requestBody,
},
null,
2
);
}, [sessionId, exportSequence, requestMeta, requestHeaders, requestBody]);

Comment on lines +197 to +214
const handleDownload = () => {
const blob = new Blob([content], {
type: language === "json" ? "application/json" : "text/plain",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
try {
a.href = url;
a.download = downloadFileName;
document.body.appendChild(a);
a.click();
} finally {
if (a.isConnected) {
document.body.removeChild(a);
}
URL.revokeObjectURL(url);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

handleDownload 函数在每次组件渲染时都会被重新创建,建议使用 useCallback 进行性能优化。
此外,同步调用 URL.revokeObjectURL(url)removeChild(a) 可能会在某些浏览器中导致下载失败的竞态条件。更稳妥的做法是将它们放入 setTimeout 中延迟执行,以确保下载已正常启动。

Suggested change
const handleDownload = () => {
const blob = new Blob([content], {
type: language === "json" ? "application/json" : "text/plain",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
try {
a.href = url;
a.download = downloadFileName;
document.body.appendChild(a);
a.click();
} finally {
if (a.isConnected) {
document.body.removeChild(a);
}
URL.revokeObjectURL(url);
}
};
const handleDownload = useCallback(() => {
const blob = new Blob([content], {
type: language === "json" ? "application/json" : "text/plain",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = downloadFileName;
document.body.appendChild(a);
a.click();
// Delay cleanup to ensure the download can start.
setTimeout(() => {
if (a.isConnected) {
document.body.removeChild(a);
}
URL.revokeObjectURL(url);
}, 100);
}, [content, downloadFileName, language]);

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx (1)

220-221: 建议:考虑 exportSequence 为 0 的边界情况

exportSequence0 时,由于 JavaScript 的 falsy 判断,seqPart 会变成空字符串。虽然实际场景中 sequence 从 1 开始,但显式判断 null/undefined 会更安全。

🔎 可选的防御性改进
-    const seqPart = exportSequence ? `-seq-${exportSequence}` : "";
+    const seqPart = exportSequence != null ? `-seq-${exportSequence}` : "";
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx (1)

113-114: 建议:注释使用英文

代码中的中文注释(如第 113-114 行和 119-120 行)建议改为英文,以保持代码库的一致性。

🔎 建议的注释修改
 async function clickAsync(el: Element) {
   await act(async () => {
     el.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
     el.dispatchEvent(new MouseEvent("mouseup", { bubbles: true }));
     el.dispatchEvent(new MouseEvent("click", { bubbles: true }));
-    // 让事件处理器内的 await 续体在 act 作用域内完成
+    // Let async continuations inside event handlers complete within act scope
     await Promise.resolve();
   });
 }

 async function flushEffects() {
-  // SessionMessagesClient 内部有异步 useEffect(await getSessionDetails + 多次 setState)。
-  // 这里用两轮 tick 来确保状态更新都在 act 范围内落地,避免 act 警告。
+  // SessionMessagesClient has async useEffect (await getSessionDetails + multiple setState calls).
+  // Use two ticks to ensure state updates settle within act scope, avoiding act warnings.
   await act(async () => {

Also applies to: 119-120

src/components/ui/code-display.tsx (1)

252-253: 建议:下载按钮文本国际化

下载按钮的文本 "Download" 是硬编码的英文,建议使用 next-intl 进行国际化处理,与项目其他部分保持一致。

🔎 建议的国际化改进

需要在 messages/{locale}/dashboard.jsoncodeDisplay 部分添加 download 键,然后修改代码:

             <Button
               type="button"
               variant="outline"
               size="sm"
               onClick={handleDownload}
               data-testid="code-display-hard-limit-download"
             >
               <Download className="h-4 w-4 mr-2" />
-              Download
+              {t("codeDisplay.download")}
             </Button>
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between d302935 and bd98cce.

📒 Files selected for processing (11)
  • messages/en/dashboard.json
  • messages/ja/dashboard.json
  • messages/ru/dashboard.json
  • messages/zh-CN/dashboard.json
  • messages/zh-TW/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/__tests__/code-display.test.tsx
  • src/components/ui/code-display.tsx
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use 2-space indentation in all code files

Files:

  • messages/zh-CN/dashboard.json
  • messages/zh-TW/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • messages/ru/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/code-display.tsx
  • messages/en/dashboard.json
  • messages/ja/dashboard.json
  • src/components/ui/__tests__/code-display.test.tsx
messages/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in messages/{locale}/*.json

Store message translations in messages/{locale}/*.json files

Files:

  • messages/zh-CN/dashboard.json
  • messages/zh-TW/dashboard.json
  • messages/ru/dashboard.json
  • messages/en/dashboard.json
  • messages/ja/dashboard.json
**/*.{tsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW

Files:

  • messages/zh-CN/dashboard.json
  • messages/zh-TW/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • messages/ru/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/code-display.tsx
  • messages/en/dashboard.json
  • messages/ja/dashboard.json
  • src/components/ui/__tests__/code-display.test.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use double quotes for strings instead of single quotes
Use trailing commas in multi-line structures
Enforce maximum line length of 100 characters
Use path alias @/* to reference files from ./src/* directory

**/*.{ts,tsx,js,jsx}: Use Biome for linting and formatting with 2-space indent, double quotes, trailing commas, and 100 character max line length
Use path alias @/* to reference files in ./src/* directory

Files:

  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
src/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{tsx,jsx}: Use lucide-react for icons, no custom SVGs
Use React's automatic escaping to prevent XSS vulnerabilities

Files:

  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript strict mode for type safety
Use readonly or const assertions for immutable data structures

Files:

  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Vitest for unit testing with Node environment, coverage thresholds: 50% lines/functions, 40% branches

Files:

  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/components/ui/__tests__/code-display.test.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use lucide-react for icons instead of custom SVGs

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
src/components/ui/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place UI components in src/components/ui/ directory (excluded from typecheck)

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
src/components/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/components/**/*.{tsx,jsx}: Use Tailwind CSS for styling, place utility classes close to JSX
Use shadcn/ui component library for high-quality, accessible UI components

Files:

  • src/components/ui/code-display.tsx
  • src/components/ui/__tests__/code-display.test.tsx
🧠 Learnings (8)
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to messages/**/*.json : Support 5 locales via next-intl: en, ja, ru, zh-CN, zh-TW with messages in `messages/{locale}/*.json`

Applied to files:

  • messages/zh-CN/dashboard.json
  • messages/zh-TW/dashboard.json
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
  • messages/ja/dashboard.json
  • src/components/ui/__tests__/code-display.test.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit testing with Node environment, coverage thresholds: 50% lines/functions, 40% branches

Applied to files:

  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx
  • src/components/ui/__tests__/code-display.test.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Enforce maximum line length of 100 characters

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Biome for linting and formatting with 2-space indent, double quotes, trailing commas, and 100 character max line length

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:20.573Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-03T09:08:20.573Z
Learning: Applies to src/components/**/*.{ts,tsx} : Use `lucide-react` for icons instead of custom SVGs

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/**/*.{tsx,jsx} : Use `lucide-react` for icons, no custom SVGs

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to src/components/**/*.{tsx,jsx} : Use shadcn/ui component library for high-quality, accessible UI components

Applied to files:

  • src/components/ui/code-display.tsx
📚 Learning: 2026-01-03T09:08:49.019Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-03T09:08:49.019Z
Learning: Applies to **/*.{tsx,json} : Use next-intl for internationalization with 5 locales: en, ja, ru, zh-CN, zh-TW

Applied to files:

  • src/components/ui/__tests__/code-display.test.tsx
🧬 Code graph analysis (4)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx (1)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx (1)
  • SessionMessagesClient (40-661)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx (1)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx (1)
  • SessionMessagesDetailsTabs (42-219)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx (2)
scripts/sync-settings-keys.js (1)
  • t (72-72)
src/components/ui/button.tsx (1)
  • Button (58-58)
src/components/ui/code-display.tsx (2)
src/lib/utils/sse.ts (1)
  • parseSSEDataForDisplay (93-98)
src/components/ui/button.tsx (1)
  • Button (58-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Greptile Review
  • GitHub Check: pr-review
  • GitHub Check: pr-label
  • GitHub Check: pr-description
  • GitHub Check: check-codex-status
  • GitHub Check: Docker Build Test
  • GitHub Check: 🌐 API Tests
  • GitHub Check: dev-build-deploy
🔇 Additional comments (17)
messages/zh-CN/dashboard.json (1)

396-397: 会话操作文案与新导出行为一致,保持即可

这两行准确说明按钮操作是针对“请求头和请求体”,与英文及实际导出内容对齐,键名保持不变,JSON 结构与缩进也正确,无需调整。

messages/en/dashboard.json (1)

396-397: 英文主文案清晰标注 Headers + Body,与功能契合

说明文本明确为“Request (Headers + Body)”,与会话消息导出新行为匹配,键名和 JSON 结构均未改变,可直接接受。

messages/ja/dashboard.json (1)

395-396: 日文文案自然且语义与其它语言一致

新文案清楚说明操作对象是「リクエスト(ヘッダーとボディ)」,与实际导出内容及其他 locale 保持一致,键名与 JSON 结构均正确。

messages/ru/dashboard.json (1)

395-396: 俄文操作文案准确反映“完整请求”导出

文本明确为“запрос (заголовки и тело)”,与新行为和其它 locale 对齐,键名未改动,JSON 格式良好。

messages/zh-TW/dashboard.json (1)

396-397: 繁体中文文案与简体及英文版本语义一致

使用「複製/下載請求頭與請求體」清楚描述操作对象,与 PR 中“完整請求(Headers + Body)”的行为相符,键名与 JSON 结构均正常。

src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-details-tabs.tsx (2)

11-13: 常量定义合理

新增的 SESSION_DETAILS_MAX_CONTENT_BYTES (5MB) 和 SESSION_DETAILS_MAX_LINES (30,000) 常量符合 PR 目标要求,数值设置合理。常量作为模块级定义,便于后续调整阈值。


141-142: CodeDisplay 限制参数传递一致

所有 CodeDisplay 组件的调用都正确传递了 maxContentBytesmaxLines 参数,确保了整个 Session Details 页面的内容限制行为一致。

Also applies to: 158-159, 175-176, 192-193, 209-210

src/components/ui/__tests__/code-display.test.tsx (1)

296-340: 测试覆盖全面

新增的 hard-limited content provides download action 测试全面验证了硬限制内容的下载流程,包括:

  • Blob URL 创建与回收
  • 下载文件名和 href 设置
  • Blob 内容验证
  • Mock 清理

测试设计合理,符合项目测试规范。

src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.test.tsx (2)

190-223: 硬限制阈值验证测试

测试正确验证了提升后的阈值行为:10,100 个请求头(约 20,200 行)不会触发 "Content too large" 警告,因为新的上限是 30,000 行。测试逻辑清晰,断言准确。


225-286: 面板内下载功能测试完善

测试全面验证了当请求体超过 30,000 行时:

  • 显示 "Content too large" 提示
  • 下载按钮存在且可点击
  • 下载的文件名正确 (request.json)
  • Blob 内容与预期 JSON 一致
  • URL 资源正确回收
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx (2)

130-140: 错误路径的状态重置逻辑完善

result.ok === falsecatch 分支中全面重置了相关状态(messages、response、headers、meta、sequences),避免了旧数据残留导致的 UI 不一致问题。实现严谨。

Also applies to: 145-156


171-186: 请求导出逻辑设计合理

新增的导出逻辑结构清晰:

  • hasRequestForExport: 检查是否有可导出的内容
  • canExportRequest: 综合判断导出按钮是否可用
  • getRequestExportJson: 构建标准化的导出 JSON 结构

导出的 JSON 包含 sessionIdsequencemetaheadersbody,结构完整,便于后续分析和调试。

src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx (2)

1-137: 测试设置完备

测试文件的 Mock 设置全面覆盖了所有外部依赖:

  • @tanstack/react-querynext-intlnext/navigation 等库
  • 路由和 action 函数
  • 子组件

afterEach 中正确重置了所有 mock 状态,确保测试隔离性。


139-430: 测试用例覆盖全面

测试用例完整覆盖了请求导出功能的各个方面:

  1. URL seq 参数覆盖 currentSequence 用于导出
  2. 复制/下载导出内容包含完整的请求信息
  3. 缺少 headers/body 时不渲染导出按钮
  4. 错误状态正确显示
  5. Session 统计视图、导航、复制响应、终止会话流程

测试设计符合项目规范,异步处理和 fake timers 使用正确。

src/components/ui/code-display.tsx (3)

16-18: 可配置限制参数设计良好

新增的 DEFAULT_MAX_CONTENT_BYTESDEFAULT_MAX_LINESPRETTY_MODE_DEFAULT_MAX_CHARS 常量与 maxContentBytesmaxLines props 提供了灵活的配置能力,同时保持了向后兼容性。

Also applies to: 27-28


80-86: Pretty 模式的内容限制处理合理

初始化时根据 PRETTY_MODE_DEFAULT_MAX_CHARS 判断是否使用 raw 模式,并通过 useEffect 在内容变化时动态切换,避免了大内容在 pretty 模式下的性能问题。

Also applies to: 107-112


190-259: 硬限制 UI 和下载功能实现完善

硬限制分支的实现要点:

  • 清晰显示内容大小和允许的最大值
  • 使用 try/finally 确保 URL 资源正确回收
  • isConnected 检查增强了代码健壮性
  • data-testid 便于测试

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Code Review Summary

This PR enhances session message viewing by raising content limits and improving request export functionality. The implementation is clean, well-tested, and follows project conventions. No significant issues identified.

PR Size: L (Large)

  • Lines changed: 764 (721 additions + 43 deletions)
  • Files changed: 11

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Key Observations

Positive Implementation Details:

  1. Configurable thresholds: CodeDisplay now accepts maxContentBytes and maxLines props with sensible defaults (1MB/10k lines), allowing session details to use higher limits (5MB/30k lines)

  2. Proper resource cleanup: Download handlers correctly revoke blob URLs and clean up anchor elements:

    // code-display.tsx:197-213
    try {
      a.href = url;
      a.download = downloadFileName;
      document.body.appendChild(a);
      a.click();
    } finally {
      if (a.isConnected) {
        document.body.removeChild(a);
      }
      URL.revokeObjectURL(url);
    }
  3. Complete state reset on error: Error paths now properly reset all state variables to prevent stale data display

  4. Smart export condition: canExportRequest properly gates export buttons on loading/error state and data availability

  5. Accurate byte size calculation: Using new Blob([content]).size for UTF-8 accurate measurement

  6. Auto-fallback for large content: Pretty mode automatically falls back to raw mode for content > 100k chars to prevent performance issues

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (errors logged to console)
  • Type safety - Clean (no any usage)
  • Documentation accuracy - Clean
  • Test coverage - Good (431 lines of new tests)
  • Code clarity - Good

Automated review by Claude AI

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Code Review Summary

This PR enhances session message viewing by raising content limits and improving request export functionality. The implementation is clean, well-tested, and follows project conventions. No significant issues identified.

PR Size: L (Large)

  • Lines changed: 764 (721 additions + 43 deletions)
  • Files changed: 11

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Key Observations

Positive Implementation Details:

  1. Configurable thresholds: CodeDisplay now accepts maxContentBytes and maxLines props with sensible defaults (1MB/10k lines), allowing session details to use higher limits (5MB/30k lines)

  2. Proper resource cleanup: Download handlers correctly revoke blob URLs and clean up anchor elements with try/finally pattern

  3. Complete state reset on error: Error paths now properly reset all state variables to prevent stale data display

  4. Smart export condition: canExportRequest properly gates export buttons on loading/error state and data availability

  5. Accurate byte size calculation: Using new Blob([content]).size for UTF-8 accurate measurement

  6. Auto-fallback for large content: Pretty mode automatically falls back to raw mode for content > 100k chars to prevent performance issues

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (errors logged to console)
  • Type safety - Clean (no any usage)
  • Documentation accuracy - Clean
  • Test coverage - Good (431 lines of new tests)
  • Code clarity - Good

Automated review by Claude AI

const handleCopyMessages = async () => {
if (!messages) return;
const hasRequestForExport = requestHeaders !== null || requestBody !== null;
const canExportRequest = !isLoading && error === null && hasRequestForExport;
Copy link
Contributor

Choose a reason for hiding this comment

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

[HIGH] [LOGIC-BUG] Request export can be enabled without a body

Evidence (src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx:171):
const hasRequestForExport = requestHeaders !== null || requestBody !== null;

Why this is a problem: requestBody can legitimately be null (e.g., when request body storage is disabled), but requestHeaders may still be available. This makes the UI show “Copy/Download Request (Headers + Body)” while exporting JSON with "body": null, which is misleading and makes the feature appear broken.

Suggested fix (only enable export when both headers and body are present):

const canExportRequest =
  !isLoading &&
  error === null &&
  requestHeaders !== null &&
  requestBody !== null;

Test suggestion:

// requestBody: null, requestHeaders: { "content-type": "application/json" } => no export buttons

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Code Review Summary

PR updates the Session Messages detail UI thresholds and adds request export + in-panel download for hard-limited content, with new tests and i18n string updates. One functional gap remains: request export actions can be enabled even when the request body is unavailable, producing incomplete exports while the UI labels claim “Headers + Body”.

PR Size: L

  • Lines changed: 764
  • Files changed: 11
  • Split suggestion (recommended for L PRs): split into (1) CodeDisplay hard-limit download + tests, (2) Session Messages request export actions + tests, (3) i18n copy updates + threshold tuning.

Issues Found

Category Critical High Medium Low
Logic/Bugs 1 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Critical Issues (Must Fix)

  • (Confidence 95) src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx:171: export gating allows missing requestBody, so “Copy/Download Request (Headers + Body)” can export JSON with "body": null.

High Priority Issues (Should Fix)

  • None.

Review Coverage

  • Logic and correctness
  • Security (OWASP Top 10)
  • Error handling
  • Type safety
  • Documentation accuracy
  • Test coverage
  • Code clarity

Automated review by Codex AI

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

  • Reviewed PR #537 and applied label size/L.
  • Left 1 inline review comment on src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx:171 about request export being enabled when requestBody is null, which can produce exports with "body": null despite the UI label claiming “Headers + Body”.
  • Submitted the full review summary via gh pr review (includes split suggestions since this is a size L PR).

- 修复导出按钮在缺失请求体时仍可用的问题(避免导出 body:null 误导)\n- 提取错误态重置逻辑,减少重复\n- CodeDisplay 超限提示文案与下载按钮改为 i18n(5 语言补齐)\n- 补充单元测试覆盖缺失请求体场景
@github-actions
Copy link
Contributor

github-actions bot commented Jan 4, 2026

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@ding113 ding113 merged commit 7c13cc6 into dev Jan 4, 2026
9 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Jan 4, 2026
This was referenced Jan 6, 2026
@ding113 ding113 deleted the fix/session-messages-content-limit branch January 27, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:i18n area:session area:UI enhancement New feature or request size/L Large PR (< 1000 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant

Comments