dsh-codegraph-visualizer 0.3.0 → 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.
package/dist/index.js CHANGED
@@ -6,9 +6,9 @@ import { inferLayerFromPath } from "./layerUtils-DDm-EsaD.js";
6
6
  import "./treeSitterExtractors-B1ybKNrC.js";
7
7
  import { TreeSitterAdapter, isTreeSitterRuntimePresent } from "./TreeSitterAdapter-C-EWy8br.js";
8
8
  import { FILTERED_EDGE_KINDS, isNoisePath, mapEdgeKind, mapNodeKind, mapRowsToGraphEdges, mapRowsToGraphNodes, normalizeRepoPath } from "./codeGraphRows-C7hqu35E.js";
9
- import "./nativeIndex-DlSpD611.js";
10
- import { closeAllDbConnections, countEdgesInDb, readFileOutlineFromDb, readNodeChildrenFromDb, readSymbolASTFromDb, readTopLevelNodesFromDb } from "./codeGraphDb-BT9nZCEO.js";
11
- import { CODEGRAPH_SOURCE, readEdgesForNodesFromDb, readEdgesFromDb, readFilesFromDb, readIncidentEdgesWithFilePathsFromDb, resolveDbPath, sortEdgesByKindGroup } from "./CodeGraphAdapter-eyrhs0K0.js";
9
+ import "./nativeIndex-CABbgERW.js";
10
+ import { closeAllDbConnections, countEdgesInDb, readFileOutlineFromDb, readNodeChildrenFromDb, readSymbolASTFromDb, readTopLevelNodesFromDb } from "./codeGraphDb-T6K3dK5D.js";
11
+ import { CODEGRAPH_SOURCE, readEdgesForNodesFromDb, readEdgesFromDb, readFilesFromDb, readIncidentEdgesWithFilePathsFromDb, resolveDbPath, sortEdgesByKindGroup } from "./CodeGraphAdapter-BNIK0xHU.js";
12
12
  import { defineTool } from "@deepseek-ai/dsh-tools";
13
13
  import { ToolCallId } from "@deepseek-ai/dsh-llm";
14
14
  import Schema from "@deepseek-ai/schemastery";
@@ -5895,11 +5895,8 @@ const PATH_EDGE_TYPE_DOMAIN = new Set([
5895
5895
  "composition"
5896
5896
  ]);
5897
5897
  /**
5898
-
5899
5898
  * 解析 `edgeTypes` 逗号列表:只保留域内类型;未提供或全部非法时返回 null(用默认读法)。
5900
-
5901
5899
  * 空集规则匹配不到任何边(璇玑图 §八),所以「全部非法」不能静默变成空集过滤。
5902
-
5903
5900
  */
5904
5901
  function parseEdgeTypes$1(raw) {
5905
5902
  if (!raw) return null;
@@ -5911,9 +5908,52 @@ function clampInt$1(value, min, max, fallback) {
5911
5908
  if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
5912
5909
  return Math.min(max, Math.max(min, Math.trunc(value)));
5913
5910
  }
5911
+ /** UI 摘要文本块上限(单条 content ≤ 300 字符)。 */
5912
+ const SUMMARY_MAX_CHARS = 300;
5913
+ /** 把一行摘要截到上限内并包成 content 形状。 */
5914
+ function summaryBlock(text) {
5915
+ const clipped = text.length > SUMMARY_MAX_CHARS ? `${text.slice(0, SUMMARY_MAX_CHARS - 1)}…` : text;
5916
+ return [{
5917
+ type: "text",
5918
+ text: clipped
5919
+ }];
5920
+ }
5921
+ /** meta 持久化行上限(tool/result.meta 不是日志:单工具 ≤10 键、单值 ≤200 字符)。 */
5922
+ const META_MAX_CHARS = 200;
5923
+ /** presentationMeta 的统一出口:把一行 meta 摘要截到持久化上限内。 */
5924
+ function metaText(text) {
5925
+ return text.length > META_MAX_CHARS ? `${text.slice(0, META_MAX_CHARS - 1)}…` : text;
5926
+ }
5927
+ /** 成功态 UI 摘要:只认 meta(value 通道);meta 缺席/非字符串 = undefined(UI 回退原始内容)。 */
5928
+ function successSummaryFromMeta(meta) {
5929
+ if (typeof meta !== "string" || meta === "") return void 0;
5930
+ return summaryBlock(meta);
5931
+ }
5932
+ /** 失败态一行摘要:压平错误投影的首条文本;投影为空 = undefined(UI 回退渲染原始错误文本)。 */
5933
+ function failureSummaryFromContent(content) {
5934
+ const first = (content ?? []).find((b) => typeof b === "object" && b !== null && typeof b.text === "string");
5935
+ if (!first) return void 0;
5936
+ const flat = first.text.replace(/\s+/g, " ").trim();
5937
+ return summaryBlock(flat.length > 0 ? `Failed: ${flat}` : "Failed.");
5938
+ }
5939
+ /**
5940
+ * presentResult 工厂:成功/失败标题 + UI 一行摘要。
5941
+ * 成功摘要只来自 meta(presentationMeta 从 value 投影),失败摘要只来自 result.content
5942
+ * (错误投影)——模型通道 render 的输出从不进入本函数,UI 通道 content 也从不进入 render。
5943
+ */
5944
+ function presentResultWithSummary(okTitle, failTitle) {
5945
+ return (_args, result) => {
5946
+ const content = result.isError ? failureSummaryFromContent(result.content) : successSummaryFromMeta(result.meta);
5947
+ return {
5948
+ card: "generic",
5949
+ title: result.isError ? failTitle : okTitle,
5950
+ ...content === void 0 ? {} : { content }
5951
+ };
5952
+ };
5953
+ }
5914
5954
  const GRAPH_CACHE_LIMIT = CACHE.GRAPH_CACHE_LIMIT;
5915
5955
  async function createGraphToolDeps() {
5916
- const [{ CodeGraphAdapter: CGA }, { LensAdapter: LA }] = await Promise.all([import("./CodeGraphAdapter-C8JvcS7m.js"), import("./LensAdapter-C9Saf_i_.js")]);
5956
+ const [{ CodeGraphAdapter: CGA }, { LensAdapter: LA }] = await Promise.all([import("./CodeGraphAdapter-CXj1hbdm.js"), import("./LensAdapter-C9Saf_i_.js")]);
5917
5957
  return {
5918
5958
  codegraphAdapter: new CGA(),
5919
5959
  lensAdapter: new LA(),
@@ -5922,15 +5962,10 @@ async function createGraphToolDeps() {
5922
5962
  };
5923
5963
  }
5924
5964
  /**
5925
-
5926
5965
  * 原生图适配器的模块级单例(cycle-131 · P0 第二层修复)。
5927
-
5928
5966
  *
5929
-
5930
5967
  * 组装一次全 host 复用(Node fs + TreeSitterAdapter 各自内部已单例化 wasm);
5931
-
5932
5968
  * 失败结果也缓存(null = 环境不支持,避免每次调用重试)。
5933
-
5934
5969
  */
5935
5970
  let nativeAdapterSingleton;
5936
5971
  async function ensureNativeAdapter() {
@@ -5976,9 +6011,9 @@ async function fetchMergedGraph(invoke, repoId, source = "both", deps) {
5976
6011
  const allowNativeFallback = merged.nodes.length === 0 && d.nativeAdapter !== null && (source === "auto" || source === "both");
5977
6012
  if (allowNativeFallback) try {
5978
6013
  const [{ readGraphFromDbPaged }, { mapRowsToGraphNodes: mapRowsToGraphNodes$1, mapRowsToGraphEdges: mapRowsToGraphEdges$1 }, { resolveNativeIndexPath, readNativeIndexMeta, writeNativeIndex }] = await Promise.all([
5979
- import("./codeGraphDb-Bg7bWud2.js"),
6014
+ import("./codeGraphDb-B-vpZmpm.js"),
5980
6015
  import("./codeGraphRows-BhZX34uB.js"),
5981
- import("./nativeIndex-Cx7RLXUp.js")
6016
+ import("./nativeIndex-esaDOsq8.js")
5982
6017
  ]);
5983
6018
  try {
5984
6019
  const indexPath = resolveNativeIndexPath(repoId);
@@ -6196,31 +6231,18 @@ async function executeGraphImpact(args, invoke) {
6196
6231
  });
6197
6232
  }
6198
6233
  /**
6199
-
6200
6234
  * `graph_slice` 的执行体(cycle-135:多维视图切片)。
6201
-
6202
6235
  *
6203
-
6204
6236
  * 四个视图共用一条链路:先 `fetchMergedGraph` 取合并图,再交给 `graphSlice` 统一切片。
6205
-
6206
6237
  * 时序/所有权视图的**外部事实**(commit 历史、blame)通过两个可选字符串参数注入:
6207
-
6208
6238
  * - `commitLog`:`git log --name-only --format=%x1e%H%x1f%ct` 的原始输出;
6209
-
6210
6239
  * - `blameLog`:`git blame --porcelain <file>` 的原始输出。
6211
-
6212
6240
  *
6213
-
6214
6241
  * 为什么让模型/调用方注入原始文本而不是在工具里直接跑 git:本工具是**读图**工具,
6215
-
6216
6242
  * 与其余 `graph_*` 一样只依赖 `invoke` 上游通道;git 子进程属于宿主 `/churn`、
6217
-
6218
6243
  * `/blame` 一类的分析路由职责(`gitChurn.ts` 已有实现)。这样切片逻辑保持纯函数、
6219
-
6220
6244
  * 可单测,也避免在工具层再引入一条 git 依赖。缺这两个参数时,对应视图走**显式降级**
6221
-
6222
6245
  * (`viewDataAvailable: false` + `reason`),而不是编造一份缺维度的图。
6223
-
6224
6246
  */
6225
6247
  async function executeGraphSlice(args, invoke) {
6226
6248
  const data = await fetchMergedGraph(invoke, args.repoId);
@@ -6260,7 +6282,12 @@ const createGraphTools = async (ctx, options = {}) => {
6260
6282
  } },
6261
6283
  output: {
6262
6284
  schema: { type: "json" },
6263
- render: renderGraphStatus
6285
+ render: renderGraphStatus,
6286
+ presentationMeta: (_args, value) => {
6287
+ const v = value;
6288
+ const s = v?.sources;
6289
+ return metaText(`status=${String(v?.status ?? "unknown")}, nodes=${String(v?.nodeCount ?? 0)}, edges=${String(v?.edgeCount ?? 0)}, sources: codegraph=${s?.codegraph === true ? "✓" : "✗"} lens=${s?.lens === true ? "✓" : "✗"}`);
6290
+ }
6264
6291
  },
6265
6292
  presentCall: (args) => {
6266
6293
  const a = args;
@@ -6271,10 +6298,7 @@ const createGraphTools = async (ctx, options = {}) => {
6271
6298
  rawInput: { repoId: a.repoId }
6272
6299
  };
6273
6300
  },
6274
- presentResult: (_args, result) => ({
6275
- card: "generic",
6276
- title: result.isError ? "Graph status failed" : "Graph status"
6277
- }),
6301
+ presentResult: presentResultWithSummary("Graph status", "Graph status failed"),
6278
6302
  execute: (args) => executeGraphStatus(args, invoke, deps)
6279
6303
  });
6280
6304
  const graphData = defineTool({
@@ -6299,7 +6323,15 @@ const createGraphTools = async (ctx, options = {}) => {
6299
6323
  },
6300
6324
  output: {
6301
6325
  schema: { type: "json" },
6302
- render: renderGraphData
6326
+ render: renderGraphData,
6327
+ presentationMeta: (_args, value) => {
6328
+ const d = value;
6329
+ if (!d) return "empty graph";
6330
+ const x = d.metadata.xuanji;
6331
+ const mode = x ? x.applied ? `incremental delta (+${String(x.addedPaths ?? 0)} paths)` : "full rebuild" : "no delta signal";
6332
+ const layer = d.metadata.graphLayer === void 0 ? "" : ` · layer=${String(d.metadata.graphLayer)}`;
6333
+ return metaText(`${String(d.metadata.nodeCount)} node(s) / ${String(d.metadata.edgeCount)} edge(s) · ${mode}${layer}`);
6334
+ }
6303
6335
  },
6304
6336
  presentCall: (args) => {
6305
6337
  const a = args;
@@ -6313,10 +6345,7 @@ const createGraphTools = async (ctx, options = {}) => {
6313
6345
  }
6314
6346
  };
6315
6347
  },
6316
- presentResult: (_args, result) => ({
6317
- card: "generic",
6318
- title: result.isError ? "Graph fetch failed" : "Code graph fetched"
6319
- }),
6348
+ presentResult: presentResultWithSummary("Code graph fetched", "Graph fetch failed"),
6320
6349
  execute: (args) => executeGraphData(args, invoke, emitUpdate, emitData, graphCache, deps, xuanjiPool)
6321
6350
  });
6322
6351
  const graphSymbol = defineTool({
@@ -6329,7 +6358,12 @@ const createGraphTools = async (ctx, options = {}) => {
6329
6358
  } },
6330
6359
  output: {
6331
6360
  schema: { type: "json" },
6332
- render: renderGraphSymbol
6361
+ render: renderGraphSymbol,
6362
+ presentationMeta: (_args, value) => {
6363
+ const v = value;
6364
+ if (!v) return "Symbol not found.";
6365
+ return metaText(`${String(v.name ?? v.symbolId ?? "?")} (${String(v.category ?? "unknown")}) @ ${String(v.file ?? "?")}:${String(v.line ?? "?")}`);
6366
+ }
6333
6367
  },
6334
6368
  presentCall: (args) => {
6335
6369
  const a = args;
@@ -6340,10 +6374,7 @@ const createGraphTools = async (ctx, options = {}) => {
6340
6374
  rawInput: { symbolId: a.symbolId }
6341
6375
  };
6342
6376
  },
6343
- presentResult: (_args, result) => ({
6344
- card: "generic",
6345
- title: result.isError ? "Symbol resolution failed" : "Symbol resolved"
6346
- }),
6377
+ presentResult: presentResultWithSummary("Symbol resolved", "Symbol resolution failed"),
6347
6378
  execute: (args) => executeGraphSymbol(args, invoke)
6348
6379
  });
6349
6380
  const graphImpact = defineTool({
@@ -6356,7 +6387,13 @@ const createGraphTools = async (ctx, options = {}) => {
6356
6387
  } },
6357
6388
  output: {
6358
6389
  schema: { type: "json" },
6359
- render: renderGraphImpact
6390
+ render: renderGraphImpact,
6391
+ presentationMeta: (_args, value) => {
6392
+ const v = value;
6393
+ const n = v?.affected?.length ?? 0;
6394
+ if (n === 0) return "No affected symbols.";
6395
+ return metaText(`${String(n)} symbol(s) affected (depth ${String(v?.depth ?? 0)}): ${v?.affected?.slice(0, 5).join(", ") ?? ""}`);
6396
+ }
6360
6397
  },
6361
6398
  presentCall: (args) => {
6362
6399
  const a = args;
@@ -6367,10 +6404,7 @@ const createGraphTools = async (ctx, options = {}) => {
6367
6404
  rawInput: { symbolId: a.symbolId }
6368
6405
  };
6369
6406
  },
6370
- presentResult: (_args, result) => ({
6371
- card: "generic",
6372
- title: result.isError ? "Impact analysis failed" : "Impact analyzed"
6373
- }),
6407
+ presentResult: presentResultWithSummary("Impact analyzed", "Impact analysis failed"),
6374
6408
  execute: (args) => executeGraphImpact(args, invoke)
6375
6409
  });
6376
6410
  const graphPathFind = defineTool({
@@ -6411,6 +6445,12 @@ const createGraphTools = async (ctx, options = {}) => {
6411
6445
  type: "text",
6412
6446
  text: `${TOOL_MESSAGES.PATH_FOUND?.en ?? "Path found"} (${v.length} ${TOOL_MESSAGES.HOPS?.en ?? "hops"}): ${v.path.join(" → ")}`
6413
6447
  }];
6448
+ },
6449
+ presentationMeta: (_args, value) => {
6450
+ const v = value;
6451
+ if (v?.truncated) return "Graph too large for path search.";
6452
+ if (!v || !v.path || v.path.length === 0) return "No path found.";
6453
+ return metaText(`${String(v.length)} hops: ${v.path.join(" → ")}`);
6414
6454
  }
6415
6455
  },
6416
6456
  presentCall: (args) => {
@@ -6425,10 +6465,7 @@ const createGraphTools = async (ctx, options = {}) => {
6425
6465
  }
6426
6466
  };
6427
6467
  },
6428
- presentResult: (_args, result) => ({
6429
- card: "generic",
6430
- title: result.isError ? "Path search failed" : "Call path"
6431
- }),
6468
+ presentResult: presentResultWithSummary("Call path", "Path search failed"),
6432
6469
  execute: async (args) => {
6433
6470
  const a = args;
6434
6471
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -6511,6 +6548,13 @@ const createGraphTools = async (ctx, options = {}) => {
6511
6548
  type: "text",
6512
6549
  text: `${v.total ?? v.paths.length} path(s)${suffix}${next}\n${lines.join("\n")}`
6513
6550
  }];
6551
+ },
6552
+ presentationMeta: (_args, value) => {
6553
+ const v = value;
6554
+ if (!v || !v.paths || v.paths.length === 0) return "No path found.";
6555
+ const first = v.paths[0]?.join(" → ") ?? "";
6556
+ const cursor = v.nextCursor === null || v.nextCursor === void 0 ? "" : `, nextCursor=${String(v.nextCursor)}`;
6557
+ return metaText(`${String(v.total ?? v.paths.length)} path(s)${v.truncated ? " (truncated)" : ""}${cursor}; first: ${first}`);
6514
6558
  }
6515
6559
  },
6516
6560
  presentCall: (args) => {
@@ -6525,10 +6569,7 @@ const createGraphTools = async (ctx, options = {}) => {
6525
6569
  }
6526
6570
  };
6527
6571
  },
6528
- presentResult: (_args, result) => ({
6529
- card: "generic",
6530
- title: result.isError ? "Path enumeration failed" : "Paths enumerated"
6531
- }),
6572
+ presentResult: presentResultWithSummary("Paths enumerated", "Path enumeration failed"),
6532
6573
  execute: async (args) => {
6533
6574
  const a = args;
6534
6575
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -6556,29 +6597,17 @@ const createGraphTools = async (ctx, options = {}) => {
6556
6597
  }
6557
6598
  });
6558
6599
  /**
6559
-
6560
6600
  * 路径模式 ρ(cycle-134):`graph_path_enumerate` 的**序列约束**版本。
6561
-
6562
6601
  *
6563
-
6564
6602
  * 与 `graph_path_enumerate` 的差别只在表达能力:
6565
-
6566
6603
  * - 后者 `edgeTypes` 是扁平集合(「每步走这些之一」);
6567
-
6568
6604
  * - 本工具 `pattern` 是边类型**序列正则**,能表达「先 call 再 import 再 dependency」
6569
-
6570
6605
  * 这类跨视图路径(研究方案 §4 的 `P = (v_s, ρ, v_t)`)。
6571
-
6572
6606
  *
6573
-
6574
6607
  * 为什么仍是独立工具而不合并进 `graph_path_enumerate`:两者的**参数语义不同**
6575
-
6576
6608
  * (`edgeTypes` 是集合语义、`pattern` 是序列语义),合并成一个可选参数会让模型
6577
-
6578
6609
  * 无法从参数名判断该传哪个,且两者同时给出时的优先级无自然定义。模型侧的选择表
6579
-
6580
6610
  * 写在 `src/host/skills.ts` 的 SKILL_CONTENT 第 8 条。
6581
-
6582
6611
  */
6583
6612
  const graphPathPattern = defineTool({
6584
6613
  name: "graph_path_pattern",
@@ -6684,6 +6713,20 @@ const createGraphTools = async (ctx, options = {}) => {
6684
6713
  type: "text",
6685
6714
  text: `${head}\n${v.total ?? v.paths.length} path(s)${suffix}${next}\n${lines.join("\n")}`
6686
6715
  }];
6716
+ },
6717
+ presentationMeta: (_args, value) => {
6718
+ const v = value;
6719
+ if (v?.error) return `Pattern error: ${v.error}`;
6720
+ const unknown = v?.unknownEdgeTypes ?? [];
6721
+ if (unknown.length > 0) return `Unknown edge type(s): ${unknown.join(", ")}.`;
6722
+ if (!v || !v.paths) return "Pattern evaluation failed.";
6723
+ if (v.paths.length === 0) {
6724
+ const degraded = v.temporal?.requested === true && v.temporal.available === false;
6725
+ return degraded ? `No paths; temporal slice unavailable (${String(v.reason ?? "unknown")}).` : "No paths matched the pattern.";
6726
+ }
6727
+ const first = v.paths[0]?.join(" → ") ?? "";
6728
+ const cursor = v.nextCursor === null || v.nextCursor === void 0 ? "" : `, nextCursor=${String(v.nextCursor)}`;
6729
+ return metaText(`pattern "${String(v.pattern ?? "")}": ${String(v.total ?? v.paths.length)} path(s)${v.truncated ? " (truncated)" : ""}${cursor}; first: ${first}`);
6687
6730
  }
6688
6731
  },
6689
6732
  presentCall: (args) => {
@@ -6699,10 +6742,7 @@ const createGraphTools = async (ctx, options = {}) => {
6699
6742
  }
6700
6743
  };
6701
6744
  },
6702
- presentResult: (_args, result) => ({
6703
- card: "generic",
6704
- title: result.isError ? "Path pattern failed" : "Pattern paths"
6705
- }),
6745
+ presentResult: presentResultWithSummary("Pattern paths", "Path pattern failed"),
6706
6746
  execute: async (args) => {
6707
6747
  const a = args;
6708
6748
  const merged = await fetchMergedGraph(invoke, a.repoId);
@@ -6823,6 +6863,13 @@ const createGraphTools = async (ctx, options = {}) => {
6823
6863
  type: "text",
6824
6864
  text: `${v.total ?? v.paths.length} cycle(s)${suffix}${next}\n${lines.join("\n")}`
6825
6865
  }];
6866
+ },
6867
+ presentationMeta: (_args, value) => {
6868
+ const v = value;
6869
+ if (!v || !v.paths || v.paths.length === 0) return "No dependency cycles detected.";
6870
+ const first3 = v.paths.slice(0, 3).map((c, i) => `${String(i + 1)}) ${c.join(" → ")}`).join("; ");
6871
+ const cursor = v.nextCursor === null || v.nextCursor === void 0 ? "" : `, nextCursor=${String(v.nextCursor)}`;
6872
+ return metaText(`${String(v.total ?? v.paths.length)} cycle(s)${v.truncated ? " (truncated)" : ""}${cursor}: ${first3}`);
6826
6873
  }
6827
6874
  },
6828
6875
  presentCall: (args) => {
@@ -6834,10 +6881,7 @@ const createGraphTools = async (ctx, options = {}) => {
6834
6881
  rawInput: { repoId: a.repoId }
6835
6882
  };
6836
6883
  },
6837
- presentResult: (_args, result) => ({
6838
- card: "generic",
6839
- title: result.isError ? "Cycle enumeration failed" : "Dependency cycles"
6840
- }),
6884
+ presentResult: presentResultWithSummary("Dependency cycles", "Cycle enumeration failed"),
6841
6885
  execute: async (args) => {
6842
6886
  const a = args;
6843
6887
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -6881,6 +6925,11 @@ const createGraphTools = async (ctx, options = {}) => {
6881
6925
  type: "text",
6882
6926
  text: `Architecture Health: ${v.overall}/100\n Coupling: ${v.coupling}/100\n Cohesion: ${v.cohesion}/100\n Cyclic Dep Rate: ${v.cyclicDependencyRate}/100\n Modularity: ${v.modularity}/100`
6883
6927
  }];
6928
+ },
6929
+ presentationMeta: (_args, value) => {
6930
+ const v = value;
6931
+ if (!v) return "Insufficient data for health scoring.";
6932
+ return metaText(`overall ${String(v.overall)}/100 (coupling ${String(v.coupling)}, cohesion ${String(v.cohesion)}, cyclic-dep ${String(v.cyclicDependencyRate)}, modularity ${String(v.modularity)}) — ${v.overall >= 70 ? "healthy" : v.overall >= 40 ? "degraded" : "poor"}`);
6884
6933
  }
6885
6934
  },
6886
6935
  presentCall: (args) => {
@@ -6892,10 +6941,7 @@ const createGraphTools = async (ctx, options = {}) => {
6892
6941
  rawInput: { repoId: a.repoId }
6893
6942
  };
6894
6943
  },
6895
- presentResult: (_args, result) => ({
6896
- card: "generic",
6897
- title: result.isError ? "Health scoring failed" : "Health score"
6898
- }),
6944
+ presentResult: presentResultWithSummary("Health score", "Health scoring failed"),
6899
6945
  execute: async (args) => {
6900
6946
  const a = args;
6901
6947
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -6936,6 +6982,11 @@ const createGraphTools = async (ctx, options = {}) => {
6936
6982
  type: "text",
6937
6983
  text: `${v.length} ${TOOL_MESSAGES.RULE_VIOLATIONS?.en ?? "rule violations:"}\n${lines.join("\n")}`
6938
6984
  }];
6985
+ },
6986
+ presentationMeta: (_args, value) => {
6987
+ const v = value;
6988
+ if (!v || v.length === 0) return "No rule violations.";
6989
+ return metaText(`${String(v.length)} violation(s): ${v.slice(0, 3).map((r) => `[${r.severity}] ${r.message}`).join("; ")}`);
6939
6990
  }
6940
6991
  },
6941
6992
  presentCall: (args) => {
@@ -6951,10 +7002,7 @@ const createGraphTools = async (ctx, options = {}) => {
6951
7002
  }
6952
7003
  };
6953
7004
  },
6954
- presentResult: (_args, result) => ({
6955
- card: "generic",
6956
- title: result.isError ? "Rules check failed" : "Rules checked"
6957
- }),
7005
+ presentResult: presentResultWithSummary("Rules checked", "Rules check failed"),
6958
7006
  execute: async (args) => {
6959
7007
  const a = args;
6960
7008
  const data = await fetchMergedGraph(invoke, a.repoId, "both", deps);
@@ -7008,6 +7056,12 @@ const createGraphTools = async (ctx, options = {}) => {
7008
7056
  type: "text",
7009
7057
  text: `Focus on ${v.symbolId}: ${v.neighbors?.length ?? 0} direct neighbors\n ${v.neighbors?.slice(0, 15).join(", ") ?? ""}`
7010
7058
  }];
7059
+ },
7060
+ presentationMeta: (_args, value) => {
7061
+ const v = value;
7062
+ if (!v) return "Symbol not found in graph.";
7063
+ const n = v.neighbors?.length ?? 0;
7064
+ return metaText(n === 0 ? `${String(v.symbolId)}: 0 direct neighbors` : `${String(v.symbolId)}: ${String(n)} direct neighbor(s), e.g. ${v.neighbors?.slice(0, 3).join(", ") ?? ""}`);
7011
7065
  }
7012
7066
  },
7013
7067
  presentCall: (args) => {
@@ -7019,10 +7073,7 @@ const createGraphTools = async (ctx, options = {}) => {
7019
7073
  rawInput: { symbolId: a.symbolId }
7020
7074
  };
7021
7075
  },
7022
- presentResult: (_args, result) => ({
7023
- card: "generic",
7024
- title: result.isError ? "Focus failed" : "Symbol neighborhood"
7025
- }),
7076
+ presentResult: presentResultWithSummary("Symbol neighborhood", "Focus failed"),
7026
7077
  execute: async (args) => {
7027
7078
  const a = args;
7028
7079
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -7080,6 +7131,11 @@ const createGraphTools = async (ctx, options = {}) => {
7080
7131
  type: "text",
7081
7132
  text: `${seedLine}${meta}\n${v.text}`
7082
7133
  }];
7134
+ },
7135
+ presentationMeta: (_args, value) => {
7136
+ const v = value;
7137
+ if (!v || !v.text) return "No seed matched the query.";
7138
+ return metaText(`${String(v.seeds?.length ?? 0)} seed(s), ${String(v.nodeCount ?? 0)} node(s) / ${String(v.edgeCount ?? 0)} edge(s) in subgraph, ${String(v.tokens ?? 0)} tokens${v.truncated === true ? ` (truncated: ${String(v.reason ?? "unknown")})` : ""}`);
7083
7139
  }
7084
7140
  },
7085
7141
  presentCall: (args) => {
@@ -7094,10 +7150,7 @@ const createGraphTools = async (ctx, options = {}) => {
7094
7150
  }
7095
7151
  };
7096
7152
  },
7097
- presentResult: (_args, result) => ({
7098
- card: "generic",
7099
- title: result.isError ? "Graph query failed" : "Graph query result"
7100
- }),
7153
+ presentResult: presentResultWithSummary("Graph query result", "Graph query failed"),
7101
7154
  execute: async (args) => {
7102
7155
  const a = args;
7103
7156
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -7192,6 +7245,22 @@ const createGraphTools = async (ctx, options = {}) => {
7192
7245
  type: "text",
7193
7246
  text: lines.join("\n")
7194
7247
  }];
7248
+ },
7249
+ presentationMeta: (_args, value) => {
7250
+ const v = value;
7251
+ if (!v || v.loaded !== true) return "Graph layer not loaded for this repo yet.";
7252
+ const g = v.graph ?? {
7253
+ nodes: 0,
7254
+ edges: 0,
7255
+ version: 0
7256
+ };
7257
+ const c = v.changeLog ?? {
7258
+ pending: 0,
7259
+ dropped: 0,
7260
+ drained: null
7261
+ };
7262
+ const stale = (v.rules ?? []).reduce((sum, r) => sum + r.counters.stale, 0);
7263
+ return metaText(`loaded, nodes=${String(g.nodes)} edges=${String(g.edges)} version=${String(g.version)}; changeLog pending=${String(c.pending)} dropped=${String(c.dropped)}${c.drained === null ? "" : ` drained=${String(c.drained)}`}; stale index entries=${String(stale)}${v.incrementalIdle === true ? "; incremental pipeline dormant" : ""}`);
7195
7264
  }
7196
7265
  },
7197
7266
  presentCall: (args) => {
@@ -7203,10 +7272,7 @@ const createGraphTools = async (ctx, options = {}) => {
7203
7272
  rawInput: { repoId: a.repoId }
7204
7273
  };
7205
7274
  },
7206
- presentResult: (_args, result) => ({
7207
- card: "generic",
7208
- title: result.isError ? "Integrity check failed" : "Graph integrity"
7209
- }),
7275
+ presentResult: presentResultWithSummary("Graph integrity", "Integrity check failed"),
7210
7276
  execute: async (args) => {
7211
7277
  const a = args;
7212
7278
  try {
@@ -7273,6 +7339,11 @@ const createGraphTools = async (ctx, options = {}) => {
7273
7339
  type: "text",
7274
7340
  text: lines.join("\n")
7275
7341
  }];
7342
+ },
7343
+ presentationMeta: (_args, value) => {
7344
+ const v = value;
7345
+ if (!v || !v.available) return `Slice unavailable: ${String(v?.reason ?? "unknown reason")}`;
7346
+ return metaText(`${String(v.view)} @ ${String(v.granularity)}: ${String(v.nodes.length)} node(s), ${String(v.edges.length)} edge(s), ${String(Object.keys(v.labels).length)} label(s)${v.viewDataAvailable ? "" : " (view data unavailable)"}`);
7276
7347
  }
7277
7348
  },
7278
7349
  presentCall: (args) => {
@@ -7288,10 +7359,7 @@ const createGraphTools = async (ctx, options = {}) => {
7288
7359
  }
7289
7360
  };
7290
7361
  },
7291
- presentResult: (_args, result) => ({
7292
- card: "generic",
7293
- title: result.isError ? "Graph slice failed" : "Graph slice"
7294
- }),
7362
+ presentResult: presentResultWithSummary("Graph slice", "Graph slice failed"),
7295
7363
  execute: async (args) => {
7296
7364
  const slice = await executeGraphSlice(args, invoke);
7297
7365
  return toJsonValue(slice);
@@ -7347,6 +7415,12 @@ const createGraphTools = async (ctx, options = {}) => {
7347
7415
  type: "text",
7348
7416
  text: lines.join("\n")
7349
7417
  }];
7418
+ },
7419
+ presentationMeta: (_args, value) => {
7420
+ const v = value;
7421
+ if (!v) return "View partition unavailable.";
7422
+ const counts = Object.entries(v.viewCounts ?? {}).map(([k, n]) => `${k}=${String(n)}`).join(", ");
7423
+ return metaText(`${String(v.nodes?.length ?? 0)} node(s) / ${String(v.edges?.length ?? 0)} edge(s) partitioned; view counts: ${counts || "none"}${v.domain ? `; ${String(v.domain.domainCount)} domain community(ies)` : ""}`);
7350
7424
  }
7351
7425
  },
7352
7426
  presentCall: (args) => {
@@ -7361,10 +7435,7 @@ const createGraphTools = async (ctx, options = {}) => {
7361
7435
  }
7362
7436
  };
7363
7437
  },
7364
- presentResult: (_args, result) => ({
7365
- card: "generic",
7366
- title: result.isError ? "View partition failed" : "View partition Π"
7367
- }),
7438
+ presentResult: presentResultWithSummary("View partition Π", "View partition failed"),
7368
7439
  execute: async (args) => {
7369
7440
  const a = args;
7370
7441
  const data = await fetchMergedGraph(invoke, a.repoId);
@@ -7437,7 +7508,7 @@ const createGraphTools = async (ctx, options = {}) => {
7437
7508
 
7438
7509
  //#endregion
7439
7510
  //#region src/generated/version.ts
7440
- const PLUGIN_VERSION = "0.3.0";
7511
+ const PLUGIN_VERSION = "0.3.1";
7441
7512
 
7442
7513
  //#endregion
7443
7514
  //#region src/host/config.ts
@@ -10457,7 +10528,7 @@ const resolveIndexDbPath = async (workspacePath) => {
10457
10528
  layer: "upstream"
10458
10529
  };
10459
10530
  try {
10460
- const { resolveNativeIndexPath } = await import("./nativeIndex-Cx7RLXUp.js");
10531
+ const { resolveNativeIndexPath } = await import("./nativeIndex-esaDOsq8.js");
10461
10532
  return {
10462
10533
  dbPath: resolveNativeIndexPath(workspacePath),
10463
10534
  layer: "native"
@@ -11392,7 +11463,7 @@ function registerManageDeleteRoute(rc) {
11392
11463
  const pathInput = extractStringField(parsed, "path", VALIDATION.MAX_PATH_LENGTH);
11393
11464
  const deletePath = await resolveAndValidatePath(pathInput, ctx, deps, req, res, corsConfig);
11394
11465
  if (deletePath === null) return;
11395
- const { deleteNativeIndex } = await import("./nativeIndex-Cx7RLXUp.js");
11466
+ const { deleteNativeIndex } = await import("./nativeIndex-esaDOsq8.js");
11396
11467
  const deleted = deleteNativeIndex(deletePath);
11397
11468
  if (!deleted) {
11398
11469
  sendJson(res, 200, {
@@ -11496,7 +11567,7 @@ function registerManageMetricsRoute(rc) {
11496
11567
  const upstreamDbPath = resolveDbPath(workspacePath);
11497
11568
  if (existsSync(upstreamDbPath)) dbPath = upstreamDbPath;
11498
11569
  else try {
11499
- const { resolveNativeIndexPath } = await import("./nativeIndex-Cx7RLXUp.js");
11570
+ const { resolveNativeIndexPath } = await import("./nativeIndex-esaDOsq8.js");
11500
11571
  const nativePath = resolveNativeIndexPath(workspacePath);
11501
11572
  if (existsSync(nativePath)) dbPath = nativePath;
11502
11573
  } catch (e) {
@@ -11511,7 +11582,7 @@ function registerManageMetricsRoute(rc) {
11511
11582
  }, req, corsConfig);
11512
11583
  return;
11513
11584
  }
11514
- const { readGraphFromDbPaged } = await import("./codeGraphDb-Bg7bWud2.js");
11585
+ const { readGraphFromDbPaged } = await import("./codeGraphDb-B-vpZmpm.js");
11515
11586
  const { mapRowsToGraphNodes: mapRowsToGraphNodes$1, mapRowsToGraphEdges: mapRowsToGraphEdges$1 } = await import("./codeGraphRows-BhZX34uB.js");
11516
11587
  const MAX_NODES = METRICS.MAX_NODES;
11517
11588
  const MAX_EDGES = METRICS.MAX_EDGES;
@@ -11549,7 +11620,7 @@ function registerManageMetricsRoute(rc) {
11549
11620
  const truncated = !readExhausted || nodesTotal !== nodesSampled || edgesTotal !== edgesSampled;
11550
11621
  let coverage = null;
11551
11622
  try {
11552
- const { readNativeIndexCoverage } = await import("./nativeIndex-Cx7RLXUp.js");
11623
+ const { readNativeIndexCoverage } = await import("./nativeIndex-esaDOsq8.js");
11553
11624
  coverage = readNativeIndexCoverage(workspacePath);
11554
11625
  } catch {
11555
11626
  coverage = null;
@@ -12925,10 +12996,10 @@ function clampInt(v, min, max, dflt) {
12925
12996
  async function readIndexGraph(workspacePath) {
12926
12997
  try {
12927
12998
  const [{ resolveDbPath: resolveDbPath$1 }, { readGraphFromDb }, rows, native] = await Promise.all([
12928
- import("./CodeGraphAdapter-C8JvcS7m.js"),
12929
- import("./codeGraphDb-Bg7bWud2.js"),
12999
+ import("./CodeGraphAdapter-CXj1hbdm.js"),
13000
+ import("./codeGraphDb-B-vpZmpm.js"),
12930
13001
  import("./codeGraphRows-BhZX34uB.js"),
12931
- import("./nativeIndex-Cx7RLXUp.js")
13002
+ import("./nativeIndex-esaDOsq8.js")
12932
13003
  ]);
12933
13004
  let dbPath = resolveDbPath$1(workspacePath);
12934
13005
  if (!existsSync(dbPath)) try {
@@ -13459,14 +13530,14 @@ async function readGraphFromIndex(workspacePath) {
13459
13530
  const upstreamDbPath = resolveDbPath(workspacePath);
13460
13531
  if (existsSync(upstreamDbPath)) dbPath = upstreamDbPath;
13461
13532
  else try {
13462
- const { resolveNativeIndexPath } = await import("./nativeIndex-Cx7RLXUp.js");
13533
+ const { resolveNativeIndexPath } = await import("./nativeIndex-esaDOsq8.js");
13463
13534
  const nativePath = resolveNativeIndexPath(workspacePath);
13464
13535
  if (existsSync(nativePath)) dbPath = nativePath;
13465
13536
  } catch (e) {
13466
13537
  log$9.warn("views route: native index path rejected", e);
13467
13538
  }
13468
13539
  if (!dbPath) return null;
13469
- const { readGraphFromDbPaged } = await import("./codeGraphDb-Bg7bWud2.js");
13540
+ const { readGraphFromDbPaged } = await import("./codeGraphDb-B-vpZmpm.js");
13470
13541
  const { mapRowsToGraphNodes: mapRowsToGraphNodes$1, mapRowsToGraphEdges: mapRowsToGraphEdges$1 } = await import("./codeGraphRows-BhZX34uB.js");
13471
13542
  let cursor = null;
13472
13543
  const allDbNodes = [];
@@ -13854,7 +13925,7 @@ async function buildIncrementalUpdate(input) {
13854
13925
  }
13855
13926
  let rows = readFilesFromDb(dbPath, changedFiles);
13856
13927
  if (!rows) try {
13857
- const { resolveNativeIndexPath } = await import("./nativeIndex-Cx7RLXUp.js");
13928
+ const { resolveNativeIndexPath } = await import("./nativeIndex-esaDOsq8.js");
13858
13929
  const nativePath = resolveNativeIndexPath(workspacePath);
13859
13930
  rows = readFilesFromDb(nativePath, changedFiles);
13860
13931
  if (rows) log$5.info("incremental update using native index", { changedFiles: changedFiles.length });
@@ -14849,37 +14920,45 @@ async function apply(ctx, userConfig) {
14849
14920
  nativeWorkspaceRoot: primaryWorkspace
14850
14921
  });
14851
14922
  ctx.effect(() => {
14852
- const d1 = ctx.tools.register(graphStatus);
14853
- const d2 = ctx.tools.register(graphData);
14854
- const d3 = ctx.tools.register(graphSymbol);
14855
- const d4 = ctx.tools.register(graphImpact);
14856
- const d5 = ctx.tools.register(graphPathFind);
14857
- const d6 = ctx.tools.register(graphHealth);
14858
- const d7 = ctx.tools.register(graphRulesCheck);
14859
- const d8 = ctx.tools.register(graphFocus);
14860
- const d9 = ctx.tools.register(graphPathEnumerate);
14861
- const d10 = ctx.tools.register(graphCycles);
14862
- const d11 = ctx.tools.register(graphQuery);
14863
- const d12 = ctx.tools.register(graphIntegrity);
14864
- const d13 = ctx.tools.register(graphPathPattern);
14865
- const d14 = ctx.tools.register(graphSlice$1);
14866
- const d15 = ctx.tools.register(graphViews);
14923
+ const disposers = [];
14924
+ const failed$2 = [];
14925
+ const safeRegister = (label, register) => {
14926
+ try {
14927
+ const d = register();
14928
+ if (typeof d === "function") disposers.push(d);
14929
+ else failed$2.push(`${label} (register returned no disposer)`);
14930
+ } catch (err) {
14931
+ failed$2.push(`${label} (${err instanceof Error ? err.message : String(err)})`);
14932
+ }
14933
+ };
14934
+ safeRegister("graph_status", () => ctx.tools.register(graphStatus));
14935
+ safeRegister("graph_data", () => ctx.tools.register(graphData));
14936
+ safeRegister("graph_symbol", () => ctx.tools.register(graphSymbol));
14937
+ safeRegister("graph_impact", () => ctx.tools.register(graphImpact));
14938
+ safeRegister("graph_path_find", () => ctx.tools.register(graphPathFind));
14939
+ safeRegister("graph_health", () => ctx.tools.register(graphHealth));
14940
+ safeRegister("graph_rules_check", () => ctx.tools.register(graphRulesCheck));
14941
+ safeRegister("graph_focus", () => ctx.tools.register(graphFocus));
14942
+ safeRegister("graph_path_enumerate", () => ctx.tools.register(graphPathEnumerate));
14943
+ safeRegister("graph_cycles", () => ctx.tools.register(graphCycles));
14944
+ safeRegister("graph_query", () => ctx.tools.register(graphQuery));
14945
+ safeRegister("graph_integrity", () => ctx.tools.register(graphIntegrity));
14946
+ safeRegister("graph_path_pattern", () => ctx.tools.register(graphPathPattern));
14947
+ safeRegister("graph_slice", () => ctx.tools.register(graphSlice$1));
14948
+ safeRegister("graph_views", () => ctx.tools.register(graphViews));
14949
+ if (failed$2.length > 0) log.warn("tool registration degraded", {
14950
+ failed: failed$2,
14951
+ registered: disposers.length
14952
+ });
14953
+ else log.info("tool registrations complete", { registered: disposers.length });
14954
+ globalThis.__cgvRegistrationOutcome = {
14955
+ registered: disposers.length,
14956
+ failed: failed$2
14957
+ };
14867
14958
  return () => {
14868
- d1();
14869
- d2();
14870
- d3();
14871
- d4();
14872
- d5();
14873
- d6();
14874
- d7();
14875
- d8();
14876
- d9();
14877
- d10();
14878
- d11();
14879
- d12();
14880
- d13();
14881
- d14();
14882
- d15();
14959
+ for (const d of disposers) try {
14960
+ d();
14961
+ } catch {}
14883
14962
  };
14884
14963
  }, "codegraph: tool registrations");
14885
14964
  let lastGraphData = null;
@@ -14997,7 +15076,7 @@ async function apply(ctx, userConfig) {
14997
15076
  securityManager.reset();
14998
15077
  disposeGraphTools();
14999
15078
  closeAllDbConnections();
15000
- import("./nativeIndex-Cx7RLXUp.js").then(({ closeNativeIndexConnections }) => closeNativeIndexConnections());
15079
+ import("./nativeIndex-esaDOsq8.js").then(({ closeNativeIndexConnections }) => closeNativeIndexConnections());
15001
15080
  graphRepo.close();
15002
15081
  };
15003
15082
  }, "codegraph: state cleanup");