mirror of
https://github.com/Gmaker689/ai-diff-preview.git
synced 2026-09-26 23:11:51 +08:00
v0.2.0: VSCode内置Diff + QuickPick总览 + EditRecord粒度 + Bug修复
新增: - VSCode内置Diff编辑器 (diffViewer.ts) 替代Webview,零保存提示 - EditRecord独立追踪: 每次Edit/Write不合并,支持逐次编辑Accept/Reject - QuickPick文件列表总览,含Accept All / Reject All - 智能Auto-Advance: Accept/Reject后自动推进,同文件多编辑智能停留 - 状态栏常驻显示 AI Diff,Diff模式下切换为操作按钮 修复: - Accept后同文件再编辑不触发选项 (pending-priority匹配) - Accept All / Reject All写入与状态顺序修复 - acceptFile/rejectFile改为先写入成功再标记状态 - 同文件多个FileChange孤儿编辑问题 变更: - ChangeSetManager重构为EditRecord[] + FileChange聚合 - HookHandler精简,QuickPick移入hookHandler - 移除InlineDecorator/CodeLens (主流程),ReviewPanel降级为备用 - package.json: publisher=YonHao Guo, repository, v0.2.0, 新配置项/快捷键 测试: 13/13通过 (7 diffEngine + 6 changeSetManager回归)
This commit is contained in:
@@ -1,71 +1,112 @@
|
||||
# AI Code Diff Preview
|
||||
|
||||
类 Cursor 的 AI 代码差异预览 VSCode 插件,使用 **VSCode 内置 Diff 编辑器** + **浮动 Accept/Reject 标签**。
|
||||
> 类 Cursor 的 AI 代码差异预览 VSCode 插件
|
||||
|
||||
## 功能特性
|
||||
[](https://github.com/YonHaoGuo/ai-diff-preview/blob/master/CHANGELOG.md)
|
||||
[](https://code.visualstudio.com/)
|
||||
[](LICENSE)
|
||||
|
||||
- ✅ **VSCode 原生 Diff 编辑器** — 使用内置 `vscode.diff`,不自定义 Webview
|
||||
- ✅ **EditRecord 独立追踪** — 每次 Edit/Write 独立记录,不合并
|
||||
- ✅ **逐次编辑 Accept/Reject** — 细粒度控制每次 AI 修改
|
||||
- ✅ **QuickPick 文件列表** — 对话结束后弹出原生文件选择器
|
||||
- ✅ **快捷键导航** — `Alt+↑/↓` 跳转变更文件
|
||||
- ✅ **Bug 修复** — Accept 后再编辑不再丢失追踪
|
||||
- ✅ **冲突检测** — 自动检测用户手动修改导致的冲突
|
||||
AI Code Diff Preview 为 VSCode 注入 Cursor 风格的 Accept/Reject 差异审查体验。AI 对话中的每一次代码编辑自动收集,对话结束后弹出完整的变更文件列表。点击任意文件即可在 **VSCode 内置 Diff 编辑器**中逐文件审查,状态栏实时显示 Accept/Reject 按钮,操作完成后自动推进到下一个待处理文件。
|
||||
|
||||
## 工作流程
|
||||
## 特性
|
||||
|
||||
```
|
||||
Claude Edit/Write → 收集到 ChangeSet (EditRecord 粒度)
|
||||
├── autoShowDiffPerEdit=true → 立即弹出 VSCode 内置 Diff
|
||||
└── autoShowDiffPerEdit=false → 静默收集,更新状态栏
|
||||
|
||||
Claude Stop → 变更集就绪
|
||||
├── showAllDiffsOnStop=true → QuickPick 文件列表 → 点击打开内置 Diff
|
||||
└── showAllDiffsOnStop=false → 仅通知,用户手动 Ctrl+Shift+D 查看
|
||||
```
|
||||
- **VSCode 原生 Diff 编辑器** — 使用 `vscode.diff` 命令,100% 原生交互体验,无自定义 Webview
|
||||
- **EditRecord 独立追踪** — 每次 `Edit`/`Write` 操作作为独立编辑记录,支持逐次编辑 Accept/Reject
|
||||
- **QuickPick 总览** — 对话结束后弹出原生文件列表,含 Accept All / Reject All 一键操作
|
||||
- **智能 Auto-Advance** — Accept/Reject 后自动推进到下一个待处理文件,同文件多编辑自动停留
|
||||
- **状态栏常驻** — 插件激活后状态栏始终可见 `$(diff) AI Diff`,有变更时黄底高亮
|
||||
- **零保存提示** — Diff 编辑器使用临时文件,关闭时自动删除,不会弹出"是否保存"对话框
|
||||
- **多轮对话追踪** — 支持同一轮对话中对同文件的多次编辑合并、跨轮对话的独立追踪
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/ai-diff-preview.git
|
||||
# 克隆仓库
|
||||
git clone https://github.com/YonHaoGuo/ai-diff-preview.git
|
||||
cd ai-diff-preview
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 编译
|
||||
npm run build
|
||||
|
||||
# 打包 vsix
|
||||
npm run package
|
||||
```
|
||||
|
||||
或通过 VSCode 扩展市场安装(即将发布)。
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 工作流程
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ AI 对话中(Claude Code / Cursor / Copilot) │
|
||||
│ │
|
||||
│ Edit/Write 工具调用 → .claude/hooks/pending.json │
|
||||
│ → 插件自动收集变更 (静默) │
|
||||
│ │
|
||||
│ Stop/对话结束 → QuickPick 总览弹窗 │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ AI Diff 总览 — 3 文件 5 编辑 │ │
|
||||
│ │ │ │
|
||||
│ │ 📄 src/utils.ts +3 -2 · 2次编辑 │ │
|
||||
│ │ 📄 src/index.ts +9 -1 · 2次编辑 │ │
|
||||
│ │ 📄 src/types.ts +5 -0 · 1次编辑 │ │
|
||||
│ │ ──────────────────────────────── │ │
|
||||
│ │ ✅ Accept All ❌ Reject All │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
│ ↓ 点击文件 │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ VSCode 内置 Diff 编辑器 │ │
|
||||
│ │ ┌──── 原始代码 ──┬── 变更后 ────┐ │ │
|
||||
│ │ │ ... │ ... │ │ │
|
||||
│ │ └───────────────┴──────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ 状态栏: [✓ Accept] [✗ Reject] │ │
|
||||
│ │ [✓✓ 接受此文件全部] │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
│ ↓ Accept/Reject │
|
||||
│ → 自动推进到下一个文件/同文件剩余编辑 │
|
||||
│ → 全部完成: 🎉 通知 │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 快捷键
|
||||
|
||||
| 快捷键 | 条件 | 功能 |
|
||||
|--------|------|------|
|
||||
| `Alt+↓` | `aiDiffPreview.isActive` | 下一个变更文件 |
|
||||
| `Alt+↑` | `aiDiffPreview.isActive` | 上一个变更文件 |
|
||||
| `Tab` | `aiDiffPreview.isActive` | 接受当前编辑 |
|
||||
| `Esc` | `aiDiffPreview.isActive` | 拒绝所有变更 |
|
||||
| `Ctrl+Shift+A` | `aiDiffPreview.isActive` | Accept All |
|
||||
| `Ctrl+Shift+R` | `aiDiffPreview.isActive` | Reject All |
|
||||
| `Ctrl+Shift+D` | `aiDiffPreview.isActive` | 显示文件列表 |
|
||||
| `Ctrl+Shift+F` | `aiDiffPreview.isActive` | 查看当前文件 Diff |
|
||||
| 快捷键 | 条件 | 功能 |
|
||||
| ---------------- | -------------------------- | ----------------------- |
|
||||
| `Alt+↓` | `aiDiffPreview.isActive` | 下一个变更文件 |
|
||||
| `Alt+↑` | `aiDiffPreview.isActive` | 上一个变更文件 |
|
||||
| `Ctrl+Shift+D` | `aiDiffPreview.isActive` | 显示 QuickPick 文件列表 |
|
||||
| `Ctrl+Shift+F` | `aiDiffPreview.isActive` | 查看当前文件 Diff |
|
||||
| `Ctrl+Shift+A` | `aiDiffPreview.isActive` | Accept All |
|
||||
| `Ctrl+Shift+R` | `aiDiffPreview.isActive` | Reject All |
|
||||
|
||||
### 命令
|
||||
|
||||
| 命令 ID | 标题 |
|
||||
| ------------------------------------- | ----------------------------- |
|
||||
| `aiDiffPreview.showDiffPanel` | AI Diff: 显示所有变更文件列表 |
|
||||
| `aiDiffPreview.showCurrentFileDiff` | AI Diff: 查看当前文件 Diff |
|
||||
| `aiDiffPreview.acceptCurrentEdit` | AI Diff: 接受当前编辑 |
|
||||
| `aiDiffPreview.rejectCurrentEdit` | AI Diff: 拒绝当前编辑 |
|
||||
| `aiDiffPreview.acceptAll` | AI Diff: 接受所有变更 |
|
||||
| `aiDiffPreview.rejectAll` | AI Diff: 拒绝所有变更 |
|
||||
| `aiDiffPreview.nextDiff` | AI Diff: 下一个变更 |
|
||||
| `aiDiffPreview.prevDiff` | AI Diff: 上一个变更 |
|
||||
|
||||
### 配置项
|
||||
|
||||
| 配置项 | 类型 | 默认值 | 说明 |
|
||||
|--------|------|--------|------|
|
||||
| `aiDiffPreview.enableAutoTrigger` | boolean | true | 启用自动触发 |
|
||||
| `aiDiffPreview.autoShowDiffPerEdit` | boolean | false | 每次编辑自动弹 Diff |
|
||||
| `aiDiffPreview.showAllDiffsOnStop` | boolean | true | Stop 后弹文件列表 |
|
||||
| `aiDiffPreview.floatingLabelMode` | string | "statusBar" | 浮动标签位置 |
|
||||
| `aiDiffPreview.maxFileSize` | number | 100000 | 最大文件大小 |
|
||||
|
||||
## 开发
|
||||
|
||||
```bash
|
||||
npm run watch # 监听模式
|
||||
npm run test # 运行测试 (13 tests)
|
||||
npm run lint # 代码检查
|
||||
npm run package # 打包 vsix
|
||||
```
|
||||
| 配置项 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------------------- | ------- | --------------- | ------------------------------------------------ |
|
||||
| `aiDiffPreview.enableAutoTrigger` | boolean | `true` | 启用自动触发(监听 pending.json) |
|
||||
| `aiDiffPreview.autoShowDiffPerEdit` | boolean | `false` | 每次 Edit/Write 后自动弹出 Diff |
|
||||
| `aiDiffPreview.showAllDiffsOnStop` | boolean | `true` | Stop 后自动弹出 QuickPick 总览 |
|
||||
| `aiDiffPreview.floatingLabelMode` | string | `"statusBar"` | 浮动标签位置(statusBar / inline / both / none) |
|
||||
| `aiDiffPreview.maxFileSize` | number | `100000` | 最大处理文件大小(字符数) |
|
||||
|
||||
## 项目结构
|
||||
|
||||
@@ -73,25 +114,50 @@ npm run package # 打包 vsix
|
||||
src/
|
||||
├── extension.ts # 插件入口
|
||||
├── trigger/
|
||||
│ └── hookHandler.ts # Hook 处理器 + QuickPick 文件列表
|
||||
│ └── hookHandler.ts # Hook 处理器 + QuickPick 总览
|
||||
├── snapshot/
|
||||
│ └── snapshotManager.ts # 变更集管理器 (ChangeSetManager)
|
||||
├── diff/
|
||||
│ └── diffEngine.ts # Diff 计算引擎
|
||||
├── render/
|
||||
│ ├── diffViewer.ts # ★ VSCode 内置 Diff 查看器
|
||||
│ ├── reviewPanel.ts # Webview 面板 (次要)
|
||||
│ ├── inlineDecorator.ts # 内联装饰器
|
||||
│ ├── codeLensProvider.ts # CodeLens 提供器
|
||||
│ └── statusBar.ts # 状态栏
|
||||
│ ├── diffViewer.ts # VSCode 内置 Diff 查看器 + 自动推进
|
||||
│ ├── reviewPanel.ts # Webview 面板 (实验性/备用)
|
||||
│ ├── inlineDecorator.ts # 内联装饰器 (备用)
|
||||
│ ├── codeLensProvider.ts # CodeLens 提供器 (备用)
|
||||
│ └── statusBar.ts # 状态栏管理器 (常驻 + Diff 模式)
|
||||
├── transaction/
|
||||
│ ├── acceptHandler.ts # Accept 处理器
|
||||
│ └── rejectHandler.ts # Reject 处理器
|
||||
└── models/
|
||||
├── types.ts # 类型定义
|
||||
└── constants.ts # 常量定义
|
||||
│ ├── acceptHandler.ts # Accept 处理器 (旧版)
|
||||
│ └── rejectHandler.ts # Reject 处理器 (旧版)
|
||||
├── models/
|
||||
│ ├── types.ts # 类型定义
|
||||
│ └── constants.ts # 常量定义
|
||||
└── __tests__/
|
||||
├── diffEngine.test.ts # Diff 引擎测试
|
||||
└── changeSetManager.test.ts # 变更集管理器回归测试
|
||||
```
|
||||
|
||||
## License
|
||||
## 开发
|
||||
|
||||
MIT
|
||||
```bash
|
||||
npm run watch # esbuild 监听模式 + sourcemap
|
||||
npm run build # 生产构建 (minify)
|
||||
npm run test # 运行测试 (13 tests)
|
||||
npm run test:watch # 测试监听模式
|
||||
npm run lint # ESLint
|
||||
npm run package # vsce package → .vsix
|
||||
```
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 领域 | 选型 |
|
||||
| --------- | -------------------- |
|
||||
| 框架 | VSCode Extension API |
|
||||
| 语言 | TypeScript (ES2022) |
|
||||
| Diff 算法 | `diff` (Myers) |
|
||||
| 绑定 | esbuild |
|
||||
| 测试 | Vitest |
|
||||
| 规范 | ESLint + Prettier |
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT © 2026 [Gmaker689](https://github.com/Gmaker689)
|
||||
|
||||
Reference in New Issue
Block a user