@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,13 @@
1
+ import { type ReactNode } from 'react';
2
+ /** True under `CustomizeFrame`: the bar above holds the title-bar row and the sidebar opener. */
3
+ export declare function useInCustomizeFrame(): boolean;
4
+ /** The bar, then the page. Every Customize and Project admin route renders through it,
5
+ * except the agents' own pages (`/customize/agents/…`): an agent is reached from the
6
+ * sidebar's Customize and keeps its own header, with no bar over it. */
7
+ export declare function CustomizeFrame({ projectId, children }: {
8
+ projectId: string;
9
+ children: ReactNode;
10
+ }): import("react").JSX.Element;
11
+ export declare function CustomizeTabBar({ projectId }: {
12
+ projectId: string;
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,95 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Customize's top bar, over every Customize and Project admin page: the
5
+ * project's libraries (Connectors, Secrets, Skills, Tools, Extensions, Drives,
6
+ * Triggers, Models, Repo), Review, then Members ↗ and Settings on the right.
7
+ * Agents are not a tab: the sidebar's Customize lists them. Prod's layout (Jay, 2026-10-29): one row of tabs,
8
+ * no second column beside the sidebar. A library tab opens its Project admin
9
+ * page full width; Settings opens Project admin's settings sections, which
10
+ * keep a short sub-nav of their own.
11
+ *
12
+ * `CustomizeFrame` draws the bar above its children and tells the page
13
+ * headers below it (`useInCustomizeFrame`) that the bar is the window's
14
+ * title-bar row and holds the sidebar opener, so they do not draw a second.
15
+ *
16
+ * The tabs a caller sees follow the same rules as the pages: Review and
17
+ * Settings by `capabilityAccess`, each library by its row's capability
18
+ * and the `drives` flag (`PROJECT_ADMIN_RESOURCES`).
19
+ */
20
+ import { getProjectDetail } from '@kortix/sdk';
21
+ import { contract, qk, useFeatureFlag } from '@kortix/sdk/react';
22
+ import { ArrowUpRightIcon } from '@phosphor-icons/react';
23
+ import { useQuery } from '@tanstack/react-query';
24
+ import { createContext, useContext } from 'react';
25
+ import { useTranslations } from '../../i18n/index.js';
26
+ import { HubLink } from '../../internal/account-hub/account-hub-location.js';
27
+ import { useCapabilityAccess } from '../../internal/layout/project-settings-nav.js';
28
+ import { SidebarToggle } from '../../internal/layout/sidebar-toggle.js';
29
+ import { capabilityTabHref } from '../../internal/lib/capability-tab-routes.js';
30
+ import { PROJECT_ACTIONS } from '../../internal/lib/project-actions.js';
31
+ import { useProjectPageCans } from '../../internal/lib/use-project-can.js';
32
+ import { cn } from '../../internal/lib/utils.js';
33
+ import { hubTarget } from '../../internal/stores/account-panel-store.js';
34
+ import { adminPath } from '../../lib/routes.js';
35
+ import { FadedScrollArea } from '../../primitives/faded-scroll-area.js';
36
+ import { useOptionalSidebar } from '../../primitives/sidebar.js';
37
+ import { Tabs, TabsList, TabsTrigger } from '../../primitives/tabs.js';
38
+ import { UiLink as Link, useUiPathname } from '../../providers/ui-provider.js';
39
+ import { PROJECT_ADMIN_RESOURCES, RESOURCE_LABEL_KEYS, isProjectAdminResource, parseProjectAdminSection, projectAdminHref, } from '../project-settings/project-admin-sections.js';
40
+ import { receivedDenial } from './capability-access-gate.js';
41
+ const InCustomizeFrame = createContext(false);
42
+ /** True under `CustomizeFrame`: the bar above holds the title-bar row and the sidebar opener. */
43
+ export function useInCustomizeFrame() {
44
+ return useContext(InCustomizeFrame);
45
+ }
46
+ /** The bar, then the page. Every Customize and Project admin route renders through it,
47
+ * except the agents' own pages (`/customize/agents/…`): an agent is reached from the
48
+ * sidebar's Customize and keeps its own header, with no bar over it. */
49
+ export function CustomizeFrame({ projectId, children }) {
50
+ const pathname = useUiPathname() ?? '';
51
+ if (/\/customize\/agents(\/|$)/.test(pathname))
52
+ return _jsx(_Fragment, { children: children });
53
+ return (_jsxs(InCustomizeFrame.Provider, { value: true, children: [_jsx(CustomizeTabBar, { projectId: projectId }), children] }));
54
+ }
55
+ const TAB_CLASS = 'w-fit flex-none px-1 py-3';
56
+ const MEMBERS_LINK_CLASS = 'text-muted-foreground hover:text-foreground flex w-fit flex-none items-center gap-1 px-1 py-3 text-sm font-medium whitespace-nowrap transition-colors';
57
+ /** The active tab: `/admin/<library>` that library, Review, or any settings section Settings. */
58
+ function activeTab(pathname) {
59
+ if (/\/customize\/review(\/|$)/.test(pathname))
60
+ return 'review';
61
+ const section = pathname.match(/\/admin\/([^/?#]+)/)?.[1];
62
+ const key = parseProjectAdminSection(section);
63
+ if (!key)
64
+ return '';
65
+ return isProjectAdminResource(key) ? key : 'settings';
66
+ }
67
+ function MembersLink({ projectId }) {
68
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
69
+ const { data } = useQuery({
70
+ queryKey: qk.project.detail(projectId),
71
+ queryFn: () => getProjectDetail(projectId),
72
+ ...contract('config'),
73
+ });
74
+ const canReadMembers = useProjectPageCans(projectId)[PROJECT_ACTIONS.PROJECT_MEMBERS_READ];
75
+ const accountId = data?.project?.account_id;
76
+ if (receivedDenial(canReadMembers) || !accountId)
77
+ return null;
78
+ return (_jsxs(HubLink, { to: hubTarget(accountId, { tab: 'access-projects', project: projectId }), className: MEMBERS_LINK_CLASS, children: [tI18nComplete.raw('text1044a4c056d0'), _jsx(ArrowUpRightIcon, { className: "size-3 opacity-60", "aria-hidden": true })] }));
79
+ }
80
+ export function CustomizeTabBar({ projectId }) {
81
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
82
+ const tTabs = useTranslations('agentEditor.tabs');
83
+ const tAdmin = useTranslations('projectAdmin');
84
+ const pathname = useUiPathname() ?? '';
85
+ const sidebar = useOptionalSidebar();
86
+ const access = useCapabilityAccess(projectId);
87
+ const drives = useFeatureFlag(projectId, 'drives');
88
+ const allowed = new Set(access.tabs);
89
+ const libraries = PROJECT_ADMIN_RESOURCES.filter((r) => !r.host && (!r.capability || allowed.has(r.capability)) && (r.flag !== 'drives' || drives.enabled));
90
+ const tab = (value, href, label) => (_jsx(TabsTrigger, { value: value, asChild: true, className: TAB_CLASS, children: _jsx(Link, { href: href, prefetch: true, children: label }) }, value));
91
+ return (_jsxs("div", { className: "kx-titlebar-row kx-capability-titlebar relative flex shrink-0 items-center gap-1 border-b px-2", "data-sidebar-collapsed": sidebar?.state === 'collapsed' || undefined, children: [_jsx(SidebarToggle, {}), _jsx(FadedScrollArea, { orientation: "horizontal", fadeColor: "from-background", rootClassName: "min-w-0 flex-1", children: _jsx(Tabs, { value: activeTab(pathname), className: "w-max min-w-full", children: _jsxs(TabsList, { type: "underline", underlineSize: "md", size: "lg", className: cn('h-auto w-full justify-start gap-5 border-b-0 px-2', !access.settled && 'invisible'), "aria-busy": !access.settled || undefined, children: [libraries.map((r) => {
92
+ const legacy = RESOURCE_LABEL_KEYS[r.key];
93
+ return tab(r.key, projectAdminHref(projectId, r.key), legacy ? tI18nComplete.raw(legacy) : tAdmin(r.key));
94
+ }), allowed.has('review') ? tab('review', capabilityTabHref(projectId, 'review'), tTabs('review')) : null, _jsxs("span", { className: "ml-auto flex items-center gap-5", children: [_jsx(MembersLink, { projectId: projectId }), allowed.has('config') ? tab('settings', adminPath(projectId, 'general'), tTabs('settings')) : null] })] }) }) })] }));
95
+ }
@@ -5,6 +5,20 @@ export interface EntityDetailEntity {
5
5
  path: string;
6
6
  description: string | null;
7
7
  }
8
+ /**
9
+ * Where the modal reads the entity's files when they are not in the project's
10
+ * repo: a Kortix built-in skill ships with Kortix (`getBuiltinSkill`). `key`
11
+ * scopes the cache. With a source the modal is read-only: no Edit, no Remove.
12
+ */
13
+ export interface EntityFileSource {
14
+ key: string;
15
+ list: () => Promise<{
16
+ path: string;
17
+ }[]>;
18
+ read: (path: string) => Promise<{
19
+ content: string;
20
+ }>;
21
+ }
8
22
  export interface EntityDetailModalProps {
9
23
  projectId: string;
10
24
  /** The skill/command to show, or `null` when it has not resolved yet. `open`
@@ -33,6 +47,8 @@ export interface EntityDetailModalProps {
33
47
  * the modal when the refetched config drops the skill. The agent editor
34
48
  * does not, because its unsaved draft could grant the removed skill again. */
35
49
  removable?: boolean;
50
+ /** Read the files from here instead of the project's repo (read-only). */
51
+ source?: EntityFileSource;
36
52
  onOpenChange: (open: boolean) => void;
37
53
  }
38
54
  /**
@@ -49,7 +65,7 @@ export interface EntityDetailModalProps {
49
65
  * `Modal`/`ModalContent` itself, which would replay the open animation and
50
66
  * drop focus trap continuity.
51
67
  */
52
- export declare function EntityDetailModal({ projectId, entity, kind, open, isResolving, aside, meta, paneOverride, removable, onOpenChange, }: EntityDetailModalProps): import("react").JSX.Element;
68
+ export declare function EntityDetailModal({ projectId, entity, kind, open, isResolving, aside, meta, paneOverride, removable, source, onOpenChange, }: EntityDetailModalProps): import("react").JSX.Element;
53
69
  export declare function EntityFilePane({ path, content, isLoading, isError, error, onRetry, errorTitle, skeletonRows, }: {
54
70
  path: string;
55
71
  content: string | undefined;
@@ -61,7 +61,7 @@ const OWNS_ITS_DIRECTORY = {
61
61
  * `Modal`/`ModalContent` itself, which would replay the open animation and
62
62
  * drop focus trap continuity.
63
63
  */
64
- export function EntityDetailModal({ projectId, entity, kind, open, isResolving = false, aside, meta, paneOverride, removable = false, onOpenChange, }) {
64
+ export function EntityDetailModal({ projectId, entity, kind, open, isResolving = false, aside, meta, paneOverride, removable = false, source, onOpenChange, }) {
65
65
  // A skill/command with no description renders no `ModalDescription`, so
66
66
  // Radix's Dialog can't find one to auto-associate via `aria-describedby`
67
67
  // and logs a dev-only "Missing Description" warning. Passing
@@ -70,7 +70,7 @@ export function EntityDetailModal({ projectId, entity, kind, open, isResolving =
70
70
  // message itself names this exact fix. Only applied when there truly is no
71
71
  // description; when one exists, `ModalDescription` wires up normally.
72
72
  const suppressDescriptionWarning = !entity?.description;
73
- return (_jsx(Modal, { open: open, onOpenChange: onOpenChange, children: _jsx(ModalContent, { className: "bg-popover space-y-0 lg:max-w-6xl", ...(suppressDescriptionWarning ? { 'aria-describedby': undefined } : {}), children: entity ? (_jsx(EntityModalBody, { projectId: projectId, entity: entity, kind: kind, aside: aside, meta: meta, paneOverride: paneOverride, removable: removable }, entity.path)) : isResolving ? (_jsx(EntityModalSkeleton, { kind: kind })) : null }) }));
73
+ return (_jsx(Modal, { open: open, onOpenChange: onOpenChange, children: _jsx(ModalContent, { className: "bg-popover space-y-0 lg:max-w-6xl", ...(suppressDescriptionWarning ? { 'aria-describedby': undefined } : {}), children: entity ? (_jsx(EntityModalBody, { projectId: projectId, entity: entity, kind: kind, aside: aside, meta: meta, paneOverride: paneOverride, removable: removable, source: source }, entity.path)) : isResolving ? (_jsx(EntityModalSkeleton, { kind: kind })) : null }) }));
74
74
  }
75
75
  /**
76
76
  * The shell, while the selected path is being resolved against a config that
@@ -84,7 +84,7 @@ function EntityModalSkeleton({ kind }) {
84
84
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
85
85
  return (_jsxs(_Fragment, { children: [_jsxs(ModalHeader, { className: "border-border/60 space-y-1 border-b pb-4", children: [_jsxs(ModalTitle, { className: "sr-only", children: [tI18nComplete.raw('textdc380888c4e2'), " ", kind] }), _jsx(Skeleton, { className: "h-5 w-48 rounded-sm", "aria-hidden": true })] }), _jsx(ModalBody, { className: "max-h-[70vh] overflow-hidden p-0", children: _jsxs("div", { className: "flex min-h-0 flex-col lg:h-[70vh] lg:flex-row", children: [OWNS_ITS_DIRECTORY[kind] ? (_jsx("div", { className: "border-border/60 shrink-0 space-y-1.5 border-b p-2 lg:h-full lg:w-64 lg:border-r lg:border-b-0", children: [0, 1, 2].map((i) => (_jsx(Skeleton, { className: "h-7 w-full rounded-md" }, i))) })) : null, _jsxs("div", { className: "min-w-0 flex-1 space-y-3 p-4", children: [_jsx(Skeleton, { className: "h-4 w-32 rounded-sm" }), _jsx(Skeleton, { className: "h-40 w-full rounded-md" })] })] }) })] }));
86
86
  }
87
- function EntityModalBody({ projectId, entity, kind, aside, meta, paneOverride, removable, }) {
87
+ function EntityModalBody({ projectId, entity, kind, aside, meta, paneOverride, removable, source, }) {
88
88
  const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
89
89
  const configure = useConfigureThread(projectId);
90
90
  // `accountId` skips useProjectCan's own getProject and lets the IAM probe
@@ -105,15 +105,15 @@ function EntityModalBody({ projectId, entity, kind, aside, meta, paneOverride, r
105
105
  // Not fetched at all for a single-file kind: the listing would be every
106
106
  // sibling entity's source, and nothing renders it (see OWNS_ITS_DIRECTORY).
107
107
  const filesQuery = useQuery({
108
- queryKey: ['entity-files', projectId, dir],
109
- queryFn: () => listProjectFiles(projectId, { path: dir }),
110
- enabled: hasFileRail && dir !== '',
108
+ queryKey: source ? ['entity-files', source.key] : ['entity-files', projectId, dir],
109
+ queryFn: () => (source ? source.list() : listProjectFiles(projectId, { path: dir })),
110
+ enabled: hasFileRail && (!!source || dir !== ''),
111
111
  staleTime: 30_000,
112
112
  });
113
113
  const nodes = useMemo(() => buildFileTree(filesQuery.data?.map((f) => f.path) ?? [], dir), [filesQuery.data, dir]);
114
114
  const fileQuery = useQuery({
115
- queryKey: ['entity-file-content', projectId, selectedPath],
116
- queryFn: () => readProjectFile(projectId, selectedPath),
115
+ queryKey: source ? ['entity-file-content', source.key, selectedPath] : ['entity-file-content', projectId, selectedPath],
116
+ queryFn: () => (source ? source.read(selectedPath) : readProjectFile(projectId, selectedPath)),
117
117
  staleTime: 30_000,
118
118
  });
119
119
  // The one write affordance, placed by layout: at the foot of the file rail
@@ -126,7 +126,8 @@ function EntityModalBody({ projectId, entity, kind, aside, meta, paneOverride, r
126
126
  // React tree on purpose: rendered as a sibling, Radix would read every
127
127
  // click in the alert as an outside-click and dismiss the modal underneath
128
128
  // (see packages/ui/src/primitives/alert-dialog.tsx).
129
- const editButton = canWrite ? (_jsx(EntityEditButton, { name: entity.name, pending: configure.pending, onEdit: () => configure.start(editConfigPrompt(kind, entity.name, entity.path)) })) : null;
129
+ // Kortix's own files (a `source`) are read-only here.
130
+ const editButton = canWrite && !source ? (_jsx(EntityEditButton, { name: entity.name, pending: configure.pending, onEdit: () => configure.start(editConfigPrompt(kind, entity.name, entity.path)) })) : null;
130
131
  // Only a project skill can be removed; the API refuses a platform `kortix-*` one.
131
132
  const removableFolder = removable && canWrite && kind === 'skill' ? removableSkillFolder(entity.path) : null;
132
133
  // The aside earns its column when it holds something: the caller's settings,
@@ -0,0 +1,23 @@
1
+ export declare const LeaveGuardProvider: import("react").Provider<((leave: () => void) => void) | null>;
2
+ /** Runs `leave` now, or, under a dirty page, once the person confirms. */
3
+ export declare function useGuardedLeave(): (leave: () => void) => void;
4
+ /**
5
+ * Holds a dirty page on the page until the person decides.
6
+ *
7
+ * Three exits, one question. A tab close or a reload reaches only
8
+ * `beforeunload`, so that is armed while dirty. An in-app link — the sidebar, a
9
+ * tab, the breadcrumb — never fires it, and the App Router has no navigation
10
+ * event to cancel, so anchor clicks are intercepted in the capture phase: the
11
+ * click is swallowed, the exit is parked, and the page asks. A programmatic
12
+ * exit from an embedded screen reaches `confirmLeave` through
13
+ * {@link LeaveGuardProvider}. `leave` runs the parked exit; `stay` drops it.
14
+ * Modified clicks (new tab) and external links pass through — nothing is lost
15
+ * by opening a second tab.
16
+ */
17
+ export declare function useUnsavedChangesGuard(isDirty: boolean, currentPath?: string): {
18
+ /** True while the page asks whether to leave. */
19
+ asking: boolean;
20
+ confirmLeave: (leave: () => void) => void;
21
+ stay: () => void;
22
+ leave: () => void;
23
+ };
@@ -0,0 +1,87 @@
1
+ 'use client';
2
+ import { createContext, useCallback, useContext, useEffect, useState } from 'react';
3
+ import { useUiRouter } from '../../providers/ui-provider.js';
4
+ /**
5
+ * A page with unsaved edits (the agent editor) puts its "leave anyway?" question
6
+ * here, so a screen it embeds asks it before a programmatic exit: a
7
+ * `router.push` from the settings nav, or a configure session that navigates
8
+ * into a new thread. Outside such a page there is no guard and the exit runs.
9
+ */
10
+ const LeaveGuardContext = createContext(null);
11
+ export const LeaveGuardProvider = LeaveGuardContext.Provider;
12
+ /** Runs `leave` now, or, under a dirty page, once the person confirms. */
13
+ export function useGuardedLeave() {
14
+ const guard = useContext(LeaveGuardContext);
15
+ return useCallback((leave) => (guard ? guard(leave) : leave()), [guard]);
16
+ }
17
+ /**
18
+ * Holds a dirty page on the page until the person decides.
19
+ *
20
+ * Three exits, one question. A tab close or a reload reaches only
21
+ * `beforeunload`, so that is armed while dirty. An in-app link — the sidebar, a
22
+ * tab, the breadcrumb — never fires it, and the App Router has no navigation
23
+ * event to cancel, so anchor clicks are intercepted in the capture phase: the
24
+ * click is swallowed, the exit is parked, and the page asks. A programmatic
25
+ * exit from an embedded screen reaches `confirmLeave` through
26
+ * {@link LeaveGuardProvider}. `leave` runs the parked exit; `stay` drops it.
27
+ * Modified clicks (new tab) and external links pass through — nothing is lost
28
+ * by opening a second tab.
29
+ */
30
+ export function useUnsavedChangesGuard(isDirty, currentPath) {
31
+ const router = useUiRouter();
32
+ // A function in state is set through the updater form: `setPending(() => fn)`.
33
+ const [pending, setPending] = useState(null);
34
+ useEffect(() => {
35
+ if (!isDirty)
36
+ return;
37
+ const onBeforeUnload = (event) => {
38
+ event.preventDefault();
39
+ };
40
+ const onClick = (event) => {
41
+ if (event.defaultPrevented || event.button !== 0)
42
+ return;
43
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
44
+ return;
45
+ const anchor = event.target?.closest?.('a[href]');
46
+ if (!(anchor instanceof HTMLAnchorElement))
47
+ return;
48
+ if (anchor.target && anchor.target !== '_self')
49
+ return;
50
+ if (anchor.origin !== window.location.origin)
51
+ return;
52
+ const href = anchor.pathname + anchor.search + anchor.hash;
53
+ if (href === window.location.pathname + window.location.search + window.location.hash)
54
+ return;
55
+ // A link that only changes `?section=` on this page switches topic; the
56
+ // draft survives that, so it never needs the question.
57
+ if (currentPath && anchor.pathname === currentPath)
58
+ return;
59
+ event.preventDefault();
60
+ event.stopPropagation();
61
+ setPending(() => () => router.push(href));
62
+ };
63
+ window.addEventListener('beforeunload', onBeforeUnload);
64
+ document.addEventListener('click', onClick, true);
65
+ return () => {
66
+ window.removeEventListener('beforeunload', onBeforeUnload);
67
+ document.removeEventListener('click', onClick, true);
68
+ };
69
+ }, [isDirty, currentPath, router]);
70
+ const confirmLeave = useCallback((leave) => {
71
+ if (isDirty)
72
+ setPending(() => leave);
73
+ else
74
+ leave();
75
+ }, [isDirty]);
76
+ return {
77
+ /** True while the page asks whether to leave. */
78
+ asking: pending !== null,
79
+ confirmLeave,
80
+ stay: () => setPending(null),
81
+ leave: () => {
82
+ const exit = pending;
83
+ setPending(null);
84
+ exit?.();
85
+ },
86
+ };
87
+ }
@@ -21,6 +21,7 @@
21
21
  */
22
22
  import { uiRoutes } from '../../lib/routes.js';
23
23
  import { useUiRouter } from '../../providers/ui-provider.js';
24
+ import { useGuardedLeave } from './leave-guard.js';
24
25
  import { useCallback, useMemo } from 'react';
25
26
  import { ACCOUNT_GRADUATED, isAccountGraduatedSection, resolveOverlayTab, } from '../settings/settings-tabs.js';
26
27
  import { hubTarget, openAccountPanel } from '../../internal/stores/account-panel-store.js';
@@ -124,6 +125,8 @@ export function buildStandaloneCapabilityNav(state) {
124
125
  export function useStandaloneCapabilityNav(projectId, activeTab, accountId) {
125
126
  const router = useUiRouter();
126
127
  const membersTab = useSettingsPanelStore((s) => s.membersTab);
127
- const navigateTo = useCallback((href) => router.push(href), [router]);
128
+ // Under a page with unsaved edits (the agent editor), leaving asks first.
129
+ const guardedLeave = useGuardedLeave();
130
+ const navigateTo = useCallback((href) => guardedLeave(() => router.push(href)), [router, guardedLeave]);
128
131
  return useMemo(() => buildStandaloneCapabilityNav({ projectId, activeTab, membersTab, accountId, navigateTo }), [projectId, activeTab, membersTab, accountId, navigateTo]);
129
132
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * What an agent's `permission` block says about one tool, for the rail
3
+ * layout's Tools rows and its Approval rules card. A bare action applies to
4
+ * every tool; a tool's own key wins over `*`; a pattern map (bash command
5
+ * globs) reads as its `*` action, else as custom rules.
6
+ */
7
+ import type { PermissionAction, PermissionConfig } from '@kortix/sdk';
8
+ export type ToolRule = PermissionAction | 'custom';
9
+ export declare function toolRule(permission: PermissionConfig | undefined, tool: string): ToolRule | undefined;
10
+ /** The patterns a pattern map denies ("rm -rf *"), across every tool. */
11
+ export declare function deniedPatterns(permission: PermissionConfig | undefined): string[];
@@ -0,0 +1,29 @@
1
+ /**
2
+ * What an agent's `permission` block says about one tool, for the rail
3
+ * layout's Tools rows and its Approval rules card. A bare action applies to
4
+ * every tool; a tool's own key wins over `*`; a pattern map (bash command
5
+ * globs) reads as its `*` action, else as custom rules.
6
+ */
7
+ export function toolRule(permission, tool) {
8
+ if (permission === undefined)
9
+ return undefined;
10
+ if (typeof permission === 'string')
11
+ return permission;
12
+ const value = permission[tool] ?? permission['*'];
13
+ if (value === undefined)
14
+ return undefined;
15
+ if (typeof value === 'string')
16
+ return value;
17
+ const fallback = value['*'];
18
+ return typeof fallback === 'string' ? fallback : 'custom';
19
+ }
20
+ /** The patterns a pattern map denies ("rm -rf *"), across every tool. */
21
+ export function deniedPatterns(permission) {
22
+ if (!permission || typeof permission === 'string')
23
+ return [];
24
+ return Object.values(permission).flatMap((value) => value && typeof value === 'object'
25
+ ? Object.entries(value)
26
+ .filter(([pattern, action]) => pattern !== '*' && action === 'deny')
27
+ .map(([pattern]) => pattern)
28
+ : []);
29
+ }
@@ -0,0 +1,6 @@
1
+ export declare function BuiltinSkillModal({ projectId, name, description, onOpenChange, }: {
2
+ projectId: string;
3
+ name: string | null;
4
+ description: string | null;
5
+ onOpenChange: (open: boolean) => void;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * A Kortix built-in skill, opened from its card in Project admin → Skills: the
5
+ * same modal as a project skill (`EntityDetailModal`: the file tree, the
6
+ * frontmatter card, the rendered SKILL.md), read-only. A built-in skill ships
7
+ * with Kortix and is not a file in the project's repo, so its files come from
8
+ * `getBuiltinSkill(name, { full: true })`, read once and shared by the tree
9
+ * and the pane.
10
+ */
11
+ import { getBuiltinSkill } from '@kortix/sdk';
12
+ import { useQueryClient } from '@tanstack/react-query';
13
+ import { useMemo } from 'react';
14
+ import { EntityDetailModal } from '../shared/entity/entity-modal.js';
15
+ export function BuiltinSkillModal({ projectId, name, description, onOpenChange, }) {
16
+ const queryClient = useQueryClient();
17
+ const source = useMemo(() => {
18
+ if (!name)
19
+ return undefined;
20
+ const skill = () => queryClient.ensureQueryData({
21
+ queryKey: ['builtin-skill', name, 'full'],
22
+ queryFn: () => getBuiltinSkill(name, { full: true }),
23
+ staleTime: 5 * 60_000,
24
+ });
25
+ return {
26
+ key: `builtin-skill:${name}`,
27
+ list: async () => {
28
+ const s = await skill();
29
+ return [{ path: `${name}/SKILL.md` }, ...s.references.map((ref) => ({ path: `${name}/${ref.path}` }))];
30
+ },
31
+ read: async (path) => {
32
+ const s = await skill();
33
+ const relative = path.slice(name.length + 1);
34
+ if (relative === 'SKILL.md')
35
+ return { content: s.body };
36
+ return { content: s.references.find((ref) => ref.path === relative)?.content ?? '' };
37
+ },
38
+ };
39
+ }, [name, queryClient]);
40
+ return (_jsx(EntityDetailModal, { projectId: projectId, entity: name ? { name, path: `${name}/SKILL.md`, description } : null, kind: "skill", open: !!name, source: source, onOpenChange: onOpenChange }));
41
+ }
@@ -1,22 +1,25 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type CapabilityAgent } from '../shared/capability-library.js';
1
3
  /**
2
- * /projects/[id]/skills — the standalone Skills catalog. Reads
3
- * `config.skills` off the same `qk.project.detail(id)` query
4
- * Customize reads, so the two surfaces cannot disagree
5
- * about what a project's skills are.
6
- *
7
- * Card click opens `EntityDetailModal` (file tree + rendered markdown) for
8
- * the clicked skill. `selectedPath` is looked up against the unfiltered
9
- * `skills` list, not `filtered` — so typing into search while the modal is
10
- * open can't yank it shut out from under the user.
11
- * "New" in the header and "Create a skill" in the empty state are the SAME
12
- * control under two labels (`createButton`), with two ways in:
13
- * "Create in chat" reuses `useConfigureThread` / `newConfigPrompt('skill')`
14
- * (an agent edits the repo on a branch — needs a model), and "Create with a
15
- * form" commits the skill straight onto the default branch, no model needed
16
- * — on a fresh free account the chat path was a dead end ("requires a paid
17
- * plan", no model to pick). The empty state adds Docs as its secondary,
18
- * which is all a reader without write permission gets.
4
+ * Skills: the one component for Project admin → Skills and an agent's
5
+ * Access → Skills (`CapabilityLibrary`). Without `agent` it is the project's
6
+ * catalog with New, each skill's files and Remove, filtered All / Project /
7
+ * Kortix; with it, the same list with the agent's switches.
19
8
  */
20
- export declare function SkillsPage({ projectId }: {
9
+ export declare function SkillsPage({ projectId, agent }: {
21
10
  projectId: string;
11
+ agent?: CapabilityAgent;
12
+ footer?: ReactNode;
13
+ }): import("react").JSX.Element;
14
+ /** Tools: every tool an agent can call, project-wide or for one agent. */
15
+ export declare function ToolsPage({ projectId, agent, footer }: {
16
+ projectId: string;
17
+ agent?: CapabilityAgent;
18
+ footer?: ReactNode;
19
+ }): import("react").JSX.Element;
20
+ /** Extensions: code that runs inside sessions, project-wide or for one agent. */
21
+ export declare function ExtensionsPage({ projectId, agent }: {
22
+ projectId: string;
23
+ agent?: CapabilityAgent;
24
+ footer?: ReactNode;
22
25
  }): import("react").JSX.Element;
@@ -1,114 +1,20 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { NewEntityMenu } from '../shared/new-entity-menu.js';
4
- import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
5
- import { useMemo, useRef, useState } from 'react';
6
- import { Button } from '../../primitives/button.js';
7
- import { InputGroupSearch, InputGroupSearchClear, InputGroupSearchIcon, InputGroupSearchInput, } from '../../primitives/input-group.js';
8
- import { Tabs, TabsList, TabsTrigger } from '../../primitives/tabs.js';
9
- import { EmptyState } from '../../primitives/empty-state.js';
10
- import { newConfigPrompt, useConfigureThread, } from '../use-configure-thread.js';
11
- import { PROJECT_ACTIONS } from '../../internal/lib/project-actions.js';
12
- import { useProjectCan } from '../../internal/lib/use-project-can.js';
13
- import { getProjectDetail } from '@kortix/sdk';
14
- import { contract, qk, useProjectAccountId } from '@kortix/sdk/react';
15
- import { MagnifyingGlassIcon, SparkleIcon } from '@phosphor-icons/react';
16
- import { useQuery } from '@tanstack/react-query';
17
- import { CapabilityPageShell } from '../shared/capability-page-shell.js';
18
- import { CatalogCard } from '../shared/catalog/catalog-card.js';
19
- import { catalogEmptyKind } from '../shared/catalog/catalog-empty.js';
20
- import { CatalogEmptyNote, CatalogNoMatch, } from '../shared/catalog/catalog-empty-state.js';
21
- import { CatalogGrid } from '../shared/catalog/catalog-grid.js';
22
- import { detailSelection } from '../shared/detail-selection.js';
23
- import { EntityDetailModal } from '../shared/entity/entity-modal.js';
24
- import { NewSkillModal } from './new-skill-modal.js';
25
- import { filterSkills } from './skill-scope.js';
26
- import { useSlashFocus } from '../../internal/hooks/index.js';
27
- const SCOPE_FILTERS = [
28
- { value: 'all', label: 'All' },
29
- { value: 'project', label: 'Project' },
30
- { value: 'kortix', label: 'Kortix' },
31
- ];
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { CapabilityLibrary } from '../shared/capability-library.js';
32
4
  /**
33
- * /projects/[id]/skills — the standalone Skills catalog. Reads
34
- * `config.skills` off the same `qk.project.detail(id)` query
35
- * Customize reads, so the two surfaces cannot disagree
36
- * about what a project's skills are.
37
- *
38
- * Card click opens `EntityDetailModal` (file tree + rendered markdown) for
39
- * the clicked skill. `selectedPath` is looked up against the unfiltered
40
- * `skills` list, not `filtered` — so typing into search while the modal is
41
- * open can't yank it shut out from under the user.
42
- * "New" in the header and "Create a skill" in the empty state are the SAME
43
- * control under two labels (`createButton`), with two ways in:
44
- * "Create in chat" reuses `useConfigureThread` / `newConfigPrompt('skill')`
45
- * (an agent edits the repo on a branch — needs a model), and "Create with a
46
- * form" commits the skill straight onto the default branch, no model needed
47
- * — on a fresh free account the chat path was a dead end ("requires a paid
48
- * plan", no model to pick). The empty state adds Docs as its secondary,
49
- * which is all a reader without write permission gets.
5
+ * Skills: the one component for Project admin → Skills and an agent's
6
+ * Access → Skills (`CapabilityLibrary`). Without `agent` it is the project's
7
+ * catalog with New, each skill's files and Remove, filtered All / Project /
8
+ * Kortix; with it, the same list with the agent's switches.
50
9
  */
51
- export function SkillsPage({ projectId }) {
52
- const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
53
- // `accountId` skips useProjectCan's own getProject and lets the IAM probe
54
- // run on the first render instead of waiting a round-trip for it.
55
- const accountId = useProjectAccountId(projectId);
56
- const canWrite = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_SKILL_WRITE, { accountId }).allowed === true;
57
- const configure = useConfigureThread(projectId);
58
- const [query, setQuery] = useState('');
59
- const searchRef = useRef(null);
60
- useSlashFocus(searchRef);
61
- const [scope, setScope] = useState('all');
62
- const [selectedPath, setSelectedPath] = useState(null);
63
- const [formOpen, setFormOpen] = useState(false);
64
- const detailQuery = useQuery({
65
- queryKey: qk.project.detail(projectId),
66
- queryFn: () => getProjectDetail(projectId),
67
- ...contract('config'),
68
- });
69
- const skills = useMemo(() => {
70
- const raw = detailQuery.data?.config.skills;
71
- return Array.isArray(raw) ? raw : [];
72
- }, [detailQuery.data]);
73
- const scopeArg = scope === 'all' ? null : scope;
74
- const filtered = useMemo(() => filterSkills(skills, { scope: scopeArg, query }), [skills, scopeArg, query]);
75
- // Unfiltered lookup (see the component doc comment above) — deliberately
76
- // not `filtered.find(...)`.
77
- // `open` follows `selectedPath` alone — see `shared/detail-selection.ts`.
78
- // Deriving it from this lookup meant any blip in `detailQuery` (a failed
79
- // refetch, or a background agent renaming the path in kortix.yaml) closed
80
- // the modal while the user was reading a file inside it.
81
- const detail = detailSelection({
82
- selection: selectedPath,
83
- record: skills.find((skill) => skill.path === selectedPath),
84
- isSuccess: detailQuery.isSuccess,
85
- });
86
- // The one honest auto-close: the config came back and this skill is not in
87
- // it, so it really was deleted or renamed.
88
- if (detail.isMissing)
89
- setSelectedPath(null);
90
- // `null` = render the grid. Otherwise which "nothing to show" copy applies:
91
- // genuinely zero skills vs. skills exist but this filter/search hid all of
92
- // them. Telling the user "No skills yet" in the second case is false and
93
- // points at the wrong fix (clear the filter, not create a skill).
94
- const emptyKind = catalogEmptyKind(skills.length, filtered.length);
95
- const scopeLabel = SCOPE_FILTERS.find((filter) => filter.value === scope)?.label ?? 'All';
96
- // One control, two labels. The header has a title beside it and can be terse;
97
- // the empty state is the whole screen and has to name what it creates. Both
98
- // offer the same two ways in, so they cannot drift apart.
99
- // The header button is `h-9`, the height of the `size="sm"` search input
100
- // beside it. The empty state keeps `sm` to match its `sm` docs link.
101
- const createButton = (label, size) => canWrite ? (_jsx(NewEntityMenu, { label: label, size: size, pending: configure.pending, onChat: () => configure.start(newConfigPrompt('skill')), manual: {
102
- label: tI18nComplete.raw('texta38668224f1a'),
103
- description: tI18nComplete.raw('textedac6130dac7'),
104
- onSelect: () => setFormOpen(true),
105
- } })) : null;
106
- return (_jsxs(CapabilityPageShell, { title: tI18nComplete.raw('text66d0f523a379'), description: tI18nComplete.raw('text000c02c11c7a'), action: createButton('New'), search: _jsxs(InputGroupSearch, { children: [_jsx(InputGroupSearchIcon, { children: _jsx(MagnifyingGlassIcon, {}) }), _jsx(InputGroupSearchInput, { ref: searchRef, placeholder: tI18nComplete.raw('text76c02b7eddca'), value: query, onChange: (event) => setQuery(event.target.value), variant: "popover", size: "sm" }), _jsx(InputGroupSearchClear, { onClick: () => setQuery('') })] }), filters: _jsx(Tabs, { value: scope, onValueChange: (value) => setScope(value), children: _jsx(TabsList, { children: SCOPE_FILTERS.map((filter) => (_jsx(TabsTrigger, { value: filter.value, children: filter.label }, filter.value))) }) }), children: [_jsx(CatalogGrid, { isLoading: detailQuery.isLoading, isError: detailQuery.isError, onRetry: () => detailQuery.refetch(), isEmpty: emptyKind !== null, empty: emptyKind === 'no-match' ? (query.trim() ? (_jsx(CatalogNoMatch, { query: query })) : (_jsxs(CatalogEmptyNote, { children: [tI18nComplete.raw('textdc5255461795'), scopeLabel, "."] }))) : (_jsx(EmptyState, { icon: SparkleIcon, size: "sm", title: tI18nComplete.raw('text32ae9b80f832'), description: tI18nComplete.raw('text031b8fd1f46a'),
107
- // The copy invites an action, so the action is here — not only in
108
- // the header. Docs stays as the secondary, for the reader who has
109
- // no write permission and gets no primary at all.
110
- action: createButton('Create a skill', 'sm'), secondaryAction: _jsx(Button, { asChild: true, variant: "ghost", size: "sm", className: "gap-1.5", children: _jsx("a", { href: "/docs/project/agents#skills", target: "_blank", rel: "noopener noreferrer", children: tI18nComplete.raw('text7af023c43013') }) }) })), children: filtered.map((skill) => (_jsx(CatalogCard, { title: skill.name, description: skill.description, onClick: () => setSelectedPath(skill.path) }, skill.path))) }), _jsx(EntityDetailModal, { projectId: projectId, entity: detail.record, kind: "skill", removable: true, open: detail.open, isResolving: detail.isResolving, onOpenChange: (next) => {
111
- if (!next)
112
- setSelectedPath(null);
113
- } }), _jsx(NewSkillModal, { projectId: projectId, open: formOpen, onOpenChange: setFormOpen })] }));
10
+ export function SkillsPage({ projectId, agent }) {
11
+ return _jsx(CapabilityLibrary, { projectId: projectId, view: "skills", agent: agent });
12
+ }
13
+ /** Tools: every tool an agent can call, project-wide or for one agent. */
14
+ export function ToolsPage({ projectId, agent, footer }) {
15
+ return _jsx(CapabilityLibrary, { projectId: projectId, view: "tools", agent: agent, footer: footer });
16
+ }
17
+ /** Extensions: code that runs inside sessions, project-wide or for one agent. */
18
+ export function ExtensionsPage({ projectId, agent }) {
19
+ return _jsx(CapabilityLibrary, { projectId: projectId, view: "extensions", agent: agent });
114
20
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The runtime half of the Triggers page: triggers stored in the database, not
3
+ * kortix.yaml — loops, and rows an agent or the CLI created with
4
+ * `POST /triggers/runtime`. Each row reads as name, source, target, next run, last
5
+ * run, on/off. The kortix.yaml half above it keeps its own editor; a runtime
6
+ * row only pauses, runs once, or goes.
7
+ *
8
+ * It renders nothing while the project has none, so a project without runtime
9
+ * triggers sees the page it saw before.
10
+ */
11
+ import type { UnifiedTrigger } from '@kortix/sdk';
12
+ /** `true` for a row this page lists: runtime, and (on an agent's page) one that starts that agent. */
13
+ export declare function runtimeRowsFor(triggers: readonly UnifiedTrigger[], agentName: string | null): UnifiedTrigger[];
14
+ export declare function RuntimeTriggers({ projectId, agentName }: {
15
+ projectId: string;
16
+ agentName?: string | null;
17
+ }): import("react").JSX.Element | null;