@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
@@ -140,7 +140,7 @@ export function dedentCommand(raw) {
140
140
  * The exit-code strip keeps its shorter 8px vertical inset: it is metadata
141
141
  * about the card, not a third pane of content.
142
142
  */
143
- function CommandBlock({ command, output, richOutput, exitCode, recovered = false, settled, }) {
143
+ function CommandBlock({ command, output, richOutput, exitCode, settled, }) {
144
144
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
145
145
  const hasOutput = Boolean(richOutput || output);
146
146
  const failed = typeof exitCode === 'number' && exitCode !== 0;
@@ -159,9 +159,10 @@ function CommandBlock({ command, output, richOutput, exitCode, recovered = false
159
159
  // `overflow-hidden` clips the command pane's tint to the rounded frame;
160
160
  // without it the wash pokes square corners past `rounded-md`.
161
161
  _jsxs("div", { className: cn('relative overflow-hidden', frame), children: [_jsx("div", { "data-scrollable": true, className: cn('max-h-64 overflow-auto', frame && 'bg-muted/40'), children: _jsx("pre", { className: cn('text-foreground font-mono text-xs leading-relaxed wrap-break-word whitespace-pre-wrap [&_code]:border-none [&_code]:bg-transparent [&_code]:p-0 [&_code]:text-xs [&_code]:leading-relaxed [&_code]:whitespace-pre-wrap [&_pre]:whitespace-pre-wrap [&_span]:border-none [&_span]:outline-none', paneInset, 'pr-11'), children: _jsx(HighlightedCode, { code: command, language: "bash", children: command }) }) }), _jsx("div", { className: "absolute top-2 right-2", children: _jsx(CopyButton, { code: command, className: "text-muted-foreground hover:text-foreground" }) }), (hasOutput || settled) && (_jsx("div", { className: "border-border/60 border-t", children: richOutput ? (richOutput) : output ? (_jsxs("div", { className: "relative", children: [_jsx("div", { "data-scrollable": true, className: "max-h-80 overflow-auto", children: _jsx("div", { className: cn('text-muted-foreground font-mono text-xs leading-relaxed wrap-break-word whitespace-pre-wrap', paneInset, 'pr-11'), children: output }) }), _jsx("div", { className: "absolute top-2 right-2", children: _jsx(CopyButton, { code: output, className: "text-muted-foreground hover:text-foreground" }) })] })) : (_jsx("p", { className: cn('text-muted-foreground', paneInset, 'text-xs leading-relaxed'), children: tI18nComplete.raw('textf7e31759b202') })) })), failed && (_jsxs("div", { className: cn(
162
- // `kortix-red`, matching the trigger's "Command failed": the strip
163
- // is the card's own copy of the verdict, so the two agree in tone.
164
- 'border-border/60 border-t py-2 font-mono text-xs tabular-nums', recovered ? 'text-muted-foreground' : 'text-kortix-red',
162
+ // Muted ink, like the trigger's "Command failed": a failed command
163
+ // is ordinary agent work (it reads the error and tries again), so
164
+ // the words carry the verdict and no color raises an alarm.
165
+ 'border-border/60 border-t py-2 font-mono text-xs tabular-nums text-muted-foreground',
165
166
  // Metadata about the card, not a third pane: it keeps the shorter
166
167
  // 8px vertical inset, and only the horizontal one is the surface's
167
168
  // to supply.
@@ -198,7 +199,7 @@ function BashTrigger({ title, failed, command, commandPreview, extraLines, live,
198
199
  }
199
200
  return (_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden", children: _jsxs("span", { className: "flex min-w-0 shrink-0 items-center gap-2 text-xs",
200
201
  // Redundant once the card spells the command out below.
201
- title: open ? undefined : command, children: [_jsx("span", { className: cn('min-w-0 truncate', failed ? 'text-kortix-red' : 'text-foreground'), children: title }), !open && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-muted-foreground min-w-0 truncate font-mono", children: commandPreview }), extraLines > 0 && (_jsxs("span", { className: "text-muted-foreground shrink-0 tabular-nums", children: ["+", extraLines] }))] }))] }) }));
202
+ title: open ? undefined : command, children: [_jsx("span", { className: "min-w-0 truncate text-foreground", children: title }), !open && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-muted-foreground min-w-0 truncate font-mono", children: commandPreview }), extraLines > 0 && (_jsxs("span", { className: "text-muted-foreground shrink-0 tabular-nums", children: ["+", extraLines] }))] }))] }) }));
202
203
  }
203
204
  export function BashTool({ call, defaultOpen, forceOpen, locked }) {
204
205
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
@@ -278,6 +279,6 @@ export function BashTool({ call, defaultOpen, forceOpen, locked }) {
278
279
  // `CommandBlock` is a bordered card like the shared three, so it takes
279
280
  // the same gate: the seam belongs to the inline row it hangs under, not
280
281
  // to the panel body that already supplies `px-3 py-3`.
281
- _jsx("div", { className: cn(indent && 'mt-1.5', indent), children: _jsx(CommandBlock, { command: command, output: plainOutput, richOutput: richOutput, exitCode: exitCode, recovered: recovered, settled: status === 'completed' || status === 'error' }) }))] }));
282
+ _jsx("div", { className: cn(indent && 'mt-1.5', indent), children: _jsx(CommandBlock, { command: command, output: plainOutput, richOutput: richOutput, exitCode: exitCode, settled: status === 'completed' || status === 'error' }) }))] }));
282
283
  }
283
284
  ToolRegistry.register('bash', BashTool);
@@ -1,8 +1,7 @@
1
- import { type ChannelPlatform } from '../../turn/channel-message.js';
2
1
  import { useTranslations } from '../../../i18n/index.js';
3
2
  import { type ChannelSend } from './channel-send.js';
4
3
  /** "Replied in Microsoft Teams" — the row title for a channel send. */
5
- export declare function channelSendTitle(platform: ChannelPlatform, tI18nComplete: ReturnType<typeof useTranslations>): string;
4
+ export declare function channelSendTitle(platform: ChannelSend['platform'], tI18nComplete: ReturnType<typeof useTranslations>): string;
6
5
  /**
7
6
  * The reply as the person in the channel saw it: a left-anchored card with the
8
7
  * platform badge, the text as the channel shows it, and the attachment name
@@ -13,7 +13,8 @@
13
13
  */
14
14
  import type { ChannelPlatform } from '../../turn/channel-message.js';
15
15
  export interface ChannelSend {
16
- platform: ChannelPlatform;
16
+ /** A sandbox channel CLI: there is none for email. */
17
+ platform: Exclude<ChannelPlatform, 'Email'>;
17
18
  /** The message text, or null for a bare file send. */
18
19
  text: string | null;
19
20
  /** Basename of a `--file` attachment, when one was sent. */
@@ -68,7 +68,7 @@ function CallMark({ status }) {
68
68
  if (status === 'ok')
69
69
  return _jsx(CheckIcon, { className: "text-kortix-green size-3 shrink-0" });
70
70
  if (status === 'error')
71
- return _jsx(WarningIcon, { weight: "fill", className: "text-kortix-red size-3 shrink-0" });
71
+ return _jsx(WarningIcon, { weight: "fill", className: "text-muted-foreground size-3 shrink-0" });
72
72
  if (status === 'refused')
73
73
  return _jsx(ProhibitIcon, { weight: "fill", className: "text-kortix-orange size-3 shrink-0" });
74
74
  return _jsx(MinusIcon, { className: "text-muted-foreground size-3 shrink-0" });
@@ -122,7 +122,7 @@ export function ConnectorCallTool({ call, defaultOpen, forceOpen, locked }) {
122
122
  ...(parsed?.risk ? [String(parsed.risk)] : []),
123
123
  ...(outcome ? [outcome.label] : []),
124
124
  ].filter(Boolean),
125
- }, defaultOpen: defaultOpen, forceOpen: forceOpen, locked: locked, children: _jsxs(_Fragment, { children: [_jsxs(ToolResultCard, { bodyClassName: "space-y-2.5 p-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "text-foreground font-mono", children: ref }), _jsx(ConnectorRiskBadge, { risk: parsed?.risk }), outcome && (_jsx("span", { className: cn('ml-auto text-[10px] font-semibold uppercase', outcome.tint), children: outcome.label }))] }), Object.keys(args).length > 0 && (_jsx(FoldedSection, { label: tI18nComplete.raw('text59f03d642b41'), children: _jsx(ConnectorJson, { value: args }) })), !outputIsError && parsed ? (_jsx(ToolSection, { label: tI18nComplete.raw('text9061383b8e22'), children: parsed.reason && !ok ? (_jsx("p", { className: "text-destructive font-mono text-xs", children: String(parsed.reason) })) : (_jsx(ConnectorJson, { value: 'data' in parsed ? parsed.data : parsed })) })) : output ? null : (_jsx(ToolEmptyState, { message: isStreaming
125
+ }, defaultOpen: defaultOpen, forceOpen: forceOpen, locked: locked, children: _jsxs(_Fragment, { children: [_jsxs(ToolResultCard, { bodyClassName: "space-y-2.5 p-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "text-foreground font-mono", children: ref }), _jsx(ConnectorRiskBadge, { risk: parsed?.risk }), outcome && (_jsx("span", { className: cn('ml-auto text-[10px] font-semibold uppercase', outcome.tint), children: outcome.label }))] }), Object.keys(args).length > 0 && (_jsx(FoldedSection, { label: tI18nComplete.raw('text59f03d642b41'), children: _jsx(ConnectorJson, { value: args }) })), !outputIsError && parsed ? (_jsx(ToolSection, { label: tI18nComplete.raw('text9061383b8e22'), children: parsed.reason && !ok ? (_jsx("p", { className: "text-muted-foreground font-mono text-xs", children: String(parsed.reason) })) : (_jsx(ConnectorJson, { value: 'data' in parsed ? parsed.data : parsed })) })) : output ? null : (_jsx(ToolEmptyState, { message: isStreaming
126
126
  ? tI18nComplete.raw('text46c541363b02')
127
127
  : tI18nComplete.raw('text752edcfbfb98') }))] }), (outputIsError || (!parsed && output)) && (_jsx(ToolOutputFallback, { output: output, isStreaming: isStreaming, toolName: "call" }))] }) }));
128
128
  }
@@ -1,2 +1,2 @@
1
1
  import type { ToolProps } from '../shared/types.js';
2
- export declare function ImageGenTool({ call, defaultOpen, forceOpen, locked }: ToolProps): import("react").JSX.Element;
2
+ export declare function ImageGenTool({ call }: ToolProps): import("react").JSX.Element;
@@ -1,61 +1,248 @@
1
1
  'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { SessionDotMatrix } from '../../../primitives/dot-matrix/session-dot-matrix.js';
3
4
  import { TextShimmer } from '../../../primitives/text-shimmer.js';
4
- import { useFileContent } from '../../../files/runtime/hooks/use-file-content.js';
5
- import { parseImageOutput } from '../../media/image-output-path.js';
6
- import { BasicTool, isLocalSandboxFilePath, partInput, partOutput, ToolOutputFallback, } from '../shared/infrastructure.js';
5
+ import { useSharedImage } from '../../../files/runtime/hooks/use-shared-image.js';
6
+ import { useFilePreviewStore } from '../../../internal/stores/file-preview-store.js';
7
+ import { ImageFrame, ImageUnavailable } from '../../../files/renderers/image-frame.js';
8
+ import { Button } from '../../../primitives/button.js';
9
+ import { ChatGptConnectionSlot } from '../../models/chatgpt-connection-button.js';
10
+ import { useModelConnectionGate } from '../../models/use-model-connection-gate.js';
11
+ import { sessionPersonalUser } from '../../overrides/provider-pool-draft.js';
12
+ import { useSessionIds } from '../../../providers/session-ids.js';
13
+ import { useUiViewerId } from '../../../providers/ui-provider.js';
14
+ import { ImageGenRunsContext, InTranscriptTurnContext, isLocalSandboxFilePath, ReadOnlySessionContext, TurnLiveContext, useToolNavigation, } from '../shared/infrastructure.js';
7
15
  import { ToolRegistry } from '../shared/registry.js';
8
- import { ToolResultCard } from '../shared/result-card.js';
9
- import { isSandboxNotReadyError } from '@kortix/sdk';
10
- import { ImageIcon } from '@phosphor-icons/react';
11
- import { useTranslations } from '../../../i18n/index.js';
12
- import { useEffect, useMemo, useState } from 'react';
13
- const TITLE_BY_ACTION = {
14
- generate: 'Generate Image',
15
- edit: 'Edit Image',
16
- upscale: 'Upscale Image',
17
- remove_bg: 'Remove Background',
18
- };
19
- export function ImageGenTool({ call, defaultOpen, forceOpen, locked }) {
20
- const tHardcodedUi = useTranslations('hardcodedUi');
21
- const input = partInput(call);
22
- const output = partOutput(call);
23
- const prompt = input.prompt;
24
- const action = input.action;
25
- const { imagePath, directUrl } = useMemo(() => parseImageOutput(output), [output]);
26
- const isLocalPath = imagePath ? isLocalSandboxFilePath(imagePath) : false;
27
- const fileContentPath = useMemo(() => {
28
- if (!isLocalPath || !imagePath || directUrl)
29
- return null;
30
- return imagePath.replace(/^\/workspace\//, '');
31
- }, [isLocalPath, imagePath, directUrl]);
32
- const { data: fileContentData, isLoading: isQueryLoading, error: fileContentError, } = useFileContent(fileContentPath, {
33
- enabled: !!fileContentPath,
34
- });
35
- // A readiness 503 (parked/booting sandbox) counts as loading: useFileContent
36
- // keeps polling while it lasts, so the image resolves once the box is up.
37
- const isImageLoading = isQueryLoading || isSandboxNotReadyError(fileContentError);
38
- const [imageUrl, setImageUrl] = useState(null);
16
+ import { useKortixComputerStore } from '../../../internal/stores/kortix-computer-store.js';
17
+ import { cn } from '../../../lib/utils.js';
18
+ import { useLocale, useTranslations } from '../../../i18n/index.js';
19
+ import { formatImageGenElapsed, imageGenGrid, imageGenRetryDelay, imageGenView, sessionLogOpenCall, } from '@kortix/sdk';
20
+ import { useProjectSession } from '@kortix/sdk/react';
21
+ import { ArrowsOutSimpleIcon } from '@phosphor-icons/react';
22
+ import { useContext, useEffect, useMemo, useState } from 'react';
23
+ /** The one busy signal over the flat frame. Elapsed time counts from the call's start, so a reload keeps it. */
24
+ function BusyLabel({ seed, label, startedAt }) {
25
+ const [mountedAt] = useState(() => Date.now());
26
+ const [now, setNow] = useState(() => Date.now());
27
+ const timed = startedAt !== undefined;
39
28
  useEffect(() => {
40
- if (!(fileContentData?.encoding === 'base64' && fileContentData?.content)) {
41
- setImageUrl(null);
29
+ if (!timed)
42
30
  return;
31
+ const id = setInterval(() => setNow(Date.now()), 1000);
32
+ return () => clearInterval(id);
33
+ }, [timed]);
34
+ return (_jsxs("span", { className: "text-muted-foreground flex flex-wrap items-center justify-center gap-2 text-xs", children: [_jsx(SessionDotMatrix, { sessionId: seed, size: 14, className: "shrink-0" }), _jsx(TextShimmer, { duration: 1, spread: 2, className: "text-xs", children: label }), timed ? _jsx("span", { className: "tabular-nums", children: formatImageGenElapsed(now - (startedAt ?? mountedAt)) }) : null] }));
35
+ }
36
+ /** "Try again in 2 hours." in the viewer's language. */
37
+ function useRetryLine(seconds) {
38
+ const t = useTranslations('imageGen');
39
+ const locale = useLocale();
40
+ if (seconds === undefined)
41
+ return null;
42
+ const { value, unit } = imageGenRetryDelay(seconds);
43
+ // The Serbian catalog is Latin; Intl's `sr` is Cyrillic.
44
+ const when = new Intl.RelativeTimeFormat(locale === 'sr' ? 'sr-Latn' : locale, { numeric: 'always' }).format(value, unit);
45
+ return t('retry', { when });
46
+ }
47
+ /** Stable empty list, as `ModelConnectionBar` passes: the card needs only the routing. */
48
+ const NO_MODELS = [];
49
+ /**
50
+ * Opens the project's model settings on Providers: the model picker's connect
51
+ * action (`useModelConnectionGate`). Shown only to a viewer who can change the
52
+ * project's models (`project.model.write`), in a session private to them;
53
+ * hidden outside a project or without the host's provider modal.
54
+ */
55
+ function ConnectModelAction() {
56
+ const t = useTranslations('sessionUi.modelGate');
57
+ const { canConnectProvider, canWriteProviders, openConnectProvider, modal } = useModelConnectionGate(NO_MODELS);
58
+ const { projectId, sessionId } = useSessionIds();
59
+ const viewerId = useUiViewerId();
60
+ const session = useProjectSession(projectId ?? '', sessionId ?? '', { enabled: !!projectId && !!sessionId });
61
+ const ownSession = !!viewerId && sessionPersonalUser(session.data) === viewerId;
62
+ if (!canConnectProvider || !canWriteProviders || !ownSession)
63
+ return null;
64
+ return (_jsxs(_Fragment, { children: [modal, _jsx(Button, { size: "sm", className: "mt-1 active:scale-[0.96]", onClick: () => openConnectProvider('providers'), children: t('connectModel') })] }));
65
+ }
66
+ /**
67
+ * The fix for a failure a connection can repair, as the session error banner
68
+ * routes it: the member's own ChatGPT login (`ChatGptConnectionSlot`, which
69
+ * applies `chatGptActionApplies`) when ChatGPT (`openai-codex`) is the provider
70
+ * that failed with `provider_not_connected` or `provider_reauth_required`; the
71
+ * project's model settings for any other provider and for
72
+ * `image_model_unavailable` (R37). None in a read-only view.
73
+ */
74
+ function ConnectAction({ code, provider }) {
75
+ const readOnly = useContext(ReadOnlySessionContext);
76
+ if (readOnly)
77
+ return null;
78
+ if (provider === 'openai-codex' && code === 'provider_not_connected')
79
+ return _jsx(ChatGptConnectionSlot, { action: "connect", className: "mt-1" });
80
+ if (provider === 'openai-codex' && code === 'provider_reauth_required')
81
+ return _jsx(ChatGptConnectionSlot, { action: "reconnect", className: "mt-1" });
82
+ return _jsx(ConnectModelAction, {});
83
+ }
84
+ /** A failure in a quiet plate: the message, the suggestion, the retry wait and `action`. No error reads "Stopped". */
85
+ function FailureNote({ error, action, fill = false }) {
86
+ const t = useTranslations('imageGen');
87
+ const retryLine = useRetryLine(error?.retryAfterSeconds);
88
+ return (_jsx("div", { className: cn('bg-muted flex flex-col items-start gap-1 rounded-md px-3 py-2.5 text-xs',
89
+ // In a tile: the slot's box, scrolling a long message inside it.
90
+ fill && 'h-full overflow-y-auto'), children: error ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-foreground", children: error.message || t('failed') }), error.suggestion ? _jsx("span", { className: "text-muted-foreground", children: error.suggestion }) : null, retryLine ? _jsx("span", { className: "text-muted-foreground", children: retryLine }) : null, action] })) : (_jsx("span", { className: "text-muted-foreground", children: t('stopped') })) }));
91
+ }
92
+ /**
93
+ * One image, from its generating frame to the file. `busy` is what the frame
94
+ * shows while it generates (the busy line, or the glyph alone in a tile); a
95
+ * frame whose file is still on the way says "Loading image". `fill`: a tile
96
+ * of the bento, which fills its slot and crops the image (`object-cover`).
97
+ * The frame shows no prompt and no toolbar: the whole frame opens the image
98
+ * full screen, uncropped, with its prompt and `model` under it.
99
+ */
100
+ function ImageGenFrame({ image, seed, busy, model, fill, }) {
101
+ const t = useTranslations('imageGen');
102
+ const { enabled: navigationEnabled } = useToolNavigation();
103
+ const filePath = image.imagePath && isLocalSandboxFilePath(image.imagePath) ? image.imagePath : null;
104
+ // The page's shared image store: the viewer and a `show` of the same bytes draw this URL too (R38).
105
+ // A sandbox still starting (a waking 503, a runtime URL not pinned yet) is a
106
+ // wait, not a failure: the store reports it as loading and the read keeps
107
+ // polling, so the image lands once the box is up.
108
+ const { url: blobUrl, error: blobError, retry, naturalRatio, onNaturalSize } = useSharedImage(filePath, image.sha256);
109
+ if (image.phase === 'failed' || image.phase === 'stopped')
110
+ return _jsx(FailureNote, { error: image.error, fill: fill });
111
+ if (image.imagePath && !filePath && !image.directUrl) {
112
+ // A path the file API cannot read: name it, as the old card did, instead of loading forever.
113
+ return (_jsx("div", { className: cn('bg-muted text-muted-foreground rounded-md px-3 py-2.5 font-mono text-xs break-all', fill && 'h-full overflow-y-auto'), children: image.imagePath }));
114
+ }
115
+ const generating = image.phase === 'generating';
116
+ const src = generating ? null : (image.directUrl ?? blobUrl);
117
+ const caption = image.prompt
118
+ ? { text: image.prompt, model, ...(image.sha256 && { sha256: image.sha256 }) }
119
+ : undefined;
120
+ const openFullScreen = filePath && navigationEnabled
121
+ ? () => {
122
+ useFilePreviewStore.getState().openPreview(filePath, undefined, caption);
123
+ // Expand after the open, as the file actions' Full screen does: the
124
+ // detail's own open resets the split, and `isExpanded` outranks it.
125
+ useKortixComputerStore.getState().setIsExpanded(true);
43
126
  }
44
- const binary = atob(fileContentData.content);
45
- const bytes = new Uint8Array(binary.length);
46
- for (let i = 0; i < binary.length; i++)
47
- bytes[i] = binary.charCodeAt(i);
48
- const blob = new Blob([bytes], {
49
- type: fileContentData.mimeType || 'image/webp',
50
- });
51
- const url = URL.createObjectURL(blob);
52
- setImageUrl(url);
53
- return () => URL.revokeObjectURL(url);
54
- }, [fileContentData]);
55
- const displayImageSrc = directUrl || imageUrl || '';
56
- return (_jsx(BasicTool, { icon: _jsx(ImageIcon, { className: "size-3.5 shrink-0" }), trigger: {
57
- title: TITLE_BY_ACTION[action ?? ''] || tHardcodedUi.raw('i18nComplete.text0753bd774f1b'),
58
- subtitle: prompt?.slice(0, 60),
59
- }, defaultOpen: defaultOpen, forceOpen: forceOpen, locked: locked, children: imagePath || directUrl ? (_jsx(ToolResultCard, { bodyClassName: "p-1", children: displayImageSrc ? (_jsx("img", { src: displayImageSrc, alt: String(prompt || tHardcodedUi.raw('i18nComplete.textdf37e04fda71')), className: "max-h-64 rounded-sm object-contain" })) : isImageLoading ? (_jsx("div", { className: "px-2 py-1.5 text-xs", children: _jsx(TextShimmer, { duration: 1, spread: 2, className: "text-xs", children: tHardcodedUi.raw('componentsSessionToolRenderers.line4414JsxTextLoadingImagePreview') }) })) : (_jsx("div", { className: "text-muted-foreground px-2 py-1.5 font-mono text-xs break-all", children: imagePath })) })) : output ? (_jsx(ToolOutputFallback, { output: output, toolName: "image_gen" })) : null }));
127
+ : undefined;
128
+ return (_jsxs("div", { className: cn('group relative', fill && 'h-full'), children: [_jsx(ImageFrame, { aspectRatio: image.aspectRatio, fill: fill, maxHeight: fill ? undefined : IMAGE_MAX_HEIGHT, openLabel: image.prompt ? t('openFullScreenPrompt', { prompt: image.prompt }) : t('openFullScreen'), src: src, alt: image.prompt || t('generating'), pending: generating || (!src && !blobError), label: generating ? (busy) : blobError ? (_jsx(ImageUnavailable, { onRetry: retry })) : !src ? (_jsx(BusyLabel, { seed: seed, label: t('loading') })) : null, onOpen: openFullScreen, naturalRatio: naturalRatio, onNaturalSize: onNaturalSize }), src && openFullScreen ? (
129
+ // The one hint that the image opens full screen, on hover only; the whole frame is the button.
130
+ _jsx("span", { "data-image-gen-expand": "", "aria-hidden": "true", className: "bg-popover text-foreground pointer-events-none absolute top-1.5 right-1.5 flex size-6 items-center justify-center rounded-md opacity-0 shadow-xs transition-opacity duration-fast group-focus-within:opacity-100 group-hover:opacity-100", children: _jsx(ArrowsOutSimpleIcon, { className: "size-3.5" }) })) : null] }));
131
+ }
132
+ /**
133
+ * The tallest a lone image or the bento may be (R33). The box narrows to
134
+ * keep its ratio, so it never crops more and never letterboxes.
135
+ */
136
+ const IMAGE_MAX_HEIGHT = '60vh';
137
+ /** `'3 / 2'` → `1.5`; anything unreadable → `1`. */
138
+ function ratioValue(ratio) {
139
+ const [w, h] = ratio.split('/').map((part) => Number(part.trim()));
140
+ return w && h ? w / h : 1;
141
+ }
142
+ /**
143
+ * The bento: several images fill one rectangle, the width of the message up
144
+ * to `IMAGE_MAX_HEIGHT` tall, its ratio fixed from the requested one, so
145
+ * nothing moves when they land.
146
+ * Tile i keeps slot i. Every tile has the requested ratio `r`:
147
+ * - 2: side by side, one row → the rectangle is `2r`;
148
+ * - 3: tile 0 takes 2/3 of the width and both rows, tiles 1 and 2 stack on
149
+ * the right third → `1.5r`;
150
+ * - 4: 2×2 → `r`.
151
+ */
152
+ const BENTO = {
153
+ // Explicit rows: each is minmax(0, 1fr), so a loaded image never stretches one.
154
+ 2: { grid: 'grid-cols-2 grid-rows-1', scale: 2 },
155
+ 3: { grid: 'grid-cols-3 grid-rows-2', scale: 1.5, first: 'col-span-2 row-span-2' },
156
+ 4: { grid: 'grid-cols-2 grid-rows-2', scale: 1 },
157
+ };
158
+ /** `min(100%, …)`: the widest a rectangle of ratio `rect` may be under the height cap. */
159
+ const cappedWidth = (rect) => `min(100%, calc(${IMAGE_MAX_HEIGHT} * ${rect}))`;
160
+ /**
161
+ * Five or more images (R38): ONE grid of six columns whose rows are the
162
+ * bento patterns (`imageGenGrid().rows`: 5 = 3+2, 8 = 4+4, …). Every tile sits
163
+ * in the same grid, placed by line numbers, so a tile is never re-parented.
164
+ *
165
+ * The grid is as wide as its tallest row allows under the cap (`width`), and
166
+ * each row is exactly `width / rects[k]` tall (`rects[k]` = its tile ratio ×
167
+ * the pattern's scale), so no row passes `IMAGE_MAX_HEIGHT`. Track heights are
168
+ * lengths, read from the figure's inline size (`cqw`): the grid is the sum of
169
+ * its rows and the gaps between them, with no aspect ratio of its own. (Flex
170
+ * rows under an aspect ratio left an empty band whenever their `fr` factors
171
+ * summed below 1, e.g. 16:9 tiles.) A two-track row subtracts the gap between
172
+ * its tracks, so a large tile spanning both is the row's height.
173
+ */
174
+ function gridPlacement(rows, rects) {
175
+ const width = `min(100cqw, ${IMAGE_MAX_HEIGHT} * ${Math.min(...rects)})`;
176
+ const tracks = [];
177
+ const places = [];
178
+ rows.forEach((count, row) => {
179
+ const track = tracks.length + 1;
180
+ const height = `${width} / ${rects[row]}`;
181
+ if (count === 2)
182
+ tracks.push(`calc(${height})`);
183
+ else
184
+ tracks.push(`calc((${height} - var(--spacing)) / 2)`, `calc((${height} - var(--spacing)) / 2)`);
185
+ for (let i = 0; i < count; i++) {
186
+ if (count === 2)
187
+ places.push({ gridColumn: `${1 + 3 * i} / span 3`, gridRow: `${track}` });
188
+ else if (count === 4)
189
+ places.push({ gridColumn: `${1 + 3 * (i % 2)} / span 3`, gridRow: `${track + Math.floor(i / 2)}` });
190
+ else if (i === 0)
191
+ places.push({ gridColumn: '1 / span 4', gridRow: `${track} / span 2` });
192
+ else
193
+ places.push({ gridColumn: '5 / span 2', gridRow: `${track + i - 1}` });
194
+ }
195
+ });
196
+ return { style: { gridTemplateRows: tracks.join(' '), width }, places };
197
+ }
198
+ export function ImageGenTool({ call }) {
199
+ const t = useTranslations('imageGen');
200
+ // In a transcript turn, the turn says whether an open call still runs.
201
+ const live = useContext(TurnLiveContext);
202
+ const inTurn = useContext(InTranscriptTurnContext);
203
+ // Consecutive image_gen calls of a turn draw as one grid, here, at the first (R38).
204
+ const run = useContext(ImageGenRunsContext).get(call.id);
205
+ const views = useMemo(() => (run ? run.map(sessionLogOpenCall) : [call]).map((one) => imageGenView(one, inTurn ? live : undefined)), [run, call, inTurn, live]);
206
+ const grid = useMemo(() => imageGenGrid(views), [views]);
207
+ const view = views[0];
208
+ const solo = views.length === 1 && view.images.length === 1;
209
+ // One fix per card, even when several frames failed for the same reason.
210
+ const repairable = views.find((one) => one.error?.connectModel)?.error ??
211
+ views.flatMap((one) => one.images).find((image) => image.error?.connectModel)?.error;
212
+ const action = repairable ? _jsx(ConnectAction, { code: repairable.code, provider: repairable.provider }) : null;
213
+ // The card carries no prompt and no model (R29): the frames are the content,
214
+ // their status (busy, loading, an error) the only text.
215
+ if (views.length === 1 && !view.images.length) {
216
+ // The whole call failed or stopped.
217
+ return (_jsx("div", { className: "w-full max-w-md", children: _jsx(FailureNote, { error: view.error, action: action }) }));
218
+ }
219
+ const callIds = (run ?? [call]).map((one) => one.call_id);
220
+ const frame = ({ image, call: at, first }) => {
221
+ const callView = views[at];
222
+ const edit = callView.action === 'edit';
223
+ const seed = callIds[at];
224
+ const several = callView.images.length > 1;
225
+ return (_jsx(ImageGenFrame, { image: image, seed: seed, model: callView.model, fill: !solo,
226
+ // Each call's first frame carries its busy line, the one status region
227
+ // per call; the others show its glyph alone, hidden from assistive tech.
228
+ busy: first ? (_jsx(BusyLabel, { seed: seed, label: several ? t(edit ? 'editingCount' : 'generatingCount', { count: callView.images.length }) : t(edit ? 'editing' : 'generating'), startedAt: callView.startedAt })) : (_jsx("span", { "aria-hidden": "true", className: "text-muted-foreground", children: _jsx(SessionDotMatrix, { sessionId: seed, size: 14 }) })) }));
229
+ };
230
+ // A tile is keyed by its call and place in it: it keeps its frame (and its
231
+ // loaded image) while the run grows.
232
+ // A call's tiles are contiguous, so its place is the distance to its first tile.
233
+ const tileKey = (tile, i) => `${callIds[tile.call]}:${i - grid.tiles.findIndex((other) => other.call === tile.call)}`;
234
+ if (solo) {
235
+ return (_jsxs("figure", { className: "flex w-full flex-col gap-2", children: [frame(grid.tiles[0]), action ? _jsx("div", { className: "flex flex-col items-start", children: action }) : null] }));
236
+ }
237
+ const count = grid.tiles.length;
238
+ const bento = grid.rows.length === 1 ? BENTO[count] : null;
239
+ const rowRects = grid.rows.map((size, row) => {
240
+ const firstTile = grid.tiles[grid.rows.slice(0, row).reduce((sum, n) => sum + n, 0)];
241
+ return ratioValue(views[firstTile.call].aspectRatio) * BENTO[size].scale;
242
+ });
243
+ const placed = bento ? null : gridPlacement(grid.rows, rowRects);
244
+ return (
245
+ // An inline-size container: the merged grid sizes its rows from its width (`cqw`).
246
+ _jsxs("figure", { className: cn('flex w-full flex-col gap-2', !bento && '@container'), children: [_jsx("div", { ...(bento ? { 'data-image-gen-bento': count } : { 'data-image-gen-grid': grid.rows.join('+') }), className: cn('grid min-h-0 w-full gap-1', bento ? bento.grid : 'grid-cols-6'), style: placed ? placed.style : { aspectRatio: rowRects[0], width: cappedWidth(rowRects[0]) }, children: grid.tiles.map((tile, i) => (_jsx("div", { "data-image-gen-tile": i, className: cn('min-h-0 min-w-0', bento && i === 0 && bento.first), style: placed?.places[i], children: frame(tile) }, tileKey(tile, i)))) }), action ? _jsx("div", { className: "flex flex-col items-start", children: action }) : null] }));
60
247
  }
61
248
  ToolRegistry.register('image-gen', ImageGenTool);
@@ -1,14 +1,16 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { parseArtifactUrl } from '../../../artifacts/frame-policy.js';
3
4
  import { Button } from '../../../primitives/button.js';
4
5
  import Hint from '../../../primitives/hint.js';
5
6
  import Loading from '../../../primitives/loading.js';
6
7
  import { SessionDotMatrix } from '../../../primitives/dot-matrix/session-dot-matrix.js';
7
8
  import { TextShimmer } from '../../../primitives/text-shimmer.js';
8
9
  import { isShowContentUnavailable, isShowPayloadEmpty, } from '@kortix/sdk';
9
- import { BoundActivateContext, InlineServicePreview, partInput, ServicePreviewActions, ToolRunningContext, ToolSurfaceContext, useToolNavigation, } from '../shared/infrastructure.js';
10
+ import { BoundActivateContext, ImageGenDigestsContext, ImageGenPathsContext, InlineServicePreview, partInput, ServicePreviewActions, ToolRunningContext, ToolSurfaceContext, useToolNavigation, } from '../shared/infrastructure.js';
10
11
  import { ToolRegistry } from '../shared/registry.js';
11
12
  import { buildHtmlStaticUrl, isShowHtmlFile, ServicePreviewViewport, ShowCarousel, ShowCarouselTabs, ShowContentRenderer, showDomain, ShowFileActions, showFileTypeIcon, ShowHoverCard, showHoverDetails, useServicePreview, } from '../shared/show-helpers.js';
13
+ import { showDrawnByImageGen, showItemDigest, withoutImageGenDuplicates } from '@kortix/sdk';
12
14
  import { useTranslations } from '../../../i18n/index.js';
13
15
  import { cn } from '../../../lib/utils.js';
14
16
  import { isAppRouteUrl, parseLocalhostUrl } from '@kortix/sdk';
@@ -44,18 +46,25 @@ export function ShowTool({ call, sessionId }) {
44
46
  // Present only on a card served from saved history: the server's copy of
45
47
  // `path`, so the card renders while the sandbox is off.
46
48
  const attachment = input.attachment || '';
49
+ // Images an `image_gen` card of this turn already drew are not drawn twice:
50
+ // the same path (D5), or the same bytes at another path, by sha256 (R38).
51
+ const drawnByImageGen = useContext(ImageGenPathsContext);
52
+ const drawnDigests = useContext(ImageGenDigestsContext);
47
53
  const items = useMemo(() => {
48
54
  const raw = input.items;
49
55
  if (!raw)
50
56
  return null;
51
57
  try {
52
58
  const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
53
- if (Array.isArray(parsed) && parsed.length > 0)
54
- return parsed;
59
+ if (Array.isArray(parsed) && parsed.length > 0) {
60
+ const withDigests = parsed.map((item) => ({ ...item, sha256: item.sha256 ?? showItemDigest(call, item.path) }));
61
+ const rest = withoutImageGenDuplicates(withDigests, drawnByImageGen, drawnDigests);
62
+ return rest.length > 0 ? rest : null;
63
+ }
55
64
  }
56
65
  catch { }
57
66
  return null;
58
- }, [input.items]);
67
+ }, [input.items, call, drawnByImageGen, drawnDigests]);
59
68
  const isCarousel = !!items && items.length > 0;
60
69
  const [carouselIndex, setCarouselIndex] = useState(0);
61
70
  // Clamped: a grouped carousel can lose an item (a call that settled empty).
@@ -107,9 +116,11 @@ export function ShowTool({ call, sessionId }) {
107
116
  const activeItemLabel = currentItem
108
117
  ? currentItem.title || currentItem.path?.split('/').pop()
109
118
  : '';
119
+ // A Kortix artifact's app link is the artifact, not a website: its name and a document icon.
120
+ const isArtifactLink = !!activeUrl && !!parseArtifactUrl(activeUrl);
110
121
  const displayTitle = isCarousel
111
122
  ? activeItemLabel || title || `${items.length} items`
112
- : title || (type === 'error' ? 'Error' : type === 'url' ? subtitleDomain || 'Link' : 'Output');
123
+ : title || (isArtifactLink ? 'Artifact' : type === 'error' ? 'Error' : type === 'url' ? subtitleDomain || 'Link' : 'Output');
113
124
  const hoverTarget = {
114
125
  path: activePath,
115
126
  url: activeUrl,
@@ -122,7 +133,7 @@ export function ShowTool({ call, sessionId }) {
122
133
  // While the card's preview loads, every port tab shows its own glyph,
123
134
  // seeded by that tab's title or URL.
124
135
  const portTabIcon = (item) => parseLocalhostUrl(item.url || '') ? (_jsx(SessionDotMatrix, { sessionId: item.title || item.url, size: 14, className: "shrink-0" })) : null;
125
- const headerIcon = isCarousel ? currentItem?.type || 'image' : isWebsitePreview ? 'url' : type;
136
+ const headerIcon = isCarousel ? currentItem?.type || 'image' : isArtifactLink ? 'markdown' : isWebsitePreview ? 'url' : type;
126
137
  // Inline card header owns the toolbar. Panel keeps the actions inside the
127
138
  // renderer / website header as before.
128
139
  const inlineToolbar = isWebsitePreview ? (_jsx(ServicePreviewActions, { preview: preview, compact: inlineTabs })) : (fileActions || contentActions);
@@ -143,7 +154,7 @@ export function ShowTool({ call, sessionId }) {
143
154
  // arguments has an empty input because the input has not arrived yet, and its
144
155
  // header carries the spinner that says so.
145
156
  const hasNothingToShow = useMemo(() => isShowPayloadEmpty({ items, path, url, content }), [items, path, url, content]);
146
- if (!running && hasNothingToShow)
157
+ if (!running && (hasNothingToShow || showDrawnByImageGen(call, drawnByImageGen, drawnDigests)))
147
158
  return null;
148
159
  const unavailable = isShowContentUnavailable({
149
160
  running,
@@ -172,7 +183,7 @@ export function ShowTool({ call, sessionId }) {
172
183
  body = _jsx(ShowUnavailableNote, { isWebsitePreview: true, href: null, fill: fill });
173
184
  }
174
185
  else {
175
- body = (_jsxs("div", { className: cn('overflow-hidden', fill ? 'flex h-full flex-col' : 'min-h-0 flex-1'), children: [isWebsitePreview && fill && (_jsxs("div", { className: "border-border flex shrink-0 items-center justify-between gap-3 border-b px-4 py-1", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [_jsx(Globe, { className: "text-muted-foreground size-3.5 shrink-0" }), _jsx("span", { className: "text-foreground truncate text-xs font-medium", children: preview.displayLabel })] }), _jsx(ServicePreviewActions, { preview: preview })] })), _jsx("div", { className: cn(fill && 'flex min-h-0 flex-1 flex-col'), children: isCarousel ? (_jsx(ActiveServicePreviewContext.Provider, { value: isWebsitePreview ? preview : null, children: _jsx(ShowCarousel, { items: items, LocalhostPreview: CarouselServicePreview, onIndexChange: setCarouselIndex, activeIndex: activeIndex, hideNav: inlineTabs, fill: fill, toolbarActions: fill ? fileActions : undefined }) })) : isWebsitePreview ? (_jsx(ServicePreviewViewport, { preview: preview })) : (_jsxs(_Fragment, { children: [fileUnavailable && (_jsx(ShowUnavailableNote, { isWebsitePreview: false, href: safeHttpUrl(activeUrl), fill: fill })), _jsx("div", { className: cn(fill && 'min-h-0 flex-1 overflow-hidden', fileUnavailable && 'hidden'), children: _jsx(ShowContentRenderer, { type: type, title: title, description: description, path: path, url: url, content: content, language: language, aspectRatio: aspectRatio, attachment: attachment, LocalhostPreview: InlineServicePreview, fill: fill, onStatusChange: setContentStatus, toolbarActions: fill ? fileActions : undefined }) }), description && !title && !fileUnavailable && (_jsx("div", { className: "border-border/15 shrink-0 border-t px-5 py-3", children: _jsx("p", { className: "text-muted-foreground text-xs", children: description }) }))] })) })] }));
186
+ body = (_jsxs("div", { className: cn('overflow-hidden', fill ? 'flex h-full flex-col' : 'min-h-0 flex-1'), children: [isWebsitePreview && fill && (_jsxs("div", { className: "border-border flex shrink-0 items-center justify-between gap-3 border-b px-4 py-1", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [_jsx(Globe, { className: "text-muted-foreground size-3.5 shrink-0" }), _jsx("span", { className: "text-foreground truncate text-xs font-medium", children: preview.displayLabel })] }), _jsx(ServicePreviewActions, { preview: preview })] })), _jsx("div", { className: cn(fill && 'flex min-h-0 flex-1 flex-col'), children: isCarousel ? (_jsx(ActiveServicePreviewContext.Provider, { value: isWebsitePreview ? preview : null, children: _jsx(ShowCarousel, { items: items, LocalhostPreview: CarouselServicePreview, onIndexChange: setCarouselIndex, activeIndex: activeIndex, hideNav: inlineTabs, fill: fill, toolbarActions: fill ? fileActions : undefined }) })) : isWebsitePreview ? (_jsx(ServicePreviewViewport, { preview: preview })) : (_jsxs(_Fragment, { children: [fileUnavailable && (_jsx(ShowUnavailableNote, { isWebsitePreview: false, href: safeHttpUrl(activeUrl), fill: fill })), _jsx("div", { className: cn(fill && 'min-h-0 flex-1 overflow-hidden', fileUnavailable && 'hidden'), children: _jsx(ShowContentRenderer, { type: type, title: title, description: description, path: path, url: url, content: content, language: language, aspectRatio: aspectRatio, attachment: attachment, sha256: showItemDigest(call, path), LocalhostPreview: InlineServicePreview, fill: fill, onStatusChange: setContentStatus, toolbarActions: fill ? fileActions : undefined }) }), description && !title && !fileUnavailable && (_jsx("div", { className: "border-border/15 shrink-0 border-t px-5 py-3", children: _jsx("p", { className: "text-muted-foreground text-xs", children: description }) }))] })) })] }));
176
187
  }
177
188
  // Panel surface: `fillsPanel` (tool-part-renderer.tsx) special-cases show/
178
189
  // show-user because the preview IS the payload — keep it exactly as before,
@@ -10,13 +10,18 @@ import type { ChannelPlatform } from './channel-message.js';
10
10
  * The hues are the platforms' own brand colors, not themeable tokens — which
11
11
  * is why they live here as named constants rather than as classes. Slack has
12
12
  * none to tint a label with: its mark is four colors and its wordmark is the
13
- * text color, black or white. It was Material pink (#E91E63).
13
+ * text color, black or white. It was Material pink (#E91E63). Email is no
14
+ * brand: its envelope and its label take the text color too.
14
15
  */
15
16
  export declare const CHANNEL_BRAND_COLOR: Record<ChannelPlatform, string | undefined>;
16
- /** The platform's own mark, in its brand colors. */
17
+ /**
18
+ * The platform's own mark, in its brand colors. Email draws the envelope an
19
+ * email session wears in the sidebar. A platform this build does not know (a
20
+ * newer `@kortix/shared`) draws a neutral chat glyph, never another brand.
21
+ */
17
22
  export declare function ChannelBrandMark({ platform, className, }: {
18
23
  platform: ChannelPlatform;
19
24
  className?: string;
20
25
  }): import("react").JSX.Element;
21
- /** The platform's display name; only Teams has a catalog string (its full name). */
26
+ /** The platform's display name: Teams (its full name) and Email have catalog strings, the brands are their own words. */
22
27
  export declare function channelPlatformLabel(platform: ChannelPlatform, tI18nComplete: UiTranslator): string;
@@ -1,5 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { ChatCircleIcon } from '@phosphor-icons/react';
4
+ import { Email } from '../../internal/icons/email.js';
3
5
  import { MicrosoftTeams } from '../../internal/icons/microsoft-teams.js';
4
6
  import { Slack } from '../../internal/icons/slack.js';
5
7
  /**
@@ -12,23 +14,37 @@ import { Slack } from '../../internal/icons/slack.js';
12
14
  * The hues are the platforms' own brand colors, not themeable tokens — which
13
15
  * is why they live here as named constants rather than as classes. Slack has
14
16
  * none to tint a label with: its mark is four colors and its wordmark is the
15
- * text color, black or white. It was Material pink (#E91E63).
17
+ * text color, black or white. It was Material pink (#E91E63). Email is no
18
+ * brand: its envelope and its label take the text color too.
16
19
  */
17
20
  export const CHANNEL_BRAND_COLOR = {
18
21
  Telegram: '#29B6F6',
19
22
  Slack: undefined,
20
23
  Teams: '#5B5FC7',
24
+ Email: undefined,
21
25
  };
22
26
  const TELEGRAM_PATH = 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69a.2.2 0 00-.05-.18c-.06-.05-.14-.03-.21-.02-.09.02-1.49.95-4.22 2.79-.4.27-.76.41-1.08.4-.36-.01-1.04-.2-1.55-.37-.63-.2-1.12-.31-1.08-.66.02-.18.27-.36.74-.55 2.92-1.27 4.86-2.11 5.83-2.51 2.78-1.16 3.35-1.36 3.73-1.36.08 0 .27.02.39.12.1.08.13.19.14.27-.01.06.01.24 0 .38z';
23
- /** The platform's own mark, in its brand colors. */
27
+ /**
28
+ * The platform's own mark, in its brand colors. Email draws the envelope an
29
+ * email session wears in the sidebar. A platform this build does not know (a
30
+ * newer `@kortix/shared`) draws a neutral chat glyph, never another brand.
31
+ */
24
32
  export function ChannelBrandMark({ platform, className = 'size-3.5 shrink-0', }) {
25
33
  if (platform === 'Teams')
26
34
  return _jsx(MicrosoftTeams, { className: className });
27
35
  if (platform === 'Slack')
28
36
  return _jsx(Slack, { className: className });
37
+ if (platform === 'Email')
38
+ return _jsx(Email, { className: className });
39
+ if (platform !== 'Telegram')
40
+ return _jsx(ChatCircleIcon, { className: className, "aria-hidden": "true" });
29
41
  return (_jsx("svg", { className: className, viewBox: "0 0 24 24", fill: CHANNEL_BRAND_COLOR.Telegram, "aria-hidden": "true", children: _jsx("path", { d: TELEGRAM_PATH }) }));
30
42
  }
31
- /** The platform's display name; only Teams has a catalog string (its full name). */
43
+ /** The platform's display name: Teams (its full name) and Email have catalog strings, the brands are their own words. */
32
44
  export function channelPlatformLabel(platform, tI18nComplete) {
33
- return platform === 'Teams' ? tI18nComplete.raw('texta7b52b269a23') : platform;
45
+ if (platform === 'Teams')
46
+ return tI18nComplete.raw('texta7b52b269a23');
47
+ if (platform === 'Email')
48
+ return tI18nComplete.raw('text969ccbd3cf63');
49
+ return platform;
34
50
  }
@@ -44,4 +44,12 @@ export declare function stoppedByName(data: SessionMessageAuthors | undefined, m
44
44
  export declare function awaitsAgent(prompt: {
45
45
  no_reply?: boolean;
46
46
  }): boolean;
47
+ /**
48
+ * The user messages the viewer may edit and rewind to: their own, with no
49
+ * other person's message after it (a rewind deletes everything after the
50
+ * target). An agent's message, or one with no recorded author, belongs to the
51
+ * thread's starter and never blocks a later rewind. The server applies the same
52
+ * rule (`rewind-authority.ts`). Null with no viewer id: nothing to filter on.
53
+ */
54
+ export declare function rewindableMessageIds(messageIds: readonly string[], authors: ReadonlyMap<string, SessionMessageAuthor>, viewerId: string | undefined, starterId: string | null | undefined): Set<string> | null;
47
55
  export {};
@@ -73,3 +73,27 @@ export function stoppedByName(data, messageId, viewerId) {
73
73
  export function awaitsAgent(prompt) {
74
74
  return !prompt.no_reply;
75
75
  }
76
+ /**
77
+ * The user messages the viewer may edit and rewind to: their own, with no
78
+ * other person's message after it (a rewind deletes everything after the
79
+ * target). An agent's message, or one with no recorded author, belongs to the
80
+ * thread's starter and never blocks a later rewind. The server applies the same
81
+ * rule (`rewind-authority.ts`). Null with no viewer id: nothing to filter on.
82
+ */
83
+ export function rewindableMessageIds(messageIds, authors, viewerId, starterId) {
84
+ if (viewerId === undefined)
85
+ return null;
86
+ const allowed = new Set();
87
+ for (let i = messageIds.length - 1; i >= 0; i--) {
88
+ const author = authors.get(messageIds[i]);
89
+ if (author?.kind === 'member') {
90
+ if (author.user_id !== viewerId)
91
+ break;
92
+ allowed.add(messageIds[i]);
93
+ }
94
+ else if (!starterId || starterId === viewerId) {
95
+ allowed.add(messageIds[i]);
96
+ }
97
+ }
98
+ return allowed;
99
+ }