@agent-native/core 0.132.1 → 0.133.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 (456) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +198 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/correlation.ts +11 -1
  5. package/corpus/core/src/a2a/types.ts +11 -3
  6. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +33 -46
  7. package/corpus/core/src/agent/engine/builder-engine.ts +22 -10
  8. package/corpus/core/src/agent/engine/error-detail.ts +184 -3
  9. package/corpus/core/src/agent/engine/failure-taxonomy.ts +123 -0
  10. package/corpus/core/src/agent/engine/index.ts +8 -0
  11. package/corpus/core/src/agent/engine/registry.ts +92 -8
  12. package/corpus/core/src/agent/engine/translate-ai-sdk.ts +17 -2
  13. package/corpus/core/src/agent/production-agent.ts +13 -33
  14. package/corpus/core/src/agent/run-loop-with-resume.ts +1 -1
  15. package/corpus/core/src/agent/run-manager.ts +43 -14
  16. package/corpus/core/src/agent/run-store.ts +30 -3
  17. package/corpus/core/src/agent/thread-data-builder.ts +36 -4
  18. package/corpus/core/src/chat-threads/store.ts +42 -0
  19. package/corpus/core/src/cli/templates-meta.ts +13 -0
  20. package/corpus/core/src/cli/workspace-dev.ts +1 -0
  21. package/corpus/core/src/client/error-format.ts +12 -0
  22. package/corpus/core/src/client/use-chat-threads.ts +76 -16
  23. package/corpus/core/src/credentials/index.ts +51 -12
  24. package/corpus/core/src/extensions/url-safety.ts +46 -12
  25. package/corpus/core/src/integrations/adapters/slack.ts +32 -10
  26. package/corpus/core/src/integrations/google-docs-poller.ts +12 -1
  27. package/corpus/core/src/integrations/installations-store.ts +30 -0
  28. package/corpus/core/src/integrations/plugin.ts +5 -5
  29. package/corpus/core/src/integrations/types.ts +7 -0
  30. package/corpus/core/src/integrations/webhook-handler.ts +24 -1
  31. package/corpus/core/src/jobs/background-automation-runner.ts +38 -1
  32. package/corpus/core/src/provider-api/index.ts +8 -2
  33. package/corpus/core/src/scripts/call-agent.ts +6 -0
  34. package/corpus/core/src/server/agent-chat-plugin.ts +46 -10
  35. package/corpus/core/src/server/agent-discovery.ts +2 -0
  36. package/corpus/core/src/server/builder-design-systems.ts +21 -0
  37. package/corpus/core/src/server/credential-provider.ts +51 -12
  38. package/corpus/core/src/server/index.ts +1 -0
  39. package/corpus/core/src/server/onboarding-html.ts +37 -2
  40. package/corpus/core/src/shared/reasoning-effort.ts +1 -1
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  42. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -2
  43. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +39 -19
  44. package/corpus/templates/assets/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  45. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +30 -3
  46. package/corpus/templates/brain/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  47. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
  48. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +54 -25
  49. package/corpus/templates/calendar/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  50. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  51. package/corpus/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  52. package/corpus/templates/clips/app/components/library/library-layout.tsx +37 -21
  53. package/corpus/templates/clips/changelog/2026-07-30-meeting-microphone-transcription-works-reliably-from-the-fir.md +6 -0
  54. package/corpus/templates/clips/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  55. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +1 -1
  56. package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +1 -1
  57. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +13 -0
  58. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +2 -0
  59. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +25 -132
  60. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +34 -17
  61. package/corpus/templates/content/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  62. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -2
  63. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +5 -0
  64. package/corpus/templates/design/actions/create-design-system.ts +1 -0
  65. package/corpus/templates/design/actions/set-default-design-system.ts +34 -26
  66. package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +5 -3
  67. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +23 -0
  68. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +3 -0
  69. package/corpus/templates/design/app/components/layout/Sidebar.tsx +21 -4
  70. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -7
  71. package/corpus/templates/design/app/i18n-data.ts +39 -0
  72. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +229 -12
  73. package/corpus/templates/design/app/pages/DesignSystems.tsx +10 -4
  74. package/corpus/templates/design/changelog/2026-07-30-fixed-the-keyboard-shortcuts-panel-not-opening-with-ctrl-shi.md +6 -0
  75. package/corpus/templates/design/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  76. package/corpus/templates/design/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
  77. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +19 -4
  78. package/corpus/templates/dispatch/AGENTS.md +4 -0
  79. package/corpus/templates/factory/.agents/skills/actions/SKILL.md +562 -0
  80. package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +198 -0
  81. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +115 -0
  82. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +182 -0
  83. package/corpus/templates/factory/.agents/skills/capture-learnings/SKILL.md +89 -0
  84. package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +221 -0
  85. package/corpus/templates/factory/.agents/skills/customizing-agent-native/SKILL.md +220 -0
  86. package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +263 -0
  87. package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +52 -0
  88. package/corpus/templates/factory/.agents/skills/feature-flags/SKILL.md +169 -0
  89. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +174 -0
  90. package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +232 -0
  91. package/corpus/templates/factory/.agents/skills/security/SKILL.md +324 -0
  92. package/corpus/templates/factory/.agents/skills/self-modifying-code/SKILL.md +119 -0
  93. package/corpus/templates/factory/.agents/skills/shadcn-ui/SKILL.md +123 -0
  94. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +232 -0
  95. package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +178 -0
  96. package/corpus/templates/factory/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
  97. package/corpus/templates/factory/.env.example +24 -0
  98. package/corpus/templates/factory/.ignore +0 -0
  99. package/corpus/templates/factory/.oxfmtrc.json +8 -0
  100. package/corpus/templates/factory/AGENTS.md +90 -0
  101. package/corpus/templates/factory/CHANGELOG.md +10 -0
  102. package/corpus/templates/factory/DEVELOPING.md +185 -0
  103. package/corpus/templates/factory/README.md +64 -0
  104. package/corpus/templates/factory/_gitignore +42 -0
  105. package/corpus/templates/factory/actions/add-factory-comment.ts +55 -0
  106. package/corpus/templates/factory/actions/approve-factory-item.ts +214 -0
  107. package/corpus/templates/factory/actions/babysit-pull-request.ts +126 -0
  108. package/corpus/templates/factory/actions/evaluate-triage-item.ts +172 -0
  109. package/corpus/templates/factory/actions/get-factory-graph.ts +62 -0
  110. package/corpus/templates/factory/actions/get-triage-config.ts +42 -0
  111. package/corpus/templates/factory/actions/get-triage-item.ts +74 -0
  112. package/corpus/templates/factory/actions/hello.ts +13 -0
  113. package/corpus/templates/factory/actions/ingest-github-observation.ts +100 -0
  114. package/corpus/templates/factory/actions/list-factories.ts +40 -0
  115. package/corpus/templates/factory/actions/list-factory-comments.ts +40 -0
  116. package/corpus/templates/factory/actions/list-triage-items.ts +85 -0
  117. package/corpus/templates/factory/actions/list-triage-rules.ts +44 -0
  118. package/corpus/templates/factory/actions/navigate.ts +41 -0
  119. package/corpus/templates/factory/actions/poll-slack-channel.ts +118 -0
  120. package/corpus/templates/factory/actions/reconcile-triage-run.ts +179 -0
  121. package/corpus/templates/factory/actions/record-triage-feedback.ts +58 -0
  122. package/corpus/templates/factory/actions/run.ts +2 -0
  123. package/corpus/templates/factory/actions/save-factory-graph.ts +129 -0
  124. package/corpus/templates/factory/actions/save-triage-config.ts +67 -0
  125. package/corpus/templates/factory/actions/save-triage-rule.ts +89 -0
  126. package/corpus/templates/factory/actions/suggest-factory-rules.ts +70 -0
  127. package/corpus/templates/factory/actions/view-screen.ts +73 -0
  128. package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +441 -0
  129. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +388 -0
  130. package/corpus/templates/factory/app/components/layout/Header.tsx +60 -0
  131. package/corpus/templates/factory/app/components/layout/Layout.tsx +190 -0
  132. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +538 -0
  133. package/corpus/templates/factory/app/components/triage/triage-status-pill.tsx +28 -0
  134. package/corpus/templates/factory/app/components/ui/button.tsx +1 -0
  135. package/corpus/templates/factory/app/components/ui/card.tsx +1 -0
  136. package/corpus/templates/factory/app/components/ui/dropdown-menu.tsx +1 -0
  137. package/corpus/templates/factory/app/components/ui/input.tsx +1 -0
  138. package/corpus/templates/factory/app/components/ui/label.tsx +1 -0
  139. package/corpus/templates/factory/app/components/ui/sheet.tsx +1 -0
  140. package/corpus/templates/factory/app/components/ui/textarea.tsx +1 -0
  141. package/corpus/templates/factory/app/components/ui/toolkit-provider.tsx +17 -0
  142. package/corpus/templates/factory/app/components/ui/tooltip.tsx +1 -0
  143. package/corpus/templates/factory/app/design-system.ts +3 -0
  144. package/corpus/templates/factory/app/entry.client.tsx +22 -0
  145. package/corpus/templates/factory/app/entry.server.tsx +10 -0
  146. package/corpus/templates/factory/app/global.css +93 -0
  147. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +113 -0
  148. package/corpus/templates/factory/app/i18n/en-US.ts +211 -0
  149. package/corpus/templates/factory/app/i18n/index.ts +34 -0
  150. package/corpus/templates/factory/app/i18n-data.ts +556 -0
  151. package/corpus/templates/factory/app/lib/agent-page.tsx +49 -0
  152. package/corpus/templates/factory/app/lib/app-config.ts +11 -0
  153. package/corpus/templates/factory/app/lib/tab-id.ts +1 -0
  154. package/corpus/templates/factory/app/lib/utils.ts +1 -0
  155. package/corpus/templates/factory/app/root.tsx +175 -0
  156. package/corpus/templates/factory/app/routes/_index.tsx +94 -0
  157. package/corpus/templates/factory/app/routes/agent.tsx +24 -0
  158. package/corpus/templates/factory/app/routes/chat.$threadId.tsx +1 -0
  159. package/corpus/templates/factory/app/routes/database.tsx +17 -0
  160. package/corpus/templates/factory/app/routes/extensions.$id.$slug.tsx +2 -0
  161. package/corpus/templates/factory/app/routes/extensions.$id.tsx +11 -0
  162. package/corpus/templates/factory/app/routes/extensions._index.tsx +11 -0
  163. package/corpus/templates/factory/app/routes/extensions.tsx +5 -0
  164. package/corpus/templates/factory/app/routes/factory.tsx +1003 -0
  165. package/corpus/templates/factory/app/routes/observability.tsx +19 -0
  166. package/corpus/templates/factory/app/routes/settings.tsx +89 -0
  167. package/corpus/templates/factory/app/routes/team.tsx +11 -0
  168. package/corpus/templates/factory/app/routes.ts +4 -0
  169. package/corpus/templates/factory/app/vite-env.d.ts +6 -0
  170. package/corpus/templates/factory/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  171. package/corpus/templates/factory/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  172. package/corpus/templates/factory/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
  173. package/corpus/templates/factory/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  174. package/corpus/templates/factory/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  175. package/corpus/templates/factory/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  176. package/corpus/templates/factory/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  177. package/corpus/templates/factory/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  178. package/corpus/templates/factory/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
  179. package/corpus/templates/factory/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  180. package/corpus/templates/factory/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
  181. package/corpus/templates/factory/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
  182. package/corpus/templates/factory/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  183. package/corpus/templates/factory/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  184. package/corpus/templates/factory/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  185. package/corpus/templates/factory/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  186. package/corpus/templates/factory/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
  187. package/corpus/templates/factory/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  188. package/corpus/templates/factory/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  189. package/corpus/templates/factory/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
  190. package/corpus/templates/factory/changelog/2026-07-29-sidebar-footers-now-keep-feedback-search-and-collapse-togeth.md +6 -0
  191. package/corpus/templates/factory/changelog/2026-07-31-added-an-inspectable-observe-only-factory-queue-for-slack-.md +6 -0
  192. package/corpus/templates/factory/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  193. package/corpus/templates/factory/components.json +20 -0
  194. package/corpus/templates/factory/data/sync-config.json +1 -0
  195. package/corpus/templates/factory/learnings.defaults.md +5 -0
  196. package/corpus/templates/factory/netlify.toml +10 -0
  197. package/corpus/templates/factory/package.json +105 -0
  198. package/corpus/templates/factory/public/agent-native-icon-dark.svg +10 -0
  199. package/corpus/templates/factory/public/agent-native-icon-light.svg +10 -0
  200. package/corpus/templates/factory/public/agent-native-logo-dark.svg +21 -0
  201. package/corpus/templates/factory/public/agent-native-logo-light.svg +21 -0
  202. package/corpus/templates/factory/public/favicon.svg +1 -0
  203. package/corpus/templates/factory/public/icon-180.svg +1 -0
  204. package/corpus/templates/factory/public/icon-192.svg +1 -0
  205. package/corpus/templates/factory/public/icon-512.svg +1 -0
  206. package/corpus/templates/factory/public/manifest.json +21 -0
  207. package/corpus/templates/factory/react-router.config.ts +7 -0
  208. package/corpus/templates/factory/server/connectors/credentials.ts +129 -0
  209. package/corpus/templates/factory/server/connectors/slack.ts +129 -0
  210. package/corpus/templates/factory/server/db/index.ts +6 -0
  211. package/corpus/templates/factory/server/db/schema.ts +193 -0
  212. package/corpus/templates/factory/server/factory-graph/contracts.ts +212 -0
  213. package/corpus/templates/factory/server/factory-graph/store.ts +121 -0
  214. package/corpus/templates/factory/server/lib/require-workspace-member.ts +55 -0
  215. package/corpus/templates/factory/server/middleware/auth.ts +15 -0
  216. package/corpus/templates/factory/server/plugins/agent-chat.ts +58 -0
  217. package/corpus/templates/factory/server/plugins/auth.ts +14 -0
  218. package/corpus/templates/factory/server/plugins/factory-migrations.ts +247 -0
  219. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +116 -0
  220. package/corpus/templates/factory/server/plugins/integrations.ts +46 -0
  221. package/corpus/templates/factory/server/routes/[...page].get.ts +5 -0
  222. package/corpus/templates/factory/server/routes/_agent-native/factory/builder-callback.post.ts +116 -0
  223. package/corpus/templates/factory/server/triage/ai-services-git.ts +197 -0
  224. package/corpus/templates/factory/server/triage/builder-executor.ts +118 -0
  225. package/corpus/templates/factory/server/triage/contracts.ts +164 -0
  226. package/corpus/templates/factory/server/triage/github-ingestion.ts +35 -0
  227. package/corpus/templates/factory/server/triage/guards.ts +121 -0
  228. package/corpus/templates/factory/server/triage/ids.ts +27 -0
  229. package/corpus/templates/factory/server/triage/pr-babysit.ts +100 -0
  230. package/corpus/templates/factory/server/triage/pr-monitor.ts +220 -0
  231. package/corpus/templates/factory/server/triage/slack-client.ts +55 -0
  232. package/corpus/templates/factory/server/triage/slack-poller.ts +152 -0
  233. package/corpus/templates/factory/ssr-entry.ts +15 -0
  234. package/corpus/templates/factory/tsconfig.json +21 -0
  235. package/corpus/templates/factory/vite.config.ts +19 -0
  236. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +55 -5
  237. package/corpus/templates/forms/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  238. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +6 -2
  239. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +21 -6
  240. package/corpus/templates/plan/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  241. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +12 -0
  242. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -0
  243. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +11 -0
  244. package/corpus/templates/slides/AGENTS.md +5 -6
  245. package/corpus/templates/slides/actions/_await-fit-check.ts +20 -10
  246. package/corpus/templates/slides/actions/add-slide.ts +17 -4
  247. package/corpus/templates/slides/actions/create-design-system.ts +16 -4
  248. package/corpus/templates/slides/actions/delete-design-system.ts +18 -2
  249. package/corpus/templates/slides/actions/get-layout-overflows.ts +88 -0
  250. package/corpus/templates/slides/actions/import-file.ts +1 -0
  251. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +8 -0
  252. package/corpus/templates/slides/actions/patch-deck.ts +48 -16
  253. package/corpus/templates/slides/actions/set-default-design-system.ts +49 -19
  254. package/corpus/templates/slides/actions/update-slide.ts +13 -3
  255. package/corpus/templates/slides/actions/view-screen.ts +87 -10
  256. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +155 -28
  257. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +21 -17
  258. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +849 -341
  259. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +102 -2
  260. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +13 -16
  261. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +60 -12
  262. package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +11 -1
  263. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +66 -19
  264. package/corpus/templates/slides/app/i18n/en-US.ts +23 -0
  265. package/corpus/templates/slides/app/lib/normalize-slide-padding.ts +8 -15
  266. package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -3
  267. package/corpus/templates/slides/app/pages/DesignSystems.tsx +4 -3
  268. package/corpus/templates/slides/app/pages/Index.tsx +1 -1
  269. package/corpus/templates/slides/changelog/2026-07-31-design-system-details-now-show-their-source-and-indexing-sta.md +6 -0
  270. package/corpus/templates/slides/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
  271. package/corpus/templates/slides/changelog/2026-07-31-design-system-setup-keeps-focus-rings-visible-and-uses-a-sim.md +6 -0
  272. package/corpus/templates/slides/changelog/2026-07-31-skip-prompt-is-now-available-in-the-new-deck-prompt-header.md +6 -0
  273. package/corpus/templates/slides/changelog/2026-07-31-slides-now-detect-real-text-and-box-overflow-across-the-deck.md +6 -0
  274. package/corpus/templates/slides/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
  275. package/corpus/templates/slides/server/handlers/design-systems.ts +1 -0
  276. package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +1 -0
  277. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +23 -4
  278. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
  279. package/corpus/templates/slides/server/plugins/creative-context.ts +16 -3
  280. package/corpus/templates/slides/server/workspace-defaults.ts +5 -1
  281. package/corpus/templates/slides/shared/slide-fit.ts +26 -0
  282. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +30 -3
  283. package/corpus/templates/tasks/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  284. package/dist/a2a/correlation.d.ts +4 -1
  285. package/dist/a2a/correlation.d.ts.map +1 -1
  286. package/dist/a2a/correlation.js +8 -1
  287. package/dist/a2a/correlation.js.map +1 -1
  288. package/dist/a2a/types.d.ts +11 -3
  289. package/dist/a2a/types.d.ts.map +1 -1
  290. package/dist/a2a/types.js.map +1 -1
  291. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  292. package/dist/agent/engine/ai-sdk-engine.js +27 -41
  293. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  294. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  295. package/dist/agent/engine/builder-engine.js +18 -8
  296. package/dist/agent/engine/builder-engine.js.map +1 -1
  297. package/dist/agent/engine/error-detail.d.ts +61 -0
  298. package/dist/agent/engine/error-detail.d.ts.map +1 -1
  299. package/dist/agent/engine/error-detail.js +145 -3
  300. package/dist/agent/engine/error-detail.js.map +1 -1
  301. package/dist/agent/engine/failure-taxonomy.d.ts +24 -0
  302. package/dist/agent/engine/failure-taxonomy.d.ts.map +1 -0
  303. package/dist/agent/engine/failure-taxonomy.js +88 -0
  304. package/dist/agent/engine/failure-taxonomy.js.map +1 -0
  305. package/dist/agent/engine/index.d.ts +2 -1
  306. package/dist/agent/engine/index.d.ts.map +1 -1
  307. package/dist/agent/engine/index.js +2 -1
  308. package/dist/agent/engine/index.js.map +1 -1
  309. package/dist/agent/engine/registry.d.ts +16 -0
  310. package/dist/agent/engine/registry.d.ts.map +1 -1
  311. package/dist/agent/engine/registry.js +71 -6
  312. package/dist/agent/engine/registry.js.map +1 -1
  313. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  314. package/dist/agent/engine/translate-ai-sdk.js +14 -2
  315. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  316. package/dist/agent/production-agent.d.ts.map +1 -1
  317. package/dist/agent/production-agent.js +13 -24
  318. package/dist/agent/production-agent.js.map +1 -1
  319. package/dist/agent/run-loop-with-resume.js +1 -1
  320. package/dist/agent/run-loop-with-resume.js.map +1 -1
  321. package/dist/agent/run-manager.d.ts.map +1 -1
  322. package/dist/agent/run-manager.js +39 -10
  323. package/dist/agent/run-manager.js.map +1 -1
  324. package/dist/agent/run-store.d.ts +10 -0
  325. package/dist/agent/run-store.d.ts.map +1 -1
  326. package/dist/agent/run-store.js +20 -3
  327. package/dist/agent/run-store.js.map +1 -1
  328. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  329. package/dist/agent/thread-data-builder.js +28 -4
  330. package/dist/agent/thread-data-builder.js.map +1 -1
  331. package/dist/chat-threads/store.d.ts +13 -0
  332. package/dist/chat-threads/store.d.ts.map +1 -1
  333. package/dist/chat-threads/store.js +35 -0
  334. package/dist/chat-threads/store.js.map +1 -1
  335. package/dist/cli/templates-meta.d.ts.map +1 -1
  336. package/dist/cli/templates-meta.js +13 -0
  337. package/dist/cli/templates-meta.js.map +1 -1
  338. package/dist/cli/workspace-dev.d.ts.map +1 -1
  339. package/dist/cli/workspace-dev.js +1 -0
  340. package/dist/cli/workspace-dev.js.map +1 -1
  341. package/dist/client/error-format.d.ts.map +1 -1
  342. package/dist/client/error-format.js +10 -0
  343. package/dist/client/error-format.js.map +1 -1
  344. package/dist/client/use-chat-threads.d.ts.map +1 -1
  345. package/dist/client/use-chat-threads.js +66 -16
  346. package/dist/client/use-chat-threads.js.map +1 -1
  347. package/dist/collab/awareness.d.ts +2 -2
  348. package/dist/collab/awareness.d.ts.map +1 -1
  349. package/dist/collab/struct-routes.d.ts +1 -1
  350. package/dist/credentials/index.d.ts +9 -2
  351. package/dist/credentials/index.d.ts.map +1 -1
  352. package/dist/credentials/index.js +50 -8
  353. package/dist/credentials/index.js.map +1 -1
  354. package/dist/extensions/url-safety.d.ts.map +1 -1
  355. package/dist/extensions/url-safety.js +38 -12
  356. package/dist/extensions/url-safety.js.map +1 -1
  357. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  358. package/dist/integrations/adapters/slack.js +25 -8
  359. package/dist/integrations/adapters/slack.js.map +1 -1
  360. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  361. package/dist/integrations/google-docs-poller.js +13 -1
  362. package/dist/integrations/google-docs-poller.js.map +1 -1
  363. package/dist/integrations/installations-store.d.ts +10 -0
  364. package/dist/integrations/installations-store.d.ts.map +1 -1
  365. package/dist/integrations/installations-store.js +24 -0
  366. package/dist/integrations/installations-store.js.map +1 -1
  367. package/dist/integrations/plugin.d.ts.map +1 -1
  368. package/dist/integrations/plugin.js +6 -5
  369. package/dist/integrations/plugin.js.map +1 -1
  370. package/dist/integrations/types.d.ts +7 -0
  371. package/dist/integrations/types.d.ts.map +1 -1
  372. package/dist/integrations/types.js.map +1 -1
  373. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  374. package/dist/integrations/webhook-handler.js +16 -1
  375. package/dist/integrations/webhook-handler.js.map +1 -1
  376. package/dist/jobs/background-automation-runner.d.ts.map +1 -1
  377. package/dist/jobs/background-automation-runner.js +35 -2
  378. package/dist/jobs/background-automation-runner.js.map +1 -1
  379. package/dist/notifications/routes.d.ts +6 -6
  380. package/dist/observability/routes.d.ts +3 -3
  381. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  382. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  383. package/dist/provider-api/index.js +7 -3
  384. package/dist/provider-api/index.js.map +1 -1
  385. package/dist/scripts/call-agent.d.ts.map +1 -1
  386. package/dist/scripts/call-agent.js +6 -1
  387. package/dist/scripts/call-agent.js.map +1 -1
  388. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  389. package/dist/server/agent-chat-plugin.js +38 -9
  390. package/dist/server/agent-chat-plugin.js.map +1 -1
  391. package/dist/server/agent-discovery.d.ts +2 -0
  392. package/dist/server/agent-discovery.d.ts.map +1 -1
  393. package/dist/server/agent-discovery.js.map +1 -1
  394. package/dist/server/builder-design-systems.d.ts +4 -1
  395. package/dist/server/builder-design-systems.d.ts.map +1 -1
  396. package/dist/server/builder-design-systems.js +11 -1
  397. package/dist/server/builder-design-systems.js.map +1 -1
  398. package/dist/server/credential-provider.d.ts.map +1 -1
  399. package/dist/server/credential-provider.js +49 -12
  400. package/dist/server/credential-provider.js.map +1 -1
  401. package/dist/server/index.d.ts +1 -1
  402. package/dist/server/index.d.ts.map +1 -1
  403. package/dist/server/index.js.map +1 -1
  404. package/dist/server/onboarding-html.d.ts.map +1 -1
  405. package/dist/server/onboarding-html.js +37 -2
  406. package/dist/server/onboarding-html.js.map +1 -1
  407. package/dist/server/transcribe-voice.d.ts +1 -1
  408. package/dist/shared/reasoning-effort.d.ts +1 -0
  409. package/dist/shared/reasoning-effort.d.ts.map +1 -1
  410. package/dist/shared/reasoning-effort.js +1 -1
  411. package/dist/shared/reasoning-effort.js.map +1 -1
  412. package/dist/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  413. package/dist/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  414. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  415. package/package.json +1 -1
  416. package/src/a2a/correlation.ts +11 -1
  417. package/src/a2a/types.ts +11 -3
  418. package/src/agent/engine/ai-sdk-engine.ts +33 -46
  419. package/src/agent/engine/builder-engine.ts +22 -10
  420. package/src/agent/engine/error-detail.ts +184 -3
  421. package/src/agent/engine/failure-taxonomy.ts +123 -0
  422. package/src/agent/engine/index.ts +8 -0
  423. package/src/agent/engine/registry.ts +92 -8
  424. package/src/agent/engine/translate-ai-sdk.ts +17 -2
  425. package/src/agent/production-agent.ts +13 -33
  426. package/src/agent/run-loop-with-resume.ts +1 -1
  427. package/src/agent/run-manager.ts +43 -14
  428. package/src/agent/run-store.ts +30 -3
  429. package/src/agent/thread-data-builder.ts +36 -4
  430. package/src/chat-threads/store.ts +42 -0
  431. package/src/cli/templates-meta.ts +13 -0
  432. package/src/cli/workspace-dev.ts +1 -0
  433. package/src/client/error-format.ts +12 -0
  434. package/src/client/use-chat-threads.ts +76 -16
  435. package/src/credentials/index.ts +51 -12
  436. package/src/extensions/url-safety.ts +46 -12
  437. package/src/integrations/adapters/slack.ts +32 -10
  438. package/src/integrations/google-docs-poller.ts +12 -1
  439. package/src/integrations/installations-store.ts +30 -0
  440. package/src/integrations/plugin.ts +5 -5
  441. package/src/integrations/types.ts +7 -0
  442. package/src/integrations/webhook-handler.ts +24 -1
  443. package/src/jobs/background-automation-runner.ts +38 -1
  444. package/src/provider-api/index.ts +8 -2
  445. package/src/scripts/call-agent.ts +6 -0
  446. package/src/server/agent-chat-plugin.ts +46 -10
  447. package/src/server/agent-discovery.ts +2 -0
  448. package/src/server/builder-design-systems.ts +21 -0
  449. package/src/server/credential-provider.ts +51 -12
  450. package/src/server/index.ts +1 -0
  451. package/src/server/onboarding-html.ts +37 -2
  452. package/src/shared/reasoning-effort.ts +1 -1
  453. package/src/templates/chat/app/components/layout/Sidebar.tsx +30 -3
  454. package/src/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
  455. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
  456. package/corpus/templates/clips/desktop/src/lib/media-device-selection.ts +0 -157
@@ -578,6 +578,41 @@ export async function searchThreads(ownerEmail, query, limit = 50, options = {})
578
578
  .map((r) => rowToSummary(r))
579
579
  .filter((r) => r !== null);
580
580
  }
581
+ /**
582
+ * Scope a thread should carry after a run inside a resource: adopt when it has
583
+ * none, otherwise keep what it has. An unscoped thread reads as general, and a
584
+ * general chat renders inside every resource — so never retag, never clear.
585
+ */
586
+ export function resolveRunThreadScope(existing, incoming) {
587
+ if (existing)
588
+ return existing;
589
+ return incoming ?? null;
590
+ }
591
+ /**
592
+ * Claim an unscoped thread for `scope`, returning the scope it actually ends up
593
+ * with. `withThreadDataLock` only serializes one process, so two workers can
594
+ * both read the same unscoped row; the `scope_type IS NULL` guard makes the
595
+ * first writer win and the loser reports the winner instead of retagging.
596
+ */
597
+ export async function adoptThreadScopeIfUnscoped(id, scope) {
598
+ await ensureTable();
599
+ const client = getDbExec();
600
+ const result = await client.execute({
601
+ sql: `UPDATE chat_threads SET scope_type = ?, scope_id = ?, scope_label = ?, updated_at = ? WHERE id = ? AND scope_type IS NULL`,
602
+ args: [
603
+ scope.type,
604
+ scope.id,
605
+ scope.label ?? null,
606
+ Math.max(Date.now(), 1),
607
+ id,
608
+ ],
609
+ });
610
+ if (result.rowsAffected > 0) {
611
+ emitChatThreadChange(id);
612
+ return scope;
613
+ }
614
+ return (await getThread(id))?.scope ?? null;
615
+ }
581
616
  /**
582
617
  * Detach or rebind a chat's scope. Used by the UI's "Detach from <resource>"
583
618
  * action and by templates that need to retag a chat after a rename. Pass
@@ -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 // 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"]}
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 * Scope a thread should carry after a run inside a resource: adopt when it has\n * none, otherwise keep what it has. An unscoped thread reads as general, and a\n * general chat renders inside every resource — so never retag, never clear.\n */\nexport function resolveRunThreadScope(\n existing: ChatThreadScope | null,\n incoming: ChatThreadScope | null | undefined,\n): ChatThreadScope | null {\n if (existing) return existing;\n return incoming ?? null;\n}\n\n/**\n * Claim an unscoped thread for `scope`, returning the scope it actually ends up\n * with. `withThreadDataLock` only serializes one process, so two workers can\n * both read the same unscoped row; the `scope_type IS NULL` guard makes the\n * first writer win and the loser reports the winner instead of retagging.\n */\nexport async function adoptThreadScopeIfUnscoped(\n id: string,\n scope: ChatThreadScope,\n): Promise<ChatThreadScope | null> {\n await ensureTable();\n const client = getDbExec();\n const result = await client.execute({\n sql: `UPDATE chat_threads SET scope_type = ?, scope_id = ?, scope_label = ?, updated_at = ? WHERE id = ? AND scope_type IS NULL`,\n args: [\n scope.type,\n scope.id,\n scope.label ?? null,\n Math.max(Date.now(), 1),\n id,\n ],\n });\n if (result.rowsAffected > 0) {\n emitChatThreadChange(id);\n return scope;\n }\n return (await getThread(id))?.scope ?? 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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"templates-meta.d.ts","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gEAAgE;IAChE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,SAAS,EAAE,YAAY,EA4MnC,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,YAAY,EAAE,CAE9C;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAQlE;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C"}
1
+ {"version":3,"file":"templates-meta.d.ts","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gEAAgE;IAChE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,SAAS,EAAE,YAAY,EAyNnC,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,YAAY,EAAE,CAE9C;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAQlE;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C"}
@@ -218,6 +218,19 @@ export const TEMPLATES = [
218
218
  hidden: true,
219
219
  defaultMode: "dev",
220
220
  },
221
+ {
222
+ name: "factory",
223
+ label: "Factory",
224
+ hint: "Build agent factories with gates you control",
225
+ icon: "Users",
226
+ color: "#7C3AED",
227
+ colorRgb: "124 58 237",
228
+ devPort: 8108,
229
+ prodUrl: "https://agent-native-factory.netlify.app",
230
+ hidden: true,
231
+ defaultMode: "dev",
232
+ core: false,
233
+ },
221
234
  ];
222
235
  /** Return templates visible in user-facing pickers (excludes hidden). */
223
236
  export function visibleTemplates() {
@@ -1 +1 @@
1
- {"version":3,"file":"templates-meta.js","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-party template metadata used by the `agent-native` CLI.\n *\n * This file is intentionally inlined here (rather than imported from a\n * separate workspace package) so that the published `@agent-native/core`\n * has no `workspace:*` runtime dependencies. Without this inlining, `npx\n * @agent-native/core create ...` fails on a fresh machine with:\n *\n * npm error code EUNSUPPORTEDPROTOCOL\n * npm error Unsupported URL Type \"workspace:\": workspace:*\n *\n * Keep this list in sync with `packages/shared-app-config/templates.ts`,\n * which serves the same metadata to the desktop / mobile / frame packages\n * that always run inside the workspace. Duplication is intentional: the\n * CLI must remain installable outside the monorepo.\n */\n\nexport interface TemplateMeta {\n /** Directory name under templates/ and package name */\n name: string;\n /** Display name in pickers */\n label: string;\n /** One-line description shown in the picker */\n hint: string;\n /** Longer description (optional) */\n description?: string;\n /** Tabler icon name used in the desktop sidebar */\n icon: string;\n /** Hex accent color */\n color: string;\n /** CSS-safe RGB triplet (e.g. \"59 130 246\") */\n colorRgb: string;\n /** Dev server port for desktop `pnpm dev` */\n devPort: number;\n /** Production URL when running as a first-party app on agent-native.com */\n prodUrl?: string;\n /** Default URL path when deployed in a workspace (defaults to \"/<name>\") */\n prodPath?: string;\n /** Default mode when added to desktop app */\n defaultMode?: \"dev\" | \"prod\";\n /** Hide from pickers but still scaffoldable via explicit --template */\n hidden?: boolean;\n /** Include as a built-in connected A2A agent even when hidden from pickers */\n defaultAgent?: boolean;\n /** Always scaffold without prompting (e.g. chat as fallback) */\n alwaysAvailable?: boolean;\n /** Internal workspace packages this template depends on (e.g. \"scheduling\") */\n requiredPackages?: string[];\n /** Core app — featured in the CLI picker, homepage, and docs gallery */\n core?: boolean;\n}\n\nexport const TEMPLATES: TemplateMeta[] = [\n {\n name: \"calendar\",\n label: \"Calendar\",\n hint: \"Agent-native Google Calendar — manage events, sync, and public booking\",\n icon: \"CalendarDays\",\n color: \"#00B5FF\",\n colorRgb: \"0 181 255\",\n devPort: 8082,\n prodUrl: \"https://calendar.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"scheduling\"],\n core: true,\n },\n {\n name: \"content\",\n label: \"Content\",\n hint: \"Open-source Obsidian for MDX — edit local docs with agent assistance\",\n icon: \"FileText\",\n color: \"#10B981\",\n colorRgb: \"16 185 129\",\n devPort: 8083,\n prodUrl: \"https://content.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"creative-context\"],\n core: true,\n },\n {\n name: \"plan\",\n label: \"Plan\",\n hint: \"Structured visual plans and PR recaps with diagrams, wireframes, prototypes, annotations, and sharing\",\n icon: \"FileText\",\n color: \"#52525B\",\n colorRgb: \"82 82 91\",\n devPort: 8105,\n prodUrl: \"https://plan.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"slides\",\n label: \"Slides\",\n hint: \"Agent-native Google Slides — generate and edit React presentations\",\n icon: \"GalleryHorizontal\",\n color: \"#EC4899\",\n colorRgb: \"236 72 153\",\n devPort: 8086,\n prodUrl: \"https://slides.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"creative-context\"],\n core: true,\n },\n {\n name: \"analytics\",\n label: \"Analytics\",\n hint: \"Agent-native Amplitude/Mixpanel — connect data sources, prompt for charts\",\n icon: \"BarChart2\",\n color: \"#F59E0B\",\n colorRgb: \"245 158 11\",\n devPort: 8088,\n prodUrl: \"https://analytics.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"creative-context\"],\n core: true,\n },\n {\n name: \"mail\",\n label: \"Mail\",\n hint: \"Agent-native Superhuman — email client with keyboard shortcuts and AI triage\",\n icon: \"Mail\",\n color: \"#3B82F6\",\n colorRgb: \"59 130 246\",\n devPort: 8085,\n prodUrl: \"https://mail.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"dispatch\",\n label: \"Dispatch\",\n hint: \"Central Slack/Telegram router with jobs, memory, approvals, and A2A delegation\",\n icon: \"MessageCircle\",\n color: \"#14B8A6\",\n colorRgb: \"20 184 166\",\n devPort: 8092,\n prodUrl: \"https://dispatch.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"forms\",\n label: \"Forms\",\n hint: \"Agent-native form builder — create, edit, and manage forms\",\n icon: \"ClipboardList\",\n color: \"#06B6D4\",\n colorRgb: \"6 182 212\",\n devPort: 8084,\n prodUrl: \"https://forms.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"chat\",\n label: \"Chat\",\n hint: \"Minimal chat-first app with durable threads, actions, and the app-agent loop\",\n icon: \"MessageCircle\",\n color: \"#18181B\",\n colorRgb: \"24 24 27\",\n devPort: 8089,\n prodUrl: \"https://chat.agent-native.com\",\n defaultMode: \"prod\",\n alwaysAvailable: true,\n core: true,\n },\n {\n name: \"clips\",\n label: \"Clips\",\n hint: \"Screen recording, meeting notes, and voice dictation — all with AI\",\n icon: \"ScreenShare\",\n color: \"#0EA5E9\",\n colorRgb: \"14 165 233\",\n devPort: 8094,\n prodUrl: \"https://clips.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"brain\",\n label: \"Brain\",\n hint: \"Cited company knowledge from Slack, meetings, transcripts, and decisions\",\n icon: \"Brain\",\n color: \"#8B5CF6\",\n colorRgb: \"139 92 246\",\n devPort: 8102,\n prodUrl: \"https://brain.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n core: true,\n },\n {\n name: \"design\",\n label: \"Design\",\n hint: \"Agent-native design tool — create and edit visual designs with agent assistance\",\n icon: \"Brush\",\n color: \"#F472B6\",\n colorRgb: \"244 114 182\",\n devPort: 8099,\n prodUrl: \"https://design.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"embedding\", \"creative-context\"],\n core: true,\n },\n {\n name: \"assets\",\n label: \"Assets\",\n hint: \"Digital asset manager — upload, organize, search, and generate on-brand images and videos\",\n icon: \"Photo\",\n color: \"#0F766E\",\n colorRgb: \"15 118 110\",\n devPort: 8100,\n prodUrl: \"https://assets.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n requiredPackages: [\"embedding\", \"creative-context\"],\n core: true,\n },\n {\n name: \"tasks\",\n label: \"Tasks\",\n hint: \"Task-list-first workspace — inbox capture, custom fields, and drag-and-drop ordering\",\n icon: \"ListCheck\",\n color: \"#6366F1\",\n colorRgb: \"99 102 241\",\n devPort: 8091,\n prodUrl: \"https://tasks.agent-native.com\",\n defaultMode: \"prod\",\n hidden: true,\n core: false,\n },\n {\n name: \"crm\",\n label: \"CRM\",\n hint: \"Agent-native CRM over native SQL, HubSpot, or Salesforce — typed attributes, lists, pipelines, and evidence-grounded signals\",\n icon: \"Users\",\n color: \"#2563EB\",\n colorRgb: \"37 99 235\",\n devPort: 8107,\n prodUrl: \"https://crm.agent-native.com\",\n hidden: true,\n defaultMode: \"dev\",\n core: false,\n },\n {\n name: \"macros\",\n label: \"Macros\",\n hint: \"Internal template — not shown in pickers\",\n icon: \"Code\",\n color: \"#71717A\",\n colorRgb: \"113 113 122\",\n devPort: 8093,\n prodUrl: \"https://macros.agent-native.com\",\n hidden: true,\n defaultMode: \"dev\",\n },\n];\n\n/** Return templates visible in user-facing pickers (excludes hidden). */\nexport function visibleTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => !t.hidden);\n}\n\n/** Return core templates — the featured set shown in CLI pickers by default. */\nexport function coreTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => t.core);\n}\n\n/** Lookup by name. Returns undefined for unknown names. */\nexport function getTemplate(name: string): TemplateMeta | undefined {\n // Tolerate legacy / renamed aliases.\n if (name === \"starter\") name = \"chat\";\n if (name === \"image\" || name === \"images\" || name === \"asset\") {\n name = \"assets\";\n }\n if (name === \"contracts\" || name === \"visual-plans\") name = \"plan\";\n return TEMPLATES.find((t) => t.name === name);\n}\n\n/** Names of all templates (including hidden) for validation. */\nexport function allTemplateNames(): string[] {\n return TEMPLATES.map((t) => t.name);\n}\n"]}
1
+ {"version":3,"file":"templates-meta.js","sourceRoot":"","sources":["../../src/cli/templates-meta.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First-party template metadata used by the `agent-native` CLI.\n *\n * This file is intentionally inlined here (rather than imported from a\n * separate workspace package) so that the published `@agent-native/core`\n * has no `workspace:*` runtime dependencies. Without this inlining, `npx\n * @agent-native/core create ...` fails on a fresh machine with:\n *\n * npm error code EUNSUPPORTEDPROTOCOL\n * npm error Unsupported URL Type \"workspace:\": workspace:*\n *\n * Keep this list in sync with `packages/shared-app-config/templates.ts`,\n * which serves the same metadata to the desktop / mobile / frame packages\n * that always run inside the workspace. Duplication is intentional: the\n * CLI must remain installable outside the monorepo.\n */\n\nexport interface TemplateMeta {\n /** Directory name under templates/ and package name */\n name: string;\n /** Display name in pickers */\n label: string;\n /** One-line description shown in the picker */\n hint: string;\n /** Longer description (optional) */\n description?: string;\n /** Tabler icon name used in the desktop sidebar */\n icon: string;\n /** Hex accent color */\n color: string;\n /** CSS-safe RGB triplet (e.g. \"59 130 246\") */\n colorRgb: string;\n /** Dev server port for desktop `pnpm dev` */\n devPort: number;\n /** Production URL when running as a first-party app on agent-native.com */\n prodUrl?: string;\n /** Default URL path when deployed in a workspace (defaults to \"/<name>\") */\n prodPath?: string;\n /** Default mode when added to desktop app */\n defaultMode?: \"dev\" | \"prod\";\n /** Hide from pickers but still scaffoldable via explicit --template */\n hidden?: boolean;\n /** Include as a built-in connected A2A agent even when hidden from pickers */\n defaultAgent?: boolean;\n /** Always scaffold without prompting (e.g. chat as fallback) */\n alwaysAvailable?: boolean;\n /** Internal workspace packages this template depends on (e.g. \"scheduling\") */\n requiredPackages?: string[];\n /** Core app — featured in the CLI picker, homepage, and docs gallery */\n core?: boolean;\n}\n\nexport const TEMPLATES: TemplateMeta[] = [\n {\n name: \"calendar\",\n label: \"Calendar\",\n hint: \"Agent-native Google Calendar — manage events, sync, and public booking\",\n icon: \"CalendarDays\",\n color: \"#00B5FF\",\n colorRgb: \"0 181 255\",\n devPort: 8082,\n prodUrl: \"https://calendar.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"scheduling\"],\n core: true,\n },\n {\n name: \"content\",\n label: \"Content\",\n hint: \"Open-source Obsidian for MDX — edit local docs with agent assistance\",\n icon: \"FileText\",\n color: \"#10B981\",\n colorRgb: \"16 185 129\",\n devPort: 8083,\n prodUrl: \"https://content.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"creative-context\"],\n core: true,\n },\n {\n name: \"plan\",\n label: \"Plan\",\n hint: \"Structured visual plans and PR recaps with diagrams, wireframes, prototypes, annotations, and sharing\",\n icon: \"FileText\",\n color: \"#52525B\",\n colorRgb: \"82 82 91\",\n devPort: 8105,\n prodUrl: \"https://plan.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"slides\",\n label: \"Slides\",\n hint: \"Agent-native Google Slides — generate and edit React presentations\",\n icon: \"GalleryHorizontal\",\n color: \"#EC4899\",\n colorRgb: \"236 72 153\",\n devPort: 8086,\n prodUrl: \"https://slides.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"creative-context\"],\n core: true,\n },\n {\n name: \"analytics\",\n label: \"Analytics\",\n hint: \"Agent-native Amplitude/Mixpanel — connect data sources, prompt for charts\",\n icon: \"BarChart2\",\n color: \"#F59E0B\",\n colorRgb: \"245 158 11\",\n devPort: 8088,\n prodUrl: \"https://analytics.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"creative-context\"],\n core: true,\n },\n {\n name: \"mail\",\n label: \"Mail\",\n hint: \"Agent-native Superhuman — email client with keyboard shortcuts and AI triage\",\n icon: \"Mail\",\n color: \"#3B82F6\",\n colorRgb: \"59 130 246\",\n devPort: 8085,\n prodUrl: \"https://mail.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"dispatch\",\n label: \"Dispatch\",\n hint: \"Central Slack/Telegram router with jobs, memory, approvals, and A2A delegation\",\n icon: \"MessageCircle\",\n color: \"#14B8A6\",\n colorRgb: \"20 184 166\",\n devPort: 8092,\n prodUrl: \"https://dispatch.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"forms\",\n label: \"Forms\",\n hint: \"Agent-native form builder — create, edit, and manage forms\",\n icon: \"ClipboardList\",\n color: \"#06B6D4\",\n colorRgb: \"6 182 212\",\n devPort: 8084,\n prodUrl: \"https://forms.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"chat\",\n label: \"Chat\",\n hint: \"Minimal chat-first app with durable threads, actions, and the app-agent loop\",\n icon: \"MessageCircle\",\n color: \"#18181B\",\n colorRgb: \"24 24 27\",\n devPort: 8089,\n prodUrl: \"https://chat.agent-native.com\",\n defaultMode: \"prod\",\n alwaysAvailable: true,\n core: true,\n },\n {\n name: \"clips\",\n label: \"Clips\",\n hint: \"Screen recording, meeting notes, and voice dictation — all with AI\",\n icon: \"ScreenShare\",\n color: \"#0EA5E9\",\n colorRgb: \"14 165 233\",\n devPort: 8094,\n prodUrl: \"https://clips.agent-native.com\",\n defaultMode: \"prod\",\n core: true,\n },\n {\n name: \"brain\",\n label: \"Brain\",\n hint: \"Cited company knowledge from Slack, meetings, transcripts, and decisions\",\n icon: \"Brain\",\n color: \"#8B5CF6\",\n colorRgb: \"139 92 246\",\n devPort: 8102,\n prodUrl: \"https://brain.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n core: true,\n },\n {\n name: \"design\",\n label: \"Design\",\n hint: \"Agent-native design tool — create and edit visual designs with agent assistance\",\n icon: \"Brush\",\n color: \"#F472B6\",\n colorRgb: \"244 114 182\",\n devPort: 8099,\n prodUrl: \"https://design.agent-native.com\",\n defaultMode: \"prod\",\n requiredPackages: [\"embedding\", \"creative-context\"],\n core: true,\n },\n {\n name: \"assets\",\n label: \"Assets\",\n hint: \"Digital asset manager — upload, organize, search, and generate on-brand images and videos\",\n icon: \"Photo\",\n color: \"#0F766E\",\n colorRgb: \"15 118 110\",\n devPort: 8100,\n prodUrl: \"https://assets.agent-native.com\",\n defaultMode: \"prod\",\n defaultAgent: true,\n requiredPackages: [\"embedding\", \"creative-context\"],\n core: true,\n },\n {\n name: \"tasks\",\n label: \"Tasks\",\n hint: \"Task-list-first workspace — inbox capture, custom fields, and drag-and-drop ordering\",\n icon: \"ListCheck\",\n color: \"#6366F1\",\n colorRgb: \"99 102 241\",\n devPort: 8091,\n prodUrl: \"https://tasks.agent-native.com\",\n defaultMode: \"prod\",\n hidden: true,\n core: false,\n },\n {\n name: \"crm\",\n label: \"CRM\",\n hint: \"Agent-native CRM over native SQL, HubSpot, or Salesforce — typed attributes, lists, pipelines, and evidence-grounded signals\",\n icon: \"Users\",\n color: \"#2563EB\",\n colorRgb: \"37 99 235\",\n devPort: 8107,\n prodUrl: \"https://crm.agent-native.com\",\n hidden: true,\n defaultMode: \"dev\",\n core: false,\n },\n {\n name: \"macros\",\n label: \"Macros\",\n hint: \"Internal template — not shown in pickers\",\n icon: \"Code\",\n color: \"#71717A\",\n colorRgb: \"113 113 122\",\n devPort: 8093,\n prodUrl: \"https://macros.agent-native.com\",\n hidden: true,\n defaultMode: \"dev\",\n },\n {\n name: \"factory\",\n label: \"Factory\",\n hint: \"Build agent factories with gates you control\",\n icon: \"Users\",\n color: \"#7C3AED\",\n colorRgb: \"124 58 237\",\n devPort: 8108,\n prodUrl: \"https://agent-native-factory.netlify.app\",\n hidden: true,\n defaultMode: \"dev\",\n core: false,\n },\n];\n\n/** Return templates visible in user-facing pickers (excludes hidden). */\nexport function visibleTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => !t.hidden);\n}\n\n/** Return core templates — the featured set shown in CLI pickers by default. */\nexport function coreTemplates(): TemplateMeta[] {\n return TEMPLATES.filter((t) => t.core);\n}\n\n/** Lookup by name. Returns undefined for unknown names. */\nexport function getTemplate(name: string): TemplateMeta | undefined {\n // Tolerate legacy / renamed aliases.\n if (name === \"starter\") name = \"chat\";\n if (name === \"image\" || name === \"images\" || name === \"asset\") {\n name = \"assets\";\n }\n if (name === \"contracts\" || name === \"visual-plans\") name = \"plan\";\n return TEMPLATES.find((t) => t.name === name);\n}\n\n/** Names of all templates (including hidden) for validation. */\nexport function allTemplateNames(): string[] {\n return TEMPLATES.map((t) => t.name);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-dev.d.ts","sourceRoot":"","sources":["../../src/cli/workspace-dev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace-dev.d.ts","sourceRoot":"","sources":["../../src/cli/workspace-dev.ts"],"names":[],"mappings":"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"}
@@ -535,6 +535,7 @@ export async function runWorkspaceDev(options = {}) {
535
535
  name: workspaceApp.name,
536
536
  description: workspaceApp.description,
537
537
  path: `/${workspaceApp.id}`,
538
+ port: workspaceApp.port,
538
539
  audience: workspaceApp.audience,
539
540
  publicPaths: workspaceApp.publicPaths,
540
541
  protectedPaths: workspaceApp.protectedPaths,