@kortix/ui 0.14.12 → 0.14.14

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 (438) hide show
  1. package/README.md +1 -1
  2. package/dist/_vendor/kortix-shared.js +521 -7045
  3. package/dist/_vendor/shared/app-config.d.ts +8 -0
  4. package/dist/_vendor/shared/artifact-annotations.d.ts +708 -0
  5. package/dist/_vendor/shared/artifact-comments.d.ts +327 -0
  6. package/dist/_vendor/shared/index.d.ts +3 -1
  7. package/dist/_vendor/shared/my-kortix-agent.d.ts +40 -0
  8. package/dist/_vendor/shared/peer-message-prompt.d.ts +35 -0
  9. package/dist/_vendor/shared/pixel-mark.d.ts +11 -0
  10. package/dist/_vendor/shared/prompt-attachments.d.ts +1 -0
  11. package/dist/_vendor/shared/reminder-prompt.d.ts +8 -2
  12. package/dist/_vendor/shared/runtime-versions.d.ts +8 -0
  13. package/dist/artifacts/artifact-frame.d.ts +1 -0
  14. package/dist/artifacts/artifact-frame.js +18 -5
  15. package/dist/artifacts/frame-policy.d.ts +1 -1
  16. package/dist/artifacts/frame-policy.js +10 -5
  17. package/dist/customize/agents/agent-access-text.d.ts +16 -0
  18. package/dist/customize/agents/agent-access-text.js +54 -0
  19. package/dist/customize/agents/agent-approval-rules.d.ts +8 -0
  20. package/dist/customize/agents/agent-approval-rules.js +26 -0
  21. package/dist/customize/agents/agent-authority-card.js +4 -1
  22. package/dist/customize/agents/agent-cover-card.d.ts +4 -1
  23. package/dist/customize/agents/agent-cover-card.js +2 -2
  24. package/dist/customize/agents/agent-detail-aside.d.ts +1 -2
  25. package/dist/customize/agents/agent-detail-aside.js +8 -11
  26. package/dist/customize/agents/agent-drives-section.d.ts +23 -7
  27. package/dist/customize/agents/agent-drives-section.js +107 -41
  28. package/dist/customize/agents/agent-instructions.d.ts +11 -0
  29. package/dist/customize/agents/agent-instructions.js +114 -0
  30. package/dist/customize/agents/agent-model-view.d.ts +17 -0
  31. package/dist/customize/agents/agent-model-view.js +67 -0
  32. package/dist/customize/agents/agent-overview.d.ts +53 -0
  33. package/dist/customize/agents/agent-overview.js +242 -0
  34. package/dist/customize/agents/agent-page-chrome.d.ts +128 -0
  35. package/dist/customize/agents/agent-page-chrome.js +145 -0
  36. package/dist/customize/agents/agent-page.d.ts +13 -1
  37. package/dist/customize/agents/agent-page.js +478 -367
  38. package/dist/customize/agents/agent-pin-button.d.ts +10 -0
  39. package/dist/customize/agents/agent-pin-button.js +20 -0
  40. package/dist/customize/agents/agent-policy-sets-section.d.ts +16 -0
  41. package/dist/customize/agents/agent-policy-sets-section.js +80 -0
  42. package/dist/customize/agents/agent-policy-sets.js +1 -1
  43. package/dist/customize/agents/agent-section-rail.d.ts +21 -0
  44. package/dist/customize/agents/agent-section-rail.js +23 -0
  45. package/dist/customize/agents/agent-share-control.d.ts +4 -3
  46. package/dist/customize/agents/agent-share-control.js +15 -16
  47. package/dist/customize/agents/{agent-people-section.d.ts → agent-share-dialog.d.ts} +3 -1
  48. package/dist/customize/agents/{agent-people-section.js → agent-share-dialog.js} +21 -21
  49. package/dist/customize/agents/agent-tabs.d.ts +95 -0
  50. package/dist/customize/agents/agent-tabs.js +199 -0
  51. package/dist/customize/agents/agents-page.d.ts +0 -21
  52. package/dist/customize/agents/agents-page.js +104 -118
  53. package/dist/customize/agents/connectors-required.d.ts +16 -0
  54. package/dist/customize/agents/connectors-required.js +19 -0
  55. package/dist/customize/agents/create-agent-modal.d.ts +19 -0
  56. package/dist/customize/agents/create-agent-modal.js +94 -0
  57. package/dist/customize/connectors/agent-access.d.ts +4 -4
  58. package/dist/customize/connectors/agent-access.js +7 -10
  59. package/dist/customize/connectors/connector-identity.d.ts +12 -0
  60. package/dist/customize/connectors/connector-identity.js +15 -2
  61. package/dist/customize/connectors/connector-routes.js +2 -2
  62. package/dist/customize/connectors/connectors-page.d.ts +14 -1
  63. package/dist/customize/connectors/connectors-page.js +101 -32
  64. package/dist/customize/connectors/detail/app-page.js +1 -1
  65. package/dist/customize/connectors/detail/connector-agents.js +0 -3
  66. package/dist/customize/connectors/detail/connector-page.d.ts +1 -1
  67. package/dist/customize/connectors/detail/connector-page.js +5 -2
  68. package/dist/customize/connectors/detail/connector-policy-sets.js +1 -1
  69. package/dist/customize/connectors/detail/connector-triggers.js +2 -2
  70. package/dist/customize/connectors/use-agent-access.d.ts +7 -5
  71. package/dist/customize/connectors/use-agent-access.js +2 -6
  72. package/dist/customize/models/models-page.d.ts +7 -1
  73. package/dist/customize/models/models-page.js +2 -2
  74. package/dist/customize/project-settings/project-admin-sections.d.ts +63 -0
  75. package/dist/customize/project-settings/project-admin-sections.js +80 -0
  76. package/dist/customize/project-settings/project-settings-page.d.ts +1 -1
  77. package/dist/customize/project-settings/project-settings-page.js +4 -13
  78. package/dist/customize/project-settings/project-settings-sections.d.ts +5 -5
  79. package/dist/customize/project-settings/project-settings-sections.js +6 -20
  80. package/dist/customize/providers/provider-accordion.js +29 -17
  81. package/dist/customize/providers/provider-connect.js +1 -1
  82. package/dist/customize/providers/provider-sheet.d.ts +4 -1
  83. package/dist/customize/providers/provider-sheet.js +15 -5
  84. package/dist/customize/secrets/secrets-page.d.ts +5 -1
  85. package/dist/customize/secrets/secrets-page.js +2 -2
  86. package/dist/customize/sections/gateway-view.d.ts +10 -2
  87. package/dist/customize/sections/gateway-view.js +16 -4
  88. package/dist/customize/sections/llm-provider/chatgpt-subscription-connect.d.ts +12 -5
  89. package/dist/customize/sections/llm-provider/chatgpt-subscription-connect.js +131 -8
  90. package/dist/customize/sections/llm-provider/claude-code-step.d.ts +10 -0
  91. package/dist/customize/sections/llm-provider/claude-code-step.js +32 -0
  92. package/dist/customize/sections/llm-provider/models-tab.js +5 -1
  93. package/dist/customize/sections/view/account-secret-resources-panel.d.ts +5 -3
  94. package/dist/customize/sections/view/account-secret-resources-panel.js +122 -19
  95. package/dist/customize/sections/view/agent-editor-access-fields.d.ts +1 -1
  96. package/dist/customize/sections/view/agent-editor-access-fields.js +8 -4
  97. package/dist/customize/sections/view/agent-editor-basics-fields.d.ts +4 -1
  98. package/dist/customize/sections/view/agent-editor-basics-fields.js +33 -4
  99. package/dist/customize/sections/view/agent-editor-catalog.d.ts +2 -2
  100. package/dist/customize/sections/view/agent-editor-catalog.js +10 -12
  101. package/dist/customize/sections/view/agent-editor-primitives.d.ts +1 -1
  102. package/dist/customize/sections/view/agent-editor-primitives.js +4 -4
  103. package/dist/customize/sections/view/agent-editor.d.ts +37 -26
  104. package/dist/customize/sections/view/agent-editor.js +19 -19
  105. package/dist/customize/sections/view/grant-mode-field.d.ts +8 -20
  106. package/dist/customize/sections/view/grant-mode-field.js +31 -57
  107. package/dist/customize/sections/view/permission-editor.d.ts +3 -1
  108. package/dist/customize/sections/view/permission-editor.js +19 -10
  109. package/dist/customize/sections/view/review-view.d.ts +8 -0
  110. package/dist/customize/sections/view/review-view.js +12 -1
  111. package/dist/customize/sections/view/secret-delivery.js +1 -4
  112. package/dist/customize/sections/view/secrets-view.d.ts +7 -1
  113. package/dist/customize/sections/view/secrets-view.js +42 -6
  114. package/dist/customize/settings/rail.js +2 -8
  115. package/dist/customize/settings/settings-tabs.d.ts +2 -2
  116. package/dist/customize/settings/settings-tabs.js +17 -19
  117. package/dist/customize/settings/tabs/experimental-tab.d.ts +3 -0
  118. package/dist/customize/settings/tabs/experimental-tab.js +6 -1
  119. package/dist/customize/settings/tabs/sandbox-tab.d.ts +4 -6
  120. package/dist/customize/settings/tabs/sandbox-tab.js +9 -9
  121. package/dist/customize/shared/access-list.d.ts +39 -0
  122. package/dist/customize/shared/access-list.js +62 -0
  123. package/dist/customize/shared/agent-resource-scope.d.ts +87 -0
  124. package/dist/customize/shared/agent-resource-scope.js +123 -0
  125. package/dist/customize/shared/capability-library.d.ts +41 -0
  126. package/dist/customize/shared/capability-library.js +271 -0
  127. package/dist/customize/shared/capability-page-shell.d.ts +18 -1
  128. package/dist/customize/shared/capability-page-shell.js +21 -1
  129. package/dist/customize/shared/catalog/catalog-space-tabs.d.ts +14 -0
  130. package/dist/customize/shared/catalog/catalog-space-tabs.js +20 -0
  131. package/dist/customize/shared/customize-tab-bar.d.ts +13 -0
  132. package/dist/customize/shared/customize-tab-bar.js +95 -0
  133. package/dist/customize/shared/entity/entity-modal.d.ts +17 -1
  134. package/dist/customize/shared/entity/entity-modal.js +10 -9
  135. package/dist/customize/shared/leave-guard.d.ts +23 -0
  136. package/dist/customize/shared/leave-guard.js +87 -0
  137. package/dist/customize/shared/standalone-settings-nav.js +4 -1
  138. package/dist/customize/shared/tool-rules.d.ts +11 -0
  139. package/dist/customize/shared/tool-rules.js +29 -0
  140. package/dist/customize/skills/builtin-skill-modal.d.ts +6 -0
  141. package/dist/customize/skills/builtin-skill-modal.js +41 -0
  142. package/dist/customize/skills/skills-page.d.ts +21 -18
  143. package/dist/customize/skills/skills-page.js +16 -110
  144. package/dist/customize/triggers/runtime-triggers.d.ts +17 -0
  145. package/dist/customize/triggers/runtime-triggers.js +57 -0
  146. package/dist/customize/triggers/schedule/event-trigger-copy.js +2 -2
  147. package/dist/customize/triggers/schedule/post-to-field.js +2 -2
  148. package/dist/customize/triggers/schedule/schedule-copy.d.ts +11 -6
  149. package/dist/customize/triggers/schedule/schedule-copy.js +29 -8
  150. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +7 -3
  151. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +26 -1
  152. package/dist/customize/triggers/schedule/trigger-composer-logic.js +64 -3
  153. package/dist/customize/triggers/schedule/trigger-composer.js +57 -20
  154. package/dist/customize/triggers/schedule/trigger-edit-logic.js +18 -5
  155. package/dist/customize/triggers/schedule/trigger-filter.d.ts +10 -0
  156. package/dist/customize/triggers/schedule/trigger-filter.js +16 -0
  157. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  158. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  159. package/dist/customize/triggers/schedule/use-trigger-mutations.d.ts +1 -1
  160. package/dist/customize/triggers/schedule/use-trigger-mutations.js +1 -1
  161. package/dist/customize/triggers/schedule/when-app.d.ts +15 -0
  162. package/dist/customize/triggers/schedule/when-app.js +21 -0
  163. package/dist/customize/triggers/schedule/when-change-request.d.ts +10 -0
  164. package/dist/customize/triggers/schedule/when-change-request.js +15 -0
  165. package/dist/customize/triggers/schedule-view.d.ts +17 -3
  166. package/dist/customize/triggers/schedule-view.js +46 -16
  167. package/dist/customize/triggers/triggers-page.d.ts +3 -3
  168. package/dist/customize/triggers/triggers-page.js +2 -2
  169. package/dist/customize/use-configure-thread.d.ts +8 -2
  170. package/dist/customize/use-configure-thread.js +30 -18
  171. package/dist/files/project/components/change-request-detail-dialog.js +2 -3
  172. package/dist/files/project/components/drive-explorer.js +6 -5
  173. package/dist/files/project/explorer-source.d.ts +3 -0
  174. package/dist/files/project/upload-batch.d.ts +3 -3
  175. package/dist/files/project/upload-batch.js +7 -6
  176. package/dist/files/runtime/sandbox-explorer-source.js +3 -3
  177. package/dist/i18n/en.d.ts +1330 -53
  178. package/dist/i18n/en.js +1422 -145
  179. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +16 -7
  180. package/dist/internal/auth/auth-primitives.d.ts +1 -3
  181. package/dist/internal/auth/auth-primitives.js +2 -2
  182. package/dist/internal/billing/session-cost-format.d.ts +1 -0
  183. package/dist/internal/billing/session-cost-format.js +11 -0
  184. package/dist/internal/components/agent-mark.d.ts +12 -1
  185. package/dist/internal/components/agent-mark.js +34 -11
  186. package/dist/internal/components/nav-rail.d.ts +22 -0
  187. package/dist/internal/components/nav-rail.js +16 -0
  188. package/dist/internal/components/repository-disconnected.js +2 -2
  189. package/dist/internal/goals/goal-meta.d.ts +15 -1
  190. package/dist/internal/goals/goal-meta.js +42 -2
  191. package/dist/internal/hooks/projects/use-agent-config.d.ts +11 -7
  192. package/dist/internal/hooks/projects/use-agent-config.js +28 -11
  193. package/dist/internal/hooks/use-slash-focus.d.ts +7 -1
  194. package/dist/internal/hooks/use-slash-focus.js +9 -3
  195. package/dist/internal/layout/project-capability-nav.d.ts +24 -0
  196. package/dist/internal/layout/project-capability-nav.js +86 -0
  197. package/dist/internal/layout/project-page-header.d.ts +1 -1
  198. package/dist/internal/layout/project-page-header.js +1 -1
  199. package/dist/internal/layout/project-settings-nav.d.ts +3 -2
  200. package/dist/internal/layout/project-settings-nav.js +5 -3
  201. package/dist/internal/lib/browser-noise/rules/old-browsers.js +1 -1
  202. package/dist/internal/lib/capability-tab-routes.d.ts +34 -3
  203. package/dist/internal/lib/capability-tab-routes.js +76 -8
  204. package/dist/internal/lib/manifest-health.d.ts +10 -0
  205. package/dist/internal/lib/manifest-health.js +20 -0
  206. package/dist/internal/lib/pixel-mark.d.ts +4 -1
  207. package/dist/internal/lib/pixel-mark.js +33 -6
  208. package/dist/internal/lib/project-actions.d.ts +1 -1
  209. package/dist/internal/lib/project-actions.js +0 -4
  210. package/dist/internal/lib/provider-branding.js +2 -0
  211. package/dist/internal/lib/space-scope.d.ts +29 -0
  212. package/dist/internal/lib/space-scope.js +28 -0
  213. package/dist/internal/lib/use-project-feature-flags.js +3 -3
  214. package/dist/internal/lib/web-notifications.d.ts +74 -8
  215. package/dist/internal/lib/web-notifications.js +243 -117
  216. package/dist/internal/notifications/notification-rows.d.ts +14 -7
  217. package/dist/internal/notifications/notification-rows.js +21 -14
  218. package/dist/internal/notifications/session-toast-cards.d.ts +2 -2
  219. package/dist/internal/reminders/reminder-format.d.ts +6 -2
  220. package/dist/internal/reminders/reminder-format.js +7 -1
  221. package/dist/internal/stores/active-space-store.d.ts +35 -0
  222. package/dist/internal/stores/active-space-store.js +29 -0
  223. package/dist/internal/stores/kortix-computer-store.js +13 -4
  224. package/dist/internal/stores/pinned-agents-store.d.ts +26 -0
  225. package/dist/internal/stores/pinned-agents-store.js +20 -0
  226. package/dist/internal/stores/session-panel-memory-store.js +3 -0
  227. package/dist/internal/stores/turn-attention-store.d.ts +5 -4
  228. package/dist/lib/routes.d.ts +16 -1
  229. package/dist/lib/routes.js +15 -3
  230. package/dist/markdown/doc-editor/doc-embed.d.ts +31 -0
  231. package/dist/markdown/doc-editor/doc-embed.js +168 -0
  232. package/dist/markdown/doc-editor/doc-extensions.d.ts +26 -0
  233. package/dist/markdown/doc-editor/doc-extensions.js +149 -0
  234. package/dist/markdown/doc-editor/doc-menus.d.ts +9 -0
  235. package/dist/markdown/doc-editor/doc-menus.js +56 -0
  236. package/dist/markdown/doc-editor/markdown.d.ts +12 -0
  237. package/dist/markdown/doc-editor/markdown.js +140 -0
  238. package/dist/markdown/genui/components/inline.d.ts +1 -1
  239. package/dist/primitives/badge.d.ts +1 -1
  240. package/dist/primitives/button.d.ts +1 -1
  241. package/dist/primitives/pixel-kortix-mark.d.ts +5 -4
  242. package/dist/primitives/pixel-kortix-mark.js +5 -15
  243. package/dist/primitives/tag.d.ts +1 -1
  244. package/dist/primitives/textarea.js +14 -0
  245. package/dist/primitives/toast.d.ts +2 -0
  246. package/dist/primitives/toast.js +4 -2
  247. package/dist/providers/ui-provider.d.ts +16 -0
  248. package/dist/session/actions/session-label.d.ts +1 -1
  249. package/dist/session/actions/session-label.js +3 -3
  250. package/dist/session/agents/agent-model.d.ts +92 -0
  251. package/dist/session/agents/agent-model.js +123 -0
  252. package/dist/session/agents/agent-state-mark.d.ts +10 -0
  253. package/dist/session/agents/agent-state-mark.js +22 -0
  254. package/dist/session/agents/agent-strip.d.ts +58 -0
  255. package/dist/session/agents/agent-strip.js +259 -0
  256. package/dist/session/agents/held-messages.d.ts +33 -0
  257. package/dist/session/agents/held-messages.js +50 -0
  258. package/dist/session/agents/legacy-subagent-chat.d.ts +11 -0
  259. package/dist/session/agents/legacy-subagent-chat.js +19 -0
  260. package/dist/session/agents/session-peek.d.ts +20 -0
  261. package/dist/session/agents/session-peek.js +67 -0
  262. package/dist/session/agents/session-prompt.d.ts +13 -0
  263. package/dist/session/agents/session-prompt.js +18 -0
  264. package/dist/session/agents/steer-session.d.ts +13 -0
  265. package/dist/session/agents/steer-session.js +29 -0
  266. package/dist/session/agents/subagent-dialog-content.d.ts +11 -0
  267. package/dist/session/agents/subagent-dialog-content.js +115 -0
  268. package/dist/session/agents/subagent-view.d.ts +8 -0
  269. package/dist/session/agents/subagent-view.js +18 -0
  270. package/dist/session/agents/tasks-panel.d.ts +13 -0
  271. package/dist/session/agents/tasks-panel.js +41 -0
  272. package/dist/session/agents/workflow-run-controls.d.ts +43 -0
  273. package/dist/session/agents/workflow-run-controls.js +141 -0
  274. package/dist/session/composer/ComposerCard.d.ts +1 -1
  275. package/dist/session/composer/ComposerCard.js +3 -3
  276. package/dist/session/composer/agent-selector.js +13 -19
  277. package/dist/session/composer/composer-underbar.d.ts +3 -1
  278. package/dist/session/composer/composer-underbar.js +2 -2
  279. package/dist/session/composer/composer.d.ts +5 -0
  280. package/dist/session/composer/composer.js +16 -10
  281. package/dist/session/composer/editor/composer-editor.js +19 -8
  282. package/dist/session/composer/editor/ultracode.d.ts +34 -0
  283. package/dist/session/composer/editor/ultracode.js +127 -0
  284. package/dist/session/composer/send-blockers.d.ts +1 -11
  285. package/dist/session/composer/send-blockers.js +1 -11
  286. package/dist/session/composer/session-composer-readiness.d.ts +1 -28
  287. package/dist/session/composer/session-composer-readiness.js +5 -16
  288. package/dist/session/header/reminder-parts.d.ts +1 -1
  289. package/dist/session/header/session-site-header.js +6 -3
  290. package/dist/session/header/subagent-hover-card.d.ts +0 -2
  291. package/dist/session/header/subagent-hover-card.js +1 -4
  292. package/dist/session/models/claude-connection-slot.d.ts +11 -0
  293. package/dist/session/models/claude-connection-slot.js +30 -0
  294. package/dist/session/models/model-availability.d.ts +3 -1
  295. package/dist/session/models/model-availability.js +3 -0
  296. package/dist/session/models/model-selector.js +11 -12
  297. package/dist/session/models/model-tags.d.ts +9 -0
  298. package/dist/session/models/model-tags.js +8 -0
  299. package/dist/session/panel/easy/easy-panel.js +1 -1
  300. package/dist/session/panel/easy/step-icon.js +5 -1
  301. package/dist/session/panel/mobile-tool-drawer.js +1 -1
  302. package/dist/session/panel/session-action-panel-column.js +1 -1
  303. package/dist/session/panel/session-desktop.js +41 -14
  304. package/dist/session/panel/session-panel-provider.d.ts +1 -1
  305. package/dist/session/panel/session-panel-provider.js +7 -11
  306. package/dist/session/prompts/question-prompt.js +3 -1
  307. package/dist/session/status/session-error-banner.js +4 -1
  308. package/dist/session/thread/session-chat.js +286 -296
  309. package/dist/session/thread/session-context-modal.js +29 -10
  310. package/dist/session/thread/session-context-spawned-sessions.d.ts +13 -0
  311. package/dist/session/thread/session-context-spawned-sessions.js +44 -0
  312. package/dist/session/thread/session-context-sub-sessions.js +3 -8
  313. package/dist/session/thread/transcript.d.ts +3 -0
  314. package/dist/session/thread/transcript.js +32 -8
  315. package/dist/session/tool/shared/full-view-action.d.ts +29 -0
  316. package/dist/session/tool/shared/full-view-action.js +43 -0
  317. package/dist/session/tool/tool-part-renderer.js +10 -2
  318. package/dist/session/tool/tools/agent-message-tool.js +2 -2
  319. package/dist/session/tool/tools/agent-spawn-tool.js +2 -2
  320. package/dist/session/tool/tools/agent-status-tool.js +2 -2
  321. package/dist/session/tool/tools/kortix-action-tool.d.ts +2 -0
  322. package/dist/session/tool/tools/kortix-action-tool.js +148 -0
  323. package/dist/session/tool/tools/kortix-tool-card.d.ts +83 -0
  324. package/dist/session/tool/tools/kortix-tool-card.js +186 -0
  325. package/dist/session/tool/tools/multi-agent-tool-bodies.d.ts +11 -0
  326. package/dist/session/tool/tools/multi-agent-tool-bodies.js +141 -0
  327. package/dist/session/tool/tools/multi-agent-tool-data.d.ts +63 -0
  328. package/dist/session/tool/tools/multi-agent-tool-data.js +118 -0
  329. package/dist/session/tool/tools/multi-agent-tools.d.ts +9 -0
  330. package/dist/session/tool/tools/multi-agent-tools.js +38 -0
  331. package/dist/session/tool/tools/question-tool.js +1 -1
  332. package/dist/session/tool/tools/register.d.ts +3 -0
  333. package/dist/session/tool/tools/register.js +3 -0
  334. package/dist/session/tool/tools/session-spawn-tool.js +2 -2
  335. package/dist/session/tool/tools/task-tool.d.ts +1 -1
  336. package/dist/session/tool/tools/task-tool.js +29 -41
  337. package/dist/session/tool/tools/workflow-progress.d.ts +34 -0
  338. package/dist/session/tool/tools/workflow-progress.js +186 -0
  339. package/dist/session/tool/tools/workflow-run.d.ts +128 -0
  340. package/dist/session/tool/tools/workflow-run.js +251 -0
  341. package/dist/session/tool/tools/workflow-tool.d.ts +9 -0
  342. package/dist/session/tool/tools/workflow-tool.js +253 -0
  343. package/dist/session/turn/notice-batch-group.d.ts +12 -0
  344. package/dist/session/turn/notice-batch-group.js +17 -0
  345. package/dist/session/turn/peer-message-row.d.ts +14 -0
  346. package/dist/session/turn/peer-message-row.js +57 -0
  347. package/dist/session/turn/subagent-notice-row.d.ts +4 -0
  348. package/dist/session/turn/subagent-notice-row.js +50 -0
  349. package/dist/session/turn/subagent-notice.d.ts +58 -0
  350. package/dist/session/turn/subagent-notice.js +111 -0
  351. package/dist/session/turn/user-message.js +24 -5
  352. package/dist/styles/tokens.css +2 -0
  353. package/dist/styles.css +1 -1
  354. package/dist/terminal/session-terminal-connect-bar.js +1 -1
  355. package/dist/workspace/admin/project-admin-dashboard.d.ts +53 -0
  356. package/dist/workspace/admin/project-admin-dashboard.js +252 -0
  357. package/dist/workspace/admin/project-admin-nav.d.ts +20 -0
  358. package/dist/workspace/admin/project-admin-nav.js +41 -0
  359. package/dist/workspace/home/welcome-body.js +25 -3
  360. package/dist/workspace/index.d.ts +6 -2
  361. package/dist/workspace/index.js +12 -2
  362. package/dist/workspace/layout/new-session-create.js +3 -3
  363. package/dist/workspace/layout/project-home.js +3 -3
  364. package/dist/workspace/memory/memory-labels.js +5 -0
  365. package/dist/workspace/repository-disconnected.js +2 -2
  366. package/dist/workspace/sessions/board-dispatch.d.ts +52 -0
  367. package/dist/workspace/sessions/board-dispatch.js +110 -0
  368. package/dist/workspace/sessions/board-grouping.d.ts +63 -0
  369. package/dist/workspace/sessions/board-grouping.js +141 -0
  370. package/dist/workspace/sessions/board-peek.d.ts +15 -0
  371. package/dist/workspace/sessions/board-peek.js +54 -0
  372. package/dist/workspace/sessions/board-state-mark.d.ts +15 -0
  373. package/dist/workspace/sessions/board-state-mark.js +24 -0
  374. package/dist/workspace/sessions/project-sessions-view.js +42 -31
  375. package/dist/workspace/sessions/sessions-board.d.ts +12 -0
  376. package/dist/workspace/sessions/sessions-board.js +214 -0
  377. package/dist/workspace/sidebar/footer/project-manifest-issues-alert.d.ts +46 -0
  378. package/dist/workspace/sidebar/footer/project-manifest-issues-alert.js +85 -0
  379. package/dist/workspace/sidebar/footer/sidebar-alert.js +1 -1
  380. package/dist/workspace/sidebar/new-agent-modal-provider.d.ts +12 -0
  381. package/dist/workspace/sidebar/new-agent-modal-provider.js +19 -0
  382. package/dist/workspace/sidebar/project-nav-items.d.ts +3 -1
  383. package/dist/workspace/sidebar/project-nav-items.js +53 -5
  384. package/dist/workspace/sidebar/project-session-list.js +35 -12
  385. package/dist/workspace/sidebar/project-sidebar.js +6 -3
  386. package/dist/workspace/sidebar/session-filter-menu.js +2 -1
  387. package/dist/workspace/space/space-blocks.d.ts +25 -0
  388. package/dist/workspace/space/space-blocks.js +124 -0
  389. package/dist/workspace/space/space-filter-tabs.d.ts +17 -0
  390. package/dist/workspace/space/space-filter-tabs.js +31 -0
  391. package/dist/workspace/space/space-page.d.ts +24 -0
  392. package/dist/workspace/space/space-page.js +157 -0
  393. package/dist/workspace/space/space-room.d.ts +20 -0
  394. package/dist/workspace/space/space-room.js +27 -0
  395. package/dist/workspace/space/space-tab-menu.d.ts +14 -0
  396. package/dist/workspace/space/space-tab-menu.js +127 -0
  397. package/dist/workspace/space/space-tab-panels.d.ts +9 -0
  398. package/dist/workspace/space/space-tab-panels.js +203 -0
  399. package/dist/workspace/space/space-templates.d.ts +34 -0
  400. package/dist/workspace/space/space-templates.js +71 -0
  401. package/dist/workspace/space/use-space-filter.d.ts +10 -0
  402. package/dist/workspace/space/use-space-filter.js +40 -0
  403. package/dist/workspace/space/use-space-manifest.d.ts +8 -0
  404. package/dist/workspace/space/use-space-manifest.js +27 -0
  405. package/dist/workspace/spaces/space-timeline.js +2 -2
  406. package/package.json +56 -53
  407. package/skills/kortix-ui/SKILL.md +1 -1
  408. package/skills/kortix-ui/references/custom-dashboard.md +10 -4
  409. package/skills/kortix-ui/references/modules.md +10 -8
  410. package/dist/_vendor/shared/meta-agent.d.ts +0 -7
  411. package/dist/customize/agents/agent-grant-pages.d.ts +0 -37
  412. package/dist/customize/agents/agent-grant-pages.js +0 -226
  413. package/dist/customize/agents/agent-triggers-section.d.ts +0 -17
  414. package/dist/customize/agents/agent-triggers-section.js +0 -109
  415. package/dist/customize/migrate-to-v2/index.d.ts +0 -5
  416. package/dist/customize/migrate-to-v2/index.js +0 -5
  417. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +0 -16
  418. package/dist/customize/migrate-to-v2/migration-prompt.js +0 -59
  419. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +0 -30
  420. package/dist/customize/migrate-to-v2/upgrade-defs.js +0 -43
  421. package/dist/customize/migrate-to-v2/upgrade-view.d.ts +0 -32
  422. package/dist/customize/migrate-to-v2/upgrade-view.js +0 -152
  423. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +0 -18
  424. package/dist/customize/migrate-to-v2/use-run-upgrade.js +0 -16
  425. package/dist/customize/shared/capability-tabs.d.ts +0 -3
  426. package/dist/customize/shared/capability-tabs.js +0 -137
  427. package/dist/customize/skills/skill-scope.d.ts +0 -14
  428. package/dist/customize/skills/skill-scope.js +0 -18
  429. package/dist/internal/lib/manifest-version.d.ts +0 -21
  430. package/dist/internal/lib/manifest-version.js +0 -55
  431. package/dist/session/composer/hooks/use-composer-escape-stop.d.ts +0 -6
  432. package/dist/session/composer/hooks/use-composer-escape-stop.js +0 -28
  433. package/dist/session/thread/sub-session-modal-content.d.ts +0 -8
  434. package/dist/session/thread/sub-session-modal-content.js +0 -23
  435. package/dist/session/thread/sub-session-modal.d.ts +0 -2
  436. package/dist/session/thread/sub-session-modal.js +0 -14
  437. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.d.ts +0 -13
  438. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +0 -48
@@ -0,0 +1,141 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Badge } from '../../primitives/badge.js';
4
+ import { Button } from '../../primitives/button.js';
5
+ import { ButtonGroup } from '../../primitives/button-group.js';
6
+ import { Hint } from '../../primitives/hint.js';
7
+ import Loading from '../../primitives/loading.js';
8
+ import { errorToast, successToast } from '../../primitives/toast.js';
9
+ import { useTranslations } from '../../i18n/index.js';
10
+ import { FloppyDiskIcon, PauseIcon, PlayIcon, SquareIcon, WarningIcon } from '@phosphor-icons/react';
11
+ import { useEffect, useMemo, useState } from 'react';
12
+ import { WORKFLOW_LARGE_AGENT_COUNT } from '@kortix/sdk';
13
+ import { useSessionWorkflows } from '@kortix/sdk/react';
14
+ import { parseWorkflowRun } from '../tool/tools/workflow-run.js';
15
+ import { useSessionPromptSend } from './session-prompt.js';
16
+ /**
17
+ * One workflow run's controls, for the run card in the chat and the strip's
18
+ * "Workflows" group: Claude Code's `/workflows` keys as buttons. Pause or
19
+ * resume (`p`), stop the run (`x`), save its script as a workflow (`s`), and,
20
+ * per agent row, restart (`r`). Every control goes to the box that runs the
21
+ * run: the session that called `workflow`, or a background run's runner.
22
+ */
23
+ /** A run's large-run warning: more agents than Claude Code's "Large workflow" threshold, or the run says so. */
24
+ export function isLargeRun(run) {
25
+ return run.large === true || run.agents.length > WORKFLOW_LARGE_AGENT_COUNT;
26
+ }
27
+ /** The file name a run saves as: its saved name, else its title in kebab case. */
28
+ export function workflowFileName(run) {
29
+ const base = (run.name || run.title || '')
30
+ .toLowerCase()
31
+ .normalize('NFKD')
32
+ .replace(/[^a-z0-9]+/g, '-')
33
+ .replace(/^-+|-+$/g, '')
34
+ .slice(0, 48)
35
+ .replace(/-+$/g, '');
36
+ return base || 'workflow';
37
+ }
38
+ /**
39
+ * The live copy of a run: a background run's progress lives on its runner's box,
40
+ * so it is read from there (`useSessionWorkflows(project, runner)`, polled while it
41
+ * runs) and keeps updating after this session's turn ended. A foreground run is the
42
+ * card's own metadata. `controlSessionId` is the session whose box takes the controls.
43
+ */
44
+ export function useLiveWorkflowRun(projectId, sessionId, run) {
45
+ const runner = run?.background?.sessionId;
46
+ const { data } = useSessionWorkflows(projectId, runner, { enabled: !!projectId && !!runner });
47
+ const live = useMemo(() => {
48
+ if (!run || !runner || !data)
49
+ return null;
50
+ const match = data.find((candidate) => candidate.runId === run.runId) ?? (run.runId ? undefined : data[0]);
51
+ const parsed = match ? parseWorkflowRun(match) : null;
52
+ // The runner runs it in the foreground; this card still knows it as a background run.
53
+ return parsed ? { ...parsed, background: run.background } : null;
54
+ }, [run, runner, data]);
55
+ if (!run)
56
+ return { run: null, controlSessionId: undefined, fromRunner: false };
57
+ if (runner)
58
+ return { run: live ?? run, controlSessionId: runner, fromRunner: !!live };
59
+ return { run, controlSessionId: sessionId, fromRunner: false };
60
+ }
61
+ /** The current time, every second while `active`: a live run's elapsed labels tick. */
62
+ export function useNow(active) {
63
+ const [now, setNow] = useState(() => Date.now());
64
+ useEffect(() => {
65
+ if (!active)
66
+ return;
67
+ const timer = setInterval(() => setNow(Date.now()), 1_000);
68
+ return () => clearInterval(timer);
69
+ }, [active]);
70
+ return now;
71
+ }
72
+ /** The prompt "Save" sends to the session that owns the run. */
73
+ export function useSaveWorkflowPrompt() {
74
+ const t = useTranslations('multiAgent.workflow');
75
+ return (run) => t('savePrompt', { title: run.title || run.name || run.runId, runId: run.runId, file: `.kortix/workflows/${workflowFileName(run)}.js` });
76
+ }
77
+ export function LargeRunBadge() {
78
+ const t = useTranslations('multiAgent.workflow');
79
+ return (_jsx(Hint, { label: t('largeHint'), side: "top", children: _jsxs(Badge, { variant: "warning", size: "sm", children: [_jsx(WarningIcon, { weight: "fill", "aria-hidden": true }), t('large')] }) }));
80
+ }
81
+ export function WorkflowRunControls({ projectId, controlSessionId, ownerSessionId, run }) {
82
+ const t = useTranslations('multiAgent.workflow');
83
+ const { control } = useSessionWorkflows(projectId, controlSessionId, { enabled: false });
84
+ const send = useSessionPromptSend(ownerSessionId);
85
+ const savePrompt = useSaveWorkflowPrompt();
86
+ const running = run.status === 'running';
87
+ const canControl = !!projectId && !!controlSessionId && !!run.runId && running;
88
+ const pending = control.isPending ? control.variables?.body.action : undefined;
89
+ const act = (action) => control.mutate({ runId: run.runId, body: { action } }, {
90
+ onError: (error) => errorToast(t(`failed.${action}`), { description: error instanceof Error ? error.message : undefined }),
91
+ });
92
+ const save = async () => {
93
+ if (!send)
94
+ return;
95
+ try {
96
+ await send(savePrompt(run));
97
+ successToast(t('saveSent'));
98
+ }
99
+ catch (error) {
100
+ errorToast(t('saveFailed'), { description: error instanceof Error ? error.message : undefined });
101
+ }
102
+ };
103
+ const buttons = [
104
+ canControl && (_jsx(Hint, { label: run.paused ? t('resumeHint') : t('pauseHint'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": run.paused ? t('resume') : t('pause'), disabled: !!pending, onClick: (event) => {
105
+ event.stopPropagation();
106
+ act(run.paused ? 'resume' : 'pause');
107
+ }, children: pending === 'pause' || pending === 'resume' ? (_jsx(Loading, { className: "size-3 shrink-0" })) : run.paused ? (_jsx(PlayIcon, { weight: "fill", className: "size-3 shrink-0" })) : (_jsx(PauseIcon, { weight: "fill", className: "size-3 shrink-0" })) }) }, "pause")),
108
+ canControl && (_jsx(Hint, { label: t('stopHint'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": t('stop'), disabled: !!pending, onClick: (event) => {
109
+ event.stopPropagation();
110
+ act('stop');
111
+ }, children: pending === 'stop' ? _jsx(Loading, { className: "size-3 shrink-0" }) : _jsx(SquareIcon, { weight: "fill", className: "size-2.5 shrink-0" }) }) }, "stop")),
112
+ // A saved workflow is a file already; any other run can become one.
113
+ !run.name && send && run.runId && (_jsx(Hint, { label: t('saveHint'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": t('save'), onClick: (event) => {
114
+ event.stopPropagation();
115
+ void save();
116
+ }, children: _jsx(FloppyDiskIcon, { className: "size-3 shrink-0" }) }) }, "save")),
117
+ ].filter(Boolean);
118
+ if (buttons.length === 0)
119
+ return null;
120
+ return buttons.length === 1 ? _jsx(_Fragment, { children: buttons }) : _jsx(ButtonGroup, { children: buttons });
121
+ }
122
+ /** `restart_agent` for one agent row of a run, on the box that runs it. */
123
+ export function useRestartAgent(projectId, controlSessionId, run) {
124
+ const t = useTranslations('multiAgent.workflow');
125
+ const { control } = useSessionWorkflows(projectId, controlSessionId, { enabled: false });
126
+ const enabled = !!projectId && !!controlSessionId && !!run?.runId && run.status === 'running';
127
+ const restarting = control.isPending && control.variables?.body.action === 'restart_agent' ? control.variables.body.session_id : undefined;
128
+ return {
129
+ enabled,
130
+ restarting,
131
+ restart: (agent) => {
132
+ if (!enabled || !agent.sessionId || !run)
133
+ return;
134
+ control.mutate({ runId: run.runId, body: { action: 'restart_agent', session_id: agent.sessionId } }, {
135
+ onError: (error) => errorToast(t('failed.restart', { label: agent.label }), {
136
+ description: error instanceof Error ? error.message : undefined,
137
+ }),
138
+ });
139
+ },
140
+ };
141
+ }
@@ -71,4 +71,4 @@ export interface ComposerCardDerived {
71
71
  noModelsConnected: boolean;
72
72
  }
73
73
  export type ComposerCardProps = SessionChatInputProps & ComposerCardDerived;
74
- export declare function ComposerCard({ tHardcodedUi, isDragOver, handleDragEnter, handleDragOver, handleDragLeave, handleDropFiles, attachedFiles, promptAttachmentItems, removeAttachedFile, retryAttachedFile, pastes, removePaste, onOpenPastedContent, commandAttachmentPlan, editorDisabled, editorRef, setEditorRef, editorPlaceholder, animatePlaceholder, handleSubmit, handleArrowUpAtStart, setIsEmpty, handleDocChange, allSessions, slashActions, handleSelectAction, dockId, setMenuOpen, fileInputRef, handleFileSelect, sessionId, handleAttachClick, primaryAgents, availableSelectedModel, agentMenuOpen, setAgentMenuOpen, modelMenuOpen, setModelMenuOpen, reasoningMenuOpen, setReasoningMenuOpen, isEmpty, canSubmit, submitDisabled, attachmentFailed, modelRejectingImages, imagesUnsupportedReason, modelUnavailable, agentUnavailable, noModelsConnected, agents, commands, slashFiles, models, notice, disabled, lockForQuestion, lockForApproval, questionButtonLabel, questionActive, submitLabel, questionCanAct, escCount, isBusy, isSending, onStop, stopDisabled, canStop, modelsLoading, modelRequired, onModelChange, modelDefaultControls, providers, variants, selectedVariant, onVariantChange, projectId, toolbarSlot, rewind, selectedAgent, onAgentChange, noAccessibleAgents, onContextClick, messages, underbarPlacement, agentPickerCompact, slashMenuPlacement, cardClassName, onArrowUpAtStart, }: ComposerCardProps): import("react").JSX.Element;
74
+ export declare function ComposerCard({ tHardcodedUi, isDragOver, handleDragEnter, handleDragOver, handleDragLeave, handleDropFiles, attachedFiles, promptAttachmentItems, removeAttachedFile, retryAttachedFile, pastes, removePaste, onOpenPastedContent, commandAttachmentPlan, editorDisabled, editorRef, setEditorRef, editorPlaceholder, animatePlaceholder, handleSubmit, handleArrowUpAtStart, setIsEmpty, handleDocChange, allSessions, slashActions, handleSelectAction, dockId, setMenuOpen, fileInputRef, handleFileSelect, sessionId, handleAttachClick, primaryAgents, availableSelectedModel, agentMenuOpen, setAgentMenuOpen, modelMenuOpen, setModelMenuOpen, reasoningMenuOpen, setReasoningMenuOpen, isEmpty, canSubmit, submitDisabled, attachmentFailed, modelRejectingImages, imagesUnsupportedReason, modelUnavailable, agentUnavailable, noModelsConnected, agents, commands, slashFiles, models, notice, disabled, lockForQuestion, lockForApproval, questionButtonLabel, questionActive, submitLabel, questionCanAct, escCount, isBusy, isSending, onStop, stopDisabled, canStop, modelsLoading, modelRequired, onModelChange, modelDefaultControls, providers, variants, selectedVariant, onVariantChange, projectId, toolbarSlot, underbarSlot, rewind, selectedAgent, onAgentChange, noAccessibleAgents, onContextClick, messages, underbarPlacement, agentPickerCompact, slashMenuPlacement, cardClassName, onArrowUpAtStart, }: ComposerCardProps): import("react").JSX.Element;
@@ -21,7 +21,7 @@ export function ComposerCard({ tHardcodedUi, isDragOver, handleDragEnter, handle
21
21
  // Raw props the moved JSX reads; `{...props}` carries the rest. These
22
22
  // defaults mirror `ComposerImpl`'s, because the spread passes the raw
23
23
  // values, not the component's defaulted locals.
24
- agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES, models = EMPTY_MODELS, notice = null, disabled = false, lockForQuestion = false, lockForApproval = false, questionButtonLabel = null, questionActive = false, submitLabel = null, questionCanAct = true, escCount = 0, isBusy = false, isSending = false, onStop, stopDisabled = false, canStop = true, modelsLoading = false, modelRequired = false, onModelChange, modelDefaultControls, providers, variants = EMPTY_VARIANTS, selectedVariant = null, onVariantChange, projectId, toolbarSlot, rewind, selectedAgent = null, onAgentChange, noAccessibleAgents = false, onContextClick, messages, underbarPlacement = 'below', agentPickerCompact = false, slashMenuPlacement = 'above', cardClassName, onArrowUpAtStart, }) {
24
+ agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES, models = EMPTY_MODELS, notice = null, disabled = false, lockForQuestion = false, lockForApproval = false, questionButtonLabel = null, questionActive = false, submitLabel = null, questionCanAct = true, escCount = 0, isBusy = false, isSending = false, onStop, stopDisabled = false, canStop = true, modelsLoading = false, modelRequired = false, onModelChange, modelDefaultControls, providers, variants = EMPTY_VARIANTS, selectedVariant = null, onVariantChange, projectId, toolbarSlot, underbarSlot, rewind, selectedAgent = null, onAgentChange, noAccessibleAgents = false, onContextClick, messages, underbarPlacement = 'below', agentPickerCompact = false, slashMenuPlacement = 'above', cardClassName, onArrowUpAtStart, }) {
25
25
  const cardRef = useRef(null);
26
26
  const { attachAccept } = useUiHostConfig();
27
27
  const inlineUnderbar = underbarPlacement === 'inline';
@@ -51,7 +51,7 @@ agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES
51
51
  // the div and immediately fights the caret we are placing.
52
52
  e.preventDefault();
53
53
  editorRef.current?.focus();
54
- }, children: [_jsx(AnimatedComposerPlaceholder, { placeholder: editorPlaceholder, active: animatePlaceholder }), _jsx(Suspense, { fallback: _jsx(ComposerEditorFallback, {}), children: _jsx(ComposerEditorLazy, { ref: setEditorRef, placeholder: animatePlaceholder ? '' : editorPlaceholder, disabled: editorDisabled, onSubmit: handleSubmit, onArrowUpAtStart: onArrowUpAtStart ? handleArrowUpAtStart : undefined, onEmptyChange: setIsEmpty, onDocChange: handleDocChange, agents: agents, sessions: allSessions ?? [], currentSessionId: sessionId, commands: commands, actions: slashActions, files: slashFiles, onSelectAction: handleSelectAction, slashDockSelector: `#${dockId}`, onMenuOpenChange: setMenuOpen }) })] }), _jsx("input", { ref: fileInputRef, type: "file", accept: attachAccept ?? DEFAULT_ATTACH_ACCEPT, multiple: true, className: "hidden", onChange: handleFileSelect }), _jsx(ComposerToolbar, { leading: inlineUnderbar ? (_jsx(ComposerUnderbar, { variant: "inline", agentPickerCompact: agentPickerCompact, onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick })) : null, modelsLoading: modelsLoading, models: models, selectedModel: availableSelectedModel, onModelChange: onModelChange, modelDefaultControls: modelDefaultControls, providers: providers, modelRequired: modelRequired, modelMenuOpen: modelMenuOpen, onModelMenuOpenChange: setModelMenuOpen, reasoningMenuOpen: reasoningMenuOpen, onReasoningMenuOpenChange: setReasoningMenuOpen, variants: variants, selectedVariant: selectedVariant, onVariantChange: onVariantChange, projectId: projectId,
54
+ }, children: [_jsx(AnimatedComposerPlaceholder, { placeholder: editorPlaceholder, active: animatePlaceholder }), _jsx(Suspense, { fallback: _jsx(ComposerEditorFallback, {}), children: _jsx(ComposerEditorLazy, { ref: setEditorRef, placeholder: animatePlaceholder ? '' : editorPlaceholder, disabled: editorDisabled, onSubmit: handleSubmit, onArrowUpAtStart: onArrowUpAtStart ? handleArrowUpAtStart : undefined, onEmptyChange: setIsEmpty, onDocChange: handleDocChange, agents: agents, sessions: allSessions ?? [], currentSessionId: sessionId, commands: commands, actions: slashActions, files: slashFiles, onSelectAction: handleSelectAction, slashDockSelector: `#${dockId}`, onMenuOpenChange: setMenuOpen }) })] }), _jsx("input", { ref: fileInputRef, type: "file", accept: attachAccept ?? DEFAULT_ATTACH_ACCEPT, multiple: true, className: "hidden", onChange: handleFileSelect }), _jsx(ComposerToolbar, { leading: inlineUnderbar ? (_jsx(ComposerUnderbar, { variant: "inline", agentPickerCompact: agentPickerCompact, onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick, agentsSlot: underbarSlot })) : null, modelsLoading: modelsLoading, models: models, selectedModel: availableSelectedModel, onModelChange: onModelChange, modelDefaultControls: modelDefaultControls, providers: providers, modelRequired: modelRequired, modelMenuOpen: modelMenuOpen, onModelMenuOpenChange: setModelMenuOpen, reasoningMenuOpen: reasoningMenuOpen, onReasoningMenuOpenChange: setReasoningMenuOpen, variants: variants, selectedVariant: selectedVariant, onVariantChange: onVariantChange, projectId: projectId,
55
55
  // Inline placement has no under-row, so the slot (the session
56
56
  // overrides gear, meta indicator) rides the toolbar itself. With
57
57
  // the 'below' placement the ComposerUnderbar further down renders
@@ -59,5 +59,5 @@ agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES
59
59
  toolbarSlot: inlineUnderbar ? toolbarSlot : undefined, rewind: rewind, isSending: isSending, isBusy: isBusy, onStop: onStop, stopDisabled: stopDisabled, canStop: canStop, escCount: escCount, lockForQuestion: lockForQuestion, questionButtonLabel: questionButtonLabel, submitLabel: submitLabel, questionCanAct: questionCanAct, hasText: !isEmpty, canSubmit: canSubmit, submitDisabled: submitDisabled ||
60
60
  attachmentFailed ||
61
61
  modelRejectingImages !== null ||
62
- commandAttachmentPlan.kind === 'refuse', attachmentFailed: attachmentFailed, attachmentUnsupported: imagesUnsupportedReason, disabled: disabled, modelUnavailable: modelUnavailable, agentUnavailable: agentUnavailable, onSubmit: () => handleSubmit() })] })] })] }), _jsx(ModelConnectionBar, { show: noModelsConnected }), _jsx(ImagesUnsupportedBar, { modelName: noModelsConnected ? null : modelRejectingImages }), inlineUnderbar ? null : (_jsx(ComposerUnderbar, { onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick, toolbarSlot: toolbarSlot })), slashMenuPlacement === 'below' && (_jsx("div", { id: dockId, className: "absolute top-full right-4 left-4 z-99 mt-3.5" }))] }));
62
+ commandAttachmentPlan.kind === 'refuse', attachmentFailed: attachmentFailed, attachmentUnsupported: imagesUnsupportedReason, disabled: disabled, modelUnavailable: modelUnavailable, agentUnavailable: agentUnavailable, onSubmit: () => handleSubmit() })] })] })] }), _jsx(ModelConnectionBar, { show: noModelsConnected }), _jsx(ImagesUnsupportedBar, { modelName: noModelsConnected ? null : modelRejectingImages }), inlineUnderbar ? null : (_jsx(ComposerUnderbar, { onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick, toolbarSlot: toolbarSlot, agentsSlot: underbarSlot })), slashMenuPlacement === 'below' && (_jsx("div", { id: dockId, className: "absolute top-full right-4 left-4 z-99 mt-3.5" }))] }));
63
63
  }
@@ -1,6 +1,5 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Badge } from '../../primitives/badge.js';
4
3
  import { Button } from '../../primitives/button.js';
5
4
  import { CommandGroup, CommandInput, CommandItem, CommandList, CommandPopover, CommandPopoverContent, CommandPopoverTrigger, CommandSeparator, } from '../../primitives/command.js';
6
5
  import Hint from '../../primitives/hint.js';
@@ -8,7 +7,7 @@ import { useTranslations } from '../../i18n/index.js';
8
7
  import { useUiHostConfig } from '../../providers/ui-provider.js';
9
8
  import { cn } from '../../lib/utils.js';
10
9
  import { TRIGGER_CARET_CLASS, triggerVariants } from '../../primitives/trigger-variants.js';
11
- import { capitalizeWords, isMetaAgentName, META_AGENT_DISPLAY_NAME } from '../../_vendor/kortix-shared.js';
10
+ import { capitalizeWords, isMyKortixAgentName, MY_KORTIX_DISPLAY_NAME } from '../../_vendor/kortix-shared.js';
12
11
  import { CaretDownIcon, CheckIcon } from '@phosphor-icons/react';
13
12
  import { AgentMark } from '../../internal/components/agent-mark.js';
14
13
  import { createContext, useContext, useEffect, useMemo, useState } from 'react';
@@ -42,7 +41,7 @@ export function agentDisplayLabel(agents, selectedAgent) {
42
41
  const name = resolveDisplayedAgentName(composerSelectableAgents(agents), selectedAgent);
43
42
  if (!name)
44
43
  return 'Agent';
45
- return isMetaAgentName(name) ? META_AGENT_DISPLAY_NAME : capitalizeWords(name);
44
+ return isMyKortixAgentName(name) ? MY_KORTIX_DISPLAY_NAME : capitalizeWords(name);
46
45
  }
47
46
  export function AgentSelector({ agents, selectedAgent, onSelect, disabled = false, triggerLabelClassName, unavailableHint, open: controlledOpen, onOpenChange, compact = false, appearance = 'chip', }) {
48
47
  const tHardcodedUi = useTranslations('hardcodedUi');
@@ -60,7 +59,7 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
60
59
  return agents.filter((a) => offeredNames.has(a.name));
61
60
  }, [agents, offeredAgents]);
62
61
  const primaryAgents = useMemo(() => composerSelectableAgents(offered), [offered]);
63
- const label = (name) => agentLabels?.[name] ?? (isMetaAgentName(name) ? META_AGENT_DISPLAY_NAME : capitalizeWords(name));
62
+ const label = (name) => agentLabels?.[name] ?? (isMyKortixAgentName(name) ? MY_KORTIX_DISPLAY_NAME : capitalizeWords(name));
64
63
  // A `flash` state, a `prevAgentRef` feeding it, two effects and a 400ms
65
64
  // timer used to live here. Nothing ever READ `flash` — it was written on
66
65
  // every agent change and rendered nowhere, so the whole apparatus bought a
@@ -77,8 +76,8 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
77
76
  (agentLabels?.[a.name] ?? '').toLowerCase().includes(q) ||
78
77
  (a.description || '').toLowerCase().includes(q));
79
78
  }, [primaryAgents, search, agentLabels]);
80
- const filteredMeta = useMemo(() => filteredPrimary.filter((a) => isMetaAgentName(a.name)), [filteredPrimary]);
81
- const filteredProject = useMemo(() => filteredPrimary.filter((a) => !isMetaAgentName(a.name)), [filteredPrimary]);
79
+ const filteredMeta = useMemo(() => filteredPrimary.filter((a) => isMyKortixAgentName(a.name)), [filteredPrimary]);
80
+ const filteredProject = useMemo(() => filteredPrimary.filter((a) => !isMyKortixAgentName(a.name)), [filteredPrimary]);
82
81
  // The place's agents, in its order, then every other agent.
83
82
  const featured = useContext(FeaturedAgentsContext);
84
83
  const filteredFeatured = useMemo(() => (featured?.names ?? []).flatMap((name) => {
@@ -106,16 +105,11 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
106
105
  const field = appearance === 'field';
107
106
  const fieldTrigger = (caret, props) => (_jsxs("button", { type: "button", className: cn(triggerVariants(), 'h-9 w-full'), ...props, children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [triggerMark, _jsx("span", { className: "truncate", children: displayName })] }), caret ? _jsx(CaretDownIcon, { className: cn(TRIGGER_CARET_CLASS, 'size-4') }) : null] }));
108
107
  /**
109
- * One agent: name, its type, its description, and a check when it is the
110
- * one in use.
108
+ * One agent: its mark, name and description (My Kortix: what picking it
109
+ * does), and a check when it is the one in use.
111
110
  *
112
- * The type is a `Badge` on the row rather than a `CommandGroup` heading.
113
- * Headings only earn their place when there is more than one section to
114
- * tell apart, and there usually is not — most projects have no meta agents
115
- * at all, so the list rendered a lone "Agents" label over a single group,
116
- * captioning something that needed no caption. A badge says the same thing
117
- * where it is actually useful (on the row that differs) and disappears
118
- * entirely when every agent is the same kind.
111
+ * No type badge and no group heading: My Kortix sorts first, a separator
112
+ * follows it, and its own line says what it does.
119
113
  *
120
114
  * Selection is shown ONCE, by the check plus the tinted row. It used to be
121
115
  * said three times — check, tinted row, AND a heavier font weight on the
@@ -131,7 +125,7 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
131
125
  className: cn('items-start gap-2 py-2', isSelected && 'bg-primary/[0.06]'), onSelect: () => {
132
126
  onSelect(agent.name);
133
127
  setOpen(false);
134
- }, children: [agent.description ? (_jsx(AgentMark, { slug: agent.name, size: 28, tile: 36 })) : (_jsx(AgentMark, { slug: agent.name, size: 14 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [_jsx("span", { className: "text-foreground truncate text-sm font-medium", children: label(agent.name) }), meta && (_jsx(Badge, { variant: "outline", size: "xs", className: "shrink-0 font-normal", children: tHardcodedUi.raw('i18nComplete.textc78ffe195710') }))] }), agent.description && (_jsx("p", { className: "text-muted-foreground truncate text-xs", children: agent.description }))] }), isSelected && (
128
+ }, children: [agent.description || meta ? (_jsx(AgentMark, { slug: agent.name, size: 28, tile: 36 })) : (_jsx(AgentMark, { slug: agent.name, size: 14 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "text-foreground block truncate text-sm font-medium", children: label(agent.name) }), meta ? (_jsx("p", { className: "text-muted-foreground text-xs", children: t('myKortixRoutes') })) : agent.description ? (_jsx("p", { className: "text-muted-foreground line-clamp-2 text-xs text-pretty", children: agent.description })) : null] }), isSelected && (
135
129
  // `mt-0.5` optically centres the 16px check against the first line
136
130
  // rather than the top edge of the text box.
137
131
  _jsx(CheckIcon, { className: "text-foreground mt-0.5 size-4 shrink-0" }))] }, agent.name));
@@ -173,11 +167,11 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
173
167
  // The mark alone: the name is the tooltip and the menu's checked row.
174
168
  // A placeholder name has no mark, so it shows as text.
175
169
  triggerMark ?? _jsx("span", { className: cn('max-w-[100px] truncate', triggerLabelClassName), children: displayName })) : (_jsxs(_Fragment, { children: [triggerMark, _jsx("span", { className: cn('max-w-[100px] truncate', triggerLabelClassName), children: displayName }), _jsx(CaretDownIcon, { className: cn('size-3 transition-transform duration-moderate ease-out', open && 'rotate-180') })] })) })) }));
176
- return (_jsxs(CommandPopover, { open: open, onOpenChange: setOpen, children: [compact ? (_jsx(Hint, { side: "top", label: displayName, children: trigger })) : (trigger), _jsxs(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(300px,calc(100vw-1.5rem))]", children: [_jsx("div", { className: showSearch ? undefined : 'sr-only', children: _jsx(CommandInput, { compact: true, placeholder: tHardcodedUi.raw('componentsSessionSessionChatInput.line231JsxAttrPlaceholderSearchAgents'), value: search, onValueChange: setSearch }) }), _jsxs(CommandList, { className: "max-h-[320px]", children: [filteredFeatured.length > 0 && featured ? (
170
+ return (_jsxs(CommandPopover, { open: open, onOpenChange: setOpen, children: [compact ? (_jsx(Hint, { side: "top", label: displayName, children: trigger })) : (trigger), _jsxs(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(340px,calc(100vw-1.5rem))]", children: [_jsx("div", { className: showSearch ? undefined : 'sr-only', children: _jsx(CommandInput, { compact: true, placeholder: tHardcodedUi.raw('componentsSessionSessionChatInput.line231JsxAttrPlaceholderSearchAgents'), value: search, onValueChange: setSearch }) }), _jsxs(CommandList, { className: "max-h-[320px]", children: [filteredFeatured.length > 0 && featured ? (
177
171
  // Two groups, so each earns its heading: the place's agents, then the rest.
178
- _jsxs(_Fragment, { children: [_jsx(CommandGroup, { forceMount: true, heading: featured.label, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredFeatured.map((agent) => renderAgentItem(agent, isMetaAgentName(agent.name))) }), filteredPrimary.length > filteredFeatured.length && (_jsx(CommandGroup, { forceMount: true, heading: featured.restLabel, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredPrimary
172
+ _jsxs(_Fragment, { children: [_jsx(CommandGroup, { forceMount: true, heading: featured.label, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredFeatured.map((agent) => renderAgentItem(agent, isMyKortixAgentName(agent.name))) }), filteredPrimary.length > filteredFeatured.length && (_jsx(CommandGroup, { forceMount: true, heading: featured.restLabel, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredPrimary
179
173
  .filter((agent) => !filteredFeatured.includes(agent))
180
- .map((agent) => renderAgentItem(agent, isMetaAgentName(agent.name))) }))] })) : filteredPrimary.length > 0 && (
174
+ .map((agent) => renderAgentItem(agent, isMyKortixAgentName(agent.name))) }))] })) : filteredPrimary.length > 0 && (
181
175
  // `gap-px` between rows: a selected row and a hovered row next to it
182
176
  // otherwise draw one merged grey block.
183
177
  _jsxs(CommandGroup, { forceMount: true, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: [filteredMeta.map((agent) => renderAgentItem(agent, true)), filteredMeta.length > 0 && filteredProject.length > 0 && (_jsx(CommandSeparator, { className: "my-1" })), filteredProject.map((agent) => renderAgentItem(agent, false))] })), filteredPrimary.length === 0 && search.trim() && (_jsxs("div", { className: "text-muted-foreground py-8 text-center text-xs", children: [tHardcodedUi.raw('componentsSessionSessionChatInput.line273JsxTextNoAgentsMatchLdquo'), search.trim(), tHardcodedUi.raw('componentsSessionSessionChatInput.line273JsxTextRdquo')] }))] })] })] }));
@@ -52,5 +52,7 @@ export interface ComposerUnderbarProps {
52
52
  /** See `SessionChatInputProps.agentPickerCompact`. */
53
53
  agentPickerCompact?: boolean;
54
54
  toolbarSlot?: React.ReactNode;
55
+ /** Right of the agent picker: the session's agents line. Same row, no added height. */
56
+ agentsSlot?: React.ReactNode;
55
57
  }
56
- export declare function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents, messages, models, selectedModel, onContextClick, variant, agentPickerCompact, toolbarSlot, }: ComposerUnderbarProps): import("react").JSX.Element;
58
+ export declare function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents, messages, models, selectedModel, onContextClick, variant, agentPickerCompact, toolbarSlot, agentsSlot, }: ComposerUnderbarProps): import("react").JSX.Element;
@@ -14,7 +14,7 @@ import { TokenProgress } from './token-progress.js';
14
14
  const NO_AGENT_SELECT = () => { };
15
15
  /** Stable identity so the empty roster doesn't remount the picker per render. */
16
16
  const EMPTY_AGENTS = [];
17
- export function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents = false, messages, models, selectedModel, onContextClick, variant = 'row', agentPickerCompact = false, toolbarSlot, }) {
17
+ export function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents = false, messages, models, selectedModel, onContextClick, variant = 'row', agentPickerCompact = false, toolbarSlot, agentsSlot, }) {
18
18
  const t = useTranslations('threads');
19
19
  const { contextMeterEnabled } = useUiHostConfig();
20
20
  /*
@@ -55,5 +55,5 @@ export function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMe
55
55
  : 'kortix-composer-underbar flex items-center justify-between gap-2 px-px pt-1.5 pb-2', children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [_jsx(Hint, { side: "top", label: t('attachFiles'), children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-base", onClick: onAttachClick, "aria-label": t('attachFiles'),
56
56
  // `hit-area-3` — the ≈29px ghost chip clears the 44px mobile tap
57
57
  // floor only with the shared pseudo-element extension.
58
- className: "text-muted-foreground hit-area-3 rounded-lg", children: _jsx(Paperclip, { className: "size-4 shrink-0" }) }) }), _jsx(AgentSelector, { compact: agentPickerCompact, agents: noAccessibleAgents ? EMPTY_AGENTS : agents, selectedAgent: selectedAgent, open: agentMenuOpen, onOpenChange: onAgentMenuOpenChange, onSelect: onAgentChange ?? NO_AGENT_SELECT, triggerLabelClassName: "max-w-[7rem]", unavailableHint: noAccessibleAgents ? NO_AGENT_ACCESS_MESSAGE : undefined })] }), _jsxs("div", { className: "flex items-center gap-1", children: [(inline && !messages) || !contextMeterEnabled ? null : (_jsx(TokenProgress, { messages: messages, models: models, selectedModel: selectedModel, onContextClick: onContextClick })), toolbarSlot] })] }));
58
+ className: "text-muted-foreground hit-area-3 rounded-lg", children: _jsx(Paperclip, { className: "size-4 shrink-0" }) }) }), _jsx(AgentSelector, { compact: agentPickerCompact, agents: noAccessibleAgents ? EMPTY_AGENTS : agents, selectedAgent: selectedAgent, open: agentMenuOpen, onOpenChange: onAgentMenuOpenChange, onSelect: onAgentChange ?? NO_AGENT_SELECT, triggerLabelClassName: "max-w-[7rem]", unavailableHint: noAccessibleAgents ? NO_AGENT_ACCESS_MESSAGE : undefined }), agentsSlot] }), _jsxs("div", { className: "flex items-center gap-1", children: [(inline && !messages) || !contextMeterEnabled ? null : (_jsx(TokenProgress, { messages: messages, models: models, selectedModel: selectedModel, onContextClick: onContextClick })), toolbarSlot] })] }));
59
59
  }
@@ -234,6 +234,11 @@ export interface SessionChatInputProps {
234
234
  aboveSlot?: React.ReactNode;
235
235
  inputSlot?: React.ReactNode;
236
236
  toolbarSlot?: React.ReactNode;
237
+ /**
238
+ * Rides the under-row right of the agent picker, in both placements: the
239
+ * session's agents line (`AgentsLine`). It must not add height to the row.
240
+ */
241
+ underbarSlot?: React.ReactNode;
237
242
  /**
238
243
  * Where the under-row's controls live — attach, the agent picker and the
239
244
  * context ring.
@@ -5,7 +5,8 @@ import { useUiHostConfig } from '../../providers/ui-provider.js';
5
5
  import { useTranslations } from '../../i18n/index.js';
6
6
  import { cn } from '../../lib/utils.js';
7
7
  import { isImageFile } from '../../internal/lib/utils/file-utils.js';
8
- import { usePromptAttachments, useRuntimeSessions } from '@kortix/sdk/react';
8
+ import { useProjectConfig, usePromptAttachments, useRuntimeSessions } from '@kortix/sdk/react';
9
+ import { useActiveSpace } from '../../internal/stores/active-space-store.js';
9
10
  import { newPastedContentId, splitPastedContent, trimPastedText } from '../../_vendor/kortix-shared.js';
10
11
  import { memo, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
11
12
  import { extractClipboardFiles } from './clipboard-files.js';
@@ -16,7 +17,6 @@ import { isModelRequiredButUnavailable, NO_MODEL_AVAILABLE_ACTION_MESSAGE, NO_MO
16
17
  import { useModelConnectionGate } from '../models/use-model-connection-gate.js';
17
18
  import { NO_AGENT_ACCESS_HINT, NO_AGENT_ACCESS_LABEL } from './composer-agent-access.js';
18
19
  import { useComposerDropZone } from './composer-drop-zone.js';
19
- import { useComposerEscapeStop } from './hooks/use-composer-escape-stop.js';
20
20
  import { finishedDraftUploads, keepUnsentUploadFile, restoreDraftUploads } from './draft/draft-uploads.js';
21
21
  import { useComposerDraft } from './draft/use-composer-draft.js';
22
22
  import { commandBlocker, sendBlocker, sendBlockerMessage } from './send-blockers.js';
@@ -110,7 +110,7 @@ function setDocumentWithoutStealingFocus(handle, doc) {
110
110
  }
111
111
  }
112
112
  function ComposerImpl(props) {
113
- const { onSend, promptAttachments: hostPromptAttachments, isBusy = false, sessionWorking, runtimeReady = true, onStop, stopDisabled = false, canStop = true, isSending = false, rewind, agents = EMPTY_AGENTS, selectedAgent = null, onAgentChange, noAccessibleAgents = false, commands: runtimeCommands = EMPTY_COMMANDS,
113
+ const { onSend, promptAttachments: hostPromptAttachments, isBusy = false, sessionWorking, runtimeReady = true, onStop, stopDisabled = false, isSending = false, rewind, agents = EMPTY_AGENTS, selectedAgent = null, onAgentChange, noAccessibleAgents = false, commands: runtimeCommands = EMPTY_COMMANDS,
114
114
  /** Whether the live command list has EVER resolved — see `planUnresolvedCommandChip`. */
115
115
  commandsResolved = false, slashFiles = EMPTY_SLASH_FILES, onCommand, onHoldCommand, models = EMPTY_MODELS, selectedModel = null, onModelChange, modelDefaultControls, variants = EMPTY_VARIANTS, selectedVariant = null, onVariantChange, messages, sessionId, projectId, draftScope = null, draftActive = true, disabled = false, notice = null, onNoticeRetry, clearOnSend = true, modelRequired = false, modelsLoading = false, autoFocus, placeholder = 'Ask anything…', hint, onArrowUpAtStart, prefill = null, onPrefillApplied, attachRequestId = null, providers, onContextClick, onCompactClick, inputSlot, toolbarSlot, underbarPlacement = 'below', slashMenuPlacement = 'above', cardClassName, quoteRequests = NO_QUOTE_REQUESTS, onQuoteRequestsApplied, lockForQuestion = false, lockForApproval = false, onCustomAnswer, questionButtonLabel = null, questionCanAct = true, onQuestionAction, escCount = 0, parentClassName, } = props;
116
116
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
@@ -317,7 +317,19 @@ function ComposerImpl(props) {
317
317
  handleDocChange(doc, isEmpty);
318
318
  }, [handleDocChange]);
319
319
  const { data: allSessions } = useRuntimeSessions();
320
- const primaryAgents = useMemo(() => agents.filter((a) => !a.hidden && a.mode !== 'subagent'), [agents]);
320
+ // Scope the startable agents to the active space (the sidebar's Spaces
321
+ // selection): in a space you start only that space's agents. The current
322
+ // agent is always kept so a session's own agent never disappears while you
323
+ // are viewing another space. No space selected = every agent, as before.
324
+ const [activeSpace] = useActiveSpace(projectId ?? '');
325
+ const scopeConfig = useProjectConfig(projectId);
326
+ const primaryAgents = useMemo(() => {
327
+ const base = agents.filter((a) => !a.hidden && a.mode !== 'subagent');
328
+ if (!activeSpace || !scopeConfig)
329
+ return base;
330
+ const spaceByName = new Map(scopeConfig.agents.map((a) => [a.name, a.space ?? null]));
331
+ return base.filter((a) => spaceByName.get(a.name) === activeSpace || a.name === selectedAgent);
332
+ }, [agents, activeSpace, scopeConfig, selectedAgent]);
321
333
  const editorDisabled = disabled || lockForApproval;
322
334
  const appendAttachedFiles = useCallback((files) => {
323
335
  // The host keeps files in its own store: they go there, not to the session.
@@ -676,12 +688,6 @@ function ComposerImpl(props) {
676
688
  const canSubmit = !isEmpty ||
677
689
  attachedFiles.length > 0 ||
678
690
  (!lockForQuestion && (quotes.length > 0 || pastes.length > 0));
679
- useComposerEscapeStop({
680
- editorElement,
681
- enabled: isBusy && canStop && !stopDisabled && !isSending && !lockForQuestion && !props.submitLabel,
682
- hasDraft: canSubmit,
683
- onStop,
684
- });
685
691
  /**
686
692
  * No agent may run this prompt. Refused here rather than at the server:
687
693
  * `lockForQuestion` is exempt because answering an open question is not a new
@@ -1,9 +1,9 @@
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
3
  import { useTranslations } from '../../../i18n/index.js';
4
4
  import { cn } from '../../../lib/utils.js';
5
5
  import { EditorContent, useEditor } from '@tiptap/react';
6
- import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
6
+ import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
7
7
  import { textToParagraphs } from '../composer-logic.js';
8
8
  import { COMPOSER_TEXT_METRICS } from '../composer-text-metrics.js';
9
9
  import { useLatestRef } from '../hooks/use-latest-ref.js';
@@ -15,6 +15,7 @@ import { isCursorOnFirstVisualLine } from './first-visual-line.js';
15
15
  import { MentionNode } from './mention-node.js';
16
16
  import { serializeDocument } from './serialize.js';
17
17
  import { createSuggestionExtension } from './suggestion.js';
18
+ import { UltracodeHighlight } from './ultracode.js';
18
19
  /**
19
20
  * Wraps `onEmptyChange` so it fires ONLY on the empty<->non-empty boundary.
20
21
  * Exported (rather than kept as an inline `useEditor({ onUpdate })` closure)
@@ -161,8 +162,16 @@ export function insertTextAtCursor(editor, text) {
161
162
  return;
162
163
  editor.commands.insertContent(content);
163
164
  }
165
+ /** The dismiss shortcut as the person's keyboard prints it. */
166
+ function dismissKeyLabel() {
167
+ const platform = typeof navigator !== 'undefined' ? navigator.platform || navigator.userAgent : '';
168
+ return /Mac|iPhone|iPad/.test(platform) ? '⌥W' : 'Alt+W';
169
+ }
164
170
  export const ComposerEditor = forwardRef(function ComposerEditor({ placeholder, disabled, autoFocus = false, onSubmit, onArrowUpAtStart, onEmptyChange, onDocChange, agents, sessions, currentSessionId, commands, onSelectCommand, onSelectAction, actions, files, slashDockSelector, onMenuOpenChange, }, ref) {
165
171
  const t = useTranslations('threads');
172
+ const tUltracode = useTranslations('multiAgent.ultracode');
173
+ // A marked `ultracode` keyword: the one-line hint under the text says what it does.
174
+ const [ultracodeActive, setUltracodeActive] = useState(false);
166
175
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
167
176
  const defaultActions = useMemo(() => localizedSlashActions(tI18nComplete), [tI18nComplete]);
168
177
  // Mirrors use-composer-focus.ts's onTypeAheadRef: @tiptap/react only
@@ -277,6 +286,8 @@ export const ComposerEditor = forwardRef(function ComposerEditor({ placeholder,
277
286
  extensions: [
278
287
  ...baseExtensions(() => placeholderRef.current),
279
288
  MentionNode,
289
+ // `setUltracodeActive` is a state setter: stable, so freezing it at construction is safe.
290
+ UltracodeHighlight.configure({ onActiveChange: setUltracodeActive }),
280
291
  // The one `@tiptap/suggestion` code path both `@` and `/` register
281
292
  // through (editor/suggestion.ts's `createSuggestionExtension`).
282
293
  // Built fresh every render like every extension above, but only the
@@ -427,10 +438,10 @@ export const ComposerEditor = forwardRef(function ComposerEditor({ placeholder,
427
438
  isEmpty: () => editor?.isEmpty ?? true,
428
439
  getElement: () => (editor && !editor.isDestroyed ? editor.view.dom : null),
429
440
  }), [editor]);
430
- return (_jsx(EditorContent, { editor: editor, className: cn(
431
- // `text-base` (16px) on mobile, NOT 15px: iOS Safari force-zooms the
432
- // page on focus for any input under 16px, and the composer is the one
433
- // field on the screen. `sm:text-sm` above 640px, which is the size
434
- // `styles/components.css`'s slash-trigger rule already documents.
435
- 'kortix-composer-editor w-full text-sm', disabled && 'opacity-50') }));
441
+ return (_jsxs(_Fragment, { children: [_jsx(EditorContent, { editor: editor, className: cn(
442
+ // `text-base` (16px) on mobile, NOT 15px: iOS Safari force-zooms the
443
+ // page on focus for any input under 16px, and the composer is the one
444
+ // field on the screen. `sm:text-sm` above 640px, which is the size
445
+ // `styles/components.css`'s slash-trigger rule already documents.
446
+ 'kortix-composer-editor w-full text-sm', disabled && 'opacity-50') }), ultracodeActive ? (_jsxs("p", { "data-slot": "ultracode-hint", className: "text-muted-foreground mt-1 truncate text-xs", children: [tUltracode('hint'), _jsx("span", { "aria-hidden": true, className: "px-1", children: "\u00B7" }), tUltracode('dismiss', { key: dismissKeyLabel() })] })) : null] }));
436
447
  });
@@ -0,0 +1,34 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import type { Node as ProseMirrorNode } from '@tiptap/pm/model';
3
+ import { PluginKey, type EditorState, type Transaction } from '@tiptap/pm/state';
4
+ import { DecorationSet } from '@tiptap/pm/view';
5
+ /** The utility classes of a marked keyword: the mention chip's tint, no padding (the caret must not jump). */
6
+ export declare const ULTRACODE_MARK_CLASS = "kortix-ultracode rounded-sm bg-primary/[0.08] font-medium text-foreground";
7
+ export interface UltracodeRange {
8
+ from: number;
9
+ to: number;
10
+ }
11
+ /** Every occurrence of the keyword in a document, as document positions. */
12
+ export declare function findUltracodeRanges(doc: ProseMirrorNode): UltracodeRange[];
13
+ /** True for a plain-text keyword check (the sent prompt, a test). Same rule as the editor mark. */
14
+ export declare function hasUltracodeKeyword(text: string): boolean;
15
+ export interface UltracodeState {
16
+ /** The person dismissed the keyword for this prompt. */
17
+ dismissed: boolean;
18
+ ranges: UltracodeRange[];
19
+ /** At least one marked keyword: the host shows the hint. */
20
+ active: boolean;
21
+ decorations: DecorationSet;
22
+ }
23
+ export declare const ultracodePluginKey: PluginKey<UltracodeState>;
24
+ /** The next state after a transaction: a dismiss meta sets it, an empty document resets it. */
25
+ export declare function nextUltracodeState(tr: Transaction, previous: UltracodeState, state: EditorState): UltracodeState;
26
+ /** Dismiss the keyword for this prompt. Returns false when nothing is marked. */
27
+ export declare function dismissUltracode(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
28
+ /** Alt+W anywhere, or Backspace with the caret right after a marked keyword. */
29
+ export declare function isUltracodeDismissKey(event: Pick<KeyboardEvent, 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'>, state: EditorState): boolean;
30
+ export interface UltracodeOptions {
31
+ /** Fires when the hint should appear or go: a marked keyword exists, or none does. */
32
+ onActiveChange?: (active: boolean) => void;
33
+ }
34
+ export declare const UltracodeHighlight: Extension<UltracodeOptions, any>;
@@ -0,0 +1,127 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import { Plugin, PluginKey } from '@tiptap/pm/state';
3
+ import { Decoration, DecorationSet } from '@tiptap/pm/view';
4
+ /**
5
+ * The `ultracode` keyword, as Claude Code's dynamic workflows treat it: a
6
+ * prompt that holds the word runs as a workflow of agents. The composer marks
7
+ * each occurrence in place and the host shows a one-line hint, so the person
8
+ * sees the opt-in before they send. The prompt text never changes: the word
9
+ * is sent as typed, and the agent reads it.
10
+ *
11
+ * Alt+W (Option+W on a Mac), or Backspace right after a marked word, dismisses
12
+ * the mark and the hint for this prompt. A dismissed prompt stays dismissed
13
+ * while the person keeps typing; an empty composer (the prompt was sent or
14
+ * cleared) arms the keyword again.
15
+ */
16
+ /** Whole word, any case. `\b` keeps `ultracoder` and `myultracode` plain text. */
17
+ const KEYWORD = /\bultracode\b/gi;
18
+ /** The utility classes of a marked keyword: the mention chip's tint, no padding (the caret must not jump). */
19
+ export const ULTRACODE_MARK_CLASS = 'kortix-ultracode rounded-sm bg-primary/[0.08] font-medium text-foreground';
20
+ /** Every occurrence of the keyword in a document, as document positions. */
21
+ export function findUltracodeRanges(doc) {
22
+ const ranges = [];
23
+ doc.descendants((node, pos) => {
24
+ if (!node.isText || !node.text)
25
+ return;
26
+ for (const match of node.text.matchAll(KEYWORD)) {
27
+ const from = pos + (match.index ?? 0);
28
+ ranges.push({ from, to: from + match[0].length });
29
+ }
30
+ });
31
+ return ranges;
32
+ }
33
+ /** True for a plain-text keyword check (the sent prompt, a test). Same rule as the editor mark. */
34
+ export function hasUltracodeKeyword(text) {
35
+ KEYWORD.lastIndex = 0;
36
+ const found = KEYWORD.test(text);
37
+ KEYWORD.lastIndex = 0;
38
+ return found;
39
+ }
40
+ export const ultracodePluginKey = new PluginKey('ultracode');
41
+ const isBlank = (doc) => doc.textContent.trim().length === 0;
42
+ function stateFor(doc, dismissed) {
43
+ const ranges = dismissed ? [] : findUltracodeRanges(doc);
44
+ return {
45
+ dismissed,
46
+ ranges,
47
+ active: ranges.length > 0,
48
+ decorations: ranges.length
49
+ ? DecorationSet.create(doc, ranges.map(({ from, to }) => Decoration.inline(from, to, { class: ULTRACODE_MARK_CLASS, 'data-ultracode': '' })))
50
+ : DecorationSet.empty,
51
+ };
52
+ }
53
+ /** The next state after a transaction: a dismiss meta sets it, an empty document resets it. */
54
+ export function nextUltracodeState(tr, previous, state) {
55
+ const meta = tr.getMeta(ultracodePluginKey);
56
+ let dismissed = meta?.dismiss ? true : previous.dismissed;
57
+ if (dismissed && isBlank(state.doc))
58
+ dismissed = false;
59
+ if (!tr.docChanged && dismissed === previous.dismissed)
60
+ return previous;
61
+ return stateFor(state.doc, dismissed);
62
+ }
63
+ /** Dismiss the keyword for this prompt. Returns false when nothing is marked. */
64
+ export function dismissUltracode(state, dispatch) {
65
+ if (!ultracodePluginKey.getState(state)?.active)
66
+ return false;
67
+ dispatch?.(state.tr.setMeta(ultracodePluginKey, { dismiss: true }));
68
+ return true;
69
+ }
70
+ /** Alt+W anywhere, or Backspace with the caret right after a marked keyword. */
71
+ export function isUltracodeDismissKey(event, state) {
72
+ const plugin = ultracodePluginKey.getState(state);
73
+ if (!plugin?.active)
74
+ return false;
75
+ // `code`, not `key`: Option+W on a Mac types `∑`.
76
+ if (event.altKey && !event.ctrlKey && !event.metaKey && event.code === 'KeyW')
77
+ return true;
78
+ if (event.key !== 'Backspace' || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
79
+ return false;
80
+ const { empty, from } = state.selection;
81
+ return empty && plugin.ranges.some((range) => range.to === from);
82
+ }
83
+ export const UltracodeHighlight = Extension.create({
84
+ name: 'ultracodeHighlight',
85
+ addOptions() {
86
+ return { onActiveChange: undefined };
87
+ },
88
+ addProseMirrorPlugins() {
89
+ const options = this.options;
90
+ return [
91
+ new Plugin({
92
+ key: ultracodePluginKey,
93
+ state: {
94
+ init: (_config, state) => stateFor(state.doc, false),
95
+ apply: (tr, previous, _old, state) => nextUltracodeState(tr, previous, state),
96
+ },
97
+ props: {
98
+ decorations: (state) => ultracodePluginKey.getState(state)?.decorations ?? DecorationSet.empty,
99
+ handleKeyDown: (view, event) => {
100
+ if (!isUltracodeDismissKey(event, view.state))
101
+ return false;
102
+ event.preventDefault();
103
+ return dismissUltracode(view.state, view.dispatch);
104
+ },
105
+ },
106
+ view: (view) => {
107
+ let reported = ultracodePluginKey.getState(view.state)?.active ?? false;
108
+ if (reported)
109
+ options.onActiveChange?.(true);
110
+ return {
111
+ update: (next) => {
112
+ const active = ultracodePluginKey.getState(next.state)?.active ?? false;
113
+ if (active === reported)
114
+ return;
115
+ reported = active;
116
+ options.onActiveChange?.(active);
117
+ },
118
+ destroy: () => {
119
+ if (reported)
120
+ options.onActiveChange?.(false);
121
+ },
122
+ };
123
+ },
124
+ }),
125
+ ];
126
+ },
127
+ });