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