@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,729 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useState } from 'react';
3
+ import { MemoryRouter, useInRouterContext, useLocation, useNavigate } from 'react-router-dom';
4
+ import { useTaskforce } from './hooks/useTaskforce';
5
+ import { WidgetView } from './components/views/WidgetView';
6
+ import { StandaloneLayout } from './components/views/StandaloneLayout';
7
+ import styles from './Taskforce.module.css';
8
+ import { t } from './localization';
9
+ import { resolveWorkspaceLifecycleState } from './utils/workspaceLifecycle';
10
+ import logo from './assets/branding/logos/logo_white_01.png';
11
+ import taskforceBg from './assets/images/taskforce.png';
12
+ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange, onHeaderMouseDown, isDragging, onClose, mode = 'standalone' }) {
13
+ const location = useLocation();
14
+ const navigate = useNavigate();
15
+ const [loginEmail, setLoginEmail] = useState('');
16
+ const [loginPassword, setLoginPassword] = useState('');
17
+ const [authMode, setAuthMode] = useState('login');
18
+ const [verificationToken, setVerificationToken] = useState('');
19
+ const [resetToken, setResetToken] = useState('');
20
+ const [inviteToken, setInviteToken] = useState('');
21
+ const [inviteEmail, setInviteEmail] = useState(null);
22
+ const [inviteWorkspaceId, setInviteWorkspaceId] = useState(null);
23
+ const [loginNotice, setLoginNotice] = useState(null);
24
+ const [loginError, setLoginError] = useState(null);
25
+ const [loginErrorCode, setLoginErrorCode] = useState(null);
26
+ const [loginBusy, setLoginBusy] = useState(false);
27
+ const [verifyCooldownUntil, setVerifyCooldownUntil] = useState(0);
28
+ const [resetCooldownUntil, setResetCooldownUntil] = useState(0);
29
+ const [cooldownNow, setCooldownNow] = useState(() => Date.now());
30
+ const [setupModeChoice, setSetupModeChoice] = useState('core');
31
+ const [setupBusy, setSetupBusy] = useState(false);
32
+ const [setupError, setSetupError] = useState(null);
33
+ const [setupNotice, setSetupNotice] = useState(null);
34
+ const [workspaceNameInput, setWorkspaceNameInput] = useState('');
35
+ const [workspaceDescriptionInput, setWorkspaceDescriptionInput] = useState('');
36
+ const [workspaceSetupSource, setWorkspaceSetupSource] = useState('local');
37
+ const [cloudWorkspaceOptions, setCloudWorkspaceOptions] = useState([]);
38
+ const [cloudWorkspaceSelection, setCloudWorkspaceSelection] = useState('');
39
+ const [cloudWorkspaceLoading, setCloudWorkspaceLoading] = useState(false);
40
+ const [cloudWorkspaceError, setCloudWorkspaceError] = useState(null);
41
+ const [syncNewLocalWorkspaceToCloud, setSyncNewLocalWorkspaceToCloud] = useState(false);
42
+ const [bootstrapRetryBusy, setBootstrapRetryBusy] = useState(false);
43
+ // Initialize the hook
44
+ const taskforceState = useTaskforce({
45
+ config,
46
+ initialTaskId,
47
+ onTaskCountChange,
48
+ onClose
49
+ });
50
+ const { runtimeMode, workspaceSwitchingEnabled, currentWorkspaceId, configLoaded, cloudAuthConfigured, authRequiredForApi, authBlocked, isAuthenticated, hasBetaAccess, authSessionResolved, workspaceBootstrapPending, bootstrapPhase, bootstrapError, setupState, runtimeCapabilities, refreshSetupContext, retryBootstrapChecks, saveWorkspaceProfile, fetchWorkspaces, applyWorkspaceSyncStateSnapshot, loginWithCredentials, registerWithCredentials, requestEmailVerification, confirmEmailVerification, requestPasswordReset, confirmPasswordReset, inspectInviteAcceptance, acceptInviteWithToken, currentTheme, logout } = taskforceState;
51
+ const normalizedCloudAuthBase = useMemo(() => {
52
+ const raw = String(config.cloudAuthBaseUrl || config.apiBaseUrl || '').trim();
53
+ if (!raw)
54
+ return '';
55
+ return raw.replace(/\/+$/, '');
56
+ }, [config.apiBaseUrl, config.cloudAuthBaseUrl]);
57
+ const isCloudRuntime = runtimeMode === 'cloud' || runtimeCapabilities?.runtimeMode === 'cloud';
58
+ const canUseCloudWorkspaceSetup = !isCloudRuntime && cloudAuthConfigured && Boolean(normalizedCloudAuthBase);
59
+ const isLikelyCloudAppHost = typeof window !== 'undefined' && /^app\./i.test(window.location.hostname);
60
+ const isCloudAuthRequired = runtimeMode === 'cloud' && authRequiredForApi;
61
+ const shouldForceForAuthBlocked = runtimeMode === 'cloud' && authBlocked;
62
+ const shouldForceLogin = isLikelyCloudAppHost
63
+ ? (!isAuthenticated || authBlocked)
64
+ : ((isCloudAuthRequired && !isAuthenticated) || shouldForceForAuthBlocked);
65
+ const shouldForceComingSoon = runtimeMode === 'cloud' && isAuthenticated && !hasBetaAccess;
66
+ const isLoginRoute = location.pathname === '/login';
67
+ const isSetupRoute = location.pathname === '/setup';
68
+ const isComingSoonRoute = location.pathname === '/coming-soon';
69
+ const setupStep = useMemo(() => String(new URLSearchParams(location.search).get('step') || '').trim().toLowerCase(), [location.search]);
70
+ const shouldHoldForAuthBootstrap = mode !== 'widget'
71
+ && !authSessionResolved
72
+ && !isLoginRoute
73
+ && !isSetupRoute
74
+ && (runtimeMode === 'cloud' || isLikelyCloudAppHost);
75
+ const workspaceLifecycle = useMemo(() => resolveWorkspaceLifecycleState({
76
+ setupState: setupState
77
+ ? {
78
+ globalSetupState: setupState.globalSetupState,
79
+ workspaceSetupState: setupState.workspaceSetupState,
80
+ runtimeMode: setupState.runtimeMode,
81
+ workspaceId: setupState.workspaceId,
82
+ mode: setupState.mode,
83
+ forceSetup: setupState.forceSetup,
84
+ forceGlobalSetup: setupState.forceGlobalSetup,
85
+ forceWorkspaceSetup: setupState.forceWorkspaceSetup
86
+ }
87
+ : null,
88
+ runtimeMode,
89
+ isAuthenticated
90
+ }), [setupState, runtimeMode, isAuthenticated]);
91
+ const setupGateActive = workspaceLifecycle.setupGateActive;
92
+ const needsGlobalSetup = workspaceLifecycle.needsGlobalSetup;
93
+ const needsWorkspaceSetup = workspaceLifecycle.needsWorkspaceSetup;
94
+ const hasSetupReadError = workspaceLifecycle.hasSetupReadError;
95
+ const shouldHoldForSetupBootstrap = mode !== 'widget'
96
+ && authSessionResolved
97
+ && !shouldForceLogin
98
+ && !shouldForceComingSoon
99
+ && (!configLoaded || workspaceBootstrapPending || bootstrapPhase === 'stalled')
100
+ && (isSetupRoute || runtimeMode === 'cloud' || isLikelyCloudAppHost);
101
+ const bootstrapSubtitle = useMemo(() => {
102
+ if (bootstrapPhase === 'auth')
103
+ return 'Verifying session...';
104
+ if (bootstrapPhase === 'workspace')
105
+ return 'Resolving workspace access...';
106
+ if (bootstrapPhase === 'config')
107
+ return 'Loading configuration...';
108
+ return 'Checking account, workspace access, and setup status...';
109
+ }, [bootstrapPhase]);
110
+ const isPlaceholderWorkspaceName = useCallback((name, workspaceId, _description) => {
111
+ const normalizedName = String(name || '').trim().toLowerCase();
112
+ const normalizedWorkspaceId = String(workspaceId || '').trim().toLowerCase();
113
+ if (!normalizedName)
114
+ return true;
115
+ if (normalizedName === 'system default workspace')
116
+ return true;
117
+ if (normalizedWorkspaceId && normalizedName === normalizedWorkspaceId)
118
+ return true;
119
+ return false;
120
+ }, []);
121
+ useEffect(() => {
122
+ const modeValue = setupState?.mode === 'operations' ? 'operations' : 'core';
123
+ setSetupModeChoice(modeValue);
124
+ }, [setupState?.mode]);
125
+ useEffect(() => {
126
+ if (!setupState)
127
+ return;
128
+ const currentName = String(setupState.workspace?.name || '').trim();
129
+ const suggested = String(setupState.suggestedWorkspaceName || '').trim();
130
+ const preferredName = isPlaceholderWorkspaceName(currentName, setupState.workspaceId, setupState.workspace?.description)
131
+ ? suggested
132
+ : currentName;
133
+ setWorkspaceNameInput(preferredName || suggested || currentName);
134
+ setWorkspaceDescriptionInput(String(setupState.workspace?.description || ''));
135
+ }, [
136
+ setupState?.workspace?.name,
137
+ setupState?.workspace?.description,
138
+ setupState?.suggestedWorkspaceName,
139
+ setupState?.workspaceId,
140
+ isPlaceholderWorkspaceName
141
+ ]);
142
+ useEffect(() => {
143
+ if (!isSetupRoute || setupStep !== 'workspace')
144
+ return;
145
+ const source = String(new URLSearchParams(location.search).get('source') || '').trim().toLowerCase();
146
+ if (source === 'cloud' && canUseCloudWorkspaceSetup) {
147
+ setWorkspaceSetupSource('cloud');
148
+ setSyncNewLocalWorkspaceToCloud(false);
149
+ return;
150
+ }
151
+ setWorkspaceSetupSource('local');
152
+ }, [canUseCloudWorkspaceSetup, isSetupRoute, location.search, setupStep]);
153
+ const fetchCloudWorkspaceOptions = useCallback(async () => {
154
+ if (!canUseCloudWorkspaceSetup || !isAuthenticated) {
155
+ setCloudWorkspaceOptions([]);
156
+ setCloudWorkspaceSelection('');
157
+ return;
158
+ }
159
+ setCloudWorkspaceLoading(true);
160
+ setCloudWorkspaceError(null);
161
+ try {
162
+ const res = await fetch(`${normalizedCloudAuthBase}/api/taskforce/workspaces`, {
163
+ method: 'GET',
164
+ credentials: 'include'
165
+ });
166
+ const data = await res.json().catch(() => ({}));
167
+ if (!res.ok || data?.success === false) {
168
+ setCloudWorkspaceOptions([]);
169
+ setCloudWorkspaceSelection('');
170
+ setCloudWorkspaceError(data?.error || `Failed to load cloud projects (${res.status})`);
171
+ return;
172
+ }
173
+ const cloudWorkspaces = Array.isArray(data?.workspaces)
174
+ ? data.workspaces
175
+ .map((workspace) => ({
176
+ id: String(workspace?.id || '').trim(),
177
+ name: String(workspace?.name || workspace?.id || '').trim(),
178
+ description: typeof workspace?.description === 'string' ? workspace.description : null
179
+ }))
180
+ .filter((workspace) => workspace.id.length > 0)
181
+ : [];
182
+ setCloudWorkspaceOptions(cloudWorkspaces);
183
+ setCloudWorkspaceSelection((prev) => {
184
+ if (prev && cloudWorkspaces.some((workspace) => workspace.id === prev))
185
+ return prev;
186
+ return cloudWorkspaces[0]?.id || '';
187
+ });
188
+ }
189
+ catch {
190
+ setCloudWorkspaceOptions([]);
191
+ setCloudWorkspaceSelection('');
192
+ setCloudWorkspaceError('Failed to load cloud projects.');
193
+ }
194
+ finally {
195
+ setCloudWorkspaceLoading(false);
196
+ }
197
+ }, [canUseCloudWorkspaceSetup, isAuthenticated, normalizedCloudAuthBase]);
198
+ useEffect(() => {
199
+ if (workspaceSetupSource !== 'cloud')
200
+ return;
201
+ void fetchCloudWorkspaceOptions();
202
+ }, [fetchCloudWorkspaceOptions, workspaceSetupSource]);
203
+ const nextPath = useMemo(() => {
204
+ const raw = new URLSearchParams(location.search).get('next') || '/';
205
+ if (!raw.startsWith('/'))
206
+ return '/';
207
+ if (raw === '/login')
208
+ return '/';
209
+ return raw;
210
+ }, [location.search]);
211
+ const loginRouteMode = useMemo(() => {
212
+ const modeRaw = String(new URLSearchParams(location.search).get('mode') || '').trim().toLowerCase();
213
+ if (modeRaw === 'register' || modeRaw === 'verify' || modeRaw === 'forgot' || modeRaw === 'reset' || modeRaw === 'invite') {
214
+ return modeRaw;
215
+ }
216
+ return 'login';
217
+ }, [location.search]);
218
+ const loginRouteToken = useMemo(() => String(new URLSearchParams(location.search).get('token') || '').trim(), [location.search]);
219
+ const setLoginMode = useCallback((mode) => {
220
+ const params = new URLSearchParams(location.search);
221
+ if (mode === 'login') {
222
+ params.delete('mode');
223
+ }
224
+ else {
225
+ params.set('mode', mode);
226
+ }
227
+ const query = params.toString();
228
+ navigate(`/login${query ? `?${query}` : ''}`, { replace: true });
229
+ }, [location.search, navigate]);
230
+ const routeToWorkspaceSetupIfNeeded = useCallback(async (hintWorkspaceSetupRequired) => {
231
+ if (!workspaceSwitchingEnabled)
232
+ return false;
233
+ const workspacesResult = await fetchWorkspaces();
234
+ if (workspacesResult.success) {
235
+ const workspaceCount = Array.isArray(workspacesResult.workspaces)
236
+ ? workspacesResult.workspaces.length
237
+ : 0;
238
+ if (workspaceCount === 0) {
239
+ navigate('/setup?step=workspace', { replace: true });
240
+ return true;
241
+ }
242
+ return false;
243
+ }
244
+ if (hintWorkspaceSetupRequired) {
245
+ navigate('/setup?step=workspace', { replace: true });
246
+ return true;
247
+ }
248
+ return false;
249
+ }, [fetchWorkspaces, navigate, workspaceSwitchingEnabled]);
250
+ useEffect(() => {
251
+ if (!isLoginRoute)
252
+ return;
253
+ setAuthMode(loginRouteMode);
254
+ if (loginRouteMode === 'verify' && loginRouteToken)
255
+ setVerificationToken(loginRouteToken);
256
+ if (loginRouteMode === 'reset' && loginRouteToken)
257
+ setResetToken(loginRouteToken);
258
+ if (loginRouteMode === 'invite' && loginRouteToken)
259
+ setInviteToken(loginRouteToken);
260
+ }, [isLoginRoute, loginRouteMode, loginRouteToken]);
261
+ useEffect(() => {
262
+ if (!isLoginRoute || authMode !== 'invite' || !inviteToken.trim())
263
+ return;
264
+ let active = true;
265
+ (async () => {
266
+ const inspected = await inspectInviteAcceptance(inviteToken);
267
+ if (!active)
268
+ return;
269
+ if (inspected.success) {
270
+ setInviteEmail(inspected.email || null);
271
+ setInviteWorkspaceId(inspected.workspaceId || null);
272
+ setLoginNotice('Invite ready. Set your password to join.');
273
+ setLoginError(null);
274
+ setLoginErrorCode(null);
275
+ }
276
+ else {
277
+ setInviteEmail(null);
278
+ setInviteWorkspaceId(null);
279
+ setLoginError(formatAuthError(inspected));
280
+ setLoginErrorCode(inspected.code || inspected.state || null);
281
+ }
282
+ })();
283
+ return () => { active = false; };
284
+ }, [isLoginRoute, authMode, inviteToken, inspectInviteAcceptance]);
285
+ useEffect(() => {
286
+ const hasCooldown = verifyCooldownUntil > Date.now() || resetCooldownUntil > Date.now();
287
+ if (!hasCooldown)
288
+ return;
289
+ const id = window.setInterval(() => setCooldownNow(Date.now()), 1000);
290
+ return () => window.clearInterval(id);
291
+ }, [verifyCooldownUntil, resetCooldownUntil]);
292
+ const verifyCooldownSeconds = Math.max(0, Math.ceil((verifyCooldownUntil - cooldownNow) / 1000));
293
+ const resetCooldownSeconds = Math.max(0, Math.ceil((resetCooldownUntil - cooldownNow) / 1000));
294
+ const verifyCooldownActive = verifyCooldownSeconds > 0;
295
+ const resetCooldownActive = resetCooldownSeconds > 0;
296
+ const formatAuthError = (result) => {
297
+ const message = result.error || 'Request failed.';
298
+ const code = result.code || result.state;
299
+ return code ? `[${code}] ${message}` : message;
300
+ };
301
+ useEffect(() => {
302
+ if (mode === 'widget')
303
+ return;
304
+ if (workspaceBootstrapPending)
305
+ return;
306
+ if (shouldForceComingSoon) {
307
+ if (!isComingSoonRoute)
308
+ navigate('/coming-soon', { replace: true });
309
+ return;
310
+ }
311
+ if (isComingSoonRoute && !shouldForceComingSoon) {
312
+ navigate('/', { replace: true });
313
+ return;
314
+ }
315
+ if (!shouldForceLogin) {
316
+ if (isLoginRoute && isAuthenticated)
317
+ navigate(nextPath, { replace: true });
318
+ }
319
+ else {
320
+ if (!isLoginRoute) {
321
+ const target = `${location.pathname}${location.search}${location.hash}`;
322
+ navigate(`/login?next=${encodeURIComponent(target || '/')}`, { replace: true });
323
+ return;
324
+ }
325
+ return;
326
+ }
327
+ if (setupGateActive) {
328
+ if (hasSetupReadError) {
329
+ if (!isSetupRoute || setupStep !== 'error') {
330
+ navigate('/setup?step=error', { replace: true });
331
+ }
332
+ return;
333
+ }
334
+ if (needsGlobalSetup) {
335
+ if (!isSetupRoute || setupStep !== 'global') {
336
+ navigate('/setup?step=global', { replace: true });
337
+ }
338
+ return;
339
+ }
340
+ if (needsWorkspaceSetup) {
341
+ if (!isSetupRoute || setupStep !== 'workspace') {
342
+ navigate('/setup?step=workspace', { replace: true });
343
+ }
344
+ return;
345
+ }
346
+ if (isSetupRoute) {
347
+ navigate('/', { replace: true });
348
+ }
349
+ return;
350
+ }
351
+ if (isSetupRoute && setupState) {
352
+ navigate('/', { replace: true });
353
+ }
354
+ }, [
355
+ mode,
356
+ shouldForceLogin,
357
+ shouldForceComingSoon,
358
+ isLoginRoute,
359
+ isSetupRoute,
360
+ isComingSoonRoute,
361
+ setupGateActive,
362
+ setupState,
363
+ hasSetupReadError,
364
+ needsGlobalSetup,
365
+ needsWorkspaceSetup,
366
+ setupStep,
367
+ workspaceBootstrapPending,
368
+ location.pathname,
369
+ location.search,
370
+ location.hash,
371
+ navigate,
372
+ nextPath
373
+ ]);
374
+ useEffect(() => {
375
+ if (mode === 'widget')
376
+ return;
377
+ if (runtimeMode !== 'local')
378
+ return;
379
+ if (!configLoaded)
380
+ return;
381
+ if (isLoginRoute || isSetupRoute)
382
+ return;
383
+ const workspaceId = String(currentWorkspaceId || '').trim().toLowerCase();
384
+ if (!workspaceId || workspaceId === 'default') {
385
+ navigate('/setup?step=workspace', { replace: true });
386
+ }
387
+ }, [mode, runtimeMode, configLoaded, isLoginRoute, isSetupRoute, currentWorkspaceId, navigate]);
388
+ const handleRetryBootstrap = useCallback(async () => {
389
+ setBootstrapRetryBusy(true);
390
+ try {
391
+ await retryBootstrapChecks();
392
+ }
393
+ finally {
394
+ setBootstrapRetryBusy(false);
395
+ }
396
+ }, [retryBootstrapChecks]);
397
+ const handleGoToSignIn = useCallback(async () => {
398
+ await logout();
399
+ navigate('/login', { replace: true });
400
+ }, [logout, navigate]);
401
+ // Standalone-first: widget remains opt-in only.
402
+ if (mode === 'widget') {
403
+ return (_jsx(WidgetView, { ...taskforceState, onHeaderMouseDown: onHeaderMouseDown, isDragging: isDragging, onClose: onClose }));
404
+ }
405
+ if (shouldHoldForAuthBootstrap) {
406
+ return (_jsx("div", { className: styles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: styles.loginView, children: _jsxs("div", { className: styles.loginCard, children: [_jsxs("div", { className: styles.authBrandRow, children: [_jsx("img", { src: logo, alt: "Taskforce", className: styles.loginLogo }), _jsx("h1", { className: styles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: styles.loginSubtitle, children: "Checking your session..." })] }) }) }));
407
+ }
408
+ if (shouldHoldForSetupBootstrap) {
409
+ return (_jsx("div", { className: styles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: styles.loginView, children: _jsxs("div", { className: styles.loginCard, children: [_jsxs("div", { className: styles.authBrandRow, children: [_jsx("img", { src: logo, alt: "Taskforce", className: styles.loginLogo }), _jsx("h1", { className: styles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: styles.loginSubtitle, children: bootstrapSubtitle }), bootstrapPhase === 'stalled' && (_jsxs(_Fragment, { children: [_jsx("p", { className: styles.loginError, children: bootstrapError || 'Startup checks timed out.' }), _jsx("button", { className: styles.submitBtn, disabled: bootstrapRetryBusy, onClick: handleRetryBootstrap, children: bootstrapRetryBusy ? 'Retrying...' : 'Retry checks' }), isCloudRuntime && (_jsx("button", { className: styles.cancelBtn, disabled: bootstrapRetryBusy, onClick: handleGoToSignIn, children: "Go to sign-in" }))] }))] }) }) }));
410
+ }
411
+ if (isLoginRoute) {
412
+ return (_jsx("div", { className: styles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: styles.loginView, style: {
413
+ backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
414
+ }, children: _jsxs("div", { className: styles.loginCard, children: [!isCloudRuntime && !shouldForceLogin && (_jsx("button", { className: styles.loginCloseBtn, "aria-label": "Close sign in", onClick: () => navigate(nextPath, { replace: true }), children: "\u00D7" })), _jsxs("div", { className: styles.authBrandRow, children: [_jsx("img", { src: logo, alt: "Taskforce", className: styles.loginLogo }), _jsxs("h1", { className: styles.loginTitle, children: ["TASKFORCE ", _jsx("span", { className: styles.loginTitleAccent, children: "HQ" })] })] }), _jsxs("p", { className: styles.loginSubtitle, children: [authMode === 'login' && 'Sign in with your account credentials.', authMode === 'register' && 'Create your Taskforce account.', authMode === 'verify' && 'Enter your verification token.', authMode === 'forgot' && 'Request a password reset link.', authMode === 'reset' && 'Set a new password using your reset token.', authMode === 'invite' && 'Accept your invite and create a password.'] }), (authMode === 'login' || authMode === 'register' || authMode === 'forgot') && (_jsx("input", { className: styles.input, type: "email", value: loginEmail, placeholder: "Email", onChange: (event) => setLoginEmail(event.target.value) })), (authMode === 'login' || authMode === 'register' || authMode === 'reset') && (_jsx("input", { className: styles.input, type: "password", value: loginPassword, placeholder: authMode === 'reset' ? 'New password' : 'Password', onChange: (event) => setLoginPassword(event.target.value) })), authMode === 'verify' && (_jsx("input", { className: styles.input, type: "text", value: verificationToken, placeholder: "Verification token", onChange: (event) => setVerificationToken(event.target.value) })), authMode === 'reset' && (_jsx("input", { className: styles.input, type: "text", value: resetToken, placeholder: "Reset token", onChange: (event) => setResetToken(event.target.value) })), authMode === 'invite' && (_jsxs(_Fragment, { children: [_jsx("input", { className: styles.input, type: "text", value: inviteToken, placeholder: "Invite token", onChange: (event) => setInviteToken(event.target.value) }), inviteEmail && (_jsxs("p", { className: styles.loginSubtitle, children: ["Invite for: ", _jsx("strong", { children: inviteEmail }), inviteWorkspaceId ? ` · Workspace: ${inviteWorkspaceId}` : ''] }))] })), loginNotice && _jsx("p", { className: styles.loginSubtitle, children: loginNotice }), loginError && _jsx("p", { className: styles.loginError, children: loginError }), authMode === 'login' && loginErrorCode === 'EMAIL_NOT_VERIFIED' && loginEmail.trim() && (_jsx("button", { className: styles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: async () => {
415
+ setLoginBusy(true);
416
+ setLoginNotice(null);
417
+ const sent = await requestEmailVerification(loginEmail);
418
+ if (sent.success) {
419
+ setVerifyCooldownUntil(Date.now() + 30_000);
420
+ setLoginMode('verify');
421
+ if (sent.verificationToken)
422
+ setVerificationToken(sent.verificationToken);
423
+ setLoginNotice('Verification email resent.');
424
+ setLoginError(null);
425
+ setLoginErrorCode(null);
426
+ }
427
+ else {
428
+ setLoginError(formatAuthError(sent));
429
+ }
430
+ setLoginBusy(false);
431
+ }, children: verifyCooldownActive ? `Resend in ${verifyCooldownSeconds}s` : 'Resend Verification Email' })), _jsx("button", { className: styles.submitBtn, disabled: loginBusy || (authMode === 'verify' && verifyCooldownActive) || (authMode === 'forgot' && resetCooldownActive), onClick: async () => {
432
+ setLoginBusy(true);
433
+ setLoginNotice(null);
434
+ setLoginError(null);
435
+ setLoginErrorCode(null);
436
+ let result = { success: false };
437
+ if (authMode === 'login') {
438
+ result = await loginWithCredentials(loginEmail, loginPassword);
439
+ }
440
+ else if (authMode === 'register') {
441
+ result = await registerWithCredentials(loginEmail, loginPassword);
442
+ }
443
+ else if (authMode === 'verify') {
444
+ result = await confirmEmailVerification(verificationToken);
445
+ }
446
+ else if (authMode === 'forgot') {
447
+ result = await requestPasswordReset(loginEmail);
448
+ }
449
+ else if (authMode === 'reset') {
450
+ result = await confirmPasswordReset(resetToken, loginPassword);
451
+ }
452
+ else if (authMode === 'invite') {
453
+ result = await acceptInviteWithToken(inviteToken, loginPassword);
454
+ }
455
+ if (!result.success) {
456
+ setLoginError(formatAuthError(result));
457
+ setLoginErrorCode(result.code || null);
458
+ if (authMode === 'login' && (result.code === 'WORKSPACE_NOT_FOUND' || result.code === 'WORKSPACE_ID_REQUIRED')) {
459
+ navigate('/setup?step=workspace', { replace: true });
460
+ setLoginBusy(false);
461
+ return;
462
+ }
463
+ if (authMode === 'login' && result.code === 'EMAIL_NOT_VERIFIED' && loginEmail.trim()) {
464
+ const sent = await requestEmailVerification(loginEmail);
465
+ if (sent.success) {
466
+ setVerifyCooldownUntil(Date.now() + 30_000);
467
+ setLoginMode('verify');
468
+ if (sent.verificationToken)
469
+ setVerificationToken(sent.verificationToken);
470
+ setLoginNotice('Email not verified. A verification token was sent.');
471
+ setLoginError(null);
472
+ setLoginErrorCode(null);
473
+ }
474
+ }
475
+ }
476
+ else if (authMode === 'register') {
477
+ if (await routeToWorkspaceSetupIfNeeded(result.workspaceSetupRequired)) {
478
+ setLoginBusy(false);
479
+ return;
480
+ }
481
+ if (result.verificationToken)
482
+ setVerificationToken(result.verificationToken);
483
+ setVerifyCooldownUntil(Date.now() + 30_000);
484
+ setLoginMode('verify');
485
+ setLoginNotice(result.emailSent === false
486
+ ? `Account created, but verification email failed to send. ${result.emailError || 'Try Resend Verification again.'}`
487
+ : 'Account created. Check your email for verification instructions.');
488
+ }
489
+ else if (authMode === 'verify') {
490
+ setLoginMode('login');
491
+ setLoginNotice('Email verified. You can sign in now.');
492
+ }
493
+ else if (authMode === 'forgot') {
494
+ if (result.resetToken)
495
+ setResetToken(result.resetToken);
496
+ setResetCooldownUntil(Date.now() + 30_000);
497
+ setLoginMode('reset');
498
+ setLoginNotice(result.emailSent === false
499
+ ? `Password reset email failed to send. ${result.emailError || 'Try again in a minute.'}`
500
+ : 'Password reset instructions sent.');
501
+ }
502
+ else if (authMode === 'reset') {
503
+ setLoginMode('login');
504
+ setLoginNotice('Password updated. Sign in with your new password.');
505
+ }
506
+ else if (authMode === 'invite') {
507
+ if (result.workspaceSetupRequired) {
508
+ navigate('/setup?step=workspace', { replace: true });
509
+ setLoginBusy(false);
510
+ return;
511
+ }
512
+ navigate(nextPath, { replace: true });
513
+ }
514
+ else if (authMode === 'login') {
515
+ if (result.workspaceSetupRequired) {
516
+ navigate('/setup?step=workspace', { replace: true });
517
+ setLoginBusy(false);
518
+ return;
519
+ }
520
+ setLoginEmail('');
521
+ setLoginPassword('');
522
+ navigate(nextPath, { replace: true });
523
+ }
524
+ else {
525
+ setLoginEmail('');
526
+ setLoginPassword('');
527
+ navigate(nextPath, { replace: true });
528
+ }
529
+ setLoginBusy(false);
530
+ }, children: loginBusy ? 'Working...' : (authMode === 'login' ? 'Sign In'
531
+ : authMode === 'register' ? 'Create Account'
532
+ : authMode === 'verify'
533
+ ? (verifyCooldownActive ? `Resend in ${verifyCooldownSeconds}s` : 'Resend Verification')
534
+ : authMode === 'forgot'
535
+ ? (resetCooldownActive ? `Retry in ${resetCooldownSeconds}s` : 'Send Reset Link')
536
+ : authMode === 'reset'
537
+ ? 'Reset Password'
538
+ : 'Accept Invite') }), (authMode === 'login' || authMode === 'register') && (_jsxs("p", { className: styles.authModeSwitch, children: [authMode === 'login' ? 'Need an account?' : 'Already have an account?', ' ', _jsx("button", { className: styles.authModeSwitchLink, disabled: loginBusy, onClick: () => {
539
+ setLoginError(null);
540
+ setLoginErrorCode(null);
541
+ setLoginNotice(null);
542
+ setLoginMode(authMode === 'login' ? 'register' : 'login');
543
+ }, children: authMode === 'login' ? 'Register' : 'Sign In' })] })), _jsxs("div", { className: styles.authModeLinks, children: [(authMode === 'login' || authMode === 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: styles.authModeLink, disabled: loginBusy || resetCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }), _jsx("button", { className: styles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('verify'); }, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' }), _jsx("button", { className: styles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('invite'); }, children: "Accept Invite" })] })), (authMode !== 'login' && authMode !== 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: styles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('login'); }, children: "Sign In" }), _jsx("button", { className: styles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('register'); }, children: "Register" }), authMode === 'reset' && (_jsx("button", { className: styles.authModeLink, disabled: loginBusy || resetCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }))] }))] })] }) }) }));
544
+ }
545
+ if (shouldForceLogin && !isLoginRoute) {
546
+ return (_jsx("div", { className: styles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: styles.loginView, children: _jsxs("div", { className: styles.loginCard, children: [_jsxs("div", { className: styles.authBrandRow, children: [_jsx("img", { src: logo, alt: "Taskforce", className: styles.loginLogo }), _jsx("h1", { className: styles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: styles.loginSubtitle, children: "Redirecting to sign in..." })] }) }) }));
547
+ }
548
+ if (isComingSoonRoute && shouldForceComingSoon) {
549
+ return (_jsx("div", { className: styles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: styles.loginView, style: {
550
+ backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
551
+ }, children: _jsxs("div", { className: styles.loginCard, children: [_jsxs("div", { className: styles.authBrandRow, children: [_jsx("img", { src: logo, alt: "Taskforce", className: styles.loginLogo }), _jsx("h1", { className: styles.loginTitle, children: "Private Beta" })] }), _jsx("p", { className: styles.loginSubtitle, children: "You are signed in, but your account is not in the beta allowlist yet." }), _jsx("p", { className: styles.loginSubtitle, children: "You will see the full app as soon as beta access is enabled." }), _jsx("button", { className: styles.cancelBtn, onClick: async () => { await taskforceState.logout(); navigate('/login', { replace: true }); }, children: "Sign Out" })] }) }) }));
552
+ }
553
+ if (isSetupRoute && setupGateActive && (hasSetupReadError || needsGlobalSetup || needsWorkspaceSetup)) {
554
+ const isError = hasSetupReadError || setupStep === 'error';
555
+ const isGlobal = !isError && (needsGlobalSetup || setupStep === 'global');
556
+ const heading = isError
557
+ ? t('setup.headingCheckFailed')
558
+ : (isGlobal ? t('setup.headingGlobalRequired') : t('setup.headingWorkspaceRequired'));
559
+ const subtitle = isError
560
+ ? t('setup.subtitleUnreadable')
561
+ : isGlobal
562
+ ? t('setup.subtitleGlobalRequired')
563
+ : t('setup.subtitleWorkspaceRequired');
564
+ const workspaceLabel = setupModeChoice === 'operations'
565
+ ? t('setup.workspaceTermMission')
566
+ : t('setup.workspaceTermProject');
567
+ return (_jsx("div", { className: styles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: styles.loginView, style: {
568
+ backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
569
+ }, children: _jsxs("div", { className: styles.loginCard, children: [_jsxs("div", { className: styles.authBrandRow, children: [_jsx("img", { src: logo, alt: "Taskforce", className: styles.loginLogo }), _jsxs("h1", { className: styles.loginTitle, children: ["TASKFORCE ", _jsx("span", { className: styles.loginTitleAccent, children: "HQ" })] })] }), _jsx("p", { className: styles.loginSubtitle, children: _jsx("strong", { children: heading }) }), _jsx("p", { className: styles.loginSubtitle, children: subtitle }), runtimeCapabilities && (_jsxs("p", { className: styles.loginSubtitle, children: [t('setup.runtimeLabel'), ": ", _jsx("strong", { children: runtimeCapabilities.runtimeMode })] })), setupNotice && _jsx("p", { className: styles.loginSubtitle, children: setupNotice }), setupError && _jsx("p", { className: styles.loginError, children: setupError }), isGlobal && (_jsxs("div", { style: { display: 'grid', gap: 10, textAlign: 'left' }, children: [_jsxs("label", { className: styles.authModeLink, style: { display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer' }, children: [_jsx("input", { type: "radio", name: "setup-mode", value: "core", checked: setupModeChoice === 'core', onChange: () => setSetupModeChoice('core'), disabled: setupBusy }), _jsx("span", { children: t('setup.coreModeOption', { workspaceLabel }) })] }), _jsxs("label", { className: styles.authModeLink, style: { display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer' }, children: [_jsx("input", { type: "radio", name: "setup-mode", value: "operations", checked: setupModeChoice === 'operations', onChange: () => setSetupModeChoice('operations'), disabled: setupBusy }), _jsx("span", { children: t('setup.operationsModeOption') })] })] })), !isError && !isGlobal && (_jsxs("div", { style: { display: 'grid', gap: 10, textAlign: 'left' }, children: [!isCloudRuntime && canUseCloudWorkspaceSetup && (_jsxs("div", { style: { display: 'grid', gap: 8 }, children: [_jsxs("label", { className: styles.authModeLink, style: { display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer' }, children: [_jsx("input", { type: "radio", name: "workspace-setup-source", value: "local", checked: workspaceSetupSource === 'local', onChange: () => setWorkspaceSetupSource('local'), disabled: setupBusy }), _jsxs("span", { children: ["Create new local ", workspaceLabel.toLowerCase()] })] }), _jsxs("label", { className: styles.authModeLink, style: { display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer' }, children: [_jsx("input", { type: "radio", name: "workspace-setup-source", value: "cloud", checked: workspaceSetupSource === 'cloud', onChange: () => setWorkspaceSetupSource('cloud'), disabled: setupBusy }), _jsxs("span", { children: ["Sync existing cloud ", workspaceLabel.toLowerCase()] })] })] })), !isCloudRuntime && workspaceSetupSource === 'cloud' && canUseCloudWorkspaceSetup ? (_jsxs("div", { style: { display: 'grid', gap: 8 }, children: [!isAuthenticated && (_jsxs(_Fragment, { children: [_jsx("p", { className: styles.loginSubtitle, style: { margin: 0 }, children: "Sign in to choose one of your cloud projects." }), _jsx("button", { className: styles.cancelBtn, disabled: setupBusy, onClick: () => {
570
+ navigate(`/login?mode=login&next=${encodeURIComponent('/setup?step=workspace&source=cloud')}`, { replace: true });
571
+ }, children: "Sign In" })] })), isAuthenticated && (_jsxs(_Fragment, { children: [_jsxs("select", { className: styles.input, value: cloudWorkspaceSelection, onChange: (event) => setCloudWorkspaceSelection(event.target.value), disabled: setupBusy || cloudWorkspaceLoading || cloudWorkspaceOptions.length === 0, children: [cloudWorkspaceOptions.length === 0 && (_jsx("option", { value: "", children: cloudWorkspaceLoading ? 'Loading cloud projects...' : 'No cloud projects found' })), cloudWorkspaceOptions.map((workspace) => (_jsxs("option", { value: workspace.id, children: [workspace.name, " (", workspace.id, ")"] }, workspace.id)))] }), _jsx("div", { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 }, children: _jsx("button", { className: styles.cancelBtn, disabled: setupBusy || cloudWorkspaceLoading, onClick: () => void fetchCloudWorkspaceOptions(), children: "Refresh Cloud Projects" }) }), cloudWorkspaceError && _jsx("p", { className: styles.loginError, children: cloudWorkspaceError })] }))] })) : (_jsxs(_Fragment, { children: [_jsx("input", { className: styles.input, type: "text", value: workspaceNameInput, placeholder: t('setup.workspaceNamePlaceholder', { workspaceLabel }), onChange: (event) => setWorkspaceNameInput(event.target.value), disabled: setupBusy }), _jsx("textarea", { className: styles.textarea, value: workspaceDescriptionInput, placeholder: t('setup.workspaceDescriptionPlaceholder', { workspaceLabel }), onChange: (event) => setWorkspaceDescriptionInput(event.target.value), disabled: setupBusy, rows: 4 }), !isCloudRuntime && canUseCloudWorkspaceSetup && isAuthenticated && (_jsxs("div", { style: { display: 'grid', gap: 4 }, children: [_jsxs("label", { className: styles.authModeLink, style: { display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer' }, children: [_jsx("input", { type: "checkbox", checked: syncNewLocalWorkspaceToCloud, onChange: (event) => setSyncNewLocalWorkspaceToCloud(event.target.checked), disabled: setupBusy }), _jsx("span", { children: "Sync to cloud after setup" })] }), _jsx("p", { style: { margin: 0, color: 'var(--text-muted)', fontSize: '12px' }, children: "When enabled, this project will connect to cloud sync as soon as setup finishes." })] }))] }))] })), _jsxs("div", { className: styles.authModeLinks, children: [isGlobal ? (_jsx("button", { className: styles.submitBtn, disabled: setupBusy, onClick: async () => {
572
+ setSetupBusy(true);
573
+ setSetupNotice(null);
574
+ setSetupError(null);
575
+ try {
576
+ const res = await fetch('/api/taskforce/global-settings', {
577
+ method: 'POST',
578
+ headers: { 'Content-Type': 'application/json' },
579
+ credentials: 'include',
580
+ body: JSON.stringify({ setup: { mode: setupModeChoice } })
581
+ });
582
+ const data = await res.json().catch(() => ({}));
583
+ if (!res.ok || data?.success === false) {
584
+ setSetupError(data?.error || t('setup.saveFailedWithStatus', { status: res.status }));
585
+ }
586
+ else {
587
+ setSetupNotice(t('setup.globalSetupSaved'));
588
+ await refreshSetupContext();
589
+ }
590
+ }
591
+ catch {
592
+ setSetupError(t('setup.saveFailed'));
593
+ }
594
+ finally {
595
+ setSetupBusy(false);
596
+ }
597
+ }, children: setupBusy ? t('setup.saving') : t('setup.saveGlobalSetup') })) : !isError ? (_jsx("button", { className: styles.submitBtn, disabled: setupBusy, onClick: async () => {
598
+ setSetupBusy(true);
599
+ setSetupNotice(null);
600
+ setSetupError(null);
601
+ if (!isCloudRuntime && workspaceSetupSource === 'cloud' && canUseCloudWorkspaceSetup) {
602
+ if (!isAuthenticated) {
603
+ setSetupError('Sign in is required before syncing a cloud project.');
604
+ setSetupBusy(false);
605
+ return;
606
+ }
607
+ const selectedWorkspace = cloudWorkspaceOptions.find((workspace) => workspace.id === cloudWorkspaceSelection);
608
+ if (!selectedWorkspace) {
609
+ setSetupError('Select a cloud project to sync.');
610
+ setSetupBusy(false);
611
+ return;
612
+ }
613
+ const result = await saveWorkspaceProfile({
614
+ workspaceId: selectedWorkspace.id,
615
+ name: selectedWorkspace.name || selectedWorkspace.id,
616
+ description: selectedWorkspace.description || undefined
617
+ });
618
+ if (!result.success) {
619
+ setSetupError(result.error || t('setup.saveWorkspaceFailed'));
620
+ setSetupBusy(false);
621
+ return;
622
+ }
623
+ const workspaceIdForSync = String(result.workspaceId || selectedWorkspace.id || '').trim();
624
+ if (!workspaceIdForSync) {
625
+ setSetupError('Failed to resolve workspace id for sync setup.');
626
+ setSetupBusy(false);
627
+ return;
628
+ }
629
+ const stateRes = await fetch('/api/taskforce/ui-state', {
630
+ method: 'POST',
631
+ headers: { 'Content-Type': 'application/json' },
632
+ credentials: 'include',
633
+ body: JSON.stringify({
634
+ workspaceId: workspaceIdForSync,
635
+ stateKey: 'workspace-sync',
636
+ patch: {
637
+ cloudSyncEnabled: true,
638
+ sourceOfTruth: 'cloud',
639
+ // I6: start false; the orchestrator marks it true after first successful pull.
640
+ onboardingCompleted: false,
641
+ pullCursor: null,
642
+ updatedAt: new Date().toISOString()
643
+ }
644
+ })
645
+ });
646
+ const statePayload = await stateRes.json().catch(() => ({}));
647
+ if (!stateRes.ok || statePayload?.success === false) {
648
+ setSetupError(statePayload?.error || `Failed to configure workspace sync (${stateRes.status})`);
649
+ setSetupBusy(false);
650
+ return;
651
+ }
652
+ applyWorkspaceSyncStateSnapshot({
653
+ cloudSyncEnabled: true,
654
+ sourceOfTruth: 'cloud',
655
+ // I6: start false; the orchestrator marks it true after first successful pull.
656
+ onboardingCompleted: false,
657
+ pullCursor: null
658
+ });
659
+ await refreshSetupContext();
660
+ setSetupNotice(`Cloud project synced setup ready: ${selectedWorkspace.name}`);
661
+ }
662
+ else {
663
+ const creatingNewLocalWorkspace = setupState?.workspaceSetupState === 'missing';
664
+ const result = await saveWorkspaceProfile({
665
+ workspaceId: creatingNewLocalWorkspace ? undefined : setupState?.workspaceId,
666
+ name: workspaceNameInput,
667
+ description: workspaceDescriptionInput
668
+ });
669
+ if (!result.success) {
670
+ setSetupError(result.error || t('setup.saveWorkspaceFailed'));
671
+ }
672
+ else {
673
+ const shouldEnableCloudSync = Boolean(!isCloudRuntime && syncNewLocalWorkspaceToCloud && canUseCloudWorkspaceSetup && isAuthenticated);
674
+ const workspaceIdForSync = String(result.workspaceId || setupState?.workspaceId || '').trim();
675
+ if (!workspaceIdForSync) {
676
+ setSetupError('Failed to resolve workspace id for sync setup.');
677
+ setSetupBusy(false);
678
+ return;
679
+ }
680
+ const stateRes = await fetch('/api/taskforce/ui-state', {
681
+ method: 'POST',
682
+ headers: { 'Content-Type': 'application/json' },
683
+ credentials: 'include',
684
+ body: JSON.stringify({
685
+ workspaceId: workspaceIdForSync,
686
+ stateKey: 'workspace-sync',
687
+ patch: {
688
+ cloudSyncEnabled: shouldEnableCloudSync,
689
+ sourceOfTruth: shouldEnableCloudSync ? 'local' : null,
690
+ // I6: start false; the orchestrator marks it true after first successful pull.
691
+ onboardingCompleted: false,
692
+ pullCursor: null,
693
+ updatedAt: new Date().toISOString()
694
+ }
695
+ })
696
+ });
697
+ const statePayload = await stateRes.json().catch(() => ({}));
698
+ if (!stateRes.ok || statePayload?.success === false) {
699
+ setSetupError(statePayload?.error || `Failed to configure workspace sync (${stateRes.status})`);
700
+ setSetupBusy(false);
701
+ return;
702
+ }
703
+ applyWorkspaceSyncStateSnapshot({
704
+ cloudSyncEnabled: shouldEnableCloudSync,
705
+ sourceOfTruth: shouldEnableCloudSync ? 'local' : null,
706
+ // I6: start false; the orchestrator marks it true after first successful pull.
707
+ onboardingCompleted: false,
708
+ pullCursor: null
709
+ });
710
+ if (shouldEnableCloudSync) {
711
+ setSetupNotice(`${workspaceLabel} setup saved. Cloud sync enabled.`);
712
+ }
713
+ else {
714
+ setSetupNotice(t('setup.workspaceSetupSaved', { workspaceLabel }));
715
+ }
716
+ }
717
+ }
718
+ setSetupBusy(false);
719
+ }, children: setupBusy ? t('setup.saving') : t('setup.saveWorkspaceSetup', { workspaceLabel }) })) : (_jsx("button", { className: styles.submitBtn, disabled: setupBusy, onClick: refreshSetupContext, children: t('setup.retrySetupCheck') })), runtimeMode === 'cloud' && (_jsx("button", { className: styles.cancelBtn, onClick: async () => { await taskforceState.logout(); navigate('/login', { replace: true }); }, children: t('setup.signOut') }))] })] }) }) }));
720
+ }
721
+ return (_jsx(StandaloneLayout, { ...taskforceState, onHeaderMouseDown: onHeaderMouseDown, isDragging: isDragging, onClose: onClose }));
722
+ }
723
+ export function TaskforceCore(props) {
724
+ const inRouterContext = useInRouterContext();
725
+ if (!inRouterContext) {
726
+ return (_jsx(MemoryRouter, { children: _jsx(TaskforceCoreWithRouter, { ...props }) }));
727
+ }
728
+ return _jsx(TaskforceCoreWithRouter, { ...props });
729
+ }