@stigmer/react 3.2.3 → 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.
- package/agent/steps/ReviewStep.d.ts.map +1 -1
- package/agent/steps/ReviewStep.js +2 -3
- package/agent/steps/ReviewStep.js.map +1 -1
- package/billing/BaselineEditor.d.ts +9 -0
- package/billing/BaselineEditor.d.ts.map +1 -0
- package/billing/BaselineEditor.js +253 -0
- package/billing/BaselineEditor.js.map +1 -0
- package/billing/ModelCatalogPanel.d.ts +28 -0
- package/billing/ModelCatalogPanel.d.ts.map +1 -0
- package/billing/ModelCatalogPanel.js +102 -0
- package/billing/ModelCatalogPanel.js.map +1 -0
- package/billing/ModelGovernanceDetail.d.ts +8 -0
- package/billing/ModelGovernanceDetail.d.ts.map +1 -0
- package/billing/ModelGovernanceDetail.js +64 -0
- package/billing/ModelGovernanceDetail.js.map +1 -0
- package/billing/OperatorAccessNotice.d.ts +12 -0
- package/billing/OperatorAccessNotice.d.ts.map +1 -0
- package/billing/OperatorAccessNotice.js +15 -0
- package/billing/OperatorAccessNotice.js.map +1 -0
- package/billing/PricingGovernanceConsole.d.ts +57 -0
- package/billing/PricingGovernanceConsole.d.ts.map +1 -0
- package/billing/PricingGovernanceConsole.js +164 -0
- package/billing/PricingGovernanceConsole.js.map +1 -0
- package/billing/PricingGovernancePanel.d.ts +26 -0
- package/billing/PricingGovernancePanel.d.ts.map +1 -0
- package/billing/PricingGovernancePanel.js +64 -0
- package/billing/PricingGovernancePanel.js.map +1 -0
- package/billing/RetireConfirm.d.ts +9 -0
- package/billing/RetireConfirm.d.ts.map +1 -0
- package/billing/RetireConfirm.js +19 -0
- package/billing/RetireConfirm.js.map +1 -0
- package/billing/form-primitives.d.ts +18 -0
- package/billing/form-primitives.d.ts.map +1 -0
- package/billing/form-primitives.js +19 -0
- package/billing/form-primitives.js.map +1 -0
- package/billing/governance-primitives.d.ts +33 -0
- package/billing/governance-primitives.d.ts.map +1 -0
- package/billing/governance-primitives.js +43 -0
- package/billing/governance-primitives.js.map +1 -0
- package/billing/index.d.ts +18 -0
- package/billing/index.d.ts.map +1 -1
- package/billing/index.js +9 -0
- package/billing/index.js.map +1 -1
- package/billing/pricing-format.d.ts +12 -0
- package/billing/pricing-format.d.ts.map +1 -0
- package/billing/pricing-format.js +50 -0
- package/billing/pricing-format.js.map +1 -0
- package/billing/useDecidePricingOverride.d.ts +46 -0
- package/billing/useDecidePricingOverride.d.ts.map +1 -0
- package/billing/useDecidePricingOverride.js +44 -0
- package/billing/useDecidePricingOverride.js.map +1 -0
- package/billing/useModelGovernanceView.d.ts +103 -0
- package/billing/useModelGovernanceView.d.ts.map +1 -0
- package/billing/useModelGovernanceView.js +144 -0
- package/billing/useModelGovernanceView.js.map +1 -0
- package/billing/useModelPricingBaselines.d.ts +40 -0
- package/billing/useModelPricingBaselines.d.ts.map +1 -0
- package/billing/useModelPricingBaselines.js +32 -0
- package/billing/useModelPricingBaselines.js.map +1 -0
- package/billing/usePricingGovernance.d.ts +39 -0
- package/billing/usePricingGovernance.d.ts.map +1 -0
- package/billing/usePricingGovernance.js +31 -0
- package/billing/usePricingGovernance.js.map +1 -0
- package/billing/useRetireModelPricingBaseline.d.ts +31 -0
- package/billing/useRetireModelPricingBaseline.d.ts.map +1 -0
- package/billing/useRetireModelPricingBaseline.js +36 -0
- package/billing/useRetireModelPricingBaseline.js.map +1 -0
- package/billing/useUpsertModelPricingBaseline.d.ts +38 -0
- package/billing/useUpsertModelPricingBaseline.d.ts.map +1 -0
- package/billing/useUpsertModelPricingBaseline.js +37 -0
- package/billing/useUpsertModelPricingBaseline.js.map +1 -0
- package/channel/AgentChannelsPanel.d.ts.map +1 -1
- package/channel/AgentChannelsPanel.js +11 -5
- package/channel/AgentChannelsPanel.js.map +1 -1
- package/composer/SessionComposer.d.ts +1 -1
- package/cursor-accounts/CursorAccountEditor.d.ts +28 -0
- package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountEditor.js +51 -0
- package/cursor-accounts/CursorAccountEditor.js.map +1 -0
- package/cursor-accounts/CursorAccountsAccessNotice.d.ts +11 -0
- package/cursor-accounts/CursorAccountsAccessNotice.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountsAccessNotice.js +14 -0
- package/cursor-accounts/CursorAccountsAccessNotice.js.map +1 -0
- package/cursor-accounts/CursorAccountsConsole.d.ts +28 -0
- package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountsConsole.js +275 -0
- package/cursor-accounts/CursorAccountsConsole.js.map +1 -0
- package/cursor-accounts/cursor-account-format.d.ts +10 -0
- package/cursor-accounts/cursor-account-format.d.ts.map +1 -0
- package/cursor-accounts/cursor-account-format.js +26 -0
- package/cursor-accounts/cursor-account-format.js.map +1 -0
- package/cursor-accounts/index.d.ts +18 -0
- package/cursor-accounts/index.d.ts.map +1 -0
- package/cursor-accounts/index.js +13 -0
- package/cursor-accounts/index.js.map +1 -0
- package/cursor-accounts/useCursorAccountView.d.ts +30 -0
- package/cursor-accounts/useCursorAccountView.d.ts.map +1 -0
- package/cursor-accounts/useCursorAccountView.js +25 -0
- package/cursor-accounts/useCursorAccountView.js.map +1 -0
- package/cursor-accounts/useCursorAccounts.d.ts +33 -0
- package/cursor-accounts/useCursorAccounts.d.ts.map +1 -0
- package/cursor-accounts/useCursorAccounts.js +25 -0
- package/cursor-accounts/useCursorAccounts.js.map +1 -0
- package/cursor-accounts/useCursorMemberKeyActions.d.ts +49 -0
- package/cursor-accounts/useCursorMemberKeyActions.d.ts.map +1 -0
- package/cursor-accounts/useCursorMemberKeyActions.js +38 -0
- package/cursor-accounts/useCursorMemberKeyActions.js.map +1 -0
- package/cursor-accounts/useDeleteCursorAccount.d.ts +30 -0
- package/cursor-accounts/useDeleteCursorAccount.d.ts.map +1 -0
- package/cursor-accounts/useDeleteCursorAccount.js +32 -0
- package/cursor-accounts/useDeleteCursorAccount.js.map +1 -0
- package/cursor-accounts/useSyncCursorAccount.d.ts +23 -0
- package/cursor-accounts/useSyncCursorAccount.d.ts.map +1 -0
- package/cursor-accounts/useSyncCursorAccount.js +31 -0
- package/cursor-accounts/useSyncCursorAccount.js.map +1 -0
- package/cursor-accounts/useUpsertCursorAccount.d.ts +26 -0
- package/cursor-accounts/useUpsertCursorAccount.d.ts.map +1 -0
- package/cursor-accounts/useUpsertCursorAccount.js +34 -0
- package/cursor-accounts/useUpsertCursorAccount.js.map +1 -0
- package/datastore/CollectionRecordsBrowser.d.ts +34 -0
- package/datastore/CollectionRecordsBrowser.d.ts.map +1 -0
- package/datastore/CollectionRecordsBrowser.js +209 -0
- package/datastore/CollectionRecordsBrowser.js.map +1 -0
- package/datastore/CollectionSchemaView.d.ts +29 -0
- package/datastore/CollectionSchemaView.d.ts.map +1 -0
- package/datastore/CollectionSchemaView.js +93 -0
- package/datastore/CollectionSchemaView.js.map +1 -0
- package/datastore/DatastoreDetailView.d.ts +44 -0
- package/datastore/DatastoreDetailView.d.ts.map +1 -0
- package/datastore/DatastoreDetailView.js +76 -0
- package/datastore/DatastoreDetailView.js.map +1 -0
- package/datastore/DatastoreSyncReport.d.ts +19 -0
- package/datastore/DatastoreSyncReport.d.ts.map +1 -0
- package/datastore/DatastoreSyncReport.js +45 -0
- package/datastore/DatastoreSyncReport.js.map +1 -0
- package/datastore/DeleteDatastoreDialog.d.ts +35 -0
- package/datastore/DeleteDatastoreDialog.d.ts.map +1 -0
- package/datastore/DeleteDatastoreDialog.js +90 -0
- package/datastore/DeleteDatastoreDialog.js.map +1 -0
- package/datastore/FieldValueControl.d.ts +55 -0
- package/datastore/FieldValueControl.d.ts.map +1 -0
- package/datastore/FieldValueControl.js +138 -0
- package/datastore/FieldValueControl.js.map +1 -0
- package/datastore/RecordFilterBuilder.d.ts +30 -0
- package/datastore/RecordFilterBuilder.d.ts.map +1 -0
- package/datastore/RecordFilterBuilder.js +122 -0
- package/datastore/RecordFilterBuilder.js.map +1 -0
- package/datastore/RecordFormPanel.d.ts +45 -0
- package/datastore/RecordFormPanel.d.ts.map +1 -0
- package/datastore/RecordFormPanel.js +215 -0
- package/datastore/RecordFormPanel.js.map +1 -0
- package/datastore/index.d.ts +43 -0
- package/datastore/index.d.ts.map +1 -0
- package/datastore/index.js +22 -0
- package/datastore/index.js.map +1 -0
- package/datastore/recordFilter.d.ts +54 -0
- package/datastore/recordFilter.d.ts.map +1 -0
- package/datastore/recordFilter.js +93 -0
- package/datastore/recordFilter.js.map +1 -0
- package/datastore/recordValues.d.ts +85 -0
- package/datastore/recordValues.d.ts.map +1 -0
- package/datastore/recordValues.js +282 -0
- package/datastore/recordValues.js.map +1 -0
- package/datastore/useDatastore.d.ts +39 -0
- package/datastore/useDatastore.d.ts.map +1 -0
- package/datastore/useDatastore.js +44 -0
- package/datastore/useDatastore.js.map +1 -0
- package/datastore/useDatastoreCount.d.ts +48 -0
- package/datastore/useDatastoreCount.d.ts.map +1 -0
- package/datastore/useDatastoreCount.js +27 -0
- package/datastore/useDatastoreCount.js.map +1 -0
- package/datastore/useDatastoreDescription.d.ts +54 -0
- package/datastore/useDatastoreDescription.d.ts.map +1 -0
- package/datastore/useDatastoreDescription.js +50 -0
- package/datastore/useDatastoreDescription.js.map +1 -0
- package/datastore/useDatastoreList.d.ts +57 -0
- package/datastore/useDatastoreList.d.ts.map +1 -0
- package/datastore/useDatastoreList.js +29 -0
- package/datastore/useDatastoreList.js.map +1 -0
- package/datastore/useDatastoreSearch.d.ts +19 -0
- package/datastore/useDatastoreSearch.d.ts.map +1 -0
- package/datastore/useDatastoreSearch.js +22 -0
- package/datastore/useDatastoreSearch.js.map +1 -0
- package/datastore/useDeleteDatastore.d.ts +53 -0
- package/datastore/useDeleteDatastore.d.ts.map +1 -0
- package/datastore/useDeleteDatastore.js +40 -0
- package/datastore/useDeleteDatastore.js.map +1 -0
- package/datastore/useDeleteRecord.d.ts +34 -0
- package/datastore/useDeleteRecord.d.ts.map +1 -0
- package/datastore/useDeleteRecord.js +43 -0
- package/datastore/useDeleteRecord.js.map +1 -0
- package/datastore/useInsertRecord.d.ts +50 -0
- package/datastore/useInsertRecord.d.ts.map +1 -0
- package/datastore/useInsertRecord.js +55 -0
- package/datastore/useInsertRecord.js.map +1 -0
- package/datastore/useRecordCollection.d.ts +104 -0
- package/datastore/useRecordCollection.d.ts.map +1 -0
- package/datastore/useRecordCollection.js +136 -0
- package/datastore/useRecordCollection.js.map +1 -0
- package/datastore/useRecordList.d.ts +66 -0
- package/datastore/useRecordList.d.ts.map +1 -0
- package/datastore/useRecordList.js +58 -0
- package/datastore/useRecordList.js.map +1 -0
- package/datastore/useUpdateRecord.d.ts +52 -0
- package/datastore/useUpdateRecord.d.ts.map +1 -0
- package/datastore/useUpdateRecord.js +55 -0
- package/datastore/useUpdateRecord.js.map +1 -0
- package/environment/EnvironmentListPanel.d.ts.map +1 -1
- package/environment/EnvironmentListPanel.js +12 -7
- package/environment/EnvironmentListPanel.js.map +1 -1
- package/iam-policy/index.d.ts +1 -1
- package/iam-policy/index.d.ts.map +1 -1
- package/iam-policy/index.js.map +1 -1
- package/iam-policy/useCheckPermission.d.ts +32 -11
- package/iam-policy/useCheckPermission.d.ts.map +1 -1
- package/iam-policy/useCheckPermission.js +24 -19
- package/iam-policy/useCheckPermission.js.map +1 -1
- package/index.d.ts +12 -6
- package/index.d.ts.map +1 -1
- package/index.js +14 -3
- package/index.js.map +1 -1
- package/library/index.d.ts +0 -7
- package/library/index.d.ts.map +1 -1
- package/library/index.js +0 -4
- package/library/index.js.map +1 -1
- package/library/useApplyResource.d.ts +12 -12
- package/library/useApplyResource.d.ts.map +1 -1
- package/library/useApplyResource.js +16 -25
- package/library/useApplyResource.js.map +1 -1
- package/library/useExportResource.d.ts +13 -9
- package/library/useExportResource.d.ts.map +1 -1
- package/library/useExportResource.js +18 -36
- package/library/useExportResource.js.map +1 -1
- package/manifest/ApplyManifestDialog.d.ts +48 -0
- package/manifest/ApplyManifestDialog.d.ts.map +1 -0
- package/manifest/ApplyManifestDialog.js +135 -0
- package/manifest/ApplyManifestDialog.js.map +1 -0
- package/manifest/EditResourceYamlDialog.d.ts +51 -0
- package/manifest/EditResourceYamlDialog.d.ts.map +1 -0
- package/manifest/EditResourceYamlDialog.js +104 -0
- package/manifest/EditResourceYamlDialog.js.map +1 -0
- package/manifest/RedactedSecretsNotice.d.ts +14 -0
- package/manifest/RedactedSecretsNotice.d.ts.map +1 -0
- package/manifest/RedactedSecretsNotice.js +14 -0
- package/manifest/RedactedSecretsNotice.js.map +1 -0
- package/manifest/YamlEditor.d.ts +44 -0
- package/manifest/YamlEditor.d.ts.map +1 -0
- package/manifest/YamlEditor.js +216 -0
- package/manifest/YamlEditor.js.map +1 -0
- package/manifest/index.d.ts +13 -0
- package/manifest/index.d.ts.map +1 -0
- package/manifest/index.js +13 -0
- package/manifest/index.js.map +1 -0
- package/manifest/useApplyManifest.d.ts +82 -0
- package/manifest/useApplyManifest.d.ts.map +1 -0
- package/manifest/useApplyManifest.js +180 -0
- package/manifest/useApplyManifest.js.map +1 -0
- package/manifest/useEditResourceYaml.d.ts +106 -0
- package/manifest/useEditResourceYaml.d.ts.map +1 -0
- package/manifest/useEditResourceYaml.js +168 -0
- package/manifest/useEditResourceYaml.js.map +1 -0
- package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
- package/mcp-server/steps/ReviewStep.js +2 -3
- package/mcp-server/steps/ReviewStep.js.map +1 -1
- package/package.json +4 -4
- package/resource-creation/templates/workflow-templates.js +4 -4
- package/session/useEditSessionPrep.js +3 -3
- package/session/useEditSessionPrep.js.map +1 -1
- package/settings/index.d.ts +2 -1
- package/settings/index.d.ts.map +1 -1
- package/settings/index.js +2 -1
- package/settings/index.js.map +1 -1
- package/settings/settings-nav.d.ts +22 -0
- package/settings/settings-nav.d.ts.map +1 -1
- package/settings/settings-nav.js +32 -1
- package/settings/settings-nav.js.map +1 -1
- package/settings/useSettingsNavGroups.d.ts +29 -0
- package/settings/useSettingsNavGroups.d.ts.map +1 -0
- package/settings/useSettingsNavGroups.js +61 -0
- package/settings/useSettingsNavGroups.js.map +1 -0
- package/src/agent/steps/ReviewStep.tsx +2 -3
- package/src/billing/BaselineEditor.tsx +619 -0
- package/src/billing/ModelCatalogPanel.tsx +283 -0
- package/src/billing/ModelGovernanceDetail.tsx +289 -0
- package/src/billing/OperatorAccessNotice.tsx +32 -0
- package/src/billing/PricingGovernanceConsole.tsx +465 -0
- package/src/billing/PricingGovernancePanel.tsx +166 -0
- package/src/billing/RetireConfirm.tsx +82 -0
- package/src/billing/__tests__/ModelCatalogPanel.test.tsx +253 -0
- package/src/billing/__tests__/PricingGovernanceConsole.test.tsx +410 -0
- package/src/billing/__tests__/useModelGovernanceView.test.tsx +308 -0
- package/src/billing/form-primitives.tsx +68 -0
- package/src/billing/governance-primitives.tsx +133 -0
- package/src/billing/index.ts +37 -0
- package/src/billing/pricing-format.ts +53 -0
- package/src/billing/useDecidePricingOverride.ts +78 -0
- package/src/billing/useModelGovernanceView.ts +290 -0
- package/src/billing/useModelPricingBaselines.ts +69 -0
- package/src/billing/usePricingGovernance.ts +57 -0
- package/src/billing/useRetireModelPricingBaseline.ts +65 -0
- package/src/billing/useUpsertModelPricingBaseline.ts +72 -0
- package/src/channel/AgentChannelsPanel.tsx +27 -1
- package/src/composer/SessionComposer.tsx +1 -1
- package/src/cursor-accounts/CursorAccountEditor.tsx +181 -0
- package/src/cursor-accounts/CursorAccountsAccessNotice.tsx +36 -0
- package/src/cursor-accounts/CursorAccountsConsole.tsx +810 -0
- package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +384 -0
- package/src/cursor-accounts/cursor-account-format.ts +29 -0
- package/src/cursor-accounts/index.ts +29 -0
- package/src/cursor-accounts/useCursorAccountView.ts +49 -0
- package/src/cursor-accounts/useCursorAccounts.ts +49 -0
- package/src/cursor-accounts/useCursorMemberKeyActions.ts +106 -0
- package/src/cursor-accounts/useDeleteCursorAccount.ts +62 -0
- package/src/cursor-accounts/useSyncCursorAccount.ts +54 -0
- package/src/cursor-accounts/useUpsertCursorAccount.ts +57 -0
- package/src/datastore/CollectionRecordsBrowser.tsx +544 -0
- package/src/datastore/CollectionSchemaView.tsx +247 -0
- package/src/datastore/DatastoreDetailView.tsx +201 -0
- package/src/datastore/DatastoreSyncReport.tsx +105 -0
- package/src/datastore/DeleteDatastoreDialog.tsx +202 -0
- package/src/datastore/FieldValueControl.tsx +289 -0
- package/src/datastore/RecordFilterBuilder.tsx +411 -0
- package/src/datastore/RecordFormPanel.tsx +432 -0
- package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +207 -0
- package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +133 -0
- package/src/datastore/__tests__/FieldValueControl.test.tsx +160 -0
- package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +141 -0
- package/src/datastore/__tests__/RecordFormPanel.test.tsx +227 -0
- package/src/datastore/__tests__/recordFilter.test.ts +156 -0
- package/src/datastore/__tests__/recordMutations.test.tsx +195 -0
- package/src/datastore/__tests__/recordValues.test.ts +359 -0
- package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +142 -0
- package/src/datastore/__tests__/useDatastoreDescription.test.tsx +143 -0
- package/src/datastore/__tests__/useRecordCollection.test.tsx +250 -0
- package/src/datastore/__tests__/useRecordList.test.tsx +85 -0
- package/src/datastore/index.ts +111 -0
- package/src/datastore/recordFilter.ts +140 -0
- package/src/datastore/recordValues.ts +327 -0
- package/src/datastore/useDatastore.ts +67 -0
- package/src/datastore/useDatastoreCount.ts +67 -0
- package/src/datastore/useDatastoreDescription.ts +90 -0
- package/src/datastore/useDatastoreList.ts +79 -0
- package/src/datastore/useDatastoreSearch.ts +39 -0
- package/src/datastore/useDeleteDatastore.ts +87 -0
- package/src/datastore/useDeleteRecord.ts +77 -0
- package/src/datastore/useInsertRecord.ts +92 -0
- package/src/datastore/useRecordCollection.ts +256 -0
- package/src/datastore/useRecordList.ts +131 -0
- package/src/datastore/useUpdateRecord.ts +95 -0
- package/src/environment/EnvironmentListPanel.tsx +24 -0
- package/src/execution/__tests__/useArtifactInspection.test.tsx +12 -2
- package/src/iam-policy/__tests__/useCheckPermission.test.tsx +221 -0
- package/src/iam-policy/index.ts +1 -0
- package/src/iam-policy/useCheckPermission.ts +45 -19
- package/src/index.ts +163 -13
- package/src/library/index.ts +0 -20
- package/src/library/useApplyResource.ts +27 -34
- package/src/library/useExportResource.ts +21 -40
- package/src/manifest/ApplyManifestDialog.tsx +315 -0
- package/src/manifest/EditResourceYamlDialog.tsx +265 -0
- package/src/manifest/RedactedSecretsNotice.tsx +30 -0
- package/src/manifest/YamlEditor.tsx +272 -0
- package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +118 -0
- package/src/manifest/__tests__/useApplyManifest.test.tsx +237 -0
- package/src/manifest/__tests__/useEditResourceYaml.test.tsx +252 -0
- package/src/manifest/index.ts +33 -0
- package/src/manifest/useApplyManifest.ts +270 -0
- package/src/manifest/useEditResourceYaml.ts +273 -0
- package/src/mcp-server/steps/ReviewStep.tsx +2 -3
- package/src/resource-creation/templates/workflow-templates.ts +4 -4
- package/src/session/useEditSessionPrep.ts +3 -3
- package/src/settings/__tests__/useSettingsNavGroups.test.tsx +138 -0
- package/src/settings/index.ts +5 -1
- package/src/settings/settings-nav.ts +43 -0
- package/src/settings/useSettingsNavGroups.ts +81 -0
- package/src/workflow/WorkflowYamlEditor.tsx +6 -270
- package/styles.css +1 -1
- package/workflow/CanvasTransitionEdge.d.ts +1 -1
- package/workflow/WorkflowYamlEditor.d.ts +2 -42
- package/workflow/WorkflowYamlEditor.d.ts.map +1 -1
- package/workflow/WorkflowYamlEditor.js +5 -214
- package/workflow/WorkflowYamlEditor.js.map +1 -1
- package/library/ImportResourceDialog.d.ts +0 -43
- package/library/ImportResourceDialog.d.ts.map +0 -1
- package/library/ImportResourceDialog.js +0 -90
- package/library/ImportResourceDialog.js.map +0 -1
- package/library/parse-resource-yaml.d.ts +0 -63
- package/library/parse-resource-yaml.d.ts.map +0 -1
- package/library/parse-resource-yaml.js +0 -407
- package/library/parse-resource-yaml.js.map +0 -1
- package/library/serialize-resource-yaml.d.ts +0 -103
- package/library/serialize-resource-yaml.d.ts.map +0 -1
- package/library/serialize-resource-yaml.js +0 -565
- package/library/serialize-resource-yaml.js.map +0 -1
- package/library/useImportResource.d.ts +0 -84
- package/library/useImportResource.d.ts.map +0 -1
- package/library/useImportResource.js +0 -188
- package/library/useImportResource.js.map +0 -1
- package/src/library/ImportResourceDialog.tsx +0 -227
- package/src/library/parse-resource-yaml.ts +0 -630
- package/src/library/serialize-resource-yaml.ts +0 -756
- package/src/library/useImportResource.ts +0 -253
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach, beforeEach } from "vitest";
|
|
2
|
+
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
ModelPricingBaselineSchema,
|
|
6
|
+
ModelPricingBaselineStatus,
|
|
7
|
+
PricingBlockSchema,
|
|
8
|
+
} from "@stigmer/protos/ai/stigmer/billing/v1/model_pricing_baseline_pb";
|
|
9
|
+
import {
|
|
10
|
+
ModelPricingGovernanceEntrySchema,
|
|
11
|
+
type ModelPricingGovernanceEntry,
|
|
12
|
+
} from "@stigmer/protos/ai/stigmer/billing/v1/io_pb";
|
|
13
|
+
import {
|
|
14
|
+
ModelPricingOverrideSchema,
|
|
15
|
+
type ModelPricingOverride,
|
|
16
|
+
} from "@stigmer/protos/ai/stigmer/billing/v1/pricing_override_pb";
|
|
17
|
+
import type { ModelPricingBaseline } from "@stigmer/protos/ai/stigmer/billing/v1/model_pricing_baseline_pb";
|
|
18
|
+
import { useModelGovernanceView } from "../useModelGovernanceView";
|
|
19
|
+
|
|
20
|
+
// The view hook is pure composition over the two data hooks — drive it
|
|
21
|
+
// through mocks; the RPC wiring is covered by the console tests.
|
|
22
|
+
const baselinesReturn = vi.fn();
|
|
23
|
+
const governanceReturn = vi.fn();
|
|
24
|
+
vi.mock("../useModelPricingBaselines", () => ({
|
|
25
|
+
useModelPricingBaselines: (options: unknown) => {
|
|
26
|
+
lastBaselinesOptions = options;
|
|
27
|
+
return baselinesReturn();
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
vi.mock("../usePricingGovernance", () => ({
|
|
31
|
+
usePricingGovernance: () => governanceReturn(),
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
let lastBaselinesOptions: unknown = null;
|
|
35
|
+
|
|
36
|
+
function baseline(overrides: Record<string, unknown> = {}): ModelPricingBaseline {
|
|
37
|
+
return create(ModelPricingBaselineSchema, {
|
|
38
|
+
baselineId: "bl-sonnet",
|
|
39
|
+
modelId: "claude-sonnet-4-6",
|
|
40
|
+
provider: "anthropic",
|
|
41
|
+
harness: "native",
|
|
42
|
+
displayName: "Claude Sonnet",
|
|
43
|
+
status: ModelPricingBaselineStatus.pricing_baseline_active,
|
|
44
|
+
pricing: create(PricingBlockSchema, {
|
|
45
|
+
inputPriceMicrosPerMillion: 3_000_000n,
|
|
46
|
+
outputPriceMicrosPerMillion: 15_000_000n,
|
|
47
|
+
}),
|
|
48
|
+
...overrides,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function entry(overrides: Record<string, unknown> = {}): ModelPricingGovernanceEntry {
|
|
53
|
+
return create(ModelPricingGovernanceEntrySchema, {
|
|
54
|
+
modelId: "claude-sonnet-4-6",
|
|
55
|
+
provider: "anthropic",
|
|
56
|
+
harness: "native",
|
|
57
|
+
variant: "",
|
|
58
|
+
baselineInputMicrosPerMillion: 3_000_000n,
|
|
59
|
+
effectiveInputMicrosPerMillion: 3_100_000n,
|
|
60
|
+
ledgerReconcilable: true,
|
|
61
|
+
...overrides,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function override(overrides: Record<string, unknown> = {}): ModelPricingOverride {
|
|
66
|
+
return create(ModelPricingOverrideSchema, {
|
|
67
|
+
overrideId: "ovr-1",
|
|
68
|
+
modelId: "claude-sonnet-4-6",
|
|
69
|
+
variant: "",
|
|
70
|
+
...overrides,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function setData({
|
|
75
|
+
baselines = [] as readonly ModelPricingBaseline[],
|
|
76
|
+
entries = [] as readonly ModelPricingGovernanceEntry[],
|
|
77
|
+
pendingOverrides = [] as readonly ModelPricingOverride[],
|
|
78
|
+
} = {}) {
|
|
79
|
+
baselinesReturn.mockReturnValue({
|
|
80
|
+
baselines,
|
|
81
|
+
isLoading: false,
|
|
82
|
+
isRefetching: false,
|
|
83
|
+
error: null,
|
|
84
|
+
refetch: vi.fn(),
|
|
85
|
+
});
|
|
86
|
+
governanceReturn.mockReturnValue({
|
|
87
|
+
governance: { entries, pendingOverrides },
|
|
88
|
+
isLoading: false,
|
|
89
|
+
isRefetching: false,
|
|
90
|
+
error: null,
|
|
91
|
+
refetch: vi.fn(),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Renders the hook and exposes the parts under test via data attributes. */
|
|
96
|
+
function Probe() {
|
|
97
|
+
const view = useModelGovernanceView();
|
|
98
|
+
return (
|
|
99
|
+
<div>
|
|
100
|
+
<div
|
|
101
|
+
data-testid="models"
|
|
102
|
+
data-keys={view.models.map((m) => m.key).join(";")}
|
|
103
|
+
data-governance={view.models
|
|
104
|
+
.map((m) => (m.governance ? "joined" : "none"))
|
|
105
|
+
.join(";")}
|
|
106
|
+
data-variants={view.models
|
|
107
|
+
.map((m) => m.variantGovernance.map((v) => v.variant).join(","))
|
|
108
|
+
.join(";")}
|
|
109
|
+
data-history={view.models.map((m) => m.history.length).join(";")}
|
|
110
|
+
/>
|
|
111
|
+
<div
|
|
112
|
+
data-testid="signoffs"
|
|
113
|
+
data-count={view.pendingCount}
|
|
114
|
+
data-ids={view.pendingOverrides.map((o) => o.overrideId).join(";")}
|
|
115
|
+
/>
|
|
116
|
+
<div
|
|
117
|
+
data-testid="flow"
|
|
118
|
+
data-phase={view.flow.phase}
|
|
119
|
+
data-mode={view.flow.phase === "detail" ? view.flow.mode : ""}
|
|
120
|
+
data-selected={view.selected?.key ?? "none"}
|
|
121
|
+
/>
|
|
122
|
+
<input
|
|
123
|
+
aria-label="model query"
|
|
124
|
+
value={view.modelQuery}
|
|
125
|
+
onChange={(e) => view.setModelQuery(e.target.value)}
|
|
126
|
+
/>
|
|
127
|
+
<input
|
|
128
|
+
aria-label="signoff query"
|
|
129
|
+
value={view.signOffQuery}
|
|
130
|
+
onChange={(e) => view.setSignOffQuery(e.target.value)}
|
|
131
|
+
/>
|
|
132
|
+
<button onClick={() => view.openDetail("claude-sonnet-4-6|anthropic|native")}>detail</button>
|
|
133
|
+
<button onClick={() => view.openEdit()}>edit</button>
|
|
134
|
+
<button onClick={() => view.openRetire()}>retire</button>
|
|
135
|
+
<button onClick={() => view.backToDetail()}>back-detail</button>
|
|
136
|
+
<button onClick={() => view.backToList()}>back-list</button>
|
|
137
|
+
<button onClick={() => view.openCreate()}>create</button>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
beforeEach(() => {
|
|
143
|
+
setData();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
afterEach(() => {
|
|
147
|
+
cleanup();
|
|
148
|
+
baselinesReturn.mockReset();
|
|
149
|
+
governanceReturn.mockReset();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe("useModelGovernanceView — join", () => {
|
|
153
|
+
it("joins governance entries onto baselines by (modelId, provider, harness)", () => {
|
|
154
|
+
setData({
|
|
155
|
+
baselines: [baseline()],
|
|
156
|
+
entries: [entry()],
|
|
157
|
+
});
|
|
158
|
+
render(<Probe />);
|
|
159
|
+
|
|
160
|
+
const models = screen.getByTestId("models");
|
|
161
|
+
expect(models.getAttribute("data-keys")).toBe("claude-sonnet-4-6|anthropic|native");
|
|
162
|
+
expect(models.getAttribute("data-governance")).toBe("joined");
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("keeps baseline-only models with no governance state", () => {
|
|
166
|
+
setData({
|
|
167
|
+
baselines: [baseline()],
|
|
168
|
+
entries: [entry({ harness: "cursor" })], // different key — must not join
|
|
169
|
+
});
|
|
170
|
+
render(<Probe />);
|
|
171
|
+
|
|
172
|
+
expect(screen.getByTestId("models").getAttribute("data-governance")).toBe("none");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("folds variant entries into their model instead of top-level rows", () => {
|
|
176
|
+
setData({
|
|
177
|
+
baselines: [baseline()],
|
|
178
|
+
entries: [entry(), entry({ variant: "fast" })],
|
|
179
|
+
});
|
|
180
|
+
render(<Probe />);
|
|
181
|
+
|
|
182
|
+
const models = screen.getByTestId("models");
|
|
183
|
+
expect(models.getAttribute("data-keys")).toBe("claude-sonnet-4-6|anthropic|native");
|
|
184
|
+
expect(models.getAttribute("data-variants")).toBe("fast");
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("separates ACTIVE rows from their revision history", () => {
|
|
188
|
+
setData({
|
|
189
|
+
baselines: [
|
|
190
|
+
baseline(),
|
|
191
|
+
baseline({
|
|
192
|
+
baselineId: "bl-old",
|
|
193
|
+
status: ModelPricingBaselineStatus.pricing_baseline_superseded,
|
|
194
|
+
}),
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
render(<Probe />);
|
|
198
|
+
|
|
199
|
+
const models = screen.getByTestId("models");
|
|
200
|
+
expect(models.getAttribute("data-keys")).toBe("claude-sonnet-4-6|anthropic|native");
|
|
201
|
+
expect(models.getAttribute("data-history")).toBe("1");
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("always fetches with history so the detail view needs no second round-trip", () => {
|
|
205
|
+
render(<Probe />);
|
|
206
|
+
expect(lastBaselinesOptions).toEqual({ includeHistory: true });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("sorts models by display name", () => {
|
|
210
|
+
setData({
|
|
211
|
+
baselines: [
|
|
212
|
+
baseline({ baselineId: "bl-z", modelId: "z-model", displayName: "Zed" }),
|
|
213
|
+
baseline({ baselineId: "bl-a", modelId: "a-model", displayName: "Alpha" }),
|
|
214
|
+
],
|
|
215
|
+
});
|
|
216
|
+
render(<Probe />);
|
|
217
|
+
|
|
218
|
+
expect(screen.getByTestId("models").getAttribute("data-keys")).toBe(
|
|
219
|
+
"a-model|anthropic|native;z-model|anthropic|native",
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("useModelGovernanceView — search", () => {
|
|
225
|
+
it("filters models by id, display name, or provider (case-insensitive)", () => {
|
|
226
|
+
setData({
|
|
227
|
+
baselines: [
|
|
228
|
+
baseline(),
|
|
229
|
+
baseline({ baselineId: "bl-gpt", modelId: "gpt-5.6", provider: "openai", displayName: "GPT" }),
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
render(<Probe />);
|
|
233
|
+
|
|
234
|
+
fireEvent.change(screen.getByLabelText("model query"), { target: { value: "OPENAI" } });
|
|
235
|
+
expect(screen.getByTestId("models").getAttribute("data-keys")).toBe(
|
|
236
|
+
"gpt-5.6|openai|native",
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("filters sign-offs by query but keeps the unfiltered badge count", () => {
|
|
241
|
+
setData({
|
|
242
|
+
pendingOverrides: [
|
|
243
|
+
override(),
|
|
244
|
+
override({ overrideId: "ovr-2", modelId: "gpt-5.6" }),
|
|
245
|
+
],
|
|
246
|
+
});
|
|
247
|
+
render(<Probe />);
|
|
248
|
+
|
|
249
|
+
fireEvent.change(screen.getByLabelText("signoff query"), { target: { value: "gpt" } });
|
|
250
|
+
const signoffs = screen.getByTestId("signoffs");
|
|
251
|
+
expect(signoffs.getAttribute("data-ids")).toBe("ovr-2");
|
|
252
|
+
expect(signoffs.getAttribute("data-count")).toBe("2");
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe("useModelGovernanceView — flow", () => {
|
|
257
|
+
it("walks list → detail (view → edit → view → retire) → list", () => {
|
|
258
|
+
setData({ baselines: [baseline()] });
|
|
259
|
+
render(<Probe />);
|
|
260
|
+
const flow = screen.getByTestId("flow");
|
|
261
|
+
|
|
262
|
+
expect(flow.getAttribute("data-phase")).toBe("list");
|
|
263
|
+
|
|
264
|
+
fireEvent.click(screen.getByText("detail"));
|
|
265
|
+
expect(flow.getAttribute("data-phase")).toBe("detail");
|
|
266
|
+
expect(flow.getAttribute("data-mode")).toBe("view");
|
|
267
|
+
expect(flow.getAttribute("data-selected")).toBe("claude-sonnet-4-6|anthropic|native");
|
|
268
|
+
|
|
269
|
+
fireEvent.click(screen.getByText("edit"));
|
|
270
|
+
expect(flow.getAttribute("data-mode")).toBe("edit");
|
|
271
|
+
|
|
272
|
+
fireEvent.click(screen.getByText("back-detail"));
|
|
273
|
+
expect(flow.getAttribute("data-mode")).toBe("view");
|
|
274
|
+
|
|
275
|
+
fireEvent.click(screen.getByText("retire"));
|
|
276
|
+
expect(flow.getAttribute("data-mode")).toBe("retire");
|
|
277
|
+
|
|
278
|
+
fireEvent.click(screen.getByText("back-list"));
|
|
279
|
+
expect(flow.getAttribute("data-phase")).toBe("list");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("ignores edit/retire transitions outside the detail phase", () => {
|
|
283
|
+
setData({ baselines: [baseline()] });
|
|
284
|
+
render(<Probe />);
|
|
285
|
+
const flow = screen.getByTestId("flow");
|
|
286
|
+
|
|
287
|
+
fireEvent.click(screen.getByText("edit"));
|
|
288
|
+
expect(flow.getAttribute("data-phase")).toBe("list");
|
|
289
|
+
|
|
290
|
+
fireEvent.click(screen.getByText("create"));
|
|
291
|
+
fireEvent.click(screen.getByText("retire"));
|
|
292
|
+
expect(flow.getAttribute("data-phase")).toBe("create");
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("resolves selected to null when the focused model disappears (e.g. retired)", () => {
|
|
296
|
+
setData({ baselines: [baseline()] });
|
|
297
|
+
const { rerender } = render(<Probe />);
|
|
298
|
+
|
|
299
|
+
fireEvent.click(screen.getByText("detail"));
|
|
300
|
+
expect(screen.getByTestId("flow").getAttribute("data-selected")).toBe(
|
|
301
|
+
"claude-sonnet-4-6|anthropic|native",
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
setData({ baselines: [] });
|
|
305
|
+
rerender(<Probe />);
|
|
306
|
+
expect(screen.getByTestId("flow").getAttribute("data-selected")).toBe("none");
|
|
307
|
+
});
|
|
308
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Shared form primitives for the operator pricing surfaces (BaselineEditor,
|
|
7
|
+
// RetireConfirm, the console's search inputs). Internal — not exported
|
|
8
|
+
// from the billing barrel.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
/** Standard text-input styling for the pricing surfaces. */
|
|
12
|
+
export const INPUT_CLASSES = cn(
|
|
13
|
+
"w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground",
|
|
14
|
+
"placeholder:text-muted-foreground",
|
|
15
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
16
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
/** Labelled form field wrapper. */
|
|
20
|
+
export function Field({
|
|
21
|
+
label,
|
|
22
|
+
required,
|
|
23
|
+
className,
|
|
24
|
+
children,
|
|
25
|
+
}: {
|
|
26
|
+
readonly label: string;
|
|
27
|
+
readonly required?: boolean;
|
|
28
|
+
readonly className?: string;
|
|
29
|
+
readonly children: React.ReactNode;
|
|
30
|
+
}) {
|
|
31
|
+
return (
|
|
32
|
+
<label className={cn("block space-y-1", className)}>
|
|
33
|
+
<span className="text-[11px] font-medium text-muted-foreground">
|
|
34
|
+
{label}
|
|
35
|
+
{required ? " *" : ""}
|
|
36
|
+
</span>
|
|
37
|
+
{children}
|
|
38
|
+
</label>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Dollar-rate input field (decimal keypad, "$ per million tokens"). */
|
|
43
|
+
export function RateField({
|
|
44
|
+
label,
|
|
45
|
+
value,
|
|
46
|
+
placeholder,
|
|
47
|
+
disabled,
|
|
48
|
+
onChange,
|
|
49
|
+
}: {
|
|
50
|
+
readonly label: string;
|
|
51
|
+
readonly value: string;
|
|
52
|
+
readonly placeholder?: string;
|
|
53
|
+
readonly disabled: boolean;
|
|
54
|
+
readonly onChange: (value: string) => void;
|
|
55
|
+
}) {
|
|
56
|
+
return (
|
|
57
|
+
<Field label={label}>
|
|
58
|
+
<input
|
|
59
|
+
className={INPUT_CLASSES}
|
|
60
|
+
inputMode="decimal"
|
|
61
|
+
value={value}
|
|
62
|
+
onChange={(e) => onChange(e.target.value)}
|
|
63
|
+
placeholder={placeholder ?? "0.00"}
|
|
64
|
+
disabled={disabled}
|
|
65
|
+
/>
|
|
66
|
+
</Field>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
import type { ModelPricingOverride } from "@stigmer/protos/ai/stigmer/billing/v1/pricing_override_pb";
|
|
5
|
+
import { Button } from "../button/index.js";
|
|
6
|
+
import { RATE_FIELD_LABELS, formatDeltaBp, formatRate } from "./pricing-format.js";
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Shared display primitives for the operator pricing surfaces. Internal —
|
|
10
|
+
// not exported from the billing barrel.
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* One PENDING_SIGNOFF pricing override with approve/reject actions and
|
|
15
|
+
* its ledger provenance (what was observed, against what, over which
|
|
16
|
+
* window) so the operator decides from evidence, not a bare number.
|
|
17
|
+
*/
|
|
18
|
+
export function PendingOverrideCard({
|
|
19
|
+
override,
|
|
20
|
+
isSubmitting,
|
|
21
|
+
onDecide,
|
|
22
|
+
}: {
|
|
23
|
+
readonly override: ModelPricingOverride;
|
|
24
|
+
readonly isSubmitting: boolean;
|
|
25
|
+
readonly onDecide: (overrideId: string, approve: boolean) => void;
|
|
26
|
+
}) {
|
|
27
|
+
const provenance = override.provenance;
|
|
28
|
+
return (
|
|
29
|
+
<div className="rounded-lg border border-border bg-card px-3 py-2">
|
|
30
|
+
<div className="flex items-center justify-between gap-2">
|
|
31
|
+
<div className="min-w-0">
|
|
32
|
+
<p className="truncate text-xs font-medium text-foreground">
|
|
33
|
+
{override.modelId}
|
|
34
|
+
{override.variant ? ` (${override.variant})` : ""}
|
|
35
|
+
{" · "}
|
|
36
|
+
{RATE_FIELD_LABELS[override.rateField] ?? "Rate"}
|
|
37
|
+
</p>
|
|
38
|
+
<p className="text-[11px] text-muted-foreground">
|
|
39
|
+
{provenance ? (
|
|
40
|
+
<>
|
|
41
|
+
Ledger observed {formatRate(provenance.observedRateMicrosPerMillion)} vs
|
|
42
|
+
effective {formatRate(provenance.effectiveRateAtDerivationMicrosPerMillion)}
|
|
43
|
+
{" "}({formatDeltaBp(provenance.deltaBasisPoints)}) over{" "}
|
|
44
|
+
{provenance.windowFrom}..{provenance.windowTo}
|
|
45
|
+
</>
|
|
46
|
+
) : (
|
|
47
|
+
<>Proposed rate {formatRate(override.rateMicrosPerMillion)}</>
|
|
48
|
+
)}
|
|
49
|
+
</p>
|
|
50
|
+
</div>
|
|
51
|
+
<div className="flex shrink-0 gap-2">
|
|
52
|
+
<Button
|
|
53
|
+
size="sm"
|
|
54
|
+
disabled={isSubmitting}
|
|
55
|
+
onClick={() => onDecide(override.overrideId, true)}
|
|
56
|
+
>
|
|
57
|
+
Approve
|
|
58
|
+
</Button>
|
|
59
|
+
<Button
|
|
60
|
+
size="sm"
|
|
61
|
+
variant="outline"
|
|
62
|
+
disabled={isSubmitting}
|
|
63
|
+
onClick={() => onDecide(override.overrideId, false)}
|
|
64
|
+
>
|
|
65
|
+
Reject
|
|
66
|
+
</Button>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Effective rate; when an override moved it, the baseline shows
|
|
75
|
+
* struck-through. Pass `role="cell"` when rendered inside an ARIA
|
|
76
|
+
* table row; leave unset inside interactive list rows (a `<button>`
|
|
77
|
+
* row cannot contain table cells).
|
|
78
|
+
*/
|
|
79
|
+
export function RateCell({
|
|
80
|
+
baseline,
|
|
81
|
+
effective,
|
|
82
|
+
role,
|
|
83
|
+
}: {
|
|
84
|
+
readonly baseline: bigint;
|
|
85
|
+
readonly effective: bigint;
|
|
86
|
+
readonly role?: "cell";
|
|
87
|
+
}) {
|
|
88
|
+
const overridden = baseline !== effective;
|
|
89
|
+
return (
|
|
90
|
+
<span role={role} className="text-right text-foreground">
|
|
91
|
+
{overridden && (
|
|
92
|
+
<span className="mr-1 text-[10px] text-muted-foreground line-through">
|
|
93
|
+
{formatRate(baseline)}
|
|
94
|
+
</span>
|
|
95
|
+
)}
|
|
96
|
+
{formatRate(effective)}
|
|
97
|
+
</span>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Governance state chip: how this entry's rates are governed —
|
|
103
|
+
* ledger-verified (reconcilable, no overrides), ledger-corrected
|
|
104
|
+
* (reconcilable with active overrides), or manually governed (no
|
|
105
|
+
* external ledger can verify it).
|
|
106
|
+
*/
|
|
107
|
+
export function GovernanceBadge({
|
|
108
|
+
ledgerReconcilable,
|
|
109
|
+
hasOverrides,
|
|
110
|
+
}: {
|
|
111
|
+
readonly ledgerReconcilable: boolean;
|
|
112
|
+
readonly hasOverrides: boolean;
|
|
113
|
+
}) {
|
|
114
|
+
if (!ledgerReconcilable) {
|
|
115
|
+
return (
|
|
116
|
+
<span className="rounded bg-muted-subtle px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
|
117
|
+
Manually governed
|
|
118
|
+
</span>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return (
|
|
122
|
+
<span
|
|
123
|
+
className={cn(
|
|
124
|
+
"rounded px-1.5 py-0.5 text-[10px] font-medium",
|
|
125
|
+
hasOverrides
|
|
126
|
+
? "bg-accent text-primary"
|
|
127
|
+
: "bg-muted-subtle text-muted-foreground",
|
|
128
|
+
)}
|
|
129
|
+
>
|
|
130
|
+
{hasOverrides ? "Ledger-corrected" : "Ledger-verified"}
|
|
131
|
+
</span>
|
|
132
|
+
);
|
|
133
|
+
}
|
package/src/billing/index.ts
CHANGED
|
@@ -7,6 +7,19 @@ export { useBillingUsageReport } from "./useBillingUsageReport.js";
|
|
|
7
7
|
export type { UseBillingUsageReportReturn } from "./useBillingUsageReport.js";
|
|
8
8
|
export { useCustomerModelPricing } from "./useCustomerModelPricing.js";
|
|
9
9
|
export type { UseCustomerModelPricingReturn } from "./useCustomerModelPricing.js";
|
|
10
|
+
export { usePricingGovernance } from "./usePricingGovernance.js";
|
|
11
|
+
export type { UsePricingGovernanceReturn } from "./usePricingGovernance.js";
|
|
12
|
+
export { useModelPricingBaselines } from "./useModelPricingBaselines.js";
|
|
13
|
+
export type {
|
|
14
|
+
UseModelPricingBaselinesOptions,
|
|
15
|
+
UseModelPricingBaselinesReturn,
|
|
16
|
+
} from "./useModelPricingBaselines.js";
|
|
17
|
+
export { useModelGovernanceView } from "./useModelGovernanceView.js";
|
|
18
|
+
export type {
|
|
19
|
+
GovernanceFlow,
|
|
20
|
+
ModelGovernanceRow,
|
|
21
|
+
UseModelGovernanceViewReturn,
|
|
22
|
+
} from "./useModelGovernanceView.js";
|
|
10
23
|
|
|
11
24
|
// Behavior hooks
|
|
12
25
|
export { useCreateCheckoutSession } from "./useCreateCheckoutSession.js";
|
|
@@ -21,6 +34,21 @@ export type {
|
|
|
21
34
|
SetAutoRechargeConfigInput,
|
|
22
35
|
UseSetAutoRechargeConfigReturn,
|
|
23
36
|
} from "./useSetAutoRechargeConfig.js";
|
|
37
|
+
export { useDecidePricingOverride } from "./useDecidePricingOverride.js";
|
|
38
|
+
export type {
|
|
39
|
+
DecidePricingOverrideInput,
|
|
40
|
+
UseDecidePricingOverrideReturn,
|
|
41
|
+
} from "./useDecidePricingOverride.js";
|
|
42
|
+
export { useUpsertModelPricingBaseline } from "./useUpsertModelPricingBaseline.js";
|
|
43
|
+
export type {
|
|
44
|
+
UpsertModelPricingBaselineInput,
|
|
45
|
+
UseUpsertModelPricingBaselineReturn,
|
|
46
|
+
} from "./useUpsertModelPricingBaseline.js";
|
|
47
|
+
export { useRetireModelPricingBaseline } from "./useRetireModelPricingBaseline.js";
|
|
48
|
+
export type {
|
|
49
|
+
RetireModelPricingBaselineInput,
|
|
50
|
+
UseRetireModelPricingBaselineReturn,
|
|
51
|
+
} from "./useRetireModelPricingBaseline.js";
|
|
24
52
|
|
|
25
53
|
// Styled components
|
|
26
54
|
export { BillingSection } from "./BillingSection.js";
|
|
@@ -37,6 +65,15 @@ export { CreditLedgerTable } from "./CreditLedgerTable.js";
|
|
|
37
65
|
export type { CreditLedgerTableProps } from "./CreditLedgerTable.js";
|
|
38
66
|
export { LowBalanceBanner } from "./LowBalanceBanner.js";
|
|
39
67
|
export type { LowBalanceBannerProps } from "./LowBalanceBanner.js";
|
|
68
|
+
export { PricingGovernancePanel } from "./PricingGovernancePanel.js";
|
|
69
|
+
export type { PricingGovernancePanelProps } from "./PricingGovernancePanel.js";
|
|
70
|
+
export { ModelCatalogPanel } from "./ModelCatalogPanel.js";
|
|
71
|
+
export type { ModelCatalogPanelProps } from "./ModelCatalogPanel.js";
|
|
72
|
+
export { PricingGovernanceConsole } from "./PricingGovernanceConsole.js";
|
|
73
|
+
export type {
|
|
74
|
+
PricingGovernanceConsoleProps,
|
|
75
|
+
PricingGovernanceTab,
|
|
76
|
+
} from "./PricingGovernanceConsole.js";
|
|
40
77
|
|
|
41
78
|
// Credit pack catalog and formatting utilities
|
|
42
79
|
export { CREDIT_PACKS, formatPackPrice, formatCreditCount } from "./credit-packs.js";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PricingRateField } from "@stigmer/protos/ai/stigmer/billing/v1/pricing_override_pb";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Shared money/label helpers for the platform-operator pricing surfaces
|
|
5
|
+
// (PricingGovernanceConsole and the panels it grew out of). Internal —
|
|
6
|
+
// not exported from the billing barrel.
|
|
7
|
+
//
|
|
8
|
+
// The UI works in dollars-per-million tokens; the protos store integer
|
|
9
|
+
// micro-USD. Registry prices carry at most 4 decimal places, so the
|
|
10
|
+
// round-trip through Math.round is exact.
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
// BigInt literals (0n) require an ES2020 target, which not every consuming
|
|
14
|
+
// app's tsconfig guarantees — the constructor form is target-agnostic.
|
|
15
|
+
export const ZERO = BigInt(0);
|
|
16
|
+
|
|
17
|
+
/** Human labels for {@link PricingRateField} values. */
|
|
18
|
+
export const RATE_FIELD_LABELS: Record<number, string> = {
|
|
19
|
+
[PricingRateField.input]: "Input",
|
|
20
|
+
[PricingRateField.output]: "Output",
|
|
21
|
+
[PricingRateField.cache_write]: "Cache write",
|
|
22
|
+
[PricingRateField.cache_read]: "Cache read",
|
|
23
|
+
[PricingRateField.cursor_token_rate]: "Cursor token rate",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** Micro-USD per million tokens → "$X.XX/M" (raw provider rate). */
|
|
27
|
+
export function formatRate(microsPerMillion: bigint): string {
|
|
28
|
+
const dollars = Number(microsPerMillion) / 1_000_000;
|
|
29
|
+
return `$${dollars.toFixed(dollars < 1 ? 4 : 2)}/M`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Basis points → signed percentage, e.g. 530n → "+5.30%". */
|
|
33
|
+
export function formatDeltaBp(deltaBp: bigint): string {
|
|
34
|
+
const pct = Number(deltaBp) / 100;
|
|
35
|
+
return `${pct > 0 ? "+" : ""}${pct.toFixed(2)}%`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Micro-USD → editable dollar string, trailing zeros trimmed ("0.075"). */
|
|
39
|
+
export function microsToDollarString(micros: bigint): string {
|
|
40
|
+
if (micros === ZERO) return "0";
|
|
41
|
+
const dollars = Number(micros) / 1_000_000;
|
|
42
|
+
// Trim trailing zeros without losing sub-cent precision (e.g. 0.075).
|
|
43
|
+
return String(parseFloat(dollars.toFixed(6)));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Parse a dollar input; returns null for anything that is not a finite, non-negative number. */
|
|
47
|
+
export function dollarsToMicros(value: string): bigint | null {
|
|
48
|
+
const trimmed = value.trim();
|
|
49
|
+
if (trimmed === "") return null;
|
|
50
|
+
const parsed = Number(trimmed);
|
|
51
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
52
|
+
return BigInt(Math.round(parsed * 1_000_000));
|
|
53
|
+
}
|