@taskforcehq/taskforce 0.3.329 → 0.3.332

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.
Files changed (363) hide show
  1. package/README.md +7 -2
  2. package/dist/Taskforce.module.css +290 -45
  3. package/dist/components/features/AiProfilesModule.js +3 -5
  4. package/dist/components/features/TaskSettings.js +70 -14
  5. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  6. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  7. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
  8. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
  9. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  10. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  11. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  12. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  13. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  14. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  15. package/dist/components/features/planning/PlanningModule.js +15 -3
  16. package/dist/components/features/planning/planningMetadata.d.ts +10 -0
  17. package/dist/components/features/planning/planningMetadata.js +8 -0
  18. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  19. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  20. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  21. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  22. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  23. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  24. package/dist/components/views/StandaloneLayout.js +62 -27
  25. package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
  26. package/dist/components/views/panels/PlanningDrawer.js +12 -8
  27. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  28. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  29. package/dist/config/envSchema.js +55 -1
  30. package/dist/core/McpTokenService.d.ts +25 -1
  31. package/dist/core/McpTokenService.js +106 -15
  32. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  33. package/dist/core/TaskChecklistCommandService.js +83 -5
  34. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  35. package/dist/core/TaskLifecycleCommandService.js +6 -2
  36. package/dist/core/Taskforce.d.ts +43 -3
  37. package/dist/core/Taskforce.js +158 -7
  38. package/dist/core/types.d.ts +9 -0
  39. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
  40. package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
  41. package/dist/documentReviews/commandService.d.ts +2 -1
  42. package/dist/documentReviews/commandService.js +6 -3
  43. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  44. package/dist/hooks/sync/orchestratorShared.js +2 -0
  45. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  46. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  47. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  48. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  49. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  50. package/dist/hooks/useSyncOrchestrator.js +111 -2
  51. package/dist/hooks/useTaskData.d.ts +31 -1
  52. package/dist/hooks/useTaskData.js +29 -7
  53. package/dist/hooks/useTaskMutations.d.ts +3 -1
  54. package/dist/hooks/useTaskMutations.js +46 -12
  55. package/dist/hooks/useTaskforce.d.ts +2 -0
  56. package/dist/hooks/useTaskforce.js +11 -2
  57. package/dist/mcp/clientRegistry.d.ts +2 -2
  58. package/dist/mcp/clientRegistry.js +1 -1
  59. package/dist/mcp/documentAssetRegistrar.js +9 -6
  60. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  61. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  62. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  63. package/dist/mcp/httpProtocolRouting.d.ts +11 -0
  64. package/dist/mcp/httpProtocolRouting.js +22 -0
  65. package/dist/mcp/localCliHealth.d.ts +2 -2
  66. package/dist/mcp/localCliHealth.js +2 -2
  67. package/dist/mcp/localServiceProxy.d.ts +1 -0
  68. package/dist/mcp/localServiceProxy.js +530 -68
  69. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  70. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  71. package/dist/mcp/runtime.d.ts +54 -79
  72. package/dist/mcp/runtime.js +408 -102
  73. package/dist/mcp/taskPlanningRegistrar.js +25 -6
  74. package/dist/mcp/toolProfiles.d.ts +2 -0
  75. package/dist/mcp/toolProfiles.js +11 -0
  76. package/dist/mcp/toolRegistry.d.ts +1 -0
  77. package/dist/mcp/toolRegistry.js +9 -8
  78. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  79. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  80. package/dist/migrations/taskSchemaMigrations.js +415 -0
  81. package/dist/runtime/appGates.d.ts +2 -1
  82. package/dist/runtime/appGates.js +7 -0
  83. package/dist/server/buildInfo.d.ts +1 -0
  84. package/dist/server/buildInfo.js +5 -1
  85. package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
  86. package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
  87. package/dist/server/index.d.ts +3 -0
  88. package/dist/server/index.js +108 -11
  89. package/dist/server/localDatabaseIdentity.js +4 -1
  90. package/dist/server/localServiceLease.js +2 -1
  91. package/dist/server/localServiceSessions.d.ts +14 -17
  92. package/dist/server/localServiceSessions.js +308 -94
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
  94. package/dist/server/routes/admin.d.ts +4 -0
  95. package/dist/server/routes/admin.js +126 -5
  96. package/dist/server/routes/agents.d.ts +7 -0
  97. package/dist/server/routes/agents.js +277 -24
  98. package/dist/server/routes/billing.js +5 -1
  99. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  100. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  101. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  102. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  103. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  104. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  105. package/dist/server/routes/githubReviewEvidence.js +116 -0
  106. package/dist/server/routes/localService.d.ts +15 -4
  107. package/dist/server/routes/localService.js +136 -40
  108. package/dist/server/routes/modelConnections.d.ts +24 -0
  109. package/dist/server/routes/modelConnections.js +205 -0
  110. package/dist/server/routes/shared.d.ts +22 -0
  111. package/dist/server/routes/shared.js +298 -182
  112. package/dist/server/routes/sync.js +1 -0
  113. package/dist/server/routes/syncAuxRoutes.js +5 -1
  114. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  115. package/dist/server/routes/syncPushRoutes.js +1 -0
  116. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  117. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  118. package/dist/server/routes/tasks.js +21 -2
  119. package/dist/server/routes/workflows.js +9 -1
  120. package/dist/server/routes.js +59 -0
  121. package/dist/service/localServiceCli.d.ts +2 -2
  122. package/dist/service/localServiceCli.js +4 -3
  123. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  124. package/dist/services/codexAppServerModelGateway.js +246 -21
  125. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  126. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  127. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  128. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  129. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  130. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  131. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  132. package/dist/services/executorPhaseAApprovalService.js +609 -0
  133. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  134. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  135. package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
  136. package/dist/services/executorPhaseAIssuerCore.js +402 -0
  137. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  138. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  139. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  140. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  141. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  142. package/dist/services/githubReviewEvidenceService.js +336 -0
  143. package/dist/services/modelGateway.d.ts +7 -0
  144. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  145. package/dist/services/modelProviderConnectionService.js +279 -0
  146. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  147. package/dist/services/modelProviderCredentialHome.js +271 -0
  148. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  149. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  150. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  151. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  152. package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
  153. package/dist/services/taskforceAgentMcpBridge.js +42 -29
  154. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  155. package/dist/shared/adminEdgeProxy.js +94 -0
  156. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  157. package/dist/shared/adminProxySessionCookies.js +86 -0
  158. package/dist/shared/aiProfileColors.d.ts +31 -1
  159. package/dist/shared/aiProfileColors.js +14 -6
  160. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  161. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  162. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  163. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  164. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  165. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  166. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  167. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  168. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  169. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  170. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  171. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  172. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  173. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  174. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  175. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  176. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  177. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  178. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  179. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  180. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  181. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  182. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  183. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  184. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  185. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  186. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  187. package/dist/shared/executorPhaseATiming.js +1 -0
  188. package/dist/shared/planningIdentity.js +1 -1
  189. package/dist/shared/productLogoKeys.d.ts +2 -0
  190. package/dist/shared/productLogoKeys.js +18 -0
  191. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  192. package/dist/shared/taskforceAgentDefinition.js +6 -9
  193. package/dist/shared/taskforceAgentModels.js +7 -3
  194. package/dist/shared/userFeatureGrants.d.ts +4 -0
  195. package/dist/shared/userFeatureGrants.js +7 -0
  196. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  197. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  198. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  199. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  200. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  201. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  202. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  203. package/dist/storage/modelProviderConnectionStore.js +446 -0
  204. package/dist/storage/postgresAdapter.d.ts +4 -0
  205. package/dist/storage/postgresAdapter.js +14 -1
  206. package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
  207. package/dist/storage/postgresRequestDiagnostics.js +15 -2
  208. package/dist/storage/postgresWorker.js +20 -2
  209. package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
  210. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  211. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  212. package/dist/storage/workflowStore.d.ts +2 -0
  213. package/dist/storage/workflowStore.js +39 -2
  214. package/dist/sync/cloudSyncApi.js +4 -2
  215. package/dist/sync/collaborationSyncState.js +5 -0
  216. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  217. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  218. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  219. package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
  220. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
  221. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  222. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  223. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  224. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  225. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  226. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  227. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  228. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  229. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  230. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  231. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  232. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  233. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  234. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  235. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  236. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  237. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  238. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
  239. package/dist/sync/syncApplyHandlers.d.ts +3 -0
  240. package/dist/sync/syncApplyHandlers.js +81 -15
  241. package/dist/sync/syncService.d.ts +15 -0
  242. package/dist/sync/syncService.js +83 -18
  243. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  244. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  245. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  246. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  247. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  248. package/dist/sync/v3/durableOperationReplay.js +18 -0
  249. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  250. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  251. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  252. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  253. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  254. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  255. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  256. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
  257. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
  258. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  259. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  260. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  261. package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
  262. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  263. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  264. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  265. package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
  266. package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
  267. package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
  268. package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
  269. package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
  270. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
  271. package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
  272. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
  273. package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
  274. package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
  275. package/dist/sync/v3/syncDurabilityStore.js +202 -8
  276. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  277. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  278. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  279. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  280. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  281. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  282. package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
  283. package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
  284. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  285. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  286. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  287. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  288. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  289. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
  290. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  291. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  292. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  293. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  294. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  295. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  296. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  297. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  298. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  299. package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
  300. package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
  301. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
  302. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
  303. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  304. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  305. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  306. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  307. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  308. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
  309. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
  310. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  311. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  312. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  313. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  314. package/dist/sync/workspaceRepair.d.ts +5 -2
  315. package/dist/sync/workspaceRepair.js +161 -6
  316. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  317. package/dist/sync/workspaceSyncModel.js +35 -7
  318. package/dist/sync/workspaceSyncState.d.ts +1 -0
  319. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  320. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  321. package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
  322. package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
  323. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
  324. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
  325. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
  326. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
  327. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
  328. package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
  329. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
  330. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
  331. package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
  332. package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
  333. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  334. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
  335. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  336. package/dist/ui/assets/index-DSQINwt9.js +7 -0
  337. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  338. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  339. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  340. package/dist/ui/branding/logos/signature_dark.png +0 -0
  341. package/dist/ui/branding/logos/signature_light.png +0 -0
  342. package/dist/ui/index.html +3 -3
  343. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  344. package/dist/utils/httpSetCookie.d.ts +1 -0
  345. package/dist/utils/httpSetCookie.js +4 -1
  346. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  347. package/dist/utils/localRuntimeUrl.js +14 -0
  348. package/dist/utils/productLogoRegistry.d.ts +2 -0
  349. package/dist/utils/productLogoRegistry.js +36 -0
  350. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  351. package/dist/utils/syncStatusPresentation.js +17 -0
  352. package/dist/utils/taskEvents.d.ts +2 -0
  353. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  354. package/dist/utils/workspaceSyncPresentation.js +23 -17
  355. package/package.json +24 -4
  356. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  357. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  358. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
  359. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  360. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  361. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  362. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  363. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -10,8 +10,8 @@ export declare const TASKFORCE_TOOL_MODULES: readonly [{
10
10
  readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
11
11
  }, {
12
12
  readonly key: "documents";
13
- readonly label: "Documents";
14
- readonly description: "Find and read Taskforce documents and their review context.";
13
+ readonly label: "Documents and reviews";
14
+ readonly description: "Find and read Taskforce documents, inspect review context, and post document review feedback.";
15
15
  readonly icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
16
16
  }, {
17
17
  readonly key: "images";
@@ -17,8 +17,8 @@ export const TASKFORCE_TOOL_MODULES = [
17
17
  },
18
18
  {
19
19
  key: 'documents',
20
- label: 'Documents',
21
- description: 'Find and read Taskforce documents and their review context.',
20
+ label: 'Documents and reviews',
21
+ description: 'Find and read Taskforce documents, inspect review context, and post document review feedback.',
22
22
  icon: FileText,
23
23
  },
24
24
  {
@@ -0,0 +1,15 @@
1
+ type AgentConnectionControlProps = {
2
+ workspaceId: string;
3
+ runtimeMode: 'local' | 'cloud';
4
+ agentId: string | null;
5
+ providerKey: string;
6
+ active: boolean;
7
+ refreshKey: number;
8
+ cloudAccessAvailable?: boolean;
9
+ cloudAccessPending?: boolean;
10
+ cloudAuthConfigured?: boolean;
11
+ resolveCloudAuthUrl?: (path: string) => string;
12
+ onManageConnections: () => void;
13
+ };
14
+ export declare function AgentConnectionControl({ workspaceId, runtimeMode, agentId, providerKey, active, refreshKey, cloudAccessAvailable, cloudAccessPending, cloudAuthConfigured, resolveCloudAuthUrl, onManageConnections, }: AgentConnectionControlProps): import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,125 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { AlertTriangle, CheckCircle, Link, Loader2, Plug } from 'lucide-react';
4
+ import styles from '../../../Taskforce.module.css';
5
+ import { bindAgentConnection, inspectAgentConnectionBinding, listModelConnections, } from './modelConnectionsApi.js';
6
+ export function AgentConnectionControl({ workspaceId, runtimeMode, agentId, providerKey, active, refreshKey, cloudAccessAvailable = runtimeMode === 'cloud', cloudAccessPending = false, cloudAuthConfigured = runtimeMode === 'cloud', resolveCloudAuthUrl, onManageConnections, }) {
7
+ const context = useMemo(() => ({
8
+ workspaceId,
9
+ resolveApiUrl: resolveCloudAuthUrl,
10
+ }), [resolveCloudAuthUrl, workspaceId]);
11
+ const [binding, setBinding] = useState(null);
12
+ const [connections, setConnections] = useState([]);
13
+ const [selectedConnectionId, setSelectedConnectionId] = useState('');
14
+ const [loading, setLoading] = useState(false);
15
+ const [busy, setBusy] = useState(false);
16
+ const [error, setError] = useState('');
17
+ const loadGenerationRef = useRef(0);
18
+ const activeConnections = useMemo(() => connections.filter((connection) => (connection.providerKey === providerKey
19
+ && connection.authenticationType === 'chatgpt_device_code'
20
+ && connection.lifecycleStatus === 'active')), [connections, providerKey]);
21
+ const load = useCallback(async () => {
22
+ if (!active || !cloudAccessAvailable || !agentId)
23
+ return;
24
+ const generation = ++loadGenerationRef.current;
25
+ setLoading(true);
26
+ setBinding(null);
27
+ setConnections([]);
28
+ setSelectedConnectionId('');
29
+ setError('');
30
+ try {
31
+ const [nextBinding, nextConnections] = await Promise.all([
32
+ inspectAgentConnectionBinding(agentId, context),
33
+ listModelConnections(context),
34
+ ]);
35
+ if (generation !== loadGenerationRef.current)
36
+ return;
37
+ setConnections(nextConnections);
38
+ const ownedBindingId = nextBinding.ownerIsCaller ? String(nextBinding.connectionId || '') : '';
39
+ const matchingConnections = nextConnections.filter((connection) => (connection.providerKey === providerKey
40
+ && connection.authenticationType === 'chatgpt_device_code'
41
+ && connection.lifecycleStatus === 'active'));
42
+ const firstActiveId = matchingConnections[0]?.id || '';
43
+ const ownedBindingIsActive = matchingConnections.some((connection) => connection.id === ownedBindingId);
44
+ setSelectedConnectionId(ownedBindingIsActive ? ownedBindingId : firstActiveId);
45
+ let resolvedBinding = nextBinding;
46
+ const mayReplaceBinding = !nextBinding.bound || (nextBinding.ownerIsCaller && !nextBinding.available);
47
+ if (mayReplaceBinding && matchingConnections.length === 1) {
48
+ try {
49
+ resolvedBinding = await bindAgentConnection(agentId, matchingConnections[0].id, context);
50
+ }
51
+ catch (bindError) {
52
+ if (generation !== loadGenerationRef.current)
53
+ return;
54
+ setError(bindError.message || 'Unable to assign this account to the Agent.');
55
+ }
56
+ }
57
+ if (generation !== loadGenerationRef.current)
58
+ return;
59
+ setBinding(resolvedBinding);
60
+ }
61
+ catch (loadError) {
62
+ if (generation !== loadGenerationRef.current)
63
+ return;
64
+ setError(loadError.message || 'Unable to inspect this Agent connection.');
65
+ }
66
+ finally {
67
+ if (generation === loadGenerationRef.current)
68
+ setLoading(false);
69
+ }
70
+ }, [active, agentId, cloudAccessAvailable, context, providerKey]);
71
+ useEffect(() => {
72
+ loadGenerationRef.current += 1;
73
+ setBinding(null);
74
+ setConnections([]);
75
+ setSelectedConnectionId('');
76
+ setLoading(false);
77
+ setBusy(false);
78
+ setError('');
79
+ }, [cloudAccessAvailable, context]);
80
+ useEffect(() => {
81
+ void load();
82
+ return () => {
83
+ loadGenerationRef.current += 1;
84
+ };
85
+ }, [load, refreshKey]);
86
+ const bind = useCallback(async () => {
87
+ if (!agentId || !selectedConnectionId)
88
+ return;
89
+ const generation = loadGenerationRef.current;
90
+ setBusy(true);
91
+ setError('');
92
+ try {
93
+ const nextBinding = await bindAgentConnection(agentId, selectedConnectionId, context);
94
+ if (generation !== loadGenerationRef.current)
95
+ return;
96
+ setBinding(nextBinding);
97
+ }
98
+ catch (bindError) {
99
+ if (generation !== loadGenerationRef.current)
100
+ return;
101
+ setError(bindError.message || 'Unable to assign this account to the Agent.');
102
+ }
103
+ finally {
104
+ if (generation === loadGenerationRef.current)
105
+ setBusy(false);
106
+ }
107
+ }, [agentId, context, selectedConnectionId]);
108
+ if (!cloudAccessAvailable) {
109
+ return (_jsxs("div", { className: styles.taskforceAgentConnectionControl, children: [_jsxs("div", { children: [_jsx(Plug, { size: 15 }), _jsx("strong", { children: "Connected account" })] }), _jsx("span", { children: cloudAccessPending
110
+ ? 'Checking Taskforce Cloud sign-in...'
111
+ : cloudAuthConfigured
112
+ ? 'Sign in to Taskforce Cloud to configure this model.'
113
+ : 'Connect this local runtime to Taskforce Cloud to configure this model.' })] }));
114
+ }
115
+ if (!agentId) {
116
+ return (_jsxs("div", { className: styles.taskforceAgentConnectionControl, children: [_jsxs("div", { children: [_jsx(Plug, { size: 15 }), _jsx("strong", { children: "Connected account" })] }), _jsx("span", { children: "Save this Agent to assign a connected account." })] }));
117
+ }
118
+ return (_jsxs("div", { className: styles.taskforceAgentConnectionControl, children: [_jsxs("div", { className: styles.taskforceAgentConnectionControlHeader, children: [_jsxs("div", { children: [_jsx(Plug, { size: 15 }), _jsx("strong", { children: "Connected account" })] }), _jsx("span", { role: "status", "aria-live": "polite", children: loading ? _jsx(Loader2, { size: 14, className: styles.spinner }) : binding?.available ? (_jsxs("span", { className: "tf-chip-success", children: [_jsx(CheckCircle, { size: 12 }), " Assigned"] })) : binding?.bound ? (_jsxs("span", { className: "tf-chip-warning", children: [_jsx(AlertTriangle, { size: 12 }), " Unavailable"] })) : (_jsx("span", { className: "tf-chip-neutral", children: "Not assigned" })) })] }), error ? _jsx("span", { className: "tf-text-error", role: "alert", children: error }) : null, !loading && activeConnections.length > 0 && (!binding?.bound || binding.ownerIsCaller) ? (_jsxs("div", { className: styles.taskforceAgentConnectionBindingRow, children: [_jsxs("label", { className: styles.field, children: [_jsx("span", { className: styles.label, children: "Account" }), _jsx("select", { className: styles.select, value: selectedConnectionId, onChange: (event) => setSelectedConnectionId(event.target.value), "aria-label": "Connected model account", disabled: busy || activeConnections.length === 1, children: activeConnections.map((connection) => (_jsx("option", { value: connection.id, children: connection.displayMetadata.accountLabel
119
+ || connection.displayMetadata.accountEmail
120
+ || 'ChatGPT subscription' }, connection.id))) })] }), activeConnections.length > 1 || !binding?.available ? (_jsxs("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => { void bind(); }, disabled: busy || !selectedConnectionId || (binding?.available && binding.connectionId === selectedConnectionId), children: [busy ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(Link, { size: 14 }), "Use account"] })) : null] })) : !loading ? (_jsxs("div", { className: styles.taskforceAgentConnectionCallout, children: [_jsx("span", { children: binding?.bound && !binding.ownerIsCaller
121
+ ? "This Agent uses another eligible user's private connection. Ask the connection owner to reconnect it."
122
+ : binding?.bound
123
+ ? 'The bound connection is unavailable.'
124
+ : 'Connect ChatGPT before running this Agent.' }), binding?.ownerIsCaller !== false ? (_jsxs("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: onManageConnections, children: [_jsx(Plug, { size: 14 }), " Manage connections"] })) : null] })) : null] }));
125
+ }
@@ -0,0 +1,18 @@
1
+ import { type ModelConnection } from './modelConnectionsApi.js';
2
+ type ModelConnectionsPanelProps = {
3
+ workspaceId: string;
4
+ active: boolean;
5
+ runtimeMode: 'local' | 'cloud';
6
+ eligible: boolean;
7
+ cloudAccessAvailable?: boolean;
8
+ cloudAccessPending?: boolean;
9
+ cloudAuthConfigured?: boolean;
10
+ resolveCloudAuthUrl?: (path: string) => string;
11
+ onConnectionActivated?: (connection: ModelConnection) => void | Promise<void>;
12
+ onConnectionUnavailable?: (connectionId: string) => void;
13
+ onReturnToAgent?: () => void;
14
+ pollIntervalMs?: number;
15
+ libraryPortalTarget?: HTMLElement | null;
16
+ };
17
+ export declare function ModelConnectionsPanel({ workspaceId, active, runtimeMode, eligible, cloudAccessAvailable, cloudAccessPending, cloudAuthConfigured, resolveCloudAuthUrl, onConnectionActivated, onConnectionUnavailable, onReturnToAgent, pollIntervalMs, libraryPortalTarget, }: ModelConnectionsPanelProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,393 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { AlertTriangle, Check, CircleSlash, Copy, ExternalLink, Loader2, LogOut, Pencil, Plug, RefreshCw, RotateCcw, Trash2, X, } from 'lucide-react';
5
+ import styles from '../../../Taskforce.module.css';
6
+ import { cancelDeviceCodeLogin, createOpenAiCodexConnection, disconnectModelConnection, getDeviceCodeLogin, listModelConnections, loadModelConnectionsSnapshot, modelConnectionFailureMessage, refreshModelConnection, renameModelConnection, removeModelConnection, startDeviceCodeLogin, verifyModelConnection, } from './modelConnectionsApi.js';
7
+ import managerStyles from '../agentBehavior/AgentBehaviorManagerShared.module.css';
8
+ import { getProductLogoUrl } from '../../../utils/productLogoRegistry.js';
9
+ const LOGIN_POLL_INTERVAL_MS = 1_500;
10
+ const CHATGPT_LOGO_URL = getProductLogoUrl('chatgpt');
11
+ function connectionStatusLabel(status) {
12
+ switch (status) {
13
+ case 'active': return 'Connected';
14
+ case 'pending': return 'Not authorized';
15
+ case 'reconnect_required': return 'Reconnect required';
16
+ case 'revoked': return 'Revoked';
17
+ case 'disconnected': return 'Disconnected';
18
+ default: return 'Unavailable';
19
+ }
20
+ }
21
+ function connectionStatusClass(status) {
22
+ if (status === 'active')
23
+ return 'tf-chip-success';
24
+ if (status === 'pending' || status === 'disconnected')
25
+ return 'tf-chip-neutral';
26
+ if (status === 'reconnect_required')
27
+ return 'tf-chip-warning';
28
+ return 'tf-chip-danger';
29
+ }
30
+ function connectionAccountLabel(connection) {
31
+ return String(connection.displayMetadata.displayName
32
+ || connection.displayMetadata.accountLabel
33
+ || connection.displayMetadata.accountEmail
34
+ || 'ChatGPT subscription');
35
+ }
36
+ function connectionLastChecked(connection) {
37
+ const timestamps = [connection.lastVerifiedAt, connection.lastRefreshedAt]
38
+ .filter((value) => Boolean(value))
39
+ .map((value) => new Date(value))
40
+ .filter((value) => !Number.isNaN(value.getTime()))
41
+ .sort((left, right) => right.getTime() - left.getTime());
42
+ const value = timestamps[0];
43
+ if (!value)
44
+ return 'Not verified yet';
45
+ return `Checked ${value.toLocaleString()}`;
46
+ }
47
+ export function ModelConnectionsPanel({ workspaceId, active, runtimeMode, eligible, cloudAccessAvailable = runtimeMode === 'cloud', cloudAccessPending = false, cloudAuthConfigured = runtimeMode === 'cloud', resolveCloudAuthUrl, onConnectionActivated, onConnectionUnavailable, onReturnToAgent, pollIntervalMs = LOGIN_POLL_INTERVAL_MS, libraryPortalTarget, }) {
48
+ const context = useMemo(() => ({
49
+ workspaceId,
50
+ resolveApiUrl: resolveCloudAuthUrl,
51
+ }), [resolveCloudAuthUrl, workspaceId]);
52
+ const [connections, setConnections] = useState([]);
53
+ const [selectedConnectionId, setSelectedConnectionId] = useState('');
54
+ const [localEligible, setLocalEligible] = useState(runtimeMode === 'local' ? null : eligible);
55
+ const [loading, setLoading] = useState(false);
56
+ const [busyConnectionId, setBusyConnectionId] = useState(null);
57
+ const [login, setLogin] = useState(null);
58
+ const [feedback, setFeedback] = useState(null);
59
+ const [copied, setCopied] = useState(false);
60
+ const [renamingConnectionId, setRenamingConnectionId] = useState(null);
61
+ const [connectionNameDraft, setConnectionNameDraft] = useState('');
62
+ const pollGenerationRef = useRef(0);
63
+ const loadGenerationRef = useRef(0);
64
+ const connectButtonRef = useRef(null);
65
+ const effectiveEligible = runtimeMode === 'local' ? localEligible : eligible;
66
+ const selectedConnection = connections.find((connection) => connection.id === selectedConnectionId) || null;
67
+ const loadConnections = useCallback(async (quiet = false) => {
68
+ if (!cloudAccessAvailable)
69
+ return;
70
+ const generation = ++loadGenerationRef.current;
71
+ if (!quiet)
72
+ setLoading(true);
73
+ try {
74
+ if (runtimeMode === 'local') {
75
+ const snapshot = await loadModelConnectionsSnapshot(context);
76
+ if (generation !== loadGenerationRef.current)
77
+ return;
78
+ setLocalEligible(snapshot.eligible);
79
+ setConnections(snapshot.connections);
80
+ }
81
+ else {
82
+ const next = await listModelConnections(context);
83
+ if (generation !== loadGenerationRef.current)
84
+ return;
85
+ setConnections(next);
86
+ }
87
+ if (!quiet)
88
+ setFeedback(null);
89
+ }
90
+ catch (error) {
91
+ if (generation !== loadGenerationRef.current)
92
+ return;
93
+ const apiError = error;
94
+ setFeedback({ type: 'error', message: apiError.message || 'Unable to load model connections.' });
95
+ }
96
+ finally {
97
+ if (!quiet && generation === loadGenerationRef.current)
98
+ setLoading(false);
99
+ }
100
+ }, [cloudAccessAvailable, context, runtimeMode]);
101
+ useEffect(() => {
102
+ loadGenerationRef.current += 1;
103
+ pollGenerationRef.current += 1;
104
+ setConnections([]);
105
+ setSelectedConnectionId('');
106
+ setLocalEligible(runtimeMode === 'local' ? null : eligible);
107
+ setLoading(false);
108
+ setBusyConnectionId(null);
109
+ setLogin(null);
110
+ setFeedback(null);
111
+ setCopied(false);
112
+ setRenamingConnectionId(null);
113
+ setConnectionNameDraft('');
114
+ }, [cloudAccessAvailable, context, eligible, runtimeMode]);
115
+ useEffect(() => {
116
+ setSelectedConnectionId((current) => {
117
+ if (current && connections.some((connection) => connection.id === current))
118
+ return current;
119
+ return connections.length === 1 ? connections[0].id : '';
120
+ });
121
+ }, [connections]);
122
+ useEffect(() => {
123
+ if (!active || !cloudAccessAvailable || (runtimeMode === 'cloud' && !eligible))
124
+ return;
125
+ void loadConnections();
126
+ }, [active, cloudAccessAvailable, eligible, loadConnections, runtimeMode]);
127
+ useEffect(() => () => {
128
+ pollGenerationRef.current += 1;
129
+ }, []);
130
+ const completeActiveLogin = useCallback(async (current, generation) => {
131
+ if (generation !== pollGenerationRef.current)
132
+ return;
133
+ setLogin(null);
134
+ let nextConnections;
135
+ try {
136
+ nextConnections = await listModelConnections(context);
137
+ }
138
+ catch (error) {
139
+ if (generation !== pollGenerationRef.current)
140
+ return;
141
+ setFeedback({
142
+ type: 'error',
143
+ message: error.message || 'ChatGPT was authorized, but the connection status could not be refreshed.',
144
+ });
145
+ return;
146
+ }
147
+ if (generation !== pollGenerationRef.current)
148
+ return;
149
+ setConnections(nextConnections);
150
+ const activated = nextConnections.find((connection) => connection.id === current.connectionId) || null;
151
+ if (!activated) {
152
+ setFeedback({ type: 'error', message: 'ChatGPT was authorized, but the connection status could not be refreshed.' });
153
+ return;
154
+ }
155
+ setSelectedConnectionId(activated.id);
156
+ try {
157
+ await onConnectionActivated?.(activated);
158
+ }
159
+ catch (error) {
160
+ if (generation !== pollGenerationRef.current)
161
+ return;
162
+ setFeedback({
163
+ type: 'error',
164
+ message: `ChatGPT is connected, but this Agent could not refresh its account selection. ${error.message || 'Return to the Agent and select the account again.'}`,
165
+ returnToAgent: Boolean(onReturnToAgent),
166
+ });
167
+ return;
168
+ }
169
+ if (generation !== pollGenerationRef.current)
170
+ return;
171
+ setFeedback({ type: 'success', message: 'ChatGPT connection authorized.' });
172
+ }, [context, onConnectionActivated, onReturnToAgent]);
173
+ const pollLogin = useCallback(async (initial, generation) => {
174
+ let current = initial;
175
+ while (generation === pollGenerationRef.current && current.status === 'pending') {
176
+ await new Promise((resolve) => window.setTimeout(resolve, pollIntervalMs));
177
+ if (generation !== pollGenerationRef.current)
178
+ return;
179
+ try {
180
+ current = await getDeviceCodeLogin(current.connectionId, current.id, context);
181
+ if (generation !== pollGenerationRef.current)
182
+ return;
183
+ setLogin(current);
184
+ }
185
+ catch (error) {
186
+ if (generation !== pollGenerationRef.current)
187
+ return;
188
+ const apiError = error;
189
+ setFeedback({ type: 'error', message: apiError.message || 'Unable to check device authorization.' });
190
+ return;
191
+ }
192
+ }
193
+ if (generation !== pollGenerationRef.current)
194
+ return;
195
+ if (current.status === 'active') {
196
+ await completeActiveLogin(current, generation);
197
+ return;
198
+ }
199
+ setLogin(null);
200
+ if (current.status !== 'cancelled') {
201
+ setFeedback({ type: 'error', message: modelConnectionFailureMessage(current.failureCode) });
202
+ }
203
+ }, [completeActiveLogin, context, pollIntervalMs]);
204
+ const beginAuthorization = useCallback(async (connection) => {
205
+ const generation = ++pollGenerationRef.current;
206
+ setFeedback(null);
207
+ setCopied(false);
208
+ setBusyConnectionId(connection?.id || 'new');
209
+ try {
210
+ const target = connection || await createOpenAiCodexConnection(context);
211
+ if (generation !== pollGenerationRef.current)
212
+ return;
213
+ setConnections((current) => current.some((item) => item.id === target.id)
214
+ ? current.map((item) => item.id === target.id ? target : item)
215
+ : [target, ...current]);
216
+ setSelectedConnectionId(target.id);
217
+ const nextLogin = await startDeviceCodeLogin(target.id, context);
218
+ if (generation !== pollGenerationRef.current)
219
+ return;
220
+ setLogin(nextLogin);
221
+ window.open(nextLogin.verificationUrl, '_blank', 'noopener,noreferrer');
222
+ void pollLogin(nextLogin, generation);
223
+ }
224
+ catch (error) {
225
+ if (generation !== pollGenerationRef.current)
226
+ return;
227
+ const apiError = error;
228
+ setFeedback({
229
+ type: 'error',
230
+ message: apiError.code
231
+ ? modelConnectionFailureMessage(apiError.code, apiError.message)
232
+ : apiError.message,
233
+ });
234
+ await loadConnections(true);
235
+ }
236
+ finally {
237
+ if (generation === pollGenerationRef.current)
238
+ setBusyConnectionId(null);
239
+ }
240
+ }, [context, loadConnections, pollLogin]);
241
+ const cancelLogin = useCallback(async () => {
242
+ if (!login)
243
+ return;
244
+ const generation = ++pollGenerationRef.current;
245
+ setBusyConnectionId(login.connectionId);
246
+ try {
247
+ const cancelled = await cancelDeviceCodeLogin(login.connectionId, login.id, context);
248
+ if (generation !== pollGenerationRef.current)
249
+ return;
250
+ if (cancelled.status === 'active') {
251
+ await completeActiveLogin(cancelled, generation);
252
+ }
253
+ else if (cancelled.status === 'pending') {
254
+ setLogin(cancelled);
255
+ setBusyConnectionId(null);
256
+ void pollLogin(cancelled, generation);
257
+ }
258
+ else {
259
+ setLogin(null);
260
+ setFeedback(cancelled.status === 'cancelled'
261
+ ? null
262
+ : { type: 'error', message: modelConnectionFailureMessage(cancelled.failureCode) });
263
+ }
264
+ }
265
+ catch (error) {
266
+ if (generation !== pollGenerationRef.current)
267
+ return;
268
+ setFeedback({ type: 'error', message: error.message || 'Unable to cancel authorization.' });
269
+ setBusyConnectionId(null);
270
+ void pollLogin(login, generation);
271
+ }
272
+ finally {
273
+ if (generation === pollGenerationRef.current)
274
+ setBusyConnectionId(null);
275
+ }
276
+ }, [completeActiveLogin, context, login, pollLogin]);
277
+ const copyCode = useCallback(async () => {
278
+ if (!login?.userCode || !navigator.clipboard?.writeText)
279
+ return;
280
+ try {
281
+ await navigator.clipboard.writeText(login.userCode);
282
+ setCopied(true);
283
+ }
284
+ catch {
285
+ setCopied(false);
286
+ }
287
+ }, [login?.userCode]);
288
+ const runConnectionAction = useCallback(async (connection, action) => {
289
+ setBusyConnectionId(connection.id);
290
+ setFeedback(null);
291
+ try {
292
+ if (action === 'disconnect' && !window.confirm('Disconnect this ChatGPT connection? Agents bound to it will be unavailable until you reconnect.'))
293
+ return;
294
+ if (action === 'remove' && !window.confirm('Remove this ChatGPT connection and its stored credentials? This cannot be undone.'))
295
+ return;
296
+ if (action === 'remove') {
297
+ await removeModelConnection(connection.id, context);
298
+ onConnectionUnavailable?.(connection.id);
299
+ setConnections((current) => current.filter((item) => item.id !== connection.id));
300
+ setSelectedConnectionId((current) => current === connection.id ? '' : current);
301
+ setFeedback({ type: 'success', message: 'ChatGPT connection removed.' });
302
+ window.setTimeout(() => connectButtonRef.current?.focus(), 0);
303
+ return;
304
+ }
305
+ const next = action === 'verify'
306
+ ? await verifyModelConnection(connection.id, context)
307
+ : action === 'refresh'
308
+ ? await refreshModelConnection(connection.id, context)
309
+ : await disconnectModelConnection(connection.id, context);
310
+ if (next.lifecycleStatus !== 'active')
311
+ onConnectionUnavailable?.(connection.id);
312
+ setConnections((current) => current.map((item) => item.id === next.id ? next : item));
313
+ setFeedback({
314
+ type: 'success',
315
+ message: action === 'disconnect' ? 'ChatGPT connection disconnected.' : 'ChatGPT connection verified.',
316
+ });
317
+ }
318
+ catch (error) {
319
+ const apiError = error;
320
+ setFeedback({
321
+ type: 'error',
322
+ message: apiError.code
323
+ ? modelConnectionFailureMessage(apiError.code, apiError.message)
324
+ : apiError.message,
325
+ });
326
+ }
327
+ finally {
328
+ setBusyConnectionId(null);
329
+ }
330
+ }, [context, onConnectionUnavailable]);
331
+ const saveConnectionName = useCallback(async (connection) => {
332
+ const displayName = connectionNameDraft.trim();
333
+ if (!displayName || busyConnectionId)
334
+ return;
335
+ setBusyConnectionId(connection.id);
336
+ setFeedback(null);
337
+ try {
338
+ const next = await renameModelConnection(connection.id, displayName, context);
339
+ setConnections((current) => current.map((item) => item.id === next.id ? next : item));
340
+ setRenamingConnectionId(null);
341
+ setConnectionNameDraft('');
342
+ setFeedback({ type: 'success', message: 'Model account renamed.' });
343
+ }
344
+ catch (error) {
345
+ setFeedback({ type: 'error', message: error.message || 'Unable to rename this model account.' });
346
+ }
347
+ finally {
348
+ setBusyConnectionId(null);
349
+ }
350
+ }, [busyConnectionId, connectionNameDraft, context]);
351
+ const connectionLibrary = (_jsxs("div", { className: `${managerStyles.library} ${libraryPortalTarget ? managerStyles.libraryExternal : ''}`.trim(), "aria-label": "Connection list", children: [cloudAccessAvailable && effectiveEligible === true ? (_jsxs("button", { ref: connectButtonRef, type: "button", className: "tf-button-primary tf-button-compact", onClick: () => { void beginAuthorization(); }, disabled: Boolean(busyConnectionId || login), children: [busyConnectionId === 'new' ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(Plug, { size: 14 }), "Connect ChatGPT"] })) : null, _jsx("div", { className: managerStyles.libraryList, "aria-busy": loading, children: !cloudAccessAvailable ? (_jsxs("div", { className: managerStyles.libraryState, children: [_jsx(CircleSlash, { size: 18 }), _jsx("span", { children: cloudAccessPending ? 'Checking Taskforce Cloud sign-in…' : 'Taskforce Cloud sign-in required.' })] })) : effectiveEligible === false ? (_jsxs("div", { className: managerStyles.libraryState, children: [_jsx(CircleSlash, { size: 18 }), _jsx("span", { children: "Connected accounts are not enabled." })] })) : effectiveEligible === null || loading ? (_jsxs("div", { className: managerStyles.libraryState, children: [_jsx(Loader2, { size: 16, className: styles.spinner }), _jsx("span", { children: "Loading connections\u2026" })] })) : connections.length === 0 ? (_jsxs("div", { className: managerStyles.libraryState, children: [_jsx(Plug, { size: 18 }), _jsx("span", { children: "No connections yet." })] })) : connections.map((connection) => {
352
+ const selected = connection.id === selectedConnectionId;
353
+ return (_jsxs("button", { type: "button", className: `${managerStyles.libraryCard} ${selected ? managerStyles.libraryCardSelected : ''}`.trim(), "aria-pressed": selected, "aria-label": `Open ${connectionAccountLabel(connection)}`, onClick: () => {
354
+ setSelectedConnectionId(connection.id);
355
+ setRenamingConnectionId(null);
356
+ setConnectionNameDraft('');
357
+ }, children: [_jsx("span", { className: `${managerStyles.libraryCardIcon} ${managerStyles.libraryCardLogo}`.trim(), "aria-hidden": "true", children: _jsx("img", { src: CHATGPT_LOGO_URL, alt: "" }) }), _jsxs("span", { className: managerStyles.libraryCardBody, children: [_jsx("strong", { children: connectionAccountLabel(connection) }), _jsxs("span", { children: ["OpenAI \u00B7 ", connection.displayMetadata.planLabel || 'ChatGPT'] })] }), _jsx("span", { className: connectionStatusClass(connection.lifecycleStatus), children: connectionStatusLabel(connection.lifecycleStatus) })] }, connection.id));
358
+ }) })] }));
359
+ let mainContent;
360
+ if (!cloudAccessAvailable) {
361
+ mainContent = (_jsxs("div", { className: styles.taskforceModelConnectionsEmpty, children: [_jsx(CircleSlash, { size: 28 }), _jsx("strong", { children: cloudAccessPending ? 'Checking Taskforce Cloud sign-in' : cloudAuthConfigured ? 'Taskforce Cloud sign-in required' : 'Taskforce Cloud connection required' }), _jsx("span", { children: cloudAccessPending
362
+ ? 'Connection management will be available after your sign-in status is resolved.'
363
+ : cloudAuthConfigured
364
+ ? 'Sign in to Taskforce Cloud to manage connected model accounts from this local runtime.'
365
+ : 'Connect this local runtime to a Taskforce Cloud environment to manage connected model accounts.' })] }));
366
+ }
367
+ else if (effectiveEligible === false) {
368
+ mainContent = (_jsxs("div", { className: styles.taskforceModelConnectionsEmpty, children: [_jsx(CircleSlash, { size: 28 }), _jsx("strong", { children: "Connected accounts are not enabled" }), _jsx("span", { children: "Contact a Taskforce administrator to enable subscription-backed models for this account." })] }));
369
+ }
370
+ else if (effectiveEligible === null) {
371
+ mainContent = feedback?.type === 'error' ? (_jsxs("div", { className: styles.taskforceAgentTestError, role: "alert", children: [_jsx(AlertTriangle, { size: 14 }), _jsx("span", { children: feedback.message }), _jsxs("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => { void loadConnections(); }, disabled: loading, children: [_jsx(RefreshCw, { size: 14 }), " Retry"] })] })) : (_jsxs("div", { className: styles.taskforceModelConnectionsLoading, children: [_jsx(Loader2, { size: 18, className: styles.spinner }), " Checking connection access"] }));
372
+ }
373
+ else {
374
+ const connection = selectedConnection;
375
+ const busy = connection ? busyConnectionId === connection.id : false;
376
+ const canAuthorize = connection?.lifecycleStatus === 'pending'
377
+ || connection?.lifecycleStatus === 'reconnect_required'
378
+ || connection?.lifecycleStatus === 'disconnected';
379
+ mainContent = (_jsxs(_Fragment, { children: [_jsx("header", { className: styles.taskforceModelConnectionsHeader, children: _jsxs("div", { children: [_jsx("span", { className: "tf-heading-section", children: login ? 'Add connection' : connection ? 'Connection details' : 'Connections' }), _jsx("p", { className: "tf-text-secondary", children: "Authorize accounts used by your Taskforce Agents in this environment." })] }) }), feedback ? (_jsxs("div", { className: feedback.type === 'error' ? styles.taskforceAgentTestError : styles.taskforceAgentTestNotice, role: feedback.type === 'error' ? 'alert' : 'status', children: [feedback.type === 'error' ? _jsx(AlertTriangle, { size: 14 }) : _jsx(Check, { size: 14 }), _jsx("span", { children: feedback.message }), feedback.returnToAgent ? (_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: onReturnToAgent, children: "Return to Agent" })) : null] })) : null, login ? (_jsxs("section", { className: `${styles.taskforceModelConnectionCard} ${styles.taskforceModelConnectionLogin}`, children: [_jsxs("div", { className: styles.taskforceModelConnectionCardHeader, children: [_jsxs("div", { children: [_jsx("strong", { children: "Authorize ChatGPT" }), _jsx("span", { children: "Enter this one-time code in the browser window." })] }), _jsxs("span", { className: "tf-chip-warning", children: [_jsx(Loader2, { size: 12, className: styles.spinner }), " Waiting"] })] }), _jsxs("div", { className: styles.taskforceModelConnectionCodeRow, children: [_jsx("code", { children: login.userCode }), _jsx("button", { type: "button", className: "tf-control-icon", onClick: () => { void copyCode(); }, title: copied ? 'Authorization code copied' : 'Copy authorization code', "aria-label": copied ? 'Authorization code copied' : 'Copy authorization code', children: copied ? _jsx(Check, { size: 15 }) : _jsx(Copy, { size: 15 }) }), _jsx("span", { role: "status", "aria-live": "polite", children: copied ? 'Code copied.' : '' }), _jsxs("a", { className: "tf-button-secondary tf-button-compact", href: login.verificationUrl, target: "_blank", rel: "noreferrer", children: [_jsx(ExternalLink, { size: 14 }), " Open ChatGPT"] }), _jsxs("button", { type: "button", className: "tf-button-ghost tf-button-compact", onClick: () => { void cancelLogin(); }, children: [_jsx(X, { size: 14 }), " Cancel"] })] })] })) : loading ? (_jsxs("div", { className: styles.taskforceModelConnectionsLoading, children: [_jsx(Loader2, { size: 18, className: styles.spinner }), " Loading connections"] })) : !connection ? (_jsxs("div", { className: styles.taskforceModelConnectionsEmpty, children: [_jsx(Plug, { size: 28 }), _jsx("strong", { children: connections.length === 0 ? 'No connected accounts' : 'Select a connection' }), _jsx("span", { children: connections.length === 0
380
+ ? 'Connect ChatGPT to run eligible Codex Agents with your subscription.'
381
+ : 'Choose an account from the Connection Library to view and manage it.' })] })) : (_jsxs("section", { className: styles.taskforceModelConnectionCard, children: [_jsxs("div", { className: styles.taskforceModelConnectionCardHeader, children: [_jsxs("div", { className: styles.taskforceModelConnectionIdentity, children: [_jsx("span", { className: styles.taskforceModelConnectionLogo, children: _jsx("img", { src: CHATGPT_LOGO_URL, alt: "" }) }), _jsxs("div", { className: styles.taskforceModelConnectionIdentityText, children: [renamingConnectionId === connection.id ? (_jsxs("div", { className: styles.taskforceModelConnectionNameEditor, children: [_jsx("input", { className: styles.input, value: connectionNameDraft, onChange: (event) => setConnectionNameDraft(event.target.value), "aria-label": "Model account name", maxLength: 80, autoFocus: true }), _jsx("button", { type: "button", className: "tf-control-icon", "aria-label": "Save model account name", title: "Save name", onClick: () => { void saveConnectionName(connection); }, disabled: busy || !connectionNameDraft.trim(), children: busy ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(Check, { size: 14 }) }), _jsx("button", { type: "button", className: "tf-control-icon", "aria-label": "Cancel model account rename", title: "Cancel", onClick: () => {
382
+ setRenamingConnectionId(null);
383
+ setConnectionNameDraft('');
384
+ }, disabled: busy, children: _jsx(X, { size: 14 }) })] })) : (_jsxs("div", { className: styles.taskforceModelConnectionNameRow, children: [_jsx("strong", { children: connectionAccountLabel(connection) }), _jsx("button", { type: "button", className: "tf-control-icon", "aria-label": `Rename ${connectionAccountLabel(connection)}`, title: "Rename model account", onClick: () => {
385
+ setRenamingConnectionId(connection.id);
386
+ setConnectionNameDraft(connectionAccountLabel(connection));
387
+ }, children: _jsx(Pencil, { size: 13 }) })] })), _jsx("span", { children: "OpenAI \u00B7 ChatGPT/Codex subscription" })] })] }), _jsx("span", { className: connectionStatusClass(connection.lifecycleStatus), children: connectionStatusLabel(connection.lifecycleStatus) })] }), _jsxs("div", { className: styles.taskforceModelConnectionMeta, children: [_jsx("span", { children: connection.displayMetadata.planLabel || 'Subscription plan' }), _jsx("span", { children: connectionLastChecked(connection) })] }), connection.failureCode ? (_jsx("span", { className: "tf-text-warning", children: modelConnectionFailureMessage(connection.failureCode) })) : null, _jsxs("div", { className: styles.taskforceModelConnectionActions, children: [canAuthorize ? (_jsxs("button", { type: "button", className: "tf-button-primary tf-button-compact", onClick: () => { void beginAuthorization(connection); }, disabled: Boolean(busyConnectionId || login), children: [busy ? _jsx(Loader2, { size: 14, className: styles.spinner }) : _jsx(RotateCcw, { size: 14 }), connection.lifecycleStatus === 'pending' ? 'Authorize' : 'Reconnect'] })) : null, connection.lifecycleStatus === 'active' ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => { void runConnectionAction(connection, 'verify'); }, disabled: busy, children: [_jsx(Check, { size: 14 }), " Verify"] }), _jsxs("button", { type: "button", className: "tf-button-ghost tf-button-compact", onClick: () => { void runConnectionAction(connection, 'refresh'); }, disabled: busy, title: "Refresh ChatGPT account status", children: [_jsx(RefreshCw, { size: 14 }), " Refresh"] }), _jsxs("button", { type: "button", className: "tf-button-ghost tf-button-compact", onClick: () => { void runConnectionAction(connection, 'disconnect'); }, disabled: busy, children: [_jsx(LogOut, { size: 14 }), " Disconnect"] })] })) : null, (connection.lifecycleStatus === 'pending'
388
+ || connection.lifecycleStatus === 'reconnect_required'
389
+ || connection.lifecycleStatus === 'disconnected'
390
+ || connection.lifecycleStatus === 'revoked') ? (_jsxs("button", { type: "button", className: "tf-button-destructive tf-button-compact", onClick: () => { void runConnectionAction(connection, 'remove'); }, disabled: busy, children: [_jsx(Trash2, { size: 14 }), " Remove"] })) : null] })] }))] }));
391
+ }
392
+ return (_jsxs("div", { className: `${styles.taskforceModelConnectionsRoot} ${libraryPortalTarget ? styles.taskforceModelConnectionsRootExternalLibrary : ''}`.trim(), children: [libraryPortalTarget ? createPortal(connectionLibrary, libraryPortalTarget) : connectionLibrary, _jsx("div", { className: styles.taskforceModelConnectionsWorkspace, children: mainContent })] }));
393
+ }