Skip to content

Commit c88eb5f

Browse files
committed
fix: report edit failures to AI and hint live preview reload
Edit/Write hooks now return actual error messages instead of false success. When the edited file is part of the active live preview, the response hints the AI to reload via execJsInLivePreview.
1 parent 8967c86 commit c88eb5f

File tree

3 files changed

+41
-9
lines changed

3 files changed

+41
-9
lines changed

src-node/claude-code-agent.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,16 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale)
281281
toolId: myToolId,
282282
edit: edit
283283
});
284-
const reason = (editResult && editResult.applied === false)
285-
? "Edit FAILED: " + (editResult.error || "unknown error")
286-
: "Edit applied successfully via Phoenix editor.";
284+
let reason;
285+
if (editResult && editResult.applied === false) {
286+
reason = "Edit FAILED: " + (editResult.error || "unknown error");
287+
} else {
288+
reason = "Edit applied successfully via Phoenix editor.";
289+
if (editResult && editResult.isLivePreviewRelated) {
290+
reason += " The edited file is part of the active live preview." +
291+
" Reload when ready with execJsInLivePreview: `location.reload()`";
292+
}
293+
}
287294
return {
288295
hookSpecificOutput: {
289296
hookEventName: "PreToolUse",
@@ -347,21 +354,33 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale)
347354
newText: input.tool_input.content
348355
};
349356
editCount++;
357+
let writeResult;
350358
try {
351-
await nodeConnector.execPeer("applyEditToBuffer", edit);
359+
writeResult = await nodeConnector.execPeer("applyEditToBuffer", edit);
352360
} catch (err) {
353361
console.warn("[Phoenix AI] Failed to apply write to buffer:", err.message);
362+
writeResult = { applied: false, error: err.message };
354363
}
355364
nodeConnector.triggerPeer("aiToolEdit", {
356365
requestId: requestId,
357366
toolId: myToolId,
358367
edit: edit
359368
});
369+
let reason;
370+
if (writeResult && writeResult.applied === false) {
371+
reason = "Write FAILED: " + (writeResult.error || "unknown error");
372+
} else {
373+
reason = "Write applied successfully via Phoenix editor.";
374+
if (writeResult && writeResult.isLivePreviewRelated) {
375+
reason += " The written file is part of the active live preview." +
376+
" Reload when ready with execJsInLivePreview: `location.reload()`";
377+
}
378+
}
360379
return {
361380
hookSpecificOutput: {
362381
hookEventName: "PreToolUse",
363382
permissionDecision: "deny",
364-
permissionDecisionReason: "Write applied successfully via Phoenix editor."
383+
permissionDecisionReason: reason
365384
}
366385
};
367386
}

src/core-ai/AIChatPanel.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,6 @@ define(function (require, exports, module) {
905905
// Record pre-edit content into pending snapshot and back-fill
906906
SnapshotStore.recordFileBeforeEdit(edit.file, previousContent, isNewFile);
907907

908-
// Reload live preview so the user sees the edit reflected immediately
909-
CommandManager.execute(Commands.CMD_RELOAD_LIVE_PREVIEW);
910-
911908
// Find the oldest Edit/Write tool indicator for this file that doesn't
912909
// already have edit actions. This is more robust than matching by toolId
913910
// because the SDK with includePartialMessages may re-emit tool_use blocks

src/core-ai/aiPhoenixConnectors.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,14 +442,30 @@ define(function (require, exports, module) {
442442
* @param {Object} params - {file, oldText, newText}
443443
* @return {Promise<{applied: boolean, error?: string}>}
444444
*/
445+
function _isFileInLivePreview(filePath) {
446+
const liveDetails = LiveDevMain.getLivePreviewDetails();
447+
if (!liveDetails || !liveDetails.liveDocument) {
448+
return false;
449+
}
450+
const vfsPath = SnapshotStore.realToVfsPath(filePath);
451+
const liveDocPath = liveDetails.liveDocument.doc.file.fullPath;
452+
if (vfsPath === liveDocPath) {
453+
return true;
454+
}
455+
return !!(liveDetails.liveDocument.isRelated && liveDetails.liveDocument.isRelated(vfsPath));
456+
}
457+
445458
function applyEditToBuffer(params) {
446459
const deferred = new $.Deferred();
447460
_applySingleEdit(params)
448461
.done(function (result) {
449462
if (result && result.previousContent !== undefined) {
450463
_previousContentMap[params.file] = result.previousContent;
451464
}
452-
deferred.resolve({ applied: true });
465+
deferred.resolve({
466+
applied: true,
467+
isLivePreviewRelated: _isFileInLivePreview(params.file)
468+
});
453469
})
454470
.fail(function (err) {
455471
deferred.resolve({ applied: false, error: err.message || String(err) });

0 commit comments

Comments
 (0)