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 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>
- 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 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>
Add appearance theme support (dark/light/system) using CSS custom
property overrides. In light mode the Tailwind zinc scale is inverted
and semantic surface/border tokens are swapped, so all existing
utility classes pick up the new palette automatically.
- Add AppearanceTheme type and theme field to WorkspaceSettings
- Add setTheme IPC channel wiring (contracts, preload, handler, service)
- Add [data-theme='light'] CSS overrides for zinc scale, surface tokens,
scrollbar, and markdown prose colours
- Add Appearance section to SettingsPanel with radio-button theme picker
- Apply data-theme attribute on document root via useEffect in App.tsx,
with matchMedia listener for the system option
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>