@stigmer/react 3.2.2 → 3.3.0

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 (513) hide show
  1. package/agent/AgentDetailView.d.ts.map +1 -1
  2. package/agent/AgentDetailView.js +6 -3
  3. package/agent/AgentDetailView.js.map +1 -1
  4. package/agent/steps/ReviewStep.d.ts.map +1 -1
  5. package/agent/steps/ReviewStep.js +2 -3
  6. package/agent/steps/ReviewStep.js.map +1 -1
  7. package/billing/BaselineEditor.d.ts +9 -0
  8. package/billing/BaselineEditor.d.ts.map +1 -0
  9. package/billing/BaselineEditor.js +253 -0
  10. package/billing/BaselineEditor.js.map +1 -0
  11. package/billing/ModelCatalogPanel.d.ts +28 -0
  12. package/billing/ModelCatalogPanel.d.ts.map +1 -0
  13. package/billing/ModelCatalogPanel.js +102 -0
  14. package/billing/ModelCatalogPanel.js.map +1 -0
  15. package/billing/ModelGovernanceDetail.d.ts +8 -0
  16. package/billing/ModelGovernanceDetail.d.ts.map +1 -0
  17. package/billing/ModelGovernanceDetail.js +64 -0
  18. package/billing/ModelGovernanceDetail.js.map +1 -0
  19. package/billing/OperatorAccessNotice.d.ts +12 -0
  20. package/billing/OperatorAccessNotice.d.ts.map +1 -0
  21. package/billing/OperatorAccessNotice.js +15 -0
  22. package/billing/OperatorAccessNotice.js.map +1 -0
  23. package/billing/PricingGovernanceConsole.d.ts +57 -0
  24. package/billing/PricingGovernanceConsole.d.ts.map +1 -0
  25. package/billing/PricingGovernanceConsole.js +164 -0
  26. package/billing/PricingGovernanceConsole.js.map +1 -0
  27. package/billing/PricingGovernancePanel.d.ts +26 -0
  28. package/billing/PricingGovernancePanel.d.ts.map +1 -0
  29. package/billing/PricingGovernancePanel.js +64 -0
  30. package/billing/PricingGovernancePanel.js.map +1 -0
  31. package/billing/RetireConfirm.d.ts +9 -0
  32. package/billing/RetireConfirm.d.ts.map +1 -0
  33. package/billing/RetireConfirm.js +19 -0
  34. package/billing/RetireConfirm.js.map +1 -0
  35. package/billing/form-primitives.d.ts +18 -0
  36. package/billing/form-primitives.d.ts.map +1 -0
  37. package/billing/form-primitives.js +19 -0
  38. package/billing/form-primitives.js.map +1 -0
  39. package/billing/governance-primitives.d.ts +33 -0
  40. package/billing/governance-primitives.d.ts.map +1 -0
  41. package/billing/governance-primitives.js +43 -0
  42. package/billing/governance-primitives.js.map +1 -0
  43. package/billing/index.d.ts +18 -0
  44. package/billing/index.d.ts.map +1 -1
  45. package/billing/index.js +9 -0
  46. package/billing/index.js.map +1 -1
  47. package/billing/pricing-format.d.ts +12 -0
  48. package/billing/pricing-format.d.ts.map +1 -0
  49. package/billing/pricing-format.js +50 -0
  50. package/billing/pricing-format.js.map +1 -0
  51. package/billing/useDecidePricingOverride.d.ts +46 -0
  52. package/billing/useDecidePricingOverride.d.ts.map +1 -0
  53. package/billing/useDecidePricingOverride.js +44 -0
  54. package/billing/useDecidePricingOverride.js.map +1 -0
  55. package/billing/useModelGovernanceView.d.ts +103 -0
  56. package/billing/useModelGovernanceView.d.ts.map +1 -0
  57. package/billing/useModelGovernanceView.js +144 -0
  58. package/billing/useModelGovernanceView.js.map +1 -0
  59. package/billing/useModelPricingBaselines.d.ts +40 -0
  60. package/billing/useModelPricingBaselines.d.ts.map +1 -0
  61. package/billing/useModelPricingBaselines.js +32 -0
  62. package/billing/useModelPricingBaselines.js.map +1 -0
  63. package/billing/usePricingGovernance.d.ts +39 -0
  64. package/billing/usePricingGovernance.d.ts.map +1 -0
  65. package/billing/usePricingGovernance.js +31 -0
  66. package/billing/usePricingGovernance.js.map +1 -0
  67. package/billing/useRetireModelPricingBaseline.d.ts +31 -0
  68. package/billing/useRetireModelPricingBaseline.d.ts.map +1 -0
  69. package/billing/useRetireModelPricingBaseline.js +36 -0
  70. package/billing/useRetireModelPricingBaseline.js.map +1 -0
  71. package/billing/useUpsertModelPricingBaseline.d.ts +38 -0
  72. package/billing/useUpsertModelPricingBaseline.d.ts.map +1 -0
  73. package/billing/useUpsertModelPricingBaseline.js +37 -0
  74. package/billing/useUpsertModelPricingBaseline.js.map +1 -0
  75. package/channel/AgentChannelsPanel.d.ts.map +1 -1
  76. package/channel/AgentChannelsPanel.js +11 -5
  77. package/channel/AgentChannelsPanel.js.map +1 -1
  78. package/composer/SessionComposer.d.ts +1 -1
  79. package/cursor-accounts/CursorAccountEditor.d.ts +28 -0
  80. package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -0
  81. package/cursor-accounts/CursorAccountEditor.js +51 -0
  82. package/cursor-accounts/CursorAccountEditor.js.map +1 -0
  83. package/cursor-accounts/CursorAccountsAccessNotice.d.ts +11 -0
  84. package/cursor-accounts/CursorAccountsAccessNotice.d.ts.map +1 -0
  85. package/cursor-accounts/CursorAccountsAccessNotice.js +14 -0
  86. package/cursor-accounts/CursorAccountsAccessNotice.js.map +1 -0
  87. package/cursor-accounts/CursorAccountsConsole.d.ts +28 -0
  88. package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -0
  89. package/cursor-accounts/CursorAccountsConsole.js +275 -0
  90. package/cursor-accounts/CursorAccountsConsole.js.map +1 -0
  91. package/cursor-accounts/cursor-account-format.d.ts +10 -0
  92. package/cursor-accounts/cursor-account-format.d.ts.map +1 -0
  93. package/cursor-accounts/cursor-account-format.js +26 -0
  94. package/cursor-accounts/cursor-account-format.js.map +1 -0
  95. package/cursor-accounts/index.d.ts +18 -0
  96. package/cursor-accounts/index.d.ts.map +1 -0
  97. package/cursor-accounts/index.js +13 -0
  98. package/cursor-accounts/index.js.map +1 -0
  99. package/cursor-accounts/useCursorAccountView.d.ts +30 -0
  100. package/cursor-accounts/useCursorAccountView.d.ts.map +1 -0
  101. package/cursor-accounts/useCursorAccountView.js +25 -0
  102. package/cursor-accounts/useCursorAccountView.js.map +1 -0
  103. package/cursor-accounts/useCursorAccounts.d.ts +33 -0
  104. package/cursor-accounts/useCursorAccounts.d.ts.map +1 -0
  105. package/cursor-accounts/useCursorAccounts.js +25 -0
  106. package/cursor-accounts/useCursorAccounts.js.map +1 -0
  107. package/cursor-accounts/useCursorMemberKeyActions.d.ts +49 -0
  108. package/cursor-accounts/useCursorMemberKeyActions.d.ts.map +1 -0
  109. package/cursor-accounts/useCursorMemberKeyActions.js +38 -0
  110. package/cursor-accounts/useCursorMemberKeyActions.js.map +1 -0
  111. package/cursor-accounts/useDeleteCursorAccount.d.ts +30 -0
  112. package/cursor-accounts/useDeleteCursorAccount.d.ts.map +1 -0
  113. package/cursor-accounts/useDeleteCursorAccount.js +32 -0
  114. package/cursor-accounts/useDeleteCursorAccount.js.map +1 -0
  115. package/cursor-accounts/useSyncCursorAccount.d.ts +23 -0
  116. package/cursor-accounts/useSyncCursorAccount.d.ts.map +1 -0
  117. package/cursor-accounts/useSyncCursorAccount.js +31 -0
  118. package/cursor-accounts/useSyncCursorAccount.js.map +1 -0
  119. package/cursor-accounts/useUpsertCursorAccount.d.ts +26 -0
  120. package/cursor-accounts/useUpsertCursorAccount.d.ts.map +1 -0
  121. package/cursor-accounts/useUpsertCursorAccount.js +34 -0
  122. package/cursor-accounts/useUpsertCursorAccount.js.map +1 -0
  123. package/datastore/CollectionRecordsBrowser.d.ts +34 -0
  124. package/datastore/CollectionRecordsBrowser.d.ts.map +1 -0
  125. package/datastore/CollectionRecordsBrowser.js +209 -0
  126. package/datastore/CollectionRecordsBrowser.js.map +1 -0
  127. package/datastore/CollectionSchemaView.d.ts +29 -0
  128. package/datastore/CollectionSchemaView.d.ts.map +1 -0
  129. package/datastore/CollectionSchemaView.js +93 -0
  130. package/datastore/CollectionSchemaView.js.map +1 -0
  131. package/datastore/DatastoreDetailView.d.ts +44 -0
  132. package/datastore/DatastoreDetailView.d.ts.map +1 -0
  133. package/datastore/DatastoreDetailView.js +76 -0
  134. package/datastore/DatastoreDetailView.js.map +1 -0
  135. package/datastore/DatastoreSyncReport.d.ts +19 -0
  136. package/datastore/DatastoreSyncReport.d.ts.map +1 -0
  137. package/datastore/DatastoreSyncReport.js +45 -0
  138. package/datastore/DatastoreSyncReport.js.map +1 -0
  139. package/datastore/DeleteDatastoreDialog.d.ts +35 -0
  140. package/datastore/DeleteDatastoreDialog.d.ts.map +1 -0
  141. package/datastore/DeleteDatastoreDialog.js +90 -0
  142. package/datastore/DeleteDatastoreDialog.js.map +1 -0
  143. package/datastore/FieldValueControl.d.ts +55 -0
  144. package/datastore/FieldValueControl.d.ts.map +1 -0
  145. package/datastore/FieldValueControl.js +138 -0
  146. package/datastore/FieldValueControl.js.map +1 -0
  147. package/datastore/RecordFilterBuilder.d.ts +30 -0
  148. package/datastore/RecordFilterBuilder.d.ts.map +1 -0
  149. package/datastore/RecordFilterBuilder.js +122 -0
  150. package/datastore/RecordFilterBuilder.js.map +1 -0
  151. package/datastore/RecordFormPanel.d.ts +45 -0
  152. package/datastore/RecordFormPanel.d.ts.map +1 -0
  153. package/datastore/RecordFormPanel.js +215 -0
  154. package/datastore/RecordFormPanel.js.map +1 -0
  155. package/datastore/index.d.ts +43 -0
  156. package/datastore/index.d.ts.map +1 -0
  157. package/datastore/index.js +22 -0
  158. package/datastore/index.js.map +1 -0
  159. package/datastore/recordFilter.d.ts +54 -0
  160. package/datastore/recordFilter.d.ts.map +1 -0
  161. package/datastore/recordFilter.js +93 -0
  162. package/datastore/recordFilter.js.map +1 -0
  163. package/datastore/recordValues.d.ts +85 -0
  164. package/datastore/recordValues.d.ts.map +1 -0
  165. package/datastore/recordValues.js +282 -0
  166. package/datastore/recordValues.js.map +1 -0
  167. package/datastore/useDatastore.d.ts +39 -0
  168. package/datastore/useDatastore.d.ts.map +1 -0
  169. package/datastore/useDatastore.js +44 -0
  170. package/datastore/useDatastore.js.map +1 -0
  171. package/datastore/useDatastoreCount.d.ts +48 -0
  172. package/datastore/useDatastoreCount.d.ts.map +1 -0
  173. package/datastore/useDatastoreCount.js +27 -0
  174. package/datastore/useDatastoreCount.js.map +1 -0
  175. package/datastore/useDatastoreDescription.d.ts +54 -0
  176. package/datastore/useDatastoreDescription.d.ts.map +1 -0
  177. package/datastore/useDatastoreDescription.js +50 -0
  178. package/datastore/useDatastoreDescription.js.map +1 -0
  179. package/datastore/useDatastoreList.d.ts +57 -0
  180. package/datastore/useDatastoreList.d.ts.map +1 -0
  181. package/datastore/useDatastoreList.js +29 -0
  182. package/datastore/useDatastoreList.js.map +1 -0
  183. package/datastore/useDatastoreSearch.d.ts +19 -0
  184. package/datastore/useDatastoreSearch.d.ts.map +1 -0
  185. package/datastore/useDatastoreSearch.js +22 -0
  186. package/datastore/useDatastoreSearch.js.map +1 -0
  187. package/datastore/useDeleteDatastore.d.ts +53 -0
  188. package/datastore/useDeleteDatastore.d.ts.map +1 -0
  189. package/datastore/useDeleteDatastore.js +40 -0
  190. package/datastore/useDeleteDatastore.js.map +1 -0
  191. package/datastore/useDeleteRecord.d.ts +34 -0
  192. package/datastore/useDeleteRecord.d.ts.map +1 -0
  193. package/datastore/useDeleteRecord.js +43 -0
  194. package/datastore/useDeleteRecord.js.map +1 -0
  195. package/datastore/useInsertRecord.d.ts +50 -0
  196. package/datastore/useInsertRecord.d.ts.map +1 -0
  197. package/datastore/useInsertRecord.js +55 -0
  198. package/datastore/useInsertRecord.js.map +1 -0
  199. package/datastore/useRecordCollection.d.ts +104 -0
  200. package/datastore/useRecordCollection.d.ts.map +1 -0
  201. package/datastore/useRecordCollection.js +136 -0
  202. package/datastore/useRecordCollection.js.map +1 -0
  203. package/datastore/useRecordList.d.ts +66 -0
  204. package/datastore/useRecordList.d.ts.map +1 -0
  205. package/datastore/useRecordList.js +58 -0
  206. package/datastore/useRecordList.js.map +1 -0
  207. package/datastore/useUpdateRecord.d.ts +52 -0
  208. package/datastore/useUpdateRecord.d.ts.map +1 -0
  209. package/datastore/useUpdateRecord.js +55 -0
  210. package/datastore/useUpdateRecord.js.map +1 -0
  211. package/environment/EnvironmentListPanel.d.ts.map +1 -1
  212. package/environment/EnvironmentListPanel.js +12 -7
  213. package/environment/EnvironmentListPanel.js.map +1 -1
  214. package/execution/index.d.ts +1 -2
  215. package/execution/index.d.ts.map +1 -1
  216. package/execution/index.js +0 -1
  217. package/execution/index.js.map +1 -1
  218. package/execution/useLiveAgentExecution.d.ts +17 -1
  219. package/execution/useLiveAgentExecution.d.ts.map +1 -1
  220. package/execution/useLiveAgentExecution.js +19 -4
  221. package/execution/useLiveAgentExecution.js.map +1 -1
  222. package/iam-policy/index.d.ts +1 -1
  223. package/iam-policy/index.d.ts.map +1 -1
  224. package/iam-policy/index.js.map +1 -1
  225. package/iam-policy/useCheckPermission.d.ts +32 -11
  226. package/iam-policy/useCheckPermission.d.ts.map +1 -1
  227. package/iam-policy/useCheckPermission.js +24 -19
  228. package/iam-policy/useCheckPermission.js.map +1 -1
  229. package/index.d.ts +16 -10
  230. package/index.d.ts.map +1 -1
  231. package/index.js +16 -5
  232. package/index.js.map +1 -1
  233. package/internal/useInViewport.d.ts +24 -0
  234. package/internal/useInViewport.d.ts.map +1 -0
  235. package/internal/useInViewport.js +49 -0
  236. package/internal/useInViewport.js.map +1 -0
  237. package/library/VisibilitySelector.d.ts +22 -6
  238. package/library/VisibilitySelector.d.ts.map +1 -1
  239. package/library/VisibilitySelector.js +12 -4
  240. package/library/VisibilitySelector.js.map +1 -1
  241. package/library/index.d.ts +1 -8
  242. package/library/index.d.ts.map +1 -1
  243. package/library/index.js +0 -4
  244. package/library/index.js.map +1 -1
  245. package/library/useApplyResource.d.ts +12 -12
  246. package/library/useApplyResource.d.ts.map +1 -1
  247. package/library/useApplyResource.js +16 -25
  248. package/library/useApplyResource.js.map +1 -1
  249. package/library/useExportResource.d.ts +13 -9
  250. package/library/useExportResource.d.ts.map +1 -1
  251. package/library/useExportResource.js +18 -36
  252. package/library/useExportResource.js.map +1 -1
  253. package/manifest/ApplyManifestDialog.d.ts +48 -0
  254. package/manifest/ApplyManifestDialog.d.ts.map +1 -0
  255. package/manifest/ApplyManifestDialog.js +135 -0
  256. package/manifest/ApplyManifestDialog.js.map +1 -0
  257. package/manifest/EditResourceYamlDialog.d.ts +51 -0
  258. package/manifest/EditResourceYamlDialog.d.ts.map +1 -0
  259. package/manifest/EditResourceYamlDialog.js +104 -0
  260. package/manifest/EditResourceYamlDialog.js.map +1 -0
  261. package/manifest/RedactedSecretsNotice.d.ts +14 -0
  262. package/manifest/RedactedSecretsNotice.d.ts.map +1 -0
  263. package/manifest/RedactedSecretsNotice.js +14 -0
  264. package/manifest/RedactedSecretsNotice.js.map +1 -0
  265. package/manifest/YamlEditor.d.ts +44 -0
  266. package/manifest/YamlEditor.d.ts.map +1 -0
  267. package/manifest/YamlEditor.js +216 -0
  268. package/manifest/YamlEditor.js.map +1 -0
  269. package/manifest/index.d.ts +13 -0
  270. package/manifest/index.d.ts.map +1 -0
  271. package/manifest/index.js +13 -0
  272. package/manifest/index.js.map +1 -0
  273. package/manifest/useApplyManifest.d.ts +82 -0
  274. package/manifest/useApplyManifest.d.ts.map +1 -0
  275. package/manifest/useApplyManifest.js +180 -0
  276. package/manifest/useApplyManifest.js.map +1 -0
  277. package/manifest/useEditResourceYaml.d.ts +106 -0
  278. package/manifest/useEditResourceYaml.d.ts.map +1 -0
  279. package/manifest/useEditResourceYaml.js +168 -0
  280. package/manifest/useEditResourceYaml.js.map +1 -0
  281. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  282. package/mcp-server/McpServerDetailView.js +4 -3
  283. package/mcp-server/McpServerDetailView.js.map +1 -1
  284. package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
  285. package/mcp-server/steps/ReviewStep.js +2 -3
  286. package/mcp-server/steps/ReviewStep.js.map +1 -1
  287. package/package.json +4 -4
  288. package/resource-creation/templates/workflow-templates.js +4 -4
  289. package/session/SessionViewer.js +8 -1
  290. package/session/SessionViewer.js.map +1 -1
  291. package/session/audience.d.ts +6 -1
  292. package/session/audience.d.ts.map +1 -1
  293. package/session/useEditSessionPrep.js +3 -3
  294. package/session/useEditSessionPrep.js.map +1 -1
  295. package/settings/index.d.ts +2 -1
  296. package/settings/index.d.ts.map +1 -1
  297. package/settings/index.js +2 -1
  298. package/settings/index.js.map +1 -1
  299. package/settings/settings-nav.d.ts +22 -0
  300. package/settings/settings-nav.d.ts.map +1 -1
  301. package/settings/settings-nav.js +32 -1
  302. package/settings/settings-nav.js.map +1 -1
  303. package/settings/useSettingsNavGroups.d.ts +29 -0
  304. package/settings/useSettingsNavGroups.d.ts.map +1 -0
  305. package/settings/useSettingsNavGroups.js +61 -0
  306. package/settings/useSettingsNavGroups.js.map +1 -0
  307. package/skill/SkillDetailView.d.ts.map +1 -1
  308. package/skill/SkillDetailView.js +4 -3
  309. package/skill/SkillDetailView.js.map +1 -1
  310. package/src/access/__tests__/useManageAccess.test.tsx +104 -0
  311. package/src/agent/AgentDetailView.tsx +9 -3
  312. package/src/agent/steps/ReviewStep.tsx +2 -3
  313. package/src/billing/BaselineEditor.tsx +619 -0
  314. package/src/billing/ModelCatalogPanel.tsx +283 -0
  315. package/src/billing/ModelGovernanceDetail.tsx +289 -0
  316. package/src/billing/OperatorAccessNotice.tsx +32 -0
  317. package/src/billing/PricingGovernanceConsole.tsx +465 -0
  318. package/src/billing/PricingGovernancePanel.tsx +166 -0
  319. package/src/billing/RetireConfirm.tsx +82 -0
  320. package/src/billing/__tests__/ModelCatalogPanel.test.tsx +253 -0
  321. package/src/billing/__tests__/PricingGovernanceConsole.test.tsx +410 -0
  322. package/src/billing/__tests__/useModelGovernanceView.test.tsx +308 -0
  323. package/src/billing/form-primitives.tsx +68 -0
  324. package/src/billing/governance-primitives.tsx +133 -0
  325. package/src/billing/index.ts +37 -0
  326. package/src/billing/pricing-format.ts +53 -0
  327. package/src/billing/useDecidePricingOverride.ts +78 -0
  328. package/src/billing/useModelGovernanceView.ts +290 -0
  329. package/src/billing/useModelPricingBaselines.ts +69 -0
  330. package/src/billing/usePricingGovernance.ts +57 -0
  331. package/src/billing/useRetireModelPricingBaseline.ts +65 -0
  332. package/src/billing/useUpsertModelPricingBaseline.ts +72 -0
  333. package/src/channel/AgentChannelsPanel.tsx +27 -1
  334. package/src/composer/SessionComposer.tsx +1 -1
  335. package/src/cursor-accounts/CursorAccountEditor.tsx +181 -0
  336. package/src/cursor-accounts/CursorAccountsAccessNotice.tsx +36 -0
  337. package/src/cursor-accounts/CursorAccountsConsole.tsx +810 -0
  338. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +384 -0
  339. package/src/cursor-accounts/cursor-account-format.ts +29 -0
  340. package/src/cursor-accounts/index.ts +29 -0
  341. package/src/cursor-accounts/useCursorAccountView.ts +49 -0
  342. package/src/cursor-accounts/useCursorAccounts.ts +49 -0
  343. package/src/cursor-accounts/useCursorMemberKeyActions.ts +106 -0
  344. package/src/cursor-accounts/useDeleteCursorAccount.ts +62 -0
  345. package/src/cursor-accounts/useSyncCursorAccount.ts +54 -0
  346. package/src/cursor-accounts/useUpsertCursorAccount.ts +57 -0
  347. package/src/datastore/CollectionRecordsBrowser.tsx +544 -0
  348. package/src/datastore/CollectionSchemaView.tsx +247 -0
  349. package/src/datastore/DatastoreDetailView.tsx +201 -0
  350. package/src/datastore/DatastoreSyncReport.tsx +105 -0
  351. package/src/datastore/DeleteDatastoreDialog.tsx +202 -0
  352. package/src/datastore/FieldValueControl.tsx +289 -0
  353. package/src/datastore/RecordFilterBuilder.tsx +411 -0
  354. package/src/datastore/RecordFormPanel.tsx +432 -0
  355. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +207 -0
  356. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +133 -0
  357. package/src/datastore/__tests__/FieldValueControl.test.tsx +160 -0
  358. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +141 -0
  359. package/src/datastore/__tests__/RecordFormPanel.test.tsx +227 -0
  360. package/src/datastore/__tests__/recordFilter.test.ts +156 -0
  361. package/src/datastore/__tests__/recordMutations.test.tsx +195 -0
  362. package/src/datastore/__tests__/recordValues.test.ts +359 -0
  363. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +142 -0
  364. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +143 -0
  365. package/src/datastore/__tests__/useRecordCollection.test.tsx +250 -0
  366. package/src/datastore/__tests__/useRecordList.test.tsx +85 -0
  367. package/src/datastore/index.ts +111 -0
  368. package/src/datastore/recordFilter.ts +140 -0
  369. package/src/datastore/recordValues.ts +327 -0
  370. package/src/datastore/useDatastore.ts +67 -0
  371. package/src/datastore/useDatastoreCount.ts +67 -0
  372. package/src/datastore/useDatastoreDescription.ts +90 -0
  373. package/src/datastore/useDatastoreList.ts +79 -0
  374. package/src/datastore/useDatastoreSearch.ts +39 -0
  375. package/src/datastore/useDeleteDatastore.ts +87 -0
  376. package/src/datastore/useDeleteRecord.ts +77 -0
  377. package/src/datastore/useInsertRecord.ts +92 -0
  378. package/src/datastore/useRecordCollection.ts +256 -0
  379. package/src/datastore/useRecordList.ts +131 -0
  380. package/src/datastore/useUpdateRecord.ts +95 -0
  381. package/src/environment/EnvironmentListPanel.tsx +24 -0
  382. package/src/execution/__tests__/useArtifactInspection.test.tsx +12 -2
  383. package/src/execution/__tests__/useLiveAgentExecution.test.tsx +125 -0
  384. package/src/execution/index.ts +4 -7
  385. package/src/execution/useLiveAgentExecution.ts +41 -3
  386. package/src/iam-policy/__tests__/useCheckPermission.test.tsx +221 -0
  387. package/src/iam-policy/index.ts +1 -0
  388. package/src/iam-policy/useCheckPermission.ts +45 -19
  389. package/src/index.ts +167 -18
  390. package/src/internal/__tests__/useInViewport.test.tsx +115 -0
  391. package/src/internal/useInViewport.ts +63 -0
  392. package/src/library/VisibilitySelector.tsx +50 -9
  393. package/src/library/__tests__/VisibilitySelector.test.tsx +38 -0
  394. package/src/library/index.ts +4 -21
  395. package/src/library/useApplyResource.ts +27 -34
  396. package/src/library/useExportResource.ts +21 -40
  397. package/src/manifest/ApplyManifestDialog.tsx +315 -0
  398. package/src/manifest/EditResourceYamlDialog.tsx +265 -0
  399. package/src/manifest/RedactedSecretsNotice.tsx +30 -0
  400. package/src/manifest/YamlEditor.tsx +272 -0
  401. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +118 -0
  402. package/src/manifest/__tests__/useApplyManifest.test.tsx +237 -0
  403. package/src/manifest/__tests__/useEditResourceYaml.test.tsx +252 -0
  404. package/src/manifest/index.ts +33 -0
  405. package/src/manifest/useApplyManifest.ts +270 -0
  406. package/src/manifest/useEditResourceYaml.ts +273 -0
  407. package/src/mcp-server/McpServerDetailView.tsx +7 -3
  408. package/src/mcp-server/steps/ReviewStep.tsx +2 -3
  409. package/src/resource-creation/templates/workflow-templates.ts +4 -4
  410. package/src/session/SessionViewer.tsx +7 -1
  411. package/src/session/__tests__/audienceWiring.test.tsx +31 -1
  412. package/src/session/audience.ts +6 -1
  413. package/src/session/useEditSessionPrep.ts +3 -3
  414. package/src/settings/__tests__/useSettingsNavGroups.test.tsx +138 -0
  415. package/src/settings/index.ts +5 -1
  416. package/src/settings/settings-nav.ts +43 -0
  417. package/src/settings/useSettingsNavGroups.ts +81 -0
  418. package/src/skill/SkillDetailView.tsx +7 -3
  419. package/src/workflow/WorkflowAgentCallTranscript.tsx +279 -0
  420. package/src/workflow/WorkflowDetailView.tsx +7 -3
  421. package/src/workflow/WorkflowExecutionViewer.tsx +20 -77
  422. package/src/workflow/WorkflowTaskApprovalSummary.tsx +45 -8
  423. package/src/workflow/WorkflowYamlEditor.tsx +6 -270
  424. package/src/workflow/__tests__/WorkflowAgentCallTranscript.liveregion.test.tsx +124 -0
  425. package/src/workflow/__tests__/{WorkflowAgentExecutionDocument.test.tsx → WorkflowAgentCallTranscript.test.tsx} +146 -121
  426. package/src/workflow/__tests__/WorkflowExecutionViewer.approvals.test.tsx +81 -220
  427. package/src/workflow/__tests__/WorkflowExecutionViewer.reconciliation.test.tsx +17 -16
  428. package/src/workflow/__tests__/WorkflowTaskApprovalSummary.test.tsx +52 -2
  429. package/src/workflow/__tests__/WorkflowTaskThread.test.tsx +168 -185
  430. package/src/workflow/__tests__/agent-call-live-experience.test.ts +4 -4
  431. package/src/workflow/__tests__/task-approval.test.ts +119 -0
  432. package/src/workflow/__tests__/task-presentation.test.ts +35 -1
  433. package/src/workflow/__tests__/useWorkflowExecutionPanel.test.ts +0 -57
  434. package/src/workflow/index.ts +6 -3
  435. package/src/workflow/task-detail/index.ts +3 -0
  436. package/src/workflow/task-detail/task-approval.ts +95 -1
  437. package/src/workflow/thread/WorkflowTaskThread.tsx +96 -252
  438. package/src/workflow/thread/task-presentation.ts +8 -2
  439. package/src/workflow/useWorkflowExecutionPanel.ts +0 -47
  440. package/styles.css +1 -1
  441. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  442. package/workflow/WorkflowAgentCallTranscript.d.ts +87 -0
  443. package/workflow/WorkflowAgentCallTranscript.d.ts.map +1 -0
  444. package/workflow/WorkflowAgentCallTranscript.js +98 -0
  445. package/workflow/WorkflowAgentCallTranscript.js.map +1 -0
  446. package/workflow/WorkflowDetailView.d.ts.map +1 -1
  447. package/workflow/WorkflowDetailView.js +4 -3
  448. package/workflow/WorkflowDetailView.js.map +1 -1
  449. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  450. package/workflow/WorkflowExecutionViewer.js +23 -52
  451. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  452. package/workflow/WorkflowTaskApprovalSummary.d.ts +1 -1
  453. package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
  454. package/workflow/WorkflowTaskApprovalSummary.js +18 -1
  455. package/workflow/WorkflowTaskApprovalSummary.js.map +1 -1
  456. package/workflow/WorkflowYamlEditor.d.ts +2 -42
  457. package/workflow/WorkflowYamlEditor.d.ts.map +1 -1
  458. package/workflow/WorkflowYamlEditor.js +5 -214
  459. package/workflow/WorkflowYamlEditor.js.map +1 -1
  460. package/workflow/index.d.ts +2 -2
  461. package/workflow/index.d.ts.map +1 -1
  462. package/workflow/index.js +2 -2
  463. package/workflow/index.js.map +1 -1
  464. package/workflow/task-detail/index.d.ts +1 -1
  465. package/workflow/task-detail/index.d.ts.map +1 -1
  466. package/workflow/task-detail/index.js +1 -1
  467. package/workflow/task-detail/index.js.map +1 -1
  468. package/workflow/task-detail/task-approval.d.ts +44 -1
  469. package/workflow/task-detail/task-approval.d.ts.map +1 -1
  470. package/workflow/task-detail/task-approval.js +47 -0
  471. package/workflow/task-detail/task-approval.js.map +1 -1
  472. package/workflow/thread/WorkflowTaskThread.d.ts +17 -25
  473. package/workflow/thread/WorkflowTaskThread.d.ts.map +1 -1
  474. package/workflow/thread/WorkflowTaskThread.js +60 -105
  475. package/workflow/thread/WorkflowTaskThread.js.map +1 -1
  476. package/workflow/thread/task-presentation.d.ts.map +1 -1
  477. package/workflow/thread/task-presentation.js +7 -2
  478. package/workflow/thread/task-presentation.js.map +1 -1
  479. package/workflow/useWorkflowExecutionPanel.d.ts +0 -12
  480. package/workflow/useWorkflowExecutionPanel.d.ts.map +1 -1
  481. package/workflow/useWorkflowExecutionPanel.js +0 -12
  482. package/workflow/useWorkflowExecutionPanel.js.map +1 -1
  483. package/execution/agent-execution-document.d.ts +0 -31
  484. package/execution/agent-execution-document.d.ts.map +0 -1
  485. package/execution/agent-execution-document.js +0 -48
  486. package/execution/agent-execution-document.js.map +0 -1
  487. package/library/ImportResourceDialog.d.ts +0 -43
  488. package/library/ImportResourceDialog.d.ts.map +0 -1
  489. package/library/ImportResourceDialog.js +0 -90
  490. package/library/ImportResourceDialog.js.map +0 -1
  491. package/library/parse-resource-yaml.d.ts +0 -63
  492. package/library/parse-resource-yaml.d.ts.map +0 -1
  493. package/library/parse-resource-yaml.js +0 -407
  494. package/library/parse-resource-yaml.js.map +0 -1
  495. package/library/serialize-resource-yaml.d.ts +0 -103
  496. package/library/serialize-resource-yaml.d.ts.map +0 -1
  497. package/library/serialize-resource-yaml.js +0 -565
  498. package/library/serialize-resource-yaml.js.map +0 -1
  499. package/library/useImportResource.d.ts +0 -84
  500. package/library/useImportResource.d.ts.map +0 -1
  501. package/library/useImportResource.js +0 -188
  502. package/library/useImportResource.js.map +0 -1
  503. package/src/execution/__tests__/agent-execution-document.test.ts +0 -45
  504. package/src/execution/agent-execution-document.ts +0 -54
  505. package/src/library/ImportResourceDialog.tsx +0 -227
  506. package/src/library/parse-resource-yaml.ts +0 -630
  507. package/src/library/serialize-resource-yaml.ts +0 -756
  508. package/src/library/useImportResource.ts +0 -253
  509. package/src/workflow/WorkflowAgentExecutionDocument.tsx +0 -283
  510. package/workflow/WorkflowAgentExecutionDocument.d.ts +0 -79
  511. package/workflow/WorkflowAgentExecutionDocument.d.ts.map +0 -1
  512. package/workflow/WorkflowAgentExecutionDocument.js +0 -87
  513. package/workflow/WorkflowAgentExecutionDocument.js.map +0 -1
@@ -360,10 +360,16 @@ export function AgentDetailView({
360
360
  updatedAt: specAudit?.updatedAt ? timestampDate(specAudit.updatedAt) : null,
361
361
  };
362
362
 
363
- // Inline visibility is read-only (at-a-glance); editing lives in the
364
- // Manage access dialog, the single writer for both access axes.
363
+ // Inline visibility is at-a-glance AND a shortcut into the Manage access
364
+ // dialog the single writer for both access axes. The chip is navigation
365
+ // only (never edits in place); it stays a static badge for users who
366
+ // cannot view access. An inert chip reads as "not editable" (2026-07-18
367
+ // dogfood friction), so the shortcut is the discoverability affordance.
365
368
  const visibilityControl = meta ? (
366
- <VisibilityBadge visibility={meta.visibility} />
369
+ <VisibilityBadge
370
+ visibility={meta.visibility}
371
+ onClick={access.action ? access.open : undefined}
372
+ />
367
373
  ) : undefined;
368
374
 
369
375
  // Share — the sibling consent to Manage access: visibility governs who
@@ -2,9 +2,8 @@
2
2
 
3
3
  import { useMemo } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
- import { getUserMessage } from "@stigmer/sdk";
5
+ import { buildAgentProto, getUserMessage, serializeManifest } from "@stigmer/sdk";
6
6
  import type { AgentInput } from "@stigmer/sdk";
7
- import { serializeAgentInputYaml } from "../../library/serialize-resource-yaml.js";
8
7
  import type { AgentWizardData } from "./types.js";
9
8
 
10
9
  /** Props for {@link ReviewStep}. */
@@ -30,7 +29,7 @@ export function ReviewStep({
30
29
  }: ReviewStepProps) {
31
30
  const agentInput = useMemo(() => buildAgentInput(org, data), [org, data]);
32
31
  const yamlPreview = useMemo(
33
- () => serializeAgentInputYaml(agentInput),
32
+ () => serializeManifest(buildAgentProto(agentInput)),
34
33
  [agentInput],
35
34
  );
36
35
 
@@ -0,0 +1,619 @@
1
+ "use client";
2
+
3
+ import { useCallback, useState, type FormEvent } from "react";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import { getUserMessage } from "@stigmer/sdk";
6
+ import {
7
+ ModelPricingBaselineSchema,
8
+ PricingBlockSchema,
9
+ PricingVariantSchema,
10
+ type ModelPricingBaseline,
11
+ } from "@stigmer/protos/ai/stigmer/billing/v1/model_pricing_baseline_pb";
12
+ import { Button } from "../button/index.js";
13
+ import { Field, INPUT_CLASSES, RateField } from "./form-primitives.js";
14
+ import {
15
+ ZERO,
16
+ dollarsToMicros,
17
+ formatRate,
18
+ microsToDollarString,
19
+ } from "./pricing-format.js";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // BaselineEditor — the add/edit form for model registry baselines, with an
23
+ // explicit old→new rate confirmation step (a billing-critical edit is never
24
+ // submitted without the operator seeing exactly which rates move).
25
+ //
26
+ // Internal to the billing module: rendered by PricingGovernanceConsole and
27
+ // ModelCatalogPanel, never exported from the barrel.
28
+ // ---------------------------------------------------------------------------
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Form model — strings while editing, converted + validated on submit.
32
+ // Validation mirrors the protovalidate rules on ModelPricingBaseline so
33
+ // errors surface before the RPC.
34
+ // ---------------------------------------------------------------------------
35
+
36
+ interface VariantForm {
37
+ readonly key: string;
38
+ readonly input: string;
39
+ readonly output: string;
40
+ readonly cacheWrite: string;
41
+ readonly cacheRead: string;
42
+ /** Comma-separated wire ids. */
43
+ readonly wireIds: string;
44
+ }
45
+
46
+ interface CatalogForm {
47
+ readonly modelId: string;
48
+ readonly apiModelId: string;
49
+ readonly provider: string;
50
+ readonly harness: string;
51
+ readonly displayName: string;
52
+ readonly shortDescription: string;
53
+ readonly speedTier: string;
54
+ readonly costTier: string;
55
+ readonly featured: boolean;
56
+ readonly input: string;
57
+ readonly output: string;
58
+ readonly cacheWrite: string;
59
+ readonly cacheRead: string;
60
+ readonly cursorRate: string;
61
+ readonly variants: readonly VariantForm[];
62
+ readonly revisionNote: string;
63
+ }
64
+
65
+ const EMPTY_FORM: CatalogForm = {
66
+ modelId: "",
67
+ apiModelId: "",
68
+ provider: "",
69
+ harness: "native",
70
+ displayName: "",
71
+ shortDescription: "",
72
+ speedTier: "fast",
73
+ costTier: "standard",
74
+ featured: false,
75
+ input: "",
76
+ output: "",
77
+ cacheWrite: "0",
78
+ cacheRead: "0",
79
+ cursorRate: "",
80
+ variants: [],
81
+ revisionNote: "",
82
+ };
83
+
84
+ function formFromBaseline(baseline: ModelPricingBaseline): CatalogForm {
85
+ const pricing = baseline.pricing;
86
+ return {
87
+ modelId: baseline.modelId,
88
+ apiModelId: baseline.apiModelId,
89
+ provider: baseline.provider,
90
+ harness: baseline.harness,
91
+ displayName: baseline.displayName,
92
+ shortDescription: baseline.shortDescription,
93
+ speedTier: baseline.speedTier || "fast",
94
+ costTier: baseline.costTier || "standard",
95
+ featured: baseline.featured,
96
+ input: microsToDollarString(pricing?.inputPriceMicrosPerMillion ?? ZERO),
97
+ output: microsToDollarString(pricing?.outputPriceMicrosPerMillion ?? ZERO),
98
+ cacheWrite: microsToDollarString(pricing?.cacheWritePriceMicrosPerMillion ?? ZERO),
99
+ cacheRead: microsToDollarString(pricing?.cacheReadPriceMicrosPerMillion ?? ZERO),
100
+ cursorRate:
101
+ (pricing?.cursorTokenRateMicrosPerMillion ?? ZERO) > ZERO
102
+ ? microsToDollarString(pricing!.cursorTokenRateMicrosPerMillion)
103
+ : "",
104
+ variants: Object.entries(baseline.pricingVariants).map(([key, variant]) => ({
105
+ key,
106
+ input: microsToDollarString(variant.pricing?.inputPriceMicrosPerMillion ?? ZERO),
107
+ output: microsToDollarString(variant.pricing?.outputPriceMicrosPerMillion ?? ZERO),
108
+ cacheWrite: microsToDollarString(variant.pricing?.cacheWritePriceMicrosPerMillion ?? ZERO),
109
+ cacheRead: microsToDollarString(variant.pricing?.cacheReadPriceMicrosPerMillion ?? ZERO),
110
+ wireIds: variant.wireIds.join(", "),
111
+ })),
112
+ revisionNote: "",
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Convert the form to a baseline proto, or return field-level errors.
118
+ *
119
+ * When editing, runtime metadata the form does not surface (context
120
+ * window, summarization, capabilities, per-block provenance) is carried
121
+ * over from the previous revision so a price edit never erases catalog
122
+ * documentation.
123
+ */
124
+ function buildBaseline(
125
+ form: CatalogForm,
126
+ carryOver: ModelPricingBaseline | null,
127
+ ): { baseline?: ModelPricingBaseline; errors: string[] } {
128
+ const errors: string[] = [];
129
+ const requireText = (value: string, label: string) => {
130
+ if (value.trim() === "") errors.push(`${label} is required.`);
131
+ return value.trim();
132
+ };
133
+ const requireRate = (value: string, label: string): bigint => {
134
+ const micros = dollarsToMicros(value);
135
+ if (micros === null) {
136
+ errors.push(`${label} must be a non-negative dollar amount.`);
137
+ return ZERO;
138
+ }
139
+ return micros;
140
+ };
141
+
142
+ const modelId = requireText(form.modelId, "Model id");
143
+ const provider = requireText(form.provider, "Provider");
144
+ const harness = requireText(form.harness, "Harness");
145
+ const displayName = requireText(form.displayName, "Display name");
146
+
147
+ const input = requireRate(form.input, "Input rate");
148
+ const output = requireRate(form.output, "Output rate");
149
+ const cacheWrite = requireRate(form.cacheWrite, "Cache-write rate");
150
+ const cacheRead = requireRate(form.cacheRead, "Cache-read rate");
151
+ const cursorRate = form.cursorRate.trim() === "" ? ZERO : requireRate(form.cursorRate, "Cursor token rate");
152
+
153
+ const seenKeys = new Set<string>();
154
+ const variants: Record<string, ReturnType<typeof buildVariant>> = {};
155
+ for (const variant of form.variants) {
156
+ const key = variant.key.trim();
157
+ if (key === "") {
158
+ errors.push("Every variant needs a key (e.g. \"fast\").");
159
+ continue;
160
+ }
161
+ if (seenKeys.has(key)) {
162
+ errors.push(`Duplicate variant key "${key}".`);
163
+ continue;
164
+ }
165
+ seenKeys.add(key);
166
+ variants[key] = buildVariant(variant, key, carryOver, errors);
167
+ }
168
+
169
+ if (errors.length > 0) return { errors };
170
+
171
+ const previousPricing = carryOver?.pricing;
172
+ const baseline = create(ModelPricingBaselineSchema, {
173
+ modelId,
174
+ apiModelId: form.apiModelId.trim(),
175
+ provider,
176
+ harness,
177
+ displayName,
178
+ shortDescription: form.shortDescription.trim(),
179
+ speedTier: form.speedTier,
180
+ costTier: form.costTier,
181
+ featured: form.featured,
182
+ pricing: create(PricingBlockSchema, {
183
+ inputPriceMicrosPerMillion: input,
184
+ outputPriceMicrosPerMillion: output,
185
+ cacheWritePriceMicrosPerMillion: cacheWrite,
186
+ cacheReadPriceMicrosPerMillion: cacheRead,
187
+ cursorTokenRateMicrosPerMillion: cursorRate,
188
+ // Provenance of an operator edit is the revision itself; keep the
189
+ // previous source string so "where did this rate come from" is
190
+ // never blanked by a UI edit. effective_at is server-stamped.
191
+ source: previousPricing?.source ?? "operator_console",
192
+ sourceNote: previousPricing?.sourceNote ?? "",
193
+ }),
194
+ pricingVariants: variants,
195
+ // Runtime metadata is not editable here — carry the previous
196
+ // revision's values so an edit never erases them.
197
+ contextWindowTokens: carryOver?.contextWindowTokens ?? 0,
198
+ maxOutputTokens: carryOver?.maxOutputTokens ?? 0,
199
+ tokenCounterMethod: carryOver?.tokenCounterMethod ?? "",
200
+ summarization: carryOver?.summarization,
201
+ capabilities: carryOver?.capabilities,
202
+ });
203
+ return { baseline, errors: [] };
204
+ }
205
+
206
+ function buildVariant(
207
+ variant: VariantForm,
208
+ key: string,
209
+ carryOver: ModelPricingBaseline | null,
210
+ errors: string[],
211
+ ) {
212
+ const rate = (value: string, label: string): bigint => {
213
+ const micros = dollarsToMicros(value);
214
+ if (micros === null) {
215
+ errors.push(`Variant "${key}" ${label} must be a non-negative dollar amount.`);
216
+ return ZERO;
217
+ }
218
+ return micros;
219
+ };
220
+ const previous = carryOver?.pricingVariants[key]?.pricing;
221
+ return create(PricingVariantSchema, {
222
+ pricing: create(PricingBlockSchema, {
223
+ inputPriceMicrosPerMillion: rate(variant.input, "input rate"),
224
+ outputPriceMicrosPerMillion: rate(variant.output, "output rate"),
225
+ cacheWritePriceMicrosPerMillion: rate(variant.cacheWrite, "cache-write rate"),
226
+ cacheReadPriceMicrosPerMillion: rate(variant.cacheRead, "cache-read rate"),
227
+ source: previous?.source ?? "operator_console",
228
+ sourceNote: previous?.sourceNote ?? "",
229
+ }),
230
+ wireIds: variant.wireIds
231
+ .split(",")
232
+ .map((w) => w.trim())
233
+ .filter((w) => w !== ""),
234
+ });
235
+ }
236
+
237
+ // ---------------------------------------------------------------------------
238
+ // Rate diff for the confirmation step
239
+ // ---------------------------------------------------------------------------
240
+
241
+ interface RateChange {
242
+ readonly label: string;
243
+ readonly before: string;
244
+ readonly after: string;
245
+ }
246
+
247
+ function diffRates(
248
+ previous: ModelPricingBaseline | null,
249
+ next: ModelPricingBaseline,
250
+ ): RateChange[] {
251
+ const changes: RateChange[] = [];
252
+ const compare = (label: string, before: bigint | undefined, after: bigint | undefined) => {
253
+ const b = before ?? ZERO;
254
+ const a = after ?? ZERO;
255
+ if (b !== a) {
256
+ changes.push({
257
+ label,
258
+ before: previous ? formatRate(b) : "—",
259
+ after: formatRate(a),
260
+ });
261
+ }
262
+ };
263
+
264
+ compare("Input", previous?.pricing?.inputPriceMicrosPerMillion, next.pricing?.inputPriceMicrosPerMillion);
265
+ compare("Output", previous?.pricing?.outputPriceMicrosPerMillion, next.pricing?.outputPriceMicrosPerMillion);
266
+ compare("Cache write", previous?.pricing?.cacheWritePriceMicrosPerMillion, next.pricing?.cacheWritePriceMicrosPerMillion);
267
+ compare("Cache read", previous?.pricing?.cacheReadPriceMicrosPerMillion, next.pricing?.cacheReadPriceMicrosPerMillion);
268
+ compare("Cursor token rate", previous?.pricing?.cursorTokenRateMicrosPerMillion, next.pricing?.cursorTokenRateMicrosPerMillion);
269
+
270
+ const variantKeys = new Set([
271
+ ...Object.keys(previous?.pricingVariants ?? {}),
272
+ ...Object.keys(next.pricingVariants),
273
+ ]);
274
+ for (const key of variantKeys) {
275
+ const before = previous?.pricingVariants[key]?.pricing;
276
+ const after = next.pricingVariants[key]?.pricing;
277
+ if (!after) {
278
+ changes.push({ label: `Variant "${key}"`, before: "present", after: "removed" });
279
+ continue;
280
+ }
281
+ compare(`Variant "${key}" input`, before?.inputPriceMicrosPerMillion, after.inputPriceMicrosPerMillion);
282
+ compare(`Variant "${key}" output`, before?.outputPriceMicrosPerMillion, after.outputPriceMicrosPerMillion);
283
+ compare(`Variant "${key}" cache write`, before?.cacheWritePriceMicrosPerMillion, after.cacheWritePriceMicrosPerMillion);
284
+ compare(`Variant "${key}" cache read`, before?.cacheReadPriceMicrosPerMillion, after.cacheReadPriceMicrosPerMillion);
285
+ }
286
+ return changes;
287
+ }
288
+
289
+ // ---------------------------------------------------------------------------
290
+ // BaselineEditor — form step, then an explicit confirm step
291
+ // ---------------------------------------------------------------------------
292
+
293
+ export function BaselineEditor({
294
+ initial,
295
+ isSubmitting,
296
+ submitError,
297
+ onSubmit,
298
+ onCancel,
299
+ }: {
300
+ readonly initial: ModelPricingBaseline | null;
301
+ readonly isSubmitting: boolean;
302
+ readonly submitError: Error | null;
303
+ readonly onSubmit: (baseline: ModelPricingBaseline, revisionNote: string) => Promise<void>;
304
+ readonly onCancel: () => void;
305
+ }) {
306
+ const [form, setForm] = useState<CatalogForm>(
307
+ initial ? formFromBaseline(initial) : EMPTY_FORM,
308
+ );
309
+ const [validationErrors, setValidationErrors] = useState<string[]>([]);
310
+ const [pendingBaseline, setPendingBaseline] = useState<ModelPricingBaseline | null>(null);
311
+
312
+ const set = <K extends keyof CatalogForm>(field: K, value: CatalogForm[K]) =>
313
+ setForm((f) => ({ ...f, [field]: value }));
314
+
315
+ const handleReview = useCallback(
316
+ (e: FormEvent) => {
317
+ e.preventDefault();
318
+ const { baseline, errors } = buildBaseline(form, initial);
319
+ setValidationErrors(errors);
320
+ if (baseline) setPendingBaseline(baseline);
321
+ },
322
+ [form, initial],
323
+ );
324
+
325
+ const handleConfirm = useCallback(async () => {
326
+ if (!pendingBaseline) return;
327
+ try {
328
+ await onSubmit(pendingBaseline, form.revisionNote.trim());
329
+ } catch {
330
+ // Surfaced via submitError; return to the confirm view.
331
+ }
332
+ }, [pendingBaseline, form.revisionNote, onSubmit]);
333
+
334
+ // ── confirm step ──────────────────────────────────────────────────────────
335
+ if (pendingBaseline) {
336
+ const changes = diffRates(initial, pendingBaseline);
337
+ return (
338
+ <div className="space-y-3 rounded-lg border border-border bg-card px-3 py-3">
339
+ <h4 className="text-xs font-semibold text-foreground">
340
+ {initial ? "Confirm baseline revision" : "Confirm new catalog entry"}
341
+ {" · "}
342
+ <span className="font-normal text-muted-foreground">
343
+ {pendingBaseline.modelId} / {pendingBaseline.provider} / {pendingBaseline.harness}
344
+ </span>
345
+ </h4>
346
+ {changes.length === 0 ? (
347
+ <p className="text-xs text-muted-foreground">
348
+ No rate changes — only catalog fields move. Billing is unaffected.
349
+ </p>
350
+ ) : (
351
+ <div className="space-y-1" role="table" aria-label="Rate changes">
352
+ {changes.map((change) => (
353
+ <p key={change.label} className="text-xs text-foreground" role="row">
354
+ <span className="text-muted-foreground">{change.label}: </span>
355
+ <span className="line-through">{change.before}</span>
356
+ {" → "}
357
+ <span className="font-medium">{change.after}</span>
358
+ </p>
359
+ ))}
360
+ <p className="text-[11px] text-muted-foreground">
361
+ New rates govern charges from the moment this revision is applied
362
+ (forward-only; already-billed records keep their stamps).
363
+ </p>
364
+ </div>
365
+ )}
366
+ {submitError && (
367
+ <p className="text-destructive text-xs" role="alert">
368
+ {getUserMessage(submitError)}
369
+ </p>
370
+ )}
371
+ <div className="flex gap-2">
372
+ <Button size="sm" disabled={isSubmitting} onClick={handleConfirm}>
373
+ {isSubmitting ? "Applying…" : "Apply revision"}
374
+ </Button>
375
+ <Button
376
+ size="sm"
377
+ variant="outline"
378
+ disabled={isSubmitting}
379
+ onClick={() => setPendingBaseline(null)}
380
+ >
381
+ Back
382
+ </Button>
383
+ </div>
384
+ </div>
385
+ );
386
+ }
387
+
388
+ // ── form step ─────────────────────────────────────────────────────────────
389
+ return (
390
+ <form
391
+ onSubmit={handleReview}
392
+ className="space-y-3 rounded-lg border border-border bg-card px-3 py-3"
393
+ >
394
+ <h4 className="text-xs font-semibold text-foreground">
395
+ {initial ? `Edit ${initial.modelId}` : "Add model"}
396
+ </h4>
397
+
398
+ <div className="grid grid-cols-2 gap-2">
399
+ <Field label="Model id" required>
400
+ <input
401
+ className={INPUT_CLASSES}
402
+ value={form.modelId}
403
+ onChange={(e) => set("modelId", e.target.value)}
404
+ placeholder="e.g. claude-sonnet-4.6"
405
+ // Identity is the catalog key: editing it would create a NEW
406
+ // entry, not revise this one — lock it on edit.
407
+ disabled={initial !== null || isSubmitting}
408
+ required
409
+ />
410
+ </Field>
411
+ <Field label="Provider API id">
412
+ <input
413
+ className={INPUT_CLASSES}
414
+ value={form.apiModelId}
415
+ onChange={(e) => set("apiModelId", e.target.value)}
416
+ placeholder="e.g. claude-sonnet-4-6"
417
+ disabled={isSubmitting}
418
+ />
419
+ </Field>
420
+ <Field label="Provider" required>
421
+ <input
422
+ className={INPUT_CLASSES}
423
+ value={form.provider}
424
+ onChange={(e) => set("provider", e.target.value)}
425
+ placeholder="e.g. anthropic"
426
+ disabled={initial !== null || isSubmitting}
427
+ required
428
+ />
429
+ </Field>
430
+ <Field label="Harness" required>
431
+ <select
432
+ className={INPUT_CLASSES}
433
+ value={form.harness}
434
+ onChange={(e) => set("harness", e.target.value)}
435
+ disabled={initial !== null || isSubmitting}
436
+ >
437
+ <option value="native">native</option>
438
+ <option value="cursor">cursor</option>
439
+ </select>
440
+ </Field>
441
+ <Field label="Display name" required>
442
+ <input
443
+ className={INPUT_CLASSES}
444
+ value={form.displayName}
445
+ onChange={(e) => set("displayName", e.target.value)}
446
+ disabled={isSubmitting}
447
+ required
448
+ />
449
+ </Field>
450
+ <Field label="Short description">
451
+ <input
452
+ className={INPUT_CLASSES}
453
+ value={form.shortDescription}
454
+ onChange={(e) => set("shortDescription", e.target.value)}
455
+ placeholder="3-6 word pitch"
456
+ disabled={isSubmitting}
457
+ />
458
+ </Field>
459
+ <Field label="Speed tier">
460
+ <select
461
+ className={INPUT_CLASSES}
462
+ value={form.speedTier}
463
+ onChange={(e) => set("speedTier", e.target.value)}
464
+ disabled={isSubmitting}
465
+ >
466
+ <option value="fastest">fastest</option>
467
+ <option value="fast">fast</option>
468
+ <option value="balanced">balanced</option>
469
+ <option value="slow">slow</option>
470
+ </select>
471
+ </Field>
472
+ <Field label="Cost tier">
473
+ <select
474
+ className={INPUT_CLASSES}
475
+ value={form.costTier}
476
+ onChange={(e) => set("costTier", e.target.value)}
477
+ disabled={isSubmitting}
478
+ >
479
+ <option value="economy">economy</option>
480
+ <option value="standard">standard</option>
481
+ <option value="premium">premium</option>
482
+ </select>
483
+ </Field>
484
+ </div>
485
+
486
+ <label className="flex cursor-pointer items-center gap-1.5 text-xs text-foreground">
487
+ <input
488
+ type="checkbox"
489
+ checked={form.featured}
490
+ onChange={(e) => set("featured", e.target.checked)}
491
+ disabled={isSubmitting}
492
+ />
493
+ Featured (appears in the curated default picker list)
494
+ </label>
495
+
496
+ <fieldset className="space-y-2">
497
+ <legend className="text-xs font-medium text-foreground">
498
+ Rates ($ per million tokens)
499
+ </legend>
500
+ <div className="grid grid-cols-2 gap-2 sm:grid-cols-5">
501
+ <RateField label="Input" value={form.input} disabled={isSubmitting} onChange={(v) => set("input", v)} />
502
+ <RateField label="Output" value={form.output} disabled={isSubmitting} onChange={(v) => set("output", v)} />
503
+ <RateField label="Cache write" value={form.cacheWrite} disabled={isSubmitting} onChange={(v) => set("cacheWrite", v)} />
504
+ <RateField label="Cache read" value={form.cacheRead} disabled={isSubmitting} onChange={(v) => set("cacheRead", v)} />
505
+ <RateField
506
+ label="Cursor token rate"
507
+ value={form.cursorRate}
508
+ placeholder="cursor only"
509
+ disabled={isSubmitting}
510
+ onChange={(v) => set("cursorRate", v)}
511
+ />
512
+ </div>
513
+ </fieldset>
514
+
515
+ <fieldset className="space-y-2">
516
+ <legend className="text-xs font-medium text-foreground">Pricing variants</legend>
517
+ {form.variants.map((variant, index) => (
518
+ <div key={index} className="space-y-2 rounded-md border border-border-muted px-2.5 py-2">
519
+ <div className="flex items-end gap-2">
520
+ <Field label="Variant key" className="w-32">
521
+ <input
522
+ className={INPUT_CLASSES}
523
+ value={variant.key}
524
+ onChange={(e) => updateVariant(setForm, index, { key: e.target.value })}
525
+ placeholder="fast"
526
+ disabled={isSubmitting}
527
+ />
528
+ </Field>
529
+ <Field label="Wire ids (comma-separated)" className="flex-1">
530
+ <input
531
+ className={INPUT_CLASSES}
532
+ value={variant.wireIds}
533
+ onChange={(e) => updateVariant(setForm, index, { wireIds: e.target.value })}
534
+ placeholder="e.g. composer-2.5-fast"
535
+ disabled={isSubmitting}
536
+ />
537
+ </Field>
538
+ <Button
539
+ size="sm"
540
+ variant="outline"
541
+ disabled={isSubmitting}
542
+ onClick={() =>
543
+ setForm((f) => ({
544
+ ...f,
545
+ variants: f.variants.filter((_, i) => i !== index),
546
+ }))
547
+ }
548
+ >
549
+ Remove
550
+ </Button>
551
+ </div>
552
+ <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
553
+ <RateField label="Input" value={variant.input} disabled={isSubmitting} onChange={(v) => updateVariant(setForm, index, { input: v })} />
554
+ <RateField label="Output" value={variant.output} disabled={isSubmitting} onChange={(v) => updateVariant(setForm, index, { output: v })} />
555
+ <RateField label="Cache write" value={variant.cacheWrite} disabled={isSubmitting} onChange={(v) => updateVariant(setForm, index, { cacheWrite: v })} />
556
+ <RateField label="Cache read" value={variant.cacheRead} disabled={isSubmitting} onChange={(v) => updateVariant(setForm, index, { cacheRead: v })} />
557
+ </div>
558
+ </div>
559
+ ))}
560
+ <Button
561
+ size="sm"
562
+ variant="outline"
563
+ disabled={isSubmitting}
564
+ onClick={() =>
565
+ setForm((f) => ({
566
+ ...f,
567
+ variants: [
568
+ ...f.variants,
569
+ { key: "", input: "", output: "", cacheWrite: "0", cacheRead: "0", wireIds: "" },
570
+ ],
571
+ }))
572
+ }
573
+ >
574
+ Add variant
575
+ </Button>
576
+ </fieldset>
577
+
578
+ <Field label="Revision note">
579
+ <input
580
+ className={INPUT_CLASSES}
581
+ value={form.revisionNote}
582
+ onChange={(e) => set("revisionNote", e.target.value)}
583
+ placeholder="Why this revision (audit trail)"
584
+ disabled={isSubmitting}
585
+ />
586
+ </Field>
587
+
588
+ {validationErrors.length > 0 && (
589
+ <div role="alert" className="space-y-0.5">
590
+ {validationErrors.map((message) => (
591
+ <p key={message} className="text-destructive text-xs">
592
+ {message}
593
+ </p>
594
+ ))}
595
+ </div>
596
+ )}
597
+
598
+ <div className="flex gap-2">
599
+ <Button size="sm" type="submit" disabled={isSubmitting}>
600
+ Review changes
601
+ </Button>
602
+ <Button size="sm" variant="outline" disabled={isSubmitting} onClick={onCancel}>
603
+ Cancel
604
+ </Button>
605
+ </div>
606
+ </form>
607
+ );
608
+ }
609
+
610
+ function updateVariant(
611
+ setForm: (updater: (f: CatalogForm) => CatalogForm) => void,
612
+ index: number,
613
+ patch: Partial<VariantForm>,
614
+ ) {
615
+ setForm((f) => ({
616
+ ...f,
617
+ variants: f.variants.map((v, i) => (i === index ? { ...v, ...patch } : v)),
618
+ }));
619
+ }