@taskforcehq/taskforce 0.3.329 → 0.3.332

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/README.md +7 -2
  2. package/dist/Taskforce.module.css +290 -45
  3. package/dist/components/features/AiProfilesModule.js +3 -5
  4. package/dist/components/features/TaskSettings.js +70 -14
  5. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  6. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  7. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
  8. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
  9. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  10. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  11. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  12. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  13. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  14. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  15. package/dist/components/features/planning/PlanningModule.js +15 -3
  16. package/dist/components/features/planning/planningMetadata.d.ts +10 -0
  17. package/dist/components/features/planning/planningMetadata.js +8 -0
  18. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  19. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  20. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  21. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  22. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  23. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  24. package/dist/components/views/StandaloneLayout.js +62 -27
  25. package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
  26. package/dist/components/views/panels/PlanningDrawer.js +12 -8
  27. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  28. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  29. package/dist/config/envSchema.js +55 -1
  30. package/dist/core/McpTokenService.d.ts +25 -1
  31. package/dist/core/McpTokenService.js +106 -15
  32. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  33. package/dist/core/TaskChecklistCommandService.js +83 -5
  34. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  35. package/dist/core/TaskLifecycleCommandService.js +6 -2
  36. package/dist/core/Taskforce.d.ts +43 -3
  37. package/dist/core/Taskforce.js +158 -7
  38. package/dist/core/types.d.ts +9 -0
  39. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
  40. package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
  41. package/dist/documentReviews/commandService.d.ts +2 -1
  42. package/dist/documentReviews/commandService.js +6 -3
  43. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  44. package/dist/hooks/sync/orchestratorShared.js +2 -0
  45. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  46. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  47. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  48. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  49. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  50. package/dist/hooks/useSyncOrchestrator.js +111 -2
  51. package/dist/hooks/useTaskData.d.ts +31 -1
  52. package/dist/hooks/useTaskData.js +29 -7
  53. package/dist/hooks/useTaskMutations.d.ts +3 -1
  54. package/dist/hooks/useTaskMutations.js +46 -12
  55. package/dist/hooks/useTaskforce.d.ts +2 -0
  56. package/dist/hooks/useTaskforce.js +11 -2
  57. package/dist/mcp/clientRegistry.d.ts +2 -2
  58. package/dist/mcp/clientRegistry.js +1 -1
  59. package/dist/mcp/documentAssetRegistrar.js +9 -6
  60. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  61. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  62. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  63. package/dist/mcp/httpProtocolRouting.d.ts +11 -0
  64. package/dist/mcp/httpProtocolRouting.js +22 -0
  65. package/dist/mcp/localCliHealth.d.ts +2 -2
  66. package/dist/mcp/localCliHealth.js +2 -2
  67. package/dist/mcp/localServiceProxy.d.ts +1 -0
  68. package/dist/mcp/localServiceProxy.js +530 -68
  69. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  70. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  71. package/dist/mcp/runtime.d.ts +54 -79
  72. package/dist/mcp/runtime.js +408 -102
  73. package/dist/mcp/taskPlanningRegistrar.js +25 -6
  74. package/dist/mcp/toolProfiles.d.ts +2 -0
  75. package/dist/mcp/toolProfiles.js +11 -0
  76. package/dist/mcp/toolRegistry.d.ts +1 -0
  77. package/dist/mcp/toolRegistry.js +9 -8
  78. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  79. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  80. package/dist/migrations/taskSchemaMigrations.js +415 -0
  81. package/dist/runtime/appGates.d.ts +2 -1
  82. package/dist/runtime/appGates.js +7 -0
  83. package/dist/server/buildInfo.d.ts +1 -0
  84. package/dist/server/buildInfo.js +5 -1
  85. package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
  86. package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
  87. package/dist/server/index.d.ts +3 -0
  88. package/dist/server/index.js +108 -11
  89. package/dist/server/localDatabaseIdentity.js +4 -1
  90. package/dist/server/localServiceLease.js +2 -1
  91. package/dist/server/localServiceSessions.d.ts +14 -17
  92. package/dist/server/localServiceSessions.js +308 -94
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
  94. package/dist/server/routes/admin.d.ts +4 -0
  95. package/dist/server/routes/admin.js +126 -5
  96. package/dist/server/routes/agents.d.ts +7 -0
  97. package/dist/server/routes/agents.js +277 -24
  98. package/dist/server/routes/billing.js +5 -1
  99. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  100. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  101. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  102. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  103. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  104. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  105. package/dist/server/routes/githubReviewEvidence.js +116 -0
  106. package/dist/server/routes/localService.d.ts +15 -4
  107. package/dist/server/routes/localService.js +136 -40
  108. package/dist/server/routes/modelConnections.d.ts +24 -0
  109. package/dist/server/routes/modelConnections.js +205 -0
  110. package/dist/server/routes/shared.d.ts +22 -0
  111. package/dist/server/routes/shared.js +298 -182
  112. package/dist/server/routes/sync.js +1 -0
  113. package/dist/server/routes/syncAuxRoutes.js +5 -1
  114. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  115. package/dist/server/routes/syncPushRoutes.js +1 -0
  116. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  117. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  118. package/dist/server/routes/tasks.js +21 -2
  119. package/dist/server/routes/workflows.js +9 -1
  120. package/dist/server/routes.js +59 -0
  121. package/dist/service/localServiceCli.d.ts +2 -2
  122. package/dist/service/localServiceCli.js +4 -3
  123. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  124. package/dist/services/codexAppServerModelGateway.js +246 -21
  125. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  126. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  127. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  128. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  129. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  130. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  131. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  132. package/dist/services/executorPhaseAApprovalService.js +609 -0
  133. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  134. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  135. package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
  136. package/dist/services/executorPhaseAIssuerCore.js +402 -0
  137. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  138. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  139. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  140. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  141. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  142. package/dist/services/githubReviewEvidenceService.js +336 -0
  143. package/dist/services/modelGateway.d.ts +7 -0
  144. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  145. package/dist/services/modelProviderConnectionService.js +279 -0
  146. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  147. package/dist/services/modelProviderCredentialHome.js +271 -0
  148. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  149. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  150. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  151. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  152. package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
  153. package/dist/services/taskforceAgentMcpBridge.js +42 -29
  154. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  155. package/dist/shared/adminEdgeProxy.js +94 -0
  156. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  157. package/dist/shared/adminProxySessionCookies.js +86 -0
  158. package/dist/shared/aiProfileColors.d.ts +31 -1
  159. package/dist/shared/aiProfileColors.js +14 -6
  160. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  161. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  162. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  163. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  164. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  165. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  166. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  167. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  168. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  169. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  170. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  171. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  172. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  173. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  174. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  175. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  176. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  177. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  178. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  179. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  180. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  181. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  182. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  183. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  184. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  185. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  186. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  187. package/dist/shared/executorPhaseATiming.js +1 -0
  188. package/dist/shared/planningIdentity.js +1 -1
  189. package/dist/shared/productLogoKeys.d.ts +2 -0
  190. package/dist/shared/productLogoKeys.js +18 -0
  191. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  192. package/dist/shared/taskforceAgentDefinition.js +6 -9
  193. package/dist/shared/taskforceAgentModels.js +7 -3
  194. package/dist/shared/userFeatureGrants.d.ts +4 -0
  195. package/dist/shared/userFeatureGrants.js +7 -0
  196. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  197. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  198. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  199. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  200. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  201. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  202. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  203. package/dist/storage/modelProviderConnectionStore.js +446 -0
  204. package/dist/storage/postgresAdapter.d.ts +4 -0
  205. package/dist/storage/postgresAdapter.js +14 -1
  206. package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
  207. package/dist/storage/postgresRequestDiagnostics.js +15 -2
  208. package/dist/storage/postgresWorker.js +20 -2
  209. package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
  210. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  211. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  212. package/dist/storage/workflowStore.d.ts +2 -0
  213. package/dist/storage/workflowStore.js +39 -2
  214. package/dist/sync/cloudSyncApi.js +4 -2
  215. package/dist/sync/collaborationSyncState.js +5 -0
  216. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  217. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  218. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  219. package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
  220. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
  221. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  222. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  223. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  224. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  225. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  226. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  227. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  228. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  229. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  230. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  231. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  232. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  233. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  234. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  235. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  236. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  237. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  238. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
  239. package/dist/sync/syncApplyHandlers.d.ts +3 -0
  240. package/dist/sync/syncApplyHandlers.js +81 -15
  241. package/dist/sync/syncService.d.ts +15 -0
  242. package/dist/sync/syncService.js +83 -18
  243. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  244. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  245. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  246. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  247. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  248. package/dist/sync/v3/durableOperationReplay.js +18 -0
  249. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  250. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  251. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  252. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  253. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  254. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  255. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  256. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
  257. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
  258. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  259. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  260. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  261. package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
  262. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  263. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  264. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  265. package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
  266. package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
  267. package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
  268. package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
  269. package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
  270. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
  271. package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
  272. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
  273. package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
  274. package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
  275. package/dist/sync/v3/syncDurabilityStore.js +202 -8
  276. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  277. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  278. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  279. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  280. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  281. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  282. package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
  283. package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
  284. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  285. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  286. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  287. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  288. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  289. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
  290. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  291. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  292. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  293. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  294. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  295. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  296. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  297. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  298. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  299. package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
  300. package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
  301. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
  302. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
  303. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  304. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  305. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  306. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  307. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  308. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
  309. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
  310. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  311. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  312. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  313. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  314. package/dist/sync/workspaceRepair.d.ts +5 -2
  315. package/dist/sync/workspaceRepair.js +161 -6
  316. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  317. package/dist/sync/workspaceSyncModel.js +35 -7
  318. package/dist/sync/workspaceSyncState.d.ts +1 -0
  319. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  320. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  321. package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
  322. package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
  323. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
  324. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
  325. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
  326. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
  327. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
  328. package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
  329. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
  330. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
  331. package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
  332. package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
  333. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  334. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
  335. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  336. package/dist/ui/assets/index-DSQINwt9.js +7 -0
  337. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  338. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  339. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  340. package/dist/ui/branding/logos/signature_dark.png +0 -0
  341. package/dist/ui/branding/logos/signature_light.png +0 -0
  342. package/dist/ui/index.html +3 -3
  343. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  344. package/dist/utils/httpSetCookie.d.ts +1 -0
  345. package/dist/utils/httpSetCookie.js +4 -1
  346. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  347. package/dist/utils/localRuntimeUrl.js +14 -0
  348. package/dist/utils/productLogoRegistry.d.ts +2 -0
  349. package/dist/utils/productLogoRegistry.js +36 -0
  350. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  351. package/dist/utils/syncStatusPresentation.js +17 -0
  352. package/dist/utils/taskEvents.d.ts +2 -0
  353. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  354. package/dist/utils/workspaceSyncPresentation.js +23 -17
  355. package/package.json +24 -4
  356. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  357. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  358. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
  359. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  360. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  361. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  362. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  363. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -229,6 +229,9 @@ export interface WorkspaceSyncInitiativeSnapshot {
229
229
  order?: number | null;
230
230
  attachments?: Array<string | AttachmentItem>;
231
231
  isArchived?: boolean;
232
+ icon?: PlanningIdentityIcon | null;
233
+ color?: PlanningIdentityColor | null;
234
+ identityUpdatedAt?: string | null;
232
235
  durableRevision?: WorkspaceSyncDurablePlanningRevision<'initiative'>;
233
236
  }
234
237
  export interface WorkspaceSyncWorkstreamSnapshot {
@@ -245,6 +248,9 @@ export interface WorkspaceSyncWorkstreamSnapshot {
245
248
  order?: number | null;
246
249
  attachments?: Array<string | AttachmentItem>;
247
250
  isArchived?: boolean;
251
+ icon?: PlanningIdentityIcon | null;
252
+ color?: PlanningIdentityColor | null;
253
+ identityUpdatedAt?: string | null;
248
254
  durableRevision?: WorkspaceSyncDurablePlanningRevision<'workstream'>;
249
255
  }
250
256
  export interface WorkspaceSyncPlanningIdentitySnapshot {
@@ -425,6 +431,7 @@ export interface WorkspaceSyncPayload {
425
431
  currentInitiativeWatermarks: Map<string, string>;
426
432
  currentWorkstreamIds: Set<string>;
427
433
  currentWorkstreamWatermarks: Map<string, string>;
434
+ currentPlanningIdentityWatermarks?: Map<string, string>;
428
435
  currentAiProfileIds: Set<string>;
429
436
  currentAiProfileWatermarks: Map<string, string>;
430
437
  currentAiProfileChangeKeys?: Map<string, string>;
@@ -472,6 +479,7 @@ export interface WorkspaceSyncDeltaDiagnostics {
472
479
  taskRelationships?: WorkspaceSyncDomainDeltaDiagnostics;
473
480
  initiatives: WorkspaceSyncDomainDeltaDiagnostics;
474
481
  workstreams: WorkspaceSyncDomainDeltaDiagnostics;
482
+ planningIdentities?: WorkspaceSyncDomainDeltaDiagnostics;
475
483
  aiProfiles: WorkspaceSyncDomainDeltaDiagnostics;
476
484
  documents: WorkspaceSyncDomainDeltaDiagnostics;
477
485
  assets: WorkspaceSyncDomainDeltaDiagnostics;
@@ -537,6 +545,18 @@ export declare function buildWorkspaceSyncPayloadModel(input: {
537
545
  assets?: WorkspaceSyncAssetSnapshot[];
538
546
  currentDocumentPaths?: Iterable<string>;
539
547
  currentAssetPaths?: Iterable<string>;
548
+ /**
549
+ * Positive completeness signal for the current-workspace document/asset
550
+ * snapshot used to compute deleteDocumentPaths/deleteAssetPaths. Explicit
551
+ * `false` means the snapshot is known failed, partial, stale, for the wrong
552
+ * workspace, or not yet hydrated — the delete-diff for that domain is
553
+ * suppressed entirely rather than trusted. Omitted/undefined defaults to
554
+ * `true` for callers (tests, other pure-function consumers) that don't model
555
+ * hydration state; the real browser sync orchestrator always passes the
556
+ * verified value.
557
+ */
558
+ documentsSnapshotComplete?: boolean;
559
+ assetsSnapshotComplete?: boolean;
540
560
  documentReviewSessions?: WorkspaceSyncDocumentReviewSessionSnapshot[];
541
561
  documentReviewComments?: WorkspaceSyncDocumentReviewCommentSnapshot[];
542
562
  annotatedAttachmentSessions?: WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
@@ -549,6 +569,7 @@ export declare function buildWorkspaceSyncPayloadModel(input: {
549
569
  lastPushedInitiativeWatermarks?: Map<string, string>;
550
570
  lastPushedWorkstreamIds?: Set<string>;
551
571
  lastPushedWorkstreamWatermarks?: Map<string, string>;
572
+ lastPushedPlanningIdentityWatermarks?: Map<string, string>;
552
573
  lastPushedAiProfileIds?: Set<string>;
553
574
  lastPushedAiProfileWatermarks?: Map<string, string>;
554
575
  lastPushedDocumentPaths?: Set<string>;
@@ -223,6 +223,8 @@ export function buildWorkspaceSyncPayloadModel(input) {
223
223
  return true;
224
224
  return previousWorkstreamWatermarks.get(change.workstream.id) !== change.workstream.updatedAt;
225
225
  });
226
+ const previousPlanningIdentityWatermarks = input.lastPushedPlanningIdentityWatermarks;
227
+ const currentPlanningIdentityWatermarks = new Map();
226
228
  const planningIdentityUpsertChanges = [
227
229
  ...(Array.isArray(input.initiatives) ? input.initiatives : []).map((initiative) => ({
228
230
  entityType: 'initiative',
@@ -240,7 +242,13 @@ export function buildWorkspaceSyncPayloadModel(input) {
240
242
  })),
241
243
  ]
242
244
  .filter((identity) => identity.entityId.length > 0 && Number.isFinite(Date.parse(identity.updatedAt)))
243
- .map((identity) => ({ op: 'planning-identity-upsert', identity }));
245
+ .map((identity) => {
246
+ const identityKey = `${identity.entityType}:${identity.entityId}`;
247
+ currentPlanningIdentityWatermarks.set(identityKey, identity.updatedAt);
248
+ return { op: 'planning-identity-upsert', identity, identityKey };
249
+ })
250
+ .filter((change) => previousPlanningIdentityWatermarks?.get(change.identityKey) !== change.identity.updatedAt)
251
+ .map(({ identityKey: _identityKey, ...change }) => change);
244
252
  const currentAiProfileIds = new Set((Array.isArray(input.aiProfiles) ? input.aiProfiles : [])
245
253
  .map((profile) => String(profile?.id || '').trim())
246
254
  .filter((profileId) => profileId.length > 0));
@@ -312,9 +320,18 @@ export function buildWorkspaceSyncPayloadModel(input) {
312
320
  });
313
321
  const currentDocumentPaths = normalizeWorkspaceSyncPathSet(input.currentDocumentPaths, (Array.isArray(input.documents) ? input.documents : [])
314
322
  .map((doc) => String(doc?.path || '').trim()));
315
- const deleteDocumentPaths = new Set(Array.from(input.lastPushedDocumentPaths || new Set())
316
- .map((docPath) => String(docPath || '').trim())
317
- .filter((docPath) => docPath.length > 0 && !currentDocumentPaths.has(docPath)));
323
+ // A raw set-difference against the previous push is only trustworthy when the
324
+ // current snapshot is a verified-complete, current-workspace read. A failed,
325
+ // partial, stale, or not-yet-hydrated snapshot must never be interpreted as
326
+ // deletion intent — so documentsSnapshotComplete === false suppresses the
327
+ // entire delete-diff for this cycle rather than trusting a plausible-looking
328
+ // but potentially wrong difference.
329
+ const documentsSnapshotComplete = input.documentsSnapshotComplete !== false;
330
+ const deleteDocumentPaths = documentsSnapshotComplete
331
+ ? new Set(Array.from(input.lastPushedDocumentPaths || new Set())
332
+ .map((docPath) => String(docPath || '').trim())
333
+ .filter((docPath) => docPath.length > 0 && !currentDocumentPaths.has(docPath)))
334
+ : new Set();
318
335
  const currentDocumentWatermarks = new Map((Array.isArray(input.documents) ? input.documents : [])
319
336
  .map((doc) => [String(doc?.path || '').trim(), String(doc?.updatedAt || '').trim()])
320
337
  .filter(([docPath]) => docPath.length > 0));
@@ -349,9 +366,14 @@ export function buildWorkspaceSyncPayloadModel(input) {
349
366
  });
350
367
  const currentAssetPaths = normalizeWorkspaceSyncPathSet(input.currentAssetPaths, (Array.isArray(input.assets) ? input.assets : [])
351
368
  .map((asset) => String(asset?.path || '').trim()));
352
- const deleteAssetPaths = new Set(Array.from(input.lastPushedAssetPaths || new Set())
353
- .map((assetPath) => String(assetPath || '').trim())
354
- .filter((assetPath) => assetPath.length > 0 && !currentAssetPaths.has(assetPath)));
369
+ // See documentsSnapshotComplete above the same admission boundary applies
370
+ // to assets.
371
+ const assetsSnapshotComplete = input.assetsSnapshotComplete !== false;
372
+ const deleteAssetPaths = assetsSnapshotComplete
373
+ ? new Set(Array.from(input.lastPushedAssetPaths || new Set())
374
+ .map((assetPath) => String(assetPath || '').trim())
375
+ .filter((assetPath) => assetPath.length > 0 && !currentAssetPaths.has(assetPath)))
376
+ : new Set();
355
377
  const currentAssetWatermarks = new Map((Array.isArray(input.assets) ? input.assets : [])
356
378
  .map((asset) => [String(asset?.path || '').trim(), String(asset?.updatedAt || '').trim()])
357
379
  .filter(([assetPath]) => assetPath.length > 0));
@@ -958,6 +980,7 @@ export function buildWorkspaceSyncPayloadModel(input) {
958
980
  currentInitiativeWatermarks,
959
981
  currentWorkstreamIds,
960
982
  currentWorkstreamWatermarks,
983
+ currentPlanningIdentityWatermarks,
961
984
  currentAiProfileIds,
962
985
  currentAiProfileWatermarks,
963
986
  currentAiProfileChangeKeys,
@@ -1012,6 +1035,11 @@ export function buildWorkspaceSyncPayloadModel(input) {
1012
1035
  baselineCount: previousWorkstreamWatermarks?.size || 0,
1013
1036
  upsertCount: workstreamUpsertChanges.length
1014
1037
  }),
1038
+ planningIdentities: resolveDomainDeltaDiagnostics({
1039
+ currentCount: currentPlanningIdentityWatermarks.size,
1040
+ baselineCount: previousPlanningIdentityWatermarks?.size || 0,
1041
+ upsertCount: planningIdentityUpsertChanges.length
1042
+ }),
1015
1043
  aiProfiles: resolveDomainDeltaDiagnostics({
1016
1044
  currentCount: currentAiProfileIds.size,
1017
1045
  baselineCount: previousAiProfileWatermarks?.size || 0,
@@ -11,6 +11,7 @@ export interface WorkspaceSyncPushBaselineSnapshot {
11
11
  taskRelationshipChangeKeys?: Array<[string, string]>;
12
12
  initiativeWatermarks: Array<[string, string]>;
13
13
  workstreamWatermarks: Array<[string, string]>;
14
+ planningIdentityWatermarks?: Array<[string, string]>;
14
15
  aiProfileWatermarks: Array<[string, string]>;
15
16
  aiProfileChangeKeys?: Array<[string, string]>;
16
17
  taskforceAgentWatermarks?: Array<[string, string]>;
@@ -19,6 +19,9 @@ export interface WorkspaceSyncV2SnapshotInput {
19
19
  assets?: readonly WorkspaceSyncAssetSnapshot[];
20
20
  currentDocumentPaths?: ReadonlySet<string>;
21
21
  currentAssetPaths?: ReadonlySet<string>;
22
+ /** See WorkspaceSyncPayloadModel's documentsSnapshotComplete/assetsSnapshotComplete. */
23
+ documentsSnapshotComplete?: boolean;
24
+ assetsSnapshotComplete?: boolean;
22
25
  documentReviewSessions?: readonly WorkspaceSyncDocumentReviewSessionSnapshot[];
23
26
  documentReviewComments?: readonly WorkspaceSyncDocumentReviewCommentSnapshot[];
24
27
  annotatedAttachmentSessions?: readonly WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
@@ -45,6 +48,8 @@ export interface WorkspaceSyncV2FrozenSnapshot {
45
48
  readonly assets: readonly WorkspaceSyncAssetSnapshot[];
46
49
  readonly currentDocumentPaths: ReadonlySet<string>;
47
50
  readonly currentAssetPaths: ReadonlySet<string>;
51
+ readonly documentsSnapshotComplete: boolean;
52
+ readonly assetsSnapshotComplete: boolean;
48
53
  readonly documentReviewSessions: readonly WorkspaceSyncDocumentReviewSessionSnapshot[];
49
54
  readonly documentReviewComments: readonly WorkspaceSyncDocumentReviewCommentSnapshot[];
50
55
  readonly annotatedAttachmentSessions: readonly WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
@@ -64,6 +69,7 @@ export interface WorkspaceSyncV2PushBaseline {
64
69
  readonly lastPushedInitiativeWatermarks: ReadonlyMap<string, string>;
65
70
  readonly lastPushedWorkstreamIds: ReadonlySet<string>;
66
71
  readonly lastPushedWorkstreamWatermarks: ReadonlyMap<string, string>;
72
+ readonly lastPushedPlanningIdentityWatermarks?: ReadonlyMap<string, string>;
67
73
  readonly lastPushedAiProfileIds: ReadonlySet<string>;
68
74
  readonly lastPushedAiProfileWatermarks: ReadonlyMap<string, string>;
69
75
  readonly lastPushedAiProfileChangeKeys: ReadonlyMap<string, string>;
@@ -62,6 +62,8 @@ export function createWorkspaceSyncV2FrozenSnapshot(input) {
62
62
  assets,
63
63
  currentDocumentPaths: stringSet(input.currentDocumentPaths, documents.map((entry) => entry.path)),
64
64
  currentAssetPaths: stringSet(input.currentAssetPaths, assets.map((entry) => entry.path)),
65
+ documentsSnapshotComplete: input.documentsSnapshotComplete !== false,
66
+ assetsSnapshotComplete: input.assetsSnapshotComplete !== false,
65
67
  documentReviewSessions: frozenArray(input.documentReviewSessions),
66
68
  documentReviewComments: frozenArray(input.documentReviewComments),
67
69
  annotatedAttachmentSessions: frozenArray(input.annotatedAttachmentSessions),
@@ -119,6 +121,7 @@ export function buildWorkspaceSyncV2Candidate(input) {
119
121
  lastPushedInitiativeWatermarks: mutableMap(baseline.lastPushedInitiativeWatermarks),
120
122
  lastPushedWorkstreamIds: mutableSet(baseline.lastPushedWorkstreamIds),
121
123
  lastPushedWorkstreamWatermarks: mutableMap(baseline.lastPushedWorkstreamWatermarks),
124
+ lastPushedPlanningIdentityWatermarks: mutableMap(baseline.lastPushedPlanningIdentityWatermarks || new Map()),
122
125
  aiProfiles: Array.from(snapshot.aiProfiles),
123
126
  lastPushedAiProfileIds: forceAllAiProfiles ? new Set() : mutableSet(baseline.lastPushedAiProfileIds),
124
127
  lastPushedAiProfileWatermarks: forceAllAiProfiles ? new Map() : mutableMap(baseline.lastPushedAiProfileWatermarks),
@@ -127,6 +130,8 @@ export function buildWorkspaceSyncV2Candidate(input) {
127
130
  assets: Array.from(snapshot.assets),
128
131
  currentDocumentPaths: snapshot.currentDocumentPaths,
129
132
  currentAssetPaths: snapshot.currentAssetPaths,
133
+ documentsSnapshotComplete: snapshot.documentsSnapshotComplete,
134
+ assetsSnapshotComplete: snapshot.assetsSnapshotComplete,
130
135
  documentReviewSessions: Array.from(snapshot.documentReviewSessions),
131
136
  documentReviewComments: Array.from(snapshot.documentReviewComments),
132
137
  annotatedAttachmentSessions: Array.from(snapshot.annotatedAttachmentSessions),
@@ -0,0 +1 @@
1
+ import{j as i}from"./vendor-react-CKJs5o3c.js";import{t as r}from"./index-DSQINwt9.js";const t=[{name:"Blue",value:"#4269d0"},{name:"Orange",value:"#efb118"},{name:"Red",value:"#ff725c"},{name:"Cyan",value:"#6cc5b0"},{name:"Green",value:"#3ca951"},{name:"Pink",value:"#ff8ab7"},{name:"Purple",value:"#a463f2"},{name:"Light blue",value:"#97bbf5"},{name:"Brown",value:"#9c6b4e"},{name:"Gray",value:"#9498a0"}];function N(e){const s=String(e||"ai").trim().toLowerCase();let a=2166136261;for(let l=0;l<s.length;l+=1)a^=s.charCodeAt(l),a=Math.imul(a,16777619);return t[(a>>>0)%t.length].value}function b(e){const[s,a=""]=e.split("#"),n=s.includes("?")?"&":"?";return`${s}${n}taskforceCloud=1${a?`#${a}`:""}`}function $(e){return/^https?:\/\//i.test(e)?e:b(e)}function j({name:e,username:s,subtitle:a,avatar:n,selected:l,disabled:o=!1,onSelect:u,ariaLabel:c,avatarVariant:f="portrait",avatarClassName:m="",avatarStyle:d,className:p="",topUtility:h,bottomUtility:v,footer:P}){return i.jsxs("button",{type:"button",className:`${r.aiProfileGroup} ${l?r.aiProfileGroupSelected:""} ${p}`.trim(),onClick:u,disabled:o,"aria-label":c,"aria-pressed":l,children:[h,v,i.jsxs("span",{className:r.aiProfileGroupHeader,children:[i.jsx("span",{className:`${r.aiProfileGroupAvatar} ${f==="logo"?r.aiProfileGroupAvatarLogo:""} ${m}`.trim(),style:d,"aria-hidden":"true",children:n}),i.jsxs("span",{className:r.aiProfileGroupIdentity,children:[i.jsx("span",{className:r.aiProfileName,children:e}),s?i.jsxs("span",{className:r.aiProfileHandle,children:["@",s]}):null,i.jsx("span",{className:r.aiProfileRole,children:a}),P]})]})]})}export{j as A,N as a,t as b,$ as r,b as w};
@@ -0,0 +1 @@
1
+ import{r as f,j as a}from"./vendor-react-CKJs5o3c.js";import{ad as Qe,ae as re,U as Ue,af as ea,ag as W,t as r,W as aa,ah as ra,ai as Re,X as ta,aj as ia,ak as te,al as Me,am as la,Z as oa,Y as Ee,a0 as b,a1 as ke}from"./index-DSQINwt9.js";import{A as sa,b as na,r as Ce}from"./AiIdentityRosterCard-CDMPtnbC.js";import{ay as ca,ak as da,U as fa,w as ua,Z as V,J as Le,ax as pa,aC as ma}from"./vendor-icons-Bsq-mcEn.js";import"./vendor-markdown-_lhNCyq-.js";import"./vendor-dnd-CJ-AjP-Y.js";import"./vendor-router-AqJMU8Lz.js";const va=["chat_app","ide","cli","coding_tool","taskforce_agent","agent","unclassified"];function L(l){return typeof l.avatarUrl=="string"&&l.avatarUrl.trim().length>0}function ie(l){return l?Ee(l.avatarUrl,l.avatarRevision,l.avatarUpdatedAt):""}function ga(l){return l?Ee(l.avatarSourceUrl,l.avatarRevision,l.avatarUpdatedAt):""}function ha(l){return l.find(L)||l[0]}function ya({profile:l,className:g=""}){const A=ie(l),$=W(l),{activeImageUrl:T,handleImageError:Y}=oa(A,$);return T?a.jsx("img",{src:T,alt:"",className:g,onError:Y}):a.jsx(Le,{size:22})}function K(l){const g=te(l);return g?`taskforce-agent:${g}`:`${l.seatScope||"unknown"}:${l.name.trim().toLowerCase()}`}function le(l){const g=l.providerMetadata?.taskforce;return!!(g&&typeof g=="object"&&!Array.isArray(g)&&String(g.taskforceAgentId||"").trim())}function Pa(l){return le(l)?"taskforce_agent":Me(l.surfaceType)}function Te(l){return l==="taskforce_agent"?"Taskforce Agents":la(l)}function Aa(l){return le(l)?"Taskforce Agent":l.surfaceType?Re(l.surfaceType):""}function Sa(l){const g=Math.max(0,l-1);return`${g} duplicate${g===1?"":"s"}`}function we(l){return!l||typeof l!="object"?null:{used:Math.max(0,Number(l.used||0)),limit:l.limit===null||l.limit===void 0?null:Math.max(0,Number(l.limit||0)),remaining:l.remaining===null||l.remaining===void 0?null:Math.max(0,Number(l.remaining||0))}}function De(l,g){const A=g?.variant==="inline"?`${r.aiProfileSeatScopeIcon} ${r.aiProfileSeatScopeIconInline}`:g?.variant==="detail"?`${r.aiProfileSeatScopeIcon} ${r.aiProfileSeatScopeIconDetail}`:r.aiProfileSeatScopeIcon;return l==="cloud_metered"?a.jsx("span",{className:`${A} ${r.aiProfileSeatScopeIconCloud}`,title:"Cloud MCP","aria-label":"Cloud MCP",children:a.jsx(pa,{size:20})}):l==="local_unmetered"?a.jsx("span",{className:`${A} ${r.aiProfileSeatScopeIconLocal}`,title:"Local MCP","aria-label":"Local MCP",children:a.jsx(ma,{size:20})}):null}function Ca({workspaceId:l,runtimeMode:g="local",cloudAuthConfigured:A=!1,authSessionResolved:$=!1,isAuthenticated:T=!1,cloudAiProfileSeatUsage:Y=null,agentTrayOpen:Z=!1,onCloseAgentTray:$e,mcpSettingsNode:oe=null,resolveCloudAuthUrl:B,theme:Be="dark",onNotice:w}){const[N,O]=f.useState([]),[Oe,Fe]=f.useState(null),[Ge,se]=f.useState(!1),[S,F]=f.useState(null),[G,D]=f.useState(null),[ne,X]=f.useState(null),[_e,ce]=f.useState(!1),[U,_]=f.useState(null),[de,fe]=f.useState(null),[ue,z]=f.useState(!1),[ze,P]=f.useState(null),[He,x]=f.useState(null),[R,pe]=f.useState(null),[me,k]=f.useState({}),[ve,ge]=f.useState(!1),[q,he]=f.useState(!1),[ye,Pe]=f.useState(null),C=f.useCallback(async()=>{if(l){se(!0);try{const e=`/api/taskforce/workspace/assignee-options?workspaceId=${encodeURIComponent(l)}&kind=agent`,t=await fetch(e,{credentials:"include"}),o=t.ok?await t.json().catch(()=>({})):{},s=we(o?.aiProfileSeatUsage),d=Array.isArray(o?.assignees)?o.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"),colorSource:typeof i.colorSource=="string"?i.colorSource:null,colorUpdatedAt:typeof i.colorUpdatedAt=="string"?i.colorUpdatedAt:null,avatarUrl:typeof i.avatarUrl=="string"?i.avatarUrl:null,avatarSourceUrl:typeof i.avatarSourceUrl=="string"?i.avatarSourceUrl:null,avatarRevision:Number.isFinite(Number(i.avatarRevision))?Math.max(0,Math.floor(Number(i.avatarRevision))):0,avatarUpdatedAt:typeof i.avatarUpdatedAt=="string"?i.avatarUpdatedAt:null,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:re(i.surfaceType),seatScope:Qe(i.seatScope),providerMetadata:i.providerMetadata&&typeof i.providerMetadata=="object"&&!Array.isArray(i.providerMetadata)?i.providerMetadata:null,archivedAt:typeof i.archivedAt=="string"?i.archivedAt:null,createdAt:String(i.createdAt||""),updatedAt:String(i.updatedAt||i.createdAt||""),lastActiveAt:typeof i.lastActiveAt=="string"?i.lastActiveAt:null})):[];O(d),Fe(s),D(i=>i&&!d.some(u=>u.id===i.profileId)?null:i),X(i=>i&&!d.some(u=>u.id===i.profileId)?null:i)}finally{se(!1)}}},[l]);f.useEffect(()=>{C()},[C]),f.useEffect(()=>{const e=t=>{const o=t.detail;(String(o?.workspaceId||"").trim()||"default")===l&&o?.origin!=="ai-profiles-module"&&C()};return window.addEventListener(Ue,e),()=>window.removeEventListener(Ue,e)},[C,l]);const H=f.useMemo(()=>{const e=new Map;for(const t of N){const o=Pa(t);e.has(o)||e.set(o,new Map);const s=e.get(o),d=K(t);s.has(d)||s.set(d,[]),s.get(d).push(t)}return va.map(t=>({section:t,label:Te(t),groups:Array.from(e.get(t)?.entries()||[]).map(([o,s])=>({groupId:`${t}:${o}`,section:t,sectionLabel:Te(t),profiles:s,primaryProfile:ha(s)}))})).filter(t=>t.groups.length>0)},[N]),I=f.useMemo(()=>H.flatMap(e=>e.groups),[H]),n=f.useMemo(()=>I.find(e=>e.groupId===U)||I[0]||null,[I,U]),p=f.useMemo(()=>N.find(e=>e.id===de)||null,[N,de]),Ae=p&&me[p.id]||null,Se=n&&me[n.primaryProfile.id]||null;f.useEffect(()=>{if(!I.length){U!==null&&_(null);return}(!U||!I.some(e=>e.groupId===U))&&_(I[0].groupId)},[I,U]);const Je=async(e,t)=>{D(null);try{const o=await fetch("/api/taskforce/workspace/ai-profiles/merge",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({keepId:e,mergeId:t})}),s=await o.json().catch(()=>({}));if(!o.ok){w?.(String(s?.error||"Failed to merge AI profiles."),"error");return}F(null),w?.("AI profiles merged.","success"),await C(),b({workspaceId:l,profileId:e,reason:"merge",origin:"ai-profiles-module"})}catch{w?.("Failed to merge AI profiles.","error")}},xe=async e=>{if(window.confirm(`Remove ${e.name} from the active roster? This frees an AI profile seat and preserves task and comment history.`)){D(null);try{const o=await fetch("/api/taskforce/workspace/ai-profiles/archive",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:e.id,reason:"manual_archive"})}),s=await o.json().catch(()=>({}));if(!o.ok){D({profileId:e.id,message:String(s?.error||"Failed to remove AI profile from roster.")});return}(S?.keepId===e.id||S?.mergeId===e.id)&&F(null),w?.("AI profile removed from active roster.","success"),await C(),b({workspaceId:l,profileId:e.id,reason:"archive",origin:"ai-profiles-module"})}catch{D({profileId:e.id,message:"Failed to remove AI profile from roster."})}}},Ve=async(e,t)=>{const o=re(t),s=new Set(e.profiles.map(u=>u.surfaceType??"")),d=o??"";if(s.size===1&&s.has(d))return;ce(!0),X(null);const i=[];try{for(const c of e.profiles){const m=await fetch("/api/taskforce/workspace/ai-profiles/surface-type",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:c.id,surfaceType:o})}),v=await m.json().catch(()=>({}));if(!m.ok||!v?.profile)throw new Error(String(v?.error||"Failed to update AI profile category."));const j=v.profile;i.push({...c,surfaceType:re(j.surfaceType),updatedAt:typeof j.updatedAt=="string"?j.updatedAt:c.updatedAt})}const u=new Map(i.map(c=>[c.id,c]));O(c=>c.map(m=>u.get(m.id)||m));const h=u.get(e.primaryProfile.id)||{...e.primaryProfile,surfaceType:o},y=Me(h.surfaceType);_(`${y}:${K(h)}`),w?.("AI profile category updated.","success");for(const c of i)b({workspaceId:l,profileId:c.id,reason:"update",origin:"ai-profiles-module"})}catch(u){X({profileId:e.primaryProfile.id,message:String(u?.message||"Failed to update AI profile category.")})}finally{ce(!1)}},Ie=async(e,t,o=!1)=>{he(!0),Pe(null);try{const s=K(e.primaryProfile),d=N.filter(c=>K(c)===s),i=await fetch("/api/taskforce/workspace/ai-profiles/color",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileIds:d.map(c=>c.id),color:t,reset:o})}),u=await i.text();let h={};try{h=u?JSON.parse(u):{}}catch{h={}}if(!i.ok){const c=i.status===404?"Color updates are unavailable in the running Taskforce server. Restart Taskforce and try again.":`Failed to update AI profile color (HTTP ${i.status}).`;throw new Error(String(h.error||c))}if(!Array.isArray(h.profiles))throw new Error("Taskforce returned an invalid response while updating the AI profile color.");const y=new Map(h.profiles.map(c=>[String(c.id),c]));O(c=>c.map(m=>{const v=y.get(m.id);return v?{...m,color:String(v.color||m.color),colorSource:v.colorSource??m.colorSource,colorUpdatedAt:v.colorUpdatedAt??m.colorUpdatedAt,updatedAt:v.updatedAt??m.updatedAt}:m})),ge(!1);for(const c of d)b({workspaceId:l,profileId:c.id,reason:"update",origin:"ai-profiles-module"})}catch(s){Pe(String(s?.message||"Failed to update AI profile color."))}finally{he(!1)}},je=e=>new Promise((t,o)=>{const s=new FileReader;s.onload=()=>t(String(s.result||"")),s.onerror=()=>o(new Error("Failed to read image file.")),s.readAsDataURL(e)}),Q=e=>{const t=String(e?.id||"").trim();t&&O(o=>o.map(s=>s.id===t?{...s,avatarUrl:typeof e.avatarUrl=="string"?e.avatarUrl:null,avatarSourceUrl:typeof e.avatarSourceUrl=="string"?e.avatarSourceUrl:null,avatarRevision:Number.isFinite(Number(e.avatarRevision))?Math.max(0,Math.floor(Number(e.avatarRevision))):s.avatarRevision,avatarUpdatedAt:typeof e.avatarUpdatedAt=="string"?e.avatarUpdatedAt:s.avatarUpdatedAt,updatedAt:typeof e.updatedAt=="string"?e.updatedAt:s.updatedAt}:s))},Ke=async(e,t,o,s=!1)=>{const d=await je(t),i=o?await je(o):null,u={profileId:e,preserveExistingSource:s,displayImage:{dataUrl:d,mimeType:t.type||"application/octet-stream",originalName:t.name||"display-avatar"}};o&&i&&(u.sourceImage={dataUrl:i,mimeType:o.type||"application/octet-stream",originalName:o.name||"source-avatar"});const h=await fetch("/api/taskforce/workspace/ai-profiles/avatar/upload",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}),y=await h.json().catch(()=>({}));if(!h.ok||!y?.profile)throw new Error(String(y?.error||"Failed to update AI profile avatar."));Q(y.profile),b({workspaceId:l,profileId:e,reason:"avatar",origin:"ai-profiles-module"})},We=async e=>{const t=await fetch("/api/taskforce/workspace/ai-profiles/avatar",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:e,avatarUrl:null,avatarSourceUrl:null})}),o=await t.json().catch(()=>({}));if(!t.ok||!o?.profile)throw new Error(String(o?.error||"Failed to update AI profile avatar."));Q(o.profile),b({workspaceId:l,profileId:e,reason:"avatar",origin:"ai-profiles-module"})},Ye=async e=>{if(R)return!1;const t=te(e),o=L(e);if(o&&!window.confirm(`Replace the existing avatar for ${e.name}?`))return!1;const s=t?"":window.prompt("Optional visual direction (300 characters maximum). Leave blank to use the profile details.","");if(s===null)return!1;const d=g==="local";if(d&&(!A||!$||!T||!B))return P("Sign in to Taskforce Cloud to generate profile avatars."),x(null),!1;pe(e.id),P(null),x(null),k(i=>({...i,[e.id]:{error:null,notice:null}}));try{const i=t?`/api/taskforce/agents/${encodeURIComponent(t)}/avatar/generate`:"/api/taskforce/workspace/ai-profiles/avatar/generate",u=d&&B?B(i):i,h=await fetch(u,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(t?{workspaceId:l}:{workspaceId:l,profileId:e.id,visualDirection:s.slice(0,300),replaceExisting:o})}),y=await h.text().catch(()=>"");let c={};if(y&&!/^\s*(?:<!doctype\s+html|<html\b)/i.test(y))try{c=JSON.parse(y)}catch{c={}}if(!h.ok||!c?.profile&&!c?.agent)throw new Error(String(c?.error||(h.status?`Unable to generate avatar. HTTP ${h.status}.`:"Unable to generate avatar.")));const m=c.profile||{id:e.id,avatarUrl:c.agent?.avatarUrl??null,avatarSourceUrl:c.agent?.avatarSourceUrl??null,avatarRevision:c.agent?.avatarRevision??0,avatarUpdatedAt:c.agent?.avatarUpdatedAt??null},v=d&&B?{...m,avatarUrl:m.avatarUrl?Ce(m.avatarUrl):m.avatarUrl,avatarSourceUrl:m.avatarSourceUrl?Ce(m.avatarSourceUrl):m.avatarSourceUrl}:m;return Q(v),k(d?j=>({...j,[e.id]:{error:null,notice:`Generated photo for ${e.name} was saved in Taskforce Cloud. The local copy will be retained when sync runs.`}}):j=>({...j,[e.id]:{error:null,notice:`Generated photo for ${e.name} was saved.`}})),b({workspaceId:l,profileId:e.id,reason:"avatar",origin:"ai-profiles-module",...t?{taskforceAgentAvatar:{agentId:t,avatarUrl:typeof v.avatarUrl=="string"?v.avatarUrl:null,avatarSourceUrl:typeof v.avatarSourceUrl=="string"?v.avatarSourceUrl:null,avatarRevision:Number.isFinite(Number(v.avatarRevision))?Math.max(0,Math.floor(Number(v.avatarRevision))):0,avatarUpdatedAt:typeof v.avatarUpdatedAt=="string"?v.avatarUpdatedAt:null}}:{}}),!0}catch(i){return k(u=>({...u,[e.id]:{error:String(i?.message||"Unable to generate profile avatar."),notice:null}})),!1}finally{pe(null)}},Ze=async(e,t,o)=>{if(!p)return!1;if(!e.type.startsWith("image/"))return P("AI profile photo must be an image file."),!1;z(!0),P(null),x(null),k(s=>{const d={...s};return delete d[p.id],d});try{const s=await ke(e,{maxBytes:5242880});if(s.exceededLimit)throw new Error(e.type==="image/gif"?"Animated GIF AI profile photos must be 5 MB or smaller.":"AI profile photo must be 5 MB or smaller.");const d=s.file;let i=null;if(t){const u=await ke(t,{maxBytes:5242880});if(u.exceededLimit)throw new Error(t.type==="image/gif"?"Animated GIF AI profile photos must be 5 MB or smaller.":"AI profile source photo must be 5 MB or smaller.");i=u.file}return await Ke(p.id,d,i,o?.preserveExistingSource===!0),!0}catch(s){return P(String(s?.message||"Failed to update AI profile photo.")),!1}finally{z(!1)}},Xe=async()=>{if(p){z(!0),P(null),x(null),k(e=>{const t={...e};return delete t[p.id],t});try{await We(p.id),x("Profile photo removed.")}catch(e){P(String(e?.message||"Failed to remove AI profile photo."))}finally{z(!1)}}},M=e=>{const t=String(e||"").trim();if(!t)return"Unknown";const o=Date.parse(t);return Number.isFinite(o)?new Date(o).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):t},be=f.useMemo(()=>{if(!n)return{attributes:[],dates:[]};const e=n.primaryProfile,t=o=>o||"Not set";return{attributes:[{label:"Category",value:Aa(e)},{label:"Connection",value:e.seatScope?ea(e.seatScope):""},{label:"Provider",value:e.provider||""},{label:"Model",value:e.model||""}].map(o=>({...o,value:t(o.value)})),dates:[{label:"Status",value:e.archivedAt?"Retired":"Active"},{label:"Recruited",value:M(e.createdAt)},{label:"Last updated",value:M(e.updatedAt)},{label:"Last active",value:M(e.lastActiveAt)}].map(o=>({...o,value:t(o.value)}))}},[n]),qe=!!n&&n.profiles.length>1,E=!!n&&!L(n.primaryProfile)&&!!W(n.primaryProfile),Ne=A&&$&&!T,J=A?we(Y):Oe,ee=Ne?"Log into account for Cloud AI Profiles":J?`${J.used}/${J.limit===null?"Unlimited":J.limit}`:null,ae=!!oe;return a.jsxs("section",{className:`${r.agentsModuleRoot} ${ae?r.agentsModuleWithTray:""} ${ae&&Z?r.agentsModuleTrayOpen:""}`.trim(),children:[ae&&a.jsxs("aside",{className:`${r.agentTrayPanel} ${Z?r.agentTrayPanelOpen:""}`.trim(),"aria-label":"AI Profile MCP settings tray","aria-hidden":!Z,children:[a.jsxs("div",{className:r.agentTrayHeader,children:[a.jsxs("span",{className:r.agentTrayTitle,children:[a.jsx(ca,{size:14}),"MCP Settings"]}),a.jsx("button",{type:"button",className:"tf-control-icon",onClick:$e,title:"Collapse AI Profile tray","aria-label":"Collapse AI Profile tray",children:a.jsx(da,{size:16})})]}),a.jsx("div",{className:`${r.agentTrayContent} tf-scrollbar tf-scrollbar--track-transparent`,children:a.jsx("div",{className:r.agentTrayContentInner,children:oe})})]}),a.jsx("div",{className:r.agentsModuleContent,children:a.jsxs("div",{className:r.aiProfilesExplorer,children:[a.jsxs("aside",{className:r.aiProfilesRosterPanel,"aria-label":"AI profile roster",children:[a.jsx("div",{className:r.taskforceAgentRosterHeader,children:a.jsxs("span",{className:r.taskforceAgentRosterTitle,children:[a.jsx(fa,{size:14}),"AI Profiles"]})}),ee&&a.jsx("div",{className:r.aiProfilesRosterSummary,children:a.jsx("div",{className:r.aiProfileSeatSummary,children:Ne?ee:`Registered Cloud AI Profiles: ${ee}`})}),Ge?a.jsxs("div",{className:r.aiProfilesRosterState,role:"status","aria-live":"polite",children:[a.jsx(ua,{size:13,className:r.spinner})," Loading profiles…"]}):N.length===0?a.jsx("div",{className:r.aiProfilesRosterState,children:"No AI profiles registered yet."}):H.length>0?a.jsx("div",{className:`${r.aiProfilesListPane} tf-scrollbar tf-scrollbar--track-transparent tf-tray-scroll-viewport`,children:a.jsx("div",{className:r.aiProfilesList,children:H.map(e=>a.jsxs("div",{className:r.aiProfilesSection,children:[a.jsx("div",{className:r.aiProfilesSectionHeader,children:e.label}),e.groups.map(t=>{const o=n?.groupId===t.groupId,s=t.primaryProfile,d=!L(s)&&!!W(s);return a.jsx(sa,{name:s.name,username:s.username,subtitle:s.role||"Role not set",selected:o,onSelect:()=>_(t.groupId),avatarVariant:d?"logo":"portrait",avatar:a.jsx(ya,{profile:s}),avatarStyle:{color:s.color},className:t.profiles.length>1?r.aiProfileGroupDuplicate:"",topUtility:De(s.seatScope),bottomUtility:a.jsx("span",{className:r.aiProfileGroupSignatureSwatch,style:{backgroundColor:s.color},title:`Signature color ${s.color}`,"aria-hidden":"true"}),footer:t.profiles.length>1?a.jsxs("span",{className:r.aiProfileDuplicateBadge,children:[a.jsx(V,{size:11})," ",Sa(t.profiles.length)]}):null},t.groupId)})]},e.section))})}):null]}),a.jsx("main",{className:`${r.aiProfilesDetailViewport} tf-scrollbar`,"aria-label":"AI profile details",children:n&&a.jsx("div",{className:r.aiProfileDetailPane,children:a.jsxs("div",{className:r.aiProfileDetailCard,children:[De(n.primaryProfile.seatScope,{variant:"detail"}),a.jsxs("div",{className:r.aiProfileDetailHero,children:[a.jsx(aa,{label:"Edit AI profile photo",imageUrl:ie(n.primaryProfile),fallbackImageUrl:W(n.primaryProfile),fallback:a.jsx(Le,{size:38}),accentColor:E?null:n.primaryProfile.color,size:176,width:E?176:153,height:E?176:207,radius:E?0:6,editBadgeSize:28,editIconSize:14,loading:R===n.primaryProfile.id,loadingLabel:`Generating ${n.primaryProfile.name} photo`,error:!!Se?.error,errorLabel:Se?.error||"Profile photo generation failed",className:`${r.aiProfileDetailAvatar} ${E?r.aiProfileDetailAvatarLogo:""}`.trim(),onClick:()=>{P(null),x(null),fe(n.primaryProfile.id)}}),a.jsxs("div",{className:r.aiProfileDetailHeading,children:[a.jsx("div",{className:r.aiProfileDetailTitleRow,children:a.jsx("h5",{className:r.aiProfileDetailTitle,children:n.primaryProfile.name})}),a.jsxs("div",{className:r.aiProfileDetailMetaRow,children:[a.jsxs("span",{className:r.aiProfileDetailHandle,children:["@",n.primaryProfile.username]}),n.profiles.length>1&&a.jsxs("span",{className:r.aiProfileDetailLinkedCount,children:[n.profiles.length," linked"]})]}),a.jsxs("div",{className:r.aiProfileDetailRole,children:["Role: ",n.primaryProfile.role||"Not set"]}),n.primaryProfile.description&&a.jsx("div",{className:r.aiProfileDetailDescription,children:n.primaryProfile.description}),a.jsxs("div",{className:r.aiProfileSignatureColor,children:[a.jsx("span",{children:"Signature color"}),a.jsxs("button",{type:"button",className:r.aiProfileSignatureColorButton,onClick:()=>ge(e=>!e),disabled:q,"aria-expanded":ve,"aria-label":"Change signature color",children:[a.jsx("span",{className:r.aiProfileSignatureSwatch,style:{backgroundColor:n.primaryProfile.color},"aria-hidden":"true"}),a.jsx("span",{children:n.primaryProfile.color})]})]}),ve&&a.jsxs("div",{className:r.aiProfileColorPicker,"aria-label":"Signature color options",children:[na.map(({name:e,value:t})=>a.jsx("button",{type:"button",className:r.aiProfileColorOption,style:{backgroundColor:t},"aria-label":`Use ${e}`,"aria-pressed":n.primaryProfile.color.toLowerCase()===t.toLowerCase(),disabled:q,onClick:()=>{Ie(n,t)}},t)),a.jsx("button",{type:"button",className:r.secondaryHeaderBtn,disabled:q,onClick:()=>{Ie(n,void 0,!0)},children:"Reset"})]}),ye&&a.jsx("div",{className:r.aiProfileInlineError,children:ye})]})]}),a.jsxs("div",{className:r.aiProfileDetailDataList,children:[a.jsx("div",{className:r.aiProfileDetailDataGroup,children:be.attributes.map(e=>a.jsxs("div",{className:r.aiProfileDetailDataRow,children:[a.jsx("span",{className:r.aiProfileDetailDataLabel,children:e.label}),e.label==="Category"&&!le(n.primaryProfile)?a.jsx("span",{className:r.aiProfileDetailDataValue,children:a.jsxs("select",{className:r.aiProfileStatusSelect,"aria-label":"Agent category",value:n.primaryProfile.surfaceType??"",disabled:_e,onChange:t=>{Ve(n,t.target.value)},children:[a.jsx("option",{value:"",children:"Unclassified"}),ra.map(t=>a.jsx("option",{value:t,children:Re(t)},t))]})}):a.jsx("span",{className:r.aiProfileDetailDataValue,children:e.value})]},e.label))}),a.jsx("div",{className:`${r.aiProfileDetailDataGroup} ${r.aiProfileDetailDateGroup}`,children:be.dates.map(e=>a.jsxs("div",{className:r.aiProfileDetailDataRow,children:[a.jsx("span",{className:r.aiProfileDetailDataLabel,children:e.label}),e.label==="Status"?a.jsx("span",{className:r.aiProfileDetailDataValue,children:a.jsxs("select",{className:r.aiProfileStatusSelect,"aria-label":"Agent roster status",value:n.primaryProfile.archivedAt?"retired":"active",onChange:t=>{t.target.value==="retire"&&xe(n.primaryProfile)},children:[a.jsx("option",{value:"active",children:"Active"}),n.primaryProfile.archivedAt?a.jsx("option",{value:"retired",children:"Retired"}):a.jsx("option",{value:"retire",children:"Retire from roster"})]})}):a.jsx("span",{className:r.aiProfileDetailDataValue,children:e.value})]},e.label))})]}),ne?.profileId===n.primaryProfile.id&&a.jsxs("div",{className:r.aiProfileInlineError,role:"alert",children:[a.jsx(V,{size:12}),a.jsx("span",{children:ne.message})]}),qe?a.jsxs("div",{className:r.aiProfileInstanceSection,children:[a.jsxs("div",{className:r.aiProfileInstanceSectionHeader,children:[a.jsx("span",{children:"Profile instances"}),a.jsx("span",{className:r.settingsHint,children:"Choose a keeper here if duplicates need to be merged."})]}),a.jsx("div",{className:r.aiProfileInstanceList,children:n.profiles.map(e=>a.jsxs("div",{className:r.aiProfileInstanceCard,children:[a.jsxs("div",{className:r.aiProfileInstanceTopRow,children:[a.jsxs("div",{children:[a.jsxs("div",{className:r.aiProfileInstanceName,children:["@",e.username]}),a.jsx("div",{className:r.aiProfileIdChip,children:e.id})]}),S?.keepId===e.id&&a.jsx("span",{className:r.aiProfileKeepBadge,children:"Keeping"})]}),a.jsxs("div",{className:r.aiProfileInstanceMeta,children:[a.jsxs("span",{children:["Created ",M(e.createdAt)]}),a.jsxs("span",{children:["Updated ",M(e.updatedAt)]})]}),S?.keepId!==e.id&&a.jsx("button",{className:r.secondaryHeaderBtn,title:"Keep this profile, merge others into it",onClick:()=>{const t=n.profiles.find(o=>o.id!==e.id)?.id;t&&F({keepId:e.id,mergeId:t})},children:"Keep this"}),G?.profileId===e.id&&a.jsxs("div",{className:r.aiProfileInlineError,role:"alert",children:[a.jsx(V,{size:12}),a.jsx("span",{children:G.message})]}),a.jsx("button",{className:r.aiProfileDangerTextButton,title:"Remove this profile from the active roster",onClick:()=>{xe(e)},children:"Remove from roster"})]},e.id))}),S&&n.profiles.some(e=>e.id===S.keepId)&&a.jsxs("div",{className:r.aiProfileMergeActions,children:[a.jsx("button",{className:r.dangerBtn,onClick:()=>{Je(S.keepId,S.mergeId)},children:"Merge duplicates"}),a.jsx("button",{className:r.secondaryHeaderBtn,onClick:()=>F(null),children:"Cancel"})]})]}):a.jsxs("div",{className:r.aiProfileIdFooter,children:[a.jsx("div",{className:r.aiProfileIdFooterValue,children:n.primaryProfile.id}),G?.profileId===n.primaryProfile.id&&a.jsxs("div",{className:r.aiProfileInlineError,role:"alert",children:[a.jsx(V,{size:12}),a.jsx("span",{children:G.message})]})]})]})})})]})}),a.jsx(ta,{isOpen:!!p,theme:Be,title:"Edit AI Profile Photo",currentImageUrl:ie(p),editorImageUrl:ga(p),fallbackInitial:(p?.name||"AI").charAt(0).toUpperCase(),accept:"image/png,image/jpeg,image/webp,image/gif",busy:ue,generating:R===p?.id,generateLabel:p&&L(p)?"Regenerate":"Generate",hasPendingImage:!1,canRemove:!!p?.avatarUrl,error:ze||Ae?.error||null,notice:He||Ae?.notice||null,onClose:()=>{ue||(fe(null),P(null),x(null))},onApplyImage:Ze,onGenerateImage:p&&(!R||R===p.id)&&(ia(p)||te(p))?()=>Ye(p):void 0,onRemoveImage:Xe},p?.id||"ai-profile-avatar-closed")]})}export{Ca as AiProfilesModule};
@@ -1,3 +1,3 @@
1
- import{j as t,r as s,R as aa}from"./vendor-react-CKJs5o3c.js";import{u as As,a as zn,D as Es,c as Ms,S as Ps,v as Bs,C as Fs,f as Hs,s as Ds,K as Os,P as Us,d as Gs}from"./vendor-dnd-CJ-AjP-Y.js";import{R as Ks,f as ce,h as na,i as Vs,t as Sn,M as sa}from"./index-I5zhdtgt.js";import{s as Ws,A as Ys}from"./AssetTraySortControl-C8Rztyal.js";import{aE as Cn,ak as qs,S as Xs,a5 as Js,V as Zs,q as Qs,t as er,ah as Ea,r as Nn,a6 as tr,w as jn,aP as ar,R as nr,aQ as sr,aR as rr,aS as or,aT as ir,aU as Ba,C as Fa,aV as lr,aW as Fn,aX as Hn,aY as Dn,aZ as On,u as Ha,Q as Tn}from"./vendor-icons-D9Lpw-j4.js";import"./vendor-markdown-_lhNCyq-.js";import"./vendor-router-AqJMU8Lz.js";function cr({copied:r,disabled:l=!1,label:p,onClick:g,title:v="Copy image reference",ariaLabel:_,className:F=""}){return t.jsx(Ks,{copied:r,disabled:l,label:"",onClick:g,title:v,ariaLabel:_,className:F,children:p})}const dr="_shell_5pzz0_1",ur="_shellWithImageTray_5pzz0_18",mr="_shellImageTrayOpen_5pzz0_22",fr="_imageTrayPanel_5pzz0_26",pr="_imageTrayPanelOpen_5pzz0_50",hr="_imageTrayHeader_5pzz0_58",gr="_imageTrayTitle_5pzz0_73",yr="_imageTraySearch_5pzz0_85",br="_imageTraySearchIcon_5pzz0_91",xr="_imageTraySearchInput_5pzz0_100",vr="_imageTraySortControlRow_5pzz0_117",_r="_imageTrayList_5pzz0_124",kr="_imageTrayState_5pzz0_136",wr="_imageTrayStateError_5pzz0_137",Ir="_imageTrayItem_5pzz0_149",zr="_imageTrayItemActive_5pzz0_171",Sr="_imageTrayThumb_5pzz0_181",Cr="_imageTrayItemBody_5pzz0_198",Nr="_imageTrayItemTitle_5pzz0_206",jr="_imageTrayItemTask_5pzz0_207",Tr="_imageTrayItemMetaDetails_5pzz0_208",$r="_imageTrayItemMeta_5pzz0_208",Lr="_imageTrayItemReference_5pzz0_246",Rr="_panel_5pzz0_253",Ar="_sessionPanel_5pzz0_259",Er="_detailPanel_5pzz0_260",Mr="_sessionContextBar_5pzz0_266",Pr="_sessionContextLeft_5pzz0_277",Br="_sessionContextRight_5pzz0_278",Fr="_sessionContextLabel_5pzz0_293",Hr="_sessionContextSpacer_5pzz0_299",Dr="_canvasPanel_5pzz0_304",Or="_canvasWorkspace_5pzz0_311",Ur="_canvasMain_5pzz0_318",Gr="_panelHeader_5pzz0_325",Kr="_panelHeaderText_5pzz0_334",Vr="_panelTitle_5pzz0_338",Wr="_canvasHeading_5pzz0_342",Yr="_sessionActions_5pzz0_346",qr="_taskLinkModalBody_5pzz0_354",Xr="_taskLinkList_5pzz0_364",Jr="_taskLinkOption_5pzz0_372",Zr="_taskLinkOptionActive_5pzz0_387",Qr="_taskLinkOptionTitle_5pzz0_395",eo="_taskLinkActions_5pzz0_399",to="_sessionList_5pzz0_405",ao="_annotationList_5pzz0_406",no="_markerHelpModalBody_5pzz0_416",so="_openImageModalBody_5pzz0_422",ro="_openImageField_5pzz0_428",oo="_openImageActions_5pzz0_432",io="_markerHelpItem_5pzz0_438",lo="_markerHelpHeader_5pzz0_446",co="_markerHelpExample_5pzz0_458",uo="_sessionCard_5pzz0_462",mo="_annotationCard_5pzz0_463",fo="_sessionEmptyState_5pzz0_477",po="_sessionCardButton_5pzz0_484",ho="_annotationCardButton_5pzz0_494",go="_sessionCardBody_5pzz0_506",yo="_sessionCardActive_5pzz0_512",bo="_annotationCardActive_5pzz0_513",xo="_annotationCardHovered_5pzz0_518",vo="_annotationMeta_5pzz0_533",_o="_annotationDragHandle_5pzz0_540",ko="_annotationCardDragging_5pzz0_566",wo="_annotationDragOverlay_5pzz0_570",Io="_annotationDragOverlayGrip_5pzz0_577",zo="_annotationDragOverlayTitle_5pzz0_581",So="_annotationInstructionPreview_5pzz0_587",Co="_annotationPreviewFooter_5pzz0_595",No="_annotationInstructionEditor_5pzz0_602",jo="_annotationTypeField_5pzz0_608",To="_annotationGeometryDetails_5pzz0_614",$o="_annotationGeometryFields_5pzz0_623",Lo="_annotationGeometryField_5pzz0_623",Ro="_annotationGeometryLabel_5pzz0_636",Ao="_annotationGeometryInput_5pzz0_641",Eo="_annotationInstructionButton_5pzz0_646",Mo="_annotationInstructionField_5pzz0_655",Po="_sessionMeta_5pzz0_659",Bo="_sessionTitle_5pzz0_666",Fo="_annotationTitle_5pzz0_667",Ho="_sessionTimestamp_5pzz0_673",Do="_annotationKind_5pzz0_674",Oo="_annotationInstructionTypeIcon_5pzz0_678",Uo="_sessionInstructionPreview_5pzz0_684",Go="_sessionInstructionEditor_5pzz0_692",Ko="_sessionCardFooter_5pzz0_698",Vo="_toolRail_5pzz0_705",Wo="_canvasToolRail_5pzz0_714",Yo="_toolbarCluster_5pzz0_735",qo="_toolbarViewportCluster_5pzz0_742",Xo="_toolbarSeparator_5pzz0_746",Jo="_toolBtn_5pzz0_752",Zo="_toolRailButton_5pzz0_756",Qo="_toolbarButton_5pzz0_766",ei="_toolBtnActive_5pzz0_771",ti="_toolbarActions_5pzz0_778",ai="_toolbarSelectionActions_5pzz0_787",ni="_toolbarColorPicker_5pzz0_795",si="_colorPickerButton_5pzz0_799",ri="_colorPickerSwatch_5pzz0_804",oi="_colorPickerPopover_5pzz0_812",ii="_colorOption_5pzz0_827",li="_colorOptionActive_5pzz0_837",ci="_toolbarUtilities_5pzz0_844",di="_iconButton_5pzz0_852",ui="_ghostBtn_5pzz0_857",mi="_payloadBtn_5pzz0_858",fi="_backToTaskBtn_5pzz0_859",pi="_canvasScroller_5pzz0_879",hi="_canvasFrame_5pzz0_895",gi="_canvasMedia_5pzz0_904",yi="_canvasStatusOverlay_5pzz0_912",bi="_canvasStatusCard_5pzz0_924",xi="_canvasImage_5pzz0_937",vi="_overlay_5pzz0_944",_i="_overlaySelect_5pzz0_950",ki="_overlayPan_5pzz0_954",wi="_overlaySvg_5pzz0_958",Ii="_overlayHitLayer_5pzz0_967",zi="_arrowHitArea_5pzz0_976",Si="_canvasHandleHit_5pzz0_983",Ci="_canvasResizeHandleHit_5pzz0_990",Ni="_canvasHandleVisible_5pzz0_994",ji="_pin_5pzz0_1011",Ti="_note_5pzz0_1012",$i="_markerHovered_5pzz0_1029",Li="_annotationNumberBadge_5pzz0_1033",Ri="_box_5pzz0_1058",Ai="_boxNumberBadge_5pzz0_1067",Ei="_arrowNumberBadge_5pzz0_1073",Mi="_boxSurface_5pzz0_1077",Pi="_selected_5pzz0_1090",Bi="_textInput_5pzz0_1107",Fi="_textArea_5pzz0_1108",Hi="_select_5pzz0_1090",Di="_sessionTitleInput_5pzz0_1117",Oi="_sessionInstructionField_5pzz0_1122",Ui="_detailEmpty_5pzz0_1131",Gi="_emptyState_5pzz0_1132",Ki="_payloadModalBody_5pzz0_1144",Vi="_payloadModalToolbar_5pzz0_1151",Wi="_payloadViewToggle_5pzz0_1158",Yi="_payloadModalActions_5pzz0_1159",qi="_payloadModalPreview_5pzz0_1166",Xi="_statusBar_5pzz0_1181",Ji="_annotationSummary_5pzz0_1193",a={shell:dr,shellWithImageTray:ur,shellImageTrayOpen:mr,imageTrayPanel:fr,imageTrayPanelOpen:pr,imageTrayHeader:hr,imageTrayTitle:gr,imageTraySearch:yr,imageTraySearchIcon:br,imageTraySearchInput:xr,imageTraySortControlRow:vr,imageTrayList:_r,imageTrayState:kr,imageTrayStateError:wr,imageTrayItem:Ir,imageTrayItemActive:zr,imageTrayThumb:Sr,imageTrayItemBody:Cr,imageTrayItemTitle:Nr,imageTrayItemTask:jr,imageTrayItemMetaDetails:Tr,imageTrayItemMeta:$r,imageTrayItemReference:Lr,panel:Rr,sessionPanel:Ar,detailPanel:Er,sessionContextBar:Mr,sessionContextLeft:Pr,sessionContextRight:Br,sessionContextLabel:Fr,sessionContextSpacer:Hr,canvasPanel:Dr,canvasWorkspace:Or,canvasMain:Ur,panelHeader:Gr,panelHeaderText:Kr,panelTitle:Vr,canvasHeading:Wr,sessionActions:Yr,taskLinkModalBody:qr,taskLinkList:Xr,taskLinkOption:Jr,taskLinkOptionActive:Zr,taskLinkOptionTitle:Qr,taskLinkActions:eo,sessionList:to,annotationList:ao,markerHelpModalBody:no,openImageModalBody:so,openImageField:ro,openImageActions:oo,markerHelpItem:io,markerHelpHeader:lo,markerHelpExample:co,sessionCard:uo,annotationCard:mo,sessionEmptyState:fo,sessionCardButton:po,annotationCardButton:ho,sessionCardBody:go,sessionCardActive:yo,annotationCardActive:bo,annotationCardHovered:xo,annotationMeta:vo,annotationDragHandle:_o,annotationCardDragging:ko,annotationDragOverlay:wo,annotationDragOverlayGrip:Io,annotationDragOverlayTitle:zo,annotationInstructionPreview:So,annotationPreviewFooter:Co,annotationInstructionEditor:No,annotationTypeField:jo,annotationGeometryDetails:To,annotationGeometryFields:$o,annotationGeometryField:Lo,annotationGeometryLabel:Ro,annotationGeometryInput:Ao,annotationInstructionButton:Eo,annotationInstructionField:Mo,sessionMeta:Po,sessionTitle:Bo,annotationTitle:Fo,sessionTimestamp:Ho,annotationKind:Do,annotationInstructionTypeIcon:Oo,sessionInstructionPreview:Uo,sessionInstructionEditor:Go,sessionCardFooter:Ko,toolRail:Vo,canvasToolRail:Wo,toolbarCluster:Yo,toolbarViewportCluster:qo,toolbarSeparator:Xo,toolBtn:Jo,toolRailButton:Zo,toolbarButton:Qo,toolBtnActive:ei,toolbarActions:ti,toolbarSelectionActions:ai,toolbarColorPicker:ni,colorPickerButton:si,colorPickerSwatch:ri,colorPickerPopover:oi,colorOption:ii,colorOptionActive:li,toolbarUtilities:ci,iconButton:di,ghostBtn:ui,payloadBtn:mi,backToTaskBtn:fi,canvasScroller:pi,canvasFrame:hi,canvasMedia:gi,canvasStatusOverlay:yi,canvasStatusCard:bi,canvasImage:xi,overlay:vi,overlaySelect:_i,overlayPan:ki,overlaySvg:wi,overlayHitLayer:Ii,arrowHitArea:zi,canvasHandleHit:Si,canvasResizeHandleHit:Ci,canvasHandleVisible:Ni,pin:ji,note:Ti,markerHovered:$i,annotationNumberBadge:Li,box:Ri,boxNumberBadge:Ai,arrowNumberBadge:Ei,boxSurface:Mi,selected:Pi,textInput:Bi,textArea:Fi,select:Hi,sessionTitleInput:Di,sessionInstructionField:Oi,detailEmpty:Ui,emptyState:Gi,payloadModalBody:Ki,payloadModalToolbar:Vi,payloadViewToggle:Wi,payloadModalActions:Yi,payloadModalPreview:qi,statusBar:Xi,annotationSummary:Ji};function Zi({id:r,children:l}){return t.jsx(t.Fragment,{children:l(Gs({id:r}))})}const $n=[{value:"review",label:"Review"},{value:"change",label:"Change"},{value:"question",label:"Question"}],Ln=[{value:"select",label:"Select",icon:lr},{value:"pin",label:"Pin",icon:Fn},{value:"box",label:"Box",icon:Hn},{value:"arrow",label:"Arrow",icon:Dn},{value:"text-note",label:"Note",icon:On}],Qi=200,Rn={pin:Fn,box:Hn,arrow:Dn,"text-note":On},An={pin:"Pin",box:"Box",arrow:"Arrow","text-note":"Note"},el={review:Ba,change:Ha,question:Fa,issue:Fa,idea:Ba},ra={select:{short:"Select and edit existing markers.",detail:"Use Select to click, drag, reorder, resize, and update markers that are already on the image.",example:"Example: move an existing marker after the screenshot changes."},pin:{short:"Mark a precise spot.",detail:"Use Pin when feedback points to one exact location instead of a broader area.",example:'Example: "This icon is misaligned by 2px."'},box:{short:"Mark an area or component.",detail:"Use Box when the feedback applies to a whole region, card, panel, or bounded UI block.",example:'Example: "This whole card needs tighter padding and a stronger border."'},arrow:{short:"Show direction or relationship.",detail:"Use Arrow when you need to show movement, attachment, flow, or source-to-target intent.",example:'Example: "This tooltip should anchor to this button, not the panel."'},"text-note":{short:"Add a comment-style point marker.",detail:"Use Note when you want a point marker that reads more like a comment or open question.",example:'Example: "Ask design whether this badge should stay."'}},Tt={question:"#0f766e",change:"#2563eb",issue:"#dc2626",idea:"#d97706",review:"#7c3aed"},tl=["#7c3aed","#2563eb","#0f766e","#dc2626","#d97706","#111827"],ye="review";function tt(r){const l=String(r.displayName||"").trim();return l?`${l} review`:"Annotated session"}function Un(){return`annotation-${Math.random().toString(36).slice(2,10)}`}function I(r){return!Number.isFinite(r)||r<=0?0:r>=1?1:r}function Ee(r){return I(Math.max(.02,r))}function Re(r){return r?[String(r.taskId||"").trim(),String(r.assetId||"").trim(),String(r.path||"").trim()].join("::"):""}function Gn(r){if(!(r instanceof HTMLElement))return!1;const l=r.tagName.toLowerCase();return r.isContentEditable?!0:l==="input"||l==="textarea"||l==="select"}function al(r){if(!(r instanceof HTMLElement))return!1;if(Gn(r))return!0;const l=r.tagName.toLowerCase();return l==="button"||l==="a"||r.getAttribute("role")==="button"}function Ae(r){return r.map((l,p)=>({...l,order:p}))}function Ma(r){if(!r)return"Unsaved";const l=new Date(r);return Number.isNaN(l.getTime())?"Unsaved":l.toLocaleString()}function nl(r){const l=typeof r=="number"&&Number.isFinite(r)?Math.max(0,r):0;return l<1024?`${l}B`:l<1024*1024?`${(l/1024).toFixed(1)}KB`:`${(l/(1024*1024)).toFixed(1)}MB`}function sl(r){if(!r)return"";const l=new Date(r);if(Number.isNaN(l.getTime()))return"";const g=new Date().getTime()-l.getTime(),v=Math.floor(g/(1e3*60*60*24));return v<=0?"Today":v===1?"Yesterday":v<7?`${v}d ago`:v<30?`${Math.floor(v/7)}w ago`:l.toLocaleDateString()}function oa(r){const l=String(r.createdByActor?.label||"").trim();return l||null}function rl(r){const l=String(r||"").trim().replace(/\s+/g," ");return l?l.length>110?`${l.slice(0,107)}...`:l:""}function En(r,l,p,g=Tt[ye]){const v={id:Un(),order:0,instruction:"",markerType:ye,color:g};if(r==="pin")return{...v,kind:r,x:l.x,y:l.y};if(r==="text-note")return{...v,kind:r,x:l.x,y:l.y};if(r==="box"){const F=p||l;return{...v,kind:r,x:I(Math.min(l.x,F.x)),y:I(Math.min(l.y,F.y)),width:Ee(Math.abs(F.x-l.x)),height:Ee(Math.abs(F.y-l.y))}}const _=p||l;return{...v,kind:"arrow",x:l.x,y:l.y,x2:_.x,y2:_.y}}function ia(r){return r.color?r.color:Tt[r.markerType||ye]}function ol(r,l){const p=Math.max(l.width,1),g=Math.max(l.height,1),v=r.x*p,_=r.y*g,F=r.x2*p,ue=r.y2*g,me=F-v,$t=ue-_,be=Math.hypot(me,$t)||1,at=me/be,Me=$t/be,G=Math.max(10,Math.min(16,be-2)),Se=G*.62,nt=F-at*G,Ce=ue-Me*G,st=-Me,T=at;return{shaftX1:v,shaftY1:_,shaftX2:nt,shaftY2:Ce,headPoints:[`${F},${ue}`,`${nt+st*Se},${Ce+T*Se}`,`${nt-st*Se},${Ce-T*Se}`].join(" ")}}function il(r,l){return{...r,markerType:l,color:r.color||Tt[l]}}function ll(r,l){return{...r,id:Un(),order:l}}function cl(r,l){const p=String(r||"").trim()||(l?tt(l):"Annotated session");return/\bcopy$/i.test(p)?`${p} 2`:`${p} copy`}function dl(r,l,p){if(l===p||l<0||p<0||l>=r.length||p>=r.length)return r;const g=[...r],[v]=g.splice(l,1);return v?(g.splice(p,0,v),Ae(g)):r}function de(r){return String(Math.round(I(r)*1e3)/10)}function ul(r){const l=Number.parseFloat(r);return Number.isFinite(l)?I(l/100):null}function ml(r,l,p){return r.kind==="pin"||r.kind==="text-note"?l==="x"||l==="y"?{...r,[l]:I(p)}:r:r.kind==="box"?l==="x"||l==="y"?{...r,[l]:I(p)}:l==="width"||l==="height"?{...r,[l]:Ee(p)}:r:l==="x"||l==="y"||l==="x2"||l==="y2"?{...r,[l]:I(p)}:r}function fl(r){return r.kind==="pin"||r.kind==="text-note"?[{key:"x",label:"X",value:de(r.x)},{key:"y",label:"Y",value:de(r.y)}]:r.kind==="box"?[{key:"x",label:"X",value:de(r.x)},{key:"y",label:"Y",value:de(r.y)},{key:"width",label:"Width",value:de(r.width)},{key:"height",label:"Height",value:de(r.height)}]:[{key:"x",label:"Start X",value:de(r.x)},{key:"y",label:"Start Y",value:de(r.y)},{key:"x2",label:"End X",value:de(r.x2)},{key:"y2",label:"End Y",value:de(r.y2)}]}function pl(r){if(!r)return null;const l=Math.round(r.x*100),p=Math.round(r.y*100),g=Math.round(r.width*100),v=Math.round(r.height*100);return`crop ${l}%, ${p}% size ${g}% x ${v}%`}function Pa(r){return Number.isFinite(r)?Math.min(4,Math.max(.25,Number(r.toFixed(2)))):1}function Mn(r){const l=[`Annotated attachment: ${r.title||r.image.displayName}`,`Image: ${r.image.displayName}`,`Image Reference: ${r.image.referenceLabel||r.image.assetId}`,`Task ID: ${r.taskId}`,r.globalInstruction?`Global instruction: ${r.globalInstruction}`:"Global instruction: None provided.","Markers:"];return r.annotations.length===0?(l.push("0. No markers."),l.join(`
1
+ import{j as t,r as s,R as aa}from"./vendor-react-CKJs5o3c.js";import{u as As,a as zn,D as Es,c as Ms,S as Ps,v as Bs,C as Fs,f as Hs,s as Ds,K as Os,P as Us,d as Gs}from"./vendor-dnd-CJ-AjP-Y.js";import{R as Ks,f as ce,h as na,i as Vs,t as Sn,M as sa}from"./index-DSQINwt9.js";import{s as Ws,A as Ys}from"./AssetTraySortControl-CKgapnxu.js";import{aE as Cn,ak as qs,S as Xs,a5 as Js,V as Zs,q as Qs,t as er,ah as Ea,r as Nn,a6 as tr,w as jn,aP as ar,R as nr,aQ as sr,aR as rr,aS as or,aT as ir,aU as Ba,C as Fa,aV as lr,aW as Fn,aX as Hn,aY as Dn,aZ as On,u as Ha,Q as Tn}from"./vendor-icons-Bsq-mcEn.js";import"./vendor-markdown-_lhNCyq-.js";import"./vendor-router-AqJMU8Lz.js";function cr({copied:r,disabled:l=!1,label:p,onClick:g,title:v="Copy image reference",ariaLabel:_,className:F=""}){return t.jsx(Ks,{copied:r,disabled:l,label:"",onClick:g,title:v,ariaLabel:_,className:F,children:p})}const dr="_shell_5pzz0_1",ur="_shellWithImageTray_5pzz0_18",mr="_shellImageTrayOpen_5pzz0_22",fr="_imageTrayPanel_5pzz0_26",pr="_imageTrayPanelOpen_5pzz0_50",hr="_imageTrayHeader_5pzz0_58",gr="_imageTrayTitle_5pzz0_73",yr="_imageTraySearch_5pzz0_85",br="_imageTraySearchIcon_5pzz0_91",xr="_imageTraySearchInput_5pzz0_100",vr="_imageTraySortControlRow_5pzz0_117",_r="_imageTrayList_5pzz0_124",kr="_imageTrayState_5pzz0_136",wr="_imageTrayStateError_5pzz0_137",Ir="_imageTrayItem_5pzz0_149",zr="_imageTrayItemActive_5pzz0_171",Sr="_imageTrayThumb_5pzz0_181",Cr="_imageTrayItemBody_5pzz0_198",Nr="_imageTrayItemTitle_5pzz0_206",jr="_imageTrayItemTask_5pzz0_207",Tr="_imageTrayItemMetaDetails_5pzz0_208",$r="_imageTrayItemMeta_5pzz0_208",Lr="_imageTrayItemReference_5pzz0_246",Rr="_panel_5pzz0_253",Ar="_sessionPanel_5pzz0_259",Er="_detailPanel_5pzz0_260",Mr="_sessionContextBar_5pzz0_266",Pr="_sessionContextLeft_5pzz0_277",Br="_sessionContextRight_5pzz0_278",Fr="_sessionContextLabel_5pzz0_293",Hr="_sessionContextSpacer_5pzz0_299",Dr="_canvasPanel_5pzz0_304",Or="_canvasWorkspace_5pzz0_311",Ur="_canvasMain_5pzz0_318",Gr="_panelHeader_5pzz0_325",Kr="_panelHeaderText_5pzz0_334",Vr="_panelTitle_5pzz0_338",Wr="_canvasHeading_5pzz0_342",Yr="_sessionActions_5pzz0_346",qr="_taskLinkModalBody_5pzz0_354",Xr="_taskLinkList_5pzz0_364",Jr="_taskLinkOption_5pzz0_372",Zr="_taskLinkOptionActive_5pzz0_387",Qr="_taskLinkOptionTitle_5pzz0_395",eo="_taskLinkActions_5pzz0_399",to="_sessionList_5pzz0_405",ao="_annotationList_5pzz0_406",no="_markerHelpModalBody_5pzz0_416",so="_openImageModalBody_5pzz0_422",ro="_openImageField_5pzz0_428",oo="_openImageActions_5pzz0_432",io="_markerHelpItem_5pzz0_438",lo="_markerHelpHeader_5pzz0_446",co="_markerHelpExample_5pzz0_458",uo="_sessionCard_5pzz0_462",mo="_annotationCard_5pzz0_463",fo="_sessionEmptyState_5pzz0_477",po="_sessionCardButton_5pzz0_484",ho="_annotationCardButton_5pzz0_494",go="_sessionCardBody_5pzz0_506",yo="_sessionCardActive_5pzz0_512",bo="_annotationCardActive_5pzz0_513",xo="_annotationCardHovered_5pzz0_518",vo="_annotationMeta_5pzz0_533",_o="_annotationDragHandle_5pzz0_540",ko="_annotationCardDragging_5pzz0_566",wo="_annotationDragOverlay_5pzz0_570",Io="_annotationDragOverlayGrip_5pzz0_577",zo="_annotationDragOverlayTitle_5pzz0_581",So="_annotationInstructionPreview_5pzz0_587",Co="_annotationPreviewFooter_5pzz0_595",No="_annotationInstructionEditor_5pzz0_602",jo="_annotationTypeField_5pzz0_608",To="_annotationGeometryDetails_5pzz0_614",$o="_annotationGeometryFields_5pzz0_623",Lo="_annotationGeometryField_5pzz0_623",Ro="_annotationGeometryLabel_5pzz0_636",Ao="_annotationGeometryInput_5pzz0_641",Eo="_annotationInstructionButton_5pzz0_646",Mo="_annotationInstructionField_5pzz0_655",Po="_sessionMeta_5pzz0_659",Bo="_sessionTitle_5pzz0_666",Fo="_annotationTitle_5pzz0_667",Ho="_sessionTimestamp_5pzz0_673",Do="_annotationKind_5pzz0_674",Oo="_annotationInstructionTypeIcon_5pzz0_678",Uo="_sessionInstructionPreview_5pzz0_684",Go="_sessionInstructionEditor_5pzz0_692",Ko="_sessionCardFooter_5pzz0_698",Vo="_toolRail_5pzz0_705",Wo="_canvasToolRail_5pzz0_714",Yo="_toolbarCluster_5pzz0_735",qo="_toolbarViewportCluster_5pzz0_742",Xo="_toolbarSeparator_5pzz0_746",Jo="_toolBtn_5pzz0_752",Zo="_toolRailButton_5pzz0_756",Qo="_toolbarButton_5pzz0_766",ei="_toolBtnActive_5pzz0_771",ti="_toolbarActions_5pzz0_778",ai="_toolbarSelectionActions_5pzz0_787",ni="_toolbarColorPicker_5pzz0_795",si="_colorPickerButton_5pzz0_799",ri="_colorPickerSwatch_5pzz0_804",oi="_colorPickerPopover_5pzz0_812",ii="_colorOption_5pzz0_827",li="_colorOptionActive_5pzz0_837",ci="_toolbarUtilities_5pzz0_844",di="_iconButton_5pzz0_852",ui="_ghostBtn_5pzz0_857",mi="_payloadBtn_5pzz0_858",fi="_backToTaskBtn_5pzz0_859",pi="_canvasScroller_5pzz0_879",hi="_canvasFrame_5pzz0_895",gi="_canvasMedia_5pzz0_904",yi="_canvasStatusOverlay_5pzz0_912",bi="_canvasStatusCard_5pzz0_924",xi="_canvasImage_5pzz0_937",vi="_overlay_5pzz0_944",_i="_overlaySelect_5pzz0_950",ki="_overlayPan_5pzz0_954",wi="_overlaySvg_5pzz0_958",Ii="_overlayHitLayer_5pzz0_967",zi="_arrowHitArea_5pzz0_976",Si="_canvasHandleHit_5pzz0_983",Ci="_canvasResizeHandleHit_5pzz0_990",Ni="_canvasHandleVisible_5pzz0_994",ji="_pin_5pzz0_1011",Ti="_note_5pzz0_1012",$i="_markerHovered_5pzz0_1029",Li="_annotationNumberBadge_5pzz0_1033",Ri="_box_5pzz0_1058",Ai="_boxNumberBadge_5pzz0_1067",Ei="_arrowNumberBadge_5pzz0_1073",Mi="_boxSurface_5pzz0_1077",Pi="_selected_5pzz0_1090",Bi="_textInput_5pzz0_1107",Fi="_textArea_5pzz0_1108",Hi="_select_5pzz0_1090",Di="_sessionTitleInput_5pzz0_1117",Oi="_sessionInstructionField_5pzz0_1122",Ui="_detailEmpty_5pzz0_1131",Gi="_emptyState_5pzz0_1132",Ki="_payloadModalBody_5pzz0_1144",Vi="_payloadModalToolbar_5pzz0_1151",Wi="_payloadViewToggle_5pzz0_1158",Yi="_payloadModalActions_5pzz0_1159",qi="_payloadModalPreview_5pzz0_1166",Xi="_statusBar_5pzz0_1181",Ji="_annotationSummary_5pzz0_1193",a={shell:dr,shellWithImageTray:ur,shellImageTrayOpen:mr,imageTrayPanel:fr,imageTrayPanelOpen:pr,imageTrayHeader:hr,imageTrayTitle:gr,imageTraySearch:yr,imageTraySearchIcon:br,imageTraySearchInput:xr,imageTraySortControlRow:vr,imageTrayList:_r,imageTrayState:kr,imageTrayStateError:wr,imageTrayItem:Ir,imageTrayItemActive:zr,imageTrayThumb:Sr,imageTrayItemBody:Cr,imageTrayItemTitle:Nr,imageTrayItemTask:jr,imageTrayItemMetaDetails:Tr,imageTrayItemMeta:$r,imageTrayItemReference:Lr,panel:Rr,sessionPanel:Ar,detailPanel:Er,sessionContextBar:Mr,sessionContextLeft:Pr,sessionContextRight:Br,sessionContextLabel:Fr,sessionContextSpacer:Hr,canvasPanel:Dr,canvasWorkspace:Or,canvasMain:Ur,panelHeader:Gr,panelHeaderText:Kr,panelTitle:Vr,canvasHeading:Wr,sessionActions:Yr,taskLinkModalBody:qr,taskLinkList:Xr,taskLinkOption:Jr,taskLinkOptionActive:Zr,taskLinkOptionTitle:Qr,taskLinkActions:eo,sessionList:to,annotationList:ao,markerHelpModalBody:no,openImageModalBody:so,openImageField:ro,openImageActions:oo,markerHelpItem:io,markerHelpHeader:lo,markerHelpExample:co,sessionCard:uo,annotationCard:mo,sessionEmptyState:fo,sessionCardButton:po,annotationCardButton:ho,sessionCardBody:go,sessionCardActive:yo,annotationCardActive:bo,annotationCardHovered:xo,annotationMeta:vo,annotationDragHandle:_o,annotationCardDragging:ko,annotationDragOverlay:wo,annotationDragOverlayGrip:Io,annotationDragOverlayTitle:zo,annotationInstructionPreview:So,annotationPreviewFooter:Co,annotationInstructionEditor:No,annotationTypeField:jo,annotationGeometryDetails:To,annotationGeometryFields:$o,annotationGeometryField:Lo,annotationGeometryLabel:Ro,annotationGeometryInput:Ao,annotationInstructionButton:Eo,annotationInstructionField:Mo,sessionMeta:Po,sessionTitle:Bo,annotationTitle:Fo,sessionTimestamp:Ho,annotationKind:Do,annotationInstructionTypeIcon:Oo,sessionInstructionPreview:Uo,sessionInstructionEditor:Go,sessionCardFooter:Ko,toolRail:Vo,canvasToolRail:Wo,toolbarCluster:Yo,toolbarViewportCluster:qo,toolbarSeparator:Xo,toolBtn:Jo,toolRailButton:Zo,toolbarButton:Qo,toolBtnActive:ei,toolbarActions:ti,toolbarSelectionActions:ai,toolbarColorPicker:ni,colorPickerButton:si,colorPickerSwatch:ri,colorPickerPopover:oi,colorOption:ii,colorOptionActive:li,toolbarUtilities:ci,iconButton:di,ghostBtn:ui,payloadBtn:mi,backToTaskBtn:fi,canvasScroller:pi,canvasFrame:hi,canvasMedia:gi,canvasStatusOverlay:yi,canvasStatusCard:bi,canvasImage:xi,overlay:vi,overlaySelect:_i,overlayPan:ki,overlaySvg:wi,overlayHitLayer:Ii,arrowHitArea:zi,canvasHandleHit:Si,canvasResizeHandleHit:Ci,canvasHandleVisible:Ni,pin:ji,note:Ti,markerHovered:$i,annotationNumberBadge:Li,box:Ri,boxNumberBadge:Ai,arrowNumberBadge:Ei,boxSurface:Mi,selected:Pi,textInput:Bi,textArea:Fi,select:Hi,sessionTitleInput:Di,sessionInstructionField:Oi,detailEmpty:Ui,emptyState:Gi,payloadModalBody:Ki,payloadModalToolbar:Vi,payloadViewToggle:Wi,payloadModalActions:Yi,payloadModalPreview:qi,statusBar:Xi,annotationSummary:Ji};function Zi({id:r,children:l}){return t.jsx(t.Fragment,{children:l(Gs({id:r}))})}const $n=[{value:"review",label:"Review"},{value:"change",label:"Change"},{value:"question",label:"Question"}],Ln=[{value:"select",label:"Select",icon:lr},{value:"pin",label:"Pin",icon:Fn},{value:"box",label:"Box",icon:Hn},{value:"arrow",label:"Arrow",icon:Dn},{value:"text-note",label:"Note",icon:On}],Qi=200,Rn={pin:Fn,box:Hn,arrow:Dn,"text-note":On},An={pin:"Pin",box:"Box",arrow:"Arrow","text-note":"Note"},el={review:Ba,change:Ha,question:Fa,issue:Fa,idea:Ba},ra={select:{short:"Select and edit existing markers.",detail:"Use Select to click, drag, reorder, resize, and update markers that are already on the image.",example:"Example: move an existing marker after the screenshot changes."},pin:{short:"Mark a precise spot.",detail:"Use Pin when feedback points to one exact location instead of a broader area.",example:'Example: "This icon is misaligned by 2px."'},box:{short:"Mark an area or component.",detail:"Use Box when the feedback applies to a whole region, card, panel, or bounded UI block.",example:'Example: "This whole card needs tighter padding and a stronger border."'},arrow:{short:"Show direction or relationship.",detail:"Use Arrow when you need to show movement, attachment, flow, or source-to-target intent.",example:'Example: "This tooltip should anchor to this button, not the panel."'},"text-note":{short:"Add a comment-style point marker.",detail:"Use Note when you want a point marker that reads more like a comment or open question.",example:'Example: "Ask design whether this badge should stay."'}},Tt={question:"#0f766e",change:"#2563eb",issue:"#dc2626",idea:"#d97706",review:"#7c3aed"},tl=["#7c3aed","#2563eb","#0f766e","#dc2626","#d97706","#111827"],ye="review";function tt(r){const l=String(r.displayName||"").trim();return l?`${l} review`:"Annotated session"}function Un(){return`annotation-${Math.random().toString(36).slice(2,10)}`}function I(r){return!Number.isFinite(r)||r<=0?0:r>=1?1:r}function Ee(r){return I(Math.max(.02,r))}function Re(r){return r?[String(r.taskId||"").trim(),String(r.assetId||"").trim(),String(r.path||"").trim()].join("::"):""}function Gn(r){if(!(r instanceof HTMLElement))return!1;const l=r.tagName.toLowerCase();return r.isContentEditable?!0:l==="input"||l==="textarea"||l==="select"}function al(r){if(!(r instanceof HTMLElement))return!1;if(Gn(r))return!0;const l=r.tagName.toLowerCase();return l==="button"||l==="a"||r.getAttribute("role")==="button"}function Ae(r){return r.map((l,p)=>({...l,order:p}))}function Ma(r){if(!r)return"Unsaved";const l=new Date(r);return Number.isNaN(l.getTime())?"Unsaved":l.toLocaleString()}function nl(r){const l=typeof r=="number"&&Number.isFinite(r)?Math.max(0,r):0;return l<1024?`${l}B`:l<1024*1024?`${(l/1024).toFixed(1)}KB`:`${(l/(1024*1024)).toFixed(1)}MB`}function sl(r){if(!r)return"";const l=new Date(r);if(Number.isNaN(l.getTime()))return"";const g=new Date().getTime()-l.getTime(),v=Math.floor(g/(1e3*60*60*24));return v<=0?"Today":v===1?"Yesterday":v<7?`${v}d ago`:v<30?`${Math.floor(v/7)}w ago`:l.toLocaleDateString()}function oa(r){const l=String(r.createdByActor?.label||"").trim();return l||null}function rl(r){const l=String(r||"").trim().replace(/\s+/g," ");return l?l.length>110?`${l.slice(0,107)}...`:l:""}function En(r,l,p,g=Tt[ye]){const v={id:Un(),order:0,instruction:"",markerType:ye,color:g};if(r==="pin")return{...v,kind:r,x:l.x,y:l.y};if(r==="text-note")return{...v,kind:r,x:l.x,y:l.y};if(r==="box"){const F=p||l;return{...v,kind:r,x:I(Math.min(l.x,F.x)),y:I(Math.min(l.y,F.y)),width:Ee(Math.abs(F.x-l.x)),height:Ee(Math.abs(F.y-l.y))}}const _=p||l;return{...v,kind:"arrow",x:l.x,y:l.y,x2:_.x,y2:_.y}}function ia(r){return r.color?r.color:Tt[r.markerType||ye]}function ol(r,l){const p=Math.max(l.width,1),g=Math.max(l.height,1),v=r.x*p,_=r.y*g,F=r.x2*p,ue=r.y2*g,me=F-v,$t=ue-_,be=Math.hypot(me,$t)||1,at=me/be,Me=$t/be,G=Math.max(10,Math.min(16,be-2)),Se=G*.62,nt=F-at*G,Ce=ue-Me*G,st=-Me,T=at;return{shaftX1:v,shaftY1:_,shaftX2:nt,shaftY2:Ce,headPoints:[`${F},${ue}`,`${nt+st*Se},${Ce+T*Se}`,`${nt-st*Se},${Ce-T*Se}`].join(" ")}}function il(r,l){return{...r,markerType:l,color:r.color||Tt[l]}}function ll(r,l){return{...r,id:Un(),order:l}}function cl(r,l){const p=String(r||"").trim()||(l?tt(l):"Annotated session");return/\bcopy$/i.test(p)?`${p} 2`:`${p} copy`}function dl(r,l,p){if(l===p||l<0||p<0||l>=r.length||p>=r.length)return r;const g=[...r],[v]=g.splice(l,1);return v?(g.splice(p,0,v),Ae(g)):r}function de(r){return String(Math.round(I(r)*1e3)/10)}function ul(r){const l=Number.parseFloat(r);return Number.isFinite(l)?I(l/100):null}function ml(r,l,p){return r.kind==="pin"||r.kind==="text-note"?l==="x"||l==="y"?{...r,[l]:I(p)}:r:r.kind==="box"?l==="x"||l==="y"?{...r,[l]:I(p)}:l==="width"||l==="height"?{...r,[l]:Ee(p)}:r:l==="x"||l==="y"||l==="x2"||l==="y2"?{...r,[l]:I(p)}:r}function fl(r){return r.kind==="pin"||r.kind==="text-note"?[{key:"x",label:"X",value:de(r.x)},{key:"y",label:"Y",value:de(r.y)}]:r.kind==="box"?[{key:"x",label:"X",value:de(r.x)},{key:"y",label:"Y",value:de(r.y)},{key:"width",label:"Width",value:de(r.width)},{key:"height",label:"Height",value:de(r.height)}]:[{key:"x",label:"Start X",value:de(r.x)},{key:"y",label:"Start Y",value:de(r.y)},{key:"x2",label:"End X",value:de(r.x2)},{key:"y2",label:"End Y",value:de(r.y2)}]}function pl(r){if(!r)return null;const l=Math.round(r.x*100),p=Math.round(r.y*100),g=Math.round(r.width*100),v=Math.round(r.height*100);return`crop ${l}%, ${p}% size ${g}% x ${v}%`}function Pa(r){return Number.isFinite(r)?Math.min(4,Math.max(.25,Number(r.toFixed(2)))):1}function Mn(r){const l=[`Annotated attachment: ${r.title||r.image.displayName}`,`Image: ${r.image.displayName}`,`Image Reference: ${r.image.referenceLabel||r.image.assetId}`,`Task ID: ${r.taskId}`,r.globalInstruction?`Global instruction: ${r.globalInstruction}`:"Global instruction: None provided.","Markers:"];return r.annotations.length===0?(l.push("0. No markers."),l.join(`
2
2
  `)):(r.annotations.forEach((p,g)=>{const v=p.markerType||ye,_=pl(p.cropHint);l.push(`${g+1}. ${p.kind} (${v})`),l.push(`Instruction: ${p.instruction||"No marker instruction."}`),_&&l.push(`Region: ${_}`)}),l.join(`
3
3
  `))}function la(r){return{title:r.title,globalInstruction:r.globalInstruction,annotations:Ae(r.annotations)}}function Pn(r){return JSON.stringify(la(r))}function Bn(r){const l=JSON.parse(r);return la({title:String(l?.title||""),globalInstruction:String(l?.globalInstruction||""),annotations:Array.isArray(l?.annotations)?l.annotations:[]})}function hl(r,l){return la({title:r?.title||l,globalInstruction:r?.globalInstruction||"",annotations:r?.annotations||[]})}function Il({runtimeMode:r="local",apiBaseUrl:l="",cloudAuthBaseUrl:p="",workspaceId:g="default",sessionLoadReady:v=!0,requestedTarget:_=null,requestedSessionId:F=null,requestedOpenVersion:ue=0,imageTrayOpen:me,onCloseImageTray:$t,resolveTaskReferenceLabel:be,resolveImageReferenceLabel:at,onRequestedTargetHandled:Me,onOpenTarget:G,onContextChange:Se,viewportByContextKey:nt,onViewportChange:Ce,onBackToTask:st}){const T=r==="cloud"&&(p||l)||"",[Kn,Lt]=s.useState(_),[Rt,Pe]=s.useState([]),[y,Be]=s.useState(null),[ca,rt]=s.useState(!1),[Fe,ot]=s.useState(""),[He,it]=s.useState(""),[L,fe]=s.useState([]),[R,Q]=s.useState(null),[lt,De]=s.useState(null),[ct,ee]=s.useState(!1),[Da,da]=s.useState(null),[At,Oa]=s.useState(Tt[ye]),[Et,Mt]=s.useState(!1),[A,Oe]=s.useState("select"),[Vn,Ne]=s.useState(!1),[Pt,Ua]=s.useState(!1),[te,ae]=s.useState(!1),[Ga,f]=s.useState(null),[Y,P]=s.useState("saved"),[gl,O]=s.useState(null),[Bt,Ka]=s.useState(!1),[pe,ua]=s.useState(null),[xe,ma]=s.useState(!1),[Wn,fa]=s.useState(!1),[pa,Va]=s.useState("json"),[Yn,Ft]=s.useState(!1),[ha,Wa]=s.useState(""),[ga,qn]=s.useState([]),[Ht,Ya]=s.useState(!1),[Ue,qa]=s.useState(!1),[Dt,ya]=s.useState(!1),[Ot,ba]=s.useState(!1),[Xn,Xa]=s.useState(!1),[Jn,Ut]=s.useState(!1),[xa,Gt]=s.useState(""),[dt,Ja]=s.useState(!1),[va,Zn]=s.useState([]),[Kt,Qn]=s.useState(""),[_a,es]=s.useState("updated"),[ka,ts]=s.useState("desc"),[as,Za]=s.useState(!1),[Qa,en]=s.useState(null),[q,ut]=s.useState(!1),[mt,ft]=s.useState(!1),[E,pt]=s.useState(1),[ns,ht]=s.useState(!1),[ss,gt]=s.useState(!1),[Vt,tn]=s.useState(!1),[N,yt]=s.useState({width:0,height:0}),an=s.useRef(null),ne=s.useRef(null),wa=s.useRef(null),nn=s.useRef(null),ve=s.useRef(F),he=s.useRef(""),Wt=s.useRef(0),Ia=s.useRef(""),je=s.useRef(0),Yt=s.useRef(null),sn=s.useRef(0),_e=s.useRef(!1),bt=s.useRef(null),za=s.useRef(null),ke=s.useRef(null),H=s.useRef(""),B=s.useRef(""),qt=s.useRef(null),se=s.useRef(null),Sa=s.useRef(!1),Ge=s.useRef(!1),Xt=s.useRef(null),xt=s.useRef(null),vt=s.useRef(null),Ca=s.useRef(null),_t=s.useRef(null),Ke=s.useRef(!1),Ve=s.useRef(!0),rn=s.useRef(""),on=s.useRef(Ce),Te=s.useRef(null),We=s.useRef(null),Ye=s.useRef(null),qe=s.useRef(null),we=s.useRef(null),re=s.useRef(null),ln=s.useRef(null),cn=s.useRef(null),Na=s.useRef(new Map),b=s.useMemo(()=>Rt.find(e=>e.id===y)||null,[y,Rt]),U=s.useMemo(()=>`workspaceId=${encodeURIComponent(String(g||"default").trim()||"default")}`,[g]),j=s.useMemo(()=>({"x-taskforce-workspace-id":String(g||"default").trim()||"default"}),[g]),ge=s.useMemo(()=>L.find(e=>e.id===R)||null,[L,R]),kt=s.useMemo(()=>L.find(e=>e.id===Da)||null,[Da,L]),rs=As(zn(Us,{activationConstraint:{distance:6}}),zn(Os,{coordinateGetter:Ds})),oe=s.useMemo(()=>Re(_),[_]),X=typeof G=="function",d=X?_:Kn,V=s.useMemo(()=>{const e=Re(d);return e?`${e}::${y||""}`:""},[d,y]),wt=V?nt?.[V]??null:null,Jt=s.useMemo(()=>{const e=String(b?.taskId||"").trim();if(!e)return"";const n=be?.(e).trim()||"";if(n)return n;const o=String(d?.taskId||"").trim(),i=String(d?.taskReferenceLabel||"").trim();return e===o&&i&&i!==e?i:e},[d?.taskId,d?.taskReferenceLabel,be,b?.taskId]),dn=s.useMemo(()=>{const e=ha.trim().toLowerCase();return e?ga.filter(n=>[n.title,n.referenceLabel,n.id].filter(Boolean).join(" ").toLowerCase().includes(e)):ga},[ga,ha]),It=s.useMemo(()=>{const e=String(d?.assetId||"").trim();if(!e)return"";const n=at?.(e).trim()||"";return n||String(d?.imageReferenceLabel||"").trim()},[d?.assetId,d?.imageReferenceLabel,at]),ja=ge?.color||At,un=s.useMemo(()=>la({title:Fe,globalInstruction:He,annotations:L}),[L,He,Fe]),Xe=s.useMemo(()=>Pn(un),[un]),mn=Xe!==B.current,x=s.useMemo(()=>({width:Math.max(N.width*E,0),height:Math.max(N.height*E,0)}),[N.height,N.width,E]),Je=s.useMemo(()=>({visibleRadius:7,hitRadius:11}),[]),Ta=s.useMemo(()=>`0 0 ${Math.max(x.width,1)} ${Math.max(x.height,1)}`,[x.height,x.width]),zt=typeof me=="boolean",fn=s.useMemo(()=>{const e=Kt.trim().toLowerCase();let n=va;return e&&(n=va.filter(o=>[o.displayName,o.originalFilename,o.imageReferenceLabel,o.taskReferenceLabel,o.assetId].filter(Boolean).join(" ").toLowerCase().includes(e))),Ws(n,_a,ka)},[va,Kt,_a,ka]),Ze=s.useMemo(()=>{const e=ne.current;return e?E>1||x.width>e.clientWidth+1||x.height>e.clientHeight+1:E>1},[x.height,x.width,E]),$a=`${Math.round(E*100)}%`,J=Ze&&(ns||ss),La=s.useMemo(()=>{const e=new Map;return L.forEach((n,o)=>{e.set(n.id,o+1)}),e},[L]);s.useEffect(()=>{ve.current=F},[F]),s.useEffect(()=>{const e=nn.current;if(!e||!R||ct)return;e.focus();const n=e.value.length;e.setSelectionRange(n,n)},[ct,R]),s.useEffect(()=>{ke.current=y},[y]),s.useEffect(()=>{on.current=Ce},[Ce]);const Zt=s.useCallback(()=>{_t.current!==null&&(window.clearTimeout(_t.current),_t.current=null);const e=Ca.current;Ca.current=null,e&&V&&on.current?.(V,e)},[V]),ie=s.useCallback(e=>{if(Ke.current||!V)return;const n=ne.current;n&&(Ca.current={zoomLevel:e??E,scrollLeft:Math.max(0,Math.round(n.scrollLeft)),scrollTop:Math.max(0,Math.round(n.scrollTop))},_t.current===null&&(_t.current=window.setTimeout(Zt,Qi)))},[V,Zt,E]),St=s.useCallback(()=>{const e=ne.current;if(!e||e.clientWidth<=0||e.clientHeight<=0||N.width<=0||N.height<=0)return;const n=Pa(Math.min(e.clientWidth/N.width,e.clientHeight/N.height)),o=N.width*n,i=N.height*n;Ve.current=!0,Ke.current=!0,pt(n),window.requestAnimationFrame(()=>{e.scrollLeft=Math.max(0,(o-e.clientWidth)/2),e.scrollTop=Math.max(0,(i-e.clientHeight)/2),ie(n),window.requestAnimationFrame(()=>{Ke.current=!1})})},[N.height,N.width,ie]);s.useEffect(()=>()=>{ie(),Zt()},[V,Zt,ie]),s.useEffect(()=>{rt(!1)},[y]),s.useEffect(()=>{if(!ge){Mt(!1);return}Oa(ge.color||Tt[ge.markerType||ye])},[ge]);const Qt=s.useCallback(async e=>{const n=typeof performance<"u"?performance.now():Date.now(),o=await ce(`/api/taskforce/annotated-attachments/sessions?${U}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...j},body:JSON.stringify({taskId:e.taskId,baseImageAssetId:e.assetId,title:tt(e),globalInstruction:"",annotations:[]})},T),i=await o.json().catch(()=>({}));if(!o.ok)throw new Error(String(i?.error||"Failed to create session."));const c=i?.session;if(!c?.id)throw new Error("Failed to create session.");return na("annotated_session_create_completed",{assetId:e.assetId,taskId:e.taskId||null,sessionId:c.id,durationMs:Math.round((typeof performance<"u"?performance.now():Date.now())-n),debugTimings:i?.debugTimings||null,serverTiming:typeof o.headers?.get=="function"&&o.headers.get("server-timing")||null}),c},[j,T,U]),pn=s.useCallback(e=>new Promise((n,o)=>{const i=new FileReader;i.onload=()=>n(typeof i.result=="string"?i.result:""),i.onerror=()=>o(i.error||new Error("Failed to read clipboard image.")),i.readAsDataURL(e)}),[]),$=s.useCallback(()=>{bt.current!==null&&(window.clearTimeout(bt.current),bt.current=null),vt.current!==null&&(window.clearTimeout(vt.current),vt.current=null)},[]),Qe=s.useCallback(e=>{ot(e.title),it(e.globalInstruction),fe(e.annotations),Q(n=>n&&e.annotations.some(o=>o.id===n)?n:null)},[]),Ie=s.useCallback((e,n)=>{const o=tt(n||d||{assetId:e.baseImageAssetId,displayName:"Annotated session"}),i=hl(e,o),c=Pn(i);_e.current=!0,$(),Qe(i),B.current=c,H.current=c,qt.current=null,Ge.current=!1,Xt.current=null,xt.current=null,O(null),P("saved"),ae(!1)},[d,Qe,$]),Ct=s.useCallback(e=>{_e.current=!0,$(),Pe([]),Be(null),Ne(!1),rt(!1),ot(tt(e)),it(""),fe([]),Q(null),ee(!1),B.current="",H.current="",qt.current=null,Ge.current=!1,Xt.current=null,xt.current=null,ua(null),fa(!1),O(null),P("saved"),ae(!1)},[$]),$e=s.useCallback(async(e,n,o)=>{const i=ke.current;if(!i)return!0;if(e===B.current)return se.current||(O(null),P("saved")),!0;if(se.current){if(Ge.current=!0,!o?.waitForInFlight||!await se.current)return!1;const h=H.current;return h===B.current?!0:$e(h,n,o)}$();const c=Bn(e);Xt.current=i,qt.current=e,ae(!0),f(null),O(null),P("saving");const m=(async()=>{try{const u=await ce(`/api/taskforce/annotated-attachments/sessions/${encodeURIComponent(i)}?${U}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json",...j},body:JSON.stringify(c)},T),h=await u.json().catch(()=>({}));if(!u.ok)throw new Error(String(h?.error||"Failed to save session."));const k=h?.session;if(!k?.id)throw new Error("Failed to save session.");Pe(jt=>{const C=jt.findIndex(ta=>ta.id===k.id);if(C===-1)return[k,...jt];const ze=[...jt];return ze[C]=k,ze}),B.current=e,xt.current=null,O(null);const w=ke.current===k.id,S=H.current,K=S!==e,Le=Ge.current||K;return Ge.current=!1,w&&!Le?(_e.current=!0,Qe(c),P("saved")):!Le&&S===B.current?P("saved"):P("pending"),!0}catch(u){const h=u instanceof Error?u.message:"Failed to save session.";return f(h),O(h),P("error"),xt.current!==e&&ke.current===i&&H.current===e&&(xt.current=e,vt.current=window.setTimeout(()=>{vt.current=null,!(ke.current!==i||H.current!==e)&&$e(e,n,{waitForInFlight:!0})},1500)),!1}finally{qt.current=null,se.current=null,Xt.current=null,ae(!1)}})();se.current=m;const z=await m;if(z){const u=H.current;if(u!==B.current)return $e(u,n,o)}return z},[Qe,$,j,T,U]),hn=s.useCallback(e=>{if(ke.current){if(H.current===B.current){O(null),se.current||P("saved");return}Y!=="saving"&&P("pending"),$(),bt.current=window.setTimeout(()=>{bt.current=null,$e(H.current,"structure")},e)}},[$,$e,Y]),Z=s.useCallback(e=>{za.current=e},[]),M=s.useCallback(async e=>{$();const n=H.current;return!ke.current||n===B.current?(O(null),se.current||P("saved"),!0):$e(n,e,{waitForInFlight:!0})},[$,$e]),os=s.useCallback(()=>{const e=B.current;e&&($(),_e.current=!0,Qe(Bn(e)),O(null),P("saved"),f(null))},[Qe,$]),W=s.useCallback(async(e,n)=>{const o=typeof performance<"u"?performance.now():Date.now(),i=JSON.stringify({targetKey:Re(e),requestedSessionId:n?.requestedSessionId??null,autoCreateIfEmpty:n?.autoCreateIfEmpty===!0});if(Yt.current===i)return;const c=je.current+1;je.current=c,Yt.current=i,Ua(!0),f(null);try{const m=new URLSearchParams;g&&m.set("workspaceId",g),e.taskId&&m.set("taskId",e.taskId),m.set("imageAssetId",e.assetId);const z=await ce(`/api/taskforce/annotated-attachments/sessions?${m.toString()}`,{credentials:"include",headers:j,cache:"no-store"},T),u=await z.json().catch(()=>({}));if(!z.ok)throw new Error(String(u?.error||"Failed to load annotated attachment sessions."));const h=Array.isArray(u?.sessions)?u.sessions:[];if(na("annotated_sessions_loaded",{assetId:e.assetId,taskId:e.taskId||null,requestedSessionId:n?.requestedSessionId??null,autoCreateIfEmpty:n?.autoCreateIfEmpty===!0,sessionCount:h.length,durationMs:Math.round((typeof performance<"u"?performance.now():Date.now())-o),serverTiming:typeof z.headers?.get=="function"&&z.headers.get("server-timing")||null}),h.length===0&&n?.autoCreateIfEmpty&&String(e.assetId||"").trim()){const S=n?.requestedSessionId??ve.current;if(ve.current=null,S&&f("The previously selected annotation session could not be restored."),je.current!==c)return;const K=await Qt(e);if(na("annotated_sessions_auto_created_after_empty_load",{assetId:e.assetId,taskId:e.taskId||null,sessionId:K.id,totalDurationMs:Math.round((typeof performance<"u"?performance.now():Date.now())-o)}),je.current!==c)return;Pe([K]),Be(K.id),Ne(!1),Ie(K,e);return}if(je.current!==c)return;Pe(h),Ne(h.length===0);const k=n?.requestedSessionId??ve.current;ve.current=null;const w=h.find(S=>S.id===k)||h[0]||null;k&&!w&&f("The previously selected annotation session could not be restored."),Be(w?.id||null),w?Ie(w,e):(_e.current=!0,$(),ot(tt(e)),it(""),fe([]),Q(null),ee(!1),B.current="",H.current="",O(null),P("saved"))}catch(m){if(je.current!==c)return;f(m instanceof Error?m.message:"Failed to load sessions.")}finally{Yt.current===i&&(Yt.current=null),je.current===c&&Ua(!1)}},[$,Qt,j,T,Ie,g]),gn=s.useCallback(async()=>{Za(!0),en(null);try{const e=new URLSearchParams;e.set("workspaceId",String(g||"default").trim()||"default");const n=await ce(`/api/taskforce/annotated-attachments/images?${e.toString()}`,{credentials:"include",headers:j,cache:"no-store"},T),o=await n.json().catch(()=>({}));if(!n.ok)throw new Error(String(o?.error||"Failed to load images."));Zn(Array.isArray(o?.images)?o.images:[])}catch(e){en(e instanceof Error?e.message:"Failed to load images.")}finally{Za(!1)}},[j,T,g]),is=s.useCallback(async()=>{if(typeof navigator>"u"||!navigator.clipboard||typeof navigator.clipboard.read!="function"){f("Clipboard image paste is not supported in this environment.");return}tn(!0),f(null),sn.current=Date.now()+2e3;try{const n=(await navigator.clipboard.read()).find(k=>k.types.some(w=>w.startsWith("image/"))),o=n?.types.find(k=>k.startsWith("image/"))||"";if(!n||!o)throw new Error("No image found on the clipboard.");const i=await n.getType(o),c=await pn(i);if(!c)throw new Error("Failed to read clipboard image.");const m=o==="image/jpeg"?"jpg":o==="image/webp"?"webp":o==="image/gif"?"gif":"png",z=await fetch("/api/taskforce/context-upload",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...j},body:JSON.stringify({file:c,originalName:`pasted-image.${m}`,workspaceId:String(g||"default").trim()||"default"})}),u=await z.json().catch(()=>({}));if(!z.ok||!u?.success||typeof u?.assetId!="string"||typeof u?.path!="string")throw new Error(String(u?.error||"Failed to paste image into Image Notes."));const h={assetId:u.assetId,imageReferenceLabel:typeof u?.referenceLabel=="string"?u.referenceLabel:void 0,path:u.path,displayName:typeof u?.displayName=="string"&&u.displayName.trim().length>0?u.displayName.trim():"Pasted image"};ve.current=null,X?(he.current="",G?.(h,{sessionId:null})):(Lt(h),he.current=Re(h),W(h,{autoCreateIfEmpty:!0}))}catch(e){f(e instanceof Error?e.message:"Failed to paste image.")}finally{tn(!1)}},[X,W,G,pn,j,g]),ls=s.useCallback(async()=>{const e=xa.trim();if(!e){f("Enter an image reference to open.");return}Ja(!0),f(null);try{const n=new URLSearchParams({workspaceId:String(g||"default").trim()||"default"}),o=await ce(`/api/taskforce/annotated-attachments/images/${encodeURIComponent(e)}?${n.toString()}`,{method:"GET",credentials:"include",headers:j}),i=await o.json().catch(()=>({}));if(!o.ok||!i?.target||typeof i.target.assetId!="string"||typeof i.target.path!="string")throw new Error(String(i?.error||"Failed to open image reference."));const c={assetId:i.target.assetId,path:i.target.path,displayName:typeof i.target.displayName=="string"&&i.target.displayName.trim().length>0?i.target.displayName.trim():"Image attachment",taskId:typeof i.target.taskId=="string"&&i.target.taskId.trim().length>0?i.target.taskId.trim():void 0,taskReferenceLabel:typeof i.target.taskReferenceLabel=="string"&&i.target.taskReferenceLabel.trim().length>0?i.target.taskReferenceLabel.trim():void 0,imageReferenceLabel:typeof i.target.imageReferenceLabel=="string"&&i.target.imageReferenceLabel.trim().length>0?i.target.imageReferenceLabel.trim():void 0};ve.current=null,Ut(!1),Gt(""),X?(he.current="",G?.(c,{sessionId:null})):(Lt(c),he.current=Re(c),W(c,{autoCreateIfEmpty:!0}))}catch(n){f(n instanceof Error?n.message:"Failed to open image reference.")}finally{Ja(!1)}},[X,W,G,xa,j,g]),cs=s.useCallback(async e=>{if(!e.assetId||!e.path||!await M("session-switch"))return;const o={assetId:e.assetId,path:e.path,displayName:String(e.displayName||e.originalFilename||"Image attachment").trim()||"Image attachment",...e.taskId?{taskId:e.taskId}:{},...e.taskReferenceLabel?{taskReferenceLabel:e.taskReferenceLabel}:{},...e.imageReferenceLabel?{imageReferenceLabel:e.imageReferenceLabel}:{}};ve.current=null,f(null),X?(he.current="",G?.(o,{sessionId:null})):(Lt(o),he.current=Re(o),Ct(o),W(o,{autoCreateIfEmpty:!0}))},[M,X,W,G,Ct]),ea=s.useCallback(e=>{if(X&&d&&d.taskId!==e.taskId){const n={...d};e.taskId?(n.taskId=e.taskId,n.taskReferenceLabel=be?.(e.taskId)||e.taskId):(delete n.taskId,delete n.taskReferenceLabel),G?.(n,{sessionId:e.id})}Pe(n=>{const o=n.findIndex(c=>c.id===e.id);if(o===-1)return[e,...n];const i=[...n];return i[o]=e,i}),Be(e.id),Ie(e,d)},[d,X,G,be,Ie]),yn=s.useCallback(e=>{Pe(n=>{const o=n.filter(c=>c.id!==e),i=o[0]||null;return Be(i?.id||null),i?Ie(i,d):(_e.current=!0,$(),ot(tt(d||{displayName:"Annotated session"})),it(""),fe([]),Q(null),ee(!1),B.current="",H.current="",O(null),P("saved")),o})},[d,$,Ie]);s.useEffect(()=>{if(!_)return;if(X||Lt(n=>n&&Re(n)===oe&&n.taskReferenceLabel===_.taskReferenceLabel&&n.imageReferenceLabel===_.imageReferenceLabel&&n.displayName===_.displayName?n:_),!v){oe&&(oe!==he.current||ue!==Wt.current)&&oe!==Ia.current&&(Ct(_),Ia.current=oe,Wt.current=ue,na("annotated_sessions_load_deferred",{assetId:_.assetId,taskId:_.taskId||null,requestedTargetKey:oe})),Me?.();return}oe&&(oe!==he.current||ue!==Wt.current)&&(Ct(_),he.current=oe,Wt.current=ue,Ia.current="",W(_,{autoCreateIfEmpty:!0})),Me?.()},[X,W,Me,ue,_,oe,Ct,F,v]),s.useEffect(()=>{d&&Se?.({target:d,sessionId:y})},[d,Se,y]),s.useEffect(()=>{if(!d||typeof document>"u"||!v)return;const e=()=>{Date.now()<sn.current||H.current!==B.current||te||Pt||W(d,{requestedSessionId:y})},n=()=>{document.visibilityState==="visible"&&e()};return document.addEventListener("visibilitychange",n),()=>{document.removeEventListener("visibilitychange",n)}},[d,W,Pt,te,y,v]),s.useEffect(()=>{if(!d?.path){ut(!1),ft(!1),yt({width:0,height:0});return}ut(!0),ft(!1),yt({width:0,height:0}),pt(1),Ve.current=!0,ht(!1),gt(!1)},[d?.path]),s.useEffect(()=>{if(!q)return;const e=wa.current;!e||!e.complete||e.naturalWidth<=0||e.naturalHeight<=0||(yt({width:e.naturalWidth,height:e.naturalHeight}),ut(!1),ft(!1))},[d?.path,q]),s.useEffect(()=>{Ze||(ht(!1),gt(!1))},[Ze]),s.useEffect(()=>{if(!y||!V||q||mt||N.width<=0||N.height<=0||rn.current===V)return;if(rn.current=V,!wt){St();return}Ve.current=!1,Ke.current=!0;const e=Pa(wt.zoomLevel);pt(e),window.requestAnimationFrame(()=>{window.requestAnimationFrame(()=>{const n=ne.current;n&&(n.scrollLeft=Math.max(0,wt.scrollLeft),n.scrollTop=Math.max(0,wt.scrollTop)),Ke.current=!1})})},[V,mt,q,N.height,N.width,St,wt,y]),s.useEffect(()=>{const e=ne.current;if(!e||N.width<=0||N.height<=0)return;const n=new ResizeObserver(()=>{Ve.current&&St()});return n.observe(e),()=>n.disconnect()},[St,N.height,N.width]),s.useEffect(()=>{ua(null)},[y]),s.useEffect(()=>{if(H.current=Xe,_e.current){_e.current=!1;return}if(!y){$(),O(null),P("saved");return}if(Xe===B.current){$(),se.current||(O(null),P("saved"));return}const e=za.current;if(za.current=null,Y==="error"&&e===null)return;const n=e??600;if(se.current){Ge.current=!0,P("pending");return}hn(n)},[$,Xe,Y,hn,y]),s.useEffect(()=>{y&&(se.current||Xe===B.current&&Y!=="error"&&Y!=="saved"&&(O(null),P("saved")))},[Xe,Y,y]),s.useEffect(()=>{!zt||!me||gn()},[gn,me,zt]),s.useEffect(()=>{if(typeof window>"u")return;const e=n=>{H.current!==B.current&&(n.preventDefault(),n.returnValue="")};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[]),s.useEffect(()=>{if(typeof document>"u")return;const e=()=>{document.visibilityState==="hidden"&&M("visibility-hidden")};return document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[M]),s.useEffect(()=>{if(!Et||typeof document>"u")return;const e=n=>{const o=n.target;o instanceof Node&&(ln.current?.contains(o)||Mt(!1))};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[Et]),s.useEffect(()=>{if(!ca||typeof document>"u")return;const e=n=>{const o=n.target;o instanceof Node&&(cn.current?.contains(o)||rt(!1))};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[ca]),s.useEffect(()=>()=>{$()},[$]),s.useEffect(()=>{if(!xe)return;const e=window.setTimeout(()=>ma(!1),2e3);return()=>window.clearTimeout(e)},[xe]),s.useEffect(()=>{if(!Dt)return;const e=window.setTimeout(()=>ya(!1),2e3);return()=>window.clearTimeout(e)},[Dt]),s.useEffect(()=>{if(!Ot)return;const e=window.setTimeout(()=>ba(!1),2e3);return()=>window.clearTimeout(e)},[Ot]);const le=s.useCallback((e,n,o=300)=>{fe(i=>Ae(i.map(c=>c.id===e?n(c):c))),Z(o)},[Z]),ds=s.useCallback(e=>{ge&&(le(ge.id,n=>({...n,color:e})),Oa(e),Mt(!1))},[ge,le]),bn=s.useCallback(async()=>{if(!(!d||!await M("session-switch"))){ae(!0),f(null);try{const n=await Qt(d);Ne(!1),await W(d,{requestedSessionId:n.id,autoCreateIfEmpty:!1}),Oe("select")}catch(n){f(n instanceof Error?n.message:"Failed to create session."),Ne(!0)}finally{ae(!1)}}},[d,Qt,M,W]),us=s.useCallback(e=>{if(e!=="select"&&!b){ht(!1),f("No session exists for this image yet."),Ne(!0);return}f(null),Ne(!1),ht(!1),Oe(e)},[b]),ms=s.useCallback(async()=>{if(!(!d||!b||!await M("duplicate"))){ae(!0),f(null);try{const n=Ae(L.map((m,z)=>ll(m,z))),o=await ce(`/api/taskforce/annotated-attachments/sessions?${U}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...j},body:JSON.stringify({taskId:d.taskId,baseImageAssetId:d.assetId,title:cl(Fe||b.title,d),globalInstruction:He,annotations:n})},T),i=await o.json().catch(()=>({}));if(!o.ok)throw new Error(String(i?.error||"Failed to duplicate session."));const c=i?.session;if(!c?.id)throw new Error("Failed to duplicate session.");ea(c),Oe("select")}catch(n){f(n instanceof Error?n.message:"Failed to duplicate session.")}finally{ae(!1)}}},[d,L,He,Fe,ea,M,j,T,b,U]),fs=s.useCallback(async()=>M("manual"),[M]),xn=s.useCallback(async()=>{if(y){Ka(!0),f(null);try{const e=await ce(`/api/taskforce/annotated-attachments/sessions/${encodeURIComponent(y)}/payload?${U}`,{credentials:"include",headers:j},T),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(String(n?.error||"Failed to load payload preview."));ua(n?.payload||null)}catch(e){f(e instanceof Error?e.message:"Failed to load payload preview.")}finally{Ka(!1)}}},[j,T,y,U]),ps=s.useCallback(()=>{y&&M("payload-preview").then(e=>{e&&(fa(!0),xn())})},[M,xn,y]),vn=s.useCallback(async e=>{if(!pe||!navigator.clipboard||typeof navigator.clipboard.writeText!="function"){f("Clipboard copy is not available in this browser.");return}try{const n=e==="json"?JSON.stringify(pe,null,2):Mn(pe);await navigator.clipboard.writeText(n),ma(e)}catch(n){f(n instanceof Error?n.message:"Failed to copy payload content."),ma(!1)}},[pe]),hs=s.useCallback(async()=>{if(!Jt||!navigator.clipboard||typeof navigator.clipboard.writeText!="function"){f("Clipboard copy is not available in this browser.");return}try{await navigator.clipboard.writeText(Jt),ya(!0)}catch(e){f(e instanceof Error?e.message:"Failed to copy task id."),ya(!1)}},[Jt]),gs=s.useCallback(async()=>{if(!(!b||Ht)){Ft(!0),Wa(""),Ya(!0),f(null);try{const e=await ce(`/api/taskforce/tasks?${U}`,{credentials:"include",headers:j},T),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(String(n?.error||"Failed to load tasks."));qn(Array.isArray(n?.tasks)?n.tasks:[])}catch(e){f(e instanceof Error?e.message:"Failed to load tasks.")}finally{Ya(!1)}}},[j,T,b,Ht,U]),Ra=s.useCallback(async e=>{const n=ke.current;if(!(!n||Sa.current)){Sa.current=!0,qa(!0);try{if(!await M("task-link"))return;f(null);const i=await ce(`/api/taskforce/annotated-attachments/sessions/${encodeURIComponent(n)}?${U}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json",...j},body:JSON.stringify({taskId:e||""})},T),c=await i.json().catch(()=>({}));if(!i.ok)throw new Error(String(c?.error||"Failed to update session task."));const m=c?.session;if(!m?.id)throw new Error("Failed to update session task.");ea(m),Ft(!1)}catch(o){f(o instanceof Error?o.message:"Failed to update session task.")}finally{Sa.current=!1,qa(!1)}}},[ea,M,j,T,U]),ys=s.useCallback(async()=>{if(!It||!navigator.clipboard||typeof navigator.clipboard.writeText!="function"){f("Clipboard copy is not available in this browser.");return}try{await navigator.clipboard.writeText(It),ba(!0)}catch(e){f(e instanceof Error?e.message:"Failed to copy image reference."),ba(!1)}},[It]),bs=s.useCallback(async()=>{if(!y||!await M("delete-session"))return;const n=(b?.title||"Untitled session").trim()||"Untitled session";if(window.confirm(`Delete the annotated attachment session "${n}"?`)){ae(!0),f(null);try{const o=await ce(`/api/taskforce/annotated-attachments/sessions/${encodeURIComponent(y)}?${U}`,{method:"DELETE",credentials:"include",headers:j},T),i=await o.json().catch(()=>({}));if(!o.ok)throw new Error(String(i?.error||"Failed to delete session."));yn(y),Oe("select")}catch(o){f(o instanceof Error?o.message:"Failed to delete session.")}finally{ae(!1)}}},[M,yn,j,T,b,y,U]),_n=s.useCallback(()=>{R&&(fe(e=>Ae(e.filter(n=>n.id!==R))),Q(null),ee(!1),Z(300))},[Z,R]),Aa=s.useCallback(()=>{R&&window.confirm("Delete this marker? This cannot be undone.")&&_n()},[_n,R]),Nt=s.useCallback(e=>{Q(e),ee(!1),window.requestAnimationFrame(()=>{Na.current.get(e)?.scrollIntoView?.({block:"nearest",behavior:"smooth"})})},[]),xs=s.useCallback(e=>{if(R===e&&!ct){ee(!0);return}Nt(e)},[ct,Nt,R]),et=s.useCallback(e=>{Ve.current=!1;const n=Pa(e),o=ne.current;if(!o||n===E){pt(n),window.requestAnimationFrame(()=>ie(n));return}const i=(o.scrollLeft+o.clientWidth/2)*(n/E)-o.clientWidth/2,c=(o.scrollTop+o.clientHeight/2)*(n/E)-o.clientHeight/2;pt(n),window.requestAnimationFrame(()=>{o.scrollLeft=Math.max(0,i),o.scrollTop=Math.max(0,c),ie(n)})},[ie,E]),vs=s.useCallback(()=>{et(E+.25)},[et,E]),_s=s.useCallback(()=>{et(E-.25)},[et,E]),ks=s.useCallback(()=>{et(1);const e=ne.current;e&&window.requestAnimationFrame(()=>{e.scrollLeft=0,e.scrollTop=0,ie(1)})},[et,ie]),kn=s.useCallback((e,n)=>{e!==n&&fe(o=>{const i=o.findIndex(m=>m.id===e),c=o.findIndex(m=>m.id===n);return i===-1||c===-1?o:(Z(300),dl(o,i,c))})},[Z]),ws=s.useCallback(e=>{da(String(e.active.id))},[]),Is=s.useCallback(e=>{const n=String(e.active.id),o=e.over?String(e.over.id):null;o&&n!==o&&kn(n,o),da(null)},[kn]);s.useEffect(()=>{if(!R)return;const e=n=>{n.key!=="Delete"&&n.key!=="Backspace"||Gn(n.target)||(n.preventDefault(),Aa())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[Aa,R]),s.useEffect(()=>{const e=i=>{i.code==="Space"&&Ze&&(al(i.target)||(i.preventDefault(),gt(!0)))},n=i=>{i.code==="Space"&&gt(!1)},o=()=>{gt(!1)};return window.addEventListener("keydown",e),window.addEventListener("keyup",n),window.addEventListener("blur",o),()=>{window.removeEventListener("keydown",e),window.removeEventListener("keyup",n),window.removeEventListener("blur",o)}},[Ze]);const D=s.useCallback(e=>{const n=an.current?.getBoundingClientRect();return!n||n.width<=0||n.height<=0?null:{x:I((e.clientX-n.left)/n.width),y:I((e.clientY-n.top)/n.height)}},[]),zs=s.useCallback(e=>{if(J){const i=ne.current;if(!i)return;re.current={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,scrollLeft:i.scrollLeft,scrollTop:i.scrollTop},e.currentTarget.setPointerCapture(e.pointerId),e.preventDefault();return}if(!y)return;if(A==="select"){Q(null),ee(!1);return}const n=D(e);if(!n)return;if(A==="pin"||A==="text-note"){const i=En(A,n,n,At);fe(c=>Ae([...c,i])),Q(i.id),ee(!1),Z(300),Oe("select");return}Te.current=n;const o=En(A,n,n,At);we.current={annotationId:o.id,kind:A},e.currentTarget.setPointerCapture?.(e.pointerId),fe(i=>Ae([...i,o])),Q(o.id),ee(!1),Z(300)},[At,J,Z,D,y,A]),Ss=s.useCallback(e=>{if(re.current?.pointerId===e.pointerId){e.currentTarget.releasePointerCapture?.(e.pointerId);return}if(!Te.current||!we.current||A!=="box"&&A!=="arrow")return;const n=D(e);Te.current=null,we.current=null,e.currentTarget.releasePointerCapture?.(e.pointerId),n&&Oe("select")},[D,A]),wn=s.useCallback((e,n)=>{if(A!=="select"||J)return;const o=D(e);o&&(We.current={annotationId:n.id,originPointer:o,originAnnotation:n},Q(n.id),e.stopPropagation())},[J,D,A]),Cs=s.useCallback(e=>{if(re.current?.pointerId===e.pointerId){const u=ne.current;if(!u)return;const h=e.clientX-re.current.startX,k=e.clientY-re.current.startY;u.scrollLeft=re.current.scrollLeft-h,u.scrollTop=re.current.scrollTop-k;return}if(we.current&&Te.current){const u=D(e);if(!u)return;const{annotationId:h,kind:k}=we.current,w=Te.current;le(h,S=>k==="box"&&S.kind==="box"?{...S,x:I(Math.min(w.x,u.x)),y:I(Math.min(w.y,u.y)),width:Ee(Math.abs(u.x-w.x)),height:Ee(Math.abs(u.y-w.y))}:k==="arrow"&&S.kind==="arrow"?{...S,x:w.x,y:w.y,x2:u.x,y2:u.y}:S);return}if(Ye.current){const u=D(e);if(!u)return;const{annotationId:h,originPointer:k,originAnnotation:w}=Ye.current,S=u.x-k.x,K=u.y-k.y;le(h,()=>({...w,width:Ee(w.width+S),height:Ee(w.height+K)}));return}if(qe.current){const u=D(e);if(!u)return;const{annotationId:h,endpoint:k,originPointer:w,originAnnotation:S}=qe.current,K=u.x-w.x,Le=u.y-w.y;le(h,()=>k==="tail"?{...S,x:I(S.x+K),y:I(S.y+Le)}:{...S,x2:I(S.x2+K),y2:I(S.y2+Le)});return}if(!We.current)return;const n=D(e);if(!n)return;const{annotationId:o,originPointer:i,originAnnotation:c}=We.current,m=n.x-i.x,z=n.y-i.y;le(o,()=>c.kind==="pin"||c.kind==="text-note"?{...c,x:I(c.x+m),y:I(c.y+z)}:c.kind==="box"?{...c,x:I(c.x+m),y:I(c.y+z)}:{...c,x:I(c.x+m),y:I(c.y+z),x2:I(c.x2+m),y2:I(c.y2+z)})},[D,le]),Ns=s.useCallback(()=>{Te.current=null,We.current=null,Ye.current=null,qe.current=null,we.current=null,re.current=null},[]),js=s.useCallback(()=>{Te.current=null,We.current=null,Ye.current=null,qe.current=null,we.current=null,re.current=null},[]),Ts=s.useCallback(()=>{We.current=null,Ye.current=null,qe.current=null,we.current=null,re.current=null},[]),$s=s.useCallback((e,n)=>{if(A!=="select"||J)return;const o=D(e);o&&(Ye.current={annotationId:n.id,originPointer:o,originAnnotation:n},e.stopPropagation())},[J,D,A]),In=s.useCallback((e,n,o)=>{if(A!=="select"||J)return;const i=D(e);i&&(qe.current={annotationId:n.id,originPointer:i,originAnnotation:n,endpoint:o},e.stopPropagation())},[J,D,A]),Ls=b?.updatedAt?Ma(b.updatedAt):"Not saved yet";return t.jsxs("div",{className:`${a.shell} ${zt?a.shellWithImageTray:""} ${zt&&me?a.shellImageTrayOpen:""}`.trim(),children:[zt?t.jsxs("aside",{className:`${a.imageTrayPanel} ${me?a.imageTrayPanelOpen:""}`.trim(),"aria-label":"Image tray","aria-hidden":!me,children:[t.jsxs("div",{className:a.imageTrayHeader,children:[t.jsxs("span",{className:a.imageTrayTitle,children:[t.jsx(Cn,{size:14}),"Images"]}),t.jsx("button",{type:"button",className:"tf-control-icon",onClick:$t,title:"Collapse image tray","aria-label":"Collapse image tray",children:t.jsx(qs,{size:16})})]}),t.jsxs("div",{className:a.imageTraySearch,children:[t.jsx(Xs,{size:12,className:a.imageTraySearchIcon}),t.jsx("input",{type:"text",placeholder:"Search images...",value:Kt,onChange:e=>Qn(e.target.value),className:a.imageTraySearchInput})]}),t.jsx("div",{className:a.imageTraySortControlRow,children:t.jsx(Ys,{field:_a,order:ka,onFieldChange:es,onOrderChange:ts})}),t.jsx("div",{className:`tf-scrollbar tf-tray-scroll-viewport ${a.imageTrayList}`,children:as?t.jsx("div",{className:a.imageTrayState,children:"Loading images..."}):Qa?t.jsx("div",{className:a.imageTrayStateError,children:Qa}):fn.length===0?t.jsx("div",{className:a.imageTrayState,children:Kt.trim()?"No images match your search.":"No images found."}):fn.map(e=>{const n=d?.assetId===e.assetId,o=typeof e.attachmentCount=="number"&&Number.isFinite(e.attachmentCount)?Math.max(0,e.attachmentCount):0,i=typeof e.sessionCount=="number"&&Number.isFinite(e.sessionCount)?Math.max(0,e.sessionCount):0,c=o>1?`${o} tasks linked`:o===1?e.taskReferenceLabel||"1 task linked":"Unattached",m=String(e.displayName||e.originalFilename||"Image attachment").trim()||"Image attachment";return t.jsxs("button",{type:"button",className:`${a.imageTrayItem} ${n?a.imageTrayItemActive:""}`.trim(),onClick:()=>{cs(e)},title:m,children:[t.jsx("span",{className:a.imageTrayThumb,children:t.jsx("img",{src:e.path,alt:"",loading:"lazy"})}),t.jsxs("span",{className:a.imageTrayItemBody,children:[t.jsx("span",{className:a.imageTrayItemTitle,children:m}),t.jsx("span",{className:a.imageTrayItemTask,children:c}),t.jsxs("span",{className:a.imageTrayItemMeta,children:[t.jsxs("span",{className:a.imageTrayItemMetaDetails,children:[nl(e.sizeBytes),e.updatedAt?t.jsxs(t.Fragment,{children:[" · ",sl(e.updatedAt)]}):null,i>0?t.jsxs(t.Fragment,{children:[" · ",i," session",i===1?"":"s"]}):null]}),e.imageReferenceLabel?t.jsx("span",{className:a.imageTrayItemReference,children:e.imageReferenceLabel}):null]})]})]},e.assetId)})})]}):null,t.jsxs("section",{className:`tf-surface-panel ${a.panel} ${a.sessionPanel}`,children:[t.jsx("div",{className:a.sessionContextBar,children:b?.taskId?t.jsxs(t.Fragment,{children:[t.jsx("div",{className:a.sessionContextLeft,children:st?t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.backToTaskBtn}`,onClick:()=>{M("back-to-task").then(e=>{e&&b.taskId&&st(b.taskId)})},"aria-label":"Back to task",title:"Back to task",children:t.jsx(Js,{size:16})}):t.jsx("div",{className:a.sessionContextSpacer,"aria-hidden":"true"})}),t.jsxs("div",{className:a.sessionContextRight,children:[t.jsx(Vs,{copied:Dt,onClick:()=>{hs()},title:"Copy task id",ariaLabel:Dt?"Copied task id":"Copy task id",label:Jt}),t.jsx("button",{type:"button",className:`tf-control-icon ${a.iconButton}`,onClick:()=>{Ra(null)},disabled:Ue,"aria-label":"Unlink session from task",title:"Unlink session from task",children:t.jsx(Zs,{size:16})})]})]}):t.jsxs(t.Fragment,{children:[t.jsx("div",{className:a.sessionContextLeft,children:t.jsx("span",{className:`tf-label-micro ${a.sessionContextLabel}`,children:"Unattached session"})}),t.jsx("div",{className:a.sessionContextRight,children:t.jsx("div",{className:a.sessionContextSpacer,"aria-hidden":"true"})})]})}),t.jsxs("div",{className:a.panelHeader,children:[t.jsxs("div",{className:a.panelHeaderText,children:[t.jsx("div",{className:`tf-heading-card ${a.panelTitle}`,children:"Sessions"}),d?null:t.jsx("div",{className:"tf-text-secondary",children:"Open an image attachment to begin"})]}),t.jsxs("div",{className:a.sessionActions,children:[t.jsx("button",{type:"button",className:`tf-control-icon ${a.iconButton}`,onClick:()=>{gs()},disabled:!b||Ht||Ue,"aria-label":b?.taskId?"Change linked task":"Link session to task",title:b?.taskId?"Change linked task":"Link session to task",children:t.jsx(Qs,{size:16})}),t.jsx("button",{type:"button",className:`tf-control-icon ${a.iconButton}`,onClick:()=>{bn()},disabled:!d||te,"aria-label":"Create session",title:"Create session",children:t.jsx(er,{size:16})})]})]}),d?Pt?t.jsx("div",{className:a.emptyState,children:t.jsx("p",{className:"tf-empty-copy",children:"Loading sessions…"})}):t.jsx("div",{className:`tf-scrollbar ${a.sessionList}`,children:Rt.length===0?t.jsxs("div",{className:a.sessionEmptyState,children:[t.jsx("div",{className:`tf-heading-card ${a.sessionTitle}`,children:"No sessions yet"}),t.jsx("div",{className:`tf-text-secondary ${a.annotationSummary}`,children:"Create the first annotation session for this image."})]}):Rt.map(e=>{const n=y===e.id,o=n&&ca,i=rl(n?He:e.globalInstruction),c=(n?Fe:e.title)||"Untitled session";return t.jsxs("div",{className:`tf-surface-elevated ${a.sessionCard} ${n?a.sessionCardActive:""}`,ref:n?cn:void 0,onBlur:o?m=>{const z=m.relatedTarget;z instanceof Node&&m.currentTarget.contains(z)||rt(!1)}:void 0,children:[o?t.jsxs("div",{className:a.sessionCardBody,children:[t.jsxs("div",{className:a.sessionMeta,children:[t.jsx("label",{className:"tf-field-label",htmlFor:"annotated-session-title",children:"Session title"}),t.jsx("input",{id:"annotated-session-title",className:`tf-field-shell ${a.textInput} ${a.sessionTitleInput}`,value:Fe,onChange:m=>{ot(m.target.value),Z(600)},placeholder:"Session title"}),t.jsx("span",{className:`tf-text-meta ${a.sessionTimestamp}`,children:Ma(e.updatedAt)})]}),oa(e)?t.jsxs("div",{className:`tf-text-secondary ${a.sessionCreator}`,children:["Created by ",oa(e)]}):null,t.jsxs("div",{className:a.sessionInstructionEditor,children:[t.jsx("label",{className:"tf-field-label",htmlFor:"annotated-session-instruction",children:"Session instruction"}),t.jsx("textarea",{id:"annotated-session-instruction",className:`tf-field-shell ${a.textArea} ${a.sessionInstructionField}`,value:He,onChange:m=>{it(m.target.value),Z(600)},placeholder:"Add overall instructions, context, or framing for this session."})]}),t.jsxs("div",{className:`tf-text-secondary ${a.annotationSummary}`,children:[e.annotations.length," annotation",e.annotations.length===1?"":"s"]})]}):t.jsxs("button",{type:"button",className:a.sessionCardButton,onClick:()=>{if(n){rt(!0);return}M("session-switch").then(m=>{m&&(Be(e.id),Ie(e,d))})},"aria-pressed":n,children:[t.jsxs("div",{className:a.sessionMeta,children:[t.jsx("span",{className:`tf-heading-card ${a.sessionTitle}`,children:c}),t.jsx("span",{className:`tf-text-meta ${a.sessionTimestamp}`,children:Ma(e.updatedAt)})]}),oa(e)?t.jsxs("div",{className:`tf-text-secondary ${a.sessionCreator}`,children:["Created by ",oa(e)]}):null,i?t.jsx("div",{className:`tf-text-secondary ${a.sessionInstructionPreview}`,children:i}):null,t.jsxs("div",{className:`tf-text-secondary ${a.annotationSummary}`,children:[e.annotations.length," annotation",e.annotations.length===1?"":"s"]})]}),n?t.jsx("div",{className:a.sessionCardFooter,children:t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",className:`tf-button-ghost ${a.toolRailButton} ${a.iconButton}`,onClick:()=>{ms()},disabled:te,"aria-label":"Duplicate session",title:`Duplicate session "${c}"`,children:t.jsx(Ea,{size:16})}),t.jsx("button",{type:"button",className:`tf-button-ghost ${a.toolRailButton} ${a.iconButton}`,onClick:()=>{bs()},disabled:te,"aria-label":"Delete session",title:`Delete session "${c}"`,children:t.jsx(Nn,{size:16})})]})}):null]},e.id)})}):t.jsxs("div",{className:a.emptyState,children:[t.jsx("strong",{className:"tf-empty-title",children:"No image selected"}),t.jsx("p",{className:"tf-empty-copy",children:"Open an image attachment from a task to start an annotated session."})]})]}),t.jsxs("section",{className:`tf-surface-panel ${a.panel} ${a.canvasPanel}`,children:[t.jsxs("div",{className:a.panelHeader,children:[t.jsxs("div",{className:a.canvasHeading,children:[t.jsx("div",{className:"tf-heading-card",children:d?.displayName||"Annotated attachment"}),t.jsx("div",{className:"tf-text-secondary",children:b?`${L.length} markers · ${Ls}`:"Pick or create a session"})]}),It?t.jsx(cr,{copied:Ot,onClick:()=>{ys()},title:d?.displayName||"Annotated attachment",ariaLabel:Ot?"Copied image reference":"Copy image reference",label:It}):null]}),t.jsxs("div",{className:a.toolRail,children:[t.jsxs("div",{className:`${a.toolbarCluster} ${a.toolbarViewportCluster}`,children:[t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:()=>{fs()},disabled:!b||te||!mn&&Y!=="error","aria-label":te?"Saving session":"Save session",title:te?"Saving session":"Save session",children:t.jsx(tr,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:()=>Ut(!0),disabled:dt,"aria-label":"Open image",title:"Open image",children:t.jsx(Cn,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:()=>{is()},disabled:Vt,"aria-label":Vt?"Pasting image":"Paste image",title:Vt?"Pasting image":"Paste image",children:Vt?t.jsx(jn,{size:18,className:Sn.spin}):t.jsx(ar,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:()=>{b&&os()},disabled:!b||!mn,"aria-label":"Reset unsaved changes",title:"Reset unsaved changes",children:t.jsx(nr,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:St,disabled:!d||q||N.width<=0||N.height<=0,"aria-label":"Fit image to viewport",title:"Fit image to viewport",children:t.jsx(sr,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost ${a.toolRailButton} ${a.iconButton}`,onClick:_s,disabled:!d||q||E<=.25,"aria-label":"Zoom out",children:t.jsx(rr,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:ks,disabled:!d||q||E===1,"aria-label":`Reset zoom to 100 percent (currently ${$a})`,title:`Reset zoom to 100% (currently ${$a})`,children:t.jsx("span",{children:$a})}),t.jsx("button",{type:"button",className:`tf-button-ghost ${a.toolRailButton} ${a.iconButton}`,onClick:vs,disabled:!d||q||E>=4,"aria-label":"Zoom in",children:t.jsx(or,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.toolBtn} ${a.toolbarButton} ${J?a.toolBtnActive:""}`,onClick:()=>ht(e=>!e),disabled:!d||q||!Ze,"aria-label":"Pan canvas",title:"Pan canvas",children:t.jsx(ir,{size:18})})]}),t.jsx("span",{className:a.toolbarSeparator,"aria-hidden":"true"}),t.jsxs("div",{className:a.toolbarActions,children:[t.jsx("div",{className:a.toolbarSelectionActions,children:ge?t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:ln,className:a.toolbarColorPicker,children:[t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton} ${a.colorPickerButton}`,onClick:()=>Mt(e=>!e),"aria-label":"Marker color","aria-expanded":Et,title:"Marker color",children:t.jsx("span",{className:a.colorPickerSwatch,style:{backgroundColor:ja},"aria-hidden":"true"})}),Et?t.jsx("div",{className:a.colorPickerPopover,role:"menu","aria-label":"Marker color options",children:tl.map(e=>t.jsx("button",{type:"button",className:`${a.colorOption} ${ja===e?a.colorOptionActive:""}`,style:{backgroundColor:e},onClick:()=>ds(e),"aria-label":`Use marker color ${e}`,"aria-pressed":ja===e},e))}):null]}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:Aa,"aria-label":"Delete marker",title:"Delete selected marker",children:t.jsx(Nn,{size:18})})]}):null}),t.jsxs("div",{className:a.toolbarUtilities,children:[t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.payloadBtn} ${a.toolbarButton}`,onClick:ps,disabled:!b||Bt,"aria-label":Bt?"Loading payload preview":"Preview payload",title:Bt?"Loading payload preview":"Preview payload",children:t.jsx(Ba,{size:18})}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:()=>Xa(!0),"aria-label":"How to use marker tools",title:"How to use marker tools",children:t.jsx(Fa,{size:18})})]})]})]}),t.jsxs("div",{className:a.canvasWorkspace,children:[t.jsx("div",{className:a.canvasToolRail,"aria-label":"Annotation tools",children:Ln.map(e=>{const n=e.icon;return t.jsx("button",{type:"button",className:`tf-button-ghost ${a.toolRailButton} ${A===e.value?a.toolBtnActive:""}`,onClick:()=>us(e.value),disabled:!d,title:e.label,"aria-label":`${e.label} tool. ${ra[e.value].short}`,children:t.jsx(n,{size:18})},e.value)})}),t.jsx("div",{className:a.canvasMain,children:t.jsx("div",{ref:ne,className:`tf-scrollbar ${a.canvasScroller}`,onScroll:()=>{Ke.current||(Ve.current=!1),ie()},children:d?t.jsxs(t.Fragment,{children:[q&&!mt?t.jsx("div",{className:a.canvasStatusOverlay,"aria-live":"polite",children:t.jsxs("div",{className:a.canvasStatusCard,children:[t.jsx(jn,{size:20,className:Sn.spinner}),t.jsx("span",{children:"Loading image…"})]})}):null,mt?t.jsx("div",{className:a.canvasStatusOverlay,"aria-live":"polite",children:t.jsx("div",{className:a.canvasStatusCard,children:t.jsx("span",{children:"Image failed to load."})})}):null,t.jsx("div",{className:a.canvasFrame,children:t.jsxs("div",{className:a.canvasMedia,style:{width:x.width?`${x.width}px`:void 0,height:x.height?`${x.height}px`:void 0},children:[t.jsx("img",{ref:wa,src:d.path,alt:d.displayName,className:a.canvasImage,onLoad:()=>{const e=wa.current;yt({width:e?.naturalWidth||0,height:e?.naturalHeight||0}),ut(!1),ft(!1)},onError:()=>{yt({width:0,height:0}),ut(!1),ft(!0)}}),!q&&!mt&&b?t.jsxs("div",{ref:an,className:`${a.overlay} ${A==="select"?a.overlaySelect:""} ${J?a.overlayPan:""}`,onPointerDown:zs,onPointerMove:Cs,onPointerUp:e=>{Ss(e),Ts()},"data-testid":"annotated-attachment-overlay",onPointerLeave:Ns,onPointerCancel:js,children:[t.jsx("svg",{className:a.overlaySvg,viewBox:Ta,preserveAspectRatio:"none","aria-hidden":"true",children:L.filter(e=>e.kind==="arrow").map(e=>{const n=ol(e,x),o=ia(e),c=R===e.id||lt===e.id;return t.jsxs(aa.Fragment,{children:[c?t.jsxs(t.Fragment,{children:[t.jsx("line",{x1:n.shaftX1,y1:n.shaftY1,x2:n.shaftX2,y2:n.shaftY2,stroke:"color-mix(in srgb, var(--surface-elevated) 92%, transparent)",strokeWidth:14,strokeLinecap:"round"}),t.jsx("polygon",{points:n.headPoints,fill:o,stroke:"color-mix(in srgb, var(--surface-elevated) 92%, transparent)",strokeWidth:4,strokeLinejoin:"round"})]}):null,t.jsx("line",{x1:n.shaftX1,y1:n.shaftY1,x2:n.shaftX2,y2:n.shaftY2,stroke:o,strokeWidth:c?10:6,strokeLinecap:"round"}),t.jsx("polygon",{points:n.headPoints,fill:o})]},e.id)})}),t.jsx("svg",{className:a.overlayHitLayer,viewBox:Ta,preserveAspectRatio:"none",children:L.filter(e=>e.kind==="arrow").map(e=>t.jsxs(aa.Fragment,{children:[t.jsx("line",{x1:e.x*x.width,y1:e.y*x.height,x2:e.x2*x.width,y2:e.y2*x.height,className:a.arrowHitArea,"data-testid":`annotated-arrow-hit-${e.id}`,"aria-label":`Arrow marker ${La.get(e.id)||0}`,onMouseEnter:()=>De(e.id),onMouseLeave:()=>De(null),onPointerDown:n=>wn(n,e),onClick:n=>{n.stopPropagation(),Nt(e.id)}}),R===e.id?t.jsxs(t.Fragment,{children:[t.jsx("circle",{cx:e.x*x.width,cy:e.y*x.height,r:Je.hitRadius,className:a.canvasHandleHit,role:"button",tabIndex:0,"aria-label":"Move arrow tail",onPointerDown:n=>In(n,e,"tail")}),t.jsx("circle",{cx:e.x*x.width,cy:e.y*x.height,r:Je.visibleRadius,className:a.canvasHandleVisible,"aria-hidden":"true"}),t.jsx("circle",{cx:e.x2*x.width,cy:e.y2*x.height,r:Je.hitRadius,className:a.canvasHandleHit,role:"button",tabIndex:0,"aria-label":"Move arrow tip",onPointerDown:n=>In(n,e,"tip")}),t.jsx("circle",{cx:e.x2*x.width,cy:e.y2*x.height,r:Je.visibleRadius,className:a.canvasHandleVisible,"aria-hidden":"true"})]}):null]},`hit-${e.id}`))}),L.filter(e=>e.kind==="arrow").map(e=>t.jsx("div",{className:`${a.annotationNumberBadge} ${a.arrowNumberBadge}`,style:{left:`${(e.x+e.x2)/2*100}%`,top:`${(e.y+e.y2)/2*100}%`,backgroundColor:ia(e)},"aria-hidden":"true",children:La.get(e.id)||0},`arrow-number-${e.id}`)),L.filter(e=>e.kind!=="arrow").map(e=>{const n=ia(e),o=La.get(e.id)||0,i={onPointerDown:c=>wn(c,e),onMouseEnter:()=>De(e.id),onMouseLeave:()=>De(null),onClick:c=>{c.stopPropagation(),Nt(e.id)}};return e.kind==="pin"?t.jsx("button",{type:"button",...i,className:`${a.pin} ${R===e.id?a.selected:""} ${lt===e.id?a.markerHovered:""}`,style:{left:`${e.x*100}%`,top:`${e.y*100}%`,backgroundColor:n},children:o},e.id):e.kind==="text-note"?t.jsx("button",{type:"button",...i,className:`${a.note} ${R===e.id?a.selected:""} ${lt===e.id?a.markerHovered:""}`,style:{left:`${e.x*100}%`,top:`${e.y*100}%`,backgroundColor:n},children:o},e.id):t.jsxs("div",{className:`${a.box} ${R===e.id?a.selected:""} ${lt===e.id?a.markerHovered:""}`,style:{left:`${e.x*100}%`,top:`${e.y*100}%`,width:`${e.width*100}%`,height:`${e.height*100}%`,borderColor:n},children:[t.jsx("span",{className:`${a.annotationNumberBadge} ${a.boxNumberBadge}`,style:{backgroundColor:n},"aria-hidden":"true",children:o}),t.jsx("button",{type:"button",...i,className:a.boxSurface,"aria-label":`Box marker ${o}`})]},e.id)}),t.jsx("svg",{className:a.overlaySvg,viewBox:Ta,preserveAspectRatio:"none",children:L.filter(e=>e.kind==="box"&&R===e.id).map(e=>t.jsxs(aa.Fragment,{children:[t.jsx("circle",{cx:(e.x+e.width)*x.width,cy:(e.y+e.height)*x.height,r:Je.hitRadius,className:`${a.canvasHandleHit} ${a.canvasResizeHandleHit}`,role:"button",tabIndex:0,"aria-label":"Resize box marker",onPointerDown:n=>$s(n,e)}),t.jsx("circle",{cx:(e.x+e.width)*x.width,cy:(e.y+e.height)*x.height,r:Je.visibleRadius,className:a.canvasHandleVisible,"aria-hidden":"true"})]},`box-handle-${e.id}`))})]}):null]})})]}):t.jsx("div",{className:a.emptyState,children:t.jsx("p",{className:"tf-empty-copy",children:"Select an image attachment to annotate."})})})})]}),t.jsxs("div",{className:a.statusBar,children:[t.jsx("span",{children:Y==="error"?"Save failed. Retry now.":Y==="saving"||Y==="pending"?"Saving…":"Saved"}),Ga?t.jsx("span",{children:Ga}):t.jsx("span",{children:b?J?"Drag on the image to pan.":A==="select"?"Select a marker to edit it.":`Click on the image to place a ${A}.`:"Create a session to begin placing markers on this image."}),d&&!b&&Vn?t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn} ${a.toolbarButton}`,onClick:()=>{bn()},disabled:te||Pt,children:te?"Creating…":"Create one now"}):null]})]}),t.jsx("section",{className:`tf-surface-panel ${a.panel} ${a.detailPanel}`,children:b?t.jsxs(t.Fragment,{children:[t.jsx("div",{className:a.panelHeader,children:t.jsxs("div",{className:a.panelHeaderText,children:[t.jsx("div",{className:`tf-heading-card ${a.panelTitle}`,children:"Markers"}),t.jsxs("div",{className:"tf-text-secondary",children:[L.length," in this session"]})]})}),t.jsxs(Es,{sensors:rs,collisionDetection:Ms,onDragStart:ws,onDragEnd:Is,onDragCancel:()=>da(null),children:[t.jsx("div",{className:`tf-scrollbar ${a.annotationList}`,children:L.length===0?t.jsx("div",{className:a.detailEmpty,children:t.jsx("p",{className:"tf-empty-copy",children:"Add a marker on the image to begin."})}):t.jsx(Ps,{items:L.map(e=>e.id),strategy:Bs,children:L.map((e,n)=>{const o=Rn[e.kind],i=An[e.kind],c=`${i} ${n+1}`,m=el[e.markerType||ye],z=$n.find(k=>k.value===(e.markerType||ye))?.label||"Review",u=R===e.id,h=u&&!ct;return t.jsx(Zi,{id:e.id,children:({attributes:k,listeners:w,setNodeRef:S,transform:K,transition:Le,isDragging:jt})=>t.jsxs("div",{className:`tf-surface-elevated ${a.annotationCard} ${u?a.annotationCardActive:""} ${lt===e.id?a.annotationCardHovered:""} ${jt?a.annotationCardDragging:""}`,"data-testid":`annotation-card-${e.id}`,ref:C=>{S(C),C?Na.current.set(e.id,C):Na.current.delete(e.id)},style:{...u?{"--annotation-card-accent":ia(e)}:{},transform:Fs.Transform.toString(K),transition:Le},onBlur:C=>{C.currentTarget.contains(C.relatedTarget)||ee(!0)},onMouseEnter:()=>De(e.id),onMouseLeave:()=>De(null),children:[t.jsxs("div",{className:a.annotationMeta,children:[t.jsx("button",{type:"button",className:a.annotationDragHandle,"aria-label":`Reorder ${c}`,title:"Drag to reorder. Press Space, then use the arrow keys to reorder with the keyboard.",...k,...w,children:t.jsx(Tn,{size:16})}),t.jsx("button",{type:"button",className:a.annotationCardButton,onClick:()=>{xs(e.id)},"aria-label":i,"aria-expanded":h,children:t.jsx("span",{className:`tf-heading-card ${a.annotationTitle}`,children:c})}),t.jsx("span",{className:`tf-text-meta ${a.annotationKind}`,"aria-hidden":"true",children:t.jsx(o,{size:16})})]}),h?t.jsxs("div",{className:a.annotationInstructionEditor,children:[t.jsx("label",{className:"tf-field-label",htmlFor:"annotated-marker-instruction",children:"Marker instruction"}),t.jsx("textarea",{id:"annotated-marker-instruction",ref:u?nn:null,className:`tf-field-shell ${a.textArea} ${a.annotationInstructionField}`,value:e.instruction,onChange:C=>{le(e.id,ze=>({...ze,instruction:C.target.value}),600)},onBlur:()=>{M("text")},placeholder:"What should the AI focus on for this marker?"}),t.jsxs("div",{className:a.annotationTypeField,children:[t.jsx("label",{className:"tf-field-label",htmlFor:"annotated-marker-type",children:"Instruction type"}),t.jsx("select",{id:"annotated-marker-type",className:`tf-field-shell ${a.select}`,value:e.markerType||ye,onChange:C=>{le(e.id,ze=>il(ze,C.target.value))},children:$n.map(C=>t.jsx("option",{value:C.value,children:C.label},C.value))})]}),t.jsxs("details",{className:a.annotationGeometryDetails,children:[t.jsx("summary",{className:"tf-field-label",children:"Precise placement"}),t.jsx("div",{className:a.annotationGeometryFields,"aria-label":"Marker geometry percent controls",children:fl(e).map(C=>t.jsxs("label",{className:a.annotationGeometryField,children:[t.jsx("span",{className:`tf-text-meta ${a.annotationGeometryLabel}`,children:C.label}),t.jsx("input",{className:`tf-field-shell ${a.annotationGeometryInput}`,type:"number",min:0,max:100,step:.1,value:C.value,onChange:ze=>{const ta=ul(ze.target.value);ta!==null&&le(e.id,Rs=>ml(Rs,C.key,ta))},"aria-label":`${C.label} percent`})]},C.key))})]})]}):t.jsx("button",{type:"button",className:a.annotationInstructionButton,onClick:()=>{Nt(e.id)},"aria-label":`Edit ${i} instruction`,children:t.jsxs("div",{className:a.annotationInstructionEditor,children:[e.instruction.trim()?t.jsx("div",{className:`tf-text-secondary ${a.annotationInstructionPreview}`,children:e.instruction.trim()}):null,t.jsx("div",{className:a.annotationPreviewFooter,children:t.jsx("span",{className:`tf-text-meta ${a.annotationInstructionTypeIcon}`,"aria-label":`Instruction type: ${z}`,title:z,children:t.jsx(m,{size:16})})})]})})]})},e.id)})})}),t.jsx(Hs,{children:kt?t.jsxs("div",{className:`tf-surface-elevated ${a.annotationCard} ${a.annotationDragOverlay}`,"data-testid":"annotation-drag-overlay",children:[t.jsxs("div",{className:a.annotationMeta,children:[t.jsx(Tn,{size:16,className:a.annotationDragOverlayGrip}),t.jsx("span",{className:`tf-heading-card ${a.annotationTitle} ${a.annotationDragOverlayTitle}`,children:An[kt.kind]}),t.jsx("span",{className:`tf-text-meta ${a.annotationKind}`,"aria-hidden":"true",children:aa.createElement(Rn[kt.kind],{size:16})})]}),kt.instruction.trim()?t.jsx("div",{className:`tf-text-secondary ${a.annotationInstructionPreview}`,children:kt.instruction.trim()}):null]}):null})]})]}):t.jsxs("div",{className:a.emptyState,children:[t.jsx("strong",{className:"tf-empty-title",children:"No active session"}),t.jsx("p",{className:"tf-empty-copy",children:"Create or select a session to edit annotations."})]})}),t.jsx(sa,{isOpen:Jn,onClose:()=>{dt||(Ut(!1),Gt(""))},title:"Open Image",size:"sm",children:t.jsxs("form",{className:a.openImageModalBody,onSubmit:e=>{e.preventDefault(),ls()},children:[t.jsx("label",{className:"tf-field-label",htmlFor:"annotated-open-image-reference",children:"Image reference number"}),t.jsx("input",{id:"annotated-open-image-reference",className:`tf-field-shell ${a.textInput} ${a.openImageField}`,value:xa,onChange:e=>Gt(e.target.value),placeholder:"I-24",autoFocus:!0}),t.jsxs("div",{className:a.openImageActions,children:[t.jsx("button",{type:"button",className:"tf-button-ghost tf-button-compact",onClick:()=>{Ut(!1),Gt("")},disabled:dt,children:"Cancel"}),t.jsx("button",{type:"submit",className:"tf-button-primary tf-button-compact",disabled:dt,children:dt?"Opening…":"Open"})]})]})}),t.jsx(sa,{isOpen:Xn,onClose:()=>Xa(!1),title:"How To Use Markers",size:"md",children:t.jsx("div",{className:a.markerHelpModalBody,children:Ln.filter(e=>e.value!=="select").map(e=>t.jsxs("div",{className:`tf-surface-inset ${a.markerHelpItem}`,children:[t.jsxs("div",{className:a.markerHelpHeader,children:[t.jsx("strong",{className:"tf-heading-card",children:e.label}),t.jsx("span",{className:"tf-text-meta",children:ra[e.value].short})]}),t.jsx("p",{className:"tf-text-secondary",children:ra[e.value].detail}),t.jsx("p",{className:`tf-text-body ${a.markerHelpExample}`,children:ra[e.value].example})]},e.value))})}),t.jsx(sa,{isOpen:Yn,onClose:()=>{Ue||Ft(!1)},title:"Link Session to Task",size:"sm",children:t.jsxs("div",{className:a.taskLinkModalBody,children:[t.jsx("p",{className:"tf-text-secondary",children:"This links the review session only. The image stays unattached."}),t.jsx("input",{className:`tf-field-shell ${a.textInput}`,value:ha,onChange:e=>Wa(e.target.value),placeholder:"Search tasks...","aria-label":"Search tasks",autoFocus:!0}),Ht?t.jsx("div",{className:a.detailEmpty,children:t.jsx("p",{className:"tf-empty-copy",children:"Loading tasks…"})}):dn.length===0?t.jsx("div",{className:a.detailEmpty,children:t.jsx("p",{className:"tf-empty-copy",children:"No tasks match your search."})}):t.jsx("div",{className:`tf-scrollbar ${a.taskLinkList}`,children:dn.map(e=>{const n=String(e.referenceLabel||e.id).trim()||e.id,o=e.id===b?.taskId;return t.jsxs("button",{type:"button",className:`tf-surface-elevated ${a.taskLinkOption} ${o?a.taskLinkOptionActive:""}`,onClick:()=>{Ra(e.id)},disabled:Ue||o,children:[t.jsx("span",{className:a.taskLinkOptionTitle,children:e.title}),t.jsxs("span",{className:"tf-text-meta",children:[n,o?" · Linked":""]})]},e.id)})}),t.jsxs("div",{className:a.taskLinkActions,children:[t.jsx("button",{type:"button",className:"tf-button-ghost tf-button-compact",onClick:()=>Ft(!1),disabled:Ue,children:"Cancel"}),b?.taskId?t.jsx("button",{type:"button",className:"tf-button-ghost tf-button-compact",onClick:()=>{Ra(null)},disabled:Ue,children:"Unlink"}):null]})]})}),t.jsx(sa,{isOpen:Wn,onClose:()=>fa(!1),title:"AI Payload",size:"lg",children:t.jsxs("div",{className:a.payloadModalBody,children:[t.jsxs("div",{className:a.payloadModalToolbar,children:[t.jsxs("div",{className:a.payloadViewToggle,children:[t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.toolBtn} ${pa==="json"?a.toolBtnActive:""}`,onClick:()=>Va("json"),children:"JSON"}),t.jsx("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.toolBtn} ${pa==="brief"?a.toolBtnActive:""}`,onClick:()=>Va("brief"),children:"AI Brief"})]}),t.jsxs("div",{className:a.payloadModalActions,children:[t.jsxs("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn}`,onClick:()=>{vn("json")},disabled:!pe,"aria-label":xe==="json"?"Copied JSON":"Copy JSON",title:xe==="json"?"Copied JSON":"Copy JSON",children:[xe==="json"?t.jsx(Ha,{size:16}):t.jsx(Ea,{size:16}),t.jsx("span",{children:"JSON"})]}),t.jsxs("button",{type:"button",className:`tf-button-ghost tf-button-compact ${a.ghostBtn}`,onClick:()=>{vn("brief")},disabled:!pe,"aria-label":xe==="brief"?"Copied AI Brief":"Copy AI Brief",title:xe==="brief"?"Copied AI Brief":"Copy AI Brief",children:[xe==="brief"?t.jsx(Ha,{size:16}):t.jsx(Ea,{size:16}),t.jsx("span",{children:"AI Brief"})]})]})]}),Bt?t.jsx("div",{className:a.detailEmpty,children:t.jsx("p",{className:"tf-empty-copy",children:"Loading payload…"})}):pe?t.jsx("pre",{className:`tf-surface-inset tf-scrollbar ${a.payloadModalPreview}`,children:pa==="json"?JSON.stringify(pe,null,2):Mn(pe)}):t.jsx("div",{className:a.detailEmpty,children:t.jsx("p",{className:"tf-empty-copy",children:"Load a payload preview to inspect the current session contract."})})]})})]})}export{Il as AnnotatedAttachmentWorkspaceShell};
@@ -1 +1 @@
1
- import{R as _,j as o}from"./vendor-react-CKJs5o3c.js";import{j as k}from"./index-I5zhdtgt.js";import{aj as v,a as I,A as N,v as j,u as x}from"./vendor-icons-D9Lpw-j4.js";const y=[{value:"updated",label:"Updated"},{value:"reference",label:"Reference"},{value:"name",label:"Name"},{value:"size",label:"Size"},{value:"created",label:"Created"}];function g(e){if(typeof e?.referenceNumber=="number"&&Number.isFinite(e.referenceNumber))return e.referenceNumber;const r=String(e?.referenceLabel||e?.imageReferenceLabel||"").match(/(\d+)/);return r?parseInt(r[1],10):0}function w(e){if(!e)return"";const t=e.displayName||e.title||e.originalFilename||e.fsPath||e.path||e.storageKey||"";return String(t).toLowerCase()}function A(e){return k(e).toLowerCase()}function m(e,t){return String(t(e)||"").toLowerCase()}function S(e){const t=e?.sizeBytes;return typeof t=="number"&&Number.isFinite(t)?t:0}function p(e,t){const r=e?.createdAt,u=e?.updatedAt,a=t?r||u:u||r;if(!a)return 0;const n=Date.parse(String(a));return Number.isNaN(n)?0:n}function C(e,t,r,u,a=w){let n=0;if(r==="reference"){const l=g(e),d=g(t);n=l-d,n===0&&(n=m(e,a).localeCompare(m(t,a)))}else r==="name"?n=m(e,a).localeCompare(m(t,a)):r==="size"?n=S(e)-S(t):r==="created"?n=p(e,!0)-p(t,!0):n=p(e,!1)-p(t,!1);return n!==0?u==="desc"?-n:n:(n=g(t)-g(e),n!==0?n:m(e,a).localeCompare(m(t,a)))}function D(e,t,r,u){return[...e].sort((a,n)=>C(a,n,t,r,u))}function q(e,t,r){return D(e,t,r,A)}const R="_root_7pmuk_1",O="_trigger_7pmuk_9",T="_directionToggle_7pmuk_10",z="_triggerOpen_7pmuk_38",$="_triggerLabel_7pmuk_45",F="_menu_7pmuk_51",E="_menuLabel_7pmuk_64",P="_menuItem_7pmuk_72",U="_menuItemActive_7pmuk_94",K="_menuItemLabel_7pmuk_99",c={root:R,trigger:O,directionToggle:T,triggerOpen:z,triggerLabel:$,menu:F,menuLabel:E,menuItem:P,menuItemActive:U,menuItemLabel:K};function G({field:e,order:t,onFieldChange:r,onOrderChange:u,className:a}){const[n,l]=_.useState(!1),d=_.useRef(null),f=y.find(s=>s.value===e)??y[0],L=t==="desc"?N:j;_.useEffect(()=>{if(!n)return;const s=b=>{d.current?.contains(b.target)||l(!1)},i=b=>{b.key==="Escape"&&l(!1)};return document.addEventListener("mousedown",s),document.addEventListener("keydown",i),()=>{document.removeEventListener("mousedown",s),document.removeEventListener("keydown",i)}},[n]);const h=s=>{r(s),l(!1)};return o.jsxs("div",{ref:d,className:`${c.root} ${a||""}`.trim(),children:[o.jsxs("button",{type:"button",className:`${c.trigger} ${n?c.triggerOpen:""}`.trim(),onClick:()=>l(s=>!s),"aria-haspopup":"menu","aria-expanded":n,"aria-label":`Sort tray by ${f.label}`,title:`Sort by ${f.label}`,children:[o.jsx(v,{size:13}),o.jsx("span",{className:c.triggerLabel,children:f.label}),o.jsx(I,{size:13})]}),o.jsx("button",{type:"button",className:c.directionToggle,onClick:()=>u(t==="desc"?"asc":"desc"),"aria-label":`Sort tray ${t==="desc"?"descending":"ascending"}`,title:t==="desc"?"Sort descending":"Sort ascending",children:o.jsx(L,{size:13})}),n?o.jsxs("div",{className:c.menu,role:"menu","aria-label":"Sort tray items",children:[o.jsx("div",{className:c.menuLabel,children:"Sort by"}),y.map(s=>{const i=s.value===e;return o.jsxs("button",{type:"button",role:"menuitemradio","aria-checked":i,className:`${c.menuItem} ${i?c.menuItemActive:""}`.trim(),onClick:()=>h(s.value),children:[o.jsx("span",{className:c.menuItemLabel,children:s.label}),i?o.jsx(x,{size:13}):null]},s.value)})]}):null]})}export{G as A,q as a,D as s};
1
+ import{R as _,j as o}from"./vendor-react-CKJs5o3c.js";import{j as k}from"./index-DSQINwt9.js";import{aj as v,a as I,A as N,v as j,u as x}from"./vendor-icons-Bsq-mcEn.js";const y=[{value:"updated",label:"Updated"},{value:"reference",label:"Reference"},{value:"name",label:"Name"},{value:"size",label:"Size"},{value:"created",label:"Created"}];function g(e){if(typeof e?.referenceNumber=="number"&&Number.isFinite(e.referenceNumber))return e.referenceNumber;const r=String(e?.referenceLabel||e?.imageReferenceLabel||"").match(/(\d+)/);return r?parseInt(r[1],10):0}function w(e){if(!e)return"";const t=e.displayName||e.title||e.originalFilename||e.fsPath||e.path||e.storageKey||"";return String(t).toLowerCase()}function A(e){return k(e).toLowerCase()}function m(e,t){return String(t(e)||"").toLowerCase()}function S(e){const t=e?.sizeBytes;return typeof t=="number"&&Number.isFinite(t)?t:0}function p(e,t){const r=e?.createdAt,u=e?.updatedAt,a=t?r||u:u||r;if(!a)return 0;const n=Date.parse(String(a));return Number.isNaN(n)?0:n}function C(e,t,r,u,a=w){let n=0;if(r==="reference"){const l=g(e),d=g(t);n=l-d,n===0&&(n=m(e,a).localeCompare(m(t,a)))}else r==="name"?n=m(e,a).localeCompare(m(t,a)):r==="size"?n=S(e)-S(t):r==="created"?n=p(e,!0)-p(t,!0):n=p(e,!1)-p(t,!1);return n!==0?u==="desc"?-n:n:(n=g(t)-g(e),n!==0?n:m(e,a).localeCompare(m(t,a)))}function D(e,t,r,u){return[...e].sort((a,n)=>C(a,n,t,r,u))}function q(e,t,r){return D(e,t,r,A)}const R="_root_7pmuk_1",O="_trigger_7pmuk_9",T="_directionToggle_7pmuk_10",z="_triggerOpen_7pmuk_38",$="_triggerLabel_7pmuk_45",F="_menu_7pmuk_51",E="_menuLabel_7pmuk_64",P="_menuItem_7pmuk_72",U="_menuItemActive_7pmuk_94",K="_menuItemLabel_7pmuk_99",c={root:R,trigger:O,directionToggle:T,triggerOpen:z,triggerLabel:$,menu:F,menuLabel:E,menuItem:P,menuItemActive:U,menuItemLabel:K};function G({field:e,order:t,onFieldChange:r,onOrderChange:u,className:a}){const[n,l]=_.useState(!1),d=_.useRef(null),f=y.find(s=>s.value===e)??y[0],L=t==="desc"?N:j;_.useEffect(()=>{if(!n)return;const s=b=>{d.current?.contains(b.target)||l(!1)},i=b=>{b.key==="Escape"&&l(!1)};return document.addEventListener("mousedown",s),document.addEventListener("keydown",i),()=>{document.removeEventListener("mousedown",s),document.removeEventListener("keydown",i)}},[n]);const h=s=>{r(s),l(!1)};return o.jsxs("div",{ref:d,className:`${c.root} ${a||""}`.trim(),children:[o.jsxs("button",{type:"button",className:`${c.trigger} ${n?c.triggerOpen:""}`.trim(),onClick:()=>l(s=>!s),"aria-haspopup":"menu","aria-expanded":n,"aria-label":`Sort tray by ${f.label}`,title:`Sort by ${f.label}`,children:[o.jsx(v,{size:13}),o.jsx("span",{className:c.triggerLabel,children:f.label}),o.jsx(I,{size:13})]}),o.jsx("button",{type:"button",className:c.directionToggle,onClick:()=>u(t==="desc"?"asc":"desc"),"aria-label":`Sort tray ${t==="desc"?"descending":"ascending"}`,title:t==="desc"?"Sort descending":"Sort ascending",children:o.jsx(L,{size:13})}),n?o.jsxs("div",{className:c.menu,role:"menu","aria-label":"Sort tray items",children:[o.jsx("div",{className:c.menuLabel,children:"Sort by"}),y.map(s=>{const i=s.value===e;return o.jsxs("button",{type:"button",role:"menuitemradio","aria-checked":i,className:`${c.menuItem} ${i?c.menuItemActive:""}`.trim(),onClick:()=>h(s.value),children:[o.jsx("span",{className:c.menuItemLabel,children:s.label}),i?o.jsx(x,{size:13}):null]},s.value)})]}):null]})}export{G as A,q as a,D as s};