@xenosystem/agent-interface-ui 0.1.25 → 0.1.27
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/dist/adapters/agentHostPlatformBridge.d.ts.map +1 -1
- package/dist/adapters/agentHostPlatformBridge.js +96 -16
- package/dist/adapters/agentHostPlatformBridge.js.map +1 -1
- package/dist/adapters/hubAgentPlatformBridge.d.ts.map +1 -1
- package/dist/adapters/hubAgentPlatformBridge.js +2 -0
- package/dist/adapters/hubAgentPlatformBridge.js.map +1 -1
- package/dist/adapters/scopedBackupBridge.d.ts +4 -0
- package/dist/adapters/scopedBackupBridge.d.ts.map +1 -0
- package/dist/adapters/scopedBackupBridge.js +49 -0
- package/dist/adapters/scopedBackupBridge.js.map +1 -0
- package/dist/adapters/xenoAgentCompatibilityBridge.d.ts.map +1 -1
- package/dist/adapters/xenoAgentCompatibilityBridge.js +9 -1
- package/dist/adapters/xenoAgentCompatibilityBridge.js.map +1 -1
- package/dist/agent.css +13227 -0
- package/dist/components/agent/AgentIdentityGenerator.d.ts +16 -0
- package/dist/components/agent/AgentIdentityGenerator.d.ts.map +1 -0
- package/dist/components/agent/AgentIdentityGenerator.js +80 -0
- package/dist/components/agent/AgentIdentityGenerator.js.map +1 -0
- package/dist/components/agent/AgentInterface.d.ts +1 -0
- package/dist/components/agent/AgentInterface.d.ts.map +1 -1
- package/dist/components/agent/AgentInterface.js +1816 -643
- package/dist/components/agent/AgentInterface.js.map +1 -1
- package/dist/components/agent/AgentNotificationBanner.d.ts +10 -0
- package/dist/components/agent/AgentNotificationBanner.d.ts.map +1 -0
- package/dist/components/agent/AgentNotificationBanner.js +28 -0
- package/dist/components/agent/AgentNotificationBanner.js.map +1 -0
- package/dist/components/agent/AgentOnboarding.d.ts +16 -2
- package/dist/components/agent/AgentOnboarding.d.ts.map +1 -1
- package/dist/components/agent/AgentOnboarding.js +93 -201
- package/dist/components/agent/AgentOnboarding.js.map +1 -1
- package/dist/components/agent/AgentView.d.ts.map +1 -1
- package/dist/components/agent/AgentView.js +533 -308
- package/dist/components/agent/AgentView.js.map +1 -1
- package/dist/components/agent/AgentWorkbenchPanel.d.ts +3 -1
- package/dist/components/agent/AgentWorkbenchPanel.d.ts.map +1 -1
- package/dist/components/agent/AgentWorkbenchPanel.js +3 -2
- package/dist/components/agent/AgentWorkbenchPanel.js.map +1 -1
- package/dist/components/agent/AgentWorkspaceBrowserPanel.d.ts +4 -1
- package/dist/components/agent/AgentWorkspaceBrowserPanel.d.ts.map +1 -1
- package/dist/components/agent/AgentWorkspaceBrowserPanel.js +23 -195
- package/dist/components/agent/AgentWorkspaceBrowserPanel.js.map +1 -1
- package/dist/components/agent/AgentsWorkspaceView.d.ts +12 -0
- package/dist/components/agent/AgentsWorkspaceView.d.ts.map +1 -0
- package/dist/components/agent/AgentsWorkspaceView.js +129 -0
- package/dist/components/agent/AgentsWorkspaceView.js.map +1 -0
- package/dist/components/agent/DevelopmentCoordinationPanel.d.ts +7 -0
- package/dist/components/agent/DevelopmentCoordinationPanel.d.ts.map +1 -1
- package/dist/components/agent/DevelopmentCoordinationPanel.js +57 -49
- package/dist/components/agent/DevelopmentCoordinationPanel.js.map +1 -1
- package/dist/components/agent/KnowledgePanel.d.ts.map +1 -1
- package/dist/components/agent/KnowledgePanel.js +17 -67
- package/dist/components/agent/KnowledgePanel.js.map +1 -1
- package/dist/components/agent/LiveConversationCollaboration.d.ts +27 -0
- package/dist/components/agent/LiveConversationCollaboration.d.ts.map +1 -0
- package/dist/components/agent/LiveConversationCollaboration.js +127 -0
- package/dist/components/agent/LiveConversationCollaboration.js.map +1 -0
- package/dist/components/agent/MonacoDiffWorkbenchEditor.d.ts.map +1 -1
- package/dist/components/agent/MonacoDiffWorkbenchEditor.js +1 -1
- package/dist/components/agent/MonacoDiffWorkbenchEditor.js.map +1 -1
- package/dist/components/agent/MonacoWorkbenchEditor.d.ts.map +1 -1
- package/dist/components/agent/MonacoWorkbenchEditor.js +3 -3
- package/dist/components/agent/MonacoWorkbenchEditor.js.map +1 -1
- package/dist/components/agent/OwnedBrowserController.d.ts +55 -0
- package/dist/components/agent/OwnedBrowserController.d.ts.map +1 -0
- package/dist/components/agent/OwnedBrowserController.js +166 -0
- package/dist/components/agent/OwnedBrowserController.js.map +1 -0
- package/dist/components/agent/OwnedWorkforceView.d.ts +10 -0
- package/dist/components/agent/OwnedWorkforceView.d.ts.map +1 -0
- package/dist/components/agent/OwnedWorkforceView.js +256 -0
- package/dist/components/agent/OwnedWorkforceView.js.map +1 -0
- package/dist/components/agent/PluginManager.d.ts +34 -0
- package/dist/components/agent/PluginManager.d.ts.map +1 -1
- package/dist/components/agent/PluginManager.js +187 -126
- package/dist/components/agent/PluginManager.js.map +1 -1
- package/dist/components/agent/ProjectsWorkspaceView.d.ts +14 -0
- package/dist/components/agent/ProjectsWorkspaceView.d.ts.map +1 -0
- package/dist/components/agent/ProjectsWorkspaceView.js +176 -0
- package/dist/components/agent/ProjectsWorkspaceView.js.map +1 -0
- package/dist/components/agent/RunReviewPanel.d.ts +8 -13
- package/dist/components/agent/RunReviewPanel.d.ts.map +1 -1
- package/dist/components/agent/RunReviewPanel.js +120 -106
- package/dist/components/agent/RunReviewPanel.js.map +1 -1
- package/dist/components/agent/ScheduledWorkspaceView.d.ts +19 -0
- package/dist/components/agent/ScheduledWorkspaceView.d.ts.map +1 -0
- package/dist/components/agent/ScheduledWorkspaceView.js +150 -0
- package/dist/components/agent/ScheduledWorkspaceView.js.map +1 -0
- package/dist/components/agent/SdkSessionPanel.d.ts +25 -0
- package/dist/components/agent/SdkSessionPanel.d.ts.map +1 -0
- package/dist/components/agent/SdkSessionPanel.js +15 -0
- package/dist/components/agent/SdkSessionPanel.js.map +1 -0
- package/dist/components/agent/SlashCommandAutocomplete.d.ts +12 -0
- package/dist/components/agent/SlashCommandAutocomplete.d.ts.map +1 -0
- package/dist/components/agent/SlashCommandAutocomplete.js +33 -0
- package/dist/components/agent/SlashCommandAutocomplete.js.map +1 -0
- package/dist/components/agent/TeamsWorkspaceView.d.ts +12 -0
- package/dist/components/agent/TeamsWorkspaceView.d.ts.map +1 -0
- package/dist/components/agent/TeamsWorkspaceView.js +127 -0
- package/dist/components/agent/TeamsWorkspaceView.js.map +1 -0
- package/dist/components/agent/WorkspacePersistenceNotice.d.ts +3 -0
- package/dist/components/agent/WorkspacePersistenceNotice.d.ts.map +1 -0
- package/dist/components/agent/WorkspacePersistenceNotice.js +23 -0
- package/dist/components/agent/WorkspacePersistenceNotice.js.map +1 -0
- package/dist/components/agent/acp/AcpAgentConfigForm.d.ts +1 -0
- package/dist/components/agent/acp/AcpAgentConfigForm.d.ts.map +1 -1
- package/dist/components/agent/acp/AcpAgentConfigForm.js +47 -14
- package/dist/components/agent/acp/AcpAgentConfigForm.js.map +1 -1
- package/dist/components/agent/acp/AcpAgentDiagnosticsPanel.js +1 -1
- package/dist/components/agent/acp/AcpAgentDiagnosticsPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpAgentManager.d.ts.map +1 -1
- package/dist/components/agent/acp/AcpAgentManager.js +18 -18
- package/dist/components/agent/acp/AcpAgentManager.js.map +1 -1
- package/dist/components/agent/acp/AcpAgentTestResultPanel.js +1 -1
- package/dist/components/agent/acp/AcpAgentTestResultPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpApprovalPanel.js +2 -2
- package/dist/components/agent/acp/AcpApprovalPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpCertificationPanel.js +1 -1
- package/dist/components/agent/acp/AcpCertificationPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpLiveProviderWorkflowPanel.js +1 -1
- package/dist/components/agent/acp/AcpLiveProviderWorkflowPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpProviderManagerPanel.js +1 -1
- package/dist/components/agent/acp/AcpProviderManagerPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpProviderModelsPanel.js +1 -1
- package/dist/components/agent/acp/AcpProviderModelsPanel.js.map +1 -1
- package/dist/components/agent/acp/AcpSupportBundlePanel.js +1 -1
- package/dist/components/agent/acp/AcpSupportBundlePanel.js.map +1 -1
- package/dist/components/agent/collaborationWindow.d.ts +11 -0
- package/dist/components/agent/collaborationWindow.d.ts.map +1 -0
- package/dist/components/agent/collaborationWindow.js +10 -0
- package/dist/components/agent/collaborationWindow.js.map +1 -0
- package/dist/components/agent/conversationCollaborationAppendJournal.d.ts +25 -0
- package/dist/components/agent/conversationCollaborationAppendJournal.d.ts.map +1 -0
- package/dist/components/agent/conversationCollaborationAppendJournal.js +118 -0
- package/dist/components/agent/conversationCollaborationAppendJournal.js.map +1 -0
- package/dist/components/agent/conversationCollaborationController.d.ts +96 -0
- package/dist/components/agent/conversationCollaborationController.d.ts.map +1 -0
- package/dist/components/agent/conversationCollaborationController.js +597 -0
- package/dist/components/agent/conversationCollaborationController.js.map +1 -0
- package/dist/components/agent/destructiveConfirmation.d.ts +76 -0
- package/dist/components/agent/destructiveConfirmation.d.ts.map +1 -0
- package/dist/components/agent/destructiveConfirmation.js +231 -0
- package/dist/components/agent/destructiveConfirmation.js.map +1 -0
- package/dist/components/agent/developmentCoordinationController.d.ts +43 -0
- package/dist/components/agent/developmentCoordinationController.d.ts.map +1 -0
- package/dist/components/agent/developmentCoordinationController.js +94 -0
- package/dist/components/agent/developmentCoordinationController.js.map +1 -0
- package/dist/components/agent/developmentCoordinationProjection.d.ts +24 -0
- package/dist/components/agent/developmentCoordinationProjection.d.ts.map +1 -1
- package/dist/components/agent/developmentCoordinationProjection.js +34 -5
- package/dist/components/agent/developmentCoordinationProjection.js.map +1 -1
- package/dist/components/agent/editorOperationAuthority.d.ts +29 -0
- package/dist/components/agent/editorOperationAuthority.d.ts.map +1 -0
- package/dist/components/agent/editorOperationAuthority.js +73 -0
- package/dist/components/agent/editorOperationAuthority.js.map +1 -0
- package/dist/components/agent/knowledgePagination.d.ts +7 -0
- package/dist/components/agent/knowledgePagination.d.ts.map +1 -0
- package/dist/components/agent/knowledgePagination.js +7 -0
- package/dist/components/agent/knowledgePagination.js.map +1 -0
- package/dist/components/agent/knowledgePanelController.d.ts +32 -0
- package/dist/components/agent/knowledgePanelController.d.ts.map +1 -0
- package/dist/components/agent/knowledgePanelController.js +119 -0
- package/dist/components/agent/knowledgePanelController.js.map +1 -0
- package/dist/components/agent/monacoWorkbenchShared.js +1 -1
- package/dist/components/agent/onboardingModels.d.ts +31 -0
- package/dist/components/agent/onboardingModels.d.ts.map +1 -0
- package/dist/components/agent/onboardingModels.js +107 -0
- package/dist/components/agent/onboardingModels.js.map +1 -0
- package/dist/components/agent/personalConversationScope.d.ts +26 -0
- package/dist/components/agent/personalConversationScope.d.ts.map +1 -0
- package/dist/components/agent/personalConversationScope.js +43 -0
- package/dist/components/agent/personalConversationScope.js.map +1 -0
- package/dist/components/agent/reviewRequestScope.d.ts +16 -0
- package/dist/components/agent/reviewRequestScope.d.ts.map +1 -0
- package/dist/components/agent/reviewRequestScope.js +101 -0
- package/dist/components/agent/reviewRequestScope.js.map +1 -0
- package/dist/components/agent/scheduleCreationAttempt.d.ts +12 -0
- package/dist/components/agent/scheduleCreationAttempt.d.ts.map +1 -0
- package/dist/components/agent/scheduleCreationAttempt.js +30 -0
- package/dist/components/agent/scheduleCreationAttempt.js.map +1 -0
- package/dist/components/agent/settings/EntitySettingsLayout.d.ts +1 -1
- package/dist/components/agent/settings/EntitySettingsLayout.d.ts.map +1 -1
- package/dist/components/agent/settings/EntitySettingsLayout.js +64 -44
- package/dist/components/agent/settings/EntitySettingsLayout.js.map +1 -1
- package/dist/components/agent/settings/SettingsNavigation.d.ts.map +1 -1
- package/dist/components/agent/settings/SettingsNavigation.js +17 -17
- package/dist/components/agent/settings/SettingsNavigation.js.map +1 -1
- package/dist/components/agent/settings/entityArchiveState.d.ts +24 -0
- package/dist/components/agent/settings/entityArchiveState.d.ts.map +1 -0
- package/dist/components/agent/settings/entityArchiveState.js +12 -0
- package/dist/components/agent/settings/entityArchiveState.js.map +1 -0
- package/dist/components/agent/settings/sections/AccessMembersSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/AccessMembersSection.js +10 -25
- package/dist/components/agent/settings/sections/AccessMembersSection.js.map +1 -1
- package/dist/components/agent/settings/sections/AccountWorkspacePanel.d.ts +16 -0
- package/dist/components/agent/settings/sections/AccountWorkspacePanel.d.ts.map +1 -0
- package/dist/components/agent/settings/sections/AccountWorkspacePanel.js +265 -0
- package/dist/components/agent/settings/sections/AccountWorkspacePanel.js.map +1 -0
- package/dist/components/agent/settings/sections/AgentPermissionRulesPanel.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/AgentPermissionRulesPanel.js +47 -32
- package/dist/components/agent/settings/sections/AgentPermissionRulesPanel.js.map +1 -1
- package/dist/components/agent/settings/sections/DangerZoneSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/DangerZoneSection.js +30 -6
- package/dist/components/agent/settings/sections/DangerZoneSection.js.map +1 -1
- package/dist/components/agent/settings/sections/DefaultAgentConfigSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/DefaultAgentConfigSection.js +47 -37
- package/dist/components/agent/settings/sections/DefaultAgentConfigSection.js.map +1 -1
- package/dist/components/agent/settings/sections/EnvironmentSecretsSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/EnvironmentSecretsSection.js +30 -43
- package/dist/components/agent/settings/sections/EnvironmentSecretsSection.js.map +1 -1
- package/dist/components/agent/settings/sections/ExportBackupSection.d.ts +3 -1
- package/dist/components/agent/settings/sections/ExportBackupSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/ExportBackupSection.js +14 -12
- package/dist/components/agent/settings/sections/ExportBackupSection.js.map +1 -1
- package/dist/components/agent/settings/sections/GeneralSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/GeneralSection.js +47 -4
- package/dist/components/agent/settings/sections/GeneralSection.js.map +1 -1
- package/dist/components/agent/settings/sections/IntegrationsSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/IntegrationsSection.js +14 -21
- package/dist/components/agent/settings/sections/IntegrationsSection.js.map +1 -1
- package/dist/components/agent/settings/sections/NotificationsSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/NotificationsSection.js +125 -20
- package/dist/components/agent/settings/sections/NotificationsSection.js.map +1 -1
- package/dist/components/agent/settings/sections/ResourceLimitsSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/ResourceLimitsSection.js +7 -7
- package/dist/components/agent/settings/sections/ResourceLimitsSection.js.map +1 -1
- package/dist/components/agent/settings/sections/SecurityComplianceSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/SecurityComplianceSection.js +5 -4
- package/dist/components/agent/settings/sections/SecurityComplianceSection.js.map +1 -1
- package/dist/components/agent/settings/sections/UsageAnalyticsSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/UsageAnalyticsSection.js +2 -3
- package/dist/components/agent/settings/sections/UsageAnalyticsSection.js.map +1 -1
- package/dist/components/agent/settings/sections/WorkspaceDirectoryAccessSection.d.ts.map +1 -1
- package/dist/components/agent/settings/sections/WorkspaceDirectoryAccessSection.js +39 -26
- package/dist/components/agent/settings/sections/WorkspaceDirectoryAccessSection.js.map +1 -1
- package/dist/components/agent/settings/sections/WorkspaceKeysPanel.d.ts +6 -0
- package/dist/components/agent/settings/sections/WorkspaceKeysPanel.d.ts.map +1 -0
- package/dist/components/agent/settings/sections/WorkspaceKeysPanel.js +205 -0
- package/dist/components/agent/settings/sections/WorkspaceKeysPanel.js.map +1 -0
- package/dist/components/agent/settings/sections/environmentDraftAction.d.ts +3 -0
- package/dist/components/agent/settings/sections/environmentDraftAction.d.ts.map +1 -0
- package/dist/components/agent/settings/sections/environmentDraftAction.js +6 -0
- package/dist/components/agent/settings/sections/environmentDraftAction.js.map +1 -0
- package/dist/components/agent/settings/sections/membershipOperationProjection.d.ts +3 -0
- package/dist/components/agent/settings/sections/membershipOperationProjection.d.ts.map +1 -0
- package/dist/components/agent/settings/sections/membershipOperationProjection.js +9 -0
- package/dist/components/agent/settings/sections/membershipOperationProjection.js.map +1 -0
- package/dist/components/agent/settings/sections/workspaceKeyOperationProjection.d.ts +6 -0
- package/dist/components/agent/settings/sections/workspaceKeyOperationProjection.d.ts.map +1 -0
- package/dist/components/agent/settings/sections/workspaceKeyOperationProjection.js +8 -0
- package/dist/components/agent/settings/sections/workspaceKeyOperationProjection.js.map +1 -0
- package/dist/components/agent/settings/shared/InAppConfirmationDialog.d.ts +25 -0
- package/dist/components/agent/settings/shared/InAppConfirmationDialog.d.ts.map +1 -0
- package/dist/components/agent/settings/shared/InAppConfirmationDialog.js +89 -0
- package/dist/components/agent/settings/shared/InAppConfirmationDialog.js.map +1 -0
- package/dist/components/agent/settings/shared/InputField.d.ts +1 -1
- package/dist/components/agent/settings/shared/InputField.d.ts.map +1 -1
- package/dist/components/agent/settings/shared/InputField.js +4 -3
- package/dist/components/agent/settings/shared/InputField.js.map +1 -1
- package/dist/components/agent/settings/shared/MembersTable.d.ts +3 -3
- package/dist/components/agent/settings/shared/MembersTable.d.ts.map +1 -1
- package/dist/components/agent/settings/shared/MembersTable.js +1 -1
- package/dist/components/agent/settings/shared/MembersTable.js.map +1 -1
- package/dist/components/agent/settings/shared/ScopedAuditPanel.d.ts +5 -0
- package/dist/components/agent/settings/shared/ScopedAuditPanel.d.ts.map +1 -0
- package/dist/components/agent/settings/shared/ScopedAuditPanel.js +70 -0
- package/dist/components/agent/settings/shared/ScopedAuditPanel.js.map +1 -0
- package/dist/components/agent/settings/shared/SettingsCard.d.ts +2 -1
- package/dist/components/agent/settings/shared/SettingsCard.d.ts.map +1 -1
- package/dist/components/agent/settings/shared/SettingsCard.js +2 -2
- package/dist/components/agent/settings/shared/SettingsCard.js.map +1 -1
- package/dist/components/agent/settings/shared/ToggleSwitch.d.ts.map +1 -1
- package/dist/components/agent/settings/shared/ToggleSwitch.js +1 -1
- package/dist/components/agent/settings/shared/ToggleSwitch.js.map +1 -1
- package/dist/components/agent/settings/shared/UsageChart.d.ts +10 -0
- package/dist/components/agent/settings/shared/UsageChart.d.ts.map +1 -1
- package/dist/components/agent/settings/shared/UsageChart.js +16 -10
- package/dist/components/agent/settings/shared/UsageChart.js.map +1 -1
- package/dist/components/agent/settings/shared/WorkspaceRulesControl.d.ts +8 -0
- package/dist/components/agent/settings/shared/WorkspaceRulesControl.d.ts.map +1 -0
- package/dist/components/agent/settings/shared/WorkspaceRulesControl.js +26 -0
- package/dist/components/agent/settings/shared/WorkspaceRulesControl.js.map +1 -0
- package/dist/components/agent/settings/shared/useScopedConfirmation.d.ts +8 -0
- package/dist/components/agent/settings/shared/useScopedConfirmation.d.ts.map +1 -0
- package/dist/components/agent/settings/shared/useScopedConfirmation.js +53 -0
- package/dist/components/agent/settings/shared/useScopedConfirmation.js.map +1 -0
- package/dist/components/agent/settings/shared/useSettingsConfirmation.d.ts +8 -0
- package/dist/components/agent/settings/shared/useSettingsConfirmation.d.ts.map +1 -0
- package/dist/components/agent/settings/shared/useSettingsConfirmation.js +51 -0
- package/dist/components/agent/settings/shared/useSettingsConfirmation.js.map +1 -0
- package/dist/components/agent/settings/shared/workspaceRulesController.d.ts +28 -0
- package/dist/components/agent/settings/shared/workspaceRulesController.d.ts.map +1 -0
- package/dist/components/agent/settings/shared/workspaceRulesController.js +82 -0
- package/dist/components/agent/settings/shared/workspaceRulesController.js.map +1 -0
- package/dist/components/agent/sidebarEntityPins.d.ts +11 -0
- package/dist/components/agent/sidebarEntityPins.d.ts.map +1 -0
- package/dist/components/agent/sidebarEntityPins.js +37 -0
- package/dist/components/agent/sidebarEntityPins.js.map +1 -0
- package/dist/components/agent/workspaceHierarchy.d.ts +24 -0
- package/dist/components/agent/workspaceHierarchy.d.ts.map +1 -0
- package/dist/components/agent/workspaceHierarchy.js +50 -0
- package/dist/components/agent/workspaceHierarchy.js.map +1 -0
- package/dist/components/product/XenoAgentProductHeader.d.ts +4 -2
- package/dist/components/product/XenoAgentProductHeader.d.ts.map +1 -1
- package/dist/components/product/XenoAgentProductHeader.js +22 -4
- package/dist/components/product/XenoAgentProductHeader.js.map +1 -1
- package/dist/components/product/XenoAgentSessionTabs.js +1 -1
- package/dist/components/product/XenoAgentSessionTabs.js.map +1 -1
- package/dist/components/product/XenoAgentWorkspaceSelector.d.ts +7 -0
- package/dist/components/product/XenoAgentWorkspaceSelector.d.ts.map +1 -0
- package/dist/components/product/XenoAgentWorkspaceSelector.js +237 -0
- package/dist/components/product/XenoAgentWorkspaceSelector.js.map +1 -0
- package/dist/components/workspace/WorkspaceCreationWizard.d.ts +6 -0
- package/dist/components/workspace/WorkspaceCreationWizard.d.ts.map +1 -0
- package/dist/components/workspace/WorkspaceCreationWizard.js +48 -0
- package/dist/components/workspace/WorkspaceCreationWizard.js.map +1 -0
- package/dist/hooks/useSidebarLayoutPreference.d.ts +29 -0
- package/dist/hooks/useSidebarLayoutPreference.d.ts.map +1 -0
- package/dist/hooks/useSidebarLayoutPreference.js +83 -0
- package/dist/hooks/useSidebarLayoutPreference.js.map +1 -0
- package/dist/hooks/useWorkspaceCreation.d.ts +8 -0
- package/dist/hooks/useWorkspaceCreation.d.ts.map +1 -0
- package/dist/hooks/useWorkspaceCreation.js +40 -0
- package/dist/hooks/useWorkspaceCreation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/platformApiTypes.d.ts +77 -36
- package/dist/platformApiTypes.d.ts.map +1 -1
- package/dist/platformBridge.d.ts +4 -0
- package/dist/platformBridge.d.ts.map +1 -1
- package/dist/platformBridge.js +10 -0
- package/dist/platformBridge.js.map +1 -1
- package/dist/stores/agentChatStore.d.ts +120 -2
- package/dist/stores/agentChatStore.d.ts.map +1 -1
- package/dist/stores/agentChatStore.js +329 -35
- package/dist/stores/agentChatStore.js.map +1 -1
- package/dist/stores/agentCreationDefaults.d.ts +25 -0
- package/dist/stores/agentCreationDefaults.d.ts.map +1 -0
- package/dist/stores/agentCreationDefaults.js +11 -0
- package/dist/stores/agentCreationDefaults.js.map +1 -0
- package/dist/stores/entitySettingsStore.d.ts +37 -12
- package/dist/stores/entitySettingsStore.d.ts.map +1 -1
- package/dist/stores/entitySettingsStore.js +558 -585
- package/dist/stores/entitySettingsStore.js.map +1 -1
- package/dist/stores/suggestionStore.d.ts +9 -2
- package/dist/stores/suggestionStore.d.ts.map +1 -1
- package/dist/stores/suggestionStore.js +51 -24
- package/dist/stores/suggestionStore.js.map +1 -1
- package/dist/stores/workspaceCreationAttempt.d.ts +14 -0
- package/dist/stores/workspaceCreationAttempt.d.ts.map +1 -0
- package/dist/stores/workspaceCreationAttempt.js +35 -0
- package/dist/stores/workspaceCreationAttempt.js.map +1 -0
- package/dist/stores/workspaceReconciliation.d.ts +6 -0
- package/dist/stores/workspaceReconciliation.d.ts.map +1 -0
- package/dist/stores/workspaceReconciliation.js +33 -0
- package/dist/stores/workspaceReconciliation.js.map +1 -0
- package/dist/stores/workspaceStore.d.ts +44 -9
- package/dist/stores/workspaceStore.d.ts.map +1 -1
- package/dist/stores/workspaceStore.js +238 -99
- package/dist/stores/workspaceStore.js.map +1 -1
- package/dist/types/agentEditor.d.ts +1 -0
- package/dist/types/agentEditor.d.ts.map +1 -1
- package/dist/utils/advertisedReasoning.d.ts +25 -0
- package/dist/utils/advertisedReasoning.d.ts.map +1 -0
- package/dist/utils/advertisedReasoning.js +62 -0
- package/dist/utils/advertisedReasoning.js.map +1 -0
- package/dist/utils/clipboardCopy.d.ts +4 -0
- package/dist/utils/clipboardCopy.d.ts.map +1 -0
- package/dist/utils/clipboardCopy.js +27 -0
- package/dist/utils/clipboardCopy.js.map +1 -0
- package/dist/utils/providerCommandArgs.d.ts +11 -0
- package/dist/utils/providerCommandArgs.d.ts.map +1 -0
- package/dist/utils/providerCommandArgs.js +18 -0
- package/dist/utils/providerCommandArgs.js.map +1 -0
- package/dist/utils/rendererTeardown.d.ts +6 -0
- package/dist/utils/rendererTeardown.d.ts.map +1 -0
- package/dist/utils/rendererTeardown.js +18 -0
- package/dist/utils/rendererTeardown.js.map +1 -0
- package/package.json +20 -8
- package/src/agent.css +39 -9
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getAgentPlatformBridge } from '../platformBridge.js';
|
|
2
|
+
import { isAgentUsageResult } from '@xenosystem/agent-interface-contract';
|
|
2
3
|
import { create } from 'zustand';
|
|
3
|
-
import { useWorkspaceStore } from './workspaceStore.js';
|
|
4
|
-
import { useAgentChatStore } from './agentChatStore.js';
|
|
5
|
-
import { useAuthStore } from './authStore.js';
|
|
4
|
+
import { useWorkspaceStore, toolsForAgentCapabilities, requestWorkspaceLifecycle, requireWorkspacePersistence } from './workspaceStore.js';
|
|
5
|
+
import { useAgentChatStore, loadLocalAgentConversations } from './agentChatStore.js';
|
|
6
6
|
export const SETTINGS_SECTIONS = [
|
|
7
7
|
{ id: 'general', label: 'General', icon: 'settings', availableFor: ['workspace', 'team', 'agent'] },
|
|
8
8
|
{ id: 'directoryAccess', label: 'Directory Access', icon: 'folder', availableFor: ['workspace', 'team', 'agent'] },
|
|
@@ -11,274 +11,263 @@ export const SETTINGS_SECTIONS = [
|
|
|
11
11
|
{ id: 'resourceLimits', label: 'Resource Limits', icon: 'gauge', availableFor: ['workspace', 'team', 'agent'] },
|
|
12
12
|
{ id: 'usage', label: 'Usage & Analytics', icon: 'barChart', availableFor: ['workspace', 'team', 'agent'] },
|
|
13
13
|
{ id: 'integrations', label: 'Integrations', icon: 'plug', availableFor: ['workspace', 'team'] },
|
|
14
|
-
{ id: 'environment', label: 'Environment & Secrets', icon: 'key', availableFor: ['workspace', 'team'] },
|
|
14
|
+
{ id: 'environment', label: 'Environment & Secrets', icon: 'key', availableFor: ['workspace', 'team', 'agent'] },
|
|
15
15
|
{ id: 'notifications', label: 'Notifications', icon: 'bell', availableFor: ['workspace', 'team', 'agent'] },
|
|
16
16
|
{ id: 'security', label: 'Security & Compliance', icon: 'shield', availableFor: ['workspace', 'team'] },
|
|
17
|
-
{ id: 'exportBackup', label: 'Export & Backup', icon: 'download', availableFor: ['workspace', 'team'] },
|
|
17
|
+
{ id: 'exportBackup', label: 'Export & Backup', icon: 'download', availableFor: ['workspace', 'team', 'agent'] },
|
|
18
18
|
{ id: 'dangerZone', label: 'Danger Zone', icon: 'alertTriangle', availableFor: ['workspace', 'team', 'agent'] },
|
|
19
19
|
];
|
|
20
20
|
export function getSectionsForEntity(entityType) {
|
|
21
21
|
return SETTINGS_SECTIONS.filter(s => s.availableFor.includes(entityType));
|
|
22
22
|
}
|
|
23
23
|
// =============================================================================
|
|
24
|
-
//
|
|
24
|
+
// INITIAL UNOBSERVED STATE
|
|
25
25
|
// =============================================================================
|
|
26
26
|
function generateId() {
|
|
27
27
|
return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const owner =
|
|
33
|
-
id: 'user_owner_1',
|
|
34
|
-
name: 'You',
|
|
35
|
-
email: 'you@example.com',
|
|
36
|
-
role: 'owner',
|
|
37
|
-
joinedAt: thirtyDaysAgo,
|
|
38
|
-
};
|
|
39
|
-
const members = [
|
|
40
|
-
owner,
|
|
41
|
-
{ id: 'user_2', name: 'Alice Chen', email: 'alice@example.com', role: 'admin', joinedAt: thirtyDaysAgo },
|
|
42
|
-
{ id: 'user_3', name: 'Bob Smith', email: 'bob@example.com', role: 'editor', joinedAt: now },
|
|
43
|
-
];
|
|
44
|
-
const dailyUsage = Array.from({ length: 7 }, (_, i) => ({
|
|
45
|
-
label: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][i],
|
|
46
|
-
value: Math.floor(Math.random() * 50000) + 5000,
|
|
47
|
-
}));
|
|
48
|
-
const weeklyUsage = Array.from({ length: 4 }, (_, i) => ({
|
|
49
|
-
label: `Week ${i + 1}`,
|
|
50
|
-
value: Math.floor(Math.random() * 200000) + 50000,
|
|
51
|
-
}));
|
|
52
|
-
const monthlyUsage = Array.from({ length: 6 }, (_, i) => ({
|
|
53
|
-
label: ['Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan'][i],
|
|
54
|
-
value: Math.floor(Math.random() * 800000) + 100000,
|
|
55
|
-
}));
|
|
56
|
-
const workspaceQuotas = [
|
|
57
|
-
{ label: 'Teams', current: 3, limit: 10, unit: 'teams' },
|
|
58
|
-
{ label: 'Tokens / month', current: 425000, limit: 1000000, unit: 'tokens' },
|
|
59
|
-
{ label: 'Storage', current: 2.4, limit: 10, unit: 'GB' },
|
|
60
|
-
];
|
|
61
|
-
const teamQuotas = [
|
|
62
|
-
{ label: 'Agents', current: 5, limit: 20, unit: 'agents' },
|
|
63
|
-
{ label: 'Tokens / month', current: 180000, limit: 500000, unit: 'tokens' },
|
|
64
|
-
];
|
|
65
|
-
const agentQuotas = [
|
|
66
|
-
{ label: 'Tokens / month', current: 42000, limit: 100000, unit: 'tokens' },
|
|
67
|
-
];
|
|
68
|
-
const quotas = entityType === 'workspace' ? workspaceQuotas : entityType === 'team' ? teamQuotas : agentQuotas;
|
|
29
|
+
function createInitialSettings(entityId, entityType, entityName, extra) {
|
|
30
|
+
// Empty means unobserved, not a synthetic successful response. Load statuses
|
|
31
|
+
// distinguish unavailable services from successfully observed empty collections.
|
|
32
|
+
const owner = null;
|
|
69
33
|
return {
|
|
70
|
-
entityId,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
workspaceId: extra?.workspaceId,
|
|
74
|
-
workspaceName: extra?.workspaceName,
|
|
75
|
-
teamId: extra?.teamId,
|
|
76
|
-
teamName: extra?.teamName,
|
|
34
|
+
entityId, entityType, entityName,
|
|
35
|
+
workspaceId: extra?.workspaceId, workspaceName: extra?.workspaceName,
|
|
36
|
+
teamId: extra?.teamId, teamName: extra?.teamName,
|
|
77
37
|
general: {
|
|
78
|
-
name: entityName,
|
|
79
|
-
|
|
80
|
-
icon: entityType === 'workspace' ? 'building' : entityType === 'team' ? 'users' : 'bot',
|
|
81
|
-
slug: entityName.toLowerCase().replace(/\s+/g, '-'),
|
|
82
|
-
createdAt: thirtyDaysAgo,
|
|
83
|
-
updatedAt: now,
|
|
84
|
-
},
|
|
85
|
-
defaultAgentConfig: entityType !== 'agent' ? {
|
|
86
|
-
defaultModel: 'claude-sonnet-4-6',
|
|
87
|
-
systemInstructions: 'You are a helpful AI assistant.',
|
|
88
|
-
enabledTools: ['web-search', 'code-execution', 'file-read'],
|
|
89
|
-
availableTools: ['web-search', 'code-execution', 'file-read', 'file-write', 'image-generation', 'data-analysis'],
|
|
90
|
-
} : undefined,
|
|
91
|
-
access: {
|
|
92
|
-
owner,
|
|
93
|
-
members: entityType === 'agent' ? [owner] : members,
|
|
94
|
-
pendingInvites: entityType === 'agent' ? [] : [
|
|
95
|
-
{ id: 'inv_1', email: 'carol@example.com', role: 'viewer', sentAt: now, expiresAt: new Date(Date.now() + 7 * 86400000).toISOString() },
|
|
96
|
-
],
|
|
97
|
-
publicAccess: false,
|
|
98
|
-
allowGuestViewing: false,
|
|
99
|
-
},
|
|
100
|
-
resourceLimits: {
|
|
101
|
-
quotas,
|
|
102
|
-
rateLimitRpm: entityType === 'workspace' ? 1000 : entityType === 'team' ? 500 : 100,
|
|
103
|
-
rateLimitTpd: entityType === 'workspace' ? 1000000 : entityType === 'team' ? 500000 : 100000,
|
|
104
|
-
},
|
|
105
|
-
usage: {
|
|
106
|
-
totalTokens: 425000,
|
|
107
|
-
totalCost: 12.50,
|
|
108
|
-
totalRequests: 1842,
|
|
109
|
-
dailyUsage,
|
|
110
|
-
weeklyUsage,
|
|
111
|
-
monthlyUsage,
|
|
112
|
-
costByModel: [
|
|
113
|
-
{ model: 'Opus 4.5', cost: 8.20, tokens: 280000 },
|
|
114
|
-
{ model: 'GPT 5.3 Codex', cost: 3.10, tokens: 105000 },
|
|
115
|
-
{ model: 'Flash 3.0', cost: 1.20, tokens: 40000 },
|
|
116
|
-
],
|
|
117
|
-
topAgents: [
|
|
118
|
-
{ name: 'Code Reviewer', tokens: 120000, cost: 3.60 },
|
|
119
|
-
{ name: 'Research Bot', tokens: 95000, cost: 2.85 },
|
|
120
|
-
{ name: 'Doc Writer', tokens: 72000, cost: 2.16 },
|
|
121
|
-
],
|
|
38
|
+
name: entityName, description: '', icon: entityType === 'workspace' ? 'building' : entityType === 'team' ? 'users' : 'bot',
|
|
39
|
+
slug: entityName.toLowerCase().replace(/\s+/g, '-'), createdAt: '', updatedAt: '',
|
|
122
40
|
},
|
|
41
|
+
defaultAgentConfig: entityType !== 'agent'
|
|
42
|
+
? { defaultModel: '', systemInstructions: '', enabledTools: [], availableTools: [] }
|
|
43
|
+
: undefined,
|
|
44
|
+
access: { owner, members: [], pendingInvites: [], publicAccess: false, allowGuestViewing: false },
|
|
45
|
+
resourceLimits: { quotas: [], rateLimitRpm: 0, rateLimitTpd: 0 },
|
|
46
|
+
usage: { totalTokens: 0, totalCost: null, totalRequests: 0, dailyUsage: [], weeklyUsage: [], monthlyUsage: [], costByModel: [], topAgents: [] },
|
|
123
47
|
integrations: {
|
|
124
48
|
integrations: [
|
|
125
|
-
{ id: '
|
|
126
|
-
{ id: '
|
|
127
|
-
{ id: '
|
|
128
|
-
{ id: 'int_4', type: 'webhook', name: 'Custom Webhook', enabled: true, connectedAt: thirtyDaysAgo, status: 'connected', config: { url: 'https://api.example.com/webhook' } },
|
|
129
|
-
],
|
|
130
|
-
apiKeys: [
|
|
131
|
-
{ id: 'key_1', name: 'Production Key', prefix: 'xk_prod_...a3f2', createdAt: thirtyDaysAgo, lastUsed: now },
|
|
132
|
-
{ id: 'key_2', name: 'Development Key', prefix: 'xk_dev_...b1c4', createdAt: now, lastUsed: now },
|
|
133
|
-
],
|
|
134
|
-
webhookEndpoints: [
|
|
135
|
-
{ id: 'wh_1', url: 'https://api.example.com/webhook', events: ['agent.started', 'agent.completed'], enabled: true, secret: 'whsec_...x9y2', createdAt: thirtyDaysAgo },
|
|
136
|
-
],
|
|
137
|
-
},
|
|
138
|
-
environment: {
|
|
139
|
-
variables: [
|
|
140
|
-
{ id: 'env_1', key: 'API_BASE_URL', value: 'https://api.example.com', isSecret: false, updatedAt: now },
|
|
141
|
-
{ id: 'env_2', key: 'DATABASE_URL', value: '••••••••••••', isSecret: true, updatedAt: thirtyDaysAgo },
|
|
142
|
-
{ id: 'env_3', key: 'OPENAI_API_KEY', value: '••••••••••••', isSecret: true, updatedAt: thirtyDaysAgo },
|
|
143
|
-
],
|
|
144
|
-
},
|
|
145
|
-
notifications: {
|
|
146
|
-
emailEnabled: true,
|
|
147
|
-
slackEnabled: false,
|
|
148
|
-
discordEnabled: false,
|
|
149
|
-
webhookEnabled: true,
|
|
150
|
-
rules: [
|
|
151
|
-
{ id: 'rule_1', event: 'Agent Error', channel: 'email', enabled: true, description: 'Notify when an agent encounters an error' },
|
|
152
|
-
{ id: 'rule_2', event: 'Task Completed', channel: 'webhook', enabled: true, description: 'Webhook on task completion' },
|
|
153
|
-
{ id: 'rule_3', event: 'Quota Warning', channel: 'email', enabled: true, description: 'Alert when approaching usage limits' },
|
|
154
|
-
],
|
|
155
|
-
digestFrequency: 'daily',
|
|
156
|
-
},
|
|
157
|
-
security: {
|
|
158
|
-
auditLog: [
|
|
159
|
-
{ id: 'log_1', action: 'member.added', actor: 'You', target: 'Alice Chen', timestamp: now, details: 'Added as admin' },
|
|
160
|
-
{ id: 'log_2', action: 'settings.updated', actor: 'You', target: 'General Settings', timestamp: thirtyDaysAgo, details: 'Updated workspace name' },
|
|
161
|
-
{ id: 'log_3', action: 'agent.created', actor: 'Alice Chen', target: 'Code Reviewer', timestamp: thirtyDaysAgo, details: 'Created new agent' },
|
|
162
|
-
{ id: 'log_4', action: 'apikey.created', actor: 'You', target: 'Production Key', timestamp: thirtyDaysAgo, details: 'Created API key' },
|
|
163
|
-
{ id: 'log_5', action: 'member.role_changed', actor: 'You', target: 'Bob Smith', timestamp: now, details: 'Changed role to editor' },
|
|
164
|
-
],
|
|
165
|
-
ipAllowlist: [],
|
|
166
|
-
require2FA: false,
|
|
167
|
-
requireApiKeyAuth: true,
|
|
168
|
-
sessionTimeout: 30,
|
|
169
|
-
},
|
|
170
|
-
exportBackup: {
|
|
171
|
-
autoBackupEnabled: true,
|
|
172
|
-
backupFrequency: 'weekly',
|
|
173
|
-
retentionDays: 30,
|
|
174
|
-
availableBackups: [
|
|
175
|
-
{ id: 'bk_1', name: 'Auto Backup', size: '2.4 MB', createdAt: now, type: 'auto' },
|
|
176
|
-
{ id: 'bk_2', name: 'Pre-migration Backup', size: '1.8 MB', createdAt: thirtyDaysAgo, type: 'manual' },
|
|
177
|
-
],
|
|
178
|
-
availableExports: [
|
|
179
|
-
{ format: 'json', label: 'JSON Export' },
|
|
180
|
-
{ format: 'csv', label: 'CSV Export' },
|
|
181
|
-
{ format: 'yaml', label: 'YAML Export' },
|
|
49
|
+
{ id: 'github', type: 'github', name: 'GitHub', enabled: false, connectedAt: '', status: 'disconnected' },
|
|
50
|
+
{ id: 'slack', type: 'slack', name: 'Slack', enabled: false, connectedAt: '', status: 'disconnected' },
|
|
51
|
+
{ id: 'discord', type: 'discord', name: 'Discord', enabled: false, connectedAt: '', status: 'disconnected' },
|
|
182
52
|
],
|
|
53
|
+
apiKeys: [], webhookEndpoints: [],
|
|
183
54
|
},
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
55
|
+
environment: { variables: [] },
|
|
56
|
+
notifications: { emailEnabled: false, slackEnabled: false, discordEnabled: false, webhookEnabled: false, rules: [], digestFrequency: 'daily' },
|
|
57
|
+
security: { auditLog: [], ipAllowlist: [], require2FA: false, requireApiKeyAuth: false, sessionTimeout: 0 },
|
|
58
|
+
exportBackup: { autoBackupEnabled: false, backupFrequency: 'weekly', retentionDays: 30, availableBackups: [], availableExports: [{ format: 'json', label: 'JSON Export' }, { format: 'csv', label: 'CSV Export' }] },
|
|
59
|
+
dangerZone: { canArchive: true, canTransferOwnership: false, canDelete: true },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
let selectedHierarchyBaseline;
|
|
63
|
+
const profileDrafts = new WeakMap();
|
|
64
|
+
function currentProfileDrafts() {
|
|
65
|
+
const storage = getAgentPlatformBridge()?.workspaceStorage;
|
|
66
|
+
if (!storage)
|
|
67
|
+
return new Map();
|
|
68
|
+
let drafts = profileDrafts.get(storage);
|
|
69
|
+
if (!drafts) {
|
|
70
|
+
drafts = new Map();
|
|
71
|
+
profileDrafts.set(storage, drafts);
|
|
72
|
+
}
|
|
73
|
+
return drafts;
|
|
74
|
+
}
|
|
75
|
+
function profileIdentityExists(identity, workspaces) {
|
|
76
|
+
const [workspaceId, createdAt, teamId, agentId] = JSON.parse(identity);
|
|
77
|
+
const matches = workspaces.filter(workspace => workspace.id === workspaceId && workspace.createdAt === createdAt);
|
|
78
|
+
if (matches.length !== 1)
|
|
79
|
+
return false;
|
|
80
|
+
if (teamId === null)
|
|
81
|
+
return true;
|
|
82
|
+
const teams = matches[0].teams.filter(team => team.id === teamId);
|
|
83
|
+
return teams.length === 1 && (agentId === null || teams[0].agents.filter(agent => agent.id === agentId).length === 1);
|
|
84
|
+
}
|
|
85
|
+
export function validateProfileDraft(profile) {
|
|
86
|
+
if (!profile.name.trim())
|
|
87
|
+
return 'Name is required. Enter a name or discard profile changes.';
|
|
88
|
+
if (profile.name.length > 200)
|
|
89
|
+
return 'Name must be at most 200 characters.';
|
|
90
|
+
if (/[\u0000-\u001f\u007f-\u009f]/.test(profile.name))
|
|
91
|
+
return 'Name cannot contain control characters.';
|
|
92
|
+
if (profile.description.length > 4000)
|
|
93
|
+
return 'Description must be at most 4000 characters.';
|
|
94
|
+
if (/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/.test(profile.description))
|
|
95
|
+
return 'Description contains unsupported control characters.';
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (typeof window !== 'undefined')
|
|
99
|
+
window.addEventListener('beforeunload', event => {
|
|
100
|
+
if (!currentProfileDrafts().size)
|
|
101
|
+
return;
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
event.returnValue = '';
|
|
104
|
+
});
|
|
105
|
+
/** One projection shared by initial load and acknowledged remote reconciliation. */
|
|
106
|
+
function projectHierarchySettings(settings, workspaces) {
|
|
107
|
+
const matches = workspaces.filter(w => w.id === (settings.entityType === 'workspace' ? settings.entityId : settings.workspaceId));
|
|
108
|
+
if (matches.length !== 1)
|
|
109
|
+
return undefined;
|
|
110
|
+
const workspace = matches[0];
|
|
111
|
+
const teams = settings.entityType === 'workspace' ? [] : workspace.teams.filter(t => t.id === (settings.entityType === 'team' ? settings.entityId : settings.teamId));
|
|
112
|
+
if (settings.entityType !== 'workspace' && teams.length !== 1)
|
|
113
|
+
return undefined;
|
|
114
|
+
const team = teams[0];
|
|
115
|
+
const agents = settings.entityType === 'agent' ? team.agents.filter(a => a.id === settings.entityId) : [];
|
|
116
|
+
if (settings.entityType === 'agent' && agents.length !== 1)
|
|
117
|
+
return undefined;
|
|
118
|
+
const agent = agents[0];
|
|
119
|
+
const entity = agent ?? team ?? workspace;
|
|
120
|
+
const defaults = settings.entityType === 'workspace' ? workspace.agentDefaults
|
|
121
|
+
: settings.entityType === 'team' ? { ...workspace.agentDefaults, ...team?.agentDefaults }
|
|
122
|
+
: { model: agent?.model, systemPrompt: agent?.systemPrompt, tools: agent?.tools ?? toolsForAgentCapabilities(agent?.capabilities) };
|
|
123
|
+
const createdAt = Number.isFinite(workspace.createdAt) ? new Date(workspace.createdAt).toISOString() : '';
|
|
124
|
+
return {
|
|
125
|
+
// Team/Agent IDs have no generation field in the current canonical schema.
|
|
126
|
+
// Observed disappearance invalidates selection; workspace recreation is exact.
|
|
127
|
+
identity: JSON.stringify([workspace.id, workspace.createdAt, team?.id ?? null, agent?.id ?? null]),
|
|
128
|
+
entityName: entity.name, workspaceName: workspace.name, ...(team ? { teamName: team.name } : {}),
|
|
129
|
+
general: {
|
|
130
|
+
name: entity.name, description: entity.description ?? '',
|
|
131
|
+
slug: entity.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
|
|
132
|
+
icon: settings.entityType === 'workspace' ? 'building' : settings.entityType === 'team' ? 'users' : 'bot',
|
|
133
|
+
createdAt: settings.entityType === 'workspace' ? createdAt : settings.general.createdAt,
|
|
134
|
+
updatedAt: settings.entityType === 'workspace' ? (workspace.updatedAt ? new Date(workspace.updatedAt).toISOString() : createdAt) : settings.general.updatedAt,
|
|
188
135
|
},
|
|
136
|
+
...(settings.defaultAgentConfig ? { defaultAgentConfig: {
|
|
137
|
+
defaultModel: defaults?.model ?? '', systemInstructions: defaults?.systemPrompt ?? '',
|
|
138
|
+
enabledTools: [...(defaults?.tools ?? toolsForAgentCapabilities())],
|
|
139
|
+
availableTools: settings.defaultAgentConfig.availableTools,
|
|
140
|
+
} } : {}),
|
|
189
141
|
};
|
|
190
142
|
}
|
|
143
|
+
function mergeAcknowledgedFields(local, previous, incoming) {
|
|
144
|
+
const merged = { ...local };
|
|
145
|
+
for (const key of Object.keys(incoming)) {
|
|
146
|
+
if (JSON.stringify(local[key]) === JSON.stringify(previous[key]))
|
|
147
|
+
merged[key] = incoming[key];
|
|
148
|
+
}
|
|
149
|
+
return merged;
|
|
150
|
+
}
|
|
191
151
|
function normalizeBackupFrequency(value, fallback) {
|
|
192
152
|
return value === 'daily' || value === 'weekly' || value === 'monthly' ? value : fallback;
|
|
193
153
|
}
|
|
194
|
-
|
|
195
|
-
|
|
154
|
+
function backupScope(settings) {
|
|
155
|
+
const scope = {
|
|
156
|
+
workspaceId: settings.entityType === 'workspace' ? settings.entityId : settings.workspaceId,
|
|
157
|
+
teamId: settings.entityType === 'team' ? settings.entityId : settings.teamId,
|
|
158
|
+
agentId: settings.entityType === 'agent' ? settings.entityId : undefined,
|
|
159
|
+
};
|
|
160
|
+
return { ...scope, caller: { ...scope } };
|
|
161
|
+
}
|
|
162
|
+
function requireSuccess(value, operation) {
|
|
163
|
+
if (!value || typeof value !== 'object' || value.success !== true) {
|
|
164
|
+
const error = value?.error;
|
|
165
|
+
throw new Error(typeof error === 'string' ? error : `${operation} was not confirmed by the host.`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function settingsError(error) {
|
|
169
|
+
return error instanceof Error ? error.message : 'The host operation failed.';
|
|
170
|
+
}
|
|
171
|
+
// Each load has a generation, not just an entity id: A -> B -> A must not accept
|
|
172
|
+
// a response from the first A. Independent services load concurrently.
|
|
173
|
+
async function loadAsyncSectionData(settings, generation) {
|
|
196
174
|
const store = useEntitySettingsStore;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (current?.entityId === entityId) {
|
|
205
|
-
const normalizedBackupFrequency = normalizeBackupFrequency(backupSettings?.settings?.frequency, current.exportBackup.backupFrequency);
|
|
206
|
-
store.setState({
|
|
207
|
-
settings: {
|
|
208
|
-
...current,
|
|
209
|
-
exportBackup: {
|
|
210
|
-
...current.exportBackup,
|
|
211
|
-
autoBackupEnabled: backupSettings?.settings?.autoBackupEnabled ?? current.exportBackup.autoBackupEnabled,
|
|
212
|
-
backupFrequency: normalizedBackupFrequency,
|
|
213
|
-
retentionDays: backupSettings?.settings?.retentionDays ?? current.exportBackup.retentionDays,
|
|
214
|
-
availableBackups: (backupList?.backups || []).map((b) => ({
|
|
215
|
-
id: b.id,
|
|
216
|
-
name: b.name,
|
|
217
|
-
size: formatBytes(b.size),
|
|
218
|
-
createdAt: b.createdAt,
|
|
219
|
-
type: 'manual',
|
|
220
|
-
})),
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
});
|
|
175
|
+
const load = async (section, read) => {
|
|
176
|
+
try {
|
|
177
|
+
const patch = await read();
|
|
178
|
+
const state = store.getState();
|
|
179
|
+
if (state.loadGeneration !== generation || !state.settings)
|
|
180
|
+
return;
|
|
181
|
+
store.setState({ settings: { ...state.settings, ...patch } });
|
|
224
182
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (store.getState().loadGeneration === generation) {
|
|
185
|
+
store.setState(state => ({ sectionErrors: { ...state.sectionErrors, [section]: settingsError(error) } }));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
if (store.getState().loadGeneration === generation) {
|
|
190
|
+
store.setState(state => ({ sectionLoading: { ...state.sectionLoading, [section]: false } }));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
await Promise.all([
|
|
195
|
+
load('environment', async () => {
|
|
196
|
+
const api = getAgentPlatformBridge().workspace.environment;
|
|
197
|
+
if (!api)
|
|
198
|
+
throw new Error('Protected environment service is unavailable on this host.');
|
|
199
|
+
const result = await api({ scope: environmentScope(settings), action: 'list' });
|
|
200
|
+
requireSuccess(result, 'Environment load');
|
|
201
|
+
return { environment: environmentMetadata(result) };
|
|
202
|
+
}),
|
|
203
|
+
load('exportBackup', async () => {
|
|
204
|
+
const api = getAgentPlatformBridge().exportBackup;
|
|
205
|
+
if (!api?.listBackups || !api.getSettings)
|
|
206
|
+
throw new Error('Backup service is not available on this host.');
|
|
207
|
+
const [list, policy] = await Promise.all([api.listBackups(backupScope(settings)), api.getSettings(backupScope(settings))]);
|
|
208
|
+
requireSuccess(list, 'Backup listing');
|
|
209
|
+
requireSuccess(policy, 'Backup policy');
|
|
210
|
+
if (!Array.isArray(list.backups) || !policy.settings)
|
|
211
|
+
throw new Error('The host returned an invalid backup response.');
|
|
212
|
+
return { exportBackup: {
|
|
213
|
+
...settings.exportBackup,
|
|
214
|
+
autoBackupEnabled: policy.settings.autoBackupEnabled,
|
|
215
|
+
backupFrequency: normalizeBackupFrequency(policy.settings.frequency, settings.exportBackup.backupFrequency),
|
|
216
|
+
retentionDays: policy.settings.retentionDays,
|
|
217
|
+
lastError: policy.settings.lastError,
|
|
218
|
+
availableBackups: list.backups.map(b => ({
|
|
219
|
+
id: b.id, name: b.name, size: formatBytes(b.size), createdAt: b.createdAt, type: 'manual',
|
|
220
|
+
})),
|
|
221
|
+
} };
|
|
222
|
+
}),
|
|
223
|
+
load('usage', async () => {
|
|
224
|
+
const api = getAgentPlatformBridge().usage;
|
|
225
|
+
if (!api?.snapshot)
|
|
226
|
+
throw new Error('Scoped usage service is not available on this host.');
|
|
227
|
+
const result = await api.snapshot({ entityType: settings.entityType, entityId: settings.entityId });
|
|
228
|
+
if (!isAgentUsageResult(result))
|
|
229
|
+
throw new Error('The host returned an invalid usage response.');
|
|
230
|
+
if (!result.success)
|
|
231
|
+
throw new Error(result.error);
|
|
232
|
+
const summary = result.snapshot;
|
|
233
|
+
if (!Number.isSafeInteger(summary.totalTokens) || summary.totalTokens < 0 || !Array.isArray(summary.costByModel) || !Array.isArray(summary.topAgents)) {
|
|
234
|
+
throw new Error('The host returned an invalid usage response.');
|
|
235
|
+
}
|
|
236
|
+
return { usage: {
|
|
237
|
+
totalTokens: summary.totalTokens, totalCost: summary.totalCost, totalRequests: summary.totalRequests,
|
|
238
|
+
unmeasuredRequests: summary.unmeasuredRequests, observedAt: summary.observedAt,
|
|
239
|
+
dailyUsage: summary.dailyUsage, weeklyUsage: summary.weeklyUsage, monthlyUsage: summary.monthlyUsage,
|
|
240
|
+
costByModel: summary.costByModel, topAgents: summary.topAgents,
|
|
241
|
+
} };
|
|
242
|
+
}),
|
|
243
|
+
]);
|
|
244
|
+
}
|
|
245
|
+
async function runBackupOperation(operation) {
|
|
246
|
+
const store = useEntitySettingsStore;
|
|
247
|
+
const state = store.getState();
|
|
248
|
+
if (!state.settings || state.backupBusy || state.sectionLoading.exportBackup)
|
|
249
|
+
return;
|
|
250
|
+
const { settings, loadGeneration } = state;
|
|
251
|
+
store.setState({ backupBusy: true, sectionErrors: { ...state.sectionErrors, exportBackup: undefined } });
|
|
228
252
|
try {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const usageSummary = (summary || {});
|
|
237
|
-
const usageByModel = (byModel || {});
|
|
238
|
-
const usageTopAgents = (topAgents || {});
|
|
239
|
-
store.setState({
|
|
240
|
-
settings: {
|
|
241
|
-
...current,
|
|
242
|
-
usage: {
|
|
243
|
-
totalTokens: usageSummary.totalTokens ?? 0,
|
|
244
|
-
totalCost: usageSummary.totalCost ?? 0,
|
|
245
|
-
totalRequests: usageSummary.totalRequests ?? 0,
|
|
246
|
-
dailyUsage: usageSummary.dataPoints || [],
|
|
247
|
-
weeklyUsage: [],
|
|
248
|
-
monthlyUsage: [],
|
|
249
|
-
costByModel: usageByModel.costByModel || [],
|
|
250
|
-
topAgents: usageTopAgents.topAgents || [],
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
});
|
|
253
|
+
const api = getAgentPlatformBridge().exportBackup;
|
|
254
|
+
if (!api)
|
|
255
|
+
throw new Error('Backup service is not available on this host.');
|
|
256
|
+
const patch = await operation(api, settings);
|
|
257
|
+
const current = store.getState();
|
|
258
|
+
if (current.loadGeneration === loadGeneration && current.settings && patch) {
|
|
259
|
+
store.setState({ settings: { ...current.settings, exportBackup: { ...current.settings.exportBackup, ...patch } } });
|
|
254
260
|
}
|
|
255
261
|
}
|
|
256
|
-
catch {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const result = await getAgentPlatformBridge()?.audit?.list?.(20);
|
|
260
|
-
const current = store.getState().settings;
|
|
261
|
-
if (current?.entityId === entityId) {
|
|
262
|
-
const auditEntries = (result || {}).entries || [];
|
|
263
|
-
store.setState({
|
|
264
|
-
settings: {
|
|
265
|
-
...current,
|
|
266
|
-
security: {
|
|
267
|
-
...current.security,
|
|
268
|
-
auditLog: auditEntries.map((e, i) => ({
|
|
269
|
-
id: `audit_${i}`,
|
|
270
|
-
action: e.action,
|
|
271
|
-
actor: e.user || 'You',
|
|
272
|
-
target: e.entity || '',
|
|
273
|
-
timestamp: e.timestamp,
|
|
274
|
-
details: e.details || '',
|
|
275
|
-
})),
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
});
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (store.getState().loadGeneration === loadGeneration) {
|
|
264
|
+
store.setState(current => ({ sectionErrors: { ...current.sectionErrors, exportBackup: settingsError(error) } }));
|
|
279
265
|
}
|
|
280
266
|
}
|
|
281
|
-
|
|
267
|
+
finally {
|
|
268
|
+
if (store.getState().loadGeneration === loadGeneration)
|
|
269
|
+
store.setState({ backupBusy: false });
|
|
270
|
+
}
|
|
282
271
|
}
|
|
283
272
|
function formatBytes(bytes) {
|
|
284
273
|
if (bytes < 1024)
|
|
@@ -303,39 +292,69 @@ function syncNotificationsToWorkspaceStore(settings, notif) {
|
|
|
303
292
|
});
|
|
304
293
|
}
|
|
305
294
|
// Sync env vars from settings back to workspace store
|
|
306
|
-
function
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
295
|
+
function environmentScope(settings) {
|
|
296
|
+
const value = backupScope(settings);
|
|
297
|
+
return { workspaceId: String(value.workspaceId || ''), ...(value.teamId ? { teamId: String(value.teamId) } : {}), ...(value.agentId ? { agentId: String(value.agentId) } : {}) };
|
|
298
|
+
}
|
|
299
|
+
function environmentMetadata(result) {
|
|
300
|
+
if (!Array.isArray(result.variables))
|
|
301
|
+
throw new Error('Invalid environment metadata from host');
|
|
302
|
+
return { environmentRevision: result.environmentRevision, protectedStorageAvailable: result.protectedStorageAvailable, variables: result.variables.map(variable => ({ ...variable, id: variable.key, value: '' })) };
|
|
303
|
+
}
|
|
304
|
+
async function changeEnvironment(input) {
|
|
305
|
+
const store = useEntitySettingsStore;
|
|
306
|
+
const initial = store.getState();
|
|
307
|
+
if (!initial.settings || initial.environmentBusy || initial.sectionLoading.environment)
|
|
308
|
+
return false;
|
|
309
|
+
const generation = initial.loadGeneration;
|
|
310
|
+
store.setState({ environmentBusy: true, sectionErrors: { ...initial.sectionErrors, environment: undefined } });
|
|
311
|
+
try {
|
|
312
|
+
const bridge = getAgentPlatformBridge();
|
|
313
|
+
const api = bridge.workspace.environment;
|
|
314
|
+
if (!api)
|
|
315
|
+
throw new Error('Protected environment service is unavailable on this host.');
|
|
316
|
+
const state = await bridge.workspaceStorage.load();
|
|
317
|
+
if (!state.success || !state.revision)
|
|
318
|
+
throw new Error('Reload workspace state before changing environment values.');
|
|
319
|
+
const result = await api({ ...input, scope: environmentScope(initial.settings), expectedRevision: state.revision, expectedEnvironmentRevision: initial.settings.environment.environmentRevision });
|
|
320
|
+
requireSuccess(result, 'Environment update');
|
|
321
|
+
if (store.getState().loadGeneration === generation)
|
|
322
|
+
store.setState(current => ({ settings: current.settings ? { ...current.settings, environment: environmentMetadata(result) } : null }));
|
|
323
|
+
return true;
|
|
311
324
|
}
|
|
312
|
-
|
|
313
|
-
|
|
325
|
+
catch (error) {
|
|
326
|
+
if (store.getState().loadGeneration === generation)
|
|
327
|
+
store.setState(current => ({ sectionErrors: { ...current.sectionErrors, environment: settingsError(error) } }));
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
finally {
|
|
331
|
+
if (store.getState().loadGeneration === generation)
|
|
332
|
+
store.setState({ environmentBusy: false });
|
|
314
333
|
}
|
|
315
334
|
}
|
|
316
335
|
export const useEntitySettingsStore = create((set, get) => ({
|
|
336
|
+
environmentBusy: false,
|
|
317
337
|
settings: null,
|
|
318
338
|
activeSection: 'general',
|
|
319
339
|
isLoading: false,
|
|
320
340
|
isDirty: false,
|
|
341
|
+
profileDraftPending: false,
|
|
342
|
+
profileDraftError: undefined,
|
|
343
|
+
loadGeneration: 0,
|
|
344
|
+
sectionErrors: {},
|
|
345
|
+
sectionLoading: {},
|
|
346
|
+
backupBusy: false,
|
|
321
347
|
loadSettings: (entityId, entityType, entityName, extra) => {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
348
|
+
const generation = get().loadGeneration + 1;
|
|
349
|
+
set({ isLoading: true, loadGeneration: generation, sectionErrors: {}, backupBusy: false,
|
|
350
|
+
environmentBusy: false, backupRestoreResult: undefined,
|
|
351
|
+
sectionLoading: { exportBackup: true, usage: true, environment: true } });
|
|
352
|
+
const settings = createInitialSettings(entityId, entityType, entityName, extra);
|
|
325
353
|
const wsStore = useWorkspaceStore.getState();
|
|
326
354
|
// Get current user from auth store for real owner info
|
|
327
|
-
const authUser = useAuthStore.getState().user;
|
|
328
355
|
if (entityType === 'workspace') {
|
|
329
356
|
const ws = wsStore.workspaces.find(w => w.id === entityId);
|
|
330
357
|
if (ws) {
|
|
331
|
-
// General — all real
|
|
332
|
-
const slug = ws.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
333
|
-
settings.general.name = ws.name;
|
|
334
|
-
settings.general.description = ws.description || '';
|
|
335
|
-
settings.general.slug = slug;
|
|
336
|
-
settings.general.icon = 'building';
|
|
337
|
-
settings.general.createdAt = ws.createdAt ? new Date(ws.createdAt).toISOString() : settings.general.createdAt;
|
|
338
|
-
settings.general.updatedAt = ws.updatedAt ? new Date(ws.updatedAt).toISOString() : settings.general.createdAt;
|
|
339
358
|
// Resource limits — real quotas from hierarchy
|
|
340
359
|
const teamCount = ws.teams.length;
|
|
341
360
|
const agentCount = ws.teams.reduce((sum, t) => sum + t.agents.length, 0);
|
|
@@ -351,6 +370,8 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
351
370
|
variables: (ws.envVars || []).map((v, i) => ({
|
|
352
371
|
id: `env_${i}`,
|
|
353
372
|
...v,
|
|
373
|
+
value: '',
|
|
374
|
+
legacy: true,
|
|
354
375
|
updatedAt: new Date().toISOString(),
|
|
355
376
|
})),
|
|
356
377
|
};
|
|
@@ -369,11 +390,9 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
369
390
|
};
|
|
370
391
|
}
|
|
371
392
|
// Access — real current user as owner, no fake members
|
|
372
|
-
const ownerName = authUser?.display_name || authUser?.username || 'You';
|
|
373
|
-
const ownerEmail = authUser?.email || '';
|
|
374
393
|
settings.access = {
|
|
375
|
-
owner:
|
|
376
|
-
members: [
|
|
394
|
+
owner: null,
|
|
395
|
+
members: [],
|
|
377
396
|
pendingInvites: [],
|
|
378
397
|
publicAccess: ws.access?.publicAccess ?? false,
|
|
379
398
|
allowGuestViewing: ws.access?.allowGuestViewing ?? false,
|
|
@@ -397,10 +416,6 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
397
416
|
const ws = wsStore.workspaces.find(w => w.id === extra.workspaceId);
|
|
398
417
|
const team = ws?.teams.find(t => t.id === entityId);
|
|
399
418
|
if (team) {
|
|
400
|
-
settings.general.name = team.name;
|
|
401
|
-
settings.general.description = team.description || '';
|
|
402
|
-
settings.general.slug = team.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
403
|
-
settings.general.icon = 'users';
|
|
404
419
|
settings.resourceLimits.quotas = [
|
|
405
420
|
{ label: 'Agents', current: team.agents.length, limit: 50, unit: 'agents' },
|
|
406
421
|
];
|
|
@@ -410,15 +425,15 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
410
425
|
variables: (team.envVars || []).map((v, i) => ({
|
|
411
426
|
id: `env_${i}`,
|
|
412
427
|
...v,
|
|
428
|
+
value: '',
|
|
429
|
+
legacy: true,
|
|
413
430
|
updatedAt: new Date().toISOString(),
|
|
414
431
|
})),
|
|
415
432
|
};
|
|
416
433
|
// Real owner
|
|
417
|
-
const ownerName = authUser?.display_name || authUser?.username || 'You';
|
|
418
|
-
const ownerEmail = authUser?.email || '';
|
|
419
434
|
settings.access = {
|
|
420
|
-
owner:
|
|
421
|
-
members: [
|
|
435
|
+
owner: null,
|
|
436
|
+
members: [],
|
|
422
437
|
pendingInvites: [],
|
|
423
438
|
publicAccess: false,
|
|
424
439
|
allowGuestViewing: false,
|
|
@@ -430,65 +445,102 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
430
445
|
const team = ws?.teams.find(t => t.id === extra.teamId);
|
|
431
446
|
const agent = team?.agents.find(a => a.id === entityId);
|
|
432
447
|
if (agent) {
|
|
433
|
-
settings.general.name = agent.name;
|
|
434
|
-
settings.general.description = agent.description || '';
|
|
435
|
-
settings.general.slug = agent.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
|
|
436
|
-
settings.general.icon = 'bot';
|
|
437
448
|
settings.resourceLimits.quotas = [
|
|
438
449
|
{ label: 'Conversations', current: Object.values(useAgentChatStore.getState().conversations).filter(c => c.agentId === entityId).length, limit: 1000, unit: 'convs' },
|
|
439
450
|
];
|
|
440
451
|
// Real owner
|
|
441
|
-
const ownerName = authUser?.display_name || authUser?.username || 'You';
|
|
442
|
-
const ownerEmail = authUser?.email || '';
|
|
443
452
|
settings.access = {
|
|
444
|
-
owner:
|
|
445
|
-
members: [
|
|
453
|
+
owner: null,
|
|
454
|
+
members: [],
|
|
446
455
|
pendingInvites: [],
|
|
447
456
|
publicAccess: false,
|
|
448
457
|
allowGuestViewing: false,
|
|
449
458
|
};
|
|
450
|
-
if (settings.defaultAgentConfig) {
|
|
451
|
-
settings.defaultAgentConfig.defaultModel = agent.model || 'claude-sonnet-4-6';
|
|
452
|
-
settings.defaultAgentConfig.systemInstructions = agent.systemPrompt || '';
|
|
453
|
-
settings.defaultAgentConfig.enabledTools = agent.tools || ['web-search', 'code-execution', 'file-read'];
|
|
454
|
-
}
|
|
455
459
|
settings.resourceLimits.rateLimitRpm = agent.rateLimits?.requestsPerMinute ?? settings.resourceLimits.rateLimitRpm;
|
|
456
460
|
settings.resourceLimits.rateLimitTpd = agent.rateLimits?.tokensPerDay ?? settings.resourceLimits.rateLimitTpd;
|
|
457
461
|
}
|
|
458
462
|
}
|
|
459
|
-
|
|
463
|
+
selectedHierarchyBaseline = projectHierarchySettings(settings, wsStore.workspaces);
|
|
464
|
+
if (selectedHierarchyBaseline) {
|
|
465
|
+
const { identity: _identity, ...projection } = selectedHierarchyBaseline;
|
|
466
|
+
Object.assign(settings, projection);
|
|
467
|
+
}
|
|
468
|
+
const draft = selectedHierarchyBaseline && currentProfileDrafts().get(selectedHierarchyBaseline.identity);
|
|
469
|
+
if (draft)
|
|
470
|
+
settings.general = { ...settings.general, ...draft.fields };
|
|
471
|
+
set({ settings, isLoading: false, activeSection: 'general', isDirty: Boolean(draft),
|
|
472
|
+
profileDraftPending: Boolean(draft), profileDraftError: draft ? validateProfileDraft(settings.general) : undefined });
|
|
460
473
|
// Async: load real data for IPC-backed sections
|
|
461
|
-
loadAsyncSectionData(
|
|
474
|
+
void loadAsyncSectionData(settings, generation);
|
|
462
475
|
},
|
|
463
476
|
setActiveSection: (section) => set({ activeSection: section }),
|
|
464
|
-
clearSettings: () =>
|
|
477
|
+
clearSettings: () => {
|
|
478
|
+
selectedHierarchyBaseline = undefined;
|
|
479
|
+
set(state => ({ settings: null, activeSection: 'general', isDirty: false,
|
|
480
|
+
profileDraftPending: false, profileDraftError: undefined,
|
|
481
|
+
loadGeneration: state.loadGeneration + 1, sectionErrors: {}, sectionLoading: {}, backupBusy: false }));
|
|
482
|
+
},
|
|
465
483
|
updateGeneral: (updates) => {
|
|
466
484
|
const { settings } = get();
|
|
467
|
-
|
|
485
|
+
const identity = selectedHierarchyBaseline?.identity;
|
|
486
|
+
if (!settings || !identity)
|
|
487
|
+
return;
|
|
488
|
+
const fields = {
|
|
489
|
+
...(updates.name !== undefined ? { name: updates.name } : {}),
|
|
490
|
+
...(updates.description !== undefined ? { description: updates.description } : {}),
|
|
491
|
+
};
|
|
492
|
+
if (!Object.keys(fields).length)
|
|
468
493
|
return;
|
|
494
|
+
const drafts = currentProfileDrafts();
|
|
495
|
+
const previous = drafts.get(identity);
|
|
496
|
+
const draft = { fields: { ...previous?.fields, ...fields }, submitted: { ...previous?.submitted } };
|
|
497
|
+
drafts.set(identity, draft);
|
|
498
|
+
const general = { ...settings.general, ...draft.fields };
|
|
499
|
+
const error = validateProfileDraft(general);
|
|
469
500
|
set({
|
|
470
|
-
settings: { ...settings, general
|
|
471
|
-
isDirty: true,
|
|
501
|
+
settings: { ...settings, general }, isDirty: true, profileDraftPending: true, profileDraftError: error,
|
|
472
502
|
});
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
503
|
+
if (!error)
|
|
504
|
+
void persistProfileFields(settings, identity, drafts, draft.fields);
|
|
505
|
+
},
|
|
506
|
+
discardProfileChanges: async () => {
|
|
507
|
+
const state = get(), identity = selectedHierarchyBaseline?.identity;
|
|
508
|
+
if (!state.settings || !identity)
|
|
509
|
+
return false;
|
|
510
|
+
const drafts = currentProfileDrafts(), draft = drafts.get(identity);
|
|
511
|
+
if (!draft)
|
|
512
|
+
return true;
|
|
513
|
+
try {
|
|
514
|
+
const loaded = await getAgentPlatformBridge().workspaceStorage.load();
|
|
515
|
+
if (!loaded.success || !Array.isArray(loaded.workspaces))
|
|
516
|
+
throw new Error('Acknowledged profile is unavailable; draft retained.');
|
|
517
|
+
const incoming = projectHierarchySettings(state.settings, loaded.workspaces);
|
|
518
|
+
if (!incoming || incoming.identity !== identity)
|
|
519
|
+
throw new Error('The original profile no longer exists; draft retained.');
|
|
520
|
+
if (selectedHierarchyBaseline?.identity !== identity || drafts.get(identity) !== draft)
|
|
521
|
+
return false;
|
|
522
|
+
// Submitted edits may still exist in the optimistic hierarchy. Revert only
|
|
523
|
+
// those profile fields through its existing CAS path, never reset the tree.
|
|
524
|
+
if (Object.keys(draft.submitted).length) {
|
|
525
|
+
const revert = Object.fromEntries(Object.keys(draft.submitted).map(key => [key, incoming.general[key]]));
|
|
526
|
+
draft.fields = revert;
|
|
527
|
+
if (!await persistProfileFields(state.settings, identity, drafts, revert))
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
if (selectedHierarchyBaseline?.identity !== identity || (drafts.has(identity) && drafts.get(identity) !== draft))
|
|
531
|
+
return false;
|
|
532
|
+
drafts.delete(identity);
|
|
533
|
+
selectedHierarchyBaseline = incoming;
|
|
534
|
+
const current = get();
|
|
535
|
+
if (current.settings && projectHierarchySettings(current.settings, loaded.workspaces)?.identity === identity) {
|
|
536
|
+
set({ settings: { ...current.settings, general: { ...current.settings.general, name: incoming.general.name, description: incoming.general.description, slug: incoming.general.slug } }, profileDraftPending: false, profileDraftError: undefined });
|
|
537
|
+
}
|
|
538
|
+
return true;
|
|
486
539
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
});
|
|
540
|
+
catch (error) {
|
|
541
|
+
if (selectedHierarchyBaseline?.identity === identity)
|
|
542
|
+
set({ profileDraftError: error instanceof Error ? error.message : 'Profile discard failed; draft retained.' });
|
|
543
|
+
return false;
|
|
492
544
|
}
|
|
493
545
|
},
|
|
494
546
|
updateDefaultAgentConfig: (updates) => {
|
|
@@ -499,6 +551,21 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
499
551
|
settings: { ...settings, defaultAgentConfig: { ...settings.defaultAgentConfig, ...updates } },
|
|
500
552
|
isDirty: true,
|
|
501
553
|
});
|
|
554
|
+
const workspace = useWorkspaceStore.getState().workspaces.find(w => w.id === (settings.workspaceId || settings.entityId));
|
|
555
|
+
const existing = settings.entityType === 'workspace' ? workspace?.agentDefaults
|
|
556
|
+
: workspace?.teams.find(t => t.id === settings.entityId)?.agentDefaults;
|
|
557
|
+
const defaults = {
|
|
558
|
+
...existing,
|
|
559
|
+
...(updates.defaultModel !== undefined ? { model: updates.defaultModel } : {}),
|
|
560
|
+
...(updates.systemInstructions !== undefined ? { systemPrompt: updates.systemInstructions } : {}),
|
|
561
|
+
...(updates.enabledTools !== undefined ? { tools: [...updates.enabledTools] } : {}),
|
|
562
|
+
};
|
|
563
|
+
if (settings.entityType === 'workspace') {
|
|
564
|
+
useWorkspaceStore.getState().updateWorkspace(settings.entityId, { agentDefaults: defaults });
|
|
565
|
+
}
|
|
566
|
+
else if (settings.entityType === 'team' && settings.workspaceId) {
|
|
567
|
+
useWorkspaceStore.getState().updateTeam(settings.workspaceId, settings.entityId, { agentDefaults: defaults });
|
|
568
|
+
}
|
|
502
569
|
// Persist to workspace store — for agents, update model/prompt/tools
|
|
503
570
|
if (settings.entityType === 'agent' && settings.workspaceId && settings.teamId) {
|
|
504
571
|
const agentUpdates = {};
|
|
@@ -512,22 +579,7 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
512
579
|
}
|
|
513
580
|
},
|
|
514
581
|
updateAccess: (updates) => {
|
|
515
|
-
|
|
516
|
-
if (!settings)
|
|
517
|
-
return;
|
|
518
|
-
set({
|
|
519
|
-
settings: { ...settings, access: { ...settings.access, ...updates } },
|
|
520
|
-
isDirty: true,
|
|
521
|
-
});
|
|
522
|
-
// Persist access settings to workspace store
|
|
523
|
-
if (settings.entityType === 'workspace') {
|
|
524
|
-
useWorkspaceStore.getState().updateWorkspace(settings.entityId, {
|
|
525
|
-
access: {
|
|
526
|
-
publicAccess: updates.publicAccess ?? settings.access.publicAccess,
|
|
527
|
-
allowGuestViewing: updates.allowGuestViewing ?? settings.access.allowGuestViewing,
|
|
528
|
-
},
|
|
529
|
-
});
|
|
530
|
-
}
|
|
582
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, access: 'Workspace sharing is not connected to an access-control authority. Access was not changed.' } }));
|
|
531
583
|
},
|
|
532
584
|
updateResourceLimits: (updates) => {
|
|
533
585
|
const { settings } = get();
|
|
@@ -577,155 +629,55 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
577
629
|
}
|
|
578
630
|
},
|
|
579
631
|
updateSecurity: (updates) => {
|
|
580
|
-
|
|
581
|
-
if (!settings)
|
|
582
|
-
return;
|
|
583
|
-
const merged = { ...settings.security, ...updates };
|
|
584
|
-
set({
|
|
585
|
-
settings: { ...settings, security: merged },
|
|
586
|
-
isDirty: true,
|
|
587
|
-
});
|
|
588
|
-
// Persist security settings to workspace store
|
|
589
|
-
if (settings.entityType === 'workspace') {
|
|
590
|
-
useWorkspaceStore.getState().updateWorkspace(settings.entityId, {
|
|
591
|
-
security: {
|
|
592
|
-
require2FA: merged.require2FA,
|
|
593
|
-
requireApiKeyAuth: merged.requireApiKeyAuth,
|
|
594
|
-
sessionTimeout: merged.sessionTimeout,
|
|
595
|
-
ipAllowlist: [...merged.ipAllowlist],
|
|
596
|
-
},
|
|
597
|
-
});
|
|
598
|
-
}
|
|
632
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, security: 'Workspace authentication policy is not connected to an enforcement authority. Security settings were not changed.' } }));
|
|
599
633
|
},
|
|
600
|
-
updateExportBackup: (updates) => {
|
|
601
|
-
const
|
|
602
|
-
if (!settings)
|
|
603
|
-
return;
|
|
604
|
-
set({
|
|
605
|
-
settings: { ...settings, exportBackup: { ...settings.exportBackup, ...updates } },
|
|
606
|
-
isDirty: true,
|
|
607
|
-
});
|
|
608
|
-
// Persist backup settings
|
|
609
|
-
getAgentPlatformBridge()?.exportBackup?.updateSettings?.({
|
|
634
|
+
updateExportBackup: (updates) => runBackupOperation(async (api, settings) => {
|
|
635
|
+
const policy = {
|
|
610
636
|
autoBackupEnabled: updates.autoBackupEnabled ?? settings.exportBackup.autoBackupEnabled,
|
|
611
637
|
frequency: updates.backupFrequency ?? settings.exportBackup.backupFrequency,
|
|
612
638
|
retentionDays: updates.retentionDays ?? settings.exportBackup.retentionDays,
|
|
613
|
-
}
|
|
614
|
-
|
|
639
|
+
};
|
|
640
|
+
if (!Number.isInteger(policy.retentionDays) || policy.retentionDays < 7 || policy.retentionDays > 90) {
|
|
641
|
+
throw new Error('Backup retention must be an integer between 7 and 90 days.');
|
|
642
|
+
}
|
|
643
|
+
const result = await api.updateSettings({ ...backupScope(settings), ...policy });
|
|
644
|
+
requireSuccess(result, 'Backup policy update');
|
|
645
|
+
return { autoBackupEnabled: policy.autoBackupEnabled, backupFrequency: policy.frequency, retentionDays: policy.retentionDays };
|
|
646
|
+
}),
|
|
615
647
|
addMember: (member) => {
|
|
616
|
-
|
|
617
|
-
if (!settings)
|
|
618
|
-
return;
|
|
619
|
-
const newMember = { ...member, id: `user_${generateId()}`, joinedAt: new Date().toISOString() };
|
|
620
|
-
set({
|
|
621
|
-
settings: { ...settings, access: { ...settings.access, members: [...settings.access.members, newMember] } },
|
|
622
|
-
isDirty: true,
|
|
623
|
-
});
|
|
648
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, access: 'Member invitations require a connected workspace membership authority. No invitation was sent.' } }));
|
|
624
649
|
},
|
|
625
650
|
removeMember: (memberId) => {
|
|
626
|
-
|
|
627
|
-
if (!settings)
|
|
628
|
-
return;
|
|
629
|
-
set({
|
|
630
|
-
settings: {
|
|
631
|
-
...settings,
|
|
632
|
-
access: { ...settings.access, members: settings.access.members.filter(m => m.id !== memberId) },
|
|
633
|
-
},
|
|
634
|
-
isDirty: true,
|
|
635
|
-
});
|
|
651
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, access: 'Member removal requires a connected workspace membership authority. Membership was not changed.' } }));
|
|
636
652
|
},
|
|
637
653
|
updateMemberRole: (memberId, role) => {
|
|
638
|
-
|
|
639
|
-
if (!settings)
|
|
640
|
-
return;
|
|
641
|
-
set({
|
|
642
|
-
settings: {
|
|
643
|
-
...settings,
|
|
644
|
-
access: {
|
|
645
|
-
...settings.access,
|
|
646
|
-
members: settings.access.members.map(m => m.id === memberId ? { ...m, role } : m),
|
|
647
|
-
},
|
|
648
|
-
},
|
|
649
|
-
isDirty: true,
|
|
650
|
-
});
|
|
654
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, access: 'Role changes require a connected workspace membership authority. Permissions were not changed.' } }));
|
|
651
655
|
},
|
|
652
656
|
addIntegration: (integration) => {
|
|
653
|
-
|
|
654
|
-
if (!settings)
|
|
655
|
-
return;
|
|
656
|
-
const newInt = { ...integration, id: `int_${generateId()}` };
|
|
657
|
-
set({
|
|
658
|
-
settings: {
|
|
659
|
-
...settings,
|
|
660
|
-
integrations: { ...settings.integrations, integrations: [...settings.integrations.integrations, newInt] },
|
|
661
|
-
},
|
|
662
|
-
isDirty: true,
|
|
663
|
-
});
|
|
657
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Integration authorization is not connected on this surface. No service was connected.' } }));
|
|
664
658
|
},
|
|
665
659
|
removeIntegration: (integrationId) => {
|
|
666
|
-
|
|
667
|
-
if (!settings)
|
|
668
|
-
return;
|
|
669
|
-
set({
|
|
670
|
-
settings: {
|
|
671
|
-
...settings,
|
|
672
|
-
integrations: {
|
|
673
|
-
...settings.integrations,
|
|
674
|
-
integrations: settings.integrations.integrations.filter(i => i.id !== integrationId),
|
|
675
|
-
},
|
|
676
|
-
},
|
|
677
|
-
isDirty: true,
|
|
678
|
-
});
|
|
660
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Integration revocation is not connected on this surface. No service was disconnected.' } }));
|
|
679
661
|
},
|
|
680
662
|
toggleIntegration: (integrationId) => {
|
|
681
|
-
|
|
682
|
-
if (!settings)
|
|
683
|
-
return;
|
|
684
|
-
set({
|
|
685
|
-
settings: {
|
|
686
|
-
...settings,
|
|
687
|
-
integrations: {
|
|
688
|
-
...settings.integrations,
|
|
689
|
-
integrations: settings.integrations.integrations.map(i => i.id === integrationId ? { ...i, enabled: !i.enabled, status: !i.enabled ? 'connected' : 'disconnected' } : i),
|
|
690
|
-
},
|
|
691
|
-
},
|
|
692
|
-
isDirty: true,
|
|
693
|
-
});
|
|
663
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Integration authorization is not connected on this surface. Connection status was not changed.' } }));
|
|
694
664
|
},
|
|
695
665
|
addEnvironmentVariable: (variable) => {
|
|
696
|
-
|
|
697
|
-
if (!settings)
|
|
698
|
-
return;
|
|
699
|
-
const newVar = { ...variable, id: `env_${generateId()}`, updatedAt: new Date().toISOString() };
|
|
700
|
-
const nextVars = [...settings.environment.variables, newVar];
|
|
701
|
-
set({
|
|
702
|
-
settings: { ...settings, environment: { variables: nextVars } },
|
|
703
|
-
isDirty: true,
|
|
704
|
-
});
|
|
705
|
-
syncEnvVarsToWorkspaceStore(settings, nextVars);
|
|
666
|
+
return changeEnvironment({ action: 'set', key: variable.key, value: variable.value, isSecret: variable.isSecret });
|
|
706
667
|
},
|
|
707
668
|
updateEnvironmentVariable: (variableId, updates) => {
|
|
708
669
|
const { settings } = get();
|
|
709
670
|
if (!settings)
|
|
710
|
-
return;
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
});
|
|
716
|
-
syncEnvVarsToWorkspaceStore(settings, nextVars);
|
|
671
|
+
return Promise.resolve(false);
|
|
672
|
+
const current = settings.environment.variables.find(variable => variable.id === variableId);
|
|
673
|
+
if (!current || updates.value === undefined)
|
|
674
|
+
return Promise.resolve(false);
|
|
675
|
+
return changeEnvironment({ action: 'set', key: current.key, value: updates.value, isSecret: updates.isSecret ?? current.isSecret });
|
|
717
676
|
},
|
|
718
677
|
deleteEnvironmentVariable: (variableId) => {
|
|
719
|
-
|
|
720
|
-
if (!settings)
|
|
721
|
-
return;
|
|
722
|
-
const nextVars = settings.environment.variables.filter(v => v.id !== variableId);
|
|
723
|
-
set({
|
|
724
|
-
settings: { ...settings, environment: { variables: nextVars } },
|
|
725
|
-
isDirty: true,
|
|
726
|
-
});
|
|
727
|
-
syncEnvVarsToWorkspaceStore(settings, nextVars);
|
|
678
|
+
return changeEnvironment({ action: 'delete', key: variableId });
|
|
728
679
|
},
|
|
680
|
+
migrateEnvironmentVariables: () => changeEnvironment({ action: 'migrate' }),
|
|
729
681
|
addNotificationRule: (rule) => {
|
|
730
682
|
const { settings } = get();
|
|
731
683
|
if (!settings)
|
|
@@ -761,156 +713,177 @@ export const useEntitySettingsStore = create((set, get) => ({
|
|
|
761
713
|
syncNotificationsToWorkspaceStore(settings, { ...settings.notifications, rules: nextRules });
|
|
762
714
|
},
|
|
763
715
|
addApiKey: (key) => {
|
|
764
|
-
|
|
765
|
-
if (!settings)
|
|
766
|
-
return;
|
|
767
|
-
const now = new Date().toISOString();
|
|
768
|
-
const newKey = { ...key, id: `key_${generateId()}`, createdAt: now, lastUsed: now };
|
|
769
|
-
set({
|
|
770
|
-
settings: {
|
|
771
|
-
...settings,
|
|
772
|
-
integrations: { ...settings.integrations, apiKeys: [...settings.integrations.apiKeys, newKey] },
|
|
773
|
-
},
|
|
774
|
-
isDirty: true,
|
|
775
|
-
});
|
|
716
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Workspace API-key issuance is not connected on this surface. No API key was created.' } }));
|
|
776
717
|
},
|
|
777
718
|
removeApiKey: (keyId) => {
|
|
778
|
-
|
|
779
|
-
if (!settings)
|
|
780
|
-
return;
|
|
781
|
-
set({
|
|
782
|
-
settings: {
|
|
783
|
-
...settings,
|
|
784
|
-
integrations: { ...settings.integrations, apiKeys: settings.integrations.apiKeys.filter(k => k.id !== keyId) },
|
|
785
|
-
},
|
|
786
|
-
isDirty: true,
|
|
787
|
-
});
|
|
719
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Workspace API-key revocation is not connected on this surface. No API key was revoked.' } }));
|
|
788
720
|
},
|
|
789
721
|
addWebhook: (webhook) => {
|
|
790
|
-
|
|
791
|
-
if (!settings)
|
|
792
|
-
return;
|
|
793
|
-
const newWh = { ...webhook, id: `wh_${generateId()}`, createdAt: new Date().toISOString() };
|
|
794
|
-
set({
|
|
795
|
-
settings: {
|
|
796
|
-
...settings,
|
|
797
|
-
integrations: { ...settings.integrations, webhookEndpoints: [...settings.integrations.webhookEndpoints, newWh] },
|
|
798
|
-
},
|
|
799
|
-
isDirty: true,
|
|
800
|
-
});
|
|
722
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Webhook delivery is not connected on this surface. No webhook was registered.' } }));
|
|
801
723
|
},
|
|
802
724
|
removeWebhook: (webhookId) => {
|
|
803
|
-
|
|
804
|
-
if (!settings)
|
|
805
|
-
return;
|
|
806
|
-
set({
|
|
807
|
-
settings: {
|
|
808
|
-
...settings,
|
|
809
|
-
integrations: {
|
|
810
|
-
...settings.integrations,
|
|
811
|
-
webhookEndpoints: settings.integrations.webhookEndpoints.filter(w => w.id !== webhookId),
|
|
812
|
-
},
|
|
813
|
-
},
|
|
814
|
-
isDirty: true,
|
|
815
|
-
});
|
|
725
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Webhook delivery is not connected on this surface. No webhook was removed.' } }));
|
|
816
726
|
},
|
|
817
727
|
toggleWebhook: (webhookId) => {
|
|
818
|
-
|
|
819
|
-
if (!settings)
|
|
820
|
-
return;
|
|
821
|
-
set({
|
|
822
|
-
settings: {
|
|
823
|
-
...settings,
|
|
824
|
-
integrations: {
|
|
825
|
-
...settings.integrations,
|
|
826
|
-
webhookEndpoints: settings.integrations.webhookEndpoints.map(w => w.id === webhookId ? { ...w, enabled: !w.enabled } : w),
|
|
827
|
-
},
|
|
828
|
-
},
|
|
829
|
-
isDirty: true,
|
|
830
|
-
});
|
|
831
|
-
},
|
|
832
|
-
createBackup: async (name) => {
|
|
833
|
-
const { settings } = get();
|
|
834
|
-
if (!settings)
|
|
835
|
-
return;
|
|
836
|
-
const result = await getAgentPlatformBridge()?.exportBackup?.createBackup?.(name);
|
|
837
|
-
if (result?.success && result.backup) {
|
|
838
|
-
const backup = result.backup;
|
|
839
|
-
const newBackup = {
|
|
840
|
-
id: backup.id || `backup_${Date.now()}`,
|
|
841
|
-
name: backup.name || name || 'Backup',
|
|
842
|
-
size: formatBytes(backup.size || 0),
|
|
843
|
-
createdAt: backup.createdAt || new Date().toISOString(),
|
|
844
|
-
type: 'manual',
|
|
845
|
-
};
|
|
846
|
-
set({
|
|
847
|
-
settings: {
|
|
848
|
-
...settings,
|
|
849
|
-
exportBackup: {
|
|
850
|
-
...settings.exportBackup,
|
|
851
|
-
availableBackups: [newBackup, ...settings.exportBackup.availableBackups],
|
|
852
|
-
},
|
|
853
|
-
},
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
},
|
|
857
|
-
deleteBackup: async (backupId) => {
|
|
858
|
-
const { settings } = get();
|
|
859
|
-
if (!settings)
|
|
860
|
-
return;
|
|
861
|
-
await getAgentPlatformBridge()?.exportBackup?.deleteBackup?.(backupId);
|
|
862
|
-
set({
|
|
863
|
-
settings: {
|
|
864
|
-
...settings,
|
|
865
|
-
exportBackup: {
|
|
866
|
-
...settings.exportBackup,
|
|
867
|
-
availableBackups: settings.exportBackup.availableBackups.filter(b => b.id !== backupId),
|
|
868
|
-
},
|
|
869
|
-
},
|
|
870
|
-
});
|
|
728
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, integrations: 'Webhook delivery is not connected on this surface. Delivery status was not changed.' } }));
|
|
871
729
|
},
|
|
872
|
-
|
|
873
|
-
const
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
ws.archiveWorkspace(settings.entityId);
|
|
730
|
+
createBackup: (name) => runBackupOperation(async (api, settings) => {
|
|
731
|
+
const result = await api.createBackup({ ...backupScope(settings), name });
|
|
732
|
+
requireSuccess(result, 'Backup creation');
|
|
733
|
+
const backup = result.backup;
|
|
734
|
+
if (!backup?.id || !backup.createdAt || typeof backup.size !== 'number') {
|
|
735
|
+
throw new Error('The host did not return a valid created backup.');
|
|
879
736
|
}
|
|
880
|
-
|
|
737
|
+
return { availableBackups: [{
|
|
738
|
+
id: backup.id, name: backup.name || name, size: formatBytes(backup.size),
|
|
739
|
+
createdAt: backup.createdAt, type: 'manual',
|
|
740
|
+
}, ...settings.exportBackup.availableBackups] };
|
|
741
|
+
}),
|
|
742
|
+
deleteBackup: (id) => runBackupOperation(async (api, settings) => {
|
|
743
|
+
const result = await api.deleteBackup({ ...backupScope(settings), id });
|
|
744
|
+
requireSuccess(result, 'Backup deletion');
|
|
745
|
+
return { availableBackups: settings.exportBackup.availableBackups.filter(backup => backup.id !== id) };
|
|
746
|
+
}),
|
|
747
|
+
downloadBackup: (id) => runBackupOperation(async (api, settings) => {
|
|
748
|
+
requireSuccess(await api.downloadBackup({ ...backupScope(settings), id }), 'Backup download');
|
|
749
|
+
}),
|
|
750
|
+
restoreBackup: (id) => runBackupOperation(async (api, settings) => {
|
|
751
|
+
const result = await api.importBackup({ ...backupScope(settings), id });
|
|
752
|
+
requireSuccess(result, 'Backup restore');
|
|
753
|
+
set({ backupRestoreResult: result.restoredConversations ?? [] });
|
|
754
|
+
await useWorkspaceStore.getState().loadWorkspaces();
|
|
755
|
+
await loadLocalAgentConversations();
|
|
756
|
+
}),
|
|
757
|
+
exportData: (format) => runBackupOperation(async (api, settings) => {
|
|
758
|
+
requireSuccess(await (format === 'json' ? api.exportJson(backupScope(settings)) : api.exportCsv(backupScope(settings))), 'Workspace export');
|
|
759
|
+
}),
|
|
760
|
+
archiveEntity: () => applyEntityLifecycle('archive'),
|
|
881
761
|
transferOwnership: (newOwnerId) => {
|
|
882
|
-
|
|
883
|
-
if (!settings)
|
|
884
|
-
return;
|
|
885
|
-
const newOwner = settings.access.members.find(m => m.id === newOwnerId);
|
|
886
|
-
if (!newOwner)
|
|
887
|
-
return;
|
|
888
|
-
set({
|
|
889
|
-
settings: {
|
|
890
|
-
...settings,
|
|
891
|
-
access: {
|
|
892
|
-
...settings.access,
|
|
893
|
-
owner: { ...newOwner, role: 'owner' },
|
|
894
|
-
members: settings.access.members.map(m => m.id === newOwnerId ? { ...m, role: 'owner' } : m.id === settings.access.owner.id ? { ...m, role: 'admin' } : m),
|
|
895
|
-
},
|
|
896
|
-
},
|
|
897
|
-
isDirty: true,
|
|
898
|
-
});
|
|
762
|
+
set(state => ({ sectionErrors: { ...state.sectionErrors, access: 'Ownership transfer requires a connected workspace membership authority. Ownership was not changed.' } }));
|
|
899
763
|
},
|
|
900
|
-
deleteEntity: () =>
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
764
|
+
deleteEntity: () => applyEntityLifecycle('delete'),
|
|
765
|
+
}));
|
|
766
|
+
async function persistProfileFields(settings, identity, drafts, fields) {
|
|
767
|
+
const sent = { ...fields };
|
|
768
|
+
const draft = drafts.get(identity);
|
|
769
|
+
if (!draft)
|
|
770
|
+
return false;
|
|
771
|
+
draft.submitted = { ...draft.submitted, ...sent };
|
|
772
|
+
const workspace = useWorkspaceStore.getState();
|
|
773
|
+
if (settings.entityType === 'workspace')
|
|
774
|
+
workspace.updateWorkspace(settings.entityId, sent);
|
|
775
|
+
else if (settings.entityType === 'team' && settings.workspaceId)
|
|
776
|
+
workspace.updateTeam(settings.workspaceId, settings.entityId, sent);
|
|
777
|
+
else if (settings.entityType === 'agent' && settings.workspaceId && settings.teamId)
|
|
778
|
+
workspace.updateAgent(settings.workspaceId, settings.teamId, settings.entityId, sent);
|
|
779
|
+
else
|
|
780
|
+
return false;
|
|
781
|
+
try {
|
|
782
|
+
await requireWorkspacePersistence(workspaces => {
|
|
783
|
+
const current = projectHierarchySettings(settings, workspaces);
|
|
784
|
+
return current?.identity === identity && Object.entries(sent).every(([key, value]) => current.general[key] === value);
|
|
785
|
+
});
|
|
786
|
+
const currentDraft = drafts.get(identity);
|
|
787
|
+
if (currentDraft) {
|
|
788
|
+
for (const key of Object.keys(sent)) {
|
|
789
|
+
if (currentDraft.fields[key] === sent[key])
|
|
790
|
+
delete currentDraft.fields[key];
|
|
791
|
+
if (currentDraft.submitted[key] === sent[key])
|
|
792
|
+
delete currentDraft.submitted[key];
|
|
793
|
+
}
|
|
794
|
+
if (!Object.keys(currentDraft.fields).length)
|
|
795
|
+
drafts.delete(identity);
|
|
907
796
|
}
|
|
908
|
-
|
|
909
|
-
|
|
797
|
+
if (selectedHierarchyBaseline?.identity === identity) {
|
|
798
|
+
const remaining = drafts.get(identity);
|
|
799
|
+
useEntitySettingsStore.setState({ profileDraftPending: Boolean(remaining), profileDraftError: remaining && useEntitySettingsStore.getState().settings ? validateProfileDraft(useEntitySettingsStore.getState().settings.general) : undefined });
|
|
910
800
|
}
|
|
911
|
-
|
|
912
|
-
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
catch (error) {
|
|
804
|
+
if (selectedHierarchyBaseline?.identity === identity && drafts.has(identity))
|
|
805
|
+
useEntitySettingsStore.setState({ profileDraftError: error instanceof Error ? error.message : 'Profile save was not acknowledged.' });
|
|
806
|
+
return false;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
let hierarchyRefreshGeneration = 0;
|
|
810
|
+
useWorkspaceStore.subscribe((next, previous) => {
|
|
811
|
+
if (next.workspaces === previous.workspaces && next.persistenceStatus === previous.persistenceStatus)
|
|
812
|
+
return;
|
|
813
|
+
const refresh = ++hierarchyRefreshGeneration;
|
|
814
|
+
const loadGeneration = useEntitySettingsStore.getState().loadGeneration;
|
|
815
|
+
if (!selectedHierarchyBaseline && !currentProfileDrafts().size)
|
|
816
|
+
return;
|
|
817
|
+
// Workspace mutations enqueue persistence inside Zustand updates. Start after
|
|
818
|
+
// that enqueue, then inspect the host ACK rather than accepting optimistic data.
|
|
819
|
+
queueMicrotask(() => { void reconcileAcknowledgedHierarchy(refresh, loadGeneration); });
|
|
820
|
+
});
|
|
821
|
+
async function reconcileAcknowledgedHierarchy(refresh, loadGeneration) {
|
|
822
|
+
let acknowledged;
|
|
823
|
+
try {
|
|
824
|
+
await requireWorkspacePersistence(workspaces => {
|
|
825
|
+
// The persistence guard checks acknowledged state first, then optimistic
|
|
826
|
+
// state. Capture only the former; a pending/conflicted edit is not authority.
|
|
827
|
+
acknowledged ??= workspaces;
|
|
828
|
+
return true;
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
catch {
|
|
832
|
+
return;
|
|
833
|
+
} // WorkspaceStore retains the actionable persistence error.
|
|
834
|
+
if (refresh === hierarchyRefreshGeneration && acknowledged) {
|
|
835
|
+
for (const identity of currentProfileDrafts().keys()) {
|
|
836
|
+
if (!profileIdentityExists(identity, acknowledged))
|
|
837
|
+
currentProfileDrafts().delete(identity);
|
|
913
838
|
}
|
|
914
|
-
}
|
|
915
|
-
|
|
839
|
+
}
|
|
840
|
+
const state = useEntitySettingsStore.getState();
|
|
841
|
+
const baseline = selectedHierarchyBaseline;
|
|
842
|
+
if (refresh !== hierarchyRefreshGeneration || loadGeneration !== state.loadGeneration || !state.settings || !baseline || !acknowledged)
|
|
843
|
+
return;
|
|
844
|
+
const incoming = projectHierarchySettings(state.settings, acknowledged);
|
|
845
|
+
if (!incoming || incoming.identity !== baseline.identity) {
|
|
846
|
+
currentProfileDrafts().delete(baseline.identity);
|
|
847
|
+
state.clearSettings();
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
if (JSON.stringify(incoming) === JSON.stringify(baseline))
|
|
851
|
+
return;
|
|
852
|
+
selectedHierarchyBaseline = incoming;
|
|
853
|
+
useEntitySettingsStore.setState({ settings: {
|
|
854
|
+
...state.settings,
|
|
855
|
+
entityName: incoming.entityName, workspaceName: incoming.workspaceName,
|
|
856
|
+
...(incoming.teamName !== undefined ? { teamName: incoming.teamName } : {}),
|
|
857
|
+
general: mergeAcknowledgedFields(state.settings.general, baseline.general, incoming.general),
|
|
858
|
+
...(state.settings.defaultAgentConfig && baseline.defaultAgentConfig && incoming.defaultAgentConfig ? {
|
|
859
|
+
defaultAgentConfig: mergeAcknowledgedFields(state.settings.defaultAgentConfig, baseline.defaultAgentConfig, incoming.defaultAgentConfig),
|
|
860
|
+
} : {}),
|
|
861
|
+
} });
|
|
862
|
+
}
|
|
863
|
+
async function applyEntityLifecycle(action) {
|
|
864
|
+
const initial = useEntitySettingsStore.getState();
|
|
865
|
+
const settings = initial.settings;
|
|
866
|
+
if (!settings || initial.sectionLoading.dangerZone)
|
|
867
|
+
return false;
|
|
868
|
+
const generation = initial.loadGeneration;
|
|
869
|
+
const current = () => useEntitySettingsStore.getState().loadGeneration === generation;
|
|
870
|
+
useEntitySettingsStore.setState(state => ({ sectionLoading: { ...state.sectionLoading, dangerZone: true }, sectionErrors: { ...state.sectionErrors, dangerZone: undefined } }));
|
|
871
|
+
try {
|
|
872
|
+
const scope = { workspaceId: settings.entityType === 'workspace' ? settings.entityId : settings.workspaceId,
|
|
873
|
+
...(settings.entityType === 'team' ? { teamId: settings.entityId } : settings.teamId ? { teamId: settings.teamId } : {}),
|
|
874
|
+
...(settings.entityType === 'agent' ? { agentId: settings.entityId } : {}) };
|
|
875
|
+
if (!await requestWorkspaceLifecycle(scope, action))
|
|
876
|
+
throw new Error(useWorkspaceStore.getState().lifecycleError || 'Lifecycle was not confirmed');
|
|
877
|
+
return current();
|
|
878
|
+
}
|
|
879
|
+
catch (error) {
|
|
880
|
+
if (current())
|
|
881
|
+
useEntitySettingsStore.setState(state => ({ sectionErrors: { ...state.sectionErrors, dangerZone: settingsError(error) } }));
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
finally {
|
|
885
|
+
if (current())
|
|
886
|
+
useEntitySettingsStore.setState(state => ({ sectionLoading: { ...state.sectionLoading, dangerZone: false } }));
|
|
887
|
+
}
|
|
888
|
+
}
|
|
916
889
|
//# sourceMappingURL=entitySettingsStore.js.map
|