@documentation-robotics/cli 0.2.0 → 0.4.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 (335) hide show
  1. package/README.md +46 -16
  2. package/dist/analysis/relationship-classifier.js +2 -9
  3. package/dist/analysis/relationship-classifier.js.map +2 -2
  4. package/dist/analyzers/active-analyzer.js +62 -0
  5. package/dist/analyzers/active-analyzer.js.map +7 -0
  6. package/dist/analyzers/call-graph-utils.js +2 -2
  7. package/dist/analyzers/call-graph-utils.js.map +2 -2
  8. package/dist/analyzers/cards/build.js +191 -0
  9. package/dist/analyzers/cards/build.js.map +7 -0
  10. package/dist/analyzers/cards/classify.js +42 -0
  11. package/dist/analyzers/cards/classify.js.map +7 -0
  12. package/dist/analyzers/cards/edge-index.js +44 -0
  13. package/dist/analyzers/cards/edge-index.js.map +7 -0
  14. package/dist/analyzers/cards/extract.js +138 -0
  15. package/dist/analyzers/cards/extract.js.map +7 -0
  16. package/dist/analyzers/cards/facts.js +46 -0
  17. package/dist/analyzers/cards/facts.js.map +7 -0
  18. package/dist/analyzers/cards/graph.js +42 -0
  19. package/dist/analyzers/cards/graph.js.map +7 -0
  20. package/dist/analyzers/cards/index.js +8 -0
  21. package/dist/analyzers/cards/index.js.map +7 -0
  22. package/dist/analyzers/cards/routes.js +96 -0
  23. package/dist/analyzers/cards/routes.js.map +7 -0
  24. package/dist/analyzers/cards/tier0.js +18 -0
  25. package/dist/analyzers/cards/tier0.js.map +7 -0
  26. package/dist/analyzers/cards/types.js +1 -0
  27. package/dist/analyzers/cards/types.js.map +7 -0
  28. package/dist/analyzers/cbm-analyzer.js +270 -174
  29. package/dist/analyzers/cbm-analyzer.js.map +2 -2
  30. package/dist/analyzers/cbm-responses.js +342 -0
  31. package/dist/analyzers/cbm-responses.js.map +7 -0
  32. package/dist/analyzers/code-changes.js +159 -0
  33. package/dist/analyzers/code-changes.js.map +7 -0
  34. package/dist/analyzers/edge-relationships.js +49 -0
  35. package/dist/analyzers/edge-relationships.js.map +7 -0
  36. package/dist/analyzers/extraction-plan.js +541 -0
  37. package/dist/analyzers/extraction-plan.js.map +7 -0
  38. package/dist/analyzers/index-job.js +229 -0
  39. package/dist/analyzers/index-job.js.map +7 -0
  40. package/dist/analyzers/mapping-loader.js +9 -0
  41. package/dist/analyzers/mapping-loader.js.map +2 -2
  42. package/dist/analyzers/tier0-rules.js +153 -0
  43. package/dist/analyzers/tier0-rules.js.map +7 -0
  44. package/dist/analyzers/types.js.map +1 -1
  45. package/dist/audit/relationships/ai/prompts.js +10 -10
  46. package/dist/audit/relationships/ai/prompts.js.map +2 -2
  47. package/dist/audit/relationships/analysis/layer-templates.js +52 -52
  48. package/dist/audit/relationships/analysis/layer-templates.js.map +1 -1
  49. package/dist/cli.js +23 -11
  50. package/dist/cli.js.map +2 -2
  51. package/dist/coding-agents/default-permissions.js +31 -1
  52. package/dist/coding-agents/default-permissions.js.map +2 -2
  53. package/dist/coding-agents/drbot-mcp.js +269 -0
  54. package/dist/coding-agents/drbot-mcp.js.map +7 -0
  55. package/dist/commands/add.js +7 -4
  56. package/dist/commands/add.js.map +2 -2
  57. package/dist/commands/analyzer.js +143 -40
  58. package/dist/commands/analyzer.js.map +2 -2
  59. package/dist/commands/changeset-verify.js +63 -0
  60. package/dist/commands/changeset-verify.js.map +7 -0
  61. package/dist/commands/changeset.js +80 -29
  62. package/dist/commands/changeset.js.map +2 -2
  63. package/dist/commands/delete.js +10 -4
  64. package/dist/commands/delete.js.map +2 -2
  65. package/dist/commands/farm.js +176 -60
  66. package/dist/commands/farm.js.map +2 -2
  67. package/dist/commands/init.js +9 -26
  68. package/dist/commands/init.js.map +2 -2
  69. package/dist/commands/mcp.js +40 -21
  70. package/dist/commands/mcp.js.map +3 -3
  71. package/dist/commands/relationship.js +208 -37
  72. package/dist/commands/relationship.js.map +2 -2
  73. package/dist/commands/reports.js +3 -3
  74. package/dist/commands/reports.js.map +2 -2
  75. package/dist/commands/update.js +52 -32
  76. package/dist/commands/update.js.map +2 -2
  77. package/dist/commands/upgrade.js +99 -103
  78. package/dist/commands/upgrade.js.map +3 -3
  79. package/dist/commands/validate.js +19 -3
  80. package/dist/commands/validate.js.map +2 -2
  81. package/dist/commands/version.js +1 -1
  82. package/dist/commands/visualize.js +34 -15
  83. package/dist/commands/visualize.js.map +2 -2
  84. package/dist/core/annotation-store.js +15 -5
  85. package/dist/core/annotation-store.js.map +2 -2
  86. package/dist/core/catalog-migration.js +34 -0
  87. package/dist/core/catalog-migration.js.map +7 -0
  88. package/dist/core/changeset-analysis.js +421 -0
  89. package/dist/core/changeset-analysis.js.map +7 -0
  90. package/dist/core/changeset-base-index.js +160 -0
  91. package/dist/core/changeset-base-index.js.map +7 -0
  92. package/dist/core/changeset-brief-compact.js +256 -0
  93. package/dist/core/changeset-brief-compact.js.map +7 -0
  94. package/dist/core/changeset-brief-delta.js +102 -0
  95. package/dist/core/changeset-brief-delta.js.map +7 -0
  96. package/dist/core/changeset-graph.js +281 -0
  97. package/dist/core/changeset-graph.js.map +7 -0
  98. package/dist/core/changeset-only-guard.js +32 -0
  99. package/dist/core/changeset-only-guard.js.map +7 -0
  100. package/dist/core/changeset-summary.js +68 -0
  101. package/dist/core/changeset-summary.js.map +7 -0
  102. package/dist/core/changeset-validator.js +66 -20
  103. package/dist/core/changeset-validator.js.map +2 -2
  104. package/dist/core/changeset-verify.js +848 -0
  105. package/dist/core/changeset-verify.js.map +7 -0
  106. package/dist/core/changeset.js +56 -9
  107. package/dist/core/changeset.js.map +2 -2
  108. package/dist/core/element-type-migration.js +145 -0
  109. package/dist/core/element-type-migration.js.map +7 -0
  110. package/dist/core/extraction-observability.js +161 -0
  111. package/dist/core/extraction-observability.js.map +7 -0
  112. package/dist/core/farm-manifest.js +12 -6
  113. package/dist/core/farm-manifest.js.map +2 -2
  114. package/dist/core/farm-sync-engine.js +1 -1
  115. package/dist/core/farm-sync-engine.js.map +2 -2
  116. package/dist/core/farm-sync-state.js +10 -2
  117. package/dist/core/farm-sync-state.js.map +2 -2
  118. package/dist/core/migration-registry.js +88 -47
  119. package/dist/core/migration-registry.js.map +2 -2
  120. package/dist/core/model-upgrade.js +102 -0
  121. package/dist/core/model-upgrade.js.map +7 -0
  122. package/dist/core/model.js +82 -30
  123. package/dist/core/model.js.map +2 -2
  124. package/dist/core/mutation-handler.js +71 -6
  125. package/dist/core/mutation-handler.js.map +2 -2
  126. package/dist/core/project-init.js +53 -0
  127. package/dist/core/project-init.js.map +7 -0
  128. package/dist/core/relationship-migration-table.js +6639 -0
  129. package/dist/core/relationship-migration-table.js.map +7 -0
  130. package/dist/core/relationship-migration.js +272 -0
  131. package/dist/core/relationship-migration.js.map +7 -0
  132. package/dist/core/relationship-prune.js +49 -0
  133. package/dist/core/relationship-prune.js.map +7 -0
  134. package/dist/core/relationship-staging.js +161 -0
  135. package/dist/core/relationship-staging.js.map +7 -0
  136. package/dist/core/relationships.js +26 -4
  137. package/dist/core/relationships.js.map +2 -2
  138. package/dist/core/report-data-model.js +7 -13
  139. package/dist/core/report-data-model.js.map +2 -2
  140. package/dist/core/staged-changeset-storage.js +145 -18
  141. package/dist/core/staged-changeset-storage.js.map +2 -2
  142. package/dist/core/staged-source-reference.js +28 -0
  143. package/dist/core/staged-source-reference.js.map +7 -0
  144. package/dist/core/staging-area.js +166 -24
  145. package/dist/core/staging-area.js.map +2 -2
  146. package/dist/core/upgrade-plan.js +117 -0
  147. package/dist/core/upgrade-plan.js.map +7 -0
  148. package/dist/core/virtual-projection.js +13 -5
  149. package/dist/core/virtual-projection.js.map +2 -2
  150. package/dist/export/archimate-exporter.js +1 -0
  151. package/dist/export/archimate-exporter.js.map +2 -2
  152. package/dist/generated/compiled-validators.js +2 -2
  153. package/dist/generated/compiled-validators.js.map +2 -2
  154. package/dist/generated/layer-registry.js +16 -16
  155. package/dist/generated/layer-registry.js.map +2 -2
  156. package/dist/generated/node-types.js +186 -168
  157. package/dist/generated/node-types.js.map +2 -2
  158. package/dist/generated/relationship-index.js +2468 -7913
  159. package/dist/generated/relationship-index.js.map +2 -2
  160. package/dist/integrations/claude_code/.claude-plugin/plugin.json +24 -0
  161. package/dist/integrations/claude_code/agents/dr-architect.md +30 -3
  162. package/dist/integrations/claude_code/agents/dr-extractor.md +8 -2
  163. package/dist/integrations/claude_code/commands/dr-analyzer.md +565 -0
  164. package/dist/integrations/claude_code/commands/dr-changeset.md +2 -1
  165. package/dist/integrations/claude_code/commands/dr-map.md +20 -1
  166. package/dist/integrations/claude_code/commands/dr-plan.md +66 -0
  167. package/dist/integrations/claude_code/commands/dr-relate.md +106 -96
  168. package/dist/integrations/claude_code/commands/dr-verify.md +45 -2
  169. package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +14 -0
  170. package/dist/integrations/claude_code/docs/MCP_SERVER.md +47 -26
  171. package/dist/integrations/claude_code/docs/QUICK_START.md +37 -8
  172. package/dist/integrations/claude_code/docs/README.md +68 -2
  173. package/dist/integrations/claude_code/plugin-agents/dr-advisor.md +255 -0
  174. package/dist/integrations/claude_code/plugin-agents/dr-architect.md +306 -0
  175. package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +93 -72
  176. package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +163 -126
  177. package/dist/integrations/claude_code/skills/dr_03_product_layer/SKILL.md +161 -126
  178. package/dist/integrations/claude_code/skills/dr_04_security_layer/SKILL.md +153 -133
  179. package/dist/integrations/claude_code/skills/dr_05_application_layer/SKILL.md +129 -100
  180. package/dist/integrations/claude_code/skills/dr_06_technology_layer/SKILL.md +111 -94
  181. package/dist/integrations/claude_code/skills/dr_07_api_layer/SKILL.md +143 -157
  182. package/dist/integrations/claude_code/skills/dr_08_data_model_layer/SKILL.md +117 -33
  183. package/dist/integrations/claude_code/skills/dr_09_dataset_layer/SKILL.md +74 -25
  184. package/dist/integrations/claude_code/skills/dr_10_ux_layer/SKILL.md +88 -12
  185. package/dist/integrations/claude_code/skills/dr_11_navigation_layer/SKILL.md +83 -24
  186. package/dist/integrations/claude_code/skills/dr_12_apm_layer/SKILL.md +57 -12
  187. package/dist/integrations/claude_code/skills/dr_13_testing_layer/SKILL.md +95 -15
  188. package/dist/integrations/claude_code/skills/dr_change_planning/SKILL.md +178 -0
  189. package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +8 -0
  190. package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +6 -1
  191. package/dist/integrations/github_copilot/agents/dr-architect.md +3 -1
  192. package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +182 -102
  193. package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +266 -148
  194. package/dist/integrations/github_copilot/skills/dr_03_product_layer/SKILL.md +547 -86
  195. package/dist/integrations/github_copilot/skills/dr_04_security_layer/SKILL.md +164 -169
  196. package/dist/integrations/github_copilot/skills/dr_05_application_layer/SKILL.md +420 -150
  197. package/dist/integrations/github_copilot/skills/dr_06_technology_layer/SKILL.md +331 -138
  198. package/dist/integrations/github_copilot/skills/dr_07_api_layer/SKILL.md +265 -201
  199. package/dist/integrations/github_copilot/skills/dr_08_data_model_layer/SKILL.md +181 -58
  200. package/dist/integrations/github_copilot/skills/dr_09_dataset_layer/SKILL.md +209 -57
  201. package/dist/integrations/github_copilot/skills/dr_10_ux_layer/SKILL.md +277 -112
  202. package/dist/integrations/github_copilot/skills/dr_11_navigation_layer/SKILL.md +219 -70
  203. package/dist/integrations/github_copilot/skills/dr_12_apm_layer/SKILL.md +189 -105
  204. package/dist/integrations/github_copilot/skills/dr_13_testing_layer/SKILL.md +225 -102
  205. package/dist/integrations/github_copilot/skills/dr_change_planning/SKILL.md +177 -0
  206. package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +3 -0
  207. package/dist/integrations/hash-utils.js.map +2 -2
  208. package/dist/mcp/api-key-manager.js +14 -1
  209. package/dist/mcp/api-key-manager.js.map +2 -2
  210. package/dist/mcp/changeset-only.js +45 -0
  211. package/dist/mcp/changeset-only.js.map +7 -0
  212. package/dist/mcp/project-root.js +85 -0
  213. package/dist/mcp/project-root.js.map +7 -0
  214. package/dist/mcp/server-instructions.js +27 -0
  215. package/dist/mcp/server-instructions.js.map +7 -0
  216. package/dist/mcp/strict-schema.js +52 -0
  217. package/dist/mcp/strict-schema.js.map +7 -0
  218. package/dist/mcp/tool-registry.js +55 -5
  219. package/dist/mcp/tool-registry.js.map +2 -2
  220. package/dist/mcp/tools/changeset-analysis-tools.js +98 -0
  221. package/dist/mcp/tools/changeset-analysis-tools.js.map +7 -0
  222. package/dist/mcp/tools/changeset-commit.js +224 -0
  223. package/dist/mcp/tools/changeset-commit.js.map +7 -0
  224. package/dist/mcp/tools/changeset-editing.js +260 -0
  225. package/dist/mcp/tools/changeset-editing.js.map +7 -0
  226. package/dist/mcp/tools/changeset-lifecycle.js +83 -0
  227. package/dist/mcp/tools/changeset-lifecycle.js.map +7 -0
  228. package/dist/mcp/tools/changeset-shared.js +31 -0
  229. package/dist/mcp/tools/changeset-shared.js.map +7 -0
  230. package/dist/mcp/tools/changeset-show.js +17 -1
  231. package/dist/mcp/tools/changeset-show.js.map +2 -2
  232. package/dist/mcp/tools/changeset-verify.js +49 -0
  233. package/dist/mcp/tools/changeset-verify.js.map +7 -0
  234. package/dist/mcp/tools/codebase-extract.js +836 -0
  235. package/dist/mcp/tools/codebase-extract.js.map +7 -0
  236. package/dist/mcp/tools/codebase-index.js +125 -0
  237. package/dist/mcp/tools/codebase-index.js.map +7 -0
  238. package/dist/mcp/tools/codebase-shared.js +265 -0
  239. package/dist/mcp/tools/codebase-shared.js.map +7 -0
  240. package/dist/mcp/tools/codebase-verify.js +48 -0
  241. package/dist/mcp/tools/codebase-verify.js.map +7 -0
  242. package/dist/mcp/tools/index.js +34 -1
  243. package/dist/mcp/tools/index.js.map +2 -2
  244. package/dist/mcp/tools/model-add.js +191 -74
  245. package/dist/mcp/tools/model-add.js.map +2 -2
  246. package/dist/mcp/tools/model-delete.js +2 -2
  247. package/dist/mcp/tools/model-delete.js.map +2 -2
  248. package/dist/mcp/tools/model-search.js +14 -0
  249. package/dist/mcp/tools/model-search.js.map +2 -2
  250. package/dist/mcp/tools/model-show.js +29 -2
  251. package/dist/mcp/tools/model-show.js.map +2 -2
  252. package/dist/mcp/tools/model-trace.js +93 -30
  253. package/dist/mcp/tools/model-trace.js.map +2 -2
  254. package/dist/mcp/tools/model-update.js +46 -26
  255. package/dist/mcp/tools/model-update.js.map +2 -2
  256. package/dist/mcp/tools/model-validate.js +46 -4
  257. package/dist/mcp/tools/model-validate.js.map +2 -2
  258. package/dist/mcp/tools/project-status-collectors.js +381 -0
  259. package/dist/mcp/tools/project-status-collectors.js.map +7 -0
  260. package/dist/mcp/tools/project-status.js +237 -0
  261. package/dist/mcp/tools/project-status.js.map +7 -0
  262. package/dist/mcp/tools/project-tools.js +505 -0
  263. package/dist/mcp/tools/project-tools.js.map +7 -0
  264. package/dist/mcp/tools/relationship-tools.js +167 -0
  265. package/dist/mcp/tools/relationship-tools.js.map +7 -0
  266. package/dist/mcp/tools/review-open.js +210 -0
  267. package/dist/mcp/tools/review-open.js.map +7 -0
  268. package/dist/mcp/tools/shared.js +35 -4
  269. package/dist/mcp/tools/shared.js.map +2 -2
  270. package/dist/mcp/tools/spec-type.js +90 -0
  271. package/dist/mcp/tools/spec-type.js.map +7 -0
  272. package/dist/reports/model-report-orchestrator.js +31 -2
  273. package/dist/reports/model-report-orchestrator.js.map +2 -2
  274. package/dist/schemas/bundled/analyzers/cbm.json +1200 -70
  275. package/dist/schemas/bundled/analyzers/manifest.json +2 -2
  276. package/dist/schemas/bundled/api.json +1029 -1658
  277. package/dist/schemas/bundled/apm.json +499 -734
  278. package/dist/schemas/bundled/application.json +735 -371
  279. package/dist/schemas/bundled/base.json +3 -220
  280. package/dist/schemas/bundled/business.json +452 -366
  281. package/dist/schemas/bundled/data-model.json +395 -411
  282. package/dist/schemas/bundled/data-store.json +334 -558
  283. package/dist/schemas/bundled/manifest.json +18 -18
  284. package/dist/schemas/bundled/motivation.json +349 -368
  285. package/dist/schemas/bundled/navigation.json +415 -731
  286. package/dist/schemas/bundled/product.json +325 -159
  287. package/dist/schemas/bundled/security.json +864 -1232
  288. package/dist/schemas/bundled/technology.json +574 -703
  289. package/dist/schemas/bundled/testing.json +865 -1646
  290. package/dist/schemas/bundled/ux.json +739 -1352
  291. package/dist/server/schemas.js +8 -0
  292. package/dist/server/schemas.js.map +2 -2
  293. package/dist/server/server.js +686 -231
  294. package/dist/server/server.js.map +3 -3
  295. package/dist/server/viewer-registry.js +264 -0
  296. package/dist/server/viewer-registry.js.map +7 -0
  297. package/dist/server-entry.js +2 -1
  298. package/dist/server-entry.js.map +2 -2
  299. package/dist/telemetry/index.js +1 -1
  300. package/dist/utils/ansi-suppressor.js +6 -8
  301. package/dist/utils/ansi-suppressor.js.map +2 -2
  302. package/dist/utils/attribute-patch.js +41 -0
  303. package/dist/utils/attribute-patch.js.map +7 -0
  304. package/dist/utils/error-hints.js +29 -0
  305. package/dist/utils/error-hints.js.map +7 -0
  306. package/dist/utils/errors.js +9 -3
  307. package/dist/utils/errors.js.map +2 -2
  308. package/dist/utils/id-generator.js +5 -2
  309. package/dist/utils/id-generator.js.map +2 -2
  310. package/dist/utils/project-paths.js +26 -1
  311. package/dist/utils/project-paths.js.map +2 -2
  312. package/dist/utils/source-reference.js +64 -31
  313. package/dist/utils/source-reference.js.map +2 -2
  314. package/dist/utils/spec-version.js +2 -2
  315. package/dist/utils/spec-version.js.map +1 -1
  316. package/dist/validators/composed-reference-validator.js +5 -27
  317. package/dist/validators/composed-reference-validator.js.map +2 -2
  318. package/dist/validators/model-warnings.js +28 -0
  319. package/dist/validators/model-warnings.js.map +7 -0
  320. package/dist/validators/reference-validator.js +0 -7
  321. package/dist/validators/reference-validator.js.map +2 -2
  322. package/dist/validators/relationship-schema-validator.js +3 -3
  323. package/dist/validators/relationship-schema-validator.js.map +2 -2
  324. package/dist/validators/schema-validator.js +27 -9
  325. package/dist/validators/schema-validator.js.map +2 -2
  326. package/dist/validators/types.js.map +1 -1
  327. package/dist/viewer/README.md +6 -6
  328. package/dist/viewer/assets/main-CUOQGGRA.css +1 -0
  329. package/dist/viewer/assets/main-DvH3gYrI.js +84 -0
  330. package/dist/viewer/index.html +2 -2
  331. package/dist/viewer/manifest.json +10 -10
  332. package/dist/viewer/version.json +1 -1
  333. package/package.json +2 -1
  334. package/dist/viewer/assets/main-B7AOQXXX.js +0 -81
  335. package/dist/viewer/assets/main-vdrFrG7q.css +0 -1
@@ -1,101 +1,218 @@
1
1
  import { z } from "zod";
2
+ import { strictItem } from "../strict-schema.js";
3
+ import { ChangesetGraph } from "../../core/changeset-graph.js";
2
4
  import { Element } from "../../core/element.js";
3
5
  import { Layer } from "../../core/layer.js";
4
6
  import { MutationHandler } from "../../core/mutation-handler.js";
7
+ import { countByStatus, planRelationshipBatch } from "../../core/relationship-staging.js";
8
+ import { StagingAreaManager } from "../../core/staging-area.js";
5
9
  import { getAllLayerIds, isValidLayer } from "../../generated/layer-registry.js";
6
10
  import { getNodeTypesForLayer, isValidNodeType, normalizeNodeType } from "../../generated/node-types.js";
7
11
  import { generateElementId, generateUUID } from "../../utils/id-generator.js";
8
- import { buildSourceReference, validateSourceReferenceOptions } from "../../utils/source-reference.js";
12
+ import { buildSourceReference, resolveSourceReferenceOptions } from "../../utils/source-reference.js";
13
+ import { schemaLookupHint } from "../../utils/error-hints.js";
9
14
  import { SchemaValidator } from "../../validators/schema-validator.js";
10
- import { CLIError, ErrorCategory, findSimilar, formatValidOptions } from "../../utils/errors.js";
11
- import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
12
- const inputSchema = {
13
- layer: z.string().describe("Canonical layer name (e.g. 'api', 'data-model')."),
14
- type: z.string().describe("Element type within the layer (e.g. 'operation', 'entity')."),
15
- name: z.string().describe("Human-readable element name; used to derive the element ID."),
15
+ import { CLIError, ErrorCategory, findSimilar, formatValidOptions, getErrorMessage } from "../../utils/errors.js";
16
+ import { jsonResult, loadModel, reloadModel, rootPathSchema, runTool } from "./shared.js";
17
+ import { activeStagedChangeset } from "./changeset-shared.js";
18
+ import { applyRelationshipPlan, previewChangeset, relationshipItemSchema } from "./relationship-tools.js";
19
+ const provenanceSchema = z.enum(["extracted", "manual", "inferred", "generated"]).optional().describe("How the source reference was made. Defaults to 'manual' when sourceFile is sent alone. 'extracted' and 'manual' need a sourceFile (sent without one, it is ignored with a warning). For a planned element with no code yet, send no source fields."), elementFields = {
16
20
  description: z.string().optional(),
17
21
  attributes: z.record(z.string(), z.unknown()).optional().describe("Type-specific attributes, validated against the element's spec schema."),
18
22
  sourceFile: z.string().optional().describe("Source file path relative to the repository root."),
19
23
  sourceSymbol: z.string().optional(),
20
- sourceProvenance: z.enum(["extracted", "manual", "inferred", "generated"]).optional(),
24
+ sourceProvenance: provenanceSchema,
21
25
  sourceRepoRemote: z.string().optional(),
22
- sourceRepoCommit: z.string().optional().describe("Full 40-character Git commit SHA."),
26
+ sourceRepoCommit: z.string().optional().describe("Full 40-character Git commit SHA.")
27
+ }, elementItemSchema = strictItem("An elements[] item", {
28
+ layer: z.string().describe("Canonical layer name."),
29
+ type: z.string().describe("Element type within the layer."),
30
+ name: z.string().describe("Human-readable element name; used to derive the element ID."),
31
+ ...elementFields
32
+ }), inputSchema = {
33
+ layer: z.string().optional().describe("Canonical layer name (e.g. 'api', 'data-model'). Single form."),
34
+ type: z.string().optional().describe("Element type within the layer (e.g. 'operation', 'entity'). Single form."),
35
+ name: z.string().optional().describe("Human-readable element name; used to derive the element ID. Single form."),
36
+ ...elementFields,
37
+ elements: z.array(elementItemSchema).optional().describe("Batch form, instead of layer/type/name: a list of elements ({layer, type, name, description?, attributes?, source fields?}), staged in one write. Each is validated on its own; an invalid one is skipped and reported."),
38
+ relationships: z.array(relationshipItemSchema).optional().describe("Batch form only: relationships to stage in the same write, as relationship_add takes them. They may name elements this call adds (by the id layer.type.kebab-name)."),
23
39
  rootPath: rootPathSchema
24
- };
40
+ }, SINGLE_FORM_FIELDS = [
41
+ "layer",
42
+ "type",
43
+ "name",
44
+ ...Object.keys(elementFields)
45
+ ];
46
+ async function prepareElement(spec) {
47
+ if (!isValidLayer(spec.layer)) {
48
+ const validLayers = getAllLayerIds(), similar = findSimilar(spec.layer, validLayers, 3), suggestions = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];
49
+ throw similar.length > 0 && suggestions.unshift(`Did you mean: ${similar.join(" or ")}?`), new CLIError(`Unknown layer "${spec.layer}"`, ErrorCategory.USER, suggestions);
50
+ }
51
+ if (!isValidNodeType(spec.layer, spec.type)) {
52
+ const typeNames = getNodeTypesForLayer(spec.layer).map((t) => t.type).sort(), similar = findSimilar(spec.type, typeNames, 3), suggestions = [`Valid types for ${spec.layer}: ${formatValidOptions(typeNames)}`];
53
+ throw similar.length > 0 && suggestions.unshift(`Did you mean: ${similar.join(" or ")}?`), new CLIError(`Invalid element type "${spec.type}" for layer "${spec.layer}"`, ErrorCategory.USER, suggestions);
54
+ }
55
+ const resolvedType = normalizeNodeType(spec.layer, spec.type), elementPath = generateElementId(spec.layer, resolvedType, spec.name);
56
+ if (!elementPath.split(".")[2])
57
+ throw new CLIError(`Cannot generate a valid element ID from name "${spec.name}"`, ErrorCategory.USER, [
58
+ "Element names must contain at least one letter or digit"
59
+ ]);
60
+ const { options: sourceOptions, warnings } = resolveSourceReferenceOptions(spec, "mcp"), now = (/* @__PURE__ */ new Date()).toISOString(), element = new Element({
61
+ id: generateUUID(),
62
+ path: elementPath,
63
+ spec_node_id: `${spec.layer}.${resolvedType}`,
64
+ layer_id: spec.layer,
65
+ type: resolvedType,
66
+ name: spec.name,
67
+ description: spec.description,
68
+ attributes: spec.attributes ?? {},
69
+ metadata: {
70
+ created_at: now,
71
+ updated_at: now,
72
+ version: 1
73
+ },
74
+ layer: spec.layer
75
+ }), sourceRef = buildSourceReference(sourceOptions);
76
+ sourceRef && element.setSourceReference(sourceRef);
77
+ const schemaValidator = new SchemaValidator(), tempLayer = new Layer(spec.layer);
78
+ tempLayer.addElement(element);
79
+ const attrValidation = await schemaValidator.validateLayer(tempLayer);
80
+ if (!attrValidation.isValid()) {
81
+ const errorMessages = attrValidation.errors.map((e) => ` ${e.message}`).join(`
82
+ `);
83
+ throw new CLIError(`Element ${elementPath} has invalid attributes:
84
+ ${errorMessages}`, ErrorCategory.USER, [
85
+ schemaLookupHint("mcp", spec.layer, resolvedType)
86
+ ]);
87
+ }
88
+ return { element, id: elementPath, layer: spec.layer, type: resolvedType, warnings };
89
+ }
25
90
  async function modelAddHandler(args) {
26
91
  return runTool(async () => {
27
- if (!isValidLayer(args.layer)) {
28
- const validLayers = getAllLayerIds(), similar = findSimilar(args.layer, validLayers, 3), suggestions = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];
29
- throw similar.length > 0 && suggestions.unshift(`Did you mean: ${similar.join(" or ")}?`), new CLIError(`Unknown layer "${args.layer}"`, ErrorCategory.USER, suggestions);
92
+ if (args.elements !== void 0) {
93
+ const singleFields = SINGLE_FORM_FIELDS.filter((field) => args[field] !== void 0);
94
+ if (singleFields.length > 0)
95
+ throw new CLIError(`Send either a single element or elements, not both (got ${singleFields.join(", ")} beside elements)`, ErrorCategory.USER, ["Put those fields on the items of the elements list"]);
96
+ return jsonResult(await addElementBatch(args.elements, args.relationships ?? [], args.rootPath));
30
97
  }
31
- if (!isValidNodeType(args.layer, args.type)) {
32
- const typeNames = getNodeTypesForLayer(args.layer).map((t) => t.type).sort(), similar = findSimilar(args.type, typeNames, 3), suggestions = [`Valid types for ${args.layer}: ${formatValidOptions(typeNames)}`];
33
- throw similar.length > 0 && suggestions.unshift(`Did you mean: ${similar.join(" or ")}?`), new CLIError(`Invalid element type "${args.type}" for layer "${args.layer}"`, ErrorCategory.USER, suggestions);
34
- }
35
- const resolvedType = normalizeNodeType(args.layer, args.type), elementPath = generateElementId(args.layer, resolvedType, args.name), elementUUID = generateUUID();
36
- if (!elementPath.split(".")[2])
37
- throw new CLIError(`Cannot generate a valid element ID from name "${args.name}"`, ErrorCategory.USER, [
38
- "Element names must contain at least one letter or digit"
98
+ if (args.relationships !== void 0)
99
+ throw new CLIError("relationships goes with the elements list", ErrorCategory.USER, [
100
+ "Send {elements: [...], relationships: [...]}, or use relationship_add for relationships alone"
39
101
  ]);
40
- validateSourceReferenceOptions(args);
41
- const model = await loadModel(args.rootPath);
42
- let layerObj = await model.getLayer(args.layer), isNewLayer = !1;
43
- layerObj || (layerObj = new Layer(args.layer), isNewLayer = !0);
44
- const now = (/* @__PURE__ */ new Date()).toISOString(), element = new Element({
45
- id: elementUUID,
46
- path: elementPath,
47
- spec_node_id: `${args.layer}.${resolvedType}`,
48
- layer_id: args.layer,
49
- type: resolvedType,
50
- name: args.name,
51
- description: args.description,
52
- attributes: args.attributes ?? {},
53
- metadata: {
54
- created_at: now,
55
- updated_at: now,
56
- version: 1
57
- },
58
- layer: args.layer
59
- }), sourceRef = buildSourceReference(args);
60
- sourceRef && element.setSourceReference(sourceRef);
61
- {
62
- const schemaValidator = new SchemaValidator(), tempLayer = new Layer(args.layer);
63
- tempLayer.addElement(element);
64
- const attrValidation = await schemaValidator.validateLayer(tempLayer);
65
- if (!attrValidation.isValid()) {
66
- const errorMessages = attrValidation.errors.map((e) => ` ${e.message}`).join(`
67
- `);
68
- throw new CLIError(`Element ${elementPath} has invalid attributes:
69
- ${errorMessages}`, ErrorCategory.USER, [
70
- `Use "model_info" with layer "${args.layer}" and the spec resource for "${args.type}" to see the required attributes`
71
- ]);
72
- }
73
- }
74
- if (layerObj.getElement(elementPath))
75
- throw new CLIError(`Element ${elementPath} already exists in ${args.layer} layer`, ErrorCategory.USER, [
76
- 'Use "model_show" to view the existing element',
77
- 'Use "model_update" to modify it',
78
- 'Use "model_delete" to remove it first if you want to recreate it'
102
+ if (!args.layer || !args.type || !args.name)
103
+ throw new CLIError("model_add needs layer, type and name, or an elements list", ErrorCategory.USER, [
104
+ 'Single: {layer: "api", type: "operation", name: "Create Order"}',
105
+ "Batch: {elements: [{layer, type, name}, ...], relationships: [{source, predicate, target}, ...]}"
79
106
  ]);
80
- isNewLayer && model.addLayer(layerObj);
81
- const mutationHandler = new MutationHandler(model, elementPath, args.layer);
82
- await mutationHandler.executeAdd(element, (elem) => {
83
- layerObj.addElement(elem);
84
- });
85
- const activeChangeset = await mutationHandler.getStagingManager().getActive(), staged = !!(activeChangeset && activeChangeset.status === "staged");
86
- return jsonResult({
87
- status: staged ? "staged" : "added",
88
- changeset: staged ? activeChangeset.name : void 0,
89
- id: elementPath,
90
- layer: args.layer,
91
- type: resolvedType,
92
- name: args.name
107
+ return addSingleElement({ ...args, layer: args.layer, type: args.type, name: args.name }, args.rootPath);
108
+ });
109
+ }
110
+ async function addSingleElement(spec, rootPath) {
111
+ const prepared = await prepareElement(spec), { element, id: elementPath, layer } = prepared, model = await loadModel(rootPath), layerKnown = model.getLayerNames().includes(layer);
112
+ let layerObj = await model.getLayer(layer), isNewLayer = !1;
113
+ if (layerObj || (layerObj = new Layer(layer), isNewLayer = !0), layerObj.getElement(elementPath))
114
+ throw new CLIError(`Element ${elementPath} already exists in ${layer} layer`, ErrorCategory.USER, [
115
+ 'Use "model_show" to view the existing element',
116
+ 'Use "model_update" to modify it',
117
+ 'Use "model_delete" to remove it first if you want to recreate it'
118
+ ]);
119
+ isNewLayer && model.addLayer(layerObj);
120
+ const mutationHandler = new MutationHandler(model, elementPath, layer);
121
+ await mutationHandler.executeAdd(element, (elem) => {
122
+ layerObj.addElement(elem);
123
+ });
124
+ const activeChangeset = await mutationHandler.getStagingManager().getActive(), staged = !!(activeChangeset && activeChangeset.status === "staged");
125
+ return staged && !layerKnown && await reloadModel(rootPath), jsonResult({
126
+ status: staged ? "staged" : "added",
127
+ changeset: staged ? activeChangeset.name : void 0,
128
+ id: elementPath,
129
+ layer,
130
+ type: prepared.type,
131
+ name: spec.name,
132
+ ...prepared.warnings.length > 0 ? { warnings: prepared.warnings } : {}
133
+ });
134
+ }
135
+ async function addElementBatch(specs, relationships, rootPath) {
136
+ const model = await loadModel(rootPath), manager = new StagingAreaManager(model.rootPath, model), active = await activeStagedChangeset(manager), changeset = active ?? previewChangeset(), graph = await ChangesetGraph.build(model, changeset), prepared = [], pending = /* @__PURE__ */ new Map(), rejected = /* @__PURE__ */ new Map(), results = [];
137
+ for (const [index, spec] of specs.entries()) {
138
+ const asSent = { index, name: spec.name };
139
+ let item;
140
+ try {
141
+ item = await prepareElement(spec);
142
+ } catch (error) {
143
+ const id = idFor(spec);
144
+ id && rejected.set(id, getErrorMessage(error)), results.push({
145
+ ...asSent,
146
+ ...id ? { id } : {},
147
+ status: "invalid",
148
+ reason: getErrorMessage(error),
149
+ ...error instanceof CLIError && error.suggestions?.length ? { suggestions: error.suggestions } : {}
150
+ });
151
+ continue;
152
+ }
153
+ const existing = graph.getElement(item.id);
154
+ if (existing && existing.status !== "deleted") {
155
+ results.push({
156
+ ...asSent,
157
+ id: item.id,
158
+ status: "invalid",
159
+ reason: `Element ${item.id} already exists`,
160
+ suggestions: ['Use "model_update" to change it']
161
+ });
162
+ continue;
163
+ }
164
+ if (pending.has(item.id)) {
165
+ results.push({ ...asSent, id: item.id, status: "invalid", reason: "Repeated earlier in this batch" });
166
+ continue;
167
+ }
168
+ pending.set(item.id, { id: item.id, layer: item.layer, type: item.type }), prepared.push(item), results.push({
169
+ ...asSent,
170
+ id: item.id,
171
+ status: active ? "staged" : "added",
172
+ ...item.warnings.length > 0 ? { warnings: item.warnings } : {}
93
173
  });
174
+ }
175
+ const plan = await planRelationshipBatch(graph, changeset, relationships, {
176
+ pending,
177
+ rejected,
178
+ addStatus: active ? "staged" : "added"
94
179
  });
180
+ if (active) {
181
+ const elementChanges = prepared.map((p) => ({
182
+ type: "add",
183
+ elementId: p.id,
184
+ layerName: p.layer,
185
+ after: p.element.toJSON()
186
+ }));
187
+ await applyRelationshipPlan(model, manager, active, plan, elementChanges);
188
+ } else {
189
+ for (const p of prepared)
190
+ await writeElement(model, p);
191
+ await applyRelationshipPlan(model, manager, null, plan, []);
192
+ }
193
+ return (prepared.length > 0 || plan.changes.length > 0 || plan.unstageKeys.length > 0) && await reloadModel(rootPath), {
194
+ ...active ? { changeset: active.name } : {},
195
+ elements: { counts: countByStatus(results), results },
196
+ ...relationships.length > 0 ? { relationships: { counts: countByStatus(plan.results), results: plan.results } } : {}
197
+ };
198
+ }
199
+ async function writeElement(model, prepared) {
200
+ let layerObj = await model.getLayer(prepared.layer);
201
+ layerObj || (layerObj = new Layer(prepared.layer), model.addLayer(layerObj));
202
+ const target = layerObj;
203
+ await new MutationHandler(model, prepared.id, prepared.layer).executeAdd(prepared.element, (elem) => {
204
+ target.addElement(elem);
205
+ });
206
+ }
207
+ function idFor(spec) {
208
+ if (!isValidLayer(spec.layer) || !isValidNodeType(spec.layer, spec.type))
209
+ return;
210
+ const id = generateElementId(spec.layer, normalizeNodeType(spec.layer, spec.type), spec.name);
211
+ return id.split(".")[2] ? id : void 0;
95
212
  }
96
213
  const modelAddTool = {
97
214
  name: "model_add",
98
- description: "Add a new element to a layer, validated against its spec schema.",
215
+ description: "Add elements, validated against their spec schemas. Send one (layer/type/name) or many (elements: [...], with optional relationships: [...] that may name the new elements); a list is staged in one write, so use it when adding several. A list returns a result per element and per relationship: staged (added, with no changeset active), restored or duplicate (relationships), or invalid with the reason. Invalid items are skipped; the rest are still staged.",
99
216
  inputSchema,
100
217
  handler: modelAddHandler
101
218
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mcp/tools/model-add.ts"],
4
- "sourcesContent": ["/**\n * model_add \u2014 add an element to a layer. Mirrors `dr add`, operating through\n * the shared MutationHandler so staging and base-model persistence stay\n * consistent with the CLI.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { Element } from \"../../core/element.js\";\nimport { Layer } from \"../../core/layer.js\";\nimport { MutationHandler } from \"../../core/mutation-handler.js\";\nimport { getAllLayerIds, isValidLayer } from \"../../generated/layer-registry.js\";\nimport { getNodeTypesForLayer, isValidNodeType, normalizeNodeType } from \"../../generated/node-types.js\";\nimport { generateElementId, generateUUID } from \"../../utils/id-generator.js\";\nimport { buildSourceReference, validateSourceReferenceOptions } from \"../../utils/source-reference.js\";\nimport { SchemaValidator } from \"../../validators/schema-validator.js\";\nimport { CLIError, ErrorCategory, findSimilar, formatValidOptions } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n layer: z.string().describe(\"Canonical layer name (e.g. 'api', 'data-model').\"),\n type: z.string().describe(\"Element type within the layer (e.g. 'operation', 'entity').\"),\n name: z.string().describe(\"Human-readable element name; used to derive the element ID.\"),\n description: z.string().optional(),\n attributes: z.record(z.string(), z.unknown()).optional().describe(\"Type-specific attributes, validated against the element's spec schema.\"),\n sourceFile: z.string().optional().describe(\"Source file path relative to the repository root.\"),\n sourceSymbol: z.string().optional(),\n sourceProvenance: z.enum([\"extracted\", \"manual\", \"inferred\", \"generated\"]).optional(),\n sourceRepoRemote: z.string().optional(),\n sourceRepoCommit: z.string().optional().describe(\"Full 40-character Git commit SHA.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelAddArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelAddHandler(args: ModelAddArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (!isValidLayer(args.layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(args.layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Unknown layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n if (!isValidNodeType(args.layer, args.type)) {\n const validNodeTypes = getNodeTypesForLayer(args.layer);\n const typeNames = validNodeTypes.map((t) => t.type).sort();\n const similar = findSimilar(args.type, typeNames, 3);\n const suggestions: string[] = [`Valid types for ${args.layer}: ${formatValidOptions(typeNames)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Invalid element type \"${args.type}\" for layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n const resolvedType = normalizeNodeType(args.layer, args.type);\n const elementPath = generateElementId(args.layer, resolvedType, args.name);\n const elementUUID = generateUUID();\n\n const slugPart = elementPath.split(\".\")[2];\n if (!slugPart) {\n throw new CLIError(`Cannot generate a valid element ID from name \"${args.name}\"`, ErrorCategory.USER, [\n \"Element names must contain at least one letter or digit\",\n ]);\n }\n\n validateSourceReferenceOptions(args);\n\n const model = await loadModel(args.rootPath);\n\n let layerObj = await model.getLayer(args.layer);\n let isNewLayer = false;\n if (!layerObj) {\n layerObj = new Layer(args.layer);\n isNewLayer = true;\n }\n\n const now = new Date().toISOString();\n const element = new Element({\n id: elementUUID,\n path: elementPath,\n spec_node_id: `${args.layer}.${resolvedType}`,\n layer_id: args.layer,\n type: resolvedType,\n name: args.name,\n description: args.description,\n attributes: args.attributes ?? {},\n metadata: {\n created_at: now,\n updated_at: now,\n version: 1,\n },\n layer: args.layer,\n });\n\n const sourceRef = buildSourceReference(args);\n if (sourceRef) {\n element.setSourceReference(sourceRef);\n }\n\n {\n const schemaValidator = new SchemaValidator();\n const tempLayer = new Layer(args.layer);\n tempLayer.addElement(element);\n const attrValidation = await schemaValidator.validateLayer(tempLayer);\n if (!attrValidation.isValid()) {\n const errorMessages = attrValidation.errors.map((e) => ` ${e.message}`).join(\"\\n\");\n throw new CLIError(`Element ${elementPath} has invalid attributes:\\n${errorMessages}`, ErrorCategory.USER, [\n `Use \"model_info\" with layer \"${args.layer}\" and the spec resource for \"${args.type}\" to see the required attributes`,\n ]);\n }\n }\n\n if (layerObj.getElement(elementPath)) {\n throw new CLIError(`Element ${elementPath} already exists in ${args.layer} layer`, ErrorCategory.USER, [\n `Use \"model_show\" to view the existing element`,\n `Use \"model_update\" to modify it`,\n `Use \"model_delete\" to remove it first if you want to recreate it`,\n ]);\n }\n\n if (isNewLayer) {\n model.addLayer(layerObj);\n }\n\n const mutationHandler = new MutationHandler(model, elementPath, args.layer);\n await mutationHandler.executeAdd(element, (elem) => {\n layerObj!.addElement(elem);\n });\n\n const stagingManager = mutationHandler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n const staged = !!(activeChangeset && activeChangeset.status === \"staged\");\n\n return jsonResult({\n status: staged ? \"staged\" : \"added\",\n changeset: staged ? activeChangeset!.name : undefined,\n id: elementPath,\n layer: args.layer,\n type: resolvedType,\n name: args.name,\n });\n });\n}\n\nexport const modelAddTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_add\",\n description: \"Add a new element to a layer, validated against its spec schema.\",\n inputSchema,\n handler: modelAddHandler,\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * model_add \u2014 add an element to a layer. Mirrors `dr add`, operating through\n * the shared MutationHandler so staging and base-model persistence stay\n * consistent with the CLI.\n *\n * It also takes a list (`elements`, with optional `relationships` between them and the model):\n * each item is validated on its own, and the valid ones are staged in one write. Invalid items\n * are skipped and reported.\n */\n\nimport { z } from \"zod\";\nimport { strictItem } from \"../strict-schema.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { StagedChange } from \"../../core/changeset.js\";\nimport { ChangesetGraph } from \"../../core/changeset-graph.js\";\nimport { Element } from \"../../core/element.js\";\nimport { Layer } from \"../../core/layer.js\";\nimport type { Model } from \"../../core/model.js\";\nimport { MutationHandler } from \"../../core/mutation-handler.js\";\nimport { countByStatus, planRelationshipBatch, type PendingElement } from \"../../core/relationship-staging.js\";\nimport { StagingAreaManager } from \"../../core/staging-area.js\";\nimport { getAllLayerIds, isValidLayer } from \"../../generated/layer-registry.js\";\nimport { getNodeTypesForLayer, isValidNodeType, normalizeNodeType } from \"../../generated/node-types.js\";\nimport { generateElementId, generateUUID } from \"../../utils/id-generator.js\";\nimport { buildSourceReference, resolveSourceReferenceOptions } from \"../../utils/source-reference.js\";\nimport { schemaLookupHint } from \"../../utils/error-hints.js\";\nimport { SchemaValidator } from \"../../validators/schema-validator.js\";\nimport { CLIError, ErrorCategory, findSimilar, formatValidOptions, getErrorMessage } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, reloadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\nimport { activeStagedChangeset } from \"./changeset-shared.js\";\nimport { applyRelationshipPlan, previewChangeset, relationshipItemSchema } from \"./relationship-tools.js\";\n\nconst provenanceSchema = z\n .enum([\"extracted\", \"manual\", \"inferred\", \"generated\"])\n .optional()\n .describe(\n \"How the source reference was made. Defaults to 'manual' when sourceFile is sent alone. 'extracted' and \" +\n \"'manual' need a sourceFile (sent without one, it is ignored with a warning). For a planned element with no \" +\n \"code yet, send no source fields.\"\n );\n\nconst elementFields = {\n description: z.string().optional(),\n attributes: z.record(z.string(), z.unknown()).optional().describe(\"Type-specific attributes, validated against the element's spec schema.\"),\n sourceFile: z.string().optional().describe(\"Source file path relative to the repository root.\"),\n sourceSymbol: z.string().optional(),\n sourceProvenance: provenanceSchema,\n sourceRepoRemote: z.string().optional(),\n sourceRepoCommit: z.string().optional().describe(\"Full 40-character Git commit SHA.\"),\n};\n\nconst elementItemSchema = strictItem(\"An elements[] item\", {\n layer: z.string().describe(\"Canonical layer name.\"),\n type: z.string().describe(\"Element type within the layer.\"),\n name: z.string().describe(\"Human-readable element name; used to derive the element ID.\"),\n ...elementFields,\n});\n\nconst inputSchema = {\n layer: z.string().optional().describe(\"Canonical layer name (e.g. 'api', 'data-model'). Single form.\"),\n type: z.string().optional().describe(\"Element type within the layer (e.g. 'operation', 'entity'). Single form.\"),\n name: z.string().optional().describe(\"Human-readable element name; used to derive the element ID. Single form.\"),\n ...elementFields,\n elements: z\n .array(elementItemSchema)\n .optional()\n .describe(\n \"Batch form, instead of layer/type/name: a list of elements ({layer, type, name, description?, attributes?, \" +\n \"source fields?}), staged in one write. Each is validated on its own; an invalid one is skipped and reported.\"\n ),\n relationships: z\n .array(relationshipItemSchema)\n .optional()\n .describe(\n \"Batch form only: relationships to stage in the same write, as relationship_add takes them. They may name \" +\n \"elements this call adds (by the id layer.type.kebab-name).\"\n ),\n rootPath: rootPathSchema,\n};\n\nexport type ModelAddArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\n/** The single form's fields: refused beside `elements`, where they would otherwise be dropped. */\nconst SINGLE_FORM_FIELDS = [\n \"layer\",\n \"type\",\n \"name\",\n ...(Object.keys(elementFields) as Array<keyof typeof elementFields>),\n] as const;\ntype ElementSpec = z.infer<typeof elementItemSchema>;\n\ninterface PreparedElement {\n element: Element;\n id: string;\n layer: string;\n type: string;\n warnings: string[];\n}\n\n/** Validates one element and builds it; throws a CLIError saying what is wrong. */\nasync function prepareElement(spec: ElementSpec): Promise<PreparedElement> {\n if (!isValidLayer(spec.layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(spec.layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Unknown layer \"${spec.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n if (!isValidNodeType(spec.layer, spec.type)) {\n const validNodeTypes = getNodeTypesForLayer(spec.layer);\n const typeNames = validNodeTypes.map((t) => t.type).sort();\n const similar = findSimilar(spec.type, typeNames, 3);\n const suggestions: string[] = [`Valid types for ${spec.layer}: ${formatValidOptions(typeNames)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Invalid element type \"${spec.type}\" for layer \"${spec.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n const resolvedType = normalizeNodeType(spec.layer, spec.type);\n const elementPath = generateElementId(spec.layer, resolvedType, spec.name);\n\n const slugPart = elementPath.split(\".\")[2];\n if (!slugPart) {\n throw new CLIError(`Cannot generate a valid element ID from name \"${spec.name}\"`, ErrorCategory.USER, [\n \"Element names must contain at least one letter or digit\",\n ]);\n }\n\n const { options: sourceOptions, warnings } = resolveSourceReferenceOptions(spec, \"mcp\");\n\n const now = new Date().toISOString();\n const element = new Element({\n id: generateUUID(),\n path: elementPath,\n spec_node_id: `${spec.layer}.${resolvedType}`,\n layer_id: spec.layer,\n type: resolvedType,\n name: spec.name,\n description: spec.description,\n attributes: spec.attributes ?? {},\n metadata: {\n created_at: now,\n updated_at: now,\n version: 1,\n },\n layer: spec.layer,\n });\n\n const sourceRef = buildSourceReference(sourceOptions);\n if (sourceRef) {\n element.setSourceReference(sourceRef);\n }\n\n const schemaValidator = new SchemaValidator();\n const tempLayer = new Layer(spec.layer);\n tempLayer.addElement(element);\n const attrValidation = await schemaValidator.validateLayer(tempLayer);\n if (!attrValidation.isValid()) {\n const errorMessages = attrValidation.errors.map((e) => ` ${e.message}`).join(\"\\n\");\n throw new CLIError(`Element ${elementPath} has invalid attributes:\\n${errorMessages}`, ErrorCategory.USER, [\n schemaLookupHint(\"mcp\", spec.layer, resolvedType),\n ]);\n }\n\n return { element, id: elementPath, layer: spec.layer, type: resolvedType, warnings };\n}\n\nexport async function modelAddHandler(args: ModelAddArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (args.elements !== undefined) {\n const singleFields = SINGLE_FORM_FIELDS.filter((field) => args[field] !== undefined);\n if (singleFields.length > 0) {\n throw new CLIError(\n `Send either a single element or elements, not both (got ${singleFields.join(\", \")} beside elements)`,\n ErrorCategory.USER,\n [\"Put those fields on the items of the elements list\"]\n );\n }\n return jsonResult(await addElementBatch(args.elements, args.relationships ?? [], args.rootPath));\n }\n if (args.relationships !== undefined) {\n throw new CLIError(\"relationships goes with the elements list\", ErrorCategory.USER, [\n \"Send {elements: [...], relationships: [...]}, or use relationship_add for relationships alone\",\n ]);\n }\n if (!args.layer || !args.type || !args.name) {\n throw new CLIError(\"model_add needs layer, type and name, or an elements list\", ErrorCategory.USER, [\n 'Single: {layer: \"api\", type: \"operation\", name: \"Create Order\"}',\n \"Batch: {elements: [{layer, type, name}, ...], relationships: [{source, predicate, target}, ...]}\",\n ]);\n }\n return addSingleElement({ ...args, layer: args.layer, type: args.type, name: args.name }, args.rootPath);\n });\n}\n\nasync function addSingleElement(spec: ElementSpec, rootPath: string | undefined): Promise<CallToolResult> {\n const prepared = await prepareElement(spec);\n const { element, id: elementPath, layer } = prepared;\n\n const model = await loadModel(rootPath);\n\n // Inside a changeset getLayer() projects even a layer the model has no elements in, so ask the\n // model's layer list whether this layer is new to it.\n const layerKnown = model.getLayerNames().includes(layer);\n let layerObj = await model.getLayer(layer);\n let isNewLayer = false;\n if (!layerObj) {\n layerObj = new Layer(layer);\n isNewLayer = true;\n }\n\n if (layerObj.getElement(elementPath)) {\n throw new CLIError(`Element ${elementPath} already exists in ${layer} layer`, ErrorCategory.USER, [\n `Use \"model_show\" to view the existing element`,\n `Use \"model_update\" to modify it`,\n `Use \"model_delete\" to remove it first if you want to recreate it`,\n ]);\n }\n\n if (isNewLayer) {\n model.addLayer(layerObj);\n }\n\n const mutationHandler = new MutationHandler(model, elementPath, layer);\n await mutationHandler.executeAdd(element, (elem) => {\n layerObj!.addElement(elem);\n });\n\n const stagingManager = mutationHandler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n const staged = !!(activeChangeset && activeChangeset.status === \"staged\");\n if (staged && !layerKnown) {\n // The cached model did not list this layer: reread it so every later tool call\n // (relationship_add, model_show, model_update, ...) sees the layer and the element.\n await reloadModel(rootPath);\n }\n\n return jsonResult({\n status: staged ? \"staged\" : \"added\",\n changeset: staged ? activeChangeset!.name : undefined,\n id: elementPath,\n layer,\n type: prepared.type,\n name: spec.name,\n ...(prepared.warnings.length > 0 ? { warnings: prepared.warnings } : {}),\n });\n}\n\ninterface ElementBatchResult {\n index: number;\n id?: string;\n name: string;\n status: \"staged\" | \"added\" | \"invalid\";\n reason?: string;\n suggestions?: string[];\n warnings?: string[];\n}\n\n/**\n * model_add's batch form: validate every element and relationship, then stage the valid ones in\n * one write (or, with no active changeset, write them to the model).\n */\nasync function addElementBatch(\n specs: ElementSpec[],\n relationships: z.infer<typeof relationshipItemSchema>[],\n rootPath: string | undefined\n) {\n const model = await loadModel(rootPath);\n const manager = new StagingAreaManager(model.rootPath, model);\n const active = await activeStagedChangeset(manager);\n const changeset = active ?? previewChangeset();\n const graph = await ChangesetGraph.build(model, changeset);\n\n const prepared: PreparedElement[] = [];\n const pending = new Map<string, PendingElement>();\n const rejected = new Map<string, string>();\n const results: ElementBatchResult[] = [];\n\n for (const [index, spec] of specs.entries()) {\n const asSent = { index, name: spec.name };\n let item: PreparedElement;\n try {\n item = await prepareElement(spec);\n } catch (error) {\n const id = idFor(spec);\n if (id) rejected.set(id, getErrorMessage(error));\n results.push({\n ...asSent,\n ...(id ? { id } : {}),\n status: \"invalid\",\n reason: getErrorMessage(error),\n ...(error instanceof CLIError && error.suggestions?.length ? { suggestions: error.suggestions } : {}),\n });\n continue;\n }\n const existing = graph.getElement(item.id);\n if (existing && existing.status !== \"deleted\") {\n results.push({\n ...asSent,\n id: item.id,\n status: \"invalid\",\n reason: `Element ${item.id} already exists`,\n suggestions: ['Use \"model_update\" to change it'],\n });\n continue;\n }\n if (pending.has(item.id)) {\n results.push({ ...asSent, id: item.id, status: \"invalid\", reason: \"Repeated earlier in this batch\" });\n continue;\n }\n pending.set(item.id, { id: item.id, layer: item.layer, type: item.type });\n prepared.push(item);\n results.push({\n ...asSent,\n id: item.id,\n status: active ? \"staged\" : \"added\",\n ...(item.warnings.length > 0 ? { warnings: item.warnings } : {}),\n });\n }\n\n const plan = await planRelationshipBatch(graph, changeset, relationships, {\n pending,\n rejected,\n addStatus: active ? \"staged\" : \"added\",\n });\n\n if (active) {\n const elementChanges: Array<Omit<StagedChange, \"sequenceNumber\">> = prepared.map((p) => ({\n type: \"add\",\n elementId: p.id,\n layerName: p.layer,\n after: p.element.toJSON() as unknown as Record<string, unknown>,\n }));\n await applyRelationshipPlan(model, manager, active, plan, elementChanges);\n } else {\n for (const p of prepared) {\n await writeElement(model, p);\n }\n await applyRelationshipPlan(model, manager, null, plan, []);\n }\n if (prepared.length > 0 || plan.changes.length > 0 || plan.unstageKeys.length > 0) {\n await reloadModel(rootPath);\n }\n\n return {\n ...(active ? { changeset: active.name } : {}),\n elements: { counts: countByStatus(results), results },\n ...(relationships.length > 0\n ? { relationships: { counts: countByStatus(plan.results), results: plan.results } }\n : {}),\n };\n}\n\n/** Writes one element to the base model (no changeset is active). */\nasync function writeElement(model: Model, prepared: PreparedElement): Promise<void> {\n let layerObj = await model.getLayer(prepared.layer);\n if (!layerObj) {\n layerObj = new Layer(prepared.layer);\n model.addLayer(layerObj);\n }\n const target = layerObj;\n const handler = new MutationHandler(model, prepared.id, prepared.layer);\n await handler.executeAdd(prepared.element, (elem) => {\n target.addElement(elem);\n });\n}\n\n/** The id an element spec would get, when its layer and type are valid. */\nfunction idFor(spec: ElementSpec): string | undefined {\n if (!isValidLayer(spec.layer) || !isValidNodeType(spec.layer, spec.type)) return undefined;\n const id = generateElementId(spec.layer, normalizeNodeType(spec.layer, spec.type), spec.name);\n return id.split(\".\")[2] ? id : undefined;\n}\n\nexport const modelAddTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_add\",\n description:\n \"Add elements, validated against their spec schemas. Send one (layer/type/name) or many (elements: [...], \" +\n \"with optional relationships: [...] that may name the new elements); a list is staged in one write, so use it \" +\n \"when adding several. A list returns a result per element and per relationship: staged (added, with no \" +\n \"changeset active), restored or duplicate (relationships), or invalid with the reason. Invalid items are \" +\n \"skipped; the rest are still staged.\",\n inputSchema,\n handler: modelAddHandler,\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,7 @@ import { MutationHandler } from "../../core/mutation-handler.js";
4
4
  import { ReferenceRegistry } from "../../core/reference-registry.js";
5
5
  import { findElementLayer } from "../../utils/element-utils.js";
6
6
  import { CLIError, ErrorCategory, getErrorMessage } from "../../utils/errors.js";
7
- import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
7
+ import { jsonResult, loadModel, reloadModel, rootPathSchema, runTool } from "./shared.js";
8
8
  const inputSchema = {
9
9
  id: z.string().describe("Element ID or path to delete."),
10
10
  cascade: z.boolean().optional().describe("Also delete elements that depend on this one."),
@@ -76,7 +76,7 @@ async function modelDeleteHandler(args) {
76
76
  const mutationHandler = new MutationHandler(model, args.id, layerName);
77
77
  await mutationHandler.executeDelete(element);
78
78
  const activeChangeset = await mutationHandler.getStagingManager().getActive(), staged = !!(activeChangeset && activeChangeset.status === "staged");
79
- return jsonResult({
79
+ return staged && await reloadModel(args.rootPath), jsonResult({
80
80
  status: staged ? "staged" : "deleted",
81
81
  changeset: staged ? activeChangeset.name : void 0,
82
82
  id: args.id,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mcp/tools/model-delete.ts"],
4
- "sourcesContent": ["/**\n * model_delete \u2014 delete an element (optionally cascading to dependents).\n * Mirrors `dr delete`, but since an MCP session has no interactive confirmation\n * channel, the caller must pass `force` or `cascade` explicitly when dependents\n * exist rather than being prompted; operates through the shared MutationHandler.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { DependencyTracker, TraceDirection } from \"../../core/dependency-tracker.js\";\nimport { MutationHandler } from \"../../core/mutation-handler.js\";\nimport { ReferenceRegistry } from \"../../core/reference-registry.js\";\nimport { findElementLayer } from \"../../utils/element-utils.js\";\nimport { CLIError, ErrorCategory, getErrorMessage } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n id: z.string().describe(\"Element ID or path to delete.\"),\n cascade: z.boolean().optional().describe(\"Also delete elements that depend on this one.\"),\n force: z.boolean().optional().describe(\"Skip the dependency check and delete only this element, even if others depend on it.\"),\n dryRun: z.boolean().optional().describe(\"Preview what would be deleted without making changes.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelDeleteArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelDeleteHandler(args: ModelDeleteArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n\n const layerName = await findElementLayer(model, args.id);\n if (!layerName) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n ]);\n }\n\n const layer = (await model.getLayer(layerName))!;\n const element = layer.getElement(args.id);\n if (!element) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n ]);\n }\n\n // Cascade is scoped to cross-layer references only, matching `dr delete`. This is\n // narrower than \"model_trace\", which also follows intra-layer relationships.yaml\n // edges \u2014 a dependent found by model_trace may not be included in a cascade delete.\n const registry = new ReferenceRegistry();\n for (const l of model.layers.values()) {\n for (const el of l.listElements()) {\n registry.registerElement(el);\n }\n }\n const tracker = new DependencyTracker(registry, model);\n const dependents = tracker.traceDependencies(args.id, TraceDirection.DOWN, null);\n\n if (dependents.length > 0 && !args.cascade && !args.force) {\n throw new CLIError(\"Element has dependencies\", ErrorCategory.USER, [\n \"Use cascade=true to remove all dependent elements\",\n \"Use dryRun=true with cascade=true to preview what would be deleted\",\n \"Or use force=true to remove only this element (dependencies will reference a non-existent element)\",\n ]);\n }\n\n const elementsToRemove = args.cascade ? [args.id, ...dependents] : [args.id];\n\n if (args.dryRun) {\n return jsonResult({\n status: \"dry-run\",\n id: args.id,\n layer: layerName,\n elementsToRemove,\n });\n }\n\n let deletedCount = 0;\n const skippedDependents: string[] = [];\n const cascadeDeleted: string[] = [];\n if (args.cascade && dependents.length > 0) {\n for (const depId of [...dependents].reverse()) {\n const depLayerName = await findElementLayer(model, depId);\n if (!depLayerName) {\n console.error(`[mcp] model_delete: cascade dependent \"${depId}\" not found, skipping`);\n skippedDependents.push(depId);\n continue;\n }\n\n const depLayer = (await model.getLayer(depLayerName))!;\n const depElement = depLayer.getElement(depId);\n if (!depElement) {\n console.error(`[mcp] model_delete: cascade dependent \"${depId}\" not found, skipping`);\n skippedDependents.push(depId);\n continue;\n }\n\n const depHandler = new MutationHandler(model, depId, depLayerName);\n try {\n await depHandler.executeDelete(depElement);\n } catch (error) {\n throw new CLIError(\n `Failed to delete dependent element \"${depId}\": ${getErrorMessage(error)}`,\n ErrorCategory.SYSTEM,\n [\n `${cascadeDeleted.length} dependent element(s) were deleted before the error`,\n 'Use \"model_validate\" to check the model for broken references',\n `\"${args.id}\" was not deleted \u2014 you can retry the operation once dependents are resolved`,\n ],\n {\n operation: \"model_delete (cascade)\",\n relatedElements: cascadeDeleted,\n partialProgress: { completed: cascadeDeleted.length, total: dependents.length },\n }\n );\n }\n cascadeDeleted.push(depId);\n deletedCount++;\n }\n }\n\n const mutationHandler = new MutationHandler(model, args.id, layerName);\n await mutationHandler.executeDelete(element);\n\n const stagingManager = mutationHandler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n const staged = !!(activeChangeset && activeChangeset.status === \"staged\");\n\n return jsonResult({\n status: staged ? \"staged\" : \"deleted\",\n changeset: staged ? activeChangeset!.name : undefined,\n id: args.id,\n layer: layerName,\n cascadedDeletes: deletedCount,\n ...(skippedDependents.length > 0 ? { skippedDependents } : {}),\n });\n });\n}\n\nexport const modelDeleteTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_delete\",\n description: \"Delete an element, optionally cascading to elements that depend on it.\",\n inputSchema,\n handler: modelDeleteHandler,\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * model_delete \u2014 delete an element (optionally cascading to dependents).\n * Mirrors `dr delete`, but since an MCP session has no interactive confirmation\n * channel, the caller must pass `force` or `cascade` explicitly when dependents\n * exist rather than being prompted; operates through the shared MutationHandler.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { DependencyTracker, TraceDirection } from \"../../core/dependency-tracker.js\";\nimport { MutationHandler } from \"../../core/mutation-handler.js\";\nimport { ReferenceRegistry } from \"../../core/reference-registry.js\";\nimport { findElementLayer } from \"../../utils/element-utils.js\";\nimport { CLIError, ErrorCategory, getErrorMessage } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, reloadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n id: z.string().describe(\"Element ID or path to delete.\"),\n cascade: z.boolean().optional().describe(\"Also delete elements that depend on this one.\"),\n force: z.boolean().optional().describe(\"Skip the dependency check and delete only this element, even if others depend on it.\"),\n dryRun: z.boolean().optional().describe(\"Preview what would be deleted without making changes.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelDeleteArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelDeleteHandler(args: ModelDeleteArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n\n const layerName = await findElementLayer(model, args.id);\n if (!layerName) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n ]);\n }\n\n const layer = (await model.getLayer(layerName))!;\n const element = layer.getElement(args.id);\n if (!element) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n ]);\n }\n\n // Cascade is scoped to cross-layer references only, matching `dr delete`. This is\n // narrower than \"model_trace\", which also follows intra-layer relationships.yaml\n // edges \u2014 a dependent found by model_trace may not be included in a cascade delete.\n const registry = new ReferenceRegistry();\n for (const l of model.layers.values()) {\n for (const el of l.listElements()) {\n registry.registerElement(el);\n }\n }\n const tracker = new DependencyTracker(registry, model);\n const dependents = tracker.traceDependencies(args.id, TraceDirection.DOWN, null);\n\n if (dependents.length > 0 && !args.cascade && !args.force) {\n throw new CLIError(\"Element has dependencies\", ErrorCategory.USER, [\n \"Use cascade=true to remove all dependent elements\",\n \"Use dryRun=true with cascade=true to preview what would be deleted\",\n \"Or use force=true to remove only this element (dependencies will reference a non-existent element)\",\n ]);\n }\n\n const elementsToRemove = args.cascade ? [args.id, ...dependents] : [args.id];\n\n if (args.dryRun) {\n return jsonResult({\n status: \"dry-run\",\n id: args.id,\n layer: layerName,\n elementsToRemove,\n });\n }\n\n let deletedCount = 0;\n const skippedDependents: string[] = [];\n const cascadeDeleted: string[] = [];\n if (args.cascade && dependents.length > 0) {\n for (const depId of [...dependents].reverse()) {\n const depLayerName = await findElementLayer(model, depId);\n if (!depLayerName) {\n console.error(`[mcp] model_delete: cascade dependent \"${depId}\" not found, skipping`);\n skippedDependents.push(depId);\n continue;\n }\n\n const depLayer = (await model.getLayer(depLayerName))!;\n const depElement = depLayer.getElement(depId);\n if (!depElement) {\n console.error(`[mcp] model_delete: cascade dependent \"${depId}\" not found, skipping`);\n skippedDependents.push(depId);\n continue;\n }\n\n const depHandler = new MutationHandler(model, depId, depLayerName);\n try {\n await depHandler.executeDelete(depElement);\n } catch (error) {\n throw new CLIError(\n `Failed to delete dependent element \"${depId}\": ${getErrorMessage(error)}`,\n ErrorCategory.SYSTEM,\n [\n `${cascadeDeleted.length} dependent element(s) were deleted before the error`,\n 'Use \"model_validate\" to check the model for broken references',\n `\"${args.id}\" was not deleted \u2014 you can retry the operation once dependents are resolved`,\n ],\n {\n operation: \"model_delete (cascade)\",\n relatedElements: cascadeDeleted,\n partialProgress: { completed: cascadeDeleted.length, total: dependents.length },\n }\n );\n }\n cascadeDeleted.push(depId);\n deletedCount++;\n }\n }\n\n const mutationHandler = new MutationHandler(model, args.id, layerName);\n await mutationHandler.executeDelete(element);\n\n const stagingManager = mutationHandler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n const staged = !!(activeChangeset && activeChangeset.status === \"staged\");\n // The cached model's merged relationships still hold the rows the delete just staged for\n // removal; reload so later reads (model_validate, model_export) see the plan.\n if (staged) await reloadModel(args.rootPath);\n\n return jsonResult({\n status: staged ? \"staged\" : \"deleted\",\n changeset: staged ? activeChangeset!.name : undefined,\n id: args.id,\n layer: layerName,\n cascadedDeletes: deletedCount,\n ...(skippedDependents.length > 0 ? { skippedDependents } : {}),\n });\n });\n}\n\nexport const modelDeleteTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_delete\",\n description: \"Delete an element, optionally cascading to elements that depend on it.\",\n inputSchema,\n handler: modelDeleteHandler,\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,7 @@
1
1
  import { z } from "zod";
2
+ import { ChangesetGraph } from "../../core/changeset-graph.js";
3
+ import { StagingAreaManager } from "../../core/staging-area.js";
4
+ import { activeStagedChangeset } from "./changeset-shared.js";
2
5
  import { getAllLayerIds, isValidLayer } from "../../generated/layer-registry.js";
3
6
  import { NODE_TYPES } from "../../generated/node-types.js";
4
7
  import { CLIError, ErrorCategory, findSimilar, formatValidOptions } from "../../utils/errors.js";
@@ -67,6 +70,17 @@ async function modelSearchHandler(args) {
67
70
  });
68
71
  }
69
72
  }
73
+ const active = await activeStagedChangeset(new StagingAreaManager(model.rootPath, model));
74
+ if (active) {
75
+ const graph = await ChangesetGraph.build(model, active);
76
+ return jsonResult({
77
+ query: args.query ?? "",
78
+ sourceFile: args.sourceFile,
79
+ changeset: { id: active.id, name: active.name },
80
+ count: results.length,
81
+ results: results.map((r) => ({ ...r, changeStatus: graph.getElement(r.id)?.status ?? "unchanged" }))
82
+ });
83
+ }
70
84
  return jsonResult({
71
85
  query: args.query ?? "",
72
86
  sourceFile: args.sourceFile,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mcp/tools/model-search.ts"],
4
- "sourcesContent": ["/**\n * model_search \u2014 search for elements across the model by name/ID substring or\n * source file reference. Mirrors `dr search`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Element } from \"../../core/element.js\";\nimport { getAllLayerIds, isValidLayer } from \"../../generated/layer-registry.js\";\nimport { NODE_TYPES } from \"../../generated/node-types.js\";\nimport { CLIError, ErrorCategory, findSimilar, formatValidOptions } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n query: z\n .string()\n .optional()\n .describe(\"Text to match against element ID and name (case-insensitive substring). Ignored when sourceFile is set.\"),\n layer: z.string().optional().describe(\"Restrict search to a single layer.\"),\n type: z.string().optional().describe(\"Restrict search to a single element type.\"),\n sourceFile: z.string().optional().describe(\"Find elements whose source_reference points at this file path.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelSearchArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nfunction normalizePath(filePath: string): string {\n return filePath.replace(/^\\.\\//, \"\").replace(/\\\\/g, \"/\");\n}\n\nfunction matchesSourceFile(element: Element, sourceFilePath: string): boolean {\n const sourceRef = element.getSourceReference();\n if (!sourceRef) return false;\n\n const normalizedQuery = normalizePath(sourceFilePath);\n return (sourceRef.locations ?? []).some((loc) => normalizePath(loc.file) === normalizedQuery);\n}\n\nexport async function modelSearchHandler(args: ModelSearchArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (!args.query && !args.sourceFile && !args.layer && !args.type) {\n throw new CLIError(\n \"At least one of query, sourceFile, layer, or type must be provided\",\n ErrorCategory.USER,\n ['Use \"model_list\" to list all elements without filtering']\n );\n }\n\n if (args.layer && !isValidLayer(args.layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(args.layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Unknown layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n if (args.type) {\n const candidateTypes = args.layer\n ? Array.from(NODE_TYPES.values()).filter((t) => t.layer === args.layer)\n : Array.from(NODE_TYPES.values());\n const isKnownType = candidateTypes.some((t) => t.type === args.type);\n if (!isKnownType) {\n const validTypeNames = Array.from(new Set(candidateTypes.map((t) => t.type))).sort();\n const similar = findSimilar(args.type, validTypeNames, 3);\n const suggestions: string[] = [\n args.layer\n ? `Valid types for ${args.layer}: ${formatValidOptions(validTypeNames)}`\n : `Valid types: ${formatValidOptions(validTypeNames)}`,\n ];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(\n `Unknown element type \"${args.type}\"${args.layer ? ` for layer \"${args.layer}\"` : \"\"}`,\n ErrorCategory.USER,\n suggestions\n );\n }\n }\n\n const model = await loadModel(args.rootPath);\n const isSourceFileSearch = !!args.sourceFile;\n const queryLower = (args.query ?? \"\").toLowerCase();\n\n const results: Array<{\n layer: string;\n id: string;\n type: string;\n name: string;\n description?: string;\n sourceFile?: string;\n sourceSymbol?: string;\n }> = [];\n\n for (const layerName of model.getLayerNames()) {\n if (args.layer && layerName !== args.layer) continue;\n\n const layerObj = await model.getLayer(layerName);\n if (!layerObj) continue;\n\n for (const element of layerObj.listElements()) {\n if (args.type && element.type !== args.type) continue;\n\n if (isSourceFileSearch) {\n if (!matchesSourceFile(element, args.sourceFile!)) continue;\n } else {\n const displayId = element.path || element.id;\n const idMatch = displayId.toLowerCase().includes(queryLower);\n const nameMatch = element.name.toLowerCase().includes(queryLower);\n if (!idMatch && !nameMatch) continue;\n }\n\n let sourceFile: string | undefined;\n let sourceSymbol: string | undefined;\n const sourceRef = element.getSourceReference();\n if (sourceRef?.locations && sourceRef.locations.length > 0) {\n sourceFile = sourceRef.locations[0].file;\n sourceSymbol = sourceRef.locations[0].symbol;\n }\n\n results.push({\n layer: layerName,\n id: element.path || element.id,\n type: element.type,\n name: element.name,\n description: element.description,\n sourceFile,\n sourceSymbol,\n });\n }\n }\n\n return jsonResult({\n query: args.query ?? \"\",\n sourceFile: args.sourceFile,\n count: results.length,\n results,\n });\n });\n}\n\nexport const modelSearchTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_search\",\n description: \"Search for elements across the model by name/ID substring or by source file reference.\",\n inputSchema,\n handler: modelSearchHandler,\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * model_search \u2014 search for elements across the model by name/ID substring or\n * source file reference. Mirrors `dr search`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Element } from \"../../core/element.js\";\nimport { ChangesetGraph } from \"../../core/changeset-graph.js\";\nimport { StagingAreaManager } from \"../../core/staging-area.js\";\nimport { activeStagedChangeset } from \"./changeset-shared.js\";\nimport { getAllLayerIds, isValidLayer } from \"../../generated/layer-registry.js\";\nimport { NODE_TYPES } from \"../../generated/node-types.js\";\nimport { CLIError, ErrorCategory, findSimilar, formatValidOptions } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n query: z\n .string()\n .optional()\n .describe(\"Text to match against element ID and name (case-insensitive substring). Ignored when sourceFile is set.\"),\n layer: z.string().optional().describe(\"Restrict search to a single layer.\"),\n type: z.string().optional().describe(\"Restrict search to a single element type.\"),\n sourceFile: z.string().optional().describe(\"Find elements whose source_reference points at this file path.\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelSearchArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nfunction normalizePath(filePath: string): string {\n return filePath.replace(/^\\.\\//, \"\").replace(/\\\\/g, \"/\");\n}\n\nfunction matchesSourceFile(element: Element, sourceFilePath: string): boolean {\n const sourceRef = element.getSourceReference();\n if (!sourceRef) return false;\n\n const normalizedQuery = normalizePath(sourceFilePath);\n return (sourceRef.locations ?? []).some((loc) => normalizePath(loc.file) === normalizedQuery);\n}\n\nexport async function modelSearchHandler(args: ModelSearchArgs): Promise<CallToolResult> {\n return runTool(async () => {\n if (!args.query && !args.sourceFile && !args.layer && !args.type) {\n throw new CLIError(\n \"At least one of query, sourceFile, layer, or type must be provided\",\n ErrorCategory.USER,\n ['Use \"model_list\" to list all elements without filtering']\n );\n }\n\n if (args.layer && !isValidLayer(args.layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(args.layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(`Unknown layer \"${args.layer}\"`, ErrorCategory.USER, suggestions);\n }\n\n if (args.type) {\n const candidateTypes = args.layer\n ? Array.from(NODE_TYPES.values()).filter((t) => t.layer === args.layer)\n : Array.from(NODE_TYPES.values());\n const isKnownType = candidateTypes.some((t) => t.type === args.type);\n if (!isKnownType) {\n const validTypeNames = Array.from(new Set(candidateTypes.map((t) => t.type))).sort();\n const similar = findSimilar(args.type, validTypeNames, 3);\n const suggestions: string[] = [\n args.layer\n ? `Valid types for ${args.layer}: ${formatValidOptions(validTypeNames)}`\n : `Valid types: ${formatValidOptions(validTypeNames)}`,\n ];\n if (similar.length > 0) suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n throw new CLIError(\n `Unknown element type \"${args.type}\"${args.layer ? ` for layer \"${args.layer}\"` : \"\"}`,\n ErrorCategory.USER,\n suggestions\n );\n }\n }\n\n const model = await loadModel(args.rootPath);\n const isSourceFileSearch = !!args.sourceFile;\n const queryLower = (args.query ?? \"\").toLowerCase();\n\n const results: Array<{\n layer: string;\n id: string;\n type: string;\n name: string;\n description?: string;\n sourceFile?: string;\n sourceSymbol?: string;\n }> = [];\n\n for (const layerName of model.getLayerNames()) {\n if (args.layer && layerName !== args.layer) continue;\n\n const layerObj = await model.getLayer(layerName);\n if (!layerObj) continue;\n\n for (const element of layerObj.listElements()) {\n if (args.type && element.type !== args.type) continue;\n\n if (isSourceFileSearch) {\n if (!matchesSourceFile(element, args.sourceFile!)) continue;\n } else {\n const displayId = element.path || element.id;\n const idMatch = displayId.toLowerCase().includes(queryLower);\n const nameMatch = element.name.toLowerCase().includes(queryLower);\n if (!idMatch && !nameMatch) continue;\n }\n\n let sourceFile: string | undefined;\n let sourceSymbol: string | undefined;\n const sourceRef = element.getSourceReference();\n if (sourceRef?.locations && sourceRef.locations.length > 0) {\n sourceFile = sourceRef.locations[0].file;\n sourceSymbol = sourceRef.locations[0].symbol;\n }\n\n results.push({\n layer: layerName,\n id: element.path || element.id,\n type: element.type,\n name: element.name,\n description: element.description,\n sourceFile,\n sourceSymbol,\n });\n }\n }\n\n // Inside an active changeset, say which results the changeset adds or updates.\n const active = await activeStagedChangeset(new StagingAreaManager(model.rootPath, model));\n if (active) {\n const graph = await ChangesetGraph.build(model, active);\n return jsonResult({\n query: args.query ?? \"\",\n sourceFile: args.sourceFile,\n changeset: { id: active.id, name: active.name },\n count: results.length,\n results: results.map((r) => ({ ...r, changeStatus: graph.getElement(r.id)?.status ?? \"unchanged\" })),\n });\n }\n\n return jsonResult({\n query: args.query ?? \"\",\n sourceFile: args.sourceFile,\n count: results.length,\n results,\n });\n });\n}\n\nexport const modelSearchTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_search\",\n description: \"Search for elements across the model by name/ID substring or by source file reference.\",\n inputSchema,\n handler: modelSearchHandler,\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,8 @@
1
1
  import { z } from "zod";
2
+ import { ChangesetGraph } from "../../core/changeset-graph.js";
3
+ import { StagingAreaManager } from "../../core/staging-area.js";
2
4
  import { findElementLayer } from "../../utils/element-utils.js";
5
+ import { activeStagedChangeset } from "./changeset-shared.js";
3
6
  import { CLIError, ErrorCategory } from "../../utils/errors.js";
4
7
  import { jsonResult, loadModel, rootPathSchema, runTool } from "./shared.js";
5
8
  const inputSchema = {
@@ -20,7 +23,31 @@ async function modelShowHandler(args) {
20
23
  'Use "model_search" to find similar elements',
21
24
  'Use "model_list" to list all elements in a layer'
22
25
  ]);
23
- const elementId = element.path || element.id, { outgoing, incoming } = model.relationships.getForElement(elementId);
26
+ const elementId = element.path || element.id, active = await activeStagedChangeset(new StagingAreaManager(model.rootPath, model));
27
+ if (active) {
28
+ const graph = await ChangesetGraph.build(model, active), graphElement = graph.getElement(elementId), neighbors = graph.neighbors(elementId, { includeDeleted: !0 }), row = (n) => {
29
+ const rel = n.relationship;
30
+ return {
31
+ source: rel.source,
32
+ predicate: rel.predicate,
33
+ target: rel.target,
34
+ layer: rel.layer,
35
+ ...rel.targetLayer ? { targetLayer: rel.targetLayer } : {},
36
+ ...rel.properties ? { properties: rel.properties } : {},
37
+ status: rel.status
38
+ };
39
+ };
40
+ return jsonResult({
41
+ layer: layerName,
42
+ element: element.toJSON(),
43
+ changeset: { id: active.id, name: active.name, elementStatus: graphElement?.status ?? "unchanged" },
44
+ relationships: {
45
+ outgoing: neighbors.filter((n) => n.direction === "out").map(row),
46
+ incoming: neighbors.filter((n) => n.direction === "in").map(row)
47
+ }
48
+ });
49
+ }
50
+ const { outgoing, incoming } = model.relationships.getForElement(elementId);
24
51
  return jsonResult({
25
52
  layer: layerName,
26
53
  element: element.toJSON(),
@@ -30,7 +57,7 @@ async function modelShowHandler(args) {
30
57
  }
31
58
  const modelShowTool = {
32
59
  name: "model_show",
33
- description: "Show a single element's full details, attributes, and relationships.",
60
+ description: "Show a single element's full details, attributes, and relationships. Inside an active changeset the relationships include staged ones, each with a status (added, deleted, unchanged).",
34
61
  inputSchema,
35
62
  handler: modelShowHandler
36
63
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mcp/tools/model-show.ts"],
4
- "sourcesContent": ["/**\n * model_show \u2014 show a single element with its relationships. Mirrors `dr show`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { findElementLayer } from \"../../utils/element-utils.js\";\nimport { CLIError, ErrorCategory } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n id: z.string().describe(\"Element ID or path (e.g. 'api.operation.create-order').\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelShowArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelShowHandler(args: ModelShowArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n\n const layerName = await findElementLayer(model, args.id);\n if (!layerName) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n 'Use \"model_list\" to list all elements in a layer',\n ]);\n }\n\n const layer = await model.getLayer(layerName);\n const element = layer?.getElement(args.id);\n if (!layer || !element) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n 'Use \"model_list\" to list all elements in a layer',\n ]);\n }\n\n const elementId = element.path || element.id;\n const { outgoing, incoming } = model.relationships.getForElement(elementId);\n\n return jsonResult({\n layer: layerName,\n element: element.toJSON(),\n relationships: { outgoing, incoming },\n });\n });\n}\n\nexport const modelShowTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_show\",\n description: \"Show a single element's full details, attributes, and relationships.\",\n inputSchema,\n handler: modelShowHandler,\n};\n"],
5
- "mappings": "AAIA,SAAS,SAAS;AAElB,SAAS,wBAAwB;AACjC,SAAS,UAAU,qBAAqB;AACxC,SAAS,YAAY,WAAW,gBAAgB,eAAuC;AAEvF,MAAM,cAAc;EAClB,IAAI,EAAE,OAAM,EAAG,SAAS,yDAAyD;EACjF,UAAU;;AAKZ,eAAsB,iBAAiB,MAAmB;AACxD,SAAO,QAAQ,YAAW;AACxB,UAAM,QAAQ,MAAM,UAAU,KAAK,QAAQ,GAErC,YAAY,MAAM,iBAAiB,OAAO,KAAK,EAAE;AACvD,QAAI,CAAC;AACH,YAAM,IAAI,SAAS,WAAW,KAAK,EAAE,cAAc,cAAc,WAAW;QAC1E;QACA;OACD;AAGH,UAAM,QAAQ,MAAM,MAAM,SAAS,SAAS,GACtC,UAAU,OAAO,WAAW,KAAK,EAAE;AACzC,QAAI,CAAC,SAAS,CAAC;AACb,YAAM,IAAI,SAAS,WAAW,KAAK,EAAE,cAAc,cAAc,WAAW;QAC1E;QACA;OACD;AAGH,UAAM,YAAY,QAAQ,QAAQ,QAAQ,IACpC,EAAE,UAAU,SAAQ,IAAK,MAAM,cAAc,cAAc,SAAS;AAE1E,WAAO,WAAW;MAChB,OAAO;MACP,SAAS,QAAQ,OAAM;MACvB,eAAe,EAAE,UAAU,SAAQ;KACpC;EACH,CAAC;AACH;AAEO,MAAM,gBAAuD;EAClE,MAAM;EACN,aAAa;EACb;EACA,SAAS;;",
4
+ "sourcesContent": ["/**\n * model_show \u2014 show a single element with its relationships. Mirrors `dr show`.\n */\n\nimport { z } from \"zod\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { ChangesetGraph } from \"../../core/changeset-graph.js\";\nimport { StagingAreaManager } from \"../../core/staging-area.js\";\nimport { findElementLayer } from \"../../utils/element-utils.js\";\nimport { activeStagedChangeset } from \"./changeset-shared.js\";\nimport { CLIError, ErrorCategory } from \"../../utils/errors.js\";\nimport { jsonResult, loadModel, rootPathSchema, runTool, type McpToolDefinition } from \"./shared.js\";\n\nconst inputSchema = {\n id: z.string().describe(\"Element ID or path (e.g. 'api.operation.create-order').\"),\n rootPath: rootPathSchema,\n};\n\nexport type ModelShowArgs = z.infer<z.ZodObject<typeof inputSchema>>;\n\nexport async function modelShowHandler(args: ModelShowArgs): Promise<CallToolResult> {\n return runTool(async () => {\n const model = await loadModel(args.rootPath);\n\n const layerName = await findElementLayer(model, args.id);\n if (!layerName) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n 'Use \"model_list\" to list all elements in a layer',\n ]);\n }\n\n const layer = await model.getLayer(layerName);\n const element = layer?.getElement(args.id);\n if (!layer || !element) {\n throw new CLIError(`Element ${args.id} not found`, ErrorCategory.NOT_FOUND, [\n 'Use \"model_search\" to find similar elements',\n 'Use \"model_list\" to list all elements in a layer',\n ]);\n }\n\n const elementId = element.path || element.id;\n\n // Inside an active changeset, show the element's relationships as the changeset leaves them:\n // staged additions included, staged removals marked, each with its change status.\n const active = await activeStagedChangeset(new StagingAreaManager(model.rootPath, model));\n if (active) {\n const graph = await ChangesetGraph.build(model, active);\n const graphElement = graph.getElement(elementId);\n const neighbors = graph.neighbors(elementId, { includeDeleted: true });\n const row = (n: (typeof neighbors)[number]) => {\n const rel = n.relationship;\n return {\n source: rel.source,\n predicate: rel.predicate,\n target: rel.target,\n layer: rel.layer,\n ...(rel.targetLayer ? { targetLayer: rel.targetLayer } : {}),\n ...(rel.properties ? { properties: rel.properties } : {}),\n status: rel.status,\n };\n };\n return jsonResult({\n layer: layerName,\n element: element.toJSON(),\n changeset: { id: active.id, name: active.name, elementStatus: graphElement?.status ?? \"unchanged\" },\n relationships: {\n outgoing: neighbors.filter((n) => n.direction === \"out\").map(row),\n incoming: neighbors.filter((n) => n.direction === \"in\").map(row),\n },\n });\n }\n\n const { outgoing, incoming } = model.relationships.getForElement(elementId);\n\n return jsonResult({\n layer: layerName,\n element: element.toJSON(),\n relationships: { outgoing, incoming },\n });\n });\n}\n\nexport const modelShowTool: McpToolDefinition<typeof inputSchema> = {\n name: \"model_show\",\n description:\n \"Show a single element's full details, attributes, and relationships. Inside an active changeset the \" +\n \"relationships include staged ones, each with a status (added, deleted, unchanged).\",\n inputSchema,\n handler: modelShowHandler,\n};\n"],
5
+ "mappings": "AAIA,SAAS,SAAS;AAElB,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AACtC,SAAS,UAAU,qBAAqB;AACxC,SAAS,YAAY,WAAW,gBAAgB,eAAuC;AAEvF,MAAM,cAAc;EAClB,IAAI,EAAE,OAAM,EAAG,SAAS,yDAAyD;EACjF,UAAU;;AAKZ,eAAsB,iBAAiB,MAAmB;AACxD,SAAO,QAAQ,YAAW;AACxB,UAAM,QAAQ,MAAM,UAAU,KAAK,QAAQ,GAErC,YAAY,MAAM,iBAAiB,OAAO,KAAK,EAAE;AACvD,QAAI,CAAC;AACH,YAAM,IAAI,SAAS,WAAW,KAAK,EAAE,cAAc,cAAc,WAAW;QAC1E;QACA;OACD;AAGH,UAAM,QAAQ,MAAM,MAAM,SAAS,SAAS,GACtC,UAAU,OAAO,WAAW,KAAK,EAAE;AACzC,QAAI,CAAC,SAAS,CAAC;AACb,YAAM,IAAI,SAAS,WAAW,KAAK,EAAE,cAAc,cAAc,WAAW;QAC1E;QACA;OACD;AAGH,UAAM,YAAY,QAAQ,QAAQ,QAAQ,IAIpC,SAAS,MAAM,sBAAsB,IAAI,mBAAmB,MAAM,UAAU,KAAK,CAAC;AACxF,QAAI,QAAQ;AACV,YAAM,QAAQ,MAAM,eAAe,MAAM,OAAO,MAAM,GAChD,eAAe,MAAM,WAAW,SAAS,GACzC,YAAY,MAAM,UAAU,WAAW,EAAE,gBAAgB,GAAI,CAAE,GAC/D,MAAM,CAAC,MAAiC;AAC5C,cAAM,MAAM,EAAE;AACd,eAAO;UACL,QAAQ,IAAI;UACZ,WAAW,IAAI;UACf,QAAQ,IAAI;UACZ,OAAO,IAAI;UACX,GAAI,IAAI,cAAc,EAAE,aAAa,IAAI,YAAW,IAAK,CAAA;UACzD,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,WAAU,IAAK,CAAA;UACtD,QAAQ,IAAI;;MAEhB;AACA,aAAO,WAAW;QAChB,OAAO;QACP,SAAS,QAAQ,OAAM;QACvB,WAAW,EAAE,IAAI,OAAO,IAAI,MAAM,OAAO,MAAM,eAAe,cAAc,UAAU,YAAW;QACjG,eAAe;UACb,UAAU,UAAU,OAAO,CAAC,MAAM,EAAE,cAAc,KAAK,EAAE,IAAI,GAAG;UAChE,UAAU,UAAU,OAAO,CAAC,MAAM,EAAE,cAAc,IAAI,EAAE,IAAI,GAAG;;OAElE;IACH;AAEA,UAAM,EAAE,UAAU,SAAQ,IAAK,MAAM,cAAc,cAAc,SAAS;AAE1E,WAAO,WAAW;MAChB,OAAO;MACP,SAAS,QAAQ,OAAM;MACvB,eAAe,EAAE,UAAU,SAAQ;KACpC;EACH,CAAC;AACH;AAEO,MAAM,gBAAuD;EAClE,MAAM;EACN,aACE;EAEF;EACA,SAAS;;",
6
6
  "names": []
7
7
  }