@amodalai/runtime 0.1.26 → 0.2.0

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 (347) hide show
  1. package/dist/src/__fixtures__/README.md +84 -0
  2. package/dist/src/__fixtures__/smoke-agent/amodal.json +11 -0
  3. package/dist/src/__fixtures__/smoke-agent/automations/test-auto.md +5 -0
  4. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/access.json +11 -0
  5. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/spec.json +4 -0
  6. package/dist/src/__fixtures__/smoke-agent/connections/mock-api/surface.md +9 -0
  7. package/dist/src/__fixtures__/smoke-agent/connections/mock-mcp/access.json +3 -0
  8. package/dist/src/__fixtures__/smoke-agent/connections/mock-mcp/spec.json +8 -0
  9. package/dist/src/__fixtures__/smoke-agent/evals/basic-eval.md +12 -0
  10. package/dist/src/__fixtures__/smoke-agent/knowledge/test-knowledge.md +3 -0
  11. package/dist/src/__fixtures__/smoke-agent/skills/test-skill/SKILL.md +11 -0
  12. package/dist/src/__fixtures__/smoke-agent/stores/test-items.json +11 -0
  13. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.d.ts +18 -0
  14. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.js +22 -0
  15. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/handler.js.map +1 -0
  16. package/dist/src/__fixtures__/smoke-agent/tools/echo_tool/tool.json +17 -0
  17. package/dist/src/__fixtures__/smoke.test.js +718 -0
  18. package/dist/src/__fixtures__/smoke.test.js.map +1 -0
  19. package/dist/src/__tests__/test-providers.d.ts +40 -0
  20. package/dist/src/__tests__/test-providers.js +61 -0
  21. package/dist/src/__tests__/test-providers.js.map +1 -0
  22. package/dist/src/agent/local-server.d.ts +3 -3
  23. package/dist/src/agent/local-server.js +213 -122
  24. package/dist/src/agent/local-server.js.map +1 -1
  25. package/dist/src/agent/loop-types.d.ts +175 -0
  26. package/dist/src/agent/loop-types.js +20 -0
  27. package/dist/src/agent/loop-types.js.map +1 -0
  28. package/dist/src/agent/loop.d.ts +31 -0
  29. package/dist/src/agent/loop.js +139 -0
  30. package/dist/src/agent/loop.js.map +1 -0
  31. package/dist/src/agent/loop.test.js +1030 -0
  32. package/dist/src/agent/loop.test.js.map +1 -0
  33. package/dist/src/agent/mcp-config.d.ts +28 -0
  34. package/dist/src/agent/mcp-config.js +57 -0
  35. package/dist/src/agent/mcp-config.js.map +1 -0
  36. package/dist/src/agent/page-builder.js +6 -1
  37. package/dist/src/agent/page-builder.js.map +1 -1
  38. package/dist/src/agent/proactive/proactive-runner.d.ts +24 -8
  39. package/dist/src/agent/proactive/proactive-runner.js +30 -32
  40. package/dist/src/agent/proactive/proactive-runner.js.map +1 -1
  41. package/dist/src/agent/proactive/proactive-runner.test.d.ts +1 -1
  42. package/dist/src/agent/proactive/proactive-runner.test.js +75 -87
  43. package/dist/src/agent/proactive/proactive-runner.test.js.map +1 -1
  44. package/dist/src/agent/routes/admin-chat.d.ts +15 -3
  45. package/dist/src/agent/routes/admin-chat.js +63 -18
  46. package/dist/src/agent/routes/admin-chat.js.map +1 -1
  47. package/dist/src/agent/routes/automations.js +5 -6
  48. package/dist/src/agent/routes/automations.js.map +1 -1
  49. package/dist/src/agent/routes/evals.d.ts +3 -2
  50. package/dist/src/agent/routes/evals.js +25 -12
  51. package/dist/src/agent/routes/evals.js.map +1 -1
  52. package/dist/src/agent/routes/files.js +7 -9
  53. package/dist/src/agent/routes/files.js.map +1 -1
  54. package/dist/src/agent/routes/inspect.d.ts +6 -2
  55. package/dist/src/agent/routes/inspect.js +31 -17
  56. package/dist/src/agent/routes/inspect.js.map +1 -1
  57. package/dist/src/agent/routes/inspect.test.js +18 -42
  58. package/dist/src/agent/routes/inspect.test.js.map +1 -1
  59. package/dist/src/agent/routes/stores.js +9 -12
  60. package/dist/src/agent/routes/stores.js.map +1 -1
  61. package/dist/src/agent/routes/task.d.ts +15 -3
  62. package/dist/src/agent/routes/task.js +16 -7
  63. package/dist/src/agent/routes/task.js.map +1 -1
  64. package/dist/src/agent/routes/task.test.d.ts +1 -1
  65. package/dist/src/agent/routes/task.test.js +70 -53
  66. package/dist/src/agent/routes/task.test.js.map +1 -1
  67. package/dist/src/agent/routes/webhooks.js +12 -3
  68. package/dist/src/agent/routes/webhooks.js.map +1 -1
  69. package/dist/src/agent/session-store.d.ts +11 -2
  70. package/dist/src/agent/session-store.js +1 -1
  71. package/dist/src/agent/session-store.js.map +1 -1
  72. package/dist/src/agent/snapshot-server.d.ts +2 -22
  73. package/dist/src/agent/snapshot-server.js +50 -27
  74. package/dist/src/agent/snapshot-server.js.map +1 -1
  75. package/dist/src/agent/states/compacting.d.ts +14 -0
  76. package/dist/src/agent/states/compacting.js +258 -0
  77. package/dist/src/agent/states/compacting.js.map +1 -0
  78. package/dist/src/agent/states/confirming.d.ts +10 -0
  79. package/dist/src/agent/states/confirming.js +76 -0
  80. package/dist/src/agent/states/confirming.js.map +1 -0
  81. package/dist/src/agent/states/dispatching.d.ts +18 -0
  82. package/dist/src/agent/states/dispatching.js +241 -0
  83. package/dist/src/agent/states/dispatching.js.map +1 -0
  84. package/dist/src/agent/states/executing.d.ts +21 -0
  85. package/dist/src/agent/states/executing.js +308 -0
  86. package/dist/src/agent/states/executing.js.map +1 -0
  87. package/dist/src/agent/states/streaming.d.ts +10 -0
  88. package/dist/src/agent/states/streaming.js +155 -0
  89. package/dist/src/agent/states/streaming.js.map +1 -0
  90. package/dist/src/agent/states/thinking.d.ts +13 -0
  91. package/dist/src/agent/states/thinking.js +233 -0
  92. package/dist/src/agent/states/thinking.js.map +1 -0
  93. package/dist/src/agent/token-estimate.d.ts +17 -0
  94. package/dist/src/agent/token-estimate.js +13 -0
  95. package/dist/src/agent/token-estimate.js.map +1 -0
  96. package/dist/src/agent/tool-executor-local.js +9 -18
  97. package/dist/src/agent/tool-executor-local.js.map +1 -1
  98. package/dist/src/agent/tool-executor-local.test.js +3 -5
  99. package/dist/src/agent/tool-executor-local.test.js.map +1 -1
  100. package/dist/src/api/create-agent.d.ts +15 -0
  101. package/dist/src/api/create-agent.js +137 -0
  102. package/dist/src/api/create-agent.js.map +1 -0
  103. package/dist/src/api/types.d.ts +68 -0
  104. package/dist/src/api/types.js +7 -0
  105. package/dist/src/api/types.js.map +1 -0
  106. package/dist/src/context/compiler.d.ts +13 -0
  107. package/dist/src/context/compiler.js +358 -0
  108. package/dist/src/context/compiler.js.map +1 -0
  109. package/dist/src/context/compiler.test.js +532 -0
  110. package/dist/src/context/compiler.test.js.map +1 -0
  111. package/dist/src/context/types.d.ts +110 -0
  112. package/dist/src/context/types.js +7 -0
  113. package/dist/src/context/types.js.map +1 -0
  114. package/dist/src/index.d.ts +33 -6
  115. package/dist/src/index.js +35 -21
  116. package/dist/src/index.js.map +1 -1
  117. package/dist/src/providers/create-provider.d.ts +23 -0
  118. package/dist/src/providers/create-provider.js +185 -0
  119. package/dist/src/providers/create-provider.js.map +1 -0
  120. package/dist/src/{agent/stores-e2e.test.d.ts → providers/create-provider.test.d.ts} +1 -1
  121. package/dist/src/providers/create-provider.test.js +95 -0
  122. package/dist/src/providers/create-provider.test.js.map +1 -0
  123. package/dist/src/providers/failover.d.ts +38 -0
  124. package/dist/src/providers/failover.js +147 -0
  125. package/dist/src/providers/failover.js.map +1 -0
  126. package/dist/src/providers/failover.test.d.ts +6 -0
  127. package/dist/src/providers/failover.test.js +169 -0
  128. package/dist/src/providers/failover.test.js.map +1 -0
  129. package/dist/src/providers/types.d.ts +110 -0
  130. package/dist/src/providers/types.js +7 -0
  131. package/dist/src/providers/types.js.map +1 -0
  132. package/dist/src/routes/ai-stream.d.ts +13 -10
  133. package/dist/src/routes/ai-stream.js +76 -41
  134. package/dist/src/routes/ai-stream.js.map +1 -1
  135. package/dist/src/routes/chat-new.test.d.ts +6 -0
  136. package/dist/src/routes/chat-new.test.js +107 -0
  137. package/dist/src/routes/chat-new.test.js.map +1 -0
  138. package/dist/src/routes/chat-stream-new.test.d.ts +6 -0
  139. package/dist/src/routes/chat-stream-new.test.js +135 -0
  140. package/dist/src/routes/chat-stream-new.test.js.map +1 -0
  141. package/dist/src/routes/chat-stream.d.ts +14 -4
  142. package/dist/src/routes/chat-stream.js +47 -29
  143. package/dist/src/routes/chat-stream.js.map +1 -1
  144. package/dist/src/routes/chat.d.ts +13 -4
  145. package/dist/src/routes/chat.js +60 -23
  146. package/dist/src/routes/chat.js.map +1 -1
  147. package/dist/src/routes/health.d.ts +3 -2
  148. package/dist/src/routes/health.js.map +1 -1
  149. package/dist/src/routes/route-helpers.d.ts +50 -0
  150. package/dist/src/routes/route-helpers.js +80 -0
  151. package/dist/src/routes/route-helpers.js.map +1 -0
  152. package/dist/src/routes/session-resolver.d.ts +72 -0
  153. package/dist/src/routes/session-resolver.js +123 -0
  154. package/dist/src/routes/session-resolver.js.map +1 -0
  155. package/dist/src/routes/session-resolver.test.d.ts +6 -0
  156. package/dist/src/routes/session-resolver.test.js +206 -0
  157. package/dist/src/routes/session-resolver.test.js.map +1 -0
  158. package/dist/src/routes/webhooks.d.ts +3 -1
  159. package/dist/src/routes/webhooks.js +12 -4
  160. package/dist/src/routes/webhooks.js.map +1 -1
  161. package/dist/src/security/permission-checker.d.ts +80 -0
  162. package/dist/src/security/permission-checker.js +75 -0
  163. package/dist/src/security/permission-checker.js.map +1 -0
  164. package/dist/src/security/permission-checker.test.d.ts +6 -0
  165. package/dist/src/security/permission-checker.test.js +208 -0
  166. package/dist/src/security/permission-checker.test.js.map +1 -0
  167. package/dist/src/server.d.ts +12 -11
  168. package/dist/src/server.js +44 -46
  169. package/dist/src/server.js.map +1 -1
  170. package/dist/src/server.test.d.ts +1 -1
  171. package/dist/src/server.test.js +6 -144
  172. package/dist/src/server.test.js.map +1 -1
  173. package/dist/src/session/manager.d.ts +98 -0
  174. package/dist/src/session/manager.js +364 -0
  175. package/dist/src/session/manager.js.map +1 -0
  176. package/dist/src/session/manager.test.d.ts +6 -0
  177. package/dist/src/session/manager.test.js +315 -0
  178. package/dist/src/session/manager.test.js.map +1 -0
  179. package/dist/src/session/session-builder.d.ts +71 -0
  180. package/dist/src/session/session-builder.js +364 -0
  181. package/dist/src/session/session-builder.js.map +1 -0
  182. package/dist/src/session/session-builder.test.d.ts +6 -0
  183. package/dist/src/session/session-builder.test.js +352 -0
  184. package/dist/src/session/session-builder.test.js.map +1 -0
  185. package/dist/src/session/store.d.ts +57 -0
  186. package/dist/src/session/store.js +167 -0
  187. package/dist/src/session/store.js.map +1 -0
  188. package/dist/src/session/store.test.d.ts +6 -0
  189. package/dist/src/session/store.test.js +145 -0
  190. package/dist/src/session/store.test.js.map +1 -0
  191. package/dist/src/session/stream-hooks.d.ts +39 -0
  192. package/dist/src/session/stream-hooks.js +7 -0
  193. package/dist/src/session/stream-hooks.js.map +1 -0
  194. package/dist/src/session/tool-context-factory.d.ts +60 -0
  195. package/dist/src/session/tool-context-factory.js +190 -0
  196. package/dist/src/session/tool-context-factory.js.map +1 -0
  197. package/dist/src/session/tool-context-factory.test.d.ts +6 -0
  198. package/dist/src/session/tool-context-factory.test.js +287 -0
  199. package/dist/src/session/tool-context-factory.test.js.map +1 -0
  200. package/dist/src/session/types.d.ts +188 -0
  201. package/dist/src/session/types.js +7 -0
  202. package/dist/src/session/types.js.map +1 -0
  203. package/dist/src/stores/drizzle-store-backend.d.ts +49 -0
  204. package/dist/src/stores/drizzle-store-backend.js +306 -0
  205. package/dist/src/stores/drizzle-store-backend.js.map +1 -0
  206. package/dist/src/stores/drizzle-store-backend.test.d.ts +6 -0
  207. package/dist/src/stores/drizzle-store-backend.test.js +215 -0
  208. package/dist/src/stores/drizzle-store-backend.test.js.map +1 -0
  209. package/dist/src/stores/index.d.ts +4 -0
  210. package/dist/src/stores/index.js +2 -0
  211. package/dist/src/stores/index.js.map +1 -1
  212. package/dist/src/stores/pglite-store-backend.d.ts +16 -19
  213. package/dist/src/stores/pglite-store-backend.js +85 -239
  214. package/dist/src/stores/pglite-store-backend.js.map +1 -1
  215. package/dist/src/stores/postgres-store-backend.d.ts +30 -0
  216. package/dist/src/stores/postgres-store-backend.js +100 -0
  217. package/dist/src/stores/postgres-store-backend.js.map +1 -0
  218. package/dist/src/stores/schema.d.ts +491 -0
  219. package/dist/src/stores/schema.js +57 -0
  220. package/dist/src/stores/schema.js.map +1 -0
  221. package/dist/src/tools/admin-file-tools.d.ts +13 -0
  222. package/dist/src/tools/admin-file-tools.js +200 -0
  223. package/dist/src/tools/admin-file-tools.js.map +1 -0
  224. package/dist/src/tools/admin-file-tools.test.d.ts +6 -0
  225. package/dist/src/tools/admin-file-tools.test.js +152 -0
  226. package/dist/src/tools/admin-file-tools.test.js.map +1 -0
  227. package/dist/src/tools/custom-tool-adapter.d.ts +41 -0
  228. package/dist/src/tools/custom-tool-adapter.js +190 -0
  229. package/dist/src/tools/custom-tool-adapter.js.map +1 -0
  230. package/dist/src/tools/custom-tool-adapter.test.d.ts +6 -0
  231. package/dist/src/tools/custom-tool-adapter.test.js +244 -0
  232. package/dist/src/tools/custom-tool-adapter.test.js.map +1 -0
  233. package/dist/src/tools/dispatch-tool.d.ts +52 -0
  234. package/dist/src/tools/dispatch-tool.js +71 -0
  235. package/dist/src/tools/dispatch-tool.js.map +1 -0
  236. package/dist/src/tools/dispatch-tool.test.d.ts +6 -0
  237. package/dist/src/tools/dispatch-tool.test.js +75 -0
  238. package/dist/src/tools/dispatch-tool.test.js.map +1 -0
  239. package/dist/src/tools/mcp-tool-adapter.d.ts +18 -0
  240. package/dist/src/tools/mcp-tool-adapter.js +135 -0
  241. package/dist/src/tools/mcp-tool-adapter.js.map +1 -0
  242. package/dist/src/tools/mcp-tool-adapter.test.d.ts +6 -0
  243. package/dist/src/tools/mcp-tool-adapter.test.js +227 -0
  244. package/dist/src/tools/mcp-tool-adapter.test.js.map +1 -0
  245. package/dist/src/tools/registry.d.ts +25 -0
  246. package/dist/src/tools/registry.js +72 -0
  247. package/dist/src/tools/registry.js.map +1 -0
  248. package/dist/src/tools/registry.test.d.ts +6 -0
  249. package/dist/src/tools/registry.test.js +121 -0
  250. package/dist/src/tools/registry.test.js.map +1 -0
  251. package/dist/src/tools/request-tool.d.ts +42 -0
  252. package/dist/src/tools/request-tool.js +190 -0
  253. package/dist/src/tools/request-tool.js.map +1 -0
  254. package/dist/src/tools/request-tool.test.d.ts +6 -0
  255. package/dist/src/tools/request-tool.test.js +254 -0
  256. package/dist/src/tools/request-tool.test.js.map +1 -0
  257. package/dist/src/tools/store-tools.d.ts +29 -0
  258. package/dist/src/tools/store-tools.js +224 -0
  259. package/dist/src/tools/store-tools.js.map +1 -0
  260. package/dist/src/tools/store-tools.test.d.ts +6 -0
  261. package/dist/src/tools/store-tools.test.js +216 -0
  262. package/dist/src/tools/store-tools.test.js.map +1 -0
  263. package/dist/src/tools/types.d.ts +111 -0
  264. package/dist/src/tools/types.js +7 -0
  265. package/dist/src/tools/types.js.map +1 -0
  266. package/dist/src/types.d.ts +20 -12
  267. package/dist/src/types.js +3 -2
  268. package/dist/src/types.js.map +1 -1
  269. package/dist/tsconfig.tsbuildinfo +1 -1
  270. package/package.json +13 -4
  271. package/dist/src/__tests__/sse-contract.test.js +0 -464
  272. package/dist/src/__tests__/sse-contract.test.js.map +0 -1
  273. package/dist/src/__tests__/tools.test.js +0 -583
  274. package/dist/src/__tests__/tools.test.js.map +0 -1
  275. package/dist/src/agent/agent-runner.d.ts +0 -33
  276. package/dist/src/agent/agent-runner.js +0 -1040
  277. package/dist/src/agent/agent-runner.js.map +0 -1
  278. package/dist/src/agent/custom-tools-e2e.test.d.ts +0 -6
  279. package/dist/src/agent/custom-tools-e2e.test.js +0 -566
  280. package/dist/src/agent/custom-tools-e2e.test.js.map +0 -1
  281. package/dist/src/agent/request-helper.d.ts +0 -16
  282. package/dist/src/agent/request-helper.js +0 -96
  283. package/dist/src/agent/request-helper.js.map +0 -1
  284. package/dist/src/agent/stores-e2e.test.js +0 -433
  285. package/dist/src/agent/stores-e2e.test.js.map +0 -1
  286. package/dist/src/agent/tool-context-builder.d.ts +0 -11
  287. package/dist/src/agent/tool-context-builder.js +0 -102
  288. package/dist/src/agent/tool-context-builder.js.map +0 -1
  289. package/dist/src/agent/tool-context-builder.test.d.ts +0 -6
  290. package/dist/src/agent/tool-context-builder.test.js +0 -152
  291. package/dist/src/agent/tool-context-builder.test.js.map +0 -1
  292. package/dist/src/agent/write-repo-file.test.js +0 -270
  293. package/dist/src/agent/write-repo-file.test.js.map +0 -1
  294. package/dist/src/cron/heartbeat-runner.d.ts +0 -21
  295. package/dist/src/cron/heartbeat-runner.js +0 -79
  296. package/dist/src/cron/heartbeat-runner.js.map +0 -1
  297. package/dist/src/cron/heartbeat-runner.test.d.ts +0 -6
  298. package/dist/src/cron/heartbeat-runner.test.js +0 -120
  299. package/dist/src/cron/heartbeat-runner.test.js.map +0 -1
  300. package/dist/src/cron/heartbeat-scheduler.d.ts +0 -26
  301. package/dist/src/cron/heartbeat-scheduler.js +0 -55
  302. package/dist/src/cron/heartbeat-scheduler.js.map +0 -1
  303. package/dist/src/cron/heartbeat-scheduler.test.d.ts +0 -6
  304. package/dist/src/cron/heartbeat-scheduler.test.js +0 -61
  305. package/dist/src/cron/heartbeat-scheduler.test.js.map +0 -1
  306. package/dist/src/routes/ai-stream.test.d.ts +0 -6
  307. package/dist/src/routes/ai-stream.test.js +0 -586
  308. package/dist/src/routes/ai-stream.test.js.map +0 -1
  309. package/dist/src/routes/ask-user-response.d.ts +0 -30
  310. package/dist/src/routes/ask-user-response.js +0 -61
  311. package/dist/src/routes/ask-user-response.js.map +0 -1
  312. package/dist/src/routes/ask-user-response.test.d.ts +0 -6
  313. package/dist/src/routes/ask-user-response.test.js +0 -88
  314. package/dist/src/routes/ask-user-response.test.js.map +0 -1
  315. package/dist/src/routes/chat-stream.test.d.ts +0 -6
  316. package/dist/src/routes/chat-stream.test.js +0 -155
  317. package/dist/src/routes/chat-stream.test.js.map +0 -1
  318. package/dist/src/routes/chat.test.d.ts +0 -6
  319. package/dist/src/routes/chat.test.js +0 -99
  320. package/dist/src/routes/chat.test.js.map +0 -1
  321. package/dist/src/routes/widget-actions.d.ts +0 -49
  322. package/dist/src/routes/widget-actions.js +0 -78
  323. package/dist/src/routes/widget-actions.js.map +0 -1
  324. package/dist/src/session/custom-tool-adapter.d.ts +0 -74
  325. package/dist/src/session/custom-tool-adapter.js +0 -180
  326. package/dist/src/session/custom-tool-adapter.js.map +0 -1
  327. package/dist/src/session/history-converter.d.ts +0 -21
  328. package/dist/src/session/history-converter.js +0 -59
  329. package/dist/src/session/history-converter.js.map +0 -1
  330. package/dist/src/session/history-converter.test.d.ts +0 -6
  331. package/dist/src/session/history-converter.test.js +0 -130
  332. package/dist/src/session/history-converter.test.js.map +0 -1
  333. package/dist/src/session/session-manager.d.ts +0 -219
  334. package/dist/src/session/session-manager.js +0 -915
  335. package/dist/src/session/session-manager.js.map +0 -1
  336. package/dist/src/session/session-manager.test.d.ts +0 -6
  337. package/dist/src/session/session-manager.test.js +0 -455
  338. package/dist/src/session/session-manager.test.js.map +0 -1
  339. package/dist/src/session/session-runner.d.ts +0 -45
  340. package/dist/src/session/session-runner.js +0 -719
  341. package/dist/src/session/session-runner.js.map +0 -1
  342. package/dist/src/session/session-runner.test.d.ts +0 -6
  343. package/dist/src/session/session-runner.test.js +0 -834
  344. package/dist/src/session/session-runner.test.js.map +0 -1
  345. /package/dist/src/{__tests__/sse-contract.test.d.ts → __fixtures__/smoke.test.d.ts} +0 -0
  346. /package/dist/src/{__tests__/tools.test.d.ts → agent/loop.test.d.ts} +0 -0
  347. /package/dist/src/{agent/write-repo-file.test.d.ts → context/compiler.test.d.ts} +0 -0
@@ -3,279 +3,125 @@
3
3
  * Copyright 2025 Amodal Labs, Inc.
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
- import { resolveTtl } from './ttl-resolver.js';
7
- import { log } from '../logger.js';
8
6
  /**
9
7
  * PGLite-backed store backend.
10
8
  *
11
- * Uses in-process WASM Postgres via @electric-sql/pglite.
12
- * Data is stored in a configurable directory (default: .amodal/store-data/).
9
+ * Uses in-process WASM Postgres via @electric-sql/pglite + Drizzle ORM.
10
+ * Data is stored in a configurable directory (default: in-memory).
13
11
  *
14
- * All writes are serialized through a queue to prevent concurrent access
15
- * issues with PGLite's single-threaded WASM engine.
12
+ * This file is a thin factory over DrizzleStoreBackend it constructs
13
+ * the PGLite client, runs DDL, wraps it in drizzle(), and hands off all
14
+ * query logic to the shared backend.
16
15
  */
16
+ import { drizzle } from 'drizzle-orm/pglite';
17
+ import { DrizzleStoreBackend } from './drizzle-store-backend.js';
18
+ import { StoreError } from '../errors.js';
19
+ import { log as defaultLogger } from '../logger.js';
20
+ const CREATE_TABLES_DDL = `
21
+ CREATE TABLE IF NOT EXISTS store_documents (
22
+ app_id TEXT NOT NULL,
23
+ store TEXT NOT NULL,
24
+ key TEXT NOT NULL,
25
+ version INTEGER NOT NULL DEFAULT 1,
26
+ payload JSONB NOT NULL,
27
+ meta JSONB NOT NULL,
28
+ expires_at TIMESTAMPTZ,
29
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
30
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
31
+ PRIMARY KEY (app_id, store, key)
32
+ );
33
+
34
+ CREATE INDEX IF NOT EXISTS idx_store_documents_store
35
+ ON store_documents (app_id, store);
36
+
37
+ CREATE INDEX IF NOT EXISTS idx_store_documents_expires
38
+ ON store_documents (expires_at)
39
+ WHERE expires_at IS NOT NULL;
40
+
41
+ CREATE TABLE IF NOT EXISTS store_document_versions (
42
+ id SERIAL PRIMARY KEY,
43
+ app_id TEXT NOT NULL,
44
+ store TEXT NOT NULL,
45
+ key TEXT NOT NULL,
46
+ version INTEGER NOT NULL,
47
+ payload JSONB NOT NULL,
48
+ meta JSONB NOT NULL,
49
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
50
+ );
51
+
52
+ CREATE INDEX IF NOT EXISTS idx_store_versions_lookup
53
+ ON store_document_versions (app_id, store, key, version DESC);
54
+ `;
17
55
  export class PGLiteStoreBackend {
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
- db = null;
20
56
  dataDir;
21
- stores = new Map();
22
- writeQueue = Promise.resolve();
23
- constructor(dataDir) {
24
- this.dataDir = dataDir;
25
- }
26
- /**
27
- * Serialize a write operation through the queue.
28
- * Ensures PGLite only processes one write at a time.
29
- */
30
- enqueue(fn) {
31
- const task = this.writeQueue.then(fn, fn);
32
- this.writeQueue = task.then(() => { }, () => { });
33
- return task;
57
+ logger;
58
+ inner = null;
59
+ constructor(dataDirOrOpts) {
60
+ const opts = typeof dataDirOrOpts === 'string' || dataDirOrOpts === undefined
61
+ ? { dataDir: dataDirOrOpts }
62
+ : dataDirOrOpts;
63
+ this.dataDir = opts.dataDir;
64
+ this.logger = opts.logger ?? defaultLogger;
34
65
  }
35
66
  async initialize(stores) {
67
+ if (this.inner)
68
+ return;
36
69
  if (this.dataDir) {
37
70
  const { mkdirSync } = await import('node:fs');
38
71
  mkdirSync(this.dataDir, { recursive: true });
39
72
  }
40
73
  const { PGlite } = await import('@electric-sql/pglite');
41
- this.db = new PGlite(this.dataDir ?? undefined);
42
- for (const store of stores) {
43
- this.stores.set(store.name, store);
44
- }
45
- await this.db.exec(`
46
- CREATE TABLE IF NOT EXISTS store_documents (
47
- app_id TEXT NOT NULL,
48
- store TEXT NOT NULL,
49
- key TEXT NOT NULL,
50
- version INTEGER NOT NULL DEFAULT 1,
51
- payload JSONB NOT NULL,
52
- meta JSONB NOT NULL,
53
- expires_at TIMESTAMPTZ,
54
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
55
- updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
56
- PRIMARY KEY (app_id, store, key)
57
- );
58
-
59
- CREATE INDEX IF NOT EXISTS idx_store_documents_store
60
- ON store_documents (app_id, store);
61
-
62
- CREATE INDEX IF NOT EXISTS idx_store_documents_expires
63
- ON store_documents (expires_at)
64
- WHERE expires_at IS NOT NULL;
65
-
66
- CREATE TABLE IF NOT EXISTS store_document_versions (
67
- id SERIAL PRIMARY KEY,
68
- app_id TEXT NOT NULL,
69
- store TEXT NOT NULL,
70
- key TEXT NOT NULL,
71
- version INTEGER NOT NULL,
72
- payload JSONB NOT NULL,
73
- meta JSONB NOT NULL,
74
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
75
- );
76
-
77
- CREATE INDEX IF NOT EXISTS idx_store_versions_lookup
78
- ON store_document_versions (app_id, store, key, version DESC);
79
- `);
74
+ const pglite = new PGlite(this.dataDir ?? undefined);
75
+ await pglite.exec(CREATE_TABLES_DDL);
76
+ const db = drizzle(pglite);
77
+ this.inner = new DrizzleStoreBackend({
78
+ db,
79
+ stores,
80
+ logger: this.logger,
81
+ onClose: async () => {
82
+ await pglite.close();
83
+ },
84
+ });
80
85
  }
81
- ensureDb() {
82
- if (!this.db) {
83
- throw new Error('PGLite store backend is not initialized or was closed');
86
+ ensure() {
87
+ if (!this.inner) {
88
+ throw new StoreError('PGLite store backend is not initialized or was closed', {
89
+ store: '(uninitialized)',
90
+ operation: 'ensure',
91
+ });
84
92
  }
93
+ return this.inner;
85
94
  }
86
95
  async get(appId, store, key) {
87
- this.ensureDb();
88
- try {
89
- const result = await this.db.query(`SELECT key, app_id, store, version, payload, meta, expires_at
90
- FROM store_documents
91
- WHERE app_id = $1 AND store = $2 AND key = $3`, [appId, store, key]);
92
- if (result.rows.length === 0)
93
- return null;
94
- return this.rowToDocument(result.rows[0]);
95
- }
96
- catch (err) {
97
- log.error(`get error: ${err instanceof Error ? err.message : String(err)}`, 'store');
98
- return null;
99
- }
96
+ return this.ensure().get(appId, store, key);
100
97
  }
101
98
  async put(appId, store, key, payload, meta) {
102
- this.ensureDb();
103
- return this.enqueue(async () => {
104
- const storeConfig = this.stores.get(store);
105
- const ttlSeconds = resolveTtl(storeConfig?.ttl, payload);
106
- const maxVersions = storeConfig?.history?.versions;
107
- const fullMeta = {
108
- computedAt: new Date().toISOString(),
109
- stale: false,
110
- ...meta,
111
- ttl: ttlSeconds,
112
- };
113
- const expiresAt = ttlSeconds
114
- ? new Date(Date.now() + ttlSeconds * 1000).toISOString()
115
- : null;
116
- try {
117
- // Use upsert to avoid read-then-write race
118
- const existing = await this.db.query(`SELECT version, payload, meta FROM store_documents
119
- WHERE app_id = $1 AND store = $2 AND key = $3`, [appId, store, key]);
120
- if (existing.rows.length > 0) {
121
- const oldVersion = Number(existing.rows[0].version);
122
- const newVersion = oldVersion + 1;
123
- if (maxVersions && maxVersions > 0) {
124
- await this.db.query(`INSERT INTO store_document_versions (app_id, store, key, version, payload, meta)
125
- VALUES ($1, $2, $3, $4, $5, $6)`, [appId, store, key, oldVersion, JSON.stringify(existing.rows[0].payload), JSON.stringify(existing.rows[0].meta)]);
126
- await this.db.query(`DELETE FROM store_document_versions
127
- WHERE app_id = $1 AND store = $2 AND key = $3
128
- AND version <= (
129
- SELECT COALESCE(MAX(version), 0) - $4
130
- FROM store_document_versions
131
- WHERE app_id = $1 AND store = $2 AND key = $3
132
- )`, [appId, store, key, maxVersions]);
133
- }
134
- await this.db.query(`UPDATE store_documents
135
- SET version = $4, payload = $5, meta = $6, expires_at = $7, updated_at = NOW()
136
- WHERE app_id = $1 AND store = $2 AND key = $3`, [appId, store, key, newVersion, JSON.stringify(payload), JSON.stringify(fullMeta), expiresAt]);
137
- return { stored: true, key, version: newVersion, previousVersion: oldVersion };
138
- }
139
- await this.db.query(`INSERT INTO store_documents (app_id, store, key, version, payload, meta, expires_at)
140
- VALUES ($1, $2, $3, 1, $4, $5, $6)`, [appId, store, key, JSON.stringify(payload), JSON.stringify(fullMeta), expiresAt]);
141
- return { stored: true, key, version: 1 };
142
- }
143
- catch (err) {
144
- log.error(`put error (${store}/${key}): ${err instanceof Error ? err.message : String(err)}`, 'store');
145
- return { stored: false, key, version: 0 };
146
- }
147
- });
99
+ return this.ensure().put(appId, store, key, payload, meta);
148
100
  }
149
- async list(appId, store, options = {}) {
150
- this.ensureDb();
151
- const { filter, sort, limit = 100, offset = 0, includeStale = false } = options;
152
- try {
153
- let where = 'WHERE app_id = $1 AND store = $2';
154
- const params = [appId, store];
155
- let paramIndex = 3;
156
- if (!includeStale) {
157
- where += ` AND (expires_at IS NULL OR expires_at > NOW())`;
158
- }
159
- if (filter) {
160
- for (const [field, value] of Object.entries(filter)) {
161
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(field)) {
162
- throw new Error(`Invalid store filter field name: ${field}`);
163
- }
164
- where += ` AND payload->>'${field}' = $${paramIndex}`;
165
- params.push(String(value));
166
- paramIndex++;
167
- }
168
- }
169
- const countResult = await this.db.query(`SELECT COUNT(*)::int AS total FROM store_documents ${where}`, params);
170
- const total = Number(countResult.rows[0].total);
171
- let orderBy = 'ORDER BY updated_at DESC';
172
- if (sort) {
173
- const desc = sort.startsWith('-');
174
- const field = desc ? sort.slice(1) : sort;
175
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(field)) {
176
- throw new Error(`Invalid store sort field name: ${field}`);
177
- }
178
- const dir = desc ? 'DESC' : 'ASC';
179
- orderBy = `ORDER BY payload->>'${field}' ${dir}`;
180
- }
181
- const result = await this.db.query(`SELECT key, app_id, store, version, payload, meta, expires_at
182
- FROM store_documents ${where} ${orderBy}
183
- LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [...params, limit, offset]);
184
- const documents = result.rows.map((row) => this.rowToDocument(row));
185
- return { documents, total, hasMore: offset + documents.length < total };
186
- }
187
- catch (err) {
188
- log.error(`list error (${store}): ${err instanceof Error ? err.message : String(err)}`, 'store');
189
- return { documents: [], total: 0, hasMore: false };
190
- }
101
+ async list(appId, store, options) {
102
+ return this.ensure().list(appId, store, options);
191
103
  }
192
104
  async delete(appId, store, key) {
193
- this.ensureDb();
194
- return this.enqueue(async () => {
195
- try {
196
- await this.db.query(`DELETE FROM store_document_versions WHERE app_id = $1 AND store = $2 AND key = $3`, [appId, store, key]);
197
- const result = await this.db.query(`DELETE FROM store_documents WHERE app_id = $1 AND store = $2 AND key = $3`, [appId, store, key]);
198
- return (result.affectedRows ?? 0) > 0;
199
- }
200
- catch (err) {
201
- log.error(`delete error (${store}/${key}): ${err instanceof Error ? err.message : String(err)}`, 'store');
202
- return false;
203
- }
204
- });
105
+ return this.ensure().delete(appId, store, key);
205
106
  }
206
107
  async history(appId, store, key) {
207
- this.ensureDb();
208
- try {
209
- const result = await this.db.query(`SELECT key, $1::text AS app_id, store, version, payload, meta
210
- FROM store_document_versions
211
- WHERE app_id = $1 AND store = $2 AND key = $3
212
- ORDER BY version DESC`, [appId, store, key]);
213
- return result.rows.map((row) => ({
214
- key: String(row['key']),
215
- appId: String(row['app_id']),
216
- store: String(row['store']),
217
- version: Number(row['version']),
218
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
219
- payload: (typeof row['payload'] === 'string' ? JSON.parse(row['payload']) : row['payload']),
220
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
221
- meta: (typeof row['meta'] === 'string' ? JSON.parse(row['meta']) : row['meta']),
222
- }));
223
- }
224
- catch (err) {
225
- log.error(`history error (${store}/${key}): ${err instanceof Error ? err.message : String(err)}`, 'store');
226
- return [];
227
- }
108
+ return this.ensure().history(appId, store, key);
228
109
  }
229
110
  async purgeExpired(appId, store) {
230
- this.ensureDb();
231
- return this.enqueue(async () => {
232
- try {
233
- let query = `DELETE FROM store_documents WHERE app_id = $1 AND expires_at IS NOT NULL AND expires_at <= NOW()`;
234
- const params = [appId];
235
- if (store) {
236
- query += ` AND store = $2`;
237
- params.push(store);
238
- }
239
- const result = await this.db.query(query, params);
240
- return result.affectedRows ?? 0;
241
- }
242
- catch (err) {
243
- log.error(`purgeExpired error: ${err instanceof Error ? err.message : String(err)}`, 'store');
244
- return 0;
245
- }
246
- });
111
+ return this.ensure().purgeExpired(appId, store);
247
112
  }
248
113
  async close() {
249
- if (this.db) {
250
- try {
251
- await this.db.close();
252
- }
253
- catch { /* best effort */ }
254
- this.db = null;
255
- }
256
- }
257
- rowToDocument(row) {
258
- const expiresAt = row['expires_at'];
259
- const isStale = expiresAt ? new Date(String(expiresAt)) <= new Date() : false;
260
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
261
- const meta = (typeof row['meta'] === 'string' ? JSON.parse(row['meta']) : row['meta']);
262
- meta.stale = isStale;
263
- return {
264
- key: String(row['key']),
265
- appId: String(row['app_id']),
266
- store: String(row['store']),
267
- version: Number(row['version']),
268
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
269
- payload: (typeof row['payload'] === 'string' ? JSON.parse(row['payload']) : row['payload']),
270
- meta,
271
- };
114
+ if (!this.inner)
115
+ return;
116
+ await this.inner.close();
117
+ this.inner = null;
272
118
  }
273
119
  }
274
120
  /**
275
121
  * Create a PGLite store backend.
276
122
  */
277
- export async function createPGLiteStoreBackend(stores, dataDir) {
278
- const backend = new PGLiteStoreBackend(dataDir);
123
+ export async function createPGLiteStoreBackend(stores, dataDirOrOpts) {
124
+ const backend = new PGLiteStoreBackend(dataDirOrOpts);
279
125
  await backend.initialize(stores);
280
126
  return backend;
281
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pglite-store-backend.js","sourceRoot":"","sources":["../../../src/stores/pglite-store-backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pglite-store-backend.js","sourceRoot":"","sources":["../../../src/stores/pglite-store-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import type { LoadedStore } from '@amodalai/core';
7
+ import { DrizzleStoreBackend } from './drizzle-store-backend.js';
8
+ import type { Logger } from '../logger.js';
9
+ export interface PostgresStoreBackendOptions {
10
+ /** Postgres connection string, e.g. `postgres://user:pass@host:5432/db`. */
11
+ connectionString: string;
12
+ /** Pool size (default 10). */
13
+ max?: number;
14
+ /** Per-statement timeout in ms (default 30_000). */
15
+ statementTimeoutMs?: number;
16
+ /** Logger. Defaults to the runtime's global logger. */
17
+ logger?: Logger;
18
+ }
19
+ /**
20
+ * Create a Postgres store backend.
21
+ *
22
+ * Opens a connection pool with `statement_timeout` set so hung queries
23
+ * can't block the write queue, runs idempotent DDL, and returns a
24
+ * DrizzleStoreBackend wired to the pool. The returned backend's
25
+ * `close()` will drain and end the pool.
26
+ *
27
+ * Accepts either a connection string (shorthand) or a full options
28
+ * object — matches `createPGLiteStoreBackend`'s call-site ergonomics.
29
+ */
30
+ export declare function createPostgresStoreBackend(stores: LoadedStore[], optsOrUrl: PostgresStoreBackendOptions | string): Promise<DrizzleStoreBackend>;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Amodal Labs, Inc.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Postgres-backed store backend for the hosted runtime.
8
+ *
9
+ * Thin factory over DrizzleStoreBackend using drizzle-orm/node-postgres.
10
+ * Shares all query logic and DDL with the PGLite backend via the
11
+ * `stores/schema.ts` Drizzle schema.
12
+ *
13
+ * Tables are created in the connection's default schema (typically
14
+ * `public`). Callers who need isolation should use a dedicated database
15
+ * per tenant/environment rather than schema namespacing — that avoids
16
+ * the search_path / connection-pool interaction hazards that
17
+ * schema-scoping introduces.
18
+ */
19
+ import { drizzle } from 'drizzle-orm/node-postgres';
20
+ import { DrizzleStoreBackend } from './drizzle-store-backend.js';
21
+ import { log as defaultLogger } from '../logger.js';
22
+ // Default per-statement timeout. Protects against hung queries blocking
23
+ // the write queue — satisfies the CLAUDE.md "External calls (fetch,
24
+ // database, MCP) without AbortSignal.timeout()" rule at the pool level.
25
+ const DEFAULT_STATEMENT_TIMEOUT_MS = 30_000;
26
+ const CREATE_TABLES_DDL = `
27
+ CREATE TABLE IF NOT EXISTS store_documents (
28
+ app_id TEXT NOT NULL,
29
+ store TEXT NOT NULL,
30
+ key TEXT NOT NULL,
31
+ version INTEGER NOT NULL DEFAULT 1,
32
+ payload JSONB NOT NULL,
33
+ meta JSONB NOT NULL,
34
+ expires_at TIMESTAMPTZ,
35
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
36
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
37
+ PRIMARY KEY (app_id, store, key)
38
+ );
39
+
40
+ CREATE INDEX IF NOT EXISTS idx_store_documents_store
41
+ ON store_documents (app_id, store);
42
+
43
+ CREATE INDEX IF NOT EXISTS idx_store_documents_expires
44
+ ON store_documents (expires_at)
45
+ WHERE expires_at IS NOT NULL;
46
+
47
+ CREATE TABLE IF NOT EXISTS store_document_versions (
48
+ id SERIAL PRIMARY KEY,
49
+ app_id TEXT NOT NULL,
50
+ store TEXT NOT NULL,
51
+ key TEXT NOT NULL,
52
+ version INTEGER NOT NULL,
53
+ payload JSONB NOT NULL,
54
+ meta JSONB NOT NULL,
55
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
56
+ );
57
+
58
+ CREATE INDEX IF NOT EXISTS idx_store_versions_lookup
59
+ ON store_document_versions (app_id, store, key, version DESC);
60
+ `;
61
+ /**
62
+ * Create a Postgres store backend.
63
+ *
64
+ * Opens a connection pool with `statement_timeout` set so hung queries
65
+ * can't block the write queue, runs idempotent DDL, and returns a
66
+ * DrizzleStoreBackend wired to the pool. The returned backend's
67
+ * `close()` will drain and end the pool.
68
+ *
69
+ * Accepts either a connection string (shorthand) or a full options
70
+ * object — matches `createPGLiteStoreBackend`'s call-site ergonomics.
71
+ */
72
+ export async function createPostgresStoreBackend(stores, optsOrUrl) {
73
+ const opts = typeof optsOrUrl === 'string' ? { connectionString: optsOrUrl } : optsOrUrl;
74
+ const logger = opts.logger ?? defaultLogger;
75
+ // Dynamic import so `pg` stays an optional peer at the package level —
76
+ // PGLite users don't need it installed.
77
+ const pg = await import('pg');
78
+ const { Pool } = pg.default ?? pg;
79
+ const pool = new Pool({
80
+ connectionString: opts.connectionString,
81
+ max: opts.max ?? 10,
82
+ statement_timeout: opts.statementTimeoutMs ?? DEFAULT_STATEMENT_TIMEOUT_MS,
83
+ });
84
+ await pool.query(CREATE_TABLES_DDL);
85
+ const db = drizzle(pool);
86
+ logger.info('postgres_store_backend_ready', {
87
+ max: opts.max ?? 10,
88
+ statementTimeoutMs: opts.statementTimeoutMs ?? DEFAULT_STATEMENT_TIMEOUT_MS,
89
+ storeCount: stores.length,
90
+ });
91
+ return new DrizzleStoreBackend({
92
+ db,
93
+ stores,
94
+ logger,
95
+ onClose: async () => {
96
+ await pool.end();
97
+ },
98
+ });
99
+ }
100
+ //# sourceMappingURL=postgres-store-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-store-backend.js","sourceRoot":"","sources":["../../../src/stores/postgres-store-backend.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,2BAA2B,CAAC;AAGlD,OAAO,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAC,GAAG,IAAI,aAAa,EAAC,MAAM,cAAc,CAAC;AAGlD,wEAAwE;AACxE,oEAAoE;AACpE,wEAAwE;AACxE,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAE5C,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCzB,CAAC;AAaF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAAqB,EACrB,SAA+C;IAE/C,MAAM,IAAI,GACR,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAC,gBAAgB,EAAE,SAAS,EAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE5E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC;IAE5C,uEAAuE;IACvE,wCAAwC;IACxC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,EAAC,IAAI,EAAC,GAAG,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC;IAEhC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;QACpB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE;QACnB,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,IAAI,4BAA4B;KAC3E,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAEpC,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE;QAC1C,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE;QACnB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,4BAA4B;QAC3E,UAAU,EAAE,MAAM,CAAC,MAAM;KAC1B,CAAC,CAAC;IAEH,OAAO,IAAI,mBAAmB,CAAC;QAC7B,EAAE;QACF,MAAM;QACN,MAAM;QACN,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;QACnB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}