AGENTS.md
packages/lsp-daemon/AGENTS.mdAGENTS.md
Quality
84/100
Scores the file, not the repository.Length
833 words
5 headings · 1 code blocksRepository
67k
— · pushed 0 days agoLast changed
2 days ago
First indexed 2 days ago.1# lsp-daemon -- Shared Per-User LSP Daemon23**Generated:** 2026-07-17 / 7d664b96b45## OVERVIEW67Vendored, Node-targeted MCP-layer package (`@code-yeongyu/lsp-daemon`). Runs ONE long-lived LSP process per user and fans many short-lived agent sessions into it over a unix socket (Windows named pipe). The runtime contract is harness-neutral so Codex, OpenCode, and Senpi can converge on the same authenticated daemon. Sessions launch a thin stdio MCP **proxy** that forwards to the warm **daemon**. Reuses [`@code-yeongyu/lsp-tools-mcp`](../lsp-tools-mcp) for the actual LSP manager + MCP request handler - this package only adds the daemon/proxy/transport layer. Built with `npm` + vitest + biome (NOT Bun); `engines.node >= 20`.89## KEY FILES1011| File | Role |12|------|------|13| `cli.ts` | Bin `omo-lsp-daemon`. `mcp` (default) → `runMcpStdioProxy()`; `daemon` → `runDaemon()` |14| `proxy.ts` | `runMcpStdioProxy()`: reads JSON-RPC lines from stdin; `tools/call` → daemon via client; other LSP MCP requests handled locally; startup watchdog + aborts on stdin close |15| `daemon-server.ts` | `startDaemonServer()`: `net.createServer` on the socket, owns the LSP manager, idle auto-shutdown, pid/endpoint files, SIGTERM/SIGINT cleanup |16| `daemon-client.ts` | `callToolViaDaemon()` / `callDiagnosticsViaDaemon()`: connect to socket, send tool call, await response; honors `AbortSignal`, sends `$/cancelRequest` on abort/timeout |17| `ensure-daemon.ts` | `ensureDaemonRunning()`: probe → lock → spawn detached daemon → poll until reachable (DI'd deps for tests); accepts `AbortSignal`, abort cancels pending startup |18| `request-routing.ts` | `handleDaemonMessage()`: strips `_context` (cwd/env) from args, runs request inside that `RequestContext` |19| `runtime-contract.ts` | Exact three-variable runtime override contract + typed validation errors |20| `paths.ts` | OMO-owned versioned socket/lock/pid/log path resolution |21| `lock.ts` | Single-flight file lock + `unlinkQuietly` |22| `socket-jsonrpc.ts` | Newline-delimited JSON-RPC framing over the socket |23| `run-daemon.ts` | `daemon` subcommand entry (boots the server) |24| `index.ts` | Barrel: `runMcpStdioProxy`, `ensureDaemonRunning`, `callToolViaDaemon`, `callDiagnosticsViaDaemon`, `daemonPaths`, `disposeDefaultLspManager` |2526## FLOW2728```29session → omo-lsp-daemon (mcp proxy, stdio)30 ├─ ensureDaemonRunning(): probe socket31 │ ├─ reachable → reuse32 │ └─ down → tryAcquireLock → spawn detached `cli.js daemon` → poll until reachable33 ├─ tools/call (+ _context {cwd,env}) → daemon-client → unix socket34 │ └─ daemon: handleDaemonMessage → runWithRequestContext(cwd/env) → lsp-tools-mcp handler35 └─ non tool-call LSP MCP request → handled locally in the proxy36```3738## NOTES3940- **Startup watchdog:** the proxy exits if no MCP request arrives within `startupTimeoutMs` (default `DEFAULT_STARTUP_TIMEOUT_MS` = 10 s). The first handler invocation clears the watchdog; on expiry it destroys stdin and writes a `[lsp-daemon]` diagnostic to stderr, then swallows the resulting `ERR_STREAM_PREMATURE_CLOSE`.41- **Cancellation lifecycle:** the proxy owns an `AbortController` aborted on stdin `end`/`close`. That signal threads through `callToolViaDaemon` into `ensureDaemonAvailable` (rejects `DaemonRequestCancelledError`) and `sendToolCall`, which sends a `$/cancelRequest` (auth envelope + request id) to the daemon and rejects. `callToolViaDaemon` retries only on auth refresh; it breaks on `DaemonRequestCancelledError` and on a `DaemonRequestError` that was already written or names a non-retryable tool (`rename`/`lsp_rename`).42- **QA smoke scripts:** `scripts/qa/cancellation-smoke.mjs` drives one deterministic socket-to-LSP cancellation end-to-end; `scripts/qa/commit-barrier-smoke.mjs` proves an aborted `textDocument/rename` emits `$/cancelRequest` before any workspace edit applies (an abort mid-apply still commits exactly one edit, reported as a late abort). Both take the repo root as `argv[2]` and are wired into the codex-qa/opencode-qa `lsp-e2e.sh` drivers.43- **Per-request context threading:** the proxy injects `_context` (cwd + env allowlist) into each `tools/call`; the daemon runs that request inside `runWithRequestContext` so one shared process correctly serves many working directories.44- **Idle shutdown:** daemon self-exits after 30 min (`DEFAULT_IDLE_SHUTDOWN_MS`) once there are no live connections AND `getLspManager().clientCount() === 0`. Live LSP clients keep it warm.45- **State root:** `$OMO_LSP_DAEMON_DIR` when it is already absolute, otherwise `~/.omo/lsp-daemon`; every runtime is isolated under `v<version>`.46- **Runtime overrides are paired:** `$OMO_LSP_DAEMON_CLI` and `$OMO_LSP_DAEMON_VERSION` must be both absent or both present. A singleton pair fails before path creation or spawn. Explicit CLI paths must be absolute existing regular files; versions must match `[A-Za-z0-9][A-Za-z0-9._+-]{0,127}`.47- **Socket path:** Unix uses `<version-dir>/daemon.sock` and keeps the short hashed `tmpdir()` fallback when the natural path reaches 100 characters. Windows binds the pipe digest to the canonical version directory plus the current user discriminator; request authentication remains the security boundary.48- **OpenCode bootstrap:** dist/bootstrap resolves the package `./cli` export instead of deep-running generated files. Source mode runs the actual `src/cli.ts` with Bun and sets the paired `OMO_LSP_DAEMON_CLI`/`OMO_LSP_DAEMON_VERSION` override to that source CLI plus the package version. The OpenCode adapter supplies only the three `LSP_TOOLS_MCP_*` translator inputs for request context: `.opencode/lsp.json`, `.omo/lsp.json`, `.omo/lsp-client.json`, then the OpenCode user config and install-decision paths.49- **Legacy cleanup input:** `test/fixtures/legacy-path-vectors.json` freezes the pre-migration natural Unix, hashed Unix, and Windows named-pipe paths for the installer cleanup work. Do not regenerate those paths from the new resolver.50- **Clean builds:** `scripts/clean-dist.mjs` removes the complete old `dist` tree before TypeScript and Bun emit new artifacts, so deleted generated files cannot survive a build.51- **Spawn is detached + log-redirected:** child runs `node cli.js daemon` with `stdio: ["ignore", logFd, logFd]` (→ `daemon.log`) and `unref()`, so the parent session never blocks on it.52- **Build before use:** `bun run build:lsp-daemon` (`npm ci` + `npm run build`) before anything needing `dist/`. Shipped via the root `package.json` `files` array (`packages/lsp-daemon/{package.json,dist}`).53
Also in code-yeongyu/oh-my-openagent
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| code-yeongyu/oh-my-openagent.agents/AGENTS.md · 67k | AGENTS.md | stylearchtesting-strategydatabase | 64/100 | 2 days ago | |
| code-yeongyu/oh-my-openagent.opencode/AGENTS.md · 67k | AGENTS.md | stylearchdo-not | 71/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentAGENTS.md · 67k | AGENTS.md | setupbuildtestlint-format+11 | 84/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentassets/AGENTS.md · 67k | AGENTS.md | buildteststylearch | 88/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentbin/AGENTS.md · 67k | AGENTS.md | teststylearch | 64/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/AGENTS.md · 67k | AGENTS.md | buildtestlint-formatstyle+3 | 83/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/agents-md-core/AGENTS.md · 67k | AGENTS.md | archdependenciesapi | 48/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/boulder-state/AGENTS.md · 67k | AGENTS.md | archapi | 48/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/claude-code-compat-core/AGENTS.md · 67k | AGENTS.md | archagent-behaviour | 56/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/comment-checker-core/AGENTS.md · 67k | AGENTS.md | archdependenciesapi | 48/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/delegate-core/AGENTS.md · 67k | AGENTS.md | stylearchdependenciesapi | 60/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/git-bash-mcp/AGENTS.md · 67k | AGENTS.md | buildtestlint-formatarch+1 | 82/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/hashline-core/AGENTS.md · 67k | AGENTS.md | archtypesdependenciesapi | 48/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/lsp-core/AGENTS.md · 67k | AGENTS.md | archmonorepo | 43/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/lsp-tools-mcp/AGENTS.md · 67k | AGENTS.md | buildtestlint-formatarch | 74/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/mcp-client-core/AGENTS.md · 67k | AGENTS.md | arch | 43/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/mcp-stdio-core/AGENTS.md · 67k | AGENTS.md | archapi | 56/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/model-core/AGENTS.md · 67k | AGENTS.md | arch | 54/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/omo-codex/AGENTS.md · 67k | AGENTS.md | setupbuildtestarch+6 | 93/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/omo-codex/plugin/components/bootstrap/AGENTS.md · 67k | AGENTS.md | buildtestarchagent-behaviour | 88/100 | 2 days ago |
Diff against .agents/AGENTS.md Diff against .opencode/AGENTS.md Diff against AGENTS.md Diff against assets/AGENTS.md Diff against bin/AGENTS.md Diff against packages/AGENTS.md Diff against packages/agents-md-core/AGENTS.md Diff against packages/boulder-state/AGENTS.md Diff against packages/claude-code-compat-core/AGENTS.md Diff against packages/comment-checker-core/AGENTS.md Diff against packages/delegate-core/AGENTS.md Diff against packages/git-bash-mcp/AGENTS.md Diff against packages/hashline-core/AGENTS.md Diff against packages/lsp-core/AGENTS.md Diff against packages/lsp-tools-mcp/AGENTS.md Diff against packages/mcp-client-core/AGENTS.md Diff against packages/mcp-stdio-core/AGENTS.md Diff against packages/model-core/AGENTS.md Diff against packages/omo-codex/AGENTS.md Diff against packages/omo-codex/plugin/components/bootstrap/AGENTS.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | 3 days ago | |
| code-yeongyu/oh-my-openagentpackages/web/AGENTS.md · 67k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 2 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| SkeneTechnologies/skene-cookbookAGENTS.md · 51 | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 2 days ago | |
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| aaif-goose/gooseAGENTS.md · 52k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| elastic/elasticsearchx-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/AGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+2 | 100/100 | 3 days ago |
