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.
Files changed (66) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.es.md +176 -129
  3. package/README.hi.md +176 -129
  4. package/README.md +170 -129
  5. package/README.pt.md +176 -129
  6. package/README.zh.md +224 -0
  7. package/cordis.patch.yml +6 -0
  8. package/docs/editor-protocol.md +159 -0
  9. package/docs/editor-protocol.zh-CN.md +159 -0
  10. package/docs/seam-extension-notes.md +76 -0
  11. package/examples/vscode/README.md +72 -0
  12. package/examples/vscode/README.zh-CN.md +72 -0
  13. package/examples/vscode/backend/bin.mjs +44 -0
  14. package/examples/vscode/backend/cordis.yml +53 -0
  15. package/examples/vscode/backend/package.json +22 -0
  16. package/examples/vscode/extension/package.json +96 -0
  17. package/examples/vscode/extension/src/client.js +100 -0
  18. package/examples/vscode/extension/src/extension.js +187 -0
  19. package/examples/vscode/extension/src/views.js +127 -0
  20. package/lib/client.d.ts +3 -3
  21. package/lib/editor/actions.d.ts +44 -0
  22. package/lib/editor/actions.d.ts.map +1 -0
  23. package/lib/editor/actions.js +370 -0
  24. package/lib/editor/actions.js.map +1 -0
  25. package/lib/editor/cache.d.ts +51 -0
  26. package/lib/editor/cache.d.ts.map +1 -0
  27. package/lib/editor/cache.js +75 -0
  28. package/lib/editor/cache.js.map +1 -0
  29. package/lib/editor/server.d.ts +61 -0
  30. package/lib/editor/server.d.ts.map +1 -0
  31. package/lib/editor/server.js +97 -0
  32. package/lib/editor/server.js.map +1 -0
  33. package/lib/editor/service.d.ts +67 -0
  34. package/lib/editor/service.d.ts.map +1 -0
  35. package/lib/editor/service.js +182 -0
  36. package/lib/editor/service.js.map +1 -0
  37. package/lib/editor/transport.d.ts +53 -0
  38. package/lib/editor/transport.d.ts.map +1 -0
  39. package/lib/editor/transport.js +143 -0
  40. package/lib/editor/transport.js.map +1 -0
  41. package/lib/editor/types.d.ts +185 -0
  42. package/lib/editor/types.d.ts.map +1 -0
  43. package/lib/editor/types.js +13 -0
  44. package/lib/editor/types.js.map +1 -0
  45. package/lib/edits.d.ts +1 -1
  46. package/lib/extra-tools.d.ts +3 -3
  47. package/lib/index.d.ts +17 -11
  48. package/lib/index.d.ts.map +1 -1
  49. package/lib/index.js +26 -1
  50. package/lib/index.js.map +1 -1
  51. package/lib/runner.d.ts +5 -5
  52. package/lib/seam.d.ts +1 -1
  53. package/lib/servers.d.ts +20 -1
  54. package/lib/servers.d.ts.map +1 -1
  55. package/lib/servers.js +6 -0
  56. package/lib/servers.js.map +1 -1
  57. package/lib/tools.d.ts +18 -5
  58. package/lib/tools.d.ts.map +1 -1
  59. package/lib/tools.js +2 -2
  60. package/lib/tools.js.map +1 -1
  61. package/lib/translate.d.ts +1 -1
  62. package/lib/vocabulary.d.ts +3 -1
  63. package/lib/vocabulary.d.ts.map +1 -1
  64. package/lib/vocabulary.js.map +1 -1
  65. package/package.json +61 -8
  66. package/README.zh-CN.md +0 -181
package/CHANGELOG.md CHANGED
@@ -3,6 +3,63 @@
3
3
  All notable changes to dsh-lsp-actions are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## 0.3.1 — 2026-08-19
7
+
8
+ ### Fixed
9
+
10
+ - The editor service's request-id serial is now instance-owned instead of module-level, matching its documented per-instance semantics — a plugin reload no longer shares counter state across mounts.
11
+
12
+ ## 0.3.0 — 2026-08-16
13
+
14
+ ### Added
15
+
16
+ - **Editor action protocol v1 — the IDE integration backend.** With `editor.enabled: true` in a
17
+ dedicated headless composition, the plugin serves `lsp.actions.list` / `lsp.actions.run` /
18
+ `lsp.events` over newline-delimited JSON-RPC 2.0 (wire-framing-compatible with the official
19
+ SDK/ACP transports), so any editor can consume the LSP capabilities directly — no agent round-trip.
20
+ - Four v1 actions: `diagnostics.get` (read-only), `completion.get` (read-only, zero-based LSP
21
+ positions), `quickfix.apply` (selects a server-verified code action by `title`/`index` and
22
+ applies its edits), and `format` (whole-file or range).
23
+ - `run` always answers one structured `{ requestId, action, status, result | error }` envelope;
24
+ failures carry the stable `LSP_ACTION_*` codes, extended with `LSP_ACTION_UNKNOWN`,
25
+ `LSP_ACTION_INVALID_ARGS`, `LSP_ACTION_APPROVAL_UNAVAILABLE`, and
26
+ `LSP_PROTOCOL_VERSION_UNSUPPORTED`.
27
+ - Streamed `lsp.event` notifications: `diagnostics.updated`, `action.status`, `file.changed`,
28
+ `sessions.changed`; `lsp.events {subscribe}` controls the stream.
29
+ - **Versioning & backward compatibility**: `lsp-actions/v1` is frozen; evolution is additive
30
+ only; breaking changes ship under a new protocol version. Documented in the bilingual spec
31
+ [`docs/editor-protocol.md`](docs/editor-protocol.md) / [`docs/editor-protocol.zh-CN.md`](docs/editor-protocol.zh-CN.md).
32
+ - **Official permission presets and approval for editor writes.** `quickfix.apply` and `format`
33
+ resolve the addressed session's official sandbox policy (read-only sessions fail with
34
+ `LSP_ACTION_READ_ONLY` before any server round-trip), write through the `fs/write-intent`
35
+ waterfall with guarded writes, and resolve the `sandbox_permissions` + `justification` escalation
36
+ pair through the official `approveEscalation` ask (fail-closed with
37
+ `LSP_ACTION_APPROVAL_UNAVAILABLE` when no answerer can decide).
38
+ - **Bounded LRU diagnostics cache** (`editor.diagnosticsCacheMaxFiles`, default 64):
39
+ freshness-stamped snapshots, least-recently-used eviction, invalidated by filesystem
40
+ observations and by the plugin's own writes; never persisted across restarts. Cached
41
+ first-error ranges power range-less `quickfix.apply` targeting.
42
+ - **Schema configuration** for the backend: `editor.enabled` (default `false` — only headless
43
+ backends may claim stdio), `editor.requestTimeoutMs` (default 60000, enforced per run), and
44
+ `editor.diagnosticsCacheMaxFiles`. Misconfiguration fails at load.
45
+ - **Reversible registration.** The transport, event listeners, and cache live entirely inside the
46
+ plugin's effect scope; stopping or updating the plugin tears the whole surface down.
47
+ - **`examples/vscode/`**: a minimal UI-only VS Code extension (sidebar with DSH sessions +
48
+ diagnostics list + one-click quickfix + open-at-range + format) plus the headless backend
49
+ composition (`backend/cordis.yml` + `bin.mjs`). The extension implements zero LSP logic.
50
+ - **Tests**: bounded-LRU coverage, editor-protocol service semantics (permission gating, escalation
51
+ fail-closed, timeouts, cache invalidation), and a full diagnostics → quickfix → format chain over
52
+ real JSON-RPC frames against the fixture LSP server.
53
+
54
+ ### Changed
55
+
56
+ - **Prompt hygiene commitment**: the plugin injects no persona or prompt prose (model-facing
57
+ surface = the eight tool schemas); any future prompt segment must open with one short role
58
+ sentence and stay brief, aligned with the official Minimal persona style.
59
+ - README (EN/zh-CN) now documents the IDE-backend architecture (editor protocol × official ACP
60
+ server × Python SDK), the versioning promise, the VS Code example, and the extended error-code
61
+ table; es/hi/pt READMEs point at the canonical protocol docs.
62
+
6
63
  ## 0.2.0 — 2026-08-15
7
64
 
8
65
  ### Added
package/README.es.md CHANGED
@@ -2,93 +2,163 @@
2
2
 
3
3
  # 🛰️ dsh-lsp-actions
4
4
 
5
- **La superficie de acción LSP para DeepSeek Harness — servidores de lenguaje reales, retroalimentación real.**
5
+ **La superficie de acción LSP para DeepSeek Harness — servidores de lenguaje reales, retroalimentación real y el backend de integración IDE para editores.**
6
6
 
7
- Diagnósticos, formateo, completado de código, correcciones rápidas, símbolos, ayuda de firmas y sugerencias insertadas para el bucle del editor de tu agente, impulsados por los mismos servidores de lenguaje que usa tu IDE.
7
+ *Diagnósticos, formateo, completado, acciones de código, símbolos, ayuda de firmas, sugerencias insertadas y renombrado para el bucle de editor de tu agente — más el protocolo estable de acciones para editores (`lsp.actions.*`) que permite a cualquier editor consumirlos directamente.*
8
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)
9
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
10
+ [![DSH plugin](https://img.shields.io/badge/dsh-plugin-✅-green)](https://github.com/topics/dsh-plugin)
11
+ [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
12
+ [![CI](https://img.shields.io/github/actions/workflow/status/PerryLink/dsh-lsp-actions/ci.yml?branch=main&label=CI)](https://github.com/PerryLink/dsh-lsp-actions/actions)
13
+ [![Version](https://img.shields.io/github/v/tag/PerryLink/dsh-lsp-actions?label=version)](https://github.com/PerryLink/dsh-lsp-actions/releases)
14
+ [![npm version](https://img.shields.io/npm/v/dsh-lsp-actions)](https://www.npmjs.com/package/dsh-lsp-actions)
15
+ [![npm downloads](https://img.shields.io/npm/dm/dsh-lsp-actions)](https://www.npmjs.com/package/dsh-lsp-actions)
13
16
 
14
- [English](README.md) · [简体中文](README.zh-CN.md) · [Español](README.es.md) · [हिन्दी](README.hi.md) · [Português](README.pt.md)
17
+ [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
15
18
 
16
19
  </div>
17
20
 
18
21
  ---
19
22
 
20
- ## Qué aporta este plugin a tu agente
23
+ ## Compatibility
21
24
 
22
- El seam oficial `ctx.lsp` de DeepSeek Harness cubre la **navegación** (ir a definición, referencias, implementación, hover). `dsh-lsp-actions` completa la **superficie de acción**: el bucle de retroalimentación que un agente necesita mientras escribe y corrige código:
25
+ | Surface | Status |
26
+ |---|---|
27
+ | Harness | DeepSeek Harness `0.1.0-rc.6` (compatibilidad declarada para `>=0.1.0-rc.6`) |
28
+ | Node | `^22.19.0 \|\| >=24.0.0` |
29
+ | Platforms | Todas (host puro; subprocesos + sistema de archivos, sin red) |
30
+ | Model | Cualquiera (las herramientas son independientes del modelo; el plugin nunca llama a un modelo) |
23
31
 
24
- | Herramienta | Qué hace | ¿Escribe? |
25
- | --- | --- | --- |
26
- | `lsp_diagnostics <file>` | Errores, advertencias y sugerencias del compilador/analizador con severidad, rango, mensaje y servidor de origen | ❌ solo lectura |
27
- | `lsp_format <file> [range?]` | Formatea un archivo o selección mediante el servidor de lenguaje y aplica el resultado, devolviendo el diff | ✅ vía `fs/write-intent` + política sandbox |
28
- | `lsp_completion <file> <line> <character>` | Sugerencias de completado en una posición del cursor, incluido el texto de inserción real | ❌ solo lectura |
29
- | `lsp_code_action <file> [range?] [only?]` | Correcciones/refactorizaciones verificadas por el servidor (con sus ediciones) para un rango o el primer diagnóstico | ❌ solo referencia |
30
- | `lsp_symbols <query?> <file_path?>` | Búsqueda de símbolos por nombre en todo el workspace, o el esquema de símbolos de un archivo | ❌ solo lectura |
31
- | `lsp_signature <file> <line> <character>` | Ayuda de firmas (parámetros y documentación) dentro de una llamada | ❌ solo lectura |
32
- | `lsp_inlay_hints <file> [range?]` | Anotaciones de tipo y sugerencias de nombres de parámetros del servidor | ❌ solo lectura |
33
- | `lsp_rename <file> <line> <character> <new_name>` | Renombrado de símbolo verificado por el servidor, aplicado en todo el workspace con diffs por archivo | ✅ vía `fs/write-intent` + política sandbox |
32
+ ## What you get
34
33
 
35
- > ✨ Una ejecución real de `typescript-language-server` forma parte de la suite de tests: diagnósticos, formateo, completado, búsqueda de símbolos y renombrado se verifican de extremo a extremo contra un servidor vivo, no solo con mocks. La suite es autocontenida (tsls es una devDependency) y corre en CI con Node 22/24 en Linux, Windows y macOS.
34
+ `dsh-lsp-actions` se monta como una única fila de host (`id: lsp-actions`, `name: dsh-lsp-actions`, `inject: [tools, fs, subprocess]`). El seam oficial `ctx.lsp` de DeepSeek Harness cubre la **navegación** (ir a definición, referencias, implementación, hover); este plugin completa la **superficie de acción**: el bucle de retroalimentación que un agente necesita mientras escribe y corrige código:
36
35
 
37
- ## Inicio rápido
36
+ 1. **Ocho herramientas `lsp_*`** — diagnósticos, formateo, completado, acciones de código, símbolos, ayuda de firmas, sugerencias insertadas y renombrado, todas servidas por los mismos servidores de lenguaje que usa tu IDE.
37
+ 2. **Protocolo de acciones para editores v1** — una superficie JSON-RPC estable (`lsp.actions.list` / `lsp.actions.run` / `lsp.events`) que permite a cualquier editor (VS Code primero) consumir esas capacidades directamente.
38
+ 3. **Verificación con servidor real** — una ejecución real de `typescript-language-server` forma parte de la suite de tests (autocontenida, CI en Node 22/24 en Linux, Windows y macOS), no solo mocks.
38
39
 
39
- ```sh
40
- dsh plugin --profile <name> add <ruta-o-tarball-de-dsh-lsp-actions>
41
- ```
40
+ ## Quick start
42
41
 
43
- Configura una entrada por servidor de lenguaje (la forma replica la configuración oficial de `lsp-stdio`):
44
-
45
- ```yaml
46
- # en el cordis.patch.yml de tu perfil (o en la fila del 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
- ```
42
+ ```sh
43
+ # 1. install the bundle into your profile
44
+ dsh plugin --profile web add "github:PerryLink/dsh-lsp-actions#main"
73
45
 
74
- Las ocho herramientas se registran siempre. Con una **tabla `servers` vacía y ningún seam `ctx.lsp` montado, las llamadas fallan en voz alta** con `LSP_ACTION_UNAVAILABLE` indicando qué configurar — el plugin nunca arranca servidores que no configuraste. Un seam `ctx.lsp` montado **después** de este plugin se detecta en la siguiente llamada (la detección del seam es por llamada, así que el orden de carga no importa).
46
+ # or from npm (published releases)
47
+ dsh plugin --profile web add dsh-lsp-actions
75
48
 
76
- ## Por qué es seguro por construcción
49
+ # 2. restart and verify the row
50
+ dsh --profile web --dump-config | grep -A3 'id: lsp-actions'
51
+ ```
77
52
 
78
- - **El formateo y el renombrado son mutaciones reales, tratadas como `write`/`edit`.** Cada byte pasa por el waterfall `fs/write-intent` (observación → escritura protegida → observación) y por la política sandbox de cada llamada. `lsp_rename` pre-vuela cada archivo editado (contención en el workspace, comprobación de solapamientos, lectura con tope de bytes) *antes* de la primera escritura, de modo que una respuesta mala del servidor no puede dejar un renombrado a medio aplicar.
79
- - **Todo lo demás es de solo lectura por diseño.** Las acciones de código, completados, símbolos, firmas y sugerencias se reportan como material de referencia; aplicarlas es decisión propia del modelo con write/edit. Las formas de comando se reportan y **nunca se ejecutan**.
80
- - **Las sesiones de solo lectura fallan en voz alta, rápido y estructurado** — `LSP_ACTION_READ_ONLY` con el marcador compartido `[sandbox: …]`, lanzado *antes* de cualquier ida y vuelta con el servidor.
81
- - **La escalada coincide con las herramientas oficiales.** Bajo un sistema de archivos restrictivo, `lsp_format` y `lsp_rename` anuncian el mismo reintento único `sandbox_permissions` / `justification` que `write`/`edit`, resuelto mediante `ctx.approval`.
82
- - **Los conflictos nunca pisan nada.** Si el archivo cambió en disco después de leerse, la escritura protegida falla con `LSP_ACTION_CONFLICT` y se le dice al modelo que elija: releer y repetir, o aplicar el diff manualmente.
83
- - **Los timeouts son de la plataforma.** Cada herramienta declara `timeoutMs`; la política oficial `dsh-tool-call-timeout-policy` lo hace cumplir, y cada await respeta `exec.signal`.
84
- - **No se cachea nada.** Los resultados viven solo en el log de sesión; no hay persistencia entre sesiones.
53
+ ## Install & uninstall
54
+
55
+ - **git channel** (último `main`): `dsh plugin --profile web add "github:PerryLink/dsh-lsp-actions#main"` — el script `prepare` compila (`tsc --noEmitOnError`).
56
+ - **npm channel** (versiones publicadas): `dsh plugin --profile web add dsh-lsp-actions`.
57
+ - **tarball channel**: ejecuta `pnpm pack` en este repo y luego `dsh plugin --profile web add ./dsh-lsp-actions-<version>.tgz`.
58
+ - **uninstall**: `dsh plugin --profile web remove dsh-lsp-actions` (o quita la fila del patch del perfil).
59
+
60
+ ## Configuration
61
+
62
+ Todos los ajustes son campos Schemastery `Config` (modificables desde cordis.yml). Una sobrescritura dirigida por id reemplaza toda la fila — repite cada clave que necesites. `cordis.patch.yml` documenta cada clave en línea.
63
+
64
+ | Key | Default | Meaning |
65
+ |---|---|---|
66
+ | `servers` | `{}` | Servidores de lenguaje nombrados; una tabla vacía no activa ningún servidor |
67
+ | `editor.enabled` | `false` | Sirve el protocolo de acciones para editores por JSON-RPC stdio (solo backend headless) |
68
+ | `editor.requestTimeoutMs` | `60000` | Presupuesto de timeout por ejecución (ms) del protocolo de editor |
69
+ | `editor.diagnosticsCacheMaxFiles` | `64` | Tamaño de la caché LRU de diagnósticos (en archivos) |
70
+ | `maxDiagnostics` | `200` | Tope de diagnósticos por resultado |
71
+ | `maxCompletionItems` | `20` | Tope de elementos de completado por resultado |
72
+ | `maxCodeActions` | `50` | Tope de acciones de código por resultado |
73
+ | `maxSymbols` | `100` | Tope de resultados de símbolos |
74
+ | `maxSignatures` | `10` | Tope de ayuda de firmas |
75
+ | `maxInlayHints` | `200` | Tope de sugerencias insertadas |
76
+ | `maxResultChars` | `16000` | Tope del resultado renderizado (caracteres) |
77
+ | `maxDocumentBytes` | `4000000` | Tope de lectura de documento (bytes) |
78
+ | `timeoutMs` | `60000` | Timeout por llamada, aplicado por la política oficial de timeout |
79
+
80
+ Cada entrada de `servers` es un `LspServerEntry`: `command` (ejecutable resuelto en PATH al cargar) y `extensionToLanguage` (`".ts"` → `typescript`) son obligatorios; los opcionales `fileGlobs`, `args`, `env`, `initializationOptions`, `configuration`, `formattingOptions`, `maxMessageBytes`, `maxStderrBytes`, `killGraceMs`, `shutdownTimeoutMs`, `diagnosticsSettleMs`, `diagnosticsDebounceMs` e `idleTimeoutMs` (`0` = mantener vivo el proceso del servidor) ajustan el cliente stdio integrado.
81
+
82
+ ## Tools & surfaces
83
+
84
+ | Surface | Kind | Notes |
85
+ |---|---|---|
86
+ | `lsp_diagnostics` | tool | `<file>` — errores, advertencias y sugerencias del compilador/analizador con severidad, rango, mensaje y servidor de origen (solo lectura) |
87
+ | `lsp_format` | tool | `<file> [range?]` — formatea un archivo/selección mediante el servidor de lenguaje y lo aplica, devolviendo el diff (escribe vía `fs/write-intent`) |
88
+ | `lsp_completion` | tool | `<file> <line> <character>` — sugerencias de completado en una posición del cursor, incluido el texto de inserción (solo lectura) |
89
+ | `lsp_code_action` | tool | `<file> [range?] [only?]` — correcciones/refactorizaciones verificadas por el servidor con sus ediciones, para un rango o el primer diagnóstico (solo referencia) |
90
+ | `lsp_symbols` | tool | `<query?> <file_path?>` — búsqueda de símbolos por nombre en todo el workspace, o el esquema de un archivo (solo lectura) |
91
+ | `lsp_signature` | tool | `<file> <line> <character>` — ayuda de firmas (parámetros y documentación) dentro de una llamada (solo lectura) |
92
+ | `lsp_inlay_hints` | tool | `<file> [range?]` — anotaciones de tipo y sugerencias de nombres de parámetros del servidor (solo lectura) |
93
+ | `lsp_rename` | tool | `<file> <line> <character> <new_name>` — renombrado verificado por el servidor, aplicado en todo el workspace con diffs por archivo (escribe vía `fs/write-intent`) |
94
+ | `lsp.actions.*` | protocol | Protocolo de acciones para editores v1: `lsp.actions.list` / `lsp.actions.run` / `lsp.events` por JSON-RPC |
95
+ | `examples/vscode/` | extension | Extensión de VS Code solo-UI más la composición de backend headless a la que se conecta |
96
+
97
+ ## Editor action protocol v1
98
+
99
+ Cuando se establece `editor.enabled: true` en una composición headless dedicada, `dsh-lsp-actions` sirve un protocolo de editor estable por JSON-RPC 2.0 delimitado por saltos de línea (el mismo encuadre de wire que los transportes oficiales SDK/ACP):
100
+
101
+ | Method | What it does |
102
+ |---|---|
103
+ | `lsp.actions.list` | Devuelve la versión de protocolo `lsp-actions/v1`, el catálogo de acciones (`diagnostics.get`, `completion.get`, `quickfix.apply`, `format` — cada una marcada `writes`) y las sesiones DSH direccionables |
104
+ | `lsp.actions.run` | Ejecuta una acción con un sobre estructurado `{ requestId, action, status, result \| error }`; los errores llevan los códigos estables `LSP_ACTION_*` |
105
+ | `lsp.events` | Se suscribe a las notificaciones `lsp.event` transmitidas: `diagnostics.updated`, `action.status`, `file.changed`, `sessions.changed` |
106
+
107
+ Todas las acciones de escritura (`quickfix.apply`, `format`) pasan por los **presets de permisos oficiales y la aprobación**: una sesión `read-only` es rechazada con `LSP_ACTION_READ_ONLY` antes de cualquier ida y vuelta con el servidor, las ediciones viajan por el waterfall `fs/write-intent` y el par de escalado `sandbox_permissions` + `justification` se resuelve mediante el `approveEscalation` oficial (fail-closed cuando no hay quién decida). Especificación de wire completa, bilingüe: [`docs/editor-protocol.md`](docs/editor-protocol.md) · [`docs/editor-protocol.zh-CN.md`](docs/editor-protocol.zh-CN.md).
108
+
109
+ **Versionado y la promesa de compatibilidad hacia atrás**
110
+
111
+ - El protocolo está versionado — `lsp.actions.list` devuelve `protocol: "lsp-actions/v1"`, `version: 1`. **v1 está congelado:** los nombres de campos, ids de acción, tipos de evento y códigos de error se mantienen estables para siempre.
112
+ - La evolución es **solo aditiva**: nuevas acciones, campos y tipos de evento llegan sin subir la versión; la semántica existente nunca cambia en su sitio; un cambio que rompe compatibilidad se publica bajo una nueva versión de `protocol`, que los servidores pueden servir en paralelo.
113
+ - Los clientes deben ignorar campos, tipos de evento y acciones desconocidos, y enrutar por el `code` de error estable, nunca por el texto del mensaje.
114
+
115
+ **Códigos de error**
116
+
117
+ Cada fallo lleva un `code` estable; los modelos y llamadores enrutan por el código, nunca por el texto del mensaje.
118
+
119
+ | Code | Meaning |
120
+ |---|---|
121
+ | `LSP_ACTION_UNAVAILABLE` | Ninguna entrada de servidor ni provider del seam maneja este archivo |
122
+ | `LSP_ACTION_UNSUPPORTED` | El servidor (o el provider del seam) no anuncia la operación |
123
+ | `LSP_ACTION_SERVER_FAILED` | El servidor falló (con la cola de su stderr); los fallos de arranque reintentan una vez |
124
+ | `LSP_ACTION_MALFORMED_RESPONSE` | El servidor envió una carga estructuralmente inválida |
125
+ | `LSP_ACTION_CONFLICT` | El archivo cambió desde que se leyó, o las ediciones se solapan / salen de límites / salen del workspace |
126
+ | `LSP_ACTION_READ_ONLY` | El modo sandbox de la sesión prohíbe la escritura del formateo/renombrado |
127
+ | `LSP_ACTION_WORKSPACE_REQUIRED` | La sesión que llama no tiene un cwd de workspace donde enraizar el servidor |
128
+ | `LSP_ACTION_NO_SYMBOL` | El servidor no encontró un símbolo renombrable en la posición del cursor |
129
+ | `LSP_ACTION_UNKNOWN` | Protocolo de editor: id de acción desconocido, o ninguna acción de código coincidió con `title`/`index` |
130
+ | `LSP_ACTION_INVALID_ARGS` | Protocolo de editor: parámetros de acción mal formados |
131
+ | `LSP_ACTION_APPROVAL_UNAVAILABLE` | Protocolo de editor: la ruta de aprobación no pudo conceder un modo sandbox más amplio (fail-closed) |
132
+ | `LSP_PROTOCOL_VERSION_UNSUPPORTED` | Protocolo de editor: la versión de protocolo declarada no es compatible |
133
+
134
+ ## VS Code extension
135
+
136
+ [`examples/vscode/`](examples/vscode/) incluye una extensión **solo-UI** (barra lateral con las sesiones DSH, la lista de diagnósticos, aplicar quickfix con un clic, abrir en rango y formatear) más la composición de backend headless (`backend/cordis.yml`) a la que se conecta por JSON-RPC estilo ACP. La extensión implementa cero lógica LSP — cada capacidad y cada byte escrito pertenecen al plugin. Los pasos de instalación, ajustes y el script de grabación del gif de demostración están en [`examples/vscode/README.md`](examples/vscode/README.md).
137
+
138
+ ![Editor demo](docs/editor-demo.gif)
139
+
140
+ ## Permissions & data
141
+
142
+ - **Permisos**: el formateo y el renombrado viajan por los presets de permisos oficiales y la aprobación — el waterfall `fs/write-intent` y el par de escalado `sandbox_permissions` / `justification` resuelto mediante `ctx.approval`. El plugin declara `fs:read`, `fs:write`, `subprocess:spawn` y `network:none` en su manifiesto de workshop.
143
+ - **Datos**: no se almacena nada en disco; los resultados de las herramientas viven solo en el log de sesión (sin persistencia entre sesiones). El protocolo de editor mantiene una única caché LRU de diagnósticos en memoria, acotada, con sello de frescura y nunca persistida entre reinicios.
144
+ - **Sin red**: el plugin no hace peticiones de red; habla con los servidores de lenguaje por stdio de subprocesos locales.
145
+
146
+ ## Security boundaries
147
+
148
+ - **Solo lectura por defecto.** Seis de las ocho herramientas son solo de referencia; únicamente `lsp_format` y `lsp_rename` mutan, y lo hacen como mutaciones reales de `write`/`edit`.
149
+ - **Seams oficiales, no reimplementados.** Cada byte pasa por el waterfall `fs/write-intent` (observación → escritura protegida → observación) y por la política sandbox de cada llamada; el escalado coincide con las herramientas oficiales `write`/`edit`.
150
+ - **Falla en voz alta, rápido y estructurado.** `servers` vacío + sin seam `ctx.lsp` → `LSP_ACTION_UNAVAILABLE`; sesiones de solo lectura → `LSP_ACTION_READ_ONLY` antes de cualquier ida y vuelta con el servidor; las formas de comando se reportan y nunca se ejecutan.
151
+ - **Los conflictos nunca pisan nada.** Un archivo cambiado en disco tras leerse falla con `LSP_ACTION_CONFLICT`; `lsp_rename` pre-vuela cada archivo editado antes de la primera escritura.
152
+ - **Trabajo acotado.** Los topes de resultados, los topes de bytes y la política de timeout de la plataforma acotan cada llamada; la caché de diagnósticos es una LRU acotada.
153
+ - **Nada se cachea en la ruta del modelo.** Los resultados de las herramientas viven solo en el log de sesión; la caché de diagnósticos nunca persiste entre reinicios.
85
154
  - **Los servidores rotos fallan en voz alta.** Un ejecutable inexistente falla al cargar; un servidor que muere al arrancar falla la llamada con `LSP_ACTION_SERVER_FAILED` más la cola de su stderr (tras un reintento con proceso nuevo).
155
+ - **Higiene del prompt.** El plugin no inyecta persona ni prosa de prompt en el system prompt de la sesión — su superficie de cara al modelo son los ocho esquemas de herramientas.
86
156
 
87
- ## Arquitectura
157
+ ## Architecture
88
158
 
89
159
  Las acciones van **primero por el seam oficial** y caen al cliente stdio mínimo propio del plugin:
90
160
 
91
- ```
161
+ ```text
92
162
  lsp_diagnostics / lsp_format / lsp_completion / lsp_code_action /
93
163
  lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
94
164
  │
@@ -99,79 +169,56 @@ lsp_symbols / lsp_signature / lsp_inlay_hints / lsp_rename
99
169
  cliente stdio integrado ← tabla servers (ctx.subprocess.spawn + JSON-RPC)
100
170
  ```
101
171
 
102
- La extensión del seam está propuesta upstream (`upstream/lsp-action-seam.patch`, descripción del PR en `upstream/PR-description.md`). Cuando aterrice, el plugin sigue funcionando sin cambios — el cliente integrado simplemente deja de usarse. El cliente integrado se conserva como respaldo independiente para la tabla `servers`. Notas completas de investigación y diseño: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md), [`upstream/README.md`](upstream/README.md).
103
-
104
- ## Referencia de configuración
105
-
106
- ```ts
107
- interface Config {
108
- /** Servidores de lenguaje nombrados; vacío = el cliente propio no sirve nada. */
109
- servers?: Record<string, LspServerEntry>
110
- maxDiagnostics?: number // por defecto 200
111
- maxCompletionItems?: number // por defecto 20
112
- maxCodeActions?: number // por defecto 50
113
- maxSymbols?: number // por defecto 100
114
- maxSignatures?: number // por defecto 10
115
- maxInlayHints?: number // por defecto 200
116
- maxResultChars?: number // por defecto 16000 (tope del resultado renderizado completo)
117
- maxDocumentBytes?: number // por defecto 4000000
118
- timeoutMs?: number // por defecto 60000 (aplicado por la política oficial de timeout)
119
- }
120
-
121
- interface LspServerEntry {
122
- command: string // ejecutable, resuelto en PATH al cargar
123
- extensionToLanguage: Record<string, string> // ".ts" → "typescript"
124
- fileGlobs?: string[] // opcional; los globs ganan al mapa de extensiones
125
- args?: string[] // sin shell
126
- env?: Record<string, string>
127
- initializationOptions?: unknown
128
- configuration?: unknown // forma de objeto responde workspace/configuration por sección
129
- formattingOptions?: unknown // p. ej. { tabSize: 2, insertSpaces: true }
130
- maxMessageBytes?: number // por defecto 16000000
131
- maxStderrBytes?: number // por defecto 1000000
132
- killGraceMs?: number // por defecto 2000
133
- shutdownTimeoutMs?: number // por defecto 5000
134
- diagnosticsSettleMs?: number // por defecto 2000 (ventana de diagnósticos solo push)
135
- diagnosticsDebounceMs?: number // por defecto 250 (período de calma tras el último lote empujado)
136
- idleTimeoutMs?: number // por defecto 0 (0 = mantener vivo el proceso del servidor)
137
- }
138
- ```
172
+ La extensión del seam está propuesta upstream (`upstream/lsp-action-seam.patch`, descripción del PR en `upstream/PR-description.md`). Cuando aterrice, el plugin sigue funcionando sin cambios — el cliente integrado simplemente deja de usarse. El cliente integrado se conserva como respaldo independiente para la tabla `servers`. El **protocolo de editor** usa el mismo runner, la misma ruta de escritura y la misma maquinaria de permisos. Notas completas de investigación y diseño: [`docs/seam-extension-notes.md`](docs/seam-extension-notes.md).
139
173
 
140
- ### Códigos de error
174
+ ## Known limitations
141
175
 
142
- Cada fallo lleva un `code` estable en el resultado de error; los modelos y llamadores enrutan por el código, nunca por el texto del mensaje.
176
+ - **Documentos transitorios.** Cada acción abre el archivo, ejecuta una petición y lo cierra de nuevo (igual que el host stdio oficial). Los servidores basados en proyecto que exigen un archivo abierto residente para peticiones sin documento (tsls rechaza `workspace/symbol` sin uno) se sirven pasando `file_path` a `lsp_symbols`. tsls también responde `textDocument/signatureHelp` con `null` bajo este ciclo de vida; otros servidores (gopls, pyright, rust-analyzer) lo sirven con normalidad.
177
+ - **El formateo de rango exige el provider de rango del servidor.** Los servidores que solo anuncian formateo de documento completo fallan las peticiones de rango con `LSP_ACTION_UNSUPPORTED`.
178
+ - **El renombrado solo aplica ediciones de texto.** Las operaciones de recursos (crear/borrar/renombrar archivos) en la respuesta de renombrado del servidor se rechazan con `LSP_ACTION_UNSUPPORTED`, y las ediciones fuera del workspace fallan como `LSP_ACTION_CONFLICT` antes de escribir nada.
143
179
 
144
- | Code | Significado |
145
- | --- | --- |
146
- | `LSP_ACTION_UNAVAILABLE` | Ninguna entrada de servidor ni provider del seam maneja este archivo. |
147
- | `LSP_ACTION_UNSUPPORTED` | El servidor (o el provider del seam) no anuncia la operación. |
148
- | `LSP_ACTION_SERVER_FAILED` | El servidor falló (con la cola de su stderr); los fallos de arranque reintentan una vez. |
149
- | `LSP_ACTION_MALFORMED_RESPONSE` | El servidor envió una carga estructuralmente inválida. |
150
- | `LSP_ACTION_CONFLICT` | El archivo cambió desde que se leyó, o las ediciones del servidor se solapan / salen de límites / salen del workspace. |
151
- | `LSP_ACTION_READ_ONLY` | El modo sandbox de la sesión prohíbe la escritura del formateo/renombrado. |
152
- | `LSP_ACTION_WORKSPACE_REQUIRED` | La sesión que llama no tiene un cwd de workspace donde enraizar el servidor. |
153
- | `LSP_ACTION_NO_SYMBOL` | El servidor no encontró un símbolo renombrable en la posición del cursor. |
180
+ ## Development
154
181
 
155
- ### Versión de host soportada
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
+ ```
156
191
 
157
- El plugin declara los paquetes de 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 una sola copia sirve al host y al plugin. Probado contra `0.1.0-rc.6`.
192
+ ## Topics
158
193
 
159
- ### Limitaciones conocidas
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`
160
195
 
161
- - **Documentos transitorios.** Cada acción abre el archivo, ejecuta una petición y lo cierra de nuevo (igual que el host stdio oficial). Los servidores basados en proyecto que exigen un archivo abierto residente para peticiones sin documento (tsls rechaza `workspace/symbol` sin uno) se sirven pasando `file_path` a `lsp_symbols`, que mantiene el archivo de enrutamiento abierto durante esa petición. tsls también responde `textDocument/signatureHelp` con `null` bajo este ciclo de vida; otros servidores (gopls, pyright, rust-analyzer) lo sirven con normalidad.
162
- - **El formateo de rango exige el provider de rango del servidor.** Los servidores que solo anuncian formateo de documento completo fallan las peticiones de rango con `LSP_ACTION_UNSUPPORTED`.
163
- - **El renombrado solo aplica ediciones de texto.** Las operaciones de recursos (crear/borrar/renombrar archivos) en la respuesta de renombrado del servidor se rechazan con `LSP_ACTION_UNSUPPORTED`, y las ediciones fuera del workspace fallan con `LSP_ACTION_CONFLICT` antes de escribir nada. En servidores `utf-8`/`utf-32`, las posiciones de renombrado entre archivos se decodifican leyendo cada archivo editado; un archivo editado ilegible falla la llamada como conflicto en lugar de decodificar mal las posiciones.
196
+ ## Contributors
164
197
 
165
- ## Desarrollo
198
+ - [@PerryLink](https://github.com/PerryLink) — creador y mantenedor: el cliente de acciones LSP y el ciclo de vida del servidor, las ocho herramientas, el protocolo de acciones para editores, los tests, la CI y la documentación en cinco idiomas.
166
199
 
167
- ```sh
168
- pnpm install
169
- pnpm run lint # oxlint sobre src/ y tests/
170
- pnpm test # más de 240 tests: unidad + integración con servidor fixture + e2e real con tsls
171
- pnpm run test:coverage # puertas: líneas/sentencias/funciones ≥ 90%, ramas ≥ 85%
172
- pnpm build # emite lib/
173
- ```
200
+ ## PerryLink DSH Plugin Family
201
+
202
+ Este proyecto es uno de los [15 plugins de DeepSeek Harness](https://github.com/PerryLink) mantenidos por [PerryLink](https://github.com/PerryLink). Si este te ayuda, es probable que los demás también:
203
+
204
+ | Plugin | One-liner |
205
+ |---|---|
206
+ | [dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel) | Panel de runtime MCP de solo lectura: comando /mcp + pestaña de configuración con estado, herramientas y errores |
207
+ | [dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck) | Guardia de disciplina de ingeniería: interrogatorio de requisitos, puertas de test, revisión adversaria |
208
+ | [dsh-background-agents](https://github.com/PerryLink/dsh-background-agents) | Agentes hijos en segundo plano duraderos con una barra lateral Web, mensajería e interrupción |
209
+ | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | Diagnósticos, formateo, completado, acciones de código y renombrado LSP sobre servidores de lenguaje |
210
+ | [dsh-output-styles](https://github.com/PerryLink/dsh-output-styles) | Cambio de estilo en tiempo de ejecución equivalente a outputStyles de Claude Code |
211
+ | [dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind) | Equivalente a /rewind de Claude Code: instantáneas, bifurcaciones de sesión, restauración de un solo paso |
212
+ | [dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules) | Reglas de permisos declarativas allow/deny/ask estilo Claude Code con auditoría |
213
+ | [dsh-auto-review](https://github.com/PerryLink/dsh-auto-review) | Auto-revisión con segundo modelo en la cadena de aprobación, fail-closed por defecto |
214
+ | [dsh-memento](https://github.com/PerryLink/dsh-memento) | Memoria entre sesiones con puerta de aprobación: seam ctx.memory + SQLite + herramienta memory |
215
+ | [dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security) | Paquete de habilidades de auditoría de seguridad: escaneo de secretos, revisión de dependencias y cadena de suministro |
216
+ | [dsh-session-pin](https://github.com/PerryLink/dsh-session-pin) | Fija sesiones en la barra lateral Web con orden duradero |
217
+ | [dsh-composer-history](https://github.com/PerryLink/dsh-composer-history) | Historial de entrada estilo terminal para el compositor web: flechas, búsqueda Ctrl+R |
218
+ | [dsh-github](https://github.com/PerryLink/dsh-github) | Integración de PR/issues de GitHub para DSH, cada escritura con puerta de aprobación |
219
+ | [dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide) | Base de conocimiento de desarrollo de plugins como habilidad de agente bajo demanda |
220
+ | [dsh-claude-move](https://github.com/PerryLink/dsh-claude-move) | Migra sesiones, memoria, habilidades y CLAUDE.md de Claude Code a DSH |
174
221
 
175
222
  ## License
176
223
 
177
- [Apache License 2.0](LICENSE)
224
+ [Apache License 2.0](LICENSE) © 2026 dsh-lsp-actions contributors