From 1f5c9e130c1137d670aa08b3e44b0f3b1920e1e2 Mon Sep 17 00:00:00 2001 From: OpenClaw Date: Fri, 22 May 2026 23:40:33 -0800 Subject: [PATCH 1/3] Eclipse fork analysis: architecture audit, MCP constraint bridge, bathymetric editor design, multi-model routing --- ARCHITECTURE-AUDIT.md | 760 ++++++++++++++++++++++++++++++++++++ CONSTRAINT-EDITOR-DESIGN.md | 757 +++++++++++++++++++++++++++++++++++ MULTI-MODEL-DESIGN.md | 460 ++++++++++++++++++++++ 3 files changed, 1977 insertions(+) create mode 100644 ARCHITECTURE-AUDIT.md create mode 100644 CONSTRAINT-EDITOR-DESIGN.md create mode 100644 MULTI-MODEL-DESIGN.md diff --git a/ARCHITECTURE-AUDIT.md b/ARCHITECTURE-AUDIT.md new file mode 100644 index 00000000..c2bc9d71 --- /dev/null +++ b/ARCHITECTURE-AUDIT.md @@ -0,0 +1,760 @@ +# Architecture Audit: GitHub Copilot for Eclipse + +**Version:** 0.18.0-SNAPSHOT +**Date:** 2026-05-22 +**Codebase:** ~507 Java files, ~83,669 lines +**Build:** Maven + Tycho 4.0.13, targets JavaSE-21 + +--- + +## 1. System Overview + +GitHub Copilot for Eclipse is an Eclipse IDE plugin that wraps the **Copilot Language Server (CLS)** — a proprietary binary/JS agent from Microsoft — and exposes its capabilities through Eclipse's LSP4E framework. The plugin provides: + +- **Inline code completions** (ghost text) +- **Chat panel** with multi-turn conversations, multiple models, and vision support +- **Agent mode** with autonomous tool execution (file create/edit, terminal, debugger, etc.) +- **Next Edit Suggestions** (inline edits beyond just completion) +- **MCP (Model Context Protocol)** integration for external tool servers +- **BYOK (Bring Your Own Key)** for custom LLM providers +- **Coding Agent** for autonomous coding tasks +- **Git integration** (commit message generation, PR search) + +The plugin is structured as an **OSGi multi-bundle** system with Tycho building platform-specific fragments for the native Copilot Language Server binary. + +### Module Layout + +| Module | Purpose | +|--------|---------| +| `com.microsoft.copilot.eclipse.core` | LSP connection, protocol types, auth, persistence, chat events, MCP protocol | +| `com.microsoft.copilot.eclipse.ui` | Chat view, tool implementations, completions UI, settings pages, extension points | +| `com.microsoft.copilot.eclipse.ui.jobs` | Background job infrastructure | +| `com.microsoft.copilot.eclipse.terminal.api` | Terminal SPI (`IRunInTerminalTool`, `ShellIntegrationScripts`) | +| `com.microsoft.copilot.eclipse.ui.terminal` | Modern terminal tool (TM Terminal based) | +| `com.microsoft.copilot.eclipse.ui.terminal.tm` | Alternate terminal tool | +| `com.microsoft.copilot.eclipse.core.agent.{platform}` | Platform-specific native binary fragments (5 platforms) | +| `com.microsoft.copilot.eclipse.branding` | Plugin branding | +| `com.microsoft.copilot.eclipse.feature` | Eclipse feature descriptor | +| `com.microsoft.copilot.eclipse.repository` | P2 update site | + +--- + +## 2. LSP Layer + +### 2.1 Language Server Startup (`LsStreamConnectionProvider`) + +**Class:** `com.microsoft.copilot.eclipse.core.lsp.LsStreamConnectionProvider` +**Extends:** `ProcessStreamConnectionProvider` (from LSP4E) + +The startup follows a **binary-first, JS-fallback** strategy: + +1. **Binary agent** — attempts to locate and launch `copilot-language-server` (or `.exe` on Windows) from platform-specific fragment bundles +2. **JS fallback** — if binary fails, falls back to running `language-server.js` via Node.js from the Wild Web Developer embedded Node +3. **Debug mode** — `COPILOT_DEBUG_LOCAL=true` env var forces JS agent with `--inspect` + +Both paths append `--stdio` and enforce UTF-8 encoding. + +**Binary resolution flow:** +``` +getPlatformSpecificFragmentBundleId() → identifies correct fragment bundle + → com.microsoft.copilot.eclipse.core.agent.linux.x64 + → com.microsoft.copilot.eclipse.core.agent.linux.aarch64 + → com.microsoft.copilot.eclipse.core.agent.win32 + → com.microsoft.copilot.eclipse.core.agent.macosx.x64 + → com.microsoft.copilot.eclipse.core.agent.macosx.aarch64 + +findBinaryFromFragment() → loads "copilot-agent" entry from fragment bundle + → resolves to: copilot-language-server (or copilot-language-server.exe) +``` + +**Initialization options** sent to the server: +```java +InitializationOptions { + editorInfo: NameAndVersion("Eclipse", ) + editorPluginInfo: NameAndVersion("copilot-eclipse", ) + capabilities: CopilotCapabilities { + supportsSemanticHighlighting: false, + workspaceContextEnabled: , + subAgentEnabled: , + supportedUriSchemes: ["file", ...] + } +} +``` + +**macOS shell environment:** On macOS, it spawns `/bin/zsh -i -l -c env` with a 5-second timeout to harvest login shell environment variables. This is necessary because MCP servers launched from the agent may need PATH and other env vars from the user's shell profile. + +### 2.2 Client → Server Protocol (`CopilotLanguageServer`) + +**Interface:** `com.microsoft.copilot.eclipse.core.lsp.CopilotLanguageServer` +**Extends:** `LanguageServer` (LSP4J) + +All methods use `@JsonRequest` / `@JsonNotification` annotations for LSP4J's JSON-RPC serialization. + +**Authentication:** +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `checkStatus(CheckStatusParams)` | `checkStatus` | Check login status | +| `signInInitiate(NullParams)` | `signInInitiate` | Start device-code OAuth flow | +| `signInConfirm(SignInConfirmParams)` | `signInConfirm` | Complete sign-in with user code | +| `signOut(NullParams)` | `signOut` | Sign out | + +**Completions:** +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `getCompletions(CompletionParams)` | — | Inline code suggestions | +| `notifyShown(NotifyShownParams)` | — | Telemetry: suggestion displayed | +| `notifyAccepted(NotifyAcceptedParams)` | — | Telemetry: suggestion accepted | +| `notifyRejected(NotifyRejectedParams)` | — | Telemetry: suggestion rejected | +| `getNextEditSuggestions(...)` | `textDocument/copilotInlineEdit` | Next Edit Suggestions | + +**Chat:** +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `create(ConversationCreateParams)` | `conversation/create` | Create new conversation | +| `addTurn(ConversationTurnParams)` | `conversation/turn` | Add turn to conversation | +| `listTemplates(ConversationTemplatesParams)` | `conversation/templates` | List prompt templates | +| `listModes(ConversationModesParams)` | `conversation/modes` | List chat modes (agent, ask, etc.) | +| `listAgents(NullParams)` | `conversation/agents` | List conversation agents | +| `copyCode(...)` | `conversation/copyCode` | Telemetry: code copy | +| `persistence(NullParams)` | `conversation/persistence` | Get persistence token | +| `destroy(ConversationDestroyParams)` | `conversation/destroy` | Destroy conversation | +| `registerTools(RegisterToolsParams)` | `conversation/registerTools` | Register client-side tools | +| `updateConversationToolsStatus(...)` | `conversation/updateToolsStatus` | Enable/disable built-in tools | +| `notifyCodeAcceptance(...)` | `conversation/notifyCodeAcceptance` | Code acceptance telemetry | + +**MCP:** +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `updateMcpToolsStatus(...)` | `mcp/updateToolsStatus` | Enable/disable MCP tools | +| `listMcpServers(ListServersParams)` | `mcp/registry/listServers` | List MCP servers from registry | +| `getMcpServer(GetServerParams)` | `mcp/registry/getServer` | Get MCP server details | +| `getMcpAllowlist(Object)` | `mcp/registry/getAllowlist` | Get allowlist | + +**BYOK:** +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `listByokModels(ByokListModelParams)` | `copilot/byok/listModels` | List BYOK models | +| `saveByokModel(ByokModel)` | `copilot/byok/saveModel` | Save BYOK model | +| `deleteByokModel(ByokModel)` | `copilot/byok/deleteModel` | Delete BYOK model | +| `saveByokApiKey(ByokApiKey)` | `copilot/byok/saveApiKey` | Save API key | +| `deleteByokApiKey(ByokApiKey)` | `copilot/byok/deleteApiKey` | Delete API key | +| `listByokApiKeys(ByokApiKey)` | `copilot/byok/listApiKeys` | List API keys | + +**Other:** +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `listModels(NullParams)` | `copilot/models` | List available Copilot models | +| `generateCommitMessage(...)` | `git/commitGenerate` | Generate git commit message | +| `generateThinkingTitle(...)` | `thinking/generateTitle` | Summarize thinking block | +| `searchPr(SearchPrParams)` | `githubApi/searchPR` | Search GitHub PRs | +| `checkQuota(NullParams)` | `checkQuota` | Check usage quota | +| `sendExceptionTelemetry(...)` | `telemetry/exception` | Send to GitHub Sentry | +| `didShowInlineEdit(...)` | `textDocument/didShowInlineEdit` | Inline edit shown notification | + +### 2.3 Server → Client Protocol (`CopilotLanguageClient`) + +**Class:** `com.microsoft.copilot.eclipse.core.lsp.CopilotLanguageClient` +**Extends:** `LanguageClientImpl` (LSP4E) + +Handles **requests from the language server to the Eclipse client:** + +| Method | LSP Method | Purpose | +|--------|-----------|---------| +| `getConversationContext(...)` | `conversation/context` | Provide current editor context | +| `invokeClientTool(...)` | `conversation/invokeClientTool` | Server requests tool execution | +| `confirmClientTool(...)` | `conversation/invokeClientToolConfirmation` | User confirmation for tool | +| `getWatchedFiles(...)` | `copilot/watchedFiles` | Return watched file list | +| `mcpTools(...)` | `copilot/mcpTools` | MCP tool change notification | +| `mcpRuntimeLogs(...)` | `copilot/mcpRuntimeLogs` | MCP runtime log notification | +| `onRateLimitWarning(...)` | `$/copilot/rateLimitWarning` | Rate limit warning | +| `onQuotaWarning(...)` | `copilot/quotaWarning` | Quota warning | +| `onDidChangeFeatureFlags(...)` | `copilot/didChangeFeatureFlags` | Server pushes feature flags | +| `onDidChangePolicy(...)` | `policy/didChange` | Enterprise policy changes | +| `onDidChangeCustomSkill(...)` | `copilot/customSkill/didChange` | Custom skill change | +| `onDidChangeCustomPrompt(...)` | `copilot/customPrompt/didChange` | Custom prompt change | +| `mcpOauth(...)` | `copilot/dynamicOAuth` | MCP OAuth flow | +| `onCodingAgentMessage(...)` | `copilot/codingAgentMessage` | Coding agent message | +| `readFile(String uri)` | `workspace/readFile` | Read file contents + stats | +| `readDirectory(String uri)` | `workspace/readDirectory` | List directory entries | +| `findFiles(FindFilesParams)` | `workspace/findFiles` | Glob file search | +| `findTextInFiles(...)` | `workspace/findTextInFiles` | Text/regex search | +| `notifyProgress(...)` | `$/progress` | Chat progress updates | +| `showDocument(...)` | `window/showDocument` | Open file/URL (overrides for browser) | + +**Event propagation:** Most notifications post to Eclipse's `IEventBroker` using constants from `CopilotEventConstants`, enabling loose coupling between the LSP layer and UI. + +### 2.4 Connection Layer (`CopilotLanguageServerConnection`) + +**Class:** `com.microsoft.copilot.eclipse.core.lsp.CopilotLanguageServerConnection` + +This is the **high-level API facade** that wraps `LanguageServerWrapper` (LSP4E) and provides typed methods for all operations. Key patterns: + +- All requests go through `languageServerWrapper.execute(fn)` which queues the request to the language server +- All notifications go through `languageServerWrapper.sendNotification(fn)` +- Document lifecycle: `connectDocument(IDocument, IFile)` / `disconnectDocument(URI)` +- `SERVER_ID = "com.microsoft.copilot.eclipse.ls"` + +**Conversation creation flow:** +```java +createConversation(workDoneToken, message, files, currentFile, selection, + activeModel, reasoningEffort, chatModeName, customChatModeId, + todos, agentSlug, agentJobWorkspaceFolder, conversationId, + restoreToTurnId, workspaceFolders) +``` + +This assembles `ConversationCreateParams` with: +- Prompt as `Either>` (supports images for vision models) +- Historical turns prepended +- Model info with optional `reasoningEffort` +- `needToolCallConfirmation = true` (client handles tool confirmations) +- Chat mode and custom mode ID +- Agent slug for sub-agent conversations +- Optional `conversationId` + `restoreToTurnId` for session restoration + +--- + +## 3. Chat System + +### 3.1 Conversations & Turns + +**Conversation lifecycle:** +1. `create()` → `ChatCreateResult { conversationId, turnId, agentSlug, modelName, modelProviderName, billingMultiplier }` +2. Server streams `$/progress` notifications with `ChatProgressValue` containing incremental reply content +3. `addTurn()` adds subsequent user messages +4. `destroy()` terminates in-progress processing + +**Chat modes** (from `conversation/modes`): +- Built-in: Agent, Ask (etc.) +- Custom: User-defined via `CustomChatMode` → supports tool configuration, custom model, hand-offs + +**Conversation agents:** Currently hard-coded to only expose `@project` agent (slug: `"project"`). The `@github` agent is not yet enabled. + +### 3.2 Progress & Streaming + +The server sends `$/progress` notifications with `ChatProgressValue` containing: +- Incremental reply text +- Tool calls and their results +- Thinking blocks with collapsible summaries +- Step status updates +- Todo list updates + +These are routed through `ChatEventsManager.notifyProgress()` → `IEventBroker` → UI update. + +### 3.3 Templates & Customization + +- **Conversation templates** (`conversation/templates`): Built-in prompt templates discovered from workspace folders +- **Custom skills** (`copilot/customSkill/didChange`): User-defined skills +- **Custom prompts** (`copilot/customPrompt/didChange`): User-defined prompt files + +--- + +## 4. Tool System + +### 4.1 Architecture + +**Tool registration flow:** +``` +AgentToolService.registerDefaultTools() + → Creates tool instances (CreateFileTool, EditFileTool, GetErrorsTool, JavaDebuggerToolAdapter) + → registerToolWithServer() → lsConnection.registerTools(RegisterToolsParams) + → Server returns List (server's view of registered tools) +``` + +**Tool invocation flow:** +``` +CLS sends "conversation/invokeClientTool" request + → CopilotLanguageClient.invokeClientTool() + → ChatEventsManager.invokeAgentTool() + → AgentToolService.onToolInvocation() + → BaseTool.invoke() + → Tool executes, returns LanguageModelToolResult[] +``` + +**Tool confirmation flow:** +``` +CLS sends "conversation/invokeClientToolConfirmation" request + → CopilotLanguageClient.confirmClientTool() + → ChatEventsManager.confirmAgentToolInvocation() + → AgentToolService.onToolConfirmation() + → Finds TurnWidget in ChatView + → activeTurnWidget.requestToolExecutionConfirmation() + → User sees confirmation dialog → approve/deny + → Returns LanguageModelToolConfirmationResult { APPROVE / DENY / DISMISS } +``` + +### 4.2 BaseTool Interface + +```java +abstract class BaseTool { + String name; + CompletableFuture invoke(Map input, ChatView chatView); + LanguageModelToolInformation getToolInformation(); // includes InputSchema, confirmation messages + boolean needConfirmation(); // default: false + ConfirmationMessages getConfirmationMessages(); +} +``` + +### 4.3 Built-in Tools + +| Tool | Class | Confirmation | Purpose | +|------|-------|-------------|---------| +| `create_file` | `CreateFileTool` | ✅ | Create new files with content | +| `edit_file` | `EditFileTool` | ✅ | Edit existing files with diff | +| `get_errors` | `GetErrorsTool` | ❌ | Get diagnostic errors for files | +| `java_debugger` | `JavaDebuggerToolAdapter` | ✅ | Full Java debugger control (1334 lines) | +| `run_in_terminal` | `RunInTerminalToolAdapter` | ✅ | Execute commands in terminal | +| `get_terminal_output` | `GetTerminalOutputTool` | ❌ | Retrieve terminal output | + +### 4.4 JavaDebuggerToolAdapter + +This is the most complex tool (1334 lines). It provides **complete Java debug session control**: + +**Actions:** `get_state`, `get_variables`, `get_stack_trace`, `evaluate_expression`, `set_variable`, `set_breakpoint`, `remove_breakpoint`, `list_breakpoints`, `set_exception_breakpoint`, `remove_exception_breakpoint`, `step_over`, `step_into`, `step_out`, `continue`, `suspend` + +**Key features:** +- Conditional breakpoints with Java boolean expressions +- Hit count breakpoints +- Expression evaluation using JDT's `IAstEvaluationEngine` with 5-second timeout +- Nested variable inspection with configurable depth +- Thread selection by unique ID +- Automatic fallback thread selection (first suspended thread) +- Exception breakpoints (caught/uncaught) +- Variable modification for primitives, strings, and null + +**Only registered when:** `JdtUtils.isJdtDebugAvailable() && PlatformUtils.isNightly()` + +### 4.5 File Tool Service + +`FileToolService` manages the "working set" — files created or edited by the agent that await user review. It provides: +- `WorkingSetBar` UI showing pending file changes +- Keep/undo/diff-view operations per file +- Batch keep-all / undo-all +- Observables (`IObservableValue`) for reactive UI updates + +--- + +## 5. Completion System + +### 5.1 Inline Code Completions + +**Core:** `CompletionProvider` → `CopilotLanguageServerConnection.getCompletions(CompletionParams)` +**UI:** `CompletionManager` manages ghost text rendering in editors + +Ghost text types: +- `EolGhostText` — end-of-line suggestions +- `InlineGhostText` — inline suggestions +- `GhostText` — base ghost text abstraction +- `BlockGhostText` — multi-line block suggestions +- `LineEndGhostText` / `LineContentGhostText` — code mining-based + +### 5.2 Next Edit Suggestions (NES) + +**Request:** `textDocument/copilotInlineEdit` → `NextEditSuggestionsResult` +**Notification:** `textDocument/didShowInlineEdit` (telemetry) +**Accept:** `github.copilot.didAcceptNextEditSuggestionItem` workspace command + +--- + +## 6. Terminal Integration + +### 6.1 SPI Architecture + +**API bundle:** `com.microsoft.copilot.eclipse.terminal.api` +- `IRunInTerminalTool` — interface for terminal implementations +- `ShellIntegrationScripts` — shell integration markers for output capture +- `TerminalServiceManager` — singleton service locator with listener pattern + +**Two implementations:** +1. `com.microsoft.copilot.eclipse.ui.terminal.RunInTerminalTool` — modern, TM Terminal based (OSGi `@Component`) +2. `com.microsoft.copilot.eclipse.ui.terminal.tm.RunInTerminalTool` — alternate + +### 6.2 Terminal Tool Adapter + +`RunInTerminalToolAdapter` wraps `IRunInTerminalTool` as a `BaseTool`: +- Executes commands in a dedicated "Copilot" terminal tab +- Supports background execution with `executionId` tracking +- Uses shell integration markers to detect command completion +- `GetTerminalOutputTool` retrieves output from background commands + +--- + +## 7. MCP (Model Context Protocol) + +### 7.1 Protocol Types + +**Package:** `com.microsoft.copilot.eclipse.core.lsp.mcp` + +| Class | Purpose | +|-------|---------| +| `McpServerToolsCollection` | Server → tool mappings | +| `McpServerStatus` | Server status enum | +| `McpRegistryAllowList` | User/org allowlist | +| `McpRegistryEntry` | Registry entry | +| `McpRegistryOwner` | Registry ownership | +| `McpOauthRequest` | OAuth flow data | +| `McpRuntimeLog` | Runtime log events | +| `McpPrompt` / `McpResource` / `McpResourceTemplate` | MCP primitives | +| `McpToolsStatusCollection` / `McpServerToolsStatusCollection` | Tool status tracking | + +**Registry sub-package:** `com.microsoft.copilot.eclipse.core.lsp.mcp.registry` +- `ServerList`, `ServerResponse`, `ServerDetail` — registry API responses +- `StdioTransport`, `SseTransport`, `UrlBasedTransport` — transport types +- `TransportType` — enum of transport types + +### 7.2 MCP Lifecycle + +1. **Discovery:** `listMcpServers(ListServersParams)` → fetches from Copilot MCP registry +2. **Tool notification:** Server sends `copilot/mcpTools` → `CopilotLanguageClient.mcpTools()` → posts to event broker +3. **Status management:** `updateMcpToolsStatus(UpdateMcpToolsStatusParams)` → enable/disable individual tools +4. **OAuth:** `copilot/dynamicOAuth` → `IMcpConfigService.mcpOauth()` → shows dialog, returns credentials +5. **Runtime logs:** `copilot/mcpRuntimeLogs` → forwarded to UI for display + +### 7.3 MCP Configuration Service + +`IMcpConfigService` (from `IChatServiceManager.getMcpConfigService()`): +- Manages MCP server configurations +- Handles OAuth flows +- Provides MCP server configs for persistence + +--- + +## 8. BYOK (Bring Your Own Key) + +Supports plugging in external LLM providers (OpenAI, Anthropic, etc.) with your own API keys. + +**Protocol types:** `com.microsoft.copilot.eclipse.core.lsp.protocol.byok` +- `ByokModel` — model definition (provider, model ID, capabilities) +- `ByokApiKey` — API key (provider, key reference) +- `ByokListModelParams` / `ByokListModelResponse` — list models +- `ByokStatusResponse` — operation result +- `ByokListApiKeyResponse` — key listing + +**Server methods:** `listByokModels`, `saveByokModel`, `deleteByokModel`, `saveByokApiKey`, `deleteByokApiKey`, `listByokApiKeys` + +**Feature flag:** `FeatureFlags.isByokEnabled()` — controlled by server via `copilot/didChangeFeatureFlags` + +--- + +## 9. Coding Agent + +**Protocol types:** `com.microsoft.copilot.eclipse.core.lsp.protocol.codingagent` + +The coding agent enables autonomous coding tasks: + +```java +CodingAgentMessageRequestParams { + String title; + String description; + String prLink; + String conversationId; + String turnId; +} + +CodingAgentMessageResult { + boolean success; + String error; +} +``` + +**Flow:** +1. Server sends `copilot/codingAgentMessage` request to client +2. `CopilotLanguageClient.onCodingAgentMessage()` → posts to event broker as `TOPIC_CHAT_CODING_AGENT_MESSAGE` +3. Client returns `CodingAgentMessageResult { success: true }` +4. UI renders the coding agent message in the chat + +This is a **server-initiated request** — the coding agent runs server-side and sends status updates to the client. + +--- + +## 10. Persistence + +### 10.1 Architecture + +**Package:** `com.microsoft.copilot.eclipse.core.persistence` + +| Class | Purpose | +|-------|---------| +| `ConversationPersistenceManager` | Business logic, lifecycle, state management | +| `ConversationPersistenceService` | File I/O (XML index + JSON per-conversation) | +| `ConversationDataFactory` | Creates data objects from progress events | +| `ConversationData` | Full conversation state | +| `ConversationXmlData` | Summary for index (conversationId, title, creationDate, lastMessageDate) | +| `AbstractTurnData` | Base for turn data | +| `UserTurnData` | User message with attached files | +| `CopilotTurnData` | Copilot reply with ReplyData, ToolCallData, ThinkingBlockData, EditAgentRoundData | +| `Turn` | Protocol-level turn representation | + +### 10.2 Storage Format + +- **Index:** `conversation_index.xml` in Eclipse metadata area + - XML structure: `` + - Scoped per user (GitHub account) +- **Per-conversation:** JSON files in `conversations/` folder + - Contains full turn history with tool calls, thinking blocks, code references + - Max 256 conversations persisted + +### 10.3 Conversation Restoration + +Conversations can be restored from history by passing `conversationId` + `restoreToTurnId` in `ConversationCreateParams`. The server re-fetches the conversation state and the client replays the turns. + +--- + +## 11. Extension Points + +### 11.1 `mcpRegistration` Extension Point + +**Defined in:** `com.microsoft.copilot.eclipse.ui/plugin.xml` + +```xml + +``` + +**Interface:** `IMcpRegistrationProvider` +```java +public interface IMcpRegistrationProvider { + CompletableFuture getMcpServerConfigurations(); + // Returns JSON: {"servers":{"serverName1":{...config...}}} +} +``` + +Third-party plugins can implement this interface and register via the extension point to provide MCP server configurations to Copilot. + +### 11.2 Chat Modes + +**`BaseChatMode`** (abstract): +```java +abstract class BaseChatMode { + String id, displayName, description; + List tools; + String model; + List handOffs; + abstract boolean allowsToolConfiguration(); + abstract boolean isBuiltIn(); +} +``` + +**`CustomChatMode`** extends `BaseChatMode`: +- Loaded from `conversation/modes` API response +- `allowsToolConfiguration() = true` +- `isBuiltIn() = false` +- Can specify custom tools list, model, and hand-off targets + +### 11.3 Feature Flags (Server-Controlled) + +`FeatureFlags` class tracks server-pushed capabilities: + +| Flag | Default | Purpose | +|------|---------|---------| +| `agentModeEnabled` | `true` | Agent mode availability | +| `mcpEnabled` | `true` | MCP feature availability | +| `byokEnabled` | `true` | BYOK feature availability | +| `clientPreviewFeatureEnabled` | `true` | Preview features | +| `mcpContributionPointEnabled` | `false` | MCP extension point (policy-gated) | +| `subAgentPolicyEnabled` | `true` | Sub-agent availability | +| `customAgentPolicyEnabled` | `true` | Custom agent availability | + +Updated via `copilot/didChangeFeatureFlags` and `policy/didChange` notifications. + +--- + +## 12. Agent Binary + +### 12.1 Platform Fragments + +Five platform-specific OSGi fragment bundles ship the native `copilot-language-server` binary: + +| Bundle ID | OS | Arch | Binary | +|-----------|-----|------|--------| +| `com.microsoft.copilot.eclipse.core.agent.linux.x64` | Linux | x86_64 | `copilot-agent/copilot-language-server` | +| `com.microsoft.copilot.eclipse.core.agent.linux.aarch64` | Linux | aarch64 | `copilot-agent/copilot-language-server` | +| `com.microsoft.copilot.eclipse.core.agent.win32` | Windows | x86_64 | `copilot-agent/copilot-language-server.exe` | +| `com.microsoft.copilot.eclipse.core.agent.macosx.x64` | macOS | x86_64 | `copilot-agent/copilot-language-server` | +| `com.microsoft.copilot.eclipse.core.agent.macosx.aarch64` | macOS | aarch64 | `copilot-agent/copilot-language-server` | + +Binary is made executable via `File.setExecutable(true)` if needed. On Linux, there's a retry with 1-second delay (workaround for filesystem race condition). + +### 12.2 Fallback JS Agent + +If no binary is found, falls back to: +1. Locate Node.js from Wild Web Developer's `NodeJSManager` +2. Find `language-server.js` from `copilot-agent/dist` bundle entry +3. Run: `node [--inspect] language-server.js --stdio` + +Env var `COPILOT_LS_JS_PATH` can override the JS path. + +--- + +## 13. Integration Surface (Constraint Ecosystem Hooks) + +### Where constraints can plug in: + +1. **Tool confirmation (`AgentToolService.onToolConfirmation`)** — All tool executions requiring confirmation flow through here. This is the gate for constraint enforcement before tool execution. + +2. **Tool invocation (`AgentToolService.onToolInvocation`)** — Every tool call from the server passes through here. Pre/post conditions can be added. + +3. **MCP tool registration/update (`CopilotLanguageServer`)** — `registerTools()`, `updateMcpToolsStatus()`, and `updateConversationToolsStatus()` control which tools are available. + +4. **Feature flags / Policy (`FeatureFlags`, `policy/didChange`)** — Enterprise policies already gate features. Additional constraints can be enforced here. + +5. **Chat mode tool configuration (`BaseChatMode.tools`)** — Each mode has a tool allowlist. Constraints can filter tools per mode. + +6. **MCP extension point (`mcpRegistration`)** — Third-party MCP servers enter through this extension point. Validation/filtering can be applied. + +7. **File operations (`FileToolService`)** — All file create/edit operations are tracked. Pre-commit hooks can validate changes. + +8. **Terminal execution (`IRunInTerminalTool`)** — Command execution can be intercepted. + +9. **Debugger operations (`JavaDebuggerToolAdapter`)** — All 15 debug actions flow through `executeAction()` switch. + +10. **Conversation persistence (`ConversationPersistenceManager`)** — Conversation storage/retrieval can be augmented. + +11. **`CopilotLanguageClient` notifications** — All server→client notifications can be intercepted via `IEventBroker` subscribers. + +--- + +## 14. Low-Level Metal (Wire Protocol) + +### 14.1 Transport + +- **JSON-RPC 2.0** over **stdio** (the only transport) +- Implemented via LSP4J's `LanguageServerWrapper` which manages the process lifecycle +- All messages are UTF-8 encoded + +### 14.2 Request/Response Pattern + +Requests use LSP4J's `@JsonRequest` annotation → method name derived from Java method name unless specified (e.g., `@JsonRequest("conversation/create")`). + +Responses return `CompletableFuture` — LSP4J handles the JSON-RPC correlation. + +### 14.3 Key Protocol Messages + +**Client → Server (requests):** +``` +conversation/create → ChatCreateResult +conversation/turn → ChatTurnResult +conversation/templates → ConversationTemplate[] +conversation/modes → ConversationMode[] +conversation/registerTools → LanguageModelToolInformation[] +copilot/models → CopilotModel[] +copilot/byok/* → Byok responses +mcp/registry/* → MCP registry responses +textDocument/copilotInlineEdit → NextEditSuggestionsResult +git/commitGenerate → GenerateCommitMessageResult +``` + +**Server → Client (requests):** +``` +conversation/context → Object[] +conversation/invokeClientTool → LanguageModelToolResult[] +conversation/invokeClientToolConfirmation → Object[] +copilot/watchedFiles → GetWatchedFilesResponse +copilot/dynamicOAuth → Map +copilot/codingAgentMessage → CodingAgentMessageResult +workspace/readFile → ReadFileResult +workspace/readDirectory → ReadDirectoryResult +workspace/findFiles → FindFilesResult +workspace/findTextInFiles → FindTextInFilesResult +``` + +**Server → Client (notifications):** +``` +copilot/mcpTools +copilot/mcpRuntimeLogs +$/copilot/rateLimitWarning +copilot/quotaWarning +copilot/didChangeFeatureFlags +policy/didChange +copilot/customSkill/didChange +copilot/customPrompt/didChange +$/progress (with ChatProgressValue) +``` + +### 14.4 ConversationCreateParams Wire Format + +```json +{ + "workDoneToken": "string", + "turns": [{ + "prompt": "string | ChatCompletionContentPart[]", + "agentSlug": "string?", + "response": null + }], + "capabilities": { "skills": ["currentEditor"] }, + "computeSuggestions": true, + "textDocument": { "uri": "file:///..." }, + "selection": { "start": {...}, "end": {...} }, + "references": [...], + "source": "panel", + "workspaceFolder": "file:///...", + "workspaceFolders": [...], + "model": "gpt-4", + "modelProviderName": "openai", + "modelInfo": { "id": "...", "providerName": "...", "reasoningEffort": "medium" }, + "chatMode": "agent", + "customChatModeId": "...", + "needToolCallConfirmation": true, + "todoList": [...], + "conversationId": "uuid?", + "restoreToTurnId": "uuid?" +} +``` + +### 14.5 Tool Registration Wire Format + +```json +{ + "tools": [{ + "name": "create_file", + "description": "...", + "inputSchema": { + "type": "object", + "properties": { ... }, + "required": [...] + }, + "confirmationMessages": { + "title": "...", + "message": "..." + } + }] +} +``` + +### 14.6 Tool Invocation Wire Format + +**Server → Client request:** +```json +{ + "conversationId": "uuid", + "turnId": "uuid", + "name": "edit_file", + "input": { "file": "/path/to/File.java", "content": "..." } +} +``` + +**Client → Server response:** +```json +[{ + "content": ["result text"], + "status": "success | error | cancelled" +}] +``` + +--- + +## Summary + +This is a sophisticated LSP client that wraps GitHub's Copilot Language Server. The architecture is clean: + +- **LSP4E** handles the JSON-RPC transport and document synchronization +- **CopilotLanguageServer** / **CopilotLanguageClient** define the full protocol surface +- **CopilotLanguageServerConnection** provides the high-level API +- **AgentToolService** manages the tool lifecycle (registration, invocation, confirmation) +- **BaseTool** is the SPI for all tools — new tools just extend it +- **MCP** extends the tool surface to external servers +- **Persistence** uses XML index + JSON files, scoped per GitHub user +- **Feature flags** and **enterprise policies** gate capabilities server-side + +The main extension points for constraint enforcement are the tool confirmation flow, the MCP registration extension point, and the feature flag system. diff --git a/CONSTRAINT-EDITOR-DESIGN.md b/CONSTRAINT-EDITOR-DESIGN.md new file mode 100644 index 00000000..18cc90f2 --- /dev/null +++ b/CONSTRAINT-EDITOR-DESIGN.md @@ -0,0 +1,757 @@ +# CONSTRAINT-EDITOR-DESIGN.md + +## The Bathymetric Compiler — An IDE That Feels the Constraint Surface of Code + +> "When you write code in 12 languages, you aren't precalculating 12 scenarios. You are creating a bathymetric chart of the landscape of mathematical possibilities on the metal." + +--- + +## 0. Preamble: Why This Exists + +The copilot-for-eclipse plugin is a completion engine. It sends positions to a language server, receives suggestions, and renders them as ghost text or inline edits. It does not *understand* the code — it *predicts* it. + +This design asks: what if the editing surface itself understood the **constraint geometry** of the code being written? Not as a tool Copilot calls, but as a property of the editor — as fundamental as syntax highlighting. + +The five substrate primitives from constraint theory (`lattice_snap`, `funnel`, `is_laman`, `consensus`, `holonomy`) are not abstractions. They are real forces acting on code at every keystroke. The editor should make them visible, audible, and navigable — like a bathymetric chart showing the depth of water beneath a ship. + +--- + +## 1. Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ Eclipse IDE Surface │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ +│ │ Code Mining │ │ Ruler Column │ │ Annotation Model │ │ +│ │ (inline text)│ │ (gutter icons│ │ (underlines, highlights) │ │ +│ │ │ │ depth marks)│ │ │ │ +│ └──────┬───────┘ └──────┬───────┘ └────────────┬─────────────┘ │ +│ │ │ │ │ +│ ┌──────┴─────────────────┴────────────────────────┴─────────────┐ │ +│ │ CONSTRAINT SURFACE LAYER │ │ +│ │ │ │ +│ │ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐ │ │ +│ │ │ Constraint │ │ Terrain │ │ Flow Monitor │ │ │ +│ │ │ Analyzer │ │ Classifier │ │ (developer state) │ │ │ +│ │ │ Engine │ │ (language → │ │ │ │ │ +│ │ │ │ │ terrain) │ │ │ │ │ +│ │ └──────┬──────┘ └──────┬──────┘ └──────────┬───────────┘ │ │ +│ │ │ │ │ │ │ +│ │ ┌──────┴────────────────┴─────────────────────┴────────────┐ │ │ +│ │ │ COMPLETION INTERCEPTOR │ │ │ +│ │ │ (wraps CompletionProvider, reorders/reroutes) │ │ │ +│ │ └──────────────────────────┬───────────────────────────────┘ │ │ +│ └─────────────────────────────┼────────────────────────────────┘ │ +│ │ │ +│ ┌─────────────────────────────┴────────────────────────────────┐ │ +│ │ COPILOT LANGUAGE SERVER (existing) │ │ +│ │ CompletionProvider → CopilotLanguageServerConnection │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +The design adds two layers between the existing completion infrastructure and the visual surface: + +1. **Constraint Surface Layer** — computes constraint properties of the code in real-time +2. **Completion Interceptor** — wraps the existing `CompletionProvider` to reorder, filter, or augment suggestions based on constraint state and developer flow + +--- + +## 2. Constraint Annotations — The Five Primitives + +Each substrate primitive maps to a measurable property of code. These are not metaphors — they are formal analogies where the same mathematical structure appears in both domains. + +### 2.1 `lattice_snap` → Type Safety + +**Formal analogy:** A lattice is a partially ordered set where every pair has a unique supremum (join) and infimum (meet). In type theory, the subtype relation forms a lattice. "Snapping" means the code resolves to the nearest lattice point — the most specific valid type. + +**Code property:** How tightly do expressions resolve to their most specific valid type? Loose typing (dynamic casts, `Object` everywhere) = far from lattice points. Tight typing (generics, pattern matching) = snapping to lattice. + +**Computation:** +- Parse the AST (Eclipse JDT already has full type binding information) +- For each expression node, compute the *type specificity ratio*: `specificity = depth_in_type_hierarchy(declared_type) / depth_in_type_hierarchy(actual_type)` +- A value near 1.0 = tight lattice snap. A value near 0.0 = floating free. + +**Visualization:** +- Code mining annotation: `[snap: 0.92]` next to type declarations +- Green when specificity > 0.8, yellow 0.5–0.8, red < 0.5 +- Annotation underline on expressions with poor snap (dotted yellow = loose, solid green = tight) + +**Eclipse integration:** +- Uses `org.eclipse.jdt.core.dom.ASTVisitor` to walk type bindings +- Annotation type: `com.bathymetric.constraint.snap` registered via `org.eclipse.ui.editors.annotationTypes` +- Marker specification via `org.eclipse.ui.editors.markerAnnotationSpecification` + +### 2.2 `funnel` → Code Navigation Gravity + +**Formal analogy:** A funnel is a convergence structure where nearby starting points all flow to the same attractor. In code, certain symbols (core interfaces, base classes, entry points) act as attractors — most navigation paths lead toward them. + +**Code property:** Which symbols in this file act as gravitational attractors? How strongly does the call/reference graph funnel toward them? + +**Computation:** +- Build a local reference graph using Eclipse's `IIndex` and `ICallHierarchy` +- For each symbol, compute fan-in ratio: `gravity = inbound_references / (inbound + outbound_references)` +- Symbols with high gravity are funnels — they concentrate the navigation flow + +**Visualization:** +- Ruler column markers: `●` (high gravity), `○` (medium), `·` (low) in the gutter +- Hovering shows: `[funnel: 0.78 — 47 inbound refs converge here]` +- When navigating, highlight the "gravitational well" — the nearest high-gravity symbol + +**Eclipse integration:** +- Uses `org.eclipse.jdt.ui.actions.OpenCallHierarchyAction` / `CallHierarchyViewPart` APIs +- Ruler column via `org.eclipse.ui.workbench.texteditor.rulerColumns` (same pattern as existing `RulerColumn` in NES) + +### 2.3 `is_laman` → Structural Rigidity + +**Formal analogy:** A Laman graph is a minimally rigid structure — remove any edge and it becomes flexible. In dependency graphs, a Laman structure means every dependency is load-bearing; none are redundant. + +**Code property:** Is the dependency graph of this module rigid (every import matters) or flexible (redundant connections)? A rigid dependency graph fails predictably when a dependency is removed. A flexible one degrades gracefully. + +**Computation:** +- Build the import/dependency graph for the current file +- Compute the Laman condition: for `n` nodes, a graph is minimally rigid if it has exactly `2n - 3` edges and every subgraph of `k` nodes has at most `2k - 3` edges +- Rigidity ratio: `actual_edges / (2n - 3)` where n = number of connected dependencies +- Ratio = 1.0 → minimally rigid. > 1.0 → over-constrained (fragile). < 1.0 → under-constrained (floppy). + +**Visualization:** +- Code mining at file header: `[rigidity: 1.12 — over-constrained, 3 redundant deps]` +- Color-coded: green (0.9–1.1), yellow (1.1–1.5 or 0.6–0.9), red (> 1.5 or < 0.6) +- Quick-fix: "Remove redundant dependencies" for over-constrained graphs + +**Eclipse integration:** +- Parse imports using JDT's `ICompilationUnit.getImports()` +- Build graph with `org.eclipse.jdt.core.search.IJavaSearchConstants.REFERENCES` +- Contributes quick-fix via `org.eclipse.jdt.ui.quickFixProcessors` + +### 2.4 `consensus` → Linter/Analyzer Agreement + +**Formal analogy:** Consensus in distributed systems means multiple independent agents reach the same conclusion. For code quality, if multiple independent analyzers (compiler, linter, type checker, static analysis) all agree a region is fine, that's high consensus. + +**Code property:** Do the available analyzers agree on the quality of this code region? Disagreement flags areas that need attention. + +**Computation:** +- Eclipse already aggregates: compiler warnings (`IMarker`), JDT warnings, checkstyle, PMD, SpotBugs +- For each code region: `consensus = 1.0 - (disagreeing_analyzers / total_analyzers)` +- An analyzer "disagrees" if it flags a problem that no other analyzer flags (unique finding = low consensus) + +**Visualization:** +- Code mining: `[consensus: 0.4 — 2 unique findings]` +- Annotations: underline regions where consensus is low with a distinctive pattern (wavy purple) +- Marker aggregation in Problems view: group by consensus level + +**Eclipse integration:** +- Reads `IMarker` from `IResource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE)` +- Aggregates across builder participants and `org.eclipse.core.resources.incrementalProjectBuilder` extensions + +### 2.5 `holonomy` → Import Cycle Detection + +**Formal analogy:** Holonomy measures how much a vector rotates when parallel-transported around a closed loop. In code, import cycles are closed loops — importing A→B→C→A means the dependency vector returns to its origin having "rotated" through the package structure. + +**Code property:** Are there cycles in the import/dependency graph? How "tight" are they (how many hops)? + +**Computation:** +- Build the package-level dependency graph using JDT's `IPackageFragment` dependencies +- Detect cycles with DFS; for each cycle compute: `holonomy = cycle_length / total_packages` +- Smaller cycles = tighter holonomy = more problematic + +**Visualization:** +- Code mining at package declaration: `[holonomy: cycle detected — A→B→C→A (3 hops)]` +- Annotation: red underline on import statements that participate in cycles +- Quick-fix: "Break cycle by extracting interface" + +**Eclipse integration:** +- Uses `org.eclipse.jdt.core.IPackageFragment` and cross-reference search +- Cycle detection runs as an incremental builder via `org.eclipse.core.resources.incrementalProjectBuilder` + +--- + +## 3. Bathymetric Code Mining — The Depth Sounder + +### 3.1 Concept + +Eclipse's code mining API (`org.eclipse.jface.text.codemining`) renders inline annotations in the editor text area. The copilot-for-eclipse plugin already uses this for ghost text (see `GhostTextProvider`, `LineEndGhostText`, `BlockGhostText`). We extend this to show constraint depth values. + +The constraint depth is a composite metric: + +``` +depth = (w_snap * lattice_snap + w_funnel * funnel + w_rigidity * is_laman + + w_consensus * consensus + w_holonomy * (1 - holonomy_violation)) + / sum(weights) +``` + +Default weights: all equal (0.2). The depth value ranges from 0.0 (chaos) to 1.0 (perfect constraint satisfaction). + +### 3.2 Implementation + +```java +package com.bathymetric.editor.mining; + +/** + * Code mining provider that shows constraint depth inline. + * Registered via org.eclipse.ui.workbench.texteditor.codeMiningProviders. + */ +public class ConstraintDepthMiningProvider extends AbstractCodeMiningProvider { + + private ConstraintAnalyzerEngine engine; + + @Override + public CompletableFuture> provideCodeMinings( + ITextViewer viewer, IProgressMonitor monitor) { + + return CompletableFuture.supplyAsync(() -> { + IDocument document = viewer.getDocument(); + IFile file = resolveFile(viewer); + if (file == null) return Collections.emptyList(); + + // Compute constraint depth for each method/class declaration + ConstraintSurface surface = engine.analyze(file, document); + List minings = new ArrayList<>(); + + for (ConstraintRegion region : surface.getRegions()) { + // Line-header mining: [depth: 0.87 ●] + minings.add(new ConstraintDepthCodeMining( + region.getStartLine(), + document, + this, + region.getDepth(), + region.getDominantPrimitive() + )); + } + return minings; + }); + } +} +``` + +### 3.3 Visual Design + +``` + 24 │ [depth: 0.92 ●] public class PaymentProcessor { + 25 │ [depth: 0.87 ●] public void processOrder(Order order) { + 26 │ // lattice_snap detects: order param is typed, good + 27 │ PaymentResult result = validate(order); // [snap: 0.95] + 28 │ if (result.isValid()) { + 29 │ charge(result.getAmount()); // [consensus: 0.4 ⚠] ← unique PMD finding + 30 │ } + 31 │ } + 32 │ } +``` + +**Color mapping:** +- `depth ≥ 0.8`: Green `●` — constraint surface is optimal +- `0.5 ≤ depth < 0.8`: Yellow `◐` — acceptable, some tension +- `depth < 0.5`: Red `○` — constraint violations, needs attention + +### 3.4 Registration (plugin.xml) + +```xml + + + + + + + + + + + + + + + + + +``` + +--- + +## 4. The Terrain Map — Language as Landscape + +### 4.1 Concept + +Different programming languages have fundamentally different constraint surfaces. Writing Java is like navigating classical counterpoint — strict rules, high rigidity, every voice must resolve correctly. Writing Python is modal jazz — flexible scales, many valid paths through the changes. The terrain you're on determines how the depth sounder should be calibrated. + +### 4.2 Terrain Classifications + +| Language | Musical Analogy | Terrain | Rigidity | Snap Weight | Funnel Weight | Holonomy Concern | +|----------|----------------|---------|----------|-------------|---------------|------------------| +| Java | Classical Counterpoint | Mountains | High | 0.35 | 0.25 | 0.15 | +| Python | Modal Jazz | Rolling Hills | Low | 0.15 | 0.20 | 0.10 | +| Rust | Bebop | Cliffs/Dense | Very High | 0.30 | 0.30 | 0.25 | +| C | Delta Blues | Desert/Flat | Medium | 0.20 | 0.15 | 0.15 | +| JavaScript | Free Improvisation | Ocean | Very Low | 0.10 | 0.10 | 0.05 | +| TypeScript | Cool Jazz | Foothills | Medium-High | 0.25 | 0.20 | 0.15 | +| Go | Minimalism | Plains | High | 0.25 | 0.25 | 0.20 | +| Haskell | Serialism | Crystal Lattice | Very High | 0.40 | 0.20 | 0.30 | + +### 4.3 Terrain-Aware Depth Calibration + +The terrain classifier adjusts the constraint weights based on file type: + +```java +package com.bathymetric.editor.terrain; + +public class TerrainClassifier { + + private static final Map TERRAINS = Map.of( + "java", new TerrainProfile("classical_counterpoint", 0.35, 0.25, 0.20, 0.10, 0.10), + "python", new TerrainProfile("modal_jazz", 0.15, 0.20, 0.10, 0.15, 0.10), + "rust", new TerrainProfile("bebop", 0.30, 0.30, 0.25, 0.10, 0.20), + "c", new TerrainProfile("delta_blues", 0.20, 0.15, 0.15, 0.15, 0.10), + "javascript", new TerrainProfile("free_improvisation", 0.10, 0.10, 0.05, 0.20, 0.05), + "typescript", new TerrainProfile("cool_jazz", 0.25, 0.20, 0.15, 0.15, 0.10), + "go", new TerrainProfile("minimalism", 0.25, 0.25, 0.20, 0.15, 0.15), + "haskell", new TerrainProfile("serialism", 0.40, 0.20, 0.30, 0.05, 0.25) + ); + + public TerrainProfile classify(IFile file) { + String ext = file.getFileExtension(); + return TERRAINS.getOrDefault(ext, + new TerrainProfile("default", 0.20, 0.20, 0.20, 0.20, 0.20)); + } +} + +record TerrainProfile( + String name, + double snapWeight, + double funnelWeight, + double rigidityWeight, + double consensusWeight, + double holonomyWeight +) {} +``` + +### 4.4 Terrain Display + +The terrain is shown subtly in the editor status area or as a persistent code mining at the file header: + +``` + 1 │ [terrain: classical_counterpoint — rigidity matters here] + 2 │ package com.example.payments; +``` + +The terrain classification also affects the ruler column icon style — mountain terrain uses sharper icons, ocean terrain uses wavy ones. + +--- + +## 5. The Monitor — Developer Flow State + +### 5.1 Concept + +Just as the musical Monitor tracks whether the performer is in flow or struggling, the Code Monitor watches the developer's editing pattern and adjusts the constraint surface's visibility and the completion engine's behavior accordingly. + +### 5.2 Flow State Detection + +The monitor tracks these signals from the existing editor event listeners (the plugin already listens to `KeyListener`, `MouseListener`, `ITextListener` in `BaseCompletionManager`): + +| Signal | How to Measure | Flow Indicator | +|--------|---------------|----------------| +| Typing cadence | Inter-keystroke interval via existing `KeyListener` | Regular = flowing, bursts+pauses = struggling | +| Error rate | `IMarker` creation/deletion frequency | Low = flowing, high = struggling | +| Acceptance rate | Copilot `notifyAccepted`/`notifyRejected` ratio | High = flowing, low = uncertain | +| Navigation frequency | Editor part activation events | Low = deep focus, high = searching | +| Undo frequency | `ITextListener` detecting reversed changes | Low = flowing, high = thrashing | +| Completion dismissal rate | Ghost text shown but not accepted | Low = flowing, high = noise | + +```java +package com.bathymetric.editor.monitor; + +public class FlowMonitor implements KeyListener, ITextListener { + + private Deque keystrokeTimestamps = new ArrayDeque<>(); + private AtomicInteger errorsIntroduced = new AtomicInteger(0); + private AtomicInteger completionsAccepted = new AtomicInteger(0); + private AtomicInteger completionsRejected = new AtomicInteger(0); + private AtomicInteger undoCount = new AtomicInteger(0); + + private static final int WINDOW_SECONDS = 60; + + enum FlowState { + FLOWING, // Regular cadence, low errors, high acceptance + EXPLORING, // Irregular cadence, navigation-heavy + STRUGGLING, // High errors, frequent undos, low acceptance + IDLE // No activity + } + + public FlowState computeState() { + double cadence = computeCadence(); + double errorRate = errorsIntroduced.get() / (double) WINDOW_SECONDS; + double acceptanceRate = computeAcceptanceRate(); + + if (cadence < 0.1) return FlowState.IDLE; + if (errorRate > 0.1 && undoCount.get() > 3) return FlowState.STRUGGLING; + if (cadence > 0.5 && acceptanceRate > 0.6) return FlowState.FLOWING; + return FlowState.EXPLORING; + } + + // ... measurement methods ... +} +``` + +### 5.3 Adaptive Behavior + +The flow state drives three behaviors: + +**When FLOWING:** +- Dim the constraint annotations (lower opacity) +- Don't interfere with completions — pass through directly +- The depth sounder goes quiet: minimal visual noise + +**When EXPLORING:** +- Show constraint annotations at normal intensity +- Highlight funnels (navigation attractors) to help orient +- Completions pass through, but constraint depth shown in completion proposals + +**When STRUGGLING:** +- Full constraint annotation visibility +- Reorder completion proposals to prefer ones that improve constraint satisfaction +- Show "constraint hint" popups explaining why the current code has low depth +- Increase `CompletionJob` timeout slightly (more time for better suggestions) + +**When IDLE:** +- Full constraint surface visible — this is when developers read and review +- Show the terrain map overlay +- Annotate all regions with their dominant primitive + +### 5.4 Vanishing + +The key insight from the musical Monitor: the constraint surface should **vanish** when the developer has internalized the patterns. We track internalization through: + +1. **Declining error rate over time** for a given constraint type +2. **Declining rejection rate** for constraint-aware completion suggestions +3. **Consistent high depth scores** in recent code + +When internalization is detected for a specific primitive, that primitive's annotations fade out. They return only when depth drops below a threshold — like a check-engine light that only illuminates when there's actually a problem. + +--- + +## 6. The Completion Interceptor — Wrapping Copilot + +### 6.1 Architecture + +The interceptor sits between the existing `CompletionProvider`/`CompletionListener` chain and the visual rendering layer. It does **not** replace the Copilot language server — it wraps it. + +``` +Existing flow: + Editor events → CompletionProvider → LS → completions → BaseCompletionManager → ghost text + +New flow: + Editor events → CompletionProvider → LS → completions + → CompletionInterceptor (reorder, annotate, filter) + → BaseCompletionManager → ghost text (with constraint metadata) +``` + +### 6.2 Implementation Strategy + +The interceptor implements `CompletionListener` and registers itself between the provider and the rendering manager: + +```java +package com.bathymetric.editor.interceptor; + +public class ConstraintCompletionInterceptor implements CompletionListener { + + private final List downstreamListeners; + private final ConstraintAnalyzerEngine engine; + private final FlowMonitor flowMonitor; + + @Override + public void onCompletionResolved(String uriString, List completions) { + if (completions == null || completions.isEmpty()) { + forward(uriString, completions); + return; + } + + FlowState state = flowMonitor.computeState(); + + switch (state) { + case FLOWING: + // Pass through unmodified + forward(uriString, completions); + break; + + case STRUGGLING: + // Reorder: prefer completions that improve constraint depth + List reordered = reorderForConstraints(uriString, completions); + forward(uriString, reordered); + break; + + case EXPLORING: + // Annotate with constraint metadata but don't reorder + List annotated = annotateWithDepth(uriString, completions); + forward(uriString, annotated); + break; + + default: + forward(uriString, completions); + } + } + + private List reorderForConstraints(String uri, List items) { + ConstraintSurface surface = engine.getCachedSurface(uri); + return items.stream() + .sorted(Comparator.comparingDouble(item -> + -estimateConstraintImprovement(surface, item))) + .collect(Collectors.toList()); + } + + // Forward to all downstream listeners (the rendering managers) + private void forward(String uri, List completions) { + for (CompletionListener listener : downstreamListeners) { + listener.onCompletionResolved(uri, completions); + } + } +} +``` + +### 6.3 Constraint-Aware Completion Scoring + +Each completion proposal is scored by how much it would improve the constraint surface: + +```java +private double estimateConstraintImprovement(ConstraintSurface current, CompletionItem item) { + double score = 0.0; + String text = item.getDisplayText(); + + // lattice_snap: does this completion introduce typed references? + if (introducesTypeAnnotation(text)) score += 0.15; + + // is_laman: does this reduce over-constraint (remove redundant deps)? + if (removesRedundantDependency(text, current)) score += 0.20; + + // consensus: does this fix a region flagged by multiple analyzers? + if (fixesConsensusViolation(text, current)) score += 0.25; + + // holonomy: does this break an import cycle? + if (breaksCycle(text, current)) score += 0.30; + + return score; +} +``` + +--- + +## 7. Implementation Path + +### 7.1 What Can Be a Separate Plugin vs. What Needs Fork Modifications + +| Component | Separate Plugin | Fork Modification | Reason | +|-----------|:-:|:-:|--------| +| Constraint Analyzer Engine | ✅ | | Pure computation, no Eclipse API dependency | +| Terrain Classifier | ✅ | | File extension → profile mapping | +| Flow Monitor | ✅ | | Uses standard Eclipse APIs | +| Constraint Depth Code Mining | ✅ | | Standard `codeMiningProviders` extension point | +| Constraint Annotations | ✅ | | Standard `annotationTypes` extension | +| Ruler Column (constraint gutter) | ✅ | | Standard `rulerColumns` extension point | +| **CompletionInterceptor** | | ⚠️ | Needs to be inserted into `CompletionProvider`'s listener chain | +| **Flow-aware completion timeout** | | ⚠️ | Needs access to `CompletionJob.COMPLETION_TIMEOUT_MILLIS` | +| **Ghost text constraint overlay** | | ⚠️ | Needs to extend `GhostTextProvider` or `BaseCompletionManager` | + +### 7.2 Recommended Approach: Hybrid Plugin + +Create a new Eclipse plugin `com.bathymetric.editor` that: + +1. **Depends on** `com.microsoft.copilot.eclipse.core` and `com.microsoft.copilot.eclipse.ui` (the existing Copilot plugins) +2. **Contributes** all new extension points (code mining, annotations, ruler column, builder) +3. **Hooks into** the completion system via the `CompletionListener` interface — no fork needed for the interceptor if we register as a listener + +The interceptor works because `CompletionProvider` already supports multiple `CompletionListener` instances via `CopyOnWriteArraySet`. We register our interceptor *first* so it receives completions before the rendering managers. The interceptor holds a reference to the *original* listeners, removes them from the provider, adds itself, then forwards to the originals after processing. + +```java +// In plugin activation: +CompletionProvider provider = /* get from CopilotCore */; +List original = new ArrayList<>(provider.getListeners()); +original.forEach(provider::removeCompletionListener); +ConstraintCompletionInterceptor interceptor = + new ConstraintCompletionInterceptor(original, engine, monitor); +provider.addCompletionListener(interceptor); +``` + +### 7.3 Minimal Fork Changes (for deeper integration) + +If we want flow-aware timeout adjustment or constraint metadata in ghost text rendering, we need small modifications to the fork: + +**Change 1: Expose completion timeout as configurable** +```java +// CompletionProvider.java — make timeout mutable +private static int completionTimeoutMillis = 5000; +public static void setCompletionTimeout(int millis) { + completionTimeoutMillis = millis; +} +``` + +**Change 2: Add constraint metadata to CompletionItem rendering** +```java +// BaseCompletionManager.java — add constraint depth to ghost text +protected double constraintDepth = Double.NaN; // NaN = not computed + +// In onCompletionResolved, read constraint metadata: +@Override +public void onCompletionResolved(String uriString, List completions) { + if (completions != null && !completions.isEmpty()) { + // Read constraint depth from completion item metadata + CompletionItem first = completions.get(0); + // If the interceptor annotated the item, extract depth + this.constraintDepth = first.getConstraintDepth(); + } + // ... existing rendering logic ... +} +``` + +**Change 3: Add extension point for completion post-processing** +```java +// New extension point in plugin.xml: +// org.eclipse.ui.completionPostProcessors +// Allows third-party plugins to intercept/reorder completions +// This is the cleanest way — proper Eclipse extension point pattern +``` + +### 7.4 Build and Dependency Structure + +``` +com.bathymetric.editor/ +├── META-INF/ +│ └── MANIFEST.MF # Requires-Bundle: +│ # com.microsoft.copilot.eclipse.core, +│ # com.microsoft.copilot.eclipse.ui, +│ # org.eclipse.jdt.core, +│ # org.eclipse.jface.text +├── plugin.xml # All extension points +├── src/com/bathymetric/editor/ +│ ├── analyzer/ +│ │ ├── ConstraintAnalyzerEngine.java +│ │ ├── LatticeSnapAnalyzer.java +│ │ ├── FunnelAnalyzer.java +│ │ ├── RigidityAnalyzer.java +│ │ ├── ConsensusAnalyzer.java +│ │ └── HolonomyAnalyzer.java +│ ├── terrain/ +│ │ ├── TerrainClassifier.java +│ │ └── TerrainProfile.java +│ ├── monitor/ +│ │ ├── FlowMonitor.java +│ │ └── FlowState.java +│ ├── mining/ +│ │ ├── ConstraintDepthMiningProvider.java +│ │ └── ConstraintDepthCodeMining.java +│ ├── annotation/ +│ │ ├── ConstraintAnnotationProvider.java +│ │ └── ConstraintReconciler.java +│ ├── interceptor/ +│ │ └── ConstraintCompletionInterceptor.java +│ ├── ruler/ +│ │ └── ConstraintRulerColumn.java +│ └── internal/ +│ └── BathymetricPlugin.java # Activator +└── icons/ + ├── depth-green.png + ├── depth-yellow.png + ├── depth-red.png + ├── terrain-mountain.png + ├── terrain-ocean.png + └── terrain-foothills.png +``` + +### 7.5 Performance Considerations + +The constraint analysis must not block the UI thread. Strategy: + +1. **Incremental analysis:** Only re-analyze regions that changed (use `IDocumentExtension.IIncrementalRulerColumn` pattern) +2. **Cached surfaces:** `ConstraintSurface` objects are cached per-file and invalidated on document change +3. **Background jobs:** Analysis runs in Eclipse `Job` with `INTERACTIVE` priority (same as existing `CompletionJob`) +4. **Debouncing:** Analysis is triggered with a 300ms debounce after last keystroke (not on every keystroke) +5. **Lazy primitives:** Each constraint primitive is computed independently and only when needed for display + +```java +public class ConstraintAnalyzerEngine { + + private final Map cache = new ConcurrentHashMap<>(); + private final DebouncingJob analyzerJob; + + public ConstraintSurface analyze(IFile file, IDocument document) { + String key = file.getFullPath().toString(); + return cache.computeIfAbsent(key, k -> computeSurface(file, document)); + } + + public void invalidate(IFile file) { + cache.remove(file.getFullPath().toString()); + analyzerJob.schedule(300); // debounced + } +} +``` + +--- + +## 8. Eclipse Extension Points Used + +| Extension Point | Purpose | Existing in copilot-for-eclipse? | +|----------------|---------|:-:| +| `org.eclipse.ui.workbench.texteditor.codeMiningProviders` | Inline constraint depth annotations | ✅ Yes (GhostTextProvider) | +| `org.eclipse.ui.workbench.texteditor.rulerColumns` | Constraint gutter icons | ✅ Yes (RulerColumn for NES) | +| `org.eclipse.ui.editors.annotationTypes` | Constraint violation underlines | ✅ Yes (NES change/delete) | +| `org.eclipse.ui.editors.markerAnnotationSpecification` | Visual styling for annotations | ✅ Yes | +| `org.eclipse.core.resources.incrementalProjectBuilder` | Holonomy cycle detection builder | No — new | +| `org.eclipse.jdt.ui.quickFixProcessors` | Quick fixes for constraint violations | No — new | +| `org.eclipse.ui.preferencePages` | Terrain weight configuration | No — new | +| `org.eclipse.ui.views` | Constraint surface overview view | No — new | + +--- + +## 9. The Constraint Surface View + +A dedicated Eclipse view (`org.eclipse.ui.views`) that shows the full constraint surface for the current file: + +``` +┌─ Constraint Surface ─────────────────────────────────┐ +│ File: PaymentProcessor.java │ +│ Terrain: classical_counterpoint (Java) │ +│ │ +│ Overall Depth: 0.82 ● │ +│ │ +│ ┌─ Primitives ──────────────────────────────────────┐ │ +│ │ lattice_snap ████████████████░░░░ 0.92 │ │ +│ │ funnel ██████████████░░░░░░ 0.78 │ │ +│ │ is_laman ██████████░░░░░░░░░░ 0.63 ⚠ │ │ +│ │ consensus █████████████████░░░ 0.88 │ │ +│ │ holonomy ████████████████████ 1.00 │ │ +│ └───────────────────────────────────────────────────┘ │ +│ │ +│ Violations: │ +│ ⚠ Line 29: consensus 0.4 — unique PMD finding │ +│ ⚠ Line 45: rigidity 1.3 — 2 redundant deps │ +│ │ +│ Flow State: EXPLORING │ +│ Internalized: holonomy, consensus │ +└───────────────────────────────────────────────────────┘ +``` + +--- + +## 10. Summary: What This Builds + +The Bathymetric Compiler transforms the Eclipse IDE from a surface that *displays code* into a surface that *feels the constraint geometry* of code. It does this by: + +1. **Mapping five formal constraint primitives** to measurable code properties (type safety, navigation gravity, dependency rigidity, analyzer agreement, import cycles) +2. **Rendering constraint depth inline** via Eclipse's existing code mining infrastructure — always visible, but ignorable, like a depth sounder +3. **Classifying programming languages as terrains** with different constraint weight profiles +4. **Monitoring developer flow state** to adapt visibility and completion behavior — vanishing when patterns are internalized +5. **Wrapping the Copilot completion chain** to reorder and annotate suggestions based on constraint satisfaction + +The result is an editor where the *geometry of possibility* is always perceptible. The developer navigates not just syntax, but the constraint surface — the landscape of what the code can and cannot become. + +--- + +*This document describes a design for the most ambitious extension to copilot-for-eclipse: an IDE that understands constraint surfaces. Implementation should begin with the separate plugin approach (Section 7.2) and iterate from there.* diff --git a/MULTI-MODEL-DESIGN.md b/MULTI-MODEL-DESIGN.md new file mode 100644 index 00000000..bfeac73a --- /dev/null +++ b/MULTI-MODEL-DESIGN.md @@ -0,0 +1,460 @@ +# Multi-Model Integration Design for copilot-for-eclipse + +## Overview + +This document describes how to extend the BYOK (Bring Your Own Key) system in copilot-for-eclipse to support a fleet of model providers (GLM/ZhipuAI, DeepSeek, local models) and implement intelligent model routing using constraint-terrain principles — cheaper models for simple terrain, expensive models for complex terrain. + +## Architecture Summary + +The BYOK system is an LSP-based model management layer: + +``` +Eclipse Plugin (Java) + ├── ByokModelProvider enum → defines supported providers + ├── ByokModel → model config (id, provider, capabilities, apiKey, deploymentUrl) + ├── ByokApiKey → provider credential storage + ├── ByokService (UI) → orchestrates API keys + model CRUD via LSP + ├── ByokPreferencePage → SWT UI for managing providers/models + ├── ModelService → selects active chat model from CopilotModel list + └── CopilotLanguageServerConnection → LSP calls to copilot/byok/* endpoints + ↓ + Copilot Language Server (Node.js) — handles actual API routing +``` + +Key insight: **The Eclipse plugin is a thin client.** All actual model API calls go through the Copilot Language Server. The plugin sends `ByokModel` configurations via LSP (`copilot/byok/saveModel`, `copilot/byok/listModels`, etc.), and the language server handles provider-specific API translation. + +--- + +## Part 1: Adding New Providers + +### File: `ByokModelProvider.java` + +**Path:** `com.microsoft.copilot.eclipse.core/src/.../lsp/protocol/byok/ByokModelProvider.java` + +Add new enum values: + +```java +public enum ByokModelProvider { + AZURE("Azure"), + OPENAI("OpenAI"), + GEMINI("Gemini"), + GROQ("Groq"), + OPENROUTER("OpenRouter"), + ANTHROPIC("Anthropic"), + // --- New providers --- + ZHIPUAI("ZhipuAI"), // GLM models (glm-4, glm-4-flash, etc.) + DEEPSEEK("DeepSeek"), // DeepSeek models (deepseek-chat, deepseek-coder) + LOCAL("Local"); // Local/self-hosted models (Ollama, vLLM, etc.) + + // ... existing code unchanged ... +} +``` + +### Supporting Files (no changes needed) + +The following files are **provider-agnostic** and need no modification: +- `ByokModel.java` — uses `providerName` (String), not the enum directly +- `ByokApiKey.java` — uses `providerName` (String) +- `ByokModelCapabilities.java` — generic (name, maxTokens, toolCalling, vision) +- `ByokStatusResponse.java`, `ByokListModelResponse.java`, `ByokListApiKeyResponse.java`, `ByokListModelParams.java` + +### UI Files That Auto-Adapt + +- **`ByokPreferencePage.java`** — iterates `ByokModelProvider.values()` for the tree, so new enum values appear automatically as provider nodes +- **`ByokService.java`** — fully provider-agnostic; routes by `providerName` string +- **`ModelPickerGroupsBuilder.java`** — separates BYOK models into a "Custom Models" group via `providerName != null` check + +### Language Server Side + +The Copilot Language Server (Node.js, not in this repo) must be extended to understand the new provider names. This is where the actual HTTP API integration lives: +- `ZhipuAI` → `https://open.bigmodel.cn/api/paas/v4/chat/completions` +- `DeepSeek` → `https://api.deepseek.com/chat/completions` +- `Local` → configurable endpoint (default `http://localhost:11434/v1/chat/completions` for Ollama) + +All three use OpenAI-compatible APIs, so the language server's OpenAI adapter can likely be reused with URL overrides. + +--- + +## Part 2: Model Routing Design + +### The Bathymetric Principle + +**Simpler terrain → cheaper model. Complex terrain → expensive model.** + +Terrain is classified by constraint complexity: + +| Terrain Level | Constraint Signature | Model Tier | Example Models | +|---|---|---|---| +| **Shallow** | Single-line completion, no context | Budget | GLM-4-Flash, DeepSeek-Lite | +| **Mid** | Multi-line completion, file context | Standard | DeepSeek-V3, GLM-4 | +| **Deep** | Chat with tool calling, reasoning | Premium | GPT-4o, Claude 3.5, GLM-4-Plus | +| **Abyssal** | Agent mode, multi-file, debugging | Flagship | Claude 3.5 Sonnet, o3, GLM-5 | + +### Configuration Format + +Add a new preference/configuration file: `model-routing.json` + +```json +{ + "routing": { + "completion": { + "default": "deepseek-chat", + "shallow": { "provider": "ZhipuAI", "model": "glm-4-flash" }, + "mid": { "provider": "DeepSeek", "model": "deepseek-chat" }, + "deep": { "provider": "OpenRouter", "model": "anthropic/claude-3.5-sonnet" } + }, + "chat": { + "default": "deepseek-chat", + "shallow": { "provider": "DeepSeek", "model": "deepseek-chat" }, + "mid": { "provider": "ZhipuAI", "model": "glm-4-plus" }, + "deep": { "provider": "Anthropic", "model": "claude-3.5-sonnet" } + }, + "agent": { + "default": "claude-3.5-sonnet", + "deep": { "provider": "Anthropic", "model": "claude-3.5-sonnet" } + } + }, + "fallback": { + "provider": "OpenRouter", + "model": "meta-llama/llama-3-70b" + }, + "costLimits": { + "dailyBudgetUsd": 1.00, + "perRequestMaxUsd": 0.05 + } +} +``` + +### Terrain Classification Logic + +Create a new class: `ConstraintTerrainAnalyzer.java` + +**Path:** `com.microsoft.copilot.eclipse.core/src/.../lsp/protocol/byok/ConstraintTerrainAnalyzer.java` + +```java +package com.microsoft.copilot.eclipse.core.lsp.protocol.byok; + +/** + * Analyzes the constraint terrain of a request to determine model routing. + * Bathymetric principle: simpler terrain = cheaper model. + */ +public class ConstraintTerrainAnalyzer { + + public enum TerrainDepth { + SHALLOW, // Single token/line prediction, no cross-file context + MID, // Multi-line with file context, standard completions + DEEP, // Chat with tool calling, reasoning, code generation + ABYSSAL // Agent mode: multi-file, debugging, complex workflows + } + + public static TerrainDepth classifyCompletion( + int prefixLength, + int suffixLength, + String languageId, + boolean hasImports, + boolean hasTypeContext) { + // Shallow: single line, no context needed + if (prefixLength < 200 && suffixLength < 50) return TerrainDepth.SHALLOW; + // Mid: multi-line, needs file understanding + if (prefixLength < 2000) return TerrainDepth.MID; + // Deep: large context, complex completion + return TerrainDepth.DEEP; + } + + public static TerrainDepth classifyChat( + int turnCount, + boolean hasToolCalls, + boolean hasFileReferences, + boolean isAgentMode, + String chatMode) { + if (isAgentMode) return TerrainDepth.ABYSSAL; + if (hasToolCalls || "agent".equals(chatMode)) return TerrainDepth.DEEP; + if (turnCount > 3 || hasFileReferences) return TerrainDepth.MID; + return TerrainDepth.SHALLOW; + } +} +``` + +### Model Router + +Create: `ModelRouter.java` + +**Path:** `com.microsoft.copilot.eclipse.core/src/.../lsp/protocol/byok/ModelRouter.java` + +```java +package com.microsoft.copilot.eclipse.core.lsp.protocol.byok; + +import java.util.Map; +import java.util.Optional; + +/** + * Routes requests to the appropriate BYOK model based on constraint terrain. + * Bathymetric principle: simpler terrain = cheaper model, complex terrain = expensive model. + */ +public class ModelRouter { + + private final ModelRoutingConfig config; + private final Map availableModels; // keyed by providerName_modelId + + public ByokModel routeCompletion( + int prefixLength, int suffixLength, + String languageId, boolean hasImports, boolean hasTypeContext) { + + var depth = ConstraintTerrainAnalyzer.classifyCompletion( + prefixLength, suffixLength, languageId, hasImports, hasTypeContext); + return resolveModel(config.getCompletionRoute(depth), depth); + } + + public ByokModel routeChat( + int turnCount, boolean hasToolCalls, + boolean hasFileReferences, boolean isAgentMode, String chatMode) { + + var depth = ConstraintTerrainAnalyzer.classifyChat( + turnCount, hasToolCalls, hasFileReferences, isAgentMode, chatMode); + return resolveModel(config.getChatRoute(depth), depth); + } + + private ByokModel resolveModel(ModelRoute route, TerrainDepth depth) { + // Try the configured model first + Optional model = findRegistered(route.getProvider(), route.getModel()); + if (model.isPresent()) return model.get(); + + // Fallback: try default for the operation type + // Fallback: try any registered model at this terrain depth + // Final fallback: the config's fallback model + return findRegistered(config.getFallback().getProvider(), config.getFallback().getModel()) + .orElseThrow(() -> new IllegalStateException("No available model for terrain: " + depth)); + } + + private Optional findRegistered(String provider, String modelId) { + String key = provider + "_" + modelId; + ByokModel m = availableModels.get(key); + return (m != null && m.isRegistered()) ? Optional.of(m) : Optional.empty(); + } +} +``` + +--- + +## Part 3: Integration Points + +### Where to Wire Model Routing + +#### 3a. Chat Model Selection — `ModelService.java` + +**Path:** `com.microsoft.copilot.eclipse.ui/src/.../chat/services/ModelService.java` + +Currently, `ModelService` manages an `activeModelObservable` that the user picks from the dropdown. To add automatic routing: + +```java +// In ModelService, add: +private ModelRouter modelRouter; // initialized with routing config + available BYOK models + +/** + * For chat: use the user-selected model (existing behavior). + * For auto-routed scenarios (inline completion), use the router. + */ +public CopilotModel getRoutedModel(String operationType, TerrainDepth depth) { + if ("chat".equals(operationType)) { + return getActiveModel(); // User's explicit choice for chat + } + ByokModel routed = modelRouter.routeForTerrain(operationType, depth); + return convertToCopilotModel(routed); +} +``` + +#### 3b. Inline Completion — `CopilotLanguageServerConnection.java` + +**Path:** `com.microsoft.copilot.eclipse.core/src/.../lsp/CopilotLanguageServerConnection.java` + +The inline completion flow sends requests through the LSP. To route via terrain: + +1. Before sending `textDocument/inlineCompletion`, classify the terrain using `ConstraintTerrainAnalyzer.classifyCompletion()` +2. Select the appropriate BYOK model +3. Include the model selection in the LSP request parameters + +#### 3c. Chat Requests — `ChatView.java` + +**Path:** `com.microsoft.copilot.eclipse.ui/src/.../chat/ChatView.java` + +Currently uses `chatServiceManager.getModelService().getActiveModel()`. For agent mode with constraint terrain: + +```java +// Before sending chat request, optionally override the model: +if (isAgentMode) { + CopilotModel routed = modelService.getRoutedModel("agent", TerrainDepth.ABYSSAL); + // Use routed model instead of activeModel +} +``` + +--- + +## Part 4: Files to Modify (Summary) + +### Must Modify + +| File | Change | +|---|---| +| `ByokModelProvider.java` | Add `ZHIPUAI`, `DEEPSEEK`, `LOCAL` enum values | + +### New Files to Create + +| File | Purpose | +|---|---| +| `ConstraintTerrainAnalyzer.java` | Classifies request complexity into terrain depth levels | +| `ModelRouter.java` | Routes requests to models based on terrain + config | +| `ModelRoutingConfig.java` | Loads/represents `model-routing.json` configuration | +| `model-routing.json` | User-editable routing configuration (in plugin state area) | + +### Optional Modifications + +| File | Change | Why | +|---|---|---| +| `ModelService.java` | Add `getRoutedModel()` method | Auto-routing for non-chat operations | +| `ByokPreferencePage.java` | Add routing config section | Let users configure terrain→model mapping | +| `ByokService.java` | Expose `ModelRouter` instance | Central access point for routing | +| `AddApiKeyDialog.java` | Handle new provider URL patterns | Provider-specific hints | +| `AddByokModelDialog.java` | Provider-specific model ID suggestions | Better UX for new providers | + +### No Changes Needed + +| File | Reason | +|---|---| +| `ByokModel.java` | Already provider-agnostic (String-based) | +| `ByokApiKey.java` | Already provider-agnostic | +| `ByokModelCapabilities.java` | Generic, no provider specifics | +| `CopilotCapabilities.java` | Server capabilities, not model-related | +| `InitializationOptions.java` | LSP init, not model-related | +| `FeatureFlags.java` | Feature toggles, no provider-specific logic | +| `ModelPickerGroupsBuilder.java` | Auto-adapts via `ByokModelProvider.values()` iteration | +| `CopilotLanguageServer.java` | LSP protocol interface, provider-agnostic endpoints | + +--- + +## Part 5: OpenRouter as Universal Gateway + +OpenRouter is already supported and serves as our **universal fallback gateway**. It provides API access to: + +- GLM-4 models (ZhipuAI) +- DeepSeek models +- Claude, GPT-4, Llama, Mistral, etc. + +This means even without direct provider integrations, we can route to any model through OpenRouter. The dedicated `ZHIPUAI` and `DEEPSEEK` enum values are for users who have their own API keys and want direct, lower-latency, lower-cost access. + +**Routing priority:** +1. Direct provider API key (if configured) — lowest cost +2. OpenRouter (if configured) — universal access +3. GitHub Copilot default models — built-in fallback + +--- + +## Part 6: Constraint-Substrate Lattice Snap for Completion + +The "constraint-substrate lattice snap" concept: when the completion engine identifies a constraint (type signature, method signature, known pattern), it "snaps" to the simplest model that can satisfy that constraint. + +**Implementation:** + +```java +public class CompletionConstraintAnalyzer { + + /** + * Snap to the cheapest model that can handle this completion's constraints. + */ + public static ByokModel snapToModel( + CompletionContext ctx, + Map modelLattice) { + + // Constraint primitives: + // 1. Type constraint: return type, parameter types known + // 2. Pattern constraint: implements known pattern (builder, factory, etc.) + // 3. Context constraint: imports, file structure available + + int constraintCount = 0; + if (ctx.hasTypeConstraint()) constraintCount++; + if (ctx.hasPatternConstraint()) constraintCount++; + if (ctx.hasContextConstraint()) constraintCount++; + + // More constraints = tighter lattice = cheaper model can snap + // Fewer constraints = looser lattice = need more capable model + + if (constraintCount >= 2) return modelLattice.get(TerrainDepth.SHALLOW); + if (constraintCount == 1) return modelLattice.get(TerrainDepth.MID); + return modelLattice.get(TerrainDepth.DEEP); + } +} +``` + +**Counter-intuitive insight:** More constraints → simpler model. When we know the type signature and the pattern, the model just needs to fill in boilerplate. A cheap model can do that. When we have *no* constraints, we need a smart model to *infer* intent. + +--- + +## Part 7: Monitor Integration (Chat Flow Detection) + +For chat, the **Monitor** system detects conversation flow patterns and adapts model selection: + +```java +public class ChatFlowMonitor { + + public enum FlowState { + EXPLORATORY, // User asking questions → cheap model + IMPLEMENTING, // Writing code → standard model + DEBUGGING, // Troubleshooting → capable model + REFACTORING // Complex multi-step → flagship model + } + + /** + * Detect flow state from conversation turns. + */ + public static FlowState detectFlow(List turns) { + Turn lastTurn = turns.get(turns.size() - 1); + + if (lastTurn.containsToolCalls()) return FlowState.DEBUGGING; + if (lastTurn.referencesMultipleFiles()) return FlowState.REFACTORING; + if (lastTurn.containsCodeBlocks()) return FlowState.IMPLEMENTING; + return FlowState.EXPLORATORY; + } + + /** + * Map flow state to model terrain → model selection. + */ + public static ByokModel selectModelForFlow( + FlowState flow, + ModelRouter router) { + return switch (flow) { + case EXPLORATORY -> router.routeForTerrain(TerrainDepth.SHALLOW); + case IMPLEMENTING -> router.routeForTerrain(TerrainDepth.MID); + case DEBUGGING -> router.routeForTerrain(TerrainDepth.DEEP); + case REFACTORING -> router.routeForTerrain(TerrainDepth.ABYSSAL); + }; + } +} +``` + +--- + +## Implementation Order + +1. **Phase 1 — Provider Extension** (Low effort, high impact) + - Add `ZHIPUAI`, `DEEPSEEK`, `LOCAL` to `ByokModelProvider` + - Test that the preference page shows them + - Verify API key management works + +2. **Phase 2 — Routing Config** (Medium effort) + - Create `ModelRoutingConfig` + `model-routing.json` loader + - Create `ModelRouter` with terrain-based selection + - Add routing config to preference page + +3. **Phase 3 — Terrain Classification** (Medium effort) + - Implement `ConstraintTerrainAnalyzer` + - Wire into completion flow + - Measure accuracy of terrain classification + +4. **Phase 4 — Constraint-Substrate Snap** (Advanced) + - Implement `CompletionConstraintAnalyzer` + - Build the lattice of constraint primitives + - Test snap accuracy across terrains + +5. **Phase 5 — Chat Flow Monitor** (Advanced) + - Implement `ChatFlowMonitor` + - Wire into chat request flow + - Adaptive model switching mid-conversation From de40bfeb9cd8a586409c085d6d8422f03da62a34 Mon Sep 17 00:00:00 2001 From: OpenClaw Date: Fri, 22 May 2026 23:59:47 -0800 Subject: [PATCH 2/3] Constraint copilot plugin buildable in Tycho reactor --- .../.classpath | 7 + com.superinstance.constraint.copilot/.project | 28 ++++ com.superinstance.constraint.copilot/BUILD.md | 53 +++++++ .../META-INF/MANIFEST.MF | 9 ++ .../build.properties | 5 + .../plugin.xml | 11 ++ com.superinstance.constraint.copilot/pom.xml | 14 ++ .../copilot/ConstraintMcpProvider.java | 130 ++++++++++++++++++ .../build.properties | 1 + .../feature.xml | 38 +++++ com.superinstance.constraint.feature/pom.xml | 14 ++ pom.xml | 4 + 12 files changed, 314 insertions(+) create mode 100644 com.superinstance.constraint.copilot/.classpath create mode 100644 com.superinstance.constraint.copilot/.project create mode 100644 com.superinstance.constraint.copilot/BUILD.md create mode 100644 com.superinstance.constraint.copilot/META-INF/MANIFEST.MF create mode 100644 com.superinstance.constraint.copilot/build.properties create mode 100644 com.superinstance.constraint.copilot/plugin.xml create mode 100644 com.superinstance.constraint.copilot/pom.xml create mode 100644 com.superinstance.constraint.copilot/src/com/superinstance/constraint/copilot/ConstraintMcpProvider.java create mode 100644 com.superinstance.constraint.feature/build.properties create mode 100644 com.superinstance.constraint.feature/feature.xml create mode 100644 com.superinstance.constraint.feature/pom.xml diff --git a/com.superinstance.constraint.copilot/.classpath b/com.superinstance.constraint.copilot/.classpath new file mode 100644 index 00000000..92ebb099 --- /dev/null +++ b/com.superinstance.constraint.copilot/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/com.superinstance.constraint.copilot/.project b/com.superinstance.constraint.copilot/.project new file mode 100644 index 00000000..30c44d76 --- /dev/null +++ b/com.superinstance.constraint.copilot/.project @@ -0,0 +1,28 @@ + + + com.superinstance.constraint.copilot + Constraint Theory MCP for Copilot + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/com.superinstance.constraint.copilot/BUILD.md b/com.superinstance.constraint.copilot/BUILD.md new file mode 100644 index 00000000..53bcfe52 --- /dev/null +++ b/com.superinstance.constraint.copilot/BUILD.md @@ -0,0 +1,53 @@ +# Building the Constraint Copilot Eclipse Plugin + +## Prerequisites + +- **Java 17+** (JDK, not JRE) +- **Maven 3.9+** +- **Eclipse 4.34+** target platform (handled by Tycho + `base.target`) + +## Quick Build + +```bash +cd copilot-for-eclipse +mvn clean install -DskipTests +``` + +This runs the full Tycho reactor build including our two new modules: +- `com.superinstance.constraint.copilot` — the plugin bundle +- `com.superinstance.constraint.feature` — the Eclipse feature + +## Build Just Our Modules + +```bash +cd copilot-for-eclipse +mvn clean install -pl com.superinstance.constraint.copilot,com.superinstance.constraint.feature -am -DskipTests +``` + +The `-am` flag also builds required upstream modules (core, ui, etc.). + +## What Gets Built + +| Module | Output | +|--------|--------| +| `com.superinstance.constraint.copilot` | OSGi bundle JAR in `target/` | +| `com.superinstance.constraint.feature` | Feature JAR (for p2 update site) | + +## How It Works + +1. **`ConstraintMcpProvider`** implements `IMcpRegistrationProvider` from the Copilot Eclipse UI bundle. +2. At runtime, the `plugin.xml` extension point `com.microsoft.copilot.eclipse.ui.mcpRegistration` registers our provider. +3. Copilot calls `getMcpServerConfigurations()` which returns JSON pointing to the Python `constraint_mcp_server`. +4. If Python + the server package aren't found, it gracefully returns an empty config (no tools shown, no errors). + +## Installing in Eclipse + +After building, install the feature via: +1. **Help → Install New Software → Add → Archive…** — point to `com.microsoft.copilot.eclipse.repository/target/repository/` +2. Or drop the built JARs directly into Eclipse's `dropins/` folder. + +## Troubleshooting + +- **"Cannot resolve IMcpRegistrationProvider"**: The Copilot UI bundle must build first. Use `-am` or build the full reactor. +- **Checkstyle failures**: Use `-Dcheckstyle.skip=true` to bypass. +- **Target platform errors**: Ensure `base.target` references a valid Eclipse 4.34+ target definition. diff --git a/com.superinstance.constraint.copilot/META-INF/MANIFEST.MF b/com.superinstance.constraint.copilot/META-INF/MANIFEST.MF new file mode 100644 index 00000000..ea3d3558 --- /dev/null +++ b/com.superinstance.constraint.copilot/META-INF/MANIFEST.MF @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Constraint Theory MCP for Copilot +Bundle-SymbolicName: com.superinstance.constraint.copilot;singleton:=true +Bundle-Version: 0.1.0.qualifier +Bundle-Vendor: SuperInstance +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Require-Bundle: com.microsoft.copilot.eclipse.ui +Automatic-Module-Name: com.superinstance.constraint.copilot diff --git a/com.superinstance.constraint.copilot/build.properties b/com.superinstance.constraint.copilot/build.properties new file mode 100644 index 00000000..ad3634d4 --- /dev/null +++ b/com.superinstance.constraint.copilot/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = target/classes/ +bin.includes = META-INF/,\ + plugin.xml,\ + . diff --git a/com.superinstance.constraint.copilot/plugin.xml b/com.superinstance.constraint.copilot/plugin.xml new file mode 100644 index 00000000..c97b5ad5 --- /dev/null +++ b/com.superinstance.constraint.copilot/plugin.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/com.superinstance.constraint.copilot/pom.xml b/com.superinstance.constraint.copilot/pom.xml new file mode 100644 index 00000000..121d9ca7 --- /dev/null +++ b/com.superinstance.constraint.copilot/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + + com.microsoft.copilot.eclipse + github-copilot-for-eclipse + ${copilot-plugin-version} + + com.superinstance.constraint.copilot + eclipse-plugin + Constraint Theory MCP for Copilot + diff --git a/com.superinstance.constraint.copilot/src/com/superinstance/constraint/copilot/ConstraintMcpProvider.java b/com.superinstance.constraint.copilot/src/com/superinstance/constraint/copilot/ConstraintMcpProvider.java new file mode 100644 index 00000000..5ad73842 --- /dev/null +++ b/com.superinstance.constraint.copilot/src/com/superinstance/constraint/copilot/ConstraintMcpProvider.java @@ -0,0 +1,130 @@ +package com.superinstance.constraint.copilot; + +import java.io.File; +import java.util.concurrent.CompletableFuture; + +import com.microsoft.copilot.eclipse.ui.extensions.IMcpRegistrationProvider; + +/** + * Registers the Constraint Theory MCP server with Copilot for Eclipse. + * + *

This provider discovers the Python MCP server bundled alongside the plugin + * (or installed via pip) and returns JSON configuration that Copilot uses to + * connect via stdio JSON-RPC.

+ * + *

The server exposes 7 tools:

+ *
    + *
  • constraint_snap — snap pitch to Eisenstein lattice
  • + *
  • constraint_funnel — gravitational pull toward target
  • + *
  • constraint_diagnose — 4-order Goodman diagnostic
  • + *
  • constraint_generate — generate music in mode + terrain
  • + *
  • constraint_render — render notes to WAV
  • + *
  • constraint_terrain_list — list available terrains
  • + *
+ */ +public class ConstraintMcpProvider implements IMcpRegistrationProvider { + + private static final String SERVER_NAME = "constraint-ecosystem"; + + @Override + public CompletableFuture getMcpServerConfigurations() { + return CompletableFuture.supplyAsync(() -> { + // Try to find the Python MCP server + String pythonPath = findPython(); + String serverScript = findServerScript(); + + if (pythonPath == null || serverScript == null) { + // Return empty config if server not found — Copilot will just + // not show these tools. User can configure path in preferences. + return "{\"servers\":{}}"; + } + + // Build MCP server config JSON + // Format matches VS Code / Copilot MCP registration schema + String json = String.format(""" + { + "servers": { + "%s": { + "command": "%s", + "args": ["-m", "constraint_mcp_server"], + "env": { + "PYTHONPATH": "%s", + "CONSTRAINT_WORKSPACE": "%s" + }, + "type": "stdio" + } + } + } + """, + SERVER_NAME, + escapeJson(pythonPath), + escapeJson(serverScript), + escapeJson(getWorkspacePath()) + ); + + return json; + }); + } + + /** + * Find the Python executable on PATH. + */ + private String findPython() { + String[] candidates = {"python3", "python"}; + for (String cmd : candidates) { + try { + ProcessBuilder pb = new ProcessBuilder(cmd, "--version"); + pb.redirectErrorStream(true); + Process p = pb.start(); + int code = p.waitFor(); + if (code == 0) { + return cmd; + } + } catch (Exception e) { + // try next + } + } + return null; + } + + /** + * Find the constraint-mcp-server package on PYTHONPATH. + * Checks pip-installed location first, then relative to this plugin. + */ + private String findServerScript() { + // If installed via pip: `constraint-mcp-server` is on sys.path + // We return the workspace path so PYTHONPATH includes the ecosystem + String workspace = getWorkspacePath(); + if (workspace != null) { + File serverPkg = new File(workspace, "constraint-mcp-server"); + if (serverPkg.isDirectory()) { + return serverPkg.getAbsolutePath(); + } + } + return null; + } + + /** + * Get the workspace root path where the constraint ecosystem lives. + * In production this would use a preference or bundle location. + */ + private String getWorkspacePath() { + // TODO: Make this configurable via Eclipse preferences + String workspace = System.getProperty("constraint.workspace"); + if (workspace != null) { + return workspace; + } + // Fallback: look for CONSTRAINT_WORKSPACE env var + workspace = System.getenv("CONSTRAINT_WORKSPACE"); + if (workspace != null) { + return workspace; + } + // Default: user home / superinstance-workspace + return System.getProperty("user.home") + File.separator + "superinstance-workspace"; + } + + private String escapeJson(String s) { + if (s == null) return ""; + return s.replace("\\", "\\\\").replace("\"", "\\\""); + } +} diff --git a/com.superinstance.constraint.feature/build.properties b/com.superinstance.constraint.feature/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/com.superinstance.constraint.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/com.superinstance.constraint.feature/feature.xml b/com.superinstance.constraint.feature/feature.xml new file mode 100644 index 00000000..09f2b29e --- /dev/null +++ b/com.superinstance.constraint.feature/feature.xml @@ -0,0 +1,38 @@ + + + + + Constraint Theory MCP server integration for GitHub Copilot in Eclipse. + Provides constraint snapping, funneling, diagnostics, generation, and rendering tools. + + + + MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + + diff --git a/com.superinstance.constraint.feature/pom.xml b/com.superinstance.constraint.feature/pom.xml new file mode 100644 index 00000000..bd04b1ce --- /dev/null +++ b/com.superinstance.constraint.feature/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + + com.microsoft.copilot.eclipse + github-copilot-for-eclipse + ${copilot-plugin-version} + + com.superinstance.constraint.feature + eclipse-feature + Constraint Theory MCP Feature + diff --git a/pom.xml b/pom.xml index b49c8076..d0210338 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,10 @@ com.microsoft.copilot.eclipse.feature com.microsoft.copilot.eclipse.repository + + com.superinstance.constraint.copilot + com.superinstance.constraint.feature + com.microsoft.copilot.eclipse.core.test com.microsoft.copilot.eclipse.ui.test From e956528bafc6e889e63991cc08ab4c9134e5c8a0 Mon Sep 17 00:00:00 2001 From: OpenClaw Date: Mon, 25 May 2026 09:37:11 -0800 Subject: [PATCH 3/3] docs: engineering README --- README.md | 180 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 95 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 31cddede..62aa1152 100644 --- a/README.md +++ b/README.md @@ -1,128 +1,138 @@ # GitHub Copilot for Eclipse -GitHub Copilot for Eclipse brings AI-assisted coding to the Eclipse IDE with these core capabilities: +GitHub Copilot for Eclipse brings AI-assisted coding to the Eclipse IDE. This is a fork maintained by **SuperInstance** that adds Constraint Theory integration via MCP and a multi-model BYOK routing system. -- **Code completions** for in-editor suggestions from code context or natural-language comments. -- **Next Edit Suggestions** provide context-aware suggestions for your next code edits. -- **Agent Mode** for conversational help and more autonomous, project-aware assistance. -- **Model Context Protocol (MCP)** integration to connect Copilot with external tools and services. -- **Advanced Agentic Capabilities** include Custom Agents, Isolated Subagents, and Plan Agent, with more agentic capabilities coming soon. +## What This Fork Adds -## Usage-based billing support +### Constraint Theory MCP Server (`com.superinstance.constraint.copilot`) -Starting from version **0.18.0**, we have added internal support for the upcoming [usage-based billing experience](https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/), including experience updates to the usage panel, usage notifications, and model picker. These changes will become visible once usage-based billing is rolled out. +A bundled Eclipse plugin that registers a Python MCP (Model Context Protocol) server with Copilot. The server exposes 6 tools: -To ensure compatibility with the new billing experience, we strongly recommend upgrading the plugin to **0.18.0 or later** as soon as possible. +| Tool | Description | +|------|-------------| +| `constraint_snap` | Snap pitch to the Eisenstein A₂ lattice | +| `constraint_funnel` | Gravitational pull toward a target constraint | +| `constraint_diagnose` | 4-order Goodman diagnostic for constraint health | +| `constraint_generate` | Generate music in a given mode + terrain | +| `constraint_render` | Render notes to WAV audio | +| `constraint_terrain_list` | List available musical terrains | -Clients using older plugin versions will continue to function. However, the billing and usage experience may not be optimal and may not accurately reflect the latest usage-based billing experience. +The MCP server is discovered automatically via `ConstraintMcpProvider` (implements `IMcpRegistrationProvider`). It locates the `constraint-mcp-server` Python package on `PYTHONPATH` and connects via stdio JSON-RPC. If the server is not found, the plugin degrades gracefully — Copilot simply won't show those tools. +### Multi-Model BYOK Routing (`MULTI-MODEL-DESIGN.md`) -## Getting access to GitHub Copilot +An architecture for routing code completions and chat requests to different AI models based on "constraint terrain" complexity: -Sign up for [GitHub Copilot Free](https://github.com/settings/copilot?utm_source=vscode-chat-readme&utm_medium=second&utm_campaign=2025mar-em-MSFT-signup), or request access from your enterprise admin. +- **Shallow terrain** (single-line completion, no context) → budget models (GLM-4-Flash, DeepSeek-Lite) +- **Mid terrain** (multi-line, file context) → standard models (DeepSeek-V3, GLM-4) +- **Deep terrain** (chat with tools, reasoning) → premium models (GPT-4o, Claude 3.5) +- **Abyssal terrain** (agent mode, multi-file) → flagship models (Claude 3.5 Sonnet, o3) -To use GitHub Copilot, an active subscription is required. Learn more about business and individual plans at [github.com/features/copilot](https://github.com/features/copilot?utm_source=vscode-chat&utm_medium=readme&utm_campaign=2025mar-em-MSFT-signup). +See [`MULTI-MODEL-DESIGN.md`](MULTI-MODEL-DESIGN.md) for the full design document. -## Prerequisites - -- [Eclipse IDE](https://www.eclipse.org/downloads/) -- An active [GitHub Copilot subscription](https://github.com/features/copilot) - -## Install and set up - -### Option 1: Eclipse Marketplace - -1. Open [Eclipse Marketplace](https://marketplace.eclipse.org/) and go to the [GitHub Copilot plugin page](https://marketplace.eclipse.org/content/github-copilot). -2. Drag **Install** to your running Eclipse workspace. -3. Restart Eclipse. -4. Sign in to GitHub Copilot from Eclipse. - -### Option 2: Install from update site - -1. In Eclipse, open **Help → Install New Software…** -2. Add this update site URL: `https://azuredownloads-g3ahgwb5b8bkbxhd.b01.azurefd.net/github-copilot/` -3. Select **GitHub Copilot** and complete installation. -4. Restart Eclipse and sign in. - -## Core capabilities +## Core Capabilities (from upstream) -### Code completions +- **Code completions** — Inline ghost-text suggestions as you type +- **Next Edit Suggestions** — Predict your next edit location and propose changes +- **Agent Mode** — Autonomous project-aware assistance with tool calling +- **Ask Mode** — Conversational AI for explanations, refactors, debugging +- **MCP integration** — Connect Copilot with external tools and services +- **Custom Agents, Subagents, Plan Agent** — Advanced agentic workflows +- **BYOK (Bring Your Own Key)** — Use your own API keys for Azure, OpenAI, Gemini, Groq, OpenRouter, Anthropic -Inline suggestions (ghost text) appear as you type in the editor. Suggestions can range from small edits to multi-line changes. - -### Next Edit Suggestions - -Next Edit Suggestions predict your next edit location and propose the next change based on your recent edits and context. - -### Agent and Ask Mode - -**Ask Mode** provides conversational AI assistance for explaining code, generating code from requirements, suggesting refactors, and providing debugging guidance. - -**Agent Mode** works autonomously across your project context to identify and fix issues, propose implementation steps, and support larger coding tasks with iterative guidance. +## Prerequisites -### Model Context Protocol (MCP) +- [Eclipse IDE](https://www.eclipse.org/downloads/) +- Java 17+ (Bundle-RequiredExecutionEnvironment: JavaSE-17) +- Active [GitHub Copilot subscription](https://github.com/features/copilot) +- Python 3.10+ (for Constraint Theory MCP tools — optional) -MCP support enables integrating external tools and services into Copilot workflows where configured. +## Install -### Advanced Agentic Capabilities +### Eclipse Marketplace -- **Custom Agents** allow users to create personalized agents with specific instructions and behaviors. -- **Isolated Subagents** can be spawned by the main agent to handle specific tasks or contexts independently. -- **Plan Agent** can generate multi-step plans to accomplish complex tasks, breaking them down into manageable actions. -- **Skills** are reusable, specialized AI assistant templates that enrich chat context in Agent Mode. Skills are defined as `SKILL.md` files and can be scoped to a workspace or shared globally. +1. Open [Eclipse Marketplace](https://marketplace.eclipse.org/) → [GitHub Copilot](https://marketplace.eclipse.org/content/github-copilot) +2. Drag **Install** to your running Eclipse workspace +3. Restart Eclipse +4. Sign in to GitHub Copilot - - Creating Skills +### Update Site - Place a `SKILL.md` file in any of these directories: +1. **Help → Install New Software…** +2. Add update site: `https://azuredownloads-g3ahgwb5b8bkbxhd.b01.azurefd.net/github-copilot/` +3. Select **GitHub Copilot**, complete installation, restart Eclipse - - **Project-scoped:** `.github/skills//`, `.claude/skills//`, `.agents/skills//` - - **User-scoped (global):** `~/.copilot/skills//`, `~/.claude/skills//`, `~/.agents/skills//` +## Building from Source - Each `SKILL.md` file can include YAML front matter with metadata (name, description) followed by Markdown content that provides domain knowledge, workflows, or instructions for the AI assistant. +```bash +git clone https://github.com/SuperInstance/copilot-for-eclipse.git +cd copilot-for-eclipse +./mvnw clean verify +``` - Skills are automatically discovered and available in Agent Mode. You can enable or disable skills in **Window → Preferences → Copilot → Chat → Enable Skills**. +The build uses Maven + Tycho 4.0.13. Modules: -For other available features in Eclipse, see the [Copilot feature matrix](https://docs.github.com/en/copilot/reference/copilot-feature-matrix?tool=eclipse). +| Module | Description | +|--------|-------------| +| `com.microsoft.copilot.eclipse.core` | Core plugin: LSP client, completion, chat, BYOK, persistence | +| `com.microsoft.copilot.eclipse.ui` | UI layer: chat view, inline completion, model picker, preferences | +| `com.microsoft.copilot.eclipse.ui.terminal` | Terminal integration | +| `com.superinstance.constraint.copilot` | Constraint Theory MCP registration | +| `com.superinstance.constraint.feature` | Feature packaging for the constraint plugin | +| `com.microsoft.copilot.eclipse.core.agent.*` | Platform-specific Copilot agent binaries | -## Privacy and responsible use +## Project Structure -We follow responsible practices in accordance with our -[Privacy Statement](https://docs.github.com/en/site-policy/privacy-policies/github-privacy-statement). +``` +com.microsoft.copilot.eclipse.core/src/ +├── lsp/ # LSP client + protocol types +│ ├── CopilotLanguageClient.java +│ └── protocol/ # BYOK, quota, conversation, coding-agent types +├── completion/ # Inline completion provider + suggestion management +├── chat/ # Chat modes (Ask, Agent), custom modes, MCP config +├── nes/ # Next Edit Suggestion provider +├── persistence/ # Conversation serialization (XML-based) +├── format/ # Language-specific formatting (Java, CDT) +└── IdeCapabilities.java # IDE feature detection -To get the latest security fixes, please use the latest version of GitHub Copilot for Eclipse. +com.superinstance.constraint.copilot/src/ +└── ConstraintMcpProvider.java # MCP server discovery + registration +``` -## Data and telemetry +## Configuration -The GitHub Copilot for Eclipse plugin collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://privacy.microsoft.com/privacystatement) to learn more. +### Constraint Theory MCP -## Security +Set the workspace path where the constraint ecosystem lives: -Please do not report security vulnerabilities in public issues. +```bash +# Option 1: JVM system property +-Dconstraint.workspace=/path/to/constraint-ecosystem -See [SECURITY.md](SECURITY.md) for vulnerability reporting instructions. +# Option 2: Environment variable +export CONSTRAINT_WORKSPACE=/path/to/constraint-ecosystem -## Support +# Option 3: Default fallback +~/superinstance-workspace +``` -For bug reports and feature requests, use this repository’s Issues. +The `constraint-mcp-server` Python package must be on `PYTHONPATH` within that workspace. -For support guidance, see [SUPPORT.md](SUPPORT.md). +### Multi-Model Routing -## Contributing +See [`MULTI-MODEL-DESIGN.md`](MULTI-MODEL-DESIGN.md) for the full routing configuration format (`model-routing.json`). -This project welcomes contributions and suggestions. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to get started, build the project, submit pull requests, and follow our code style guidelines. +## Related Repos -Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [Contributor License Agreements](https://cla.opensource.microsoft.com). +- [constraint-theory-core](https://github.com/SuperInstance/constraint-theory-core) — Mathematical primitives for the constraint ecosystem +- [snapkit-v2](https://github.com/SuperInstance/snapkit-v2) — Eisenstein lattice snap (Python) +- [snapkit-js](https://github.com/SuperInstance/snapkit-js) — Eisenstein lattice snap (JS/TS) +- [style-dna](https://github.com/SuperInstance/style-dna) — Musical DNA extraction and style morphing -## Trademarks +## Upstream -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft -trademarks or logos is subject to and must follow -[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/legal/intellectualproperty/trademarks/usage/general). -Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. -Any use of third-party trademarks or logos are subject to those third-party's policies. +This is a fork of [github/copilot-for-eclipse](https://github.com/microsoft/copilot-for-eclipse) (Apache 2.0 License). ## License -Copyright (c) Microsoft Corporation. All rights reserved. - -This project is licensed under the MIT License. See [LICENSE](LICENSE) for details. \ No newline at end of file +Apache License 2.0