# Lingma Proxy Architecture This document describes the current architecture of **Lingma Proxy**, including both backend modes: - `remote`: the default and recommended mode, calling Lingma remote HTTP APIs directly with detected credentials - `ipc`: a compatibility mode that bridges to the local Lingma IDE plugin transport --- ## 1. System Overview ```mermaid flowchart LR A["Clients
Claude Code / Hermes / Cline / Continue / OpenAI SDK / Anthropic SDK"] B["internal/httpapi
OpenAI + Anthropic compatible routes"] C["internal/service
request normalization / session policy / streaming / fallback"] D["internal/toolemulation
tool prompt injection + action block parsing"] E["internal/lingmaipc
WebSocket / Named Pipe"] F["internal/remote
credential detection / model list / chat / SSE"] G["Lingma plugin local process"] H["Lingma remote API"] I["Desktop app
Wails GUI / logs / token stats / persisted state"] A --> B I --> B B --> C C --> D C --> E C --> F E --> G F --> H ``` --- ## 2. Runtime Modes ### 2.1 Remote API mode `backend=remote` - Reads Lingma remote base URL from config, environment, or detected local Lingma logs - Loads credentials from: - explicit `remote_auth_file` - or detected Lingma login cache - Calls remote model list and chat endpoints directly - Supports timeout / 429 / 5xx fallback across available remote models - Does not use local plugin session environment knobs - Avoids IDE/plugin IPC session lifetime, working directory, and extension environment limitations ### 2.2 IPC plugin mode `backend=ipc` - Reads local plugin transport information - Connects through: - WebSocket on macOS / Linux - Named Pipe on Windows - Reuses Lingma plugin session semantics - Session/environment options in the desktop UI apply only here - This mode is based on the IPC protocol insight from `coolxll/lingma-ipc-proxy` --- ## 3. Module Responsibilities ### 3.1 `cmd/lingma-ipc-proxy` Entry point and config loading. Responsibilities: - parse CLI flags - merge config file + environment + flags - choose backend mode - build `service.Config` - start `internal/httpapi.Server` Important config fields: - `backend` - `transport` - `websocket_url` - `pipe` - `remote_base_url` - `remote_auth_file` - `remote_version` - `remote_fallback_enabled` - `remote_fallback_models` ### 3.2 `internal/httpapi` Compatibility layer for OpenAI and Anthropic style APIs. Primary routes: - `GET /v1/models` - `POST /v1/chat/completions` - `POST /v1/messages` - `GET /health` - `GET /props` Responsibilities: - normalize OpenAI / Anthropic requests into `service.ChatRequest` - convert service results back to OpenAI / Anthropic payloads - stream SSE responses - sanitize and record request / response payloads for debug UI ### 3.3 `internal/service` Core orchestration layer. Responsibilities: - choose active backend - warm up backend connection / credentials - list models - generate non-streaming responses - generate streaming responses - apply session reuse policy in IPC mode - inject / parse tool emulation - normalize image inputs - apply remote fallback order Important behavior split: - IPC path uses `internal/lingmaipc` - Remote path uses `internal/remote` ### 3.4 `internal/lingmaipc` Local transport client for Lingma plugin IPC. Responsibilities: - detect WebSocket / pipe endpoint - dial and reconnect - send RPC messages such as: - `session/new` - `session/prompt` - `session/set_model` - `chat/deleteSessionById` - consume `session/update` notifications ### 3.5 `internal/remote` Remote HTTP client for Lingma cloud APIs. Responsibilities: - resolve base URL - load and validate credentials - derive machine / user identity for remote auth - list remote models - call remote chat endpoint - handle remote SSE streaming ### 3.6 `internal/toolemulation` Prompt-based tool bridge for models that do not expose native tool calling in Lingma transport. Responsibilities: - extract tool definitions from OpenAI / Anthropic requests - append tool contract to prompt - parse JSON action blocks from model output - project tool calls back to: - Anthropic `tool_use` - OpenAI `tool_calls` --- ## 4. Request Flow ### 4.1 Shared ingress flow ```mermaid sequenceDiagram participant Client participant HTTP as httpapi participant Service as service Client->>HTTP: OpenAI/Anthropic request HTTP->>HTTP: normalize request HTTP->>Service: Generate / GenerateStream ``` ### 4.2 IPC backend flow ```mermaid sequenceDiagram participant Service participant Tool as toolemulation participant IPC as lingmaipc participant Plugin as Lingma plugin Service->>Tool: inject tool contract if needed Service->>IPC: ensure connected Service->>IPC: create/reuse session Service->>IPC: session/prompt IPC->>Plugin: RPC message Plugin-->>IPC: session/update chunks IPC-->>Service: stream events Service-->>Service: parse tool blocks / image references / stop reason ``` ### 4.3 Remote backend flow ```mermaid sequenceDiagram participant Service participant Remote as remote client participant API as Lingma remote API Service->>Remote: load credentials / ensure client Service->>Remote: list models if needed Service->>Remote: chat request Remote->>API: HTTPS request API-->>Remote: JSON or SSE response Remote-->>Service: normalized result Service-->>Service: fallback to next model when allowed ``` --- ## 5. Remote Fallback Strategy Remote fallback is used only when all conditions are true: - `backend=remote` - `remote_fallback_enabled=true` - request has not emitted stream output yet - upstream error matches timeout / 429 / 5xx class Current default order: 1. `kmodel` 2. `mmodel` 3. `dashscope_qwen3_coder` 4. `dashscope_qmodel` 5. `dashscope_qwen_max_latest` 6. `dashscope_qwen_plus_20250428_thinking` Before using that order, the service filters candidates against the actual `/v1/models` result from the remote backend so unavailable models are skipped. --- ## 6. Desktop App Architecture The Wails desktop app is a management UI around the local proxy process. Responsibilities: - start / stop / restart proxy - show current backend and resolved endpoints - persist: - request history - logs - token statistics - show detected IPC and remote credentials metadata - edit config and restart proxy on save Persisted local state: - config: `~/.config/lingma-proxy/config.json` - legacy config fallback: `~/.config/lingma-ipc-proxy/config.json` - UI/runtime state: `~/.config/lingma-ipc-proxy/app-state.json` Production packaging rules: - packaged app should not auto-open inspector - local development can opt in with `LINGMA_DESKTOP_DEBUG=1` --- ## 7. Key Design Decisions ### 7.1 Why keep both IPC and remote modes? Because the two modes solve different problems: - Remote mode avoids plugin runtime coupling and is usually better for third-party agent clients. - IPC mode preserves plugin session semantics and remains useful when the caller specifically wants the local plugin's context or model list. ### 7.2 Why keep tool emulation even with remote mode? Because Lingma-exposed models are not guaranteed to speak OpenAI/Anthropic native tool protocol consistently across all routes. The proxy must keep a stable external contract even when the upstream model capability is uneven. ### 7.3 Why persist requests and token stats in the desktop app? Because the GUI is used as an operational console, not a transient preview. Users need model usage, logs, and recent traffic to survive app restarts. --- ## 8. Known Boundaries - IPC mode still has stronger environment coupling with the local Lingma plugin - remote credential detection depends on local Lingma cache / auth file layout - image payloads are sanitized in persisted request logs to avoid oversized local state - request history may contain mixed models in remote mode when fallback is triggered or when different clients specify different models --- ## 9. Files to Read First If you are extending the system, start here: - `cmd/lingma-ipc-proxy/main.go` - `internal/httpapi/server.go` - `internal/service/service.go` - `internal/lingmaipc/*` - `internal/remote/*` - `desktop/app.go` - `desktop/main.go` --- Document version: 2026-05-06