@agent-native/core 0.90.2 → 0.90.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) hide show
  1. package/bin/agent-native.js +25 -3
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +21 -0
  4. package/corpus/core/bin/agent-native.js +25 -3
  5. package/corpus/core/docs/content/agent-native-toolkit.mdx +87 -80
  6. package/corpus/core/docs/content/locales/ar-SA/agent-native-toolkit.mdx +89 -80
  7. package/corpus/core/docs/content/locales/de-DE/agent-native-toolkit.mdx +89 -80
  8. package/corpus/core/docs/content/locales/es-ES/agent-native-toolkit.mdx +89 -80
  9. package/corpus/core/docs/content/locales/fr-FR/agent-native-toolkit.mdx +89 -80
  10. package/corpus/core/docs/content/locales/hi-IN/agent-native-toolkit.mdx +89 -80
  11. package/corpus/core/docs/content/locales/ja-JP/agent-native-toolkit.mdx +89 -80
  12. package/corpus/core/docs/content/locales/ko-KR/agent-native-toolkit.mdx +89 -80
  13. package/corpus/core/docs/content/locales/pt-BR/agent-native-toolkit.mdx +89 -80
  14. package/corpus/core/docs/content/locales/zh-CN/agent-native-toolkit.mdx +89 -80
  15. package/corpus/core/docs/content/locales/zh-TW/agent-native-toolkit.mdx +89 -80
  16. package/corpus/core/docs/content/toolkit-agent-ux.mdx +43 -0
  17. package/corpus/core/docs/content/toolkit-app-adapters.mdx +9 -0
  18. package/corpus/core/docs/content/toolkit-collaboration-ui.mdx +12 -0
  19. package/corpus/core/docs/content/toolkit-collaboration.mdx +74 -0
  20. package/corpus/core/docs/content/toolkit-command-navigation.mdx +106 -0
  21. package/corpus/core/docs/content/toolkit-comments-review.mdx +98 -0
  22. package/corpus/core/docs/content/toolkit-history.mdx +95 -0
  23. package/corpus/core/docs/content/toolkit-observability.mdx +41 -0
  24. package/corpus/core/docs/content/toolkit-org-team.mdx +80 -0
  25. package/corpus/core/docs/content/toolkit-resources.mdx +57 -0
  26. package/corpus/core/docs/content/toolkit-settings.mdx +65 -0
  27. package/corpus/core/docs/content/toolkit-setup-connections.mdx +109 -0
  28. package/corpus/core/docs/content/toolkit-sharing-ui.mdx +18 -6
  29. package/corpus/core/docs/content/toolkit-sharing.mdx +81 -0
  30. package/corpus/core/docs/content/toolkit-shell-hooks.mdx +9 -0
  31. package/corpus/core/docs/content/toolkit-ui.mdx +9 -0
  32. package/corpus/core/package.json +35 -1
  33. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +19 -1
  34. package/corpus/core/src/agent/engine/anthropic-engine.ts +25 -1
  35. package/corpus/core/src/agent/engine/index.ts +1 -0
  36. package/corpus/core/src/agent/engine/registry.ts +86 -18
  37. package/corpus/core/src/agent/production-agent.ts +37 -6
  38. package/corpus/core/src/cli/create.ts +35 -0
  39. package/corpus/core/src/cli/design-connect.ts +248 -0
  40. package/corpus/core/src/cli/index.ts +84 -7
  41. package/corpus/core/src/cli/workspacify.ts +34 -0
  42. package/corpus/core/src/client/command-navigation/index.ts +15 -0
  43. package/corpus/core/src/client/comments-review/index.ts +1 -0
  44. package/corpus/core/src/client/history/VersionHistoryPanel.tsx +175 -0
  45. package/corpus/core/src/client/history/index.ts +21 -0
  46. package/corpus/core/src/client/history/use-history.ts +114 -0
  47. package/corpus/core/src/client/index.ts +84 -9
  48. package/corpus/core/src/client/org/OrgSwitcher.tsx +6 -6
  49. package/corpus/core/src/client/org/RequireActiveOrg.tsx +2 -2
  50. package/corpus/core/src/client/org/TeamPage.tsx +3 -3
  51. package/corpus/core/src/client/org/hooks.ts +32 -0
  52. package/corpus/core/src/client/org/index.ts +30 -1
  53. package/corpus/core/src/client/org-team/index.ts +1 -0
  54. package/corpus/core/src/client/review/ReviewStatusBadge.tsx +39 -0
  55. package/corpus/core/src/client/review/ReviewThreadPanel.tsx +278 -0
  56. package/corpus/core/src/client/review/index.ts +30 -0
  57. package/corpus/core/src/client/review/use-review.ts +152 -0
  58. package/corpus/core/src/client/settings/index.ts +11 -1
  59. package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +94 -0
  60. package/corpus/core/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
  61. package/corpus/core/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
  62. package/corpus/core/src/client/setup-connections/index.ts +46 -0
  63. package/corpus/core/src/client/sharing/ShareButton.tsx +20 -14
  64. package/corpus/core/src/client/sharing/ShareDialog.tsx +3 -3
  65. package/corpus/core/src/command-navigation/actions.ts +100 -0
  66. package/corpus/core/src/command-navigation/index.ts +12 -0
  67. package/corpus/core/src/comments-review/index.ts +1 -0
  68. package/corpus/core/src/file-upload/builder.ts +24 -3
  69. package/corpus/core/src/file-upload/types.ts +3 -1
  70. package/corpus/core/src/history/actions/create-resource-version.ts +92 -0
  71. package/corpus/core/src/history/actions/get-resource-version.ts +60 -0
  72. package/corpus/core/src/history/actions/list-resource-history.ts +53 -0
  73. package/corpus/core/src/history/actions/list-resource-versions.ts +43 -0
  74. package/corpus/core/src/history/actions/restore-resource-version.ts +96 -0
  75. package/corpus/core/src/history/index.ts +26 -0
  76. package/corpus/core/src/history/registry.ts +111 -0
  77. package/corpus/core/src/history/store.ts +379 -0
  78. package/corpus/core/src/history/types.ts +69 -0
  79. package/corpus/core/src/index.ts +10 -0
  80. package/corpus/core/src/navigation/index.ts +170 -0
  81. package/corpus/core/src/org/index.ts +8 -0
  82. package/corpus/core/src/org/permissions.ts +30 -0
  83. package/corpus/core/src/org-team/index.ts +1 -0
  84. package/corpus/core/src/private-blob/registry.ts +1 -0
  85. package/corpus/core/src/review/actions/consume-review-feedback.ts +48 -0
  86. package/corpus/core/src/review/actions/create-review-comment.ts +107 -0
  87. package/corpus/core/src/review/actions/delete-review-comment.ts +67 -0
  88. package/corpus/core/src/review/actions/get-review-feedback.ts +54 -0
  89. package/corpus/core/src/review/actions/list-review-comments.ts +53 -0
  90. package/corpus/core/src/review/actions/reply-review-comment.ts +107 -0
  91. package/corpus/core/src/review/actions/resolve-review-thread.ts +67 -0
  92. package/corpus/core/src/review/actions/set-review-status.ts +58 -0
  93. package/corpus/core/src/review/index.ts +31 -0
  94. package/corpus/core/src/review/mentions.ts +44 -0
  95. package/corpus/core/src/review/registry.ts +111 -0
  96. package/corpus/core/src/review/store.ts +690 -0
  97. package/corpus/core/src/review/types.ts +97 -0
  98. package/corpus/core/src/server/action-discovery.ts +54 -0
  99. package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
  100. package/corpus/core/src/server/agent-engine-api-key-route.ts +5 -0
  101. package/corpus/core/src/server/credential-provider.ts +118 -0
  102. package/corpus/core/src/setup-connections/index.ts +89 -0
  103. package/corpus/core/src/setup-connections/onboarding.ts +47 -0
  104. package/corpus/core/src/transcription/builder-transcription.ts +9 -2
  105. package/corpus/core/src/vite/action-types-plugin.ts +52 -0
  106. package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -1
  107. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +2 -2
  108. package/corpus/templates/analytics/app/global.css +22 -10
  109. package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -1
  110. package/corpus/templates/analytics/app/i18n-data.ts +81 -13
  111. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
  112. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
  113. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +528 -108
  114. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +466 -183
  115. package/corpus/templates/analytics/changelog/2026-07-07-session-replays-load-sooner-show-clearer-activity-timelines-.md +6 -0
  116. package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +11 -11
  117. package/corpus/templates/assets/actions/generate-image.ts +64 -28
  118. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +1 -1
  119. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +91 -74
  120. package/corpus/templates/assets/server/lib/generation.ts +29 -4
  121. package/corpus/templates/assets/server/lib/image-processing.ts +131 -0
  122. package/corpus/templates/brain/app/routes/settings.tsx +2 -2
  123. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +24 -2
  124. package/corpus/templates/calendar/AGENTS.md +3 -0
  125. package/corpus/templates/calendar/actions/create-event.ts +8 -34
  126. package/corpus/templates/calendar/actions/event-action-helpers.ts +52 -0
  127. package/corpus/templates/calendar/actions/manage-event-draft.ts +7 -34
  128. package/corpus/templates/calendar/actions/update-event.ts +10 -23
  129. package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +79 -6
  130. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +23 -0
  131. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +59 -2
  132. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +40 -1
  133. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +154 -41
  134. package/corpus/templates/calendar/app/hooks/use-events.ts +6 -0
  135. package/corpus/templates/calendar/app/hooks/use-people.ts +55 -0
  136. package/corpus/templates/calendar/app/i18n/zh-TW.ts +4 -0
  137. package/corpus/templates/calendar/app/i18n-data.ts +40 -0
  138. package/corpus/templates/calendar/changelog/2026-07-07-guest-suggestions-now-find-coworkers-from-your-google-worksp.md +6 -0
  139. package/corpus/templates/calendar/changelog/2026-07-07-you-can-mark-event-guests-as-optional-while-inviting-them-or.md +6 -0
  140. package/corpus/templates/calendar/changelog/2026-07-07-zoom-stays-selected-after-connecting-it-from-a-draft-event.md +6 -0
  141. package/corpus/templates/calendar/server/handlers/events.ts +1 -0
  142. package/corpus/templates/calendar/server/lib/google-calendar.ts +4 -0
  143. package/corpus/templates/calendar/server/plugins/agent-chat.ts +1 -1
  144. package/corpus/templates/calendar/shared/api.ts +2 -0
  145. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +29 -3
  146. package/corpus/templates/clips/actions/create-recording.ts +5 -1
  147. package/corpus/templates/clips/actions/finalize-recording.ts +140 -1
  148. package/corpus/templates/clips/actions/generate-workflow.ts +19 -8
  149. package/corpus/templates/clips/actions/get-clips-ai-prefs.ts +36 -0
  150. package/corpus/templates/clips/actions/import-loom-recording.ts +1 -0
  151. package/corpus/templates/clips/actions/lib/clips-ai-prefs.ts +28 -0
  152. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +1 -0
  153. package/corpus/templates/clips/actions/regenerate-chapters.ts +21 -7
  154. package/corpus/templates/clips/actions/regenerate-summary.ts +26 -8
  155. package/corpus/templates/clips/actions/regenerate-title.ts +44 -7
  156. package/corpus/templates/clips/actions/request-transcript.ts +31 -0
  157. package/corpus/templates/clips/actions/set-thumbnail.ts +2 -0
  158. package/corpus/templates/clips/actions/update-clips-ai-prefs.ts +50 -0
  159. package/corpus/templates/clips/app/components/library/organization-switcher.tsx +2 -2
  160. package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +7 -2
  161. package/corpus/templates/clips/app/components/player/scrubber-position.ts +9 -0
  162. package/corpus/templates/clips/app/components/player/scrubber.tsx +5 -2
  163. package/corpus/templates/clips/app/components/player/share-dialog.tsx +69 -41
  164. package/corpus/templates/clips/app/components/player/video-player.tsx +38 -1
  165. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -3
  166. package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +9 -19
  167. package/corpus/templates/clips/app/hooks/use-auto-title.ts +25 -10
  168. package/corpus/templates/clips/app/i18n/ar-SA.ts +28 -6
  169. package/corpus/templates/clips/app/i18n/de-DE.ts +28 -6
  170. package/corpus/templates/clips/app/i18n/en-US.ts +29 -6
  171. package/corpus/templates/clips/app/i18n/es-ES.ts +29 -6
  172. package/corpus/templates/clips/app/i18n/fr-FR.ts +30 -6
  173. package/corpus/templates/clips/app/i18n/hi-IN.ts +26 -6
  174. package/corpus/templates/clips/app/i18n/ja-JP.ts +27 -6
  175. package/corpus/templates/clips/app/i18n/ko-KR.ts +28 -6
  176. package/corpus/templates/clips/app/i18n/pt-BR.ts +28 -6
  177. package/corpus/templates/clips/app/i18n/zh-CN.ts +26 -6
  178. package/corpus/templates/clips/app/i18n/zh-TW.ts +25 -6
  179. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +73 -0
  180. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -0
  181. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +79 -5
  182. package/corpus/templates/clips/app/routes/record.tsx +21 -12
  183. package/corpus/templates/clips/changelog/2026-07-02-recordings-now-wait-for-storage-media-to-serve-before-finishing.md +6 -0
  184. package/corpus/templates/clips/changelog/2026-07-07-a-pending-app-update-no-longer-blocks-screen-recording-updat.md +6 -0
  185. package/corpus/templates/clips/changelog/2026-07-07-ai-tools-can-include-the-full-video-not-just-the-transcript-.md +6 -0
  186. package/corpus/templates/clips/changelog/2026-07-07-chrome-extension-recordings-keep-audio-after-refreshing-tab.md +6 -0
  187. package/corpus/templates/clips/changelog/2026-07-07-clip-playback-progress-now-starts-and-finishes-at-the-right-times.md +6 -0
  188. package/corpus/templates/clips/changelog/2026-07-07-clips-desktop-now-surfaces-meetings-and-dictate-directly-in-.md +6 -0
  189. package/corpus/templates/clips/changelog/2026-07-07-meeting-notes-now-explain-exactly-how-to-start-granola-style.md +6 -0
  190. package/corpus/templates/clips/changelog/2026-07-07-meeting-start-alerts-now-include-separate-start-notes-and-jo.md +6 -0
  191. package/corpus/templates/clips/changelog/2026-07-07-recordings-start-more-predictably-and-newly-saved-clips-refr.md +6 -0
  192. package/corpus/templates/clips/changelog/2026-07-07-sharing-public-clips-now-stays-focused-on-the-normal-link-wi.md +6 -0
  193. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  194. package/corpus/templates/clips/chrome-extension/src/background.ts +18 -0
  195. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +23 -8
  196. package/corpus/templates/clips/desktop/src/app.tsx +475 -108
  197. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +19 -7
  198. package/corpus/templates/clips/desktop/src/lib/permissions.ts +2 -0
  199. package/corpus/templates/clips/desktop/src/lib/recorder.ts +27 -21
  200. package/corpus/templates/clips/desktop/src/lib/updater.ts +25 -2
  201. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -22
  202. package/corpus/templates/clips/desktop/src/styles.css +167 -2
  203. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +8 -1
  204. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -7
  205. package/corpus/templates/clips/desktop/src-tauri/src/tray_meetings.rs +5 -4
  206. package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.put.ts +16 -8
  207. package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +1 -0
  208. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +22 -5
  209. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +8 -0
  210. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +13 -6
  211. package/corpus/templates/clips/shared/clips-ai-prefs.ts +81 -0
  212. package/corpus/templates/clips/shared/finalize-recovery.ts +12 -0
  213. package/corpus/templates/content/actions/delete-document.ts +337 -52
  214. package/corpus/templates/content/changelog/2026-07-07-permanently-deleting-trashed-databases-now-finishes-reliably.md +6 -0
  215. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +16 -1
  216. package/corpus/templates/design/actions/add-localhost-screens.ts +1 -0
  217. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +345 -11
  218. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +89 -14
  219. package/corpus/templates/design/app/components/design/bridge-security.ts +7 -1
  220. package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -1
  221. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  222. package/corpus/templates/design/app/i18n-data.ts +41 -0
  223. package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-uses-live-app-iframes-for-click-to-edit-pr.md +6 -0
  224. package/corpus/templates/slides/app/pages/DeckEditor.tsx +2 -2
  225. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  226. package/dist/agent/engine/ai-sdk-engine.js +15 -1
  227. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  228. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  229. package/dist/agent/engine/anthropic-engine.js +20 -1
  230. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  231. package/dist/agent/engine/index.d.ts +1 -1
  232. package/dist/agent/engine/index.d.ts.map +1 -1
  233. package/dist/agent/engine/index.js +1 -1
  234. package/dist/agent/engine/index.js.map +1 -1
  235. package/dist/agent/engine/registry.d.ts +14 -0
  236. package/dist/agent/engine/registry.d.ts.map +1 -1
  237. package/dist/agent/engine/registry.js +78 -16
  238. package/dist/agent/engine/registry.js.map +1 -1
  239. package/dist/agent/production-agent.d.ts.map +1 -1
  240. package/dist/agent/production-agent.js +27 -7
  241. package/dist/agent/production-agent.js.map +1 -1
  242. package/dist/cli/create.d.ts.map +1 -1
  243. package/dist/cli/create.js +31 -0
  244. package/dist/cli/create.js.map +1 -1
  245. package/dist/cli/design-connect.d.ts.map +1 -1
  246. package/dist/cli/design-connect.js +186 -0
  247. package/dist/cli/design-connect.js.map +1 -1
  248. package/dist/cli/index.js +76 -9
  249. package/dist/cli/index.js.map +1 -1
  250. package/dist/cli/workspacify.d.ts.map +1 -1
  251. package/dist/cli/workspacify.js +30 -0
  252. package/dist/cli/workspacify.js.map +1 -1
  253. package/dist/client/command-navigation/index.d.ts +4 -0
  254. package/dist/client/command-navigation/index.d.ts.map +1 -0
  255. package/dist/client/command-navigation/index.js +4 -0
  256. package/dist/client/command-navigation/index.js.map +1 -0
  257. package/dist/client/comments-review/index.d.ts +2 -0
  258. package/dist/client/comments-review/index.d.ts.map +1 -0
  259. package/dist/client/comments-review/index.js +2 -0
  260. package/dist/client/comments-review/index.js.map +1 -0
  261. package/dist/client/history/VersionHistoryPanel.d.ts +18 -0
  262. package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -0
  263. package/dist/client/history/VersionHistoryPanel.js +31 -0
  264. package/dist/client/history/VersionHistoryPanel.js.map +1 -0
  265. package/dist/client/history/index.d.ts +3 -0
  266. package/dist/client/history/index.d.ts.map +1 -0
  267. package/dist/client/history/index.js +3 -0
  268. package/dist/client/history/index.js.map +1 -0
  269. package/dist/client/history/use-history.d.ts +58 -0
  270. package/dist/client/history/use-history.d.ts.map +1 -0
  271. package/dist/client/history/use-history.js +24 -0
  272. package/dist/client/history/use-history.js.map +1 -0
  273. package/dist/client/index.d.ts +6 -4
  274. package/dist/client/index.d.ts.map +1 -1
  275. package/dist/client/index.js +6 -4
  276. package/dist/client/index.js.map +1 -1
  277. package/dist/client/org/OrgSwitcher.js +5 -5
  278. package/dist/client/org/OrgSwitcher.js.map +1 -1
  279. package/dist/client/org/RequireActiveOrg.js +2 -2
  280. package/dist/client/org/RequireActiveOrg.js.map +1 -1
  281. package/dist/client/org/TeamPage.js +3 -3
  282. package/dist/client/org/TeamPage.js.map +1 -1
  283. package/dist/client/org/hooks.d.ts +12 -1
  284. package/dist/client/org/hooks.d.ts.map +1 -1
  285. package/dist/client/org/hooks.js +15 -0
  286. package/dist/client/org/hooks.js.map +1 -1
  287. package/dist/client/org/index.d.ts +4 -2
  288. package/dist/client/org/index.d.ts.map +1 -1
  289. package/dist/client/org/index.js +3 -1
  290. package/dist/client/org/index.js.map +1 -1
  291. package/dist/client/org-team/index.d.ts +2 -0
  292. package/dist/client/org-team/index.d.ts.map +1 -0
  293. package/dist/client/org-team/index.js +2 -0
  294. package/dist/client/org-team/index.js.map +1 -0
  295. package/dist/client/review/ReviewStatusBadge.d.ts +7 -0
  296. package/dist/client/review/ReviewStatusBadge.d.ts.map +1 -0
  297. package/dist/client/review/ReviewStatusBadge.js +19 -0
  298. package/dist/client/review/ReviewStatusBadge.js.map +1 -0
  299. package/dist/client/review/ReviewThreadPanel.d.ts +20 -0
  300. package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -0
  301. package/dist/client/review/ReviewThreadPanel.js +84 -0
  302. package/dist/client/review/ReviewThreadPanel.js.map +1 -0
  303. package/dist/client/review/index.d.ts +4 -0
  304. package/dist/client/review/index.d.ts.map +1 -0
  305. package/dist/client/review/index.js +4 -0
  306. package/dist/client/review/index.js.map +1 -0
  307. package/dist/client/review/use-review.d.ts +91 -0
  308. package/dist/client/review/use-review.d.ts.map +1 -0
  309. package/dist/client/review/use-review.js +30 -0
  310. package/dist/client/review/use-review.js.map +1 -0
  311. package/dist/client/settings/index.d.ts +1 -1
  312. package/dist/client/settings/index.d.ts.map +1 -1
  313. package/dist/client/settings/index.js +1 -1
  314. package/dist/client/settings/index.js.map +1 -1
  315. package/dist/client/setup-connections/BuilderConnectCard.d.ts +9 -0
  316. package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -0
  317. package/dist/client/setup-connections/BuilderConnectCard.js +25 -0
  318. package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -0
  319. package/dist/client/setup-connections/ProviderReadinessBadge.d.ts +8 -0
  320. package/dist/client/setup-connections/ProviderReadinessBadge.d.ts.map +1 -0
  321. package/dist/client/setup-connections/ProviderReadinessBadge.js +32 -0
  322. package/dist/client/setup-connections/ProviderReadinessBadge.js.map +1 -0
  323. package/dist/client/setup-connections/SetupConnectionsPage.d.ts +17 -0
  324. package/dist/client/setup-connections/SetupConnectionsPage.d.ts.map +1 -0
  325. package/dist/client/setup-connections/SetupConnectionsPage.js +10 -0
  326. package/dist/client/setup-connections/SetupConnectionsPage.js.map +1 -0
  327. package/dist/client/setup-connections/index.d.ts +7 -0
  328. package/dist/client/setup-connections/index.d.ts.map +1 -0
  329. package/dist/client/setup-connections/index.js +7 -0
  330. package/dist/client/setup-connections/index.js.map +1 -0
  331. package/dist/client/sharing/ShareButton.d.ts +4 -4
  332. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  333. package/dist/client/sharing/ShareButton.js +13 -7
  334. package/dist/client/sharing/ShareButton.js.map +1 -1
  335. package/dist/client/sharing/ShareDialog.js +3 -3
  336. package/dist/client/sharing/ShareDialog.js.map +1 -1
  337. package/dist/collab/awareness.d.ts +2 -2
  338. package/dist/collab/awareness.d.ts.map +1 -1
  339. package/dist/collab/routes.d.ts +1 -1
  340. package/dist/collab/struct-routes.d.ts +1 -1
  341. package/dist/command-navigation/actions.d.ts +25 -0
  342. package/dist/command-navigation/actions.d.ts.map +1 -0
  343. package/dist/command-navigation/actions.js +64 -0
  344. package/dist/command-navigation/actions.js.map +1 -0
  345. package/dist/command-navigation/index.d.ts +4 -0
  346. package/dist/command-navigation/index.d.ts.map +1 -0
  347. package/dist/command-navigation/index.js +4 -0
  348. package/dist/command-navigation/index.js.map +1 -0
  349. package/dist/comments-review/index.d.ts +2 -0
  350. package/dist/comments-review/index.d.ts.map +1 -0
  351. package/dist/comments-review/index.js +2 -0
  352. package/dist/comments-review/index.js.map +1 -0
  353. package/dist/file-upload/builder.d.ts.map +1 -1
  354. package/dist/file-upload/builder.js +18 -2
  355. package/dist/file-upload/builder.js.map +1 -1
  356. package/dist/file-upload/types.d.ts +3 -0
  357. package/dist/file-upload/types.d.ts.map +1 -1
  358. package/dist/file-upload/types.js.map +1 -1
  359. package/dist/history/actions/create-resource-version.d.ts +10 -0
  360. package/dist/history/actions/create-resource-version.d.ts.map +1 -0
  361. package/dist/history/actions/create-resource-version.js +68 -0
  362. package/dist/history/actions/create-resource-version.js.map +1 -0
  363. package/dist/history/actions/get-resource-version.d.ts +10 -0
  364. package/dist/history/actions/get-resource-version.d.ts.map +1 -0
  365. package/dist/history/actions/get-resource-version.js +38 -0
  366. package/dist/history/actions/get-resource-version.js.map +1 -0
  367. package/dist/history/actions/list-resource-history.d.ts +10 -0
  368. package/dist/history/actions/list-resource-history.d.ts.map +1 -0
  369. package/dist/history/actions/list-resource-history.js +45 -0
  370. package/dist/history/actions/list-resource-history.js.map +1 -0
  371. package/dist/history/actions/list-resource-versions.d.ts +10 -0
  372. package/dist/history/actions/list-resource-versions.d.ts.map +1 -0
  373. package/dist/history/actions/list-resource-versions.js +35 -0
  374. package/dist/history/actions/list-resource-versions.js.map +1 -0
  375. package/dist/history/actions/restore-resource-version.d.ts +11 -0
  376. package/dist/history/actions/restore-resource-version.d.ts.map +1 -0
  377. package/dist/history/actions/restore-resource-version.js +59 -0
  378. package/dist/history/actions/restore-resource-version.js.map +1 -0
  379. package/dist/history/index.d.ts +4 -0
  380. package/dist/history/index.d.ts.map +1 -0
  381. package/dist/history/index.js +3 -0
  382. package/dist/history/index.js.map +1 -0
  383. package/dist/history/registry.d.ts +10 -0
  384. package/dist/history/registry.d.ts.map +1 -0
  385. package/dist/history/registry.js +63 -0
  386. package/dist/history/registry.js.map +1 -0
  387. package/dist/history/store.d.ts +34 -0
  388. package/dist/history/store.d.ts.map +1 -0
  389. package/dist/history/store.js +290 -0
  390. package/dist/history/store.js.map +1 -0
  391. package/dist/history/types.d.ts +55 -0
  392. package/dist/history/types.d.ts.map +1 -0
  393. package/dist/history/types.js +2 -0
  394. package/dist/history/types.js.map +1 -0
  395. package/dist/index.d.ts +6 -0
  396. package/dist/index.d.ts.map +1 -1
  397. package/dist/index.js +6 -0
  398. package/dist/index.js.map +1 -1
  399. package/dist/navigation/index.d.ts +53 -0
  400. package/dist/navigation/index.d.ts.map +1 -0
  401. package/dist/navigation/index.js +105 -0
  402. package/dist/navigation/index.js.map +1 -0
  403. package/dist/observability/routes.d.ts +3 -3
  404. package/dist/org/index.d.ts +1 -0
  405. package/dist/org/index.d.ts.map +1 -1
  406. package/dist/org/index.js +1 -0
  407. package/dist/org/index.js.map +1 -1
  408. package/dist/org/permissions.d.ts +7 -0
  409. package/dist/org/permissions.d.ts.map +1 -0
  410. package/dist/org/permissions.js +21 -0
  411. package/dist/org/permissions.js.map +1 -0
  412. package/dist/org-team/index.d.ts +2 -0
  413. package/dist/org-team/index.d.ts.map +1 -0
  414. package/dist/org-team/index.js +2 -0
  415. package/dist/org-team/index.js.map +1 -0
  416. package/dist/private-blob/registry.d.ts.map +1 -1
  417. package/dist/private-blob/registry.js +1 -0
  418. package/dist/private-blob/registry.js.map +1 -1
  419. package/dist/progress/routes.d.ts +1 -1
  420. package/dist/resources/handlers.d.ts +2 -2
  421. package/dist/review/actions/consume-review-feedback.d.ts +10 -0
  422. package/dist/review/actions/consume-review-feedback.d.ts.map +1 -0
  423. package/dist/review/actions/consume-review-feedback.js +35 -0
  424. package/dist/review/actions/consume-review-feedback.js.map +1 -0
  425. package/dist/review/actions/create-review-comment.d.ts +18 -0
  426. package/dist/review/actions/create-review-comment.d.ts.map +1 -0
  427. package/dist/review/actions/create-review-comment.js +81 -0
  428. package/dist/review/actions/create-review-comment.js.map +1 -0
  429. package/dist/review/actions/delete-review-comment.d.ts +11 -0
  430. package/dist/review/actions/delete-review-comment.d.ts.map +1 -0
  431. package/dist/review/actions/delete-review-comment.js +53 -0
  432. package/dist/review/actions/delete-review-comment.js.map +1 -0
  433. package/dist/review/actions/get-review-feedback.d.ts +10 -0
  434. package/dist/review/actions/get-review-feedback.d.ts.map +1 -0
  435. package/dist/review/actions/get-review-feedback.js +45 -0
  436. package/dist/review/actions/get-review-feedback.js.map +1 -0
  437. package/dist/review/actions/list-review-comments.d.ts +13 -0
  438. package/dist/review/actions/list-review-comments.d.ts.map +1 -0
  439. package/dist/review/actions/list-review-comments.js +44 -0
  440. package/dist/review/actions/list-review-comments.js.map +1 -0
  441. package/dist/review/actions/reply-review-comment.d.ts +16 -0
  442. package/dist/review/actions/reply-review-comment.d.ts.map +1 -0
  443. package/dist/review/actions/reply-review-comment.js +84 -0
  444. package/dist/review/actions/reply-review-comment.js.map +1 -0
  445. package/dist/review/actions/resolve-review-thread.d.ts +12 -0
  446. package/dist/review/actions/resolve-review-thread.d.ts.map +1 -0
  447. package/dist/review/actions/resolve-review-thread.js +49 -0
  448. package/dist/review/actions/resolve-review-thread.js.map +1 -0
  449. package/dist/review/actions/set-review-status.d.ts +9 -0
  450. package/dist/review/actions/set-review-status.d.ts.map +1 -0
  451. package/dist/review/actions/set-review-status.js +43 -0
  452. package/dist/review/actions/set-review-status.js.map +1 -0
  453. package/dist/review/index.d.ts +5 -0
  454. package/dist/review/index.d.ts.map +1 -0
  455. package/dist/review/index.js +4 -0
  456. package/dist/review/index.js.map +1 -0
  457. package/dist/review/mentions.d.ts +4 -0
  458. package/dist/review/mentions.d.ts.map +1 -0
  459. package/dist/review/mentions.js +39 -0
  460. package/dist/review/mentions.js.map +1 -0
  461. package/dist/review/registry.d.ts +10 -0
  462. package/dist/review/registry.d.ts.map +1 -0
  463. package/dist/review/registry.js +63 -0
  464. package/dist/review/registry.js.map +1 -0
  465. package/dist/review/store.d.ts +63 -0
  466. package/dist/review/store.d.ts.map +1 -0
  467. package/dist/review/store.js +561 -0
  468. package/dist/review/store.js.map +1 -0
  469. package/dist/review/types.d.ts +77 -0
  470. package/dist/review/types.d.ts.map +1 -0
  471. package/dist/review/types.js +2 -0
  472. package/dist/review/types.js.map +1 -0
  473. package/dist/secrets/routes.d.ts +9 -9
  474. package/dist/server/action-discovery.d.ts.map +1 -1
  475. package/dist/server/action-discovery.js +54 -0
  476. package/dist/server/action-discovery.js.map +1 -1
  477. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  478. package/dist/server/agent-chat-plugin.js +5 -0
  479. package/dist/server/agent-chat-plugin.js.map +1 -1
  480. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  481. package/dist/server/agent-engine-api-key-route.d.ts.map +1 -1
  482. package/dist/server/agent-engine-api-key-route.js +5 -0
  483. package/dist/server/agent-engine-api-key-route.js.map +1 -1
  484. package/dist/server/credential-provider.d.ts +28 -0
  485. package/dist/server/credential-provider.d.ts.map +1 -1
  486. package/dist/server/credential-provider.js +92 -0
  487. package/dist/server/credential-provider.js.map +1 -1
  488. package/dist/setup-connections/index.d.ts +6 -0
  489. package/dist/setup-connections/index.d.ts.map +1 -0
  490. package/dist/setup-connections/index.js +6 -0
  491. package/dist/setup-connections/index.js.map +1 -0
  492. package/dist/setup-connections/onboarding.d.ts +14 -0
  493. package/dist/setup-connections/onboarding.d.ts.map +1 -0
  494. package/dist/setup-connections/onboarding.js +23 -0
  495. package/dist/setup-connections/onboarding.js.map +1 -0
  496. package/dist/transcription/builder-transcription.d.ts +1 -0
  497. package/dist/transcription/builder-transcription.d.ts.map +1 -1
  498. package/dist/transcription/builder-transcription.js +5 -2
  499. package/dist/transcription/builder-transcription.js.map +1 -1
  500. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  501. package/dist/vite/action-types-plugin.js +52 -0
  502. package/dist/vite/action-types-plugin.js.map +1 -1
  503. package/docs/content/agent-native-toolkit.mdx +87 -80
  504. package/docs/content/locales/ar-SA/agent-native-toolkit.mdx +89 -80
  505. package/docs/content/locales/de-DE/agent-native-toolkit.mdx +89 -80
  506. package/docs/content/locales/es-ES/agent-native-toolkit.mdx +89 -80
  507. package/docs/content/locales/fr-FR/agent-native-toolkit.mdx +89 -80
  508. package/docs/content/locales/hi-IN/agent-native-toolkit.mdx +89 -80
  509. package/docs/content/locales/ja-JP/agent-native-toolkit.mdx +89 -80
  510. package/docs/content/locales/ko-KR/agent-native-toolkit.mdx +89 -80
  511. package/docs/content/locales/pt-BR/agent-native-toolkit.mdx +89 -80
  512. package/docs/content/locales/zh-CN/agent-native-toolkit.mdx +89 -80
  513. package/docs/content/locales/zh-TW/agent-native-toolkit.mdx +89 -80
  514. package/docs/content/toolkit-agent-ux.mdx +43 -0
  515. package/docs/content/toolkit-app-adapters.mdx +9 -0
  516. package/docs/content/toolkit-collaboration-ui.mdx +12 -0
  517. package/docs/content/toolkit-collaboration.mdx +74 -0
  518. package/docs/content/toolkit-command-navigation.mdx +106 -0
  519. package/docs/content/toolkit-comments-review.mdx +98 -0
  520. package/docs/content/toolkit-history.mdx +95 -0
  521. package/docs/content/toolkit-observability.mdx +41 -0
  522. package/docs/content/toolkit-org-team.mdx +80 -0
  523. package/docs/content/toolkit-resources.mdx +57 -0
  524. package/docs/content/toolkit-settings.mdx +65 -0
  525. package/docs/content/toolkit-setup-connections.mdx +109 -0
  526. package/docs/content/toolkit-sharing-ui.mdx +18 -6
  527. package/docs/content/toolkit-sharing.mdx +81 -0
  528. package/docs/content/toolkit-shell-hooks.mdx +9 -0
  529. package/docs/content/toolkit-ui.mdx +9 -0
  530. package/package.json +36 -2
@@ -6,13 +6,15 @@ import {
6
6
  IconSearch,
7
7
  IconTerminal2,
8
8
  } from "@tabler/icons-react";
9
- import { type ReactNode, useEffect, useMemo, useRef, useState } from "react";
10
-
11
9
  import {
12
- Collapsible,
13
- CollapsibleContent,
14
- CollapsibleTrigger,
15
- } from "@/components/ui/collapsible";
10
+ type ReactNode,
11
+ type PointerEvent as ReactPointerEvent,
12
+ useEffect,
13
+ useMemo,
14
+ useRef,
15
+ useState,
16
+ } from "react";
17
+
16
18
  import { Input } from "@/components/ui/input";
17
19
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
18
20
  import { cn } from "@/lib/utils";
@@ -34,14 +36,22 @@ import {
34
36
 
35
37
  /** Pause row auto-follow for a while after the user scrolls the list. */
36
38
  const MANUAL_SCROLL_FOLLOW_PAUSE_MS = 4000;
39
+ const DEVTOOLS_ROW_HEIGHT = 34;
40
+ const DEVTOOLS_OVERSCAN_ROWS = 10;
41
+ const DEVTOOLS_MIN_HEIGHT = 180;
42
+ const DEVTOOLS_MAX_HEIGHT = 620;
37
43
 
38
44
  export function SessionDevToolsPanel({
39
45
  diagnostics,
40
46
  currentTime,
47
+ height,
48
+ onHeightChange,
41
49
  onSeek,
42
50
  }: {
43
51
  diagnostics: ReplayDevToolsDiagnostics;
44
52
  currentTime: number;
53
+ height: number;
54
+ onHeightChange: (height: number) => void;
45
55
  onSeek: (ms: number) => void;
46
56
  }) {
47
57
  const t = useT();
@@ -50,6 +60,12 @@ export function SessionDevToolsPanel({
50
60
  const [consoleQuery, setConsoleQuery] = useState("");
51
61
  const [networkKind, setNetworkKind] = useState<NetworkKindFilter>("all");
52
62
  const [networkQuery, setNetworkQuery] = useState("");
63
+ const [selectedConsoleId, setSelectedConsoleId] = useState<string | null>(
64
+ null,
65
+ );
66
+ const [selectedNetworkId, setSelectedNetworkId] = useState<string | null>(
67
+ null,
68
+ );
53
69
 
54
70
  const filteredConsole = useMemo(
55
71
  () => filterConsoleEntries(diagnostics.console, consoleLevel, consoleQuery),
@@ -71,6 +87,29 @@ export function SessionDevToolsPanel({
71
87
  ?.id ?? null)
72
88
  : null;
73
89
 
90
+ const selectedConsole =
91
+ filteredConsole.find((entry) => entry.id === selectedConsoleId) ?? null;
92
+ const selectedNetwork =
93
+ filteredNetwork.find((entry) => entry.id === selectedNetworkId) ?? null;
94
+
95
+ useEffect(() => {
96
+ if (
97
+ selectedConsoleId &&
98
+ !filteredConsole.some((entry) => entry.id === selectedConsoleId)
99
+ ) {
100
+ setSelectedConsoleId(null);
101
+ }
102
+ }, [filteredConsole, selectedConsoleId]);
103
+
104
+ useEffect(() => {
105
+ if (
106
+ selectedNetworkId &&
107
+ !filteredNetwork.some((entry) => entry.id === selectedNetworkId)
108
+ ) {
109
+ setSelectedNetworkId(null);
110
+ }
111
+ }, [filteredNetwork, selectedNetworkId]);
112
+
74
113
  const consoleLevelCounts = useMemo(() => {
75
114
  const counts = { log: 0, info: 0, warn: 0, error: 0 };
76
115
  for (const entry of diagnostics.console) {
@@ -89,12 +128,17 @@ export function SessionDevToolsPanel({
89
128
  }, [diagnostics.network]);
90
129
 
91
130
  return (
92
- <div className="analytics-session-devtools shrink-0 border-t">
131
+ <div
132
+ className="analytics-session-devtools relative flex min-h-0 shrink-0 flex-col border-t bg-background"
133
+ style={{ height }}
134
+ >
135
+ <DevToolsResizeHandle height={height} onHeightChange={onHeightChange} />
93
136
  <Tabs
94
137
  value={tab}
95
138
  onValueChange={(value) => setTab(value as "console" | "network")}
139
+ className="flex min-h-0 flex-1 flex-col"
96
140
  >
97
- <div className="flex items-center gap-2 px-3 pt-2">
141
+ <div className="flex shrink-0 items-center gap-2 px-3 pt-2">
98
142
  <TabsList className="h-8 p-0.5">
99
143
  <TabsTrigger value="console" className="h-7 gap-1.5 px-2.5 text-xs">
100
144
  <IconTerminal2 className="h-3.5 w-3.5" />
@@ -117,8 +161,11 @@ export function SessionDevToolsPanel({
117
161
  </TabsList>
118
162
  </div>
119
163
 
120
- <TabsContent value="console" className="mt-0">
121
- <div className="flex flex-wrap items-center gap-1.5 px-3 py-2">
164
+ <TabsContent
165
+ value="console"
166
+ className="mt-0 flex min-h-0 flex-1 flex-col"
167
+ >
168
+ <div className="flex shrink-0 flex-wrap items-center gap-1.5 px-3 py-2">
122
169
  <FilterChip
123
170
  label={t("sessions.devtoolsFilterAll", {
124
171
  count: String(diagnostics.console.length),
@@ -162,30 +209,38 @@ export function SessionDevToolsPanel({
162
209
  placeholder={t("sessions.devtoolsConsoleSearch")}
163
210
  />
164
211
  </div>
165
- <DevToolsScrollArea activeEntryId={activeConsoleId}>
166
- {filteredConsole.length ? (
167
- filteredConsole.map((entry) => (
168
- <ConsoleRow
169
- key={entry.id}
170
- entry={entry}
171
- active={entry.id === activeConsoleId}
172
- onSeek={onSeek}
173
- />
174
- ))
175
- ) : (
176
- <DevToolsEmptyState
177
- message={
178
- diagnostics.console.length
179
- ? t("sessions.devtoolsNoConsoleMatches")
180
- : t("sessions.devtoolsNoConsole")
212
+ <VirtualizedDevToolsList
213
+ entries={filteredConsole}
214
+ activeEntryId={activeConsoleId}
215
+ emptyMessage={
216
+ diagnostics.console.length
217
+ ? t("sessions.devtoolsNoConsoleMatches")
218
+ : t("sessions.devtoolsNoConsole")
219
+ }
220
+ renderRow={(entry) => (
221
+ <ConsoleRow
222
+ entry={entry}
223
+ active={entry.id === activeConsoleId}
224
+ selected={entry.id === selectedConsoleId}
225
+ onSelect={() =>
226
+ setSelectedConsoleId((current) =>
227
+ current === entry.id ? null : entry.id,
228
+ )
181
229
  }
230
+ onSeek={onSeek}
182
231
  />
183
232
  )}
184
- </DevToolsScrollArea>
233
+ />
234
+ {selectedConsole ? (
235
+ <ConsoleDetailPane entry={selectedConsole} onSeek={onSeek} />
236
+ ) : null}
185
237
  </TabsContent>
186
238
 
187
- <TabsContent value="network" className="mt-0">
188
- <div className="flex flex-wrap items-center gap-1.5 px-3 py-2">
239
+ <TabsContent
240
+ value="network"
241
+ className="mt-0 flex min-h-0 flex-1 flex-col"
242
+ >
243
+ <div className="flex shrink-0 flex-wrap items-center gap-1.5 px-3 py-2">
189
244
  <FilterChip
190
245
  label={t("sessions.devtoolsFilterAll", {
191
246
  count: String(diagnostics.network.length),
@@ -221,69 +276,188 @@ export function SessionDevToolsPanel({
221
276
  placeholder={t("sessions.devtoolsNetworkSearch")}
222
277
  />
223
278
  </div>
224
- <DevToolsScrollArea activeEntryId={activeNetworkId}>
225
- {filteredNetwork.length ? (
226
- filteredNetwork.map((entry) => (
227
- <NetworkRow
228
- key={entry.id}
229
- entry={entry}
230
- active={entry.id === activeNetworkId}
231
- onSeek={onSeek}
232
- />
233
- ))
234
- ) : (
235
- <DevToolsEmptyState
236
- message={
237
- diagnostics.network.length
238
- ? t("sessions.devtoolsNoNetworkMatches")
239
- : t("sessions.devtoolsNoNetwork")
279
+ <VirtualizedDevToolsList
280
+ entries={filteredNetwork}
281
+ activeEntryId={activeNetworkId}
282
+ emptyMessage={
283
+ diagnostics.network.length
284
+ ? t("sessions.devtoolsNoNetworkMatches")
285
+ : t("sessions.devtoolsNoNetwork")
286
+ }
287
+ renderRow={(entry) => (
288
+ <NetworkRow
289
+ entry={entry}
290
+ active={entry.id === activeNetworkId}
291
+ selected={entry.id === selectedNetworkId}
292
+ onSelect={() =>
293
+ setSelectedNetworkId((current) =>
294
+ current === entry.id ? null : entry.id,
295
+ )
240
296
  }
297
+ onSeek={onSeek}
241
298
  />
242
299
  )}
243
- </DevToolsScrollArea>
300
+ />
301
+ {selectedNetwork ? (
302
+ <NetworkDetailPane entry={selectedNetwork} onSeek={onSeek} />
303
+ ) : null}
244
304
  </TabsContent>
245
305
  </Tabs>
246
306
  </div>
247
307
  );
248
308
  }
249
309
 
250
- function DevToolsScrollArea({
310
+ function DevToolsResizeHandle({
311
+ height,
312
+ onHeightChange,
313
+ }: {
314
+ height: number;
315
+ onHeightChange: (height: number) => void;
316
+ }) {
317
+ const t = useT();
318
+
319
+ function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {
320
+ event.preventDefault();
321
+ const startY = event.clientY;
322
+ const startHeight = height;
323
+
324
+ function handlePointerMove(moveEvent: PointerEvent) {
325
+ onHeightChange(
326
+ clamp(
327
+ startHeight - (moveEvent.clientY - startY),
328
+ DEVTOOLS_MIN_HEIGHT,
329
+ DEVTOOLS_MAX_HEIGHT,
330
+ ),
331
+ );
332
+ }
333
+
334
+ function handlePointerUp() {
335
+ window.removeEventListener("pointermove", handlePointerMove);
336
+ window.removeEventListener("pointerup", handlePointerUp);
337
+ }
338
+
339
+ window.addEventListener("pointermove", handlePointerMove);
340
+ window.addEventListener("pointerup", handlePointerUp, { once: true });
341
+ }
342
+
343
+ return (
344
+ <div
345
+ role="separator"
346
+ aria-label={t("sessions.devtoolsResize")}
347
+ aria-orientation="horizontal"
348
+ aria-valuemin={DEVTOOLS_MIN_HEIGHT}
349
+ aria-valuemax={DEVTOOLS_MAX_HEIGHT}
350
+ aria-valuenow={Math.round(height)}
351
+ className="absolute inset-x-0 -top-1 z-10 flex h-2 cursor-row-resize items-center justify-center"
352
+ onPointerDown={handlePointerDown}
353
+ >
354
+ <span className="h-0.5 w-9 rounded-full bg-border opacity-0 transition-opacity hover:opacity-100" />
355
+ </div>
356
+ );
357
+ }
358
+
359
+ function VirtualizedDevToolsList<T extends { id: string }>({
360
+ entries,
251
361
  activeEntryId,
252
- children,
362
+ emptyMessage,
363
+ renderRow,
253
364
  }: {
365
+ entries: T[];
254
366
  activeEntryId: string | null;
255
- children: ReactNode;
367
+ emptyMessage: string;
368
+ renderRow: (entry: T) => ReactNode;
256
369
  }) {
257
370
  const containerRef = useRef<HTMLDivElement>(null);
258
371
  const lastManualScrollAtRef = useRef(0);
372
+ const [scrollTop, setScrollTop] = useState(0);
373
+ const [viewportHeight, setViewportHeight] = useState(0);
374
+
375
+ const activeIndex = activeEntryId
376
+ ? entries.findIndex((entry) => entry.id === activeEntryId)
377
+ : -1;
378
+
379
+ useEffect(() => {
380
+ const el = containerRef.current;
381
+ if (!el) return;
382
+ const update = () => setViewportHeight(el.clientHeight);
383
+ update();
384
+ const observer = new ResizeObserver(update);
385
+ observer.observe(el);
386
+ return () => observer.disconnect();
387
+ }, []);
259
388
 
260
389
  useEffect(() => {
261
- if (!activeEntryId) return;
390
+ if (activeIndex < 0) return;
262
391
  if (
263
392
  Date.now() - lastManualScrollAtRef.current <
264
393
  MANUAL_SCROLL_FOLLOW_PAUSE_MS
265
394
  ) {
266
395
  return;
267
396
  }
268
- const row = containerRef.current?.querySelector(
269
- `[data-entry-id="${activeEntryId}"]`,
270
- );
271
- row?.scrollIntoView({ block: "nearest" });
272
- }, [activeEntryId]);
397
+ const el = containerRef.current;
398
+ if (!el) return;
399
+ const rowTop = activeIndex * DEVTOOLS_ROW_HEIGHT;
400
+ const rowBottom = rowTop + DEVTOOLS_ROW_HEIGHT;
401
+ if (rowTop >= el.scrollTop && rowBottom <= el.scrollTop + el.clientHeight) {
402
+ return;
403
+ }
404
+ el.scrollTo({
405
+ top: Math.max(0, rowTop - el.clientHeight / 2 + DEVTOOLS_ROW_HEIGHT),
406
+ });
407
+ }, [activeIndex, entries.length]);
273
408
 
274
409
  const markManualScroll = () => {
275
410
  lastManualScrollAtRef.current = Date.now();
276
411
  };
277
412
 
413
+ if (!entries.length) {
414
+ return (
415
+ <div className="min-h-0 flex-1 overflow-y-auto border-t">
416
+ <DevToolsEmptyState message={emptyMessage} />
417
+ </div>
418
+ );
419
+ }
420
+
421
+ const measuredHeight = viewportHeight || 240;
422
+ const startIndex = clamp(
423
+ Math.floor(scrollTop / DEVTOOLS_ROW_HEIGHT) - DEVTOOLS_OVERSCAN_ROWS,
424
+ 0,
425
+ entries.length,
426
+ );
427
+ const endIndex = clamp(
428
+ Math.ceil((scrollTop + measuredHeight) / DEVTOOLS_ROW_HEIGHT) +
429
+ DEVTOOLS_OVERSCAN_ROWS,
430
+ startIndex,
431
+ entries.length,
432
+ );
433
+ const visibleEntries = entries.slice(startIndex, endIndex);
434
+
278
435
  return (
279
436
  <div
280
437
  ref={containerRef}
281
- className="max-h-56 overflow-y-auto border-t"
438
+ className="min-h-0 flex-1 overflow-y-auto border-t"
439
+ onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}
282
440
  onWheel={markManualScroll}
283
441
  onPointerDown={markManualScroll}
284
442
  onTouchMove={markManualScroll}
285
443
  >
286
- {children}
444
+ <div
445
+ className="relative"
446
+ style={{ height: entries.length * DEVTOOLS_ROW_HEIGHT }}
447
+ >
448
+ {visibleEntries.map((entry, offset) => (
449
+ <div
450
+ key={entry.id}
451
+ className="absolute inset-x-0"
452
+ style={{
453
+ height: DEVTOOLS_ROW_HEIGHT,
454
+ top: (startIndex + offset) * DEVTOOLS_ROW_HEIGHT,
455
+ }}
456
+ >
457
+ {renderRow(entry)}
458
+ </div>
459
+ ))}
460
+ </div>
287
461
  </div>
288
462
  );
289
463
  }
@@ -379,32 +553,39 @@ function JumpToButton({
379
553
  function ConsoleRow({
380
554
  entry,
381
555
  active,
556
+ selected,
557
+ onSelect,
382
558
  onSeek,
383
559
  }: {
384
560
  entry: ReplayConsoleEntry;
385
561
  active: boolean;
562
+ selected: boolean;
563
+ onSelect: () => void;
386
564
  onSeek: (ms: number) => void;
387
565
  }) {
388
- const t = useT();
389
- const [open, setOpen] = useState(false);
390
- const hasDetail = Boolean(entry.stack || entry.args.length > 1 || entry.url);
391
566
  const bucket = consoleLevelBucket(entry.level);
392
567
 
393
568
  return (
394
- <Collapsible open={open} onOpenChange={setOpen}>
395
- <div
396
- data-entry-id={entry.id}
397
- className={cn(
398
- "group flex items-start gap-2 border-b px-3 py-1.5 transition-colors last:border-b-0 hover:bg-muted/50",
399
- active && "bg-muted",
400
- )}
569
+ <div
570
+ data-entry-id={entry.id}
571
+ className={cn(
572
+ "group flex h-full items-center gap-2 border-b px-3 transition-colors hover:bg-muted/50",
573
+ active && "bg-muted",
574
+ selected && "bg-muted/80",
575
+ )}
576
+ >
577
+ <button
578
+ type="button"
579
+ className="flex min-w-0 flex-1 items-center gap-2 text-left"
580
+ aria-expanded={selected}
581
+ onClick={onSelect}
401
582
  >
402
- <span className="mt-0.5 w-10 shrink-0 font-mono text-[11px] text-muted-foreground">
583
+ <span className="w-10 shrink-0 font-mono text-[11px] text-muted-foreground">
403
584
  {formatOffsetClock(entry.offsetMs)}
404
585
  </span>
405
586
  <span
406
587
  className={cn(
407
- "mt-1.5 h-2 w-2 shrink-0 rounded-full",
588
+ "h-2 w-2 shrink-0 rounded-full",
408
589
  bucket === "error" && "bg-red-500",
409
590
  bucket === "warn" && "bg-amber-500",
410
591
  bucket === "info" && "bg-sky-500",
@@ -412,109 +593,69 @@ function ConsoleRow({
412
593
  )}
413
594
  aria-hidden
414
595
  />
415
- <span className="min-w-0 flex-1">
416
- <span
417
- className={cn(
418
- "block truncate font-mono text-xs",
419
- bucket === "error" && "text-red-600 dark:text-red-400",
420
- bucket === "warn" && "text-amber-600 dark:text-amber-400",
421
- bucket !== "error" && bucket !== "warn" && "text-foreground/80",
422
- )}
423
- title={entry.message}
424
- >
425
- {entry.message}
426
- </span>
596
+ <span
597
+ className={cn(
598
+ "min-w-0 flex-1 truncate font-mono text-xs",
599
+ bucket === "error" && "text-red-600 dark:text-red-400",
600
+ bucket === "warn" && "text-amber-600 dark:text-amber-400",
601
+ bucket !== "error" && bucket !== "warn" && "text-foreground/80",
602
+ )}
603
+ title={entry.message}
604
+ >
605
+ {entry.message || entry.level}
427
606
  </span>
428
607
  {entry.repeat > 1 ? (
429
- <span className="mt-0.5 inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 font-mono text-[10px] text-muted-foreground">
430
- {t("sessions.devtoolsRepeatCount", {
431
- count: String(entry.repeat),
432
- })}
608
+ <span className="inline-flex shrink-0 items-center rounded-full bg-muted px-1.5 font-mono text-[10px] text-muted-foreground">
609
+ x{entry.repeat}
433
610
  </span>
434
611
  ) : null}
435
612
  {entry.source !== "console" ? (
436
- <span className="mt-0.5 inline-flex shrink-0 items-center rounded border px-1 font-mono text-[10px] text-muted-foreground">
613
+ <span className="hidden shrink-0 rounded border px-1 font-mono text-[10px] text-muted-foreground sm:inline-flex">
437
614
  {entry.source}
438
615
  </span>
439
616
  ) : null}
440
- <JumpToButton offsetMs={entry.offsetMs} onSeek={onSeek} />
441
- {hasDetail ? (
442
- <CollapsibleTrigger asChild>
443
- <button
444
- type="button"
445
- className="mt-0.5 shrink-0 rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
446
- aria-label={t("sessions.devtoolsToggleDetails")}
447
- >
448
- <IconChevronRight
449
- className={cn(
450
- "h-3.5 w-3.5 transition-transform rtl:-scale-x-100",
451
- open && "rotate-90 rtl:scale-x-100",
452
- )}
453
- />
454
- </button>
455
- </CollapsibleTrigger>
456
- ) : null}
457
- </div>
458
- {hasDetail ? (
459
- <CollapsibleContent>
460
- <div className="space-y-2 border-b bg-muted/30 px-3 py-2 ps-[3.75rem]">
461
- {entry.url ? (
462
- <p
463
- className="truncate font-mono text-[11px] text-muted-foreground"
464
- title={entry.url}
465
- >
466
- {entry.url}
467
- </p>
468
- ) : null}
469
- {entry.args.length > 1 ? (
470
- <div>
471
- <p className="mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
472
- {t("sessions.devtoolsArgs")}
473
- </p>
474
- <pre className="overflow-x-auto whitespace-pre-wrap break-all font-mono text-[11px] text-foreground/80">
475
- {entry.args.join("\n")}
476
- </pre>
477
- </div>
478
- ) : null}
479
- {entry.stack ? (
480
- <div>
481
- <p className="mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
482
- {t("sessions.devtoolsStack")}
483
- </p>
484
- <pre className="max-h-40 overflow-auto whitespace-pre-wrap break-all font-mono text-[11px] text-muted-foreground">
485
- {entry.stack}
486
- </pre>
487
- </div>
488
- ) : null}
489
- </div>
490
- </CollapsibleContent>
491
- ) : null}
492
- </Collapsible>
617
+ <IconChevronRight
618
+ className={cn(
619
+ "h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform rtl:-scale-x-100",
620
+ selected && "rotate-90 rtl:scale-x-100",
621
+ )}
622
+ />
623
+ </button>
624
+ <JumpToButton offsetMs={entry.offsetMs} onSeek={onSeek} />
625
+ </div>
493
626
  );
494
627
  }
495
628
 
496
629
  function NetworkRow({
497
630
  entry,
498
631
  active,
632
+ selected,
633
+ onSelect,
499
634
  onSeek,
500
635
  }: {
501
636
  entry: ReplayNetworkEntry;
502
637
  active: boolean;
638
+ selected: boolean;
639
+ onSelect: () => void;
503
640
  onSeek: (ms: number) => void;
504
641
  }) {
505
642
  const t = useT();
506
- const [open, setOpen] = useState(false);
507
- const hasDetail = Boolean(entry.responseBody);
508
643
  const displayUrl = middleTruncate(networkDisplayUrl(entry.url), 72);
509
644
 
510
645
  return (
511
- <Collapsible open={open} onOpenChange={setOpen}>
512
- <div
513
- data-entry-id={entry.id}
514
- className={cn(
515
- "group flex items-center gap-2 border-b px-3 py-1.5 transition-colors last:border-b-0 hover:bg-muted/50",
516
- active && "bg-muted",
517
- )}
646
+ <div
647
+ data-entry-id={entry.id}
648
+ className={cn(
649
+ "group flex h-full items-center gap-2 border-b px-3 transition-colors hover:bg-muted/50",
650
+ active && "bg-muted",
651
+ selected && "bg-muted/80",
652
+ )}
653
+ >
654
+ <button
655
+ type="button"
656
+ className="flex min-w-0 flex-1 items-center gap-2 text-left"
657
+ aria-expanded={selected}
658
+ onClick={onSelect}
518
659
  >
519
660
  <span className="w-10 shrink-0 font-mono text-[11px] text-muted-foreground">
520
661
  {formatOffsetClock(entry.offsetMs)}
@@ -532,7 +673,7 @@ function NetworkRow({
532
673
  <span className="w-12 shrink-0 font-mono text-[11px] text-muted-foreground">
533
674
  {entry.method}
534
675
  </span>
535
- <span className="w-10 shrink-0 font-mono text-[10px] uppercase text-muted-foreground/70">
676
+ <span className="hidden w-10 shrink-0 font-mono text-[10px] uppercase text-muted-foreground/70 sm:inline">
536
677
  {entry.api === "xhr" ? "XHR" : "fetch"}
537
678
  </span>
538
679
  <span
@@ -543,7 +684,7 @@ function NetworkRow({
543
684
  </span>
544
685
  {entry.error ? (
545
686
  <span
546
- className="max-w-32 shrink-0 truncate font-mono text-[11px] text-red-600 dark:text-red-400"
687
+ className="hidden max-w-32 shrink-0 truncate font-mono text-[11px] text-red-600 dark:text-red-400 lg:inline"
547
688
  title={entry.error}
548
689
  >
549
690
  {entry.error}
@@ -554,40 +695,182 @@ function NetworkRow({
554
695
  ms: String(entry.durationMs),
555
696
  })}
556
697
  </span>
557
- <JumpToButton offsetMs={entry.offsetMs} onSeek={onSeek} />
558
- {hasDetail ? (
559
- <CollapsibleTrigger asChild>
560
- <button
561
- type="button"
562
- className="mt-0.5 shrink-0 rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
563
- aria-label={t("sessions.devtoolsToggleDetails")}
564
- >
565
- <IconChevronRight
566
- className={cn(
567
- "h-3.5 w-3.5 transition-transform rtl:-scale-x-100",
568
- open && "rotate-90 rtl:scale-x-100",
569
- )}
570
- />
571
- </button>
572
- </CollapsibleTrigger>
573
- ) : null}
698
+ <IconChevronRight
699
+ className={cn(
700
+ "h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform rtl:-scale-x-100",
701
+ selected && "rotate-90 rtl:scale-x-100",
702
+ )}
703
+ />
704
+ </button>
705
+ <JumpToButton offsetMs={entry.offsetMs} onSeek={onSeek} />
706
+ </div>
707
+ );
708
+ }
709
+
710
+ function ConsoleDetailPane({
711
+ entry,
712
+ onSeek,
713
+ }: {
714
+ entry: ReplayConsoleEntry;
715
+ onSeek: (ms: number) => void;
716
+ }) {
717
+ const t = useT();
718
+ return (
719
+ <DevToolsDetailPane
720
+ title={`${entry.level} at ${formatOffsetClock(entry.offsetMs)}`}
721
+ onSeek={() => onSeek(entry.offsetMs)}
722
+ >
723
+ <DetailField label={t("sessions.devtoolsMessage")}>
724
+ <pre className="whitespace-pre-wrap break-all font-mono text-[11px] text-foreground/85">
725
+ {entry.message || entry.level}
726
+ </pre>
727
+ </DetailField>
728
+ {entry.url ? (
729
+ <DetailField label={t("sessions.url")}>
730
+ <p className="break-all font-mono text-[11px] text-muted-foreground">
731
+ {entry.url}
732
+ </p>
733
+ </DetailField>
734
+ ) : null}
735
+ {entry.args.length ? (
736
+ <DetailField label={t("sessions.devtoolsArgs")}>
737
+ <pre className="whitespace-pre-wrap break-all font-mono text-[11px] text-muted-foreground">
738
+ {entry.args.join("\n")}
739
+ </pre>
740
+ </DetailField>
741
+ ) : null}
742
+ {entry.stack ? (
743
+ <DetailField label={t("sessions.devtoolsStack")}>
744
+ <pre className="max-h-32 overflow-auto whitespace-pre-wrap break-all font-mono text-[11px] text-muted-foreground">
745
+ {entry.stack}
746
+ </pre>
747
+ </DetailField>
748
+ ) : null}
749
+ </DevToolsDetailPane>
750
+ );
751
+ }
752
+
753
+ function NetworkDetailPane({
754
+ entry,
755
+ onSeek,
756
+ }: {
757
+ entry: ReplayNetworkEntry;
758
+ onSeek: (ms: number) => void;
759
+ }) {
760
+ const t = useT();
761
+ return (
762
+ <DevToolsDetailPane
763
+ title={`${entry.method} ${entry.status > 0 ? entry.status : t("sessions.devtoolsFailedStatus")}`}
764
+ onSeek={() => onSeek(entry.offsetMs)}
765
+ >
766
+ <div className="grid gap-2 sm:grid-cols-2">
767
+ <DetailValue
768
+ label={t("sessions.time")}
769
+ value={formatOffsetClock(entry.offsetMs)}
770
+ />
771
+ <DetailValue
772
+ label="API"
773
+ value={entry.api === "xhr" ? "XHR" : "fetch"}
774
+ />
775
+ <DetailValue
776
+ label="Status"
777
+ value={
778
+ entry.status > 0
779
+ ? String(entry.status)
780
+ : t("sessions.devtoolsFailedStatus")
781
+ }
782
+ />
783
+ <DetailValue
784
+ label="Duration"
785
+ value={t("sessions.devtoolsDurationMs", {
786
+ ms: String(entry.durationMs),
787
+ })}
788
+ />
574
789
  </div>
575
- {hasDetail ? (
576
- <CollapsibleContent>
577
- <div className="space-y-2 border-b bg-muted/30 px-3 py-2 ps-[3.75rem]">
578
- {entry.responseBody ? (
579
- <div>
580
- <p className="mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
581
- {t("sessions.devtoolsResponseBody")}
582
- </p>
583
- <pre className="max-h-40 overflow-auto whitespace-pre-wrap break-all font-mono text-[11px] text-muted-foreground">
584
- {entry.responseBody}
585
- </pre>
586
- </div>
587
- ) : null}
588
- </div>
589
- </CollapsibleContent>
790
+ <DetailField label={t("sessions.url")}>
791
+ <p className="break-all font-mono text-[11px] text-muted-foreground">
792
+ {entry.url}
793
+ </p>
794
+ </DetailField>
795
+ {entry.error ? (
796
+ <DetailField label="Error">
797
+ <pre className="whitespace-pre-wrap break-all font-mono text-[11px] text-red-600 dark:text-red-400">
798
+ {entry.error}
799
+ </pre>
800
+ </DetailField>
801
+ ) : null}
802
+ {entry.responseBody ? (
803
+ <DetailField label={t("sessions.devtoolsResponseBody")}>
804
+ <pre className="max-h-32 overflow-auto whitespace-pre-wrap break-all font-mono text-[11px] text-muted-foreground">
805
+ {entry.responseBody}
806
+ </pre>
807
+ </DetailField>
590
808
  ) : null}
591
- </Collapsible>
809
+ </DevToolsDetailPane>
810
+ );
811
+ }
812
+
813
+ function DevToolsDetailPane({
814
+ title,
815
+ onSeek,
816
+ children,
817
+ }: {
818
+ title: string;
819
+ onSeek: () => void;
820
+ children: ReactNode;
821
+ }) {
822
+ const t = useT();
823
+ return (
824
+ <div className="max-h-44 shrink-0 overflow-auto border-t bg-muted/25 px-3 py-2">
825
+ <div className="mb-2 flex items-center justify-between gap-3">
826
+ <p className="truncate text-xs font-semibold text-foreground">
827
+ {title}
828
+ </p>
829
+ <button
830
+ type="button"
831
+ className="inline-flex shrink-0 items-center gap-1 rounded border px-1.5 py-0.5 text-[11px] font-medium text-muted-foreground hover:bg-muted hover:text-foreground"
832
+ onClick={onSeek}
833
+ >
834
+ <IconPlayerPlay className="h-3 w-3" />
835
+ {t("sessions.devtoolsJumpTo")}
836
+ </button>
837
+ </div>
838
+ <div className="space-y-2">{children}</div>
839
+ </div>
592
840
  );
593
841
  }
842
+
843
+ function DetailValue({ label, value }: { label: string; value: string }) {
844
+ return (
845
+ <div>
846
+ <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
847
+ {label}
848
+ </p>
849
+ <p className="mt-0.5 truncate font-mono text-[11px] text-foreground/80">
850
+ {value}
851
+ </p>
852
+ </div>
853
+ );
854
+ }
855
+
856
+ function DetailField({
857
+ label,
858
+ children,
859
+ }: {
860
+ label: string;
861
+ children: ReactNode;
862
+ }) {
863
+ return (
864
+ <div>
865
+ <p className="mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
866
+ {label}
867
+ </p>
868
+ {children}
869
+ </div>
870
+ );
871
+ }
872
+
873
+ function clamp(value: number, min: number, max: number): number {
874
+ if (!Number.isFinite(value)) return min;
875
+ return Math.min(max, Math.max(min, value));
876
+ }