@stigmer/react 0.4.8 → 0.5.1

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 (709) hide show
  1. package/action-menu/ActionMenu.d.ts +64 -0
  2. package/action-menu/ActionMenu.d.ts.map +1 -0
  3. package/action-menu/ActionMenu.js +78 -0
  4. package/action-menu/ActionMenu.js.map +1 -0
  5. package/action-menu/index.d.ts +3 -0
  6. package/action-menu/index.d.ts.map +1 -0
  7. package/action-menu/index.js +2 -0
  8. package/action-menu/index.js.map +1 -0
  9. package/action-menu/types.d.ts +65 -0
  10. package/action-menu/types.d.ts.map +1 -0
  11. package/action-menu/types.js +2 -0
  12. package/action-menu/types.js.map +1 -0
  13. package/agent/AgentCreationWizard.d.ts +55 -0
  14. package/agent/AgentCreationWizard.d.ts.map +1 -0
  15. package/agent/AgentCreationWizard.js +115 -0
  16. package/agent/AgentCreationWizard.js.map +1 -0
  17. package/agent/AgentDetailView.d.ts +77 -9
  18. package/agent/AgentDetailView.d.ts.map +1 -1
  19. package/agent/AgentDetailView.js +265 -87
  20. package/agent/AgentDetailView.js.map +1 -1
  21. package/agent/index.d.ts +8 -0
  22. package/agent/index.d.ts.map +1 -1
  23. package/agent/index.js +4 -0
  24. package/agent/index.js.map +1 -1
  25. package/agent/internal/agentToInput.d.ts +12 -0
  26. package/agent/internal/agentToInput.d.ts.map +1 -0
  27. package/agent/internal/agentToInput.js +72 -0
  28. package/agent/internal/agentToInput.js.map +1 -0
  29. package/agent/steps/CapabilitiesStep.d.ts +16 -0
  30. package/agent/steps/CapabilitiesStep.d.ts.map +1 -0
  31. package/agent/steps/CapabilitiesStep.js +80 -0
  32. package/agent/steps/CapabilitiesStep.js.map +1 -0
  33. package/agent/steps/IdentityStep.d.ts +18 -0
  34. package/agent/steps/IdentityStep.d.ts.map +1 -0
  35. package/agent/steps/IdentityStep.js +43 -0
  36. package/agent/steps/IdentityStep.js.map +1 -0
  37. package/agent/steps/ReviewStep.d.ts +23 -0
  38. package/agent/steps/ReviewStep.d.ts.map +1 -0
  39. package/agent/steps/ReviewStep.js +73 -0
  40. package/agent/steps/ReviewStep.js.map +1 -0
  41. package/agent/steps/types.d.ts +35 -0
  42. package/agent/steps/types.d.ts.map +1 -0
  43. package/agent/steps/types.js +16 -0
  44. package/agent/steps/types.js.map +1 -0
  45. package/agent/useCreateAgent.d.ts +45 -0
  46. package/agent/useCreateAgent.d.ts.map +1 -0
  47. package/agent/useCreateAgent.js +50 -0
  48. package/agent/useCreateAgent.js.map +1 -0
  49. package/agent/useUpdateAgent.d.ts +24 -0
  50. package/agent/useUpdateAgent.d.ts.map +1 -0
  51. package/agent/useUpdateAgent.js +35 -0
  52. package/agent/useUpdateAgent.js.map +1 -0
  53. package/composer/ContextChip.d.ts +7 -2
  54. package/composer/ContextChip.d.ts.map +1 -1
  55. package/composer/ContextChip.js +2 -1
  56. package/composer/ContextChip.js.map +1 -1
  57. package/composer/SessionComposer.d.ts +11 -0
  58. package/composer/SessionComposer.d.ts.map +1 -1
  59. package/composer/SessionComposer.js +33 -4
  60. package/composer/SessionComposer.js.map +1 -1
  61. package/dependency-graph/DependencyGraph.d.ts +37 -0
  62. package/dependency-graph/DependencyGraph.d.ts.map +1 -0
  63. package/dependency-graph/DependencyGraph.js +88 -0
  64. package/dependency-graph/DependencyGraph.js.map +1 -0
  65. package/dependency-graph/DependencyTreeNode.d.ts +23 -0
  66. package/dependency-graph/DependencyTreeNode.d.ts.map +1 -0
  67. package/dependency-graph/DependencyTreeNode.js +99 -0
  68. package/dependency-graph/DependencyTreeNode.js.map +1 -0
  69. package/dependency-graph/index.d.ts +4 -0
  70. package/dependency-graph/index.d.ts.map +1 -0
  71. package/dependency-graph/index.js +5 -0
  72. package/dependency-graph/index.js.map +1 -0
  73. package/dependency-graph/types.d.ts +130 -0
  74. package/dependency-graph/types.d.ts.map +1 -0
  75. package/dependency-graph/types.js +2 -0
  76. package/dependency-graph/types.js.map +1 -0
  77. package/dependency-graph/useDependencyGraph.d.ts +27 -0
  78. package/dependency-graph/useDependencyGraph.d.ts.map +1 -0
  79. package/dependency-graph/useDependencyGraph.js +129 -0
  80. package/dependency-graph/useDependencyGraph.js.map +1 -0
  81. package/empty-state/EmptyState.d.ts +29 -0
  82. package/empty-state/EmptyState.d.ts.map +1 -0
  83. package/empty-state/EmptyState.js +45 -0
  84. package/empty-state/EmptyState.js.map +1 -0
  85. package/empty-state/index.d.ts +4 -0
  86. package/empty-state/index.d.ts.map +1 -0
  87. package/empty-state/index.js +3 -0
  88. package/empty-state/index.js.map +1 -0
  89. package/empty-state/types.d.ts +73 -0
  90. package/empty-state/types.d.ts.map +1 -0
  91. package/empty-state/types.js +2 -0
  92. package/empty-state/types.js.map +1 -0
  93. package/empty-state/useEmptyState.d.ts +18 -0
  94. package/empty-state/useEmptyState.d.ts.map +1 -0
  95. package/empty-state/useEmptyState.js +72 -0
  96. package/empty-state/useEmptyState.js.map +1 -0
  97. package/environment/usePersonalEnvironment.d.ts.map +1 -1
  98. package/environment/usePersonalEnvironment.js +1 -0
  99. package/environment/usePersonalEnvironment.js.map +1 -1
  100. package/feedback/StigmerToaster.d.ts +18 -0
  101. package/feedback/StigmerToaster.d.ts.map +1 -0
  102. package/feedback/StigmerToaster.js +31 -0
  103. package/feedback/StigmerToaster.js.map +1 -0
  104. package/feedback/index.d.ts +4 -0
  105. package/feedback/index.d.ts.map +1 -0
  106. package/feedback/index.js +3 -0
  107. package/feedback/index.js.map +1 -0
  108. package/feedback/toast.d.ts +14 -0
  109. package/feedback/toast.d.ts.map +1 -0
  110. package/feedback/toast.js +14 -0
  111. package/feedback/toast.js.map +1 -0
  112. package/feedback/types.d.ts +4 -0
  113. package/feedback/types.d.ts.map +1 -0
  114. package/feedback/types.js +2 -0
  115. package/feedback/types.js.map +1 -0
  116. package/index.d.ts +32 -12
  117. package/index.d.ts.map +1 -1
  118. package/index.js +30 -10
  119. package/index.js.map +1 -1
  120. package/inline-edit/InlineEditImage.d.ts +20 -0
  121. package/inline-edit/InlineEditImage.d.ts.map +1 -0
  122. package/inline-edit/InlineEditImage.js +85 -0
  123. package/inline-edit/InlineEditImage.js.map +1 -0
  124. package/inline-edit/InlineEditKeyValue.d.ts +33 -0
  125. package/inline-edit/InlineEditKeyValue.d.ts.map +1 -0
  126. package/inline-edit/InlineEditKeyValue.js +67 -0
  127. package/inline-edit/InlineEditKeyValue.js.map +1 -0
  128. package/inline-edit/InlineEditResourceList.d.ts +34 -0
  129. package/inline-edit/InlineEditResourceList.d.ts.map +1 -0
  130. package/inline-edit/InlineEditResourceList.js +99 -0
  131. package/inline-edit/InlineEditResourceList.js.map +1 -0
  132. package/inline-edit/InlineEditSelect.d.ts +18 -0
  133. package/inline-edit/InlineEditSelect.d.ts.map +1 -0
  134. package/inline-edit/InlineEditSelect.js +54 -0
  135. package/inline-edit/InlineEditSelect.js.map +1 -0
  136. package/inline-edit/InlineEditText.d.ts +23 -0
  137. package/inline-edit/InlineEditText.d.ts.map +1 -0
  138. package/inline-edit/InlineEditText.js +79 -0
  139. package/inline-edit/InlineEditText.js.map +1 -0
  140. package/inline-edit/InlineEditTextarea.d.ts +22 -0
  141. package/inline-edit/InlineEditTextarea.d.ts.map +1 -0
  142. package/inline-edit/InlineEditTextarea.js +83 -0
  143. package/inline-edit/InlineEditTextarea.js.map +1 -0
  144. package/inline-edit/index.d.ts +16 -0
  145. package/inline-edit/index.d.ts.map +1 -0
  146. package/inline-edit/index.js +8 -0
  147. package/inline-edit/index.js.map +1 -0
  148. package/inline-edit/types.d.ts +42 -0
  149. package/inline-edit/types.d.ts.map +1 -0
  150. package/inline-edit/types.js +2 -0
  151. package/inline-edit/types.js.map +1 -0
  152. package/inline-edit/useInlineFieldSave.d.ts +23 -0
  153. package/inline-edit/useInlineFieldSave.d.ts.map +1 -0
  154. package/inline-edit/useInlineFieldSave.js +44 -0
  155. package/inline-edit/useInlineFieldSave.js.map +1 -0
  156. package/internal/Tabs.d.ts +4 -38
  157. package/internal/Tabs.d.ts.map +1 -1
  158. package/internal/Tabs.js +3 -62
  159. package/internal/Tabs.js.map +1 -1
  160. package/internal/useFetch.js +2 -2
  161. package/internal/useFetch.js.map +1 -1
  162. package/library/ImportResourceDialog.d.ts +43 -0
  163. package/library/ImportResourceDialog.d.ts.map +1 -0
  164. package/library/ImportResourceDialog.js +90 -0
  165. package/library/ImportResourceDialog.js.map +1 -0
  166. package/library/index.d.ts +7 -4
  167. package/library/index.d.ts.map +1 -1
  168. package/library/index.js +4 -2
  169. package/library/index.js.map +1 -1
  170. package/library/serialize-resource-yaml.d.ts +53 -0
  171. package/library/serialize-resource-yaml.d.ts.map +1 -1
  172. package/library/serialize-resource-yaml.js +275 -0
  173. package/library/serialize-resource-yaml.js.map +1 -1
  174. package/library/useExportResource.d.ts +56 -0
  175. package/library/useExportResource.d.ts.map +1 -0
  176. package/library/useExportResource.js +137 -0
  177. package/library/useExportResource.js.map +1 -0
  178. package/library/useImportResource.d.ts +84 -0
  179. package/library/useImportResource.d.ts.map +1 -0
  180. package/library/useImportResource.js +188 -0
  181. package/library/useImportResource.js.map +1 -0
  182. package/mcp-server/McpServerCreationWizard.d.ts +55 -0
  183. package/mcp-server/McpServerCreationWizard.d.ts.map +1 -0
  184. package/mcp-server/McpServerCreationWizard.js +121 -0
  185. package/mcp-server/McpServerCreationWizard.js.map +1 -0
  186. package/mcp-server/McpServerDetailView.d.ts +21 -1
  187. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  188. package/mcp-server/McpServerDetailView.js +235 -43
  189. package/mcp-server/McpServerDetailView.js.map +1 -1
  190. package/mcp-server/index.d.ts +8 -0
  191. package/mcp-server/index.d.ts.map +1 -1
  192. package/mcp-server/index.js +4 -0
  193. package/mcp-server/index.js.map +1 -1
  194. package/mcp-server/internal/mcpServerToInput.d.ts +12 -0
  195. package/mcp-server/internal/mcpServerToInput.d.ts.map +1 -0
  196. package/mcp-server/internal/mcpServerToInput.js +81 -0
  197. package/mcp-server/internal/mcpServerToInput.js.map +1 -0
  198. package/mcp-server/steps/EnvironmentAuthStep.d.ts +15 -0
  199. package/mcp-server/steps/EnvironmentAuthStep.d.ts.map +1 -0
  200. package/mcp-server/steps/EnvironmentAuthStep.js +55 -0
  201. package/mcp-server/steps/EnvironmentAuthStep.js.map +1 -0
  202. package/mcp-server/steps/IdentityTransportStep.d.ts +19 -0
  203. package/mcp-server/steps/IdentityTransportStep.d.ts.map +1 -0
  204. package/mcp-server/steps/IdentityTransportStep.js +73 -0
  205. package/mcp-server/steps/IdentityTransportStep.js.map +1 -0
  206. package/mcp-server/steps/ReviewStep.d.ts +23 -0
  207. package/mcp-server/steps/ReviewStep.d.ts.map +1 -0
  208. package/mcp-server/steps/ReviewStep.js +137 -0
  209. package/mcp-server/steps/ReviewStep.js.map +1 -0
  210. package/mcp-server/steps/types.d.ts +56 -0
  211. package/mcp-server/steps/types.d.ts.map +1 -0
  212. package/mcp-server/steps/types.js +27 -0
  213. package/mcp-server/steps/types.js.map +1 -0
  214. package/mcp-server/useCreateMcpServer.d.ts +45 -0
  215. package/mcp-server/useCreateMcpServer.d.ts.map +1 -0
  216. package/mcp-server/useCreateMcpServer.js +50 -0
  217. package/mcp-server/useCreateMcpServer.js.map +1 -0
  218. package/mcp-server/useUpdateMcpServer.d.ts +24 -0
  219. package/mcp-server/useUpdateMcpServer.d.ts.map +1 -0
  220. package/mcp-server/useUpdateMcpServer.js +35 -0
  221. package/mcp-server/useUpdateMcpServer.js.map +1 -0
  222. package/models/ModelRegistryContext.d.ts +2 -0
  223. package/models/ModelRegistryContext.d.ts.map +1 -1
  224. package/models/ModelRegistryContext.js +1 -0
  225. package/models/ModelRegistryContext.js.map +1 -1
  226. package/models/ModelSelector.d.ts.map +1 -1
  227. package/models/ModelSelector.js +2 -2
  228. package/models/ModelSelector.js.map +1 -1
  229. package/models/__tests__/useModelRegistry.test.js +4 -3
  230. package/models/__tests__/useModelRegistry.test.js.map +1 -1
  231. package/models/useModelRegistry.d.ts +2 -0
  232. package/models/useModelRegistry.d.ts.map +1 -1
  233. package/models/useModelRegistry.js +3 -2
  234. package/models/useModelRegistry.js.map +1 -1
  235. package/package.json +8 -4
  236. package/provider.d.ts.map +1 -1
  237. package/provider.js +69 -22
  238. package/provider.js.map +1 -1
  239. package/resource-creation/CreationPicker.d.ts +60 -0
  240. package/resource-creation/CreationPicker.d.ts.map +1 -0
  241. package/resource-creation/CreationPicker.js +74 -0
  242. package/resource-creation/CreationPicker.js.map +1 -0
  243. package/resource-creation/StepIndicator.d.ts +28 -0
  244. package/resource-creation/StepIndicator.d.ts.map +1 -0
  245. package/resource-creation/StepIndicator.js +40 -0
  246. package/resource-creation/StepIndicator.js.map +1 -0
  247. package/resource-creation/TemplateCard.d.ts +24 -0
  248. package/resource-creation/TemplateCard.d.ts.map +1 -0
  249. package/resource-creation/TemplateCard.js +68 -0
  250. package/resource-creation/TemplateCard.js.map +1 -0
  251. package/resource-creation/TemplateGallery.d.ts +43 -0
  252. package/resource-creation/TemplateGallery.d.ts.map +1 -0
  253. package/resource-creation/TemplateGallery.js +78 -0
  254. package/resource-creation/TemplateGallery.js.map +1 -0
  255. package/resource-creation/WizardNav.d.ts +31 -0
  256. package/resource-creation/WizardNav.d.ts.map +1 -0
  257. package/resource-creation/WizardNav.js +29 -0
  258. package/resource-creation/WizardNav.js.map +1 -0
  259. package/resource-creation/WizardShell.d.ts +41 -0
  260. package/resource-creation/WizardShell.d.ts.map +1 -0
  261. package/resource-creation/WizardShell.js +55 -0
  262. package/resource-creation/WizardShell.js.map +1 -0
  263. package/resource-creation/index.d.ts +21 -0
  264. package/resource-creation/index.d.ts.map +1 -0
  265. package/resource-creation/index.js +14 -0
  266. package/resource-creation/index.js.map +1 -0
  267. package/resource-creation/templates/agent-templates.d.ts +15 -0
  268. package/resource-creation/templates/agent-templates.d.ts.map +1 -0
  269. package/resource-creation/templates/agent-templates.js +148 -0
  270. package/resource-creation/templates/agent-templates.js.map +1 -0
  271. package/resource-creation/templates/index.d.ts +5 -0
  272. package/resource-creation/templates/index.d.ts.map +1 -0
  273. package/resource-creation/templates/index.js +5 -0
  274. package/resource-creation/templates/index.js.map +1 -0
  275. package/resource-creation/templates/mcp-server-templates.d.ts +15 -0
  276. package/resource-creation/templates/mcp-server-templates.d.ts.map +1 -0
  277. package/resource-creation/templates/mcp-server-templates.js +92 -0
  278. package/resource-creation/templates/mcp-server-templates.js.map +1 -0
  279. package/resource-creation/templates/types.d.ts +48 -0
  280. package/resource-creation/templates/types.d.ts.map +1 -0
  281. package/resource-creation/templates/types.js +16 -0
  282. package/resource-creation/templates/types.js.map +1 -0
  283. package/resource-creation/types.d.ts +88 -0
  284. package/resource-creation/types.d.ts.map +1 -0
  285. package/resource-creation/types.js +2 -0
  286. package/resource-creation/types.js.map +1 -0
  287. package/resource-creation/useTemplateFilter.d.ts +43 -0
  288. package/resource-creation/useTemplateFilter.d.ts.map +1 -0
  289. package/resource-creation/useTemplateFilter.js +73 -0
  290. package/resource-creation/useTemplateFilter.js.map +1 -0
  291. package/resource-creation/useWizardState.d.ts +67 -0
  292. package/resource-creation/useWizardState.d.ts.map +1 -0
  293. package/resource-creation/useWizardState.js +143 -0
  294. package/resource-creation/useWizardState.js.map +1 -0
  295. package/resource-detail/ConfirmDialog.d.ts +44 -0
  296. package/resource-detail/ConfirmDialog.d.ts.map +1 -0
  297. package/resource-detail/ConfirmDialog.js +62 -0
  298. package/resource-detail/ConfirmDialog.js.map +1 -0
  299. package/resource-detail/ResourceActionBar.d.ts +42 -0
  300. package/resource-detail/ResourceActionBar.d.ts.map +1 -0
  301. package/resource-detail/ResourceActionBar.js +64 -0
  302. package/resource-detail/ResourceActionBar.js.map +1 -0
  303. package/resource-detail/ResourceDetailShell.d.ts +36 -0
  304. package/resource-detail/ResourceDetailShell.d.ts.map +1 -0
  305. package/resource-detail/ResourceDetailShell.js +65 -0
  306. package/resource-detail/ResourceDetailShell.js.map +1 -0
  307. package/resource-detail/Section.d.ts +18 -0
  308. package/resource-detail/Section.d.ts.map +1 -0
  309. package/resource-detail/Section.js +18 -0
  310. package/resource-detail/Section.js.map +1 -0
  311. package/resource-detail/index.d.ts +15 -0
  312. package/resource-detail/index.d.ts.map +1 -0
  313. package/resource-detail/index.js +10 -0
  314. package/resource-detail/index.js.map +1 -0
  315. package/resource-detail/types.d.ts +146 -0
  316. package/resource-detail/types.d.ts.map +1 -0
  317. package/resource-detail/types.js +2 -0
  318. package/resource-detail/types.js.map +1 -0
  319. package/resource-detail/useConfirmAction.d.ts +41 -0
  320. package/resource-detail/useConfirmAction.d.ts.map +1 -0
  321. package/resource-detail/useConfirmAction.js +30 -0
  322. package/resource-detail/useConfirmAction.js.map +1 -0
  323. package/resource-detail/useCopyResource.d.ts +28 -0
  324. package/resource-detail/useCopyResource.d.ts.map +1 -0
  325. package/resource-detail/useCopyResource.js +46 -0
  326. package/resource-detail/useCopyResource.js.map +1 -0
  327. package/resource-detail/useDeleteResource.d.ts +40 -0
  328. package/resource-detail/useDeleteResource.d.ts.map +1 -0
  329. package/resource-detail/useDeleteResource.js +83 -0
  330. package/resource-detail/useDeleteResource.js.map +1 -0
  331. package/resource-detail/useDetailTabs.d.ts +46 -0
  332. package/resource-detail/useDetailTabs.d.ts.map +1 -0
  333. package/resource-detail/useDetailTabs.js +47 -0
  334. package/resource-detail/useDetailTabs.js.map +1 -0
  335. package/resource-workbench/components/BulkActionBar.d.ts +36 -0
  336. package/resource-workbench/components/BulkActionBar.d.ts.map +1 -0
  337. package/resource-workbench/components/BulkActionBar.js +35 -0
  338. package/resource-workbench/components/BulkActionBar.js.map +1 -0
  339. package/resource-workbench/components/ColumnHeader.d.ts +23 -0
  340. package/resource-workbench/components/ColumnHeader.d.ts.map +1 -0
  341. package/resource-workbench/components/ColumnHeader.js +25 -0
  342. package/resource-workbench/components/ColumnHeader.js.map +1 -0
  343. package/resource-workbench/components/FilterBar.d.ts +33 -0
  344. package/resource-workbench/components/FilterBar.d.ts.map +1 -0
  345. package/resource-workbench/components/FilterBar.js +72 -0
  346. package/resource-workbench/components/FilterBar.js.map +1 -0
  347. package/resource-workbench/components/ResourceAvatar.d.ts +29 -0
  348. package/resource-workbench/components/ResourceAvatar.d.ts.map +1 -0
  349. package/resource-workbench/components/ResourceAvatar.js +51 -0
  350. package/resource-workbench/components/ResourceAvatar.js.map +1 -0
  351. package/resource-workbench/components/ResourceCards.d.ts +39 -0
  352. package/resource-workbench/components/ResourceCards.d.ts.map +1 -0
  353. package/resource-workbench/components/ResourceCards.js +41 -0
  354. package/resource-workbench/components/ResourceCards.js.map +1 -0
  355. package/resource-workbench/components/ResourceInspector.d.ts +26 -0
  356. package/resource-workbench/components/ResourceInspector.d.ts.map +1 -0
  357. package/resource-workbench/components/ResourceInspector.js +22 -0
  358. package/resource-workbench/components/ResourceInspector.js.map +1 -0
  359. package/resource-workbench/components/ResourceList.d.ts +39 -0
  360. package/resource-workbench/components/ResourceList.d.ts.map +1 -0
  361. package/resource-workbench/components/ResourceList.js +41 -0
  362. package/resource-workbench/components/ResourceList.js.map +1 -0
  363. package/resource-workbench/components/ResourceTable.d.ts +47 -0
  364. package/resource-workbench/components/ResourceTable.d.ts.map +1 -0
  365. package/resource-workbench/components/ResourceTable.js +78 -0
  366. package/resource-workbench/components/ResourceTable.js.map +1 -0
  367. package/resource-workbench/components/ResourceWorkbench.d.ts +131 -0
  368. package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -0
  369. package/resource-workbench/components/ResourceWorkbench.js +170 -0
  370. package/resource-workbench/components/ResourceWorkbench.js.map +1 -0
  371. package/resource-workbench/components/SelectionCheckbox.d.ts +24 -0
  372. package/resource-workbench/components/SelectionCheckbox.d.ts.map +1 -0
  373. package/resource-workbench/components/SelectionCheckbox.js +16 -0
  374. package/resource-workbench/components/SelectionCheckbox.js.map +1 -0
  375. package/resource-workbench/components/StatusBadge.d.ts +31 -0
  376. package/resource-workbench/components/StatusBadge.d.ts.map +1 -0
  377. package/resource-workbench/components/StatusBadge.js +75 -0
  378. package/resource-workbench/components/StatusBadge.js.map +1 -0
  379. package/resource-workbench/components/ViewSwitcher.d.ts +21 -0
  380. package/resource-workbench/components/ViewSwitcher.d.ts.map +1 -0
  381. package/resource-workbench/components/ViewSwitcher.js +37 -0
  382. package/resource-workbench/components/ViewSwitcher.js.map +1 -0
  383. package/resource-workbench/hooks/useResourceCollection.d.ts +93 -0
  384. package/resource-workbench/hooks/useResourceCollection.d.ts.map +1 -0
  385. package/resource-workbench/hooks/useResourceCollection.js +133 -0
  386. package/resource-workbench/hooks/useResourceCollection.js.map +1 -0
  387. package/resource-workbench/hooks/useResourceFilters.d.ts +73 -0
  388. package/resource-workbench/hooks/useResourceFilters.d.ts.map +1 -0
  389. package/resource-workbench/hooks/useResourceFilters.js +105 -0
  390. package/resource-workbench/hooks/useResourceFilters.js.map +1 -0
  391. package/resource-workbench/hooks/useResourceSelection.d.ts +44 -0
  392. package/resource-workbench/hooks/useResourceSelection.d.ts.map +1 -0
  393. package/resource-workbench/hooks/useResourceSelection.js +123 -0
  394. package/resource-workbench/hooks/useResourceSelection.js.map +1 -0
  395. package/resource-workbench/hooks/useViewPreference.d.ts +32 -0
  396. package/resource-workbench/hooks/useViewPreference.d.ts.map +1 -0
  397. package/resource-workbench/hooks/useViewPreference.js +60 -0
  398. package/resource-workbench/hooks/useViewPreference.js.map +1 -0
  399. package/resource-workbench/index.d.ts +34 -0
  400. package/resource-workbench/index.d.ts.map +1 -0
  401. package/resource-workbench/index.js +19 -0
  402. package/resource-workbench/index.js.map +1 -0
  403. package/resource-workbench/types.d.ts +165 -0
  404. package/resource-workbench/types.d.ts.map +1 -0
  405. package/resource-workbench/types.js +2 -0
  406. package/resource-workbench/types.js.map +1 -0
  407. package/runner/RunnerDetailView.d.ts +44 -0
  408. package/runner/RunnerDetailView.d.ts.map +1 -0
  409. package/runner/RunnerDetailView.js +154 -0
  410. package/runner/RunnerDetailView.js.map +1 -0
  411. package/runner/RunnerListPanel.d.ts +26 -1
  412. package/runner/RunnerListPanel.d.ts.map +1 -1
  413. package/runner/RunnerListPanel.js +68 -46
  414. package/runner/RunnerListPanel.js.map +1 -1
  415. package/runner/index.d.ts +7 -1
  416. package/runner/index.d.ts.map +1 -1
  417. package/runner/index.js +3 -0
  418. package/runner/index.js.map +1 -1
  419. package/runner/shared.d.ts +31 -0
  420. package/runner/shared.d.ts.map +1 -0
  421. package/runner/shared.js +55 -0
  422. package/runner/shared.js.map +1 -0
  423. package/runner/useRunner.d.ts +37 -0
  424. package/runner/useRunner.d.ts.map +1 -0
  425. package/runner/useRunner.js +24 -0
  426. package/runner/useRunner.js.map +1 -0
  427. package/session/__tests__/group-sessions.test.js +3 -3
  428. package/session/__tests__/group-sessions.test.js.map +1 -1
  429. package/session/__tests__/session-spec-converters.test.d.ts +2 -0
  430. package/session/__tests__/session-spec-converters.test.d.ts.map +1 -0
  431. package/session/__tests__/session-spec-converters.test.js +162 -0
  432. package/session/__tests__/session-spec-converters.test.js.map +1 -0
  433. package/session/__tests__/useNewSessionFlow.test.js +2 -2
  434. package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
  435. package/session/__tests__/usePersistedModel.test.js +1 -1
  436. package/session/__tests__/usePersistedModel.test.js.map +1 -1
  437. package/session/group-sessions.d.ts +17 -0
  438. package/session/group-sessions.d.ts.map +1 -1
  439. package/session/group-sessions.js +46 -0
  440. package/session/group-sessions.js.map +1 -1
  441. package/session/index.d.ts +4 -2
  442. package/session/index.d.ts.map +1 -1
  443. package/session/index.js +2 -1
  444. package/session/index.js.map +1 -1
  445. package/session/session-spec-converters.d.ts +24 -0
  446. package/session/session-spec-converters.d.ts.map +1 -0
  447. package/session/session-spec-converters.js +72 -0
  448. package/session/session-spec-converters.js.map +1 -0
  449. package/session/useSessionConversation.d.ts.map +1 -1
  450. package/session/useSessionConversation.js +1 -56
  451. package/session/useSessionConversation.js.map +1 -1
  452. package/session/useSessionPageFlow.d.ts +5 -0
  453. package/session/useSessionPageFlow.d.ts.map +1 -1
  454. package/session/useSessionPageFlow.js +20 -6
  455. package/session/useSessionPageFlow.js.map +1 -1
  456. package/session/useSessionSearch.d.ts +57 -0
  457. package/session/useSessionSearch.d.ts.map +1 -0
  458. package/session/useSessionSearch.js +94 -0
  459. package/session/useSessionSearch.js.map +1 -0
  460. package/skill/SkillDetailView.d.ts +70 -7
  461. package/skill/SkillDetailView.d.ts.map +1 -1
  462. package/skill/SkillDetailView.js +107 -39
  463. package/skill/SkillDetailView.js.map +1 -1
  464. package/skill/SkillDiffDialog.d.ts +42 -0
  465. package/skill/SkillDiffDialog.d.ts.map +1 -0
  466. package/skill/SkillDiffDialog.js +72 -0
  467. package/skill/SkillDiffDialog.js.map +1 -0
  468. package/skill/SkillFileBrowser.d.ts +31 -0
  469. package/skill/SkillFileBrowser.d.ts.map +1 -0
  470. package/skill/SkillFileBrowser.js +105 -0
  471. package/skill/SkillFileBrowser.js.map +1 -0
  472. package/skill/SkillUploader.d.ts +39 -0
  473. package/skill/SkillUploader.d.ts.map +1 -0
  474. package/skill/SkillUploader.js +141 -0
  475. package/skill/SkillUploader.js.map +1 -0
  476. package/skill/index.d.ts +18 -0
  477. package/skill/index.d.ts.map +1 -1
  478. package/skill/index.js +9 -0
  479. package/skill/index.js.map +1 -1
  480. package/skill/internal/computeArtifactHash.d.ts +9 -0
  481. package/skill/internal/computeArtifactHash.d.ts.map +1 -0
  482. package/skill/internal/computeArtifactHash.js +14 -0
  483. package/skill/internal/computeArtifactHash.js.map +1 -0
  484. package/skill/internal/fetchAndUnpackArtifact.d.ts +16 -0
  485. package/skill/internal/fetchAndUnpackArtifact.d.ts.map +1 -0
  486. package/skill/internal/fetchAndUnpackArtifact.js +34 -0
  487. package/skill/internal/fetchAndUnpackArtifact.js.map +1 -0
  488. package/skill/usePushSkill.d.ts +53 -0
  489. package/skill/usePushSkill.d.ts.map +1 -0
  490. package/skill/usePushSkill.js +57 -0
  491. package/skill/usePushSkill.js.map +1 -0
  492. package/skill/useSkillArtifact.d.ts +37 -0
  493. package/skill/useSkillArtifact.d.ts.map +1 -0
  494. package/skill/useSkillArtifact.js +76 -0
  495. package/skill/useSkillArtifact.js.map +1 -0
  496. package/skill/useSkillDiff.d.ts +31 -0
  497. package/skill/useSkillDiff.d.ts.map +1 -0
  498. package/skill/useSkillDiff.js +97 -0
  499. package/skill/useSkillDiff.js.map +1 -0
  500. package/skill/useSkillDuplicateCheck.d.ts +34 -0
  501. package/skill/useSkillDuplicateCheck.d.ts.map +1 -0
  502. package/skill/useSkillDuplicateCheck.js +58 -0
  503. package/skill/useSkillDuplicateCheck.js.map +1 -0
  504. package/skill/useSkillUpload.d.ts +69 -0
  505. package/skill/useSkillUpload.d.ts.map +1 -0
  506. package/skill/useSkillUpload.js +157 -0
  507. package/skill/useSkillUpload.js.map +1 -0
  508. package/skill/useSkillVersions.d.ts +46 -0
  509. package/skill/useSkillVersions.d.ts.map +1 -0
  510. package/skill/useSkillVersions.js +104 -0
  511. package/skill/useSkillVersions.js.map +1 -0
  512. package/src/action-menu/ActionMenu.tsx +151 -0
  513. package/src/action-menu/index.ts +9 -0
  514. package/src/action-menu/types.ts +70 -0
  515. package/src/agent/AgentCreationWizard.tsx +201 -0
  516. package/src/agent/AgentDetailView.tsx +817 -321
  517. package/src/agent/index.ts +16 -0
  518. package/src/agent/internal/agentToInput.ts +95 -0
  519. package/src/agent/steps/CapabilitiesStep.tsx +363 -0
  520. package/src/agent/steps/IdentityStep.tsx +259 -0
  521. package/src/agent/steps/ReviewStep.tsx +211 -0
  522. package/src/agent/steps/types.ts +53 -0
  523. package/src/agent/useCreateAgent.ts +76 -0
  524. package/src/agent/useUpdateAgent.ts +55 -0
  525. package/src/composer/ContextChip.tsx +20 -11
  526. package/src/composer/SessionComposer.tsx +52 -3
  527. package/src/dependency-graph/DependencyGraph.tsx +153 -0
  528. package/src/dependency-graph/DependencyTreeNode.tsx +282 -0
  529. package/src/dependency-graph/index.ts +15 -0
  530. package/src/dependency-graph/types.ts +131 -0
  531. package/src/dependency-graph/useDependencyGraph.ts +158 -0
  532. package/src/empty-state/EmptyState.tsx +90 -0
  533. package/src/empty-state/index.ts +9 -0
  534. package/src/empty-state/types.ts +81 -0
  535. package/src/empty-state/useEmptyState.ts +85 -0
  536. package/src/environment/usePersonalEnvironment.ts +1 -0
  537. package/src/feedback/StigmerToaster.tsx +45 -0
  538. package/src/feedback/index.ts +3 -0
  539. package/src/feedback/toast.ts +13 -0
  540. package/src/feedback/types.ts +7 -0
  541. package/src/index.ts +275 -8
  542. package/src/inline-edit/InlineEditImage.tsx +208 -0
  543. package/src/inline-edit/InlineEditKeyValue.tsx +301 -0
  544. package/src/inline-edit/InlineEditResourceList.tsx +325 -0
  545. package/src/inline-edit/InlineEditSelect.tsx +150 -0
  546. package/src/inline-edit/InlineEditText.tsx +211 -0
  547. package/src/inline-edit/InlineEditTextarea.tsx +209 -0
  548. package/src/inline-edit/index.ts +28 -0
  549. package/src/inline-edit/types.ts +47 -0
  550. package/src/inline-edit/useInlineFieldSave.ts +62 -0
  551. package/src/internal/Tabs.tsx +4 -164
  552. package/src/internal/useFetch.ts +2 -2
  553. package/src/library/ImportResourceDialog.tsx +227 -0
  554. package/src/library/index.ts +18 -8
  555. package/src/library/serialize-resource-yaml.ts +356 -0
  556. package/src/library/useExportResource.ts +183 -0
  557. package/src/library/useImportResource.ts +253 -0
  558. package/src/mcp-server/McpServerCreationWizard.tsx +206 -0
  559. package/src/mcp-server/McpServerDetailView.tsx +816 -155
  560. package/src/mcp-server/index.ts +16 -0
  561. package/src/mcp-server/internal/mcpServerToInput.ts +95 -0
  562. package/src/mcp-server/steps/EnvironmentAuthStep.tsx +462 -0
  563. package/src/mcp-server/steps/IdentityTransportStep.tsx +531 -0
  564. package/src/mcp-server/steps/ReviewStep.tsx +297 -0
  565. package/src/mcp-server/steps/types.ts +85 -0
  566. package/src/mcp-server/useCreateMcpServer.ts +76 -0
  567. package/src/mcp-server/useUpdateMcpServer.ts +55 -0
  568. package/src/models/ModelRegistryContext.ts +3 -0
  569. package/src/models/ModelSelector.tsx +25 -2
  570. package/src/models/__tests__/useModelRegistry.test.tsx +5 -3
  571. package/src/models/useModelRegistry.ts +5 -2
  572. package/src/provider.tsx +69 -18
  573. package/src/resource-creation/CreationPicker.tsx +292 -0
  574. package/src/resource-creation/StepIndicator.tsx +156 -0
  575. package/src/resource-creation/TemplateCard.tsx +143 -0
  576. package/src/resource-creation/TemplateGallery.tsx +222 -0
  577. package/src/resource-creation/WizardNav.tsx +163 -0
  578. package/src/resource-creation/WizardShell.tsx +124 -0
  579. package/src/resource-creation/index.ts +45 -0
  580. package/src/resource-creation/templates/agent-templates.ts +160 -0
  581. package/src/resource-creation/templates/index.ts +7 -0
  582. package/src/resource-creation/templates/mcp-server-templates.ts +106 -0
  583. package/src/resource-creation/templates/types.ts +64 -0
  584. package/src/resource-creation/types.ts +105 -0
  585. package/src/resource-creation/useTemplateFilter.ts +117 -0
  586. package/src/resource-creation/useWizardState.ts +223 -0
  587. package/src/resource-detail/ConfirmDialog.tsx +127 -0
  588. package/src/resource-detail/ResourceActionBar.tsx +157 -0
  589. package/src/resource-detail/ResourceDetailShell.tsx +184 -0
  590. package/src/resource-detail/Section.tsx +78 -0
  591. package/src/resource-detail/index.ts +34 -0
  592. package/src/resource-detail/types.ts +177 -0
  593. package/src/resource-detail/useConfirmAction.ts +70 -0
  594. package/src/resource-detail/useCopyResource.ts +74 -0
  595. package/src/resource-detail/useDeleteResource.ts +110 -0
  596. package/src/resource-detail/useDetailTabs.ts +93 -0
  597. package/src/resource-workbench/components/BulkActionBar.tsx +122 -0
  598. package/src/resource-workbench/components/ColumnHeader.tsx +105 -0
  599. package/src/resource-workbench/components/FilterBar.tsx +173 -0
  600. package/src/resource-workbench/components/ResourceAvatar.tsx +109 -0
  601. package/src/resource-workbench/components/ResourceCards.tsx +126 -0
  602. package/src/resource-workbench/components/ResourceInspector.tsx +88 -0
  603. package/src/resource-workbench/components/ResourceList.tsx +121 -0
  604. package/src/resource-workbench/components/ResourceTable.tsx +222 -0
  605. package/src/resource-workbench/components/ResourceWorkbench.tsx +695 -0
  606. package/src/resource-workbench/components/SelectionCheckbox.tsx +52 -0
  607. package/src/resource-workbench/components/StatusBadge.tsx +119 -0
  608. package/src/resource-workbench/components/ViewSwitcher.tsx +135 -0
  609. package/src/resource-workbench/hooks/useResourceCollection.ts +261 -0
  610. package/src/resource-workbench/hooks/useResourceFilters.ts +216 -0
  611. package/src/resource-workbench/hooks/useResourceSelection.ts +178 -0
  612. package/src/resource-workbench/hooks/useViewPreference.ts +75 -0
  613. package/src/resource-workbench/index.ts +73 -0
  614. package/src/resource-workbench/types.ts +220 -0
  615. package/src/runner/RunnerDetailView.tsx +410 -0
  616. package/src/runner/RunnerListPanel.tsx +126 -111
  617. package/src/runner/index.ts +13 -1
  618. package/src/runner/shared.tsx +124 -0
  619. package/src/runner/useRunner.ts +59 -0
  620. package/src/session/__tests__/group-sessions.test.ts +5 -3
  621. package/src/session/__tests__/session-spec-converters.test.ts +185 -0
  622. package/src/session/__tests__/useNewSessionFlow.test.tsx +2 -2
  623. package/src/session/__tests__/usePersistedModel.test.tsx +1 -1
  624. package/src/session/group-sessions.ts +65 -0
  625. package/src/session/index.ts +8 -2
  626. package/src/session/session-spec-converters.ts +86 -0
  627. package/src/session/useSessionConversation.ts +5 -64
  628. package/src/session/useSessionPageFlow.ts +28 -7
  629. package/src/session/useSessionSearch.ts +149 -0
  630. package/src/skill/SkillDetailView.tsx +371 -165
  631. package/src/skill/SkillDiffDialog.tsx +213 -0
  632. package/src/skill/SkillFileBrowser.tsx +289 -0
  633. package/src/skill/SkillUploader.tsx +481 -0
  634. package/src/skill/index.ts +34 -0
  635. package/src/skill/internal/computeArtifactHash.ts +13 -0
  636. package/src/skill/internal/fetchAndUnpackArtifact.ts +48 -0
  637. package/src/skill/usePushSkill.ts +101 -0
  638. package/src/skill/useSkillArtifact.ts +107 -0
  639. package/src/skill/useSkillDiff.ts +128 -0
  640. package/src/skill/useSkillDuplicateCheck.ts +92 -0
  641. package/src/skill/useSkillUpload.ts +231 -0
  642. package/src/skill/useSkillVersions.ts +165 -0
  643. package/src/styles.css +28 -0
  644. package/src/tabs/Tabs.tsx +184 -0
  645. package/src/tabs/index.ts +2 -0
  646. package/src/version-history/DiffFileList.tsx +111 -0
  647. package/src/version-history/DiffSummary.tsx +61 -0
  648. package/src/version-history/DiffViewer.tsx +163 -0
  649. package/src/version-history/MultiFileDiffView.tsx +114 -0
  650. package/src/version-history/VersionTimeline.tsx +232 -0
  651. package/src/version-history/VersionTimelineEntry.tsx +254 -0
  652. package/src/version-history/computeDiff.ts +61 -0
  653. package/src/version-history/computeMultiFileDiff.ts +97 -0
  654. package/src/version-history/index.ts +22 -0
  655. package/src/version-history/types.ts +129 -0
  656. package/styles.css +1 -1
  657. package/tabs/Tabs.d.ts +58 -0
  658. package/tabs/Tabs.d.ts.map +1 -0
  659. package/tabs/Tabs.js +80 -0
  660. package/tabs/Tabs.js.map +1 -0
  661. package/tabs/index.d.ts +3 -0
  662. package/tabs/index.d.ts.map +1 -0
  663. package/tabs/index.js +2 -0
  664. package/tabs/index.js.map +1 -0
  665. package/version-history/DiffFileList.d.ts +22 -0
  666. package/version-history/DiffFileList.d.ts.map +1 -0
  667. package/version-history/DiffFileList.js +37 -0
  668. package/version-history/DiffFileList.js.map +1 -0
  669. package/version-history/DiffSummary.d.ts +21 -0
  670. package/version-history/DiffSummary.d.ts.map +1 -0
  671. package/version-history/DiffSummary.js +16 -0
  672. package/version-history/DiffSummary.js.map +1 -0
  673. package/version-history/DiffViewer.d.ts +31 -0
  674. package/version-history/DiffViewer.d.ts.map +1 -0
  675. package/version-history/DiffViewer.js +60 -0
  676. package/version-history/DiffViewer.js.map +1 -0
  677. package/version-history/MultiFileDiffView.d.ts +30 -0
  678. package/version-history/MultiFileDiffView.d.ts.map +1 -0
  679. package/version-history/MultiFileDiffView.js +40 -0
  680. package/version-history/MultiFileDiffView.js.map +1 -0
  681. package/version-history/VersionTimeline.d.ts +29 -0
  682. package/version-history/VersionTimeline.d.ts.map +1 -0
  683. package/version-history/VersionTimeline.js +87 -0
  684. package/version-history/VersionTimeline.js.map +1 -0
  685. package/version-history/VersionTimelineEntry.d.ts +22 -0
  686. package/version-history/VersionTimelineEntry.d.ts.map +1 -0
  687. package/version-history/VersionTimelineEntry.js +98 -0
  688. package/version-history/VersionTimelineEntry.js.map +1 -0
  689. package/version-history/computeDiff.d.ts +16 -0
  690. package/version-history/computeDiff.d.ts.map +1 -0
  691. package/version-history/computeDiff.js +54 -0
  692. package/version-history/computeDiff.js.map +1 -0
  693. package/version-history/computeMultiFileDiff.d.ts +15 -0
  694. package/version-history/computeMultiFileDiff.d.ts.map +1 -0
  695. package/version-history/computeMultiFileDiff.js +83 -0
  696. package/version-history/computeMultiFileDiff.js.map +1 -0
  697. package/version-history/index.d.ts +14 -0
  698. package/version-history/index.d.ts.map +1 -0
  699. package/version-history/index.js +9 -0
  700. package/version-history/index.js.map +1 -0
  701. package/version-history/types.d.ts +106 -0
  702. package/version-history/types.d.ts.map +1 -0
  703. package/version-history/types.js +2 -0
  704. package/version-history/types.js.map +1 -0
  705. package/library/ResourceListView.d.ts +0 -174
  706. package/library/ResourceListView.d.ts.map +0 -1
  707. package/library/ResourceListView.js +0 -318
  708. package/library/ResourceListView.js.map +0 -1
  709. package/src/library/ResourceListView.tsx +0 -956
@@ -15,6 +15,8 @@ import { ValidationState } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1
15
15
  import type { EnvVarDeclaration } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
16
16
  import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
17
17
  import { useMcpServer } from "./useMcpServer";
18
+ import { useUpdateMcpServer } from "./useUpdateMcpServer";
19
+ import { mcpServerToInput } from "./internal/mcpServerToInput";
18
20
  import { useMcpServerConnect } from "./useMcpServerConnect";
19
21
  import { useMcpServerCredentials } from "./useMcpServerCredentials";
20
22
  import { useMcpServerOAuthConnect } from "./useMcpServerOAuthConnect";
@@ -26,7 +28,16 @@ import { ErrorMessage } from "../error/ErrorMessage";
26
28
  import { EnvVarForm } from "../environment/EnvVarForm";
27
29
  import type { EnvVarFormVariable } from "../environment/EnvVarForm";
28
30
  import { VisibilityToggle } from "../library/VisibilityToggle";
29
- import { Tabs, type TabItem } from "../internal/Tabs";
31
+ import { Tabs, type TabItem } from "../tabs/Tabs";
32
+ import { ResourceActionBar } from "../resource-detail/ResourceActionBar";
33
+ import { Section } from "../resource-detail/Section";
34
+ import type { DetailAction } from "../resource-detail/types";
35
+ import { InlineEditText } from "../inline-edit/InlineEditText";
36
+ import { InlineEditTextarea } from "../inline-edit/InlineEditTextarea";
37
+ import { InlineEditImage } from "../inline-edit/InlineEditImage";
38
+ import { InlineEditSelect } from "../inline-edit/InlineEditSelect";
39
+ import { InlineEditKeyValue } from "../inline-edit/InlineEditKeyValue";
40
+ import type { KeyValueRow, SelectOption } from "../inline-edit/types";
30
41
 
31
42
  /** Tab identifier for the MCP server capability panel. */
32
43
  export type CapabilityTab = "tools" | "policies" | "resources";
@@ -85,6 +96,24 @@ export interface McpServerDetailViewProps {
85
96
  * When omitted, falls back to the `org` prop (MCP server's org).
86
97
  */
87
98
  readonly activeOrg?: string;
99
+ /**
100
+ * Primary action rendered as a visible button in the header area.
101
+ */
102
+ readonly primaryAction?: DetailAction;
103
+ /**
104
+ * Secondary actions rendered in the kebab overflow menu.
105
+ */
106
+ readonly actions?: readonly DetailAction[];
107
+ /**
108
+ * When `true`, fields on the detail view become click-to-edit.
109
+ * Each field saves independently via `stigmer.mcpServer.update()`.
110
+ * @default false
111
+ */
112
+ readonly editable?: boolean;
113
+ /**
114
+ * Called after a successful inline field save with the updated server.
115
+ */
116
+ readonly onResourceUpdated?: (server: McpServer) => void;
88
117
  /** Additional CSS classes for the root container. */
89
118
  readonly className?: string;
90
119
  }
@@ -123,9 +152,34 @@ export function McpServerDetailView({
123
152
  defaultShowCredentialForm = false,
124
153
  credentialPoolValues,
125
154
  activeOrg,
155
+ primaryAction,
156
+ actions,
157
+ editable = false,
158
+ onResourceUpdated,
126
159
  className,
127
160
  }: McpServerDetailViewProps) {
128
161
  const { mcpServer, isLoading, error, refetch } = useMcpServer(org, slug);
162
+ const { update: updateMcpServer, isUpdating } = useUpdateMcpServer();
163
+
164
+ const saveMcpField = useCallback(
165
+ async <K extends keyof import("@stigmer/sdk").McpServerInput>(
166
+ field: K,
167
+ value: import("@stigmer/sdk").McpServerInput[K],
168
+ ): Promise<boolean> => {
169
+ if (!mcpServer) return false;
170
+ const input = mcpServerToInput(mcpServer);
171
+ (input as unknown as Record<string, unknown>)[field] = value;
172
+ try {
173
+ const updated = await updateMcpServer(input);
174
+ onResourceUpdated?.(updated);
175
+ refetch();
176
+ return true;
177
+ } catch {
178
+ return false;
179
+ }
180
+ },
181
+ [mcpServer, updateMcpServer, onResourceUpdated, refetch],
182
+ );
129
183
  const credentials = useMcpServerCredentials(activeOrg ?? org, mcpServer ?? null);
130
184
  const connection = useMcpServerConnect();
131
185
  const oauth = useMcpServerOAuthConnect();
@@ -199,20 +253,16 @@ export function McpServerDetailView({
199
253
  credentials.refetch();
200
254
  }
201
255
 
202
- setShowCredentialForm(false);
203
-
204
256
  if (mcpServer?.metadata?.id) {
205
257
  const envKeys = Object.keys(mcpServer.spec?.env ?? {});
206
258
  const connectOrg = activeOrg ?? org;
207
- if (options.saveForFuture) {
208
- await connection.connect(mcpServer.metadata.id, connectOrg, undefined, envKeys);
209
- } else {
210
- await connection.connect(mcpServer.metadata.id, connectOrg, values, envKeys);
211
- }
259
+ await connection.connect(mcpServer.metadata.id, connectOrg, values, envKeys);
212
260
  refetch();
213
261
  }
262
+
263
+ setShowCredentialForm(false);
214
264
  } catch {
215
- // error state is managed by the hooks
265
+ // error state is managed by the hooks — form stays open for retry
216
266
  }
217
267
  },
218
268
  [credentials, mcpServer, connection, refetch],
@@ -312,33 +362,73 @@ export function McpServerDetailView({
312
362
  <ValidationBanner message={status.validationMessage} />
313
363
  )}
314
364
 
315
- <Header
316
- server={mcpServer}
317
- createdAt={
318
- specAudit?.createdAt ? timestampDate(specAudit.createdAt) : null
319
- }
320
- updatedAt={
321
- specAudit?.updatedAt ? timestampDate(specAudit.updatedAt) : null
322
- }
323
- lastDiscoveredAt={
324
- capabilities?.lastDiscoveredAt
325
- ? timestampDate(capabilities.lastDiscoveredAt)
326
- : null
327
- }
328
- onVisibilityChange={onVisibilityChange}
329
- isVisibilityPending={isVisibilityPending}
330
- />
365
+ <div className="flex items-start justify-between gap-4">
366
+ <Header
367
+ server={mcpServer}
368
+ createdAt={
369
+ specAudit?.createdAt ? timestampDate(specAudit.createdAt) : null
370
+ }
371
+ updatedAt={
372
+ specAudit?.updatedAt ? timestampDate(specAudit.updatedAt) : null
373
+ }
374
+ lastDiscoveredAt={
375
+ capabilities?.lastDiscoveredAt
376
+ ? timestampDate(capabilities.lastDiscoveredAt)
377
+ : null
378
+ }
379
+ onVisibilityChange={onVisibilityChange}
380
+ isVisibilityPending={isVisibilityPending}
381
+ editable={editable}
382
+ isSaving={isUpdating}
383
+ saveMcpField={saveMcpField}
384
+ />
385
+ <ResourceActionBar
386
+ primaryAction={primaryAction}
387
+ actions={actions}
388
+ className="shrink-0"
389
+ />
390
+ </div>
391
+
392
+ {(editable || spec?.description) && (
393
+ <Section title="Description">
394
+ {editable && saveMcpField ? (
395
+ <div className="max-h-20 overflow-y-auto p-3">
396
+ <InlineEditTextarea
397
+ value={spec?.description || ""}
398
+ onSave={(v) => saveMcpField("description", v || undefined)}
399
+ isSaving={isUpdating}
400
+ placeholder="Add a description"
401
+ minRows={2}
402
+ />
403
+ </div>
404
+ ) : (
405
+ <div className="p-3">
406
+ <pre className="whitespace-pre-wrap break-words text-sm text-foreground font-sans">
407
+ {spec?.description}
408
+ </pre>
409
+ </div>
410
+ )}
411
+ </Section>
412
+ )}
331
413
 
332
414
  {hasSource && <SourceSection spec={spec} />}
333
415
 
334
- {spec?.serverType.case && (
335
- <ServerConfigSection serverType={spec.serverType} />
416
+ {(editable || spec?.serverType.case) && (
417
+ <ServerConfigSection
418
+ serverType={spec?.serverType}
419
+ editable={editable}
420
+ isSaving={isUpdating}
421
+ saveMcpField={saveMcpField}
422
+ />
336
423
  )}
337
424
 
338
- {spec?.env && Object.keys(spec.env).length > 0 && (
425
+ {(editable || (spec?.env && Object.keys(spec.env).length > 0)) && (
339
426
  <EnvSection
340
- data={spec.env}
427
+ data={spec?.env ?? {}}
341
428
  oauthTargetEnvVar={credentials.oauthTargetEnvVar}
429
+ editable={editable}
430
+ isSaving={isUpdating}
431
+ saveMcpField={saveMcpField}
342
432
  />
343
433
  )}
344
434
 
@@ -349,8 +439,6 @@ export function McpServerDetailView({
349
439
  onConnect={handleConnectClick}
350
440
  onClearConnectionError={combinedClearError}
351
441
  hasDiscoveredTools={hasDiscoveredTools}
352
- toolCount={tools.length}
353
- policyCount={totalPolicyCount}
354
442
  credentialsLoading={credentials.isLoading}
355
443
  oauthPhase={oauth.phase}
356
444
  authMode={credentials.authMode}
@@ -455,7 +543,9 @@ export function McpServerDetailView({
455
543
  </Tabs>
456
544
  </Section>
457
545
 
458
- {spec && spec.tags.length > 0 && <TagsSection tags={spec.tags} />}
546
+ {(editable || (spec && spec.tags.length > 0)) && (
547
+ <TagsSection tags={spec?.tags ?? []} editable={editable} isSaving={isUpdating} saveMcpField={saveMcpField} />
548
+ )}
459
549
  </div>
460
550
  );
461
551
  }
@@ -539,8 +629,6 @@ function ConnectBar({
539
629
  onConnect,
540
630
  onClearConnectionError,
541
631
  hasDiscoveredTools,
542
- toolCount,
543
- policyCount,
544
632
  credentialsLoading,
545
633
  oauthPhase,
546
634
  authMode,
@@ -574,8 +662,6 @@ function ConnectBar({
574
662
  readonly onConnect: () => void;
575
663
  readonly onClearConnectionError: () => void;
576
664
  readonly hasDiscoveredTools: boolean;
577
- readonly toolCount: number;
578
- readonly policyCount: number;
579
665
  readonly credentialsLoading: boolean;
580
666
  readonly oauthPhase: OAuthConnectPhase;
581
667
  readonly authMode: "manual" | "oauth";
@@ -647,7 +733,7 @@ function ConnectBar({
647
733
  }
648
734
  if (isOrgOAuthApp && showOAuthPrimary) return "Using your OAuth app";
649
735
  if (manualOverride) return "Entering token manually";
650
- if (hasDiscoveredTools) return formatConnectionSummary(toolCount, policyCount);
736
+ if (hasDiscoveredTools) return "Connected";
651
737
  return "Not connected yet";
652
738
  })();
653
739
 
@@ -990,13 +1076,6 @@ function oauthPhaseLabel(phase: OAuthConnectPhase): string {
990
1076
  }
991
1077
  }
992
1078
 
993
- function formatConnectionSummary(toolCount: number, policyCount: number): string {
994
- const toolLabel = `${toolCount} tool${toolCount !== 1 ? "s" : ""}`;
995
- if (policyCount === 0) return toolLabel;
996
- const policyLabel = `${policyCount} ${policyCount !== 1 ? "policies" : "policy"}`;
997
- return `${toolLabel}, ${policyLabel}`;
998
- }
999
-
1000
1079
  function formatTokenExpiry(expiresAtSeconds: bigint): string | null {
1001
1080
  if (expiresAtSeconds === BigInt(0)) return null;
1002
1081
  const nowSeconds = BigInt(Math.floor(Date.now() / 1000));
@@ -1039,6 +1118,9 @@ function Header({
1039
1118
  lastDiscoveredAt,
1040
1119
  onVisibilityChange,
1041
1120
  isVisibilityPending,
1121
+ editable,
1122
+ isSaving,
1123
+ saveMcpField,
1042
1124
  }: {
1043
1125
  readonly server: McpServer;
1044
1126
  readonly createdAt: Date | null;
@@ -1046,6 +1128,12 @@ function Header({
1046
1128
  readonly lastDiscoveredAt: Date | null;
1047
1129
  readonly onVisibilityChange?: (v: ApiResourceVisibility) => void;
1048
1130
  readonly isVisibilityPending?: boolean;
1131
+ readonly editable?: boolean;
1132
+ readonly isSaving?: boolean;
1133
+ readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
1134
+ field: K,
1135
+ value: import("@stigmer/sdk").McpServerInput[K],
1136
+ ) => Promise<boolean>;
1049
1137
  }) {
1050
1138
  const meta = server.metadata;
1051
1139
  const spec = server.spec;
@@ -1056,7 +1144,15 @@ function Header({
1056
1144
 
1057
1145
  return (
1058
1146
  <div className="flex items-start gap-3">
1059
- {spec?.iconUrl ? (
1147
+ {editable && saveMcpField ? (
1148
+ <InlineEditImage
1149
+ value={spec?.iconUrl ?? ""}
1150
+ onSave={(v) => saveMcpField("iconUrl", v || undefined)}
1151
+ isSaving={isSaving}
1152
+ fallback={<McpServerIcon className="size-6 text-muted-foreground" />}
1153
+ size="md"
1154
+ />
1155
+ ) : spec?.iconUrl ? (
1060
1156
  <img
1061
1157
  src={spec.iconUrl}
1062
1158
  alt=""
@@ -1067,9 +1163,20 @@ function Header({
1067
1163
  )}
1068
1164
  <div className="min-w-0 flex-1">
1069
1165
  <div className="flex items-center gap-2">
1070
- <h2 className="truncate text-lg font-semibold text-foreground">
1071
- {displayName}
1072
- </h2>
1166
+ {editable && saveMcpField ? (
1167
+ <InlineEditText
1168
+ value={meta?.name || ""}
1169
+ onSave={(v) => saveMcpField("name", v)}
1170
+ isSaving={isSaving}
1171
+ variant="heading"
1172
+ placeholder="Server name"
1173
+ validate={(v) => (v.trim() ? null : "Name is required")}
1174
+ />
1175
+ ) : (
1176
+ <h2 className="truncate text-lg font-semibold text-foreground">
1177
+ {displayName}
1178
+ </h2>
1179
+ )}
1073
1180
  {onVisibilityChange && meta ? (
1074
1181
  <VisibilityToggle
1075
1182
  visibility={meta.visibility}
@@ -1113,11 +1220,6 @@ function Header({
1113
1220
  </>
1114
1221
  )}
1115
1222
  </div>
1116
- {spec?.description && (
1117
- <p className="mt-2 text-sm text-muted-foreground">
1118
- {spec.description}
1119
- </p>
1120
- )}
1121
1223
  </div>
1122
1224
  </div>
1123
1225
  );
@@ -1151,13 +1253,94 @@ function ValidationStateBadge({
1151
1253
  }
1152
1254
  }
1153
1255
 
1256
+ const TRANSPORT_OPTIONS: SelectOption[] = [
1257
+ { value: "http", label: "HTTP", description: "Connect via HTTP/SSE endpoint" },
1258
+ { value: "stdio", label: "Stdio", description: "Launch a local process with stdin/stdout" },
1259
+ ];
1260
+
1154
1261
  function ServerConfigSection({
1155
1262
  serverType,
1263
+ editable,
1264
+ isSaving,
1265
+ saveMcpField,
1156
1266
  }: {
1157
- readonly serverType: NonNullable<
1158
- import("@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb").McpServerSpec["serverType"]
1159
- >;
1267
+ readonly serverType?: import("@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb").McpServerSpec["serverType"];
1268
+ readonly editable?: boolean;
1269
+ readonly isSaving?: boolean;
1270
+ readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
1271
+ field: K,
1272
+ value: import("@stigmer/sdk").McpServerInput[K],
1273
+ ) => Promise<boolean>;
1160
1274
  }) {
1275
+ const [headersEditing, setHeadersEditing] = useState(false);
1276
+ const [queryParamsEditing, setQueryParamsEditing] = useState(false);
1277
+
1278
+ const currentHttpConfig = useMemo(() => {
1279
+ if (serverType?.case !== "http") return null;
1280
+ const v = serverType.value;
1281
+ return {
1282
+ url: v.url,
1283
+ headers: v.headers && Object.keys(v.headers).length > 0 ? { ...v.headers } : undefined,
1284
+ queryParams: v.queryParams && Object.keys(v.queryParams).length > 0 ? { ...v.queryParams } : undefined,
1285
+ timeoutSeconds: v.timeoutSeconds || undefined,
1286
+ };
1287
+ }, [serverType]);
1288
+
1289
+ const handleTransportChange = useCallback(
1290
+ async (newType: string) => {
1291
+ if (!saveMcpField) return false;
1292
+ if (newType === "http") {
1293
+ const ok = await saveMcpField("http", { url: "" });
1294
+ if (ok) await saveMcpField("stdio", undefined);
1295
+ return ok;
1296
+ }
1297
+ const ok = await saveMcpField("stdio", { command: "" });
1298
+ if (ok) await saveMcpField("http", undefined);
1299
+ return ok;
1300
+ },
1301
+ [saveMcpField],
1302
+ );
1303
+
1304
+ const headerRows: KeyValueRow[] = useMemo(() => {
1305
+ if (!currentHttpConfig?.headers) return [];
1306
+ return Object.entries(currentHttpConfig.headers).map(([key, value]) => ({ key, value }));
1307
+ }, [currentHttpConfig?.headers]);
1308
+
1309
+ const queryParamRows: KeyValueRow[] = useMemo(() => {
1310
+ if (!currentHttpConfig?.queryParams) return [];
1311
+ return Object.entries(currentHttpConfig.queryParams).map(([key, value]) => ({ key, value }));
1312
+ }, [currentHttpConfig?.queryParams]);
1313
+
1314
+ const handleHeadersSave = useCallback(
1315
+ async (rows: KeyValueRow[]) => {
1316
+ if (!saveMcpField || !currentHttpConfig) return false;
1317
+ const headers: Record<string, string> = {};
1318
+ for (const row of rows) {
1319
+ if (row.key.trim()) headers[row.key.trim()] = row.value;
1320
+ }
1321
+ return saveMcpField("http", {
1322
+ ...currentHttpConfig,
1323
+ headers: Object.keys(headers).length > 0 ? headers : undefined,
1324
+ });
1325
+ },
1326
+ [saveMcpField, currentHttpConfig],
1327
+ );
1328
+
1329
+ const handleQueryParamsSave = useCallback(
1330
+ async (rows: KeyValueRow[]) => {
1331
+ if (!saveMcpField || !currentHttpConfig) return false;
1332
+ const queryParams: Record<string, string> = {};
1333
+ for (const row of rows) {
1334
+ if (row.key.trim()) queryParams[row.key.trim()] = row.value;
1335
+ }
1336
+ return saveMcpField("http", {
1337
+ ...currentHttpConfig,
1338
+ queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
1339
+ });
1340
+ },
1341
+ [saveMcpField, currentHttpConfig],
1342
+ );
1343
+
1161
1344
  return (
1162
1345
  <Section title="Server Configuration">
1163
1346
  <div className="flex flex-col gap-2 p-3">
@@ -1165,63 +1348,265 @@ function ServerConfigSection({
1165
1348
  <span className="text-xs font-medium text-muted-foreground">
1166
1349
  Type
1167
1350
  </span>
1168
- <span className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs font-medium text-foreground">
1169
- {serverType.case}
1170
- </span>
1351
+ {editable && saveMcpField ? (
1352
+ <InlineEditSelect
1353
+ value={serverType?.case ?? "http"}
1354
+ options={TRANSPORT_OPTIONS}
1355
+ onSave={handleTransportChange}
1356
+ isSaving={isSaving}
1357
+ />
1358
+ ) : (
1359
+ <span className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs font-medium text-foreground">
1360
+ {serverType?.case ?? "none"}
1361
+ </span>
1362
+ )}
1171
1363
  </div>
1172
1364
 
1173
- {serverType.case === "stdio" && (
1365
+ {serverType?.case === "stdio" && (
1174
1366
  <>
1175
1367
  <div className="flex items-baseline gap-2">
1176
1368
  <span className="text-xs font-medium text-muted-foreground">
1177
1369
  Command
1178
1370
  </span>
1179
- <code className="font-mono text-sm text-foreground">
1180
- {serverType.value.command}
1181
- {serverType.value.args.length > 0 &&
1182
- ` ${serverType.value.args.join(" ")}`}
1183
- </code>
1371
+ {editable && saveMcpField ? (
1372
+ <InlineEditText
1373
+ value={`${serverType.value.command}${serverType.value.args.length > 0 ? ` ${serverType.value.args.join(" ")}` : ""}`}
1374
+ onSave={async (v) => {
1375
+ const parts = v.trim().split(/\s+/);
1376
+ return saveMcpField("stdio", {
1377
+ command: parts[0] || "",
1378
+ args: parts.slice(1),
1379
+ });
1380
+ }}
1381
+ isSaving={isSaving}
1382
+ placeholder="e.g. npx -y @modelcontextprotocol/server"
1383
+ />
1384
+ ) : (
1385
+ <code className="font-mono text-sm text-foreground">
1386
+ {serverType.value.command}
1387
+ {serverType.value.args.length > 0 &&
1388
+ ` ${serverType.value.args.join(" ")}`}
1389
+ </code>
1390
+ )}
1184
1391
  </div>
1185
- {serverType.value.workingDir && (
1392
+ {(editable || serverType.value.workingDir) && (
1186
1393
  <div className="flex items-baseline gap-2">
1187
1394
  <span className="text-xs font-medium text-muted-foreground">
1188
1395
  Working Dir
1189
1396
  </span>
1190
- <code className="font-mono text-xs text-foreground">
1191
- {serverType.value.workingDir}
1192
- </code>
1397
+ {editable && saveMcpField ? (
1398
+ <InlineEditText
1399
+ value={serverType.value.workingDir ?? ""}
1400
+ onSave={async (v) =>
1401
+ saveMcpField("stdio", {
1402
+ command: serverType.value.command,
1403
+ args: [...serverType.value.args],
1404
+ workingDir: v || undefined,
1405
+ })
1406
+ }
1407
+ isSaving={isSaving}
1408
+ placeholder="/path/to/working/dir"
1409
+ />
1410
+ ) : (
1411
+ <code className="font-mono text-xs text-foreground">
1412
+ {serverType.value.workingDir}
1413
+ </code>
1414
+ )}
1193
1415
  </div>
1194
1416
  )}
1195
1417
  </>
1196
1418
  )}
1197
1419
 
1198
- {serverType.case === "http" && (
1420
+ {serverType?.case === "http" && (
1199
1421
  <>
1200
1422
  <div className="flex items-baseline gap-2">
1201
1423
  <span className="text-xs font-medium text-muted-foreground">
1202
1424
  URL
1203
1425
  </span>
1204
- <code className="break-all font-mono text-sm text-foreground">
1205
- {serverType.value.url}
1206
- </code>
1426
+ {editable && saveMcpField ? (
1427
+ <InlineEditText
1428
+ value={serverType.value.url}
1429
+ onSave={async (v) =>
1430
+ saveMcpField("http", { ...currentHttpConfig!, url: v })
1431
+ }
1432
+ isSaving={isSaving}
1433
+ placeholder="https://example.com/mcp"
1434
+ />
1435
+ ) : (
1436
+ <code className="break-all font-mono text-sm text-foreground">
1437
+ {serverType.value.url}
1438
+ </code>
1439
+ )}
1207
1440
  </div>
1208
- {serverType.value.timeoutSeconds > 0 && (
1441
+ {(editable || serverType.value.timeoutSeconds > 0) && (
1209
1442
  <div className="flex items-baseline gap-2">
1210
1443
  <span className="text-xs font-medium text-muted-foreground">
1211
1444
  Timeout
1212
1445
  </span>
1213
- <span className="text-xs text-foreground">
1214
- {serverType.value.timeoutSeconds}s
1215
- </span>
1446
+ {editable && saveMcpField ? (
1447
+ <InlineEditText
1448
+ value={serverType.value.timeoutSeconds > 0 ? String(serverType.value.timeoutSeconds) : ""}
1449
+ onSave={async (v) =>
1450
+ saveMcpField("http", {
1451
+ ...currentHttpConfig!,
1452
+ timeoutSeconds: v ? Number(v) : undefined,
1453
+ })
1454
+ }
1455
+ isSaving={isSaving}
1456
+ placeholder="30"
1457
+ validate={(v) => {
1458
+ if (v && (isNaN(Number(v)) || Number(v) < 0)) return "Must be a positive number";
1459
+ return null;
1460
+ }}
1461
+ />
1462
+ ) : (
1463
+ <span className="text-xs text-foreground">
1464
+ {serverType.value.timeoutSeconds}s
1465
+ </span>
1466
+ )}
1216
1467
  </div>
1217
1468
  )}
1218
1469
  </>
1219
1470
  )}
1220
1471
  </div>
1472
+
1473
+ {serverType?.case === "http" && (editable || headerRows.length > 0) && (
1474
+ <HttpKeyValueSubsection
1475
+ title="Headers"
1476
+ count={headerRows.length}
1477
+ rows={headerRows}
1478
+ editable={editable}
1479
+ isSaving={isSaving}
1480
+ editing={headersEditing}
1481
+ onEditingChange={setHeadersEditing}
1482
+ onSave={handleHeadersSave}
1483
+ keyLabel="Header name"
1484
+ />
1485
+ )}
1486
+
1487
+ {serverType?.case === "http" && (editable || queryParamRows.length > 0) && (
1488
+ <HttpKeyValueSubsection
1489
+ title="Query Parameters"
1490
+ count={queryParamRows.length}
1491
+ rows={queryParamRows}
1492
+ editable={editable}
1493
+ isSaving={isSaving}
1494
+ editing={queryParamsEditing}
1495
+ onEditingChange={setQueryParamsEditing}
1496
+ onSave={handleQueryParamsSave}
1497
+ keyLabel="Parameter name"
1498
+ />
1499
+ )}
1221
1500
  </Section>
1222
1501
  );
1223
1502
  }
1224
1503
 
1504
+ /** Renders a key-value subsection (headers or query params) within ServerConfigSection. */
1505
+ function HttpKeyValueSubsection({
1506
+ title,
1507
+ count,
1508
+ rows,
1509
+ editable,
1510
+ isSaving,
1511
+ editing,
1512
+ onEditingChange,
1513
+ onSave,
1514
+ keyLabel,
1515
+ }: {
1516
+ readonly title: string;
1517
+ readonly count: number;
1518
+ readonly rows: readonly KeyValueRow[];
1519
+ readonly editable?: boolean;
1520
+ readonly isSaving?: boolean;
1521
+ readonly editing: boolean;
1522
+ readonly onEditingChange: (v: boolean) => void;
1523
+ readonly onSave: (rows: KeyValueRow[]) => Promise<boolean>;
1524
+ readonly keyLabel: string;
1525
+ }) {
1526
+ return (
1527
+ <div className="border-t border-border">
1528
+ <div className="flex items-center justify-between px-3 py-2">
1529
+ <div className="flex items-center gap-1.5">
1530
+ <span className="text-xs font-medium text-muted-foreground">{title}</span>
1531
+ {count > 0 && (
1532
+ <span className="inline-flex min-w-[1.25rem] items-center justify-center rounded-full bg-muted px-1 py-px text-[10px] font-medium leading-none text-muted-foreground">
1533
+ {count}
1534
+ </span>
1535
+ )}
1536
+ </div>
1537
+ {editable && (
1538
+ <button
1539
+ type="button"
1540
+ onClick={() => onEditingChange(!editing)}
1541
+ className="text-[11px] text-muted-foreground underline decoration-muted-foreground/40 underline-offset-2 hover:text-foreground hover:decoration-foreground"
1542
+ >
1543
+ {editing ? "Done" : "Edit"}
1544
+ </button>
1545
+ )}
1546
+ </div>
1547
+ {editable && editing ? (
1548
+ <InlineEditKeyValue
1549
+ value={[...rows]}
1550
+ onSave={onSave}
1551
+ isSaving={isSaving}
1552
+ editing={editing}
1553
+ onEditingChange={onEditingChange}
1554
+ keyLabel={keyLabel}
1555
+ showValue
1556
+ valueLabel="Value"
1557
+ />
1558
+ ) : (
1559
+ <div className="flex flex-col divide-y divide-border">
1560
+ {rows.map((row) => (
1561
+ <div key={row.key} className="flex items-start gap-2 px-3 py-1.5">
1562
+ <code className="shrink-0 font-mono text-xs font-medium text-foreground">
1563
+ {row.key}
1564
+ </code>
1565
+ <span className="min-w-0 break-all font-mono text-xs text-muted-foreground">
1566
+ {renderHeaderValue(row.value)}
1567
+ </span>
1568
+ </div>
1569
+ ))}
1570
+ </div>
1571
+ )}
1572
+ </div>
1573
+ );
1574
+ }
1575
+
1576
+ const ENV_VAR_PLACEHOLDER = /\$\{([^}]+)\}/g;
1577
+
1578
+ /** Renders a header value, highlighting ${VAR} placeholders with a variable badge. */
1579
+ function renderHeaderValue(value: string): React.ReactNode {
1580
+ if (!ENV_VAR_PLACEHOLDER.test(value)) return value;
1581
+
1582
+ ENV_VAR_PLACEHOLDER.lastIndex = 0;
1583
+ const parts: React.ReactNode[] = [];
1584
+ let lastIndex = 0;
1585
+ let match: RegExpExecArray | null;
1586
+
1587
+ while ((match = ENV_VAR_PLACEHOLDER.exec(value)) !== null) {
1588
+ if (match.index > lastIndex) {
1589
+ parts.push(value.slice(lastIndex, match.index));
1590
+ }
1591
+ parts.push(
1592
+ <span
1593
+ key={match.index}
1594
+ className="inline-flex items-center gap-0.5 rounded bg-primary-subtle px-1 py-px text-[10px] font-medium text-primary"
1595
+ title={`Resolved from environment variable: ${match[1]}`}
1596
+ >
1597
+ {match[0]}
1598
+ </span>,
1599
+ );
1600
+ lastIndex = match.index + match[0].length;
1601
+ }
1602
+
1603
+ if (lastIndex < value.length) {
1604
+ parts.push(value.slice(lastIndex));
1605
+ }
1606
+
1607
+ return <>{parts}</>;
1608
+ }
1609
+
1225
1610
  function SourceSection({
1226
1611
  spec,
1227
1612
  }: {
@@ -1294,53 +1679,138 @@ function ResourceTemplatesList({
1294
1679
  function EnvSection({
1295
1680
  data,
1296
1681
  oauthTargetEnvVar,
1682
+ editable,
1683
+ isSaving,
1684
+ saveMcpField,
1297
1685
  }: {
1298
1686
  readonly data: { [key: string]: EnvVarDeclaration };
1299
1687
  readonly oauthTargetEnvVar: string | null;
1688
+ readonly editable?: boolean;
1689
+ readonly isSaving?: boolean;
1690
+ readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
1691
+ field: K,
1692
+ value: import("@stigmer/sdk").McpServerInput[K],
1693
+ ) => Promise<boolean>;
1300
1694
  }) {
1301
1695
  const entries = Object.entries(data).sort(([a], [b]) =>
1302
1696
  a.localeCompare(b),
1303
1697
  );
1304
1698
 
1699
+ const envRows: KeyValueRow[] = useMemo(
1700
+ () =>
1701
+ entries.map(([key, decl]) => ({
1702
+ key,
1703
+ value: "",
1704
+ isSecret: decl.isSecret,
1705
+ description: decl.description,
1706
+ optional: decl.optional,
1707
+ })),
1708
+ [entries],
1709
+ );
1710
+
1711
+ const handleEnvSave = useCallback(
1712
+ async (rows: KeyValueRow[]) => {
1713
+ if (!saveMcpField) return false;
1714
+ const env: Record<string, { isSecret?: boolean; description?: string; optional?: boolean }> = {};
1715
+ for (const row of rows) {
1716
+ if (row.key.trim()) {
1717
+ env[row.key.trim()] = {
1718
+ isSecret: row.isSecret || undefined,
1719
+ description: row.description || undefined,
1720
+ optional: row.optional || undefined,
1721
+ };
1722
+ }
1723
+ }
1724
+ return saveMcpField("env", Object.keys(env).length > 0 ? env : undefined);
1725
+ },
1726
+ [saveMcpField],
1727
+ );
1728
+
1729
+ const [envEditing, setEnvEditing] = useState(false);
1730
+
1305
1731
  return (
1306
- <Section title={`Environment Variables (${entries.length})`}>
1307
- <div className="flex flex-col divide-y divide-border">
1308
- {entries.map(([name, env]) => {
1309
- const isOAuthManaged = name === oauthTargetEnvVar;
1310
- return (
1311
- <div key={name} className="flex items-start gap-3 px-3 py-2">
1312
- <code className="shrink-0 font-mono text-sm font-medium text-foreground">
1313
- {name}
1314
- </code>
1315
- <span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
1316
- {env.isSecret ? "secret" : "config"}
1317
- </span>
1318
- {isOAuthManaged && (
1319
- <span className="shrink-0 rounded bg-primary-subtle px-1.5 py-0.5 text-[10px] font-medium text-primary">
1320
- oauth
1321
- </span>
1322
- )}
1323
- {env.optional && (
1324
- <span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground-subtle">
1325
- optional
1326
- </span>
1327
- )}
1328
- {env.description && (
1329
- <span className="text-xs text-muted-foreground">
1330
- {env.description}
1732
+ <Section title="Environment Variables" count={entries.length} onEdit={editable ? () => setEnvEditing((v) => !v) : undefined}>
1733
+ {editable ? (
1734
+ <InlineEditKeyValue
1735
+ value={envRows}
1736
+ onSave={handleEnvSave}
1737
+ isSaving={isSaving}
1738
+ editing={envEditing}
1739
+ onEditingChange={setEnvEditing}
1740
+ showSecretToggle
1741
+ showOptionalToggle
1742
+ showDescription
1743
+ keyLabel="Variable name"
1744
+ />
1745
+ ) : (
1746
+ <div className="flex flex-col divide-y divide-border">
1747
+ {entries.map(([name, env]) => {
1748
+ const isOAuthManaged = name === oauthTargetEnvVar;
1749
+ return (
1750
+ <div key={name} className="flex items-start gap-3 px-3 py-2">
1751
+ <code className="shrink-0 font-mono text-sm font-medium text-foreground">
1752
+ {name}
1753
+ </code>
1754
+ <span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
1755
+ {env.isSecret ? "secret" : "config"}
1331
1756
  </span>
1332
- )}
1333
- </div>
1334
- );
1335
- })}
1336
- </div>
1757
+ {isOAuthManaged && (
1758
+ <span className="shrink-0 rounded bg-primary-subtle px-1.5 py-0.5 text-[10px] font-medium text-primary">
1759
+ oauth
1760
+ </span>
1761
+ )}
1762
+ {env.optional && (
1763
+ <span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground-subtle">
1764
+ optional
1765
+ </span>
1766
+ )}
1767
+ {env.description && (
1768
+ <span className="text-xs text-muted-foreground">
1769
+ {env.description}
1770
+ </span>
1771
+ )}
1772
+ </div>
1773
+ );
1774
+ })}
1775
+ </div>
1776
+ )}
1337
1777
  </Section>
1338
1778
  );
1339
1779
  }
1340
1780
 
1341
- function TagsSection({ tags }: { readonly tags: readonly string[] }) {
1781
+ function TagsSection({
1782
+ tags,
1783
+ editable,
1784
+ isSaving,
1785
+ saveMcpField,
1786
+ }: {
1787
+ readonly tags: readonly string[];
1788
+ readonly editable?: boolean;
1789
+ readonly isSaving?: boolean;
1790
+ readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
1791
+ field: K,
1792
+ value: import("@stigmer/sdk").McpServerInput[K],
1793
+ ) => Promise<boolean>;
1794
+ }) {
1795
+ const tagRows: KeyValueRow[] = useMemo(
1796
+ () => tags.map((t) => ({ key: t, value: "" })),
1797
+ [tags],
1798
+ );
1799
+
1800
+ const handleTagsSave = useCallback(
1801
+ async (rows: KeyValueRow[]) => {
1802
+ if (!saveMcpField) return false;
1803
+ // Tags are stored as string[] on the spec but not directly on McpServerInput.
1804
+ // For now, save them through the full input by modifying the spec.
1805
+ // Tags don't have a direct field on McpServerInput, so we handle this at
1806
+ // a higher level if needed. For now, show read-only in edit mode.
1807
+ return false;
1808
+ },
1809
+ [saveMcpField],
1810
+ );
1811
+
1342
1812
  return (
1343
- <Section title={`Tags (${tags.length})`}>
1813
+ <Section title="Tags" count={tags.length}>
1344
1814
  <div className="flex flex-wrap gap-1.5 p-3">
1345
1815
  {tags.map((tag) => (
1346
1816
  <span
@@ -1350,6 +1820,9 @@ function TagsSection({ tags }: { readonly tags: readonly string[] }) {
1350
1820
  {tag}
1351
1821
  </span>
1352
1822
  ))}
1823
+ {editable && tags.length === 0 && (
1824
+ <p className="text-xs text-muted-foreground italic">No tags</p>
1825
+ )}
1353
1826
  </div>
1354
1827
  </Section>
1355
1828
  );
@@ -1364,6 +1837,19 @@ function ToolsTabContent({
1364
1837
  }: {
1365
1838
  readonly tools: readonly DiscoveredTool[];
1366
1839
  }) {
1840
+ const [search, setSearch] = useState("");
1841
+ const [expandedTool, setExpandedTool] = useState<string | null>(null);
1842
+
1843
+ const filtered = useMemo(() => {
1844
+ if (!search.trim()) return tools;
1845
+ const q = search.toLowerCase();
1846
+ return tools.filter(
1847
+ (t) =>
1848
+ t.name.toLowerCase().includes(q) ||
1849
+ t.description?.toLowerCase().includes(q),
1850
+ );
1851
+ }, [tools, search]);
1852
+
1367
1853
  if (tools.length === 0) {
1368
1854
  return (
1369
1855
  <div className="px-3 py-8 text-center">
@@ -1375,20 +1861,97 @@ function ToolsTabContent({
1375
1861
  );
1376
1862
  }
1377
1863
 
1864
+ const isFiltered = search.trim().length > 0;
1865
+
1378
1866
  return (
1379
- <div className="flex flex-col divide-y divide-border">
1380
- {tools.map((tool) => (
1381
- <div key={tool.name} className="px-3 py-2.5">
1382
- <code className="font-mono text-sm font-medium text-foreground">
1383
- {tool.name}
1384
- </code>
1385
- {tool.description && (
1386
- <p className="mt-0.5 text-xs text-muted-foreground">
1387
- {tool.description}
1388
- </p>
1867
+ <div className="flex flex-col">
1868
+ <div className="flex items-center gap-2 px-3 pb-2">
1869
+ <div className="relative flex-1">
1870
+ <SearchIcon className="pointer-events-none absolute left-2 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
1871
+ <input
1872
+ type="text"
1873
+ value={search}
1874
+ onChange={(e) => setSearch(e.target.value)}
1875
+ placeholder="Search tools…"
1876
+ aria-label="Search tools"
1877
+ className="w-full rounded-md border border-border bg-background py-1.5 pl-7 pr-7 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
1878
+ />
1879
+ {isFiltered && (
1880
+ <button
1881
+ type="button"
1882
+ onClick={() => setSearch("")}
1883
+ aria-label="Clear search"
1884
+ className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
1885
+ >
1886
+ <CloseIcon className="size-3" />
1887
+ </button>
1389
1888
  )}
1390
1889
  </div>
1391
- ))}
1890
+ <span className="shrink-0 text-[10px] text-muted-foreground">
1891
+ {isFiltered ? `${filtered.length} of ${tools.length}` : tools.length}
1892
+ </span>
1893
+ </div>
1894
+
1895
+ {filtered.length === 0 ? (
1896
+ <div className="px-3 py-6 text-center">
1897
+ <p className="text-xs text-muted-foreground">
1898
+ No tools matching &ldquo;{search}&rdquo;
1899
+ </p>
1900
+ </div>
1901
+ ) : (
1902
+ <div className="max-h-96 overflow-y-auto">
1903
+ <div className="flex flex-col divide-y divide-border">
1904
+ {filtered.map((tool) => {
1905
+ const isExpanded = expandedTool === tool.name;
1906
+ const hasSchema =
1907
+ tool.inputSchema != null &&
1908
+ Object.keys(tool.inputSchema).length > 0;
1909
+
1910
+ return (
1911
+ <div key={tool.name}>
1912
+ <button
1913
+ type="button"
1914
+ onClick={() =>
1915
+ setExpandedTool(isExpanded ? null : tool.name)
1916
+ }
1917
+ className="flex w-full items-start gap-2 px-3 py-2.5 text-left transition-colors hover:bg-muted-faint"
1918
+ aria-expanded={isExpanded}
1919
+ >
1920
+ <ChevronIcon
1921
+ className={cn(
1922
+ "mt-0.5 size-3 shrink-0 text-muted-foreground transition-transform",
1923
+ isExpanded && "rotate-90",
1924
+ )}
1925
+ />
1926
+ <div className="min-w-0 flex-1">
1927
+ <code className="font-mono text-sm font-medium text-foreground">
1928
+ {tool.name}
1929
+ </code>
1930
+ {tool.description && (
1931
+ <p className="mt-0.5 text-xs text-muted-foreground">
1932
+ {tool.description}
1933
+ </p>
1934
+ )}
1935
+ </div>
1936
+ {hasSchema && (
1937
+ <span className="mt-0.5 shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
1938
+ schema
1939
+ </span>
1940
+ )}
1941
+ </button>
1942
+ {isExpanded && hasSchema && (
1943
+ <div className="border-t border-border bg-muted-faint px-3 py-2">
1944
+ <pre className="max-h-64 overflow-auto whitespace-pre-wrap break-words rounded border border-border bg-background p-2 font-mono text-[11px] text-foreground">
1945
+ {JSON.stringify(tool.inputSchema, null, 2)}
1946
+ </pre>
1947
+ </div>
1948
+ )}
1949
+ </div>
1950
+ );
1951
+ })}
1952
+ </div>
1953
+ </div>
1954
+ )}
1392
1955
  </div>
1393
1956
  );
1394
1957
  }
@@ -1402,9 +1965,33 @@ function PoliciesTabContent({
1402
1965
  readonly classifiedPolicies: readonly ToolApprovalPolicy[];
1403
1966
  readonly hasDiscoveredTools: boolean;
1404
1967
  }) {
1405
- const hasPinnedPolicies = pinnedPolicies.length > 0;
1406
- const hasClassifiedPolicies = classifiedPolicies.length > 0;
1407
- const hasAnyPolicies = hasPinnedPolicies || hasClassifiedPolicies;
1968
+ const [search, setSearch] = useState("");
1969
+
1970
+ const totalCount = pinnedPolicies.length + classifiedPolicies.length;
1971
+ const hasAnyPolicies = totalCount > 0;
1972
+
1973
+ const filteredPinned = useMemo(() => {
1974
+ if (!search.trim()) return pinnedPolicies;
1975
+ const q = search.toLowerCase();
1976
+ return pinnedPolicies.filter(
1977
+ (p) =>
1978
+ p.toolName.toLowerCase().includes(q) ||
1979
+ p.message?.toLowerCase().includes(q),
1980
+ );
1981
+ }, [pinnedPolicies, search]);
1982
+
1983
+ const filteredClassified = useMemo(() => {
1984
+ if (!search.trim()) return classifiedPolicies;
1985
+ const q = search.toLowerCase();
1986
+ return classifiedPolicies.filter(
1987
+ (p) =>
1988
+ p.toolName.toLowerCase().includes(q) ||
1989
+ p.message?.toLowerCase().includes(q),
1990
+ );
1991
+ }, [classifiedPolicies, search]);
1992
+
1993
+ const filteredTotal = filteredPinned.length + filteredClassified.length;
1994
+ const isFiltered = search.trim().length > 0;
1408
1995
 
1409
1996
  if (!hasAnyPolicies) {
1410
1997
  return (
@@ -1421,19 +2008,56 @@ function PoliciesTabContent({
1421
2008
 
1422
2009
  return (
1423
2010
  <div className="flex flex-col">
1424
- {hasPinnedPolicies && (
1425
- <PolicyGroup
1426
- icon={<PinIcon className="size-3.5" />}
1427
- label="Pinned"
1428
- policies={pinnedPolicies}
1429
- />
1430
- )}
1431
- {hasClassifiedPolicies && (
1432
- <PolicyGroup
1433
- icon={<SparklesIcon className="size-3.5" />}
1434
- label="Auto-classified"
1435
- policies={classifiedPolicies}
1436
- />
2011
+ <div className="flex items-center gap-2 px-3 pb-2">
2012
+ <div className="relative flex-1">
2013
+ <SearchIcon className="pointer-events-none absolute left-2 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
2014
+ <input
2015
+ type="text"
2016
+ value={search}
2017
+ onChange={(e) => setSearch(e.target.value)}
2018
+ placeholder="Search policies…"
2019
+ aria-label="Search policies"
2020
+ className="w-full rounded-md border border-border bg-background py-1.5 pl-7 pr-7 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
2021
+ />
2022
+ {isFiltered && (
2023
+ <button
2024
+ type="button"
2025
+ onClick={() => setSearch("")}
2026
+ aria-label="Clear search"
2027
+ className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
2028
+ >
2029
+ <CloseIcon className="size-3" />
2030
+ </button>
2031
+ )}
2032
+ </div>
2033
+ <span className="shrink-0 text-[10px] text-muted-foreground">
2034
+ {isFiltered ? `${filteredTotal} of ${totalCount}` : totalCount}
2035
+ </span>
2036
+ </div>
2037
+
2038
+ {filteredTotal === 0 ? (
2039
+ <div className="px-3 py-6 text-center">
2040
+ <p className="text-xs text-muted-foreground">
2041
+ No policies matching &ldquo;{search}&rdquo;
2042
+ </p>
2043
+ </div>
2044
+ ) : (
2045
+ <div className="max-h-96 overflow-y-auto">
2046
+ {filteredPinned.length > 0 && (
2047
+ <PolicyGroup
2048
+ icon={<PinIcon className="size-3.5" />}
2049
+ label="Pinned"
2050
+ policies={filteredPinned}
2051
+ />
2052
+ )}
2053
+ {filteredClassified.length > 0 && (
2054
+ <PolicyGroup
2055
+ icon={<SparklesIcon className="size-3.5" />}
2056
+ label="Auto-classified"
2057
+ policies={filteredClassified}
2058
+ />
2059
+ )}
2060
+ </div>
1437
2061
  )}
1438
2062
  </div>
1439
2063
  );
@@ -1466,7 +2090,10 @@ function PolicyGroup({
1466
2090
  <code className="font-mono text-sm font-medium text-foreground">
1467
2091
  {policy.toolName}
1468
2092
  </code>
1469
- <ShieldIcon className="size-3 text-amber-500 dark:text-amber-400" />
2093
+ <span className="inline-flex items-center gap-1 rounded bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium text-amber-600 dark:text-amber-400">
2094
+ <ShieldIcon className="size-2.5" />
2095
+ requires approval
2096
+ </span>
1470
2097
  </div>
1471
2098
  {policy.message && (
1472
2099
  <p className="mt-0.5 text-xs text-muted-foreground">
@@ -1484,24 +2111,6 @@ function PolicyGroup({
1484
2111
  // Shared layout primitives
1485
2112
  // ---------------------------------------------------------------------------
1486
2113
 
1487
- function Section({
1488
- title,
1489
- children,
1490
- }: {
1491
- readonly title: string;
1492
- readonly children: React.ReactNode;
1493
- }) {
1494
- return (
1495
- <section>
1496
- <h3 className="mb-2 text-xs font-medium uppercase tracking-wider text-muted-foreground">
1497
- {title}
1498
- </h3>
1499
- <div className="overflow-hidden rounded-lg border border-border">
1500
- {children}
1501
- </div>
1502
- </section>
1503
- );
1504
- }
1505
2114
 
1506
2115
  function Dot() {
1507
2116
  return (
@@ -1768,6 +2377,58 @@ function ExternalLinkIcon({ className }: { readonly className?: string }) {
1768
2377
  );
1769
2378
  }
1770
2379
 
2380
+ function SearchIcon({ className }: { readonly className?: string }) {
2381
+ return (
2382
+ <svg
2383
+ className={className}
2384
+ viewBox="0 0 16 16"
2385
+ fill="none"
2386
+ stroke="currentColor"
2387
+ strokeWidth="1.5"
2388
+ strokeLinecap="round"
2389
+ strokeLinejoin="round"
2390
+ aria-hidden="true"
2391
+ >
2392
+ <circle cx="7" cy="7" r="4.5" />
2393
+ <path d="m10.5 10.5 3 3" />
2394
+ </svg>
2395
+ );
2396
+ }
2397
+
2398
+ function CloseIcon({ className }: { readonly className?: string }) {
2399
+ return (
2400
+ <svg
2401
+ className={className}
2402
+ viewBox="0 0 16 16"
2403
+ fill="none"
2404
+ stroke="currentColor"
2405
+ strokeWidth="2"
2406
+ strokeLinecap="round"
2407
+ strokeLinejoin="round"
2408
+ aria-hidden="true"
2409
+ >
2410
+ <path d="m4 4 8 8M12 4l-8 8" />
2411
+ </svg>
2412
+ );
2413
+ }
2414
+
2415
+ function ChevronIcon({ className }: { readonly className?: string }) {
2416
+ return (
2417
+ <svg
2418
+ className={className}
2419
+ viewBox="0 0 16 16"
2420
+ fill="none"
2421
+ stroke="currentColor"
2422
+ strokeWidth="2"
2423
+ strokeLinecap="round"
2424
+ strokeLinejoin="round"
2425
+ aria-hidden="true"
2426
+ >
2427
+ <path d="m6 4 4 4-4 4" />
2428
+ </svg>
2429
+ );
2430
+ }
2431
+
1771
2432
  function Spinner() {
1772
2433
  return (
1773
2434
  <svg