dsh-lsp-actions 0.2.0

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/LICENSE +201 -0
  3. package/README.es.md +177 -0
  4. package/README.hi.md +177 -0
  5. package/README.md +183 -0
  6. package/README.pt.md +177 -0
  7. package/README.zh-CN.md +181 -0
  8. package/cordis.patch.yml +17 -0
  9. package/lib/abort.d.ts +13 -0
  10. package/lib/abort.d.ts.map +1 -0
  11. package/lib/abort.js +31 -0
  12. package/lib/abort.js.map +1 -0
  13. package/lib/client.d.ts +173 -0
  14. package/lib/client.d.ts.map +1 -0
  15. package/lib/client.js +926 -0
  16. package/lib/client.js.map +1 -0
  17. package/lib/connection.d.ts +103 -0
  18. package/lib/connection.d.ts.map +1 -0
  19. package/lib/connection.js +241 -0
  20. package/lib/connection.js.map +1 -0
  21. package/lib/edits.d.ts +17 -0
  22. package/lib/edits.d.ts.map +1 -0
  23. package/lib/edits.js +76 -0
  24. package/lib/edits.js.map +1 -0
  25. package/lib/extension.d.ts +9 -0
  26. package/lib/extension.d.ts.map +1 -0
  27. package/lib/extension.js +17 -0
  28. package/lib/extension.js.map +1 -0
  29. package/lib/extra-tools.d.ts +45 -0
  30. package/lib/extra-tools.d.ts.map +1 -0
  31. package/lib/extra-tools.js +406 -0
  32. package/lib/extra-tools.js.map +1 -0
  33. package/lib/framing.d.ts +33 -0
  34. package/lib/framing.d.ts.map +1 -0
  35. package/lib/framing.js +80 -0
  36. package/lib/framing.js.map +1 -0
  37. package/lib/host.d.ts +64 -0
  38. package/lib/host.d.ts.map +1 -0
  39. package/lib/host.js +152 -0
  40. package/lib/host.js.map +1 -0
  41. package/lib/index.d.ts +42 -0
  42. package/lib/index.d.ts.map +1 -0
  43. package/lib/index.js +78 -0
  44. package/lib/index.js.map +1 -0
  45. package/lib/render.d.ts +364 -0
  46. package/lib/render.d.ts.map +1 -0
  47. package/lib/render.js +485 -0
  48. package/lib/render.js.map +1 -0
  49. package/lib/runner.d.ts +55 -0
  50. package/lib/runner.d.ts.map +1 -0
  51. package/lib/runner.js +149 -0
  52. package/lib/runner.js.map +1 -0
  53. package/lib/sandbox.d.ts +69 -0
  54. package/lib/sandbox.d.ts.map +1 -0
  55. package/lib/sandbox.js +98 -0
  56. package/lib/sandbox.js.map +1 -0
  57. package/lib/seam.d.ts +67 -0
  58. package/lib/seam.d.ts.map +1 -0
  59. package/lib/seam.js +62 -0
  60. package/lib/seam.js.map +1 -0
  61. package/lib/servers.d.ts +120 -0
  62. package/lib/servers.d.ts.map +1 -0
  63. package/lib/servers.js +216 -0
  64. package/lib/servers.js.map +1 -0
  65. package/lib/session-cwd.d.ts +15 -0
  66. package/lib/session-cwd.d.ts.map +1 -0
  67. package/lib/session-cwd.js +16 -0
  68. package/lib/session-cwd.js.map +1 -0
  69. package/lib/tools.d.ts +150 -0
  70. package/lib/tools.d.ts.map +1 -0
  71. package/lib/tools.js +543 -0
  72. package/lib/tools.js.map +1 -0
  73. package/lib/translate.d.ts +181 -0
  74. package/lib/translate.d.ts.map +1 -0
  75. package/lib/translate.js +715 -0
  76. package/lib/translate.js.map +1 -0
  77. package/lib/vocabulary.d.ts +167 -0
  78. package/lib/vocabulary.d.ts.map +1 -0
  79. package/lib/vocabulary.js +20 -0
  80. package/lib/vocabulary.js.map +1 -0
  81. package/package.json +95 -0
package/README.hi.md ADDED
@@ -0,0 +1,177 @@
1
+ <div align="center">
2
+
3
+ # 🛰️ dsh-lsp-actions
4
+
5
+ **DeepSeek Harness के लिए LSP एक्शन सतह — असली language server, असली फीडबैक।**
6
+
7
+ आपके एजेंट के एडिटर लूप के लिए डायग्नोस्टिक्स, फ़ॉर्मेटिंग, कोड कम्प्लीशन, क्विकफिक्स, सिंबल, सिग्नेचर हेल्प और इनले हिंट्स — उन्हीं language servers से संचालित जिन्हें आपका IDE इस्तेमाल करता है।
8
+
9
+ [![Topic: dsh](https://img.shields.io/badge/Topic-dsh-4D6BFE?style=for-the-badge)](https://github.com/topics/dsh)
10
+ [![Topic: dsh-plugin](https://img.shields.io/badge/Topic-dsh--plugin-8257D0?style=for-the-badge)](https://github.com/topics/dsh-plugin)
11
+ [![License](https://img.shields.io/badge/License-Apache%202.0-D22128?style=flat-square)](LICENSE)
12
+ [![Node](https://img.shields.io/badge/Node-%5E22.19%20%7C%7C%20%3E%3D24-43853D?style=flat-square)](package.json)
13
+
14
+ [English](README.md) · [简体中文](README.zh-CN.md) · [Español](README.es.md) · [हिन्दी](README.hi.md) · [Português](README.pt.md)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## यह प्लगइन आपके एजेंट को क्या देता है
21
+
22
+ आधिकारिक DeepSeek Harness `ctx.lsp` seam **नेविगेशन** (go-to-definition, references, implementation, hover) को कवर करता है। `dsh-lsp-actions` **एक्शन सतह** को पूरा करता है — वह फीडबैक लूप जिसकी एक एजेंट को कोड लिखते और ठीक करते समय ज़रूरत होती है:
23
+
24
+ | टूल | क्या करता है | लिखता है? |
25
+ | --- | --- | --- |
26
+ | `lsp_diagnostics <file>` | कंपाइलर/एनालाइज़र की एरर, वॉर्निंग और हिंट्स — severity, range, message और स्रोत server के साथ | ❌ केवल-पठन |
27
+ | `lsp_format <file> [range?]` | language server के ज़रिए फ़ाइल या चयन को फ़ॉर्मेट करता है और परिणाम लागू करता है, diff लौटाता है | ✅ `fs/write-intent` + sandbox नीति से |
28
+ | `lsp_completion <file> <line> <character>` | कर्सर स्थान पर कम्प्लीशन सुझाव, असली इंसर्शन टेक्स्ट सहित | ❌ केवल-पठन |
29
+ | `lsp_code_action <file> [range?] [only?]` | किसी range या पहले डायग्नोस्टिक के लिए server-सत्यापित क्विकफिक्स/रिफैक्टरिंग (उनके edits सहित) | ❌ केवल संदर्भ |
30
+ | `lsp_symbols <query?> <file_path?>` | नाम से पूरे workspace में सिंबल खोज, या एक फ़ाइल की सिंबल रूपरेखा | ❌ केवल-पठन |
31
+ | `lsp_signature <file> <line> <character>` | कॉल के अंदर सिग्नेचर हेल्प (पैरामीटर और दस्तावेज़ीकरण) | ❌ केवल-पठन |
32
+ | `lsp_inlay_hints <file> [range?]` | server के टाइप एनोटेशन और पैरामीटर-नाम संकेत | ❌ केवल-पठन |
33
+ | `lsp_rename <file> <line> <character> <new_name>` | server-सत्यापित सिंबल नाम बदलना, पूरे workspace में प्रति-फ़ाइल diffs के साथ लागू | ✅ `fs/write-intent` + sandbox नीति से |
34
+
35
+ > ✨ टेस्ट सूट में एक असली `typescript-language-server` रन शामिल है: डायग्नोस्टिक्स, फ़ॉर्मेटिंग, कम्प्लीशन, सिंबल खोज और रिनेम एक जीवित server के ख़िलाफ़ end-to-end सत्यापित होते हैं, सिर्फ़ mocks से नहीं। सूट आत्मनिर्भर है (tsls एक devDependency है) और CI में Node 22/24 पर Linux, Windows और macOS में चलती है।
36
+
37
+ ## त्वरित शुरुआत
38
+
39
+ ```sh
40
+ dsh plugin --profile <name> add <path-or-tarball-of-dsh-lsp-actions>
41
+ ```
42
+
43
+ हर language server के लिए एक entry कॉन्फ़िगर करें (आकार आधिकारिक `lsp-stdio` कॉन्फ़िग से मेल खाता है):
44
+
45
+ ```yaml
46
+ # अपने profile के cordis.patch.yml में (या bundle पंक्ति में)
47
+ - insert:
48
+ - id: lsp-actions
49
+ name: dsh-lsp-actions
50
+ inject: [tools, fs, subprocess]
51
+ config:
52
+ servers:
53
+ ts:
54
+ command: typescript-language-server
55
+ args: [--stdio]
56
+ extensionToLanguage:
57
+ ".ts": typescript
58
+ formattingOptions: { tabSize: 2, insertSpaces: true }
59
+ py:
60
+ command: pyright-langserver
61
+ args: [--stdio]
62
+ extensionToLanguage:
63
+ ".py": python
64
+ maxDiagnostics: 200
65
+ maxCompletionItems: 20
66
+ maxCodeActions: 50
67
+ maxSymbols: 100
68
+ maxSignatures: 10
69
+ maxInlayHints: 200
70
+ maxResultChars: 16000
71
+ timeoutMs: 60000
72
+ ```
73
+
74
+ आठों टूल हमेशा पंजीकृत रहते हैं। **खाली `servers` तालिका और बिना माउंटेड `ctx.lsp` seam के कॉल ज़ोर से विफल होते हैं** (`LSP_ACTION_UNAVAILABLE` बताता है कि क्या कॉन्फ़िगर करना है) — प्लगइन वे server कभी शुरू नहीं करता जो आपने कॉन्फ़िगर नहीं किए। इस प्लगइन के **बाद** माउंट हुआ `ctx.lsp` seam अगली कॉल पर पहचान लिया जाता है (seam का पता हर कॉल पर चलता है, इसलिए लोड क्रम मायने नहीं रखता)।
75
+
76
+ ## यह निर्माण से ही सुरक्षित क्यों है
77
+
78
+ - **फ़ॉर्मेटिंग और रिनेम असली बदलाव हैं, `write`/`edit` जैसे ही माने जाते हैं।** हर बाइट `fs/write-intent` waterfall (निरीक्षण → संरक्षित लेखन → निरीक्षण) और प्रति-कॉल sandbox नीति से गुज़रता है। `lsp_rename` हर संपादित फ़ाइल को पहली लेखन से *पहले* प्री-फ़्लाइट करता है (workspace समाहितता, ओवरलैप जाँच, बाइट-सीमित पठन), ताकि ख़राब server उत्तर आधा-लागू रिनेम न छोड़ सके।
79
+ - **बाक़ी सब डिज़ाइन से केवल-पठन है।** कोड एक्शन, कम्प्लीशन, सिंबल, सिग्नेचर और हिंट्स संदर्भ सामग्री के रूप में रिपोर्ट होते हैं; उन्हें लागू करना मॉडल का अपना write/edit निर्णय है। कमांड रूप रिपोर्ट होते हैं और **कभी निष्पादित नहीं होते**।
80
+ - **केवल-पठन सत्र ज़ोर से, तेज़ी से और संरचित रूप से विफल होते हैं** — साझा `[sandbox: …]` मार्कर के साथ `LSP_ACTION_READ_ONLY`, किसी भी server दौर से *पहले* उठाया जाता है।
81
+ - **एस्केलेशन आधिकारिक टूल्स से मेल खाता है।** प्रतिबंधित फ़ाइलसिस्टम के तहत `lsp_format` और `lsp_rename` वही एक-बार `sandbox_permissions` / `justification` पुनर्प्रयास विज्ञापित करते हैं जो `write`/`edit` करते हैं, `ctx.approval` के ज़रिए हल होता है।
82
+ - **संघर्ष कभी कुछ नहीं मिटाते।** अगर फ़ाइल पढ़े जाने के बाद डिस्क पर बदल गई, तो संरक्षित लेखन `LSP_ACTION_CONFLICT` से विफल होता है और मॉडल को चुनने को कहा जाता है: दोबारा पढ़कर फिर चलाएँ, या diff हाथ से लागू करें।
83
+ - **टाइमआउट प्लेटफ़ॉर्म के हैं।** हर टूल `timeoutMs` घोषित करता है; आधिकारिक `dsh-tool-call-timeout-policy` उसे लागू करती है, और हर await `exec.signal` का सम्मान करता है।
84
+ - **कुछ भी कैश नहीं होता।** परिणाम केवल सत्र लॉग में रहते हैं; सत्रों के बीच कोई स्थायित्व नहीं है।
85
+ - **ख़राब server ज़ोर से विफल होते हैं।** ग़ैर-मौजूद निष्पादन योग्य लोड पर विफल होता है; स्टार्टअप पर मरने वाला server कॉल को `LSP_ACTION_SERVER_FAILED` + उसके stderr टेल से विफल करता है (एक नए-प्रक्रिया पुनर्प्रयास के बाद)।
86
+
87
+ ## आर्किटेक्चर
88
+
89
+ एक्शन **पहले आधिकारिक seam** से चलते हैं और प्लगइन के अपने न्यूनतम stdio क्लाइंट पर गिरते हैं:
90
+
91
+ ```
92
+ lsp_diagnostics / lsp_format / lsp_completion / lsp_code_action /
93
+ lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
94
+ │
95
+ ▼
96
+ ctx.lsp seam (विस्तारित: diagnostics / formatDocument / completion)
97
+ │ अनुपस्थित · पुराना · इस फ़ाइल के लिए कोई provider नहीं
98
+ ▼
99
+ अंतर्निहित stdio क्लाइंट ← servers तालिका (ctx.subprocess.spawn + JSON-RPC)
100
+ ```
101
+
102
+ seam विस्तार upstream प्रस्तावित है (`upstream/lsp-action-seam.patch`, PR विवरण `upstream/PR-description.md` में)। जब वह आ जाएगा, प्लगइन बिना बदलाव के काम करता रहेगा — अंतर्निहित क्लाइंट का उपयोग बस बंद हो जाएगा। अंतर्निहित क्लाइंट `servers` तालिका के लिए स्वतंत्र fallback के रूप में बना रहेगा। पूर्ण शोध और डिज़ाइन नोट्स: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md), [`upstream/README.md`](upstream/README.md)।
103
+
104
+ ## कॉन्फ़िगरेशन संदर्भ
105
+
106
+ ```ts
107
+ interface Config {
108
+ /** नामित language servers; खाली = प्लगइन का अपना क्लाइंट कुछ नहीं परोसता। */
109
+ servers?: Record<string, LspServerEntry>
110
+ maxDiagnostics?: number // डिफ़ॉल्ट 200
111
+ maxCompletionItems?: number // डिफ़ॉल्ट 20
112
+ maxCodeActions?: number // डिफ़ॉल्ट 50
113
+ maxSymbols?: number // डिफ़ॉल्ट 100
114
+ maxSignatures?: number // डिफ़ॉल्ट 10
115
+ maxInlayHints?: number // डिफ़ॉल्ट 200
116
+ maxResultChars?: number // डिफ़ॉल्ट 16000 (पूर्ण रेंडर परिणाम की सीमा)
117
+ maxDocumentBytes?: number // डिफ़ॉल्ट 4000000
118
+ timeoutMs?: number // डिफ़ॉल्ट 60000 (आधिकारिक timeout नीति द्वारा लागू)
119
+ }
120
+
121
+ interface LspServerEntry {
122
+ command: string // निष्पादन योग्य, लोड पर PATH में हल होता है
123
+ extensionToLanguage: Record<string, string> // ".ts" → "typescript"
124
+ fileGlobs?: string[] // वैकल्पिक; glob मिलान एक्सटेंशन मैप पर जीतता है
125
+ args?: string[] // बिना shell
126
+ env?: Record<string, string>
127
+ initializationOptions?: unknown
128
+ configuration?: unknown // ऑब्जेक्ट रूप workspace/configuration का section-वार उत्तर देता है
129
+ formattingOptions?: unknown // जैसे { tabSize: 2, insertSpaces: true }
130
+ maxMessageBytes?: number // डिफ़ॉल्ट 16000000
131
+ maxStderrBytes?: number // डिफ़ॉल्ट 1000000
132
+ killGraceMs?: number // डिफ़ॉल्ट 2000
133
+ shutdownTimeoutMs?: number // डिफ़ॉल्ट 5000
134
+ diagnosticsSettleMs?: number // डिफ़ॉल्ट 2000 (केवल-push डायग्नोस्टिक्स विंडो)
135
+ diagnosticsDebounceMs?: number // डिफ़ॉल्ट 250 (अंतिम push बैच के बाद का शांत काल)
136
+ idleTimeoutMs?: number // डिफ़ॉल्ट 0 (0 = server प्रक्रिया को जीवित रखें)
137
+ }
138
+ ```
139
+
140
+ ### त्रुटि कोड
141
+
142
+ हर विफलता त्रुटि परिणाम पर एक स्थिर `code` रखती है; मॉडल और कॉलर code से रूट करते हैं, संदेश पाठ से कभी नहीं।
143
+
144
+ | Code | अर्थ |
145
+ | --- | --- |
146
+ | `LSP_ACTION_UNAVAILABLE` | कोई server entry नहीं और seam का कोई provider इस फ़ाइल को नहीं संभालता। |
147
+ | `LSP_ACTION_UNSUPPORTED` | server (या seam provider) ऑपरेशन का विज्ञापन नहीं करता। |
148
+ | `LSP_ACTION_SERVER_FAILED` | server विफल हुआ (अपने stderr टेल सहित); स्टार्टअप विफलताएँ एक बार पुनः प्रयास करती हैं। |
149
+ | `LSP_ACTION_MALFORMED_RESPONSE` | server ने संरचनात्मक रूप से अमान्य पेलोड भेजा। |
150
+ | `LSP_ACTION_CONFLICT` | फ़ाइल पढ़े जाने के बाद बदल गई, या server के edits ओवरलैप / सीमा से बाहर / workspace से बाहर हैं। |
151
+ | `LSP_ACTION_READ_ONLY` | सत्र का sandbox मोड फ़ॉर्मेटिंग/रिनेम लेखन को मना करता है। |
152
+ | `LSP_ACTION_WORKSPACE_REQUIRED` | कॉल करने वाले सत्र के पास server को जड़ देने के लिए workspace cwd नहीं है। |
153
+ | `LSP_ACTION_NO_SYMBOL` | server को कर्सर स्थान पर नाम बदलने योग्य कोई सिंबल नहीं मिला। |
154
+
155
+ ### होस्ट संस्करण समर्थन
156
+
157
+ प्लगइन DeepSeek Harness पैकेजों को **peer dependencies** के रूप में घोषित करता है (`@deepseek-ai/dsh-fs`, `dsh-llm`, `dsh-sandbox`, `dsh-subprocess`, `dsh-tools` ≥ `0.1.0-rc.6`), ताकि एक ही प्रति होस्ट और प्लगइन दोनों को सेवा दे। `0.1.0-rc.6` के विरुद्ध परीक्षित।
158
+
159
+ ### ज्ञात सीमाएँ
160
+
161
+ - **क्षणिक दस्तावेज़।** हर एक्शन फ़ाइल खोलता है, एक अनुरोध चलाता है और फिर बंद कर देता है (आधिकारिक stdio host की तरह)। बिना-दस्तावेज़ अनुरोधों के लिए निवासी खुली फ़ाइल माँगने वाले प्रोजेक्ट-आधारित server (tsls बिना खुली फ़ाइल के `workspace/symbol` मना करता है) को `lsp_symbols` में `file_path` देकर सेवा दी जाती है — प्लगइन उस अनुरोध के दौरान रूटिंग फ़ाइल खुली रखता है। tsls इस जीवनचक्र में `textDocument/signatureHelp` का उत्तर `null` से भी देता है; अन्य server (gopls, pyright, rust-analyzer) इसे सामान्य रूप से परोसते हैं।
162
+ - **रेंज फ़ॉर्मेटिंग के लिए server का range provider चाहिए।** केवल पूर्ण-दस्तावेज़ फ़ॉर्मेटिंग विज्ञापित करने वाले server रेंज अनुरोधों को `LSP_ACTION_UNSUPPORTED` से विफल करते हैं।
163
+ - **रिनेम केवल टेक्स्ट edits लागू करता है।** server के रिनेम उत्तर में रिसोर्स ऑपरेशन (फ़ाइल बनाना/मिटाना/नाम बदलना) `LSP_ACTION_UNSUPPORTED` से अस्वीकार होते हैं, और workspace से बाहर के edits कुछ भी लिखे जाने से पहले `LSP_ACTION_CONFLICT` से विफल होते हैं। `utf-8`/`utf-32` server पर क्रॉस-फ़ाइल रिनेम स्थितियाँ हर संपादित फ़ाइल को पढ़कर डिकोड होती हैं; अपठनीय संपादित फ़ाइल स्थितियों को ग़लत डिकोड करने के बजाय कॉल को संघर्ष के रूप में विफल करती है।
164
+
165
+ ## विकास
166
+
167
+ ```sh
168
+ pnpm install
169
+ pnpm run lint # src/ और tests/ पर oxlint
170
+ pnpm test # 240+ टेस्ट: यूनिट + fixture-server एकीकरण + असली tsls e2e
171
+ pnpm run test:coverage # द्वार: पंक्तियाँ/कथन/फ़ंक्शन ≥ 90%, शाखाएँ ≥ 85%
172
+ pnpm build # lib/ उत्पन्न करता है
173
+ ```
174
+
175
+ ## License
176
+
177
+ [Apache License 2.0](LICENSE)
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ <div align="center">
2
+
3
+ # 🛰️ dsh-lsp-actions
4
+
5
+ **The LSP action surface for DeepSeek Harness — real language servers, real feedback.**
6
+
7
+ Diagnostics, formatting, code completion, quickfixes, symbols, signature help, inlay hints, and workspace-wide rename for your agent's editor loop, powered by the same language servers your IDE uses.
8
+
9
+ [![Topic: dsh](https://img.shields.io/badge/Topic-dsh-4D6BFE?style=for-the-badge)](https://github.com/topics/dsh)
10
+ [![Topic: dsh-plugin](https://img.shields.io/badge/Topic-dsh--plugin-8257D0?style=for-the-badge)](https://github.com/topics/dsh-plugin)
11
+ [![CI](https://github.com/PerryLink/dsh-lsp-actions/actions/workflows/ci.yml/badge.svg)](https://github.com/PerryLink/dsh-lsp-actions/actions/workflows/ci.yml)
12
+ [![npm](https://img.shields.io/npm/v/dsh-lsp-actions?style=flat-square)](https://www.npmjs.com/package/dsh-lsp-actions)
13
+ [![License](https://img.shields.io/badge/License-Apache%202.0-D22128?style=flat-square)](LICENSE)
14
+ [![Node](https://img.shields.io/badge/Node-%5E22.19%20%7C%7C%20%3E%3D24-43853D?style=flat-square)](package.json)
15
+
16
+ [English](README.md) · [简体中文](README.zh-CN.md) · [Español](README.es.md) · [हिन्दी](README.hi.md) · [Português](README.pt.md)
17
+
18
+ </div>
19
+
20
+ ---
21
+
22
+ ## What this plugin gives your agent
23
+
24
+ The official DeepSeek Harness `ctx.lsp` seam covers **navigation** (go-to-definition, references, implementation, hover). `dsh-lsp-actions` completes the **action surface** — the feedback loop an agent needs while it writes and fixes code:
25
+
26
+ | Tool | What it does | Writes? |
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 |
36
+
37
+ > ✨ A real `typescript-language-server` run is part of the test suite: diagnostics, formatting, completion, symbol search, and rename are verified end-to-end against a live server, not just mocks. The suite is self-contained (tsls is a devDependency) and runs in CI on Node 22/24 across Linux, Windows, and macOS.
38
+
39
+ ## Quick start
40
+
41
+ ```sh
42
+ dsh plugin --profile <name> add <path-or-tarball-of-dsh-lsp-actions>
43
+ ```
44
+
45
+ Configure one entry per language server (the shape mirrors the official `lsp-stdio` config):
46
+
47
+ ```yaml
48
+ # in your profile's cordis.patch.yml (or the bundle row)
49
+ - insert:
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
74
+ ```
75
+
76
+ The eight tools are always registered. With an **empty `servers` table and no `ctx.lsp` seam mounted, calls fail loudly** with `LSP_ACTION_UNAVAILABLE` telling the user what to configure — the plugin never starts servers you did not configure. A `ctx.lsp` seam mounted **after** this plugin is picked up on the next call (seam detection is per-call, so load order does not matter).
77
+
78
+ ## Why it is safe by construction
79
+
80
+ - **Formatting and rename are real mutations, treated like `write`/`edit`.** Every byte goes through the `fs/write-intent` waterfall (observation → guarded write → observation) and the per-call sandbox policy. `lsp_rename` pre-flights every edited file (workspace containment, overlap check, byte-capped read) *before* the first write, so a bad server response cannot leave a half-applied rename.
81
+ - **Everything else is read-only by design.** Code actions, completions, symbols, signatures, and hints are reported as reference material; applying them is the model's own write/edit decision. Command forms are reported and **never executed**.
82
+ - **Read-only sessions fail loud, fast, and structured** — `LSP_ACTION_READ_ONLY` with the shared `[sandbox: …]` marker, raised *before* any server round-trip.
83
+ - **Escalation matches the official tools.** Under a confining filesystem, `lsp_format` and `lsp_rename` advertise the same `sandbox_permissions` / `justification` one-shot retry as `write`/`edit`, resolved through `ctx.approval`.
84
+ - **Conflicts never clobber.** If the file changed on disk after it was read, the guarded write fails with `LSP_ACTION_CONFLICT` and the model is told to choose: re-read and re-run, or apply the diff manually.
85
+ - **Timeouts are the platform's.** Each tool declares `timeoutMs`; the official `dsh-tool-call-timeout-policy` enforces it, and every await honors `exec.signal`.
86
+ - **Nothing is cached.** Results live only in the session log; there is no cross-session persistence.
87
+ - **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).
88
+
89
+ ## Architecture
90
+
91
+ Actions run **official-seam-first** and fall back to the plugin's own minimal stdio client:
92
+
93
+ ```
94
+ lsp_diagnostics / lsp_format / lsp_completion / lsp_code_action /
95
+ lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
96
+ │
97
+ ▼
98
+ ctx.lsp seam (extended: diagnostics / formatDocument / completion)
99
+ │ absent · legacy · no provider for this file
100
+ ▼
101
+ built-in stdio client ← servers table (ctx.subprocess.spawn + JSON-RPC)
102
+ ```
103
+
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
+ ```
141
+
142
+ ### Error codes
143
+
144
+ Every failure carries a stable `code` on the error result; models and callers route on the code, never on message text.
145
+
146
+ | Code | Meaning |
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. |
156
+
157
+ ### Host version support
158
+
159
+ The plugin declares its DeepSeek Harness packages as **peer dependencies** (`@deepseek-ai/dsh-fs`, `dsh-llm`, `dsh-sandbox`, `dsh-subprocess`, `dsh-tools` ≥ `0.1.0-rc.6`), so one copy serves both the host and the plugin. Tested against `0.1.0-rc.6`.
160
+
161
+ ### Known limitations
162
+
163
+ - **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`, which keeps the routing file open for that request. tsls also answers `textDocument/signatureHelp` with `null` under this lifecycle; other servers (gopls, pyright, rust-analyzer) serve it normally.
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.
166
+
167
+ ## Development
168
+
169
+ ```sh
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
+ ```
176
+
177
+ ### Releasing
178
+
179
+ CI runs the lint/build/test matrix plus the coverage gate on every push and pull request. Pushing a `v*` tag triggers the publish workflow, which verifies the suite and publishes the package to npm — it needs an `NPM_TOKEN` Actions secret (a publish-scoped npm access token) set once on the repository. The version is bumped manually in `package.json`/`CHANGELOG.md` before tagging.
180
+
181
+ ## License
182
+
183
+ [Apache License 2.0](LICENSE)
package/README.pt.md ADDED
@@ -0,0 +1,177 @@
1
+ <div align="center">
2
+
3
+ # 🛰️ dsh-lsp-actions
4
+
5
+ **A superfície de ação LSP para o DeepSeek Harness — servidores de linguagem reais, feedback real.**
6
+
7
+ Diagnósticos, formatação, autocompletar de código, correções rápidas, símbolos, ajuda de assinatura e dicas embutidas para o loop do editor do seu agente, alimentados pelos mesmos servidores de linguagem que o seu IDE usa.
8
+
9
+ [![Topic: dsh](https://img.shields.io/badge/Topic-dsh-4D6BFE?style=for-the-badge)](https://github.com/topics/dsh)
10
+ [![Topic: dsh-plugin](https://img.shields.io/badge/Topic-dsh--plugin-8257D0?style=for-the-badge)](https://github.com/topics/dsh-plugin)
11
+ [![License](https://img.shields.io/badge/License-Apache%202.0-D22128?style=flat-square)](LICENSE)
12
+ [![Node](https://img.shields.io/badge/Node-%5E22.19%20%7C%7C%20%3E%3D24-43853D?style=flat-square)](package.json)
13
+
14
+ [English](README.md) · [简体中文](README.zh-CN.md) · [Español](README.es.md) · [हिन्दी](README.hi.md) · [Português](README.pt.md)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## O que este plugin dá ao seu agente
21
+
22
+ O seam oficial `ctx.lsp` do DeepSeek Harness cobre **navegação** (ir para definição, referências, implementação, hover). O `dsh-lsp-actions` completa a **superfície de ação** — o loop de feedback que um agente precisa enquanto escreve e corrige código:
23
+
24
+ | Ferramenta | O que faz | Grava? |
25
+ | --- | --- | --- |
26
+ | `lsp_diagnostics <file>` | Erros, avisos e dicas do compilador/analisador com severidade, intervalo, mensagem e servidor de origem | ❌ somente leitura |
27
+ | `lsp_format <file> [range?]` | Formata um arquivo ou seleção pelo servidor de linguagem e aplica o resultado, devolvendo o diff | ✅ via `fs/write-intent` + política de sandbox |
28
+ | `lsp_completion <file> <line> <character>` | Sugestões de autocompletar em uma posição do cursor, incluindo o texto de inserção real | ❌ somente leitura |
29
+ | `lsp_code_action <file> [range?] [only?]` | Correções/refatorações verificadas pelo servidor (com suas edições) para um intervalo ou o primeiro diagnóstico | ❌ somente referência |
30
+ | `lsp_symbols <query?> <file_path?>` | Busca de símbolos por nome em todo o workspace, ou o esboço de símbolos de um arquivo | ❌ somente leitura |
31
+ | `lsp_signature <file> <line> <character>` | Ajuda de assinatura (parâmetros e documentação) dentro de uma chamada | ❌ somente leitura |
32
+ | `lsp_inlay_hints <file> [range?]` | Anotações de tipo e dicas de nomes de parâmetros do servidor | ❌ somente leitura |
33
+ | `lsp_rename <file> <line> <character> <new_name>` | Renomeação de símbolo verificada pelo servidor, aplicada em todo o workspace com diffs por arquivo | ✅ via `fs/write-intent` + política de sandbox |
34
+
35
+ > ✨ Uma execução real do `typescript-language-server` faz parte da suíte de testes: diagnósticos, formatação, autocompletar, busca de símbolos e renomeação são verificados de ponta a ponta contra um servidor vivo, não apenas com mocks. A suíte é autocontida (tsls é uma devDependency) e roda no CI com Node 22/24 em Linux, Windows e macOS.
36
+
37
+ ## Início rápido
38
+
39
+ ```sh
40
+ dsh plugin --profile <name> add <caminho-ou-tarball-do-dsh-lsp-actions>
41
+ ```
42
+
43
+ Configure uma entrada por servidor de linguagem (a forma espelha a configuração oficial do `lsp-stdio`):
44
+
45
+ ```yaml
46
+ # no cordis.patch.yml do seu perfil (ou na linha do bundle)
47
+ - insert:
48
+ - id: lsp-actions
49
+ name: dsh-lsp-actions
50
+ inject: [tools, fs, subprocess]
51
+ config:
52
+ servers:
53
+ ts:
54
+ command: typescript-language-server
55
+ args: [--stdio]
56
+ extensionToLanguage:
57
+ ".ts": typescript
58
+ formattingOptions: { tabSize: 2, insertSpaces: true }
59
+ py:
60
+ command: pyright-langserver
61
+ args: [--stdio]
62
+ extensionToLanguage:
63
+ ".py": python
64
+ maxDiagnostics: 200
65
+ maxCompletionItems: 20
66
+ maxCodeActions: 50
67
+ maxSymbols: 100
68
+ maxSignatures: 10
69
+ maxInlayHints: 200
70
+ maxResultChars: 16000
71
+ timeoutMs: 60000
72
+ ```
73
+
74
+ As oito ferramentas são sempre registradas. Com uma **tabela `servers` vazia e nenhum seam `ctx.lsp` montado, as chamadas falham em alto e bom som** com `LSP_ACTION_UNAVAILABLE` dizendo o que configurar — o plugin nunca inicia servidores que você não configurou. Um seam `ctx.lsp` montado **depois** deste plugin é detectado na próxima chamada (a detecção do seam é por chamada, então a ordem de carregamento não importa).
75
+
76
+ ## Por que é seguro por construção
77
+
78
+ - **Formatação e renomeação são mutações reais, tratadas como `write`/`edit`.** Cada byte passa pelo waterfall `fs/write-intent` (observação → escrita protegida → observação) e pela política de sandbox de cada chamada. O `lsp_rename` faz o pré-voo de cada arquivo editado (contenção no workspace, verificação de sobreposição, leitura limitada por bytes) *antes* da primeira escrita, para que uma resposta ruim do servidor não deixe uma renomeação pela metade.
79
+ - **Todo o resto é somente leitura por design.** Ações de código, autocompletar, símbolos, assinaturas e dicas são reportados como material de referência; aplicá-los é decisão própria do modelo com write/edit. Formas de comando são reportadas e **nunca executadas**.
80
+ - **Sessões somente leitura falham em alto e bom som, rápido e estruturado** — `LSP_ACTION_READ_ONLY` com o marcador compartilhado `[sandbox: …]`, lançado *antes* de qualquer ida e volta com o servidor.
81
+ - **A escalada acompanha as ferramentas oficiais.** Sob um sistema de arquivos restritivo, o `lsp_format` e o `lsp_rename` anunciam a mesma nova tentativa única `sandbox_permissions` / `justification` que `write`/`edit`, resolvida por meio de `ctx.approval`.
82
+ - **Conflitos nunca sobrescrevem.** Se o arquivo mudou em disco depois de lido, a escrita protegida falha com `LSP_ACTION_CONFLICT` e o modelo é instruído a escolher: reler e repetir, ou aplicar o diff manualmente.
83
+ - **Os timeouts são da plataforma.** Cada ferramenta declara `timeoutMs`; a política oficial `dsh-tool-call-timeout-policy` o aplica, e cada await respeita `exec.signal`.
84
+ - **Nada é cacheado.** Os resultados vivem apenas no log da sessão; não há persistência entre sessões.
85
+ - **Servidores ruins falham em alto e bom som.** Um executável inexistente falha no carregamento; um servidor que morre na inicialização falha a chamada com `LSP_ACTION_SERVER_FAILED` mais o final do seu stderr (após uma nova tentativa com processo novo).
86
+
87
+ ## Arquitetura
88
+
89
+ As ações vão **primeiro pelo seam oficial** e caem para o cliente stdio mínimo do próprio plugin:
90
+
91
+ ```
92
+ lsp_diagnostics / lsp_format / lsp_completion / lsp_code_action /
93
+ lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
94
+ │
95
+ ▼
96
+ ctx.lsp seam (estendido: diagnostics / formatDocument / completion)
97
+ │ ausente · legado · sem provider para este arquivo
98
+ ▼
99
+ cliente stdio integrado ← tabela servers (ctx.subprocess.spawn + JSON-RPC)
100
+ ```
101
+
102
+ A extensão do seam está proposta upstream (`upstream/lsp-action-seam.patch`, descrição do PR em `upstream/PR-description.md`). Quando for integrada, o plugin continua funcionando sem mudanças — o cliente integrado simplesmente deixa de ser usado. O cliente integrado permanece como fallback independente para a tabela `servers`. Notas completas de pesquisa e design: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md), [`upstream/README.md`](upstream/README.md).
103
+
104
+ ## Referência de configuração
105
+
106
+ ```ts
107
+ interface Config {
108
+ /** Servidores de linguagem nomeados; vazio = o cliente próprio não serve nada. */
109
+ servers?: Record<string, LspServerEntry>
110
+ maxDiagnostics?: number // padrão 200
111
+ maxCompletionItems?: number // padrão 20
112
+ maxCodeActions?: number // padrão 50
113
+ maxSymbols?: number // padrão 100
114
+ maxSignatures?: number // padrão 10
115
+ maxInlayHints?: number // padrão 200
116
+ maxResultChars?: number // padrão 16000 (teto do resultado renderizado completo)
117
+ maxDocumentBytes?: number // padrão 4000000
118
+ timeoutMs?: number // padrão 60000 (aplicado pela política oficial de timeout)
119
+ }
120
+
121
+ interface LspServerEntry {
122
+ command: string // executável, resolvido no PATH no carregamento
123
+ extensionToLanguage: Record<string, string> // ".ts" → "typescript"
124
+ fileGlobs?: string[] // opcional; globs vencem o mapa de extensões
125
+ args?: string[] // sem shell
126
+ env?: Record<string, string>
127
+ initializationOptions?: unknown
128
+ configuration?: unknown // forma de objeto responde workspace/configuration por seção
129
+ formattingOptions?: unknown // p. ex. { tabSize: 2, insertSpaces: true }
130
+ maxMessageBytes?: number // padrão 16000000
131
+ maxStderrBytes?: number // padrão 1000000
132
+ killGraceMs?: number // padrão 2000
133
+ shutdownTimeoutMs?: number // padrão 5000
134
+ diagnosticsSettleMs?: number // padrão 2000 (janela de diagnósticos só por push)
135
+ diagnosticsDebounceMs?: number // padrão 250 (período de calma após o último lote enviado)
136
+ idleTimeoutMs?: number // padrão 0 (0 = manter o processo do servidor vivo)
137
+ }
138
+ ```
139
+
140
+ ### Códigos de erro
141
+
142
+ Cada falha carrega um `code` estável no resultado de erro; modelos e chamadores roteiam pelo código, nunca pelo texto da mensagem.
143
+
144
+ | Code | Significado |
145
+ | --- | --- |
146
+ | `LSP_ACTION_UNAVAILABLE` | Nenhuma entrada de servidor nem provider do seam trata este arquivo. |
147
+ | `LSP_ACTION_UNSUPPORTED` | O servidor (ou o provider do seam) não anuncia a operação. |
148
+ | `LSP_ACTION_SERVER_FAILED` | O servidor falhou (com o final do seu stderr); falhas de inicialização tentam de novo uma vez. |
149
+ | `LSP_ACTION_MALFORMED_RESPONSE` | O servidor enviou uma carga estruturalmente inválida. |
150
+ | `LSP_ACTION_CONFLICT` | O arquivo mudou desde que foi lido, ou as edições do servidor se sobrepõem / saem dos limites / saem do workspace. |
151
+ | `LSP_ACTION_READ_ONLY` | O modo de sandbox da sessão proíbe a escrita da formatação/renomeação. |
152
+ | `LSP_ACTION_WORKSPACE_REQUIRED` | A sessão chamadora não tem um cwd de workspace para enraizar o servidor. |
153
+ | `LSP_ACTION_NO_SYMBOL` | O servidor não encontrou um símbolo renomeável na posição do cursor. |
154
+
155
+ ### Versão de host suportada
156
+
157
+ O plugin declara os pacotes do DeepSeek Harness como **peer dependencies** (`@deepseek-ai/dsh-fs`, `dsh-llm`, `dsh-sandbox`, `dsh-subprocess`, `dsh-tools` ≥ `0.1.0-rc.6`), de modo que uma única cópia serve ao host e ao plugin. Testado contra `0.1.0-rc.6`.
158
+
159
+ ### Limitações conhecidas
160
+
161
+ - **Documentos transitórios.** Cada ação abre o arquivo, executa uma requisição e o fecha de novo (igual ao host stdio oficial). Servidores baseados em projeto que exigem um arquivo aberto residente para requisições sem documento (o tsls recusa `workspace/symbol` sem um) são atendidos passando `file_path` para `lsp_symbols`, que mantém o arquivo de roteamento aberto durante aquela requisição. O tsls também responde `textDocument/signatureHelp` com `null` sob esse ciclo de vida; outros servidores (gopls, pyright, rust-analyzer) o atendem normalmente.
162
+ - **Formatação de intervalo exige o provider de intervalo do servidor.** Servidores que só anunciam formatação de documento completo falham requisições de intervalo com `LSP_ACTION_UNSUPPORTED`.
163
+ - **A renomeação aplica apenas edições de texto.** Operações de recursos (criar/excluir/renomear arquivos) na resposta de renomeação do servidor são recusadas com `LSP_ACTION_UNSUPPORTED`, e edições fora do workspace falham com `LSP_ACTION_CONFLICT` antes de qualquer escrita. Em servidores `utf-8`/`utf-32`, as posições de renomeação entre arquivos são decodificadas lendo cada arquivo editado; um arquivo editado ilegível falha a chamada como conflito em vez de decodificar mal as posições.
164
+
165
+ ## Desenvolvimento
166
+
167
+ ```sh
168
+ pnpm install
169
+ pnpm run lint # oxlint sobre src/ e tests/
170
+ pnpm test # mais de 240 testes: unidade + integração com servidor fixture + e2e real com tsls
171
+ pnpm run test:coverage # portões: linhas/instruções/funções ≥ 90%, ramos ≥ 85%
172
+ pnpm build # emite lib/
173
+ ```
174
+
175
+ ## License
176
+
177
+ [Apache License 2.0](LICENSE)