@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,8 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { AgentDraft } from '../sections/view/agent-editor.js';
3
+ export declare function AgentApprovalRules({ projectId, editor, rules, }: {
4
+ projectId: string;
5
+ editor: AgentDraft;
6
+ /** The rules editor Edit rules unfolds. */
7
+ rules: ReactNode;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { capabilityGranted } from '@kortix/sdk';
4
+ import { ShieldIcon } from '@phosphor-icons/react';
5
+ import { useState } from 'react';
6
+ import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
7
+ import { useProjectCapabilities } from '../../internal/hooks/projects/use-agent-config.js';
8
+ import { Button } from '../../primitives/button.js';
9
+ import { deniedPatterns, toolRule } from '../shared/tool-rules.js';
10
+ export function AgentApprovalRules({ projectId, editor, rules, }) {
11
+ const t = useI18nTranslations('agentEditor.tabs');
12
+ const [open, setOpen] = useState(false);
13
+ const tools = useProjectCapabilities(projectId).data?.tools ?? [];
14
+ const permission = editor.oc.permission;
15
+ const asking = tools.filter((tool) => capabilityGranted(editor.draft.tools, tool.id, 'all') && toolRule(permission, tool.id) === 'ask').length;
16
+ const denied = deniedPatterns(permission);
17
+ const sentence = asking === 0 && denied.length === 0
18
+ ? t('approvalNone')
19
+ : [
20
+ asking > 0 ? t('approvalAsk', { count: asking }) : null,
21
+ denied.length > 0 ? t('approvalDenied', { list: denied.join(', ') }) : null,
22
+ ]
23
+ .filter(Boolean)
24
+ .join(' ');
25
+ return (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "bg-popover flex items-center gap-3 rounded-lg px-4 py-3", children: [_jsx(ShieldIcon, { className: "text-muted-foreground size-4 shrink-0" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground text-sm font-medium", children: t('approvalTitle') }), _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: sentence })] }), _jsx(Button, { variant: "secondary", size: "sm", "aria-expanded": open, onClick: () => setOpen((v) => !v), children: open ? t('hideRules') : t('editRules') })] }), open ? rules : null] }));
26
+ }
@@ -5,6 +5,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  *
6
6
  * Kortix permissions (kortix.yaml) ∩ ceiling role (IAM) − human-only
7
7
  *
8
+ * The UI says "Granted in kortix.yaml" and "Maximum allowed". The fixed
9
+ * human-only set is named in the effective-permissions help, not as a row.
10
+ *
8
11
  * This is how Kortix works, not a mode the project chose: there is no switch,
9
12
  * so the card states it flatly.
10
13
  *
@@ -38,7 +41,7 @@ export function AgentAuthorityCard({ projectId, agentName, grant, }) {
38
41
  : authority.declared.length === 0
39
42
  ? t('declaredNone')
40
43
  : t('declaredCount', { count: authority.declared.length });
41
- return (_jsx("div", { "data-testid": "agent-authority", children: _jsxs(EditorSection, { title: t('title'), description: t('description'), children: [_jsx(SettingRow, { label: t('kortixPermissions'), help: t('kortixPermissionsHelp', { agent: agentName }), children: _jsx("span", { className: "text-foreground block text-sm sm:text-right", children: declaredLabel }) }), _jsx(SettingRow, { label: t('ceiling'), help: t('ceilingHelp'), children: _jsxs("div", { className: "flex flex-wrap items-center gap-1.5 sm:justify-end", "data-testid": "agent-ceiling", children: [ceiling.kind === 'loading' ? (_jsx(Skeleton, { className: "h-5 w-32" })) : ceiling.kind === 'hidden' ? (_jsx("span", { className: "text-muted-foreground text-sm", children: t('ceilingHidden') })) : ceiling.kind === 'default' ? (_jsx("span", { className: "text-foreground text-sm", children: t('ceilingDefault') })) : (ceiling.roleKeys.map((key) => (_jsx(Badge, { variant: "outline", size: "sm", className: "capitalize", children: key }, key)))), accountId && ceiling.kind !== 'hidden' && ceiling.kind !== 'loading' ? (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(HubLink, { to: hubTarget(accountId, { tab: 'access-projects', project: projectId }), children: t('changeCeiling') }) })) : null] }) }), _jsx(SettingRow, { label: t('humanOnly'), help: t('humanOnlyHelp'), children: _jsx("span", { className: "text-foreground block text-sm sm:text-right", children: t('humanOnlyValue') }) }), _jsxs(SettingBlock, { label: t('effective'), help: t('effectiveHelp'), children: [_jsx("ul", { className: "flex flex-wrap gap-1", "data-testid": "agent-effective-permissions", children: authority.effective.map((permission) => (_jsx("li", { children: _jsx(Badge, { variant: "outline", size: "xs", className: "font-mono", children: permission }) }, permission))) }), authority.outsideCeiling.length > 0 ? (_jsx(DroppedList, { label: t('outsideCeiling'), permissions: authority.outsideCeiling, testId: "agent-outside-ceiling" })) : null, authority.humanOnly.length > 0 ? (_jsx(DroppedList, { label: t('droppedHumanOnly'), permissions: authority.humanOnly, testId: "agent-dropped-human-only" })) : null] })] }) }));
44
+ return (_jsx("div", { "data-testid": "agent-authority", children: _jsxs(EditorSection, { title: t('title'), description: t('description'), children: [_jsx(SettingRow, { label: t('kortixPermissions'), help: t('kortixPermissionsHelp', { agent: agentName }), children: _jsx("span", { className: "text-foreground block text-sm sm:text-right", children: declaredLabel }) }), _jsx(SettingRow, { label: t('ceiling'), help: t('ceilingHelp'), children: _jsxs("div", { className: "flex flex-wrap items-center gap-1.5 sm:justify-end", "data-testid": "agent-ceiling", children: [ceiling.kind === 'loading' ? (_jsx(Skeleton, { className: "h-5 w-32" })) : ceiling.kind === 'hidden' ? (_jsx("span", { className: "text-muted-foreground text-sm", children: t('ceilingHidden') })) : ceiling.kind === 'default' ? (_jsx("span", { className: "text-foreground text-sm", children: t('ceilingDefault') })) : (ceiling.roleKeys.map((key) => (_jsx(Badge, { variant: "outline", size: "sm", className: "capitalize", children: key }, key)))), accountId && ceiling.kind !== 'hidden' && ceiling.kind !== 'loading' ? (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(HubLink, { to: hubTarget(accountId, { tab: 'access-projects', project: projectId }), children: t('changeCeiling') }) })) : null] }) }), _jsxs(SettingBlock, { label: t('effective'), help: t('effectiveHelp'), children: [_jsx("ul", { className: "flex flex-wrap gap-1", "data-testid": "agent-effective-permissions", children: authority.effective.map((permission) => (_jsx("li", { children: _jsx(Badge, { variant: "outline", size: "xs", className: "font-mono", children: permission }) }, permission))) }), authority.outsideCeiling.length > 0 ? (_jsx(DroppedList, { label: t('outsideCeiling'), permissions: authority.outsideCeiling, testId: "agent-outside-ceiling" })) : null, authority.humanOnly.length > 0 ? (_jsx(DroppedList, { label: t('droppedHumanOnly'), permissions: authority.humanOnly, testId: "agent-dropped-human-only" })) : null] })] }) }));
42
45
  }
43
46
  function DroppedList({ label, permissions, testId, }) {
44
47
  return (_jsxs("div", { className: "space-y-1.5", "data-testid": testId, children: [_jsx("p", { className: "text-muted-foreground text-xs", children: label }), _jsx("ul", { className: "flex flex-wrap gap-1", children: permissions.map((permission) => (_jsx("li", { children: _jsx(Badge, { variant: "muted", size: "xs", className: "font-mono line-through", children: permission }) }, permission))) })] }));
@@ -4,7 +4,7 @@ import type { ReactNode } from 'react';
4
4
  * every agent a face that is the same wherever the agent appears, so a long
5
5
  * list is scanned by shape and tone before names are read.
6
6
  */
7
- export declare function AgentCoverCard({ slug, href, onIntent, title, description, badges, meta, coverLabel, }: {
7
+ export declare function AgentCoverCard({ slug, href, onIntent, title, description, badges, meta, coverLabel, action, }: {
8
8
  slug: string;
9
9
  href: string;
10
10
  onIntent?: () => void;
@@ -14,4 +14,7 @@ export declare function AgentCoverCard({ slug, href, onIntent, title, descriptio
14
14
  meta?: ReactNode;
15
15
  /** A short pill on the cover's top-left corner — "Default". */
16
16
  coverLabel?: string;
17
+ /** A control on the cover's top-right corner (the pin). A sibling of the
18
+ * card's link, never inside it: a button may not sit in a link. */
19
+ action?: ReactNode;
17
20
  }): import("react").JSX.Element;
@@ -8,6 +8,6 @@ import { cn } from '../../internal/lib/utils.js';
8
8
  * every agent a face that is the same wherever the agent appears, so a long
9
9
  * list is scanned by shape and tone before names are read.
10
10
  */
11
- export function AgentCoverCard({ slug, href, onIntent, title, description, badges, meta, coverLabel, }) {
12
- return (_jsxs(Link, { href: href, prefetch: true, onPointerEnter: onIntent, onFocus: onIntent, style: agentMarkVars(slug), className: cn('group bg-card border-border/60 flex flex-col overflow-hidden rounded-md border text-left', 'hover:border-border transition-[border-color] duration-(--duration-normal) ease-out', 'focus-visible:ring-ring/50 focus-visible:ring-2 focus-visible:outline-none'), children: [_jsxs("span", { className: "relative flex h-31 items-center justify-center bg-(--mark-tile)", children: [_jsx(AgentMarkGlyph, { slug: slug, size: 56 }), coverLabel ? (_jsx("span", { className: "bg-background/20 absolute top-2.5 left-2.5 rounded-sm px-2 py-0.5 text-xs font-medium text-(--mark-ink) backdrop-blur-sm", children: coverLabel })) : null] }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1 px-3.5 pt-3 pb-3.5", children: [_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-foreground truncate text-sm font-medium", children: title }), badges] }), description ? (_jsx("span", { className: "text-muted-foreground line-clamp-2 text-xs text-pretty", children: description })) : null, meta ? (_jsx("span", { className: "text-muted-foreground mt-auto flex flex-wrap items-center gap-x-2 gap-y-0.5 pt-1.5 text-xs", children: meta })) : null] })] }));
11
+ export function AgentCoverCard({ slug, href, onIntent, title, description, badges, meta, coverLabel, action, }) {
12
+ return (_jsxs("div", { className: "group/card relative flex", children: [_jsxs(Link, { href: href, prefetch: true, onPointerEnter: onIntent, onFocus: onIntent, style: agentMarkVars(slug), className: cn('group bg-card flex-1 border-border/60 flex flex-col overflow-hidden rounded-md border text-left', 'hover:border-border transition-[border-color] duration-(--duration-normal) ease-out', 'focus-visible:ring-ring/50 focus-visible:ring-2 focus-visible:outline-none'), children: [_jsxs("span", { className: "relative flex h-31 items-center justify-center bg-(--mark-tile)", children: [_jsx(AgentMarkGlyph, { slug: slug, size: 56 }), coverLabel ? (_jsx("span", { className: "bg-background/20 absolute top-2.5 left-2.5 rounded-sm px-2 py-0.5 text-xs font-medium text-(--mark-ink) backdrop-blur-sm", children: coverLabel })) : null] }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1 px-3.5 pt-3 pb-3.5", children: [_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-foreground truncate text-sm font-medium", children: title }), badges] }), description ? (_jsx("span", { className: "text-muted-foreground line-clamp-2 text-xs text-pretty", children: description })) : null, meta ? (_jsx("span", { className: "text-muted-foreground mt-auto flex flex-wrap items-center gap-x-2 gap-y-0.5 pt-1.5 text-xs", children: meta })) : null] })] }), action ? _jsx("span", { className: "absolute top-2 right-2", children: action }) : null] }));
13
13
  }
@@ -11,8 +11,7 @@ export declare function AgentModel({ projectId, agentName }: {
11
11
  agentName: string;
12
12
  }): import("react").JSX.Element;
13
13
  /**
14
- * An agent's manifest allowlist (`agents:` in kortix.yaml, or the legacy
15
- * `[[agents]]` in kortix.toml) — which secrets it receives in $ENV, which
14
+ * An agent's manifest allowlist (`agents:` in kortix.yaml) — which secrets it receives in $ENV, which
16
15
  * connectors it may call, which Kortix permissions it has. Editors EDIT
17
16
  * secrets + connectors here (persisted straight to the manifest); everyone
18
17
  * else sees the read-only mirror. `kortix_permissions` stays read-only (a sharper
@@ -2,20 +2,18 @@
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
4
4
  /**
5
- * The v1 fallback cards of the agent page, plus the scope-checklist helpers
6
- * the v2 editor shares with them.
5
+ * The read-only cards of the agent page, plus the scope-checklist helpers the
6
+ * editor shares with them.
7
7
  *
8
- * `AgentModel` and `AgentScope` are what a project on the legacy manifest
9
- * (kortix.toml, kortix_version 1) gets in place of the full editor — the
10
- * per-agent gateway model pin and the read-only/editable scope mirror. We
11
- * degrade, never blank the column. The v2 page
12
- * (`capabilities/agents/agent-page.tsx`) renders neither; its Model and Access
13
- * sections write the manifest block directly.
8
+ * `AgentModel` and `AgentScope` are what the read-only agent page shows in
9
+ * place of the full editor — the per-agent gateway model pin and the scope
10
+ * mirror. The editable page (`agent-page.tsx`) renders neither; its Model and
11
+ * Access sections write the manifest block directly.
14
12
  *
15
13
  * Historically this file was the whole right-hand aside of the agent detail
16
14
  * MODAL (assignments + configuration summary). The modal is gone — an agent
17
15
  * is a routed page now, Customize being agent-centric (Marko, 2026-09-01) —
18
- * and the assignments moved to `agent-people-section.tsx`.
16
+ * and the assignments moved to `agent-share-dialog.tsx`.
19
17
  */
20
18
  import { Badge } from '../../primitives/badge.js';
21
19
  import { Button } from '../../primitives/button.js';
@@ -66,8 +64,7 @@ export function AgentModel({ projectId, agentName }) {
66
64
  } })] })) : (_jsx("span", { className: "text-foreground block truncate text-sm sm:text-right", children: nameOf(resolved) ?? tI18nComplete.raw('text1f0a5246c481') })) }) }));
67
65
  }
68
66
  /**
69
- * An agent's manifest allowlist (`agents:` in kortix.yaml, or the legacy
70
- * `[[agents]]` in kortix.toml) — which secrets it receives in $ENV, which
67
+ * An agent's manifest allowlist (`agents:` in kortix.yaml) — which secrets it receives in $ENV, which
71
68
  * connectors it may call, which Kortix permissions it has. Editors EDIT
72
69
  * secrets + connectors here (persisted straight to the manifest); everyone
73
70
  * else sees the read-only mirror. `kortix_permissions` stays read-only (a sharper
@@ -1,11 +1,27 @@
1
1
  /**
2
- * Which shared drives an agent gets, on the agent's page, beside Apps and
3
- * Secrets. Turning one on shares that drive's folder with the agent: every
4
- * session of the agent then mounts it under /drives. It writes the folder's
5
- * access at once, the same grant Drive → Share makes, so it does not wait for
6
- * the page's Save.
2
+ * Drives as mounts, ONE component in two modes (Marko, 2026-10-27: "folder
3
+ * mount based, exactly", "one component, agent-based or project-wide"):
4
+ *
5
+ * - **Project** (Project admin → Drives): the folders EVERY new session
6
+ * mounts, the ones shared with everyone in the project.
7
+ * - **Agent** (Access → Drives): what a new session of this agent mounts,
8
+ * its own folders plus the project's.
9
+ *
10
+ * Each row is one folder a new session mounts: where
11
+ * it appears (`/drives/...`), which Files folder it is, who it comes through
12
+ * (this agent, or everyone in the project) and whether it is read-only. The
13
+ * list is the server's own plan (`GET /drives/:id/agents/:name/mounts`, the
14
+ * functions a session boot runs), so it never guesses.
15
+ *
16
+ * Mounting, changing the level and unmounting share or unshare the folder
17
+ * with the agent at once, the same grant Files > Share makes; they do not
18
+ * wait for the page's Save. A folder that comes through the project is
19
+ * changed in Files, where its sharing lives.
7
20
  */
8
- export declare function AgentDrivesSection({ projectId, agentName }: {
21
+ export declare function AgentDrivesSection({ projectId, agentName, repositoryAccess, }: {
9
22
  projectId: string;
10
- agentName: string;
23
+ /** Absent: the project's mounts (Project admin). */
24
+ agentName?: string;
25
+ /** Whether sessions of the agent get the project repository at /workspace. Agent mode only. */
26
+ repositoryAccess?: boolean;
11
27
  }): import("react").JSX.Element;
@@ -1,66 +1,132 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useAgentMounts, useProjectMounts } from '@kortix/sdk/react';
4
+ import { CaretRightIcon, FolderSimpleIcon, HardDrivesIcon, PlusIcon, XIcon } from '@phosphor-icons/react';
5
+ import { useState } from 'react';
6
+ import { useDriveFolder, useFolderAccess, useProjectDrive, useShareFolder, useUnshareFolder } from '../../files/drives/use-drives.js';
7
+ import { useTranslations } from '../../i18n/index.js';
8
+ import { agentDisplayName } from '../../internal/components/agent-mark.js';
3
9
  import { uiRoutes } from '../../lib/routes.js';
10
+ import { Button } from '../../primitives/button.js';
11
+ import { ConfirmDialog } from '../../primitives/confirm-dialog.js';
12
+ import { EmptyArt } from '../../primitives/empty-art.js';
4
13
  import { EmptyState } from '../../primitives/empty-state.js';
5
14
  import { ErrorState } from '../../primitives/error-state.js';
6
- import { EditorList, EditorSection } from '../sections/view/agent-editor-primitives.js';
7
- import { Button } from '../../primitives/button.js';
15
+ import Hint from '../../primitives/hint.js';
16
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle } from '../../primitives/modal.js';
17
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../primitives/select.js';
8
18
  import { Skeleton } from '../../primitives/skeleton.js';
9
- import { Switch } from '../../primitives/switch.js';
10
19
  import { errorToast } from '../../primitives/toast.js';
11
- import { useDriveFolder, useFolderAccess, useProjectDrive, useShareFolder, useUnshareFolder, } from '../../files/drives/use-drives.js';
12
- import { useTranslations } from '../../i18n/index.js';
13
- import { UiLink as Link } from '../../providers/ui-provider.js';
20
+ import { ManageButton } from '../sections/view/agent-editor-access-fields.js';
21
+ import { EditorList } from '../sections/view/agent-editor-primitives.js';
22
+ import { CapabilityPageShell } from '../shared/capability-page-shell.js';
14
23
  /**
15
- * Which shared drives an agent gets, on the agent's page, beside Apps and
16
- * Secrets. Turning one on shares that drive's folder with the agent: every
17
- * session of the agent then mounts it under /drives. It writes the folder's
18
- * access at once, the same grant Drive → Share makes, so it does not wait for
19
- * the page's Save.
24
+ * Drives as mounts, ONE component in two modes (Marko, 2026-10-27: "folder
25
+ * mount based, exactly", "one component, agent-based or project-wide"):
26
+ *
27
+ * - **Project** (Project admin → Drives): the folders EVERY new session
28
+ * mounts, the ones shared with everyone in the project.
29
+ * - **Agent** (Access → Drives): what a new session of this agent mounts,
30
+ * its own folders plus the project's.
31
+ *
32
+ * Each row is one folder a new session mounts: where
33
+ * it appears (`/drives/...`), which Files folder it is, who it comes through
34
+ * (this agent, or everyone in the project) and whether it is read-only. The
35
+ * list is the server's own plan (`GET /drives/:id/agents/:name/mounts`, the
36
+ * functions a session boot runs), so it never guesses.
37
+ *
38
+ * Mounting, changing the level and unmounting share or unshare the folder
39
+ * with the agent at once, the same grant Files > Share makes; they do not
40
+ * wait for the page's Save. A folder that comes through the project is
41
+ * changed in Files, where its sharing lives.
20
42
  */
21
- export function AgentDrivesSection({ projectId, agentName }) {
22
- const t = useTranslations('drives');
43
+ export function AgentDrivesSection({ projectId, agentName, repositoryAccess = true, }) {
44
+ const t = useTranslations('agentMounts');
23
45
  const drive = useProjectDrive(projectId);
24
- const driveHref = uiRoutes().drive(projectId);
25
- const root = useDriveFolder(drive.data?.driveId ?? null, '/');
26
- const drives = (root.data?.entries ?? []).filter((e) => e.type === 'dir' && !/^\/?Users(\/|$)/.test(e.path));
46
+ const driveId = drive.data?.driveId ?? null;
47
+ const agentPlan = useAgentMounts(agentName ? driveId : null, agentName ?? '');
48
+ const projectPlan = useProjectMounts(agentName ? null : driveId);
49
+ const plan = agentName ? agentPlan : projectPlan;
50
+ const showRepository = !!agentName && repositoryAccess;
51
+ const root = useFolderAccess(driveId, '/');
52
+ // Mounting needs `manage` on the folder; someone who holds it at the top holds it below.
53
+ const canMount = root.data?.access === 'manage';
54
+ const [picking, setPicking] = useState(false);
27
55
  let body;
28
- if (drive.isLoading || root.isLoading) {
29
- body = (_jsx(EditorList, { children: [0, 1].map((i) => (_jsx("li", { className: "flex items-center gap-3 px-4 py-3", children: _jsx(Skeleton, { className: "h-4 w-40 rounded-sm" }) }, i))) }));
56
+ if (drive.isLoading || plan.isLoading) {
57
+ body = (_jsx(EditorList, { children: [0, 1].map((i) => (_jsx("li", { className: "flex min-h-12 items-center gap-3 px-4 py-2", children: _jsx(Skeleton, { className: "h-4 w-48 rounded-sm" }) }, i))) }));
30
58
  }
31
- else if (drive.isError || root.isError || !drive.data) {
32
- body = (_jsx(ErrorState, { size: "sm", title: t('loadError'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => void root.refetch(), children: t('retry') }) }));
59
+ else if (drive.isError || plan.isError || !driveId || !plan.data) {
60
+ body = (_jsx(ErrorState, { size: "sm", title: t('loadError'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => void plan.refetch(), children: t('retry') }) }));
33
61
  }
34
- else if (drives.length === 0) {
35
- body = _jsx(EmptyState, { size: "sm", title: t('noCompanyDrives') });
62
+ else if (plan.data.mounts.length === 0 && !showRepository) {
63
+ body = (_jsx(EmptyState, { media: _jsx(EmptyArt, { icon: HardDrivesIcon }), title: t('emptyTitle'), description: t('emptyDescription') }));
36
64
  }
37
65
  else {
38
- body = (_jsx(EditorList, { children: drives.map((entry) => (_jsx(AgentDriveRow, { driveId: drive.data.driveId, entry: entry, agentName: agentName }, entry.path))) }));
66
+ body = (_jsxs("div", { className: "space-y-3", children: [_jsxs(EditorList, { children: [showRepository ? (_jsxs("li", { className: "flex min-h-12 items-center gap-3 px-4 py-2", children: [_jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("code", { className: "text-foreground block truncate font-mono text-sm", children: "/workspace" }), _jsx("span", { className: "text-muted-foreground block truncate text-xs", children: t('repository') })] }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: t('readWrite') })] })) : null, plan.data.mounts.map((mount) => (_jsx(MountRow, { driveId: driveId, agentName: agentName, mount: mount }, mount.path)))] }), plan.data.skipped.length > 0 ? (_jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: t('skipped', { slots: plan.data.slots, list: plan.data.skipped.join(', ') }) })) : null] }));
39
67
  }
40
- return (_jsx(EditorSection, { title: t('customizeTitle'), description: t('accessAgentsCompanyHint'), trailing: driveHref ? (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(Link, { href: driveHref, children: t('driveLabel') }) })) : undefined, lead: true, bare: true, children: body }));
68
+ return (_jsxs(CapabilityPageShell, { title: t('title'), description: agentName ? t('lead') : t('projectLead'), action: _jsxs(_Fragment, { children: [canMount && driveId ? (_jsxs(Button, { variant: "secondary", size: "sm", className: "gap-1.5", onClick: () => setPicking(true), children: [_jsx(PlusIcon, { className: "size-3.5 shrink-0" }), t('mount')] })) : null, _jsx(ManageButton, { href: (id) => uiRoutes().drive(id) })] }), children: [_jsx("div", { "data-testid": "drive-mounts", children: body }), driveId ? (_jsx(FolderPicker, { open: picking, onOpenChange: setPicking, driveId: driveId, agentName: agentName, mounted: new Set(plan.data?.mounts.map((m) => m.path)) })) : null] }));
41
69
  }
42
- function AgentDriveRow({ driveId, entry, agentName }) {
43
- const t = useTranslations('drives');
44
- const path = entry.path.startsWith('/') ? entry.path : `/${entry.path}`;
45
- const access = useFolderAccess(driveId, path);
70
+ /** The level a mount gives: read only, or read and write. `manage` mounts read and write. */
71
+ const levelValue = (level) => (level === 'read' ? 'read' : 'write');
72
+ /** Who a mount is shared with: the agent, or everyone in the project. */
73
+ const principalOf = (agentName) => agentName ? { principalType: 'agent', principalId: agentName } : { principalType: 'project' };
74
+ function MountRow({ driveId, agentName, mount }) {
75
+ const t = useTranslations('agentMounts');
46
76
  const share = useShareFolder();
47
77
  const unshare = useUnshareFolder();
48
- const grants = access.data?.grants ?? [];
49
- const own = grants.find((g) => !g.inherited && g.principalType === 'agent' && g.principalId === agentName);
50
- // Everyone in the project, or a grant on a folder above, already reaches the agent.
51
- const inherited = !own && grants.some((g) => g.principalType === 'project' || (g.principalType === 'agent' && g.principalId === agentName));
52
- const canManage = access.data?.access === 'manage' && !!access.data?.grantable;
78
+ const access = useFolderAccess(driveId, mount.path, !!mount.grantId);
79
+ const canChange = !!mount.grantId && access.data?.access === 'manage';
80
+ const [confirming, setConfirming] = useState(false);
53
81
  const pending = share.isPending || unshare.isPending;
54
- const toggle = async (on) => {
82
+ const setLevel = async (level) => {
83
+ try {
84
+ await share.mutateAsync({ driveId, path: mount.path, ...principalOf(agentName), level });
85
+ }
86
+ catch {
87
+ errorToast(t('changeFailed'));
88
+ }
89
+ };
90
+ const unmount = async () => {
91
+ try {
92
+ await unshare.mutateAsync({ driveId, grantId: mount.grantId });
93
+ setConfirming(false);
94
+ }
95
+ catch {
96
+ errorToast(t('changeFailed'));
97
+ }
98
+ };
99
+ const who = mount.via === 'agent' ? t('viaAgent') : t('viaProject');
100
+ return (_jsxs("li", { className: "flex min-h-12 items-center gap-3 px-4 py-2", children: [_jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "text-foreground block truncate font-mono text-sm", children: mount.mountPath }), _jsx("span", { className: "text-muted-foreground block truncate text-xs", children: t('from', { path: mount.path, who }) })] }), canChange ? (_jsxs(_Fragment, { children: [_jsxs(Select, { value: levelValue(mount.level), onValueChange: (v) => void setLevel(v), disabled: pending, children: [_jsx(SelectTrigger, { size: "sm", className: "w-36 shrink-0", "aria-label": t('levelFor', { path: mount.path }), children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { align: "end", children: [_jsx(SelectItem, { value: "read", children: t('readOnly') }), _jsx(SelectItem, { value: "write", children: t('readWrite') })] })] }), _jsx(Hint, { label: t('unmountLabel', { path: mount.path }), children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": t('unmountLabel', { path: mount.path }), onClick: () => setConfirming(true), disabled: pending, children: _jsx(XIcon, { className: "size-4" }) }) }), _jsx(ConfirmDialog, { open: confirming, onOpenChange: setConfirming, title: t('unmountTitle', { path: mount.mountPath }), description: agentName ? t('unmountDescription', { agent: agentDisplayName(agentName) }) : t('unmountProjectDescription'), confirmLabel: t('unmount'), confirmVariant: "destructive", isPending: unshare.isPending, onConfirm: () => void unmount() })] })) : (_jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: mount.readOnly ? t('readOnly') : t('readWrite') }))] }));
101
+ }
102
+ /** Pick a folder in Files and the level, then mount it for the agent. */
103
+ function FolderPicker({ open, onOpenChange, driveId, agentName, mounted, }) {
104
+ const t = useTranslations('agentMounts');
105
+ const [path, setPath] = useState('/');
106
+ const [level, setLevel] = useState('read');
107
+ const folder = useDriveFolder(open ? driveId : null, path);
108
+ const share = useShareFolder();
109
+ // Personal folders under /Users are their owners' to share, never a mount to pick here.
110
+ const dirs = (folder.data?.entries ?? []).filter((e) => e.type === 'dir' && !(path === '/' && /^\/?Users$/.test(e.path)));
111
+ const crumbs = path.split('/').filter(Boolean);
112
+ const close = (next) => {
113
+ if (share.isPending)
114
+ return;
115
+ if (!next)
116
+ setPath('/');
117
+ onOpenChange(next);
118
+ };
119
+ const mount = async () => {
55
120
  try {
56
- if (on)
57
- await share.mutateAsync({ driveId, path, principalType: 'agent', principalId: agentName, level: 'write' });
58
- else if (own)
59
- await unshare.mutateAsync({ driveId, grantId: own.grantId });
121
+ await share.mutateAsync({ driveId, path, ...principalOf(agentName), level });
122
+ close(false);
60
123
  }
61
124
  catch {
62
- errorToast(t('shareFailed'));
125
+ errorToast(t('changeFailed'));
63
126
  }
64
127
  };
65
- return (_jsxs("li", { className: "flex items-center gap-3 px-4 py-2.5", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground truncate text-sm font-medium", children: entry.name }), _jsx("p", { className: "text-muted-foreground truncate font-mono text-xs", children: inherited ? t('everyoneInProject') : `/drives${path}` })] }), access.isLoading ? (_jsx(Skeleton, { className: "h-5 w-9 rounded-full" })) : (_jsx(Switch, { checked: !!own || inherited, disabled: !canManage || inherited || pending, onCheckedChange: (v) => void toggle(v), "aria-label": t('levelFor', { name: entry.name }) }))] }));
128
+ return (_jsx(Modal, { open: open, onOpenChange: close, children: _jsxs(ModalContent, { className: "lg:max-w-lg", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: t('pickerTitle') }), _jsx(ModalDescription, { children: agentName ? t('pickerDescription', { agent: agentDisplayName(agentName) }) : t('pickerProjectDescription') })] }), _jsxs(ModalBody, { className: "space-y-3", children: [_jsxs("nav", { "aria-label": t('pickerPath'), className: "flex min-w-0 flex-wrap items-center gap-1 text-sm", children: [_jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground rounded-sm", onClick: () => setPath('/'), children: t('pickerRoot') }), crumbs.map((name, i) => (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(CaretRightIcon, { "aria-hidden": true, className: "text-muted-foreground size-3" }), _jsx("button", { type: "button", className: i === crumbs.length - 1 ? 'text-foreground' : 'text-muted-foreground hover:text-foreground', onClick: () => setPath(`/${crumbs.slice(0, i + 1).join('/')}`), children: name })] }, i)))] }), _jsx(EditorList, { className: "max-h-72 overflow-y-auto", children: folder.isLoading ? (_jsx("li", { className: "flex min-h-10 items-center px-4 py-2", children: _jsx(Skeleton, { className: "h-4 w-40 rounded-sm" }) })) : dirs.length === 0 ? (_jsx("li", { className: "text-muted-foreground px-4 py-3 text-sm", children: t('pickerEmpty') })) : (dirs.map((entry) => {
129
+ const next = entry.path.startsWith('/') ? entry.path : `/${entry.path}`;
130
+ return (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => setPath(next), className: "hover:bg-hover flex min-h-10 w-full items-center gap-2 px-4 py-2 text-left text-sm", children: [_jsx(FolderSimpleIcon, { "aria-hidden": true, className: "text-muted-foreground size-4 shrink-0" }), _jsx("span", { className: "text-foreground min-w-0 flex-1 truncate", children: entry.name }), mounted.has(next) ? _jsx("span", { className: "text-muted-foreground text-xs", children: t('alreadyMounted') }) : null, _jsx(CaretRightIcon, { "aria-hidden": true, className: "text-muted-foreground size-3.5 shrink-0" })] }) }, next));
131
+ })) })] }), _jsxs(ModalFooter, { className: "flex items-center justify-between gap-2", children: [_jsxs(Select, { value: level, onValueChange: (v) => setLevel(v), children: [_jsx(SelectTrigger, { size: "sm", className: "w-36 shrink-0", "aria-label": t('levelFor', { path }), children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "read", children: t('readOnly') }), _jsx(SelectItem, { value: "write", children: t('readWrite') })] })] }), _jsx(Button, { onClick: () => void mount(), disabled: path === '/' || share.isPending, "aria-busy": share.isPending, children: path === '/' ? t('pickerChoose') : t('pickerMount', { path }) })] })] }) }));
66
132
  }
@@ -0,0 +1,11 @@
1
+ export declare function wordCount(text: string): number;
2
+ export declare function AgentInstructions({ value, onChange, onAskMyKortix, autoFocus, }: {
3
+ /** The instructions as Markdown; null while a reader's source file loads. */
4
+ value: string | null;
5
+ /** Writes the draft. Without it the document is read-only. */
6
+ onChange?: (next: string) => void;
7
+ /** Opens a configure thread that asks My Kortix to edit the instructions. */
8
+ onAskMyKortix?: () => void;
9
+ /** Open unfolded with the cursor in it (the old `?tab=instructions` link). */
10
+ autoFocus?: boolean;
11
+ }): import("react").JSX.Element;
@@ -0,0 +1,114 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * The agent's instructions on the Overview, edited in place: the formatted
5
+ * document is the editor. A person clicks into it and types, like a doc; the
6
+ * Markdown file (`agents/<name>.md`) never shows its `**` or `##`. It is the
7
+ * same editor as doc artifacts (`markdown/doc-editor`), so Kortix has one
8
+ * document editor, and a file opened and saved unchanged stays byte for byte
9
+ * the same (`doc-round-trip.test.ts`).
10
+ *
11
+ * Edits go to the page's draft on every change; the save bar, ⌘S and the
12
+ * leave guard save them. A long document opens folded under a fade that runs
13
+ * to the block's bottom edge; Show more or a click into it unfolds it, for
14
+ * good. Escape leaves the editor.
15
+ */
16
+ import { ARTIFACT_DOC_CSS } from '../../_vendor/kortix-shared.js';
17
+ import { CaretDownIcon, PencilSimpleIcon } from '@phosphor-icons/react';
18
+ import { EditorContent, useEditor } from '@tiptap/react';
19
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
20
+ import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
21
+ import { cn } from '../../internal/lib/utils.js';
22
+ import { docExtensions } from '../../markdown/doc-editor/doc-extensions.js';
23
+ import { DocMenus } from '../../markdown/doc-editor/doc-menus.js';
24
+ import { htmlToMarkdown, markdownToHtml } from '../../markdown/doc-editor/markdown.js';
25
+ import { Button } from '../../primitives/button.js';
26
+ import { ConfirmDialog } from '../../primitives/confirm-dialog.js';
27
+ import Hint from '../../primitives/hint.js';
28
+ import { Skeleton } from '../../primitives/skeleton.js';
29
+ export function wordCount(text) {
30
+ const trimmed = text.trim();
31
+ return trimmed ? trimmed.split(/\s+/).length : 0;
32
+ }
33
+ export function AgentInstructions({ value, onChange, onAskMyKortix, autoFocus = false, }) {
34
+ const t = useI18nTranslations('agentEditor.page');
35
+ const tTabs = useI18nTranslations('agentEditor.tabs');
36
+ const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
37
+ const editable = onChange !== undefined;
38
+ const [unfolded, setUnfolded] = useState(autoFocus);
39
+ // Taller than the fold: measured while folded, kept once unfolded.
40
+ const [long, setLong] = useState(false);
41
+ const frame = useRef(null);
42
+ // The Markdown the editor last wrote. A value that differs came from
43
+ // outside (Discard, a save's read-back) and reloads the document.
44
+ const written = useRef(value);
45
+ // The document as loaded: its source, and what the editor saves it as.
46
+ // Saving the loaded document gives back the source, byte for byte.
47
+ const loaded = useRef({ source: value ?? '', saved: null });
48
+ const latest = useRef(onChange);
49
+ useEffect(() => {
50
+ latest.current = onChange;
51
+ });
52
+ const editor = useEditor({
53
+ immediatelyRender: false,
54
+ editable,
55
+ autofocus: autoFocus ? 'start' : false,
56
+ extensions: docExtensions({ editable, placeholder: () => tTabs('instructionsPlaceholder') }),
57
+ content: value === null ? '' : markdownToHtml(value),
58
+ editorProps: {
59
+ attributes: { 'aria-label': t('instructions') },
60
+ handleKeyDown: (view, event) => {
61
+ if (event.key !== 'Escape')
62
+ return false;
63
+ view.dom.blur();
64
+ return true;
65
+ },
66
+ },
67
+ onCreate: ({ editor: e }) => {
68
+ loaded.current = { source: value ?? '', saved: htmlToMarkdown(e.getHTML()) };
69
+ },
70
+ onFocus: () => setUnfolded(true),
71
+ onUpdate: ({ editor: e }) => {
72
+ // Only a person's edit writes the draft. The editor's own fix-ups on
73
+ // load (a trailing paragraph after a list) are not an edit.
74
+ if (!e.isFocused)
75
+ return;
76
+ const saved = htmlToMarkdown(e.getHTML());
77
+ const next = saved === loaded.current.saved ? loaded.current.source : saved;
78
+ written.current = next;
79
+ latest.current?.(next);
80
+ },
81
+ }, [editable, value === null]);
82
+ useEffect(() => {
83
+ if (!editor || value === null || value === written.current)
84
+ return;
85
+ written.current = value;
86
+ editor.commands.setContent(markdownToHtml(value), { emitUpdate: false });
87
+ loaded.current = { source: value, saved: htmlToMarkdown(editor.getHTML()) };
88
+ }, [editor, value]);
89
+ // Fold only a document taller than the fold.
90
+ useLayoutEffect(() => {
91
+ const el = frame.current;
92
+ if (!el || unfolded)
93
+ return;
94
+ const measure = () => setLong(el.scrollHeight > el.clientHeight + 1);
95
+ measure();
96
+ const observer = new ResizeObserver(measure);
97
+ observer.observe(el);
98
+ return () => observer.disconnect();
99
+ }, [editor, unfolded]);
100
+ const [confirmEdit, setConfirmEdit] = useState(false);
101
+ const words = wordCount(value ?? '');
102
+ const folded = long && !unfolded;
103
+ return (_jsxs("section", { className: "space-y-3", children: [_jsx("div", { className: "flex items-center justify-between gap-3", children: _jsxs("h2", { className: "text-muted-foreground text-sm font-medium", children: [t('instructions'), words > 0 ? (_jsx("span", { className: "text-muted-foreground ml-2 font-normal tabular-nums", children: t('words', { count: words }) })) : null] }) }), _jsxs("div", { className: cn(
104
+ // A filled block, no border. Folded, it has no bottom inset: the fade meets the edge.
105
+ 'bg-popover relative overflow-hidden rounded-lg px-5 pt-4',
106
+ // Room for the pencil in the top-right corner.
107
+ onAskMyKortix && 'pr-12', folded ? 'pb-0' : 'pb-4', editable && 'cursor-text'), children: [_jsx("style", { children: ARTIFACT_DOC_CSS }), onAskMyKortix ? (
108
+ // The Description box's pencil, in the same corner. My Kortix edits the
109
+ // instructions in a new session, so a click asks first.
110
+ _jsx(Hint, { label: tTabs('askToEdit'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": tTabs('askToEdit'), onClick: () => setConfirmEdit(true), className: "text-muted-foreground hover:text-foreground absolute top-3 right-3 z-10", children: _jsx(PencilSimpleIcon, { className: "size-3.5" }) }) })) : null, _jsx("div", { ref: frame, className: cn('kx-doc kx-doc-inline', !unfolded && 'max-h-80 overflow-hidden'), children: value === null || !editor ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-5/6" })] })) : (_jsxs(_Fragment, { children: [editable ? _jsx(DocMenus, { editor: editor }) : null, _jsx(EditorContent, { editor: editor })] })) }), folded ? (_jsx("div", { className: "to-popover absolute inset-x-0 bottom-0 flex h-32 items-end justify-center bg-gradient-to-b from-transparent to-80% pb-4", children: _jsxs(Button, { variant: "secondary", size: "sm", onClick: () => setUnfolded(true), children: [tI18nComplete.raw('textf5c9bd131486'), _jsx(CaretDownIcon, { className: "size-3" })] }) })) : null] }), onAskMyKortix ? (_jsx(ConfirmDialog, { open: confirmEdit, onOpenChange: setConfirmEdit, title: tTabs('editInstructionsConfirmTitle'), description: tTabs('editInstructionsConfirmBody'), confirmLabel: tTabs('askToEdit'), onConfirm: () => {
111
+ setConfirmEdit(false);
112
+ onAskMyKortix();
113
+ } })) : null] }));
114
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The agent page's Model view, in the Settings dialect the rest of the agent
3
+ * page uses (`EditorSection` in `panel` style): a title per group, no
4
+ * sentence under it, and the settings as rows in one bordered group. The
5
+ * model (the project default or a pinned one) and its thinking effort, then
6
+ * sampling and limits, then the provider options. Every control writes the
7
+ * page's draft through `setOc`, the same keys `ModelSection` writes.
8
+ */
9
+ import { type RuntimeAgentConfig } from '@kortix/sdk';
10
+ import { type ReactNode } from 'react';
11
+ type SetRuntime = <K extends keyof RuntimeAgentConfig>(key: K, value: RuntimeAgentConfig[K]) => void;
12
+ export declare function AgentModelView({ oc, setOc, footer }: {
13
+ oc: RuntimeAgentConfig;
14
+ setOc: SetRuntime;
15
+ footer?: ReactNode;
16
+ }): import("react").JSX.Element;
17
+ export {};
@@ -0,0 +1,67 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * The agent page's Model view, in the Settings dialect the rest of the agent
5
+ * page uses (`EditorSection` in `panel` style): a title per group, no
6
+ * sentence under it, and the settings as rows in one bordered group. The
7
+ * model (the project default or a pinned one) and its thinking effort, then
8
+ * sampling and limits, then the provider options. Every control writes the
9
+ * page's draft through `setOc`, the same keys `ModelSection` writes.
10
+ */
11
+ import { modelRefToKey } from '@kortix/sdk';
12
+ import { flattenModels, modelKeyToWire, modelProviderMode, useRuntimeProviders } from '@kortix/sdk/react';
13
+ import { useState } from 'react';
14
+ import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
15
+ import { Input } from '../../primitives/input.js';
16
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../primitives/select.js';
17
+ import { Slider } from '../../primitives/slider.js';
18
+ import { Textarea } from '../../primitives/textarea.js';
19
+ import { ModelSelector } from '../../session/models/model-selector.js';
20
+ import { isSliderAtDefault } from '../sections/view/agent-editor-basics-fields.js';
21
+ import { EditorSection, EditorSectionStyleProvider, SettingBlock, SettingRow, } from '../sections/view/agent-editor-primitives.js';
22
+ /** The select's value for "no variant": the model decides. */
23
+ const AUTO = '__auto__';
24
+ /** A slider that can be unset: `—` and no Reset while it follows the default. */
25
+ function SliderField({ label, help, value, fallback, min, max, step, onChange, }) {
26
+ const t = useI18nTranslations('agentEditor.modelView');
27
+ return (_jsx(SettingBlock, { label: label, help: help, children: _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Slider, { className: "flex-1", value: [value ?? fallback], min: min, max: max, step: step, thumbLabel: label, formatValue: (v) => v.toFixed(2), onValueChange: ([v]) => onChange(v) }), _jsxs("div", { className: "flex w-24 shrink-0 items-baseline justify-end gap-2.5 text-sm tabular-nums", children: [isSliderAtDefault(value, fallback) ? null : (_jsx("button", { type: "button", onClick: () => onChange(undefined), className: "text-muted-foreground hover:text-foreground transition-colors duration-fast", children: t('reset') })), _jsx("span", { className: value === undefined ? 'text-muted-foreground' : 'text-foreground', children: value === undefined ? '—' : value.toFixed(2) })] })] }) }));
28
+ }
29
+ /** `options` as JSON: the draft changes only when the text parses to an object. */
30
+ function ProviderOptions({ value, onChange, }) {
31
+ const tTabs = useI18nTranslations('agentEditor.tabs');
32
+ const [text, setText] = useState(() => (value ? JSON.stringify(value, null, 2) : ''));
33
+ const [invalid, setInvalid] = useState(false);
34
+ const commit = (next) => {
35
+ setText(next);
36
+ if (!next.trim()) {
37
+ setInvalid(false);
38
+ return onChange(undefined);
39
+ }
40
+ try {
41
+ const parsed = JSON.parse(next);
42
+ const ok = !!parsed && typeof parsed === 'object' && !Array.isArray(parsed);
43
+ setInvalid(!ok);
44
+ if (ok)
45
+ onChange(parsed);
46
+ }
47
+ catch {
48
+ setInvalid(true);
49
+ }
50
+ };
51
+ return (
52
+ // The section title names it; the row holds the rule and the field.
53
+ _jsxs("div", { className: "space-y-2.5 px-4 py-3", children: [_jsx("p", { className: "text-muted-foreground text-xs leading-normal text-pretty", children: tTabs('providerOptionsHelp') }), _jsx(Textarea, { "aria-label": tTabs('providerOptions'), value: text, placeholder: JSON.stringify({ reasoning: 'high' }), className: "min-h-20 font-mono text-xs", "aria-invalid": invalid || undefined, onChange: (e) => commit(e.target.value) }), invalid ? _jsx("p", { className: "text-destructive text-xs", children: tTabs('providerOptionsInvalid') }) : null] }));
54
+ }
55
+ export function AgentModelView({ oc, setOc, footer }) {
56
+ const t = useI18nTranslations('agentEditor.modelView');
57
+ const tTabs = useI18nTranslations('agentEditor.tabs');
58
+ const { data: providers } = useRuntimeProviders();
59
+ const models = flattenModels(providers, { providerMode: modelProviderMode(providers) });
60
+ const pinned = oc.model ? modelRefToKey(oc.model) : null;
61
+ const pinnedModel = pinned
62
+ ? models.find((m) => m.providerID === pinned.providerID && m.modelID === pinned.modelID)
63
+ : undefined;
64
+ // The pinned model's published variants: the composer's thinking-effort choices.
65
+ const variants = pinnedModel?.variants ? Object.keys(pinnedModel.variants) : [];
66
+ return (_jsx(EditorSectionStyleProvider, { value: "panel", children: _jsxs("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-8", children: [_jsxs(EditorSection, { title: t('title'), lead: true, children: [_jsx(SettingRow, { label: pinned ? (pinnedModel?.modelName ?? pinned.modelID) : t('projectDefault'), help: pinned ? (_jsxs(_Fragment, { children: [t('pinned'), " \u00B7", ' ', _jsx("button", { type: "button", onClick: () => setOc('model', undefined), className: "text-foreground decoration-border hover:decoration-foreground underline underline-offset-4 transition-colors", children: t('followDefault') })] })) : (t('followsDefault')), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ModelSelector, { models: models, providers: providers, selectedModel: pinned, unsetLabel: t('pinModel'), triggerVariant: "secondary", onSelect: (m) => setOc('model', m ? modelKeyToWire(m) : undefined) }) }) }), _jsx(SettingRow, { label: t('thinkingEffort'), help: variants.length > 0 ? (oc.variant ? t('effortSetHelp') : t('effortAutoHelp')) : t('effortNoVariantsHelp'), children: variants.length > 0 ? (_jsxs(Select, { value: oc.variant && variants.includes(oc.variant) ? oc.variant : AUTO, onValueChange: (v) => setOc('variant', v === AUTO ? undefined : v), children: [_jsx(SelectTrigger, { "aria-label": t('thinkingEffort'), size: "sm", className: "w-full", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: AUTO, children: t('auto') }), variants.map((v) => (_jsx(SelectItem, { value: v, className: "capitalize", children: v }, v)))] })] })) : (_jsx(Input, { "aria-label": t('thinkingEffort'), value: oc.variant ?? '', placeholder: t('auto'), className: "h-8", onChange: (e) => setOc('variant', e.target.value || undefined) })) })] }), _jsxs(EditorSection, { title: t('samplingTitle'), children: [_jsx(SliderField, { label: t('temperature'), help: `${t('temperatureMin')} · ${t('temperatureMax')}`, value: oc.temperature, fallback: 0, min: 0, max: 2, step: 0.05, onChange: (v) => setOc('temperature', v) }), _jsx(SliderField, { label: t('topP'), help: t('topPHelp'), value: oc.top_p, fallback: 1, min: 0, max: 1, step: 0.01, onChange: (v) => setOc('top_p', v) }), _jsx(SettingRow, { label: t('stepLimit'), help: t('stepLimitHelp'), children: _jsxs("div", { className: "relative", children: [_jsx(Input, { "aria-label": t('stepLimit'), type: "number", min: 1, value: oc.steps ?? '', placeholder: t('noLimit'), className: "h-8 pr-12 tabular-nums", onChange: (e) => setOc('steps', e.target.value ? Math.max(1, Number(e.target.value)) : undefined) }), _jsx("span", { className: "text-muted-foreground pointer-events-none absolute inset-y-0 right-2.5 flex items-center text-xs", children: t('steps') })] }) })] }), _jsx(EditorSection, { title: tTabs('providerOptions'), children: _jsx(ProviderOptions, { value: oc.options, onChange: (next) => setOc('options', next) }) }), footer] }) }));
67
+ }