@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,396 @@
1
+ import { dynamicTool, type Tool } from 'ai'
2
+ import type { AwilixContainer } from 'awilix'
3
+ import type { ZodType } from 'zod'
4
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
+ import type { AiAgentDefinition, AiAgentMutationPolicy } from './ai-agent-definition'
6
+ import type { AiChatRequestContext, AiUiPart } from './attachment-bridge-types'
7
+ import type { AiToolDefinition, McpToolContext } from './types'
8
+ import { loadAgentRegistry } from './agent-registry'
9
+ import {
10
+ checkAgentPolicy,
11
+ resolveEffectiveMutationPolicy,
12
+ type AgentPolicyDenyCode,
13
+ } from './agent-policy'
14
+ import { toolRegistry } from './tool-registry'
15
+ import { toSafeZodSchema } from './schema-utils'
16
+ import { prepareMutation } from './prepare-mutation'
17
+
18
+ /**
19
+ * Error thrown by `resolveAiAgentTools` (and downstream `runAiAgentText`) when
20
+ * the agent-level policy check denies a request. Carries the structured deny
21
+ * code so HTTP dispatchers can map it to a stable status and JSON body.
22
+ */
23
+ export class AgentPolicyError extends Error {
24
+ readonly code: AgentPolicyDenyCode
25
+
26
+ constructor(code: AgentPolicyDenyCode, message: string) {
27
+ super(message)
28
+ this.name = 'AgentPolicyError'
29
+ this.code = code
30
+ }
31
+ }
32
+
33
+ export interface ResolveAiAgentToolsInput {
34
+ agentId: string
35
+ authContext: AiChatRequestContext
36
+ pageContext?: Record<string, unknown>
37
+ attachmentIds?: string[]
38
+ /**
39
+ * Execution mode the caller intends to run the agent in. Defaults to
40
+ * `'chat'` to preserve the existing chat dispatcher contract. Object-mode
41
+ * callers (see `runAiAgentObject`) MUST pass `'object'` so the policy gate
42
+ * can reject chat-only agents early with `execution_mode_not_supported`.
43
+ */
44
+ requestedExecutionMode?: 'chat' | 'object'
45
+ /**
46
+ * Optional tenant-scoped mutation-policy DOWNGRADE. When supplied, the
47
+ * effective policy evaluated by `checkAgentPolicy` is the most restrictive
48
+ * of `{ agent.mutationPolicy, mutationPolicyOverride }`. Escalation is
49
+ * rejected at the route layer; this helper trusts callers to pass only
50
+ * values produced by the override repository.
51
+ */
52
+ mutationPolicyOverride?: AiAgentMutationPolicy | null
53
+ /**
54
+ * DI container used by the `prepareMutation` tool-call wrapper (Step 5.6).
55
+ * When present AND the agent's effective mutation policy is non-read-only,
56
+ * `isMutation: true` tools are intercepted: the runtime creates an
57
+ * `AiPendingAction` row and enqueues a `mutation-preview-card` UI part in
58
+ * the returned {@link ResolvedAgentTools.uiPartQueue} instead of running the
59
+ * tool's handler. When absent, mutation tools degrade-gracefully to the
60
+ * pre-5.6 pass-through adapter — existing read-only agents are unaffected.
61
+ */
62
+ container?: AwilixContainer
63
+ /**
64
+ * Optional chat-turn correlation id used when hashing the
65
+ * `AiPendingAction.idempotencyKey` so retries of the same mutation collapse
66
+ * to a single row. The chat dispatcher supplies the OpenCode / AI SDK turn
67
+ * id here; when omitted the hash falls back to `null` which still preserves
68
+ * per-tenant/org uniqueness within the TTL window.
69
+ */
70
+ conversationId?: string | null
71
+ }
72
+
73
+ /**
74
+ * Queue of UI parts the mutation-preview wrapper accumulates during a turn.
75
+ * The chat/object dispatcher flushes these on the next emission boundary
76
+ * (spec §9 allows either direct streaming or this queue pattern — we ship the
77
+ * queue in Step 5.6 and the chat dispatcher will drain it in Step 5.10 when
78
+ * the `mutation-preview-card` component registers). BC: callers that ignore
79
+ * the field are unaffected.
80
+ */
81
+ export interface AiUiPartQueue {
82
+ /** Pushed by the mutation wrapper; drained by the dispatcher in order. */
83
+ enqueue: (part: AiUiPart) => void
84
+ drain: () => AiUiPart[]
85
+ size: () => number
86
+ }
87
+
88
+ function createAiUiPartQueue(): AiUiPartQueue {
89
+ const buffer: AiUiPart[] = []
90
+ return {
91
+ enqueue: (part) => {
92
+ buffer.push(part)
93
+ },
94
+ drain: () => {
95
+ const snapshot = buffer.slice()
96
+ buffer.length = 0
97
+ return snapshot
98
+ },
99
+ size: () => buffer.length,
100
+ }
101
+ }
102
+
103
+ export interface ResolvedAgentTools {
104
+ agent: AiAgentDefinition
105
+ tools: Record<string, Tool<unknown, unknown>>
106
+ /**
107
+ * Per-request UI-part queue the chat dispatcher drains between streamText
108
+ * chunks (Step 5.10 contract). Always present; empty when no mutation-tool
109
+ * calls fire during the turn.
110
+ */
111
+ uiPartQueue: AiUiPartQueue
112
+ }
113
+
114
+ function toPolicyAuthContext(ctx: AiChatRequestContext): {
115
+ userFeatures: string[]
116
+ isSuperAdmin: boolean
117
+ } {
118
+ return {
119
+ userFeatures: ctx.features,
120
+ isSuperAdmin: ctx.isSuperAdmin,
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Sanitize a dotted tool name (e.g. `search.hybrid_search`) into a format
126
+ * accepted by all major LLM providers. OpenAI requires tool names to match
127
+ * `^[a-zA-Z0-9_-]+$`; dots are replaced with double underscores (`__`).
128
+ * Anthropic and Google accept both formats, so this is safe across providers.
129
+ */
130
+ function sanitizeToolNameForModel(name: string): string {
131
+ return name.replace(/\./g, '__')
132
+ }
133
+
134
+ function formatToolResult(result: unknown): string {
135
+ if (result === null || result === undefined) return 'No result returned'
136
+ if (typeof result === 'string') return result
137
+ if (typeof result === 'number' || typeof result === 'boolean') return String(result)
138
+ try {
139
+ return JSON.stringify(result, null, 2)
140
+ } catch {
141
+ return String(result)
142
+ }
143
+ }
144
+
145
+ function buildToolHandlerContext(
146
+ ctx: AiChatRequestContext,
147
+ container?: AwilixContainer,
148
+ tool?: AiToolDefinition,
149
+ ): McpToolContext {
150
+ return {
151
+ tenantId: ctx.tenantId,
152
+ organizationId: ctx.organizationId,
153
+ userId: ctx.userId,
154
+ container: (container ?? undefined) as unknown as McpToolContext['container'],
155
+ userFeatures: ctx.features,
156
+ isSuperAdmin: ctx.isSuperAdmin,
157
+ ...(tool ? { tool } : {}),
158
+ }
159
+ }
160
+
161
+ interface MutationInterceptorOptions {
162
+ agent: AiAgentDefinition
163
+ tool: AiToolDefinition
164
+ container: AwilixContainer
165
+ ctx: AiChatRequestContext
166
+ mutationPolicyOverride: AiAgentMutationPolicy | null
167
+ conversationId: string | null
168
+ uiPartQueue: AiUiPartQueue
169
+ }
170
+
171
+ function formatPendingActionToolResult(
172
+ agent: AiAgentDefinition,
173
+ tool: AiToolDefinition,
174
+ pendingActionId: string,
175
+ expiresAt: Date,
176
+ ): string {
177
+ return formatToolResult({
178
+ status: 'pending-confirmation',
179
+ agentId: agent.id,
180
+ toolName: tool.name,
181
+ pendingActionId,
182
+ expiresAt: expiresAt.toISOString(),
183
+ message: `Awaiting user confirmation for mutation "${tool.name}". The action will NOT run until the user approves it.`,
184
+ })
185
+ }
186
+
187
+ /**
188
+ * Per-call gating decision for the destructive-confirm-required policy.
189
+ * Honors a static boolean OR a predicate evaluated against the actual
190
+ * tool-call args, so a multi-operation tool (e.g.
191
+ * `customers.manage_deal_comment` with `operation: 'create' | 'update'
192
+ * | 'delete'`) can gate only its destructive branches without being
193
+ * split into multiple tools.
194
+ */
195
+ function resolveIsDestructive(
196
+ isDestructive: boolean | ((input: unknown) => boolean) | undefined,
197
+ args: unknown,
198
+ ): boolean {
199
+ if (typeof isDestructive === 'function') {
200
+ try {
201
+ return isDestructive(args) === true
202
+ } catch {
203
+ // If the predicate throws (e.g. unexpected input shape), default to
204
+ // gating — fail-safe for destructive policy.
205
+ return true
206
+ }
207
+ }
208
+ return isDestructive === true
209
+ }
210
+
211
+ function adaptToolToAiSdk(
212
+ tool: AiToolDefinition,
213
+ ctx: AiChatRequestContext,
214
+ mutation: MutationInterceptorOptions | null,
215
+ container?: AwilixContainer,
216
+ effectiveMutationPolicy?: 'read-only' | 'confirm-required' | 'destructive-confirm-required',
217
+ ): Tool<unknown, unknown> {
218
+ const safeSchema = toSafeZodSchema(tool.inputSchema as ZodType)
219
+ const handlerContext = buildToolHandlerContext(ctx, container, tool)
220
+ return dynamicTool({
221
+ description: tool.description,
222
+ inputSchema: safeSchema,
223
+ execute: async (args: unknown) => {
224
+ // Per-call gating decision. Under `destructive-confirm-required`,
225
+ // tools with a predicate `isDestructive(args)` may flip per call —
226
+ // e.g. comment delete gates while comment create runs direct.
227
+ const requiresApprovalNow = (() => {
228
+ if (!mutation) return false
229
+ if (effectiveMutationPolicy === 'confirm-required') return true
230
+ if (effectiveMutationPolicy === 'destructive-confirm-required') {
231
+ return resolveIsDestructive(mutation.tool.isDestructive, args)
232
+ }
233
+ return false
234
+ })()
235
+ if (mutation && requiresApprovalNow) {
236
+ try {
237
+ const toolCallArgs =
238
+ args && typeof args === 'object' && !Array.isArray(args)
239
+ ? { ...(args as Record<string, unknown>) }
240
+ : {}
241
+ const { uiPart, pendingAction } = await prepareMutation(
242
+ {
243
+ agent: mutation.agent,
244
+ tool: mutation.tool,
245
+ toolCallArgs,
246
+ conversationId: mutation.conversationId,
247
+ mutationPolicyOverride: mutation.mutationPolicyOverride,
248
+ },
249
+ {
250
+ tenantId: mutation.ctx.tenantId,
251
+ organizationId: mutation.ctx.organizationId,
252
+ userId: mutation.ctx.userId,
253
+ features: mutation.ctx.features,
254
+ isSuperAdmin: mutation.ctx.isSuperAdmin,
255
+ container: mutation.container,
256
+ },
257
+ )
258
+ mutation.uiPartQueue.enqueue(uiPart)
259
+ return formatPendingActionToolResult(
260
+ mutation.agent,
261
+ mutation.tool,
262
+ pendingAction.id,
263
+ pendingAction.expiresAt,
264
+ )
265
+ } catch (error) {
266
+ const message = error instanceof Error ? error.message : String(error)
267
+ throw new Error(
268
+ `Tool "${tool.name}" could not be prepared for confirmation: ${message}`,
269
+ )
270
+ }
271
+ }
272
+ try {
273
+ // Create a fresh container per tool call so the EM is never stale.
274
+ const freshContainer = await createRequestContainer()
275
+ const freshContext: McpToolContext = {
276
+ ...handlerContext,
277
+ container: freshContainer as unknown as McpToolContext['container'],
278
+ }
279
+ const { executeTool } = await import('./tool-executor')
280
+ const execResult = await executeTool(tool.name, args, freshContext)
281
+ if (!execResult.success) {
282
+ throw new Error(execResult.error || 'Tool execution failed')
283
+ }
284
+ return formatToolResult(execResult.result)
285
+ } catch (error) {
286
+ const message = error instanceof Error ? error.message : String(error)
287
+ throw new Error(`Tool "${tool.name}" failed: ${message}`)
288
+ }
289
+ },
290
+ })
291
+ }
292
+
293
+ /**
294
+ * Resolves the agent's whitelisted tools into an AI SDK `tools` map, enforcing
295
+ * the same policy gate as the HTTP dispatcher. Throws {@link AgentPolicyError}
296
+ * on agent-level deny; tool-level denies are skipped with a `console.warn`
297
+ * because the agent author whitelisted a tool the caller is not currently
298
+ * permitted to execute (deterministic non-failure — the remaining tools still
299
+ * reach the model).
300
+ */
301
+ export async function resolveAiAgentTools(
302
+ input: ResolveAiAgentToolsInput,
303
+ ): Promise<ResolvedAgentTools> {
304
+ await loadAgentRegistry()
305
+
306
+ const policyAuth = toPolicyAuthContext(input.authContext)
307
+ const mutationPolicyOverride = input.mutationPolicyOverride ?? null
308
+ const agentDecision = checkAgentPolicy({
309
+ agentId: input.agentId,
310
+ authContext: policyAuth,
311
+ requestedExecutionMode: input.requestedExecutionMode ?? 'chat',
312
+ mutationPolicyOverride,
313
+ })
314
+ if (!agentDecision.ok) {
315
+ throw new AgentPolicyError(agentDecision.code, agentDecision.message)
316
+ }
317
+
318
+ const { agent } = agentDecision
319
+ const tools: Record<string, Tool<unknown, unknown>> = {}
320
+ const uiPartQueue = createAiUiPartQueue()
321
+ const effectiveMutationPolicy = resolveEffectiveMutationPolicy(
322
+ agent.mutationPolicy,
323
+ mutationPolicyOverride,
324
+ agent.id,
325
+ )
326
+ const canInterceptMutations =
327
+ effectiveMutationPolicy !== 'read-only' && typeof input.container !== 'undefined'
328
+
329
+ for (const toolName of agent.allowedTools) {
330
+ const toolDecision = checkAgentPolicy({
331
+ agentId: input.agentId,
332
+ authContext: policyAuth,
333
+ toolName,
334
+ mutationPolicyOverride,
335
+ })
336
+ if (!toolDecision.ok) {
337
+ console.warn(
338
+ `[AI Agents] Skipping tool "${toolName}" for agent "${agent.id}": ${toolDecision.message}`,
339
+ )
340
+ continue
341
+ }
342
+
343
+ const record = (toolDecision.tool ?? toolRegistry.getTool(toolName)) as
344
+ | AiToolDefinition
345
+ | undefined
346
+ if (!record) {
347
+ console.warn(
348
+ `[AI Agents] Tool "${toolName}" vanished from registry between policy checks; skipping.`,
349
+ )
350
+ continue
351
+ }
352
+
353
+ try {
354
+ // For any mutation tool whose policy isn't read-only, prepare the
355
+ // interceptor options once. The actual gate-vs-run-direct decision
356
+ // happens at call time inside `adaptToolToAiSdk` because under
357
+ // `destructive-confirm-required` `isDestructive` may be a predicate
358
+ // evaluated against the per-call args (e.g. a multi-operation
359
+ // tool with `operation: 'create' | 'update' | 'delete'` gates only
360
+ // the destructive branch).
361
+ const mutationOptions: MutationInterceptorOptions | null =
362
+ record.isMutation === true && canInterceptMutations && input.container
363
+ ? {
364
+ agent,
365
+ tool: record,
366
+ container: input.container,
367
+ ctx: input.authContext,
368
+ mutationPolicyOverride,
369
+ conversationId: input.conversationId ?? null,
370
+ uiPartQueue,
371
+ }
372
+ : null
373
+ // Sanitize tool name for model API compatibility: OpenAI requires
374
+ // names matching ^[a-zA-Z0-9_-]+$ (no dots). Replace dots with
375
+ // double underscores so `search.hybrid_search` becomes
376
+ // `search__hybrid_search`. The AI SDK uses the record key as the
377
+ // tool name sent to the model; the original dotted name stays on
378
+ // the `tool` object for logging and prepareMutation hashing.
379
+ const modelSafeToolName = sanitizeToolNameForModel(toolName)
380
+ tools[modelSafeToolName] = adaptToolToAiSdk(
381
+ record,
382
+ input.authContext,
383
+ mutationOptions,
384
+ input.container,
385
+ effectiveMutationPolicy,
386
+ )
387
+ } catch (error) {
388
+ console.error(
389
+ `[AI Agents] Failed to adapt tool "${toolName}" for agent "${agent.id}":`,
390
+ error,
391
+ )
392
+ }
393
+ }
394
+
395
+ return { agent, tools, uiPartQueue }
396
+ }
@@ -0,0 +1,51 @@
1
+ import { DefaultChatTransport, type ChatTransport, type UIMessage } from 'ai'
2
+
3
+ /**
4
+ * Default dispatcher URL. Mirrors the module-id-prefixed layout emitted by the
5
+ * app router — the spec shorthand `/api/ai/chat` appears in the source spec
6
+ * but the generator maps it to `/api/ai_assistant/ai/chat`. Downstream
7
+ * consumers should import this helper rather than hardcoding the literal.
8
+ */
9
+ const DEFAULT_ENDPOINT = '/api/ai_assistant/ai/chat'
10
+
11
+ export interface CreateAiAgentTransportInput {
12
+ agentId: string
13
+ endpoint?: string
14
+ body?: Record<string, unknown>
15
+ debug?: boolean
16
+ }
17
+
18
+ function buildEndpointWithAgentQuery(endpoint: string, agentId: string): string {
19
+ if (!agentId) return endpoint
20
+ const separator = endpoint.includes('?') ? '&' : '?'
21
+ return `${endpoint}${separator}agent=${encodeURIComponent(agentId)}`
22
+ }
23
+
24
+ /**
25
+ * Thin wrapper around `DefaultChatTransport` that binds the agent id as a
26
+ * query parameter and merges any agent-specific body fields into every
27
+ * outbound request. Returned value conforms to the AI SDK's `ChatTransport`
28
+ * contract so consumers can plug it directly into `useChat({ transport })`.
29
+ *
30
+ * TODO: when the AI SDK standardizes agent-binding as a first-class input,
31
+ * this helper can collapse into a one-liner. Until then it owns the
32
+ * endpoint-URL convention so UI callers do not hardcode dispatcher paths.
33
+ */
34
+ export function createAiAgentTransport<UI_MESSAGE extends UIMessage = UIMessage>(
35
+ input: CreateAiAgentTransportInput,
36
+ ): ChatTransport<UI_MESSAGE> {
37
+ const endpoint = buildEndpointWithAgentQuery(
38
+ input.endpoint && input.endpoint.length > 0 ? input.endpoint : DEFAULT_ENDPOINT,
39
+ input.agentId,
40
+ )
41
+
42
+ const extraBody: Record<string, unknown> = { ...(input.body ?? {}) }
43
+ if (typeof input.debug === 'boolean') {
44
+ extraBody.debug = input.debug
45
+ }
46
+
47
+ return new DefaultChatTransport<UI_MESSAGE>({
48
+ api: endpoint,
49
+ body: extraBody,
50
+ })
51
+ }
@@ -0,0 +1,86 @@
1
+ import type { AwilixContainer } from 'awilix'
2
+ import type { ZodTypeAny } from 'zod'
3
+
4
+ export type AiAgentExecutionMode = 'chat' | 'object'
5
+
6
+ export type AiAgentMutationPolicy =
7
+ | 'read-only'
8
+ | 'confirm-required'
9
+ | 'destructive-confirm-required'
10
+
11
+ export type AiAgentAcceptedMediaType = 'image' | 'pdf' | 'file'
12
+
13
+ export type AiAgentDataOperation = 'read' | 'search' | 'aggregate'
14
+
15
+ export interface AiAgentPageContextInput {
16
+ entityType: string
17
+ recordId: string
18
+ container: AwilixContainer
19
+ tenantId: string | null
20
+ organizationId: string | null
21
+ }
22
+
23
+ export interface AiAgentStructuredOutput<TSchema = ZodTypeAny> {
24
+ schemaName: string
25
+ schema: TSchema
26
+ mode?: 'generate' | 'stream'
27
+ }
28
+
29
+ export interface AiAgentDataCapabilities {
30
+ entities?: string[]
31
+ operations?: AiAgentDataOperation[]
32
+ searchableFields?: string[]
33
+ }
34
+
35
+ export interface AiAgentSuggestion {
36
+ label: string
37
+ prompt: string
38
+ }
39
+
40
+ export interface AiAgentDefinition {
41
+ id: string
42
+ moduleId: string
43
+ label: string
44
+ description: string
45
+ systemPrompt: string
46
+ allowedTools: string[]
47
+ suggestions?: AiAgentSuggestion[]
48
+ executionMode?: AiAgentExecutionMode
49
+ defaultModel?: string
50
+ acceptedMediaTypes?: AiAgentAcceptedMediaType[]
51
+ requiredFeatures?: string[]
52
+ uiParts?: string[]
53
+ readOnly?: boolean
54
+ mutationPolicy?: AiAgentMutationPolicy
55
+ maxSteps?: number
56
+ output?: AiAgentStructuredOutput
57
+ resolvePageContext?: (ctx: AiAgentPageContextInput) => Promise<string | null>
58
+ keywords?: string[]
59
+ domain?: string
60
+ dataCapabilities?: AiAgentDataCapabilities
61
+ }
62
+
63
+ export interface AiAgentExtension {
64
+ targetAgentId: string
65
+ replaceAllowedTools?: string[]
66
+ deleteAllowedTools?: string[]
67
+ appendAllowedTools?: string[]
68
+ replaceSystemPrompt?: string
69
+ appendSystemPrompt?: string
70
+ replaceSuggestions?: AiAgentSuggestion[]
71
+ deleteSuggestions?: string[]
72
+ appendSuggestions?: AiAgentSuggestion[]
73
+ /**
74
+ * @deprecated Use `appendSuggestions` for new code. Preserved as the
75
+ * original append-only field for backward compatibility.
76
+ */
77
+ suggestions?: AiAgentSuggestion[]
78
+ }
79
+
80
+ export function defineAiAgent(definition: AiAgentDefinition): AiAgentDefinition {
81
+ return definition
82
+ }
83
+
84
+ export function defineAiAgentExtension(extension: AiAgentExtension): AiAgentExtension {
85
+ return extension
86
+ }
@@ -0,0 +1,18 @@
1
+ declare module '@/.mercato/generated/ai-agents.generated' {
2
+ export const aiAgentConfigEntries: Array<{
3
+ moduleId: string
4
+ agents: unknown[]
5
+ overrides?: Record<string, unknown>
6
+ extensions?: unknown[]
7
+ }>
8
+ export const allAiAgents: unknown[]
9
+ export const allAiAgentExtensions: unknown[]
10
+ export const aiAgentExtensionEntries: Array<{
11
+ moduleId: string
12
+ extensions: unknown[]
13
+ }>
14
+ export const aiAgentOverrideEntries: Array<{
15
+ moduleId: string
16
+ overrides: Record<string, unknown>
17
+ }>
18
+ }