@agent-native/core 0.149.1 → 0.149.3

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 (422) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +54 -488
  3. package/corpus/templates/analytics/.agents/skills/actions/references/action-fields.md +136 -0
  4. package/corpus/templates/analytics/.agents/skills/actions/references/examples.md +94 -0
  5. package/corpus/templates/analytics/.agents/skills/actions/references/provider-apis.md +95 -0
  6. package/corpus/templates/analytics/.agents/skills/create-skill/SKILL.md +9 -35
  7. package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +4 -2
  8. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +2 -0
  9. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +4 -5
  10. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -31
  11. package/corpus/templates/analytics/AGENTS.md +25 -32
  12. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +150 -46
  13. package/corpus/templates/analytics/app/global.css +1 -1
  14. package/corpus/templates/analytics/app/i18n-data.ts +37 -0
  15. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
  16. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -0
  17. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -0
  18. package/corpus/templates/analytics/changelog/2026-08-10-dashboard-tables-can-be-copied-and-sorted-by-multiple-column.md +6 -0
  19. package/corpus/templates/analytics/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  20. package/corpus/templates/analytics/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  21. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +54 -488
  22. package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +136 -0
  23. package/corpus/templates/assets/.agents/skills/actions/references/examples.md +94 -0
  24. package/corpus/templates/assets/.agents/skills/actions/references/provider-apis.md +95 -0
  25. package/corpus/templates/assets/.agents/skills/create-skill/SKILL.md +9 -35
  26. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +4 -2
  27. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +4 -5
  28. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -31
  29. package/corpus/templates/assets/AGENTS.md +6 -9
  30. package/corpus/templates/assets/app/global.css +1 -1
  31. package/corpus/templates/assets/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  32. package/corpus/templates/assets/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  33. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +54 -488
  34. package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +136 -0
  35. package/corpus/templates/brain/.agents/skills/actions/references/examples.md +94 -0
  36. package/corpus/templates/brain/.agents/skills/actions/references/provider-apis.md +95 -0
  37. package/corpus/templates/brain/.agents/skills/create-skill/SKILL.md +9 -35
  38. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +4 -5
  39. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -31
  40. package/corpus/templates/brain/AGENTS.md +5 -12
  41. package/corpus/templates/brain/app/global.css +1 -1
  42. package/corpus/templates/brain/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  43. package/corpus/templates/brain/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  44. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +54 -488
  45. package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +136 -0
  46. package/corpus/templates/calendar/.agents/skills/actions/references/examples.md +94 -0
  47. package/corpus/templates/calendar/.agents/skills/actions/references/provider-apis.md +95 -0
  48. package/corpus/templates/calendar/.agents/skills/create-skill/SKILL.md +9 -35
  49. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +4 -5
  50. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -31
  51. package/corpus/templates/calendar/AGENTS.md +8 -9
  52. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +54 -488
  53. package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
  54. package/corpus/templates/chat/.agents/skills/actions/references/examples.md +94 -0
  55. package/corpus/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
  56. package/corpus/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
  57. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
  58. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
  59. package/corpus/templates/chat/AGENTS.md +32 -80
  60. package/corpus/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  61. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +54 -488
  62. package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +136 -0
  63. package/corpus/templates/clips/.agents/skills/actions/references/examples.md +94 -0
  64. package/corpus/templates/clips/.agents/skills/actions/references/provider-apis.md +95 -0
  65. package/corpus/templates/clips/.agents/skills/create-skill/SKILL.md +9 -35
  66. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +4 -5
  67. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -31
  68. package/corpus/templates/clips/AGENTS.md +25 -31
  69. package/corpus/templates/clips/changelog/2026-08-10-clips-desktop-sign-in-now-starts-with-magic-links-and-google.md +6 -0
  70. package/corpus/templates/clips/chrome-extension/src/overlay.css +1 -0
  71. package/corpus/templates/clips/desktop/src/app.tsx +274 -137
  72. package/corpus/templates/clips/desktop/src/styles.css +35 -0
  73. package/corpus/templates/content/.agents/skills/actions/SKILL.md +54 -488
  74. package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +136 -0
  75. package/corpus/templates/content/.agents/skills/actions/references/examples.md +94 -0
  76. package/corpus/templates/content/.agents/skills/actions/references/provider-apis.md +95 -0
  77. package/corpus/templates/content/.agents/skills/create-skill/SKILL.md +9 -35
  78. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +4 -2
  79. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +4 -5
  80. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -31
  81. package/corpus/templates/content/AGENTS.md +5 -9
  82. package/corpus/templates/content/app/global.css +1 -0
  83. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -31
  84. package/corpus/templates/crm/AGENTS.md +7 -11
  85. package/corpus/templates/crm/app/global.css +1 -1
  86. package/corpus/templates/crm/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  87. package/corpus/templates/crm/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  88. package/corpus/templates/design/.agents/skills/actions/SKILL.md +54 -488
  89. package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +136 -0
  90. package/corpus/templates/design/.agents/skills/actions/references/examples.md +94 -0
  91. package/corpus/templates/design/.agents/skills/actions/references/provider-apis.md +95 -0
  92. package/corpus/templates/design/.agents/skills/create-skill/SKILL.md +9 -35
  93. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +4 -2
  94. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +4 -5
  95. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -31
  96. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +70 -3
  97. package/corpus/templates/design/AGENTS.md +13 -21
  98. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -0
  99. package/corpus/templates/design/app/components/design/LayersPanel.tsx +19 -2
  100. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +115 -7
  101. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +82 -7
  102. package/corpus/templates/design/app/components/design/design-trace.ts +120 -0
  103. package/corpus/templates/design/app/components/design/dnd-debug.ts +2 -1
  104. package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +40 -26
  105. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -1
  106. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +12 -3
  107. package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +4 -0
  108. package/corpus/templates/design/app/components/design/multi-screen/types.ts +7 -0
  109. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -2
  110. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
  111. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -0
  112. package/corpus/templates/design/app/i18n-data.ts +1 -0
  113. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -5
  114. package/corpus/templates/design/app/pages/DesignSystems.tsx +3 -2
  115. package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +100 -13
  116. package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +1 -1
  117. package/corpus/templates/design/app/pages/design-editor/data-operations.ts +14 -0
  118. package/corpus/templates/design/changelog/2026-08-10-marquee-selecting-layers-far-down-a-tall-screen-now-selects-.md +6 -0
  119. package/corpus/templates/design/changelog/2026-08-10-the-frame-tool-draws-a-plain-frame-by-default-with-screen-av.md +6 -0
  120. package/corpus/templates/design/e2e/global-setup.ts +27 -32
  121. package/corpus/templates/design/playwright.config.ts +3 -5
  122. package/corpus/templates/design/shared/breakpoint-media.ts +9 -2
  123. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +54 -488
  124. package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +136 -0
  125. package/corpus/templates/dispatch/.agents/skills/actions/references/examples.md +94 -0
  126. package/corpus/templates/dispatch/.agents/skills/actions/references/provider-apis.md +95 -0
  127. package/corpus/templates/dispatch/.agents/skills/create-skill/SKILL.md +9 -35
  128. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +4 -5
  129. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -31
  130. package/corpus/templates/dispatch/AGENTS.md +9 -16
  131. package/corpus/templates/dispatch/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  132. package/corpus/templates/factory/.agents/skills/actions/SKILL.md +54 -488
  133. package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +136 -0
  134. package/corpus/templates/factory/.agents/skills/actions/references/examples.md +94 -0
  135. package/corpus/templates/factory/.agents/skills/actions/references/provider-apis.md +95 -0
  136. package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +9 -35
  137. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +4 -5
  138. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -31
  139. package/corpus/templates/factory/AGENTS.md +10 -24
  140. package/corpus/templates/factory/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  141. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +54 -488
  142. package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +136 -0
  143. package/corpus/templates/forms/.agents/skills/actions/references/examples.md +94 -0
  144. package/corpus/templates/forms/.agents/skills/actions/references/provider-apis.md +95 -0
  145. package/corpus/templates/forms/.agents/skills/create-skill/SKILL.md +9 -35
  146. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +4 -5
  147. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -31
  148. package/corpus/templates/forms/AGENTS.md +11 -17
  149. package/corpus/templates/forms/app/global.css +1 -0
  150. package/corpus/templates/forms/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  151. package/corpus/templates/forms/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  152. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +4 -5
  153. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -31
  154. package/corpus/templates/macros/AGENTS.md +8 -8
  155. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +54 -488
  156. package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +136 -0
  157. package/corpus/templates/mail/.agents/skills/actions/references/examples.md +94 -0
  158. package/corpus/templates/mail/.agents/skills/actions/references/provider-apis.md +95 -0
  159. package/corpus/templates/mail/.agents/skills/create-skill/SKILL.md +9 -35
  160. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +4 -5
  161. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -31
  162. package/corpus/templates/mail/AGENTS.md +5 -6
  163. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +54 -488
  164. package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +136 -0
  165. package/corpus/templates/plan/.agents/skills/actions/references/examples.md +94 -0
  166. package/corpus/templates/plan/.agents/skills/actions/references/provider-apis.md +95 -0
  167. package/corpus/templates/plan/.agents/skills/create-skill/SKILL.md +9 -35
  168. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +4 -5
  169. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -31
  170. package/corpus/templates/plan/AGENTS.md +5 -14
  171. package/corpus/templates/plan/app/global.css +1 -0
  172. package/corpus/templates/plan/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  173. package/corpus/templates/plan/changelog/2026-08-11-plan-no-longer-reloads-when-runtime-state-changes.md +6 -0
  174. package/corpus/templates/plan/server/ui-plan-html.ts +4 -1
  175. package/corpus/templates/plan/vite.config.ts +5 -0
  176. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +54 -488
  177. package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +136 -0
  178. package/corpus/templates/slides/.agents/skills/actions/references/examples.md +94 -0
  179. package/corpus/templates/slides/.agents/skills/actions/references/provider-apis.md +95 -0
  180. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -2
  181. package/corpus/templates/slides/.agents/skills/create-skill/SKILL.md +9 -35
  182. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +6 -3
  183. package/corpus/templates/slides/.agents/skills/deck-management/SKILL.md +6 -1
  184. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +4 -5
  185. package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +3 -2
  186. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +3 -0
  187. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +3 -3
  188. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -31
  189. package/corpus/templates/slides/AGENTS.md +33 -35
  190. package/corpus/templates/slides/actions/add-deck.ts +2 -0
  191. package/corpus/templates/slides/actions/add-slide.ts +15 -1
  192. package/corpus/templates/slides/actions/create-deck.ts +18 -6
  193. package/corpus/templates/slides/actions/get-deck-reference-context.ts +2 -2
  194. package/corpus/templates/slides/actions/get-deck.ts +83 -7
  195. package/corpus/templates/slides/actions/import-file.ts +2 -1
  196. package/corpus/templates/slides/actions/patch-deck.ts +165 -9
  197. package/corpus/templates/slides/actions/save-deck.ts +24 -1
  198. package/corpus/templates/slides/actions/update-slide.ts +1 -1
  199. package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +2 -2
  200. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -23
  201. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +2 -2
  202. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +6 -6
  203. package/corpus/templates/slides/app/components/editor/AnimationsPanel.tsx +3 -3
  204. package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +4 -4
  205. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +1 -1
  206. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +432 -668
  207. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +296 -259
  208. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -1
  209. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +13 -1
  210. package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +56 -174
  211. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +241 -116
  212. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
  213. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +42 -14
  214. package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +6 -12
  215. package/corpus/templates/slides/app/components/editor/editor-command-model.ts +35 -0
  216. package/corpus/templates/slides/app/components/layout/AgentWorkIndicator.tsx +1 -1
  217. package/corpus/templates/slides/app/components/layout/Layout.tsx +34 -35
  218. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +8 -10
  219. package/corpus/templates/slides/app/components/layout/layout-route-policy.ts +2 -5
  220. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +45 -40
  221. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +63 -16
  222. package/corpus/templates/slides/app/context/DeckContext.tsx +2 -1
  223. package/corpus/templates/slides/app/global.css +76 -1
  224. package/corpus/templates/slides/app/hooks/use-generating-slide-preview.ts +25 -3
  225. package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
  226. package/corpus/templates/slides/app/lib/create-deck-generation.ts +52 -23
  227. package/corpus/templates/slides/app/lib/recent-references.ts +23 -1
  228. package/corpus/templates/slides/app/lib/slide-animation-elements.ts +104 -3
  229. package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -33
  230. package/corpus/templates/slides/app/pages/DesignSystems.tsx +2 -2
  231. package/corpus/templates/slides/app/pages/Index.tsx +315 -151
  232. package/corpus/templates/slides/app/root.tsx +43 -0
  233. package/corpus/templates/slides/changelog/2026-08-10-ai-editing-avatar-badge.md +6 -0
  234. package/corpus/templates/slides/changelog/2026-08-10-generated-decks-keep-a-clear-human-readable-title.md +6 -0
  235. package/corpus/templates/slides/changelog/2026-08-10-new-deck-creation-now-shows-progress-opens-the-editor-direct.md +6 -0
  236. package/corpus/templates/slides/changelog/2026-08-10-presentation-reveals-now-follow-valid-targets.md +6 -0
  237. package/corpus/templates/slides/changelog/2026-08-10-slides-editing-controls-are-consolidated-into-one-focused-me.md +6 -0
  238. package/corpus/templates/slides/changelog/2026-08-10-slides-now-verify-and-restyle-every-imported-slide-in-one-pa.md +6 -0
  239. package/corpus/templates/slides/changelog/2026-08-10-slides-only-suggests-a-google-connection-for-relevant-reques.md +6 -0
  240. package/corpus/templates/slides/changelog/2026-08-10-the-google-slides-import-option-is-now-labeled-slides.md +6 -0
  241. package/corpus/templates/slides/changelog/2026-08-11-faster-slides-chat-deck-reads.md +6 -0
  242. package/corpus/templates/slides/changelog/2026-08-11-slides-chat-can-read-one-slide-without-loading-the-full-deck.md +6 -0
  243. package/corpus/templates/slides/changelog/2026-08-11-slides-clearly-indicate-when-an-ai-agent-is-editing-alongsid.md +6 -0
  244. package/corpus/templates/slides/package.json +1 -0
  245. package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
  246. package/corpus/templates/slides/server/lib/validate-slide-animations.ts +163 -0
  247. package/corpus/templates/slides/server/plugins/agent-chat.ts +8 -5
  248. package/corpus/templates/slides/shared/api.ts +47 -15
  249. package/corpus/templates/slides/shared/deck-title.ts +135 -0
  250. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +54 -488
  251. package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +136 -0
  252. package/corpus/templates/tasks/.agents/skills/actions/references/examples.md +94 -0
  253. package/corpus/templates/tasks/.agents/skills/actions/references/provider-apis.md +95 -0
  254. package/corpus/templates/tasks/.agents/skills/agent-watchdog/SKILL.md +1 -0
  255. package/corpus/templates/tasks/.agents/skills/create-skill/SKILL.md +9 -35
  256. package/corpus/templates/tasks/.agents/skills/efficient-fable/SKILL.md +1 -0
  257. package/corpus/templates/tasks/.agents/skills/efficient-frontier/SKILL.md +1 -0
  258. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +4 -5
  259. package/corpus/templates/tasks/.agents/skills/plan-arbiter/SKILL.md +1 -0
  260. package/corpus/templates/tasks/.agents/skills/plow-ahead/SKILL.md +1 -0
  261. package/corpus/templates/tasks/.agents/skills/quick-recap/SKILL.md +1 -0
  262. package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/SKILL.md +1 -0
  263. package/corpus/templates/tasks/.agents/skills/stay-within-limits/SKILL.md +1 -0
  264. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -31
  265. package/corpus/templates/tasks/AGENTS.md +5 -20
  266. package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +4 -1
  267. package/dist/agent/engine/ai-sdk-engine.js +1 -1
  268. package/dist/agent/production-agent.d.ts +21 -1
  269. package/dist/agent/production-agent.js +505 -355
  270. package/dist/agent/run-manager.js +156 -14
  271. package/dist/agent/run-store.d.ts +11 -10
  272. package/dist/agent/run-store.js +17 -13
  273. package/dist/agent/tool-approval-store.d.ts +18 -0
  274. package/dist/agent/tool-approval-store.js +122 -0
  275. package/dist/agent/types.d.ts +1 -1
  276. package/dist/cli/code-agent-executor.js +11 -2
  277. package/dist/client/AgentPanel.js +31 -6
  278. package/dist/client/AssistantChat.d.ts +9 -4
  279. package/dist/client/AssistantChat.js +221 -149
  280. package/dist/client/active-run-state.d.ts +9 -1
  281. package/dist/client/active-run-state.js +34 -3
  282. package/dist/client/agent-chat/index.d.ts +1 -1
  283. package/dist/client/agent-chat-adapter.d.ts +8 -0
  284. package/dist/client/agent-chat-adapter.js +125 -28
  285. package/dist/client/agent-chat.d.ts +1 -1
  286. package/dist/client/chat/markdown-renderer.js +14 -2
  287. package/dist/client/chat/message-components.d.ts +13 -3
  288. package/dist/client/chat/message-components.js +57 -52
  289. package/dist/client/chat/run-recovery.d.ts +1 -0
  290. package/dist/client/chat/run-recovery.js +8 -0
  291. package/dist/client/chat/tool-call-display.d.ts +5 -5
  292. package/dist/client/chat/tool-call-display.js +9 -212
  293. package/dist/client/chat-first/apps-rail.js +3 -3
  294. package/dist/client/chat-first/browser-pane.js +4 -1
  295. package/dist/client/chat-first/chat-history.d.ts +3 -1
  296. package/dist/client/chat-first/chat-history.js +7 -4
  297. package/dist/client/chat-first/surface-tabs.d.ts +1 -1
  298. package/dist/client/chat-first/surface-tabs.js +52 -41
  299. package/dist/client/chat-first/types.d.ts +3 -0
  300. package/dist/client/chat-first.d.ts +10 -0
  301. package/dist/client/chat-first.js +37 -2
  302. package/dist/client/components/ui/message-scroller.js +4 -1
  303. package/dist/client/i18n.js +3 -1
  304. package/dist/client/resources/McpConnectionSuggestion.js +9 -1
  305. package/dist/client/sse-event-processor.d.ts +4 -2
  306. package/dist/client/sse-event-processor.js +46 -6
  307. package/dist/client/use-chat-models.js +156 -80
  308. package/dist/client/use-run-stuck-detection.d.ts +2 -0
  309. package/dist/client/use-run-stuck-detection.js +85 -9
  310. package/dist/collab/awareness.d.ts +2 -2
  311. package/dist/collab/routes.d.ts +1 -1
  312. package/dist/collab/struct-routes.d.ts +1 -1
  313. package/dist/integrations/adapters/slack.d.ts +0 -4
  314. package/dist/integrations/adapters/slack.js +6 -30
  315. package/dist/integrations/catalog.js +1 -1
  316. package/dist/integrations/pending-tasks-store.d.ts +0 -8
  317. package/dist/integrations/pending-tasks-store.js +0 -21
  318. package/dist/integrations/slack-manifest.d.ts +2 -2
  319. package/dist/integrations/slack-manifest.js +0 -3
  320. package/dist/integrations/webhook-handler.js +1 -1
  321. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  322. package/dist/observability/routes.d.ts +3 -3
  323. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  324. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  325. package/dist/scripts/docs/source-search.js +2 -2
  326. package/dist/server/agent-chat/framework-prompts.js +7 -2
  327. package/dist/server/agent-chat/prompt-resources.js +2 -2
  328. package/dist/server/agent-chat/skill-frontmatter.d.ts +31 -2
  329. package/dist/server/agent-chat/skill-frontmatter.js +41 -15
  330. package/dist/server/agent-chat-plugin.js +3 -3
  331. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  332. package/dist/server/agents-bundle.d.ts +16 -19
  333. package/dist/server/agents-bundle.js +19 -35
  334. package/dist/server/auth.js +262 -31
  335. package/dist/server/better-auth-instance.d.ts +1 -0
  336. package/dist/server/better-auth-instance.js +17 -2
  337. package/dist/server/onboarding-html.js +56 -9
  338. package/dist/server/prompts/framework-core-compact.d.ts +6 -1
  339. package/dist/server/prompts/framework-core-compact.js +12 -9
  340. package/dist/server/prompts/framework-core.d.ts +6 -1
  341. package/dist/server/prompts/framework-core.js +11 -9
  342. package/dist/server/prompts/index.d.ts +1 -1
  343. package/dist/server/prompts/index.js +1 -1
  344. package/dist/server/prompts/shared-rules.d.ts +15 -11
  345. package/dist/server/prompts/shared-rules.js +17 -13
  346. package/dist/server/realtime-token.d.ts +1 -1
  347. package/dist/server/transcribe-voice.d.ts +1 -1
  348. package/dist/shared/reasoning-effort.d.ts +8 -8
  349. package/dist/shared/reasoning-effort.js +10 -10
  350. package/dist/shared/streaming-text-smoothing.js +41 -11
  351. package/dist/styles/agent-native.css +19 -32
  352. package/dist/templates/chat/.agents/skills/actions/SKILL.md +54 -488
  353. package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
  354. package/dist/templates/chat/.agents/skills/actions/references/examples.md +94 -0
  355. package/dist/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
  356. package/dist/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
  357. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
  358. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
  359. package/dist/templates/chat/AGENTS.md +32 -80
  360. package/dist/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  361. package/dist/templates/default/.agents/skills/actions/SKILL.md +54 -488
  362. package/dist/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
  363. package/dist/templates/default/.agents/skills/actions/references/examples.md +94 -0
  364. package/dist/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
  365. package/dist/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
  366. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
  367. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
  368. package/dist/templates/headless/.agents/skills/actions/SKILL.md +54 -488
  369. package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
  370. package/dist/templates/headless/.agents/skills/actions/references/examples.md +94 -0
  371. package/dist/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
  372. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
  373. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
  374. package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
  375. package/dist/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
  376. package/dist/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
  377. package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
  378. package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
  379. package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
  380. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
  381. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
  382. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
  383. package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
  384. package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
  385. package/dist/templates/workspace-core/AGENTS.md +7 -16
  386. package/docs/content/messaging.mdx +6 -7
  387. package/docs/content/template-chat.mdx +1 -1
  388. package/package.json +2 -2
  389. package/src/templates/chat/.agents/skills/actions/SKILL.md +54 -488
  390. package/src/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
  391. package/src/templates/chat/.agents/skills/actions/references/examples.md +94 -0
  392. package/src/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
  393. package/src/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
  394. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
  395. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
  396. package/src/templates/chat/AGENTS.md +32 -80
  397. package/src/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  398. package/src/templates/default/.agents/skills/actions/SKILL.md +54 -488
  399. package/src/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
  400. package/src/templates/default/.agents/skills/actions/references/examples.md +94 -0
  401. package/src/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
  402. package/src/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
  403. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
  404. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
  405. package/src/templates/headless/.agents/skills/actions/SKILL.md +54 -488
  406. package/src/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
  407. package/src/templates/headless/.agents/skills/actions/references/examples.md +94 -0
  408. package/src/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
  409. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
  410. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
  411. package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
  412. package/src/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
  413. package/src/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
  414. package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
  415. package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
  416. package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
  417. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
  418. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
  419. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
  420. package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
  421. package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
  422. package/src/templates/workspace-core/AGENTS.md +7 -16
@@ -6,6 +6,22 @@ import { fetchBuilderStatus, fetchEnvironmentStatus, } from "./client-status-req
6
6
  import { callAction } from "./use-action.js";
7
7
  const DEFAULT_STORAGE_KEY = "agent-native:chat-models:selection";
8
8
  export const CHAT_MODEL_SELECTION_CHANGED_EVENT = "agent-native:chat-model-selection-changed";
9
+ const MODEL_DISCOVERY_RETRY_DELAYS_MS = [250, 1_000];
10
+ async function fetchEngineCatalog() {
11
+ try {
12
+ const result = (await callAction("manage-agent-engine", { action: "list" }));
13
+ if (!result ||
14
+ typeof result !== "object" ||
15
+ !("engines" in result) ||
16
+ !Array.isArray(result.engines)) {
17
+ return { state: "unavailable" };
18
+ }
19
+ return { state: "available", value: result };
20
+ }
21
+ catch {
22
+ return { state: "unavailable" };
23
+ }
24
+ }
9
25
  function readPersisted(key) {
10
26
  if (!key || typeof window === "undefined")
11
27
  return {};
@@ -50,6 +66,9 @@ export function useChatModels({ storageKey = DEFAULT_STORAGE_KEY, enabled = true
50
66
  selectedEngine,
51
67
  selectedEffort,
52
68
  });
69
+ const mountedRef = useRef(true);
70
+ const refreshGenerationRef = useRef(0);
71
+ const retryTimerRef = useRef(null);
53
72
  useEffect(() => {
54
73
  selectionRef.current = {
55
74
  selectedModel,
@@ -109,98 +128,155 @@ export function useChatModels({ storageKey = DEFAULT_STORAGE_KEY, enabled = true
109
128
  const refreshEngines = useCallback(() => {
110
129
  if (!enabled)
111
130
  return;
131
+ refreshGenerationRef.current += 1;
132
+ const refreshGeneration = refreshGenerationRef.current;
133
+ if (retryTimerRef.current !== null) {
134
+ clearTimeout(retryTimerRef.current);
135
+ retryTimerRef.current = null;
136
+ }
112
137
  setIsLoading(true);
113
- Promise.all([
114
- callAction("manage-agent-engine", { action: "list" }).catch(() => null),
115
- fetchEnvironmentStatus(),
116
- fetchBuilderStatus(),
117
- ])
118
- .then(([enginesData, envResult, builderResult]) => {
119
- if (!enginesData?.engines) {
120
- // Without a catalog the picker keeps an unvalidated DEFAULT_MODEL,
121
- // which is indistinguishable from a real selection unless we say so.
122
- console.warn("[agent-chat] no engine list; model picker is showing an unvalidated default");
123
- return;
124
- }
125
- if (envResult.state !== "available" ||
126
- builderResult.state !== "available") {
138
+ const isCurrentRefresh = () => mountedRef.current && refreshGenerationRef.current === refreshGeneration;
139
+ const finish = () => {
140
+ if (isCurrentRefresh())
141
+ setIsLoading(false);
142
+ };
143
+ function scheduleRetry(attempt) {
144
+ const delay = MODEL_DISCOVERY_RETRY_DELAYS_MS[attempt];
145
+ if (delay === undefined || !isCurrentRefresh())
146
+ return false;
147
+ retryTimerRef.current = setTimeout(() => {
148
+ retryTimerRef.current = null;
149
+ load(attempt + 1);
150
+ }, delay);
151
+ return true;
152
+ }
153
+ function load(attempt) {
154
+ if (!isCurrentRefresh())
127
155
  return;
128
- }
129
- const envKeys = envResult.value;
130
- const builderStatus = builderResult.value;
131
- const configuredKeys = new Set(envKeys.filter((k) => k.configured).map((k) => k.key));
132
- const builderConnected = builderStatus?.configured === true;
133
- const currentEngineName = enginesData.current?.engine;
134
- const currentModel = enginesData.current?.model;
135
- const groups = buildChatModelGroups({
136
- engines: enginesData.engines,
137
- configuredKeys,
138
- builderConnected,
139
- currentEngineName,
140
- currentModel,
141
- });
142
- const nextDefaultModel = currentModel ?? DEFAULT_MODEL;
143
- setAvailableModels(groups);
144
- setDefaultModel(nextDefaultModel);
145
- const selection = selectionRef.current;
146
- // Default only to a CONFIGURED group, and to nothing when there is
147
- // none. `DEFAULT_MODEL` is a builder-gateway id that no group carries
148
- // unless Builder is connected, and unconfigured groups are kept in the
149
- // list for their connect affordance — so both `?? DEFAULT_MODEL` and
150
- // `?? groups[0]` yield a selection the app cannot route, which the
151
- // server silently replaces with its own default. An empty selection
152
- // hides the picker instead of showing a model that will not be used.
153
- const configuredGroups = groups.filter((g) => g.configured);
154
- const resolveRoutableSelection = () => {
155
- const group = configuredGroups.find((g) => g.models.includes(nextDefaultModel)) ??
156
- configuredGroups[0];
157
- if (!group)
158
- return null;
159
- const model = group.models.find((m) => m === nextDefaultModel) ?? group.models[0];
160
- if (!model)
161
- return null;
162
- return {
163
- model,
164
- engine: group.engine,
165
- effort: resolveReasoningEffortSelection(model, selection.selectedEffort),
156
+ Promise.all([
157
+ fetchEngineCatalog(),
158
+ fetchEnvironmentStatus(),
159
+ fetchBuilderStatus(),
160
+ ])
161
+ .then(([engineResult, envResult, builderResult]) => {
162
+ if (!isCurrentRefresh())
163
+ return;
164
+ if (engineResult.state !== "available" ||
165
+ envResult.state !== "available" ||
166
+ builderResult.state !== "available") {
167
+ if (scheduleRetry(attempt))
168
+ return;
169
+ if (engineResult.state !== "available") {
170
+ // Without a catalog the picker keeps an unvalidated DEFAULT_MODEL,
171
+ // which is indistinguishable from a real selection unless we say so.
172
+ console.warn("[agent-chat] engine list unavailable; model picker is showing an unvalidated default");
173
+ }
174
+ finish();
175
+ return;
176
+ }
177
+ const enginesData = engineResult.value;
178
+ const envKeys = envResult.value;
179
+ const builderStatus = builderResult.value;
180
+ const configuredKeys = new Set(envKeys.filter((k) => k.configured).map((k) => k.key));
181
+ const builderConnected = builderStatus?.configured === true;
182
+ const currentEngineName = enginesData.current?.engine;
183
+ const currentModel = enginesData.current?.model;
184
+ const groups = buildChatModelGroups({
185
+ engines: enginesData.engines,
186
+ configuredKeys,
187
+ builderConnected,
188
+ currentEngineName,
189
+ currentModel,
190
+ });
191
+ const nextDefaultModel = currentModel ?? DEFAULT_MODEL;
192
+ setAvailableModels(groups);
193
+ setDefaultModel(nextDefaultModel);
194
+ const selection = selectionRef.current;
195
+ // Default only to a CONFIGURED group, and to nothing when there is
196
+ // none. `DEFAULT_MODEL` is a builder-gateway id that no group carries
197
+ // unless Builder is connected, and unconfigured groups are kept in the
198
+ // list for their connect affordance — so both `?? DEFAULT_MODEL` and
199
+ // `?? groups[0]` yield a selection the app cannot route, which the
200
+ // server silently replaces with its own default. An empty selection
201
+ // hides the picker instead of showing a model that will not be used.
202
+ const configuredGroups = groups.filter((g) => g.configured);
203
+ const resolveRoutableSelection = () => {
204
+ const group = configuredGroups.find((g) => g.models.includes(nextDefaultModel)) ?? configuredGroups[0];
205
+ if (!group)
206
+ return null;
207
+ const model = group.models.find((m) => m === nextDefaultModel) ??
208
+ group.models[0];
209
+ if (!model)
210
+ return null;
211
+ return {
212
+ model,
213
+ engine: group.engine,
214
+ effort: resolveReasoningEffortSelection(model, selection.selectedEffort),
215
+ };
216
+ };
217
+ const applyFallback = (persist) => {
218
+ const next = resolveRoutableSelection();
219
+ setSelectedModel(next?.model ?? "");
220
+ setSelectedEngine(next?.engine ?? "");
221
+ if (next) {
222
+ setSelectedEffort(next.effort);
223
+ if (persist)
224
+ writePersisted(storageKey, next);
225
+ }
166
226
  };
167
- };
168
- const applyFallback = (persist) => {
169
- const next = resolveRoutableSelection();
170
- setSelectedModel(next?.model ?? "");
171
- setSelectedEngine(next?.engine ?? "");
172
- if (next) {
173
- setSelectedEffort(next.effort);
174
- if (persist)
175
- writePersisted(storageKey, next);
227
+ if (!hasExplicitSelectionRef.current) {
228
+ applyFallback(false);
229
+ finish();
230
+ return;
176
231
  }
177
- };
178
- if (!hasExplicitSelectionRef.current) {
179
- applyFallback(false);
180
- return;
181
- }
182
- const selectedGroup = groups.find((group) => group.models.includes(selection.selectedModel) &&
183
- (!selection.selectedEngine ||
184
- group.engine === selection.selectedEngine));
185
- if (selectedGroup) {
186
- // Heal a selection stored without an engine (or with a stale one) so
187
- // later submits carry the pair the catalog resolved.
188
- if (selection.selectedEngine !== selectedGroup.engine) {
189
- setSelectedEngine(selectedGroup.engine);
232
+ const selectedGroup = groups.find((group) => group.models.includes(selection.selectedModel) &&
233
+ (!selection.selectedEngine ||
234
+ group.engine === selection.selectedEngine));
235
+ if (selectedGroup) {
236
+ // Heal a selection stored without an engine (or with a stale one) so
237
+ // later submits carry the pair the catalog resolved.
238
+ if (selection.selectedEngine !== selectedGroup.engine) {
239
+ setSelectedEngine(selectedGroup.engine);
240
+ }
241
+ finish();
242
+ return;
190
243
  }
191
- return;
192
- }
193
- applyFallback(true);
194
- })
195
- .catch(() => { })
196
- .finally(() => setIsLoading(false));
244
+ applyFallback(true);
245
+ finish();
246
+ })
247
+ .catch(() => {
248
+ if (!isCurrentRefresh())
249
+ return;
250
+ if (!scheduleRetry(attempt))
251
+ finish();
252
+ });
253
+ }
254
+ load(0);
197
255
  }, [enabled, storageKey]);
256
+ useEffect(() => {
257
+ mountedRef.current = true;
258
+ return () => {
259
+ mountedRef.current = false;
260
+ refreshGenerationRef.current += 1;
261
+ if (retryTimerRef.current !== null) {
262
+ clearTimeout(retryTimerRef.current);
263
+ retryTimerRef.current = null;
264
+ }
265
+ };
266
+ }, []);
198
267
  useEffect(() => {
199
268
  if (!enabled) {
269
+ refreshGenerationRef.current += 1;
270
+ if (retryTimerRef.current !== null) {
271
+ clearTimeout(retryTimerRef.current);
272
+ retryTimerRef.current = null;
273
+ }
200
274
  setIsLoading(false);
201
275
  return;
202
276
  }
203
277
  refreshEngines();
278
+ window.addEventListener("agent-engine:configured-changed", refreshEngines);
279
+ return () => window.removeEventListener("agent-engine:configured-changed", refreshEngines);
204
280
  }, [enabled, refreshEngines]);
205
281
  return {
206
282
  availableModels,
@@ -18,6 +18,8 @@ export interface RunStuckState {
18
18
  lastProgressAt: number | null;
19
19
  /** Milliseconds since `lastProgressAt`, or null. */
20
20
  stuckSinceMs: number | null;
21
+ /** Last browser SSE sequence classified as real work progress, or null. */
22
+ lastProgressSeq: number | null;
21
23
  /** Server timestamp (ms) of the last process-alive heartbeat. */
22
24
  heartbeatAt: number | null;
23
25
  /** Milliseconds since `heartbeatAt`, computed against the server clock. */
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useState, useCallback } from "react";
2
2
  import { createPollEngine } from "../shared/poll-engine.js";
3
+ import { ACTIVE_RUN_STATE_EVENT, getActiveRun, } from "./active-run-state.js";
3
4
  import { agentNativePath } from "./api-path.js";
4
5
  const DEFAULT_STUCK_THRESHOLD_MS = 90_000;
5
6
  export const DEFAULT_BACKGROUND_STUCK_THRESHOLD_MS = 180_000;
@@ -20,6 +21,7 @@ const EMPTY_STATE = {
20
21
  status: null,
21
22
  lastProgressAt: null,
22
23
  stuckSinceMs: null,
24
+ lastProgressSeq: null,
23
25
  heartbeatAt: null,
24
26
  heartbeatSinceMs: null,
25
27
  dispatchMode: null,
@@ -37,6 +39,8 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
37
39
  let cancelled = false;
38
40
  let snapshotTransitionTimer = null;
39
41
  let snapshotVersion = 0;
42
+ let lastObservedLocalProgressAt = null;
43
+ let lastObservedLocalProgressSeq = null;
40
44
  let consecutivePollFailures = 0;
41
45
  // The engine's own cadence varies per tick (idle backoff, error backoff),
42
46
  // which is why intervalMs below reads from this ref instead of a fixed
@@ -86,8 +90,14 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
86
90
  const currentStuckSinceMs = snapshot.stuckSinceMs == null
87
91
  ? null
88
92
  : snapshot.stuckSinceMs + currentElapsedMs;
93
+ const currentLocalProgressSinceMs = snapshot.localProgressObservedAt == null
94
+ ? null
95
+ : Math.max(0, Date.now() - snapshot.localProgressObservedAt);
89
96
  const effectiveThresholdMs = effectiveThresholdFor(snapshot.dispatchMode, currentHeartbeatSinceMs);
90
- const currentlyStuck = Boolean(currentStuckSinceMs != null &&
97
+ const localProgressFresh = Boolean(currentLocalProgressSinceMs != null &&
98
+ currentLocalProgressSinceMs <= effectiveThresholdMs);
99
+ const currentlyStuck = Boolean(!localProgressFresh &&
100
+ currentStuckSinceMs != null &&
91
101
  currentStuckSinceMs > effectiveThresholdMs);
92
102
  const transitionDelaysMs = [];
93
103
  if (currentHeartbeatSinceMs != null &&
@@ -95,9 +105,14 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
95
105
  currentHeartbeatSinceMs < FRESH_BACKGROUND_HEARTBEAT_MS) {
96
106
  transitionDelaysMs.push(FRESH_BACKGROUND_HEARTBEAT_MS - currentHeartbeatSinceMs + 1);
97
107
  }
98
- if (currentStuckSinceMs != null && !currentlyStuck) {
108
+ if (!localProgressFresh &&
109
+ currentStuckSinceMs != null &&
110
+ !currentlyStuck) {
99
111
  transitionDelaysMs.push(Math.max(1, effectiveThresholdMs - currentStuckSinceMs + 1));
100
112
  }
113
+ if (localProgressFresh && currentLocalProgressSinceMs != null) {
114
+ transitionDelaysMs.push(Math.max(1, effectiveThresholdMs - currentLocalProgressSinceMs + 1));
115
+ }
101
116
  if (transitionDelaysMs.length === 0)
102
117
  return;
103
118
  // Both ages originate from the server clock. Advance those snapshots by
@@ -116,26 +131,66 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
116
131
  const nextStuckSinceMs = snapshot.stuckSinceMs == null
117
132
  ? null
118
133
  : snapshot.stuckSinceMs + elapsedSinceObservationMs;
134
+ const nextLocalProgressSinceMs = snapshot.localProgressObservedAt == null
135
+ ? null
136
+ : Math.max(0, Date.now() - snapshot.localProgressObservedAt);
119
137
  const nextEffectiveThresholdMs = effectiveThresholdFor(snapshot.dispatchMode, nextHeartbeatSinceMs);
120
- const nextIsStuck = Boolean(nextStuckSinceMs != null &&
138
+ const nextLocalProgressFresh = Boolean(nextLocalProgressSinceMs != null &&
139
+ nextLocalProgressSinceMs <= nextEffectiveThresholdMs);
140
+ const nextIsStuck = Boolean(!nextLocalProgressFresh &&
141
+ nextStuckSinceMs != null &&
121
142
  nextStuckSinceMs > nextEffectiveThresholdMs);
122
143
  setState((current) => {
123
144
  if (version !== snapshotVersion ||
124
145
  current.runId !== snapshot.runId ||
125
146
  current.lastProgressAt !== snapshot.lastProgressAt ||
126
- current.heartbeatAt !== snapshot.heartbeatAt) {
147
+ current.heartbeatAt !== snapshot.heartbeatAt ||
148
+ current.lastProgressSeq !== snapshot.lastProgressSeq) {
127
149
  return current;
128
150
  }
129
151
  return {
130
152
  ...current,
131
153
  isStuck: nextIsStuck,
132
- stuckSinceMs: nextStuckSinceMs,
154
+ stuckSinceMs: nextLocalProgressFresh ? null : nextStuckSinceMs,
133
155
  heartbeatSinceMs: nextHeartbeatSinceMs,
134
156
  };
135
157
  });
136
158
  scheduleSnapshotTransition(snapshot, observedAtMs, version);
137
159
  }, delayMs);
138
160
  };
161
+ // A healthy SSE stream is a stronger local proof of progress than a
162
+ // delayed SQL timestamp. Listen only to the real-progress cursor - raw
163
+ // keepalives still advance the reconnect cursor but must not suppress the
164
+ // stuck detector forever.
165
+ const onActiveRunStateChange = (event) => {
166
+ const activeRun = (event.detail?.state ?? getActiveRun());
167
+ const progressSeq = activeRun?.lastProgressSeq ?? null;
168
+ const hasNewerProgress = typeof activeRun?.lastProgressObservedAt === "number" &&
169
+ (activeRun.lastProgressObservedAt >
170
+ (lastObservedLocalProgressAt ?? -1) ||
171
+ (activeRun.lastProgressObservedAt === lastObservedLocalProgressAt &&
172
+ progressSeq != null &&
173
+ progressSeq > (lastObservedLocalProgressSeq ?? -1)));
174
+ if (!activeRun ||
175
+ activeRun.threadId !== threadId ||
176
+ typeof activeRun.lastProgressObservedAt !== "number" ||
177
+ !hasNewerProgress) {
178
+ return;
179
+ }
180
+ lastObservedLocalProgressAt = activeRun.lastProgressObservedAt;
181
+ lastObservedLocalProgressSeq = progressSeq;
182
+ snapshotVersion += 1;
183
+ if (snapshotTransitionTimer)
184
+ clearTimeout(snapshotTransitionTimer);
185
+ snapshotTransitionTimer = null;
186
+ setState((current) => {
187
+ if (current.runId !== activeRun.runId || !current.isStuck) {
188
+ return current;
189
+ }
190
+ return { ...current, isStuck: false, stuckSinceMs: null };
191
+ });
192
+ };
193
+ window.addEventListener(ACTIVE_RUN_STATE_EVENT, onActiveRunStateChange);
139
194
  const attempt = async (signal) => {
140
195
  let nextDelay = pollIntervalMs;
141
196
  try {
@@ -156,6 +211,14 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
156
211
  const heartbeatAt = data.heartbeatAt ?? null;
157
212
  const heartbeatSinceMs = heartbeatAt != null ? nowMs - heartbeatAt : null;
158
213
  const dispatchMode = typeof data.dispatchMode === "string" ? data.dispatchMode : null;
214
+ const runId = data.runId ?? null;
215
+ const activeRun = getActiveRun();
216
+ const localProgressObservedAt = activeRun?.threadId === threadId && activeRun.runId === runId
217
+ ? (activeRun.lastProgressObservedAt ?? null)
218
+ : null;
219
+ const localProgressSinceMs = localProgressObservedAt == null
220
+ ? null
221
+ : Math.max(0, Date.now() - localProgressObservedAt);
159
222
  // A claimed durable worker with a fresh heartbeat can legitimately
160
223
  // be waiting on a bounded long-running tool/sub-agent call. Still
161
224
  // surface informational status at the normal background threshold;
@@ -166,25 +229,37 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
166
229
  const isStuck = Boolean(data.active &&
167
230
  data.status === "running" &&
168
231
  stuckSinceMs != null &&
169
- stuckSinceMs > effectiveThresholdMs);
232
+ stuckSinceMs > effectiveThresholdMs &&
233
+ (localProgressSinceMs == null ||
234
+ localProgressSinceMs > effectiveThresholdMs));
170
235
  const observedAtMs = Date.now();
171
236
  const version = ++snapshotVersion;
172
237
  scheduleSnapshotTransition({
173
238
  active: data.active,
174
- runId: data.runId ?? null,
239
+ runId,
175
240
  status: data.status ?? null,
176
241
  lastProgressAt,
177
242
  stuckSinceMs,
243
+ localProgressObservedAt,
244
+ lastProgressSeq: activeRun?.threadId === threadId && activeRun.runId === runId
245
+ ? (activeRun.lastProgressSeq ?? null)
246
+ : null,
178
247
  heartbeatAt,
179
248
  heartbeatSinceMs,
180
249
  dispatchMode,
181
250
  }, observedAtMs, version);
182
251
  setState({
183
252
  isStuck,
184
- runId: data.runId ?? null,
253
+ runId,
185
254
  status: data.status ?? null,
186
255
  lastProgressAt,
187
- stuckSinceMs,
256
+ stuckSinceMs: localProgressSinceMs != null &&
257
+ localProgressSinceMs <= effectiveThresholdMs
258
+ ? null
259
+ : stuckSinceMs,
260
+ lastProgressSeq: activeRun?.threadId === threadId && activeRun.runId === runId
261
+ ? (activeRun.lastProgressSeq ?? null)
262
+ : null,
188
263
  heartbeatAt,
189
264
  heartbeatSinceMs,
190
265
  dispatchMode,
@@ -245,6 +320,7 @@ export function useRunStuckDetection({ threadId, enabled = true, stuckThresholdM
245
320
  engine.stop();
246
321
  if (snapshotTransitionTimer)
247
322
  clearTimeout(snapshotTransitionTimer);
323
+ window.removeEventListener(ACTIVE_RUN_STATE_EVENT, onActiveRunStateChange);
248
324
  document.removeEventListener("visibilitychange", onVisibilityChange);
249
325
  };
250
326
  }, [
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
62
62
  error: string;
63
63
  states?: undefined;
64
64
  } | {
65
+ error?: undefined;
65
66
  states: {
66
67
  clientId: number;
67
68
  state: string;
68
69
  }[];
69
- error?: undefined;
70
70
  }>>;
71
71
  /**
72
72
  * GET /_agent-native/collab/:docId/users
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
77
77
  error: string;
78
78
  users?: undefined;
79
79
  } | {
80
+ error?: undefined;
80
81
  users: {
81
82
  clientId: number;
82
83
  lastSeen: number;
83
84
  }[];
84
- error?: undefined;
85
85
  }>>;
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- ok?: undefined;
30
29
  error: string;
30
+ ok?: undefined;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -13,8 +13,8 @@
13
13
  * Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
14
14
  */
15
15
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- ok?: undefined;
17
16
  error: string;
17
+ ok?: undefined;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -2,10 +2,6 @@ import type { PlatformAdapter, IncomingMessage } from "../types.js";
2
2
  export interface SlackAdapterOptions {
3
3
  /** Resolve the bot token for the exact Slack installation. */
4
4
  resolveBotToken?: (incoming: IncomingMessage) => Promise<string | undefined>;
5
- /** Override active-thread detection for hosted adapters/tests. */
6
- isThreadActive?: (incoming: IncomingMessage) => Promise<boolean>;
7
- /** Override one-shot clarification-window consumption for tests. */
8
- consumeAwaitingInput?: (incoming: IncomingMessage) => Promise<boolean>;
9
5
  }
10
6
  /**
11
7
  * Create a Slack platform adapter.
@@ -3,10 +3,8 @@ import { createError, getHeader, readRawBody } from "h3";
3
3
  import { resolveSecret } from "../../server/credential-provider.js";
4
4
  import { getRequestContext } from "../../server/request-context.js";
5
5
  import { getIntegrationRequestContext } from "../../server/request-context.js";
6
- import { consumeIntegrationAwaitingInput } from "../awaiting-input-store.js";
7
6
  import { createIntegrationControl } from "../controls-store.js";
8
7
  import { getActiveIntegrationInstallationByKey, listActiveIntegrationInstallationsForTenant, listIntegrationInstallations, resolveIntegrationTokenBundle, } from "../installations-store.js";
9
- import { hasActivePendingTask } from "../pending-tasks-store.js";
10
8
  import { slackInstallationKey } from "../slack-oauth.js";
11
9
  /** Slack's max message length */
12
10
  const SLACK_MAX_LENGTH = 4000;
@@ -195,10 +193,10 @@ export function slackAdapter(options = {}) {
195
193
  // Ignore message edits and deletes
196
194
  if (e.subtype === "message_changed" || e.subtype === "message_deleted")
197
195
  return null;
198
- // Handle DMs and explicit mentions. Ordinary channel replies are only
199
- // accepted while this exact workspace-qualified thread has queued or
200
- // executing work; broad message subscriptions must never invoke the
201
- // agent for general channel chatter.
196
+ // Handle DMs and explicit mentions only. A channel thread can contain
197
+ // many human replies after an agent mention; each new agent turn must
198
+ // opt in with another explicit mention instead of inheriting the
199
+ // parent message's invocation.
202
200
  const text = e.text?.trim();
203
201
  if (!text)
204
202
  return null;
@@ -211,8 +209,7 @@ export function slackAdapter(options = {}) {
211
209
  ? e.channel_type === "im"
212
210
  : typeof e.channel === "string" && e.channel.startsWith("D");
213
211
  const isMention = e.type === "app_mention";
214
- const isThreadReply = !isDm && !isMention && !!e.thread_ts;
215
- if (!isDm && !isMention && !isThreadReply)
212
+ if (!isDm && !isMention)
216
213
  return null;
217
214
  // Remove bot mention from text (e.g., "<@U123> do something" → "do something")
218
215
  const cleanText = text.replace(/<@[A-Z0-9]+>/g, "").trim();
@@ -227,7 +224,7 @@ export function slackAdapter(options = {}) {
227
224
  text: cleanText,
228
225
  senderName: e.user,
229
226
  senderId: e.user,
230
- triggerKind: isDm ? "dm" : isMention ? "mention" : "thread_reply",
227
+ triggerKind: isDm ? "dm" : "mention",
231
228
  conversationType: isDm ? "dm" : "unknown",
232
229
  tenantId: teamId,
233
230
  // The signed Slack envelope authenticates the workspace, not the
@@ -256,27 +253,6 @@ export function slackAdapter(options = {}) {
256
253
  replyRef: e.ts,
257
254
  timestamp: Math.floor(parseFloat(e.ts) * 1000),
258
255
  };
259
- if (isThreadReply) {
260
- // An ordinary thread reply is narrowly admitted when either work is
261
- // still queued or the same Slack user is answering a fresh
262
- // integration-originated clarification. Consuming the latter is a
263
- // conditional SQL delete, so concurrent replies cannot both reopen
264
- // the agent and unrelated channel messages remain ignored.
265
- const answeredClarification = options.consumeAwaitingInput
266
- ? await options.consumeAwaitingInput(partialIncoming)
267
- : options.isThreadActive
268
- ? false
269
- : await consumeIntegrationAwaitingInput({
270
- platform: "slack",
271
- externalThreadId,
272
- requesterId: e.user,
273
- });
274
- const active = options.isThreadActive
275
- ? await options.isThreadActive(partialIncoming)
276
- : await hasActivePendingTask("slack", externalThreadId);
277
- if (!active && !answeredClarification)
278
- return null;
279
- }
280
256
  const token = await resolveBotToken(partialIncoming);
281
257
  const threadPermalink = await resolveSlackThreadPermalink(e.channel, threadTs, token);
282
258
  return {
@@ -36,7 +36,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
36
36
  "Apply the Agent Native Slack manifest to enable Agent View and writable direct messages.",
37
37
  "Configure the OAuth client id, client secret, and signing secret.",
38
38
  "Enable Event Subscriptions and Interactivity with the documented URLs.",
39
- "Subscribe to app_home_opened, app_context_changed, app_mention, and message.im/channels/groups, then use Add to Slack.",
39
+ "Subscribe to app_home_opened, app_context_changed, app_mention, and message.im, then use Add to Slack.",
40
40
  ],
41
41
  },
42
42
  credentialRequirements: [
@@ -20,14 +20,6 @@ export interface PendingTask {
20
20
  updatedAt: number;
21
21
  completedAt: number | null;
22
22
  }
23
- /**
24
- * Whether a provider thread currently has queued or executing work.
25
- *
26
- * Messaging adapters use this to accept unmentioned replies only while an
27
- * agent task is active. This prevents broad message subscriptions from turning
28
- * every channel message into an agent invocation.
29
- */
30
- export declare function hasActivePendingTask(platform: string, externalThreadId: string): Promise<boolean>;
31
23
  /**
32
24
  * Insert a new pending task. Returns the generated task id.
33
25
  *