Add a new BookmarksPanel accessible via Ctrl/Cmd+Shift+B or the
command palette (View Bookmarks). The panel lists all pinned messages
across all sessions globally, with:
- Click-to-navigate: switches session and scrolls to the message
- Inline unpin: remove bookmarks directly from the panel
- Keyboard navigation: arrow keys, Enter, Escape
- Empty state when no messages are pinned
New shared helper listPinnedMessages() in sessionLibrary.ts derives
pinned messages from the workspace state in the renderer.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When electron-updater reports no update available, the service now
transitions to 'up-to-date' instead of reverting silently to 'idle'.
The troubleshooting UI shows a green check icon, 'Up to date' label,
and 'You are running the latest version of Aryx.' description.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When multiple MCP servers expose tools with the same name, the approval
pill showed an incorrect count (e.g. 150/300) even when everything was
approved. The numerator used a Set<string> to deduplicate by tool ID,
so shared tools were counted once, while the denominator counted each
group occurrence independently.
Extract countApprovedToolsInGroups() into shared/domain/tooling.ts and
switch to per-group counting that mirrors the totalItemCount formula.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Relax branchSessionRecord validation to accept user or assistant roles
- Show "Branch from here" hover button on all conversation messages
- Contextual tooltip: "starting from this message" vs "continuing from this response"
- Add test for branching from assistant message
- Replace non-user rejection test with non-conversation rejection test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add the backend contract and session-domain support for
'Branch from here':
- new branchSession IPC method and sessions:branch channel
- branchOrigin metadata on SessionRecord
- session branching helper that truncates the transcript at a
chosen user message and clears runtime state
- AryxAppService branching flow with scratchpad directory support
- persistence normalization and regression coverage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
System tray:
- Always-visible tray icon with context menu
- Quick Scratchpad action from tray (triggers session creation
via IPC bridge to renderer)
- Running session count in tray tooltip and menu
- Click tray icon to show/focus window
- Quit option in tray menu
Minimize to tray:
- New 'Minimize to tray on close' toggle in Settings > Appearance
- When enabled, closing the window hides to tray instead of
quitting (configurable per-user, default off)
- macOS: hides dock icon when minimized to tray
- Proper force-quit handling (Cmd+Q on macOS, tray Quit)
Full IPC contract chain:
- minimizeToTray setting in WorkspaceSettings
- setMinimizeToTray channel + ElectronApi method
- Preload bridge, service handler, IPC registration
- Preserved through workspace normalization
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Show native OS notifications when a session run completes, fails, or
needs approval while the app window is unfocused. Clicking a
notification focuses the window and selects the relevant session.
Includes a toggle in Settings > Appearance to enable/disable
notifications (enabled by default).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add three layers of usage visibility:
- ChatPane footer: premium request count, AIU consumed, and quota
remaining below the existing context-window bar
- Settings / CopilotStatusCard: on-demand account quota section with
progress bars, overage indicators, and reset dates fetched via
the new get-quota sidecar command
- Activity Panel: per-agent token/cost/duration totals on each agent
row and a Session Usage summary section between agents and timeline
Backend (sidecar):
- New get-quota command using SDK account.getQuota RPC
- New assistant-usage turn-scoped event from SDK assistant.usage
- QuotaSnapshotMapper for both typed and untyped SDK quota payloads
- DTOs: GetQuotaCommandDto, QuotaSnapshotDto, AccountQuotaResultEventDto,
AssistantUsageEventDto
Frontend:
- Shared types: AssistantUsageEvent, QuotaSnapshot, GetQuotaCommand
- IPC bridge: getQuota channel, assistant-usage event dispatch
- State: SessionRequestUsageMap accumulator with per-agent breakdown
- 8 new tests for accumulator logic and formatting helpers
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Display compact status cards in the chat transcript showing each
sub-agent's name, current activity (Thinking, Using grep, etc.),
and elapsed time. Cards appear while sub-agents are running and
clear when the session goes idle.
- Extend SessionEventRecord with description, error, toolCallId,
and model fields for subagent events
- Forward additional subagent fields in handleTurnScopedEvent
- Add subagentTracker reducer to derive active subagent state from
session events, including agent-activity correlation
- Create SubagentActivityCard component with spinner, status icon,
agent name, activity label, and live elapsed timer
- Wire activeSubagents state in App.tsx and pass to ChatPane
- Add 16 unit tests for the subagent tracker
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- add a PTY manager with platform shell resolution and streamed data/exit events
- expose terminal lifecycle and terminal height IPC through preload and app service
- persist terminal panel height in workspace settings and document the backend contract
- add backend tests and validate native packaging with bun run package
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mergeDiscoveredToolingState now carries over probedTools from existing
servers when the config fingerprint is unchanged. The equality check in
syncProjectDiscoveredTooling also strips probedTools before comparing,
so runtime-only probe data never triggers a spurious state replacement.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When multiple MCP servers expose the same tool names (e.g., several
kusto-mcp instances), each server's group now shows its tools instead
of only the first server getting the tools and others showing 0/0.
Deduplicate the effectiveAutoApprovedCount to avoid double-counting
shared tools in the pill header.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When MCP server configs declare wildcard tools (empty tools array),
the Copilot SDK has no API to list individual tool names. Add direct
MCP protocol probing using @modelcontextprotocol/sdk to discover
available tools from each accepted server.
- Add McpToolProber service supporting stdio/SSE/HTTP transports
- Probe accepted MCP servers on project load, acceptance, and rescan
- Store probed tools on DiscoveredMcpServer and McpServerDefinition
- Use probed tools in listApprovalToolDefinitions when declared tools
are empty, so the approval pill shows individual tool toggles
- Remove unused isMcpServerApprovalKey helper
- Fix effectiveAutoApprovedCount Math.max workaround in ChatPane
- Add comprehensive tests for probed tool behavior
- Update ARCHITECTURE.md tooling integration section
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MCP servers configured with empty tools arrays (wildcard) now appear in the
auto-approval pill with a server-level toggle. When toggled, a server-level
approval key (mcp_server:<name>) is added to autoApprovedToolNames. The
sidecar matches this key against PermissionRequestMcp.ServerName to auto-
approve all tools from that server without needing individual tool names.
- Add buildMcpServerApprovalKey/isMcpServerApprovalKey helpers
- Create approval groups for all MCP servers including empty-tools ones
- Add serverApprovalKey to ApprovalToolGroup for server-level toggles
- Update sidecar RequiresToolCallApproval to check server-level keys
- Include server-level keys in listApprovalToolNames for pruning safety
- Add tests for both shared domain and sidecar approval matching
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Group MCP tools by server and LSP tools by profile in the approval popover
instead of showing a flat list. Each server/profile group gets a collapsible
header with a batch toggle to approve/unapprove all tools at once. Add a
search filter (visible when >10 tools) and partial-state indicators for
groups with mixed approval. Add groupApprovalToolsByProvider shared helper
with tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Give each scratchpad session its own working directory, migrate existing scratchpad sessions on workspace load, and route sidecar turns through the session-specific cwd. Add regression coverage for create, duplicate, delete, and migration flows, and document the new persistence model.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add mode-aware graph mutation helpers for pattern topology so backend
code can add and remove agents without forcing a full graph rebuild.
Also preserve an existing pattern graph in savePattern instead of
re-syncing it from defaults, and cover the new behavior with shared
and main-process tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When a tool-call approval banner appears, users can now click 'Always
approve' to both approve the current call AND add the tool to the
session's autoApprovedToolNames. Future calls to that tool are then
auto-approved without showing the banner.
- Add alwaysApprove?: boolean to ResolveSessionApprovalInput
- In resolveSessionApproval, atomically append tool to session
approvalSettings when alwaysApprove is true (avoids running guard)
- Add 'Always approve' button in ApprovalBanner (tool-call kind only)
- Wire through ChatPane and App.tsx with updated callback signatures
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Create mcpTokenStore: in-memory token storage keyed by normalized server URL
with automatic expiry checking
- Create mcpOAuthService: full OAuth 2.1 + PKCE flow implementation
- Protected Resource Metadata discovery (RFC 9728)
- Authorization Server Metadata fetch (RFC 8414)
- Dynamic Client Registration (RFC 7591) when no static client ID
- PKCE S256 code challenge generation
- Local HTTP callback server for auth code receipt
- Browser-based consent via Electron shell.openExternal
- Authorization code to token exchange
- Add startSessionMcpAuth IPC channel and handler to trigger OAuth flow
- Inject stored OAuth tokens as Authorization headers in buildRunTurnToolingConfig
- Update McpAuthBanner with 'Authenticate in browser' button and loading state
- Add tests for token store (7 tests) and token injection (3 tests)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add McpOauthRequiredEvent and McpOauthStaticClientConfigEvent to sidecar contracts
- Add PendingMcpAuthRecord domain type with status tracking (pending/authenticating/failed/done)
- Add pendingMcpAuth field to SessionRecord for session-level auth state
- Wire onMcpOAuthRequired callback through sidecarProcess, runTurnPending, and AryxAppService
- Handle mcp-oauth-required events: set session pendingMcpAuth, clear on turn finalize/cancel
- Add dismissSessionMcpAuth IPC channel with preload binding and handler registration
- Create McpAuthBanner component (amber-themed, shows server name/URL, dismiss button)
- Integrate McpAuthBanner into ChatPane with placeholder text and App.tsx callback
- Update test fixtures for new RunTurnPendingCommand.onMcpOAuthRequired field
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add InteractionMode type and ExitPlanModeRequestedEvent to sidecar contracts
- Add PendingPlanReviewRecord domain type and interactionMode to SessionRecord
- Wire onExitPlanMode callback through SidecarClient and RunTurnPendingCommand
- Pass session interaction mode to RunTurnCommand for sidecar consumption
- Handle exit-plan-mode-requested events in AryxAppService
- Add setSessionInteractionMode and dismissSessionPlanReview IPC methods
- Create PlanReviewBanner component with summary, markdown content, and actions
- Add plan mode toggle pill in ChatPane composer area
- Wire implement action as follow-up message (graceful degradation)
- Clear pending plan review on new turn, turn completion, and cancellation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a builtin tool label registry mapping all ~30 official SDK tool IDs
to human-readable display names. Update listApprovalToolDefinitions to
resolve labels from the registry instead of showing raw tool IDs like
read_bash or fetch_copilot_cli_documentation. Expand the fallback
runtime tool catalog from 6 to 23 non-internal standard tools.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wire the sidecar user-input-requested protocol event through the main
process, IPC layer, and renderer UI so agents can ask the user
interactive questions with choices and freeform input.
- Add UserInputRequestedEvent and ResolveUserInputCommand to sidecar
protocol types
- Add resolveUserInput method to SidecarClient and onUserInput callback
to runTurn
- Create PendingUserInputRecord domain type and add pendingUserInput to
SessionRecord
- Add handleUserInputRequested and resolveSessionUserInput to
AryxAppService with handle management
- Register sessions:resolve-user-input IPC channel with preload bridge
- Create UserInputBanner component with choice buttons and freeform
input
- Integrate UserInputBanner into ChatPane with header indicator
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generalize the scratchpad-only model/reasoning-effort selector to work
in any session whose pattern has exactly one agent. This enables model
switching above the chat input for project 1-on-1 chats, not just
scratchpads.
- Rename ScratchpadSessionConfig -> SessionModelConfig across domain,
contracts, IPC, preload, and renderer
- Replace isScratchpadProject guard with agents.length === 1 check in
EryxAppService.updateSessionModelConfig and ChatPane pills gate
- Apply session model config in buildEffectivePattern whenever present,
regardless of project type
- Seed sessionModelConfig on session creation for any single-agent
pattern
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds cancel-turn IPC channel, SidecarClient.cancelTurn(), TurnCancelledError,
EryxAppService.cancelSessionTurn(), finalizeCancelledTurn(), stop button in
ChatPane, and cancelled run status throughout the run timeline.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a Troubleshooting section under a Support nav group in Settings:
- Open App Data Folder: reveals the user-data directory in the OS file
explorer via shell.openPath.
- Reset Local Workspace: destructive action that deletes workspace.json
and scratchpad contents, clears the in-memory cache, and reseeds
defaults. Auth secrets are preserved. Requires two-step confirmation.
New IPC channels, ElectronApi methods, and preload bridge added for
openAppDataFolder and resetLocalWorkspace. Existing electron mock in
tests updated to include shell.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add CSS styling for selected edges (indigo highlight with glow)
- Enable orchestrator↔agent connections in group-chat mode
- Downgrade disconnected-agent validation from error to warning
- Rename addHandoffEdge to addEdge (generic for all modes)
- Add tests for group-chat connection rules
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Color-code edges by semantic role: structural edges (system↔node) in
muted zinc, agent-to-agent edges in indigo for clear visual separation
- Switch from smoothstep to bezier curves for smoother, more natural
edge routing that reduces right-angle overlaps
- Stagger agent nodes at alternating X offsets in concurrent, handoff,
and group-chat layouts so parallel fan-out/fan-in edges take distinct
bezier paths instead of stacking
- Increase spacing in all layouts to give edges more room
- Add dagre-powered auto-layout button (top-right of canvas) that
computes optimal left-to-right hierarchical node positions
- Add 2 new tests for auto-layout across all orchestration modes
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Hide input handle on User Input nodes and output handle on User Output
nodes (separate userInputNode/userOutputNode node types)
- Enable edge deletion in handoff mode only (Delete key or React Flow UI);
only agent-to-agent edges are deletable, structural edges are protected
- Block all edge mutations (add/delete) in concurrent and group chat modes
- Add agent as disconnected node without auto-rebuilding the graph
- Add sequential reorder controls (↑↓) in the inspector panel with
position/order swap and automatic edge rebuilding
- Replace circular group chat layout with vertical column to prevent
bidirectional edge crossings
- Tighten handoff layout spacing so edges between triage and specialists
don't overlap nodes
- Use smoothstep edge type for cleaner edge routing across all modes
- Add 6 new tests covering reorder, disconnected add, edge deletion rules,
and node type assertions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- load runtime tools dynamically from Copilot CLI capabilities via tools.list
- merge runtime tools with configured MCP and LSP tools in the approval catalog
- keep a fallback builtin runtime tool list when capabilities are unavailable
- move approval-tool pruning to the app service so dynamic tools are not dropped on load
- update approval UI and docs to use the corrected runtime-tool model
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>