mirror of
https://github.com/Gmaker689/ai-diff-preview.git
synced 2026-10-01 13:51:52 +08:00
refactor: 用 StopFailure 事件替代定时轮询,移除空闲检测定时器
- 移除 heartbeat 空闲检测机制(PreToolUse 空 matcher) - 新增 StopFailure hooks 处理 API 错误中断场景 - PostToolUse 仅保留 Edit(Write 通过 PreToolUse 快照实现) - 移除 extension.ts 中 idleTimer/idleCooldown/heartbeatWatcher - 更新 README hooks 配置文档 - 添加 MIT LICENSE
This commit is contained in:
+44
-10
@@ -30,6 +30,10 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
hookHandler = new HookHandler(changeSetManager, diffViewer);
|
||||
statusBar = new StatusBarManager(changeSetManager, diffViewer);
|
||||
|
||||
// ★ 设置 hook 目录路径,供 snapshotManager 读取 PreToolUse 快照
|
||||
const hookDir = getHookDir();
|
||||
if (hookDir) changeSetManager.setHookDir(hookDir);
|
||||
|
||||
// DiffViewer 操作后刷新状态栏
|
||||
diffViewer.onDiffAction = () => refreshUI();
|
||||
|
||||
@@ -95,6 +99,24 @@ function registerCommands(context: vscode.ExtensionContext) {
|
||||
vscode.commands.registerCommand(COMMANDS.PREV_DIFF, () => navigateDiff(-1))
|
||||
);
|
||||
|
||||
// ★ 逐次编辑导航
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('aiDiffPreview.nextEdit', () => diffViewer.showNextEdit())
|
||||
);
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('aiDiffPreview.prevEdit', () => diffViewer.showPrevEdit())
|
||||
);
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('aiDiffPreview.showEditAtIndex', () => {
|
||||
const session = diffViewer.getActiveSession();
|
||||
if (session) {
|
||||
const set = changeSetManager.getCurrentSet();
|
||||
const fc = set?.changes.find(c => c.id === session.fileId);
|
||||
if (fc) diffViewer.showEditAtIndex(fc, 0);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Diff 界面状态栏按钮
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('aiDiffPreview.acceptCurrentDiff', async () => {
|
||||
@@ -150,6 +172,14 @@ function refreshUI(): void {
|
||||
vscode.commands.executeCommand('setContext', 'aiDiffPreview.isActive', hasPending);
|
||||
}
|
||||
|
||||
// ---- Hook 目录 ----
|
||||
|
||||
function getHookDir(): string | null {
|
||||
const folder = vscode.workspace.workspaceFolders?.[0];
|
||||
if (!folder) return null;
|
||||
return path.join(folder.uri.fsPath, '.claude', 'hooks');
|
||||
}
|
||||
|
||||
// ---- Hook 监听 ----
|
||||
|
||||
function registerHookFileWatcher(context: vscode.ExtensionContext) {
|
||||
@@ -160,11 +190,13 @@ function registerHookFileWatcher(context: vscode.ExtensionContext) {
|
||||
if (!fs.existsSync(hookDir)) fs.mkdirSync(hookDir, { recursive: true });
|
||||
|
||||
const pendingFile = path.join(hookDir, 'pending.json');
|
||||
const watcher = vscode.workspace.createFileSystemWatcher(
|
||||
|
||||
// ★ 监听 pending.json(Edit/Stop/StopFailure 事件)
|
||||
const pendingWatcher = vscode.workspace.createFileSystemWatcher(
|
||||
new vscode.RelativePattern(hookDir, 'pending.json')
|
||||
);
|
||||
|
||||
const handle = () => {
|
||||
const handlePending = () => {
|
||||
try {
|
||||
if (!fs.existsSync(pendingFile)) return;
|
||||
const content = fs.readFileSync(pendingFile, 'utf-8');
|
||||
@@ -172,18 +204,20 @@ function registerHookFileWatcher(context: vscode.ExtensionContext) {
|
||||
const event: ClaudeHookEvent = JSON.parse(content);
|
||||
if (Date.now() - event.timestamp > 10000) return;
|
||||
|
||||
if (event.toolName === 'Stop') {
|
||||
if (event.toolName === 'Stop' || event.toolName === 'StopFailure') {
|
||||
// ★ 对话结束(正常完成或 API 失败)→ 触发 diff 总览
|
||||
hookHandler.handleStop();
|
||||
} else if (event.toolName === 'Edit' || event.toolName === 'Write') {
|
||||
} else if (event.toolName === 'Edit') {
|
||||
hookHandler.handleEdit(event);
|
||||
}
|
||||
refreshUI();
|
||||
} catch (e) { console.error('[AI Diff] 处理触发文件失败:', e); }
|
||||
} catch (e) { console.error('[AI Diff] 处理 pending 文件失败:', e); }
|
||||
};
|
||||
|
||||
watcher.onDidChange(handle);
|
||||
watcher.onDidCreate(handle);
|
||||
context.subscriptions.push(watcher);
|
||||
pendingWatcher.onDidChange(handlePending);
|
||||
pendingWatcher.onDidCreate(handlePending);
|
||||
context.subscriptions.push(pendingWatcher);
|
||||
|
||||
console.log(`[AI Diff] Hook 监听已启动: ${hookDir}`);
|
||||
}
|
||||
|
||||
@@ -199,8 +233,8 @@ function checkPendingHookFile() {
|
||||
fs.unlinkSync(pendingFile);
|
||||
const event: ClaudeHookEvent = JSON.parse(content);
|
||||
if (Date.now() - event.timestamp < 15000) {
|
||||
if (event.toolName === 'Stop') hookHandler.handleStop();
|
||||
else if (event.toolName === 'Edit' || event.toolName === 'Write') hookHandler.handleEdit(event);
|
||||
if (event.toolName === 'Stop' || event.toolName === 'StopFailure') hookHandler.handleStop();
|
||||
else if (event.toolName === 'Edit') hookHandler.handleEdit(event);
|
||||
refreshUI();
|
||||
}
|
||||
} catch (e) { console.error('[AI Diff] 处理 pending hook 失败:', e); }
|
||||
|
||||
Reference in New Issue
Block a user