@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,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { create, type JsonObject } from "@bufbuild/protobuf";
|
|
5
|
+
import {
|
|
6
|
+
UpdateRecordRequestSchema,
|
|
7
|
+
type RecordEnvelope,
|
|
8
|
+
} from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
|
|
9
|
+
import { useStigmer } from "../hooks.js";
|
|
10
|
+
import { toError } from "../internal/toError.js";
|
|
11
|
+
import type { RecordScope } from "./useRecordList.js";
|
|
12
|
+
|
|
13
|
+
/** Arguments for a single record update. */
|
|
14
|
+
export interface UpdateRecordArgs extends RecordScope {
|
|
15
|
+
/** Record id (`dsr_…`). */
|
|
16
|
+
readonly id: string;
|
|
17
|
+
/**
|
|
18
|
+
* Partial merge (DD-005): only the supplied fields change; an
|
|
19
|
+
* explicit `null` clears a field; absent fields keep their stored
|
|
20
|
+
* values. Constraints evaluate on the merged result. Build this from
|
|
21
|
+
* per-field edits with `buildUpdateFields`.
|
|
22
|
+
*/
|
|
23
|
+
readonly fields: JsonObject;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Return value of {@link useUpdateRecord}. */
|
|
27
|
+
export interface UseUpdateRecordReturn {
|
|
28
|
+
/**
|
|
29
|
+
* Update one record by id. Resolves with the merged envelope. Rejects
|
|
30
|
+
* — and sets `error` — on denial or constraint violation; the error's
|
|
31
|
+
* message is the server's relayable text, byte-for-byte.
|
|
32
|
+
*/
|
|
33
|
+
readonly updateRecord: (args: UpdateRecordArgs) => Promise<RecordEnvelope>;
|
|
34
|
+
/** `true` while the update is in flight. */
|
|
35
|
+
readonly isUpdating: boolean;
|
|
36
|
+
/** Error from the last failed update, or `null` when healthy. */
|
|
37
|
+
readonly error: Error | null;
|
|
38
|
+
/** Reset `error` to `null`. */
|
|
39
|
+
readonly clearError: () => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Behavior hook that wraps `datastore.updateRecord()` with loading and
|
|
44
|
+
* error state.
|
|
45
|
+
*
|
|
46
|
+
* The RPC is an honest tri-state partial merge — the hook adds no
|
|
47
|
+
* merge semantics of its own. A record in another partition is
|
|
48
|
+
* NOT_FOUND (DD-010: partition scoping is structural).
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* const { updateRecord } = useUpdateRecord();
|
|
53
|
+
* await updateRecord({
|
|
54
|
+
* org: "acme",
|
|
55
|
+
* datastore: "clinic",
|
|
56
|
+
* collection: "bookings",
|
|
57
|
+
* id: "dsr_01j9...",
|
|
58
|
+
* fields: { patient_phone: "+15550100", notes: null }, // notes cleared
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function useUpdateRecord(): UseUpdateRecordReturn {
|
|
63
|
+
const stigmer = useStigmer();
|
|
64
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
65
|
+
const [error, setError] = useState<Error | null>(null);
|
|
66
|
+
|
|
67
|
+
const clearError = useCallback(() => setError(null), []);
|
|
68
|
+
|
|
69
|
+
const updateRecord = useCallback(
|
|
70
|
+
async (args: UpdateRecordArgs): Promise<RecordEnvelope> => {
|
|
71
|
+
setIsUpdating(true);
|
|
72
|
+
setError(null);
|
|
73
|
+
try {
|
|
74
|
+
return await stigmer.datastore.updateRecord(
|
|
75
|
+
create(UpdateRecordRequestSchema, {
|
|
76
|
+
org: args.org,
|
|
77
|
+
datastore: args.datastore,
|
|
78
|
+
collection: args.collection,
|
|
79
|
+
partition: args.partition ?? "",
|
|
80
|
+
id: args.id,
|
|
81
|
+
fields: args.fields,
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
setError(toError(err));
|
|
86
|
+
throw err;
|
|
87
|
+
} finally {
|
|
88
|
+
setIsUpdating(false);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
[stigmer],
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return { updateRecord, isUpdating, error, clearError };
|
|
95
|
+
}
|
|
@@ -6,6 +6,7 @@ import { getUserMessage } from "@stigmer/sdk";
|
|
|
6
6
|
import type { Environment } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
7
7
|
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
8
8
|
import { ResourceVisibilityControl } from "../library/ResourceVisibilityControl.js";
|
|
9
|
+
import { EditResourceYamlDialog } from "../manifest/EditResourceYamlDialog.js";
|
|
9
10
|
import { useEnvironmentList } from "./useEnvironmentList.js";
|
|
10
11
|
import { EnvironmentVariableEditor } from "./EnvironmentVariableEditor.js";
|
|
11
12
|
import { isShareRestrictedEnvironment } from "./shareRestriction.js";
|
|
@@ -94,6 +95,7 @@ export function EnvironmentListPanel({
|
|
|
94
95
|
labels,
|
|
95
96
|
);
|
|
96
97
|
const [expandedId, setExpandedId] = useState<string | null>(null);
|
|
98
|
+
const [yamlEnvironment, setYamlEnvironment] = useState<Environment | null>(null);
|
|
97
99
|
|
|
98
100
|
if (onRefetchRef) {
|
|
99
101
|
onRefetchRef(refetch);
|
|
@@ -179,9 +181,18 @@ export function EnvironmentListPanel({
|
|
|
179
181
|
onToggle={() => handleToggle(env)}
|
|
180
182
|
readOnly={readOnly}
|
|
181
183
|
onVisibilityChanged={refetch}
|
|
184
|
+
onEditYaml={() => setYamlEnvironment(env)}
|
|
182
185
|
/>
|
|
183
186
|
);
|
|
184
187
|
})}
|
|
188
|
+
<EditResourceYamlDialog
|
|
189
|
+
open={yamlEnvironment !== null}
|
|
190
|
+
onOpenChange={(open) => {
|
|
191
|
+
if (!open) setYamlEnvironment(null);
|
|
192
|
+
}}
|
|
193
|
+
resource={yamlEnvironment}
|
|
194
|
+
onApplied={refetch}
|
|
195
|
+
/>
|
|
185
196
|
</div>
|
|
186
197
|
);
|
|
187
198
|
}
|
|
@@ -196,12 +207,14 @@ function EnvironmentCard({
|
|
|
196
207
|
onToggle,
|
|
197
208
|
readOnly,
|
|
198
209
|
onVisibilityChanged,
|
|
210
|
+
onEditYaml,
|
|
199
211
|
}: {
|
|
200
212
|
environment: Environment;
|
|
201
213
|
isExpanded: boolean;
|
|
202
214
|
onToggle: () => void;
|
|
203
215
|
readOnly: boolean;
|
|
204
216
|
onVisibilityChanged: () => void;
|
|
217
|
+
onEditYaml: () => void;
|
|
205
218
|
}) {
|
|
206
219
|
const name =
|
|
207
220
|
environment.metadata?.name || environment.metadata?.slug || "Unnamed";
|
|
@@ -249,6 +262,17 @@ function EnvironmentCard({
|
|
|
249
262
|
</div>
|
|
250
263
|
</button>
|
|
251
264
|
|
|
265
|
+
{!readOnly && (
|
|
266
|
+
<button
|
|
267
|
+
type="button"
|
|
268
|
+
onClick={onEditYaml}
|
|
269
|
+
aria-label={`Edit ${name} as YAML`}
|
|
270
|
+
className="shrink-0 rounded px-1.5 py-0.5 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
271
|
+
>
|
|
272
|
+
Edit YAML
|
|
273
|
+
</button>
|
|
274
|
+
)}
|
|
275
|
+
|
|
252
276
|
{showVisibilityControl && (
|
|
253
277
|
<ResourceVisibilityControl
|
|
254
278
|
kind="environment"
|
|
@@ -119,12 +119,20 @@ describe("useArtifactInspection — detection + apply", () => {
|
|
|
119
119
|
|
|
120
120
|
it("applies a detected Agent and fires onApplied with the result", async () => {
|
|
121
121
|
const getArtifactContent = vi.fn().mockResolvedValue(contentResult(AGENT_YAML));
|
|
122
|
+
// The apply path routes through the kind-agnostic manifest engine:
|
|
123
|
+
// the hook parses the YAML into a ManifestDocument and hands it to
|
|
124
|
+
// stigmer.manifest.apply.
|
|
122
125
|
const apply = vi.fn().mockResolvedValue({
|
|
123
|
-
|
|
126
|
+
yamlKind: "Agent",
|
|
127
|
+
displayName: "Agent",
|
|
128
|
+
name: "my-agent",
|
|
129
|
+
org: "acme",
|
|
130
|
+
slug: "my-agent",
|
|
131
|
+
id: "agt_01",
|
|
124
132
|
});
|
|
125
133
|
const stigmer = {
|
|
126
134
|
agentExecution: { getArtifactContent },
|
|
127
|
-
|
|
135
|
+
manifest: { apply },
|
|
128
136
|
} as unknown as Stigmer;
|
|
129
137
|
const onApplied = vi.fn();
|
|
130
138
|
|
|
@@ -144,6 +152,8 @@ describe("useArtifactInspection — detection + apply", () => {
|
|
|
144
152
|
|
|
145
153
|
expect(apply).toHaveBeenCalledTimes(1);
|
|
146
154
|
expect(apply.mock.calls[0][0].name).toBe("my-agent");
|
|
155
|
+
expect(apply.mock.calls[0][0].handler.yamlKind).toBe("Agent");
|
|
156
|
+
expect(apply.mock.calls[0][0].org).toBe("acme");
|
|
147
157
|
await waitFor(() => expect(result.current.applyResult?.kind).toBe("Agent"));
|
|
148
158
|
expect(onApplied).toHaveBeenCalledTimes(1);
|
|
149
159
|
expect(onApplied.mock.calls[0][0].name).toBe("my-agent");
|
|
@@ -200,3 +200,128 @@ describe("useLiveAgentExecution", () => {
|
|
|
200
200
|
}
|
|
201
201
|
});
|
|
202
202
|
});
|
|
203
|
+
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// The { live } visibility gate (T07)
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
describe("useLiveAgentExecution { live }", () => {
|
|
209
|
+
it("live: false fetches the snapshot but never subscribes", async () => {
|
|
210
|
+
const running = executionFixture("aex_p1", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
211
|
+
mockGet(async () => running);
|
|
212
|
+
|
|
213
|
+
const { result } = renderHook(() =>
|
|
214
|
+
useLiveAgentExecution("aex_p1", { live: false }),
|
|
215
|
+
);
|
|
216
|
+
await waitFor(() => expect(result.current.execution).toBe(running));
|
|
217
|
+
|
|
218
|
+
// Non-terminal + fetched, yet the gate stays closed on every render.
|
|
219
|
+
for (const call of mockUseExecutionStream.mock.calls) {
|
|
220
|
+
expect(call[0]).toBeNull();
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("live: true (and omitted) behave identically for a non-terminal execution", async () => {
|
|
225
|
+
const running = executionFixture("aex_p2", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
226
|
+
mockGet(async () => running);
|
|
227
|
+
|
|
228
|
+
const { result } = renderHook(() =>
|
|
229
|
+
useLiveAgentExecution("aex_p2", { live: true }),
|
|
230
|
+
);
|
|
231
|
+
await waitFor(() => expect(result.current.execution).not.toBeNull());
|
|
232
|
+
|
|
233
|
+
const lastCall =
|
|
234
|
+
mockUseExecutionStream.mock.calls[mockUseExecutionStream.mock.calls.length - 1];
|
|
235
|
+
expect(lastCall[0]).toBe("aex_p2");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("a terminal execution never streams regardless of live", async () => {
|
|
239
|
+
const terminal = executionFixture("aex_p3", ExecutionPhase.EXECUTION_COMPLETED);
|
|
240
|
+
mockGet(async () => terminal);
|
|
241
|
+
|
|
242
|
+
const { result } = renderHook(() =>
|
|
243
|
+
useLiveAgentExecution("aex_p3", { live: true }),
|
|
244
|
+
);
|
|
245
|
+
await waitFor(() => expect(result.current.execution).toBe(terminal));
|
|
246
|
+
|
|
247
|
+
for (const call of mockUseExecutionStream.mock.calls) {
|
|
248
|
+
expect(call[0]).toBeNull();
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("false → true attaches the stream in place", async () => {
|
|
253
|
+
const running = executionFixture("aex_p4", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
254
|
+
mockGet(async () => running);
|
|
255
|
+
|
|
256
|
+
const { result, rerender } = renderHook(
|
|
257
|
+
({ live }: { live: boolean }) =>
|
|
258
|
+
useLiveAgentExecution("aex_p4", { live }),
|
|
259
|
+
{ initialProps: { live: false } },
|
|
260
|
+
);
|
|
261
|
+
await waitFor(() => expect(result.current.execution).toBe(running));
|
|
262
|
+
|
|
263
|
+
let lastCall =
|
|
264
|
+
mockUseExecutionStream.mock.calls[mockUseExecutionStream.mock.calls.length - 1];
|
|
265
|
+
expect(lastCall[0]).toBeNull();
|
|
266
|
+
|
|
267
|
+
rerender({ live: true });
|
|
268
|
+
|
|
269
|
+
lastCall =
|
|
270
|
+
mockUseExecutionStream.mock.calls[mockUseExecutionStream.mock.calls.length - 1];
|
|
271
|
+
expect(lastCall[0]).toBe("aex_p4");
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("never rewinds: a stream pause keeps the last-streamed snapshot, not the mount fetch", async () => {
|
|
275
|
+
const fetched = executionFixture("aex_p5", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
276
|
+
const streamed = executionFixture("aex_p5", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
277
|
+
mockGet(async () => fetched);
|
|
278
|
+
mockUseExecutionStream.mockReturnValue({
|
|
279
|
+
...idleStream(),
|
|
280
|
+
execution: streamed,
|
|
281
|
+
isStreaming: true,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const { result, rerender } = renderHook(
|
|
285
|
+
({ live }: { live: boolean }) =>
|
|
286
|
+
useLiveAgentExecution("aex_p5", { live }),
|
|
287
|
+
{ initialProps: { live: true } },
|
|
288
|
+
);
|
|
289
|
+
await waitFor(() => expect(result.current.execution).toBe(streamed));
|
|
290
|
+
|
|
291
|
+
// Pause: the stream hook resets to its idle shape (execution: null) —
|
|
292
|
+
// the exact behavior of an unsubscribed useExecutionStream.
|
|
293
|
+
mockUseExecutionStream.mockReturnValue(idleStream());
|
|
294
|
+
rerender({ live: false });
|
|
295
|
+
|
|
296
|
+
// The freshest streamed snapshot stays visible; the view never rolls
|
|
297
|
+
// back to the mount-time fetch.
|
|
298
|
+
expect(result.current.execution).toBe(streamed);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it("does not leak the previous execution's snapshot across an id switch", async () => {
|
|
302
|
+
const first = executionFixture("aex_p6a", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
303
|
+
const streamedFirst = executionFixture("aex_p6a", ExecutionPhase.EXECUTION_IN_PROGRESS);
|
|
304
|
+
const second = executionFixture("aex_p6b", ExecutionPhase.EXECUTION_COMPLETED);
|
|
305
|
+
mockGet(async (id) => (id === "aex_p6a" ? first : second));
|
|
306
|
+
mockUseExecutionStream.mockReturnValue({
|
|
307
|
+
...idleStream(),
|
|
308
|
+
execution: streamedFirst,
|
|
309
|
+
isStreaming: true,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const { result, rerender } = renderHook(
|
|
313
|
+
({ id }: { id: string }) => useLiveAgentExecution(id, { live: true }),
|
|
314
|
+
{ initialProps: { id: "aex_p6a" } },
|
|
315
|
+
);
|
|
316
|
+
await waitFor(() => expect(result.current.execution).toBe(streamedFirst));
|
|
317
|
+
|
|
318
|
+
// Switch executions; the stream resets while the new fetch is in flight.
|
|
319
|
+
mockUseExecutionStream.mockReturnValue(idleStream());
|
|
320
|
+
rerender({ id: "aex_p6b" });
|
|
321
|
+
|
|
322
|
+
// The retained snapshot is keyed by id — it must NOT bleed into the
|
|
323
|
+
// new execution's view.
|
|
324
|
+
expect(result.current.execution).not.toBe(streamedFirst);
|
|
325
|
+
await waitFor(() => expect(result.current.execution).toBe(second));
|
|
326
|
+
});
|
|
327
|
+
});
|
package/src/execution/index.ts
CHANGED
|
@@ -13,7 +13,10 @@ export { useExecutionStream } from "./useExecutionStream.js";
|
|
|
13
13
|
export type { UseExecutionStreamReturn } from "./useExecutionStream.js";
|
|
14
14
|
|
|
15
15
|
export { useLiveAgentExecution } from "./useLiveAgentExecution.js";
|
|
16
|
-
export type {
|
|
16
|
+
export type {
|
|
17
|
+
UseLiveAgentExecutionOptions,
|
|
18
|
+
UseLiveAgentExecutionReturn,
|
|
19
|
+
} from "./useLiveAgentExecution.js";
|
|
17
20
|
|
|
18
21
|
export { useAgentExecutionActions } from "./useAgentExecutionActions.js";
|
|
19
22
|
export type {
|
|
@@ -291,12 +294,6 @@ export {
|
|
|
291
294
|
fileChangeTabPath,
|
|
292
295
|
} from "./file-change-document.js";
|
|
293
296
|
|
|
294
|
-
export {
|
|
295
|
-
AGENT_EXECUTION_DOCUMENT_ENTRY_ID,
|
|
296
|
-
agentExecutionTabPath,
|
|
297
|
-
parseAgentExecutionTabPath,
|
|
298
|
-
} from "./agent-execution-document.js";
|
|
299
|
-
|
|
300
297
|
export { ArtifactContentRenderer } from "./ArtifactContentRenderer.js";
|
|
301
298
|
export type { ArtifactContentRendererProps } from "./ArtifactContentRenderer.js";
|
|
302
299
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useMemo } from "react";
|
|
3
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
4
4
|
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
5
5
|
import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
6
|
import { isNotFound } from "@stigmer/sdk";
|
|
@@ -9,6 +9,23 @@ import { useFetch } from "../internal/useFetch.js";
|
|
|
9
9
|
import { isTerminalPhase } from "./execution-phases.js";
|
|
10
10
|
import { useExecutionStream } from "./useExecutionStream.js";
|
|
11
11
|
|
|
12
|
+
/** Options for {@link useLiveAgentExecution}. */
|
|
13
|
+
export interface UseLiveAgentExecutionOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Whether the live stream may be open. Defaults to `true`.
|
|
16
|
+
*
|
|
17
|
+
* When `false`, the snapshot fetch still runs (so consumers always have
|
|
18
|
+
* something to render) but no subscription is opened — the
|
|
19
|
+
* visibility-gating seam for surfaces that mount many executions at once
|
|
20
|
+
* (e.g. inline agent-call transcripts in the workflow task thread, where
|
|
21
|
+
* only on-screen cards stream). A `false → true` transition attaches the
|
|
22
|
+
* stream in place; a `true → false` transition pauses it while the
|
|
23
|
+
* last-streamed snapshot stays visible (the view never rewinds to the
|
|
24
|
+
* mount-time snapshot).
|
|
25
|
+
*/
|
|
26
|
+
readonly live?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
/** Return value of {@link useLiveAgentExecution}. */
|
|
13
30
|
export interface UseLiveAgentExecutionReturn {
|
|
14
31
|
/**
|
|
@@ -67,8 +84,10 @@ export interface UseLiveAgentExecutionReturn {
|
|
|
67
84
|
*/
|
|
68
85
|
export function useLiveAgentExecution(
|
|
69
86
|
executionId: string | null,
|
|
87
|
+
options?: UseLiveAgentExecutionOptions,
|
|
70
88
|
): UseLiveAgentExecutionReturn {
|
|
71
89
|
const stigmer = useStigmer();
|
|
90
|
+
const live = options?.live ?? true;
|
|
72
91
|
|
|
73
92
|
const fetchFn = executionId
|
|
74
93
|
? async () => {
|
|
@@ -94,12 +113,31 @@ export function useLiveAgentExecution(
|
|
|
94
113
|
// snapshot never advances, so a run that terminates mid-stream does not
|
|
95
114
|
// flip this gate and unmount-thrash the subscription — useExecutionStream
|
|
96
115
|
// ends itself on the terminal snapshot (completion is phase-driven).
|
|
116
|
+
// `live` is the consumer's visibility gate layered on top (an off-screen
|
|
117
|
+
// surface pauses its subscription without losing the fetch).
|
|
97
118
|
const fetchedPhase =
|
|
98
119
|
fetched?.status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED;
|
|
99
|
-
const shouldStream =
|
|
120
|
+
const shouldStream =
|
|
121
|
+
live && fetched !== null && !isTerminalPhase(fetchedPhase);
|
|
100
122
|
const stream = useExecutionStream(shouldStream ? executionId : null);
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
// Retain the freshest snapshot ever shown for THIS execution across a
|
|
125
|
+
// stream pause (`live: true → false`): useExecutionStream resets its
|
|
126
|
+
// store when unsubscribed, so without this a paused surface would rewind
|
|
127
|
+
// to the mount-time fetch — visibly rolling the view backwards. Keyed by
|
|
128
|
+
// id so an execution switch never leaks the previous one's snapshot.
|
|
129
|
+
const lastStreamedRef = useRef<{
|
|
130
|
+
id: string;
|
|
131
|
+
execution: AgentExecution;
|
|
132
|
+
} | null>(null);
|
|
133
|
+
if (executionId && stream.execution) {
|
|
134
|
+
lastStreamedRef.current = { id: executionId, execution: stream.execution };
|
|
135
|
+
} else if (lastStreamedRef.current?.id !== executionId) {
|
|
136
|
+
lastStreamedRef.current = null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const execution =
|
|
140
|
+
stream.execution ?? lastStreamedRef.current?.execution ?? fetched;
|
|
103
141
|
const phase =
|
|
104
142
|
execution?.status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED;
|
|
105
143
|
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
+
import { cleanup, render, screen, waitFor } from "@testing-library/react";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { StigmerContext } from "../../context";
|
|
5
|
+
import {
|
|
6
|
+
useCheckPermission,
|
|
7
|
+
type CheckPermissionOptions,
|
|
8
|
+
type PermissionCheckResource,
|
|
9
|
+
} from "../useCheckPermission";
|
|
10
|
+
|
|
11
|
+
function createMockStigmer(checkMyPermission: ReturnType<typeof vi.fn>) {
|
|
12
|
+
return { iamPolicy: { checkMyPermission } } as never;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function wrapper(client: unknown) {
|
|
16
|
+
return function Wrapper({ children }: { children: ReactNode }) {
|
|
17
|
+
return (
|
|
18
|
+
<StigmerContext.Provider value={client as never}>
|
|
19
|
+
{children}
|
|
20
|
+
</StigmerContext.Provider>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Renders the hook and exposes its state via data attributes. */
|
|
26
|
+
function Probe({
|
|
27
|
+
resource,
|
|
28
|
+
relation = "can_edit",
|
|
29
|
+
options,
|
|
30
|
+
}: {
|
|
31
|
+
resource: PermissionCheckResource | null;
|
|
32
|
+
relation?: string;
|
|
33
|
+
options?: CheckPermissionOptions;
|
|
34
|
+
}) {
|
|
35
|
+
const { allowed, isLoading, error } = useCheckPermission(
|
|
36
|
+
resource,
|
|
37
|
+
relation,
|
|
38
|
+
options,
|
|
39
|
+
);
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
data-testid="probe"
|
|
43
|
+
data-allowed={String(allowed)}
|
|
44
|
+
data-loading={String(isLoading)}
|
|
45
|
+
data-error={String(error !== null)}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const AGENT: PermissionCheckResource = { kind: "agent", id: "agt_1" };
|
|
51
|
+
|
|
52
|
+
/** A checkMyPermission stub that stays pending until resolved manually. */
|
|
53
|
+
function pendingCheck() {
|
|
54
|
+
let resolve!: (value: { isAuthorized: boolean }) => void;
|
|
55
|
+
let reject!: (err: unknown) => void;
|
|
56
|
+
const check = vi.fn().mockReturnValue(
|
|
57
|
+
new Promise((res, rej) => {
|
|
58
|
+
resolve = res;
|
|
59
|
+
reject = rej;
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
return { check, resolve: (v: boolean) => resolve({ isAuthorized: v }), reject: (e: unknown) => reject(e) };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
afterEach(cleanup);
|
|
66
|
+
|
|
67
|
+
describe("useCheckPermission — fail-open (default)", () => {
|
|
68
|
+
it("is allowed while the check is in flight", async () => {
|
|
69
|
+
const { check } = pendingCheck();
|
|
70
|
+
render(<Probe resource={AGENT} />, {
|
|
71
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const probe = screen.getByTestId("probe");
|
|
75
|
+
expect(probe.getAttribute("data-allowed")).toBe("true");
|
|
76
|
+
await waitFor(() =>
|
|
77
|
+
expect(probe.getAttribute("data-loading")).toBe("true"),
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("respects an explicit server denial", async () => {
|
|
82
|
+
const check = vi.fn().mockResolvedValue({ isAuthorized: false });
|
|
83
|
+
render(<Probe resource={AGENT} />, {
|
|
84
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await waitFor(() =>
|
|
88
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("false"),
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("respects an explicit server grant", async () => {
|
|
93
|
+
const check = vi.fn().mockResolvedValue({ isAuthorized: true });
|
|
94
|
+
render(<Probe resource={AGENT} />, {
|
|
95
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const probe = screen.getByTestId("probe");
|
|
99
|
+
await waitFor(() => expect(probe.getAttribute("data-loading")).toBe("false"));
|
|
100
|
+
expect(probe.getAttribute("data-allowed")).toBe("true");
|
|
101
|
+
expect(probe.getAttribute("data-error")).toBe("false");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("fails open on RPC rejection (OSS single-user mode)", async () => {
|
|
105
|
+
const check = vi.fn().mockRejectedValue(new Error("unimplemented"));
|
|
106
|
+
render(<Probe resource={AGENT} />, {
|
|
107
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const probe = screen.getByTestId("probe");
|
|
111
|
+
await waitFor(() => expect(probe.getAttribute("data-error")).toBe("true"));
|
|
112
|
+
expect(probe.getAttribute("data-allowed")).toBe("true");
|
|
113
|
+
expect(probe.getAttribute("data-loading")).toBe("false");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("is allowed when resource is null (check skipped, no RPC)", () => {
|
|
117
|
+
const check = vi.fn();
|
|
118
|
+
render(<Probe resource={null} />, {
|
|
119
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true");
|
|
123
|
+
expect(check).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe("useCheckPermission — fail-closed", () => {
|
|
128
|
+
const CLOSED: CheckPermissionOptions = { fail: "closed" };
|
|
129
|
+
|
|
130
|
+
it("is denied while the check is in flight (no flash of gated UI)", async () => {
|
|
131
|
+
const { check } = pendingCheck();
|
|
132
|
+
render(<Probe resource={AGENT} options={CLOSED} />, {
|
|
133
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const probe = screen.getByTestId("probe");
|
|
137
|
+
expect(probe.getAttribute("data-allowed")).toBe("false");
|
|
138
|
+
await waitFor(() =>
|
|
139
|
+
expect(probe.getAttribute("data-loading")).toBe("true"),
|
|
140
|
+
);
|
|
141
|
+
expect(probe.getAttribute("data-allowed")).toBe("false");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("is allowed only on an explicit server grant", async () => {
|
|
145
|
+
const check = vi.fn().mockResolvedValue({ isAuthorized: true });
|
|
146
|
+
render(<Probe resource={AGENT} options={CLOSED} />, {
|
|
147
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await waitFor(() =>
|
|
151
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("fails closed on RPC rejection", async () => {
|
|
156
|
+
const check = vi.fn().mockRejectedValue(new Error("unimplemented"));
|
|
157
|
+
render(<Probe resource={AGENT} options={CLOSED} />, {
|
|
158
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const probe = screen.getByTestId("probe");
|
|
162
|
+
await waitFor(() => expect(probe.getAttribute("data-error")).toBe("true"));
|
|
163
|
+
expect(probe.getAttribute("data-allowed")).toBe("false");
|
|
164
|
+
expect(probe.getAttribute("data-loading")).toBe("false");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("is denied when resource is null (check skipped)", () => {
|
|
168
|
+
const check = vi.fn();
|
|
169
|
+
render(<Probe resource={null} options={CLOSED} />, {
|
|
170
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("false");
|
|
174
|
+
expect(check).not.toHaveBeenCalled();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe("useCheckPermission — caching", () => {
|
|
179
|
+
it("serves repeat checks of the same triple from the mount cache", async () => {
|
|
180
|
+
const check = vi.fn().mockResolvedValue({ isAuthorized: true });
|
|
181
|
+
const { rerender } = render(<Probe resource={AGENT} />, {
|
|
182
|
+
wrapper: wrapper(createMockStigmer(check)),
|
|
183
|
+
});
|
|
184
|
+
await waitFor(() =>
|
|
185
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Switch relation (new triple → one more RPC), then switch back
|
|
189
|
+
// (cached triple → served without an RPC).
|
|
190
|
+
rerender(<Probe resource={AGENT} relation="can_delete" />);
|
|
191
|
+
await waitFor(() => expect(check).toHaveBeenCalledTimes(2));
|
|
192
|
+
rerender(<Probe resource={AGENT} relation="can_edit" />);
|
|
193
|
+
await waitFor(() =>
|
|
194
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
|
|
195
|
+
);
|
|
196
|
+
expect(check).toHaveBeenCalledTimes(2);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("does not cache a failed check as a verdict", async () => {
|
|
200
|
+
// First mount errors; the error must not be pinned as `true` — a
|
|
201
|
+
// remount (fresh cache) with a healthy server gets the real verdict.
|
|
202
|
+
const failing = vi.fn().mockRejectedValue(new Error("blip"));
|
|
203
|
+
const { unmount } = render(
|
|
204
|
+
<Probe resource={AGENT} options={{ fail: "closed" }} />,
|
|
205
|
+
{ wrapper: wrapper(createMockStigmer(failing)) },
|
|
206
|
+
);
|
|
207
|
+
await waitFor(() =>
|
|
208
|
+
expect(screen.getByTestId("probe").getAttribute("data-error")).toBe("true"),
|
|
209
|
+
);
|
|
210
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("false");
|
|
211
|
+
unmount();
|
|
212
|
+
|
|
213
|
+
const healthy = vi.fn().mockResolvedValue({ isAuthorized: true });
|
|
214
|
+
render(<Probe resource={AGENT} options={{ fail: "closed" }} />, {
|
|
215
|
+
wrapper: wrapper(createMockStigmer(healthy)),
|
|
216
|
+
});
|
|
217
|
+
await waitFor(() =>
|
|
218
|
+
expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
|
|
219
|
+
);
|
|
220
|
+
});
|
|
221
|
+
});
|