@kortix/ui 0.14.8 → 0.14.10

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 (567) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +116 -3
  3. package/dist/_vendor/shared/app-config.d.ts +175 -0
  4. package/dist/_vendor/shared/artifact-comments.d.ts +235 -0
  5. package/dist/_vendor/shared/channel-descriptors.d.ts +96 -0
  6. package/dist/_vendor/shared/channel-message.d.ts +45 -5
  7. package/dist/_vendor/shared/index.d.ts +2 -0
  8. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  9. package/dist/access/access/access-detail-shell.js +1 -1
  10. package/dist/access/access/principal-picker.d.ts +11 -0
  11. package/dist/access/access/principal-picker.js +3 -2
  12. package/dist/apps/app-preview-pool.d.ts +7 -2
  13. package/dist/apps/app-preview-pool.js +30 -7
  14. package/dist/apps/app-shared.d.ts +22 -15
  15. package/dist/apps/app-shared.js +37 -19
  16. package/dist/apps/index.d.ts +2 -2
  17. package/dist/apps/index.js +2 -2
  18. package/dist/artifacts/artifact-frame.d.ts +16 -0
  19. package/dist/artifacts/artifact-frame.js +55 -0
  20. package/dist/artifacts/artifact-session.d.ts +18 -0
  21. package/dist/artifacts/artifact-session.js +101 -0
  22. package/dist/artifacts/frame-policy.d.ts +30 -0
  23. package/dist/artifacts/frame-policy.js +61 -0
  24. package/dist/artifacts/index.d.ts +3 -0
  25. package/dist/artifacts/index.js +5 -0
  26. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  27. package/dist/browser/sandbox-browser-chrome.js +2 -2
  28. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  29. package/dist/customize/agents/agent-grant-pages.js +30 -4
  30. package/dist/customize/agents/agent-page.js +3 -1
  31. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  32. package/dist/customize/agents/agent-policy-sets.js +72 -0
  33. package/dist/customize/agents/agent-triggers-section.js +2 -1
  34. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  35. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  36. package/dist/customize/connectors/agent-access.d.ts +35 -0
  37. package/dist/customize/connectors/agent-access.js +77 -0
  38. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  39. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  40. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  41. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  42. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  43. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  44. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  45. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  46. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  47. package/dist/customize/connectors/connector-identity.js +13 -42
  48. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  49. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  50. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  51. package/dist/customize/connectors/connector-routes.js +29 -20
  52. package/dist/customize/connectors/connectors-page.js +53 -82
  53. package/dist/customize/connectors/detail/app-page.js +226 -98
  54. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  55. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  56. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  57. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  58. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  59. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  60. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  61. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  62. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  63. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  64. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  65. package/dist/customize/connectors/detail/connector-page.js +14 -10
  66. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  67. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  68. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  69. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  70. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  71. package/dist/customize/connectors/detail/connector-status.js +34 -10
  72. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  73. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  74. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  75. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  76. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  77. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  78. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  79. package/dist/customize/connectors/detail/provider-info.js +2 -2
  80. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  81. package/dist/customize/connectors/detail/status-badge.js +4 -5
  82. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  83. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  84. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  85. package/dist/customize/connectors/install/install-dialog.js +40 -0
  86. package/dist/customize/connectors/install/install.d.ts +13 -2
  87. package/dist/customize/connectors/install/install.js +9 -4
  88. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  89. package/dist/customize/connectors/install/use-install.js +65 -37
  90. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  91. package/dist/customize/connectors/install/way-kind.js +16 -0
  92. package/dist/customize/connectors/provider-label.d.ts +2 -1
  93. package/dist/customize/connectors/provider-label.js +13 -3
  94. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  95. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  96. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  97. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  98. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  99. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  100. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  101. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  102. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  103. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  104. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  105. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  106. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  107. package/dist/customize/connectors/use-agent-access.js +72 -0
  108. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  109. package/dist/customize/migrate-to-v2/index.js +1 -2
  110. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -25
  111. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -236
  112. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  113. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  114. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  115. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  116. package/dist/customize/providers/provider-accordion.js +17 -2
  117. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  118. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  119. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  120. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  121. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  122. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  123. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  124. package/dist/customize/sections/component/channel-mocks.js +46 -0
  125. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  126. package/dist/customize/sections/component/channel-row.js +10 -4
  127. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  128. package/dist/customize/sections/component/email-connect-form.js +183 -0
  129. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  130. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  131. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  132. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  133. package/dist/customize/sections/component/telegram-channel-row.js +21 -28
  134. package/dist/customize/sections/connectors-view.d.ts +1 -15
  135. package/dist/customize/sections/connectors-view.js +81 -314
  136. package/dist/customize/sections/view/agent-editor-catalog.js +10 -0
  137. package/dist/customize/sections/view/channels-view.d.ts +6 -1
  138. package/dist/customize/sections/view/channels-view.js +72 -81
  139. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  140. package/dist/customize/settings/rail.js +9 -0
  141. package/dist/customize/settings/settings-tabs.d.ts +1 -1
  142. package/dist/customize/settings/settings-tabs.js +1 -0
  143. package/dist/customize/settings/tabs/chrome-connections-tab.d.ts +6 -0
  144. package/dist/customize/settings/tabs/chrome-connections-tab.js +99 -0
  145. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  146. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +4 -15
  147. package/dist/customize/shared/catalog/catalog-empty-state.js +9 -7
  148. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  149. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  150. package/dist/customize/shared/feature-gate-screen.js +27 -9
  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/triggers/schedule/post-to-field.d.ts +18 -0
  154. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  155. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  156. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  157. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  158. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  159. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  160. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  161. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  162. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  163. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  164. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  165. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  166. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  167. package/dist/customize/triggers/schedule-view.js +5 -2
  168. package/dist/files/index.d.ts +1 -0
  169. package/dist/files/index.js +1 -0
  170. package/dist/files/project/change-request-recovery.d.ts +1 -26
  171. package/dist/files/project/change-request-recovery.js +1 -59
  172. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  173. package/dist/files/project/components/drive-explorer.js +15 -15
  174. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  175. package/dist/files/project/components/drive-toolbar.js +14 -5
  176. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  177. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  178. package/dist/files/project/hooks/use-change-requests.js +11 -2
  179. package/dist/files/renderers/image-frame.d.ts +48 -0
  180. package/dist/files/renderers/image-frame.js +59 -0
  181. package/dist/files/renderers/image-renderer.d.ts +11 -1
  182. package/dist/files/renderers/image-renderer.js +13 -3
  183. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  184. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  185. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  186. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  187. package/dist/files/renderers/show-content-renderer.js +56 -14
  188. package/dist/files/runtime/file-source.js +2 -0
  189. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  190. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  191. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  192. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  193. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  194. package/dist/files/viewer/file-content-renderer.js +50 -7
  195. package/dist/files/viewer/file-header.d.ts +7 -3
  196. package/dist/files/viewer/file-header.js +20 -11
  197. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  198. package/dist/files/viewer/file-preview-modal.js +10 -22
  199. package/dist/files/viewer/file-source.d.ts +13 -0
  200. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  201. package/dist/files/viewer/use-file-content-state.js +28 -10
  202. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  203. package/dist/files/viewer/viewer-actions.js +2 -2
  204. package/dist/hooks/use-media-query.d.ts +1 -0
  205. package/dist/hooks/use-mobile.d.ts +5 -0
  206. package/dist/hooks/use-mobile.js +8 -0
  207. package/dist/i18n/en.d.ts +1062 -85
  208. package/dist/i18n/en.js +1078 -101
  209. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  210. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  211. package/dist/index.d.ts +2 -2
  212. package/dist/index.js +2 -2
  213. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  214. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  215. package/dist/internal/account-hub/hub-sheet.js +21 -5
  216. package/dist/internal/account-hub/sections.d.ts +1 -1
  217. package/dist/internal/account-hub/sections.js +2 -1
  218. package/dist/internal/apps-and-extensions/apps-modal.d.ts +9 -0
  219. package/dist/internal/apps-and-extensions/apps-modal.js +107 -0
  220. package/dist/internal/auth/auth-card-shell.js +3 -3
  221. package/dist/internal/chrome/browser-icon.d.ts +24 -0
  222. package/dist/internal/chrome/browser-icon.js +58 -0
  223. package/dist/internal/chrome/chrome-card-state.d.ts +16 -0
  224. package/dist/internal/chrome/chrome-card-state.js +9 -0
  225. package/dist/internal/chrome/chrome-connect.d.ts +69 -0
  226. package/dist/internal/chrome/chrome-connect.js +178 -0
  227. package/dist/internal/chrome/chrome-mock.d.ts +4 -0
  228. package/dist/internal/chrome/chrome-mock.js +15 -0
  229. package/dist/internal/chrome/chrome-names.d.ts +15 -0
  230. package/dist/internal/chrome/chrome-names.js +35 -0
  231. package/dist/internal/chrome/extension.d.ts +47 -0
  232. package/dist/internal/chrome/extension.js +91 -0
  233. package/dist/internal/chrome/use-chrome-offered.d.ts +11 -0
  234. package/dist/internal/chrome/use-chrome-offered.js +22 -0
  235. package/dist/internal/components/agent-mark.js +5 -2
  236. package/dist/internal/connector-logo/connector-logo-source.d.ts +64 -0
  237. package/dist/internal/connector-logo/connector-logo-source.js +49 -0
  238. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  239. package/dist/internal/connector-logo/connector-logo.js +56 -0
  240. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  241. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  242. package/dist/internal/files/file-read-retry.d.ts +13 -0
  243. package/dist/internal/files/file-read-retry.js +23 -3
  244. package/dist/internal/files/session-drive-files.d.ts +5 -1
  245. package/dist/internal/files/session-drive-files.js +7 -2
  246. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  247. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  248. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  249. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  250. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  251. package/dist/internal/hooks/index.d.ts +1 -1
  252. package/dist/internal/hooks/index.js +1 -1
  253. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  254. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  255. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  256. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  257. package/dist/internal/icons/edge.d.ts +5 -0
  258. package/dist/internal/icons/edge.js +10 -0
  259. package/dist/internal/icons/telegram.d.ts +5 -0
  260. package/dist/internal/icons/telegram.js +6 -1
  261. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  262. package/dist/internal/layout/nav-hover-card.js +84 -0
  263. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  264. package/dist/internal/layout/project-nav-row.js +3 -2
  265. package/dist/internal/layout/project-page-header.d.ts +4 -2
  266. package/dist/internal/layout/project-page-header.js +4 -3
  267. package/dist/internal/layout/project-settings-nav.js +59 -2
  268. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  269. package/dist/internal/lib/browser-error-noise.js +1 -1
  270. package/dist/internal/lib/browser-noise/rules/extensions.js +17 -3
  271. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  272. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  273. package/dist/internal/lib/detect-os.d.ts +43 -0
  274. package/dist/internal/lib/detect-os.js +70 -0
  275. package/dist/internal/lib/manifest-version.d.ts +1 -1
  276. package/dist/internal/lib/manifest-version.js +2 -2
  277. package/dist/internal/lib/memory-href.d.ts +16 -0
  278. package/dist/internal/lib/memory-href.js +46 -0
  279. package/dist/internal/lib/use-project-feature-flags.js +13 -9
  280. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  281. package/dist/internal/lib/utils/heic-convert.js +3 -4
  282. package/dist/internal/lib/web-notifications.d.ts +20 -0
  283. package/dist/internal/lib/web-notifications.js +48 -4
  284. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  285. package/dist/internal/notifications/notification-bell.js +2 -2
  286. package/dist/internal/selection/selection-bar.d.ts +2 -1
  287. package/dist/internal/selection/selection-bar.js +1 -1
  288. package/dist/internal/stores/apps-modal-store.d.ts +8 -0
  289. package/dist/internal/stores/apps-modal-store.js +6 -0
  290. package/dist/internal/stores/composer-prefill-store.d.ts +12 -5
  291. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  292. package/dist/internal/stores/file-preview-store.js +19 -1
  293. package/dist/internal/stores/kortix-computer-store.js +3 -0
  294. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  295. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  296. package/dist/lib/routes.d.ts +13 -1
  297. package/dist/lib/routes.js +13 -0
  298. package/dist/markdown/index.d.ts +2 -1
  299. package/dist/markdown/index.js +2 -1
  300. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  301. package/dist/markdown/setup-links/approval-decision.js +9 -3
  302. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  303. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  304. package/dist/markdown/setup-links/secret-intake-form.d.ts +0 -10
  305. package/dist/markdown/setup-links/secret-intake-form.js +1 -1
  306. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  307. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  308. package/dist/markdown/unified-markdown.js +5 -5
  309. package/dist/primitives/badge.d.ts +1 -1
  310. package/dist/primitives/badge.js +2 -0
  311. package/dist/primitives/disclosure.js +14 -2
  312. package/dist/primitives/empty-art.d.ts +12 -0
  313. package/dist/primitives/empty-art.js +11 -0
  314. package/dist/primitives/empty-state.d.ts +2 -2
  315. package/dist/primitives/empty-state.js +6 -5
  316. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  317. package/dist/primitives/mermaid-renderer.js +21 -15
  318. package/dist/primitives/resizable.js +6 -1
  319. package/dist/primitives/resize-seam.d.ts +11 -0
  320. package/dist/primitives/resize-seam.js +12 -0
  321. package/dist/primitives/sidebar-panel.js +4 -7
  322. package/dist/primitives/tabs.d.ts +14 -1
  323. package/dist/primitives/tabs.js +1 -1
  324. package/dist/providers/ui-provider.d.ts +9 -0
  325. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  326. package/dist/session/composer/ComposerAboveCard.js +2 -2
  327. package/dist/session/composer/ComposerCard.d.ts +1 -1
  328. package/dist/session/composer/ComposerCard.js +3 -3
  329. package/dist/session/composer/agent-selector.d.ts +13 -1
  330. package/dist/session/composer/agent-selector.js +25 -5
  331. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  332. package/dist/session/composer/composer-agent-access.js +27 -0
  333. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  334. package/dist/session/composer/composer-chat-input.js +8 -6
  335. package/dist/session/composer/composer-logic.d.ts +16 -0
  336. package/dist/session/composer/composer-logic.js +12 -0
  337. package/dist/session/composer/composer-underbar.d.ts +3 -1
  338. package/dist/session/composer/composer-underbar.js +4 -3
  339. package/dist/session/composer/composer.d.ts +15 -1
  340. package/dist/session/composer/composer.js +19 -1
  341. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  342. package/dist/session/composer/draft/composer-draft.js +5 -1
  343. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  344. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  345. package/dist/session/models/chatgpt-connection-button.js +54 -0
  346. package/dist/session/models/model-selector.js +5 -2
  347. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  348. package/dist/session/models/use-model-connection-gate.js +5 -5
  349. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  350. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  351. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  352. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  353. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  354. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  355. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  356. package/dist/session/panel/easy/app-preview.js +31 -12
  357. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  358. package/dist/session/panel/easy/change-requests-card.js +17 -0
  359. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  360. package/dist/session/panel/easy/easy-panel.js +5 -2
  361. package/dist/session/panel/easy/file-preview.js +1 -1
  362. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  363. package/dist/session/panel/easy/outputs-card.js +3 -2
  364. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  365. package/dist/session/panel/session-audit-panel.js +9 -2
  366. package/dist/session/panel/session-audit-shared.js +3 -1
  367. package/dist/session/panel/session-detail-panel.js +9 -3
  368. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  369. package/dist/session/panel/session-files-explorer.js +12 -3
  370. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  371. package/dist/session/panel/session-panel-provider.js +32 -7
  372. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  373. package/dist/session/panel/shared/derive-panels.js +12 -2
  374. package/dist/session/panel/shared/output-priority.js +2 -0
  375. package/dist/session/participants/session-participants.d.ts +8 -2
  376. package/dist/session/participants/session-participants.js +11 -4
  377. package/dist/session/prompts/approval-request.d.ts +5 -0
  378. package/dist/session/prompts/approval-request.js +9 -1
  379. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  380. package/dist/session/prompts/session-approval-review.js +18 -0
  381. package/dist/session/status/session-error-banner.js +2 -49
  382. package/dist/session/status/session-starting-loader.d.ts +14 -2
  383. package/dist/session/status/session-starting-loader.js +16 -4
  384. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  385. package/dist/session/thread/after-first-prompt.js +8 -0
  386. package/dist/session/thread/detect-command.d.ts +12 -0
  387. package/dist/session/thread/detect-command.js +20 -0
  388. package/dist/session/thread/session-chat.d.ts +3 -1
  389. package/dist/session/thread/session-chat.js +377 -252
  390. package/dist/session/thread/session-thread.d.ts +15 -1
  391. package/dist/session/thread/session-thread.js +20 -3
  392. package/dist/session/thread/session-transcript-class.d.ts +5 -1
  393. package/dist/session/thread/session-transcript-class.js +5 -1
  394. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  395. package/dist/session/thread/thread-boot-rows.js +89 -0
  396. package/dist/session/thread/transcript-rows.d.ts +31 -0
  397. package/dist/session/thread/transcript-rows.js +3 -0
  398. package/dist/session/thread/transcript.d.ts +0 -9
  399. package/dist/session/thread/transcript.js +104 -19
  400. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  401. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  402. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  403. package/dist/session/tool/tool-part-renderer.js +8 -3
  404. package/dist/session/tool/tools/bash-tool.js +7 -6
  405. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  406. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  407. package/dist/session/tool/tools/codemode-tool.js +1 -1
  408. package/dist/session/tool/tools/connector-tools.js +1 -1
  409. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  410. package/dist/session/tool/tools/image-gen-tool.js +241 -53
  411. package/dist/session/tool/tools/show-tool.js +19 -8
  412. package/dist/session/turn/channel-brand.d.ts +8 -3
  413. package/dist/session/turn/channel-brand.js +20 -4
  414. package/dist/session/turn/message-author.d.ts +8 -0
  415. package/dist/session/turn/message-author.js +24 -0
  416. package/dist/session/turn/message-row.d.ts +52 -0
  417. package/dist/session/turn/message-row.js +44 -0
  418. package/dist/session/turn/plan-anchor.d.ts +1 -1
  419. package/dist/session/turn/plan-anchor.js +1 -1
  420. package/dist/session/turn/user-message.d.ts +14 -6
  421. package/dist/session/turn/user-message.js +35 -15
  422. package/dist/styles.css +1 -1
  423. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  424. package/dist/workspace/home/access-requests-bell.js +20 -6
  425. package/dist/workspace/home/first-chat.d.ts +8 -21
  426. package/dist/workspace/home/first-chat.js +22 -72
  427. package/dist/workspace/index.d.ts +6 -0
  428. package/dist/workspace/index.js +6 -0
  429. package/dist/workspace/layout/project-home.d.ts +14 -2
  430. package/dist/workspace/layout/project-home.js +60 -21
  431. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  432. package/dist/workspace/layout/use-project-home-send.js +82 -3
  433. package/dist/workspace/memory/body-doc.d.ts +17 -0
  434. package/dist/workspace/memory/body-doc.js +208 -0
  435. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  436. package/dist/workspace/memory/body-extensions.js +103 -0
  437. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  438. package/dist/workspace/memory/company-memory-page.js +16 -0
  439. package/dist/workspace/memory/memory-all.d.ts +20 -0
  440. package/dist/workspace/memory/memory-all.js +27 -0
  441. package/dist/workspace/memory/memory-body.d.ts +19 -0
  442. package/dist/workspace/memory/memory-body.js +139 -0
  443. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  444. package/dist/workspace/memory/memory-empty.js +28 -0
  445. package/dist/workspace/memory/memory-history.d.ts +27 -0
  446. package/dist/workspace/memory/memory-history.js +108 -0
  447. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  448. package/dist/workspace/memory/memory-labels.js +47 -0
  449. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  450. package/dist/workspace/memory/memory-page-list.js +156 -0
  451. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  452. package/dist/workspace/memory/memory-reader.js +123 -0
  453. package/dist/workspace/memory/memory-view.d.ts +21 -0
  454. package/dist/workspace/memory/memory-view.js +124 -0
  455. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  456. package/dist/workspace/memory/remember-popover.js +61 -0
  457. package/dist/workspace/memory/remember-this.d.ts +12 -0
  458. package/dist/workspace/memory/remember-this.js +89 -0
  459. package/dist/workspace/memory/source-mark.d.ts +18 -0
  460. package/dist/workspace/memory/source-mark.js +79 -0
  461. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  462. package/dist/workspace/memory/used-memory-chip.js +61 -0
  463. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  464. package/dist/workspace/new/advanced-fields.js +2 -2
  465. package/dist/workspace/new/source-param.d.ts +1 -1
  466. package/dist/workspace/new/source-param.js +3 -1
  467. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  468. package/dist/workspace/new/use-create-workspace.js +3 -3
  469. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  470. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  471. package/dist/workspace/projects/policies-panel.js +5 -3
  472. package/dist/workspace/review/review-actions.d.ts +4 -2
  473. package/dist/workspace/review/review-actions.js +8 -2
  474. package/dist/workspace/review/review-center.js +11 -7
  475. package/dist/workspace/review/review-detail.d.ts +10 -0
  476. package/dist/workspace/review/review-detail.js +101 -13
  477. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  478. package/dist/workspace/saved-session-skeleton.js +3 -3
  479. package/dist/workspace/session-workspace.js +15 -13
  480. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  481. package/dist/workspace/sessions/session-label-badges.js +2 -1
  482. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  483. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  484. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  485. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  486. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  487. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  488. package/dist/workspace/sidebar/footer/project-chrome-nav.d.ts +10 -0
  489. package/dist/workspace/sidebar/footer/project-chrome-nav.js +56 -0
  490. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  491. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  492. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  493. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  494. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  495. package/dist/workspace/sidebar/project-session-list.js +68 -56
  496. package/dist/workspace/sidebar/project-sidebar.js +13 -2
  497. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  498. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  499. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  500. package/dist/workspace/sidebar/session-group-order.js +25 -0
  501. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  502. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  503. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  504. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  505. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  506. package/dist/workspace/spaces/channel-glyph.js +6 -0
  507. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  508. package/dist/workspace/spaces/channel-setup.js +105 -0
  509. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  510. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  511. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  512. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  513. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  514. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  515. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  516. package/dist/workspace/spaces/space-agents.js +10 -0
  517. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  518. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  519. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  520. package/dist/workspace/spaces/space-link-label.js +73 -0
  521. package/dist/workspace/spaces/space-links.d.ts +19 -0
  522. package/dist/workspace/spaces/space-links.js +230 -0
  523. package/dist/workspace/spaces/space-members.d.ts +46 -0
  524. package/dist/workspace/spaces/space-members.js +182 -0
  525. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  526. package/dist/workspace/spaces/space-roster.js +44 -0
  527. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  528. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  529. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  530. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  531. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  532. package/dist/workspace/spaces/space-timeline.js +183 -0
  533. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  534. package/dist/workspace/spaces/space-triggers.js +78 -0
  535. package/dist/workspace/spaces/space-view.d.ts +37 -0
  536. package/dist/workspace/spaces/space-view.js +436 -0
  537. package/package.json +67 -36
  538. package/skills/kortix-ui/SKILL.md +3 -3
  539. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  540. package/skills/kortix-ui/references/modules.md +29 -5
  541. package/skills/kortix-ui/references/theming.md +1 -1
  542. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  543. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  544. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  545. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  546. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  547. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  548. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  549. package/dist/customize/sections/connector-connection-header.js +0 -33
  550. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  551. package/dist/customize/sections/connector-connection-modal.js +0 -72
  552. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  553. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  554. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  555. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  556. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  557. package/dist/customize/sections/discover-catalogue.js +0 -132
  558. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  559. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  560. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  561. package/dist/files/project/components/drive-empty-art.js +0 -5
  562. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  563. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  564. package/dist/internal/share/public-share-link-button.js +0 -17
  565. package/dist/markdown/setup-links/app-credentials-form.d.ts +0 -12
  566. package/dist/markdown/setup-links/app-credentials-form.js +0 -115
  567. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -231,4 +231,14 @@ 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
+ },
239
+ {
240
+ group: 'Artifact comments',
241
+ actions: ['project.artifact.comment'],
242
+ featureFlag: 'artifact_comments',
243
+ },
234
244
  ];
@@ -1,3 +1,8 @@
1
- export declare function ChannelsSection({ projectId }: {
1
+ import { type ChannelPlatformId } from '../../../_vendor/shared/channel-descriptors.js';
2
+ /** Reserved slug for the built-in Email channel (see api connectors.ts). */
3
+ /** A Kortix channel's own page (`platform`), or every channel (the Channels page). */
4
+ export type ChannelPlatform = ChannelPlatformId;
5
+ export declare function ChannelsSection({ projectId, platform }: {
2
6
  projectId: string;
7
+ platform?: ChannelPlatform;
3
8
  }): import("react").JSX.Element;
@@ -75,64 +75,43 @@ 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
+ import { CHANNEL_PLATFORM_IDS, CHANNELS, isChannelPlatform, } from '../../../_vendor/kortix-shared.js';
112
+ export function ChannelsSection({ projectId, platform }) {
120
113
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
121
114
  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
115
  const { data: install, isLoading: loadingInstall } = useSlackInstall(projectId);
137
116
  const { data: mode, isLoading: loadingMode } = useSlackMode(projectId);
138
117
  // Teams is on for every project (its feature flag graduated on 2026-10-01).
@@ -140,11 +119,12 @@ export function ChannelsSection({ projectId }) {
140
119
  const { data: teamsMode } = useTeamsMode(projectId);
141
120
  // Not connected, Teams gets the same hero as Slack; connected, it is a row.
142
121
  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);
122
+ // Email (Resend Inboxes) is experimental behind `email_channel`. Off, it is on
123
+ // no surface, and its inboxes are never read (EmailHero is not mounted).
124
+ const emailFlag = useFeatureFlag(projectId, 'email_channel');
125
+ const emailEnabled = emailFlag.enabled;
126
+ const loading = loadingInstall || loadingMode || emailFlag.isLoading;
127
+ const tPages = useTranslations('connectorPages');
148
128
  const oauthInstallUrl = mode?.oauth_available ? mode.install_url : null;
149
129
  const canWrite = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_CONNECTOR_WRITE).allowed === true;
150
130
  // Each platform's row shows how many conversations it has bound and opens
@@ -154,29 +134,55 @@ export function ChannelsSection({ projectId }) {
154
134
  const channelCounts = new Map(bindingTabs(bindingsQuery.data?.bindings ?? []).map((tab) => [tab.platform, tab.count]));
155
135
  const [channelsDialog, setChannelsDialog] = useState({ open: false, platform: 'slack', session: 0 });
156
136
  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;
137
+ // Every channel draws as a hero, connected or not: its own page shows one
138
+ // platform, the Channels tab every platform, one under the other.
139
+ const platforms = platform
140
+ ? [platform]
141
+ : CHANNEL_PLATFORM_IDS.filter((pf) => pf !== 'email' || emailEnabled);
142
+ // The Kortix tab also holds the computer, where this deployment can pair one
143
+ // (the machine list answers 503 where computers are off).
144
+ const computersEnabled = useTunnelConnections({ refetchInterval: false }).isSuccess;
145
+ const showComputer = !platform && computersEnabled;
146
+ const hero = (pf) => {
147
+ switch (pf) {
148
+ case 'slack':
149
+ 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 }));
150
+ case 'teams':
151
+ 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] }));
152
+ case 'email':
153
+ // Each inbox is an account on `kortix_email`: the hero counts them, Manage lists them.
154
+ return _jsx(EmailHero, { projectId: projectId, canWrite: canWrite });
155
+ case 'telegram':
156
+ return _jsx(TelegramChannelRow, { projectId: projectId, canWrite: canWrite });
157
+ default: {
158
+ // A new channel id fails here until it has a hero.
159
+ const _exhaustive = pf;
160
+ return _exhaustive;
161
+ }
162
+ }
163
+ };
164
+ // The Email page with the flag off: the standard flag-off screen, with its enable action.
165
+ if (platform === 'email' && !emailFlag.isLoading && !emailEnabled) {
166
+ return (_jsx(FeatureGateScreen, { featureKey: "email_channel", featureName: tPages('emailGateName'), description: tPages('emailGateDescription') }));
167
+ }
164
168
  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)] })) }));
169
+ /* Full width of the Connectors shell: the heroes are split cards whose
170
+ chat preview needs the room. No heading and no scroll container here;
171
+ both belong to the `CapabilityPageShell` in `connectors-page.tsx`. */
172
+ _jsx(ChannelHeroLayoutProvider, { children: _jsxs("div", { className: "w-full space-y-6", children: [loading
173
+ ? platforms.map((pf) => _jsx(Skeleton, { className: "h-72 w-full rounded-lg" }, pf))
174
+ : 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
175
  }
175
176
  /** Slack as a peer row, once it is connected. */
176
177
  function SlackChannelRow({ projectId, installation, canWrite, channelCount, onOpenChannels, }) {
177
178
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
179
+ const tPages = useTranslations('connectorPages');
178
180
  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, {
181
+ return (_jsx(ChannelRow, { app: "slack", name: "Slack", connected: true, detail: installation.workspaceName ?? installation.workspaceId, pitch: tI18nComplete.raw('text9bd1c37ed121'), hero: {
182
+ title: tI18nComplete.raw('text89e9e20668f3'),
183
+ connectedTitle: tPages('channelConnectedTitle', { name: 'Slack' }),
184
+ preview: _jsx(SlackChannelMock, {}),
185
+ }, 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
186
  onSuccess: () => {
181
187
  done();
182
188
  successToast(tI18nComplete.raw('textd948c285986a'));
@@ -190,14 +196,15 @@ function ChannelsButton({ count, onOpen }) {
190
196
  }
191
197
  /**
192
198
  * What follows a connected Slack before its first channel: the one-time "now
193
- * do this in Slack" nudge. It retires itself as soon as `bindings.length > 0`:
194
- * a bound channel is proof the user already invited the bot and mentioned it,
199
+ * do this in Slack" nudge. It retires itself as soon as a Slack channel is
200
+ * bound: that is proof the user already invited the bot and mentioned it,
195
201
  * and from then on the Slack row's "N channels" opens the bindings dialog.
202
+ * Another platform's row (a Telegram chat's `/model`) proves nothing about Slack.
196
203
  */
197
204
  function SlackFollowUp({ projectId }) {
198
205
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
199
206
  const bindingsQuery = useChannelBindings(projectId);
200
- const bindings = bindingsQuery.data?.bindings ?? [];
207
+ const bindings = (bindingsQuery.data?.bindings ?? []).filter((b) => b.platform === 'slack');
201
208
  return bindings.length === 0 && !bindingsQuery.isLoading ? (_jsxs(InfoBanner, { tone: "neutral", icon: AtIcon, title: tI18nComplete.raw('textd63af8edd3d6'), children: [tI18nComplete.raw('text1fd9ae1607aa'), ' ', _jsx("span", { className: "text-foreground font-medium", children: tI18nComplete.raw('text476b90bdc143') }), ' ', tI18nComplete.raw('textb81b729b4538')] })) : null;
202
209
  }
203
210
  /**
@@ -249,7 +256,7 @@ function ChannelBindingsDialog({ projectId, canWrite, platform, open, onOpenChan
249
256
  return (_jsx(Modal, { open: open, onOpenChange: onOpenChange, children: selected ? (_jsx(ChannelSettingsModalContent, { projectId: projectId, binding: selected.binding, name: selected.name, scope: selected.scope, projectDefaultAgent: projectDefaultAgent, canWrite: canWrite, onBack: back })) : (_jsxs(ModalContent, { className: "lg:max-w-lg", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: tI18nComplete.raw('text5f61b63c2c4a') }), _jsx(ModalDescription, { children: tI18nComplete.raw('text1f2550ed44dc') })] }), _jsxs(ModalBody, { className: "space-y-3 pt-4", children: [tabs.length > 1 ? (_jsx(Tabs, { value: active, onValueChange: (value) => {
250
257
  setTab(value);
251
258
  setQuery('');
252
- }, children: _jsx(TabsListCompact, { children: tabs.map((t) => (_jsxs(TabsTriggerCompact, { value: t.platform, className: "gap-1.5", children: [PLATFORM_NAMES[t.platform] ?? t.platform, _jsx("span", { className: "text-muted-foreground tabular-nums", children: t.count })] }, t.platform))) }) })) : null, inTab.length >= BINDING_SEARCH_MIN ? (_jsxs(InputGroupSearch, { children: [_jsx(InputGroupSearchIcon, { children: _jsx(MagnifyingGlassIcon, {}) }), _jsx(InputGroupSearchInput, { placeholder: tI18nComplete.raw('text49c266baaaa7'), value: query, onChange: (e) => setQuery(e.target.value), size: "sm" }), _jsx(InputGroupSearchClear, { onClick: () => setQuery('') })] })) : null, bindingsQuery.isLoading ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-12 rounded-md" }), _jsx(Skeleton, { className: "h-12 rounded-md" })] })) : visible.length === 0 ? (_jsx("p", { className: "text-muted-foreground px-3 py-6 text-center text-xs", children: tI18nComplete.raw('texte8dd87902b91') })) : (
259
+ }, children: _jsx(TabsListCompact, { children: tabs.map((t) => (_jsxs(TabsTriggerCompact, { value: t.platform, className: "gap-1.5", children: [isChannelPlatform(t.platform) ? CHANNELS[t.platform].label : t.platform, _jsx("span", { className: "text-muted-foreground tabular-nums", children: t.count })] }, t.platform))) }) })) : null, inTab.length >= BINDING_SEARCH_MIN ? (_jsxs(InputGroupSearch, { children: [_jsx(InputGroupSearchIcon, { children: _jsx(MagnifyingGlassIcon, {}) }), _jsx(InputGroupSearchInput, { placeholder: tI18nComplete.raw('text49c266baaaa7'), value: query, onChange: (e) => setQuery(e.target.value), size: "sm" }), _jsx(InputGroupSearchClear, { onClick: () => setQuery('') })] })) : null, bindingsQuery.isLoading ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-12 rounded-md" }), _jsx(Skeleton, { className: "h-12 rounded-md" })] })) : visible.length === 0 ? (_jsx("p", { className: "text-muted-foreground px-3 py-6 text-center text-xs", children: tI18nComplete.raw('texte8dd87902b91') })) : (
253
260
  // The list scrolls; the tabs and search above it stay put. Capped at
254
261
  // the viewport less ~21rem of header, tabs, search and footer, so
255
262
  // the footer stays on screen at the 720 × 480 desktop minimum,
@@ -262,8 +269,6 @@ function ChannelBindingsDialog({ projectId, canWrite, platform, open, onOpenChan
262
269
  _jsx(BindingOverrides, { binding: binding, policies: conversationPolicies }, "overrides"),
263
270
  ], onClick: () => setSelectedId(binding.bindingId) }, binding.bindingId))) }))] }), _jsx(ModalFooter, { className: "pt-2 pb-5", children: _jsx(Button, { type: "button", variant: "outline-ghost", onClick: () => onOpenChange(false), children: tI18nComplete.raw('text11a6767d5674') }) })] })) }));
264
271
  }
265
- /** Brand names, as the platform rows spell them. */
266
- const PLATFORM_NAMES = { slack: 'Slack', teams: 'Microsoft Teams' };
267
272
  /** A row's settings at a glance: only what overrides the project, else "Project default". */
268
273
  function BindingOverrides({ binding, policies, }) {
269
274
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
@@ -556,6 +561,7 @@ function TeamsAppUpdateNotice({ install, tI18nComplete, }) {
556
561
  }
557
562
  function TeamsChannelRow({ projectId, canWrite, channelCount, onOpenChannels, }) {
558
563
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
564
+ const tPages = useTranslations('connectorPages');
559
565
  const { data: install } = useTeamsInstall(projectId);
560
566
  const { data: mode } = useTeamsMode(projectId);
561
567
  const disconnect = useDisconnectTeams();
@@ -579,29 +585,14 @@ function TeamsChannelRow({ projectId, canWrite, channelCount, onOpenChannels, })
579
585
  const detail = install?.publishState === 'failed' && install.publishError
580
586
  ? `${install.teamName ?? install.tenantId} · ${install.publishError}`
581
587
  : (install?.teamName ?? install?.tenantId ?? null);
582
- 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, {
588
+ return (_jsx(ChannelRow, { app: "teams", name: "Microsoft Teams", connected: connected, detail: detail, pitch: tI18nComplete.raw('text9225e456b795'), hero: {
589
+ title: tI18nComplete.raw('textc1bd5ca19f5f'),
590
+ connectedTitle: tPages('channelConnectedTitle', { name: 'Microsoft Teams' }),
591
+ preview: _jsx(TeamsChannelMock, {}),
592
+ }, 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
593
  onSuccess: () => {
584
594
  done();
585
595
  successToast(tI18nComplete.raw('textf2e69a5e24ba'));
586
596
  },
587
- }) })] })) : installUrl ? (_jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: _jsx(Link, { href: installUrl, target: "_blank", rel: "noopener noreferrer", children: tI18nComplete.raw('text1a2303ede074') }) })) : null] }) }));
588
- }
589
- function EmailChannelRow({ projectId, enabled, installation, canWrite, }) {
590
- const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
591
- const disconnect = useDisconnectEmail();
592
- const [connectOpen, setConnectOpen] = useState(false);
593
- const connected = Boolean(installation);
594
- 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
595
- ? tI18nComplete.raw('text27ba4ec98716')
596
- : // `FeatureGateScreen`'s exact words for a flag that is off, with
597
- // the name the Feature flags section lists the flag under.
598
- `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 }, {
599
- onSuccess: () => {
600
- done();
601
- successToast(tI18nComplete.raw('text958c8e06d3e7'));
602
- },
603
- }) })) : (_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: () => {
604
- setConnectOpen(false);
605
- successToast(tI18nComplete.raw('text62c381e56f37'));
606
- } }) })] }) })] }));
597
+ }) })] })) : 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] }) }));
607
598
  }
@@ -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,
@@ -1,5 +1,6 @@
1
1
  import { ArrowCircleUpIcon as ArrowUpCircle, ChatCircleIcon as ChatCircle, CoinsIcon as Coins, ShippingContainerIcon as Container, CreditCardIcon as CreditCard, FlaskIcon as Flask, KeyIcon as Key, LaptopIcon as Laptop, LinkIcon as Link, PaletteIcon as Palette, ShieldCheckIcon as ShieldCheck, SlidersHorizontalIcon as SlidersHorizontal, SquaresFourIcon as SquaresFour, UserIcon as User, } from '@phosphor-icons/react';
2
2
  import { Mcp } from '../../internal/icons/mcp.js';
3
+ import { ChromeRailIcon } from '../../internal/chrome/browser-icon.js';
3
4
  /**
4
5
  * Whether a rail item is the active one for the current settings tab.
5
6
  *
@@ -64,6 +65,14 @@ const STATIC_GROUPS = [
64
65
  description: 'Language and keyboard shortcuts.',
65
66
  icon: SlidersHorizontal,
66
67
  },
68
+ {
69
+ tab: 'chrome',
70
+ label: 'Kortix in Chrome',
71
+ description: 'Your sessions use Chrome with your logins. You see every step.',
72
+ docsHref: '/docs/connect/chrome',
73
+ // Monochrome like its neighbours; `ChromeRailIcon` takes only `className`.
74
+ icon: ChromeRailIcon,
75
+ },
67
76
  // Labelled "API keys", routed at `/settings/tokens`. The id has to be
68
77
  // `tokens` — it is the URL segment, and the account page already spends
69
78
  // `api-keys` on a legacy redirect (`RENAMED` in `settings-tabs.ts`) —
@@ -1,4 +1,4 @@
1
- export type SettingsTab = 'profile' | 'security' | 'appearance' | 'sessions' | 'preferences' | 'connected' | 'tokens' | 'plan' | 'credits' | 'workspace' | 'sandbox' | 'feature-flags' | 'upgrades' | 'mcp' | 'computer';
1
+ export type SettingsTab = 'profile' | 'security' | 'appearance' | 'sessions' | 'preferences' | 'connected' | 'chrome' | 'tokens' | 'plan' | 'credits' | 'workspace' | 'sandbox' | 'feature-flags' | 'upgrades' | 'mcp' | 'computer';
2
2
  /**
3
3
  * The default must be a tab that survives every gate, or the overlay opens on
4
4
  * nothing. It was `general` until project configuration moved to
@@ -54,6 +54,7 @@ export const SETTINGS_TABS = [
54
54
  'appearance',
55
55
  'sessions',
56
56
  'preferences',
57
+ 'chrome',
57
58
  'tokens',
58
59
  'mcp',
59
60
  'computer',
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Settings → Kortix in Chrome: the browsers this person connected with the
3
+ * Kortix extension. With none, the three connect steps stand inline and the
4
+ * connect action sits in the page header.
5
+ */
6
+ export declare function ChromeConnectionsTab(): import("react").JSX.Element;
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useChromeConnections, useDeleteChromeConnection, useUpdateChromeConnection } from '@kortix/sdk/react';
4
+ import { PencilSimpleIcon } from '@phosphor-icons/react';
5
+ import { useState } from 'react';
6
+ import { Button } from '../../../primitives/button.js';
7
+ import { ConfirmDialog } from '../../../primitives/confirm-dialog.js';
8
+ import { InlineMeta } from '../../../primitives/inline-meta.js';
9
+ import { Input } from '../../../primitives/input.js';
10
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../../primitives/select.js';
11
+ import { SettingsRow, SettingsRowGroup } from '../../../primitives/settings-row.js';
12
+ import { SettingsSubsectionHeader } from '../../../primitives/settings-subsection-header.js';
13
+ import { Skeleton } from '../../../primitives/skeleton.js';
14
+ import { errorToast, successToast } from '../../../primitives/toast.js';
15
+ import { ErrorState } from '../../../primitives/error-state.js';
16
+ import { SettingsTabHeader } from '../settings-tab-header.js';
17
+ import { useLocale, useTranslations } from '../../../i18n/index.js';
18
+ import { relativeTime } from '../../../internal/lib/relative-time.js';
19
+ import { ChromeButtonMark, ChromeConnectModal, ChromeConnectSteps, ChromeCopyLink, ChromeInstallActions, ChromeOnlineDot, useChromeConnect, } from '../../../internal/chrome/chrome-connect.js';
20
+ import { BrowserLogoTile } from '../../../internal/chrome/browser-icon.js';
21
+ import { chromeDisplayNames, offlineLongerThan } from '../../../internal/chrome/chrome-names.js';
22
+ import { ChromeMock } from '../../../internal/chrome/chrome-mock.js';
23
+ const ACCESS_MODES = ['always', 'ask', 'off'];
24
+ // `all` first: it is the recommended default.
25
+ const TAB_SCOPES = ['all', 'own'];
26
+ /** Offline longer than this shows when the browser was last seen. Shorter is just "Offline". */
27
+ const LAST_SEEN_AFTER_MS = 10 * 60_000;
28
+ /**
29
+ * Settings → Kortix in Chrome: the browsers this person connected with the
30
+ * Kortix extension. With none, the three connect steps stand inline and the
31
+ * connect action sits in the page header.
32
+ */
33
+ export function ChromeConnectionsTab() {
34
+ const t = useTranslations('chrome');
35
+ const connections = useChromeConnections();
36
+ const [connectOpen, setConnectOpen] = useState(false);
37
+ const list = connections.data ?? [];
38
+ if (connections.isSuccess && list.length === 0)
39
+ return _jsx(ChromeEmptyTab, {});
40
+ const names = chromeDisplayNames(list);
41
+ return (
42
+ // `max-w-2xl`: the form tier every person-scoped pane in this dialog uses.
43
+ _jsxs("div", { className: "mx-auto w-full max-w-2xl space-y-5", children: [_jsx(SettingsTabHeader, { tab: "chrome", action: list.length > 0 ? (_jsxs(Button, { size: "sm", variant: "secondary", className: "gap-1.5", onClick: () => setConnectOpen(true), children: [_jsx(ChromeButtonMark, {}), t('connectAnother')] })) : undefined }), connections.isPending ? (_jsx("div", { className: "space-y-2", children: _jsx(Skeleton, { className: "h-24 rounded-md" }) })) : connections.isError ? (_jsx(ErrorState, { size: "sm", title: t('loadFailed'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => connections.refetch(), children: t('retry') }) })) : (_jsxs(_Fragment, { children: [_jsxs("section", { className: "space-y-3", children: [_jsx(SettingsSubsectionHeader, { title: t('listTitle') }), _jsx("ul", { className: "space-y-3", children: list.map((chrome) => (_jsx(ChromeRow, { chrome: chrome, displayName: names.get(chrome.id) ?? chrome.name }, chrome.id))) })] }), _jsxs("section", { className: "space-y-2", children: [_jsx(SettingsSubsectionHeader, { title: t('how.title') }), _jsxs("ul", { className: "text-muted-foreground list-disc space-y-1 pl-5 text-sm text-pretty", children: [_jsx("li", { children: t('how.group') }), _jsx("li", { children: t('how.control') }), _jsx("li", { children: t('how.own') })] })] })] })), _jsx(ChromeConnectModal, { open: connectOpen, onOpenChange: setConnectOpen, fresh: true })] }));
44
+ }
45
+ /** No browser yet: the steps stand inline, the one action is in the header. */
46
+ function ChromeEmptyTab() {
47
+ const state = useChromeConnect();
48
+ return (_jsxs("div", { className: "mx-auto w-full max-w-2xl space-y-5", children: [_jsx(SettingsTabHeader, { tab: "chrome", action: state.environment === 'unsupported' ? (_jsx(ChromeCopyLink, {})) : (_jsx(ChromeInstallActions, { state: state, showGuide: false })) }), _jsxs("div", { className: "space-y-4", children: [_jsx(ChromeMock, { className: "mx-auto max-w-md" }), _jsx("div", { className: "bg-popover flex flex-col gap-5 rounded-md border px-4 py-5", children: _jsx(ChromeConnectSteps, { state: state, showActions: false }) })] })] }));
49
+ }
50
+ /** "Chromium on macOS · Work · v1.0.0": what tells two browsers apart. The name is not repeated. */
51
+ function chromeMeta(chrome, displayName) {
52
+ // The profile label already sits in the display name of a duplicate: say it once.
53
+ const profile = chrome.profileLabel && !displayName.includes(chrome.profileLabel) ? chrome.profileLabel : null;
54
+ return [profile, chrome.extensionVersion ? `v${chrome.extensionVersion}` : null].filter((part) => Boolean(part));
55
+ }
56
+ function ChromeRow({ chrome, displayName }) {
57
+ const t = useTranslations('chrome');
58
+ const locale = useLocale();
59
+ const update = useUpdateChromeConnection();
60
+ const remove = useDeleteChromeConnection();
61
+ const [confirmOpen, setConfirmOpen] = useState(false);
62
+ const [draft, setDraft] = useState(null);
63
+ const save = (change) => update.mutate({ id: chrome.id, ...change }, { onError: () => errorToast(t('updateFailed')) });
64
+ const commitName = () => {
65
+ const name = draft?.trim();
66
+ // An empty name is not a name: keep the field open and flag it. Blur reverts.
67
+ if (!name)
68
+ return false;
69
+ setDraft(null);
70
+ if (name !== chrome.name)
71
+ save({ name });
72
+ return true;
73
+ };
74
+ const sessions = chrome.activeSessions.length;
75
+ // "Last seen just now" beside "Offline" contradicts itself: say it only once it is a while ago.
76
+ const longOffline = !chrome.online && offlineLongerThan(chrome.lastSeenAt, LAST_SEEN_AFTER_MS);
77
+ const status = chrome.online
78
+ ? t('online')
79
+ : longOffline
80
+ ? t('lastSeen', { time: relativeTime(chrome.lastSeenAt, locale) })
81
+ : t('offline');
82
+ const meta = [...chromeMeta(chrome, displayName), status];
83
+ return (_jsxs("li", { children: [_jsxs(SettingsRowGroup, { children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-3", children: [_jsx(BrowserLogoTile, { brand: chrome.brand }), _jsxs("div", { className: "min-w-0 flex-1 space-y-0.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ChromeOnlineDot, { online: chrome.online }), draft === null ? (_jsxs("button", { type: "button", "aria-label": t('rename', { name: displayName }), title: displayName, className: "focus-visible:ring-ring/50 -mx-1 flex min-w-0 items-center gap-1.5 rounded-sm px-1 text-left outline-none focus-visible:ring-3", onClick: () => setDraft(chrome.name), children: [_jsx("span", { className: "truncate text-sm font-medium", children: displayName }), _jsx(PencilSimpleIcon, { className: "text-muted-foreground size-3.5 shrink-0" })] })) : (_jsx(Input, { autoFocus: true, value: draft, maxLength: 255, "aria-label": t('renameLabel'), className: "h-6 py-0", "aria-invalid": draft.trim() === '' ? true : undefined, onChange: (event) => setDraft(event.target.value), onBlur: () => {
84
+ if (!commitName())
85
+ setDraft(null);
86
+ }, onKeyDown: (event) => {
87
+ if (event.key === 'Enter')
88
+ commitName();
89
+ // Closes the field only. The settings dialog ignores Escape from a text field.
90
+ if (event.key === 'Escape')
91
+ setDraft(null);
92
+ } }))] }), _jsxs(InlineMeta, { children: [meta, sessions > 0 ? t('usedBy', { count: sessions }) : ''] })] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setConfirmOpen(true), children: t('disconnect') })] }), _jsx(SettingsRow, { label: t('access.label'), description: t('access.description'), children: _jsxs(Select, { value: chrome.accessMode, disabled: update.isPending, onValueChange: (value) => save({ accessMode: value }), children: [_jsx(SelectTrigger, { size: "sm", className: "w-44", "aria-label": t('access.label'), children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: ACCESS_MODES.map((mode) => (_jsx(SelectItem, { value: mode, children: t(`access.${mode}`) }, mode))) })] }) }), _jsx(SettingsRow, { label: t('scope.label'), description: t('scope.description'), children: _jsxs(Select, { value: chrome.tabScope, disabled: update.isPending, onValueChange: (value) => save({ tabScope: value }), children: [_jsx(SelectTrigger, { size: "sm", className: "w-44", "aria-label": t('scope.label'), children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: TAB_SCOPES.map((scope) => (_jsx(SelectItem, { value: scope, children: t(`scope.${scope}`) }, scope))) })] }) })] }), _jsx(ConfirmDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, title: t('disconnectTitle', { name: displayName }), description: _jsxs(_Fragment, { children: [_jsx("span", { className: "text-muted-foreground mb-2 block text-xs", children: meta.join(' · ') }), t('disconnectDescription')] }), confirmLabel: t('disconnect'), confirmVariant: "destructive", isPending: remove.isPending, onConfirm: () => remove.mutate(chrome.id, {
93
+ onSuccess: () => {
94
+ setConfirmOpen(false);
95
+ successToast(t('disconnected'));
96
+ },
97
+ onError: () => errorToast(t('disconnectFailed')),
98
+ }) })] }));
99
+ }
@@ -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
  }
@@ -1,8 +1,8 @@
1
1
  import type { ReactNode } from 'react';
2
2
  /**
3
- * The "nothing here" line every catalog uses, so five hand-typed copies of one
4
- * class string cannot drift into five different-looking messages. `CatalogGrid`
5
- * owns loading/error/empty; this is what callers put IN the empty slot when the
3
+ * The "nothing here" state every catalog uses: the shared `EmptyState`, so a
4
+ * catalog's empty slot looks like every other empty view. `CatalogGrid` owns
5
+ * loading/error/empty; this is what callers put IN the empty slot when the
6
6
  * cause is the search box rather than an empty project.
7
7
  */
8
8
  export declare function CatalogEmptyNote({ children }: {
@@ -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;