vgxness 1.20.4 → 1.20.6

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 (375) hide show
  1. package/dist/adapters/claude/agent-renderer.js +82 -0
  2. package/dist/{mcp → adapters/claude/install}/claude-code-agent-config.js +64 -9
  3. package/dist/{mcp → adapters/claude/install}/claude-code-config.js +28 -6
  4. package/dist/{mcp → adapters/claude/install}/claude-code-project-memory.js +35 -5
  5. package/dist/{mcp → adapters/claude/install}/claude-code-scope.js +12 -3
  6. package/dist/{mcp → adapters/claude/install}/claude-code-user-config.js +26 -5
  7. package/dist/{mcp → adapters/claude/install}/claude-code-user-memory.js +47 -7
  8. package/dist/{mcp → adapters/claude/install}/client-install-claude-code-contract.js +45 -8
  9. package/dist/{mcp → adapters/claude/install}/client-install-claude-code.js +98 -14
  10. package/dist/adapters/json/agent-renderer.js +104 -0
  11. package/dist/adapters/opencode/agent-renderer.js +113 -0
  12. package/dist/{mcp → adapters/opencode/install}/client-install-opencode-contract.js +2 -2
  13. package/dist/{mcp → adapters/opencode/install}/client-install-opencode.js +1 -1
  14. package/dist/{mcp → adapters/opencode/install}/opencode-default-agent-config.js +2 -2
  15. package/dist/{mcp → adapters/opencode/install}/opencode-handoff-preview.js +60 -7
  16. package/dist/{mcp → adapters/opencode/install}/opencode-visibility.js +1 -1
  17. package/dist/adapters/provider-renderer.js +6 -0
  18. package/dist/agents/agent-activation-service.js +1 -263
  19. package/dist/agents/agent-lookup-contexts.js +1 -28
  20. package/dist/agents/agent-registry-service.js +1 -81
  21. package/dist/agents/agent-resolver.js +1 -287
  22. package/dist/agents/agent-seed-service.js +1 -157
  23. package/dist/agents/agent-seed-upgrade-service.js +1 -231
  24. package/dist/agents/agent-selector-resolver.js +1 -28
  25. package/dist/agents/boot-upgrade.js +1 -59
  26. package/dist/agents/canonical-agent-manifest.js +1 -245
  27. package/dist/agents/canonical-agent-projection.js +1 -236
  28. package/dist/agents/manager-profile-overlay-service.js +1 -60
  29. package/dist/agents/profile-model-routing.js +1 -30
  30. package/dist/agents/renderers/claude-renderer.js +1 -82
  31. package/dist/agents/renderers/index.js +1 -14
  32. package/dist/agents/renderers/json-renderer.js +1 -104
  33. package/dist/agents/renderers/opencode-renderer.js +1 -113
  34. package/dist/agents/renderers/provider-adapter.js +1 -6
  35. package/dist/agents/repositories/agent-seed-history.js +1 -128
  36. package/dist/agents/repositories/agents.js +1 -200
  37. package/dist/agents/repositories/manager-profile-overlays.js +1 -90
  38. package/dist/agents/schema.js +1 -1
  39. package/dist/application/agents/agent-activation-service.js +261 -0
  40. package/dist/application/agents/agent-lookup-contexts.js +28 -0
  41. package/dist/application/agents/agent-registry-service.js +81 -0
  42. package/dist/application/agents/agent-resolver.js +287 -0
  43. package/dist/application/agents/agent-seed-service.js +157 -0
  44. package/dist/application/agents/agent-seed-upgrade-service.js +231 -0
  45. package/dist/application/agents/agent-selector-resolver.js +28 -0
  46. package/dist/application/agents/boot-upgrade.js +59 -0
  47. package/dist/application/agents/canonical-agent-projection.js +236 -0
  48. package/dist/application/agents/manager-profile-overlay-service.js +68 -0
  49. package/dist/application/agents/profile-model-routing.js +30 -0
  50. package/dist/application/agents/renderers/claude-renderer.js +1 -0
  51. package/dist/application/agents/renderers/index.js +14 -0
  52. package/dist/application/agents/renderers/json-renderer.js +1 -0
  53. package/dist/application/agents/renderers/opencode-renderer.js +1 -0
  54. package/dist/application/agents/renderers/provider-adapter.js +1 -0
  55. package/dist/application/memory/active-work-preview.js +75 -0
  56. package/dist/application/memory/agent-memory-capture-service.js +498 -0
  57. package/dist/application/memory/import/dry-run-planner.js +58 -0
  58. package/dist/application/memory/import/index.js +3 -0
  59. package/dist/application/memory/import/observation-writer.js +226 -0
  60. package/dist/application/memory/import/package.js +179 -0
  61. package/dist/application/memory/memory-service.js +202 -0
  62. package/dist/application/memory/search.js +11 -0
  63. package/dist/{mcp → application/provider-setup}/provider-change-plan.js +74 -13
  64. package/dist/{mcp → application/provider-setup}/provider-doctor.js +201 -31
  65. package/dist/{mcp → application/provider-setup}/provider-health-types.js +1 -1
  66. package/dist/{mcp → application/provider-setup}/provider-status.js +170 -33
  67. package/dist/application/runs/execution-planning.js +180 -0
  68. package/dist/application/runs/operation-execution.js +1 -0
  69. package/dist/application/runs/operation-retry.js +129 -0
  70. package/dist/application/runs/resume-after-approval-result.js +88 -0
  71. package/dist/application/runs/run-insights.js +270 -0
  72. package/dist/application/runs/run-service.js +1480 -0
  73. package/dist/application/runs/run-snapshot-export-service.js +31 -0
  74. package/dist/application/runs/sandbox-process-execution.js +244 -0
  75. package/dist/application/runs/sandbox-worktree-planning.js +59 -0
  76. package/dist/application/runs/task-scoped-command-grant-service.js +224 -0
  77. package/dist/application/sdd/artifact-portability-service.js +137 -0
  78. package/dist/application/sdd/cockpit-read-model.js +195 -0
  79. package/dist/application/sdd/sdd-continuation-plan.js +265 -0
  80. package/dist/application/sdd/sdd-workflow-service.js +892 -0
  81. package/dist/application/skills/boot-seed.js +42 -0
  82. package/dist/application/skills/personal-skills.js +41 -0
  83. package/dist/application/skills/skill-export-service.js +34 -0
  84. package/dist/application/skills/skill-index-service.js +126 -0
  85. package/dist/application/skills/skill-payload.js +186 -0
  86. package/dist/application/skills/skill-registry-service.js +648 -0
  87. package/dist/application/skills/skill-resolver.js +368 -0
  88. package/dist/application/skills/skill-seed-service.js +242 -0
  89. package/dist/application/skills/skill-status-service.js +147 -0
  90. package/dist/cli/bun-bin.js +0 -0
  91. package/dist/cli/cli-flags.js +1 -387
  92. package/dist/cli/cli-help.js +1 -173
  93. package/dist/cli/cli-helpers.js +1 -77
  94. package/dist/cli/cli-types.js +1 -1
  95. package/dist/cli/commands/agent-skill-dispatcher.js +1 -700
  96. package/dist/cli/commands/index.js +1 -9
  97. package/dist/cli/commands/interactive-entrypoint-dispatcher.js +1 -14
  98. package/dist/cli/commands/mcp-dispatcher.js +1 -232
  99. package/dist/cli/commands/memory-sdd-dispatcher.js +1 -367
  100. package/dist/cli/commands/run-permission-dispatcher.js +1 -455
  101. package/dist/cli/commands/setup-dispatcher.js +1 -496
  102. package/dist/cli/commands/status-dispatcher.js +1 -130
  103. package/dist/cli/commands/verification-dispatcher.js +1 -47
  104. package/dist/cli/commands/workflow-dispatcher.js +1 -566
  105. package/dist/cli/dispatcher.js +1 -247
  106. package/dist/cli/doctor-renderer.js +1 -26
  107. package/dist/cli/home-tui-app.js +1 -411
  108. package/dist/cli/home-tui-controller.js +1 -314
  109. package/dist/cli/mcp-start-path.js +1 -21
  110. package/dist/cli/product-resume-renderer.js +1 -32
  111. package/dist/cli/product-status-renderer.js +1 -81
  112. package/dist/cli/sdd-renderer.js +1 -247
  113. package/dist/cli/setup-plan-renderer.js +1 -79
  114. package/dist/cli/setup-status-renderer.js +1 -50
  115. package/dist/cli/setup-tui-app.js +1 -130
  116. package/dist/cli/setup-tui-controller.js +1 -89
  117. package/dist/cli/tui/focus-reducer.js +1 -0
  118. package/dist/cli/tui/focus-types.js +1 -0
  119. package/dist/cli/tui/ink/app-shell.js +1 -0
  120. package/dist/cli/tui/ink/components.js +1 -38
  121. package/dist/cli/tui/ink/help-overlay.js +1 -0
  122. package/dist/cli/tui/ink/state-components.js +1 -0
  123. package/dist/cli/tui/ink/theme.js +1 -36
  124. package/dist/cli/tui/key-intents.js +1 -0
  125. package/dist/cli/tui/keymap.js +1 -20
  126. package/dist/cli/tui/navigation.js +1 -10
  127. package/dist/cli/tui/screen-registry.js +1 -0
  128. package/dist/cli/tui/terminal-capabilities.js +1 -12
  129. package/dist/cli/tui/tui-types.js +1 -1
  130. package/dist/cli/tui/visual/badges.js +1 -19
  131. package/dist/cli/tui/visual/footer.js +1 -27
  132. package/dist/cli/tui/visual/index.js +1 -3
  133. package/dist/cli/tui/visual/viewport.js +1 -11
  134. package/dist/cli/tui-render-helpers.js +1 -200
  135. package/dist/cli/verification-plan-renderer.js +1 -25
  136. package/dist/cli/verification-report-renderer.js +1 -19
  137. package/dist/domain/agents/canonical-agent-manifest.js +355 -0
  138. package/dist/domain/agents/schema.js +1 -0
  139. package/dist/domain/memory/active-work-topics.js +64 -0
  140. package/dist/domain/memory/memory-capture-schema.js +1 -0
  141. package/dist/domain/memory/schema.js +1 -0
  142. package/dist/domain/runs/schema.js +5 -0
  143. package/dist/domain/sdd/cockpit-types.js +1 -0
  144. package/dist/domain/sdd/schema.js +111 -0
  145. package/dist/domain/skills/schema.js +1 -0
  146. package/dist/governance/risk-classifier.js +2 -0
  147. package/dist/interfaces/cli/bun-bin.js +46 -0
  148. package/dist/interfaces/cli/cli-flags.js +391 -0
  149. package/dist/interfaces/cli/cli-help.js +173 -0
  150. package/dist/interfaces/cli/cli-helpers.js +77 -0
  151. package/dist/interfaces/cli/cli-types.js +1 -0
  152. package/dist/interfaces/cli/commands/agent-skill-dispatcher.js +700 -0
  153. package/dist/interfaces/cli/commands/index.js +9 -0
  154. package/dist/interfaces/cli/commands/interactive-entrypoint-dispatcher.js +14 -0
  155. package/dist/interfaces/cli/commands/mcp-dispatcher.js +252 -0
  156. package/dist/interfaces/cli/commands/memory-sdd-dispatcher.js +367 -0
  157. package/dist/interfaces/cli/commands/run-permission-dispatcher.js +460 -0
  158. package/dist/interfaces/cli/commands/setup-dispatcher.js +496 -0
  159. package/dist/interfaces/cli/commands/status-dispatcher.js +130 -0
  160. package/dist/interfaces/cli/commands/verification-dispatcher.js +47 -0
  161. package/dist/interfaces/cli/commands/workflow-dispatcher.js +566 -0
  162. package/dist/interfaces/cli/dispatcher.js +247 -0
  163. package/dist/interfaces/cli/doctor-renderer.js +26 -0
  164. package/dist/interfaces/cli/home-tui-app.js +462 -0
  165. package/dist/interfaces/cli/home-tui-controller.js +341 -0
  166. package/dist/interfaces/cli/index.js +27 -0
  167. package/dist/interfaces/cli/mcp-start-path.js +21 -0
  168. package/dist/interfaces/cli/product-resume-renderer.js +32 -0
  169. package/dist/interfaces/cli/product-status-renderer.js +81 -0
  170. package/dist/interfaces/cli/sdd-renderer.js +247 -0
  171. package/dist/interfaces/cli/setup-plan-renderer.js +79 -0
  172. package/dist/interfaces/cli/setup-status-renderer.js +50 -0
  173. package/dist/interfaces/cli/setup-tui-app.js +135 -0
  174. package/dist/interfaces/cli/setup-tui-controller.js +89 -0
  175. package/dist/interfaces/cli/tui/focus-reducer.js +60 -0
  176. package/dist/interfaces/cli/tui/focus-types.js +10 -0
  177. package/dist/interfaces/cli/tui/ink/app-shell.js +16 -0
  178. package/dist/interfaces/cli/tui/ink/components.js +38 -0
  179. package/dist/interfaces/cli/tui/ink/help-overlay.js +6 -0
  180. package/dist/interfaces/cli/tui/ink/state-components.js +22 -0
  181. package/dist/interfaces/cli/tui/ink/theme.js +36 -0
  182. package/dist/interfaces/cli/tui/key-intents.js +33 -0
  183. package/dist/interfaces/cli/tui/keymap.js +20 -0
  184. package/dist/interfaces/cli/tui/navigation.js +10 -0
  185. package/dist/interfaces/cli/tui/screen-registry.js +43 -0
  186. package/dist/interfaces/cli/tui/terminal-capabilities.js +12 -0
  187. package/dist/interfaces/cli/tui/tui-types.js +1 -0
  188. package/dist/interfaces/cli/tui/visual/badges.js +19 -0
  189. package/dist/interfaces/cli/tui/visual/footer.js +27 -0
  190. package/dist/interfaces/cli/tui/visual/index.js +3 -0
  191. package/dist/interfaces/cli/tui/visual/viewport.js +11 -0
  192. package/dist/interfaces/cli/tui-render-helpers.js +200 -0
  193. package/dist/interfaces/cli/verification-plan-renderer.js +25 -0
  194. package/dist/interfaces/cli/verification-report-renderer.js +19 -0
  195. package/dist/interfaces/mcp/contracts/agents.js +1 -0
  196. package/dist/interfaces/mcp/contracts/context.js +1 -0
  197. package/dist/interfaces/mcp/contracts/governance.js +1 -0
  198. package/dist/interfaces/mcp/contracts/index.js +1 -0
  199. package/dist/interfaces/mcp/contracts/memory.js +1 -0
  200. package/dist/interfaces/mcp/contracts/providers.js +1 -0
  201. package/dist/interfaces/mcp/contracts/runs.js +1 -0
  202. package/dist/interfaces/mcp/contracts/sdd.js +1 -0
  203. package/dist/interfaces/mcp/contracts/sessions.js +1 -0
  204. package/dist/interfaces/mcp/contracts/skills.js +1 -0
  205. package/dist/interfaces/mcp/contracts/verification.js +1 -0
  206. package/dist/interfaces/mcp/control-plane/handlers/agents.js +38 -0
  207. package/dist/interfaces/mcp/control-plane/handlers/context.js +12 -0
  208. package/dist/interfaces/mcp/control-plane/handlers/memory.js +95 -0
  209. package/dist/interfaces/mcp/control-plane/handlers/providers.js +19 -0
  210. package/dist/interfaces/mcp/control-plane/handlers/runs.js +134 -0
  211. package/dist/interfaces/mcp/control-plane/handlers/sdd.js +225 -0
  212. package/dist/interfaces/mcp/control-plane/handlers/sessions.js +39 -0
  213. package/dist/interfaces/mcp/control-plane/handlers/skills.js +82 -0
  214. package/dist/interfaces/mcp/control-plane/handlers/verification.js +11 -0
  215. package/dist/interfaces/mcp/control-plane/types.js +1 -0
  216. package/dist/interfaces/mcp/control-plane.js +235 -0
  217. package/dist/interfaces/mcp/schema.js +174 -0
  218. package/dist/interfaces/mcp/schemas/common.js +121 -0
  219. package/dist/interfaces/mcp/schemas/inputs/agents.js +69 -0
  220. package/dist/interfaces/mcp/schemas/inputs/context.js +32 -0
  221. package/dist/interfaces/mcp/schemas/inputs/governance.js +23 -0
  222. package/dist/interfaces/mcp/schemas/inputs/index.js +10 -0
  223. package/dist/interfaces/mcp/schemas/inputs/memory.js +50 -0
  224. package/dist/interfaces/mcp/schemas/inputs/providers.js +35 -0
  225. package/dist/interfaces/mcp/schemas/inputs/runs.js +146 -0
  226. package/dist/interfaces/mcp/schemas/inputs/sdd.js +102 -0
  227. package/dist/interfaces/mcp/schemas/inputs/sessions.js +32 -0
  228. package/dist/interfaces/mcp/schemas/inputs/skills.js +231 -0
  229. package/dist/interfaces/mcp/schemas/inputs/verification.js +9 -0
  230. package/dist/interfaces/mcp/schemas/outputs/index.js +2 -0
  231. package/dist/interfaces/mcp/schemas/outputs/providers.js +28 -0
  232. package/dist/interfaces/mcp/schemas/outputs/sdd.js +166 -0
  233. package/dist/interfaces/mcp/stdio-server.js +116 -0
  234. package/dist/interfaces/mcp/validation/agents.js +189 -0
  235. package/dist/interfaces/mcp/validation/common.js +415 -0
  236. package/dist/interfaces/mcp/validation/governance.js +50 -0
  237. package/dist/interfaces/mcp/validation/memory.js +133 -0
  238. package/dist/interfaces/mcp/validation/providers.js +94 -0
  239. package/dist/interfaces/mcp/validation/runs.js +514 -0
  240. package/dist/interfaces/mcp/validation/sdd.js +247 -0
  241. package/dist/interfaces/mcp/validation/sessions.js +51 -0
  242. package/dist/interfaces/mcp/validation/skills.js +685 -0
  243. package/dist/interfaces/mcp/validation/verification.js +24 -0
  244. package/dist/interfaces/mcp/validation.js +149 -0
  245. package/dist/mcp/control-plane-snapshot-service.js +65 -2
  246. package/dist/mcp/control-plane.js +1 -646
  247. package/dist/mcp/doctor.js +1 -1
  248. package/dist/mcp/index.js +17 -17
  249. package/dist/mcp/schema.js +1 -1072
  250. package/dist/mcp/stdio-server.js +1 -116
  251. package/dist/mcp/validation.js +1 -2239
  252. package/dist/memory/active-work-preview.js +1 -75
  253. package/dist/memory/active-work-topics.js +1 -64
  254. package/dist/memory/agent-memory-capture-service.js +1 -497
  255. package/dist/memory/import/dry-run-planner.js +1 -58
  256. package/dist/memory/import/index.js +1 -3
  257. package/dist/memory/import/observation-writer.js +1 -226
  258. package/dist/memory/import/package.js +1 -179
  259. package/dist/memory/memory-capture-schema.js +1 -1
  260. package/dist/memory/memory-service.js +1 -201
  261. package/dist/memory/repositories/artifacts.js +1 -67
  262. package/dist/memory/repositories/observations.js +1 -217
  263. package/dist/memory/repositories/sessions.js +1 -125
  264. package/dist/memory/repositories/traces.js +1 -78
  265. package/dist/memory/schema.js +1 -1
  266. package/dist/memory/search.js +1 -11
  267. package/dist/memory/sqlite/database.js +1 -228
  268. package/dist/memory/storage-paths.js +1 -72
  269. package/dist/payload/context-budget-policy.js +10 -0
  270. package/dist/payload/context-budget-service.js +26 -0
  271. package/dist/payload/payload-diagnostics.js +50 -0
  272. package/dist/permissions/explicit-request-authorization.js +126 -0
  273. package/dist/permissions/policy-evaluator.js +54 -14
  274. package/dist/runs/execution-planning.js +1 -178
  275. package/dist/runs/operation-execution.js +1 -1
  276. package/dist/runs/operation-retry.js +1 -129
  277. package/dist/runs/repositories/runs.js +1 -676
  278. package/dist/runs/repositories/task-scoped-command-grants.js +1 -462
  279. package/dist/runs/resume-after-approval-result.js +1 -84
  280. package/dist/runs/run-insights.js +1 -270
  281. package/dist/runs/run-service.js +1 -1439
  282. package/dist/runs/run-snapshot-export-service.js +1 -31
  283. package/dist/runs/sandbox-process-execution.js +1 -240
  284. package/dist/runs/sandbox-worktree-planning.js +1 -59
  285. package/dist/runs/schema.js +1 -5
  286. package/dist/runs/task-scoped-command-grant-service.js +1 -216
  287. package/dist/sdd/artifact-portability-service.js +1 -137
  288. package/dist/sdd/cockpit-read-model.js +1 -195
  289. package/dist/sdd/cockpit-types.js +1 -1
  290. package/dist/sdd/schema.js +1 -111
  291. package/dist/sdd/sdd-continuation-plan.js +1 -265
  292. package/dist/sdd/sdd-workflow-service.js +1 -822
  293. package/dist/setup/providers/claude-setup-adapter.js +11 -4
  294. package/dist/setup/providers/opencode-setup-adapter.js +10 -7
  295. package/dist/setup/setup-plan.js +20 -7
  296. package/dist/skills/boot-seed.js +1 -42
  297. package/dist/skills/personal-skills.js +1 -41
  298. package/dist/skills/repositories/skill-evaluation-requests.js +1 -190
  299. package/dist/skills/repositories/skill-evaluation-scenarios.js +1 -305
  300. package/dist/skills/repositories/skill-improvement-proposals.js +1 -355
  301. package/dist/skills/repositories/skills.js +1 -1077
  302. package/dist/skills/schema.js +1 -1
  303. package/dist/skills/skill-export-service.js +1 -34
  304. package/dist/skills/skill-index-service.js +1 -126
  305. package/dist/skills/skill-payload.js +1 -186
  306. package/dist/skills/skill-registry-service.js +1 -644
  307. package/dist/skills/skill-resolver.js +1 -368
  308. package/dist/skills/skill-seed-service.js +1 -242
  309. package/dist/skills/skill-status-service.js +1 -147
  310. package/dist/storage/agents/repositories/agent-seed-history.js +128 -0
  311. package/dist/storage/agents/repositories/agents.js +200 -0
  312. package/dist/storage/agents/repositories/manager-profile-overlays.js +90 -0
  313. package/dist/storage/memory/repositories/artifacts.js +67 -0
  314. package/dist/storage/memory/repositories/observations.js +217 -0
  315. package/dist/storage/memory/repositories/sessions.js +125 -0
  316. package/dist/storage/memory/repositories/traces.js +78 -0
  317. package/dist/storage/memory/sqlite/database.js +228 -0
  318. package/dist/storage/memory/storage-paths.js +72 -0
  319. package/dist/storage/runs/repositories/runs.js +676 -0
  320. package/dist/storage/runs/repositories/task-scoped-command-grants.js +464 -0
  321. package/dist/storage/skills/repositories/skill-evaluation-requests.js +190 -0
  322. package/dist/storage/skills/repositories/skill-evaluation-scenarios.js +305 -0
  323. package/dist/storage/skills/repositories/skill-improvement-proposals.js +355 -0
  324. package/dist/storage/skills/repositories/skills.js +1084 -0
  325. package/docs/architecture.md +2 -2
  326. package/docs/glossary.md +1 -1
  327. package/docs/mcp.md +1 -1
  328. package/docs/module-boundaries.md +114 -0
  329. package/docs/prd.md +1 -1
  330. package/docs/project-health-audit-v1.10.x.md +1 -1
  331. package/docs/providers.md +2 -2
  332. package/docs/safety.md +3 -3
  333. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/apply-progress.md +122 -0
  334. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/archive-report.md +61 -0
  335. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/design.md +66 -0
  336. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/proposal.md +79 -0
  337. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/spec.md +67 -0
  338. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/tasks.md +63 -0
  339. package/docs/sdd/archive/2026-06-26-ambitious-structure-reorganization/verify-report.md +71 -0
  340. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/apply-progress.md +68 -0
  341. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/archive-report.md +61 -0
  342. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/design.md +43 -0
  343. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/proposal.md +61 -0
  344. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/spec.md +31 -0
  345. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/tasks.md +27 -0
  346. package/docs/sdd/archive/2026-06-26-legacy-facade-cleanup/verify-report.md +58 -0
  347. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/apply-progress.md +65 -0
  348. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/archive-report.md +53 -0
  349. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/design.md +64 -0
  350. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/proposal.md +62 -0
  351. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/spec.md +51 -0
  352. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/tasks.md +50 -0
  353. package/docs/sdd/archive/2026-06-26-provider-install-adapter-boundary/verify-report.md +66 -0
  354. package/docs/storage.md +2 -2
  355. package/package.json +2 -2
  356. /package/dist/{mcp → adapters/claude/install}/claude-code-cli.js +0 -0
  357. /package/dist/{memory → storage/memory}/sqlite/migrations/001_initial.sql +0 -0
  358. /package/dist/{memory → storage/memory}/sqlite/migrations/002_observation_revisions.sql +0 -0
  359. /package/dist/{memory → storage/memory}/sqlite/migrations/003_agent_registry.sql +0 -0
  360. /package/dist/{memory → storage/memory}/sqlite/migrations/004_run_runtime.sql +0 -0
  361. /package/dist/{memory → storage/memory}/sqlite/migrations/005_run_approvals.sql +0 -0
  362. /package/dist/{memory → storage/memory}/sqlite/migrations/006_run_operation_attempts.sql +0 -0
  363. /package/dist/{memory → storage/memory}/sqlite/migrations/007_abandoned_operation_attempts.sql +0 -0
  364. /package/dist/{memory → storage/memory}/sqlite/migrations/008_run_execution_plan_events.sql +0 -0
  365. /package/dist/{memory → storage/memory}/sqlite/migrations/009_multiple_operation_attempts.sql +0 -0
  366. /package/dist/{memory → storage/memory}/sqlite/migrations/010_skill_registry.sql +0 -0
  367. /package/dist/{memory → storage/memory}/sqlite/migrations/011_skill_usage_resolution_outcomes.sql +0 -0
  368. /package/dist/{memory → storage/memory}/sqlite/migrations/012_skill_improvement_proposals.sql +0 -0
  369. /package/dist/{memory → storage/memory}/sqlite/migrations/013_skill_evaluation_scenarios.sql +0 -0
  370. /package/dist/{memory → storage/memory}/sqlite/migrations/014_manager_profile_overlays.sql +0 -0
  371. /package/dist/{memory → storage/memory}/sqlite/migrations/015_artifact_metadata.sql +0 -0
  372. /package/dist/{memory → storage/memory}/sqlite/migrations/016_agent_seed_history.sql +0 -0
  373. /package/dist/{memory → storage/memory}/sqlite/migrations/017_intent_signal_skill_targets.sql +0 -0
  374. /package/dist/{memory → storage/memory}/sqlite/migrations/018_skill_system_v2.sql +0 -0
  375. /package/dist/{memory → storage/memory}/sqlite/migrations/019_task_scoped_command_grants.sql +0 -0
@@ -1,2239 +1 @@
1
- import { isRiskyPermissionCategory, permissionCategories } from '../permissions/schema.js';
2
- import { parseOperationRetryPolicy } from '../runs/operation-retry.js';
3
- import { normalizeSddPhaseInput, sddPhases } from '../sdd/schema.js';
4
- import { workflowIds } from '../workflows/schema.js';
5
- import { commandAllowlistIds } from '../workflows/command-allowlist-adapter.js';
6
- import { supportedTypeMessage, verificationChangeTypes } from '../verification/index.js';
7
- import { errorEnvelope, isVgxMcpToolName, } from './schema.js';
8
- const scopes = ['project', 'personal'];
9
- const agentModes = ['agent', 'subagent'];
10
- const memoryTypes = ['architecture', 'decision', 'bugfix', 'pattern', 'config', 'discovery', 'learning', 'preference', 'manual'];
11
- const activityKinds = ['prompt', 'tool_call', 'artifact', 'summary', 'error'];
12
- const runStatuses = ['created', 'planned', 'running', 'needs-human', 'completed', 'failed', 'blocked', 'cancelled'];
13
- const taskGrantStatuses = ['active', 'revoked', 'expired', 'exhausted'];
14
- const taskGrantCategories = ['shell', 'test-run', 'git'];
15
- const finalRunStatuses = ['completed', 'failed', 'blocked', 'cancelled'];
16
- const runOutcomes = ['success', 'partial', 'failure', 'blocked', 'cancelled'];
17
- const permissionDecisions = ['allow', 'ask', 'deny'];
18
- const payloadModes = ['compact', 'verbose'];
19
- const contextCockpitLevels = ['compact', 'expanded', 'verbose'];
20
- const skillVersionStatuses = ['draft', 'active', 'deprecated', 'archived'];
21
- const skillImprovementProposalStatuses = ['draft', 'pending-approval', 'approved', 'rejected', 'cancelled', 'applied'];
22
- const skillEvaluationRequestStatuses = ['requested', 'planned', 'running', 'completed', 'failed', 'cancelled', 'skipped'];
23
- const skillSourceKinds = ['path', 'url', 'inline'];
24
- const skillUsageOutcomes = ['selected', 'injected', 'helped', 'failed', 'neutral'];
25
- const skillAttachmentTargetTypes = ['agent', 'subagent', 'workflow-phase', 'provider-adapter', 'intent-signal'];
26
- const providerChangePlanProviders = ['opencode', 'claude', 'antigravity', 'custom'];
27
- const providerChangePlanTypes = ['opencode-mcp-install', 'claude-mcp-install', 'setup', 'install', 'config-preparation'];
28
- const providerInstallTargets = ['user-global'];
29
- const providerUserGlobalOnlyMigrationMessage = 'VGX-managed provider configuration is user-global only for OpenCode and Claude. Project/local provider files are treated as external/manual diagnostics and will not be written by VGXNESS. Use installTarget: user-global.';
30
- const validChangePattern = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
31
- const validMemoryTopicKeyPattern = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;
32
- const maxMemoryTitleLength = 200;
33
- const maxMemoryContentLength = 20_000;
34
- const maxMemoryTopicKeyLength = 200;
35
- export function validateVgxMcpToolCall(call) {
36
- const envelope = asRecord(call, undefined, 'Tool call must be an object');
37
- if (!envelope.ok)
38
- return toValidationResultFailure(envelope);
39
- const tool = readString(envelope.value, 'tool', undefined);
40
- if (!tool.ok)
41
- return toValidationResultFailure(tool);
42
- if (!isVgxMcpToolName(tool.value))
43
- return toValidationResultFailure(validationFailure(`Unsupported MCP control-plane tool: ${tool.value}`));
44
- const input = envelope.value.input;
45
- switch (tool.value) {
46
- case 'vgxness_sdd_status':
47
- return validationSuccess(tool.value, validateSddStatusInput(input, tool.value));
48
- case 'vgxness_sdd_ready':
49
- return validationSuccess(tool.value, validateSddReadyInput(input, tool.value));
50
- case 'vgxness_sdd_get_readiness':
51
- return validationSuccess(tool.value, validateSddGetReadinessInput(input, tool.value));
52
- case 'vgxness_sdd_save_artifact':
53
- return validationSuccess(tool.value, validateSddSaveArtifactInput(input, tool.value));
54
- case 'vgxness_sdd_accept_artifact':
55
- return validationSuccess(tool.value, validateSddAcceptArtifactInput(input, tool.value));
56
- case 'vgxness_sdd_reopen_artifact':
57
- return validationSuccess(tool.value, validateSddReopenArtifactInput(input, tool.value));
58
- case 'vgxness_sdd_get_artifact':
59
- return validationSuccess(tool.value, validateSddGetArtifactInput(input, tool.value));
60
- case 'vgxness_sdd_list_artifacts':
61
- return validationSuccess(tool.value, validateSddListArtifactsInput(input, tool.value));
62
- case 'vgxness_sdd_next':
63
- return validationSuccess(tool.value, validateSddNextInput(input, tool.value));
64
- case 'vgxness_sdd_cockpit':
65
- return validationSuccess(tool.value, validateSddCockpitInput(input, tool.value));
66
- case 'vgxness_sdd_continue':
67
- return validationSuccess(tool.value, validateSddContinueInput(input, tool.value));
68
- case 'vgxness_governance_report':
69
- return validationSuccess(tool.value, validateGovernanceReportInput(input, tool.value));
70
- case 'vgxness_memory_save':
71
- return validationSuccess(tool.value, validateMemorySaveInput(input, tool.value));
72
- case 'vgxness_memory_search':
73
- return validationSuccess(tool.value, validateMemorySearchInput(input, tool.value));
74
- case 'vgxness_memory_get':
75
- return validationSuccess(tool.value, validateMemoryGetInput(input, tool.value));
76
- case 'vgxness_memory_update':
77
- return validationSuccess(tool.value, validateMemoryUpdateInput(input, tool.value));
78
- case 'vgxness_session_start':
79
- return validationSuccess(tool.value, validateSessionStartInput(input, tool.value));
80
- case 'vgxness_session_append_activity':
81
- return validationSuccess(tool.value, validateSessionAppendActivityInput(input, tool.value));
82
- case 'vgxness_session_close':
83
- return validationSuccess(tool.value, validateSessionCloseInput(input, tool.value));
84
- case 'vgxness_session_restore':
85
- return validationSuccess(tool.value, validateSessionRestoreInput(input, tool.value));
86
- case 'vgxness_context_cockpit':
87
- return validationSuccess(tool.value, validateContextCockpitInput(input, tool.value));
88
- case 'vgxness_resume_context':
89
- return validationSuccess(tool.value, validateResumeContextInput(input, tool.value));
90
- case 'vgxness_agent_resolve':
91
- return validationSuccess(tool.value, validateAgentResolveInput(input, tool.value));
92
- case 'vgxness_agent_activate':
93
- return validationSuccess(tool.value, validateAgentActivateInput(input, tool.value));
94
- case 'vgxness_manager_profile_get':
95
- return validationSuccess(tool.value, validateManagerProfileGetInput(input, tool.value));
96
- case 'vgxness_manager_profile_set':
97
- return validationSuccess(tool.value, validateManagerProfileSetInput(input, tool.value));
98
- case 'vgxness_skill_index':
99
- return validationSuccess(tool.value, validateSkillIndexInput(input, tool.value));
100
- case 'vgxness_skill_search':
101
- return validationSuccess(tool.value, validateSkillSearchInput(input, tool.value));
102
- case 'vgxness_skill_get':
103
- return validationSuccess(tool.value, validateSkillGetInput(input, tool.value));
104
- case 'vgxness_skill_status':
105
- return validationSuccess(tool.value, validateSkillStatusInput(input, tool.value));
106
- case 'vgxness_skill_payload':
107
- return validationSuccess(tool.value, validateSkillPayloadInput(input, tool.value));
108
- case 'vgxness_skill_activate':
109
- return validationSuccess(tool.value, validateSkillActivateInput(input, tool.value));
110
- case 'vgxness_skill_record_usage':
111
- return validationSuccess(tool.value, validateSkillRecordUsageInput(input, tool.value));
112
- case 'vgxness_skill_propose_improvement':
113
- return validationSuccess(tool.value, validateSkillProposeImprovementInput(input, tool.value));
114
- case 'vgxness_skill_list_improvement_proposals':
115
- return validationSuccess(tool.value, validateSkillListImprovementProposalsInput(input, tool.value));
116
- case 'vgxness_skill_request_evaluation':
117
- return validationSuccess(tool.value, validateSkillRequestEvaluationInput(input, tool.value));
118
- case 'vgxness_skill_list_evaluations':
119
- return validationSuccess(tool.value, validateSkillListEvaluationsInput(input, tool.value));
120
- case 'vgxness_skill_get_evaluation':
121
- return validationSuccess(tool.value, validateSkillGetEvaluationInput(input, tool.value));
122
- case 'vgxness_skill_create_draft':
123
- return validationSuccess(tool.value, validateSkillCreateDraftInput(input, tool.value));
124
- case 'vgxness_skill_update_draft':
125
- return validationSuccess(tool.value, validateSkillUpdateDraftInput(input, tool.value));
126
- case 'vgxness_skill_publish_version':
127
- return validationSuccess(tool.value, validateSkillPublishVersionInput(input, tool.value));
128
- case 'vgxness_opencode_manager_payload':
129
- return validationSuccess(tool.value, validateOpenCodeManagerPayloadInput(input, tool.value));
130
- case 'vgxness_opencode_handoff_preview':
131
- return validationSuccess(tool.value, validateOpenCodeHandoffPreviewInput(input, tool.value));
132
- case 'vgxness_run_list':
133
- return validationSuccess(tool.value, validateRunListInput(input, tool.value));
134
- case 'vgxness_run_get':
135
- return validationSuccess(tool.value, validateRunGetInput(input, tool.value));
136
- case 'vgxness_run_preflight':
137
- return validationSuccess(tool.value, validateRunPreflightInput(input, tool.value));
138
- case 'vgxness_run_task_grant_create':
139
- return validationSuccess(tool.value, validateRunTaskGrantCreateInput(input, tool.value));
140
- case 'vgxness_run_task_grant_list':
141
- return validationSuccess(tool.value, validateRunTaskGrantListInput(input, tool.value));
142
- case 'vgxness_run_task_grant_get':
143
- return validationSuccess(tool.value, validateRunTaskGrantGetInput(input, tool.value));
144
- case 'vgxness_run_task_grant_revoke':
145
- return validationSuccess(tool.value, validateRunTaskGrantRevokeInput(input, tool.value));
146
- case 'vgxness_run_task_grant_preview_match':
147
- return validationSuccess(tool.value, validateRunTaskGrantPreviewMatchInput(input, tool.value));
148
- case 'vgxness_run_start':
149
- return validationSuccess(tool.value, validateRunStartInput(input, tool.value));
150
- case 'vgxness_run_checkpoint':
151
- return validationSuccess(tool.value, validateRunCheckpointInput(input, tool.value));
152
- case 'vgxness_run_finalize':
153
- return validationSuccess(tool.value, validateRunFinalizeInput(input, tool.value));
154
- case 'vgxness_run_resume_candidates':
155
- return validationSuccess(tool.value, validateRunResumeCandidatesInput(input, tool.value));
156
- case 'vgxness_run_resume_inspect':
157
- return validationSuccess(tool.value, validateRunResumeInspectInput(input, tool.value));
158
- case 'vgxness_run_resume_gate':
159
- return validationSuccess(tool.value, validateRunResumeGateInput(input, tool.value));
160
- case 'vgxness_provider_status':
161
- return validationSuccess(tool.value, validateProviderHealthInput(input, tool.value));
162
- case 'vgxness_provider_doctor':
163
- return validationSuccess(tool.value, validateProviderHealthInput(input, tool.value));
164
- case 'vgxness_provider_change_plan':
165
- return validationSuccess(tool.value, validateProviderChangePlanInput(input, tool.value));
166
- case 'vgxness_verification_plan':
167
- return validationSuccess(tool.value, validateVerificationPlanInput(input, tool.value));
168
- }
169
- }
170
- function validateVerificationPlanInput(input, tool) {
171
- const record = inputRecord(input, tool, ['changeType']);
172
- if (!record.ok)
173
- return record;
174
- const changeType = readVerificationChangeType(record.value, tool);
175
- if (!changeType.ok)
176
- return changeType;
177
- return { ok: true, value: { changeType: changeType.value } };
178
- }
179
- function readVerificationChangeType(record, tool) {
180
- if (record.changeType === undefined)
181
- return validationFailure(supportedTypeMessage('changeType is required'), tool);
182
- const value = readString(record, 'changeType', tool);
183
- if (!value.ok)
184
- return value;
185
- const trimmed = value.value.trim();
186
- if (trimmed.length === 0)
187
- return validationFailure(supportedTypeMessage('changeType must not be empty'), tool);
188
- if (!verificationChangeTypes.includes(trimmed))
189
- return validationFailure(supportedTypeMessage(`Unsupported changeType: ${trimmed}`), tool);
190
- return { ok: true, value: trimmed };
191
- }
192
- function validateProviderChangePlanInput(input, tool) {
193
- const record = inputRecord(input, tool, ['project', 'scope', 'installTarget', 'provider', 'changeType', 'workspaceRoot', 'payloadMode']);
194
- if (!record.ok)
195
- return record;
196
- const provider = readRequiredOneOf(record.value, 'provider', providerChangePlanProviders, tool);
197
- if (!provider.ok)
198
- return provider;
199
- const changeType = readRequiredOneOf(record.value, 'changeType', providerChangePlanTypes, tool);
200
- if (!changeType.ok)
201
- return changeType;
202
- const workspaceRoot = readNonEmptyString(record.value, 'workspaceRoot', tool);
203
- if (!workspaceRoot.ok)
204
- return workspaceRoot;
205
- const payloadMode = readRequiredOneOf(record.value, 'payloadMode', payloadModes, tool);
206
- if (!payloadMode.ok)
207
- return payloadMode;
208
- const result = {
209
- provider: provider.value,
210
- changeType: changeType.value,
211
- workspaceRoot: workspaceRoot.value,
212
- payloadMode: payloadMode.value,
213
- };
214
- const project = readOptionalNonEmptyString(record.value, 'project', tool);
215
- if (!project.ok)
216
- return project;
217
- if (project.value !== undefined)
218
- result.project = project.value;
219
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
220
- if (!scope.ok)
221
- return scope;
222
- if (scope.value !== undefined)
223
- result.scope = scope.value;
224
- if (typeof record.value.installTarget === 'string' && record.value.installTarget.trim() !== 'user-global') {
225
- return validationFailure(providerUserGlobalOnlyMigrationMessage, tool);
226
- }
227
- const installTarget = readOptionalOneOf(record.value, 'installTarget', providerInstallTargets, tool);
228
- if (!installTarget.ok)
229
- return installTarget;
230
- if (installTarget.value !== undefined)
231
- result.installTarget = installTarget.value;
232
- return { ok: true, value: result };
233
- }
234
- function validateProviderHealthInput(input, tool) {
235
- const record = inputRecord(input ?? {}, tool, [
236
- 'project',
237
- 'scope',
238
- 'providerAdapter',
239
- 'workspaceRoot',
240
- 'change',
241
- 'expectedPromptContractVersion',
242
- 'payloadMode',
243
- ]);
244
- if (!record.ok)
245
- return record;
246
- const result = {};
247
- const project = readOptionalNonEmptyString(record.value, 'project', tool);
248
- if (!project.ok)
249
- return project;
250
- if (project.value !== undefined)
251
- result.project = project.value;
252
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
253
- if (!scope.ok)
254
- return scope;
255
- if (scope.value !== undefined)
256
- result.scope = scope.value;
257
- const providerAdapter = readOptionalOneOf(record.value, 'providerAdapter', ['opencode', 'claude'], tool);
258
- if (!providerAdapter.ok)
259
- return providerAdapter;
260
- if (providerAdapter.value !== undefined)
261
- result.providerAdapter = providerAdapter.value;
262
- const workspaceRoot = readOptionalNonEmptyString(record.value, 'workspaceRoot', tool);
263
- if (!workspaceRoot.ok)
264
- return workspaceRoot;
265
- if (workspaceRoot.value !== undefined)
266
- result.workspaceRoot = workspaceRoot.value;
267
- const change = readOptionalNonEmptyString(record.value, 'change', tool);
268
- if (!change.ok)
269
- return change;
270
- if (change.value !== undefined)
271
- result.change = change.value;
272
- const expectedPromptContractVersion = record.value.expectedPromptContractVersion;
273
- if (expectedPromptContractVersion !== undefined) {
274
- if (typeof expectedPromptContractVersion !== 'number' || !Number.isSafeInteger(expectedPromptContractVersion) || expectedPromptContractVersion <= 0)
275
- return validationFailure('expectedPromptContractVersion must be a positive safe integer', tool);
276
- result.expectedPromptContractVersion = expectedPromptContractVersion;
277
- }
278
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
279
- if (!payloadMode.ok)
280
- return payloadMode;
281
- if (payloadMode.value !== undefined)
282
- result.payloadMode = payloadMode.value;
283
- return { ok: true, value: result };
284
- }
285
- export function validateVgxMcpToolInput(tool, input) {
286
- return validateVgxMcpToolCall({ tool, input });
287
- }
288
- function validateSddStatusInput(input, tool) {
289
- const record = inputRecord(input, tool, ['project', 'change']);
290
- if (!record.ok)
291
- return record;
292
- return readProjectAndChange(record.value, tool);
293
- }
294
- function validateSddNextInput(input, tool) {
295
- const record = inputRecord(input, tool, ['project', 'change']);
296
- if (!record.ok)
297
- return record;
298
- return readProjectAndChange(record.value, tool);
299
- }
300
- function validateSddCockpitInput(input, tool) {
301
- const record = inputRecord(input, tool, ['project', 'change']);
302
- if (!record.ok)
303
- return record;
304
- return readProjectAndChange(record.value, tool);
305
- }
306
- function validateSddContinueInput(input, tool) {
307
- const record = inputRecord(input, tool, ['project', 'change', 'payloadMode']);
308
- if (!record.ok)
309
- return record;
310
- const base = readProjectAndChange(record.value, tool);
311
- if (!base.ok)
312
- return base;
313
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
314
- if (!payloadMode.ok)
315
- return payloadMode;
316
- const result = { ...base.value };
317
- if (payloadMode.value !== undefined)
318
- result.payloadMode = payloadMode.value;
319
- return { ok: true, value: result };
320
- }
321
- function validateContextCockpitInput(input, tool) {
322
- const record = inputRecord(input, tool, ['project', 'change', 'directory', 'limit', 'level']);
323
- if (!record.ok)
324
- return record;
325
- const project = readNonEmptyString(record.value, 'project', tool);
326
- if (!project.ok)
327
- return project;
328
- const result = { project: project.value };
329
- const change = readOptionalContextCockpitChange(record.value, tool);
330
- if (!change.ok)
331
- return change;
332
- if (change.value !== undefined)
333
- result.change = change.value;
334
- const directory = readOptionalNonEmptyString(record.value, 'directory', tool);
335
- if (!directory.ok)
336
- return directory;
337
- if (directory.value !== undefined)
338
- result.directory = directory.value;
339
- if (record.value.limit !== undefined) {
340
- if (typeof record.value.limit !== 'number' || !Number.isSafeInteger(record.value.limit) || record.value.limit < 1 || record.value.limit > 100)
341
- return validationFailure('limit must be an integer between 1 and 100', tool);
342
- result.limit = record.value.limit;
343
- }
344
- const level = readOptionalOneOf(record.value, 'level', contextCockpitLevels, tool);
345
- if (!level.ok)
346
- return level;
347
- if (level.value !== undefined)
348
- result.level = level.value;
349
- return { ok: true, value: result };
350
- }
351
- function validateResumeContextInput(input, tool) {
352
- const record = inputRecord(input, tool, ['project', 'directory', 'workspaceRoot', 'userPrompt', 'explicitChange', 'limit', 'payloadMode']);
353
- if (!record.ok)
354
- return record;
355
- const project = readNonEmptyString(record.value, 'project', tool);
356
- if (!project.ok)
357
- return project;
358
- const result = { project: project.value };
359
- const directory = readOptionalNonEmptyString(record.value, 'directory', tool);
360
- if (!directory.ok)
361
- return directory;
362
- if (directory.value !== undefined)
363
- result.directory = directory.value;
364
- const workspaceRoot = readOptionalNonEmptyString(record.value, 'workspaceRoot', tool);
365
- if (!workspaceRoot.ok)
366
- return workspaceRoot;
367
- if (workspaceRoot.value !== undefined)
368
- result.workspaceRoot = workspaceRoot.value;
369
- if (record.value.userPrompt !== undefined) {
370
- if (typeof record.value.userPrompt !== 'string')
371
- return validationFailure('userPrompt must be a string', tool);
372
- result.userPrompt = record.value.userPrompt;
373
- }
374
- const explicitChange = readOptionalExplicitChange(record.value, tool);
375
- if (!explicitChange.ok)
376
- return explicitChange;
377
- if (explicitChange.value !== undefined)
378
- result.explicitChange = explicitChange.value;
379
- if (record.value.limit !== undefined) {
380
- if (typeof record.value.limit !== 'number' || !Number.isSafeInteger(record.value.limit) || record.value.limit < 1 || record.value.limit > 25)
381
- return validationFailure('limit must be an integer between 1 and 25', tool);
382
- result.limit = record.value.limit;
383
- }
384
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
385
- if (!payloadMode.ok)
386
- return payloadMode;
387
- result.payloadMode = payloadMode.value ?? 'compact';
388
- return { ok: true, value: result };
389
- }
390
- function readProjectAndChange(record, tool) {
391
- const project = readNonEmptyString(record, 'project', tool);
392
- if (!project.ok)
393
- return project;
394
- const change = readChange(record, tool);
395
- if (!change.ok)
396
- return change;
397
- return { ok: true, value: { project: project.value, change: change.value } };
398
- }
399
- function validateSddReadyInput(input, tool) {
400
- const record = inputRecord(input, tool, ['project', 'change', 'phase', 'runId', 'agentId']);
401
- if (!record.ok)
402
- return record;
403
- const base = readProjectAndChange(record.value, tool);
404
- if (!base.ok)
405
- return base;
406
- const phase = readPhase(record.value, tool);
407
- if (!phase.ok)
408
- return phase;
409
- const result = { ...base.value, phase: phase.value };
410
- const copied = copyOptionalStrings(result, record.value, tool, ['runId', 'agentId']);
411
- if (!copied.ok)
412
- return copied;
413
- return { ok: true, value: result };
414
- }
415
- function validateSddGetReadinessInput(input, tool) {
416
- return validateSddReadyInput(input, tool);
417
- }
418
- function validateSddSaveArtifactInput(input, tool) {
419
- const record = inputRecord(input, tool, ['project', 'change', 'phase', 'content']);
420
- if (!record.ok)
421
- return record;
422
- const base = readProjectAndChange(record.value, tool);
423
- if (!base.ok)
424
- return base;
425
- const phase = readPhase(record.value, tool);
426
- if (!phase.ok)
427
- return phase;
428
- const content = readNonEmptyString(record.value, 'content', tool);
429
- if (!content.ok)
430
- return content;
431
- return { ok: true, value: { ...base.value, phase: phase.value, content: content.value } };
432
- }
433
- function validateSddAcceptArtifactInput(input, tool) {
434
- const record = inputRecord(input, tool, ['project', 'change', 'phase', 'acceptedBy', 'acceptedAt', 'note', 'runId', 'agentId']);
435
- if (!record.ok)
436
- return record;
437
- const base = readProjectAndChange(record.value, tool);
438
- if (!base.ok)
439
- return base;
440
- const phase = readPhase(record.value, tool);
441
- if (!phase.ok)
442
- return phase;
443
- const acceptedByRecord = asRecord(record.value.acceptedBy, tool, 'acceptedBy is required');
444
- if (!acceptedByRecord.ok)
445
- return acceptedByRecord;
446
- const acceptedByExtra = Object.keys(acceptedByRecord.value).find((key) => !['type', 'id', 'displayName'].includes(key));
447
- if (acceptedByExtra !== undefined)
448
- return validationFailure(`Unexpected field: acceptedBy.${acceptedByExtra}`, tool);
449
- const type = readRequiredOneOf(acceptedByRecord.value, 'type', ['human'], tool);
450
- if (!type.ok)
451
- return type;
452
- const id = readNonEmptyString(acceptedByRecord.value, 'id', tool);
453
- if (!id.ok)
454
- return id;
455
- const displayName = readOptionalNonEmptyString(acceptedByRecord.value, 'displayName', tool);
456
- if (!displayName.ok)
457
- return displayName;
458
- const acceptedBy = { type: type.value, id: id.value };
459
- if (displayName.value !== undefined)
460
- acceptedBy.displayName = displayName.value;
461
- const result = { ...base.value, phase: phase.value, acceptedBy };
462
- const copied = copyOptionalLimitedStrings(result, record.value, tool, ['acceptedAt', 'note', 'runId', 'agentId'], undefined);
463
- if (!copied.ok)
464
- return copied;
465
- return { ok: true, value: result };
466
- }
467
- function validateSddReopenArtifactInput(input, tool) {
468
- const record = inputRecord(input, tool, ['project', 'change', 'phase', 'reopenedBy', 'reopenedAt', 'note', 'runId', 'agentId']);
469
- if (!record.ok)
470
- return record;
471
- const base = readProjectAndChange(record.value, tool);
472
- if (!base.ok)
473
- return base;
474
- const phase = readPhase(record.value, tool);
475
- if (!phase.ok)
476
- return phase;
477
- const reopenedByRecord = asRecord(record.value.reopenedBy, tool, 'reopenedBy is required');
478
- if (!reopenedByRecord.ok)
479
- return reopenedByRecord;
480
- const reopenedByExtra = Object.keys(reopenedByRecord.value).find((key) => !['type', 'id', 'displayName'].includes(key));
481
- if (reopenedByExtra !== undefined)
482
- return validationFailure(`Unexpected field: reopenedBy.${reopenedByExtra}`, tool);
483
- const type = readRequiredOneOf(reopenedByRecord.value, 'type', ['human'], tool);
484
- if (!type.ok)
485
- return type;
486
- const id = readNonEmptyString(reopenedByRecord.value, 'id', tool);
487
- if (!id.ok)
488
- return id;
489
- const displayName = readOptionalNonEmptyString(reopenedByRecord.value, 'displayName', tool);
490
- if (!displayName.ok)
491
- return displayName;
492
- const reopenedBy = { type: type.value, id: id.value };
493
- if (displayName.value !== undefined)
494
- reopenedBy.displayName = displayName.value;
495
- const result = { ...base.value, phase: phase.value, reopenedBy };
496
- const copied = copyOptionalLimitedStrings(result, record.value, tool, ['reopenedAt', 'note', 'runId', 'agentId'], undefined);
497
- if (!copied.ok)
498
- return copied;
499
- return { ok: true, value: result };
500
- }
501
- function validateSddGetArtifactInput(input, tool) {
502
- const record = inputRecord(input, tool, ['project', 'change', 'phase', 'payloadMode']);
503
- if (!record.ok)
504
- return record;
505
- const base = readProjectAndChange(record.value, tool);
506
- if (!base.ok)
507
- return base;
508
- const phase = readPhase(record.value, tool);
509
- if (!phase.ok)
510
- return phase;
511
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
512
- if (!payloadMode.ok)
513
- return payloadMode;
514
- const result = { ...base.value, phase: phase.value };
515
- if (payloadMode.value !== undefined)
516
- result.payloadMode = payloadMode.value;
517
- return { ok: true, value: result };
518
- }
519
- function validateSddListArtifactsInput(input, tool) {
520
- const record = inputRecord(input, tool, ['project', 'change', 'payloadMode']);
521
- if (!record.ok)
522
- return record;
523
- const base = readProjectAndChange(record.value, tool);
524
- if (!base.ok)
525
- return base;
526
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
527
- if (!payloadMode.ok)
528
- return payloadMode;
529
- const result = { ...base.value };
530
- if (payloadMode.value !== undefined)
531
- result.payloadMode = payloadMode.value;
532
- return { ok: true, value: result };
533
- }
534
- function validateGovernanceReportInput(input, tool) {
535
- const record = inputRecord(input, tool, ['project', 'change', 'runId', 'workflow', 'phase', 'agentId', 'payloadMode', 'agent']);
536
- if (!record.ok)
537
- return record;
538
- const project = readNonEmptyString(record.value, 'project', tool);
539
- if (!project.ok)
540
- return project;
541
- const result = { project: project.value };
542
- const copied = copyOptionalLimitedStrings(result, record.value, tool, ['change', 'runId', 'workflow', 'phase', 'agentId'], undefined);
543
- if (!copied.ok)
544
- return copied;
545
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
546
- if (!payloadMode.ok)
547
- return payloadMode;
548
- if (payloadMode.value !== undefined)
549
- result.payloadMode = payloadMode.value;
550
- if (record.value.agent !== undefined) {
551
- const agent = readGovernanceAgent(record.value.agent, tool);
552
- if (!agent.ok)
553
- return agent;
554
- result.agent = agent.value;
555
- }
556
- return { ok: true, value: result };
557
- }
558
- function readGovernanceAgent(value, tool) {
559
- const record = asRecord(value, tool, 'agent must be an object');
560
- if (!record.ok)
561
- return record;
562
- const unexpected = Object.keys(record.value).find((key) => !['id', 'name', 'mode', 'scope'].includes(key));
563
- if (unexpected !== undefined)
564
- return validationFailure(`Unexpected agent field: ${unexpected}`, tool);
565
- const agent = {};
566
- const copied = copyOptionalLimitedStrings(agent, record.value, tool, ['id', 'name'], undefined);
567
- if (!copied.ok)
568
- return copied;
569
- const mode = readOptionalOneOf(record.value, 'mode', agentModes, tool);
570
- if (!mode.ok)
571
- return mode;
572
- if (mode.value !== undefined)
573
- agent.mode = mode.value;
574
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
575
- if (!scope.ok)
576
- return scope;
577
- if (scope.value !== undefined)
578
- agent.scope = scope.value;
579
- if (Object.keys(agent).length === 0)
580
- return validationFailure('agent must include at least one of: id, name, mode, scope', tool);
581
- return { ok: true, value: agent };
582
- }
583
- function validateMemorySaveInput(input, tool) {
584
- const record = inputRecord(input, tool, ['project', 'scope', 'type', 'title', 'content', 'topicKey']);
585
- if (!record.ok)
586
- return record;
587
- const project = readLimitedNonEmptyString(record.value, 'project', tool, undefined);
588
- if (!project.ok)
589
- return project;
590
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
591
- if (!scope.ok)
592
- return scope;
593
- const type = readRequiredOneOf(record.value, 'type', memoryTypes, tool);
594
- if (!type.ok)
595
- return type;
596
- const title = readLimitedNonEmptyString(record.value, 'title', tool, maxMemoryTitleLength);
597
- if (!title.ok)
598
- return title;
599
- const content = readLimitedNonEmptyString(record.value, 'content', tool, maxMemoryContentLength);
600
- if (!content.ok)
601
- return content;
602
- const topicKey = readOptionalTopicKey(record.value, tool);
603
- if (!topicKey.ok)
604
- return topicKey;
605
- const result = { project: project.value, scope: scope.value ?? 'project', type: type.value, title: title.value, content: content.value };
606
- if (topicKey.value !== undefined)
607
- result.topicKey = topicKey.value;
608
- return { ok: true, value: result };
609
- }
610
- function validateMemorySearchInput(input, tool) {
611
- const record = inputRecord(input, tool, ['project', 'scope', 'type', 'topicKey', 'query', 'limit']);
612
- if (!record.ok)
613
- return record;
614
- const result = {};
615
- const copied = copyOptionalLimitedStrings(result, record.value, tool, ['project', 'query'], undefined);
616
- if (!copied.ok)
617
- return copied;
618
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
619
- if (!scope.ok)
620
- return scope;
621
- if (scope.value !== undefined)
622
- result.scope = scope.value;
623
- const type = readOptionalOneOf(record.value, 'type', memoryTypes, tool);
624
- if (!type.ok)
625
- return type;
626
- if (type.value !== undefined)
627
- result.type = type.value;
628
- const topicKey = readOptionalSearchTopicKey(record.value, tool);
629
- if (!topicKey.ok)
630
- return topicKey;
631
- if (topicKey.value !== undefined)
632
- result.topicKey = topicKey.value;
633
- const limit = readMemorySearchLimit(record.value, tool);
634
- if (!limit.ok)
635
- return limit;
636
- result.limit = limit.value;
637
- return { ok: true, value: result };
638
- }
639
- function validateMemoryGetInput(input, tool) {
640
- const record = inputRecord(input, tool, ['id']);
641
- if (!record.ok)
642
- return record;
643
- const id = readNonEmptyString(record.value, 'id', tool);
644
- if (!id.ok)
645
- return id;
646
- return { ok: true, value: { id: id.value } };
647
- }
648
- function validateMemoryUpdateInput(input, tool) {
649
- const record = inputRecord(input, tool, ['id', 'type', 'title', 'content', 'topicKey']);
650
- if (!record.ok)
651
- return record;
652
- const id = readNonEmptyString(record.value, 'id', tool);
653
- if (!id.ok)
654
- return id;
655
- const result = { id: id.value };
656
- const type = readOptionalOneOf(record.value, 'type', memoryTypes, tool);
657
- if (!type.ok)
658
- return type;
659
- if (type.value !== undefined)
660
- result.type = type.value;
661
- const copied = copyOptionalLimitedStrings(result, record.value, tool, ['title', 'content'], undefined);
662
- if (!copied.ok)
663
- return copied;
664
- if (result.title !== undefined && result.title.length > maxMemoryTitleLength)
665
- return validationFailure(`title must be ${maxMemoryTitleLength} characters or fewer`, tool);
666
- if (result.content !== undefined && result.content.length > maxMemoryContentLength)
667
- return validationFailure(`content must be ${maxMemoryContentLength} characters or fewer`, tool);
668
- const topicKey = readOptionalTopicKey(record.value, tool);
669
- if (!topicKey.ok)
670
- return topicKey;
671
- if (topicKey.value !== undefined)
672
- result.topicKey = topicKey.value;
673
- if (result.type === undefined && result.title === undefined && result.content === undefined && result.topicKey === undefined) {
674
- return validationFailure('At least one editable field is required', tool);
675
- }
676
- return { ok: true, value: result };
677
- }
678
- function validateSkillIndexInput(input, tool) {
679
- const record = inputRecord(input, tool, ['project', 'scope']);
680
- if (!record.ok)
681
- return record;
682
- const project = readNonEmptyString(record.value, 'project', tool);
683
- if (!project.ok)
684
- return project;
685
- const scope = readRequiredOneOf(record.value, 'scope', scopes, tool);
686
- if (!scope.ok)
687
- return scope;
688
- return { ok: true, value: { project: project.value, scope: scope.value } };
689
- }
690
- function validateSkillSearchInput(input, tool) {
691
- const record = inputRecord(input, tool, ['project', 'scope', 'query', 'status', 'sourceKind', 'limit']);
692
- if (!record.ok)
693
- return record;
694
- const project = readNonEmptyString(record.value, 'project', tool);
695
- if (!project.ok)
696
- return project;
697
- const result = { project: project.value };
698
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
699
- if (!scope.ok)
700
- return scope;
701
- if (scope.value !== undefined)
702
- result.scope = scope.value;
703
- const query = readOptionalNonEmptyString(record.value, 'query', tool);
704
- if (!query.ok)
705
- return query;
706
- if (query.value !== undefined)
707
- result.query = query.value;
708
- const status = readOptionalOneOf(record.value, 'status', skillVersionStatuses, tool);
709
- if (!status.ok)
710
- return status;
711
- if (status.value !== undefined)
712
- result.status = status.value;
713
- const sourceKind = readOptionalOneOf(record.value, 'sourceKind', skillSourceKinds, tool);
714
- if (!sourceKind.ok)
715
- return sourceKind;
716
- if (sourceKind.value !== undefined)
717
- result.sourceKind = sourceKind.value;
718
- if (record.value.limit !== undefined) {
719
- const limit = record.value.limit;
720
- if (typeof limit !== 'number' || !Number.isSafeInteger(limit) || limit < 1 || limit > 100)
721
- return validationFailure('limit must be an integer between 1 and 100', tool);
722
- result.limit = limit;
723
- }
724
- return { ok: true, value: result };
725
- }
726
- function validateSkillGetInput(input, tool) {
727
- const record = inputRecord(input, tool, ['project', 'scope', 'id', 'name', 'includeUsage']);
728
- if (!record.ok)
729
- return record;
730
- const project = readNonEmptyString(record.value, 'project', tool);
731
- if (!project.ok)
732
- return project;
733
- const result = { project: project.value };
734
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
735
- if (!scope.ok)
736
- return scope;
737
- if (scope.value !== undefined)
738
- result.scope = scope.value;
739
- const id = readOptionalNonEmptyString(record.value, 'id', tool);
740
- if (!id.ok)
741
- return id;
742
- if (id.value !== undefined)
743
- result.id = id.value;
744
- const name = readOptionalNonEmptyString(record.value, 'name', tool);
745
- if (!name.ok)
746
- return name;
747
- if (name.value !== undefined)
748
- result.name = name.value;
749
- if (result.id === undefined && result.name === undefined)
750
- return validationFailure('Either id or name is required', tool);
751
- if (record.value.includeUsage !== undefined) {
752
- if (typeof record.value.includeUsage !== 'boolean')
753
- return validationFailure('includeUsage must be boolean', tool);
754
- result.includeUsage = record.value.includeUsage;
755
- }
756
- return { ok: true, value: result };
757
- }
758
- function validateSkillStatusInput(input, tool) {
759
- const record = inputRecord(input, tool, ['project', 'scope', 'provider', 'mode', 'agent']);
760
- if (!record.ok)
761
- return record;
762
- const project = readNonEmptyString(record.value, 'project', tool);
763
- if (!project.ok)
764
- return project;
765
- const result = { project: project.value };
766
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
767
- if (!scope.ok)
768
- return scope;
769
- if (scope.value !== undefined)
770
- result.scope = scope.value;
771
- const mode = readOptionalOneOf(record.value, 'mode', agentModes, tool);
772
- if (!mode.ok)
773
- return mode;
774
- if (mode.value !== undefined)
775
- result.mode = mode.value;
776
- const copied = copyOptionalStrings(result, record.value, tool, ['provider', 'agent']);
777
- if (!copied.ok)
778
- return copied;
779
- return { ok: true, value: result };
780
- }
781
- function validateSessionStartInput(input, tool) {
782
- const record = inputRecord(input, tool, ['id', 'project', 'directory']);
783
- if (!record.ok)
784
- return record;
785
- const project = readNonEmptyString(record.value, 'project', tool);
786
- if (!project.ok)
787
- return project;
788
- const result = { project: project.value };
789
- const copied = copyOptionalStrings(result, record.value, tool, ['id', 'directory']);
790
- if (!copied.ok)
791
- return copied;
792
- return { ok: true, value: result };
793
- }
794
- function validateSessionAppendActivityInput(input, tool) {
795
- const record = inputRecord(input, tool, ['sessionId', 'actor', 'kind', 'payloadJson']);
796
- if (!record.ok)
797
- return record;
798
- const result = {};
799
- const copied = copyRequiredStrings(result, record.value, tool, ['sessionId', 'actor', 'payloadJson']);
800
- if (!copied.ok)
801
- return copied;
802
- const kind = readRequiredOneOf(record.value, 'kind', activityKinds, tool);
803
- if (!kind.ok)
804
- return kind;
805
- result.kind = kind.value;
806
- return { ok: true, value: result };
807
- }
808
- function validateSessionCloseInput(input, tool) {
809
- const record = inputRecord(input, tool, ['sessionId', 'actor', 'summary']);
810
- if (!record.ok)
811
- return record;
812
- const result = {};
813
- const copied = copyRequiredStrings(result, record.value, tool, ['sessionId', 'actor', 'summary']);
814
- if (!copied.ok)
815
- return copied;
816
- return { ok: true, value: result };
817
- }
818
- function validateSessionRestoreInput(input, tool) {
819
- const record = inputRecord(input, tool, ['project', 'directory']);
820
- if (!record.ok)
821
- return record;
822
- const project = readNonEmptyString(record.value, 'project', tool);
823
- if (!project.ok)
824
- return project;
825
- const result = { project: project.value };
826
- const copied = copyOptionalStrings(result, record.value, tool, ['directory']);
827
- if (!copied.ok)
828
- return copied;
829
- return { ok: true, value: result };
830
- }
831
- function validateAgentResolveInput(input, tool) {
832
- const record = inputRecord(input, tool, [
833
- 'project',
834
- 'scope',
835
- 'taskDescription',
836
- 'intent',
837
- 'desiredCapabilities',
838
- 'workflow',
839
- 'phase',
840
- 'providerAdapter',
841
- 'mode',
842
- ]);
843
- if (!record.ok)
844
- return record;
845
- const result = {};
846
- const copied = copyOptionalStrings(result, record.value, tool, ['project', 'taskDescription', 'intent', 'workflow', 'phase', 'providerAdapter']);
847
- if (!copied.ok)
848
- return copied;
849
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
850
- if (!scope.ok)
851
- return scope;
852
- if (scope.value !== undefined)
853
- result.scope = scope.value;
854
- const mode = readOptionalOneOf(record.value, 'mode', agentModes, tool);
855
- if (!mode.ok)
856
- return mode;
857
- if (mode.value !== undefined)
858
- result.mode = mode.value;
859
- const desiredCapabilities = readOptionalStringArray(record.value, 'desiredCapabilities', tool);
860
- if (!desiredCapabilities.ok)
861
- return desiredCapabilities;
862
- if (desiredCapabilities.value !== undefined)
863
- result.desiredCapabilities = desiredCapabilities.value;
864
- return { ok: true, value: result };
865
- }
866
- function validateAgentActivateInput(input, tool) {
867
- const record = inputRecord(input, tool, [
868
- 'project',
869
- 'scope',
870
- 'agentId',
871
- 'userIntent',
872
- 'workflow',
873
- 'phase',
874
- 'workspaceRoot',
875
- 'maxSourceBytes',
876
- 'providerAdapter',
877
- 'payloadMode',
878
- ]);
879
- if (!record.ok)
880
- return record;
881
- const project = readNonEmptyString(record.value, 'project', tool);
882
- if (!project.ok)
883
- return project;
884
- const userIntent = readNonEmptyString(record.value, 'userIntent', tool);
885
- if (!userIntent.ok)
886
- return userIntent;
887
- const result = {
888
- project: project.value,
889
- scope: 'project',
890
- userIntent: userIntent.value,
891
- workflow: 'agent-activation',
892
- phase: 'activation',
893
- };
894
- const copied = copyOptionalStrings(result, record.value, tool, ['agentId', 'workflow', 'phase', 'workspaceRoot']);
895
- if (!copied.ok)
896
- return copied;
897
- if (record.value.providerAdapter !== undefined) {
898
- const providerAdapter = readNonEmptyString(record.value, 'providerAdapter', tool);
899
- if (!providerAdapter.ok)
900
- return providerAdapter;
901
- result.providerAdapter = providerAdapter.value.trim();
902
- }
903
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
904
- if (!scope.ok)
905
- return scope;
906
- result.scope = scope.value ?? 'project';
907
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
908
- if (!payloadMode.ok)
909
- return payloadMode;
910
- if (payloadMode.value !== undefined)
911
- result.payloadMode = payloadMode.value;
912
- if (record.value.maxSourceBytes !== undefined) {
913
- const maxSourceBytes = record.value.maxSourceBytes;
914
- if (typeof maxSourceBytes !== 'number' || !Number.isSafeInteger(maxSourceBytes) || maxSourceBytes <= 0)
915
- return validationFailure('maxSourceBytes must be a positive safe integer', tool);
916
- result.maxSourceBytes = maxSourceBytes;
917
- }
918
- return { ok: true, value: result };
919
- }
920
- function validateSkillPayloadInput(input, tool) {
921
- const record = inputRecord(input, tool, [
922
- 'workspaceRoot',
923
- 'maxSourceBytes',
924
- 'project',
925
- 'scope',
926
- 'agentId',
927
- 'agentName',
928
- 'workflow',
929
- 'phase',
930
- 'intentSignals',
931
- 'providerAdapter',
932
- 'runId',
933
- 'mode',
934
- ]);
935
- if (!record.ok)
936
- return record;
937
- const workspaceRoot = readNonEmptyString(record.value, 'workspaceRoot', tool);
938
- if (!workspaceRoot.ok)
939
- return workspaceRoot;
940
- const result = { workspaceRoot: workspaceRoot.value };
941
- const copied = copyOptionalStrings(result, record.value, tool, ['project', 'agentId', 'agentName', 'workflow', 'phase', 'providerAdapter', 'runId']);
942
- if (!copied.ok)
943
- return copied;
944
- const intentSignals = readOptionalStringArray(record.value, 'intentSignals', tool);
945
- if (!intentSignals.ok)
946
- return intentSignals;
947
- if (intentSignals.value !== undefined)
948
- result.intentSignals = intentSignals.value;
949
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
950
- if (!scope.ok)
951
- return scope;
952
- if (scope.value !== undefined)
953
- result.scope = scope.value;
954
- const mode = readOptionalOneOf(record.value, 'mode', payloadModes, tool);
955
- if (!mode.ok)
956
- return mode;
957
- if (mode.value !== undefined)
958
- result.mode = mode.value;
959
- if (record.value.maxSourceBytes !== undefined) {
960
- const maxSourceBytes = record.value.maxSourceBytes;
961
- if (typeof maxSourceBytes !== 'number' || !Number.isSafeInteger(maxSourceBytes) || maxSourceBytes <= 0)
962
- return validationFailure('maxSourceBytes must be a positive safe integer', tool);
963
- result.maxSourceBytes = maxSourceBytes;
964
- }
965
- return { ok: true, value: result };
966
- }
967
- function validateSkillActivateInput(input, tool) {
968
- const record = inputRecord(input, tool, [
969
- 'project',
970
- 'scope',
971
- 'skillId',
972
- 'name',
973
- 'versionId',
974
- 'version',
975
- 'runId',
976
- 'agentId',
977
- 'workflow',
978
- 'phase',
979
- 'providerAdapter',
980
- 'intent',
981
- 'reason',
982
- 'workspaceRoot',
983
- 'maxSourceBytes',
984
- 'mode',
985
- ]);
986
- if (!record.ok)
987
- return record;
988
- const project = readNonEmptyString(record.value, 'project', tool);
989
- if (!project.ok)
990
- return project;
991
- const result = { project: project.value };
992
- const copied = copyOptionalStrings(result, record.value, tool, [
993
- 'skillId',
994
- 'name',
995
- 'versionId',
996
- 'version',
997
- 'runId',
998
- 'agentId',
999
- 'workflow',
1000
- 'phase',
1001
- 'providerAdapter',
1002
- 'reason',
1003
- 'workspaceRoot',
1004
- ]);
1005
- if (!copied.ok)
1006
- return copied;
1007
- if (result.skillId === undefined && result.name === undefined)
1008
- return validationFailure('Either skillId or name is required', tool);
1009
- if (result.versionId !== undefined && result.version !== undefined)
1010
- return validationFailure('Use either versionId or version, not both', tool);
1011
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1012
- if (!scope.ok)
1013
- return scope;
1014
- if (scope.value !== undefined)
1015
- result.scope = scope.value;
1016
- const mode = readOptionalOneOf(record.value, 'mode', payloadModes, tool);
1017
- if (!mode.ok)
1018
- return mode;
1019
- if (mode.value !== undefined)
1020
- result.mode = mode.value;
1021
- const intent = readOptionalJsonObject(record.value, 'intent', tool);
1022
- if (!intent.ok)
1023
- return intent;
1024
- if (intent.value !== undefined)
1025
- result.intent = intent.value;
1026
- if (record.value.maxSourceBytes !== undefined) {
1027
- const maxSourceBytes = record.value.maxSourceBytes;
1028
- if (typeof maxSourceBytes !== 'number' || !Number.isSafeInteger(maxSourceBytes) || maxSourceBytes <= 0)
1029
- return validationFailure('maxSourceBytes must be a positive safe integer', tool);
1030
- result.maxSourceBytes = maxSourceBytes;
1031
- }
1032
- return { ok: true, value: result };
1033
- }
1034
- function validateSkillRecordUsageInput(input, tool) {
1035
- const record = inputRecord(input, tool, [
1036
- 'skillId',
1037
- 'versionId',
1038
- 'runId',
1039
- 'targetType',
1040
- 'targetKey',
1041
- 'outcome',
1042
- 'notes',
1043
- 'workflow',
1044
- 'phase',
1045
- 'providerAdapter',
1046
- 'agentId',
1047
- 'intent',
1048
- 'evidence',
1049
- ]);
1050
- if (!record.ok)
1051
- return record;
1052
- const skillId = readNonEmptyString(record.value, 'skillId', tool);
1053
- if (!skillId.ok)
1054
- return skillId;
1055
- const outcome = readRequiredOneOf(record.value, 'outcome', skillUsageOutcomes, tool);
1056
- if (!outcome.ok)
1057
- return outcome;
1058
- const result = { skillId: skillId.value, outcome: outcome.value };
1059
- const copied = copyOptionalStrings(result, record.value, tool, ['versionId', 'runId', 'targetKey', 'notes', 'workflow', 'phase', 'providerAdapter', 'agentId']);
1060
- if (!copied.ok)
1061
- return copied;
1062
- const targetType = readOptionalOneOf(record.value, 'targetType', skillAttachmentTargetTypes, tool);
1063
- if (!targetType.ok)
1064
- return targetType;
1065
- if (targetType.value !== undefined)
1066
- result.targetType = targetType.value;
1067
- if (result.targetType !== undefined && result.targetKey === undefined)
1068
- return validationFailure('targetKey is required when targetType is set', tool);
1069
- if (result.targetType === undefined && result.targetKey !== undefined)
1070
- return validationFailure('targetType is required when targetKey is set', tool);
1071
- const intent = readOptionalJsonObject(record.value, 'intent', tool);
1072
- if (!intent.ok)
1073
- return intent;
1074
- if (intent.value !== undefined)
1075
- result.intent = intent.value;
1076
- const evidence = readOptionalJsonObject(record.value, 'evidence', tool);
1077
- if (!evidence.ok)
1078
- return evidence;
1079
- if (evidence.value !== undefined)
1080
- result.evidence = evidence.value;
1081
- return { ok: true, value: result };
1082
- }
1083
- function validateSkillProposeImprovementInput(input, tool) {
1084
- const record = inputRecord(input, tool, [
1085
- 'project',
1086
- 'scope',
1087
- 'skillId',
1088
- 'name',
1089
- 'baseVersionId',
1090
- 'baseVersion',
1091
- 'proposedVersion',
1092
- 'proposedSource',
1093
- 'proposedCompatibility',
1094
- 'title',
1095
- 'problem',
1096
- 'suggestedChange',
1097
- 'sourceContext',
1098
- 'runId',
1099
- 'agentId',
1100
- 'workflow',
1101
- 'phase',
1102
- 'providerAdapter',
1103
- 'evidenceRefs',
1104
- 'evidence',
1105
- 'actor',
1106
- ]);
1107
- if (!record.ok)
1108
- return record;
1109
- const result = {};
1110
- const copied = copyRequiredStrings(result, record.value, tool, ['project', 'proposedVersion', 'title', 'problem', 'suggestedChange']);
1111
- if (!copied.ok)
1112
- return copied;
1113
- const optional = copyOptionalStrings(result, record.value, tool, ['skillId', 'name', 'baseVersionId', 'baseVersion', 'runId', 'agentId', 'workflow', 'phase', 'providerAdapter', 'actor']);
1114
- if (!optional.ok)
1115
- return optional;
1116
- if (result.skillId === undefined && result.name === undefined)
1117
- return validationFailure('Either skillId or name is required', tool);
1118
- if (result.baseVersionId !== undefined && result.baseVersion !== undefined)
1119
- return validationFailure('Use either baseVersionId or baseVersion, not both', tool);
1120
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1121
- if (!scope.ok)
1122
- return scope;
1123
- if (scope.value !== undefined)
1124
- result.scope = scope.value;
1125
- const source = readSkillSource(record.value, 'proposedSource', tool);
1126
- if (!source.ok)
1127
- return source;
1128
- result.proposedSource = source.value;
1129
- const compatibility = readOptionalJsonObject(record.value, 'proposedCompatibility', tool);
1130
- if (!compatibility.ok)
1131
- return compatibility;
1132
- if (compatibility.value !== undefined) {
1133
- const proposedCompatibility = compatibility.value;
1134
- if (proposedCompatibility !== undefined)
1135
- result.proposedCompatibility = proposedCompatibility;
1136
- }
1137
- const sourceContext = readOptionalJsonObject(record.value, 'sourceContext', tool);
1138
- if (!sourceContext.ok)
1139
- return sourceContext;
1140
- if (sourceContext.value !== undefined)
1141
- result.sourceContext = sourceContext.value;
1142
- const evidence = readOptionalJsonObject(record.value, 'evidence', tool);
1143
- if (!evidence.ok)
1144
- return evidence;
1145
- if (evidence.value !== undefined)
1146
- result.evidence = evidence.value;
1147
- const evidenceRefs = readOptionalStringArray(record.value, 'evidenceRefs', tool);
1148
- if (!evidenceRefs.ok)
1149
- return evidenceRefs;
1150
- if (evidenceRefs.value !== undefined)
1151
- result.evidenceRefs = evidenceRefs.value;
1152
- return { ok: true, value: result };
1153
- }
1154
- function validateSkillListImprovementProposalsInput(input, tool) {
1155
- const record = inputRecord(input, tool, ['project', 'scope', 'skillId', 'name', 'baseVersionId', 'status', 'runId', 'agentId', 'limit']);
1156
- if (!record.ok)
1157
- return record;
1158
- const project = readNonEmptyString(record.value, 'project', tool);
1159
- if (!project.ok)
1160
- return project;
1161
- const result = { project: project.value };
1162
- const copied = copyOptionalStrings(result, record.value, tool, ['skillId', 'name', 'baseVersionId', 'runId', 'agentId']);
1163
- if (!copied.ok)
1164
- return copied;
1165
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1166
- if (!scope.ok)
1167
- return scope;
1168
- if (scope.value !== undefined)
1169
- result.scope = scope.value;
1170
- const status = readOptionalOneOf(record.value, 'status', skillImprovementProposalStatuses, tool);
1171
- if (!status.ok)
1172
- return status;
1173
- if (status.value !== undefined)
1174
- result.status = status.value;
1175
- const limit = readOptionalBoundedLimit(record.value, tool);
1176
- if (!limit.ok)
1177
- return limit;
1178
- if (limit.value !== undefined)
1179
- result.limit = limit.value;
1180
- return { ok: true, value: result };
1181
- }
1182
- function validateSkillRequestEvaluationInput(input, tool) {
1183
- const record = inputRecord(input, tool, [
1184
- 'project',
1185
- 'scope',
1186
- 'skillId',
1187
- 'name',
1188
- 'versionId',
1189
- 'version',
1190
- 'scenarioId',
1191
- 'proposalId',
1192
- 'requestedBy',
1193
- 'runId',
1194
- 'agentId',
1195
- 'workflow',
1196
- 'phase',
1197
- 'providerAdapter',
1198
- 'risk',
1199
- 'preflight',
1200
- ]);
1201
- if (!record.ok)
1202
- return record;
1203
- const result = {};
1204
- const copied = copyRequiredStrings(result, record.value, tool, ['project', 'requestedBy']);
1205
- if (!copied.ok)
1206
- return copied;
1207
- const optional = copyOptionalStrings(result, record.value, tool, ['skillId', 'name', 'versionId', 'version', 'scenarioId', 'proposalId', 'runId', 'agentId', 'workflow', 'phase', 'providerAdapter']);
1208
- if (!optional.ok)
1209
- return optional;
1210
- if (result.skillId === undefined && result.name === undefined)
1211
- return validationFailure('Either skillId or name is required', tool);
1212
- if (result.versionId !== undefined && result.version !== undefined)
1213
- return validationFailure('Use either versionId or version, not both', tool);
1214
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1215
- if (!scope.ok)
1216
- return scope;
1217
- if (scope.value !== undefined)
1218
- result.scope = scope.value;
1219
- const risk = readOptionalJsonObject(record.value, 'risk', tool);
1220
- if (!risk.ok)
1221
- return risk;
1222
- if (risk.value !== undefined)
1223
- result.risk = risk.value;
1224
- const preflight = readOptionalJsonObject(record.value, 'preflight', tool);
1225
- if (!preflight.ok)
1226
- return preflight;
1227
- if (preflight.value !== undefined)
1228
- result.preflight = preflight.value;
1229
- return { ok: true, value: result };
1230
- }
1231
- function validateSkillListEvaluationsInput(input, tool) {
1232
- const record = inputRecord(input, tool, ['project', 'scope', 'skillId', 'name', 'versionId', 'scenarioId', 'proposalId', 'status', 'runId', 'agentId', 'limit']);
1233
- if (!record.ok)
1234
- return record;
1235
- const project = readNonEmptyString(record.value, 'project', tool);
1236
- if (!project.ok)
1237
- return project;
1238
- const result = { project: project.value };
1239
- const copied = copyOptionalStrings(result, record.value, tool, ['skillId', 'name', 'versionId', 'scenarioId', 'proposalId', 'runId', 'agentId']);
1240
- if (!copied.ok)
1241
- return copied;
1242
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1243
- if (!scope.ok)
1244
- return scope;
1245
- if (scope.value !== undefined)
1246
- result.scope = scope.value;
1247
- const status = readOptionalOneOf(record.value, 'status', skillEvaluationRequestStatuses, tool);
1248
- if (!status.ok)
1249
- return status;
1250
- if (status.value !== undefined)
1251
- result.status = status.value;
1252
- const limit = readOptionalBoundedLimit(record.value, tool);
1253
- if (!limit.ok)
1254
- return limit;
1255
- if (limit.value !== undefined)
1256
- result.limit = limit.value;
1257
- return { ok: true, value: result };
1258
- }
1259
- function validateSkillGetEvaluationInput(input, tool) {
1260
- const record = inputRecord(input, tool, ['project', 'scope', 'id']);
1261
- if (!record.ok)
1262
- return record;
1263
- const project = readNonEmptyString(record.value, 'project', tool);
1264
- if (!project.ok)
1265
- return project;
1266
- const id = readNonEmptyString(record.value, 'id', tool);
1267
- if (!id.ok)
1268
- return id;
1269
- const result = { project: project.value, id: id.value };
1270
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1271
- if (!scope.ok)
1272
- return scope;
1273
- if (scope.value !== undefined)
1274
- result.scope = scope.value;
1275
- return { ok: true, value: result };
1276
- }
1277
- function validateSkillCreateDraftInput(input, tool) {
1278
- const record = inputRecord(input, tool, [
1279
- 'project',
1280
- 'scope',
1281
- 'name',
1282
- 'description',
1283
- 'version',
1284
- 'source',
1285
- 'compatibility',
1286
- 'draftParentVersionId',
1287
- 'actor',
1288
- 'reason',
1289
- 'runId',
1290
- 'agentId',
1291
- 'evidence',
1292
- 'governance',
1293
- ]);
1294
- if (!record.ok)
1295
- return record;
1296
- const result = {};
1297
- const required = copyRequiredStrings(result, record.value, tool, ['project', 'name', 'description', 'version']);
1298
- if (!required.ok)
1299
- return required;
1300
- const optional = copyOptionalStrings(result, record.value, tool, ['draftParentVersionId', 'reason', 'runId', 'agentId']);
1301
- if (!optional.ok)
1302
- return optional;
1303
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1304
- if (!scope.ok)
1305
- return scope;
1306
- if (scope.value !== undefined)
1307
- result.scope = scope.value;
1308
- const source = readSkillSource(record.value, 'source', tool);
1309
- if (!source.ok)
1310
- return source;
1311
- result.source = source.value;
1312
- const actor = readSkillLifecycleActor(record.value, tool);
1313
- if (!actor.ok)
1314
- return actor;
1315
- result.actor = actor.value;
1316
- const compatibility = readOptionalJsonObject(record.value, 'compatibility', tool);
1317
- if (!compatibility.ok)
1318
- return compatibility;
1319
- if (compatibility.value !== undefined)
1320
- result.compatibility = compatibility.value;
1321
- const evidence = readOptionalJsonObject(record.value, 'evidence', tool);
1322
- if (!evidence.ok)
1323
- return evidence;
1324
- if (evidence.value !== undefined)
1325
- result.evidence = evidence.value;
1326
- const governance = readOptionalJsonObject(record.value, 'governance', tool);
1327
- if (!governance.ok)
1328
- return governance;
1329
- if (governance.value !== undefined)
1330
- result.governance = governance.value;
1331
- return { ok: true, value: result };
1332
- }
1333
- function validateSkillUpdateDraftInput(input, tool) {
1334
- const record = inputRecord(input, tool, [
1335
- 'project',
1336
- 'scope',
1337
- 'skillId',
1338
- 'name',
1339
- 'versionId',
1340
- 'version',
1341
- 'source',
1342
- 'compatibility',
1343
- 'expectedDraftRevision',
1344
- 'actor',
1345
- 'reason',
1346
- 'runId',
1347
- 'agentId',
1348
- 'evidence',
1349
- 'governance',
1350
- ]);
1351
- if (!record.ok)
1352
- return record;
1353
- const result = {};
1354
- const required = copyRequiredStrings(result, record.value, tool, ['project']);
1355
- if (!required.ok)
1356
- return required;
1357
- const optional = copyOptionalStrings(result, record.value, tool, ['skillId', 'name', 'versionId', 'version', 'reason', 'runId', 'agentId']);
1358
- if (!optional.ok)
1359
- return optional;
1360
- if (result.skillId === undefined && result.name === undefined)
1361
- return validationFailure('Either skillId or name is required', tool);
1362
- if (result.versionId === undefined && result.version === undefined)
1363
- return validationFailure('Either versionId or version is required', tool);
1364
- if (result.versionId !== undefined && result.version !== undefined)
1365
- return validationFailure('Use either versionId or version, not both', tool);
1366
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1367
- if (!scope.ok)
1368
- return scope;
1369
- if (scope.value !== undefined)
1370
- result.scope = scope.value;
1371
- const actor = readSkillLifecycleActor(record.value, tool);
1372
- if (!actor.ok)
1373
- return actor;
1374
- result.actor = actor.value;
1375
- if (record.value.source !== undefined) {
1376
- const source = readSkillSource(record.value, 'source', tool);
1377
- if (!source.ok)
1378
- return source;
1379
- result.source = source.value;
1380
- }
1381
- const compatibility = readOptionalJsonObject(record.value, 'compatibility', tool);
1382
- if (!compatibility.ok)
1383
- return compatibility;
1384
- if (compatibility.value !== undefined)
1385
- result.compatibility = compatibility.value;
1386
- if (record.value.expectedDraftRevision !== undefined) {
1387
- const revision = record.value.expectedDraftRevision;
1388
- if (typeof revision !== 'number' || !Number.isSafeInteger(revision) || revision < 1)
1389
- return validationFailure('expectedDraftRevision must be a positive safe integer', tool);
1390
- result.expectedDraftRevision = revision;
1391
- }
1392
- const evidence = readOptionalJsonObject(record.value, 'evidence', tool);
1393
- if (!evidence.ok)
1394
- return evidence;
1395
- if (evidence.value !== undefined)
1396
- result.evidence = evidence.value;
1397
- const governance = readOptionalJsonObject(record.value, 'governance', tool);
1398
- if (!governance.ok)
1399
- return governance;
1400
- if (governance.value !== undefined)
1401
- result.governance = governance.value;
1402
- if (result.source === undefined && result.compatibility === undefined && result.governance === undefined)
1403
- return validationFailure('At least one draft update field is required', tool);
1404
- return { ok: true, value: result };
1405
- }
1406
- function validateSkillPublishVersionInput(input, tool) {
1407
- const record = inputRecord(input, tool, ['project', 'scope', 'skillId', 'name', 'versionId', 'version', 'actor', 'reason', 'runId', 'agentId', 'evidence', 'governance']);
1408
- if (!record.ok)
1409
- return record;
1410
- const result = {};
1411
- const required = copyRequiredStrings(result, record.value, tool, ['project', 'reason']);
1412
- if (!required.ok)
1413
- return required;
1414
- const optional = copyOptionalStrings(result, record.value, tool, ['skillId', 'name', 'versionId', 'version', 'runId', 'agentId']);
1415
- if (!optional.ok)
1416
- return optional;
1417
- if (result.skillId === undefined && result.name === undefined)
1418
- return validationFailure('Either skillId or name is required', tool);
1419
- if (result.versionId === undefined && result.version === undefined)
1420
- return validationFailure('Either versionId or version is required', tool);
1421
- if (result.versionId !== undefined && result.version !== undefined)
1422
- return validationFailure('Use either versionId or version, not both', tool);
1423
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1424
- if (!scope.ok)
1425
- return scope;
1426
- if (scope.value !== undefined)
1427
- result.scope = scope.value;
1428
- const actor = readSkillLifecycleActor(record.value, tool);
1429
- if (!actor.ok)
1430
- return actor;
1431
- result.actor = actor.value;
1432
- const evidence = readOptionalJsonObject(record.value, 'evidence', tool);
1433
- if (!evidence.ok)
1434
- return evidence;
1435
- if (evidence.value !== undefined)
1436
- result.evidence = evidence.value;
1437
- const governance = readOptionalJsonObject(record.value, 'governance', tool);
1438
- if (!governance.ok)
1439
- return governance;
1440
- if (governance.value !== undefined)
1441
- result.governance = governance.value;
1442
- return { ok: true, value: result };
1443
- }
1444
- function validateManagerProfileGetInput(input, tool) {
1445
- const record = inputRecord(input, tool, ['project', 'scope', 'managerName']);
1446
- if (!record.ok)
1447
- return record;
1448
- const project = readNonEmptyString(record.value, 'project', tool);
1449
- if (!project.ok)
1450
- return project;
1451
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1452
- if (!scope.ok)
1453
- return scope;
1454
- const result = { project: project.value };
1455
- if (scope.value !== undefined)
1456
- result.scope = scope.value;
1457
- const copied = copyOptionalStrings(result, record.value, tool, ['managerName']);
1458
- if (!copied.ok)
1459
- return copied;
1460
- return { ok: true, value: result };
1461
- }
1462
- function validateManagerProfileSetInput(input, tool) {
1463
- const record = inputRecord(input, tool, ['project', 'scope', 'managerName', 'instructions']);
1464
- if (!record.ok)
1465
- return record;
1466
- const result = {};
1467
- const copied = copyRequiredStrings(result, record.value, tool, ['project', 'managerName', 'instructions']);
1468
- if (!copied.ok)
1469
- return copied;
1470
- const scope = readRequiredOneOf(record.value, 'scope', scopes, tool);
1471
- if (!scope.ok)
1472
- return scope;
1473
- result.scope = scope.value;
1474
- return { ok: true, value: result };
1475
- }
1476
- function validateOpenCodeManagerPayloadInput(input, tool) {
1477
- const record = inputRecord(input, tool, ['project', 'scope', 'agentId', 'agentName', 'workspaceRoot', 'maxSourceBytes', 'payloadMode']);
1478
- if (!record.ok)
1479
- return record;
1480
- const project = readNonEmptyString(record.value, 'project', tool);
1481
- if (!project.ok)
1482
- return project;
1483
- const result = { project: project.value };
1484
- const copied = copyOptionalStrings(result, record.value, tool, ['agentId', 'agentName', 'workspaceRoot']);
1485
- if (!copied.ok)
1486
- return copied;
1487
- // Some MCP hosts expose optional fields as required in their generated tool
1488
- // facade. Accept both selectors here and let the provider payload service
1489
- // verify that they refer to the same top-level agent.
1490
- if (result.agentId === undefined && result.agentName === undefined)
1491
- result.agentName = 'vgxness-manager';
1492
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1493
- if (!scope.ok)
1494
- return scope;
1495
- result.scope = scope.value ?? 'project';
1496
- const payloadMode = readOptionalOneOf(record.value, 'payloadMode', payloadModes, tool);
1497
- if (!payloadMode.ok)
1498
- return payloadMode;
1499
- if (payloadMode.value !== undefined)
1500
- result.payloadMode = payloadMode.value;
1501
- if (record.value.maxSourceBytes !== undefined) {
1502
- const maxSourceBytes = record.value.maxSourceBytes;
1503
- if (typeof maxSourceBytes !== 'number' || !Number.isSafeInteger(maxSourceBytes) || maxSourceBytes <= 0)
1504
- return validationFailure('maxSourceBytes must be a positive safe integer', tool);
1505
- result.maxSourceBytes = maxSourceBytes;
1506
- }
1507
- return { ok: true, value: result };
1508
- }
1509
- function validateOpenCodeHandoffPreviewInput(input, tool) {
1510
- const record = inputRecord(input, tool, ['project', 'scope', 'agentId', 'agentName', 'workspaceRoot', 'maxSourceBytes', 'change', 'phase']);
1511
- if (!record.ok)
1512
- return record;
1513
- const project = readNonEmptyString(record.value, 'project', tool);
1514
- if (!project.ok)
1515
- return project;
1516
- const result = { project: project.value, scope: 'project', agentName: 'vgxness-manager' };
1517
- const copied = copyOptionalStrings(result, record.value, tool, ['agentId', 'agentName', 'workspaceRoot']);
1518
- if (!copied.ok)
1519
- return copied;
1520
- const scope = readOptionalOneOf(record.value, 'scope', scopes, tool);
1521
- if (!scope.ok)
1522
- return scope;
1523
- result.scope = scope.value ?? 'project';
1524
- const change = readOptionalChange(record.value, tool);
1525
- if (!change.ok)
1526
- return change;
1527
- if (change.value !== undefined)
1528
- result.change = change.value;
1529
- if (record.value.phase !== undefined) {
1530
- const phase = readPhase(record.value, tool);
1531
- if (!phase.ok)
1532
- return phase;
1533
- result.phase = phase.value;
1534
- }
1535
- if (record.value.maxSourceBytes !== undefined) {
1536
- const maxSourceBytes = record.value.maxSourceBytes;
1537
- if (typeof maxSourceBytes !== 'number' || !Number.isSafeInteger(maxSourceBytes) || maxSourceBytes <= 0)
1538
- return validationFailure('maxSourceBytes must be a positive safe integer', tool);
1539
- result.maxSourceBytes = maxSourceBytes;
1540
- }
1541
- return { ok: true, value: result };
1542
- }
1543
- function validateRunListInput(input, tool) {
1544
- const record = inputRecord(input, tool, ['project', 'status', 'limit']);
1545
- if (!record.ok)
1546
- return record;
1547
- const result = {};
1548
- const project = copyOptionalStrings(result, record.value, tool, ['project']);
1549
- if (!project.ok)
1550
- return project;
1551
- const status = readOptionalOneOf(record.value, 'status', runStatuses, tool);
1552
- if (!status.ok)
1553
- return status;
1554
- if (status.value !== undefined)
1555
- result.status = status.value;
1556
- const limit = readBoundedLimit(record.value, tool);
1557
- if (!limit.ok)
1558
- return limit;
1559
- result.limit = limit.value;
1560
- return { ok: true, value: result };
1561
- }
1562
- function validateRunGetInput(input, tool) {
1563
- const record = inputRecord(input, tool, ['id']);
1564
- if (!record.ok)
1565
- return record;
1566
- const id = readNonEmptyString(record.value, 'id', tool);
1567
- if (!id.ok)
1568
- return id;
1569
- return { ok: true, value: { id: id.value } };
1570
- }
1571
- function validateRunPreflightInput(input, tool) {
1572
- const record = inputRecord(input, tool, [
1573
- 'runId',
1574
- 'category',
1575
- 'operation',
1576
- 'workflow',
1577
- 'phase',
1578
- 'agentId',
1579
- 'workspaceRoot',
1580
- 'targetPath',
1581
- 'taskFingerprint',
1582
- 'commandId',
1583
- 'cwd',
1584
- 'targetPaths',
1585
- 'providerToolName',
1586
- 'agent',
1587
- 'sandboxStrategy',
1588
- 'destructive',
1589
- 'external',
1590
- 'privileged',
1591
- 'ambiguous',
1592
- ]);
1593
- if (!record.ok)
1594
- return record;
1595
- const runId = readNonEmptyString(record.value, 'runId', tool);
1596
- if (!runId.ok)
1597
- return runId;
1598
- const category = readRequiredOneOf(record.value, 'category', permissionCategories, tool);
1599
- if (!category.ok)
1600
- return category;
1601
- const operation = readNonEmptyString(record.value, 'operation', tool);
1602
- if (!operation.ok)
1603
- return operation;
1604
- const result = { runId: runId.value, category: category.value, operation: operation.value };
1605
- const workflow = readOptionalOneOf(record.value, 'workflow', workflowIds, tool);
1606
- if (!workflow.ok)
1607
- return workflow;
1608
- if (workflow.value !== undefined)
1609
- result.workflow = workflow.value;
1610
- const copied = copyOptionalStrings(result, record.value, tool, ['phase', 'agentId', 'workspaceRoot', 'targetPath', 'taskFingerprint', 'commandId', 'cwd', 'providerToolName']);
1611
- if (!copied.ok)
1612
- return copied;
1613
- const targetPaths = readOptionalStringArray(record.value, 'targetPaths', tool);
1614
- if (!targetPaths.ok)
1615
- return targetPaths;
1616
- if (targetPaths.value !== undefined)
1617
- result.targetPaths = targetPaths.value;
1618
- const sandboxStrategy = readOptionalOneOf(record.value, 'sandboxStrategy', ['worktree'], tool);
1619
- if (!sandboxStrategy.ok)
1620
- return sandboxStrategy;
1621
- if (sandboxStrategy.value !== undefined)
1622
- result.sandboxStrategy = sandboxStrategy.value;
1623
- const booleans = copyOptionalBooleans(result, record.value, tool, ['destructive', 'external', 'privileged', 'ambiguous']);
1624
- if (!booleans.ok)
1625
- return booleans;
1626
- if (record.value.agent !== undefined) {
1627
- const agent = readPreflightAgent(record.value.agent, tool);
1628
- if (!agent.ok)
1629
- return agent;
1630
- result.agent = agent.value;
1631
- }
1632
- if (isRiskyPermissionCategory(result.category)) {
1633
- if (result.phase !== undefined && result.agentId === undefined && result.agent === undefined) {
1634
- return validationFailure(`VGX-managed preflight for risky category ${result.category} requires agentId when phase metadata is provided`, tool);
1635
- }
1636
- if (result.agentId !== undefined && result.phase === undefined) {
1637
- return validationFailure(`VGX-managed preflight for risky category ${result.category} requires phase when agentId metadata is provided`, tool);
1638
- }
1639
- }
1640
- return { ok: true, value: result };
1641
- }
1642
- function validateRunTaskGrantCreateInput(input, tool) {
1643
- const record = inputRecord(input, tool, [
1644
- 'runId',
1645
- 'agentId',
1646
- 'taskFingerprint',
1647
- 'categories',
1648
- 'externalRoots',
1649
- 'cwdPatterns',
1650
- 'commandPolicy',
1651
- 'expiresAt',
1652
- 'maxUses',
1653
- 'createdBy',
1654
- 'creationReason',
1655
- 'approvedScopeSummary',
1656
- ]);
1657
- if (!record.ok)
1658
- return record;
1659
- const result = {};
1660
- const copied = copyRequiredStrings(result, record.value, tool, ['runId', 'agentId', 'taskFingerprint', 'expiresAt', 'creationReason', 'approvedScopeSummary']);
1661
- if (!copied.ok)
1662
- return copied;
1663
- const categories = readRequiredOneOfArray(record.value, 'categories', taskGrantCategories, tool);
1664
- if (!categories.ok)
1665
- return categories;
1666
- result.categories = categories.value;
1667
- const externalRoots = readRequiredStringArray(record.value, 'externalRoots', tool);
1668
- if (!externalRoots.ok)
1669
- return externalRoots;
1670
- result.externalRoots = externalRoots.value;
1671
- const cwdPatterns = readOptionalStringArray(record.value, 'cwdPatterns', tool);
1672
- if (!cwdPatterns.ok)
1673
- return cwdPatterns;
1674
- if (cwdPatterns.value !== undefined)
1675
- result.cwdPatterns = cwdPatterns.value;
1676
- const commandPolicy = readTaskGrantCommandPolicy(record.value.commandPolicy, tool);
1677
- if (!commandPolicy.ok)
1678
- return commandPolicy;
1679
- result.commandPolicy = commandPolicy.value;
1680
- const createdBy = readTaskGrantActor(record.value.createdBy, tool, ['human']);
1681
- if (!createdBy.ok)
1682
- return createdBy;
1683
- result.createdBy = createdBy.value;
1684
- if (typeof record.value.maxUses !== 'number' || !Number.isSafeInteger(record.value.maxUses) || record.value.maxUses < 1)
1685
- return validationFailure('maxUses must be a positive safe integer', tool);
1686
- result.maxUses = record.value.maxUses;
1687
- const expiresAt = Date.parse(result.expiresAt ?? '');
1688
- if (!Number.isFinite(expiresAt) || new Date(expiresAt).toISOString() !== result.expiresAt)
1689
- return validationFailure('expiresAt must be a valid ISO date', tool);
1690
- const expiryDelta = expiresAt - Date.now();
1691
- if (expiryDelta <= 0)
1692
- return validationFailure('expiresAt must be in the future', tool);
1693
- if (expiryDelta > 24 * 60 * 60 * 1000)
1694
- return validationFailure('expiresAt must be within 24 hours', tool);
1695
- return { ok: true, value: result };
1696
- }
1697
- function validateRunTaskGrantListInput(input, tool) {
1698
- const record = inputRecord(input, tool, ['runId', 'agentId', 'status', 'limit']);
1699
- if (!record.ok)
1700
- return record;
1701
- const result = {};
1702
- const copied = copyOptionalStrings(result, record.value, tool, ['runId', 'agentId']);
1703
- if (!copied.ok)
1704
- return copied;
1705
- const status = readOptionalOneOf(record.value, 'status', taskGrantStatuses, tool);
1706
- if (!status.ok)
1707
- return status;
1708
- if (status.value !== undefined)
1709
- result.status = status.value;
1710
- const limit = readOptionalBoundedLimit(record.value, tool);
1711
- if (!limit.ok)
1712
- return limit;
1713
- if (limit.value !== undefined)
1714
- result.limit = limit.value;
1715
- return { ok: true, value: result };
1716
- }
1717
- function validateRunTaskGrantGetInput(input, tool) {
1718
- const record = inputRecord(input, tool, ['grantId']);
1719
- if (!record.ok)
1720
- return record;
1721
- const grantId = readNonEmptyString(record.value, 'grantId', tool);
1722
- if (!grantId.ok)
1723
- return grantId;
1724
- return { ok: true, value: { grantId: grantId.value } };
1725
- }
1726
- function validateRunTaskGrantRevokeInput(input, tool) {
1727
- const record = inputRecord(input, tool, ['grantId', 'actor', 'reason']);
1728
- if (!record.ok)
1729
- return record;
1730
- const grantId = readNonEmptyString(record.value, 'grantId', tool);
1731
- if (!grantId.ok)
1732
- return grantId;
1733
- const reason = readNonEmptyString(record.value, 'reason', tool);
1734
- if (!reason.ok)
1735
- return reason;
1736
- const actor = readTaskGrantActor(record.value.actor, tool, ['human', 'system']);
1737
- if (!actor.ok)
1738
- return actor;
1739
- return { ok: true, value: { grantId: grantId.value, actor: actor.value, reason: reason.value } };
1740
- }
1741
- function validateRunTaskGrantPreviewMatchInput(input, tool) {
1742
- const record = inputRecord(input, tool, ['runId', 'agentId', 'taskFingerprint', 'category', 'operation', 'workspaceRoot', 'cwd', 'targetPaths']);
1743
- if (!record.ok)
1744
- return record;
1745
- const runId = readNonEmptyString(record.value, 'runId', tool);
1746
- if (!runId.ok)
1747
- return runId;
1748
- const taskFingerprint = readNonEmptyString(record.value, 'taskFingerprint', tool);
1749
- if (!taskFingerprint.ok)
1750
- return taskFingerprint;
1751
- const category = readRequiredOneOf(record.value, 'category', permissionCategories, tool);
1752
- if (!category.ok)
1753
- return category;
1754
- const operation = readNonEmptyString(record.value, 'operation', tool);
1755
- if (!operation.ok)
1756
- return operation;
1757
- const cwd = readNonEmptyString(record.value, 'cwd', tool);
1758
- if (!cwd.ok)
1759
- return cwd;
1760
- const result = { runId: runId.value, taskFingerprint: taskFingerprint.value, category: category.value, operation: operation.value, cwd: cwd.value };
1761
- const copied = copyOptionalStrings(result, record.value, tool, ['agentId', 'workspaceRoot']);
1762
- if (!copied.ok)
1763
- return copied;
1764
- const targetPaths = readOptionalStringArray(record.value, 'targetPaths', tool);
1765
- if (!targetPaths.ok)
1766
- return targetPaths;
1767
- if (targetPaths.value !== undefined)
1768
- result.targetPaths = targetPaths.value;
1769
- return { ok: true, value: result };
1770
- }
1771
- function validateRunStartInput(input, tool) {
1772
- const record = inputRecord(input, tool, ['project', 'userIntent', 'workflow', 'phase', 'selectedAgentId', 'providerAdapter', 'model']);
1773
- if (!record.ok)
1774
- return record;
1775
- const result = {};
1776
- const copied = copyRequiredStrings(result, record.value, tool, ['project', 'userIntent', 'workflow', 'phase', 'selectedAgentId', 'providerAdapter', 'model']);
1777
- if (!copied.ok)
1778
- return copied;
1779
- return { ok: true, value: result };
1780
- }
1781
- function validateRunCheckpointInput(input, tool) {
1782
- const record = inputRecord(input, tool, ['runId', 'label', 'state']);
1783
- if (!record.ok)
1784
- return record;
1785
- const runId = readNonEmptyString(record.value, 'runId', tool);
1786
- if (!runId.ok)
1787
- return runId;
1788
- const label = readNonEmptyString(record.value, 'label', tool);
1789
- if (!label.ok)
1790
- return label;
1791
- const state = readJsonValue(record.value, 'state', tool);
1792
- if (!state.ok)
1793
- return state;
1794
- return { ok: true, value: { runId: runId.value, label: label.value, state: state.value } };
1795
- }
1796
- function validateRunFinalizeInput(input, tool) {
1797
- const record = inputRecord(input, tool, ['runId', 'status', 'outcome', 'outcomeReason']);
1798
- if (!record.ok)
1799
- return record;
1800
- const runId = readNonEmptyString(record.value, 'runId', tool);
1801
- if (!runId.ok)
1802
- return runId;
1803
- const status = readRequiredOneOf(record.value, 'status', finalRunStatuses, tool);
1804
- if (!status.ok)
1805
- return status;
1806
- const outcome = readRequiredOneOf(record.value, 'outcome', runOutcomes, tool);
1807
- if (!outcome.ok)
1808
- return outcome;
1809
- const result = { runId: runId.value, status: status.value, outcome: outcome.value };
1810
- const copied = copyOptionalStrings(result, record.value, tool, ['outcomeReason']);
1811
- if (!copied.ok)
1812
- return copied;
1813
- return { ok: true, value: result };
1814
- }
1815
- function validateRunResumeCandidatesInput(input, tool) {
1816
- const record = inputRecord(input, tool, ['project', 'limit']);
1817
- if (!record.ok)
1818
- return record;
1819
- const project = readNonEmptyString(record.value, 'project', tool);
1820
- if (!project.ok)
1821
- return project;
1822
- const result = { project: project.value };
1823
- if (record.value.limit !== undefined) {
1824
- const limit = readBoundedLimit(record.value, tool);
1825
- if (!limit.ok)
1826
- return limit;
1827
- result.limit = limit.value;
1828
- }
1829
- return { ok: true, value: result };
1830
- }
1831
- function validateRunResumeInspectInput(input, tool) {
1832
- const record = inputRecord(input, tool, ['runId']);
1833
- if (!record.ok)
1834
- return record;
1835
- const runId = readNonEmptyString(record.value, 'runId', tool);
1836
- if (!runId.ok)
1837
- return runId;
1838
- return { ok: true, value: { runId: runId.value } };
1839
- }
1840
- function validateRunResumeGateInput(input, tool) {
1841
- const record = inputRecord(input, tool, ['approvalId', 'policy']);
1842
- if (!record.ok)
1843
- return record;
1844
- const approvalId = readNonEmptyString(record.value, 'approvalId', tool);
1845
- if (!approvalId.ok)
1846
- return approvalId;
1847
- const result = { approvalId: approvalId.value };
1848
- if (record.value.policy !== undefined) {
1849
- const policy = parseOperationRetryPolicy(record.value.policy);
1850
- if (!policy.ok)
1851
- return validationFailure(policy.errors.join('; '), tool);
1852
- result.policy = policy.policy;
1853
- }
1854
- return { ok: true, value: result };
1855
- }
1856
- function validationSuccess(tool, validation) {
1857
- if (!validation.ok)
1858
- return validation;
1859
- return { ok: true, tool, input: validation.value };
1860
- }
1861
- function inputRecord(input, tool, allowed) {
1862
- const record = asRecord(input, tool, 'Tool input must be an object');
1863
- if (!record.ok)
1864
- return record;
1865
- const unexpected = Object.keys(record.value).find((key) => !allowed.includes(key));
1866
- if (unexpected !== undefined)
1867
- return validationFailure(`Unexpected field: ${unexpected}`, tool);
1868
- return record;
1869
- }
1870
- function asRecord(value, tool, message) {
1871
- if (typeof value !== 'object' || value === null || Array.isArray(value))
1872
- return validationFailure(message, tool);
1873
- return { ok: true, value: value };
1874
- }
1875
- function readString(record, field, tool) {
1876
- const value = record[field];
1877
- if (typeof value !== 'string')
1878
- return validationFailure(`${field} must be a string`, tool);
1879
- return { ok: true, value };
1880
- }
1881
- function readNonEmptyString(record, field, tool) {
1882
- if (record[field] === undefined)
1883
- return validationFailure(`${field} is required`, tool);
1884
- const value = readString(record, field, tool);
1885
- if (!value.ok)
1886
- return value;
1887
- if (value.value.trim().length === 0)
1888
- return validationFailure(`${field} must not be empty`, tool);
1889
- return value;
1890
- }
1891
- function readOptionalNonEmptyString(record, field, tool) {
1892
- if (record[field] === undefined)
1893
- return { ok: true, value: undefined };
1894
- return readNonEmptyString(record, field, tool);
1895
- }
1896
- function readChange(record, tool) {
1897
- const change = readNonEmptyString(record, 'change', tool);
1898
- if (!change.ok)
1899
- return change;
1900
- if (!validChangePattern.test(change.value))
1901
- return validationFailure(`Invalid SDD change id: ${change.value}`, tool);
1902
- return change;
1903
- }
1904
- function readOptionalChange(record, tool) {
1905
- if (record.change === undefined)
1906
- return { ok: true, value: undefined };
1907
- return readChange(record, tool);
1908
- }
1909
- function readOptionalContextCockpitChange(record, tool) {
1910
- if (record.change === '')
1911
- return { ok: true, value: undefined };
1912
- return readOptionalChange(record, tool);
1913
- }
1914
- function readOptionalExplicitChange(record, tool) {
1915
- if (record.explicitChange === undefined)
1916
- return { ok: true, value: undefined };
1917
- if (typeof record.explicitChange !== 'string')
1918
- return validationFailure('explicitChange must be a string', tool);
1919
- const trimmed = record.explicitChange.trim();
1920
- if (trimmed.length === 0)
1921
- return { ok: true, value: undefined };
1922
- if (!validChangePattern.test(trimmed))
1923
- return validationFailure(`Invalid explicit change id: ${trimmed}`, tool);
1924
- return { ok: true, value: trimmed };
1925
- }
1926
- function readPhase(record, tool) {
1927
- const phase = readNonEmptyString(record, 'phase', tool);
1928
- if (!phase.ok)
1929
- return phase;
1930
- const normalized = normalizeSddPhaseInput(phase.value);
1931
- if (normalized === undefined)
1932
- return validationFailure(`phase must be one of: ${sddPhases.join(', ')}`, tool);
1933
- return { ok: true, value: normalized };
1934
- }
1935
- function copyOptionalStrings(target, record, tool, fields) {
1936
- for (const field of fields) {
1937
- if (record[field] === undefined)
1938
- continue;
1939
- const value = readNonEmptyString(record, field, tool);
1940
- if (!value.ok)
1941
- return value;
1942
- target[field] = value.value;
1943
- }
1944
- return { ok: true, value: undefined };
1945
- }
1946
- function copyRequiredStrings(target, record, tool, fields) {
1947
- for (const field of fields) {
1948
- const value = readNonEmptyString(record, field, tool);
1949
- if (!value.ok)
1950
- return value;
1951
- target[field] = value.value;
1952
- }
1953
- return { ok: true, value: undefined };
1954
- }
1955
- function readJsonValue(record, field, tool) {
1956
- if (record[field] === undefined)
1957
- return validationFailure(`${field} is required`, tool);
1958
- if (!isJsonValue(record[field]))
1959
- return validationFailure(`${field} must be JSON-compatible`, tool);
1960
- return { ok: true, value: record[field] };
1961
- }
1962
- function readOptionalJsonObject(record, field, tool) {
1963
- if (record[field] === undefined)
1964
- return { ok: true, value: undefined };
1965
- const value = record[field];
1966
- if (!isJsonValue(value) || typeof value !== 'object' || value === null || Array.isArray(value))
1967
- return validationFailure(`${field} must be a JSON object`, tool);
1968
- return { ok: true, value: value };
1969
- }
1970
- function isJsonValue(value) {
1971
- if (value === null)
1972
- return true;
1973
- if (typeof value === 'string' || typeof value === 'boolean')
1974
- return true;
1975
- if (typeof value === 'number')
1976
- return Number.isFinite(value);
1977
- if (Array.isArray(value))
1978
- return value.every(isJsonValue);
1979
- if (typeof value !== 'object')
1980
- return false;
1981
- return Object.values(value).every(isJsonValue);
1982
- }
1983
- function copyOptionalBooleans(target, record, tool, fields) {
1984
- for (const field of fields) {
1985
- if (record[field] === undefined)
1986
- continue;
1987
- if (typeof record[field] !== 'boolean')
1988
- return validationFailure(`${field} must be a boolean`, tool);
1989
- target[field] = record[field];
1990
- }
1991
- return { ok: true, value: undefined };
1992
- }
1993
- function readPreflightAgent(value, tool) {
1994
- const record = asRecord(value, tool, 'agent must be an object');
1995
- if (!record.ok)
1996
- return record;
1997
- const unexpected = Object.keys(record.value).find((key) => !['id', 'name', 'mode', 'permissions'].includes(key));
1998
- if (unexpected !== undefined)
1999
- return validationFailure(`Unexpected agent field: ${unexpected}`, tool);
2000
- const id = readNonEmptyString(record.value, 'id', tool);
2001
- if (!id.ok)
2002
- return id;
2003
- const mode = readRequiredOneOf(record.value, 'mode', agentModes, tool);
2004
- if (!mode.ok)
2005
- return mode;
2006
- const agent = { id: id.value, name: id.value, mode: mode.value, permissions: {} };
2007
- const name = copyOptionalStrings(agent, record.value, tool, ['name']);
2008
- if (!name.ok)
2009
- return name;
2010
- if (record.value.permissions !== undefined) {
2011
- const permissions = readPreflightAgentPermissions(record.value.permissions, tool);
2012
- if (!permissions.ok)
2013
- return permissions;
2014
- agent.permissions = permissions.value;
2015
- }
2016
- return { ok: true, value: agent };
2017
- }
2018
- function readPreflightAgentPermissions(value, tool) {
2019
- const record = asRecord(value, tool, 'agent.permissions must be an object');
2020
- if (!record.ok)
2021
- return record;
2022
- const permissions = {};
2023
- for (const [category, decision] of Object.entries(record.value)) {
2024
- if (!permissionCategories.includes(category))
2025
- return validationFailure(`agent.permissions category must be one of: ${permissionCategories.join(', ')}`, tool);
2026
- if (typeof decision !== 'string' || !permissionDecisions.includes(decision))
2027
- return validationFailure(`agent.permissions.${category} must be one of: ${permissionDecisions.join(', ')}`, tool);
2028
- permissions[category] = decision;
2029
- }
2030
- return { ok: true, value: permissions };
2031
- }
2032
- function copyOptionalLimitedStrings(target, record, tool, fields, maxLength) {
2033
- for (const field of fields) {
2034
- if (record[field] === undefined)
2035
- continue;
2036
- const value = readLimitedNonEmptyString(record, field, tool, maxLength);
2037
- if (!value.ok)
2038
- return value;
2039
- target[field] = value.value;
2040
- }
2041
- return { ok: true, value: undefined };
2042
- }
2043
- function readLimitedNonEmptyString(record, field, tool, maxLength) {
2044
- const value = readNonEmptyString(record, field, tool);
2045
- if (!value.ok)
2046
- return value;
2047
- if (maxLength !== undefined && value.value.length > maxLength)
2048
- return validationFailure(`${field} must be ${maxLength} characters or fewer`, tool);
2049
- return value;
2050
- }
2051
- function readRequiredOneOf(record, field, values, tool) {
2052
- const value = readNonEmptyString(record, field, tool);
2053
- if (!value.ok)
2054
- return value;
2055
- if (!values.includes(value.value))
2056
- return validationFailure(`${field} must be one of: ${values.join(', ')}`, tool);
2057
- return { ok: true, value: value.value };
2058
- }
2059
- function readRequiredOneOfArray(record, field, values, tool) {
2060
- const array = readRequiredStringArray(record, field, tool);
2061
- if (!array.ok)
2062
- return array;
2063
- for (const item of array.value) {
2064
- if (!values.includes(item))
2065
- return validationFailure(`${field} must contain only: ${values.join(', ')}`, tool);
2066
- }
2067
- return { ok: true, value: array.value };
2068
- }
2069
- function readRequiredStringArray(record, field, tool) {
2070
- if (record[field] === undefined)
2071
- return validationFailure(`${field} is required`, tool);
2072
- const values = readOptionalStringArray(record, field, tool);
2073
- if (!values.ok)
2074
- return values;
2075
- if (values.value === undefined || values.value.length === 0)
2076
- return validationFailure(`${field} must contain at least one item`, tool);
2077
- if (new Set(values.value).size !== values.value.length)
2078
- return validationFailure(`${field} must be unique`, tool);
2079
- return { ok: true, value: values.value };
2080
- }
2081
- function readTaskGrantCommandPolicy(value, tool) {
2082
- const record = asRecord(value, tool, 'commandPolicy must be an object');
2083
- if (!record.ok)
2084
- return record;
2085
- const unexpected = Object.keys(record.value).find((key) => !['kind', 'ids'].includes(key));
2086
- if (unexpected !== undefined)
2087
- return validationFailure(`Unexpected commandPolicy field: ${unexpected}`, tool);
2088
- const kind = readRequiredOneOf(record.value, 'kind', ['allowlisted-command-ids'], tool);
2089
- if (!kind.ok)
2090
- return kind;
2091
- const ids = readRequiredStringArray(record.value, 'ids', tool);
2092
- if (!ids.ok)
2093
- return ids;
2094
- const known = new Set(commandAllowlistIds());
2095
- for (const id of ids.value)
2096
- if (!known.has(id))
2097
- return validationFailure(`Unknown allowlisted command id: ${id}`, tool);
2098
- return { ok: true, value: { kind: kind.value, ids: ids.value } };
2099
- }
2100
- function readTaskGrantActor(value, tool, allowedTypes) {
2101
- const record = asRecord(value, tool, 'actor must be an object');
2102
- if (!record.ok)
2103
- return record;
2104
- const unexpected = Object.keys(record.value).find((key) => !['type', 'id', 'displayName'].includes(key));
2105
- if (unexpected !== undefined)
2106
- return validationFailure(`Unexpected actor field: ${unexpected}`, tool);
2107
- const type = readRequiredOneOf(record.value, 'type', allowedTypes, tool);
2108
- if (!type.ok)
2109
- return type;
2110
- const id = readNonEmptyString(record.value, 'id', tool);
2111
- if (!id.ok)
2112
- return id;
2113
- const actor = { type: type.value, id: id.value };
2114
- const displayName = readOptionalNonEmptyString(record.value, 'displayName', tool);
2115
- if (!displayName.ok)
2116
- return displayName;
2117
- if (displayName.value !== undefined)
2118
- actor.displayName = displayName.value;
2119
- return { ok: true, value: actor };
2120
- }
2121
- function readOptionalOneOf(record, field, values, tool) {
2122
- if (record[field] === undefined)
2123
- return { ok: true, value: undefined };
2124
- const value = readNonEmptyString(record, field, tool);
2125
- if (!value.ok)
2126
- return value;
2127
- if (!values.includes(value.value))
2128
- return validationFailure(`${field} must be one of: ${values.join(', ')}`, tool);
2129
- return { ok: true, value: value.value };
2130
- }
2131
- function readOptionalTopicKey(record, tool) {
2132
- if (record.topicKey === undefined)
2133
- return { ok: true, value: undefined };
2134
- const topicKey = readLimitedNonEmptyString(record, 'topicKey', tool, maxMemoryTopicKeyLength);
2135
- if (!topicKey.ok)
2136
- return topicKey;
2137
- if (!validMemoryTopicKeyPattern.test(topicKey.value))
2138
- return validationFailure('topicKey must contain only letters, numbers, dots, underscores, slashes, or hyphens', tool);
2139
- return topicKey;
2140
- }
2141
- function readOptionalSearchTopicKey(record, tool) {
2142
- if (record.topicKey === undefined)
2143
- return { ok: true, value: undefined };
2144
- const topicKey = readLimitedNonEmptyString(record, 'topicKey', tool, maxMemoryTopicKeyLength);
2145
- if (!topicKey.ok)
2146
- return topicKey;
2147
- if (topicKey.value === '*')
2148
- return topicKey;
2149
- if (!validMemoryTopicKeyPattern.test(topicKey.value))
2150
- return validationFailure('topicKey must be * or contain only letters, numbers, dots, underscores, slashes, or hyphens', tool);
2151
- return topicKey;
2152
- }
2153
- function readMemorySearchLimit(record, tool) {
2154
- return readBoundedLimit(record, tool);
2155
- }
2156
- function readBoundedLimit(record, tool) {
2157
- if (record.limit === undefined)
2158
- return validationFailure('limit is required', tool);
2159
- const limit = record.limit;
2160
- if (typeof limit !== 'number' || !Number.isSafeInteger(limit) || limit < 1 || limit > 100)
2161
- return validationFailure('limit must be between 1 and 100', tool);
2162
- return { ok: true, value: limit };
2163
- }
2164
- function readOptionalBoundedLimit(record, tool) {
2165
- if (record.limit === undefined)
2166
- return { ok: true, value: undefined };
2167
- return readBoundedLimit(record, tool);
2168
- }
2169
- function readSkillSource(record, field, tool) {
2170
- const source = asRecord(record[field], tool, `${field} must be an object`);
2171
- if (!source.ok)
2172
- return source;
2173
- const kind = readRequiredOneOf(source.value, 'kind', skillSourceKinds, tool);
2174
- if (!kind.ok)
2175
- return kind;
2176
- const result = { kind: kind.value };
2177
- const path = readOptionalNonEmptyString(source.value, 'path', tool);
2178
- if (!path.ok)
2179
- return path;
2180
- if (path.value !== undefined)
2181
- result.path = path.value;
2182
- const url = readOptionalNonEmptyString(source.value, 'url', tool);
2183
- if (!url.ok)
2184
- return url;
2185
- if (url.value !== undefined)
2186
- result.url = url.value;
2187
- const inlineMetadata = readOptionalJsonObject(source.value, 'inlineMetadata', tool);
2188
- if (!inlineMetadata.ok)
2189
- return inlineMetadata;
2190
- if (inlineMetadata.value !== undefined)
2191
- result.inlineMetadata = inlineMetadata.value;
2192
- if (result.kind === 'path' && result.path === undefined)
2193
- return validationFailure('proposedSource.path is required when proposedSource.kind is path', tool);
2194
- if (result.kind === 'url' && result.url === undefined)
2195
- return validationFailure('proposedSource.url is required when proposedSource.kind is url', tool);
2196
- if (result.kind === 'inline' && (result.path !== undefined || result.url !== undefined))
2197
- return validationFailure('Inline proposedSource cannot include path or url', tool);
2198
- return { ok: true, value: result };
2199
- }
2200
- function readSkillLifecycleActor(record, tool) {
2201
- const actorRecord = asRecord(record.actor, tool, 'actor must be an object');
2202
- if (!actorRecord.ok)
2203
- return actorRecord;
2204
- const type = readRequiredOneOf(actorRecord.value, 'type', ['human', 'agent', 'system'], tool);
2205
- if (!type.ok)
2206
- return type;
2207
- const id = readNonEmptyString(actorRecord.value, 'id', tool);
2208
- if (!id.ok)
2209
- return id;
2210
- const actor = { type: type.value, id: id.value };
2211
- const displayName = readOptionalNonEmptyString(actorRecord.value, 'displayName', tool);
2212
- if (!displayName.ok)
2213
- return displayName;
2214
- if (displayName.value !== undefined)
2215
- actor.displayName = displayName.value;
2216
- return { ok: true, value: actor };
2217
- }
2218
- function readOptionalStringArray(record, field, tool) {
2219
- if (record[field] === undefined)
2220
- return { ok: true, value: undefined };
2221
- if (!Array.isArray(record[field]))
2222
- return validationFailure(`${field} must be an array`, tool);
2223
- const values = record[field];
2224
- const result = [];
2225
- for (const [index, item] of values.entries()) {
2226
- if (typeof item !== 'string')
2227
- return validationFailure(`${field}[${index}] must be a string`, tool);
2228
- if (item.trim().length === 0)
2229
- return validationFailure(`${field}[${index}] must not be empty`, tool);
2230
- result.push(item);
2231
- }
2232
- return { ok: true, value: result };
2233
- }
2234
- function validationFailure(message, tool) {
2235
- return errorEnvelope('validation_failed', message, tool);
2236
- }
2237
- function toValidationResultFailure(failure) {
2238
- return failure;
2239
- }
1
+ export * from '../interfaces/mcp/validation.js';