Add multiple features and fix many things#7
Open
the-dem wants to merge 115 commits into
Open
Conversation
Enhanced permission request display for ExitPlanMode: - JavaScript now checks if input has a "plan" field - If present, renders plan content as markdown using marked.js - Otherwise, shows JSON as before This makes ExitPlanMode permission dialogs much more readable: - Formatted headings, lists, code blocks - Syntax highlighted code samples in plan - Proper typography instead of JSON string Added comprehensive CSS for .permission-plan: - Markdown element styling (h1-h3, p, ul, ol, code, pre) - Consistent with chat message markdown styling - Proper spacing and colors for dark theme - Tables support for plan documentation The plan is now shown as a nicely formatted document rather than raw JSON, making it easy to review before approving. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Bundle highlight.js and marked.js locally to avoid QWebEngineView CDN blocking. Implement automatic light/dark theme detection based on KDE color scheme luminance, dynamically applying appropriate highlight.js themes (atom-one-light/dark) and code block backgrounds. Add copy-to-clipboard button on code blocks with visual feedback and base64 encoding for reliable copying of complete code regardless of special characters. Include JavaScript bridge logging for debugging. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement ACP session mode switching following the Agent Client Protocol specification. Users can select modes (Default, Plan, Accept Edits, Don't Ask) from a dropdown above the input field, and the agent can also change modes dynamically during conversation. Add mode dropdown to ChatInputWidget with label and QComboBox showing available modes. Parse availableModes and currentModeId from session/new response. Implement session/set_mode method to change modes on user selection. Handle current_mode_update notifications from agent when it changes modes. Connect signals for bidirectional mode synchronization between UI and agent. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement QCompleter-based autocompletion for slash commands (/) and file references (@) in the chat input. Commands are populated from ACP's available_commands_update notifications, and files from project scanning. Also adds dynamic mode dropdown population from ACP, enhanced Edit/Write tool handling with diff display, and project file listing with common directory filtering. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ContextChunk struct for passing file selections as context - Implement 'Add to Context' action in Kate editor context menu - Add context chips UI to display attached file selections - Update sendMessage to include context chunks in prompt payload - Replace naive line diff with Myers' LCS-based diff algorithm 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds automatic Kate editor theme integration for syntax highlighting, supporting both user themes and built-in KSyntaxHighlighting themes (Breeze Dark, Dracula, Monokai, etc.). Code highlighting now matches Kate's color scheme with proper token colors and backgrounds. Implements proper LCS-based diff algorithm (similar to git diff) for Edit tools, replacing naive line-by-line comparison. Shows minimal change sets with context lines. Adds support for multiple edits per Edit tool call. When ACP returns multiple diffs in a single tool call, all are displayed with headers showing "Edit 1 of N: filename" for each. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add SessionStore for saving/loading session IDs per project and SessionSelectionDialog for resume vs new session choice. The ACP session layer now separates initialize from session creation, emitting initializeComplete to let ChatWidget decide the action. Session resumption is currently disabled in ChatWidget since ACP doesn't support it well - always creates new sessions for now. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add context menu quick actions: Explain Code, Find Bugs, Suggest Improvements, and Add Tests. Each sends the selected code with a prompt to Claude. Include DiffHighlightManager infrastructure for showing pending edits in the editor (currently disabled - diffs shown inline in tool call UI instead). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Read Kate's configured editor font from katerc and inject it into the chat WebView via CSS variables. Add shades-of-purple syntax highlighting theme as an option. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Disconnect signals before cleanup in ACPService destructor to prevent emission during destruction. Add Q_UNUSED for unused exitStatus param. Update chat CSS and JS with various UI improvements. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update diff rendering to preserve hljs syntax highlighting within diff lines by using inline spans and tinted backgrounds instead of overriding text color. Also update theme converter to target pre.diff selectors for consistent highlighting. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix race condition in ACPService::stop() by disconnecting signals before killing process to prevent concurrent cleanup - Add dedicated styling for Task and TaskOutput tools in chat UI with subagent type badges, background/resume indicators - Render Task tools with prompt details and model info - Add tool-specific icons (🤖 Task, 📥 TaskOutput, etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduce TranscriptWriter utility that saves session conversations as markdown files to ~/.kate-code/transcripts/, including messages, tool calls with diffs, and command results. Supports session resume with continuation markers. Update Task tool styling to use CSS variables (--task-purple, --task-purple-bg) that adapt to light/dark themes. Refactor ChatWidget header bar to use icon-only tool buttons with status indicator dot. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to cancel running prompts via stop button or Escape key, using the ACP $/cancel_request notification. Replace emoji icons with Material Symbols throughout the chat UI for a cleaner look. Organize transcripts into project-specific subfolders. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add debian/ directory and kate-code.spec for building .deb and .rpm packages. Include Dockerfiles and build-packages.sh script for cross-distro builds. Update README with installation instructions for Arch, Fedora, and Debian/Ubuntu. Also fix missing QJsonDocument include in TranscriptWriter.cpp for stricter Qt header handling on Fedora. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Detect ExitPlanMode tool completion and automatically switch the mode dropdown to the appropriate state. If launchSwarm is requested, switch to "acceptEdits" mode; otherwise switch to "default" mode. Track tool inputs by toolCallId to access parameters when tool completes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Dockerfile.arch and update build-packages.sh to support building .pkg.tar.zst packages using makepkg in a Docker container. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add SummaryGenerator and SummaryStore utilities for generating and persisting session summaries. Integrate summarization into ChatWidget and SessionSelectionDialog for improved session management. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Re-enable session resumption dialog that offers to resume with prior session summary. Add markdown rendering for user messages in chat. Clear todos when starting new session. Add debug logging for summary generation flow. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensure session summaries are generated when Kate closes by: - Connecting to QApplication::aboutToQuit in KateCodePlugin - Adding prepareForShutdown() chain through View to ChatWidget - Implementing waitForPendingRequests() in SummaryGenerator with timeout and event loop processing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow users to configure an MCP server JSON config file path per ACP provider. This enables external MCP servers (like the oia ClickHouse/S3 server) to be loaded when using Kate Code with different agents. Changes: - Added mcpConfigPath field to ACPProvider struct - Added loadExternalMcpServers() helper to read ~/.cursor/mcp.json format - Added setMcpConfigPath() to ACPSession - Updated config UI to show/edit MCP config path in provider table - Updated ChatWidget to pass MCP config path when configuring backend The MCP config path is optional. When set, external MCP servers are loaded from the JSON file and passed to the ACP session/new request alongside the built-in Kate MCP server. Co-authored-by: Cursor <cursoragent@cursor.com>
The working tree carried a coherent but uncommitted body of 1.3.1 changes (plain-text chat input, friendly permission-mode labels, Unicode icon glyphs, a clear-output control, ordered WebView update replay, and Codex KVP guidance). Leaving it uncommitted made further work hard to review and risked losing it. Commit the intentional source changes as a labelled baseline so subsequent fixes produce clean, reviewable diffs. The untracked dist/ directory of old RPM artifacts is deliberately left out. Verified: cmake --build succeeds on this tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agent output area showed a blinking block caret while a response streamed (animation: blink 1s infinite), which the user found distracting. Replace the blink animation with a steady, fixed-opacity caret and drop the now-unused @Keyframes blink rule. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was no global setting to pre-approve routine agent commands, so every command permission request had to be answered by hand. Add a global "allowed commands" glob list. SettingsStore persists it under Permissions/allowedCommands and exposes isCommandAllowed(), which matches a command against each pattern via QRegularExpression::wildcardToRegularExpression (anchored, case sensitive); an empty list approves nothing. A "Command Auto-Approval" group on the Advanced config tab edits the patterns, one per line. Wiring this matcher into the permission flow follows in a later commit. The logic was prototyped by a Sonnet worker agent; it was reintegrated here by hand because its worktree branched from origin/main and predated the reworked config page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closing Kate (or a window) while an agent session and its embedded QWebEngineView were alive could crash during teardown. The main causes: the QWebEngineView's web channel and pending runJavaScript callbacks were torn down in an uncontrolled order, and because m_chatWebView is constructed after m_session it is destroyed first, so when ~ACPSession later emits disconnected(0) the still-connected onStatusChanged handler called the already-freed web view. Give ChatWebView a real destructor and sever session/web-view signals before Qt destroys ChatWidget's children, so nothing re-enters a half-destroyed object. Implementation: - ChatWebView::~ChatWebView() now marks the page unloaded, clears the pending-script queue, disconnects the view and bridge, stops any in-flight load, and detaches the web channel (page()->setWebChannel (nullptr)) symmetrically to setupBridge(); runJavaScript()'s callback is guarded with a QPointer so late Chromium results are a no-op. - ChatWidget::~ChatWidget() disconnects m_session and m_chatWebView signals (idempotent via m_shutdownDone) but does not run summary generation, which would block on the network and pump the event loop inside a destructor. prepareForShutdown() keeps that heavier work for the application-quit path and is now null-safe. - KateCodeView removes itself from the plugin's view list on destruction (new KateCodePlugin::removeView) so onAboutToQuit() cannot dereference a freed view; it no longer calls prepareForShutdown() from its destructor, where the tool view may already be gone. - onStatusChanged() null-checks the settings store. Prototyped by a Sonnet worker agent; the coordinator reworked the shutdown-trigger placement to avoid a network wait and a use-after-free the agent's first version would have introduced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two separate Kate processes both registered the fixed DBus service name org.kde.katecode.editor, so the second process's Kate MCP server could not reach its own editor: agents in a second Kate instance lost the katecode_read/write/edit/documents tools. A fixed WebEngine remote debugging port (9222) collided the same way and was on by default. Give each Kate process a unique primary service name and tell its MCP server which name to use, keeping the legacy name as a best-effort fallback so single-process behaviour is unchanged. Implementation: - EditorDBusService registers org.kde.katecode.editor.<pid> as the primary name and best-effort also claims the bare legacy name (first process wins; later ones skip it harmlessly). The object path is unchanged, so the service is reachable under either name. - ACPSession::buildMcpServers() passes KATECODE_DBUS_SERVICE=<pid name> in the Kate MCP server's env. - MCPServer reads that env var (falling back to the legacy name) for all five editor DBus calls. - ChatWebView only enables QTWEBENGINE_REMOTE_DEBUGGING when the user sets KATECODE_REMOTE_DEBUGGING, so no fixed port is opened by default. This lets two separate Kate processes each run an agent. Concurrent agents within one process are handled by a separate gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Within a single Kate process all windows share one editor DBus service, so letting two windows run agents at once would cross their MCP editor calls. Rather than the large per-window routing rework, block the second window cleanly (the fallback the user asked for). Add a process-wide single-active-agent gate owned by the plugin and consulted by each ChatWidget before it starts a session. Implementation: - KateCodePlugin tracks the owning widget in a QPointer (auto-clears if that window is destroyed) and exposes acquireAgentSlot/releaseAgentSlot /agentSlotAvailableFor plus an agentActivityChanged() signal; removeView also emits it so a closed window lets others refresh. - ChatWidget gains std::function gate hooks (wired by KateCodeView to the plugin). ensureAgentSlot() guards all three connect entry points and shows a clear message when blocked; the slot is released on both the Disconnected and Error status transitions; refreshAgentAvailability() enables/disables Connect and Resume (only while disconnected) and is driven by the plugin signal. Combined with the per-process DBus name, two separate Kate processes can each run an agent, while extra windows in one process are safely blocked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The permission-mode dropdown always sent legacy session/set_mode, even though modern agents (Claude, Codex) advertise a "mode" config option and expect session/set_config_option; failed changes also left the dropdown showing a mode the agent had rejected. Make setMode() choose the transport and confirm the result, following implementation.md. Implementation: - setMode() prefers session/set_config_option (configId "mode") when the agent advertised a "mode" config option, validating the value against the advertised choices; otherwise it falls back to session/set_mode. - Interactive changes use a dedicated request id and handler, kept entirely separate from the startup per-provider config flow so session setup is never re-run. - handleInteractiveModeResponse() drives m_currentMode from the returned configOptions on success (emitting modesAvailable/modeChanged), accepts a bodyless legacy success, and on failure re-emits the last confirmed mode so ChatInputWidget rolls the dropdown back; the session is not dropped. - Rapid selections coalesce: one request in flight, the latest desired value queued and sent once the response arrives, so the agent converges on the final choice. State is reset on stop(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two robustness improvements for working across all ACP servers. Kate context: the first-message system-reminder only listed the kate MCP tool preferences, so the agent was not explicitly told it runs inside Kate. Prepend a concise orientation: it is running in the KDE Kate editor via Kate Code, the user's open files are its working context, file operations should go through the kate MCP tools for in-editor review, and the workspace root is the project directory. Capabilities: image and embedded-context (resource) prompt blocks were sent unconditionally, which can break agents that don't advertise them (e.g. Codex). Parse agentCapabilities from the initialize response into m_supportsImage / m_supportsEmbeddedContext / m_supportsPromptQueueing (reset on stop, exposed via getters) and only append image and resource/context blocks when advertised; the plain text block and the reminder are always sent. supportsPromptQueueing and supportsEmbeddedContext also feed later input-side features. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Submitting a message while the agent was still streaming eagerly created a second assistant placeholder (a second streaming caret) and sent a concurrent session/prompt, which agents without prompt queueing mishandle and which broke the single m_promptRequestId matching. Show the follow-up user message immediately but queue the send until the current turn finishes, so only one streaming placeholder exists at a time and prompts are sent one at a time (uniform across all ACP servers). Implementation: - Extract the assistant-placeholder + prompt-block + session/prompt send into dispatchPrompt(); sendMessage() now always emits the user message, then either queues a QueuedPrompt (when isPromptRunning()) or dispatches. - On prompt completion, after clearing m_promptRequestId, flush one queued prompt via dispatchPrompt(); the queue is cleared on stop() and on cancelPrompt(). The normal, not-busy single-message path is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Input-area UX improvements the user asked for. - Resizable input (Task 9): the chat view and the input area now sit in a vertical QSplitter, so the input box can be dragged larger. resizeEvent caps the input area at half the widget height so it can never crowd out the chat view. The text edit drops its fixed 100px cap and expands to fill the pane. resetWebView() swaps the view via QSplitter::replaceWidget and defers deletion with deleteLater. - Waiting indicator (Task 10): a label in the mode row shows "Waiting for your input" when the agent is idle and connected, or "Agent is working…" while a prompt runs; blank when disconnected. Driven by the existing setEnabled()/setPromptRunning() calls. - File-include button (Task 11): a button opens a file picker; text files (by MIME, with a UTF-8/NUL heuristic fallback, capped at 1 MiB) are inlined into the message as a fenced block, while binary or oversized files insert their path so the agent can read them via the Kate MCP/fs tools. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two related conveniences. Save output (Task 13): a header button exports the current session's Markdown transcript to a user-chosen file. ACPSession::transcriptFilePath() exposes the live TranscriptWriter path; the button copies it via a save dialog (overwrite-safe) and reports success/failure as a system message, or notes when there is nothing to save yet. Command auto-approval (Task 14): wires the global allow-list into the permission flow. onPermissionRequested() extracts the command from the request input, and when it matches SettingsStore::isCommandAllowed() and a clear allow option exists (kind allow_once/allow_always, else an allow/approve/yes option), it sends that outcome immediately and notes the auto-approval instead of prompting. It is deliberately conservative: it never auto-rejects, falls through to the dialog whenever anything is ambiguous, and does nothing when the allow-list is empty (the default). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reflect the feature set added on top of 1.3.1: crash-on-close fix, multi-window support (per-process DBus name plus a single-agent gate), preferred set_config_option mode switching, capability detection and Kate orientation, prompt queueing, resizable input with a waiting indicator and file-include, save-output, and command auto-approval. Update CMakeLists.txt, src/katecode.json and kate-code.spec (1.4.0-1) with a changelog entry. No RPM was built or published. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace comments that referenced internal task numbers (e.g. "Task 9") with self-describing wording, since those numbers mean nothing in the repository. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A Codex upstream failure arrived as a session_info_update with threadStatus systemError, which Kate ignored entirely, plus a normal message chunk carrying "stream disconnected … request ID" — so the failure was invisible or looked like ordinary assistant output, and the session felt dead. Genuine ACP error responses were only logged too. Detect and show these as distinct error messages. Implementation: - ACPSession emits a new sessionError() on session_info_update when the Codex threadStatus is systemError/error, without disturbing the normal turn finalisation (the trailing chunk and prompt response still run). A defensive final else logs any unhandled session/update type. - ChatWebView::showError() renders a red-tinted "error" message (base64-passed, textContent so no injection); chat.js/chat.css gain the addErrorMessage() renderer and .message.error style. - ChatWidget surfaces both sessionError and onError() in the chat. - ACPService no longer routes bridge stderr through errorOccurred, so the now-visible error channel carries only genuine errors, not noisy informational stderr. This does not stop the upstream disconnect (that is OpenAI/bridge side), but makes Kate report it clearly and stay usable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agent's streamed reply could fail to appear at the end of the visible log, and a saved transcript captured only the user message. Several causes: scrollToBottom() scrolled the window, but the real scroll container is #messages, so streamed output stayed below the fold; a fresh Connect reused the previous session's page, leaving stale content; the assistant transcript was only recorded on agent_message_end, which the Claude agent never sends (it ends the turn via the prompt response); and JS exceptions in injected calls were silently swallowed. Fixes: - scrollToBottom() now scrolls the #messages element (window scroll kept as a harmless fallback). - onConnectClicked() clears the web view before starting a fresh session so the log begins clean. - The session/prompt completion path records the assistant message to the transcript when agent_message_end did not (idempotent: that handler clears the content, so there is no double-record). - runJavaScript() wraps injected scripts in try/catch and qWarns any exception (with script context), so a render failure is no longer invisible. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships the Codex/ACP error surfacing and the agent-output-to-end-of-log fixes on top of 1.4.0. Updates CMakeLists.txt, src/katecode.json and kate-code.spec (1.4.1-1) with a changelog entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The session summariser was a separate mechanism: it POSTed to the Anthropic HTTP API with a KWallet-stored key and a model chosen from a hard-coded two-entry combo box. If the hard-coded Claude models are renamed or withdrawn, or the user wants a different/cheaper model or vendor, there is no way to select one, and summaries silently depend on an API key that nothing else uses. Summaries are now produced by ACP agents instead. The Session Summaries settings group gains a "Summary agent" dropdown listing the configured providers plus a "Current agent" entry, which is the new default: when the session ends, the live agent is asked to summarise itself from its own context, with a cancellable progress dialogue while the reply streams in. Implementation: - SettingsStore: new summaryProviderId()/setSummaryProviderId() (key Summaries/providerId, defaulting to the __current__ sentinel) and providerById(). summaryModel() remains but is no longer used. - SummaryGenerator: rewritten from QNetworkAccessManager to a headless ACP run (initialize -> session/new with no MCP servers -> session/prompt -> collect agent_message_chunk text) per job, keyed by ACPService instance. Tool permission requests are declined so a misbehaving agent cannot hang a summary. The public interface is unchanged; waitForPendingRequests() default timeout rises to 60 s because a subprocess is slower to start than an HTTP call. - ACPSession: new requestSummary()/cancelSummary()/summaryResult(). While a summary prompt is in flight its chunks accumulate silently (no chat messages, no transcript entries); stop() and disconnects fail the summary so waiters return. - ChatWidget: disconnect now summarises before stopping the session so the current agent is still available; the Disconnected handler keeps triggering for unexpected agent deaths, where the current-agent option falls back to a headless run of the active provider over the saved transcript (now read via SummaryStore instead of a hand-built path). The API-key gating of summaries is gone. - Config page: summaries no longer disabled when KWallet or the API key is missing; the summariseOnResume path drops its key check. The Anthropic API-key storage and settings UI are now unused and will be removed separately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resuming a session by context injection sent the prior summary or raw transcript as "Summary from last session:" with no further guidance. A raw transcript ends with the last user prompt and agent turn, so agents routinely read it as a fresh instruction and re-perform the final task of the old session. There was also no feedback that the restored context had actually been read and understood. Wrap the injected record in a system-reminder that states this is a session restore, that the material is background context only (no acting on instructions in it, no resuming work, no file changes), and that the agent should reply with a single sentence describing what the previous session covered before waiting for the user. That one line doubles as visible confirmation to the user that the restore was processed. Applies to both summary and raw-transcript injection; true resume (session/load) is unaffected as the agent restores its own context. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
With summaries generated through ACP agents, the Anthropic API key and the KWallet machinery that stored it no longer have any consumer, yet the Advanced tab still claimed the key was "used for generating session summaries" and the summaries checkbox was greyed out whenever KWallet or the key was missing. Delete the dead path outright: - SettingsStore: loadApiKey()/saveApiKey(), the KWallet open/close state machine, the apiKeyLoaded/apiKeySaved/walletError signals and summaryModel()/setSummaryModel() are gone. The stale Summaries/model key is removed from storage on startup. - KateCodeConfigPage: the whole "Anthropic API Key" group and its slots are removed; summary controls no longer depend on the wallet. - Build: KF6::Wallet and Qt6::Network are no longer linked (the network module was only used by the old HTTP summariser). The key itself is left untouched in the user's wallet; kate-code simply no longer reads it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A five-way review of the new summariser code and the wider codebase, with every finding adversarially verified, confirmed a set of real bugs in the summary flow, the ACP layer, terminal handling and the single-agent gate. Summary flow: - requestSummary() raced the prompt it had just cancelled: cancel is only a notification and chunks carry no request id, so fragments of the aborted turn were collected into the saved summary, and agents that reject concurrent prompts failed the summary outright. The summary prompt is now parked until the cancelled prompt's response arrives. - Tool permission requests during a summary turn are auto-declined (mirroring the headless generator) instead of rendering an unanswerable prompt behind the modal wait dialogue. - generateSummaryWithCurrentAgent() hardened: heap-allocated dialogue and QPointer guards survive widget destruction mid-wait; the summaryResult connection uses a stack context object so prepareForShutdown()'s blanket disconnect cannot sever it; a re-entrancy flag stops shutdown or the Disconnected handler from stacking a second summary; WaitForMoreEvents stops the wait loop busy-spinning a core. - resolveResumeContext()'s summarise-on-resume wait now shows a window-modal dialogue (no more re-entrant clicks corrupting session state) and both it and its caller guard against destruction. - Headless summary jobs get a hard 120 s timeout so a silent agent no longer leaks a subprocess per session end; unknown provider ids fall back to the active provider; a crashed session is no longer summarised twice (m_userSentMessage now resets in the Disconnected handler); m_lastProjectRoot uses the directory the session actually started in rather than re-querying the provider mid-handshake. ACP layer: - A JSON-RPC error response to session/prompt now finalises the turn (previously isPromptRunning() stayed true and every later prompt queued forever); initialize/session-new errors move the status to Error instead of wedging on "Connecting". - Unexpected agent death now runs the same cleanup as stop(): transcript finalised, terminals released, prompt queue and request ids cleared, so reconnect after a crash works. - ACPService buffers raw bytes and splits lines before UTF-8 decoding (multi-byte characters straddling a 64 KiB read no longer corrupt), and clears the buffer on start() so a crashed process's partial line cannot poison the next session's first message. Terminals: - waitForExit() re-looks the terminal up after its nested event loop; the old reference dangled if the terminal was released during the wait (use-after-free on disconnect during a long command). - terminal/create with an args array now execs the program directly instead of joining args with spaces into `bash -c`, which destroyed argument boundaries and re-interpreted metacharacters. UI/config: - The single-agent slot is released again when Resume Session is aborted, and re-acquired after the stop()/start() cycle in New Session and Resume so two agents can no longer run concurrently. - Provider update/remove/reorder now start from the effective provider list, so edits are no longer silently discarded when the list came from the defaults fallback; removing the provider selected as the summary agent resets the setting to "Current agent". - TranscriptWriter and SummaryStore now derive identical project folder names for trailing-slash and empty roots. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Users intermittently see "MCP error -32000: Connection closed" from the kate MCP tools: the client-side error a dead MCP server produces on every subsequent tool call. Three defects in kate-mcp-server could end the process (or the connection) prematurely: - The stdin loop treated any read() failure as end-of-input and quit. A signal-interrupted read (EINTR) or a spurious socket-notifier wakeup on a non-blocking pipe (EAGAIN; node-based parents such as claude-code can leave the shared pipe description non-blocking) silently killed the server mid-session. These errnos now simply return and wait for the next activation. - MCP ping requests were answered with -32601 "Method not found". The spec requires a prompt empty result, and clients may treat a failed ping as a stale connection and close it. ping is now handled. - Responses were written with a single unchecked write(): a large katecode_read reply could be partially written (corrupting the JSON stream), and a client tearing down its pipe could kill the server via the default SIGPIPE action. Writes now loop over partial writes and EINTR, and SIGPIPE is ignored so the process ends via the clean stdin-EOF path instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Feature release: ACP-agent session summaries with a current-agent option, session-restore framing, removal of the Anthropic API-key path, a sweep of review fixes, and kate-mcp-server robustness. kf6-kwallet-devel is dropped from the spec BuildRequires to match the removed KWallet dependency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kate-mcp-server crashed with SIGABRT ("has encountered a fatal error
and was closed") whenever a kate MCP tool was invoked. The coredump
backtrace ended in libdbus aborting from dbus_message_new_method_call
via the QDBusInterface constructor:
assertion "_dbus_check_is_valid_bus_name (destination)" failed
The per-process editor service name (added in 1.4.0 so multiple Kate
windows can each own an agent) was built as
"org.kde.katecode.editor.<pid>". A D-Bus well-known name element must
not begin with a digit, so the all-digit pid element is an invalid bus
name; libdbus aborts the whole process when handed it as a call
destination. This also meant the per-process name never actually
registered, so the feature never worked as intended.
Prefix the pid element with "p" ("...editor.p<pid>") in both places
that build the name — EditorDBusService::registerOnBus() (the
registrar) and ACPSession::buildMcpServers() (which passes it to the
child via KATECODE_DBUS_SERVICE) — so the name is valid and the two
sides still agree.
Also harden the MCP server: validate the target name against the D-Bus
bus-name grammar in handleToolsCall() before constructing any
QDBusInterface, returning a normal MCP error if it is malformed. A bad
name can no longer abort the server and kill the agent's tool access;
it degrades to a visible error instead.
Reproduced and verified: the old "...editor.12345" name aborted the
1.5.0 binary (exit -6) on the first tool call and now returns a clean
error; the fixed "...editor.p12345" name is accepted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Patch release for the kate-mcp-server per-process D-Bus name crash fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I have been using this for a while, and adding features. I have kept these features local though.
This update makes kate-code more generic and works better with more providers. It uses more ACP features, and has more configuration options. It also fixes many bugs that caused it to crash or become unusable.
Please cherry pick as needed. The commit IDs will be munged, and a bunch of upstream will be in there, since my tooling found a log in there (it after running it, I figured it was from upstream, but it was still a log) and, because this is a company laptop, I sanitised out the log before pushing.
This was mostly vibed, and it was done by Claude Opus/Sonnet/Fable, Codex 5.x, Composer 2.5, and maybe some Kimi 2.x. I feel that, because of the subject of the application, this is probably OK, but feel free to reject code if you do not think it is.