@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
@@ -0,0 +1,99 @@
1
+ import type { DatabaseAdapter } from './databaseAdapter.js';
2
+ export type ModelProviderConnectionLifecycleStatus = 'pending' | 'active' | 'reconnect_required' | 'disconnected' | 'revoked';
3
+ export interface ModelProviderConnectionDisplayMetadata {
4
+ displayName?: string;
5
+ accountLabel?: string;
6
+ accountEmail?: string;
7
+ planLabel?: string;
8
+ }
9
+ export interface ModelProviderConnectionRecord {
10
+ id: string;
11
+ tenantId: string;
12
+ ownerUserId: string;
13
+ providerKey: string;
14
+ authenticationType: string;
15
+ lifecycleStatus: ModelProviderConnectionLifecycleStatus;
16
+ displayMetadata: ModelProviderConnectionDisplayMetadata;
17
+ credentialHomeRef: string;
18
+ lastVerifiedAt: string | null;
19
+ lastRefreshedAt: string | null;
20
+ lastFailureAt: string | null;
21
+ failureCode: string | null;
22
+ disconnectedAt: string | null;
23
+ revokedAt: string | null;
24
+ createdAt: string;
25
+ updatedAt: string;
26
+ }
27
+ export interface ModelProviderConnectionLease {
28
+ connectionId: string;
29
+ token: string;
30
+ operation: string;
31
+ acquiredAt: string;
32
+ expiresAt: string;
33
+ }
34
+ export declare class ModelProviderConnectionError extends Error {
35
+ readonly statusCode: number;
36
+ readonly code: string;
37
+ constructor(message: string, statusCode: number, code: string);
38
+ }
39
+ export declare function sanitizeModelProviderConnectionDisplayMetadata(value: unknown): ModelProviderConnectionDisplayMetadata;
40
+ export declare class ModelProviderConnectionStore {
41
+ private readonly db;
42
+ private readonly tenantId;
43
+ private readonly now;
44
+ constructor(db: DatabaseAdapter, tenantId: string, now?: () => Date);
45
+ private leaseNow;
46
+ private leaseClockPredicate;
47
+ create(input: {
48
+ ownerUserId: string;
49
+ providerKey: string;
50
+ authenticationType: string;
51
+ displayMetadata?: unknown;
52
+ }): ModelProviderConnectionRecord;
53
+ listOwned(ownerUserIdRaw: string): ModelProviderConnectionRecord[];
54
+ getOwned(ownerUserIdRaw: string, connectionIdRaw: string): ModelProviderConnectionRecord | null;
55
+ requireOwned(ownerUserId: string, connectionId: string): ModelProviderConnectionRecord;
56
+ renameOwned(ownerUserId: string, connectionId: string, displayNameRaw: unknown): ModelProviderConnectionRecord;
57
+ requireOwnedUnderLease(ownerUserId: string, connectionId: string, leaseToken: string): ModelProviderConnectionRecord;
58
+ deletePendingOwned(ownerUserId: string, connectionId: string): boolean;
59
+ acquireLease(input: {
60
+ ownerUserId: string;
61
+ connectionId: string;
62
+ operation: string;
63
+ durationMs?: number;
64
+ }): ModelProviderConnectionLease;
65
+ renewLease(lease: ModelProviderConnectionLease, durationMs?: number): boolean;
66
+ releaseLease(lease: ModelProviderConnectionLease): boolean;
67
+ completeLease(lease: ModelProviderConnectionLease): boolean;
68
+ deleteCleanableUnderLease(input: {
69
+ ownerUserId: string;
70
+ connectionId: string;
71
+ leaseToken: string;
72
+ }): boolean;
73
+ markVerified(input: {
74
+ ownerUserId: string;
75
+ connectionId: string;
76
+ leaseToken: string;
77
+ displayMetadata?: unknown;
78
+ }): ModelProviderConnectionRecord;
79
+ markRefreshed(input: {
80
+ ownerUserId: string;
81
+ connectionId: string;
82
+ leaseToken: string;
83
+ displayMetadata?: unknown;
84
+ }): ModelProviderConnectionRecord;
85
+ markReconnectRequired(input: {
86
+ ownerUserId: string;
87
+ connectionId: string;
88
+ leaseToken: string;
89
+ failureCode: string;
90
+ }): ModelProviderConnectionRecord;
91
+ markDisconnected(input: {
92
+ ownerUserId: string;
93
+ connectionId: string;
94
+ leaseToken: string;
95
+ }): ModelProviderConnectionRecord;
96
+ private updateUnderLease;
97
+ private updateUnderLeaseTransaction;
98
+ private insertEvent;
99
+ }
@@ -0,0 +1,446 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ export class ModelProviderConnectionError extends Error {
3
+ statusCode;
4
+ code;
5
+ constructor(message, statusCode, code) {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.code = code;
9
+ this.name = 'ModelProviderConnectionError';
10
+ }
11
+ }
12
+ const SAFE_METADATA_KEYS = ['accountLabel', 'accountEmail', 'planLabel'];
13
+ const MAX_DISPLAY_NAME_LENGTH = 80;
14
+ const POSTGRES_LEASE_CLOCK_SQL = `TO_CHAR(
15
+ clock_timestamp() AT TIME ZONE 'UTC',
16
+ 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'
17
+ )`;
18
+ const POSTGRES_LEASE_EXPIRY_SQL = `TO_CHAR(
19
+ (clock_timestamp() + (CAST(? AS BIGINT) * INTERVAL '1 millisecond')) AT TIME ZONE 'UTC',
20
+ 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'
21
+ )`;
22
+ function randomOpaqueId(prefix) {
23
+ return `${prefix}_${randomBytes(24).toString('base64url')}`;
24
+ }
25
+ function normalizeIdentifier(value, label) {
26
+ const normalized = String(value || '').trim().toLowerCase();
27
+ if (!/^[a-z][a-z0-9._-]{0,63}$/.test(normalized)) {
28
+ throw new ModelProviderConnectionError(`${label} is invalid.`, 400, 'MODEL_CONNECTION_INVALID_INPUT');
29
+ }
30
+ return normalized;
31
+ }
32
+ export function sanitizeModelProviderConnectionDisplayMetadata(value) {
33
+ if (!value || typeof value !== 'object' || Array.isArray(value))
34
+ return {};
35
+ const source = value;
36
+ const result = {};
37
+ for (const key of SAFE_METADATA_KEYS) {
38
+ const normalized = typeof source[key] === 'string'
39
+ ? String(source[key]).trim().slice(0, 200)
40
+ : '';
41
+ const sanitized = normalized
42
+ .replace(/sk-[A-Za-z0-9_-]{8,}/g, '[redacted]')
43
+ .replace(/(Bearer\s+)[^\s]+/gi, '$1[redacted]')
44
+ .replace(/\beyJ[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\b/g, '[redacted]');
45
+ if (sanitized)
46
+ result[key] = sanitized;
47
+ }
48
+ return result;
49
+ }
50
+ function normalizeDisplayName(value) {
51
+ if (typeof value !== 'string') {
52
+ throw new ModelProviderConnectionError('Display name must be a nonempty string of at most 80 characters.', 400, 'MODEL_CONNECTION_INVALID_DISPLAY_NAME');
53
+ }
54
+ const displayName = value.trim();
55
+ if (!displayName || displayName.length > MAX_DISPLAY_NAME_LENGTH) {
56
+ throw new ModelProviderConnectionError('Display name must be a nonempty string of at most 80 characters.', 400, 'MODEL_CONNECTION_INVALID_DISPLAY_NAME');
57
+ }
58
+ return displayName;
59
+ }
60
+ function parseDisplayMetadata(value) {
61
+ try {
62
+ const parsed = JSON.parse(String(value || '{}'));
63
+ const metadata = sanitizeModelProviderConnectionDisplayMetadata(parsed);
64
+ if (typeof parsed.displayName === 'string') {
65
+ const displayName = parsed.displayName.trim().slice(0, MAX_DISPLAY_NAME_LENGTH);
66
+ if (displayName)
67
+ metadata.displayName = displayName;
68
+ }
69
+ return metadata;
70
+ }
71
+ catch {
72
+ return {};
73
+ }
74
+ }
75
+ function mapRow(row) {
76
+ const status = String(row.lifecycle_status || 'pending');
77
+ return {
78
+ id: String(row.id || ''),
79
+ tenantId: String(row.tenant_id || 'default'),
80
+ ownerUserId: String(row.owner_user_id || ''),
81
+ providerKey: String(row.provider_key || ''),
82
+ authenticationType: String(row.authentication_type || ''),
83
+ lifecycleStatus: status,
84
+ displayMetadata: parseDisplayMetadata(row.display_metadata_json),
85
+ credentialHomeRef: String(row.credential_home_ref || ''),
86
+ lastVerifiedAt: row.last_verified_at ? String(row.last_verified_at) : null,
87
+ lastRefreshedAt: row.last_refreshed_at ? String(row.last_refreshed_at) : null,
88
+ lastFailureAt: row.last_failure_at ? String(row.last_failure_at) : null,
89
+ failureCode: row.failure_code ? String(row.failure_code) : null,
90
+ disconnectedAt: row.disconnected_at ? String(row.disconnected_at) : null,
91
+ revokedAt: row.revoked_at ? String(row.revoked_at) : null,
92
+ createdAt: String(row.created_at || ''),
93
+ updatedAt: String(row.updated_at || ''),
94
+ };
95
+ }
96
+ export class ModelProviderConnectionStore {
97
+ db;
98
+ tenantId;
99
+ now;
100
+ constructor(db, tenantId, now = () => new Date()) {
101
+ this.db = db;
102
+ this.tenantId = tenantId;
103
+ this.now = now;
104
+ }
105
+ leaseNow() {
106
+ if (this.db.provider === 'sqlite')
107
+ return this.now();
108
+ const row = this.db.prepare(`
109
+ SELECT ${POSTGRES_LEASE_CLOCK_SQL} AS current_time
110
+ `).get();
111
+ const currentTime = new Date(String(row?.current_time || ''));
112
+ if (Number.isNaN(currentTime.getTime())) {
113
+ throw new Error('[Taskforce] PostgreSQL did not return a valid lease clock value.');
114
+ }
115
+ return currentTime;
116
+ }
117
+ leaseClockPredicate(nowIso) {
118
+ return this.db.provider === 'postgres'
119
+ ? { sql: POSTGRES_LEASE_CLOCK_SQL, params: [] }
120
+ : { sql: '?', params: [nowIso] };
121
+ }
122
+ create(input) {
123
+ const ownerUserId = String(input.ownerUserId || '').trim();
124
+ if (!ownerUserId) {
125
+ throw new ModelProviderConnectionError('Authentication is required.', 401, 'AUTH_REQUIRED');
126
+ }
127
+ const providerKey = normalizeIdentifier(input.providerKey, 'Provider key');
128
+ const authenticationType = normalizeIdentifier(input.authenticationType, 'Authentication type');
129
+ const id = randomOpaqueId('mpc');
130
+ const credentialHomeRef = randomOpaqueId('home');
131
+ const now = this.now().toISOString();
132
+ const displayMetadata = sanitizeModelProviderConnectionDisplayMetadata(input.displayMetadata);
133
+ this.db.transaction(() => {
134
+ this.db.prepare(`
135
+ INSERT INTO model_provider_connections (
136
+ id, tenant_id, owner_user_id, provider_key, authentication_type,
137
+ lifecycle_status, display_metadata_json, credential_home_ref,
138
+ created_at, updated_at
139
+ ) VALUES (?, ?, ?, ?, ?, 'pending', ?, ?, ?, ?)
140
+ `).run(id, this.tenantId, ownerUserId, providerKey, authenticationType, JSON.stringify(displayMetadata), credentialHomeRef, now, now);
141
+ this.insertEvent({
142
+ connectionId: id,
143
+ ownerUserId,
144
+ actorUserId: ownerUserId,
145
+ eventType: 'created',
146
+ outcome: 'success',
147
+ createdAt: now,
148
+ });
149
+ })();
150
+ return this.requireOwned(ownerUserId, id);
151
+ }
152
+ listOwned(ownerUserIdRaw) {
153
+ const ownerUserId = String(ownerUserIdRaw || '').trim();
154
+ if (!ownerUserId)
155
+ return [];
156
+ const rows = this.db.prepare(`
157
+ SELECT *
158
+ FROM model_provider_connections
159
+ WHERE tenant_id = ? AND owner_user_id = ?
160
+ ORDER BY created_at ASC, id ASC
161
+ `).all(this.tenantId, ownerUserId);
162
+ return rows.map(mapRow);
163
+ }
164
+ getOwned(ownerUserIdRaw, connectionIdRaw) {
165
+ const ownerUserId = String(ownerUserIdRaw || '').trim();
166
+ const connectionId = String(connectionIdRaw || '').trim();
167
+ if (!ownerUserId || !connectionId)
168
+ return null;
169
+ const row = this.db.prepare(`
170
+ SELECT *
171
+ FROM model_provider_connections
172
+ WHERE tenant_id = ? AND owner_user_id = ? AND id = ?
173
+ LIMIT 1
174
+ `).get(this.tenantId, ownerUserId, connectionId);
175
+ return row ? mapRow(row) : null;
176
+ }
177
+ requireOwned(ownerUserId, connectionId) {
178
+ const connection = this.getOwned(ownerUserId, connectionId);
179
+ if (!connection) {
180
+ throw new ModelProviderConnectionError('Model connection was not found.', 404, 'MODEL_CONNECTION_NOT_FOUND');
181
+ }
182
+ return connection;
183
+ }
184
+ renameOwned(ownerUserId, connectionId, displayNameRaw) {
185
+ const displayName = normalizeDisplayName(displayNameRaw);
186
+ return this.db.transaction(() => {
187
+ const current = this.requireOwned(ownerUserId, connectionId);
188
+ const now = this.now().toISOString();
189
+ const result = this.db.prepare(`
190
+ UPDATE model_provider_connections
191
+ SET display_metadata_json = ?, updated_at = ?
192
+ WHERE tenant_id = ? AND owner_user_id = ? AND id = ?
193
+ `).run(JSON.stringify({ ...current.displayMetadata, displayName }), now, this.tenantId, ownerUserId, connectionId);
194
+ if (Number(result?.changes || 0) !== 1) {
195
+ throw new ModelProviderConnectionError('Model connection was not found.', 404, 'MODEL_CONNECTION_NOT_FOUND');
196
+ }
197
+ this.insertEvent({
198
+ connectionId,
199
+ ownerUserId,
200
+ actorUserId: ownerUserId,
201
+ eventType: 'renamed',
202
+ outcome: 'success',
203
+ createdAt: now,
204
+ });
205
+ return this.requireOwned(ownerUserId, connectionId);
206
+ })();
207
+ }
208
+ requireOwnedUnderLease(ownerUserId, connectionId, leaseToken) {
209
+ const now = this.leaseNow().toISOString();
210
+ const clock = this.leaseClockPredicate(now);
211
+ const row = this.db.prepare(`
212
+ SELECT connection.*
213
+ FROM model_provider_connections connection
214
+ WHERE connection.tenant_id = ? AND connection.owner_user_id = ? AND connection.id = ?
215
+ AND EXISTS (
216
+ SELECT 1 FROM model_provider_connection_leases lease
217
+ WHERE lease.tenant_id = connection.tenant_id
218
+ AND lease.connection_id = connection.id
219
+ AND lease.lease_token = ?
220
+ AND lease.expires_at > ${clock.sql}
221
+ )
222
+ LIMIT 1
223
+ `).get(this.tenantId, ownerUserId, connectionId, leaseToken, ...clock.params);
224
+ if (!row) {
225
+ throw new ModelProviderConnectionError('Model connection operation lease is no longer valid.', 409, 'MODEL_CONNECTION_LEASE_LOST');
226
+ }
227
+ return mapRow(row);
228
+ }
229
+ deletePendingOwned(ownerUserId, connectionId) {
230
+ return this.db.transaction(() => {
231
+ const result = this.db.prepare(`
232
+ DELETE FROM model_provider_connections
233
+ WHERE tenant_id = ? AND owner_user_id = ? AND id = ? AND lifecycle_status = 'pending'
234
+ `).run(this.tenantId, ownerUserId, connectionId);
235
+ if (Number(result?.changes || 0) === 1) {
236
+ this.db.prepare(`
237
+ DELETE FROM model_provider_connection_events
238
+ WHERE tenant_id = ? AND connection_id = ?
239
+ `).run(this.tenantId, connectionId);
240
+ return true;
241
+ }
242
+ return false;
243
+ })();
244
+ }
245
+ acquireLease(input) {
246
+ this.requireOwned(input.ownerUserId, input.connectionId);
247
+ const operation = normalizeIdentifier(input.operation, 'Connection operation');
248
+ const durationMs = Math.min(10 * 60_000, Math.max(1_000, input.durationMs ?? 120_000));
249
+ const token = randomOpaqueId('lease');
250
+ if (this.db.provider === 'postgres') {
251
+ const row = this.db.prepare(`
252
+ INSERT INTO model_provider_connection_leases (
253
+ tenant_id, connection_id, lease_token, operation, acquired_at, expires_at, updated_at
254
+ ) VALUES (
255
+ ?, ?, ?, ?, ${POSTGRES_LEASE_CLOCK_SQL}, ${POSTGRES_LEASE_EXPIRY_SQL}, ${POSTGRES_LEASE_CLOCK_SQL}
256
+ )
257
+ ON CONFLICT (tenant_id, connection_id) DO UPDATE SET
258
+ lease_token = excluded.lease_token,
259
+ operation = excluded.operation,
260
+ acquired_at = ${POSTGRES_LEASE_CLOCK_SQL},
261
+ expires_at = ${POSTGRES_LEASE_EXPIRY_SQL},
262
+ updated_at = ${POSTGRES_LEASE_CLOCK_SQL}
263
+ WHERE model_provider_connection_leases.expires_at <= ${POSTGRES_LEASE_CLOCK_SQL}
264
+ RETURNING acquired_at, expires_at
265
+ `).get(this.tenantId, input.connectionId, token, operation, durationMs, durationMs);
266
+ if (!row) {
267
+ throw new ModelProviderConnectionError('Model connection is busy. Try again shortly.', 409, 'MODEL_CONNECTION_BUSY');
268
+ }
269
+ return {
270
+ connectionId: input.connectionId,
271
+ token,
272
+ operation,
273
+ acquiredAt: String(row.acquired_at || ''),
274
+ expiresAt: String(row.expires_at || ''),
275
+ };
276
+ }
277
+ const acquiredAt = this.leaseNow();
278
+ const acquiredAtIso = acquiredAt.toISOString();
279
+ const expiresAt = new Date(acquiredAt.getTime() + durationMs).toISOString();
280
+ const result = this.db.prepare(`
281
+ INSERT INTO model_provider_connection_leases (
282
+ tenant_id, connection_id, lease_token, operation, acquired_at, expires_at, updated_at
283
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
284
+ ON CONFLICT (tenant_id, connection_id) DO UPDATE SET
285
+ lease_token = excluded.lease_token,
286
+ operation = excluded.operation,
287
+ acquired_at = excluded.acquired_at,
288
+ expires_at = excluded.expires_at,
289
+ updated_at = excluded.updated_at
290
+ WHERE model_provider_connection_leases.expires_at <= excluded.acquired_at
291
+ `).run(this.tenantId, input.connectionId, token, operation, acquiredAtIso, expiresAt, acquiredAtIso);
292
+ if (Number(result?.changes || 0) !== 1) {
293
+ throw new ModelProviderConnectionError('Model connection is busy. Try again shortly.', 409, 'MODEL_CONNECTION_BUSY');
294
+ }
295
+ return { connectionId: input.connectionId, token, operation, acquiredAt: acquiredAtIso, expiresAt };
296
+ }
297
+ renewLease(lease, durationMs = 120_000) {
298
+ const boundedDurationMs = Math.min(10 * 60_000, Math.max(1_000, durationMs));
299
+ if (this.db.provider === 'postgres') {
300
+ const row = this.db.prepare(`
301
+ UPDATE model_provider_connection_leases
302
+ SET expires_at = ${POSTGRES_LEASE_EXPIRY_SQL},
303
+ updated_at = ${POSTGRES_LEASE_CLOCK_SQL}
304
+ WHERE tenant_id = ? AND connection_id = ? AND lease_token = ?
305
+ AND expires_at > ${POSTGRES_LEASE_CLOCK_SQL}
306
+ RETURNING expires_at
307
+ `).get(boundedDurationMs, this.tenantId, lease.connectionId, lease.token);
308
+ return Boolean(row);
309
+ }
310
+ const now = this.leaseNow();
311
+ const nowIso = now.toISOString();
312
+ const expiresAt = new Date(now.getTime() + boundedDurationMs).toISOString();
313
+ const clock = this.leaseClockPredicate(nowIso);
314
+ const result = this.db.prepare(`
315
+ UPDATE model_provider_connection_leases
316
+ SET expires_at = ?, updated_at = ?
317
+ WHERE tenant_id = ? AND connection_id = ? AND lease_token = ? AND expires_at > ${clock.sql}
318
+ `).run(expiresAt, nowIso, this.tenantId, lease.connectionId, lease.token, ...clock.params);
319
+ return Number(result?.changes || 0) === 1;
320
+ }
321
+ releaseLease(lease) {
322
+ const result = this.db.prepare(`
323
+ DELETE FROM model_provider_connection_leases
324
+ WHERE tenant_id = ? AND connection_id = ? AND lease_token = ?
325
+ `).run(this.tenantId, lease.connectionId, lease.token);
326
+ return Number(result?.changes || 0) === 1;
327
+ }
328
+ completeLease(lease) {
329
+ const now = this.leaseNow().toISOString();
330
+ const clock = this.leaseClockPredicate(now);
331
+ const result = this.db.prepare(`
332
+ DELETE FROM model_provider_connection_leases
333
+ WHERE tenant_id = ? AND connection_id = ? AND lease_token = ? AND expires_at > ${clock.sql}
334
+ `).run(this.tenantId, lease.connectionId, lease.token, ...clock.params);
335
+ return Number(result?.changes || 0) === 1;
336
+ }
337
+ deleteCleanableUnderLease(input) {
338
+ return this.db.transaction(() => {
339
+ const now = this.leaseNow().toISOString();
340
+ const clock = this.leaseClockPredicate(now);
341
+ const result = this.db.prepare(`
342
+ DELETE FROM model_provider_connections
343
+ WHERE tenant_id = ? AND owner_user_id = ? AND id = ?
344
+ AND lifecycle_status IN ('pending', 'reconnect_required', 'disconnected', 'revoked')
345
+ AND EXISTS (
346
+ SELECT 1 FROM model_provider_connection_leases lease
347
+ WHERE lease.tenant_id = model_provider_connections.tenant_id
348
+ AND lease.connection_id = model_provider_connections.id
349
+ AND lease.lease_token = ?
350
+ AND lease.expires_at > ${clock.sql}
351
+ )
352
+ `).run(this.tenantId, input.ownerUserId, input.connectionId, input.leaseToken, ...clock.params);
353
+ if (Number(result?.changes || 0) !== 1)
354
+ return false;
355
+ this.insertEvent({
356
+ connectionId: input.connectionId,
357
+ ownerUserId: input.ownerUserId,
358
+ actorUserId: input.ownerUserId,
359
+ eventType: 'cleaned_up',
360
+ outcome: 'success',
361
+ createdAt: now,
362
+ });
363
+ return true;
364
+ })();
365
+ }
366
+ markVerified(input) {
367
+ return this.updateUnderLease(input, 'active', {
368
+ displayMetadata: input.displayMetadata,
369
+ verified: true,
370
+ eventType: 'verified',
371
+ });
372
+ }
373
+ markRefreshed(input) {
374
+ return this.updateUnderLease(input, 'active', {
375
+ displayMetadata: input.displayMetadata,
376
+ refreshed: true,
377
+ eventType: 'refreshed',
378
+ });
379
+ }
380
+ markReconnectRequired(input) {
381
+ return this.updateUnderLease(input, 'reconnect_required', {
382
+ failureCode: normalizeIdentifier(input.failureCode, 'Failure code'),
383
+ eventType: 'reconnect_required',
384
+ });
385
+ }
386
+ markDisconnected(input) {
387
+ return this.updateUnderLease(input, 'disconnected', {
388
+ disconnected: true,
389
+ eventType: 'disconnected',
390
+ });
391
+ }
392
+ updateUnderLease(input, lifecycleStatus, options) {
393
+ return this.db.transaction(() => this.updateUnderLeaseTransaction(input, lifecycleStatus, options))();
394
+ }
395
+ updateUnderLeaseTransaction(input, lifecycleStatus, options) {
396
+ this.requireOwned(input.ownerUserId, input.connectionId);
397
+ const now = this.leaseNow().toISOString();
398
+ const clock = this.leaseClockPredicate(now);
399
+ const current = this.requireOwned(input.ownerUserId, input.connectionId);
400
+ const displayMetadata = options.displayMetadata === undefined
401
+ ? current.displayMetadata
402
+ : {
403
+ ...current.displayMetadata,
404
+ ...sanitizeModelProviderConnectionDisplayMetadata(options.displayMetadata),
405
+ };
406
+ const result = this.db.prepare(`
407
+ UPDATE model_provider_connections
408
+ SET lifecycle_status = ?, display_metadata_json = ?,
409
+ last_verified_at = CASE WHEN ? = 1 THEN ? ELSE last_verified_at END,
410
+ last_refreshed_at = CASE WHEN ? = 1 THEN ? ELSE last_refreshed_at END,
411
+ last_failure_at = CASE WHEN CAST(? AS TEXT) IS NOT NULL THEN ? ELSE NULL END,
412
+ failure_code = ?,
413
+ disconnected_at = CASE WHEN ? = 1 THEN ? ELSE disconnected_at END,
414
+ updated_at = ?
415
+ WHERE tenant_id = ? AND owner_user_id = ? AND id = ?
416
+ AND EXISTS (
417
+ SELECT 1 FROM model_provider_connection_leases lease
418
+ WHERE lease.tenant_id = model_provider_connections.tenant_id
419
+ AND lease.connection_id = model_provider_connections.id
420
+ AND lease.lease_token = ?
421
+ AND lease.expires_at > ${clock.sql}
422
+ )
423
+ `).run(lifecycleStatus, JSON.stringify(displayMetadata), options.verified ? 1 : 0, now, options.refreshed ? 1 : 0, now, options.failureCode || null, now, options.failureCode || null, options.disconnected ? 1 : 0, now, now, this.tenantId, input.ownerUserId, input.connectionId, input.leaseToken, ...clock.params);
424
+ if (Number(result?.changes || 0) !== 1) {
425
+ throw new ModelProviderConnectionError('Model connection operation lease is no longer valid.', 409, 'MODEL_CONNECTION_LEASE_LOST');
426
+ }
427
+ this.insertEvent({
428
+ connectionId: input.connectionId,
429
+ ownerUserId: input.ownerUserId,
430
+ actorUserId: input.ownerUserId,
431
+ eventType: options.eventType,
432
+ outcome: options.failureCode ? 'failure' : 'success',
433
+ reasonCode: options.failureCode,
434
+ createdAt: now,
435
+ });
436
+ return this.requireOwned(input.ownerUserId, input.connectionId);
437
+ }
438
+ insertEvent(input) {
439
+ this.db.prepare(`
440
+ INSERT INTO model_provider_connection_events (
441
+ id, tenant_id, connection_id, owner_user_id, actor_user_id,
442
+ event_type, outcome, reason_code, created_at
443
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
444
+ `).run(randomOpaqueId('mpce'), this.tenantId, input.connectionId, input.ownerUserId, input.actorUserId, input.eventType, input.outcome, input.reasonCode || null, input.createdAt);
445
+ }
446
+ }
@@ -9,6 +9,10 @@ export declare class PostgresWorkerUnavailableError extends Error {
9
9
  readonly code = "POSTGRES_WORKER_UNAVAILABLE";
10
10
  constructor();
11
11
  }
12
+ export declare class PostgresDatabaseError extends Error {
13
+ readonly code: string;
14
+ constructor(message: string, code: string);
15
+ }
12
16
  export declare function replaceQMarkParams(sql: string, params: unknown[]): {
13
17
  text: string;
14
18
  values: unknown[];
@@ -27,6 +27,14 @@ export class PostgresWorkerUnavailableError extends Error {
27
27
  this.name = 'PostgresWorkerUnavailableError';
28
28
  }
29
29
  }
30
+ export class PostgresDatabaseError extends Error {
31
+ code;
32
+ constructor(message, code) {
33
+ super(message);
34
+ this.code = code;
35
+ this.name = 'PostgresDatabaseError';
36
+ }
37
+ }
30
38
  function isPlainObject(value) {
31
39
  return !!value && typeof value === 'object' && !Array.isArray(value);
32
40
  }
@@ -171,8 +179,9 @@ export class PostgresAdapter {
171
179
  }
172
180
  const waitStartedAt = performance.now();
173
181
  const waitResult = Atomics.wait(status, RESPONSE_STATUS_INDEX, RESPONSE_INITIAL, this.deadlines.responseTimeoutMs);
174
- recordPostgresWorkerWait(payload.op, performance.now() - waitStartedAt);
182
+ const workerWaitMs = performance.now() - waitStartedAt;
175
183
  if (waitResult === 'timed-out') {
184
+ recordPostgresWorkerWait(payload.op, workerWaitMs);
176
185
  this.quarantineWorker(worker);
177
186
  throw new PostgresWorkerOutcomeUnknownError(payload.op);
178
187
  }
@@ -182,6 +191,7 @@ export class PostgresAdapter {
182
191
  }
183
192
  const body = this.decoder.decode(responseBytes.subarray(0, responseLength));
184
193
  const parsed = JSON.parse(body);
194
+ recordPostgresWorkerWait(payload.op, workerWaitMs, parsed.pool);
185
195
  this.consecutiveUnexpectedExits = 0;
186
196
  if (!parsed.ok && parsed.errorCode === 'RESPONSE_BUFFER_TOO_SMALL') {
187
197
  const requiredBytes = Number(parsed.requiredBytes);
@@ -195,6 +205,9 @@ export class PostgresAdapter {
195
205
  return this.callWorker({ op: 'read-response', responseToken }, requiredBytes);
196
206
  }
197
207
  if (!parsed.ok) {
208
+ if (parsed.databaseErrorCode) {
209
+ throw new PostgresDatabaseError(parsed.error || 'Unknown Postgres database error', parsed.databaseErrorCode);
210
+ }
198
211
  throw new Error(parsed.error || 'Unknown Postgres worker error');
199
212
  }
200
213
  return parsed;
@@ -2,7 +2,15 @@ export type RequestPerformanceDiagnostics = {
2
2
  postgresQueryCount: number;
3
3
  postgresWorkerCallCount: number;
4
4
  postgresWorkerWaitMs: number;
5
+ postgresWorkerWaitMaxMs: number;
6
+ postgresPoolWaitingMax: number;
7
+ postgresPoolTotalMax: number;
8
+ postgresPoolIdleMin: number | null;
5
9
  };
6
10
  export declare function runWithRequestPerformanceDiagnostics<T>(enabled: boolean, callback: () => T): T;
7
- export declare function recordPostgresWorkerWait(operation: string, durationMs: number): void;
11
+ export declare function recordPostgresWorkerWait(operation: string, durationMs: number, pool?: {
12
+ totalCount: number;
13
+ idleCount: number;
14
+ waitingCount: number;
15
+ }): void;
8
16
  export declare function getRequestPerformanceDiagnostics(): RequestPerformanceDiagnostics | null;
@@ -7,16 +7,29 @@ export function runWithRequestPerformanceDiagnostics(enabled, callback) {
7
7
  postgresQueryCount: 0,
8
8
  postgresWorkerCallCount: 0,
9
9
  postgresWorkerWaitMs: 0,
10
+ postgresWorkerWaitMaxMs: 0,
11
+ postgresPoolWaitingMax: 0,
12
+ postgresPoolTotalMax: 0,
13
+ postgresPoolIdleMin: null,
10
14
  }, callback);
11
15
  }
12
- export function recordPostgresWorkerWait(operation, durationMs) {
16
+ export function recordPostgresWorkerWait(operation, durationMs, pool) {
13
17
  const diagnostics = requestPerformanceStorage.getStore();
14
18
  if (!diagnostics)
15
19
  return;
16
20
  diagnostics.postgresWorkerCallCount += 1;
17
21
  if (operation === 'query')
18
22
  diagnostics.postgresQueryCount += 1;
19
- diagnostics.postgresWorkerWaitMs += Math.max(0, durationMs);
23
+ const boundedDurationMs = Math.max(0, durationMs);
24
+ diagnostics.postgresWorkerWaitMs += boundedDurationMs;
25
+ diagnostics.postgresWorkerWaitMaxMs = Math.max(diagnostics.postgresWorkerWaitMaxMs, boundedDurationMs);
26
+ if (pool) {
27
+ diagnostics.postgresPoolWaitingMax = Math.max(diagnostics.postgresPoolWaitingMax, pool.waitingCount);
28
+ diagnostics.postgresPoolTotalMax = Math.max(diagnostics.postgresPoolTotalMax, pool.totalCount);
29
+ diagnostics.postgresPoolIdleMin = diagnostics.postgresPoolIdleMin === null
30
+ ? pool.idleCount
31
+ : Math.min(diagnostics.postgresPoolIdleMin, pool.idleCount);
32
+ }
20
33
  }
21
34
  export function getRequestPerformanceDiagnostics() {
22
35
  const diagnostics = requestPerformanceStorage.getStore();