@stigmer/react 3.2.2 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +6 -3
- package/agent/AgentDetailView.js.map +1 -1
- 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/execution/index.d.ts +1 -2
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +0 -1
- package/execution/index.js.map +1 -1
- package/execution/useLiveAgentExecution.d.ts +17 -1
- package/execution/useLiveAgentExecution.d.ts.map +1 -1
- package/execution/useLiveAgentExecution.js +19 -4
- package/execution/useLiveAgentExecution.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 +16 -10
- package/index.d.ts.map +1 -1
- package/index.js +16 -5
- package/index.js.map +1 -1
- package/internal/useInViewport.d.ts +24 -0
- package/internal/useInViewport.d.ts.map +1 -0
- package/internal/useInViewport.js +49 -0
- package/internal/useInViewport.js.map +1 -0
- package/library/VisibilitySelector.d.ts +22 -6
- package/library/VisibilitySelector.d.ts.map +1 -1
- package/library/VisibilitySelector.js +12 -4
- package/library/VisibilitySelector.js.map +1 -1
- package/library/index.d.ts +1 -8
- 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/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +4 -3
- package/mcp-server/McpServerDetailView.js.map +1 -1
- 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/SessionViewer.js +8 -1
- package/session/SessionViewer.js.map +1 -1
- package/session/audience.d.ts +6 -1
- package/session/audience.d.ts.map +1 -1
- 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/skill/SkillDetailView.d.ts.map +1 -1
- package/skill/SkillDetailView.js +4 -3
- package/skill/SkillDetailView.js.map +1 -1
- package/src/access/__tests__/useManageAccess.test.tsx +104 -0
- package/src/agent/AgentDetailView.tsx +9 -3
- 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/execution/__tests__/useLiveAgentExecution.test.tsx +125 -0
- package/src/execution/index.ts +4 -7
- package/src/execution/useLiveAgentExecution.ts +41 -3
- 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 +167 -18
- package/src/internal/__tests__/useInViewport.test.tsx +115 -0
- package/src/internal/useInViewport.ts +63 -0
- package/src/library/VisibilitySelector.tsx +50 -9
- package/src/library/__tests__/VisibilitySelector.test.tsx +38 -0
- package/src/library/index.ts +4 -21
- 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/McpServerDetailView.tsx +7 -3
- package/src/mcp-server/steps/ReviewStep.tsx +2 -3
- package/src/resource-creation/templates/workflow-templates.ts +4 -4
- package/src/session/SessionViewer.tsx +7 -1
- package/src/session/__tests__/audienceWiring.test.tsx +31 -1
- package/src/session/audience.ts +6 -1
- 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/skill/SkillDetailView.tsx +7 -3
- package/src/workflow/WorkflowAgentCallTranscript.tsx +279 -0
- package/src/workflow/WorkflowDetailView.tsx +7 -3
- package/src/workflow/WorkflowExecutionViewer.tsx +20 -77
- package/src/workflow/WorkflowTaskApprovalSummary.tsx +45 -8
- package/src/workflow/WorkflowYamlEditor.tsx +6 -270
- package/src/workflow/__tests__/WorkflowAgentCallTranscript.liveregion.test.tsx +124 -0
- package/src/workflow/__tests__/{WorkflowAgentExecutionDocument.test.tsx → WorkflowAgentCallTranscript.test.tsx} +146 -121
- package/src/workflow/__tests__/WorkflowExecutionViewer.approvals.test.tsx +81 -220
- package/src/workflow/__tests__/WorkflowExecutionViewer.reconciliation.test.tsx +17 -16
- package/src/workflow/__tests__/WorkflowTaskApprovalSummary.test.tsx +52 -2
- package/src/workflow/__tests__/WorkflowTaskThread.test.tsx +168 -185
- package/src/workflow/__tests__/agent-call-live-experience.test.ts +4 -4
- package/src/workflow/__tests__/task-approval.test.ts +119 -0
- package/src/workflow/__tests__/task-presentation.test.ts +35 -1
- package/src/workflow/__tests__/useWorkflowExecutionPanel.test.ts +0 -57
- package/src/workflow/index.ts +6 -3
- package/src/workflow/task-detail/index.ts +3 -0
- package/src/workflow/task-detail/task-approval.ts +95 -1
- package/src/workflow/thread/WorkflowTaskThread.tsx +96 -252
- package/src/workflow/thread/task-presentation.ts +8 -2
- package/src/workflow/useWorkflowExecutionPanel.ts +0 -47
- package/styles.css +1 -1
- package/workflow/CanvasTransitionEdge.d.ts +1 -1
- package/workflow/WorkflowAgentCallTranscript.d.ts +87 -0
- package/workflow/WorkflowAgentCallTranscript.d.ts.map +1 -0
- package/workflow/WorkflowAgentCallTranscript.js +98 -0
- package/workflow/WorkflowAgentCallTranscript.js.map +1 -0
- package/workflow/WorkflowDetailView.d.ts.map +1 -1
- package/workflow/WorkflowDetailView.js +4 -3
- package/workflow/WorkflowDetailView.js.map +1 -1
- package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
- package/workflow/WorkflowExecutionViewer.js +23 -52
- package/workflow/WorkflowExecutionViewer.js.map +1 -1
- package/workflow/WorkflowTaskApprovalSummary.d.ts +1 -1
- package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
- package/workflow/WorkflowTaskApprovalSummary.js +18 -1
- package/workflow/WorkflowTaskApprovalSummary.js.map +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/workflow/index.d.ts +2 -2
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +2 -2
- package/workflow/index.js.map +1 -1
- package/workflow/task-detail/index.d.ts +1 -1
- package/workflow/task-detail/index.d.ts.map +1 -1
- package/workflow/task-detail/index.js +1 -1
- package/workflow/task-detail/index.js.map +1 -1
- package/workflow/task-detail/task-approval.d.ts +44 -1
- package/workflow/task-detail/task-approval.d.ts.map +1 -1
- package/workflow/task-detail/task-approval.js +47 -0
- package/workflow/task-detail/task-approval.js.map +1 -1
- package/workflow/thread/WorkflowTaskThread.d.ts +17 -25
- package/workflow/thread/WorkflowTaskThread.d.ts.map +1 -1
- package/workflow/thread/WorkflowTaskThread.js +60 -105
- package/workflow/thread/WorkflowTaskThread.js.map +1 -1
- package/workflow/thread/task-presentation.d.ts.map +1 -1
- package/workflow/thread/task-presentation.js +7 -2
- package/workflow/thread/task-presentation.js.map +1 -1
- package/workflow/useWorkflowExecutionPanel.d.ts +0 -12
- package/workflow/useWorkflowExecutionPanel.d.ts.map +1 -1
- package/workflow/useWorkflowExecutionPanel.js +0 -12
- package/workflow/useWorkflowExecutionPanel.js.map +1 -1
- package/execution/agent-execution-document.d.ts +0 -31
- package/execution/agent-execution-document.d.ts.map +0 -1
- package/execution/agent-execution-document.js +0 -48
- package/execution/agent-execution-document.js.map +0 -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/execution/__tests__/agent-execution-document.test.ts +0 -45
- package/src/execution/agent-execution-document.ts +0 -54
- 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
- package/src/workflow/WorkflowAgentExecutionDocument.tsx +0 -283
- package/workflow/WorkflowAgentExecutionDocument.d.ts +0 -79
- package/workflow/WorkflowAgentExecutionDocument.d.ts.map +0 -1
- package/workflow/WorkflowAgentExecutionDocument.js +0 -87
- package/workflow/WorkflowAgentExecutionDocument.js.map +0 -1
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
+
import { cleanup, render, screen, waitFor } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import { create } from "@bufbuild/protobuf";
|
|
6
|
+
import { timestampFromDate } from "@bufbuild/protobuf/wkt";
|
|
7
|
+
import { StigmerError } from "@stigmer/sdk";
|
|
8
|
+
import {
|
|
9
|
+
CursorAccountSchema,
|
|
10
|
+
CursorMemberKeySchema,
|
|
11
|
+
CursorTeamMemberSchema,
|
|
12
|
+
CursorMemberSpendSchema,
|
|
13
|
+
CursorAccountSyncSnapshotSchema,
|
|
14
|
+
} from "@stigmer/protos/ai/stigmer/platform/cursoraccount/v1/cursor_account_pb";
|
|
15
|
+
import {
|
|
16
|
+
CursorAccountSummarySchema,
|
|
17
|
+
CursorAccountViewSchema,
|
|
18
|
+
CursorMemberKeyViewSchema,
|
|
19
|
+
CursorMemberKeyState,
|
|
20
|
+
} from "@stigmer/protos/ai/stigmer/platform/cursoraccount/v1/io_pb";
|
|
21
|
+
import { StigmerContext } from "../../context";
|
|
22
|
+
import { FetchCacheContext } from "../../internal/FetchCacheProvider";
|
|
23
|
+
import { CursorAccountsConsole } from "../CursorAccountsConsole";
|
|
24
|
+
|
|
25
|
+
interface MockCursorAccounts {
|
|
26
|
+
listAccounts: ReturnType<typeof vi.fn>;
|
|
27
|
+
getAccountView: ReturnType<typeof vi.fn>;
|
|
28
|
+
upsertAccount: ReturnType<typeof vi.fn>;
|
|
29
|
+
deleteAccount: ReturnType<typeof vi.fn>;
|
|
30
|
+
addMemberKey: ReturnType<typeof vi.fn>;
|
|
31
|
+
removeMemberKey: ReturnType<typeof vi.fn>;
|
|
32
|
+
setMemberKeyEnabled: ReturnType<typeof vi.fn>;
|
|
33
|
+
syncAccount: ReturnType<typeof vi.fn>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function createMockStigmer(cursorAccounts: Partial<MockCursorAccounts> = {}) {
|
|
37
|
+
return {
|
|
38
|
+
cursorAccounts: {
|
|
39
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [] }),
|
|
40
|
+
getAccountView: vi.fn(),
|
|
41
|
+
upsertAccount: vi.fn(),
|
|
42
|
+
deleteAccount: vi.fn(),
|
|
43
|
+
addMemberKey: vi.fn(),
|
|
44
|
+
removeMemberKey: vi.fn(),
|
|
45
|
+
setMemberKeyEnabled: vi.fn(),
|
|
46
|
+
syncAccount: vi.fn(),
|
|
47
|
+
...cursorAccounts,
|
|
48
|
+
},
|
|
49
|
+
} as never;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function wrapper(client: unknown) {
|
|
53
|
+
return function Wrapper({ children }: { children: ReactNode }) {
|
|
54
|
+
return (
|
|
55
|
+
<FetchCacheContext.Provider value={null}>
|
|
56
|
+
<StigmerContext.Provider value={client as never}>
|
|
57
|
+
{children}
|
|
58
|
+
</StigmerContext.Provider>
|
|
59
|
+
</FetchCacheContext.Provider>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function scenarAccount(overrides: Record<string, unknown> = {}) {
|
|
65
|
+
return create(CursorAccountSchema, {
|
|
66
|
+
accountId: "acc-1",
|
|
67
|
+
displayName: "scenar team",
|
|
68
|
+
adminApiKey: "***REDACTED***",
|
|
69
|
+
enabled: true,
|
|
70
|
+
orgIds: ["org-a"],
|
|
71
|
+
memberKeys: [
|
|
72
|
+
create(CursorMemberKeySchema, {
|
|
73
|
+
keyId: "k-1",
|
|
74
|
+
apiKey: "***REDACTED***",
|
|
75
|
+
boundEmail: "zane@scenar.ai",
|
|
76
|
+
cursorKeyName: "stigmer-prod",
|
|
77
|
+
enabled: true,
|
|
78
|
+
}),
|
|
79
|
+
],
|
|
80
|
+
...overrides,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function scenarSummary() {
|
|
85
|
+
return create(CursorAccountSummarySchema, {
|
|
86
|
+
account: scenarAccount(),
|
|
87
|
+
enabledKeyCount: 1,
|
|
88
|
+
lastSyncedAt: timestampFromDate(new Date("2026-07-22T12:00:00Z")),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function scenarView() {
|
|
93
|
+
return create(CursorAccountViewSchema, {
|
|
94
|
+
account: scenarAccount(),
|
|
95
|
+
snapshot: create(CursorAccountSyncSnapshotSchema, {
|
|
96
|
+
accountId: "acc-1",
|
|
97
|
+
syncedAt: timestampFromDate(new Date("2026-07-22T12:00:00Z")),
|
|
98
|
+
members: [
|
|
99
|
+
create(CursorTeamMemberSchema, {
|
|
100
|
+
userId: "u1",
|
|
101
|
+
email: "zane@scenar.ai",
|
|
102
|
+
name: "Zane S",
|
|
103
|
+
role: "owner",
|
|
104
|
+
}),
|
|
105
|
+
create(CursorTeamMemberSchema, {
|
|
106
|
+
userId: "u2",
|
|
107
|
+
email: "uncovered@scenar.ai",
|
|
108
|
+
name: "Uncovered U",
|
|
109
|
+
role: "member",
|
|
110
|
+
}),
|
|
111
|
+
],
|
|
112
|
+
spend: [
|
|
113
|
+
create(CursorMemberSpendSchema, {
|
|
114
|
+
userId: "u1",
|
|
115
|
+
email: "zane@scenar.ai",
|
|
116
|
+
includedSpendUsdMicros: 169342n,
|
|
117
|
+
}),
|
|
118
|
+
],
|
|
119
|
+
}),
|
|
120
|
+
keyViews: [
|
|
121
|
+
create(CursorMemberKeyViewSchema, {
|
|
122
|
+
key: scenarAccount().memberKeys[0],
|
|
123
|
+
state: CursorMemberKeyState.member_key_active,
|
|
124
|
+
spend: create(CursorMemberSpendSchema, {
|
|
125
|
+
userId: "u1",
|
|
126
|
+
email: "zane@scenar.ai",
|
|
127
|
+
includedSpendUsdMicros: 169342n,
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
130
|
+
],
|
|
131
|
+
membersWithoutKeys: [
|
|
132
|
+
create(CursorTeamMemberSchema, {
|
|
133
|
+
userId: "u2",
|
|
134
|
+
email: "uncovered@scenar.ai",
|
|
135
|
+
name: "Uncovered U",
|
|
136
|
+
role: "member",
|
|
137
|
+
}),
|
|
138
|
+
],
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
afterEach(() => {
|
|
143
|
+
cleanup();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe("CursorAccountsConsole", () => {
|
|
147
|
+
it("renders the empty state with onboarding guidance", async () => {
|
|
148
|
+
const client = createMockStigmer();
|
|
149
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
150
|
+
|
|
151
|
+
await waitFor(() =>
|
|
152
|
+
expect(screen.getByText(/No Cursor accounts yet/)).toBeTruthy(),
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("lists accounts with routability at a glance", async () => {
|
|
157
|
+
const notRoutable = create(CursorAccountSummarySchema, {
|
|
158
|
+
account: scenarAccount({
|
|
159
|
+
accountId: "acc-2",
|
|
160
|
+
displayName: "empty team",
|
|
161
|
+
memberKeys: [],
|
|
162
|
+
orgIds: [],
|
|
163
|
+
isPlatformDefault: true,
|
|
164
|
+
}),
|
|
165
|
+
enabledKeyCount: 0,
|
|
166
|
+
});
|
|
167
|
+
const client = createMockStigmer({
|
|
168
|
+
listAccounts: vi
|
|
169
|
+
.fn()
|
|
170
|
+
.mockResolvedValue({ accounts: [scenarSummary(), notRoutable] }),
|
|
171
|
+
});
|
|
172
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
173
|
+
|
|
174
|
+
await waitFor(() => expect(screen.getByText("scenar team")).toBeTruthy());
|
|
175
|
+
expect(screen.getByText("empty team")).toBeTruthy();
|
|
176
|
+
expect(screen.getByText("Not routable")).toBeTruthy();
|
|
177
|
+
expect(screen.getByText("platform default")).toBeTruthy();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("shows the designed access notice on PERMISSION_DENIED", async () => {
|
|
181
|
+
const client = createMockStigmer({
|
|
182
|
+
listAccounts: vi
|
|
183
|
+
.fn()
|
|
184
|
+
.mockRejectedValue(
|
|
185
|
+
new StigmerError("permission-denied", "only platform operators", 7),
|
|
186
|
+
),
|
|
187
|
+
});
|
|
188
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
189
|
+
|
|
190
|
+
await waitFor(() =>
|
|
191
|
+
expect(screen.getByText("Platform operator access required")).toBeTruthy(),
|
|
192
|
+
);
|
|
193
|
+
expect(screen.queryByText(/only platform operators/)).toBeNull();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("opens the detail view with key coverage, spend, and gap list", async () => {
|
|
197
|
+
const client = createMockStigmer({
|
|
198
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [scenarSummary()] }),
|
|
199
|
+
getAccountView: vi.fn().mockResolvedValue(scenarView()),
|
|
200
|
+
});
|
|
201
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
202
|
+
|
|
203
|
+
await waitFor(() => expect(screen.getByText("scenar team")).toBeTruthy());
|
|
204
|
+
await userEvent.click(screen.getByRole("button", { name: /scenar team/ }));
|
|
205
|
+
|
|
206
|
+
await waitFor(() => expect(screen.getByText(/zane@scenar\.ai/)).toBeTruthy());
|
|
207
|
+
// Spend joined to the key row: 169342 micro-USD = $0.17.
|
|
208
|
+
expect(screen.getByText(/\$0\.17 this cycle/)).toBeTruthy();
|
|
209
|
+
// Coverage gap: the active member with no key, by name and email.
|
|
210
|
+
expect(screen.getByText(/uncovered@scenar\.ai/)).toBeTruthy();
|
|
211
|
+
expect(screen.getByText("Active")).toBeTruthy();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("adds a member key and refreshes both views", async () => {
|
|
215
|
+
const addMemberKey = vi.fn().mockResolvedValue(scenarAccount());
|
|
216
|
+
const client = createMockStigmer({
|
|
217
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [scenarSummary()] }),
|
|
218
|
+
getAccountView: vi.fn().mockResolvedValue(scenarView()),
|
|
219
|
+
addMemberKey,
|
|
220
|
+
});
|
|
221
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
222
|
+
|
|
223
|
+
await waitFor(() => expect(screen.getByText("scenar team")).toBeTruthy());
|
|
224
|
+
await userEvent.click(screen.getByRole("button", { name: /scenar team/ }));
|
|
225
|
+
await waitFor(() =>
|
|
226
|
+
expect(screen.getByLabelText(/User-scoped API key/)).toBeTruthy(),
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
await userEvent.type(
|
|
230
|
+
screen.getByLabelText(/User-scoped API key/),
|
|
231
|
+
"key_user_plain",
|
|
232
|
+
);
|
|
233
|
+
await userEvent.click(screen.getByRole("button", { name: "Add key" }));
|
|
234
|
+
|
|
235
|
+
await waitFor(() =>
|
|
236
|
+
expect(addMemberKey).toHaveBeenCalledWith({
|
|
237
|
+
accountId: "acc-1",
|
|
238
|
+
apiKey: "key_user_plain",
|
|
239
|
+
label: undefined,
|
|
240
|
+
}),
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it("surfaces Cursor's own explanation when a wrong key class is added", async () => {
|
|
245
|
+
const client = createMockStigmer({
|
|
246
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [scenarSummary()] }),
|
|
247
|
+
getAccountView: vi.fn().mockResolvedValue(scenarView()),
|
|
248
|
+
addMemberKey: vi
|
|
249
|
+
.fn()
|
|
250
|
+
.mockRejectedValue(
|
|
251
|
+
new StigmerError(
|
|
252
|
+
"invalid-argument",
|
|
253
|
+
"Key rejected by Cursor — This is a team API key from the dashboard's Team API Keys tab",
|
|
254
|
+
3,
|
|
255
|
+
),
|
|
256
|
+
),
|
|
257
|
+
});
|
|
258
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
259
|
+
|
|
260
|
+
await waitFor(() => expect(screen.getByText("scenar team")).toBeTruthy());
|
|
261
|
+
await userEvent.click(screen.getByRole("button", { name: /scenar team/ }));
|
|
262
|
+
await waitFor(() =>
|
|
263
|
+
expect(screen.getByLabelText(/User-scoped API key/)).toBeTruthy(),
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
await userEvent.type(screen.getByLabelText(/User-scoped API key/), "wrong-class");
|
|
267
|
+
await userEvent.click(screen.getByRole("button", { name: "Add key" }));
|
|
268
|
+
|
|
269
|
+
await waitFor(() =>
|
|
270
|
+
expect(screen.getByText(/Team API Keys tab/i)).toBeTruthy(),
|
|
271
|
+
);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("creates an account through the editor", async () => {
|
|
275
|
+
const upsertAccount = vi.fn().mockResolvedValue(scenarAccount());
|
|
276
|
+
const client = createMockStigmer({
|
|
277
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [] }),
|
|
278
|
+
upsertAccount,
|
|
279
|
+
});
|
|
280
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
281
|
+
|
|
282
|
+
await waitFor(() =>
|
|
283
|
+
expect(screen.getByRole("button", { name: "Add account" })).toBeTruthy(),
|
|
284
|
+
);
|
|
285
|
+
await userEvent.click(screen.getByRole("button", { name: "Add account" }));
|
|
286
|
+
|
|
287
|
+
await userEvent.type(screen.getByLabelText(/Display name/), "new team");
|
|
288
|
+
await userEvent.type(
|
|
289
|
+
screen.getByLabelText(/Team Admin API key/),
|
|
290
|
+
"key_admin_plain",
|
|
291
|
+
);
|
|
292
|
+
await userEvent.type(
|
|
293
|
+
screen.getByLabelText(/Assigned organization ids/),
|
|
294
|
+
"org-x org-y",
|
|
295
|
+
);
|
|
296
|
+
await userEvent.click(screen.getByRole("button", { name: "Create account" }));
|
|
297
|
+
|
|
298
|
+
await waitFor(() => expect(upsertAccount).toHaveBeenCalledTimes(1));
|
|
299
|
+
const submitted = upsertAccount.mock.calls[0][0].account;
|
|
300
|
+
expect(submitted.displayName).toBe("new team");
|
|
301
|
+
expect(submitted.adminApiKey).toBe("key_admin_plain");
|
|
302
|
+
expect(submitted.orgIds).toEqual(["org-x", "org-y"]);
|
|
303
|
+
expect(submitted.enabled).toBe(true);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it("bulk-imports keys one per line, keeping failed lines for retry", async () => {
|
|
307
|
+
const accountWithNewKey = scenarAccount({
|
|
308
|
+
memberKeys: [
|
|
309
|
+
scenarAccount().memberKeys[0],
|
|
310
|
+
create(CursorMemberKeySchema, {
|
|
311
|
+
keyId: "k-new",
|
|
312
|
+
apiKey: "***REDACTED***",
|
|
313
|
+
boundEmail: "morgan@scenar.ai",
|
|
314
|
+
enabled: true,
|
|
315
|
+
}),
|
|
316
|
+
],
|
|
317
|
+
});
|
|
318
|
+
const addMemberKey = vi
|
|
319
|
+
.fn()
|
|
320
|
+
.mockResolvedValueOnce(accountWithNewKey)
|
|
321
|
+
.mockRejectedValueOnce(
|
|
322
|
+
new StigmerError("invalid-argument", "Key rejected by Cursor", 3),
|
|
323
|
+
);
|
|
324
|
+
const syncAccount = vi.fn().mockResolvedValue(scenarView());
|
|
325
|
+
const client = createMockStigmer({
|
|
326
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [scenarSummary()] }),
|
|
327
|
+
getAccountView: vi.fn().mockResolvedValue(scenarView()),
|
|
328
|
+
addMemberKey,
|
|
329
|
+
syncAccount,
|
|
330
|
+
});
|
|
331
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
332
|
+
|
|
333
|
+
await waitFor(() => expect(screen.getByText("scenar team")).toBeTruthy());
|
|
334
|
+
await userEvent.click(screen.getByRole("button", { name: /scenar team/ }));
|
|
335
|
+
await waitFor(() =>
|
|
336
|
+
expect(screen.getByRole("button", { name: "Import keys" })).toBeTruthy(),
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
await userEvent.click(screen.getByRole("button", { name: "Import keys" }));
|
|
340
|
+
const textarea = screen.getByLabelText(/one user-scoped API key per line/);
|
|
341
|
+
await userEvent.type(textarea, "key_good_1234{Enter}key_bad_5678");
|
|
342
|
+
await userEvent.click(screen.getByRole("button", { name: "Import 2 keys" }));
|
|
343
|
+
|
|
344
|
+
await waitFor(() => expect(addMemberKey).toHaveBeenCalledTimes(2));
|
|
345
|
+
expect(addMemberKey).toHaveBeenNthCalledWith(1, {
|
|
346
|
+
accountId: "acc-1",
|
|
347
|
+
apiKey: "key_good_1234",
|
|
348
|
+
});
|
|
349
|
+
expect(addMemberKey).toHaveBeenNthCalledWith(2, {
|
|
350
|
+
accountId: "acc-1",
|
|
351
|
+
apiKey: "key_bad_5678",
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Per-line outcomes: success bound to its member, failure with the error.
|
|
355
|
+
await waitFor(() =>
|
|
356
|
+
expect(screen.getByText(/added — bound to morgan@scenar\.ai/)).toBeTruthy(),
|
|
357
|
+
);
|
|
358
|
+
expect(screen.getByText(/Key rejected by Cursor/)).toBeTruthy();
|
|
359
|
+
// Only the failed key remains in the box for retry.
|
|
360
|
+
expect((textarea as HTMLTextAreaElement).value).toBe("key_bad_5678");
|
|
361
|
+
// The roster sync runs automatically after the import.
|
|
362
|
+
await waitFor(() => expect(syncAccount).toHaveBeenCalledWith("acc-1"));
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it("keeps the stored admin key when the editor's masked value is untouched", async () => {
|
|
366
|
+
const upsertAccount = vi.fn().mockResolvedValue(scenarAccount());
|
|
367
|
+
const client = createMockStigmer({
|
|
368
|
+
listAccounts: vi.fn().mockResolvedValue({ accounts: [scenarSummary()] }),
|
|
369
|
+
getAccountView: vi.fn().mockResolvedValue(scenarView()),
|
|
370
|
+
upsertAccount,
|
|
371
|
+
});
|
|
372
|
+
render(<CursorAccountsConsole />, { wrapper: wrapper(client) });
|
|
373
|
+
|
|
374
|
+
await waitFor(() => expect(screen.getByText("scenar team")).toBeTruthy());
|
|
375
|
+
await userEvent.click(screen.getByRole("button", { name: /scenar team/ }));
|
|
376
|
+
await waitFor(() => expect(screen.getByRole("button", { name: "Edit" })).toBeTruthy());
|
|
377
|
+
await userEvent.click(screen.getByRole("button", { name: "Edit" }));
|
|
378
|
+
|
|
379
|
+
await userEvent.click(screen.getByRole("button", { name: "Save changes" }));
|
|
380
|
+
|
|
381
|
+
await waitFor(() => expect(upsertAccount).toHaveBeenCalledTimes(1));
|
|
382
|
+
expect(upsertAccount.mock.calls[0][0].account.adminApiKey).toBe("***REDACTED***");
|
|
383
|
+
});
|
|
384
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Timestamp } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
|
|
3
|
+
// BigInt literals (0n) require an ES2020 target, which not every consuming
|
|
4
|
+
// app's tsconfig guarantees — the constructor form is target-agnostic (the
|
|
5
|
+
// billing pricing-format precedent).
|
|
6
|
+
const ZERO = BigInt(0);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Micro-USD to a display dollar string (e.g. `169342n` → `"$0.17"`).
|
|
10
|
+
* Spend figures are Cursor-reported cycle totals — two decimals is the
|
|
11
|
+
* honest precision for a monitoring surface.
|
|
12
|
+
*/
|
|
13
|
+
export function formatSpendMicros(micros: bigint): string {
|
|
14
|
+
const dollars = Number(micros) / 1_000_000;
|
|
15
|
+
return `$${dollars.toFixed(2)}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Proto Timestamp to a compact local date-time (e.g. "Jul 22, 14:05"). */
|
|
19
|
+
export function formatSyncTime(ts: Timestamp | undefined): string {
|
|
20
|
+
if (!ts || ts.seconds === ZERO) {
|
|
21
|
+
return "never";
|
|
22
|
+
}
|
|
23
|
+
return new Date(Number(ts.seconds) * 1000).toLocaleString(undefined, {
|
|
24
|
+
month: "short",
|
|
25
|
+
day: "numeric",
|
|
26
|
+
hour: "2-digit",
|
|
27
|
+
minute: "2-digit",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Data hooks
|
|
2
|
+
export { useCursorAccounts } from "./useCursorAccounts.js";
|
|
3
|
+
export type { UseCursorAccountsReturn } from "./useCursorAccounts.js";
|
|
4
|
+
export { useCursorAccountView } from "./useCursorAccountView.js";
|
|
5
|
+
export type { UseCursorAccountViewReturn } from "./useCursorAccountView.js";
|
|
6
|
+
|
|
7
|
+
// Behavior hooks
|
|
8
|
+
export { useUpsertCursorAccount } from "./useUpsertCursorAccount.js";
|
|
9
|
+
export type { UseUpsertCursorAccountReturn } from "./useUpsertCursorAccount.js";
|
|
10
|
+
export { useDeleteCursorAccount } from "./useDeleteCursorAccount.js";
|
|
11
|
+
export type {
|
|
12
|
+
DeleteCursorAccountInput,
|
|
13
|
+
UseDeleteCursorAccountReturn,
|
|
14
|
+
} from "./useDeleteCursorAccount.js";
|
|
15
|
+
export { useCursorMemberKeyActions } from "./useCursorMemberKeyActions.js";
|
|
16
|
+
export type {
|
|
17
|
+
AddCursorMemberKeyInput,
|
|
18
|
+
RemoveCursorMemberKeyInput,
|
|
19
|
+
UseCursorMemberKeyActionsReturn,
|
|
20
|
+
} from "./useCursorMemberKeyActions.js";
|
|
21
|
+
export { useSyncCursorAccount } from "./useSyncCursorAccount.js";
|
|
22
|
+
export type { UseSyncCursorAccountReturn } from "./useSyncCursorAccount.js";
|
|
23
|
+
|
|
24
|
+
// Styled components
|
|
25
|
+
export { CursorAccountsConsole } from "./CursorAccountsConsole.js";
|
|
26
|
+
export type { CursorAccountsConsoleProps } from "./CursorAccountsConsole.js";
|
|
27
|
+
export { CursorAccountEditor } from "./CursorAccountEditor.js";
|
|
28
|
+
export type { CursorAccountEditorProps } from "./CursorAccountEditor.js";
|
|
29
|
+
export { CursorAccountsAccessNotice } from "./CursorAccountsAccessNotice.js";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { CursorAccountView } from "@stigmer/protos/ai/stigmer/platform/cursoraccount/v1/io_pb";
|
|
4
|
+
import { useStigmer } from "../hooks.js";
|
|
5
|
+
import { useFetch } from "../internal/useFetch.js";
|
|
6
|
+
|
|
7
|
+
/** Return value of {@link useCursorAccountView}. */
|
|
8
|
+
export interface UseCursorAccountViewReturn {
|
|
9
|
+
/** The detail view, or `null` before the first successful fetch. */
|
|
10
|
+
readonly view: CursorAccountView | null;
|
|
11
|
+
/** `true` while the initial fetch is in flight. */
|
|
12
|
+
readonly isLoading: boolean;
|
|
13
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
14
|
+
readonly isRefetching: boolean;
|
|
15
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
16
|
+
readonly error: Error | null;
|
|
17
|
+
/** Discard cached data and re-fetch from the server. */
|
|
18
|
+
readonly refetch: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Data hook for one Cursor account's detail view: the redacted account,
|
|
23
|
+
* the latest roster/spend snapshot, and the server-computed coverage
|
|
24
|
+
* join (per-key owner state and cycle spend, active members without
|
|
25
|
+
* keys).
|
|
26
|
+
*
|
|
27
|
+
* Pass `null` as `accountId` to skip fetching (e.g. while the console is
|
|
28
|
+
* on the list phase).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const { view, isLoading, refetch } = useCursorAccountView(accountId);
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function useCursorAccountView(
|
|
36
|
+
accountId: string | null,
|
|
37
|
+
): UseCursorAccountViewReturn {
|
|
38
|
+
const stigmer = useStigmer();
|
|
39
|
+
|
|
40
|
+
const { data: view, isLoading, isRefetching, error, refetch } = useFetch(
|
|
41
|
+
accountId
|
|
42
|
+
? () => stigmer.cursorAccounts.getAccountView(accountId)
|
|
43
|
+
: null,
|
|
44
|
+
[accountId, stigmer],
|
|
45
|
+
null as CursorAccountView | null,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return { view, isLoading, isRefetching, error, refetch };
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { CursorAccountsResponse } from "@stigmer/protos/ai/stigmer/platform/cursoraccount/v1/io_pb";
|
|
4
|
+
import { useStigmer } from "../hooks.js";
|
|
5
|
+
import { useFetch } from "../internal/useFetch.js";
|
|
6
|
+
|
|
7
|
+
/** Return value of {@link useCursorAccounts}. */
|
|
8
|
+
export interface UseCursorAccountsReturn {
|
|
9
|
+
/** The account summaries, or `null` before the first successful fetch. */
|
|
10
|
+
readonly accounts: CursorAccountsResponse | null;
|
|
11
|
+
/** `true` while the initial fetch is in flight. */
|
|
12
|
+
readonly isLoading: boolean;
|
|
13
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
14
|
+
readonly isRefetching: boolean;
|
|
15
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
16
|
+
readonly error: Error | null;
|
|
17
|
+
/** Discard cached data and re-fetch from the server. */
|
|
18
|
+
readonly refetch: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Data hook that lists every managed Cursor account with its routing and
|
|
23
|
+
* sync summary (enabled member key count, last-synced timestamp). Key
|
|
24
|
+
* material is always redacted server-side.
|
|
25
|
+
*
|
|
26
|
+
* Platform-operator surface: the caller needs
|
|
27
|
+
* `can_manage_cursor_accounts` on `platform:stigmer`.
|
|
28
|
+
*
|
|
29
|
+
* Pass `enabled: false` to skip fetching (stable no-op).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { accounts, isLoading, refetch } = useCursorAccounts();
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function useCursorAccounts(
|
|
37
|
+
options?: { readonly enabled?: boolean },
|
|
38
|
+
): UseCursorAccountsReturn {
|
|
39
|
+
const stigmer = useStigmer();
|
|
40
|
+
const enabled = options?.enabled ?? true;
|
|
41
|
+
|
|
42
|
+
const { data: accounts, isLoading, isRefetching, error, refetch } = useFetch(
|
|
43
|
+
enabled ? () => stigmer.cursorAccounts.listAccounts() : null,
|
|
44
|
+
[enabled, stigmer],
|
|
45
|
+
null as CursorAccountsResponse | null,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return { accounts, isLoading, isRefetching, error, refetch };
|
|
49
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { CursorAccount } from "@stigmer/protos/ai/stigmer/platform/cursoraccount/v1/cursor_account_pb";
|
|
5
|
+
import { useStigmer } from "../hooks.js";
|
|
6
|
+
import { toError } from "../internal/toError.js";
|
|
7
|
+
|
|
8
|
+
/** Input for adding one member key. */
|
|
9
|
+
export interface AddCursorMemberKeyInput {
|
|
10
|
+
readonly accountId: string;
|
|
11
|
+
/**
|
|
12
|
+
* Plaintext user-scoped Cursor API key. The server identifies it via
|
|
13
|
+
* Cursor's `/v1/me` and binds it to its owning team member; admin and
|
|
14
|
+
* service-account keys are rejected with Cursor's own explanation —
|
|
15
|
+
* surface the error verbatim.
|
|
16
|
+
*/
|
|
17
|
+
readonly apiKey: string;
|
|
18
|
+
/** Optional operator label. */
|
|
19
|
+
readonly label?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Input for removing one member key. */
|
|
23
|
+
export interface RemoveCursorMemberKeyInput {
|
|
24
|
+
readonly accountId: string;
|
|
25
|
+
readonly keyId: string;
|
|
26
|
+
/**
|
|
27
|
+
* Removal is refused while live sessions are pinned to this key.
|
|
28
|
+
* `force: true` overrides; prefer disabling (always safe).
|
|
29
|
+
*/
|
|
30
|
+
readonly force?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Return value of {@link useCursorMemberKeyActions}. */
|
|
34
|
+
export interface UseCursorMemberKeyActionsReturn {
|
|
35
|
+
/** Add one execution-capable member key. Returns the redacted account. */
|
|
36
|
+
readonly addKey: (input: AddCursorMemberKeyInput) => Promise<CursorAccount>;
|
|
37
|
+
/** Remove one member key (live-pin guarded). */
|
|
38
|
+
readonly removeKey: (input: RemoveCursorMemberKeyInput) => Promise<CursorAccount>;
|
|
39
|
+
/** Enable/disable one key for NEW-session selection (pins unaffected). */
|
|
40
|
+
readonly setKeyEnabled: (
|
|
41
|
+
accountId: string,
|
|
42
|
+
keyId: string,
|
|
43
|
+
enabled: boolean,
|
|
44
|
+
) => Promise<CursorAccount>;
|
|
45
|
+
/** `true` while any key mutation is in flight. */
|
|
46
|
+
readonly isSubmitting: boolean;
|
|
47
|
+
/** Error from the last failed attempt, or `null` when healthy. */
|
|
48
|
+
readonly error: Error | null;
|
|
49
|
+
/** Reset `error` to `null`. */
|
|
50
|
+
readonly clearError: () => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Behavior hook bundling the member-key mutations of one Cursor account —
|
|
55
|
+
* add, remove, enable/disable. One hook because the console's key panel
|
|
56
|
+
* performs all three and they share submit/error surfaces.
|
|
57
|
+
*
|
|
58
|
+
* Rotation is deliberately remove + add (no in-place key swap), so the
|
|
59
|
+
* server-side `/v1/me` identity binding can never go stale.
|
|
60
|
+
*/
|
|
61
|
+
export function useCursorMemberKeyActions(): UseCursorMemberKeyActionsReturn {
|
|
62
|
+
const stigmer = useStigmer();
|
|
63
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
64
|
+
const [error, setError] = useState<Error | null>(null);
|
|
65
|
+
|
|
66
|
+
const run = useCallback(
|
|
67
|
+
async (op: () => Promise<CursorAccount>): Promise<CursorAccount> => {
|
|
68
|
+
setIsSubmitting(true);
|
|
69
|
+
setError(null);
|
|
70
|
+
try {
|
|
71
|
+
return await op();
|
|
72
|
+
} catch (e) {
|
|
73
|
+
const err = toError(e);
|
|
74
|
+
setError(err);
|
|
75
|
+
throw err;
|
|
76
|
+
} finally {
|
|
77
|
+
setIsSubmitting(false);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
[],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const addKey = useCallback(
|
|
84
|
+
(input: AddCursorMemberKeyInput) =>
|
|
85
|
+
run(() => stigmer.cursorAccounts.addMemberKey(input)),
|
|
86
|
+
[run, stigmer.cursorAccounts],
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const removeKey = useCallback(
|
|
90
|
+
(input: RemoveCursorMemberKeyInput) =>
|
|
91
|
+
run(() => stigmer.cursorAccounts.removeMemberKey(input)),
|
|
92
|
+
[run, stigmer.cursorAccounts],
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const setKeyEnabled = useCallback(
|
|
96
|
+
(accountId: string, keyId: string, enabled: boolean) =>
|
|
97
|
+
run(() =>
|
|
98
|
+
stigmer.cursorAccounts.setMemberKeyEnabled({ accountId, keyId, enabled }),
|
|
99
|
+
),
|
|
100
|
+
[run, stigmer.cursorAccounts],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const clearError = useCallback(() => setError(null), []);
|
|
104
|
+
|
|
105
|
+
return { addKey, removeKey, setKeyEnabled, isSubmitting, error, clearError };
|
|
106
|
+
}
|