@agent-native/core 0.129.1 → 0.130.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 (596) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +78 -0
  3. package/corpus/core/docs/content/cloneable-saas.mdx +114 -0
  4. package/corpus/core/docs/content/creating-templates.mdx +28 -2
  5. package/corpus/core/docs/content/syncing-template-changes.mdx +7 -0
  6. package/corpus/core/docs/content/template-clips-developers.mdx +12 -5
  7. package/corpus/core/docs/content/template-dispatch-developers.mdx +1 -1
  8. package/corpus/core/docs/content/template-dispatch.mdx +1 -1
  9. package/corpus/core/package.json +1 -1
  10. package/corpus/core/src/action-ui.ts +1 -0
  11. package/corpus/core/src/action.ts +5 -1
  12. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +15 -5
  13. package/corpus/core/src/agent/harness/runner.ts +5 -0
  14. package/corpus/core/src/agent/production-agent.ts +33 -0
  15. package/corpus/core/src/agent/run-loop-with-resume.ts +5 -0
  16. package/corpus/core/src/agent/run-manager.ts +126 -1
  17. package/corpus/core/src/agent/thread-data-builder.ts +47 -2
  18. package/corpus/core/src/agent/types.ts +2 -0
  19. package/corpus/core/src/chat-threads/store.ts +4 -5
  20. package/corpus/core/src/cli/create.ts +1139 -65
  21. package/corpus/core/src/cli/design-connect.ts +3 -7
  22. package/corpus/core/src/cli/index.ts +5 -3
  23. package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +83 -47
  24. package/corpus/core/src/client/AssistantChat.tsx +27 -16
  25. package/corpus/core/src/client/agent-chat-adapter.ts +24 -0
  26. package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +17 -2
  27. package/corpus/core/src/client/chat/index.ts +1 -0
  28. package/corpus/core/src/client/chat/message-components.tsx +104 -1
  29. package/corpus/core/src/client/chat/run-recovery.tsx +15 -3
  30. package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +10 -29
  31. package/corpus/core/src/client/chat/widgets/WorkspaceFileWidget.tsx +71 -0
  32. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +22 -0
  33. package/corpus/core/src/client/chat/widgets/workspace-file-result.ts +49 -0
  34. package/corpus/core/src/client/embed-auth.ts +2 -0
  35. package/corpus/core/src/client/org/InvitationBanner.tsx +14 -1
  36. package/corpus/core/src/client/org/OrgSwitcher.tsx +23 -0
  37. package/corpus/core/src/client/org/TeamPage.tsx +130 -0
  38. package/corpus/core/src/client/org/WorkspaceNotice.tsx +85 -0
  39. package/corpus/core/src/client/org/hooks.ts +14 -0
  40. package/corpus/core/src/client/org/index.ts +2 -0
  41. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +27 -40
  42. package/corpus/core/src/client/resources/ResourcesPanel.tsx +134 -51
  43. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +7 -0
  44. package/corpus/core/src/client/resources/use-resources.ts +6 -0
  45. package/corpus/core/src/client/use-action.ts +3 -1
  46. package/corpus/core/src/client/widgets/index.ts +1 -0
  47. package/corpus/core/src/coding-tools/run-code.ts +2 -1
  48. package/corpus/core/src/db/client.ts +28 -4
  49. package/corpus/core/src/deploy/build.ts +31 -3
  50. package/corpus/core/src/eject/remote-mcp-presets.ts +1 -1
  51. package/corpus/core/src/index.browser.ts +1 -0
  52. package/corpus/core/src/index.ts +1 -0
  53. package/corpus/core/src/integrations/google-docs-poller.ts +3 -0
  54. package/corpus/core/src/integrations/webhook-handler.ts +28 -11
  55. package/corpus/core/src/jobs/scheduler.ts +4 -0
  56. package/corpus/core/src/localization/default-messages.ts +3 -2
  57. package/corpus/core/src/mcp/build-server.ts +20 -2
  58. package/corpus/core/src/observability/traces.ts +48 -12
  59. package/corpus/core/src/org/handlers.ts +52 -1
  60. package/corpus/core/src/org/migrations.ts +4 -0
  61. package/corpus/core/src/org/plugin.ts +14 -0
  62. package/corpus/core/src/org/schema.ts +1 -0
  63. package/corpus/core/src/org/types.ts +8 -0
  64. package/corpus/core/src/org/workspace-url.ts +74 -0
  65. package/corpus/core/src/resources/handlers.ts +35 -5
  66. package/corpus/core/src/scripts/runner.ts +183 -5
  67. package/corpus/core/src/server/action-routes.ts +32 -2
  68. package/corpus/core/src/server/agent-chat-plugin.ts +29 -0
  69. package/corpus/core/src/server/agent-teams.ts +10 -1
  70. package/corpus/core/src/server/auth.ts +33 -7
  71. package/corpus/core/src/server/embed-route.ts +9 -0
  72. package/corpus/core/src/server/embed-session.ts +62 -3
  73. package/corpus/core/src/server/open-route.ts +20 -6
  74. package/corpus/core/src/server/prompts/framework-core-compact.ts +1 -1
  75. package/corpus/core/src/server/prompts/framework-core.ts +1 -0
  76. package/corpus/core/src/server/request-context.ts +36 -1
  77. package/corpus/core/src/shared/embed-auth.ts +1 -0
  78. package/corpus/core/src/shared/html-document.ts +115 -0
  79. package/corpus/core/src/shared/index.ts +1 -0
  80. package/corpus/core/src/sharing/access.ts +8 -1
  81. package/corpus/core/src/sharing/registry.ts +11 -2
  82. package/corpus/core/src/workspace-files/actions.ts +100 -0
  83. package/corpus/core/src/workspace-files/tool.ts +4 -0
  84. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +4 -0
  85. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +9 -1
  86. package/corpus/templates/analytics/AGENTS.md +17 -24
  87. package/corpus/templates/analytics/actions/data-source-status.ts +11 -1
  88. package/corpus/templates/analytics/app/i18n-data.ts +34 -0
  89. package/corpus/templates/analytics/app/lib/data-source-status.ts +86 -0
  90. package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +9 -0
  91. package/corpus/templates/analytics/app/pages/DataSources.tsx +184 -20
  92. package/corpus/templates/analytics/changelog/2026-07-28-native-analytics-data-sources-no-longer-show-duplicate-mc.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-29-exports-now-appear-in-chat-with-a-direct-download-instead-of.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-29-queued-chat-prompts-no-longer-resend-after-analytics-navigat.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-29-scheduled-dashboard-emails-load-every-panel-reliably-without.md +6 -0
  96. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +6 -3
  97. package/corpus/templates/analytics/server/lib/credential-keys.ts +1 -1
  98. package/corpus/templates/analytics/server/lib/hubspot.ts +1 -1
  99. package/corpus/templates/analytics/server/lib/provider-credentials.ts +55 -1
  100. package/corpus/templates/analytics/server/plugins/agent-chat.ts +123 -27
  101. package/corpus/templates/analytics/server/routes/[...page].get.ts +2 -7
  102. package/corpus/templates/analytics/vite.config.ts +7 -0
  103. package/corpus/templates/brain/actions/list-connection-providers.ts +100 -2
  104. package/corpus/templates/brain/app/lib/brain.ts +10 -0
  105. package/corpus/templates/brain/app/routes/sources.tsx +15 -4
  106. package/corpus/templates/brain/changelog/2026-07-29-brain-automatically-retries-failed-source-syncs-and-guides-y.md +6 -0
  107. package/corpus/templates/brain/jobs/process-ingest-queue.ts +13 -0
  108. package/corpus/templates/brain/server/jobs/sync-sources.ts +27 -22
  109. package/corpus/templates/brain/server/plugins/agent-chat.ts +2 -1
  110. package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +7 -1
  111. package/corpus/templates/clips/AGENTS.md +1 -1
  112. package/corpus/templates/clips/actions/create-recording-agent-link.ts +11 -1
  113. package/corpus/templates/clips/actions/update-comment.ts +68 -0
  114. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +0 -1
  115. package/corpus/templates/clips/app/components/player/comments-panel.tsx +221 -65
  116. package/corpus/templates/clips/app/components/player/video-player.tsx +101 -27
  117. package/corpus/templates/clips/app/i18n/en-US.ts +2 -1
  118. package/corpus/templates/clips/app/routes/bug-report.done.tsx +48 -27
  119. package/corpus/templates/clips/app/routes/bug-report.tsx +43 -4
  120. package/corpus/templates/clips/app/routes/record.tsx +2 -0
  121. package/corpus/templates/clips/changelog/2026-07-29-clip-playback-now-recovers-instead-of-getting-stuck-when-a-b.md +6 -0
  122. package/corpus/templates/clips/changelog/2026-07-29-comments-can-now-be-edited-after-posting.md +6 -0
  123. package/corpus/templates/clips/changelog/2026-07-29-download-actions-now-use-a-shorter-clearer-label.md +6 -0
  124. package/corpus/templates/clips/changelog/2026-07-29-embedded-bug-reports-now-return-a-temporary-agent-readable.md +6 -0
  125. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
  126. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +21 -1
  127. package/corpus/templates/clips/shared/bug-report.ts +99 -0
  128. package/corpus/templates/content/actions/_content-database-personal-view.ts +7 -1
  129. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +5 -2
  130. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +20 -8
  131. package/corpus/templates/content/changelog/2026-07-29-missing-databases-no-longer-trigger-repeated-personal-view-e.md +6 -0
  132. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +83 -47
  133. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +474 -55
  134. package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +3 -0
  135. package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +18 -1
  136. package/corpus/templates/design/.generated/bridge/source-location.generated.ts +348 -0
  137. package/corpus/templates/design/actions/add-localhost-screens.ts +2 -7
  138. package/corpus/templates/design/actions/apply-visual-edit.ts +7 -1
  139. package/corpus/templates/design/actions/connect-localhost.ts +5 -9
  140. package/corpus/templates/design/actions/create-component.ts +16 -13
  141. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +2 -7
  142. package/corpus/templates/design/actions/list-design-source-capabilities.ts +4 -7
  143. package/corpus/templates/design/actions/list-local-files.ts +26 -50
  144. package/corpus/templates/design/actions/list-localhost-connections.ts +2 -7
  145. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +2 -2
  146. package/corpus/templates/design/actions/open-visual-edit.ts +234 -135
  147. package/corpus/templates/design/actions/read-local-file.ts +26 -50
  148. package/corpus/templates/design/actions/request-localhost-write-consent.ts +2 -7
  149. package/corpus/templates/design/actions/write-local-file.ts +31 -73
  150. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +307 -133
  151. package/corpus/templates/design/app/components/design/EditPanel.tsx +94 -22
  152. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +137 -60
  153. package/corpus/templates/design/app/components/design/ResponsiveInteractBar.tsx +75 -14
  154. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +755 -97
  155. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +8 -0
  156. package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +24 -1
  157. package/corpus/templates/design/app/components/design/bridge/source-location.bridge.ts +530 -0
  158. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbenchLoader.tsx +278 -0
  159. package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +32 -12
  160. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +14 -3
  161. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +87 -24
  162. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +36 -0
  163. package/corpus/templates/design/app/components/design/code-workbench/store.tsx +2 -1
  164. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +48 -8
  165. package/corpus/templates/design/app/components/design/design-canvas/content-size-report.ts +3 -13
  166. package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +4 -2
  167. package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +3 -13
  168. package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +3 -1
  169. package/corpus/templates/design/app/components/design/edit-panel/inspect-code-source.ts +93 -0
  170. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -2
  171. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +35 -0
  172. package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +24 -0
  173. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -0
  174. package/corpus/templates/design/app/components/design/types.ts +29 -0
  175. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -4
  176. package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -0
  177. package/corpus/templates/design/app/i18n-data.ts +153 -46
  178. package/corpus/templates/design/app/i18n-responsive-interact.ts +12 -12
  179. package/corpus/templates/design/app/lib/design-editor-route.ts +23 -0
  180. package/corpus/templates/design/app/pages/VisualEdit.tsx +19 -6
  181. package/corpus/templates/design/app/pages/design-editor/action-error.ts +19 -0
  182. package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +29 -0
  183. package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +6 -0
  184. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +277 -15
  185. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +75 -9
  186. package/corpus/templates/design/app/pages/design-editor/layer-state-scope.ts +28 -0
  187. package/corpus/templates/design/app/pages/design-editor/live-screen-layer-drop.ts +41 -0
  188. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +496 -41
  189. package/corpus/templates/design/app/pages/design-editor/pending-live-edit-unload-guard.ts +27 -0
  190. package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +10 -0
  191. package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +168 -9
  192. package/corpus/templates/design/app/pages/design-editor/responsive-interact.ts +41 -3
  193. package/corpus/templates/design/app/pages/design-editor/screen-command-utils.ts +5 -0
  194. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +42 -13
  195. package/corpus/templates/design/app/pages/design-editor/source-location.ts +180 -0
  196. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +17 -0
  197. package/corpus/templates/design/app/public-routes.ts +1 -0
  198. package/corpus/templates/design/app/routes/visual-edit.$id.tsx +15 -0
  199. package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +1 -1
  200. package/corpus/templates/design/changelog/2026-07-28-deleting-a-selected-element-now-removes-it-from-the-live-pre.md +6 -0
  201. package/corpus/templates/design/changelog/2026-07-28-deleting-an-element-on-a-connected-localhost-screen-now-queu.md +6 -0
  202. package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-shows-a-responsive-device-preview-with-pre.md +6 -0
  203. package/corpus/templates/design/changelog/2026-07-28-layer-hide-and-lock-now-apply-to-the-live-preview-instead-of.md +6 -0
  204. package/corpus/templates/design/changelog/2026-07-28-layers-panel-selections-on-a-connected-localhost-screen-can-.md +6 -0
  205. package/corpus/templates/design/changelog/2026-07-28-locked-layers-now-show-a-subtle-dashed-outline-in-the-live-p.md +6 -0
  206. package/corpus/templates/design/changelog/2026-07-28-the-apply-design-updates-button-now-counts-pending-live-text.md +6 -0
  207. package/corpus/templates/design/changelog/2026-07-28-the-design-canvas-no-longer-stalls-on-a-render-loop-while-a-.md +6 -0
  208. package/corpus/templates/design/changelog/2026-07-28-visual-edit-on-a-local-dev-server-no-longer-requires-signing.md +6 -0
  209. package/corpus/templates/design/changelog/2026-07-28-visual-edits-on-a-react-19-app-no-longer-report-a-source-lin.md +6 -0
  210. package/corpus/templates/design/changelog/2026-07-29-an-edit-that-cannot-be-written-to-source-now-names-the-reaso.md +6 -0
  211. package/corpus/templates/design/changelog/2026-07-29-applying-a-primitive-dropped-onto-a-connected-localhost-scre.md +6 -0
  212. package/corpus/templates/design/changelog/2026-07-29-changing-a-style-in-the-inspector-now-updates-a-connected-lo.md +6 -0
  213. package/corpus/templates/design/changelog/2026-07-29-choosing-edit-or-annotate-from-a-focused-screen-now-returns-.md +6 -0
  214. package/corpus/templates/design/changelog/2026-07-29-concurrent-source-edits-now-return-a-clear-conflict-response.md +6 -0
  215. package/corpus/templates/design/changelog/2026-07-29-creating-a-component-from-an-element-that-repeats-in-the-sou.md +6 -0
  216. package/corpus/templates/design/changelog/2026-07-29-deleting-an-element-you-just-dropped-onto-a-live-screen-no-l.md +6 -0
  217. package/corpus/templates/design/changelog/2026-07-29-dragging-a-layer-across-screens-no-longer-dies-when-the-poin.md +6 -0
  218. package/corpus/templates/design/changelog/2026-07-29-dragging-an-element-from-a-stored-screen-into-a-live-localho.md +6 -0
  219. package/corpus/templates/design/changelog/2026-07-29-drawing-a-box-on-the-canvas-and-dragging-it-into-a-connected.md +6 -0
  220. package/corpus/templates/design/changelog/2026-07-29-fixed-a-loading-screen-flicker-when-reopening-designs-with-a.md +6 -0
  221. package/corpus/templates/design/changelog/2026-07-29-interact-mode-has-edit-and-annotate-buttons-again-so-you-can.md +6 -0
  222. package/corpus/templates/design/changelog/2026-07-29-layer-groups-can-be-dropped-onto-live-localhost-screens.md +6 -0
  223. package/corpus/templates/design/changelog/2026-07-29-localhost-source-errors-now-say-what-actually-went-wrong-whi.md +6 -0
  224. package/corpus/templates/design/changelog/2026-07-29-opening-or-refreshing-a-live-localhost-screen-in-single-scre.md +6 -0
  225. package/corpus/templates/design/changelog/2026-07-29-redo-after-undoing-a-drop-onto-a-live-screen-puts-the-elemen.md +6 -0
  226. package/corpus/templates/design/changelog/2026-07-29-shapes-can-be-drawn-directly-onto-live-localhost-screens.md +6 -0
  227. package/corpus/templates/design/changelog/2026-07-29-shapes-drawn-on-the-canvas-board-now-appear-immediately-inst.md +6 -0
  228. package/corpus/templates/design/changelog/2026-07-29-style-edits-on-a-running-localhost-screen-now-preview-live-a.md +6 -0
  229. package/corpus/templates/design/changelog/2026-07-29-the-apply-design-updates-control-now-appears-as-a-clean-conn.md +6 -0
  230. package/corpus/templates/design/changelog/2026-07-29-visual-edits-on-a-mapped-component-instance-now-tell-the-age.md +6 -0
  231. package/corpus/templates/design/server/lib/design-data-access.ts +21 -7
  232. package/corpus/templates/design/server/lib/localhost-connection.ts +240 -0
  233. package/corpus/templates/design/server/routes/[...page].get.ts +2 -5
  234. package/corpus/templates/design/server/source-workspace.ts +2 -0
  235. package/corpus/templates/design/shared/code-layer.ts +43 -0
  236. package/corpus/templates/design/shared/html-content.ts +26 -0
  237. package/corpus/templates/design/shared/html-integrity.ts +21 -1
  238. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +15 -0
  239. package/corpus/templates/design/shared/source-mode.ts +76 -0
  240. package/corpus/templates/dispatch/changelog/2026-07-29-workspace-members-without-admin-access-now-see-a-clear-permi.md +6 -0
  241. package/corpus/templates/dispatch/server/lib/usage-metrics.ts +2 -1
  242. package/corpus/templates/plan/app/lib/plan-annotation-runtime.ts +3 -4
  243. package/corpus/templates/plan/server/routes/[...page].get.ts +2 -5
  244. package/corpus/templates/slides/actions/patch-deck.ts +29 -17
  245. package/corpus/toolkit/CHANGELOG.md +6 -0
  246. package/corpus/toolkit/package.json +1 -1
  247. package/corpus/toolkit/src/composer/ComposerPlusMenu.tsx +3 -2
  248. package/dist/action-ui.d.ts +1 -0
  249. package/dist/action-ui.d.ts.map +1 -1
  250. package/dist/action-ui.js +1 -0
  251. package/dist/action-ui.js.map +1 -1
  252. package/dist/action.d.ts +5 -1
  253. package/dist/action.d.ts.map +1 -1
  254. package/dist/action.js.map +1 -1
  255. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  256. package/dist/agent/engine/ai-sdk-engine.js +13 -5
  257. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  258. package/dist/agent/harness/runner.d.ts.map +1 -1
  259. package/dist/agent/harness/runner.js +5 -0
  260. package/dist/agent/harness/runner.js.map +1 -1
  261. package/dist/agent/production-agent.d.ts +16 -0
  262. package/dist/agent/production-agent.d.ts.map +1 -1
  263. package/dist/agent/production-agent.js +18 -1
  264. package/dist/agent/production-agent.js.map +1 -1
  265. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  266. package/dist/agent/run-loop-with-resume.js +6 -0
  267. package/dist/agent/run-loop-with-resume.js.map +1 -1
  268. package/dist/agent/run-manager.d.ts +14 -0
  269. package/dist/agent/run-manager.d.ts.map +1 -1
  270. package/dist/agent/run-manager.js +91 -1
  271. package/dist/agent/run-manager.js.map +1 -1
  272. package/dist/agent/thread-data-builder.d.ts +3 -0
  273. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  274. package/dist/agent/thread-data-builder.js +35 -3
  275. package/dist/agent/thread-data-builder.js.map +1 -1
  276. package/dist/agent/types.d.ts +2 -0
  277. package/dist/agent/types.d.ts.map +1 -1
  278. package/dist/agent/types.js.map +1 -1
  279. package/dist/chat-threads/store.d.ts.map +1 -1
  280. package/dist/chat-threads/store.js +4 -6
  281. package/dist/chat-threads/store.js.map +1 -1
  282. package/dist/cli/create.d.ts +66 -6
  283. package/dist/cli/create.d.ts.map +1 -1
  284. package/dist/cli/create.js +765 -66
  285. package/dist/cli/create.js.map +1 -1
  286. package/dist/cli/design-connect.d.ts.map +1 -1
  287. package/dist/cli/design-connect.js +2 -7
  288. package/dist/cli/design-connect.js.map +1 -1
  289. package/dist/cli/index.js +5 -3
  290. package/dist/cli/index.js.map +1 -1
  291. package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
  292. package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
  293. package/dist/cli/skills-content/design-visual-edit-skill.js +83 -47
  294. package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
  295. package/dist/client/AssistantChat.d.ts.map +1 -1
  296. package/dist/client/AssistantChat.js +16 -9
  297. package/dist/client/AssistantChat.js.map +1 -1
  298. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  299. package/dist/client/agent-chat-adapter.js +21 -0
  300. package/dist/client/agent-chat-adapter.js.map +1 -1
  301. package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
  302. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
  303. package/dist/client/blocks/library/wireframe-kit.js +8 -2
  304. package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
  305. package/dist/client/chat/index.d.ts +1 -1
  306. package/dist/client/chat/index.d.ts.map +1 -1
  307. package/dist/client/chat/index.js +1 -1
  308. package/dist/client/chat/index.js.map +1 -1
  309. package/dist/client/chat/message-components.d.ts +17 -0
  310. package/dist/client/chat/message-components.d.ts.map +1 -1
  311. package/dist/client/chat/message-components.js +24 -2
  312. package/dist/client/chat/message-components.js.map +1 -1
  313. package/dist/client/chat/run-recovery.d.ts +6 -0
  314. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  315. package/dist/client/chat/run-recovery.js +13 -3
  316. package/dist/client/chat/run-recovery.js.map +1 -1
  317. package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
  318. package/dist/client/chat/widgets/DataTableWidget.js +2 -3
  319. package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
  320. package/dist/client/chat/widgets/WorkspaceFileWidget.d.ts +5 -0
  321. package/dist/client/chat/widgets/WorkspaceFileWidget.d.ts.map +1 -0
  322. package/dist/client/chat/widgets/WorkspaceFileWidget.js +34 -0
  323. package/dist/client/chat/widgets/WorkspaceFileWidget.js.map +1 -0
  324. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  325. package/dist/client/chat/widgets/builtin-tool-renderers.js +13 -1
  326. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  327. package/dist/client/chat/widgets/workspace-file-result.d.ts +12 -0
  328. package/dist/client/chat/widgets/workspace-file-result.d.ts.map +1 -0
  329. package/dist/client/chat/widgets/workspace-file-result.js +34 -0
  330. package/dist/client/chat/widgets/workspace-file-result.js.map +1 -0
  331. package/dist/client/embed-auth.d.ts.map +1 -1
  332. package/dist/client/embed-auth.js +2 -1
  333. package/dist/client/embed-auth.js.map +1 -1
  334. package/dist/client/org/InvitationBanner.d.ts +5 -2
  335. package/dist/client/org/InvitationBanner.d.ts.map +1 -1
  336. package/dist/client/org/InvitationBanner.js +9 -2
  337. package/dist/client/org/InvitationBanner.js.map +1 -1
  338. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  339. package/dist/client/org/OrgSwitcher.js +3 -2
  340. package/dist/client/org/OrgSwitcher.js.map +1 -1
  341. package/dist/client/org/TeamPage.d.ts.map +1 -1
  342. package/dist/client/org/TeamPage.js +27 -3
  343. package/dist/client/org/TeamPage.js.map +1 -1
  344. package/dist/client/org/WorkspaceNotice.d.ts +18 -0
  345. package/dist/client/org/WorkspaceNotice.d.ts.map +1 -0
  346. package/dist/client/org/WorkspaceNotice.js +56 -0
  347. package/dist/client/org/WorkspaceNotice.js.map +1 -0
  348. package/dist/client/org/hooks.d.ts +1 -0
  349. package/dist/client/org/hooks.d.ts.map +1 -1
  350. package/dist/client/org/hooks.js +12 -0
  351. package/dist/client/org/hooks.js.map +1 -1
  352. package/dist/client/org/index.d.ts +2 -1
  353. package/dist/client/org/index.d.ts.map +1 -1
  354. package/dist/client/org/index.js +2 -1
  355. package/dist/client/org/index.js.map +1 -1
  356. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  357. package/dist/client/resources/McpIntegrationDialog.js +8 -12
  358. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  359. package/dist/client/resources/ResourcesPanel.d.ts +3 -0
  360. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  361. package/dist/client/resources/ResourcesPanel.js +49 -20
  362. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  363. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  364. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  365. package/dist/client/resources/mcp-integration-catalog.js +3 -0
  366. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  367. package/dist/client/resources/use-resources.d.ts +1 -0
  368. package/dist/client/resources/use-resources.d.ts.map +1 -1
  369. package/dist/client/resources/use-resources.js +3 -0
  370. package/dist/client/resources/use-resources.js.map +1 -1
  371. package/dist/client/use-action.d.ts +3 -1
  372. package/dist/client/use-action.d.ts.map +1 -1
  373. package/dist/client/use-action.js +3 -1
  374. package/dist/client/use-action.js.map +1 -1
  375. package/dist/client/widgets/index.d.ts +1 -1
  376. package/dist/client/widgets/index.d.ts.map +1 -1
  377. package/dist/client/widgets/index.js +1 -1
  378. package/dist/client/widgets/index.js.map +1 -1
  379. package/dist/coding-tools/run-code.js +2 -1
  380. package/dist/coding-tools/run-code.js.map +1 -1
  381. package/dist/collab/awareness.d.ts +2 -2
  382. package/dist/collab/awareness.d.ts.map +1 -1
  383. package/dist/collab/routes.d.ts +1 -1
  384. package/dist/db/client.d.ts +1 -0
  385. package/dist/db/client.d.ts.map +1 -1
  386. package/dist/db/client.js +24 -3
  387. package/dist/db/client.js.map +1 -1
  388. package/dist/deploy/build.d.ts.map +1 -1
  389. package/dist/deploy/build.js +25 -3
  390. package/dist/deploy/build.js.map +1 -1
  391. package/dist/eject/remote-mcp-presets.js +1 -1
  392. package/dist/eject/remote-mcp-presets.js.map +1 -1
  393. package/dist/index.browser.d.ts +1 -1
  394. package/dist/index.browser.d.ts.map +1 -1
  395. package/dist/index.browser.js +1 -1
  396. package/dist/index.browser.js.map +1 -1
  397. package/dist/index.d.ts +1 -1
  398. package/dist/index.d.ts.map +1 -1
  399. package/dist/index.js +1 -1
  400. package/dist/index.js.map +1 -1
  401. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  402. package/dist/integrations/google-docs-poller.js +4 -1
  403. package/dist/integrations/google-docs-poller.js.map +1 -1
  404. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  405. package/dist/integrations/webhook-handler.js +23 -11
  406. package/dist/integrations/webhook-handler.js.map +1 -1
  407. package/dist/jobs/scheduler.js +4 -0
  408. package/dist/jobs/scheduler.js.map +1 -1
  409. package/dist/localization/default-messages.d.ts +3 -2
  410. package/dist/localization/default-messages.d.ts.map +1 -1
  411. package/dist/localization/default-messages.js +3 -2
  412. package/dist/localization/default-messages.js.map +1 -1
  413. package/dist/mcp/build-server.d.ts.map +1 -1
  414. package/dist/mcp/build-server.js +10 -1
  415. package/dist/mcp/build-server.js.map +1 -1
  416. package/dist/notifications/routes.d.ts +1 -1
  417. package/dist/observability/traces.d.ts.map +1 -1
  418. package/dist/observability/traces.js +27 -7
  419. package/dist/observability/traces.js.map +1 -1
  420. package/dist/org/handlers.d.ts +15 -0
  421. package/dist/org/handlers.d.ts.map +1 -1
  422. package/dist/org/handlers.js +45 -1
  423. package/dist/org/handlers.js.map +1 -1
  424. package/dist/org/migrations.d.ts.map +1 -1
  425. package/dist/org/migrations.js +4 -0
  426. package/dist/org/migrations.js.map +1 -1
  427. package/dist/org/plugin.d.ts +1 -0
  428. package/dist/org/plugin.d.ts.map +1 -1
  429. package/dist/org/plugin.js +10 -1
  430. package/dist/org/plugin.js.map +1 -1
  431. package/dist/org/schema.d.ts +19 -0
  432. package/dist/org/schema.d.ts.map +1 -1
  433. package/dist/org/schema.js +1 -0
  434. package/dist/org/schema.js.map +1 -1
  435. package/dist/org/types.d.ts +8 -0
  436. package/dist/org/types.d.ts.map +1 -1
  437. package/dist/org/types.js.map +1 -1
  438. package/dist/org/workspace-url.d.ts +32 -0
  439. package/dist/org/workspace-url.d.ts.map +1 -0
  440. package/dist/org/workspace-url.js +63 -0
  441. package/dist/org/workspace-url.js.map +1 -0
  442. package/dist/progress/routes.d.ts +1 -1
  443. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  444. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  445. package/dist/resources/handlers.d.ts +2 -3
  446. package/dist/resources/handlers.d.ts.map +1 -1
  447. package/dist/resources/handlers.js +25 -5
  448. package/dist/resources/handlers.js.map +1 -1
  449. package/dist/scripts/runner.d.ts +17 -0
  450. package/dist/scripts/runner.d.ts.map +1 -1
  451. package/dist/scripts/runner.js +130 -5
  452. package/dist/scripts/runner.js.map +1 -1
  453. package/dist/secrets/routes.d.ts +9 -9
  454. package/dist/server/action-routes.d.ts.map +1 -1
  455. package/dist/server/action-routes.js +24 -2
  456. package/dist/server/action-routes.js.map +1 -1
  457. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  458. package/dist/server/agent-chat-plugin.js +26 -1
  459. package/dist/server/agent-chat-plugin.js.map +1 -1
  460. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  461. package/dist/server/agent-teams.d.ts.map +1 -1
  462. package/dist/server/agent-teams.js +10 -1
  463. package/dist/server/agent-teams.js.map +1 -1
  464. package/dist/server/auth.d.ts +22 -0
  465. package/dist/server/auth.d.ts.map +1 -1
  466. package/dist/server/auth.js +33 -7
  467. package/dist/server/auth.js.map +1 -1
  468. package/dist/server/embed-route.d.ts.map +1 -1
  469. package/dist/server/embed-route.js +6 -1
  470. package/dist/server/embed-route.js.map +1 -1
  471. package/dist/server/embed-session.d.ts +7 -0
  472. package/dist/server/embed-session.d.ts.map +1 -1
  473. package/dist/server/embed-session.js +46 -4
  474. package/dist/server/embed-session.js.map +1 -1
  475. package/dist/server/open-route.d.ts.map +1 -1
  476. package/dist/server/open-route.js +17 -7
  477. package/dist/server/open-route.js.map +1 -1
  478. package/dist/server/prompts/framework-core-compact.js +1 -1
  479. package/dist/server/prompts/framework-core-compact.js.map +1 -1
  480. package/dist/server/prompts/framework-core.d.ts.map +1 -1
  481. package/dist/server/prompts/framework-core.js +1 -0
  482. package/dist/server/prompts/framework-core.js.map +1 -1
  483. package/dist/server/request-context.d.ts +26 -0
  484. package/dist/server/request-context.d.ts.map +1 -1
  485. package/dist/server/request-context.js +18 -1
  486. package/dist/server/request-context.js.map +1 -1
  487. package/dist/shared/embed-auth.d.ts +1 -0
  488. package/dist/shared/embed-auth.d.ts.map +1 -1
  489. package/dist/shared/embed-auth.js +1 -0
  490. package/dist/shared/embed-auth.js.map +1 -1
  491. package/dist/shared/html-document.d.ts +12 -0
  492. package/dist/shared/html-document.d.ts.map +1 -0
  493. package/dist/shared/html-document.js +92 -0
  494. package/dist/shared/html-document.js.map +1 -0
  495. package/dist/shared/index.d.ts +1 -0
  496. package/dist/shared/index.d.ts.map +1 -1
  497. package/dist/shared/index.js +1 -0
  498. package/dist/shared/index.js.map +1 -1
  499. package/dist/sharing/access.d.ts +1 -0
  500. package/dist/sharing/access.d.ts.map +1 -1
  501. package/dist/sharing/access.js +8 -2
  502. package/dist/sharing/access.js.map +1 -1
  503. package/dist/sharing/registry.d.ts +3 -0
  504. package/dist/sharing/registry.d.ts.map +1 -1
  505. package/dist/sharing/registry.js.map +1 -1
  506. package/dist/workspace-files/actions.d.ts +28 -0
  507. package/dist/workspace-files/actions.d.ts.map +1 -0
  508. package/dist/workspace-files/actions.js +75 -0
  509. package/dist/workspace-files/actions.js.map +1 -0
  510. package/dist/workspace-files/tool.d.ts.map +1 -1
  511. package/dist/workspace-files/tool.js +4 -0
  512. package/dist/workspace-files/tool.js.map +1 -1
  513. package/docs/content/cloneable-saas.mdx +114 -0
  514. package/docs/content/creating-templates.mdx +28 -2
  515. package/docs/content/syncing-template-changes.mdx +7 -0
  516. package/docs/content/template-clips-developers.mdx +12 -5
  517. package/docs/content/template-dispatch-developers.mdx +1 -1
  518. package/docs/content/template-dispatch.mdx +1 -1
  519. package/package.json +2 -2
  520. package/src/action-ui.ts +1 -0
  521. package/src/action.ts +5 -1
  522. package/src/agent/engine/ai-sdk-engine.ts +15 -5
  523. package/src/agent/harness/runner.ts +5 -0
  524. package/src/agent/production-agent.ts +33 -0
  525. package/src/agent/run-loop-with-resume.ts +5 -0
  526. package/src/agent/run-manager.ts +126 -1
  527. package/src/agent/thread-data-builder.ts +47 -2
  528. package/src/agent/types.ts +2 -0
  529. package/src/chat-threads/store.ts +4 -5
  530. package/src/cli/create.ts +1139 -65
  531. package/src/cli/design-connect.ts +3 -7
  532. package/src/cli/index.ts +5 -3
  533. package/src/cli/skills-content/design-visual-edit-skill.ts +83 -47
  534. package/src/client/AssistantChat.tsx +27 -16
  535. package/src/client/agent-chat-adapter.ts +24 -0
  536. package/src/client/blocks/library/wireframe-kit.tsx +17 -2
  537. package/src/client/chat/index.ts +1 -0
  538. package/src/client/chat/message-components.tsx +104 -1
  539. package/src/client/chat/run-recovery.tsx +15 -3
  540. package/src/client/chat/widgets/DataTableWidget.tsx +10 -29
  541. package/src/client/chat/widgets/WorkspaceFileWidget.tsx +71 -0
  542. package/src/client/chat/widgets/builtin-tool-renderers.tsx +22 -0
  543. package/src/client/chat/widgets/workspace-file-result.ts +49 -0
  544. package/src/client/embed-auth.ts +2 -0
  545. package/src/client/org/InvitationBanner.tsx +14 -1
  546. package/src/client/org/OrgSwitcher.tsx +23 -0
  547. package/src/client/org/TeamPage.tsx +130 -0
  548. package/src/client/org/WorkspaceNotice.tsx +85 -0
  549. package/src/client/org/hooks.ts +14 -0
  550. package/src/client/org/index.ts +2 -0
  551. package/src/client/resources/McpIntegrationDialog.tsx +27 -40
  552. package/src/client/resources/ResourcesPanel.tsx +134 -51
  553. package/src/client/resources/mcp-integration-catalog.ts +7 -0
  554. package/src/client/resources/use-resources.ts +6 -0
  555. package/src/client/use-action.ts +3 -1
  556. package/src/client/widgets/index.ts +1 -0
  557. package/src/coding-tools/run-code.ts +2 -1
  558. package/src/db/client.ts +28 -4
  559. package/src/deploy/build.ts +31 -3
  560. package/src/eject/remote-mcp-presets.ts +1 -1
  561. package/src/index.browser.ts +1 -0
  562. package/src/index.ts +1 -0
  563. package/src/integrations/google-docs-poller.ts +3 -0
  564. package/src/integrations/webhook-handler.ts +28 -11
  565. package/src/jobs/scheduler.ts +4 -0
  566. package/src/localization/default-messages.ts +3 -2
  567. package/src/mcp/build-server.ts +20 -2
  568. package/src/observability/traces.ts +48 -12
  569. package/src/org/handlers.ts +52 -1
  570. package/src/org/migrations.ts +4 -0
  571. package/src/org/plugin.ts +14 -0
  572. package/src/org/schema.ts +1 -0
  573. package/src/org/types.ts +8 -0
  574. package/src/org/workspace-url.ts +74 -0
  575. package/src/resources/handlers.ts +35 -5
  576. package/src/scripts/runner.ts +183 -5
  577. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +2 -1
  578. package/src/server/action-routes.ts +32 -2
  579. package/src/server/agent-chat-plugin.ts +29 -0
  580. package/src/server/agent-teams.ts +10 -1
  581. package/src/server/auth.ts +33 -7
  582. package/src/server/embed-route.ts +9 -0
  583. package/src/server/embed-session.ts +62 -3
  584. package/src/server/open-route.ts +20 -6
  585. package/src/server/prompts/framework-core-compact.ts +1 -1
  586. package/src/server/prompts/framework-core.ts +1 -0
  587. package/src/server/request-context.ts +36 -1
  588. package/src/shared/embed-auth.ts +1 -0
  589. package/src/shared/html-document.ts +115 -0
  590. package/src/shared/index.ts +1 -0
  591. package/src/sharing/access.ts +8 -1
  592. package/src/sharing/registry.ts +11 -2
  593. package/src/workspace-files/actions.ts +100 -0
  594. package/src/workspace-files/tool.ts +4 -0
  595. package/corpus/templates/design/changelog/2026-07-28-interact-mode-can-preview-designs-in-responsive-device-sizes.md +0 -6
  596. package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-opens-a-full-screen-responsive-preview-wit.md +0 -6
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAwXA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,cAAc;IACd,iBAAiB;IACjB,qBAAqB;CACb,CAAC;AAIX;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAe;IAC1D,OAAO,CACL,MAAM,KAAK,eAAe;QAC1B,oBAAoB,CAAC,QAAQ,CAAC,MAA4B,CAAC,CAC5D,CAAC;AACJ,CAAC","sourcesContent":["import type { A2AAgentActivitySnapshot } from \"../a2a/activity.js\";\nimport type { ActionChatUIConfig } from \"../action-ui.js\";\nimport type { AgentMcpAppPayload } from \"../mcp-client/app-result.js\";\nimport type { ReasoningEffort } from \"../shared/reasoning-effort.js\";\n\nexport interface AgentNativeJsonSchema {\n type?: string | string[];\n description?: string;\n enum?: unknown[];\n const?: unknown;\n properties?: Record<string, AgentNativeJsonSchema>;\n required?: string[];\n additionalProperties?: boolean | AgentNativeJsonSchema;\n items?: AgentNativeJsonSchema;\n oneOf?: AgentNativeJsonSchema[];\n anyOf?: AgentNativeJsonSchema[];\n allOf?: AgentNativeJsonSchema[];\n not?: AgentNativeJsonSchema;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n minimum?: number;\n maximum?: number;\n minItems?: number;\n maxItems?: number;\n}\n\nexport interface ActionTool {\n description: string;\n parameters?: AgentNativeJsonSchema & {\n type: \"object\";\n properties: Record<string, AgentNativeJsonSchema>;\n required?: string[];\n };\n}\n\n/** @deprecated Use `ActionTool` instead */\nexport type ScriptTool = ActionTool;\n\nexport interface AgentMessage {\n role: \"user\" | \"assistant\";\n content: string;\n}\n\nexport type AgentChatStructuredContentPart =\n | { type: \"text\"; text: string }\n | {\n type: \"tool-call\";\n id?: string;\n toolCallId?: string;\n name?: string;\n toolName?: string;\n input?: unknown;\n args?: unknown;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n /** Persisted for replay; omitted in older rows is backfilled server-side. */\n toolName?: string;\n toolInput?: string;\n content: string;\n isError?: boolean;\n };\n\nexport interface AgentChatStructuredMessage {\n role: \"user\" | \"assistant\";\n content: AgentChatStructuredContentPart[];\n}\n\nexport interface AgentChatReference {\n type: \"file\" | \"skill\" | \"mention\" | \"agent\" | \"custom-agent\";\n path: string;\n name: string;\n source: string;\n refType?: string;\n refId?: string;\n slotKey?: string;\n slotLabel?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MentionProviderItem {\n id: string;\n label: string;\n description?: string;\n icon?: string;\n refType: string;\n refId?: string;\n refPath?: string;\n slotKey?: string;\n slotLabel?: string;\n metadata?: Record<string, unknown>;\n clearsSlots?: string[];\n relatedReferences?: MentionProviderReference[];\n}\n\nexport interface MentionProviderReference {\n label: string;\n icon?: string;\n source?: string;\n refType: string;\n refId?: string | null;\n refPath?: string | null;\n slotKey?: string;\n slotLabel?: string;\n metadata?: Record<string, unknown>;\n clearsSlots?: string[];\n relatedReferences?: MentionProviderReference[];\n}\n\nexport interface MentionProvider {\n label: string;\n icon?: string;\n search: (\n query: string,\n /** The H3 event for the current request — use to make internal API calls */\n event?: any,\n ) => MentionProviderItem[] | Promise<MentionProviderItem[]>;\n}\n\nexport interface AgentChatAttachment {\n type: string;\n name: string;\n data?: string;\n contentType?: string;\n text?: string;\n}\n\nexport interface AgentChatScope {\n type: string;\n id: string;\n label?: string;\n}\n\nexport interface AgentChatRequest {\n message: string;\n /**\n * User-visible text to persist in chat history. `message` may be normalized\n * for the model (for example mention markup or internal continuation text).\n */\n displayMessage?: string;\n history?: AgentMessage[];\n /**\n * Provider-neutral transcript used for run recovery. Unlike `history`,\n * this preserves assistant tool calls and matching tool results so\n * continuation turns do not re-run completed read-only tools.\n */\n structuredHistory?: AgentChatStructuredMessage[];\n references?: AgentChatReference[];\n threadId?: string;\n attachments?: AgentChatAttachment[];\n /** Internal retry/continuation requests should not create visible user turns. */\n internalContinuation?: boolean;\n /**\n * Internal marker set ONLY by the durable-background self-dispatch (see\n * `AGENT_CHAT_BACKGROUND_RUN_FIELD`). Present when the agent-chat handler is\n * re-entered as the background worker: it carries the pre-claimed `runId` and\n * logical `turnId` so the worker runs the loop inline with the background\n * soft-timeout instead of re-claiming the slot or re-dispatching. Untrusted\n * on its own — the `_process-run` route HMAC-verifies the dispatch before\n * invoking the handler. Absent on every normal client request.\n */\n __backgroundRun?: {\n runId: string;\n turnId?: string;\n continuationReason?:\n | \"run_timeout\"\n | \"loop_limit\"\n | \"max_tokens\"\n | \"no_progress\"\n | \"stream_ended\"\n | \"gateway_timeout\"\n | \"network_interrupted\";\n actionPreparationTool?: string;\n /**\n * Number of server-driven background→background continuations already\n * chained into this logical turn (0 on the first chunk). The worker\n * increments this when it re-fires `_process-run` at a soft-timeout\n * boundary and refuses to chain past `MAX_BACKGROUND_RUN_CONTINUATIONS`.\n */\n continuationCount?: number;\n /**\n * True when the dispatcher expects the self-POST to land in a real\n * Netlify `-background` function rather than the ~60s synchronous function.\n * This is diagnostic only; the 15-minute budget is unlocked by the worker's\n * actual runtime marker.\n */\n backgroundFunctionRuntimeExpected?: boolean;\n /**\n * True when the dispatch body carries ONLY this marker and the worker\n * must rehydrate the full request body from the run row's\n * `dispatch_payload` column (`readRunDispatchPayload`). Keeps the\n * self-POST under Netlify's 256KB background-function body cap.\n */\n payloadRef?: boolean;\n };\n /**\n * Stable identity for the logical assistant turn this request belongs to.\n * The client sends the SAME turnId for the initial POST and every\n * auto-continuation re-POST of one turn, so the server can fold each\n * continuation run's output onto a single durable assistant message instead\n * of dropping the earlier chunks. Defaults to the run id when absent.\n */\n turnId?: string;\n /** Execution mode for this turn. Plan mode is read-only and proposes before acting. */\n mode?: \"act\" | \"plan\";\n /** Per-request model override (ephemeral, from the composer model picker). */\n model?: string;\n /** Per-request engine override (sent alongside model for cross-provider switches). */\n engine?: string;\n /** Per-request reasoning effort override (ephemeral, from the composer picker). */\n effort?: ReasoningEffort;\n /** Usage-tracking label for this call (e.g. \"chat\", \"summarize\"). Default: \"chat\". */\n usageLabel?: string;\n /** Stable browser tab id so screen/url context and navigation commands are tab-scoped. */\n browserTabId?: string;\n /** Resource scope for this chat thread, e.g. the deck currently bound to the tab. */\n scope?: AgentChatScope | null;\n /** When true, expose this chat turn as a user-visible run in RunsTray. */\n trackInRunsTray?: boolean;\n /**\n * Approval grants for human-in-the-loop actions. Each entry is a stable\n * approval key (see the `approval_required` event's `approvalKey`). When the\n * agent calls an action declared `needsApproval`, the loop pauses and emits\n * `approval_required`; the client re-issues the turn (typically an empty\n * continuation) with the approved call's key here so the gate lets it run.\n * Keys not present here keep the action paused. The model never sees or sets\n * this — it is supplied by the human's approve affordance.\n */\n approvedToolCalls?: string[];\n}\n\nexport type AgentToolInput = Record<string, unknown>;\n\nexport type AgentChatEvent =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; text: string }\n | {\n type: \"activity\";\n label: string;\n tool?: string;\n id?: string;\n progressBytes?: number;\n }\n | { type: \"stream_keepalive\" }\n | { type: \"tool_start\"; tool: string; id?: string; input: AgentToolInput }\n | {\n type: \"tool_done\";\n tool: string;\n id?: string;\n input?: AgentToolInput;\n result: string;\n isError?: boolean;\n completedSideEffect?: boolean;\n mcpApp?: AgentMcpAppPayload;\n chatUI?: ActionChatUIConfig;\n }\n | {\n /**\n * The agent tried to call an action declared `needsApproval` and the loop\n * paused instead of executing it. The client should surface an\n * approve/deny affordance; on approve, re-issue the turn with\n * `approvedToolCalls: [approvalKey]` so the gate lets this call run.\n */\n type: \"approval_required\";\n tool: string;\n input: Record<string, string>;\n /** Stable key the client echoes back in `approvedToolCalls` to approve. */\n approvalKey: string;\n /** The model-side tool-call id for this paused call, when available. */\n toolCallId?: string;\n }\n | {\n type: \"agent_call\";\n agent: string;\n status: \"start\" | \"done\" | \"error\";\n agentCallId?: string;\n durationMs?: number;\n }\n | {\n /**\n * Periodic liveness for an in-flight cross-app A2A call. Emitted by the\n * `call-agent` action once per throttle window ONLY when a real poll\n * round-trip to the remote agent succeeds and reports a non-terminal\n * state — never on a timer, so a hung/dead remote emits nothing and the\n * stuck-detector can still fire. Counts as real progress in\n * `run-manager`'s `shouldBumpProgressForEvent` (any non-special event\n * type does), which keeps `last_progress_at` fresh so a slow-but-healthy\n * sub-agent call doesn't trip the client's stuck banner. A distinct\n * event type (not an `agent_call` status) so existing `agent_call`\n * consumers that treat \"not start/done\" as a failure don't render an\n * in-flight tick as an error.\n */\n type: \"agent_call_progress\";\n agent: string;\n /** Remote A2A task state for this poll, e.g. \"working\" | \"processing\". */\n state: string;\n /** Elapsed wall-clock seconds since the cross-app call began. */\n elapsedSeconds: number;\n /** Optional short text surfaced from the remote poll, when present. */\n detail?: string;\n agentCallId?: string;\n }\n | {\n type: \"agent_call_text\";\n agent: string;\n text: string;\n agentCallId?: string;\n }\n | {\n type: \"agent_call_activity\";\n agent: string;\n snapshot: A2AAgentActivitySnapshot;\n agentCallId?: string;\n }\n | {\n type: \"agent_task\";\n taskId: string;\n threadId: string;\n description: string;\n status: \"running\" | \"completed\" | \"errored\";\n }\n | {\n type: \"agent_task_update\";\n taskId: string;\n preview: string;\n currentStep?: string;\n }\n | {\n type: \"agent_task_complete\";\n taskId: string;\n summary: string;\n }\n | { type: \"done\" }\n | {\n type: \"error\";\n error: string;\n /**\n * Optional machine-readable error code. Builder gateway uses codes\n * like \"credits-limit-monthly\" / \"unauthorized\" / \"gateway_not_enabled\"\n * so the chat UI can render a structured CTA (e.g. upgrade button).\n */\n errorCode?: string;\n /** Optional link paired with errorCode — e.g. Builder billing page. */\n upgradeUrl?: string;\n /** Optional details for expandable UI/debugging. */\n details?: string;\n /** True when the user can reasonably continue/retry from partial work. */\n recoverable?: boolean;\n }\n /**\n * Legacy SSE terminal event. New streams emit\n * `{ type: \"error\", errorCode: \"missing_credentials\" }` instead.\n */\n | { type: \"missing_api_key\" }\n | { type: \"loop_limit\"; maxIterations?: number }\n | {\n /**\n * An in-loop `Processor` aborted the run via `abort()` (which throws a\n * `TripWire`). The loop catches it, emits this event, stops cleanly, and\n * surfaces the reason as a final assistant message. Structural hook for\n * real-time guardrails and a proof-of-done / coverage gate.\n */\n type: \"tripwire\";\n reason: string;\n /** Name of the processor that aborted, when it declared one. */\n processor?: string;\n }\n | {\n type: \"auto_continue\";\n reason: ContinuationReason;\n maxIterations?: number;\n }\n | { type: \"clear\" };\n\nexport const CONTINUATION_REASONS = [\n \"run_timeout\",\n \"loop_limit\",\n \"max_tokens\",\n \"no_progress\",\n \"stream_ended\",\n \"gateway_timeout\",\n \"network_interrupted\",\n] as const;\n\nexport type ContinuationReason = (typeof CONTINUATION_REASONS)[number];\n\n/**\n * True when an `agent_runs.terminal_reason` marks a CHUNK boundary rather than\n * the end of the turn — i.e. the run was TRUNCATED at a budget/timeout/loop/\n * no-progress boundary and did not finish what it was asked to do.\n *\n * This is the single predicate for \"the reason says this run did not finish\".\n * `setRunTerminalReason` (run-store) uses it to record `status='truncated'`\n * instead of `'completed'`, so consumers should read the status rather than\n * re-deriving truncation from the reason. It stays exported for legacy\n * `status='completed'` rows written before the `truncated` status existed,\n * which linger for one retention window.\n */\nexport function isContinuationTerminalReason(reason: unknown): boolean {\n return (\n reason === \"auto_continue\" ||\n CONTINUATION_REASONS.includes(reason as ContinuationReason)\n );\n}\n\nexport interface RunEvent {\n seq: number;\n event: AgentChatEvent;\n}\n\n/**\n * `agent_runs.status`. `completed` means the turn actually finished (terminal\n * reason `done`); `truncated` means it stopped at a budget/timeout/loop/\n * no-progress boundary with work still outstanding. Truncations were previously\n * filed as `completed`, which made them invisible to every success-rate query\n * and — because retention keys off status — deleted them a week before the\n * genuine failures they belong with.\n */\nexport type RunStatus =\n | \"running\"\n | \"completed\"\n | \"truncated\"\n | \"errored\"\n | \"aborted\";\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AA0XA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,cAAc;IACd,iBAAiB;IACjB,qBAAqB;CACb,CAAC;AAIX;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAe;IAC1D,OAAO,CACL,MAAM,KAAK,eAAe;QAC1B,oBAAoB,CAAC,QAAQ,CAAC,MAA4B,CAAC,CAC5D,CAAC;AACJ,CAAC","sourcesContent":["import type { A2AAgentActivitySnapshot } from \"../a2a/activity.js\";\nimport type { ActionChatUIConfig } from \"../action-ui.js\";\nimport type { AgentMcpAppPayload } from \"../mcp-client/app-result.js\";\nimport type { ReasoningEffort } from \"../shared/reasoning-effort.js\";\n\nexport interface AgentNativeJsonSchema {\n type?: string | string[];\n description?: string;\n enum?: unknown[];\n const?: unknown;\n properties?: Record<string, AgentNativeJsonSchema>;\n required?: string[];\n additionalProperties?: boolean | AgentNativeJsonSchema;\n items?: AgentNativeJsonSchema;\n oneOf?: AgentNativeJsonSchema[];\n anyOf?: AgentNativeJsonSchema[];\n allOf?: AgentNativeJsonSchema[];\n not?: AgentNativeJsonSchema;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n minimum?: number;\n maximum?: number;\n minItems?: number;\n maxItems?: number;\n}\n\nexport interface ActionTool {\n description: string;\n parameters?: AgentNativeJsonSchema & {\n type: \"object\";\n properties: Record<string, AgentNativeJsonSchema>;\n required?: string[];\n };\n}\n\n/** @deprecated Use `ActionTool` instead */\nexport type ScriptTool = ActionTool;\n\nexport interface AgentMessage {\n role: \"user\" | \"assistant\";\n content: string;\n}\n\nexport type AgentChatStructuredContentPart =\n | { type: \"text\"; text: string }\n | {\n type: \"tool-call\";\n id?: string;\n toolCallId?: string;\n name?: string;\n toolName?: string;\n input?: unknown;\n args?: unknown;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n /** Persisted for replay; omitted in older rows is backfilled server-side. */\n toolName?: string;\n toolInput?: string;\n content: string;\n isError?: boolean;\n };\n\nexport interface AgentChatStructuredMessage {\n role: \"user\" | \"assistant\";\n content: AgentChatStructuredContentPart[];\n}\n\nexport interface AgentChatReference {\n type: \"file\" | \"skill\" | \"mention\" | \"agent\" | \"custom-agent\";\n path: string;\n name: string;\n source: string;\n refType?: string;\n refId?: string;\n slotKey?: string;\n slotLabel?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MentionProviderItem {\n id: string;\n label: string;\n description?: string;\n icon?: string;\n refType: string;\n refId?: string;\n refPath?: string;\n slotKey?: string;\n slotLabel?: string;\n metadata?: Record<string, unknown>;\n clearsSlots?: string[];\n relatedReferences?: MentionProviderReference[];\n}\n\nexport interface MentionProviderReference {\n label: string;\n icon?: string;\n source?: string;\n refType: string;\n refId?: string | null;\n refPath?: string | null;\n slotKey?: string;\n slotLabel?: string;\n metadata?: Record<string, unknown>;\n clearsSlots?: string[];\n relatedReferences?: MentionProviderReference[];\n}\n\nexport interface MentionProvider {\n label: string;\n icon?: string;\n search: (\n query: string,\n /** The H3 event for the current request — use to make internal API calls */\n event?: any,\n ) => MentionProviderItem[] | Promise<MentionProviderItem[]>;\n}\n\nexport interface AgentChatAttachment {\n type: string;\n name: string;\n data?: string;\n contentType?: string;\n text?: string;\n}\n\nexport interface AgentChatScope {\n type: string;\n id: string;\n label?: string;\n}\n\nexport interface AgentChatRequest {\n message: string;\n /** Stable identity of a durable queued message, used to reject replayed delivery. */\n queuedMessageId?: string;\n /**\n * User-visible text to persist in chat history. `message` may be normalized\n * for the model (for example mention markup or internal continuation text).\n */\n displayMessage?: string;\n history?: AgentMessage[];\n /**\n * Provider-neutral transcript used for run recovery. Unlike `history`,\n * this preserves assistant tool calls and matching tool results so\n * continuation turns do not re-run completed read-only tools.\n */\n structuredHistory?: AgentChatStructuredMessage[];\n references?: AgentChatReference[];\n threadId?: string;\n attachments?: AgentChatAttachment[];\n /** Internal retry/continuation requests should not create visible user turns. */\n internalContinuation?: boolean;\n /**\n * Internal marker set ONLY by the durable-background self-dispatch (see\n * `AGENT_CHAT_BACKGROUND_RUN_FIELD`). Present when the agent-chat handler is\n * re-entered as the background worker: it carries the pre-claimed `runId` and\n * logical `turnId` so the worker runs the loop inline with the background\n * soft-timeout instead of re-claiming the slot or re-dispatching. Untrusted\n * on its own — the `_process-run` route HMAC-verifies the dispatch before\n * invoking the handler. Absent on every normal client request.\n */\n __backgroundRun?: {\n runId: string;\n turnId?: string;\n continuationReason?:\n | \"run_timeout\"\n | \"loop_limit\"\n | \"max_tokens\"\n | \"no_progress\"\n | \"stream_ended\"\n | \"gateway_timeout\"\n | \"network_interrupted\";\n actionPreparationTool?: string;\n /**\n * Number of server-driven background→background continuations already\n * chained into this logical turn (0 on the first chunk). The worker\n * increments this when it re-fires `_process-run` at a soft-timeout\n * boundary and refuses to chain past `MAX_BACKGROUND_RUN_CONTINUATIONS`.\n */\n continuationCount?: number;\n /**\n * True when the dispatcher expects the self-POST to land in a real\n * Netlify `-background` function rather than the ~60s synchronous function.\n * This is diagnostic only; the 15-minute budget is unlocked by the worker's\n * actual runtime marker.\n */\n backgroundFunctionRuntimeExpected?: boolean;\n /**\n * True when the dispatch body carries ONLY this marker and the worker\n * must rehydrate the full request body from the run row's\n * `dispatch_payload` column (`readRunDispatchPayload`). Keeps the\n * self-POST under Netlify's 256KB background-function body cap.\n */\n payloadRef?: boolean;\n };\n /**\n * Stable identity for the logical assistant turn this request belongs to.\n * The client sends the SAME turnId for the initial POST and every\n * auto-continuation re-POST of one turn, so the server can fold each\n * continuation run's output onto a single durable assistant message instead\n * of dropping the earlier chunks. Defaults to the run id when absent.\n */\n turnId?: string;\n /** Execution mode for this turn. Plan mode is read-only and proposes before acting. */\n mode?: \"act\" | \"plan\";\n /** Per-request model override (ephemeral, from the composer model picker). */\n model?: string;\n /** Per-request engine override (sent alongside model for cross-provider switches). */\n engine?: string;\n /** Per-request reasoning effort override (ephemeral, from the composer picker). */\n effort?: ReasoningEffort;\n /** Usage-tracking label for this call (e.g. \"chat\", \"summarize\"). Default: \"chat\". */\n usageLabel?: string;\n /** Stable browser tab id so screen/url context and navigation commands are tab-scoped. */\n browserTabId?: string;\n /** Resource scope for this chat thread, e.g. the deck currently bound to the tab. */\n scope?: AgentChatScope | null;\n /** When true, expose this chat turn as a user-visible run in RunsTray. */\n trackInRunsTray?: boolean;\n /**\n * Approval grants for human-in-the-loop actions. Each entry is a stable\n * approval key (see the `approval_required` event's `approvalKey`). When the\n * agent calls an action declared `needsApproval`, the loop pauses and emits\n * `approval_required`; the client re-issues the turn (typically an empty\n * continuation) with the approved call's key here so the gate lets it run.\n * Keys not present here keep the action paused. The model never sees or sets\n * this — it is supplied by the human's approve affordance.\n */\n approvedToolCalls?: string[];\n}\n\nexport type AgentToolInput = Record<string, unknown>;\n\nexport type AgentChatEvent =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; text: string }\n | {\n type: \"activity\";\n label: string;\n tool?: string;\n id?: string;\n progressBytes?: number;\n }\n | { type: \"stream_keepalive\" }\n | { type: \"tool_start\"; tool: string; id?: string; input: AgentToolInput }\n | {\n type: \"tool_done\";\n tool: string;\n id?: string;\n input?: AgentToolInput;\n result: string;\n isError?: boolean;\n completedSideEffect?: boolean;\n mcpApp?: AgentMcpAppPayload;\n chatUI?: ActionChatUIConfig;\n }\n | {\n /**\n * The agent tried to call an action declared `needsApproval` and the loop\n * paused instead of executing it. The client should surface an\n * approve/deny affordance; on approve, re-issue the turn with\n * `approvedToolCalls: [approvalKey]` so the gate lets this call run.\n */\n type: \"approval_required\";\n tool: string;\n input: Record<string, string>;\n /** Stable key the client echoes back in `approvedToolCalls` to approve. */\n approvalKey: string;\n /** The model-side tool-call id for this paused call, when available. */\n toolCallId?: string;\n }\n | {\n type: \"agent_call\";\n agent: string;\n status: \"start\" | \"done\" | \"error\";\n agentCallId?: string;\n durationMs?: number;\n }\n | {\n /**\n * Periodic liveness for an in-flight cross-app A2A call. Emitted by the\n * `call-agent` action once per throttle window ONLY when a real poll\n * round-trip to the remote agent succeeds and reports a non-terminal\n * state — never on a timer, so a hung/dead remote emits nothing and the\n * stuck-detector can still fire. Counts as real progress in\n * `run-manager`'s `shouldBumpProgressForEvent` (any non-special event\n * type does), which keeps `last_progress_at` fresh so a slow-but-healthy\n * sub-agent call doesn't trip the client's stuck banner. A distinct\n * event type (not an `agent_call` status) so existing `agent_call`\n * consumers that treat \"not start/done\" as a failure don't render an\n * in-flight tick as an error.\n */\n type: \"agent_call_progress\";\n agent: string;\n /** Remote A2A task state for this poll, e.g. \"working\" | \"processing\". */\n state: string;\n /** Elapsed wall-clock seconds since the cross-app call began. */\n elapsedSeconds: number;\n /** Optional short text surfaced from the remote poll, when present. */\n detail?: string;\n agentCallId?: string;\n }\n | {\n type: \"agent_call_text\";\n agent: string;\n text: string;\n agentCallId?: string;\n }\n | {\n type: \"agent_call_activity\";\n agent: string;\n snapshot: A2AAgentActivitySnapshot;\n agentCallId?: string;\n }\n | {\n type: \"agent_task\";\n taskId: string;\n threadId: string;\n description: string;\n status: \"running\" | \"completed\" | \"errored\";\n }\n | {\n type: \"agent_task_update\";\n taskId: string;\n preview: string;\n currentStep?: string;\n }\n | {\n type: \"agent_task_complete\";\n taskId: string;\n summary: string;\n }\n | { type: \"done\" }\n | {\n type: \"error\";\n error: string;\n /**\n * Optional machine-readable error code. Builder gateway uses codes\n * like \"credits-limit-monthly\" / \"unauthorized\" / \"gateway_not_enabled\"\n * so the chat UI can render a structured CTA (e.g. upgrade button).\n */\n errorCode?: string;\n /** Optional link paired with errorCode — e.g. Builder billing page. */\n upgradeUrl?: string;\n /** Optional details for expandable UI/debugging. */\n details?: string;\n /** True when the user can reasonably continue/retry from partial work. */\n recoverable?: boolean;\n }\n /**\n * Legacy SSE terminal event. New streams emit\n * `{ type: \"error\", errorCode: \"missing_credentials\" }` instead.\n */\n | { type: \"missing_api_key\" }\n | { type: \"loop_limit\"; maxIterations?: number }\n | {\n /**\n * An in-loop `Processor` aborted the run via `abort()` (which throws a\n * `TripWire`). The loop catches it, emits this event, stops cleanly, and\n * surfaces the reason as a final assistant message. Structural hook for\n * real-time guardrails and a proof-of-done / coverage gate.\n */\n type: \"tripwire\";\n reason: string;\n /** Name of the processor that aborted, when it declared one. */\n processor?: string;\n }\n | {\n type: \"auto_continue\";\n reason: ContinuationReason;\n maxIterations?: number;\n }\n | { type: \"clear\" };\n\nexport const CONTINUATION_REASONS = [\n \"run_timeout\",\n \"loop_limit\",\n \"max_tokens\",\n \"no_progress\",\n \"stream_ended\",\n \"gateway_timeout\",\n \"network_interrupted\",\n] as const;\n\nexport type ContinuationReason = (typeof CONTINUATION_REASONS)[number];\n\n/**\n * True when an `agent_runs.terminal_reason` marks a CHUNK boundary rather than\n * the end of the turn — i.e. the run was TRUNCATED at a budget/timeout/loop/\n * no-progress boundary and did not finish what it was asked to do.\n *\n * This is the single predicate for \"the reason says this run did not finish\".\n * `setRunTerminalReason` (run-store) uses it to record `status='truncated'`\n * instead of `'completed'`, so consumers should read the status rather than\n * re-deriving truncation from the reason. It stays exported for legacy\n * `status='completed'` rows written before the `truncated` status existed,\n * which linger for one retention window.\n */\nexport function isContinuationTerminalReason(reason: unknown): boolean {\n return (\n reason === \"auto_continue\" ||\n CONTINUATION_REASONS.includes(reason as ContinuationReason)\n );\n}\n\nexport interface RunEvent {\n seq: number;\n event: AgentChatEvent;\n}\n\n/**\n * `agent_runs.status`. `completed` means the turn actually finished (terminal\n * reason `done`); `truncated` means it stopped at a budget/timeout/loop/\n * no-progress boundary with work still outstanding. Truncations were previously\n * filed as `completed`, which made them invisible to every success-rate query\n * and — because retention keys off status — deleted them a week before the\n * genuine failures they belong with.\n */\nexport type RunStatus =\n | \"running\"\n | \"completed\"\n | \"truncated\"\n | \"errored\"\n | \"aborted\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/chat-threads/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/chat-threads/store.ts"],"names":[],"mappings":"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"}
@@ -787,12 +787,10 @@ export async function setThreadQueuedMessages(threadId, queuedMessages, options
787
787
  data = JSON.parse(thread.threadData);
788
788
  }
789
789
  catch { }
790
- if (queuedMessages.length === 0) {
791
- delete data.queuedMessages;
792
- }
793
- else {
794
- data.queuedMessages = queuedMessages;
795
- }
790
+ // Keep an explicit empty tombstone. Other mounted chat surfaces only
791
+ // reconcile queue state when this field is present; deleting it lets a
792
+ // stale local queue survive the clear and submit the same prompt again.
793
+ data.queuedMessages = queuedMessages;
796
794
  await updateThreadData(threadId, JSON.stringify(data), thread.title, thread.preview, thread.messageCount, { preserveExistingQueuedMessages: false });
797
795
  return true;
798
796
  });
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/chat-threads/store.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"node:crypto\";\n\nimport {\n mergeThreadDataForClientSave,\n normalizeThreadRepository,\n normalizeThreadTitle,\n} from \"../agent/thread-data-builder.js\";\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport { createGetDb } from \"../db/create-get-db.js\";\nimport {\n ensureColumnExists,\n ensureIndexExists,\n ensureTableExists,\n} from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport { getRequestOrgId } from \"../server/request-context.js\";\nimport { resolveAccess, type AccessContext } from \"../sharing/access.js\";\nimport { registerShareableResource } from \"../sharing/registry.js\";\nimport { roleSatisfies, type ShareRole } from \"../sharing/schema.js\";\nimport { emitChatThreadChange } from \"./emitter.js\";\nimport {\n chatThreads,\n chatThreadShares,\n CHAT_THREAD_SHARES_CREATE_SQL,\n CHAT_THREAD_SHARES_CREATE_SQL_PG,\n CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,\n} from \"./schema.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n/**\n * Per-thread async mutex. Read-modify-write on the `thread_data` JSON blob\n * is not atomic at the DB level — two concurrent callers (e.g. the UI\n * persisting queued messages while `onRunComplete` appends agent output)\n * would both read the same row, each mutate it independently, and the\n * second write clobbers the first. Serializing on thread id inside this\n * process eliminates the race for the usual single-process deployment\n * while leaving straight reads and other thread-data-unrelated updates\n * untouched.\n *\n * Cross-process races are handled by `updateThreadData`, which performs a\n * compare-and-swap on `updated_at`, rereads the latest row on conflict, and\n * remerges message history before retrying.\n */\nconst _threadDataLocks = new Map<string, Promise<unknown>>();\nconst DEFAULT_THREAD_DATA_UPDATE_ATTEMPTS = 12;\nconst THREAD_DATA_CONFLICT_BACKOFF_MS = 25;\nconst getChatThreadsDb = createGetDb({ chatThreads, chatThreadShares });\n\nexport function withThreadDataLock<T>(\n threadId: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const prev = _threadDataLocks.get(threadId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n _threadDataLocks.set(threadId, next);\n // Use `.then(cleanup, cleanup)` (not `.finally`) so the rejection is\n // observed on this chained promise — otherwise any failure inside `fn`\n // triggers `unhandledRejection` on the discarded `finally()` return.\n // The caller still sees the rejection via `next`.\n const cleanup = () => {\n if (_threadDataLocks.get(threadId) === next) {\n _threadDataLocks.delete(threadId);\n }\n };\n next.then(cleanup, cleanup);\n return next as Promise<T>;\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS chat_threads (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n title TEXT NOT NULL DEFAULT '',\n preview TEXT NOT NULL DEFAULT '',\n thread_data TEXT NOT NULL DEFAULT '{}',\n message_count ${intType()} NOT NULL DEFAULT 0,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n scope_type TEXT,\n scope_id TEXT,\n scope_label TEXT,\n pinned_at ${intType()},\n archived_at ${intType()},\n share_token_hash TEXT,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n )\n `;\n\n if (isPostgres()) {\n // Hot path: the `chat_threads` table and its indexes are virtually\n // always already present in production. Issuing `CREATE TABLE`/\n // `CREATE INDEX` still takes a lock that, in a fresh background-worker\n // process behind a concurrent connection on the shared Neon DB, can\n // block ~indefinitely (ACCESS EXCLUSIVE for CREATE TABLE; a write-\n // blocking SHARE lock for CREATE INDEX). The ensure* wrappers probe\n // `information_schema`/`pg_indexes` first (plain reads, no lock) and\n // run DDL ONLY for what is actually missing, bounded by a transaction-\n // scoped `lock_timeout`. If a swallowed lock-timeout leaves the schema\n // still missing they RE-PROBE and THROW rather than letting init\n // memoize success against absent schema. `chat_threads` is the\n // unqualified name even though the table lives in `public`.\n await ensureTableExists(\"chat_threads\", createSql);\n // Additive columns — guarded so the hot path (columns already present)\n // skips the ACCESS EXCLUSIVE ALTER entirely.\n for (const [col, type] of [\n [\"scope_type\", \"TEXT\"],\n [\"scope_id\", \"TEXT\"],\n [\"scope_label\", \"TEXT\"],\n [\"pinned_at\", intType()],\n [\"archived_at\", intType()],\n [\"share_token_hash\", \"TEXT\"],\n [\"org_id\", \"TEXT\"],\n [\"visibility\", \"TEXT NOT NULL DEFAULT 'private'\"],\n ] as const) {\n await ensureColumnExists(\n \"chat_threads\",\n col,\n `ALTER TABLE chat_threads ADD COLUMN IF NOT EXISTS ${col} ${type}`,\n );\n }\n await ensureTableExists(\n \"chat_thread_shares\",\n CHAT_THREAD_SHARES_CREATE_SQL_PG,\n );\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`; on Postgres the `Date.now()` written on every turn\n // overflows int4. No-op once widened / on fresh BIGINT databases.\n await widenIntColumnsToBigInt(\"chat_threads\", [\n \"created_at\",\n \"updated_at\",\n \"pinned_at\",\n \"archived_at\",\n ]);\n // Indexes for the hot read paths. Both the sidebar list and the\n // scoped/per-resource list filter on owner_email (and optionally\n // scope) and sort by updated_at. Probe pg_indexes first (no lock)\n // and skip the SHARE-locking CREATE INDEX when already present.\n await ensureIndexExists(\n \"chat_threads_owner_updated_idx\",\n `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`,\n );\n await ensureIndexExists(\n \"chat_threads_scope_updated_idx\",\n `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`,\n );\n // Public share-link resolution looks threads up by token hash;\n // without this index it degrades to a LIKE scan over every blob.\n await ensureIndexExists(\n \"chat_threads_share_token_idx\",\n `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`,\n );\n await ensureIndexExists(\n \"chat_thread_shares_resource_idx\",\n CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n // Additive migration for existing tables. Both SQLite and Postgres\n // accept `ALTER TABLE ADD COLUMN` and will raise when the column\n // already exists; the try/catch makes the call idempotent across\n // both dialects without requiring an information_schema probe.\n for (const [col, type] of [\n [\"scope_type\", \"TEXT\"],\n [\"scope_id\", \"TEXT\"],\n [\"scope_label\", \"TEXT\"],\n [\"pinned_at\", intType()],\n [\"archived_at\", intType()],\n [\"share_token_hash\", \"TEXT\"],\n [\"org_id\", \"TEXT\"],\n [\"visibility\", \"TEXT NOT NULL DEFAULT 'private'\"],\n ] as const) {\n try {\n await client.execute(\n `ALTER TABLE chat_threads ADD COLUMN ${col} ${type}`,\n );\n } catch {\n // Column already exists.\n }\n }\n try {\n await client.execute(CHAT_THREAD_SHARES_CREATE_SQL);\n } catch {\n // Table already exists.\n }\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`; on Postgres the `Date.now()` written on every turn\n // overflows int4. No-op once widened / on fresh BIGINT databases.\n await widenIntColumnsToBigInt(\"chat_threads\", [\n \"created_at\",\n \"updated_at\",\n \"pinned_at\",\n \"archived_at\",\n ]);\n // Indexes for the hot read paths. Both the sidebar list and the\n // scoped/per-resource list filter on owner_email (and optionally\n // scope) and sort by updated_at. Keep these dialect-agnostic (no\n // DESC, partial, or PG-only syntax) so they apply identically on\n // SQLite and the configured Postgres. `IF NOT EXISTS` makes them\n // idempotent across restarts.\n for (const ddl of [\n `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`,\n `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`,\n `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`,\n CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,\n ]) {\n try {\n await client.execute(ddl);\n } catch {\n // Index already exists or the dialect rejected a duplicate.\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\n/**\n * Explicitly repair `message_count` for legacy rows written before the count\n * was maintained. This must never run from table/bootstrap initialization:\n * serverless isolates would each scan the full `thread_data` blob column on\n * cold start. Operators may invoke it once when upgrading an old database.\n */\nexport async function repairLegacyChatThreadMessageCounts(\n options: {\n batchSize?: number;\n } = {},\n): Promise<{ scanned: number; updated: number }> {\n await ensureTable();\n const client = getDbExec();\n const batchSize = Math.max(1, Math.min(options.batchSize ?? 100, 1_000));\n let afterId = \"\";\n let scanned = 0;\n let updated = 0;\n while (true) {\n const { rows } = await client.execute({\n sql: `SELECT id, thread_data, message_count FROM chat_threads\n WHERE message_count = 0\n AND thread_data LIKE '%\"messages\"%'\n AND id > ?\n ORDER BY id\n LIMIT ?`,\n args: [afterId, batchSize],\n });\n if (rows.length === 0) break;\n for (const row of rows) {\n afterId = String(row.id);\n scanned++;\n const count = deriveMessageCount(row.thread_data, 0);\n if (count <= 0) continue;\n const result = await client.execute({\n sql: `UPDATE chat_threads SET message_count = ? WHERE id = ? AND message_count = 0`,\n args: [count, afterId],\n });\n if (result.rowsAffected > 0) updated++;\n }\n if (rows.length < batchSize) break;\n }\n return { scanned, updated };\n}\n\nfunction generateId(): string {\n return `thread-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * A resource the chat is bound to, e.g. `{ type: \"deck\", id: \"deck-abc\" }`.\n * The framework is opaque to the type string — each template chooses what\n * its primary resource is and the surface it scopes to (deck, design,\n * dashboard, etc.). `label` is a denormalized snapshot for display when\n * the resource isn't on hand at render time; the live template can\n * overwrite it via the next createThread call.\n */\nexport interface ChatThreadScope {\n type: string;\n id: string;\n label?: string;\n}\n\nexport interface ChatThread {\n id: string;\n ownerEmail: string;\n title: string;\n preview: string;\n threadData: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n scope: ChatThreadScope | null;\n pinnedAt: number | null;\n archivedAt: number | null;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\nexport interface ChatThreadSummary {\n id: string;\n title: string;\n preview: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n scope: ChatThreadScope | null;\n pinnedAt: number | null;\n archivedAt: number | null;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\nexport interface ForkThreadSourceSnapshot {\n threadData: string;\n title?: string;\n preview?: string;\n messageCount?: number;\n scope?: ChatThreadScope | null;\n}\n\nfunction readScope(r: Record<string, unknown>): ChatThreadScope | null {\n const type = r.scope_type as string | null | undefined;\n const id = r.scope_id as string | null | undefined;\n if (!type || !id) return null;\n const label = r.scope_label as string | null | undefined;\n return label ? { type, id, label } : { type, id };\n}\n\nfunction readNullableNumber(value: unknown): number | null {\n if (value == null) return null;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : null;\n}\n\nfunction readVisibility(value: unknown): \"private\" | \"org\" | \"public\" {\n return value === \"org\" || value === \"public\" ? value : \"private\";\n}\n\nfunction normalizeForkSourceSnapshot(\n source: ForkThreadSourceSnapshot | null | undefined,\n): {\n threadData: string;\n title: string;\n preview: string;\n messageCount: number;\n scope?: ChatThreadScope | null;\n} | null {\n if (!source || typeof source.threadData !== \"string\") return null;\n const threadData = source.threadData.trim();\n if (!threadData) return null;\n\n let parsed: any;\n try {\n parsed = normalizeThreadRepository(JSON.parse(threadData));\n } catch {\n return null;\n }\n\n const repoMessageCount = Array.isArray(parsed.messages)\n ? parsed.messages.length\n : 0;\n if (repoMessageCount <= 0) return null;\n\n return {\n threadData: JSON.stringify(parsed),\n title: typeof source.title === \"string\" ? source.title : \"\",\n preview: typeof source.preview === \"string\" ? source.preview : \"\",\n messageCount: repoMessageCount,\n ...(Object.prototype.hasOwnProperty.call(source, \"scope\")\n ? { scope: source.scope ?? null }\n : {}),\n };\n}\n\nfunction deriveMessageCount(threadData: unknown, fallback: number): number {\n if (typeof threadData !== \"string\" || !threadData.trim()) return fallback;\n try {\n const repo = normalizeThreadRepository(JSON.parse(threadData));\n if (Array.isArray(repo.messages)) return repo.messages.length;\n } catch {\n // Keep the stored count if the JSON blob is malformed.\n }\n return fallback;\n}\n\nfunction rowToThread(r: Record<string, unknown>): ChatThread {\n const threadData = (r.thread_data as string) ?? \"{}\";\n const storedCount = Number(r.message_count);\n return {\n id: r.id as string,\n ownerEmail: r.owner_email as string,\n title: r.title as string,\n preview: r.preview as string,\n threadData,\n messageCount: deriveMessageCount(threadData, storedCount),\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n scope: readScope(r),\n pinnedAt: readNullableNumber(r.pinned_at),\n archivedAt: readNullableNumber(r.archived_at),\n orgId: (r.org_id as string | null | undefined) ?? null,\n visibility: readVisibility(r.visibility),\n };\n}\n\nfunction rowToSummary(r: Record<string, unknown>): ChatThreadSummary | null {\n // The summary path never loads `thread_data`; the count comes from the\n // dedicated `message_count` column maintained on write. Empty threads are\n // filtered out of the list.\n const messageCount = Number(r.message_count);\n if (!Number.isFinite(messageCount) || messageCount <= 0) return null;\n return {\n id: r.id as string,\n title: r.title as string,\n preview: r.preview as string,\n messageCount,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n scope: readScope(r),\n pinnedAt: readNullableNumber(r.pinned_at),\n archivedAt: readNullableNumber(r.archived_at),\n orgId: (r.org_id as string | null | undefined) ?? null,\n visibility: readVisibility(r.visibility),\n };\n}\n\nexport async function createThread(\n ownerEmail: string,\n opts?: { id?: string; title?: string; scope?: ChatThreadScope | null },\n): Promise<ChatThread> {\n await ensureTable();\n const client = getDbExec();\n const id = opts?.id ?? generateId();\n const now = Date.now();\n const title = opts?.title ?? \"\";\n const scope = opts?.scope ?? null;\n const orgId = getRequestOrgId() ?? null;\n\n await client.execute({\n sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, org_id, visibility) VALUES (?, ?, ?, '', '{}', 0, ?, ?, ?, ?, ?, ?, 'private')`,\n args: [\n id,\n ownerEmail,\n title,\n now,\n now,\n scope?.type ?? null,\n scope?.id ?? null,\n scope?.label ?? null,\n orgId,\n ],\n });\n\n return {\n id,\n ownerEmail,\n title,\n preview: \"\",\n threadData: \"{}\",\n messageCount: 0,\n createdAt: now,\n updatedAt: now,\n scope,\n pinnedAt: null,\n archivedAt: null,\n orgId,\n visibility: \"private\",\n };\n}\n\nconst THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;\n// The list/summary path deliberately omits `thread_data`: it is the full\n// message-history JSON blob and selecting it for every row turns \"open the\n// sidebar\" into \"download every conversation\". The summary derives nothing\n// from the blob anymore — preview and message_count are dedicated columns\n// (message_count is maintained on write). The detail path (`THREAD_COLUMNS` /\n// `getThread`) still returns the full blob.\nconst SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;\n\nexport function registerChatThreadsShareable(): void {\n registerShareableResource({\n type: \"chat_thread\",\n resourceTable: chatThreads,\n sharesTable: chatThreadShares,\n displayName: \"Chat\",\n titleColumn: \"title\",\n getResourcePath: (thread) =>\n `/?thread=${encodeURIComponent(String(thread.id ?? \"\"))}`,\n getDb: () => getChatThreadsDb(),\n allowPublic: false,\n ownerAccessIgnoresOrg: true,\n });\n}\n\nexport async function ensureChatThreadTables(): Promise<void> {\n await ensureTable();\n}\n\nexport async function resolveThreadAccess(\n userEmail: string | null | undefined,\n threadId: string | null | undefined,\n minRole: ShareRole | \"owner\" = \"viewer\",\n ctx: Omit<AccessContext, \"userEmail\"> = {},\n): Promise<ChatThread | null> {\n if (!userEmail || !threadId) return null;\n const access = await resolveAccess(\"chat_thread\", threadId, {\n userEmail,\n orgId: ctx.orgId,\n });\n if (!access || !roleSatisfies(access.role, minRole)) return null;\n return await getThread(threadId);\n}\n\nexport async function getThread(id: string): Promise<ChatThread | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT ${THREAD_COLUMNS} FROM chat_threads WHERE id = ?`,\n args: [id],\n });\n if (rows.length === 0) return null;\n return rowToThread(rows[0]);\n}\n\nexport async function forkThread(\n sourceId: string,\n ownerEmail: string,\n opts?: {\n id?: string;\n source?: ForkThreadSourceSnapshot | null;\n sourceAccessGranted?: boolean;\n },\n): Promise<ChatThread | null> {\n const snapshot = normalizeForkSourceSnapshot(opts?.source);\n let source = await getThread(sourceId);\n if (!source) {\n if (snapshot) {\n try {\n await createThread(ownerEmail, {\n id: sourceId,\n title: snapshot.title,\n scope: snapshot.scope ?? null,\n });\n } catch {\n // The agent run may have created the row while the user clicked Fork.\n }\n const created = await getThread(sourceId);\n if (created?.ownerEmail === ownerEmail) {\n await updateThreadData(\n sourceId,\n snapshot.threadData,\n snapshot.title || created.title,\n snapshot.preview || created.preview,\n snapshot.messageCount,\n );\n if (Object.prototype.hasOwnProperty.call(snapshot, \"scope\")) {\n await setThreadScope(sourceId, snapshot.scope ?? null);\n }\n source = await getThread(sourceId);\n }\n }\n } else if (\n snapshot &&\n source.ownerEmail === ownerEmail &&\n snapshot.messageCount > source.messageCount\n ) {\n // The source row exists but the in-memory snapshot is fresher — the agent\n // run flushed an older state to SQL, but the tab has additional unflushed\n // messages. Overlay the snapshot before cloning so the fork captures the\n // latest user-visible content. Guard with messageCount > stored to avoid\n // clobbering a fresher persisted row with a stale snapshot from another\n // tab.\n source = {\n ...source,\n threadData: snapshot.threadData,\n title: snapshot.title || source.title,\n preview: snapshot.preview || source.preview,\n messageCount: snapshot.messageCount,\n };\n }\n if (\n !source ||\n (!opts?.sourceAccessGranted && source.ownerEmail !== ownerEmail)\n ) {\n return null;\n }\n const id = opts?.id ?? generateId();\n const now = Date.now();\n const title = source.title ? `${source.title} (fork)` : \"\";\n const client = getDbExec();\n const orgId = getRequestOrgId() ?? null;\n await client.execute({\n sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, org_id, visibility) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')`,\n args: [\n id,\n ownerEmail,\n title,\n source.preview,\n source.threadData,\n source.messageCount,\n now,\n now,\n source.scope?.type ?? null,\n source.scope?.id ?? null,\n source.scope?.label ?? null,\n orgId,\n ],\n });\n return {\n id,\n ownerEmail,\n title,\n preview: source.preview,\n threadData: source.threadData,\n messageCount: source.messageCount,\n createdAt: now,\n updatedAt: now,\n scope: source.scope,\n pinnedAt: null,\n archivedAt: null,\n orgId,\n visibility: \"private\",\n };\n}\n\nexport interface ListThreadsOptions {\n limit?: number;\n offset?: number;\n /**\n * Filter for chats bound to a specific resource. The default (undefined)\n * returns every thread the user owns. `{ type: \"deck\", id: \"abc\" }`\n * returns only that resource's threads. `{ type: \"deck\", id: null }` is\n * NOT supported — pass `unscopedOnly: true` to get only general chats.\n */\n scope?: { type: string; id: string };\n /** When true, returns only threads with no scope (general chats). */\n unscopedOnly?: boolean;\n orgId?: string | null;\n /**\n * Include archived threads in the results. Defaults to false: archived\n * threads (`archived_at` set via `setThreadArchived`) are hidden from the\n * ordinary chat list/search so archiving actually removes a thread from\n * view. Pass true for surfaces that explicitly need to see archived chats\n * (e.g. an \"Archived\" filter or restoring one via `setThreadArchived`).\n */\n includeArchived?: boolean;\n}\n\nfunction chatThreadAccessSql(\n userEmail: string,\n orgId: string | null | undefined,\n): { sql: string; args: (string | number)[] } {\n const normalizedEmail = userEmail.trim().toLowerCase();\n const clauses = [\n `LOWER(owner_email) = ?`,\n `EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'user' AND LOWER(chat_thread_shares.principal_id) = ?)`,\n ];\n const args: (string | number)[] = [normalizedEmail, normalizedEmail];\n if (orgId) {\n clauses.push(`(visibility = 'org' AND org_id = ?)`);\n args.push(orgId);\n clauses.push(\n `EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'org' AND chat_thread_shares.principal_id = ?)`,\n );\n args.push(orgId);\n }\n return { sql: `(${clauses.join(\" OR \")})`, args };\n}\n\nexport async function listThreads(\n ownerEmail: string,\n options: ListThreadsOptions | number = {},\n legacyOffset?: number,\n): Promise<ChatThreadSummary[]> {\n await ensureTable();\n // Back-compat shim: previous signature was (owner, limit, offset).\n const opts: ListThreadsOptions =\n typeof options === \"number\"\n ? { limit: options, offset: legacyOffset ?? 0 }\n : options;\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const client = getDbExec();\n // `message_count > 0` is the authoritative \"has messages\" signal maintained\n // on every write, so the old `OR thread_data LIKE '%\"messages\"%'` substring\n // scan over the full blob is no longer needed here.\n const access = chatThreadAccessSql(\n ownerEmail,\n opts.orgId ?? getRequestOrgId(),\n );\n const filters: string[] = [access.sql, `message_count > 0`];\n const args: (string | number)[] = [...access.args];\n if (!opts.includeArchived) {\n filters.push(`archived_at IS NULL`);\n }\n if (opts.scope) {\n filters.push(`scope_type = ? AND scope_id = ?`);\n args.push(opts.scope.type, opts.scope.id);\n } else if (opts.unscopedOnly) {\n filters.push(`scope_type IS NULL`);\n }\n args.push(limit, offset);\n const { rows } = await client.execute({\n sql: `SELECT ${SUMMARY_COLUMNS} FROM chat_threads WHERE ${filters.join(\" AND \")} ORDER BY CASE WHEN pinned_at IS NULL THEN 1 ELSE 0 END, pinned_at DESC, updated_at DESC LIMIT ? OFFSET ?`,\n args,\n });\n return rows\n .map((r) => rowToSummary(r))\n .filter((r): r is ChatThreadSummary => r !== null);\n}\n\nfunction escapeLike(s: string): string {\n return s.replace(/[!%_]/g, (match) => `!${match}`);\n}\n\nexport async function searchThreads(\n ownerEmail: string,\n query: string,\n limit = 50,\n options: {\n scope?: { type: string; id: string };\n orgId?: string | null;\n /** See `ListThreadsOptions.includeArchived` — defaults to false. */\n includeArchived?: boolean;\n } = {},\n): Promise<ChatThreadSummary[]> {\n await ensureTable();\n const client = getDbExec();\n const pattern = `%${escapeLike(query)}%`;\n // The count-guard uses the maintained `message_count` column (same as\n // listThreads). The content match still scans `thread_data` — search\n // legitimately needs to look inside message history.\n const access = chatThreadAccessSql(\n ownerEmail,\n options.orgId ?? getRequestOrgId(),\n );\n const filters: string[] = [\n access.sql,\n `message_count > 0`,\n `(title LIKE ? ESCAPE '!' OR preview LIKE ? ESCAPE '!' OR thread_data LIKE ? ESCAPE '!')`,\n ];\n const args: (string | number)[] = [...access.args, pattern, pattern, pattern];\n if (!options.includeArchived) {\n filters.push(`archived_at IS NULL`);\n }\n if (options.scope) {\n filters.push(`scope_type = ? AND scope_id = ?`);\n args.push(options.scope.type, options.scope.id);\n }\n args.push(limit);\n const { rows } = await client.execute({\n sql: `SELECT ${SUMMARY_COLUMNS} FROM chat_threads WHERE ${filters.join(\" AND \")} ORDER BY CASE WHEN pinned_at IS NULL THEN 1 ELSE 0 END, pinned_at DESC, updated_at DESC LIMIT ?`,\n args,\n });\n return rows\n .map((r) => rowToSummary(r))\n .filter((r): r is ChatThreadSummary => r !== null);\n}\n\n/**\n * Detach or rebind a chat's scope. Used by the UI's \"Detach from <resource>\"\n * action and by templates that need to retag a chat after a rename. Pass\n * `null` to clear the scope (chat becomes general).\n */\nexport async function setThreadScope(\n id: string,\n scope: ChatThreadScope | null,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE chat_threads SET scope_type = ?, scope_id = ?, scope_label = ?, updated_at = ? WHERE id = ?`,\n args: [\n scope?.type ?? null,\n scope?.id ?? null,\n scope?.label ?? null,\n Math.max(Date.now(), 1),\n id,\n ],\n });\n emitChatThreadChange(id);\n}\n\nexport async function renameThread(\n id: string,\n title: string,\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n const nextTitle = normalizeThreadTitle(title);\n if (!nextTitle) return false;\n\n return await withThreadDataLock(id, async () => {\n const thread = await getThread(id);\n if (!thread) return false;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return false;\n }\n\n const repo = parseThreadData(thread.threadData);\n repo._titleOverride = nextTitle;\n await updateThreadData(\n id,\n JSON.stringify(repo),\n nextTitle,\n thread.preview,\n thread.messageCount,\n );\n return true;\n });\n}\n\nexport async function setThreadPinned(\n id: string,\n pinned: boolean,\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const now = Math.max(Date.now(), 1);\n const args: (string | number | null)[] = [pinned ? now : null, id];\n let ownerFilter = \"\";\n if (options.ownerEmail) {\n ownerFilter = \" AND owner_email = ?\";\n args.push(options.ownerEmail);\n }\n const result = await client.execute({\n sql: `UPDATE chat_threads SET pinned_at = ? WHERE id = ?${ownerFilter}`,\n args,\n });\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return true;\n }\n return false;\n}\n\nexport async function setThreadArchived(\n id: string,\n archived: boolean,\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const now = Math.max(Date.now(), 1);\n const args: (string | number | null)[] = [archived ? now : null, id];\n let ownerFilter = \"\";\n if (options.ownerEmail) {\n ownerFilter = \" AND owner_email = ?\";\n args.push(options.ownerEmail);\n }\n const result = await client.execute({\n sql: `UPDATE chat_threads SET archived_at = ? WHERE id = ?${ownerFilter}`,\n args,\n });\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return true;\n }\n return false;\n}\n\nexport interface UpdateThreadDataOptions {\n preserveExistingQueuedMessages?: boolean;\n preserveExistingTopLevelKeys?: boolean;\n maxAttempts?: number;\n ignoreConflicts?: boolean;\n}\n\nfunction parseThreadData(value: string): any {\n try {\n return JSON.parse(value || \"{}\");\n } catch {\n return {};\n }\n}\n\nexport async function updateThreadData(\n id: string,\n threadData: string,\n title: string,\n preview: string,\n messageCount: number,\n options: UpdateThreadDataOptions = {},\n): Promise<void> {\n // getThread() ensures the table exists. Keep that bootstrap inside the\n // retry boundary below so a cold serverless process can recover from a\n // transient initialization/read failure too.\n const client = getDbExec();\n const maxAttempts = Math.max(\n 1,\n options.maxAttempts ?? DEFAULT_THREAD_DATA_UPDATE_ATTEMPTS,\n );\n let lastConflict = false;\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const current = await getThread(id);\n if (!current) return;\n\n let nextThreadData = threadData;\n let nextMessageCount = messageCount;\n try {\n const merged = mergeThreadDataForClientSave(\n parseThreadData(current.threadData),\n parseThreadData(threadData),\n {\n preserveExistingQueuedMessages:\n options.preserveExistingQueuedMessages ?? true,\n preserveExistingTopLevelKeys:\n options.preserveExistingTopLevelKeys ?? true,\n },\n );\n nextThreadData = JSON.stringify(merged);\n if (Array.isArray(merged.messages)) {\n nextMessageCount = merged.messages.length;\n }\n } catch {\n // Keep the caller's serialized value if either JSON blob is malformed.\n }\n\n const nextUpdatedAt = Math.max(Date.now(), current.updatedAt + 1);\n const result = await client.execute({\n sql: `UPDATE chat_threads SET thread_data = ?, title = ?, preview = ?, message_count = ?, updated_at = ? WHERE id = ? AND updated_at = ?`,\n args: [\n nextThreadData,\n title,\n preview,\n nextMessageCount,\n nextUpdatedAt,\n id,\n current.updatedAt,\n ],\n });\n\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return;\n }\n\n lastConflict = true;\n } catch (error) {\n // Completion saves happen after a long model/tool turn, when a\n // transient connection or serverless DB failure is especially costly.\n // Retry the whole read/merge/write attempt like a CAS conflict, while\n // preserving the final error if the database remains unavailable.\n lastError = error;\n }\n\n if (attempt < maxAttempts - 1) {\n await new Promise((resolve) =>\n setTimeout(\n resolve,\n Math.min(250, THREAD_DATA_CONFLICT_BACKOFF_MS * (attempt + 1)),\n ),\n );\n }\n }\n\n if (lastError) throw lastError;\n\n if (lastConflict) {\n if (options.ignoreConflicts) return;\n throw new Error(\n `Failed to update chat thread ${id} after concurrent write conflicts.`,\n );\n }\n}\n\nexport interface ThreadEngineMeta {\n engineName: string;\n model: string;\n}\n\n/**\n * Read the engine pinned to a thread (stored in thread_data JSON).\n * Returns null if no engine is pinned.\n */\nexport async function getThreadEngineMeta(\n threadId: string,\n): Promise<ThreadEngineMeta | null> {\n const thread = await getThread(threadId);\n if (!thread?.threadData) return null;\n try {\n const data = JSON.parse(thread.threadData);\n if (data.engineMeta?.engineName) return data.engineMeta as ThreadEngineMeta;\n } catch {}\n return null;\n}\n\n/**\n * Pin an engine to a thread by storing engineMeta in thread_data JSON.\n * Does not change messages, title, or preview.\n */\nexport async function setThreadEngineMeta(\n threadId: string,\n meta: ThreadEngineMeta,\n): Promise<void> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return;\n let data: Record<string, unknown> = {};\n try {\n data = JSON.parse(thread.threadData);\n } catch {}\n data.engineMeta = meta;\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n );\n });\n}\n\nexport interface QueuedMessage {\n id: string;\n text: string;\n images?: string[];\n references?: unknown[];\n}\n\n/**\n * Persist the user's queued (not-yet-sent) messages onto the thread.\n * Stored in thread_data JSON so it survives reloads without a schema\n * change. Safe to call often — the frontend debounces writes.\n *\n * Returns false when the thread is missing or `ownerEmail` doesn't match.\n * Callers that already need an ownership check should pass `ownerEmail`\n * here instead of doing their own getThread first — this path fires on\n * debounced composer writes, so a redundant pre-read of the full\n * thread_data blob is a real per-keystroke cost.\n */\nexport async function setThreadQueuedMessages(\n threadId: string,\n queuedMessages: QueuedMessage[],\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return false;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return false;\n }\n let data: Record<string, unknown> = {};\n try {\n data = JSON.parse(thread.threadData);\n } catch {}\n if (queuedMessages.length === 0) {\n delete data.queuedMessages;\n } else {\n data.queuedMessages = queuedMessages;\n }\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n { preserveExistingQueuedMessages: false },\n );\n return true;\n });\n}\n\nconst THREAD_SHARE_DATA_KEY = \"_share\";\n\ninterface StoredThreadShare {\n tokenHash?: string;\n createdAt?: number;\n updatedAt?: number;\n revokedAt?: number | null;\n}\n\nexport interface ChatThreadShareState {\n enabled: boolean;\n createdAt: number | null;\n updatedAt: number | null;\n revokedAt: number | null;\n}\n\nexport interface ChatThreadShareLink extends ChatThreadShareState {\n enabled: true;\n token: string;\n}\n\nfunction generateShareToken(): string {\n return crypto.randomBytes(24).toString(\"base64url\");\n}\n\nexport function hashThreadShareToken(token: string): string {\n return crypto.createHash(\"sha256\").update(token).digest(\"hex\");\n}\n\nfunction normalizeThreadShare(value: unknown): StoredThreadShare | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const r = value as Record<string, unknown>;\n const tokenHash =\n typeof r.tokenHash === \"string\" && /^[a-f0-9]{64}$/i.test(r.tokenHash)\n ? r.tokenHash.toLowerCase()\n : undefined;\n const createdAt = normalizeTimestamp(r.createdAt);\n const updatedAt = normalizeTimestamp(r.updatedAt);\n const revokedAt = normalizeTimestamp(r.revokedAt);\n if (!tokenHash && !createdAt && !updatedAt && !revokedAt) return null;\n return {\n ...(tokenHash ? { tokenHash } : {}),\n ...(createdAt ? { createdAt } : {}),\n ...(updatedAt ? { updatedAt } : {}),\n ...(revokedAt ? { revokedAt } : {}),\n };\n}\n\nfunction normalizeTimestamp(value: unknown): number | undefined {\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nfunction shareStateFromStored(\n stored: StoredThreadShare | null,\n): ChatThreadShareState {\n const revokedAt = stored?.revokedAt ?? null;\n return {\n enabled: Boolean(stored?.tokenHash && !revokedAt),\n createdAt: stored?.createdAt ?? null,\n updatedAt: stored?.updatedAt ?? null,\n revokedAt,\n };\n}\n\nfunction readStoredThreadShare(threadData: string): StoredThreadShare | null {\n const data = parseThreadData(threadData);\n return normalizeThreadShare(data[THREAD_SHARE_DATA_KEY]);\n}\n\nexport async function getThreadShareState(\n threadId: string,\n options: { ownerEmail?: string } = {},\n): Promise<ChatThreadShareState | null> {\n const thread = await getThread(threadId);\n if (!thread) return null;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return null;\n }\n return shareStateFromStored(readStoredThreadShare(thread.threadData));\n}\n\nexport async function createThreadShareLink(\n threadId: string,\n options: { ownerEmail?: string } = {},\n): Promise<ChatThreadShareLink | null> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return null;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return null;\n }\n\n const now = Date.now();\n const token = generateShareToken();\n const tokenHash = hashThreadShareToken(token);\n const data = parseThreadData(thread.threadData);\n const existing = normalizeThreadShare(data[THREAD_SHARE_DATA_KEY]);\n data[THREAD_SHARE_DATA_KEY] = {\n tokenHash,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n revokedAt: null,\n } satisfies StoredThreadShare;\n\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n );\n // Mirror the hash into the indexed column so getThreadByShareToken\n // resolves via an equality lookup instead of a LIKE scan over every\n // thread's blob. thread_data stays the source of truth for validation.\n await setThreadShareTokenHashColumn(threadId, tokenHash);\n\n return {\n enabled: true,\n token,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n revokedAt: null,\n };\n });\n}\n\nasync function setThreadShareTokenHashColumn(\n threadId: string,\n tokenHash: string | null,\n): Promise<void> {\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE chat_threads SET share_token_hash = ? WHERE id = ?`,\n args: [tokenHash, threadId],\n });\n}\n\nexport async function revokeThreadShareLink(\n threadId: string,\n options: { ownerEmail?: string } = {},\n): Promise<ChatThreadShareState | null> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return null;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return null;\n }\n\n const now = Date.now();\n const data = parseThreadData(thread.threadData);\n const existing = normalizeThreadShare(data[THREAD_SHARE_DATA_KEY]);\n data[THREAD_SHARE_DATA_KEY] = {\n ...(existing?.createdAt ? { createdAt: existing.createdAt } : {}),\n updatedAt: now,\n revokedAt: now,\n } satisfies StoredThreadShare;\n\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n );\n await setThreadShareTokenHashColumn(threadId, null);\n\n return {\n enabled: false,\n createdAt: existing?.createdAt ?? null,\n updatedAt: now,\n revokedAt: now,\n };\n });\n}\n\nexport async function getThreadByShareToken(\n token: string,\n): Promise<ChatThread | null> {\n const cleanToken = token.trim();\n if (!cleanToken || cleanToken.length < 16) return null;\n await ensureTable();\n const tokenHash = hashThreadShareToken(cleanToken);\n const client = getDbExec();\n\n const validate = (row: Record<string, unknown>): ChatThread | null => {\n const thread = rowToThread(row);\n // thread_data remains the source of truth: verify the stored share\n // matches and is not revoked even when the indexed column matched.\n const stored = readStoredThreadShare(thread.threadData);\n if (!stored?.tokenHash || stored.revokedAt) return null;\n if (stored.tokenHash !== tokenHash) return null;\n return thread;\n };\n\n // Fast path: indexed equality lookup on the mirrored hash column.\n const indexed = await client.execute({\n sql: `SELECT ${THREAD_COLUMNS} FROM chat_threads WHERE share_token_hash = ? LIMIT 10`,\n args: [tokenHash],\n });\n for (const row of indexed.rows) {\n const thread = validate(row);\n if (thread) return thread;\n }\n\n // Legacy fallback: shares created before the share_token_hash column\n // existed only carry the hash inside the thread_data blob. Backfill the\n // column on hit so the next lookup takes the indexed path.\n const legacy = await client.execute({\n sql: `SELECT ${THREAD_COLUMNS} FROM chat_threads WHERE share_token_hash IS NULL AND thread_data LIKE ? LIMIT 10`,\n args: [`%${tokenHash}%`],\n });\n for (const row of legacy.rows) {\n const thread = validate(row);\n if (thread) {\n await setThreadShareTokenHashColumn(thread.id, tokenHash).catch(() => {});\n return thread;\n }\n }\n return null;\n}\n\n/**\n * Grant a user an explicit share on a thread they don't own. Used by the\n * messaging-integration path, where a channel conversation runs as the\n * integration service principal and so creates a thread owned by\n * `integration@<platform>` rather than the human who asked — without this the\n * \"Open thread\" deep link resolves to a 404 for them.\n *\n * Idempotent, and never downgrades an existing stronger role.\n */\nexport async function grantThreadUserShare(\n threadId: string,\n userEmail: string,\n role: ShareRole,\n grantedBy: string,\n): Promise<void> {\n const normalizedEmail = userEmail.trim().toLowerCase();\n if (!threadId || !normalizedEmail.includes(\"@\")) return;\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, role FROM chat_thread_shares WHERE resource_id = ? AND principal_type = 'user' AND LOWER(principal_id) = ?`,\n args: [threadId, normalizedEmail],\n });\n const existing = rows[0];\n if (existing) {\n if (roleSatisfies(existing.role as ShareRole, role)) return;\n await client.execute({\n sql: `UPDATE chat_thread_shares SET role = ? WHERE id = ?`,\n args: [role, existing.id as string],\n });\n return;\n }\n await client.execute({\n sql: `INSERT INTO chat_thread_shares (id, resource_id, principal_type, principal_id, role, created_by, created_at) VALUES (?, ?, 'user', ?, ?, ?, ?)`,\n args: [\n crypto.randomUUID(),\n threadId,\n normalizedEmail,\n role,\n grantedBy,\n new Date().toISOString(),\n ],\n });\n}\n\nexport async function deleteThread(id: string): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `DELETE FROM chat_threads WHERE id = ?`,\n args: [id],\n });\n if (result.rowsAffected > 0) {\n await client\n .execute({\n sql: `DELETE FROM chat_thread_shares WHERE resource_id = ?`,\n args: [id],\n })\n .catch(() => {});\n emitChatThreadChange(id);\n return true;\n }\n return false;\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/chat-threads/store.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"node:crypto\";\n\nimport {\n mergeThreadDataForClientSave,\n normalizeThreadRepository,\n normalizeThreadTitle,\n} from \"../agent/thread-data-builder.js\";\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport { createGetDb } from \"../db/create-get-db.js\";\nimport {\n ensureColumnExists,\n ensureIndexExists,\n ensureTableExists,\n} from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport { getRequestOrgId } from \"../server/request-context.js\";\nimport { resolveAccess, type AccessContext } from \"../sharing/access.js\";\nimport { registerShareableResource } from \"../sharing/registry.js\";\nimport { roleSatisfies, type ShareRole } from \"../sharing/schema.js\";\nimport { emitChatThreadChange } from \"./emitter.js\";\nimport {\n chatThreads,\n chatThreadShares,\n CHAT_THREAD_SHARES_CREATE_SQL,\n CHAT_THREAD_SHARES_CREATE_SQL_PG,\n CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,\n} from \"./schema.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n/**\n * Per-thread async mutex. Read-modify-write on the `thread_data` JSON blob\n * is not atomic at the DB level — two concurrent callers (e.g. the UI\n * persisting queued messages while `onRunComplete` appends agent output)\n * would both read the same row, each mutate it independently, and the\n * second write clobbers the first. Serializing on thread id inside this\n * process eliminates the race for the usual single-process deployment\n * while leaving straight reads and other thread-data-unrelated updates\n * untouched.\n *\n * Cross-process races are handled by `updateThreadData`, which performs a\n * compare-and-swap on `updated_at`, rereads the latest row on conflict, and\n * remerges message history before retrying.\n */\nconst _threadDataLocks = new Map<string, Promise<unknown>>();\nconst DEFAULT_THREAD_DATA_UPDATE_ATTEMPTS = 12;\nconst THREAD_DATA_CONFLICT_BACKOFF_MS = 25;\nconst getChatThreadsDb = createGetDb({ chatThreads, chatThreadShares });\n\nexport function withThreadDataLock<T>(\n threadId: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const prev = _threadDataLocks.get(threadId) ?? Promise.resolve();\n const next = prev.then(fn, fn);\n _threadDataLocks.set(threadId, next);\n // Use `.then(cleanup, cleanup)` (not `.finally`) so the rejection is\n // observed on this chained promise — otherwise any failure inside `fn`\n // triggers `unhandledRejection` on the discarded `finally()` return.\n // The caller still sees the rejection via `next`.\n const cleanup = () => {\n if (_threadDataLocks.get(threadId) === next) {\n _threadDataLocks.delete(threadId);\n }\n };\n next.then(cleanup, cleanup);\n return next as Promise<T>;\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const createSql = `\n CREATE TABLE IF NOT EXISTS chat_threads (\n id TEXT PRIMARY KEY,\n owner_email TEXT NOT NULL,\n title TEXT NOT NULL DEFAULT '',\n preview TEXT NOT NULL DEFAULT '',\n thread_data TEXT NOT NULL DEFAULT '{}',\n message_count ${intType()} NOT NULL DEFAULT 0,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n scope_type TEXT,\n scope_id TEXT,\n scope_label TEXT,\n pinned_at ${intType()},\n archived_at ${intType()},\n share_token_hash TEXT,\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n )\n `;\n\n if (isPostgres()) {\n // Hot path: the `chat_threads` table and its indexes are virtually\n // always already present in production. Issuing `CREATE TABLE`/\n // `CREATE INDEX` still takes a lock that, in a fresh background-worker\n // process behind a concurrent connection on the shared Neon DB, can\n // block ~indefinitely (ACCESS EXCLUSIVE for CREATE TABLE; a write-\n // blocking SHARE lock for CREATE INDEX). The ensure* wrappers probe\n // `information_schema`/`pg_indexes` first (plain reads, no lock) and\n // run DDL ONLY for what is actually missing, bounded by a transaction-\n // scoped `lock_timeout`. If a swallowed lock-timeout leaves the schema\n // still missing they RE-PROBE and THROW rather than letting init\n // memoize success against absent schema. `chat_threads` is the\n // unqualified name even though the table lives in `public`.\n await ensureTableExists(\"chat_threads\", createSql);\n // Additive columns — guarded so the hot path (columns already present)\n // skips the ACCESS EXCLUSIVE ALTER entirely.\n for (const [col, type] of [\n [\"scope_type\", \"TEXT\"],\n [\"scope_id\", \"TEXT\"],\n [\"scope_label\", \"TEXT\"],\n [\"pinned_at\", intType()],\n [\"archived_at\", intType()],\n [\"share_token_hash\", \"TEXT\"],\n [\"org_id\", \"TEXT\"],\n [\"visibility\", \"TEXT NOT NULL DEFAULT 'private'\"],\n ] as const) {\n await ensureColumnExists(\n \"chat_threads\",\n col,\n `ALTER TABLE chat_threads ADD COLUMN IF NOT EXISTS ${col} ${type}`,\n );\n }\n await ensureTableExists(\n \"chat_thread_shares\",\n CHAT_THREAD_SHARES_CREATE_SQL_PG,\n );\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`; on Postgres the `Date.now()` written on every turn\n // overflows int4. No-op once widened / on fresh BIGINT databases.\n await widenIntColumnsToBigInt(\"chat_threads\", [\n \"created_at\",\n \"updated_at\",\n \"pinned_at\",\n \"archived_at\",\n ]);\n // Indexes for the hot read paths. Both the sidebar list and the\n // scoped/per-resource list filter on owner_email (and optionally\n // scope) and sort by updated_at. Probe pg_indexes first (no lock)\n // and skip the SHARE-locking CREATE INDEX when already present.\n await ensureIndexExists(\n \"chat_threads_owner_updated_idx\",\n `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`,\n );\n await ensureIndexExists(\n \"chat_threads_scope_updated_idx\",\n `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`,\n );\n // Public share-link resolution looks threads up by token hash;\n // without this index it degrades to a LIKE scan over every blob.\n await ensureIndexExists(\n \"chat_threads_share_token_idx\",\n `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`,\n );\n await ensureIndexExists(\n \"chat_thread_shares_resource_idx\",\n CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n // Additive migration for existing tables. Both SQLite and Postgres\n // accept `ALTER TABLE ADD COLUMN` and will raise when the column\n // already exists; the try/catch makes the call idempotent across\n // both dialects without requiring an information_schema probe.\n for (const [col, type] of [\n [\"scope_type\", \"TEXT\"],\n [\"scope_id\", \"TEXT\"],\n [\"scope_label\", \"TEXT\"],\n [\"pinned_at\", intType()],\n [\"archived_at\", intType()],\n [\"share_token_hash\", \"TEXT\"],\n [\"org_id\", \"TEXT\"],\n [\"visibility\", \"TEXT NOT NULL DEFAULT 'private'\"],\n ] as const) {\n try {\n await client.execute(\n `ALTER TABLE chat_threads ADD COLUMN ${col} ${type}`,\n );\n } catch {\n // Column already exists.\n }\n }\n try {\n await client.execute(CHAT_THREAD_SHARES_CREATE_SQL);\n } catch {\n // Table already exists.\n }\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`; on Postgres the `Date.now()` written on every turn\n // overflows int4. No-op once widened / on fresh BIGINT databases.\n await widenIntColumnsToBigInt(\"chat_threads\", [\n \"created_at\",\n \"updated_at\",\n \"pinned_at\",\n \"archived_at\",\n ]);\n // Indexes for the hot read paths. Both the sidebar list and the\n // scoped/per-resource list filter on owner_email (and optionally\n // scope) and sort by updated_at. Keep these dialect-agnostic (no\n // DESC, partial, or PG-only syntax) so they apply identically on\n // SQLite and the configured Postgres. `IF NOT EXISTS` makes them\n // idempotent across restarts.\n for (const ddl of [\n `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`,\n `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`,\n `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`,\n CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,\n ]) {\n try {\n await client.execute(ddl);\n } catch {\n // Index already exists or the dialect rejected a duplicate.\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\n/**\n * Explicitly repair `message_count` for legacy rows written before the count\n * was maintained. This must never run from table/bootstrap initialization:\n * serverless isolates would each scan the full `thread_data` blob column on\n * cold start. Operators may invoke it once when upgrading an old database.\n */\nexport async function repairLegacyChatThreadMessageCounts(\n options: {\n batchSize?: number;\n } = {},\n): Promise<{ scanned: number; updated: number }> {\n await ensureTable();\n const client = getDbExec();\n const batchSize = Math.max(1, Math.min(options.batchSize ?? 100, 1_000));\n let afterId = \"\";\n let scanned = 0;\n let updated = 0;\n while (true) {\n const { rows } = await client.execute({\n sql: `SELECT id, thread_data, message_count FROM chat_threads\n WHERE message_count = 0\n AND thread_data LIKE '%\"messages\"%'\n AND id > ?\n ORDER BY id\n LIMIT ?`,\n args: [afterId, batchSize],\n });\n if (rows.length === 0) break;\n for (const row of rows) {\n afterId = String(row.id);\n scanned++;\n const count = deriveMessageCount(row.thread_data, 0);\n if (count <= 0) continue;\n const result = await client.execute({\n sql: `UPDATE chat_threads SET message_count = ? WHERE id = ? AND message_count = 0`,\n args: [count, afterId],\n });\n if (result.rowsAffected > 0) updated++;\n }\n if (rows.length < batchSize) break;\n }\n return { scanned, updated };\n}\n\nfunction generateId(): string {\n return `thread-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * A resource the chat is bound to, e.g. `{ type: \"deck\", id: \"deck-abc\" }`.\n * The framework is opaque to the type string — each template chooses what\n * its primary resource is and the surface it scopes to (deck, design,\n * dashboard, etc.). `label` is a denormalized snapshot for display when\n * the resource isn't on hand at render time; the live template can\n * overwrite it via the next createThread call.\n */\nexport interface ChatThreadScope {\n type: string;\n id: string;\n label?: string;\n}\n\nexport interface ChatThread {\n id: string;\n ownerEmail: string;\n title: string;\n preview: string;\n threadData: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n scope: ChatThreadScope | null;\n pinnedAt: number | null;\n archivedAt: number | null;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\nexport interface ChatThreadSummary {\n id: string;\n title: string;\n preview: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n scope: ChatThreadScope | null;\n pinnedAt: number | null;\n archivedAt: number | null;\n orgId: string | null;\n visibility: \"private\" | \"org\" | \"public\";\n}\n\nexport interface ForkThreadSourceSnapshot {\n threadData: string;\n title?: string;\n preview?: string;\n messageCount?: number;\n scope?: ChatThreadScope | null;\n}\n\nfunction readScope(r: Record<string, unknown>): ChatThreadScope | null {\n const type = r.scope_type as string | null | undefined;\n const id = r.scope_id as string | null | undefined;\n if (!type || !id) return null;\n const label = r.scope_label as string | null | undefined;\n return label ? { type, id, label } : { type, id };\n}\n\nfunction readNullableNumber(value: unknown): number | null {\n if (value == null) return null;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : null;\n}\n\nfunction readVisibility(value: unknown): \"private\" | \"org\" | \"public\" {\n return value === \"org\" || value === \"public\" ? value : \"private\";\n}\n\nfunction normalizeForkSourceSnapshot(\n source: ForkThreadSourceSnapshot | null | undefined,\n): {\n threadData: string;\n title: string;\n preview: string;\n messageCount: number;\n scope?: ChatThreadScope | null;\n} | null {\n if (!source || typeof source.threadData !== \"string\") return null;\n const threadData = source.threadData.trim();\n if (!threadData) return null;\n\n let parsed: any;\n try {\n parsed = normalizeThreadRepository(JSON.parse(threadData));\n } catch {\n return null;\n }\n\n const repoMessageCount = Array.isArray(parsed.messages)\n ? parsed.messages.length\n : 0;\n if (repoMessageCount <= 0) return null;\n\n return {\n threadData: JSON.stringify(parsed),\n title: typeof source.title === \"string\" ? source.title : \"\",\n preview: typeof source.preview === \"string\" ? source.preview : \"\",\n messageCount: repoMessageCount,\n ...(Object.prototype.hasOwnProperty.call(source, \"scope\")\n ? { scope: source.scope ?? null }\n : {}),\n };\n}\n\nfunction deriveMessageCount(threadData: unknown, fallback: number): number {\n if (typeof threadData !== \"string\" || !threadData.trim()) return fallback;\n try {\n const repo = normalizeThreadRepository(JSON.parse(threadData));\n if (Array.isArray(repo.messages)) return repo.messages.length;\n } catch {\n // Keep the stored count if the JSON blob is malformed.\n }\n return fallback;\n}\n\nfunction rowToThread(r: Record<string, unknown>): ChatThread {\n const threadData = (r.thread_data as string) ?? \"{}\";\n const storedCount = Number(r.message_count);\n return {\n id: r.id as string,\n ownerEmail: r.owner_email as string,\n title: r.title as string,\n preview: r.preview as string,\n threadData,\n messageCount: deriveMessageCount(threadData, storedCount),\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n scope: readScope(r),\n pinnedAt: readNullableNumber(r.pinned_at),\n archivedAt: readNullableNumber(r.archived_at),\n orgId: (r.org_id as string | null | undefined) ?? null,\n visibility: readVisibility(r.visibility),\n };\n}\n\nfunction rowToSummary(r: Record<string, unknown>): ChatThreadSummary | null {\n // The summary path never loads `thread_data`; the count comes from the\n // dedicated `message_count` column maintained on write. Empty threads are\n // filtered out of the list.\n const messageCount = Number(r.message_count);\n if (!Number.isFinite(messageCount) || messageCount <= 0) return null;\n return {\n id: r.id as string,\n title: r.title as string,\n preview: r.preview as string,\n messageCount,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n scope: readScope(r),\n pinnedAt: readNullableNumber(r.pinned_at),\n archivedAt: readNullableNumber(r.archived_at),\n orgId: (r.org_id as string | null | undefined) ?? null,\n visibility: readVisibility(r.visibility),\n };\n}\n\nexport async function createThread(\n ownerEmail: string,\n opts?: { id?: string; title?: string; scope?: ChatThreadScope | null },\n): Promise<ChatThread> {\n await ensureTable();\n const client = getDbExec();\n const id = opts?.id ?? generateId();\n const now = Date.now();\n const title = opts?.title ?? \"\";\n const scope = opts?.scope ?? null;\n const orgId = getRequestOrgId() ?? null;\n\n await client.execute({\n sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, org_id, visibility) VALUES (?, ?, ?, '', '{}', 0, ?, ?, ?, ?, ?, ?, 'private')`,\n args: [\n id,\n ownerEmail,\n title,\n now,\n now,\n scope?.type ?? null,\n scope?.id ?? null,\n scope?.label ?? null,\n orgId,\n ],\n });\n\n return {\n id,\n ownerEmail,\n title,\n preview: \"\",\n threadData: \"{}\",\n messageCount: 0,\n createdAt: now,\n updatedAt: now,\n scope,\n pinnedAt: null,\n archivedAt: null,\n orgId,\n visibility: \"private\",\n };\n}\n\nconst THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;\n// The list/summary path deliberately omits `thread_data`: it is the full\n// message-history JSON blob and selecting it for every row turns \"open the\n// sidebar\" into \"download every conversation\". The summary derives nothing\n// from the blob anymore — preview and message_count are dedicated columns\n// (message_count is maintained on write). The detail path (`THREAD_COLUMNS` /\n// `getThread`) still returns the full blob.\nconst SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;\n\nexport function registerChatThreadsShareable(): void {\n registerShareableResource({\n type: \"chat_thread\",\n resourceTable: chatThreads,\n sharesTable: chatThreadShares,\n displayName: \"Chat\",\n titleColumn: \"title\",\n getResourcePath: (thread) =>\n `/?thread=${encodeURIComponent(String(thread.id ?? \"\"))}`,\n getDb: () => getChatThreadsDb(),\n allowPublic: false,\n ownerAccessIgnoresOrg: true,\n });\n}\n\nexport async function ensureChatThreadTables(): Promise<void> {\n await ensureTable();\n}\n\nexport async function resolveThreadAccess(\n userEmail: string | null | undefined,\n threadId: string | null | undefined,\n minRole: ShareRole | \"owner\" = \"viewer\",\n ctx: Omit<AccessContext, \"userEmail\"> = {},\n): Promise<ChatThread | null> {\n if (!userEmail || !threadId) return null;\n const access = await resolveAccess(\"chat_thread\", threadId, {\n userEmail,\n orgId: ctx.orgId,\n });\n if (!access || !roleSatisfies(access.role, minRole)) return null;\n return await getThread(threadId);\n}\n\nexport async function getThread(id: string): Promise<ChatThread | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT ${THREAD_COLUMNS} FROM chat_threads WHERE id = ?`,\n args: [id],\n });\n if (rows.length === 0) return null;\n return rowToThread(rows[0]);\n}\n\nexport async function forkThread(\n sourceId: string,\n ownerEmail: string,\n opts?: {\n id?: string;\n source?: ForkThreadSourceSnapshot | null;\n sourceAccessGranted?: boolean;\n },\n): Promise<ChatThread | null> {\n const snapshot = normalizeForkSourceSnapshot(opts?.source);\n let source = await getThread(sourceId);\n if (!source) {\n if (snapshot) {\n try {\n await createThread(ownerEmail, {\n id: sourceId,\n title: snapshot.title,\n scope: snapshot.scope ?? null,\n });\n } catch {\n // The agent run may have created the row while the user clicked Fork.\n }\n const created = await getThread(sourceId);\n if (created?.ownerEmail === ownerEmail) {\n await updateThreadData(\n sourceId,\n snapshot.threadData,\n snapshot.title || created.title,\n snapshot.preview || created.preview,\n snapshot.messageCount,\n );\n if (Object.prototype.hasOwnProperty.call(snapshot, \"scope\")) {\n await setThreadScope(sourceId, snapshot.scope ?? null);\n }\n source = await getThread(sourceId);\n }\n }\n } else if (\n snapshot &&\n source.ownerEmail === ownerEmail &&\n snapshot.messageCount > source.messageCount\n ) {\n // The source row exists but the in-memory snapshot is fresher — the agent\n // run flushed an older state to SQL, but the tab has additional unflushed\n // messages. Overlay the snapshot before cloning so the fork captures the\n // latest user-visible content. Guard with messageCount > stored to avoid\n // clobbering a fresher persisted row with a stale snapshot from another\n // tab.\n source = {\n ...source,\n threadData: snapshot.threadData,\n title: snapshot.title || source.title,\n preview: snapshot.preview || source.preview,\n messageCount: snapshot.messageCount,\n };\n }\n if (\n !source ||\n (!opts?.sourceAccessGranted && source.ownerEmail !== ownerEmail)\n ) {\n return null;\n }\n const id = opts?.id ?? generateId();\n const now = Date.now();\n const title = source.title ? `${source.title} (fork)` : \"\";\n const client = getDbExec();\n const orgId = getRequestOrgId() ?? null;\n await client.execute({\n sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, org_id, visibility) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')`,\n args: [\n id,\n ownerEmail,\n title,\n source.preview,\n source.threadData,\n source.messageCount,\n now,\n now,\n source.scope?.type ?? null,\n source.scope?.id ?? null,\n source.scope?.label ?? null,\n orgId,\n ],\n });\n return {\n id,\n ownerEmail,\n title,\n preview: source.preview,\n threadData: source.threadData,\n messageCount: source.messageCount,\n createdAt: now,\n updatedAt: now,\n scope: source.scope,\n pinnedAt: null,\n archivedAt: null,\n orgId,\n visibility: \"private\",\n };\n}\n\nexport interface ListThreadsOptions {\n limit?: number;\n offset?: number;\n /**\n * Filter for chats bound to a specific resource. The default (undefined)\n * returns every thread the user owns. `{ type: \"deck\", id: \"abc\" }`\n * returns only that resource's threads. `{ type: \"deck\", id: null }` is\n * NOT supported — pass `unscopedOnly: true` to get only general chats.\n */\n scope?: { type: string; id: string };\n /** When true, returns only threads with no scope (general chats). */\n unscopedOnly?: boolean;\n orgId?: string | null;\n /**\n * Include archived threads in the results. Defaults to false: archived\n * threads (`archived_at` set via `setThreadArchived`) are hidden from the\n * ordinary chat list/search so archiving actually removes a thread from\n * view. Pass true for surfaces that explicitly need to see archived chats\n * (e.g. an \"Archived\" filter or restoring one via `setThreadArchived`).\n */\n includeArchived?: boolean;\n}\n\nfunction chatThreadAccessSql(\n userEmail: string,\n orgId: string | null | undefined,\n): { sql: string; args: (string | number)[] } {\n const normalizedEmail = userEmail.trim().toLowerCase();\n const clauses = [\n `LOWER(owner_email) = ?`,\n `EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'user' AND LOWER(chat_thread_shares.principal_id) = ?)`,\n ];\n const args: (string | number)[] = [normalizedEmail, normalizedEmail];\n if (orgId) {\n clauses.push(`(visibility = 'org' AND org_id = ?)`);\n args.push(orgId);\n clauses.push(\n `EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'org' AND chat_thread_shares.principal_id = ?)`,\n );\n args.push(orgId);\n }\n return { sql: `(${clauses.join(\" OR \")})`, args };\n}\n\nexport async function listThreads(\n ownerEmail: string,\n options: ListThreadsOptions | number = {},\n legacyOffset?: number,\n): Promise<ChatThreadSummary[]> {\n await ensureTable();\n // Back-compat shim: previous signature was (owner, limit, offset).\n const opts: ListThreadsOptions =\n typeof options === \"number\"\n ? { limit: options, offset: legacyOffset ?? 0 }\n : options;\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const client = getDbExec();\n // `message_count > 0` is the authoritative \"has messages\" signal maintained\n // on every write, so the old `OR thread_data LIKE '%\"messages\"%'` substring\n // scan over the full blob is no longer needed here.\n const access = chatThreadAccessSql(\n ownerEmail,\n opts.orgId ?? getRequestOrgId(),\n );\n const filters: string[] = [access.sql, `message_count > 0`];\n const args: (string | number)[] = [...access.args];\n if (!opts.includeArchived) {\n filters.push(`archived_at IS NULL`);\n }\n if (opts.scope) {\n filters.push(`scope_type = ? AND scope_id = ?`);\n args.push(opts.scope.type, opts.scope.id);\n } else if (opts.unscopedOnly) {\n filters.push(`scope_type IS NULL`);\n }\n args.push(limit, offset);\n const { rows } = await client.execute({\n sql: `SELECT ${SUMMARY_COLUMNS} FROM chat_threads WHERE ${filters.join(\" AND \")} ORDER BY CASE WHEN pinned_at IS NULL THEN 1 ELSE 0 END, pinned_at DESC, updated_at DESC LIMIT ? OFFSET ?`,\n args,\n });\n return rows\n .map((r) => rowToSummary(r))\n .filter((r): r is ChatThreadSummary => r !== null);\n}\n\nfunction escapeLike(s: string): string {\n return s.replace(/[!%_]/g, (match) => `!${match}`);\n}\n\nexport async function searchThreads(\n ownerEmail: string,\n query: string,\n limit = 50,\n options: {\n scope?: { type: string; id: string };\n orgId?: string | null;\n /** See `ListThreadsOptions.includeArchived` — defaults to false. */\n includeArchived?: boolean;\n } = {},\n): Promise<ChatThreadSummary[]> {\n await ensureTable();\n const client = getDbExec();\n const pattern = `%${escapeLike(query)}%`;\n // The count-guard uses the maintained `message_count` column (same as\n // listThreads). The content match still scans `thread_data` — search\n // legitimately needs to look inside message history.\n const access = chatThreadAccessSql(\n ownerEmail,\n options.orgId ?? getRequestOrgId(),\n );\n const filters: string[] = [\n access.sql,\n `message_count > 0`,\n `(title LIKE ? ESCAPE '!' OR preview LIKE ? ESCAPE '!' OR thread_data LIKE ? ESCAPE '!')`,\n ];\n const args: (string | number)[] = [...access.args, pattern, pattern, pattern];\n if (!options.includeArchived) {\n filters.push(`archived_at IS NULL`);\n }\n if (options.scope) {\n filters.push(`scope_type = ? AND scope_id = ?`);\n args.push(options.scope.type, options.scope.id);\n }\n args.push(limit);\n const { rows } = await client.execute({\n sql: `SELECT ${SUMMARY_COLUMNS} FROM chat_threads WHERE ${filters.join(\" AND \")} ORDER BY CASE WHEN pinned_at IS NULL THEN 1 ELSE 0 END, pinned_at DESC, updated_at DESC LIMIT ?`,\n args,\n });\n return rows\n .map((r) => rowToSummary(r))\n .filter((r): r is ChatThreadSummary => r !== null);\n}\n\n/**\n * Detach or rebind a chat's scope. Used by the UI's \"Detach from <resource>\"\n * action and by templates that need to retag a chat after a rename. Pass\n * `null` to clear the scope (chat becomes general).\n */\nexport async function setThreadScope(\n id: string,\n scope: ChatThreadScope | null,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE chat_threads SET scope_type = ?, scope_id = ?, scope_label = ?, updated_at = ? WHERE id = ?`,\n args: [\n scope?.type ?? null,\n scope?.id ?? null,\n scope?.label ?? null,\n Math.max(Date.now(), 1),\n id,\n ],\n });\n emitChatThreadChange(id);\n}\n\nexport async function renameThread(\n id: string,\n title: string,\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n const nextTitle = normalizeThreadTitle(title);\n if (!nextTitle) return false;\n\n return await withThreadDataLock(id, async () => {\n const thread = await getThread(id);\n if (!thread) return false;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return false;\n }\n\n const repo = parseThreadData(thread.threadData);\n repo._titleOverride = nextTitle;\n await updateThreadData(\n id,\n JSON.stringify(repo),\n nextTitle,\n thread.preview,\n thread.messageCount,\n );\n return true;\n });\n}\n\nexport async function setThreadPinned(\n id: string,\n pinned: boolean,\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const now = Math.max(Date.now(), 1);\n const args: (string | number | null)[] = [pinned ? now : null, id];\n let ownerFilter = \"\";\n if (options.ownerEmail) {\n ownerFilter = \" AND owner_email = ?\";\n args.push(options.ownerEmail);\n }\n const result = await client.execute({\n sql: `UPDATE chat_threads SET pinned_at = ? WHERE id = ?${ownerFilter}`,\n args,\n });\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return true;\n }\n return false;\n}\n\nexport async function setThreadArchived(\n id: string,\n archived: boolean,\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const now = Math.max(Date.now(), 1);\n const args: (string | number | null)[] = [archived ? now : null, id];\n let ownerFilter = \"\";\n if (options.ownerEmail) {\n ownerFilter = \" AND owner_email = ?\";\n args.push(options.ownerEmail);\n }\n const result = await client.execute({\n sql: `UPDATE chat_threads SET archived_at = ? WHERE id = ?${ownerFilter}`,\n args,\n });\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return true;\n }\n return false;\n}\n\nexport interface UpdateThreadDataOptions {\n preserveExistingQueuedMessages?: boolean;\n preserveExistingTopLevelKeys?: boolean;\n maxAttempts?: number;\n ignoreConflicts?: boolean;\n}\n\nfunction parseThreadData(value: string): any {\n try {\n return JSON.parse(value || \"{}\");\n } catch {\n return {};\n }\n}\n\nexport async function updateThreadData(\n id: string,\n threadData: string,\n title: string,\n preview: string,\n messageCount: number,\n options: UpdateThreadDataOptions = {},\n): Promise<void> {\n // getThread() ensures the table exists. Keep that bootstrap inside the\n // retry boundary below so a cold serverless process can recover from a\n // transient initialization/read failure too.\n const client = getDbExec();\n const maxAttempts = Math.max(\n 1,\n options.maxAttempts ?? DEFAULT_THREAD_DATA_UPDATE_ATTEMPTS,\n );\n let lastConflict = false;\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const current = await getThread(id);\n if (!current) return;\n\n let nextThreadData = threadData;\n let nextMessageCount = messageCount;\n try {\n const merged = mergeThreadDataForClientSave(\n parseThreadData(current.threadData),\n parseThreadData(threadData),\n {\n preserveExistingQueuedMessages:\n options.preserveExistingQueuedMessages ?? true,\n preserveExistingTopLevelKeys:\n options.preserveExistingTopLevelKeys ?? true,\n },\n );\n nextThreadData = JSON.stringify(merged);\n if (Array.isArray(merged.messages)) {\n nextMessageCount = merged.messages.length;\n }\n } catch {\n // Keep the caller's serialized value if either JSON blob is malformed.\n }\n\n const nextUpdatedAt = Math.max(Date.now(), current.updatedAt + 1);\n const result = await client.execute({\n sql: `UPDATE chat_threads SET thread_data = ?, title = ?, preview = ?, message_count = ?, updated_at = ? WHERE id = ? AND updated_at = ?`,\n args: [\n nextThreadData,\n title,\n preview,\n nextMessageCount,\n nextUpdatedAt,\n id,\n current.updatedAt,\n ],\n });\n\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return;\n }\n\n lastConflict = true;\n } catch (error) {\n // Completion saves happen after a long model/tool turn, when a\n // transient connection or serverless DB failure is especially costly.\n // Retry the whole read/merge/write attempt like a CAS conflict, while\n // preserving the final error if the database remains unavailable.\n lastError = error;\n }\n\n if (attempt < maxAttempts - 1) {\n await new Promise((resolve) =>\n setTimeout(\n resolve,\n Math.min(250, THREAD_DATA_CONFLICT_BACKOFF_MS * (attempt + 1)),\n ),\n );\n }\n }\n\n if (lastError) throw lastError;\n\n if (lastConflict) {\n if (options.ignoreConflicts) return;\n throw new Error(\n `Failed to update chat thread ${id} after concurrent write conflicts.`,\n );\n }\n}\n\nexport interface ThreadEngineMeta {\n engineName: string;\n model: string;\n}\n\n/**\n * Read the engine pinned to a thread (stored in thread_data JSON).\n * Returns null if no engine is pinned.\n */\nexport async function getThreadEngineMeta(\n threadId: string,\n): Promise<ThreadEngineMeta | null> {\n const thread = await getThread(threadId);\n if (!thread?.threadData) return null;\n try {\n const data = JSON.parse(thread.threadData);\n if (data.engineMeta?.engineName) return data.engineMeta as ThreadEngineMeta;\n } catch {}\n return null;\n}\n\n/**\n * Pin an engine to a thread by storing engineMeta in thread_data JSON.\n * Does not change messages, title, or preview.\n */\nexport async function setThreadEngineMeta(\n threadId: string,\n meta: ThreadEngineMeta,\n): Promise<void> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return;\n let data: Record<string, unknown> = {};\n try {\n data = JSON.parse(thread.threadData);\n } catch {}\n data.engineMeta = meta;\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n );\n });\n}\n\nexport interface QueuedMessage {\n id: string;\n text: string;\n images?: string[];\n references?: unknown[];\n}\n\n/**\n * Persist the user's queued (not-yet-sent) messages onto the thread.\n * Stored in thread_data JSON so it survives reloads without a schema\n * change. Safe to call often — the frontend debounces writes.\n *\n * Returns false when the thread is missing or `ownerEmail` doesn't match.\n * Callers that already need an ownership check should pass `ownerEmail`\n * here instead of doing their own getThread first — this path fires on\n * debounced composer writes, so a redundant pre-read of the full\n * thread_data blob is a real per-keystroke cost.\n */\nexport async function setThreadQueuedMessages(\n threadId: string,\n queuedMessages: QueuedMessage[],\n options: { ownerEmail?: string } = {},\n): Promise<boolean> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return false;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return false;\n }\n let data: Record<string, unknown> = {};\n try {\n data = JSON.parse(thread.threadData);\n } catch {}\n // Keep an explicit empty tombstone. Other mounted chat surfaces only\n // reconcile queue state when this field is present; deleting it lets a\n // stale local queue survive the clear and submit the same prompt again.\n data.queuedMessages = queuedMessages;\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n { preserveExistingQueuedMessages: false },\n );\n return true;\n });\n}\n\nconst THREAD_SHARE_DATA_KEY = \"_share\";\n\ninterface StoredThreadShare {\n tokenHash?: string;\n createdAt?: number;\n updatedAt?: number;\n revokedAt?: number | null;\n}\n\nexport interface ChatThreadShareState {\n enabled: boolean;\n createdAt: number | null;\n updatedAt: number | null;\n revokedAt: number | null;\n}\n\nexport interface ChatThreadShareLink extends ChatThreadShareState {\n enabled: true;\n token: string;\n}\n\nfunction generateShareToken(): string {\n return crypto.randomBytes(24).toString(\"base64url\");\n}\n\nexport function hashThreadShareToken(token: string): string {\n return crypto.createHash(\"sha256\").update(token).digest(\"hex\");\n}\n\nfunction normalizeThreadShare(value: unknown): StoredThreadShare | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const r = value as Record<string, unknown>;\n const tokenHash =\n typeof r.tokenHash === \"string\" && /^[a-f0-9]{64}$/i.test(r.tokenHash)\n ? r.tokenHash.toLowerCase()\n : undefined;\n const createdAt = normalizeTimestamp(r.createdAt);\n const updatedAt = normalizeTimestamp(r.updatedAt);\n const revokedAt = normalizeTimestamp(r.revokedAt);\n if (!tokenHash && !createdAt && !updatedAt && !revokedAt) return null;\n return {\n ...(tokenHash ? { tokenHash } : {}),\n ...(createdAt ? { createdAt } : {}),\n ...(updatedAt ? { updatedAt } : {}),\n ...(revokedAt ? { revokedAt } : {}),\n };\n}\n\nfunction normalizeTimestamp(value: unknown): number | undefined {\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nfunction shareStateFromStored(\n stored: StoredThreadShare | null,\n): ChatThreadShareState {\n const revokedAt = stored?.revokedAt ?? null;\n return {\n enabled: Boolean(stored?.tokenHash && !revokedAt),\n createdAt: stored?.createdAt ?? null,\n updatedAt: stored?.updatedAt ?? null,\n revokedAt,\n };\n}\n\nfunction readStoredThreadShare(threadData: string): StoredThreadShare | null {\n const data = parseThreadData(threadData);\n return normalizeThreadShare(data[THREAD_SHARE_DATA_KEY]);\n}\n\nexport async function getThreadShareState(\n threadId: string,\n options: { ownerEmail?: string } = {},\n): Promise<ChatThreadShareState | null> {\n const thread = await getThread(threadId);\n if (!thread) return null;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return null;\n }\n return shareStateFromStored(readStoredThreadShare(thread.threadData));\n}\n\nexport async function createThreadShareLink(\n threadId: string,\n options: { ownerEmail?: string } = {},\n): Promise<ChatThreadShareLink | null> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return null;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return null;\n }\n\n const now = Date.now();\n const token = generateShareToken();\n const tokenHash = hashThreadShareToken(token);\n const data = parseThreadData(thread.threadData);\n const existing = normalizeThreadShare(data[THREAD_SHARE_DATA_KEY]);\n data[THREAD_SHARE_DATA_KEY] = {\n tokenHash,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n revokedAt: null,\n } satisfies StoredThreadShare;\n\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n );\n // Mirror the hash into the indexed column so getThreadByShareToken\n // resolves via an equality lookup instead of a LIKE scan over every\n // thread's blob. thread_data stays the source of truth for validation.\n await setThreadShareTokenHashColumn(threadId, tokenHash);\n\n return {\n enabled: true,\n token,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n revokedAt: null,\n };\n });\n}\n\nasync function setThreadShareTokenHashColumn(\n threadId: string,\n tokenHash: string | null,\n): Promise<void> {\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE chat_threads SET share_token_hash = ? WHERE id = ?`,\n args: [tokenHash, threadId],\n });\n}\n\nexport async function revokeThreadShareLink(\n threadId: string,\n options: { ownerEmail?: string } = {},\n): Promise<ChatThreadShareState | null> {\n return withThreadDataLock(threadId, async () => {\n const thread = await getThread(threadId);\n if (!thread) return null;\n if (options.ownerEmail && thread.ownerEmail !== options.ownerEmail) {\n return null;\n }\n\n const now = Date.now();\n const data = parseThreadData(thread.threadData);\n const existing = normalizeThreadShare(data[THREAD_SHARE_DATA_KEY]);\n data[THREAD_SHARE_DATA_KEY] = {\n ...(existing?.createdAt ? { createdAt: existing.createdAt } : {}),\n updatedAt: now,\n revokedAt: now,\n } satisfies StoredThreadShare;\n\n await updateThreadData(\n threadId,\n JSON.stringify(data),\n thread.title,\n thread.preview,\n thread.messageCount,\n );\n await setThreadShareTokenHashColumn(threadId, null);\n\n return {\n enabled: false,\n createdAt: existing?.createdAt ?? null,\n updatedAt: now,\n revokedAt: now,\n };\n });\n}\n\nexport async function getThreadByShareToken(\n token: string,\n): Promise<ChatThread | null> {\n const cleanToken = token.trim();\n if (!cleanToken || cleanToken.length < 16) return null;\n await ensureTable();\n const tokenHash = hashThreadShareToken(cleanToken);\n const client = getDbExec();\n\n const validate = (row: Record<string, unknown>): ChatThread | null => {\n const thread = rowToThread(row);\n // thread_data remains the source of truth: verify the stored share\n // matches and is not revoked even when the indexed column matched.\n const stored = readStoredThreadShare(thread.threadData);\n if (!stored?.tokenHash || stored.revokedAt) return null;\n if (stored.tokenHash !== tokenHash) return null;\n return thread;\n };\n\n // Fast path: indexed equality lookup on the mirrored hash column.\n const indexed = await client.execute({\n sql: `SELECT ${THREAD_COLUMNS} FROM chat_threads WHERE share_token_hash = ? LIMIT 10`,\n args: [tokenHash],\n });\n for (const row of indexed.rows) {\n const thread = validate(row);\n if (thread) return thread;\n }\n\n // Legacy fallback: shares created before the share_token_hash column\n // existed only carry the hash inside the thread_data blob. Backfill the\n // column on hit so the next lookup takes the indexed path.\n const legacy = await client.execute({\n sql: `SELECT ${THREAD_COLUMNS} FROM chat_threads WHERE share_token_hash IS NULL AND thread_data LIKE ? LIMIT 10`,\n args: [`%${tokenHash}%`],\n });\n for (const row of legacy.rows) {\n const thread = validate(row);\n if (thread) {\n await setThreadShareTokenHashColumn(thread.id, tokenHash).catch(() => {});\n return thread;\n }\n }\n return null;\n}\n\n/**\n * Grant a user an explicit share on a thread they don't own. Used by the\n * messaging-integration path, where a channel conversation runs as the\n * integration service principal and so creates a thread owned by\n * `integration@<platform>` rather than the human who asked — without this the\n * \"Open thread\" deep link resolves to a 404 for them.\n *\n * Idempotent, and never downgrades an existing stronger role.\n */\nexport async function grantThreadUserShare(\n threadId: string,\n userEmail: string,\n role: ShareRole,\n grantedBy: string,\n): Promise<void> {\n const normalizedEmail = userEmail.trim().toLowerCase();\n if (!threadId || !normalizedEmail.includes(\"@\")) return;\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, role FROM chat_thread_shares WHERE resource_id = ? AND principal_type = 'user' AND LOWER(principal_id) = ?`,\n args: [threadId, normalizedEmail],\n });\n const existing = rows[0];\n if (existing) {\n if (roleSatisfies(existing.role as ShareRole, role)) return;\n await client.execute({\n sql: `UPDATE chat_thread_shares SET role = ? WHERE id = ?`,\n args: [role, existing.id as string],\n });\n return;\n }\n await client.execute({\n sql: `INSERT INTO chat_thread_shares (id, resource_id, principal_type, principal_id, role, created_by, created_at) VALUES (?, ?, 'user', ?, ?, ?, ?)`,\n args: [\n crypto.randomUUID(),\n threadId,\n normalizedEmail,\n role,\n grantedBy,\n new Date().toISOString(),\n ],\n });\n}\n\nexport async function deleteThread(id: string): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `DELETE FROM chat_threads WHERE id = ?`,\n args: [id],\n });\n if (result.rowsAffected > 0) {\n await client\n .execute({\n sql: `DELETE FROM chat_thread_shares WHERE resource_id = ?`,\n args: [id],\n })\n .catch(() => {});\n emitChatThreadChange(id);\n return true;\n }\n return false;\n}\n"]}