dsh-vscode-mode 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +23 -6
  2. package/assets/icon.svg +7 -0
  3. package/cordis.patch.yml +12 -0
  4. package/lib/client.js +1167 -188
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +845 -96
  7. package/lib/index.js.map +1 -1
  8. package/locale/en.json +4 -0
  9. package/locale/zh.json +4 -0
  10. package/package.json +3 -1
  11. package/src/client/compat.ts +134 -4
  12. package/src/client/imagePreview.ts +76 -2
  13. package/src/client/index.ts +65 -36
  14. package/src/client/monaco/lsp/lspClient.ts +46 -0
  15. package/src/client/monaco/lsp/providers.ts +245 -1
  16. package/src/client/nativeOpenStore.ts +91 -0
  17. package/src/client/officialSidebar.ts +11 -45
  18. package/src/client/outline/index.ts +1 -1
  19. package/src/client/pdf/pdfPanel.ts +18 -0
  20. package/src/client/settingsContext.ts +6 -4
  21. package/src/client/sidebar/panels/FileExplorer.ts +1 -1
  22. package/src/client/sidebar/panels/SvnPanel.ts +1 -1
  23. package/src/client/sidebar/panels/index.ts +1 -1
  24. package/src/client/styles/editor.css +5 -3
  25. package/src/client/svnStore.ts +6 -1
  26. package/src/client/ui/EditorView.ts +117 -18
  27. package/src/client/ui/McpSettings.ts +30 -0
  28. package/src/client/ui/PerfSettings.ts +4 -1
  29. package/src/client/ui/icons.ts +72 -0
  30. package/src/compat.ts +2 -2
  31. package/src/dshVersion.ts +2 -1
  32. package/src/fileOpenSettings.ts +163 -40
  33. package/src/index.ts +15 -1
  34. package/src/lsp/client.ts +24 -0
  35. package/src/lsp/rpc.ts +57 -0
  36. package/src/lsp/server.ts +272 -2
  37. package/src/perf.ts +90 -4
  38. package/src/routes.ts +13 -1
  39. package/src/rpc.ts +96 -34
  40. package/src/shared/lsp.ts +79 -0
  41. package/src/shared/nativeOpen.ts +91 -0
  42. package/src/shared/rpc.ts +146 -1
package/src/shared/lsp.ts CHANGED
@@ -125,6 +125,82 @@ export function decodeSemanticTokens(
125
125
  return out
126
126
  }
127
127
 
128
+ /**
129
+ * LSP CompletionItemKind(协议 1-based)→ Monaco CompletionItemKind 枚举名(0-based)。
130
+ *
131
+ * 为什么按**名称**而不是编号直传:两侧枚举编号并不一致 —— LSP 2=Method,而 Monaco
132
+ * 0=Method。若把协议编号当 Monaco 编号塞回去,草稿纸上的「只差一位」会变成全表错位
133
+ * (属性显示成方法图标等)。用名称映射让两侧各自的编号在各自类型系统里解析,杜绝硬编码。
134
+ * 索引 i 对应 LSP kind i(索引 0 占位,协议从 1 起)。
135
+ * @author ddj 2026年09月22号
136
+ */
137
+ export const LSP_COMPLETION_KIND_NAMES = [
138
+ '', 'Text', 'Method', 'Function', 'Constructor', 'Field', 'Variable', 'Class',
139
+ 'Interface', 'Module', 'Property', 'Unit', 'Value', 'Enum', 'Keyword', 'Snippet',
140
+ 'Color', 'File', 'Reference', 'Folder', 'EnumMember', 'Constant', 'Struct',
141
+ 'Event', 'Operator', 'TypeParameter',
142
+ ] as const
143
+
144
+ /** LSP InsertTextFormat:1=PlainText,2=Snippet。 */
145
+ export const LSP_INSERT_TEXT_FORMAT_SNIPPET = 2
146
+
147
+ /**
148
+ * LSP 补全项文本编辑范围(单 range 或 insert/replace 双 range 形态)。
149
+ * 两种形态由服务器任选,必须都能解析:只认一种会让另一家服务器的补全落点错位。
150
+ */
151
+ export interface LspCompletionTextEdit {
152
+ range?: LspRange
153
+ insert?: LspRange
154
+ replace?: LspRange
155
+ newText: string
156
+ }
157
+
158
+ /** 归一化后的补全项(host 归一化;client 映射为 Monaco suggestion)。 */
159
+ export interface LspCompletionItem {
160
+ label: string
161
+ kind?: number // LSP CompletionItemKind 原始编号(client 经名称表转 Monaco)
162
+ detail?: string
163
+ documentation?: string
164
+ insertText?: string
165
+ insertTextFormat?: number
166
+ textEdit?: LspCompletionTextEdit
167
+ additionalTextEdits?: Array<{ range: LspRange; newText: string }>
168
+ sortText?: string
169
+ filterText?: string
170
+ preselect?: boolean
171
+ commitCharacters?: string[]
172
+ deprecated?: boolean
173
+ data?: unknown // 原样透传,completionItem/resolve 需回传
174
+ }
175
+
176
+ /** 归一化后的补全列表(incomplete:服务器要求按已输入内容重查)。 */
177
+ export interface LspCompletionList {
178
+ items: LspCompletionItem[]
179
+ incomplete: boolean
180
+ truncated?: boolean
181
+ }
182
+
183
+ /** 签名帮助中的单个参数(label 可为字符串或 [start, end] 元组,原样透传)。 */
184
+ export interface LspParameterInformation {
185
+ label: string | [number, number]
186
+ documentation?: string
187
+ }
188
+
189
+ /** 归一化后的单个签名。 */
190
+ export interface LspSignatureInformation {
191
+ label: string
192
+ documentation?: string
193
+ parameters: LspParameterInformation[]
194
+ activeParameter?: number
195
+ }
196
+
197
+ /** 归一化后的签名帮助结果。 */
198
+ export interface LspSignatureHelp {
199
+ signatures: LspSignatureInformation[]
200
+ activeSignature: number
201
+ activeParameter: number
202
+ }
203
+
128
204
  /** LSP 服务器能力子集:本插件会用到的方法。 */
129
205
  export interface LspServerCapabilities {
130
206
  definition: boolean
@@ -134,6 +210,9 @@ export interface LspServerCapabilities {
134
210
  workspaceSymbol: boolean
135
211
  hover: boolean
136
212
  semanticTokens: boolean
213
+ completion: boolean
214
+ completionResolve: boolean
215
+ signatureHelp: boolean
137
216
  semanticTokenTypes?: string[]
138
217
  semanticTokenModifiers?: string[]
139
218
  }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * dsh-vscode-mode shared — 原生打开范围判定(host/client 双面契约)。
3
+ * 背景:DSH 文件预览双形态——本插件认领 `dsh-resource://file/**` 进 Monaco 编辑,
4
+ * 官方渲染器(Office 预览/不可预览提示/表格预览)看认领让位。本模块承载「原生打开」
5
+ * 范围的单一事实源:默认集 = 让位清单(插件本来就不认领的后缀),用户可经设置
6
+ * `nativeOpenExts`(逗号分隔)增删;host 的 Config schema 默认值与 client 的
7
+ * 文件树点击判定 / claim 认领判定共用,保证三处永不同源漂移。
8
+ * 决策沿袭(不因本模块迁移而变):CSV/TSV **不在**默认集——官方 0.1.7 有表格预览,
9
+ * 但编辑器可编辑性优先,仅用户显式加入 nativeOpenExts 才让位(同 avif 例外先例)。
10
+ * 作者 ddj 2026年09月22号
11
+ */
12
+
13
+ /**
14
+ * Office 文档后缀:官方 `dsh-client-ui-sidebar-documentpreview` 的 Office 渲染器
15
+ * 声明 `doc/docx/xls/xlsx/ppt/pptx`(0.1.6 起侧栏 Office 预览;0.1.7 扩展表格 CSV/TSV
16
+ * 只读预览——本清单刻意不含 csv/tsv,见文件头决策)。本插件让位官方(不认领),
17
+ * 否则会把这些文件路由进 Monaco 而丢掉官方预览。
18
+ */
19
+ export const OFFICE_EXT: readonly string[] = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'odt', 'ods', 'odp', 'pages', 'numbers']
20
+
21
+ /**
22
+ * 官方「不可预览二进制容器」清单(`UNVIEWABLE_BINARY_EXTENSIONS`,逐项取自
23
+ * `dsh-client-ui-sidebar-documentpreview/lib/client.js`)。这些后缀官方会给出
24
+ * 「无法预览」提示;本插件让位官方,避免把二进制当文本读成乱码。
25
+ *
26
+ * ⚠️ 刻意例外:官方清单含 `avif`,但本插件图片预览支持 avif(浏览器原生解码),
27
+ * 故从本表**移除** `avif` —— 保留本插件的图片预览优于官方的「不可预览」。
28
+ * @author ddj 2026年09月18号
29
+ */
30
+ export const BLIND_EXT: readonly string[] = [
31
+ // 媒体
32
+ 'mp4', 'mov', 'avi', 'mkv', 'webm', 'flv', 'wmv', 'm4v', 'mp3', 'wav', 'flac', 'ogg', 'm4a', 'aac', 'wma', 'opus',
33
+ // 归档
34
+ 'zip', 'gz', 'tgz', 'bz2', 'xz', 'zst', '7z', 'rar', 'tar', 'jar',
35
+ // 可执行与库
36
+ 'exe', 'dll', 'so', 'dylib', 'bin', 'o', 'class', 'pyc', 'wasm',
37
+ // 字体
38
+ 'ttf', 'otf', 'woff', 'woff2', 'eot',
39
+ // 磁盘映像
40
+ 'dmg', 'iso', 'img',
41
+ // 数据库与设计文件
42
+ 'sqlite', 'db', 'psd', 'ai', 'sketch', 'tiff', 'tif', 'heic', 'heif',
43
+ ]
44
+
45
+ /** 原生打开默认后缀集 = 让位清单并集(两清单元素天然互斥,直接拼接)。 */
46
+ export const DEFAULT_NATIVE_EXT: readonly string[] = [...OFFICE_EXT, ...BLIND_EXT]
47
+
48
+ /** 默认范围的设置序列(逗号分隔;Config schema 默认值与设置页回显同源)。 */
49
+ export const DEFAULT_NATIVE_CSV: string = DEFAULT_NATIVE_EXT.join(',')
50
+
51
+ /**
52
+ * 取 path 的 basename 后缀(小写、无点);无后缀/隐藏文件返回 ''。
53
+ * @author ddj 2026年09月22号
54
+ * @param path 文件路径(`/` 或 `\` 分隔均可)
55
+ * @returns 小写后缀或 ''
56
+ */
57
+ export function suffixOf(path: unknown): string {
58
+ const base = String(path ?? '').replace(/\\/g, '/').split('/').pop() ?? ''
59
+ const dot = base.lastIndexOf('.')
60
+ return dot > 0 ? base.slice(dot + 1).toLowerCase() : ''
61
+ }
62
+
63
+ /**
64
+ * 解析设置串为后缀集合:逗号分隔、去空白、去前导点、小写;空段丢弃。
65
+ * 解析失败/空串 → 空集合(= 不追加任何原生打开范围,让位仍走 deferToOfficial)。
66
+ * @author ddj 2026年09月22号
67
+ * @param csv 逗号分隔后缀串
68
+ * @returns 后缀集合
69
+ */
70
+ export function parseExtCsv(csv: unknown): Set<string> {
71
+ const out = new Set<string>()
72
+ if (typeof csv !== 'string') return out
73
+ for (const raw of csv.split(',')) {
74
+ const item = raw.trim().replace(/^\./, '').toLowerCase()
75
+ if (item) out.add(item)
76
+ }
77
+ return out
78
+ }
79
+
80
+ /**
81
+ * 该路径是否命中「原生打开」范围(仅看用户配置集合;默认集语义由调用方
82
+ * 与 deferToOfficial 取并,保持两判定各司其职)。
83
+ * @author ddj 2026年09月22号
84
+ * @param path 文件路径
85
+ * @param exts 已解析的后缀集合(parseExtCsv 产物)
86
+ * @returns 是否命中
87
+ */
88
+ export function inNativeOpen(path: unknown, exts: ReadonlySet<string>): boolean {
89
+ const ext = suffixOf(path)
90
+ return ext !== '' && exts.has(ext)
91
+ }
package/src/shared/rpc.ts CHANGED
@@ -17,7 +17,7 @@ import type { CompatReport, DevFormInfo } from './compat.js'
17
17
  import type { ShellIntegrationStatus, UnityListPayload, UnityProjectEntry } from './integration.js'
18
18
  import type { RuleInfo, RuleProject, RuleRefInput, RuleSaveInput } from './rules.js'
19
19
  import type { SnippetEntry, SnippetInfo, SnippetProject, SnippetRefInput, SnippetSaveInput } from './snippets.js'
20
- import type { LspEnvInstallState, LspExtInfo, LspExtUpdate, LspHover, LspLocation, LspMarketItem, LspPosition, LspSemanticTokens, LspServerStatus, LspSymbol } from './lsp.js'
20
+ import type { LspCompletionItem, LspCompletionList, LspEnvInstallState, LspExtInfo, LspExtUpdate, LspHover, LspLocation, LspMarketItem, LspPosition, LspSemanticTokens, LspServerStatus, LspSignatureHelp, LspSymbol } from './lsp.js'
21
21
  import type { AiConfigPatch, AiConfigView, AiDirectoryView, AiInlineRequest, AiInlineResult } from './ai.js'
22
22
  import type { SvnAction, SvnChangeEntry, SvnConflictArtifact, SvnDiffRevResult, SvnLogEntry, SvnRemoteOutdatedEntry, SvnStatusPayload, SvnSumEntry, SvnUpdateResult } from './svn.js'
23
23
  import type { DapAction, DapAdapterInfo, DapBreakpointAck, DapBreakpointInput, DapConfigSnippet, DapConfigSource, DapDebugConfig, DapFrameView, DapPhase, DapPollResult, DapProcessInfo, DapScopeView, DapVariableView } from './dap.js'
@@ -73,6 +73,139 @@ export function binaryMimeOf(path: string): string {
73
73
  return imageMimeOf(path)
74
74
  }
75
75
 
76
+ // --region 二进制预览通道(edrv.readBinary:响应侧原始字节,省 ~33% base64 编码开销)
77
+
78
+ /** 二进制读成功响应头(octet-stream 携带元数据;同源请求可直接读取自定义头)。 */
79
+ export const BINARY_READ_HEADERS = {
80
+ mime: 'x-edrv-mime',
81
+ size: 'x-edrv-size',
82
+ version: 'x-edrv-version',
83
+ } as const
84
+
85
+ /** edrv.readBinary 成功载荷(host Uint8Array 信封;routes 接线后以 octet-stream 原样直出)。 */
86
+ export interface BinaryReadPayload {
87
+ bytes: Uint8Array
88
+ mime: string
89
+ size: number
90
+ version: string
91
+ }
92
+
93
+ /** 普通 JSON RPC 调用签名(回退通道复用;shared 不反向依赖 client 包装)。 */
94
+ export type RpcJsonCall = <M extends RpcMethod>(method: M, args: RpcRequestMap[M]) => Promise<RpcResult<M>>
95
+
96
+ /** 二进制预览读取统一结果:binary=新通道原始字节,base64=回退通道,probed=本次尝试过新通道。 */
97
+ export type PreviewRead =
98
+ | ({ ok: true; via: 'binary' } & BinaryReadPayload)
99
+ | { ok: true; via: 'base64'; content: string; size: number; encoding?: 'base64'; mime?: string; version?: string; probed?: boolean }
100
+ | { ok: false; error: string; resolvedPath?: string; probed?: boolean }
101
+
102
+ /** 通道探测状态:unknown=按次尝试;unwired=host 有 handler 但 routes 仍强制 JSON(本页不再尝试)。 */
103
+ let binaryTransport: 'unknown' | 'unwired' = 'unknown'
104
+
105
+ /**
106
+ * 二进制预览读取(edrv.readBinary,失败自动回退 edrv.read base64 现有路径)。
107
+ * 降级链:非 200 / 非 octet-stream / 元数据头缺失或长度不符 / 网络错 / host 未接线
108
+ * 把信封 JSON 化 → 一律立即回退 base64 路径,功能不降级;
109
+ * 其中「信封被 JSON 化」判定为未接线,探测一次后本页生命周期内不再尝试新通道
110
+ * (避免每次读图都付一次无效往返与大响应序列化);其余失败不关停通道(瞬时故障可自愈)。
111
+ * @author ddj 2026年09月22号
112
+ * @param rpcJson 类型化 JSON RPC 调用(调用方传入 client rpc 包装)
113
+ * @param args edrv.readBinary 请求参数
114
+ * @returns 统一读取结果(via 标记实际通道;probed 供调用方做一次性回退日志)
115
+ */
116
+ export async function readBinaryPreview(
117
+ rpcJson: RpcJsonCall,
118
+ args: RpcRequestMap['edrv.readBinary'],
119
+ ): Promise<PreviewRead> {
120
+ const attempted = binaryTransport !== 'unwired'
121
+ if (attempted) {
122
+ const direct = await tryBinaryRead(args)
123
+ if (direct) return direct
124
+ }
125
+ return fallbackRead(rpcJson, args, attempted)
126
+ }
127
+
128
+ /**
129
+ * 新通道单次尝试:响应完全符合约定才返回二进制结果,否则返回 null 触发回退。
130
+ * @author ddj 2026年09月22号
131
+ * @param args edrv.readBinary 请求参数
132
+ * @returns 二进制读取结果或 null(null=回退 base64)
133
+ */
134
+ async function tryBinaryRead(args: RpcRequestMap['edrv.readBinary']): Promise<PreviewRead | null> {
135
+ try {
136
+ const res = await fetch(RPC_PATH, {
137
+ method: 'POST',
138
+ headers: { 'content-type': 'application/json' },
139
+ body: JSON.stringify({ method: 'edrv.readBinary', args }),
140
+ })
141
+ if (!res.ok) return null
142
+ const type = res.headers.get('content-type') ?? ''
143
+ if (!type.includes('application/octet-stream')) return noteJsonBody(res)
144
+ const size = Number(res.headers.get(BINARY_READ_HEADERS.size))
145
+ const bytes = new Uint8Array(await res.arrayBuffer())
146
+ // 元数据头长度必须与实际字节数一致,否则视为非本插件响应(防御中间层/代理)
147
+ if (!Number.isFinite(size) || size !== bytes.byteLength) return null
148
+ return {
149
+ ok: true,
150
+ via: 'binary',
151
+ bytes,
152
+ mime: res.headers.get(BINARY_READ_HEADERS.mime) || binaryMimeOf(args.path),
153
+ size: bytes.byteLength,
154
+ version: res.headers.get(BINARY_READ_HEADERS.version) || '',
155
+ }
156
+ } catch (error) {
157
+ return null // 网络错按瞬时故障处理:回退但不关停通道
158
+ }
159
+ }
160
+
161
+ /**
162
+ * 非 octet-stream 响应体判定:host 已有 edrv.readBinary 但 routes 尚未接线时,
163
+ * 二进制信封会被 JSON 序列化成 {bytes:{0:..}} 普通对象——识别到该形态即标记
164
+ * 「未接线」(本页不再尝试);其余 JSON(错误响应/未知方法)仅本次回退不关停。
165
+ * @author ddj 2026年09月22号
166
+ * @param res JSON 形态的响应
167
+ * @returns 恒为 null(统一由调用方回退)
168
+ */
169
+ async function noteJsonBody(res: Response): Promise<null> {
170
+ try {
171
+ const body = (await res.json()) as { ok?: unknown; binary?: { bytes?: unknown } } | null
172
+ if (body && body.ok === true && body.binary && typeof body.binary === 'object' && body.binary.bytes != null) {
173
+ binaryTransport = 'unwired'
174
+ }
175
+ } catch (error) {
176
+ /* 非 JSON(代理页/空体):不判定,仅本次回退 */
177
+ }
178
+ return null
179
+ }
180
+
181
+ /**
182
+ * base64 回退读取(现有 edrv.read JSON 通道,载荷形状与历史实现一致)。
183
+ * @author ddj 2026年09月22号
184
+ * @param rpcJson 类型化 JSON RPC 调用
185
+ * @param args 请求参数
186
+ * @param attempted 本次是否尝试过新通道(回带给调用方做一次性日志)
187
+ * @returns 统一读取结果(调用失败转错误结果,不向上抛)
188
+ */
189
+ async function fallbackRead(
190
+ rpcJson: RpcJsonCall,
191
+ args: RpcRequestMap['edrv.readBinary'],
192
+ attempted: boolean,
193
+ ): Promise<PreviewRead> {
194
+ const probed = attempted ? { probed: true } : {}
195
+ try {
196
+ const res = await rpcJson('edrv.read', { sessionId: args.sessionId, path: args.path, encoding: 'base64' })
197
+ if (!res.ok) {
198
+ const legacy = res as { ok: false; error: string; resolvedPath?: string }
199
+ return { ok: false, error: legacy.error, ...probed, ...(legacy.resolvedPath !== undefined ? { resolvedPath: legacy.resolvedPath } : {}) }
200
+ }
201
+ if (res.encoding !== 'base64') return { ok: false, error: '读取失败', ...probed }
202
+ return { ok: true, via: 'base64', content: res.content, size: res.size, encoding: res.encoding, mime: res.mime, version: res.version, ...probed }
203
+ } catch (error) {
204
+ return { ok: false, error: 'read异常:' + String(error), ...probed }
205
+ }
206
+ }
207
+ // --endregion
208
+
76
209
  /** 决策作用域:call=整条记录,hunk=单个差异块。 */
77
210
  export type RpcScope = 'call' | 'hunk'
78
211
 
@@ -101,6 +234,10 @@ export interface PerfSession {
101
234
  bytes: number
102
235
  mtime: number
103
236
  active: boolean
237
+ /** 官方侧栏已归档(0.1.7+ workspaceRegistry.archivedSessionIds 持久位;旧 host 不回传 → undefined,按 false 渲染)。 */
238
+ archived?: boolean
239
+ /** 官方侧栏已置顶(0.1.7+ workspaceRegistry.pinnedSessionIds 持久位;旧 host 不回传 → undefined,按 false 渲染)。 */
240
+ pinned?: boolean
104
241
  }
105
242
 
106
243
  /** 一个工作区的会话聚合(edrv.perf.inventory)。 */
@@ -200,6 +337,7 @@ export interface RpcRequestMap {
200
337
  'edrv.reject': { sessionId?: string; callId: string; scope?: RpcScope; hunkIndex?: number }
201
338
  'edrv.decideBatch': { sessionId?: string; items: DecideItem[] }
202
339
  'edrv.read': { sessionId?: string; path: string; encoding?: 'base64' }
340
+ 'edrv.readBinary': { sessionId?: string; path: string }
203
341
  'edrv.versions': { sessionId?: string; paths: string[] }
204
342
  'edrv.original': { sessionId?: string; path: string }
205
343
  'edrv.save': { sessionId?: string; path: string; content: string; rev?: string }
@@ -258,6 +396,9 @@ export interface RpcRequestMap {
258
396
  'edrv.lsp.workspaceSymbol': { sessionId?: string; query: string }
259
397
  'edrv.lsp.hover': { sessionId?: string; path: string; position: LspPosition }
260
398
  'edrv.lsp.semanticTokens': { sessionId?: string; path: string }
399
+ 'edrv.lsp.completion': { sessionId?: string; path: string; position: LspPosition; context?: { triggerKind?: number; triggerCharacter?: string } }
400
+ 'edrv.lsp.resolveCompletion': { sessionId?: string; path: string; item: LspCompletionItem }
401
+ 'edrv.lsp.signatureHelp': { sessionId?: string; path: string; position: LspPosition }
261
402
  'edrv.lsp.redetect': { languageId: string }
262
403
  'edrv.lsp.envInstall': { languageId: string; id: string }
263
404
  'edrv.lsp.envState': {}
@@ -335,6 +476,7 @@ export interface RpcOkMap {
335
476
  'edrv.reject': { record: RecordView }
336
477
  'edrv.decideBatch': { results: DecideResult[] }
337
478
  'edrv.read': { content: string; size: number; encoding?: 'base64'; mime?: string; version?: string }
479
+ 'edrv.readBinary': { binary: BinaryReadPayload }
338
480
  'edrv.versions': { items: FileVersionItem[] }
339
481
  'edrv.original': { content: string; size: number; stale: StaleHunk[]; fallback: boolean }
340
482
  'edrv.save': { rev?: string; conflict?: boolean }
@@ -393,6 +535,9 @@ export interface RpcOkMap {
393
535
  'edrv.lsp.workspaceSymbol': { symbols: LspSymbol[]; truncated?: boolean }
394
536
  'edrv.lsp.hover': { hover?: LspHover }
395
537
  'edrv.lsp.semanticTokens': { tokens?: LspSemanticTokens }
538
+ 'edrv.lsp.completion': { completions?: LspCompletionList }
539
+ 'edrv.lsp.resolveCompletion': { item?: LspCompletionItem }
540
+ 'edrv.lsp.signatureHelp': { signatureHelp?: LspSignatureHelp }
396
541
  'edrv.lsp.redetect': { servers: LspServerStatus[] }
397
542
  'edrv.lsp.envInstall': { started: boolean }
398
543
  'edrv.lsp.envState': { states: LspEnvInstallState[] }