@kortix/ui 0.14.7 → 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 (576) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +64 -4
  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/runtime-versions.d.ts +4 -0
  7. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  8. package/dist/access/access/access-detail-shell.js +1 -1
  9. package/dist/access/access/access-dialog-share.js +4 -7
  10. package/dist/access/access/access-dialog.js +2 -1
  11. package/dist/access/access/principal-picker.d.ts +11 -0
  12. package/dist/access/access/principal-picker.js +9 -7
  13. package/dist/apps/app-preview-pool.d.ts +7 -2
  14. package/dist/apps/app-preview-pool.js +11 -5
  15. package/dist/apps/app-shared.d.ts +22 -15
  16. package/dist/apps/app-shared.js +37 -19
  17. package/dist/apps/index.d.ts +2 -2
  18. package/dist/apps/index.js +2 -2
  19. package/dist/artifacts/artifact-frame.d.ts +16 -0
  20. package/dist/artifacts/artifact-frame.js +51 -0
  21. package/dist/artifacts/artifact-session.d.ts +18 -0
  22. package/dist/artifacts/artifact-session.js +101 -0
  23. package/dist/artifacts/frame-policy.d.ts +30 -0
  24. package/dist/artifacts/frame-policy.js +61 -0
  25. package/dist/artifacts/index.d.ts +3 -0
  26. package/dist/artifacts/index.js +5 -0
  27. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  28. package/dist/browser/sandbox-browser-chrome.js +2 -2
  29. package/dist/customize/agents/agent-cover-card.d.ts +17 -0
  30. package/dist/customize/agents/agent-cover-card.js +13 -0
  31. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  32. package/dist/customize/agents/agent-grant-pages.js +30 -4
  33. package/dist/customize/agents/agent-page.js +8 -33
  34. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  35. package/dist/customize/agents/agent-policy-sets.js +72 -0
  36. package/dist/customize/agents/agent-triggers-section.js +2 -1
  37. package/dist/customize/agents/agents-page.js +43 -49
  38. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  39. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  40. package/dist/customize/connectors/agent-access.d.ts +35 -0
  41. package/dist/customize/connectors/agent-access.js +77 -0
  42. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  43. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  44. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  45. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  46. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  47. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  48. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  49. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  50. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  51. package/dist/customize/connectors/connector-identity.js +13 -42
  52. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  53. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  54. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  55. package/dist/customize/connectors/connector-routes.js +29 -20
  56. package/dist/customize/connectors/connectors-page.js +53 -82
  57. package/dist/customize/connectors/detail/app-page.js +226 -98
  58. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  59. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  60. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  61. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  62. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  63. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  64. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  65. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  66. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  67. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  68. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  69. package/dist/customize/connectors/detail/connector-page.js +14 -10
  70. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  71. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  72. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  73. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  74. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  75. package/dist/customize/connectors/detail/connector-status.js +34 -10
  76. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  77. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  78. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  79. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  80. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  81. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  82. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  83. package/dist/customize/connectors/detail/provider-info.js +2 -2
  84. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  85. package/dist/customize/connectors/detail/status-badge.js +4 -5
  86. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  87. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  88. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  89. package/dist/customize/connectors/install/install-dialog.js +40 -0
  90. package/dist/customize/connectors/install/install.d.ts +13 -2
  91. package/dist/customize/connectors/install/install.js +9 -4
  92. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  93. package/dist/customize/connectors/install/use-install.js +65 -37
  94. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  95. package/dist/customize/connectors/install/way-kind.js +16 -0
  96. package/dist/customize/connectors/provider-label.d.ts +2 -1
  97. package/dist/customize/connectors/provider-label.js +13 -3
  98. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  99. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  100. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  101. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  102. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  103. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  104. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  105. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  106. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  107. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  108. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  109. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  110. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  111. package/dist/customize/connectors/use-agent-access.js +72 -0
  112. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  113. package/dist/customize/migrate-to-v2/index.js +1 -2
  114. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -24
  115. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -235
  116. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  117. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  118. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  119. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  120. package/dist/customize/providers/provider-accordion.js +17 -2
  121. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  122. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  123. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  124. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  125. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  126. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  127. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  128. package/dist/customize/sections/component/channel-mocks.js +46 -0
  129. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  130. package/dist/customize/sections/component/channel-row.js +10 -4
  131. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  132. package/dist/customize/sections/component/email-connect-form.js +183 -0
  133. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  134. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  135. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  136. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  137. package/dist/customize/sections/component/telegram-channel-row.js +16 -25
  138. package/dist/customize/sections/connectors-view.d.ts +1 -15
  139. package/dist/customize/sections/connectors-view.js +81 -314
  140. package/dist/customize/sections/view/agent-editor-catalog.js +5 -0
  141. package/dist/customize/sections/view/channels-view.d.ts +5 -1
  142. package/dist/customize/sections/view/channels-view.js +63 -81
  143. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  144. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  145. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +1 -12
  146. package/dist/customize/shared/catalog/catalog-empty-state.js +3 -3
  147. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  148. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  149. package/dist/customize/shared/feature-gate-screen.js +27 -9
  150. package/dist/customize/shared/new-entity-menu.js +4 -1
  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/skills/skills-page.js +4 -5
  154. package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
  155. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  156. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  157. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  158. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  159. package/dist/customize/triggers/schedule/then-fields.js +1 -5
  160. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  161. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  162. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  163. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  164. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  165. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  166. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  167. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  168. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  169. package/dist/customize/triggers/schedule-view.js +9 -4
  170. package/dist/files/index.d.ts +1 -0
  171. package/dist/files/index.js +1 -0
  172. package/dist/files/project/change-request-recovery.d.ts +1 -26
  173. package/dist/files/project/change-request-recovery.js +1 -59
  174. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  175. package/dist/files/project/components/drive-explorer.js +15 -15
  176. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  177. package/dist/files/project/components/drive-toolbar.js +14 -5
  178. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  179. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  180. package/dist/files/project/hooks/use-change-requests.js +11 -2
  181. package/dist/files/renderers/image-frame.d.ts +46 -0
  182. package/dist/files/renderers/image-frame.js +59 -0
  183. package/dist/files/renderers/image-renderer.d.ts +11 -1
  184. package/dist/files/renderers/image-renderer.js +13 -3
  185. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  186. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  187. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  188. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  189. package/dist/files/renderers/show-content-renderer.js +56 -14
  190. package/dist/files/runtime/file-source.js +2 -0
  191. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  192. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  193. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  194. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  195. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  196. package/dist/files/viewer/file-content-renderer.js +50 -7
  197. package/dist/files/viewer/file-header.d.ts +7 -3
  198. package/dist/files/viewer/file-header.js +20 -11
  199. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  200. package/dist/files/viewer/file-preview-modal.js +10 -22
  201. package/dist/files/viewer/file-source.d.ts +13 -0
  202. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  203. package/dist/files/viewer/use-file-content-state.js +28 -10
  204. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  205. package/dist/files/viewer/viewer-actions.js +2 -2
  206. package/dist/hooks/use-media-query.d.ts +1 -0
  207. package/dist/hooks/use-mobile.d.ts +5 -0
  208. package/dist/hooks/use-mobile.js +8 -0
  209. package/dist/i18n/en.d.ts +906 -70
  210. package/dist/i18n/en.js +924 -88
  211. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  212. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  213. package/dist/index.d.ts +2 -2
  214. package/dist/index.js +2 -2
  215. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  216. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  217. package/dist/internal/account-hub/hub-sheet.js +21 -5
  218. package/dist/internal/account-hub/sections.d.ts +1 -1
  219. package/dist/internal/account-hub/sections.js +2 -1
  220. package/dist/internal/auth/auth-card-shell.js +3 -3
  221. package/dist/internal/components/agent-mark.d.ts +38 -0
  222. package/dist/internal/components/agent-mark.js +41 -0
  223. package/dist/internal/connector-logo/connector-logo-source.d.ts +63 -0
  224. package/dist/internal/connector-logo/connector-logo-source.js +48 -0
  225. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  226. package/dist/internal/connector-logo/connector-logo.js +56 -0
  227. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  228. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  229. package/dist/internal/files/file-read-retry.d.ts +13 -0
  230. package/dist/internal/files/file-read-retry.js +23 -3
  231. package/dist/internal/files/session-drive-files.d.ts +5 -1
  232. package/dist/internal/files/session-drive-files.js +7 -2
  233. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  234. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  235. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  236. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  237. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  238. package/dist/internal/hooks/index.d.ts +1 -1
  239. package/dist/internal/hooks/index.js +1 -1
  240. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  241. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  242. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  243. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  244. package/dist/internal/icons/telegram.d.ts +5 -0
  245. package/dist/internal/icons/telegram.js +6 -1
  246. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  247. package/dist/internal/layout/nav-hover-card.js +84 -0
  248. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  249. package/dist/internal/layout/project-nav-row.js +3 -2
  250. package/dist/internal/layout/project-page-header.d.ts +4 -2
  251. package/dist/internal/layout/project-page-header.js +4 -3
  252. package/dist/internal/layout/project-settings-nav.js +59 -2
  253. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  254. package/dist/internal/lib/browser-error-noise.js +1 -1
  255. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  256. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  257. package/dist/internal/lib/manifest-version.d.ts +1 -1
  258. package/dist/internal/lib/manifest-version.js +2 -2
  259. package/dist/internal/lib/memory-href.d.ts +16 -0
  260. package/dist/internal/lib/memory-href.js +46 -0
  261. package/dist/internal/lib/pixel-mark.d.ts +33 -0
  262. package/dist/internal/lib/pixel-mark.js +152 -0
  263. package/dist/internal/lib/use-project-feature-flags.js +11 -11
  264. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  265. package/dist/internal/lib/utils/heic-convert.js +3 -4
  266. package/dist/internal/lib/web-notifications.d.ts +20 -0
  267. package/dist/internal/lib/web-notifications.js +48 -4
  268. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  269. package/dist/internal/notifications/notification-bell.js +2 -2
  270. package/dist/internal/selection/selection-bar.d.ts +2 -1
  271. package/dist/internal/selection/selection-bar.js +1 -1
  272. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  273. package/dist/internal/stores/file-preview-store.js +19 -1
  274. package/dist/internal/stores/kortix-computer-store.js +3 -0
  275. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  276. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  277. package/dist/lib/routes.d.ts +13 -1
  278. package/dist/lib/routes.js +13 -0
  279. package/dist/markdown/genui/components/inline.d.ts +1 -1
  280. package/dist/markdown/index.d.ts +2 -1
  281. package/dist/markdown/index.js +2 -1
  282. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  283. package/dist/markdown/setup-links/approval-decision.js +6 -2
  284. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  285. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  286. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  287. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  288. package/dist/markdown/unified-markdown.js +5 -5
  289. package/dist/primitives/badge.d.ts +1 -1
  290. package/dist/primitives/badge.js +2 -0
  291. package/dist/primitives/disclosure.js +14 -2
  292. package/dist/primitives/empty-art.d.ts +12 -0
  293. package/dist/primitives/empty-art.js +11 -0
  294. package/dist/primitives/entity-avatar.d.ts +4 -1
  295. package/dist/primitives/entity-avatar.js +4 -2
  296. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  297. package/dist/primitives/mermaid-renderer.js +21 -15
  298. package/dist/primitives/resizable.js +6 -1
  299. package/dist/primitives/resize-seam.d.ts +11 -0
  300. package/dist/primitives/resize-seam.js +12 -0
  301. package/dist/primitives/sidebar-panel.js +4 -7
  302. package/dist/primitives/tabs.d.ts +14 -1
  303. package/dist/primitives/tabs.js +1 -1
  304. package/dist/primitives/user-avatar.d.ts +3 -1
  305. package/dist/primitives/user-avatar.js +4 -2
  306. package/dist/providers/ui-provider.d.ts +10 -1
  307. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  308. package/dist/session/composer/ComposerAboveCard.js +2 -2
  309. package/dist/session/composer/ComposerCard.d.ts +1 -1
  310. package/dist/session/composer/ComposerCard.js +3 -3
  311. package/dist/session/composer/agent-selector.d.ts +19 -1
  312. package/dist/session/composer/agent-selector.js +42 -12
  313. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  314. package/dist/session/composer/composer-agent-access.js +27 -0
  315. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  316. package/dist/session/composer/composer-chat-input.js +8 -6
  317. package/dist/session/composer/composer-logic.d.ts +16 -0
  318. package/dist/session/composer/composer-logic.js +12 -0
  319. package/dist/session/composer/composer-underbar.d.ts +3 -1
  320. package/dist/session/composer/composer-underbar.js +4 -3
  321. package/dist/session/composer/composer.d.ts +15 -1
  322. package/dist/session/composer/composer.js +19 -1
  323. package/dist/session/composer/context-usage.d.ts +5 -0
  324. package/dist/session/composer/context-usage.js +6 -1
  325. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  326. package/dist/session/composer/draft/composer-draft.js +5 -1
  327. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  328. package/dist/session/composer/token-progress.js +4 -4
  329. package/dist/session/header/export-transcript-modal.d.ts +3 -2
  330. package/dist/session/header/export-transcript-modal.js +6 -3
  331. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  332. package/dist/session/models/chatgpt-connection-button.js +54 -0
  333. package/dist/session/models/model-selector.d.ts +3 -1
  334. package/dist/session/models/model-selector.js +7 -3
  335. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  336. package/dist/session/models/use-model-connection-gate.js +5 -5
  337. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  338. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  339. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  340. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  341. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  342. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  343. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  344. package/dist/session/panel/easy/app-preview.js +31 -12
  345. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  346. package/dist/session/panel/easy/change-requests-card.js +17 -0
  347. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  348. package/dist/session/panel/easy/easy-panel.js +5 -2
  349. package/dist/session/panel/easy/file-preview.js +1 -1
  350. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  351. package/dist/session/panel/easy/outputs-card.js +3 -2
  352. package/dist/session/panel/easy/plan-card.d.ts +2 -0
  353. package/dist/session/panel/easy/plan-card.js +2 -0
  354. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  355. package/dist/session/panel/session-audit-panel.js +9 -2
  356. package/dist/session/panel/session-detail-panel.js +9 -3
  357. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  358. package/dist/session/panel/session-files-explorer.js +12 -3
  359. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  360. package/dist/session/panel/session-panel-provider.js +32 -7
  361. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  362. package/dist/session/panel/shared/derive-panels.js +12 -2
  363. package/dist/session/panel/shared/output-priority.js +2 -0
  364. package/dist/session/participants/session-participants.d.ts +5 -1
  365. package/dist/session/participants/session-participants.js +9 -2
  366. package/dist/session/prompts/approval-request.d.ts +5 -0
  367. package/dist/session/prompts/approval-request.js +7 -1
  368. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  369. package/dist/session/prompts/session-approval-review.js +18 -0
  370. package/dist/session/status/session-error-banner.js +2 -49
  371. package/dist/session/status/session-starting-loader.d.ts +14 -2
  372. package/dist/session/status/session-starting-loader.js +16 -4
  373. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  374. package/dist/session/thread/after-first-prompt.js +8 -0
  375. package/dist/session/thread/detect-command.d.ts +12 -0
  376. package/dist/session/thread/detect-command.js +20 -0
  377. package/dist/session/thread/plan-surface.d.ts +1 -0
  378. package/dist/session/thread/plan-surface.js +1 -0
  379. package/dist/session/thread/session-chat.d.ts +3 -1
  380. package/dist/session/thread/session-chat.js +377 -252
  381. package/dist/session/thread/session-context-metrics.d.ts +15 -0
  382. package/dist/session/thread/session-context-metrics.js +10 -1
  383. package/dist/session/thread/session-context-modal.d.ts +4 -2
  384. package/dist/session/thread/session-context-modal.js +16 -9
  385. package/dist/session/thread/session-thread.d.ts +3 -1
  386. package/dist/session/thread/session-thread.js +9 -2
  387. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  388. package/dist/session/thread/thread-boot-rows.js +89 -0
  389. package/dist/session/thread/transcript-rows.d.ts +31 -0
  390. package/dist/session/thread/transcript-rows.js +3 -0
  391. package/dist/session/thread/transcript.d.ts +4 -9
  392. package/dist/session/thread/transcript.js +119 -21
  393. package/dist/session/thread/turn-share.d.ts +16 -0
  394. package/dist/session/thread/turn-share.js +162 -0
  395. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  396. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  397. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  398. package/dist/session/tool/tool-part-renderer.js +8 -3
  399. package/dist/session/tool/tools/apply-patch-tool.d.ts +1 -0
  400. package/dist/session/tool/tools/apply-patch-tool.js +1 -0
  401. package/dist/session/tool/tools/bash-tool.js +7 -6
  402. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  403. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  404. package/dist/session/tool/tools/codemode-tool.js +1 -1
  405. package/dist/session/tool/tools/connector-tools.js +1 -1
  406. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  407. package/dist/session/tool/tools/image-gen-tool.js +240 -53
  408. package/dist/session/tool/tools/pty-kill-tool.d.ts +1 -0
  409. package/dist/session/tool/tools/pty-kill-tool.js +1 -0
  410. package/dist/session/tool/tools/pty-read-tool.d.ts +2 -0
  411. package/dist/session/tool/tools/pty-read-tool.js +2 -0
  412. package/dist/session/tool/tools/pty-spawn-tool.d.ts +1 -0
  413. package/dist/session/tool/tools/pty-spawn-tool.js +1 -0
  414. package/dist/session/tool/tools/pty-write-tool.d.ts +1 -0
  415. package/dist/session/tool/tools/pty-write-tool.js +1 -0
  416. package/dist/session/tool/tools/show-tool.js +19 -8
  417. package/dist/session/tool/tools/todo-write-tool.d.ts +1 -0
  418. package/dist/session/tool/tools/todo-write-tool.js +1 -0
  419. package/dist/session/turn/channel-brand.d.ts +8 -3
  420. package/dist/session/turn/channel-brand.js +20 -4
  421. package/dist/session/turn/message-author-label.js +6 -2
  422. package/dist/session/turn/message-author.d.ts +8 -0
  423. package/dist/session/turn/message-author.js +24 -0
  424. package/dist/session/turn/message-row.d.ts +52 -0
  425. package/dist/session/turn/message-row.js +44 -0
  426. package/dist/session/turn/plan-anchor.d.ts +4 -1
  427. package/dist/session/turn/plan-anchor.js +4 -1
  428. package/dist/session/turn/plan-card.d.ts +7 -0
  429. package/dist/session/turn/plan-card.js +7 -0
  430. package/dist/session/turn/user-message.d.ts +7 -1
  431. package/dist/session/turn/user-message.js +21 -7
  432. package/dist/styles.css +1 -1
  433. package/dist/terminal/session-terminal-connect-bar.js +2 -1
  434. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  435. package/dist/workspace/home/access-requests-bell.js +20 -6
  436. package/dist/workspace/home/first-chat.d.ts +8 -21
  437. package/dist/workspace/home/first-chat.js +22 -72
  438. package/dist/workspace/index.d.ts +6 -0
  439. package/dist/workspace/index.js +6 -0
  440. package/dist/workspace/layout/project-home.d.ts +14 -2
  441. package/dist/workspace/layout/project-home.js +60 -21
  442. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  443. package/dist/workspace/layout/use-project-home-send.js +82 -3
  444. package/dist/workspace/memory/body-doc.d.ts +17 -0
  445. package/dist/workspace/memory/body-doc.js +208 -0
  446. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  447. package/dist/workspace/memory/body-extensions.js +103 -0
  448. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  449. package/dist/workspace/memory/company-memory-page.js +16 -0
  450. package/dist/workspace/memory/memory-all.d.ts +20 -0
  451. package/dist/workspace/memory/memory-all.js +27 -0
  452. package/dist/workspace/memory/memory-body.d.ts +19 -0
  453. package/dist/workspace/memory/memory-body.js +139 -0
  454. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  455. package/dist/workspace/memory/memory-empty.js +28 -0
  456. package/dist/workspace/memory/memory-history.d.ts +27 -0
  457. package/dist/workspace/memory/memory-history.js +108 -0
  458. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  459. package/dist/workspace/memory/memory-labels.js +47 -0
  460. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  461. package/dist/workspace/memory/memory-page-list.js +156 -0
  462. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  463. package/dist/workspace/memory/memory-reader.js +123 -0
  464. package/dist/workspace/memory/memory-view.d.ts +21 -0
  465. package/dist/workspace/memory/memory-view.js +124 -0
  466. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  467. package/dist/workspace/memory/remember-popover.js +61 -0
  468. package/dist/workspace/memory/remember-this.d.ts +12 -0
  469. package/dist/workspace/memory/remember-this.js +89 -0
  470. package/dist/workspace/memory/source-mark.d.ts +18 -0
  471. package/dist/workspace/memory/source-mark.js +79 -0
  472. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  473. package/dist/workspace/memory/used-memory-chip.js +61 -0
  474. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  475. package/dist/workspace/new/advanced-fields.js +2 -2
  476. package/dist/workspace/new/source-param.d.ts +1 -1
  477. package/dist/workspace/new/source-param.js +3 -1
  478. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  479. package/dist/workspace/new/use-create-workspace.js +3 -3
  480. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  481. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  482. package/dist/workspace/projects/policies-panel.js +5 -3
  483. package/dist/workspace/review/review-actions.d.ts +4 -2
  484. package/dist/workspace/review/review-actions.js +8 -2
  485. package/dist/workspace/review/review-center.js +11 -7
  486. package/dist/workspace/review/review-detail.d.ts +10 -0
  487. package/dist/workspace/review/review-detail.js +101 -13
  488. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  489. package/dist/workspace/saved-session-skeleton.js +3 -3
  490. package/dist/workspace/session-workspace.js +15 -13
  491. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  492. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  493. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  494. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  495. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  496. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  497. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  498. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  499. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  500. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  501. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  502. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  503. package/dist/workspace/sidebar/project-session-list.js +68 -56
  504. package/dist/workspace/sidebar/project-sidebar.js +9 -2
  505. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  506. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  507. package/dist/workspace/sidebar/session-brief-hover-card.js +28 -1
  508. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  509. package/dist/workspace/sidebar/session-group-order.js +25 -0
  510. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  511. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  512. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  513. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  514. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  515. package/dist/workspace/spaces/channel-glyph.js +6 -0
  516. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  517. package/dist/workspace/spaces/channel-setup.js +105 -0
  518. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  519. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  520. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  521. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  522. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  523. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  524. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  525. package/dist/workspace/spaces/space-agents.js +10 -0
  526. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  527. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  528. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  529. package/dist/workspace/spaces/space-link-label.js +73 -0
  530. package/dist/workspace/spaces/space-links.d.ts +19 -0
  531. package/dist/workspace/spaces/space-links.js +230 -0
  532. package/dist/workspace/spaces/space-members.d.ts +46 -0
  533. package/dist/workspace/spaces/space-members.js +182 -0
  534. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  535. package/dist/workspace/spaces/space-roster.js +44 -0
  536. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  537. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  538. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  539. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  540. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  541. package/dist/workspace/spaces/space-timeline.js +183 -0
  542. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  543. package/dist/workspace/spaces/space-triggers.js +78 -0
  544. package/dist/workspace/spaces/space-view.d.ts +37 -0
  545. package/dist/workspace/spaces/space-view.js +436 -0
  546. package/package.json +31 -32
  547. package/skills/kortix-ui/SKILL.md +3 -3
  548. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  549. package/skills/kortix-ui/references/modules.md +28 -4
  550. package/skills/kortix-ui/references/theming.md +1 -1
  551. package/dist/customize/agents/agent-nav.prototype.d.ts +0 -35
  552. package/dist/customize/agents/agent-nav.prototype.js +0 -95
  553. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  554. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  555. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  556. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  557. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  558. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  559. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  560. package/dist/customize/sections/connector-connection-header.js +0 -33
  561. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  562. package/dist/customize/sections/connector-connection-modal.js +0 -72
  563. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  564. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  565. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  566. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  567. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  568. package/dist/customize/sections/discover-catalogue.js +0 -132
  569. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  570. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  571. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  572. package/dist/files/project/components/drive-empty-art.js +0 -5
  573. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  574. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  575. package/dist/internal/share/public-share-link-button.js +0 -17
  576. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -13,11 +13,19 @@ import { UnifiedMarkdown } from '../../markdown/unified-markdown.js';
13
13
  import { detectCommandFromText } from './detect-command.js';
14
14
  import { GenuiTelemetryContext } from '../../markdown/genui/block-telemetry.js';
15
15
  import { copyGenuiText } from '../../markdown/genui/to-markdown.js';
16
- import { useTranslations } from '../../i18n/index.js';
16
+ import { useLocale, useTranslations } from '../../i18n/index.js';
17
17
  import { isSessionLogRestoreNote, sessionLogActivityText, sessionLogAnsweredQuestionCall, sessionLogBurstSteps, sessionLogOpenCall, sessionLogTurnSegments, sessionPromptActions, splitSessionLogTurnWork, toolCallMetadata, toolKind, } from '@kortix/sdk';
18
18
  import { WarningIcon as AlertTriangle, CheckCircleIcon as CheckCircle, CheckIcon, CaretDownIcon as ChevronDown, ArrowSquareOutIcon as ExternalLink, StopCircleIcon, } from '@phosphor-icons/react';
19
19
  import { AnimatePresence, m } from 'motion/react';
20
- import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
20
+ import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
21
+ import { AfterFirstPromptContext } from './after-first-prompt.js';
22
+ import { TranscriptRowsContext } from './transcript-rows.js';
23
+ import { AgentBusyRow } from './thread-boot-rows.js';
24
+ import { MessageRow } from '../turn/message-row.js';
25
+ import { agentDisplayLabel } from '../composer/agent-selector.js';
26
+ import { participantLabel } from '../participants/session-participants.js';
27
+ import { AgentMark } from '../../internal/components/agent-mark.js';
28
+ import { UserAvatar } from '../../primitives/user-avatar.js';
21
29
  import { stripSystemPtyText, } from './message-parsing.js';
22
30
  import { ActivityBurst } from '../turn/activity-burst.js';
23
31
  import { TurnWorkAccordion } from '../turn/turn-work-accordion.js';
@@ -37,13 +45,15 @@ import { SessionRetryDisplay, TurnErrorDisplay } from '../status/session-error-b
37
45
  import { showTurnBusyIndicator } from '@kortix/sdk';
38
46
  import { SessionBusyIndicator } from '../status/session-busy-indicator.js';
39
47
  import { SessionTurnMeta } from './session-turn-meta.js';
48
+ import { TurnShareButton } from './turn-share.js';
40
49
  import { sessionTurnDurationMs, sessionTurnEndedAt, sessionTurnSpan, } from './session-turn-meta-rows.js';
41
50
  import { Button } from '../../primitives/button.js';
42
51
  import { Disclosure, DisclosureContent, DisclosureTrigger } from '../../primitives/disclosure.js';
43
52
  import { useUserPreferencesStore } from '../../internal/stores/user-preferences-store.js';
44
53
  import { SubSessionModal } from './sub-session-modal.js';
45
54
  import { ToolPartRenderer, TurnLiveContext } from '../tool/tool-renderers.js';
46
- import { RecoveredCallsContext } from '../tool/shared/infrastructure.js';
55
+ import { ImageGenDigestsContext, ImageGenPathsContext, ImageGenRunsContext, InTranscriptTurnContext, RecoveredCallsContext, } from '../tool/shared/infrastructure.js';
56
+ import { imageDigestsShownByImageGen, imagePathsShownByImageGen, sessionLogImageGenRuns, showDrawnByImageGen } from '@kortix/sdk';
47
57
  import { recoveredShellFailures } from '../turn/recovered-failures.js';
48
58
  import { cn } from '../../lib/utils.js';
49
59
  import { extractKortixSystemMessages, extractSessionReport, stripKortixSystemTags, } from '../../internal/lib/utils/kortix-system-tags.js';
@@ -54,6 +64,8 @@ import { isAbortError, turnEndNotice, } from '@kortix/sdk';
54
64
  import { isOptimisticSessionPrompt } from '@kortix/sdk/react';
55
65
  import { CodeBlockEndpoints, SandboxUrlDetector } from '../media/sandbox-url-detector.js';
56
66
  import { HarnessSwitchMarker, RestoreNoteMarker, TurnFullText } from './session-history.js';
67
+ /** The agent whose mark stands in when a row does not name its agent. */
68
+ const DEFAULT_AGENT_SLUG = 'kortix';
57
69
  // ============================================================================
58
70
  // Optimistic answers cache
59
71
  // ============================================================================
@@ -108,7 +120,7 @@ function SystemMessageIndicator({ messages }) {
108
120
  // Combine all messages into a single line: "Goal · iteration 3/50"
109
121
  const parts = messages.map((msg) => (msg.detail ? `${msg.label} · ${msg.detail}` : msg.label));
110
122
  const text = parts.join(' · ');
111
- return (_jsxs("div", { className: "-my-1 flex items-center gap-2", children: [_jsx("div", { className: "bg-border/30 h-px flex-1" }), _jsx("span", { className: "text-muted-foreground/30 text-xs whitespace-nowrap select-none", children: text }), _jsx("div", { className: "bg-border/30 h-px flex-1" })] }));
123
+ return (_jsxs("div", { className: "-my-1 flex items-center gap-2", children: [_jsx("div", { className: "bg-border/30 h-px flex-1" }), _jsx("span", { className: "text-muted-foreground text-xs whitespace-nowrap select-none", children: text }), _jsx("div", { className: "bg-border/30 h-px flex-1" })] }));
112
124
  }
113
125
  // ============================================================================
114
126
  // Answered question card — collapsible summary of completed Q&A
@@ -232,7 +244,7 @@ export function SessionReportCard({ report, onOpen, }) {
232
244
  return (
233
245
  // A real <button>: Enter, Space and the focus ring come free, where the
234
246
  // previous role="button" div hand-rolled Enter only.
235
- _jsxs("button", { type: "button", onClick: onOpen, className: "group/report bg-popover hover:bg-accent/40 flex w-full items-center gap-3 rounded-md border px-3 py-2 text-left transition-colors active:scale-[0.99]", children: [_jsx("span", { className: cn('flex size-8 shrink-0 items-center justify-center rounded-sm', complete ? 'bg-kortix-green/15' : 'bg-kortix-red/15'), children: complete ? (_jsx(CheckCircle, { className: "text-kortix-green size-4" })) : (_jsx(AlertTriangle, { className: "text-kortix-red size-4" })) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "text-foreground block truncate text-sm font-medium", children: [tI18nComplete.raw('texta67b04cd5c49'), " ", complete ? 'complete' : 'failed'] }), (report.project || report.prompt) && (_jsxs("span", { className: "text-muted-foreground block truncate text-xs", children: [report.project, report.project && report.prompt && (_jsxs("span", { className: "text-muted-foreground/40", children: [' ', tI18nComplete.raw('text3b9453dad42b'), ' '] })), report.prompt] }))] }), _jsx(ExternalLink, { className: "text-muted-foreground/40 group-hover/report:text-muted-foreground size-3.5 shrink-0 transition-colors" })] }));
247
+ _jsxs("button", { type: "button", onClick: onOpen, className: "group/report bg-popover hover:bg-accent/40 flex w-full items-center gap-3 rounded-md border px-3 py-2 text-left transition-colors active:scale-[0.99]", children: [_jsx("span", { className: cn('flex size-8 shrink-0 items-center justify-center rounded-sm', complete ? 'bg-kortix-green/15' : 'bg-kortix-red/15'), children: complete ? (_jsx(CheckCircle, { className: "text-kortix-green size-4" })) : (_jsx(AlertTriangle, { className: "text-kortix-red size-4" })) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "text-foreground block truncate text-sm font-medium", children: [tI18nComplete.raw('texta67b04cd5c49'), " ", complete ? 'complete' : 'failed'] }), (report.project || report.prompt) && (_jsxs("span", { className: "text-muted-foreground block truncate text-xs", children: [report.project, report.project && report.prompt && (_jsxs("span", { className: "text-muted-foreground", children: [' ', tI18nComplete.raw('text3b9453dad42b'), ' '] })), report.prompt] }))] }), _jsx(ExternalLink, { className: "text-muted-foreground group-hover/report:text-foreground size-3.5 shrink-0 transition-colors" })] }));
236
248
  }
237
249
  /**
238
250
  * The error a turn renders, which also hides its own Thinking row: the first
@@ -658,6 +670,8 @@ function useTurnUserContent({ turn, commandMessages, commands, }) {
658
670
  const commandOutput = useMemo(() => {
659
671
  if (!commandForTurn)
660
672
  return undefined;
673
+ if ('source' in commandForTurn && commandForTurn.source === 'skill')
674
+ return undefined;
661
675
  const source = Array.isArray(commands) ? commands.find((c) => c.name === commandForTurn.name)?.source : undefined;
662
676
  return source === 'skill' ? undefined : commandForTurn;
663
677
  }, [commandForTurn, commands]);
@@ -898,7 +912,10 @@ function useTurnSegments({ blocks, answeredQuestionCallsById, shouldUseInlineCon
898
912
  // - While working: it renders INSIDE steps as a regular text part (hideResponsePart=false)
899
913
  // - When done: it's HIDDEN from steps (hideResponsePart=true) and shown below as Response
900
914
  // ============================================================================
901
- /** Shell mode — a live shell tool replaces the whole turn scaffold. */
915
+ /**
916
+ * Shell mode — a live shell tool replaces the whole turn scaffold.
917
+ * @deprecated Renders an OpenCode shell turn (session.shell; pi has none). OpenCode is sunset (2026-10-23): no new code; delete with OpenCode.
918
+ */
902
919
  function TurnShellMode(props) {
903
920
  const { call, working, providers, errors, connectProviderOpen, onConnectProviderOpenChange, permissions, sessionId, disableToolNavigation, onPermissionReply, } = props;
904
921
  // Permission matching for this session (used for tool-level permission overlays)
@@ -978,6 +995,19 @@ function TurnToolBlocks(props) {
978
995
  const split = useMemo(() => (fold && !working ? splitSessionLogTurnWork(segments.filter(segmentRendersSomething), { working }) : null), [fold, segments, working]);
979
996
  // Settled turns only: while the turn runs, the next step has not happened yet.
980
997
  const recovered = useMemo(() => (working ? NO_RECOVERED_CALLS : recoveredShellFailures(turnBlocks(turn))), [turn, working]);
998
+ // D5: a `show` of an image this turn's `image_gen` already drew does not draw it again.
999
+ // Read from the segments, not the raw blocks: a script's nested call (a v2 `nested_part`
1000
+ // block) is a real `image_gen` call there. Keyed by its content so the context keeps one
1001
+ // identity across stream frames.
1002
+ // R38: the same bytes at another path (a Drive copy) count too, by sha256.
1003
+ const [imageGenPathsKey, imageGenDigestsKey] = useMemo(() => {
1004
+ const blocks = segments.flatMap((s) => (s.kind === 'burst' || s.kind === 'show-group' ? s.blocks : [s.block]));
1005
+ return [[...imagePathsShownByImageGen(blocks)].join('\n'), [...imageDigestsShownByImageGen(blocks)].join('\n')];
1006
+ }, [segments]);
1007
+ const imageGenPaths = useMemo(() => new Set(imageGenPathsKey ? imageGenPathsKey.split('\n') : []), [imageGenPathsKey]);
1008
+ const imageGenDigests = useMemo(() => new Set(imageGenDigestsKey ? imageGenDigestsKey.split('\n') : []), [imageGenDigestsKey]);
1009
+ // R38: consecutive image_gen deliverables draw as one grid at the first call, live and settled.
1010
+ const imageGenRuns = useMemo(() => sessionLogImageGenRuns(segments, { paths: imageGenPaths, digests: imageGenDigests }), [segments, imageGenPaths, imageGenDigests]);
981
1011
  const renderSegment = (segment) => {
982
1012
  const key = turnSegmentKey(segment);
983
1013
  if (key === null)
@@ -990,13 +1020,13 @@ function TurnToolBlocks(props) {
990
1020
  // will. Provided here rather than per-row because `working` is a fact
991
1021
  // about the TURN, and this block is the turn's whole part tree.
992
1022
  // See `TurnLiveContext`.
993
- _jsx(TurnLiveContext.Provider, { value: working, children: _jsx(RecoveredCallsContext.Provider, { value: recovered, children: _jsx("div", { className: "space-y-3", children: split
994
- ? [
995
- _jsx(TurnWorkAccordion, { durationMs: durationMs, children: split.work.map(renderSegment) }, "turn-work"),
996
- ...split.hoisted.map(renderSegment),
997
- ...split.final.map(renderSegment),
998
- ]
999
- : segments.map(renderSegment) }) }) })) }));
1023
+ _jsx(TurnLiveContext.Provider, { value: working, children: _jsx(RecoveredCallsContext.Provider, { value: recovered, children: _jsx(ImageGenPathsContext.Provider, { value: imageGenPaths, children: _jsx(ImageGenDigestsContext.Provider, { value: imageGenDigests, children: _jsx(ImageGenRunsContext.Provider, { value: imageGenRuns, children: _jsx(InTranscriptTurnContext.Provider, { value: true, children: _jsx("div", { className: "space-y-3", children: split
1024
+ ? [
1025
+ _jsx(TurnWorkAccordion, { durationMs: durationMs, children: split.work.map(renderSegment) }, "turn-work"),
1026
+ ...split.hoisted.map(renderSegment),
1027
+ ...split.final.map(renderSegment),
1028
+ ]
1029
+ : segments.map(renderSegment) }) }) }) }) }) }) })) }));
1000
1030
  }
1001
1031
  /** One segment of the turn's steps section: a burst, a show group, a
1002
1032
  * standalone deliverable, or prose between bursts. Keyed by the first
@@ -1019,18 +1049,30 @@ function segmentRendersSomething(segment) {
1019
1049
  return turnSegmentKey(segment) !== null;
1020
1050
  }
1021
1051
  function TurnSegment({ segment, isTrailing, working, openText, hasSteps, sessionId, permissions, onPermissionReply, disableNavigation, conversationDensity, }) {
1052
+ // A `show` whose every file this turn's `image_gen` already drew renders nothing,
1053
+ // not even ToolPartRenderer's wrapper (it would leave a gap in the stack).
1054
+ const imageGenPaths = useContext(ImageGenPathsContext);
1055
+ const imageGenDigests = useContext(ImageGenDigestsContext);
1056
+ const imageGenRuns = useContext(ImageGenRunsContext);
1057
+ const drawnByImageGen = (call) => showDrawnByImageGen(call, imageGenPaths, imageGenDigests);
1022
1058
  if (segment.kind === 'burst') {
1023
1059
  return (_jsx(ActivityBurst, { blocks: segment.blocks, sessionId: sessionId, working: working, isTrailing: isTrailing, disableNavigation: disableNavigation, density: conversationDensity }));
1024
1060
  }
1025
1061
  if (segment.kind === 'show-group') {
1026
- const visible = segment.blocks.filter(shouldShowToolPart);
1062
+ const visible = segment.blocks.filter((block) => shouldShowToolPart(block) && !drawnByImageGen(block));
1063
+ if (visible.length === 0)
1064
+ return null;
1027
1065
  if (visible.length === 1) {
1028
1066
  return (_jsx(ToolPartRenderer, { call: visible[0], sessionId: sessionId, disableNavigation: disableNavigation }));
1029
1067
  }
1030
1068
  return _jsx(ShowGroupRenderer, { calls: visible, sessionId: sessionId, disableNavigation: disableNavigation });
1031
1069
  }
1032
1070
  if (segment.kind === 'standalone') {
1033
- if (!shouldShowToolPart(segment.block))
1071
+ if (!shouldShowToolPart(segment.block) || drawnByImageGen(segment.block))
1072
+ return null;
1073
+ // A later call of an image_gen run draws in the first call's grid (R38).
1074
+ const run = imageGenRuns.get(segment.block.id);
1075
+ if (run && run[0] !== segment.block)
1034
1076
  return null;
1035
1077
  return (_jsx(ToolPartRenderer, { call: segment.block, sessionId: sessionId, disableNavigation: disableNavigation, permission: getPermissionForTool(permissions, segment.block.call_id), onPermissionReply: onPermissionReply }));
1036
1078
  }
@@ -1088,13 +1130,22 @@ function TurnAutoRetryNote({ count }) {
1088
1130
  /** The turn's footer: the working row, the error banner, the outcomes, the
1089
1131
  * action bar, the connect-provider dialog, and who stopped the turn. */
1090
1132
  function TurnFooter(props) {
1091
- const { turn, providers, model, errors, answered, status, retry, meta, tHardcodedUi, connectProviderOpen, onConnectProviderOpenChange, servedModel, stoppedBy, modelOptions, } = props;
1133
+ const { turn, providers, model, errors, answered, status, retry, meta, tHardcodedUi, connectProviderOpen, onConnectProviderOpenChange, servedModel, stoppedBy, modelOptions, projectId, projectSessionId, } = props;
1092
1134
  const { working, response } = model;
1093
1135
  const { turnError, turnErrorRow, turnErrorRowDetails, turnErrorRaw } = errors;
1094
1136
  const { statusPhrase, statusElapsedLabel } = status;
1095
1137
  const { retryInfo, retryMessage, retrySecondsLeft } = retry;
1096
1138
  const { turnEndedAt, turnDurationMs, costInfo } = meta;
1097
- return (_jsxs(_Fragment, { children: [_jsx(TurnBusyRow, { ...props, working: working, turnError: turnError, tHardcodedUi: tHardcodedUi }), turnErrorRow.text && !turn.autoRetry?.continued && (_jsx(TurnErrorDisplay, { errorText: turnErrorRow.text, errorDetails: turnErrorRowDetails, errorRaw: turnErrorRaw, isAbort: turnErrorRow.isAbort, modelOptions: modelOptions })), turnErrorRow.text && !turnErrorRow.isAbort && !turn.autoRetry?.continued && !!turn.autoRetry?.retries && (_jsx(TurnAutoRetryNote, { count: turn.autoRetry.retries })), !working && !turn.autoRetry?.continued && (stoppedBy || errors.turnErrorIsAbort) && _jsx(TurnStoppedBy, { name: stoppedBy ?? undefined }), !working && _jsx(TurnOutcomes, { turnKey: turn.id }), !working && (_jsx(TurnActionBar, { response: response, inlineContentParts: answered.inlineContentParts, turnEndedAt: turnEndedAt, turnDurationMs: turnDurationMs, costInfo: costInfo, servedModel: servedModel, tHardcodedUi: tHardcodedUi })), _jsx(ConnectProviderDialog, { open: connectProviderOpen, onOpenChange: onConnectProviderOpenChange, providers: providers })] }));
1139
+ return (_jsxs(_Fragment, { children: [_jsx(TurnBusyRow, { ...props, working: working, turnError: turnError, tHardcodedUi: tHardcodedUi }), turnErrorRow.text && !turn.autoRetry?.continued && (_jsx(TurnErrorDisplay, { errorText: turnErrorRow.text, errorDetails: turnErrorRowDetails, errorRaw: turnErrorRaw, isAbort: turnErrorRow.isAbort, modelOptions: modelOptions })), turnErrorRow.text && !turnErrorRow.isAbort && !turn.autoRetry?.continued && !!turn.autoRetry?.retries && (_jsx(TurnAutoRetryNote, { count: turn.autoRetry.retries })), !working && !turn.autoRetry?.continued && (stoppedBy || errors.turnErrorIsAbort) && _jsx(TurnStoppedBy, { name: stoppedBy ?? undefined }), !working && _jsx(TurnOutcomes, { turnKey: turn.id }), !working && !props.hideActionBar && (_jsx(TurnActionBar, { response: response, inlineContentParts: answered.inlineContentParts, turnEndedAt: turnEndedAt, turnDurationMs: turnDurationMs, costInfo: costInfo, servedModel: servedModel, tHardcodedUi: tHardcodedUi,
1140
+ // A continuation turn's id names a compaction marker, not a user
1141
+ // message, so it has no response of its own to share.
1142
+ share: turn.continues
1143
+ ? undefined
1144
+ : {
1145
+ projectId,
1146
+ sessionId: projectSessionId,
1147
+ turnId: turn.id,
1148
+ } })), _jsx(ConnectProviderDialog, { open: connectProviderOpen, onOpenChange: onConnectProviderOpenChange, providers: providers })] }));
1098
1149
  }
1099
1150
  /** The working turn's waiting row: the retry banner and the busy indicator. */
1100
1151
  function TurnBusyRow(props) {
@@ -1112,7 +1163,7 @@ function TurnBusyRow(props) {
1112
1163
  }
1113
1164
  /** Copy + the turn's settled meta row — the hover-revealed bar at the end of
1114
1165
  * a settled turn. Owns the copy state: it is the only consumer. */
1115
- function TurnActionBar({ response, inlineContentParts, turnEndedAt, turnDurationMs, costInfo, servedModel, tHardcodedUi, }) {
1166
+ function TurnActionBar({ response, inlineContentParts, turnEndedAt, turnDurationMs, costInfo, servedModel, tHardcodedUi, inToolbar = false, share, }) {
1116
1167
  const [copied, setCopied] = useState(false);
1117
1168
  // ---- Copy response ----
1118
1169
  const handleCopy = async () => {
@@ -1138,11 +1189,29 @@ function TurnActionBar({ response, inlineContentParts, turnEndedAt, turnDuration
1138
1189
  // The browser refused the write; `copied` stays false.
1139
1190
  }
1140
1191
  };
1141
- return (_jsxs("div", { className: "duration-normal flex items-center gap-0.5 opacity-0 transition-opacity group-hover/turn:opacity-100 focus-within:opacity-100 has-[[data-state=open]]:opacity-100 max-md:opacity-100", children: [response ? (_jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleCopy, "aria-label": copied ? 'Copied' : tHardcodedUi.raw('i18nComplete.textf0f755afea88'), className: "hit-area-3", children: _jsx("span", { className: "relative inline-flex shrink-0 items-center justify-center", children: _jsx(AnimatePresence, { initial: false, mode: "popLayout", children: _jsx(m.span, { initial: { scale: 0.25, opacity: 0, filter: 'blur(4px)' }, animate: { scale: 1, opacity: 1, filter: 'blur(0px)' }, exit: { scale: 0.25, opacity: 0, filter: 'blur(4px)' }, transition: { type: 'spring', duration: 0.3, bounce: 0 }, className: "absolute inset-0 inline-flex items-center justify-center", children: copied ? (_jsx(CheckIcon, { className: "text-muted-foreground size-[1.05rem]" })) : (_jsx(Copy, { className: "text-muted-foreground size-[1.05rem]" })) }, copied ? 'check' : 'copy') }) }) })) : null, _jsx(SessionTurnMeta, { endedAt: turnEndedAt, durationMs: turnDurationMs, cost: costInfo, served: servedModel, className: "flex items-center justify-center" })] }));
1192
+ return (_jsxs("div", { className: cn('flex items-center gap-0.5', !inToolbar &&
1193
+ 'duration-normal opacity-0 transition-opacity group-hover/turn:opacity-100 focus-within:opacity-100 has-[[data-state=open]]:opacity-100 max-md:opacity-100'), children: [response ? (_jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleCopy, "aria-label": copied ? 'Copied' : tHardcodedUi.raw('i18nComplete.textf0f755afea88'), className: "hit-area-3", children: _jsx("span", { className: "relative inline-flex shrink-0 items-center justify-center", children: _jsx(AnimatePresence, { initial: false, mode: "popLayout", children: _jsx(m.span, { initial: { scale: 0.25, opacity: 0, filter: 'blur(4px)' }, animate: { scale: 1, opacity: 1, filter: 'blur(0px)' }, exit: { scale: 0.25, opacity: 0, filter: 'blur(4px)' }, transition: { type: 'spring', duration: 0.3, bounce: 0 }, className: "absolute inset-0 inline-flex items-center justify-center", children: copied ? (_jsx(CheckIcon, { className: cn('text-muted-foreground', inToolbar ? 'size-3.5' : 'size-[1.05rem]') })) : (_jsx(Copy, { className: cn('text-muted-foreground', inToolbar ? 'size-3.5' : 'size-[1.05rem]') })) }, copied ? 'check' : 'copy') }) }) })) : null, response && share ? (_jsx(TurnShareButton, { projectId: share.projectId, sessionId: share.sessionId, turnId: share.turnId })) : null, _jsx(SessionTurnMeta, { endedAt: turnEndedAt, durationMs: turnDurationMs, cost: costInfo, served: servedModel,
1194
+ // `icon-sm`, the same as the copy button beside it; in a row's
1195
+ // toolbar its dots match the 14px icons of the toolbar.
1196
+ className: cn('flex items-center justify-center', inToolbar && '[&_svg]:size-4!') })] }));
1197
+ }
1198
+ /** A row's time: "1:44 AM" beside the name, the full date on hover. Null without a stamp. */
1199
+ function rowTime(at, locale) {
1200
+ if (!Number.isFinite(at) || at <= 0)
1201
+ return null;
1202
+ const date = new Date(at);
1203
+ return {
1204
+ iso: date.toISOString(),
1205
+ label: date.toLocaleTimeString(locale, { hour: 'numeric', minute: '2-digit' }),
1206
+ title: date.toLocaleString(locale, { dateStyle: 'full', timeStyle: 'short' }),
1207
+ };
1142
1208
  }
1143
1209
  function SessionTurnImpl(props) {
1144
1210
  const { turn, turnOutcome, sessionId, sessionStatus, permissions, questions, sessionWorking, isWorkingTurn, awaitingUser, pending, pendingPrompt, interruptedBeforeRun, isCompaction, providers, commandMessages, commands, } = props;
1145
1211
  const tHardcodedUi = useTranslations('hardcodedUi');
1212
+ const locale = useLocale();
1213
+ const afterFirstPrompt = useContext(AfterFirstPromptContext);
1214
+ const rows = useContext(TranscriptRowsContext);
1146
1215
  const [connectProviderOpen, setConnectProviderOpen] = useState(false);
1147
1216
  // `?? 'normal'` — legacy persisted preferences predate this key (same rule
1148
1217
  // as every `panelMode` read site).
@@ -1182,7 +1251,31 @@ function SessionTurnImpl(props) {
1182
1251
  // turn works, trimmed once it landed.
1183
1252
  response: model.working ? (compactionInfo.block?.summary ?? '') : (compactionInfo.block?.summary ?? '').trim(), turnError: errors.turnError, turnErrorIsAbort: errors.turnErrorIsAbort }));
1184
1253
  }
1185
- return (_jsxs("div", { className: "group/turn text-factor-[2] space-y-2.5", children: [_jsx(TurnUserBlock, { ...props, model: model, queueTone: queueTone, userContent: userContent }), _jsx(TurnFallbackRows, { working: model.working, events: props.servedModel?.fallbacks }), _jsxs(GenuiTelemetryContext.Provider, { value: genuiTelemetry, children: [_jsx(TurnToolBlocks, { ...props, model: model, segments: segments, conversationDensity: conversationDensity, fold: !answered.shouldUseInlineContent, durationMs: meta.turnDurationMs }), _jsx(TurnAssistantBlock, { ...props, model: model, answered: answered, userContent: userContent, tHardcodedUi: tHardcodedUi })] }), _jsx(TurnFooter, { ...props, model: model, errors: errors, answered: answered, status: status, retry: retry, meta: meta, tHardcodedUi: tHardcodedUi, connectProviderOpen: connectProviderOpen, onConnectProviderOpenChange: setConnectProviderOpen })] }));
1254
+ if (rows) {
1255
+ const userAt = Date.parse(turn.user.created_at);
1256
+ const answerAt = Date.parse(turn.assistant[0]?.created_at ?? '');
1257
+ const author = props.author;
1258
+ // Another session's agent wrote this prompt (a spawned thread's first
1259
+ // message, a coordinator): its agent's row, not the thread owner's.
1260
+ const sender = author?.kind === 'session'
1261
+ ? (author.agent ? agentDisplayLabel([], author.agent) : author.name) || rows.unknownAuthor
1262
+ : null;
1263
+ const person = author?.kind === 'member'
1264
+ ? { name: author.name, email: author.email, avatarUrl: author.avatar_url ?? null }
1265
+ : rows.owner;
1266
+ const personName = person ? participantLabel(person) : '';
1267
+ const showAnswer = turn.assistant.length > 0 || model.working || !!errors.turnErrorRow.text;
1268
+ return (_jsxs("div", { className: "text-factor-[2]", children: [userContent.hasVisibleUserContent || userContent.sessionReport || userContent.systemMessages.length > 0 ? (_jsx(MessageRow
1269
+ // The first message's turn clips its toolbar's overhang: it sits inside the row.
1270
+ , {
1271
+ // The first message's turn clips its toolbar's overhang: it sits inside the row.
1272
+ className: cn('group/turn', props.isFirstTurn && '[&_[data-slot=row-toolbar]]:top-0.5'), avatar: sender ? (
1273
+ // 36px, the `lg` avatar column (`w-10`).
1274
+ _jsx(AgentMark, { slug: author?.kind === 'session' && author.agent ? author.agent : DEFAULT_AGENT_SLUG, size: 28, tile: 36, label: sender })) : (_jsx(UserAvatar, { email: person?.email ?? '', name: personName, avatarUrl: person?.avatarUrl, size: "lg" })), name: sender ?? (personName || rows.unknownAuthor), time: rowTime(userAt, locale), children: _jsx(TurnUserBlock, { ...props, model: model, queueTone: queueTone, userContent: userContent }) })) : null, props.isFirstTurn ? afterFirstPrompt : null, showAnswer ? (_jsx(MessageRow, { className: "group/turn", avatar: _jsx(AgentMark, { slug: rows.agentSlug ?? DEFAULT_AGENT_SLUG, size: 28, tile: 36, label: rows.agent }), name: rows.agent, time: rowTime(answerAt, locale), toolbar: model.working ? null : (_jsx(TurnActionBar, { inToolbar: true, response: model.response, inlineContentParts: answered.inlineContentParts, turnEndedAt: meta.turnEndedAt, turnDurationMs: meta.turnDurationMs, costInfo: meta.costInfo, servedModel: props.servedModel, tHardcodedUi: tHardcodedUi, share: turn.continues
1275
+ ? undefined
1276
+ : { projectId: props.projectId, sessionId: props.projectSessionId, turnId: turn.id } })), children: _jsxs("div", { className: "mt-0.5 space-y-2.5", children: [_jsx(TurnFallbackRows, { working: model.working, events: props.servedModel?.fallbacks }), _jsxs(GenuiTelemetryContext.Provider, { value: genuiTelemetry, children: [_jsx(TurnToolBlocks, { ...props, model: model, segments: segments, conversationDensity: conversationDensity, fold: !answered.shouldUseInlineContent, durationMs: meta.turnDurationMs }), _jsx(TurnAssistantBlock, { ...props, model: model, answered: answered, userContent: userContent, tHardcodedUi: tHardcodedUi })] }), _jsx(TurnFooter, { ...props, hideActionBar: true, model: model, errors: errors, answered: answered, status: status, retry: retry, meta: meta, tHardcodedUi: tHardcodedUi, connectProviderOpen: connectProviderOpen, onConnectProviderOpenChange: setConnectProviderOpen })] }) })) : null] }));
1277
+ }
1278
+ return (_jsxs("div", { className: "group/turn text-factor-[2] space-y-2.5", children: [_jsx(TurnUserBlock, { ...props, model: model, queueTone: queueTone, userContent: userContent }), props.isFirstTurn ? afterFirstPrompt : null, _jsx(TurnFallbackRows, { working: model.working, events: props.servedModel?.fallbacks }), _jsxs(GenuiTelemetryContext.Provider, { value: genuiTelemetry, children: [_jsx(TurnToolBlocks, { ...props, model: model, segments: segments, conversationDensity: conversationDensity, fold: !answered.shouldUseInlineContent, durationMs: meta.turnDurationMs }), _jsx(TurnAssistantBlock, { ...props, model: model, answered: answered, userContent: userContent, tHardcodedUi: tHardcodedUi })] }), _jsx(TurnFooter, { ...props, model: model, errors: errors, answered: answered, status: status, retry: retry, meta: meta, tHardcodedUi: tHardcodedUi, connectProviderOpen: connectProviderOpen, onConnectProviderOpenChange: setConnectProviderOpen })] }));
1186
1279
  }
1187
1280
  /**
1188
1281
  * The boundary that stops the transcript re-rendering with the stream.
@@ -1213,7 +1306,12 @@ SessionTurn.displayName = 'SessionTurn';
1213
1306
  * settled `SessionTurn` bailed out. Every prop here is a primitive or a
1214
1307
  * reference that holds while another turn streams.
1215
1308
  */
1309
+ /** The fallback waiting row: a channel thread's agent row, or the bare line under a bubble. */
1310
+ function TurnFallbackBusyRow({ sessionId }) {
1311
+ const rows = useContext(TranscriptRowsContext);
1312
+ return rows ? _jsx(AgentBusyRow, { sessionId: sessionId }) : _jsx(SessionBusyIndicator, { sessionId: sessionId, className: "mt-2.5" });
1313
+ }
1216
1314
  export const TranscriptTurnRow = memo(function TranscriptTurnRow({ turnId, viewportClassName, suppressed, showBusyRow, continuedWith, fullTextState, onLoadFullText, ...turnProps }) {
1217
- return (_jsxs(TurnViewport, { turnId: turnId, className: viewportClassName, continues: turnProps.turn.compaction !== null || turnProps.turn.continues !== null, children: [continuedWith && (_jsx("div", { className: "mb-6", children: _jsx(HarnessSwitchMarker, { harness: continuedWith }) })), suppressed ? null : _jsx(SessionTurn, { ...turnProps }), !suppressed && _jsx(TurnFullText, { turn: turnProps.turn, state: fullTextState, onLoad: onLoadFullText }), showBusyRow && _jsx(SessionBusyIndicator, { sessionId: turnProps.sessionId, className: "mt-2.5" })] }));
1315
+ return (_jsxs(TurnViewport, { turnId: turnId, className: viewportClassName, continues: turnProps.turn.compaction !== null || turnProps.turn.continues !== null, children: [continuedWith && (_jsx("div", { className: "mb-6", children: _jsx(HarnessSwitchMarker, { harness: continuedWith }) })), suppressed ? null : _jsx(SessionTurn, { ...turnProps }), !suppressed && _jsx(TurnFullText, { turn: turnProps.turn, state: fullTextState, onLoad: onLoadFullText }), showBusyRow && _jsx(TurnFallbackBusyRow, { sessionId: turnProps.sessionId })] }));
1218
1316
  });
1219
1317
  TranscriptTurnRow.displayName = 'TranscriptTurnRow';
@@ -0,0 +1,16 @@
1
+ export interface TurnShareTarget {
2
+ projectId: string;
3
+ /** The Kortix project session id (`projectSessionId`), not the runtime id. */
4
+ sessionId: string;
5
+ /** The user message id that opens the turn (`SessionLogTurn.id`). */
6
+ turnId: string;
7
+ }
8
+ export declare function turnShareQueryKey({ projectId, sessionId, turnId }: TurnShareTarget): readonly ["turn-share", string, string, string];
9
+ /**
10
+ * The Share icon button of a settled turn's action bar, and the dialog it
11
+ * opens. Renders only where the API would accept the share: a host with public
12
+ * share pages, a turn inside a Kortix session, and a viewer the server says may
13
+ * publish (`can_publish_response === true`, the API's `mayPublishTurn`).
14
+ * Hidden while the session row loads: an unknown answer is not a yes.
15
+ */
16
+ export declare function TurnShareButton({ projectId, sessionId, turnId }: Partial<TurnShareTarget>): import("react").JSX.Element | null;
@@ -0,0 +1,162 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Share ONE assistant response through a public, read-only link.
5
+ *
6
+ * Private by default: the dialog reads the turn's live share
7
+ * (`getTurnShare`) and the "Public link" switch stays off until one exists.
8
+ * The server snapshots the text when it shares (`shareTurn`), with the prompt
9
+ * only when the person picks "Prompt and response". A re-share keeps the token
10
+ * and URL, so changing the scope or "Update link" (after `share.stale`) never
11
+ * breaks a link someone already holds. Turning the link off is destructive and
12
+ * takes a second, explicit click.
13
+ */
14
+ import { getTurnShare, shareTurn, unshareTurn } from '@kortix/sdk';
15
+ import { useProjectSession } from '@kortix/sdk/react';
16
+ import { CheckIcon, ShareNetworkIcon, WarningCircleIcon } from '@phosphor-icons/react';
17
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
18
+ import { RadioGroup as RadioGroupPrimitive } from 'radix-ui';
19
+ import { useEffect, useRef, useState } from 'react';
20
+ import { Copy } from '../../icons/copy.js';
21
+ import { useTranslations } from '../../i18n/index.js';
22
+ import { cn } from '../../lib/utils.js';
23
+ import { Button } from '../../primitives/button.js';
24
+ import Hint from '../../primitives/hint.js';
25
+ import { Input } from '../../primitives/input.js';
26
+ import { Label } from '../../primitives/label.js';
27
+ import { Modal, ModalContent, ModalTitle } from '../../primitives/modal.js';
28
+ import { RadioGroup } from '../../primitives/radio-group.js';
29
+ import { Separator } from '../../primitives/separator.js';
30
+ import { Switch } from '../../primitives/switch.js';
31
+ import { successToast } from '../../primitives/toast.js';
32
+ import { useUiHostConfig } from '../../providers/ui-provider.js';
33
+ export function turnShareQueryKey({ projectId, sessionId, turnId }) {
34
+ return ['turn-share', projectId, sessionId, turnId];
35
+ }
36
+ /**
37
+ * The server's own message for a failed call, or null. Only an error that
38
+ * carries an HTTP status (`ApiError.status`) came from the server; a network
39
+ * failure's message ("Failed to fetch") is not worth showing.
40
+ */
41
+ function serverMessage(error) {
42
+ const { status, message } = (error ?? {});
43
+ return typeof status === 'number' && typeof message === 'string' && message.trim()
44
+ ? message.trim()
45
+ : null;
46
+ }
47
+ /**
48
+ * The Share icon button of a settled turn's action bar, and the dialog it
49
+ * opens. Renders only where the API would accept the share: a host with public
50
+ * share pages, a turn inside a Kortix session, and a viewer the server says may
51
+ * publish (`can_publish_response === true`, the API's `mayPublishTurn`).
52
+ * Hidden while the session row loads: an unknown answer is not a yes.
53
+ */
54
+ export function TurnShareButton({ projectId, sessionId, turnId }) {
55
+ const t = useTranslations('turnShare');
56
+ const { publicSharesEnabled } = useUiHostConfig();
57
+ const { data: session } = useProjectSession(projectId, sessionId);
58
+ const [open, setOpen] = useState(false);
59
+ if (!publicSharesEnabled || !projectId || !sessionId || !turnId)
60
+ return null;
61
+ if (session?.can_publish_response !== true)
62
+ return null;
63
+ return (_jsxs(_Fragment, { children: [_jsx(Hint, { label: t('shareResponse'), side: "top", children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => setOpen(true), "aria-label": t('shareResponse'), className: "hit-area-3", children: _jsx(ShareNetworkIcon, { className: "text-muted-foreground size-4" }) }) }), _jsx(Modal, { open: open, onOpenChange: setOpen, children: open ? _jsx(TurnShareDialogContent, { target: { projectId, sessionId, turnId } }) : null })] }));
64
+ }
65
+ function TurnShareDialogContent({ target }) {
66
+ const t = useTranslations('turnShare');
67
+ const queryClient = useQueryClient();
68
+ const key = turnShareQueryKey(target);
69
+ const [error, setError] = useState(null);
70
+ const [copied, setCopied] = useState(false);
71
+ // The scope the person picked; null = whatever the live share says.
72
+ const [pickedIncludePrompt, setPickedIncludePrompt] = useState(null);
73
+ // "Turn off link" waits for this second, explicit click.
74
+ const [confirmingOff, setConfirmingOff] = useState(false);
75
+ const copiedTimer = useRef(null);
76
+ useEffect(() => () => {
77
+ if (copiedTimer.current)
78
+ clearTimeout(copiedTimer.current);
79
+ }, []);
80
+ const query = useQuery({
81
+ queryKey: key,
82
+ queryFn: () => getTurnShare(target.projectId, target.sessionId, target.turnId),
83
+ // A 403 or 404 is a settled answer; retrying it only delays the error line.
84
+ retry: false,
85
+ staleTime: 30_000,
86
+ });
87
+ const share = query.data?.share ?? null;
88
+ const includePrompt = pickedIncludePrompt ?? share?.include_prompt ?? false;
89
+ const copyUrl = async (url) => {
90
+ try {
91
+ await navigator.clipboard.writeText(url);
92
+ setCopied(true);
93
+ if (copiedTimer.current)
94
+ clearTimeout(copiedTimer.current);
95
+ copiedTimer.current = setTimeout(() => setCopied(false), 2000);
96
+ return true;
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ };
102
+ const publish = useMutation({
103
+ mutationFn: ({ includePrompt: include_prompt }) => shareTurn(target.projectId, target.sessionId, target.turnId, { include_prompt }),
104
+ onMutate: () => setError(null),
105
+ onSuccess: async (data, { reason }) => {
106
+ queryClient.setQueryData(key, data);
107
+ setPickedIncludePrompt(null);
108
+ if (reason !== 'share') {
109
+ successToast(t('linkUpdated'));
110
+ return;
111
+ }
112
+ // Sharing is the moment the person wants the link: put it on the clipboard.
113
+ successToast((await copyUrl(data.share.url)) ? t('linkCopied') : t('responseShared'));
114
+ },
115
+ onError: (err, { reason }) => {
116
+ // A failed scope change leaves the live share as it was: show its scope.
117
+ if (reason === 'scope')
118
+ setPickedIncludePrompt(null);
119
+ setError(serverMessage(err) ?? t('shareError'));
120
+ },
121
+ });
122
+ const unpublish = useMutation({
123
+ mutationFn: () => unshareTurn(target.projectId, target.sessionId, target.turnId),
124
+ onMutate: () => setError(null),
125
+ onSuccess: (data) => {
126
+ queryClient.setQueryData(key, data);
127
+ setConfirmingOff(false);
128
+ },
129
+ onError: (err) => setError(serverMessage(err) ?? t('unshareError')),
130
+ });
131
+ const pending = query.isLoading || publish.isPending || unpublish.isPending;
132
+ const shownError = error ?? (query.isError ? (serverMessage(query.error) ?? t('loadError')) : null);
133
+ const pickScope = (value) => {
134
+ const next = value === 'prompt';
135
+ if (next === includePrompt)
136
+ return;
137
+ setPickedIncludePrompt(next);
138
+ // Private: the pick waits for the switch. Public: re-share under the same URL.
139
+ if (share)
140
+ publish.mutate({ includePrompt: next, reason: 'scope' });
141
+ };
142
+ return (_jsx(ModalContent, { className: "space-y-0 lg:max-w-lg", children: _jsxs("div", { className: "flex flex-col gap-5 p-5", children: [_jsx(ModalTitle, { className: "pr-10 text-lg font-medium", children: t('shareResponse') }), _jsxs("div", { className: "space-y-2.5", children: [_jsx(Label, { id: "turn-share-scope", children: t('whatToInclude') }), _jsxs(RadioGroup, { "aria-labelledby": "turn-share-scope", value: includePrompt ? 'prompt' : 'response', onValueChange: pickScope, disabled: pending, className: "grid grid-cols-1 gap-2.5 sm:grid-cols-2", children: [_jsx(ScopeTile, { value: "response", title: t('responseOnly'), hint: t('responseOnlyHint'), withPrompt: false }), _jsx(ScopeTile, { value: "prompt", title: t('promptAndResponse'), hint: t('promptAndResponseHint'), withPrompt: true })] })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(Label, { htmlFor: "turn-share-public", children: t('publicLink') }), _jsx("p", { className: "text-muted-foreground text-xs", children: t('publicLinkHint') })] }), _jsx(Switch, { id: "turn-share-public", checked: !!share && !confirmingOff, disabled: pending, "aria-busy": pending || undefined, onCheckedChange: (on) => {
143
+ if (on && confirmingOff)
144
+ setConfirmingOff(false);
145
+ else if (on)
146
+ publish.mutate({ includePrompt, reason: 'share' });
147
+ else if (share)
148
+ setConfirmingOff(true);
149
+ } })] }), share && confirmingOff ? (_jsxs("div", { role: "group", "aria-label": t('turnOffLink'), className: "flex flex-wrap items-center justify-between gap-2", children: [_jsx("p", { className: "text-muted-foreground text-xs", children: t('stopNote') }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { variant: "outline-ghost", size: "xs", disabled: pending, onClick: () => setConfirmingOff(false), children: t('cancel') }), _jsx(Button, { variant: "destructive", size: "xs", disabled: pending, onClick: () => unpublish.mutate(), children: t('turnOffLink') })] })] })) : null, share && !confirmingOff ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex gap-2", children: [_jsx(Input, { readOnly: true, "aria-label": t('publicLink'), value: share.url, onFocus: (event) => event.currentTarget.select() }), _jsxs(Button, { className: "shrink-0", disabled: pending, onClick: () => void copyUrl(share.url).then((ok) => !ok && setError(t('copyError'))), children: [copied ? (_jsx(CheckIcon, { className: "size-4 shrink-0" })) : (_jsx(Copy, { className: "size-4 shrink-0" })), copied ? t('copied') : t('copyLink')] })] }), share.stale ? (_jsxs("p", { className: "text-muted-foreground flex flex-wrap items-center gap-1 text-xs", children: [t('stale'), " \u00B7", _jsx(Button, { variant: "link", size: "xs", className: "h-auto px-0 text-xs", disabled: pending, onClick: () => publish.mutate({ includePrompt, reason: 'update' }), children: t('updateLink') })] })) : null] })) : null, shownError ? (_jsxs("p", { role: "alert", className: "text-foreground flex items-start gap-2 text-xs text-pretty", children: [_jsx(WarningCircleIcon, { weight: "fill", className: "text-kortix-red mt-0.5 size-4 shrink-0" }), shownError] })) : null] })] }) }));
150
+ }
151
+ /** Widths of the skeleton text lines, longest first. */
152
+ const RESPONSE_LINES = ['w-full', 'w-11/12', 'w-2/3', 'w-5/6', 'w-1/2'];
153
+ const RESPONSE_LINES_UNDER_PROMPT = ['w-full', 'w-5/6', 'w-2/3'];
154
+ /**
155
+ * One scope choice: a skeleton of what the reader sees, a title and a hint.
156
+ * The prompt variant draws the prompt bubble top-right, where the transcript
157
+ * puts it. Outer `rounded-xl` minus the `p-2` inset gives the preview's
158
+ * `rounded-sm` (14 - 7.4 ≈ 6.6px), so the corners stay concentric.
159
+ */
160
+ function ScopeTile({ value, title, hint, withPrompt, }) {
161
+ return (_jsxs(RadioGroupPrimitive.Item, { value: value, className: cn('border-border flex flex-col gap-2.5 rounded-xl border p-2 text-left', 'hover:bg-hover transition-colors', 'data-[state=checked]:border-foreground', 'focus-visible:ring-ring outline-none focus-visible:ring-2', 'disabled:pointer-events-none disabled:opacity-50'), children: [_jsxs("span", { "aria-hidden": "true", className: "bg-background flex h-24 flex-col gap-1.5 rounded-sm p-3", children: [withPrompt ? _jsx("span", { className: "bg-muted ml-auto h-4 w-3/5 rounded-sm" }) : null, (withPrompt ? RESPONSE_LINES_UNDER_PROMPT : RESPONSE_LINES).map((width, index) => (_jsx("span", { className: cn('bg-border h-1.5 rounded-full', width) }, index)))] }), _jsxs("span", { className: "flex flex-col gap-0.5 px-1 pb-1", children: [_jsx("span", { className: "text-foreground text-sm font-medium", children: title }), _jsx("span", { className: "text-muted-foreground text-xs", children: hint })] })] }));
162
+ }
@@ -66,7 +66,35 @@ export declare const TurnLiveContext: import("react").Context<boolean>;
66
66
  * the turn ended on (KRTX-3021). Empty outside a settled turn.
67
67
  */
68
68
  export declare const RecoveredCallsContext: import("react").Context<ReadonlySet<string>>;
69
+ /**
70
+ * The images the turn's `image_gen` calls already drew (`imagePathsShownByImageGen`).
71
+ * A `show` of the same file in that turn does not draw it a second time (D5).
72
+ */
73
+ export declare const ImageGenPathsContext: import("react").Context<ReadonlySet<string>>;
74
+ /**
75
+ * The sha256 of the images the turn's `image_gen` calls already drew
76
+ * (`imageDigestsShownByImageGen`): a `show` of the same bytes at another path
77
+ * (a Drive copy) is not drawn a second time either (R38).
78
+ */
79
+ export declare const ImageGenDigestsContext: import("react").Context<ReadonlySet<string>>;
80
+ /**
81
+ * The runs of the turn's `image_gen` calls that draw as one grid
82
+ * (`sessionLogImageGenRuns`), by block id: the first call draws the run, the
83
+ * others nothing (R38).
84
+ */
85
+ export declare const ImageGenRunsContext: import("react").Context<ReadonlyMap<string, ToolCallBlock[]>>;
86
+ /**
87
+ * True inside a transcript turn's steps, where `TurnLiveContext` is a fact
88
+ * about the owning turn rather than its `false` default. The image card reads
89
+ * both to tell a stopped generation from one still running.
90
+ */
91
+ export declare const InTranscriptTurnContext: import("react").Context<boolean>;
69
92
  export declare const ToolDurationContext: import("react").Context<number | undefined>;
93
+ /**
94
+ * True in a read-only session view (the sub-session modal): a tool card shows
95
+ * what happened and offers no fix (connect a model, reconnect ChatGPT).
96
+ */
97
+ export declare const ReadOnlySessionContext: import("react").Context<boolean>;
70
98
  export declare function shouldShowToolPartInActionsPanel(call: ToolCallBlock): boolean;
71
99
  export declare const ToolActivateContext: import("react").Context<((callID: string) => void) | null>;
72
100
  export declare const BoundActivateContext: import("react").Context<(() => void) | null>;
@@ -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';
@@ -1,2 +1,3 @@
1
1
  import type { ToolProps } from '../shared/types.js';
2
+ /** @deprecated Renders an OpenCode-only tool or todo list in an OpenCode session (pi has none). OpenCode is sunset (2026-10-23): no new code; delete with OpenCode. */
2
3
  export declare function ApplyPatchTool({ call, defaultOpen, forceOpen, locked }: ToolProps): import("react").JSX.Element;