@kortix/ui 0.14.8 → 0.14.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +63 -3
  3. package/dist/_vendor/shared/app-config.d.ts +175 -0
  4. package/dist/_vendor/shared/channel-message.d.ts +34 -5
  5. package/dist/_vendor/shared/index.d.ts +1 -0
  6. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  7. package/dist/access/access/access-detail-shell.js +1 -1
  8. package/dist/access/access/principal-picker.d.ts +11 -0
  9. package/dist/access/access/principal-picker.js +3 -2
  10. package/dist/apps/app-preview-pool.d.ts +7 -2
  11. package/dist/apps/app-preview-pool.js +11 -5
  12. package/dist/apps/app-shared.d.ts +22 -15
  13. package/dist/apps/app-shared.js +37 -19
  14. package/dist/apps/index.d.ts +2 -2
  15. package/dist/apps/index.js +2 -2
  16. package/dist/artifacts/artifact-frame.d.ts +16 -0
  17. package/dist/artifacts/artifact-frame.js +51 -0
  18. package/dist/artifacts/artifact-session.d.ts +18 -0
  19. package/dist/artifacts/artifact-session.js +101 -0
  20. package/dist/artifacts/frame-policy.d.ts +30 -0
  21. package/dist/artifacts/frame-policy.js +61 -0
  22. package/dist/artifacts/index.d.ts +3 -0
  23. package/dist/artifacts/index.js +5 -0
  24. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  25. package/dist/browser/sandbox-browser-chrome.js +2 -2
  26. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  27. package/dist/customize/agents/agent-grant-pages.js +30 -4
  28. package/dist/customize/agents/agent-page.js +3 -1
  29. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  30. package/dist/customize/agents/agent-policy-sets.js +72 -0
  31. package/dist/customize/agents/agent-triggers-section.js +2 -1
  32. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  33. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  34. package/dist/customize/connectors/agent-access.d.ts +35 -0
  35. package/dist/customize/connectors/agent-access.js +77 -0
  36. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  37. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  38. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  39. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  40. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  41. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  42. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  43. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  44. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  45. package/dist/customize/connectors/connector-identity.js +13 -42
  46. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  47. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  48. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  49. package/dist/customize/connectors/connector-routes.js +29 -20
  50. package/dist/customize/connectors/connectors-page.js +53 -82
  51. package/dist/customize/connectors/detail/app-page.js +226 -98
  52. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  53. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  54. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  55. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  56. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  57. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  58. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  59. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  60. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  61. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  62. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  63. package/dist/customize/connectors/detail/connector-page.js +14 -10
  64. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  65. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  66. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  67. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  68. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  69. package/dist/customize/connectors/detail/connector-status.js +34 -10
  70. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  71. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  72. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  73. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  74. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  75. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  76. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  77. package/dist/customize/connectors/detail/provider-info.js +2 -2
  78. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  79. package/dist/customize/connectors/detail/status-badge.js +4 -5
  80. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  81. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  82. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  83. package/dist/customize/connectors/install/install-dialog.js +40 -0
  84. package/dist/customize/connectors/install/install.d.ts +13 -2
  85. package/dist/customize/connectors/install/install.js +9 -4
  86. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  87. package/dist/customize/connectors/install/use-install.js +65 -37
  88. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  89. package/dist/customize/connectors/install/way-kind.js +16 -0
  90. package/dist/customize/connectors/provider-label.d.ts +2 -1
  91. package/dist/customize/connectors/provider-label.js +13 -3
  92. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  93. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  94. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  95. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  96. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  97. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  98. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  99. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  100. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  101. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  102. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  103. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  104. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  105. package/dist/customize/connectors/use-agent-access.js +72 -0
  106. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  107. package/dist/customize/migrate-to-v2/index.js +1 -2
  108. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -25
  109. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -236
  110. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  111. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  112. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  113. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  114. package/dist/customize/providers/provider-accordion.js +17 -2
  115. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  116. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  117. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  118. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  119. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  120. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  121. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  122. package/dist/customize/sections/component/channel-mocks.js +46 -0
  123. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  124. package/dist/customize/sections/component/channel-row.js +10 -4
  125. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  126. package/dist/customize/sections/component/email-connect-form.js +183 -0
  127. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  128. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  129. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  130. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  131. package/dist/customize/sections/component/telegram-channel-row.js +16 -25
  132. package/dist/customize/sections/connectors-view.d.ts +1 -15
  133. package/dist/customize/sections/connectors-view.js +81 -314
  134. package/dist/customize/sections/view/agent-editor-catalog.js +5 -0
  135. package/dist/customize/sections/view/channels-view.d.ts +5 -1
  136. package/dist/customize/sections/view/channels-view.js +61 -75
  137. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  138. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  139. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +1 -12
  140. package/dist/customize/shared/catalog/catalog-empty-state.js +3 -3
  141. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  142. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  143. package/dist/customize/shared/feature-gate-screen.js +27 -9
  144. package/dist/customize/shared/use-customize-prefetch.d.ts +2 -3
  145. package/dist/customize/shared/use-customize-prefetch.js +9 -27
  146. package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
  147. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  148. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  149. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  150. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  151. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  152. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  153. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  154. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  155. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  156. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  157. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  158. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  159. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  160. package/dist/customize/triggers/schedule-view.js +5 -2
  161. package/dist/files/index.d.ts +1 -0
  162. package/dist/files/index.js +1 -0
  163. package/dist/files/project/change-request-recovery.d.ts +1 -26
  164. package/dist/files/project/change-request-recovery.js +1 -59
  165. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  166. package/dist/files/project/components/drive-explorer.js +15 -15
  167. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  168. package/dist/files/project/components/drive-toolbar.js +14 -5
  169. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  170. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  171. package/dist/files/project/hooks/use-change-requests.js +11 -2
  172. package/dist/files/renderers/image-frame.d.ts +46 -0
  173. package/dist/files/renderers/image-frame.js +59 -0
  174. package/dist/files/renderers/image-renderer.d.ts +11 -1
  175. package/dist/files/renderers/image-renderer.js +13 -3
  176. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  177. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  178. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  179. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  180. package/dist/files/renderers/show-content-renderer.js +56 -14
  181. package/dist/files/runtime/file-source.js +2 -0
  182. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  183. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  184. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  185. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  186. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  187. package/dist/files/viewer/file-content-renderer.js +50 -7
  188. package/dist/files/viewer/file-header.d.ts +7 -3
  189. package/dist/files/viewer/file-header.js +20 -11
  190. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  191. package/dist/files/viewer/file-preview-modal.js +10 -22
  192. package/dist/files/viewer/file-source.d.ts +13 -0
  193. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  194. package/dist/files/viewer/use-file-content-state.js +28 -10
  195. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  196. package/dist/files/viewer/viewer-actions.js +2 -2
  197. package/dist/hooks/use-media-query.d.ts +1 -0
  198. package/dist/hooks/use-mobile.d.ts +5 -0
  199. package/dist/hooks/use-mobile.js +8 -0
  200. package/dist/i18n/en.d.ts +873 -85
  201. package/dist/i18n/en.js +888 -100
  202. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  203. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  204. package/dist/index.d.ts +2 -2
  205. package/dist/index.js +2 -2
  206. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  207. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  208. package/dist/internal/account-hub/hub-sheet.js +21 -5
  209. package/dist/internal/account-hub/sections.d.ts +1 -1
  210. package/dist/internal/account-hub/sections.js +2 -1
  211. package/dist/internal/auth/auth-card-shell.js +3 -3
  212. package/dist/internal/components/agent-mark.js +5 -2
  213. package/dist/internal/connector-logo/connector-logo-source.d.ts +63 -0
  214. package/dist/internal/connector-logo/connector-logo-source.js +48 -0
  215. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  216. package/dist/internal/connector-logo/connector-logo.js +56 -0
  217. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  218. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  219. package/dist/internal/files/file-read-retry.d.ts +13 -0
  220. package/dist/internal/files/file-read-retry.js +23 -3
  221. package/dist/internal/files/session-drive-files.d.ts +5 -1
  222. package/dist/internal/files/session-drive-files.js +7 -2
  223. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  224. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  225. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  226. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  227. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  228. package/dist/internal/hooks/index.d.ts +1 -1
  229. package/dist/internal/hooks/index.js +1 -1
  230. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  231. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  232. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  233. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  234. package/dist/internal/icons/telegram.d.ts +5 -0
  235. package/dist/internal/icons/telegram.js +6 -1
  236. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  237. package/dist/internal/layout/nav-hover-card.js +84 -0
  238. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  239. package/dist/internal/layout/project-nav-row.js +3 -2
  240. package/dist/internal/layout/project-page-header.d.ts +4 -2
  241. package/dist/internal/layout/project-page-header.js +4 -3
  242. package/dist/internal/layout/project-settings-nav.js +59 -2
  243. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  244. package/dist/internal/lib/browser-error-noise.js +1 -1
  245. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  246. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  247. package/dist/internal/lib/manifest-version.d.ts +1 -1
  248. package/dist/internal/lib/manifest-version.js +2 -2
  249. package/dist/internal/lib/memory-href.d.ts +16 -0
  250. package/dist/internal/lib/memory-href.js +46 -0
  251. package/dist/internal/lib/use-project-feature-flags.js +9 -9
  252. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  253. package/dist/internal/lib/utils/heic-convert.js +3 -4
  254. package/dist/internal/lib/web-notifications.d.ts +20 -0
  255. package/dist/internal/lib/web-notifications.js +48 -4
  256. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  257. package/dist/internal/notifications/notification-bell.js +2 -2
  258. package/dist/internal/selection/selection-bar.d.ts +2 -1
  259. package/dist/internal/selection/selection-bar.js +1 -1
  260. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  261. package/dist/internal/stores/file-preview-store.js +19 -1
  262. package/dist/internal/stores/kortix-computer-store.js +3 -0
  263. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  264. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  265. package/dist/lib/routes.d.ts +13 -1
  266. package/dist/lib/routes.js +13 -0
  267. package/dist/markdown/index.d.ts +2 -1
  268. package/dist/markdown/index.js +2 -1
  269. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  270. package/dist/markdown/setup-links/approval-decision.js +6 -2
  271. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  272. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  273. package/dist/markdown/setup-links/secret-intake-form.d.ts +0 -10
  274. package/dist/markdown/setup-links/secret-intake-form.js +1 -1
  275. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  276. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  277. package/dist/markdown/unified-markdown.js +5 -5
  278. package/dist/primitives/badge.d.ts +1 -1
  279. package/dist/primitives/badge.js +2 -0
  280. package/dist/primitives/disclosure.js +14 -2
  281. package/dist/primitives/empty-art.d.ts +12 -0
  282. package/dist/primitives/empty-art.js +11 -0
  283. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  284. package/dist/primitives/mermaid-renderer.js +21 -15
  285. package/dist/primitives/resizable.js +6 -1
  286. package/dist/primitives/resize-seam.d.ts +11 -0
  287. package/dist/primitives/resize-seam.js +12 -0
  288. package/dist/primitives/sidebar-panel.js +4 -7
  289. package/dist/primitives/tabs.d.ts +14 -1
  290. package/dist/primitives/tabs.js +1 -1
  291. package/dist/providers/ui-provider.d.ts +9 -0
  292. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  293. package/dist/session/composer/ComposerAboveCard.js +2 -2
  294. package/dist/session/composer/ComposerCard.d.ts +1 -1
  295. package/dist/session/composer/ComposerCard.js +3 -3
  296. package/dist/session/composer/agent-selector.d.ts +13 -1
  297. package/dist/session/composer/agent-selector.js +25 -5
  298. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  299. package/dist/session/composer/composer-agent-access.js +27 -0
  300. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  301. package/dist/session/composer/composer-chat-input.js +8 -6
  302. package/dist/session/composer/composer-logic.d.ts +16 -0
  303. package/dist/session/composer/composer-logic.js +12 -0
  304. package/dist/session/composer/composer-underbar.d.ts +3 -1
  305. package/dist/session/composer/composer-underbar.js +4 -3
  306. package/dist/session/composer/composer.d.ts +15 -1
  307. package/dist/session/composer/composer.js +19 -1
  308. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  309. package/dist/session/composer/draft/composer-draft.js +5 -1
  310. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  311. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  312. package/dist/session/models/chatgpt-connection-button.js +54 -0
  313. package/dist/session/models/model-selector.js +5 -2
  314. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  315. package/dist/session/models/use-model-connection-gate.js +5 -5
  316. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  317. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  318. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  319. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  320. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  321. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  322. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  323. package/dist/session/panel/easy/app-preview.js +31 -12
  324. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  325. package/dist/session/panel/easy/change-requests-card.js +17 -0
  326. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  327. package/dist/session/panel/easy/easy-panel.js +5 -2
  328. package/dist/session/panel/easy/file-preview.js +1 -1
  329. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  330. package/dist/session/panel/easy/outputs-card.js +3 -2
  331. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  332. package/dist/session/panel/session-audit-panel.js +9 -2
  333. package/dist/session/panel/session-detail-panel.js +9 -3
  334. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  335. package/dist/session/panel/session-files-explorer.js +12 -3
  336. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  337. package/dist/session/panel/session-panel-provider.js +32 -7
  338. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  339. package/dist/session/panel/shared/derive-panels.js +12 -2
  340. package/dist/session/panel/shared/output-priority.js +2 -0
  341. package/dist/session/participants/session-participants.d.ts +5 -1
  342. package/dist/session/participants/session-participants.js +9 -2
  343. package/dist/session/prompts/approval-request.d.ts +5 -0
  344. package/dist/session/prompts/approval-request.js +7 -1
  345. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  346. package/dist/session/prompts/session-approval-review.js +18 -0
  347. package/dist/session/status/session-error-banner.js +2 -49
  348. package/dist/session/status/session-starting-loader.d.ts +14 -2
  349. package/dist/session/status/session-starting-loader.js +16 -4
  350. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  351. package/dist/session/thread/after-first-prompt.js +8 -0
  352. package/dist/session/thread/detect-command.d.ts +12 -0
  353. package/dist/session/thread/detect-command.js +20 -0
  354. package/dist/session/thread/session-chat.d.ts +3 -1
  355. package/dist/session/thread/session-chat.js +377 -252
  356. package/dist/session/thread/session-thread.d.ts +3 -1
  357. package/dist/session/thread/session-thread.js +9 -2
  358. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  359. package/dist/session/thread/thread-boot-rows.js +89 -0
  360. package/dist/session/thread/transcript-rows.d.ts +31 -0
  361. package/dist/session/thread/transcript-rows.js +3 -0
  362. package/dist/session/thread/transcript.d.ts +0 -9
  363. package/dist/session/thread/transcript.js +104 -19
  364. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  365. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  366. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  367. package/dist/session/tool/tool-part-renderer.js +8 -3
  368. package/dist/session/tool/tools/bash-tool.js +7 -6
  369. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  370. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  371. package/dist/session/tool/tools/codemode-tool.js +1 -1
  372. package/dist/session/tool/tools/connector-tools.js +1 -1
  373. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  374. package/dist/session/tool/tools/image-gen-tool.js +240 -53
  375. package/dist/session/tool/tools/show-tool.js +19 -8
  376. package/dist/session/turn/channel-brand.d.ts +8 -3
  377. package/dist/session/turn/channel-brand.js +20 -4
  378. package/dist/session/turn/message-author.d.ts +8 -0
  379. package/dist/session/turn/message-author.js +24 -0
  380. package/dist/session/turn/message-row.d.ts +52 -0
  381. package/dist/session/turn/message-row.js +44 -0
  382. package/dist/session/turn/plan-anchor.d.ts +1 -1
  383. package/dist/session/turn/plan-anchor.js +1 -1
  384. package/dist/session/turn/user-message.d.ts +7 -1
  385. package/dist/session/turn/user-message.js +21 -7
  386. package/dist/styles.css +1 -1
  387. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  388. package/dist/workspace/home/access-requests-bell.js +20 -6
  389. package/dist/workspace/home/first-chat.d.ts +8 -21
  390. package/dist/workspace/home/first-chat.js +22 -72
  391. package/dist/workspace/index.d.ts +6 -0
  392. package/dist/workspace/index.js +6 -0
  393. package/dist/workspace/layout/project-home.d.ts +14 -2
  394. package/dist/workspace/layout/project-home.js +60 -21
  395. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  396. package/dist/workspace/layout/use-project-home-send.js +82 -3
  397. package/dist/workspace/memory/body-doc.d.ts +17 -0
  398. package/dist/workspace/memory/body-doc.js +208 -0
  399. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  400. package/dist/workspace/memory/body-extensions.js +103 -0
  401. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  402. package/dist/workspace/memory/company-memory-page.js +16 -0
  403. package/dist/workspace/memory/memory-all.d.ts +20 -0
  404. package/dist/workspace/memory/memory-all.js +27 -0
  405. package/dist/workspace/memory/memory-body.d.ts +19 -0
  406. package/dist/workspace/memory/memory-body.js +139 -0
  407. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  408. package/dist/workspace/memory/memory-empty.js +28 -0
  409. package/dist/workspace/memory/memory-history.d.ts +27 -0
  410. package/dist/workspace/memory/memory-history.js +108 -0
  411. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  412. package/dist/workspace/memory/memory-labels.js +47 -0
  413. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  414. package/dist/workspace/memory/memory-page-list.js +156 -0
  415. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  416. package/dist/workspace/memory/memory-reader.js +123 -0
  417. package/dist/workspace/memory/memory-view.d.ts +21 -0
  418. package/dist/workspace/memory/memory-view.js +124 -0
  419. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  420. package/dist/workspace/memory/remember-popover.js +61 -0
  421. package/dist/workspace/memory/remember-this.d.ts +12 -0
  422. package/dist/workspace/memory/remember-this.js +89 -0
  423. package/dist/workspace/memory/source-mark.d.ts +18 -0
  424. package/dist/workspace/memory/source-mark.js +79 -0
  425. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  426. package/dist/workspace/memory/used-memory-chip.js +61 -0
  427. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  428. package/dist/workspace/new/advanced-fields.js +2 -2
  429. package/dist/workspace/new/source-param.d.ts +1 -1
  430. package/dist/workspace/new/source-param.js +3 -1
  431. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  432. package/dist/workspace/new/use-create-workspace.js +3 -3
  433. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  434. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  435. package/dist/workspace/projects/policies-panel.js +5 -3
  436. package/dist/workspace/review/review-actions.d.ts +4 -2
  437. package/dist/workspace/review/review-actions.js +8 -2
  438. package/dist/workspace/review/review-center.js +11 -7
  439. package/dist/workspace/review/review-detail.d.ts +10 -0
  440. package/dist/workspace/review/review-detail.js +101 -13
  441. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  442. package/dist/workspace/saved-session-skeleton.js +3 -3
  443. package/dist/workspace/session-workspace.js +15 -13
  444. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  445. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  446. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  447. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  448. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  449. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  450. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  451. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  452. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  453. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  454. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  455. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  456. package/dist/workspace/sidebar/project-session-list.js +68 -56
  457. package/dist/workspace/sidebar/project-sidebar.js +9 -2
  458. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  459. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  460. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  461. package/dist/workspace/sidebar/session-group-order.js +25 -0
  462. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  463. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  464. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  465. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  466. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  467. package/dist/workspace/spaces/channel-glyph.js +6 -0
  468. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  469. package/dist/workspace/spaces/channel-setup.js +105 -0
  470. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  471. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  472. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  473. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  474. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  475. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  476. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  477. package/dist/workspace/spaces/space-agents.js +10 -0
  478. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  479. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  480. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  481. package/dist/workspace/spaces/space-link-label.js +73 -0
  482. package/dist/workspace/spaces/space-links.d.ts +19 -0
  483. package/dist/workspace/spaces/space-links.js +230 -0
  484. package/dist/workspace/spaces/space-members.d.ts +46 -0
  485. package/dist/workspace/spaces/space-members.js +182 -0
  486. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  487. package/dist/workspace/spaces/space-roster.js +44 -0
  488. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  489. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  490. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  491. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  492. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  493. package/dist/workspace/spaces/space-timeline.js +183 -0
  494. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  495. package/dist/workspace/spaces/space-triggers.js +78 -0
  496. package/dist/workspace/spaces/space-view.d.ts +37 -0
  497. package/dist/workspace/spaces/space-view.js +436 -0
  498. package/package.json +27 -36
  499. package/skills/kortix-ui/SKILL.md +3 -3
  500. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  501. package/skills/kortix-ui/references/modules.md +28 -4
  502. package/skills/kortix-ui/references/theming.md +1 -1
  503. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  504. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  505. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  506. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  507. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  508. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  509. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  510. package/dist/customize/sections/connector-connection-header.js +0 -33
  511. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  512. package/dist/customize/sections/connector-connection-modal.js +0 -72
  513. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  514. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  515. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  516. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  517. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  518. package/dist/customize/sections/discover-catalogue.js +0 -132
  519. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  520. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  521. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  522. package/dist/files/project/components/drive-empty-art.js +0 -5
  523. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  524. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  525. package/dist/internal/share/public-share-link-button.js +0 -17
  526. package/dist/markdown/setup-links/app-credentials-form.d.ts +0 -12
  527. package/dist/markdown/setup-links/app-credentials-form.js +0 -115
  528. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useProjectMemoryPages, useSessionMemoryUsage } from '@kortix/sdk/react';
4
+ import { CaretRightIcon, SunDimIcon } from '@phosphor-icons/react';
5
+ import { useEffect, useState } from 'react';
6
+ import { useLocale, useTranslations } from '../../i18n/index.js';
7
+ import { cn } from '../../lib/utils.js';
8
+ import { Popover, PopoverContent, PopoverTrigger } from '../../primitives/popover.js';
9
+ import { UiLink as Link } from '../../providers/ui-provider.js';
10
+ import { agentLabel } from '../spaces/space-timeline.js';
11
+ import { MEMORY_TYPE_ICON } from './memory-labels.js';
12
+ import { useMemoryPageHref } from '../../internal/lib/memory-href.js';
13
+ const ROW = 'flex h-7.5 w-full items-center gap-2 rounded-md px-2 text-left text-xs';
14
+ /** A layer's name in the chip: "Company", "#marketing", or the DM's agent. */
15
+ function useLayerName() {
16
+ const t = useTranslations('spaces.memory.used');
17
+ return (layer) => (layer.scope === 'company' ? t('company') : layer.scope === 'dm' ? agentLabel(layer.name) : layer.name);
18
+ }
19
+ /**
20
+ * "Used #marketing memory · 3 pages ›" under a thread's first prompt: the
21
+ * pages its agent was given at the first turn. It reads the record only once
22
+ * `ready` (a turn has finished): before that the record is empty, and nothing
23
+ * polls it. A turn that ends while the record is still empty reads it again.
24
+ * Hidden when the thread loaded no page.
25
+ */
26
+ export function UsedMemoryChip({ projectId, sessionId, ready, className, }) {
27
+ const t = useTranslations('spaces.memory.used');
28
+ const locale = useLocale();
29
+ const layerName = useLayerName();
30
+ const [open, setOpen] = useState(false);
31
+ const usage = useSessionMemoryUsage(projectId, sessionId, { enabled: ready });
32
+ const layers = usage.data?.loaded_at ? usage.data.layers.filter((layer) => layer.pages.length > 0) : [];
33
+ const count = layers.reduce((sum, layer) => sum + layer.pages.length, 0);
34
+ if (count === 0)
35
+ return null;
36
+ const places = new Intl.ListFormat(locale, { type: 'conjunction' }).format(layers.map(layerName));
37
+ return (_jsx("div", { className: cn('flex py-1', className), children: _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "group/used text-muted-foreground hover:bg-hover hover:text-foreground focus-visible:ring-ring -mx-1 flex max-w-full items-center gap-1.5 rounded-md px-1 py-0.5 text-xs outline-none focus-visible:ring-2", children: [_jsx(SunDimIcon, { "aria-hidden": true, className: "size-4 shrink-0" }), _jsx("span", { className: "min-w-0 truncate", children: t('label', { places, count }) }), _jsx(CaretRightIcon, { "aria-hidden": true, className: "size-3 shrink-0" })] }) }), _jsxs(PopoverContent, { align: "start", className: "flex max-h-96 w-80 flex-col gap-1 overflow-y-auto p-1.5", children: [_jsx("p", { className: "text-muted-foreground px-2 pt-1 pb-0.5 text-xs", children: t('title') }), layers.map((layer) => (_jsx(UsedLayer, { projectId: projectId, layer: layer, name: layerName(layer), open: open, onOpen: () => setOpen(false) }, layer.layer_key)))] })] }) }));
38
+ }
39
+ /**
40
+ * One layer's pages. A page deleted since the thread started is shown as
41
+ * removed, read from the layer's live list (the one the Memory tab shares).
42
+ * No page request per row: a deleted page never reaches a 404.
43
+ */
44
+ function UsedLayer({ projectId, layer, name, open, onOpen, }) {
45
+ const t = useTranslations('spaces.memory.used');
46
+ const live = useProjectMemoryPages(projectId, layer.layer_key, { enabled: open });
47
+ // Mounted when the popover opens: read the live list again, so a page
48
+ // deleted since the last read shows as removed, not as a link.
49
+ const { refetch } = live;
50
+ useEffect(() => {
51
+ void refetch();
52
+ }, [refetch]);
53
+ const href = useMemoryPageHref(projectId, open);
54
+ return (_jsxs("section", { className: "flex flex-col pt-1.5", children: [_jsx("p", { className: "px-2 pb-0.5 text-xs font-medium", children: name }), layer.pages.map((page) => {
55
+ const Glyph = MEMORY_TYPE_ICON[page.type];
56
+ const removed = !!live.data && !live.data.some((candidate) => candidate.page_id === page.page_id);
57
+ const target = removed ? null : href({ scope: layer.scope, key: layer.layer_key }, page.page_id);
58
+ const body = (_jsxs(_Fragment, { children: [_jsx(Glyph, { "aria-hidden": true, className: "text-muted-foreground size-3.5 shrink-0" }), _jsx("span", { className: cn('min-w-0 flex-1 truncate', removed && 'text-muted-foreground'), children: page.title }), removed ? _jsx("span", { className: "text-muted-foreground shrink-0", children: t('removed') }) : null] }));
59
+ return target ? (_jsx(Link, { href: target, onClick: onOpen, className: cn(ROW, 'hover:bg-hover focus-visible:ring-ring outline-none focus-visible:ring-2'), children: body }, page.page_id)) : (_jsx("div", { className: ROW, children: body }, page.page_id));
60
+ })] }));
61
+ }
@@ -1,6 +1,7 @@
1
1
  import type { NewWorkspaceFormState } from './new-workspace-form.js';
2
- export declare function AdvancedFields({ state, accountId, onChange, }: {
2
+ export declare function AdvancedFields({ state, accountId, onChange, connectComputer, }: {
3
3
  state: NewWorkspaceFormState;
4
+ connectComputer?: boolean;
4
5
  /** The account the create targets — resolved by the page, which owns the
5
6
  * "one account, nothing to pick" fallback. The GitHub queries below are
6
7
  * account-scoped, so they cannot run on `state.accountId` alone: that is
@@ -55,7 +55,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
55
55
  */
56
56
  /** The `<Select>` value that opens the add-account dialog instead of picking. */
57
57
  const ADD_ACCOUNT_VALUE = '__add_github_account__';
58
- export function AdvancedFields({ state, accountId, onChange, }) {
58
+ export function AdvancedFields({ state, accountId, onChange, connectComputer, }) {
59
59
  const t = useTranslations('newWorkspace');
60
60
  const [addOpen, setAddOpen] = useState(false);
61
61
  // Same cache key the account hub's Git tab and `connected-tab.tsx` use, so
@@ -128,7 +128,7 @@ export function AdvancedFields({ state, accountId, onChange, }) {
128
128
  const addAccountDialog = accountId ? (_jsx(AddGitHubAccountDialog, { open: addOpen, onOpenChange: setAddOpen, accountId: accountId, installUrl: installUrl,
129
129
  // Round trip: the setup page reads this path back on completion, so
130
130
  // the user lands on `/new` with the same source AND the same account.
131
- returnPath: newWorkspaceReturnPath(state.source, accountId) })) : null;
131
+ returnPath: newWorkspaceReturnPath(state.source, accountId, connectComputer) })) : null;
132
132
  return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col space-y-3", children: [_jsx(Label, { htmlFor: "workspace-source", children: t('repository.gitAccountLabel') }), optionsLoading ? (
133
133
  // The trigger's own shape (md: `h-10`, the field radius), so the
134
134
  // Select lands in exactly the box that was holding its place — no
@@ -16,4 +16,4 @@
16
16
  import type { RepositorySource } from './new-workspace-form.js';
17
17
  export declare function readSourceParam(params: URLSearchParams): RepositorySource | null;
18
18
  /** The path `/github/setup` should return to, preserving the picked source. */
19
- export declare function newWorkspaceReturnPath(source: RepositorySource, accountId?: string | null): string;
19
+ export declare function newWorkspaceReturnPath(source: RepositorySource, accountId?: string | null, connectComputer?: boolean): string;
@@ -6,7 +6,7 @@ export function readSourceParam(params) {
6
6
  return SOURCES.find((source) => source === raw) ?? null;
7
7
  }
8
8
  /** The path `/github/setup` should return to, preserving the picked source. */
9
- export function newWorkspaceReturnPath(source, accountId) {
9
+ export function newWorkspaceReturnPath(source, accountId, connectComputer) {
10
10
  const params = new URLSearchParams();
11
11
  if (source !== 'managed')
12
12
  params.set('source', source);
@@ -15,6 +15,8 @@ export function newWorkspaceReturnPath(source, accountId) {
15
15
  // account is connected" about the wrong account (dev, 2026-09-17).
16
16
  if (accountId)
17
17
  params.set('account', accountId);
18
+ if (connectComputer)
19
+ params.set('connect', 'computer');
18
20
  const qs = params.toString();
19
21
  return qs ? `/new?${qs}` : '/new';
20
22
  }
@@ -401,19 +401,15 @@ export type CreateOrchestrationClient = {
401
401
  projectsCachedForAccount: (accountId: string) => KortixProject[] | undefined;
402
402
  /**
403
403
  * Stamp the created project onboarded — the same `PATCH /projects/:id/onboarding`
404
- * the wizard's own exits run. A create that lands the user directly on the
405
- * project page (see `enterProject`) is an implicit skip: the wizard must not
406
- * mount full-screen over the workspace they just asked for. This is why the
404
+ * the onboarding chat's kickoff runs. A later project lands on the usual home,
405
+ * never on the onboarding chat. This is why the
407
406
  * stamp lives in the flow and not on the server's provision route: it reuses
408
407
  * an existing endpoint instead of growing the create contract.
409
408
  *
410
409
  * Only a LATER project is stamped. A fresh account's first project stays
411
- * unstamped, so the shell's wizard opens on the landing and walks the new
412
- * user through work, apps and models — the post-signup onboarding the
413
- * signup journey expects (KRTX-2092). That mount is not the trap the
414
- * implicit skip exists to prevent: the shell's wizard now carries the Skip
415
- * control, and its exit opens the first chat in place. An experienced user
416
- * creating project two never sees the wizard again (KRTX-1419).
410
+ * unstamped, so it opens on the onboarding chat, where the agent onboards
411
+ * the new user (KRTX-2092). An experienced user creating project two never
412
+ * sees onboarding again (KRTX-1419).
417
413
  */
418
414
  completeOnboarding: (projectId: string) => Promise<unknown>;
419
415
  /**
@@ -497,7 +493,9 @@ export declare function runCreate(state: NewWorkspaceFormState, creatableAccount
497
493
  * target account (`resolveTargetAccountId`) without a second, page-specific
498
494
  * query.
499
495
  */
500
- export declare function useCreateWorkspace(): {
496
+ export declare function useCreateWorkspace(options?: {
497
+ enterProject?: (projectId: string) => void;
498
+ }): {
501
499
  create: (state: NewWorkspaceFormState) => Promise<void>;
502
500
  status: CreateStatus;
503
501
  error: string | null;
@@ -641,7 +641,7 @@ export async function runCreate(state, creatableAccounts, userId, client) {
641
641
  * target account (`resolveTargetAccountId`) without a second, page-specific
642
642
  * query.
643
643
  */
644
- export function useCreateWorkspace() {
644
+ export function useCreateWorkspace(options) {
645
645
  const router = useUiRouter();
646
646
  const queryClient = useQueryClient();
647
647
  const viewerId = useUiViewerId();
@@ -726,7 +726,7 @@ export function useCreateWorkspace() {
726
726
  // decision reads `projectsCachedForAccount`), so its onboarding wizard
727
727
  // opens on the landing (KRTX-2092).
728
728
  completeOnboarding: (projectId) => setProjectOnboardingComplete(projectId, true),
729
- enterProject: (projectId) => router.replace(uiRoutes().project(encodeURIComponent(projectId))),
729
+ enterProject: options?.enterProject ?? ((projectId) => router.replace(uiRoutes().project(encodeURIComponent(projectId)))),
730
730
  now: Date.now,
731
731
  });
732
732
  if (!result.ok) {
@@ -734,7 +734,7 @@ export function useCreateWorkspace() {
734
734
  setError(messageFor(result.error));
735
735
  setLastError(result.error);
736
736
  }
737
- }, [creatableAccounts, queryClient, router, viewerId]);
737
+ }, [creatableAccounts, queryClient, router, viewerId, options?.enterProject]);
738
738
  const retry = useCallback(() => {
739
739
  if (lastState)
740
740
  void create(lastState);
@@ -1,5 +1,10 @@
1
- /** A catalogue app's logo in a 24px slot, or a plug when the catalogue has none. */
2
- export declare function AppLogo({ src, className }: {
1
+ /**
2
+ * A catalogue app's logo in a 24px slot: the one connector logo
3
+ * (`ConnectorLogo`), so an app reads the same here as on its connector page.
4
+ * `slug` lets a Kortix-built app (Slack, Email, …) show its own mark.
5
+ */
6
+ export declare function AppLogo({ src, slug, className, }: {
3
7
  src: string | null;
8
+ slug?: string | null;
4
9
  className?: string;
5
10
  }): import("react").JSX.Element;
@@ -1,18 +1,11 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { PlugIcon } from '@phosphor-icons/react';
4
- import { UiImage as Image } from '../../../providers/ui-provider.js';
5
- import { cn } from '../../../internal/lib/utils.js';
3
+ import { ConnectorLogo } from '../../../internal/connector-logo/connector-logo.js';
6
4
  /**
7
- * Third-party logos are drawn for a white page: many are black marks (GitHub,
8
- * X, Notion) that vanish on a dark tile. Each one sits on a white chip in both
9
- * themes; on the light theme the chip matches the tile.
5
+ * A catalogue app's logo in a 24px slot: the one connector logo
6
+ * (`ConnectorLogo`), so an app reads the same here as on its connector page.
7
+ * `slug` lets a Kortix-built app (Slack, Email, …) show its own mark.
10
8
  */
11
- const LOGO_CHIP_CLASS = 'bg-white';
12
- /** A catalogue app's logo in a 24px slot, or a plug when the catalogue has none. */
13
- export function AppLogo({ src, className }) {
14
- if (!src) {
15
- return (_jsx("span", { "aria-hidden": true, className: cn('bg-muted text-muted-foreground flex size-6 shrink-0 items-center justify-center rounded-sm', className), children: _jsx(PlugIcon, { className: "size-3.5" }) }));
16
- }
17
- return (_jsx("span", { className: cn('flex size-6 shrink-0 items-center justify-center rounded-sm', LOGO_CHIP_CLASS, className), children: _jsx(Image, { src: src, alt: "", width: 24, height: 24, unoptimized: true, referrerPolicy: "no-referrer", className: "size-5 object-contain" }) }));
9
+ export function AppLogo({ src, slug, className, }) {
10
+ return _jsx(ConnectorLogo, { source: { slug, icon: src }, size: "sm", className: className });
18
11
  }
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  * this panel CRUDs the same file via the admin endpoint, then the gateway
6
6
  * enforces on every Connector call.
7
7
  *
8
- * Rendered in two places: the Global rules sheet on the Connectors page
8
+ * Rendered in two places: the Rules tab of the Connectors page
9
9
  * (`capabilities/connectors/connectors-page.tsx`), and the Connectors section
10
10
  * of the customize panel. Both are narrow columns, so
11
11
  * the layout is a single stack of `Label` + `bg-popover rounded-md border`
@@ -136,7 +136,9 @@ export function PoliciesPanel({ projectId }) {
136
136
  policies: draft.map((d) => toPayloadRule(d)),
137
137
  defaultMode,
138
138
  });
139
- const dirty = currentSig !== serverSig;
139
+ // Nothing is unsaved before the rules have loaded: the empty draft would
140
+ // differ from the empty signature and show the save bar over skeletons.
141
+ const dirty = serverSig !== '' && currentSig !== serverSig;
140
142
  const save = useMutation({
141
143
  mutationFn: async () => {
142
144
  const payload = [];
@@ -197,7 +199,7 @@ export function PoliciesPanel({ projectId }) {
197
199
  return (_jsxs("button", { type: "button", onClick: () => setDefaultMode(opt.value), "aria-pressed": selected, className: cn('flex cursor-pointer flex-col items-start gap-1 rounded-md border px-4 py-3 text-left',
198
200
  // Never `transition-all` — `scale` is listed so the press
199
201
  // feedback below actually eases instead of snapping.
200
- 'transition-[background-color,border-color,scale] duration-150 ease-out', 'motion-safe:active:scale-[0.99]', selected
202
+ 'transition-[background-color,border-color,scale] duration-normal ease-out', 'motion-safe:active:scale-[0.99]', selected
201
203
  ? 'border-primary/40 bg-primary/[0.06]'
202
204
  : 'bg-popover hover:bg-foreground/[0.03]'), children: [_jsxs("span", { className: "flex w-full items-center justify-between gap-2", children: [_jsx("span", { className: "text-foreground text-sm font-medium", children: opt.label }), selected ? _jsx(CheckIcon, { className: "text-foreground size-4 shrink-0" }) : null] }), _jsx("span", { className: "text-muted-foreground text-xs text-pretty", children: opt.description })] }, opt.value));
203
205
  }) }))] }), _jsxs("section", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: tI18nHardcoded.raw('i18nComplete.text4228aeb07c41') }), _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: tI18nHardcoded.raw('i18nComplete.texteb35a8dd49a7') })] }), draft.length > 0 && (_jsxs(Button, { size: "sm", variant: "secondary", className: "shrink-0 gap-1.5 self-start sm:self-auto", onClick: addRule, disabled: query.isLoading, children: [_jsx(PlusIcon, { className: "size-4 shrink-0" }), tI18nHardcoded.raw('i18nComplete.texta27cff51a2e0')] }))] }), parseErrors.length > 0 && (_jsx(InfoBanner, { tone: "warning", title: tI18nHardcoded.raw('autoComponentsProjectsPoliciesPanelJsxAttrTitleKortixTomlHad8db85c74'), children: _jsx("ul", { className: "space-y-1", children: parseErrors.map((e) => (_jsxs("li", { className: "text-xs", children: [_jsx("span", { className: "font-mono", children: e.path }), ": ", e.error] }, `${e.path}:${e.error}`))) }) })), query.isLoading ? (_jsx("div", { className: "space-y-2", children: [0, 1].map((i) => (_jsx(Skeleton, { className: "h-28 rounded-md" }, i))) })) : draft.length === 0 ? (_jsx("div", { className: "bg-popover rounded-md border", children: _jsx(EmptyState, { icon: ShieldCheckIcon, size: "sm", className: "p-8 md:p-10", title: tI18nHardcoded.raw('autoComponentsProjectsPoliciesPanelJsxAttrTitleNoRulesYet795c2fb5'), description: tI18nHardcoded.raw('autoComponentsProjectsPoliciesPanelJsxAttrDescriptionRequireApprovalFor7e7b9477'), action: _jsxs(Button, { size: "sm", variant: "outline", className: "gap-1.5", onClick: addRule, children: [_jsx(PlusIcon, { className: "size-4 shrink-0" }), tI18nHardcoded.raw('i18nComplete.texta27cff51a2e0')] }) }) })) : (_jsx("ul", { className: "space-y-2", children: draft.map((rule, idx) => (_jsx(RuleRow, { rule: rule, index: idx, onChange: (patch) => updateRule(rule.id, patch), onRemove: () => removeRule(rule.id), onAddCondition: () => addCondition(rule.id), onChangeCondition: (cIdx, patch) => updateCondition(rule.id, cIdx, patch), onRemoveCondition: (cIdx) => removeCondition(rule.id, cIdx) }, rule.id))) }))] }), dirty && (_jsxs("div", { className: "bg-popover z-10 mt-auto flex flex-wrap items-center justify-between gap-3 rounded-md border px-4 py-3", children: [_jsxs("p", { className: "text-muted-foreground min-w-0 text-xs text-pretty", children: [tI18nHardcoded.raw('i18nComplete.text53121d4517f7'), ' ', _jsx("code", { className: "bg-muted text-foreground rounded-sm px-1 py-0.5 font-mono text-xs", children: "kortix.yaml" }), "."] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: revert, disabled: save.isPending, children: tI18nHardcoded.raw('i18nComplete.text0026c5053478') }), _jsxs(Button, { size: "sm", onClick: () => save.mutate(), disabled: save.isPending, children: [save.isPending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, tI18nHardcoded.raw('i18nComplete.textdd0ae7a5cbcf')] })] })] }))] }));
@@ -60,8 +60,10 @@ export declare const BULK_VERDICT: Record<BulkVerb, ReviewVerdict>;
60
60
  /**
61
61
  * Whether a bar verb acts on `item`, decided before the request so the bar
62
62
  * never sends an id the server must refuse. Approve and Deny decide a pending
63
- * approval; Approve also needs a call this viewer could review
64
- * (`approvalReviewable`) that has not expired. Dismiss acts on native items only. A `cr:` id takes no verb.
63
+ * approval, an output or a batch; on a connector approval Approve also needs a
64
+ * call this viewer could review (`approvalReviewable`) that has not expired.
65
+ * Dismiss acts on native items only. A question takes Dismiss only. A `cr:` id
66
+ * takes no verb.
65
67
  */
66
68
  export declare function bulkSupports(item: ReviewItem, verb: BulkVerb, allows: (item: ReviewItem, verdict: ReviewVerdict) => boolean, now?: number): boolean;
67
69
  /** True when any bar verb acts on `item`: the row shows a checkbox. */
@@ -86,8 +86,10 @@ export const BULK_VERDICT = {
86
86
  /**
87
87
  * Whether a bar verb acts on `item`, decided before the request so the bar
88
88
  * never sends an id the server must refuse. Approve and Deny decide a pending
89
- * approval; Approve also needs a call this viewer could review
90
- * (`approvalReviewable`) that has not expired. Dismiss acts on native items only. A `cr:` id takes no verb.
89
+ * approval, an output or a batch; on a connector approval Approve also needs a
90
+ * call this viewer could review (`approvalReviewable`) that has not expired.
91
+ * Dismiss acts on native items only. A question takes Dismiss only. A `cr:` id
92
+ * takes no verb.
91
93
  */
92
94
  export function bulkSupports(item, verb, allows, now = Date.now()) {
93
95
  if (segmentForStatus(item.status) !== 'needs_you')
@@ -96,6 +98,10 @@ export function bulkSupports(item, verb, allows, now = Date.now()) {
96
98
  return false;
97
99
  if (verb === 'dismiss')
98
100
  return connectorCallId(item.id) === null;
101
+ // A native output or batch takes the verdicts its own dialog offers. A
102
+ // question needs an answer, which no bar verb carries.
103
+ if (item.kind === 'output' || item.kind === 'batch')
104
+ return true;
99
105
  if (item.kind !== 'approval')
100
106
  return false;
101
107
  if (item.expiresAt && Date.parse(item.expiresAt) <= now)
@@ -45,7 +45,7 @@ import { reviewArgsSummary } from '../../session/prompts/session-approval-review
45
45
  import { approvalIdentity } from '../../markdown/setup-links/approval-decision.js';
46
46
  import { ConnectorAppMark } from '../../markdown/setup-links/connector-handshake.js';
47
47
  import { ApprovalDecisionModal, reviewApprovalAsker, reviewApprovalDenyOnly, reviewApprovalDetails, } from './approval-modal.js';
48
- import { ReviewDetail } from './review-detail.js';
48
+ import { ReviewDetail, ReviewItemModal } from './review-detail.js';
49
49
  import { KIND_META, reviewKindLabel, reviewStatusLabel, } from './review-meta.js';
50
50
  import { bulkSetStatus, decideApprovalAction, filterItems, groupBySession, sessionOptions, setStatus, } from './review-reducer.js';
51
51
  import { segmentForStatus, } from './types.js';
@@ -591,7 +591,9 @@ export function ReviewCenter({ initialItems, segment: segmentProp, onSegmentChan
591
591
  return setHelpOpen(false);
592
592
  if (typing)
593
593
  return el.blur();
594
- if (selectedId)
594
+ // A modal closes itself on Escape and marks it handled: only the top
595
+ // layer closes (a file preview opened from the item, then the item).
596
+ if (selectedId && !e.defaultPrevented)
595
597
  return setSelectedId(null);
596
598
  // An Esc that a dialog or menu already handled is theirs, not the selection's.
597
599
  if (selectMode && !bulkProgress && !e.defaultPrevented && !hasOpenFloatingLayer()) {
@@ -724,7 +726,7 @@ export function ReviewCenter({ initialItems, segment: segmentProp, onSegmentChan
724
726
  const details = reviewApprovalDetails(i);
725
727
  const args = reviewArgsSummary(details?.resolved_preview, details?.args_preview);
726
728
  const who = details ? approvalIdentity(details) : null;
727
- return (_jsxs("li", { className: "flex min-w-0 items-center gap-3 px-3 py-2.5", title: details?.action, children: [who ? _jsx(ConnectorAppMark, { name: who.connector ?? i.title, iconUrl: who.iconUrl, size: "md" }) : null, _jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "text-foreground truncate text-sm leading-5", children: who?.connector && who.action ? `${who.connector} · ${who.action}` : i.title }), args ? _jsx("span", { className: "text-muted-foreground truncate text-xs leading-4", children: args }) : null] }), _jsx(Badge, { variant: risk.variant, size: "xs", className: "shrink-0", children: tBulk(risk.key) })] }, i.id));
729
+ return (_jsxs("li", { className: "flex min-w-0 items-center gap-3 px-3 py-2.5", title: details?.action, children: [who ? _jsx(ConnectorAppMark, { name: who.connector ?? i.title, slug: who.slug, iconUrl: who.iconUrl, size: "md" }) : null, _jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "text-foreground truncate text-sm leading-5", children: who?.connector && who.action ? `${who.connector} · ${who.action}` : i.title }), args ? _jsx("span", { className: "text-muted-foreground truncate text-xs leading-4", children: args }) : null] }), _jsx(Badge, { variant: risk.variant, size: "xs", className: "shrink-0", children: tBulk(risk.key) })] }, i.id));
728
730
  }) }));
729
731
  const withList = (text) => (_jsxs("div", { className: "space-y-3", children: [_jsx("p", { children: text }), confirmList] }));
730
732
  const confirmCopy = confirm.verb === 'approve'
@@ -762,9 +764,11 @@ export function ReviewCenter({ initialItems, segment: segmentProp, onSegmentChan
762
764
  : undefined, onOpenSession: selected?.sessionId && onOpenSession
763
765
  ? () => onOpenSession(selected.sessionId)
764
766
  : undefined, onClose: () => setSelectedId(null) }));
765
- // Every other review page replaces the inbox in place — same scroll
766
- // container, no modal. Escape and "Back to inbox" return to the list.
767
- if (selected && !approval) {
767
+ // Every other item opens in a modal over the inbox, the same way.
768
+ const itemModal = (_jsx(ReviewItemModal, { item: selected && !approval && selected.kind !== 'change' ? selected : null, actions: actions, onClose: () => setSelectedId(null) }));
769
+ // A change request replaces the inbox in place: its diff needs the width.
770
+ // Escape and "Back to inbox" return to the list.
771
+ if (selected?.kind === 'change') {
768
772
  return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: _jsx(ReviewDetail, { item: selected, actions: actions, onBack: () => setSelectedId(null) }) }), _jsx(KeyboardHelp, { open: helpOpen, onClose: () => setHelpOpen(false) })] }));
769
773
  }
770
774
  return (_jsxs("div", { className: "relative flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: _jsxs("div", { className: cn('w-full px-4', selectMode && segment === 'needs_you' && 'pb-20'), children: [_jsxs("div", { className: "flex flex-col gap-2 py-4 sm:flex-row sm:items-center sm:justify-between", children: [_jsx(Tabs, { value: segment, onValueChange: (v) => {
@@ -797,5 +801,5 @@ export function ReviewCenter({ initialItems, segment: segmentProp, onSegmentChan
797
801
  _jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-4 z-10 flex justify-center px-4", children: _jsx("div", { className: "pointer-events-auto w-full max-w-xl", children: _jsx(SelectionBar, { selectedCount: selectedItems.length, allSelected: selectableIds.length > 0 &&
798
802
  selectedItems.length >= Math.min(BULK_MAX, selectableIds.length), canSelectAll: selectableIds.length > 0, onSelectAll: () => setSelectedIds(new Set(selectableIds.slice(0, BULK_MAX))), onClear: () => setSelectedIds(new Set()), onExit: exitSelectMode, actions: bulkActions, progress: bulkProgress, animateIn: selectMode !== 'key', note: selectedItems.length >= BULK_MAX && selectableIds.length > BULK_MAX
799
803
  ? tBulk('limitNote', { count: BULK_MAX })
800
- : undefined }) }) })) : null, _jsx(ConfirmDialog, { open: confirm.open, onOpenChange: (open) => setConfirm((c) => ({ ...c, open })), title: confirmCopy.title, description: confirmCopy.description, confirmLabel: confirmCopy.confirm, confirmVariant: confirm.verb === 'approve' ? 'default' : 'destructive', onConfirm: () => void runBulk(confirm.verb) }), approvalModal, _jsx(KeyboardHelp, { open: helpOpen, onClose: () => setHelpOpen(false) })] }));
804
+ : undefined }) }) })) : null, _jsx(ConfirmDialog, { open: confirm.open, onOpenChange: (open) => setConfirm((c) => ({ ...c, open })), title: confirmCopy.title, description: confirmCopy.description, confirmLabel: confirmCopy.confirm, confirmVariant: confirm.verb === 'approve' ? 'default' : 'destructive', onConfirm: () => void runBulk(confirm.verb) }), approvalModal, itemModal, _jsx(KeyboardHelp, { open: helpOpen, onClose: () => setHelpOpen(false) })] }));
801
805
  }
@@ -28,3 +28,13 @@ export declare function ReviewDetail({ item, actions, onBack, }: {
28
28
  actions: ReviewActions;
29
29
  onBack: () => void;
30
30
  }): import("react").JSX.Element;
31
+ /**
32
+ * Every review item but a change request opens here, over the inbox, the way a
33
+ * connector approval does (`ApprovalDecisionModal`). A change keeps its page:
34
+ * its diff needs the width. Null closes the modal.
35
+ */
36
+ export declare function ReviewItemModal({ item, actions, onClose, }: {
37
+ item: ReviewItem | null;
38
+ actions: ReviewActions;
39
+ onClose: () => void;
40
+ }): import("react").JSX.Element;
@@ -2,9 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useTranslations } from '../../i18n/index.js';
4
4
  /**
5
- * Review Center — the per-item review page. It replaces the inbox in place
6
- * (no modal): a status + title header, the branch/diff facts for a change,
7
- * the plain-language body for the item's kind, and the live file diffs.
5
+ * Review Center — one item. A change request opens as a page that replaces the
6
+ * inbox in place: a status + title header, the branch/diff facts, and the live
7
+ * file diffs. Every other kind opens in `ReviewItemModal`, over the inbox, the
8
+ * way a connector approval does.
8
9
  *
9
10
  * Actions mutate parent state optimistically via the passed handlers.
10
11
  */
@@ -13,9 +14,16 @@ import { Button } from '../../primitives/button.js';
13
14
  import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from '../../primitives/item.js';
14
15
  import { Kbd } from '../../primitives/kbd.js';
15
16
  import Loading from '../../primitives/loading.js';
17
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalHeader, ModalTitle, } from '../../primitives/modal.js';
16
18
  import { DiffStat } from '../../primitives/status.js';
17
19
  import { infoToast, successToast } from '../../primitives/toast.js';
20
+ import { useProjectContext } from '../../files/project/context.js';
21
+ import { getFileIcon } from '../../files/project/components/file-icon.js';
18
22
  import { useChangeRequestDiff, useChangeRequestMergePreview, } from '../../files/project/hooks/use-change-requests.js';
23
+ import { ShowContentRenderer } from '../../files/renderers/show-content-renderer.js';
24
+ import { getShowFileCategory } from '../../files/renderers/show-type-utils.js';
25
+ import { SessionDriveFilesScope, sessionDriveMountPath, } from '../../internal/files/session-drive-files.js';
26
+ import { useFilePreviewStore } from '../../internal/stores/file-preview-store.js';
19
27
  import { cn } from '../../internal/lib/utils.js';
20
28
  import { ArrowLeftIcon as ArrowLeft, ArrowUpRightIcon as ArrowUpRight, CheckIcon as Check, CheckCircleIcon as CheckCircleSolid, EyeIcon as Eye, SparkleIcon as SparklesSolid, } from '@phosphor-icons/react';
21
29
  import { useEffect, useRef, useState } from 'react';
@@ -91,10 +99,38 @@ function ApprovalBody({ item, actions, }) {
91
99
  })() }));
92
100
  }
93
101
  // ── output ────────────────────────────────────────────────────────────────
102
+ /** File kinds an output draws inline. Everything else is a row that opens it. */
103
+ const INLINE_MEDIA = new Set(['image', 'video', 'audio']);
104
+ /** One file of an output: its label and name, and when it can be read, a
105
+ * button that opens it in the file preview. */
106
+ function OutputFileRow({ file, readable, }) {
107
+ const name = file.path.split('/').pop() || file.path;
108
+ const body = (_jsxs(_Fragment, { children: [getFileIcon(name, { className: 'text-muted-foreground size-4 shrink-0' }), _jsx("span", { className: "text-foreground truncate text-sm", children: file.note ?? name }), file.note ? (_jsx("span", { className: "text-muted-foreground truncate font-mono text-xs", children: name })) : null] }));
109
+ return (_jsx("li", { title: file.path, children: readable ? (_jsx("button", { type: "button", onClick: () => useFilePreviewStore.getState().openPreview(file.path), className: "hover:bg-hover duration-fast focus-visible:ring-ring flex w-full min-w-0 items-center gap-2.5 rounded-md px-2 py-1.5 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none", children: body })) : (_jsx("div", { className: "flex min-w-0 items-center gap-2.5 px-2 py-1.5", children: body })) }));
110
+ }
111
+ /**
112
+ * The agent's note, then what it made: the first image, video or sound drawn
113
+ * inline, its text, and every other file as a row. Nothing it made, no section.
114
+ *
115
+ * A `/drives/…` path reads through the item's session: its mounts name the
116
+ * drive behind each path (`SessionDriveFilesScope`), exactly as in the
117
+ * session. A workspace path needs a running box, which the inbox does not
118
+ * have, so it is listed and not opened.
119
+ */
94
120
  function OutputBody({ item }) {
95
121
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
122
+ const projectId = useProjectContext()?.projectId;
123
+ const sessionId = item.sessionId;
96
124
  const d = item.detail;
97
- return (_jsxs(_Fragment, { children: [_jsx(Panel, { children: _jsxs("div", { className: "text-foreground flex items-start gap-2 text-sm text-pretty", children: [_jsx(SparklesSolid, { weight: "fill", className: "text-kortix-purple mt-0.5 size-4 shrink-0" }), _jsx("span", { children: d.note })] }) }), _jsxs(Panel, { children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx(SectionLabel, { children: d.artifactLabel }), d.preview && (_jsx("div", { className: "text-muted-foreground text-sm text-pretty", children: d.preview }))] }), d.previewUrl && (_jsx(Button, { variant: "outline", size: "sm", className: "shrink-0 gap-1.5", asChild: true, children: _jsxs("a", { href: d.previewUrl, target: "_blank", rel: "noopener noreferrer", children: [tI18nComplete.raw('textf7afe3dde18c'), _jsx(ArrowUpRight, { className: "size-3.5" })] }) }))] }), d.files && d.files.length > 0 && (_jsx("div", { className: "mt-3 space-y-1", children: d.files.map((f) => (_jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "text-foreground truncate font-mono", children: f.path }), f.note && _jsxs("span", { className: "text-muted-foreground", children: ["\u2014 ", f.note] })] }, f.path))) }))] })] }));
125
+ const files = d.files ?? [];
126
+ const readable = (path) => !!projectId && !!sessionId && sessionDriveMountPath(path) !== null;
127
+ const media = files.find((f) => readable(f.path) && INLINE_MEDIA.has(getShowFileCategory(f.path)));
128
+ const rest = files.filter((f) => f !== media);
129
+ const video = !!media && getShowFileCategory(media.path) === 'video';
130
+ return (_jsxs(_Fragment, { children: [projectId && sessionId ? (_jsx(SessionDriveFilesScope, { projectId: projectId, sessionId: sessionId })) : null, d.note ? (_jsx("p", { className: "text-foreground text-sm whitespace-pre-wrap text-pretty", children: d.note })) : null, media ? (
131
+ // A video takes a 16:9 box: the inline card's fixed height bars a
132
+ // landscape cut top and bottom, worst on a phone.
133
+ _jsx("div", { className: cn('overflow-hidden rounded-md border', video && 'aspect-video'), children: _jsx(ShowContentRenderer, { type: "file", path: media.path, fill: video }) })) : null, d.preview ? (_jsxs("section", { children: [_jsx(SectionLabel, { children: tI18nComplete.raw('text526e0087cc3f') }), _jsx("p", { className: "text-foreground text-sm whitespace-pre-wrap text-pretty", children: d.preview })] })) : null, rest.length > 0 ? (_jsxs("section", { children: [_jsx(SectionLabel, { children: tI18nComplete.raw('textabc7e9892806') }), _jsx("ul", { className: "-mx-2 space-y-0.5", children: rest.map((f) => (_jsx(OutputFileRow, { file: f, readable: readable(f.path) }, f.path))) })] })) : null, d.previewUrl ? (_jsx(Button, { variant: "outline", size: "sm", className: "gap-1.5", asChild: true, children: _jsxs("a", { href: d.previewUrl, target: "_blank", rel: "noopener noreferrer", children: [tI18nComplete.raw('textf7afe3dde18c'), _jsx(ArrowUpRight, { className: "size-3.5 shrink-0" })] }) })) : null] }));
98
134
  }
99
135
  // ── decision ──────────────────────────────────────────────────────────────
100
136
  function DecisionBody({ item, actions, onClose, }) {
@@ -136,19 +172,22 @@ function FeedbackComposer({ onCancel, onSend, }) {
136
172
  /** The header's right-hand group: what you can do to this item right now. */
137
173
  function ActionBar({ item, actions, onBack, conflicts, checkingConflicts, composing, setComposing, }) {
138
174
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
175
+ // Decisions and native approvals decide inside their body, with their own session link.
176
+ if (item.kind === 'decision' || item.kind === 'approval') {
177
+ return item.status === 'needs_you' ? null : (_jsxs("span", { className: "text-muted-foreground text-xs", children: [reviewStatusLabel(item.status, tI18nComplete), " \u00B7 ", formatItemAgeLong(item.createdAt)] }));
178
+ }
179
+ // The session that produced this item is where its reasoning lives.
180
+ const openSession = item.sessionId && actions.openSession ? (_jsx(Button, { variant: "secondary", size: "sm", onClick: () => actions.openSession?.(item.sessionId), children: tI18nComplete.raw('textb205bb47f81a') })) : null;
139
181
  if (item.status !== 'needs_you') {
140
- return (_jsxs("span", { className: "text-muted-foreground text-xs", children: [reviewStatusLabel(item.status, tI18nComplete), " \u00B7 ", formatItemAgeLong(item.createdAt)] }));
182
+ return (_jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [_jsxs("span", { className: "text-muted-foreground text-xs", children: [reviewStatusLabel(item.status, tI18nComplete), " \u00B7 ", formatItemAgeLong(item.createdAt)] }), openSession] }));
141
183
  }
142
- // Decisions and native approvals decide inside their body.
143
- if (item.kind === 'decision' || item.kind === 'approval')
144
- return null;
145
184
  // change · output · batch. Each control shows only for a verdict the viewer
146
185
  // may give (KRTX-1720). Ship it on a change merges it; the conflict fix stands
147
186
  // in for Ship it, so it follows the same verdict.
148
187
  const secondaryLabel = item.secondaryAction;
149
188
  const hasConflicts = item.kind === 'change' && conflicts.length > 0;
150
189
  const showPrimary = actions.allows(item, 'approve');
151
- return (_jsxs("div", { className: "flex items-center gap-2", children: [secondaryLabel && !composing && actions.allows(item, 'changes') && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setComposing(true), children: secondaryLabel })), !showPrimary ? null : hasConflicts && item.kind === 'change' ? (_jsxs(Button, { size: "sm", disabled: actions.recoveringCrId === item.detail.crId, onClick: () => {
190
+ return (_jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [openSession, secondaryLabel && !composing && actions.allows(item, 'changes') && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setComposing(true), children: secondaryLabel })), !showPrimary ? null : hasConflicts && item.kind === 'change' ? (_jsxs(Button, { size: "sm", disabled: actions.recoveringCrId === item.detail.crId, onClick: () => {
152
191
  if (actions.recoverChange) {
153
192
  actions.recoverChange(item, conflicts);
154
193
  }
@@ -180,6 +219,28 @@ function ChangeFacts({ item }) {
180
219
  return null;
181
220
  return (_jsxs(_Fragment, { children: [hasRefs && (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Badge, { variant: "secondary", className: "border-0 align-middle font-mono ring-0", size: "sm", children: adv.baseRef || '—' }), _jsx(ArrowLeft, { className: "text-muted-foreground size-3.5 shrink-0", "aria-label": tI18nComplete.raw('text75857a458999') }), _jsx(Badge, { variant: "secondary", size: "sm", className: "line-clamp-1 max-w-96 truncate border-0 align-middle font-mono ring-0", children: _jsx("span", { className: "truncate", children: adv.headRef || '—' }) })] })), files > 0 && (_jsxs("span", { className: "tabular-nums", children: [files, " ", files === 1 ? 'file' : 'files'] })), _jsx(DiffStat, { additions: additions, deletions: deletions })] }));
182
221
  }
222
+ /** The plain-language body for the item's kind: the page's and the modal's. */
223
+ function KindBody({ item, actions, onClose, conflicts, }) {
224
+ switch (item.kind) {
225
+ case 'change':
226
+ return _jsx(ChangeBody, { item: item, actions: actions, onClose: onClose, conflicts: conflicts });
227
+ case 'approval':
228
+ return _jsx(ApprovalBody, { item: item, actions: actions });
229
+ case 'output':
230
+ return _jsx(OutputBody, { item: item });
231
+ case 'decision':
232
+ return _jsx(DecisionBody, { item: item, actions: actions, onClose: onClose });
233
+ case 'batch':
234
+ return _jsx(BatchBody, { item: item });
235
+ }
236
+ }
237
+ /** "Ask for changes" with an optional note, sent back to the agent. */
238
+ function ChangesComposer({ item, actions, onCancel, onSent, }) {
239
+ return (_jsx(FeedbackComposer, { onCancel: onCancel, onSend: (text) => {
240
+ actions.resolve(item.id, 'changes_requested', text ? `Sent to the agent: “${text}”` : `${item.secondaryAction} — sent to the agent`, text || undefined);
241
+ onSent();
242
+ } }));
243
+ }
183
244
  export function ReviewDetail({ item, actions, onBack, }) {
184
245
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
185
246
  const crId = item.kind === 'change' ? (item.detail.crId ?? null) : null;
@@ -203,8 +264,35 @@ export function ReviewDetail({ item, actions, onBack, }) {
203
264
  : reviewStatusLabel(item.status, tI18nComplete);
204
265
  const statusBadge = open ? 'success' : STATUS_META[item.status].badge;
205
266
  const secondaryLabel = item.secondaryAction;
206
- return (_jsxs("div", { className: "w-full p-4", children: [_jsxs("header", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "min-w-0 space-y-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: onBack, className: "text-muted-foreground hover:text-foreground -ml-2.5", children: [_jsx(ArrowLeft, { className: "size-3.5 shrink-0" }), tI18nComplete.raw('text76900f1bfd16')] }), _jsx(Badge, { variant: statusBadge, size: "sm", children: statusLabel }), item.kind !== 'change' && (_jsx(Badge, { variant: "outline", size: "sm", children: reviewKindLabel(item.kind, tI18nComplete) }))] }), _jsxs("div", { className: "mt-10 space-y-2", children: [_jsxs("p", { className: "text-muted-foreground text-xs", children: [item.project, number != null && _jsxs("span", { className: "tabular-nums", children: [" #", number] })] }), _jsx("h1", { className: "text-foreground line-clamp-2 truncate text-2xl font-semibold tracking-tight text-pretty", children: item.title })] }), _jsxs("div", { className: "text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1.5 text-sm", children: [_jsx("span", { children: item.agent }), item.kind === 'change' && _jsx(ChangeFacts, { item: item }), _jsx("span", { children: formatItemAgeLong(item.createdAt) })] })] }), _jsx("div", { className: "shrink-0", children: _jsx(ActionBar, { item: item, actions: actions, onBack: onBack, conflicts: conflicts, checkingConflicts: Boolean(crId) && mergePreview.isLoading, composing: composing, setComposing: setComposing }) })] }), _jsxs("div", { className: "mt-8 space-y-8", children: [composing && secondaryLabel && item.kind !== 'approval' && (_jsx(FeedbackComposer, { onCancel: () => setComposing(false), onSend: (text) => {
207
- actions.resolve(item.id, 'changes_requested', text ? `Sent to the agent: “${text}”` : `${secondaryLabel} — sent to the agent`, text || undefined);
208
- onBack();
209
- } })), _jsxs("section", { className: "space-y-3", children: [_jsx("h2", { className: "text-foreground text-sm font-medium", children: tI18nComplete.raw('text526e0087cc3f') }), _jsxs("div", { className: "space-y-4", children: [item.kind === 'change' && (_jsx(ChangeBody, { item: item, actions: actions, onClose: onBack, conflicts: conflicts })), item.kind === 'approval' && _jsx(ApprovalBody, { item: item, actions: actions }), item.kind === 'output' && _jsx(OutputBody, { item: item }), item.kind === 'decision' && (_jsx(DecisionBody, { item: item, actions: actions, onClose: onBack })), item.kind === 'batch' && _jsx(BatchBody, { item: item })] })] }), crId && _jsx(ChangeFiles, { crId: crId })] })] }));
267
+ return (_jsxs("div", { className: "w-full p-4", children: [_jsxs("header", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "min-w-0 space-y-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: onBack, className: "text-muted-foreground hover:text-foreground -ml-2.5", children: [_jsx(ArrowLeft, { className: "size-3.5 shrink-0" }), tI18nComplete.raw('text76900f1bfd16')] }), _jsx(Badge, { variant: statusBadge, size: "sm", children: statusLabel }), item.kind !== 'change' && (_jsx(Badge, { variant: "outline", size: "sm", children: reviewKindLabel(item.kind, tI18nComplete) }))] }), _jsxs("div", { className: "mt-10 space-y-2", children: [_jsxs("p", { className: "text-muted-foreground text-xs", children: [item.project, number != null && _jsxs("span", { className: "tabular-nums", children: [" #", number] })] }), _jsx("h1", { className: "text-foreground line-clamp-2 truncate text-2xl font-semibold tracking-tight text-pretty", children: item.title })] }), _jsxs("div", { className: "text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1.5 text-sm", children: [_jsx("span", { children: item.agent }), item.kind === 'change' && _jsx(ChangeFacts, { item: item }), _jsx("span", { children: formatItemAgeLong(item.createdAt) })] })] }), _jsx("div", { className: "shrink-0", children: _jsx(ActionBar, { item: item, actions: actions, onBack: onBack, conflicts: conflicts, checkingConflicts: Boolean(crId) && mergePreview.isLoading, composing: composing, setComposing: setComposing }) })] }), _jsxs("div", { className: "mt-8 space-y-8", children: [composing && secondaryLabel && item.kind !== 'approval' && (_jsx(ChangesComposer, { item: item, actions: actions, onCancel: () => setComposing(false), onSent: onBack })), _jsxs("section", { className: "space-y-3", children: [_jsx("h2", { className: "text-foreground text-sm font-medium", children: tI18nComplete.raw('text526e0087cc3f') }), _jsx("div", { className: "space-y-4", children: _jsx(KindBody, { item: item, actions: actions, onClose: onBack, conflicts: conflicts }) })] }), crId && _jsx(ChangeFiles, { crId: crId })] })] }));
268
+ }
269
+ /** The open item in its modal: who made it, its title, its body, its verdict. */
270
+ function ReviewItemDialog({ item, actions, onClose, }) {
271
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
272
+ const [composing, setComposing] = useState(false);
273
+ const kind = KIND_META[item.kind];
274
+ // A question and a native approval decide inside their body.
275
+ const decidesInBody = (item.kind === 'decision' || item.kind === 'approval') && item.status === 'needs_you';
276
+ return (_jsxs(_Fragment, { children: [_jsxs(ModalHeader, { className: "shrink-0 gap-3 pr-12 pb-4", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [_jsx("span", { className: cn('flex size-8 shrink-0 items-center justify-center rounded-sm', kind.tile), children: _jsx(kind.icon, { className: cn('size-4', kind.iconColor) }) }), _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("p", { className: "text-foreground truncate text-sm leading-5 font-medium", children: reviewKindLabel(item.kind, tI18nComplete) }), _jsxs(ModalDescription, { className: "truncate text-xs leading-4", children: [item.agent, " \u00B7 ", formatItemAgeLong(item.createdAt)] })] })] }), _jsx(ModalTitle, { className: "text-xl leading-snug wrap-anywhere", children: item.title })] }), _jsx(ModalBody, { className: "min-h-0 space-y-5 overflow-y-auto pb-5", children: _jsx(KindBody, { item: item, actions: actions, onClose: onClose, conflicts: [] }) }), decidesInBody ? null : (_jsx("div", { className: "border-border flex shrink-0 justify-end border-t px-5 pt-4 pb-5", children: composing && item.secondaryAction ? (_jsx("div", { className: "w-full", children: _jsx(ChangesComposer, { item: item, actions: actions, onCancel: () => setComposing(false), onSent: onClose }) })) : (_jsx(ActionBar, { item: item, actions: actions, onBack: onClose, conflicts: [], checkingConflicts: false, composing: composing, setComposing: setComposing })) }))] }));
277
+ }
278
+ /**
279
+ * Every review item but a change request opens here, over the inbox, the way a
280
+ * connector approval does (`ApprovalDecisionModal`). A change keeps its page:
281
+ * its diff needs the width. Null closes the modal.
282
+ */
283
+ export function ReviewItemModal({ item, actions, onClose, }) {
284
+ // The last item stays drawn while the modal fades out.
285
+ const [shown, setShown] = useState(item);
286
+ if (item && item !== shown)
287
+ setShown(item);
288
+ return (_jsx(Modal, { open: item !== null, onOpenChange: (open) => !open && onClose(), children: _jsx(ModalContent
289
+ // Focus the dialog, not its first control: a file row or the video
290
+ // would open with a focus ring nobody asked for.
291
+ , {
292
+ // Focus the dialog, not its first control: a file row or the video
293
+ // would open with a focus ring nobody asked for.
294
+ onOpenAutoFocus: (event) => {
295
+ event.preventDefault();
296
+ event.currentTarget?.focus();
297
+ }, className: "flex flex-col space-y-0 overflow-hidden lg:h-auto lg:max-h-[85svh] lg:max-w-2xl", children: shown ? (_jsx(ReviewItemDialog, { item: shown, actions: actions, onClose: onClose }, shown.id)) : null }) }));
210
298
  }
@@ -5,7 +5,7 @@ export declare function SavedSessionSkeleton({ projectId, sessionId, stage, stat
5
5
  /** The route's session id. */
6
6
  sessionId: string;
7
7
  stage: SessionStartStage;
8
- /** Drawn in place of the skeleton rows: there is no saved conversation to
9
- * stand in for, only the wake's status. */
8
+ /** The wake's status, centered above the skeleton rows. It may render
9
+ * nothing (a routine wake); the rows show either way. */
10
10
  status?: ReactNode;
11
11
  }): import("react").JSX.Element;
@@ -16,8 +16,8 @@ import { useMemo } from 'react';
16
16
  * answers in one round trip; the computer takes 5-240 s to wake. So a session
17
17
  * that has a saved copy opens on this — its header, skeleton turns, and the
18
18
  * composer's outline — and the conversation replaces it in one step. A session
19
- * with nothing to read (`resolveResumeOverlay`) gets the same frame with a
20
- * `status` in place of the rows.
19
+ * with nothing to read (`resolveResumeOverlay`) gets the same frame and rows,
20
+ * with the wake's `status` centered above them.
21
21
  *
22
22
  * Built from the geometry the real chat uses (`SessionLayout`, `SessionBodyRow`,
23
23
  * `SESSION_TRANSCRIPT_CLASS`, `COMPOSER_SHELL_CLASS`), so the crossfade into
@@ -40,5 +40,5 @@ const APPEAR_AFTER_A_MOMENT = 'animate-in fade-in fill-mode-both duration-normal
40
40
  export function SavedSessionSkeleton({ projectId, sessionId, stage, status, }) {
41
41
  const t = useTranslations('sessionPage');
42
42
  const shape = useMemo(() => savedSessionSkeletonShape(sessionId), [sessionId]);
43
- return (_jsx(SessionLayout, { sessionId: sessionId, projectId: projectId, projectSessionId: sessionId, transient: true, bootStage: stage === 'ready' ? null : stage, children: _jsxs("div", { className: "bg-background relative flex h-full flex-col", children: [_jsx(SessionSiteHeader, { sessionId: sessionId, sessionTitle: "" }), _jsxs(SessionBodyRow, { transient: true, children: [_jsx("div", { className: "relative z-10 min-h-0 flex-1 overflow-hidden", children: status ?? (_jsx("div", { role: "status", "aria-busy": "true", "aria-label": t('loadingConversation'), "data-testid": "saved-session-skeleton", className: cn(SESSION_TRANSCRIPT_CLASS, APPEAR_AFTER_A_MOMENT), children: _jsx(SavedSessionSkeletonRows, { shape: shape }) })) }), _jsx("div", { "aria-hidden": true, className: cn(COMPOSER_SHELL_CLASS, 'pb-8', APPEAR_AFTER_A_MOMENT), children: _jsx(SkeletonBar, { phase: shape.composerPhase, phases: shape.phases, className: "h-28 w-full rounded-xl" }) })] })] }) }));
43
+ return (_jsx(SessionLayout, { sessionId: sessionId, projectId: projectId, projectSessionId: sessionId, transient: true, bootStage: stage === 'ready' ? null : stage, children: _jsxs("div", { className: "bg-background relative flex h-full flex-col", children: [_jsx(SessionSiteHeader, { sessionId: sessionId, sessionTitle: "" }), _jsxs(SessionBodyRow, { transient: true, children: [_jsxs("div", { className: "relative z-10 min-h-0 flex-1 overflow-hidden", children: [_jsx("div", { role: "status", "aria-busy": "true", "aria-label": t('loadingConversation'), "data-testid": "saved-session-skeleton", className: cn(SESSION_TRANSCRIPT_CLASS, APPEAR_AFTER_A_MOMENT), children: _jsx(SavedSessionSkeletonRows, { shape: shape }) }), status ? (_jsx("div", { className: "absolute inset-0 flex items-center justify-center px-4", children: _jsx("div", { className: "bg-background border-border rounded-xl border py-4 empty:hidden", children: status }) })) : null] }), _jsx("div", { "aria-hidden": true, className: cn(COMPOSER_SHELL_CLASS, 'pb-8', APPEAR_AFTER_A_MOMENT), children: _jsx(SkeletonBar, { phase: shape.composerPhase, phases: shape.phases, className: "h-28 w-full rounded-xl" }) })] })] }) }));
44
44
  }