@kortix/ui 0.14.8 → 0.14.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (567) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +116 -3
  3. package/dist/_vendor/shared/app-config.d.ts +175 -0
  4. package/dist/_vendor/shared/artifact-comments.d.ts +235 -0
  5. package/dist/_vendor/shared/channel-descriptors.d.ts +96 -0
  6. package/dist/_vendor/shared/channel-message.d.ts +45 -5
  7. package/dist/_vendor/shared/index.d.ts +2 -0
  8. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  9. package/dist/access/access/access-detail-shell.js +1 -1
  10. package/dist/access/access/principal-picker.d.ts +11 -0
  11. package/dist/access/access/principal-picker.js +3 -2
  12. package/dist/apps/app-preview-pool.d.ts +7 -2
  13. package/dist/apps/app-preview-pool.js +30 -7
  14. package/dist/apps/app-shared.d.ts +22 -15
  15. package/dist/apps/app-shared.js +37 -19
  16. package/dist/apps/index.d.ts +2 -2
  17. package/dist/apps/index.js +2 -2
  18. package/dist/artifacts/artifact-frame.d.ts +16 -0
  19. package/dist/artifacts/artifact-frame.js +55 -0
  20. package/dist/artifacts/artifact-session.d.ts +18 -0
  21. package/dist/artifacts/artifact-session.js +101 -0
  22. package/dist/artifacts/frame-policy.d.ts +30 -0
  23. package/dist/artifacts/frame-policy.js +61 -0
  24. package/dist/artifacts/index.d.ts +3 -0
  25. package/dist/artifacts/index.js +5 -0
  26. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  27. package/dist/browser/sandbox-browser-chrome.js +2 -2
  28. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  29. package/dist/customize/agents/agent-grant-pages.js +30 -4
  30. package/dist/customize/agents/agent-page.js +3 -1
  31. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  32. package/dist/customize/agents/agent-policy-sets.js +72 -0
  33. package/dist/customize/agents/agent-triggers-section.js +2 -1
  34. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  35. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  36. package/dist/customize/connectors/agent-access.d.ts +35 -0
  37. package/dist/customize/connectors/agent-access.js +77 -0
  38. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  39. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  40. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  41. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  42. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  43. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  44. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  45. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  46. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  47. package/dist/customize/connectors/connector-identity.js +13 -42
  48. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  49. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  50. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  51. package/dist/customize/connectors/connector-routes.js +29 -20
  52. package/dist/customize/connectors/connectors-page.js +53 -82
  53. package/dist/customize/connectors/detail/app-page.js +226 -98
  54. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  55. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  56. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  57. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  58. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  59. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  60. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  61. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  62. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  63. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  64. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  65. package/dist/customize/connectors/detail/connector-page.js +14 -10
  66. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  67. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  68. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  69. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  70. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  71. package/dist/customize/connectors/detail/connector-status.js +34 -10
  72. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  73. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  74. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  75. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  76. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  77. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  78. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  79. package/dist/customize/connectors/detail/provider-info.js +2 -2
  80. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  81. package/dist/customize/connectors/detail/status-badge.js +4 -5
  82. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  83. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  84. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  85. package/dist/customize/connectors/install/install-dialog.js +40 -0
  86. package/dist/customize/connectors/install/install.d.ts +13 -2
  87. package/dist/customize/connectors/install/install.js +9 -4
  88. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  89. package/dist/customize/connectors/install/use-install.js +65 -37
  90. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  91. package/dist/customize/connectors/install/way-kind.js +16 -0
  92. package/dist/customize/connectors/provider-label.d.ts +2 -1
  93. package/dist/customize/connectors/provider-label.js +13 -3
  94. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  95. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  96. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  97. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  98. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  99. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  100. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  101. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  102. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  103. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  104. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  105. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  106. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  107. package/dist/customize/connectors/use-agent-access.js +72 -0
  108. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  109. package/dist/customize/migrate-to-v2/index.js +1 -2
  110. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -25
  111. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -236
  112. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  113. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  114. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  115. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  116. package/dist/customize/providers/provider-accordion.js +17 -2
  117. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  118. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  119. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  120. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  121. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  122. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  123. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  124. package/dist/customize/sections/component/channel-mocks.js +46 -0
  125. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  126. package/dist/customize/sections/component/channel-row.js +10 -4
  127. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  128. package/dist/customize/sections/component/email-connect-form.js +183 -0
  129. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  130. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  131. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  132. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  133. package/dist/customize/sections/component/telegram-channel-row.js +21 -28
  134. package/dist/customize/sections/connectors-view.d.ts +1 -15
  135. package/dist/customize/sections/connectors-view.js +81 -314
  136. package/dist/customize/sections/view/agent-editor-catalog.js +10 -0
  137. package/dist/customize/sections/view/channels-view.d.ts +6 -1
  138. package/dist/customize/sections/view/channels-view.js +72 -81
  139. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  140. package/dist/customize/settings/rail.js +9 -0
  141. package/dist/customize/settings/settings-tabs.d.ts +1 -1
  142. package/dist/customize/settings/settings-tabs.js +1 -0
  143. package/dist/customize/settings/tabs/chrome-connections-tab.d.ts +6 -0
  144. package/dist/customize/settings/tabs/chrome-connections-tab.js +99 -0
  145. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  146. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +4 -15
  147. package/dist/customize/shared/catalog/catalog-empty-state.js +9 -7
  148. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  149. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  150. package/dist/customize/shared/feature-gate-screen.js +27 -9
  151. package/dist/customize/shared/use-customize-prefetch.d.ts +2 -3
  152. package/dist/customize/shared/use-customize-prefetch.js +9 -27
  153. package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
  154. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  155. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  156. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  157. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  158. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  159. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  160. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  161. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  162. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  163. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  164. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  165. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  166. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  167. package/dist/customize/triggers/schedule-view.js +5 -2
  168. package/dist/files/index.d.ts +1 -0
  169. package/dist/files/index.js +1 -0
  170. package/dist/files/project/change-request-recovery.d.ts +1 -26
  171. package/dist/files/project/change-request-recovery.js +1 -59
  172. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  173. package/dist/files/project/components/drive-explorer.js +15 -15
  174. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  175. package/dist/files/project/components/drive-toolbar.js +14 -5
  176. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  177. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  178. package/dist/files/project/hooks/use-change-requests.js +11 -2
  179. package/dist/files/renderers/image-frame.d.ts +48 -0
  180. package/dist/files/renderers/image-frame.js +59 -0
  181. package/dist/files/renderers/image-renderer.d.ts +11 -1
  182. package/dist/files/renderers/image-renderer.js +13 -3
  183. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  184. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  185. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  186. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  187. package/dist/files/renderers/show-content-renderer.js +56 -14
  188. package/dist/files/runtime/file-source.js +2 -0
  189. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  190. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  191. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  192. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  193. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  194. package/dist/files/viewer/file-content-renderer.js +50 -7
  195. package/dist/files/viewer/file-header.d.ts +7 -3
  196. package/dist/files/viewer/file-header.js +20 -11
  197. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  198. package/dist/files/viewer/file-preview-modal.js +10 -22
  199. package/dist/files/viewer/file-source.d.ts +13 -0
  200. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  201. package/dist/files/viewer/use-file-content-state.js +28 -10
  202. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  203. package/dist/files/viewer/viewer-actions.js +2 -2
  204. package/dist/hooks/use-media-query.d.ts +1 -0
  205. package/dist/hooks/use-mobile.d.ts +5 -0
  206. package/dist/hooks/use-mobile.js +8 -0
  207. package/dist/i18n/en.d.ts +1062 -85
  208. package/dist/i18n/en.js +1078 -101
  209. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  210. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  211. package/dist/index.d.ts +2 -2
  212. package/dist/index.js +2 -2
  213. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  214. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  215. package/dist/internal/account-hub/hub-sheet.js +21 -5
  216. package/dist/internal/account-hub/sections.d.ts +1 -1
  217. package/dist/internal/account-hub/sections.js +2 -1
  218. package/dist/internal/apps-and-extensions/apps-modal.d.ts +9 -0
  219. package/dist/internal/apps-and-extensions/apps-modal.js +107 -0
  220. package/dist/internal/auth/auth-card-shell.js +3 -3
  221. package/dist/internal/chrome/browser-icon.d.ts +24 -0
  222. package/dist/internal/chrome/browser-icon.js +58 -0
  223. package/dist/internal/chrome/chrome-card-state.d.ts +16 -0
  224. package/dist/internal/chrome/chrome-card-state.js +9 -0
  225. package/dist/internal/chrome/chrome-connect.d.ts +69 -0
  226. package/dist/internal/chrome/chrome-connect.js +178 -0
  227. package/dist/internal/chrome/chrome-mock.d.ts +4 -0
  228. package/dist/internal/chrome/chrome-mock.js +15 -0
  229. package/dist/internal/chrome/chrome-names.d.ts +15 -0
  230. package/dist/internal/chrome/chrome-names.js +35 -0
  231. package/dist/internal/chrome/extension.d.ts +47 -0
  232. package/dist/internal/chrome/extension.js +91 -0
  233. package/dist/internal/chrome/use-chrome-offered.d.ts +11 -0
  234. package/dist/internal/chrome/use-chrome-offered.js +22 -0
  235. package/dist/internal/components/agent-mark.js +5 -2
  236. package/dist/internal/connector-logo/connector-logo-source.d.ts +64 -0
  237. package/dist/internal/connector-logo/connector-logo-source.js +49 -0
  238. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  239. package/dist/internal/connector-logo/connector-logo.js +56 -0
  240. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  241. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  242. package/dist/internal/files/file-read-retry.d.ts +13 -0
  243. package/dist/internal/files/file-read-retry.js +23 -3
  244. package/dist/internal/files/session-drive-files.d.ts +5 -1
  245. package/dist/internal/files/session-drive-files.js +7 -2
  246. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  247. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  248. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  249. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  250. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  251. package/dist/internal/hooks/index.d.ts +1 -1
  252. package/dist/internal/hooks/index.js +1 -1
  253. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  254. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  255. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  256. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  257. package/dist/internal/icons/edge.d.ts +5 -0
  258. package/dist/internal/icons/edge.js +10 -0
  259. package/dist/internal/icons/telegram.d.ts +5 -0
  260. package/dist/internal/icons/telegram.js +6 -1
  261. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  262. package/dist/internal/layout/nav-hover-card.js +84 -0
  263. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  264. package/dist/internal/layout/project-nav-row.js +3 -2
  265. package/dist/internal/layout/project-page-header.d.ts +4 -2
  266. package/dist/internal/layout/project-page-header.js +4 -3
  267. package/dist/internal/layout/project-settings-nav.js +59 -2
  268. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  269. package/dist/internal/lib/browser-error-noise.js +1 -1
  270. package/dist/internal/lib/browser-noise/rules/extensions.js +17 -3
  271. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  272. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  273. package/dist/internal/lib/detect-os.d.ts +43 -0
  274. package/dist/internal/lib/detect-os.js +70 -0
  275. package/dist/internal/lib/manifest-version.d.ts +1 -1
  276. package/dist/internal/lib/manifest-version.js +2 -2
  277. package/dist/internal/lib/memory-href.d.ts +16 -0
  278. package/dist/internal/lib/memory-href.js +46 -0
  279. package/dist/internal/lib/use-project-feature-flags.js +13 -9
  280. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  281. package/dist/internal/lib/utils/heic-convert.js +3 -4
  282. package/dist/internal/lib/web-notifications.d.ts +20 -0
  283. package/dist/internal/lib/web-notifications.js +48 -4
  284. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  285. package/dist/internal/notifications/notification-bell.js +2 -2
  286. package/dist/internal/selection/selection-bar.d.ts +2 -1
  287. package/dist/internal/selection/selection-bar.js +1 -1
  288. package/dist/internal/stores/apps-modal-store.d.ts +8 -0
  289. package/dist/internal/stores/apps-modal-store.js +6 -0
  290. package/dist/internal/stores/composer-prefill-store.d.ts +12 -5
  291. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  292. package/dist/internal/stores/file-preview-store.js +19 -1
  293. package/dist/internal/stores/kortix-computer-store.js +3 -0
  294. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  295. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  296. package/dist/lib/routes.d.ts +13 -1
  297. package/dist/lib/routes.js +13 -0
  298. package/dist/markdown/index.d.ts +2 -1
  299. package/dist/markdown/index.js +2 -1
  300. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  301. package/dist/markdown/setup-links/approval-decision.js +9 -3
  302. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  303. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  304. package/dist/markdown/setup-links/secret-intake-form.d.ts +0 -10
  305. package/dist/markdown/setup-links/secret-intake-form.js +1 -1
  306. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  307. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  308. package/dist/markdown/unified-markdown.js +5 -5
  309. package/dist/primitives/badge.d.ts +1 -1
  310. package/dist/primitives/badge.js +2 -0
  311. package/dist/primitives/disclosure.js +14 -2
  312. package/dist/primitives/empty-art.d.ts +12 -0
  313. package/dist/primitives/empty-art.js +11 -0
  314. package/dist/primitives/empty-state.d.ts +2 -2
  315. package/dist/primitives/empty-state.js +6 -5
  316. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  317. package/dist/primitives/mermaid-renderer.js +21 -15
  318. package/dist/primitives/resizable.js +6 -1
  319. package/dist/primitives/resize-seam.d.ts +11 -0
  320. package/dist/primitives/resize-seam.js +12 -0
  321. package/dist/primitives/sidebar-panel.js +4 -7
  322. package/dist/primitives/tabs.d.ts +14 -1
  323. package/dist/primitives/tabs.js +1 -1
  324. package/dist/providers/ui-provider.d.ts +9 -0
  325. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  326. package/dist/session/composer/ComposerAboveCard.js +2 -2
  327. package/dist/session/composer/ComposerCard.d.ts +1 -1
  328. package/dist/session/composer/ComposerCard.js +3 -3
  329. package/dist/session/composer/agent-selector.d.ts +13 -1
  330. package/dist/session/composer/agent-selector.js +25 -5
  331. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  332. package/dist/session/composer/composer-agent-access.js +27 -0
  333. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  334. package/dist/session/composer/composer-chat-input.js +8 -6
  335. package/dist/session/composer/composer-logic.d.ts +16 -0
  336. package/dist/session/composer/composer-logic.js +12 -0
  337. package/dist/session/composer/composer-underbar.d.ts +3 -1
  338. package/dist/session/composer/composer-underbar.js +4 -3
  339. package/dist/session/composer/composer.d.ts +15 -1
  340. package/dist/session/composer/composer.js +19 -1
  341. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  342. package/dist/session/composer/draft/composer-draft.js +5 -1
  343. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  344. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  345. package/dist/session/models/chatgpt-connection-button.js +54 -0
  346. package/dist/session/models/model-selector.js +5 -2
  347. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  348. package/dist/session/models/use-model-connection-gate.js +5 -5
  349. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  350. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  351. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  352. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  353. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  354. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  355. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  356. package/dist/session/panel/easy/app-preview.js +31 -12
  357. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  358. package/dist/session/panel/easy/change-requests-card.js +17 -0
  359. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  360. package/dist/session/panel/easy/easy-panel.js +5 -2
  361. package/dist/session/panel/easy/file-preview.js +1 -1
  362. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  363. package/dist/session/panel/easy/outputs-card.js +3 -2
  364. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  365. package/dist/session/panel/session-audit-panel.js +9 -2
  366. package/dist/session/panel/session-audit-shared.js +3 -1
  367. package/dist/session/panel/session-detail-panel.js +9 -3
  368. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  369. package/dist/session/panel/session-files-explorer.js +12 -3
  370. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  371. package/dist/session/panel/session-panel-provider.js +32 -7
  372. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  373. package/dist/session/panel/shared/derive-panels.js +12 -2
  374. package/dist/session/panel/shared/output-priority.js +2 -0
  375. package/dist/session/participants/session-participants.d.ts +8 -2
  376. package/dist/session/participants/session-participants.js +11 -4
  377. package/dist/session/prompts/approval-request.d.ts +5 -0
  378. package/dist/session/prompts/approval-request.js +9 -1
  379. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  380. package/dist/session/prompts/session-approval-review.js +18 -0
  381. package/dist/session/status/session-error-banner.js +2 -49
  382. package/dist/session/status/session-starting-loader.d.ts +14 -2
  383. package/dist/session/status/session-starting-loader.js +16 -4
  384. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  385. package/dist/session/thread/after-first-prompt.js +8 -0
  386. package/dist/session/thread/detect-command.d.ts +12 -0
  387. package/dist/session/thread/detect-command.js +20 -0
  388. package/dist/session/thread/session-chat.d.ts +3 -1
  389. package/dist/session/thread/session-chat.js +377 -252
  390. package/dist/session/thread/session-thread.d.ts +15 -1
  391. package/dist/session/thread/session-thread.js +20 -3
  392. package/dist/session/thread/session-transcript-class.d.ts +5 -1
  393. package/dist/session/thread/session-transcript-class.js +5 -1
  394. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  395. package/dist/session/thread/thread-boot-rows.js +89 -0
  396. package/dist/session/thread/transcript-rows.d.ts +31 -0
  397. package/dist/session/thread/transcript-rows.js +3 -0
  398. package/dist/session/thread/transcript.d.ts +0 -9
  399. package/dist/session/thread/transcript.js +104 -19
  400. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  401. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  402. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  403. package/dist/session/tool/tool-part-renderer.js +8 -3
  404. package/dist/session/tool/tools/bash-tool.js +7 -6
  405. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  406. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  407. package/dist/session/tool/tools/codemode-tool.js +1 -1
  408. package/dist/session/tool/tools/connector-tools.js +1 -1
  409. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  410. package/dist/session/tool/tools/image-gen-tool.js +241 -53
  411. package/dist/session/tool/tools/show-tool.js +19 -8
  412. package/dist/session/turn/channel-brand.d.ts +8 -3
  413. package/dist/session/turn/channel-brand.js +20 -4
  414. package/dist/session/turn/message-author.d.ts +8 -0
  415. package/dist/session/turn/message-author.js +24 -0
  416. package/dist/session/turn/message-row.d.ts +52 -0
  417. package/dist/session/turn/message-row.js +44 -0
  418. package/dist/session/turn/plan-anchor.d.ts +1 -1
  419. package/dist/session/turn/plan-anchor.js +1 -1
  420. package/dist/session/turn/user-message.d.ts +14 -6
  421. package/dist/session/turn/user-message.js +35 -15
  422. package/dist/styles.css +1 -1
  423. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  424. package/dist/workspace/home/access-requests-bell.js +20 -6
  425. package/dist/workspace/home/first-chat.d.ts +8 -21
  426. package/dist/workspace/home/first-chat.js +22 -72
  427. package/dist/workspace/index.d.ts +6 -0
  428. package/dist/workspace/index.js +6 -0
  429. package/dist/workspace/layout/project-home.d.ts +14 -2
  430. package/dist/workspace/layout/project-home.js +60 -21
  431. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  432. package/dist/workspace/layout/use-project-home-send.js +82 -3
  433. package/dist/workspace/memory/body-doc.d.ts +17 -0
  434. package/dist/workspace/memory/body-doc.js +208 -0
  435. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  436. package/dist/workspace/memory/body-extensions.js +103 -0
  437. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  438. package/dist/workspace/memory/company-memory-page.js +16 -0
  439. package/dist/workspace/memory/memory-all.d.ts +20 -0
  440. package/dist/workspace/memory/memory-all.js +27 -0
  441. package/dist/workspace/memory/memory-body.d.ts +19 -0
  442. package/dist/workspace/memory/memory-body.js +139 -0
  443. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  444. package/dist/workspace/memory/memory-empty.js +28 -0
  445. package/dist/workspace/memory/memory-history.d.ts +27 -0
  446. package/dist/workspace/memory/memory-history.js +108 -0
  447. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  448. package/dist/workspace/memory/memory-labels.js +47 -0
  449. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  450. package/dist/workspace/memory/memory-page-list.js +156 -0
  451. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  452. package/dist/workspace/memory/memory-reader.js +123 -0
  453. package/dist/workspace/memory/memory-view.d.ts +21 -0
  454. package/dist/workspace/memory/memory-view.js +124 -0
  455. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  456. package/dist/workspace/memory/remember-popover.js +61 -0
  457. package/dist/workspace/memory/remember-this.d.ts +12 -0
  458. package/dist/workspace/memory/remember-this.js +89 -0
  459. package/dist/workspace/memory/source-mark.d.ts +18 -0
  460. package/dist/workspace/memory/source-mark.js +79 -0
  461. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  462. package/dist/workspace/memory/used-memory-chip.js +61 -0
  463. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  464. package/dist/workspace/new/advanced-fields.js +2 -2
  465. package/dist/workspace/new/source-param.d.ts +1 -1
  466. package/dist/workspace/new/source-param.js +3 -1
  467. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  468. package/dist/workspace/new/use-create-workspace.js +3 -3
  469. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  470. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  471. package/dist/workspace/projects/policies-panel.js +5 -3
  472. package/dist/workspace/review/review-actions.d.ts +4 -2
  473. package/dist/workspace/review/review-actions.js +8 -2
  474. package/dist/workspace/review/review-center.js +11 -7
  475. package/dist/workspace/review/review-detail.d.ts +10 -0
  476. package/dist/workspace/review/review-detail.js +101 -13
  477. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  478. package/dist/workspace/saved-session-skeleton.js +3 -3
  479. package/dist/workspace/session-workspace.js +15 -13
  480. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  481. package/dist/workspace/sessions/session-label-badges.js +2 -1
  482. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  483. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  484. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  485. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  486. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  487. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  488. package/dist/workspace/sidebar/footer/project-chrome-nav.d.ts +10 -0
  489. package/dist/workspace/sidebar/footer/project-chrome-nav.js +56 -0
  490. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  491. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  492. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  493. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  494. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  495. package/dist/workspace/sidebar/project-session-list.js +68 -56
  496. package/dist/workspace/sidebar/project-sidebar.js +13 -2
  497. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  498. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  499. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  500. package/dist/workspace/sidebar/session-group-order.js +25 -0
  501. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  502. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  503. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  504. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  505. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  506. package/dist/workspace/spaces/channel-glyph.js +6 -0
  507. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  508. package/dist/workspace/spaces/channel-setup.js +105 -0
  509. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  510. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  511. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  512. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  513. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  514. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  515. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  516. package/dist/workspace/spaces/space-agents.js +10 -0
  517. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  518. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  519. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  520. package/dist/workspace/spaces/space-link-label.js +73 -0
  521. package/dist/workspace/spaces/space-links.d.ts +19 -0
  522. package/dist/workspace/spaces/space-links.js +230 -0
  523. package/dist/workspace/spaces/space-members.d.ts +46 -0
  524. package/dist/workspace/spaces/space-members.js +182 -0
  525. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  526. package/dist/workspace/spaces/space-roster.js +44 -0
  527. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  528. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  529. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  530. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  531. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  532. package/dist/workspace/spaces/space-timeline.js +183 -0
  533. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  534. package/dist/workspace/spaces/space-triggers.js +78 -0
  535. package/dist/workspace/spaces/space-view.d.ts +37 -0
  536. package/dist/workspace/spaces/space-view.js +436 -0
  537. package/package.json +67 -36
  538. package/skills/kortix-ui/SKILL.md +3 -3
  539. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  540. package/skills/kortix-ui/references/modules.md +29 -5
  541. package/skills/kortix-ui/references/theming.md +1 -1
  542. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  543. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  544. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  545. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  546. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  547. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  548. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  549. package/dist/customize/sections/connector-connection-header.js +0 -33
  550. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  551. package/dist/customize/sections/connector-connection-modal.js +0 -72
  552. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  553. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  554. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  555. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  556. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  557. package/dist/customize/sections/discover-catalogue.js +0 -132
  558. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  559. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  560. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  561. package/dist/files/project/components/drive-empty-art.js +0 -5
  562. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  563. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  564. package/dist/internal/share/public-share-link-button.js +0 -17
  565. package/dist/markdown/setup-links/app-credentials-form.d.ts +0 -12
  566. package/dist/markdown/setup-links/app-credentials-form.js +0 -115
  567. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { createContext, useContext } from 'react';
3
- import { isEmptyShowPart } from '@kortix/sdk';
3
+ import { isInvisibleActivityPart } from '@kortix/sdk';
4
4
  import { toolKind } from '@kortix/sdk';
5
5
  export const ToolRunningContext = createContext(false);
6
6
  /**
@@ -70,7 +70,35 @@ export const TurnLiveContext = createContext(false);
70
70
  * the turn ended on (KRTX-3021). Empty outside a settled turn.
71
71
  */
72
72
  export const RecoveredCallsContext = createContext(new Set());
73
+ /**
74
+ * The images the turn's `image_gen` calls already drew (`imagePathsShownByImageGen`).
75
+ * A `show` of the same file in that turn does not draw it a second time (D5).
76
+ */
77
+ export const ImageGenPathsContext = createContext(new Set());
78
+ /**
79
+ * The sha256 of the images the turn's `image_gen` calls already drew
80
+ * (`imageDigestsShownByImageGen`): a `show` of the same bytes at another path
81
+ * (a Drive copy) is not drawn a second time either (R38).
82
+ */
83
+ export const ImageGenDigestsContext = createContext(new Set());
84
+ /**
85
+ * The runs of the turn's `image_gen` calls that draw as one grid
86
+ * (`sessionLogImageGenRuns`), by block id: the first call draws the run, the
87
+ * others nothing (R38).
88
+ */
89
+ export const ImageGenRunsContext = createContext(new Map());
90
+ /**
91
+ * True inside a transcript turn's steps, where `TurnLiveContext` is a fact
92
+ * about the owning turn rather than its `false` default. The image card reads
93
+ * both to tell a stopped generation from one still running.
94
+ */
95
+ export const InTranscriptTurnContext = createContext(false);
73
96
  export const ToolDurationContext = createContext(undefined);
97
+ /**
98
+ * True in a read-only session view (the sub-session modal): a tool card shows
99
+ * what happened and offers no fix (connect a model, reconnect ChatGPT).
100
+ */
101
+ export const ReadOnlySessionContext = createContext(false);
74
102
  // Background memory plumbing (searches/gets and raw memory/ reads) stays
75
103
  // out of the Actions panel. The memory editor tool itself ('memory'/'oc-memory')
76
104
  // is NOT listed here — it renders in the panel so clicking its chat row works.
@@ -91,9 +119,9 @@ const MEMORY_LOOKUP_TOOL_NAMES = new Set([
91
119
  export function shouldShowToolPartInActionsPanel(call) {
92
120
  if (MEMORY_LOOKUP_TOOL_NAMES.has(call.name))
93
121
  return false;
94
- // A `show` that handed nothing over renders an empty card, so its stepper row
122
+ // A `show` that handed nothing over, or a read of an empty memory folder,
95
123
  // would open onto blank space. Same verdict the chat transcript reaches.
96
- if (isEmptyShowPart(call))
124
+ if (isInvisibleActivityPart(call))
97
125
  return false;
98
126
  // A skill row opens its SKILL.md in the detail panel, so it has no Actions
99
127
  // row of its own. (It used to raise a side sheet; that sheet is gone.)
@@ -16,9 +16,6 @@ interface ToolPartRendererProps {
16
16
  defaultOpen?: boolean;
17
17
  disableNavigation?: boolean;
18
18
  }
19
- declare function ToolPartRendererImpl({ call: given, sessionId, permission, question, onPermissionReply, onQuestionReply, onQuestionReject, defaultOpen, disableNavigation, }: ToolPartRendererProps & {
20
- sessionId?: string;
21
- }): import("react").JSX.Element | null;
22
19
  /**
23
20
  * The boundary that stops a settled tool row re-rendering with the stream.
24
21
  *
@@ -35,5 +32,9 @@ declare function ToolPartRendererImpl({ call: given, sessionId, permission, ques
35
32
  * `memo` does not block context propagation, so `ToolSurfaceContext`,
36
33
  * `ToolActivateContext` and `ToolOutcomeContext` still reach the tool.
37
34
  */
38
- export declare const ToolPartRenderer: import("react").MemoExoticComponent<typeof ToolPartRendererImpl>;
35
+ /** A block that is not a tool call (a harness block a host mistyped) renders nothing: the row must never throw. */
36
+ declare function ToolPartRendererGuard(props: ToolPartRendererProps & {
37
+ sessionId?: string;
38
+ }): import("react").JSX.Element | null;
39
+ export declare const ToolPartRenderer: import("react").MemoExoticComponent<typeof ToolPartRendererGuard>;
39
40
  export {};
@@ -79,8 +79,9 @@ function ToolPartRendererImpl({ call: given, sessionId, permission, question, on
79
79
  const errorStr = partError(call);
80
80
  const childBearingTaskError = errorStr !== undefined && toolKind(call.name) === 'task' && Boolean(getChildSessionId(call));
81
81
  // A failed codemode script keeps its partial output and the calls it made before
82
- // the failure: its own row draws them, with the error.
83
- const drawsOwnError = childBearingTaskError || call.name === 'codemode';
82
+ // the failure: its own row draws them, with the error. The image card draws its
83
+ // failure (with the Connect ChatGPT action) and a stop in place of the image.
84
+ const drawsOwnError = childBearingTaskError || call.name === 'codemode' || call.name === 'image_gen';
84
85
  if (errorStr !== undefined && !drawsOwnError) {
85
86
  const { display, server } = (() => {
86
87
  const slashIdx = call.name.lastIndexOf('/');
@@ -146,5 +147,9 @@ function ToolPartRendererImpl({ call: given, sessionId, permission, question, on
146
147
  * `memo` does not block context propagation, so `ToolSurfaceContext`,
147
148
  * `ToolActivateContext` and `ToolOutcomeContext` still reach the tool.
148
149
  */
149
- export const ToolPartRenderer = memo(ToolPartRendererImpl);
150
+ /** A block that is not a tool call (a harness block a host mistyped) renders nothing: the row must never throw. */
151
+ function ToolPartRendererGuard(props) {
152
+ return props.call?.type === 'tool_call' ? _jsx(ToolPartRendererImpl, { ...props }) : null;
153
+ }
154
+ export const ToolPartRenderer = memo(ToolPartRendererGuard);
150
155
  ToolPartRenderer.displayName = 'ToolPartRenderer';
@@ -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,249 @@
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 (_jsx(ImageFrame, { className: "group", 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, children: src && openFullScreen ? (
129
+ // The one hint that the image opens full screen, on hover only; the whole frame is the button.
130
+ // A child of the frame: a tall image narrows the frame, and the hint stays on its corner.
131
+ _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 }));
132
+ }
133
+ /**
134
+ * The tallest a lone image or the bento may be (R33). The box narrows to
135
+ * keep its ratio, so it never crops more and never letterboxes.
136
+ */
137
+ const IMAGE_MAX_HEIGHT = '60vh';
138
+ /** `'3 / 2'` → `1.5`; anything unreadable → `1`. */
139
+ function ratioValue(ratio) {
140
+ const [w, h] = ratio.split('/').map((part) => Number(part.trim()));
141
+ return w && h ? w / h : 1;
142
+ }
143
+ /**
144
+ * The bento: several images fill one rectangle, the width of the message up
145
+ * to `IMAGE_MAX_HEIGHT` tall, its ratio fixed from the requested one, so
146
+ * nothing moves when they land.
147
+ * Tile i keeps slot i. Every tile has the requested ratio `r`:
148
+ * - 2: side by side, one row → the rectangle is `2r`;
149
+ * - 3: tile 0 takes 2/3 of the width and both rows, tiles 1 and 2 stack on
150
+ * the right third → `1.5r`;
151
+ * - 4: 2×2 → `r`.
152
+ */
153
+ const BENTO = {
154
+ // Explicit rows: each is minmax(0, 1fr), so a loaded image never stretches one.
155
+ 2: { grid: 'grid-cols-2 grid-rows-1', scale: 2 },
156
+ 3: { grid: 'grid-cols-3 grid-rows-2', scale: 1.5, first: 'col-span-2 row-span-2' },
157
+ 4: { grid: 'grid-cols-2 grid-rows-2', scale: 1 },
158
+ };
159
+ /** `min(100%, …)`: the widest a rectangle of ratio `rect` may be under the height cap. */
160
+ const cappedWidth = (rect) => `min(100%, calc(${IMAGE_MAX_HEIGHT} * ${rect}))`;
161
+ /**
162
+ * Five or more images (R38): ONE grid of six columns whose rows are the
163
+ * bento patterns (`imageGenGrid().rows`: 5 = 3+2, 8 = 4+4, …). Every tile sits
164
+ * in the same grid, placed by line numbers, so a tile is never re-parented.
165
+ *
166
+ * The grid is as wide as its tallest row allows under the cap (`width`), and
167
+ * each row is exactly `width / rects[k]` tall (`rects[k]` = its tile ratio ×
168
+ * the pattern's scale), so no row passes `IMAGE_MAX_HEIGHT`. Track heights are
169
+ * lengths, read from the figure's inline size (`cqw`): the grid is the sum of
170
+ * its rows and the gaps between them, with no aspect ratio of its own. (Flex
171
+ * rows under an aspect ratio left an empty band whenever their `fr` factors
172
+ * summed below 1, e.g. 16:9 tiles.) A two-track row subtracts the gap between
173
+ * its tracks, so a large tile spanning both is the row's height.
174
+ */
175
+ function gridPlacement(rows, rects) {
176
+ const width = `min(100cqw, ${IMAGE_MAX_HEIGHT} * ${Math.min(...rects)})`;
177
+ const tracks = [];
178
+ const places = [];
179
+ rows.forEach((count, row) => {
180
+ const track = tracks.length + 1;
181
+ const height = `${width} / ${rects[row]}`;
182
+ if (count === 2)
183
+ tracks.push(`calc(${height})`);
184
+ else
185
+ tracks.push(`calc((${height} - var(--spacing)) / 2)`, `calc((${height} - var(--spacing)) / 2)`);
186
+ for (let i = 0; i < count; i++) {
187
+ if (count === 2)
188
+ places.push({ gridColumn: `${1 + 3 * i} / span 3`, gridRow: `${track}` });
189
+ else if (count === 4)
190
+ places.push({ gridColumn: `${1 + 3 * (i % 2)} / span 3`, gridRow: `${track + Math.floor(i / 2)}` });
191
+ else if (i === 0)
192
+ places.push({ gridColumn: '1 / span 4', gridRow: `${track} / span 2` });
193
+ else
194
+ places.push({ gridColumn: '5 / span 2', gridRow: `${track + i - 1}` });
195
+ }
196
+ });
197
+ return { style: { gridTemplateRows: tracks.join(' '), width }, places };
198
+ }
199
+ export function ImageGenTool({ call }) {
200
+ const t = useTranslations('imageGen');
201
+ // In a transcript turn, the turn says whether an open call still runs.
202
+ const live = useContext(TurnLiveContext);
203
+ const inTurn = useContext(InTranscriptTurnContext);
204
+ // Consecutive image_gen calls of a turn draw as one grid, here, at the first (R38).
205
+ const run = useContext(ImageGenRunsContext).get(call.id);
206
+ const views = useMemo(() => (run ? run.map(sessionLogOpenCall) : [call]).map((one) => imageGenView(one, inTurn ? live : undefined)), [run, call, inTurn, live]);
207
+ const grid = useMemo(() => imageGenGrid(views), [views]);
208
+ const view = views[0];
209
+ const solo = views.length === 1 && view.images.length === 1;
210
+ // One fix per card, even when several frames failed for the same reason.
211
+ const repairable = views.find((one) => one.error?.connectModel)?.error ??
212
+ views.flatMap((one) => one.images).find((image) => image.error?.connectModel)?.error;
213
+ const action = repairable ? _jsx(ConnectAction, { code: repairable.code, provider: repairable.provider }) : null;
214
+ // The card carries no prompt and no model (R29): the frames are the content,
215
+ // their status (busy, loading, an error) the only text.
216
+ if (views.length === 1 && !view.images.length) {
217
+ // The whole call failed or stopped.
218
+ return (_jsx("div", { className: "w-full max-w-md", children: _jsx(FailureNote, { error: view.error, action: action }) }));
219
+ }
220
+ const callIds = (run ?? [call]).map((one) => one.call_id);
221
+ const frame = ({ image, call: at, first }) => {
222
+ const callView = views[at];
223
+ const edit = callView.action === 'edit';
224
+ const seed = callIds[at];
225
+ const several = callView.images.length > 1;
226
+ return (_jsx(ImageGenFrame, { image: image, seed: seed, model: callView.model, fill: !solo,
227
+ // Each call's first frame carries its busy line, the one status region
228
+ // per call; the others show its glyph alone, hidden from assistive tech.
229
+ 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 }) })) }));
230
+ };
231
+ // A tile is keyed by its call and place in it: it keeps its frame (and its
232
+ // loaded image) while the run grows.
233
+ // A call's tiles are contiguous, so its place is the distance to its first tile.
234
+ const tileKey = (tile, i) => `${callIds[tile.call]}:${i - grid.tiles.findIndex((other) => other.call === tile.call)}`;
235
+ if (solo) {
236
+ 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] }));
237
+ }
238
+ const count = grid.tiles.length;
239
+ const bento = grid.rows.length === 1 ? BENTO[count] : null;
240
+ const rowRects = grid.rows.map((size, row) => {
241
+ const firstTile = grid.tiles[grid.rows.slice(0, row).reduce((sum, n) => sum + n, 0)];
242
+ return ratioValue(views[firstTile.call].aspectRatio) * BENTO[size].scale;
243
+ });
244
+ const placed = bento ? null : gridPlacement(grid.rows, rowRects);
245
+ return (
246
+ // An inline-size container: the merged grid sizes its rows from its width (`cqw`).
247
+ _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
248
  }
61
249
  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,