@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,179 @@
1
+ /**
2
+ * Pending-action cancel executor (spec §9.4, Step 5.9).
3
+ *
4
+ * Flips an `AiPendingAction` from `pending → cancelled` and emits the
5
+ * typed `ai.action.cancelled` event via `emitAiAssistantEvent`. Unlike
6
+ * {@link executePendingActionConfirm} the tool handler is NEVER invoked —
7
+ * cancellation is a pure state-machine transition plus an event emission.
8
+ * Any other status short-circuits: already-`cancelled` is idempotent (no
9
+ * second emit, same row returned); `confirmed` / `executing` / `failed`
10
+ * are treated as invariant violations and bubble up as 409 via the route.
11
+ *
12
+ * If the row's `expiresAt` is in the past at the time of this call we
13
+ * flip it to `expired` (not `cancelled`) — the Step 5.12 cleanup worker
14
+ * races with this code path and we want a single canonical terminal
15
+ * status for a row that reached its TTL.
16
+ *
17
+ * Idempotency: the caller MUST handle the already-`cancelled` branch
18
+ * BEFORE invoking this helper so the event is emitted exactly once per
19
+ * cancellation.
20
+ */
21
+ import { AiPendingActionRepository } from '../data/repositories/AiPendingActionRepository'
22
+ import type { AiPendingAction } from '../data/entities'
23
+ import { emitAiAssistantEvent } from '../events'
24
+ import type {
25
+ AiActionCancelledPayload,
26
+ AiActionExpiredPayload,
27
+ AiAssistantEventId,
28
+ } from '../events'
29
+ import type { AiPendingActionExecutionResult } from './pending-action-types'
30
+
31
+ export interface PendingActionCancelContext {
32
+ tenantId: string
33
+ organizationId: string | null
34
+ userId: string
35
+ container: import('awilix').AwilixContainer
36
+ }
37
+
38
+ export type CancelEmitter = (
39
+ eventId: Extract<AiAssistantEventId, 'ai.action.cancelled' | 'ai.action.expired'>,
40
+ payload: AiActionCancelledPayload | AiActionExpiredPayload,
41
+ ) => Promise<void>
42
+
43
+ export interface PendingActionCancelInput {
44
+ action: AiPendingAction
45
+ ctx: PendingActionCancelContext
46
+ /** Optional, caller-supplied cancellation reason (already trimmed by the route). */
47
+ reason?: string | null
48
+ repo?: AiPendingActionRepository
49
+ /**
50
+ * Injection seam for unit tests. When omitted, emission is routed via
51
+ * the typed `emitAiAssistantEvent` helper (the normal production path).
52
+ */
53
+ emitEvent?: CancelEmitter
54
+ now?: Date
55
+ }
56
+
57
+ export type PendingActionCancelStatus = 'cancelled' | 'expired'
58
+
59
+ export interface PendingActionCancelResult {
60
+ row: AiPendingAction
61
+ status: PendingActionCancelStatus
62
+ }
63
+
64
+ const CANCELLED_EVENT_ID = 'ai.action.cancelled' as const
65
+ const EXPIRED_EVENT_ID = 'ai.action.expired' as const
66
+
67
+ const defaultCancelEmitter: CancelEmitter = async (eventId, payload) => {
68
+ await emitAiAssistantEvent(eventId, payload as unknown as Record<string, unknown>, {
69
+ persistent: true,
70
+ })
71
+ }
72
+
73
+ async function emitEventSafe(
74
+ emitter: CancelEmitter,
75
+ eventId: Parameters<CancelEmitter>[0],
76
+ payload: Parameters<CancelEmitter>[1],
77
+ ): Promise<void> {
78
+ try {
79
+ await emitter(eventId, payload)
80
+ } catch (error) {
81
+ console.warn(`[AI Pending Action] Failed to emit ${eventId}:`, error)
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Atomic `pending → cancelled` transition with TTL-race safety.
87
+ *
88
+ * - If `action.status === 'cancelled'`, returns the current row WITHOUT
89
+ * emitting a second event. Callers should typically short-circuit on
90
+ * this branch BEFORE invoking the helper (see the Step 5.9 route).
91
+ * - If `action.expiresAt <= now`, the row is flipped to `expired` and the
92
+ * `ai.action.expired` event is emitted via the typed
93
+ * `emitAiAssistantEvent` helper (see `../events`). Returns
94
+ * `{ status: 'expired' }` so the route can translate to a 409
95
+ * `expired` envelope.
96
+ * - Otherwise flips `pending → cancelled`, writes `resolvedAt` + the
97
+ * optional cancellation reason onto `executionResult.error`, and emits
98
+ * `ai.action.cancelled`.
99
+ *
100
+ * Any status other than `pending` / `cancelled` is treated as an
101
+ * invariant violation — the route returns 409 `invalid_status` before
102
+ * reaching this helper. If the caller invokes the helper on such a row
103
+ * it will throw via the repo's state-machine guard.
104
+ */
105
+ export async function executePendingActionCancel(
106
+ input: PendingActionCancelInput,
107
+ ): Promise<PendingActionCancelResult> {
108
+ const { action, ctx, now } = input
109
+ const repo = input.repo ?? new AiPendingActionRepository(ctx.container.resolve('em'))
110
+ const scope = {
111
+ tenantId: ctx.tenantId,
112
+ organizationId: ctx.organizationId,
113
+ userId: ctx.userId,
114
+ }
115
+ const clock = now ?? new Date()
116
+ const emitter: CancelEmitter = input.emitEvent ?? defaultCancelEmitter
117
+
118
+ if (action.status === 'cancelled') {
119
+ return { row: action, status: 'cancelled' }
120
+ }
121
+
122
+ const expiresAt =
123
+ action.expiresAt instanceof Date ? action.expiresAt : new Date(action.expiresAt)
124
+ if (expiresAt.getTime() <= clock.getTime()) {
125
+ const expiredRow = await repo.setStatus(action.id, 'expired', scope, { now: clock })
126
+ const resolvedAtIso =
127
+ (expiredRow.resolvedAt ?? clock).toISOString?.() ?? new Date(clock).toISOString()
128
+ const expiresAtIso =
129
+ (expiresAt ?? clock).toISOString?.() ?? new Date(clock).toISOString()
130
+ const expiredPayload: AiActionExpiredPayload = {
131
+ pendingActionId: expiredRow.id,
132
+ agentId: expiredRow.agentId,
133
+ toolName: expiredRow.toolName,
134
+ status: expiredRow.status,
135
+ tenantId: ctx.tenantId,
136
+ organizationId: ctx.organizationId ?? null,
137
+ userId: ctx.userId,
138
+ resolvedByUserId: null,
139
+ resolvedAt: resolvedAtIso,
140
+ expiresAt: expiresAtIso,
141
+ expiredAt: resolvedAtIso,
142
+ }
143
+ await emitEventSafe(emitter, EXPIRED_EVENT_ID, expiredPayload)
144
+ return { row: expiredRow, status: 'expired' }
145
+ }
146
+
147
+ const trimmedReason = typeof input.reason === 'string' ? input.reason.trim() : ''
148
+ const executionResult: AiPendingActionExecutionResult = {
149
+ error: {
150
+ code: 'cancelled_by_user',
151
+ message: trimmedReason.length > 0 ? trimmedReason : 'Cancelled by user',
152
+ },
153
+ }
154
+
155
+ const cancelledRow = await repo.setStatus(action.id, 'cancelled', scope, {
156
+ resolvedByUserId: ctx.userId,
157
+ executionResult,
158
+ now: clock,
159
+ })
160
+ const cancelledPayload: AiActionCancelledPayload = {
161
+ pendingActionId: cancelledRow.id,
162
+ agentId: cancelledRow.agentId,
163
+ toolName: cancelledRow.toolName,
164
+ status: cancelledRow.status,
165
+ tenantId: ctx.tenantId,
166
+ organizationId: ctx.organizationId ?? null,
167
+ userId: ctx.userId,
168
+ resolvedByUserId: ctx.userId,
169
+ resolvedAt: (cancelledRow.resolvedAt ?? clock).toISOString?.() ?? new Date(clock).toISOString(),
170
+ executionResult,
171
+ ...(trimmedReason.length > 0 ? { reason: trimmedReason } : {}),
172
+ }
173
+ await emitEventSafe(emitter, CANCELLED_EVENT_ID, cancelledPayload)
174
+
175
+ return { row: cancelledRow, status: 'cancelled' }
176
+ }
177
+
178
+ export const PENDING_ACTION_CANCELLED_EVENT_ID = CANCELLED_EVENT_ID
179
+ export const PENDING_ACTION_EXPIRED_EVENT_ID = EXPIRED_EVENT_ID
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Whitelist-based client serializer for {@link AiPendingAction} (Phase 3 WS-C,
3
+ * Step 5.7). The pending-action table carries server-internal fields
4
+ * (`normalizedInput`, `createdByUserId`, `idempotencyKey`) that MUST NOT be
5
+ * exposed to the browser: `normalizedInput` can contain raw tool arguments
6
+ * including PII or credentials; `createdByUserId` leaks an internal principal
7
+ * when the UI never needs it (the `resolvedByUserId` field is the only
8
+ * actor the UI renders); `idempotencyKey` is a deterministic hash that,
9
+ * combined with `(tenantId, organizationId, agentId)`, lets an attacker
10
+ * collide deduplication windows by crafting identical normalized inputs.
11
+ *
12
+ * This helper is shared by the GET /api/ai/actions/:id reconnect route
13
+ * (Step 5.7) and re-used by the confirm (Step 5.8) and cancel (Step 5.9)
14
+ * response bodies so the UI always sees the same shape.
15
+ *
16
+ * The serializer is deliberately WHITELIST-based: adding a new internal
17
+ * column to the entity must never leak to the client as a side-effect of
18
+ * a generic `{...row}` copy. Any new client-visible field MUST be added
19
+ * here explicitly with a matching update to {@link SerializedPendingAction}.
20
+ */
21
+
22
+ import type {
23
+ AiPendingActionExecutionResult,
24
+ AiPendingActionFailedRecord,
25
+ AiPendingActionFieldDiff,
26
+ AiPendingActionQueueMode,
27
+ AiPendingActionRecordDiff,
28
+ AiPendingActionStatus,
29
+ } from './pending-action-types'
30
+
31
+ /**
32
+ * Client-visible subset of {@link AiPendingAction}. Never includes
33
+ * `normalizedInput`, `createdByUserId`, or `idempotencyKey` — see the
34
+ * module-level doc above.
35
+ */
36
+ export interface SerializedPendingAction {
37
+ id: string
38
+ agentId: string
39
+ toolName: string
40
+ status: AiPendingActionStatus
41
+ fieldDiff: AiPendingActionFieldDiff[]
42
+ records: AiPendingActionRecordDiff[] | null
43
+ failedRecords: AiPendingActionFailedRecord[] | null
44
+ sideEffectsSummary: string | null
45
+ attachmentIds: string[]
46
+ targetEntityType: string | null
47
+ targetRecordId: string | null
48
+ recordVersion: string | null
49
+ queueMode: AiPendingActionQueueMode
50
+ executionResult: AiPendingActionExecutionResult | null
51
+ createdAt: string
52
+ expiresAt: string
53
+ resolvedAt: string | null
54
+ resolvedByUserId: string | null
55
+ }
56
+
57
+ /**
58
+ * Minimal row shape the serializer accepts. Defined by name rather than
59
+ * importing the entity class directly so this module stays usable in test
60
+ * contexts that stub the ORM row without loading MikroORM decorators.
61
+ */
62
+ export interface SerializablePendingActionRow {
63
+ id: string
64
+ agentId: string
65
+ toolName: string
66
+ status: AiPendingActionStatus
67
+ fieldDiff?: AiPendingActionFieldDiff[] | null
68
+ records?: AiPendingActionRecordDiff[] | null
69
+ failedRecords?: AiPendingActionFailedRecord[] | null
70
+ sideEffectsSummary?: string | null
71
+ attachmentIds?: string[] | null
72
+ targetEntityType?: string | null
73
+ targetRecordId?: string | null
74
+ recordVersion?: string | null
75
+ queueMode?: AiPendingActionQueueMode | null
76
+ executionResult?: AiPendingActionExecutionResult | null
77
+ createdAt: Date | string
78
+ expiresAt: Date | string
79
+ resolvedAt?: Date | string | null
80
+ resolvedByUserId?: string | null
81
+ }
82
+
83
+ function dateToIso(value: Date | string): string {
84
+ if (value instanceof Date) return value.toISOString()
85
+ if (typeof value === 'string') return value
86
+ return new Date().toISOString()
87
+ }
88
+
89
+ function optionalDateToIso(value: Date | string | null | undefined): string | null {
90
+ if (value == null) return null
91
+ return dateToIso(value)
92
+ }
93
+
94
+ /**
95
+ * Build the client-facing view of a pending action. Strips server-internal
96
+ * fields (`normalizedInput`, `createdByUserId`, `idempotencyKey`) and
97
+ * normalizes Date instances to ISO-8601 strings so the result round-trips
98
+ * through JSON without losing precision.
99
+ */
100
+ export function serializePendingActionForClient(
101
+ row: SerializablePendingActionRow,
102
+ ): SerializedPendingAction {
103
+ return {
104
+ id: row.id,
105
+ agentId: row.agentId,
106
+ toolName: row.toolName,
107
+ status: row.status,
108
+ fieldDiff: Array.isArray(row.fieldDiff) ? row.fieldDiff : [],
109
+ records: Array.isArray(row.records) && row.records.length > 0 ? row.records : null,
110
+ failedRecords:
111
+ Array.isArray(row.failedRecords) && row.failedRecords.length > 0
112
+ ? row.failedRecords
113
+ : null,
114
+ sideEffectsSummary: row.sideEffectsSummary ?? null,
115
+ attachmentIds: Array.isArray(row.attachmentIds) ? row.attachmentIds : [],
116
+ targetEntityType: row.targetEntityType ?? null,
117
+ targetRecordId: row.targetRecordId ?? null,
118
+ recordVersion: row.recordVersion ?? null,
119
+ queueMode: (row.queueMode ?? 'inline') as AiPendingActionQueueMode,
120
+ executionResult: row.executionResult ?? null,
121
+ createdAt: dateToIso(row.createdAt),
122
+ expiresAt: dateToIso(row.expiresAt),
123
+ resolvedAt: optionalDateToIso(row.resolvedAt),
124
+ resolvedByUserId: row.resolvedByUserId ?? null,
125
+ }
126
+ }