@taskforcehq/taskforce 0.3.168

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 (492) hide show
  1. package/README.md +241 -0
  2. package/dist/Taskforce.d.ts +3 -0
  3. package/dist/Taskforce.js +3 -0
  4. package/dist/Taskforce.module.css +7587 -0
  5. package/dist/TaskforceCore.CategoryFallback.test.d.ts +1 -0
  6. package/dist/TaskforceCore.CategoryFallback.test.js +98 -0
  7. package/dist/TaskforceCore.d.ts +12 -0
  8. package/dist/TaskforceCore.js +729 -0
  9. package/dist/TaskforceCore.test.d.ts +1 -0
  10. package/dist/TaskforceCore.test.js +2132 -0
  11. package/dist/TaskforceScreenshot.d.ts +11 -0
  12. package/dist/TaskforceScreenshot.js +113 -0
  13. package/dist/TaskforceWidget.d.ts +6 -0
  14. package/dist/TaskforceWidget.js +101 -0
  15. package/dist/TaskforceWidget.test.d.ts +1 -0
  16. package/dist/TaskforceWidget.test.js +92 -0
  17. package/dist/UnsavedChangesRelaxed.test.d.ts +1 -0
  18. package/dist/UnsavedChangesRelaxed.test.js +16 -0
  19. package/dist/__tests__/localizationCatalogs.test.d.ts +1 -0
  20. package/dist/__tests__/localizationCatalogs.test.js +37 -0
  21. package/dist/__tests__/planParser.test.d.ts +1 -0
  22. package/dist/__tests__/planParser.test.js +183 -0
  23. package/dist/__tests__/releaseVersion.test.d.ts +1 -0
  24. package/dist/__tests__/releaseVersion.test.js +32 -0
  25. package/dist/__tests__/structuredCommentValidation.test.d.ts +1 -0
  26. package/dist/__tests__/structuredCommentValidation.test.js +31 -0
  27. package/dist/__tests__/structuredDocValidation.test.d.ts +1 -0
  28. package/dist/__tests__/structuredDocValidation.test.js +30 -0
  29. package/dist/__tests__/templateEngine.test.d.ts +1 -0
  30. package/dist/__tests__/templateEngine.test.js +150 -0
  31. package/dist/__tests__/templates.test.d.ts +1 -0
  32. package/dist/__tests__/templates.test.js +45 -0
  33. package/dist/__tests__/workflowDocumentFixtures.test.d.ts +1 -0
  34. package/dist/__tests__/workflowDocumentFixtures.test.js +78 -0
  35. package/dist/__tests__/workflowExportMatrix.test.d.ts +1 -0
  36. package/dist/__tests__/workflowExportMatrix.test.js +113 -0
  37. package/dist/__tests__/workflowExportSnapshots.test.d.ts +1 -0
  38. package/dist/__tests__/workflowExportSnapshots.test.js +28 -0
  39. package/dist/__tests__/workflowGeneration.test.d.ts +1 -0
  40. package/dist/__tests__/workflowGeneration.test.js +12 -0
  41. package/dist/__tests__/workflowSimulation.test.d.ts +1 -0
  42. package/dist/__tests__/workflowSimulation.test.js +113 -0
  43. package/dist/__tests__/workflowV2Policy.test.d.ts +1 -0
  44. package/dist/__tests__/workflowV2Policy.test.js +80 -0
  45. package/dist/api.d.ts +30 -0
  46. package/dist/api.js +85 -0
  47. package/dist/cli.d.ts +2 -0
  48. package/dist/cli.js +217 -0
  49. package/dist/compat/priorityCompat.d.ts +2 -0
  50. package/dist/compat/priorityCompat.js +24 -0
  51. package/dist/components/features/DocumentGenerateModal.d.ts +9 -0
  52. package/dist/components/features/DocumentGenerateModal.js +114 -0
  53. package/dist/components/features/DocumentIndex.d.ts +19 -0
  54. package/dist/components/features/DocumentIndex.js +51 -0
  55. package/dist/components/features/DocumentViewer.d.ts +9 -0
  56. package/dist/components/features/DocumentViewer.js +253 -0
  57. package/dist/components/features/DocumentWorkspace.d.ts +21 -0
  58. package/dist/components/features/DocumentWorkspace.js +88 -0
  59. package/dist/components/features/TaskSettings.d.ts +209 -0
  60. package/dist/components/features/TaskSettings.js +500 -0
  61. package/dist/components/features/TaskSettings.test.d.ts +1 -0
  62. package/dist/components/features/TaskSettings.test.js +308 -0
  63. package/dist/components/features/settings/CategoryManager.d.ts +19 -0
  64. package/dist/components/features/settings/CategoryManager.js +113 -0
  65. package/dist/components/features/settings/TaxonomyEditor.d.ts +8 -0
  66. package/dist/components/features/settings/TaxonomyEditor.js +98 -0
  67. package/dist/components/features/settings/TaxonomyManager 2.d.ts +52 -0
  68. package/dist/components/features/settings/TaxonomyManager 2.js +75 -0
  69. package/dist/components/features/settings/TaxonomyManager.d.ts +54 -0
  70. package/dist/components/features/settings/TaxonomyManager.js +77 -0
  71. package/dist/components/features/settings/TypeManager.d.ts +10 -0
  72. package/dist/components/features/settings/TypeManager.js +50 -0
  73. package/dist/components/features/settings/WorkflowEditorPrototype.d.ts +15 -0
  74. package/dist/components/features/settings/WorkflowEditorPrototype.js +245 -0
  75. package/dist/components/task/TaskActionHeader.d.ts +20 -0
  76. package/dist/components/task/TaskActionHeader.js +13 -0
  77. package/dist/components/task/TaskCard.d.ts +47 -0
  78. package/dist/components/task/TaskCard.js +326 -0
  79. package/dist/components/task/TaskCard.test.d.ts +1 -0
  80. package/dist/components/task/TaskCard.test.js +95 -0
  81. package/dist/components/task/TaskContextUpload.d.ts +12 -0
  82. package/dist/components/task/TaskContextUpload.js +393 -0
  83. package/dist/components/task/TaskContextUpload.test.d.ts +1 -0
  84. package/dist/components/task/TaskContextUpload.test.js +189 -0
  85. package/dist/components/task/TaskForm.d.ts +105 -0
  86. package/dist/components/task/TaskForm.js +241 -0
  87. package/dist/components/task/TaskForm.test.d.ts +1 -0
  88. package/dist/components/task/TaskForm.test.js +288 -0
  89. package/dist/components/task/TaskKanban 2.d.ts +76 -0
  90. package/dist/components/task/TaskKanban 2.js +1004 -0
  91. package/dist/components/task/TaskKanban.d.ts +76 -0
  92. package/dist/components/task/TaskKanban.empty-column-drop.test.d.ts +1 -0
  93. package/dist/components/task/TaskKanban.empty-column-drop.test.js +66 -0
  94. package/dist/components/task/TaskKanban.js +1026 -0
  95. package/dist/components/task/TaskKanban.test.d.ts +1 -0
  96. package/dist/components/task/TaskKanban.test.js +46 -0
  97. package/dist/components/task/TaskList.d.ts +74 -0
  98. package/dist/components/task/TaskList.js +38 -0
  99. package/dist/components/task/TaskList.test.d.ts +1 -0
  100. package/dist/components/task/TaskList.test.js +270 -0
  101. package/dist/components/task/TaskScreenshotSection.d.ts +15 -0
  102. package/dist/components/task/TaskScreenshotSection.js +22 -0
  103. package/dist/components/ui/LevelSelector.d.ts +13 -0
  104. package/dist/components/ui/LevelSelector.js +25 -0
  105. package/dist/components/ui/LevelSelector.test.d.ts +1 -0
  106. package/dist/components/ui/LevelSelector.test.js +55 -0
  107. package/dist/components/ui/Markdown.d.ts +6 -0
  108. package/dist/components/ui/Markdown.js +94 -0
  109. package/dist/components/ui/Markdown.test.d.ts +1 -0
  110. package/dist/components/ui/Markdown.test.js +38 -0
  111. package/dist/components/ui/Modal.d.ts +16 -0
  112. package/dist/components/ui/Modal.js +49 -0
  113. package/dist/components/ui/MultiSelectFilter.d.ts +10 -0
  114. package/dist/components/ui/MultiSelectFilter.js +71 -0
  115. package/dist/components/ui/MultiSelectFilter.test.d.ts +1 -0
  116. package/dist/components/ui/MultiSelectFilter.test.js +74 -0
  117. package/dist/components/ui/TaxonomyDropdown.d.ts +17 -0
  118. package/dist/components/ui/TaxonomyDropdown.js +145 -0
  119. package/dist/components/ui/TaxonomyDropdown.test.d.ts +1 -0
  120. package/dist/components/ui/TaxonomyDropdown.test.js +130 -0
  121. package/dist/components/views/StandaloneLayout 2.d.ts +8 -0
  122. package/dist/components/views/StandaloneLayout 2.js +1660 -0
  123. package/dist/components/views/StandaloneLayout.d.ts +8 -0
  124. package/dist/components/views/StandaloneLayout.js +2117 -0
  125. package/dist/components/views/WidgetView.d.ts +8 -0
  126. package/dist/components/views/WidgetView.js +221 -0
  127. package/dist/config/envSchema.d.ts +28 -0
  128. package/dist/config/envSchema.js +374 -0
  129. package/dist/config/envSchema.test.d.ts +1 -0
  130. package/dist/config/envSchema.test.js +97 -0
  131. package/dist/config/surfaceBase.d.ts +2 -0
  132. package/dist/config/surfaceBase.js +8 -0
  133. package/dist/core/BulkUpdateFieldsPreview.test.d.ts +1 -0
  134. package/dist/core/BulkUpdateFieldsPreview.test.js +62 -0
  135. package/dist/core/CompletedAt.test.d.ts +1 -0
  136. package/dist/core/CompletedAt.test.js +44 -0
  137. package/dist/core/CreatedBy.test.d.ts +1 -0
  138. package/dist/core/CreatedBy.test.js +60 -0
  139. package/dist/core/EntitlementsPolicy.test.d.ts +1 -0
  140. package/dist/core/EntitlementsPolicy.test.js +145 -0
  141. package/dist/core/InitiativeTemplates.test.d.ts +1 -0
  142. package/dist/core/InitiativeTemplates.test.js +50 -0
  143. package/dist/core/ParentLifecycle.test.d.ts +1 -0
  144. package/dist/core/ParentLifecycle.test.js +98 -0
  145. package/dist/core/ScheduleFields.test.d.ts +1 -0
  146. package/dist/core/ScheduleFields.test.js +197 -0
  147. package/dist/core/SetupState.test.d.ts +1 -0
  148. package/dist/core/SetupState.test.js +113 -0
  149. package/dist/core/SystemAdmin.test.d.ts +1 -0
  150. package/dist/core/SystemAdmin.test.js +295 -0
  151. package/dist/core/TaskTaxonomyValidation.test.d.ts +1 -0
  152. package/dist/core/TaskTaxonomyValidation.test.js +64 -0
  153. package/dist/core/Taskforce.d.ts +1063 -0
  154. package/dist/core/Taskforce.ids.test.d.ts +1 -0
  155. package/dist/core/Taskforce.ids.test.js +168 -0
  156. package/dist/core/Taskforce.js +5981 -0
  157. package/dist/core/Taskforce.realtimeMutation.test.d.ts +1 -0
  158. package/dist/core/Taskforce.realtimeMutation.test.js +76 -0
  159. package/dist/core/WorkspaceDelete.test.d.ts +1 -0
  160. package/dist/core/WorkspaceDelete.test.js +140 -0
  161. package/dist/core/WorkspacePermissions.test.d.ts +1 -0
  162. package/dist/core/WorkspacePermissions.test.js +151 -0
  163. package/dist/core/WorkspacePlanMode.test.d.ts +1 -0
  164. package/dist/core/WorkspacePlanMode.test.js +104 -0
  165. package/dist/hooks/authGuardPolicy.d.ts +26 -0
  166. package/dist/hooks/authGuardPolicy.js +32 -0
  167. package/dist/hooks/authGuardPolicy.test.d.ts +1 -0
  168. package/dist/hooks/authGuardPolicy.test.js +76 -0
  169. package/dist/hooks/useDraggable.d.ts +12 -0
  170. package/dist/hooks/useDraggable.js +65 -0
  171. package/dist/hooks/useRealtimeSync.d.ts +24 -0
  172. package/dist/hooks/useRealtimeSync.js +275 -0
  173. package/dist/hooks/useRealtimeSync.test.d.ts +1 -0
  174. package/dist/hooks/useRealtimeSync.test.js +284 -0
  175. package/dist/hooks/useSyncOrchestrator.d.ts +164 -0
  176. package/dist/hooks/useSyncOrchestrator.js +1427 -0
  177. package/dist/hooks/useSyncOrchestrator.retry-closure.test.d.ts +1 -0
  178. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +367 -0
  179. package/dist/hooks/useTaskforce.d.ts +727 -0
  180. package/dist/hooks/useTaskforce.js +4396 -0
  181. package/dist/hooks/useTaskforce.priority-filters.test.d.ts +1 -0
  182. package/dist/hooks/useTaskforce.priority-filters.test.js +33 -0
  183. package/dist/hooks/useWorkspaceSyncController.d.ts +80 -0
  184. package/dist/hooks/useWorkspaceSyncController.js +598 -0
  185. package/dist/hooks/useWorkspaceSyncController.test.d.ts +1 -0
  186. package/dist/hooks/useWorkspaceSyncController.test.js +236 -0
  187. package/dist/index.d.ts +12 -0
  188. package/dist/index.js +11 -0
  189. package/dist/localization/index.d.ts +8 -0
  190. package/dist/localization/index.js +81 -0
  191. package/dist/localization/locales/en-US.d.ts +151 -0
  192. package/dist/localization/locales/en-US.js +150 -0
  193. package/dist/localization/locales/es-419.d.ts +2 -0
  194. package/dist/localization/locales/es-419.js +150 -0
  195. package/dist/localization/locales/pt-BR.d.ts +2 -0
  196. package/dist/localization/locales/pt-BR.js +150 -0
  197. package/dist/main.d.ts +1 -0
  198. package/dist/main.js +33 -0
  199. package/dist/mcp/optionResolution.d.ts +14 -0
  200. package/dist/mcp/optionResolution.js +126 -0
  201. package/dist/mcp/optionResolution.test.d.ts +1 -0
  202. package/dist/mcp/optionResolution.test.js +39 -0
  203. package/dist/mcp/server.d.ts +1 -0
  204. package/dist/mcp/server.js +1793 -0
  205. package/dist/mcp/structuredCommentValidation.d.ts +6 -0
  206. package/dist/mcp/structuredCommentValidation.js +56 -0
  207. package/dist/mcp/structuredDocValidation.d.ts +6 -0
  208. package/dist/mcp/structuredDocValidation.js +75 -0
  209. package/dist/migrations/billingSchemaParity.test.d.ts +1 -0
  210. package/dist/migrations/billingSchemaParity.test.js +46 -0
  211. package/dist/migrations/clientMigrations.d.ts +9 -0
  212. package/dist/migrations/clientMigrations.js +74 -0
  213. package/dist/migrations/flags.d.ts +6 -0
  214. package/dist/migrations/flags.js +8 -0
  215. package/dist/migrations/taskMigrations.d.ts +71 -0
  216. package/dist/migrations/taskMigrations.js +236 -0
  217. package/dist/migrations/taskMigrations.test.d.ts +1 -0
  218. package/dist/migrations/taskMigrations.test.js +34 -0
  219. package/dist/migrations/taskSchemaMigrations.d.ts +11 -0
  220. package/dist/migrations/taskSchemaMigrations.js +453 -0
  221. package/dist/plugins/index.d.ts +10 -0
  222. package/dist/plugins/index.js +10 -0
  223. package/dist/plugins/vite.d.ts +19 -0
  224. package/dist/plugins/vite.js +271 -0
  225. package/dist/public/android-chrome-192x192.png +0 -0
  226. package/dist/public/android-chrome-512x512.png +0 -0
  227. package/dist/public/apple-touch-icon.png +0 -0
  228. package/dist/public/favicon-16x16.png +0 -0
  229. package/dist/public/favicon-32x32.png +0 -0
  230. package/dist/public/favicon.ico +0 -0
  231. package/dist/public/favicon.png +0 -0
  232. package/dist/public/site.webmanifest +1 -0
  233. package/dist/public/taskforce.png +0 -0
  234. package/dist/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
  235. package/dist/resources/templates/environments/aider.yaml +14 -0
  236. package/dist/resources/templates/environments/antigravity.yaml +10 -0
  237. package/dist/resources/templates/environments/claude.yaml +10 -0
  238. package/dist/resources/templates/environments/cline.yaml +10 -0
  239. package/dist/resources/templates/environments/codex.yaml +13 -0
  240. package/dist/resources/templates/environments/copilot.yaml +10 -0
  241. package/dist/resources/templates/environments/cursor.yaml +9 -0
  242. package/dist/resources/templates/environments/gemini.yaml +9 -0
  243. package/dist/resources/templates/environments/windsurf.yaml +10 -0
  244. package/dist/resources/templates/workflow-sources/README.md +9 -0
  245. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
  246. package/dist/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
  247. package/dist/resources/templates/workflows/collaborate.yaml +104 -0
  248. package/dist/resources/templates/workflows/do.yaml +82 -0
  249. package/dist/resources/templates/workflows/evaluate.yaml +111 -0
  250. package/dist/resources/templates/workflows/execute.yaml +142 -0
  251. package/dist/resources/templates/workflows/plan.yaml +112 -0
  252. package/dist/resources/templates/workflows/review.yaml +109 -0
  253. package/dist/runtime/capabilities.d.ts +8 -0
  254. package/dist/runtime/capabilities.js +16 -0
  255. package/dist/security/virusScan.d.ts +16 -0
  256. package/dist/security/virusScan.js +83 -0
  257. package/dist/server/auth.d.ts +51 -0
  258. package/dist/server/auth.js +266 -0
  259. package/dist/server/auth.test.d.ts +1 -0
  260. package/dist/server/auth.test.js +111 -0
  261. package/dist/server/buildInfo.d.ts +7 -0
  262. package/dist/server/buildInfo.js +100 -0
  263. package/dist/server/buildInfo.test.d.ts +1 -0
  264. package/dist/server/buildInfo.test.js +29 -0
  265. package/dist/server/cors.d.ts +7 -0
  266. package/dist/server/cors.js +76 -0
  267. package/dist/server/cors.test.d.ts +1 -0
  268. package/dist/server/cors.test.js +71 -0
  269. package/dist/server/email.d.ts +28 -0
  270. package/dist/server/email.js +138 -0
  271. package/dist/server/email.test.d.ts +1 -0
  272. package/dist/server/email.test.js +113 -0
  273. package/dist/server/index.cookieProxy.test.d.ts +1 -0
  274. package/dist/server/index.cookieProxy.test.js +19 -0
  275. package/dist/server/index.d.ts +17 -0
  276. package/dist/server/index.js +757 -0
  277. package/dist/server/index.rateLimit.test.d.ts +1 -0
  278. package/dist/server/index.rateLimit.test.js +13 -0
  279. package/dist/server/index.test.d.ts +1 -0
  280. package/dist/server/index.test.js +19 -0
  281. package/dist/server/rateLimit.d.ts +29 -0
  282. package/dist/server/rateLimit.js +99 -0
  283. package/dist/server/rateLimit.test.d.ts +1 -0
  284. package/dist/server/rateLimit.test.js +107 -0
  285. package/dist/server/realtimeSync.auth.test.d.ts +1 -0
  286. package/dist/server/realtimeSync.auth.test.js +62 -0
  287. package/dist/server/realtimeSync.replay.test.d.ts +1 -0
  288. package/dist/server/realtimeSync.replay.test.js +192 -0
  289. package/dist/server/realtimeSync.workspaceIsolation.test.d.ts +1 -0
  290. package/dist/server/realtimeSync.workspaceIsolation.test.js +101 -0
  291. package/dist/server/realtimeSyncWs.d.ts +30 -0
  292. package/dist/server/realtimeSyncWs.js +257 -0
  293. package/dist/server/routes.billing.d.ts +15 -0
  294. package/dist/server/routes.billing.js +991 -0
  295. package/dist/server/routes.billing.test.d.ts +1 -0
  296. package/dist/server/routes.billing.test.js +387 -0
  297. package/dist/server/routes.d.ts +72 -0
  298. package/dist/server/routes.js +4820 -0
  299. package/dist/server/routes.sync.d.ts +17 -0
  300. package/dist/server/routes.sync.integration.test.d.ts +1 -0
  301. package/dist/server/routes.sync.integration.test.js +470 -0
  302. package/dist/server/routes.sync.js +1141 -0
  303. package/dist/server/routes.test.d.ts +1 -0
  304. package/dist/server/routes.test.js +4945 -0
  305. package/dist/server/runtimeMode.d.ts +4 -0
  306. package/dist/server/runtimeMode.js +25 -0
  307. package/dist/server/runtimeMode.test.d.ts +1 -0
  308. package/dist/server/runtimeMode.test.js +26 -0
  309. package/dist/server/securityHeaders.d.ts +3 -0
  310. package/dist/server/securityHeaders.js +25 -0
  311. package/dist/server/securityHeaders.test.d.ts +1 -0
  312. package/dist/server/securityHeaders.test.js +32 -0
  313. package/dist/server/smtpTransport.d.ts +21 -0
  314. package/dist/server/smtpTransport.js +11 -0
  315. package/dist/server/start.d.ts +1 -0
  316. package/dist/server/start.js +17 -0
  317. package/dist/services/formatTransformers.d.ts +29 -0
  318. package/dist/services/formatTransformers.js +56 -0
  319. package/dist/services/templateEngine.d.ts +46 -0
  320. package/dist/services/templateEngine.js +148 -0
  321. package/dist/shared/runtimeContract.d.ts +12 -0
  322. package/dist/shared/runtimeContract.js +23 -0
  323. package/dist/shared/runtimeContract.test.d.ts +1 -0
  324. package/dist/shared/runtimeContract.test.js +23 -0
  325. package/dist/soak/preflight.cli.d.ts +1 -0
  326. package/dist/soak/preflight.cli.js +28 -0
  327. package/dist/soak/preflight.d.ts +26 -0
  328. package/dist/soak/preflight.js +113 -0
  329. package/dist/soak/preflight.test.d.ts +1 -0
  330. package/dist/soak/preflight.test.js +39 -0
  331. package/dist/soak/syncSoakHarness.d.ts +6 -0
  332. package/dist/soak/syncSoakHarness.js +10 -0
  333. package/dist/storage/createDatabaseAdapter.d.ts +2 -0
  334. package/dist/storage/createDatabaseAdapter.js +9 -0
  335. package/dist/storage/databaseAdapter.d.ts +22 -0
  336. package/dist/storage/databaseAdapter.js +1 -0
  337. package/dist/storage/documentIntegrity.d.ts +28 -0
  338. package/dist/storage/documentIntegrity.js +103 -0
  339. package/dist/storage/documentPurge.d.ts +14 -0
  340. package/dist/storage/documentPurge.js +46 -0
  341. package/dist/storage/documentRegistry.d.ts +39 -0
  342. package/dist/storage/documentRegistry.js +115 -0
  343. package/dist/storage/integritySchedule.d.ts +17 -0
  344. package/dist/storage/integritySchedule.js +62 -0
  345. package/dist/storage/objectStorage.d.ts +20 -0
  346. package/dist/storage/objectStorage.js +15 -0
  347. package/dist/storage/objectStorageClient.d.ts +18 -0
  348. package/dist/storage/objectStorageClient.js +301 -0
  349. package/dist/storage/objectStorageConfig.d.ts +2 -0
  350. package/dist/storage/objectStorageConfig.js +45 -0
  351. package/dist/storage/postgresAdapter.d.ts +20 -0
  352. package/dist/storage/postgresAdapter.js +204 -0
  353. package/dist/storage/postgresWorker.d.ts +1 -0
  354. package/dist/storage/postgresWorker.js +110 -0
  355. package/dist/storage/providerConfig.d.ts +6 -0
  356. package/dist/storage/providerConfig.js +11 -0
  357. package/dist/storage/sqliteAdapter.d.ts +14 -0
  358. package/dist/storage/sqliteAdapter.js +28 -0
  359. package/dist/storage/taskAssetStore.d.ts +56 -0
  360. package/dist/storage/taskAssetStore.js +297 -0
  361. package/dist/sync/cloudSyncApi.d.ts +47 -0
  362. package/dist/sync/cloudSyncApi.js +138 -0
  363. package/dist/sync/cloudSyncApi.test.d.ts +1 -0
  364. package/dist/sync/cloudSyncApi.test.js +54 -0
  365. package/dist/sync/encryptionService.d.ts +11 -0
  366. package/dist/sync/encryptionService.js +61 -0
  367. package/dist/sync/encryptionService.test.d.ts +1 -0
  368. package/dist/sync/encryptionService.test.js +52 -0
  369. package/dist/sync/realtimeFeature.d.ts +6 -0
  370. package/dist/sync/realtimeFeature.js +20 -0
  371. package/dist/sync/realtimeFeature.test.d.ts +1 -0
  372. package/dist/sync/realtimeFeature.test.js +30 -0
  373. package/dist/sync/realtimeReconcile.d.ts +30 -0
  374. package/dist/sync/realtimeReconcile.js +90 -0
  375. package/dist/sync/realtimeReconcile.test.d.ts +1 -0
  376. package/dist/sync/realtimeReconcile.test.js +43 -0
  377. package/dist/sync/syncService.d.ts +96 -0
  378. package/dist/sync/syncService.js +423 -0
  379. package/dist/sync/syncService.test.d.ts +1 -0
  380. package/dist/sync/syncService.test.js +484 -0
  381. package/dist/sync/workspaceSyncModel.d.ts +61 -0
  382. package/dist/sync/workspaceSyncModel.js +136 -0
  383. package/dist/sync/workspaceSyncModel.test.d.ts +1 -0
  384. package/dist/sync/workspaceSyncModel.test.js +73 -0
  385. package/dist/test/setup.d.ts +1 -0
  386. package/dist/test/setup.js +15 -0
  387. package/dist/types.d.ts +157 -0
  388. package/dist/types.js +41 -0
  389. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  390. package/dist/ui/assets/index-0W5vyCpn.css +1 -0
  391. package/dist/ui/assets/index-MCZuNNfn.js +23 -0
  392. package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
  393. package/dist/ui/assets/taskforce-BxLPokNB.png +0 -0
  394. package/dist/ui/assets/vendor-dnd-BI1K77C1.js +5 -0
  395. package/dist/ui/assets/vendor-icons-ZFG3SGwo.js +1 -0
  396. package/dist/ui/assets/vendor-markdown-CKYkQHfj.js +29 -0
  397. package/dist/ui/assets/vendor-react-DdIDsh7f.js +9 -0
  398. package/dist/ui/assets/vendor-router-BtiNU7Dl.js +3 -0
  399. package/dist/ui/branding/logos/logo_black_01.png +0 -0
  400. package/dist/ui/branding/logos/logo_black_02.png +0 -0
  401. package/dist/ui/branding/logos/logo_white_01.png +0 -0
  402. package/dist/ui/branding/logos/logo_white_02.png +0 -0
  403. package/dist/ui/favicon/android-chrome-192x192.png +0 -0
  404. package/dist/ui/favicon/android-chrome-512x512.png +0 -0
  405. package/dist/ui/favicon/apple-touch-icon.png +0 -0
  406. package/dist/ui/favicon/favicon-16x16.png +0 -0
  407. package/dist/ui/favicon/favicon-32x32.png +0 -0
  408. package/dist/ui/favicon/favicon.ico +0 -0
  409. package/dist/ui/favicon/favicon.png +0 -0
  410. package/dist/ui/favicon/site.webmanifest +1 -0
  411. package/dist/ui/fonts/RussoOne-Regular.ttf +0 -0
  412. package/dist/ui/images/taskforce.png +0 -0
  413. package/dist/ui/index.html +19 -0
  414. package/dist/utils/checklistMarkdown.d.ts +9 -0
  415. package/dist/utils/checklistMarkdown.js +46 -0
  416. package/dist/utils/constants.d.ts +21 -0
  417. package/dist/utils/constants.icons.test.d.ts +1 -0
  418. package/dist/utils/constants.icons.test.js +40 -0
  419. package/dist/utils/constants.js +100 -0
  420. package/dist/utils/contextFiles.d.ts +8 -0
  421. package/dist/utils/contextFiles.js +54 -0
  422. package/dist/utils/formatting.d.ts +5 -0
  423. package/dist/utils/formatting.js +30 -0
  424. package/dist/utils/planParser.d.ts +22 -0
  425. package/dist/utils/planParser.js +151 -0
  426. package/dist/utils/taskDragZones.d.ts +8 -0
  427. package/dist/utils/taskDragZones.js +14 -0
  428. package/dist/utils/taskDragZones.test.d.ts +1 -0
  429. package/dist/utils/taskDragZones.test.js +14 -0
  430. package/dist/utils/taskHierarchy.d.ts +4 -0
  431. package/dist/utils/taskHierarchy.js +69 -0
  432. package/dist/utils/taskHierarchy.test.d.ts +1 -0
  433. package/dist/utils/taskHierarchy.test.js +38 -0
  434. package/dist/utils/taskParenting.d.ts +3 -0
  435. package/dist/utils/taskParenting.js +24 -0
  436. package/dist/utils/taskParenting.test.d.ts +1 -0
  437. package/dist/utils/taskParenting.test.js +21 -0
  438. package/dist/utils/taskRelations.d.ts +6 -0
  439. package/dist/utils/taskRelations.js +24 -0
  440. package/dist/utils/taskRelations.test.d.ts +1 -0
  441. package/dist/utils/taskRelations.test.js +34 -0
  442. package/dist/utils/taskUtils.d.ts +2 -0
  443. package/dist/utils/taskUtils.js +20 -0
  444. package/dist/utils/taskforceApiClient.d.ts +7 -0
  445. package/dist/utils/taskforceApiClient.js +42 -0
  446. package/dist/utils/workspaceIdentity.d.ts +8 -0
  447. package/dist/utils/workspaceIdentity.js +47 -0
  448. package/dist/utils/workspaceIdentity.test.d.ts +1 -0
  449. package/dist/utils/workspaceIdentity.test.js +32 -0
  450. package/dist/utils/workspaceLifecycle.d.ts +26 -0
  451. package/dist/utils/workspaceLifecycle.js +69 -0
  452. package/dist/utils/workspaceLifecycle.test.d.ts +1 -0
  453. package/dist/utils/workspaceLifecycle.test.js +64 -0
  454. package/package.json +133 -0
  455. package/scripts/check-compat-boundaries.js +48 -0
  456. package/scripts/check-env.ts +24 -0
  457. package/scripts/check-localization-strings.mjs +49 -0
  458. package/scripts/check-runtime-boundaries.mjs +44 -0
  459. package/scripts/debug-global.mjs +34 -0
  460. package/scripts/debug-server.mjs +36 -0
  461. package/scripts/export-sqlite-to-postgres.mjs +125 -0
  462. package/scripts/generate-env-example.ts +8 -0
  463. package/scripts/generate-workflow-templates.mjs +134 -0
  464. package/scripts/mcp-stdio-adapter.mjs +160 -0
  465. package/scripts/postinstall.js +60 -0
  466. package/scripts/release-version-lib.mjs +88 -0
  467. package/scripts/release-version.mjs +72 -0
  468. package/scripts/run-dev-proxy.sh +49 -0
  469. package/scripts/run-e2e-realtime.sh +16 -0
  470. package/scripts/run-smoke.sh +23 -0
  471. package/scripts/run-soak.sh +29 -0
  472. package/scripts/test-global.js +143 -0
  473. package/scripts/update-homebrew-formula.sh +38 -0
  474. package/src/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
  475. package/src/resources/templates/environments/aider.yaml +14 -0
  476. package/src/resources/templates/environments/antigravity.yaml +10 -0
  477. package/src/resources/templates/environments/claude.yaml +10 -0
  478. package/src/resources/templates/environments/cline.yaml +10 -0
  479. package/src/resources/templates/environments/codex.yaml +13 -0
  480. package/src/resources/templates/environments/copilot.yaml +10 -0
  481. package/src/resources/templates/environments/cursor.yaml +9 -0
  482. package/src/resources/templates/environments/gemini.yaml +9 -0
  483. package/src/resources/templates/environments/windsurf.yaml +10 -0
  484. package/src/resources/templates/workflow-sources/README.md +9 -0
  485. package/src/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
  486. package/src/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
  487. package/src/resources/templates/workflows/collaborate.yaml +104 -0
  488. package/src/resources/templates/workflows/do.yaml +82 -0
  489. package/src/resources/templates/workflows/evaluate.yaml +111 -0
  490. package/src/resources/templates/workflows/execute.yaml +142 -0
  491. package/src/resources/templates/workflows/plan.yaml +112 -0
  492. package/src/resources/templates/workflows/review.yaml +109 -0
@@ -0,0 +1,15 @@
1
+ export function toPublicObjectStorageConfig(config) {
2
+ if (config.provider !== 'r2' || !config.r2) {
3
+ return { provider: config.provider };
4
+ }
5
+ return {
6
+ provider: 'r2',
7
+ r2: {
8
+ bucket: config.r2.bucket,
9
+ endpoint: config.r2.endpoint,
10
+ keyPrefix: config.r2.keyPrefix,
11
+ signedUploadTtlSeconds: config.r2.signedUploadTtlSeconds,
12
+ signedDownloadTtlSeconds: config.r2.signedDownloadTtlSeconds
13
+ }
14
+ };
15
+ }
@@ -0,0 +1,18 @@
1
+ import type { ResolvedObjectStorageConfig } from './objectStorage.js';
2
+ export interface StoredObject {
3
+ body: Buffer;
4
+ contentType: string;
5
+ }
6
+ export declare class ObjectStorageClient {
7
+ private readonly config;
8
+ constructor(config: ResolvedObjectStorageConfig);
9
+ provider(): 'local' | 'r2';
10
+ keyForRelativePath(relativePath: string): string;
11
+ putObject(relativePath: string, body: Buffer, contentType: string): Promise<void>;
12
+ getObject(relativePath: string): Promise<StoredObject | null>;
13
+ objectExists(relativePath: string): Promise<boolean>;
14
+ deleteObject(relativePath: string): Promise<boolean>;
15
+ createSignedGetUrl(relativePath: string, expiresInSeconds: number): string;
16
+ createSignedPutUrl(relativePath: string, expiresInSeconds: number): string;
17
+ }
18
+ export declare function normalizeTaskDataRelativePath(rawPath: string): string | null;
@@ -0,0 +1,301 @@
1
+ import { createHash, createHmac } from 'crypto';
2
+ const AWS_ALGORITHM = 'AWS4-HMAC-SHA256';
3
+ const AWS_SERVICE = 's3';
4
+ const AWS_REGION = 'auto';
5
+ function sha256Hex(value) {
6
+ return createHash('sha256').update(value).digest('hex');
7
+ }
8
+ function hmac(key, value) {
9
+ return createHmac('sha256', key).update(value, 'utf8').digest();
10
+ }
11
+ function encodeRfc3986(value) {
12
+ return encodeURIComponent(value).replace(/[!*'()]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`);
13
+ }
14
+ function encodeUriPath(pathname) {
15
+ return pathname
16
+ .split('/')
17
+ .map((segment) => encodeRfc3986(segment))
18
+ .join('/');
19
+ }
20
+ function normalizeRelativePath(rawPath) {
21
+ const value = String(rawPath || '').trim().replace(/\\/g, '/');
22
+ if (!value || value.startsWith('/'))
23
+ return null;
24
+ const parts = value.split('/').filter(Boolean);
25
+ if (parts.length === 0)
26
+ return null;
27
+ if (parts.some((part) => part === '.' || part === '..'))
28
+ return null;
29
+ return parts.join('/');
30
+ }
31
+ function buildObjectKey(config, relativePath) {
32
+ const normalized = normalizeRelativePath(relativePath);
33
+ if (!normalized)
34
+ throw new Error('Invalid object path.');
35
+ if (config.provider !== 'r2' || !config.r2?.keyPrefix)
36
+ return normalized;
37
+ const prefix = config.r2.keyPrefix.replace(/^\/+|\/+$/g, '');
38
+ return prefix ? `${prefix}/${normalized}` : normalized;
39
+ }
40
+ function buildCanonicalQuery(searchParams) {
41
+ const entries = Array.from(searchParams.entries())
42
+ .map(([key, value]) => [encodeRfc3986(key), encodeRfc3986(value)])
43
+ .sort((a, b) => (a[0] === b[0] ? a[1].localeCompare(b[1]) : a[0].localeCompare(b[0])));
44
+ return entries.map(([key, value]) => `${key}=${value}`).join('&');
45
+ }
46
+ function buildSigningKey(secretAccessKey, dateStamp) {
47
+ const kDate = hmac(`AWS4${secretAccessKey}`, dateStamp);
48
+ const kRegion = hmac(kDate, AWS_REGION);
49
+ const kService = hmac(kRegion, AWS_SERVICE);
50
+ return hmac(kService, 'aws4_request');
51
+ }
52
+ function toDateStamp(amzDate) {
53
+ return amzDate.slice(0, 8);
54
+ }
55
+ function createAmzDate(now = new Date()) {
56
+ const iso = now.toISOString();
57
+ return iso.replace(/[:-]|\.\d{3}/g, '');
58
+ }
59
+ function signRequest(params) {
60
+ const amzDate = createAmzDate(params.now);
61
+ const dateStamp = toDateStamp(amzDate);
62
+ const host = params.url.host;
63
+ const canonicalUri = encodeUriPath(params.url.pathname);
64
+ const canonicalQuery = buildCanonicalQuery(params.url.searchParams);
65
+ const canonicalHeaders = `host:${host}\n` + `x-amz-content-sha256:${params.payloadHash}\n` + `x-amz-date:${amzDate}\n`;
66
+ const signedHeaders = 'host;x-amz-content-sha256;x-amz-date';
67
+ const canonicalRequest = [
68
+ params.method.toUpperCase(),
69
+ canonicalUri,
70
+ canonicalQuery,
71
+ canonicalHeaders,
72
+ signedHeaders,
73
+ params.payloadHash
74
+ ].join('\n');
75
+ const credentialScope = `${dateStamp}/${AWS_REGION}/${AWS_SERVICE}/aws4_request`;
76
+ const stringToSign = [
77
+ AWS_ALGORITHM,
78
+ amzDate,
79
+ credentialScope,
80
+ sha256Hex(canonicalRequest)
81
+ ].join('\n');
82
+ const signature = createHmac('sha256', buildSigningKey(params.secretAccessKey, dateStamp))
83
+ .update(stringToSign, 'utf8')
84
+ .digest('hex');
85
+ const authorization = `${AWS_ALGORITHM} Credential=${params.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
86
+ return { authorization, amzDate, canonicalQuery };
87
+ }
88
+ export class ObjectStorageClient {
89
+ config;
90
+ constructor(config) {
91
+ this.config = config;
92
+ }
93
+ provider() {
94
+ return this.config.provider;
95
+ }
96
+ keyForRelativePath(relativePath) {
97
+ return buildObjectKey(this.config, relativePath);
98
+ }
99
+ async putObject(relativePath, body, contentType) {
100
+ if (this.config.provider !== 'r2' || !this.config.r2) {
101
+ throw new Error('R2 object storage is not configured.');
102
+ }
103
+ const key = this.keyForRelativePath(relativePath);
104
+ const url = new URL(`/${this.config.r2.bucket}/${key}`, this.config.r2.endpoint);
105
+ const payloadHash = sha256Hex(body);
106
+ const signed = signRequest({
107
+ method: 'PUT',
108
+ url,
109
+ accessKeyId: this.config.r2.accessKeyId,
110
+ secretAccessKey: this.config.r2.secretAccessKey,
111
+ payloadHash
112
+ });
113
+ const response = await fetch(url, {
114
+ method: 'PUT',
115
+ headers: {
116
+ 'authorization': signed.authorization,
117
+ 'x-amz-date': signed.amzDate,
118
+ 'x-amz-content-sha256': payloadHash,
119
+ 'content-type': contentType
120
+ },
121
+ body: new Uint8Array(body)
122
+ });
123
+ if (!response.ok) {
124
+ const text = await response.text().catch(() => '');
125
+ throw new Error(`Failed to upload object (${response.status}): ${text || response.statusText}`);
126
+ }
127
+ }
128
+ async getObject(relativePath) {
129
+ if (this.config.provider !== 'r2' || !this.config.r2) {
130
+ throw new Error('R2 object storage is not configured.');
131
+ }
132
+ const key = this.keyForRelativePath(relativePath);
133
+ const url = new URL(`/${this.config.r2.bucket}/${key}`, this.config.r2.endpoint);
134
+ const payloadHash = sha256Hex('');
135
+ const signed = signRequest({
136
+ method: 'GET',
137
+ url,
138
+ accessKeyId: this.config.r2.accessKeyId,
139
+ secretAccessKey: this.config.r2.secretAccessKey,
140
+ payloadHash
141
+ });
142
+ const response = await fetch(url, {
143
+ method: 'GET',
144
+ headers: {
145
+ 'authorization': signed.authorization,
146
+ 'x-amz-date': signed.amzDate,
147
+ 'x-amz-content-sha256': payloadHash
148
+ }
149
+ });
150
+ if (response.status === 404)
151
+ return null;
152
+ if (!response.ok) {
153
+ const text = await response.text().catch(() => '');
154
+ throw new Error(`Failed to read object (${response.status}): ${text || response.statusText}`);
155
+ }
156
+ const contentType = String(response.headers.get('content-type') || 'application/octet-stream');
157
+ const body = Buffer.from(await response.arrayBuffer());
158
+ return { body, contentType };
159
+ }
160
+ async objectExists(relativePath) {
161
+ if (this.config.provider !== 'r2' || !this.config.r2) {
162
+ throw new Error('R2 object storage is not configured.');
163
+ }
164
+ const key = this.keyForRelativePath(relativePath);
165
+ const url = new URL(`/${this.config.r2.bucket}/${key}`, this.config.r2.endpoint);
166
+ const payloadHash = sha256Hex('');
167
+ const signed = signRequest({
168
+ method: 'HEAD',
169
+ url,
170
+ accessKeyId: this.config.r2.accessKeyId,
171
+ secretAccessKey: this.config.r2.secretAccessKey,
172
+ payloadHash
173
+ });
174
+ const response = await fetch(url, {
175
+ method: 'HEAD',
176
+ headers: {
177
+ 'authorization': signed.authorization,
178
+ 'x-amz-date': signed.amzDate,
179
+ 'x-amz-content-sha256': payloadHash
180
+ }
181
+ });
182
+ if (response.status === 404)
183
+ return false;
184
+ if (!response.ok) {
185
+ const text = await response.text().catch(() => '');
186
+ throw new Error(`Failed to check object (${response.status}): ${text || response.statusText}`);
187
+ }
188
+ return true;
189
+ }
190
+ async deleteObject(relativePath) {
191
+ if (this.config.provider !== 'r2' || !this.config.r2) {
192
+ throw new Error('R2 object storage is not configured.');
193
+ }
194
+ const key = this.keyForRelativePath(relativePath);
195
+ const url = new URL(`/${this.config.r2.bucket}/${key}`, this.config.r2.endpoint);
196
+ const payloadHash = sha256Hex('');
197
+ const signed = signRequest({
198
+ method: 'DELETE',
199
+ url,
200
+ accessKeyId: this.config.r2.accessKeyId,
201
+ secretAccessKey: this.config.r2.secretAccessKey,
202
+ payloadHash
203
+ });
204
+ const response = await fetch(url, {
205
+ method: 'DELETE',
206
+ headers: {
207
+ 'authorization': signed.authorization,
208
+ 'x-amz-date': signed.amzDate,
209
+ 'x-amz-content-sha256': payloadHash
210
+ }
211
+ });
212
+ if (response.status === 404)
213
+ return false;
214
+ if (!response.ok) {
215
+ const text = await response.text().catch(() => '');
216
+ throw new Error(`Failed to delete object (${response.status}): ${text || response.statusText}`);
217
+ }
218
+ return true;
219
+ }
220
+ createSignedGetUrl(relativePath, expiresInSeconds) {
221
+ if (this.config.provider !== 'r2' || !this.config.r2) {
222
+ throw new Error('R2 object storage is not configured.');
223
+ }
224
+ const ttl = Number.isFinite(expiresInSeconds) ? Math.max(1, Math.min(3600, Math.floor(expiresInSeconds))) : 300;
225
+ const key = this.keyForRelativePath(relativePath);
226
+ const url = new URL(`/${this.config.r2.bucket}/${key}`, this.config.r2.endpoint);
227
+ const amzDate = createAmzDate();
228
+ const dateStamp = toDateStamp(amzDate);
229
+ const credentialScope = `${dateStamp}/${AWS_REGION}/${AWS_SERVICE}/aws4_request`;
230
+ url.searchParams.set('X-Amz-Algorithm', AWS_ALGORITHM);
231
+ url.searchParams.set('X-Amz-Credential', `${this.config.r2.accessKeyId}/${credentialScope}`);
232
+ url.searchParams.set('X-Amz-Date', amzDate);
233
+ url.searchParams.set('X-Amz-Expires', String(ttl));
234
+ url.searchParams.set('X-Amz-SignedHeaders', 'host');
235
+ const canonicalUri = encodeUriPath(url.pathname);
236
+ const canonicalQuery = buildCanonicalQuery(url.searchParams);
237
+ const canonicalRequest = [
238
+ 'GET',
239
+ canonicalUri,
240
+ canonicalQuery,
241
+ `host:${url.host}\n`,
242
+ 'host',
243
+ 'UNSIGNED-PAYLOAD'
244
+ ].join('\n');
245
+ const stringToSign = [
246
+ AWS_ALGORITHM,
247
+ amzDate,
248
+ credentialScope,
249
+ sha256Hex(canonicalRequest)
250
+ ].join('\n');
251
+ const signingKey = buildSigningKey(this.config.r2.secretAccessKey, dateStamp);
252
+ const signature = createHmac('sha256', signingKey).update(stringToSign, 'utf8').digest('hex');
253
+ url.searchParams.set('X-Amz-Signature', signature);
254
+ return url.toString();
255
+ }
256
+ createSignedPutUrl(relativePath, expiresInSeconds) {
257
+ if (this.config.provider !== 'r2' || !this.config.r2) {
258
+ throw new Error('R2 object storage is not configured.');
259
+ }
260
+ const ttl = Number.isFinite(expiresInSeconds) ? Math.max(1, Math.min(3600, Math.floor(expiresInSeconds))) : 600;
261
+ const key = this.keyForRelativePath(relativePath);
262
+ const url = new URL(`/${this.config.r2.bucket}/${key}`, this.config.r2.endpoint);
263
+ const amzDate = createAmzDate();
264
+ const dateStamp = toDateStamp(amzDate);
265
+ const credentialScope = `${dateStamp}/${AWS_REGION}/${AWS_SERVICE}/aws4_request`;
266
+ url.searchParams.set('X-Amz-Algorithm', AWS_ALGORITHM);
267
+ url.searchParams.set('X-Amz-Credential', `${this.config.r2.accessKeyId}/${credentialScope}`);
268
+ url.searchParams.set('X-Amz-Date', amzDate);
269
+ url.searchParams.set('X-Amz-Expires', String(ttl));
270
+ url.searchParams.set('X-Amz-SignedHeaders', 'host');
271
+ const canonicalUri = encodeUriPath(url.pathname);
272
+ const canonicalQuery = buildCanonicalQuery(url.searchParams);
273
+ const canonicalRequest = [
274
+ 'PUT',
275
+ canonicalUri,
276
+ canonicalQuery,
277
+ `host:${url.host}\n`,
278
+ 'host',
279
+ 'UNSIGNED-PAYLOAD'
280
+ ].join('\n');
281
+ const stringToSign = [
282
+ AWS_ALGORITHM,
283
+ amzDate,
284
+ credentialScope,
285
+ sha256Hex(canonicalRequest)
286
+ ].join('\n');
287
+ const signingKey = buildSigningKey(this.config.r2.secretAccessKey, dateStamp);
288
+ const signature = createHmac('sha256', signingKey).update(stringToSign, 'utf8').digest('hex');
289
+ url.searchParams.set('X-Amz-Signature', signature);
290
+ return url.toString();
291
+ }
292
+ }
293
+ export function normalizeTaskDataRelativePath(rawPath) {
294
+ const normalized = normalizeRelativePath(rawPath);
295
+ if (!normalized)
296
+ return null;
297
+ const allowedRoots = ['task-data/', 'users/', 'workspaces/', 'system/', 'tmp/', 'quarantine/'];
298
+ if (!allowedRoots.some((root) => normalized.startsWith(root)))
299
+ return null;
300
+ return normalized;
301
+ }
@@ -0,0 +1,2 @@
1
+ import type { ResolvedObjectStorageConfig } from './objectStorage.js';
2
+ export declare function resolveObjectStorageConfigFromEnv(env?: NodeJS.ProcessEnv): ResolvedObjectStorageConfig;
@@ -0,0 +1,45 @@
1
+ function readProvider(env) {
2
+ const raw = String(env.TASKFORCE_OBJECT_STORAGE_PROVIDER || env.TASKFORCE_STORAGE_PROVIDER || '').trim().toLowerCase();
3
+ if (raw === 'r2')
4
+ return 'r2';
5
+ return 'local';
6
+ }
7
+ function readPositiveInteger(value, fallback) {
8
+ const parsed = Number.parseInt(String(value || '').trim(), 10);
9
+ if (!Number.isFinite(parsed) || parsed <= 0)
10
+ return fallback;
11
+ return parsed;
12
+ }
13
+ function readRequired(env, key) {
14
+ const value = String(env[key] || '').trim();
15
+ if (!value) {
16
+ throw new Error(`[Taskforce] ${key} is required when object storage provider is r2.`);
17
+ }
18
+ return value;
19
+ }
20
+ export function resolveObjectStorageConfigFromEnv(env = process.env) {
21
+ const provider = readProvider(env);
22
+ if (provider !== 'r2')
23
+ return { provider: 'local' };
24
+ const accountId = readRequired(env, 'R2_ACCOUNT_ID');
25
+ const bucket = readRequired(env, 'R2_BUCKET');
26
+ const accessKeyId = readRequired(env, 'R2_ACCESS_KEY_ID');
27
+ const secretAccessKey = readRequired(env, 'R2_SECRET_ACCESS_KEY');
28
+ const endpoint = String(env.R2_ENDPOINT || '').trim() || `https://${accountId}.r2.cloudflarestorage.com`;
29
+ const keyPrefix = String(env.R2_KEY_PREFIX || 'taskforce').trim() || 'taskforce';
30
+ const signedUploadTtlSeconds = readPositiveInteger(env.R2_SIGNED_UPLOAD_TTL_SECONDS, 600);
31
+ const signedDownloadTtlSeconds = readPositiveInteger(env.R2_SIGNED_DOWNLOAD_TTL_SECONDS, 300);
32
+ return {
33
+ provider: 'r2',
34
+ r2: {
35
+ accountId,
36
+ bucket,
37
+ endpoint,
38
+ accessKeyId,
39
+ secretAccessKey,
40
+ keyPrefix,
41
+ signedUploadTtlSeconds,
42
+ signedDownloadTtlSeconds
43
+ }
44
+ };
45
+ }
@@ -0,0 +1,20 @@
1
+ import type { DatabaseAdapter, DatabaseStatement } from './databaseAdapter.js';
2
+ export declare class PostgresAdapter implements DatabaseAdapter {
3
+ readonly provider: "postgres";
4
+ readonly open = true;
5
+ private readonly worker;
6
+ private readonly encoder;
7
+ private readonly decoder;
8
+ private txId;
9
+ constructor(connectionString?: string);
10
+ private callWorker;
11
+ private query;
12
+ private bindParams;
13
+ prepare(sql: string): DatabaseStatement;
14
+ exec(sql: string): void;
15
+ transaction<T extends (...args: any[]) => any>(fn: T): T;
16
+ pragma(name: string, options?: {
17
+ simple?: boolean;
18
+ }): unknown;
19
+ close(): void;
20
+ }
@@ -0,0 +1,204 @@
1
+ import { TextDecoder, TextEncoder } from 'util';
2
+ import { Worker } from 'worker_threads';
3
+ const RESPONSE_STATUS_INDEX = 0;
4
+ const RESPONSE_LENGTH_INDEX = 1;
5
+ const RESPONSE_READY = 1;
6
+ const RESPONSE_INITIAL = 0;
7
+ const RESPONSE_TIMEOUT_MS = 20_000;
8
+ const RESPONSE_BUFFER_BYTES = 2 * 1024 * 1024;
9
+ function isPlainObject(value) {
10
+ return !!value && typeof value === 'object' && !Array.isArray(value);
11
+ }
12
+ function replaceQMarkParams(sql, params) {
13
+ let index = 0;
14
+ const text = sql.replace(/\?/g, () => {
15
+ index += 1;
16
+ return `$${index}`;
17
+ });
18
+ return { text, values: params };
19
+ }
20
+ function replaceNamedParams(sql, params) {
21
+ const values = [];
22
+ const keyToIndex = new Map();
23
+ const text = sql.replace(/@([a-zA-Z_][a-zA-Z0-9_]*)/g, (_match, key) => {
24
+ if (!keyToIndex.has(key)) {
25
+ keyToIndex.set(key, values.length + 1);
26
+ values.push(params[key]);
27
+ }
28
+ return `$${keyToIndex.get(key)}`;
29
+ });
30
+ return { text, values };
31
+ }
32
+ function translateInsertOrReplace(sql) {
33
+ const match = sql.match(/INSERT\s+OR\s+REPLACE\s+INTO\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(([\s\S]*?)\)\s*VALUES\s*\(([\s\S]*?)\)/i);
34
+ if (!match)
35
+ return sql;
36
+ const table = match[1];
37
+ const columns = match[2].split(',').map((c) => c.trim()).filter(Boolean);
38
+ if (columns.length === 0)
39
+ return sql.replace(/INSERT\s+OR\s+REPLACE/i, 'INSERT');
40
+ const updateColumns = columns.filter((c) => c !== 'id');
41
+ const updateClause = updateColumns.length === 0
42
+ ? 'NOTHING'
43
+ : `UPDATE SET ${updateColumns.map((c) => `${c} = EXCLUDED.${c}`).join(', ')}`;
44
+ return sql.replace(/INSERT\s+OR\s+REPLACE\s+INTO[\s\S]*?\)\s*VALUES\s*\([\s\S]*?\)/i, `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${match[3]}) ON CONFLICT (id) DO ${updateClause}`);
45
+ }
46
+ function normalizeSchemaSql(sql) {
47
+ return sql
48
+ .replace(/\bBOOLEAN\b/gi, 'INTEGER')
49
+ .replace(/\bTRUE\b/gi, '1')
50
+ .replace(/\bFALSE\b/gi, '0');
51
+ }
52
+ function parsePragmaTableInfo(sql) {
53
+ const match = sql.trim().match(/^PRAGMA\s+table_info\((['"]?)([a-zA-Z_][a-zA-Z0-9_]*)\1\)\s*;?$/i);
54
+ return match?.[2] || null;
55
+ }
56
+ function toRowCount(result) {
57
+ return typeof result.rowCount === 'number' ? result.rowCount : 0;
58
+ }
59
+ export class PostgresAdapter {
60
+ provider = 'postgres';
61
+ open = true;
62
+ worker;
63
+ encoder = new TextEncoder();
64
+ decoder = new TextDecoder();
65
+ txId = null;
66
+ constructor(connectionString) {
67
+ if (!connectionString || !connectionString.trim()) {
68
+ throw new Error('[Taskforce] Postgres adapter requires a non-empty connection string.');
69
+ }
70
+ this.worker = new Worker(new URL('./postgresWorker.js', import.meta.url), {
71
+ workerData: {
72
+ connectionString
73
+ }
74
+ });
75
+ }
76
+ callWorker(payload) {
77
+ const statusBuffer = new SharedArrayBuffer(8);
78
+ const status = new Int32Array(statusBuffer);
79
+ status[RESPONSE_STATUS_INDEX] = RESPONSE_INITIAL;
80
+ status[RESPONSE_LENGTH_INDEX] = 0;
81
+ const responseBuffer = new SharedArrayBuffer(RESPONSE_BUFFER_BYTES);
82
+ const responseBytes = new Uint8Array(responseBuffer);
83
+ this.worker.postMessage({
84
+ payload,
85
+ statusBuffer,
86
+ responseBuffer
87
+ });
88
+ const waitResult = Atomics.wait(status, RESPONSE_STATUS_INDEX, RESPONSE_INITIAL, RESPONSE_TIMEOUT_MS);
89
+ if (waitResult === 'timed-out') {
90
+ throw new Error('[Taskforce] Postgres worker timed out.');
91
+ }
92
+ const responseLength = status[RESPONSE_LENGTH_INDEX];
93
+ if (!Number.isFinite(responseLength) || responseLength <= 0 || responseLength > RESPONSE_BUFFER_BYTES) {
94
+ throw new Error('[Taskforce] Invalid Postgres worker response.');
95
+ }
96
+ const body = this.decoder.decode(responseBytes.subarray(0, responseLength));
97
+ const parsed = JSON.parse(body);
98
+ if (!parsed.ok) {
99
+ throw new Error(parsed.error || 'Unknown Postgres worker error');
100
+ }
101
+ return parsed;
102
+ }
103
+ query(sql, values = []) {
104
+ const response = this.callWorker({
105
+ op: 'query',
106
+ sql,
107
+ values,
108
+ txId: this.txId || undefined
109
+ });
110
+ return response.result || { rows: [], rowCount: 0 };
111
+ }
112
+ bindParams(sql, params) {
113
+ const translated = translateInsertOrReplace(sql);
114
+ if (params.length === 1 && isPlainObject(params[0])) {
115
+ return replaceNamedParams(translated, params[0]);
116
+ }
117
+ return replaceQMarkParams(translated, params);
118
+ }
119
+ prepare(sql) {
120
+ const pragmaTable = parsePragmaTableInfo(sql);
121
+ if (pragmaTable) {
122
+ return {
123
+ run: () => ({ changes: 0 }),
124
+ get: () => {
125
+ const row = this.query(`SELECT column_name AS name
126
+ FROM information_schema.columns
127
+ WHERE table_schema = 'public' AND table_name = $1
128
+ ORDER BY ordinal_position
129
+ LIMIT 1`, [pragmaTable]).rows[0];
130
+ return row || undefined;
131
+ },
132
+ all: () => this.query(`SELECT column_name AS name
133
+ FROM information_schema.columns
134
+ WHERE table_schema = 'public' AND table_name = $1
135
+ ORDER BY ordinal_position`, [pragmaTable]).rows
136
+ };
137
+ }
138
+ return {
139
+ run: (...params) => {
140
+ const { text, values } = this.bindParams(sql, params);
141
+ const result = this.query(text, values);
142
+ return { changes: toRowCount(result) };
143
+ },
144
+ get: (...params) => {
145
+ const { text, values } = this.bindParams(sql, params);
146
+ const result = this.query(text, values);
147
+ return result.rows[0] || undefined;
148
+ },
149
+ all: (...params) => {
150
+ const { text, values } = this.bindParams(sql, params);
151
+ return this.query(text, values).rows;
152
+ }
153
+ };
154
+ }
155
+ exec(sql) {
156
+ const normalized = normalizeSchemaSql(sql);
157
+ this.query(normalized, []);
158
+ }
159
+ transaction(fn) {
160
+ const wrapped = ((...args) => {
161
+ if (this.txId) {
162
+ return fn(...args);
163
+ }
164
+ const txId = `tx-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
165
+ this.callWorker({ op: 'begin', txId });
166
+ this.txId = txId;
167
+ try {
168
+ const value = fn(...args);
169
+ this.callWorker({ op: 'commit', txId });
170
+ return value;
171
+ }
172
+ catch (error) {
173
+ try {
174
+ this.callWorker({ op: 'rollback', txId });
175
+ }
176
+ catch {
177
+ // Best effort rollback.
178
+ }
179
+ throw error;
180
+ }
181
+ finally {
182
+ this.txId = null;
183
+ }
184
+ });
185
+ return wrapped;
186
+ }
187
+ pragma(name, options) {
188
+ const normalized = String(name || '').trim().toLowerCase();
189
+ if (normalized === 'data_version') {
190
+ const row = this.query('SELECT EXTRACT(EPOCH FROM now())::bigint AS version').rows[0];
191
+ const version = Number(row?.version || 0);
192
+ return options?.simple ? version : [{ data_version: version }];
193
+ }
194
+ return options?.simple ? null : [];
195
+ }
196
+ close() {
197
+ try {
198
+ this.callWorker({ op: 'close' });
199
+ }
200
+ finally {
201
+ this.worker.terminate();
202
+ }
203
+ }
204
+ }
@@ -0,0 +1 @@
1
+ export {};