@stigmer/react 3.3.0 → 3.4.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 (344) hide show
  1. package/agent/useAgentCount.d.ts +2 -0
  2. package/agent/useAgentCount.d.ts.map +1 -1
  3. package/agent/useAgentCount.js.map +1 -1
  4. package/api-key/CreateApiKeyForm.d.ts +7 -1
  5. package/api-key/CreateApiKeyForm.d.ts.map +1 -1
  6. package/api-key/CreateApiKeyForm.js +2 -2
  7. package/api-key/CreateApiKeyForm.js.map +1 -1
  8. package/billing/index.d.ts +0 -18
  9. package/billing/index.d.ts.map +1 -1
  10. package/billing/index.js +4 -9
  11. package/billing/index.js.map +1 -1
  12. package/cursor-accounts/CursorAccountEditor.d.ts +7 -1
  13. package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -1
  14. package/cursor-accounts/CursorAccountEditor.js +21 -5
  15. package/cursor-accounts/CursorAccountEditor.js.map +1 -1
  16. package/cursor-accounts/CursorAccountsConsole.d.ts +9 -5
  17. package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -1
  18. package/cursor-accounts/CursorAccountsConsole.js +34 -140
  19. package/cursor-accounts/CursorAccountsConsole.js.map +1 -1
  20. package/cursor-accounts/MemberCoverageTable.d.ts +29 -0
  21. package/cursor-accounts/MemberCoverageTable.d.ts.map +1 -0
  22. package/cursor-accounts/MemberCoverageTable.js +150 -0
  23. package/cursor-accounts/MemberCoverageTable.js.map +1 -0
  24. package/cursor-accounts/MemberKeysPanel.d.ts +25 -0
  25. package/cursor-accounts/MemberKeysPanel.d.ts.map +1 -0
  26. package/cursor-accounts/MemberKeysPanel.js +115 -0
  27. package/cursor-accounts/MemberKeysPanel.js.map +1 -0
  28. package/cursor-accounts/badges.d.ts +9 -0
  29. package/cursor-accounts/badges.d.ts.map +1 -0
  30. package/cursor-accounts/badges.js +10 -0
  31. package/cursor-accounts/badges.js.map +1 -0
  32. package/cursor-accounts/cursor-account-coverage.d.ts +41 -0
  33. package/cursor-accounts/cursor-account-coverage.d.ts.map +1 -0
  34. package/cursor-accounts/cursor-account-coverage.js +26 -0
  35. package/cursor-accounts/cursor-account-coverage.js.map +1 -0
  36. package/cursor-accounts/cursor-account-format.d.ts +13 -0
  37. package/cursor-accounts/cursor-account-format.d.ts.map +1 -1
  38. package/cursor-accounts/cursor-account-format.js +16 -1
  39. package/cursor-accounts/cursor-account-format.js.map +1 -1
  40. package/datastore/CollectionRecordsBrowser.js +18 -4
  41. package/datastore/CollectionRecordsBrowser.js.map +1 -1
  42. package/datastore/RecordFilterBuilder.d.ts +8 -1
  43. package/datastore/RecordFilterBuilder.d.ts.map +1 -1
  44. package/datastore/RecordFilterBuilder.js +2 -2
  45. package/datastore/RecordFilterBuilder.js.map +1 -1
  46. package/datastore/recordFilter.d.ts +9 -1
  47. package/datastore/recordFilter.d.ts.map +1 -1
  48. package/datastore/recordFilter.js +12 -1
  49. package/datastore/recordFilter.js.map +1 -1
  50. package/datastore/useDatastoreCount.d.ts +2 -0
  51. package/datastore/useDatastoreCount.d.ts.map +1 -1
  52. package/datastore/useDatastoreCount.js.map +1 -1
  53. package/execution/ExecutionProgress.d.ts.map +1 -1
  54. package/execution/ExecutionProgress.js +13 -4
  55. package/execution/ExecutionProgress.js.map +1 -1
  56. package/execution/MessageThread.d.ts.map +1 -1
  57. package/execution/MessageThread.js +10 -2
  58. package/execution/MessageThread.js.map +1 -1
  59. package/execution/useCreateAgentExecution.d.ts +31 -1
  60. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  61. package/execution/useCreateAgentExecution.js +2 -0
  62. package/execution/useCreateAgentExecution.js.map +1 -1
  63. package/index.d.ts +8 -6
  64. package/index.d.ts.map +1 -1
  65. package/index.js +8 -4
  66. package/index.js.map +1 -1
  67. package/internal/form-primitives.d.ts +10 -0
  68. package/internal/form-primitives.d.ts.map +1 -0
  69. package/{billing → internal}/form-primitives.js +5 -9
  70. package/internal/form-primitives.js.map +1 -0
  71. package/manifest/ApplyManifestDialog.d.ts +10 -5
  72. package/manifest/ApplyManifestDialog.d.ts.map +1 -1
  73. package/manifest/ApplyManifestDialog.js +30 -13
  74. package/manifest/ApplyManifestDialog.js.map +1 -1
  75. package/manifest/useApplyManifest.d.ts +6 -2
  76. package/manifest/useApplyManifest.d.ts.map +1 -1
  77. package/manifest/useApplyManifest.js +5 -5
  78. package/manifest/useApplyManifest.js.map +1 -1
  79. package/mcp-server/McpServerDetailView.d.ts +38 -2
  80. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  81. package/mcp-server/McpServerDetailView.js +21 -5
  82. package/mcp-server/McpServerDetailView.js.map +1 -1
  83. package/mcp-server/index.d.ts +7 -0
  84. package/mcp-server/index.d.ts.map +1 -1
  85. package/mcp-server/index.js +9 -0
  86. package/mcp-server/index.js.map +1 -1
  87. package/mcp-server/steps/EnvironmentAuthStep.d.ts +4 -0
  88. package/mcp-server/steps/EnvironmentAuthStep.d.ts.map +1 -1
  89. package/mcp-server/steps/EnvironmentAuthStep.js +4 -0
  90. package/mcp-server/steps/EnvironmentAuthStep.js.map +1 -1
  91. package/mcp-server/steps/IdentityTransportStep.d.ts +6 -0
  92. package/mcp-server/steps/IdentityTransportStep.d.ts.map +1 -1
  93. package/mcp-server/steps/IdentityTransportStep.js +7 -1
  94. package/mcp-server/steps/IdentityTransportStep.js.map +1 -1
  95. package/mcp-server/steps/ReviewStep.d.ts +5 -0
  96. package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
  97. package/mcp-server/steps/ReviewStep.js +16 -2
  98. package/mcp-server/steps/ReviewStep.js.map +1 -1
  99. package/mcp-server/useMcpServerCount.d.ts +2 -0
  100. package/mcp-server/useMcpServerCount.d.ts.map +1 -1
  101. package/mcp-server/useMcpServerCount.js.map +1 -1
  102. package/package.json +4 -4
  103. package/pricing-governance/BaselineEditor.d.ts.map +1 -0
  104. package/{billing → pricing-governance}/BaselineEditor.js +19 -2
  105. package/pricing-governance/BaselineEditor.js.map +1 -0
  106. package/pricing-governance/ModelCatalogPanel.d.ts.map +1 -0
  107. package/pricing-governance/ModelCatalogPanel.js.map +1 -0
  108. package/pricing-governance/ModelGovernanceDetail.d.ts.map +1 -0
  109. package/pricing-governance/ModelGovernanceDetail.js.map +1 -0
  110. package/pricing-governance/OperatorAccessNotice.d.ts.map +1 -0
  111. package/pricing-governance/OperatorAccessNotice.js.map +1 -0
  112. package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -0
  113. package/{billing → pricing-governance}/PricingGovernanceConsole.js +1 -1
  114. package/pricing-governance/PricingGovernanceConsole.js.map +1 -0
  115. package/pricing-governance/PricingGovernancePanel.d.ts.map +1 -0
  116. package/pricing-governance/PricingGovernancePanel.js.map +1 -0
  117. package/pricing-governance/RetireConfirm.d.ts.map +1 -0
  118. package/{billing → pricing-governance}/RetireConfirm.js +1 -1
  119. package/pricing-governance/RetireConfirm.js.map +1 -0
  120. package/pricing-governance/governance-primitives.d.ts.map +1 -0
  121. package/pricing-governance/governance-primitives.js.map +1 -0
  122. package/pricing-governance/index.d.ts +19 -0
  123. package/pricing-governance/index.d.ts.map +1 -0
  124. package/pricing-governance/index.js +20 -0
  125. package/pricing-governance/index.js.map +1 -0
  126. package/pricing-governance/pricing-format.d.ts.map +1 -0
  127. package/pricing-governance/pricing-format.js.map +1 -0
  128. package/pricing-governance/useDecidePricingOverride.d.ts.map +1 -0
  129. package/pricing-governance/useDecidePricingOverride.js.map +1 -0
  130. package/pricing-governance/useModelGovernanceView.d.ts.map +1 -0
  131. package/pricing-governance/useModelGovernanceView.js.map +1 -0
  132. package/pricing-governance/useModelPricingBaselines.d.ts.map +1 -0
  133. package/pricing-governance/useModelPricingBaselines.js.map +1 -0
  134. package/pricing-governance/usePricingGovernance.d.ts.map +1 -0
  135. package/pricing-governance/usePricingGovernance.js.map +1 -0
  136. package/pricing-governance/useRetireModelPricingBaseline.d.ts.map +1 -0
  137. package/pricing-governance/useRetireModelPricingBaseline.js.map +1 -0
  138. package/pricing-governance/useUpsertModelPricingBaseline.d.ts.map +1 -0
  139. package/pricing-governance/useUpsertModelPricingBaseline.js.map +1 -0
  140. package/resource-creation/CreationPicker.d.ts.map +1 -1
  141. package/resource-creation/CreationPicker.js +3 -3
  142. package/resource-creation/CreationPicker.js.map +1 -1
  143. package/resource-creation/WizardNav.d.ts.map +1 -1
  144. package/resource-creation/WizardNav.js +1 -1
  145. package/resource-creation/WizardNav.js.map +1 -1
  146. package/resource-detail/Section.d.ts +8 -1
  147. package/resource-detail/Section.d.ts.map +1 -1
  148. package/resource-detail/Section.js +2 -2
  149. package/resource-detail/Section.js.map +1 -1
  150. package/resource-workbench/components/ResourceWorkbench.d.ts +9 -1
  151. package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -1
  152. package/resource-workbench/components/ResourceWorkbench.js +2 -1
  153. package/resource-workbench/components/ResourceWorkbench.js.map +1 -1
  154. package/resource-workbench/hooks/useResourceCollection.d.ts +9 -0
  155. package/resource-workbench/hooks/useResourceCollection.d.ts.map +1 -1
  156. package/resource-workbench/hooks/useResourceCollection.js +2 -2
  157. package/resource-workbench/hooks/useResourceCollection.js.map +1 -1
  158. package/search/useResourceCount.d.ts +7 -0
  159. package/search/useResourceCount.d.ts.map +1 -1
  160. package/search/useResourceCount.js +2 -1
  161. package/search/useResourceCount.js.map +1 -1
  162. package/session/NewSessionViewer.d.ts.map +1 -1
  163. package/session/NewSessionViewer.js +17 -3
  164. package/session/NewSessionViewer.js.map +1 -1
  165. package/session/SessionViewer.d.ts +2 -1
  166. package/session/SessionViewer.d.ts.map +1 -1
  167. package/session/SessionViewer.js +19 -11
  168. package/session/SessionViewer.js.map +1 -1
  169. package/session/SessionViewerLayout.d.ts +90 -0
  170. package/session/SessionViewerLayout.d.ts.map +1 -0
  171. package/session/SessionViewerLayout.js +32 -0
  172. package/session/SessionViewerLayout.js.map +1 -0
  173. package/session/index.d.ts +4 -0
  174. package/session/index.d.ts.map +1 -1
  175. package/session/index.js +10 -0
  176. package/session/index.js.map +1 -1
  177. package/session/useCreateSession.d.ts +28 -0
  178. package/session/useCreateSession.d.ts.map +1 -1
  179. package/session/useCreateSession.js +2 -1
  180. package/session/useCreateSession.js.map +1 -1
  181. package/session/useNewSessionFlow.d.ts +30 -0
  182. package/session/useNewSessionFlow.d.ts.map +1 -1
  183. package/session/useNewSessionFlow.js +7 -1
  184. package/session/useNewSessionFlow.js.map +1 -1
  185. package/session/useSessionRailViews.d.ts +2 -2
  186. package/session/useUpdateSession.d.ts +29 -10
  187. package/session/useUpdateSession.d.ts.map +1 -1
  188. package/session/useUpdateSession.js +29 -10
  189. package/session/useUpdateSession.js.map +1 -1
  190. package/skill/useSkillCount.d.ts +2 -0
  191. package/skill/useSkillCount.d.ts.map +1 -1
  192. package/skill/useSkillCount.js.map +1 -1
  193. package/src/agent/useAgentCount.ts +2 -0
  194. package/src/api-key/CreateApiKeyForm.tsx +8 -1
  195. package/src/api-key/__tests__/CreateApiKeyForm.test.tsx +58 -0
  196. package/src/billing/index.ts +5 -37
  197. package/src/cursor-accounts/CursorAccountEditor.tsx +61 -13
  198. package/src/cursor-accounts/CursorAccountsConsole.tsx +44 -400
  199. package/src/cursor-accounts/MemberCoverageTable.tsx +439 -0
  200. package/src/cursor-accounts/MemberKeysPanel.tsx +278 -0
  201. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +306 -10
  202. package/src/cursor-accounts/__tests__/cursor-account-coverage.test.ts +73 -0
  203. package/src/cursor-accounts/badges.tsx +26 -0
  204. package/src/cursor-accounts/cursor-account-coverage.ts +71 -0
  205. package/src/cursor-accounts/cursor-account-format.ts +17 -1
  206. package/src/datastore/CollectionRecordsBrowser.tsx +29 -3
  207. package/src/datastore/RecordFilterBuilder.tsx +12 -1
  208. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +38 -0
  209. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +14 -0
  210. package/src/datastore/__tests__/recordFilter.test.ts +13 -0
  211. package/src/datastore/recordFilter.ts +15 -1
  212. package/src/datastore/useDatastoreCount.ts +2 -0
  213. package/src/execution/ExecutionProgress.tsx +14 -4
  214. package/src/execution/MessageThread.tsx +10 -2
  215. package/src/execution/__tests__/ExecutionProgress.test.tsx +67 -0
  216. package/src/execution/__tests__/MessageThread.test.tsx +44 -0
  217. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +86 -0
  218. package/src/execution/useCreateAgentExecution.ts +41 -6
  219. package/src/index.ts +43 -24
  220. package/src/{billing → internal}/form-primitives.tsx +4 -32
  221. package/src/manifest/ApplyManifestDialog.tsx +40 -16
  222. package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +147 -0
  223. package/src/manifest/__tests__/useApplyManifest.test.tsx +6 -6
  224. package/src/manifest/useApplyManifest.ts +12 -8
  225. package/src/mcp-server/McpServerDetailView.tsx +52 -4
  226. package/src/mcp-server/__tests__/McpServerDetailView.test.tsx +345 -0
  227. package/src/mcp-server/index.ts +13 -0
  228. package/src/mcp-server/steps/EnvironmentAuthStep.tsx +4 -0
  229. package/src/mcp-server/steps/IdentityTransportStep.tsx +9 -1
  230. package/src/mcp-server/steps/ReviewStep.tsx +18 -1
  231. package/src/mcp-server/useMcpServerCount.ts +2 -0
  232. package/src/{billing → pricing-governance}/BaselineEditor.tsx +36 -3
  233. package/src/{billing → pricing-governance}/PricingGovernanceConsole.tsx +1 -1
  234. package/src/{billing → pricing-governance}/RetireConfirm.tsx +1 -1
  235. package/src/pricing-governance/index.ts +50 -0
  236. package/src/resource-creation/CreationPicker.tsx +7 -0
  237. package/src/resource-creation/WizardNav.tsx +1 -0
  238. package/src/resource-detail/Section.tsx +9 -1
  239. package/src/resource-workbench/components/ResourceWorkbench.tsx +13 -0
  240. package/src/resource-workbench/hooks/useResourceCollection.ts +11 -1
  241. package/src/search/useResourceCount.ts +9 -1
  242. package/src/session/NewSessionViewer.tsx +48 -61
  243. package/src/session/SessionViewer.tsx +71 -86
  244. package/src/session/SessionViewerLayout.tsx +131 -0
  245. package/src/session/__tests__/SessionViewerLayout.test.tsx +140 -0
  246. package/src/session/__tests__/useCreateSession.test.tsx +94 -0
  247. package/src/session/__tests__/useNewSessionFlow.test.tsx +33 -0
  248. package/src/session/index.ts +14 -0
  249. package/src/session/useCreateSession.ts +30 -0
  250. package/src/session/useNewSessionFlow.ts +45 -1
  251. package/src/session/useSessionRailViews.tsx +2 -2
  252. package/src/session/useUpdateSession.ts +29 -10
  253. package/src/skill/useSkillCount.ts +2 -0
  254. package/src/test/__tests__/samples.test.ts +159 -2
  255. package/src/test/index.ts +1 -1
  256. package/src/test/samples.ts +109 -14
  257. package/src/workflow/useWorkflowCount.ts +2 -0
  258. package/styles.css +1 -1
  259. package/test/index.d.ts +1 -1
  260. package/test/index.d.ts.map +1 -1
  261. package/test/index.js +1 -1
  262. package/test/index.js.map +1 -1
  263. package/test/samples.d.ts +79 -7
  264. package/test/samples.d.ts.map +1 -1
  265. package/test/samples.js +101 -14
  266. package/test/samples.js.map +1 -1
  267. package/workflow/useWorkflowCount.d.ts +2 -0
  268. package/workflow/useWorkflowCount.d.ts.map +1 -1
  269. package/workflow/useWorkflowCount.js.map +1 -1
  270. package/billing/BaselineEditor.d.ts.map +0 -1
  271. package/billing/BaselineEditor.js.map +0 -1
  272. package/billing/ModelCatalogPanel.d.ts.map +0 -1
  273. package/billing/ModelCatalogPanel.js.map +0 -1
  274. package/billing/ModelGovernanceDetail.d.ts.map +0 -1
  275. package/billing/ModelGovernanceDetail.js.map +0 -1
  276. package/billing/OperatorAccessNotice.d.ts.map +0 -1
  277. package/billing/OperatorAccessNotice.js.map +0 -1
  278. package/billing/PricingGovernanceConsole.d.ts.map +0 -1
  279. package/billing/PricingGovernanceConsole.js.map +0 -1
  280. package/billing/PricingGovernancePanel.d.ts.map +0 -1
  281. package/billing/PricingGovernancePanel.js.map +0 -1
  282. package/billing/RetireConfirm.d.ts.map +0 -1
  283. package/billing/RetireConfirm.js.map +0 -1
  284. package/billing/form-primitives.d.ts +0 -18
  285. package/billing/form-primitives.d.ts.map +0 -1
  286. package/billing/form-primitives.js.map +0 -1
  287. package/billing/governance-primitives.d.ts.map +0 -1
  288. package/billing/governance-primitives.js.map +0 -1
  289. package/billing/pricing-format.d.ts.map +0 -1
  290. package/billing/pricing-format.js.map +0 -1
  291. package/billing/useDecidePricingOverride.d.ts.map +0 -1
  292. package/billing/useDecidePricingOverride.js.map +0 -1
  293. package/billing/useModelGovernanceView.d.ts.map +0 -1
  294. package/billing/useModelGovernanceView.js.map +0 -1
  295. package/billing/useModelPricingBaselines.d.ts.map +0 -1
  296. package/billing/useModelPricingBaselines.js.map +0 -1
  297. package/billing/usePricingGovernance.d.ts.map +0 -1
  298. package/billing/usePricingGovernance.js.map +0 -1
  299. package/billing/useRetireModelPricingBaseline.d.ts.map +0 -1
  300. package/billing/useRetireModelPricingBaseline.js.map +0 -1
  301. package/billing/useUpsertModelPricingBaseline.d.ts.map +0 -1
  302. package/billing/useUpsertModelPricingBaseline.js.map +0 -1
  303. /package/{billing → pricing-governance}/BaselineEditor.d.ts +0 -0
  304. /package/{billing → pricing-governance}/ModelCatalogPanel.d.ts +0 -0
  305. /package/{billing → pricing-governance}/ModelCatalogPanel.js +0 -0
  306. /package/{billing → pricing-governance}/ModelGovernanceDetail.d.ts +0 -0
  307. /package/{billing → pricing-governance}/ModelGovernanceDetail.js +0 -0
  308. /package/{billing → pricing-governance}/OperatorAccessNotice.d.ts +0 -0
  309. /package/{billing → pricing-governance}/OperatorAccessNotice.js +0 -0
  310. /package/{billing → pricing-governance}/PricingGovernanceConsole.d.ts +0 -0
  311. /package/{billing → pricing-governance}/PricingGovernancePanel.d.ts +0 -0
  312. /package/{billing → pricing-governance}/PricingGovernancePanel.js +0 -0
  313. /package/{billing → pricing-governance}/RetireConfirm.d.ts +0 -0
  314. /package/{billing → pricing-governance}/governance-primitives.d.ts +0 -0
  315. /package/{billing → pricing-governance}/governance-primitives.js +0 -0
  316. /package/{billing → pricing-governance}/pricing-format.d.ts +0 -0
  317. /package/{billing → pricing-governance}/pricing-format.js +0 -0
  318. /package/{billing → pricing-governance}/useDecidePricingOverride.d.ts +0 -0
  319. /package/{billing → pricing-governance}/useDecidePricingOverride.js +0 -0
  320. /package/{billing → pricing-governance}/useModelGovernanceView.d.ts +0 -0
  321. /package/{billing → pricing-governance}/useModelGovernanceView.js +0 -0
  322. /package/{billing → pricing-governance}/useModelPricingBaselines.d.ts +0 -0
  323. /package/{billing → pricing-governance}/useModelPricingBaselines.js +0 -0
  324. /package/{billing → pricing-governance}/usePricingGovernance.d.ts +0 -0
  325. /package/{billing → pricing-governance}/usePricingGovernance.js +0 -0
  326. /package/{billing → pricing-governance}/useRetireModelPricingBaseline.d.ts +0 -0
  327. /package/{billing → pricing-governance}/useRetireModelPricingBaseline.js +0 -0
  328. /package/{billing → pricing-governance}/useUpsertModelPricingBaseline.d.ts +0 -0
  329. /package/{billing → pricing-governance}/useUpsertModelPricingBaseline.js +0 -0
  330. /package/src/{billing → pricing-governance}/ModelCatalogPanel.tsx +0 -0
  331. /package/src/{billing → pricing-governance}/ModelGovernanceDetail.tsx +0 -0
  332. /package/src/{billing → pricing-governance}/OperatorAccessNotice.tsx +0 -0
  333. /package/src/{billing → pricing-governance}/PricingGovernancePanel.tsx +0 -0
  334. /package/src/{billing → pricing-governance}/__tests__/ModelCatalogPanel.test.tsx +0 -0
  335. /package/src/{billing → pricing-governance}/__tests__/PricingGovernanceConsole.test.tsx +0 -0
  336. /package/src/{billing → pricing-governance}/__tests__/useModelGovernanceView.test.tsx +0 -0
  337. /package/src/{billing → pricing-governance}/governance-primitives.tsx +0 -0
  338. /package/src/{billing → pricing-governance}/pricing-format.ts +0 -0
  339. /package/src/{billing → pricing-governance}/useDecidePricingOverride.ts +0 -0
  340. /package/src/{billing → pricing-governance}/useModelGovernanceView.ts +0 -0
  341. /package/src/{billing → pricing-governance}/useModelPricingBaselines.ts +0 -0
  342. /package/src/{billing → pricing-governance}/usePricingGovernance.ts +0 -0
  343. /package/src/{billing → pricing-governance}/useRetireModelPricingBaseline.ts +0 -0
  344. /package/src/{billing → pricing-governance}/useUpsertModelPricingBaseline.ts +0 -0
@@ -55,9 +55,13 @@ export interface UseApplyManifestReturn {
55
55
  /**
56
56
  * Apply all documents sequentially in dependency order. Entries update
57
57
  * live. Stops at the first failure (later entries become `"skipped"`).
58
- * Resolves `true` when every document applied.
58
+ * Resolves to the final per-document entries with terminal statuses —
59
+ * the caller derives full success (`every applied`) and the applied
60
+ * subset (for a list refresh) without re-reading React state, which is
61
+ * still stale in the calling closure. Empty when there was nothing to
62
+ * apply.
59
63
  */
60
- readonly applyAll: () => Promise<boolean>;
64
+ readonly applyAll: () => Promise<readonly ManifestPreviewEntry[]>;
61
65
  /** `true` while applies are in flight. */
62
66
  readonly isApplying: boolean;
63
67
  /** Clear all state (content, preview, errors). */
@@ -194,8 +198,8 @@ export function useApplyManifest(org: string): UseApplyManifestReturn {
194
198
  return () => clearTimeout(timer);
195
199
  }, [content, stigmer, isApplying]);
196
200
 
197
- const applyAll = useCallback(async (): Promise<boolean> => {
198
- if (!entries || entries.length === 0) return false;
201
+ const applyAll = useCallback(async (): Promise<readonly ManifestPreviewEntry[]> => {
202
+ if (!entries || entries.length === 0) return [];
199
203
 
200
204
  // Invalidate any in-flight validation so it cannot clobber apply statuses.
201
205
  validateSeq.current++;
@@ -206,10 +210,10 @@ export function useApplyManifest(org: string): UseApplyManifestReturn {
206
210
  const working = entries.map((entry): ManifestPreviewEntry => ({ ...entry, status: "pending" }));
207
211
  const commit = () => setEntries([...working]);
208
212
 
209
- let allApplied = true;
213
+ let stopped = false;
210
214
 
211
215
  for (let i = 0; i < working.length; i++) {
212
- if (!allApplied) {
216
+ if (stopped) {
213
217
  working[i] = { ...working[i], status: "skipped" };
214
218
  continue;
215
219
  }
@@ -226,14 +230,14 @@ export function useApplyManifest(org: string): UseApplyManifestReturn {
226
230
  status: "failed",
227
231
  errorMessage: toError(err).message,
228
232
  };
229
- allApplied = false;
233
+ stopped = true;
230
234
  }
231
235
  commit();
232
236
  }
233
237
 
234
238
  commit();
235
239
  setIsApplying(false);
236
- return allApplied;
240
+ return working;
237
241
  }, [entries, stigmer]);
238
242
 
239
243
  const hasRedactedSecrets = useMemo(
@@ -14,6 +14,7 @@ import type { ToolApprovalPolicy, McpServerSpec } from "@stigmer/protos/ai/stigm
14
14
  import { ValidationState } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
15
15
  import type { EnvVarDeclaration } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
16
16
  import { useMcpServer } from "./useMcpServer.js";
17
+ import type { UseMcpServerReturn } from "./useMcpServer.js";
17
18
  import { useUpdateMcpServer } from "./useUpdateMcpServer.js";
18
19
  import { mcpServerToInput } from "./internal/mcpServerToInput.js";
19
20
  import { useMcpServerConnect } from "./useMcpServerConnect.js";
@@ -51,6 +52,31 @@ export interface McpServerDetailViewProps {
51
52
  readonly org: string;
52
53
  /** MCP server slug (URL-friendly identifier unique within the org). */
53
54
  readonly slug: string;
55
+ /**
56
+ * Hoisted resource state from {@link useMcpServer}, for callers that
57
+ * already own the fetch. When provided, the view issues **no**
58
+ * `getByReference` RPC of its own and renders entirely from this state —
59
+ * loading, error, and not-found included, so a caller mid-fetch still
60
+ * gets the loading skeleton rather than a false not-found.
61
+ *
62
+ * Ownership contract: supplying this state means supplying its
63
+ * lifecycle. The view calls `mcpServerState.refetch()` after connect,
64
+ * disconnect, and inline edits, so the `refetch` you pass must refresh
65
+ * the data behind `mcpServer` or the view will render stale state after
66
+ * those actions.
67
+ *
68
+ * Two callers this serves:
69
+ * - A page that already fetched the server (e.g. for export/YAML
70
+ * actions) passes `useMcpServer(org, slug)` straight through instead
71
+ * of paying a duplicate RPC.
72
+ * - A guided tour or demo supplies frozen state
73
+ * (`{ mcpServer, isLoading: false, isRefetching: false, error: null,
74
+ * refetch: noop }`) so every depicted beat renders deterministically
75
+ * from data the tour owns (scenar-cloud DD-006).
76
+ *
77
+ * When omitted, the view fetches by `org`/`slug` itself, as before.
78
+ */
79
+ readonly mcpServerState?: UseMcpServerReturn;
54
80
  /**
55
81
  * Called once when the MCP server resource has been fetched successfully.
56
82
  * Provides the resource display name for use cases like breadcrumbs,
@@ -115,7 +141,8 @@ export interface McpServerDetailViewProps {
115
141
  /**
116
142
  * Detail view for an MCP Server integration.
117
143
  *
118
- * Fetches the server via {@link useMcpServer} internally and renders
144
+ * Fetches the server via {@link useMcpServer} internally or renders
145
+ * from hoisted state when the caller passes `mcpServerState` — and shows
119
146
  * its full configuration: validation banner (if invalid), header,
120
147
  * a **Connect bar** with a single Connect/Reconnect action, and a
121
148
  * **tabbed capabilities panel** (Tools, Policies, and optionally
@@ -135,10 +162,20 @@ export interface McpServerDetailViewProps {
135
162
  * // Minimal — self-contained, fetches its own data
136
163
  * <McpServerDetailView org="acme" slug="github" />
137
164
  * ```
165
+ *
166
+ * @example
167
+ * ```tsx
168
+ * // Hoisted — the page already fetched the server (e.g. for YAML
169
+ * // export actions), so pass that state through instead of paying a
170
+ * // second getByReference RPC.
171
+ * const state = useMcpServer(org, slug);
172
+ * <McpServerDetailView org={org} slug={slug} mcpServerState={state} />
173
+ * ```
138
174
  */
139
175
  export function McpServerDetailView({
140
176
  org,
141
177
  slug,
178
+ mcpServerState,
142
179
  onResourceLoad,
143
180
  defaultCapabilityTab = "tools",
144
181
  defaultShowCredentialForm = false,
@@ -150,7 +187,16 @@ export function McpServerDetailView({
150
187
  onResourceUpdated,
151
188
  className,
152
189
  }: McpServerDetailViewProps) {
153
- const { mcpServer, isLoading, error, refetch } = useMcpServer(org, slug);
190
+ // Hoisted-state mode: when the caller supplies `mcpServerState`, disable
191
+ // the internal fetch via the hook's documented null-skip (a stable no-op,
192
+ // so `fetched` reports isLoading=false with no RPC) and render from the
193
+ // caller's state instead — all four states (loading/error/not-found/data)
194
+ // transfer intact.
195
+ const fetched = useMcpServer(
196
+ mcpServerState ? null : org,
197
+ mcpServerState ? null : slug,
198
+ );
199
+ const { mcpServer, isLoading, error, refetch } = mcpServerState ?? fetched;
154
200
  const { update: updateMcpServer, isUpdating } = useUpdateMcpServer();
155
201
 
156
202
  const saveMcpField = useCallback(
@@ -493,7 +539,9 @@ export function McpServerDetailView({
493
539
  />
494
540
  )}
495
541
 
496
- <Section title="Connection">
542
+ {/* scrollTarget: guided tours/demos bring the connect flow into view
543
+ (see IdentityTransportStep's "mcp-transport" for the convention). */}
544
+ <Section title="Connection" scrollTarget="mcp-connection">
497
545
  <StdioSandboxNotice serverType={spec?.serverType} className="mb-3" />
498
546
  <OAuthRequiredNotice oauthOnly={spec?.auth?.oauthOnly} className="mb-3" />
499
547
  <ConnectBar
@@ -582,7 +630,7 @@ export function McpServerDetailView({
582
630
  />
583
631
  </dialog>
584
632
 
585
- <Section title="Capabilities">
633
+ <Section title="Capabilities" scrollTarget="mcp-capabilities">
586
634
  <Tabs
587
635
  tabs={capabilityTabs}
588
636
  activeTab={capabilityTab}
@@ -0,0 +1,345 @@
1
+ import { describe, it, expect, vi, beforeAll, afterEach } from "vitest";
2
+ import { render, screen, cleanup, fireEvent, within } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import { timestampFromDate } from "@bufbuild/protobuf/wkt";
6
+ import { createRouterTransport, ConnectError, Code } from "@connectrpc/connect";
7
+ import { Stigmer } from "@stigmer/sdk";
8
+ import { McpServerQueryController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/query_pb";
9
+ import {
10
+ McpServerSpecSchema,
11
+ HttpServerConfigSchema,
12
+ ToolApprovalPolicySchema,
13
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
14
+ import {
15
+ McpServerStatusSchema,
16
+ DiscoveredCapabilitiesSchema,
17
+ DiscoveredToolSchema,
18
+ ValidationState,
19
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
20
+ import { EnvVarDeclarationSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
21
+ import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
22
+ import { samples } from "../../test/samples";
23
+ import { StigmerContext } from "../../context";
24
+ import { McpServerDetailView } from "../McpServerDetailView";
25
+ import type { UseMcpServerReturn } from "../useMcpServer";
26
+
27
+ // The kebab menu and dialogs portal their content; without a StigmerProvider
28
+ // the portal container is null — pin it to document.body like sibling tests.
29
+ vi.mock("../../portal-container", () => ({
30
+ useStigmerPortalContainer: () => document.body,
31
+ }));
32
+
33
+ beforeAll(() => {
34
+ // happy-dom lacks ResizeObserver, which Base UI positioners observe.
35
+ if (!("ResizeObserver" in globalThis)) {
36
+ (globalThis as unknown as { ResizeObserver: unknown }).ResizeObserver =
37
+ class {
38
+ observe() {}
39
+ unobserve() {}
40
+ disconnect() {}
41
+ };
42
+ }
43
+ });
44
+
45
+ afterEach(cleanup);
46
+
47
+ const ORG = "acme";
48
+ const SLUG = "order-management-api";
49
+
50
+ /** Frozen discovery instant — fixtures must never read the real clock. */
51
+ const DISCOVERED_AT = new Date("2026-07-20T09:30:00Z");
52
+
53
+ /** The server as registered: HTTP transport, one secret env var, no tools. */
54
+ function buildBaseServer(): McpServer {
55
+ const server = samples.mcpServer({ name: "Order Management API", org: ORG, slug: SLUG });
56
+ server.spec = create(McpServerSpecSchema, {
57
+ description: "REST API for order lookup, inventory, and return processing.",
58
+ serverType: {
59
+ case: "http",
60
+ value: create(HttpServerConfigSchema, { url: "https://api.acme.com/mcp" }),
61
+ },
62
+ env: {
63
+ API_TOKEN: create(EnvVarDeclarationSchema, {
64
+ isSecret: true,
65
+ description: "Bearer token for the Order Management API",
66
+ }),
67
+ },
68
+ });
69
+ return server;
70
+ }
71
+
72
+ /** The same server after Connect: 3 discovered tools, 1 classified policy. */
73
+ function buildConnectedServer(): McpServer {
74
+ const server = buildBaseServer();
75
+ server.status = create(McpServerStatusSchema, {
76
+ validationState: ValidationState.valid,
77
+ discoveredCapabilities: create(DiscoveredCapabilitiesSchema, {
78
+ lastDiscoveredAt: timestampFromDate(DISCOVERED_AT),
79
+ tools: [
80
+ create(DiscoveredToolSchema, { name: "get_order", description: "Retrieve one order by ID." }),
81
+ create(DiscoveredToolSchema, { name: "list_orders", description: "List recent orders." }),
82
+ create(DiscoveredToolSchema, { name: "process_return", description: "Initiate a return and refund." }),
83
+ ],
84
+ }),
85
+ toolApprovals: [
86
+ create(ToolApprovalPolicySchema, {
87
+ toolName: "process_return",
88
+ message: "Process return for order '{{args.order_id}}'",
89
+ }),
90
+ ],
91
+ });
92
+ return server;
93
+ }
94
+
95
+ /** Hoisted-state bag in its settled, data-loaded shape. */
96
+ function loadedState(server: McpServer): UseMcpServerReturn {
97
+ return { mcpServer: server, isLoading: false, isRefetching: false, error: null, refetch: vi.fn() };
98
+ }
99
+
100
+ /**
101
+ * Mounts the view against a real Connect router transport. RPCs the test
102
+ * does not register fall through to Connect's `unimplemented`, which the
103
+ * SDK hooks degrade from — the same contract the tours rely on.
104
+ */
105
+ function renderView(
106
+ ui: ReactNode,
107
+ register: Parameters<typeof createRouterTransport>[0] = () => {},
108
+ ) {
109
+ const client = new Stigmer({
110
+ baseUrl: "/",
111
+ getAccessToken: () => "test-token",
112
+ customTransport: createRouterTransport(register),
113
+ });
114
+ return render(
115
+ <StigmerContext.Provider value={client}>{ui}</StigmerContext.Provider>,
116
+ );
117
+ }
118
+
119
+ describe("McpServerDetailView — hoisted mcpServerState", () => {
120
+ it("renders from injected state without issuing getByReference", async () => {
121
+ const getByReference = vi.fn(() => {
122
+ throw new ConnectError("must not fetch", Code.FailedPrecondition);
123
+ });
124
+
125
+ renderView(
126
+ <McpServerDetailView
127
+ org={ORG}
128
+ slug={SLUG}
129
+ mcpServerState={loadedState(buildBaseServer())}
130
+ />,
131
+ (router) => {
132
+ router.service(McpServerQueryController, { getByReference });
133
+ },
134
+ );
135
+
136
+ // Content is on screen synchronously — no skeleton frame first.
137
+ expect(
138
+ screen.getByRole("heading", { name: "Order Management API" }),
139
+ ).toBeTruthy();
140
+ expect(screen.queryByLabelText("Loading MCP server details")).toBeNull();
141
+
142
+ // Let pending microtasks (credentials/permission fetches) settle, then
143
+ // confirm the resource fetch never fired.
144
+ await screen.findByRole("tab", { name: /Tools/ });
145
+ expect(getByReference).not.toHaveBeenCalled();
146
+ });
147
+
148
+ it("shows the loading skeleton while the injected state is loading", () => {
149
+ renderView(
150
+ <McpServerDetailView
151
+ org={ORG}
152
+ slug={SLUG}
153
+ mcpServerState={{
154
+ mcpServer: null,
155
+ isLoading: true,
156
+ isRefetching: false,
157
+ error: null,
158
+ refetch: vi.fn(),
159
+ }}
160
+ />,
161
+ );
162
+ expect(screen.getByLabelText("Loading MCP server details")).toBeTruthy();
163
+ // A loading owner must never read as a missing resource.
164
+ expect(screen.queryByText("MCP Server not found")).toBeNull();
165
+ });
166
+
167
+ it("routes the error state's Retry to the injected refetch", () => {
168
+ const refetch = vi.fn();
169
+ renderView(
170
+ <McpServerDetailView
171
+ org={ORG}
172
+ slug={SLUG}
173
+ mcpServerState={{
174
+ mcpServer: null,
175
+ isLoading: false,
176
+ isRefetching: false,
177
+ error: new ConnectError("backend down", Code.Unavailable),
178
+ refetch,
179
+ }}
180
+ />,
181
+ );
182
+
183
+ fireEvent.click(screen.getByRole("button", { name: /retry/i }));
184
+ expect(refetch).toHaveBeenCalledTimes(1);
185
+ });
186
+
187
+ it("renders not-found when the injected state settles with no resource", () => {
188
+ renderView(
189
+ <McpServerDetailView
190
+ org={ORG}
191
+ slug={SLUG}
192
+ mcpServerState={{
193
+ mcpServer: null,
194
+ isLoading: false,
195
+ isRefetching: false,
196
+ error: null,
197
+ refetch: vi.fn(),
198
+ }}
199
+ />,
200
+ );
201
+ expect(screen.getByText("MCP Server not found")).toBeTruthy();
202
+ });
203
+ });
204
+
205
+ describe("McpServerDetailView — self-fetching mode (unchanged behaviour)", () => {
206
+ it("fetches by org/slug and renders the resolved server", async () => {
207
+ const getByReference = vi.fn(() => buildBaseServer());
208
+ renderView(<McpServerDetailView org={ORG} slug={SLUG} />, (router) => {
209
+ router.service(McpServerQueryController, { getByReference });
210
+ });
211
+
212
+ // First paint is the skeleton; content follows the fetch.
213
+ expect(screen.getByLabelText("Loading MCP server details")).toBeTruthy();
214
+ expect(
215
+ await screen.findByRole("heading", { name: "Order Management API" }),
216
+ ).toBeTruthy();
217
+ expect(getByReference).toHaveBeenCalledTimes(1);
218
+ });
219
+
220
+ it("renders not-found when the fetch 404s", async () => {
221
+ renderView(<McpServerDetailView org={ORG} slug={SLUG} />, (router) => {
222
+ router.service(McpServerQueryController, {
223
+ getByReference: () => {
224
+ throw new ConnectError("no such server", Code.NotFound);
225
+ },
226
+ });
227
+ });
228
+ expect(await screen.findByText("MCP Server not found")).toBeTruthy();
229
+ });
230
+ });
231
+
232
+ describe("McpServerDetailView — connect bar and capability tabs", () => {
233
+ it("offers Connect with the not-connected status before discovery", () => {
234
+ renderView(
235
+ <McpServerDetailView
236
+ org={ORG}
237
+ slug={SLUG}
238
+ mcpServerState={loadedState(buildBaseServer())}
239
+ />,
240
+ );
241
+ expect(screen.getByRole("button", { name: /^Connect$/ })).toBeTruthy();
242
+ expect(screen.getByText("Not connected yet")).toBeTruthy();
243
+ expect(
244
+ screen.getByText("Connect to this MCP server to discover its available tools."),
245
+ ).toBeTruthy();
246
+ });
247
+
248
+ it("offers Reconnect with the connected status and discovery date after discovery", () => {
249
+ renderView(
250
+ <McpServerDetailView
251
+ org={ORG}
252
+ slug={SLUG}
253
+ mcpServerState={loadedState(buildConnectedServer())}
254
+ />,
255
+ );
256
+ expect(screen.getByRole("button", { name: /Reconnect/ })).toBeTruthy();
257
+ expect(screen.getByText("Connected")).toBeTruthy();
258
+ expect(screen.getByText("Valid")).toBeTruthy();
259
+ expect(screen.getByText(/Discovered/)).toBeTruthy();
260
+ });
261
+
262
+ it("lists the discovered tools with the count badge", () => {
263
+ renderView(
264
+ <McpServerDetailView
265
+ org={ORG}
266
+ slug={SLUG}
267
+ mcpServerState={loadedState(buildConnectedServer())}
268
+ />,
269
+ );
270
+ const toolsTab = screen.getByRole("tab", { name: /Tools/ });
271
+ expect(toolsTab.textContent).toContain("3");
272
+ expect(screen.getByText("get_order")).toBeTruthy();
273
+ expect(screen.getByText("list_orders")).toBeTruthy();
274
+ expect(screen.getByText("process_return")).toBeTruthy();
275
+ });
276
+
277
+ it("groups the classified policy under Auto-classified with a badge of 1, not 3", () => {
278
+ renderView(
279
+ <McpServerDetailView
280
+ org={ORG}
281
+ slug={SLUG}
282
+ defaultCapabilityTab="policies"
283
+ mcpServerState={loadedState(buildConnectedServer())}
284
+ />,
285
+ );
286
+ const policiesTab = screen.getByRole("tab", { name: /Policies/ });
287
+ expect(policiesTab.textContent).toContain("1");
288
+ expect(policiesTab.textContent).not.toContain("3");
289
+
290
+ const panel = screen.getByRole("tabpanel");
291
+ expect(within(panel).getByText(/Auto-classified/)).toBeTruthy();
292
+ expect(within(panel).getByText("process_return")).toBeTruthy();
293
+ expect(within(panel).getByText("requires approval")).toBeTruthy();
294
+ });
295
+ });
296
+
297
+ describe("McpServerDetailView — tour scroll anchors", () => {
298
+ it("marks the Connection and Capabilities sections as scroll targets", () => {
299
+ const { container } = renderView(
300
+ <McpServerDetailView
301
+ org={ORG}
302
+ slug={SLUG}
303
+ mcpServerState={loadedState(buildBaseServer())}
304
+ />,
305
+ );
306
+ expect(
307
+ container.querySelector('[data-scroll-target="mcp-connection"]'),
308
+ ).toBeTruthy();
309
+ expect(
310
+ container.querySelector('[data-scroll-target="mcp-capabilities"]'),
311
+ ).toBeTruthy();
312
+ });
313
+ });
314
+
315
+ describe("McpServerDetailView — credential form gating", () => {
316
+ it("opens the credential form for the declared missing variable when asked", async () => {
317
+ renderView(
318
+ <McpServerDetailView
319
+ org={ORG}
320
+ slug={SLUG}
321
+ defaultShowCredentialForm
322
+ mcpServerState={loadedState(buildBaseServer())}
323
+ />,
324
+ );
325
+ expect(await screen.findByText("Credentials Required")).toBeTruthy();
326
+ // Scope to the credential form — the Environment section also lists
327
+ // API_TOKEN as a declaration.
328
+ const form = screen.getByRole("form", {
329
+ name: /Configure Credentials Required/i,
330
+ });
331
+ // Anchored: the secret input's reveal button is labelled "Show API_TOKEN".
332
+ expect(within(form).getByLabelText(/^API_TOKEN/)).toBeTruthy();
333
+ });
334
+
335
+ it("keeps the form closed by default", () => {
336
+ renderView(
337
+ <McpServerDetailView
338
+ org={ORG}
339
+ slug={SLUG}
340
+ mcpServerState={loadedState(buildBaseServer())}
341
+ />,
342
+ );
343
+ expect(screen.queryByText("Credentials Required")).toBeNull();
344
+ });
345
+ });
@@ -100,4 +100,17 @@ export type {
100
100
  McpServerCreationResult,
101
101
  } from "./McpServerCreationWizard.js";
102
102
 
103
+ // Individual wizard steps are exported as presentational building blocks:
104
+ // they are fully prop-driven (data, validationError, error, isCreating),
105
+ // which lets platform builders and guided tours/demos render any wizard
106
+ // state — including validation and submit failures — deterministically,
107
+ // without driving the stateful McpServerCreationWizard through user events.
108
+ export { IdentityTransportStep } from "./steps/IdentityTransportStep.js";
109
+ export type { IdentityTransportStepProps } from "./steps/IdentityTransportStep.js";
110
+ export { EnvironmentAuthStep } from "./steps/EnvironmentAuthStep.js";
111
+ export type { EnvironmentAuthStepProps } from "./steps/EnvironmentAuthStep.js";
112
+ export { ReviewStep } from "./steps/ReviewStep.js";
113
+ export type { ReviewStepProps } from "./steps/ReviewStep.js";
114
+
115
+ export { createInitialMcpServerWizardData } from "./steps/types.js";
103
116
  export type { McpServerWizardData } from "./steps/types.js";
@@ -16,6 +16,10 @@ export interface EnvironmentAuthStepProps {
16
16
  * Both sections are optional. Env vars start expanded if any exist;
17
17
  * auth starts collapsed unless already enabled. No validation gate —
18
18
  * the user can proceed with zero configuration.
19
+ *
20
+ * Fully presentational: form state lives in the `data` prop and edits
21
+ * flow out through `updateData`, so standalone consumers (embedded
22
+ * builders, guided tours) can render any configuration state from props.
19
23
  */
20
24
  export function EnvironmentAuthStep({
21
25
  data,
@@ -23,6 +23,12 @@ const SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
23
23
  *
24
24
  * Transport type uses a radio group (mutually exclusive modes).
25
25
  * Conditional fields render based on the selected transport.
26
+ *
27
+ * Fully presentational: state lives in the `data` prop and every edit
28
+ * flows out through `updateData`. Inside `McpServerCreationWizard` that
29
+ * state comes from `useWizardState`; standalone consumers (embedded
30
+ * builders, guided tours) can render any form state — including a
31
+ * `validationError` — deterministically from props.
26
32
  */
27
33
  export function IdentityTransportStep({
28
34
  data,
@@ -195,7 +201,9 @@ export function IdentityTransportStep({
195
201
  </fieldset>
196
202
  </div>
197
203
 
198
- <fieldset className="space-y-3">
204
+ {/* data-scroll-target: guided tours/demos scroll the transport config
205
+ (the step's decision point) into view within the wizard's scroll area. */}
206
+ <fieldset className="space-y-3" data-scroll-target="mcp-transport">
199
207
  <legend className="text-sm font-medium text-foreground">
200
208
  Transport <span className="text-destructive">*</span>
201
209
  </legend>
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useMemo } from "react";
3
+ import { useEffect, useMemo, useRef } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
5
  import { buildMcpServerProto, getUserMessage, serializeManifest } from "@stigmer/sdk";
6
6
  import type { McpServerInput } from "@stigmer/sdk";
@@ -20,6 +20,11 @@ export interface ReviewStepProps {
20
20
  * Shows a summary card with key configuration details and a full
21
21
  * YAML preview of the MCP server that will be created. The "Create"
22
22
  * action is in the WizardNav footer, not in this component.
23
+ *
24
+ * Fully presentational: renders entirely from props, including the
25
+ * `isCreating` in-flight state and a submit `error`. Standalone
26
+ * consumers (embedded builders, guided tours) can therefore depict
27
+ * any review state — success preview or failure — deterministically.
23
28
  */
24
29
  export function ReviewStep({
25
30
  org,
@@ -27,6 +32,17 @@ export function ReviewStep({
27
32
  isCreating,
28
33
  error,
29
34
  }: ReviewStepProps) {
35
+ const errorRef = useRef<HTMLDivElement>(null);
36
+
37
+ // The error panel renders below the (tall) YAML preview inside the wizard's
38
+ // internal scroll area, so a failed create could otherwise report itself
39
+ // out of view. Bring it into view whenever a new error arrives.
40
+ useEffect(() => {
41
+ if (error) {
42
+ errorRef.current?.scrollIntoView({ block: "nearest" });
43
+ }
44
+ }, [error]);
45
+
30
46
  const mcpServerInput = useMemo(
31
47
  () => buildMcpServerInput(org, data),
32
48
  [org, data],
@@ -113,6 +129,7 @@ export function ReviewStep({
113
129
  {/* Error display */}
114
130
  {error && (
115
131
  <div
132
+ ref={errorRef}
116
133
  className="rounded-md border border-destructive bg-muted-faint px-4 py-3"
117
134
  role="alert"
118
135
  >
@@ -17,6 +17,8 @@ export interface UseMcpServerCountOptions {
17
17
  * @default "org"
18
18
  */
19
19
  readonly scope?: ResourceListScope;
20
+ /** Opaque token that forces a recount when its value changes. */
21
+ readonly refetchToken?: unknown;
20
22
  }
21
23
 
22
24
  /** Return value of {@link useMcpServerCount}. */
@@ -10,7 +10,7 @@ import {
10
10
  type ModelPricingBaseline,
11
11
  } from "@stigmer/protos/ai/stigmer/billing/v1/model_pricing_baseline_pb";
12
12
  import { Button } from "../button/index.js";
13
- import { Field, INPUT_CLASSES, RateField } from "./form-primitives.js";
13
+ import { Field, INPUT_CLASSES } from "../internal/form-primitives.js";
14
14
  import {
15
15
  ZERO,
16
16
  dollarsToMicros,
@@ -23,10 +23,43 @@ import {
23
23
  // explicit old→new rate confirmation step (a billing-critical edit is never
24
24
  // submitted without the operator seeing exactly which rates move).
25
25
  //
26
- // Internal to the billing module: rendered by PricingGovernanceConsole and
27
- // ModelCatalogPanel, never exported from the barrel.
26
+ // Internal to the pricing-governance module: rendered by
27
+ // PricingGovernanceConsole and ModelCatalogPanel, never exported from the
28
+ // barrel.
28
29
  // ---------------------------------------------------------------------------
29
30
 
31
+ /**
32
+ * Dollar-rate input field (decimal keypad, "$ per million tokens").
33
+ * File-local: this is the editor's own composition of the shared form
34
+ * primitives, used nowhere else.
35
+ */
36
+ function RateField({
37
+ label,
38
+ value,
39
+ placeholder,
40
+ disabled,
41
+ onChange,
42
+ }: {
43
+ readonly label: string;
44
+ readonly value: string;
45
+ readonly placeholder?: string;
46
+ readonly disabled: boolean;
47
+ readonly onChange: (value: string) => void;
48
+ }) {
49
+ return (
50
+ <Field label={label}>
51
+ <input
52
+ className={INPUT_CLASSES}
53
+ inputMode="decimal"
54
+ value={value}
55
+ onChange={(e) => onChange(e.target.value)}
56
+ placeholder={placeholder ?? "0.00"}
57
+ disabled={disabled}
58
+ />
59
+ </Field>
60
+ );
61
+ }
62
+
30
63
  // ---------------------------------------------------------------------------
31
64
  // Form model — strings while editing, converted + validated on submit.
32
65
  // Validation mirrors the protovalidate rules on ModelPricingBaseline so