@agent-native/core 0.109.2 → 0.109.4

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 (334) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +16 -0
  3. package/corpus/core/docs/content/agent-native-toolkit.mdx +46 -13
  4. package/corpus/core/docs/content/locales/ar-SA/agent-native-toolkit.mdx +79 -55
  5. package/corpus/core/docs/content/locales/ar-SA/toolkit-capability-packages.mdx +21 -0
  6. package/corpus/core/docs/content/locales/ar-SA/toolkit-context-knowledge.mdx +12 -0
  7. package/corpus/core/docs/content/locales/ar-SA/toolkit-editors-canvases.mdx +17 -0
  8. package/corpus/core/docs/content/locales/de-DE/agent-native-toolkit.mdx +82 -54
  9. package/corpus/core/docs/content/locales/de-DE/toolkit-capability-packages.mdx +21 -0
  10. package/corpus/core/docs/content/locales/de-DE/toolkit-context-knowledge.mdx +12 -0
  11. package/corpus/core/docs/content/locales/de-DE/toolkit-editors-canvases.mdx +17 -0
  12. package/corpus/core/docs/content/locales/es-ES/agent-native-toolkit.mdx +81 -52
  13. package/corpus/core/docs/content/locales/es-ES/toolkit-capability-packages.mdx +21 -0
  14. package/corpus/core/docs/content/locales/es-ES/toolkit-context-knowledge.mdx +12 -0
  15. package/corpus/core/docs/content/locales/es-ES/toolkit-editors-canvases.mdx +21 -0
  16. package/corpus/core/docs/content/locales/fr-FR/agent-native-toolkit.mdx +84 -54
  17. package/corpus/core/docs/content/locales/fr-FR/toolkit-capability-packages.mdx +21 -0
  18. package/corpus/core/docs/content/locales/fr-FR/toolkit-context-knowledge.mdx +12 -0
  19. package/corpus/core/docs/content/locales/fr-FR/toolkit-editors-canvases.mdx +21 -0
  20. package/corpus/core/docs/content/locales/hi-IN/agent-native-toolkit.mdx +69 -62
  21. package/corpus/core/docs/content/locales/hi-IN/toolkit-capability-packages.mdx +21 -0
  22. package/corpus/core/docs/content/locales/hi-IN/toolkit-context-knowledge.mdx +12 -0
  23. package/corpus/core/docs/content/locales/hi-IN/toolkit-editors-canvases.mdx +17 -0
  24. package/corpus/core/docs/content/locales/ja-JP/agent-native-toolkit.mdx +69 -62
  25. package/corpus/core/docs/content/locales/ja-JP/toolkit-capability-packages.mdx +21 -0
  26. package/corpus/core/docs/content/locales/ja-JP/toolkit-context-knowledge.mdx +12 -0
  27. package/corpus/core/docs/content/locales/ja-JP/toolkit-editors-canvases.mdx +17 -0
  28. package/corpus/core/docs/content/locales/ko-KR/agent-native-toolkit.mdx +69 -62
  29. package/corpus/core/docs/content/locales/ko-KR/toolkit-capability-packages.mdx +21 -0
  30. package/corpus/core/docs/content/locales/ko-KR/toolkit-context-knowledge.mdx +12 -0
  31. package/corpus/core/docs/content/locales/ko-KR/toolkit-editors-canvases.mdx +17 -0
  32. package/corpus/core/docs/content/locales/pt-BR/agent-native-toolkit.mdx +82 -54
  33. package/corpus/core/docs/content/locales/pt-BR/toolkit-capability-packages.mdx +21 -0
  34. package/corpus/core/docs/content/locales/pt-BR/toolkit-context-knowledge.mdx +12 -0
  35. package/corpus/core/docs/content/locales/pt-BR/toolkit-editors-canvases.mdx +17 -0
  36. package/corpus/core/docs/content/locales/zh-CN/agent-native-toolkit.mdx +69 -62
  37. package/corpus/core/docs/content/locales/zh-CN/toolkit-capability-packages.mdx +21 -0
  38. package/corpus/core/docs/content/locales/zh-CN/toolkit-context-knowledge.mdx +12 -0
  39. package/corpus/core/docs/content/locales/zh-CN/toolkit-editors-canvases.mdx +17 -0
  40. package/corpus/core/docs/content/locales/zh-TW/agent-native-toolkit.mdx +69 -62
  41. package/corpus/core/docs/content/locales/zh-TW/toolkit-capability-packages.mdx +21 -0
  42. package/corpus/core/docs/content/locales/zh-TW/toolkit-context-knowledge.mdx +12 -0
  43. package/corpus/core/docs/content/locales/zh-TW/toolkit-editors-canvases.mdx +17 -0
  44. package/corpus/core/docs/content/toolkit-capability-packages.mdx +52 -0
  45. package/corpus/core/docs/content/toolkit-context-knowledge.mdx +46 -0
  46. package/corpus/core/docs/content/toolkit-editors-canvases.mdx +55 -0
  47. package/corpus/core/package.json +35 -34
  48. package/corpus/core/src/cli/create.ts +57 -15
  49. package/corpus/core/src/cli/package-lifecycle.ts +2 -0
  50. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +2 -0
  51. package/corpus/core/src/client/context-xray/ContextMeter.tsx +31 -111
  52. package/corpus/core/src/client/context-xray/ContextSegmentRow.tsx +8 -111
  53. package/corpus/core/src/client/context-xray/ContextTreemap.tsx +6 -111
  54. package/corpus/core/src/client/context-xray/ContextXRayPanel.tsx +31 -391
  55. package/corpus/core/src/client/context-xray/SegmentProvenancePopover.tsx +4 -52
  56. package/corpus/core/src/client/context-xray/format.ts +0 -33
  57. package/corpus/core/src/client/require-session.tsx +19 -3
  58. package/corpus/core/src/client/rich-markdown-editor/index.ts +42 -57
  59. package/corpus/core/src/client/rich-markdown-editor/uploadEditorImage.ts +2 -1
  60. package/corpus/core/src/client/use-action.ts +145 -2
  61. package/corpus/core/src/client/use-session.ts +79 -48
  62. package/corpus/core/src/client/visual-style-controls.tsx +1 -1088
  63. package/corpus/core/src/collab/agent-identity.ts +5 -22
  64. package/corpus/core/src/collab/client.ts +1 -53
  65. package/corpus/core/src/db/client.ts +13 -7
  66. package/corpus/core/src/db/create-get-db.ts +20 -13
  67. package/corpus/core/src/db/request-telemetry.ts +154 -0
  68. package/corpus/core/src/integrations/index.ts +1 -0
  69. package/corpus/core/src/integrations/plugin.ts +9 -3
  70. package/corpus/core/src/integrations/remote-push-delivery-job.ts +48 -0
  71. package/corpus/core/src/integrations/remote-push-delivery.ts +370 -0
  72. package/corpus/core/src/integrations/remote-push-store.ts +275 -26
  73. package/corpus/core/src/server/better-auth-instance.ts +11 -3
  74. package/corpus/core/src/server/core-routes-plugin.ts +36 -14
  75. package/corpus/core/src/server/framework-request-handler.ts +11 -1
  76. package/corpus/core/src/server/http-response-telemetry.ts +233 -31
  77. package/corpus/core/src/styles/rich-markdown-editor.css +1 -510
  78. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +19 -0
  79. package/corpus/core/src/testing.ts +1 -1
  80. package/corpus/core/src/vite/client.ts +3 -0
  81. package/corpus/templates/clips/actions/finalize-recording.ts +3 -1
  82. package/corpus/templates/clips/actions/set-mobile-capture-state.ts +4 -1
  83. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -6
  84. package/corpus/templates/clips/changelog/2026-07-18-new-recording-is-now-emphasized-as-the-primary-action-in-the.md +6 -0
  85. package/corpus/templates/clips/changelog/2026-07-18-recordings-now-remain-safely-recoverable-until-the-stored-me.md +6 -0
  86. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +5 -3
  87. package/corpus/templates/content/app/components/editor/extensions/DragHandle.tsx +4 -4
  88. package/corpus/templates/content/package.json +25 -25
  89. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
  90. package/corpus/templates/design/package.json +1 -1
  91. package/corpus/templates/mail/package.json +9 -9
  92. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +2 -0
  93. package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +8 -8
  94. package/corpus/templates/plan/app/components/editor/planSlashCommands.ts +6 -6
  95. package/corpus/templates/plan/app/components/plan/PlanImageNode.tsx +4 -7
  96. package/corpus/templates/plan/app/components/plan/PlanMarkdownEditor.tsx +6 -4
  97. package/corpus/templates/plan/app/components/plan/PlanVisualSurface.tsx +1 -1
  98. package/corpus/templates/plan/changelog/2026-07-18-visual-plans-now-open-on-wireframes-by-default-when-a-protot.md +6 -0
  99. package/corpus/templates/plan/package.json +3 -3
  100. package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +2 -2
  101. package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +2 -2
  102. package/corpus/templates/slides/package.json +13 -13
  103. package/corpus/templates/tasks/AGENTS.md +3 -0
  104. package/corpus/templates/tasks/actions/render-task-list-inline.ts +202 -0
  105. package/corpus/templates/tasks/changelog/2026-07-18-task-lists-can-now-appear-as-interactive-widgets-inline-in-c.md +6 -0
  106. package/corpus/templates/tasks/docs/features/f8-chat.mdx +2 -0
  107. package/corpus/templates/tasks/server/plugins/agent-chat.ts +2 -0
  108. package/dist/catalog.json +39 -1
  109. package/dist/cli/create.d.ts +10 -1
  110. package/dist/cli/create.d.ts.map +1 -1
  111. package/dist/cli/create.js +49 -16
  112. package/dist/cli/create.js.map +1 -1
  113. package/dist/cli/package-lifecycle.d.ts.map +1 -1
  114. package/dist/cli/package-lifecycle.js +2 -0
  115. package/dist/cli/package-lifecycle.js.map +1 -1
  116. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  117. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  118. package/dist/cli/skills-content/visual-plan-skill.js +2 -0
  119. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  120. package/dist/client/context-xray/ContextMeter.d.ts.map +1 -1
  121. package/dist/client/context-xray/ContextMeter.js +8 -23
  122. package/dist/client/context-xray/ContextMeter.js.map +1 -1
  123. package/dist/client/context-xray/ContextSegmentRow.d.ts.map +1 -1
  124. package/dist/client/context-xray/ContextSegmentRow.js +3 -19
  125. package/dist/client/context-xray/ContextSegmentRow.js.map +1 -1
  126. package/dist/client/context-xray/ContextTreemap.d.ts.map +1 -1
  127. package/dist/client/context-xray/ContextTreemap.js +3 -54
  128. package/dist/client/context-xray/ContextTreemap.js.map +1 -1
  129. package/dist/client/context-xray/ContextXRayPanel.d.ts.map +1 -1
  130. package/dist/client/context-xray/ContextXRayPanel.js +21 -163
  131. package/dist/client/context-xray/ContextXRayPanel.js.map +1 -1
  132. package/dist/client/context-xray/SegmentProvenancePopover.d.ts.map +1 -1
  133. package/dist/client/context-xray/SegmentProvenancePopover.js +3 -4
  134. package/dist/client/context-xray/SegmentProvenancePopover.js.map +1 -1
  135. package/dist/client/context-xray/format.d.ts +0 -4
  136. package/dist/client/context-xray/format.d.ts.map +1 -1
  137. package/dist/client/context-xray/format.js +0 -49
  138. package/dist/client/context-xray/format.js.map +1 -1
  139. package/dist/client/require-session.d.ts.map +1 -1
  140. package/dist/client/require-session.js +6 -3
  141. package/dist/client/require-session.js.map +1 -1
  142. package/dist/client/rich-markdown-editor/index.d.ts +1 -12
  143. package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
  144. package/dist/client/rich-markdown-editor/index.js +1 -12
  145. package/dist/client/rich-markdown-editor/index.js.map +1 -1
  146. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts +1 -1
  147. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts.map +1 -1
  148. package/dist/client/rich-markdown-editor/uploadEditorImage.js.map +1 -1
  149. package/dist/client/use-action.d.ts.map +1 -1
  150. package/dist/client/use-action.js +117 -1
  151. package/dist/client/use-action.js.map +1 -1
  152. package/dist/client/use-session.d.ts.map +1 -1
  153. package/dist/client/use-session.js +72 -50
  154. package/dist/client/use-session.js.map +1 -1
  155. package/dist/client/visual-style-controls.d.ts +1 -89
  156. package/dist/client/visual-style-controls.d.ts.map +1 -1
  157. package/dist/client/visual-style-controls.js +1 -498
  158. package/dist/client/visual-style-controls.js.map +1 -1
  159. package/dist/collab/agent-identity.d.ts +1 -14
  160. package/dist/collab/agent-identity.d.ts.map +1 -1
  161. package/dist/collab/agent-identity.js +1 -13
  162. package/dist/collab/agent-identity.js.map +1 -1
  163. package/dist/collab/awareness.d.ts +2 -2
  164. package/dist/collab/awareness.d.ts.map +1 -1
  165. package/dist/collab/client.d.ts +1 -19
  166. package/dist/collab/client.d.ts.map +1 -1
  167. package/dist/collab/client.js +1 -53
  168. package/dist/collab/client.js.map +1 -1
  169. package/dist/collab/struct-routes.d.ts +1 -1
  170. package/dist/db/client.d.ts.map +1 -1
  171. package/dist/db/client.js +7 -1
  172. package/dist/db/client.js.map +1 -1
  173. package/dist/db/create-get-db.d.ts +3 -6
  174. package/dist/db/create-get-db.d.ts.map +1 -1
  175. package/dist/db/create-get-db.js +9 -2
  176. package/dist/db/create-get-db.js.map +1 -1
  177. package/dist/db/request-telemetry.d.ts +23 -0
  178. package/dist/db/request-telemetry.d.ts.map +1 -0
  179. package/dist/db/request-telemetry.js +95 -0
  180. package/dist/db/request-telemetry.js.map +1 -0
  181. package/dist/integrations/index.d.ts +1 -0
  182. package/dist/integrations/index.d.ts.map +1 -1
  183. package/dist/integrations/index.js +1 -0
  184. package/dist/integrations/index.js.map +1 -1
  185. package/dist/integrations/plugin.d.ts.map +1 -1
  186. package/dist/integrations/plugin.js +8 -3
  187. package/dist/integrations/plugin.js.map +1 -1
  188. package/dist/integrations/remote-push-delivery-job.d.ts +4 -0
  189. package/dist/integrations/remote-push-delivery-job.d.ts.map +1 -0
  190. package/dist/integrations/remote-push-delivery-job.js +44 -0
  191. package/dist/integrations/remote-push-delivery-job.js.map +1 -0
  192. package/dist/integrations/remote-push-delivery.d.ts +11 -0
  193. package/dist/integrations/remote-push-delivery.d.ts.map +1 -0
  194. package/dist/integrations/remote-push-delivery.js +265 -0
  195. package/dist/integrations/remote-push-delivery.js.map +1 -0
  196. package/dist/integrations/remote-push-store.d.ts +33 -0
  197. package/dist/integrations/remote-push-store.d.ts.map +1 -1
  198. package/dist/integrations/remote-push-store.js +195 -26
  199. package/dist/integrations/remote-push-store.js.map +1 -1
  200. package/dist/notifications/routes.d.ts +3 -3
  201. package/dist/progress/routes.d.ts +1 -1
  202. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  203. package/dist/resources/handlers.d.ts +3 -3
  204. package/dist/secrets/routes.d.ts +9 -9
  205. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  206. package/dist/server/better-auth-instance.js +7 -3
  207. package/dist/server/better-auth-instance.js.map +1 -1
  208. package/dist/server/core-routes-plugin.d.ts +8 -0
  209. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  210. package/dist/server/core-routes-plugin.js +23 -8
  211. package/dist/server/core-routes-plugin.js.map +1 -1
  212. package/dist/server/framework-request-handler.d.ts.map +1 -1
  213. package/dist/server/framework-request-handler.js +9 -1
  214. package/dist/server/framework-request-handler.js.map +1 -1
  215. package/dist/server/http-response-telemetry.d.ts +3 -2
  216. package/dist/server/http-response-telemetry.d.ts.map +1 -1
  217. package/dist/server/http-response-telemetry.js +160 -27
  218. package/dist/server/http-response-telemetry.js.map +1 -1
  219. package/dist/server/transcribe-voice.d.ts +1 -1
  220. package/dist/styles/rich-markdown-editor.css +1 -510
  221. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +19 -0
  222. package/dist/testing.d.ts +1 -1
  223. package/dist/testing.d.ts.map +1 -1
  224. package/dist/testing.js +1 -1
  225. package/dist/testing.js.map +1 -1
  226. package/dist/vite/client.d.ts.map +1 -1
  227. package/dist/vite/client.js +3 -0
  228. package/dist/vite/client.js.map +1 -1
  229. package/docs/content/agent-native-toolkit.mdx +46 -13
  230. package/docs/content/locales/ar-SA/agent-native-toolkit.mdx +79 -55
  231. package/docs/content/locales/ar-SA/toolkit-capability-packages.mdx +21 -0
  232. package/docs/content/locales/ar-SA/toolkit-context-knowledge.mdx +12 -0
  233. package/docs/content/locales/ar-SA/toolkit-editors-canvases.mdx +17 -0
  234. package/docs/content/locales/de-DE/agent-native-toolkit.mdx +82 -54
  235. package/docs/content/locales/de-DE/toolkit-capability-packages.mdx +21 -0
  236. package/docs/content/locales/de-DE/toolkit-context-knowledge.mdx +12 -0
  237. package/docs/content/locales/de-DE/toolkit-editors-canvases.mdx +17 -0
  238. package/docs/content/locales/es-ES/agent-native-toolkit.mdx +81 -52
  239. package/docs/content/locales/es-ES/toolkit-capability-packages.mdx +21 -0
  240. package/docs/content/locales/es-ES/toolkit-context-knowledge.mdx +12 -0
  241. package/docs/content/locales/es-ES/toolkit-editors-canvases.mdx +21 -0
  242. package/docs/content/locales/fr-FR/agent-native-toolkit.mdx +84 -54
  243. package/docs/content/locales/fr-FR/toolkit-capability-packages.mdx +21 -0
  244. package/docs/content/locales/fr-FR/toolkit-context-knowledge.mdx +12 -0
  245. package/docs/content/locales/fr-FR/toolkit-editors-canvases.mdx +21 -0
  246. package/docs/content/locales/hi-IN/agent-native-toolkit.mdx +69 -62
  247. package/docs/content/locales/hi-IN/toolkit-capability-packages.mdx +21 -0
  248. package/docs/content/locales/hi-IN/toolkit-context-knowledge.mdx +12 -0
  249. package/docs/content/locales/hi-IN/toolkit-editors-canvases.mdx +17 -0
  250. package/docs/content/locales/ja-JP/agent-native-toolkit.mdx +69 -62
  251. package/docs/content/locales/ja-JP/toolkit-capability-packages.mdx +21 -0
  252. package/docs/content/locales/ja-JP/toolkit-context-knowledge.mdx +12 -0
  253. package/docs/content/locales/ja-JP/toolkit-editors-canvases.mdx +17 -0
  254. package/docs/content/locales/ko-KR/agent-native-toolkit.mdx +69 -62
  255. package/docs/content/locales/ko-KR/toolkit-capability-packages.mdx +21 -0
  256. package/docs/content/locales/ko-KR/toolkit-context-knowledge.mdx +12 -0
  257. package/docs/content/locales/ko-KR/toolkit-editors-canvases.mdx +17 -0
  258. package/docs/content/locales/pt-BR/agent-native-toolkit.mdx +82 -54
  259. package/docs/content/locales/pt-BR/toolkit-capability-packages.mdx +21 -0
  260. package/docs/content/locales/pt-BR/toolkit-context-knowledge.mdx +12 -0
  261. package/docs/content/locales/pt-BR/toolkit-editors-canvases.mdx +17 -0
  262. package/docs/content/locales/zh-CN/agent-native-toolkit.mdx +69 -62
  263. package/docs/content/locales/zh-CN/toolkit-capability-packages.mdx +21 -0
  264. package/docs/content/locales/zh-CN/toolkit-context-knowledge.mdx +12 -0
  265. package/docs/content/locales/zh-CN/toolkit-editors-canvases.mdx +17 -0
  266. package/docs/content/locales/zh-TW/agent-native-toolkit.mdx +69 -62
  267. package/docs/content/locales/zh-TW/toolkit-capability-packages.mdx +21 -0
  268. package/docs/content/locales/zh-TW/toolkit-context-knowledge.mdx +12 -0
  269. package/docs/content/locales/zh-TW/toolkit-editors-canvases.mdx +17 -0
  270. package/docs/content/toolkit-capability-packages.mdx +52 -0
  271. package/docs/content/toolkit-context-knowledge.mdx +46 -0
  272. package/docs/content/toolkit-editors-canvases.mdx +55 -0
  273. package/package.json +27 -26
  274. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +19 -0
  275. package/corpus/core/src/client/rich-markdown-editor/BubbleToolbar.tsx +0 -253
  276. package/corpus/core/src/client/rich-markdown-editor/CodeBlockNode.tsx +0 -258
  277. package/corpus/core/src/client/rich-markdown-editor/DragHandle.ts +0 -1437
  278. package/corpus/core/src/client/rich-markdown-editor/ImageExtension.ts +0 -306
  279. package/corpus/core/src/client/rich-markdown-editor/RichMarkdownEditor.tsx +0 -80
  280. package/corpus/core/src/client/rich-markdown-editor/RunId.ts +0 -61
  281. package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +0 -321
  282. package/corpus/core/src/client/rich-markdown-editor/SlashCommandMenu.tsx +0 -310
  283. package/corpus/core/src/client/rich-markdown-editor/extensions.ts +0 -402
  284. package/corpus/core/src/client/rich-markdown-editor/gfmDoc.ts +0 -92
  285. package/corpus/core/src/client/rich-markdown-editor/surgical-apply.ts +0 -192
  286. package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +0 -590
  287. package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts +0 -37
  288. package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +0 -1
  289. package/dist/client/rich-markdown-editor/BubbleToolbar.js +0 -171
  290. package/dist/client/rich-markdown-editor/BubbleToolbar.js.map +0 -1
  291. package/dist/client/rich-markdown-editor/CodeBlockNode.d.ts +0 -49
  292. package/dist/client/rich-markdown-editor/CodeBlockNode.d.ts.map +0 -1
  293. package/dist/client/rich-markdown-editor/CodeBlockNode.js +0 -127
  294. package/dist/client/rich-markdown-editor/CodeBlockNode.js.map +0 -1
  295. package/dist/client/rich-markdown-editor/DragHandle.d.ts +0 -97
  296. package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +0 -1
  297. package/dist/client/rich-markdown-editor/DragHandle.js +0 -1066
  298. package/dist/client/rich-markdown-editor/DragHandle.js.map +0 -1
  299. package/dist/client/rich-markdown-editor/ImageExtension.d.ts +0 -63
  300. package/dist/client/rich-markdown-editor/ImageExtension.d.ts.map +0 -1
  301. package/dist/client/rich-markdown-editor/ImageExtension.js +0 -243
  302. package/dist/client/rich-markdown-editor/ImageExtension.js.map +0 -1
  303. package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts +0 -51
  304. package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts.map +0 -1
  305. package/dist/client/rich-markdown-editor/RichMarkdownEditor.js +0 -37
  306. package/dist/client/rich-markdown-editor/RichMarkdownEditor.js.map +0 -1
  307. package/dist/client/rich-markdown-editor/RunId.d.ts +0 -28
  308. package/dist/client/rich-markdown-editor/RunId.d.ts.map +0 -1
  309. package/dist/client/rich-markdown-editor/RunId.js +0 -60
  310. package/dist/client/rich-markdown-editor/RunId.js.map +0 -1
  311. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +0 -110
  312. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +0 -1
  313. package/dist/client/rich-markdown-editor/SharedRichEditor.js +0 -144
  314. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +0 -1
  315. package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +0 -41
  316. package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +0 -1
  317. package/dist/client/rich-markdown-editor/SlashCommandMenu.js +0 -221
  318. package/dist/client/rich-markdown-editor/SlashCommandMenu.js.map +0 -1
  319. package/dist/client/rich-markdown-editor/extensions.d.ts +0 -178
  320. package/dist/client/rich-markdown-editor/extensions.d.ts.map +0 -1
  321. package/dist/client/rich-markdown-editor/extensions.js +0 -224
  322. package/dist/client/rich-markdown-editor/extensions.js.map +0 -1
  323. package/dist/client/rich-markdown-editor/gfmDoc.d.ts +0 -24
  324. package/dist/client/rich-markdown-editor/gfmDoc.d.ts.map +0 -1
  325. package/dist/client/rich-markdown-editor/gfmDoc.js +0 -83
  326. package/dist/client/rich-markdown-editor/gfmDoc.js.map +0 -1
  327. package/dist/client/rich-markdown-editor/surgical-apply.d.ts +0 -66
  328. package/dist/client/rich-markdown-editor/surgical-apply.d.ts.map +0 -1
  329. package/dist/client/rich-markdown-editor/surgical-apply.js +0 -147
  330. package/dist/client/rich-markdown-editor/surgical-apply.js.map +0 -1
  331. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +0 -110
  332. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +0 -1
  333. package/dist/client/rich-markdown-editor/useCollabReconcile.js +0 -441
  334. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { getDbExec, isPostgres, intType, retryOnDdlRace, } from "../db/client.js";
2
- import { ensureTableExists, ensureIndexExists } from "../db/ddl-guard.js";
2
+ import { ensureColumnExists, ensureIndexExists, ensureTableExists, } from "../db/ddl-guard.js";
3
+ import { isDuplicateColumnError } from "../db/migrations.js";
3
4
  let _initPromise;
4
5
  // Build the CREATE SQL lazily (not at module scope) so intType() runs at
5
6
  // RUNTIME, not import time — a module-scope call breaks any consumer whose
@@ -33,6 +34,10 @@ function buildCreateNotificationsSql() {
33
34
  payload_json TEXT NOT NULL,
34
35
  status TEXT NOT NULL,
35
36
  attempts ${intType()} NOT NULL DEFAULT 0,
37
+ provider_ticket_id TEXT,
38
+ next_attempt_at ${intType()} NOT NULL DEFAULT 0,
39
+ last_error TEXT,
40
+ delivered_at ${intType()},
36
41
  created_at ${intType()} NOT NULL,
37
42
  updated_at ${intType()} NOT NULL
38
43
  )
@@ -51,6 +56,11 @@ async function ensureTables() {
51
56
  await ensureIndexExists("idx_remote_push_owner", `CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`);
52
57
  await ensureTableExists("integration_remote_push_notifications", createNotificationsSql);
53
58
  await ensureIndexExists("idx_remote_push_notifications_owner", `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`);
59
+ await ensureColumnExists("integration_remote_push_notifications", "provider_ticket_id", `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS provider_ticket_id TEXT`);
60
+ await ensureColumnExists("integration_remote_push_notifications", "next_attempt_at", `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS next_attempt_at ${intType()} NOT NULL DEFAULT 0`);
61
+ await ensureColumnExists("integration_remote_push_notifications", "last_error", `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS last_error TEXT`);
62
+ await ensureColumnExists("integration_remote_push_notifications", "delivered_at", `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS delivered_at ${intType()}`);
63
+ await ensureIndexExists("idx_remote_push_notifications_delivery", `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_delivery ON integration_remote_push_notifications(status, next_attempt_at, updated_at)`);
54
64
  return;
55
65
  }
56
66
  // SQLite (local dev): keep existing behavior
@@ -59,6 +69,11 @@ async function ensureTables() {
59
69
  await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`));
60
70
  await retryOnDdlRace(() => client.execute(createNotificationsSql));
61
71
  await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`));
72
+ await addNotificationColumnIfMissing("provider_ticket_id", "TEXT");
73
+ await addNotificationColumnIfMissing("next_attempt_at", `${intType()} NOT NULL DEFAULT 0`);
74
+ await addNotificationColumnIfMissing("last_error", "TEXT");
75
+ await addNotificationColumnIfMissing("delivered_at", intType());
76
+ await retryOnDdlRace(() => client.execute(`CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_delivery ON integration_remote_push_notifications(status, next_attempt_at, updated_at)`));
62
77
  })().catch((err) => {
63
78
  // Retry init on the next call after a failed startup.
64
79
  _initPromise = undefined;
@@ -67,6 +82,15 @@ async function ensureTables() {
67
82
  }
68
83
  return _initPromise;
69
84
  }
85
+ async function addNotificationColumnIfMissing(name, definition) {
86
+ try {
87
+ await retryOnDdlRace(() => getDbExec().execute(`ALTER TABLE integration_remote_push_notifications ADD COLUMN ${name} ${definition}`));
88
+ }
89
+ catch (error) {
90
+ if (!isDuplicateColumnError(error))
91
+ throw error;
92
+ }
93
+ }
70
94
  function rowToRegistration(row) {
71
95
  return {
72
96
  id: row.id,
@@ -85,13 +109,17 @@ function rowToRegistration(row) {
85
109
  };
86
110
  }
87
111
  function rowToNotification(row) {
112
+ const storedStatus = String(row.status ?? "pending");
113
+ const status = storedStatus === "delivered" || storedStatus === "failed"
114
+ ? storedStatus
115
+ : "pending";
88
116
  return {
89
117
  id: row.id,
90
118
  ownerEmail: row.owner_email,
91
119
  orgId: row.org_id ?? null,
92
120
  registrationId: row.registration_id,
93
121
  payload: parseJson(row.payload_json, null),
94
- status: row.status,
122
+ status,
95
123
  attempts: Number(row.attempts ?? 0),
96
124
  createdAt: Number(row.created_at ?? 0),
97
125
  updatedAt: Number(row.updated_at ?? 0),
@@ -235,42 +263,47 @@ export async function queueRemotePushNotifications(input) {
235
263
  orgId: input.orgId ?? null,
236
264
  limit: 100,
237
265
  });
266
+ if (registrations.length === 0)
267
+ return { queued: 0 };
238
268
  const client = getDbExec();
239
269
  const now = Date.now();
240
- let queued = 0;
241
- for (const registration of registrations) {
242
- const id = `remote-push-notification-${now}-${randomHex(8)}`;
243
- const result = await client.execute({
244
- sql: `INSERT INTO integration_remote_push_notifications
270
+ const payload = JSON.stringify(input.payload ?? null);
271
+ const values = registrations.map(() => "(?, ?, ?, ?, ?, 'pending', 0, ?, ?, ?)");
272
+ const args = registrations.flatMap((registration) => [
273
+ `remote-push-notification-${now}-${randomHex(8)}`,
274
+ input.ownerEmail,
275
+ input.orgId ?? null,
276
+ registration.id,
277
+ payload,
278
+ now,
279
+ now,
280
+ now,
281
+ ]);
282
+ const result = await client.execute({
283
+ sql: `INSERT INTO integration_remote_push_notifications
245
284
  (id, owner_email, org_id, registration_id, payload_json, status,
246
- attempts, created_at, updated_at)
247
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
248
- args: [
249
- id,
250
- input.ownerEmail,
251
- input.orgId ?? null,
252
- registration.id,
253
- JSON.stringify(input.payload ?? null),
254
- "pending",
255
- 0,
256
- now,
257
- now,
258
- ],
259
- });
260
- queued += result.rowsAffected ?? result.rowCount ?? 0;
261
- }
262
- return { queued };
285
+ attempts, next_attempt_at, created_at, updated_at)
286
+ VALUES ${values.join(", ")}`,
287
+ args,
288
+ });
289
+ return {
290
+ queued: result.rowsAffected ?? result.rowCount ?? 0,
291
+ };
263
292
  }
264
293
  export async function listRemotePushNotificationsForOwner(input) {
265
294
  await ensureTables();
266
295
  const limit = Math.max(1, Math.min(input.limit ?? 50, 100));
267
- const statusClause = input.status ? " AND status = ?" : "";
296
+ const statusClause = input.status
297
+ ? input.status === "pending"
298
+ ? " AND status IN ('pending', 'sending', 'sent', 'checking')"
299
+ : " AND status = ?"
300
+ : "";
268
301
  const args = [
269
302
  input.ownerEmail,
270
303
  input.orgId ?? null,
271
304
  input.orgId ?? null,
272
305
  ];
273
- if (input.status)
306
+ if (input.status && input.status !== "pending")
274
307
  args.push(input.status);
275
308
  args.push(limit);
276
309
  const { rows } = await getDbExec().execute({
@@ -283,6 +316,142 @@ export async function listRemotePushNotificationsForOwner(input) {
283
316
  });
284
317
  return rows.map((row) => rowToNotification(row));
285
318
  }
319
+ export async function claimNextRemotePushDelivery(input) {
320
+ await ensureTables();
321
+ const client = getDbExec();
322
+ const now = input?.now ?? Date.now();
323
+ const staleBefore = now - Math.max(30_000, input?.staleAfterMs ?? 120_000);
324
+ const { rows } = await client.execute({
325
+ sql: `SELECT n.id, n.registration_id, n.payload_json, n.status, n.attempts,
326
+ n.provider_ticket_id, n.updated_at, r.provider, r.token
327
+ FROM integration_remote_push_notifications n
328
+ INNER JOIN integration_remote_push_registrations r
329
+ ON r.id = n.registration_id
330
+ WHERE r.status = 'active'
331
+ AND (
332
+ (n.status IN ('pending', 'sent') AND n.next_attempt_at <= ?)
333
+ OR (n.status IN ('sending', 'checking') AND n.updated_at <= ?)
334
+ )
335
+ ORDER BY n.created_at ASC
336
+ LIMIT 1`,
337
+ args: [now, staleBefore],
338
+ });
339
+ const row = rows[0];
340
+ if (!row)
341
+ return null;
342
+ const previousStatus = String(row.status ?? "pending");
343
+ const providerTicketId = sanitizeString(row.provider_ticket_id, 200);
344
+ const phase = (previousStatus === "sent" || previousStatus === "checking") &&
345
+ providerTicketId
346
+ ? "receipt"
347
+ : "send";
348
+ const claimedStatus = phase === "receipt" ? "checking" : "sending";
349
+ const result = await client.execute({
350
+ sql: `UPDATE integration_remote_push_notifications
351
+ SET status = ?, attempts = attempts + 1, updated_at = ?
352
+ WHERE id = ? AND status = ? AND updated_at = ?`,
353
+ args: [
354
+ claimedStatus,
355
+ now,
356
+ row.id,
357
+ previousStatus,
358
+ Number(row.updated_at),
359
+ ],
360
+ });
361
+ if ((result.rowsAffected ?? result.rowCount ?? 0) !== 1)
362
+ return null;
363
+ return {
364
+ id: row.id,
365
+ registrationId: row.registration_id,
366
+ provider: String(row.provider ?? "unknown"),
367
+ token: row.token,
368
+ payload: parseJson(row.payload_json, null),
369
+ phase,
370
+ providerTicketId,
371
+ attempts: Number(row.attempts ?? 0) + 1,
372
+ };
373
+ }
374
+ export async function markRemotePushTicketAccepted(input) {
375
+ await ensureTables();
376
+ const now = Date.now();
377
+ const result = await getDbExec().execute({
378
+ sql: `UPDATE integration_remote_push_notifications
379
+ SET status = 'sent', provider_ticket_id = ?, next_attempt_at = ?,
380
+ last_error = NULL, updated_at = ?
381
+ WHERE id = ? AND status = 'sending'`,
382
+ args: [input.providerTicketId, input.checkAfter, now, input.id],
383
+ });
384
+ return (result.rowsAffected ?? result.rowCount ?? 0) === 1;
385
+ }
386
+ export async function markRemotePushDelivered(id) {
387
+ await ensureTables();
388
+ const now = Date.now();
389
+ const result = await getDbExec().execute({
390
+ sql: `UPDATE integration_remote_push_notifications
391
+ SET status = 'delivered', last_error = NULL, delivered_at = ?,
392
+ updated_at = ?
393
+ WHERE id = ? AND status = 'checking'`,
394
+ args: [now, now, id],
395
+ });
396
+ return (result.rowsAffected ?? result.rowCount ?? 0) === 1;
397
+ }
398
+ export async function retryRemotePushDelivery(input) {
399
+ await ensureTables();
400
+ const currentStatus = input.phase === "receipt" ? "checking" : "sending";
401
+ const retryStatus = input.phase === "receipt" && !input.resend ? "sent" : "pending";
402
+ const clearTicketClause = input.resend ? ", provider_ticket_id = NULL" : "";
403
+ const result = await getDbExec().execute({
404
+ sql: `UPDATE integration_remote_push_notifications
405
+ SET status = ?, next_attempt_at = ?, last_error = ?${clearTicketClause},
406
+ updated_at = ?
407
+ WHERE id = ? AND status = ?`,
408
+ args: [
409
+ retryStatus,
410
+ input.retryAt,
411
+ sanitizeString(input.errorCode, 160) ?? "temporary_error",
412
+ Date.now(),
413
+ input.id,
414
+ currentStatus,
415
+ ],
416
+ });
417
+ return (result.rowsAffected ?? result.rowCount ?? 0) === 1;
418
+ }
419
+ export async function failRemotePushDelivery(input) {
420
+ await ensureTables();
421
+ const currentStatus = input.phase === "receipt" ? "checking" : "sending";
422
+ const result = await getDbExec().execute({
423
+ sql: `UPDATE integration_remote_push_notifications
424
+ SET status = 'failed', last_error = ?, updated_at = ?
425
+ WHERE id = ? AND status = ?`,
426
+ args: [
427
+ sanitizeString(input.errorCode, 160) ?? "delivery_failed",
428
+ Date.now(),
429
+ input.id,
430
+ currentStatus,
431
+ ],
432
+ });
433
+ return (result.rowsAffected ?? result.rowCount ?? 0) === 1;
434
+ }
435
+ export async function deactivateRemotePushRegistration(registrationId) {
436
+ await ensureTables();
437
+ const client = getDbExec();
438
+ const now = Date.now();
439
+ const result = await client.execute({
440
+ sql: `UPDATE integration_remote_push_registrations
441
+ SET status = 'inactive', updated_at = ?
442
+ WHERE id = ? AND status = 'active'`,
443
+ args: [now, registrationId],
444
+ });
445
+ await client.execute({
446
+ sql: `UPDATE integration_remote_push_notifications
447
+ SET status = 'failed', last_error = 'registration_inactive',
448
+ updated_at = ?
449
+ WHERE registration_id = ?
450
+ AND status IN ('pending', 'sending', 'sent', 'checking')`,
451
+ args: [now, registrationId],
452
+ });
453
+ return (result.rowsAffected ?? result.rowCount ?? 0) === 1;
454
+ }
286
455
  async function getRemotePushRegistrationByTokenHash(tokenHash) {
287
456
  const { rows } = await getDbExec().execute({
288
457
  sql: `SELECT * FROM integration_remote_push_registrations
@@ -1 +1 @@
1
- {"version":3,"file":"remote-push-store.js","sourceRoot":"","sources":["../../src/integrations/remote-push-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n isPostgres,\n intType,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport { ensureTableExists, ensureIndexExists } from \"../db/ddl-guard.js\";\nimport type {\n PublicRemotePushRegistration,\n RemotePushNotification,\n RemotePushRegistration,\n} from \"./remote-types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n// Build the CREATE SQL lazily (not at module scope) so intType() runs at\n// RUNTIME, not import time — a module-scope call breaks any consumer whose\n// db/client mock doesn't stub intType (e.g. db-admin specs).\nfunction buildCreateRegistrationsSql(): string {\n return `\n CREATE TABLE IF NOT EXISTS integration_remote_push_registrations (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n provider TEXT NOT NULL,\n platform TEXT,\n client_device_id TEXT,\n label TEXT,\n token TEXT NOT NULL,\n token_hash TEXT NOT NULL,\n status TEXT NOT NULL,\n last_seen_at ${intType()},\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n`;\n}\n\nfunction buildCreateNotificationsSql(): string {\n return `\n CREATE TABLE IF NOT EXISTS integration_remote_push_notifications (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n registration_id TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n`;\n}\n\nasync function ensureTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createRegistrationsSql = buildCreateRegistrationsSql();\n const createNotificationsSql = buildCreateNotificationsSql();\n if (isPostgres()) {\n // PG guard: probe via information_schema, only issue DDL if missing, bounded lock_timeout\n await ensureTableExists(\n \"integration_remote_push_registrations\",\n createRegistrationsSql,\n );\n await ensureIndexExists(\n \"idx_remote_push_token_hash\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_push_token_hash ON integration_remote_push_registrations(token_hash)`,\n );\n await ensureIndexExists(\n \"idx_remote_push_owner\",\n `CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`,\n );\n await ensureTableExists(\n \"integration_remote_push_notifications\",\n createNotificationsSql,\n );\n await ensureIndexExists(\n \"idx_remote_push_notifications_owner\",\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`,\n );\n return;\n }\n // SQLite (local dev): keep existing behavior\n await retryOnDdlRace(() => client.execute(createRegistrationsSql));\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_push_token_hash ON integration_remote_push_registrations(token_hash)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`,\n ),\n );\n\n await retryOnDdlRace(() => client.execute(createNotificationsSql));\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`,\n ),\n );\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nfunction rowToRegistration(\n row: Record<string, unknown>,\n): RemotePushRegistration {\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n provider: row.provider as string,\n platform: (row.platform as string | null) ?? null,\n clientDeviceId: (row.client_device_id as string | null) ?? null,\n label: (row.label as string | null) ?? null,\n token: row.token as string,\n tokenHash: row.token_hash as string,\n status: row.status as RemotePushRegistration[\"status\"],\n lastSeenAt:\n row.last_seen_at == null ? null : Number(row.last_seen_at as number),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nfunction rowToNotification(\n row: Record<string, unknown>,\n): RemotePushNotification {\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n registrationId: row.registration_id as string,\n payload: parseJson(row.payload_json, null),\n status: row.status as RemotePushNotification[\"status\"],\n attempts: Number(row.attempts ?? 0),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nexport function toPublicRemotePushRegistration(\n registration: RemotePushRegistration,\n): PublicRemotePushRegistration {\n return {\n id: registration.id,\n ownerEmail: registration.ownerEmail,\n orgId: registration.orgId,\n provider: registration.provider,\n platform: registration.platform,\n clientDeviceId: registration.clientDeviceId,\n label: registration.label,\n status: registration.status,\n lastSeenAt: registration.lastSeenAt,\n createdAt: registration.createdAt,\n updatedAt: registration.updatedAt,\n };\n}\n\nexport async function upsertRemotePushRegistration(input: {\n ownerEmail: string;\n orgId?: string | null;\n provider: string;\n token: string;\n platform?: string | null;\n clientDeviceId?: string | null;\n label?: string | null;\n}): Promise<RemotePushRegistration> {\n await ensureTables();\n const client = getDbExec();\n const now = Date.now();\n const tokenHash = await hashToken(input.token);\n const provider = sanitizeString(input.provider, 80) ?? \"unknown\";\n const platform = sanitizeString(input.platform, 80);\n const clientDeviceId = sanitizeString(input.clientDeviceId, 200);\n const label = sanitizeString(input.label, 200);\n\n const existing = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (existing) {\n await client.execute({\n sql: `UPDATE integration_remote_push_registrations\n SET owner_email = ?,\n org_id = ?,\n provider = ?,\n platform = ?,\n client_device_id = ?,\n label = ?,\n token = ?,\n status = 'active',\n last_seen_at = ?,\n updated_at = ?\n WHERE token_hash = ?`,\n args: [\n input.ownerEmail,\n input.orgId ?? null,\n provider,\n platform,\n clientDeviceId,\n label,\n input.token,\n now,\n now,\n tokenHash,\n ],\n });\n const updated = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (!updated) throw new Error(\"remote push registration update failed\");\n return updated;\n }\n\n const id = `remote-push-${now}-${randomHex(8)}`;\n await client.execute({\n sql: `INSERT INTO integration_remote_push_registrations\n (id, owner_email, org_id, provider, platform, client_device_id, label,\n token, token_hash, status, last_seen_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.ownerEmail,\n input.orgId ?? null,\n provider,\n platform,\n clientDeviceId,\n label,\n input.token,\n tokenHash,\n \"active\",\n now,\n now,\n now,\n ],\n });\n const registration = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (!registration) throw new Error(\"remote push registration insert failed\");\n return registration;\n}\n\nexport async function listRemotePushRegistrationsForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n includeInactive?: boolean;\n limit?: number;\n}): Promise<RemotePushRegistration[]> {\n await ensureTables();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.includeInactive ? \"\" : \" AND status = 'active'\";\n if (!Object.prototype.hasOwnProperty.call(input, \"orgId\")) {\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE owner_email = ?${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args: [input.ownerEmail, limit],\n });\n return rows.map((row) => rowToRegistration(row as Record<string, unknown>));\n }\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args: [input.ownerEmail, input.orgId ?? null, input.orgId ?? null, limit],\n });\n return rows.map((row) => rowToRegistration(row as Record<string, unknown>));\n}\n\nexport async function unregisterRemotePushRegistrationForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n id?: string | null;\n token?: string | null;\n}): Promise<boolean> {\n await ensureTables();\n const tokenHash = input.token ? await hashToken(input.token) : null;\n if (!input.id && !tokenHash) return false;\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_registrations\n SET status = 'inactive', updated_at = ?\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)\n AND (${input.id ? \"id = ?\" : \"0 = 1\"} OR ${\n tokenHash ? \"token_hash = ?\" : \"0 = 1\"\n })`,\n args: [\n now,\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ...(input.id ? [input.id] : []),\n ...(tokenHash ? [tokenHash] : []),\n ],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) > 0;\n}\n\nexport async function queueRemotePushNotifications(input: {\n ownerEmail: string;\n orgId?: string | null;\n payload: unknown;\n}): Promise<{ queued: number }> {\n await ensureTables();\n const registrations = await listRemotePushRegistrationsForOwner({\n ownerEmail: input.ownerEmail,\n orgId: input.orgId ?? null,\n limit: 100,\n });\n const client = getDbExec();\n const now = Date.now();\n let queued = 0;\n for (const registration of registrations) {\n const id = `remote-push-notification-${now}-${randomHex(8)}`;\n const result = await client.execute({\n sql: `INSERT INTO integration_remote_push_notifications\n (id, owner_email, org_id, registration_id, payload_json, status,\n attempts, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.ownerEmail,\n input.orgId ?? null,\n registration.id,\n JSON.stringify(input.payload ?? null),\n \"pending\",\n 0,\n now,\n now,\n ],\n });\n queued += result.rowsAffected ?? (result as any).rowCount ?? 0;\n }\n return { queued };\n}\n\nexport async function listRemotePushNotificationsForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n status?: RemotePushNotification[\"status\"];\n limit?: number;\n}): Promise<RemotePushNotification[]> {\n await ensureTables();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.status ? \" AND status = ?\" : \"\";\n const args: Array<string | number | null> = [\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ];\n if (input.status) args.push(input.status);\n args.push(limit);\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_notifications\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY created_at DESC\n LIMIT ?`,\n args,\n });\n return rows.map((row) => rowToNotification(row as Record<string, unknown>));\n}\n\nasync function getRemotePushRegistrationByTokenHash(\n tokenHash: string,\n): Promise<RemotePushRegistration | null> {\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE token_hash = ?\n LIMIT 1`,\n args: [tokenHash],\n });\n return rows[0] ? rowToRegistration(rows[0] as Record<string, unknown>) : null;\n}\n\nasync function hashToken(token: string): Promise<string> {\n const bytes = new TextEncoder().encode(token);\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest))\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction randomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction sanitizeString(\n value: string | null | undefined,\n max: number,\n): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, max) : null;\n}\n\nfunction parseJson(value: unknown, fallback: unknown): unknown {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value));\n } catch {\n return fallback;\n }\n}\n"]}
1
+ {"version":3,"file":"remote-push-store.js","sourceRoot":"","sources":["../../src/integrations/remote-push-store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getDbExec,\n isPostgres,\n intType,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport {\n ensureColumnExists,\n ensureIndexExists,\n ensureTableExists,\n} from \"../db/ddl-guard.js\";\nimport { isDuplicateColumnError } from \"../db/migrations.js\";\nimport type {\n PublicRemotePushRegistration,\n RemotePushNotification,\n RemotePushRegistration,\n} from \"./remote-types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n// Build the CREATE SQL lazily (not at module scope) so intType() runs at\n// RUNTIME, not import time — a module-scope call breaks any consumer whose\n// db/client mock doesn't stub intType (e.g. db-admin specs).\nfunction buildCreateRegistrationsSql(): string {\n return `\n CREATE TABLE IF NOT EXISTS integration_remote_push_registrations (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n provider TEXT NOT NULL,\n platform TEXT,\n client_device_id TEXT,\n label TEXT,\n token TEXT NOT NULL,\n token_hash TEXT NOT NULL,\n status TEXT NOT NULL,\n last_seen_at ${intType()},\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n`;\n}\n\nfunction buildCreateNotificationsSql(): string {\n return `\n CREATE TABLE IF NOT EXISTS integration_remote_push_notifications (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n registration_id TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n provider_ticket_id TEXT,\n next_attempt_at ${intType()} NOT NULL DEFAULT 0,\n last_error TEXT,\n delivered_at ${intType()},\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n`;\n}\n\nasync function ensureTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createRegistrationsSql = buildCreateRegistrationsSql();\n const createNotificationsSql = buildCreateNotificationsSql();\n if (isPostgres()) {\n // PG guard: probe via information_schema, only issue DDL if missing, bounded lock_timeout\n await ensureTableExists(\n \"integration_remote_push_registrations\",\n createRegistrationsSql,\n );\n await ensureIndexExists(\n \"idx_remote_push_token_hash\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_push_token_hash ON integration_remote_push_registrations(token_hash)`,\n );\n await ensureIndexExists(\n \"idx_remote_push_owner\",\n `CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`,\n );\n await ensureTableExists(\n \"integration_remote_push_notifications\",\n createNotificationsSql,\n );\n await ensureIndexExists(\n \"idx_remote_push_notifications_owner\",\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`,\n );\n await ensureColumnExists(\n \"integration_remote_push_notifications\",\n \"provider_ticket_id\",\n `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS provider_ticket_id TEXT`,\n );\n await ensureColumnExists(\n \"integration_remote_push_notifications\",\n \"next_attempt_at\",\n `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS next_attempt_at ${intType()} NOT NULL DEFAULT 0`,\n );\n await ensureColumnExists(\n \"integration_remote_push_notifications\",\n \"last_error\",\n `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS last_error TEXT`,\n );\n await ensureColumnExists(\n \"integration_remote_push_notifications\",\n \"delivered_at\",\n `ALTER TABLE integration_remote_push_notifications ADD COLUMN IF NOT EXISTS delivered_at ${intType()}`,\n );\n await ensureIndexExists(\n \"idx_remote_push_notifications_delivery\",\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_delivery ON integration_remote_push_notifications(status, next_attempt_at, updated_at)`,\n );\n return;\n }\n // SQLite (local dev): keep existing behavior\n await retryOnDdlRace(() => client.execute(createRegistrationsSql));\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_remote_push_token_hash ON integration_remote_push_registrations(token_hash)`,\n ),\n );\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_owner ON integration_remote_push_registrations(owner_email, org_id, status)`,\n ),\n );\n\n await retryOnDdlRace(() => client.execute(createNotificationsSql));\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_owner ON integration_remote_push_notifications(owner_email, org_id, status, created_at)`,\n ),\n );\n await addNotificationColumnIfMissing(\"provider_ticket_id\", \"TEXT\");\n await addNotificationColumnIfMissing(\n \"next_attempt_at\",\n `${intType()} NOT NULL DEFAULT 0`,\n );\n await addNotificationColumnIfMissing(\"last_error\", \"TEXT\");\n await addNotificationColumnIfMissing(\"delivered_at\", intType());\n await retryOnDdlRace(() =>\n client.execute(\n `CREATE INDEX IF NOT EXISTS idx_remote_push_notifications_delivery ON integration_remote_push_notifications(status, next_attempt_at, updated_at)`,\n ),\n );\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nasync function addNotificationColumnIfMissing(\n name: string,\n definition: string,\n): Promise<void> {\n try {\n await retryOnDdlRace(() =>\n getDbExec().execute(\n `ALTER TABLE integration_remote_push_notifications ADD COLUMN ${name} ${definition}`,\n ),\n );\n } catch (error) {\n if (!isDuplicateColumnError(error)) throw error;\n }\n}\n\nfunction rowToRegistration(\n row: Record<string, unknown>,\n): RemotePushRegistration {\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n provider: row.provider as string,\n platform: (row.platform as string | null) ?? null,\n clientDeviceId: (row.client_device_id as string | null) ?? null,\n label: (row.label as string | null) ?? null,\n token: row.token as string,\n tokenHash: row.token_hash as string,\n status: row.status as RemotePushRegistration[\"status\"],\n lastSeenAt:\n row.last_seen_at == null ? null : Number(row.last_seen_at as number),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nfunction rowToNotification(\n row: Record<string, unknown>,\n): RemotePushNotification {\n const storedStatus = String(row.status ?? \"pending\");\n const status =\n storedStatus === \"delivered\" || storedStatus === \"failed\"\n ? storedStatus\n : \"pending\";\n return {\n id: row.id as string,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n registrationId: row.registration_id as string,\n payload: parseJson(row.payload_json, null),\n status,\n attempts: Number(row.attempts ?? 0),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nexport function toPublicRemotePushRegistration(\n registration: RemotePushRegistration,\n): PublicRemotePushRegistration {\n return {\n id: registration.id,\n ownerEmail: registration.ownerEmail,\n orgId: registration.orgId,\n provider: registration.provider,\n platform: registration.platform,\n clientDeviceId: registration.clientDeviceId,\n label: registration.label,\n status: registration.status,\n lastSeenAt: registration.lastSeenAt,\n createdAt: registration.createdAt,\n updatedAt: registration.updatedAt,\n };\n}\n\nexport async function upsertRemotePushRegistration(input: {\n ownerEmail: string;\n orgId?: string | null;\n provider: string;\n token: string;\n platform?: string | null;\n clientDeviceId?: string | null;\n label?: string | null;\n}): Promise<RemotePushRegistration> {\n await ensureTables();\n const client = getDbExec();\n const now = Date.now();\n const tokenHash = await hashToken(input.token);\n const provider = sanitizeString(input.provider, 80) ?? \"unknown\";\n const platform = sanitizeString(input.platform, 80);\n const clientDeviceId = sanitizeString(input.clientDeviceId, 200);\n const label = sanitizeString(input.label, 200);\n\n const existing = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (existing) {\n await client.execute({\n sql: `UPDATE integration_remote_push_registrations\n SET owner_email = ?,\n org_id = ?,\n provider = ?,\n platform = ?,\n client_device_id = ?,\n label = ?,\n token = ?,\n status = 'active',\n last_seen_at = ?,\n updated_at = ?\n WHERE token_hash = ?`,\n args: [\n input.ownerEmail,\n input.orgId ?? null,\n provider,\n platform,\n clientDeviceId,\n label,\n input.token,\n now,\n now,\n tokenHash,\n ],\n });\n const updated = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (!updated) throw new Error(\"remote push registration update failed\");\n return updated;\n }\n\n const id = `remote-push-${now}-${randomHex(8)}`;\n await client.execute({\n sql: `INSERT INTO integration_remote_push_registrations\n (id, owner_email, org_id, provider, platform, client_device_id, label,\n token, token_hash, status, last_seen_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.ownerEmail,\n input.orgId ?? null,\n provider,\n platform,\n clientDeviceId,\n label,\n input.token,\n tokenHash,\n \"active\",\n now,\n now,\n now,\n ],\n });\n const registration = await getRemotePushRegistrationByTokenHash(tokenHash);\n if (!registration) throw new Error(\"remote push registration insert failed\");\n return registration;\n}\n\nexport async function listRemotePushRegistrationsForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n includeInactive?: boolean;\n limit?: number;\n}): Promise<RemotePushRegistration[]> {\n await ensureTables();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.includeInactive ? \"\" : \" AND status = 'active'\";\n if (!Object.prototype.hasOwnProperty.call(input, \"orgId\")) {\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE owner_email = ?${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args: [input.ownerEmail, limit],\n });\n return rows.map((row) => rowToRegistration(row as Record<string, unknown>));\n }\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY COALESCE(last_seen_at, updated_at) DESC\n LIMIT ?`,\n args: [input.ownerEmail, input.orgId ?? null, input.orgId ?? null, limit],\n });\n return rows.map((row) => rowToRegistration(row as Record<string, unknown>));\n}\n\nexport async function unregisterRemotePushRegistrationForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n id?: string | null;\n token?: string | null;\n}): Promise<boolean> {\n await ensureTables();\n const tokenHash = input.token ? await hashToken(input.token) : null;\n if (!input.id && !tokenHash) return false;\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_registrations\n SET status = 'inactive', updated_at = ?\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)\n AND (${input.id ? \"id = ?\" : \"0 = 1\"} OR ${\n tokenHash ? \"token_hash = ?\" : \"0 = 1\"\n })`,\n args: [\n now,\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ...(input.id ? [input.id] : []),\n ...(tokenHash ? [tokenHash] : []),\n ],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) > 0;\n}\n\nexport async function queueRemotePushNotifications(input: {\n ownerEmail: string;\n orgId?: string | null;\n payload: unknown;\n}): Promise<{ queued: number }> {\n await ensureTables();\n const registrations = await listRemotePushRegistrationsForOwner({\n ownerEmail: input.ownerEmail,\n orgId: input.orgId ?? null,\n limit: 100,\n });\n if (registrations.length === 0) return { queued: 0 };\n\n const client = getDbExec();\n const now = Date.now();\n const payload = JSON.stringify(input.payload ?? null);\n const values = registrations.map(\n () => \"(?, ?, ?, ?, ?, 'pending', 0, ?, ?, ?)\",\n );\n const args = registrations.flatMap((registration) => [\n `remote-push-notification-${now}-${randomHex(8)}`,\n input.ownerEmail,\n input.orgId ?? null,\n registration.id,\n payload,\n now,\n now,\n now,\n ]);\n const result = await client.execute({\n sql: `INSERT INTO integration_remote_push_notifications\n (id, owner_email, org_id, registration_id, payload_json, status,\n attempts, next_attempt_at, created_at, updated_at)\n VALUES ${values.join(\", \")}`,\n args,\n });\n return {\n queued: result.rowsAffected ?? (result as any).rowCount ?? 0,\n };\n}\n\nexport async function listRemotePushNotificationsForOwner(input: {\n ownerEmail: string;\n orgId?: string | null;\n status?: RemotePushNotification[\"status\"];\n limit?: number;\n}): Promise<RemotePushNotification[]> {\n await ensureTables();\n const limit = Math.max(1, Math.min(input.limit ?? 50, 100));\n const statusClause = input.status\n ? input.status === \"pending\"\n ? \" AND status IN ('pending', 'sending', 'sent', 'checking')\"\n : \" AND status = ?\"\n : \"\";\n const args: Array<string | number | null> = [\n input.ownerEmail,\n input.orgId ?? null,\n input.orgId ?? null,\n ];\n if (input.status && input.status !== \"pending\") args.push(input.status);\n args.push(limit);\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_notifications\n WHERE owner_email = ?\n AND ((org_id IS NULL AND ? IS NULL) OR org_id = ?)${statusClause}\n ORDER BY created_at DESC\n LIMIT ?`,\n args,\n });\n return rows.map((row) => rowToNotification(row as Record<string, unknown>));\n}\n\nexport interface ClaimedRemotePushDelivery {\n id: string;\n registrationId: string;\n provider: string;\n token: string;\n payload: unknown;\n phase: \"send\" | \"receipt\";\n providerTicketId: string | null;\n attempts: number;\n}\n\nexport async function claimNextRemotePushDelivery(input?: {\n now?: number;\n staleAfterMs?: number;\n}): Promise<ClaimedRemotePushDelivery | null> {\n await ensureTables();\n const client = getDbExec();\n const now = input?.now ?? Date.now();\n const staleBefore = now - Math.max(30_000, input?.staleAfterMs ?? 120_000);\n const { rows } = await client.execute({\n sql: `SELECT n.id, n.registration_id, n.payload_json, n.status, n.attempts,\n n.provider_ticket_id, n.updated_at, r.provider, r.token\n FROM integration_remote_push_notifications n\n INNER JOIN integration_remote_push_registrations r\n ON r.id = n.registration_id\n WHERE r.status = 'active'\n AND (\n (n.status IN ('pending', 'sent') AND n.next_attempt_at <= ?)\n OR (n.status IN ('sending', 'checking') AND n.updated_at <= ?)\n )\n ORDER BY n.created_at ASC\n LIMIT 1`,\n args: [now, staleBefore],\n });\n const row = rows[0] as Record<string, unknown> | undefined;\n if (!row) return null;\n\n const previousStatus = String(row.status ?? \"pending\");\n const providerTicketId = sanitizeString(\n row.provider_ticket_id as string | null,\n 200,\n );\n const phase =\n (previousStatus === \"sent\" || previousStatus === \"checking\") &&\n providerTicketId\n ? \"receipt\"\n : \"send\";\n const claimedStatus = phase === \"receipt\" ? \"checking\" : \"sending\";\n const result = await client.execute({\n sql: `UPDATE integration_remote_push_notifications\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ? AND status = ? AND updated_at = ?`,\n args: [\n claimedStatus,\n now,\n row.id as string,\n previousStatus,\n Number(row.updated_at),\n ],\n });\n if ((result.rowsAffected ?? (result as any).rowCount ?? 0) !== 1) return null;\n\n return {\n id: row.id as string,\n registrationId: row.registration_id as string,\n provider: String(row.provider ?? \"unknown\"),\n token: row.token as string,\n payload: parseJson(row.payload_json, null),\n phase,\n providerTicketId,\n attempts: Number(row.attempts ?? 0) + 1,\n };\n}\n\nexport async function markRemotePushTicketAccepted(input: {\n id: string;\n providerTicketId: string;\n checkAfter: number;\n}): Promise<boolean> {\n await ensureTables();\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_notifications\n SET status = 'sent', provider_ticket_id = ?, next_attempt_at = ?,\n last_error = NULL, updated_at = ?\n WHERE id = ? AND status = 'sending'`,\n args: [input.providerTicketId, input.checkAfter, now, input.id],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) === 1;\n}\n\nexport async function markRemotePushDelivered(id: string): Promise<boolean> {\n await ensureTables();\n const now = Date.now();\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_notifications\n SET status = 'delivered', last_error = NULL, delivered_at = ?,\n updated_at = ?\n WHERE id = ? AND status = 'checking'`,\n args: [now, now, id],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) === 1;\n}\n\nexport async function retryRemotePushDelivery(input: {\n id: string;\n phase: \"send\" | \"receipt\";\n retryAt: number;\n errorCode: string;\n resend?: boolean;\n}): Promise<boolean> {\n await ensureTables();\n const currentStatus = input.phase === \"receipt\" ? \"checking\" : \"sending\";\n const retryStatus =\n input.phase === \"receipt\" && !input.resend ? \"sent\" : \"pending\";\n const clearTicketClause = input.resend ? \", provider_ticket_id = NULL\" : \"\";\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_notifications\n SET status = ?, next_attempt_at = ?, last_error = ?${clearTicketClause},\n updated_at = ?\n WHERE id = ? AND status = ?`,\n args: [\n retryStatus,\n input.retryAt,\n sanitizeString(input.errorCode, 160) ?? \"temporary_error\",\n Date.now(),\n input.id,\n currentStatus,\n ],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) === 1;\n}\n\nexport async function failRemotePushDelivery(input: {\n id: string;\n phase: \"send\" | \"receipt\";\n errorCode: string;\n}): Promise<boolean> {\n await ensureTables();\n const currentStatus = input.phase === \"receipt\" ? \"checking\" : \"sending\";\n const result = await getDbExec().execute({\n sql: `UPDATE integration_remote_push_notifications\n SET status = 'failed', last_error = ?, updated_at = ?\n WHERE id = ? AND status = ?`,\n args: [\n sanitizeString(input.errorCode, 160) ?? \"delivery_failed\",\n Date.now(),\n input.id,\n currentStatus,\n ],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) === 1;\n}\n\nexport async function deactivateRemotePushRegistration(\n registrationId: string,\n): Promise<boolean> {\n await ensureTables();\n const client = getDbExec();\n const now = Date.now();\n const result = await client.execute({\n sql: `UPDATE integration_remote_push_registrations\n SET status = 'inactive', updated_at = ?\n WHERE id = ? AND status = 'active'`,\n args: [now, registrationId],\n });\n await client.execute({\n sql: `UPDATE integration_remote_push_notifications\n SET status = 'failed', last_error = 'registration_inactive',\n updated_at = ?\n WHERE registration_id = ?\n AND status IN ('pending', 'sending', 'sent', 'checking')`,\n args: [now, registrationId],\n });\n return (result.rowsAffected ?? (result as any).rowCount ?? 0) === 1;\n}\n\nasync function getRemotePushRegistrationByTokenHash(\n tokenHash: string,\n): Promise<RemotePushRegistration | null> {\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM integration_remote_push_registrations\n WHERE token_hash = ?\n LIMIT 1`,\n args: [tokenHash],\n });\n return rows[0] ? rowToRegistration(rows[0] as Record<string, unknown>) : null;\n}\n\nasync function hashToken(token: string): Promise<string> {\n const bytes = new TextEncoder().encode(token);\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest))\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction randomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction sanitizeString(\n value: string | null | undefined,\n max: number,\n): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, max) : null;\n}\n\nfunction parseJson(value: unknown, fallback: unknown): unknown {\n if (value == null) return fallback;\n try {\n return JSON.parse(String(value));\n } catch {\n return fallback;\n }\n}\n"]}
@@ -11,14 +11,14 @@
11
11
  * DELETE /_agent-native/notifications/:id — delete
12
12
  */
13
13
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
14
+ error?: undefined;
14
15
  count: number;
15
16
  updated?: undefined;
16
- error?: undefined;
17
17
  ok?: undefined;
18
18
  } | {
19
+ error?: undefined;
19
20
  count?: undefined;
20
21
  updated: number;
21
- error?: undefined;
22
22
  ok?: undefined;
23
23
  } | {
24
24
  count?: undefined;
@@ -26,9 +26,9 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
26
26
  error: string;
27
27
  ok?: undefined;
28
28
  } | {
29
+ error?: undefined;
29
30
  count?: undefined;
30
31
  updated?: undefined;
31
32
  ok: boolean;
32
- error?: undefined;
33
33
  }>>;
34
34
  //# sourceMappingURL=routes.d.ts.map
@@ -15,7 +15,7 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- ok: boolean;
19
18
  error?: undefined;
19
+ ok: boolean;
20
20
  }>>;
21
21
  //# sourceMappingURL=routes.d.ts.map
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
+ deleted?: undefined;
76
77
  jobs: {
77
78
  id: string;
78
79
  name: string;
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
83
84
  updatedAt: string;
84
85
  }[];
85
86
  total: number;
86
- deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
+ deleted?: undefined;
94
95
  jobs?: undefined;
95
96
  total?: undefined;
96
- deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -49,11 +49,11 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
49
49
  }>;
50
50
  /** DELETE /_agent-native/resources/:id — delete a resource */
51
51
  export declare function handleDeleteResource(event: any): Promise<{
52
- error: string;
53
52
  ok?: undefined;
53
+ error: string;
54
54
  } | {
55
- ok: boolean;
56
55
  error?: undefined;
56
+ ok: boolean;
57
57
  }>;
58
58
  /** POST /_agent-native/resources/upload — upload a file as a resource */
59
59
  export declare function handleUploadResource(event: any): Promise<import("./store.js").Resource | {
@@ -74,10 +74,10 @@ export declare function handleUploadResource(event: any): Promise<import("./stor
74
74
  runId: string | null;
75
75
  expiresAt: number | null;
76
76
  metadata: string | null;
77
+ error?: undefined;
77
78
  url: string;
78
79
  provider: string;
79
80
  storageSetupRequired?: undefined;
80
- error?: undefined;
81
81
  } | {
82
82
  error: string;
83
83
  storageSetupRequired: boolean;
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
34
34
  /** POST /_agent-native/secrets/:key — write a secret. */
35
35
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
36
36
  error: string;
37
- status?: undefined;
38
37
  ok?: undefined;
38
+ status?: undefined;
39
39
  } | {
40
+ error?: undefined;
40
41
  ok: boolean;
41
42
  status: string;
42
- error?: undefined;
43
43
  } | {
44
+ ok?: undefined;
44
45
  error: string;
45
46
  removed?: undefined;
46
- ok?: undefined;
47
47
  } | {
48
+ error?: undefined;
48
49
  ok: boolean;
49
50
  removed: boolean;
50
- error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — re-run the validator against the
54
54
  * current stored value without changing anything. Useful for the "Test" button.
55
55
  */
56
56
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
57
+ ok?: undefined;
57
58
  error: string;
58
59
  note?: undefined;
59
- ok?: undefined;
60
60
  } | {
61
+ error?: undefined;
61
62
  ok: boolean;
62
63
  note?: undefined;
63
- error?: undefined;
64
64
  } | {
65
+ error?: undefined;
65
66
  ok: boolean;
66
67
  note: string;
67
- error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,12 +95,12 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
+ error?: undefined;
98
99
  ok: boolean;
99
100
  key: string;
100
- error?: undefined;
101
101
  } | {
102
+ error?: undefined;
102
103
  ok: boolean;
103
104
  removed: boolean;
104
- error?: undefined;
105
105
  }>>;
106
106
  //# sourceMappingURL=routes.d.ts.map
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
+ error?: undefined;
30
31
  ok: boolean;
31
32
  key: string;
32
33
  baseUrlKey?: string;
33
34
  scope: AgentEngineApiKeyScope;
34
- error?: undefined;
35
35
  }>>;
36
36
  export {};
37
37
  //# sourceMappingURL=agent-engine-api-key-route.d.ts.map
@@ -881,7 +881,7 @@ async function createBetterAuthInstance(config) {
881
881
  async function buildDatabaseConfig(dialect) {
882
882
  if (dialect === "postgres") {
883
883
  const url = getDatabaseUrl();
884
- const { isNeonUrl } = await import("../db/create-get-db.js");
884
+ const { buildResilientNeonPool, buildResilientPostgresJsClient, isNeonUrl, } = await import("../db/create-get-db.js");
885
885
  if (isPgliteUrl(url)) {
886
886
  const { drizzle } = await loadPgliteDrizzle();
887
887
  const client = await getPgliteClient(url);
@@ -907,7 +907,9 @@ async function buildDatabaseConfig(dialect) {
907
907
  });
908
908
  attachNeonPoolErrorLogger(_neonAuthPool, "db/neon-auth");
909
909
  const { drizzle } = await import("drizzle-orm/neon-serverless");
910
- const db = drizzle(_neonAuthPool, { schema: pgAuthSchema });
910
+ const db = drizzle(buildResilientNeonPool(_neonAuthPool), {
911
+ schema: pgAuthSchema,
912
+ });
911
913
  const { drizzleAdapter } = await import("better-auth/adapters/drizzle");
912
914
  return drizzleAdapter(db, {
913
915
  provider: "pg",
@@ -922,7 +924,9 @@ async function buildDatabaseConfig(dialect) {
922
924
  const { default: postgres } = await import("postgres");
923
925
  const sql = postgres(url, pgPoolOptions(url));
924
926
  const { drizzle } = await import("drizzle-orm/postgres-js");
925
- const db = drizzle(sql, { schema: pgAuthSchema });
927
+ const db = drizzle(buildResilientPostgresJsClient(sql), {
928
+ schema: pgAuthSchema,
929
+ });
926
930
  const { drizzleAdapter } = await import("better-auth/adapters/drizzle");
927
931
  return drizzleAdapter(db, {
928
932
  provider: "pg",