@taskforcehq/taskforce 0.3.328 → 0.3.330
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/Taskforce.module.css +523 -79
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AiProfilesModule.js +3 -5
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +217 -54
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
- package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +5 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +32 -55
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
- package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
- package/dist/config/envSchema.js +60 -1
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/McpTokenService.d.ts +23 -1
- package/dist/core/McpTokenService.js +93 -10
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/TaskChecklistCommandService.d.ts +27 -0
- package/dist/core/TaskChecklistCommandService.js +83 -5
- package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
- package/dist/core/TaskLifecycleCommandService.js +6 -2
- package/dist/core/Taskforce.d.ts +94 -2
- package/dist/core/Taskforce.js +760 -36
- package/dist/core/types.d.ts +14 -0
- package/dist/documentReviews/commandService.d.ts +2 -1
- package/dist/documentReviews/commandService.js +6 -3
- package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.js +2 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
- package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
- package/dist/hooks/sync/useSyncStatusControls.js +47 -11
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +40 -1
- package/dist/hooks/useTaskData.js +240 -9
- package/dist/hooks/useTaskMutations.d.ts +12 -2
- package/dist/hooks/useTaskMutations.js +266 -52
- package/dist/hooks/useTaskforce.d.ts +39 -9
- package/dist/hooks/useTaskforce.js +359 -40
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +53 -41
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
- package/dist/mcp/durableTaskMutationRouter.js +10 -0
- package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
- package/dist/mcp/httpProtocolRouting.d.ts +10 -0
- package/dist/mcp/httpProtocolRouting.js +19 -0
- package/dist/mcp/localCliHealth.d.ts +2 -2
- package/dist/mcp/localCliHealth.js +2 -2
- package/dist/mcp/localServiceProxy.d.ts +1 -0
- package/dist/mcp/localServiceProxy.js +530 -68
- package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
- package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
- package/dist/mcp/runtime.d.ts +54 -79
- package/dist/mcp/runtime.js +556 -139
- package/dist/mcp/taskPlanningRegistrar.js +64 -42
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +10 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +1 -0
- package/dist/mcp/workflowExecutionRegistrar.js +4 -4
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +427 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +13 -13
- package/dist/runtime/appGates.js +36 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.js +123 -14
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +11 -2
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +113 -3
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +394 -39
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
- package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
- package/dist/server/routes/executorPhaseAApprovals.js +140 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
- package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
- package/dist/server/routes/githubReviewEvidence.js +116 -0
- package/dist/server/routes/localService.d.ts +15 -4
- package/dist/server/routes/localService.js +138 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/shared.d.ts +19 -0
- package/dist/server/routes/shared.js +95 -19
- package/dist/server/routes/sync.js +1 -0
- package/dist/server/routes/syncAuxRoutes.js +9 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +27 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +45 -9
- package/dist/server/routes/tasks.js +124 -13
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/routes.js +59 -0
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +161 -0
- package/dist/services/codexAppServerModelGateway.js +663 -0
- package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
- package/dist/services/codexDeviceCodeLoginManager.js +265 -0
- package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
- package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
- package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
- package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
- package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
- package/dist/services/executorPhaseAApprovalService.js +609 -0
- package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
- package/dist/services/executorPhaseADriftEvaluator.js +93 -0
- package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
- package/dist/services/executorPhaseAIssuerCore.js +295 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
- package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
- package/dist/services/githubReviewEvidenceRuntime.js +30 -0
- package/dist/services/githubReviewEvidenceService.d.ts +93 -0
- package/dist/services/githubReviewEvidenceService.js +336 -0
- package/dist/services/modelGateway.d.ts +7 -0
- package/dist/services/modelProviderConnectionService.d.ts +71 -0
- package/dist/services/modelProviderConnectionService.js +279 -0
- package/dist/services/modelProviderCredentialHome.d.ts +32 -0
- package/dist/services/modelProviderCredentialHome.js +271 -0
- package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
- package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
- package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
- package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
- package/dist/services/taskforceAgentMcpBridge.js +30 -27
- package/dist/shared/adminEdgeProxy.d.ts +5 -0
- package/dist/shared/adminEdgeProxy.js +94 -0
- package/dist/shared/adminProxySessionCookies.d.ts +16 -0
- package/dist/shared/adminProxySessionCookies.js +86 -0
- package/dist/shared/aiProfileColors.d.ts +31 -1
- package/dist/shared/aiProfileColors.js +14 -6
- package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
- package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
- package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
- package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
- package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
- package/dist/shared/executorPhaseADriftContracts.js +63 -0
- package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
- package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
- package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
- package/dist/shared/executorPhaseARunAuthorization.js +232 -0
- package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
- package/dist/shared/executorPhaseASchemaValidation.js +53 -0
- package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
- package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
- package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
- package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
- package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
- package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
- package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
- package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
- package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
- package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
- package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
- package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
- package/dist/shared/executorPhaseATiming.d.ts +1 -0
- package/dist/shared/executorPhaseATiming.js +1 -0
- package/dist/shared/planningIdentity.js +1 -1
- package/dist/shared/productLogoKeys.d.ts +2 -0
- package/dist/shared/productLogoKeys.js +18 -0
- package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
- package/dist/shared/taskforceAgentDefinition.js +6 -3
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +36 -3
- package/dist/shared/userFeatureGrants.d.ts +4 -0
- package/dist/shared/userFeatureGrants.js +7 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
- package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
- package/dist/storage/modelProviderConnectionStore.js +446 -0
- package/dist/storage/postgresAdapter.d.ts +24 -3
- package/dist/storage/postgresAdapter.js +117 -14
- package/dist/storage/postgresWorker.js +22 -5
- package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
- package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
- package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
- package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
- package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
- package/dist/sync/syncApplyHandlers.d.ts +2 -0
- package/dist/sync/syncApplyHandlers.js +10 -1
- package/dist/sync/syncService.d.ts +17 -0
- package/dist/sync/syncService.js +87 -19
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +8 -0
- package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
- package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
- package/dist/sync/v3/durableOperationReplay.js +18 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
- package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
- package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
- package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
- package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
- package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
- package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
- package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
- package/dist/sync/v3/syncDurabilityStore.js +199 -13
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
- package/dist/sync/v3/taskChecklistMutationService.js +48 -1
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
- package/dist/sync/v3/taskStatusMutationService.js +123 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
- package/dist/sync/v3/workflowAssignmentSync.js +30 -0
- package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
- package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
- package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +8 -2
- package/dist/sync/workspaceRepair.js +222 -6
- package/dist/sync/workspaceSyncModel.d.ts +21 -0
- package/dist/sync/workspaceSyncModel.js +35 -7
- package/dist/sync/workspaceSyncState.d.ts +1 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
- package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
- package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
- package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
- package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
- package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-CTsDBaef.js +7 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
- package/dist/ui/branding/logos/letterhead_dark.png +0 -0
- package/dist/ui/branding/logos/letterhead_light.png +0 -0
- package/dist/ui/branding/logos/signature_dark.png +0 -0
- package/dist/ui/branding/logos/signature_light.png +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/aiProfileDefaultLogo.js +16 -48
- package/dist/utils/httpSetCookie.d.ts +1 -0
- package/dist/utils/httpSetCookie.js +4 -1
- package/dist/utils/localRuntimeUrl.d.ts +1 -0
- package/dist/utils/localRuntimeUrl.js +14 -0
- package/dist/utils/productLogoRegistry.d.ts +2 -0
- package/dist/utils/productLogoRegistry.js +36 -0
- package/dist/utils/syncStatusPresentation.d.ts +4 -0
- package/dist/utils/syncStatusPresentation.js +17 -0
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskEvents.d.ts +2 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +36 -6
- package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { AlertTriangle, Beaker, Bot, BriefcaseBusiness, CheckCircle, ChevronLeft, Database, ExternalLink, Loader2,
|
|
3
|
+
import { AlertTriangle, Beaker, Bot, BriefcaseBusiness, Check, CheckCircle, ChevronLeft, Copy, Database, ExternalLink, Loader2, Pencil, Plug, Plus, RotateCcw, Save, Send, Sparkles, X } from 'lucide-react';
|
|
4
4
|
import styles from '../../Taskforce.module.css';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { DEFAULT_TASKFORCE_AGENT_MODEL_KEY, DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY, TASKFORCE_AGENT_PROVIDER_OPTIONS, labelForTaskforceAgentModel, labelForTaskforceAgentProvider, modelsForTaskforceAgentProvider, normalizeTaskforceAgentModelKey, normalizeTaskforceAgentProviderKey, } from '../../shared/taskforceAgentModels';
|
|
5
|
+
import { AI_PROFILE_SIGNATURE_COLOR_OPTIONS, assignedAiProfileColor } from '../../shared/aiProfileColors.js';
|
|
6
|
+
import { DEFAULT_TASKFORCE_AGENT_MODEL_KEY, DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY, TASKFORCE_AGENT_MODEL_OPTIONS, TASKFORCE_AGENT_PROVIDER_OPTIONS, isTaskforceAgentModelVisible, labelForTaskforceAgentModel, labelForTaskforceAgentProvider, normalizeTaskforceAgentProviderKey, } from '../../shared/taskforceAgentModels';
|
|
8
7
|
import { dispatchTaskforceAgentsMutated, TASKFORCE_AGENTS_MUTATED_EVENT } from '../../utils/taskforceAgentEvents';
|
|
9
8
|
import { dispatchTaskforceTasksMutated } from '../../utils/taskEvents';
|
|
10
9
|
import { buildVersionedAvatarUrl } from '../../utils/avatarDisplay';
|
|
@@ -23,10 +22,48 @@ import { AVATAR_ART_STYLE_PRESETS, buildTaskforceAgentDefinitionFromDraft, creat
|
|
|
23
22
|
import { SkillManagerPanel } from './agentSkills/SkillManagerPanel.js';
|
|
24
23
|
import { EffectiveConfigurationSummary, FutureLibrarySummary, FutureWorkspacePanel, ToolAccessSelector, } from './agentCapabilities/AgentCapabilitiesPrototype.js';
|
|
25
24
|
import { applyCloudWorkflowCompletionProjection, } from './workflowManager/workflowManagerApi.js';
|
|
25
|
+
import { ModelConnectionsPanel } from './agentConnections/ModelConnectionsPanel.js';
|
|
26
|
+
import { bindAgentConnection, clearAgentConnectionBinding, inspectAgentConnectionBinding, listModelConnections, ModelConnectionsApiError, } from './agentConnections/modelConnectionsApi.js';
|
|
26
27
|
const DEFAULT_SYSTEM_PROMPT = 'Be concise and actionable.';
|
|
27
28
|
const DEFAULT_AGENT_NAME = 'New Taskforce Agent';
|
|
28
29
|
const TEST_PROMPT_PLACEHOLDER = 'Message this agent...';
|
|
29
30
|
const AGENT_ROSTER_REFRESH_INTERVAL_MS = 10_000;
|
|
31
|
+
const AGENT_MODEL_SOURCE_OPTIONS = [
|
|
32
|
+
{ key: 'taskforce_managed', label: 'Taskforce Managed' },
|
|
33
|
+
];
|
|
34
|
+
const CONNECTION_SOURCE_PREFIX = 'connection:';
|
|
35
|
+
const LOCAL_AGENT_BINDING_SYNC_RETRIES = 20;
|
|
36
|
+
const LOCAL_AGENT_BINDING_SYNC_DELAY_MS = 250;
|
|
37
|
+
async function bindAgentConnectionAfterLocalSync(agentId, connectionId, context, waitForCloudSync) {
|
|
38
|
+
for (let attempt = 0;; attempt += 1) {
|
|
39
|
+
try {
|
|
40
|
+
return await bindAgentConnection(agentId, connectionId, context);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const retryable = waitForCloudSync
|
|
44
|
+
&& error instanceof ModelConnectionsApiError
|
|
45
|
+
&& error.code === 'TASKFORCE_AGENT_NOT_FOUND'
|
|
46
|
+
&& attempt < LOCAL_AGENT_BINDING_SYNC_RETRIES;
|
|
47
|
+
if (!retryable)
|
|
48
|
+
throw error;
|
|
49
|
+
await new Promise((resolve) => window.setTimeout(resolve, LOCAL_AGENT_BINDING_SYNC_DELAY_MS));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function modelConnectionDisplayName(connection) {
|
|
54
|
+
return String(connection.displayMetadata.displayName
|
|
55
|
+
|| connection.displayMetadata.accountLabel
|
|
56
|
+
|| connection.displayMetadata.accountEmail
|
|
57
|
+
|| 'ChatGPT subscription');
|
|
58
|
+
}
|
|
59
|
+
function modelSourceGroupForOption(model) {
|
|
60
|
+
return model?.source === 'personal_byom' || model?.source === 'subscription_dev'
|
|
61
|
+
? 'personal_connection'
|
|
62
|
+
: 'taskforce_managed';
|
|
63
|
+
}
|
|
64
|
+
function modelMatchesSourceGroup(model, sourceGroup) {
|
|
65
|
+
return modelSourceGroupForOption(model) === sourceGroup;
|
|
66
|
+
}
|
|
30
67
|
const AGENT_BUILDER_TABS = [
|
|
31
68
|
{ id: 'agents', label: 'Agents' },
|
|
32
69
|
{ id: 'roles', label: 'Roles' },
|
|
@@ -100,17 +137,18 @@ function formatModelAvailability(availability) {
|
|
|
100
137
|
return 'Unavailable';
|
|
101
138
|
}
|
|
102
139
|
const SENSITIVE_TOOL_ARG_PATTERN = /(token|secret|password|credential|api[-_]?key|access[-_]?key)/i;
|
|
103
|
-
|
|
140
|
+
const MAX_COPIED_TOOL_RESULT_CHARS = 20_000;
|
|
141
|
+
function sanitizeToolLogValue(value, truncateStrings = true) {
|
|
104
142
|
if (Array.isArray(value))
|
|
105
|
-
return value.map((item) => sanitizeToolLogValue(item));
|
|
143
|
+
return value.map((item) => sanitizeToolLogValue(item, truncateStrings));
|
|
106
144
|
if (!value || typeof value !== 'object') {
|
|
107
145
|
if (typeof value !== 'string')
|
|
108
146
|
return value;
|
|
109
|
-
return value.length > 240 ? `${value.slice(0, 237).trim()}...` : value;
|
|
147
|
+
return truncateStrings && value.length > 240 ? `${value.slice(0, 237).trim()}...` : value;
|
|
110
148
|
}
|
|
111
149
|
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
|
|
112
150
|
key,
|
|
113
|
-
SENSITIVE_TOOL_ARG_PATTERN.test(key) ? '[redacted]' : sanitizeToolLogValue(entry),
|
|
151
|
+
SENSITIVE_TOOL_ARG_PATTERN.test(key) ? '[redacted]' : sanitizeToolLogValue(entry, truncateStrings),
|
|
114
152
|
]));
|
|
115
153
|
}
|
|
116
154
|
function formatToolLogJson(value) {
|
|
@@ -124,6 +162,20 @@ function formatToolLogResult(value) {
|
|
|
124
162
|
return 'No result text returned.';
|
|
125
163
|
return text.length > 320 ? `${text.slice(0, 317).trim()}...` : text;
|
|
126
164
|
}
|
|
165
|
+
function formatToolActivityClipboard(toolCall) {
|
|
166
|
+
const rawResult = String(toolCall.resultText || 'No result text returned.');
|
|
167
|
+
const result = rawResult.length > MAX_COPIED_TOOL_RESULT_CHARS
|
|
168
|
+
? `${rawResult.slice(0, MAX_COPIED_TOOL_RESULT_CHARS)}\n[Result truncated after ${MAX_COPIED_TOOL_RESULT_CHARS.toLocaleString()} characters]`
|
|
169
|
+
: rawResult;
|
|
170
|
+
return [
|
|
171
|
+
`Tool: ${toolCall.name}`,
|
|
172
|
+
`Status: ${toolCall.ok ? 'ok' : 'failed'}`,
|
|
173
|
+
'Arguments',
|
|
174
|
+
JSON.stringify(sanitizeToolLogValue(toolCall.arguments || {}, false), null, 2),
|
|
175
|
+
'Result',
|
|
176
|
+
result,
|
|
177
|
+
].join('\n');
|
|
178
|
+
}
|
|
127
179
|
function formatToolActivitySummary(toolActivity) {
|
|
128
180
|
const count = toolActivity.length;
|
|
129
181
|
if (count === 0)
|
|
@@ -210,7 +262,7 @@ function formatConversationOption(summary, fallbackContext = null) {
|
|
|
210
262
|
const label = count > 0 ? `${title} (${count})` : title;
|
|
211
263
|
return taskContext ? `${formatTaskContextLabel(taskContext)} · ${label}` : label;
|
|
212
264
|
}
|
|
213
|
-
export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true, onCloseAgentRosterTray, launchContext = null, onClearLaunchContext, onOpenTaskContext, taskReferences, surface = 'module', runtimeMode = 'local', cloudAuthConfigured = false, authSessionResolved = true, isAuthenticated = false, resolveCloudAuthUrl, theme = 'dark', rememberedAgentId, rememberedConversationId, rememberedConversationByAgentId, rememberedSelectionReady = true, onRememberSelection, onRenderDrawerHeader,
|
|
265
|
+
export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true, onCloseAgentRosterTray, launchContext = null, onClearLaunchContext, onOpenTaskContext, taskReferences, surface = 'module', runtimeMode = 'local', cloudAuthConfigured = false, authSessionResolved = true, isAuthenticated = false, resolveCloudAuthUrl, theme = 'dark', rememberedAgentId, rememberedConversationId, rememberedConversationByAgentId, rememberedSelectionReady = true, onRememberSelection, onRenderDrawerHeader, }) {
|
|
214
266
|
const logIdRef = useRef(1);
|
|
215
267
|
const initialAgentWorkspaceRef = useRef(null);
|
|
216
268
|
const loadedAgentWorkspaceRef = useRef(null);
|
|
@@ -220,6 +272,18 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
220
272
|
const conversationEndRef = useRef(null);
|
|
221
273
|
const conversationRenameRunIdRef = useRef(0);
|
|
222
274
|
const draftTestRunIdRef = useRef(0);
|
|
275
|
+
const conversationHistoryRunIdRef = useRef(0);
|
|
276
|
+
const conversationMutationRevisionRef = useRef(0);
|
|
277
|
+
const conversationCreateRunIdRef = useRef(0);
|
|
278
|
+
const conversationCreateScope = [
|
|
279
|
+
workspaceId,
|
|
280
|
+
String(launchContext?.taskId || ''),
|
|
281
|
+
String(launchContext?.taskReference || ''),
|
|
282
|
+
String(launchContext?.taskTitle || ''),
|
|
283
|
+
].join('\n');
|
|
284
|
+
const conversationCreateScopeRef = useRef(conversationCreateScope);
|
|
285
|
+
conversationCreateScopeRef.current = conversationCreateScope;
|
|
286
|
+
const conversationHistoryLoadRef = useRef(null);
|
|
223
287
|
const builderTabRefs = useRef({
|
|
224
288
|
agents: null,
|
|
225
289
|
roles: null,
|
|
@@ -228,12 +292,26 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
228
292
|
resources: null,
|
|
229
293
|
});
|
|
230
294
|
const [activeBuilderTab, setActiveBuilderTab] = useState('agents');
|
|
295
|
+
const activateBuilderTab = useCallback((tab, focus = false) => {
|
|
296
|
+
setActiveBuilderTab(tab);
|
|
297
|
+
if (focus)
|
|
298
|
+
window.setTimeout(() => builderTabRefs.current[tab]?.focus(), 0);
|
|
299
|
+
}, []);
|
|
300
|
+
const [connectionRefreshKey, setConnectionRefreshKey] = useState(0);
|
|
231
301
|
const [roleLibraryPortalTarget, setRoleLibraryPortalTarget] = useState(null);
|
|
232
302
|
const [skillLibraryPortalTarget, setSkillLibraryPortalTarget] = useState(null);
|
|
303
|
+
const [connectionLibraryPortalTarget, setConnectionLibraryPortalTarget] = useState(null);
|
|
233
304
|
const [agents, setAgents] = useState([]);
|
|
305
|
+
const [availableModelOptions, setAvailableModelOptions] = useState(() => (runtimeMode === 'local'
|
|
306
|
+
? TASKFORCE_AGENT_MODEL_OPTIONS.filter(isTaskforceAgentModelVisible)
|
|
307
|
+
: []));
|
|
234
308
|
const [selectedAgentId, setSelectedAgentId] = useState(null);
|
|
235
309
|
const [agentName, setAgentName] = useState('');
|
|
236
310
|
const [modelProvider, setModelProvider] = useState('taskforce_hq');
|
|
311
|
+
const [modelSourceGroup, setModelSourceGroup] = useState('taskforce_managed');
|
|
312
|
+
const [modelConnections, setModelConnections] = useState([]);
|
|
313
|
+
const [selectedConnectionId, setSelectedConnectionId] = useState('');
|
|
314
|
+
const [agentConnectionBinding, setAgentConnectionBinding] = useState(null);
|
|
237
315
|
const [providerKey, setProviderKey] = useState(DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY);
|
|
238
316
|
const [modelKey, setModelKey] = useState(DEFAULT_TASKFORCE_AGENT_MODEL_KEY);
|
|
239
317
|
const [modelTier, setModelTier] = useState('balanced');
|
|
@@ -248,7 +326,6 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
248
326
|
}, []);
|
|
249
327
|
const [signatureColor, setSignatureColor] = useState('');
|
|
250
328
|
const [signatureColorDirty, setSignatureColorDirty] = useState(false);
|
|
251
|
-
const [signatureColorReset, setSignatureColorReset] = useState(false);
|
|
252
329
|
const [prompt, setPrompt] = useState('');
|
|
253
330
|
const [conversationId, setConversationId] = useState(null);
|
|
254
331
|
const [conversationSummaries, setConversationSummaries] = useState([]);
|
|
@@ -259,6 +336,7 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
259
336
|
const [savingConversationTitle, setSavingConversationTitle] = useState(false);
|
|
260
337
|
const [result, setResult] = useState(null);
|
|
261
338
|
const [toolActivity, setToolActivity] = useState([]);
|
|
339
|
+
const [toolCopyStatus, setToolCopyStatus] = useState(null);
|
|
262
340
|
const [promptStatus, setPromptStatus] = useState('');
|
|
263
341
|
const [logs, setLogs] = useState(() => [
|
|
264
342
|
{
|
|
@@ -275,7 +353,11 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
275
353
|
const [draftTestToolActivity, setDraftTestToolActivity] = useState([]);
|
|
276
354
|
const [draftTestError, setDraftTestError] = useState('');
|
|
277
355
|
const [testingDraft, setTestingDraft] = useState(false);
|
|
356
|
+
const [testPanelOpen, setTestPanelOpen] = useState(false);
|
|
278
357
|
const [loadingAgents, setLoadingAgents] = useState(false);
|
|
358
|
+
const [modelCatalogError, setModelCatalogError] = useState('');
|
|
359
|
+
const [modelCatalogRefreshKey, setModelCatalogRefreshKey] = useState(0);
|
|
360
|
+
const cloudModelCatalogActiveRef = useRef(false);
|
|
279
361
|
const [loadingConversationList, setLoadingConversationList] = useState(false);
|
|
280
362
|
const [loadingConversation, setLoadingConversation] = useState(false);
|
|
281
363
|
const [savingAgent, setSavingAgent] = useState(false);
|
|
@@ -290,9 +372,66 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
290
372
|
const [agentProfileTrayOpen, setAgentProfileTrayOpen] = useState(false);
|
|
291
373
|
const [avatarSyncingAgentIds, setAvatarSyncingAgentIds] = useState(() => new Set());
|
|
292
374
|
const pendingCloudAvatarRevisionByAgentIdRef = useRef(new Map());
|
|
293
|
-
const
|
|
294
|
-
const
|
|
375
|
+
const bindingMutationAgentIdRef = useRef(null);
|
|
376
|
+
const bindingInspectionGenerationRef = useRef(0);
|
|
377
|
+
const configuredModelSourceOptions = useMemo(() => {
|
|
378
|
+
const options = AGENT_MODEL_SOURCE_OPTIONS
|
|
379
|
+
.filter((source) => availableModelOptions.some((model) => modelMatchesSourceGroup(model, source.key)))
|
|
380
|
+
.map((source) => ({ key: source.key, label: source.label }));
|
|
381
|
+
const activeConnections = modelConnections.filter((connection) => (connection.lifecycleStatus === 'active'
|
|
382
|
+
&& availableModelOptions.some((model) => (model.source === 'subscription_dev'
|
|
383
|
+
&& model.providerKey === connection.providerKey))));
|
|
384
|
+
for (const connection of activeConnections) {
|
|
385
|
+
options.push({
|
|
386
|
+
key: `${CONNECTION_SOURCE_PREFIX}${connection.id}`,
|
|
387
|
+
label: `${modelConnectionDisplayName(connection)} · ${labelForTaskforceAgentProvider(connection.providerKey)}`,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
if (modelSourceGroup === 'personal_connection' && selectedConnectionId
|
|
391
|
+
&& !activeConnections.some((connection) => connection.id === selectedConnectionId)) {
|
|
392
|
+
const unavailable = modelConnections.find((connection) => connection.id === selectedConnectionId);
|
|
393
|
+
options.push({
|
|
394
|
+
key: `${CONNECTION_SOURCE_PREFIX}${selectedConnectionId}`,
|
|
395
|
+
label: `${unavailable ? modelConnectionDisplayName(unavailable) : 'Connected account'} (unavailable)`,
|
|
396
|
+
disabled: true,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
else if (modelSourceGroup === 'personal_connection' && !selectedConnectionId) {
|
|
400
|
+
options.push({
|
|
401
|
+
key: agentConnectionBinding?.bound && agentConnectionBinding.ownerIsCaller === false
|
|
402
|
+
? 'connected-account-private'
|
|
403
|
+
: 'connected-account-unavailable',
|
|
404
|
+
label: agentConnectionBinding?.bound && agentConnectionBinding.ownerIsCaller === false
|
|
405
|
+
? 'Connected account managed by another user'
|
|
406
|
+
: 'Connected account unavailable',
|
|
407
|
+
disabled: true,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
return options;
|
|
411
|
+
}, [agentConnectionBinding?.bound, agentConnectionBinding?.ownerIsCaller, availableModelOptions, modelConnections, modelSourceGroup, selectedConnectionId]);
|
|
412
|
+
const modelSourceSelectionKey = modelSourceGroup === 'taskforce_managed'
|
|
413
|
+
? 'taskforce_managed'
|
|
414
|
+
: selectedConnectionId
|
|
415
|
+
? `${CONNECTION_SOURCE_PREFIX}${selectedConnectionId}`
|
|
416
|
+
: agentConnectionBinding?.bound && agentConnectionBinding.ownerIsCaller === false
|
|
417
|
+
? 'connected-account-private'
|
|
418
|
+
: 'connected-account-unavailable';
|
|
419
|
+
const selectedModelConnection = useMemo(() => modelConnections.find((connection) => connection.id === selectedConnectionId) || null, [modelConnections, selectedConnectionId]);
|
|
420
|
+
const sourceModelOptions = useMemo(() => availableModelOptions.filter((model) => (modelMatchesSourceGroup(model, modelSourceGroup)
|
|
421
|
+
&& (modelSourceGroup === 'taskforce_managed'
|
|
422
|
+
|| !selectedModelConnection
|
|
423
|
+
|| model.providerKey === selectedModelConnection.providerKey))), [availableModelOptions, modelSourceGroup, selectedModelConnection]);
|
|
424
|
+
const configuredProviderOptions = useMemo(() => TASKFORCE_AGENT_PROVIDER_OPTIONS.filter((provider) => (sourceModelOptions.some((model) => model.providerKey === provider.key)
|
|
425
|
+
|| provider.key === providerKey)), [providerKey, sourceModelOptions]);
|
|
426
|
+
const modelOptions = useMemo(() => sourceModelOptions.filter((model) => model.providerKey === providerKey), [providerKey, sourceModelOptions]);
|
|
427
|
+
const normalizeAvailableModelKey = useCallback((value, provider) => {
|
|
428
|
+
const normalizedProvider = normalizeTaskforceAgentProviderKey(provider);
|
|
429
|
+
const providerModels = availableModelOptions.filter((model) => model.providerKey === normalizedProvider);
|
|
430
|
+
const key = String(value || '').trim();
|
|
431
|
+
return key || providerModels[0]?.key || '';
|
|
432
|
+
}, [availableModelOptions]);
|
|
295
433
|
const selectedModel = useMemo(() => modelOptions.find((model) => model.key === modelKey) || null, [modelKey, modelOptions]);
|
|
434
|
+
const subscriptionConnectionsEligible = useMemo(() => (availableModelOptions.some((model) => model.source === 'subscription_dev')), [availableModelOptions]);
|
|
296
435
|
const selectedAgent = useMemo(() => agents.find((agent) => agent.id === selectedAgentId) || null, [agents, selectedAgentId]);
|
|
297
436
|
const normalizedRememberedAgentId = useMemo(() => String(rememberedAgentId || '').trim(), [rememberedAgentId]);
|
|
298
437
|
const normalizedRememberedConversationId = useMemo(() => String(rememberedConversationId || '').trim(), [rememberedConversationId]);
|
|
@@ -313,6 +452,11 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
313
452
|
const shouldUseCloudAgentRuntime = runtimeMode === 'local' && cloudAuthConfigured;
|
|
314
453
|
const canUseCloudAgentRuntime = !shouldUseCloudAgentRuntime
|
|
315
454
|
|| (authSessionResolved && isAuthenticated);
|
|
455
|
+
const modelConnectionCloudAccessAvailable = runtimeMode === 'cloud'
|
|
456
|
+
|| (cloudAuthConfigured && authSessionResolved && isAuthenticated && Boolean(resolveCloudAuthUrl));
|
|
457
|
+
const modelConnectionCloudAccessPending = runtimeMode === 'local'
|
|
458
|
+
&& cloudAuthConfigured
|
|
459
|
+
&& !authSessionResolved;
|
|
316
460
|
const selectedAgentAvatarUrl = useMemo(() => getAgentAvatarUrl(selectedAgent), [selectedAgent]);
|
|
317
461
|
const selectedAgentAvatarSourceUrl = useMemo(() => getAgentAvatarSourceUrl(selectedAgent), [selectedAgent]);
|
|
318
462
|
const isSelectedAgentAvatarSyncing = Boolean(selectedAgentId && avatarSyncingAgentIds.has(selectedAgentId));
|
|
@@ -388,21 +532,30 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
388
532
|
setTestingDraft(false);
|
|
389
533
|
}, []);
|
|
390
534
|
const applyAgent = useCallback((agent) => {
|
|
535
|
+
const switchingAgents = selectedAgentIdRef.current !== agent.id;
|
|
391
536
|
conversationRenameRunIdRef.current += 1;
|
|
537
|
+
conversationCreateRunIdRef.current += 1;
|
|
538
|
+
if (switchingAgents)
|
|
539
|
+
bindingInspectionGenerationRef.current += 1;
|
|
392
540
|
configurationDraftDirtyRef.current = false;
|
|
393
541
|
selectedAgentIdRef.current = agent.id;
|
|
394
542
|
setSelectedAgentId(agent.id);
|
|
395
543
|
setAgentName(agent.name);
|
|
396
544
|
setModelProvider('taskforce_hq');
|
|
545
|
+
const agentModel = availableModelOptions.find((model) => model.key === agent.modelKey);
|
|
546
|
+
setModelSourceGroup(modelSourceGroupForOption(agentModel || { source: agent.definition?.model.modelSource }));
|
|
547
|
+
if (switchingAgents) {
|
|
548
|
+
setSelectedConnectionId('');
|
|
549
|
+
setAgentConnectionBinding(null);
|
|
550
|
+
}
|
|
397
551
|
setProviderKey(normalizeTaskforceAgentProviderKey(agent.providerKey));
|
|
398
|
-
setModelKey(
|
|
552
|
+
setModelKey(normalizeAvailableModelKey(agent.modelKey, agent.providerKey));
|
|
399
553
|
setModelTier(agent.modelTier);
|
|
400
554
|
setDefinitionDraft(createTaskforceAgentEditorDraft(agent.definition, {
|
|
401
555
|
systemPrompt: agent.systemPrompt,
|
|
402
556
|
}));
|
|
403
557
|
setSignatureColor(agent.color || assignedAiProfileColor(agent.id));
|
|
404
558
|
setSignatureColorDirty(false);
|
|
405
|
-
setSignatureColorReset(false);
|
|
406
559
|
signatureColorEditPendingRef.current = false;
|
|
407
560
|
setConversationId(null);
|
|
408
561
|
setConversationSummaries([]);
|
|
@@ -415,7 +568,7 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
415
568
|
setToolActivity([]);
|
|
416
569
|
setConfigFeedback(null);
|
|
417
570
|
resetDraftTest();
|
|
418
|
-
}, [resetDraftTest]);
|
|
571
|
+
}, [availableModelOptions, normalizeAvailableModelKey, resetDraftTest]);
|
|
419
572
|
const selectAgent = useCallback((agent) => {
|
|
420
573
|
applyAgent(agent);
|
|
421
574
|
rememberSelection(agent.id, normalizedRememberedConversationByAgentId[agent.id] || null);
|
|
@@ -447,11 +600,13 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
447
600
|
}, []);
|
|
448
601
|
const resetAgentDraft = useCallback(() => {
|
|
449
602
|
conversationRenameRunIdRef.current += 1;
|
|
603
|
+
conversationCreateRunIdRef.current += 1;
|
|
450
604
|
configurationDraftDirtyRef.current = false;
|
|
451
605
|
selectedAgentIdRef.current = null;
|
|
452
606
|
setSelectedAgentId(null);
|
|
453
607
|
setAgentName('');
|
|
454
608
|
setModelProvider('taskforce_hq');
|
|
609
|
+
setModelSourceGroup('taskforce_managed');
|
|
455
610
|
setProviderKey(DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY);
|
|
456
611
|
setModelKey(DEFAULT_TASKFORCE_AGENT_MODEL_KEY);
|
|
457
612
|
setModelTier('balanced');
|
|
@@ -460,7 +615,6 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
460
615
|
}));
|
|
461
616
|
setSignatureColor('');
|
|
462
617
|
setSignatureColorDirty(false);
|
|
463
|
-
setSignatureColorReset(false);
|
|
464
618
|
signatureColorEditPendingRef.current = false;
|
|
465
619
|
setConversationId(null);
|
|
466
620
|
setConversationSummaries([]);
|
|
@@ -510,7 +664,7 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
510
664
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
511
665
|
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
512
666
|
}, []);
|
|
513
|
-
const loadConversation = useCallback(async (agentId, nextConversationId) => {
|
|
667
|
+
const loadConversation = useCallback(async (agentId, nextConversationId, isCurrent = () => selectedAgentIdRef.current === agentId) => {
|
|
514
668
|
setLoadingConversation(true);
|
|
515
669
|
try {
|
|
516
670
|
const res = await fetch(`/api/taskforce/agents/${encodeURIComponent(agentId)}/conversation?workspaceId=${encodeURIComponent(workspaceId)}&conversationId=${encodeURIComponent(nextConversationId)}`, {
|
|
@@ -520,6 +674,8 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
520
674
|
? await res.clone().text().catch(() => '')
|
|
521
675
|
: '';
|
|
522
676
|
const payload = await res.json().catch(() => ({}));
|
|
677
|
+
if (!isCurrent())
|
|
678
|
+
return;
|
|
523
679
|
if (!res.ok || payload?.success === false) {
|
|
524
680
|
const fallback = res.status === 404
|
|
525
681
|
? 'Taskforce agent conversation API route is not available. Restart the app server so the latest routes are active.'
|
|
@@ -527,8 +683,6 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
527
683
|
appendLog('error', String(payload?.error || responseText || fallback));
|
|
528
684
|
return;
|
|
529
685
|
}
|
|
530
|
-
if (selectedAgentIdRef.current !== agentId)
|
|
531
|
-
return;
|
|
532
686
|
const nextConversation = payload?.conversation || null;
|
|
533
687
|
applyConversation(nextConversation);
|
|
534
688
|
if (nextConversation)
|
|
@@ -537,13 +691,16 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
537
691
|
setToolActivity([]);
|
|
538
692
|
}
|
|
539
693
|
catch (err) {
|
|
540
|
-
|
|
694
|
+
if (isCurrent()) {
|
|
695
|
+
appendLog('error', String(err?.message || err || 'Unable to load saved agent conversation.'));
|
|
696
|
+
}
|
|
541
697
|
}
|
|
542
698
|
finally {
|
|
543
|
-
|
|
699
|
+
if (isCurrent())
|
|
700
|
+
setLoadingConversation(false);
|
|
544
701
|
}
|
|
545
702
|
}, [appendLog, applyConversation, rememberSelection, upsertConversationSummary, workspaceId]);
|
|
546
|
-
const loadConversationHistory = useCallback(async (agentId) => {
|
|
703
|
+
const loadConversationHistory = useCallback(async (agentId, isCurrent) => {
|
|
547
704
|
setLoadingConversationList(true);
|
|
548
705
|
setLoadingConversation(true);
|
|
549
706
|
try {
|
|
@@ -554,6 +711,8 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
554
711
|
? await res.clone().text().catch(() => '')
|
|
555
712
|
: '';
|
|
556
713
|
const payload = await res.json().catch(() => ({}));
|
|
714
|
+
if (!isCurrent())
|
|
715
|
+
return;
|
|
557
716
|
if (!res.ok || payload?.success === false) {
|
|
558
717
|
const fallback = res.status === 404
|
|
559
718
|
? 'Taskforce agent conversation API route is not available. Restart the app server so the latest routes are active.'
|
|
@@ -561,8 +720,6 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
561
720
|
appendLog('error', String(payload?.error || responseText || fallback));
|
|
562
721
|
return;
|
|
563
722
|
}
|
|
564
|
-
if (selectedAgentIdRef.current !== agentId)
|
|
565
|
-
return;
|
|
566
723
|
const summaries = Array.isArray(payload?.conversations) ? payload.conversations : [];
|
|
567
724
|
setConversationSummaries(summaries);
|
|
568
725
|
if (summaries.length > 0) {
|
|
@@ -576,7 +733,7 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
576
733
|
: null;
|
|
577
734
|
const nextConversationId = restoredConversation?.id || taskConversation?.id || (taskLaunchContext ? null : summaries[0].id);
|
|
578
735
|
if (nextConversationId) {
|
|
579
|
-
await loadConversation(agentId, nextConversationId);
|
|
736
|
+
await loadConversation(agentId, nextConversationId, isCurrent);
|
|
580
737
|
}
|
|
581
738
|
else {
|
|
582
739
|
applyConversation(null);
|
|
@@ -591,13 +748,45 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
591
748
|
}
|
|
592
749
|
}
|
|
593
750
|
catch (err) {
|
|
594
|
-
|
|
751
|
+
if (isCurrent()) {
|
|
752
|
+
appendLog('error', String(err?.message || err || 'Unable to load saved agent conversations.'));
|
|
753
|
+
}
|
|
595
754
|
}
|
|
596
755
|
finally {
|
|
597
|
-
|
|
598
|
-
|
|
756
|
+
if (isCurrent()) {
|
|
757
|
+
setLoadingConversationList(false);
|
|
758
|
+
setLoadingConversation(false);
|
|
759
|
+
}
|
|
599
760
|
}
|
|
600
761
|
}, [appendLog, applyConversation, loadConversation, normalizedRememberedAgentId, normalizedRememberedConversationByAgentId, normalizedRememberedConversationId, rememberSelection, taskLaunchContext, workspaceId]);
|
|
762
|
+
const startConversationHistoryLoad = useCallback((agentId, force = false) => {
|
|
763
|
+
const current = conversationHistoryLoadRef.current;
|
|
764
|
+
if (current?.agentId === agentId
|
|
765
|
+
&& current.loader === loadConversationHistory
|
|
766
|
+
&& !force) {
|
|
767
|
+
return current.promise || Promise.resolve();
|
|
768
|
+
}
|
|
769
|
+
const historyRunId = ++conversationHistoryRunIdRef.current;
|
|
770
|
+
const mutationRevision = conversationMutationRevisionRef.current;
|
|
771
|
+
const isCurrent = () => (selectedAgentIdRef.current === agentId
|
|
772
|
+
&& conversationHistoryRunIdRef.current === historyRunId
|
|
773
|
+
&& conversationMutationRevisionRef.current === mutationRevision);
|
|
774
|
+
const promise = loadConversationHistory(agentId, isCurrent).finally(() => {
|
|
775
|
+
if (conversationHistoryLoadRef.current?.promise === promise) {
|
|
776
|
+
conversationHistoryLoadRef.current = {
|
|
777
|
+
agentId,
|
|
778
|
+
loader: loadConversationHistory,
|
|
779
|
+
promise: null,
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
conversationHistoryLoadRef.current = {
|
|
784
|
+
agentId,
|
|
785
|
+
loader: loadConversationHistory,
|
|
786
|
+
promise,
|
|
787
|
+
};
|
|
788
|
+
return promise;
|
|
789
|
+
}, [loadConversationHistory]);
|
|
601
790
|
const loadAgents = useCallback(async (options) => {
|
|
602
791
|
const quiet = options?.quiet === true;
|
|
603
792
|
if (!quiet) {
|
|
@@ -623,6 +812,17 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
623
812
|
return;
|
|
624
813
|
}
|
|
625
814
|
const nextAgents = Array.isArray(payload?.agents) ? payload.agents : [];
|
|
815
|
+
const cloudModelCatalogExpected = runtimeMode === 'local'
|
|
816
|
+
&& cloudAuthConfigured
|
|
817
|
+
&& authSessionResolved
|
|
818
|
+
&& isAuthenticated
|
|
819
|
+
&& Boolean(resolveCloudAuthUrl);
|
|
820
|
+
if (Array.isArray(payload?.modelCatalog) && !cloudModelCatalogExpected) {
|
|
821
|
+
setAvailableModelOptions(payload.modelCatalog);
|
|
822
|
+
}
|
|
823
|
+
else if (runtimeMode === 'cloud') {
|
|
824
|
+
setAvailableModelOptions([]);
|
|
825
|
+
}
|
|
626
826
|
loadedAgentWorkspaceRef.current = workspaceId;
|
|
627
827
|
setAgents((current) => {
|
|
628
828
|
const currentById = new Map(current.map((agent) => [agent.id, agent]));
|
|
@@ -677,13 +877,129 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
677
877
|
if (!quiet)
|
|
678
878
|
setLoadingAgents(false);
|
|
679
879
|
}
|
|
680
|
-
}, [appendLog, workspaceId]);
|
|
880
|
+
}, [appendLog, authSessionResolved, cloudAuthConfigured, isAuthenticated, resolveCloudAuthUrl, runtimeMode, workspaceId]);
|
|
681
881
|
useEffect(() => {
|
|
682
882
|
resetDraftTest();
|
|
683
883
|
}, [resetDraftTest, workspaceId]);
|
|
684
884
|
useEffect(() => {
|
|
685
885
|
void loadAgents();
|
|
686
886
|
}, [loadAgents]);
|
|
887
|
+
useEffect(() => {
|
|
888
|
+
if (runtimeMode !== 'local')
|
|
889
|
+
return;
|
|
890
|
+
const localModelCatalog = TASKFORCE_AGENT_MODEL_OPTIONS.filter(isTaskforceAgentModelVisible);
|
|
891
|
+
if (!cloudAuthConfigured
|
|
892
|
+
|| !authSessionResolved
|
|
893
|
+
|| !isAuthenticated
|
|
894
|
+
|| !resolveCloudAuthUrl) {
|
|
895
|
+
if (cloudModelCatalogActiveRef.current)
|
|
896
|
+
setAvailableModelOptions(localModelCatalog);
|
|
897
|
+
cloudModelCatalogActiveRef.current = false;
|
|
898
|
+
setModelCatalogError('');
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
cloudModelCatalogActiveRef.current = true;
|
|
902
|
+
setAvailableModelOptions([]);
|
|
903
|
+
setModelCatalogError('');
|
|
904
|
+
let cancelled = false;
|
|
905
|
+
void (async () => {
|
|
906
|
+
try {
|
|
907
|
+
const response = await fetch(resolveCloudAuthUrl('/api/taskforce/agents/model-catalog'), {
|
|
908
|
+
credentials: 'include',
|
|
909
|
+
});
|
|
910
|
+
const payload = await response.json().catch(() => ({}));
|
|
911
|
+
if (!response.ok || payload?.success === false || !Array.isArray(payload?.modelCatalog)) {
|
|
912
|
+
throw new Error('Cloud model catalog unavailable.');
|
|
913
|
+
}
|
|
914
|
+
if (!cancelled)
|
|
915
|
+
setAvailableModelOptions(payload.modelCatalog);
|
|
916
|
+
}
|
|
917
|
+
catch {
|
|
918
|
+
if (!cancelled) {
|
|
919
|
+
setModelCatalogError('Unable to load models from Taskforce Cloud. Check your connection and try again.');
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
})();
|
|
923
|
+
return () => {
|
|
924
|
+
cancelled = true;
|
|
925
|
+
};
|
|
926
|
+
}, [authSessionResolved, cloudAuthConfigured, isAuthenticated, modelCatalogRefreshKey, resolveCloudAuthUrl, runtimeMode, workspaceId]);
|
|
927
|
+
useEffect(() => {
|
|
928
|
+
if (!subscriptionConnectionsEligible || !modelConnectionCloudAccessAvailable) {
|
|
929
|
+
setModelConnections([]);
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
let cancelled = false;
|
|
933
|
+
void listModelConnections({ workspaceId, resolveApiUrl: resolveCloudAuthUrl })
|
|
934
|
+
.then((connections) => {
|
|
935
|
+
if (!cancelled)
|
|
936
|
+
setModelConnections(connections);
|
|
937
|
+
})
|
|
938
|
+
.catch(() => {
|
|
939
|
+
if (!cancelled)
|
|
940
|
+
setModelConnections([]);
|
|
941
|
+
});
|
|
942
|
+
return () => {
|
|
943
|
+
cancelled = true;
|
|
944
|
+
};
|
|
945
|
+
}, [activeBuilderTab, connectionRefreshKey, modelConnectionCloudAccessAvailable, resolveCloudAuthUrl, subscriptionConnectionsEligible, workspaceId]);
|
|
946
|
+
useEffect(() => {
|
|
947
|
+
const usesConnectedAccount = selectedAgent?.definition?.model.modelSource === 'subscription_dev';
|
|
948
|
+
if (!selectedAgentId || !usesConnectedAccount || !modelConnectionCloudAccessAvailable) {
|
|
949
|
+
setAgentConnectionBinding(null);
|
|
950
|
+
if (!usesConnectedAccount)
|
|
951
|
+
setSelectedConnectionId('');
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
if (bindingMutationAgentIdRef.current === selectedAgentId)
|
|
955
|
+
return;
|
|
956
|
+
const generation = ++bindingInspectionGenerationRef.current;
|
|
957
|
+
let cancelled = false;
|
|
958
|
+
void inspectAgentConnectionBinding(selectedAgentId, { workspaceId, resolveApiUrl: resolveCloudAuthUrl })
|
|
959
|
+
.then((binding) => {
|
|
960
|
+
if (cancelled
|
|
961
|
+
|| generation !== bindingInspectionGenerationRef.current
|
|
962
|
+
|| bindingMutationAgentIdRef.current === selectedAgentId
|
|
963
|
+
|| configurationDraftDirtyRef.current)
|
|
964
|
+
return;
|
|
965
|
+
setAgentConnectionBinding(binding);
|
|
966
|
+
setSelectedConnectionId(binding.ownerIsCaller ? String(binding.connectionId || '') : '');
|
|
967
|
+
})
|
|
968
|
+
.catch(() => {
|
|
969
|
+
if (cancelled
|
|
970
|
+
|| generation !== bindingInspectionGenerationRef.current
|
|
971
|
+
|| bindingMutationAgentIdRef.current === selectedAgentId
|
|
972
|
+
|| configurationDraftDirtyRef.current)
|
|
973
|
+
return;
|
|
974
|
+
setAgentConnectionBinding(null);
|
|
975
|
+
setSelectedConnectionId('');
|
|
976
|
+
});
|
|
977
|
+
return () => {
|
|
978
|
+
cancelled = true;
|
|
979
|
+
};
|
|
980
|
+
}, [modelConnectionCloudAccessAvailable, resolveCloudAuthUrl, selectedAgent?.definition?.model.modelSource, selectedAgentId, workspaceId]);
|
|
981
|
+
useEffect(() => {
|
|
982
|
+
if (availableModelOptions.length === 0)
|
|
983
|
+
return;
|
|
984
|
+
const currentModel = availableModelOptions.find((model) => model.key === modelKey);
|
|
985
|
+
if (currentModel) {
|
|
986
|
+
const currentSourceGroup = modelSourceGroupForOption(currentModel);
|
|
987
|
+
if (currentSourceGroup !== modelSourceGroup)
|
|
988
|
+
setModelSourceGroup(currentSourceGroup);
|
|
989
|
+
if (currentModel.providerKey !== providerKey)
|
|
990
|
+
setProviderKey(currentModel.providerKey);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
if (selectedAgentId && modelKey)
|
|
994
|
+
return;
|
|
995
|
+
const nextModel = sourceModelOptions.find((model) => model.providerKey === providerKey)
|
|
996
|
+
|| sourceModelOptions[0]
|
|
997
|
+
|| availableModelOptions[0];
|
|
998
|
+
setModelSourceGroup(modelSourceGroupForOption(nextModel));
|
|
999
|
+
setProviderKey(nextModel.providerKey);
|
|
1000
|
+
setModelKey(nextModel.key);
|
|
1001
|
+
setModelTier(nextModel.defaultTier);
|
|
1002
|
+
}, [availableModelOptions, modelKey, modelSourceGroup, providerKey, selectedAgentId, sourceModelOptions]);
|
|
687
1003
|
useEffect(() => {
|
|
688
1004
|
if (!rememberedSelectionReady
|
|
689
1005
|
|| loadedAgentWorkspaceRef.current !== workspaceId
|
|
@@ -720,12 +1036,12 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
720
1036
|
const eventAgentId = String(detail?.agentId || '').trim();
|
|
721
1037
|
const activeAgentId = selectedAgentIdRef.current;
|
|
722
1038
|
if (activeAgentId && (!eventAgentId || eventAgentId === activeAgentId)) {
|
|
723
|
-
void
|
|
1039
|
+
void startConversationHistoryLoad(activeAgentId, true);
|
|
724
1040
|
}
|
|
725
1041
|
};
|
|
726
1042
|
window.addEventListener(TASKFORCE_AGENTS_MUTATED_EVENT, handleAgentsMutated);
|
|
727
1043
|
return () => window.removeEventListener(TASKFORCE_AGENTS_MUTATED_EVENT, handleAgentsMutated);
|
|
728
|
-
}, [loadAgents,
|
|
1044
|
+
}, [loadAgents, shouldUseCloudAvatarGeneration, startConversationHistoryLoad, workspaceId]);
|
|
729
1045
|
useEffect(() => {
|
|
730
1046
|
const handleAiProfilesMutated = (event) => {
|
|
731
1047
|
const detail = event.detail;
|
|
@@ -768,8 +1084,8 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
768
1084
|
useEffect(() => {
|
|
769
1085
|
if (!selectedAgentId)
|
|
770
1086
|
return;
|
|
771
|
-
void
|
|
772
|
-
}, [
|
|
1087
|
+
void startConversationHistoryLoad(selectedAgentId);
|
|
1088
|
+
}, [selectedAgentId, startConversationHistoryLoad]);
|
|
773
1089
|
useEffect(() => {
|
|
774
1090
|
if (avatarSyncingAgentIds.size === 0)
|
|
775
1091
|
return;
|
|
@@ -817,15 +1133,26 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
817
1133
|
providerKey,
|
|
818
1134
|
modelKey,
|
|
819
1135
|
tier: selectedModel?.defaultTier || modelTier,
|
|
1136
|
+
connectionScope: selectedModel?.source === 'subscription_dev'
|
|
1137
|
+
? (modelConnectionCloudAccessAvailable ? 'personal' : 'local_dev')
|
|
1138
|
+
: undefined,
|
|
820
1139
|
})), [
|
|
821
1140
|
agentName,
|
|
822
1141
|
definitionDraft,
|
|
823
1142
|
modelKey,
|
|
824
1143
|
modelTier,
|
|
1144
|
+
modelConnectionCloudAccessAvailable,
|
|
825
1145
|
providerKey,
|
|
826
1146
|
selectedAgent?.definition,
|
|
827
1147
|
selectedModel?.defaultTier,
|
|
1148
|
+
selectedModel?.source,
|
|
828
1149
|
]);
|
|
1150
|
+
const handleConnectionActivated = useCallback(async (_connection) => {
|
|
1151
|
+
setConnectionRefreshKey((current) => current + 1);
|
|
1152
|
+
}, []);
|
|
1153
|
+
const handleConnectionUnavailable = useCallback((connectionId) => {
|
|
1154
|
+
setModelConnections((current) => current.filter((connection) => connection.id !== connectionId));
|
|
1155
|
+
}, []);
|
|
829
1156
|
const handleSaveAgent = async () => {
|
|
830
1157
|
const nextAgentName = agentName.trim();
|
|
831
1158
|
const nextPurpose = definitionDraft.purpose.trim();
|
|
@@ -833,6 +1160,17 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
833
1160
|
return;
|
|
834
1161
|
const isNewAgent = !selectedAgentId;
|
|
835
1162
|
const definition = buildCurrentDraftDefinition();
|
|
1163
|
+
const usesConnectedAccount = definition.model.modelSource === 'subscription_dev';
|
|
1164
|
+
const preservesPrivateAssignment = Boolean(selectedAgentId
|
|
1165
|
+
&& agentConnectionBinding?.bound
|
|
1166
|
+
&& agentConnectionBinding.ownerIsCaller === false
|
|
1167
|
+
&& selectedAgent?.definition?.model.modelSource === 'subscription_dev'
|
|
1168
|
+
&& selectedAgent.providerKey === definition.model.providerKey);
|
|
1169
|
+
const connectionIdForSave = selectedConnectionId;
|
|
1170
|
+
if (usesConnectedAccount && !connectionIdForSave && !preservesPrivateAssignment) {
|
|
1171
|
+
setConfigFeedback({ type: 'error', message: 'Select a connected model account before saving this Agent.' });
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
836
1174
|
setSavingAgent(true);
|
|
837
1175
|
setConfigFeedback(null);
|
|
838
1176
|
try {
|
|
@@ -852,7 +1190,6 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
852
1190
|
expectedDefinitionHash: selectedAgent?.definitionHash,
|
|
853
1191
|
} : {}),
|
|
854
1192
|
...(signatureColorDirty && signatureColor ? { signatureColor } : {}),
|
|
855
|
-
...(signatureColorReset ? { resetSignatureColor: true } : {}),
|
|
856
1193
|
}),
|
|
857
1194
|
});
|
|
858
1195
|
const payload = await res.json().catch(() => ({}));
|
|
@@ -879,19 +1216,66 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
879
1216
|
setAgentName(savedAgent.name);
|
|
880
1217
|
setModelProvider('taskforce_hq');
|
|
881
1218
|
setProviderKey(normalizeTaskforceAgentProviderKey(savedAgent.providerKey));
|
|
882
|
-
setModelKey(
|
|
1219
|
+
setModelKey(normalizeAvailableModelKey(savedAgent.modelKey, savedAgent.providerKey));
|
|
883
1220
|
setModelTier(savedAgent.modelTier);
|
|
884
1221
|
setDefinitionDraft(createTaskforceAgentEditorDraft(savedAgent.definition, {
|
|
885
1222
|
systemPrompt: savedAgent.systemPrompt,
|
|
886
1223
|
}));
|
|
887
1224
|
setSignatureColor(savedAgent.color || assignedAiProfileColor(savedAgent.id));
|
|
888
1225
|
setSignatureColorDirty(false);
|
|
889
|
-
setSignatureColorReset(false);
|
|
890
1226
|
signatureColorEditPendingRef.current = false;
|
|
891
1227
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1228
|
+
let assignmentError = '';
|
|
1229
|
+
if (usesConnectedAccount && connectionIdForSave) {
|
|
1230
|
+
const mutationGeneration = ++bindingInspectionGenerationRef.current;
|
|
1231
|
+
bindingMutationAgentIdRef.current = savedAgent.id;
|
|
1232
|
+
try {
|
|
1233
|
+
const binding = await bindAgentConnectionAfterLocalSync(savedAgent.id, connectionIdForSave, { workspaceId, resolveApiUrl: resolveCloudAuthUrl }, runtimeMode === 'local');
|
|
1234
|
+
if (selectedAgentIdRef.current === savedAgent.id
|
|
1235
|
+
&& bindingInspectionGenerationRef.current === mutationGeneration) {
|
|
1236
|
+
setAgentConnectionBinding(binding);
|
|
1237
|
+
setSelectedConnectionId(connectionIdForSave);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
catch (error) {
|
|
1241
|
+
assignmentError = error.message || 'The selected model account could not be assigned.';
|
|
1242
|
+
}
|
|
1243
|
+
finally {
|
|
1244
|
+
if (bindingMutationAgentIdRef.current === savedAgent.id) {
|
|
1245
|
+
bindingMutationAgentIdRef.current = null;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
else if (!usesConnectedAccount && agentConnectionBinding?.bound && agentConnectionBinding.ownerIsCaller) {
|
|
1250
|
+
const mutationGeneration = ++bindingInspectionGenerationRef.current;
|
|
1251
|
+
bindingMutationAgentIdRef.current = savedAgent.id;
|
|
1252
|
+
try {
|
|
1253
|
+
await clearAgentConnectionBinding(savedAgent.id, {
|
|
1254
|
+
workspaceId,
|
|
1255
|
+
resolveApiUrl: resolveCloudAuthUrl,
|
|
1256
|
+
});
|
|
1257
|
+
if (selectedAgentIdRef.current === savedAgent.id
|
|
1258
|
+
&& bindingInspectionGenerationRef.current === mutationGeneration) {
|
|
1259
|
+
setAgentConnectionBinding(null);
|
|
1260
|
+
setSelectedConnectionId('');
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
catch {
|
|
1264
|
+
// The stale binding cannot authorize managed-model execution and can be cleaned up later.
|
|
1265
|
+
}
|
|
1266
|
+
finally {
|
|
1267
|
+
if (bindingMutationAgentIdRef.current === savedAgent.id) {
|
|
1268
|
+
bindingMutationAgentIdRef.current = null;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
const message = assignmentError
|
|
1273
|
+
? `Saved ${savedAgent.name}, but the model account could not be assigned. ${assignmentError}`
|
|
1274
|
+
: `Saved ${savedAgent.name}.`;
|
|
1275
|
+
appendLog(assignmentError ? 'error' : 'success', message);
|
|
1276
|
+
if (selectedAgentIdRef.current === savedAgent.id) {
|
|
1277
|
+
setConfigFeedback({ type: assignmentError ? 'error' : 'success', message });
|
|
1278
|
+
}
|
|
895
1279
|
dispatchTaskforceAgentsMutated({
|
|
896
1280
|
workspaceId,
|
|
897
1281
|
agentId: savedAgent.id,
|
|
@@ -1219,17 +1603,38 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1219
1603
|
}
|
|
1220
1604
|
};
|
|
1221
1605
|
const handleNewAgentDraft = () => requestAgentNavigation({ type: 'new' });
|
|
1606
|
+
const handleModelSourceChange = (nextSourceKey) => {
|
|
1607
|
+
configurationDraftDirtyRef.current = true;
|
|
1608
|
+
const nextConnectionId = nextSourceKey.startsWith(CONNECTION_SOURCE_PREFIX)
|
|
1609
|
+
? nextSourceKey.slice(CONNECTION_SOURCE_PREFIX.length)
|
|
1610
|
+
: '';
|
|
1611
|
+
const nextSourceGroup = nextConnectionId
|
|
1612
|
+
? 'personal_connection'
|
|
1613
|
+
: 'taskforce_managed';
|
|
1614
|
+
const nextConnection = nextConnectionId
|
|
1615
|
+
? modelConnections.find((connection) => connection.id === nextConnectionId) || null
|
|
1616
|
+
: null;
|
|
1617
|
+
const nextModels = availableModelOptions.filter((model) => modelMatchesSourceGroup(model, nextSourceGroup));
|
|
1618
|
+
const nextModel = nextModels.find((model) => !nextConnection || model.providerKey === nextConnection.providerKey) || null;
|
|
1619
|
+
setModelSourceGroup(nextSourceGroup);
|
|
1620
|
+
setSelectedConnectionId(nextConnectionId);
|
|
1621
|
+
if (!nextModel)
|
|
1622
|
+
return;
|
|
1623
|
+
setProviderKey(nextModel.providerKey);
|
|
1624
|
+
setModelKey(nextModel.key);
|
|
1625
|
+
setModelTier(nextModel.defaultTier);
|
|
1626
|
+
};
|
|
1222
1627
|
const handleProviderChange = (nextProviderKeyRaw) => {
|
|
1223
1628
|
configurationDraftDirtyRef.current = true;
|
|
1224
1629
|
const nextProviderKey = normalizeTaskforceAgentProviderKey(nextProviderKeyRaw);
|
|
1225
|
-
const nextModels =
|
|
1630
|
+
const nextModels = sourceModelOptions.filter((model) => model.providerKey === nextProviderKey);
|
|
1226
1631
|
setProviderKey(nextProviderKey);
|
|
1227
1632
|
setModelKey(nextModels[0]?.key || '');
|
|
1228
1633
|
setModelTier(nextModels[0]?.defaultTier || 'balanced');
|
|
1229
1634
|
};
|
|
1230
1635
|
const handleModelChange = (nextModelKeyRaw) => {
|
|
1231
1636
|
configurationDraftDirtyRef.current = true;
|
|
1232
|
-
const nextModelKey =
|
|
1637
|
+
const nextModelKey = normalizeAvailableModelKey(nextModelKeyRaw, providerKey);
|
|
1233
1638
|
const nextModel = modelOptions.find((model) => model.key === nextModelKey);
|
|
1234
1639
|
setModelKey(nextModelKey);
|
|
1235
1640
|
if (nextModel)
|
|
@@ -1316,10 +1721,20 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1316
1721
|
appendLog('info', 'Started a new unsaved chat.');
|
|
1317
1722
|
return;
|
|
1318
1723
|
}
|
|
1724
|
+
const targetAgentId = selectedAgentId;
|
|
1725
|
+
const targetCreateScope = conversationCreateScope;
|
|
1726
|
+
const createRunId = ++conversationCreateRunIdRef.current;
|
|
1727
|
+
const isCurrentCreate = () => (selectedAgentIdRef.current === targetAgentId
|
|
1728
|
+
&& conversationCreateRunIdRef.current === createRunId
|
|
1729
|
+
&& conversationCreateScopeRef.current === targetCreateScope);
|
|
1730
|
+
await startConversationHistoryLoad(targetAgentId);
|
|
1731
|
+
if (!isCurrentCreate())
|
|
1732
|
+
return;
|
|
1733
|
+
const mutationRevision = ++conversationMutationRevisionRef.current;
|
|
1319
1734
|
setLoadingConversation(true);
|
|
1320
1735
|
setToolActivity([]);
|
|
1321
1736
|
try {
|
|
1322
|
-
const res = await fetch(`/api/taskforce/agents/${encodeURIComponent(
|
|
1737
|
+
const res = await fetch(`/api/taskforce/agents/${encodeURIComponent(targetAgentId)}/conversation/new`, {
|
|
1323
1738
|
method: 'POST',
|
|
1324
1739
|
headers: { 'Content-Type': 'application/json' },
|
|
1325
1740
|
credentials: 'include',
|
|
@@ -1333,29 +1748,37 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1333
1748
|
}),
|
|
1334
1749
|
});
|
|
1335
1750
|
const payload = await res.json().catch(() => ({}));
|
|
1751
|
+
if (!isCurrentCreate()
|
|
1752
|
+
|| conversationMutationRevisionRef.current !== mutationRevision)
|
|
1753
|
+
return;
|
|
1336
1754
|
if (!res.ok || payload?.success === false) {
|
|
1337
1755
|
appendLog('error', String(payload?.error || 'Unable to start a new chat.'));
|
|
1338
1756
|
return;
|
|
1339
1757
|
}
|
|
1340
1758
|
setPrompt('');
|
|
1341
1759
|
const nextConversation = payload?.conversation || null;
|
|
1760
|
+
conversationMutationRevisionRef.current += 1;
|
|
1342
1761
|
applyConversation(nextConversation);
|
|
1343
|
-
rememberSelection(
|
|
1762
|
+
rememberSelection(targetAgentId, nextConversation?.id || null);
|
|
1344
1763
|
if (nextConversation)
|
|
1345
1764
|
upsertConversationSummary(nextConversation);
|
|
1346
1765
|
dispatchTaskforceAgentsMutated({
|
|
1347
1766
|
workspaceId,
|
|
1348
|
-
agentId:
|
|
1767
|
+
agentId: targetAgentId,
|
|
1349
1768
|
conversationId: payload?.conversation?.id || null,
|
|
1350
1769
|
reason: 'conversation-create',
|
|
1351
1770
|
});
|
|
1352
1771
|
appendLog('info', 'Started a new saved chat.');
|
|
1353
1772
|
}
|
|
1354
1773
|
catch (err) {
|
|
1355
|
-
|
|
1774
|
+
if (isCurrentCreate()) {
|
|
1775
|
+
appendLog('error', String(err?.message || err || 'Unable to start a new chat.'));
|
|
1776
|
+
}
|
|
1356
1777
|
}
|
|
1357
1778
|
finally {
|
|
1358
|
-
|
|
1779
|
+
if (isCurrentCreate()) {
|
|
1780
|
+
setLoadingConversation(false);
|
|
1781
|
+
}
|
|
1359
1782
|
}
|
|
1360
1783
|
};
|
|
1361
1784
|
const handleDraftTest = async () => {
|
|
@@ -1370,6 +1793,11 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1370
1793
|
: 'Cloud sign-in is still loading. Try again in a moment.');
|
|
1371
1794
|
return;
|
|
1372
1795
|
}
|
|
1796
|
+
if (draftDefinition.model.modelSource === 'subscription_dev'
|
|
1797
|
+
&& (!selectedModelConnection || selectedModelConnection.lifecycleStatus !== 'active')) {
|
|
1798
|
+
setDraftTestError('Select an active connected model account before testing this Agent.');
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1373
1801
|
setTestingDraft(true);
|
|
1374
1802
|
const runId = ++draftTestRunIdRef.current;
|
|
1375
1803
|
setDraftTestResult(null);
|
|
@@ -1389,6 +1817,9 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1389
1817
|
prompt: nextPrompt,
|
|
1390
1818
|
messages: [{ role: 'user', content: nextPrompt }],
|
|
1391
1819
|
draftDefinition,
|
|
1820
|
+
...(draftDefinition.model.modelSource === 'subscription_dev'
|
|
1821
|
+
? { connectionId: selectedConnectionId }
|
|
1822
|
+
: {}),
|
|
1392
1823
|
}),
|
|
1393
1824
|
});
|
|
1394
1825
|
const payload = await res.json().catch(() => ({}));
|
|
@@ -1433,6 +1864,12 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1433
1864
|
setTestingDraft(false);
|
|
1434
1865
|
}
|
|
1435
1866
|
};
|
|
1867
|
+
const handleDraftTestKeyDown = (event) => {
|
|
1868
|
+
if (event.key !== 'Enter' || event.shiftKey || event.nativeEvent.isComposing)
|
|
1869
|
+
return;
|
|
1870
|
+
event.preventDefault();
|
|
1871
|
+
void handleDraftTest();
|
|
1872
|
+
};
|
|
1436
1873
|
const handleTestModelGateway = async () => {
|
|
1437
1874
|
const nextPrompt = prompt.trim();
|
|
1438
1875
|
const nextSystemPrompt = systemPrompt.trim();
|
|
@@ -1460,35 +1897,49 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1460
1897
|
setToolActivity([]);
|
|
1461
1898
|
appendLog('info', `Started test prompt for ${nextAgentName}.`);
|
|
1462
1899
|
try {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1900
|
+
let res;
|
|
1901
|
+
let payload;
|
|
1902
|
+
let syncAttempt = 0;
|
|
1903
|
+
for (;;) {
|
|
1904
|
+
res = await fetch('/api/taskforce/agents/model-gateway/test', {
|
|
1905
|
+
method: 'POST',
|
|
1906
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1907
|
+
credentials: 'include',
|
|
1908
|
+
body: JSON.stringify({
|
|
1909
|
+
workspaceId,
|
|
1910
|
+
agentId: selectedAgentId,
|
|
1911
|
+
conversationId,
|
|
1912
|
+
agentName: nextAgentName,
|
|
1913
|
+
providerKey,
|
|
1914
|
+
modelKey,
|
|
1915
|
+
prompt: nextPrompt,
|
|
1916
|
+
messages: nextMessages,
|
|
1917
|
+
system: nextSystemPrompt,
|
|
1918
|
+
tier: selectedModel?.defaultTier || modelTier,
|
|
1919
|
+
...(activeTaskContext ? {
|
|
1920
|
+
taskId: activeTaskContext.taskId,
|
|
1921
|
+
taskReference: activeTaskContext.taskReference,
|
|
1922
|
+
taskTitle: activeTaskContext.taskTitle,
|
|
1923
|
+
} : {}),
|
|
1924
|
+
}),
|
|
1925
|
+
});
|
|
1926
|
+
payload = await res.json().catch(() => ({}));
|
|
1927
|
+
const awaitingCloudSync = runtimeMode === 'local'
|
|
1928
|
+
&& payload?.code === 'AGENT_NOT_AVAILABLE_IN_CLOUD'
|
|
1929
|
+
&& syncAttempt < LOCAL_AGENT_BINDING_SYNC_RETRIES;
|
|
1930
|
+
if (!awaitingCloudSync)
|
|
1931
|
+
break;
|
|
1932
|
+
syncAttempt += 1;
|
|
1933
|
+
setPromptStatus('Waiting for this Agent to synchronize with Taskforce Cloud...');
|
|
1934
|
+
await new Promise((resolve) => window.setTimeout(resolve, LOCAL_AGENT_BINDING_SYNC_DELAY_MS));
|
|
1935
|
+
}
|
|
1486
1936
|
if (!res.ok || payload?.success === false) {
|
|
1487
1937
|
const message = String(payload?.error || 'Model gateway test failed.');
|
|
1488
1938
|
setPromptStatus(message);
|
|
1489
1939
|
appendLog('error', message);
|
|
1490
1940
|
return;
|
|
1491
1941
|
}
|
|
1942
|
+
setPromptStatus('');
|
|
1492
1943
|
const nextResult = payload?.result || null;
|
|
1493
1944
|
setResult(nextResult);
|
|
1494
1945
|
const mcpToolCalls = Array.isArray(payload?.mcpToolCalls)
|
|
@@ -1521,6 +1972,7 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1521
1972
|
nextToolActivity.forEach((toolCall) => {
|
|
1522
1973
|
if ((toolCall.name === 'add_comment'
|
|
1523
1974
|
|| toolCall.name === 'add_task_checklist_item'
|
|
1975
|
+
|| toolCall.name === 'update_task_checklist_item'
|
|
1524
1976
|
|| toolCall.name === 'replace_task_checklist'
|
|
1525
1977
|
|| toolCall.name === 'complete_workflow_step') && toolCall.ok) {
|
|
1526
1978
|
dispatchTaskforceTasksMutated({
|
|
@@ -1539,6 +1991,9 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1539
1991
|
...(toolCall.name === 'complete_workflow_step' && installedWorkflowTask
|
|
1540
1992
|
? { authoritativeTask: installedWorkflowTask }
|
|
1541
1993
|
: {}),
|
|
1994
|
+
...(toolCall.name === 'complete_workflow_step' && workflowCompletion?.assignmentSnapshot
|
|
1995
|
+
? { authoritativeWorkflowAssignment: workflowCompletion.assignmentSnapshot }
|
|
1996
|
+
: {}),
|
|
1542
1997
|
});
|
|
1543
1998
|
}
|
|
1544
1999
|
});
|
|
@@ -1594,7 +2049,27 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1594
2049
|
return;
|
|
1595
2050
|
void loadConversation(selectedAgentId, nextConversationId);
|
|
1596
2051
|
};
|
|
1597
|
-
const
|
|
2052
|
+
const handleCopyToolActivity = async (toolCall) => {
|
|
2053
|
+
if (!navigator.clipboard?.writeText) {
|
|
2054
|
+
setToolCopyStatus({ id: toolCall.id, status: 'failed' });
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
try {
|
|
2058
|
+
await navigator.clipboard.writeText(formatToolActivityClipboard(toolCall));
|
|
2059
|
+
setToolCopyStatus({ id: toolCall.id, status: 'copied' });
|
|
2060
|
+
window.setTimeout(() => {
|
|
2061
|
+
setToolCopyStatus((current) => current?.id === toolCall.id ? null : current);
|
|
2062
|
+
}, 1600);
|
|
2063
|
+
}
|
|
2064
|
+
catch {
|
|
2065
|
+
setToolCopyStatus({ id: toolCall.id, status: 'failed' });
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
2068
|
+
const renderToolActivityList = (items) => (_jsx("div", { className: styles.taskforceAgentToolActivityList, children: items.map((toolCall) => (_jsxs("details", { className: `${styles.taskforceAgentToolCall} ${toolCall.ok ? '' : styles.taskforceAgentToolCallFailed}`.trim(), children: [_jsxs("summary", { children: [toolCall.ok ? _jsx(CheckCircle, { size: 13 }) : _jsx(AlertTriangle, { size: 13 }), _jsx("span", { className: styles.taskforceAgentToolCallName, children: toolCall.name }), _jsx("span", { className: styles.taskforceAgentToolCallStatus, children: toolCall.ok ? 'ok' : 'failed' })] }), _jsxs("div", { className: styles.taskforceAgentToolDetailsGrid, children: [_jsxs("button", { type: "button", className: styles.taskforceAgentToolCopyButton, onClick: () => { void handleCopyToolActivity(toolCall); }, "aria-label": `Copy ${toolCall.name} tool call details`, title: "Copy diagnostic details, including the full result up to 20,000 characters", children: [toolCopyStatus?.id === toolCall.id && toolCopyStatus.status === 'copied'
|
|
2069
|
+
? _jsx(Check, { size: 13 })
|
|
2070
|
+
: _jsx(Copy, { size: 13 }), _jsx("span", { "aria-live": "polite", children: toolCopyStatus?.id === toolCall.id
|
|
2071
|
+
? (toolCopyStatus.status === 'copied' ? 'Copied' : 'Copy failed')
|
|
2072
|
+
: 'Copy' })] }), _jsx("span", { children: "Arguments" }), _jsx("pre", { children: formatToolLogJson(toolCall.arguments) }), _jsx("span", { children: "Result preview" }), _jsx("pre", { children: formatToolLogResult(toolCall.resultText) })] })] }, toolCall.id))) }));
|
|
1598
2073
|
const renderToolActivityDetails = (items, label = 'Tool Activity') => (_jsxs("details", { className: styles.taskforceAgentToolActivity, children: [_jsxs("summary", { children: [_jsx("span", { children: label }), _jsx("strong", { children: formatToolActivitySummary(items) })] }), renderToolActivityList(items)] }));
|
|
1599
2074
|
const activeLibrary = activeBuilderTab === 'agents'
|
|
1600
2075
|
? { icon: _jsx(Bot, { size: 14 }), title: 'Agent Roster', empty: 'No agents configured yet.' }
|
|
@@ -1607,7 +2082,9 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1607
2082
|
: { icon: _jsx(Database, { size: 14 }), title: 'Resource Library', empty: 'Resource Collections are not available yet.' };
|
|
1608
2083
|
const builderTabs = (_jsxs("div", { className: styles.taskforceAgentBuilderNavigation, children: [_jsx("div", { className: styles.taskforceAgentBuilderTabs, role: "tablist", "aria-label": "Taskforce Agent builders", children: AGENT_BUILDER_TABS.map((tab, index) => {
|
|
1609
2084
|
const active = activeBuilderTab === tab.id;
|
|
1610
|
-
return (_jsx("button", { ref: (element) => { builderTabRefs.current[tab.id] = element; }, type: "button", className: `${styles.taskforceAgentBuilderTab} ${active ? styles.taskforceAgentBuilderTabActive : ''}`.trim(), role: "tab", "aria-selected": active, "aria-controls": `taskforce-agent-builder-${tab.id}`, id: `taskforce-agent-builder-tab-${tab.id}`, tabIndex: active ? 0 : -1, onClick: () =>
|
|
2085
|
+
return (_jsx("button", { ref: (element) => { builderTabRefs.current[tab.id] = element; }, type: "button", className: `${styles.taskforceAgentBuilderTab} ${active ? styles.taskforceAgentBuilderTabActive : ''}`.trim(), role: "tab", "aria-selected": active, "aria-controls": `taskforce-agent-builder-${tab.id}`, id: `taskforce-agent-builder-tab-${tab.id}`, tabIndex: active ? 0 : -1, onClick: () => {
|
|
2086
|
+
setActiveBuilderTab(tab.id);
|
|
2087
|
+
}, onKeyDown: (event) => {
|
|
1611
2088
|
let nextIndex = index;
|
|
1612
2089
|
if (event.key === 'ArrowRight')
|
|
1613
2090
|
nextIndex = (index + 1) % AGENT_BUILDER_TABS.length;
|
|
@@ -1625,7 +2102,8 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1625
2102
|
builderTabRefs.current[nextTab.id]?.focus();
|
|
1626
2103
|
}, children: tab.label }, tab.id));
|
|
1627
2104
|
}) }), activeBuilderTab === 'agents' ? (_jsxs("button", { type: "button", className: `${styles.secondaryHeaderBtn} ${styles.taskforceAgentBuilderCreateBtn}`.trim(), onClick: handleNewAgentDraft, children: [_jsx(Plus, { size: 14 }), "New Agent"] })) : null] }));
|
|
1628
|
-
const
|
|
2105
|
+
const libraryTrayVisible = agentRosterTrayOpen;
|
|
2106
|
+
const libraryTray = (_jsxs("aside", { className: `${styles.docTrayPanel} ${libraryTrayVisible ? styles.docTrayPanelOpen : ''}`.trim(), "aria-hidden": !libraryTrayVisible, "aria-label": activeLibrary.title, children: [_jsxs("div", { className: styles.taskforceAgentRosterHeader, children: [_jsxs("span", { className: styles.taskforceAgentRosterTitle, children: [activeLibrary.icon, activeLibrary.title] }), activeBuilderTab === 'agents' && loadingAgents && _jsx(Loader2, { size: 14, className: styles.spinner }), onCloseAgentRosterTray ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCloseAgentRosterTray, title: `Collapse ${activeLibrary.title.toLowerCase()}`, "aria-label": `Collapse ${activeLibrary.title.toLowerCase()}`, children: _jsx(ChevronLeft, { size: 16 }) })) : null] }), _jsx("div", { className: `${styles.taskforceAgentRosterContent} tf-scrollbar tf-tray-scroll-viewport`, children: activeBuilderTab === 'roles' ? (_jsx("div", { ref: setRoleLibraryPortalTarget, className: styles.taskforceAgentLibraryPortal })) : activeBuilderTab === 'skills' ? (_jsx("div", { ref: setSkillLibraryPortalTarget, className: styles.taskforceAgentLibraryPortal })) : activeBuilderTab === 'connections' ? (_jsx("div", { ref: setConnectionLibraryPortalTarget, className: styles.taskforceAgentLibraryPortal })) : activeBuilderTab === 'resources' ? (_jsx(FutureLibrarySummary, { kind: "resources" })) : activeBuilderTab === 'agents' && agents.length > 0 ? (_jsx("div", { className: styles.taskforceAgentList, children: agents.map((agent) => {
|
|
1629
2107
|
const avatarUrl = getAgentAvatarUrl(agent);
|
|
1630
2108
|
const color = agent.color || assignedAiProfileColor(agent.id);
|
|
1631
2109
|
return (_jsx(AiIdentityRosterCard, { name: agent.name, username: agent.username, subtitle: "Taskforce Agent", avatar: avatarUrl
|
|
@@ -1663,57 +2141,33 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1663
2141
|
setPromptStatus('');
|
|
1664
2142
|
}, onKeyDown: handlePromptKeyDown, disabled: testing || loadingConversation || !selectedAgentId, placeholder: testing ? 'Waiting for response...' : TEST_PROMPT_PLACEHOLDER, maxLength: 4000 })] }), _jsxs("button", { type: "button", className: styles.secondaryHeaderBtn, onClick: () => { void handleTestModelGateway(); }, disabled: testing || loadingConversation || !prompt.trim() || !modelKey || !selectedAgentId, children: [testing ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(Send, { size: 14 }), "Send"] }), promptStatus ? (_jsx("div", { className: styles.taskforceAgentDrawerPromptStatus, role: "status", children: promptStatus })) : null] }), _jsxs("div", { className: styles.taskforceAgentDrawerMetrics, "aria-label": "Response metrics", children: [_jsxs("span", { children: [_jsx("strong", { children: "Usage" }), formatModelGatewayUsage(result)] }), _jsxs("span", { children: [_jsx("strong", { children: "Latency" }), formatModelGatewayLatency(result)] })] })] }));
|
|
1665
2143
|
}
|
|
1666
|
-
return (_jsxs("div", { className: `${styles.standalonePage} ${styles.standaloneContent} ${styles.taskforceAgentsModuleRoot} ${
|
|
2144
|
+
return (_jsxs("div", { className: `${styles.standalonePage} ${styles.standaloneContent} ${styles.taskforceAgentsModuleRoot} ${libraryTrayVisible ? styles.taskforceAgentsModuleTrayOpen : ''}`.trim(), children: [libraryTray, _jsxs("div", { className: `${styles.taskforceAgentsModuleMain} tf-scrollbar`, children: [_jsxs("div", { className: styles.settingsContent, style: { maxWidth: 1180, margin: '0 auto', width: '100%' }, children: [builderTabs, _jsx("div", { className: `${styles.settingGroup} ${styles.taskforceAgentBuilderPanel}`, hidden: activeBuilderTab !== 'agents', children: _jsxs("div", { className: styles.taskforceAgentTestGrid, role: "tabpanel", id: "taskforce-agent-builder-agents", "aria-labelledby": "taskforce-agent-builder-tab-agents", children: [_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.taskforceAgentAvatarPanel, children: [_jsxs("div", { className: styles.taskforceAgentAvatarEditControl, children: [_jsx(EditableAvatarButton, { label: selectedAgent ? `Edit ${selectedAgent.name} photo` : 'Photo editing is unavailable until agent creation', imageUrl: selectedAgentAvatarUrl, fallback: _jsx(Bot, { size: 28 }), accentColor: signatureColor || selectedAgent?.color, size: 88, editBadgeSize: 28, editIconSize: 14, disabled: !selectedAgentId, loading: Boolean(selectedAgentId && generatingAvatarAgentIds.has(selectedAgentId)), loadingLabel: `Generating ${selectedAgent?.name || 'agent'} photo`, error: Boolean(selectedAgentGenerationFeedback?.error), errorLabel: selectedAgentGenerationFeedback?.error || 'Agent photo generation failed', onClick: () => {
|
|
1667
2145
|
setAgentAvatarError(null);
|
|
1668
2146
|
setAgentAvatarNotice(null);
|
|
1669
2147
|
setAvatarEditorOpen(true);
|
|
1670
|
-
} }), isSelectedAgentAvatarSyncing ? _jsx(Loader2, { size: 16, className: `${styles.spinner} ${styles.taskforceAgentAvatarSyncIcon}` }) : null] }), _jsxs("div", { className: styles.taskforceAgentAvatarCopy, children: [_jsx("strong", { children: agentName.trim() || selectedAgent?.name || DEFAULT_AGENT_NAME }), _jsx("span", { className: styles.taskforceAgentAvatarRole, children: "Taskforce Agent" }), isSelectedAgentAvatarSyncing ? _jsx("small", { children: "Syncing avatar..." }) : null] }), _jsxs("div", { className: styles.taskforceAgentToolbar, children: [configFeedback ? (_jsxs("span", { className: configFeedback.type === 'error' ? 'tf-chip-danger' : 'tf-chip-success', role: configFeedback.type === 'error' ? 'alert' : 'status', "aria-label": "Agent configuration status", children: [configFeedback.type === 'error' ? _jsx(AlertTriangle, { size: 12 }) : _jsx(CheckCircle, { size: 12 }), configFeedback.message] })) : null, _jsxs("button", { type: "button", className: styles.secondaryHeaderBtn, onClick: () => { void handleSaveAgent(); }, disabled: savingAgent || !agentName.trim() || !definitionDraft.purpose.trim() || !modelKey, children: [savingAgent ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(Save, { size: 14 }), "Save"] })] })] }),
|
|
2148
|
+
} }), isSelectedAgentAvatarSyncing ? _jsx(Loader2, { size: 16, className: `${styles.spinner} ${styles.taskforceAgentAvatarSyncIcon}` }) : null] }), _jsxs("div", { className: styles.taskforceAgentAvatarCopy, children: [_jsx("strong", { children: agentName.trim() || selectedAgent?.name || DEFAULT_AGENT_NAME }), _jsx("span", { className: styles.taskforceAgentAvatarRole, children: "Taskforce Agent" }), isSelectedAgentAvatarSyncing ? _jsx("small", { children: "Syncing avatar..." }) : null] }), _jsxs("div", { className: styles.taskforceAgentToolbar, children: [configFeedback ? (_jsxs("span", { className: configFeedback.type === 'error' ? 'tf-chip-danger' : 'tf-chip-success', role: configFeedback.type === 'error' ? 'alert' : 'status', "aria-label": "Agent configuration status", children: [configFeedback.type === 'error' ? _jsx(AlertTriangle, { size: 12 }) : _jsx(CheckCircle, { size: 12 }), configFeedback.message] })) : null, _jsxs("button", { type: "button", className: styles.secondaryHeaderBtn, "aria-expanded": testPanelOpen, "aria-controls": "taskforce-agent-test-panel", title: "Uses the current draft, including unsaved changes. Test messages are not saved and cannot modify tasks.", onClick: () => setTestPanelOpen((open) => !open), children: [_jsx(Beaker, { size: 14 }), "Test Agent"] }), _jsxs("button", { type: "button", className: styles.secondaryHeaderBtn, onClick: () => { void handleSaveAgent(); }, disabled: savingAgent || !agentName.trim() || !definitionDraft.purpose.trim() || !modelKey || !selectedModel, children: [savingAgent ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(Save, { size: 14 }), "Save"] })] })] }), testPanelOpen ? (_jsxs("section", { id: "taskforce-agent-test-panel", className: styles.taskforceAgentHeaderTestPanel, "aria-label": "Isolated Agent test", children: [_jsxs("div", { className: styles.taskforceAgentTestComposer, children: [_jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Test Prompt" }), _jsx("textarea", { className: styles.input, value: draftTestPrompt, onChange: (event) => setDraftTestPrompt(event.target.value), onKeyDown: handleDraftTestKeyDown, placeholder: "Ask the draft agent a representative question...", rows: 4, disabled: testingDraft })] }), _jsx("button", { type: "button", className: `tf-control-icon ${styles.taskforceAgentTestSendButton}`, "aria-label": "Send test prompt", title: "Send test prompt", onClick: () => { void handleDraftTest(); }, disabled: testingDraft || !draftTestPrompt.trim() || !definitionDraft.purpose.trim() || !modelKey, children: testingDraft ? _jsx(Loader2, { size: 15, className: styles.spinner }) : _jsx(Send, { size: 15 }) })] }), !canUseCloudAgentRuntime ? (_jsx("p", { className: styles.taskforceAgentTestRestriction, children: authSessionResolved
|
|
2149
|
+
? 'Sign in to Taskforce Cloud to run agent tests.'
|
|
2150
|
+
: 'Checking Taskforce Cloud sign-in...' })) : null, draftTestError ? (_jsxs("div", { className: styles.taskforceAgentTestError, role: "alert", children: [_jsx(AlertTriangle, { size: 14 }), _jsx("span", { children: draftTestError })] })) : null, testingDraft ? (_jsxs("div", { className: styles.taskforceAgentTestPending, role: "status", children: [_jsx(Loader2, { size: 15, className: styles.spinner }), _jsx("span", { children: "Testing agent..." })] })) : null, draftTestResult ? (_jsxs("div", { className: styles.taskforceAgentTestResult, role: "status", "aria-live": "polite", children: [_jsxs("div", { className: styles.taskforceAgentTestResultHeader, children: [_jsxs("span", { children: [_jsx(CheckCircle, { size: 14 }), " Test completed"] }), _jsxs("span", { children: [formatModelGatewayLatency(draftTestResult), " \u00B7 ", formatModelGatewayUsage(draftTestResult)] })] }), _jsx("div", { className: styles.taskforceAgentTestResponse, children: _jsx(Markdown, { variant: "conversation", children: draftTestResult.text }) }), _jsxs("details", { className: styles.taskforceAgentToolActivity, children: [_jsxs("summary", { children: [_jsx("span", { children: "Response Details" }), _jsx("strong", { children: labelForTaskforceAgentModel(draftTestSnapshot?.modelKey || modelKey) })] }), _jsxs("div", { className: styles.taskforceAgentMetaGrid, children: [_jsxs("div", { children: [_jsx("span", { children: "Tested agent" }), _jsx("strong", { children: draftTestSnapshot?.agentName || agentName.trim() || DEFAULT_AGENT_NAME })] }), _jsxs("div", { children: [_jsx("span", { children: "Provider" }), _jsx("strong", { children: labelForTaskforceAgentProvider(draftTestSnapshot?.providerKey || providerKey) })] }), _jsxs("div", { children: [_jsx("span", { children: "Runtime model" }), _jsx("code", { children: draftTestResult.modelId || 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Test prompt" }), _jsx("strong", { children: draftTestSnapshot?.prompt || 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Tested purpose" }), _jsx("strong", { children: draftTestSnapshot?.definition.purpose || 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Tested working guidelines" }), _jsx("strong", { children: draftTestSnapshot?.definition.behavior.workingGuidelines || 'None' })] }), _jsxs("div", { children: [_jsx("span", { children: "Stop reason" }), _jsx("strong", { children: draftTestResult.stopReason || 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Input tokens" }), _jsx("strong", { children: draftTestResult.usage?.inputTokens ?? 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Output tokens" }), _jsx("strong", { children: draftTestResult.usage?.outputTokens ?? 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Total tokens" }), _jsx("strong", { children: draftTestResult.usage?.totalTokens ?? 'Not reported' })] }), _jsxs("div", { children: [_jsx("span", { children: "Latency" }), _jsx("strong", { children: formatModelGatewayLatency(draftTestResult) })] })] }), draftTestToolActivity.length > 0
|
|
2151
|
+
? renderToolActivityDetails(draftTestToolActivity, 'Managed Tool Activity')
|
|
2152
|
+
: null] })] })) : null] })) : null, selectedAgent?.configurationState && selectedAgent.configurationState !== 'valid' ? (_jsxs("div", { className: styles.taskforceAgentTestError, role: "alert", children: [_jsx(AlertTriangle, { size: 14 }), _jsxs("span", { children: ["This Agent configuration is ", selectedAgent.configurationState.replace(/-/g, ' '), ".", selectedAgent.configurationIssues?.[0]?.message
|
|
1671
2153
|
? ` ${selectedAgent.configurationIssues[0].message}`
|
|
1672
|
-
: ' Repair the highlighted configuration before testing it.'] })] })) : null, _jsxs("div", { className: styles.topRow, children: [_jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Agent Name" }), _jsx("input", { className: styles.input, value: agentName, onChange: (event) => {
|
|
2154
|
+
: ' Repair the highlighted configuration before testing it.'] })] })) : null, modelCatalogError ? (_jsxs("div", { className: styles.taskforceAgentTestError, role: "alert", children: [_jsx(AlertTriangle, { size: 14 }), _jsx("span", { children: modelCatalogError }), _jsxs("button", { type: "button", className: `${styles.secondaryHeaderBtn} ${styles.taskforceAgentRetryButton}`, onClick: () => setModelCatalogRefreshKey((current) => current + 1), children: [_jsx(RotateCcw, { size: 14 }), "Retry"] })] })) : null, _jsxs("div", { className: styles.topRow, children: [_jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Agent Name" }), _jsx("input", { className: styles.input, value: agentName, onChange: (event) => {
|
|
1673
2155
|
configurationDraftDirtyRef.current = true;
|
|
1674
2156
|
setAgentName(event.target.value);
|
|
1675
|
-
}, placeholder: DEFAULT_AGENT_NAME, required: true, maxLength: 80 })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Platform" }), _jsx("div", { className: styles.taskforceAgentReadonlyField, children: formatAgentProvider(modelProvider) })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Provider" }), _jsx("select", { className: styles.select, value: providerKey, onChange: (event) => handleProviderChange(event.target.value), children: configuredProviderOptions.map((provider) => (_jsx("option", { value: provider.key, children: provider.label }, provider.key))) })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Model" }),
|
|
1676
|
-
|
|
1677
|
-
return (_jsx("button", { type: "button", className: styles.aiProfileColorOption, style: { backgroundColor: color }, "aria-label": `Use ${token}`, "aria-pressed": signatureColor.toLowerCase() === color.toLowerCase(), onClick: () => {
|
|
1678
|
-
configurationDraftDirtyRef.current = true;
|
|
1679
|
-
setSignatureColor(color);
|
|
1680
|
-
setSignatureColorDirty(true);
|
|
1681
|
-
setSignatureColorReset(false);
|
|
1682
|
-
signatureColorEditPendingRef.current = true;
|
|
1683
|
-
} }, token));
|
|
1684
|
-
}), selectedAgent ? (_jsx("button", { type: "button", className: styles.secondaryHeaderBtn, onClick: () => {
|
|
2157
|
+
}, placeholder: DEFAULT_AGENT_NAME, required: true, maxLength: 80 })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Platform" }), _jsx("div", { className: styles.taskforceAgentReadonlyField, "aria-label": "Platform", children: formatAgentProvider(modelProvider) })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Model Source" }), _jsx("select", { className: styles.select, value: modelSourceSelectionKey, onChange: (event) => handleModelSourceChange(event.target.value), children: configuredModelSourceOptions.map((source) => (_jsx("option", { value: source.key, disabled: source.disabled, children: source.label }, source.key))) })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Provider" }), _jsx("select", { className: styles.select, value: providerKey, onChange: (event) => handleProviderChange(event.target.value), children: configuredProviderOptions.map((provider) => (_jsx("option", { value: provider.key, children: provider.label }, provider.key))) })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Model" }), _jsxs("select", { className: styles.select, value: modelKey, onChange: (event) => handleModelChange(event.target.value), disabled: modelOptions.length === 0, children: [!selectedModel && modelKey ? (_jsxs("option", { value: modelKey, disabled: true, children: [labelForTaskforceAgentModel(modelKey), " (unavailable)"] })) : null, modelOptions.map((model) => (_jsx("option", { value: model.key, children: model.label }, model.key))), modelOptions.length === 0 && !modelKey ? (_jsxs("option", { value: "", children: ["No configured ", labelForTaskforceAgentProvider(providerKey), " models yet"] })) : null] })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Default Tier" }), _jsx("div", { className: styles.taskforceAgentReadonlyField, children: selectedModel ? formatModelTier(selectedModel.defaultTier) : 'No configured tier' })] })] }), _jsxs("div", { className: styles.taskforceAgentSignatureColorField, children: [_jsx("span", { className: styles.label, title: "Identifies this agent across Taskforce.", "aria-label": "Signature Color. Identifies this agent across Taskforce.", children: "Signature Color" }), _jsx("div", { className: styles.aiProfileColorPicker, "aria-label": "Signature color options", children: AI_PROFILE_SIGNATURE_COLOR_OPTIONS.map(({ name, value: color }) => {
|
|
2158
|
+
return (_jsx("button", { type: "button", className: styles.aiProfileColorOption, style: { backgroundColor: color }, "aria-label": `Use ${name}`, "aria-pressed": signatureColor.toLowerCase() === color.toLowerCase(), onClick: () => {
|
|
1685
2159
|
configurationDraftDirtyRef.current = true;
|
|
1686
|
-
setSignatureColor(
|
|
1687
|
-
setSignatureColorDirty(
|
|
1688
|
-
setSignatureColorReset(true);
|
|
2160
|
+
setSignatureColor(color);
|
|
2161
|
+
setSignatureColorDirty(true);
|
|
1689
2162
|
signatureColorEditPendingRef.current = true;
|
|
1690
|
-
}
|
|
2163
|
+
} }, color));
|
|
2164
|
+
}) })] }), _jsxs("div", { className: styles.taskforceAgentBehaviorGrid, children: [_jsxs("label", { className: `${styles.field} ${styles.taskforceAgentBehaviorWide}`, children: [_jsx("span", { className: styles.label, children: "Purpose" }), _jsx("small", { className: styles.taskforceAgentFieldHelper, children: "What should this agent help with?" }), _jsx("textarea", { className: styles.input, "aria-label": "Purpose", value: definitionDraft.purpose, onChange: (event) => {
|
|
1691
2165
|
configurationDraftDirtyRef.current = true;
|
|
1692
2166
|
setDefinitionDraft((current) => ({
|
|
1693
2167
|
...current,
|
|
1694
2168
|
purpose: event.target.value,
|
|
1695
2169
|
}));
|
|
1696
|
-
}, maxLength: 1000, rows: 3, required: true })] }), _jsx("
|
|
1697
|
-
configurationDraftDirtyRef.current = true;
|
|
1698
|
-
setDefinitionDraft((current) => ({
|
|
1699
|
-
...current,
|
|
1700
|
-
roleRef,
|
|
1701
|
-
}));
|
|
1702
|
-
}, onSkillRefsChange: (skillRefs) => {
|
|
1703
|
-
configurationDraftDirtyRef.current = true;
|
|
1704
|
-
setDefinitionDraft((current) => ({
|
|
1705
|
-
...current,
|
|
1706
|
-
skillRefs,
|
|
1707
|
-
}));
|
|
1708
|
-
}, onManageRoles: () => setActiveBuilderTab('roles'), onManageSkills: () => setActiveBuilderTab('skills') }) }), _jsx("div", { className: styles.taskforceAgentBehaviorWide, children: _jsx(ToolAccessSelector, { selectedKeys: definitionDraft.requestedCapabilities, hasCustomOverrides: Boolean(selectedAgent?.definition?.toolPolicy.toolOverrides?.length
|
|
1709
|
-
&& !definitionDraft.toolAccessChanged), onChange: (requestedCapabilities) => {
|
|
1710
|
-
configurationDraftDirtyRef.current = true;
|
|
1711
|
-
setDefinitionDraft((current) => ({
|
|
1712
|
-
...current,
|
|
1713
|
-
requestedCapabilities,
|
|
1714
|
-
toolAccessChanged: true,
|
|
1715
|
-
}));
|
|
1716
|
-
} }) }), _jsx("div", { className: styles.taskforceAgentBehaviorWide, children: _jsx(EffectiveConfigurationSummary, { hasRole: Boolean(definitionDraft.roleRef), directSkillCount: definitionDraft.skillRefs.length, toolKeys: definitionDraft.requestedCapabilities }) }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Personality and Voice" }), _jsx("small", { className: styles.taskforceAgentFieldHelper, children: "How should this agent behave or portray itself?" }), _jsxs("select", { className: styles.select, "aria-label": "Personality and Voice", value: definitionDraft.personalitySelection, onChange: (event) => {
|
|
2170
|
+
}, maxLength: 1000, rows: 3, required: true })] }), _jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Personality and Voice" }), _jsx("small", { className: styles.taskforceAgentFieldHelper, children: "How should this agent behave or portray itself?" }), _jsxs("select", { className: styles.select, "aria-label": "Personality and Voice", value: definitionDraft.personalitySelection, onChange: (event) => {
|
|
1717
2171
|
configurationDraftDirtyRef.current = true;
|
|
1718
2172
|
setDefinitionDraft((current) => ({
|
|
1719
2173
|
...current,
|
|
@@ -1764,13 +2218,29 @@ export function TaskforceAgentsModule({ workspaceId, agentRosterTrayOpen = true,
|
|
|
1764
2218
|
...current,
|
|
1765
2219
|
avatarArtStyleCustom: event.target.value,
|
|
1766
2220
|
}));
|
|
1767
|
-
}, maxLength: 4000, rows: 3, placeholder: "Describe medium, palette, lighting, period, or atmosphere." })] })) : null] }), _jsxs("details", { className: styles.taskforceAgentToolActivity, children: [_jsxs("summary", { children: [_jsx("span", { children: "Technical model details" }), _jsx("strong", { children: selectedModel ? formatModelAvailability(selectedModel.availability) : 'Unavailable' })] }), _jsxs("div", { className: styles.taskforceAgentMetaGrid, children: [_jsxs("div", { children: [_jsx("span", { children: "Model ID" }), _jsx("code", { children: selectedModel?.runtimeModelId || 'No configured model' })] }), _jsxs("div", { children: [_jsx("span", { children: "Max Output" }), _jsx("strong", { children: formatMaxOutputTokens(selectedModel?.defaultMaxTokens) })] })] })] })] }),
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
2221
|
+
}, maxLength: 4000, rows: 3, placeholder: "Describe medium, palette, lighting, period, or atmosphere." })] })) : null] }), _jsxs("details", { className: styles.taskforceAgentToolActivity, children: [_jsxs("summary", { children: [_jsx("span", { children: "Technical model details" }), _jsx("strong", { children: selectedModel ? formatModelAvailability(selectedModel.availability) : 'Unavailable' })] }), _jsxs("div", { className: styles.taskforceAgentMetaGrid, children: [_jsxs("div", { children: [_jsx("span", { children: "Model ID" }), _jsx("code", { children: selectedModel?.runtimeModelId || 'No configured model' })] }), _jsxs("div", { children: [_jsx("span", { children: "Max Output" }), _jsx("strong", { children: formatMaxOutputTokens(selectedModel?.defaultMaxTokens) })] })] })] })] }), _jsxs("aside", { className: styles.taskforceAgentOutputStack, "aria-label": "Agent Role and Capabilities", children: [_jsx(AgentBehaviorAssignments, { workspaceId: workspaceId, roleRef: definitionDraft.roleRef, skillRefs: definitionDraft.skillRefs, onRoleRefChange: (roleRef) => {
|
|
2222
|
+
configurationDraftDirtyRef.current = true;
|
|
2223
|
+
setDefinitionDraft((current) => ({
|
|
2224
|
+
...current,
|
|
2225
|
+
roleRef,
|
|
2226
|
+
}));
|
|
2227
|
+
}, onSkillRefsChange: (skillRefs) => {
|
|
2228
|
+
configurationDraftDirtyRef.current = true;
|
|
2229
|
+
setDefinitionDraft((current) => ({
|
|
2230
|
+
...current,
|
|
2231
|
+
skillRefs,
|
|
2232
|
+
}));
|
|
2233
|
+
}, onManageRoles: () => setActiveBuilderTab('roles'), onManageSkills: () => setActiveBuilderTab('skills') }), _jsx(ToolAccessSelector, { selectedKeys: definitionDraft.requestedCapabilities, hasCustomOverrides: Boolean(selectedAgent?.definition?.toolPolicy.toolOverrides?.length
|
|
2234
|
+
&& !definitionDraft.toolAccessChanged), onChange: (requestedCapabilities) => {
|
|
2235
|
+
configurationDraftDirtyRef.current = true;
|
|
2236
|
+
setDefinitionDraft((current) => ({
|
|
2237
|
+
...current,
|
|
2238
|
+
requestedCapabilities,
|
|
2239
|
+
toolAccessChanged: true,
|
|
2240
|
+
}));
|
|
2241
|
+
} }), _jsx(EffectiveConfigurationSummary, { hasRole: Boolean(definitionDraft.roleRef), directSkillCount: definitionDraft.skillRefs.length, toolKeys: definitionDraft.requestedCapabilities })] })] }) }), _jsx("section", { className: styles.taskforceAgentBuilderPanel, role: "tabpanel", id: "taskforce-agent-builder-roles", "aria-labelledby": "taskforce-agent-builder-tab-roles", hidden: activeBuilderTab !== 'roles', children: activeBuilderTab === 'roles'
|
|
1772
2242
|
? (_jsx(RoleManagerPanel, { workspaceId: workspaceId, libraryPortalTarget: roleLibraryPortalTarget }))
|
|
1773
|
-
: null }), _jsx("section", { className: styles.taskforceAgentBuilderPanel, role: "tabpanel", id: "taskforce-agent-builder-skills", "aria-labelledby": "taskforce-agent-builder-tab-skills", hidden: activeBuilderTab !== 'skills', children: _jsx(SkillManagerPanel, { workspaceId: workspaceId, active: activeBuilderTab === 'skills', libraryPortalTarget: skillLibraryPortalTarget }, workspaceId) }), _jsx("section", { className: styles.taskforceAgentBuilderPanel, role: "tabpanel", id: "taskforce-agent-builder-connections", "aria-labelledby": "taskforce-agent-builder-tab-connections", hidden: activeBuilderTab !== 'connections', children: activeBuilderTab === 'connections' ? _jsx(
|
|
2243
|
+
: null }), _jsx("section", { className: styles.taskforceAgentBuilderPanel, role: "tabpanel", id: "taskforce-agent-builder-skills", "aria-labelledby": "taskforce-agent-builder-tab-skills", hidden: activeBuilderTab !== 'skills', children: _jsx(SkillManagerPanel, { workspaceId: workspaceId, active: activeBuilderTab === 'skills', libraryPortalTarget: skillLibraryPortalTarget }, workspaceId) }), _jsx("section", { className: styles.taskforceAgentBuilderPanel, role: "tabpanel", id: "taskforce-agent-builder-connections", "aria-labelledby": "taskforce-agent-builder-tab-connections", hidden: activeBuilderTab !== 'connections', children: activeBuilderTab === 'connections' ? (_jsx(ModelConnectionsPanel, { workspaceId: workspaceId, active: true, runtimeMode: runtimeMode, eligible: subscriptionConnectionsEligible, cloudAccessAvailable: modelConnectionCloudAccessAvailable, cloudAccessPending: modelConnectionCloudAccessPending, cloudAuthConfigured: cloudAuthConfigured, resolveCloudAuthUrl: resolveCloudAuthUrl, onConnectionActivated: handleConnectionActivated, onConnectionUnavailable: handleConnectionUnavailable, onReturnToAgent: () => activateBuilderTab('agents', true), libraryPortalTarget: connectionLibraryPortalTarget })) : null }), _jsx("section", { className: styles.taskforceAgentBuilderPanel, role: "tabpanel", id: "taskforce-agent-builder-resources", "aria-labelledby": "taskforce-agent-builder-tab-resources", hidden: activeBuilderTab !== 'resources', children: activeBuilderTab === 'resources' ? _jsx(FutureWorkspacePanel, { kind: "resources" }) : null })] }), _jsx(Modal, { isOpen: Boolean(pendingAgentNavigation), onClose: () => setPendingAgentNavigation(null), title: "Discard unsaved changes?", size: "sm", theme: theme, closeOnOverlayClick: false, footer: (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "tf-button-secondary", onClick: () => setPendingAgentNavigation(null), "data-modal-initial-focus": true, children: "Keep editing" }), _jsx("button", { type: "button", className: "tf-button-destructive", onClick: discardDraftAndNavigate, children: "Discard changes" })] })), children: _jsx("p", { children: "Your unsaved Agent changes will be lost." }) }), _jsx(AvatarImageManagerModal, { isOpen: avatarEditorOpen, theme: theme, title: "Edit Agent Profile Photo", currentImageUrl: selectedAgentAvatarUrl, editorImageUrl: selectedAgentAvatarSourceUrl, fallbackInitial: (selectedAgent?.name || 'Agent').charAt(0).toUpperCase(), accept: "image/png,image/jpeg,image/webp,image/gif", busy: agentAvatarBusy, generating: Boolean(selectedAgentId && generatingAvatarAgentIds.has(selectedAgentId)), generateLabel: selectedAgent?.avatarUrl ? 'Regenerate' : 'Generate', hasPendingImage: false, canRemove: Boolean(selectedAgent?.avatarUrl), error: agentAvatarError || selectedAgentGenerationFeedback?.error || null, notice: agentAvatarNotice || selectedAgentGenerationFeedback?.notice || null, onClose: () => {
|
|
1774
2244
|
if (agentAvatarBusy)
|
|
1775
2245
|
return;
|
|
1776
2246
|
setAvatarEditorOpen(false);
|