@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,451 @@
1
+ import {
2
+ convertToModelMessages,
3
+ generateObject,
4
+ stepCountIs,
5
+ streamObject,
6
+ streamText
7
+ } from "ai";
8
+ import { llmProviderRegistry } from "@open-mercato/shared/lib/ai/llm-provider-registry";
9
+ import { resolveAiAgentTools, AgentPolicyError } from "./agent-tools.js";
10
+ import { resolveEffectiveMutationPolicy } from "./agent-policy.js";
11
+ import { toolRegistry } from "./tool-registry.js";
12
+ import {
13
+ attachmentPartsToUiFileParts,
14
+ resolveAttachmentPartsForAgent,
15
+ summarizeAttachmentPartsForPrompt
16
+ } from "./attachment-parts.js";
17
+ import { AiAgentPromptOverrideRepository } from "../data/repositories/AiAgentPromptOverrideRepository.js";
18
+ import { AiAgentMutationPolicyOverrideRepository } from "../data/repositories/AiAgentMutationPolicyOverrideRepository.js";
19
+ import { composeSystemPromptWithOverride } from "./prompt-override-merge.js";
20
+ import { isKnownMutationPolicy } from "./agent-policy.js";
21
+ import "./llm-bootstrap.js";
22
+ function resolveAgentModel(agent, modelOverride) {
23
+ const provider = llmProviderRegistry.resolveFirstConfigured();
24
+ if (!provider) {
25
+ throw new Error(
26
+ "No LLM provider is configured. Set OPENCODE_PROVIDER plus a matching API key such as ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY, then restart the app. See https://docs.openmercato.com/framework/ai-assistant/overview."
27
+ );
28
+ }
29
+ const apiKey = provider.resolveApiKey();
30
+ if (!apiKey) {
31
+ throw new Error(
32
+ `LLM provider "${provider.id}" is advertised as configured but resolveApiKey() returned empty.`
33
+ );
34
+ }
35
+ const modelId = (modelOverride && modelOverride.trim().length > 0 ? modelOverride : void 0) ?? agent.defaultModel ?? provider.defaultModel;
36
+ const model = provider.createModel({ modelId, apiKey });
37
+ return { model, modelId, providerId: provider.id };
38
+ }
39
+ async function composeSystemPrompt(agent, pageContext, container, tenantId, organizationId) {
40
+ const baseFromOverride = await resolveBaseSystemPromptWithOverride(
41
+ agent,
42
+ container,
43
+ tenantId,
44
+ organizationId
45
+ );
46
+ const resolve = agent.resolvePageContext;
47
+ if (!resolve) return baseFromOverride;
48
+ const entityType = pageContext?.entityType;
49
+ const recordId = pageContext?.recordId;
50
+ if (typeof entityType !== "string" || entityType.length === 0) return baseFromOverride;
51
+ if (typeof recordId !== "string" || recordId.length === 0) return baseFromOverride;
52
+ if (!container) {
53
+ console.warn(
54
+ `[AI Agents] Agent "${agent.id}" declares resolvePageContext but no container was passed to runAiAgentText; skipping hydration.`
55
+ );
56
+ return baseFromOverride;
57
+ }
58
+ const hydrationInput = {
59
+ entityType,
60
+ recordId,
61
+ container,
62
+ tenantId,
63
+ organizationId
64
+ };
65
+ try {
66
+ const hydrated = await resolve(hydrationInput);
67
+ if (typeof hydrated === "string" && hydrated.trim().length > 0) {
68
+ return `${baseFromOverride}
69
+
70
+ ${hydrated}`;
71
+ }
72
+ } catch (error) {
73
+ console.error(
74
+ `[AI Agents] resolvePageContext for agent "${agent.id}" failed; continuing without hydration:`,
75
+ error
76
+ );
77
+ }
78
+ return baseFromOverride;
79
+ }
80
+ async function resolveBaseSystemPromptWithOverride(agent, container, tenantId, organizationId) {
81
+ const base = agent.systemPrompt;
82
+ if (!tenantId || !container) return base;
83
+ let em = null;
84
+ try {
85
+ em = container.resolve("em");
86
+ } catch {
87
+ em = null;
88
+ }
89
+ if (!em) return base;
90
+ try {
91
+ const repo = new AiAgentPromptOverrideRepository(em);
92
+ const latest = await repo.getLatest(agent.id, {
93
+ tenantId,
94
+ organizationId: organizationId ?? null
95
+ });
96
+ if (!latest || !latest.sections || Object.keys(latest.sections).length === 0) {
97
+ return base;
98
+ }
99
+ return composeSystemPromptWithOverride(base, { sections: latest.sections });
100
+ } catch (error) {
101
+ console.warn(
102
+ `[AI Agents] Prompt-override lookup failed for agent "${agent.id}"; falling back to built-in prompt.`,
103
+ error
104
+ );
105
+ return base;
106
+ }
107
+ }
108
+ async function resolveMutationPolicyOverride(agentId, container, tenantId, organizationId) {
109
+ if (!tenantId || !container) return null;
110
+ let em = null;
111
+ try {
112
+ em = container.resolve("em");
113
+ } catch {
114
+ em = null;
115
+ }
116
+ if (!em) return null;
117
+ try {
118
+ const repo = new AiAgentMutationPolicyOverrideRepository(em);
119
+ const row = await repo.get(agentId, { tenantId, organizationId: organizationId ?? null });
120
+ if (!row) return null;
121
+ const raw = row.mutationPolicy;
122
+ if (!isKnownMutationPolicy(raw)) {
123
+ console.warn(
124
+ `[AI Agents] Ignoring corrupt mutationPolicy override row for agent "${agentId}": "${raw}". Falling back to code-declared policy.`
125
+ );
126
+ return null;
127
+ }
128
+ return raw;
129
+ } catch (error) {
130
+ console.warn(
131
+ `[AI Agents] mutationPolicy override lookup failed for agent "${agentId}"; falling back to code-declared policy.`,
132
+ error
133
+ );
134
+ return null;
135
+ }
136
+ }
137
+ function ensureUiMessageShape(messages) {
138
+ return messages.map((message, index) => {
139
+ const raw = message;
140
+ if (Array.isArray(raw.parts) && raw.parts.length > 0) {
141
+ return { ...message, id: raw.id ?? `msg-${index}` };
142
+ }
143
+ const textContent = typeof raw.content === "string" ? raw.content : "";
144
+ return {
145
+ id: raw.id ?? `msg-${index}`,
146
+ role: raw.role ?? "user",
147
+ parts: [{ type: "text", text: textContent }]
148
+ };
149
+ });
150
+ }
151
+ function attachAttachmentsToMessages(messages, parts) {
152
+ if (parts.length === 0) return messages;
153
+ const fileParts = attachmentPartsToUiFileParts(parts);
154
+ if (fileParts.length === 0) return messages;
155
+ const next = messages.slice();
156
+ let lastUserIndex = -1;
157
+ for (let index = next.length - 1; index >= 0; index -= 1) {
158
+ const candidate = next[index];
159
+ if (candidate?.role === "user") {
160
+ lastUserIndex = index;
161
+ break;
162
+ }
163
+ }
164
+ if (lastUserIndex === -1) {
165
+ next.push({
166
+ id: "ai-runtime-attachments",
167
+ role: "user",
168
+ parts: fileParts
169
+ });
170
+ return next;
171
+ }
172
+ const source = next[lastUserIndex];
173
+ const existingParts = Array.isArray(source.parts) ? source.parts : [];
174
+ next[lastUserIndex] = {
175
+ ...next[lastUserIndex],
176
+ parts: [...existingParts, ...fileParts]
177
+ };
178
+ return next;
179
+ }
180
+ function appendAttachmentSummary(systemPrompt, parts) {
181
+ const summary = summarizeAttachmentPartsForPrompt(parts);
182
+ if (!summary) return systemPrompt;
183
+ return `${systemPrompt}
184
+
185
+ ${summary}`;
186
+ }
187
+ function buildRuntimeMutationPolicySection(agent, mutationPolicyOverride) {
188
+ const effective = resolveEffectiveMutationPolicy(
189
+ agent.mutationPolicy ?? null,
190
+ mutationPolicyOverride ?? null,
191
+ agent.id
192
+ );
193
+ const lines = [];
194
+ lines.push("MUTATION POLICY (RUNTIME)");
195
+ lines.push(`Declared agent policy: ${agent.mutationPolicy ?? "read-only"}.`);
196
+ if (mutationPolicyOverride && mutationPolicyOverride !== agent.mutationPolicy) {
197
+ lines.push(`Tenant override active: ${mutationPolicyOverride}.`);
198
+ }
199
+ lines.push(`Effective policy: ${effective}.`);
200
+ const direct = [];
201
+ const gated = [];
202
+ const conditional = [];
203
+ const blocked = [];
204
+ for (const toolName of agent.allowedTools) {
205
+ const tool = toolRegistry.getTool(toolName);
206
+ if (!tool || tool.isMutation !== true) continue;
207
+ if (effective === "read-only") {
208
+ blocked.push(toolName);
209
+ continue;
210
+ }
211
+ if (effective === "confirm-required") {
212
+ gated.push(toolName);
213
+ continue;
214
+ }
215
+ if (typeof tool.isDestructive === "function") {
216
+ conditional.push(toolName);
217
+ } else if (tool.isDestructive === true) {
218
+ gated.push(toolName);
219
+ } else {
220
+ direct.push(toolName);
221
+ }
222
+ }
223
+ if (direct.length === 0 && gated.length === 0 && conditional.length === 0 && blocked.length === 0) {
224
+ return null;
225
+ }
226
+ if (direct.length > 0) {
227
+ lines.push("");
228
+ lines.push(
229
+ `Tools that WILL RUN DIRECTLY (no approval card, no pending action) under the effective policy: ${direct.join(", ")}.`
230
+ );
231
+ lines.push(
232
+ 'When you call any of these and the call returns successfully, the change has ALREADY BEEN APPLIED. Report it in the past tense ("Updated \u2026", "Added \u2026", "Created \u2026"). Do NOT tell the operator the action is "pending your approval" or "awaiting confirmation" \u2014 that would be a false statement under the current policy.'
233
+ );
234
+ }
235
+ if (gated.length > 0) {
236
+ lines.push("");
237
+ lines.push(
238
+ `Tools that REQUIRE APPROVAL under the effective policy: ${gated.join(", ")}.`
239
+ );
240
+ lines.push(
241
+ 'When you call any of these, the dispatcher returns an "awaiting confirmation" envelope and renders an inline approval card. Tell the operator the change is pending their confirmation; do NOT claim it has been applied.'
242
+ );
243
+ }
244
+ if (conditional.length > 0) {
245
+ lines.push("");
246
+ lines.push(
247
+ `Tools whose approval requirement DEPENDS ON THE INPUT under the effective policy: ${conditional.join(", ")}.`
248
+ );
249
+ lines.push(
250
+ 'These multi-operation tools gate ONLY the destructive branches (typically `operation: "delete"` or similar). Read the tool result envelope: if it carries `status: "pending-confirmation"` then the change is pending \u2014 tell the operator it needs their approval. If it carries direct success data, the change has ALREADY BEEN APPLIED \u2014 report it in the past tense. Never assume one branch behaves like another.'
251
+ );
252
+ }
253
+ if (blocked.length > 0) {
254
+ lines.push("");
255
+ lines.push(
256
+ `Tools that are BLOCKED under the effective policy (read-only): ${blocked.join(", ")}.`
257
+ );
258
+ lines.push(
259
+ "Calls to these tools are refused before the handler runs. Do not attempt them; instead direct the operator to the matching backoffice page or to switch the tenant policy if they have permission."
260
+ );
261
+ }
262
+ lines.push("");
263
+ lines.push(
264
+ 'This RUNTIME policy block always wins over any conflicting "approval card" language earlier in the prompt \u2014 the static prompt is written for the most restrictive case but real behavior depends on the per-call policy described here.'
265
+ );
266
+ return lines.join("\n");
267
+ }
268
+ function appendRuntimeMutationPolicy(systemPrompt, agent, mutationPolicyOverride) {
269
+ const block = buildRuntimeMutationPolicySection(agent, mutationPolicyOverride);
270
+ if (!block) return systemPrompt;
271
+ return `${systemPrompt}
272
+
273
+ ${block}`;
274
+ }
275
+ async function runAiAgentText(input) {
276
+ const mutationPolicyOverride = await resolveMutationPolicyOverride(
277
+ input.agentId,
278
+ input.container,
279
+ input.authContext.tenantId,
280
+ input.authContext.organizationId
281
+ );
282
+ const { agent, tools } = await resolveAiAgentTools({
283
+ agentId: input.agentId,
284
+ authContext: input.authContext,
285
+ pageContext: input.pageContext,
286
+ attachmentIds: input.attachmentIds,
287
+ mutationPolicyOverride,
288
+ container: input.container,
289
+ conversationId: input.conversationId ?? null
290
+ });
291
+ const resolvedAttachments = await resolveAttachmentPartsForAgent({
292
+ agent,
293
+ attachmentIds: input.attachmentIds,
294
+ authContext: input.authContext,
295
+ container: input.container
296
+ });
297
+ const baseSystemPrompt = await composeSystemPrompt(
298
+ agent,
299
+ input.pageContext,
300
+ input.container,
301
+ input.authContext.tenantId,
302
+ input.authContext.organizationId
303
+ );
304
+ const systemPrompt = appendRuntimeMutationPolicy(
305
+ appendAttachmentSummary(baseSystemPrompt, resolvedAttachments),
306
+ agent,
307
+ mutationPolicyOverride
308
+ );
309
+ const { model } = resolveAgentModel(agent, input.modelOverride);
310
+ const normalizedMessages = ensureUiMessageShape(input.messages);
311
+ const hydratedMessages = attachAttachmentsToMessages(normalizedMessages, resolvedAttachments);
312
+ const modelMessages = await convertToModelMessages(hydratedMessages);
313
+ const effectiveMaxSteps = typeof agent.maxSteps === "number" && agent.maxSteps > 0 ? agent.maxSteps : 10;
314
+ const stopWhen = stepCountIs(effectiveMaxSteps);
315
+ const streamArgs = {
316
+ model,
317
+ system: systemPrompt,
318
+ messages: modelMessages,
319
+ tools,
320
+ stopWhen
321
+ };
322
+ const result = streamText(streamArgs);
323
+ return result.toUIMessageStreamResponse({
324
+ sendReasoning: true,
325
+ headers: {
326
+ "Cache-Control": "no-cache, no-transform",
327
+ Connection: "keep-alive"
328
+ }
329
+ });
330
+ }
331
+ function normalizeObjectMessages(input) {
332
+ if (typeof input === "string") {
333
+ return [
334
+ {
335
+ id: "user-input",
336
+ role: "user",
337
+ parts: [{ type: "text", text: input }]
338
+ }
339
+ ];
340
+ }
341
+ return input;
342
+ }
343
+ function resolveStructuredOutput(agent, override) {
344
+ if (override) {
345
+ return {
346
+ schemaName: override.schemaName,
347
+ schema: override.schema,
348
+ mode: override.mode ?? "generate"
349
+ };
350
+ }
351
+ const declared = agent.output;
352
+ if (!declared) {
353
+ throw new AgentPolicyError(
354
+ "execution_mode_not_supported",
355
+ `Agent "${agent.id}" does not declare a structured-output schema; pass runAiAgentObject({ output }) or declare agent.output.`
356
+ );
357
+ }
358
+ return {
359
+ schemaName: declared.schemaName,
360
+ schema: declared.schema,
361
+ mode: declared.mode ?? "generate"
362
+ };
363
+ }
364
+ async function runAiAgentObject(input) {
365
+ const mutationPolicyOverride = await resolveMutationPolicyOverride(
366
+ input.agentId,
367
+ input.container,
368
+ input.authContext.tenantId,
369
+ input.authContext.organizationId
370
+ );
371
+ const { agent, tools } = await resolveAiAgentTools({
372
+ agentId: input.agentId,
373
+ authContext: input.authContext,
374
+ pageContext: input.pageContext,
375
+ attachmentIds: input.attachmentIds,
376
+ requestedExecutionMode: "object",
377
+ mutationPolicyOverride,
378
+ container: input.container
379
+ });
380
+ const resolvedOutput = resolveStructuredOutput(agent, input.output);
381
+ const resolvedAttachments = await resolveAttachmentPartsForAgent({
382
+ agent,
383
+ attachmentIds: input.attachmentIds,
384
+ authContext: input.authContext,
385
+ container: input.container
386
+ });
387
+ const baseSystemPrompt = await composeSystemPrompt(
388
+ agent,
389
+ input.pageContext,
390
+ input.container,
391
+ input.authContext.tenantId,
392
+ input.authContext.organizationId
393
+ );
394
+ const systemPrompt = appendRuntimeMutationPolicy(
395
+ appendAttachmentSummary(baseSystemPrompt, resolvedAttachments),
396
+ agent,
397
+ mutationPolicyOverride
398
+ );
399
+ const { model } = resolveAgentModel(agent, input.modelOverride);
400
+ const normalizedMessages = ensureUiMessageShape(normalizeObjectMessages(input.input));
401
+ const hydratedMessages = attachAttachmentsToMessages(
402
+ normalizedMessages,
403
+ resolvedAttachments
404
+ );
405
+ const modelMessages = await convertToModelMessages(hydratedMessages);
406
+ const stopWhen = typeof agent.maxSteps === "number" && agent.maxSteps > 0 ? stepCountIs(agent.maxSteps) : void 0;
407
+ if (resolvedOutput.mode === "stream") {
408
+ const streamArgs = {
409
+ model,
410
+ system: systemPrompt,
411
+ messages: modelMessages,
412
+ schema: resolvedOutput.schema,
413
+ schemaName: resolvedOutput.schemaName
414
+ };
415
+ const result2 = streamObject(streamArgs);
416
+ return {
417
+ mode: "stream",
418
+ object: result2.object,
419
+ partialObjectStream: result2.partialObjectStream,
420
+ textStream: result2.textStream,
421
+ finishReason: result2.finishReason,
422
+ usage: result2.usage
423
+ };
424
+ }
425
+ const generateArgs = {
426
+ model,
427
+ system: systemPrompt,
428
+ messages: modelMessages,
429
+ schema: resolvedOutput.schema,
430
+ schemaName: resolvedOutput.schemaName
431
+ };
432
+ if (stopWhen) {
433
+ ;
434
+ generateArgs.stopWhen = stopWhen;
435
+ }
436
+ void tools;
437
+ const result = await generateObject(generateArgs);
438
+ return {
439
+ mode: "generate",
440
+ object: result.object,
441
+ finishReason: result.finishReason,
442
+ usage: result.usage
443
+ };
444
+ }
445
+ export {
446
+ AgentPolicyError,
447
+ composeSystemPrompt,
448
+ runAiAgentObject,
449
+ runAiAgentText
450
+ };
451
+ //# sourceMappingURL=agent-runtime.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/ai_assistant/lib/agent-runtime.ts"],
4
+ "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { LanguageModel, UIMessage } from 'ai'\nimport {\n convertToModelMessages,\n generateObject,\n stepCountIs,\n streamObject,\n streamText,\n} from 'ai'\nimport type { ZodTypeAny } from 'zod'\nimport { llmProviderRegistry } from '@open-mercato/shared/lib/ai/llm-provider-registry'\nimport type {\n AiAgentDefinition,\n AiAgentPageContextInput,\n AiAgentStructuredOutput,\n} from './ai-agent-definition'\nimport type {\n AiChatRequestContext,\n AiResolvedAttachmentPart,\n} from './attachment-bridge-types'\nimport { resolveAiAgentTools, AgentPolicyError } from './agent-tools'\nimport { resolveEffectiveMutationPolicy } from './agent-policy'\nimport { toolRegistry } from './tool-registry'\nimport {\n attachmentPartsToUiFileParts,\n resolveAttachmentPartsForAgent,\n summarizeAttachmentPartsForPrompt,\n} from './attachment-parts'\nimport { AiAgentPromptOverrideRepository } from '../data/repositories/AiAgentPromptOverrideRepository'\nimport { AiAgentMutationPolicyOverrideRepository } from '../data/repositories/AiAgentMutationPolicyOverrideRepository'\nimport { composeSystemPromptWithOverride } from './prompt-override-merge'\nimport { isKnownMutationPolicy } from './agent-policy'\nimport type { AiAgentMutationPolicy } from './ai-agent-definition'\n\n// Ensure built-in LLM providers are registered. Side-effect import; identical to\n// what `./ai-sdk.ts` consumers already rely on.\nimport './llm-bootstrap'\n\nexport interface AgentRequestPageContext {\n pageId?: string | null\n entityType?: string | null\n recordId?: string | null\n [key: string]: unknown\n}\n\nexport interface RunAiAgentTextInput {\n agentId: string\n messages: UIMessage[]\n attachmentIds?: string[]\n pageContext?: AgentRequestPageContext\n debug?: boolean\n /**\n * Phase 1 exposes the caller-supplied auth context directly on the helper\n * input. Phase 4 may wrap this behind a thinner public API once a global\n * request-context resolver exists. Helpers running inside the HTTP\n * dispatcher receive the same `AiChatRequestContext` used by `checkAgentPolicy`.\n */\n authContext: AiChatRequestContext\n /**\n * Optional per-call model id override that wins over `agent.defaultModel`.\n * The production model-factory extraction lives in Step 5.1; this Step\n * accepts a literal model id string so the Phase 1 runtime already honors\n * `agent.defaultModel` without inventing a new indirection layer.\n */\n modelOverride?: string\n /**\n * Optional DI container used by `resolvePageContext` callbacks. When omitted\n * and the agent declares a `resolvePageContext`, hydration is skipped with a\n * warning (callbacks that need database/DI cannot run safely without one).\n */\n container?: AwilixContainer\n /**\n * Optional stable chat-turn conversation id forwarded from `<AiChat>`.\n * Bridged into the Step 5.6 `prepareMutation` idempotency hash so repeated\n * turns within the same chat collapse onto the same pending action. When\n * omitted, the idempotency hash falls back to `null` which still preserves\n * per-tenant/org uniqueness within the TTL window.\n */\n conversationId?: string | null\n}\n\ninterface ResolvedAgentModel {\n model: LanguageModel\n modelId: string\n providerId: string\n}\n\nfunction resolveAgentModel(\n agent: AiAgentDefinition,\n modelOverride: string | undefined,\n): ResolvedAgentModel {\n const provider = llmProviderRegistry.resolveFirstConfigured()\n if (!provider) {\n throw new Error(\n 'No LLM provider is configured. Set OPENCODE_PROVIDER plus a matching API key such as ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY, then restart the app. See https://docs.openmercato.com/framework/ai-assistant/overview.',\n )\n }\n const apiKey = provider.resolveApiKey()\n if (!apiKey) {\n throw new Error(\n `LLM provider \"${provider.id}\" is advertised as configured but resolveApiKey() returned empty.`,\n )\n }\n const modelId =\n (modelOverride && modelOverride.trim().length > 0 ? modelOverride : undefined) ??\n agent.defaultModel ??\n provider.defaultModel\n const model = provider.createModel({ modelId, apiKey }) as LanguageModel\n return { model, modelId, providerId: provider.id }\n}\n\n/**\n * Composes the effective system prompt for a run. When the agent declares a\n * `resolvePageContext` callback AND the incoming request carries both\n * `entityType` and `recordId`, the callback is invoked and its return value\n * is appended to `agent.systemPrompt`. Throwing callbacks are caught and\n * logged without failing the request \u2014 the spec allows hydration to be\n * best-effort until Step 5.2 wires a stricter contract.\n */\nexport async function composeSystemPrompt(\n agent: AiAgentDefinition,\n pageContext: AgentRequestPageContext | undefined,\n container: AwilixContainer | undefined,\n tenantId: string | null,\n organizationId: string | null,\n): Promise<string> {\n const baseFromOverride = await resolveBaseSystemPromptWithOverride(\n agent,\n container,\n tenantId,\n organizationId,\n )\n const resolve = agent.resolvePageContext\n if (!resolve) return baseFromOverride\n const entityType = pageContext?.entityType\n const recordId = pageContext?.recordId\n if (typeof entityType !== 'string' || entityType.length === 0) return baseFromOverride\n if (typeof recordId !== 'string' || recordId.length === 0) return baseFromOverride\n if (!container) {\n console.warn(\n `[AI Agents] Agent \"${agent.id}\" declares resolvePageContext but no container was passed to runAiAgentText; skipping hydration.`,\n )\n return baseFromOverride\n }\n const hydrationInput: AiAgentPageContextInput = {\n entityType,\n recordId,\n container,\n tenantId,\n organizationId,\n }\n try {\n const hydrated = await resolve(hydrationInput)\n if (typeof hydrated === 'string' && hydrated.trim().length > 0) {\n return `${baseFromOverride}\\n\\n${hydrated}`\n }\n } catch (error) {\n console.error(\n `[AI Agents] resolvePageContext for agent \"${agent.id}\" failed; continuing without hydration:`,\n error,\n )\n }\n return baseFromOverride\n}\n\n/**\n * Fetches the latest tenant-scoped prompt override for `agent` (if any) and\n * layers it onto the built-in `systemPrompt` via the additive merge helper.\n *\n * BC + fail-open: every failure mode \u2014 missing container, missing `em`\n * registration, repository throw, missing migration \u2014 is logged at `warn`\n * and falls back to `agent.systemPrompt`. A chat turn MUST never fail on\n * override lookup (per Step 5.3 spec: \"If the repo call throws, log and\n * fall back to the built-in prompt \u2014 never fail the chat request\").\n */\nasync function resolveBaseSystemPromptWithOverride(\n agent: AiAgentDefinition,\n container: AwilixContainer | undefined,\n tenantId: string | null,\n organizationId: string | null,\n): Promise<string> {\n const base = agent.systemPrompt\n if (!tenantId || !container) return base\n let em: EntityManager | null = null\n try {\n em = container.resolve<EntityManager>('em')\n } catch {\n em = null\n }\n if (!em) return base\n try {\n const repo = new AiAgentPromptOverrideRepository(em)\n const latest = await repo.getLatest(agent.id, {\n tenantId,\n organizationId: organizationId ?? null,\n })\n if (!latest || !latest.sections || Object.keys(latest.sections).length === 0) {\n return base\n }\n return composeSystemPromptWithOverride(base, { sections: latest.sections })\n } catch (error) {\n console.warn(\n `[AI Agents] Prompt-override lookup failed for agent \"${agent.id}\"; falling back to built-in prompt.`,\n error,\n )\n return base\n }\n}\n\n/**\n * Looks up the tenant-scoped `mutationPolicy` override for `agentId` (Step\n * 5.4). Fails SAFE: any repo error, missing container, missing `em`\n * registration, or corrupt enum value returns `null`, which causes the\n * runtime to fall back to the agent's code-declared policy. A chat turn\n * MUST never fail on override lookup.\n */\nasync function resolveMutationPolicyOverride(\n agentId: string,\n container: AwilixContainer | undefined,\n tenantId: string | null,\n organizationId: string | null,\n): Promise<AiAgentMutationPolicy | null> {\n if (!tenantId || !container) return null\n let em: EntityManager | null = null\n try {\n em = container.resolve<EntityManager>('em')\n } catch {\n em = null\n }\n if (!em) return null\n try {\n const repo = new AiAgentMutationPolicyOverrideRepository(em)\n const row = await repo.get(agentId, { tenantId, organizationId: organizationId ?? null })\n if (!row) return null\n const raw = row.mutationPolicy\n if (!isKnownMutationPolicy(raw)) {\n console.warn(\n `[AI Agents] Ignoring corrupt mutationPolicy override row for agent \"${agentId}\": \"${raw}\". Falling back to code-declared policy.`,\n )\n return null\n }\n return raw\n } catch (error) {\n console.warn(\n `[AI Agents] mutationPolicy override lookup failed for agent \"${agentId}\"; falling back to code-declared policy.`,\n error,\n )\n return null\n }\n}\n\n/**\n * Normalizes simple `{ role, content }` chat messages into the AI SDK\n * `UIMessage` shape that `convertToModelMessages` requires. When the\n * incoming message already carries a `parts` array it is left untouched;\n * otherwise a single `TextUIPart` is synthesized from `content`.\n */\nfunction ensureUiMessageShape(messages: UIMessage[]): UIMessage[] {\n return messages.map((message, index) => {\n const raw = message as unknown as { id?: string; role?: string; content?: string; parts?: unknown[] }\n if (Array.isArray(raw.parts) && raw.parts.length > 0) {\n // Already has parts \u2014 only ensure `id` is present\n return { ...message, id: raw.id ?? `msg-${index}` } as UIMessage\n }\n const textContent = typeof raw.content === 'string' ? raw.content : ''\n return {\n id: raw.id ?? `msg-${index}`,\n role: raw.role ?? 'user',\n parts: [{ type: 'text', text: textContent }],\n } as unknown as UIMessage\n })\n}\n\n/**\n * Appends AI SDK v6 `FileUIPart` entries to the last user message in the\n * request so resolved attachment bytes / signed URLs reach the model. Pure\n * helper so chat-mode and object-mode share identical behavior \u2014 any\n * divergence here breaks the Step 3.6 parity contract.\n */\nfunction attachAttachmentsToMessages(\n messages: UIMessage[],\n parts: readonly AiResolvedAttachmentPart[],\n): UIMessage[] {\n if (parts.length === 0) return messages\n const fileParts = attachmentPartsToUiFileParts(parts)\n if (fileParts.length === 0) return messages\n const next = messages.slice()\n let lastUserIndex = -1\n for (let index = next.length - 1; index >= 0; index -= 1) {\n const candidate = next[index] as unknown as { role?: string }\n if (candidate?.role === 'user') {\n lastUserIndex = index\n break\n }\n }\n if (lastUserIndex === -1) {\n next.push({\n id: 'ai-runtime-attachments',\n role: 'user',\n parts: fileParts as unknown as UIMessage['parts'],\n } as unknown as UIMessage)\n return next\n }\n const source = next[lastUserIndex] as unknown as { parts?: unknown[] }\n const existingParts = Array.isArray(source.parts) ? source.parts : []\n next[lastUserIndex] = {\n ...(next[lastUserIndex] as object),\n parts: [...existingParts, ...fileParts],\n } as UIMessage\n return next\n}\n\nfunction appendAttachmentSummary(\n systemPrompt: string,\n parts: readonly AiResolvedAttachmentPart[],\n): string {\n const summary = summarizeAttachmentPartsForPrompt(parts)\n if (!summary) return systemPrompt\n return `${systemPrompt}\\n\\n${summary}`\n}\n\n/**\n * Builds a runtime \"MUTATION POLICY (RUNTIME)\" block describing the\n * EFFECTIVE policy for this turn \u2014 what the model should expect when it\n * calls each whitelisted mutation tool. Generated dynamically because:\n *\n * - the agent's static prompt cannot know which per-tenant override is\n * in force (`destructive-confirm-required` flips most writes to\n * run-direct) and would otherwise mislead the operator with stale\n * \"this requires approval\" copy;\n * - the per-tool `isDestructive` flag determines whether each\n * whitelisted write goes through the approval card or runs inline.\n *\n * Without this block, the model parrots its hardcoded \"always route\n * through the approval card\" prompt language and tells the user \"your\n * change is awaiting approval\" when in fact the dispatcher already\n * applied the change directly. The injected block flips the model to\n * report results accurately (\"applied\", \"pending your approval\", or\n * \"blocked because read-only\") tool-by-tool.\n */\nfunction buildRuntimeMutationPolicySection(\n agent: { id: string; mutationPolicy?: string | null; allowedTools: string[] },\n mutationPolicyOverride: string | null,\n): string | null {\n const effective = resolveEffectiveMutationPolicy(\n (agent.mutationPolicy ?? null) as never,\n (mutationPolicyOverride ?? null) as never,\n agent.id,\n )\n const lines: string[] = []\n lines.push('MUTATION POLICY (RUNTIME)')\n lines.push(`Declared agent policy: ${agent.mutationPolicy ?? 'read-only'}.`)\n if (mutationPolicyOverride && mutationPolicyOverride !== agent.mutationPolicy) {\n lines.push(`Tenant override active: ${mutationPolicyOverride}.`)\n }\n lines.push(`Effective policy: ${effective}.`)\n\n // Bucket the agent's allowlisted tools into \"gated\" / \"direct\" / \"conditional\"\n // / \"blocked\" so the model can phrase outcomes correctly per tool.\n // `conditional` covers tools whose `isDestructive` is a predicate function:\n // their gate-vs-direct decision depends on the per-call input (e.g.\n // `customers.manage_deal_comment` gates only its delete branch under\n // `destructive-confirm-required`).\n const direct: string[] = []\n const gated: string[] = []\n const conditional: string[] = []\n const blocked: string[] = []\n for (const toolName of agent.allowedTools) {\n const tool = toolRegistry.getTool(toolName) as\n | { isMutation?: boolean; isDestructive?: boolean | ((input: unknown) => boolean) }\n | undefined\n if (!tool || tool.isMutation !== true) continue\n if (effective === 'read-only') {\n blocked.push(toolName)\n continue\n }\n if (effective === 'confirm-required') {\n gated.push(toolName)\n continue\n }\n // destructive-confirm-required\n if (typeof tool.isDestructive === 'function') {\n conditional.push(toolName)\n } else if (tool.isDestructive === true) {\n gated.push(toolName)\n } else {\n direct.push(toolName)\n }\n }\n\n if (\n direct.length === 0 &&\n gated.length === 0 &&\n conditional.length === 0 &&\n blocked.length === 0\n ) {\n // Read-only agent with no mutation tools \u2014 no runtime policy block needed.\n return null\n }\n if (direct.length > 0) {\n lines.push('')\n lines.push(\n `Tools that WILL RUN DIRECTLY (no approval card, no pending action) under the effective policy: ${direct.join(', ')}.`,\n )\n lines.push(\n 'When you call any of these and the call returns successfully, the change has ALREADY BEEN APPLIED. Report it in the past tense (\"Updated \u2026\", \"Added \u2026\", \"Created \u2026\"). Do NOT tell the operator the action is \"pending your approval\" or \"awaiting confirmation\" \u2014 that would be a false statement under the current policy.',\n )\n }\n if (gated.length > 0) {\n lines.push('')\n lines.push(\n `Tools that REQUIRE APPROVAL under the effective policy: ${gated.join(', ')}.`,\n )\n lines.push(\n 'When you call any of these, the dispatcher returns an \"awaiting confirmation\" envelope and renders an inline approval card. Tell the operator the change is pending their confirmation; do NOT claim it has been applied.',\n )\n }\n if (conditional.length > 0) {\n lines.push('')\n lines.push(\n `Tools whose approval requirement DEPENDS ON THE INPUT under the effective policy: ${conditional.join(', ')}.`,\n )\n lines.push(\n 'These multi-operation tools gate ONLY the destructive branches (typically `operation: \"delete\"` or similar). Read the tool result envelope: if it carries `status: \"pending-confirmation\"` then the change is pending \u2014 tell the operator it needs their approval. If it carries direct success data, the change has ALREADY BEEN APPLIED \u2014 report it in the past tense. Never assume one branch behaves like another.',\n )\n }\n if (blocked.length > 0) {\n lines.push('')\n lines.push(\n `Tools that are BLOCKED under the effective policy (read-only): ${blocked.join(', ')}.`,\n )\n lines.push(\n 'Calls to these tools are refused before the handler runs. Do not attempt them; instead direct the operator to the matching backoffice page or to switch the tenant policy if they have permission.',\n )\n }\n lines.push('')\n lines.push(\n 'This RUNTIME policy block always wins over any conflicting \"approval card\" language earlier in the prompt \u2014 the static prompt is written for the most restrictive case but real behavior depends on the per-call policy described here.',\n )\n return lines.join('\\n')\n}\n\nfunction appendRuntimeMutationPolicy(\n systemPrompt: string,\n agent: { id: string; mutationPolicy?: string | null; allowedTools: string[] },\n mutationPolicyOverride: string | null,\n): string {\n const block = buildRuntimeMutationPolicySection(agent, mutationPolicyOverride)\n if (!block) return systemPrompt\n return `${systemPrompt}\\n\\n${block}`\n}\n\n/**\n * Server-side helper that runs an Open Mercato agent in chat mode via the\n * Vercel AI SDK and returns a streaming `Response` ready to be emitted from a\n * route handler. Shares the same policy gate and tool resolution path as the\n * HTTP dispatcher \u2014 a caller using this helper can never bypass the agent's\n * `requiredFeatures`, `allowedTools`, `executionMode`, or `mutationPolicy`.\n *\n * Attachment-to-model conversion (Step 3.7): resolved\n * {@link AiResolvedAttachmentPart}s are materialized inline as AI SDK v6\n * `FileUIPart` entries on the last user message (images/PDFs) and as a\n * structured `[ATTACHMENTS]` block appended to the system prompt (text\n * extracts + metadata-only summaries). The existing `attachmentIds`\n * pass-through into `resolveAiAgentTools` is preserved \u2014 Step 3.6 parity\n * invariant #7 still holds.\n */\nexport async function runAiAgentText(input: RunAiAgentTextInput): Promise<Response> {\n const mutationPolicyOverride = await resolveMutationPolicyOverride(\n input.agentId,\n input.container,\n input.authContext.tenantId,\n input.authContext.organizationId,\n )\n const { agent, tools } = await resolveAiAgentTools({\n agentId: input.agentId,\n authContext: input.authContext,\n pageContext: input.pageContext,\n attachmentIds: input.attachmentIds,\n mutationPolicyOverride,\n container: input.container,\n conversationId: input.conversationId ?? null,\n })\n\n const resolvedAttachments = await resolveAttachmentPartsForAgent({\n agent,\n attachmentIds: input.attachmentIds,\n authContext: input.authContext,\n container: input.container,\n })\n\n const baseSystemPrompt = await composeSystemPrompt(\n agent,\n input.pageContext,\n input.container,\n input.authContext.tenantId,\n input.authContext.organizationId,\n )\n const systemPrompt = appendRuntimeMutationPolicy(\n appendAttachmentSummary(baseSystemPrompt, resolvedAttachments),\n agent,\n mutationPolicyOverride,\n )\n\n const { model } = resolveAgentModel(agent, input.modelOverride)\n const normalizedMessages = ensureUiMessageShape(input.messages)\n const hydratedMessages = attachAttachmentsToMessages(normalizedMessages, resolvedAttachments)\n const modelMessages = await convertToModelMessages(hydratedMessages)\n // Default to 10 agentic steps when the agent does not declare maxSteps.\n // Without stopWhen the AI SDK runs a single model call and never executes\n // tool calls, which makes every tool-using query return an empty stream.\n const effectiveMaxSteps = typeof agent.maxSteps === 'number' && agent.maxSteps > 0\n ? agent.maxSteps\n : 10\n const stopWhen = stepCountIs(effectiveMaxSteps)\n\n const streamArgs: Parameters<typeof streamText>[0] = {\n model,\n system: systemPrompt,\n messages: modelMessages,\n tools,\n stopWhen,\n }\n\n const result = streamText(streamArgs)\n return result.toUIMessageStreamResponse({\n sendReasoning: true,\n headers: {\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n },\n })\n}\n\n/**\n * Runtime override for the structured-output schema used by {@link runAiAgentObject}.\n * When the agent itself declares no `output` block, the caller MUST supply this;\n * otherwise the helper rejects with {@link AgentPolicyError} code\n * `execution_mode_not_supported`.\n */\nexport interface RunAiAgentObjectOutputOverride<TSchema = ZodTypeAny> {\n schemaName: string\n schema: TSchema\n /**\n * `'generate'` (default) calls AI SDK `generateObject` and resolves to the\n * parsed object. `'stream'` calls `streamObject` and returns the SDK's\n * streaming handle so callers can consume partial objects / text deltas.\n */\n mode?: 'generate' | 'stream'\n}\n\nexport interface RunAiAgentObjectInput<TSchema = ZodTypeAny> {\n agentId: string\n /**\n * Accepts either a bare user prompt (wrapped as `[{ role: 'user', content }]`)\n * or a prebuilt `UIMessage[]` array \u2014 matches the source spec's\n * `RunAiAgentObjectInput` contract (\u00A71149\u20131160).\n */\n input: string | UIMessage[]\n attachmentIds?: string[]\n pageContext?: AgentRequestPageContext\n /**\n * Same Phase-1 shim as {@link RunAiAgentTextInput.authContext}. Required until\n * a global request-context resolver lands (Phase 4).\n */\n authContext: AiChatRequestContext\n modelOverride?: string\n output?: RunAiAgentObjectOutputOverride<TSchema>\n debug?: boolean\n container?: AwilixContainer\n}\n\nexport type RunAiAgentObjectGenerateResult<TSchema> = {\n mode: 'generate'\n object: TSchema\n finishReason?: string\n usage?: { inputTokens?: number; outputTokens?: number }\n}\n\nexport type RunAiAgentObjectStreamResult<TSchema> = {\n mode: 'stream'\n /** Full parsed object once the stream completes. */\n object: Promise<TSchema>\n /** Async iterator of partial (progressively hydrated) objects. */\n partialObjectStream: AsyncIterable<Partial<TSchema>>\n /** Async iterator of the raw text deltas the model emitted. */\n textStream: AsyncIterable<string>\n finishReason?: Promise<string | undefined>\n usage?: Promise<{ inputTokens?: number; outputTokens?: number } | undefined>\n}\n\nexport type RunAiAgentObjectResult<TSchema> =\n | RunAiAgentObjectGenerateResult<TSchema>\n | RunAiAgentObjectStreamResult<TSchema>\n\nfunction normalizeObjectMessages(input: string | UIMessage[]): UIMessage[] {\n if (typeof input === 'string') {\n return [\n {\n id: 'user-input',\n role: 'user',\n parts: [{ type: 'text', text: input }],\n } as unknown as UIMessage,\n ]\n }\n return input\n}\n\nfunction resolveStructuredOutput<TSchema>(\n agent: AiAgentDefinition,\n override: RunAiAgentObjectOutputOverride<TSchema> | undefined,\n): { schemaName: string; schema: unknown; mode: 'generate' | 'stream' } {\n if (override) {\n return {\n schemaName: override.schemaName,\n schema: override.schema as unknown,\n mode: override.mode ?? 'generate',\n }\n }\n const declared = agent.output as AiAgentStructuredOutput | undefined\n if (!declared) {\n throw new AgentPolicyError(\n 'execution_mode_not_supported',\n `Agent \"${agent.id}\" does not declare a structured-output schema; pass runAiAgentObject({ output }) or declare agent.output.`,\n )\n }\n return {\n schemaName: declared.schemaName,\n schema: declared.schema as unknown,\n mode: declared.mode ?? 'generate',\n }\n}\n\n/**\n * Server-side helper that runs an Open Mercato agent in structured-output mode\n * via the Vercel AI SDK. Shares the same policy gate, tool resolution path,\n * system-prompt composition, and model resolution as {@link runAiAgentText} \u2014\n * object-mode and chat-mode CANNOT diverge.\n *\n * Attachment-to-model conversion (Step 3.7): resolved\n * {@link AiResolvedAttachmentPart}s are materialized inline as AI SDK v6\n * `FileUIPart` entries on the last user message (images/PDFs) and as a\n * structured `[ATTACHMENTS]` block appended to the system prompt (text\n * extracts + metadata-only summaries). Matches {@link runAiAgentText} byte-\n * for-byte so the Step 3.6 parity contract is preserved.\n */\nexport async function runAiAgentObject<TSchema = unknown>(\n input: RunAiAgentObjectInput<TSchema>,\n): Promise<RunAiAgentObjectResult<TSchema>> {\n const mutationPolicyOverride = await resolveMutationPolicyOverride(\n input.agentId,\n input.container,\n input.authContext.tenantId,\n input.authContext.organizationId,\n )\n const { agent, tools } = await resolveAiAgentTools({\n agentId: input.agentId,\n authContext: input.authContext,\n pageContext: input.pageContext,\n attachmentIds: input.attachmentIds,\n requestedExecutionMode: 'object',\n mutationPolicyOverride,\n container: input.container,\n })\n\n const resolvedOutput = resolveStructuredOutput(agent, input.output)\n\n const resolvedAttachments = await resolveAttachmentPartsForAgent({\n agent,\n attachmentIds: input.attachmentIds,\n authContext: input.authContext,\n container: input.container,\n })\n\n const baseSystemPrompt = await composeSystemPrompt(\n agent,\n input.pageContext,\n input.container,\n input.authContext.tenantId,\n input.authContext.organizationId,\n )\n const systemPrompt = appendRuntimeMutationPolicy(\n appendAttachmentSummary(baseSystemPrompt, resolvedAttachments),\n agent,\n mutationPolicyOverride,\n )\n\n const { model } = resolveAgentModel(agent, input.modelOverride)\n const normalizedMessages = ensureUiMessageShape(normalizeObjectMessages(input.input))\n const hydratedMessages = attachAttachmentsToMessages(\n normalizedMessages,\n resolvedAttachments,\n )\n const modelMessages = await convertToModelMessages(hydratedMessages)\n const stopWhen = typeof agent.maxSteps === 'number' && agent.maxSteps > 0\n ? stepCountIs(agent.maxSteps)\n : undefined\n\n if (resolvedOutput.mode === 'stream') {\n const streamArgs: Parameters<typeof streamObject>[0] = {\n model,\n system: systemPrompt,\n messages: modelMessages,\n schema: resolvedOutput.schema as never,\n schemaName: resolvedOutput.schemaName,\n }\n const result = streamObject(streamArgs) as unknown as {\n object: Promise<TSchema>\n partialObjectStream: AsyncIterable<Partial<TSchema>>\n textStream: AsyncIterable<string>\n finishReason?: Promise<string | undefined>\n usage?: Promise<{ inputTokens?: number; outputTokens?: number } | undefined>\n }\n return {\n mode: 'stream',\n object: result.object,\n partialObjectStream: result.partialObjectStream,\n textStream: result.textStream,\n finishReason: result.finishReason,\n usage: result.usage,\n }\n }\n\n const generateArgs: Parameters<typeof generateObject>[0] = {\n model,\n system: systemPrompt,\n messages: modelMessages,\n schema: resolvedOutput.schema as never,\n schemaName: resolvedOutput.schemaName,\n }\n if (stopWhen) {\n // generateObject shares `CallSettings` with generateText; stopWhen is ignored\n // by the typed surface but harmless for providers that respect it. Tools\n // flow through the system prompt only in object mode today \u2014 the whitelist\n // has already been resolved via `resolveAiAgentTools` above, even if we\n // don't hand it to generateObject.\n ;(generateArgs as Record<string, unknown>).stopWhen = stopWhen\n }\n void tools\n\n const result = await generateObject(generateArgs)\n return {\n mode: 'generate',\n object: (result as { object: unknown }).object as TSchema,\n finishReason: (result as { finishReason?: string }).finishReason,\n usage: (result as { usage?: { inputTokens?: number; outputTokens?: number } }).usage,\n }\n}\n\nexport { AgentPolicyError }\n"],
5
+ "mappings": "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",
6
+ "names": ["result"]
7
+ }