refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/lsp/README.md
|
||||
README.md: 3b472492ba12146101bae0e2eae9c837a7f6cb1d
|
||||
README.zh.md: 09ca13e4bc22cac746bd60e1898519a43320ae35
|
||||
README.md: 414311fd3f537634651daf6f313baf33daede26b
|
||||
README.zh.md: 8791b0ea9c01ed637586cee5c131690a73263a6a
|
||||
@@ -7,7 +7,7 @@ The language-server capability seam: an LSP Service Definition, a generic stdio
|
||||
| Package | Role | ctx key |
|
||||
|---|---|---|
|
||||
| `lsp/` | Service Definition (provider registry by branded id + extension mapping, per-query selection, vocabulary, `LspError`) | `ctx.lsp` |
|
||||
| `lsp-local/` | Generic multi-server stdio backend over `ctx.fs` and `ctx.subprocess` (JSON-RPC, transient-open queries) | (registers providers on `ctx.lsp`) |
|
||||
| `lsp-stdio/` | Generic multi-server stdio backend over `ctx.fs` and `ctx.subprocess` (JSON-RPC, transient-open queries) | (registers providers on `ctx.lsp`) |
|
||||
| `tool-lsp/` | Model-facing `lsp` tool (four operations, one-based UTF-16 cursor coordinates) | (registers on `ctx.tools`) |
|
||||
|
||||
The Service Definition lives at `lsp/lsp/`. The seam exposes exactly four semantic operations — `goToDefinition`, `findReferences`, `goToImplementation`, `hover` — and no generic JSON-RPC escape hatch, so a provider swap does not change how the model asks for navigation and no protocol payload or unreviewed mutation reaches the model contract. Providers register **capabilities**, not tools; `tool-lsp` is the only owner of the model-facing name, schema, prompt guidance, and presentation.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
| 包 | 职责 | ctx key |
|
||||
|---|---|---|
|
||||
| `lsp/` | Service Definition(按品牌化 id + 扩展名映射组织的提供方注册表、逐查询选择、词汇、`LspError`) | `ctx.lsp` |
|
||||
| `lsp-local/` | 基于 `ctx.fs` 与 `ctx.subprocess` 的通用多服务器 stdio 后端(JSON-RPC、查询时临时打开文档) | (在 `ctx.lsp` 上注册提供方) |
|
||||
| `lsp-stdio/` | 基于 `ctx.fs` 与 `ctx.subprocess` 的通用多服务器 stdio 后端(JSON-RPC、查询时临时打开文档) | (在 `ctx.lsp` 上注册提供方) |
|
||||
| `tool-lsp/` | 面向模型的 `lsp` 工具(四种操作、从 1 开始的 UTF-16 光标坐标) | (注册到 `ctx.tools`) |
|
||||
|
||||
Service Definition 位于 `lsp/lsp/`。该 seam 恰好公开四种语义操作:`goToDefinition`、`findReferences`、`goToImplementation`、`hover`,且不提供通用 JSON-RPC 逃生口;因此,替换提供方不会改变模型请求导航的方式,也不会让协议载荷或未经评审的修改进入模型约定。提供方注册的是**能力**而非工具;`tool-lsp` 是面向模型的名称、schema、提示词指引和呈现的唯一 owner。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/lsp/lsp-local/README.md
|
||||
README.md: 661c27d3326adfc3408b33550a63fe3ebe183a39
|
||||
README.zh.md: 9bc66ee00ff2f21df66b88aa607a555fd56e974b
|
||||
# pnpm run verify-translation-pairing --write packages/lsp/lsp-stdio/README.md
|
||||
README.md: beadc34ec738ae3f6511cae764240c0e9d8c61d7
|
||||
README.zh.md: 2d6516a25147fb7593e8d45d843315098cdff7d3
|
||||
@@ -1,4 +1,4 @@
|
||||
# @deepseek-ai/dsh-lsp-local
|
||||
# @deepseek-ai/dsh-lsp-stdio
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# @deepseek-ai/dsh-lsp-local
|
||||
# @deepseek-ai/dsh-lsp-stdio
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-lsp-local",
|
||||
"name": "@deepseek-ai/dsh-lsp-stdio",
|
||||
"description": "Generic stdio language-server provider for the DeepSeek Harness LSP capability seam (ctx.lsp) — spawns configured servers, translates JSON-RPC, and serves transient-open goToDefinition/findReferences/goToImplementation/hover queries in the host filesystem namespace",
|
||||
"version": "0.0.1-rc.2",
|
||||
"publishConfig": {
|
||||
@@ -8,7 +8,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
||||
"directory": "packages/lsp/lsp-local"
|
||||
"directory": "packages/lsp/lsp-stdio"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Shared cancellation helpers for the local LSP provider's host-I/O, queue, and protocol phases.
|
||||
* @module @deepseek-ai/dsh-lsp-local/abort
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/abort
|
||||
*/
|
||||
|
||||
import { timeoutOf } from '@deepseek-ai/dsh-timeout'
|
||||
@@ -7,7 +7,7 @@
|
||||
* fatal close, and exposes tree-scoped termination through the handle so the
|
||||
* instance owns teardown; group/tree mechanics live in the subprocess
|
||||
* Service provider.
|
||||
* @module @deepseek-ai/dsh-lsp-local/connection
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/connection
|
||||
*/
|
||||
|
||||
import type { Writable } from 'node:stream'
|
||||
@@ -104,7 +104,7 @@ export class LspConnection {
|
||||
})
|
||||
/* v8 ignore start -- 'pipe' dispositions expose both streams by the seam contract; defensive. */
|
||||
if (this.handle.stdin === undefined || this.handle.stdout === undefined) {
|
||||
throw new Error('lsp-local: subprocess implementation dropped a piped protocol stream')
|
||||
throw new Error('lsp-stdio: subprocess implementation dropped a piped protocol stream')
|
||||
}
|
||||
/* v8 ignore stop */
|
||||
this.stdin = this.handle.stdin
|
||||
@@ -2,7 +2,7 @@
|
||||
* LSP base-protocol framing: `Content-Length`-delimited JSON-RPC over a byte stream. The encoder
|
||||
* produces one framed buffer; the decoder buffers incoming bytes and yields complete message bodies,
|
||||
* bounding the header and total message size so a hostile or broken server cannot exhaust memory.
|
||||
* @module @deepseek-ai/dsh-lsp-local/framing
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/framing
|
||||
*/
|
||||
|
||||
/** The header/body separator in the LSP base protocol. */
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Namespace plugin (named exports, no default export). Lifecycle is effect-scoped: disposal
|
||||
* unregisters from `ctx.lsp` and tears down every live server.
|
||||
* @module @deepseek-ai/dsh-lsp-local
|
||||
* @module @deepseek-ai/dsh-lsp-stdio
|
||||
*/
|
||||
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
@@ -41,7 +41,7 @@ export { LspInstance } from './instance.ts'
|
||||
export { LspConnection } from './connection.ts'
|
||||
|
||||
/** Cordis plugin name for loader diagnostics. */
|
||||
export const name = 'lsp-local'
|
||||
export const name = 'lsp-stdio'
|
||||
|
||||
/** Services required by this plugin. */
|
||||
export const inject = ['fs', 'lsp', 'subprocess']
|
||||
@@ -125,14 +125,14 @@ function throwTeardownFailures(results: readonly PromiseSettledResult<void>[], m
|
||||
*/
|
||||
export async function apply(ctx: Context, config: Config): Promise<void> {
|
||||
const entries = Object.entries(config.servers)
|
||||
if (entries.length === 0) throw new Error('lsp-local: servers must contain at least one server')
|
||||
if (entries.length === 0) throw new Error('lsp-stdio: servers must contain at least one server')
|
||||
|
||||
const setupAbort = new AbortController()
|
||||
const stopSetupCancellation = ctx.on('internal/plugin', (fiber) => {
|
||||
// An async plugin callback must observe its own disposal before Cordis can
|
||||
// run effect cleanup, because unload otherwise waits for this callback.
|
||||
if (fiber === ctx.fiber && fiber.uid === null) {
|
||||
setupAbort.abort(new Error('lsp-local setup disposed'))
|
||||
setupAbort.abort(new Error('lsp-stdio setup disposed'))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -140,7 +140,7 @@ export async function apply(ctx: Context, config: Config): Promise<void> {
|
||||
// publish an earlier provider. Registry-level mapping conflicts are rolled back below.
|
||||
const providers = await (async () => {
|
||||
const lookups = entries.map(async ([providerId, rawConfig]) => {
|
||||
if (providerId.trim() === '') throw new Error('lsp-local: server ids must be non-empty strings')
|
||||
if (providerId.trim() === '') throw new Error('lsp-stdio: server ids must be non-empty strings')
|
||||
const resolved = rawConfig as ResolvedServerConfig
|
||||
validateServerConfig(providerId, resolved)
|
||||
const executable = await ctx.subprocess.resolveExecutable(
|
||||
@@ -180,9 +180,9 @@ export async function apply(ctx: Context, config: Config): Promise<void> {
|
||||
// Remove every route before process teardown so no new query can enter a draining provider.
|
||||
for (const dispose of disposers.reverse()) dispose()
|
||||
const results = await Promise.allSettled(providers.map(provider => provider.disposeAll()))
|
||||
throwTeardownFailures(results, 'lsp-local provider teardown failed')
|
||||
throwTeardownFailures(results, 'lsp-stdio provider teardown failed')
|
||||
}
|
||||
}, 'lsp-local.registerProviders')
|
||||
}, 'lsp-stdio.registerProviders')
|
||||
}
|
||||
|
||||
/** Validate one resolved server entry before any provider in the table is registered. */
|
||||
@@ -202,14 +202,14 @@ function validateServerConfig(providerId: string, resolved: ResolvedServerConfig
|
||||
/** Reject a timer value Node would clamp instead of scheduling as configured. */
|
||||
function assertTimer(providerId: string, name: string, value: number): void {
|
||||
if (!Number.isInteger(value) || value < 1 || value > MAX_TIMER_DELAY_MS) {
|
||||
throw new Error(`lsp-local: servers.${providerId}.${name} must be a positive integer no greater than ${MAX_TIMER_DELAY_MS}`)
|
||||
throw new Error(`lsp-stdio: servers.${providerId}.${name} must be a positive integer no greater than ${MAX_TIMER_DELAY_MS}`)
|
||||
}
|
||||
}
|
||||
|
||||
/** Reject a nonpositive or non-integer config value at load, so misconfiguration fails loud. */
|
||||
function assertPositiveInteger(providerId: string, name: string, value: number): void {
|
||||
if (!Number.isInteger(value) || value < 1) {
|
||||
throw new Error(`lsp-local: servers.${providerId}.${name} must be a positive integer`)
|
||||
throw new Error(`lsp-stdio: servers.${providerId}.${name} must be a positive integer`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ class LocalLspProvider implements LspProvider {
|
||||
private assertActive(signal?: AbortSignal): void {
|
||||
/* v8 ignore next -- the seam unregisters this provider before disposal; direct in-flight calls
|
||||
exercise the post-await check instead. */
|
||||
if (this.isDisposed()) throw new LspError('lsp-local provider is disposed', 'LSP_DISPOSED')
|
||||
if (this.isDisposed()) throw new LspError('lsp-stdio provider is disposed', 'LSP_DISPOSED')
|
||||
if (signal?.aborted) throw abortError(signal)
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ class LocalLspProvider implements LspProvider {
|
||||
/** Dispose every live instance and block further queries. */
|
||||
async disposeAll(): Promise<void> {
|
||||
this.disposed = true
|
||||
this.lifetime.abort(new LspError('lsp-local provider is disposed', 'LSP_DISPOSED'))
|
||||
this.lifetime.abort(new LspError('lsp-stdio provider is disposed', 'LSP_DISPOSED'))
|
||||
const live = [...this.instances.values()]
|
||||
const draining = [...this.queues.values()]
|
||||
const resolving = [...this.workspaceLookups]
|
||||
@@ -364,6 +364,6 @@ class LocalLspProvider implements LspProvider {
|
||||
])
|
||||
this.queues.clear()
|
||||
this.workspaceLookups.clear()
|
||||
throwTeardownFailures(results, 'lsp-local instance teardown failed')
|
||||
throwTeardownFailures(results, 'lsp-stdio instance teardown failed')
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
* instance owns one `(provider id, canonical workspace)` process. Queries serialize through a single
|
||||
* queue so a cancellation that fails to stop the server can terminate it without killing unrelated
|
||||
* work; distinct instances run in parallel.
|
||||
* @module @deepseek-ai/dsh-lsp-local/instance
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/instance
|
||||
*/
|
||||
|
||||
import { LspError } from '@deepseek-ai/dsh-lsp'
|
||||
@@ -1,16 +1,16 @@
|
||||
/**
|
||||
* Package-owned invariant companion for `@deepseek-ai/dsh-lsp-local`.
|
||||
* @module @deepseek-ai/dsh-lsp-local/invariant
|
||||
* Package-owned invariant companion for `@deepseek-ai/dsh-lsp-stdio`.
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/invariant
|
||||
*/
|
||||
|
||||
/* jscpd:ignore-start */
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
|
||||
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-lsp-local'
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-lsp-stdio'
|
||||
|
||||
/** Cordis companion plugin name. */
|
||||
export const name = 'lsp-local-invariant'
|
||||
export const name = 'lsp-stdio-invariant'
|
||||
/** Service required before the companion can reserve package ownership. */
|
||||
export const inject = ['invariants']
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* request results (`Location`, `LocationLink`, `Hover`), and the `textDocumentSync` shapes used to
|
||||
* decide transient-open support. Types only. Fields absent from a real server payload stay optional;
|
||||
* the translation layer normalizes them into the seam's closed unions.
|
||||
* @module @deepseek-ai/dsh-lsp-local/protocol
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/protocol
|
||||
*/
|
||||
|
||||
/** A zero-based UTF-16 position on the wire (the protocol's `Position`). */
|
||||
@@ -2,7 +2,7 @@
|
||||
* Pure protocol translation for the local host: what the server's capabilities allow, and how its
|
||||
* `Location`/`LocationLink`/`Hover` payloads normalize into the seam's closed result unions. No I/O
|
||||
* or process state — every function here is a pure transform, which the fake-stdio tests pin exactly.
|
||||
* @module @deepseek-ai/dsh-lsp-local/translate
|
||||
* @module @deepseek-ai/dsh-lsp-stdio/translate
|
||||
*/
|
||||
|
||||
import type {
|
||||
+4
-4
@@ -8,7 +8,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
||||
|
||||
/**
|
||||
* Keyless built-artifact smoke: plain Node imports `@deepseek-ai/dsh-lsp` and
|
||||
* `@deepseek-ai/dsh-lsp-local` by name through their exports maps, spawns the fixture server, runs
|
||||
* `@deepseek-ai/dsh-lsp-stdio` by name through their exports maps, spawns the fixture server, runs
|
||||
* one query (exercising real `Content-Length` framing over `lib/index.js`), and disposes (exercising
|
||||
* subprocess cleanup). Unit tests use `src/`; this pins the downstream `lib/` path. Skips when `lib/`
|
||||
* is absent; CI runs it after the build.
|
||||
@@ -42,12 +42,12 @@ describe.skipIf(!built)('built lib real load path (plain node)', () => {
|
||||
const script = `
|
||||
const { Context } = await import('@deepseek-ai/cordis')
|
||||
const { default: Lsp } = await import('@deepseek-ai/dsh-lsp')
|
||||
const LspLocal = await import('@deepseek-ai/dsh-lsp-local')
|
||||
const LspLocal = await import('@deepseek-ai/dsh-lsp-stdio')
|
||||
const { default: LocalFileSystem } = await import('@deepseek-ai/dsh-fs-local')
|
||||
const { default: LocalSubprocessService } = await import('@deepseek-ai/dsh-subprocess-local')
|
||||
const { default: LocalSubprocessRuntime } = await import('@deepseek-ai/dsh-subprocess-local')
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { LspConnection } from '@deepseek-ai/dsh-lsp-local'
|
||||
import type { ConnectionWriter } from '@deepseek-ai/dsh-lsp-local/src/connection.ts'
|
||||
import { LspConnection } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import type { ConnectionWriter } from '@deepseek-ai/dsh-lsp-stdio/src/connection.ts'
|
||||
import { scrubbedParentEnv } from '@deepseek-ai/dsh-subprocess'
|
||||
import { spawnSubprocess } from '@deepseek-ai/dsh-subprocess-local/src/spawn.ts'
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* A scriptable fake LSP server over stdio for lsp-local tests. It speaks the real
|
||||
* A scriptable fake LSP server over stdio for lsp-stdio tests. It speaks the real
|
||||
* `Content-Length`-framed base protocol so it exercises the client's framing, initialize handshake,
|
||||
* transient open/close, request mapping, and teardown — without a real language server.
|
||||
*
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { encodeMessage, MessageDecoder } from '@deepseek-ai/dsh-lsp-local'
|
||||
import { encodeMessage, MessageDecoder } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
|
||||
/** Frame a message the way a server would, for decoder round-trips. */
|
||||
function frame(body: string): Buffer {
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { promisify } from 'node:util'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import { deadline } from '@deepseek-ai/dsh-timeout'
|
||||
import { canonicalizeWorkspace, readHostSource } from '@deepseek-ai/dsh-lsp-local'
|
||||
import { canonicalizeWorkspace, readHostSource } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
|
||||
const execFileAsync = promisify(execFile)
|
||||
|
||||
+4
-4
@@ -6,10 +6,10 @@ import { join } from 'node:path'
|
||||
import { pathToFileURL, fileURLToPath } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import { LspInstance, readHostSource } from '@deepseek-ai/dsh-lsp-local'
|
||||
import { encodeMessage } from '@deepseek-ai/dsh-lsp-local'
|
||||
import type { ConnectionWriter } from '@deepseek-ai/dsh-lsp-local/src/connection.ts'
|
||||
import type { InstanceSpec } from '@deepseek-ai/dsh-lsp-local/src/instance.ts'
|
||||
import { LspInstance, readHostSource } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import { encodeMessage } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import type { ConnectionWriter } from '@deepseek-ai/dsh-lsp-stdio/src/connection.ts'
|
||||
import type { InstanceSpec } from '@deepseek-ai/dsh-lsp-stdio/src/instance.ts'
|
||||
import type { LspProviderQuery, LspQueryResult } from '@deepseek-ai/dsh-lsp'
|
||||
import { scrubbedParentEnv } from '@deepseek-ai/dsh-subprocess'
|
||||
import { spawnSubprocess } from '@deepseek-ai/dsh-subprocess-local/src/spawn.ts'
|
||||
+12
-12
@@ -7,10 +7,10 @@ import { pathToFileURL, fileURLToPath } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Lsp, { type LspProvider, type LspQueryRequest, type LspQueryResult } from '@deepseek-ai/dsh-lsp'
|
||||
import { deadline } from '@deepseek-ai/dsh-timeout'
|
||||
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-local'
|
||||
import type { LspLocalServerConfig } from '@deepseek-ai/dsh-lsp-local'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import type { LspLocalServerConfig } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
|
||||
const fixtureServer = fileURLToPath(new URL('./fixture-server.ts', import.meta.url))
|
||||
|
||||
@@ -39,7 +39,7 @@ function fakeServer(fakeEnv: Record<string, string> = {}, overrides: Partial<Lsp
|
||||
}
|
||||
}
|
||||
|
||||
/** Mount the real seam + lsp-local plugin driving one fake server. */
|
||||
/** Mount the real seam + lsp-stdio plugin driving one fake server. */
|
||||
async function mount(
|
||||
fakeEnv: Record<string, string> = {},
|
||||
overrides: Partial<LspLocalServerConfig> = {},
|
||||
@@ -47,7 +47,7 @@ async function mount(
|
||||
): Promise<Context> {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
const register = ctx.lsp.registerProvider.bind(ctx.lsp)
|
||||
const registrationSpy = captureProvider === undefined
|
||||
@@ -75,12 +75,12 @@ function locationJson(line: number): unknown {
|
||||
return { uri: pathToFileURL(join(ws, 'a.ts')).href, range: { start: { line, character: 0 }, end: { line, character: 3 } } }
|
||||
}
|
||||
|
||||
describe('lsp-local end to end over a fake server', () => {
|
||||
describe('lsp-stdio end to end over a fake server', () => {
|
||||
it('routes different extensions to independent configured servers', async () => {
|
||||
await writeFile(join(ws, 'a.py'), 'x = 1\n')
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
@@ -275,7 +275,7 @@ describe('lsp-local end to end over a fake server', () => {
|
||||
(registered) => { provider = registered },
|
||||
)
|
||||
expect(await ctx.lsp.query(query('goToDefinition'))).toMatchObject({ kind: 'locations' })
|
||||
if (provider === undefined) throw new Error('expected lsp-local to register a provider')
|
||||
if (provider === undefined) throw new Error('expected lsp-stdio to register a provider')
|
||||
// This implementation-local test reaches the private pool only to synchronize with its actual
|
||||
// close state. A fixed wall-clock sleep can expire before a CPU-starved child runs its exit timer.
|
||||
const instances = (provider as unknown as {
|
||||
@@ -354,7 +354,7 @@ describe('lsp-local end to end over a fake server', () => {
|
||||
it('waits for every owned teardown before aggregating instance failures', async () => {
|
||||
let provider: LspProvider | undefined
|
||||
const ctx = await mount({ LSP_FAKE_DEF: 'null' }, {}, (registered) => { provider = registered })
|
||||
if (provider === undefined) throw new Error('expected lsp-local to register a provider')
|
||||
if (provider === undefined) throw new Error('expected lsp-stdio to register a provider')
|
||||
const internals = provider as unknown as {
|
||||
readonly instances: Map<string, { dispose(): Promise<void> }>
|
||||
readonly queues: Map<string, Promise<void>>
|
||||
@@ -376,7 +376,7 @@ describe('lsp-local end to end over a fake server', () => {
|
||||
release.resolve(undefined)
|
||||
await expect(disposing).rejects.toMatchObject({
|
||||
errors: [firstFailure, secondFailure],
|
||||
message: 'lsp-local instance teardown failed',
|
||||
message: 'lsp-stdio instance teardown failed',
|
||||
})
|
||||
expect(internals.instances.size).toBe(0)
|
||||
expect(internals.queues.size).toBe(0)
|
||||
@@ -389,7 +389,7 @@ describe('lsp-local end to end over a fake server', () => {
|
||||
const disposalErrors: unknown[] = []
|
||||
ctx.logger.error = ((error: unknown) => { disposalErrors.push(error) }) as typeof ctx.logger.error
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
const providers: LspProvider[] = []
|
||||
const register = ctx.lsp.registerProvider.bind(ctx.lsp)
|
||||
@@ -446,7 +446,7 @@ describe('lsp-local end to end over a fake server', () => {
|
||||
it('rejects at load when the command is not found', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
+19
-19
@@ -3,11 +3,11 @@ import { chmod, mkdtemp, mkdir, rm, writeFile, realpath } from 'node:fs/promises
|
||||
import { tmpdir } from 'node:os'
|
||||
import { delimiter, join } from 'node:path'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import Lsp, { type LspQueryRequest } from '@deepseek-ai/dsh-lsp'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-local'
|
||||
import type { Config, LspLocalServerConfig } from '@deepseek-ai/dsh-lsp-local'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import type { Config, LspLocalServerConfig } from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'
|
||||
|
||||
let root: string
|
||||
@@ -33,7 +33,7 @@ function config(providerId: string, server: LspLocalServerConfig): Config {
|
||||
return { servers: { [providerId]: server } }
|
||||
}
|
||||
|
||||
describe('lsp-local provider resolution', () => {
|
||||
describe('lsp-stdio provider resolution', () => {
|
||||
it('resolves a bare command on the child PATH and registers the provider', async () => {
|
||||
// A tiny executable script placed on a custom PATH dir: the load-time resolver must find it.
|
||||
const bin = join(root, 'bin')
|
||||
@@ -44,7 +44,7 @@ describe('lsp-local provider resolution', () => {
|
||||
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('onpath', {
|
||||
command: 'fake-lsp',
|
||||
@@ -58,7 +58,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('skips empty PATH segments and fails when the command is absent', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('nope', {
|
||||
command: 'fake-lsp',
|
||||
@@ -73,7 +73,7 @@ describe('lsp-local provider resolution', () => {
|
||||
// Use a server that never emits results and dispose the plugin, then confirm queries are refused.
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
// Grab the provider instance by registering, then dispose the whole plugin fiber.
|
||||
const lsp = ctx.lsp
|
||||
@@ -91,7 +91,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('rejects a nonpositive teardown budget at load', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('bad-budget', {
|
||||
command: process.execPath,
|
||||
@@ -105,7 +105,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('rejects a nonpositive byte cap at load', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('bad-cap', {
|
||||
command: process.execPath,
|
||||
@@ -119,7 +119,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it.each(['shutdownTimeoutMs', 'killGraceMs'] as const)('rejects %s above Node timer range at load', async (name) => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('bad-timer', {
|
||||
command: process.execPath,
|
||||
@@ -136,7 +136,7 @@ describe('lsp-local provider resolution', () => {
|
||||
await writeFile(notExe, 'plain text, not executable')
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('abs-bad', {
|
||||
command: notExe,
|
||||
@@ -149,7 +149,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('rejects an executable directory as a command at load', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('abs-directory', {
|
||||
command: ws,
|
||||
@@ -162,7 +162,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('rejects an empty server table at load', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, { servers: {} })).rejects.toThrow(/servers must contain at least one server/)
|
||||
await ctx.fiber.dispose()
|
||||
@@ -171,7 +171,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('rejects an empty server id at load', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, config('', {
|
||||
command: process.execPath,
|
||||
@@ -183,7 +183,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('resolves every executable before publishing any provider', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
@@ -198,7 +198,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('waits for aborted sibling executable lookups before setup rejects', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
const slowStarted = Promise.withResolvers<undefined>()
|
||||
const slowAborted = Promise.withResolvers<undefined>()
|
||||
@@ -242,7 +242,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('aborts executable resolution when disposed during setup', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
const subprocess = ctx.subprocess
|
||||
const lookupStarted = Promise.withResolvers<AbortSignal>()
|
||||
@@ -268,7 +268,7 @@ describe('lsp-local provider resolution', () => {
|
||||
expect(signal.aborted).toBe(false)
|
||||
const disposing = loading.dispose()
|
||||
|
||||
await expect(loading).rejects.toThrow('lsp-local setup disposed')
|
||||
await expect(loading).rejects.toThrow('lsp-stdio setup disposed')
|
||||
await expect(disposing).resolves.toBeUndefined()
|
||||
expect(signal.aborted).toBe(true)
|
||||
await ctx.fiber.dispose()
|
||||
@@ -277,7 +277,7 @@ describe('lsp-local provider resolution', () => {
|
||||
it('rolls back earlier registrations when a later server conflicts', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await expect(ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
+2
-2
@@ -6,8 +6,8 @@ import {
|
||||
requestMethod,
|
||||
supportsOperation,
|
||||
supportsTransientOpen,
|
||||
} from '@deepseek-ai/dsh-lsp-local'
|
||||
import type { WireServerCapabilities } from '@deepseek-ai/dsh-lsp-local/src/protocol.ts'
|
||||
} from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import type { WireServerCapabilities } from '@deepseek-ai/dsh-lsp-stdio/src/protocol.ts'
|
||||
|
||||
const RANGE = { start: { line: 1, character: 2 }, end: { line: 1, character: 5 } }
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Keyless real-server e2e: drives the real `typescript-language-server` through the full
|
||||
* `ctx.lsp` → `dsh-lsp-local` stack over the base protocol, exercising all four operations. No API
|
||||
* `ctx.lsp` → `dsh-lsp-stdio` stack over the base protocol, exercising all four operations. No API
|
||||
* key needed — the server is a local dev dependency. This establishes one compatibility floor
|
||||
* (TypeScript), not a cross-language claim.
|
||||
*/
|
||||
@@ -10,10 +10,10 @@ import { mkdtemp, mkdir, rm, writeFile, realpath } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import Lsp, { type LspQueryRequest, type LspQueryResult } from '@deepseek-ai/dsh-lsp'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-local'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-stdio'
|
||||
|
||||
// The server binary is a dev dependency of this package; resolve its pnpm-hoisted .bin path.
|
||||
const serverBin = join(
|
||||
@@ -54,7 +54,7 @@ beforeAll(async () => {
|
||||
|
||||
ctx = new Context()
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
@@ -36,7 +36,7 @@
|
||||
"path": "../../subprocess/subprocess"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/lsp/lsp/README.md
|
||||
README.md: 1a4b43a157e97e88fb93a357cc2ea1ac71006a78
|
||||
README.zh.md: 9a0fb75ca392bc1ba3e30f2ea9261bb1d14dbde4
|
||||
README.md: 910b7e06ac849bbf3b56d49c1b6258a3633c6bcc
|
||||
README.zh.md: 519964cd543005b9db0b345d1632a76bf56d6b36
|
||||
@@ -9,7 +9,7 @@ This package owns the Service Definition role of the LSP capability:
|
||||
| Package | Role |
|
||||
|---|---|
|
||||
| `@deepseek-ai/dsh-lsp` (this) | Service Definition: the service, provider registry keyed by branded id + extension mapping, per-query selection, request/result vocabulary, the `LspError` taxonomy |
|
||||
| `@deepseek-ai/dsh-lsp-local` | Service provider: a generic local backend that registers configured stdio language-server providers |
|
||||
| `@deepseek-ai/dsh-lsp-stdio` | Service provider: a generic local backend that registers configured stdio language-server providers |
|
||||
| `@deepseek-ai/dsh-tool-lsp` | Consumer: the model-facing `lsp` tool over `ctx.lsp` |
|
||||
|
||||
The seam exposes exactly four semantic operations — `goToDefinition`, `findReferences`, `goToImplementation`, `hover` — and no generic JSON-RPC escape hatch, so no protocol payload or unreviewed command/mutation reaches a provider through `ctx.lsp`.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
| 包 | 职责 |
|
||||
|---|---|
|
||||
| `@deepseek-ai/dsh-lsp`(本包) | Service Definition:服务、以品牌化 id + 扩展名映射为 key 的提供方注册表、逐查询选择、请求/结果词汇、`LspError` 分类体系 |
|
||||
| `@deepseek-ai/dsh-lsp-local` | Service provider:通用本地后端,注册已配置的 stdio 语言服务器提供方 |
|
||||
| `@deepseek-ai/dsh-lsp-stdio` | Service provider:通用本地后端,注册已配置的 stdio 语言服务器提供方 |
|
||||
| `@deepseek-ai/dsh-tool-lsp` | Consumer:面向模型的 `lsp` 工具,基于 `ctx.lsp` |
|
||||
|
||||
该 seam 恰好公开四种语义操作:`goToDefinition`、`findReferences`、`goToImplementation`、`hover`,且没有通用 JSON-RPC 逃生口,因此任何协议载荷或未经评审的命令/修改都无法通过 `ctx.lsp` 到达提供方。
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"path": "../../llm/llm"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/lsp/tool-lsp/README.md
|
||||
README.md: 36fa3026cba3fc692ae5a86c7307acf77563cf53
|
||||
README.zh.md: 2372ee2501bcd6b659fe7fe984c00da632c8d0bc
|
||||
README.md: e0fd5738cf114314a8483125d20142d5f1ffac40
|
||||
README.zh.md: 8c908c1e8766ab47e9cefbc9d1f72f05e8c2709f
|
||||
@@ -18,7 +18,7 @@ The tool requires the workspace root from the session `header.cwd`, with no fall
|
||||
|---|---|---|
|
||||
| `maxLocations` | `100` | Largest number of rendered locations before an omission marker. |
|
||||
| `maxResultChars` | `16000` | Largest complete rendered result, including truncation metadata. |
|
||||
| `timeoutMs` | `60000` | Tool-call timeout budget, enforced by `dsh-timeout-policy`; covers the complete queued open/query/close lifecycle and is not model-configurable. |
|
||||
| `timeoutMs` | `60000` | Tool-call timeout budget, enforced by `dsh-tool-call-timeout-policy`; covers the complete queued open/query/close lifecycle and is not model-configurable. |
|
||||
|
||||
## Model Experience
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Namespace 插件(`name`/`inject`/`Config`/`apply`,无默认导出)
|
||||
|---|---|---|
|
||||
| `maxLocations` | `100` | 出现省略标记前可渲染位置的最大数量。 |
|
||||
| `maxResultChars` | `16000` | 完整渲染结果的最大长度,包括截断元数据。 |
|
||||
| `timeoutMs` | `60000` | 由 `dsh-timeout-policy` 强制执行的工具调用超时预算;覆盖完整的排队打开/查询/关闭生命周期,且模型不可配置。 |
|
||||
| `timeoutMs` | `60000` | 由 `dsh-tool-call-timeout-policy` 强制执行的工具调用超时预算;覆盖完整的排队打开/查询/关闭生命周期,且模型不可配置。 |
|
||||
|
||||
## 模型体验
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm": "workspace:^",
|
||||
"@deepseek-ai/dsh-lsp": "workspace:^",
|
||||
"@deepseek-ai/dsh-lsp-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-lsp-stdio": "workspace:^",
|
||||
"@deepseek-ai/dsh-session": "workspace:^",
|
||||
"@deepseek-ai/dsh-subprocess-local": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/dsh-timeout": "workspace:^",
|
||||
"@deepseek-ai/dsh-timeout-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-tool-call-timeout-policy": "workspace:^",
|
||||
"@deepseek-ai/dsh-tools": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* (`goToDefinition`/`findReferences`/`goToImplementation`/`hover`); it converts one-based UTF-16
|
||||
* cursor coordinates to the seam's zero-based positions, requires the session workspace with no
|
||||
* fallback, caps and renders results, and attaches a configurable timeout budget for
|
||||
* `dsh-timeout-policy` to enforce. It runtime-injects only `tools`, `lsp`, and `systemPrompt` and
|
||||
* `dsh-tool-call-timeout-policy` to enforce. It runtime-injects only `tools`, `lsp`, and `systemPrompt` and
|
||||
* imports no provider.
|
||||
*
|
||||
* Namespace plugin (named exports, no default export).
|
||||
|
||||
@@ -5,12 +5,12 @@ import { join } from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry from '@deepseek-ai/dsh-tools'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
|
||||
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
|
||||
import Lsp from '@deepseek-ai/dsh-lsp'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-local'
|
||||
import * as TimeoutPolicy from '@deepseek-ai/dsh-timeout-policy'
|
||||
import * as LspLocal from '@deepseek-ai/dsh-lsp-stdio'
|
||||
import * as TimeoutPolicy from '@deepseek-ai/dsh-tool-call-timeout-policy'
|
||||
import * as ToolLsp from '@deepseek-ai/dsh-tool-lsp'
|
||||
|
||||
/**
|
||||
@@ -49,10 +49,10 @@ function serverScript(hang: boolean): string {
|
||||
async function mount(hang: boolean, timeoutMs?: number): Promise<Context> {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(Lsp)
|
||||
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
await ctx.plugin(LocalSubprocessService)
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(LspLocal, {
|
||||
servers: {
|
||||
inline: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { join, resolve } from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry from '@deepseek-ai/dsh-tools'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
import Lsp, { LspProviderId, type LspProvider, type LspProviderQuery, type LspQueryResult } from '@deepseek-ai/dsh-lsp'
|
||||
import * as ToolLsp from '@deepseek-ai/dsh-tool-lsp'
|
||||
import { DEFAULT_LSP_TOOL_TIMEOUT_MS, LSP_PROMPT_TEXT } from '@deepseek-ai/dsh-tool-lsp'
|
||||
@@ -33,7 +33,7 @@ async function mount(
|
||||
): Promise<{ ctx: Context }> {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRegistry)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(Lsp)
|
||||
if (provider) (ctx.lsp as Lsp).registerProvider(provider)
|
||||
await ctx.plugin(ToolLsp, config)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"path": "../lsp"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user