@kortix/ui 0.14.7 → 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 (576) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +64 -4
  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/runtime-versions.d.ts +4 -0
  7. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  8. package/dist/access/access/access-detail-shell.js +1 -1
  9. package/dist/access/access/access-dialog-share.js +4 -7
  10. package/dist/access/access/access-dialog.js +2 -1
  11. package/dist/access/access/principal-picker.d.ts +11 -0
  12. package/dist/access/access/principal-picker.js +9 -7
  13. package/dist/apps/app-preview-pool.d.ts +7 -2
  14. package/dist/apps/app-preview-pool.js +11 -5
  15. package/dist/apps/app-shared.d.ts +22 -15
  16. package/dist/apps/app-shared.js +37 -19
  17. package/dist/apps/index.d.ts +2 -2
  18. package/dist/apps/index.js +2 -2
  19. package/dist/artifacts/artifact-frame.d.ts +16 -0
  20. package/dist/artifacts/artifact-frame.js +51 -0
  21. package/dist/artifacts/artifact-session.d.ts +18 -0
  22. package/dist/artifacts/artifact-session.js +101 -0
  23. package/dist/artifacts/frame-policy.d.ts +30 -0
  24. package/dist/artifacts/frame-policy.js +61 -0
  25. package/dist/artifacts/index.d.ts +3 -0
  26. package/dist/artifacts/index.js +5 -0
  27. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  28. package/dist/browser/sandbox-browser-chrome.js +2 -2
  29. package/dist/customize/agents/agent-cover-card.d.ts +17 -0
  30. package/dist/customize/agents/agent-cover-card.js +13 -0
  31. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  32. package/dist/customize/agents/agent-grant-pages.js +30 -4
  33. package/dist/customize/agents/agent-page.js +8 -33
  34. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  35. package/dist/customize/agents/agent-policy-sets.js +72 -0
  36. package/dist/customize/agents/agent-triggers-section.js +2 -1
  37. package/dist/customize/agents/agents-page.js +43 -49
  38. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  39. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  40. package/dist/customize/connectors/agent-access.d.ts +35 -0
  41. package/dist/customize/connectors/agent-access.js +77 -0
  42. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  43. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  44. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  45. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  46. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  47. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  48. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  49. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  50. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  51. package/dist/customize/connectors/connector-identity.js +13 -42
  52. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  53. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  54. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  55. package/dist/customize/connectors/connector-routes.js +29 -20
  56. package/dist/customize/connectors/connectors-page.js +53 -82
  57. package/dist/customize/connectors/detail/app-page.js +226 -98
  58. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  59. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  60. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  61. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  62. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  63. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  64. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  65. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  66. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  67. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  68. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  69. package/dist/customize/connectors/detail/connector-page.js +14 -10
  70. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  71. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  72. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  73. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  74. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  75. package/dist/customize/connectors/detail/connector-status.js +34 -10
  76. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  77. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  78. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  79. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  80. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  81. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  82. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  83. package/dist/customize/connectors/detail/provider-info.js +2 -2
  84. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  85. package/dist/customize/connectors/detail/status-badge.js +4 -5
  86. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  87. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  88. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  89. package/dist/customize/connectors/install/install-dialog.js +40 -0
  90. package/dist/customize/connectors/install/install.d.ts +13 -2
  91. package/dist/customize/connectors/install/install.js +9 -4
  92. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  93. package/dist/customize/connectors/install/use-install.js +65 -37
  94. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  95. package/dist/customize/connectors/install/way-kind.js +16 -0
  96. package/dist/customize/connectors/provider-label.d.ts +2 -1
  97. package/dist/customize/connectors/provider-label.js +13 -3
  98. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  99. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  100. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  101. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  102. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  103. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  104. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  105. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  106. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  107. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  108. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  109. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  110. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  111. package/dist/customize/connectors/use-agent-access.js +72 -0
  112. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  113. package/dist/customize/migrate-to-v2/index.js +1 -2
  114. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -24
  115. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -235
  116. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  117. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  118. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  119. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  120. package/dist/customize/providers/provider-accordion.js +17 -2
  121. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  122. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  123. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  124. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  125. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  126. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  127. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  128. package/dist/customize/sections/component/channel-mocks.js +46 -0
  129. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  130. package/dist/customize/sections/component/channel-row.js +10 -4
  131. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  132. package/dist/customize/sections/component/email-connect-form.js +183 -0
  133. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  134. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  135. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  136. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  137. package/dist/customize/sections/component/telegram-channel-row.js +16 -25
  138. package/dist/customize/sections/connectors-view.d.ts +1 -15
  139. package/dist/customize/sections/connectors-view.js +81 -314
  140. package/dist/customize/sections/view/agent-editor-catalog.js +5 -0
  141. package/dist/customize/sections/view/channels-view.d.ts +5 -1
  142. package/dist/customize/sections/view/channels-view.js +63 -81
  143. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  144. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  145. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +1 -12
  146. package/dist/customize/shared/catalog/catalog-empty-state.js +3 -3
  147. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  148. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  149. package/dist/customize/shared/feature-gate-screen.js +27 -9
  150. package/dist/customize/shared/new-entity-menu.js +4 -1
  151. package/dist/customize/shared/use-customize-prefetch.d.ts +2 -3
  152. package/dist/customize/shared/use-customize-prefetch.js +9 -27
  153. package/dist/customize/skills/skills-page.js +4 -5
  154. package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
  155. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  156. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  157. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  158. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  159. package/dist/customize/triggers/schedule/then-fields.js +1 -5
  160. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  161. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  162. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  163. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  164. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  165. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  166. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  167. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  168. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  169. package/dist/customize/triggers/schedule-view.js +9 -4
  170. package/dist/files/index.d.ts +1 -0
  171. package/dist/files/index.js +1 -0
  172. package/dist/files/project/change-request-recovery.d.ts +1 -26
  173. package/dist/files/project/change-request-recovery.js +1 -59
  174. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  175. package/dist/files/project/components/drive-explorer.js +15 -15
  176. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  177. package/dist/files/project/components/drive-toolbar.js +14 -5
  178. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  179. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  180. package/dist/files/project/hooks/use-change-requests.js +11 -2
  181. package/dist/files/renderers/image-frame.d.ts +46 -0
  182. package/dist/files/renderers/image-frame.js +59 -0
  183. package/dist/files/renderers/image-renderer.d.ts +11 -1
  184. package/dist/files/renderers/image-renderer.js +13 -3
  185. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  186. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  187. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  188. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  189. package/dist/files/renderers/show-content-renderer.js +56 -14
  190. package/dist/files/runtime/file-source.js +2 -0
  191. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  192. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  193. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  194. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  195. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  196. package/dist/files/viewer/file-content-renderer.js +50 -7
  197. package/dist/files/viewer/file-header.d.ts +7 -3
  198. package/dist/files/viewer/file-header.js +20 -11
  199. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  200. package/dist/files/viewer/file-preview-modal.js +10 -22
  201. package/dist/files/viewer/file-source.d.ts +13 -0
  202. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  203. package/dist/files/viewer/use-file-content-state.js +28 -10
  204. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  205. package/dist/files/viewer/viewer-actions.js +2 -2
  206. package/dist/hooks/use-media-query.d.ts +1 -0
  207. package/dist/hooks/use-mobile.d.ts +5 -0
  208. package/dist/hooks/use-mobile.js +8 -0
  209. package/dist/i18n/en.d.ts +906 -70
  210. package/dist/i18n/en.js +924 -88
  211. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  212. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  213. package/dist/index.d.ts +2 -2
  214. package/dist/index.js +2 -2
  215. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  216. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  217. package/dist/internal/account-hub/hub-sheet.js +21 -5
  218. package/dist/internal/account-hub/sections.d.ts +1 -1
  219. package/dist/internal/account-hub/sections.js +2 -1
  220. package/dist/internal/auth/auth-card-shell.js +3 -3
  221. package/dist/internal/components/agent-mark.d.ts +38 -0
  222. package/dist/internal/components/agent-mark.js +41 -0
  223. package/dist/internal/connector-logo/connector-logo-source.d.ts +63 -0
  224. package/dist/internal/connector-logo/connector-logo-source.js +48 -0
  225. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  226. package/dist/internal/connector-logo/connector-logo.js +56 -0
  227. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  228. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  229. package/dist/internal/files/file-read-retry.d.ts +13 -0
  230. package/dist/internal/files/file-read-retry.js +23 -3
  231. package/dist/internal/files/session-drive-files.d.ts +5 -1
  232. package/dist/internal/files/session-drive-files.js +7 -2
  233. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  234. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  235. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  236. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  237. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  238. package/dist/internal/hooks/index.d.ts +1 -1
  239. package/dist/internal/hooks/index.js +1 -1
  240. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  241. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  242. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  243. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  244. package/dist/internal/icons/telegram.d.ts +5 -0
  245. package/dist/internal/icons/telegram.js +6 -1
  246. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  247. package/dist/internal/layout/nav-hover-card.js +84 -0
  248. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  249. package/dist/internal/layout/project-nav-row.js +3 -2
  250. package/dist/internal/layout/project-page-header.d.ts +4 -2
  251. package/dist/internal/layout/project-page-header.js +4 -3
  252. package/dist/internal/layout/project-settings-nav.js +59 -2
  253. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  254. package/dist/internal/lib/browser-error-noise.js +1 -1
  255. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  256. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  257. package/dist/internal/lib/manifest-version.d.ts +1 -1
  258. package/dist/internal/lib/manifest-version.js +2 -2
  259. package/dist/internal/lib/memory-href.d.ts +16 -0
  260. package/dist/internal/lib/memory-href.js +46 -0
  261. package/dist/internal/lib/pixel-mark.d.ts +33 -0
  262. package/dist/internal/lib/pixel-mark.js +152 -0
  263. package/dist/internal/lib/use-project-feature-flags.js +11 -11
  264. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  265. package/dist/internal/lib/utils/heic-convert.js +3 -4
  266. package/dist/internal/lib/web-notifications.d.ts +20 -0
  267. package/dist/internal/lib/web-notifications.js +48 -4
  268. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  269. package/dist/internal/notifications/notification-bell.js +2 -2
  270. package/dist/internal/selection/selection-bar.d.ts +2 -1
  271. package/dist/internal/selection/selection-bar.js +1 -1
  272. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  273. package/dist/internal/stores/file-preview-store.js +19 -1
  274. package/dist/internal/stores/kortix-computer-store.js +3 -0
  275. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  276. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  277. package/dist/lib/routes.d.ts +13 -1
  278. package/dist/lib/routes.js +13 -0
  279. package/dist/markdown/genui/components/inline.d.ts +1 -1
  280. package/dist/markdown/index.d.ts +2 -1
  281. package/dist/markdown/index.js +2 -1
  282. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  283. package/dist/markdown/setup-links/approval-decision.js +6 -2
  284. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  285. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  286. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  287. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  288. package/dist/markdown/unified-markdown.js +5 -5
  289. package/dist/primitives/badge.d.ts +1 -1
  290. package/dist/primitives/badge.js +2 -0
  291. package/dist/primitives/disclosure.js +14 -2
  292. package/dist/primitives/empty-art.d.ts +12 -0
  293. package/dist/primitives/empty-art.js +11 -0
  294. package/dist/primitives/entity-avatar.d.ts +4 -1
  295. package/dist/primitives/entity-avatar.js +4 -2
  296. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  297. package/dist/primitives/mermaid-renderer.js +21 -15
  298. package/dist/primitives/resizable.js +6 -1
  299. package/dist/primitives/resize-seam.d.ts +11 -0
  300. package/dist/primitives/resize-seam.js +12 -0
  301. package/dist/primitives/sidebar-panel.js +4 -7
  302. package/dist/primitives/tabs.d.ts +14 -1
  303. package/dist/primitives/tabs.js +1 -1
  304. package/dist/primitives/user-avatar.d.ts +3 -1
  305. package/dist/primitives/user-avatar.js +4 -2
  306. package/dist/providers/ui-provider.d.ts +10 -1
  307. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  308. package/dist/session/composer/ComposerAboveCard.js +2 -2
  309. package/dist/session/composer/ComposerCard.d.ts +1 -1
  310. package/dist/session/composer/ComposerCard.js +3 -3
  311. package/dist/session/composer/agent-selector.d.ts +19 -1
  312. package/dist/session/composer/agent-selector.js +42 -12
  313. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  314. package/dist/session/composer/composer-agent-access.js +27 -0
  315. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  316. package/dist/session/composer/composer-chat-input.js +8 -6
  317. package/dist/session/composer/composer-logic.d.ts +16 -0
  318. package/dist/session/composer/composer-logic.js +12 -0
  319. package/dist/session/composer/composer-underbar.d.ts +3 -1
  320. package/dist/session/composer/composer-underbar.js +4 -3
  321. package/dist/session/composer/composer.d.ts +15 -1
  322. package/dist/session/composer/composer.js +19 -1
  323. package/dist/session/composer/context-usage.d.ts +5 -0
  324. package/dist/session/composer/context-usage.js +6 -1
  325. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  326. package/dist/session/composer/draft/composer-draft.js +5 -1
  327. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  328. package/dist/session/composer/token-progress.js +4 -4
  329. package/dist/session/header/export-transcript-modal.d.ts +3 -2
  330. package/dist/session/header/export-transcript-modal.js +6 -3
  331. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  332. package/dist/session/models/chatgpt-connection-button.js +54 -0
  333. package/dist/session/models/model-selector.d.ts +3 -1
  334. package/dist/session/models/model-selector.js +7 -3
  335. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  336. package/dist/session/models/use-model-connection-gate.js +5 -5
  337. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  338. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  339. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  340. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  341. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  342. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  343. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  344. package/dist/session/panel/easy/app-preview.js +31 -12
  345. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  346. package/dist/session/panel/easy/change-requests-card.js +17 -0
  347. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  348. package/dist/session/panel/easy/easy-panel.js +5 -2
  349. package/dist/session/panel/easy/file-preview.js +1 -1
  350. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  351. package/dist/session/panel/easy/outputs-card.js +3 -2
  352. package/dist/session/panel/easy/plan-card.d.ts +2 -0
  353. package/dist/session/panel/easy/plan-card.js +2 -0
  354. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  355. package/dist/session/panel/session-audit-panel.js +9 -2
  356. package/dist/session/panel/session-detail-panel.js +9 -3
  357. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  358. package/dist/session/panel/session-files-explorer.js +12 -3
  359. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  360. package/dist/session/panel/session-panel-provider.js +32 -7
  361. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  362. package/dist/session/panel/shared/derive-panels.js +12 -2
  363. package/dist/session/panel/shared/output-priority.js +2 -0
  364. package/dist/session/participants/session-participants.d.ts +5 -1
  365. package/dist/session/participants/session-participants.js +9 -2
  366. package/dist/session/prompts/approval-request.d.ts +5 -0
  367. package/dist/session/prompts/approval-request.js +7 -1
  368. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  369. package/dist/session/prompts/session-approval-review.js +18 -0
  370. package/dist/session/status/session-error-banner.js +2 -49
  371. package/dist/session/status/session-starting-loader.d.ts +14 -2
  372. package/dist/session/status/session-starting-loader.js +16 -4
  373. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  374. package/dist/session/thread/after-first-prompt.js +8 -0
  375. package/dist/session/thread/detect-command.d.ts +12 -0
  376. package/dist/session/thread/detect-command.js +20 -0
  377. package/dist/session/thread/plan-surface.d.ts +1 -0
  378. package/dist/session/thread/plan-surface.js +1 -0
  379. package/dist/session/thread/session-chat.d.ts +3 -1
  380. package/dist/session/thread/session-chat.js +377 -252
  381. package/dist/session/thread/session-context-metrics.d.ts +15 -0
  382. package/dist/session/thread/session-context-metrics.js +10 -1
  383. package/dist/session/thread/session-context-modal.d.ts +4 -2
  384. package/dist/session/thread/session-context-modal.js +16 -9
  385. package/dist/session/thread/session-thread.d.ts +3 -1
  386. package/dist/session/thread/session-thread.js +9 -2
  387. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  388. package/dist/session/thread/thread-boot-rows.js +89 -0
  389. package/dist/session/thread/transcript-rows.d.ts +31 -0
  390. package/dist/session/thread/transcript-rows.js +3 -0
  391. package/dist/session/thread/transcript.d.ts +4 -9
  392. package/dist/session/thread/transcript.js +119 -21
  393. package/dist/session/thread/turn-share.d.ts +16 -0
  394. package/dist/session/thread/turn-share.js +162 -0
  395. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  396. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  397. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  398. package/dist/session/tool/tool-part-renderer.js +8 -3
  399. package/dist/session/tool/tools/apply-patch-tool.d.ts +1 -0
  400. package/dist/session/tool/tools/apply-patch-tool.js +1 -0
  401. package/dist/session/tool/tools/bash-tool.js +7 -6
  402. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  403. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  404. package/dist/session/tool/tools/codemode-tool.js +1 -1
  405. package/dist/session/tool/tools/connector-tools.js +1 -1
  406. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  407. package/dist/session/tool/tools/image-gen-tool.js +240 -53
  408. package/dist/session/tool/tools/pty-kill-tool.d.ts +1 -0
  409. package/dist/session/tool/tools/pty-kill-tool.js +1 -0
  410. package/dist/session/tool/tools/pty-read-tool.d.ts +2 -0
  411. package/dist/session/tool/tools/pty-read-tool.js +2 -0
  412. package/dist/session/tool/tools/pty-spawn-tool.d.ts +1 -0
  413. package/dist/session/tool/tools/pty-spawn-tool.js +1 -0
  414. package/dist/session/tool/tools/pty-write-tool.d.ts +1 -0
  415. package/dist/session/tool/tools/pty-write-tool.js +1 -0
  416. package/dist/session/tool/tools/show-tool.js +19 -8
  417. package/dist/session/tool/tools/todo-write-tool.d.ts +1 -0
  418. package/dist/session/tool/tools/todo-write-tool.js +1 -0
  419. package/dist/session/turn/channel-brand.d.ts +8 -3
  420. package/dist/session/turn/channel-brand.js +20 -4
  421. package/dist/session/turn/message-author-label.js +6 -2
  422. package/dist/session/turn/message-author.d.ts +8 -0
  423. package/dist/session/turn/message-author.js +24 -0
  424. package/dist/session/turn/message-row.d.ts +52 -0
  425. package/dist/session/turn/message-row.js +44 -0
  426. package/dist/session/turn/plan-anchor.d.ts +4 -1
  427. package/dist/session/turn/plan-anchor.js +4 -1
  428. package/dist/session/turn/plan-card.d.ts +7 -0
  429. package/dist/session/turn/plan-card.js +7 -0
  430. package/dist/session/turn/user-message.d.ts +7 -1
  431. package/dist/session/turn/user-message.js +21 -7
  432. package/dist/styles.css +1 -1
  433. package/dist/terminal/session-terminal-connect-bar.js +2 -1
  434. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  435. package/dist/workspace/home/access-requests-bell.js +20 -6
  436. package/dist/workspace/home/first-chat.d.ts +8 -21
  437. package/dist/workspace/home/first-chat.js +22 -72
  438. package/dist/workspace/index.d.ts +6 -0
  439. package/dist/workspace/index.js +6 -0
  440. package/dist/workspace/layout/project-home.d.ts +14 -2
  441. package/dist/workspace/layout/project-home.js +60 -21
  442. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  443. package/dist/workspace/layout/use-project-home-send.js +82 -3
  444. package/dist/workspace/memory/body-doc.d.ts +17 -0
  445. package/dist/workspace/memory/body-doc.js +208 -0
  446. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  447. package/dist/workspace/memory/body-extensions.js +103 -0
  448. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  449. package/dist/workspace/memory/company-memory-page.js +16 -0
  450. package/dist/workspace/memory/memory-all.d.ts +20 -0
  451. package/dist/workspace/memory/memory-all.js +27 -0
  452. package/dist/workspace/memory/memory-body.d.ts +19 -0
  453. package/dist/workspace/memory/memory-body.js +139 -0
  454. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  455. package/dist/workspace/memory/memory-empty.js +28 -0
  456. package/dist/workspace/memory/memory-history.d.ts +27 -0
  457. package/dist/workspace/memory/memory-history.js +108 -0
  458. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  459. package/dist/workspace/memory/memory-labels.js +47 -0
  460. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  461. package/dist/workspace/memory/memory-page-list.js +156 -0
  462. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  463. package/dist/workspace/memory/memory-reader.js +123 -0
  464. package/dist/workspace/memory/memory-view.d.ts +21 -0
  465. package/dist/workspace/memory/memory-view.js +124 -0
  466. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  467. package/dist/workspace/memory/remember-popover.js +61 -0
  468. package/dist/workspace/memory/remember-this.d.ts +12 -0
  469. package/dist/workspace/memory/remember-this.js +89 -0
  470. package/dist/workspace/memory/source-mark.d.ts +18 -0
  471. package/dist/workspace/memory/source-mark.js +79 -0
  472. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  473. package/dist/workspace/memory/used-memory-chip.js +61 -0
  474. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  475. package/dist/workspace/new/advanced-fields.js +2 -2
  476. package/dist/workspace/new/source-param.d.ts +1 -1
  477. package/dist/workspace/new/source-param.js +3 -1
  478. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  479. package/dist/workspace/new/use-create-workspace.js +3 -3
  480. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  481. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  482. package/dist/workspace/projects/policies-panel.js +5 -3
  483. package/dist/workspace/review/review-actions.d.ts +4 -2
  484. package/dist/workspace/review/review-actions.js +8 -2
  485. package/dist/workspace/review/review-center.js +11 -7
  486. package/dist/workspace/review/review-detail.d.ts +10 -0
  487. package/dist/workspace/review/review-detail.js +101 -13
  488. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  489. package/dist/workspace/saved-session-skeleton.js +3 -3
  490. package/dist/workspace/session-workspace.js +15 -13
  491. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  492. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  493. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  494. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  495. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  496. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  497. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  498. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  499. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  500. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  501. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  502. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  503. package/dist/workspace/sidebar/project-session-list.js +68 -56
  504. package/dist/workspace/sidebar/project-sidebar.js +9 -2
  505. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  506. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  507. package/dist/workspace/sidebar/session-brief-hover-card.js +28 -1
  508. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  509. package/dist/workspace/sidebar/session-group-order.js +25 -0
  510. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  511. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  512. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  513. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  514. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  515. package/dist/workspace/spaces/channel-glyph.js +6 -0
  516. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  517. package/dist/workspace/spaces/channel-setup.js +105 -0
  518. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  519. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  520. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  521. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  522. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  523. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  524. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  525. package/dist/workspace/spaces/space-agents.js +10 -0
  526. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  527. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  528. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  529. package/dist/workspace/spaces/space-link-label.js +73 -0
  530. package/dist/workspace/spaces/space-links.d.ts +19 -0
  531. package/dist/workspace/spaces/space-links.js +230 -0
  532. package/dist/workspace/spaces/space-members.d.ts +46 -0
  533. package/dist/workspace/spaces/space-members.js +182 -0
  534. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  535. package/dist/workspace/spaces/space-roster.js +44 -0
  536. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  537. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  538. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  539. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  540. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  541. package/dist/workspace/spaces/space-timeline.js +183 -0
  542. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  543. package/dist/workspace/spaces/space-triggers.js +78 -0
  544. package/dist/workspace/spaces/space-view.d.ts +37 -0
  545. package/dist/workspace/spaces/space-view.js +436 -0
  546. package/package.json +31 -32
  547. package/skills/kortix-ui/SKILL.md +3 -3
  548. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  549. package/skills/kortix-ui/references/modules.md +28 -4
  550. package/skills/kortix-ui/references/theming.md +1 -1
  551. package/dist/customize/agents/agent-nav.prototype.d.ts +0 -35
  552. package/dist/customize/agents/agent-nav.prototype.js +0 -95
  553. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  554. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  555. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  556. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  557. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  558. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  559. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  560. package/dist/customize/sections/connector-connection-header.js +0 -33
  561. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  562. package/dist/customize/sections/connector-connection-modal.js +0 -72
  563. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  564. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  565. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  566. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  567. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  568. package/dist/customize/sections/discover-catalogue.js +0 -132
  569. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  570. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  571. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  572. package/dist/files/project/components/drive-empty-art.js +0 -5
  573. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  574. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  575. package/dist/internal/share/public-share-link-button.js +0 -17
  576. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -231,4 +231,9 @@ export const KORTIX_PERMISSIONS_CATALOG = [
231
231
  actions: ['project.room.read', 'project.room.write'],
232
232
  featureFlag: 'agent_rooms',
233
233
  },
234
+ {
235
+ group: 'Artifacts',
236
+ actions: ['project.artifact.read', 'project.artifact.write', 'project.artifact.manage', 'project.artifact.public'],
237
+ featureFlag: 'artifacts',
238
+ },
234
239
  ];
@@ -1,3 +1,7 @@
1
- export declare function ChannelsSection({ projectId }: {
1
+ /** Reserved slug for the built-in Email channel (see api connectors.ts). */
2
+ /** A Kortix channel's own page (`platform`), or every channel (the Channels page). */
3
+ export type ChannelPlatform = 'slack' | 'teams' | 'email' | 'telegram';
4
+ export declare function ChannelsSection({ projectId, platform }: {
2
5
  projectId: string;
6
+ platform?: ChannelPlatform;
3
7
  }): import("react").JSX.Element;
@@ -75,64 +75,42 @@ import { Button } from '../../../primitives/button.js';
75
75
  import { Field, FieldDescription, FieldGroup, FieldTitle } from '../../../primitives/field.js';
76
76
  import { InfoBanner } from '../../../primitives/info-banner.js';
77
77
  import { InputGroupSearch, InputGroupSearchClear, InputGroupSearchIcon, InputGroupSearchInput, } from '../../../primitives/input-group.js';
78
- import { Label } from '../../../primitives/label.js';
79
78
  import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, } from '../../../primitives/modal.js';
80
79
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../../primitives/select.js';
81
80
  import { Skeleton } from '../../../primitives/skeleton.js';
82
81
  import { Tabs, TabsListCompact, TabsTriggerCompact } from '../../../primitives/tabs.js';
83
82
  import Loading from '../../../primitives/loading.js';
84
83
  import { errorToast, infoToast, successToast, warningToast } from '../../../primitives/toast.js';
85
- import { MicrosoftTeams } from '../../../internal/icons/microsoft-teams.js';
86
- import { Slack } from '../../../internal/icons/slack.js';
87
84
  import { ModelSelector } from '../../../session/models/model-selector.js';
88
85
  import { AgentSelector } from '../../../session/composer/session-chat-input.js';
89
86
  import { ChannelDisconnectButton, ChannelRow, } from '../component/channel-row.js';
90
- import { TeamsConnectCard } from '../component/teams-connect-card.js';
87
+ import { TeamsChannelMock, TeamsConnectCard } from '../component/teams-connect-card.js';
91
88
  import { TelegramChannelRow } from '../component/telegram-channel-row.js';
92
- import { SlackConnectCard } from '../component/slack-connect-card.js';
93
- import { EmailConnectForm } from '../connectors-view.js';
89
+ import { SlackChannelMock, SlackConnectCard } from '../component/slack-connect-card.js';
90
+ import { ChannelHeroLayoutProvider } from '../component/channel-hero-frame.js';
91
+ import { EmailHero } from '../../connectors/detail/email-inboxes.js';
94
92
  import { ChannelBrandMark } from '../../../session/turn/channel-brand.js';
95
93
  import { channelSettingsPatch, } from './channel-settings-patch.js';
96
94
  import { slackConversationName } from '../../../session/turn/channel-message.js';
97
95
  import { bindingTabs } from './channel-binding-tabs.js';
98
- import { projectSettingsSectionHref } from '../../project-settings/project-settings-sections.js';
99
96
  import { AccessRow } from '../../../access/access/access-row.js';
100
97
  import { useChannelBindings, useUpdateChannelBinding, } from '../../../internal/hooks/use-channel-bindings.js';
101
- import { useDisconnectEmail, useDisconnectSlack, useEmailInstall, useSlackInstall, useSlackMode, } from '../../../internal/hooks/channels/use-channels-installations.js';
98
+ import { useDisconnectSlack, useSlackInstall, useSlackMode, } from '../../../internal/hooks/channels/use-channels-installations.js';
102
99
  import { useDisconnectTeams, useTeamsInstall, useTeamsMode, } from '@kortix/sdk/react';
103
100
  import { modelRefToKey } from '@kortix/sdk';
104
101
  import { PROJECT_ACTIONS } from '../../../internal/lib/project-actions.js';
105
102
  import { useProjectCan } from '../../../internal/lib/use-project-can.js';
106
103
  import { cn } from '../../../internal/lib/utils.js';
107
104
  import { flattenModels, modelProviderMode, useFeatureFlag, useRuntimeProviders, useVisibleAgents, } from '@kortix/sdk/react';
108
- import { AtIcon, CaretLeftIcon, CaretRightIcon, EnvelopeIcon, MagnifyingGlassIcon, WarningCircleIcon, } from '@phosphor-icons/react';
105
+ import { AtIcon, CaretLeftIcon, CaretRightIcon, MagnifyingGlassIcon, WarningCircleIcon, } from '@phosphor-icons/react';
109
106
  import { UiLink as Link, useUiPathname, useUiRouter, useUiSearchParams } from '../../../providers/ui-provider.js';
110
107
  import { useEffect, useMemo, useState } from 'react';
111
- /** Reserved slug for the built-in Email channel (see api connectors.ts). */
112
- const EMAIL_CONNECTOR_SLUG = 'kortix_email';
113
- /**
114
- * Skeleton shapes match what replaces them: one tall hero panel, then two
115
- * short rows. Matching the shape is the point — a placeholder that settles
116
- * into a different geometry reads as a layout jump, not as loading.
117
- */
118
- const CHANNEL_LOADING_ROWS = ['channel-loading-1', 'channel-loading-2'];
119
- export function ChannelsSection({ projectId }) {
108
+ import { useTunnelConnections } from '@kortix/sdk/react';
109
+ import { ComputerHero } from '../../connectors/detail/computer-app-page.js';
110
+ import { FeatureGateScreen } from '../../shared/feature-gate-screen.js';
111
+ export function ChannelsSection({ projectId, platform }) {
120
112
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
121
113
  useTeamsInstallReturnToast();
122
- // This view used to read the flags off the project SUMMARY query
123
- // (`qk.project.summary` / `getProject`, whose payload nests them one level
124
- // shallower). It now reads the one gating primitive, which is backed by
125
- // `qk.project.detail` — the entry the Customize panel that hosts this view
126
- // already holds, so the switch removes a fetch rather than adding one.
127
- //
128
- // The LOADING semantics are preserved deliberately: unlike its siblings, this
129
- // surface WAITS on the flag before painting (`emailFlag.isLoading` feeds
130
- // `loading` below), so the header action cannot flash the wrong state, and
131
- // `useEmailInstall` stays unfired until the flag resolves.
132
- const emailFlag = useFeatureFlag(projectId, 'agentmail_email');
133
- const emailChannelEnabled = emailFlag.enabled;
134
- // Telegram is a channel connector behind connectors_v2; off, it is not listed.
135
- const telegramEnabled = useFeatureFlag(projectId, 'connectors_v2').enabled;
136
114
  const { data: install, isLoading: loadingInstall } = useSlackInstall(projectId);
137
115
  const { data: mode, isLoading: loadingMode } = useSlackMode(projectId);
138
116
  // Teams is on for every project (its feature flag graduated on 2026-10-01).
@@ -140,11 +118,12 @@ export function ChannelsSection({ projectId }) {
140
118
  const { data: teamsMode } = useTeamsMode(projectId);
141
119
  // Not connected, Teams gets the same hero as Slack; connected, it is a row.
142
120
  const teamsHero = !teamsInstall && Boolean(teamsMode?.enabled);
143
- const { data: emailInstall, isLoading: loadingEmail } = useEmailInstall(emailChannelEnabled ? projectId : null, EMAIL_CONNECTOR_SLUG);
144
- const loading = loadingInstall ||
145
- loadingMode ||
146
- emailFlag.isLoading ||
147
- (emailChannelEnabled && loadingEmail);
121
+ // Email (Resend Inboxes) is experimental behind `email_channel`. Off, it is on
122
+ // no surface, and its inboxes are never read (EmailHero is not mounted).
123
+ const emailFlag = useFeatureFlag(projectId, 'email_channel');
124
+ const emailEnabled = emailFlag.enabled;
125
+ const loading = loadingInstall || loadingMode || emailFlag.isLoading;
126
+ const tPages = useTranslations('connectorPages');
148
127
  const oauthInstallUrl = mode?.oauth_available ? mode.install_url : null;
149
128
  const canWrite = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_CONNECTOR_WRITE).allowed === true;
150
129
  // Each platform's row shows how many conversations it has bound and opens
@@ -154,29 +133,50 @@ export function ChannelsSection({ projectId }) {
154
133
  const channelCounts = new Map(bindingTabs(bindingsQuery.data?.bindings ?? []).map((tab) => [tab.platform, tab.count]));
155
134
  const [channelsDialog, setChannelsDialog] = useState({ open: false, platform: 'slack', session: 0 });
156
135
  const openChannels = (platform) => setChannelsDialog((dialog) => ({ open: true, platform, session: dialog.session + 1 }));
157
- // Once Slack is connected it stops being the headline and becomes a peer of
158
- // Email and Teams — same row, same list. So the "More channels" label only
159
- // earns its place while the hero is above it; with Slack in the list, the
160
- // rows ARE the channel list and the section header already says "Channels".
161
- // The list always has the Teams row.
162
- const slackRow = Boolean(install);
163
- const showMoreLabel = !slackRow;
136
+ // Every channel draws as a hero, connected or not: its own page shows one
137
+ // platform, the Channels tab every platform, one under the other.
138
+ const platforms = platform
139
+ ? [platform]
140
+ : ['slack', 'teams', ...(emailEnabled ? ['email'] : []), 'telegram'];
141
+ // The Kortix tab also holds the computer, where this deployment can pair one
142
+ // (the machine list answers 503 where computers are off).
143
+ const computersEnabled = useTunnelConnections({ refetchInterval: false }).isSuccess;
144
+ const showComputer = !platform && computersEnabled;
145
+ const hero = (pf) => {
146
+ switch (pf) {
147
+ case 'slack':
148
+ return install ? (_jsxs(_Fragment, { children: [_jsx(SlackChannelRow, { projectId: projectId, installation: install, canWrite: canWrite, channelCount: channelCounts.get('slack') ?? 0, onOpenChannels: () => openChannels('slack') }), _jsx(SlackFollowUp, { projectId: projectId })] })) : (_jsx(SlackConnectCard, { projectId: projectId, oauthInstallUrl: oauthInstallUrl, canWrite: canWrite }));
149
+ case 'teams':
150
+ return teamsHero && teamsMode ? (_jsx(TeamsConnectCard, { projectId: projectId, mode: teamsMode, canWrite: canWrite })) : (_jsxs(_Fragment, { children: [_jsx(TeamsChannelRow, { projectId: projectId, canWrite: canWrite, channelCount: channelCounts.get('teams') ?? 0, onOpenChannels: () => openChannels('teams') }), teamsInstall?.appUpdateAvailable ? (_jsx(TeamsAppUpdateNotice, { install: teamsInstall, tI18nComplete: tI18nComplete })) : null] }));
151
+ case 'email':
152
+ // Each inbox is an account on `kortix_email`: the hero counts them, Manage lists them.
153
+ return _jsx(EmailHero, { projectId: projectId, canWrite: canWrite });
154
+ case 'telegram':
155
+ return _jsx(TelegramChannelRow, { projectId: projectId, canWrite: canWrite });
156
+ }
157
+ };
158
+ // The Email page with the flag off: the standard flag-off screen, with its enable action.
159
+ if (platform === 'email' && !emailFlag.isLoading && !emailEnabled) {
160
+ return (_jsx(FeatureGateScreen, { featureKey: "email_channel", featureName: tPages('emailGateName'), description: tPages('emailGateDescription') }));
161
+ }
164
162
  return (
165
- /* Full width of the Connectors shell, like the All and Connected scopes
166
- beside it: the connect heroes are split cards whose chat preview needs
167
- the room, and a capped column left a dead band to the right of the
168
- scope tabs.
169
-
170
- No heading and no scroll container here. Both belong to the
171
- `CapabilityPageShell` in `connectors-page.tsx`; a second of either would
172
- print a second `<h1>` and scroll the wrong box. */
173
- _jsx("div", { className: "w-full space-y-6", children: loading ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-64 rounded-md" }), _jsx("div", { className: "space-y-2", children: CHANNEL_LOADING_ROWS.map((key) => (_jsx(Skeleton, { className: "h-14 rounded-md" }, key))) })] })) : (_jsxs(_Fragment, { children: [install ? null : (_jsx(SlackConnectCard, { projectId: projectId, oauthInstallUrl: oauthInstallUrl, canWrite: canWrite })), teamsHero && teamsMode ? (_jsx(TeamsConnectCard, { projectId: projectId, mode: teamsMode, canWrite: canWrite })) : null, _jsxs("section", { className: "space-y-2", children: [showMoreLabel ? _jsx(Label, { children: tI18nComplete.raw('text28647129955c') }) : null, _jsxs("ul", { className: "space-y-2", children: [install ? (_jsx(SlackChannelRow, { projectId: projectId, installation: install, canWrite: canWrite, channelCount: channelCounts.get('slack') ?? 0, onOpenChannels: () => openChannels('slack') })) : null, _jsx(EmailChannelRow, { projectId: projectId, enabled: emailChannelEnabled, installation: emailInstall ?? null, canWrite: canWrite }), telegramEnabled ? _jsx(TelegramChannelRow, { projectId: projectId, canWrite: canWrite }) : null, teamsHero ? null : (_jsx(TeamsChannelRow, { projectId: projectId, canWrite: canWrite, channelCount: channelCounts.get('teams') ?? 0, onOpenChannels: () => openChannels('teams') }))] }), teamsInstall?.appUpdateAvailable ? (_jsx(TeamsAppUpdateNotice, { install: teamsInstall, tI18nComplete: tI18nComplete })) : null] }), install ? _jsx(SlackFollowUp, { projectId: projectId }) : null, _jsx(ChannelBindingsDialog, { projectId: projectId, canWrite: canWrite, platform: channelsDialog.platform, open: channelsDialog.open, onOpenChange: (open) => setChannelsDialog((dialog) => ({ ...dialog, open })) }, channelsDialog.session)] })) }));
163
+ /* Full width of the Connectors shell: the heroes are split cards whose
164
+ chat preview needs the room. No heading and no scroll container here;
165
+ both belong to the `CapabilityPageShell` in `connectors-page.tsx`. */
166
+ _jsx(ChannelHeroLayoutProvider, { children: _jsxs("div", { className: "w-full space-y-6", children: [loading
167
+ ? platforms.map((pf) => _jsx(Skeleton, { className: "h-72 w-full rounded-lg" }, pf))
168
+ : platforms.map((pf) => (_jsx("div", { className: "space-y-4", children: hero(pf) }, pf))), showComputer && !loading ? _jsx(ComputerHero, { projectId: projectId }) : null, _jsx(ChannelBindingsDialog, { projectId: projectId, canWrite: canWrite, platform: channelsDialog.platform, open: channelsDialog.open, onOpenChange: (open) => setChannelsDialog((dialog) => ({ ...dialog, open })) }, channelsDialog.session)] }) }));
174
169
  }
175
170
  /** Slack as a peer row, once it is connected. */
176
171
  function SlackChannelRow({ projectId, installation, canWrite, channelCount, onOpenChannels, }) {
177
172
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
173
+ const tPages = useTranslations('connectorPages');
178
174
  const disconnect = useDisconnectSlack();
179
- return (_jsx(ChannelRow, { icon: _jsx(Slack, { className: "size-5 shrink-0" }), name: "Slack", connected: true, detail: installation.workspaceName ?? installation.workspaceId, pitch: tI18nComplete.raw('text9bd1c37ed121'), actions: _jsxs(_Fragment, { children: [channelCount > 0 ? _jsx(ChannelsButton, { count: channelCount, onOpen: onOpenChannels }) : null, canWrite ? (_jsx(ChannelDisconnectButton, { pending: disconnect.isPending, onConfirm: (done) => disconnect.mutate(projectId, {
175
+ return (_jsx(ChannelRow, { app: "slack", name: "Slack", connected: true, detail: installation.workspaceName ?? installation.workspaceId, pitch: tI18nComplete.raw('text9bd1c37ed121'), hero: {
176
+ title: tI18nComplete.raw('text89e9e20668f3'),
177
+ connectedTitle: tPages('channelConnectedTitle', { name: 'Slack' }),
178
+ preview: _jsx(SlackChannelMock, {}),
179
+ }, actions: _jsxs(_Fragment, { children: [channelCount > 0 ? _jsx(ChannelsButton, { count: channelCount, onOpen: onOpenChannels }) : null, canWrite ? (_jsx(ChannelDisconnectButton, { pending: disconnect.isPending, onConfirm: (done) => disconnect.mutate(projectId, {
180
180
  onSuccess: () => {
181
181
  done();
182
182
  successToast(tI18nComplete.raw('textd948c285986a'));
@@ -280,7 +280,6 @@ function BindingOverrides({ binding, policies, }) {
280
280
  return (_jsxs("span", { title: describeEffectiveModel(binding), className: cn('inline-flex items-center gap-1', overrides && 'text-foreground'), children: [modelUnavailable ? (_jsx(WarningCircleIcon, { weight: "fill", className: "text-kortix-orange size-3.5 shrink-0" })) : null, overrides || tI18nComplete.raw('texte8cb80e5c5cb')] }));
281
281
  }
282
282
  /** The schedule modal's field frame, around each picker in the settings dialog. */
283
- const FIELD_FRAME = 'bg-popover flex w-full items-center rounded-md border px-2 py-1.5';
284
283
  /** Rows before the list grows a search field — the `AgentSelector` rule (7). */
285
284
  const BINDING_SEARCH_MIN = 7;
286
285
  const CONVERSATION_POLICIES = [
@@ -377,9 +376,6 @@ function ChannelSettingsModalContent({ projectId, binding, name, scope, projectD
377
376
  const policy = policyDraft ?? binding.conversationPolicy;
378
377
  const patch = channelSettingsPatch({ agentName: binding.agentName, model: boundModel, conversationPolicy: binding.conversationPolicy }, { agentName, model, conversationPolicy: policy });
379
378
  const dirty = Object.keys(patch).length > 0;
380
- // The pickers refuse to open when disabled but do not dim; dim them like the
381
- // disabled Select, which dims itself.
382
- const pickerFrame = cn(FIELD_FRAME, !canWrite && 'opacity-50');
383
379
  const update = useUpdateChannelBinding();
384
380
  const save = (e) => {
385
381
  e.preventDefault();
@@ -393,11 +389,11 @@ function ChannelSettingsModalContent({ projectId, binding, name, scope, projectD
393
389
  onError: (error) => errorToastFallback(error, tI18nComplete),
394
390
  });
395
391
  };
396
- return (_jsxs(ModalContent, { className: "lg:max-w-lg", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: tI18nComplete.raw('textafc219f2a1e7') }), _jsx(ModalDescription, { children: tI18nComplete.raw('text95112f275fba') })] }), _jsxs("form", { onSubmit: save, children: [_jsxs(ModalBody, { className: "max-h-[calc(100dvh-15rem)] space-y-5 overflow-y-auto pt-4", children: [_jsxs("div", { className: "bg-popover flex min-w-0 items-center gap-3 rounded-md border px-3 py-2.5", children: [_jsx(BindingBrandMark, { platform: binding.platform }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-sm font-medium", title: binding.channelId, children: name }), _jsx("p", { className: "text-muted-foreground truncate text-xs", children: scope })] })] }), _jsxs(FieldGroup, { className: "gap-5", children: [_jsxs(Field, { "data-disabled": !canWrite, children: [_jsx(FieldTitle, { children: tI18nComplete.raw('text11b39c93777e') }), _jsx("div", { className: pickerFrame, children: _jsx(AgentSelector, { agents: agents, selectedAgent: agentName ?? defaultAgentLabel, onSelect: (v) => setAgentDraft(!v || v === defaultAgentLabel ? null : v), disabled: !canWrite }) }), _jsx(FieldDescription, { className: "text-xs", children: tI18nComplete.raw('text12dc6dbd8fc8') })] }), _jsxs(Field, { "data-disabled": !canWrite, children: [_jsx(FieldTitle, { children: tI18nComplete.raw('text5e2c614c23f0') }), _jsx("div", { className: pickerFrame, children: _jsx(ModelSelector, { models: models, providers: providers, selectedModel: model, unsetLabel: tI18nComplete.raw('texte8cb80e5c5cb'), onSelect: setModelDraft, disabled: !canWrite }) }), _jsxs(FieldDescription, { className: "text-xs", children: [modelDraft === undefined &&
392
+ return (_jsxs(ModalContent, { className: "lg:max-w-lg", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: tI18nComplete.raw('textafc219f2a1e7') }), _jsx(ModalDescription, { children: tI18nComplete.raw('text95112f275fba') })] }), _jsxs("form", { onSubmit: save, children: [_jsxs(ModalBody, { className: "max-h-[calc(100dvh-15rem)] space-y-5 overflow-y-auto pt-4", children: [_jsxs("div", { className: "bg-popover flex min-w-0 items-center gap-3 rounded-md border px-3 py-2.5", children: [_jsx(BindingBrandMark, { platform: binding.platform }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-sm font-medium", title: binding.channelId, children: name }), _jsx("p", { className: "text-muted-foreground truncate text-xs", children: scope })] })] }), _jsxs(FieldGroup, { className: "gap-5", children: [_jsxs(Field, { "data-disabled": !canWrite, children: [_jsx(FieldTitle, { children: tI18nComplete.raw('text11b39c93777e') }), _jsx(AgentSelector, { agents: agents, selectedAgent: agentName ?? defaultAgentLabel, onSelect: (v) => setAgentDraft(!v || v === defaultAgentLabel ? null : v), disabled: !canWrite, appearance: "field" }), _jsx(FieldDescription, { className: "text-xs", children: tI18nComplete.raw('text12dc6dbd8fc8') })] }), _jsxs(Field, { "data-disabled": !canWrite, children: [_jsx(FieldTitle, { children: tI18nComplete.raw('text5e2c614c23f0') }), _jsx(ModelSelector, { models: models, providers: providers, selectedModel: model, unsetLabel: tI18nComplete.raw('texte8cb80e5c5cb'), onSelect: setModelDraft, disabled: !canWrite, appearance: "field" }), _jsxs(FieldDescription, { className: "text-xs", children: [modelDraft === undefined &&
397
393
  binding.effectiveModel.source !== 'explicit' &&
398
394
  (binding.opencodeModel || binding.effectiveModel.model)
399
395
  ? `${describeEffectiveModel(binding)}. `
400
- : null, tI18nComplete.raw('text9116af1ce384')] })] }), _jsxs(Field, { "data-disabled": !canWrite, children: [_jsx(FieldTitle, { children: tI18nComplete.raw('textb1ca871c6696') }), _jsx("div", { className: FIELD_FRAME, children: _jsxs(Select, { value: policy, onValueChange: (v) => setPolicyDraft(v), disabled: !canWrite, children: [_jsx(SelectTrigger, { variant: "transparent", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: conversationPolicies.map((p) => (_jsx(SelectItem, { value: p.value, children: p.label }, p.value))) })] }) }), _jsx(FieldDescription, { className: "text-xs", children: policyDescription(policy, tI18nComplete) })] })] })] }), _jsxs(ModalFooter, { className: "pt-2 pb-5 sm:justify-between", children: [_jsxs(Button, { type: "button", variant: "outline-ghost", className: "gap-1", onClick: onBack, children: [_jsx(CaretLeftIcon, { className: "size-3.5 shrink-0" }), tI18nComplete.raw('text76900f1bfd16')] }), canWrite ? (_jsxs(Button, { type: "submit", disabled: !dirty || update.isPending, children: [update.isPending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, tI18nComplete.raw('text1509f561f241')] })) : null] })] })] }));
396
+ : null, tI18nComplete.raw('text9116af1ce384')] })] }), _jsxs(Field, { "data-disabled": !canWrite, children: [_jsx(FieldTitle, { children: tI18nComplete.raw('textb1ca871c6696') }), _jsxs(Select, { value: policy, onValueChange: (v) => setPolicyDraft(v), disabled: !canWrite, children: [_jsx(SelectTrigger, { className: "h-9 w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: conversationPolicies.map((p) => (_jsx(SelectItem, { value: p.value, children: p.label }, p.value))) })] }), _jsx(FieldDescription, { className: "text-xs", children: policyDescription(policy, tI18nComplete) })] })] })] }), _jsxs(ModalFooter, { className: "pt-2 pb-5 sm:justify-between", children: [_jsxs(Button, { type: "button", variant: "outline-ghost", className: "gap-1", onClick: onBack, children: [_jsx(CaretLeftIcon, { className: "size-3.5 shrink-0" }), tI18nComplete.raw('text76900f1bfd16')] }), canWrite ? (_jsxs(Button, { type: "submit", disabled: !dirty || update.isPending, children: [update.isPending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, tI18nComplete.raw('text1509f561f241')] })) : null] })] })] }));
401
397
  }
402
398
  /** A conversation's display name: the Slack or Teams name, else its kind. */
403
399
  function bindingName(binding, tI18nComplete) {
@@ -560,6 +556,7 @@ function TeamsAppUpdateNotice({ install, tI18nComplete, }) {
560
556
  }
561
557
  function TeamsChannelRow({ projectId, canWrite, channelCount, onOpenChannels, }) {
562
558
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
559
+ const tPages = useTranslations('connectorPages');
563
560
  const { data: install } = useTeamsInstall(projectId);
564
561
  const { data: mode } = useTeamsMode(projectId);
565
562
  const disconnect = useDisconnectTeams();
@@ -583,29 +580,14 @@ function TeamsChannelRow({ projectId, canWrite, channelCount, onOpenChannels, })
583
580
  const detail = install?.publishState === 'failed' && install.publishError
584
581
  ? `${install.teamName ?? install.tenantId} · ${install.publishError}`
585
582
  : (install?.teamName ?? install?.tenantId ?? null);
586
- return (_jsx(ChannelRow, { icon: _jsx(MicrosoftTeams, { className: "size-5 shrink-0" }), name: "Microsoft Teams", connected: connected, detail: detail, pitch: tI18nComplete.raw('text9225e456b795'), badge: install ? _jsx(TeamsPublishBadge, { install: install, tI18nComplete: tI18nComplete }) : null, actions: _jsxs(_Fragment, { children: [connected && channelCount > 0 ? (_jsx(ChannelsButton, { count: channelCount, onOpen: onOpenChannels })) : null, !canWrite ? null : connected ? (_jsxs(_Fragment, { children: [deepLinkUrl ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: deepLinkUrl, target: "_blank", rel: "noopener noreferrer", children: tI18nComplete.raw('text1fece1858ee9') }) })) : null, retryUrl ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: retryUrl, target: "_blank", rel: "noopener noreferrer", children: retryLabel }) })) : null, _jsx(ChannelDisconnectButton, { pending: disconnect.isPending, onConfirm: (done) => disconnect.mutate(projectId, {
583
+ return (_jsx(ChannelRow, { app: "teams", name: "Microsoft Teams", connected: connected, detail: detail, pitch: tI18nComplete.raw('text9225e456b795'), hero: {
584
+ title: tI18nComplete.raw('textc1bd5ca19f5f'),
585
+ connectedTitle: tPages('channelConnectedTitle', { name: 'Microsoft Teams' }),
586
+ preview: _jsx(TeamsChannelMock, {}),
587
+ }, badge: install ? _jsx(TeamsPublishBadge, { install: install, tI18nComplete: tI18nComplete }) : null, actions: _jsxs(_Fragment, { children: [connected && channelCount > 0 ? (_jsx(ChannelsButton, { count: channelCount, onOpen: onOpenChannels })) : null, !canWrite ? null : connected ? (_jsxs(_Fragment, { children: [deepLinkUrl ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: deepLinkUrl, target: "_blank", rel: "noopener noreferrer", children: tI18nComplete.raw('text1fece1858ee9') }) })) : null, retryUrl ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: retryUrl, target: "_blank", rel: "noopener noreferrer", children: retryLabel }) })) : null, _jsx(ChannelDisconnectButton, { pending: disconnect.isPending, onConfirm: (done) => disconnect.mutate(projectId, {
587
588
  onSuccess: () => {
588
589
  done();
589
590
  successToast(tI18nComplete.raw('textf2e69a5e24ba'));
590
591
  },
591
- }) })] })) : installUrl ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: installUrl, target: "_blank", rel: "noopener noreferrer", children: tI18nComplete.raw('text1a2303ede074') }) })) : null] }) }));
592
- }
593
- function EmailChannelRow({ projectId, enabled, installation, canWrite, }) {
594
- const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
595
- const disconnect = useDisconnectEmail();
596
- const [connectOpen, setConnectOpen] = useState(false);
597
- const connected = Boolean(installation);
598
- return (_jsxs(_Fragment, { children: [_jsx(ChannelRow, { icon: _jsx(EnvelopeIcon, { className: "text-muted-foreground size-5 shrink-0" }), name: "Email", connected: connected, detail: installation?.email ?? null, pitch: enabled
599
- ? tI18nComplete.raw('text27ba4ec98716')
600
- : // `FeatureGateScreen`'s exact words for a flag that is off, with
601
- // the name the Feature flags section lists the flag under.
602
- `AgentMail Email ${tI18nComplete.raw('text26965989cce5')}`, actions: !enabled ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: projectSettingsSectionHref(projectId, 'feature-flags'), children: tI18nComplete.raw('text20a2e59ba129') }) })) : !canWrite ? null : connected ? (_jsx(ChannelDisconnectButton, { pending: disconnect.isPending, onConfirm: (done) => disconnect.mutate({ projectId, connectorSlug: EMAIL_CONNECTOR_SLUG }, {
603
- onSuccess: () => {
604
- done();
605
- successToast(tI18nComplete.raw('text958c8e06d3e7'));
606
- },
607
- }) })) : (_jsx(Button, { size: "sm", variant: "secondary", onClick: () => setConnectOpen(true), children: tI18nComplete.raw('text1a2303ede074') })) }), _jsx(Modal, { open: connectOpen, onOpenChange: setConnectOpen, children: _jsxs(ModalContent, { className: "lg:max-w-2xl", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: tI18nComplete.raw('text3de5e2a29bbc') }), _jsx(ModalDescription, { children: tI18nComplete.raw('texte13e04973080') })] }), _jsx(ModalBody, { className: "max-h-[75vh] overflow-y-auto", children: _jsx(EmailConnectForm, { projectId: projectId, connectorSlug: EMAIL_CONNECTOR_SLUG, onConnected: () => {
608
- setConnectOpen(false);
609
- successToast(tI18nComplete.raw('text62c381e56f37'));
610
- } }) })] }) })] }));
592
+ }) })] })) : installUrl ? (_jsx(Button, { className: "transition-transform active:scale-96", asChild: true, children: _jsx(Link, { href: installUrl, target: "_blank", rel: "noopener noreferrer", children: tI18nComplete.raw('text1a2303ede074') }) })) : null] }) }));
611
593
  }
@@ -11,6 +11,8 @@ import { cn } from '../../../../internal/lib/utils.js';
11
11
  import { CostPanel, CostSection, MetricTab, RangeSelector, ShareBar, UsageChart, fmtCompact, fmtCredits, fmtMs, weightedP50, } from './_metrics.js';
12
12
  import { displayModel } from './_shared.js';
13
13
  import { GatewayBudgetSection } from './gateway-budgets.js';
14
+ /** An LLM usage estimate in US dollars, to 4 decimals. */
15
+ const usd4 = (value) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 4, maximumFractionDigits: 4 }).format(value);
14
16
  const METRICS = [
15
17
  // Spend reads in credits; the tooltip appends the unit in the component.
16
18
  { key: 'cost', label: 'Spend', keys: ['cost'], fmt: (v) => fmtCredits(v) },
@@ -144,11 +146,17 @@ export function GatewayOverview({ projectId, canWrite = false, }) {
144
146
  // No scroller and no padding of its own: this is a tab of
145
147
  // `/projects/[id]/models`, and `CapabilityPageShell` owns the page's one
146
148
  // scroll container and its column.
147
- _jsx("div", { className: "flex flex-col", children: _jsxs("div", { className: "w-full space-y-12", children: [_jsxs("section", { className: "border-border bg-surface overflow-hidden rounded-xl border", children: [_jsxs("div", { className: "border-border flex flex-col border-b sm:flex-row", children: [_jsx("div", { role: "tablist", "aria-label": tI18nComplete.raw('text9e217716c4e0'), className: "flex min-w-0 flex-1", children: tabs.map((m) => (_jsx(MetricTab, { label: tab(m.key), value: m.value, unit: m.unit, selected: metric === m.key, onSelect: () => setMetric(m.key) }, m.key))) }), _jsx("div", { className: "border-border flex items-center border-t px-4 py-3 sm:border-t-0 sm:border-l sm:py-0", children: _jsx(RangeSelector, { days: days, setDays: setDays }) })] }), _jsxs("div", { className: "space-y-2 px-5 pt-6 pb-4", children: [_jsx("p", { className: "text-muted-foreground text-xs tabular-nums", children: tabs.find((m) => m.key === metric)?.sub }), _jsx(UsageChart, { data: series, keys: activeMetric.keys, yFormatter: activeMetric.key === 'cost'
149
+ _jsx("div", { className: "flex flex-col", children: _jsxs("div", { className: "w-full space-y-12", children: [_jsxs("section", { className: "border-border bg-surface overflow-hidden rounded-xl border", children: [_jsxs("div", { className: "border-border flex flex-col border-b sm:flex-row", children: [_jsx("div", { role: "tablist", "aria-label": tI18nComplete.raw('text9e217716c4e0'), className: "flex min-w-0 flex-1", children: tabs.map((m) => (_jsx(MetricTab, { label: tab(m.key), value: m.value, unit: m.unit, selected: metric === m.key, onSelect: () => setMetric(m.key) }, m.key))) }), _jsx("div", { className: "border-border flex items-center border-t px-4 py-3 sm:border-t-0 sm:border-l sm:py-0", children: _jsx(RangeSelector, { days: days, setDays: setDays }) })] }), _jsxs("div", { className: "space-y-2 px-5 pt-6 pb-4", children: [_jsx("p", { className: "text-muted-foreground text-xs tabular-nums", children: tabs.find((m) => m.key === metric)?.sub }), _jsxs("p", { className: "text-muted-foreground text-xs tabular-nums", children: [t('estimatedUsageValueLabel'), ' ', overview?.estimated_usage_value == null
150
+ ? t('unknownValue')
151
+ : usd4(overview.estimated_usage_value), ' · ', t('pricedRequests', { count: overview?.priced_requests ?? 0 }), ' · ', t('unpricedRequests', { count: overview?.unpriced_requests ?? 0 })] }), _jsxs("p", { className: "text-muted-foreground text-xs", children: [overview?.valuation?.coverage ?? t('estimateCoverageUnavailable'), " ", t('estimatesSeparate'), ' ', overview?.valuation?.rate_version] }), _jsx(UsageChart, { data: series, keys: activeMetric.keys, yFormatter: activeMetric.key === 'cost'
148
152
  ? (v) => `${credits(v)} ${creditsUnit}`
149
153
  : activeMetric.fmt })] })] }), _jsx(GatewayBudgetSection, { projectId: projectId, canWrite: canWrite }), _jsxs("div", { className: "flex flex-col gap-4 lg:flex-row", children: [_jsx(CostSection, { title: t('mostSpend'), description: t('mostSpendHint'), children: _jsx(CostPanel, { children: spend.named.length === 0 ? (_jsx("p", { className: "text-muted-foreground flex h-10 items-center text-xs", children: tI18nComplete.raw('textea923f45a415') })) : (_jsxs(_Fragment, { children: [spend.named.map(({ model, share }) => (_jsx(SpendRow, { label: displayModel(model.model) || 'unknown', value: `${credits(model.cost)} ${creditsUnit} · ${share}%` }, `${model.provider}/${model.model}`))), spend.rest ? (_jsx(SpendRow, { label: t('everythingElse'), value: `${credits(spend.rest.cost)} ${creditsUnit} · ${spend.rest.share}%` })) : null] })) }) }), _jsx(CostSection, { title: tI18nComplete.raw('textfec78985c8f3'), description: t('sessionsHint'), children: _jsx(CostPanel, { children: sessions.length === 0 ? (_jsx("p", { className: "text-muted-foreground flex h-10 items-center text-xs", children: tI18nComplete.raw('text0e25da739ad6') })) : (sessions.map((s) => {
150
154
  const name = sessionNames.get(s.session_id);
151
- return (_jsxs("div", { className: "border-border flex min-h-13 items-center gap-4 border-b py-2 last:border-b-0", "data-session-row": "", children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("span", { className: cn('text-foreground truncate text-xs', !name && 'font-mono'), children: name ?? s.session_id.slice(0, 8) }), _jsxs("span", { className: "text-muted-foreground truncate text-xs tabular-nums", children: [name ? _jsxs("span", { className: "font-mono", children: [s.session_id.slice(0, 8), " \u00B7 "] }) : null, t('sessionModel', { cost: credits(s.llm_cost) }), " \u00B7", ' ', t('sessionSandbox', { cost: credits(s.compute_cost) }), " \u00B7", ' ', s.requests.toLocaleString(), " ", tI18nComplete.raw('textc3f7bdf537c4')] })] }), _jsx(ShareBar, { className: "w-24", segments: [
155
+ return (_jsxs("div", { className: "border-border flex min-h-13 items-center gap-4 border-b py-2 last:border-b-0", "data-session-row": "", children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("span", { className: cn('text-foreground truncate text-xs', !name && 'font-mono'), children: name ?? s.session_id.slice(0, 8) }), _jsxs("span", { className: "text-muted-foreground truncate text-xs tabular-nums", children: [name ? (_jsxs("span", { className: "font-mono", children: [s.session_id.slice(0, 8), " \u00B7 "] })) : null, t('sessionModel', { cost: credits(s.llm_cost) }), " \u00B7", ' ', t('sessionSandbox', {
156
+ cost: credits(s.compute_cost),
157
+ }), ' ', "\u00B7 ", s.requests.toLocaleString(), " ", tI18nComplete.raw('textc3f7bdf537c4'), ' · ', t('llmEstimateLabel'), ' ', s.estimated_usage_value == null
158
+ ? t('unknownValue')
159
+ : usd4(s.estimated_usage_value)] })] }), _jsx(ShareBar, { className: "w-24", segments: [
152
160
  { pct: (s.llm_cost / maxSessionCost) * 100, color: 'var(--kortix-blue)' },
153
161
  {
154
162
  pct: (s.compute_cost / maxSessionCost) * 100,
@@ -53,7 +53,7 @@ import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
53
53
  * hook only runs once this tab is actually mounted, which `SettingsTabPane`
54
54
  * in `settings-panel.tsx` guarantees happens only while this tab is active.
55
55
  */
56
- import { useMemo, useRef, useState } from 'react';
56
+ import { useRef, useState } from 'react';
57
57
  import { Button } from '../../../primitives/button.js';
58
58
  import { InputGroupSearch, InputGroupSearchClear, InputGroupSearchIcon, InputGroupSearchInput, } from '../../../primitives/input-group.js';
59
59
  import Loading from '../../../primitives/loading.js';
@@ -70,6 +70,7 @@ import { getProject, updateFeatureFlag, } from '@kortix/sdk';
70
70
  import { contract, invalidateProject, qk } from '@kortix/sdk/react';
71
71
  import { FlagIcon, MagnifyingGlassIcon as Search } from '@phosphor-icons/react';
72
72
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
73
+ import { ChannelsSwitchDialog } from '../../shared/channels-switch-dialog.js';
73
74
  import { SettingsTabHeader } from '../settings-tab-header.js';
74
75
  export const DEFAULT_EXPERIMENTAL_COPY = {
75
76
  overridden: 'Overridden for this project',
@@ -256,22 +257,40 @@ export function ExperimentalTab({ projectId }) {
256
257
  ...f,
257
258
  enabled: pendingValues[f.key] ?? f.enabled,
258
259
  }));
259
- const features = useMemo(() => filterFeatures(withPending, query), [withPending, query]);
260
- const handleToggle = (key, next) => {
260
+ // the Channels switch changes the sidebar for everyone, so only a
261
+ // viewer who may flip it sees it (hidden while that answer loads).
262
+ const visible = canEdit ? withPending : withPending.filter((f) => f.key !== 'project_channels');
263
+ const features = filterFeatures(visible, query);
264
+ const apply = (key, next) => {
261
265
  setPendingValues((prev) => ({ ...prev, [key]: next }));
262
266
  toggleMutation.mutate({ key: key, next });
263
267
  };
264
- return (_jsx(ExperimentalTabView, { isLoading: projectQuery.isLoading, isError: projectQuery.isError, errorMessage: projectQuery.error?.message ?? '', onRetry: () => projectQuery.refetch(), features: features, pendingKeys: Object.keys(pendingValues), canManage: canEdit, canManageOperatorOnly: isOperator, onToggle: handleToggle, showPermissionNotice: !canEdit && !writeCap.isLoading, query: query, onQueryChange: setQuery, copy: {
265
- overridden: t('origin.overridden'),
266
- managedByKortix: tI18nComplete.raw('texte9ec6c0ad396'),
267
- defaultOn: t('origin.defaultOn'),
268
- defaultOff: t('origin.defaultOff'),
269
- search: t('search'),
270
- loadFailed: t('loadFailed'),
271
- retry: t('retry'),
272
- noMatches: (value) => t('noMatches', { query: value }),
273
- emptyTitle: t('emptyTitle'),
274
- emptyDescription: t('emptyDescription'),
275
- permission: t('permission'),
276
- } }));
268
+ // Channels asks first: the dialog says what changes for everyone.
269
+ const [channelsTarget, setChannelsTarget] = useState(null);
270
+ const handleToggle = (key, next) => {
271
+ if (key === 'project_channels')
272
+ setChannelsTarget(next);
273
+ else
274
+ apply(key, next);
275
+ };
276
+ const drive = rawFeatures.find((f) => f.key === 'drives');
277
+ return (_jsxs(_Fragment, { children: [_jsx(ChannelsSwitchDialog, { open: channelsTarget !== null, onOpenChange: (open) => !open && setChannelsTarget(null), turningOn: channelsTarget === true, projectName: project?.name ?? '', driveOff: !!drive && !drive.enabled && drive.operator_only !== true, onConfirm: (alsoDrive) => {
278
+ const target = channelsTarget === true;
279
+ setChannelsTarget(null);
280
+ apply('project_channels', target);
281
+ if (alsoDrive)
282
+ apply('drives', true);
283
+ } }), _jsx(ExperimentalTabView, { isLoading: projectQuery.isLoading, isError: projectQuery.isError, errorMessage: projectQuery.error?.message ?? '', onRetry: () => projectQuery.refetch(), features: features, pendingKeys: Object.keys(pendingValues), canManage: canEdit, canManageOperatorOnly: isOperator, onToggle: handleToggle, showPermissionNotice: !canEdit && !writeCap.isLoading, query: query, onQueryChange: setQuery, copy: {
284
+ overridden: t('origin.overridden'),
285
+ managedByKortix: tI18nComplete.raw('texte9ec6c0ad396'),
286
+ defaultOn: t('origin.defaultOn'),
287
+ defaultOff: t('origin.defaultOff'),
288
+ search: t('search'),
289
+ loadFailed: t('loadFailed'),
290
+ retry: t('retry'),
291
+ noMatches: (value) => t('noMatches', { query: value }),
292
+ emptyTitle: t('emptyTitle'),
293
+ emptyDescription: t('emptyDescription'),
294
+ permission: t('permission'),
295
+ } })] }));
277
296
  }
@@ -15,17 +15,6 @@ export declare function CatalogEmptyNote({ children }: {
15
15
  * spaces inside a monospace span, which reads as a rendering bug rather than as
16
16
  * a report of what was searched for.
17
17
  */
18
- export declare function CatalogNoMatch({ query, excludedNoActions, }: {
18
+ export declare function CatalogNoMatch({ query }: {
19
19
  query: string;
20
- /**
21
- * Apps that matched but expose no actions, so the catalogue does not offer
22
- * them.
23
- *
24
- * Without this the page reports a flat "No matches for SAP" — which is wrong
25
- * twice, because `sap_s_4hana_cloud` and `sap_s_4hana_cloud_sandbox` both
26
- * exist upstream and the reason they are absent is one we can state.
27
- * Reporting a bare zero is what made the catalogue look broken rather than
28
- * selective.
29
- */
30
- excludedNoActions?: number;
31
20
  }): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useTranslations } from '../../../i18n/index.js';
3
3
  /**
4
4
  * The "nothing here" line every catalog uses, so five hand-typed copies of one
@@ -16,7 +16,7 @@ export function CatalogEmptyNote({ children }) {
16
16
  * spaces inside a monospace span, which reads as a rendering bug rather than as
17
17
  * a report of what was searched for.
18
18
  */
19
- export function CatalogNoMatch({ query, excludedNoActions = 0, }) {
19
+ export function CatalogNoMatch({ query }) {
20
20
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
21
- return (_jsxs(CatalogEmptyNote, { children: [tI18nComplete.raw('texta8897de42124'), ' ', _jsx("span", { className: "text-foreground font-mono", children: query.trim() }), ".", excludedNoActions > 0 ? (_jsxs(_Fragment, { children: [" ", tI18nComplete('catalogExcludedNoActions', { count: excludedNoActions })] })) : null] }));
21
+ return (_jsxs(CatalogEmptyNote, { children: [tI18nComplete.raw('texta8897de42124'), ' ', _jsx("span", { className: "text-foreground font-mono", children: query.trim() }), "."] }));
22
22
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The confirm step of the project's Channels switch (`project_channels`):
3
+ * what turning it on or off changes for everyone in the project. Turning it
4
+ * on while Drive is off offers to turn Drive on too (channels get Files).
5
+ * Every surface that flips the flag asks through this dialog.
6
+ */
7
+ export declare function ChannelsSwitchDialog({ open, onOpenChange, turningOn, projectName, driveOff, pending, onConfirm, }: {
8
+ open: boolean;
9
+ onOpenChange: (open: boolean) => void;
10
+ /** The switch's target: on, or off. */
11
+ turningOn: boolean;
12
+ projectName: string;
13
+ /** Drive is off and the viewer could turn it on: offer it beside Channels. */
14
+ driveOff: boolean;
15
+ pending?: boolean;
16
+ /** `alsoDrive`: turn Drive on too. */
17
+ onConfirm: (alsoDrive: boolean) => void;
18
+ }): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId, useState } from 'react';
4
+ import { useTranslations } from '../../i18n/index.js';
5
+ import { Button } from '../../primitives/button.js';
6
+ import { Checkbox } from '../../primitives/checkbox.js';
7
+ import Loading from '../../primitives/loading.js';
8
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle } from '../../primitives/modal.js';
9
+ /**
10
+ * The confirm step of the project's Channels switch (`project_channels`):
11
+ * what turning it on or off changes for everyone in the project. Turning it
12
+ * on while Drive is off offers to turn Drive on too (channels get Files).
13
+ * Every surface that flips the flag asks through this dialog.
14
+ */
15
+ export function ChannelsSwitchDialog({ open, onOpenChange, turningOn, projectName, driveOff, pending = false, onConfirm, }) {
16
+ const t = useTranslations('settings.featureFlags.channelsSwitch');
17
+ const id = useId();
18
+ const [alsoDrive, setAlsoDrive] = useState(false);
19
+ const offerDrive = turningOn && driveOff;
20
+ return (_jsx(Modal, { open: open, onOpenChange: (next) => {
21
+ if (pending)
22
+ return;
23
+ if (!next)
24
+ setAlsoDrive(false);
25
+ onOpenChange(next);
26
+ }, children: _jsxs(ModalContent, { className: "lg:max-w-md", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: turningOn ? t('onTitle', { project: projectName }) : t('offTitle') }), _jsx(ModalDescription, { children: turningOn ? t('onBody') : t('offBody') })] }), offerDrive ? (_jsx(ModalBody, { children: _jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx(Checkbox, { id: `${id}-drive`, checked: alsoDrive, onCheckedChange: (value) => setAlsoDrive(value === true) }), _jsx("label", { htmlFor: `${id}-drive`, className: "text-sm", children: t('drive') })] }) })) : null, _jsxs(ModalFooter, { className: "sm:justify-between", children: [_jsx(Button, { type: "button", variant: "outline-ghost", disabled: pending, onClick: () => onOpenChange(false), children: t('cancel') }), _jsxs(Button, { type: "button", disabled: pending, "aria-busy": pending || undefined, onClick: () => {
27
+ onConfirm(offerDrive && alsoDrive);
28
+ setAlsoDrive(false);
29
+ }, children: [pending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, turningOn ? t('turnOn') : t('turnOff')] })] })] }) }));
30
+ }
@@ -4,12 +4,13 @@ import { useTranslations } from '../../i18n/index.js';
4
4
  import { UiLink, useUiParams } from '../../providers/ui-provider.js';
5
5
  import { Button } from '../../primitives/button.js';
6
6
  import { projectSettingsSectionHref } from '../project-settings/project-settings-sections.js';
7
+ import { ChannelsSwitchDialog } from './channels-switch-dialog.js';
7
8
  import { PROJECT_ACTIONS } from '../../internal/lib/project-actions.js';
8
9
  import { useProjectCan } from '../../internal/lib/use-project-can.js';
9
- import { updateFeatureFlag } from '@kortix/sdk';
10
- import { invalidateProject, qk } from '@kortix/sdk/react';
10
+ import { getProject, updateFeatureFlag } from '@kortix/sdk';
11
+ import { contract, invalidateProject, qk } from '@kortix/sdk/react';
11
12
  import { FlagIcon } from '@phosphor-icons/react';
12
- import { useMutation, useQueryClient } from '@tanstack/react-query';
13
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
13
14
  import { useState } from 'react';
14
15
  /** A disabled surface keeps its enable action and settings link in place. */
15
16
  export function FeatureGateScreen({ featureKey, featureName, description, internalOnly = false, }) {
@@ -21,11 +22,12 @@ export function FeatureGateScreen({ featureKey, featureName, description, intern
21
22
  const permission = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_SETTINGS_WRITE);
22
23
  const [error, setError] = useState('');
23
24
  const enable = useMutation({
24
- mutationFn: () => {
25
+ mutationFn: async (alsoDrive = false) => {
25
26
  if (!projectId || internalOnly || permission.isLoading || permission.allowed !== true) {
26
27
  throw new Error('Feature activation is not permitted');
27
28
  }
28
- return updateFeatureFlag(projectId, featureKey, true);
29
+ const updated = await updateFeatureFlag(projectId, featureKey, true);
30
+ return alsoDrive ? updateFeatureFlag(projectId, 'drives', true) : updated;
29
31
  },
30
32
  onSuccess: (updated) => {
31
33
  if (!projectId)
@@ -37,8 +39,24 @@ export function FeatureGateScreen({ featureKey, featureName, description, intern
37
39
  },
38
40
  onError: (cause) => setError(cause.message),
39
41
  });
40
- return (_jsx("div", { className: "bg-popover rounded-md border px-4 py-5", children: _jsxs("div", { className: "flex flex-col gap-5 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-start gap-3", children: [_jsx("span", { className: "bg-muted/50 flex size-9 shrink-0 items-center justify-center rounded-sm", children: _jsx(FlagIcon, { className: "text-muted-foreground size-5" }) }), _jsxs("div", { className: "min-w-0 space-y-1", children: [_jsxs("p", { className: "text-foreground text-sm font-medium", children: [featureName, " ", tI18nComplete.raw('text26965989cce5')] }), _jsx("p", { className: "text-muted-foreground max-w-xl text-xs text-pretty", children: description }), internalOnly ? (_jsx("p", { className: "text-muted-foreground max-w-xl text-xs text-pretty", children: tI18nComplete.raw('text1c41abcc2fff') })) : null] })] }), error ? (_jsx("p", { role: "alert", className: "text-destructive text-xs", children: error })) : null, projectId && !internalOnly ? (_jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(Button, { size: "sm", disabled: permission.isLoading || permission.allowed !== true || enable.isPending, onClick: () => {
41
- setError('');
42
- enable.mutate();
43
- }, children: enable.isPending ? t('enabling') : t('enable', { name: featureName }) }), _jsx(Button, { asChild: true, size: "sm", variant: "secondary", className: "shrink-0", children: _jsx(UiLink, { href: projectSettingsSectionHref(projectId, 'feature-flags'), children: tI18nComplete.raw('text20a2e59ba129') }) })] })) : null] }) }));
42
+ const channels = featureKey === 'project_channels';
43
+ const [confirming, setConfirming] = useState(false);
44
+ const project = useQuery({
45
+ queryKey: qk.project.summary(projectId ?? ''),
46
+ queryFn: () => getProject(projectId),
47
+ enabled: channels && !!projectId,
48
+ ...contract('config'),
49
+ });
50
+ const drive = project.data?.experimental_features?.find((f) => f.key === 'drives' && f.available);
51
+ return (_jsxs("div", { className: "bg-popover rounded-md border px-4 py-5", children: [channels ? (_jsx(ChannelsSwitchDialog, { open: confirming, onOpenChange: setConfirming, turningOn: true, projectName: project.data?.name ?? '', driveOff: !!drive && !drive.enabled && drive.operator_only !== true, onConfirm: (alsoDrive) => {
52
+ setConfirming(false);
53
+ enable.mutate(alsoDrive);
54
+ } })) : null, _jsxs("div", { className: "flex flex-col gap-5 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-start gap-3", children: [_jsx("span", { className: "bg-muted/50 flex size-9 shrink-0 items-center justify-center rounded-sm", children: _jsx(FlagIcon, { className: "text-muted-foreground size-5" }) }), _jsxs("div", { className: "min-w-0 space-y-1", children: [_jsxs("p", { className: "text-foreground text-sm font-medium", children: [featureName, " ", tI18nComplete.raw('text26965989cce5')] }), _jsx("p", { className: "text-muted-foreground max-w-xl text-xs text-pretty", children: description }), internalOnly ? (_jsx("p", { className: "text-muted-foreground max-w-xl text-xs text-pretty", children: tI18nComplete.raw('text1c41abcc2fff') })) : null] })] }), error ? (_jsx("p", { role: "alert", className: "text-destructive text-xs", children: error })) : null, projectId && !internalOnly ? (_jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(Button, { size: "sm", disabled: permission.isLoading || permission.allowed !== true || enable.isPending, onClick: () => {
55
+ setError('');
56
+ // Channels changes the sidebar for everyone: it asks first.
57
+ if (channels)
58
+ setConfirming(true);
59
+ else
60
+ enable.mutate(false);
61
+ }, children: enable.isPending ? t('enabling') : t('enable', { name: featureName }) }), _jsx(Button, { asChild: true, size: "sm", variant: "secondary", className: "shrink-0", children: _jsx(UiLink, { href: projectSettingsSectionHref(projectId, 'feature-flags'), children: tI18nComplete.raw('text20a2e59ba129') }) })] })) : null] })] }));
44
62
  }
@@ -30,7 +30,10 @@ export function RichRowBody({ icon: Glyph, title, description, }) {
30
30
  * A tab with one common case that needs no form leads with it (`quick`):
31
31
  * Connectors → "MCP server" (KRTX-2185).
32
32
  */
33
- export function NewEntityMenu({ label = 'New', size = 'sm', variant = 'secondary', caret = true, pending = false, onChat, manual, quick, }) {
33
+ export function NewEntityMenu({ label = 'New',
34
+ // `default` is `h-9`, the height of the `size="sm"` search input every
35
+ // Customize header puts beside it. `sm` (`h-8`) left the pair 4px apart.
36
+ size = 'default', variant = 'secondary', caret = true, pending = false, onChat, manual, quick, }) {
34
37
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
35
38
  if (!manual) {
36
39
  return (_jsxs(Button, { variant: variant, size: size, className: "gap-1.5", disabled: pending, onClick: onChat, children: [pending ? _jsx(Loading, { className: "size-4 shrink-0" }) : _jsx(PlusIcon, { className: "size-4" }), label] }));
@@ -18,7 +18,7 @@
18
18
  * - A longer `gcTime` keeps the entries through a long session on another
19
19
  * route; the default five minutes would drop them before Customize opens.
20
20
  */
21
- import { getConnectStatus, getModelDefaults, getProject, getProjectModelPicker, listConnectors, listProjectBranches, listProjectResourceGrants, listProjectSandboxTemplates, listProjectSecrets, listProjectSnapshots, listProjectTriggers, listReviewItems } from '@kortix/sdk';
21
+ import { getModelDefaults, getProject, getProjectModelPicker, listConnectors, listProjectBranches, listProjectResourceGrants, listProjectSandboxTemplates, listProjectSecrets, listProjectSnapshots, listProjectTriggers, listReviewItems } from '@kortix/sdk';
22
22
  import { type QueryClient } from '@tanstack/react-query';
23
23
  /** Keep prefetched Customize data for half an hour without an observer. */
24
24
  export declare const CUSTOMIZE_PREFETCH_GC_MS: number;
@@ -35,11 +35,10 @@ export interface CustomizePrefetchGates {
35
35
  reviewRead: boolean;
36
36
  membersManage: boolean;
37
37
  }
38
- type CatalogQueries = Pick<typeof import('../connectors/catalog/use-catalog.js'), 'catalogSectionsQuery' | 'connectStatusQuery'>;
38
+ type CatalogQueries = Pick<typeof import('../connectors/catalog/use-catalog.js'), 'catalogSectionsQuery'>;
39
39
  /** The reads the prefetch issues. Injected in tests; the SDK in production. */
40
40
  export interface CustomizePrefetchApi {
41
41
  getProject: typeof getProject;
42
- getConnectStatus: typeof getConnectStatus;
43
42
  getModelDefaults: typeof getModelDefaults;
44
43
  getProjectModelPicker: typeof getProjectModelPicker;
45
44
  listConnectors: typeof listConnectors;