dsh-codegraph-visualizer 0.1.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +391 -226
  2. package/assets/icon-180.png +0 -0
  3. package/assets/icon.svg +30 -0
  4. package/cordis.patch.yml +22 -17
  5. package/dist/CodeGraphAdapter-BNIK0xHU.js +422 -0
  6. package/dist/CodeGraphAdapter-BNIK0xHU.js.map +1 -0
  7. package/dist/CodeGraphAdapter-CXj1hbdm.js +10 -0
  8. package/dist/FileSystemAdapter-CgasSGbB.js +524 -0
  9. package/dist/FileSystemAdapter-CgasSGbB.js.map +1 -0
  10. package/dist/LensAdapter-C9Saf_i_.js +89 -0
  11. package/dist/LensAdapter-C9Saf_i_.js.map +1 -0
  12. package/dist/Logger-DUIJSeNu.js +80 -0
  13. package/dist/Logger-DUIJSeNu.js.map +1 -0
  14. package/dist/TreeSitterAdapter-C-EWy8br.js +631 -0
  15. package/dist/TreeSitterAdapter-C-EWy8br.js.map +1 -0
  16. package/dist/TreeSitterAdapter-C6FcO2_s.js +8 -0
  17. package/dist/client/index.css +8963 -1724
  18. package/dist/client/index.css.map +1 -0
  19. package/dist/client/index.d.ts +634 -0
  20. package/dist/client/index.d.ts.map +1 -0
  21. package/dist/client/index.esm.js +57197 -20713
  22. package/dist/client/index.js.map +1 -0
  23. package/dist/client/{index.js → worker/layoutWorker.js} +7657 -8787
  24. package/dist/client.js +90426 -0
  25. package/dist/codeGraphDb-B-vpZmpm.js +9 -0
  26. package/dist/codeGraphDb-T6K3dK5D.js +357 -0
  27. package/dist/codeGraphDb-T6K3dK5D.js.map +1 -0
  28. package/dist/codeGraphRows-BhZX34uB.js +6 -0
  29. package/dist/codeGraphRows-C7hqu35E.js +246 -0
  30. package/dist/codeGraphRows-C7hqu35E.js.map +1 -0
  31. package/dist/constants-CQq93l3e.js +399 -0
  32. package/dist/constants-CQq93l3e.js.map +1 -0
  33. package/dist/graphFingerprint-CeARo7jG.js +4 -0
  34. package/dist/graphFingerprint-PuxORZUF.js +277 -0
  35. package/dist/graphFingerprint-PuxORZUF.js.map +1 -0
  36. package/dist/graphMetrics-C0F30730.js +555 -0
  37. package/dist/graphMetrics-C0F30730.js.map +1 -0
  38. package/dist/index.d.ts +572 -9
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +14819 -2009
  41. package/dist/index.js.map +1 -1
  42. package/dist/inheritanceEnhancer-Bi3UoYJS.js +291 -0
  43. package/dist/inheritanceEnhancer-Bi3UoYJS.js.map +1 -0
  44. package/dist/layerUtils-DDm-EsaD.js +72 -0
  45. package/dist/layerUtils-DDm-EsaD.js.map +1 -0
  46. package/dist/nativeIndex-CABbgERW.js +347 -0
  47. package/dist/nativeIndex-CABbgERW.js.map +1 -0
  48. package/dist/nativeIndex-esaDOsq8.js +5 -0
  49. package/dist/treeSitterExtractors-B1ybKNrC.js +394 -0
  50. package/dist/treeSitterExtractors-B1ybKNrC.js.map +1 -0
  51. package/dist/types-BUDxI_00.js +23 -0
  52. package/dist/types-BUDxI_00.js.map +1 -0
  53. package/locale/en.json +6 -0
  54. package/locale/zh-CN.json +6 -0
  55. package/locale/zh.json +6 -0
  56. package/package.json +100 -20
  57. package/dist/client-cjs/index.cjs +0 -44283
  58. package/dist/client-cjs/index.css +0 -2404
package/dist/index.d.ts CHANGED
@@ -1,13 +1,526 @@
1
- import { Context } from "@deepseek-ai/cordis";
1
+ import Schema from "@deepseek-ai/schemastery";
2
+ import * as _deepseek_ai_cordis1 from "@deepseek-ai/cordis";
3
+ import * as _deepseek_ai_cordis2 from "@deepseek-ai/cordis";
4
+ import { Context as Context$1 } from "@deepseek-ai/cordis";
2
5
 
3
6
  //#region src/generated/version.d.ts
4
- declare const PLUGIN_VERSION = "0.1.1";
7
+ declare const PLUGIN_VERSION = "0.3.1";
5
8
 
6
9
  //#endregion
7
- //#region src/host/config.d.ts
10
+ //#region src/types/index.d.ts
8
11
  //# sourceMappingURL=version.d.ts.map
12
+ type Branded<T, Brand> = T & {
13
+ __brand: Brand;
14
+ };
15
+ type RepoId = Branded<string, 'RepoId'>;
16
+ type NodeId = Branded<string, 'NodeId'>;
17
+ type EdgeId = Branded<string, 'EdgeId'>;
18
+ declare const RepoId: (id: string) => RepoId;
19
+ declare const NodeId: (id: string) => NodeId;
20
+ declare const EdgeId: (id: string) => EdgeId;
21
+ interface GraphNode {
22
+ id: NodeId;
23
+ label: string;
24
+ type: 'function' | 'class' | 'variable' | 'module' | 'interface' | 'type';
25
+ filePath: string;
26
+ lineNumber?: number;
27
+ properties: Record<string, unknown>;
28
+ parentId?: NodeId;
29
+ summary?: string;
30
+ tags?: string[];
31
+ complexity?: 'simple' | 'moderate' | 'complex';
32
+ layer?: string;
33
+ }
34
+ type EdgeDirection = 'forward' | 'backward' | 'bidirectional';
35
+ interface GraphEdge {
36
+ id: EdgeId;
37
+ source: NodeId;
38
+ target: NodeId;
39
+ type: 'call' | 'import' | 'extend' | 'implement' | 'dependency' | 'contains' | 'association' | 'aggregation' | 'composition';
40
+ direction?: EdgeDirection;
41
+ weight?: number;
42
+ properties: Record<string, unknown>;
43
+ }
44
+ type DataSourceType = 'auto' | 'codegraph' | 'lens' | 'tree-sitter' | 'dependency';
45
+ /**
46
+ * 边的**证据分级**(本轮 T2:原生 `call` 边提取)。
47
+ *
48
+ * 为什么不是随便加一个 `confidence: number`:本轮的两跳解析只有两种可被代码证明的状态,
49
+ * 一个连续量会让「一堆 0.7」既无法验证也无法断言。
50
+ *
51
+ * - `'exact'` —— 被调名在**同一个文件**的符号集里**唯一**命中。调用发生点与符号
52
+ * 定义点在同一个语法单元内,名字→符号的映射没有歧义(仍然只是名字级解析,
53
+ * 不是类型系统级解析,见 {@link CallSite} 的注释)。
54
+ * - `'inferred'` —— 同文件未命中,靠**本文件已解析出的 import 目标文件**里的唯一同名符号
55
+ * 补上。这一步引入了「import 图 + 名字唯一性」两个前提,任何一个错了边就错了,
56
+ * 所以它必须与 exact 区分开,并落到 `edgeOrigin: 'heuristic'` 档(见
57
+ * `src/adapters/treeSitterExtractors.ts` 的 `resolveCallEdges`)。
58
+ *
59
+ * 不放在 `src/xuanji/**`:那是零宿主依赖的库(有源码级守卫
60
+ * `tests/unit/xuanji/libraryBoundary.test.ts`),图谱类型属于宿主。
61
+ */
62
+
63
+ /**
64
+ * Structural difference between two graph revisions (P2-21).
65
+ *
66
+ * Lives here rather than next to its producer so both the host diff engine and the client store can
67
+ * name it without importing each other; `shared/graphDelta.ts` re-exports it and owns the helpers.
68
+ */
69
+ interface GraphDelta {
70
+ addedNodes: GraphNode[];
71
+ removedNodes: GraphNode[];
72
+ modifiedNodes: GraphNode[];
73
+ addedEdges: GraphEdge[];
74
+ removedEdges: GraphEdge[];
75
+ modifiedEdges: GraphEdge[];
76
+ }
77
+ interface GraphUpdatedEvent {
78
+ repoId: RepoId;
79
+ nodeCount: number;
80
+ edgeCount: number;
81
+ timestamp: number;
82
+ /** P0-6 structural fingerprint; stable while graph content is unchanged. */
83
+ fingerprint?: string;
84
+ /** File paths that triggered an incremental re-scan, when the watcher drove the update. */
85
+ changedFiles?: string[];
86
+ /**
87
+ * P2-21: this update is followed by a `graph/delta` carrying the actual changes, so consumers that
88
+ * understand deltas must not re-fetch the whole graph in response to this event.
89
+ */
90
+ incremental?: boolean;
91
+ }
92
+ interface GraphDataEvent {
93
+ repoId: RepoId;
94
+ nodes: GraphNode[];
95
+ edges: GraphEdge[];
96
+ timestamp: number;
97
+ /** P0-6 structural fingerprint; stable while graph content is unchanged. */
98
+ fingerprint?: string;
99
+ /** File paths that triggered an incremental re-scan, when the watcher drove the update. */
100
+ changedFiles?: string[];
101
+ /**
102
+ * 璇玑图增量引擎健康信号(cycle-122):`executeGraphData` 组装、SSE 透传到
103
+ * 客户端 StatusBar(XJ-11 消费端收口)。增量分支才有;全量重建缺省。
104
+ */
105
+ xuanji?: {
106
+ applied: boolean;
107
+ addedPaths?: number;
108
+ degradedRules?: readonly string[];
109
+ invariantViolations?: readonly string[];
110
+ };
111
+ }
112
+ /**
113
+ * 原生索引被删除(cycle-141 管理面板)。
114
+ *
115
+ * 删除成功后 host 会失效 `scanCache` / `scanInFlightMap` 并广播本事件,客户端据此
116
+ * **丢弃陈旧状态**(清空图槽、重置 ETag 校验值)。只删文件不广播 = 用户看到一张死图。
117
+ */
118
+ interface GraphDeletedEvent {
119
+ repoId: RepoId;
120
+ path: string;
121
+ timestamp: number;
122
+ }
123
+ /**
124
+ * P2-21 targeted update: only the entries that actually changed since the consumer's revision.
125
+ *
126
+ * Consumers apply this with `applyGraphDelta()` and must check `canApplyGraphDelta()` first — a
127
+ * delta is only meaningful against the exact revision it was computed from.
128
+ */
129
+ interface GraphDeltaEvent {
130
+ repoId: RepoId;
131
+ delta: GraphDelta;
132
+ timestamp: number;
133
+ /** P0-6 structural fingerprint of the resulting graph. */
134
+ fingerprint?: string;
135
+ /** File paths that triggered this update. */
136
+ changedFiles?: string[];
137
+ }
138
+ interface RepoImportedEvent {
139
+ repoId: RepoId;
140
+ path: string;
141
+ timestamp: number;
142
+ }
143
+ interface RepoScannedEvent {
144
+ repoId: RepoId;
145
+ fileCount: number;
146
+ timestamp: number;
147
+ }
148
+ interface RepoRequestScanEvent {
149
+ path: string;
150
+ timestamp: number;
151
+ }
152
+ interface SourceOpenEvent {
153
+ filePath: string;
154
+ lineNumber: number;
155
+ }
156
+ /**
157
+ * 能力位变更事件。
158
+ *
159
+ * `astSource` / `graphSource` 是两个**不同**的能力(`docs/需求分析.md` §61.10):
160
+ * AST 分析通道存在 ≠ 能产出一张图。(cycle-118:`builtin` 兼容别名已移除,
161
+ * 事件载荷不再携带;监听方读 `astSource` / `graphSource`。)
162
+ */
163
+ interface PrerequisiteStatusEvent {
164
+ codegraph: boolean;
165
+ lens: boolean;
166
+ /** 内置 AST 分析通道是否可用(TreeSitter)。 */
167
+ astSource: boolean;
168
+ /** 内置图数据通道是否存在(manifest 依赖图)。 */
169
+ graphSource: boolean;
170
+ timestamp: number;
171
+ }
172
+ interface GraphInitEvent {
173
+ path: string;
174
+ timestamp: number;
175
+ }
176
+ interface GraphInitResultEvent {
177
+ success: boolean;
178
+ path: string;
179
+ message: string;
180
+ errorCode?: string;
181
+ timestamp: number;
182
+ }
183
+ interface WatchToggleEvent {
184
+ enabled: boolean;
185
+ path: string;
186
+ timestamp: number;
187
+ }
188
+ interface HealthScoreEvent {
189
+ repoId: RepoId;
190
+ score: HealthScore;
191
+ timestamp: number;
192
+ }
193
+ interface RuleViolationEvent {
194
+ violations: RuleViolation[];
195
+ timestamp: number;
196
+ }
197
+ interface PathFoundEvent {
198
+ path: PathResult;
199
+ timestamp: number;
200
+ }
201
+ interface FocusChangedEvent {
202
+ nodeId: NodeId | null;
203
+ depth: number;
204
+ timestamp: number;
205
+ }
206
+ interface HealthScore {
207
+ coupling: number;
208
+ cohesion: number;
209
+ cyclicDependencyRate: number;
210
+ modularity: number;
211
+ overall: number;
212
+ }
213
+ interface RuleViolation {
214
+ ruleId: string;
215
+ nodeId?: NodeId;
216
+ edgeId?: EdgeId;
217
+ message: string;
218
+ severity: 'error' | 'warning';
219
+ }
220
+ interface PathResult {
221
+ source: NodeId;
222
+ target: NodeId;
223
+ path: NodeId[];
224
+ length: number;
225
+ }
226
+ declare module '@deepseek-ai/cordis' {
227
+ interface Events {
228
+ /**
229
+ * @mode serial
230
+ * @param event Repository imported into the workspace
231
+ */
232
+ 'codegraph-visualizer/repo/imported'(event: RepoImportedEvent): void;
233
+ /**
234
+ * @mode serial
235
+ * @param event Repository scan completed with file count
236
+ */
237
+ 'codegraph-visualizer/repo/scanned'(event: RepoScannedEvent): void;
238
+ /**
239
+ * @mode serial
240
+ * @param event Request to scan a repository at the given path
241
+ */
242
+ 'codegraph-visualizer/repo/request-scan'(event: RepoRequestScanEvent): void;
243
+ /**
244
+ * @mode serial
245
+ * @param event Graph updated with new node/edge counts
246
+ */
247
+ 'codegraph-visualizer/graph/updated'(event: GraphUpdatedEvent): void;
248
+ /**
249
+ * @mode serial
250
+ * @param event Full graph data payload for rendering
251
+ */
252
+ 'codegraph-visualizer/graph/data'(event: GraphDataEvent): void;
253
+ /**
254
+ * @mode serial
255
+ * @param event Native index deleted; consumers must drop stale graph state
256
+ */
257
+ 'codegraph-visualizer/graph/deleted'(event: GraphDeletedEvent): void;
258
+ /**
259
+ * @mode serial
260
+ * @param event Targeted graph update carrying only the entries that changed (P2-21)
261
+ */
262
+ 'codegraph-visualizer/graph/delta'(event: GraphDeltaEvent): void;
263
+ /**
264
+ * @mode serial
265
+ * @param event Request to open a source file at a specific line
266
+ */
267
+ 'codegraph-visualizer/source/open'(event: SourceOpenEvent): void;
268
+ /**
269
+ * @mode serial
270
+ * @param event Prerequisite service availability status changed
271
+ */
272
+ 'codegraph-visualizer/prerequisite/status'(event: PrerequisiteStatusEvent): void;
273
+ /**
274
+ * @mode serial
275
+ * @param event Request prerequisite status check
276
+ */
277
+ 'codegraph-visualizer/prerequisite/request'(event: {
278
+ timestamp: number;
279
+ }): void;
280
+ /**
281
+ * @mode serial
282
+ * @param event Request to initialize graph for a repository path
283
+ */
284
+ 'codegraph-visualizer/graph/init'(event: GraphInitEvent): void;
285
+ /**
286
+ * @mode serial
287
+ * @param event Graph initialization result (success/failure)
288
+ */
289
+ 'codegraph-visualizer/graph/init-result'(event: GraphInitResultEvent): void;
290
+ /**
291
+ * @mode serial
292
+ * @param event File watcher toggle state changed
293
+ */
294
+ 'codegraph-visualizer/watch/toggle'(event: WatchToggleEvent): void;
295
+ /**
296
+ * @mode serial
297
+ * @param event File watcher error occurred
298
+ */
299
+ 'codegraph-visualizer/watch/error'(event: {
300
+ path: string;
301
+ message: string;
302
+ errorCode?: string;
303
+ timestamp: number;
304
+ }): void;
305
+ /**
306
+ * @mode serial
307
+ * @param event Architecture health score calculated
308
+ */
309
+ 'codegraph-visualizer/health/scored'(event: HealthScoreEvent): void;
310
+ /**
311
+ * @mode serial
312
+ * @param event Architecture rule violation detected
313
+ */
314
+ 'codegraph-visualizer/rules/violation'(event: RuleViolationEvent): void;
315
+ /**
316
+ * @mode serial
317
+ * @param event Shortest path found between two symbols
318
+ */
319
+ 'codegraph-visualizer/path/found'(event: PathFoundEvent): void;
320
+ /**
321
+ * @mode serial
322
+ * @param event Focus changed to a different node (or null to clear)
323
+ */
324
+ 'codegraph-visualizer/focus/changed'(event: FocusChangedEvent): void;
325
+ }
326
+ interface Context {
327
+ webServer: WebServerService;
328
+ effect(execute: () => (() => void) | void, label?: string): () => void;
329
+ emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void;
330
+ on<K extends keyof Events>(name: K, listener: Events[K]): () => boolean;
331
+ get(name: string, strict?: boolean): unknown;
332
+ provide(name: string, service: unknown): () => void;
333
+ /**
334
+ * 响应式服务注入:**等到依赖到齐才跑回调**,且依赖被替换时会重跑
335
+ * (旧 scope 先卸载、再跑新回调)。
336
+ *
337
+ * 契约与真实 cordis 对齐(cycle-83 修正,此前这里错写成
338
+ * `callback: (injected: Map<string, unknown>) => void`,与实现不符):
339
+ *
340
+ * - `inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>`
341
+ * (`<A>\cordis\lib\types\registry.d.ts:111` 与 `:185`)
342
+ * - `interface Function<T> extends Base<T> { (ctx: Context, config: T): any }`
343
+ * (`registry.d.ts:71-73`)⇒ **回调首参是 `Context`**,不是 Map
344
+ * - JSDoc 逐字:「Run a callback once the requested services are available.
345
+ * Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback is
346
+ * unloaded and re-run whenever a required service changes.」
347
+ *
348
+ * 返回值是**子 fiber**,随父 fiber 卸载自动释放,因此不需要手工 dispose。
349
+ * 依赖永不到齐时回调永不执行,且不阻塞父插件 apply(cordis 探针实验 1 实测)。
350
+ */
351
+ inject(deps: string[], callback: (scope: Context, config?: unknown) => void): _deepseek_ai_cordis1.Fiber & PromiseLike<_deepseek_ai_cordis2.Fiber>;
352
+ slots: {
353
+ inject(slotName: string, callback: () => void): (() => void) | void;
354
+ register(options: {
355
+ name: string;
356
+ id?: string;
357
+ key?: string;
358
+ order?: number;
359
+ label?: () => string;
360
+ inject?: (...args: unknown[]) => unknown;
361
+ }, component?: unknown): (() => void) | void;
362
+ };
363
+ betterSidebar?: {
364
+ version: string;
365
+ features: string[];
366
+ registerTab(descriptor: {
367
+ id: string;
368
+ title: string | (() => string);
369
+ description?: string | (() => string);
370
+ icon?: unknown;
371
+ order?: number;
372
+ single?: boolean;
373
+ hidden?: boolean;
374
+ badge?: () => string | number | null | undefined;
375
+ onOpen?: (tab: unknown, scope: unknown) => void;
376
+ onActivate?: (tab: unknown, scope: unknown) => void;
377
+ onClose?: (tab: unknown, scope: unknown) => void;
378
+ component: (props: {
379
+ ctx: Context;
380
+ store: unknown;
381
+ scope: unknown;
382
+ tab: {
383
+ id: string;
384
+ title: string;
385
+ path?: string;
386
+ };
387
+ visible: boolean;
388
+ expanded?: string[];
389
+ revealed?: string[];
390
+ }) => unknown;
391
+ }): (() => void) | void;
392
+ openTab(seed: {
393
+ type: string;
394
+ title?: string;
395
+ path?: string;
396
+ target?: 'right' | 'bottom';
397
+ }): void;
398
+ closeTab(tabId: string, scope?: unknown): void;
399
+ activateTab(tabId: string, scope?: unknown): void;
400
+ updateTab(tabId: string, patch: {
401
+ title?: string;
402
+ path?: string;
403
+ meta?: unknown;
404
+ }): void;
405
+ subscribe(listener: () => void): () => void;
406
+ subscribeState(listener: () => void): () => void;
407
+ getSnapshot(): {
408
+ sessionId: string | undefined;
409
+ state: {
410
+ activePane: string | null;
411
+ bottomOpen: boolean;
412
+ bottomHeight: number;
413
+ expanded: string[];
414
+ revealed: string[];
415
+ } | undefined;
416
+ prefs: unknown;
417
+ };
418
+ };
419
+ /**
420
+ * DSH 斜杠命令贡献面(`@deepseek-ai/dsh-client-ui-commands`)。
421
+ *
422
+ * 契约逐字来源:`lib/types/client/contract.d.ts:129`
423
+ * `register(contribution: CommandContribution): () => void`,JSDoc
424
+ * 「Register one client command contribution; effect disposer. Duplicate names throw
425
+ * at registration.」;`CommandContribution`(同文件 `:92-105`)必填
426
+ * `name` 与 `available(session)`;`ActionSpec`(`:75-82`)为
427
+ * `{ kind: 'action'; run(session): void }`。
428
+ *
429
+ * 本服务由 `Service` 基类 `super(ctx, 'commandUi')` 注册(gen2
430
+ * `dsh-client-ui-commands/lib/client.js:771`、gen1 同文件 `:737`),因此两代都在。
431
+ * 它替代了本项目 cycle-83 清除的 `spotlight` 幻影服务。
432
+ */
433
+ commandUi?: {
434
+ register(contribution: {
435
+ name: string;
436
+ label?: () => string;
437
+ description?: () => string;
438
+ icon?: unknown;
439
+ available: (session: unknown) => boolean;
440
+ ui: {
441
+ kind: 'action';
442
+ run: (session: unknown) => void;
443
+ };
444
+ }): (() => void) | void;
445
+ };
446
+ /**
447
+ * DSH 原生右侧栏的 tab 类型注册表(`@deepseek-ai/dsh-client-ui-sidebar-right`)。
448
+ *
449
+ * 形状逐字对齐 `lib/types/client/tab-registry.d.ts:75-120` 的
450
+ * `SidebarRightTabDefinition`:
451
+ * - `title: (address: string) => string` —— **必填**,且收 `address` 形参;
452
+ * 旧声明写成可选且无形参,是契约不精确。
453
+ * - `keepMounted?: boolean` —— 「Lazily keep a visited body mounted through hiding,
454
+ * Session changes and docking; default false」,图表面板需要它。
455
+ * - `multiple?: boolean` —— 缺省即「每个 pane 每 kind 一页」。
456
+ * - **没有 `order` 字段** —— 排序由 `priority` band 与 `RANKS`
457
+ * (`extension: 3 / builtin: 2 / fallback: 1`,见
458
+ * `dsh-client-ui-sidebar-right/lib/client.js:8619-8623`)决定,旧声明多写了 `order`。
459
+ */
460
+ sidebarRightTabs?: {
461
+ register(definition: {
462
+ id: string;
463
+ kind: string;
464
+ title: (address: string) => string;
465
+ multiple?: boolean;
466
+ keepMounted?: boolean;
467
+ patterns?: string[];
468
+ priority?: 'extension' | 'builtin' | 'fallback';
469
+ canOpen?: (address: string) => boolean;
470
+ guide?: readonly {
471
+ id: string;
472
+ [key: string]: unknown;
473
+ }[];
474
+ }): (() => void) | void;
475
+ };
476
+ workspaceRegistry?: {
477
+ list?(): Array<{
478
+ path?: string;
479
+ }>;
480
+ };
481
+ hostVersion?: string;
482
+ version?: string;
483
+ app?: {
484
+ version?: string;
485
+ };
486
+ runtime?: {
487
+ version?: string;
488
+ };
489
+ }
490
+ }
491
+ interface WebServerRoute {
492
+ kind: 'exact' | 'prefix';
493
+ path: string;
494
+ handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
495
+ }
496
+ interface WebServerService {
497
+ register(route: WebServerRoute): () => void;
498
+ registerFallback(handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>): () => void;
499
+ }
500
+ interface IncomingMessage {
501
+ url?: string;
502
+ method?: string;
503
+ headers: Record<string, string | string[] | undefined>;
504
+ socket?: {
505
+ remoteAddress?: string;
506
+ };
507
+ on(event: 'data', handler: (chunk: Buffer) => void): void;
508
+ on(event: 'end', handler: () => void): void;
509
+ on(event: 'error', handler: (err: Error) => void): void;
510
+ on(event: 'close', handler: () => void): void;
511
+ destroy(): void;
512
+ }
513
+ interface ServerResponse {
514
+ writeHead(code: number, headers?: Record<string, string>): void;
515
+ write(data: string): boolean;
516
+ end(data?: string): void;
517
+ headersSent: boolean;
518
+ } //#endregion
519
+ //#region src/host/config.d.ts
520
+
521
+ //# sourceMappingURL=index.d.ts.map
9
522
  interface VisualizerConfig {
10
- dataSource: 'auto' | 'codegraph' | 'lens';
523
+ dataSource: DataSourceType;
11
524
  requestTimeout: number;
12
525
  scanCacheTtl: number;
13
526
  scanCacheLimit: number;
@@ -15,26 +528,76 @@ interface VisualizerConfig {
15
528
  prerequisiteRetryDelay: number;
16
529
  watchDebounce: number;
17
530
  maxNodes: number;
531
+ allowedOrigins: string[];
532
+ panelMinHeight: number;
533
+ panelDefaultHeight: number;
18
534
  }
19
535
  declare const DEFAULT_CONFIG: VisualizerConfig;
536
+ /**
537
+ * Schemastery schema(cycle-146 T146-1)——与 `VisualizerConfig` 同形状的**加载时**校验器。
538
+ *
539
+ * ## 为什么必须有它
540
+ *
541
+ * 旧实现只导出 `resolveConfig`/`DEFAULT_CONFIG`:插件没有 Standard Schema 接口,于是
542
+ * ① cordis.yml 的 config 行没有声明式校验(错误要等 apply 内手动校验才报);
543
+ * ② 宿主设置 UI 无法渲染行内表单(dsh-context/dsh-ops 双插件的 `Config` 导出模式)。
544
+ *
545
+ * 官方规范(docs/user/develop/basic/config.md):插件导出 `Config` 类型 + 同名 Schemastery
546
+ * schema,默认值直接写在 schema 中;cordis 在插件加载时通过 schema 校验配置并填默认值。
547
+ *
548
+ * ## 约束:与 resolveConfig 的单一真源关系
549
+ *
550
+ * `resolveConfig` 的手写校验(正数/origin 模式/高度下界)保留——它是运行时防线,错误
551
+ * 信息更具体;schema 是加载时防线。两者必须同形状:`configSchemaContract.test.ts`
552
+ * 断言「schema 声明的默认值 === DEFAULT_CONFIG 字段值」,防止两处漂移。
553
+ */
554
+ declare const Config: Schema<any, any, "plain">;
20
555
  declare function resolveConfig(userConfig?: Partial<VisualizerConfig>): VisualizerConfig;
21
556
 
22
557
  //#endregion
23
558
  //#region src/host/security.d.ts
24
559
  //# sourceMappingURL=config.d.ts.map
25
- declare function setAllowedWorkspaceRoots(roots: string[]): void;
26
- declare function isPathAllowed(path: string): boolean;
560
+ /**
561
+ * Which host source produced the allowed roots. Reported by the workspace route so a
562
+ * "everything is 403" report can be diagnosed from outside the process instead of
563
+ * inferred from a silent 403 (see docs/需求分析.md §31.7).
564
+ */
565
+ type WorkspaceRootSource = 'registry' | 'sessions' | 'cwd' | 'unknown';
566
+ interface WorkspaceRootsSnapshot {
567
+ roots: string[];
568
+ source: WorkspaceRootSource;
569
+ }
570
+ declare class SecurityManager {
571
+ /** Raw paths as the host reported them; normalization happens at comparison time. */
572
+ private allowedWorkspaceRoots;
573
+ private rootSource;
574
+ setAllowedWorkspaceRoots(roots: string[], source?: WorkspaceRootSource): void;
575
+ /**
576
+ * Grow the allowlist instead of replacing it.
577
+ *
578
+ * The roots come from host services only (`workspaceRegistry` / `sessions`), never from a
579
+ * request, so widening is safe; shrinking is the dangerous direction because a transiently
580
+ * empty registry would deny every in-flight request (the §31.7 failure mode). A workspace
581
+ * removed at runtime therefore stays readable until the host restarts, which is the
582
+ * conservative choice for a local, read-only analysis plugin.
583
+ */
584
+ addAllowedWorkspaceRoots(roots: string[], source?: WorkspaceRootSource): void;
585
+ isPathAllowed(path: string): boolean;
586
+ /** Observable view of the allowlist (workspace route / tests). Never redacted: it is local-only. */
587
+ getSnapshot(): WorkspaceRootsSnapshot;
588
+ reset(): void;
589
+ }
590
+ declare function createSecurityManager(): SecurityManager;
27
591
 
28
592
  //#endregion
29
593
  //#region src/index.d.ts
30
594
  //# sourceMappingURL=security.d.ts.map
31
-
32
595
  declare const name = "dsh-codegraph-visualizer";
33
596
  declare const inject: string[];
34
- declare function apply(ctx: Context, userConfig?: Partial<VisualizerConfig>): void;
597
+ declare function apply(ctx: Context$1, userConfig?: Partial<VisualizerConfig>): Promise<void>;
35
598
 
36
599
  //#endregion
37
600
  //# sourceMappingURL=index.d.ts.map
38
601
 
39
- export { DEFAULT_CONFIG, PLUGIN_VERSION, VisualizerConfig, apply, inject, isPathAllowed, name, resolveConfig, setAllowedWorkspaceRoots };
602
+ export { Config, DEFAULT_CONFIG, PLUGIN_VERSION, SecurityManager, VisualizerConfig, apply, createSecurityManager, inject, name, resolveConfig };
40
603
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/generated/version.ts","../../src/host/config.ts","../../src/host/security.ts","../../src/index.ts"],"sourcesContent":null,"mappings":";;;cAAa,cAAA;;;;;UCAI,gBAAA;;;EDAJ,YAAA,EAAA,MAAc;;;;ECAV,aAAA,EAAA,MAAgB;EAWpB,QAAA,EAAA,MAAA;AAWb;AAA6B,cAXhB,cAWgB,EAXA,gBAWA;AAAsB,iBAAnC,aAAA,CAAmC,UAAA,CAAA,EAAR,OAAQ,CAAA,gBAAA,CAAA,CAAA,EAAoB,gBAApB;;;;;iBClBnC,wBAAA;iBAIA,aAAA;;;;;;ADRC,cEmBJ,IAAA,GFnBoB,0BAAA;AAWpB,cESA,MFAZ,EAAA,MAT4B,EAAA;AAWb,iBEAA,KAAA,CFAa,GAAA,EEAF,OFAE,EAAA,UAAA,CAAA,EEAoB,OFApB,CEA4B,gBFA5B,CAAA,CAAA,EAAA,IAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/generated/version.ts","../../src/types/index.ts","../../src/host/config.ts","../../src/host/security.ts","../../src/index.ts"],"sourcesContent":null,"mappings":"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"}