@taskforcehq/taskforce 0.3.305 → 0.3.307

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 (440) hide show
  1. package/README.md +0 -2
  2. package/dist/Taskforce.module.css +603 -107
  3. package/dist/TaskforceCore.js +216 -43
  4. package/dist/TaskforceCore.test.js +611 -28
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +46 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
  16. package/dist/components/activity/EntityActivityTimeline.js +81 -0
  17. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  18. package/dist/components/context/ContextAttachmentManager.js +561 -0
  19. package/dist/components/features/AgentsModule.d.ts +14 -1
  20. package/dist/components/features/AgentsModule.js +366 -18
  21. package/dist/components/features/AgentsModule.test.js +507 -8
  22. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
  23. package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
  24. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
  25. package/dist/components/features/DocumentIndex.d.ts +2 -2
  26. package/dist/components/features/DocumentIndex.js +3 -4
  27. package/dist/components/features/DocumentViewer.d.ts +7 -1
  28. package/dist/components/features/DocumentViewer.js +62 -4
  29. package/dist/components/features/DocumentWorkspace.d.ts +10 -2
  30. package/dist/components/features/DocumentWorkspace.js +15 -4
  31. package/dist/components/features/DocumentWorkspace.test.js +51 -1
  32. package/dist/components/features/TaskSettings.d.ts +2 -0
  33. package/dist/components/features/TaskSettings.js +83 -78
  34. package/dist/components/features/TaskSettings.test.js +171 -82
  35. package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
  36. package/dist/components/task/TaskActionHeader.js +11 -5
  37. package/dist/components/task/TaskActionHeader.test.js +10 -0
  38. package/dist/components/task/TaskCard.js +24 -29
  39. package/dist/components/task/TaskCard.test.js +38 -3
  40. package/dist/components/task/TaskContextUpload.js +4 -526
  41. package/dist/components/task/TaskContextUpload.test.js +3 -3
  42. package/dist/components/task/TaskForm.js +61 -116
  43. package/dist/components/task/TaskForm.test.js +110 -8
  44. package/dist/components/task/TaskKanban.d.ts +2 -1
  45. package/dist/components/task/TaskKanban.js +94 -21
  46. package/dist/components/task/TaskKanban.test.js +36 -0
  47. package/dist/components/task/TaskList.js +5 -1
  48. package/dist/components/task/TaskList.test.js +4 -0
  49. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  50. package/dist/components/ui/EditableAvatarButton.js +18 -0
  51. package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
  52. package/dist/components/ui/HierarchyActionBadge.js +5 -0
  53. package/dist/components/views/AppShellHeader.d.ts +3 -1
  54. package/dist/components/views/AppShellHeader.js +27 -11
  55. package/dist/components/views/AppShellHeader.test.js +18 -1
  56. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  57. package/dist/components/views/PlanComparisonPage.js +78 -14
  58. package/dist/components/views/PlanComparisonPage.test.js +257 -0
  59. package/dist/components/views/PlansPage.js +127 -36
  60. package/dist/components/views/PlansPage.test.js +294 -12
  61. package/dist/components/views/StandaloneLayout.js +529 -592
  62. package/dist/components/views/WidgetView.js +10 -8
  63. package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
  64. package/dist/components/views/panels/PlanningDrawer.js +270 -55
  65. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  66. package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
  67. package/dist/components/views/planningScope.d.ts +20 -0
  68. package/dist/components/views/planningScope.js +25 -0
  69. package/dist/components/views/planningScope.test.d.ts +1 -0
  70. package/dist/components/views/planningScope.test.js +60 -0
  71. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
  72. package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
  73. package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
  74. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  75. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  76. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  77. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  78. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  79. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  80. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  81. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  82. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  83. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  84. package/dist/config/envSchema.js +1 -0
  85. package/dist/core/AiProfileService.d.ts +46 -2
  86. package/dist/core/AiProfileService.js +1073 -82
  87. package/dist/core/AiProfileService.test.js +19 -1
  88. package/dist/core/AiProfiles.test.js +1249 -44
  89. package/dist/core/AttachmentLinkService.d.ts +3 -0
  90. package/dist/core/AttachmentLinkService.js +110 -23
  91. package/dist/core/AuthIdentityService.d.ts +107 -0
  92. package/dist/core/AuthIdentityService.js +284 -0
  93. package/dist/core/AuthTokenService.d.ts +4 -0
  94. package/dist/core/AuthTokenService.js +34 -6
  95. package/dist/core/AuthTokenService.test.js +3 -3
  96. package/dist/core/EntitlementsPolicy.test.js +2 -2
  97. package/dist/core/GlobalSettingsService.js +127 -6
  98. package/dist/core/McpTokenService.d.ts +12 -0
  99. package/dist/core/McpTokenService.js +44 -1
  100. package/dist/core/PlanEntitlementService.d.ts +23 -2
  101. package/dist/core/PlanEntitlementService.js +343 -57
  102. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  103. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  104. package/dist/core/PlanVersionPolicy.test.js +35 -2
  105. package/dist/core/PlanningEntities.test.js +418 -4
  106. package/dist/core/SignupMonetizationSettings.test.js +199 -27
  107. package/dist/core/SyncReconciliationService.js +2 -65
  108. package/dist/core/SystemAdmin.test.js +42 -42
  109. package/dist/core/TaskActivityService.d.ts +28 -1
  110. package/dist/core/TaskActivityService.js +227 -46
  111. package/dist/core/TaskActivitySync.test.d.ts +1 -0
  112. package/dist/core/TaskActivitySync.test.js +90 -0
  113. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  114. package/dist/core/TaskAuditTimeline.test.js +96 -0
  115. package/dist/core/Taskforce.d.ts +415 -40
  116. package/dist/core/Taskforce.ids.test.js +58 -0
  117. package/dist/core/Taskforce.js +1543 -266
  118. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  119. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  120. package/dist/core/Taskforce.mcpAuth.test.js +109 -0
  121. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  122. package/dist/core/WorkspaceLifecycleService.js +0 -5
  123. package/dist/core/WorkspacePermissions.test.js +25 -1
  124. package/dist/core/WorkspacePlanMode.test.js +117 -16
  125. package/dist/core/shared.d.ts +1 -1
  126. package/dist/core/shared.js +5 -1
  127. package/dist/core/types.d.ts +75 -2
  128. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
  129. package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
  130. package/dist/hooks/bootstrapTimeouts.js +8 -0
  131. package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
  132. package/dist/hooks/bootstrapTimeouts.test.js +12 -0
  133. package/dist/hooks/sync/bootstrap.js +2 -0
  134. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  135. package/dist/hooks/sync/controlPlane.js +78 -0
  136. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  137. package/dist/hooks/sync/controlPlane.test.js +121 -0
  138. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  139. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  140. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  141. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  142. package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
  143. package/dist/hooks/sync/orchestratorShared.js +129 -48
  144. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  145. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  146. package/dist/hooks/sync/pullLifecycle.js +24 -0
  147. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  148. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  149. package/dist/hooks/sync/recovery.d.ts +16 -2
  150. package/dist/hooks/sync/recovery.js +179 -53
  151. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  152. package/dist/hooks/sync/recovery.test.js +292 -0
  153. package/dist/hooks/sync/transfers.d.ts +16 -3
  154. package/dist/hooks/sync/transfers.js +210 -66
  155. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  156. package/dist/hooks/sync/transfers.test.js +928 -0
  157. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  158. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  159. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  160. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  161. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  162. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  163. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  164. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  165. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  166. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  167. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  168. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  169. package/dist/hooks/useFilterSort.js +13 -13
  170. package/dist/hooks/useFilterSort.test.js +87 -1
  171. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  172. package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
  173. package/dist/hooks/useSyncOrchestrator.js +409 -183
  174. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
  175. package/dist/hooks/useTaskData.js +8 -3
  176. package/dist/hooks/useTaskData.test.js +45 -0
  177. package/dist/hooks/useTaskforce.d.ts +145 -52
  178. package/dist/hooks/useTaskforce.js +592 -253
  179. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  180. package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
  181. package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
  182. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  183. package/dist/hooks/useWorkspaceSyncController.js +13 -2
  184. package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
  185. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  186. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
  187. package/dist/localization/locales/en-US.d.ts +0 -1
  188. package/dist/localization/locales/en-US.js +0 -1
  189. package/dist/localization/locales/es-419.js +0 -1
  190. package/dist/localization/locales/pt-BR.js +0 -1
  191. package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
  192. package/dist/mcp/canonicalAssetHelpers.js +18 -10
  193. package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
  194. package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
  195. package/dist/mcp/clientIntegrations.d.ts +1 -0
  196. package/dist/mcp/clientIntegrations.js +25 -0
  197. package/dist/mcp/clientIntegrations.test.js +14 -3
  198. package/dist/mcp/clientProfileDefaults.js +3 -3
  199. package/dist/mcp/collaborationRegistrar.js +7 -7
  200. package/dist/mcp/documentAssetRegistrar.js +116 -10
  201. package/dist/mcp/runtime.d.ts +3 -0
  202. package/dist/mcp/runtime.js +1099 -185
  203. package/dist/mcp/runtime.test.js +1491 -140
  204. package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
  205. package/dist/mcp/taskPlanningRegistrar.js +48 -0
  206. package/dist/mcp/toolRegistry.d.ts +56 -0
  207. package/dist/mcp/toolRegistry.js +8 -0
  208. package/dist/mcp/toolRegistry.test.js +4 -0
  209. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  210. package/dist/migrations/taskSchemaMigrations.js +192 -61
  211. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  212. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  213. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  214. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  215. package/dist/resources/templates/workflows/plan.yaml +1 -1
  216. package/dist/resources/templates/workflows/review.yaml +2 -2
  217. package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
  218. package/dist/server/aiProfileAvatarAssets.js +319 -0
  219. package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
  220. package/dist/server/aiProfileAvatarAssets.test.js +213 -0
  221. package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
  222. package/dist/server/auth/providers/apple.d.ts +33 -0
  223. package/dist/server/auth/providers/apple.js +82 -0
  224. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  225. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  226. package/dist/server/auth/providers/github.d.ts +26 -0
  227. package/dist/server/auth/providers/github.js +86 -0
  228. package/dist/server/auth/providers/google.d.ts +21 -0
  229. package/dist/server/auth/providers/google.js +56 -0
  230. package/dist/server/auth/providers/types.d.ts +21 -0
  231. package/dist/server/auth/providers/types.js +1 -0
  232. package/dist/server/auth.d.ts +2 -0
  233. package/dist/server/auth.js +6 -3
  234. package/dist/server/documentReviewRoutes.test.js +36 -3
  235. package/dist/server/index.cookieProxy.test.js +1 -0
  236. package/dist/server/index.d.ts +12 -0
  237. package/dist/server/index.js +124 -9
  238. package/dist/server/index.rateLimit.test.js +3 -0
  239. package/dist/server/index.test.js +111 -3
  240. package/dist/server/routes/admin.d.ts +3 -0
  241. package/dist/server/routes/admin.js +459 -28
  242. package/dist/server/routes/annotatedAttachments.js +51 -0
  243. package/dist/server/routes/auth.d.ts +26 -2
  244. package/dist/server/routes/auth.js +1170 -71
  245. package/dist/server/routes/authSupport.d.ts +5 -1
  246. package/dist/server/routes/authSupport.js +13 -2
  247. package/dist/server/routes/billing.js +372 -35
  248. package/dist/server/routes/billing.test.js +595 -12
  249. package/dist/server/routes/documents.d.ts +1 -0
  250. package/dist/server/routes/documents.js +182 -70
  251. package/dist/server/routes/shared.d.ts +28 -2
  252. package/dist/server/routes/shared.js +69 -14
  253. package/dist/server/routes/sync.integration.test.js +658 -39
  254. package/dist/server/routes/sync.js +74 -608
  255. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  256. package/dist/server/routes/syncAuxRoutes.js +91 -0
  257. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  258. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  259. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  260. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  261. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  262. package/dist/server/routes/syncPushRoutes.js +212 -0
  263. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  264. package/dist/server/routes/syncRouteGuards.js +67 -0
  265. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  266. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  267. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  268. package/dist/server/routes/syncRouteTypes.js +1 -0
  269. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  270. package/dist/server/routes/syncSnapshotRoutes.js +182 -0
  271. package/dist/server/routes/tasks.js +55 -10
  272. package/dist/server/routes/workspaces.js +36 -5
  273. package/dist/server/routes.js +147 -11
  274. package/dist/server/routes.test.js +2704 -183
  275. package/dist/services/workflowExportSnapshots.test.js +2 -0
  276. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  277. package/dist/shared/aiProfileSeatScope.js +21 -0
  278. package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
  279. package/dist/shared/aiProfileSurfaceType.js +10 -8
  280. package/dist/shared/passwordPolicy.d.ts +13 -0
  281. package/dist/shared/passwordPolicy.js +84 -0
  282. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  283. package/dist/shared/passwordPolicy.test.js +34 -0
  284. package/dist/storage/objectStorage.d.ts +1 -0
  285. package/dist/storage/objectStorage.js +2 -1
  286. package/dist/storage/objectStorageClient.d.ts +1 -0
  287. package/dist/storage/objectStorageClient.js +41 -8
  288. package/dist/storage/objectStorageClient.test.js +26 -1
  289. package/dist/storage/objectStorageConfig.js +3 -1
  290. package/dist/storage/objectStorageConfig.test.js +13 -1
  291. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  292. package/dist/storage/workspaceAssetStore.js +132 -44
  293. package/dist/storage/workspaceAssetStore.test.js +93 -6
  294. package/dist/styles/fonts.css +70 -0
  295. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  296. package/dist/sync/collaborationSyncPayload.js +19 -11
  297. package/dist/sync/collaborationSyncPayload.test.js +14 -1
  298. package/dist/sync/collaborationSyncState.d.ts +3 -3
  299. package/dist/sync/collaborationSyncState.js +19 -12
  300. package/dist/sync/contentSyncPayload.d.ts +5 -1
  301. package/dist/sync/contentSyncPayload.js +9 -0
  302. package/dist/sync/contentSyncPayload.test.js +39 -0
  303. package/dist/sync/contentSyncState.d.ts +9 -9
  304. package/dist/sync/contentSyncState.js +248 -107
  305. package/dist/sync/planningSyncPayload.js +5 -0
  306. package/dist/sync/planningSyncPayload.test.js +24 -0
  307. package/dist/sync/syncApplyHandlers.d.ts +11 -4
  308. package/dist/sync/syncApplyHandlers.js +115 -42
  309. package/dist/sync/syncApplyHandlers.test.js +251 -4
  310. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  311. package/dist/sync/syncFieldSemantics.js +55 -0
  312. package/dist/sync/syncResourceAdapters.d.ts +46 -0
  313. package/dist/sync/syncResourceAdapters.js +79 -0
  314. package/dist/sync/syncService.d.ts +6 -0
  315. package/dist/sync/syncService.js +65 -1
  316. package/dist/sync/syncService.test.js +96 -3
  317. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  318. package/dist/sync/taskSyncChangeKey.js +143 -0
  319. package/dist/sync/taskSyncPayload.js +3 -8
  320. package/dist/sync/workspacePullFeed.d.ts +4 -0
  321. package/dist/sync/workspacePullFeed.js +132 -72
  322. package/dist/sync/workspacePullFeed.test.js +92 -0
  323. package/dist/sync/workspaceRepair.js +5 -2
  324. package/dist/sync/workspaceSyncModel.d.ts +73 -6
  325. package/dist/sync/workspaceSyncModel.js +342 -73
  326. package/dist/sync/workspaceSyncModel.test.js +559 -14
  327. package/dist/sync/workspaceSyncState.d.ts +17 -0
  328. package/dist/sync/workspaceSyncState.js +2 -1
  329. package/dist/sync/workspaceSyncSurface.js +3 -8
  330. package/dist/types.d.ts +50 -2
  331. package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
  332. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
  333. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
  334. package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
  335. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  336. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  337. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  338. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  339. package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
  340. package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
  341. package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
  342. package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
  343. package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
  344. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  345. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  346. package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
  347. package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
  348. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  349. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  350. package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
  351. package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
  352. package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
  353. package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
  354. package/dist/ui/assets/index-607WPo_X.js +4 -0
  355. package/dist/ui/assets/index-CYyodXsg.css +1 -0
  356. package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
  357. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  358. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  359. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  360. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  361. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  362. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  363. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  364. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  365. package/dist/ui/fonts/Noir_medium.otf +0 -0
  366. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  367. package/dist/ui/fonts/Noir_regular.otf +0 -0
  368. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  369. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  370. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  371. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  372. package/dist/ui/index.html +3 -3
  373. package/dist/ui/product/agent manager.png +0 -0
  374. package/dist/ui/product/agent_manager_02.png +0 -0
  375. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  376. package/dist/utils/aiProfileEvents.d.ts +7 -0
  377. package/dist/utils/aiProfileEvents.js +6 -0
  378. package/dist/utils/assignees.d.ts +8 -0
  379. package/dist/utils/assignees.js +10 -1
  380. package/dist/utils/assignees.test.d.ts +1 -0
  381. package/dist/utils/assignees.test.js +25 -0
  382. package/dist/utils/avatarDisplay.d.ts +1 -0
  383. package/dist/utils/avatarDisplay.js +15 -0
  384. package/dist/utils/avatarUpload.d.ts +27 -0
  385. package/dist/utils/avatarUpload.js +132 -0
  386. package/dist/utils/avatarUpload.test.d.ts +1 -0
  387. package/dist/utils/avatarUpload.test.js +40 -0
  388. package/dist/utils/bootstrapTrace.d.ts +7 -0
  389. package/dist/utils/bootstrapTrace.js +29 -0
  390. package/dist/utils/commercialLifecyclePresentation.js +3 -0
  391. package/dist/utils/contextAssetEvents.d.ts +2 -0
  392. package/dist/utils/contextFiles.d.ts +3 -1
  393. package/dist/utils/contextFiles.js +2 -1
  394. package/dist/utils/syncEventDetails.d.ts +3 -0
  395. package/dist/utils/syncEventDetails.js +64 -0
  396. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  397. package/dist/utils/syncEventDetails.test.js +23 -0
  398. package/dist/utils/syncEventPresentation.d.ts +15 -0
  399. package/dist/utils/syncEventPresentation.js +129 -0
  400. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  401. package/dist/utils/syncEventPresentation.test.js +64 -0
  402. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  403. package/dist/utils/syncStatusPresentation.js +217 -0
  404. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  405. package/dist/utils/syncStatusPresentation.test.js +164 -0
  406. package/dist/utils/taskActivity.d.ts +9 -1
  407. package/dist/utils/taskActivity.js +290 -22
  408. package/dist/utils/taskActivity.test.js +141 -8
  409. package/dist/utils/taskSearch.d.ts +22 -0
  410. package/dist/utils/taskSearch.js +87 -0
  411. package/dist/utils/taskSearch.test.d.ts +1 -0
  412. package/dist/utils/taskSearch.test.js +69 -0
  413. package/dist/utils/taskUtils.js +10 -3
  414. package/dist/utils/taskUtils.test.d.ts +1 -0
  415. package/dist/utils/taskUtils.test.js +19 -0
  416. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  417. package/dist/utils/workspaceSyncPresentation.js +68 -2
  418. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  419. package/package.json +3 -2
  420. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  421. package/scripts/run-e2e-realtime.sh +17 -3
  422. package/scripts/run-smoke.sh +17 -5
  423. package/scripts/run-soak.sh +17 -5
  424. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  425. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  426. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  427. package/src/resources/templates/workflows/plan.yaml +1 -1
  428. package/src/resources/templates/workflows/review.yaml +2 -2
  429. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
  430. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
  431. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
  432. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
  433. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
  434. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  435. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
  436. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  437. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
  438. package/dist/ui/assets/index-C2-OXZV7.css +0 -1
  439. package/dist/ui/assets/index-DcSI5F86.js +0 -6
  440. package/scripts/migrate-planning-model.ts +0 -233
@@ -0,0 +1,69 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { normalizeTaskReferenceToken, normalizeTaskSearchQuery, taskMatchesSearch, } from './taskSearch';
3
+ function makeTask(overrides = {}) {
4
+ return {
5
+ id: overrides.id || 'task-1',
6
+ title: overrides.title || 'Task',
7
+ description: overrides.description ?? null,
8
+ status: overrides.status || 'task',
9
+ priority: overrides.priority ?? 2,
10
+ complexity: overrides.complexity ?? 3,
11
+ type: overrides.type || 'feature',
12
+ category: overrides.category || 'default',
13
+ createdAt: overrides.createdAt || '2026-03-23T00:00:00.000Z',
14
+ updatedAt: overrides.updatedAt || null,
15
+ completedAt: overrides.completedAt || null,
16
+ assignee: overrides.assignee || 'unassigned',
17
+ comments: [],
18
+ attachments: [],
19
+ activity: [],
20
+ taskEvents: [],
21
+ referenceLabel: overrides.referenceLabel,
22
+ taxonomies: overrides.taxonomies || {}
23
+ };
24
+ }
25
+ describe('taskSearch', () => {
26
+ it('normalizes common pasted task reference formats', () => {
27
+ expect(normalizeTaskReferenceToken(' T-123 ')).toBe('t-123');
28
+ expect(normalizeTaskReferenceToken('T - 123')).toBe('t-123');
29
+ expect(normalizeTaskReferenceToken('T 123')).toBe('t-123');
30
+ expect(normalizeTaskReferenceToken('t–123')).toBe('t-123');
31
+ expect(normalizeTaskReferenceToken('LT - 45')).toBe('lt-45');
32
+ });
33
+ it('matches canonicalized task references', () => {
34
+ const task = makeTask({ referenceLabel: 'T-123' });
35
+ expect(taskMatchesSearch(task, normalizeTaskSearchQuery('T - 123'))).toBe(true);
36
+ expect(taskMatchesSearch(task, normalizeTaskSearchQuery('t–123'))).toBe(true);
37
+ });
38
+ it('matches all query tokens across task text', () => {
39
+ const task = makeTask({ title: 'Billing cleanup', description: 'Audit the API handlers' });
40
+ expect(taskMatchesSearch(task, 'api billing')).toBe(true);
41
+ expect(taskMatchesSearch(task, 'api invoices')).toBe(false);
42
+ });
43
+ it('matches task metadata labels', () => {
44
+ const task = makeTask({
45
+ category: 'ops',
46
+ type: 'bug',
47
+ priority: 3,
48
+ assignee: 'member-1',
49
+ taxonomies: { track: 'platform' }
50
+ });
51
+ const context = {
52
+ categories: [{ value: 'ops', label: 'Operations', disabled: false }],
53
+ types: [{ value: 'bug', label: 'Bug' }],
54
+ priorities: [{ value: 3, label: 'High' }],
55
+ assigneeOptions: [{ value: 'member-1', label: 'Member One', icon: 'User', color: '#22c55e', kind: 'member' }],
56
+ taxonomies: [{
57
+ id: 'track',
58
+ label: 'Track',
59
+ options: [{ value: 'platform', label: 'Platform' }],
60
+ widgetType: 'select',
61
+ isSystem: false,
62
+ multiSelect: false
63
+ }]
64
+ };
65
+ expect(taskMatchesSearch(task, 'operations', context)).toBe(true);
66
+ expect(taskMatchesSearch(task, 'member one', context)).toBe(true);
67
+ expect(taskMatchesSearch(task, 'track platform', context)).toBe(true);
68
+ });
69
+ });
@@ -2,6 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import * as Icons from 'lucide-react';
3
3
  import { TypeMeta } from './constants';
4
4
  import styles from '../Taskforce.module.css';
5
+ import { normalizeTaskReferenceToken } from './taskSearch';
5
6
  export const getIconForType = (type, size = 10) => {
6
7
  const meta = TypeMeta[type?.toLowerCase()] || { icon: 'FileCode', color: 'indigo-500' };
7
8
  const IconComp = Icons[meta.icon] || Icons.FileCode;
@@ -10,11 +11,17 @@ export const getIconForType = (type, size = 10) => {
10
11
  export const renderHighlighted = (text, query) => {
11
12
  if (!text)
12
13
  return null;
13
- if (!query.trim())
14
+ const normalizedQuery = query.trim();
15
+ if (!normalizedQuery)
14
16
  return text;
15
- const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
17
+ const referenceToken = normalizeTaskReferenceToken(normalizedQuery);
18
+ const referenceParts = referenceToken?.match(/^(lt|t)-(\d+)$/);
19
+ const escapedQuery = referenceParts
20
+ ? `${referenceParts[1] === 'lt' ? 'l\\s*t' : 't'}\\s*(?:-|\\s)?\\s*${referenceParts[2]}`
21
+ : normalizedQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
+ const highlightPattern = new RegExp(`^${escapedQuery}$`, 'i');
16
23
  const parts = text.split(new RegExp(`(${escapedQuery})`, 'gi'));
17
- return (_jsx(_Fragment, { children: parts.map((part, i) => part.toLowerCase() === query.toLowerCase()
24
+ return (_jsx(_Fragment, { children: parts.map((part, i) => highlightPattern.test(part)
18
25
  ? _jsx("mark", { className: styles.highlight, children: part }, i)
19
26
  : part) }));
20
27
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from '@testing-library/react';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { renderHighlighted } from './taskUtils';
5
+ describe('renderHighlighted', () => {
6
+ it('highlights matches when the query has surrounding spaces', () => {
7
+ const { container } = render(_jsx("p", { children: renderHighlighted('T-123', ' T-123 ') }));
8
+ expect(container.querySelector('mark')?.textContent).toBe('T-123');
9
+ });
10
+ it('highlights task references when the query has pasted formatting', () => {
11
+ const { container } = render(_jsx("p", { children: renderHighlighted('T-123', ' T - 123 ') }));
12
+ expect(container.querySelector('mark')?.textContent).toBe('T-123');
13
+ });
14
+ it('treats whitespace-only queries as empty', () => {
15
+ const { container } = render(_jsx("p", { children: renderHighlighted('T-123', ' ') }));
16
+ expect(container.querySelector('mark')).toBeNull();
17
+ expect(container.textContent).toBe('T-123');
18
+ });
19
+ });
@@ -1,4 +1,5 @@
1
1
  export type HeaderWorkspaceSyncStatus = 'off' | 'syncing' | 'attention' | 'healthy';
2
+ type WorkspaceSyncBlockedReason = 'cloud-auth-unconfigured' | 'runtime-not-local' | 'sync-disabled' | 'invalid-workspace' | 'repair-active' | 'attach-cloud' | 'provision-local' | 'auth-required' | 'push-in-flight' | 'pull-in-flight' | 'retry-pending' | 'lease-held';
2
3
  interface ResolveHeaderWorkspaceSyncPresentationInput {
3
4
  runtimeMode: 'local' | 'cloud';
4
5
  isAuthenticated: boolean;
@@ -7,6 +8,9 @@ interface ResolveHeaderWorkspaceSyncPresentationInput {
7
8
  workspaceSyncSummary: string;
8
9
  workspaceSyncRecommendedAction: string;
9
10
  workspaceSyncError: string;
11
+ pushBlockedReason?: WorkspaceSyncBlockedReason | null;
12
+ pullBlockedReason?: WorkspaceSyncBlockedReason | null;
13
+ retryBlockedReason?: WorkspaceSyncBlockedReason | null;
10
14
  }
11
15
  export interface HeaderWorkspaceSyncPresentation {
12
16
  actionable: boolean;
@@ -1,12 +1,78 @@
1
+ function resolveBlockedReasonPresentation(reason) {
2
+ switch (reason) {
3
+ case 'auth-required':
4
+ return {
5
+ summary: 'Sync is paused until you sign in again.',
6
+ recommendedAction: 'Sign in, then press Sync to retry.'
7
+ };
8
+ case 'attach-cloud':
9
+ return {
10
+ summary: 'This workspace still needs its first cloud pull before local pushes can run.',
11
+ recommendedAction: 'Keep this window open for the first cloud pull. If it seems stuck, press Repair.'
12
+ };
13
+ case 'provision-local':
14
+ return {
15
+ summary: 'This workspace is still doing its first cloud upload before normal pulls can run.',
16
+ recommendedAction: 'Keep this window open until the first cloud upload finishes.'
17
+ };
18
+ case 'repair-active':
19
+ return {
20
+ summary: 'Repair is already running for this workspace.',
21
+ recommendedAction: 'Wait for repair to finish before retrying sync.'
22
+ };
23
+ case 'retry-pending':
24
+ return {
25
+ summary: 'Sync hit a temporary problem and is waiting for its scheduled retry.',
26
+ recommendedAction: 'Wait for the automatic retry, or press Sync to retry now.'
27
+ };
28
+ case 'push-in-flight':
29
+ case 'pull-in-flight':
30
+ return {
31
+ summary: 'A sync request is already running for this workspace.',
32
+ recommendedAction: 'Wait for the current sync request to finish.'
33
+ };
34
+ case 'lease-held':
35
+ return {
36
+ summary: 'Another local window is already syncing this workspace.',
37
+ recommendedAction: 'Use a single local window for sync, or close the other syncing window.'
38
+ };
39
+ case 'invalid-workspace':
40
+ return {
41
+ summary: 'Workspace setup is required before sync can run.',
42
+ recommendedAction: 'Open or create a named workspace before retrying sync.'
43
+ };
44
+ case 'cloud-auth-unconfigured':
45
+ return {
46
+ summary: 'Cloud sync is unavailable because cloud authentication is not configured.',
47
+ recommendedAction: 'Configure cloud authentication before turning on sync.'
48
+ };
49
+ case 'runtime-not-local':
50
+ return {
51
+ summary: 'Workspace sync controls are only available in the local runtime.',
52
+ recommendedAction: 'Open this workspace in the local app to manage sync.'
53
+ };
54
+ case 'sync-disabled':
55
+ return {
56
+ summary: 'Workspace sync is currently turned off.',
57
+ recommendedAction: 'Turn on sync when you are ready to connect this workspace to cloud.'
58
+ };
59
+ default:
60
+ return null;
61
+ }
62
+ }
1
63
  export function resolveHeaderWorkspaceSyncPresentation(input) {
2
64
  const actionable = input.runtimeMode === 'local' && input.isAuthenticated;
3
65
  if (actionable) {
66
+ const blockedReasonPresentation = resolveBlockedReasonPresentation(input.retryBlockedReason
67
+ || input.pullBlockedReason
68
+ || input.pushBlockedReason
69
+ || null);
4
70
  return {
5
71
  actionable,
6
72
  status: input.workspaceSyncStatus,
7
73
  syncEnabledLabel: input.workspaceCloudSyncEnabled ? 'yes' : 'no',
8
- summary: input.workspaceSyncSummary,
9
- recommendedAction: input.workspaceSyncRecommendedAction,
74
+ summary: blockedReasonPresentation?.summary || input.workspaceSyncSummary,
75
+ recommendedAction: blockedReasonPresentation?.recommendedAction || input.workspaceSyncRecommendedAction,
10
76
  lastError: input.workspaceSyncError
11
77
  };
12
78
  }
@@ -25,7 +25,10 @@ describe('resolveHeaderWorkspaceSyncPresentation', () => {
25
25
  workspaceCloudSyncEnabled: true,
26
26
  workspaceSyncSummary: 'Sync needs attention before it can continue.',
27
27
  workspaceSyncRecommendedAction: 'Press Sync to retry.',
28
- workspaceSyncError: 'Retry later'
28
+ workspaceSyncError: 'Retry later',
29
+ pushBlockedReason: null,
30
+ pullBlockedReason: null,
31
+ retryBlockedReason: null
29
32
  });
30
33
  expect(result.actionable).toBe(true);
31
34
  expect(result.status).toBe('attention');
@@ -33,4 +36,36 @@ describe('resolveHeaderWorkspaceSyncPresentation', () => {
33
36
  expect(result.summary).toBe('Sync needs attention before it can continue.');
34
37
  expect(result.lastError).toBe('Retry later');
35
38
  });
39
+ it('surfaces the highest-priority blocked sync reason in the visible summary', () => {
40
+ const result = resolveHeaderWorkspaceSyncPresentation({
41
+ runtimeMode: 'local',
42
+ isAuthenticated: true,
43
+ workspaceSyncStatus: 'attention',
44
+ workspaceCloudSyncEnabled: true,
45
+ workspaceSyncSummary: 'Sync needs attention before it can continue.',
46
+ workspaceSyncRecommendedAction: 'Press Sync to retry.',
47
+ workspaceSyncError: 'Retry later',
48
+ pushBlockedReason: 'attach-cloud',
49
+ pullBlockedReason: 'retry-pending',
50
+ retryBlockedReason: 'auth-required'
51
+ });
52
+ expect(result.summary).toBe('Sync is paused until you sign in again.');
53
+ expect(result.recommendedAction).toBe('Sign in, then press Sync to retry.');
54
+ });
55
+ it('explains when another local window holds the sync lease', () => {
56
+ const result = resolveHeaderWorkspaceSyncPresentation({
57
+ runtimeMode: 'local',
58
+ isAuthenticated: true,
59
+ workspaceSyncStatus: 'attention',
60
+ workspaceCloudSyncEnabled: true,
61
+ workspaceSyncSummary: 'Sync needs attention before it can continue.',
62
+ workspaceSyncRecommendedAction: 'Press Sync to retry.',
63
+ workspaceSyncError: 'Retry later',
64
+ pushBlockedReason: 'lease-held',
65
+ pullBlockedReason: null,
66
+ retryBlockedReason: null
67
+ });
68
+ expect(result.summary).toBe('Another local window is already syncing this workspace.');
69
+ expect(result.recommendedAction).toBe('Use a single local window for sync, or close the other syncing window.');
70
+ });
36
71
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taskforcehq/taskforce",
3
- "version": "0.3.305",
3
+ "version": "0.3.307",
4
4
  "description": "Mission Command center for AI-powered task management (beta - under active development)",
5
5
  "author": "Taskforce HQ <hello@taskforcehq.ai> (https://taskforcehq.ai)",
6
6
  "license": "MIT",
@@ -54,7 +54,7 @@
54
54
  "build:ui": "npm run build:app",
55
55
  "check:deploy-preflight": "npm run build",
56
56
  "hooks:install": "git config core.hooksPath .githooks",
57
- "build": "shx rm -rf dist && tsc && shx cp src/Taskforce.module.css dist/Taskforce.module.css && shx mkdir -p dist/resources && shx cp -r src/resources/* dist/resources/ && shx rm -f dist/resources/templates/workflows/release.yaml && shx mkdir -p dist/public && shx cp -r src/assets/images/* dist/public/ && shx cp -r src/assets/favicon/* dist/public/ && shx chmod +x dist/cli.js && npm run build:ui",
57
+ "build": "shx rm -rf dist && tsc && shx cp src/Taskforce.module.css dist/Taskforce.module.css && shx mkdir -p dist/styles && shx cp src/styles/fonts.css dist/styles/fonts.css && shx mkdir -p dist/assets/fonts && shx cp src/assets/fonts/*.woff2 dist/assets/fonts/ && shx mkdir -p dist/resources && shx cp -r src/resources/* dist/resources/ && shx rm -f dist/resources/templates/workflows/release.yaml && shx mkdir -p dist/public && shx cp -r src/assets/images/* dist/public/ && shx cp -r src/assets/favicon/* dist/public/ && shx chmod +x dist/cli.js && npm run build:ui",
58
58
  "mcp": "node dist/mcp/server.js",
59
59
  "gen:workflows": "node scripts/generate-workflow-templates.mjs",
60
60
  "check:workflows": "node scripts/generate-workflow-templates.mjs --check",
@@ -111,6 +111,7 @@
111
111
  "js-yaml": "^4.1.1",
112
112
  "nodemailer": "^6.10.1",
113
113
  "pg": "^8.18.0",
114
+ "react-avatar-editor": "^15.1.0",
114
115
  "rehype-sanitize": "^6.0.0",
115
116
  "stripe": "^20.3.1",
116
117
  "ws": "^8.18.0"
@@ -49,19 +49,19 @@ lines.push('');
49
49
 
50
50
  for (const t of tasks) {
51
51
  lines.push(`INSERT INTO tasks (
52
- id, tenant_id, title, description, status, priority, complexity, type, category,
52
+ id, tenant_id, workspace_id, title, description, status, priority, complexity, type, category,
53
53
  approach, created_at, updated_at, completed_at, canceled_reason,
54
54
  is_archived, specialists, taxonomies, created_by,
55
- scheduled_date, due_date, scheduled_week_key, order_in_day,
56
- parent_task_id, child_display_order
55
+ scheduled_date, due_date, scheduled_week_key, order_in_day
57
56
  ) VALUES (
58
- ${sqlString(t.id)}, ${sqlString(t.tenant_id || 'default')}, ${sqlString(t.title)}, ${sqlString(t.description)}, ${sqlString(t.status)}, ${sqlNumber(t.priority)}, ${sqlNumber(t.complexity)}, ${sqlString(t.type)}, ${sqlString(t.category)},
57
+ ${sqlString(t.id)}, ${sqlString(t.tenant_id || 'default')}, ${sqlString(t.workspace_id || 'default')}, ${sqlString(t.title)}, ${sqlString(t.description)}, ${sqlString(t.status)}, ${sqlNumber(t.priority)}, ${sqlNumber(t.complexity)}, ${sqlString(t.type)}, ${sqlString(t.category)},
59
58
  ${sqlString(t.approach)}, ${sqlString(t.created_at)}, ${sqlString(t.updated_at)}, ${sqlString(t.completed_at)}, ${sqlString(t.canceled_reason)},
60
59
  ${sqlBool(t.is_archived)}, ${sqlString(t.specialists)}, ${sqlString(t.taxonomies)}, ${sqlString(t.created_by)},
61
- ${sqlString(t.scheduled_date)}, ${sqlString(t.due_date)}, ${sqlString(t.scheduled_week_key)}, ${sqlNumber(t.order_in_day)},
62
- ${sqlString(t.parent_task_id)}, ${sqlNumber(t.child_display_order)}
60
+ ${sqlString(t.scheduled_date)}, ${sqlString(t.due_date)}, ${sqlString(t.scheduled_week_key)}, ${sqlNumber(t.order_in_day)}
63
61
  )
64
62
  ON CONFLICT (id) DO UPDATE SET
63
+ tenant_id = EXCLUDED.tenant_id,
64
+ workspace_id = EXCLUDED.workspace_id,
65
65
  title = EXCLUDED.title,
66
66
  description = EXCLUDED.description,
67
67
  status = EXCLUDED.status,
@@ -81,9 +81,7 @@ ON CONFLICT (id) DO UPDATE SET
81
81
  scheduled_date = EXCLUDED.scheduled_date,
82
82
  due_date = EXCLUDED.due_date,
83
83
  scheduled_week_key = EXCLUDED.scheduled_week_key,
84
- order_in_day = EXCLUDED.order_in_day,
85
- parent_task_id = EXCLUDED.parent_task_id,
86
- child_display_order = EXCLUDED.child_display_order;`);
84
+ order_in_day = EXCLUDED.order_in_day;`);
87
85
  }
88
86
 
89
87
  for (const c of comments) {
@@ -1,16 +1,30 @@
1
1
  #!/bin/sh
2
2
  set -eu
3
3
 
4
- if [ -f .env.e2e ]; then
4
+ LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
5
+ REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
6
+
7
+ if [ -f "$LOCAL_ENV_FILE" ]; then
8
+ set -a
9
+ # shellcheck disable=SC1090
10
+ . "$LOCAL_ENV_FILE"
11
+ set +a
12
+ elif [ -f "$REPO_E2E_ENV_FILE" ]; then
5
13
  set -a
6
- . ./.env.e2e
14
+ # shellcheck disable=SC1090
15
+ . "$REPO_E2E_ENV_FILE"
7
16
  set +a
8
17
  fi
9
18
 
10
19
  # Mirror soak defaults so realtime e2e runs are plug-compatible with existing env setup.
11
20
  export SYNC_SOAK_LOCAL_BASE_URL="${SYNC_SOAK_LOCAL_BASE_URL:-http://localhost:5174}"
12
- export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
21
+ export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}}"
13
22
  export SYNC_SOAK_WORKSPACE_ID="${SYNC_SOAK_WORKSPACE_ID:-test-smoke}"
23
+ export SYNC_SOAK_EMAIL="${SYNC_SOAK_EMAIL:-${TASKFORCE_E2E_EMAIL:-}}"
24
+ export SYNC_SOAK_PASSWORD="${SYNC_SOAK_PASSWORD:-${TASKFORCE_E2E_PASSWORD:-}}"
25
+ PLAYWRIGHT_AUTH_STORAGE_STATE="${PLAYWRIGHT_AUTH_STORAGE_STATE:-${TASKFORCE_PLAYWRIGHT_STORAGE_STATE:-}}"
26
+ unset TASKFORCE_E2E_EMAIL TASKFORCE_E2E_PASSWORD TASKFORCE_PLAYWRIGHT_STORAGE_STATE TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
14
27
 
15
28
  node --import tsx scripts/check-env.ts --target=soak --strict=true
29
+ export PLAYWRIGHT_AUTH_STORAGE_STATE
16
30
  npx playwright test -c playwright.e2e.config.ts "$@"
@@ -1,22 +1,34 @@
1
1
  #!/bin/sh
2
2
  set -eu
3
3
 
4
- if [ -f .env.e2e ]; then
4
+ LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
5
+ REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
6
+
7
+ if [ -f "$LOCAL_ENV_FILE" ]; then
8
+ set -a
9
+ # shellcheck disable=SC1090
10
+ . "$LOCAL_ENV_FILE"
11
+ set +a
12
+ elif [ -f "$REPO_E2E_ENV_FILE" ]; then
5
13
  set -a
6
- . ./.env.e2e
14
+ # shellcheck disable=SC1090
15
+ . "$REPO_E2E_ENV_FILE"
7
16
  set +a
8
17
  fi
9
18
 
10
19
  # Provide safe defaults for non-secret settings; allow caller/.env.e2e overrides.
11
20
  export SYNC_SOAK_LOCAL_BASE_URL="${SYNC_SOAK_LOCAL_BASE_URL:-http://localhost:5174}"
12
- export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
21
+ export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}}"
13
22
  export SYNC_SOAK_WORKSPACE_ID="${SYNC_SOAK_WORKSPACE_ID:-test-smoke}"
23
+ export SYNC_SOAK_EMAIL="${SYNC_SOAK_EMAIL:-${TASKFORCE_E2E_EMAIL:-}}"
24
+ export SYNC_SOAK_PASSWORD="${SYNC_SOAK_PASSWORD:-${TASKFORCE_E2E_PASSWORD:-}}"
25
+ unset TASKFORCE_E2E_EMAIL TASKFORCE_E2E_PASSWORD TASKFORCE_PLAYWRIGHT_STORAGE_STATE TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
14
26
 
15
27
  node --import tsx scripts/check-env.ts --target=soak --strict=true
16
28
 
17
- # Shared credentials are required and must come from env/.env.e2e.
29
+ # Shared credentials are required and may come from the local Playwright auth env file or repo .env.e2e.
18
30
  if [ -z "${SYNC_SOAK_ACCOUNTS_JSON:-}" ] && { [ -z "${SYNC_SOAK_EMAIL:-}" ] || [ -z "${SYNC_SOAK_PASSWORD:-}" ]; }; then
19
- echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in env/.env.e2e." >&2
31
+ echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in $TASKFORCE_PLAYWRIGHT_ENV_FILE or .env.e2e." >&2
20
32
  exit 1
21
33
  fi
22
34
 
@@ -1,23 +1,35 @@
1
1
  #!/bin/sh
2
2
  set -eu
3
3
 
4
- if [ -f .env.e2e ]; then
4
+ LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
5
+ REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
6
+
7
+ if [ -f "$LOCAL_ENV_FILE" ]; then
8
+ set -a
9
+ # shellcheck disable=SC1090
10
+ . "$LOCAL_ENV_FILE"
11
+ set +a
12
+ elif [ -f "$REPO_E2E_ENV_FILE" ]; then
5
13
  set -a
6
- . ./.env.e2e
14
+ # shellcheck disable=SC1090
15
+ . "$REPO_E2E_ENV_FILE"
7
16
  set +a
8
17
  fi
9
18
 
10
19
  # Provide safe defaults for non-secret settings; allow caller/.env.e2e overrides.
11
20
  # Soak runs target the dedicated performance cloud by default.
12
21
  export SYNC_SOAK_LOCAL_BASE_URL="${SYNC_SOAK_LOCAL_BASE_URL:-http://localhost:5174}"
13
- export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
22
+ export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}}"
14
23
  export SYNC_SOAK_WORKSPACE_ID="${SYNC_SOAK_WORKSPACE_ID:-test-smoke}"
24
+ export SYNC_SOAK_EMAIL="${SYNC_SOAK_EMAIL:-${TASKFORCE_E2E_EMAIL:-}}"
25
+ export SYNC_SOAK_PASSWORD="${SYNC_SOAK_PASSWORD:-${TASKFORCE_E2E_PASSWORD:-}}"
26
+ unset TASKFORCE_E2E_EMAIL TASKFORCE_E2E_PASSWORD TASKFORCE_PLAYWRIGHT_STORAGE_STATE TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
15
27
 
16
28
  node --import tsx scripts/check-env.ts --target=soak --strict=true
17
29
 
18
- # Shared credentials are required and must come from env/.env.e2e.
30
+ # Shared credentials are required and may come from the local Playwright auth env file or repo .env.e2e.
19
31
  if [ -z "${SYNC_SOAK_ACCOUNTS_JSON:-}" ] && { [ -z "${SYNC_SOAK_EMAIL:-}" ] || [ -z "${SYNC_SOAK_PASSWORD:-}" ]; }; then
20
- echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in env/.env.e2e." >&2
32
+ echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in $TASKFORCE_PLAYWRIGHT_ENV_FILE or .env.e2e." >&2
21
33
  exit 1
22
34
  fi
23
35
 
@@ -284,7 +284,7 @@ export const workflowDocs = [
284
284
  ' - `### Next Action`',
285
285
  '6. Ask whether to save as `{artifacts.implementationPlan.path}`.',
286
286
  '7. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "implementation-plan.md"`.',
287
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
287
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
288
288
  '8. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
289
289
  '9. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
290
290
  '10. Print `prompts.handoffPrompt` and stop.'
@@ -358,7 +358,7 @@ export const workflowDocs = [
358
358
  ' - `### Next Step`',
359
359
  '4. Ask whether to save as `{artifacts.collaborationBlueprint.path}`.',
360
360
  '5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "collaboration-blueprint.md"`.',
361
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
361
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
362
362
  '6. Ask concise clarification questions only if required fields above are missing.',
363
363
  '7. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
364
364
  '8. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
@@ -435,14 +435,14 @@ export const workflowDocs = [
435
435
  ' - `### Next Step`',
436
436
  '4. Ask whether to save as `{artifacts.evaluationReport.path}`.',
437
437
  '5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "evaluation.md"`.',
438
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
438
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
439
439
  '6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
440
440
  '',
441
441
  '## 3. Optional Report Artifact',
442
442
  '',
443
443
  '1. Use report files only when user opts in.',
444
444
  '2. Save to `task attachment "evaluation.md"` and attach to task context when approved.',
445
- ' - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.',
445
+ ' - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.',
446
446
  '3. Stop.'
447
447
  ].join('\n')
448
448
  }
@@ -513,7 +513,7 @@ export const workflowDocs = [
513
513
  ' - `### Next Status`',
514
514
  '3. Ask whether to save as `{artifacts.reviewReport.path}`.',
515
515
  '4. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "review.md"`.',
516
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
516
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
517
517
  '5. Keep status within allowed statuses (`task`, `on-hold`, `in-progress`, `review`, `done`) unless user explicitly instructs otherwise.',
518
518
  ' - If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
519
519
  '6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
@@ -522,7 +522,7 @@ export const workflowDocs = [
522
522
  '',
523
523
  '1. Use report files only when user opts in.',
524
524
  '2. Save to `task attachment "review.md"` and attach to task context when approved.',
525
- ' - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.',
525
+ ' - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.',
526
526
  '3. Stop.'
527
527
  ].join('\n')
528
528
  }
@@ -102,7 +102,7 @@ content:
102
102
  - `### Next Step`
103
103
  4. Ask whether to save as `{artifacts.collaborationBlueprint.path}`.
104
104
  5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "collaboration-blueprint.md"`.
105
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
105
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
106
106
  6. Ask concise clarification questions only if required fields above are missing.
107
107
  7. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
108
108
  8. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
@@ -106,12 +106,12 @@ content:
106
106
  - `### Next Step`
107
107
  4. Ask whether to save as `{artifacts.evaluationReport.path}`.
108
108
  5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "evaluation.md"`.
109
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
109
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
110
110
  6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
111
111
 
112
112
  ## 3. Optional Report Artifact
113
113
 
114
114
  1. Use report files only when user opts in.
115
115
  2. Save to `task attachment "evaluation.md"` and attach to task context when approved.
116
- - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.
116
+ - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.
117
117
  3. Stop.
@@ -113,7 +113,7 @@ content:
113
113
  - `### Next Action`
114
114
  6. Ask whether to save as `{artifacts.implementationPlan.path}`.
115
115
  7. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "implementation-plan.md"`.
116
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
116
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
117
117
  8. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
118
118
  9. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
119
119
  10. Print `prompts.handoffPrompt` and stop.
@@ -102,7 +102,7 @@ content:
102
102
  - `### Next Status`
103
103
  3. Ask whether to save as `{artifacts.reviewReport.path}`.
104
104
  4. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "review.md"`.
105
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
105
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
106
106
  5. Keep status within allowed statuses (`task`, `on-hold`, `in-progress`, `review`, `done`) unless user explicitly instructs otherwise.
107
107
  - If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
108
108
  6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
@@ -111,5 +111,5 @@ content:
111
111
 
112
112
  1. Use report files only when user opts in.
113
113
  2. Save to `task attachment "review.md"` and attach to task context when approved.
114
- - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.
114
+ - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.
115
115
  3. Stop.
@@ -1 +0,0 @@
1
- import{r as n,j as e}from"./vendor-react-CKJs5o3c.js";import{p as T,u as C,v as w,w as S,t as s,x as M}from"./index-DcSI5F86.js";import{h as L,B as A,k as I,aa as B,aI as H,aJ as D,b as R}from"./vendor-icons-BSUaRwF8.js";import"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";import"./vendor-router-BbWMxlnO.js";function F({workspaceId:h}){const[x,k]=n.useState([]),[j,y]=n.useState(!1),[c,P]=n.useState(null),[p,m]=n.useState(null),[d,g]=n.useState(null),N=n.useCallback(async()=>{if(h){y(!0);try{const a=await(await fetch(`/api/taskforce/workspace/assignee-options?workspaceId=${encodeURIComponent(h)}`,{credentials:"include"})).json().catch(()=>({})),t=Array.isArray(a?.assignees)?a.assignees.filter(i=>i.kind==="agent").map(i=>({id:String(i.value||""),name:String(i.label||i.value||"Unknown Agent"),username:String(i.username||i.value||""),icon:String(i.icon||"Bot"),color:String(i.color||"#6B7280"),kind:String(i.kind||"agent"),description:typeof i.description=="string"?i.description:null,role:typeof i.role=="string"?i.role:null,provider:typeof i.provider=="string"?i.provider:null,model:typeof i.model=="string"?i.model:null,surfaceType:T(i.surfaceType),createdAt:String(i.createdAt||""),updatedAt:String(i.updatedAt||i.createdAt||""),lastActiveAt:typeof i.lastActiveAt=="string"?i.lastActiveAt:null})):[];k(t)}finally{y(!1)}}},[h]);n.useEffect(()=>{N()},[N]);const f=n.useMemo(()=>{const r=new Map;for(const a of x){const t=C(a.surfaceType);r.has(t)||r.set(t,new Map);const i=r.get(t),v=a.name.toLowerCase();i.has(v)||i.set(v,[]),i.get(v).push(a)}return w.map(a=>({section:a,label:S(a),groups:Array.from(r.get(a)?.entries()||[]).map(([t,i])=>({groupId:`${a}:${t}`,section:a,sectionLabel:S(a),profiles:i,primaryProfile:i[0]}))})).filter(a=>a.groups.length>0)},[x]),o=n.useMemo(()=>f.flatMap(r=>r.groups),[f]),l=n.useMemo(()=>o.find(r=>r.groupId===d)||o[0]||null,[o,d]);n.useEffect(()=>{if(!o.length){d!==null&&g(null);return}(!d||!o.some(r=>r.groupId===d))&&g(o[0].groupId)},[o,d]);const b=async(r,a)=>{m(null);try{const t=await fetch("/api/taskforce/workspace/ai-profiles/merge",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({keepId:r,mergeId:a})}),i=await t.json().catch(()=>({}));if(!t.ok){m({type:"error",message:String(i?.error||"Failed to merge AI profiles.")});return}P(null),m({type:"success",message:"AI profiles merged."}),await N()}catch{m({type:"error",message:"Failed to merge AI profiles."})}},u=r=>{const a=String(r||"").trim();if(!a)return"Unknown";const t=Date.parse(a);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):a};return e.jsx("div",{className:`${s.standalonePage} ${s.standaloneContent}`,style:{overflow:"auto"},children:e.jsx("div",{className:s.settingsContent,style:{maxWidth:1080,margin:"0 auto",width:"100%"},children:e.jsx("div",{className:s.settingGroup,children:e.jsxs("div",{children:[e.jsx("h4",{className:s.settingSubTitle,children:"Registered AI Profiles"}),e.jsx("p",{className:`${s.settingsHint} ${s.marginBottom12}`,children:"AI agents register profiles when connecting via MCP. Merge duplicates created when a token was lost."}),j&&e.jsxs("div",{className:s.settingsHint,children:[e.jsx(L,{size:13,className:s.spinner})," Loading profiles…"]}),!j&&x.length===0&&e.jsx("div",{className:s.settingsHint,children:"No AI profiles registered yet."}),!j&&f.length>0&&e.jsxs("div",{className:s.aiProfilesExplorer,children:[e.jsx("div",{className:s.aiProfilesListPane,children:e.jsx("div",{className:s.aiProfilesList,children:f.map(r=>e.jsxs("div",{className:s.aiProfilesSection,children:[e.jsx("div",{className:s.aiProfilesSectionHeader,children:r.label}),r.groups.map(a=>{const t=l?.groupId===a.groupId,i=a.primaryProfile;return e.jsxs("button",{type:"button",className:`${s.aiProfileGroup} ${a.profiles.length>1?s.aiProfileGroupDuplicate:""} ${t?s.aiProfileGroupSelected:""}`,onClick:()=>g(a.groupId),"aria-pressed":t,children:[e.jsxs("div",{className:s.aiProfileGroupHeader,children:[e.jsx(A,{size:13,style:{color:i.color}}),e.jsx("span",{className:s.aiProfileName,children:i.name}),a.profiles.length>1&&e.jsxs("span",{className:s.aiProfileDuplicateBadge,children:[e.jsx(I,{size:11})," ",a.profiles.length," duplicates"]})]}),e.jsxs("div",{className:s.settingsHint,style:{marginTop:6},children:["@",i.username]}),(i.surfaceType||i.role||i.provider||i.model)&&e.jsxs("div",{className:s.aiProfileMetaRow,children:[i.surfaceType&&e.jsx("span",{className:s.aiProfileSurfaceBadge,children:M(i.surfaceType)}),i.role&&e.jsx("span",{children:i.role}),i.provider&&e.jsx("span",{children:i.provider}),i.model&&e.jsx("span",{children:i.model})]}),i.description&&e.jsx("div",{className:s.settingsHint,style:{marginTop:4},children:i.description})]},a.groupId)})]},r.section))})}),l&&e.jsx("div",{className:s.aiProfileDetailPane,children:e.jsxs("div",{className:s.aiProfileDetailCard,children:[e.jsxs("div",{className:s.aiProfileDetailHero,children:[e.jsx("div",{className:s.aiProfileDetailIcon,style:{color:l.primaryProfile.color},children:e.jsx(A,{size:18})}),e.jsxs("div",{className:s.aiProfileDetailHeading,children:[e.jsx("div",{className:s.aiProfileDetailTitleRow,children:e.jsx("h5",{className:s.aiProfileDetailTitle,children:l.primaryProfile.name})}),e.jsxs("div",{className:s.aiProfileDetailMetaRow,children:[e.jsxs("span",{className:s.aiProfileDetailHandle,children:["@",l.primaryProfile.username]}),e.jsx("span",{className:s.aiProfileDetailSectionBadge,children:l.sectionLabel}),l.profiles.length>1&&e.jsxs("span",{className:s.aiProfileDetailLinkedCount,children:[l.profiles.length," linked"]})]})]})]}),l.primaryProfile.description&&e.jsx("div",{className:s.aiProfileDetailDescription,children:l.primaryProfile.description}),e.jsxs("div",{className:s.aiProfileDetailGrid,children:[e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(B,{size:12})," Role"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:l.primaryProfile.role||"Not set"})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(H,{size:12})," Provider"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:[l.primaryProfile.provider,l.primaryProfile.model].filter(Boolean).join(" · ")||"Not set"})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(D,{size:12})," Last active"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:u(l.primaryProfile.lastActiveAt)})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(D,{size:12})," Updated"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:u(l.primaryProfile.updatedAt)})]})]}),e.jsxs("div",{className:s.aiProfileInstanceSection,children:[e.jsxs("div",{className:s.aiProfileInstanceSectionHeader,children:[e.jsx("span",{children:"Profile instances"}),e.jsx("span",{className:s.settingsHint,children:"Choose a keeper here if duplicates need to be merged."})]}),e.jsx("div",{className:s.aiProfileInstanceList,children:l.profiles.map(r=>e.jsxs("div",{className:s.aiProfileInstanceCard,children:[e.jsxs("div",{className:s.aiProfileInstanceTopRow,children:[e.jsxs("div",{children:[e.jsxs("div",{className:s.aiProfileInstanceName,children:["@",r.username]}),e.jsx("div",{className:s.aiProfileIdChip,children:r.id})]}),l.profiles.length>1&&c?.keepId===r.id&&e.jsx("span",{className:s.aiProfileKeepBadge,children:"Keeping"})]}),e.jsxs("div",{className:s.aiProfileInstanceMeta,children:[e.jsxs("span",{children:["Created ",u(r.createdAt)]}),e.jsxs("span",{children:["Updated ",u(r.updatedAt)]})]}),l.profiles.length>1&&c?.keepId!==r.id&&e.jsx("button",{className:s.secondaryHeaderBtn,title:"Keep this profile, merge others into it",onClick:()=>{const a=l.profiles.find(t=>t.id!==r.id)?.id;a&&P({keepId:r.id,mergeId:a})},children:"Keep this"})]},r.id))}),c&&l.profiles.some(r=>r.id===c.keepId)&&e.jsxs("div",{className:s.aiProfileMergeActions,children:[e.jsx("button",{className:s.dangerBtn,onClick:()=>{b(c.keepId,c.mergeId)},children:"Merge duplicates"}),e.jsx("button",{className:s.secondaryHeaderBtn,onClick:()=>P(null),children:"Cancel"})]})]})]})})]}),p&&e.jsxs("div",{className:`${p.type==="success"?s.successMessage:s.errorMessage} ${s.marginTop12}`,children:[p.type==="success"?e.jsx(R,{size:14}):e.jsx(I,{size:14}),p.message]})]})})})})}export{F as AgentsModule};