@kortix/ui 0.14.8 → 0.14.9

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 (528) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +63 -3
  3. package/dist/_vendor/shared/app-config.d.ts +175 -0
  4. package/dist/_vendor/shared/channel-message.d.ts +34 -5
  5. package/dist/_vendor/shared/index.d.ts +1 -0
  6. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  7. package/dist/access/access/access-detail-shell.js +1 -1
  8. package/dist/access/access/principal-picker.d.ts +11 -0
  9. package/dist/access/access/principal-picker.js +3 -2
  10. package/dist/apps/app-preview-pool.d.ts +7 -2
  11. package/dist/apps/app-preview-pool.js +11 -5
  12. package/dist/apps/app-shared.d.ts +22 -15
  13. package/dist/apps/app-shared.js +37 -19
  14. package/dist/apps/index.d.ts +2 -2
  15. package/dist/apps/index.js +2 -2
  16. package/dist/artifacts/artifact-frame.d.ts +16 -0
  17. package/dist/artifacts/artifact-frame.js +51 -0
  18. package/dist/artifacts/artifact-session.d.ts +18 -0
  19. package/dist/artifacts/artifact-session.js +101 -0
  20. package/dist/artifacts/frame-policy.d.ts +30 -0
  21. package/dist/artifacts/frame-policy.js +61 -0
  22. package/dist/artifacts/index.d.ts +3 -0
  23. package/dist/artifacts/index.js +5 -0
  24. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  25. package/dist/browser/sandbox-browser-chrome.js +2 -2
  26. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  27. package/dist/customize/agents/agent-grant-pages.js +30 -4
  28. package/dist/customize/agents/agent-page.js +3 -1
  29. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  30. package/dist/customize/agents/agent-policy-sets.js +72 -0
  31. package/dist/customize/agents/agent-triggers-section.js +2 -1
  32. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  33. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  34. package/dist/customize/connectors/agent-access.d.ts +35 -0
  35. package/dist/customize/connectors/agent-access.js +77 -0
  36. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  37. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  38. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  39. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  40. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  41. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  42. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  43. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  44. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  45. package/dist/customize/connectors/connector-identity.js +13 -42
  46. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  47. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  48. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  49. package/dist/customize/connectors/connector-routes.js +29 -20
  50. package/dist/customize/connectors/connectors-page.js +53 -82
  51. package/dist/customize/connectors/detail/app-page.js +226 -98
  52. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  53. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  54. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  55. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  56. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  57. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  58. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  59. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  60. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  61. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  62. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  63. package/dist/customize/connectors/detail/connector-page.js +14 -10
  64. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  65. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  66. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  67. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  68. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  69. package/dist/customize/connectors/detail/connector-status.js +34 -10
  70. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  71. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  72. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  73. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  74. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  75. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  76. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  77. package/dist/customize/connectors/detail/provider-info.js +2 -2
  78. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  79. package/dist/customize/connectors/detail/status-badge.js +4 -5
  80. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  81. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  82. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  83. package/dist/customize/connectors/install/install-dialog.js +40 -0
  84. package/dist/customize/connectors/install/install.d.ts +13 -2
  85. package/dist/customize/connectors/install/install.js +9 -4
  86. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  87. package/dist/customize/connectors/install/use-install.js +65 -37
  88. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  89. package/dist/customize/connectors/install/way-kind.js +16 -0
  90. package/dist/customize/connectors/provider-label.d.ts +2 -1
  91. package/dist/customize/connectors/provider-label.js +13 -3
  92. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  93. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  94. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  95. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  96. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  97. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  98. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  99. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  100. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  101. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  102. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  103. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  104. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  105. package/dist/customize/connectors/use-agent-access.js +72 -0
  106. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  107. package/dist/customize/migrate-to-v2/index.js +1 -2
  108. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -25
  109. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -236
  110. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  111. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  112. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  113. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  114. package/dist/customize/providers/provider-accordion.js +17 -2
  115. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  116. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  117. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  118. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  119. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  120. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  121. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  122. package/dist/customize/sections/component/channel-mocks.js +46 -0
  123. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  124. package/dist/customize/sections/component/channel-row.js +10 -4
  125. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  126. package/dist/customize/sections/component/email-connect-form.js +183 -0
  127. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  128. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  129. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  130. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  131. package/dist/customize/sections/component/telegram-channel-row.js +16 -25
  132. package/dist/customize/sections/connectors-view.d.ts +1 -15
  133. package/dist/customize/sections/connectors-view.js +81 -314
  134. package/dist/customize/sections/view/agent-editor-catalog.js +5 -0
  135. package/dist/customize/sections/view/channels-view.d.ts +5 -1
  136. package/dist/customize/sections/view/channels-view.js +61 -75
  137. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  138. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  139. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +1 -12
  140. package/dist/customize/shared/catalog/catalog-empty-state.js +3 -3
  141. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  142. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  143. package/dist/customize/shared/feature-gate-screen.js +27 -9
  144. package/dist/customize/shared/use-customize-prefetch.d.ts +2 -3
  145. package/dist/customize/shared/use-customize-prefetch.js +9 -27
  146. package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
  147. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  148. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  149. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  150. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  151. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  152. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  153. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  154. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  155. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  156. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  157. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  158. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  159. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  160. package/dist/customize/triggers/schedule-view.js +5 -2
  161. package/dist/files/index.d.ts +1 -0
  162. package/dist/files/index.js +1 -0
  163. package/dist/files/project/change-request-recovery.d.ts +1 -26
  164. package/dist/files/project/change-request-recovery.js +1 -59
  165. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  166. package/dist/files/project/components/drive-explorer.js +15 -15
  167. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  168. package/dist/files/project/components/drive-toolbar.js +14 -5
  169. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  170. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  171. package/dist/files/project/hooks/use-change-requests.js +11 -2
  172. package/dist/files/renderers/image-frame.d.ts +46 -0
  173. package/dist/files/renderers/image-frame.js +59 -0
  174. package/dist/files/renderers/image-renderer.d.ts +11 -1
  175. package/dist/files/renderers/image-renderer.js +13 -3
  176. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  177. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  178. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  179. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  180. package/dist/files/renderers/show-content-renderer.js +56 -14
  181. package/dist/files/runtime/file-source.js +2 -0
  182. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  183. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  184. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  185. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  186. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  187. package/dist/files/viewer/file-content-renderer.js +50 -7
  188. package/dist/files/viewer/file-header.d.ts +7 -3
  189. package/dist/files/viewer/file-header.js +20 -11
  190. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  191. package/dist/files/viewer/file-preview-modal.js +10 -22
  192. package/dist/files/viewer/file-source.d.ts +13 -0
  193. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  194. package/dist/files/viewer/use-file-content-state.js +28 -10
  195. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  196. package/dist/files/viewer/viewer-actions.js +2 -2
  197. package/dist/hooks/use-media-query.d.ts +1 -0
  198. package/dist/hooks/use-mobile.d.ts +5 -0
  199. package/dist/hooks/use-mobile.js +8 -0
  200. package/dist/i18n/en.d.ts +873 -85
  201. package/dist/i18n/en.js +888 -100
  202. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  203. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  204. package/dist/index.d.ts +2 -2
  205. package/dist/index.js +2 -2
  206. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  207. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  208. package/dist/internal/account-hub/hub-sheet.js +21 -5
  209. package/dist/internal/account-hub/sections.d.ts +1 -1
  210. package/dist/internal/account-hub/sections.js +2 -1
  211. package/dist/internal/auth/auth-card-shell.js +3 -3
  212. package/dist/internal/components/agent-mark.js +5 -2
  213. package/dist/internal/connector-logo/connector-logo-source.d.ts +63 -0
  214. package/dist/internal/connector-logo/connector-logo-source.js +48 -0
  215. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  216. package/dist/internal/connector-logo/connector-logo.js +56 -0
  217. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  218. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  219. package/dist/internal/files/file-read-retry.d.ts +13 -0
  220. package/dist/internal/files/file-read-retry.js +23 -3
  221. package/dist/internal/files/session-drive-files.d.ts +5 -1
  222. package/dist/internal/files/session-drive-files.js +7 -2
  223. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  224. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  225. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  226. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  227. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  228. package/dist/internal/hooks/index.d.ts +1 -1
  229. package/dist/internal/hooks/index.js +1 -1
  230. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  231. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  232. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  233. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  234. package/dist/internal/icons/telegram.d.ts +5 -0
  235. package/dist/internal/icons/telegram.js +6 -1
  236. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  237. package/dist/internal/layout/nav-hover-card.js +84 -0
  238. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  239. package/dist/internal/layout/project-nav-row.js +3 -2
  240. package/dist/internal/layout/project-page-header.d.ts +4 -2
  241. package/dist/internal/layout/project-page-header.js +4 -3
  242. package/dist/internal/layout/project-settings-nav.js +59 -2
  243. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  244. package/dist/internal/lib/browser-error-noise.js +1 -1
  245. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  246. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  247. package/dist/internal/lib/manifest-version.d.ts +1 -1
  248. package/dist/internal/lib/manifest-version.js +2 -2
  249. package/dist/internal/lib/memory-href.d.ts +16 -0
  250. package/dist/internal/lib/memory-href.js +46 -0
  251. package/dist/internal/lib/use-project-feature-flags.js +9 -9
  252. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  253. package/dist/internal/lib/utils/heic-convert.js +3 -4
  254. package/dist/internal/lib/web-notifications.d.ts +20 -0
  255. package/dist/internal/lib/web-notifications.js +48 -4
  256. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  257. package/dist/internal/notifications/notification-bell.js +2 -2
  258. package/dist/internal/selection/selection-bar.d.ts +2 -1
  259. package/dist/internal/selection/selection-bar.js +1 -1
  260. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  261. package/dist/internal/stores/file-preview-store.js +19 -1
  262. package/dist/internal/stores/kortix-computer-store.js +3 -0
  263. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  264. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  265. package/dist/lib/routes.d.ts +13 -1
  266. package/dist/lib/routes.js +13 -0
  267. package/dist/markdown/index.d.ts +2 -1
  268. package/dist/markdown/index.js +2 -1
  269. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  270. package/dist/markdown/setup-links/approval-decision.js +6 -2
  271. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  272. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  273. package/dist/markdown/setup-links/secret-intake-form.d.ts +0 -10
  274. package/dist/markdown/setup-links/secret-intake-form.js +1 -1
  275. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  276. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  277. package/dist/markdown/unified-markdown.js +5 -5
  278. package/dist/primitives/badge.d.ts +1 -1
  279. package/dist/primitives/badge.js +2 -0
  280. package/dist/primitives/disclosure.js +14 -2
  281. package/dist/primitives/empty-art.d.ts +12 -0
  282. package/dist/primitives/empty-art.js +11 -0
  283. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  284. package/dist/primitives/mermaid-renderer.js +21 -15
  285. package/dist/primitives/resizable.js +6 -1
  286. package/dist/primitives/resize-seam.d.ts +11 -0
  287. package/dist/primitives/resize-seam.js +12 -0
  288. package/dist/primitives/sidebar-panel.js +4 -7
  289. package/dist/primitives/tabs.d.ts +14 -1
  290. package/dist/primitives/tabs.js +1 -1
  291. package/dist/providers/ui-provider.d.ts +9 -0
  292. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  293. package/dist/session/composer/ComposerAboveCard.js +2 -2
  294. package/dist/session/composer/ComposerCard.d.ts +1 -1
  295. package/dist/session/composer/ComposerCard.js +3 -3
  296. package/dist/session/composer/agent-selector.d.ts +13 -1
  297. package/dist/session/composer/agent-selector.js +25 -5
  298. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  299. package/dist/session/composer/composer-agent-access.js +27 -0
  300. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  301. package/dist/session/composer/composer-chat-input.js +8 -6
  302. package/dist/session/composer/composer-logic.d.ts +16 -0
  303. package/dist/session/composer/composer-logic.js +12 -0
  304. package/dist/session/composer/composer-underbar.d.ts +3 -1
  305. package/dist/session/composer/composer-underbar.js +4 -3
  306. package/dist/session/composer/composer.d.ts +15 -1
  307. package/dist/session/composer/composer.js +19 -1
  308. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  309. package/dist/session/composer/draft/composer-draft.js +5 -1
  310. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  311. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  312. package/dist/session/models/chatgpt-connection-button.js +54 -0
  313. package/dist/session/models/model-selector.js +5 -2
  314. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  315. package/dist/session/models/use-model-connection-gate.js +5 -5
  316. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  317. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  318. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  319. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  320. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  321. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  322. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  323. package/dist/session/panel/easy/app-preview.js +31 -12
  324. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  325. package/dist/session/panel/easy/change-requests-card.js +17 -0
  326. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  327. package/dist/session/panel/easy/easy-panel.js +5 -2
  328. package/dist/session/panel/easy/file-preview.js +1 -1
  329. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  330. package/dist/session/panel/easy/outputs-card.js +3 -2
  331. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  332. package/dist/session/panel/session-audit-panel.js +9 -2
  333. package/dist/session/panel/session-detail-panel.js +9 -3
  334. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  335. package/dist/session/panel/session-files-explorer.js +12 -3
  336. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  337. package/dist/session/panel/session-panel-provider.js +32 -7
  338. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  339. package/dist/session/panel/shared/derive-panels.js +12 -2
  340. package/dist/session/panel/shared/output-priority.js +2 -0
  341. package/dist/session/participants/session-participants.d.ts +5 -1
  342. package/dist/session/participants/session-participants.js +9 -2
  343. package/dist/session/prompts/approval-request.d.ts +5 -0
  344. package/dist/session/prompts/approval-request.js +7 -1
  345. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  346. package/dist/session/prompts/session-approval-review.js +18 -0
  347. package/dist/session/status/session-error-banner.js +2 -49
  348. package/dist/session/status/session-starting-loader.d.ts +14 -2
  349. package/dist/session/status/session-starting-loader.js +16 -4
  350. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  351. package/dist/session/thread/after-first-prompt.js +8 -0
  352. package/dist/session/thread/detect-command.d.ts +12 -0
  353. package/dist/session/thread/detect-command.js +20 -0
  354. package/dist/session/thread/session-chat.d.ts +3 -1
  355. package/dist/session/thread/session-chat.js +377 -252
  356. package/dist/session/thread/session-thread.d.ts +3 -1
  357. package/dist/session/thread/session-thread.js +9 -2
  358. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  359. package/dist/session/thread/thread-boot-rows.js +89 -0
  360. package/dist/session/thread/transcript-rows.d.ts +31 -0
  361. package/dist/session/thread/transcript-rows.js +3 -0
  362. package/dist/session/thread/transcript.d.ts +0 -9
  363. package/dist/session/thread/transcript.js +104 -19
  364. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  365. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  366. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  367. package/dist/session/tool/tool-part-renderer.js +8 -3
  368. package/dist/session/tool/tools/bash-tool.js +7 -6
  369. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  370. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  371. package/dist/session/tool/tools/codemode-tool.js +1 -1
  372. package/dist/session/tool/tools/connector-tools.js +1 -1
  373. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  374. package/dist/session/tool/tools/image-gen-tool.js +240 -53
  375. package/dist/session/tool/tools/show-tool.js +19 -8
  376. package/dist/session/turn/channel-brand.d.ts +8 -3
  377. package/dist/session/turn/channel-brand.js +20 -4
  378. package/dist/session/turn/message-author.d.ts +8 -0
  379. package/dist/session/turn/message-author.js +24 -0
  380. package/dist/session/turn/message-row.d.ts +52 -0
  381. package/dist/session/turn/message-row.js +44 -0
  382. package/dist/session/turn/plan-anchor.d.ts +1 -1
  383. package/dist/session/turn/plan-anchor.js +1 -1
  384. package/dist/session/turn/user-message.d.ts +7 -1
  385. package/dist/session/turn/user-message.js +21 -7
  386. package/dist/styles.css +1 -1
  387. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  388. package/dist/workspace/home/access-requests-bell.js +20 -6
  389. package/dist/workspace/home/first-chat.d.ts +8 -21
  390. package/dist/workspace/home/first-chat.js +22 -72
  391. package/dist/workspace/index.d.ts +6 -0
  392. package/dist/workspace/index.js +6 -0
  393. package/dist/workspace/layout/project-home.d.ts +14 -2
  394. package/dist/workspace/layout/project-home.js +60 -21
  395. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  396. package/dist/workspace/layout/use-project-home-send.js +82 -3
  397. package/dist/workspace/memory/body-doc.d.ts +17 -0
  398. package/dist/workspace/memory/body-doc.js +208 -0
  399. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  400. package/dist/workspace/memory/body-extensions.js +103 -0
  401. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  402. package/dist/workspace/memory/company-memory-page.js +16 -0
  403. package/dist/workspace/memory/memory-all.d.ts +20 -0
  404. package/dist/workspace/memory/memory-all.js +27 -0
  405. package/dist/workspace/memory/memory-body.d.ts +19 -0
  406. package/dist/workspace/memory/memory-body.js +139 -0
  407. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  408. package/dist/workspace/memory/memory-empty.js +28 -0
  409. package/dist/workspace/memory/memory-history.d.ts +27 -0
  410. package/dist/workspace/memory/memory-history.js +108 -0
  411. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  412. package/dist/workspace/memory/memory-labels.js +47 -0
  413. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  414. package/dist/workspace/memory/memory-page-list.js +156 -0
  415. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  416. package/dist/workspace/memory/memory-reader.js +123 -0
  417. package/dist/workspace/memory/memory-view.d.ts +21 -0
  418. package/dist/workspace/memory/memory-view.js +124 -0
  419. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  420. package/dist/workspace/memory/remember-popover.js +61 -0
  421. package/dist/workspace/memory/remember-this.d.ts +12 -0
  422. package/dist/workspace/memory/remember-this.js +89 -0
  423. package/dist/workspace/memory/source-mark.d.ts +18 -0
  424. package/dist/workspace/memory/source-mark.js +79 -0
  425. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  426. package/dist/workspace/memory/used-memory-chip.js +61 -0
  427. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  428. package/dist/workspace/new/advanced-fields.js +2 -2
  429. package/dist/workspace/new/source-param.d.ts +1 -1
  430. package/dist/workspace/new/source-param.js +3 -1
  431. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  432. package/dist/workspace/new/use-create-workspace.js +3 -3
  433. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  434. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  435. package/dist/workspace/projects/policies-panel.js +5 -3
  436. package/dist/workspace/review/review-actions.d.ts +4 -2
  437. package/dist/workspace/review/review-actions.js +8 -2
  438. package/dist/workspace/review/review-center.js +11 -7
  439. package/dist/workspace/review/review-detail.d.ts +10 -0
  440. package/dist/workspace/review/review-detail.js +101 -13
  441. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  442. package/dist/workspace/saved-session-skeleton.js +3 -3
  443. package/dist/workspace/session-workspace.js +15 -13
  444. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  445. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  446. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  447. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  448. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  449. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  450. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  451. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  452. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  453. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  454. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  455. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  456. package/dist/workspace/sidebar/project-session-list.js +68 -56
  457. package/dist/workspace/sidebar/project-sidebar.js +9 -2
  458. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  459. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  460. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  461. package/dist/workspace/sidebar/session-group-order.js +25 -0
  462. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  463. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  464. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  465. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  466. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  467. package/dist/workspace/spaces/channel-glyph.js +6 -0
  468. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  469. package/dist/workspace/spaces/channel-setup.js +105 -0
  470. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  471. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  472. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  473. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  474. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  475. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  476. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  477. package/dist/workspace/spaces/space-agents.js +10 -0
  478. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  479. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  480. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  481. package/dist/workspace/spaces/space-link-label.js +73 -0
  482. package/dist/workspace/spaces/space-links.d.ts +19 -0
  483. package/dist/workspace/spaces/space-links.js +230 -0
  484. package/dist/workspace/spaces/space-members.d.ts +46 -0
  485. package/dist/workspace/spaces/space-members.js +182 -0
  486. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  487. package/dist/workspace/spaces/space-roster.js +44 -0
  488. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  489. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  490. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  491. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  492. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  493. package/dist/workspace/spaces/space-timeline.js +183 -0
  494. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  495. package/dist/workspace/spaces/space-triggers.js +78 -0
  496. package/dist/workspace/spaces/space-view.d.ts +37 -0
  497. package/dist/workspace/spaces/space-view.js +436 -0
  498. package/package.json +27 -36
  499. package/skills/kortix-ui/SKILL.md +3 -3
  500. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  501. package/skills/kortix-ui/references/modules.md +28 -4
  502. package/skills/kortix-ui/references/theming.md +1 -1
  503. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  504. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  505. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  506. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  507. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  508. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  509. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  510. package/dist/customize/sections/connector-connection-header.js +0 -33
  511. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  512. package/dist/customize/sections/connector-connection-modal.js +0 -72
  513. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  514. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  515. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  516. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  517. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  518. package/dist/customize/sections/discover-catalogue.js +0 -132
  519. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  520. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  521. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  522. package/dist/files/project/components/drive-empty-art.js +0 -5
  523. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  524. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  525. package/dist/internal/share/public-share-link-button.js +0 -17
  526. package/dist/markdown/setup-links/app-credentials-form.d.ts +0 -12
  527. package/dist/markdown/setup-links/app-credentials-form.js +0 -115
  528. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -0,0 +1,235 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useProjectSessions } from '@kortix/sdk/react';
4
+ import { CaretRightIcon, ChatTeardropTextIcon, LightningIcon, LinkSimpleIcon, PulseIcon, TimerIcon, WebhooksLogoIcon, } from '@phosphor-icons/react';
5
+ import { useEffect, useMemo, useRef, useState } from 'react';
6
+ import { useLocale, useTranslations } from '../../i18n/index.js';
7
+ import { AgentMark } from '../../internal/components/agent-mark.js';
8
+ import { useSessionNeedsYouCounts, useSessionsAwaitingAnswer } from '../../internal/hooks/use-review-session-summary.js';
9
+ import { useCopy } from '../../internal/hooks/use-copy.js';
10
+ import { relativeTime } from '../../internal/lib/relative-time.js';
11
+ import { cn } from '../../lib/utils.js';
12
+ import { Button } from '../../primitives/button.js';
13
+ import { EntityAvatar } from '../../primitives/entity-avatar.js';
14
+ import { ErrorState } from '../../primitives/error-state.js';
15
+ import Hint from '../../primitives/hint.js';
16
+ import Loading from '../../primitives/loading.js';
17
+ import { UserAvatar } from '../../primitives/user-avatar.js';
18
+ import { sessionDisplayLabel, sessionDisplayStatus } from '../../session/actions/session-label.js';
19
+ import { participantLabel } from '../../session/participants/session-participants.js';
20
+ import { MESSAGE_TEXT_CLASS, MessageRow } from '../../session/turn/message-row.js';
21
+ import { SolidCheckIcon } from '../../internal/icons/solid-check-icon.js';
22
+ import { RememberThisButton } from '../memory/remember-this.js';
23
+ import { SessionStatusMark } from '../sidebar/session-status-mark.js';
24
+ import { agentLabel, buildSpaceTimeline, DEFAULT_AGENT_SLUG, dayKind, firstPromptTruncated, gutterTime, lastReplyLabel, threadIsWorking, threadMessageText, threadStatus, } from './space-timeline.js';
25
+ /**
26
+ * The sidebar session list's needs-you read (`useSessionNeedsYouCounts`,
27
+ * `useSessionsAwaitingAnswer`), as one lookup per thread: the Threads filter's
28
+ * "Needs you" (`threadStatus`) and the row's mark agree by construction.
29
+ */
30
+ function useThreadNeedsYou(projectId) {
31
+ const counts = useSessionNeedsYouCounts(projectId);
32
+ const awaitingAnswer = useSessionsAwaitingAnswer(projectId);
33
+ return (session) => threadStatus(session, counts[session.session_id]) !== 'needs-you'
34
+ ? null
35
+ : awaitingAnswer.has(session.session_id)
36
+ ? 'answer'
37
+ : 'review';
38
+ }
39
+ /**
40
+ * The space's threads: top-level sessions only (`parent: 'root'`, a child
41
+ * thread is part of its parent). Polls page one every 5 s while an agent works
42
+ * so the "is working" line settles, else every 15 s so a member's new thread
43
+ * shows up. Active threads sort first, so page one holds them; older pages the
44
+ * viewer loaded are not re-read on each tick. `filters` narrow it on the
45
+ * server (the Threads tab); without them it is the Chat tab's list, one cache
46
+ * entry for both tabs.
47
+ */
48
+ export function useSpaceThreads(projectId, spaceId, filters) {
49
+ return useProjectSessions(projectId, {
50
+ ...filters,
51
+ spaceId,
52
+ parent: 'root',
53
+ enabled: !!spaceId,
54
+ refetchInterval: (sessions) => (sessions.some(threadIsWorking) ? 5_000 : 15_000),
55
+ pollFirstPageOnly: true,
56
+ });
57
+ }
58
+ function ThreadsLoadError({ threads }) {
59
+ const t = useTranslations('spaces.view');
60
+ return (_jsx(ErrorState, { size: "sm", title: t('threadsLoadError'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => threads.refetch(), children: t('retry') }) }));
61
+ }
62
+ /** "Load earlier threads", at the top of either list while older pages exist. */
63
+ function LoadEarlier({ threads }) {
64
+ const t = useTranslations('spaces.view');
65
+ return (_jsx("div", { className: "flex justify-center px-5 py-2", children: _jsx(Button, { variant: "ghost", size: "sm", onClick: () => threads.fetchNextPage(), disabled: threads.isFetchingNextPage, "aria-busy": threads.isFetchingNextPage || undefined, children: t('loadEarlier') }) }));
66
+ }
67
+ /**
68
+ * The Chat tab: the welcome block, then one row per thread, oldest at the top,
69
+ * grouped under day dividers. The column is reversed, so it opens scrolled to
70
+ * the newest thread and stays there as threads arrive.
71
+ */
72
+ export function SpaceTimeline({ projectId, space, threads, selectedId, onOpenThread, }) {
73
+ const t = useTranslations('spaces.view');
74
+ const locale = useLocale();
75
+ const days = useMemo(() => buildSpaceTimeline(threads.sessions), [threads.sessions]);
76
+ const loading = threads.isLoading || threads.isScanning;
77
+ const needsYou = useThreadNeedsYou(projectId);
78
+ const now = new Date();
79
+ const dayLabel = (day) => {
80
+ const kind = dayKind(day.date, now);
81
+ if (kind === 'today')
82
+ return t('today');
83
+ if (kind === 'yesterday')
84
+ return t('yesterday');
85
+ return day.date.toLocaleDateString(locale, { weekday: 'long', month: 'long', day: 'numeric' });
86
+ };
87
+ // A channel with no thread yet: the welcome at the bottom, where it always sits.
88
+ if (space.kind === 'channel' && !loading && threads.data && !threads.hasNextPage && days.length === 0) {
89
+ return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto", children: _jsx("div", { className: "mt-auto pt-4 pb-3", children: _jsx(SpaceWelcome, { space: space, empty: true }) }) }));
90
+ }
91
+ return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col-reverse overflow-y-auto", children: _jsx("div", { className: "pt-4 pb-3", children: threads.isError && !threads.data ? (_jsx("div", { className: "px-5 py-8", children: _jsx(ThreadsLoadError, { threads: threads }) })) : loading ? null : (_jsxs(_Fragment, { children: [threads.hasNextPage ? (_jsx(LoadEarlier, { threads: threads })) : (_jsx(SpaceWelcome, { space: space, empty: days.length === 0 })), days.map((day) => (_jsxs("section", { "aria-label": dayLabel(day), children: [_jsx(DayDivider, { label: dayLabel(day) }), day.threads.map((session) => (_jsx(ThreadRow, { session: session, space: space, needsYou: needsYou(session), selected: session.session_id === selectedId, onOpen: () => onOpenThread(session.session_id) }, session.session_id)))] }, day.date.getTime())))] })) }) }));
92
+ }
93
+ /** The top of the history: "Welcome to #name" for a channel, the DM's agent for a DM. */
94
+ function SpaceWelcome({ space, empty }) {
95
+ const t = useTranslations('spaces.view');
96
+ if (space.kind === 'dm' && space.dm_agent_name) {
97
+ const agent = agentLabel(space.dm_agent_name);
98
+ return (_jsxs("div", { className: "space-y-3 px-5 pt-16 pb-6", children: [_jsx(AgentMark, { slug: space.dm_agent_name, size: 42, label: agent }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("h2", { className: "text-2xl font-semibold tracking-tight text-balance", children: agent }), _jsx("p", { className: "text-muted-foreground text-sm text-pretty", children: t('dmIntro', { agent }) })] })] }));
99
+ }
100
+ const name = space.slug ?? space.name;
101
+ return (_jsxs("div", { className: "space-y-1.5 px-5 pt-16 pb-6", children: [_jsx("h2", { className: "text-2xl font-semibold tracking-tight text-balance", children: t('welcomeTitle', { name }) }), _jsx("p", { className: "text-muted-foreground text-sm text-pretty", children: space.description || t(empty ? 'welcomeEmpty' : 'welcomeStart', { name }) })] }));
102
+ }
103
+ /** A centred pill on a hairline: "Today", "Yesterday", "Thursday, October 15". */
104
+ function DayDivider({ label }) {
105
+ return (_jsxs("div", { className: "relative flex items-center justify-center py-2", "aria-hidden": true, children: [_jsx("div", { className: "bg-border absolute inset-x-0 top-1/2 h-px" }), _jsx("span", { className: "bg-background text-foreground relative rounded-full border px-3 py-0.5 text-xs font-medium", children: label })] }));
106
+ }
107
+ /** The trigger form's glyph per trigger type: a schedule, a webhook, an app event, a monitor. */
108
+ const TRIGGER_TYPE_ICONS = {
109
+ cron: TimerIcon,
110
+ webhook: WebhooksLogoIcon,
111
+ event: LightningIcon,
112
+ monitor: PulseIcon,
113
+ };
114
+ /**
115
+ * A thread a trigger started: the trigger's name (stamped at fire time, else
116
+ * its slug) and the glyph of its type. Null for any other thread.
117
+ */
118
+ function triggerAuthor(session) {
119
+ if (session.initiator?.type !== 'trigger')
120
+ return null;
121
+ const meta = (session.metadata ?? {});
122
+ const name = typeof meta.trigger_name === 'string' && meta.trigger_name ? meta.trigger_name : session.initiator.label;
123
+ if (!name)
124
+ return null;
125
+ const type = typeof meta.trigger_type === 'string' ? meta.trigger_type : '';
126
+ return { name, icon: TRIGGER_TYPE_ICONS[type] ?? LightningIcon };
127
+ }
128
+ /**
129
+ * One thread as a message: the author's avatar and name, the time, the first
130
+ * prompt, and the "N replies" line that opens the thread. Every thread shows
131
+ * its author: a new thread is a new top-level message.
132
+ */
133
+ function ThreadRow({ session, space, needsYou, selected, onOpen, }) {
134
+ const t = useTranslations('spaces.view');
135
+ const locale = useLocale();
136
+ const created = new Date(session.created_at);
137
+ // A trigger's run reads as the trigger: its name and its type's glyph.
138
+ const trigger = triggerAuthor(session);
139
+ // A trigger or an API key starts a thread as a service account: an agent tile, not a person.
140
+ const machine = trigger !== null || session.owner_type === 'service_account';
141
+ // The profile name, never a raw email (`participantLabel`).
142
+ const name = trigger
143
+ ? trigger.name
144
+ : machine
145
+ ? agentLabel(session.owner_name || t('agentFallback'))
146
+ : participantLabel({ name: session.owner_name ?? null, email: session.owner_email ?? null }) ||
147
+ t('authorFallback');
148
+ return (_jsxs(MessageRow, { selected: selected, avatar: machine ? (trigger ? (_jsx(EntityAvatar, { icon: trigger.icon, label: name, size: "lg" })) : (_jsx(AgentMark, { slug: session.agent_name ?? space.dm_agent_name ?? DEFAULT_AGENT_SLUG, size: 28,
149
+ // 36px, the `lg` avatar column (`w-10`): the 40px tile would overflow it.
150
+ tile: 36, label: name }))) : (_jsx(UserAvatar, { email: session.owner_email ?? '', name: name, avatarUrl: session.owner_avatar_url, size: "lg" })), name: name, time: {
151
+ iso: session.created_at,
152
+ label: created.toLocaleTimeString(locale, { hour: 'numeric', minute: '2-digit' }),
153
+ gutter: gutterTime(created, locale),
154
+ title: created.toLocaleString(locale, { dateStyle: 'full', timeStyle: 'short' }),
155
+ }, toolbar: _jsxs(_Fragment, { children: [_jsx(ThreadToolbar, { sessionId: session.session_id, onOpen: onOpen }), _jsx(RememberThisButton, { session: session, space: space })] }), children: [_jsx(ThreadPrompt, { session: session, onOpen: onOpen }), _jsx(ThreadSummary, { session: session, space: space, needsYou: needsYou, onOpen: onOpen })] }));
156
+ }
157
+ /**
158
+ * The thread's first prompt, clamped to 6 lines with "…". When it runs longer,
159
+ * a quiet "Show more" unfolds it in place and "Show less" folds it back. A
160
+ * prompt the server cut (`firstPromptTruncated`) ends in "…", and its "Show
161
+ * more" opens the thread, whose transcript holds the whole message.
162
+ */
163
+ function ThreadPrompt({ session, onOpen }) {
164
+ const t = useTranslations('hardcodedUi.i18nComplete');
165
+ const truncated = firstPromptTruncated(session);
166
+ const text = threadMessageText(session);
167
+ const [expanded, setExpanded] = useState(false);
168
+ const [overflows, setOverflows] = useState(false);
169
+ const ref = useRef(null);
170
+ useEffect(() => {
171
+ const el = ref.current;
172
+ if (!el || expanded)
173
+ return;
174
+ const measure = () => setOverflows(el.scrollHeight > el.clientHeight + 1);
175
+ measure();
176
+ const observer = new ResizeObserver(measure);
177
+ observer.observe(el);
178
+ return () => observer.disconnect();
179
+ }, [text, expanded]);
180
+ return (_jsxs(_Fragment, { children: [_jsx("p", { ref: ref, className: cn(MESSAGE_TEXT_CLASS, 'text-pretty whitespace-pre-wrap wrap-anywhere', !expanded && 'line-clamp-6'), children: truncated ? `${text}…` : text }), truncated || overflows || expanded ? (_jsx("button", { type: "button", "aria-expanded": truncated ? undefined : expanded, onClick: truncated ? onOpen : () => setExpanded(!expanded), className: "text-muted-foreground hover:text-foreground hit-area-x-2 hit-area-y-2 focus-visible:ring-ring mt-0.5 self-start rounded-sm text-xs font-medium transition-colors duration-(--duration-fast) focus-visible:ring-2 focus-visible:outline-none", children: expanded ? t.raw('text94ea9b1d33a0') : t.raw('textf5c9bd131486') })) : null] }));
181
+ }
182
+ /**
183
+ * The line under a message: the answering agent's tile, then "3 replies Last
184
+ * reply 2 hours ago", or "<Agent> is working…" while a turn runs. Hovering the
185
+ * line fills it and swaps the time for "View thread ›", so the whole line reads
186
+ * as the way in. A thread with no counted reply shows the tile and "View
187
+ * thread" only: the row's own time already says when it started.
188
+ */
189
+ function ThreadSummary({ session, space, needsYou, onOpen, }) {
190
+ const t = useTranslations('spaces.view');
191
+ const tf = useTranslations('spaces.view.threadFilter');
192
+ const locale = useLocale();
193
+ const agentName = session.agent_name ?? space.dm_agent_name;
194
+ const agent = agentName ? agentLabel(agentName) : t('agentFallback');
195
+ const working = threadIsWorking(session);
196
+ const replies = session.reply_count ?? 0;
197
+ return (_jsxs("button", { type: "button", onClick: onOpen,
198
+ // `-mx-1` with `pl-1`: the tile lines up with the body text above, and
199
+ // the fill extends past it. `pr-1.5`: the caret sits inside the fill,
200
+ // not on its edge. `w-full max-w-md`: the target is the line, not only
201
+ // its words, and stops before the line runs the width of a wide window.
202
+ // The fill is instant, like the row's.
203
+ className: "group/summary hover:bg-hover focus-visible:ring-ring -mx-1 mt-1 flex w-full max-w-md items-center gap-2 rounded-md py-1 pr-1.5 pl-1 text-left text-xs outline-none focus-visible:ring-2", children: [_jsx(AgentMark, { slug: agentName ?? DEFAULT_AGENT_SLUG, size: 14, label: agent }), needsYou ? (_jsxs("span", { className: "text-foreground flex shrink-0 items-center gap-1 font-medium", children: [_jsx(SessionStatusMark, { status: "needs-you", waitingOn: needsYou }), tf('statusValue.needsYou')] })) : null, working && !needsYou ? (_jsxs("span", { className: "text-muted-foreground flex min-w-0 items-center gap-1.5", children: [_jsx(Loading, { className: "in-[button]:text-muted-foreground size-3.5 shrink-0" }), _jsx("span", { className: "truncate", children: t('working', { agent }) })] })) : (_jsxs(_Fragment, { children: [replies > 0 ? (_jsx("span", { className: "text-foreground shrink-0 font-semibold tabular-nums", children: t('replies', { count: replies }) })) : null, _jsx("span", { className: cn('text-muted-foreground min-w-0 truncate', replies > 0 && 'group-hover/summary:hidden group-focus-visible/summary:hidden'), children: replies > 0 ? t('lastReply', { time: lastReplyLabel(session, locale) }) : t('openThread') }), replies > 0 ? (_jsx("span", { className: "text-muted-foreground hidden min-w-0 truncate group-hover/summary:inline group-focus-visible/summary:inline", children: t('openThread') })) : null] })), _jsx(CaretRightIcon, { "aria-hidden": true, className: "text-muted-foreground ml-auto size-3.5 shrink-0 opacity-0 group-hover/summary:opacity-100 group-focus-visible/summary:opacity-100" })] }));
204
+ }
205
+ /** The row's floating actions: reply in the thread (labelled), copy the thread's link. */
206
+ function ThreadToolbar({ sessionId, onOpen }) {
207
+ const t = useTranslations('spaces.view');
208
+ const { copied, copy } = useCopy({ toast: false });
209
+ const copyLink = () => {
210
+ const url = new URL(window.location.href);
211
+ url.search = '';
212
+ url.searchParams.set('thread', sessionId);
213
+ void copy(url.toString());
214
+ };
215
+ const linkLabel = copied ? t('linkCopied') : t('copyLink');
216
+ return (_jsxs(_Fragment, { children: [_jsx(Hint, { label: t('replyInThread'), side: "top", children: _jsxs(Button, { variant: "ghost", size: "xs", "aria-label": t('replyInThread'), onClick: onOpen, className: "gap-1 rounded-md text-xs", children: [_jsx(ChatTeardropTextIcon, { className: "size-3.5 shrink-0" }), t('reply')] }) }), _jsx(Hint, { label: linkLabel, side: "top", children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": linkLabel, onClick: copyLink, children: copied ? _jsx(SolidCheckIcon, { className: "size-3.5 shrink-0" }) : _jsx(LinkSimpleIcon, { className: "size-3.5 shrink-0" }) }) })] }));
217
+ }
218
+ /**
219
+ * The Threads tab's rows, last activity first. `sessions` are the rows to
220
+ * show (the tab filters `threads`); `empty` is drawn when there are none.
221
+ */
222
+ export function SpaceThreadList({ projectId, threads, sessions, empty, selectedId, onOpenThread, }) {
223
+ const locale = useLocale();
224
+ const needsYou = useThreadNeedsYou(projectId);
225
+ const sorted = useMemo(() => [...sessions].sort((a, b) => Date.parse(b.updated_at) - Date.parse(a.updated_at)), [sessions]);
226
+ if (threads.isError && !threads.data) {
227
+ return (_jsx("div", { className: "px-5 py-8", children: _jsx(ThreadsLoadError, { threads: threads }) }));
228
+ }
229
+ if (threads.isLoading || threads.isScanning)
230
+ return null;
231
+ if (sorted.length === 0) {
232
+ return (_jsxs("div", { className: "flex min-h-full flex-col", children: [empty, threads.hasNextPage ? _jsx(LoadEarlier, { threads: threads }) : null] }));
233
+ }
234
+ return (_jsxs("div", { className: "py-2", children: [_jsx("ul", { children: sorted.map((session) => (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => onOpenThread(session.session_id), className: cn('hover:bg-hover focus-visible:ring-ring flex w-full items-center gap-3 px-5 py-2 text-left outline-none focus-visible:ring-2 focus-visible:ring-inset', session.session_id === selectedId && 'bg-active hover:bg-active'), children: [_jsx(SessionStatusMark, { status: needsYou(session) ? 'needs-you' : sessionDisplayStatus(session), waitingOn: needsYou(session) ?? undefined }), _jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: sessionDisplayLabel(session) }), _jsx("time", { dateTime: session.updated_at, className: "text-muted-foreground shrink-0 text-xs tabular-nums", children: relativeTime(session.updated_at, locale) })] }) }, session.session_id))) }), threads.hasNextPage ? _jsx(LoadEarlier, { threads: threads }) : null] }));
235
+ }
@@ -0,0 +1,106 @@
1
+ import type { ProjectSession } from '@kortix/sdk';
2
+ export interface TimelineDay {
3
+ /** Local midnight of the day. */
4
+ date: Date;
5
+ /**
6
+ * Every thread is a new top-level message, so each one shows its author's
7
+ * avatar and name: no grouping between threads, even from one author.
8
+ */
9
+ threads: ProjectSession[];
10
+ }
11
+ /**
12
+ * A space's threads as the Chat tab draws them: oldest first, one group per
13
+ * local day. The server lists by last activity, so the order is set here.
14
+ */
15
+ export declare function buildSpaceTimeline(sessions: readonly ProjectSession[]): TimelineDay[];
16
+ /** Which label a day divider takes. */
17
+ export declare function dayKind(date: Date, now: Date): 'today' | 'yesterday' | 'earlier';
18
+ /**
19
+ * A collapsed row's time in the avatar gutter: hour and minute without the day
20
+ * period ("2:13", not "2:13 PM"), so it fits one avatar's width. The row's
21
+ * `title` carries the full time.
22
+ */
23
+ export declare function gutterTime(date: Date, locale: string): string;
24
+ /** "12 hours ago": the thread's last activity. */
25
+ export declare function lastReplyLabel(session: ProjectSession, locale: string, now?: number): string;
26
+ /**
27
+ * `reply_count` from a thread's loaded transcript, by the server's rule
28
+ * (`apps/api/.../session-reply-counts.ts`): every person message after the
29
+ * first, plus one per person message the agent answered.
30
+ */
31
+ export declare function liveReplyCount(roles: readonly string[]): number;
32
+ /** The agent is on it: a turn runs, the first prompt waits for delivery, or the computer starts. */
33
+ export declare function threadIsWorking(session: ProjectSession): boolean;
34
+ /** The thread's top message: its first prompt as the person wrote it, else its title. */
35
+ export declare function threadMessageText(session: ProjectSession): string;
36
+ /**
37
+ * The server stores a thread's first prompt cut at this length
38
+ * (`FIRST_PROMPT_MAX_CHARS` in `apps/api/src/projects/lib/project-spaces.ts`).
39
+ */
40
+ export declare const SERVER_FIRST_PROMPT_MAX_CHARS = 500;
41
+ /**
42
+ * The server cut the first prompt: the row shows "…" and its "Show more"
43
+ * opens the thread, whose transcript holds the whole message. A prompt of
44
+ * exactly the limit reads as cut too, and opening its thread is harmless.
45
+ */
46
+ export declare function firstPromptTruncated(session: ProjectSession): boolean;
47
+ /** The agent whose mark stands in when a row does not name its agent. */
48
+ export declare const DEFAULT_AGENT_SLUG = "kortix";
49
+ /** An agent's display name: the sidebar's DM row and the space view say it the same way. */
50
+ export declare function agentLabel(name: string): string;
51
+ /** A person who started a thread in the space, as the thread list names them. */
52
+ export interface SpacePerson {
53
+ id: string;
54
+ name: string | null;
55
+ email: string | null;
56
+ avatarUrl: string | null;
57
+ /** How many of the loaded threads this person started. */
58
+ threads: number;
59
+ }
60
+ /**
61
+ * Who is in a space, as far as its loaded threads tell: the people who
62
+ * started a thread, and the agents that answered one, each with how many of
63
+ * those threads it was. No roster API exists yet, so the header says "in these
64
+ * threads", not "members".
65
+ */
66
+ export declare function spaceRoster(sessions: readonly ProjectSession[], dmAgentName?: string | null): {
67
+ people: SpacePerson[];
68
+ agents: string[];
69
+ agentThreads: Record<string, number>;
70
+ };
71
+ /** A channel's tabs, in order. `?tab=` names one; Chat has no param. */
72
+ declare const CHANNEL_TABS: readonly ["chat", "threads", "files", "memory", "apps", "links", "triggers"];
73
+ export type SpaceTab = (typeof CHANNEL_TABS)[number];
74
+ export declare function spaceTabs(kind: 'channel' | 'dm'): readonly SpaceTab[];
75
+ /** The `?tab=` value as a tab of this kind of space; anything else is Chat. */
76
+ export declare function spaceTabFromParam(value: string | null, kind: 'channel' | 'dm'): SpaceTab;
77
+ /** The Threads tab's Status filter: the states a thread row shows. */
78
+ export declare const THREAD_STATUSES: readonly ["working", "needs-you", "failed", "done"];
79
+ export type ThreadStatus = (typeof THREAD_STATUSES)[number];
80
+ /** The Threads tab's Activity filter: the last activity on or after a local day. */
81
+ export declare const THREAD_ACTIVITIES: readonly ["today", "last7", "last30"];
82
+ export type ThreadActivity = (typeof THREAD_ACTIVITIES)[number];
83
+ /**
84
+ * The Threads tab's search and filters, as the URL holds them
85
+ * (`?q=&status=&by=&agent=&active=`). `by` is `me` or a user id. A DM has
86
+ * one person and one agent, so it reads no `by` or `agent`.
87
+ */
88
+ export interface ThreadFilters {
89
+ q: string;
90
+ status: ThreadStatus | null;
91
+ by: string | null;
92
+ agent: string | null;
93
+ active: ThreadActivity | null;
94
+ }
95
+ export declare function threadFiltersFromParams(params: {
96
+ get(name: string): string | null;
97
+ }, kind: 'channel' | 'dm'): ThreadFilters;
98
+ /**
99
+ * The start of an Activity window: local midnight today, 6 days earlier
100
+ * (7 days with today) or 29 days earlier. A day boundary, so the list's query
101
+ * stays the same all day.
102
+ */
103
+ export declare function threadActivitySince(active: ThreadActivity, now: Date): string;
104
+ /** A thread's Status filter value. A pending review wins; a turn in flight is Working. */
105
+ export declare function threadStatus(session: ProjectSession, reviewCount?: number): ThreadStatus;
106
+ export {};
@@ -0,0 +1,183 @@
1
+ import { capitalizeWords, isMetaAgentName, META_AGENT_DISPLAY_NAME } from '../../_vendor/kortix-shared.js';
2
+ import { relativeTime } from '../../internal/lib/relative-time.js';
3
+ import { sessionDisplayLabel, sessionDisplayStatus } from '../../session/actions/session-label.js';
4
+ import { parseAgentMentionReferences, parseFileMentionReferences, parseFileReferences, parseSessionReferences, stripReplyContexts, } from '../../session/thread/message-parsing.js';
5
+ function localDay(time) {
6
+ const date = new Date(time);
7
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
8
+ }
9
+ /**
10
+ * A space's threads as the Chat tab draws them: oldest first, one group per
11
+ * local day. The server lists by last activity, so the order is set here.
12
+ */
13
+ export function buildSpaceTimeline(sessions) {
14
+ const sorted = [...sessions].sort((a, b) => Date.parse(a.created_at) - Date.parse(b.created_at));
15
+ const days = [];
16
+ for (const session of sorted) {
17
+ const date = localDay(Date.parse(session.created_at));
18
+ let day = days.at(-1);
19
+ if (!day || day.date.getTime() !== date.getTime()) {
20
+ day = { date, threads: [] };
21
+ days.push(day);
22
+ }
23
+ day.threads.push(session);
24
+ }
25
+ return days;
26
+ }
27
+ /** Which label a day divider takes. */
28
+ export function dayKind(date, now) {
29
+ const today = localDay(now.getTime()).getTime();
30
+ const day = localDay(date.getTime()).getTime();
31
+ if (day === today)
32
+ return 'today';
33
+ const yesterday = new Date(today);
34
+ yesterday.setDate(yesterday.getDate() - 1);
35
+ return day === yesterday.getTime() ? 'yesterday' : 'earlier';
36
+ }
37
+ /**
38
+ * A collapsed row's time in the avatar gutter: hour and minute without the day
39
+ * period ("2:13", not "2:13 PM"), so it fits one avatar's width. The row's
40
+ * `title` carries the full time.
41
+ */
42
+ export function gutterTime(date, locale) {
43
+ return new Intl.DateTimeFormat(locale, { hour: 'numeric', minute: '2-digit' })
44
+ .formatToParts(date)
45
+ .filter((part) => part.type !== 'dayPeriod')
46
+ .map((part) => part.value)
47
+ .join('')
48
+ .trim();
49
+ }
50
+ /** "12 hours ago": the thread's last activity. */
51
+ export function lastReplyLabel(session, locale, now = Date.now()) {
52
+ return relativeTime(session.updated_at, locale, now, { style: 'long' });
53
+ }
54
+ /**
55
+ * `reply_count` from a thread's loaded transcript, by the server's rule
56
+ * (`apps/api/.../session-reply-counts.ts`): every person message after the
57
+ * first, plus one per person message the agent answered.
58
+ */
59
+ export function liveReplyCount(roles) {
60
+ let people = 0;
61
+ let answers = 0;
62
+ let answered = true;
63
+ for (const role of roles) {
64
+ if (role === 'user') {
65
+ people += 1;
66
+ answered = false;
67
+ }
68
+ else if (role === 'assistant' && !answered) {
69
+ answers += 1;
70
+ answered = true;
71
+ }
72
+ }
73
+ return Math.max(people - 1, 0) + answers;
74
+ }
75
+ /** The agent is on it: a turn runs, the first prompt waits for delivery, or the computer starts. */
76
+ export function threadIsWorking(session) {
77
+ if (session.working?.state === 'working' || session.working?.pending_delivery)
78
+ return true;
79
+ return session.status === 'queued' || session.status === 'branching' || session.status === 'provisioning';
80
+ }
81
+ /** The thread's top message: its first prompt as the person wrote it, else its title. */
82
+ export function threadMessageText(session) {
83
+ let text = session.first_prompt ?? '';
84
+ text = parseFileReferences(text).cleanText;
85
+ text = parseSessionReferences(text).cleanText;
86
+ text = parseFileMentionReferences(text).cleanText;
87
+ text = parseAgentMentionReferences(text).cleanText;
88
+ text = stripReplyContexts(text).trim();
89
+ return text || sessionDisplayLabel(session);
90
+ }
91
+ /**
92
+ * The server stores a thread's first prompt cut at this length
93
+ * (`FIRST_PROMPT_MAX_CHARS` in `apps/api/src/projects/lib/project-spaces.ts`).
94
+ */
95
+ export const SERVER_FIRST_PROMPT_MAX_CHARS = 500;
96
+ /**
97
+ * The server cut the first prompt: the row shows "…" and its "Show more"
98
+ * opens the thread, whose transcript holds the whole message. A prompt of
99
+ * exactly the limit reads as cut too, and opening its thread is harmless.
100
+ */
101
+ export function firstPromptTruncated(session) {
102
+ return (session.first_prompt?.length ?? 0) >= SERVER_FIRST_PROMPT_MAX_CHARS;
103
+ }
104
+ /** The agent whose mark stands in when a row does not name its agent. */
105
+ export const DEFAULT_AGENT_SLUG = 'kortix';
106
+ /** An agent's display name: the sidebar's DM row and the space view say it the same way. */
107
+ export function agentLabel(name) {
108
+ return isMetaAgentName(name) ? META_AGENT_DISPLAY_NAME : capitalizeWords(name);
109
+ }
110
+ /**
111
+ * Who is in a space, as far as its loaded threads tell: the people who
112
+ * started a thread, and the agents that answered one, each with how many of
113
+ * those threads it was. No roster API exists yet, so the header says "in these
114
+ * threads", not "members".
115
+ */
116
+ export function spaceRoster(sessions, dmAgentName) {
117
+ const people = new Map();
118
+ const agentThreads = {};
119
+ if (dmAgentName)
120
+ agentThreads[dmAgentName] = 0;
121
+ for (const session of sessions) {
122
+ if (session.created_by && session.owner_type === 'user') {
123
+ const person = people.get(session.created_by);
124
+ if (person)
125
+ person.threads += 1;
126
+ else
127
+ people.set(session.created_by, {
128
+ id: session.created_by,
129
+ name: session.owner_name ?? null,
130
+ email: session.owner_email ?? null,
131
+ avatarUrl: session.owner_avatar_url ?? null,
132
+ threads: 1,
133
+ });
134
+ }
135
+ if (session.agent_name)
136
+ agentThreads[session.agent_name] = (agentThreads[session.agent_name] ?? 0) + 1;
137
+ }
138
+ return { people: [...people.values()], agents: Object.keys(agentThreads), agentThreads };
139
+ }
140
+ /** A channel's tabs, in order. `?tab=` names one; Chat has no param. */
141
+ const CHANNEL_TABS = ['chat', 'threads', 'files', 'memory', 'apps', 'links', 'triggers'];
142
+ /** A DM has no apps or links of its own. */
143
+ const DM_TABS = ['chat', 'threads', 'files', 'memory', 'triggers'];
144
+ export function spaceTabs(kind) {
145
+ return kind === 'dm' ? DM_TABS : CHANNEL_TABS;
146
+ }
147
+ /** The `?tab=` value as a tab of this kind of space; anything else is Chat. */
148
+ export function spaceTabFromParam(value, kind) {
149
+ return spaceTabs(kind).find((tab) => tab === value) ?? 'chat';
150
+ }
151
+ /** The Threads tab's Status filter: the states a thread row shows. */
152
+ export const THREAD_STATUSES = ['working', 'needs-you', 'failed', 'done'];
153
+ /** The Threads tab's Activity filter: the last activity on or after a local day. */
154
+ export const THREAD_ACTIVITIES = ['today', 'last7', 'last30'];
155
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
156
+ const oneOf = (values, value) => values.find((candidate) => candidate === value) ?? null;
157
+ export function threadFiltersFromParams(params, kind) {
158
+ const by = params.get('by');
159
+ return {
160
+ q: params.get('q')?.trim() ?? '',
161
+ status: oneOf(THREAD_STATUSES, params.get('status')),
162
+ by: kind === 'dm' ? null : by === 'me' || (by && UUID.test(by)) ? by : null,
163
+ agent: kind === 'dm' ? null : params.get('agent') || null,
164
+ active: oneOf(THREAD_ACTIVITIES, params.get('active')),
165
+ };
166
+ }
167
+ /**
168
+ * The start of an Activity window: local midnight today, 6 days earlier
169
+ * (7 days with today) or 29 days earlier. A day boundary, so the list's query
170
+ * stays the same all day.
171
+ */
172
+ export function threadActivitySince(active, now) {
173
+ const days = active === 'today' ? 0 : active === 'last7' ? 6 : 29;
174
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate() - days).toISOString();
175
+ }
176
+ /** A thread's Status filter value. A pending review wins; a turn in flight is Working. */
177
+ export function threadStatus(session, reviewCount = 0) {
178
+ if (reviewCount > 0)
179
+ return 'needs-you';
180
+ if (threadIsWorking(session))
181
+ return 'working';
182
+ return sessionDisplayStatus(session) === 'failed' ? 'failed' : 'done';
183
+ }
@@ -0,0 +1,13 @@
1
+ import type { ProjectSpace } from '@kortix/sdk';
2
+ /**
3
+ * A channel's or DM's Triggers tab: the project's triggers that post here
4
+ * (`space_id`, filtered from the one trigger list every trigger surface
5
+ * shares), each with its schedule, its last run and its on/off switch, and
6
+ * "New trigger", which opens the trigger form posting here. A private channel
7
+ * has no "New trigger": the API refuses a trigger into it, so one line says why.
8
+ */
9
+ export declare function SpaceTriggers({ projectId, space, place }: {
10
+ projectId: string;
11
+ space: ProjectSpace;
12
+ place: string;
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,78 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { qk, useProjectTriggers } from '@kortix/sdk/react';
4
+ import { LightningIcon, PlusIcon } from '@phosphor-icons/react';
5
+ import { useQueryClient } from '@tanstack/react-query';
6
+ import { useState } from 'react';
7
+ import { describeWhen, triggerName, triggerSubtitle } from '../../customize/triggers/schedule/schedule-copy.js';
8
+ import { useTriggerControls } from '../../customize/triggers/schedule/trigger-controls.js';
9
+ import { TriggerComposer } from '../../customize/triggers/schedule/trigger-composer.js';
10
+ import { lastRunLabel } from '../../internal/lib/trigger-clock.js';
11
+ import { TriggerTile } from '../../customize/triggers/schedule/trigger-tile.js';
12
+ import { useLocale, useTranslations } from '../../i18n/index.js';
13
+ import { uiRoutes } from '../../lib/routes.js';
14
+ import { Button } from '../../primitives/button.js';
15
+ import { EmptyArt } from '../../primitives/empty-art.js';
16
+ import { EmptyState } from '../../primitives/empty-state.js';
17
+ import { ErrorState } from '../../primitives/error-state.js';
18
+ import { Switch } from '../../primitives/switch.js';
19
+ import { errorToast, successToast } from '../../primitives/toast.js';
20
+ import { UiLink as Link } from '../../providers/ui-provider.js';
21
+ /**
22
+ * A channel's or DM's Triggers tab: the project's triggers that post here
23
+ * (`space_id`, filtered from the one trigger list every trigger surface
24
+ * shares), each with its schedule, its last run and its on/off switch, and
25
+ * "New trigger", which opens the trigger form posting here. A private channel
26
+ * has no "New trigger": the API refuses a trigger into it, so one line says why.
27
+ */
28
+ export function SpaceTriggers({ projectId, space, place }) {
29
+ const t = useTranslations('spaces.view');
30
+ const queryClient = useQueryClient();
31
+ const listing = useProjectTriggers(projectId);
32
+ const controls = useTriggerControls(projectId);
33
+ const [creating, setCreating] = useState(false);
34
+ const triggers = listing.data?.triggers.filter((trigger) => trigger.space_id === space.space_id);
35
+ const isPrivate = space.visibility === 'private';
36
+ const privateNote = isPrivate ? _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: t('triggers.privateNote') }) : null;
37
+ const newButton = controls.canCreate && !isPrivate ? (_jsxs(Button, { variant: "outline", size: "sm", className: "gap-1.5", onClick: () => setCreating(true), children: [_jsx(PlusIcon, { "aria-hidden": true, className: "size-3.5 shrink-0" }), t('empty.triggers.action')] })) : null;
38
+ let body;
39
+ if (listing.isError && !listing.data) {
40
+ body = (_jsx(ErrorState, { size: "sm", title: t('triggers.loadError'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => listing.refetch(), children: t('retry') }) }));
41
+ }
42
+ else if (!triggers) {
43
+ body = null;
44
+ }
45
+ else if (triggers.length === 0) {
46
+ body = (_jsx(EmptyState, { className: "min-h-full", media: _jsx(EmptyArt, { icon: LightningIcon }), title: t('empty.triggers.title'), description: isPrivate ? t('triggers.privateNote') : t('empty.triggers.description', { place }), action: newButton }));
47
+ }
48
+ else {
49
+ body = (_jsxs("div", { className: "flex flex-col gap-3", children: [newButton ? _jsx("div", { className: "flex justify-end", children: newButton }) : null, privateNote, _jsx("ul", { className: "flex flex-col", children: triggers.map((trigger) => (_jsx(TriggerRow, { projectId: projectId, trigger: trigger, projectPaused: listing.data?.triggers_paused === true, canUpdate: controls.canUpdate, onToggle: (enabled) => listing.update.mutateAsync({ slug: trigger.slug, input: { enabled } }) }, trigger.slug))) })] }));
50
+ }
51
+ return (_jsxs("div", { className: triggers?.length ? 'px-5 py-4' : triggers ? 'flex min-h-full flex-col' : 'px-5 py-16', children: [body, _jsx(TriggerComposer, { projectId: projectId, open: creating, onOpenChange: setCreating, initialSpace: { spaceId: space.space_id, kind: space.kind },
52
+ // A DM trigger runs the DM's agent (the API rejects any other).
53
+ initialAgent: space.kind === 'dm' ? space.dm_agent_name : null, onCreated: () => {
54
+ setCreating(false);
55
+ void queryClient.invalidateQueries({ queryKey: qk.project.triggers(projectId) });
56
+ } })] }));
57
+ }
58
+ /** One trigger: its clock, its name over its schedule, its last run, and its switch. The row opens the trigger. */
59
+ function TriggerRow({ projectId, trigger, projectPaused, canUpdate, onToggle, }) {
60
+ const tTriggers = useTranslations('hardcodedUi.i18nComplete');
61
+ const locale = useLocale();
62
+ const [pending, setPending] = useState(false);
63
+ const name = triggerName(trigger);
64
+ const subtitle = triggerSubtitle(name, describeWhen(trigger), trigger.prompt_template);
65
+ // An auto-paused trigger is off until resumed: turning it on sends `enabled: true`, which resumes it.
66
+ const active = trigger.enabled && !trigger.auto_paused_at;
67
+ const href = uiRoutes().customize(projectId, `triggers?id=${encodeURIComponent(trigger.slug)}`);
68
+ const toggle = (enabled) => {
69
+ setPending(true);
70
+ onToggle(enabled)
71
+ .then(() => successToast(enabled ? tTriggers.raw('texta97d32ddb6ba') : tTriggers.raw('texte159b06187d3')))
72
+ .catch((err) => errorToast(err instanceof Error ? err.message : tTriggers.raw('text43ec39943667')))
73
+ .finally(() => setPending(false));
74
+ };
75
+ return (_jsxs("li", { className: "group hover:bg-hover relative -mx-2 flex items-center gap-3 rounded-md px-2 py-2", children: [_jsx("span", { className: "flex size-5 shrink-0 items-center justify-center", children: _jsx(TriggerTile, { trigger: trigger, projectPaused: projectPaused }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [href ? (_jsx(Link, { href: href, className: "focus-visible:ring-ring block truncate text-sm font-medium outline-none after:absolute after:inset-0 after:rounded-md focus-visible:ring-2", children: name })) : (_jsx("p", { className: "truncate text-sm font-medium", children: name })), subtitle ? _jsx("p", { className: "text-muted-foreground truncate text-xs", children: subtitle }) : null] }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs tabular-nums", children: lastRunLabel(trigger, tTriggers, locale) }), _jsx(Switch, { checked: active, onCheckedChange: toggle, disabled: !canUpdate || pending, "aria-label": name,
76
+ // Above the row's stretched link.
77
+ className: "relative z-10" })] }));
78
+ }