diff --git a/src-node/claude-code-agent.js b/src-node/claude-code-agent.js index d863e1201..921c286a0 100644 --- a/src-node/claude-code-agent.js +++ b/src-node/claude-code-agent.js @@ -363,6 +363,8 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale, "multiple Edit calls to make targeted changes rather than rewriting the entire " + "file with Write. This is critical because Write replaces the entire file content " + "which is slow and loses undo history." + + "\n\nAlways use full absolute paths for all file operations (Read, Edit, Write, " + + "controlEditor). Never use relative paths." + "\n\nWhen a tool response mentions the user has typed a clarification, immediately " + "call getUserClarification to read it and incorporate the user's feedback into your current work." + (locale && !locale.startsWith("en") diff --git a/src-node/mcp-editor-tools.js b/src-node/mcp-editor-tools.js index 962456d68..d04b698ae 100644 --- a/src-node/mcp-editor-tools.js +++ b/src-node/mcp-editor-tools.js @@ -61,7 +61,7 @@ function createEditorMcpServer(sdkModule, nodeConnector, clarificationAccessors) const hasClarification = clarificationAccessors && clarificationAccessors.hasClarification; const getEditorStateTool = sdkModule.tool( "getEditorState", - "Get the current Phoenix editor state: active file, working set (open files), live preview file, " + + "Get the current Phoenix editor state: active file, working set (open files with isDirty flag), live preview file, " + "cursor/selection info (current line text with surrounding context, or selected text), " + "and the currently selected element in the live preview (tag, selector, text preview) if any. " + "The live preview selected element may differ from the editor cursor — use execJsInLivePreview to inspect it further. " + diff --git a/src/core-ai/AIChatPanel.js b/src/core-ai/AIChatPanel.js index b6a6a616d..1d542c8ad 100644 --- a/src/core-ai/AIChatPanel.js +++ b/src/core-ai/AIChatPanel.js @@ -45,6 +45,7 @@ define(function (require, exports, module) { const _KernalModeTrust = window.KernalModeTrust; let _nodeConnector = null; + let _currentEntitlementState = null; // "chat" | "login" | "upsell" | "adminDisabled" | null let _isStreaming = false; let _queuedMessage = null; // text queued by user while AI is streaming let _currentRequestId = null; @@ -240,15 +241,20 @@ define(function (require, exports, module) { * upsell screen if no AI plan, or proceeds to CLI availability check if entitled. */ function _checkEntitlementAndInit() { - _removeCurrentPanel(); const EntitlementsManager = _KernalModeTrust && _KernalModeTrust.EntitlementsManager; if (!EntitlementsManager) { // No entitlement system (test env or dev) — skip straight to CLI check - _checkAvailability(); + if (_currentEntitlementState !== "chat") { + _removeCurrentPanel(); + _checkAvailability(); + } return; } if (!EntitlementsManager.isLoggedIn()) { - _renderLoginUI(); + if (_currentEntitlementState !== "login") { + _removeCurrentPanel(); + _renderLoginUI(); + } return; } // TODO: Switch to EntitlementsManager.getAIEntitlement() once AI entitlement is @@ -267,12 +273,21 @@ define(function (require, exports, module) { // }); EntitlementsManager.getLiveEditEntitlement().then(function (entitlement) { if (entitlement.activated) { - _checkAvailability(); + if (_currentEntitlementState !== "chat") { + _removeCurrentPanel(); + _checkAvailability(); + } } else { - _renderUpsellUI(entitlement); + if (_currentEntitlementState !== "upsell") { + _removeCurrentPanel(); + _renderUpsellUI(entitlement); + } } }).catch(function () { - _checkAvailability(); // fallback on error + if (_currentEntitlementState !== "chat") { + _removeCurrentPanel(); + _checkAvailability(); // fallback on error + } }); } @@ -280,6 +295,7 @@ define(function (require, exports, module) { * Render the login prompt UI (user not signed in). */ function _renderLoginUI() { + _currentEntitlementState = "login"; const html = '