@stigmer/react 3.3.0 → 3.4.1
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/useAgentCount.d.ts +2 -0
- package/agent/useAgentCount.d.ts.map +1 -1
- package/agent/useAgentCount.js.map +1 -1
- package/api-key/CreateApiKeyForm.d.ts +7 -1
- package/api-key/CreateApiKeyForm.d.ts.map +1 -1
- package/api-key/CreateApiKeyForm.js +2 -2
- package/api-key/CreateApiKeyForm.js.map +1 -1
- package/billing/index.d.ts +0 -18
- package/billing/index.d.ts.map +1 -1
- package/billing/index.js +4 -9
- package/billing/index.js.map +1 -1
- package/cursor-accounts/CursorAccountEditor.d.ts +7 -1
- package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -1
- package/cursor-accounts/CursorAccountEditor.js +21 -5
- package/cursor-accounts/CursorAccountEditor.js.map +1 -1
- package/cursor-accounts/CursorAccountsConsole.d.ts +9 -5
- package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -1
- package/cursor-accounts/CursorAccountsConsole.js +34 -140
- package/cursor-accounts/CursorAccountsConsole.js.map +1 -1
- package/cursor-accounts/MemberCoverageTable.d.ts +29 -0
- package/cursor-accounts/MemberCoverageTable.d.ts.map +1 -0
- package/cursor-accounts/MemberCoverageTable.js +150 -0
- package/cursor-accounts/MemberCoverageTable.js.map +1 -0
- package/cursor-accounts/MemberKeysPanel.d.ts +25 -0
- package/cursor-accounts/MemberKeysPanel.d.ts.map +1 -0
- package/cursor-accounts/MemberKeysPanel.js +115 -0
- package/cursor-accounts/MemberKeysPanel.js.map +1 -0
- package/cursor-accounts/badges.d.ts +9 -0
- package/cursor-accounts/badges.d.ts.map +1 -0
- package/cursor-accounts/badges.js +10 -0
- package/cursor-accounts/badges.js.map +1 -0
- package/cursor-accounts/cursor-account-coverage.d.ts +41 -0
- package/cursor-accounts/cursor-account-coverage.d.ts.map +1 -0
- package/cursor-accounts/cursor-account-coverage.js +26 -0
- package/cursor-accounts/cursor-account-coverage.js.map +1 -0
- package/cursor-accounts/cursor-account-format.d.ts +13 -0
- package/cursor-accounts/cursor-account-format.d.ts.map +1 -1
- package/cursor-accounts/cursor-account-format.js +16 -1
- package/cursor-accounts/cursor-account-format.js.map +1 -1
- package/datastore/CollectionRecordsBrowser.js +18 -4
- package/datastore/CollectionRecordsBrowser.js.map +1 -1
- package/datastore/RecordFilterBuilder.d.ts +8 -1
- package/datastore/RecordFilterBuilder.d.ts.map +1 -1
- package/datastore/RecordFilterBuilder.js +2 -2
- package/datastore/RecordFilterBuilder.js.map +1 -1
- package/datastore/recordFilter.d.ts +9 -1
- package/datastore/recordFilter.d.ts.map +1 -1
- package/datastore/recordFilter.js +12 -1
- package/datastore/recordFilter.js.map +1 -1
- package/datastore/useDatastoreCount.d.ts +2 -0
- package/datastore/useDatastoreCount.d.ts.map +1 -1
- package/datastore/useDatastoreCount.js.map +1 -1
- package/execution/ExecutionProgress.d.ts.map +1 -1
- package/execution/ExecutionProgress.js +13 -4
- package/execution/ExecutionProgress.js.map +1 -1
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +10 -2
- package/execution/MessageThread.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +31 -1
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +2 -0
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/index.d.ts +8 -6
- package/index.d.ts.map +1 -1
- package/index.js +8 -4
- package/index.js.map +1 -1
- package/internal/form-primitives.d.ts +10 -0
- package/internal/form-primitives.d.ts.map +1 -0
- package/{billing → internal}/form-primitives.js +5 -9
- package/internal/form-primitives.js.map +1 -0
- package/manifest/ApplyManifestDialog.d.ts +10 -5
- package/manifest/ApplyManifestDialog.d.ts.map +1 -1
- package/manifest/ApplyManifestDialog.js +30 -13
- package/manifest/ApplyManifestDialog.js.map +1 -1
- package/manifest/useApplyManifest.d.ts +6 -2
- package/manifest/useApplyManifest.d.ts.map +1 -1
- package/manifest/useApplyManifest.js +5 -5
- package/manifest/useApplyManifest.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts +38 -2
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +21 -5
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/index.d.ts +7 -0
- package/mcp-server/index.d.ts.map +1 -1
- package/mcp-server/index.js +9 -0
- package/mcp-server/index.js.map +1 -1
- package/mcp-server/steps/EnvironmentAuthStep.d.ts +4 -0
- package/mcp-server/steps/EnvironmentAuthStep.d.ts.map +1 -1
- package/mcp-server/steps/EnvironmentAuthStep.js +4 -0
- package/mcp-server/steps/EnvironmentAuthStep.js.map +1 -1
- package/mcp-server/steps/IdentityTransportStep.d.ts +6 -0
- package/mcp-server/steps/IdentityTransportStep.d.ts.map +1 -1
- package/mcp-server/steps/IdentityTransportStep.js +7 -1
- package/mcp-server/steps/IdentityTransportStep.js.map +1 -1
- package/mcp-server/steps/ReviewStep.d.ts +5 -0
- package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
- package/mcp-server/steps/ReviewStep.js +16 -2
- package/mcp-server/steps/ReviewStep.js.map +1 -1
- package/mcp-server/useMcpServerCount.d.ts +2 -0
- package/mcp-server/useMcpServerCount.d.ts.map +1 -1
- package/mcp-server/useMcpServerCount.js.map +1 -1
- package/package.json +4 -4
- package/pricing-governance/BaselineEditor.d.ts.map +1 -0
- package/{billing → pricing-governance}/BaselineEditor.js +19 -2
- package/pricing-governance/BaselineEditor.js.map +1 -0
- package/pricing-governance/ModelCatalogPanel.d.ts.map +1 -0
- package/pricing-governance/ModelCatalogPanel.js.map +1 -0
- package/pricing-governance/ModelGovernanceDetail.d.ts.map +1 -0
- package/pricing-governance/ModelGovernanceDetail.js.map +1 -0
- package/pricing-governance/OperatorAccessNotice.d.ts.map +1 -0
- package/pricing-governance/OperatorAccessNotice.js.map +1 -0
- package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -0
- package/{billing → pricing-governance}/PricingGovernanceConsole.js +1 -1
- package/pricing-governance/PricingGovernanceConsole.js.map +1 -0
- package/pricing-governance/PricingGovernancePanel.d.ts.map +1 -0
- package/pricing-governance/PricingGovernancePanel.js.map +1 -0
- package/pricing-governance/RetireConfirm.d.ts.map +1 -0
- package/{billing → pricing-governance}/RetireConfirm.js +1 -1
- package/pricing-governance/RetireConfirm.js.map +1 -0
- package/pricing-governance/governance-primitives.d.ts.map +1 -0
- package/pricing-governance/governance-primitives.js.map +1 -0
- package/pricing-governance/index.d.ts +19 -0
- package/pricing-governance/index.d.ts.map +1 -0
- package/pricing-governance/index.js +20 -0
- package/pricing-governance/index.js.map +1 -0
- package/pricing-governance/pricing-format.d.ts.map +1 -0
- package/pricing-governance/pricing-format.js.map +1 -0
- package/pricing-governance/useDecidePricingOverride.d.ts.map +1 -0
- package/pricing-governance/useDecidePricingOverride.js.map +1 -0
- package/pricing-governance/useModelGovernanceView.d.ts.map +1 -0
- package/pricing-governance/useModelGovernanceView.js.map +1 -0
- package/pricing-governance/useModelPricingBaselines.d.ts.map +1 -0
- package/pricing-governance/useModelPricingBaselines.js.map +1 -0
- package/pricing-governance/usePricingGovernance.d.ts.map +1 -0
- package/pricing-governance/usePricingGovernance.js.map +1 -0
- package/pricing-governance/useRetireModelPricingBaseline.d.ts.map +1 -0
- package/pricing-governance/useRetireModelPricingBaseline.js.map +1 -0
- package/pricing-governance/useUpsertModelPricingBaseline.d.ts.map +1 -0
- package/pricing-governance/useUpsertModelPricingBaseline.js.map +1 -0
- package/resource-creation/CreationPicker.d.ts.map +1 -1
- package/resource-creation/CreationPicker.js +3 -3
- package/resource-creation/CreationPicker.js.map +1 -1
- package/resource-creation/WizardNav.d.ts.map +1 -1
- package/resource-creation/WizardNav.js +1 -1
- package/resource-creation/WizardNav.js.map +1 -1
- package/resource-detail/Section.d.ts +8 -1
- package/resource-detail/Section.d.ts.map +1 -1
- package/resource-detail/Section.js +2 -2
- package/resource-detail/Section.js.map +1 -1
- package/resource-workbench/components/ResourceWorkbench.d.ts +9 -1
- package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -1
- package/resource-workbench/components/ResourceWorkbench.js +2 -1
- package/resource-workbench/components/ResourceWorkbench.js.map +1 -1
- package/resource-workbench/hooks/useResourceCollection.d.ts +9 -0
- package/resource-workbench/hooks/useResourceCollection.d.ts.map +1 -1
- package/resource-workbench/hooks/useResourceCollection.js +2 -2
- package/resource-workbench/hooks/useResourceCollection.js.map +1 -1
- package/search/useResourceCount.d.ts +7 -0
- package/search/useResourceCount.d.ts.map +1 -1
- package/search/useResourceCount.js +2 -1
- package/search/useResourceCount.js.map +1 -1
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +17 -3
- package/session/NewSessionViewer.js.map +1 -1
- package/session/SessionViewer.d.ts +2 -1
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +19 -11
- package/session/SessionViewer.js.map +1 -1
- package/session/SessionViewerLayout.d.ts +90 -0
- package/session/SessionViewerLayout.d.ts.map +1 -0
- package/session/SessionViewerLayout.js +32 -0
- package/session/SessionViewerLayout.js.map +1 -0
- package/session/index.d.ts +4 -0
- package/session/index.d.ts.map +1 -1
- package/session/index.js +10 -0
- package/session/index.js.map +1 -1
- package/session/useCreateSession.d.ts +28 -0
- package/session/useCreateSession.d.ts.map +1 -1
- package/session/useCreateSession.js +2 -1
- package/session/useCreateSession.js.map +1 -1
- package/session/useNewSessionFlow.d.ts +30 -0
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +7 -1
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useSessionRailViews.d.ts +2 -2
- package/session/useUpdateSession.d.ts +29 -10
- package/session/useUpdateSession.d.ts.map +1 -1
- package/session/useUpdateSession.js +29 -10
- package/session/useUpdateSession.js.map +1 -1
- package/skill/useSkillCount.d.ts +2 -0
- package/skill/useSkillCount.d.ts.map +1 -1
- package/skill/useSkillCount.js.map +1 -1
- package/src/agent/useAgentCount.ts +2 -0
- package/src/api-key/CreateApiKeyForm.tsx +8 -1
- package/src/api-key/__tests__/CreateApiKeyForm.test.tsx +58 -0
- package/src/billing/index.ts +5 -37
- package/src/cursor-accounts/CursorAccountEditor.tsx +61 -13
- package/src/cursor-accounts/CursorAccountsConsole.tsx +44 -400
- package/src/cursor-accounts/MemberCoverageTable.tsx +439 -0
- package/src/cursor-accounts/MemberKeysPanel.tsx +278 -0
- package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +306 -10
- package/src/cursor-accounts/__tests__/cursor-account-coverage.test.ts +73 -0
- package/src/cursor-accounts/badges.tsx +26 -0
- package/src/cursor-accounts/cursor-account-coverage.ts +71 -0
- package/src/cursor-accounts/cursor-account-format.ts +17 -1
- package/src/datastore/CollectionRecordsBrowser.tsx +29 -3
- package/src/datastore/RecordFilterBuilder.tsx +12 -1
- package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +38 -0
- package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +14 -0
- package/src/datastore/__tests__/recordFilter.test.ts +13 -0
- package/src/datastore/recordFilter.ts +15 -1
- package/src/datastore/useDatastoreCount.ts +2 -0
- package/src/execution/ExecutionProgress.tsx +14 -4
- package/src/execution/MessageThread.tsx +10 -2
- package/src/execution/__tests__/ExecutionProgress.test.tsx +67 -0
- package/src/execution/__tests__/MessageThread.test.tsx +44 -0
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +86 -0
- package/src/execution/useCreateAgentExecution.ts +41 -6
- package/src/index.ts +43 -24
- package/src/{billing → internal}/form-primitives.tsx +4 -32
- package/src/manifest/ApplyManifestDialog.tsx +40 -16
- package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +147 -0
- package/src/manifest/__tests__/useApplyManifest.test.tsx +6 -6
- package/src/manifest/useApplyManifest.ts +12 -8
- package/src/mcp-server/McpServerDetailView.tsx +52 -4
- package/src/mcp-server/__tests__/McpServerDetailView.test.tsx +345 -0
- package/src/mcp-server/index.ts +13 -0
- package/src/mcp-server/steps/EnvironmentAuthStep.tsx +4 -0
- package/src/mcp-server/steps/IdentityTransportStep.tsx +9 -1
- package/src/mcp-server/steps/ReviewStep.tsx +18 -1
- package/src/mcp-server/useMcpServerCount.ts +2 -0
- package/src/{billing → pricing-governance}/BaselineEditor.tsx +36 -3
- package/src/{billing → pricing-governance}/PricingGovernanceConsole.tsx +1 -1
- package/src/{billing → pricing-governance}/RetireConfirm.tsx +1 -1
- package/src/pricing-governance/index.ts +50 -0
- package/src/resource-creation/CreationPicker.tsx +7 -0
- package/src/resource-creation/WizardNav.tsx +1 -0
- package/src/resource-detail/Section.tsx +9 -1
- package/src/resource-workbench/components/ResourceWorkbench.tsx +13 -0
- package/src/resource-workbench/hooks/useResourceCollection.ts +11 -1
- package/src/search/useResourceCount.ts +9 -1
- package/src/session/NewSessionViewer.tsx +48 -61
- package/src/session/SessionViewer.tsx +71 -86
- package/src/session/SessionViewerLayout.tsx +131 -0
- package/src/session/__tests__/SessionViewerLayout.test.tsx +140 -0
- package/src/session/__tests__/useCreateSession.test.tsx +94 -0
- package/src/session/__tests__/useNewSessionFlow.test.tsx +33 -0
- package/src/session/index.ts +14 -0
- package/src/session/useCreateSession.ts +30 -0
- package/src/session/useNewSessionFlow.ts +45 -1
- package/src/session/useSessionRailViews.tsx +2 -2
- package/src/session/useUpdateSession.ts +29 -10
- package/src/skill/useSkillCount.ts +2 -0
- package/src/test/__tests__/samples.test.ts +159 -2
- package/src/test/index.ts +1 -1
- package/src/test/samples.ts +109 -14
- package/src/workflow/useWorkflowCount.ts +2 -0
- package/styles.css +1 -1
- package/test/index.d.ts +1 -1
- package/test/index.d.ts.map +1 -1
- package/test/index.js +1 -1
- package/test/index.js.map +1 -1
- package/test/samples.d.ts +79 -7
- package/test/samples.d.ts.map +1 -1
- package/test/samples.js +101 -14
- package/test/samples.js.map +1 -1
- package/workflow/useWorkflowCount.d.ts +2 -0
- package/workflow/useWorkflowCount.d.ts.map +1 -1
- package/workflow/useWorkflowCount.js.map +1 -1
- package/billing/BaselineEditor.d.ts.map +0 -1
- package/billing/BaselineEditor.js.map +0 -1
- package/billing/ModelCatalogPanel.d.ts.map +0 -1
- package/billing/ModelCatalogPanel.js.map +0 -1
- package/billing/ModelGovernanceDetail.d.ts.map +0 -1
- package/billing/ModelGovernanceDetail.js.map +0 -1
- package/billing/OperatorAccessNotice.d.ts.map +0 -1
- package/billing/OperatorAccessNotice.js.map +0 -1
- package/billing/PricingGovernanceConsole.d.ts.map +0 -1
- package/billing/PricingGovernanceConsole.js.map +0 -1
- package/billing/PricingGovernancePanel.d.ts.map +0 -1
- package/billing/PricingGovernancePanel.js.map +0 -1
- package/billing/RetireConfirm.d.ts.map +0 -1
- package/billing/RetireConfirm.js.map +0 -1
- package/billing/form-primitives.d.ts +0 -18
- package/billing/form-primitives.d.ts.map +0 -1
- package/billing/form-primitives.js.map +0 -1
- package/billing/governance-primitives.d.ts.map +0 -1
- package/billing/governance-primitives.js.map +0 -1
- package/billing/pricing-format.d.ts.map +0 -1
- package/billing/pricing-format.js.map +0 -1
- package/billing/useDecidePricingOverride.d.ts.map +0 -1
- package/billing/useDecidePricingOverride.js.map +0 -1
- package/billing/useModelGovernanceView.d.ts.map +0 -1
- package/billing/useModelGovernanceView.js.map +0 -1
- package/billing/useModelPricingBaselines.d.ts.map +0 -1
- package/billing/useModelPricingBaselines.js.map +0 -1
- package/billing/usePricingGovernance.d.ts.map +0 -1
- package/billing/usePricingGovernance.js.map +0 -1
- package/billing/useRetireModelPricingBaseline.d.ts.map +0 -1
- package/billing/useRetireModelPricingBaseline.js.map +0 -1
- package/billing/useUpsertModelPricingBaseline.d.ts.map +0 -1
- package/billing/useUpsertModelPricingBaseline.js.map +0 -1
- /package/{billing → pricing-governance}/BaselineEditor.d.ts +0 -0
- /package/{billing → pricing-governance}/ModelCatalogPanel.d.ts +0 -0
- /package/{billing → pricing-governance}/ModelCatalogPanel.js +0 -0
- /package/{billing → pricing-governance}/ModelGovernanceDetail.d.ts +0 -0
- /package/{billing → pricing-governance}/ModelGovernanceDetail.js +0 -0
- /package/{billing → pricing-governance}/OperatorAccessNotice.d.ts +0 -0
- /package/{billing → pricing-governance}/OperatorAccessNotice.js +0 -0
- /package/{billing → pricing-governance}/PricingGovernanceConsole.d.ts +0 -0
- /package/{billing → pricing-governance}/PricingGovernancePanel.d.ts +0 -0
- /package/{billing → pricing-governance}/PricingGovernancePanel.js +0 -0
- /package/{billing → pricing-governance}/RetireConfirm.d.ts +0 -0
- /package/{billing → pricing-governance}/governance-primitives.d.ts +0 -0
- /package/{billing → pricing-governance}/governance-primitives.js +0 -0
- /package/{billing → pricing-governance}/pricing-format.d.ts +0 -0
- /package/{billing → pricing-governance}/pricing-format.js +0 -0
- /package/{billing → pricing-governance}/useDecidePricingOverride.d.ts +0 -0
- /package/{billing → pricing-governance}/useDecidePricingOverride.js +0 -0
- /package/{billing → pricing-governance}/useModelGovernanceView.d.ts +0 -0
- /package/{billing → pricing-governance}/useModelGovernanceView.js +0 -0
- /package/{billing → pricing-governance}/useModelPricingBaselines.d.ts +0 -0
- /package/{billing → pricing-governance}/useModelPricingBaselines.js +0 -0
- /package/{billing → pricing-governance}/usePricingGovernance.d.ts +0 -0
- /package/{billing → pricing-governance}/usePricingGovernance.js +0 -0
- /package/{billing → pricing-governance}/useRetireModelPricingBaseline.d.ts +0 -0
- /package/{billing → pricing-governance}/useRetireModelPricingBaseline.js +0 -0
- /package/{billing → pricing-governance}/useUpsertModelPricingBaseline.d.ts +0 -0
- /package/{billing → pricing-governance}/useUpsertModelPricingBaseline.js +0 -0
- /package/src/{billing → pricing-governance}/ModelCatalogPanel.tsx +0 -0
- /package/src/{billing → pricing-governance}/ModelGovernanceDetail.tsx +0 -0
- /package/src/{billing → pricing-governance}/OperatorAccessNotice.tsx +0 -0
- /package/src/{billing → pricing-governance}/PricingGovernancePanel.tsx +0 -0
- /package/src/{billing → pricing-governance}/__tests__/ModelCatalogPanel.test.tsx +0 -0
- /package/src/{billing → pricing-governance}/__tests__/PricingGovernanceConsole.test.tsx +0 -0
- /package/src/{billing → pricing-governance}/__tests__/useModelGovernanceView.test.tsx +0 -0
- /package/src/{billing → pricing-governance}/governance-primitives.tsx +0 -0
- /package/src/{billing → pricing-governance}/pricing-format.ts +0 -0
- /package/src/{billing → pricing-governance}/useDecidePricingOverride.ts +0 -0
- /package/src/{billing → pricing-governance}/useModelGovernanceView.ts +0 -0
- /package/src/{billing → pricing-governance}/useModelPricingBaselines.ts +0 -0
- /package/src/{billing → pricing-governance}/usePricingGovernance.ts +0 -0
- /package/src/{billing → pricing-governance}/useRetireModelPricingBaseline.ts +0 -0
- /package/src/{billing → pricing-governance}/useUpsertModelPricingBaseline.ts +0 -0
|
@@ -137,6 +137,92 @@ describe("useCreateAgentExecution — one-call session bootstrap (sessionSpec)",
|
|
|
137
137
|
expect(input.sessionSpec.executionTarget).toBeUndefined();
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
+
it("passes the metadata map through on the bootstrap spec", async () => {
|
|
141
|
+
const { result } = renderHook(() => useCreateAgentExecution(), {
|
|
142
|
+
wrapper: createWrapper(makeMockClient()),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await act(async () => {
|
|
146
|
+
await result.current.create({
|
|
147
|
+
org: "acme",
|
|
148
|
+
message: "Hello",
|
|
149
|
+
sessionSpec: {
|
|
150
|
+
agentInstanceId: "ain-1",
|
|
151
|
+
metadata: { "acme/tenant": "t-1" },
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const input = mockCreate.mock.calls[0][0];
|
|
157
|
+
expect(input.sessionSpec.metadata).toEqual({ "acme/tenant": "t-1" });
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("maps the typed sessionContext onto the reserved metadata key", async () => {
|
|
161
|
+
const { result } = renderHook(() => useCreateAgentExecution(), {
|
|
162
|
+
wrapper: createWrapper(makeMockClient()),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
await act(async () => {
|
|
166
|
+
await result.current.create({
|
|
167
|
+
org: "acme",
|
|
168
|
+
message: "Hello",
|
|
169
|
+
sessionSpec: {
|
|
170
|
+
agentInstanceId: "ain-1",
|
|
171
|
+
sessionContext: "Role: platform admin",
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const input = mockCreate.mock.calls[0][0];
|
|
177
|
+
expect(input.sessionSpec.metadata).toEqual({
|
|
178
|
+
"stigmer.ai/session-context": "Role: platform admin",
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("lets the typed sessionContext win over a raw entry under the reserved key", async () => {
|
|
183
|
+
const { result } = renderHook(() => useCreateAgentExecution(), {
|
|
184
|
+
wrapper: createWrapper(makeMockClient()),
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
await act(async () => {
|
|
188
|
+
await result.current.create({
|
|
189
|
+
org: "acme",
|
|
190
|
+
message: "Hello",
|
|
191
|
+
sessionSpec: {
|
|
192
|
+
agentInstanceId: "ain-1",
|
|
193
|
+
metadata: {
|
|
194
|
+
"acme/tenant": "t-1",
|
|
195
|
+
"stigmer.ai/session-context": "stale raw value",
|
|
196
|
+
},
|
|
197
|
+
sessionContext: "typed value",
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
const input = mockCreate.mock.calls[0][0];
|
|
203
|
+
expect(input.sessionSpec.metadata).toEqual({
|
|
204
|
+
"acme/tenant": "t-1",
|
|
205
|
+
"stigmer.ai/session-context": "typed value",
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("omits metadata entirely when neither field is provided", async () => {
|
|
210
|
+
const { result } = renderHook(() => useCreateAgentExecution(), {
|
|
211
|
+
wrapper: createWrapper(makeMockClient()),
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
await act(async () => {
|
|
215
|
+
await result.current.create({
|
|
216
|
+
org: "acme",
|
|
217
|
+
message: "Hello",
|
|
218
|
+
sessionSpec: { agentInstanceId: "ain-1" },
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const input = mockCreate.mock.calls[0][0];
|
|
223
|
+
expect(input.sessionSpec.metadata).toBeUndefined();
|
|
224
|
+
});
|
|
225
|
+
|
|
140
226
|
it("returns the server-assigned session id from the bootstrap response", async () => {
|
|
141
227
|
mockCreate.mockResolvedValueOnce({
|
|
142
228
|
metadata: { id: "aex-1" },
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useState } from "react";
|
|
4
4
|
import type { JsonObject } from "@bufbuild/protobuf";
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
import {
|
|
6
|
+
mergeSessionContext,
|
|
7
|
+
type AttachmentInput,
|
|
8
|
+
type EnvVarInput,
|
|
9
|
+
type McpServerUsageInput,
|
|
10
|
+
type ResourceRef,
|
|
11
|
+
type WorkspaceEntryInput,
|
|
11
12
|
} from "@stigmer/sdk";
|
|
12
13
|
import { useStigmer } from "../hooks.js";
|
|
13
14
|
import { toError } from "../internal/toError.js";
|
|
@@ -41,6 +42,36 @@ export interface BootstrapSessionSpec {
|
|
|
41
42
|
readonly mcpServerUsages?: McpServerUsageInput[];
|
|
42
43
|
/** Skill references to enable for executions in this session. */
|
|
43
44
|
readonly skillRefs?: ResourceRef[];
|
|
45
|
+
/**
|
|
46
|
+
* Custom key-value pairs stored on the created session's
|
|
47
|
+
* `SessionSpec.metadata`.
|
|
48
|
+
*
|
|
49
|
+
* A passthrough for embedder-owned keys (correlation IDs, tenant tags)
|
|
50
|
+
* and for platform-reserved `stigmer.ai/*` keys set explicitly. For the
|
|
51
|
+
* common case — standing user context injected into the agent's prompt —
|
|
52
|
+
* prefer the typed {@link sessionContext} field, which maps onto the
|
|
53
|
+
* reserved `stigmer.ai/session-context` key and wins over a raw entry
|
|
54
|
+
* under that key when both are provided.
|
|
55
|
+
*/
|
|
56
|
+
readonly metadata?: Record<string, string>;
|
|
57
|
+
/**
|
|
58
|
+
* Standing, per-user context the agent receives on every turn but the
|
|
59
|
+
* conversation UI never renders — who the caller is, their experience
|
|
60
|
+
* level, their standing instructions (stigmer/stigmer#286).
|
|
61
|
+
*
|
|
62
|
+
* Stored on the created session's `SessionSpec.metadata` under
|
|
63
|
+
* `stigmer.ai/session-context`; the agent runner injects it into the
|
|
64
|
+
* system prompt as already-known background, so agents can greet the
|
|
65
|
+
* user by name and calibrate depth/defaults from the first turn without
|
|
66
|
+
* a visible context preamble.
|
|
67
|
+
*
|
|
68
|
+
* Personalization, not authorization: anyone who can create the session
|
|
69
|
+
* can set this (the same trust level as authoring the first message).
|
|
70
|
+
* Hidden from the conversation thread, not from the API — `session.get`
|
|
71
|
+
* returns it, so never put secrets here; secrets belong in `runtimeEnv`
|
|
72
|
+
* or Environment resources. Large values bloat every prompt.
|
|
73
|
+
*/
|
|
74
|
+
readonly sessionContext?: string;
|
|
44
75
|
/** Execution harness. Immutable after the first execution runs. */
|
|
45
76
|
readonly harness?: HarnessOption;
|
|
46
77
|
/** Where session activities execute. Immutable after the first execution runs. */
|
|
@@ -293,6 +324,10 @@ export function useCreateAgentExecution(): UseCreateAgentExecutionReturn {
|
|
|
293
324
|
workspaceEntries: input.sessionSpec.workspaceEntries,
|
|
294
325
|
mcpServerUsages: input.sessionSpec.mcpServerUsages,
|
|
295
326
|
skillRefs: input.sessionSpec.skillRefs,
|
|
327
|
+
metadata: mergeSessionContext(
|
|
328
|
+
input.sessionSpec.metadata,
|
|
329
|
+
input.sessionSpec.sessionContext,
|
|
330
|
+
),
|
|
296
331
|
harness: input.sessionSpec.harness
|
|
297
332
|
? toProtoHarness(input.sessionSpec.harness)
|
|
298
333
|
: undefined,
|
package/src/index.ts
CHANGED
|
@@ -156,7 +156,9 @@ export {
|
|
|
156
156
|
channelSessionExternalUserKey,
|
|
157
157
|
SessionViewer,
|
|
158
158
|
NewSessionViewer,
|
|
159
|
+
SessionViewerLayout,
|
|
159
160
|
useSessionPanel,
|
|
161
|
+
useSessionRailViews,
|
|
160
162
|
usePlanDraft,
|
|
161
163
|
planDraftKey,
|
|
162
164
|
PlanEditor,
|
|
@@ -201,8 +203,10 @@ export type {
|
|
|
201
203
|
SearchResultGroup,
|
|
202
204
|
SessionViewerProps,
|
|
203
205
|
NewSessionViewerProps,
|
|
206
|
+
SessionViewerLayoutProps,
|
|
204
207
|
SessionPanelController,
|
|
205
208
|
UseSessionPanelOptions,
|
|
209
|
+
UseSessionRailViewsOptions,
|
|
206
210
|
PlanDraftController,
|
|
207
211
|
PlanEditorProps,
|
|
208
212
|
PlanStreamingDocumentProps,
|
|
@@ -526,6 +530,10 @@ export {
|
|
|
526
530
|
useUpdateMcpServer,
|
|
527
531
|
mcpServerToInput,
|
|
528
532
|
toServerKey,
|
|
533
|
+
IdentityTransportStep,
|
|
534
|
+
EnvironmentAuthStep,
|
|
535
|
+
ReviewStep,
|
|
536
|
+
createInitialMcpServerWizardData,
|
|
529
537
|
} from "./mcp-server/index.js";
|
|
530
538
|
export type {
|
|
531
539
|
UseMcpServerReturn,
|
|
@@ -563,6 +571,9 @@ export type {
|
|
|
563
571
|
McpServerCreationWizardProps,
|
|
564
572
|
McpServerCreationResult,
|
|
565
573
|
McpServerWizardData,
|
|
574
|
+
IdentityTransportStepProps,
|
|
575
|
+
EnvironmentAuthStepProps,
|
|
576
|
+
ReviewStepProps,
|
|
566
577
|
} from "./mcp-server/index.js";
|
|
567
578
|
|
|
568
579
|
// Skill — data hooks, upload, file browser, and mutation
|
|
@@ -909,21 +920,16 @@ export type {
|
|
|
909
920
|
OrgSwitcherProps,
|
|
910
921
|
} from "./organization/index.js";
|
|
911
922
|
|
|
912
|
-
// Billing — data hooks, behavior hooks, styled components,
|
|
923
|
+
// Billing — customer-facing data hooks, behavior hooks, styled components,
|
|
924
|
+
// catalog, and formatting utilities
|
|
913
925
|
export {
|
|
914
926
|
useBillingAccount,
|
|
915
927
|
useCreditLedger,
|
|
916
928
|
useBillingUsageReport,
|
|
917
929
|
useCustomerModelPricing,
|
|
918
|
-
usePricingGovernance,
|
|
919
|
-
useModelPricingBaselines,
|
|
920
|
-
useModelGovernanceView,
|
|
921
930
|
useCreateCheckoutSession,
|
|
922
931
|
useCreateBillingPortalSession,
|
|
923
932
|
useSetAutoRechargeConfig,
|
|
924
|
-
useDecidePricingOverride,
|
|
925
|
-
useUpsertModelPricingBaseline,
|
|
926
|
-
useRetireModelPricingBaseline,
|
|
927
933
|
BillingSection,
|
|
928
934
|
CreditBalanceCard,
|
|
929
935
|
PaymentMethodCard,
|
|
@@ -931,9 +937,6 @@ export {
|
|
|
931
937
|
CreditPackGrid,
|
|
932
938
|
CreditLedgerTable,
|
|
933
939
|
LowBalanceBanner,
|
|
934
|
-
PricingGovernancePanel,
|
|
935
|
-
ModelCatalogPanel,
|
|
936
|
-
PricingGovernanceConsole,
|
|
937
940
|
CREDIT_PACKS,
|
|
938
941
|
formatPackPrice,
|
|
939
942
|
formatCreditCount,
|
|
@@ -950,23 +953,11 @@ export type {
|
|
|
950
953
|
UseCreditLedgerOptions,
|
|
951
954
|
UseBillingUsageReportReturn,
|
|
952
955
|
UseCustomerModelPricingReturn,
|
|
953
|
-
UsePricingGovernanceReturn,
|
|
954
|
-
UseModelPricingBaselinesOptions,
|
|
955
|
-
UseModelPricingBaselinesReturn,
|
|
956
|
-
GovernanceFlow,
|
|
957
|
-
ModelGovernanceRow,
|
|
958
|
-
UseModelGovernanceViewReturn,
|
|
959
956
|
CreateCheckoutSessionInput,
|
|
960
957
|
UseCreateCheckoutSessionReturn,
|
|
961
958
|
UseCreateBillingPortalSessionReturn,
|
|
962
959
|
SetAutoRechargeConfigInput,
|
|
963
960
|
UseSetAutoRechargeConfigReturn,
|
|
964
|
-
DecidePricingOverrideInput,
|
|
965
|
-
UseDecidePricingOverrideReturn,
|
|
966
|
-
UpsertModelPricingBaselineInput,
|
|
967
|
-
UseUpsertModelPricingBaselineReturn,
|
|
968
|
-
RetireModelPricingBaselineInput,
|
|
969
|
-
UseRetireModelPricingBaselineReturn,
|
|
970
961
|
BillingSectionProps,
|
|
971
962
|
CreditBalanceCardProps,
|
|
972
963
|
PaymentMethodCardProps,
|
|
@@ -974,12 +965,40 @@ export type {
|
|
|
974
965
|
CreditPackGridProps,
|
|
975
966
|
CreditLedgerTableProps,
|
|
976
967
|
LowBalanceBannerProps,
|
|
968
|
+
CreditPackInfo,
|
|
969
|
+
} from "./billing/index.js";
|
|
970
|
+
|
|
971
|
+
// Pricing governance — platform-operator authoring of the model registry
|
|
972
|
+
// baseline and pricing-override sign-offs (gated on can_manage_model_pricing)
|
|
973
|
+
export {
|
|
974
|
+
usePricingGovernance,
|
|
975
|
+
useModelPricingBaselines,
|
|
976
|
+
useModelGovernanceView,
|
|
977
|
+
useDecidePricingOverride,
|
|
978
|
+
useUpsertModelPricingBaseline,
|
|
979
|
+
useRetireModelPricingBaseline,
|
|
980
|
+
PricingGovernancePanel,
|
|
981
|
+
ModelCatalogPanel,
|
|
982
|
+
PricingGovernanceConsole,
|
|
983
|
+
} from "./pricing-governance/index.js";
|
|
984
|
+
export type {
|
|
985
|
+
UsePricingGovernanceReturn,
|
|
986
|
+
UseModelPricingBaselinesOptions,
|
|
987
|
+
UseModelPricingBaselinesReturn,
|
|
988
|
+
GovernanceFlow,
|
|
989
|
+
ModelGovernanceRow,
|
|
990
|
+
UseModelGovernanceViewReturn,
|
|
991
|
+
DecidePricingOverrideInput,
|
|
992
|
+
UseDecidePricingOverrideReturn,
|
|
993
|
+
UpsertModelPricingBaselineInput,
|
|
994
|
+
UseUpsertModelPricingBaselineReturn,
|
|
995
|
+
RetireModelPricingBaselineInput,
|
|
996
|
+
UseRetireModelPricingBaselineReturn,
|
|
977
997
|
PricingGovernancePanelProps,
|
|
978
998
|
ModelCatalogPanelProps,
|
|
979
999
|
PricingGovernanceConsoleProps,
|
|
980
1000
|
PricingGovernanceTab,
|
|
981
|
-
|
|
982
|
-
} from "./billing/index.js";
|
|
1001
|
+
} from "./pricing-governance/index.js";
|
|
983
1002
|
|
|
984
1003
|
// Cursor accounts — platform-operator management of managed Cursor teams
|
|
985
1004
|
// (admin keys, member execution keys, org assignments, roster/spend)
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
import { cn } from "@stigmer/theme";
|
|
4
4
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
|
-
// Shared form primitives for the operator
|
|
7
|
-
//
|
|
8
|
-
// from the
|
|
6
|
+
// Shared form primitives for the operator consoles (pricing-governance
|
|
7
|
+
// editors and search inputs, cursor-accounts editor and key forms).
|
|
8
|
+
// Internal — never exported from the package barrel.
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
|
|
11
|
-
/** Standard text-input styling for the
|
|
11
|
+
/** Standard text-input styling for the operator consoles. */
|
|
12
12
|
export const INPUT_CLASSES = cn(
|
|
13
13
|
"w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground",
|
|
14
14
|
"placeholder:text-muted-foreground",
|
|
@@ -38,31 +38,3 @@ export function Field({
|
|
|
38
38
|
</label>
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
/** Dollar-rate input field (decimal keypad, "$ per million tokens"). */
|
|
43
|
-
export function RateField({
|
|
44
|
-
label,
|
|
45
|
-
value,
|
|
46
|
-
placeholder,
|
|
47
|
-
disabled,
|
|
48
|
-
onChange,
|
|
49
|
-
}: {
|
|
50
|
-
readonly label: string;
|
|
51
|
-
readonly value: string;
|
|
52
|
-
readonly placeholder?: string;
|
|
53
|
-
readonly disabled: boolean;
|
|
54
|
-
readonly onChange: (value: string) => void;
|
|
55
|
-
}) {
|
|
56
|
-
return (
|
|
57
|
-
<Field label={label}>
|
|
58
|
-
<input
|
|
59
|
-
className={INPUT_CLASSES}
|
|
60
|
-
inputMode="decimal"
|
|
61
|
-
value={value}
|
|
62
|
-
onChange={(e) => onChange(e.target.value)}
|
|
63
|
-
placeholder={placeholder ?? "0.00"}
|
|
64
|
-
disabled={disabled}
|
|
65
|
-
/>
|
|
66
|
-
</Field>
|
|
67
|
-
);
|
|
68
|
-
}
|
|
@@ -23,10 +23,15 @@ export interface ApplyManifestDialogProps {
|
|
|
23
23
|
/** Target organization slug for documents that omit `metadata.org`. */
|
|
24
24
|
readonly org: string;
|
|
25
25
|
/**
|
|
26
|
-
* Called
|
|
27
|
-
*
|
|
26
|
+
* Called when the dialog closes after at least one document applied,
|
|
27
|
+
* with the applied entries in apply order — on full success, and also
|
|
28
|
+
* when the operator dismisses the dialog after a partial apply (some
|
|
29
|
+
* documents applied, a later one failed). Use it to refresh a list so
|
|
30
|
+
* the newly applied resources appear without a reload. It never fires
|
|
31
|
+
* when nothing applied, and fires once per close. Mirrors
|
|
32
|
+
* {@link EditResourceYamlDialog}'s `onApplied`.
|
|
28
33
|
*/
|
|
29
|
-
readonly
|
|
34
|
+
readonly onApplied?: (applied: readonly ManifestPreviewEntry[]) => void;
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
/**
|
|
@@ -56,7 +61,7 @@ export interface ApplyManifestDialogProps {
|
|
|
56
61
|
* open={open}
|
|
57
62
|
* onOpenChange={setOpen}
|
|
58
63
|
* org={activeOrg}
|
|
59
|
-
*
|
|
64
|
+
* onApplied={() => refetchList()}
|
|
60
65
|
* />
|
|
61
66
|
* ```
|
|
62
67
|
*/
|
|
@@ -64,7 +69,7 @@ export function ApplyManifestDialog({
|
|
|
64
69
|
open,
|
|
65
70
|
onOpenChange,
|
|
66
71
|
org,
|
|
67
|
-
|
|
72
|
+
onApplied,
|
|
68
73
|
}: ApplyManifestDialogProps) {
|
|
69
74
|
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
70
75
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
@@ -90,12 +95,26 @@ export function ApplyManifestDialog({
|
|
|
90
95
|
}
|
|
91
96
|
}, [open, reset]);
|
|
92
97
|
|
|
98
|
+
// Close the dialog and, if any document applied this session, refresh
|
|
99
|
+
// the caller's list. This is the dismiss-after-partial path: some
|
|
100
|
+
// documents applied before a later one failed, and the operator closes
|
|
101
|
+
// the dialog rather than retrying — those applied resources must still
|
|
102
|
+
// appear. The full-success path in `handleApply` fires `onApplied`
|
|
103
|
+
// itself (it holds the fresh applied list), so it never routes here.
|
|
104
|
+
const closeAndMaybeRefresh = useCallback(() => {
|
|
105
|
+
onOpenChange(false);
|
|
106
|
+
const applied = (manifest.entries ?? []).filter(
|
|
107
|
+
(e) => e.status === "applied",
|
|
108
|
+
);
|
|
109
|
+
if (applied.length > 0) onApplied?.(applied);
|
|
110
|
+
}, [onOpenChange, manifest.entries, onApplied]);
|
|
111
|
+
|
|
93
112
|
const handleCancel = useCallback(
|
|
94
113
|
(e: React.SyntheticEvent) => {
|
|
95
114
|
e.preventDefault();
|
|
96
|
-
|
|
115
|
+
closeAndMaybeRefresh();
|
|
97
116
|
},
|
|
98
|
-
[
|
|
117
|
+
[closeAndMaybeRefresh],
|
|
99
118
|
);
|
|
100
119
|
|
|
101
120
|
const handleFileChange = useCallback(
|
|
@@ -107,18 +126,23 @@ export function ApplyManifestDialog({
|
|
|
107
126
|
);
|
|
108
127
|
|
|
109
128
|
const handleApply = useCallback(async () => {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
129
|
+
const results = await manifest.applyAll();
|
|
130
|
+
const applied = results.filter((e) => e.status === "applied");
|
|
131
|
+
const allApplied = results.length > 0 && applied.length === results.length;
|
|
132
|
+
if (allApplied) {
|
|
113
133
|
toast.success(
|
|
114
|
-
|
|
134
|
+
applied.length === 1
|
|
135
|
+
? "Resource applied"
|
|
136
|
+
: `${applied.length} resources applied`,
|
|
115
137
|
);
|
|
116
138
|
onOpenChange(false);
|
|
117
|
-
|
|
139
|
+
onApplied?.(applied);
|
|
118
140
|
}
|
|
119
|
-
// On failure the dialog stays open — per-entry status
|
|
120
|
-
// applied and what failed.
|
|
121
|
-
|
|
141
|
+
// On partial/total failure the dialog stays open — per-entry status
|
|
142
|
+
// shows what applied and what failed. Any entries that DID apply
|
|
143
|
+
// still refresh the caller's list when the dialog is dismissed
|
|
144
|
+
// (closeAndMaybeRefresh), so successful writes are never hidden.
|
|
145
|
+
}, [manifest, onOpenChange, onApplied]);
|
|
122
146
|
|
|
123
147
|
const canApply =
|
|
124
148
|
manifest.entries !== null &&
|
|
@@ -198,7 +222,7 @@ export function ApplyManifestDialog({
|
|
|
198
222
|
<div className="flex gap-2">
|
|
199
223
|
<button
|
|
200
224
|
type="button"
|
|
201
|
-
onClick={
|
|
225
|
+
onClick={closeAndMaybeRefresh}
|
|
202
226
|
disabled={manifest.isApplying}
|
|
203
227
|
className={cn(
|
|
204
228
|
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Tests for ApplyManifestDialog's onApplied contract — the refresh
|
|
2
|
+
// signal every Library list page wires to appear-without-reload. It must
|
|
3
|
+
// fire on full success AND when the operator dismisses the dialog after a
|
|
4
|
+
// partial apply (some documents applied, a later one failed), and must
|
|
5
|
+
// never fire when nothing applied. Historically onApplied's predecessor
|
|
6
|
+
// had zero coverage and stayed unwired at every call site; this locks the
|
|
7
|
+
// contract the list pages now depend on.
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, vi, beforeAll, afterEach } from "vitest";
|
|
10
|
+
import { render, screen, cleanup, fireEvent, waitFor } from "@testing-library/react";
|
|
11
|
+
import { ApplyManifestDialog } from "../ApplyManifestDialog";
|
|
12
|
+
import type {
|
|
13
|
+
ManifestPreviewEntry,
|
|
14
|
+
UseApplyManifestReturn,
|
|
15
|
+
} from "../useApplyManifest";
|
|
16
|
+
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
HTMLDialogElement.prototype.showModal = function showModal() {
|
|
19
|
+
this.open = true;
|
|
20
|
+
};
|
|
21
|
+
HTMLDialogElement.prototype.close = function close() {
|
|
22
|
+
this.open = false;
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
cleanup();
|
|
28
|
+
vi.restoreAllMocks();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// A preview entry in a chosen terminal status; the document shape is only
|
|
32
|
+
// what the dialog's preview row and apply flow read.
|
|
33
|
+
function entry(
|
|
34
|
+
slug: string,
|
|
35
|
+
status: ManifestPreviewEntry["status"],
|
|
36
|
+
): ManifestPreviewEntry {
|
|
37
|
+
return {
|
|
38
|
+
document: {
|
|
39
|
+
handler: { yamlKind: "datastore", displayName: "Datastore" },
|
|
40
|
+
name: slug,
|
|
41
|
+
slug,
|
|
42
|
+
org: "acme",
|
|
43
|
+
},
|
|
44
|
+
action: "create",
|
|
45
|
+
status,
|
|
46
|
+
} as ManifestPreviewEntry;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The mock's mutable knobs: the entries the hook exposes and the terminal
|
|
50
|
+
// entries applyAll resolves to. Set per test before rendering.
|
|
51
|
+
let mockEntries: readonly ManifestPreviewEntry[] | null;
|
|
52
|
+
let applyAllResult: readonly ManifestPreviewEntry[];
|
|
53
|
+
const applyAllMock = vi.fn(async () => applyAllResult);
|
|
54
|
+
|
|
55
|
+
vi.mock("../useApplyManifest", () => ({
|
|
56
|
+
useApplyManifest: (): UseApplyManifestReturn =>
|
|
57
|
+
({
|
|
58
|
+
content: "kind: Datastore",
|
|
59
|
+
setContent: vi.fn(),
|
|
60
|
+
readFile: vi.fn(),
|
|
61
|
+
entries: mockEntries,
|
|
62
|
+
validationError: null,
|
|
63
|
+
isValidating: false,
|
|
64
|
+
hasRedactedSecrets: false,
|
|
65
|
+
applyAll: applyAllMock,
|
|
66
|
+
isApplying: false,
|
|
67
|
+
reset: vi.fn(),
|
|
68
|
+
}) as UseApplyManifestReturn,
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
// CodeMirror stays out of the test environment.
|
|
72
|
+
vi.mock("../YamlEditor", () => ({
|
|
73
|
+
YamlEditor: () => <div data-testid="yaml-editor" />,
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
describe("ApplyManifestDialog — onApplied", () => {
|
|
77
|
+
it("fires with the applied entries on full success and closes", async () => {
|
|
78
|
+
mockEntries = [entry("a", "pending"), entry("b", "pending")];
|
|
79
|
+
applyAllResult = [entry("a", "applied"), entry("b", "applied")];
|
|
80
|
+
const onApplied = vi.fn();
|
|
81
|
+
const onOpenChange = vi.fn();
|
|
82
|
+
|
|
83
|
+
render(
|
|
84
|
+
<ApplyManifestDialog
|
|
85
|
+
open
|
|
86
|
+
onOpenChange={onOpenChange}
|
|
87
|
+
org="acme"
|
|
88
|
+
onApplied={onApplied}
|
|
89
|
+
/>,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
fireEvent.click(screen.getByRole("button", { name: /apply/i }));
|
|
93
|
+
|
|
94
|
+
await waitFor(() => expect(onApplied).toHaveBeenCalledTimes(1));
|
|
95
|
+
expect(
|
|
96
|
+
onApplied.mock.calls[0][0].map((e: ManifestPreviewEntry) => e.document.slug),
|
|
97
|
+
).toEqual(["a", "b"]);
|
|
98
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("fires with only the applied subset when a partial apply is dismissed", async () => {
|
|
102
|
+
// Applied one, failed the next — the dialog stays open on failure.
|
|
103
|
+
mockEntries = [entry("a", "applied"), entry("b", "failed")];
|
|
104
|
+
applyAllResult = [entry("a", "applied"), entry("b", "failed")];
|
|
105
|
+
const onApplied = vi.fn();
|
|
106
|
+
const onOpenChange = vi.fn();
|
|
107
|
+
|
|
108
|
+
render(
|
|
109
|
+
<ApplyManifestDialog
|
|
110
|
+
open
|
|
111
|
+
onOpenChange={onOpenChange}
|
|
112
|
+
org="acme"
|
|
113
|
+
onApplied={onApplied}
|
|
114
|
+
/>,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Apply first: full success did not happen, so onApplied has not fired.
|
|
118
|
+
fireEvent.click(screen.getByRole("button", { name: /apply/i }));
|
|
119
|
+
await waitFor(() => expect(applyAllMock).toHaveBeenCalled());
|
|
120
|
+
expect(onApplied).not.toHaveBeenCalled();
|
|
121
|
+
|
|
122
|
+
// Dismiss with an applied entry present → refresh the list.
|
|
123
|
+
fireEvent.click(screen.getByRole("button", { name: "Cancel" }));
|
|
124
|
+
expect(onApplied).toHaveBeenCalledTimes(1);
|
|
125
|
+
expect(
|
|
126
|
+
onApplied.mock.calls[0][0].map((e: ManifestPreviewEntry) => e.document.slug),
|
|
127
|
+
).toEqual(["a"]);
|
|
128
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("does not fire when the dialog is dismissed with nothing applied", () => {
|
|
132
|
+
mockEntries = [entry("a", "pending")];
|
|
133
|
+
const onApplied = vi.fn();
|
|
134
|
+
|
|
135
|
+
render(
|
|
136
|
+
<ApplyManifestDialog
|
|
137
|
+
open
|
|
138
|
+
onOpenChange={vi.fn()}
|
|
139
|
+
org="acme"
|
|
140
|
+
onApplied={onApplied}
|
|
141
|
+
/>,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
fireEvent.click(screen.getByRole("button", { name: "Cancel" }));
|
|
145
|
+
expect(onApplied).not.toHaveBeenCalled();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
@@ -174,12 +174,12 @@ describe("useApplyManifest", () => {
|
|
|
174
174
|
});
|
|
175
175
|
await act(settleValidation);
|
|
176
176
|
|
|
177
|
-
let
|
|
177
|
+
let applied: readonly { status: string }[] = [];
|
|
178
178
|
await act(async () => {
|
|
179
|
-
|
|
179
|
+
applied = await result.current.applyAll();
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
-
expect(
|
|
182
|
+
expect(applied.map((e) => e.status)).toEqual(["applied", "applied"]);
|
|
183
183
|
expect(apply).toHaveBeenCalledTimes(2);
|
|
184
184
|
expect(result.current.entries!.map((e) => e.status)).toEqual([
|
|
185
185
|
"applied",
|
|
@@ -201,12 +201,12 @@ describe("useApplyManifest", () => {
|
|
|
201
201
|
});
|
|
202
202
|
await act(settleValidation);
|
|
203
203
|
|
|
204
|
-
let
|
|
204
|
+
let applied: readonly { status: string }[] = [];
|
|
205
205
|
await act(async () => {
|
|
206
|
-
|
|
206
|
+
applied = await result.current.applyAll();
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
-
expect(
|
|
209
|
+
expect(applied.map((e) => e.status)).toEqual(["failed", "skipped"]);
|
|
210
210
|
expect(apply).toHaveBeenCalledTimes(1);
|
|
211
211
|
expect(result.current.entries!.map((e) => e.status)).toEqual([
|
|
212
212
|
"failed",
|