dsh-lsp-actions 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.es.md +176 -129
- package/README.hi.md +176 -129
- package/README.md +170 -129
- package/README.pt.md +176 -129
- package/README.zh.md +224 -0
- package/cordis.patch.yml +6 -0
- package/docs/editor-protocol.md +159 -0
- package/docs/editor-protocol.zh-CN.md +159 -0
- package/docs/seam-extension-notes.md +76 -0
- package/examples/vscode/README.md +72 -0
- package/examples/vscode/README.zh-CN.md +72 -0
- package/examples/vscode/backend/bin.mjs +44 -0
- package/examples/vscode/backend/cordis.yml +53 -0
- package/examples/vscode/backend/package.json +22 -0
- package/examples/vscode/extension/package.json +96 -0
- package/examples/vscode/extension/src/client.js +100 -0
- package/examples/vscode/extension/src/extension.js +187 -0
- package/examples/vscode/extension/src/views.js +127 -0
- package/lib/client.d.ts +3 -3
- package/lib/editor/actions.d.ts +44 -0
- package/lib/editor/actions.d.ts.map +1 -0
- package/lib/editor/actions.js +370 -0
- package/lib/editor/actions.js.map +1 -0
- package/lib/editor/cache.d.ts +51 -0
- package/lib/editor/cache.d.ts.map +1 -0
- package/lib/editor/cache.js +75 -0
- package/lib/editor/cache.js.map +1 -0
- package/lib/editor/server.d.ts +61 -0
- package/lib/editor/server.d.ts.map +1 -0
- package/lib/editor/server.js +97 -0
- package/lib/editor/server.js.map +1 -0
- package/lib/editor/service.d.ts +67 -0
- package/lib/editor/service.d.ts.map +1 -0
- package/lib/editor/service.js +182 -0
- package/lib/editor/service.js.map +1 -0
- package/lib/editor/transport.d.ts +53 -0
- package/lib/editor/transport.d.ts.map +1 -0
- package/lib/editor/transport.js +143 -0
- package/lib/editor/transport.js.map +1 -0
- package/lib/editor/types.d.ts +185 -0
- package/lib/editor/types.d.ts.map +1 -0
- package/lib/editor/types.js +13 -0
- package/lib/editor/types.js.map +1 -0
- package/lib/edits.d.ts +1 -1
- package/lib/extra-tools.d.ts +3 -3
- package/lib/index.d.ts +17 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +26 -1
- package/lib/index.js.map +1 -1
- package/lib/runner.d.ts +5 -5
- package/lib/seam.d.ts +1 -1
- package/lib/servers.d.ts +20 -1
- package/lib/servers.d.ts.map +1 -1
- package/lib/servers.js +6 -0
- package/lib/servers.js.map +1 -1
- package/lib/tools.d.ts +18 -5
- package/lib/tools.d.ts.map +1 -1
- package/lib/tools.js +2 -2
- package/lib/tools.js.map +1 -1
- package/lib/translate.d.ts +1 -1
- package/lib/vocabulary.d.ts +3 -1
- package/lib/vocabulary.d.ts.map +1 -1
- package/lib/vocabulary.js.map +1 -1
- package/package.json +61 -8
- package/README.zh-CN.md +0 -181
package/README.md
CHANGED
|
@@ -2,95 +2,163 @@
|
|
|
2
2
|
|
|
3
3
|
# 🛰️ dsh-lsp-actions
|
|
4
4
|
|
|
5
|
-
**The LSP action surface for DeepSeek Harness — real language servers, real feedback.**
|
|
5
|
+
**The LSP action surface for DeepSeek Harness — real language servers, real feedback, and the IDE integration backend for editors.**
|
|
6
6
|
|
|
7
|
-
Diagnostics, formatting,
|
|
7
|
+
*Diagnostics, formatting, completion, code actions, symbols, signature help, inlay hints, and rename for your agent's editor loop — plus the stable editor action protocol (`lsp.actions.*`) that lets any editor consume them directly.*
|
|
8
8
|
|
|
9
|
-
[](LICENSE)
|
|
10
|
+
[](https://github.com/topics/dsh-plugin)
|
|
11
|
+
[](#)
|
|
12
|
+
[](https://github.com/PerryLink/dsh-lsp-actions/actions)
|
|
13
|
+
[](https://github.com/PerryLink/dsh-lsp-actions/releases)
|
|
14
|
+
[](https://www.npmjs.com/package/dsh-lsp-actions)
|
|
15
|
+
[](https://www.npmjs.com/package/dsh-lsp-actions)
|
|
15
16
|
|
|
16
|
-
[English](README.md) · [简体中文](README.zh
|
|
17
|
+
[English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
17
18
|
|
|
18
19
|
</div>
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
22
|
-
##
|
|
23
|
+
## Compatibility
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
| Surface | Status |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.6` (compat declared for `>=0.1.0-rc.6`) |
|
|
28
|
+
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
|
+
| Platforms | All (pure host; subprocess + filesystem, no network) |
|
|
30
|
+
| Model | Any (tools are model-agnostic; the plugin never calls a model) |
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
| --- | --- | --- |
|
|
28
|
-
| `lsp_diagnostics <file>` | Compiler/analyzer errors, warnings and hints with severity, range, message and source server | ❌ read-only |
|
|
29
|
-
| `lsp_format <file> [range?]` | Formats a file or selection through the language server and applies the result, returning the diff | ✅ via `fs/write-intent` + sandbox policy |
|
|
30
|
-
| `lsp_completion <file> <line> <character>` | Completion suggestions at a cursor position, including the actual insertion text | ❌ read-only |
|
|
31
|
-
| `lsp_code_action <file> [range?] [only?]` | Server-verified quickfixes/refactorings (with their edits) for a range or the first diagnostic | ❌ reference-only |
|
|
32
|
-
| `lsp_symbols <query?> <file_path?>` | Workspace-wide symbol search by name, or one file's symbol outline | ❌ read-only |
|
|
33
|
-
| `lsp_signature <file> <line> <character>` | Signature help (parameters and documentation) inside a call | ❌ read-only |
|
|
34
|
-
| `lsp_inlay_hints <file> [range?]` | Type annotations and parameter-name hints from the server | ❌ read-only |
|
|
35
|
-
| `lsp_rename <file> <line> <character> <new_name>` | Server-verified symbol rename, applied workspace-wide with per-file diffs | ✅ via `fs/write-intent` + sandbox policy |
|
|
32
|
+
## What you get
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
`dsh-lsp-actions` mounts as a single host row (`id: lsp-actions`, `name: dsh-lsp-actions`, `inject: [tools, fs, subprocess]`). The official DeepSeek Harness `ctx.lsp` seam covers **navigation** (go-to-definition, references, implementation, hover); this plugin completes the **action surface** — the feedback loop an agent needs while it writes and fixes code:
|
|
35
|
+
|
|
36
|
+
1. **Eight `lsp_*` tools** — diagnostics, formatting, completion, code actions, symbols, signature help, inlay hints, and rename, all served by the same language servers your IDE uses.
|
|
37
|
+
2. **Editor action protocol v1** — a stable JSON-RPC surface (`lsp.actions.list` / `lsp.actions.run` / `lsp.events`) that lets any editor (VS Code first) consume those capabilities directly.
|
|
38
|
+
3. **Real-server verification** — a real `typescript-language-server` run is part of the test suite (self-contained, CI on Node 22/24 across Linux, Windows, and macOS), not just mocks.
|
|
38
39
|
|
|
39
40
|
## Quick start
|
|
40
41
|
|
|
41
42
|
```sh
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
# 1. install the bundle into your profile
|
|
44
|
+
dsh plugin --profile web add "github:PerryLink/dsh-lsp-actions#main"
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
#
|
|
49
|
-
-
|
|
50
|
-
- id: lsp-actions
|
|
51
|
-
name: dsh-lsp-actions
|
|
52
|
-
inject: [tools, fs, subprocess]
|
|
53
|
-
config:
|
|
54
|
-
servers:
|
|
55
|
-
ts:
|
|
56
|
-
command: typescript-language-server
|
|
57
|
-
args: [--stdio]
|
|
58
|
-
extensionToLanguage:
|
|
59
|
-
".ts": typescript
|
|
60
|
-
formattingOptions: { tabSize: 2, insertSpaces: true }
|
|
61
|
-
py:
|
|
62
|
-
command: pyright-langserver
|
|
63
|
-
args: [--stdio]
|
|
64
|
-
extensionToLanguage:
|
|
65
|
-
".py": python
|
|
66
|
-
maxDiagnostics: 200
|
|
67
|
-
maxCompletionItems: 20
|
|
68
|
-
maxCodeActions: 50
|
|
69
|
-
maxSymbols: 100
|
|
70
|
-
maxSignatures: 10
|
|
71
|
-
maxInlayHints: 200
|
|
72
|
-
maxResultChars: 16000
|
|
73
|
-
timeoutMs: 60000
|
|
46
|
+
# or from npm (published releases)
|
|
47
|
+
dsh plugin --profile web add dsh-lsp-actions
|
|
48
|
+
|
|
49
|
+
# 2. restart and verify the row
|
|
50
|
+
dsh --profile web --dump-config | grep -A3 'id: lsp-actions'
|
|
74
51
|
```
|
|
75
52
|
|
|
76
|
-
|
|
53
|
+
## Install & uninstall
|
|
54
|
+
|
|
55
|
+
- **git channel** (latest `main`): `dsh plugin --profile web add "github:PerryLink/dsh-lsp-actions#main"` — the `prepare` script builds (`tsc --noEmitOnError`).
|
|
56
|
+
- **npm channel** (published releases): `dsh plugin --profile web add dsh-lsp-actions`.
|
|
57
|
+
- **tarball channel**: `pnpm pack` in this repo, then `dsh plugin --profile web add ./dsh-lsp-actions-<version>.tgz`.
|
|
58
|
+
- **uninstall**: `dsh plugin --profile web remove dsh-lsp-actions` (or remove the row from the profile patch).
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. `cordis.patch.yml` documents each key inline.
|
|
63
|
+
|
|
64
|
+
| Key | Default | Meaning |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `servers` | `{}` | Named language servers; an empty table activates no servers |
|
|
67
|
+
| `editor.enabled` | `false` | Serve the editor action protocol over JSON-RPC stdio (headless backend only) |
|
|
68
|
+
| `editor.requestTimeoutMs` | `60000` | Per-run timeout budget (ms) for the editor protocol |
|
|
69
|
+
| `editor.diagnosticsCacheMaxFiles` | `64` | Bounded LRU diagnostics-cache size (files) |
|
|
70
|
+
| `maxDiagnostics` | `200` | Diagnostics cap per result |
|
|
71
|
+
| `maxCompletionItems` | `20` | Completion-items cap per result |
|
|
72
|
+
| `maxCodeActions` | `50` | Code-actions cap per result |
|
|
73
|
+
| `maxSymbols` | `100` | Symbol-results cap |
|
|
74
|
+
| `maxSignatures` | `10` | Signature-help cap |
|
|
75
|
+
| `maxInlayHints` | `200` | Inlay-hints cap |
|
|
76
|
+
| `maxResultChars` | `16000` | Rendered-result cap (chars) |
|
|
77
|
+
| `maxDocumentBytes` | `4000000` | Document-read cap (bytes) |
|
|
78
|
+
| `timeoutMs` | `60000` | Per-call timeout, enforced by the official timeout policy |
|
|
79
|
+
|
|
80
|
+
Each `servers` entry is an `LspServerEntry`: `command` (executable resolved on PATH at load) and `extensionToLanguage` (`".ts"` → `typescript`) are required; optional `fileGlobs`, `args`, `env`, `initializationOptions`, `configuration`, `formattingOptions`, `maxMessageBytes`, `maxStderrBytes`, `killGraceMs`, `shutdownTimeoutMs`, `diagnosticsSettleMs`, `diagnosticsDebounceMs`, and `idleTimeoutMs` (`0` = keep the server process alive) tune the built-in stdio client.
|
|
81
|
+
|
|
82
|
+
## Tools & surfaces
|
|
83
|
+
|
|
84
|
+
| Surface | Kind | Notes |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `lsp_diagnostics` | tool | `<file>` — compiler/analyzer errors, warnings, and hints with severity, range, message, and source server (read-only) |
|
|
87
|
+
| `lsp_format` | tool | `<file> [range?]` — formats a file/selection through the language server and applies it, returning the diff (writes via `fs/write-intent`) |
|
|
88
|
+
| `lsp_completion` | tool | `<file> <line> <character>` — completion suggestions at a cursor position, including the insertion text (read-only) |
|
|
89
|
+
| `lsp_code_action` | tool | `<file> [range?] [only?]` — server-verified quickfixes/refactorings with their edits, for a range or the first diagnostic (reference-only) |
|
|
90
|
+
| `lsp_symbols` | tool | `<query?> <file_path?>` — workspace-wide symbol search by name, or one file's outline (read-only) |
|
|
91
|
+
| `lsp_signature` | tool | `<file> <line> <character>` — signature help (parameters and documentation) inside a call (read-only) |
|
|
92
|
+
| `lsp_inlay_hints` | tool | `<file> [range?]` — type annotations and parameter-name hints from the server (read-only) |
|
|
93
|
+
| `lsp_rename` | tool | `<file> <line> <character> <new_name>` — server-verified rename, applied workspace-wide with per-file diffs (writes via `fs/write-intent`) |
|
|
94
|
+
| `lsp.actions.*` | protocol | Editor action protocol v1: `lsp.actions.list` / `lsp.actions.run` / `lsp.events` over JSON-RPC |
|
|
95
|
+
| `examples/vscode/` | extension | UI-only VS Code extension plus the headless backend composition it connects to |
|
|
96
|
+
|
|
97
|
+
## Editor action protocol v1
|
|
98
|
+
|
|
99
|
+
When `editor.enabled: true` is set in a dedicated headless composition, `dsh-lsp-actions` serves a stable editor protocol over newline-delimited JSON-RPC 2.0 (the same wire framing as the official SDK/ACP transports):
|
|
100
|
+
|
|
101
|
+
| Method | What it does |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `lsp.actions.list` | Returns the `lsp-actions/v1` protocol version, the action catalog (`diagnostics.get`, `completion.get`, `quickfix.apply`, `format` — each flagged `writes`), and the addressable DSH sessions |
|
|
104
|
+
| `lsp.actions.run` | Executes one action with a structured `{ requestId, action, status, result \| error }` envelope; errors carry the stable `LSP_ACTION_*` codes |
|
|
105
|
+
| `lsp.events` | Subscribes to the streamed `lsp.event` notifications: `diagnostics.updated`, `action.status`, `file.changed`, `sessions.changed` |
|
|
106
|
+
|
|
107
|
+
All write actions (`quickfix.apply`, `format`) go through the **official permission presets and approval**: a `read-only` session is refused with `LSP_ACTION_READ_ONLY` before any server round-trip, edits ride the `fs/write-intent` waterfall, and the `sandbox_permissions` + `justification` escalation pair resolves through the official `approveEscalation` ask (fail-closed when no answerer can decide). Full wire spec, bilingual: [`docs/editor-protocol.md`](docs/editor-protocol.md) · [`docs/editor-protocol.zh-CN.md`](docs/editor-protocol.zh-CN.md).
|
|
108
|
+
|
|
109
|
+
**Versioning and the backward-compatibility promise**
|
|
77
110
|
|
|
78
|
-
|
|
111
|
+
- The protocol is versioned — `lsp.actions.list` returns `protocol: "lsp-actions/v1"`, `version: 1`. **v1 is frozen:** field names, action ids, event kinds, and error codes stay stable forever.
|
|
112
|
+
- Evolution is **additive only**: new actions, fields, and event kinds arrive without a version bump; existing semantics never change in place; a breaking change ships under a new `protocol` version, which servers may serve side by side.
|
|
113
|
+
- Clients must ignore unknown fields, unknown event kinds, and unknown actions, and route on the stable error `code`, never on message text.
|
|
79
114
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
**Error codes**
|
|
116
|
+
|
|
117
|
+
Every failure carries a stable `code`; models and callers route on the code, never on message text.
|
|
118
|
+
|
|
119
|
+
| Code | Meaning |
|
|
120
|
+
|---|---|
|
|
121
|
+
| `LSP_ACTION_UNAVAILABLE` | No server entry and no seam provider handles this file |
|
|
122
|
+
| `LSP_ACTION_UNSUPPORTED` | The server (or seam provider) does not advertise the operation |
|
|
123
|
+
| `LSP_ACTION_SERVER_FAILED` | The server failed (with its stderr tail); startup failures retry once |
|
|
124
|
+
| `LSP_ACTION_MALFORMED_RESPONSE` | The server sent a structurally invalid payload |
|
|
125
|
+
| `LSP_ACTION_CONFLICT` | The file changed since it was read, or the edits overlap / go out of bounds / leave the workspace |
|
|
126
|
+
| `LSP_ACTION_READ_ONLY` | The session's sandbox mode forbids the formatting/rename write |
|
|
127
|
+
| `LSP_ACTION_WORKSPACE_REQUIRED` | The calling session has no workspace cwd to root the server in |
|
|
128
|
+
| `LSP_ACTION_NO_SYMBOL` | The server found no renameable symbol at the cursor position |
|
|
129
|
+
| `LSP_ACTION_UNKNOWN` | Editor protocol: unknown action id, or no code action matched `title`/`index` |
|
|
130
|
+
| `LSP_ACTION_INVALID_ARGS` | Editor protocol: malformed action parameters |
|
|
131
|
+
| `LSP_ACTION_APPROVAL_UNAVAILABLE` | Editor protocol: the approval path could not grant a wider sandbox mode (fail-closed) |
|
|
132
|
+
| `LSP_PROTOCOL_VERSION_UNSUPPORTED` | Editor protocol: the declared protocol version is not supported |
|
|
133
|
+
|
|
134
|
+
## VS Code extension
|
|
135
|
+
|
|
136
|
+
[`examples/vscode/`](examples/vscode/) ships a **UI-only** extension (sidebar with the DSH sessions, the diagnostics list, one-click quickfix apply, open-at-range, and format) plus the headless backend composition (`backend/cordis.yml`) it connects to over ACP-style JSON-RPC. The extension implements zero LSP logic — every capability and every byte written belongs to the plugin. Install steps, settings, and the demo-gif recording script are in [`examples/vscode/README.md`](examples/vscode/README.md).
|
|
137
|
+
|
|
138
|
+

|
|
139
|
+
|
|
140
|
+
## Permissions & data
|
|
141
|
+
|
|
142
|
+
- **Permissions**: formatting and rename ride the official permission presets and approval — the `fs/write-intent` waterfall and the `sandbox_permissions` / `justification` escalation pair resolved through `ctx.approval`. The plugin declares `fs:read`, `fs:write`, `subprocess:spawn`, and `network:none` in its workshop manifest.
|
|
143
|
+
- **Data**: nothing is stored on disk; tool results live only in the session log (no cross-session persistence). The editor protocol keeps one bounded in-memory LRU diagnostics cache, freshness-stamped and never persisted across restarts.
|
|
144
|
+
- **No network**: the plugin makes no network requests; it talks to language servers over local subprocess stdio.
|
|
145
|
+
|
|
146
|
+
## Security boundaries
|
|
147
|
+
|
|
148
|
+
- **Read-only by default.** Six of the eight tools are reference-only; only `lsp_format` and `lsp_rename` mutate, and they do so as real `write`/`edit` mutations.
|
|
149
|
+
- **Official seams, not re-implemented.** Every byte goes through the `fs/write-intent` waterfall (observation → guarded write → observation) and the per-call sandbox policy; escalation matches the official `write`/`edit` tools.
|
|
150
|
+
- **Fail loud, fast, structured.** Empty `servers` + no `ctx.lsp` seam → `LSP_ACTION_UNAVAILABLE`; read-only sessions → `LSP_ACTION_READ_ONLY` before any server round-trip; command forms are reported and never executed.
|
|
151
|
+
- **Conflicts never clobber.** A file changed on disk after it was read fails with `LSP_ACTION_CONFLICT`; `lsp_rename` pre-flights every edited file before the first write.
|
|
152
|
+
- **Bounded work.** Result caps, byte caps, and the platform's timeout policy bound every call; the diagnostics cache is a bounded LRU.
|
|
153
|
+
- **Nothing cached on the model path.** Tool results live only in the session log; the diagnostics cache never persists across restarts.
|
|
87
154
|
- **Bad servers fail loudly.** A missing executable fails at load; a server that dies at startup fails the call with `LSP_ACTION_SERVER_FAILED` plus its stderr tail (after one fresh-spawn retry).
|
|
155
|
+
- **Prompt hygiene.** The plugin injects no persona or prompt prose into the session system prompt — its model-facing surface is the eight tool schemas.
|
|
88
156
|
|
|
89
157
|
## Architecture
|
|
90
158
|
|
|
91
159
|
Actions run **official-seam-first** and fall back to the plugin's own minimal stdio client:
|
|
92
160
|
|
|
93
|
-
```
|
|
161
|
+
```text
|
|
94
162
|
lsp_diagnostics / lsp_format / lsp_completion / lsp_code_action /
|
|
95
163
|
lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
|
|
96
164
|
│
|
|
@@ -101,83 +169,56 @@ lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
|
|
|
101
169
|
built-in stdio client ← servers table (ctx.subprocess.spawn + JSON-RPC)
|
|
102
170
|
```
|
|
103
171
|
|
|
104
|
-
The seam extension is proposed upstream (`upstream/lsp-action-seam.patch`, PR description in `upstream/PR-description.md`). Once it lands, the plugin keeps working unchanged — the built-in client simply stops being used. The built-in client stays as the standalone fallback for the `servers` table. Full research and design notes: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md).
|
|
105
|
-
|
|
106
|
-
## Configuration reference
|
|
107
|
-
|
|
108
|
-
```ts
|
|
109
|
-
interface Config {
|
|
110
|
-
/** Named language servers; empty = the plugin's own client serves nothing. */
|
|
111
|
-
servers?: Record<string, LspServerEntry>
|
|
112
|
-
maxDiagnostics?: number // default 200
|
|
113
|
-
maxCompletionItems?: number // default 20
|
|
114
|
-
maxCodeActions?: number // default 50
|
|
115
|
-
maxSymbols?: number // default 100
|
|
116
|
-
maxSignatures?: number // default 10
|
|
117
|
-
maxInlayHints?: number // default 200
|
|
118
|
-
maxResultChars?: number // default 16000 (complete rendered result cap)
|
|
119
|
-
maxDocumentBytes?: number // default 4000000
|
|
120
|
-
timeoutMs?: number // default 60000 (enforced by the official timeout policy)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
interface LspServerEntry {
|
|
124
|
-
command: string // executable, resolved on PATH at load
|
|
125
|
-
extensionToLanguage: Record<string, string> // ".ts" → "typescript"
|
|
126
|
-
fileGlobs?: string[] // optional; glob matches beat the extension map
|
|
127
|
-
args?: string[] // no shell
|
|
128
|
-
env?: Record<string, string>
|
|
129
|
-
initializationOptions?: unknown
|
|
130
|
-
configuration?: unknown // object form answers workspace/configuration per section
|
|
131
|
-
formattingOptions?: unknown // e.g. { tabSize: 2, insertSpaces: true }
|
|
132
|
-
maxMessageBytes?: number // default 16000000
|
|
133
|
-
maxStderrBytes?: number // default 1000000
|
|
134
|
-
killGraceMs?: number // default 2000
|
|
135
|
-
shutdownTimeoutMs?: number // default 5000
|
|
136
|
-
diagnosticsSettleMs?: number // default 2000 (push-only diagnostics window)
|
|
137
|
-
diagnosticsDebounceMs?: number // default 250 (quiet period after the last pushed batch)
|
|
138
|
-
idleTimeoutMs?: number // default 0 (0 = keep the server process alive)
|
|
139
|
-
}
|
|
140
|
-
```
|
|
172
|
+
The seam extension is proposed upstream (`upstream/lsp-action-seam.patch`, PR description in `upstream/PR-description.md`). Once it lands, the plugin keeps working unchanged — the built-in client simply stops being used. The built-in client stays as the standalone fallback for the `servers` table. The **editor protocol** rides the same runner, the same write path, and the same permission machinery. Full research and design notes: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md).
|
|
141
173
|
|
|
142
|
-
|
|
174
|
+
## Known limitations
|
|
143
175
|
|
|
144
|
-
Every
|
|
176
|
+
- **Transient documents.** Every action opens the file, runs one request, and closes it again (matching the official stdio host). Project-based servers that require a resident open file for document-free requests (tsls refuses `workspace/symbol` without one) are served by passing `file_path` to `lsp_symbols`. tsls also answers `textDocument/signatureHelp` with `null` under this lifecycle; other servers (gopls, pyright, rust-analyzer) serve it normally.
|
|
177
|
+
- **Range formatting requires the server's range provider.** Servers that only advertise whole-document formatting fail range requests with `LSP_ACTION_UNSUPPORTED`.
|
|
178
|
+
- **Rename applies text edits only.** Resource operations (create/delete/rename files) in a server's rename answer are refused with `LSP_ACTION_UNSUPPORTED`, and edits outside the workspace fail as `LSP_ACTION_CONFLICT` before anything is written.
|
|
145
179
|
|
|
146
|
-
|
|
147
|
-
| --- | --- |
|
|
148
|
-
| `LSP_ACTION_UNAVAILABLE` | No server entry and no seam provider handles this file. |
|
|
149
|
-
| `LSP_ACTION_UNSUPPORTED` | The server (or seam provider) does not advertise the operation. |
|
|
150
|
-
| `LSP_ACTION_SERVER_FAILED` | The server failed (with its stderr tail); startup failures retry once. |
|
|
151
|
-
| `LSP_ACTION_MALFORMED_RESPONSE` | The server sent a structurally invalid payload. |
|
|
152
|
-
| `LSP_ACTION_CONFLICT` | The file changed since it was read, or the server's edits overlap / go out of bounds / leave the workspace. |
|
|
153
|
-
| `LSP_ACTION_READ_ONLY` | The session's sandbox mode forbids the formatting/rename write. |
|
|
154
|
-
| `LSP_ACTION_WORKSPACE_REQUIRED` | The calling session has no workspace cwd to root the server in. |
|
|
155
|
-
| `LSP_ACTION_NO_SYMBOL` | The server found no renameable symbol at the cursor position. |
|
|
180
|
+
## Development
|
|
156
181
|
|
|
157
|
-
|
|
182
|
+
```sh
|
|
183
|
+
pnpm install # node ^22.19 || >=24
|
|
184
|
+
pnpm run lint # oxlint over src/ and tests/
|
|
185
|
+
pnpm test # vitest: unit + fixture-server integration + editor-protocol e2e + real tsls e2e
|
|
186
|
+
pnpm run test:coverage # coverage gate
|
|
187
|
+
pnpm build # tsc --noEmitOnError → lib/
|
|
188
|
+
pnpm run prepare # tsc --noEmitOnError (runs on install)
|
|
189
|
+
pnpm run prepublishOnly # tsc --noEmitOnError (runs before publish)
|
|
190
|
+
```
|
|
158
191
|
|
|
159
|
-
|
|
192
|
+
## Topics
|
|
160
193
|
|
|
161
|
-
|
|
194
|
+
`dsh`, `dsh-plugin`, `deepseek-harness`, `lsp`, `language-server`, `diagnostics`, `formatting`, `completion`, `code-action`, `symbols`, `signature-help`, `inlay-hints`, `rename`, `refactor`, `ide`, `editor`, `vscode`, `acp`, `json-rpc`
|
|
162
195
|
|
|
163
|
-
|
|
164
|
-
- **Range formatting requires the server's range provider.** Servers that only advertise whole-document formatting fail range requests with `LSP_ACTION_UNSUPPORTED`.
|
|
165
|
-
- **Rename applies text edits only.** Resource operations (create/delete/rename files) in a server's rename answer are refused with `LSP_ACTION_UNSUPPORTED`, and edits outside the workspace fail as `LSP_ACTION_CONFLICT` before anything is written. On `utf-8`/`utf-32` servers, cross-file rename positions are decoded by reading each edited file; an unreadable edited file fails the call as a conflict instead of mis-decoding positions.
|
|
196
|
+
## Contributors
|
|
166
197
|
|
|
167
|
-
|
|
198
|
+
- [@PerryLink](https://github.com/PerryLink) — creator and maintainer: the LSP action client and server lifecycle, all eight tools, the editor action protocol, tests, CI, and the five-language docs.
|
|
168
199
|
|
|
169
|
-
|
|
170
|
-
pnpm install
|
|
171
|
-
pnpm run lint # oxlint over src/ and tests/
|
|
172
|
-
pnpm test # 240+ tests: unit + fixture-server integration + real tsls e2e
|
|
173
|
-
pnpm run test:coverage # gates: lines/statements/functions ≥ 90%, branches ≥ 85%
|
|
174
|
-
pnpm build # emits lib/
|
|
175
|
-
```
|
|
200
|
+
## PerryLink DSH Plugin Family
|
|
176
201
|
|
|
177
|
-
|
|
202
|
+
This project is one of the [15 DeepSeek Harness plugins](https://github.com/PerryLink) maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
|
|
178
203
|
|
|
179
|
-
|
|
204
|
+
| Plugin | One-liner |
|
|
205
|
+
|---|---|
|
|
206
|
+
| [dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel) | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors |
|
|
207
|
+
| [dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck) | Engineering-discipline guard: requirements grill, test gates, adversary review |
|
|
208
|
+
| [dsh-background-agents](https://github.com/PerryLink/dsh-background-agents) | Durable background child agents with a Web UI sidebar, messaging and interrupt |
|
|
209
|
+
| **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers |
|
|
210
|
+
| [dsh-output-styles](https://github.com/PerryLink/dsh-output-styles) | Claude Code outputStyles-equivalent runtime style switching |
|
|
211
|
+
| [dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind) | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore |
|
|
212
|
+
| [dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules) | Claude Code-style declarative allow/deny/ask permission rules with audit |
|
|
213
|
+
| [dsh-auto-review](https://github.com/PerryLink/dsh-auto-review) | Second-model auto-review on the approval chain, fail-closed by default |
|
|
214
|
+
| [dsh-memento](https://github.com/PerryLink/dsh-memento) | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool |
|
|
215
|
+
| [dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security) | Security-audit skill pack: secret scan, dependency and supply-chain review |
|
|
216
|
+
| [dsh-session-pin](https://github.com/PerryLink/dsh-session-pin) | Pin sessions in the Web sidebar with durable ordering |
|
|
217
|
+
| [dsh-composer-history](https://github.com/PerryLink/dsh-composer-history) | Terminal-style input history for the web composer: arrows, Ctrl+R search |
|
|
218
|
+
| [dsh-github](https://github.com/PerryLink/dsh-github) | GitHub PR/issues integration for DSH, every write gated by approval |
|
|
219
|
+
| [dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide) | Plugin-development knowledge base as an on-demand agent skill |
|
|
220
|
+
| [dsh-claude-move](https://github.com/PerryLink/dsh-claude-move) | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH |
|
|
180
221
|
|
|
181
222
|
## License
|
|
182
223
|
|
|
183
|
-
[Apache License 2.0](LICENSE)
|
|
224
|
+
[Apache License 2.0](LICENSE) © 2026 dsh-lsp-actions contributors
|