Repository navigation
feat(agent): app-wide agent side panel - #437
Merged
Merged
Conversation
Tools the app must run itself (extensions, model weights, workflows, settings, mesh undo/redo, navigation) are declared in CLIENT_TOOLS. The tool loop hands them to the app as a client_tool event and waits for the answer on POST /agent/tool-result; destructive ones ask the user first and wait up to 10 minutes. Adds list_extensions, get_settings and generate_from_image, and renders the page, models, workflows, storage folders and UI options into the system prompt.
Adds window.electron.agent.conversations (list/read/save/remove), one file
per conversation in <userData>/agent/conversations. Ids are checked against
/^[a-z0-9-]{1,64}$/ and writes go through a temp file plus rename.
Pure title/sort/settle helpers live in src/shared/utils/agentConversations.
The chat leaves the Generate page's basic/chat toggle and becomes the body of an AgentPanel next to <main> in MainLayout, so it pushes the app. The panel toggles from a TopBar button or Ctrl/Cmd+L, resizes from its left edge (320-640px) and remembers its open state and width. Messages move to agentConversationStore: they survive page changes and panel close, save to disk after 500ms of quiet, and the latest conversation reopens at startup. The header lists past conversations with open and delete.
…ation runGeneration and createGenerationApi hold the from-image submit and status polling without React, so the agent can start a generation outside a hook. useGeneration and useApi now delegate to them with unchanged behaviour.
clientTools.ts runs the client_tool calls of the agent (extensions, weights, workflows, settings, storage folders, mesh undo/redo, navigation) through injected dependencies, asks for confirmation when required and posts the result to /agent/tool-result. ConfirmCard.tsx renders the Confirm/Cancel card and its promise queue. agentContext.ts builds the request context from the stores.
…panel # Conflicts: # package.json # src/shared/hooks/useApi.ts # src/shared/hooks/useGeneration.ts # src/shared/utils/agentStream.ts
…to the chat The chat runs client_tool events through the client tool registry (after a Confirm click for destructive ones), starts generate_from_image after the turn, and sends the app-wide context. Undo/redo checks read the mesh history depths.
…he app install_extension runs code downloaded from GitHub, so it now needs a Confirm click showing the URL. The app also asks for destructive tools and installs whatever the server's confirm flag says, so a backend slip cannot bypass the card.
- set_storage_folder moves what Settings would (storageEntries, so a workflows folder of JSON files moves too), refuses what Settings refuses, and reports items left behind. - set_setting declares uiScale by its scale names, matching the app. - A queued confirm card opens the panel; a card the server stopped waiting for is cancelled; answered cards are cleared per turn and per conversation. - An agent-started generation keeps the conversation busy, so its result cannot land in another one. - A failed conversation save stays dirty and blocks switching away; temp files get unique names.
The panel's slot grows to its width while the panel slides and fades in from the right (220 ms), and the reverse on close. No transition while resizing, none with reduced motion. Closed, it stays mounted but invisible.
A lighter rounded box with the text on top, a plus to attach and the send button inside; the model picker and the thinking mode sit as quiet text controls under it. The Shift+Enter hint moves to the send button's tooltip.
Agent tools: - generate_from_image refuses while a generation is already running - the tool-result endpoint no longer doubles the "Error: " prefix - a confirmed tool waits for the click (10 min), then gets tool_timeout for its run, via the new POST /agent/tool-confirmed - the non-streaming /agent/chat no longer offers client tools - uninstall_extension rejects "ext/node" ids so the card can't mislead Conversations: - every disk operation goes through one queue: a save in flight is always awaited, and a delete can't race the write of its file - a failed delete keeps the pending changes - init retries after a failure and skips unreadable conversations - rename retries on transient Windows locks; orphan .tmp files are cleaned
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.
Summary
The agent leaves the Generate page. It now lives in a right-side panel available on every page, and it can act on the whole app without changing page. Design:
docs/superpowers/specs/2026-11-12-agent-side-panel-design.md.Closes #438
Closes #305
Panel
MainLayout, next to<main>, so it pushes the app instead of covering it.Ctrl+L/Cmd+Ltoggles it, with a 220 ms slide-and-fade animation. Users with reduced motion get no animation.ChatPanelmoves tosrc/shared/components/agent/AgentChat.tsx.+to attach an image and the send button; the model picker and the thinking mode sit underneath.Conversations
<userData>/agent/conversations/.agent.conversations.list/read/save/remove.App-wide agent
Client tool bridge:
client_toolevents and waits forPOST /agent/tool-result.role: toolmessage, in the same turn.New client tools:
install_extension,uninstall_extension,reload_extensionsdownload_model_weights,delete_model_weightsopen_workflow,delete_workflowset_setting,set_storage_folderundo_mesh,redo_meshnavigate, only when the user explicitly asksNew server tools:
list_extensions,get_settings,generate_from_image. The last one generates from the image attached to the message, into the Generate viewer. The generation path is extracted intosrc/shared/utils/generationRunner.ts.Confirmation: these tools show a Confirm / Cancel card and the agent waits for the click:
The app enforces the confirmation itself, whatever the server's flag says. A card that the server stopped waiting for is cancelled, and a queued card opens the panel.
Context: every request sends the current page, the mesh, workflows, extensions, downloaded models, storage folders and UI settings.
Storage folder changes:
set_storage_folderuses the same rules as Settings > Storage:storageEntries,checkStorageLocation, the move, and a report of the items left behind.Test plan
npm run test:node: 240 tests, 239 pass, 0 failpython -m unittest discover -s tests(api): 415 tests, OK (5 skipped)srcandelectron. tsc reports no new errors; the remaining errors (assetLibrary, workflowRunStore and TS5097 in the tests) are already on dev.