@askdkc/dsh-lsp-server 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +8 -0
  2. package/lib/code-intelligence-DvhxPnpu.js +890 -0
  3. package/lib/code-intelligence-DvhxPnpu.js.map +1 -0
  4. package/lib/code-intelligence-contracts-CWXTofdI.js +8 -0
  5. package/lib/code-intelligence-contracts-CWXTofdI.js.map +1 -0
  6. package/lib/code-intelligence-contracts.js +3 -0
  7. package/lib/code-intelligence.js +5 -0
  8. package/lib/errors-DtyWAUi0.js.map +1 -1
  9. package/lib/extra-tool.js +135 -7
  10. package/lib/extra-tool.js.map +1 -1
  11. package/lib/launch-ByUvgkVv.js.map +1 -1
  12. package/lib/provider.js +639 -41
  13. package/lib/provider.js.map +1 -1
  14. package/lib/structure/grammars/manifest.json +40 -0
  15. package/lib/structure/grammars/tree-sitter-javascript.wasm +0 -0
  16. package/lib/structure/grammars/tree-sitter-tsx.wasm +0 -0
  17. package/lib/structure/grammars/tree-sitter-typescript.wasm +0 -0
  18. package/lib/structure/parser-worker.mjs +200 -0
  19. package/lib/types/code-intelligence-contracts.d.ts +113 -0
  20. package/lib/types/code-intelligence.d.ts +5 -0
  21. package/lib/types/errors.d.ts +1 -1
  22. package/lib/types/extra-tool.d.ts +2 -1
  23. package/lib/types/provider.d.ts +4 -0
  24. package/lib/types/runtime/webstack-runtime.d.ts +13 -1
  25. package/lib/types/service.d.ts +16 -0
  26. package/lib/types/structure/code-intelligence.d.ts +23 -0
  27. package/lib/types/structure/coordinates.d.ts +14 -0
  28. package/lib/types/structure/engine.d.ts +49 -0
  29. package/lib/types/structure/protocol.d.ts +19 -0
  30. package/lib/types/structure/queries.d.ts +4 -0
  31. package/lib/types/structure/snapshots.d.ts +37 -0
  32. package/lib/types/structure/types.d.ts +147 -0
  33. package/lib/types/structure/worker-pool.d.ts +66 -0
  34. package/package.json +17 -4
@@ -0,0 +1,200 @@
1
+ import { Language, Parser, Query } from 'web-tree-sitter'
2
+
3
+ const port = (await import('node:worker_threads')).parentPort
4
+ if (!port) throw new Error('structure worker requires a parent port')
5
+
6
+ const assets = {
7
+ javascript: 'tree-sitter-javascript.wasm',
8
+ typescript: 'tree-sitter-typescript.wasm',
9
+ tsx: 'tree-sitter-tsx.wasm',
10
+ }
11
+ const MAX_CACHE_ENTRIES = 16
12
+ const MAX_CACHE_BYTES = 16 * 1024 * 1024
13
+ let init
14
+ const languages = new Map()
15
+ const trees = new Map()
16
+ let cachedBytes = 0
17
+
18
+ async function loadLanguage(language) {
19
+ if (!assets[language]) throw new Error('unsupported grammar')
20
+ init ??= Parser.init()
21
+ await init
22
+ if (!languages.has(language)) {
23
+ const url = new URL(`./grammars/${assets[language]}`, import.meta.url)
24
+ languages.set(language, await Language.load(url))
25
+ }
26
+ return languages.get(language)
27
+ }
28
+
29
+ function summarizeErrors(root, limit = 100) {
30
+ const stack = [root]
31
+ let errorNodes = 0, missingNodes = 0, visited = 0
32
+ while (stack.length && visited < 200_000) {
33
+ const node = stack.pop()
34
+ visited++
35
+ if (node.type === 'ERROR') errorNodes++
36
+ if (node.isMissing) missingNodes++
37
+ if (errorNodes + missingNodes >= limit) break
38
+ for (const child of node.children) stack.push(child)
39
+ }
40
+ return { hasError: root.hasError, errorNodes: Math.min(errorNodes, limit), missingNodes: Math.min(missingNodes, limit), truncated: stack.length > 0 }
41
+ }
42
+
43
+ function nodeSummary(node) {
44
+ const name = node.childForFieldName('name')
45
+ return {
46
+ kind: node.type,
47
+ startIndex: node.startIndex,
48
+ endIndex: node.endIndex,
49
+ startPosition: node.startPosition,
50
+ endPosition: node.endPosition,
51
+ ...(name ? { nameStartIndex: name.startIndex, nameEndIndex: name.endIndex } : {}),
52
+ childCount: node.namedChildCount,
53
+ }
54
+ }
55
+
56
+ async function run(request) {
57
+ const language = await loadLanguage(request.language)
58
+ let cached = request.snapshotHandle ? trees.get(request.snapshotHandle) : undefined
59
+ let incremental = false
60
+ if (cached && (cached.languageName !== request.language || cached.text !== request.text)) {
61
+ cached.tree.delete()
62
+ cachedBytes -= cached.bytes
63
+ trees.delete(request.snapshotHandle)
64
+ cached = undefined
65
+ }
66
+ let previous = !cached && request.previousSnapshotHandle ? trees.get(request.previousSnapshotHandle) : undefined
67
+ if (previous && previous.languageName !== request.language) previous = undefined
68
+ let tree = cached?.tree
69
+ let parser
70
+ try {
71
+ if (tree) {
72
+ trees.delete(request.snapshotHandle)
73
+ trees.set(request.snapshotHandle, cached)
74
+ } else if (previous && previous.text === request.text) {
75
+ trees.delete(request.previousSnapshotHandle)
76
+ tree = previous.tree
77
+ if (request.snapshotHandle) trees.set(request.snapshotHandle, previous)
78
+ else { cachedBytes -= previous.bytes; tree.delete() }
79
+ } else {
80
+ parser = new Parser()
81
+ parser.setLanguage(language)
82
+ if (previous) {
83
+ try {
84
+ const edit = changedRange(previous.text, request.text)
85
+ previous.tree.edit(edit)
86
+ tree = parser.parse(request.text, previous.tree)
87
+ incremental = Boolean(tree)
88
+ } catch {
89
+ tree = undefined
90
+ } finally {
91
+ trees.delete(request.previousSnapshotHandle)
92
+ cachedBytes -= previous.bytes
93
+ previous.tree.delete()
94
+ }
95
+ }
96
+ tree ??= parser.parse(request.text)
97
+ if (!tree) throw new Error('parser returned no tree')
98
+ if (request.snapshotHandle && Buffer.byteLength(request.text, 'utf8') <= MAX_CACHE_BYTES) {
99
+ const bytes = Buffer.byteLength(request.text, 'utf8')
100
+ trees.set(request.snapshotHandle, { tree, text: request.text, languageName: request.language, bytes })
101
+ cachedBytes += bytes
102
+ while (trees.size > MAX_CACHE_ENTRIES || cachedBytes > MAX_CACHE_BYTES) {
103
+ const [oldestKey, oldest] = trees.entries().next().value
104
+ trees.delete(oldestKey)
105
+ cachedBytes -= oldest.bytes
106
+ oldest.tree.delete()
107
+ if (oldestKey === request.snapshotHandle) {
108
+ tree = undefined
109
+ break
110
+ }
111
+ }
112
+ }
113
+ }
114
+ const root = tree.rootNode
115
+ const errors = summarizeErrors(root)
116
+ if (request.operation === 'inspect') return { status: errors.hasError ? 'partial' : 'ok', errors, abiVersion: language.abiVersion, reusedTree: Boolean(cached), incremental }
117
+ if (request.operation === 'enclosing') {
118
+ const leaf = root.namedDescendantForIndex(request.index, request.index) ?? root
119
+ const allowed = request.kinds?.length ? new Set(request.kinds) : undefined
120
+ const nodes = []
121
+ for (let node = leaf; node && nodes.length < 16; node = node.parent) {
122
+ if (!allowed || allowed.has(node.type)) nodes.push(nodeSummary(node))
123
+ }
124
+ return { status: errors.hasError ? 'partial' : 'ok', nodes, errors, reusedTree: Boolean(cached), incremental }
125
+ }
126
+ const query = new Query(language, request.querySource)
127
+ try {
128
+ const options = {
129
+ matchLimit: Math.max(1, Math.min(2048, request.limit + 1)),
130
+ ...(request.startIndex === undefined ? {} : { startIndex: request.startIndex }),
131
+ ...(request.endIndex === undefined ? {} : { endIndex: request.endIndex }),
132
+ }
133
+ const matches = query.matches(root, options)
134
+ const result = matches.slice(0, request.limit + 1).map(match => ({
135
+ captures: match.captures.map(capture => ({ name: capture.name, ...nodeSummary(capture.node) })),
136
+ }))
137
+ return { status: errors.hasError ? 'partial' : 'ok', matches: result, truncated: matches.length > request.limit, errors, reusedTree: Boolean(cached), incremental }
138
+ } finally { query.delete() }
139
+ } finally {
140
+ if (tree && (!request.snapshotHandle || trees.get(request.snapshotHandle)?.tree !== tree)) tree.delete()
141
+ parser?.delete()
142
+ }
143
+ }
144
+
145
+ function changedRange(oldText, newText) {
146
+ let prefix = 0
147
+ const sharedLength = Math.min(oldText.length, newText.length)
148
+ while (prefix < sharedLength && oldText.charCodeAt(prefix) === newText.charCodeAt(prefix)) prefix++
149
+ while (prefix > 0 && (splitsSurrogate(oldText, prefix) || splitsSurrogate(newText, prefix))) prefix--
150
+
151
+ let suffix = 0
152
+ while (suffix < oldText.length - prefix && suffix < newText.length - prefix &&
153
+ oldText.charCodeAt(oldText.length - suffix - 1) === newText.charCodeAt(newText.length - suffix - 1)) suffix++
154
+ while (suffix > 0 && (splitsSurrogate(oldText, oldText.length - suffix) || splitsSurrogate(newText, newText.length - suffix))) suffix--
155
+
156
+ const oldEndIndex = oldText.length - suffix
157
+ const newEndIndex = newText.length - suffix
158
+ return {
159
+ startIndex: prefix,
160
+ oldEndIndex,
161
+ newEndIndex,
162
+ startPosition: pointAt(oldText, prefix),
163
+ oldEndPosition: pointAt(oldText, oldEndIndex),
164
+ newEndPosition: pointAt(newText, newEndIndex),
165
+ }
166
+ }
167
+
168
+ function pointAt(text, index) {
169
+ let row = 0
170
+ let lineStart = 0
171
+ for (let cursor = 0; cursor < index; cursor++) {
172
+ if (text.charCodeAt(cursor) === 10) { row++; lineStart = cursor + 1 }
173
+ }
174
+ return { row, column: index - lineStart }
175
+ }
176
+
177
+ function splitsSurrogate(text, index) {
178
+ if (index <= 0 || index >= text.length) return false
179
+ const before = text.charCodeAt(index - 1)
180
+ const after = text.charCodeAt(index)
181
+ return before >= 0xd800 && before <= 0xdbff && after >= 0xdc00 && after <= 0xdfff
182
+ }
183
+
184
+ port.on('message', async request => {
185
+ if (typeof request.releaseSnapshotHandle === 'string') {
186
+ const cached = trees.get(request.releaseSnapshotHandle)
187
+ if (cached) {
188
+ trees.delete(request.releaseSnapshotHandle)
189
+ cachedBytes -= cached.bytes
190
+ cached.tree.delete()
191
+ }
192
+ return
193
+ }
194
+ try {
195
+ const value = await run(request)
196
+ port.postMessage({ id: request.id, ok: true, value })
197
+ } catch (error) {
198
+ port.postMessage({ id: request.id, ok: false, error: error instanceof Error ? error.message.slice(0, 500) : 'structure parse failed' })
199
+ }
200
+ })
@@ -0,0 +1,113 @@
1
+ /** Side-effect-free V1 protocol shared with protected Lisp adapters. */
2
+ export declare const CODE_INTELLIGENCE_SERVICE: "codeIntelligence";
3
+ export declare const CODE_INTELLIGENCE_VERSION: 1;
4
+ export type CodeStatus = 'ok' | 'partial' | 'unsupported' | 'unavailable' | 'stale' | 'cancelled' | 'timeout' | 'limit_exceeded';
5
+ export interface CodePosition {
6
+ line: number;
7
+ character: number;
8
+ }
9
+ export interface CodeRange {
10
+ start: CodePosition;
11
+ end: CodePosition;
12
+ }
13
+ export type CodeSemanticKind = 'definition' | 'references' | 'implementation' | 'hover' | 'diagnostics' | 'completion';
14
+ export type CodeQueryId = 'declarations' | 'calls' | 'imports';
15
+ export type CodeRequestV1 = {
16
+ method: 'capabilities';
17
+ } | {
18
+ method: 'snapshot.open';
19
+ path: string;
20
+ } | {
21
+ method: 'snapshot.release';
22
+ handle: string;
23
+ } | {
24
+ method: 'structure.outline';
25
+ handle: string;
26
+ range?: CodeRange;
27
+ limit?: number;
28
+ } | {
29
+ method: 'structure.enclosing';
30
+ handle: string;
31
+ position: CodePosition;
32
+ kinds?: string[];
33
+ } | {
34
+ method: 'structure.query';
35
+ handle: string;
36
+ queryId: CodeQueryId;
37
+ range?: CodeRange;
38
+ limit?: number;
39
+ } | {
40
+ method: 'structure.span';
41
+ nodeHandle: string;
42
+ maxChars?: number;
43
+ } | {
44
+ method: 'semantic.query';
45
+ handle: string;
46
+ kind: CodeSemanticKind;
47
+ position?: CodePosition;
48
+ limit?: number;
49
+ };
50
+ export interface CodeCapabilitiesV1 {
51
+ version: 1;
52
+ capabilities: Array<'snapshots' | 'structure' | 'semantic'>;
53
+ languages: string[];
54
+ queryIds: CodeQueryId[];
55
+ semanticReady: boolean;
56
+ sourceKinds: ['disk'];
57
+ languageCapabilities: Array<{
58
+ language: string;
59
+ structure: boolean;
60
+ semantic: CodeSemanticKind[];
61
+ semanticReady: boolean;
62
+ reason?: string;
63
+ }>;
64
+ limits: {
65
+ documentBytes: number;
66
+ captureItems: number;
67
+ outlineItems: number;
68
+ spanChars: number;
69
+ responseBytes: number;
70
+ files: number;
71
+ inputBytes: number;
72
+ outputBytes: number;
73
+ calls: number;
74
+ batchMs: number;
75
+ structureMs: number;
76
+ semanticMs: number;
77
+ };
78
+ }
79
+ export interface CodeResponseV1 {
80
+ protocol: 'code-intelligence/v1';
81
+ status: CodeStatus;
82
+ reason?: string;
83
+ sourceKind: 'disk';
84
+ freshness: 'pinned' | 'current' | 'unknown' | 'stale';
85
+ snapshotVersion?: string;
86
+ truncated: boolean;
87
+ omitted: number;
88
+ inputBytes?: number;
89
+ data?: unknown;
90
+ }
91
+ /** Authority comes from the host binding, never from code primitive arguments. */
92
+ export interface CodeHostBindingV1 {
93
+ owner: {
94
+ agentId: string;
95
+ sessionId: string;
96
+ };
97
+ workspaceRoot: string;
98
+ scope: object;
99
+ context: {
100
+ get(name: string, strict?: boolean): unknown;
101
+ };
102
+ assertCurrent(): void | Promise<void>;
103
+ }
104
+ export interface CodeLeaseV1 {
105
+ request(input: CodeRequestV1, signal: AbortSignal): Promise<CodeResponseV1>;
106
+ dispose(): Promise<void>;
107
+ }
108
+ export interface CodeIntelligenceServiceV1 {
109
+ version: 1;
110
+ capabilities: readonly ('snapshots' | 'structure' | 'semantic')[];
111
+ bind(binding: CodeHostBindingV1, signal: AbortSignal): Promise<CodeLeaseV1>;
112
+ dispose?(): Promise<void>;
113
+ }
@@ -0,0 +1,5 @@
1
+ export { CODE_INTELLIGENCE_SERVICE, CODE_INTELLIGENCE_VERSION } from './code-intelligence-contracts.js';
2
+ export type { CodeCapabilitiesV1, CodeHostBindingV1, CodeIntelligenceServiceV1, CodeLeaseV1, CodePosition, CodeQueryId, CodeRange, CodeRequestV1, CodeResponseV1, CodeSemanticKind, CodeStatus } from './code-intelligence-contracts.js';
3
+ export type { CodeIntelligenceCapabilities, CodeIntelligenceStatus, SemanticOperation, SemanticQuery, SemanticResult, SnapshotDescriptor, SnapshotOpenResult, SnapshotReleaseResult, SnapshotScope, SourceKind, StructureCapture, StructureEnclosingResult, StructureErrorSummary, StructureLanguage, StructureNode, StructureOutlineResult, StructureQueryResult, StructureSpanResult } from './structure/types.js';
4
+ export { createCodeIntelligenceToolServiceV1 } from './structure/code-intelligence.js';
5
+ export type { CodeIntelligenceToolServiceV1 } from './structure/types.js';
@@ -1,5 +1,5 @@
1
1
  import { LspError } from '@deepseek-ai/dsh-lsp';
2
- export type WebstackErrorCode = 'LSP_UNAVAILABLE' | 'LSP_UNSUPPORTED_OPERATION' | 'LSP_DISPOSED' | 'LSP_MALFORMED_RESPONSE' | 'LSP_CONFLICT' | 'LSP_WORKSPACE_REQUIRED' | 'LSP_WEBSTACK_CONFIG_INVALID';
2
+ export type WebstackErrorCode = 'LSP_UNAVAILABLE' | 'LSP_UNSUPPORTED_OPERATION' | 'LSP_DISPOSED' | 'LSP_MALFORMED_RESPONSE' | 'LSP_CONFLICT' | 'LSP_WORKSPACE_REQUIRED' | 'LSP_WEBSTACK_CONFIG_INVALID' | 'LSP_STALE_SNAPSHOT' | 'LSP_SNAPSHOT_LIMIT' | 'LSP_STRUCTURE_BUSY' | 'LSP_STRUCTURE_TIMEOUT' | 'LSP_STRUCTURE_LIMIT' | 'LSP_STRUCTURE_UNAVAILABLE' | 'LSP_STRUCTURE_UNSUPPORTED' | 'LSP_CODE_INTELLIGENCE_UNAVAILABLE';
3
3
  export declare class WebstackLspError extends LspError {
4
4
  readonly code: WebstackErrorCode;
5
5
  constructor(code: WebstackErrorCode, message: string, options?: ErrorOptions);
@@ -1,6 +1,7 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
3
3
  import type { WebstackLspService } from './service.js';
4
+ import type { CodeIntelligenceToolServiceV1 } from './structure/types.js';
4
5
  export declare const name = "lsp_extra";
5
6
  export declare const inject: string[];
6
7
  export interface Config {
@@ -9,5 +10,5 @@ export interface Config {
9
10
  maxResultChars?: number;
10
11
  timeoutMs?: number;
11
12
  }
12
- export declare function createExtraTool(service: WebstackLspService, config?: Config): ToolDefinition;
13
+ export declare function createExtraTool(service: WebstackLspService, codeIntelligence?: CodeIntelligenceToolServiceV1, config?: Config): ToolDefinition;
13
14
  export declare function apply(ctx: Context, config?: Config): void;
@@ -2,6 +2,8 @@ import type { Context } from '@deepseek-ai/cordis';
2
2
  import type { LspProvider, LspProviderQuery, LspQueryResult } from '@deepseek-ai/dsh-lsp';
3
3
  import type { Config as PluginConfig, ResolvedConfig } from './config.js';
4
4
  import type { WebstackLspService } from './service.js';
5
+ import type { CodeIntelligenceServiceV1 } from './code-intelligence-contracts.js';
6
+ import type { CodeIntelligenceToolServiceV1 } from './structure/types.js';
5
7
  export type { LspProvider, LspProviderQuery, LspQueryResult };
6
8
  export type Config = PluginConfig;
7
9
  export declare const name = "lsp-webstack-provider";
@@ -9,6 +11,8 @@ export declare const inject: string[];
9
11
  declare module '@deepseek-ai/cordis' {
10
12
  interface Context {
11
13
  webstackLsp: WebstackLspService;
14
+ codeIntelligence: CodeIntelligenceServiceV1;
15
+ codeIntelligenceRuntime: CodeIntelligenceToolServiceV1;
12
16
  }
13
17
  }
14
18
  export declare const OUTER_EXTENSION_MAP: {
@@ -3,12 +3,18 @@ import type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess';
3
3
  import type { ResolvedConfig } from '../config.js';
4
4
  import { type HostFileSystem } from '../host/dsh.js';
5
5
  import type { CompletionRequest, CompletionResult, DiagnosticsRequest, DiagnosticsResult, WebstackLspStatus } from '../service.js';
6
+ import type { CodeIntelligenceServiceV1 } from '../code-intelligence-contracts.js';
7
+ import type { CodeIntelligenceToolServiceV1 } from '../structure/types.js';
6
8
  export type HostSubprocess = Pick<SubprocessRuntime, 'spawn' | 'resolveExecutable'>;
7
9
  export declare class WebstackLspRuntime {
8
10
  private readonly config;
9
11
  private readonly fs;
10
12
  private readonly subprocess;
11
13
  private readonly pool;
14
+ private readonly snapshots;
15
+ readonly codeIntelligence: CodeIntelligenceServiceV1;
16
+ readonly codeIntelligenceRuntime: CodeIntelligenceToolServiceV1;
17
+ private readonly semanticOperations;
12
18
  private readonly workspaces;
13
19
  private readonly lifetime;
14
20
  private readonly live;
@@ -16,12 +22,18 @@ export declare class WebstackLspRuntime {
16
22
  private readonly restarts;
17
23
  constructor(config: ResolvedConfig, fs: HostFileSystem, subprocess: HostSubprocess);
18
24
  navigation(request: LspProviderQuery, signal?: AbortSignal): Promise<LspQueryResult>;
25
+ private navigationFromSource;
19
26
  completion(request: CompletionRequest, signal?: AbortSignal): Promise<CompletionResult>;
27
+ private completionFromSource;
20
28
  diagnostics(request: DiagnosticsRequest, signal?: AbortSignal): Promise<DiagnosticsResult>;
21
- status(): Promise<WebstackLspStatus>;
29
+ private diagnosticsFromSource;
30
+ private semanticFromSnapshot;
31
+ status(signal?: AbortSignal): Promise<WebstackLspStatus>;
32
+ private codeCapabilities;
22
33
  dispose(): Promise<void>;
23
34
  private signal;
24
35
  private prepare;
36
+ private rememberWorkspace;
25
37
  private validatePosition;
26
38
  private useTailwind;
27
39
  private document;
@@ -43,6 +43,22 @@ export interface NormalizedCompletionItem {
43
43
  insertTextFormat?: number;
44
44
  deprecated?: boolean;
45
45
  }
46
+ export type NavigationResult = {
47
+ kind: 'locations';
48
+ locations: ReadonlyArray<{
49
+ uri: string;
50
+ range: LspRange;
51
+ }>;
52
+ resolvedWorkspaceUri: string;
53
+ truncated?: boolean;
54
+ omitted?: number;
55
+ } | {
56
+ kind: 'hover';
57
+ hover: {
58
+ contents: string;
59
+ range?: LspRange;
60
+ } | null;
61
+ };
46
62
  /** A skipped diagnostic query is unverified; an empty diagnostics array alone is not evidence of a clean file. */
47
63
  export interface DiagnosticsResult {
48
64
  skipped?: {
@@ -0,0 +1,23 @@
1
+ import { DocumentSnapshotStore } from './snapshots.js';
2
+ import type { SnapshotRecord } from './snapshots.js';
3
+ import type { CodeIntelligenceCapabilities, CodeIntelligenceToolServiceV1, SemanticQuery, SnapshotScope } from './types.js';
4
+ import type { CompletionResult, DiagnosticsResult, NavigationResult } from '../service.js';
5
+ export interface CodeIntelligenceServiceOptions {
6
+ snapshots: DocumentSnapshotStore;
7
+ semanticQuery(scope: SnapshotScope, snapshot: SnapshotRecord, request: SemanticQuery, signal: AbortSignal): Promise<CompletionResult | DiagnosticsResult | NavigationResult>;
8
+ }
9
+ export declare class CodeIntelligenceRuntime implements CodeIntelligenceToolServiceV1 {
10
+ readonly version: 1;
11
+ readonly snapshot: CodeIntelligenceToolServiceV1['snapshot'];
12
+ readonly structure: CodeIntelligenceToolServiceV1['structure'];
13
+ readonly semantic: CodeIntelligenceToolServiceV1['semantic'];
14
+ private readonly store;
15
+ private readonly engine;
16
+ constructor(options: CodeIntelligenceServiceOptions);
17
+ capabilities(): CodeIntelligenceCapabilities;
18
+ releaseOwner(scope: SnapshotScope): Promise<number>;
19
+ dispose(): Promise<void>;
20
+ private span;
21
+ private withSnapshot;
22
+ }
23
+ export declare function createCodeIntelligenceToolServiceV1(options: CodeIntelligenceServiceOptions): CodeIntelligenceToolServiceV1;
@@ -0,0 +1,14 @@
1
+ import type { LspPosition, LspRange } from '../service.js';
2
+ /** web-tree-sitter 0.27.1 exposes JS-string indices as UTF-16 code-unit offsets. */
3
+ export declare class Utf16Coordinates {
4
+ private readonly text;
5
+ private readonly lines;
6
+ constructor(text: string);
7
+ positionToIndex(position: LspPosition): number;
8
+ indexToPosition(index: number): LspPosition;
9
+ rangeToIndices(range: LspRange): {
10
+ startIndex: number;
11
+ endIndex: number;
12
+ };
13
+ indicesToRange(startIndex: number, endIndex: number): LspRange;
14
+ }
@@ -0,0 +1,49 @@
1
+ import { type SnapshotRecord } from './snapshots.js';
2
+ import { StructureWorkerPool } from './worker-pool.js';
3
+ import type { SnapshotScope, StructureEnclosingResult, StructureLanguage, StructureNode, StructureOutlineResult, StructureQueryResult, StructureSpanResult } from './types.js';
4
+ export declare const MAX_CAPTURES = 200;
5
+ export declare const MAX_OUTLINE = 100;
6
+ export declare const MAX_SPAN_CHARS = 8000;
7
+ export declare const MAX_STRUCTURE_RESPONSE_BYTES: number;
8
+ export declare class StructureEngine {
9
+ private readonly workers;
10
+ private readonly nodeHandles;
11
+ private readonly snapshotOwners;
12
+ private readonly parserFailures;
13
+ constructor(workers?: StructureWorkerPool);
14
+ inspect(record: SnapshotRecord, signal?: AbortSignal): Promise<{
15
+ available: boolean;
16
+ parseErrors: boolean;
17
+ reason?: string;
18
+ }>;
19
+ outline(record: SnapshotRecord, scope: SnapshotScope, options?: {
20
+ range?: StructureNode['range'];
21
+ limit?: number;
22
+ }, signal?: AbortSignal): Promise<StructureOutlineResult>;
23
+ enclosing(record: SnapshotRecord, scope: SnapshotScope, position: {
24
+ line: number;
25
+ character: number;
26
+ }, kinds?: string[], signal?: AbortSignal): Promise<StructureEnclosingResult>;
27
+ query(record: SnapshotRecord, scope: SnapshotScope, queryId: string, options?: {
28
+ range?: StructureNode['range'];
29
+ limit?: number;
30
+ }, signal?: AbortSignal): Promise<StructureQueryResult>;
31
+ span(record: SnapshotRecord, scope: SnapshotScope, nodeHandle: string, maxChars?: number): Promise<StructureSpanResult>;
32
+ releaseSnapshot(handle: string): void;
33
+ releaseSnapshotForOwner(scope: SnapshotScope, handle: string): void;
34
+ snapshotForNode(scope: SnapshotScope, nodeHandle: string): string;
35
+ releaseOwner(scope: SnapshotScope): void;
36
+ capabilities(): Array<{
37
+ language: StructureLanguage;
38
+ extensions: string[];
39
+ available: boolean;
40
+ abiVersion: number | null;
41
+ lastError?: string;
42
+ }>;
43
+ dispose(): Promise<void>;
44
+ private runMatches;
45
+ private capability;
46
+ private runWorker;
47
+ private outlineResult;
48
+ private node;
49
+ }
@@ -0,0 +1,19 @@
1
+ import type { CodeCapabilitiesV1, CodeHostBindingV1, CodeIntelligenceServiceV1, CodeLeaseV1 } from '../code-intelligence-contracts.js';
2
+ import type { CodeIntelligenceToolServiceV1 } from './types.js';
3
+ export interface CodeIntelligenceProtocolOptions {
4
+ backend: CodeIntelligenceToolServiceV1;
5
+ fs: unknown;
6
+ subprocess: unknown;
7
+ capabilities(signal: AbortSignal): Promise<CodeCapabilitiesV1>;
8
+ }
9
+ /** Host-bound V1 facade. Each lease owns its handles and cumulative evaluation budget. */
10
+ export declare class CodeIntelligenceProtocolService implements CodeIntelligenceServiceV1 {
11
+ private readonly options;
12
+ readonly version: 1;
13
+ readonly capabilities: readonly ["snapshots", "structure", "semantic"];
14
+ private readonly leases;
15
+ private closed;
16
+ constructor(options: CodeIntelligenceProtocolOptions);
17
+ bind(binding: CodeHostBindingV1, signal: AbortSignal): Promise<CodeLeaseV1>;
18
+ dispose(): Promise<void>;
19
+ }
@@ -0,0 +1,4 @@
1
+ import type { StructureLanguage } from './types.js';
2
+ export type RegisteredQueryId = 'declarations' | 'calls' | 'imports';
3
+ export declare function getRegisteredQuery(language: StructureLanguage, queryId: string): string | undefined;
4
+ export declare function isRegisteredQueryId(value: string): value is RegisteredQueryId;
@@ -0,0 +1,37 @@
1
+ import type { HostSource } from '../host/dsh.js';
2
+ import type { SnapshotDescriptor, SnapshotScope, StructureLanguage } from './types.js';
3
+ export declare const SNAPSHOT_TTL_MS: number;
4
+ export declare const SNAPSHOT_MAX_DOCUMENTS = 32;
5
+ export declare const SNAPSHOT_MAX_BYTES: number;
6
+ export declare const STRUCTURE_MAX_DOCUMENT_BYTES: number;
7
+ export interface SnapshotRecord {
8
+ readonly descriptor: SnapshotDescriptor;
9
+ readonly scopeKey: string;
10
+ readonly source: HostSource;
11
+ readonly previousSnapshotHandle?: string;
12
+ readonly openedAt: number;
13
+ lastUsedAt: number;
14
+ }
15
+ export type SnapshotReader = (workspaceRoot: string, filePath: string, maxBytes: number, signal?: AbortSignal) => Promise<HostSource>;
16
+ export declare class DocumentSnapshotStore {
17
+ private readonly readSource;
18
+ private readonly maxDocumentBytes;
19
+ private readonly records;
20
+ private readonly versions;
21
+ constructor(readSource: SnapshotReader, maxDocumentBytes: number);
22
+ open(scope: SnapshotScope, filePath: string, signal?: AbortSignal): Promise<SnapshotRecord>;
23
+ current(scope: SnapshotScope, handle: string, signal?: AbortSignal): Promise<SnapshotRecord>;
24
+ readFresh(scope: SnapshotScope, filePath: string, signal?: AbortSignal): Promise<HostSource>;
25
+ release(scope: SnapshotScope, handle: string): boolean;
26
+ releaseOwner(scope: SnapshotScope): number;
27
+ clear(): void;
28
+ get size(): number;
29
+ get documentByteLimit(): number;
30
+ private totalBytes;
31
+ private rememberVersion;
32
+ private evictExpired;
33
+ }
34
+ export declare function languageForPath(filePath: string): StructureLanguage | null;
35
+ export declare function validateScope(scope: SnapshotScope): void;
36
+ export declare function normalizeRelativePath(filePath: string): string;
37
+ export declare function scopeIdentity(scope: SnapshotScope): string;