mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-08 20:58:45 +02:00
docs: remove old plans
This commit is contained in:
-204
@@ -1,204 +0,0 @@
|
|||||||
# Git-aware context UX handover
|
|
||||||
|
|
||||||
This document covers the frontend/UX work that can now be built on top of the newly implemented backend/shared git-context support.
|
|
||||||
|
|
||||||
## What was implemented in backend/shared
|
|
||||||
|
|
||||||
The app now persists and refreshes per-project git context on `ProjectRecord`.
|
|
||||||
|
|
||||||
### New shared project shape
|
|
||||||
|
|
||||||
File: `src/shared/domain/project.ts`
|
|
||||||
|
|
||||||
`ProjectRecord` now has:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
git?: ProjectGitContext;
|
|
||||||
```
|
|
||||||
|
|
||||||
`ProjectGitContext` shape:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
type ProjectGitContextStatus = 'ready' | 'not-repository' | 'git-missing' | 'error';
|
|
||||||
|
|
||||||
interface ProjectGitContext {
|
|
||||||
status: ProjectGitContextStatus;
|
|
||||||
scannedAt: string;
|
|
||||||
repoRoot?: string;
|
|
||||||
branch?: string;
|
|
||||||
upstream?: string;
|
|
||||||
ahead?: number;
|
|
||||||
behind?: number;
|
|
||||||
isDirty?: boolean;
|
|
||||||
changedFileCount?: number;
|
|
||||||
changes?: {
|
|
||||||
staged: number;
|
|
||||||
unstaged: number;
|
|
||||||
untracked: number;
|
|
||||||
conflicted: number;
|
|
||||||
};
|
|
||||||
head?: {
|
|
||||||
hash: string;
|
|
||||||
shortHash: string;
|
|
||||||
subject: string;
|
|
||||||
committedAt: string;
|
|
||||||
};
|
|
||||||
errorMessage?: string;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### New backend behavior
|
|
||||||
|
|
||||||
Files:
|
|
||||||
|
|
||||||
- `src/main/git/gitService.ts`
|
|
||||||
- `src/main/EryxAppService.ts`
|
|
||||||
|
|
||||||
Behavior:
|
|
||||||
|
|
||||||
- when a project is added, git context is fetched immediately
|
|
||||||
- when the workspace loads, the main process schedules an initial git-context refresh for all projects
|
|
||||||
- scratchpad projects intentionally do not carry git context
|
|
||||||
- non-repo folders are represented explicitly with `status: 'not-repository'`
|
|
||||||
- missing system git is represented explicitly with `status: 'git-missing'`
|
|
||||||
- unexpected git failures are represented with `status: 'error'` plus `errorMessage`
|
|
||||||
|
|
||||||
### New Electron API
|
|
||||||
|
|
||||||
Files:
|
|
||||||
|
|
||||||
- `src/shared/contracts/channels.ts`
|
|
||||||
- `src/shared/contracts/ipc.ts`
|
|
||||||
- `src/main/ipc/registerIpcHandlers.ts`
|
|
||||||
- `src/preload/index.ts`
|
|
||||||
|
|
||||||
New API:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
refreshProjectGitContext(projectId?: string): Promise<WorkspaceState>;
|
|
||||||
```
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- call with a `projectId` to refresh a single project
|
|
||||||
- call with no argument to refresh all projects
|
|
||||||
- the renderer also receives refreshed data through the existing `onWorkspaceUpdated(...)` subscription
|
|
||||||
|
|
||||||
## Important UX constraints and current backend semantics
|
|
||||||
|
|
||||||
These are important so the frontend does not guess incorrectly:
|
|
||||||
|
|
||||||
- `project.git` is optional overall because scratchpad has no git context and older persisted workspaces may not have been refreshed yet
|
|
||||||
- `status: 'ready'` is the only state where branch/dirty/commit details should be assumed to exist
|
|
||||||
- `branch` may still be missing even when `status === 'ready'` (for example detached HEAD)
|
|
||||||
- `head` may be missing even when `status === 'ready'` (for example a repo with no commits yet)
|
|
||||||
- `upstream`, `ahead`, and `behind` are optional and should only be shown when present
|
|
||||||
- `changedFileCount` is a file-entry count, while `changes` breaks it down into staged / unstaged / untracked / conflicted
|
|
||||||
- this phase does **not** inject git context into sidecar run-turn payloads yet; this is app/backend UI support, not orchestration/runtime support
|
|
||||||
|
|
||||||
## Recommended UX surfaces
|
|
||||||
|
|
||||||
### 1. Sidebar project rows
|
|
||||||
|
|
||||||
Primary file: `src/renderer/components/Sidebar.tsx`
|
|
||||||
|
|
||||||
Current `ProjectGroup` already renders:
|
|
||||||
|
|
||||||
- project icon
|
|
||||||
- project name
|
|
||||||
- running session count
|
|
||||||
- session count
|
|
||||||
|
|
||||||
Recommended additions for non-scratchpad projects:
|
|
||||||
|
|
||||||
- branch badge next to the project name when `project.git?.status === 'ready'`
|
|
||||||
- subtle dirty indicator when `isDirty === true`
|
|
||||||
- changed file count badge when `changedFileCount > 0`
|
|
||||||
- small warning/error badge for:
|
|
||||||
- `not-repository`
|
|
||||||
- `git-missing`
|
|
||||||
- `error`
|
|
||||||
- refresh action for the selected or hovered project that calls `api.refreshProjectGitContext(project.id)`
|
|
||||||
|
|
||||||
Suggested behavior:
|
|
||||||
|
|
||||||
- keep the row compact; do not turn it into a full card
|
|
||||||
- prefer one-line metadata in the collapsed header and more detail in an expanded/hover area if needed
|
|
||||||
- scratchpad should remain visually distinct and should not show git affordances
|
|
||||||
|
|
||||||
### 2. Chat header / selected session context
|
|
||||||
|
|
||||||
Primary file: `src/renderer/components/ChatPane.tsx`
|
|
||||||
|
|
||||||
Current header already shows:
|
|
||||||
|
|
||||||
- project name
|
|
||||||
- pattern name
|
|
||||||
- pattern mode
|
|
||||||
|
|
||||||
Recommended additions for real projects:
|
|
||||||
|
|
||||||
- branch name beside the project title
|
|
||||||
- dirty state chip when the repo has pending changes
|
|
||||||
- optional compact summary like:
|
|
||||||
- `3 changed`
|
|
||||||
- `2 ahead`
|
|
||||||
- `1 behind`
|
|
||||||
- optional recent commit summary tooltip/popover using `project.git.head`
|
|
||||||
|
|
||||||
This is likely the best place to make git context feel relevant to the active conversation without overcrowding the sidebar.
|
|
||||||
|
|
||||||
### 3. Empty/welcome state
|
|
||||||
|
|
||||||
Primary file: `src/renderer/components/WelcomePane.tsx`
|
|
||||||
|
|
||||||
Optional but useful:
|
|
||||||
|
|
||||||
- update copy so project-backed sessions clearly imply branch/diff awareness
|
|
||||||
- if you add a project-management callout, mention that git state appears automatically for repositories
|
|
||||||
|
|
||||||
### 4. App-level wiring
|
|
||||||
|
|
||||||
Primary file: `src/renderer/App.tsx`
|
|
||||||
|
|
||||||
The frontend agent will likely need to thread a refresh callback into whichever component gets the refresh UI, for example:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
() => void api.refreshProjectGitContext(projectId)
|
|
||||||
```
|
|
||||||
|
|
||||||
No extra state container is required because the workspace subscription already updates the renderer.
|
|
||||||
|
|
||||||
## Suggested UX implementation order
|
|
||||||
|
|
||||||
1. Add a small git metadata presentation in `Sidebar.tsx`
|
|
||||||
2. Add selected-project git context in `ChatPane.tsx`
|
|
||||||
3. Wire refresh actions from `App.tsx`
|
|
||||||
4. Add polish for non-ready states (`not-repository`, `git-missing`, `error`)
|
|
||||||
|
|
||||||
## Edge cases the UX should handle
|
|
||||||
|
|
||||||
- scratchpad: no git UI at all
|
|
||||||
- project added outside a git repo: show a neutral non-repo state, not a scary error
|
|
||||||
- git missing on the machine: show a helpful message, not a broken state
|
|
||||||
- detached HEAD: do not assume `branch` exists; fall back to commit short hash if useful
|
|
||||||
- brand-new repo with no commits: `head` may be absent even though the repo is valid
|
|
||||||
- upstream not configured: do not show ahead/behind placeholders
|
|
||||||
- refresh while viewing the project: avoid layout jumps; optimistic spinners are fine
|
|
||||||
|
|
||||||
## Files most likely to change in the UX pass
|
|
||||||
|
|
||||||
- `src/renderer/App.tsx`
|
|
||||||
- `src/renderer/components/Sidebar.tsx`
|
|
||||||
- `src/renderer/components/ChatPane.tsx`
|
|
||||||
- `src/renderer/components/WelcomePane.tsx`
|
|
||||||
|
|
||||||
## Out of scope for this handover
|
|
||||||
|
|
||||||
These are intentionally **not** implemented yet in backend/runtime:
|
|
||||||
|
|
||||||
- passing git context into sidecar agent instructions
|
|
||||||
- git diff viewers or file-by-file change inspection
|
|
||||||
- branch switching or commit actions
|
|
||||||
- git-aware working sets / file pinning
|
|
||||||
- project summary generation beyond git metadata
|
|
||||||
@@ -1,628 +0,0 @@
|
|||||||
# MCP / LSP Support Implementation Plan
|
|
||||||
|
|
||||||
Status: implemented v1 architecture reference
|
|
||||||
|
|
||||||
Intended execution order:
|
|
||||||
|
|
||||||
1. Backend agent executes backend phases first.
|
|
||||||
2. Frontend agent executes frontend phases second.
|
|
||||||
3. Frontend work should begin only after the backend contracts, persistence, and diagnostics are stable.
|
|
||||||
|
|
||||||
## Objective
|
|
||||||
|
|
||||||
Add first-class support for MCP servers and LSP-backed project intelligence in Eryx without fighting the existing architecture. The design should preserve Eryx's current strengths:
|
|
||||||
|
|
||||||
- Electron main as the desktop control plane
|
|
||||||
- preload + typed IPC as the renderer boundary
|
|
||||||
- shared TS contracts mirrored into the .NET sidecar
|
|
||||||
- .NET sidecar as the agent runtime
|
|
||||||
- OS keychain storage for secrets
|
|
||||||
|
|
||||||
This plan is intentionally backend-first and split into backend/frontend task groups so different agents can execute them in order.
|
|
||||||
|
|
||||||
The clarified product direction for v1 is:
|
|
||||||
|
|
||||||
- users add MCPs and LSPs globally in app settings
|
|
||||||
- users enable or disable those global MCPs/LSPs per session in the right-side panel that is currently used for activity
|
|
||||||
- enabled tooling becomes available to the agent for that session
|
|
||||||
|
|
||||||
## Current state analysis
|
|
||||||
|
|
||||||
### Application architecture today
|
|
||||||
|
|
||||||
- `src/main/EryxAppService.ts`
|
|
||||||
- central orchestration layer for workspace persistence, project/session lifecycle, sidecar calls, git refresh, and event emission
|
|
||||||
- `src/main/ipc/registerIpcHandlers.ts`
|
|
||||||
- single place where Electron IPC methods are registered
|
|
||||||
- `src/preload/index.ts`
|
|
||||||
- exposes the typed `eryxApi` bridge to the renderer
|
|
||||||
- `src/renderer/App.tsx`
|
|
||||||
- loads workspace + sidecar capabilities and wires subscriptions into the UI
|
|
||||||
- `src/shared/contracts/ipc.ts`
|
|
||||||
- typed renderer/main API contract
|
|
||||||
- `src/shared/contracts/sidecar.ts`
|
|
||||||
- typed main/sidecar protocol contract
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Contracts/ProtocolModels.cs`
|
|
||||||
- C# mirror of the sidecar DTOs
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/SidecarProtocolHost.cs`
|
|
||||||
- sidecar command dispatcher and capability provider
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/CopilotWorkflowRunner.cs`
|
|
||||||
- actual agent runtime construction and activity emission
|
|
||||||
|
|
||||||
### Signals that matter for MCP
|
|
||||||
|
|
||||||
- `CopilotWorkflowRunner.cs` already loads `McpServerToolCallContent` via reflection and reports MCP tool names through `TryGetToolName(...)`.
|
|
||||||
- `CopilotWorkflowRunner.cs` builds a `SessionConfig` for each agent and already owns `AvailableTools`, `WorkingDirectory`, and `OnPermissionRequest`.
|
|
||||||
- Scratchpad explicitly clears `AvailableTools`, so scratchpad is currently a "no tools" product surface.
|
|
||||||
|
|
||||||
### Signals that matter for LSP
|
|
||||||
|
|
||||||
- `package.json` includes `typescript-language-server` and an `lsp:typescript` script, which is a good TypeScript-first bootstrap hint.
|
|
||||||
- For v1, the implemented design starts LSP processes inside the sidecar as turn-scoped tool sessions so they can surface directly as agent tools without inventing a second bridge layer.
|
|
||||||
- The current session's project root remains the source of truth for LSP initialization.
|
|
||||||
|
|
||||||
### Persistence and secrets today
|
|
||||||
|
|
||||||
- `src/main/persistence/workspaceRepository.ts` persists a single additive `workspace.json`.
|
|
||||||
- `src/shared/domain/workspace.ts` defines the root persisted shape.
|
|
||||||
- `src/shared/domain/session.ts` already carries session-scoped overrides such as `scratchpadConfig`, which makes it the natural place for per-session MCP/LSP enablement.
|
|
||||||
- `src/main/secrets/secretStore.ts` already wraps `keytar`, so secrets should stay in the OS keychain and never be stored in `workspace.json`.
|
|
||||||
|
|
||||||
### Activity and diagnostics today
|
|
||||||
|
|
||||||
- `src/shared/domain/event.ts` only exposes coarse activity today: `thinking`, `tool-calling`, `handoff`, `completed`.
|
|
||||||
- `src/renderer/components/ActivityPanel.tsx` can already show per-agent activity but not rich MCP/LSP traces.
|
|
||||||
- `src/renderer/components/CopilotStatusCard.tsx` and `SettingsPanel.tsx` already establish a diagnostics-first UX pattern worth reusing for MCP/LSP health surfaces.
|
|
||||||
|
|
||||||
## Recommended design decisions
|
|
||||||
|
|
||||||
### 1. Put global tooling definitions in workspace settings
|
|
||||||
|
|
||||||
Additive, non-secret config should live in `WorkspaceState`, for example through a new `settings.tooling` section.
|
|
||||||
|
|
||||||
Illustrative shape:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface WorkspaceState {
|
|
||||||
projects: ProjectRecord[];
|
|
||||||
patterns: PatternDefinition[];
|
|
||||||
sessions: SessionRecord[];
|
|
||||||
selectedProjectId?: string;
|
|
||||||
selectedPatternId?: string;
|
|
||||||
selectedSessionId?: string;
|
|
||||||
lastUpdatedAt: string;
|
|
||||||
settings?: WorkspaceSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WorkspaceSettings {
|
|
||||||
tooling?: {
|
|
||||||
mcpServers?: McpServerDefinition[];
|
|
||||||
lspProfiles?: LspProfileDefinition[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Why this fits:
|
|
||||||
|
|
||||||
- it follows the current single-workspace persistence model
|
|
||||||
- in the current architecture, that single local workspace file already behaves like the app-wide store on this computer
|
|
||||||
- it remains backward compatible because the new fields are optional
|
|
||||||
- it keeps MCP/LSP definitions reusable across future sessions
|
|
||||||
|
|
||||||
### 2. Put enable/disable state on `SessionRecord`
|
|
||||||
|
|
||||||
The user wants MCP/LSP enablement to be controlled per session from the right-side panel. That means the durable selection should live on `SessionRecord`, not on `ProjectRecord`.
|
|
||||||
|
|
||||||
Illustrative shape:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface SessionRecord {
|
|
||||||
id: string;
|
|
||||||
projectId: string;
|
|
||||||
patternId: string;
|
|
||||||
title: string;
|
|
||||||
titleSource?: SessionTitleSource;
|
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
status: SessionStatus;
|
|
||||||
isPinned?: boolean;
|
|
||||||
isArchived?: boolean;
|
|
||||||
messages: ChatMessageRecord[];
|
|
||||||
lastError?: string;
|
|
||||||
scratchpadConfig?: ScratchpadSessionConfig;
|
|
||||||
tooling?: {
|
|
||||||
enabledMcpServerIds?: string[];
|
|
||||||
enabledLspProfileIds?: string[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
How this should behave:
|
|
||||||
|
|
||||||
- the settings screen owns the global registry of MCP and LSP definitions
|
|
||||||
- the session panel owns which global definitions are enabled for the current session
|
|
||||||
- the session's `projectId` provides the project root for LSP initialization when the session is project-backed
|
|
||||||
- scratchpad sessions should remain tool-free unless explicitly expanded later
|
|
||||||
|
|
||||||
### 3. Keep secrets out of persisted JSON
|
|
||||||
|
|
||||||
Use `src/main/secrets/secretStore.ts` for secret material. Persist only references in workspace config.
|
|
||||||
|
|
||||||
Recommended rule set:
|
|
||||||
|
|
||||||
- `workspace.json` stores server/profile definitions and secret references
|
|
||||||
- `keytar` stores secret values
|
|
||||||
- runtime logs, process IDs, and raw diagnostics stay out of `workspace.json`
|
|
||||||
|
|
||||||
### 4. MCP belongs in the .NET sidecar runtime
|
|
||||||
|
|
||||||
The sidecar already owns agent session creation, tool attachment, permission callbacks, and tool-call activity detection. MCP should build on that instead of inventing a second runtime stack in Electron or the renderer.
|
|
||||||
|
|
||||||
Recommended flow:
|
|
||||||
|
|
||||||
1. Electron main resolves session-enabled MCP definitions.
|
|
||||||
2. `EryxAppService.sendSessionMessage()` enriches the `run-turn` payload with runtime-ready MCP config.
|
|
||||||
3. The sidecar attaches MCP tools during `SessionConfig` creation.
|
|
||||||
4. The sidecar emits richer activity and error events back through the existing streaming channel.
|
|
||||||
|
|
||||||
### 5. LSP process ownership should start in the sidecar for v1
|
|
||||||
|
|
||||||
Implemented v1 LSP ownership:
|
|
||||||
|
|
||||||
- Electron main persists global definitions and resolves per-session selections.
|
|
||||||
- The sidecar starts the selected LSP server processes for a run, initializes them with the active project root, and exposes a focused tool surface through `AIFunction`s.
|
|
||||||
- The renderer only consumes typed config and per-session enablement state.
|
|
||||||
|
|
||||||
Why this shipped path fits v1:
|
|
||||||
|
|
||||||
- it keeps LSP capabilities closest to the agent tool runtime
|
|
||||||
- it avoids building a second transport bridge between Electron main and the sidecar before the tool surface is proven
|
|
||||||
- it preserves the user-facing model of "enable a tool for this session and let the agent use it"
|
|
||||||
|
|
||||||
### 6. Prefer one user-facing tooling model
|
|
||||||
|
|
||||||
The long-term product should not feel like "MCP over here, raw LSP over there" from a UX perspective.
|
|
||||||
|
|
||||||
Recommended path:
|
|
||||||
|
|
||||||
- implement direct MCP runtime support first
|
|
||||||
- implement LSP as a backend capability service second
|
|
||||||
- where feasible, expose LSP-backed actions to agents through MCP-like or tool-like abstractions instead of teaching the system two unrelated tool invocation models
|
|
||||||
|
|
||||||
## Proposed data models
|
|
||||||
|
|
||||||
The exact names can change, but the structure should follow these boundaries.
|
|
||||||
|
|
||||||
### MCP definitions
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface McpServerDefinition {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
transport: 'stdio' | 'sse' | 'streamable-http';
|
|
||||||
command?: string;
|
|
||||||
args?: string[];
|
|
||||||
url?: string;
|
|
||||||
env?: McpEnvironmentBinding[];
|
|
||||||
cwdStrategy?: 'project-root' | 'custom';
|
|
||||||
customCwd?: string;
|
|
||||||
enabled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface McpEnvironmentBinding {
|
|
||||||
key: string;
|
|
||||||
valueSource: 'literal' | 'secret-ref';
|
|
||||||
value?: string;
|
|
||||||
secretRef?: string;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### LSP profiles
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface LspProfileDefinition {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
languageIds: string[];
|
|
||||||
transport: 'stdio';
|
|
||||||
command: string;
|
|
||||||
args?: string[];
|
|
||||||
initialization?: {
|
|
||||||
rootStrategy: 'project-root' | 'workspace-roots';
|
|
||||||
initializationOptions?: Record<string, unknown>;
|
|
||||||
};
|
|
||||||
enabled?: boolean;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Runtime diagnostics
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface ToolingHealthSummary {
|
|
||||||
status: 'ready' | 'warning' | 'error' | 'disabled';
|
|
||||||
summary: string;
|
|
||||||
detail?: string;
|
|
||||||
checkedAt: string;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Use separate summaries for:
|
|
||||||
|
|
||||||
- workspace MCP health
|
|
||||||
- current session MCP enablement health
|
|
||||||
- LSP profile health
|
|
||||||
- current session LSP enablement health
|
|
||||||
|
|
||||||
## Backend execution plan
|
|
||||||
|
|
||||||
Backend must be executed first.
|
|
||||||
|
|
||||||
### B0. Domain and persistence foundation
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/shared/domain/workspace.ts`
|
|
||||||
- `src/shared/domain/session.ts`
|
|
||||||
- `src/main/persistence/workspaceRepository.ts`
|
|
||||||
- `tests/shared/workspace.test.ts`
|
|
||||||
- `tests/shared/session.test.ts`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- add optional workspace-level tooling settings
|
|
||||||
- add optional session-level tooling enablement
|
|
||||||
- keep persisted migration additive and backward compatible
|
|
||||||
- ensure legacy workspaces load without mutation errors
|
|
||||||
- do not persist any secret values
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- old workspaces still load
|
|
||||||
- new fields round-trip through persistence
|
|
||||||
- tests cover legacy and new shapes
|
|
||||||
|
|
||||||
### B1. Main-process tooling services and IPC
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/main/EryxAppService.ts`
|
|
||||||
- `src/shared/contracts/ipc.ts`
|
|
||||||
- `src/shared/contracts/channels.ts`
|
|
||||||
- `src/main/ipc/registerIpcHandlers.ts`
|
|
||||||
- `src/preload/index.ts`
|
|
||||||
|
|
||||||
Recommended additions:
|
|
||||||
|
|
||||||
- CRUD for MCP server definitions
|
|
||||||
- CRUD for LSP profiles
|
|
||||||
- session enable/disable methods for both systems
|
|
||||||
- diagnostics/status methods
|
|
||||||
- secret-reference save/delete flows that route through `SecretStore`
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- renderer gets a typed, renderer-safe API
|
|
||||||
- all config changes persist through `WorkspaceRepository`
|
|
||||||
- diagnostics can be queried without starting a session
|
|
||||||
- session enablement can be updated without mutating global definitions
|
|
||||||
|
|
||||||
### B2. Sidecar protocol expansion for MCP
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/shared/contracts/sidecar.ts`
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Contracts/ProtocolModels.cs`
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/SidecarProtocolHost.cs`
|
|
||||||
- `src/main/sidecar/sidecarProcess.ts`
|
|
||||||
- `sidecar/tests/Eryx.AgentHost.Tests/SidecarProtocolHostTests.cs`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- extend capabilities with MCP availability/diagnostics
|
|
||||||
- extend `run-turn` with selected MCP runtime bindings
|
|
||||||
- optionally add dedicated MCP health validation commands if needed
|
|
||||||
- keep the protocol additive to avoid breaking existing clients
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- TS and C# contracts remain in sync
|
|
||||||
- protocol tests cover the new shapes
|
|
||||||
- existing capabilities and run-turn behavior still work without MCP config
|
|
||||||
|
|
||||||
### B3. MCP runtime attachment in the sidecar
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/CopilotWorkflowRunner.cs`
|
|
||||||
- new helper services under `sidecar/src/Eryx.AgentHost/Services/`
|
|
||||||
- `sidecar/tests/Eryx.AgentHost.Tests/CopilotWorkflowRunnerTests.cs`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- translate main-process MCP definitions into runtime-attached tools
|
|
||||||
- attach tools during `SessionConfig` creation
|
|
||||||
- handle startup failures and unsupported transports cleanly
|
|
||||||
- emit richer activity when tool/server identity matters
|
|
||||||
- revisit the current blanket `ApprovePermissionAsync(...)` behavior before enabling arbitrary external tools
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- project-backed runs can invoke enabled MCP tools
|
|
||||||
- tool failures surface clearly to the app
|
|
||||||
- scratchpad behavior remains intentionally restricted unless product scope changes
|
|
||||||
|
|
||||||
### B4. LSP tool sessions in the sidecar
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/LspToolSession.cs`
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/SessionToolingBundle.cs`
|
|
||||||
- `package.json`
|
|
||||||
- `sidecar/tests/Eryx.AgentHost.Tests/*`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- start selected LSP server processes inside the sidecar for the active run
|
|
||||||
- initialize them against the current session project root
|
|
||||||
- expose a focused read-oriented tool surface to agents
|
|
||||||
- keep lifecycle cleanup bound to the run/session bundle
|
|
||||||
- start with TypeScript-first support
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- a project-backed session can initialize at least one supported LSP profile
|
|
||||||
- agents can call the exposed LSP tools without any renderer-managed process lifecycle
|
|
||||||
- no raw LSP JSON-RPC is exposed to the renderer
|
|
||||||
|
|
||||||
### B5. LSP bridge into agent runtime
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/main/EryxAppService.ts`
|
|
||||||
- `src/shared/contracts/sidecar.ts`
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Contracts/ProtocolModels.cs`
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/SessionToolingBundle.cs`
|
|
||||||
- `sidecar/src/Eryx.AgentHost/Services/LspToolSession.cs`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- compose selected LSP profiles into the `run-turn` payload from Electron main
|
|
||||||
- translate those profiles into sidecar-local tool sessions
|
|
||||||
- expose a stable subset of LSP-backed operations to agents
|
|
||||||
- avoid turning the renderer into a second IDE protocol stack
|
|
||||||
|
|
||||||
Recommended direction:
|
|
||||||
|
|
||||||
- use sidecar-local `AIFunction` tools for agent consumption
|
|
||||||
- keep the exposed operations narrow and project-oriented
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- agents can request useful LSP-backed project intelligence during project runs
|
|
||||||
- the contract is observable and testable from the app side
|
|
||||||
|
|
||||||
### B6. Backend hardening and validation
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- impacted TS and C# tests
|
|
||||||
- `package.json`
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
- `bun test`
|
|
||||||
- `bun run sidecar:test`
|
|
||||||
- `bun run build`
|
|
||||||
|
|
||||||
Hardening checklist:
|
|
||||||
|
|
||||||
- additive migration coverage
|
|
||||||
- bad configuration/error reporting coverage
|
|
||||||
- environment sanitization review for spawned tools/servers
|
|
||||||
- sidecar protocol regression coverage
|
|
||||||
|
|
||||||
## Frontend execution plan
|
|
||||||
|
|
||||||
Frontend should start only after backend APIs and diagnostics are stable.
|
|
||||||
|
|
||||||
### F1. Read-only diagnostics surfaces
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/renderer/App.tsx`
|
|
||||||
- `src/renderer/components/SettingsPanel.tsx`
|
|
||||||
- `src/renderer/components/CopilotStatusCard.tsx`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- add MCP and LSP sections in settings
|
|
||||||
- surface backend-reported health, readiness, and counts
|
|
||||||
- reuse the current diagnostics-card style before introducing complex editors
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- users can see whether MCP/LSP are configured and healthy
|
|
||||||
- failures are understandable without opening logs
|
|
||||||
|
|
||||||
### F2. Global configuration editors
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/renderer/components/SettingsPanel.tsx`
|
|
||||||
- new renderer components for MCP/LSP editors
|
|
||||||
- `src/renderer/App.tsx`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- create/edit/delete MCP server definitions
|
|
||||||
- create/edit/delete LSP profiles
|
|
||||||
- manage secret references safely
|
|
||||||
- do not mix global definition editing with per-session toggles
|
|
||||||
- allow secret references without ever echoing raw secrets back into the renderer state
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- all backend CRUD flows are reachable through the UI
|
|
||||||
- global definitions are understandable and recoverable
|
|
||||||
|
|
||||||
### F3. Session tooling panel controls
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/renderer/components/ActivityPanel.tsx`
|
|
||||||
- `src/renderer/App.tsx`
|
|
||||||
- supporting renderer state/helpers
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- extend the current right-side activity panel with MCP/LSP enable/disable controls for the selected session
|
|
||||||
- show which global tools are available vs enabled for the session
|
|
||||||
- disable LSP/MCP controls when the selected session cannot use them, such as scratchpad if that restriction remains
|
|
||||||
- surface lightweight health/state next to each toggle
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- users can enable or disable global MCPs/LSPs per session from the right-side panel
|
|
||||||
- session toggles are persisted on the session record and survive app reloads
|
|
||||||
|
|
||||||
### F4. Runtime visibility in chat/activity surfaces
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/renderer/components/ActivityPanel.tsx`
|
|
||||||
- `src/renderer/lib/sessionActivity.ts`
|
|
||||||
- `src/shared/domain/event.ts`
|
|
||||||
- possibly `src/renderer/components/ChatPane.tsx`
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- show tool server name + tool name clearly
|
|
||||||
- distinguish MCP activity from LSP-backed activity if both appear
|
|
||||||
- show meaningful failure summaries
|
|
||||||
- leave room for a future richer timeline without blocking this phase
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- users can tell what tool/server was used during a run
|
|
||||||
- failures do not collapse into generic "tool-calling" noise
|
|
||||||
|
|
||||||
### F5. Session-level polish and troubleshooting UX
|
|
||||||
|
|
||||||
Primary files:
|
|
||||||
|
|
||||||
- `src/renderer/components/ActivityPanel.tsx`
|
|
||||||
- `src/renderer/components/ChatPane.tsx`
|
|
||||||
- any supporting session detail surfaces
|
|
||||||
|
|
||||||
Tasks:
|
|
||||||
|
|
||||||
- show current session tooling status clearly
|
|
||||||
- add "why unavailable?" and "fix configuration" entry points
|
|
||||||
- optionally add compact badges or chips for active MCP/LSP selections
|
|
||||||
|
|
||||||
Acceptance:
|
|
||||||
|
|
||||||
- session-scoped tooling is visible without leaving the main workflow
|
|
||||||
- troubleshooting paths are discoverable
|
|
||||||
|
|
||||||
## Handoff between backend and frontend agents
|
|
||||||
|
|
||||||
### Backend agent handoff deliverables
|
|
||||||
|
|
||||||
The backend pass should hand off:
|
|
||||||
|
|
||||||
- finalized shared domain shapes
|
|
||||||
- finalized IPC contract
|
|
||||||
- finalized sidecar contract changes
|
|
||||||
- clear diagnostics payloads
|
|
||||||
- scratchpad/tool policy behavior
|
|
||||||
- finalized session enablement state shape
|
|
||||||
- test coverage for persistence, protocol, and runtime behavior
|
|
||||||
|
|
||||||
### Frontend agent prerequisites
|
|
||||||
|
|
||||||
The frontend agent should not start until it has:
|
|
||||||
|
|
||||||
- stable backend CRUD endpoints
|
|
||||||
- stable health/diagnostic payloads
|
|
||||||
- stable activity event shapes
|
|
||||||
- at least one working MCP path and one working LSP profile path to design against
|
|
||||||
- stable session enable/disable semantics for the right-side panel
|
|
||||||
|
|
||||||
## Risks and decisions to settle early
|
|
||||||
|
|
||||||
### A. Define what "LSP support" means in v1
|
|
||||||
|
|
||||||
This is the biggest scope decision. Options include:
|
|
||||||
|
|
||||||
- agent-facing project intelligence only
|
|
||||||
- agent-facing intelligence plus light read-only diagnostics in the UI
|
|
||||||
- a much larger editor-like in-app LSP experience
|
|
||||||
|
|
||||||
Recommended default:
|
|
||||||
|
|
||||||
- agent-facing project intelligence first
|
|
||||||
- diagnostics UI second
|
|
||||||
- editor-like UX later
|
|
||||||
|
|
||||||
### B. Decide the scratchpad policy
|
|
||||||
|
|
||||||
Current behavior is strongly tool-free. Keep that default unless product scope explicitly changes.
|
|
||||||
|
|
||||||
### C. Decide the default session behavior
|
|
||||||
|
|
||||||
Need to decide whether new sessions start with:
|
|
||||||
|
|
||||||
- no MCPs/LSPs enabled by default
|
|
||||||
- a safe recommended subset enabled by default
|
|
||||||
- the same enablement as the previously selected session
|
|
||||||
|
|
||||||
Recommended default:
|
|
||||||
|
|
||||||
- start disabled by default until a session explicitly enables a tool
|
|
||||||
|
|
||||||
### D. Decide provisioning and trust
|
|
||||||
|
|
||||||
Need explicit decisions for:
|
|
||||||
|
|
||||||
- bundled vs user-installed MCP/LSP servers
|
|
||||||
- which transports are allowed in v1
|
|
||||||
- whether arbitrary commands are allowed
|
|
||||||
- whether write-capable tools need approval
|
|
||||||
- whether LSP starts TypeScript-only first
|
|
||||||
|
|
||||||
### E. Decide the approval/safety model
|
|
||||||
|
|
||||||
`ApprovePermissionAsync(...)` currently auto-approves. That is not a sufficient trust model for arbitrary MCP tooling. A v1 safety story is needed before enabling broad external tool execution.
|
|
||||||
|
|
||||||
### F. Decide observability depth
|
|
||||||
|
|
||||||
Current activity events are coarse. MCP/LSP may require richer activity or trace events to stay understandable.
|
|
||||||
|
|
||||||
## Recommended sequencing summary
|
|
||||||
|
|
||||||
1. B0: persisted vocabulary and migration-safe shapes
|
|
||||||
2. B1: main-process API and diagnostics
|
|
||||||
3. B2: sidecar protocol expansion
|
|
||||||
4. B3: MCP runtime support
|
|
||||||
5. B4: Electron-main LSP service
|
|
||||||
6. B5: LSP bridge into agent runtime
|
|
||||||
7. F1-F5: frontend diagnostics, global editors, session toggles, visibility, and polish
|
|
||||||
|
|
||||||
## Out of scope for the first implementation pass
|
|
||||||
|
|
||||||
- a full IDE/editor inside Eryx
|
|
||||||
- raw LSP transport in the renderer
|
|
||||||
- persisted secret values in workspace files
|
|
||||||
- broad packaging/install automation for every possible LSP/MCP ecosystem on day one
|
|
||||||
|
|
||||||
## Suggested validation gate before frontend begins
|
|
||||||
|
|
||||||
Before handing to the frontend agent, the backend agent should be able to demonstrate:
|
|
||||||
|
|
||||||
- additive workspace persistence for MCP/LSP config
|
|
||||||
- at least one working MCP-backed agent flow in a project session
|
|
||||||
- one initialized, health-reporting LSP profile in Electron main
|
|
||||||
- per-session enable/disable persistence for selected MCPs/LSPs
|
|
||||||
- stable diagnostics payloads exposed to the renderer
|
|
||||||
- passing `bun test`, `bun run sidecar:test`, and `bun run build`
|
|
||||||
Reference in New Issue
Block a user