diff --git a/src-node/claude-code-agent.js b/src-node/claude-code-agent.js index 108bad9d1..fac1e11ac 100644 --- a/src-node/claude-code-agent.js +++ b/src-node/claude-code-agent.js @@ -474,6 +474,9 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale, "capture the full editor, specific panels, the code area, or the live preview. " + "For HTML/CSS/JS with live preview, execJsInLivePreview can run JS in the " + "browser to confirm behavior." + + "\n\nFor tasks that involve creating new applications, extensive modifications, " + + "or architectural changes, enter plan mode first to propose a plan " + + "for user approval before writing code." + (locale && !locale.startsWith("en") ? "\n\nThe user's display language is " + locale + ". " + "Respond in this language unless they write in a different language." @@ -583,27 +586,33 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale, async (input) => { console.log("[Phoenix AI] Intercepted Write tool"); // Capture plan content when writing to .claude/plans/ - // Don't open plan files in editor — shown in plan card UI + // Plan files: capture content for plan card, write to disk + // but don't open in editor const writePath = input.tool_input.file_path || ""; - if (writePath.includes("/.claude/plans/")) { + const normalizedPath = writePath.replace(/\\/g, "/"); + if (normalizedPath.includes("/.claude/plans/")) { _lastPlanContent = input.tool_input.content || ""; console.log("[Phoenix AI] Captured plan content:", _lastPlanContent.length + "ch"); + // Write to disk so Claude can read it back later + try { + const dir = path.dirname(writePath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + fs.writeFileSync(writePath, input.tool_input.content || "", "utf8"); + } catch (err) { + console.warn("[Phoenix AI] Failed to write plan file:", err.message); + } + let planReason = "Plan file saved."; if (_queuedClarification) { - return { - hookSpecificOutput: { - hookEventName: "PreToolUse", - permissionDecision: "deny", - permissionDecisionReason: - "Plan file saved." + CLARIFICATION_HINT - } - }; + planReason += CLARIFICATION_HINT; } return { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", - permissionDecisionReason: "Plan file saved." + permissionDecisionReason: planReason } }; } diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 18d6cd7dc..113f66fa6 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -1829,6 +1829,7 @@ define({ "AI_UPSELL_DIALOG_MESSAGE": "You’ve discovered {0}. To proceed, you’ll need an AI subscription or credits.", // AI CHAT PANEL + "AI_CHAT_TITLE_NO_AI": "Phoenix Code AI", "AI_CHAT_TITLE": "Claude Code", "AI_CHAT_NEW_SESSION_TITLE": "Start a new conversation", "AI_CHAT_NEW_BTN": "New", @@ -1924,6 +1925,14 @@ define({ "AI_CHAT_PLAN_APPROVE": "Approve", "AI_CHAT_PLAN_REVISE": "Revise", "AI_CHAT_PLAN_FEEDBACK_PLACEHOLDER": "What would you like changed?", + "AI_CHAT_PLAN_REVISE_DEFAULT": "Please revise the plan.", + "AI_CHAT_CODE_DEFAULT_LANG": "text", + "AI_CHAT_CODE_COLLAPSE": "Collapse", + "AI_CHAT_CODE_EXPAND": "Expand", + "AI_CHAT_CODE_EXPAND_LINES": "Click to expand - {0} lines", + "AI_CHAT_CODE_COLLAPSE_FOOTER": "Click to collapse", + "AI_CHAT_PREVIEW_OPEN": "Preview", + "AI_CHAT_PREVIEW_VIEWING": "Previewing", "AI_CHAT_QUESTION_OTHER": "Type a custom answer\u2026", "AI_CHAT_IMAGE_LIMIT": "Maximum {0} images allowed", "AI_CHAT_IMAGE_REMOVE": "Remove image", diff --git a/src/styles/Extn-AIChatPanel.less b/src/styles/Extn-AIChatPanel.less index 721f9de7c..0aee24059 100644 --- a/src/styles/Extn-AIChatPanel.less +++ b/src/styles/Extn-AIChatPanel.less @@ -410,7 +410,7 @@ color: @project-panel-text-1; padding: 1px 4px; border-radius: 3px; - font-size: @sidebar-small-font-size; + font-size: @sidebar-md-code-font-size; font-family: 'SourceCodePro-Medium', 'SourceCodePro', monospace; } @@ -423,39 +423,20 @@ margin: 6px 0; position: relative; + &.collapsed code { + display: block; + max-height: 7.5em; // ~5 lines at 1.5 line-height + overflow: hidden; + } + code { background: none; padding: 0; border-radius: 0; - font-size: @sidebar-small-font-size; + font-size: 1em; line-height: 1.5; color: @project-panel-text-1; } - - .ai-copy-btn { - position: absolute; - top: 4px; - right: 4px; - background: rgba(255, 255, 255, 0.08); - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 4px; - color: rgba(255, 255, 255, 0.5); - cursor: pointer; - padding: 2px 6px; - font-size: 12px; - line-height: 1; - opacity: 0; - transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease; - - &:hover { - background: rgba(255, 255, 255, 0.15); - color: rgba(255, 255, 255, 0.85); - } - } - - &:hover .ai-copy-btn { - opacity: 1; - } } ul, ol { @@ -475,14 +456,22 @@ } h1, h2, h3, h4 { - font-weight: 600; color: @project-panel-text-1; + line-height: 1.25em; } - h1 { font-size: @label-font-size; margin: 12px 0 4px 0; } - h2 { font-size: @menu-item-font-size; margin: 10px 0 4px 0; } - h3 { font-size: @sidebar-content-font-size; margin: 8px 0 3px 0; } - h4 { font-size: @sidebar-content-font-size; margin: 6px 0 2px 0; opacity: 0.85; } + h1 { + font-size: @sidebar-md-h1-font-size; + margin: 12px 0 4px 0; + padding-bottom: .3em; + } + h2 { + font-size: @sidebar-md-h2-font-size; + margin: 10px 0 4px 0; + padding-bottom: .3em; + } + h3 { font-size: @sidebar-md-h3-font-size; margin: 8px 0 4px 0; } + h4 { font-size: @sidebar-md-h4-font-size; margin: 6px 0 4px 0; opacity: 0.85; } table { display: block; @@ -858,6 +847,42 @@ } } +.ai-edit-preview-btn { + display: flex; + align-items: center; + gap: 4px; + margin-top: 6px; + background: rgba(102, 187, 106, 0.1); + border: 1px solid rgba(102, 187, 106, 0.25); + color: #66bb6a; + font-size: @sidebar-small-font-size; + padding: 4px 12px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.15s ease, border-color 0.15s ease; + + &:hover:not(.active) { + background: rgba(102, 187, 106, 0.18); + border-color: rgba(102, 187, 106, 0.4); + } + + &.active { + background: rgba(102, 187, 106, 0.15); + border-color: rgba(102, 187, 106, 0.3); + color: #66bb6a; + cursor: pointer; + + &:hover { + background: rgba(102, 187, 106, 0.1); + border-color: rgba(102, 187, 106, 0.2); + } + } + + i { + font-size: 11px; + } +} + /* ── Initial restore point (PUC) ────────────────────────────────────── */ .ai-msg-restore-point { display: flex; @@ -1076,6 +1101,83 @@ } } +/* ── Code block title bar ──────────────────────────────────────────── */ +.ai-code-header { + display: flex; + align-items: center; + justify-content: space-between; + margin: -8px -10px 6px -10px; + padding: 4px 8px; + background-color: rgba(255, 255, 255, 0.04); + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 3px 3px 0 0; + font-size: @sidebar-small-font-size; + user-select: none; +} + +.ai-code-lang { + color: @project-panel-text-2; + text-transform: lowercase; +} + +.ai-code-actions { + display: flex; + align-items: center; + gap: 2px; +} + +.ai-code-copy-btn, +.ai-code-collapse-btn { + background: none; + border: none; + color: @project-panel-text-2; + cursor: pointer; + padding: 1px 5px; + border-radius: 3px; + font-size: @sidebar-small-font-size; + line-height: 1; + transition: background-color 0.15s ease, color 0.15s ease; + + &:hover { + background: rgba(255, 255, 255, 0.08); + color: @project-panel-text-1; + } + + i { + font-size: 11px; + } +} + +.ai-code-copy-btn span { + margin-left: 2px; +} + +.ai-code-footer { + display: flex; + justify-content: center; + margin: 6px -10px -8px -10px; + padding: 3px 8px; + background-color: rgba(255, 255, 255, 0.04); + border-top: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 0 0 3px 3px; +} + +.ai-code-expand-btn { + background: none; + border: none; + color: @project-panel-text-2; + cursor: pointer; + font-size: @sidebar-small-font-size; + padding: 1px 8px; + border-radius: 3px; + transition: background-color 0.15s ease, color 0.15s ease; + + &:hover { + background: rgba(255, 255, 255, 0.08); + color: @project-panel-text-1; + } +} + /* ── Plan card (ExitPlanMode) ───────────────────────────────────────── */ .ai-msg-plan { margin-bottom: 8px; @@ -1114,24 +1216,78 @@ } } + h1, h2, h3, h4 { + color: @project-panel-text-1; + line-height: 1.25em; + } + + h1 { + font-size: @sidebar-md-h1-font-size; + margin: 12px 0 4px 0; + padding-bottom: .3em; + } + h2 { + font-size: @sidebar-md-h2-font-size; + margin: 10px 0 4px 0; + padding-bottom: .3em; + } + h3 { font-size: @sidebar-md-h3-font-size; margin: 8px 0 4px 0; } + h4 { font-size: @sidebar-md-h4-font-size; margin: 6px 0 4px 0; opacity: 0.85; } + + strong { + color: @project-panel-text-1; + } + + a { + color: #6b9eff; + } + + blockquote { + border-left: 3px solid rgba(107, 158, 255, 0.3); + margin: 6px 0; + padding: 2px 10px; + color: @project-panel-text-2; + } + code { - background: rgba(255, 255, 255, 0.06); + background-color: rgba(255, 255, 255, 0.08); + color: @project-panel-text-1; padding: 1px 4px; border-radius: 3px; - font-size: 0.9em; + font-size: @sidebar-md-code-font-size; + font-family: 'SourceCodePro-Medium', 'SourceCodePro', monospace; } pre { - background: rgba(0, 0, 0, 0.2); - padding: 8px; + background-color: rgba(0, 0, 0, 0.3); + border: 1px solid rgba(255, 255, 255, 0.06); + padding: 8px 10px; border-radius: 4px; overflow-x: auto; + position: relative; + + &.collapsed code { + display: none; + } code { background: none; padding: 0; + border-radius: 0; + font-size: 1em; + line-height: 1.5; + color: @project-panel-text-1; } } + + ul, ol { + margin: 4px 0 8px 0; + padding-left: 18px; + } + + li { + margin-bottom: 2px; + } } .ai-plan-actions { diff --git a/src/styles/brackets_variables.less b/src/styles/brackets_variables.less index b690782ed..32061a5c8 100644 --- a/src/styles/brackets_variables.less +++ b/src/styles/brackets_variables.less @@ -37,6 +37,11 @@ @sidebar-small-font-size: 12px; // secondary content, inline code, status text @sidebar-xs-font-size: 11px; // meta info, timestamps, chips +@sidebar-md-h1-font-size: 2em; +@sidebar-md-h2-font-size: 1.5em; +@sidebar-md-h3-font-size: 1.25em; +@sidebar-md-h4-font-size: 1.1em; +@sidebar-md-code-font-size: .9em; /* CSS triangles */ @inline-triangle-size: 9px; @@ -72,4 +77,4 @@ @z-index-brackets-context-menu-base: 1000; @z-index-brackets-stylesheet-menu: 1000; @z-index-brackets-inline-editor-error: 1000; -@z-index-brackets-topmost-overlay: 10000; \ No newline at end of file +@z-index-brackets-topmost-overlay: 10000; diff --git a/tracking-repos.json b/tracking-repos.json index 50016da60..66abb0da1 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "ca8641e99f5954e259d1408d8bda62a5a16d4384" + "commitID": "21f226b54906adc5bd2cb0dd0d68d587dc9d22fe" } }