@open-mercato/ai-assistant 0.5.1-develop.3036.f02c281f23 → 0.5.1-develop.3045.b4b3320cc2

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 (273) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +361 -0
  3. package/README.md +5 -0
  4. package/dist/index.js +154 -0
  5. package/dist/index.js.map +2 -2
  6. package/dist/modules/ai_assistant/__integration__/TC-AI-002-agent-policy.spec.js +73 -0
  7. package/dist/modules/ai_assistant/__integration__/TC-AI-002-agent-policy.spec.js.map +7 -0
  8. package/dist/modules/ai_assistant/__integration__/TC-AI-AGENT-SETTINGS-005-settings-page.spec.js +484 -0
  9. package/dist/modules/ai_assistant/__integration__/TC-AI-AGENT-SETTINGS-005-settings-page.spec.js.map +7 -0
  10. package/dist/modules/ai_assistant/__integration__/TC-AI-PLAYGROUND-004-playground.spec.js +251 -0
  11. package/dist/modules/ai_assistant/__integration__/TC-AI-PLAYGROUND-004-playground.spec.js.map +7 -0
  12. package/dist/modules/ai_assistant/__integration__/TC-INT-AI-TOOLS.spec.js +91 -0
  13. package/dist/modules/ai_assistant/__integration__/TC-INT-AI-TOOLS.spec.js.map +7 -0
  14. package/dist/modules/ai_assistant/ai-tools/attachments-pack.js +202 -0
  15. package/dist/modules/ai_assistant/ai-tools/attachments-pack.js.map +7 -0
  16. package/dist/modules/ai_assistant/ai-tools/meta-pack.js +121 -0
  17. package/dist/modules/ai_assistant/ai-tools/meta-pack.js.map +7 -0
  18. package/dist/modules/ai_assistant/ai-tools/search-pack.js +94 -0
  19. package/dist/modules/ai_assistant/ai-tools/search-pack.js.map +7 -0
  20. package/dist/modules/ai_assistant/ai-tools.js +14 -0
  21. package/dist/modules/ai_assistant/ai-tools.js.map +7 -0
  22. package/dist/modules/ai_assistant/api/ai/actions/[id]/cancel/route.js +175 -0
  23. package/dist/modules/ai_assistant/api/ai/actions/[id]/cancel/route.js.map +7 -0
  24. package/dist/modules/ai_assistant/api/ai/actions/[id]/confirm/route.js +174 -0
  25. package/dist/modules/ai_assistant/api/ai/actions/[id]/confirm/route.js.map +7 -0
  26. package/dist/modules/ai_assistant/api/ai/actions/[id]/route.js +101 -0
  27. package/dist/modules/ai_assistant/api/ai/actions/[id]/route.js.map +7 -0
  28. package/dist/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/route.js +311 -0
  29. package/dist/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/route.js.map +7 -0
  30. package/dist/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/route.js +246 -0
  31. package/dist/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/route.js.map +7 -0
  32. package/dist/modules/ai_assistant/api/ai/agents/route.js +94 -0
  33. package/dist/modules/ai_assistant/api/ai/agents/route.js.map +7 -0
  34. package/dist/modules/ai_assistant/api/ai/chat/route.js +173 -0
  35. package/dist/modules/ai_assistant/api/ai/chat/route.js.map +7 -0
  36. package/dist/modules/ai_assistant/api/ai/run-object/route.js +167 -0
  37. package/dist/modules/ai_assistant/api/ai/run-object/route.js.map +7 -0
  38. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js +1111 -0
  39. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js.map +7 -0
  40. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.js +10 -0
  41. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.js.map +7 -0
  42. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.meta.js +28 -0
  43. package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/page.meta.js.map +7 -0
  44. package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.js +10 -0
  45. package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.js.map +7 -0
  46. package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.meta.js +30 -0
  47. package/dist/modules/ai_assistant/backend/config/ai-assistant/legacy/page.meta.js.map +7 -0
  48. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js +4 -6
  49. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.js.map +2 -2
  50. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js +1 -21
  51. package/dist/modules/ai_assistant/backend/config/ai-assistant/page.meta.js.map +2 -2
  52. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js +462 -0
  53. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js.map +7 -0
  54. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.js +10 -0
  55. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.js.map +7 -0
  56. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.meta.js +28 -0
  57. package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/page.meta.js.map +7 -0
  58. package/dist/modules/ai_assistant/cli.js +78 -12
  59. package/dist/modules/ai_assistant/cli.js.map +2 -2
  60. package/dist/modules/ai_assistant/data/entities/AiAgentMutationPolicyOverride.js +5 -0
  61. package/dist/modules/ai_assistant/data/entities/AiAgentMutationPolicyOverride.js.map +7 -0
  62. package/dist/modules/ai_assistant/data/entities/AiAgentPromptOverride.js +5 -0
  63. package/dist/modules/ai_assistant/data/entities/AiAgentPromptOverride.js.map +7 -0
  64. package/dist/modules/ai_assistant/data/entities/AiPendingAction.js +5 -0
  65. package/dist/modules/ai_assistant/data/entities/AiPendingAction.js.map +7 -0
  66. package/dist/modules/ai_assistant/data/entities.js +228 -0
  67. package/dist/modules/ai_assistant/data/entities.js.map +7 -0
  68. package/dist/modules/ai_assistant/data/repositories/AiAgentMutationPolicyOverrideRepository.js +95 -0
  69. package/dist/modules/ai_assistant/data/repositories/AiAgentMutationPolicyOverrideRepository.js.map +7 -0
  70. package/dist/modules/ai_assistant/data/repositories/AiAgentPromptOverrideRepository.js +95 -0
  71. package/dist/modules/ai_assistant/data/repositories/AiAgentPromptOverrideRepository.js.map +7 -0
  72. package/dist/modules/ai_assistant/data/repositories/AiPendingActionRepository.js +223 -0
  73. package/dist/modules/ai_assistant/data/repositories/AiPendingActionRepository.js.map +7 -0
  74. package/dist/modules/ai_assistant/events.js +33 -0
  75. package/dist/modules/ai_assistant/events.js.map +7 -0
  76. package/dist/modules/ai_assistant/i18n/de.json +252 -0
  77. package/dist/modules/ai_assistant/i18n/en.json +252 -0
  78. package/dist/modules/ai_assistant/i18n/es.json +252 -0
  79. package/dist/modules/ai_assistant/i18n/pl.json +252 -0
  80. package/dist/modules/ai_assistant/lib/agent-policy.js +168 -0
  81. package/dist/modules/ai_assistant/lib/agent-policy.js.map +7 -0
  82. package/dist/modules/ai_assistant/lib/agent-registry.js +195 -0
  83. package/dist/modules/ai_assistant/lib/agent-registry.js.map +7 -0
  84. package/dist/modules/ai_assistant/lib/agent-runtime.js +451 -0
  85. package/dist/modules/ai_assistant/lib/agent-runtime.js.map +7 -0
  86. package/dist/modules/ai_assistant/lib/agent-tools.js +223 -0
  87. package/dist/modules/ai_assistant/lib/agent-tools.js.map +7 -0
  88. package/dist/modules/ai_assistant/lib/agent-transport.js +25 -0
  89. package/dist/modules/ai_assistant/lib/agent-transport.js.map +7 -0
  90. package/dist/modules/ai_assistant/lib/ai-agent-definition.js +11 -0
  91. package/dist/modules/ai_assistant/lib/ai-agent-definition.js.map +7 -0
  92. package/dist/modules/ai_assistant/lib/ai-agents-generated.d.js +1 -0
  93. package/dist/modules/ai_assistant/lib/ai-agents-generated.d.js.map +7 -0
  94. package/dist/modules/ai_assistant/lib/ai-api-operation-runner.js +239 -0
  95. package/dist/modules/ai_assistant/lib/ai-api-operation-runner.js.map +7 -0
  96. package/dist/modules/ai_assistant/lib/ai-overrides.js +189 -0
  97. package/dist/modules/ai_assistant/lib/ai-overrides.js.map +7 -0
  98. package/dist/modules/ai_assistant/lib/ai-tool-definition.js +7 -0
  99. package/dist/modules/ai_assistant/lib/ai-tool-definition.js.map +7 -0
  100. package/dist/modules/ai_assistant/lib/ai-tools-generated.d.js +1 -0
  101. package/dist/modules/ai_assistant/lib/ai-tools-generated.d.js.map +7 -0
  102. package/dist/modules/ai_assistant/lib/api-backed-tool.js +48 -0
  103. package/dist/modules/ai_assistant/lib/api-backed-tool.js.map +7 -0
  104. package/dist/modules/ai_assistant/lib/attachment-bridge-types.js +1 -0
  105. package/dist/modules/ai_assistant/lib/attachment-bridge-types.js.map +7 -0
  106. package/dist/modules/ai_assistant/lib/attachment-parts.js +276 -0
  107. package/dist/modules/ai_assistant/lib/attachment-parts.js.map +7 -0
  108. package/dist/modules/ai_assistant/lib/model-factory.js +68 -0
  109. package/dist/modules/ai_assistant/lib/model-factory.js.map +7 -0
  110. package/dist/modules/ai_assistant/lib/pending-action-cancel.js +86 -0
  111. package/dist/modules/ai_assistant/lib/pending-action-cancel.js.map +7 -0
  112. package/dist/modules/ai_assistant/lib/pending-action-client.js +35 -0
  113. package/dist/modules/ai_assistant/lib/pending-action-client.js.map +7 -0
  114. package/dist/modules/ai_assistant/lib/pending-action-executor.js +243 -0
  115. package/dist/modules/ai_assistant/lib/pending-action-executor.js.map +7 -0
  116. package/dist/modules/ai_assistant/lib/pending-action-recheck.js +246 -0
  117. package/dist/modules/ai_assistant/lib/pending-action-recheck.js.map +7 -0
  118. package/dist/modules/ai_assistant/lib/pending-action-types.js +70 -0
  119. package/dist/modules/ai_assistant/lib/pending-action-types.js.map +7 -0
  120. package/dist/modules/ai_assistant/lib/prepare-mutation.js +315 -0
  121. package/dist/modules/ai_assistant/lib/prepare-mutation.js.map +7 -0
  122. package/dist/modules/ai_assistant/lib/prompt-composition-types.js +7 -0
  123. package/dist/modules/ai_assistant/lib/prompt-composition-types.js.map +7 -0
  124. package/dist/modules/ai_assistant/lib/prompt-override-merge.js +175 -0
  125. package/dist/modules/ai_assistant/lib/prompt-override-merge.js.map +7 -0
  126. package/dist/modules/ai_assistant/lib/schema-utils.js +5 -1
  127. package/dist/modules/ai_assistant/lib/schema-utils.js.map +2 -2
  128. package/dist/modules/ai_assistant/lib/tool-executor.js +13 -2
  129. package/dist/modules/ai_assistant/lib/tool-executor.js.map +2 -2
  130. package/dist/modules/ai_assistant/lib/tool-loader.js +86 -11
  131. package/dist/modules/ai_assistant/lib/tool-loader.js.map +2 -2
  132. package/dist/modules/ai_assistant/lib/tool-test-fixtures.js +120 -0
  133. package/dist/modules/ai_assistant/lib/tool-test-fixtures.js.map +7 -0
  134. package/dist/modules/ai_assistant/lib/tool-test-runner.js +418 -0
  135. package/dist/modules/ai_assistant/lib/tool-test-runner.js.map +7 -0
  136. package/dist/modules/ai_assistant/migrations/Migration20260419100521.js +17 -0
  137. package/dist/modules/ai_assistant/migrations/Migration20260419100521.js.map +7 -0
  138. package/dist/modules/ai_assistant/migrations/Migration20260419132948.js +16 -0
  139. package/dist/modules/ai_assistant/migrations/Migration20260419132948.js.map +7 -0
  140. package/dist/modules/ai_assistant/migrations/Migration20260419134235.js +17 -0
  141. package/dist/modules/ai_assistant/migrations/Migration20260419134235.js.map +7 -0
  142. package/dist/modules/ai_assistant/setup.js +36 -0
  143. package/dist/modules/ai_assistant/setup.js.map +2 -2
  144. package/dist/modules/ai_assistant/workers/ai-pending-action-cleanup.js +161 -0
  145. package/dist/modules/ai_assistant/workers/ai-pending-action-cleanup.js.map +7 -0
  146. package/generated/entities/ai_agent_mutation_policy_override/index.ts +9 -0
  147. package/generated/entities/ai_agent_prompt_override/index.ts +10 -0
  148. package/generated/entities/ai_pending_action/index.ts +24 -0
  149. package/generated/entities.ids.generated.ts +13 -0
  150. package/generated/entity-fields-registry.ts +57 -0
  151. package/jest.config.cjs +7 -0
  152. package/package.json +4 -4
  153. package/src/index.ts +215 -0
  154. package/src/modules/ai_assistant/__integration__/README.md +5 -0
  155. package/src/modules/ai_assistant/__integration__/TC-AI-002-agent-policy.spec.ts +115 -0
  156. package/src/modules/ai_assistant/__integration__/TC-AI-AGENT-SETTINGS-005-settings-page.spec.ts +574 -0
  157. package/src/modules/ai_assistant/__integration__/TC-AI-PLAYGROUND-004-playground.spec.ts +333 -0
  158. package/src/modules/ai_assistant/__integration__/TC-INT-AI-TOOLS.spec.ts +135 -0
  159. package/src/modules/ai_assistant/__tests__/events.test.ts +145 -0
  160. package/src/modules/ai_assistant/__tests__/integration/pending-action-contract.test.ts +1015 -0
  161. package/src/modules/ai_assistant/__tests__/integration/ws-c-attachment-bridge.test.ts +235 -0
  162. package/src/modules/ai_assistant/__tests__/integration/ws-c-policy-and-tools.test.ts +330 -0
  163. package/src/modules/ai_assistant/__tests__/integration/ws-c-tool-pack-coverage.test.ts +285 -0
  164. package/src/modules/ai_assistant/ai-tools/__tests__/attachments-pack.test.ts +322 -0
  165. package/src/modules/ai_assistant/ai-tools/__tests__/meta-pack.test.ts +218 -0
  166. package/src/modules/ai_assistant/ai-tools/__tests__/search-pack.test.ts +192 -0
  167. package/src/modules/ai_assistant/ai-tools/attachments-pack.ts +269 -0
  168. package/src/modules/ai_assistant/ai-tools/meta-pack.ts +140 -0
  169. package/src/modules/ai_assistant/ai-tools/search-pack.ts +122 -0
  170. package/src/modules/ai_assistant/ai-tools.ts +21 -0
  171. package/src/modules/ai_assistant/api/ai/actions/[id]/__tests__/route.test.ts +222 -0
  172. package/src/modules/ai_assistant/api/ai/actions/[id]/cancel/__tests__/route.test.ts +286 -0
  173. package/src/modules/ai_assistant/api/ai/actions/[id]/cancel/route.ts +237 -0
  174. package/src/modules/ai_assistant/api/ai/actions/[id]/confirm/__tests__/route.test.ts +339 -0
  175. package/src/modules/ai_assistant/api/ai/actions/[id]/confirm/route.ts +229 -0
  176. package/src/modules/ai_assistant/api/ai/actions/[id]/route.ts +142 -0
  177. package/src/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/__tests__/route.test.ts +367 -0
  178. package/src/modules/ai_assistant/api/ai/agents/[agentId]/mutation-policy/route.ts +380 -0
  179. package/src/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/__tests__/route.test.ts +333 -0
  180. package/src/modules/ai_assistant/api/ai/agents/[agentId]/prompt-override/route.ts +307 -0
  181. package/src/modules/ai_assistant/api/ai/agents/route.ts +107 -0
  182. package/src/modules/ai_assistant/api/ai/chat/__tests__/route.test.ts +282 -0
  183. package/src/modules/ai_assistant/api/ai/chat/route.ts +207 -0
  184. package/src/modules/ai_assistant/api/ai/run-object/__tests__/route.test.ts +282 -0
  185. package/src/modules/ai_assistant/api/ai/run-object/route.ts +204 -0
  186. package/src/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.tsx +1419 -0
  187. package/src/modules/ai_assistant/backend/config/ai-assistant/agents/page.meta.ts +26 -0
  188. package/src/modules/ai_assistant/backend/config/ai-assistant/agents/page.tsx +12 -0
  189. package/src/modules/ai_assistant/backend/config/ai-assistant/legacy/page.meta.ts +28 -0
  190. package/src/modules/ai_assistant/backend/config/ai-assistant/legacy/page.tsx +12 -0
  191. package/src/modules/ai_assistant/backend/config/ai-assistant/page.meta.ts +8 -23
  192. package/src/modules/ai_assistant/backend/config/ai-assistant/page.tsx +15 -10
  193. package/src/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.tsx +604 -0
  194. package/src/modules/ai_assistant/backend/config/ai-assistant/playground/page.meta.ts +26 -0
  195. package/src/modules/ai_assistant/backend/config/ai-assistant/playground/page.tsx +12 -0
  196. package/src/modules/ai_assistant/cli.ts +99 -24
  197. package/src/modules/ai_assistant/data/__tests__/schema-unique-indexes.test.ts +69 -0
  198. package/src/modules/ai_assistant/data/entities/AiAgentMutationPolicyOverride.ts +7 -0
  199. package/src/modules/ai_assistant/data/entities/AiAgentPromptOverride.ts +7 -0
  200. package/src/modules/ai_assistant/data/entities/AiPendingAction.ts +7 -0
  201. package/src/modules/ai_assistant/data/entities.ts +270 -0
  202. package/src/modules/ai_assistant/data/repositories/AiAgentMutationPolicyOverrideRepository.ts +129 -0
  203. package/src/modules/ai_assistant/data/repositories/AiAgentPromptOverrideRepository.ts +132 -0
  204. package/src/modules/ai_assistant/data/repositories/AiPendingActionRepository.ts +334 -0
  205. package/src/modules/ai_assistant/data/repositories/__tests__/AiAgentMutationPolicyOverrideRepository.test.ts +195 -0
  206. package/src/modules/ai_assistant/data/repositories/__tests__/AiAgentPromptOverrideRepository.test.ts +197 -0
  207. package/src/modules/ai_assistant/data/repositories/__tests__/AiPendingActionRepository.test.ts +357 -0
  208. package/src/modules/ai_assistant/events.ts +112 -0
  209. package/src/modules/ai_assistant/i18n/de.json +252 -0
  210. package/src/modules/ai_assistant/i18n/en.json +252 -0
  211. package/src/modules/ai_assistant/i18n/es.json +252 -0
  212. package/src/modules/ai_assistant/i18n/pl.json +252 -0
  213. package/src/modules/ai_assistant/lib/__tests__/agent-policy.mutation-override.test.ts +203 -0
  214. package/src/modules/ai_assistant/lib/__tests__/agent-policy.test.ts +385 -0
  215. package/src/modules/ai_assistant/lib/__tests__/agent-registry.test.ts +217 -0
  216. package/src/modules/ai_assistant/lib/__tests__/agent-runtime-object.test.ts +329 -0
  217. package/src/modules/ai_assistant/lib/__tests__/agent-runtime-parity.test.ts +573 -0
  218. package/src/modules/ai_assistant/lib/__tests__/agent-runtime.test.ts +291 -0
  219. package/src/modules/ai_assistant/lib/__tests__/agent-tools.test.ts +172 -0
  220. package/src/modules/ai_assistant/lib/__tests__/agent-transport.test.ts +41 -0
  221. package/src/modules/ai_assistant/lib/__tests__/ai-agent-definition.test.ts +183 -0
  222. package/src/modules/ai_assistant/lib/__tests__/ai-api-operation-runner.test.ts +432 -0
  223. package/src/modules/ai_assistant/lib/__tests__/ai-overrides.test.ts +308 -0
  224. package/src/modules/ai_assistant/lib/__tests__/api-backed-tool.test.ts +302 -0
  225. package/src/modules/ai_assistant/lib/__tests__/attachment-bridge-and-prompt-types.test.ts +188 -0
  226. package/src/modules/ai_assistant/lib/__tests__/attachment-parts.test.ts +531 -0
  227. package/src/modules/ai_assistant/lib/__tests__/max-steps-budget.integration.test.ts +263 -0
  228. package/src/modules/ai_assistant/lib/__tests__/model-factory.integration.test.ts +183 -0
  229. package/src/modules/ai_assistant/lib/__tests__/model-factory.test.ts +168 -0
  230. package/src/modules/ai_assistant/lib/__tests__/pending-action-cancel.test.ts +235 -0
  231. package/src/modules/ai_assistant/lib/__tests__/pending-action-client.test.ts +148 -0
  232. package/src/modules/ai_assistant/lib/__tests__/pending-action-executor.test.ts +348 -0
  233. package/src/modules/ai_assistant/lib/__tests__/pending-action-recheck.test.ts +378 -0
  234. package/src/modules/ai_assistant/lib/__tests__/phase-0-additive-contract.test.ts +299 -0
  235. package/src/modules/ai_assistant/lib/__tests__/prepare-mutation.test.ts +610 -0
  236. package/src/modules/ai_assistant/lib/__tests__/prompt-override-merge.test.ts +136 -0
  237. package/src/modules/ai_assistant/lib/__tests__/tool-loader.test.ts +125 -0
  238. package/src/modules/ai_assistant/lib/agent-policy.ts +270 -0
  239. package/src/modules/ai_assistant/lib/agent-registry.ts +277 -0
  240. package/src/modules/ai_assistant/lib/agent-runtime.ts +751 -0
  241. package/src/modules/ai_assistant/lib/agent-tools.ts +396 -0
  242. package/src/modules/ai_assistant/lib/agent-transport.ts +51 -0
  243. package/src/modules/ai_assistant/lib/ai-agent-definition.ts +86 -0
  244. package/src/modules/ai_assistant/lib/ai-agents-generated.d.ts +18 -0
  245. package/src/modules/ai_assistant/lib/ai-api-operation-runner.ts +333 -0
  246. package/src/modules/ai_assistant/lib/ai-overrides.ts +389 -0
  247. package/src/modules/ai_assistant/lib/ai-tool-definition.ts +7 -0
  248. package/src/modules/ai_assistant/lib/ai-tools-generated.d.ts +7 -0
  249. package/src/modules/ai_assistant/lib/api-backed-tool.ts +85 -0
  250. package/src/modules/ai_assistant/lib/attachment-bridge-types.ts +24 -0
  251. package/src/modules/ai_assistant/lib/attachment-parts.ts +433 -0
  252. package/src/modules/ai_assistant/lib/model-factory.ts +212 -0
  253. package/src/modules/ai_assistant/lib/pending-action-cancel.ts +179 -0
  254. package/src/modules/ai_assistant/lib/pending-action-client.ts +126 -0
  255. package/src/modules/ai_assistant/lib/pending-action-executor.ts +424 -0
  256. package/src/modules/ai_assistant/lib/pending-action-recheck.ts +410 -0
  257. package/src/modules/ai_assistant/lib/pending-action-types.ts +194 -0
  258. package/src/modules/ai_assistant/lib/prepare-mutation.ts +448 -0
  259. package/src/modules/ai_assistant/lib/prompt-composition-types.ts +24 -0
  260. package/src/modules/ai_assistant/lib/prompt-override-merge.ts +253 -0
  261. package/src/modules/ai_assistant/lib/schema-utils.ts +14 -2
  262. package/src/modules/ai_assistant/lib/tool-executor.ts +25 -3
  263. package/src/modules/ai_assistant/lib/tool-loader.ts +159 -13
  264. package/src/modules/ai_assistant/lib/tool-test-fixtures.ts +160 -0
  265. package/src/modules/ai_assistant/lib/tool-test-runner.ts +596 -0
  266. package/src/modules/ai_assistant/lib/types.ts +105 -2
  267. package/src/modules/ai_assistant/migrations/.snapshot-open-mercato.json +871 -0
  268. package/src/modules/ai_assistant/migrations/Migration20260419100521.ts +17 -0
  269. package/src/modules/ai_assistant/migrations/Migration20260419132948.ts +16 -0
  270. package/src/modules/ai_assistant/migrations/Migration20260419134235.ts +17 -0
  271. package/src/modules/ai_assistant/setup.ts +53 -0
  272. package/src/modules/ai_assistant/workers/__tests__/ai-pending-action-cleanup.test.ts +333 -0
  273. package/src/modules/ai_assistant/workers/ai-pending-action-cleanup.ts +269 -0
@@ -0,0 +1,121 @@
1
+ import { z } from "zod";
2
+ import { listAgents, getAgent } from "../lib/agent-registry.js";
3
+ import { hasRequiredFeatures } from "../lib/auth.js";
4
+ import { defineAiTool } from "../lib/ai-tool-definition.js";
5
+ function summarizeAgent(agent) {
6
+ return {
7
+ id: agent.id,
8
+ moduleId: agent.moduleId,
9
+ label: agent.label,
10
+ description: agent.description,
11
+ requiredFeatures: agent.requiredFeatures ?? [],
12
+ allowedTools: agent.allowedTools,
13
+ executionMode: agent.executionMode ?? "chat",
14
+ mutationPolicy: agent.mutationPolicy ?? "read-only",
15
+ readOnly: typeof agent.readOnly === "boolean" ? agent.readOnly : true,
16
+ maxSteps: agent.maxSteps ?? null,
17
+ acceptedMediaTypes: agent.acceptedMediaTypes ?? [],
18
+ domain: agent.domain ?? null,
19
+ keywords: agent.keywords ?? [],
20
+ suggestions: agent.suggestions ?? [],
21
+ dataCapabilities: agent.dataCapabilities ?? null,
22
+ hasOutputSchema: Boolean(agent.output),
23
+ hasPageContextResolver: typeof agent.resolvePageContext === "function"
24
+ };
25
+ }
26
+ function serializeStructuredOutput(output) {
27
+ if (!output) return null;
28
+ try {
29
+ const jsonSchema = z.toJSONSchema(output.schema, {
30
+ unrepresentable: "any"
31
+ });
32
+ return {
33
+ schemaName: output.schemaName,
34
+ mode: output.mode ?? "generate",
35
+ jsonSchema
36
+ };
37
+ } catch (error) {
38
+ return {
39
+ schemaName: output.schemaName,
40
+ mode: output.mode ?? "generate",
41
+ note: "non-serializable",
42
+ error: error instanceof Error ? error.message : String(error)
43
+ };
44
+ }
45
+ }
46
+ function serializePrompt(agent) {
47
+ return {
48
+ systemPrompt: agent.systemPrompt,
49
+ hasDynamicPageContext: typeof agent.resolvePageContext === "function"
50
+ };
51
+ }
52
+ const listAgentsInput = z.object({
53
+ moduleId: z.string().optional().describe("Restrict results to one module id.")
54
+ });
55
+ const listAgentsTool = defineAiTool({
56
+ name: "meta.list_agents",
57
+ displayName: "List agents",
58
+ description: "List registered AI agents the caller can invoke. Filters by requiredFeatures RBAC; returns { agents: [] } if the registry is empty.",
59
+ inputSchema: listAgentsInput,
60
+ requiredFeatures: ["ai_assistant.view"],
61
+ tags: ["read", "meta"],
62
+ handler: async (rawInput, ctx) => {
63
+ const input = listAgentsInput.parse(rawInput);
64
+ let all = [];
65
+ try {
66
+ all = listAgents();
67
+ } catch {
68
+ all = [];
69
+ }
70
+ const filtered = all.filter((agent) => {
71
+ if (input.moduleId && agent.moduleId !== input.moduleId) return false;
72
+ const features = agent.requiredFeatures ?? [];
73
+ return hasRequiredFeatures(features, ctx.userFeatures, ctx.isSuperAdmin);
74
+ });
75
+ return {
76
+ agents: filtered.map(summarizeAgent),
77
+ total: filtered.length
78
+ };
79
+ }
80
+ });
81
+ const describeAgentInput = z.object({
82
+ agentId: z.string().min(1).describe('Agent id (e.g. "catalog.merchandising_assistant").')
83
+ });
84
+ const describeAgentTool = defineAiTool({
85
+ name: "meta.describe_agent",
86
+ displayName: "Describe agent",
87
+ description: "Return metadata, RBAC, allowed tools, execution mode, output schema (JSON-Schema when representable), and prompt shape for a single agent. Never throws \u2014 returns { agent: null, reason } if missing or forbidden.",
88
+ inputSchema: describeAgentInput,
89
+ requiredFeatures: ["ai_assistant.view"],
90
+ tags: ["read", "meta"],
91
+ handler: async (rawInput, ctx) => {
92
+ const input = describeAgentInput.parse(rawInput);
93
+ let agent;
94
+ try {
95
+ agent = getAgent(input.agentId);
96
+ } catch {
97
+ agent = void 0;
98
+ }
99
+ if (!agent) {
100
+ return { agent: null, reason: "not_found" };
101
+ }
102
+ const features = agent.requiredFeatures ?? [];
103
+ if (!hasRequiredFeatures(features, ctx.userFeatures, ctx.isSuperAdmin)) {
104
+ return { agent: null, reason: "forbidden" };
105
+ }
106
+ return {
107
+ agent: {
108
+ ...summarizeAgent(agent),
109
+ output: serializeStructuredOutput(agent.output),
110
+ prompt: serializePrompt(agent)
111
+ }
112
+ };
113
+ }
114
+ });
115
+ const metaAiTools = [listAgentsTool, describeAgentTool];
116
+ var meta_pack_default = metaAiTools;
117
+ export {
118
+ meta_pack_default as default,
119
+ metaAiTools
120
+ };
121
+ //# sourceMappingURL=meta-pack.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/ai-tools/meta-pack.ts"],
4
+ "sourcesContent": ["/**\n * General-purpose `meta.*` tool pack (Phase 1 WS-C, Step 3.8).\n *\n * `list_agents` enumerates agents the caller can invoke; `describe_agent`\n * returns a serializable description (Zod output schema \u2192 JSON-Schema when\n * possible, otherwise a `non-serializable` marker). Both tools treat a\n * missing agent registry as an empty list \u2014 the chat runtime must not\n * crash if `ai-agents.generated.ts` has not been emitted yet.\n */\nimport { z } from 'zod'\nimport type { AiAgentDefinition } from '../lib/ai-agent-definition'\nimport { listAgents, getAgent } from '../lib/agent-registry'\nimport { hasRequiredFeatures } from '../lib/auth'\nimport { defineAiTool } from '../lib/ai-tool-definition'\nimport type { AiToolDefinition } from '../lib/types'\n\nfunction summarizeAgent(agent: AiAgentDefinition): Record<string, unknown> {\n return {\n id: agent.id,\n moduleId: agent.moduleId,\n label: agent.label,\n description: agent.description,\n requiredFeatures: agent.requiredFeatures ?? [],\n allowedTools: agent.allowedTools,\n executionMode: agent.executionMode ?? 'chat',\n mutationPolicy: agent.mutationPolicy ?? 'read-only',\n readOnly: typeof agent.readOnly === 'boolean' ? agent.readOnly : true,\n maxSteps: agent.maxSteps ?? null,\n acceptedMediaTypes: agent.acceptedMediaTypes ?? [],\n domain: agent.domain ?? null,\n keywords: agent.keywords ?? [],\n suggestions: agent.suggestions ?? [],\n dataCapabilities: agent.dataCapabilities ?? null,\n hasOutputSchema: Boolean(agent.output),\n hasPageContextResolver: typeof agent.resolvePageContext === 'function',\n }\n}\n\nfunction serializeStructuredOutput(\n output: AiAgentDefinition['output'],\n): Record<string, unknown> | null {\n if (!output) return null\n try {\n const jsonSchema = z.toJSONSchema(output.schema as unknown as z.ZodType, {\n unrepresentable: 'any',\n })\n return {\n schemaName: output.schemaName,\n mode: output.mode ?? 'generate',\n jsonSchema,\n }\n } catch (error) {\n return {\n schemaName: output.schemaName,\n mode: output.mode ?? 'generate',\n note: 'non-serializable',\n error: error instanceof Error ? error.message : String(error),\n }\n }\n}\n\nfunction serializePrompt(agent: AiAgentDefinition): Record<string, unknown> {\n return {\n systemPrompt: agent.systemPrompt,\n hasDynamicPageContext: typeof agent.resolvePageContext === 'function',\n }\n}\n\nconst listAgentsInput = z.object({\n moduleId: z.string().optional().describe('Restrict results to one module id.'),\n})\n\nconst listAgentsTool = defineAiTool({\n name: 'meta.list_agents',\n displayName: 'List agents',\n description:\n 'List registered AI agents the caller can invoke. Filters by requiredFeatures RBAC; returns { agents: [] } if the registry is empty.',\n inputSchema: listAgentsInput,\n requiredFeatures: ['ai_assistant.view'],\n tags: ['read', 'meta'],\n handler: async (rawInput, ctx) => {\n const input = listAgentsInput.parse(rawInput)\n let all: AiAgentDefinition[] = []\n try {\n all = listAgents()\n } catch {\n all = []\n }\n const filtered = all.filter((agent) => {\n if (input.moduleId && agent.moduleId !== input.moduleId) return false\n const features = agent.requiredFeatures ?? []\n return hasRequiredFeatures(features, ctx.userFeatures, ctx.isSuperAdmin)\n })\n return {\n agents: filtered.map(summarizeAgent),\n total: filtered.length,\n }\n },\n})\n\nconst describeAgentInput = z.object({\n agentId: z.string().min(1).describe('Agent id (e.g. \"catalog.merchandising_assistant\").'),\n})\n\nconst describeAgentTool = defineAiTool({\n name: 'meta.describe_agent',\n displayName: 'Describe agent',\n description:\n 'Return metadata, RBAC, allowed tools, execution mode, output schema (JSON-Schema when representable), and prompt shape for a single agent. Never throws \u2014 returns { agent: null, reason } if missing or forbidden.',\n inputSchema: describeAgentInput,\n requiredFeatures: ['ai_assistant.view'],\n tags: ['read', 'meta'],\n handler: async (rawInput, ctx) => {\n const input = describeAgentInput.parse(rawInput)\n let agent: AiAgentDefinition | undefined\n try {\n agent = getAgent(input.agentId)\n } catch {\n agent = undefined\n }\n if (!agent) {\n return { agent: null, reason: 'not_found' as const }\n }\n const features = agent.requiredFeatures ?? []\n if (!hasRequiredFeatures(features, ctx.userFeatures, ctx.isSuperAdmin)) {\n return { agent: null, reason: 'forbidden' as const }\n }\n return {\n agent: {\n ...summarizeAgent(agent),\n output: serializeStructuredOutput(agent.output),\n prompt: serializePrompt(agent),\n },\n }\n },\n})\n\nexport const metaAiTools: AiToolDefinition<any, any>[] = [listAgentsTool, describeAgentTool]\n\nexport default metaAiTools\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,94 @@
1
+ import { z } from "zod";
2
+ import { defineAiTool } from "../lib/ai-tool-definition.js";
3
+ const hybridSearchInput = z.object({
4
+ q: z.string().min(1).describe("Search query text."),
5
+ limit: z.number().int().min(1).max(100).optional().describe("Maximum results (default 20, max 100)."),
6
+ strategies: z.array(z.enum(["fulltext", "vector", "tokens"])).optional().describe("Subset of strategies to run; defaults to the module defaults."),
7
+ entityTypes: z.array(z.string()).optional().describe('Filter to specific entity ids (e.g. "catalog:product").')
8
+ });
9
+ const hybridSearchTool = defineAiTool({
10
+ name: "search.hybrid_search",
11
+ displayName: "Hybrid search",
12
+ description: "Run a global fulltext + vector + token search across enabled entities for the current tenant/organization.",
13
+ inputSchema: hybridSearchInput,
14
+ requiredFeatures: ["search.view"],
15
+ tags: ["read", "search"],
16
+ handler: async (rawInput, ctx) => {
17
+ if (!ctx.tenantId) {
18
+ throw new Error("Tenant context is required for search.hybrid_search");
19
+ }
20
+ const input = hybridSearchInput.parse(rawInput);
21
+ const service = ctx.container.resolve("searchService");
22
+ const limit = input.limit ?? 20;
23
+ const started = Date.now();
24
+ const results = await service.search(input.q, {
25
+ tenantId: ctx.tenantId,
26
+ organizationId: ctx.organizationId,
27
+ limit,
28
+ strategies: input.strategies,
29
+ entityTypes: input.entityTypes
30
+ });
31
+ const timingMs = Date.now() - started;
32
+ const strategiesUsed = Array.from(
33
+ new Set(results.map((result) => result.source).filter((id) => typeof id === "string"))
34
+ );
35
+ return {
36
+ query: input.q,
37
+ totalResults: results.length,
38
+ results,
39
+ strategiesUsed,
40
+ timing: { ms: timingMs }
41
+ };
42
+ }
43
+ });
44
+ const getRecordContextInput = z.object({
45
+ entityId: z.string().min(1).describe('Entity identifier (e.g. "customers:customer_person_profile").'),
46
+ recordId: z.string().min(1).describe("Record primary key (UUID).")
47
+ });
48
+ const getRecordContextTool = defineAiTool({
49
+ name: "search.get_record_context",
50
+ displayName: "Get record context",
51
+ description: "Resolve presenter, links, and URL for a specific record by re-querying the search index. Returns { found: false } when no hit matches the recordId.",
52
+ inputSchema: getRecordContextInput,
53
+ requiredFeatures: ["search.view"],
54
+ tags: ["read", "search"],
55
+ handler: async (rawInput, ctx) => {
56
+ if (!ctx.tenantId) {
57
+ throw new Error("Tenant context is required for search.get_record_context");
58
+ }
59
+ const input = getRecordContextInput.parse(rawInput);
60
+ const service = ctx.container.resolve("searchService");
61
+ const results = await service.search(input.recordId, {
62
+ tenantId: ctx.tenantId,
63
+ organizationId: ctx.organizationId,
64
+ limit: 5,
65
+ entityTypes: [input.entityId]
66
+ });
67
+ const match = results.find((result) => result.recordId === input.recordId);
68
+ if (!match) {
69
+ return {
70
+ found: false,
71
+ entityId: input.entityId,
72
+ recordId: input.recordId
73
+ };
74
+ }
75
+ return {
76
+ found: true,
77
+ entityId: match.entityId,
78
+ recordId: match.recordId,
79
+ presenter: match.presenter,
80
+ url: match.url,
81
+ links: match.links,
82
+ metadata: match.metadata,
83
+ source: match.source,
84
+ score: match.score
85
+ };
86
+ }
87
+ });
88
+ const searchAiTools = [hybridSearchTool, getRecordContextTool];
89
+ var search_pack_default = searchAiTools;
90
+ export {
91
+ search_pack_default as default,
92
+ searchAiTools
93
+ };
94
+ //# sourceMappingURL=search-pack.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/ai-tools/search-pack.ts"],
4
+ "sourcesContent": ["/**\n * General-purpose `search.*` tool pack (Phase 1 WS-C, Step 3.8).\n *\n * These tools are discovered by the generator alongside any other module\n * `ai-tools.ts`; they expose the existing `@open-mercato/search` runtime to\n * agents that whitelist them via `allowedTools`.\n */\nimport { z } from 'zod'\nimport type { SearchOptions, SearchResult, SearchStrategyId } from '@open-mercato/shared/modules/search'\nimport { defineAiTool } from '../lib/ai-tool-definition'\nimport type { AiToolDefinition } from '../lib/types'\n\ntype SearchServiceLike = {\n search: (query: string, options: SearchOptions) => Promise<SearchResult[]>\n}\n\nconst hybridSearchInput = z.object({\n q: z.string().min(1).describe('Search query text.'),\n limit: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Maximum results (default 20, max 100).'),\n strategies: z\n .array(z.enum(['fulltext', 'vector', 'tokens']))\n .optional()\n .describe('Subset of strategies to run; defaults to the module defaults.'),\n entityTypes: z\n .array(z.string())\n .optional()\n .describe('Filter to specific entity ids (e.g. \"catalog:product\").'),\n})\n\nconst hybridSearchTool = defineAiTool({\n name: 'search.hybrid_search',\n displayName: 'Hybrid search',\n description:\n 'Run a global fulltext + vector + token search across enabled entities for the current tenant/organization.',\n inputSchema: hybridSearchInput,\n requiredFeatures: ['search.view'],\n tags: ['read', 'search'],\n handler: async (rawInput, ctx) => {\n if (!ctx.tenantId) {\n throw new Error('Tenant context is required for search.hybrid_search')\n }\n const input = hybridSearchInput.parse(rawInput)\n const service = ctx.container.resolve<SearchServiceLike>('searchService')\n const limit = input.limit ?? 20\n const started = Date.now()\n const results = await service.search(input.q, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n limit,\n strategies: input.strategies as SearchStrategyId[] | undefined,\n entityTypes: input.entityTypes,\n })\n const timingMs = Date.now() - started\n const strategiesUsed = Array.from(\n new Set(results.map((result) => result.source).filter((id): id is SearchStrategyId => typeof id === 'string')),\n )\n return {\n query: input.q,\n totalResults: results.length,\n results,\n strategiesUsed,\n timing: { ms: timingMs },\n }\n },\n})\n\nconst getRecordContextInput = z.object({\n entityId: z.string().min(1).describe('Entity identifier (e.g. \"customers:customer_person_profile\").'),\n recordId: z.string().min(1).describe('Record primary key (UUID).'),\n})\n\nconst getRecordContextTool = defineAiTool({\n name: 'search.get_record_context',\n displayName: 'Get record context',\n description:\n 'Resolve presenter, links, and URL for a specific record by re-querying the search index. Returns { found: false } when no hit matches the recordId.',\n inputSchema: getRecordContextInput,\n requiredFeatures: ['search.view'],\n tags: ['read', 'search'],\n handler: async (rawInput, ctx) => {\n if (!ctx.tenantId) {\n throw new Error('Tenant context is required for search.get_record_context')\n }\n const input = getRecordContextInput.parse(rawInput)\n const service = ctx.container.resolve<SearchServiceLike>('searchService')\n const results = await service.search(input.recordId, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n limit: 5,\n entityTypes: [input.entityId],\n })\n const match = results.find((result) => result.recordId === input.recordId)\n if (!match) {\n return {\n found: false as const,\n entityId: input.entityId,\n recordId: input.recordId,\n }\n }\n return {\n found: true as const,\n entityId: match.entityId,\n recordId: match.recordId,\n presenter: match.presenter,\n url: match.url,\n links: match.links,\n metadata: match.metadata,\n source: match.source,\n score: match.score,\n }\n },\n})\n\nexport const searchAiTools: AiToolDefinition<any, any>[] = [hybridSearchTool, getRecordContextTool]\n\nexport default searchAiTools\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ import searchAiTools from "./ai-tools/search-pack.js";
2
+ import attachmentsAiTools from "./ai-tools/attachments-pack.js";
3
+ import metaAiTools from "./ai-tools/meta-pack.js";
4
+ const aiTools = [
5
+ ...searchAiTools,
6
+ ...attachmentsAiTools,
7
+ ...metaAiTools
8
+ ];
9
+ var ai_tools_default = aiTools;
10
+ export {
11
+ aiTools,
12
+ ai_tools_default as default
13
+ };
14
+ //# sourceMappingURL=ai-tools.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/ai_assistant/ai-tools.ts"],
4
+ "sourcesContent": ["/**\n * Module-root AI tools contribution for `ai_assistant` (Phase 1 WS-C, Step 3.8).\n *\n * The generator scans every module for a top-level `ai-tools.ts` and takes\n * the `aiTools` (or `default`) export as the module contribution. This file\n * aggregates the three general-purpose tool packs (`search.*`,\n * `attachments.*`, `meta.*`) so they flow through the existing\n * `ai-tools.generated.ts` pipeline without any new generator plumbing.\n */\nimport type { AiToolDefinition } from './lib/types'\nimport searchAiTools from './ai-tools/search-pack'\nimport attachmentsAiTools from './ai-tools/attachments-pack'\nimport metaAiTools from './ai-tools/meta-pack'\n\nexport const aiTools: AiToolDefinition<any, any>[] = [\n ...searchAiTools,\n ...attachmentsAiTools,\n ...metaAiTools,\n]\n\nexport default aiTools\n"],
5
+ "mappings": "AAUA,OAAO,mBAAmB;AAC1B,OAAO,wBAAwB;AAC/B,OAAO,iBAAiB;AAEjB,MAAM,UAAwC;AAAA,EACnD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAEA,IAAO,mBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,175 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import { AiPendingActionRepository } from "../../../../../data/repositories/AiPendingActionRepository.js";
6
+ import { hasRequiredFeatures } from "../../../../../lib/auth.js";
7
+ import { serializePendingActionForClient } from "../../../../../lib/pending-action-client.js";
8
+ import { checkStatusAndExpiry } from "../../../../../lib/pending-action-recheck.js";
9
+ import { executePendingActionCancel } from "../../../../../lib/pending-action-cancel.js";
10
+ const REQUIRED_FEATURE = "ai_assistant.view";
11
+ const idParamSchema = z.object({
12
+ id: z.string().trim().min(1, "id must be a non-empty string").max(128, "id exceeds the maximum length of 128 characters")
13
+ });
14
+ const bodySchema = z.object({
15
+ reason: z.string().max(500, "reason must be at most 500 characters").optional()
16
+ }).strict().optional();
17
+ const openApi = {
18
+ tag: "AI Assistant",
19
+ summary: "Pending action (mutation approval gate) cancel",
20
+ methods: {
21
+ POST: {
22
+ operationId: "aiAssistantCancelPendingAction",
23
+ summary: "Cancel an AI pending action without executing the wrapped tool.",
24
+ description: "Flips a pending AI action from `pending` to `cancelled` and emits the `ai.action.cancelled` event. The tool handler is never invoked. Idempotent: a second call on a row already in `cancelled` status returns 200 with the current row without re-emitting the event. Rows whose `expiresAt` is in the past are flipped to `expired` and returned as 409 `expired` so the client can surface the TTL loss instead of silently masking it as a cancellation.",
25
+ responses: [
26
+ {
27
+ status: 200,
28
+ description: "Cancellation complete (or idempotent replay); body includes the serialized pending action with status `cancelled`.",
29
+ mediaType: "application/json"
30
+ }
31
+ ],
32
+ errors: [
33
+ { status: 400, description: "Invalid cancel request body (unknown field, reason exceeds 500 chars, wrong type)." },
34
+ { status: 401, description: "Unauthenticated caller." },
35
+ { status: 403, description: "Caller lacks `ai_assistant.view`." },
36
+ { status: 404, description: "Pending action not found in the caller scope." },
37
+ { status: 409, description: "Pending action is not in `pending` status (already confirmed/failed/executing) or has expired." },
38
+ { status: 500, description: "Unexpected server failure during cancel." }
39
+ ]
40
+ }
41
+ }
42
+ };
43
+ const metadata = {
44
+ POST: { requireAuth: true, requireFeatures: [REQUIRED_FEATURE] }
45
+ };
46
+ function jsonError(status, message, code, extra) {
47
+ return NextResponse.json({ error: message, code, ...extra ?? {} }, { status });
48
+ }
49
+ async function readRequestBody(req) {
50
+ try {
51
+ const text = await req.text();
52
+ if (!text || text.trim().length === 0) return void 0;
53
+ return JSON.parse(text);
54
+ } catch {
55
+ return /* @__PURE__ */ Symbol.for("ai_assistant.cancel.bad_json");
56
+ }
57
+ }
58
+ async function POST(req, context) {
59
+ const auth = await getAuthFromRequest(req);
60
+ if (!auth) {
61
+ return jsonError(401, "Unauthorized", "unauthenticated");
62
+ }
63
+ const rawParams = await context.params;
64
+ const paramResult = idParamSchema.safeParse(rawParams);
65
+ if (!paramResult.success) {
66
+ return jsonError(400, "Invalid pending action id.", "validation_error", {
67
+ issues: paramResult.error.issues
68
+ });
69
+ }
70
+ const pendingActionId = paramResult.data.id;
71
+ const rawBody = await readRequestBody(req);
72
+ if (rawBody === /* @__PURE__ */ Symbol.for("ai_assistant.cancel.bad_json")) {
73
+ return jsonError(400, "Invalid JSON body.", "validation_error");
74
+ }
75
+ const bodyResult = bodySchema.safeParse(rawBody);
76
+ if (!bodyResult.success) {
77
+ return jsonError(400, "Invalid cancel body.", "validation_error", {
78
+ issues: bodyResult.error.issues
79
+ });
80
+ }
81
+ const parsedBody = bodyResult.data ?? {};
82
+ try {
83
+ const container = await createRequestContainer();
84
+ const rbacService = container.resolve("rbacService");
85
+ const acl = await rbacService.loadAcl(auth.sub, {
86
+ tenantId: auth.tenantId,
87
+ organizationId: auth.orgId
88
+ });
89
+ if (!hasRequiredFeatures([REQUIRED_FEATURE], acl.features, acl.isSuperAdmin, rbacService)) {
90
+ return jsonError(403, `Caller lacks required feature "${REQUIRED_FEATURE}".`, "forbidden");
91
+ }
92
+ if (!auth.tenantId) {
93
+ return jsonError(
94
+ 404,
95
+ `No pending action "${pendingActionId}" accessible to the caller.`,
96
+ "pending_action_not_found"
97
+ );
98
+ }
99
+ const em = container.resolve("em");
100
+ const repo = new AiPendingActionRepository(em);
101
+ const row = await repo.getById(pendingActionId, {
102
+ tenantId: auth.tenantId,
103
+ organizationId: auth.orgId ?? null,
104
+ userId: auth.sub
105
+ });
106
+ if (!row) {
107
+ return jsonError(
108
+ 404,
109
+ `No pending action "${pendingActionId}" accessible to the caller.`,
110
+ "pending_action_not_found"
111
+ );
112
+ }
113
+ if (row.status === "cancelled") {
114
+ return NextResponse.json({
115
+ ok: true,
116
+ pendingAction: serializePendingActionForClient(row)
117
+ });
118
+ }
119
+ const statusCheck = checkStatusAndExpiry(row);
120
+ if (!statusCheck.ok) {
121
+ if (statusCheck.code === "expired") {
122
+ const cancelResult2 = await executePendingActionCancel({
123
+ action: row,
124
+ ctx: {
125
+ tenantId: auth.tenantId,
126
+ organizationId: auth.orgId ?? null,
127
+ userId: auth.sub,
128
+ container
129
+ },
130
+ repo
131
+ });
132
+ return jsonError(409, statusCheck.message, "expired", {
133
+ pendingAction: serializePendingActionForClient(cancelResult2.row)
134
+ });
135
+ }
136
+ return jsonError(statusCheck.status, statusCheck.message, statusCheck.code, statusCheck.extra);
137
+ }
138
+ const cancelResult = await executePendingActionCancel({
139
+ action: row,
140
+ ctx: {
141
+ tenantId: auth.tenantId,
142
+ organizationId: auth.orgId ?? null,
143
+ userId: auth.sub,
144
+ container
145
+ },
146
+ reason: parsedBody.reason,
147
+ repo
148
+ });
149
+ if (cancelResult.status === "expired") {
150
+ return jsonError(
151
+ 409,
152
+ "Pending action has expired. The model must re-propose the mutation.",
153
+ "expired",
154
+ { pendingAction: serializePendingActionForClient(cancelResult.row) }
155
+ );
156
+ }
157
+ return NextResponse.json({
158
+ ok: true,
159
+ pendingAction: serializePendingActionForClient(cancelResult.row)
160
+ });
161
+ } catch (error) {
162
+ console.error("[AI Pending Action CANCEL] Failure:", error);
163
+ return jsonError(
164
+ 500,
165
+ error instanceof Error ? error.message : "Failed to cancel pending action.",
166
+ "cancel_internal_error"
167
+ );
168
+ }
169
+ }
170
+ export {
171
+ POST,
172
+ metadata,
173
+ openApi
174
+ };
175
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../src/modules/ai_assistant/api/ai/actions/%5Bid%5D/cancel/route.ts"],
4
+ "sourcesContent": ["import { NextResponse, type NextRequest } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { AiPendingActionRepository } from '../../../../../data/repositories/AiPendingActionRepository'\nimport { hasRequiredFeatures } from '../../../../../lib/auth'\nimport { serializePendingActionForClient } from '../../../../../lib/pending-action-client'\nimport { checkStatusAndExpiry } from '../../../../../lib/pending-action-recheck'\nimport { executePendingActionCancel } from '../../../../../lib/pending-action-cancel'\n\n/**\n * POST `/api/ai/actions/:id/cancel` \u2014 mutation approval gate cancel\n * endpoint (spec \u00A79.4, Step 5.9).\n *\n * Siblings the Step 5.8 confirm route: flips `pending \u2192 cancelled` and\n * emits `ai.action.cancelled`. The tool handler is NEVER invoked.\n *\n * The route re-uses only the `status + expiry + tenant-scope` guards\n * from `pending-action-recheck.ts` \u2014 the agent / tool / attachment /\n * record-version guards are confirm-only. A caller may cancel even when\n * they'd be blocked from confirming; cancelling does not touch data.\n *\n * Idempotency: calling this endpoint twice on an already-`cancelled`\n * row returns 200 with the current row without re-emitting the event.\n */\n\nconst REQUIRED_FEATURE = 'ai_assistant.view'\n\nconst idParamSchema = z.object({\n id: z\n .string()\n .trim()\n .min(1, 'id must be a non-empty string')\n .max(128, 'id exceeds the maximum length of 128 characters'),\n})\n\nconst bodySchema = z\n .object({\n reason: z\n .string()\n .max(500, 'reason must be at most 500 characters')\n .optional(),\n })\n .strict()\n .optional()\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'AI Assistant',\n summary: 'Pending action (mutation approval gate) cancel',\n methods: {\n POST: {\n operationId: 'aiAssistantCancelPendingAction',\n summary: 'Cancel an AI pending action without executing the wrapped tool.',\n description:\n 'Flips a pending AI action from `pending` to `cancelled` and emits the ' +\n '`ai.action.cancelled` event. The tool handler is never invoked. Idempotent: ' +\n 'a second call on a row already in `cancelled` status returns 200 with the ' +\n 'current row without re-emitting the event. Rows whose `expiresAt` is in the ' +\n 'past are flipped to `expired` and returned as 409 `expired` so the client can ' +\n 'surface the TTL loss instead of silently masking it as a cancellation.',\n responses: [\n {\n status: 200,\n description: 'Cancellation complete (or idempotent replay); body includes the serialized pending action with status `cancelled`.',\n mediaType: 'application/json',\n },\n ],\n errors: [\n { status: 400, description: 'Invalid cancel request body (unknown field, reason exceeds 500 chars, wrong type).' },\n { status: 401, description: 'Unauthenticated caller.' },\n { status: 403, description: 'Caller lacks `ai_assistant.view`.' },\n { status: 404, description: 'Pending action not found in the caller scope.' },\n { status: 409, description: 'Pending action is not in `pending` status (already confirmed/failed/executing) or has expired.' },\n { status: 500, description: 'Unexpected server failure during cancel.' },\n ],\n },\n },\n}\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: [REQUIRED_FEATURE] },\n}\n\ninterface RouteContext {\n params: Promise<{ id: string }>\n}\n\nfunction jsonError(\n status: number,\n message: string,\n code: string,\n extra?: Record<string, unknown>,\n): NextResponse {\n return NextResponse.json({ error: message, code, ...(extra ?? {}) }, { status })\n}\n\nasync function readRequestBody(req: NextRequest): Promise<unknown> {\n try {\n const text = await req.text()\n if (!text || text.trim().length === 0) return undefined\n return JSON.parse(text)\n } catch {\n return Symbol.for('ai_assistant.cancel.bad_json')\n }\n}\n\nexport async function POST(req: NextRequest, context: RouteContext): Promise<Response> {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return jsonError(401, 'Unauthorized', 'unauthenticated')\n }\n\n const rawParams = await context.params\n const paramResult = idParamSchema.safeParse(rawParams)\n if (!paramResult.success) {\n return jsonError(400, 'Invalid pending action id.', 'validation_error', {\n issues: paramResult.error.issues,\n })\n }\n const pendingActionId = paramResult.data.id\n\n const rawBody = await readRequestBody(req)\n if (rawBody === Symbol.for('ai_assistant.cancel.bad_json')) {\n return jsonError(400, 'Invalid JSON body.', 'validation_error')\n }\n const bodyResult = bodySchema.safeParse(rawBody)\n if (!bodyResult.success) {\n return jsonError(400, 'Invalid cancel body.', 'validation_error', {\n issues: bodyResult.error.issues,\n })\n }\n const parsedBody = bodyResult.data ?? {}\n\n try {\n const container = await createRequestContainer()\n const rbacService = container.resolve<RbacService>('rbacService')\n const acl = await rbacService.loadAcl(auth.sub, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n\n if (!hasRequiredFeatures([REQUIRED_FEATURE], acl.features, acl.isSuperAdmin, rbacService)) {\n return jsonError(403, `Caller lacks required feature \"${REQUIRED_FEATURE}\".`, 'forbidden')\n }\n\n if (!auth.tenantId) {\n return jsonError(\n 404,\n `No pending action \"${pendingActionId}\" accessible to the caller.`,\n 'pending_action_not_found',\n )\n }\n\n const em = container.resolve<EntityManager>('em')\n const repo = new AiPendingActionRepository(em)\n const row = await repo.getById(pendingActionId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId ?? null,\n userId: auth.sub,\n })\n if (!row) {\n return jsonError(\n 404,\n `No pending action \"${pendingActionId}\" accessible to the caller.`,\n 'pending_action_not_found',\n )\n }\n\n // Idempotent replay: second cancel on an already-cancelled row returns\n // 200 with the current row and does NOT emit a second event.\n if (row.status === 'cancelled') {\n return NextResponse.json({\n ok: true,\n pendingAction: serializePendingActionForClient(row),\n })\n }\n\n const statusCheck = checkStatusAndExpiry(row)\n if (!statusCheck.ok) {\n // Expired short-circuit: flip to `expired` + emit `ai.action.expired`\n // so Step 5.12 does not race to do it. Return 409 so the client\n // surfaces the TTL loss rather than silently cancelling.\n if (statusCheck.code === 'expired') {\n const cancelResult = await executePendingActionCancel({\n action: row,\n ctx: {\n tenantId: auth.tenantId,\n organizationId: auth.orgId ?? null,\n userId: auth.sub,\n container,\n },\n repo,\n })\n return jsonError(409, statusCheck.message, 'expired', {\n pendingAction: serializePendingActionForClient(cancelResult.row),\n })\n }\n return jsonError(statusCheck.status, statusCheck.message, statusCheck.code, statusCheck.extra)\n }\n\n const cancelResult = await executePendingActionCancel({\n action: row,\n ctx: {\n tenantId: auth.tenantId,\n organizationId: auth.orgId ?? null,\n userId: auth.sub,\n container,\n },\n reason: parsedBody.reason,\n repo,\n })\n\n if (cancelResult.status === 'expired') {\n return jsonError(\n 409,\n 'Pending action has expired. The model must re-propose the mutation.',\n 'expired',\n { pendingAction: serializePendingActionForClient(cancelResult.row) },\n )\n }\n\n return NextResponse.json({\n ok: true,\n pendingAction: serializePendingActionForClient(cancelResult.row),\n })\n } catch (error) {\n console.error('[AI Pending Action CANCEL] Failure:', error)\n return jsonError(\n 500,\n error instanceof Error ? error.message : 'Failed to cancel pending action.',\n 'cancel_internal_error',\n )\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["cancelResult"]
7
+ }