@taskforcehq/taskforce 0.3.328 → 0.3.329

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 (264) hide show
  1. package/dist/Taskforce.module.css +233 -34
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  8. package/dist/components/features/TaskSettings.d.ts +12 -1
  9. package/dist/components/features/TaskSettings.js +147 -40
  10. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  11. package/dist/components/features/planning/PlanningModule.js +2 -5
  12. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  13. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  14. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  15. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  16. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  17. package/dist/components/task/TaskCard.d.ts +5 -0
  18. package/dist/components/task/TaskCard.js +65 -10
  19. package/dist/components/task/TaskImageReviews.js +14 -5
  20. package/dist/components/task/TaskKanban.d.ts +6 -1
  21. package/dist/components/task/TaskKanban.js +152 -6
  22. package/dist/components/task/TaskList.d.ts +5 -0
  23. package/dist/components/task/TaskList.js +3 -3
  24. package/dist/components/ui/PasswordInput.d.ts +6 -0
  25. package/dist/components/ui/PasswordInput.js +11 -0
  26. package/dist/components/ui/TopNoticeLayer.js +1 -1
  27. package/dist/components/views/AppShellHeader.js +32 -11
  28. package/dist/components/views/PlanComparisonPage.js +12 -0
  29. package/dist/components/views/StandaloneLayout.js +7 -31
  30. package/dist/components/views/WidgetView.js +3 -3
  31. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  32. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  33. package/dist/config/envSchema.js +12 -0
  34. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  35. package/dist/config/localServiceRuntimeContract.js +135 -0
  36. package/dist/core/AiProfileService.js +46 -8
  37. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  38. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  39. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  40. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  41. package/dist/core/Taskforce.d.ts +62 -2
  42. package/dist/core/Taskforce.js +635 -32
  43. package/dist/core/types.d.ts +6 -0
  44. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  45. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  46. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  47. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  48. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  49. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  50. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  51. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  52. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  53. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  54. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  55. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  56. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  57. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  58. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  59. package/dist/hooks/ui/useSettingsModel.js +13 -2
  60. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  61. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  62. package/dist/hooks/useFilterSort.d.ts +7 -3
  63. package/dist/hooks/useFilterSort.js +15 -5
  64. package/dist/hooks/useTaskData.d.ts +10 -1
  65. package/dist/hooks/useTaskData.js +216 -7
  66. package/dist/hooks/useTaskMutations.d.ts +10 -2
  67. package/dist/hooks/useTaskMutations.js +223 -43
  68. package/dist/hooks/useTaskforce.d.ts +37 -9
  69. package/dist/hooks/useTaskforce.js +349 -39
  70. package/dist/hooks/useUiNotice.d.ts +4 -0
  71. package/dist/hooks/useUiNotice.js +4 -0
  72. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  73. package/dist/mcp/documentAssetRegistrar.js +44 -35
  74. package/dist/mcp/documentHelpers.d.ts +1 -0
  75. package/dist/mcp/documentHelpers.js +7 -3
  76. package/dist/mcp/runtime.js +172 -42
  77. package/dist/mcp/taskPlanningRegistrar.js +41 -38
  78. package/dist/mcp/toolCallCompatibility.js +38 -1
  79. package/dist/mcp/toolCatalog.d.ts +1 -0
  80. package/dist/migrations/taskSchemaMigrations.js +12 -0
  81. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  82. package/dist/runtime/appGateDefinitions.js +6 -6
  83. package/dist/runtime/appGates.d.ts +12 -13
  84. package/dist/runtime/appGates.js +29 -13
  85. package/dist/runtime/nodeAppGates.d.ts +8 -0
  86. package/dist/runtime/nodeAppGates.js +27 -0
  87. package/dist/server/cloudCollectionRead.d.ts +1 -1
  88. package/dist/server/cloudCollectionRead.js +2 -2
  89. package/dist/server/index.d.ts +3 -0
  90. package/dist/server/index.js +15 -3
  91. package/dist/server/localServiceLease.d.ts +3 -0
  92. package/dist/server/localServiceLease.js +9 -1
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
  94. package/dist/server/rateLimit.d.ts +1 -0
  95. package/dist/server/rateLimit.js +4 -0
  96. package/dist/server/realtimeSyncWs.js +36 -12
  97. package/dist/server/routes/admin.js +1 -0
  98. package/dist/server/routes/agentRoles.js +3 -2
  99. package/dist/server/routes/agentSkills.js +3 -2
  100. package/dist/server/routes/agents.js +118 -16
  101. package/dist/server/routes/annotatedAttachments.js +3 -2
  102. package/dist/server/routes/auth.js +3 -1
  103. package/dist/server/routes/durableTaskHttpRouters.d.ts +9 -2
  104. package/dist/server/routes/localService.js +2 -0
  105. package/dist/server/routes/primitives.d.ts +2 -0
  106. package/dist/server/routes/syncAuxRoutes.js +5 -2
  107. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  108. package/dist/server/routes/syncV3FeedRoutes.js +18 -16
  109. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  110. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  111. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  112. package/dist/server/routes/syncV3OperationRoutes.js +10 -0
  113. package/dist/server/routes/tasks.js +103 -11
  114. package/dist/server/routes/workspaces.js +43 -1
  115. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  116. package/dist/server/workspaceDeletionAdmission.js +50 -0
  117. package/dist/service/localServiceCli.js +16 -0
  118. package/dist/service/localServiceClientLifecycle.js +36 -10
  119. package/dist/services/codexAppServerModelGateway.d.ts +112 -0
  120. package/dist/services/codexAppServerModelGateway.js +438 -0
  121. package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
  122. package/dist/services/taskforceAgentMcpBridge.js +23 -3
  123. package/dist/shared/taskforceAgentDefinition.js +7 -1
  124. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  125. package/dist/shared/taskforceAgentModels.js +30 -1
  126. package/dist/storage/postgresAdapter.d.ts +20 -3
  127. package/dist/storage/postgresAdapter.js +106 -14
  128. package/dist/storage/postgresWorker.js +13 -4
  129. package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
  130. package/dist/storage/postgresWorkerProtocol.js +30 -0
  131. package/dist/sync/cloudSyncApi.d.ts +4 -1
  132. package/dist/sync/cloudSyncApi.js +7 -2
  133. package/dist/sync/contentSyncState.d.ts +1 -1
  134. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  135. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +7 -1
  136. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  137. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  138. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  139. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  140. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  141. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  142. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  143. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  144. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +25 -8
  145. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  146. package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
  147. package/dist/sync/syncService.d.ts +2 -0
  148. package/dist/sync/syncService.js +4 -1
  149. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  150. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  151. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +11 -1
  152. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
  153. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
  154. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  155. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  156. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  157. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
  158. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  159. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  160. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  161. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  162. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  163. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  164. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  165. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  166. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  167. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  168. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  169. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
  170. package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
  171. package/dist/sync/v3/syncDurabilityStore.d.ts +7 -0
  172. package/dist/sync/v3/syncDurabilityStore.js +31 -11
  173. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  174. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  175. package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
  176. package/dist/sync/v3/taskChecklistMutationService.js +4 -0
  177. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  178. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  179. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  180. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  181. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  182. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  183. package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
  184. package/dist/sync/v3/taskStatusMutationService.js +4 -0
  185. package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
  186. package/dist/sync/v3/workflowAssignmentSync.js +3 -0
  187. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  188. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  189. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  190. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  191. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  192. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  193. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -1
  194. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  195. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  196. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  197. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +30 -18
  198. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -4
  199. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +98 -47
  200. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  201. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +58 -21
  202. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
  203. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
  204. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  205. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  206. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  207. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  208. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  209. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  210. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  211. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  212. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  213. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  214. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  215. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  216. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +2 -0
  217. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
  218. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
  219. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  220. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  221. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  222. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  223. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  224. package/dist/sync/workspacePullFeed.js +2 -1
  225. package/dist/sync/workspaceRepair.d.ts +3 -0
  226. package/dist/sync/workspaceRepair.js +67 -6
  227. package/dist/types.d.ts +47 -1
  228. package/dist/types.js +6 -0
  229. package/dist/ui/assets/{AiIdentityRosterCard-MZs7lVED.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
  230. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
  231. package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
  232. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  233. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-C8Rztyal.js} +1 -1
  234. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Cj3c7X9y.js} +2 -2
  235. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-B5uvzems.js} +1 -1
  236. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-BVFvCB5R.js} +1 -1
  237. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
  238. package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
  239. package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
  240. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
  241. package/dist/ui/assets/{TaskforceAgentsModule-BazdUwxZ.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
  242. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DEr5di_r.js} +1 -1
  243. package/dist/ui/assets/index-I5zhdtgt.js +7 -0
  244. package/dist/ui/assets/index-VRFsx3wz.css +1 -0
  245. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-D9Lpw-j4.js} +1 -1
  246. package/dist/ui/index.html +3 -3
  247. package/dist/utils/taskActivity.d.ts +3 -2
  248. package/dist/utils/taskActivity.js +19 -2
  249. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  250. package/dist/utils/taskEditorReconciliation.js +217 -0
  251. package/dist/utils/taskNormalization.d.ts +1 -0
  252. package/dist/utils/taskNormalization.js +39 -0
  253. package/dist/utils/taskSearch.js +2 -2
  254. package/dist/utils/uiNotice.d.ts +4 -0
  255. package/package.json +16 -4
  256. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  257. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  258. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  259. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  260. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  261. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  262. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  263. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  264. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -0,0 +1,50 @@
1
+ export const WORKSPACE_DELETE_RETRY_COOLDOWN_MS = 30_000;
2
+ /**
3
+ * Serializes destructive workspace cleanup inside one server process and
4
+ * throttles immediate retries after an attempt settles. The caller supplies
5
+ * time so the admission policy can be verified without timers.
6
+ */
7
+ export class WorkspaceDeletionAdmission {
8
+ cooldownMs;
9
+ entries = new Map();
10
+ constructor(cooldownMs = WORKSPACE_DELETE_RETRY_COOLDOWN_MS) {
11
+ this.cooldownMs = cooldownMs;
12
+ }
13
+ checkExisting(key, now = Date.now()) {
14
+ let existing = this.entries.get(key);
15
+ if (existing?.state === 'cooldown' && existing.retryAt <= now) {
16
+ this.entries.delete(key);
17
+ existing = undefined;
18
+ }
19
+ if (existing?.state === 'in-flight') {
20
+ return {
21
+ allowed: false,
22
+ code: 'WORKSPACE_DELETE_IN_PROGRESS',
23
+ retryAfterMs: Math.max(1_000, this.cooldownMs),
24
+ };
25
+ }
26
+ if (existing?.state === 'cooldown') {
27
+ return {
28
+ allowed: false,
29
+ code: 'WORKSPACE_DELETE_RETRY_COOLDOWN',
30
+ retryAfterMs: Math.max(1_000, existing.retryAt - now),
31
+ };
32
+ }
33
+ return null;
34
+ }
35
+ acquire(key, now = Date.now()) {
36
+ const existing = this.checkExisting(key, now);
37
+ if (existing)
38
+ return existing;
39
+ this.entries.set(key, { state: 'in-flight' });
40
+ return { allowed: true };
41
+ }
42
+ settle(key, now = Date.now()) {
43
+ if (this.entries.get(key)?.state !== 'in-flight')
44
+ return;
45
+ this.entries.set(key, {
46
+ state: 'cooldown',
47
+ retryAt: now + this.cooldownMs,
48
+ });
49
+ }
50
+ }
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { applyLocalServiceCloudTarget, localServiceCloudTargetsEqual, parseLocalServiceCloudTarget, resolveLocalServiceCloudTarget, } from '../config/localServiceCloudTarget.js';
4
+ import { localServiceRuntimeContractsEqual, parseLocalServiceRuntimeContract, resolveLocalServiceRuntimeContract, } from '../config/localServiceRuntimeContract.js';
4
5
  import { createStandaloneServer } from '../server/index.js';
5
6
  import { inspectLocalServiceDescriptor, redactLocalServiceDescriptor, } from '../server/localServiceLease.js';
6
7
  import { acquireLocalServiceOwnershipForRuntime, } from '../server/localServiceOwnershipBootstrap.js';
@@ -66,6 +67,13 @@ function reportCloudTargetMismatch(descriptorTarget, requestedTarget, error) {
66
67
  + 'Stop it with `taskforce service stop --drain`, then retry.');
67
68
  return true;
68
69
  }
70
+ function reportRuntimeContractMismatch(descriptorContract, requestedContract, error) {
71
+ if (localServiceRuntimeContractsEqual(descriptorContract, requestedContract))
72
+ return false;
73
+ error('Taskforce service is running with a different or unverified local runtime contract. '
74
+ + 'Stop it with `taskforce service stop --drain`, then retry.');
75
+ return true;
76
+ }
69
77
  function defaultRegisterShutdownSignals(handler) {
70
78
  process.once('SIGINT', handler);
71
79
  process.once('SIGTERM', handler);
@@ -85,6 +93,7 @@ async function waitForDescriptor(input, expected, options) {
85
93
  async function runForeground(command, options) {
86
94
  const requestedCloudTarget = resolveLocalServiceCloudTarget(options.env);
87
95
  applyLocalServiceCloudTarget(options.env, requestedCloudTarget);
96
+ const requestedRuntimeContract = resolveLocalServiceRuntimeContract(options.env);
88
97
  const ownership = await options.acquireOwnership(command.projectRoot, options.env);
89
98
  if (!ownership)
90
99
  throw new Error('The shared local service requires local runtime mode.');
@@ -96,6 +105,8 @@ async function runForeground(command, options) {
96
105
  return 2;
97
106
  if (reportCloudTargetMismatch(inspection.descriptor.cloudTarget, requestedCloudTarget, options.error))
98
107
  return 2;
108
+ if (reportRuntimeContractMismatch(inspection.descriptor.runtimeContract, requestedRuntimeContract, options.error))
109
+ return 2;
99
110
  options.log(`Taskforce service is already running at ${inspection.descriptor.endpoint}.`);
100
111
  return 0;
101
112
  }
@@ -129,6 +140,7 @@ async function runForeground(command, options) {
129
140
  bootstrapCapability: ownership.lease.bootstrapCapability,
130
141
  ownershipKey: ownership.lease.identity.ownershipKey,
131
142
  cloudTarget: requestedCloudTarget,
143
+ runtimeContract: requestedRuntimeContract,
132
144
  },
133
145
  afterShutdown: async () => {
134
146
  removeSignals();
@@ -152,6 +164,7 @@ async function runForeground(command, options) {
152
164
  protocolVersion: LOCAL_SERVICE_PROTOCOL_VERSION,
153
165
  appVersion: options.appVersion,
154
166
  cloudTarget: requestedCloudTarget,
167
+ runtimeContract: requestedRuntimeContract,
155
168
  });
156
169
  removeSignals = options.registerShutdownSignals(shutdown);
157
170
  server.once('error', (error) => {
@@ -231,11 +244,14 @@ async function runStatus(command, options) {
231
244
  const payload = await response.json();
232
245
  const coordinatorPayload = payload.coordinator;
233
246
  const diagnosticCloudTarget = parseLocalServiceCloudTarget(payload.cloudTarget);
247
+ const diagnosticRuntimeContract = parseLocalServiceRuntimeContract(payload.runtimeContract);
234
248
  if (payload.ownerPid !== inspection.descriptor.pid
235
249
  || payload.generation !== inspection.descriptor.generation
236
250
  || payload.protocolVersion !== inspection.descriptor.protocolVersion
237
251
  || (inspection.descriptor.cloudTarget
238
252
  && !localServiceCloudTargetsEqual(diagnosticCloudTarget, inspection.descriptor.cloudTarget))
253
+ || (inspection.descriptor.runtimeContract
254
+ && !localServiceRuntimeContractsEqual(diagnosticRuntimeContract, inspection.descriptor.runtimeContract))
239
255
  || !Array.isArray(payload.sessions)
240
256
  || !coordinatorPayload
241
257
  || typeof coordinatorPayload !== 'object'
@@ -2,6 +2,7 @@ import { spawn } from 'child_process';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
4
  import { applyLocalServiceCloudTarget, localServiceCloudTargetsEqual, parseLocalServiceCloudTarget, resolveLocalServiceCloudTarget, } from '../config/localServiceCloudTarget.js';
5
+ import { localServiceRuntimeContractsEqual, parseLocalServiceRuntimeContract, resolveLocalServiceRuntimeContract, } from '../config/localServiceRuntimeContract.js';
5
6
  import { inspectLocalServiceDescriptor, } from '../server/localServiceLease.js';
6
7
  import { resolveLocalDatabaseIdentity } from '../server/localDatabaseIdentity.js';
7
8
  export const LOCAL_SERVICE_PROTOCOL_VERSION = '1';
@@ -23,6 +24,11 @@ const LOCAL_MCP_CLIENT_ENV_KEYS = [
23
24
  'TASKFORCE_AI_SURFACE_TYPE',
24
25
  'TASKFORCE_AI_SEAT_SCOPE',
25
26
  ];
27
+ function isQaIdentityEnvironmentKey(key) {
28
+ return key.startsWith('TASKFORCE_E2E_')
29
+ || key.startsWith('TASKFORCE_PLAYWRIGHT_')
30
+ || key.startsWith('SYNC_SOAK_');
31
+ }
26
32
  export function resolveLocalServiceLeaseInput(projectRoot, env) {
27
33
  const provider = env.TASKFORCE_DB_PROVIDER === 'postgres' ? 'postgres' : 'sqlite';
28
34
  return {
@@ -44,6 +50,10 @@ function buildLocalServiceProcessEnv(env, cloudTarget) {
44
50
  const serviceEnv = { ...env };
45
51
  for (const key of LOCAL_MCP_CLIENT_ENV_KEYS)
46
52
  delete serviceEnv[key];
53
+ for (const key of Object.keys(serviceEnv)) {
54
+ if (isQaIdentityEnvironmentKey(key))
55
+ delete serviceEnv[key];
56
+ }
47
57
  applyLocalServiceCloudTarget(serviceEnv, cloudTarget);
48
58
  return serviceEnv;
49
59
  }
@@ -84,10 +94,18 @@ async function validateLocalServiceReadiness(descriptor, fetchFn) {
84
94
  const readinessCloudTarget = readinessHasCloudTarget
85
95
  ? parseLocalServiceCloudTarget(readiness.cloudTarget)
86
96
  : null;
97
+ const readinessHasRuntimeContract = Object.prototype.hasOwnProperty.call(readiness, 'runtimeContract');
98
+ const readinessRuntimeContract = readinessHasRuntimeContract
99
+ ? parseLocalServiceRuntimeContract(readiness.runtimeContract)
100
+ : null;
87
101
  const descriptorCloudTarget = descriptor.cloudTarget || null;
102
+ const descriptorRuntimeContract = descriptor.runtimeContract || null;
88
103
  const cloudTargetsMatch = descriptorCloudTarget || readinessCloudTarget
89
104
  ? localServiceCloudTargetsEqual(descriptorCloudTarget, readinessCloudTarget)
90
105
  : true;
106
+ const runtimeContractsMatch = descriptorRuntimeContract || readinessRuntimeContract
107
+ ? localServiceRuntimeContractsEqual(descriptorRuntimeContract, readinessRuntimeContract)
108
+ : true;
91
109
  if (readiness.ready !== true
92
110
  || readiness.protocolVersion !== LOCAL_SERVICE_PROTOCOL_VERSION
93
111
  || readiness.protocolVersion !== descriptor.protocolVersion
@@ -96,10 +114,15 @@ async function validateLocalServiceReadiness(descriptor, fetchFn) {
96
114
  || readiness.endpoint !== descriptor.endpoint
97
115
  || readiness.dataIdentity !== descriptor.ownershipKey
98
116
  || (readinessHasCloudTarget && !readinessCloudTarget)
99
- || !cloudTargetsMatch) {
117
+ || !cloudTargetsMatch
118
+ || (readinessHasRuntimeContract && !readinessRuntimeContract)
119
+ || !runtimeContractsMatch) {
100
120
  throw new Error('Taskforce shared local service readiness does not match its descriptor.');
101
121
  }
102
- return descriptorCloudTarget;
122
+ return {
123
+ cloudTarget: descriptorCloudTarget,
124
+ runtimeContract: descriptorRuntimeContract,
125
+ };
103
126
  }
104
127
  async function requestIdleLocalServiceShutdown(descriptor, fetchFn) {
105
128
  let response;
@@ -121,7 +144,7 @@ async function requestIdleLocalServiceShutdown(descriptor, fetchFn) {
121
144
  });
122
145
  }
123
146
  catch (error) {
124
- throw new Error('Taskforce service uses a different cloud target and could not be stopped safely. '
147
+ throw new Error('Taskforce service uses a different cloud target or runtime contract and could not be stopped safely. '
125
148
  + `No replacement was started. ${String(error?.message || error)}`);
126
149
  }
127
150
  if (!response.ok) {
@@ -129,7 +152,7 @@ async function requestIdleLocalServiceShutdown(descriptor, fetchFn) {
129
152
  const activeClientHint = response.status === 409
130
153
  ? ' It may have active MCP clients; close them or run `taskforce service stop --drain`, then retry.'
131
154
  : '';
132
- throw new Error(`Taskforce service uses a different cloud target and refused safe idle replacement (${response.status}).`
155
+ throw new Error(`Taskforce service uses a different cloud target or runtime contract and refused safe idle replacement (${response.status}).`
133
156
  + activeClientHint
134
157
  + (detail ? ` ${detail}` : ''));
135
158
  }
@@ -141,13 +164,15 @@ export async function discoverOrStartLocalService(input) {
141
164
  const inspectDescriptor = input.inspectDescriptor || inspectLocalServiceDescriptor;
142
165
  const fetchFn = input.fetch || fetch;
143
166
  const requestedCloudTarget = resolveLocalServiceCloudTarget(input.env);
167
+ const requestedRuntimeContract = resolveLocalServiceRuntimeContract(input.env);
144
168
  const current = await inspectDescriptor(leaseInput);
145
169
  if (current.status === 'live' && current.descriptor) {
146
170
  if (current.descriptor.protocolVersion !== LOCAL_SERVICE_PROTOCOL_VERSION) {
147
171
  throw new Error(`Taskforce service protocol ${current.descriptor.protocolVersion} is incompatible with client protocol ${LOCAL_SERVICE_PROTOCOL_VERSION}.`);
148
172
  }
149
- const runningCloudTarget = await validateLocalServiceReadiness(current.descriptor, fetchFn);
150
- if (localServiceCloudTargetsEqual(runningCloudTarget, requestedCloudTarget)) {
173
+ const running = await validateLocalServiceReadiness(current.descriptor, fetchFn);
174
+ if (localServiceCloudTargetsEqual(running.cloudTarget, requestedCloudTarget)
175
+ && localServiceRuntimeContractsEqual(running.runtimeContract, requestedRuntimeContract)) {
151
176
  return current.descriptor;
152
177
  }
153
178
  await requestIdleLocalServiceShutdown(current.descriptor, fetchFn);
@@ -157,7 +182,7 @@ export async function discoverOrStartLocalService(input) {
157
182
  nowMs: input.nowMs,
158
183
  });
159
184
  if (stopped.status !== 'stale') {
160
- throw new Error('Taskforce service accepted cloud-target replacement but did not release its owner lease. No replacement was started.');
185
+ throw new Error('Taskforce service accepted configuration replacement but did not release its owner lease. No replacement was started.');
161
186
  }
162
187
  }
163
188
  if (current.status === 'indeterminate') {
@@ -181,9 +206,10 @@ export async function discoverOrStartLocalService(input) {
181
206
  if (inspection.descriptor.protocolVersion !== LOCAL_SERVICE_PROTOCOL_VERSION) {
182
207
  throw new Error(`Taskforce service protocol ${inspection.descriptor.protocolVersion} is incompatible with client protocol ${LOCAL_SERVICE_PROTOCOL_VERSION}.`);
183
208
  }
184
- const startedCloudTarget = await validateLocalServiceReadiness(inspection.descriptor, fetchFn);
185
- if (!localServiceCloudTargetsEqual(startedCloudTarget, requestedCloudTarget)) {
186
- throw new Error('Taskforce service started with a different or unverified cloud target; refusing to attach.');
209
+ const started = await validateLocalServiceReadiness(inspection.descriptor, fetchFn);
210
+ if (!localServiceCloudTargetsEqual(started.cloudTarget, requestedCloudTarget)
211
+ || !localServiceRuntimeContractsEqual(started.runtimeContract, requestedRuntimeContract)) {
212
+ throw new Error('Taskforce service started with a different or unverified cloud target/runtime contract; refusing to attach.');
187
213
  }
188
214
  return inspection.descriptor;
189
215
  }
@@ -0,0 +1,112 @@
1
+ import type { ModelGateway, ModelGatewayGenerateInput, ModelGatewayGenerateResult } from './modelGateway.js';
2
+ export type CodexAppServerModelKeyIdMap = Partial<Record<string, string>>;
3
+ type CodexAppServerApprovalPolicy = 'never';
4
+ type CodexAppServerSandboxMode = 'read-only';
5
+ type CodexAppServerSandboxPolicy = {
6
+ type: 'readOnly';
7
+ networkAccess: false;
8
+ };
9
+ type CodexAppServerRuntimePolicy = {
10
+ cwd: string;
11
+ approvalPolicy: CodexAppServerApprovalPolicy;
12
+ sandbox: CodexAppServerSandboxMode;
13
+ sandboxPolicy: CodexAppServerSandboxPolicy;
14
+ };
15
+ export interface CodexAppServerClient {
16
+ initialize(): Promise<void>;
17
+ assertChatGptSubscriptionAuth(): Promise<void>;
18
+ startThread(input: {
19
+ model: string;
20
+ developerInstructions?: string;
21
+ } & CodexAppServerRuntimePolicy): Promise<{
22
+ threadId: string;
23
+ }>;
24
+ startTurnAndCollectText(input: {
25
+ threadId: string;
26
+ prompt: string;
27
+ model: string;
28
+ timeoutMs: number;
29
+ } & CodexAppServerRuntimePolicy): Promise<{
30
+ text: string;
31
+ stopReason?: string;
32
+ }>;
33
+ close(): void;
34
+ }
35
+ export interface CodexAppServerModelGatewayOptions {
36
+ client?: CodexAppServerClient;
37
+ clientFactory?: () => CodexAppServerClient;
38
+ command?: string;
39
+ args?: string[];
40
+ cwd?: string;
41
+ env?: NodeJS.ProcessEnv;
42
+ modelKeyIds?: CodexAppServerModelKeyIdMap;
43
+ timeoutMs?: number;
44
+ requestTimeoutMs?: number;
45
+ }
46
+ export declare const DEFAULT_CODEX_APP_SERVER_MODEL_KEY_IDS: CodexAppServerModelKeyIdMap;
47
+ export declare function buildCodexAppServerEnv(source?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
48
+ export declare function sanitizeCodexAppServerStderr(value: unknown): string;
49
+ export declare function collectCodexAppServerStderr(current: string, chunk: unknown): string;
50
+ export declare function assertCodexChatGptSubscriptionAccount(result: unknown): void;
51
+ export declare function isCodexSubscriptionDevRuntimeAllowed(source?: NodeJS.ProcessEnv): boolean;
52
+ export declare function extractCodexTurnCompletion(messages: unknown[]): {
53
+ text: string;
54
+ stopReason: string;
55
+ } | null;
56
+ export declare class CodexAppServerJsonRpcClient implements CodexAppServerClient {
57
+ private readonly process;
58
+ private readonly pending;
59
+ private readonly notifications;
60
+ private nextId;
61
+ private initialized;
62
+ private readonly lineReader;
63
+ private readonly requestTimeoutMs;
64
+ private readonly turnRejectors;
65
+ private terminalError;
66
+ private stderrTail;
67
+ constructor(options?: {
68
+ command?: string;
69
+ args?: string[];
70
+ cwd?: string;
71
+ env?: NodeJS.ProcessEnv;
72
+ requestTimeoutMs?: number;
73
+ });
74
+ initialize(): Promise<void>;
75
+ assertChatGptSubscriptionAuth(): Promise<void>;
76
+ startThread(input: {
77
+ model: string;
78
+ developerInstructions?: string;
79
+ } & CodexAppServerRuntimePolicy): Promise<{
80
+ threadId: string;
81
+ }>;
82
+ startTurnAndCollectText(input: {
83
+ threadId: string;
84
+ prompt: string;
85
+ system?: string;
86
+ model: string;
87
+ timeoutMs: number;
88
+ } & CodexAppServerRuntimePolicy): Promise<{
89
+ text: string;
90
+ stopReason?: string;
91
+ }>;
92
+ close(): void;
93
+ private request;
94
+ private sendNotification;
95
+ private handleLine;
96
+ private sendResponseError;
97
+ private waitForTurnCompletion;
98
+ private rejectAll;
99
+ private fail;
100
+ }
101
+ export declare class CodexAppServerModelGateway implements ModelGateway {
102
+ private readonly client?;
103
+ private readonly clientFactory;
104
+ private readonly modelKeyIds;
105
+ private readonly timeoutMs;
106
+ private readonly cwd;
107
+ constructor(options?: CodexAppServerModelGatewayOptions);
108
+ generate(input: ModelGatewayGenerateInput): Promise<ModelGatewayGenerateResult>;
109
+ private resolveModelId;
110
+ private formatMessages;
111
+ }
112
+ export {};