Skip to content

feat(chat): add /export slash command for conversation export#1684

Merged
piorpua merged 9 commits intoiOfficeAI:mainfrom
amanharshx:feat/export-slash-flow
Mar 29, 2026
Merged

feat(chat): add /export slash command for conversation export#1684
piorpua merged 9 commits intoiOfficeAI:mainfrom
amanharshx:feat/export-slash-flow

Conversation

@amanharshx
Copy link
Copy Markdown
Contributor

@amanharshx amanharshx commented Mar 24, 2026

Closes #1685

Summary

  • Add /export builtin slash command to the chat sendbox for single-conversation export
  • Two actions: copy transcript to clipboard, or save as .txt to the workspace directory
  • Multi-step overlay flow: slash menu → action picker → filename input (for save)
  • Extract shared export utilities from GroupedHistory into a reusable module, removing duplication

Motivation

Users have no quick way to export a single conversation from within the chat. The existing GroupedHistory ZIP export is a different feature for bulk export. This adds a lightweight /export command accessible directly in the sendbox.

Commits

  • 47b6c238 feat(chat): add /export slash command for conversation export — core implementation: export hook, shared utilities, sendbox integration, i18n keys (6 locales)
  • fc3da0cb test(chat): expand export test coverage and fix stale button style — add tests for exportHelpers and useExport, expand coverage for hook/sendbox/utilities, remove hardcoded #000000 button color and stale CSS comment

Diff

+1850 −96 across 18 files (12 modified, 6 new)

  • Code: +825 −96 across 13 files
  • Tests: +1025 −0 across 5 files

Files changed

  • sendbox.tsx (+140 / -36) — register /export builtin command, integrate export overlay, remove hardcoded button color
  • sendbox.css (+0 / -1) — remove stale style comment
  • exportHelpers.ts (+10 / -39) — extract shared functions to new module, deduplicate role-label logic via getMessageRoleKey
  • useExport.ts (+17 / -20) — import shared utilities directly (remove transitional re-exports)
  • conversationExport.ts (+130, new) — shared pure utilities: filename generation, message extraction, transcript building
  • useConversationExport.tsx (+360, new) — state machine hook for export flow (closed → menu → filename)
  • i18n-keys.d.ts (+24) — 24 new messages.export.* type definitions
  • messages.json × 6 locales (+24 each) — en-US, ja-JP, ko-KR, tr-TR, zh-CN, zh-TW
  • conversationExport.test.ts (+137, new) — transcript building, filename generation, edge cases
  • useConversationExport.dom.test.tsx (+167, new) — hook flow, copy/save paths, error handling, keyboard navigation
  • sendboxExport.dom.test.tsx (+258, new) — end-to-end slash command → export menu → copy/save
  • exportHelpers.test.ts (+149, new) — markdown builder, zip path normalization, timeout helper
  • useExport.dom.test.tsx (+314, new) — grouped history export hook: file save, ZIP export, duplicate filename handling

Testing

  • bunx tsc --noEmit — no type errors
  • bunx oxlint — 0 errors
  • bunx oxfmt — passed
  • bunx vitest run tests/unit/chat/ — 5 files, 29 tests, all passing
  • node scripts/check-i18n.js — passed

Risks / Side effects

  • No breaking changes to existing GroupedHistory ZIP export
  • String-only i18n additions, no logic changes to existing locale files

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 75.84906% with 64 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/renderer/hooks/file/useConversationExport.tsx 71.33% 27 Missing and 16 partials ⚠️
src/renderer/utils/chat/conversationExport.ts 77.27% 4 Missing and 11 partials ⚠️
src/renderer/components/chat/sendbox.tsx 81.25% 2 Missing and 4 partials ⚠️

📢 Thoughts on this report? Let us know!

@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 27, 2026

CI 检查未通过

以下 job 在本次自动化 review 时未通过,请修复:

Job 结论
Unit Tests (ubuntu-latest) ❌ CANCELLED
Unit Tests (macos-14) ❌ CANCELLED
Unit Tests (windows-2022) ❌ CANCELLED
Coverage Test ❌ CANCELLED

本次自动化 review 暂缓,待 CI 全部通过后将重新处理。

@piorpua piorpua added bot:reviewing Review in progress (mutex) bot:ci-waiting CI failed and author notified — snoozed until new commits are pushed and removed bot:reviewing Review in progress (mutex) labels Mar 27, 2026
@amanharshx amanharshx force-pushed the feat/export-slash-flow branch from 3664441 to fc3da0c Compare March 27, 2026 12:17
@amanharshx amanharshx force-pushed the feat/export-slash-flow branch from 57b2978 to 506ebae Compare March 27, 2026 12:39
@amanharshx
Copy link
Copy Markdown
Contributor Author

@piorpua Rebased on latest main and resolved the conflict. CI should be green now.

@piorpua piorpua removed the bot:ci-waiting CI failed and author notified — snoozed until new commits are pushed label Mar 28, 2026
@piorpua piorpua added the bot:reviewing Review in progress (mutex) label Mar 29, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 29, 2026

CI 检查未通过

以下 job 在本次自动化 review 时未通过,请修复:

Job 结论
Code Quality ❌ FAILURE

本次自动化 review 暂缓,待 CI 全部通过后将重新处理。

@piorpua piorpua added bot:ci-waiting CI failed and author notified — snoozed until new commits are pushed and removed bot:reviewing Review in progress (mutex) labels Mar 29, 2026
@piorpua piorpua added bot:reviewing Review in progress (mutex) and removed bot:ci-waiting CI failed and author notified — snoozed until new commits are pushed labels Mar 29, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 29, 2026

Code Review:feat(chat): add /export slash command for conversation export (#1684)

变更概述

本 PR 在聊天输入框(sendbox)新增 /export 内置 slash 命令,支持将单条对话导出为文本(复制到剪贴板或保存为 .txt)。核心逻辑拆分为 conversationExport.ts(纯工具函数)和 useConversationExport.tsx(状态机 hook),并将原 exportHelpers.ts 中的重复代码移除,统一由共享模块提供。


方案评估

结论:✅ 方案合理

状态机设计(closed → menu → filename)清晰,IPC 调用正确发生在 renderer 层通过 ipcBridge,架构边界未越界。工具函数模块化提取彻底消除了与 GroupedHistory 的代码重复,是一次合理的 DRY 改造。无过度工程化,也未发现已知设计盲点。


问题清单

🟡 MEDIUM — useConversationExport.tsx 测试覆盖率低于项目阈值

文件src/renderer/hooks/file/useConversationExport.tsx

问题说明

Codecov 报告显示该文件 patch 覆盖率为 66.66%(32 Missing + 18 Partials),低于项目要求的 80%。
useConversationExport.dom.test.tsx 目前仅有 3 个测试用例,缺失以下路径:

未覆盖路径 说明
handleCopy 流程 选择 copy 菜单项 → 复制成功/失败
handleKeyDown — menu 步骤的 ArrowUp/ArrowDown/Enter 键盘导航菜单
handleKeyDown — filename 步骤的 Enter 键盘提交文件名
loadTranscript 缓存路径 第二次调用应直接返回缓存而不重新 fetch
submitFilenamebaseDirectoryRef.current 为空时的错误路径

修复建议:补充以下测试(示例):

it('copies transcript to clipboard when copy action is selected', async () => {
  // renderHook + openExportFlow + onSelectMenuItem('copy')
  // expect mockCopyText called, success shown, step = 'closed'
});

it('navigates menu items with ArrowDown/ArrowUp and selects with Enter', async () => {
  // renderHook + openExportFlow
  // act: handleKeyDown({ key: 'ArrowDown' }) → activeIndex = 1
  // act: handleKeyDown({ key: 'Enter' }) → triggers save flow
});

it('submits filename with Enter key in filename step', async () => {
  // renderHook + openExportFlow + onSelectMenuItem('save')
  // act: handleKeyDown({ key: 'Enter' }) → submitFilename called
});

🔵 LOW — conversationExport.ts 覆盖率略低于阈值

文件src/renderer/utils/chat/conversationExport.ts

问题说明

Codecov 报告 patch 覆盖率为 77.27%(4 Missing + 11 Partials),略低于 80%。缺失的分支主要是:

  • readMessageContentcontentnull/undefined 时的 JSON.stringify 回退路径
  • joinFilePath 中路径末尾已有分隔符的情况(dir.endsWith('/') 为 true 的分支)

修复建议:在 conversationExport.test.ts 中补充:

it('readMessageContent falls back to JSON.stringify for object content', () => {
  // message.content = { type: 'tool_call', callId: '...' }
  // expect readMessageContent(message) 返回 JSON 字符串
});

it('joinFilePath handles trailing slash in dir', () => {
  expect(joinFilePath('/workspace/', 'file.txt')).toBe('/workspace/file.txt');
});

汇总

# 严重级别 文件 问题
1 🟡 MEDIUM useConversationExport.tsx 测试覆盖率 66.66%,低于项目 80% 阈值
2 🔵 LOW conversationExport.ts 测试覆盖率 77.27%,略低于项目 80% 阈值

结论

⚠️ 有条件批准 — 实现质量整体良好(状态机设计清晰、架构边界正确、错误处理完整、i18n 完整覆盖 6 个语言),主要问题是 useConversationExport.tsx 测试覆盖率(66.66%)明显低于项目 80% 阈值,需补充 copy 流程、键盘导航等测试用例后可合并。


本报告由本地 pr-review skill 生成,包含完整项目上下文,无截断限制。

@piorpua piorpua added bot:ready-to-fix CONDITIONAL review done, waiting for bot fix and removed bot:reviewing Review in progress (mutex) labels Mar 29, 2026
@piorpua piorpua added bot:fixing Fix in progress (mutex) and removed bot:ready-to-fix CONDITIONAL review done, waiting for bot fix labels Mar 29, 2026
…shold

- Add handleCopy success and failure path tests
- Add handleKeyDown ArrowDown/ArrowUp/Enter keyboard navigation tests
- Add handleKeyDown Enter in filename step test
- Add loadTranscript cache path test (no re-fetch on second call)
- Add submitFilename error path when baseDirectory is empty

Review follow-up for iOfficeAI#1684
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 29, 2026

PR Fix 验证报告

原始 PR: #1684
修复方式: 直接推送到 feat/export-slash-flow(fork,maintainer 写入权限已开启)

# 严重级别 文件 问题 修复方式 状态
1 🟡 MEDIUM useConversationExport.dom.test.tsx 测试覆盖率 66.66%,低于项目 80% 阈值 新增 7 个测试:handleCopy 成功/失败、键盘导航(ArrowDown/ArrowUp/Enter)、filename 步骤 Enter、transcript 缓存路径、submitFilename 空目录错误路径 ✅ 已修复

总结: ✅ 已修复 1 个 | ❌ 未能修复 0 个

🔵 LOW 级别问题(conversationExport.ts 覆盖率 77.27%)已跳过(不阻塞合并,修复优先级低)。

@piorpua piorpua enabled auto-merge (squash) March 29, 2026 05:02
@piorpua piorpua added bot:done Auto-merged by bot and removed bot:fixing Fix in progress (mutex) labels Mar 29, 2026
@piorpua piorpua merged commit 27d5fa9 into iOfficeAI:main Mar 29, 2026
4 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:done Auto-merged by bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add /export slash command for quick conversation export

2 participants