@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
@@ -0,0 +1,184 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * Email inboxes as ACCOUNTS on the `kortix_email` connector profile. One
5
+ * profile, many inboxes: each Resend inbox is an account with a name, an owner
6
+ * (you only, or shared) and a default, like every other connector's accounts.
7
+ * What only email adds lives here: the "Add inbox" dialog (the standard
8
+ * account fields, then where the inbox lives and its address), who may email
9
+ * an inbox, and the Email hero that counts the inboxes.
10
+ */
11
+ import { CaretRightIcon } from '@phosphor-icons/react';
12
+ import { getProjectDetail } from '@kortix/sdk';
13
+ import { contract, qk, useProjectAccountId } from '@kortix/sdk/react';
14
+ import { useQuery } from '@tanstack/react-query';
15
+ import { useState } from 'react';
16
+ import { grantConnectionAccess } from '../../../access/access/access-dialog-share.js';
17
+ import { useTranslations } from '../../../i18n/index.js';
18
+ import { useEmailInboxes, useUpdateEmailInbox, } from '../../../internal/hooks/channels/use-email-inboxes.js';
19
+ import { PROJECT_ACTIONS } from '../../../internal/lib/project-actions.js';
20
+ import { useProjectCan } from '../../../internal/lib/use-project-can.js';
21
+ import { Button } from '../../../primitives/button.js';
22
+ import { Checkbox } from '../../../primitives/checkbox.js';
23
+ import { Field } from '../../../primitives/field.js';
24
+ import { InfoBanner } from '../../../primitives/info-banner.js';
25
+ import { Input } from '../../../primitives/input.js';
26
+ import { Label } from '../../../primitives/label.js';
27
+ import Loading from '../../../primitives/loading.js';
28
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, } from '../../../primitives/modal.js';
29
+ import { errorToast, successToast } from '../../../primitives/toast.js';
30
+ import { UiLink as Link } from '../../../providers/ui-provider.js';
31
+ import { AddAccountFields } from '../../sections/add-account-fields.js';
32
+ import { ChannelHeroFrame, ChannelHeroStatus } from '../../sections/component/channel-hero-frame.js';
33
+ import { EmailThreadMock } from '../../sections/component/channel-mocks.js';
34
+ import { EmailConnectForm } from '../../sections/component/email-connect-form.js';
35
+ import { newAccountGrantees, newAccountLabelTaken, } from '../../sections/view/connector-connections.js';
36
+ import { proposeAccountLabel } from '../install/install.js';
37
+ import { connectorHref } from '../connector-routes.js';
38
+ /** The one connector profile every inbox is an account on. */
39
+ export const EMAIL_CONNECTOR_SLUG = 'kortix_email';
40
+ /** "Kortix managed" or "Your Resend account": where an inbox lives. */
41
+ export function EmailInboxHome({ inbox }) {
42
+ const t = useTranslations('emailInboxes');
43
+ return _jsx("span", { children: inbox.managed ? t('homeManaged') : t('homeOwn') });
44
+ }
45
+ /** The sender policy in the editor's shape, whatever casing the wire used. */
46
+ export function inboxSenderPolicy(inbox) {
47
+ const raw = (inbox?.sender_policy ?? {});
48
+ const list = (camel, snake) => {
49
+ const value = raw[camel] ?? raw[snake];
50
+ return Array.isArray(value) ? value.map(String) : [];
51
+ };
52
+ const regex = raw.allowedRegex ?? raw.allowed_regex;
53
+ return {
54
+ mode: raw.mode === 'restricted' ? 'restricted' : 'allow_all',
55
+ allowedEmails: list('allowedEmails', 'allowed_emails'),
56
+ allowedDomains: list('allowedDomains', 'allowed_domains'),
57
+ allowedRegex: typeof regex === 'string' && regex ? regex : null,
58
+ };
59
+ }
60
+ /** What the account half of "Add inbox" needs: may the viewer share, and "Everyone in {project}". */
61
+ function useInboxAccountAccess(projectId) {
62
+ const tSharing = useTranslations('accessSharing');
63
+ const accountId = useProjectAccountId(projectId);
64
+ const canManageConnections = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_CONNECTOR_CONNECTIONS_MANAGE, { accountId }).allowed === true;
65
+ const projectQuery = useQuery({
66
+ queryKey: qk.project.detail(projectId),
67
+ queryFn: () => getProjectDetail(projectId),
68
+ ...contract('config'),
69
+ });
70
+ const projectName = projectQuery.data?.project?.name ?? '';
71
+ const everyoneLabel = projectName ? tSharing('everyone', { project: projectName }) : tSharing('visibilityEveryone');
72
+ return { accountId, canManageConnections, everyoneLabel };
73
+ }
74
+ const EMPTY_DRAFT = { label: '', audience: 'project', picked: { memberIds: [], groupIds: [] } };
75
+ /**
76
+ * "Add inbox": the account's name and who can use it (`AddAccountFields`, the
77
+ * same fields every connector's Add account asks), then the inbox itself
78
+ * (`EmailConnectForm`). Picked people get the account shared with them after
79
+ * it exists, exactly like `useAddAccount`.
80
+ */
81
+ export function AddEmailInboxDialog({ projectId, open, onOpenChange, existing, onAdded, }) {
82
+ const t = useTranslations('emailInboxes');
83
+ const { accountId, canManageConnections, everyoneLabel } = useInboxAccountAccess(projectId);
84
+ const [draft, setDraft] = useState(EMPTY_DRAFT);
85
+ const [opened, setOpened] = useState(false);
86
+ // Each opening starts from a free name; a shared account needs the right to share.
87
+ if (open && !opened) {
88
+ setOpened(true);
89
+ setDraft({
90
+ ...EMPTY_DRAFT,
91
+ audience: canManageConnections ? 'project' : 'private',
92
+ label: proposeAccountLabel(t('defaultLabel'), existing.map((row) => row.label)),
93
+ });
94
+ }
95
+ if (!open && opened)
96
+ setOpened(false);
97
+ const labelTaken = newAccountLabelTaken(draft, existing);
98
+ const share = draft.audience === 'private' ? 'me' : 'project';
99
+ const ready = draft.label.trim().length > 0 &&
100
+ !labelTaken &&
101
+ (draft.audience !== 'members' || draft.picked.memberIds.length + draft.picked.groupIds.length > 0);
102
+ return (_jsx(Modal, { open: open, onOpenChange: onOpenChange, children: _jsxs(ModalContent, { className: "lg:max-w-2xl", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: t('addTitle') }), _jsx(ModalDescription, { children: t('addDescription') })] }), _jsxs(ModalBody, { className: "max-h-[75vh] space-y-6 overflow-y-auto", children: [_jsx("section", { className: "space-y-4", children: _jsx(AddAccountFields, { projectId: projectId, value: draft, onChange: setDraft, labelTaken: labelTaken, canManageConnections: canManageConnections, accountId: accountId, everyoneLabel: everyoneLabel, hint: t('labelHint'), autoFocus: true }) }), ready ? (_jsx(EmailConnectForm, { projectId: projectId, account: { label: draft.label, share }, onConnected: async (inbox) => {
103
+ if (draft.audience === 'members' && accountId) {
104
+ await grantConnectionAccess(accountId, projectId, inbox.connection_id, newAccountGrantees(draft.picked)).catch((e) => errorToast(e.message));
105
+ }
106
+ successToast(t('added', { address: inbox.email }));
107
+ onAdded(inbox);
108
+ onOpenChange(false);
109
+ } })) : (_jsx("p", { className: "text-muted-foreground text-sm", children: t('nameFirst') }))] })] }) }));
110
+ }
111
+ function splitPolicyList(value) {
112
+ return Array.from(new Set(value
113
+ .split(/[\n,]+/)
114
+ .map((item) => item.trim().toLowerCase())
115
+ .filter(Boolean)));
116
+ }
117
+ /** "Who can email" for one inbox: anyone, or only the listed senders. */
118
+ export function EmailSenderPolicyDialog({ projectId, inbox, open, onOpenChange, }) {
119
+ const t = useTranslations('emailInboxes');
120
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
121
+ const update = useUpdateEmailInbox();
122
+ const initial = inboxSenderPolicy(inbox);
123
+ const [restricted, setRestricted] = useState(initial.mode === 'restricted');
124
+ const [emails, setEmails] = useState(initial.allowedEmails.join('\n'));
125
+ const [domains, setDomains] = useState(initial.allowedDomains.join('\n'));
126
+ const [regex, setRegex] = useState(initial.allowedRegex ?? '');
127
+ const [error, setError] = useState(null);
128
+ // Each inbox opened starts from its own saved policy.
129
+ const [syncedId, setSyncedId] = useState(null);
130
+ if (inbox && open && inbox.connection_id !== syncedId) {
131
+ setSyncedId(inbox.connection_id);
132
+ setRestricted(initial.mode === 'restricted');
133
+ setEmails(initial.allowedEmails.join('\n'));
134
+ setDomains(initial.allowedDomains.join('\n'));
135
+ setRegex(initial.allowedRegex ?? '');
136
+ setError(null);
137
+ }
138
+ if (!open && syncedId)
139
+ setSyncedId(null);
140
+ const save = () => {
141
+ if (!inbox)
142
+ return;
143
+ setError(null);
144
+ const sender_policy = {
145
+ mode: restricted ? 'restricted' : 'allow_all',
146
+ allowedEmails: splitPolicyList(emails),
147
+ allowedDomains: splitPolicyList(domains).map((domain) => domain.replace(/^@+/, '')),
148
+ allowedRegex: regex.trim() || null,
149
+ };
150
+ if (sender_policy.allowedRegex) {
151
+ try {
152
+ new RegExp(sender_policy.allowedRegex);
153
+ }
154
+ catch {
155
+ setError(t('regexInvalid'));
156
+ return;
157
+ }
158
+ }
159
+ update.mutate({ projectId, connectionId: inbox.connection_id, sender_policy }, {
160
+ onSuccess: () => {
161
+ successToast(t('policySaved'));
162
+ onOpenChange(false);
163
+ },
164
+ onError: (e) => setError(e.message),
165
+ });
166
+ };
167
+ return (_jsx(Modal, { open: open, onOpenChange: (next) => !update.isPending && onOpenChange(next), children: _jsxs(ModalContent, { className: "lg:max-w-lg", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: t('policyTitle', { address: inbox?.email ?? '' }) }), _jsx(ModalDescription, { children: t('policyDescription') })] }), _jsx(ModalBody, { className: "space-y-3", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(Checkbox, { id: "email-inbox-restricted", checked: restricted, onCheckedChange: (checked) => setRestricted(Boolean(checked)), className: "mt-0.5" }), _jsxs("div", { className: "min-w-0 flex-1 space-y-3", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "email-inbox-restricted", children: tI18nComplete.raw('texta48c89f63885') }), _jsx("p", { className: "text-muted-foreground mt-1 text-xs", children: tI18nComplete.raw('text8c67b476d59b') })] }), restricted ? (_jsxs("div", { className: "grid gap-3", children: [_jsx(Field, { children: _jsx(Input, { value: emails, onChange: (e) => setEmails(e.target.value), placeholder: tI18nComplete.raw('text542d24012988') }) }), _jsx(Field, { children: _jsx(Input, { value: domains, onChange: (e) => setDomains(e.target.value), placeholder: tI18nComplete.raw('texta379a6f6eeaf') }) }), _jsx(Field, { children: _jsx(Input, { value: regex, onChange: (e) => setRegex(e.target.value), placeholder: tI18nComplete.raw('text8b21058f3253'), spellCheck: false }) })] })) : null, error ? _jsx(InfoBanner, { tone: "destructive", children: error }) : null] })] }) }), _jsxs(ModalFooter, { className: "sm:justify-between", children: [_jsx(Button, { variant: "outline-ghost", onClick: () => onOpenChange(false), disabled: update.isPending, children: tI18nComplete.raw('text19766ed6ccb2') }), _jsxs(Button, { onClick: save, disabled: update.isPending, children: [update.isPending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, tI18nComplete.raw('text1509f561f241')] })] })] }) }));
168
+ }
169
+ /**
170
+ * The Email hero (Channels tab, the Email page): the pitch until a first inbox
171
+ * exists, then how many inboxes there are, their addresses, and Manage (the
172
+ * connector page with the account list) or Add another inbox. Like ComputerHero.
173
+ */
174
+ export function EmailHero({ projectId, canWrite }) {
175
+ const t = useTranslations('emailInboxes');
176
+ const tPages = useTranslations('connectorPages');
177
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
178
+ const inboxes = useEmailInboxes(projectId);
179
+ const [addOpen, setAddOpen] = useState(false);
180
+ const list = inboxes.data ?? [];
181
+ const connected = list.length > 0;
182
+ const addresses = list.map((inbox) => inbox.email).join(', ');
183
+ return (_jsxs(_Fragment, { children: [_jsx(ChannelHeroFrame, { app: "email", title: connected ? t('heroCount', { count: list.length }) : tPages('emailHeroTitle'), lede: tPages('emailHeroLede'), status: connected ? (_jsx(ChannelHeroStatus, { label: tI18nComplete.raw('text22965568d22a'), detail: addresses || null })) : undefined, actions: connected ? (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", asChild: true, children: _jsxs(Link, { href: connectorHref(projectId, EMAIL_CONNECTOR_SLUG), children: [t('heroManage'), _jsx(CaretRightIcon, { className: "size-3.5 shrink-0" })] }) }), canWrite ? (_jsx(Button, { size: "sm", variant: "secondary", onClick: () => setAddOpen(true), children: t('heroAddAnother') })) : null] })) : canWrite ? (_jsx(Button, { className: "transition-transform active:scale-96", onClick: () => setAddOpen(true), children: t('heroAdd') })) : null, preview: _jsx(EmailThreadMock, {}) }), _jsx(AddEmailInboxDialog, { projectId: projectId, open: addOpen, onOpenChange: setAddOpen, existing: list.map((inbox) => ({ label: inbox.label, owner_type: inbox.owner_type })), onAdded: () => void inboxes.refetch() })] }));
184
+ }
@@ -1,4 +1,4 @@
1
- /** The Provider value: Kortix for a managed app, else the app itself. */
1
+ /** The Provider value: the managed partner (Composio), else the app itself. */
2
2
  export declare function providerName(appName: string, managedBy: string | null): string;
3
3
  /**
4
4
  * The info button on the Provider label that explains who manages what.
@@ -4,9 +4,9 @@ import { InfoIcon } from '@phosphor-icons/react';
4
4
  import { Button } from '../../../primitives/button.js';
5
5
  import { HoverCard, HoverCardContent, HoverCardTrigger } from '../../../primitives/hover-card.js';
6
6
  import { useTranslations } from '../../../i18n/index.js';
7
- /** The Provider value: Kortix for a managed app, else the app itself. */
7
+ /** The Provider value: the managed partner (Composio), else the app itself. */
8
8
  export function providerName(appName, managedBy) {
9
- return managedBy ? 'Kortix' : appName;
9
+ return managedBy ?? appName;
10
10
  }
11
11
  /**
12
12
  * The info button on the Provider label that explains who manages what.
@@ -1,5 +1,5 @@
1
1
  import { type ConnectorStatusTone } from './connector-status.js';
2
- /** A connector's state as a Badge with its dot: Working, Error, or Needs setup. */
2
+ /** A connector's state as a Badge with its dot: Connected, Needs account or Error. */
3
3
  export declare function ConnectorStatusBadge({ tone }: {
4
4
  tone: ConnectorStatusTone;
5
5
  }): import("react").JSX.Element;
@@ -4,13 +4,12 @@ import { useTranslations } from '../../../i18n/index.js';
4
4
  import { cn } from '../../../internal/lib/utils.js';
5
5
  import { STATUS_DOT, STATUS_WORD } from './connector-status.js';
6
6
  const STATUS_BADGE = {
7
- working: 'success',
8
- pending: 'info',
7
+ connected: 'success',
8
+ account: 'warning',
9
9
  error: 'destructive',
10
- setup: 'warning',
11
10
  };
12
- /** A connector's state as a Badge with its dot: Working, Error, or Needs setup. */
11
+ /** A connector's state as a Badge with its dot: Connected, Needs account or Error. */
13
12
  export function ConnectorStatusBadge({ tone }) {
14
13
  const t = useTranslations('connectorPages');
15
- return (_jsxs(Badge, { variant: STATUS_BADGE[tone], size: "sm", children: [_jsx("span", { "data-slot": "status-dot", "aria-hidden": true, className: cn('rounded', STATUS_DOT[tone]) }), t(STATUS_WORD[tone])] }));
14
+ return (_jsxs(Badge, { variant: STATUS_BADGE[tone], size: "sm", children: [_jsx("span", { "data-slot": "status-dot", "aria-hidden": true, className: cn('rounded-full', STATUS_DOT[tone]) }), t(STATUS_WORD[tone])] }));
16
15
  }
@@ -35,3 +35,9 @@ export declare function useConnectorDetail({ projectId, connector, canWrite, onC
35
35
  computerOpen: boolean;
36
36
  setComputerOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
37
37
  };
38
+ /**
39
+ * A connector's accounts in a project's connection list: its rows minus
40
+ * revoked ones and the server's empty shared slot. The Accounts tab, the
41
+ * header and the Connectors list all count these, so they agree.
42
+ */
43
+ export declare function connectorAccounts(connections: readonly Connection[] | undefined, connector: AdminConnector): Connection[];
@@ -21,7 +21,9 @@ import { connectorUsable } from './connector-status.js';
21
21
  */
22
22
  export function useConnectorDetail({ projectId, connector, canWrite, onChanged, }) {
23
23
  const isManagedProvider = isManagedConnectorProvider(connector.provider);
24
- const isChannel = connector.provider === 'channel';
24
+ // Email is a channel whose accounts are inboxes: it lists and adds accounts
25
+ // like any connector, so only the single-install channels count here.
26
+ const isChannel = connector.provider === 'channel' && connector.platform !== 'email';
25
27
  const isComputer = connector.provider === 'computer';
26
28
  const displayName = connectorDisplayName(connector);
27
29
  const [credentialTarget, setCredentialTarget] = useState(null);
@@ -41,9 +43,7 @@ export function useConnectorDetail({ projectId, connector, canWrite, onChanged,
41
43
  // whose only shared account had just been disconnected).
42
44
  // The server's empty shared slot is a placeholder, not an account: it is
43
45
  // not listed or counted (see `emptyProjectSlot`).
44
- const rows = connectorConnectionRows(connectionsQuery.data?.connections, connector.slug);
45
- const slot = emptyProjectSlot(connector, rows);
46
- const accounts = rows.filter((connection) => connection !== slot && connection.status !== 'revoked');
46
+ const accounts = connectorAccounts(connectionsQuery.data?.connections, connector);
47
47
  const soleAccount = accounts.length === 1 ? accounts[0] : null;
48
48
  // Server-computed and account-aware: `needs_auth` means no reachable account
49
49
  // holds a usable credential, whatever the owner type.
@@ -132,3 +132,13 @@ export function useConnectorDetail({ projectId, connector, canWrite, onChanged,
132
132
  setComputerOpen,
133
133
  };
134
134
  }
135
+ /**
136
+ * A connector's accounts in a project's connection list: its rows minus
137
+ * revoked ones and the server's empty shared slot. The Accounts tab, the
138
+ * header and the Connectors list all count these, so they agree.
139
+ */
140
+ export function connectorAccounts(connections, connector) {
141
+ const rows = connectorConnectionRows(connections, connector.slug);
142
+ const slot = emptyProjectSlot(connector, rows);
143
+ return rows.filter((connection) => connection !== slot && connection.status !== 'revoked');
144
+ }
@@ -0,0 +1,23 @@
1
+ import { useTranslations } from '../../../i18n/index.js';
2
+ import { type WayKind } from './way-kind.js';
3
+ /** One way to connect, as the Install dialog describes it. */
4
+ export interface InstallWay {
5
+ kind: WayKind;
6
+ oneClick: boolean;
7
+ }
8
+ /**
9
+ * Install → this dialog → the connector. The text says which way it
10
+ * connects, so a Composio app or an API key never comes as a surprise. The
11
+ * name is the app's; Rename opens the field for the rare second install.
12
+ * Who may use an account is chosen next, in Add account.
13
+ */
14
+ export declare function InstallDialog({ appName, way, open, pending, onOpenChange, onConfirm, }: {
15
+ appName: string;
16
+ way: InstallWay;
17
+ open: boolean;
18
+ pending: boolean;
19
+ onOpenChange: (open: boolean) => void;
20
+ onConfirm: (name: string) => void;
21
+ }): import("react").JSX.Element;
22
+ /** What connecting this way means for the user, in one or two sentences. */
23
+ export declare function wayDescription(t: ReturnType<typeof useTranslations>, way: InstallWay, appName: string): string;
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId, useState } from 'react';
4
+ import { Badge } from '../../../primitives/badge.js';
5
+ import { Button } from '../../../primitives/button.js';
6
+ import { Field, FieldDescription, FieldLabel } from '../../../primitives/field.js';
7
+ import { Input } from '../../../primitives/input.js';
8
+ import Loading from '../../../primitives/loading.js';
9
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, } from '../../../primitives/modal.js';
10
+ import { useTranslations } from '../../../i18n/index.js';
11
+ import { wayKindLabel } from './way-kind.js';
12
+ /**
13
+ * Install → this dialog → the connector. The text says which way it
14
+ * connects, so a Composio app or an API key never comes as a surprise. The
15
+ * name is the app's; Rename opens the field for the rare second install.
16
+ * Who may use an account is chosen next, in Add account.
17
+ */
18
+ export function InstallDialog({ appName, way, open, pending, onOpenChange, onConfirm, }) {
19
+ const t = useTranslations('connectorPages');
20
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
21
+ const id = useId();
22
+ const [name, setName] = useState(appName);
23
+ const [renaming, setRenaming] = useState(false);
24
+ const valid = /[a-z0-9]/i.test(name);
25
+ return (_jsx(Modal, { open: open, onOpenChange: (next) => !pending && onOpenChange(next), children: _jsxs(ModalContent, { className: "lg:max-w-md", children: [_jsxs(ModalHeader, { children: [_jsxs(ModalTitle, { className: "flex items-center gap-2", children: [t('installTitle', { name: appName }), _jsx(Badge, { variant: "muted", size: "xs", children: wayKindLabel(way.kind) })] }), _jsx(ModalDescription, { children: wayDescription(t, way, appName) })] }), _jsxs("form", { onSubmit: (event) => {
26
+ event.preventDefault();
27
+ if (valid && !pending)
28
+ onConfirm(name.trim());
29
+ }, children: [_jsx(ModalBody, { className: "space-y-4", children: renaming ? (_jsxs(Field, { children: [_jsx(FieldLabel, { htmlFor: `${id}-name`, children: t('installNameLabel') }), _jsx(Input, { id: `${id}-name`, value: name, onChange: (event) => setName(event.target.value), autoComplete: "off", disabled: pending, autoFocus: true }), _jsx(FieldDescription, { children: t('installProfileHint') })] })) : (_jsxs("p", { className: "text-muted-foreground flex flex-wrap items-center gap-x-2 text-sm text-pretty", children: [t('installNextStep', { name: appName }), _jsx(Button, { type: "button", variant: "text", size: "sm", className: "h-auto px-0", onClick: () => setRenaming(true), disabled: pending, children: t('installRename') })] })) }), _jsxs(ModalFooter, { className: "sm:justify-between", children: [_jsx(Button, { type: "button", variant: "outline-ghost", onClick: () => onOpenChange(false), disabled: pending, children: tI18nComplete.raw('text19766ed6ccb2') }), _jsxs(Button, { type: "submit", disabled: !valid || pending, children: [pending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, t('install')] })] })] })] }) }));
30
+ }
31
+ /** What connecting this way means for the user, in one or two sentences. */
32
+ export function wayDescription(t, way, appName) {
33
+ if (way.kind === 'composio')
34
+ return t('wayComposio', { name: appName });
35
+ if (way.kind === 'kortix')
36
+ return t('wayChannel', { name: appName });
37
+ if (way.kind === 'mcp')
38
+ return way.oneClick ? t('wayMcpOneClick', { name: appName }) : t('wayMcpSetup', { name: appName });
39
+ return t('wayApi', { name: appName, kind: wayKindLabel(way.kind) });
40
+ }
@@ -41,13 +41,18 @@ export declare function proposeAccountLabel(appName: string, taken: readonly str
41
41
  export interface InstallDeps {
42
42
  createConnector(projectId: string, draft: ConnectorDraftInput): Promise<{
43
43
  sync?: ConnectorSyncResult;
44
+ existing?: boolean;
45
+ slug?: string;
44
46
  }>;
45
47
  /** Slug suffix source; injectable so tests are deterministic. */
46
48
  random?: () => string;
47
49
  }
48
- export type InstallResult = {
50
+ export type InstallResult =
51
+ /** `existing`: the project already had this profile, and Install opened it. */
52
+ {
49
53
  status: 'installed';
50
54
  slug: string;
55
+ existing?: boolean;
51
56
  }
52
57
  /** The profile exists; its page shows the error and Retry. */
53
58
  | {
@@ -62,10 +67,16 @@ export type InstallResult = {
62
67
  * A profile is always the project's: the app, its config and its rules (a
63
68
  * `kortix.yaml` entry). Who may use it is a property of each ACCOUNT, chosen
64
69
  * when one is added (`useAddAccount`), never here. When the project already
65
- * has a profile for this app and surface, Install reuses it.
70
+ * has a profile for this app and surface, Install reuses it, unless the user
71
+ * asked for another profile (`asNewProfile`). A server that finds the profile
72
+ * itself answers `existing: true` with its slug.
66
73
  */
67
74
  export declare function runInstall(deps: InstallDeps, input: {
68
75
  projectId: string;
69
76
  target: InstallTarget;
70
77
  connectors: readonly Pick<AdminConnector, 'slug' | 'provider' | 'name'>[];
78
+ /** The profile's name, as the user chose it. Default: the app's name. */
79
+ name?: string;
80
+ /** Add a second profile of the same app and way (Settings → Install as another profile). */
81
+ asNewProfile?: boolean;
71
82
  }): Promise<InstallResult>;
@@ -76,17 +76,22 @@ export function proposeAccountLabel(appName, taken) {
76
76
  * A profile is always the project's: the app, its config and its rules (a
77
77
  * `kortix.yaml` entry). Who may use it is a property of each ACCOUNT, chosen
78
78
  * when one is added (`useAddAccount`), never here. When the project already
79
- * has a profile for this app and surface, Install reuses it.
79
+ * has a profile for this app and surface, Install reuses it, unless the user
80
+ * asked for another profile (`asNewProfile`). A server that finds the profile
81
+ * itself answers `existing: true` with its slug.
80
82
  */
81
83
  export async function runInstall(deps, input) {
82
- const { projectId, target, connectors } = input;
84
+ const { projectId, connectors } = input;
85
+ const target = input.name?.trim() ? { ...input.target, appName: input.name.trim() } : input.target;
83
86
  const existing = connectors.find((connector) => connectorInstalledFrom(connector, target.appName, target.provider));
84
- if (existing)
85
- return { status: 'installed', slug: existing.slug };
87
+ if (existing && !input.asNewProfile)
88
+ return { status: 'installed', slug: existing.slug, existing: true };
86
89
  const slugs = connectors.map((connector) => connector.slug);
87
90
  const slug = proposeConnectorConnectionSlug(target.appName, slugs, deps.random);
88
91
  const name = proposeConnectorConnectionName(target.appName, slugs);
89
92
  const result = await deps.createConnector(projectId, target.buildDraft({ slug, name }));
93
+ if (result.existing && result.slug)
94
+ return { status: 'installed', slug: result.slug, existing: true };
90
95
  const syncError = connectorSyncErrorForSlug(result, slug);
91
96
  // An MCP server that signs in with OAuth answers its first tools/list with
92
97
  // 401 or 403: that is the sign-in still to do, not a broken install.
@@ -1,8 +1,18 @@
1
1
  import { type AdminConnector } from '@kortix/sdk';
2
- import type { CatalogEntry } from '../catalog/catalog-entry.js';
2
+ import { type CatalogEntry } from '../catalog/catalog-entry.js';
3
3
  import { type AppRef } from '../connector-routes.js';
4
4
  import { type InstallTarget } from './install.js';
5
- import { type McpServerApp } from './mcp-first.js';
5
+ import type { InstallWay } from './install-dialog.js';
6
+ import type { McpServerApp } from './mcp-first.js';
7
+ /** An Install waiting for the user to name the profile (`InstallDialog`). */
8
+ export interface InstallRequest {
9
+ target: InstallTarget;
10
+ way: InstallWay;
11
+ connectors: readonly AdminConnector[];
12
+ app: AppRef | null;
13
+ addAccount?: boolean;
14
+ asNewProfile?: boolean;
15
+ }
6
16
  /**
7
17
  * Install one app: add its connector profile to the project, then open the
8
18
  * connector page with "Add account" showing. Who may use an account is chosen
@@ -21,8 +31,15 @@ export declare function useInstall(projectId: string, options?: {
21
31
  /** Open "Add account" on the connector page. False for a server with
22
32
  * nothing to sign in to: its project account is the connection. */
23
33
  addAccount?: boolean;
34
+ /** The profile's name, as the user chose it. */
35
+ name?: string;
36
+ asNewProfile?: boolean;
24
37
  }) => void;
25
38
  installEntry: (entry: CatalogEntry, connectors: readonly AdminConnector[]) => void;
39
+ ask: (next: InstallRequest) => void;
40
+ confirm: (name: string) => void;
41
+ request: InstallRequest | null;
42
+ setRequest: import("react").Dispatch<import("react").SetStateAction<InstallRequest | null>>;
26
43
  pendingKey: string | null;
27
44
  setPendingKey: import("react").Dispatch<import("react").SetStateAction<string | null>>;
28
45
  };
@@ -5,10 +5,10 @@ import { useQueryClient } from '@tanstack/react-query';
5
5
  import { useUiRouter } from '../../../providers/ui-provider.js';
6
6
  import { useCallback, useState } from 'react';
7
7
  import { errorToast, successToast, warningToast } from '../../../primitives/toast.js';
8
+ import { connectToolkitApp } from '../catalog/catalog-entry.js';
8
9
  import { appHref, appRefFromEntry, connectorHref, } from '../connector-routes.js';
9
10
  import { useTranslations } from '../../../i18n/index.js';
10
11
  import { discoverInstallTarget, easyConnectInstallTarget, runInstall, } from './install.js';
11
- import { mcpServerFor } from './mcp-first.js';
12
12
  import { pickSurface } from './pick-surface.js';
13
13
  const sdkInstallDeps = { createConnector };
14
14
  /**
@@ -27,11 +27,18 @@ export function useInstall(projectId, options = {}) {
27
27
  const router = useUiRouter();
28
28
  const queryClient = useQueryClient();
29
29
  const [pendingKey, setPendingKey] = useState(null);
30
+ const [request, setRequest] = useState(null);
30
31
  const install = useCallback((target, options) => {
31
32
  /** Settles when every invalidated query has refetched. Never rejects. */
32
33
  const refresh = () => invalidateConnections(queryClient, projectId);
33
34
  setPendingKey(options.app?.slug ?? target.appName);
34
- void runInstall(sdkInstallDeps, { projectId, target, connectors: options.connectors })
35
+ void runInstall(sdkInstallDeps, {
36
+ projectId,
37
+ target,
38
+ connectors: options.connectors,
39
+ name: options.name,
40
+ asNewProfile: options.asNewProfile,
41
+ })
35
42
  .then(async (result) => {
36
43
  // Before the navigation: the connector page reads the fresh list.
37
44
  await refresh();
@@ -41,8 +48,11 @@ export function useInstall(projectId, options = {}) {
41
48
  if (failed) {
42
49
  warningToast(t('installedSyncFailed', { name: result.name, error: result.error }));
43
50
  }
51
+ else if (result.existing) {
52
+ successToast(t('installedAlready', { name: options.name?.trim() || target.appName }));
53
+ }
44
54
  else {
45
- successToast(t('installed', { name: target.appName }));
55
+ successToast(t('installed', { name: options.name?.trim() || target.appName }));
46
56
  }
47
57
  router.push(connectorHref(projectId, result.slug, {
48
58
  app: options.app,
@@ -58,30 +68,35 @@ export function useInstall(projectId, options = {}) {
58
68
  })
59
69
  .finally(() => setPendingKey(null));
60
70
  }, [projectId, queryClient, router, t, tI18nComplete]);
61
- /** Install straight from a catalogue card. */
71
+ /** Ask for the profile's name, then install (`confirm`). */
72
+ const ask = useCallback((next) => {
73
+ setPendingKey(null);
74
+ setRequest(next);
75
+ }, []);
76
+ /** The user named the profile in `InstallDialog`: install it. */
77
+ const confirm = useCallback((name) => {
78
+ if (!request)
79
+ return;
80
+ setRequest(null);
81
+ install(request.target, {
82
+ connectors: request.connectors,
83
+ app: request.app,
84
+ addAccount: request.addAccount,
85
+ asNewProfile: request.asNewProfile,
86
+ name,
87
+ });
88
+ }, [install, request]);
89
+ /** Install straight from a catalogue card: its recommended way, after the
90
+ * user names the profile. A one-click MCP server opens the MCP dialog. */
62
91
  const installEntry = useCallback((entry, connectors) => {
63
92
  const app = appRefFromEntry(entry);
64
- if (entry.source === 'easy-connect') {
65
- if (!onMcpServer || !entry.app.directMcpUrl) {
66
- install(easyConnectInstallTarget(entry.app), { connectors, app });
67
- return;
68
- }
69
- setPendingKey(app?.slug ?? entry.app.name);
70
- void mcpServerFor(projectId, entry.app).then((server) => {
71
- if (server) {
72
- setPendingKey(null);
73
- onMcpServer(server);
74
- }
75
- else {
76
- install(easyConnectInstallTarget(entry.app), { connectors, app });
77
- }
78
- });
93
+ // What Kortix built is set up on its own page, not installed.
94
+ if (entry.connector.kind === 'kortix') {
95
+ router.push(appHref(projectId, app));
79
96
  return;
80
97
  }
81
- if (entry.source !== 'discover' || !app)
82
- return;
83
- // A Discover card does not carry its surfaces; the detail does. Direct
84
- // providers open no provider window, so this fetch costs no click.
98
+ // A Discover card does not carry its ways to connect; the detail does,
99
+ // best first, with the recommended one marked.
85
100
  setPendingKey(app.slug);
86
101
  void queryClient
87
102
  .fetchQuery({
@@ -90,7 +105,17 @@ export function useInstall(projectId, options = {}) {
90
105
  staleTime: 15 * 60_000,
91
106
  })
92
107
  .then(async (detail) => {
93
- const variant = pickSurface(detail.variants);
108
+ const recommended = detail.variants.find((variant) => variant.recommended);
109
+ if (recommended?.kind === 'composio' && recommended.composio) {
110
+ ask({
111
+ target: easyConnectInstallTarget(connectToolkitApp(recommended.composio)),
112
+ way: { kind: 'composio', oneClick: true },
113
+ connectors,
114
+ app,
115
+ });
116
+ return;
117
+ }
118
+ const variant = pickSurface(recommended ? [recommended] : detail.variants);
94
119
  if (!variant) {
95
120
  // Nothing installable from here: the app page shows its surfaces.
96
121
  setPendingKey(null);
@@ -98,29 +123,32 @@ export function useInstall(projectId, options = {}) {
98
123
  return;
99
124
  }
100
125
  const mcpUrl = variant.kind === 'mcp' ? variant.template.url : undefined;
101
- // A Kortix catalogue app (connectors_v2) is its vendor's MCP server:
102
- // a one-click sign-in opens the one-step MCP dialog, a public server
103
- // installs with no account to add, anything else installs as before.
104
- if (entry.connector.feeds.includes('kortix') && mcpUrl && onMcpServer) {
126
+ // A Kortix catalogue app or a one-click server is the vendor's MCP
127
+ // server: a one-click sign-in opens the one-step MCP dialog (which
128
+ // names the profile too); anything else asks for the name first.
129
+ const oneClickServer = entry.connector.feeds.includes('kortix') || recommended?.oneClick === true || entry.connector.oneClick === true;
130
+ let addAccount;
131
+ if (oneClickServer && mcpUrl && onMcpServer) {
105
132
  const check = await checkMcpServerSignIn(projectId, mcpUrl).catch(() => null);
106
133
  if (check?.one_click) {
107
134
  setPendingKey(null);
108
135
  onMcpServer({ name: entry.name, url: mcpUrl });
109
136
  return;
110
137
  }
111
- install(discoverInstallTarget(entry.name, variant), {
112
- connectors,
113
- app,
114
- addAccount: check?.requires_sign_in !== false,
115
- });
116
- return;
138
+ addAccount = check?.requires_sign_in !== false;
117
139
  }
118
- install(discoverInstallTarget(entry.name, variant), { connectors, app });
140
+ ask({
141
+ target: discoverInstallTarget(entry.name, variant),
142
+ way: { kind: variant.kind, oneClick: recommended?.oneClick === true },
143
+ connectors,
144
+ app,
145
+ ...(addAccount !== undefined ? { addAccount } : {}),
146
+ });
119
147
  })
120
148
  .catch((error) => {
121
149
  setPendingKey(null);
122
150
  errorToast(error.message || tI18nComplete.raw('texta34a2714da91'));
123
151
  });
124
- }, [install, onMcpServer, projectId, queryClient, router, tI18nComplete]);
125
- return { install, installEntry, pendingKey, setPendingKey };
152
+ }, [ask, onMcpServer, projectId, queryClient, router, tI18nComplete]);
153
+ return { install, installEntry, ask, confirm, request, setRequest, pendingKey, setPendingKey };
126
154
  }
@@ -0,0 +1,5 @@
1
+ import type { DiscoverConnectorVariant } from '@kortix/sdk';
2
+ /** How one way to connect an app works: its catalogue kind, or the managed partner. */
3
+ export type WayKind = DiscoverConnectorVariant['kind'] | 'pipedream';
4
+ /** The badge a way to connect carries everywhere: cards, the app page, Install. */
5
+ export declare function wayKindLabel(kind: WayKind): string;