dsh-lsp-actions 0.5.19 → 0.5.21
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 +9 -0
- package/LICENSE +0 -0
- package/PRIVACY.md +0 -0
- package/README.en.md +520 -0
- package/README.es.md +520 -0
- package/README.hi.md +520 -0
- package/README.md +313 -235
- package/README.pt.md +520 -0
- package/cordis.patch.yml +0 -0
- package/docs/assets/dsh-lsp-actions-demo.gif +0 -0
- package/docs/assets/dsh-lsp-actions-demo.png +0 -0
- package/docs/assets/dsh-lsp-actions-flow-dark.svg +35 -0
- package/docs/assets/dsh-lsp-actions-flow-light.svg +35 -0
- package/docs/assets/dsh-lsp-actions-flow-v5-dark.svg +136 -0
- package/docs/assets/dsh-lsp-actions-flow-v5-light.svg +136 -0
- package/docs/assets/dsh-lsp-actions-flow.svg +0 -0
- package/docs/assets/dsh-lsp-actions-hero-en-dark.webp +0 -0
- package/docs/assets/dsh-lsp-actions-hero-en-light.webp +0 -0
- package/docs/assets/dsh-lsp-actions-hero-zh-dark.webp +0 -0
- package/docs/assets/dsh-lsp-actions-hero-zh-light.webp +0 -0
- package/docs/assets/dsh-lsp-actions-hero.png +0 -0
- package/docs/editor-protocol.md +0 -0
- package/docs/editor-protocol.zh-CN.md +0 -0
- package/docs/seam-extension-notes.md +0 -0
- package/examples/vscode/README.md +0 -0
- package/examples/vscode/README.zh-CN.md +0 -0
- package/examples/vscode/backend/bin.mjs +0 -0
- package/examples/vscode/backend/cordis.yml +0 -0
- package/examples/vscode/backend/package.json +0 -0
- package/examples/vscode/extension/package.json +0 -0
- package/examples/vscode/extension/src/client.js +0 -0
- package/examples/vscode/extension/src/extension.js +0 -0
- package/examples/vscode/extension/src/views.js +0 -0
- package/icon.svg +0 -0
- package/lib/abort.d.ts +0 -0
- package/lib/abort.d.ts.map +0 -0
- package/lib/abort.js +0 -0
- package/lib/abort.js.map +0 -0
- package/lib/call-id.d.ts +0 -0
- package/lib/call-id.d.ts.map +0 -0
- package/lib/call-id.js +0 -0
- package/lib/call-id.js.map +0 -0
- package/lib/client.d.ts +0 -0
- package/lib/client.d.ts.map +0 -0
- package/lib/client.js +0 -0
- package/lib/client.js.map +0 -0
- package/lib/connection.d.ts +0 -0
- package/lib/connection.d.ts.map +0 -0
- package/lib/connection.js +0 -0
- package/lib/connection.js.map +0 -0
- package/lib/editor/actions.d.ts +0 -0
- package/lib/editor/actions.d.ts.map +0 -0
- package/lib/editor/actions.js +0 -0
- package/lib/editor/actions.js.map +0 -0
- package/lib/editor/cache.d.ts +0 -0
- package/lib/editor/cache.d.ts.map +0 -0
- package/lib/editor/cache.js +0 -0
- package/lib/editor/cache.js.map +0 -0
- package/lib/editor/server.d.ts +0 -0
- package/lib/editor/server.d.ts.map +0 -0
- package/lib/editor/server.js +0 -0
- package/lib/editor/server.js.map +0 -0
- package/lib/editor/service.d.ts +0 -0
- package/lib/editor/service.d.ts.map +0 -0
- package/lib/editor/service.js +0 -0
- package/lib/editor/service.js.map +0 -0
- package/lib/editor/transport.d.ts +0 -0
- package/lib/editor/transport.d.ts.map +0 -0
- package/lib/editor/transport.js +0 -0
- package/lib/editor/transport.js.map +0 -0
- package/lib/editor/types.d.ts +0 -0
- package/lib/editor/types.d.ts.map +0 -0
- package/lib/editor/types.js +0 -0
- package/lib/editor/types.js.map +0 -0
- package/lib/edits.d.ts +0 -0
- package/lib/edits.d.ts.map +0 -0
- package/lib/edits.js +0 -0
- package/lib/edits.js.map +0 -0
- package/lib/extension.d.ts +0 -0
- package/lib/extension.d.ts.map +0 -0
- package/lib/extension.js +0 -0
- package/lib/extension.js.map +0 -0
- package/lib/extra-tools.d.ts +0 -0
- package/lib/extra-tools.d.ts.map +0 -0
- package/lib/extra-tools.js +0 -0
- package/lib/extra-tools.js.map +0 -0
- package/lib/framing.d.ts +0 -0
- package/lib/framing.d.ts.map +0 -0
- package/lib/framing.js +0 -0
- package/lib/framing.js.map +0 -0
- package/lib/host.d.ts +0 -0
- package/lib/host.d.ts.map +0 -0
- package/lib/host.js +0 -0
- package/lib/host.js.map +0 -0
- package/lib/index.d.ts +0 -0
- package/lib/index.d.ts.map +0 -0
- package/lib/index.js +0 -0
- package/lib/index.js.map +0 -0
- package/lib/project.d.ts +0 -0
- package/lib/project.d.ts.map +0 -0
- package/lib/project.js +0 -0
- package/lib/project.js.map +0 -0
- package/lib/render.d.ts +0 -0
- package/lib/render.d.ts.map +0 -0
- package/lib/render.js +0 -0
- package/lib/render.js.map +0 -0
- package/lib/runner.d.ts +0 -0
- package/lib/runner.d.ts.map +0 -0
- package/lib/runner.js +0 -0
- package/lib/runner.js.map +0 -0
- package/lib/sandbox.d.ts +0 -0
- package/lib/sandbox.d.ts.map +0 -0
- package/lib/sandbox.js +0 -0
- package/lib/sandbox.js.map +0 -0
- package/lib/seam.d.ts +0 -0
- package/lib/seam.d.ts.map +0 -0
- package/lib/seam.js +0 -0
- package/lib/seam.js.map +0 -0
- package/lib/servers.d.ts +0 -0
- package/lib/servers.d.ts.map +0 -0
- package/lib/servers.js +0 -0
- package/lib/servers.js.map +0 -0
- package/lib/session-cwd.d.ts +0 -0
- package/lib/session-cwd.d.ts.map +0 -0
- package/lib/session-cwd.js +0 -0
- package/lib/session-cwd.js.map +0 -0
- package/lib/tools.d.ts +0 -0
- package/lib/tools.d.ts.map +0 -0
- package/lib/tools.js +0 -0
- package/lib/tools.js.map +0 -0
- package/lib/translate.d.ts +0 -0
- package/lib/translate.d.ts.map +0 -0
- package/lib/translate.js +0 -0
- package/lib/translate.js.map +0 -0
- package/lib/vocabulary.d.ts +0 -0
- package/lib/vocabulary.d.ts.map +0 -0
- package/lib/vocabulary.js +0 -0
- package/lib/vocabulary.js.map +0 -0
- package/package.json +35 -20
- package/README-es.md +0 -445
- package/README-hi.md +0 -445
- package/README-pt.md +0 -445
- package/README-zh.md +0 -445
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.20] - 2026-11-13
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Dependency hygiene: `@types/node` 26.6.5 -> 26.6.6 and `oxlint` 1.89.0 -> 1.91.0, with `pnpm-lock.yaml` re-resolved (dependabot #34).
|
|
8
|
+
- Documentation: the five READMEs follow the family layout (badges, intro, five languages), carry a dedicated hero and the semantic flow diagram, and link the plugin toolchain.
|
|
9
|
+
|
|
10
|
+
No runtime, API, or behaviour change in this release.
|
|
11
|
+
|
|
3
12
|
## [0.5.18] - 2026-11-05
|
|
4
13
|
|
|
5
14
|
### Changed
|
package/LICENSE
CHANGED
|
File without changes
|
package/PRIVACY.md
CHANGED
|
File without changes
|
package/README.en.md
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/dsh-lsp-actions-hero-en-dark.webp">
|
|
5
|
+
<img src="docs/assets/dsh-lsp-actions-hero-en-light.webp" width="100%" alt="dsh-lsp-actions: eight tools and the editor protocol share one ActionRunner — diagnostics, format, completion, code action, symbols, signature, inlay hints and rename each map to a real language-server method; six read-only, two write">
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
# dsh-lsp-actions
|
|
9
|
+
|
|
10
|
+
**Let your agent write and fix code against real language servers — diagnostics, formatting, completion, code actions, symbols, signature help, inlay hints, and rename in one action surface.**
|
|
11
|
+
|
|
12
|
+
The LSP action surface for DeepSeek Harness: the official `ctx.lsp` seam covers navigation, this plugin completes the action loop, and the stable editor action protocol (`lsp.actions.*`) lets editors such as VS Code use it as their IDE backend.
|
|
13
|
+
|
|
14
|
+
[Install](#three-step-setup) · [Configuration](#configuration) · [FAQ](#faq) · [简体中文](README.md) · [English](README.en.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
15
|
+
|
|
16
|
+
[](LICENSE)
|
|
17
|
+
[](#compatibility)
|
|
18
|
+
[](https://www.npmjs.com/package/dsh-lsp-actions)
|
|
19
|
+
[](https://github.com/PerryLink/dsh-lsp-actions/actions/workflows/ci.yml)
|
|
20
|
+
[](#compatibility)
|
|
21
|
+
|
|
22
|
+
[](https://github.com/PerryLink/dsh-lsp-actions/stargazers)
|
|
23
|
+
[](https://www.npmjs.com/package/dsh-lsp-actions)
|
|
24
|
+
[](https://dshfind.com/plugins/PerryLink/dsh-lsp-actions?ref=badge)
|
|
25
|
+
[](https://securityscorecards.dev/viewer/?uri=github.com/PerryLink/dsh-lsp-actions)
|
|
26
|
+
[](https://dsh.market/)
|
|
27
|
+
[](https://gitee.com/perrylink/dsh-lsp-actions)
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
dsh plugin --profile <name> add dsh-lsp-actions
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<sub>Community plugin, not affiliated with DeepSeek. Canonical repository: <https://github.com/PerryLink/dsh-lsp-actions> (Gitee is a mirror).</sub>
|
|
36
|
+
|
|
37
|
+
## What it is
|
|
38
|
+
|
|
39
|
+
`dsh-lsp-actions` connects the feedback loop an agent needs while it writes code to real language servers: diagnostics, formatting, completion, code actions, symbols, signature help, inlay hints, and rename are answered by the same servers your IDE uses (`typescript-language-server`, gopls, pyright, rust-analyzer, ...). The official `ctx.lsp` seam covers navigation (go-to-definition, references, implementation, hover) only; this plugin completes the action surface — and packages it as the stable editor action protocol (`lsp.actions.*`), so editors such as VS Code can consume those capabilities without implementing LSP themselves. It mounts as a single host row (`id: lsp-actions`, `inject: [tools, fs, subprocess]`), spawns server processes lazily, and routes every write through the official `fs/write-intent` waterfall and sandbox approval.
|
|
40
|
+
|
|
41
|
+
<picture>
|
|
42
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/dsh-lsp-actions-flow-v5-dark.svg">
|
|
43
|
+
<img src="docs/assets/dsh-lsp-actions-flow-v5-light.svg" width="100%" alt="dsh-lsp-actions structure: a request/response round trip — tools and the editor protocol feed ActionRunner, which prefers the ctx.lsp seam and falls back to the servers route plus built-in stdio client; the answer is normalised and bounded on the way back, and only format and rename pass the write valve">
|
|
44
|
+
</picture>
|
|
45
|
+
|
|
46
|
+
## Three-step setup
|
|
47
|
+
|
|
48
|
+
1. **Install** (pick one channel):
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
# git channel (latest main; the prepare script builds lib/ with tsc)
|
|
52
|
+
dsh plugin --profile web add github:PerryLink/dsh-lsp-actions
|
|
53
|
+
# npm channel (published releases)
|
|
54
|
+
dsh plugin --profile web add dsh-lsp-actions
|
|
55
|
+
# tarball channel: pnpm pack in this repo, then
|
|
56
|
+
dsh plugin --profile web add ./dsh-lsp-actions-<version>.tgz
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
2. **Minimal config** (the default `servers: {}` activates no server; add at least one entry):
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
- insert:
|
|
63
|
+
- id: lsp-actions
|
|
64
|
+
name: dsh-lsp-actions
|
|
65
|
+
config:
|
|
66
|
+
servers:
|
|
67
|
+
typescript:
|
|
68
|
+
command: typescript-language-server
|
|
69
|
+
args: ["--stdio"]
|
|
70
|
+
extensionToLanguage: { ".ts": typescript, ".tsx": typescriptreact }
|
|
71
|
+
projectMarkers: ["package.json", "tsconfig.json"]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
3. **Verify it mounts**:
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
dsh --profile web --dump-config | grep -A3 'id: lsp-actions'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
> lsp_diagnostics a.ts
|
|
82
|
+
a.ts:1:3 [Error] boom [ts 2304]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Uninstall**: `dsh plugin --profile web remove dsh-lsp-actions` (or remove the row from the profile patch).
|
|
86
|
+
|
|
87
|
+
<details>
|
|
88
|
+
<summary>Install from the DSH Desktop market</summary>
|
|
89
|
+
|
|
90
|
+
Every PerryLink plugin is listed in the built-in DSH Desktop market: **Market → Sources → Add source → paste** `https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json` **→ select**. Installation still requires the market's npm identity check and your confirmation.
|
|
91
|
+
|
|
92
|
+
</details>
|
|
93
|
+
|
|
94
|
+
## Core capabilities
|
|
95
|
+
|
|
96
|
+
This plugin completes the **action surface** only: navigation still comes from the official `ctx.lsp` seam, and actions fall back to the plugin's own minimal stdio client when the seam is absent, of an older vintage, or has no provider for that file.
|
|
97
|
+
|
|
98
|
+
- **Eight `lsp_*` tools** — diagnostics, formatting, completion, code actions, symbols, signature help, inlay hints, and rename, all answered by real language servers rather than mocks.
|
|
99
|
+
- **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.
|
|
100
|
+
- **Real-server verification** — the test suite includes a real `typescript-language-server` run and an editor-protocol e2e; CI runs it on Node 22/24 across Linux, Windows, and macOS.
|
|
101
|
+
- **Writes ride the official path** — `lsp_format` / `lsp_rename` go through the `fs/write-intent` waterfall and the per-call sandbox policy; a read-only session is refused before any server round-trip.
|
|
102
|
+
- **Read-only by default** — six of the eight tools are reference-only; only formatting and rename mutate.
|
|
103
|
+
- **Bounded** — result counts, characters, document bytes, and per-call time all have caps; the diagnostics cache is a bounded LRU.
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
lsp_diagnostics / lsp_format / lsp_completion / lsp_code_action /
|
|
107
|
+
lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
|
|
108
|
+
│
|
|
109
|
+
▼
|
|
110
|
+
ctx.lsp seam (extended: diagnostics / formatDocument / completion)
|
|
111
|
+
│ absent · legacy · no provider for this file
|
|
112
|
+
▼
|
|
113
|
+
built-in stdio client ← servers table (ctx.subprocess.spawn + JSON-RPC)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Tools & surfaces
|
|
117
|
+
|
|
118
|
+
| Surface | Kind | Notes |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `lsp_diagnostics` | tool | `<file>` — compiler/analyzer errors, warnings, and hints with severity, range, message, and source server (read-only) |
|
|
121
|
+
| `lsp_format` | tool | `<file> [range?]` — formats a file/selection through the language server and applies it, returning the diff (writes via `fs/write-intent`) |
|
|
122
|
+
| `lsp_completion` | tool | `<file> <line> <character>` — completion suggestions at a cursor position, including the insertion text (read-only) |
|
|
123
|
+
| `lsp_code_action` | tool | `<file> [range?] [only?]` — server-verified quickfixes/refactorings with their edits, for a range or the first diagnostic (reference-only) |
|
|
124
|
+
| `lsp_symbols` | tool | `<query?> <file_path?>` — workspace-wide symbol search by name, or one file's outline (read-only) |
|
|
125
|
+
| `lsp_signature` | tool | `<file> <line> <character>` — signature help (parameters and documentation) inside a call (read-only) |
|
|
126
|
+
| `lsp_inlay_hints` | tool | `<file> [range?]` — type annotations and parameter-name hints from the server (read-only) |
|
|
127
|
+
| `lsp_rename` | tool | `<file> <line> <character> <new_name>` — server-verified rename, applied workspace-wide with per-file diffs (writes via `fs/write-intent`) |
|
|
128
|
+
| `lsp.actions.*` | protocol | Editor action protocol v1: `lsp.actions.list` / `lsp.actions.run` / `lsp.events` over JSON-RPC |
|
|
129
|
+
| `examples/vscode/` | extension | UI-only VS Code extension plus the headless backend composition it connects to |
|
|
130
|
+
|
|
131
|
+
### Examples
|
|
132
|
+
|
|
133
|
+
These are the plugin's real entry points; install once, then call one.
|
|
134
|
+
|
|
135
|
+
**Detailed example** — command `lsp_diagnostics`, input:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"file_path": "a.ts"
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Output:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
a.ts:1:3 [Error] boom [ts 2304]
|
|
147
|
+
a.ts:3:1 [Hint] hint
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
*Observed from `plugins/dsh-lsp-actions/tests/render.spec.ts:32-37 (exact toBe); tool-level no-result render at plugins/dsh-lsp-actions/tests/tools.spec.ts:150-156`*
|
|
151
|
+
|
|
152
|
+
**Failure branch** — input:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
{"action":"format","requestId":"f1","params":{"filePath":"a.ts","workspaceRoot":"<session-workspace>"}} under a read-only permission preset
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Output:
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
{
|
|
162
|
+
"requestId": "f1",
|
|
163
|
+
"action": "format",
|
|
164
|
+
"status": "failed",
|
|
165
|
+
"error": {
|
|
166
|
+
"code": "LSP_ACTION_READ_ONLY",
|
|
167
|
+
"message": "[sandbox: file access denied under read-only mode]\n[sandbox: escalation available — retry this exact operation once with sandbox_permissions (the narrowest wider mode that suffices) + justification; the approval prompt asks the user]"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
*Observed from `plugins/dsh-lsp-actions/src/tools.ts:213-223; plugins/dsh-lsp-actions/src/editor/actions.ts:320-330; plugins/dsh-lsp-actions/tests/editor-protocol.spec.ts:305-325`*
|
|
173
|
+
|
|
174
|
+
**Brief examples**: `lsp_format` · `lsp_completion`
|
|
175
|
+
|
|
176
|
+
### Editor action protocol v1
|
|
177
|
+
|
|
178
|
+
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):
|
|
179
|
+
|
|
180
|
+
| Method | What it does |
|
|
181
|
+
|---|---|
|
|
182
|
+
| `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 |
|
|
183
|
+
| `lsp.actions.run` | Executes one action with a structured `{ requestId, action, status, result \| error }` envelope; errors carry the stable `LSP_ACTION_*` codes |
|
|
184
|
+
| `lsp.events` | Subscribes to the streamed `lsp.event` notifications: `diagnostics.updated`, `action.status`, `file.changed`, `sessions.changed` |
|
|
185
|
+
|
|
186
|
+
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).
|
|
187
|
+
|
|
188
|
+
**Versioning and the backward-compatibility promise**
|
|
189
|
+
|
|
190
|
+
- 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.
|
|
191
|
+
- 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.
|
|
192
|
+
- Clients must ignore unknown fields, unknown event kinds, and unknown actions, and route on the stable error `code`, never on message text.
|
|
193
|
+
|
|
194
|
+
**Error codes**
|
|
195
|
+
|
|
196
|
+
Every failure carries a stable `code`; models and callers route on the code, never on message text.
|
|
197
|
+
|
|
198
|
+
| Code | Meaning |
|
|
199
|
+
|---|---|
|
|
200
|
+
| `LSP_ACTION_UNAVAILABLE` | No server entry and no seam provider handles this file |
|
|
201
|
+
| `LSP_ACTION_UNSUPPORTED` | The server (or seam provider) does not advertise the operation |
|
|
202
|
+
| `LSP_ACTION_SERVER_FAILED` | The server failed (with its stderr tail); startup failures retry once |
|
|
203
|
+
| `LSP_ACTION_MALFORMED_RESPONSE` | The server sent a structurally invalid payload |
|
|
204
|
+
| `LSP_ACTION_CONFLICT` | The file changed since it was read, or the edits overlap / go out of bounds / leave the workspace |
|
|
205
|
+
| `LSP_ACTION_READ_ONLY` | The session's sandbox mode forbids the formatting/rename write |
|
|
206
|
+
| `LSP_ACTION_WORKSPACE_REQUIRED` | The calling session has no workspace cwd to root the server in |
|
|
207
|
+
| `LSP_ACTION_NO_SYMBOL` | The server found no renameable symbol at the cursor position |
|
|
208
|
+
| `LSP_ACTION_UNKNOWN` | Editor protocol: unknown action id, or no code action matched `title`/`index` |
|
|
209
|
+
| `LSP_ACTION_INVALID_ARGS` | Editor protocol: malformed action parameters |
|
|
210
|
+
| `LSP_ACTION_APPROVAL_UNAVAILABLE` | Editor protocol: the approval path could not grant a wider sandbox mode (fail-closed) |
|
|
211
|
+
| `LSP_PROTOCOL_VERSION_UNSUPPORTED` | Editor protocol: the declared protocol version is not supported |
|
|
212
|
+
|
|
213
|
+
### VS Code extension
|
|
214
|
+
|
|
215
|
+
[`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).
|
|
216
|
+
|
|
217
|
+
### Architecture
|
|
218
|
+
|
|
219
|
+
Actions run **official-seam-first** and fall back to the plugin's own minimal stdio client. The seam extension is proposed upstream ([`upstream/lsp-action-seam.patch`](upstream/lsp-action-seam.patch), PR description in [`upstream/PR-description.md`](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.
|
|
220
|
+
|
|
221
|
+
The action backend is behind a public provider interface — `ActionRunner` (exported from the package) — implemented by the bundled runner and open to third-party providers: the eight tools consume only that interface, never a concrete client. Full research and design notes: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md).
|
|
222
|
+
|
|
223
|
+
## Configuration
|
|
224
|
+
|
|
225
|
+
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.
|
|
226
|
+
|
|
227
|
+
Most-used keys:
|
|
228
|
+
|
|
229
|
+
| Key | Default | Meaning |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| `servers` | `{}` | Named language servers; an empty table activates no servers |
|
|
232
|
+
| `editor.enabled` | `false` | Serve the editor action protocol over JSON-RPC stdio (headless backend only) |
|
|
233
|
+
| `maxDiagnostics` | `200` | Diagnostics cap per result |
|
|
234
|
+
| `maxResultChars` | `16000` | Rendered-result cap (chars) |
|
|
235
|
+
| `maxDocumentBytes` | `4000000` | Document-read cap (bytes) |
|
|
236
|
+
| `timeoutMs` | `60000` | Per-call timeout, enforced by the official timeout policy |
|
|
237
|
+
|
|
238
|
+
<details>
|
|
239
|
+
<summary>Full configuration table (13 keys)</summary>
|
|
240
|
+
|
|
241
|
+
| Key | Default | Meaning |
|
|
242
|
+
|---|---|---|
|
|
243
|
+
| `servers` | `{}` | Named language servers; an empty table activates no servers |
|
|
244
|
+
| `editor.enabled` | `false` | Serve the editor action protocol over JSON-RPC stdio (headless backend only) |
|
|
245
|
+
| `editor.requestTimeoutMs` | `60000` | Per-run timeout budget (ms) for the editor protocol |
|
|
246
|
+
| `editor.diagnosticsCacheMaxFiles` | `64` | Bounded LRU diagnostics-cache size (files) |
|
|
247
|
+
| `maxDiagnostics` | `200` | Diagnostics cap per result |
|
|
248
|
+
| `maxCompletionItems` | `20` | Completion-items cap per result |
|
|
249
|
+
| `maxCodeActions` | `50` | Code-actions cap per result |
|
|
250
|
+
| `maxSymbols` | `100` | Symbol-results cap |
|
|
251
|
+
| `maxSignatures` | `10` | Signature-help cap |
|
|
252
|
+
| `maxInlayHints` | `200` | Inlay-hints cap |
|
|
253
|
+
| `maxResultChars` | `16000` | Rendered-result cap (chars) |
|
|
254
|
+
| `maxDocumentBytes` | `4000000` | Document-read cap (bytes) |
|
|
255
|
+
| `timeoutMs` | `60000` | Per-call timeout, enforced by the official timeout policy |
|
|
256
|
+
|
|
257
|
+
</details>
|
|
258
|
+
|
|
259
|
+
Each `servers` entry is an `LspServerEntry`: `command` (executable resolved on PATH at load) and `extensionToLanguage` (`".ts"` → `typescript`) are required; optional `fileGlobs`, `projectMarkers`, `args`, `env`, `initializationOptions`, `configuration`, `formattingOptions`, `maxMessageBytes`, `maxStderrBytes`, `killGraceMs`, `shutdownTimeoutMs`, `diagnosticsSettleMs`, `diagnosticsDebounceMs`, and `idleTimeoutMs` (`0` = keep the server process alive, which is also the default) tune the built-in stdio client.
|
|
260
|
+
|
|
261
|
+
Routing is deterministic and configuration-driven. Every file takes the first match from: **(1)** a server entry whose `fileGlobs` match the path; **(2)** the nearest ancestor directory — walking up to the workspace root — that holds a project config file listed in some entry's `projectMarkers`, matched against the entries that also map the file's extension; **(3)** the entry whose `extensionToLanguage` maps the file's extension, in config order. A workspace holding `apps/node-app/{package.json,tsconfig.json,src/main.ts}` and `apps/deno-app/{deno.json,src/main.ts}` therefore serves each `main.ts` from its own project's server, with no path rule to maintain and nothing to change when a project is added, renamed, or moved:
|
|
262
|
+
|
|
263
|
+
```yaml
|
|
264
|
+
servers:
|
|
265
|
+
typescript:
|
|
266
|
+
command: typescript-language-server
|
|
267
|
+
args: ["--stdio"]
|
|
268
|
+
extensionToLanguage: { ".ts": typescript, ".tsx": typescriptreact }
|
|
269
|
+
projectMarkers: ["package.json", "tsconfig.json"]
|
|
270
|
+
deno:
|
|
271
|
+
command: deno
|
|
272
|
+
args: ["lsp"]
|
|
273
|
+
extensionToLanguage: { ".ts": typescript, ".tsx": typescriptreact }
|
|
274
|
+
projectMarkers: ["deno.json", "deno.jsonc"]
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
A project marker only decides among servers that already map the file's extension (it never widens an entry's file types); the walk never leaves the workspace root, and a project config in one directory never applies to a sibling directory. Step **(1)** outranks a project marker: an entry whose `fileGlobs` match the path still wins, so drop project-level globs when you adopt `projectMarkers` — a lingering `**/*.ts` glob keeps claiming those files. These rules govern the built-in stdio client — a mounted `ctx.lsp` seam provider decides its own routing.
|
|
278
|
+
|
|
279
|
+
## FAQ
|
|
280
|
+
|
|
281
|
+
<details>
|
|
282
|
+
<summary>What happens with the default <code>servers: {}</code>? Silent breakage?</summary>
|
|
283
|
+
|
|
284
|
+
Nothing is silent. The eight tools stay registered, but a call fails loudly with `LSP_ACTION_UNAVAILABLE` when neither a server entry nor a `ctx.lsp` seam provider handles the file. The seam is resolved per call, so a seam mounted after this plugin is served without a reload. With `editor.enabled: false` (the default) the editor protocol does not start at all.
|
|
285
|
+
|
|
286
|
+
</details>
|
|
287
|
+
|
|
288
|
+
<details>
|
|
289
|
+
<summary>Can a write bypass the sandbox and approval?</summary>
|
|
290
|
+
|
|
291
|
+
No. Only `lsp_format` and `lsp_rename` write, and they ride the same path as the official `write`/`edit` tools: the `fs/write-intent` waterfall (observation → guarded write → observation) and the per-call sandbox policy. A `read-only` session is refused with `LSP_ACTION_READ_ONLY` before any server round-trip; when a wider mode is needed, the `sandbox_permissions` + `justification` escalation pair goes through the official `approveEscalation` ask, and fails closed as `LSP_ACTION_APPROVAL_UNAVAILABLE` when no answerer can decide.
|
|
292
|
+
|
|
293
|
+
</details>
|
|
294
|
+
|
|
295
|
+
<details>
|
|
296
|
+
<summary>Does it fight other plugins over tool names, events, or slots?</summary>
|
|
297
|
+
|
|
298
|
+
No. Every tool is namespaced, it provides no service key, registers no client slot and no `webServer` prefix, and mutates no globals; the bundle patch only `insert`s its own row; the one shared event, `fs/write-intent`, is always delegated through `next()` and never short-circuits the chain. The point-by-point argument is in "Interoperability with other DSH plugins".
|
|
299
|
+
|
|
300
|
+
</details>
|
|
301
|
+
|
|
302
|
+
<details>
|
|
303
|
+
<summary>What if the file changes on disk after I read it?</summary>
|
|
304
|
+
|
|
305
|
+
It is never clobbered. An action fails with `LSP_ACTION_CONFLICT` when the file changed since it was read; overlapping, out-of-bounds, or out-of-workspace edits conflict the same way. `lsp_rename` pre-flights every edited file before the first write.
|
|
306
|
+
|
|
307
|
+
</details>
|
|
308
|
+
|
|
309
|
+
<details>
|
|
310
|
+
<summary>How big is the resource overhead?</summary>
|
|
311
|
+
|
|
312
|
+
Server processes are spawned lazily and each instance keeps its documents resident until the process is reclaimed; `idleTimeoutMs` defaults to `0` (stay alive), and a positive value reclaims the instance when idle. Result counts, characters, document bytes, and total duration are capped per call; the editor protocol's diagnostics cache is a bounded LRU (`editor.diagnosticsCacheMaxFiles`); the plugin makes no network requests.
|
|
313
|
+
|
|
314
|
+
</details>
|
|
315
|
+
|
|
316
|
+
## Security boundaries
|
|
317
|
+
|
|
318
|
+
- **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.
|
|
319
|
+
- **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.
|
|
320
|
+
- **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.
|
|
321
|
+
- **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.
|
|
322
|
+
- **Bounded work.** Result caps, byte caps, and the platform's timeout policy bound every call; the diagnostics cache is a bounded LRU.
|
|
323
|
+
- **Nothing cached on the model path.** Tool results live only in the session log; the diagnostics cache never persists across restarts.
|
|
324
|
+
- **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).
|
|
325
|
+
- **Prompt hygiene.** The plugin injects no persona or prompt prose into the session system prompt — its model-facing surface is the eight tool schemas.
|
|
326
|
+
|
|
327
|
+
## Permissions & data
|
|
328
|
+
|
|
329
|
+
- **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.
|
|
330
|
+
- **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. See [`PRIVACY.md`](PRIVACY.md) for the privacy note.
|
|
331
|
+
- **No network**: the plugin makes no network requests; it talks to language servers over local subprocess stdio.
|
|
332
|
+
|
|
333
|
+
## Known limitations
|
|
334
|
+
|
|
335
|
+
- **Resident documents.** Each document opens once and stays open for the server instance's lifetime — a later request with changed source sends one full-document `didChange`, and the process shutdown closes every document — so project-based servers like tsls serve `textDocument/signatureHelp` and document-free `workspace/symbol` instead of answering `null` on a freshly-closed document. The resident set is bounded by the workspace and cleared with the instance (idle eviction or plugin disposal).
|
|
336
|
+
- **Range formatting requires the server's range provider.** Servers that only advertise whole-document formatting fail range requests with `LSP_ACTION_UNSUPPORTED`.
|
|
337
|
+
- **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.
|
|
338
|
+
|
|
339
|
+
## Interoperability with other DSH plugins
|
|
340
|
+
|
|
341
|
+
Verified against **DSH `0.2.0-rc.2`** (the runtime this README ships for) and the high-star plugin set surveyed on 2026-10-05.
|
|
342
|
+
|
|
343
|
+
This plugin **does not interfere** with other plugins, including the widely installed high-star ones:
|
|
344
|
+
|
|
345
|
+
- **No tool-name collision.** Every tool is namespaced; no bare name owned by a shipped tool or another plugin is registered.
|
|
346
|
+
- **No service-key collision.** It provides no service key at all, so it cannot collide on one.
|
|
347
|
+
- **No slot collision.** It registers no client slot key, so it cannot contend for a `shadows-shipped-ui` seat.
|
|
348
|
+
- **No HTTP route collision.** It registers no `webServer` prefix.
|
|
349
|
+
- **No patch-layer collision.** The bundle patch only `insert`s its own row; it never overrides a built-in row's `config`.
|
|
350
|
+
- **No global mutation.** It does not patch prototypes, rewrite `process.env`, or replace the global fetch dispatcher.
|
|
351
|
+
|
|
352
|
+
**Shared event listeners are non-interfering by construction.** It observes the ordering-sensitive event `fs/write-intent` with `ctx.on()` — Cordis's broadcast registration, where every listener runs and none can starve another. **Every listener here delegates through `next()`**, so the chain is never short-circuited, and a mutation is applied to the value `next()` produced rather than returned in its place.
|
|
353
|
+
|
|
354
|
+
Static evidence: `dsh-plugin-doctor` K10–K13 report `pass` for every check on this repository.
|
|
355
|
+
|
|
356
|
+
## Compatibility
|
|
357
|
+
|
|
358
|
+
| Surface | Status |
|
|
359
|
+
|---|---|
|
|
360
|
+
| Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (`engines.dsh`: `>=0.2.1-0 <0.3.0 \|\| >=0.2.2-0 <0.3.0`); the plugin writes no session events itself — the host records the standard tool/call + tool/result events. The released seam still carries only the four legacy operations, so the plugin keeps its own client and records that vintage on the first action call. Verified 2026-09-24 (dual typecheck rulers + full test suite + self-contained/artifacts gates). |
|
|
361
|
+
| Node | `^22.19.0 \|\| >=24.9.0` |
|
|
362
|
+
| Platforms | All (pure host; subprocess + filesystem, no network) |
|
|
363
|
+
| Model | Any (tools are model-agnostic; the plugin never calls a model) |
|
|
364
|
+
|
|
365
|
+
## Ecosystem & quality
|
|
366
|
+
|
|
367
|
+
- [Gitee mirror](https://gitee.com/perrylink/dsh-lsp-actions) (sync mirror; GitHub is canonical)
|
|
368
|
+
- [dshfind plugin page](https://dshfind.com/plugins/PerryLink/dsh-lsp-actions) (installs and ranking)
|
|
369
|
+
- [OpenSSF Scorecard report](https://securityscorecards.dev/viewer/?uri=github.com/PerryLink/dsh-lsp-actions) (driven by [.github/workflows/scorecard.yml](.github/workflows/scorecard.yml))
|
|
370
|
+
- [dsh-plugin-doctor verification report](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章) (K10–K13 all `pass`)
|
|
371
|
+
- [DSH Market](https://dsh.market/) (listed)
|
|
372
|
+
- **1024 store channel**: `npm i -g dsh1024` once, then `dsh1024 plugin --profile web add dsh-lsp-actions` (counts toward the [deepseek1024.com](https://deepseek1024.com) install ranking)
|
|
373
|
+
- [Ecosystem knowledge base](https://perrylink.github.io/dsh-plugin-guide/) — measured data, not marketing: plugin development guide · plugin-selection data · maintenance criteria
|
|
374
|
+
|
|
375
|
+
## Development
|
|
376
|
+
|
|
377
|
+
```sh
|
|
378
|
+
pnpm install # node ^22.19 || >=24.9
|
|
379
|
+
pnpm run lint # oxlint over src/ and tests/
|
|
380
|
+
pnpm test # vitest: unit + fixture-server integration + editor-protocol e2e + real tsls e2e
|
|
381
|
+
pnpm run test:coverage # coverage gate
|
|
382
|
+
pnpm build # tsc --noEmitOnError && node scripts/fix-dts.mjs → lib/
|
|
383
|
+
pnpm run prepare # build (runs on install)
|
|
384
|
+
pnpm run prepublishOnly # build (runs before publish)
|
|
385
|
+
pnpm run check:readmes # five-language README consistency gate
|
|
386
|
+
pnpm run verify:self-contained # dependency specs resolve from the registry
|
|
387
|
+
pnpm run verify:artifacts # shipped files present + artifacts importable
|
|
388
|
+
pnpm run check:lockfile # lockfile drift check
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Repository layout:
|
|
392
|
+
|
|
393
|
+
```text
|
|
394
|
+
src/ plugin body: servers / client / runner / tools / editor / seam
|
|
395
|
+
tests/ vitest: unit + fixture server + editor-protocol e2e + real tsls e2e
|
|
396
|
+
examples/vscode UI-only VS Code extension + the headless backend it connects to
|
|
397
|
+
docs/ editor protocol (bilingual) + seam-extension research + assets/
|
|
398
|
+
scripts/ build-artifact fixes and mechanical gates (readme sync / self-contained / artifacts)
|
|
399
|
+
upstream/ upstream proposal for the seam extension (patch + PR description)
|
|
400
|
+
verify/ editor-backend smoke scripts and scratch composition
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
The README images are generated programmatically by [`scripts/gen-readme-assets.py`](scripts/gen-readme-assets.py) (Pillow builds the 1440×576 hero WebP in four variants — light/dark × zh/en — plus a hand-written 1100×660 SVG request/response round trip) and are safe to re-run.
|
|
404
|
+
|
|
405
|
+
Topics: `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`
|
|
406
|
+
|
|
407
|
+
## Family & thanks
|
|
408
|
+
|
|
409
|
+
This project is part of the DeepSeek Harness plugin family from [PerryLink](https://github.com/PerryLink) (all Apache-2.0). If it is useful, **a star helps the next person find it** — nothing is gated behind it.
|
|
410
|
+
|
|
411
|
+
- [@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.
|
|
412
|
+
|
|
413
|
+
<details>
|
|
414
|
+
<summary>Expand all plugins</summary>
|
|
415
|
+
|
|
416
|
+
| Plugin | Status |
|
|
417
|
+
|---|---|
|
|
418
|
+
| **[dsh-aqua-input-check](https://github.com/PerryLink/dsh-aqua-input-check)** | |
|
|
419
|
+
| **[dsh-archive-check](https://github.com/PerryLink/dsh-archive-check)** | |
|
|
420
|
+
| **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | |
|
|
421
|
+
| **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | 🧊 FROZEN — see the repo README |
|
|
422
|
+
| **[dsh-bid-ca-precheck](https://github.com/PerryLink/dsh-bid-ca-precheck)** | |
|
|
423
|
+
| **[dsh-bid-qual-check](https://github.com/PerryLink/dsh-bid-qual-check)** | |
|
|
424
|
+
| **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | 🧊 FROZEN — see the repo README |
|
|
425
|
+
| **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | |
|
|
426
|
+
| **[dsh-click](https://github.com/PerryLink/dsh-click)** | |
|
|
427
|
+
| **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | |
|
|
428
|
+
| **[dsh-contract-stance](https://github.com/PerryLink/dsh-contract-stance)** | |
|
|
429
|
+
| **[dsh-customs-doc-check](https://github.com/PerryLink/dsh-customs-doc-check)** | |
|
|
430
|
+
| **[dsh-data-quality](https://github.com/PerryLink/dsh-data-quality)** | 🧊 FROZEN — see the repo README |
|
|
431
|
+
| **[dsh-demurrage-ledger](https://github.com/PerryLink/dsh-demurrage-ledger)** | |
|
|
432
|
+
| **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | |
|
|
433
|
+
| **[dsh-drill-script-check](https://github.com/PerryLink/dsh-drill-script-check)** | |
|
|
434
|
+
| **[dsh-eia-guide-check](https://github.com/PerryLink/dsh-eia-guide-check)** | |
|
|
435
|
+
| **[dsh-emergency-plan](https://github.com/PerryLink/dsh-emergency-plan)** | |
|
|
436
|
+
| **[dsh-essay-rubric-check](https://github.com/PerryLink/dsh-essay-rubric-check)** | |
|
|
437
|
+
| **[dsh-evidence-check](https://github.com/PerryLink/dsh-evidence-check)** | |
|
|
438
|
+
| **[dsh-export-ctl-check](https://github.com/PerryLink/dsh-export-ctl-check)** | |
|
|
439
|
+
| **[dsh-fast](https://github.com/PerryLink/dsh-fast)** | |
|
|
440
|
+
| **[dsh-fmea-table-check](https://github.com/PerryLink/dsh-fmea-table-check)** | |
|
|
441
|
+
| **[dsh-forecast-penalty](https://github.com/PerryLink/dsh-forecast-penalty)** | |
|
|
442
|
+
| **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | |
|
|
443
|
+
| **[dsh-github](https://github.com/PerryLink/dsh-github)** | |
|
|
444
|
+
| **[dsh-gongwen-flow-check](https://github.com/PerryLink/dsh-gongwen-flow-check)** | |
|
|
445
|
+
| **[dsh-gongwen-word-check](https://github.com/PerryLink/dsh-gongwen-word-check)** | |
|
|
446
|
+
| **[dsh-guard-plan-qc](https://github.com/PerryLink/dsh-guard-plan-qc)** | |
|
|
447
|
+
| **[dsh-hazchem-check](https://github.com/PerryLink/dsh-hazchem-check)** | |
|
|
448
|
+
| **[dsh-hazplan-check](https://github.com/PerryLink/dsh-hazplan-check)** | |
|
|
449
|
+
| **[dsh-hidden-risk-map](https://github.com/PerryLink/dsh-hidden-risk-map)** | |
|
|
450
|
+
| **[dsh-hs-classify](https://github.com/PerryLink/dsh-hs-classify)** | |
|
|
451
|
+
| **[dsh-icd-rule-check](https://github.com/PerryLink/dsh-icd-rule-check)** | |
|
|
452
|
+
| **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | |
|
|
453
|
+
| **[dsh-lawcite-adapter](https://github.com/PerryLink/dsh-lawcite-adapter)** | |
|
|
454
|
+
| **[dsh-laya](https://github.com/PerryLink/dsh-laya)** | |
|
|
455
|
+
| **[dsh-lc-doc-check](https://github.com/PerryLink/dsh-lc-doc-check)** | |
|
|
456
|
+
| **[dsh-learning-gap-check](https://github.com/PerryLink/dsh-learning-gap-check)** | |
|
|
457
|
+
| **[dsh-library](https://github.com/PerryLink/dsh-library)** | |
|
|
458
|
+
| **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | |
|
|
459
|
+
| **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | |
|
|
460
|
+
| **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | |
|
|
461
|
+
| **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | |
|
|
462
|
+
| **[dsh-medrec-qc](https://github.com/PerryLink/dsh-medrec-qc)** | |
|
|
463
|
+
| **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | 🧊 FROZEN — see the repo README |
|
|
464
|
+
| **[dsh-nsfc-form-check](https://github.com/PerryLink/dsh-nsfc-form-check)** | |
|
|
465
|
+
| **[dsh-nurse-record-check](https://github.com/PerryLink/dsh-nurse-record-check)** | |
|
|
466
|
+
| **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | |
|
|
467
|
+
| **[dsh-origin-rvc-check](https://github.com/PerryLink/dsh-origin-rvc-check)** | |
|
|
468
|
+
| **[dsh-ota-review-check](https://github.com/PerryLink/dsh-ota-review-check)** | |
|
|
469
|
+
| **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | |
|
|
470
|
+
| **[dsh-paper-doc-adapter](https://github.com/PerryLink/dsh-paper-doc-adapter)** | |
|
|
471
|
+
| **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | |
|
|
472
|
+
| **[dsh-permit-report-check](https://github.com/PerryLink/dsh-permit-report-check)** | |
|
|
473
|
+
| **[dsh-pipeline-check](https://github.com/PerryLink/dsh-pipeline-check)** | |
|
|
474
|
+
| **[dsh-pleading-draft](https://github.com/PerryLink/dsh-pleading-draft)** | |
|
|
475
|
+
| **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | 🚫 RETIRED (repo archived) |
|
|
476
|
+
| **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | |
|
|
477
|
+
| **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | 🚫 RETIRED (repo archived) |
|
|
478
|
+
| **[dsh-plugin-upgrade](https://github.com/PerryLink/dsh-plugin-upgrade)** | 🚫 RETIRED (repo archived) |
|
|
479
|
+
| **[dsh-policy-brief-draft](https://github.com/PerryLink/dsh-policy-brief-draft)** | |
|
|
480
|
+
| **[dsh-power-loss-split](https://github.com/PerryLink/dsh-power-loss-split)** | |
|
|
481
|
+
| **[dsh-power-ticket-check](https://github.com/PerryLink/dsh-power-ticket-check)** | |
|
|
482
|
+
| **[dsh-ppap-check](https://github.com/PerryLink/dsh-ppap-check)** | |
|
|
483
|
+
| **[dsh-protest-deadline](https://github.com/PerryLink/dsh-protest-deadline)** | |
|
|
484
|
+
| **[dsh-railway-window](https://github.com/PerryLink/dsh-railway-window)** | |
|
|
485
|
+
| **[dsh-repair-order-qc](https://github.com/PerryLink/dsh-repair-order-qc)** | |
|
|
486
|
+
| **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | |
|
|
487
|
+
| **[dsh-review-reply-check](https://github.com/PerryLink/dsh-review-reply-check)** | |
|
|
488
|
+
| **[dsh-rulefile-check](https://github.com/PerryLink/dsh-rulefile-check)** | |
|
|
489
|
+
| **[dsh-safety-brief-check](https://github.com/PerryLink/dsh-safety-brief-check)** | |
|
|
490
|
+
| **[dsh-score](https://github.com/PerryLink/dsh-score)** | 🧊 FROZEN — see the repo README |
|
|
491
|
+
| **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | |
|
|
492
|
+
| **[dsh-site-log-check](https://github.com/PerryLink/dsh-site-log-check)** | |
|
|
493
|
+
| **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | |
|
|
494
|
+
| **[dsh-soe-decision-check](https://github.com/PerryLink/dsh-soe-decision-check)** | |
|
|
495
|
+
| **[dsh-soilwater-check](https://github.com/PerryLink/dsh-soilwater-check)** | |
|
|
496
|
+
| **[dsh-sop-sync-check](https://github.com/PerryLink/dsh-sop-sync-check)** | |
|
|
497
|
+
| **[dsh-spc-gbt-adapter](https://github.com/PerryLink/dsh-spc-gbt-adapter)** | |
|
|
498
|
+
| **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | |
|
|
499
|
+
| **[dsh-tender-extract](https://github.com/PerryLink/dsh-tender-extract)** | |
|
|
500
|
+
| **[dsh-tender-matrix](https://github.com/PerryLink/dsh-tender-matrix)** | |
|
|
501
|
+
| **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | |
|
|
502
|
+
| **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | 🚫 RETIRED (repo archived) |
|
|
503
|
+
| **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | |
|
|
504
|
+
| **[dsh-warranty-calc](https://github.com/PerryLink/dsh-warranty-calc)** | |
|
|
505
|
+
| **[dsh-budget](https://github.com/PerryLink/dsh-budget)** | 🧊 FROZEN — see the repo README |
|
|
506
|
+
| **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | 🧊 FROZEN — see the repo README |
|
|
507
|
+
| **[dsh-defend](https://github.com/PerryLink/dsh-defend)** | 🧊 FROZEN — see the repo README |
|
|
508
|
+
| **[dsh-draw](https://github.com/PerryLink/dsh-draw)** | 🧊 FROZEN — see the repo README |
|
|
509
|
+
| **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | 🧊 FROZEN — see the repo README |
|
|
510
|
+
| **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | 🚫 RETIRED (repo archived) |
|
|
511
|
+
| **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | 🚫 RETIRED (repo archived) |
|
|
512
|
+
| **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | 🚫 RETIRED (repo archived) |
|
|
513
|
+
|
|
514
|
+
</details>
|
|
515
|
+
|
|
516
|
+
## License
|
|
517
|
+
|
|
518
|
+
[LICENSE](LICENSE) (Apache License 2.0) © 2026 dsh-lsp-actions contributors
|
|
519
|
+
|
|
520
|
+
<p align="center"><sub>Apache-2.0 · Community plugin, not affiliated with DeepSeek.</sub></p>
|