@askdkc/dsh-lsp-server 0.1.10 → 0.1.12

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/README.md CHANGED
@@ -1,33 +1,61 @@
1
1
  # @askdkc/dsh-lsp-server
2
2
 
3
- An LSP plugin for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), providing code navigation, diagnostics, and completion without applying edits.
3
+ A read-only LSP plugin for DeepSeek Harness. It provides code navigation, diagnostics, and completion for PHP/Blade, TypeScript/JavaScript, Svelte, HTML, CSS, and Tailwind.
4
4
 
5
- Supports PHP/Blade via **PHPantom**, TypeScript/JavaScript, Svelte, HTML, CSS, and Tailwind.
5
+ Markdown and other unsupported documents return an explicit `skipped` diagnostic result, not a tool error or a clean-file claim. `lsp_extra status` reports routing suffixes and server availability. See [diagnostic behavior](docs/usage.md#tools).
6
+
7
+ ## Requirements
8
+
9
+ - Node.js 22.19+ (22.x) or 24+
10
+ - DSH providing the `fs`, `subprocess`, `tools`, and `systemPrompt` services
11
+ - PHPantom for PHP/Blade support (`phpantom_lsp` must be in `PATH`)
12
+
13
+ This plugin imposes no DSH version range at startup: imports and initialization report actual failures. This does not guarantee compatibility with every future DSH API.
6
14
 
7
15
  ## Install
8
16
 
9
- Requires Node.js **22.19+ (22.x) or 24+** and DSH **0.2.0-rc.2**. The DSH LSP packages and Node language servers install with this plugin. For PHP/Blade, install **PHPantom** so `phpantom_lsp` is in `PATH`.
17
+ Run this from the DeepSeek Harness project root, after the updated npm release is available:
18
+
19
+ ```sh
20
+ pnpm dsh plugin --profile web add @askdkc/dsh-lsp-server@latest
21
+ ```
22
+
23
+ `@latest` selects the npm `latest` tag. Older releases declared exact DSH host peers and can be skipped after a DSH update. Local source changes do not update the published package.
24
+
25
+ ### Apply a newly published update immediately
10
26
 
11
- Install from npm into the Web profile:
27
+ Bypass pnpm's release-age delay for this operation, including its dependencies:
12
28
 
13
29
  ```sh
14
- dsh plugin --profile web add @askdkc/dsh-lsp-server@latest
30
+ pnpm dsh plugin --profile web add @askdkc/dsh-lsp-server@latest --config.minimum-release-age=0
15
31
  ```
16
32
 
17
- Do not install this plugin with `github:askdkc/dsh-lsp-server`. Git installs must build the untracked `lib` files through `prepare`, which pnpm blocks unless the exact Git dependency is allowed in the Web profile's `allowBuilds`. The published npm package includes the built files.
33
+ The flag reaches the pnpm process running inside the Web profile and overrides its release-age setting without changing global configuration. Reuse this command for every release. See [pnpm's release-age settings](https://pnpm.io/settings/dependency-resolution#minimumreleaseage).
18
34
 
19
- If `plugin add` stops with `ERR_PNPM_IGNORED_BUILDS` for `core-js`, set the build decision in the **Web profile's** `~/.dsh/profiles/web/pnpm-workspace.yaml`. Running `pnpm approve-builds` from the harness project does not configure that profile. To skip the script, add or update:
35
+ An `incompatible with dsh` rejection is a separate check. DSH supports only exact plugin/runtime exemptions; there is no wildcard grant that survives upgrades. If you deliberately accept the compatibility risk (crashes or data loss), run this reusable block from the DSH project root. It reads both versions automatically, grants that exact pair, and installs the same plugin version, so a moving `latest` tag cannot select a different release between approval and installation:
20
36
 
21
- ```yaml
22
- allowBuilds:
23
- core-js: false
37
+ ```sh
38
+ (
39
+ set -eu
40
+ plugin='@askdkc/dsh-lsp-server'
41
+ profile='web'
42
+ plugin_version=$(pnpm view "$plugin@latest" version)
43
+ dsh_version=$(pnpm --silent dsh --version)
44
+ pnpm dsh plugin --profile "$profile" allow-version "$plugin@$plugin_version" \
45
+ --dsh-version "$dsh_version" --accept-risk
46
+ pnpm dsh plugin --profile "$profile" add "$plugin@$plugin_version" --config.minimum-release-age=0
47
+ )
24
48
  ```
25
49
 
26
- If the failed add already wrote the dependency, remove it with `dsh plugin --profile web remove @askdkc/dsh-lsp-server`, then repeat the add command using the same `dsh` launcher (for example, `pnpm dsh`). A dependency alone does not activate the plugin: confirm `@askdkc/dsh-lsp-server` appears in `dsh.profile.bundles` in the profile's `package.json`. See [installation troubleshooting](docs/usage.md#install) for details.
50
+ Change `plugin` and `profile` to reuse it for another plugin or profile. It still creates an exact exemption on each run; it does not make an incompatible plugin compatible. See [DSH's compatibility exemption rules](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/boot/plugin-manager/README.md#version-compatibility-and-exemptions).
27
51
 
28
- Version `0.1.9` is skipped on DSH 0.2.0-rc.2 because it declares DSH `0.2.0-rc.1` host peers. After installing a compatible release, use the explicit `@latest` above to update an existing dependency; an unqualified `plugin add @askdkc/dsh-lsp-server` can leave its locked old version installed with `Already up to date`. The version exemption is not a compatibility fix. Start or restart Web with `dsh web`.
52
+ Start or restart Web without opening a browser, from the same project root:
53
+
54
+ ```sh
55
+ pnpm dsh web --no-open
56
+ ```
29
57
 
30
- [Configuration, tool usage, and troubleshooting](docs/usage.md)
58
+ Install the published npm package, not a Git dependency. The npm package includes its built files; a Git install must build them during `prepare` and may be blocked by the Web profile's `allowBuilds` policy. For install recovery and configuration, see [Usage and configuration](docs/usage.md).
31
59
 
32
60
  ## License
33
61
 
package/cordis.patch.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  - insert:
2
2
  - id: lsp
3
- name: '@deepseek-ai/dsh-lsp'
3
+ name: '@askdkc/dsh-lsp-server/lsp'
4
4
 
5
5
  - id: lsp-webstack-provider
6
6
  name: '@askdkc/dsh-lsp-server/provider'
@@ -14,7 +14,7 @@
14
14
  args: ['--stdio']
15
15
 
16
16
  - id: tool-lsp
17
- name: '@deepseek-ai/dsh-tool-lsp'
17
+ name: '@askdkc/dsh-lsp-server/tool-lsp'
18
18
  config:
19
19
  maxLocations: 200
20
20
  maxResultChars: 32000
package/docs/usage.md CHANGED
@@ -18,17 +18,17 @@ The five Node language servers and TypeScript are package dependencies. PHPantom
18
18
 
19
19
  See the [installation commands](../README.md#install).
20
20
 
21
- Specify `@latest` when upgrading an existing installation. A bare `plugin add @askdkc/dsh-lsp-server` can keep a locked older version and report `Already up to date`; verify the installed version in the Web profile before restarting DSH.
21
+ Run DSH commands from the DeepSeek Harness project root. After a updated npm release is published, use `@latest` to install or upgrade; an unqualified add can keep a locked older version and report `Already up to date`. A local `package.json` version change does not update npm's `latest` tag.
22
22
 
23
23
  ```sh
24
- dsh plugin --profile web list @askdkc/dsh-lsp-server --depth 0
24
+ pnpm dsh plugin --profile web list @askdkc/dsh-lsp-server --depth 0
25
25
  ```
26
26
 
27
- pnpm may warn about missing DSH peer packages because the profile has peer auto-installation disabled. DSH resolves those host services from its own installation; do not add duplicate host packages to the profile just to silence pnpm. A DSH compatibility warning naming this bundle and an old version means the bundle itself still needs upgrading.
27
+ pnpm may warn about missing DSH peer packages because the profile has peer auto-installation disabled. DSH resolves those host services from its own installation; do not add duplicate host packages to the profile just to silence pnpm. Older releases with exact host peers may still be skipped; install the updated release to remove that version gate.
28
28
 
29
29
  The bundle adds `lsp`, `lsp-webstack-provider`, `tool-lsp`, and `tool-lsp-extra` rows. Its `@deepseek-ai/dsh-lsp` and `@deepseek-ai/dsh-tool-lsp` dependencies are installed automatically; do not install them separately. The harness still provides the profile's `fs`, `subprocess`, `tools`, and `systemPrompt` services and the shared Cordis instance. Installing this package does not install the harness itself.
30
30
 
31
- This release pins the DSH LSP service, tool, and four required host services to `0.2.0-rc.2`. A registry `next` dependency could resolve an older prerelease from cached metadata and cause DSH to reject the installed plugin rows. The repository lockfile and packed-artifact test use the same DSH release.
31
+ The four DSH host peers use `*`, including prereleases in DSH's compatibility evaluator. All four bundle rows resolve through this package's own entry points; `/lsp` and `/tool-lsp` re-export the upstream implementations without catching import or initialization errors. The LSP dependencies and development host packages remain pinned to `0.2.0-rc.2` for reproducible builds and tests; those pins do not restrict the host version at startup. Future API compatibility is not guaranteed.
32
32
 
33
33
  DSH may stop `plugin add` with `ERR_PNPM_IGNORED_BUILDS` for `core-js`, a dependency of the bundled HTML/CSS server. Decide whether to allow its build script in DSH's plugin manager. To **deny** the script from the CLI, set `allowBuilds.core-js: false` in the selected profile's `pnpm-workspace.yaml` before adding this bundle:
34
34
 
@@ -37,7 +37,14 @@ allowBuilds:
37
37
  core-js: false
38
38
  ```
39
39
 
40
- The packed-artifact test runs HTML/CSS servers with dependency scripts disabled. If an earlier CLI add stopped after writing the dependency, check that `@askdkc/dsh-lsp-server` appears in `dsh.profile.bundles` in that profile's `package.json`; a dependency entry alone does not activate the bundle. If it is absent, remove the package with `dsh plugin --profile web remove @askdkc/dsh-lsp-server`, set the build decision, then repeat the original add command. Use the same launcher prefix you use for `dsh web`.
40
+ The packed-artifact test runs HTML/CSS servers with dependency scripts disabled. If an earlier add stopped after writing the dependency, check that `@askdkc/dsh-lsp-server` appears in `dsh.profile.bundles` in that profile's `package.json`; a dependency entry alone does not activate the bundle. If it is absent, remove the package, set the build decision, then add it again:
41
+
42
+ ```sh
43
+ pnpm dsh plugin --profile web remove @askdkc/dsh-lsp-server
44
+ pnpm dsh plugin --profile web add @askdkc/dsh-lsp-server@latest
45
+ ```
46
+
47
+ Run both commands from the DeepSeek Harness project root, after a updated npm release is available.
41
48
 
42
49
  If you already enabled another LSP provider for these extensions, remove its overlapping mappings first: DSH intentionally rejects duplicate ownership with `LSP_CONFLICT`. If your profile already declares the `lsp` or `tool-lsp` rows, compose the provider and extra-tool rows manually instead of inserting the whole bundle twice.
43
50
 
@@ -57,6 +64,8 @@ Additional tool calls:
57
64
 
58
65
  Both tools obtain the workspace from the **calling session**. Completion's line and character are **one-based UTF-16**; diagnostic/output ranges are **zero-based UTF-16**. The model cannot supply a different workspace root. The underlying service API uses zero-based positions.
59
66
 
67
+ Diagnostics on existing unsupported documents such as `PLAN.md` return `{"diagnostics":[],"skipped":{"reason":"unsupported_file_type","filePath":"PLAN.md"}}`. This means no static check was performed; use document content and structure checks instead. Missing files, workspace escapes, read-limit failures, and failures from a supported primary server remain errors. `status.supportedFileSuffixes` describes routing support, while `servers` separately describes enabled/available servers.
68
+
60
69
  Hover and completion can include Tailwind results. Completion ranks the typed prefix before truncating large catalogs. Diagnostics report omitted auxiliary servers; no publication before the deadline is a failure, not a clean-file result. Unsupported navigation returns `LSP_UNSUPPORTED_OPERATION`.
61
70
 
62
71
  For servers that publish diagnostics as notifications, each diagnostic query starts a fresh process if the previous process was already used. This prevents delayed notifications from an earlier document close from being mistaken for a clean result. It adds server startup and project indexing cost to repeated diagnostic queries. Servers supporting `textDocument/diagnostic` reuse their process because responses are associated with request IDs.
@@ -92,17 +101,21 @@ Bundled mode resolves executables on the Node host and is intended for local DSH
92
101
 
93
102
  ## Doctor
94
103
 
104
+ Run from this repository's root after installing dependencies and building:
105
+
95
106
  ```sh
107
+ pnpm install --frozen-lockfile
108
+ pnpm build
96
109
  node lib/cli/doctor.js --json
97
- node lib/cli/doctor.js --config ./webstack-config.json --deep
98
110
  ```
99
111
 
100
- The JSON config file contains the provider configuration object above. Doctor checks package binaries and PATH availability without launching servers, and exits nonzero when an enabled server is missing. `--deep` adds an explicit read-only inspection summary; it is **not** a protocol handshake or a check of the running DSH profile. Runtime status is available through `lsp_extra`.
112
+ Doctor checks package binaries and PATH availability without launching servers, and exits nonzero when an enabled server is missing. To inspect an existing JSON config, pass its path with `--config`; `--deep` adds a read-only summary, not a protocol handshake or check of the running DSH profile. Runtime status is available through `lsp_extra`.
101
113
 
102
114
  ## Verification
103
115
 
104
- `pnpm pack` builds the source through `prepare` and includes the built files in the tarball; npm releases also include those files. A direct Git dependency needs to run `prepare` in the Web profile and is blocked unless that exact Git dependency is listed in the profile's `allowBuilds`. Development dependencies provide the host services needed by the tests.
116
+ From this repository root, `pnpm pack` builds the source through `prepare` and includes the built files in the tarball; npm releases also include those files. A direct Git dependency needs to run `prepare` in the Web profile and is blocked unless that exact Git dependency is listed in the profile's `allowBuilds`. Development dependencies provide the host services needed by the tests.
105
117
 
118
+ Run these from this repository's root:
106
119
  ```sh
107
120
  pnpm install --frozen-lockfile
108
121
  pnpm check # types, deterministic/DSH integration tests, build, packed-artifact smoke test
@@ -110,13 +123,13 @@ pnpm test:e2e # real TS/JS, HTML, CSS, Svelte, Tailwind v3/v4
110
123
  PHPANTOM_E2E=1 pnpm test:e2e # additionally tests installed PHPantom with PHP and Blade
111
124
  ```
112
125
 
113
- The packed-artifact test installs the archive into a fresh consumer with DSH's hoisted layout, peer auto-installation disabled, and dependency scripts disabled. It provides the host service packages but does not preinstall either LSP package, then verifies bundle imports, both tool registrations, and real TypeScript, HTML, and CSS queries. It also checks declaration paths and the executable doctor. The consumer install prefers cached packages but needs registry access for uncached packages or metadata. E2E needs working OS file watchers; sandboxed macOS watchers may fail with `EMFILE`.
126
+ The packed-artifact test installs the archive into a fresh consumer with DSH's hoisted layout, peer auto-installation disabled, and dependency scripts disabled. It provides the host service packages but does not preinstall either LSP package, then verifies official profile composition and preflight, bundle imports, both tool registrations, and real TypeScript, HTML, and CSS queries on DSH `0.2.0-rc.2` and `0.2.1-alpha.1`. It also checks that import and initialization errors retain their original cause. It also checks declaration paths and the executable doctor. The consumer install prefers cached packages but needs registry access for uncached packages or metadata. E2E needs working OS file watchers; sandboxed macOS watchers may fail with `EMFILE`.
114
127
 
115
- Integration tests run against the published DSH service/tool packages and Cordis versions recorded in the lockfile. The full Web UI and a source-built upstream application are not exercised here.
128
+ Integration tests run against the published DSH service/tool packages and Cordis versions recorded in the lockfile. The packed consumers use the published DSH runtimes named above. Future versions (`0.3.0-alpha.1` and `1.0.0`) are simulated only as version inputs to the official compatibility evaluator, not tested APIs. The full Web UI and a source-built upstream application are not exercised here.
116
129
 
117
130
  ### Dependency security
118
131
 
119
- This repository pins Vite to 6.4.3 (which uses patched esbuild 0.25.x) and overrides the Svelte Language Server's fallback compiler to Svelte 5.55.7. These versions address [Vite's Windows path bypass](https://github.com/advisories/GHSA-fx2h-pf6j-xcff) and the [Svelte SSR](https://github.com/advisories/GHSA-pr6f-5x2q-rwfp) / [DOM clobbering](https://github.com/advisories/GHSA-rcqx-6q8c-2c42) advisories. Run `pnpm audit` after dependency updates. The Svelte E2E tests exercise fallback compilation with both legacy and rune syntax, including diagnostics after edits.
132
+ This repository pins Vite to 6.4.3 (which uses patched esbuild 0.25.x) and overrides the Svelte Language Server's fallback compiler to Svelte 5.55.7. These versions address [Vite's Windows path bypass](https://github.com/advisories/GHSA-fx2h-pf6j-xcff) and the [Svelte SSR](https://github.com/advisories/GHSA-pr6f-5x2q-rwfp) / [DOM clobbering](https://github.com/advisories/GHSA-rcqx-6q8c-2c42) advisories. Run `pnpm audit` from this repository root after dependency updates. The Svelte E2E tests exercise fallback compilation with both legacy and rune syntax, including diagnostics after edits.
120
133
 
121
134
  The pinned `svelte-language-server` still declares Svelte 4 as its dependency. Repository overrides and `pnpm-lock.yaml` do **not** propagate when this plugin is installed as a dependency. Until upstream changes that dependency, the host installation must apply its own override to obtain the patched fallback compiler. For npm, merge this into the installation root's `package.json`, reinstall, and run `npm audit`:
122
135
 
package/lib/extra-tool.js CHANGED
@@ -20,7 +20,7 @@ function createExtraTool(service, config = {}) {
20
20
  for (const [key, value] of Object.entries(limits)) if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new TypeError(`${key} must be a positive integer no greater than 2147483647`);
21
21
  return defineTool({
22
22
  name,
23
- description: "Read language-server status, diagnostics, or completion candidates. file_path is workspace-relative. Completion line and character are one-based UTF-16. No edits are applied.",
23
+ description: "Read language-server status, diagnostics, or completion candidates for PHP/Blade, TypeScript/JavaScript, JSX/TSX, Svelte, HTML and CSS/PCSS. status reports supportedFileSuffixes and server availability. Unsupported document diagnostics return skipped (unverified). file_path is workspace-relative. Completion line and character are one-based UTF-16. No edits are applied.",
24
24
  parameters: {
25
25
  operation: {
26
26
  type: "string",
@@ -104,7 +104,7 @@ function apply(ctx, config = {}) {
104
104
  ctx.systemPrompt.section({
105
105
  name: "tool:lsp_extra",
106
106
  order: 500,
107
- text: "Use lsp_extra diagnostics after edits to inspect static errors. Use completion for exact symbol or framework candidates. Completion cursors are one-based UTF-16; output ranges are zero-based. The tool never applies edits."
107
+ text: "Use lsp_extra diagnostics after editing supported code files (PHP/Blade, TypeScript/JavaScript, JSX/TSX, Svelte, HTML, CSS/PCSS). Check status for supportedFileSuffixes and server availability when uncertain. For Markdown and other unsupported documents, use content/structure checks instead. A skipped query is unverified, never a clean result; do not repeat an unsupported query unchanged. Use completion for exact symbol or framework candidates. Completion cursors are one-based UTF-16; output ranges are zero-based. The tool never applies edits."
108
108
  });
109
109
  }
110
110
 
@@ -1 +1 @@
1
- {"version":3,"file":"extra-tool.js","names":["result: unknown"],"sources":["../src/extra-tool.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\nimport type { ToolDefinition } from '@deepseek-ai/dsh-tools'\nimport type {} from '@deepseek-ai/dsh-system-prompt'\nimport type {} from './provider.js'\nimport type { WebstackLspService } from './service.js'\nimport { WebstackLspError } from './errors.js'\nimport { mergeDiagnostics } from './merge/diagnostics.js'\nimport { mergeCompletions } from './merge/completion.js'\n\nexport const name = 'lsp_extra'\nexport const inject = ['tools', 'systemPrompt', 'webstackLsp']\nexport interface Config { maxDiagnostics?: number; maxCompletions?: number; maxResultChars?: number; timeoutMs?: number }\n\nexport function createExtraTool(service: WebstackLspService, config: Config = {}): ToolDefinition {\n const limits = { maxDiagnostics: 200, maxCompletions: 100, maxResultChars: 32000, timeoutMs: 60000, ...config }\n for (const [key, value] of Object.entries(limits)) if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new TypeError(`${key} must be a positive integer no greater than 2147483647`)\n return defineTool({\n name,\n description: 'Read language-server status, diagnostics, or completion candidates. file_path is workspace-relative. Completion line and character are one-based UTF-16. No edits are applied.',\n parameters: {\n operation: { type: 'string', enum: ['status', 'diagnostics', 'completion'], required: true },\n file_path: { type: 'string' }, line: { type: 'integer' }, character: { type: 'integer' },\n severity: { type: 'string', enum: ['all', 'error', 'warning'] },\n servers: { type: 'array', items: { type: 'string' } },\n },\n output: {\n schema: { type: 'json' },\n render: (_args, value) => {\n const text = JSON.stringify(value)\n return [{ type: 'text', text: text.length <= limits.maxResultChars ? text : `${text.slice(0, Math.max(0, limits.maxResultChars - 14))}\\n[truncated]`.slice(0, limits.maxResultChars) }]\n },\n },\n timeoutMs: limits.timeoutMs,\n async execute(args, exec) {\n const signal = AbortSignal.any([exec.signal, AbortSignal.timeout(limits.timeoutMs)])\n signal.throwIfAborted()\n let result: unknown\n if (args.operation === 'status') result = await service.status()\n else {\n const workspaceRoot = exec.agent?.session.header.cwd\n if (!workspaceRoot) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'lsp_extra requires a session workspace cwd')\n if (!args.file_path) throw new TypeError('file_path is required')\n if (args.operation === 'diagnostics') {\n const diagnostics = await service.diagnostics({ workspaceRoot, filePath: args.file_path, ...(args.severity ? { severity: args.severity } : {}), ...(args.servers ? { servers: args.servers } : {}) }, signal)\n result = { ...diagnostics, ...mergeDiagnostics([diagnostics.diagnostics], limits) }\n } else {\n if (!args.line || args.line < 1 || !args.character || args.character < 1) throw new TypeError('completion requires positive one-based line and character')\n const completion = await service.completion({ workspaceRoot, filePath: args.file_path, position: { line: args.line - 1, character: args.character - 1 } }, signal)\n result = { ...completion, ...mergeCompletions([completion.items], limits) }\n }\n }\n // Strip undefined optionals and expose a lossless JSON result to DSH's schema validator.\n return JSON.parse(JSON.stringify(result))\n },\n })\n}\n\nexport function apply(ctx: Context, config: Config = {}): void {\n const tool = createExtraTool(ctx.webstackLsp, config)\n ctx.tools.register(tool)\n ctx.systemPrompt.section({ name: 'tool:lsp_extra', order: 500, text: 'Use lsp_extra diagnostics after edits to inspect static errors. Use completion for exact symbol or framework candidates. Completion cursors are one-based UTF-16; output ranges are zero-based. The tool never applies edits.' })\n}\n"],"mappings":";;;;;AAUA,MAAa,OAAO;AACpB,MAAa,SAAS;CAAC;CAAS;CAAgB;CAAc;AAG9D,SAAgB,gBAAgB,SAA6B,SAAiB,EAAE,EAAkB;CAChG,MAAM,SAAS;EAAE,gBAAgB;EAAK,gBAAgB;EAAK,gBAAgB;EAAO,WAAW;EAAO,GAAG;EAAQ;AAC/G,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAAE,KAAI,CAAC,OAAO,cAAc,MAAM,IAAI,QAAQ,KAAK,QAAQ,WAAY,OAAM,IAAI,UAAU,GAAG,IAAI,wDAAwD;AAC3M,QAAO,WAAW;EAChB;EACA,aAAa;EACb,YAAY;GACV,WAAW;IAAE,MAAM;IAAU,MAAM;KAAC;KAAU;KAAe;KAAa;IAAE,UAAU;IAAM;GAC5F,WAAW,EAAE,MAAM,UAAU;GAAE,MAAM,EAAE,MAAM,WAAW;GAAE,WAAW,EAAE,MAAM,WAAW;GACxF,UAAU;IAAE,MAAM;IAAU,MAAM;KAAC;KAAO;KAAS;KAAU;IAAE;GAC/D,SAAS;IAAE,MAAM;IAAS,OAAO,EAAE,MAAM,UAAU;IAAE;GACtD;EACD,QAAQ;GACN,QAAQ,EAAE,MAAM,QAAQ;GACxB,SAAS,OAAO,UAAU;IACxB,MAAM,OAAO,KAAK,UAAU,MAAM;AAClC,WAAO,CAAC;KAAE,MAAM;KAAQ,MAAM,KAAK,UAAU,OAAO,iBAAiB,OAAO,GAAG,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,OAAO,iBAAiB,GAAG,CAAC,CAAC,eAAe,MAAM,GAAG,OAAO,eAAe;KAAE,CAAC;;GAE1L;EACD,WAAW,OAAO;EAClB,MAAM,QAAQ,MAAM,MAAM;GACxB,MAAM,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,YAAY,QAAQ,OAAO,UAAU,CAAC,CAAC;AACpF,UAAO,gBAAgB;GACvB,IAAIA;AACJ,OAAI,KAAK,cAAc,SAAU,UAAS,MAAM,QAAQ,QAAQ;QAC3D;IACH,MAAM,gBAAgB,KAAK,OAAO,QAAQ,OAAO;AACjD,QAAI,CAAC,cAAe,OAAM,IAAI,iBAAiB,0BAA0B,6CAA6C;AACtH,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,UAAU,wBAAwB;AACjE,QAAI,KAAK,cAAc,eAAe;KACpC,MAAM,cAAc,MAAM,QAAQ,YAAY;MAAE;MAAe,UAAU,KAAK;MAAW,GAAI,KAAK,WAAW,EAAE,UAAU,KAAK,UAAU,GAAG,EAAE;MAAG,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,SAAS,GAAG,EAAE;MAAG,EAAE,OAAO;AAC7M,cAAS;MAAE,GAAG;MAAa,GAAG,iBAAiB,CAAC,YAAY,YAAY,EAAE,OAAO;MAAE;WAC9E;AACL,SAAI,CAAC,KAAK,QAAQ,KAAK,OAAO,KAAK,CAAC,KAAK,aAAa,KAAK,YAAY,EAAG,OAAM,IAAI,UAAU,4DAA4D;KAC1J,MAAM,aAAa,MAAM,QAAQ,WAAW;MAAE;MAAe,UAAU,KAAK;MAAW,UAAU;OAAE,MAAM,KAAK,OAAO;OAAG,WAAW,KAAK,YAAY;OAAG;MAAE,EAAE,OAAO;AAClK,cAAS;MAAE,GAAG;MAAY,GAAG,iBAAiB,CAAC,WAAW,MAAM,EAAE,OAAO;MAAE;;;AAI/E,UAAO,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;;EAE5C,CAAC;;AAGJ,SAAgB,MAAM,KAAc,SAAiB,EAAE,EAAQ;CAC7D,MAAM,OAAO,gBAAgB,IAAI,aAAa,OAAO;AACrD,KAAI,MAAM,SAAS,KAAK;AACxB,KAAI,aAAa,QAAQ;EAAE,MAAM;EAAkB,OAAO;EAAK,MAAM;EAAiO,CAAC"}
1
+ {"version":3,"file":"extra-tool.js","names":["result: unknown"],"sources":["../src/extra-tool.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\nimport type { ToolDefinition } from '@deepseek-ai/dsh-tools'\nimport type {} from '@deepseek-ai/dsh-system-prompt'\nimport type {} from './provider.js'\nimport type { WebstackLspService } from './service.js'\nimport { WebstackLspError } from './errors.js'\nimport { mergeDiagnostics } from './merge/diagnostics.js'\nimport { mergeCompletions } from './merge/completion.js'\n\nexport const name = 'lsp_extra'\nexport const inject = ['tools', 'systemPrompt', 'webstackLsp']\nexport interface Config { maxDiagnostics?: number; maxCompletions?: number; maxResultChars?: number; timeoutMs?: number }\n\nexport function createExtraTool(service: WebstackLspService, config: Config = {}): ToolDefinition {\n const limits = { maxDiagnostics: 200, maxCompletions: 100, maxResultChars: 32000, timeoutMs: 60000, ...config }\n for (const [key, value] of Object.entries(limits)) if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new TypeError(`${key} must be a positive integer no greater than 2147483647`)\n return defineTool({\n name,\n description: 'Read language-server status, diagnostics, or completion candidates for PHP/Blade, TypeScript/JavaScript, JSX/TSX, Svelte, HTML and CSS/PCSS. status reports supportedFileSuffixes and server availability. Unsupported document diagnostics return skipped (unverified). file_path is workspace-relative. Completion line and character are one-based UTF-16. No edits are applied.',\n parameters: {\n operation: { type: 'string', enum: ['status', 'diagnostics', 'completion'], required: true },\n file_path: { type: 'string' }, line: { type: 'integer' }, character: { type: 'integer' },\n severity: { type: 'string', enum: ['all', 'error', 'warning'] },\n servers: { type: 'array', items: { type: 'string' } },\n },\n output: {\n schema: { type: 'json' },\n render: (_args, value) => {\n const text = JSON.stringify(value)\n return [{ type: 'text', text: text.length <= limits.maxResultChars ? text : `${text.slice(0, Math.max(0, limits.maxResultChars - 14))}\\n[truncated]`.slice(0, limits.maxResultChars) }]\n },\n },\n timeoutMs: limits.timeoutMs,\n async execute(args, exec) {\n const signal = AbortSignal.any([exec.signal, AbortSignal.timeout(limits.timeoutMs)])\n signal.throwIfAborted()\n let result: unknown\n if (args.operation === 'status') result = await service.status()\n else {\n const workspaceRoot = exec.agent?.session.header.cwd\n if (!workspaceRoot) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'lsp_extra requires a session workspace cwd')\n if (!args.file_path) throw new TypeError('file_path is required')\n if (args.operation === 'diagnostics') {\n const diagnostics = await service.diagnostics({ workspaceRoot, filePath: args.file_path, ...(args.severity ? { severity: args.severity } : {}), ...(args.servers ? { servers: args.servers } : {}) }, signal)\n result = { ...diagnostics, ...mergeDiagnostics([diagnostics.diagnostics], limits) }\n } else {\n if (!args.line || args.line < 1 || !args.character || args.character < 1) throw new TypeError('completion requires positive one-based line and character')\n const completion = await service.completion({ workspaceRoot, filePath: args.file_path, position: { line: args.line - 1, character: args.character - 1 } }, signal)\n result = { ...completion, ...mergeCompletions([completion.items], limits) }\n }\n }\n // Strip undefined optionals and expose a lossless JSON result to DSH's schema validator.\n return JSON.parse(JSON.stringify(result))\n },\n })\n}\n\nexport function apply(ctx: Context, config: Config = {}): void {\n const tool = createExtraTool(ctx.webstackLsp, config)\n ctx.tools.register(tool)\n ctx.systemPrompt.section({ name: 'tool:lsp_extra', order: 500, text: 'Use lsp_extra diagnostics after editing supported code files (PHP/Blade, TypeScript/JavaScript, JSX/TSX, Svelte, HTML, CSS/PCSS). Check status for supportedFileSuffixes and server availability when uncertain. For Markdown and other unsupported documents, use content/structure checks instead. A skipped query is unverified, never a clean result; do not repeat an unsupported query unchanged. Use completion for exact symbol or framework candidates. Completion cursors are one-based UTF-16; output ranges are zero-based. The tool never applies edits.' })\n}\n"],"mappings":";;;;;AAUA,MAAa,OAAO;AACpB,MAAa,SAAS;CAAC;CAAS;CAAgB;CAAc;AAG9D,SAAgB,gBAAgB,SAA6B,SAAiB,EAAE,EAAkB;CAChG,MAAM,SAAS;EAAE,gBAAgB;EAAK,gBAAgB;EAAK,gBAAgB;EAAO,WAAW;EAAO,GAAG;EAAQ;AAC/G,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAAE,KAAI,CAAC,OAAO,cAAc,MAAM,IAAI,QAAQ,KAAK,QAAQ,WAAY,OAAM,IAAI,UAAU,GAAG,IAAI,wDAAwD;AAC3M,QAAO,WAAW;EAChB;EACA,aAAa;EACb,YAAY;GACV,WAAW;IAAE,MAAM;IAAU,MAAM;KAAC;KAAU;KAAe;KAAa;IAAE,UAAU;IAAM;GAC5F,WAAW,EAAE,MAAM,UAAU;GAAE,MAAM,EAAE,MAAM,WAAW;GAAE,WAAW,EAAE,MAAM,WAAW;GACxF,UAAU;IAAE,MAAM;IAAU,MAAM;KAAC;KAAO;KAAS;KAAU;IAAE;GAC/D,SAAS;IAAE,MAAM;IAAS,OAAO,EAAE,MAAM,UAAU;IAAE;GACtD;EACD,QAAQ;GACN,QAAQ,EAAE,MAAM,QAAQ;GACxB,SAAS,OAAO,UAAU;IACxB,MAAM,OAAO,KAAK,UAAU,MAAM;AAClC,WAAO,CAAC;KAAE,MAAM;KAAQ,MAAM,KAAK,UAAU,OAAO,iBAAiB,OAAO,GAAG,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,OAAO,iBAAiB,GAAG,CAAC,CAAC,eAAe,MAAM,GAAG,OAAO,eAAe;KAAE,CAAC;;GAE1L;EACD,WAAW,OAAO;EAClB,MAAM,QAAQ,MAAM,MAAM;GACxB,MAAM,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,YAAY,QAAQ,OAAO,UAAU,CAAC,CAAC;AACpF,UAAO,gBAAgB;GACvB,IAAIA;AACJ,OAAI,KAAK,cAAc,SAAU,UAAS,MAAM,QAAQ,QAAQ;QAC3D;IACH,MAAM,gBAAgB,KAAK,OAAO,QAAQ,OAAO;AACjD,QAAI,CAAC,cAAe,OAAM,IAAI,iBAAiB,0BAA0B,6CAA6C;AACtH,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,UAAU,wBAAwB;AACjE,QAAI,KAAK,cAAc,eAAe;KACpC,MAAM,cAAc,MAAM,QAAQ,YAAY;MAAE;MAAe,UAAU,KAAK;MAAW,GAAI,KAAK,WAAW,EAAE,UAAU,KAAK,UAAU,GAAG,EAAE;MAAG,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,SAAS,GAAG,EAAE;MAAG,EAAE,OAAO;AAC7M,cAAS;MAAE,GAAG;MAAa,GAAG,iBAAiB,CAAC,YAAY,YAAY,EAAE,OAAO;MAAE;WAC9E;AACL,SAAI,CAAC,KAAK,QAAQ,KAAK,OAAO,KAAK,CAAC,KAAK,aAAa,KAAK,YAAY,EAAG,OAAM,IAAI,UAAU,4DAA4D;KAC1J,MAAM,aAAa,MAAM,QAAQ,WAAW;MAAE;MAAe,UAAU,KAAK;MAAW,UAAU;OAAE,MAAM,KAAK,OAAO;OAAG,WAAW,KAAK,YAAY;OAAG;MAAE,EAAE,OAAO;AAClK,cAAS;MAAE,GAAG;MAAY,GAAG,iBAAiB,CAAC,WAAW,MAAM,EAAE,OAAO;MAAE;;;AAI/E,UAAO,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;;EAE5C,CAAC;;AAGJ,SAAgB,MAAM,KAAc,SAAiB,EAAE,EAAQ;CAC7D,MAAM,OAAO,gBAAgB,IAAI,aAAa,OAAO;AACrD,KAAI,MAAM,SAAS,KAAK;AACxB,KAAI,aAAa,QAAQ;EAAE,MAAM;EAAkB,OAAO;EAAK,MAAM;EAAyiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"launch-ByUvgkVv.js","names":["SERVER_COMMANDS: Record<ServerId, string>","DEFAULT_SERVER_MODES: Record<ServerId, ServerMode>","SERVER_IDS: ServerId[]","DEFAULT_CONFIG: ResolvedConfig","packages: Record<Exclude<ServerId, 'phpantom'>, [string, string]>"],"sources":["../src/config.ts","../src/service.ts","../src/servers/package-bin.ts","../src/servers/launch.ts"],"sourcesContent":["import { configError } from './errors.js'\n\nexport type ServerId = 'phpantom' | 'typescript' | 'svelte' | 'html' | 'css' | 'tailwind'\nexport type ServerMode = 'bundled' | 'path'\n\nexport interface ServerConfig {\n enabled?: boolean\n mode?: ServerMode\n command?: string\n args?: string[]\n env?: Record<string, string>\n initializationOptions?: unknown\n configuration?: unknown\n}\n\nexport interface Config {\n providerId?: string\n missingServerPolicy?: 'warn' | 'error'\n limits?: {\n maxDocumentBytes?: number\n maxMessageBytes?: number\n maxStderrBytes?: number\n }\n timeouts?: {\n navigationMs?: number\n primaryHoverMs?: number\n auxiliaryHoverMs?: number\n diagnosticsMs?: number\n completionMs?: number\n shutdownMs?: number\n killGraceMs?: number\n }\n servers?: Partial<Record<ServerId, ServerConfig>>\n tailwind?: {\n enabled?: boolean\n queryStrategy?: 'candidate' | 'always'\n classAttributes?: string[]\n classRegex?: Array<string | [string, string]>\n includeLanguages?: Record<string, string>\n }\n routing?: {\n bladeSuffixes?: string[]\n tailwindLanguages?: string[]\n }\n}\n\nexport interface ResolvedServerConfig {\n enabled: boolean\n mode: ServerMode\n command: string\n args: string[]\n env: Record<string, string>\n initializationOptions?: unknown\n configuration?: unknown\n}\n\nexport interface ResolvedConfig {\n providerId: string\n missingServerPolicy: 'warn' | 'error'\n limits: {\n maxDocumentBytes: number\n maxMessageBytes: number\n maxStderrBytes: number\n }\n timeouts: {\n navigationMs: number\n primaryHoverMs: number\n auxiliaryHoverMs: number\n diagnosticsMs: number\n completionMs: number\n shutdownMs: number\n killGraceMs: number\n }\n servers: Record<ServerId, ResolvedServerConfig>\n tailwind: {\n enabled: boolean\n queryStrategy: 'candidate' | 'always'\n classAttributes: string[]\n classRegex: Array<string | [string, string]>\n includeLanguages: Record<string, string>\n }\n routing: {\n bladeSuffixes: string[]\n tailwindLanguages: string[]\n }\n}\n\nconst SERVER_COMMANDS: Record<ServerId, string> = {\n phpantom: 'phpantom_lsp',\n typescript: 'typescript-language-server',\n svelte: 'svelteserver',\n html: 'vscode-html-language-server',\n css: 'vscode-css-language-server',\n tailwind: 'tailwindcss-language-server',\n}\n\nconst DEFAULT_SERVER_MODES: Record<ServerId, ServerMode> = {\n phpantom: 'path',\n typescript: 'bundled',\n svelte: 'bundled',\n html: 'bundled',\n css: 'bundled',\n tailwind: 'bundled',\n}\n\nexport const SERVER_IDS: ServerId[] = ['phpantom', 'typescript', 'svelte', 'html', 'css', 'tailwind']\nconst DEFAULT_LIMITS = { maxDocumentBytes: 1_048_576, maxMessageBytes: 8_388_608, maxStderrBytes: 65_536 }\nconst DEFAULT_TIMEOUTS = { navigationMs: 60_000, primaryHoverMs: 30_000, auxiliaryHoverMs: 8_000, diagnosticsMs: 60_000, completionMs: 15_000, shutdownMs: 5_000, killGraceMs: 1_000 }\n\nexport const DEFAULT_CONFIG: ResolvedConfig = {\n providerId: 'webstack',\n missingServerPolicy: 'warn',\n limits: { ...DEFAULT_LIMITS },\n timeouts: { ...DEFAULT_TIMEOUTS },\n servers: Object.fromEntries(SERVER_IDS.map((id) => [id, {\n enabled: true,\n mode: DEFAULT_SERVER_MODES[id],\n command: SERVER_COMMANDS[id],\n args: ['--stdio'],\n env: {},\n }])) as Record<ServerId, ResolvedServerConfig>,\n tailwind: { enabled: true, queryStrategy: 'candidate', classAttributes: ['class', 'className', 'class:list'], classRegex: [], includeLanguages: {} },\n routing: { bladeSuffixes: ['.blade.php'], tailwindLanguages: ['html', 'svelte', 'typescript', 'typescriptreact', 'javascript', 'javascriptreact'] },\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction readPositiveInteger(value: unknown, label: string, fallback: number): number {\n if (value === undefined) return fallback\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0 || value > 2_147_483_647) throw configError(`${label} must be a positive integer no greater than 2147483647`)\n return value\n}\n\nfunction readBoolean(value: unknown, label: string, fallback: boolean): boolean {\n if (value === undefined) return fallback\n if (typeof value !== 'boolean') throw configError(`${label} must be a boolean`)\n return value\n}\n\nfunction readString(value: unknown, label: string, fallback: string): string {\n if (value === undefined) return fallback\n if (typeof value !== 'string' || value.trim().length === 0 || value.includes('\\u0000')) throw configError(`${label} must be a non-empty string without NUL`)\n return value\n}\n\nfunction cloneJson(value: unknown, label: string): unknown {\n if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value\n if (Array.isArray(value)) return value.map((item) => cloneJson(item, label))\n if (isRecord(value)) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneJson(item, label)]))\n throw configError(`${label} must contain JSON-compatible values`)\n}\n\nfunction resolveSuffixes(value: unknown, label: string, fallback: string[]): string[] {\n if (value === undefined) return [...fallback]\n if (!Array.isArray(value) || value.length === 0) throw configError(`${label} must be a non-empty array`)\n const normalized = value.map((suffix, index) => {\n if (typeof suffix !== 'string' || suffix.length === 0 || suffix.includes('/') || suffix.includes('\\\\')) throw configError(`${label}[${index}] is not a valid suffix`)\n return suffix.toLowerCase()\n })\n if (new Set(normalized).size !== normalized.length) throw configError(`${label} contains duplicate suffixes`)\n return normalized\n}\n\nfunction resolveStringArray(value: unknown, label: string, fallback: string[]): string[] {\n if (value === undefined) return [...fallback]\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) throw configError(`${label} must be an array of strings`)\n return [...value]\n}\n\nfunction resolveEnv(value: unknown, label: string): Record<string, string> {\n if (value === undefined) return {}\n if (!isRecord(value) || Object.entries(value).some(([key, item]) => key.length === 0 || typeof item !== 'string')) throw configError(`${label} must be a string map`)\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, item as string]))\n}\n\nfunction resolveServer(id: ServerId, value: unknown): ResolvedServerConfig {\n if (value !== undefined && !isRecord(value)) throw configError(`servers.${id} must be an object`)\n const input = value as Record<string, unknown> | undefined\n const mode = input?.mode === undefined ? DEFAULT_SERVER_MODES[id] : input.mode\n if (mode !== 'bundled' && mode !== 'path') throw configError(`servers.${id}.mode must be bundled or path`)\n if (id === 'phpantom' && mode === 'bundled') throw configError('PHPantom must use path mode')\n const command = input?.command === undefined ? SERVER_COMMANDS[id] : readString(input.command, `servers.${id}.command`, SERVER_COMMANDS[id])\n if (mode === 'path' && input?.command === undefined && id !== 'phpantom') throw configError(`servers.${id}.command is required in path mode`)\n const argsValue = input?.args\n if (argsValue !== undefined && (!Array.isArray(argsValue) || argsValue.some((item) => typeof item !== 'string'))) throw configError(`servers.${id}.args must be an array of strings`)\n return {\n enabled: readBoolean(input?.enabled, `servers.${id}.enabled`, true),\n mode,\n command,\n args: argsValue === undefined ? ['--stdio'] : [...argsValue] as string[],\n env: resolveEnv(input?.env, `servers.${id}.env`),\n ...(input?.initializationOptions === undefined ? {} : { initializationOptions: cloneJson(input.initializationOptions, `servers.${id}.initializationOptions`) }),\n ...(input?.configuration === undefined ? {} : { configuration: cloneJson(input.configuration, `servers.${id}.configuration`) }),\n }\n}\n\nexport function resolveConfig(input: unknown = {}): ResolvedConfig {\n if (!isRecord(input)) throw configError('config must be an object')\n const limits = isRecord(input.limits) ? input.limits : input.limits === undefined ? {} : (() => { throw configError('limits must be an object') })()\n const timeouts = isRecord(input.timeouts) ? input.timeouts : input.timeouts === undefined ? {} : (() => { throw configError('timeouts must be an object') })()\n const tailwind = isRecord(input.tailwind) ? input.tailwind : input.tailwind === undefined ? {} : (() => { throw configError('tailwind must be an object') })()\n const routing = isRecord(input.routing) ? input.routing : input.routing === undefined ? {} : (() => { throw configError('routing must be an object') })()\n const serverInput = isRecord(input.servers) ? input.servers : input.servers === undefined ? {} : (() => { throw configError('servers must be an object') })()\n const providerId = readString(input.providerId, 'providerId', DEFAULT_CONFIG.providerId)\n const missingServerPolicy = input.missingServerPolicy === undefined ? 'warn' : input.missingServerPolicy\n if (missingServerPolicy !== 'warn' && missingServerPolicy !== 'error') throw configError('missingServerPolicy must be warn or error')\n const classRegex = tailwind.classRegex\n if (classRegex !== undefined && (!Array.isArray(classRegex) || classRegex.some((item) => typeof item !== 'string' && (!Array.isArray(item) || item.length !== 2 || item.some((part) => typeof part !== 'string'))))) throw configError('tailwind.classRegex must contain strings or string pairs')\n const queryStrategy = tailwind.queryStrategy === undefined ? 'candidate' : tailwind.queryStrategy\n for (const expression of (classRegex ?? []) as Array<string | [string, string]>) {\n for (const pattern of Array.isArray(expression) ? expression : [expression]) {\n try { new RegExp(pattern) } catch { throw configError('tailwind.classRegex contains an invalid regular expression') }\n }\n }\n if (queryStrategy !== 'candidate' && queryStrategy !== 'always') throw configError('tailwind.queryStrategy must be candidate or always')\n const includeLanguages = resolveEnv(tailwind.includeLanguages, 'tailwind.includeLanguages')\n return {\n providerId,\n missingServerPolicy,\n limits: {\n maxDocumentBytes: readPositiveInteger(limits.maxDocumentBytes, 'limits.maxDocumentBytes', DEFAULT_LIMITS.maxDocumentBytes),\n maxMessageBytes: readPositiveInteger(limits.maxMessageBytes, 'limits.maxMessageBytes', DEFAULT_LIMITS.maxMessageBytes),\n maxStderrBytes: readPositiveInteger(limits.maxStderrBytes, 'limits.maxStderrBytes', DEFAULT_LIMITS.maxStderrBytes),\n },\n timeouts: {\n navigationMs: readPositiveInteger(timeouts.navigationMs, 'timeouts.navigationMs', DEFAULT_TIMEOUTS.navigationMs),\n primaryHoverMs: readPositiveInteger(timeouts.primaryHoverMs, 'timeouts.primaryHoverMs', DEFAULT_TIMEOUTS.primaryHoverMs),\n auxiliaryHoverMs: readPositiveInteger(timeouts.auxiliaryHoverMs, 'timeouts.auxiliaryHoverMs', DEFAULT_TIMEOUTS.auxiliaryHoverMs),\n diagnosticsMs: readPositiveInteger(timeouts.diagnosticsMs, 'timeouts.diagnosticsMs', DEFAULT_TIMEOUTS.diagnosticsMs),\n completionMs: readPositiveInteger(timeouts.completionMs, 'timeouts.completionMs', DEFAULT_TIMEOUTS.completionMs),\n shutdownMs: readPositiveInteger(timeouts.shutdownMs, 'timeouts.shutdownMs', DEFAULT_TIMEOUTS.shutdownMs),\n killGraceMs: readPositiveInteger(timeouts.killGraceMs, 'timeouts.killGraceMs', DEFAULT_TIMEOUTS.killGraceMs),\n },\n servers: Object.fromEntries(SERVER_IDS.map((id) => [id, resolveServer(id, serverInput[id])])) as Record<ServerId, ResolvedServerConfig>,\n tailwind: {\n enabled: readBoolean(tailwind.enabled, 'tailwind.enabled', true),\n queryStrategy,\n classAttributes: resolveStringArray(tailwind.classAttributes, 'tailwind.classAttributes', DEFAULT_CONFIG.tailwind.classAttributes),\n classRegex: classRegex === undefined ? [] : (classRegex.map((item) => Array.isArray(item) ? [...item] as [string, string] : item)),\n includeLanguages,\n },\n routing: {\n bladeSuffixes: resolveSuffixes(routing.bladeSuffixes, 'routing.bladeSuffixes', DEFAULT_CONFIG.routing.bladeSuffixes),\n tailwindLanguages: resolveStringArray(routing.tailwindLanguages, 'routing.tailwindLanguages', DEFAULT_CONFIG.routing.tailwindLanguages),\n },\n }\n}\n\nif (DEFAULT_CONFIG.tailwind.queryStrategy !== 'candidate' && DEFAULT_CONFIG.tailwind.queryStrategy !== 'always') throw new Error('invalid internal default')\n\nexport const ConfigSchema = {\n parse: resolveConfig,\n validate: resolveConfig,\n} as const\n","import { WebstackLspError } from './errors.js'\nimport type { ResolvedConfig } from './config.js'\n\nexport interface LspPosition { line: number; character: number }\nexport interface LspRange { start: LspPosition; end: LspPosition }\n\nexport interface DiagnosticsRequest { workspaceRoot: string; filePath: string; severity?: 'all' | 'error' | 'warning'; servers?: string[] }\nexport interface CompletionRequest { workspaceRoot: string; filePath: string; position: LspPosition; triggerKind?: 1 | 2 | 3; triggerCharacter?: string }\n\nexport interface NormalizedDiagnostic {\n server: string\n uri: string\n range: LspRange\n severity?: 1 | 2 | 3 | 4\n code?: string | number\n source?: string\n message: string\n tags?: number[]\n servers?: string[]\n}\nexport interface NormalizedCompletionItem { server: string; label: string; kind?: number; detail?: string; documentation?: string; sortText?: string; filterText?: string; insertText?: string; insertTextFormat?: number; deprecated?: boolean }\nexport interface DiagnosticsResult { diagnostics: NormalizedDiagnostic[]; omittedServers?: string[]; truncated?: { diagnostics: number; characters: number } }\nexport interface CompletionResult { items: NormalizedCompletionItem[]; truncated?: { items: number; characters: number } }\n\nexport interface WebstackLspStatus {\n providerId: string\n servers: Array<{ id: import('./config.js').ServerId; enabled: boolean; available: boolean; source: 'bundled' | 'path'; command?: string; version?: string; lastError?: string; liveWorkspaces: number; restarts: number }>\n}\n\nexport interface WebstackLspService {\n status(): Promise<WebstackLspStatus>\n diagnostics(request: DiagnosticsRequest, signal?: AbortSignal): Promise<DiagnosticsResult>\n completion(request: CompletionRequest, signal?: AbortSignal): Promise<CompletionResult>\n}\n\nexport interface ExtendedRuntime extends WebstackLspService {}\n\nexport function createWebstackLspService(runtime: ExtendedRuntime, config: Pick<ResolvedConfig, 'limits'> = { limits: { maxDocumentBytes: 1_048_576, maxMessageBytes: 8_388_608, maxStderrBytes: 65_536 } }): WebstackLspService {\n return {\n status: () => runtime.status(),\n diagnostics: (request, signal) => runtime.diagnostics(validateDiagnosticsRequest(request), signal),\n completion: (request, signal) => runtime.completion(validateCompletionRequest(request), signal),\n }\n}\n\nfunction validateDiagnosticsRequest(request: DiagnosticsRequest): DiagnosticsRequest {\n if (!isRequest(request) || typeof request.workspaceRoot !== 'string' || request.workspaceRoot.length === 0 || typeof request.filePath !== 'string' || request.filePath.length === 0) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'workspaceRoot and filePath are required')\n return { ...request, ...(request.servers ? { servers: [...request.servers] } : {}) }\n}\n\nfunction validateCompletionRequest(request: CompletionRequest): CompletionRequest {\n if (!isRequest(request) || typeof request.workspaceRoot !== 'string' || request.workspaceRoot.length === 0 || typeof request.filePath !== 'string' || request.filePath.length === 0 || !isPosition(request.position)) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'workspaceRoot, filePath and position are required')\n return { ...request, position: { ...request.position } }\n}\n\nfunction isPosition(value: unknown): value is LspPosition { return typeof value === 'object' && value !== null && Number.isInteger((value as { line?: unknown }).line) && Number.isInteger((value as { character?: unknown }).character) && (value as LspPosition).line >= 0 && (value as LspPosition).character >= 0 }\nfunction isRequest(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value) }\n\nexport function createUnavailableService(providerId = 'webstack'): WebstackLspService {\n return { status: async () => ({ providerId, servers: [] }), diagnostics: async () => Promise.reject(new WebstackLspError('LSP_UNAVAILABLE', 'webstack runtime is unavailable')), completion: async () => Promise.reject(new WebstackLspError('LSP_UNAVAILABLE', 'webstack runtime is unavailable')) }\n}\n","import { createRequire } from 'node:module'\nimport { dirname, resolve } from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport type { LaunchSpec } from './types.js'\n\nconst require = createRequire(import.meta.url)\n\nexport async function resolvePackageBinary(packageName: string, binName: string, cwd: string, args = ['--stdio']): Promise<LaunchSpec> {\n const packageJson = require.resolve(`${packageName}/package.json`)\n const metadata = JSON.parse(await readFile(packageJson, 'utf8')) as { bin?: string | Record<string, string> }\n const bin = typeof metadata.bin === 'string' ? metadata.bin : metadata.bin?.[binName] ?? metadata.bin?.[packageName]\n if (!bin) throw new Error(`binary ${binName} is not declared by ${packageName}`)\n return { command: process.execPath, args: [resolve(dirname(packageJson), bin), ...args], cwd }\n}\n","import { createRequire } from 'node:module'\nimport type { ResolvedConfig, ServerId } from '../config.js'\nimport { resolvePackageBinary } from './package-bin.js'\nimport type { LaunchSpec } from './types.js'\n\nconst packages: Record<Exclude<ServerId, 'phpantom'>, [string, string]> = {\n typescript: ['typescript-language-server', 'typescript-language-server'],\n svelte: ['svelte-language-server', 'svelteserver'],\n html: ['vscode-langservers-extracted', 'vscode-html-language-server'],\n css: ['vscode-langservers-extracted', 'vscode-css-language-server'],\n tailwind: ['@tailwindcss/language-server', 'tailwindcss-language-server'],\n}\n\nexport async function resolveLaunch(id: ServerId, config: ResolvedConfig, workspace: string): Promise<LaunchSpec> {\n const server = config.servers[id]\n if (server.mode === 'path' || id === 'phpantom') return { command: server.command, args: [...server.args], cwd: workspace, env: { ...server.env } }\n const [pkg, bin] = packages[id]\n return { ...await resolvePackageBinary(pkg, bin, workspace, server.args), env: { ...server.env } }\n}\n\nexport function initializationOptions(id: ServerId, config: ResolvedConfig): unknown {\n const configured = config.servers[id].initializationOptions\n if (configured !== undefined) return configured\n if (id === 'typescript' && config.servers[id].mode === 'bundled') {\n return { tsserver: { path: createRequire(import.meta.url).resolve('typescript/lib/tsserver.js') } }\n }\n if (id === 'tailwind') return { userLanguages: config.tailwind.includeLanguages }\n return null\n}\n\nexport function serverConfiguration(id: ServerId, config: ResolvedConfig): unknown {\n if (config.servers[id].configuration !== undefined) return config.servers[id].configuration\n if (id === 'tailwind') return { tailwindCSS: { classAttributes: config.tailwind.classAttributes, includeLanguages: config.tailwind.includeLanguages, experimental: { classRegex: config.tailwind.classRegex } } }\n return {}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"launch-ByUvgkVv.js","names":["SERVER_COMMANDS: Record<ServerId, string>","DEFAULT_SERVER_MODES: Record<ServerId, ServerMode>","SERVER_IDS: ServerId[]","DEFAULT_CONFIG: ResolvedConfig","packages: Record<Exclude<ServerId, 'phpantom'>, [string, string]>"],"sources":["../src/config.ts","../src/service.ts","../src/servers/package-bin.ts","../src/servers/launch.ts"],"sourcesContent":["import { configError } from './errors.js'\n\nexport type ServerId = 'phpantom' | 'typescript' | 'svelte' | 'html' | 'css' | 'tailwind'\nexport type ServerMode = 'bundled' | 'path'\n\nexport interface ServerConfig {\n enabled?: boolean\n mode?: ServerMode\n command?: string\n args?: string[]\n env?: Record<string, string>\n initializationOptions?: unknown\n configuration?: unknown\n}\n\nexport interface Config {\n providerId?: string\n missingServerPolicy?: 'warn' | 'error'\n limits?: {\n maxDocumentBytes?: number\n maxMessageBytes?: number\n maxStderrBytes?: number\n }\n timeouts?: {\n navigationMs?: number\n primaryHoverMs?: number\n auxiliaryHoverMs?: number\n diagnosticsMs?: number\n completionMs?: number\n shutdownMs?: number\n killGraceMs?: number\n }\n servers?: Partial<Record<ServerId, ServerConfig>>\n tailwind?: {\n enabled?: boolean\n queryStrategy?: 'candidate' | 'always'\n classAttributes?: string[]\n classRegex?: Array<string | [string, string]>\n includeLanguages?: Record<string, string>\n }\n routing?: {\n bladeSuffixes?: string[]\n tailwindLanguages?: string[]\n }\n}\n\nexport interface ResolvedServerConfig {\n enabled: boolean\n mode: ServerMode\n command: string\n args: string[]\n env: Record<string, string>\n initializationOptions?: unknown\n configuration?: unknown\n}\n\nexport interface ResolvedConfig {\n providerId: string\n missingServerPolicy: 'warn' | 'error'\n limits: {\n maxDocumentBytes: number\n maxMessageBytes: number\n maxStderrBytes: number\n }\n timeouts: {\n navigationMs: number\n primaryHoverMs: number\n auxiliaryHoverMs: number\n diagnosticsMs: number\n completionMs: number\n shutdownMs: number\n killGraceMs: number\n }\n servers: Record<ServerId, ResolvedServerConfig>\n tailwind: {\n enabled: boolean\n queryStrategy: 'candidate' | 'always'\n classAttributes: string[]\n classRegex: Array<string | [string, string]>\n includeLanguages: Record<string, string>\n }\n routing: {\n bladeSuffixes: string[]\n tailwindLanguages: string[]\n }\n}\n\nconst SERVER_COMMANDS: Record<ServerId, string> = {\n phpantom: 'phpantom_lsp',\n typescript: 'typescript-language-server',\n svelte: 'svelteserver',\n html: 'vscode-html-language-server',\n css: 'vscode-css-language-server',\n tailwind: 'tailwindcss-language-server',\n}\n\nconst DEFAULT_SERVER_MODES: Record<ServerId, ServerMode> = {\n phpantom: 'path',\n typescript: 'bundled',\n svelte: 'bundled',\n html: 'bundled',\n css: 'bundled',\n tailwind: 'bundled',\n}\n\nexport const SERVER_IDS: ServerId[] = ['phpantom', 'typescript', 'svelte', 'html', 'css', 'tailwind']\nconst DEFAULT_LIMITS = { maxDocumentBytes: 1_048_576, maxMessageBytes: 8_388_608, maxStderrBytes: 65_536 }\nconst DEFAULT_TIMEOUTS = { navigationMs: 60_000, primaryHoverMs: 30_000, auxiliaryHoverMs: 8_000, diagnosticsMs: 60_000, completionMs: 15_000, shutdownMs: 5_000, killGraceMs: 1_000 }\n\nexport const DEFAULT_CONFIG: ResolvedConfig = {\n providerId: 'webstack',\n missingServerPolicy: 'warn',\n limits: { ...DEFAULT_LIMITS },\n timeouts: { ...DEFAULT_TIMEOUTS },\n servers: Object.fromEntries(SERVER_IDS.map((id) => [id, {\n enabled: true,\n mode: DEFAULT_SERVER_MODES[id],\n command: SERVER_COMMANDS[id],\n args: ['--stdio'],\n env: {},\n }])) as Record<ServerId, ResolvedServerConfig>,\n tailwind: { enabled: true, queryStrategy: 'candidate', classAttributes: ['class', 'className', 'class:list'], classRegex: [], includeLanguages: {} },\n routing: { bladeSuffixes: ['.blade.php'], tailwindLanguages: ['html', 'svelte', 'typescript', 'typescriptreact', 'javascript', 'javascriptreact'] },\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction readPositiveInteger(value: unknown, label: string, fallback: number): number {\n if (value === undefined) return fallback\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0 || value > 2_147_483_647) throw configError(`${label} must be a positive integer no greater than 2147483647`)\n return value\n}\n\nfunction readBoolean(value: unknown, label: string, fallback: boolean): boolean {\n if (value === undefined) return fallback\n if (typeof value !== 'boolean') throw configError(`${label} must be a boolean`)\n return value\n}\n\nfunction readString(value: unknown, label: string, fallback: string): string {\n if (value === undefined) return fallback\n if (typeof value !== 'string' || value.trim().length === 0 || value.includes('\\u0000')) throw configError(`${label} must be a non-empty string without NUL`)\n return value\n}\n\nfunction cloneJson(value: unknown, label: string): unknown {\n if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value\n if (Array.isArray(value)) return value.map((item) => cloneJson(item, label))\n if (isRecord(value)) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneJson(item, label)]))\n throw configError(`${label} must contain JSON-compatible values`)\n}\n\nfunction resolveSuffixes(value: unknown, label: string, fallback: string[]): string[] {\n if (value === undefined) return [...fallback]\n if (!Array.isArray(value) || value.length === 0) throw configError(`${label} must be a non-empty array`)\n const normalized = value.map((suffix, index) => {\n if (typeof suffix !== 'string' || suffix.length === 0 || suffix.includes('/') || suffix.includes('\\\\')) throw configError(`${label}[${index}] is not a valid suffix`)\n return suffix.toLowerCase()\n })\n if (new Set(normalized).size !== normalized.length) throw configError(`${label} contains duplicate suffixes`)\n return normalized\n}\n\nfunction resolveStringArray(value: unknown, label: string, fallback: string[]): string[] {\n if (value === undefined) return [...fallback]\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) throw configError(`${label} must be an array of strings`)\n return [...value]\n}\n\nfunction resolveEnv(value: unknown, label: string): Record<string, string> {\n if (value === undefined) return {}\n if (!isRecord(value) || Object.entries(value).some(([key, item]) => key.length === 0 || typeof item !== 'string')) throw configError(`${label} must be a string map`)\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, item as string]))\n}\n\nfunction resolveServer(id: ServerId, value: unknown): ResolvedServerConfig {\n if (value !== undefined && !isRecord(value)) throw configError(`servers.${id} must be an object`)\n const input = value as Record<string, unknown> | undefined\n const mode = input?.mode === undefined ? DEFAULT_SERVER_MODES[id] : input.mode\n if (mode !== 'bundled' && mode !== 'path') throw configError(`servers.${id}.mode must be bundled or path`)\n if (id === 'phpantom' && mode === 'bundled') throw configError('PHPantom must use path mode')\n const command = input?.command === undefined ? SERVER_COMMANDS[id] : readString(input.command, `servers.${id}.command`, SERVER_COMMANDS[id])\n if (mode === 'path' && input?.command === undefined && id !== 'phpantom') throw configError(`servers.${id}.command is required in path mode`)\n const argsValue = input?.args\n if (argsValue !== undefined && (!Array.isArray(argsValue) || argsValue.some((item) => typeof item !== 'string'))) throw configError(`servers.${id}.args must be an array of strings`)\n return {\n enabled: readBoolean(input?.enabled, `servers.${id}.enabled`, true),\n mode,\n command,\n args: argsValue === undefined ? ['--stdio'] : [...argsValue] as string[],\n env: resolveEnv(input?.env, `servers.${id}.env`),\n ...(input?.initializationOptions === undefined ? {} : { initializationOptions: cloneJson(input.initializationOptions, `servers.${id}.initializationOptions`) }),\n ...(input?.configuration === undefined ? {} : { configuration: cloneJson(input.configuration, `servers.${id}.configuration`) }),\n }\n}\n\nexport function resolveConfig(input: unknown = {}): ResolvedConfig {\n if (!isRecord(input)) throw configError('config must be an object')\n const limits = isRecord(input.limits) ? input.limits : input.limits === undefined ? {} : (() => { throw configError('limits must be an object') })()\n const timeouts = isRecord(input.timeouts) ? input.timeouts : input.timeouts === undefined ? {} : (() => { throw configError('timeouts must be an object') })()\n const tailwind = isRecord(input.tailwind) ? input.tailwind : input.tailwind === undefined ? {} : (() => { throw configError('tailwind must be an object') })()\n const routing = isRecord(input.routing) ? input.routing : input.routing === undefined ? {} : (() => { throw configError('routing must be an object') })()\n const serverInput = isRecord(input.servers) ? input.servers : input.servers === undefined ? {} : (() => { throw configError('servers must be an object') })()\n const providerId = readString(input.providerId, 'providerId', DEFAULT_CONFIG.providerId)\n const missingServerPolicy = input.missingServerPolicy === undefined ? 'warn' : input.missingServerPolicy\n if (missingServerPolicy !== 'warn' && missingServerPolicy !== 'error') throw configError('missingServerPolicy must be warn or error')\n const classRegex = tailwind.classRegex\n if (classRegex !== undefined && (!Array.isArray(classRegex) || classRegex.some((item) => typeof item !== 'string' && (!Array.isArray(item) || item.length !== 2 || item.some((part) => typeof part !== 'string'))))) throw configError('tailwind.classRegex must contain strings or string pairs')\n const queryStrategy = tailwind.queryStrategy === undefined ? 'candidate' : tailwind.queryStrategy\n for (const expression of (classRegex ?? []) as Array<string | [string, string]>) {\n for (const pattern of Array.isArray(expression) ? expression : [expression]) {\n try { new RegExp(pattern) } catch { throw configError('tailwind.classRegex contains an invalid regular expression') }\n }\n }\n if (queryStrategy !== 'candidate' && queryStrategy !== 'always') throw configError('tailwind.queryStrategy must be candidate or always')\n const includeLanguages = resolveEnv(tailwind.includeLanguages, 'tailwind.includeLanguages')\n return {\n providerId,\n missingServerPolicy,\n limits: {\n maxDocumentBytes: readPositiveInteger(limits.maxDocumentBytes, 'limits.maxDocumentBytes', DEFAULT_LIMITS.maxDocumentBytes),\n maxMessageBytes: readPositiveInteger(limits.maxMessageBytes, 'limits.maxMessageBytes', DEFAULT_LIMITS.maxMessageBytes),\n maxStderrBytes: readPositiveInteger(limits.maxStderrBytes, 'limits.maxStderrBytes', DEFAULT_LIMITS.maxStderrBytes),\n },\n timeouts: {\n navigationMs: readPositiveInteger(timeouts.navigationMs, 'timeouts.navigationMs', DEFAULT_TIMEOUTS.navigationMs),\n primaryHoverMs: readPositiveInteger(timeouts.primaryHoverMs, 'timeouts.primaryHoverMs', DEFAULT_TIMEOUTS.primaryHoverMs),\n auxiliaryHoverMs: readPositiveInteger(timeouts.auxiliaryHoverMs, 'timeouts.auxiliaryHoverMs', DEFAULT_TIMEOUTS.auxiliaryHoverMs),\n diagnosticsMs: readPositiveInteger(timeouts.diagnosticsMs, 'timeouts.diagnosticsMs', DEFAULT_TIMEOUTS.diagnosticsMs),\n completionMs: readPositiveInteger(timeouts.completionMs, 'timeouts.completionMs', DEFAULT_TIMEOUTS.completionMs),\n shutdownMs: readPositiveInteger(timeouts.shutdownMs, 'timeouts.shutdownMs', DEFAULT_TIMEOUTS.shutdownMs),\n killGraceMs: readPositiveInteger(timeouts.killGraceMs, 'timeouts.killGraceMs', DEFAULT_TIMEOUTS.killGraceMs),\n },\n servers: Object.fromEntries(SERVER_IDS.map((id) => [id, resolveServer(id, serverInput[id])])) as Record<ServerId, ResolvedServerConfig>,\n tailwind: {\n enabled: readBoolean(tailwind.enabled, 'tailwind.enabled', true),\n queryStrategy,\n classAttributes: resolveStringArray(tailwind.classAttributes, 'tailwind.classAttributes', DEFAULT_CONFIG.tailwind.classAttributes),\n classRegex: classRegex === undefined ? [] : (classRegex.map((item) => Array.isArray(item) ? [...item] as [string, string] : item)),\n includeLanguages,\n },\n routing: {\n bladeSuffixes: resolveSuffixes(routing.bladeSuffixes, 'routing.bladeSuffixes', DEFAULT_CONFIG.routing.bladeSuffixes),\n tailwindLanguages: resolveStringArray(routing.tailwindLanguages, 'routing.tailwindLanguages', DEFAULT_CONFIG.routing.tailwindLanguages),\n },\n }\n}\n\nif (DEFAULT_CONFIG.tailwind.queryStrategy !== 'candidate' && DEFAULT_CONFIG.tailwind.queryStrategy !== 'always') throw new Error('invalid internal default')\n\nexport const ConfigSchema = {\n parse: resolveConfig,\n validate: resolveConfig,\n} as const\n","import { WebstackLspError } from './errors.js'\nimport type { ResolvedConfig } from './config.js'\n\nexport interface LspPosition { line: number; character: number }\nexport interface LspRange { start: LspPosition; end: LspPosition }\n\nexport interface DiagnosticsRequest { workspaceRoot: string; filePath: string; severity?: 'all' | 'error' | 'warning'; servers?: string[] }\nexport interface CompletionRequest { workspaceRoot: string; filePath: string; position: LspPosition; triggerKind?: 1 | 2 | 3; triggerCharacter?: string }\n\nexport interface NormalizedDiagnostic {\n server: string\n uri: string\n range: LspRange\n severity?: 1 | 2 | 3 | 4\n code?: string | number\n source?: string\n message: string\n tags?: number[]\n servers?: string[]\n}\nexport interface NormalizedCompletionItem { server: string; label: string; kind?: number; detail?: string; documentation?: string; sortText?: string; filterText?: string; insertText?: string; insertTextFormat?: number; deprecated?: boolean }\n/** A skipped diagnostic query is unverified; an empty diagnostics array alone is not evidence of a clean file. */\nexport interface DiagnosticsResult { skipped?: { reason: 'unsupported_file_type'; filePath: string }; diagnostics: NormalizedDiagnostic[]; omittedServers?: string[]; truncated?: { diagnostics: number; characters: number } }\nexport interface CompletionResult { items: NormalizedCompletionItem[]; truncated?: { items: number; characters: number } }\n\nexport interface WebstackLspStatus {\n providerId: string\n /** Routing suffixes; enabled/available servers are reported separately. */\n supportedFileSuffixes?: string[]\n servers: Array<{ id: import('./config.js').ServerId; enabled: boolean; available: boolean; source: 'bundled' | 'path'; command?: string; version?: string; lastError?: string; liveWorkspaces: number; restarts: number }>\n}\n\nexport interface WebstackLspService {\n status(): Promise<WebstackLspStatus>\n diagnostics(request: DiagnosticsRequest, signal?: AbortSignal): Promise<DiagnosticsResult>\n completion(request: CompletionRequest, signal?: AbortSignal): Promise<CompletionResult>\n}\n\nexport interface ExtendedRuntime extends WebstackLspService {}\n\nexport function createWebstackLspService(runtime: ExtendedRuntime, config: Pick<ResolvedConfig, 'limits'> = { limits: { maxDocumentBytes: 1_048_576, maxMessageBytes: 8_388_608, maxStderrBytes: 65_536 } }): WebstackLspService {\n return {\n status: () => runtime.status(),\n diagnostics: (request, signal) => runtime.diagnostics(validateDiagnosticsRequest(request), signal),\n completion: (request, signal) => runtime.completion(validateCompletionRequest(request), signal),\n }\n}\n\nfunction validateDiagnosticsRequest(request: DiagnosticsRequest): DiagnosticsRequest {\n if (!isRequest(request) || typeof request.workspaceRoot !== 'string' || request.workspaceRoot.length === 0 || typeof request.filePath !== 'string' || request.filePath.length === 0) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'workspaceRoot and filePath are required')\n return { ...request, ...(request.servers ? { servers: [...request.servers] } : {}) }\n}\n\nfunction validateCompletionRequest(request: CompletionRequest): CompletionRequest {\n if (!isRequest(request) || typeof request.workspaceRoot !== 'string' || request.workspaceRoot.length === 0 || typeof request.filePath !== 'string' || request.filePath.length === 0 || !isPosition(request.position)) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'workspaceRoot, filePath and position are required')\n return { ...request, position: { ...request.position } }\n}\n\nfunction isPosition(value: unknown): value is LspPosition { return typeof value === 'object' && value !== null && Number.isInteger((value as { line?: unknown }).line) && Number.isInteger((value as { character?: unknown }).character) && (value as LspPosition).line >= 0 && (value as LspPosition).character >= 0 }\nfunction isRequest(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value) }\n\nexport function createUnavailableService(providerId = 'webstack'): WebstackLspService {\n return { status: async () => ({ providerId, servers: [] }), diagnostics: async () => Promise.reject(new WebstackLspError('LSP_UNAVAILABLE', 'webstack runtime is unavailable')), completion: async () => Promise.reject(new WebstackLspError('LSP_UNAVAILABLE', 'webstack runtime is unavailable')) }\n}\n","import { createRequire } from 'node:module'\nimport { dirname, resolve } from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport type { LaunchSpec } from './types.js'\n\nconst require = createRequire(import.meta.url)\n\nexport async function resolvePackageBinary(packageName: string, binName: string, cwd: string, args = ['--stdio']): Promise<LaunchSpec> {\n const packageJson = require.resolve(`${packageName}/package.json`)\n const metadata = JSON.parse(await readFile(packageJson, 'utf8')) as { bin?: string | Record<string, string> }\n const bin = typeof metadata.bin === 'string' ? metadata.bin : metadata.bin?.[binName] ?? metadata.bin?.[packageName]\n if (!bin) throw new Error(`binary ${binName} is not declared by ${packageName}`)\n return { command: process.execPath, args: [resolve(dirname(packageJson), bin), ...args], cwd }\n}\n","import { createRequire } from 'node:module'\nimport type { ResolvedConfig, ServerId } from '../config.js'\nimport { resolvePackageBinary } from './package-bin.js'\nimport type { LaunchSpec } from './types.js'\n\nconst packages: Record<Exclude<ServerId, 'phpantom'>, [string, string]> = {\n typescript: ['typescript-language-server', 'typescript-language-server'],\n svelte: ['svelte-language-server', 'svelteserver'],\n html: ['vscode-langservers-extracted', 'vscode-html-language-server'],\n css: ['vscode-langservers-extracted', 'vscode-css-language-server'],\n tailwind: ['@tailwindcss/language-server', 'tailwindcss-language-server'],\n}\n\nexport async function resolveLaunch(id: ServerId, config: ResolvedConfig, workspace: string): Promise<LaunchSpec> {\n const server = config.servers[id]\n if (server.mode === 'path' || id === 'phpantom') return { command: server.command, args: [...server.args], cwd: workspace, env: { ...server.env } }\n const [pkg, bin] = packages[id]\n return { ...await resolvePackageBinary(pkg, bin, workspace, server.args), env: { ...server.env } }\n}\n\nexport function initializationOptions(id: ServerId, config: ResolvedConfig): unknown {\n const configured = config.servers[id].initializationOptions\n if (configured !== undefined) return configured\n if (id === 'typescript' && config.servers[id].mode === 'bundled') {\n return { tsserver: { path: createRequire(import.meta.url).resolve('typescript/lib/tsserver.js') } }\n }\n if (id === 'tailwind') return { userLanguages: config.tailwind.includeLanguages }\n return null\n}\n\nexport function serverConfiguration(id: ServerId, config: ResolvedConfig): unknown {\n if (config.servers[id].configuration !== undefined) return config.servers[id].configuration\n if (id === 'tailwind') return { tailwindCSS: { classAttributes: config.tailwind.classAttributes, includeLanguages: config.tailwind.includeLanguages, experimental: { classRegex: config.tailwind.classRegex } } }\n return {}\n}\n"],"mappings":";;;;;;AAuFA,MAAMA,kBAA4C;CAChD,UAAU;CACV,YAAY;CACZ,QAAQ;CACR,MAAM;CACN,KAAK;CACL,UAAU;CACX;AAED,MAAMC,uBAAqD;CACzD,UAAU;CACV,YAAY;CACZ,QAAQ;CACR,MAAM;CACN,KAAK;CACL,UAAU;CACX;AAED,MAAaC,aAAyB;CAAC;CAAY;CAAc;CAAU;CAAQ;CAAO;CAAW;AACrG,MAAM,iBAAiB;CAAE,kBAAkB;CAAW,iBAAiB;CAAW,gBAAgB;CAAQ;AAC1G,MAAM,mBAAmB;CAAE,cAAc;CAAQ,gBAAgB;CAAQ,kBAAkB;CAAO,eAAe;CAAQ,cAAc;CAAQ,YAAY;CAAO,aAAa;CAAO;AAEtL,MAAaC,iBAAiC;CAC5C,YAAY;CACZ,qBAAqB;CACrB,QAAQ,EAAE,GAAG,gBAAgB;CAC7B,UAAU,EAAE,GAAG,kBAAkB;CACjC,SAAS,OAAO,YAAY,WAAW,KAAK,OAAO,CAAC,IAAI;EACtD,SAAS;EACT,MAAM,qBAAqB;EAC3B,SAAS,gBAAgB;EACzB,MAAM,CAAC,UAAU;EACjB,KAAK,EAAE;EACR,CAAC,CAAC,CAAC;CACJ,UAAU;EAAE,SAAS;EAAM,eAAe;EAAa,iBAAiB;GAAC;GAAS;GAAa;GAAa;EAAE,YAAY,EAAE;EAAE,kBAAkB,EAAE;EAAE;CACpJ,SAAS;EAAE,eAAe,CAAC,aAAa;EAAE,mBAAmB;GAAC;GAAQ;GAAU;GAAc;GAAmB;GAAc;GAAkB;EAAE;CACpJ;AAED,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,oBAAoB,OAAgB,OAAe,UAA0B;AACpF,KAAI,UAAU,OAAW,QAAO;AAChC,KAAI,OAAO,UAAU,YAAY,CAAC,OAAO,cAAc,MAAM,IAAI,SAAS,KAAK,QAAQ,WAAe,OAAM,YAAY,GAAG,MAAM,wDAAwD;AACzL,QAAO;;AAGT,SAAS,YAAY,OAAgB,OAAe,UAA4B;AAC9E,KAAI,UAAU,OAAW,QAAO;AAChC,KAAI,OAAO,UAAU,UAAW,OAAM,YAAY,GAAG,MAAM,oBAAoB;AAC/E,QAAO;;AAGT,SAAS,WAAW,OAAgB,OAAe,UAA0B;AAC3E,KAAI,UAAU,OAAW,QAAO;AAChC,KAAI,OAAO,UAAU,YAAY,MAAM,MAAM,CAAC,WAAW,KAAK,MAAM,SAAS,KAAS,CAAE,OAAM,YAAY,GAAG,MAAM,yCAAyC;AAC5J,QAAO;;AAGT,SAAS,UAAU,OAAgB,OAAwB;AACzD,KAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO;AACnH,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,MAAM,KAAK,SAAS,UAAU,MAAM,MAAM,CAAC;AAC5E,KAAI,SAAS,MAAM,CAAE,QAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC,CAAC;AACzH,OAAM,YAAY,GAAG,MAAM,sCAAsC;;AAGnE,SAAS,gBAAgB,OAAgB,OAAe,UAA8B;AACpF,KAAI,UAAU,OAAW,QAAO,CAAC,GAAG,SAAS;AAC7C,KAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,WAAW,EAAG,OAAM,YAAY,GAAG,MAAM,4BAA4B;CACxG,MAAM,aAAa,MAAM,KAAK,QAAQ,UAAU;AAC9C,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,KAAK,OAAO,SAAS,IAAI,IAAI,OAAO,SAAS,KAAK,CAAE,OAAM,YAAY,GAAG,MAAM,GAAG,MAAM,yBAAyB;AACrK,SAAO,OAAO,aAAa;GAC3B;AACF,KAAI,IAAI,IAAI,WAAW,CAAC,SAAS,WAAW,OAAQ,OAAM,YAAY,GAAG,MAAM,8BAA8B;AAC7G,QAAO;;AAGT,SAAS,mBAAmB,OAAgB,OAAe,UAA8B;AACvF,KAAI,UAAU,OAAW,QAAO,CAAC,GAAG,SAAS;AAC7C,KAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,SAAS,OAAO,SAAS,SAAS,CAAE,OAAM,YAAY,GAAG,MAAM,8BAA8B;AACtI,QAAO,CAAC,GAAG,MAAM;;AAGnB,SAAS,WAAW,OAAgB,OAAuC;AACzE,KAAI,UAAU,OAAW,QAAO,EAAE;AAClC,KAAI,CAAC,SAAS,MAAM,IAAI,OAAO,QAAQ,MAAM,CAAC,MAAM,CAAC,KAAK,UAAU,IAAI,WAAW,KAAK,OAAO,SAAS,SAAS,CAAE,OAAM,YAAY,GAAG,MAAM,uBAAuB;AACrK,QAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,KAAe,CAAC,CAAC;;AAG9F,SAAS,cAAc,IAAc,OAAsC;AACzE,KAAI,UAAU,UAAa,CAAC,SAAS,MAAM,CAAE,OAAM,YAAY,WAAW,GAAG,oBAAoB;CACjG,MAAM,QAAQ;CACd,MAAM,OAAO,OAAO,SAAS,SAAY,qBAAqB,MAAM,MAAM;AAC1E,KAAI,SAAS,aAAa,SAAS,OAAQ,OAAM,YAAY,WAAW,GAAG,+BAA+B;AAC1G,KAAI,OAAO,cAAc,SAAS,UAAW,OAAM,YAAY,8BAA8B;CAC7F,MAAM,UAAU,OAAO,YAAY,SAAY,gBAAgB,MAAM,WAAW,MAAM,SAAS,WAAW,GAAG,WAAW,gBAAgB,IAAI;AAC5I,KAAI,SAAS,UAAU,OAAO,YAAY,UAAa,OAAO,WAAY,OAAM,YAAY,WAAW,GAAG,mCAAmC;CAC7I,MAAM,YAAY,OAAO;AACzB,KAAI,cAAc,WAAc,CAAC,MAAM,QAAQ,UAAU,IAAI,UAAU,MAAM,SAAS,OAAO,SAAS,SAAS,EAAG,OAAM,YAAY,WAAW,GAAG,mCAAmC;AACrL,QAAO;EACL,SAAS,YAAY,OAAO,SAAS,WAAW,GAAG,WAAW,KAAK;EACnE;EACA;EACA,MAAM,cAAc,SAAY,CAAC,UAAU,GAAG,CAAC,GAAG,UAAU;EAC5D,KAAK,WAAW,OAAO,KAAK,WAAW,GAAG,MAAM;EAChD,GAAI,OAAO,0BAA0B,SAAY,EAAE,GAAG,EAAE,uBAAuB,UAAU,MAAM,uBAAuB,WAAW,GAAG,wBAAwB,EAAE;EAC9J,GAAI,OAAO,kBAAkB,SAAY,EAAE,GAAG,EAAE,eAAe,UAAU,MAAM,eAAe,WAAW,GAAG,gBAAgB,EAAE;EAC/H;;AAGH,SAAgB,cAAc,QAAiB,EAAE,EAAkB;AACjE,KAAI,CAAC,SAAS,MAAM,CAAE,OAAM,YAAY,2BAA2B;CACnE,MAAM,SAAS,SAAS,MAAM,OAAO,GAAG,MAAM,SAAS,MAAM,WAAW,SAAY,EAAE,UAAU;AAAE,QAAM,YAAY,2BAA2B;KAAK;CACpJ,MAAM,WAAW,SAAS,MAAM,SAAS,GAAG,MAAM,WAAW,MAAM,aAAa,SAAY,EAAE,UAAU;AAAE,QAAM,YAAY,6BAA6B;KAAK;CAC9J,MAAM,WAAW,SAAS,MAAM,SAAS,GAAG,MAAM,WAAW,MAAM,aAAa,SAAY,EAAE,UAAU;AAAE,QAAM,YAAY,6BAA6B;KAAK;CAC9J,MAAM,UAAU,SAAS,MAAM,QAAQ,GAAG,MAAM,UAAU,MAAM,YAAY,SAAY,EAAE,UAAU;AAAE,QAAM,YAAY,4BAA4B;KAAK;CACzJ,MAAM,cAAc,SAAS,MAAM,QAAQ,GAAG,MAAM,UAAU,MAAM,YAAY,SAAY,EAAE,UAAU;AAAE,QAAM,YAAY,4BAA4B;KAAK;CAC7J,MAAM,aAAa,WAAW,MAAM,YAAY,cAAc,eAAe,WAAW;CACxF,MAAM,sBAAsB,MAAM,wBAAwB,SAAY,SAAS,MAAM;AACrF,KAAI,wBAAwB,UAAU,wBAAwB,QAAS,OAAM,YAAY,4CAA4C;CACrI,MAAM,aAAa,SAAS;AAC5B,KAAI,eAAe,WAAc,CAAC,MAAM,QAAQ,WAAW,IAAI,WAAW,MAAM,SAAS,OAAO,SAAS,aAAa,CAAC,MAAM,QAAQ,KAAK,IAAI,KAAK,WAAW,KAAK,KAAK,MAAM,SAAS,OAAO,SAAS,SAAS,EAAE,EAAG,OAAM,YAAY,2DAA2D;CAClS,MAAM,gBAAgB,SAAS,kBAAkB,SAAY,cAAc,SAAS;AACpF,MAAK,MAAM,cAAe,cAAc,EAAE,CACxC,MAAK,MAAM,WAAW,MAAM,QAAQ,WAAW,GAAG,aAAa,CAAC,WAAW,CACzE,KAAI;AAAE,MAAI,OAAO,QAAQ;SAAS;AAAE,QAAM,YAAY,6DAA6D;;AAGvH,KAAI,kBAAkB,eAAe,kBAAkB,SAAU,OAAM,YAAY,qDAAqD;CACxI,MAAM,mBAAmB,WAAW,SAAS,kBAAkB,4BAA4B;AAC3F,QAAO;EACL;EACA;EACA,QAAQ;GACN,kBAAkB,oBAAoB,OAAO,kBAAkB,2BAA2B,eAAe,iBAAiB;GAC1H,iBAAiB,oBAAoB,OAAO,iBAAiB,0BAA0B,eAAe,gBAAgB;GACtH,gBAAgB,oBAAoB,OAAO,gBAAgB,yBAAyB,eAAe,eAAe;GACnH;EACD,UAAU;GACR,cAAc,oBAAoB,SAAS,cAAc,yBAAyB,iBAAiB,aAAa;GAChH,gBAAgB,oBAAoB,SAAS,gBAAgB,2BAA2B,iBAAiB,eAAe;GACxH,kBAAkB,oBAAoB,SAAS,kBAAkB,6BAA6B,iBAAiB,iBAAiB;GAChI,eAAe,oBAAoB,SAAS,eAAe,0BAA0B,iBAAiB,cAAc;GACpH,cAAc,oBAAoB,SAAS,cAAc,yBAAyB,iBAAiB,aAAa;GAChH,YAAY,oBAAoB,SAAS,YAAY,uBAAuB,iBAAiB,WAAW;GACxG,aAAa,oBAAoB,SAAS,aAAa,wBAAwB,iBAAiB,YAAY;GAC7G;EACD,SAAS,OAAO,YAAY,WAAW,KAAK,OAAO,CAAC,IAAI,cAAc,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC;EAC7F,UAAU;GACR,SAAS,YAAY,SAAS,SAAS,oBAAoB,KAAK;GAChE;GACA,iBAAiB,mBAAmB,SAAS,iBAAiB,4BAA4B,eAAe,SAAS,gBAAgB;GAClI,YAAY,eAAe,SAAY,EAAE,GAAI,WAAW,KAAK,SAAS,MAAM,QAAQ,KAAK,GAAG,CAAC,GAAG,KAAK,GAAuB,KAAK;GACjI;GACD;EACD,SAAS;GACP,eAAe,gBAAgB,QAAQ,eAAe,yBAAyB,eAAe,QAAQ,cAAc;GACpH,mBAAmB,mBAAmB,QAAQ,mBAAmB,6BAA6B,eAAe,QAAQ,kBAAkB;GACxI;EACF;;AAGH,IAAI,eAAe,SAAS,kBAAkB,eAAe,eAAe,SAAS,kBAAkB,SAAU,OAAM,IAAI,MAAM,2BAA2B;;;;AClN5J,SAAgB,yBAAyB,SAA0B,SAAyC,EAAE,QAAQ;CAAE,kBAAkB;CAAW,iBAAiB;CAAW,gBAAgB;CAAQ,EAAE,EAAsB;AAC/N,QAAO;EACL,cAAc,QAAQ,QAAQ;EAC9B,cAAc,SAAS,WAAW,QAAQ,YAAY,2BAA2B,QAAQ,EAAE,OAAO;EAClG,aAAa,SAAS,WAAW,QAAQ,WAAW,0BAA0B,QAAQ,EAAE,OAAO;EAChG;;AAGH,SAAS,2BAA2B,SAAiD;AACnF,KAAI,CAAC,UAAU,QAAQ,IAAI,OAAO,QAAQ,kBAAkB,YAAY,QAAQ,cAAc,WAAW,KAAK,OAAO,QAAQ,aAAa,YAAY,QAAQ,SAAS,WAAW,EAAG,OAAM,IAAI,iBAAiB,0BAA0B,0CAA0C;AACpR,QAAO;EAAE,GAAG;EAAS,GAAI,QAAQ,UAAU,EAAE,SAAS,CAAC,GAAG,QAAQ,QAAQ,EAAE,GAAG,EAAE;EAAG;;AAGtF,SAAS,0BAA0B,SAA+C;AAChF,KAAI,CAAC,UAAU,QAAQ,IAAI,OAAO,QAAQ,kBAAkB,YAAY,QAAQ,cAAc,WAAW,KAAK,OAAO,QAAQ,aAAa,YAAY,QAAQ,SAAS,WAAW,KAAK,CAAC,WAAW,QAAQ,SAAS,CAAE,OAAM,IAAI,iBAAiB,0BAA0B,oDAAoD;AAC/T,QAAO;EAAE,GAAG;EAAS,UAAU,EAAE,GAAG,QAAQ,UAAU;EAAE;;AAG1D,SAAS,WAAW,OAAsC;AAAE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,OAAO,UAAW,MAA6B,KAAK,IAAI,OAAO,UAAW,MAAkC,UAAU,IAAK,MAAsB,QAAQ,KAAM,MAAsB,aAAa;;AACpT,SAAS,UAAU,OAAkD;AAAE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAElJ,SAAgB,yBAAyB,aAAa,YAAgC;AACpF,QAAO;EAAE,QAAQ,aAAa;GAAE;GAAY,SAAS,EAAE;GAAE;EAAG,aAAa,YAAY,QAAQ,OAAO,IAAI,iBAAiB,mBAAmB,kCAAkC,CAAC;EAAE,YAAY,YAAY,QAAQ,OAAO,IAAI,iBAAiB,mBAAmB,kCAAkC,CAAC;EAAE;;;;;ACzDvS,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;AAE9C,eAAsB,qBAAqB,aAAqB,SAAiB,KAAa,OAAO,CAAC,UAAU,EAAuB;CACrI,MAAM,cAAc,QAAQ,QAAQ,GAAG,YAAY,eAAe;CAClE,MAAM,WAAW,KAAK,MAAM,MAAM,SAAS,aAAa,OAAO,CAAC;CAChE,MAAM,MAAM,OAAO,SAAS,QAAQ,WAAW,SAAS,MAAM,SAAS,MAAM,YAAY,SAAS,MAAM;AACxG,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,UAAU,QAAQ,sBAAsB,cAAc;AAChF,QAAO;EAAE,SAAS,QAAQ;EAAU,MAAM,CAAC,QAAQ,QAAQ,YAAY,EAAE,IAAI,EAAE,GAAG,KAAK;EAAE;EAAK;;;;;ACPhG,MAAMC,WAAoE;CACxE,YAAY,CAAC,8BAA8B,6BAA6B;CACxE,QAAQ,CAAC,0BAA0B,eAAe;CAClD,MAAM,CAAC,gCAAgC,8BAA8B;CACrE,KAAK,CAAC,gCAAgC,6BAA6B;CACnE,UAAU,CAAC,gCAAgC,8BAA8B;CAC1E;AAED,eAAsB,cAAc,IAAc,QAAwB,WAAwC;CAChH,MAAM,SAAS,OAAO,QAAQ;AAC9B,KAAI,OAAO,SAAS,UAAU,OAAO,WAAY,QAAO;EAAE,SAAS,OAAO;EAAS,MAAM,CAAC,GAAG,OAAO,KAAK;EAAE,KAAK;EAAW,KAAK,EAAE,GAAG,OAAO,KAAK;EAAE;CACnJ,MAAM,CAAC,KAAK,OAAO,SAAS;AAC5B,QAAO;EAAE,GAAG,MAAM,qBAAqB,KAAK,KAAK,WAAW,OAAO,KAAK;EAAE,KAAK,EAAE,GAAG,OAAO,KAAK;EAAE;;AAGpG,SAAgB,sBAAsB,IAAc,QAAiC;CACnF,MAAM,aAAa,OAAO,QAAQ,IAAI;AACtC,KAAI,eAAe,OAAW,QAAO;AACrC,KAAI,OAAO,gBAAgB,OAAO,QAAQ,IAAI,SAAS,UACrD,QAAO,EAAE,UAAU,EAAE,MAAM,cAAc,OAAO,KAAK,IAAI,CAAC,QAAQ,6BAA6B,EAAE,EAAE;AAErG,KAAI,OAAO,WAAY,QAAO,EAAE,eAAe,OAAO,SAAS,kBAAkB;AACjF,QAAO;;AAGT,SAAgB,oBAAoB,IAAc,QAAiC;AACjF,KAAI,OAAO,QAAQ,IAAI,kBAAkB,OAAW,QAAO,OAAO,QAAQ,IAAI;AAC9E,KAAI,OAAO,WAAY,QAAO,EAAE,aAAa;EAAE,iBAAiB,OAAO,SAAS;EAAiB,kBAAkB,OAAO,SAAS;EAAkB,cAAc,EAAE,YAAY,OAAO,SAAS,YAAY;EAAE,EAAE;AACjN,QAAO,EAAE"}
package/lib/lsp.js ADDED
@@ -0,0 +1,5 @@
1
+ import dsh_lsp_default from "@deepseek-ai/dsh-lsp";
2
+
3
+ export * from "@deepseek-ai/dsh-lsp"
4
+
5
+ export { dsh_lsp_default as default };
package/lib/provider.js CHANGED
@@ -158,6 +158,10 @@ function classifyFile(filePath, bladeSuffixes = [".blade.php"]) {
158
158
  kind: match.kind
159
159
  };
160
160
  }
161
+ /** Return the supported suffixes, including configured Blade suffixes. */
162
+ function supportedFileSuffixes(bladeSuffixes = [".blade.php"]) {
163
+ return [...new Set([...bladeSuffixes.map((suffix) => suffix.toLowerCase()), ...CLASSIFIERS.map((item) => item.suffix)])];
164
+ }
161
165
 
162
166
  //#endregion
163
167
  //#region src/routing/route-table.ts
@@ -995,6 +999,16 @@ var WebstackLspRuntime = class {
995
999
  }
996
1000
  async diagnostics(request, signal) {
997
1001
  const deadline = this.signal(this.config.timeouts.diagnosticsMs, signal);
1002
+ if (!classifyFile(request.filePath, this.config.routing.bladeSuffixes)) {
1003
+ await readSource(this.fs, request.workspaceRoot, request.filePath, this.config.limits.maxDocumentBytes, deadline);
1004
+ return {
1005
+ diagnostics: [],
1006
+ skipped: {
1007
+ reason: "unsupported_file_type",
1008
+ filePath: request.filePath
1009
+ }
1010
+ };
1011
+ }
998
1012
  const [source, route] = await this.prepare(request, deadline);
999
1013
  const selected = [route.primary, ...route.auxiliary && this.config.tailwind.enabled ? [route.auxiliary] : []].filter((item) => this.config.servers[item.server].enabled && (!request.servers || request.servers.includes(item.server)));
1000
1014
  if (!selected.length) throw new WebstackLspError("LSP_UNAVAILABLE", "no selected diagnostic server supports this file");
@@ -1040,6 +1054,7 @@ var WebstackLspRuntime = class {
1040
1054
  async status() {
1041
1055
  return {
1042
1056
  providerId: this.config.providerId,
1057
+ supportedFileSuffixes: supportedFileSuffixes(this.config.routing.bladeSuffixes),
1043
1058
  servers: await Promise.all(SERVER_IDS.map(async (id) => {
1044
1059
  const config = this.config.servers[id];
1045
1060
  let available = false;
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","names":["CLASSIFIERS: ReadonlyArray<{ suffix: string; kind: FileKind }>","ROUTES: Record<ClassifiedFile['kind'], Route>","maxMessageBytes: number","messages: unknown[]","text: string","length: number | undefined","input: Readable","output: Writable","messages: unknown[]","isRecord","options: ServerSessionOptions","factory: SessionFactory<S>","release!: () => void","isRange","isRecord","isPosition","isRecord","isRange","isPosition","isRecord","config: ResolvedConfig","fs: HostFileSystem","subprocess: HostSubprocess","executable: string","auxiliary: typeof primary","omittedServers: string[]"],"sources":["../src/runtime/cancellation.ts","../src/host/dsh.ts","../src/routing/classifier.ts","../src/routing/route-table.ts","../src/routing/tailwind-candidate.ts","../src/protocol/initialize.ts","../src/runtime/framing.ts","../src/runtime/connection.ts","../src/runtime/server-session.ts","../src/runtime/server-pool.ts","../src/protocol/capabilities.ts","../src/protocol/normalize-hover.ts","../src/protocol/normalize-location.ts","../src/protocol/normalize-diagnostic.ts","../src/protocol/normalize-completion.ts","../src/merge/hover.ts","../src/runtime/webstack-runtime.ts","../src/provider.ts"],"sourcesContent":["export function abortError(): Error {\n const error = new Error('The operation was aborted')\n error.name = 'AbortError'\n return error\n}\n\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortError()\n}\n\nexport function onAbort(signal: AbortSignal | undefined, callback: () => void): () => void {\n if (!signal) return () => {}\n if (signal.aborted) {\n callback()\n return () => {}\n }\n signal.addEventListener('abort', callback, { once: true })\n return () => signal.removeEventListener('abort', callback)\n}\n\nexport async function withAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n throwIfAborted(signal)\n if (!signal) return promise\n return new Promise<T>((resolve, reject) => {\n const remove = onAbort(signal, () => reject(abortError()))\n promise.then((value) => { remove(); resolve(value) }, (error: unknown) => { remove(); reject(error) })\n })\n}\n","import type { FileSystem } from '@deepseek-ai/dsh-fs'\nimport { WebstackLspError } from '../errors.js'\nimport { throwIfAborted } from '../runtime/cancellation.js'\n\nexport type HostFileSystem = Pick<FileSystem, 'resolve' | 'stat' | 'processPath' | 'fileUrl' | 'contains' | 'streamText'>\nexport interface HostSource { workspace: string; workspaceUri: string; key: string; uri: string; text: string }\n\nexport async function readSource(fs: HostFileSystem, workspaceRoot: string, filePath: string, maxBytes: number, signal?: AbortSignal): Promise<HostSource> {\n if (!workspaceRoot?.trim() || !filePath?.trim()) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'workspaceRoot and filePath are required')\n throwIfAborted(signal)\n const options = signal ? { signal } : {}\n const root = await fs.resolve(workspaceRoot, options)\n if ((await fs.stat(root, signal))?.type !== 'directory') throw new Error('workspace root is not a directory')\n const workspace = fs.processPath(root)\n const target = await fs.resolve(filePath, { cwd: workspace, ...options })\n if (!fs.contains(root, target)) throw new Error('source is outside workspace')\n if ((await fs.stat(target, signal))?.type !== 'file') throw new Error('source is not a regular file')\n let text = '', bytes = 0\n for await (const chunk of await fs.streamText(target, signal)) {\n throwIfAborted(signal)\n bytes += Buffer.byteLength(chunk)\n if (bytes > maxBytes) throw new Error('source exceeds document limit')\n text += chunk\n }\n throwIfAborted(signal)\n return { workspace, workspaceUri: fs.fileUrl(root), key: root.targetKey, uri: fs.fileUrl(target), text }\n}\n","export type FileKind = 'blade' | 'php' | 'typescript' | 'typescriptreact' | 'javascript' | 'javascriptreact' | 'svelte' | 'html' | 'css'\n\nexport interface ClassifiedFile {\n path: string\n basename: string\n suffix: string\n kind: FileKind\n}\n\nconst CLASSIFIERS: ReadonlyArray<{ suffix: string; kind: FileKind }> = [\n { suffix: '.blade.php', kind: 'blade' },\n { suffix: '.typescriptreact', kind: 'typescriptreact' },\n { suffix: '.javascriptreact', kind: 'javascriptreact' },\n { suffix: '.tsx', kind: 'typescriptreact' },\n { suffix: '.jsx', kind: 'javascriptreact' },\n { suffix: '.mts', kind: 'typescript' },\n { suffix: '.cts', kind: 'typescript' },\n { suffix: '.mjs', kind: 'javascript' },\n { suffix: '.cjs', kind: 'javascript' },\n { suffix: '.svelte', kind: 'svelte' },\n { suffix: '.html', kind: 'html' },\n { suffix: '.htm', kind: 'html' },\n { suffix: '.php', kind: 'php' },\n { suffix: '.ts', kind: 'typescript' },\n { suffix: '.js', kind: 'javascript' },\n { suffix: '.css', kind: 'css' },\n { suffix: '.pcss', kind: 'css' },\n]\n\nexport function classifyFile(filePath: string, bladeSuffixes: string[] = ['.blade.php']): ClassifiedFile | undefined {\n const normalizedPath = filePath.replaceAll('\\\\', '/')\n const basename = normalizedPath.slice(normalizedPath.lastIndexOf('/') + 1).toLowerCase()\n if (!basename || basename === '.' || basename === '..' || basename.startsWith('.')) return undefined\n const customBlade = bladeSuffixes.map((suffix) => suffix.toLowerCase()).sort((left, right) => right.length - left.length)\n const classifiers = [...customBlade.map((suffix) => ({ suffix, kind: 'blade' as const })), ...CLASSIFIERS.filter((item) => !customBlade.includes(item.suffix))]\n const match = classifiers.find((item) => basename.endsWith(item.suffix))\n if (!match) return undefined\n return { path: normalizedPath, basename, suffix: match.suffix, kind: match.kind }\n}\n","import type { ServerId } from '../config.js'\nimport type { ClassifiedFile } from './classifier.js'\n\nexport interface Route {\n primary: { server: ServerId; languageId: string }\n auxiliary?: { server: 'tailwind'; languageId: string }\n}\n\nconst ROUTES: Record<ClassifiedFile['kind'], Route> = {\n blade: { primary: { server: 'phpantom', languageId: 'blade' }, auxiliary: { server: 'tailwind', languageId: 'html' } },\n php: { primary: { server: 'phpantom', languageId: 'php' } },\n typescript: { primary: { server: 'typescript', languageId: 'typescript' }, auxiliary: { server: 'tailwind', languageId: 'typescript' } },\n typescriptreact: { primary: { server: 'typescript', languageId: 'typescriptreact' }, auxiliary: { server: 'tailwind', languageId: 'typescriptreact' } },\n javascript: { primary: { server: 'typescript', languageId: 'javascript' }, auxiliary: { server: 'tailwind', languageId: 'javascript' } },\n javascriptreact: { primary: { server: 'typescript', languageId: 'javascriptreact' }, auxiliary: { server: 'tailwind', languageId: 'javascriptreact' } },\n svelte: { primary: { server: 'svelte', languageId: 'svelte' }, auxiliary: { server: 'tailwind', languageId: 'svelte' } },\n html: { primary: { server: 'html', languageId: 'html' }, auxiliary: { server: 'tailwind', languageId: 'html' } },\n css: { primary: { server: 'css', languageId: 'css' }, auxiliary: { server: 'tailwind', languageId: 'css' } },\n}\n\nexport function routeFor(file: ClassifiedFile): Route {\n const route = ROUTES[file.kind]\n return { primary: { ...route.primary }, ...(route.auxiliary ? { auxiliary: { ...route.auxiliary } } : {}) }\n}\n","const DEFAULT_PATTERNS = [\n /\\bclass\\s*=\\s*[\"'][^\"']*$/i,\n /\\bclassName\\s*=\\s*[\"'][^\"']*$/i,\n /\\bclass:list\\s*=\\s*[\"'][^\"']*$/i,\n /@apply\\s+[\\w-]*$/i,\n /\\b(?:clsx|cva)\\s*\\([^)]*[\"'][^\"']*$/i,\n]\n\nexport function hasTailwindCandidate(source: string, line: number, classRegex: Array<string | [string, string]> = [], character?: number, classAttributes: string[] = ['class', 'className', 'class:list']): boolean {\n const lines = source.split(/\\r?\\n/)\n const context = [...lines.slice(Math.max(0, line - 2), line), (lines[line] ?? '').slice(0, character)].join('\\n')\n if (classAttributes.some(attribute => {\n const index = context.lastIndexOf(attribute + '=')\n return index >= 0 && /^[\\\"'][^\\\"']*$/.test(context.slice(index + attribute.length + 1).trimStart())\n })) return true\n const configured = classRegex.flatMap((item) => Array.isArray(item) ? item : [item]).map((pattern) => new RegExp(pattern))\n return [...DEFAULT_PATTERNS, ...configured].some((pattern) => pattern.test(context))\n}\n","import type { InitializeParams, InitializeResult } from './types.js'\nimport type { JsonRpcConnection } from '../runtime/connection.js'\nimport { throwIfAborted } from '../runtime/cancellation.js'\n\nexport async function initializeServer(connection: JsonRpcConnection, params: InitializeParams, signal?: AbortSignal): Promise<InitializeResult> {\n throwIfAborted(signal)\n const value = await connection.request('initialize', params, signal)\n if (!isInitializeResult(value)) throw new Error('malformed initialize response')\n await connection.notify('initialized', {})\n return value\n}\n\nfunction isInitializeResult(value: unknown): value is InitializeResult {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && typeof (value as { capabilities?: unknown }).capabilities === 'object' && (value as { capabilities?: unknown }).capabilities !== null\n}\n","import { TextDecoder } from 'node:util'\n\nexport class JsonRpcFrameError extends Error {\n readonly code = 'LSP_MALFORMED_RESPONSE'\n\n constructor(message: string) {\n super(message)\n this.name = 'JsonRpcFrameError'\n }\n}\n\nexport class ContentLengthDecoder {\n private buffer = Buffer.alloc(0)\n private readonly decoder = new TextDecoder('utf-8', { fatal: true })\n\n constructor(private readonly maxMessageBytes: number) {\n if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0) throw new RangeError('maxMessageBytes must be positive')\n }\n\n feed(chunk: Uint8Array): unknown[] {\n this.buffer = Buffer.concat([this.buffer, Buffer.from(chunk)])\n const messages: unknown[] = []\n while (true) {\n const headerEnd = this.buffer.indexOf(Buffer.from('\\r\\n\\r\\n'))\n if (headerEnd < 0) {\n if (this.buffer.length > 8192) throw new JsonRpcFrameError('header exceeds limit')\n break\n }\n const header = this.buffer.subarray(0, headerEnd).toString('ascii')\n const length = this.parseLength(header)\n const bodyStart = headerEnd + 4\n if (length > this.maxMessageBytes) throw new JsonRpcFrameError('message exceeds configured limit')\n if (this.buffer.length < bodyStart + length) break\n const body = this.buffer.subarray(bodyStart, bodyStart + length)\n this.buffer = this.buffer.subarray(bodyStart + length)\n let text: string\n try {\n text = this.decoder.decode(body)\n } catch {\n throw new JsonRpcFrameError('message is not valid UTF-8')\n }\n try {\n messages.push(JSON.parse(text) as unknown)\n } catch {\n throw new JsonRpcFrameError('message body is not valid JSON')\n }\n }\n return messages\n }\n\n end(): void {\n if (this.buffer.length > 0) throw new JsonRpcFrameError('incomplete JSON-RPC frame')\n }\n\n private parseLength(header: string): number {\n const lines = header.split('\\r\\n')\n let length: number | undefined\n for (const line of lines) {\n const separator = line.indexOf(':')\n if (separator < 1) throw new JsonRpcFrameError('malformed header')\n const key = line.slice(0, separator).toLowerCase()\n const value = line.slice(separator + 1).trim()\n if (key === 'content-length') {\n if (length !== undefined || !/^\\d+$/.test(value)) throw new JsonRpcFrameError('invalid Content-Length')\n length = Number(value)\n }\n }\n if (length === undefined || !Number.isSafeInteger(length)) throw new JsonRpcFrameError('Content-Length is required')\n return length\n }\n}\n\nexport function encodeJsonRpc(message: object): Buffer {\n const body = Buffer.from(JSON.stringify(message), 'utf8')\n return Buffer.concat([Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, 'ascii'), body])\n}\n","import type { Readable, Writable } from 'node:stream'\nimport { abortError, onAbort, throwIfAborted } from './cancellation.js'\nimport { ContentLengthDecoder, encodeJsonRpc, JsonRpcFrameError } from './framing.js'\nimport type { JsonRpcConnectionOptions, JsonRpcId, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse } from '../protocol/types.js'\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (error: unknown) => void\n method: string\n}\n\nexport class JsonRpcConnection {\n private readonly decoder: ContentLengthDecoder\n private readonly pending = new Map<JsonRpcId, PendingRequest>()\n private readonly notificationListeners = new Set<(notification: JsonRpcNotification) => void>()\n private nextId = 1\n private closed = false\n private requestHandler: NonNullable<JsonRpcConnectionOptions['onServerRequest']>\n\n constructor(private readonly input: Readable, private readonly output: Writable, options: JsonRpcConnectionOptions) {\n this.decoder = new ContentLengthDecoder(options.maxMessageBytes)\n this.requestHandler = options.onServerRequest ?? (() => null)\n if (options.onNotification) this.notificationListeners.add(options.onNotification)\n input.on('data', (chunk: Buffer) => this.receive(chunk))\n input.once('end', () => this.close(new Error('LSP process closed stdout')))\n input.once('error', (error) => this.close(error))\n output.on('error', (error) => this.close(error))\n }\n\n get isOpen(): boolean { return !this.closed }\n\n onNotification(listener: (notification: JsonRpcNotification) => void): () => void {\n this.notificationListeners.add(listener)\n return () => this.notificationListeners.delete(listener)\n }\n\n setRequestHandler(handler: NonNullable<JsonRpcConnectionOptions['onServerRequest']>): void {\n this.requestHandler = handler\n }\n\n async request(method: string, params?: unknown, signal?: AbortSignal): Promise<unknown> {\n throwIfAborted(signal)\n if (this.closed) throw new Error('connection is closed')\n const id = this.nextId++\n const promise = new Promise<unknown>((resolve, reject) => this.pending.set(id, { resolve, reject, method }))\n void promise.catch(() => {})\n const remove = onAbort(signal, () => {\n void this.notify('$/cancelRequest', { id }).catch(() => {})\n this.pending.get(id)?.reject(abortError())\n this.pending.delete(id)\n })\n try {\n void this.write({ jsonrpc: '2.0', id, method, ...(params === undefined ? {} : { params }) }).catch(error => this.close(error))\n return await promise\n } finally {\n remove()\n this.pending.delete(id)\n }\n }\n\n async notify(method: string, params?: unknown): Promise<void> {\n if (this.closed) throw new Error('connection is closed')\n await this.write({ jsonrpc: '2.0', method, ...(params === undefined ? {} : { params }) })\n }\n\n close(reason = new Error('connection closed')): void {\n if (this.closed) return\n this.closed = true\n for (const pending of this.pending.values()) pending.reject(reason)\n this.pending.clear()\n }\n\n private receive(chunk: Buffer): void {\n if (this.closed) return\n let messages: unknown[]\n try {\n messages = this.decoder.feed(chunk)\n } catch (error) {\n this.close(error instanceof Error ? error : new JsonRpcFrameError('invalid frame'))\n return\n }\n for (const message of messages) this.dispatch(message)\n }\n\n private dispatch(value: unknown): void {\n if (!isRecord(value) || value.jsonrpc !== '2.0') return this.close(new JsonRpcFrameError('invalid JSON-RPC message'))\n if ('method' in value && typeof value.method === 'string') {\n if ('id' in value) {\n const request = value as unknown as JsonRpcRequest\n Promise.resolve().then(() => this.requestHandler(request.method, request.params)).then(\n (result) => this.write({ jsonrpc: '2.0', id: request.id, result }),\n (error: unknown) => this.write({ jsonrpc: '2.0', id: request.id, error: { code: -32603, message: error instanceof Error ? error.message : 'server request failed' } }),\n ).catch(() => {})\n } else {\n for (const listener of this.notificationListeners) listener(value as unknown as JsonRpcNotification)\n }\n return\n }\n if ('id' in value) {\n const response = value as unknown as JsonRpcResponse\n const pending = this.pending.get(response.id)\n if (!pending) return\n if (response.error) pending.reject(new Error(`${response.error.code}: ${response.error.message}`))\n else pending.resolve(response.result)\n this.pending.delete(response.id)\n }\n }\n\n private write(message: JsonRpcMessage): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.output.write(encodeJsonRpc(message), (error?: Error | null) => error ? reject(error) : resolve())\n })\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { SubprocessHandle } from '@deepseek-ai/dsh-subprocess'\nimport type { InitializeParams, InitializeResult } from '../protocol/types.js'\nimport { initializeServer } from '../protocol/initialize.js'\nimport { JsonRpcConnection } from './connection.js'\nimport { withAbort, throwIfAborted } from './cancellation.js'\n\nexport type SessionState = 'NEW' | 'STARTING' | 'READY' | 'STOPPING' | 'STOPPED' | 'FAILED'\nexport interface ServerSessionOptions {\n spawn(): SubprocessHandle\n initialize: InitializeParams\n configuration: unknown\n maxMessageBytes: number\n shutdown: { shutdownMs: number; killGraceMs: number }\n}\n\nexport class ServerSession {\n state: SessionState = 'NEW'\n capabilities: Record<string, unknown> = {}\n private child?: SubprocessHandle\n private connection?: JsonRpcConnection\n private stopping?: Promise<void>\n private readonly lifetime = new AbortController()\n constructor(private readonly options: ServerSessionOptions) {}\n\n async start(signal?: AbortSignal): Promise<InitializeResult> {\n throwIfAborted(signal)\n this.state = 'STARTING'\n try {\n const child = this.options.spawn()\n this.child = child\n // Observe failed spawn even when stdio could not be allocated.\n void child.done.catch(() => {})\n if (!child.stdout || !child.stdin) throw new Error('server stdio is unavailable')\n const connection = new JsonRpcConnection(child.stdout, child.stdin, {\n maxMessageBytes: this.options.maxMessageBytes,\n onServerRequest: (method, params) => this.answer(method, params),\n })\n this.connection = connection\n void child.done.then(() => connection.close(new Error('LSP process exited')), error => connection.close(error instanceof Error ? error : new Error('LSP spawn failed'))).then(() => {\n if (this.state !== 'STOPPING' && this.state !== 'STOPPED') this.state = 'FAILED'\n })\n const result = await initializeServer(connection, this.options.initialize, this.signal(signal))\n if (result.capabilities.positionEncoding && result.capabilities.positionEncoding !== 'utf-16') throw new Error('server requires unsupported position encoding')\n const sync = result.capabilities.textDocumentSync\n if (sync === undefined || sync === 0 || (typeof sync === 'object' && sync !== null && !(sync as { openClose?: boolean }).openClose)) throw new Error('server does not support document open/close')\n this.capabilities = result.capabilities\n await connection.notify('workspace/didChangeConfiguration', { settings: this.options.configuration })\n throwIfAborted(this.signal(signal))\n this.state = 'READY'\n return result\n } catch (error) {\n this.state = 'FAILED'\n await this.stop()\n throw error\n }\n }\n\n get usable(): boolean { return this.state === 'READY' && !!this.connection?.isOpen }\n isUsable(): boolean { return this.usable }\n async run<T>(task: (connection: JsonRpcConnection) => Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!this.usable || !this.connection) throw new Error('session is not ready')\n try { return await withAbort(task(this.connection), this.signal(signal)) }\n catch (error) {\n // Stop cancelled work before the next queued request can reuse this process.\n if (signal?.aborted || !this.connection.isOpen) await this.stop()\n throw error\n }\n }\n\n stop(): Promise<void> {\n return this.stopping ??= this.teardown()\n }\n private async teardown(): Promise<void> {\n this.state = 'STOPPING'\n this.lifetime.abort()\n const child = this.child, connection = this.connection\n const timeout = AbortSignal.timeout(this.options.shutdown.shutdownMs)\n if (connection?.isOpen) {\n try { await connection.request('shutdown', null, timeout); await connection.notify('exit') } catch {}\n }\n connection?.close(new Error('session stopped'))\n if (child) {\n child.terminate()\n if (!await child.waitForExit(AbortSignal.timeout(this.options.shutdown.killGraceMs + 1000))) throw new Error('language server process tree did not exit within the cleanup deadline')\n }\n this.state = 'STOPPED'\n }\n private signal(signal?: AbortSignal): AbortSignal { return signal ? AbortSignal.any([signal, this.lifetime.signal]) : this.lifetime.signal }\n private answer(method: string, params: unknown): unknown {\n if (method === 'workspace/applyEdit') return { applied: false, failureReason: 'read-only provider' }\n if (method === 'workspace/workspaceFolders') return this.options.initialize.workspaceFolders ?? []\n if (method === 'workspace/configuration') {\n const items = (params as { items?: Array<{ section?: string }> } | undefined)?.items ?? []\n return items.map(item => {\n let value = this.options.configuration\n for (const key of item.section?.split('.') ?? []) {\n value = typeof value === 'object' && value !== null ? (value as Record<string, unknown>)[key] : undefined\n }\n return value ?? null\n })\n }\n return null\n }\n}\n","import { throwIfAborted, withAbort } from './cancellation.js'\n\nexport interface PoolSession {\n readonly state: string\n start(signal?: AbortSignal): Promise<unknown>\n stop(): Promise<void>\n isUsable(): boolean\n}\nexport type SessionFactory<S extends PoolSession> = (serverId: string, workspace: string, signal?: AbortSignal) => Promise<S>\n\nexport class ServerPool<S extends PoolSession> {\n private readonly sessions = new Map<string, S>()\n private readonly creation = new Map<string, Promise<S>>()\n private readonly queues = new Map<string, Promise<void>>()\n private disposing = false\n constructor(private readonly factory: SessionFactory<S>) {}\n\n async getOrCreate(serverId: string, workspace: string, signal?: AbortSignal): Promise<S> {\n throwIfAborted(signal)\n if (this.disposing) throw new Error('server pool is disposing')\n const key = keyOf(serverId, workspace)\n const existing = this.sessions.get(key)\n if (existing?.isUsable()) return existing\n const pending = this.creation.get(key)\n if (pending) return withAbort(pending, signal)\n const creation = this.create(key, serverId, workspace, existing, signal)\n this.creation.set(key, creation)\n try { return await creation }\n finally { if (this.creation.get(key) === creation) this.creation.delete(key) }\n }\n\n run<T>(serverId: string, workspace: string, task: (session: S) => Promise<T>, signal?: AbortSignal): Promise<T> {\n return this.serialize(keyOf(serverId, workspace), async () => task(await this.getOrCreate(serverId, workspace, signal)), signal)\n }\n\n runWithRetry<T>(serverId: string, workspace: string, task: (session: S) => Promise<T>, signal?: AbortSignal, canReuse?: (session: S) => boolean): Promise<T> {\n // Keep failure eviction and the retry inside the same queue slot. A later query\n // must never enter a replacement process before the failed query finishes cleanup.\n return this.serialize(keyOf(serverId, workspace), async () => {\n const existing = this.sessions.get(keyOf(serverId, workspace))\n // Replacement belongs to this queue slot, after earlier work has completed.\n if (existing?.isUsable() && canReuse && !canReuse(existing)) await this.evict(serverId, workspace)\n for (let attempt = 0; ; attempt++) {\n const session = await this.getOrCreate(serverId, workspace, signal)\n try { return await task(session) }\n catch (error) {\n throwIfAborted(signal)\n if (attempt > 0 || session.isUsable()) throw error\n if (this.sessions.get(keyOf(serverId, workspace)) === session) await this.evict(serverId, workspace)\n }\n }\n }, signal)\n }\n\n async evict(serverId: string, workspace: string): Promise<void> {\n const key = keyOf(serverId, workspace)\n const session = this.sessions.get(key)\n this.sessions.delete(key)\n if (session) await session.stop()\n }\n\n async disposeAll(): Promise<void> {\n this.disposing = true\n const results = await Promise.allSettled([...this.sessions.values()].map(session => session.stop()))\n this.sessions.clear()\n await Promise.all([...this.creation.values()].map(creation => creation.then(session => session.stop(), () => {})))\n this.creation.clear()\n const failures = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n if (failures.length) throw new AggregateError(failures.map(result => result.reason), 'language server cleanup failed')\n }\n\n get size(): number { return this.sessions.size }\n\n private async serialize<T>(key: string, task: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n const previous = this.queues.get(key) ?? Promise.resolve()\n let release!: () => void\n const current = new Promise<void>(resolve => { release = resolve })\n this.queues.set(key, current)\n try {\n await withAbort(previous, signal)\n throwIfAborted(signal)\n return await task()\n } finally {\n // A cancelled waiter cannot let its successor bypass still-running work.\n void previous.then(release, release)\n void current.then(() => { if (this.queues.get(key) === current) this.queues.delete(key) })\n }\n }\n\n private async create(key: string, serverId: string, workspace: string, previous?: S, signal?: AbortSignal): Promise<S> {\n if (previous) { this.sessions.delete(key); await previous.stop() }\n throwIfAborted(signal)\n const session = await this.factory(serverId, workspace, signal)\n try { await session.start(signal) } catch (error) { await session.stop(); throw error }\n if (this.disposing) { await session.stop(); throw new Error('server pool is disposing') }\n this.sessions.set(key, session)\n return session\n }\n}\n\nexport function keyOf(serverId: string, workspace: string): string { return `${serverId}\\u0000${workspace}` }\n","export type StandardOperation = 'goToDefinition' | 'findReferences' | 'goToImplementation' | 'hover'\n\nexport function supportsOperation(capabilities: Record<string, unknown>, operation: StandardOperation): boolean {\n if (operation === 'goToDefinition') return capabilities.definitionProvider === true || isProvider(capabilities.definitionProvider)\n if (operation === 'findReferences') return capabilities.referencesProvider === true || isProvider(capabilities.referencesProvider)\n if (operation === 'goToImplementation') return capabilities.implementationProvider === true || isProvider(capabilities.implementationProvider)\n return capabilities.hoverProvider === true || isProvider(capabilities.hoverProvider)\n}\n\nfunction isProvider(value: unknown): boolean {\n return typeof value === 'object' && value !== null || value === true\n}\n\nexport function defaultServerRequest(method: string, params: unknown): unknown {\n if (method === 'workspace/configuration') {\n return Array.isArray(params) ? params.map(() => null) : []\n }\n if (method === 'window/workDoneProgress/create' || method === 'client/registerCapability' || method === 'client/unregisterCapability') return null\n if (method === 'workspace/applyEdit') return { applied: false, failureReason: 'read-only provider' }\n return null\n}\n","import type { LspRange } from '../service.js'\n\nexport interface NormalizedHover {\n contents: string\n range?: LspRange\n}\n\nexport function normalizeHover(value: unknown): NormalizedHover | null | undefined {\n if (value === null || value === undefined) return null\n if (typeof value !== 'object' || value === null) return undefined\n const record = value as { contents?: unknown; range?: unknown }\n const contents = normalizeContents(record.contents)\n if (contents === undefined) return undefined\n return { contents, ...(isRange(record.range) ? { range: record.range } : {}) }\n}\n\nfunction normalizeContents(value: unknown): string | undefined {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n const parts = value.map((item) => typeof item === 'string' ? item : isRecord(item) && typeof item.value === 'string' ? item.value : undefined)\n return parts.every((item): item is string => item !== undefined) ? parts.join('\\n') : undefined\n }\n if (isRecord(value) && typeof value.value === 'string') return value.value\n return undefined\n}\n\nfunction isRange(value: unknown): value is LspRange {\n return isRecord(value) && isPosition(value.start) && isPosition(value.end)\n}\n\nfunction isPosition(value: unknown): boolean {\n return isRecord(value) && Number.isInteger(value.line) && Number.isInteger(value.character) && value.line >= 0 && value.character >= 0\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { LspPosition, LspRange } from '../service.js'\n\nexport interface NormalizedLocation {\n uri: string\n range: LspRange\n}\n\nexport function normalizeLocation(value: unknown): NormalizedLocation | undefined {\n if (isRecord(value) && typeof value.targetUri === 'string' && isRange(value.targetSelectionRange)) return { uri: value.targetUri, range: value.targetSelectionRange }\n if (!isRecord(value) || typeof value.uri !== 'string' || !isRange(value.range)) return undefined\n return { uri: value.uri, range: value.range }\n}\n\nexport function normalizeLocations(value: unknown): NormalizedLocation[] {\n const values = Array.isArray(value) ? value : value === null || value === undefined ? [] : [value]\n return values.map(normalizeLocation).filter((location): location is NormalizedLocation => location !== undefined)\n}\n\nfunction isRange(value: unknown): value is LspRange {\n return isRecord(value) && isPosition(value.start) && isPosition(value.end)\n}\n\nfunction isPosition(value: unknown): value is LspPosition {\n return isRecord(value) && Number.isInteger(value.line) && Number.isInteger(value.character) && value.line >= 0 && value.character >= 0\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { LspRange, NormalizedDiagnostic } from '../service.js'\n\nexport function normalizeDiagnostic(value: unknown, server: string, fallbackUri: string): NormalizedDiagnostic | undefined {\n if (!isRecord(value) || !isRange(value.range) || typeof value.message !== 'string') return undefined\n const uri = typeof value.uri === 'string' ? value.uri : fallbackUri\n const severity = typeof value.severity === 'number' && value.severity >= 1 && value.severity <= 4 ? value.severity as 1 | 2 | 3 | 4 : undefined\n const code = typeof value.code === 'string' || typeof value.code === 'number' ? value.code : undefined\n return { server, uri, range: value.range, message: value.message, ...(severity === undefined ? {} : { severity }), ...(code === undefined ? {} : { code }), ...(typeof value.source === 'string' ? { source: value.source } : {}) }\n}\n\nexport function normalizeDiagnostics(value: unknown, server: string, fallbackUri: string): NormalizedDiagnostic[] {\n const values = Array.isArray(value) ? value : []\n return values.map((item) => normalizeDiagnostic(item, server, fallbackUri)).filter((item): item is NormalizedDiagnostic => item !== undefined)\n}\n\nfunction isRange(value: unknown): value is LspRange {\n return isRecord(value) && isPosition(value.start) && isPosition(value.end)\n}\n\nfunction isPosition(value: unknown): boolean {\n return isRecord(value) && Number.isInteger(value.line) && Number.isInteger(value.character) && value.line >= 0 && value.character >= 0\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { NormalizedCompletionItem } from '../service.js'\n\nexport function normalizeCompletionItem(value: unknown, server: string): NormalizedCompletionItem | undefined {\n if (!isRecord(value) || typeof value.label !== 'string' || value.label.length === 0) return undefined\n return {\n server,\n label: value.label,\n ...(typeof value.kind === 'number' ? { kind: value.kind } : {}),\n ...(typeof value.detail === 'string' ? { detail: value.detail } : {}),\n ...(typeof value.documentation === 'string' ? { documentation: value.documentation } : {}),\n ...(typeof value.sortText === 'string' ? { sortText: value.sortText } : {}),\n ...(typeof value.filterText === 'string' ? { filterText: value.filterText } : {}),\n ...(typeof value.insertText === 'string' ? { insertText: value.insertText } : {}),\n ...(typeof value.insertTextFormat === 'number' ? { insertTextFormat: value.insertTextFormat } : {}),\n ...(typeof value.deprecated === 'boolean' ? { deprecated: value.deprecated } : {}),\n }\n}\n\nexport function normalizeCompletion(value: unknown, server: string): NormalizedCompletionItem[] {\n const items = isRecord(value) && Array.isArray(value.items) ? value.items : Array.isArray(value) ? value : []\n return items.map((item) => normalizeCompletionItem(item, server)).filter((item): item is NormalizedCompletionItem => item !== undefined)\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { NormalizedHover } from '../protocol/normalize-hover.js'\nimport type { LspRange } from '../service.js'\n\nexport interface ServerHover extends NormalizedHover {\n server: string\n}\n\nexport function mergeHover(primary: ServerHover | null | undefined, auxiliary: ServerHover | null | undefined): ServerHover | null {\n if (!primary && !auxiliary) return null\n if (!primary) return auxiliary ? { ...auxiliary } : null\n if (!auxiliary) return { ...primary }\n const contents = [primary.contents, auxiliary.contents].filter((value, index, values) => values.indexOf(value) === index)\n const range = sameRange(primary.range, auxiliary.range) ? primary.range : undefined\n return { server: primary.server, contents: contents.join('\\n\\n'), ...(range ? { range } : {}) }\n}\n\nfunction sameRange(left: LspRange | undefined, right: LspRange | undefined): boolean {\n return JSON.stringify(left) === JSON.stringify(right)\n}\n","import type { LspProviderQuery, LspQueryResult } from '@deepseek-ai/dsh-lsp'\nimport type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess'\nimport type { ResolvedConfig, ServerId } from '../config.js'\nimport { SERVER_IDS } from '../config.js'\nimport { readSource, type HostFileSystem, type HostSource } from '../host/dsh.js'\nimport { classifyFile } from '../routing/classifier.js'\nimport { routeFor, type Route } from '../routing/route-table.js'\nimport { hasTailwindCandidate } from '../routing/tailwind-candidate.js'\nimport { resolveLaunch, initializationOptions, serverConfiguration } from '../servers/launch.js'\nimport { ServerSession } from './server-session.js'\nimport { ServerPool } from './server-pool.js'\nimport { throwIfAborted, withAbort } from './cancellation.js'\nimport { WebstackLspError } from '../errors.js'\nimport { supportsOperation } from '../protocol/capabilities.js'\nimport { normalizeHover } from '../protocol/normalize-hover.js'\nimport { normalizeLocations } from '../protocol/normalize-location.js'\nimport { normalizeDiagnostics } from '../protocol/normalize-diagnostic.js'\nimport { normalizeCompletion } from '../protocol/normalize-completion.js'\nimport { mergeHover } from '../merge/hover.js'\nimport { mergeDiagnostics } from '../merge/diagnostics.js'\nimport { mergeCompletions } from '../merge/completion.js'\nimport type { CompletionRequest, CompletionResult, DiagnosticsRequest, DiagnosticsResult, LspPosition, WebstackLspStatus } from '../service.js'\nimport type { JsonRpcConnection } from './connection.js'\n\nexport type HostSubprocess = Pick<SubprocessRuntime, 'spawn' | 'resolveExecutable'>\nconst methods = { hover: 'textDocument/hover', goToDefinition: 'textDocument/definition', findReferences: 'textDocument/references', goToImplementation: 'textDocument/implementation' } as const\nconst clientCapabilities = {\n general: { positionEncodings: ['utf-16'] },\n workspace: { configuration: true, workspaceFolders: true, applyEdit: false },\n textDocument: {\n synchronization: { dynamicRegistration: false, didSave: false },\n hover: { contentFormat: ['markdown', 'plaintext'] },\n completion: { completionItem: { snippetSupport: true, documentationFormat: ['markdown', 'plaintext'] } },\n publishDiagnostics: { versionSupport: true }, diagnostic: {},\n },\n}\n\nexport class WebstackLspRuntime {\n private readonly pool: ServerPool<ServerSession>\n private readonly workspaces = new Map<string, HostSource>()\n private readonly lifetime = new AbortController()\n private readonly live = new Map<ServerSession, ServerId>()\n private readonly starts = new Map<string, number>()\n private readonly restarts = new Map<ServerId, number>()\n constructor(private readonly config: ResolvedConfig, private readonly fs: HostFileSystem, private readonly subprocess: HostSubprocess) {\n this.pool = new ServerPool(async (rawId, key, signal) => {\n const id = rawId as ServerId, source = this.workspaces.get(key)!\n const spec = await resolveLaunch(id, config, source.workspace)\n let executable: string\n try { executable = await subprocess.resolveExecutable(spec.command, spec.env, signal) }\n catch { throwIfAborted(signal); throw new WebstackLspError('LSP_UNAVAILABLE', `${id} executable is unavailable; run dsh-lsp-webstack --json`) }\n const session = new ServerSession({\n spawn: () => subprocess.spawn({ argv: [executable, ...spec.args], cwd: source.workspace, env: spec.env, stdio: { stdin: 'pipe', stdout: 'pipe', stderr: { maxBytes: config.limits.maxStderrBytes } }, graceMs: config.timeouts.killGraceMs }),\n initialize: { processId: null, rootUri: source.workspaceUri, workspaceFolders: [{ uri: source.workspaceUri, name: 'workspace' }], capabilities: clientCapabilities, initializationOptions: initializationOptions(id, config) },\n configuration: serverConfiguration(id, config), maxMessageBytes: config.limits.maxMessageBytes,\n shutdown: { shutdownMs: config.timeouts.shutdownMs, killGraceMs: config.timeouts.killGraceMs },\n })\n const slot = `${id}\\u0000${key}`\n if (this.starts.has(slot)) this.restarts.set(id, (this.restarts.get(id) ?? 0) + 1)\n this.starts.set(slot, (this.starts.get(slot) ?? 0) + 1)\n for (const [old] of this.live) if (old.state === 'STOPPED' || old.state === 'FAILED') this.live.delete(old)\n this.live.set(session, id)\n return session\n })\n }\n\n async navigation(request: LspProviderQuery, signal?: AbortSignal): Promise<LspQueryResult> {\n const deadline = this.signal(request.operation === 'hover' ? this.config.timeouts.primaryHoverMs : this.config.timeouts.navigationMs, signal)\n const [source, route] = await this.prepare(request, deadline)\n this.validatePosition(source.text, request.position)\n const result = await this.document(route.primary.server, source, route.primary.languageId, deadline, async (session, connection) => {\n if (!supportsOperation(session.capabilities, request.operation)) throw new WebstackLspError('LSP_UNSUPPORTED_OPERATION', `${route.primary.server} does not support ${request.operation}`)\n return connection.request(methods[request.operation], { textDocument: { uri: source.uri }, position: request.position, ...(request.operation === 'findReferences' ? { context: { includeDeclaration: true } } : {}) }, deadline)\n })\n if (request.operation !== 'hover') return { kind: 'locations', locations: normalizeLocations(result), resolvedWorkspaceUri: source.workspaceUri }\n const primary = normalizeHover(result)\n if (primary === undefined) throw new WebstackLspError('LSP_MALFORMED_RESPONSE', 'invalid hover result')\n let auxiliary = null\n if (this.useTailwind(route, source, request.position)) {\n const auxSignal = this.signal(this.config.timeouts.auxiliaryHoverMs, signal)\n try {\n const value = await this.document('tailwind', source, route.auxiliary!.languageId, auxSignal, (_session, connection) => connection.request('textDocument/hover', { textDocument: { uri: source.uri }, position: request.position }, auxSignal))\n auxiliary = normalizeHover(value) ?? null\n } catch { throwIfAborted(signal); throwIfAborted(this.lifetime.signal) }\n }\n const hover = mergeHover(primary && { ...primary, server: route.primary.server }, auxiliary && { ...auxiliary, server: 'tailwind' })\n return { kind: 'hover', hover: hover ? { contents: hover.contents, ...(hover.range ? { range: hover.range } : {}) } : null }\n }\n\n async completion(request: CompletionRequest, signal?: AbortSignal): Promise<CompletionResult> {\n const deadline = this.signal(this.config.timeouts.completionMs, signal)\n const [source, route] = await this.prepare(request, deadline)\n this.validatePosition(source.text, request.position)\n const query = (id: ServerId, language: string) => this.document(id, source, language, deadline, (session, connection) => {\n if (!session.capabilities.completionProvider) throw new WebstackLspError('LSP_UNSUPPORTED_OPERATION', `${id} does not support completion`)\n return connection.request('textDocument/completion', { textDocument: { uri: source.uri }, position: request.position, context: { triggerKind: request.triggerKind ?? 1, ...(request.triggerCharacter ? { triggerCharacter: request.triggerCharacter } : {}) } }, deadline)\n }).then(value => {\n const prefix = source.text.split(/\\r?\\n/)[request.position.line]!.slice(0, request.position.character).match(/[\\w$:@/!\\[\\]-]+$/)?.[0]?.toLowerCase() ?? ''\n // Servers such as Tailwind return the whole catalog; the client must rank the typed prefix before applying a result cap.\n return normalizeCompletion(value, id).sort((a, b) => Number((b.filterText ?? b.label).toLowerCase().startsWith(prefix)) - Number((a.filterText ?? a.label).toLowerCase().startsWith(prefix)))\n })\n const primary = await query(route.primary.server, route.primary.languageId)\n let auxiliary: typeof primary = []\n if (this.useTailwind(route, source, request.position)) {\n try { auxiliary = await query('tailwind', route.auxiliary!.languageId) } catch { throwIfAborted(signal); throwIfAborted(this.lifetime.signal) }\n }\n return mergeCompletions([primary, auxiliary], { maxCompletions: Number.MAX_SAFE_INTEGER, maxResultChars: Number.MAX_SAFE_INTEGER })\n }\n\n async diagnostics(request: DiagnosticsRequest, signal?: AbortSignal): Promise<DiagnosticsResult> {\n const deadline = this.signal(this.config.timeouts.diagnosticsMs, signal)\n const [source, route] = await this.prepare(request, deadline)\n const selected = [route.primary, ...(route.auxiliary && this.config.tailwind.enabled ? [route.auxiliary] : [])].filter(item => this.config.servers[item.server].enabled && (!request.servers || request.servers.includes(item.server)))\n if (!selected.length) throw new WebstackLspError('LSP_UNAVAILABLE', 'no selected diagnostic server supports this file')\n const omittedServers: string[] = []\n const groups = await Promise.all(selected.map(async item => {\n try {\n const value = await this.document(item.server, source, item.languageId, deadline, async (session, connection, opened) => {\n if (session.capabilities.diagnosticProvider) {\n await opened()\n const report = await connection.request('textDocument/diagnostic', { textDocument: { uri: source.uri } }, deadline) as { items?: unknown }\n return report?.items ?? []\n }\n // Subscribe before didOpen; do not confuse a missing publication with a clean file.\n let remove = () => {}\n const published = new Promise<unknown>(resolve => {\n remove = connection.onNotification(message => {\n const p = message.params as { uri?: string; diagnostics?: unknown; version?: number } | undefined\n if (message.method === 'textDocument/publishDiagnostics' && p?.uri === source.uri && (p.version === undefined || p.version === 1)) resolve(p.diagnostics)\n })\n })\n try { await opened(); return await withAbort(published, deadline) } finally { remove() }\n }, true)\n return normalizeDiagnostics(value, item.server, source.uri).filter(d => !request.severity || request.severity === 'all' || d.severity === (request.severity === 'error' ? 1 : 2))\n } catch (error) {\n throwIfAborted(signal); throwIfAborted(this.lifetime.signal)\n if (item.server === route.primary.server || this.config.missingServerPolicy === 'error') throw error\n omittedServers.push(item.server)\n return []\n }\n }))\n return { ...mergeDiagnostics(groups, { maxDiagnostics: Number.MAX_SAFE_INTEGER, maxResultChars: Number.MAX_SAFE_INTEGER }), ...(omittedServers.length ? { omittedServers: omittedServers.sort() } : {}) }\n }\n\n async status(): Promise<WebstackLspStatus> {\n return { providerId: this.config.providerId, servers: await Promise.all(SERVER_IDS.map(async id => {\n const config = this.config.servers[id]\n let available = false\n try {\n const launch = await resolveLaunch(id, this.config, '.')\n await this.subprocess.resolveExecutable(launch.command, launch.env, this.signal(5000))\n available = true\n } catch {}\n return { id, enabled: config.enabled && (id !== 'tailwind' || this.config.tailwind.enabled), available, source: config.mode, liveWorkspaces: [...this.live].filter(([s, server]) => server === id && s.isUsable()).length, restarts: this.restarts.get(id) ?? 0 }\n })) }\n }\n\n async dispose(): Promise<void> { this.lifetime.abort(); await this.pool.disposeAll(); this.workspaces.clear(); this.live.clear() }\n\n private signal(ms: number, signal?: AbortSignal): AbortSignal { return AbortSignal.any([this.lifetime.signal, AbortSignal.timeout(ms), ...(signal ? [signal] : [])]) }\n private async prepare(request: { workspaceRoot: string; filePath: string }, signal: AbortSignal): Promise<[HostSource, Route]> {\n throwIfAborted(signal)\n const file = classifyFile(request.filePath, this.config.routing.bladeSuffixes)\n if (!file) throw new WebstackLspError('LSP_UNAVAILABLE', 'unsupported file extension')\n const source = await readSource(this.fs, request.workspaceRoot, request.filePath, this.config.limits.maxDocumentBytes, signal).catch(error => { throwIfAborted(signal); throw error })\n this.workspaces.set(source.key, { ...source, text: '' })\n return [source, routeFor(file)]\n }\n private validatePosition(text: string, position: LspPosition): void {\n const line = text.split(/\\r?\\n/)[position.line]\n if (!Number.isSafeInteger(position.line) || !Number.isSafeInteger(position.character) || position.line < 0 || position.character < 0 || line === undefined || position.character > line.length) throw new RangeError('position is outside document (zero-based UTF-16 required)')\n }\n private useTailwind(route: Route, source: HostSource, position: LspPosition): boolean {\n return !!route.auxiliary && this.config.tailwind.enabled && this.config.servers.tailwind.enabled && (route.primary.languageId === 'blade' || this.config.routing.tailwindLanguages.includes(route.primary.languageId) || route.primary.languageId === 'css') && (this.config.tailwind.queryStrategy === 'always' || hasTailwindCandidate(source.text, position.line, this.config.tailwind.classRegex, position.character, this.config.tailwind.classAttributes))\n }\n private async document<T>(id: ServerId, source: HostSource, language: string, signal: AbortSignal, task: (session: ServerSession, connection: JsonRpcConnection, open: () => Promise<void>) => Promise<T>, manualOpen = false): Promise<T> {\n if (!this.config.servers[id].enabled) throw new WebstackLspError('LSP_UNAVAILABLE', `${id} is disabled`)\n return this.pool.runWithRetry(id, source.key, session => session.run(async connection => {\n let opened = false\n const open = async () => { opened = true; await connection.notify('textDocument/didOpen', { textDocument: { uri: source.uri, languageId: language, version: 1, text: source.text } }) }\n try { if (!manualOpen) await open(); return await task(session, connection, open) }\n finally { if (opened && connection.isOpen) await connection.notify('textDocument/didClose', { textDocument: { uri: source.uri } }).catch(() => {}) }\n }, signal), signal, manualOpen ? session => {\n // Push notifications can omit document versions. A delayed didClose clear\n // from a previous operation is indistinguishable from a fresh clean result.\n // Use a fresh process for push diagnostics; pull responses have request IDs.\n return !!session.capabilities.diagnosticProvider\n } : undefined)\n }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { LspProviderId } from '@deepseek-ai/dsh-lsp'\nimport type { LspProvider, LspProviderQuery, LspQueryResult } from '@deepseek-ai/dsh-lsp'\nimport type { Config as PluginConfig, ResolvedConfig } from './config.js'\nimport { resolveConfig } from './config.js'\nimport type { WebstackLspService } from './service.js'\nimport { createWebstackLspService } from './service.js'\nimport { WebstackLspRuntime } from './runtime/webstack-runtime.js'\nimport type {} from '@deepseek-ai/dsh-fs'\nimport type {} from '@deepseek-ai/dsh-subprocess'\n\nexport type { LspProvider, LspProviderQuery, LspQueryResult }\nexport type Config = PluginConfig\nexport const name = 'lsp-webstack-provider'\nexport const inject = ['fs', 'lsp', 'subprocess']\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { webstackLsp: WebstackLspService }\n}\n\nexport const OUTER_EXTENSION_MAP = {\n '.php': 'php', '.ts': 'typescript', '.tsx': 'typescriptreact', '.mts': 'typescript', '.cts': 'typescript',\n '.js': 'javascript', '.jsx': 'javascriptreact', '.mjs': 'javascript', '.cjs': 'javascript',\n '.svelte': 'svelte', '.html': 'html', '.htm': 'html', '.css': 'css', '.pcss': 'css',\n} as const\n\nexport interface CompositeRuntime {\n navigation(request: LspProviderQuery, signal?: AbortSignal): Promise<LspQueryResult>\n dispose?(): Promise<void>\n}\n\nexport function createCompositeProvider(runtime: CompositeRuntime, config: Pick<ResolvedConfig, 'providerId'> = { providerId: 'webstack' }): LspProvider {\n return { id: LspProviderId(config.providerId), extensionToLanguage: { ...OUTER_EXTENSION_MAP }, query: (request, signal) => runtime.navigation(request, signal) }\n}\n\nexport async function apply(ctx: Context, config: unknown = {}): Promise<void> {\n const resolved = resolveConfig(config)\n const runtime = new WebstackLspRuntime(resolved, ctx.fs, ctx.subprocess)\n await ctx.effect(async function* () {\n yield () => runtime.dispose()\n if (resolved.missingServerPolicy === 'error') {\n const missing = (await runtime.status()).servers.filter(server => server.enabled && !server.available)\n if (missing.length) throw new Error(`unavailable language servers: ${missing.map(server => server.id).join(', ')}`)\n }\n yield ctx.lsp.registerProvider(createCompositeProvider(runtime, resolved))\n yield ctx.provide('webstackLsp', createWebstackLspService(runtime))\n }, 'webstack LSP provider')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","names":["CLASSIFIERS: ReadonlyArray<{ suffix: string; kind: FileKind }>","ROUTES: Record<ClassifiedFile['kind'], Route>","maxMessageBytes: number","messages: unknown[]","text: string","length: number | undefined","input: Readable","output: Writable","messages: unknown[]","isRecord","options: ServerSessionOptions","factory: SessionFactory<S>","release!: () => void","isRange","isRecord","isPosition","isRecord","isRange","isPosition","isRecord","config: ResolvedConfig","fs: HostFileSystem","subprocess: HostSubprocess","executable: string","auxiliary: typeof primary","omittedServers: string[]"],"sources":["../src/runtime/cancellation.ts","../src/host/dsh.ts","../src/routing/classifier.ts","../src/routing/route-table.ts","../src/routing/tailwind-candidate.ts","../src/protocol/initialize.ts","../src/runtime/framing.ts","../src/runtime/connection.ts","../src/runtime/server-session.ts","../src/runtime/server-pool.ts","../src/protocol/capabilities.ts","../src/protocol/normalize-hover.ts","../src/protocol/normalize-location.ts","../src/protocol/normalize-diagnostic.ts","../src/protocol/normalize-completion.ts","../src/merge/hover.ts","../src/runtime/webstack-runtime.ts","../src/provider.ts"],"sourcesContent":["export function abortError(): Error {\n const error = new Error('The operation was aborted')\n error.name = 'AbortError'\n return error\n}\n\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortError()\n}\n\nexport function onAbort(signal: AbortSignal | undefined, callback: () => void): () => void {\n if (!signal) return () => {}\n if (signal.aborted) {\n callback()\n return () => {}\n }\n signal.addEventListener('abort', callback, { once: true })\n return () => signal.removeEventListener('abort', callback)\n}\n\nexport async function withAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n throwIfAborted(signal)\n if (!signal) return promise\n return new Promise<T>((resolve, reject) => {\n const remove = onAbort(signal, () => reject(abortError()))\n promise.then((value) => { remove(); resolve(value) }, (error: unknown) => { remove(); reject(error) })\n })\n}\n","import type { FileSystem } from '@deepseek-ai/dsh-fs'\nimport { WebstackLspError } from '../errors.js'\nimport { throwIfAborted } from '../runtime/cancellation.js'\n\nexport type HostFileSystem = Pick<FileSystem, 'resolve' | 'stat' | 'processPath' | 'fileUrl' | 'contains' | 'streamText'>\nexport interface HostSource { workspace: string; workspaceUri: string; key: string; uri: string; text: string }\n\nexport async function readSource(fs: HostFileSystem, workspaceRoot: string, filePath: string, maxBytes: number, signal?: AbortSignal): Promise<HostSource> {\n if (!workspaceRoot?.trim() || !filePath?.trim()) throw new WebstackLspError('LSP_WORKSPACE_REQUIRED', 'workspaceRoot and filePath are required')\n throwIfAborted(signal)\n const options = signal ? { signal } : {}\n const root = await fs.resolve(workspaceRoot, options)\n if ((await fs.stat(root, signal))?.type !== 'directory') throw new Error('workspace root is not a directory')\n const workspace = fs.processPath(root)\n const target = await fs.resolve(filePath, { cwd: workspace, ...options })\n if (!fs.contains(root, target)) throw new Error('source is outside workspace')\n if ((await fs.stat(target, signal))?.type !== 'file') throw new Error('source is not a regular file')\n let text = '', bytes = 0\n for await (const chunk of await fs.streamText(target, signal)) {\n throwIfAborted(signal)\n bytes += Buffer.byteLength(chunk)\n if (bytes > maxBytes) throw new Error('source exceeds document limit')\n text += chunk\n }\n throwIfAborted(signal)\n return { workspace, workspaceUri: fs.fileUrl(root), key: root.targetKey, uri: fs.fileUrl(target), text }\n}\n","export type FileKind = 'blade' | 'php' | 'typescript' | 'typescriptreact' | 'javascript' | 'javascriptreact' | 'svelte' | 'html' | 'css'\n\nexport interface ClassifiedFile {\n path: string\n basename: string\n suffix: string\n kind: FileKind\n}\n\nconst CLASSIFIERS: ReadonlyArray<{ suffix: string; kind: FileKind }> = [\n { suffix: '.blade.php', kind: 'blade' },\n { suffix: '.typescriptreact', kind: 'typescriptreact' },\n { suffix: '.javascriptreact', kind: 'javascriptreact' },\n { suffix: '.tsx', kind: 'typescriptreact' },\n { suffix: '.jsx', kind: 'javascriptreact' },\n { suffix: '.mts', kind: 'typescript' },\n { suffix: '.cts', kind: 'typescript' },\n { suffix: '.mjs', kind: 'javascript' },\n { suffix: '.cjs', kind: 'javascript' },\n { suffix: '.svelte', kind: 'svelte' },\n { suffix: '.html', kind: 'html' },\n { suffix: '.htm', kind: 'html' },\n { suffix: '.php', kind: 'php' },\n { suffix: '.ts', kind: 'typescript' },\n { suffix: '.js', kind: 'javascript' },\n { suffix: '.css', kind: 'css' },\n { suffix: '.pcss', kind: 'css' },\n]\n\nexport function classifyFile(filePath: string, bladeSuffixes: string[] = ['.blade.php']): ClassifiedFile | undefined {\n const normalizedPath = filePath.replaceAll('\\\\', '/')\n const basename = normalizedPath.slice(normalizedPath.lastIndexOf('/') + 1).toLowerCase()\n if (!basename || basename === '.' || basename === '..' || basename.startsWith('.')) return undefined\n const customBlade = bladeSuffixes.map((suffix) => suffix.toLowerCase()).sort((left, right) => right.length - left.length)\n const classifiers = [...customBlade.map((suffix) => ({ suffix, kind: 'blade' as const })), ...CLASSIFIERS.filter((item) => !customBlade.includes(item.suffix))]\n const match = classifiers.find((item) => basename.endsWith(item.suffix))\n if (!match) return undefined\n return { path: normalizedPath, basename, suffix: match.suffix, kind: match.kind }\n}\n\n/** Return the supported suffixes, including configured Blade suffixes. */\nexport function supportedFileSuffixes(bladeSuffixes: string[] = ['.blade.php']): string[] {\n return [...new Set([...bladeSuffixes.map(suffix => suffix.toLowerCase()), ...CLASSIFIERS.map(item => item.suffix)])]\n}\n","import type { ServerId } from '../config.js'\nimport type { ClassifiedFile } from './classifier.js'\n\nexport interface Route {\n primary: { server: ServerId; languageId: string }\n auxiliary?: { server: 'tailwind'; languageId: string }\n}\n\nconst ROUTES: Record<ClassifiedFile['kind'], Route> = {\n blade: { primary: { server: 'phpantom', languageId: 'blade' }, auxiliary: { server: 'tailwind', languageId: 'html' } },\n php: { primary: { server: 'phpantom', languageId: 'php' } },\n typescript: { primary: { server: 'typescript', languageId: 'typescript' }, auxiliary: { server: 'tailwind', languageId: 'typescript' } },\n typescriptreact: { primary: { server: 'typescript', languageId: 'typescriptreact' }, auxiliary: { server: 'tailwind', languageId: 'typescriptreact' } },\n javascript: { primary: { server: 'typescript', languageId: 'javascript' }, auxiliary: { server: 'tailwind', languageId: 'javascript' } },\n javascriptreact: { primary: { server: 'typescript', languageId: 'javascriptreact' }, auxiliary: { server: 'tailwind', languageId: 'javascriptreact' } },\n svelte: { primary: { server: 'svelte', languageId: 'svelte' }, auxiliary: { server: 'tailwind', languageId: 'svelte' } },\n html: { primary: { server: 'html', languageId: 'html' }, auxiliary: { server: 'tailwind', languageId: 'html' } },\n css: { primary: { server: 'css', languageId: 'css' }, auxiliary: { server: 'tailwind', languageId: 'css' } },\n}\n\nexport function routeFor(file: ClassifiedFile): Route {\n const route = ROUTES[file.kind]\n return { primary: { ...route.primary }, ...(route.auxiliary ? { auxiliary: { ...route.auxiliary } } : {}) }\n}\n","const DEFAULT_PATTERNS = [\n /\\bclass\\s*=\\s*[\"'][^\"']*$/i,\n /\\bclassName\\s*=\\s*[\"'][^\"']*$/i,\n /\\bclass:list\\s*=\\s*[\"'][^\"']*$/i,\n /@apply\\s+[\\w-]*$/i,\n /\\b(?:clsx|cva)\\s*\\([^)]*[\"'][^\"']*$/i,\n]\n\nexport function hasTailwindCandidate(source: string, line: number, classRegex: Array<string | [string, string]> = [], character?: number, classAttributes: string[] = ['class', 'className', 'class:list']): boolean {\n const lines = source.split(/\\r?\\n/)\n const context = [...lines.slice(Math.max(0, line - 2), line), (lines[line] ?? '').slice(0, character)].join('\\n')\n if (classAttributes.some(attribute => {\n const index = context.lastIndexOf(attribute + '=')\n return index >= 0 && /^[\\\"'][^\\\"']*$/.test(context.slice(index + attribute.length + 1).trimStart())\n })) return true\n const configured = classRegex.flatMap((item) => Array.isArray(item) ? item : [item]).map((pattern) => new RegExp(pattern))\n return [...DEFAULT_PATTERNS, ...configured].some((pattern) => pattern.test(context))\n}\n","import type { InitializeParams, InitializeResult } from './types.js'\nimport type { JsonRpcConnection } from '../runtime/connection.js'\nimport { throwIfAborted } from '../runtime/cancellation.js'\n\nexport async function initializeServer(connection: JsonRpcConnection, params: InitializeParams, signal?: AbortSignal): Promise<InitializeResult> {\n throwIfAborted(signal)\n const value = await connection.request('initialize', params, signal)\n if (!isInitializeResult(value)) throw new Error('malformed initialize response')\n await connection.notify('initialized', {})\n return value\n}\n\nfunction isInitializeResult(value: unknown): value is InitializeResult {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && typeof (value as { capabilities?: unknown }).capabilities === 'object' && (value as { capabilities?: unknown }).capabilities !== null\n}\n","import { TextDecoder } from 'node:util'\n\nexport class JsonRpcFrameError extends Error {\n readonly code = 'LSP_MALFORMED_RESPONSE'\n\n constructor(message: string) {\n super(message)\n this.name = 'JsonRpcFrameError'\n }\n}\n\nexport class ContentLengthDecoder {\n private buffer = Buffer.alloc(0)\n private readonly decoder = new TextDecoder('utf-8', { fatal: true })\n\n constructor(private readonly maxMessageBytes: number) {\n if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0) throw new RangeError('maxMessageBytes must be positive')\n }\n\n feed(chunk: Uint8Array): unknown[] {\n this.buffer = Buffer.concat([this.buffer, Buffer.from(chunk)])\n const messages: unknown[] = []\n while (true) {\n const headerEnd = this.buffer.indexOf(Buffer.from('\\r\\n\\r\\n'))\n if (headerEnd < 0) {\n if (this.buffer.length > 8192) throw new JsonRpcFrameError('header exceeds limit')\n break\n }\n const header = this.buffer.subarray(0, headerEnd).toString('ascii')\n const length = this.parseLength(header)\n const bodyStart = headerEnd + 4\n if (length > this.maxMessageBytes) throw new JsonRpcFrameError('message exceeds configured limit')\n if (this.buffer.length < bodyStart + length) break\n const body = this.buffer.subarray(bodyStart, bodyStart + length)\n this.buffer = this.buffer.subarray(bodyStart + length)\n let text: string\n try {\n text = this.decoder.decode(body)\n } catch {\n throw new JsonRpcFrameError('message is not valid UTF-8')\n }\n try {\n messages.push(JSON.parse(text) as unknown)\n } catch {\n throw new JsonRpcFrameError('message body is not valid JSON')\n }\n }\n return messages\n }\n\n end(): void {\n if (this.buffer.length > 0) throw new JsonRpcFrameError('incomplete JSON-RPC frame')\n }\n\n private parseLength(header: string): number {\n const lines = header.split('\\r\\n')\n let length: number | undefined\n for (const line of lines) {\n const separator = line.indexOf(':')\n if (separator < 1) throw new JsonRpcFrameError('malformed header')\n const key = line.slice(0, separator).toLowerCase()\n const value = line.slice(separator + 1).trim()\n if (key === 'content-length') {\n if (length !== undefined || !/^\\d+$/.test(value)) throw new JsonRpcFrameError('invalid Content-Length')\n length = Number(value)\n }\n }\n if (length === undefined || !Number.isSafeInteger(length)) throw new JsonRpcFrameError('Content-Length is required')\n return length\n }\n}\n\nexport function encodeJsonRpc(message: object): Buffer {\n const body = Buffer.from(JSON.stringify(message), 'utf8')\n return Buffer.concat([Buffer.from(`Content-Length: ${body.length}\\r\\n\\r\\n`, 'ascii'), body])\n}\n","import type { Readable, Writable } from 'node:stream'\nimport { abortError, onAbort, throwIfAborted } from './cancellation.js'\nimport { ContentLengthDecoder, encodeJsonRpc, JsonRpcFrameError } from './framing.js'\nimport type { JsonRpcConnectionOptions, JsonRpcId, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse } from '../protocol/types.js'\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (error: unknown) => void\n method: string\n}\n\nexport class JsonRpcConnection {\n private readonly decoder: ContentLengthDecoder\n private readonly pending = new Map<JsonRpcId, PendingRequest>()\n private readonly notificationListeners = new Set<(notification: JsonRpcNotification) => void>()\n private nextId = 1\n private closed = false\n private requestHandler: NonNullable<JsonRpcConnectionOptions['onServerRequest']>\n\n constructor(private readonly input: Readable, private readonly output: Writable, options: JsonRpcConnectionOptions) {\n this.decoder = new ContentLengthDecoder(options.maxMessageBytes)\n this.requestHandler = options.onServerRequest ?? (() => null)\n if (options.onNotification) this.notificationListeners.add(options.onNotification)\n input.on('data', (chunk: Buffer) => this.receive(chunk))\n input.once('end', () => this.close(new Error('LSP process closed stdout')))\n input.once('error', (error) => this.close(error))\n output.on('error', (error) => this.close(error))\n }\n\n get isOpen(): boolean { return !this.closed }\n\n onNotification(listener: (notification: JsonRpcNotification) => void): () => void {\n this.notificationListeners.add(listener)\n return () => this.notificationListeners.delete(listener)\n }\n\n setRequestHandler(handler: NonNullable<JsonRpcConnectionOptions['onServerRequest']>): void {\n this.requestHandler = handler\n }\n\n async request(method: string, params?: unknown, signal?: AbortSignal): Promise<unknown> {\n throwIfAborted(signal)\n if (this.closed) throw new Error('connection is closed')\n const id = this.nextId++\n const promise = new Promise<unknown>((resolve, reject) => this.pending.set(id, { resolve, reject, method }))\n void promise.catch(() => {})\n const remove = onAbort(signal, () => {\n void this.notify('$/cancelRequest', { id }).catch(() => {})\n this.pending.get(id)?.reject(abortError())\n this.pending.delete(id)\n })\n try {\n void this.write({ jsonrpc: '2.0', id, method, ...(params === undefined ? {} : { params }) }).catch(error => this.close(error))\n return await promise\n } finally {\n remove()\n this.pending.delete(id)\n }\n }\n\n async notify(method: string, params?: unknown): Promise<void> {\n if (this.closed) throw new Error('connection is closed')\n await this.write({ jsonrpc: '2.0', method, ...(params === undefined ? {} : { params }) })\n }\n\n close(reason = new Error('connection closed')): void {\n if (this.closed) return\n this.closed = true\n for (const pending of this.pending.values()) pending.reject(reason)\n this.pending.clear()\n }\n\n private receive(chunk: Buffer): void {\n if (this.closed) return\n let messages: unknown[]\n try {\n messages = this.decoder.feed(chunk)\n } catch (error) {\n this.close(error instanceof Error ? error : new JsonRpcFrameError('invalid frame'))\n return\n }\n for (const message of messages) this.dispatch(message)\n }\n\n private dispatch(value: unknown): void {\n if (!isRecord(value) || value.jsonrpc !== '2.0') return this.close(new JsonRpcFrameError('invalid JSON-RPC message'))\n if ('method' in value && typeof value.method === 'string') {\n if ('id' in value) {\n const request = value as unknown as JsonRpcRequest\n Promise.resolve().then(() => this.requestHandler(request.method, request.params)).then(\n (result) => this.write({ jsonrpc: '2.0', id: request.id, result }),\n (error: unknown) => this.write({ jsonrpc: '2.0', id: request.id, error: { code: -32603, message: error instanceof Error ? error.message : 'server request failed' } }),\n ).catch(() => {})\n } else {\n for (const listener of this.notificationListeners) listener(value as unknown as JsonRpcNotification)\n }\n return\n }\n if ('id' in value) {\n const response = value as unknown as JsonRpcResponse\n const pending = this.pending.get(response.id)\n if (!pending) return\n if (response.error) pending.reject(new Error(`${response.error.code}: ${response.error.message}`))\n else pending.resolve(response.result)\n this.pending.delete(response.id)\n }\n }\n\n private write(message: JsonRpcMessage): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.output.write(encodeJsonRpc(message), (error?: Error | null) => error ? reject(error) : resolve())\n })\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { SubprocessHandle } from '@deepseek-ai/dsh-subprocess'\nimport type { InitializeParams, InitializeResult } from '../protocol/types.js'\nimport { initializeServer } from '../protocol/initialize.js'\nimport { JsonRpcConnection } from './connection.js'\nimport { withAbort, throwIfAborted } from './cancellation.js'\n\nexport type SessionState = 'NEW' | 'STARTING' | 'READY' | 'STOPPING' | 'STOPPED' | 'FAILED'\nexport interface ServerSessionOptions {\n spawn(): SubprocessHandle\n initialize: InitializeParams\n configuration: unknown\n maxMessageBytes: number\n shutdown: { shutdownMs: number; killGraceMs: number }\n}\n\nexport class ServerSession {\n state: SessionState = 'NEW'\n capabilities: Record<string, unknown> = {}\n private child?: SubprocessHandle\n private connection?: JsonRpcConnection\n private stopping?: Promise<void>\n private readonly lifetime = new AbortController()\n constructor(private readonly options: ServerSessionOptions) {}\n\n async start(signal?: AbortSignal): Promise<InitializeResult> {\n throwIfAborted(signal)\n this.state = 'STARTING'\n try {\n const child = this.options.spawn()\n this.child = child\n // Observe failed spawn even when stdio could not be allocated.\n void child.done.catch(() => {})\n if (!child.stdout || !child.stdin) throw new Error('server stdio is unavailable')\n const connection = new JsonRpcConnection(child.stdout, child.stdin, {\n maxMessageBytes: this.options.maxMessageBytes,\n onServerRequest: (method, params) => this.answer(method, params),\n })\n this.connection = connection\n void child.done.then(() => connection.close(new Error('LSP process exited')), error => connection.close(error instanceof Error ? error : new Error('LSP spawn failed'))).then(() => {\n if (this.state !== 'STOPPING' && this.state !== 'STOPPED') this.state = 'FAILED'\n })\n const result = await initializeServer(connection, this.options.initialize, this.signal(signal))\n if (result.capabilities.positionEncoding && result.capabilities.positionEncoding !== 'utf-16') throw new Error('server requires unsupported position encoding')\n const sync = result.capabilities.textDocumentSync\n if (sync === undefined || sync === 0 || (typeof sync === 'object' && sync !== null && !(sync as { openClose?: boolean }).openClose)) throw new Error('server does not support document open/close')\n this.capabilities = result.capabilities\n await connection.notify('workspace/didChangeConfiguration', { settings: this.options.configuration })\n throwIfAborted(this.signal(signal))\n this.state = 'READY'\n return result\n } catch (error) {\n this.state = 'FAILED'\n await this.stop()\n throw error\n }\n }\n\n get usable(): boolean { return this.state === 'READY' && !!this.connection?.isOpen }\n isUsable(): boolean { return this.usable }\n async run<T>(task: (connection: JsonRpcConnection) => Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!this.usable || !this.connection) throw new Error('session is not ready')\n try { return await withAbort(task(this.connection), this.signal(signal)) }\n catch (error) {\n // Stop cancelled work before the next queued request can reuse this process.\n if (signal?.aborted || !this.connection.isOpen) await this.stop()\n throw error\n }\n }\n\n stop(): Promise<void> {\n return this.stopping ??= this.teardown()\n }\n private async teardown(): Promise<void> {\n this.state = 'STOPPING'\n this.lifetime.abort()\n const child = this.child, connection = this.connection\n const timeout = AbortSignal.timeout(this.options.shutdown.shutdownMs)\n if (connection?.isOpen) {\n try { await connection.request('shutdown', null, timeout); await connection.notify('exit') } catch {}\n }\n connection?.close(new Error('session stopped'))\n if (child) {\n child.terminate()\n if (!await child.waitForExit(AbortSignal.timeout(this.options.shutdown.killGraceMs + 1000))) throw new Error('language server process tree did not exit within the cleanup deadline')\n }\n this.state = 'STOPPED'\n }\n private signal(signal?: AbortSignal): AbortSignal { return signal ? AbortSignal.any([signal, this.lifetime.signal]) : this.lifetime.signal }\n private answer(method: string, params: unknown): unknown {\n if (method === 'workspace/applyEdit') return { applied: false, failureReason: 'read-only provider' }\n if (method === 'workspace/workspaceFolders') return this.options.initialize.workspaceFolders ?? []\n if (method === 'workspace/configuration') {\n const items = (params as { items?: Array<{ section?: string }> } | undefined)?.items ?? []\n return items.map(item => {\n let value = this.options.configuration\n for (const key of item.section?.split('.') ?? []) {\n value = typeof value === 'object' && value !== null ? (value as Record<string, unknown>)[key] : undefined\n }\n return value ?? null\n })\n }\n return null\n }\n}\n","import { throwIfAborted, withAbort } from './cancellation.js'\n\nexport interface PoolSession {\n readonly state: string\n start(signal?: AbortSignal): Promise<unknown>\n stop(): Promise<void>\n isUsable(): boolean\n}\nexport type SessionFactory<S extends PoolSession> = (serverId: string, workspace: string, signal?: AbortSignal) => Promise<S>\n\nexport class ServerPool<S extends PoolSession> {\n private readonly sessions = new Map<string, S>()\n private readonly creation = new Map<string, Promise<S>>()\n private readonly queues = new Map<string, Promise<void>>()\n private disposing = false\n constructor(private readonly factory: SessionFactory<S>) {}\n\n async getOrCreate(serverId: string, workspace: string, signal?: AbortSignal): Promise<S> {\n throwIfAborted(signal)\n if (this.disposing) throw new Error('server pool is disposing')\n const key = keyOf(serverId, workspace)\n const existing = this.sessions.get(key)\n if (existing?.isUsable()) return existing\n const pending = this.creation.get(key)\n if (pending) return withAbort(pending, signal)\n const creation = this.create(key, serverId, workspace, existing, signal)\n this.creation.set(key, creation)\n try { return await creation }\n finally { if (this.creation.get(key) === creation) this.creation.delete(key) }\n }\n\n run<T>(serverId: string, workspace: string, task: (session: S) => Promise<T>, signal?: AbortSignal): Promise<T> {\n return this.serialize(keyOf(serverId, workspace), async () => task(await this.getOrCreate(serverId, workspace, signal)), signal)\n }\n\n runWithRetry<T>(serverId: string, workspace: string, task: (session: S) => Promise<T>, signal?: AbortSignal, canReuse?: (session: S) => boolean): Promise<T> {\n // Keep failure eviction and the retry inside the same queue slot. A later query\n // must never enter a replacement process before the failed query finishes cleanup.\n return this.serialize(keyOf(serverId, workspace), async () => {\n const existing = this.sessions.get(keyOf(serverId, workspace))\n // Replacement belongs to this queue slot, after earlier work has completed.\n if (existing?.isUsable() && canReuse && !canReuse(existing)) await this.evict(serverId, workspace)\n for (let attempt = 0; ; attempt++) {\n const session = await this.getOrCreate(serverId, workspace, signal)\n try { return await task(session) }\n catch (error) {\n throwIfAborted(signal)\n if (attempt > 0 || session.isUsable()) throw error\n if (this.sessions.get(keyOf(serverId, workspace)) === session) await this.evict(serverId, workspace)\n }\n }\n }, signal)\n }\n\n async evict(serverId: string, workspace: string): Promise<void> {\n const key = keyOf(serverId, workspace)\n const session = this.sessions.get(key)\n this.sessions.delete(key)\n if (session) await session.stop()\n }\n\n async disposeAll(): Promise<void> {\n this.disposing = true\n const results = await Promise.allSettled([...this.sessions.values()].map(session => session.stop()))\n this.sessions.clear()\n await Promise.all([...this.creation.values()].map(creation => creation.then(session => session.stop(), () => {})))\n this.creation.clear()\n const failures = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n if (failures.length) throw new AggregateError(failures.map(result => result.reason), 'language server cleanup failed')\n }\n\n get size(): number { return this.sessions.size }\n\n private async serialize<T>(key: string, task: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n const previous = this.queues.get(key) ?? Promise.resolve()\n let release!: () => void\n const current = new Promise<void>(resolve => { release = resolve })\n this.queues.set(key, current)\n try {\n await withAbort(previous, signal)\n throwIfAborted(signal)\n return await task()\n } finally {\n // A cancelled waiter cannot let its successor bypass still-running work.\n void previous.then(release, release)\n void current.then(() => { if (this.queues.get(key) === current) this.queues.delete(key) })\n }\n }\n\n private async create(key: string, serverId: string, workspace: string, previous?: S, signal?: AbortSignal): Promise<S> {\n if (previous) { this.sessions.delete(key); await previous.stop() }\n throwIfAborted(signal)\n const session = await this.factory(serverId, workspace, signal)\n try { await session.start(signal) } catch (error) { await session.stop(); throw error }\n if (this.disposing) { await session.stop(); throw new Error('server pool is disposing') }\n this.sessions.set(key, session)\n return session\n }\n}\n\nexport function keyOf(serverId: string, workspace: string): string { return `${serverId}\\u0000${workspace}` }\n","export type StandardOperation = 'goToDefinition' | 'findReferences' | 'goToImplementation' | 'hover'\n\nexport function supportsOperation(capabilities: Record<string, unknown>, operation: StandardOperation): boolean {\n if (operation === 'goToDefinition') return capabilities.definitionProvider === true || isProvider(capabilities.definitionProvider)\n if (operation === 'findReferences') return capabilities.referencesProvider === true || isProvider(capabilities.referencesProvider)\n if (operation === 'goToImplementation') return capabilities.implementationProvider === true || isProvider(capabilities.implementationProvider)\n return capabilities.hoverProvider === true || isProvider(capabilities.hoverProvider)\n}\n\nfunction isProvider(value: unknown): boolean {\n return typeof value === 'object' && value !== null || value === true\n}\n\nexport function defaultServerRequest(method: string, params: unknown): unknown {\n if (method === 'workspace/configuration') {\n return Array.isArray(params) ? params.map(() => null) : []\n }\n if (method === 'window/workDoneProgress/create' || method === 'client/registerCapability' || method === 'client/unregisterCapability') return null\n if (method === 'workspace/applyEdit') return { applied: false, failureReason: 'read-only provider' }\n return null\n}\n","import type { LspRange } from '../service.js'\n\nexport interface NormalizedHover {\n contents: string\n range?: LspRange\n}\n\nexport function normalizeHover(value: unknown): NormalizedHover | null | undefined {\n if (value === null || value === undefined) return null\n if (typeof value !== 'object' || value === null) return undefined\n const record = value as { contents?: unknown; range?: unknown }\n const contents = normalizeContents(record.contents)\n if (contents === undefined) return undefined\n return { contents, ...(isRange(record.range) ? { range: record.range } : {}) }\n}\n\nfunction normalizeContents(value: unknown): string | undefined {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n const parts = value.map((item) => typeof item === 'string' ? item : isRecord(item) && typeof item.value === 'string' ? item.value : undefined)\n return parts.every((item): item is string => item !== undefined) ? parts.join('\\n') : undefined\n }\n if (isRecord(value) && typeof value.value === 'string') return value.value\n return undefined\n}\n\nfunction isRange(value: unknown): value is LspRange {\n return isRecord(value) && isPosition(value.start) && isPosition(value.end)\n}\n\nfunction isPosition(value: unknown): boolean {\n return isRecord(value) && Number.isInteger(value.line) && Number.isInteger(value.character) && value.line >= 0 && value.character >= 0\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { LspPosition, LspRange } from '../service.js'\n\nexport interface NormalizedLocation {\n uri: string\n range: LspRange\n}\n\nexport function normalizeLocation(value: unknown): NormalizedLocation | undefined {\n if (isRecord(value) && typeof value.targetUri === 'string' && isRange(value.targetSelectionRange)) return { uri: value.targetUri, range: value.targetSelectionRange }\n if (!isRecord(value) || typeof value.uri !== 'string' || !isRange(value.range)) return undefined\n return { uri: value.uri, range: value.range }\n}\n\nexport function normalizeLocations(value: unknown): NormalizedLocation[] {\n const values = Array.isArray(value) ? value : value === null || value === undefined ? [] : [value]\n return values.map(normalizeLocation).filter((location): location is NormalizedLocation => location !== undefined)\n}\n\nfunction isRange(value: unknown): value is LspRange {\n return isRecord(value) && isPosition(value.start) && isPosition(value.end)\n}\n\nfunction isPosition(value: unknown): value is LspPosition {\n return isRecord(value) && Number.isInteger(value.line) && Number.isInteger(value.character) && value.line >= 0 && value.character >= 0\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { LspRange, NormalizedDiagnostic } from '../service.js'\n\nexport function normalizeDiagnostic(value: unknown, server: string, fallbackUri: string): NormalizedDiagnostic | undefined {\n if (!isRecord(value) || !isRange(value.range) || typeof value.message !== 'string') return undefined\n const uri = typeof value.uri === 'string' ? value.uri : fallbackUri\n const severity = typeof value.severity === 'number' && value.severity >= 1 && value.severity <= 4 ? value.severity as 1 | 2 | 3 | 4 : undefined\n const code = typeof value.code === 'string' || typeof value.code === 'number' ? value.code : undefined\n return { server, uri, range: value.range, message: value.message, ...(severity === undefined ? {} : { severity }), ...(code === undefined ? {} : { code }), ...(typeof value.source === 'string' ? { source: value.source } : {}) }\n}\n\nexport function normalizeDiagnostics(value: unknown, server: string, fallbackUri: string): NormalizedDiagnostic[] {\n const values = Array.isArray(value) ? value : []\n return values.map((item) => normalizeDiagnostic(item, server, fallbackUri)).filter((item): item is NormalizedDiagnostic => item !== undefined)\n}\n\nfunction isRange(value: unknown): value is LspRange {\n return isRecord(value) && isPosition(value.start) && isPosition(value.end)\n}\n\nfunction isPosition(value: unknown): boolean {\n return isRecord(value) && Number.isInteger(value.line) && Number.isInteger(value.character) && value.line >= 0 && value.character >= 0\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { NormalizedCompletionItem } from '../service.js'\n\nexport function normalizeCompletionItem(value: unknown, server: string): NormalizedCompletionItem | undefined {\n if (!isRecord(value) || typeof value.label !== 'string' || value.label.length === 0) return undefined\n return {\n server,\n label: value.label,\n ...(typeof value.kind === 'number' ? { kind: value.kind } : {}),\n ...(typeof value.detail === 'string' ? { detail: value.detail } : {}),\n ...(typeof value.documentation === 'string' ? { documentation: value.documentation } : {}),\n ...(typeof value.sortText === 'string' ? { sortText: value.sortText } : {}),\n ...(typeof value.filterText === 'string' ? { filterText: value.filterText } : {}),\n ...(typeof value.insertText === 'string' ? { insertText: value.insertText } : {}),\n ...(typeof value.insertTextFormat === 'number' ? { insertTextFormat: value.insertTextFormat } : {}),\n ...(typeof value.deprecated === 'boolean' ? { deprecated: value.deprecated } : {}),\n }\n}\n\nexport function normalizeCompletion(value: unknown, server: string): NormalizedCompletionItem[] {\n const items = isRecord(value) && Array.isArray(value.items) ? value.items : Array.isArray(value) ? value : []\n return items.map((item) => normalizeCompletionItem(item, server)).filter((item): item is NormalizedCompletionItem => item !== undefined)\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import type { NormalizedHover } from '../protocol/normalize-hover.js'\nimport type { LspRange } from '../service.js'\n\nexport interface ServerHover extends NormalizedHover {\n server: string\n}\n\nexport function mergeHover(primary: ServerHover | null | undefined, auxiliary: ServerHover | null | undefined): ServerHover | null {\n if (!primary && !auxiliary) return null\n if (!primary) return auxiliary ? { ...auxiliary } : null\n if (!auxiliary) return { ...primary }\n const contents = [primary.contents, auxiliary.contents].filter((value, index, values) => values.indexOf(value) === index)\n const range = sameRange(primary.range, auxiliary.range) ? primary.range : undefined\n return { server: primary.server, contents: contents.join('\\n\\n'), ...(range ? { range } : {}) }\n}\n\nfunction sameRange(left: LspRange | undefined, right: LspRange | undefined): boolean {\n return JSON.stringify(left) === JSON.stringify(right)\n}\n","import type { LspProviderQuery, LspQueryResult } from '@deepseek-ai/dsh-lsp'\nimport type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess'\nimport type { ResolvedConfig, ServerId } from '../config.js'\nimport { SERVER_IDS } from '../config.js'\nimport { readSource, type HostFileSystem, type HostSource } from '../host/dsh.js'\nimport { classifyFile, supportedFileSuffixes } from '../routing/classifier.js'\nimport { routeFor, type Route } from '../routing/route-table.js'\nimport { hasTailwindCandidate } from '../routing/tailwind-candidate.js'\nimport { resolveLaunch, initializationOptions, serverConfiguration } from '../servers/launch.js'\nimport { ServerSession } from './server-session.js'\nimport { ServerPool } from './server-pool.js'\nimport { throwIfAborted, withAbort } from './cancellation.js'\nimport { WebstackLspError } from '../errors.js'\nimport { supportsOperation } from '../protocol/capabilities.js'\nimport { normalizeHover } from '../protocol/normalize-hover.js'\nimport { normalizeLocations } from '../protocol/normalize-location.js'\nimport { normalizeDiagnostics } from '../protocol/normalize-diagnostic.js'\nimport { normalizeCompletion } from '../protocol/normalize-completion.js'\nimport { mergeHover } from '../merge/hover.js'\nimport { mergeDiagnostics } from '../merge/diagnostics.js'\nimport { mergeCompletions } from '../merge/completion.js'\nimport type { CompletionRequest, CompletionResult, DiagnosticsRequest, DiagnosticsResult, LspPosition, WebstackLspStatus } from '../service.js'\nimport type { JsonRpcConnection } from './connection.js'\n\nexport type HostSubprocess = Pick<SubprocessRuntime, 'spawn' | 'resolveExecutable'>\nconst methods = { hover: 'textDocument/hover', goToDefinition: 'textDocument/definition', findReferences: 'textDocument/references', goToImplementation: 'textDocument/implementation' } as const\nconst clientCapabilities = {\n general: { positionEncodings: ['utf-16'] },\n workspace: { configuration: true, workspaceFolders: true, applyEdit: false },\n textDocument: {\n synchronization: { dynamicRegistration: false, didSave: false },\n hover: { contentFormat: ['markdown', 'plaintext'] },\n completion: { completionItem: { snippetSupport: true, documentationFormat: ['markdown', 'plaintext'] } },\n publishDiagnostics: { versionSupport: true }, diagnostic: {},\n },\n}\n\nexport class WebstackLspRuntime {\n private readonly pool: ServerPool<ServerSession>\n private readonly workspaces = new Map<string, HostSource>()\n private readonly lifetime = new AbortController()\n private readonly live = new Map<ServerSession, ServerId>()\n private readonly starts = new Map<string, number>()\n private readonly restarts = new Map<ServerId, number>()\n constructor(private readonly config: ResolvedConfig, private readonly fs: HostFileSystem, private readonly subprocess: HostSubprocess) {\n this.pool = new ServerPool(async (rawId, key, signal) => {\n const id = rawId as ServerId, source = this.workspaces.get(key)!\n const spec = await resolveLaunch(id, config, source.workspace)\n let executable: string\n try { executable = await subprocess.resolveExecutable(spec.command, spec.env, signal) }\n catch { throwIfAborted(signal); throw new WebstackLspError('LSP_UNAVAILABLE', `${id} executable is unavailable; run dsh-lsp-webstack --json`) }\n const session = new ServerSession({\n spawn: () => subprocess.spawn({ argv: [executable, ...spec.args], cwd: source.workspace, env: spec.env, stdio: { stdin: 'pipe', stdout: 'pipe', stderr: { maxBytes: config.limits.maxStderrBytes } }, graceMs: config.timeouts.killGraceMs }),\n initialize: { processId: null, rootUri: source.workspaceUri, workspaceFolders: [{ uri: source.workspaceUri, name: 'workspace' }], capabilities: clientCapabilities, initializationOptions: initializationOptions(id, config) },\n configuration: serverConfiguration(id, config), maxMessageBytes: config.limits.maxMessageBytes,\n shutdown: { shutdownMs: config.timeouts.shutdownMs, killGraceMs: config.timeouts.killGraceMs },\n })\n const slot = `${id}\\u0000${key}`\n if (this.starts.has(slot)) this.restarts.set(id, (this.restarts.get(id) ?? 0) + 1)\n this.starts.set(slot, (this.starts.get(slot) ?? 0) + 1)\n for (const [old] of this.live) if (old.state === 'STOPPED' || old.state === 'FAILED') this.live.delete(old)\n this.live.set(session, id)\n return session\n })\n }\n\n async navigation(request: LspProviderQuery, signal?: AbortSignal): Promise<LspQueryResult> {\n const deadline = this.signal(request.operation === 'hover' ? this.config.timeouts.primaryHoverMs : this.config.timeouts.navigationMs, signal)\n const [source, route] = await this.prepare(request, deadline)\n this.validatePosition(source.text, request.position)\n const result = await this.document(route.primary.server, source, route.primary.languageId, deadline, async (session, connection) => {\n if (!supportsOperation(session.capabilities, request.operation)) throw new WebstackLspError('LSP_UNSUPPORTED_OPERATION', `${route.primary.server} does not support ${request.operation}`)\n return connection.request(methods[request.operation], { textDocument: { uri: source.uri }, position: request.position, ...(request.operation === 'findReferences' ? { context: { includeDeclaration: true } } : {}) }, deadline)\n })\n if (request.operation !== 'hover') return { kind: 'locations', locations: normalizeLocations(result), resolvedWorkspaceUri: source.workspaceUri }\n const primary = normalizeHover(result)\n if (primary === undefined) throw new WebstackLspError('LSP_MALFORMED_RESPONSE', 'invalid hover result')\n let auxiliary = null\n if (this.useTailwind(route, source, request.position)) {\n const auxSignal = this.signal(this.config.timeouts.auxiliaryHoverMs, signal)\n try {\n const value = await this.document('tailwind', source, route.auxiliary!.languageId, auxSignal, (_session, connection) => connection.request('textDocument/hover', { textDocument: { uri: source.uri }, position: request.position }, auxSignal))\n auxiliary = normalizeHover(value) ?? null\n } catch { throwIfAborted(signal); throwIfAborted(this.lifetime.signal) }\n }\n const hover = mergeHover(primary && { ...primary, server: route.primary.server }, auxiliary && { ...auxiliary, server: 'tailwind' })\n return { kind: 'hover', hover: hover ? { contents: hover.contents, ...(hover.range ? { range: hover.range } : {}) } : null }\n }\n\n async completion(request: CompletionRequest, signal?: AbortSignal): Promise<CompletionResult> {\n const deadline = this.signal(this.config.timeouts.completionMs, signal)\n const [source, route] = await this.prepare(request, deadline)\n this.validatePosition(source.text, request.position)\n const query = (id: ServerId, language: string) => this.document(id, source, language, deadline, (session, connection) => {\n if (!session.capabilities.completionProvider) throw new WebstackLspError('LSP_UNSUPPORTED_OPERATION', `${id} does not support completion`)\n return connection.request('textDocument/completion', { textDocument: { uri: source.uri }, position: request.position, context: { triggerKind: request.triggerKind ?? 1, ...(request.triggerCharacter ? { triggerCharacter: request.triggerCharacter } : {}) } }, deadline)\n }).then(value => {\n const prefix = source.text.split(/\\r?\\n/)[request.position.line]!.slice(0, request.position.character).match(/[\\w$:@/!\\[\\]-]+$/)?.[0]?.toLowerCase() ?? ''\n // Servers such as Tailwind return the whole catalog; the client must rank the typed prefix before applying a result cap.\n return normalizeCompletion(value, id).sort((a, b) => Number((b.filterText ?? b.label).toLowerCase().startsWith(prefix)) - Number((a.filterText ?? a.label).toLowerCase().startsWith(prefix)))\n })\n const primary = await query(route.primary.server, route.primary.languageId)\n let auxiliary: typeof primary = []\n if (this.useTailwind(route, source, request.position)) {\n try { auxiliary = await query('tailwind', route.auxiliary!.languageId) } catch { throwIfAborted(signal); throwIfAborted(this.lifetime.signal) }\n }\n return mergeCompletions([primary, auxiliary], { maxCompletions: Number.MAX_SAFE_INTEGER, maxResultChars: Number.MAX_SAFE_INTEGER })\n }\n\n async diagnostics(request: DiagnosticsRequest, signal?: AbortSignal): Promise<DiagnosticsResult> {\n const deadline = this.signal(this.config.timeouts.diagnosticsMs, signal)\n if (!classifyFile(request.filePath, this.config.routing.bladeSuffixes)) {\n // Validate workspace containment, existence and read limits even for unsupported files.\n await readSource(this.fs, request.workspaceRoot, request.filePath, this.config.limits.maxDocumentBytes, deadline)\n return { diagnostics: [], skipped: { reason: 'unsupported_file_type', filePath: request.filePath } }\n }\n const [source, route] = await this.prepare(request, deadline)\n const selected = [route.primary, ...(route.auxiliary && this.config.tailwind.enabled ? [route.auxiliary] : [])].filter(item => this.config.servers[item.server].enabled && (!request.servers || request.servers.includes(item.server)))\n if (!selected.length) throw new WebstackLspError('LSP_UNAVAILABLE', 'no selected diagnostic server supports this file')\n const omittedServers: string[] = []\n const groups = await Promise.all(selected.map(async item => {\n try {\n const value = await this.document(item.server, source, item.languageId, deadline, async (session, connection, opened) => {\n if (session.capabilities.diagnosticProvider) {\n await opened()\n const report = await connection.request('textDocument/diagnostic', { textDocument: { uri: source.uri } }, deadline) as { items?: unknown }\n return report?.items ?? []\n }\n // Subscribe before didOpen; do not confuse a missing publication with a clean file.\n let remove = () => {}\n const published = new Promise<unknown>(resolve => {\n remove = connection.onNotification(message => {\n const p = message.params as { uri?: string; diagnostics?: unknown; version?: number } | undefined\n if (message.method === 'textDocument/publishDiagnostics' && p?.uri === source.uri && (p.version === undefined || p.version === 1)) resolve(p.diagnostics)\n })\n })\n try { await opened(); return await withAbort(published, deadline) } finally { remove() }\n }, true)\n return normalizeDiagnostics(value, item.server, source.uri).filter(d => !request.severity || request.severity === 'all' || d.severity === (request.severity === 'error' ? 1 : 2))\n } catch (error) {\n throwIfAborted(signal); throwIfAborted(this.lifetime.signal)\n if (item.server === route.primary.server || this.config.missingServerPolicy === 'error') throw error\n omittedServers.push(item.server)\n return []\n }\n }))\n return { ...mergeDiagnostics(groups, { maxDiagnostics: Number.MAX_SAFE_INTEGER, maxResultChars: Number.MAX_SAFE_INTEGER }), ...(omittedServers.length ? { omittedServers: omittedServers.sort() } : {}) }\n }\n\n async status(): Promise<WebstackLspStatus> {\n return { providerId: this.config.providerId, supportedFileSuffixes: supportedFileSuffixes(this.config.routing.bladeSuffixes), servers: await Promise.all(SERVER_IDS.map(async id => {\n const config = this.config.servers[id]\n let available = false\n try {\n const launch = await resolveLaunch(id, this.config, '.')\n await this.subprocess.resolveExecutable(launch.command, launch.env, this.signal(5000))\n available = true\n } catch {}\n return { id, enabled: config.enabled && (id !== 'tailwind' || this.config.tailwind.enabled), available, source: config.mode, liveWorkspaces: [...this.live].filter(([s, server]) => server === id && s.isUsable()).length, restarts: this.restarts.get(id) ?? 0 }\n })) }\n }\n\n async dispose(): Promise<void> { this.lifetime.abort(); await this.pool.disposeAll(); this.workspaces.clear(); this.live.clear() }\n\n private signal(ms: number, signal?: AbortSignal): AbortSignal { return AbortSignal.any([this.lifetime.signal, AbortSignal.timeout(ms), ...(signal ? [signal] : [])]) }\n private async prepare(request: { workspaceRoot: string; filePath: string }, signal: AbortSignal): Promise<[HostSource, Route]> {\n throwIfAborted(signal)\n const file = classifyFile(request.filePath, this.config.routing.bladeSuffixes)\n if (!file) throw new WebstackLspError('LSP_UNAVAILABLE', 'unsupported file extension')\n const source = await readSource(this.fs, request.workspaceRoot, request.filePath, this.config.limits.maxDocumentBytes, signal).catch(error => { throwIfAborted(signal); throw error })\n this.workspaces.set(source.key, { ...source, text: '' })\n return [source, routeFor(file)]\n }\n private validatePosition(text: string, position: LspPosition): void {\n const line = text.split(/\\r?\\n/)[position.line]\n if (!Number.isSafeInteger(position.line) || !Number.isSafeInteger(position.character) || position.line < 0 || position.character < 0 || line === undefined || position.character > line.length) throw new RangeError('position is outside document (zero-based UTF-16 required)')\n }\n private useTailwind(route: Route, source: HostSource, position: LspPosition): boolean {\n return !!route.auxiliary && this.config.tailwind.enabled && this.config.servers.tailwind.enabled && (route.primary.languageId === 'blade' || this.config.routing.tailwindLanguages.includes(route.primary.languageId) || route.primary.languageId === 'css') && (this.config.tailwind.queryStrategy === 'always' || hasTailwindCandidate(source.text, position.line, this.config.tailwind.classRegex, position.character, this.config.tailwind.classAttributes))\n }\n private async document<T>(id: ServerId, source: HostSource, language: string, signal: AbortSignal, task: (session: ServerSession, connection: JsonRpcConnection, open: () => Promise<void>) => Promise<T>, manualOpen = false): Promise<T> {\n if (!this.config.servers[id].enabled) throw new WebstackLspError('LSP_UNAVAILABLE', `${id} is disabled`)\n return this.pool.runWithRetry(id, source.key, session => session.run(async connection => {\n let opened = false\n const open = async () => { opened = true; await connection.notify('textDocument/didOpen', { textDocument: { uri: source.uri, languageId: language, version: 1, text: source.text } }) }\n try { if (!manualOpen) await open(); return await task(session, connection, open) }\n finally { if (opened && connection.isOpen) await connection.notify('textDocument/didClose', { textDocument: { uri: source.uri } }).catch(() => {}) }\n }, signal), signal, manualOpen ? session => {\n // Push notifications can omit document versions. A delayed didClose clear\n // from a previous operation is indistinguishable from a fresh clean result.\n // Use a fresh process for push diagnostics; pull responses have request IDs.\n return !!session.capabilities.diagnosticProvider\n } : undefined)\n }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { LspProviderId } from '@deepseek-ai/dsh-lsp'\nimport type { LspProvider, LspProviderQuery, LspQueryResult } from '@deepseek-ai/dsh-lsp'\nimport type { Config as PluginConfig, ResolvedConfig } from './config.js'\nimport { resolveConfig } from './config.js'\nimport type { WebstackLspService } from './service.js'\nimport { createWebstackLspService } from './service.js'\nimport { WebstackLspRuntime } from './runtime/webstack-runtime.js'\nimport type {} from '@deepseek-ai/dsh-fs'\nimport type {} from '@deepseek-ai/dsh-subprocess'\n\nexport type { LspProvider, LspProviderQuery, LspQueryResult }\nexport type Config = PluginConfig\nexport const name = 'lsp-webstack-provider'\nexport const inject = ['fs', 'lsp', 'subprocess']\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { webstackLsp: WebstackLspService }\n}\n\nexport const OUTER_EXTENSION_MAP = {\n '.php': 'php', '.ts': 'typescript', '.tsx': 'typescriptreact', '.mts': 'typescript', '.cts': 'typescript',\n '.js': 'javascript', '.jsx': 'javascriptreact', '.mjs': 'javascript', '.cjs': 'javascript',\n '.svelte': 'svelte', '.html': 'html', '.htm': 'html', '.css': 'css', '.pcss': 'css',\n} as const\n\nexport interface CompositeRuntime {\n navigation(request: LspProviderQuery, signal?: AbortSignal): Promise<LspQueryResult>\n dispose?(): Promise<void>\n}\n\nexport function createCompositeProvider(runtime: CompositeRuntime, config: Pick<ResolvedConfig, 'providerId'> = { providerId: 'webstack' }): LspProvider {\n return { id: LspProviderId(config.providerId), extensionToLanguage: { ...OUTER_EXTENSION_MAP }, query: (request, signal) => runtime.navigation(request, signal) }\n}\n\nexport async function apply(ctx: Context, config: unknown = {}): Promise<void> {\n const resolved = resolveConfig(config)\n const runtime = new WebstackLspRuntime(resolved, ctx.fs, ctx.subprocess)\n await ctx.effect(async function* () {\n yield () => runtime.dispose()\n if (resolved.missingServerPolicy === 'error') {\n const missing = (await runtime.status()).servers.filter(server => server.enabled && !server.available)\n if (missing.length) throw new Error(`unavailable language servers: ${missing.map(server => server.id).join(', ')}`)\n }\n yield ctx.lsp.registerProvider(createCompositeProvider(runtime, resolved))\n yield ctx.provide('webstackLsp', createWebstackLspService(runtime))\n }, 'webstack LSP provider')\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from "@deepseek-ai/dsh-tool-lsp"
2
+
3
+ export { };
@@ -0,0 +1,2 @@
1
+ export { default } from '@deepseek-ai/dsh-lsp';
2
+ export * from '@deepseek-ai/dsh-lsp';
@@ -6,3 +6,5 @@ export interface ClassifiedFile {
6
6
  kind: FileKind;
7
7
  }
8
8
  export declare function classifyFile(filePath: string, bladeSuffixes?: string[]): ClassifiedFile | undefined;
9
+ /** Return the supported suffixes, including configured Blade suffixes. */
10
+ export declare function supportedFileSuffixes(bladeSuffixes?: string[]): string[];
@@ -43,7 +43,12 @@ export interface NormalizedCompletionItem {
43
43
  insertTextFormat?: number;
44
44
  deprecated?: boolean;
45
45
  }
46
+ /** A skipped diagnostic query is unverified; an empty diagnostics array alone is not evidence of a clean file. */
46
47
  export interface DiagnosticsResult {
48
+ skipped?: {
49
+ reason: 'unsupported_file_type';
50
+ filePath: string;
51
+ };
47
52
  diagnostics: NormalizedDiagnostic[];
48
53
  omittedServers?: string[];
49
54
  truncated?: {
@@ -60,6 +65,8 @@ export interface CompletionResult {
60
65
  }
61
66
  export interface WebstackLspStatus {
62
67
  providerId: string;
68
+ /** Routing suffixes; enabled/available servers are reported separately. */
69
+ supportedFileSuffixes?: string[];
63
70
  servers: Array<{
64
71
  id: import('./config.js').ServerId;
65
72
  enabled: boolean;
@@ -0,0 +1 @@
1
+ export * from '@deepseek-ai/dsh-tool-lsp';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askdkc/dsh-lsp-server",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Composite read-only LSP provider for DeepSeek Harness web stacks",
5
5
  "type": "module",
6
6
  "main": "./lib/provider.js",
@@ -18,7 +18,15 @@
18
18
  "types": "./lib/types/extra-tool.d.ts",
19
19
  "default": "./lib/extra-tool.js"
20
20
  },
21
- "./package.json": "./package.json"
21
+ "./package.json": "./package.json",
22
+ "./lsp": {
23
+ "types": "./lib/types/lsp.d.ts",
24
+ "default": "./lib/lsp.js"
25
+ },
26
+ "./tool-lsp": {
27
+ "types": "./lib/types/tool-lsp.d.ts",
28
+ "default": "./lib/tool-lsp.js"
29
+ }
22
30
  },
23
31
  "bin": {
24
32
  "dsh-lsp-webstack": "./lib/cli/doctor.js"
@@ -57,10 +65,10 @@
57
65
  },
58
66
  "peerDependencies": {
59
67
  "@deepseek-ai/cordis": "~4.0.4",
60
- "@deepseek-ai/dsh-fs": "0.2.0-rc.2",
61
- "@deepseek-ai/dsh-subprocess": "0.2.0-rc.2",
62
- "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
63
- "@deepseek-ai/dsh-tools": "0.2.0-rc.2",
68
+ "@deepseek-ai/dsh-fs": "*",
69
+ "@deepseek-ai/dsh-subprocess": "*",
70
+ "@deepseek-ai/dsh-system-prompt": "*",
71
+ "@deepseek-ai/dsh-tools": "*",
64
72
  "@deepseek-ai/schemastery": "~3.18.4"
65
73
  },
66
74
  "devDependencies": {