feat(permission): 实现 WebSocket 权限确认机制

重构权限系统,将终端 UI 代码从 core 模块移除,实现基于 WebSocket 的权限确认流程:

Core 模块清理:
- 删除 permission/prompt.ts 和 file-prompt.ts(终端交互)
- 删除 diff.ts 中的 chalk 渲染函数
- 删除 config.ts 中的 inquirer 交互
- 移除 chalk 依赖

Server 权限处理:
- 新增 permission/handler.ts,实现 WebSocket 权限请求/响应
- 更新 agent/adapter.ts 设置权限回调
- 更新 ws.ts 处理 permission_response 消息

Web 权限组件:
- 新增 PermissionDialog 组件,显示权限请求详情和 Diff
- 更新 useChat hook 管理权限状态
- 更新 Chat 页面集成权限弹窗
This commit is contained in:
2025-12-13 01:09:35 +08:00
parent 5d4afecd48
commit 1d69fd876d
20 changed files with 739 additions and 1560 deletions
+1 -75
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest';
import { computeDiff, countChanges, formatEditDiff, formatDiff } from '../../../src/utils/diff.js';
import { computeDiff, countChanges } from '../../../src/utils/diff.js';
describe('computeDiff - 计算文件差异', () => {
describe('新文件', () => {
@@ -156,31 +156,6 @@ describe('countChanges - 统计变更数量', () => {
});
});
describe('formatEditDiff - 格式化编辑差异', () => {
it('显示删除和新增内容', () => {
const result = formatEditDiff('old text', 'new text');
expect(result).toContain('变更内容');
expect(result).toContain('old text');
expect(result).toContain('new text');
});
it('多行内容正确显示', () => {
const result = formatEditDiff('line1\nline2', 'new1\nnew2\nnew3');
expect(result).toContain('line1');
expect(result).toContain('line2');
expect(result).toContain('new1');
expect(result).toContain('new2');
expect(result).toContain('new3');
});
it('空内容处理', () => {
const result = formatEditDiff('', 'new');
expect(result).toContain('new');
});
});
describe('DiffResult 结构', () => {
it('包含所有必要字段', () => {
@@ -248,55 +223,6 @@ describe('LCS 算法测试', () => {
});
});
describe('formatDiff - 格式化 diff 输出', () => {
it('新文件显示新增标记', () => {
const diff = computeDiff(null, 'line1\nline2');
const result = formatDiff(diff, '/test/file.ts');
expect(result).toContain('新文件');
expect(result).toContain('/test/file.ts');
});
it('修改文件显示原文件和修改后标记', () => {
const diff = computeDiff('old', 'new');
const result = formatDiff(diff, '/test/file.ts');
expect(result).toContain('原文件');
expect(result).toContain('修改后');
expect(result).toContain('/test/file.ts');
});
it('hunk 头部显示正确的行号范围', () => {
const diff = computeDiff('line1\nline2', 'line1\nnew\nline2');
const result = formatDiff(diff, '/test/file.ts');
expect(result).toContain('@@');
});
it('新增行显示 + 前缀', () => {
const diff = computeDiff(null, 'added line');
const result = formatDiff(diff, '/test/file.ts');
expect(result).toContain('+');
expect(result).toContain('added line');
});
it('删除行显示 - 前缀', () => {
const diff = computeDiff('removed line', 'new line');
const result = formatDiff(diff, '/test/file.ts');
expect(result).toContain('-');
expect(result).toContain('removed line');
});
it('空 diff 返回基本格式', () => {
const diff = computeDiff('same', 'same');
const result = formatDiff(diff, '/test/file.ts');
// 没有 hunks 时只有头部
expect(result).toContain('/test/file.ts');
});
});
describe('实际代码场景', () => {
it('函数修改', () => {