@taskforcehq/taskforce 0.3.306 → 0.3.308
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.
- package/README.md +0 -2
- package/dist/Taskforce.module.css +317 -27
- package/dist/TaskforceCore.js +1 -0
- package/dist/TaskforceCore.test.js +178 -0
- package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.js +15 -3
- package/dist/components/features/AgentsModule.d.ts +5 -1
- package/dist/components/features/AgentsModule.js +142 -39
- package/dist/components/features/AgentsModule.test.js +260 -11
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +3 -1
- package/dist/components/features/DocumentViewer.js +6 -5
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +20 -3
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +6 -2
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +14 -64
- package/dist/components/task/TaskKanban.js +0 -8
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.d.ts +20 -15
- package/dist/components/views/PlanComparisonPage.js +221 -82
- package/dist/components/views/PlanComparisonPage.test.js +268 -14
- package/dist/components/views/PlansPage.js +16 -10
- package/dist/components/views/PlansPage.test.js +4 -2
- package/dist/components/views/StandaloneLayout.js +256 -69
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +19 -6
- package/dist/components/views/panels/PlanningDrawer.js +259 -51
- package/dist/components/views/panels/PlanningDrawer.test.js +392 -4
- package/dist/config/envSchema.js +1 -0
- package/dist/core/AiProfileService.d.ts +7 -0
- package/dist/core/AiProfileService.js +460 -35
- package/dist/core/AiProfiles.test.js +648 -2
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +58 -13
- package/dist/core/GlobalSettingsService.js +30 -0
- package/dist/core/GlobalSettingsService.test.d.ts +1 -0
- package/dist/core/GlobalSettingsService.test.js +45 -0
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- package/dist/core/PlanEntitlementService.d.ts +20 -0
- package/dist/core/PlanEntitlementService.js +215 -19
- package/dist/core/PlanFeatureCatalog.test.js +55 -0
- package/dist/core/PlanningEntities.test.js +366 -4
- package/dist/core/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +204 -26
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +781 -71
- package/dist/core/Taskforce.mcpAuth.test.js +109 -0
- package/dist/core/types.d.ts +10 -0
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +2 -1
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +3 -3
- package/dist/hooks/sync/orchestratorShared.js +61 -1
- package/dist/hooks/sync/recovery.js +8 -0
- package/dist/hooks/sync/recovery.test.js +5 -5
- package/dist/hooks/sync/transfers.d.ts +2 -1
- package/dist/hooks/sync/transfers.js +36 -9
- package/dist/hooks/sync/transfers.test.js +534 -2
- package/dist/hooks/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.js +50 -5
- package/dist/hooks/useTaskforce.d.ts +85 -50
- package/dist/hooks/useTaskforce.js +44 -14
- package/dist/hooks/useTaskforce.runtime-routing.test.js +94 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +99 -0
- package/dist/hooks/useWorkspaceSyncController.js +7 -1
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +14 -7
- package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +113 -7
- package/dist/mcp/runtime.d.ts +1 -0
- package/dist/mcp/runtime.js +969 -122
- package/dist/mcp/runtime.test.js +1083 -11
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.js +58 -15
- package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +66 -7
- package/dist/server/index.js +4 -0
- package/dist/server/index.test.js +6 -1
- package/dist/server/routes/admin.js +328 -9
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +11 -0
- package/dist/server/routes/auth.js +189 -27
- package/dist/server/routes/authSupport.d.ts +5 -0
- package/dist/server/routes/authSupport.js +13 -1
- package/dist/server/routes/billing.d.ts +1 -0
- package/dist/server/routes/billing.js +116 -63
- package/dist/server/routes/billing.test.js +162 -11
- package/dist/server/routes/documents.js +10 -0
- package/dist/server/routes/shared.js +0 -10
- package/dist/server/routes/sync.integration.test.js +221 -0
- package/dist/server/routes/sync.js +13 -3
- package/dist/server/routes/syncSnapshotRoutes.js +2 -0
- package/dist/server/routes/tasks.js +12 -9
- package/dist/server/routes.js +87 -8
- package/dist/server/routes.test.js +972 -23
- package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- package/dist/storage/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- package/dist/sync/collaborationSyncPayload.js +2 -0
- package/dist/sync/collaborationSyncPayload.test.js +1 -0
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +5 -1
- package/dist/sync/contentSyncState.js +231 -37
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +4 -4
- package/dist/sync/syncApplyHandlers.js +89 -31
- package/dist/sync/syncApplyHandlers.test.js +184 -4
- package/dist/sync/syncResourceAdapters.d.ts +2 -0
- package/dist/sync/syncResourceAdapters.js +2 -0
- package/dist/sync/syncService.d.ts +1 -0
- package/dist/sync/syncService.js +13 -1
- package/dist/sync/syncService.test.js +39 -0
- package/dist/sync/workspacePullFeed.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +129 -70
- package/dist/sync/workspacePullFeed.test.js +49 -0
- package/dist/sync/workspaceSyncModel.d.ts +28 -6
- package/dist/sync/workspaceSyncModel.js +159 -45
- package/dist/sync/workspaceSyncModel.test.js +269 -3
- package/dist/types.d.ts +33 -2
- package/dist/ui/agent-logos/ChatGPT.png +0 -0
- package/dist/ui/agent-logos/Gemini CLI.jpeg +0 -0
- package/dist/ui/agent-logos/antigravity.jpeg +0 -0
- package/dist/ui/agent-logos/claude-code.jpeg +0 -0
- package/dist/ui/agent-logos/codex.jpeg +0 -0
- package/dist/ui/agent-logos/cursor.png +0 -0
- package/dist/ui/agent-logos/openclaw.jpeg +0 -0
- package/dist/ui/agent-logos/windsurf.png +0 -0
- package/dist/ui/assets/AgentsModule-BS4Pi_nC.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CCckzWYZ.js +3 -0
- package/dist/ui/assets/ContextAttachmentManager-CfG_ER7C.js +3 -0
- package/dist/ui/assets/DocumentWorkspace-BVaWPA25.js +252 -0
- package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-DSj0ThaK.js +1 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/{InitiativesModule-9E6ParrY.js → InitiativesModule-AxMkWtxH.js} +1 -1
- package/dist/ui/assets/PlansPage-B_z-D6Nh.css +1 -0
- package/dist/ui/assets/PlansPage-Ndt7mYfo.js +1 -0
- package/dist/ui/assets/TaskContextUpload-Dw4rTF4i.js +1 -0
- package/dist/ui/assets/TaskSettings-f2ga42_V.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BA7jcEpH.js → WorkflowsModule-E4UL3mov.js} +4 -4
- package/dist/ui/assets/documentReferences-BOUcJm6-.js +1 -0
- package/dist/ui/assets/index-BvAbqx5Q.css +1 -0
- package/dist/ui/assets/index-MAHKvFqp.js +4 -0
- package/dist/ui/assets/{vendor-icons-DuEd_65c.js → vendor-icons-B32hGuF2.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/ui/og-image.png +0 -0
- package/dist/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +6 -0
- package/dist/utils/assignees.js +8 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -0
- package/dist/utils/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- package/dist/utils/taskActivity.d.ts +7 -1
- package/dist/utils/taskActivity.js +63 -1
- package/dist/utils/taskActivity.test.js +23 -1
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- package/package.json +1 -1
- package/dist/ui/assets/AgentsModule-DrLawwNl.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-Z9_whf7F.js +0 -3
- package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +0 -252
- package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +0 -1
- package/dist/ui/assets/PlansPage-CvfnMiWq.css +0 -1
- package/dist/ui/assets/PlansPage-DRXscYxH.js +0 -1
- package/dist/ui/assets/TaskSettings-DZX4jk7e.js +0 -9
- package/dist/ui/assets/index-9eT8e0Lu.css +0 -1
- package/dist/ui/assets/index-C6k75jr8.js +0 -6
|
@@ -50,6 +50,8 @@ describe('workspaceSyncModel', () => {
|
|
|
50
50
|
taskEvents: [
|
|
51
51
|
{
|
|
52
52
|
id: 'task-event-1',
|
|
53
|
+
entityType: 'task',
|
|
54
|
+
entityId: 'task-1',
|
|
53
55
|
taskId: 'task-1',
|
|
54
56
|
workspaceId: 'workspace-a',
|
|
55
57
|
action: 'task-status-changed',
|
|
@@ -91,6 +93,8 @@ describe('workspaceSyncModel', () => {
|
|
|
91
93
|
taskEvents: [
|
|
92
94
|
{
|
|
93
95
|
id: 'task-event-keep',
|
|
96
|
+
entityType: 'task',
|
|
97
|
+
entityId: 'task-1',
|
|
94
98
|
taskId: 'task-1',
|
|
95
99
|
workspaceId: 'workspace-a',
|
|
96
100
|
action: 'task-status-changed',
|
|
@@ -100,6 +104,8 @@ describe('workspaceSyncModel', () => {
|
|
|
100
104
|
},
|
|
101
105
|
{
|
|
102
106
|
id: 'task-event-new',
|
|
107
|
+
entityType: 'task',
|
|
108
|
+
entityId: 'task-2',
|
|
103
109
|
taskId: 'task-2',
|
|
104
110
|
workspaceId: 'workspace-a',
|
|
105
111
|
action: 'task-archived',
|
|
@@ -147,6 +153,41 @@ describe('workspaceSyncModel', () => {
|
|
|
147
153
|
['docs/new.md', '2026-02-03T00:00:00.000Z']
|
|
148
154
|
]);
|
|
149
155
|
});
|
|
156
|
+
it('emits a document upsert when a synced document receives a newer task link', () => {
|
|
157
|
+
const payload = buildWorkspaceSyncPayloadModel({
|
|
158
|
+
tasks: [],
|
|
159
|
+
archivedTasks: [],
|
|
160
|
+
lastPushedTaskIds: new Set(),
|
|
161
|
+
pendingDeletedTaskIds: new Set(),
|
|
162
|
+
documents: [
|
|
163
|
+
{
|
|
164
|
+
path: 'workspaces/default/assets/documents/asset-doc-1-notes.md',
|
|
165
|
+
updatedAt: '2026-03-18T14:45:00.000Z',
|
|
166
|
+
content: '# Notes',
|
|
167
|
+
assetId: 'asset-doc-1',
|
|
168
|
+
documentId: 'doc-1',
|
|
169
|
+
referenceNumber: 8,
|
|
170
|
+
version: 1,
|
|
171
|
+
taskId: 'task-attach-1',
|
|
172
|
+
originalFilename: 'notes.md',
|
|
173
|
+
linkRole: 'attachment'
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
lastPushedDocumentPaths: new Set(['workspaces/default/assets/documents/asset-doc-1-notes.md']),
|
|
177
|
+
lastPushedDocumentWatermarks: new Map([
|
|
178
|
+
['workspaces/default/assets/documents/asset-doc-1-notes.md', '2026-03-18T13:30:00.000Z']
|
|
179
|
+
])
|
|
180
|
+
});
|
|
181
|
+
expect(payload.changes).toEqual(expect.arrayContaining([
|
|
182
|
+
expect.objectContaining({
|
|
183
|
+
op: 'document-upsert',
|
|
184
|
+
path: 'workspaces/default/assets/documents/asset-doc-1-notes.md',
|
|
185
|
+
updatedAt: '2026-03-18T14:45:00.000Z',
|
|
186
|
+
taskId: 'task-attach-1',
|
|
187
|
+
linkRole: 'attachment'
|
|
188
|
+
})
|
|
189
|
+
]));
|
|
190
|
+
});
|
|
150
191
|
it('reports send-all diagnostics when a domain has no baseline', () => {
|
|
151
192
|
const payload = buildWorkspaceSyncPayloadModel({
|
|
152
193
|
tasks: [],
|
|
@@ -385,6 +426,8 @@ describe('workspaceSyncModel', () => {
|
|
|
385
426
|
provider: 'OpenAI',
|
|
386
427
|
model: 'gpt-5.4',
|
|
387
428
|
surfaceType: 'coding_tool',
|
|
429
|
+
avatarRevision: 0,
|
|
430
|
+
avatarUpdatedAt: null,
|
|
388
431
|
rosterStateUpdatedAt: '2026-03-22T10:00:00.000Z'
|
|
389
432
|
})
|
|
390
433
|
})
|
|
@@ -443,6 +486,8 @@ describe('workspaceSyncModel', () => {
|
|
|
443
486
|
color: '#0ea5e9',
|
|
444
487
|
avatarUrl: '/api/taskforce/context/workspaces%2Fws-1%2Fassets%2Fimages%2Fai-profiles%2Fai-profile-1%2Favatar%2Favatar.webp',
|
|
445
488
|
avatarSourceUrl: '/api/taskforce/context/workspaces%2Fws-1%2Fassets%2Fimages%2Fai-profiles%2Fai-profile-1%2Favatar%2Fsource.webp',
|
|
489
|
+
avatarRevision: 1,
|
|
490
|
+
avatarUpdatedAt: '2026-03-22T10:04:00.000Z',
|
|
446
491
|
description: 'Terminal-first coding agent',
|
|
447
492
|
role: 'Implementer',
|
|
448
493
|
provider: 'OpenAI',
|
|
@@ -463,7 +508,9 @@ describe('workspaceSyncModel', () => {
|
|
|
463
508
|
profile: expect.objectContaining({
|
|
464
509
|
id: 'ai-profile-1',
|
|
465
510
|
avatarUrl: expect.stringContaining('/api/taskforce/context/'),
|
|
466
|
-
avatarSourceUrl: expect.stringContaining('/api/taskforce/context/')
|
|
511
|
+
avatarSourceUrl: expect.stringContaining('/api/taskforce/context/'),
|
|
512
|
+
avatarRevision: 1,
|
|
513
|
+
avatarUpdatedAt: '2026-03-22T10:04:00.000Z'
|
|
467
514
|
})
|
|
468
515
|
})
|
|
469
516
|
]));
|
|
@@ -478,6 +525,8 @@ describe('workspaceSyncModel', () => {
|
|
|
478
525
|
color: '#0ea5e9',
|
|
479
526
|
avatarUrl: '/api/taskforce/context/workspaces%2Fws-1%2Fassets%2Fimages%2Fai-profiles%2Fai-profile-1%2Favatar%2Favatar.webp',
|
|
480
527
|
avatarSourceUrl: '/api/taskforce/context/workspaces%2Fws-1%2Fassets%2Fimages%2Fai-profiles%2Fai-profile-1%2Favatar%2Fsource.webp',
|
|
528
|
+
avatarRevision: 1,
|
|
529
|
+
avatarUpdatedAt: '2026-03-22T10:04:00.000Z',
|
|
481
530
|
description: 'Terminal-first coding agent',
|
|
482
531
|
role: 'Implementer',
|
|
483
532
|
provider: 'OpenAI',
|
|
@@ -550,6 +599,12 @@ describe('workspaceSyncModel', () => {
|
|
|
550
599
|
createdAt: '2026-03-29T10:00:00.000Z',
|
|
551
600
|
updatedAt: '2026-03-29T11:00:00.000Z',
|
|
552
601
|
order: 1,
|
|
602
|
+
attachments: [{
|
|
603
|
+
path: 'workspaces/ws-1/assets/documents/asset-in.md',
|
|
604
|
+
assetId: 'asset-in',
|
|
605
|
+
referenceLabel: 'D-31',
|
|
606
|
+
caption: 'Revenue context'
|
|
607
|
+
}],
|
|
553
608
|
isArchived: false
|
|
554
609
|
}],
|
|
555
610
|
workstreams: [{
|
|
@@ -563,6 +618,12 @@ describe('workspaceSyncModel', () => {
|
|
|
563
618
|
createdAt: '2026-03-29T10:30:00.000Z',
|
|
564
619
|
updatedAt: '2026-03-29T11:30:00.000Z',
|
|
565
620
|
order: 2,
|
|
621
|
+
attachments: [{
|
|
622
|
+
path: 'workspaces/ws-1/assets/documents/asset-ws.md',
|
|
623
|
+
assetId: 'asset-ws',
|
|
624
|
+
referenceLabel: 'D-32',
|
|
625
|
+
caption: 'Checkout context'
|
|
626
|
+
}],
|
|
566
627
|
isArchived: false
|
|
567
628
|
}]
|
|
568
629
|
});
|
|
@@ -571,7 +632,13 @@ describe('workspaceSyncModel', () => {
|
|
|
571
632
|
op: 'initiative-upsert',
|
|
572
633
|
initiative: expect.objectContaining({
|
|
573
634
|
id: 'initiative-1',
|
|
574
|
-
title: 'Revenue Expansion'
|
|
635
|
+
title: 'Revenue Expansion',
|
|
636
|
+
attachments: expect.arrayContaining([
|
|
637
|
+
expect.objectContaining({
|
|
638
|
+
path: 'workspaces/ws-1/assets/documents/asset-in.md',
|
|
639
|
+
referenceLabel: 'D-31'
|
|
640
|
+
})
|
|
641
|
+
])
|
|
575
642
|
})
|
|
576
643
|
}),
|
|
577
644
|
expect.objectContaining({
|
|
@@ -579,7 +646,13 @@ describe('workspaceSyncModel', () => {
|
|
|
579
646
|
workstream: expect.objectContaining({
|
|
580
647
|
id: 'workstream-1',
|
|
581
648
|
initiativeId: 'initiative-1',
|
|
582
|
-
title: 'Checkout UX'
|
|
649
|
+
title: 'Checkout UX',
|
|
650
|
+
attachments: expect.arrayContaining([
|
|
651
|
+
expect.objectContaining({
|
|
652
|
+
path: 'workspaces/ws-1/assets/documents/asset-ws.md',
|
|
653
|
+
referenceLabel: 'D-32'
|
|
654
|
+
})
|
|
655
|
+
])
|
|
583
656
|
})
|
|
584
657
|
})
|
|
585
658
|
]));
|
|
@@ -764,6 +837,138 @@ describe('workspaceSyncModel', () => {
|
|
|
764
837
|
})
|
|
765
838
|
]));
|
|
766
839
|
});
|
|
840
|
+
it('does not resend already-acknowledged deleted collaboration records', () => {
|
|
841
|
+
const payload = buildWorkspaceSyncPayloadModel({
|
|
842
|
+
tasks: [],
|
|
843
|
+
archivedTasks: [],
|
|
844
|
+
lastPushedTaskIds: new Set(),
|
|
845
|
+
pendingDeletedTaskIds: new Set(),
|
|
846
|
+
documentReviewSessions: [
|
|
847
|
+
{
|
|
848
|
+
id: 'review-deleted',
|
|
849
|
+
assetId: 'asset-doc-1',
|
|
850
|
+
documentId: 'doc-1',
|
|
851
|
+
documentVersion: 2,
|
|
852
|
+
title: 'Review',
|
|
853
|
+
status: 'open',
|
|
854
|
+
comments: [],
|
|
855
|
+
createdByActorId: null,
|
|
856
|
+
updatedByActorId: null,
|
|
857
|
+
createdAt: '2026-03-24T10:00:00.000Z',
|
|
858
|
+
updatedAt: '2026-03-24T10:05:00.000Z',
|
|
859
|
+
deletedAt: '2026-03-24T10:06:00.000Z'
|
|
860
|
+
}
|
|
861
|
+
],
|
|
862
|
+
documentReviewComments: [
|
|
863
|
+
{
|
|
864
|
+
id: 'comment-deleted',
|
|
865
|
+
sessionId: 'review-deleted',
|
|
866
|
+
body: 'Delete me.',
|
|
867
|
+
anchor: { kind: 'document' },
|
|
868
|
+
order: 0,
|
|
869
|
+
authorActorId: null,
|
|
870
|
+
createdAt: '2026-03-24T10:00:00.000Z',
|
|
871
|
+
updatedAt: '2026-03-24T10:05:00.000Z',
|
|
872
|
+
deletedAt: '2026-03-24T10:06:30.000Z'
|
|
873
|
+
}
|
|
874
|
+
],
|
|
875
|
+
annotatedAttachmentSessions: [
|
|
876
|
+
{
|
|
877
|
+
id: 'annotation-deleted',
|
|
878
|
+
workspaceId: 'ws-1',
|
|
879
|
+
taskId: 'task-1',
|
|
880
|
+
baseImageAssetId: 'asset-image-1',
|
|
881
|
+
title: 'Annotations',
|
|
882
|
+
globalInstruction: null,
|
|
883
|
+
annotations: [],
|
|
884
|
+
createdByActorId: null,
|
|
885
|
+
updatedByActorId: null,
|
|
886
|
+
createdAt: '2026-03-24T10:00:00.000Z',
|
|
887
|
+
updatedAt: '2026-03-24T10:05:00.000Z',
|
|
888
|
+
deletedAt: '2026-03-24T10:07:00.000Z'
|
|
889
|
+
}
|
|
890
|
+
],
|
|
891
|
+
lastPushedDocumentReviewSessionIds: new Set(),
|
|
892
|
+
lastPushedDocumentReviewSessionWatermarks: new Map([
|
|
893
|
+
['review-deleted', '2026-03-24T10:06:00.000Z']
|
|
894
|
+
]),
|
|
895
|
+
lastPushedDocumentReviewCommentIds: new Set(),
|
|
896
|
+
lastPushedDocumentReviewCommentWatermarks: new Map([
|
|
897
|
+
['comment-deleted', '2026-03-24T10:06:30.000Z']
|
|
898
|
+
]),
|
|
899
|
+
lastPushedAnnotatedAttachmentSessionIds: new Set(),
|
|
900
|
+
lastPushedAnnotatedAttachmentSessionWatermarks: new Map([
|
|
901
|
+
['annotation-deleted', '2026-03-24T10:07:00.000Z']
|
|
902
|
+
])
|
|
903
|
+
});
|
|
904
|
+
expect(payload.currentDocumentReviewSessionWatermarks.get('review-deleted')).toBe('2026-03-24T10:06:00.000Z');
|
|
905
|
+
expect(payload.currentDocumentReviewCommentWatermarks.get('comment-deleted')).toBe('2026-03-24T10:06:30.000Z');
|
|
906
|
+
expect(payload.currentAnnotatedAttachmentSessionWatermarks.get('annotation-deleted')).toBe('2026-03-24T10:07:00.000Z');
|
|
907
|
+
expect(payload.changes).not.toEqual(expect.arrayContaining([
|
|
908
|
+
expect.objectContaining({ op: 'document-review-session-delete', sessionId: 'review-deleted' }),
|
|
909
|
+
expect.objectContaining({ op: 'document-review-comment-delete', commentId: 'comment-deleted' }),
|
|
910
|
+
expect.objectContaining({ op: 'annotated-attachment-session-delete', sessionId: 'annotation-deleted' })
|
|
911
|
+
]));
|
|
912
|
+
expect(payload.deltaDiagnostics?.domains.documentReviewSessions.changeCount).toBe(0);
|
|
913
|
+
expect(payload.deltaDiagnostics?.domains.documentReviewComments.changeCount).toBe(0);
|
|
914
|
+
expect(payload.deltaDiagnostics?.domains.annotatedAttachmentSessions.changeCount).toBe(0);
|
|
915
|
+
});
|
|
916
|
+
it('emits a single delete op when a previously pushed collaboration record is now soft-deleted', () => {
|
|
917
|
+
const payload = buildWorkspaceSyncPayloadModel({
|
|
918
|
+
tasks: [],
|
|
919
|
+
archivedTasks: [],
|
|
920
|
+
lastPushedTaskIds: new Set(),
|
|
921
|
+
pendingDeletedTaskIds: new Set(),
|
|
922
|
+
documentReviewSessions: [{
|
|
923
|
+
id: 'review-deleted',
|
|
924
|
+
assetId: 'asset-doc-1',
|
|
925
|
+
documentId: 'doc-1',
|
|
926
|
+
documentVersion: 2,
|
|
927
|
+
title: 'Review',
|
|
928
|
+
status: 'open',
|
|
929
|
+
comments: [],
|
|
930
|
+
createdByActorId: null,
|
|
931
|
+
updatedByActorId: null,
|
|
932
|
+
createdAt: '2026-03-24T10:00:00.000Z',
|
|
933
|
+
updatedAt: '2026-03-24T10:05:00.000Z',
|
|
934
|
+
deletedAt: '2026-03-24T10:06:00.000Z'
|
|
935
|
+
}],
|
|
936
|
+
documentReviewComments: [{
|
|
937
|
+
id: 'comment-deleted',
|
|
938
|
+
sessionId: 'review-deleted',
|
|
939
|
+
body: 'Delete me.',
|
|
940
|
+
anchor: { kind: 'document' },
|
|
941
|
+
order: 0,
|
|
942
|
+
authorActorId: null,
|
|
943
|
+
createdAt: '2026-03-24T10:00:00.000Z',
|
|
944
|
+
updatedAt: '2026-03-24T10:05:00.000Z',
|
|
945
|
+
deletedAt: '2026-03-24T10:06:30.000Z'
|
|
946
|
+
}],
|
|
947
|
+
annotatedAttachmentSessions: [{
|
|
948
|
+
id: 'annotation-deleted',
|
|
949
|
+
workspaceId: 'ws-1',
|
|
950
|
+
taskId: 'task-1',
|
|
951
|
+
baseImageAssetId: 'asset-image-1',
|
|
952
|
+
title: 'Annotations',
|
|
953
|
+
globalInstruction: null,
|
|
954
|
+
annotations: [],
|
|
955
|
+
createdByActorId: null,
|
|
956
|
+
updatedByActorId: null,
|
|
957
|
+
createdAt: '2026-03-24T10:00:00.000Z',
|
|
958
|
+
updatedAt: '2026-03-24T10:05:00.000Z',
|
|
959
|
+
deletedAt: '2026-03-24T10:07:00.000Z'
|
|
960
|
+
}],
|
|
961
|
+
lastPushedDocumentReviewSessionIds: new Set(['review-deleted']),
|
|
962
|
+
lastPushedDocumentReviewSessionWatermarks: new Map(),
|
|
963
|
+
lastPushedDocumentReviewCommentIds: new Set(['comment-deleted']),
|
|
964
|
+
lastPushedDocumentReviewCommentWatermarks: new Map(),
|
|
965
|
+
lastPushedAnnotatedAttachmentSessionIds: new Set(['annotation-deleted']),
|
|
966
|
+
lastPushedAnnotatedAttachmentSessionWatermarks: new Map()
|
|
967
|
+
});
|
|
968
|
+
expect(payload.changes.filter((change) => change.op === 'document-review-session-delete')).toHaveLength(1);
|
|
969
|
+
expect(payload.changes.filter((change) => change.op === 'document-review-comment-delete')).toHaveLength(1);
|
|
970
|
+
expect(payload.changes.filter((change) => change.op === 'annotated-attachment-session-delete')).toHaveLength(1);
|
|
971
|
+
});
|
|
767
972
|
});
|
|
768
973
|
describe('buildWorkspaceSyncSignatureModel', () => {
|
|
769
974
|
it('includes pending delete operations in the signature hash', () => {
|
|
@@ -921,6 +1126,63 @@ describe('workspaceSyncModel', () => {
|
|
|
921
1126
|
});
|
|
922
1127
|
expect(changedSignature).not.toEqual(baseSignature);
|
|
923
1128
|
});
|
|
1129
|
+
it('changes when initiative or workstream attachments change', () => {
|
|
1130
|
+
const baseSignature = buildWorkspaceSyncSignatureModel({
|
|
1131
|
+
workspaceId: 'ws-1',
|
|
1132
|
+
tasks: [],
|
|
1133
|
+
archivedTasks: [],
|
|
1134
|
+
initiatives: [{
|
|
1135
|
+
id: 'initiative-1',
|
|
1136
|
+
title: 'Revenue Expansion',
|
|
1137
|
+
description: null,
|
|
1138
|
+
createdAt: '2026-03-29T10:00:00.000Z',
|
|
1139
|
+
updatedAt: '2026-03-29T11:00:00.000Z',
|
|
1140
|
+
attachments: []
|
|
1141
|
+
}],
|
|
1142
|
+
workstreams: [{
|
|
1143
|
+
id: 'workstream-1',
|
|
1144
|
+
initiativeId: 'initiative-1',
|
|
1145
|
+
title: 'Checkout UX',
|
|
1146
|
+
description: null,
|
|
1147
|
+
createdAt: '2026-03-29T10:30:00.000Z',
|
|
1148
|
+
updatedAt: '2026-03-29T11:30:00.000Z',
|
|
1149
|
+
attachments: []
|
|
1150
|
+
}]
|
|
1151
|
+
});
|
|
1152
|
+
const changedSignature = buildWorkspaceSyncSignatureModel({
|
|
1153
|
+
workspaceId: 'ws-1',
|
|
1154
|
+
tasks: [],
|
|
1155
|
+
archivedTasks: [],
|
|
1156
|
+
initiatives: [{
|
|
1157
|
+
id: 'initiative-1',
|
|
1158
|
+
title: 'Revenue Expansion',
|
|
1159
|
+
description: null,
|
|
1160
|
+
createdAt: '2026-03-29T10:00:00.000Z',
|
|
1161
|
+
updatedAt: '2026-03-29T11:00:00.000Z',
|
|
1162
|
+
attachments: [{
|
|
1163
|
+
path: 'workspaces/ws-1/assets/documents/asset-in.md',
|
|
1164
|
+
assetId: 'asset-in',
|
|
1165
|
+
referenceLabel: 'D-31',
|
|
1166
|
+
caption: 'Revenue context'
|
|
1167
|
+
}]
|
|
1168
|
+
}],
|
|
1169
|
+
workstreams: [{
|
|
1170
|
+
id: 'workstream-1',
|
|
1171
|
+
initiativeId: 'initiative-1',
|
|
1172
|
+
title: 'Checkout UX',
|
|
1173
|
+
description: null,
|
|
1174
|
+
createdAt: '2026-03-29T10:30:00.000Z',
|
|
1175
|
+
updatedAt: '2026-03-29T11:30:00.000Z',
|
|
1176
|
+
attachments: [{
|
|
1177
|
+
path: 'workspaces/ws-1/assets/documents/asset-ws.md',
|
|
1178
|
+
assetId: 'asset-ws',
|
|
1179
|
+
referenceLabel: 'D-32',
|
|
1180
|
+
caption: 'Checkout context'
|
|
1181
|
+
}]
|
|
1182
|
+
}]
|
|
1183
|
+
});
|
|
1184
|
+
expect(changedSignature).not.toEqual(baseSignature);
|
|
1185
|
+
});
|
|
924
1186
|
it('changes when document review sessions change', () => {
|
|
925
1187
|
const baseSignature = buildWorkspaceSyncSignatureModel({
|
|
926
1188
|
workspaceId: 'ws-1',
|
|
@@ -1013,6 +1275,8 @@ describe('workspaceSyncModel', () => {
|
|
|
1013
1275
|
archivedTasks: [],
|
|
1014
1276
|
taskEvents: [{
|
|
1015
1277
|
id: 'task-event-1',
|
|
1278
|
+
entityType: 'task',
|
|
1279
|
+
entityId: 'task-1',
|
|
1016
1280
|
taskId: 'task-1',
|
|
1017
1281
|
workspaceId: 'ws-1',
|
|
1018
1282
|
action: 'task-status-changed',
|
|
@@ -1027,6 +1291,8 @@ describe('workspaceSyncModel', () => {
|
|
|
1027
1291
|
archivedTasks: [],
|
|
1028
1292
|
taskEvents: [{
|
|
1029
1293
|
id: 'task-event-1',
|
|
1294
|
+
entityType: 'task',
|
|
1295
|
+
entityId: 'task-1',
|
|
1030
1296
|
taskId: 'task-1',
|
|
1031
1297
|
workspaceId: 'ws-1',
|
|
1032
1298
|
action: 'task-status-changed',
|
package/dist/types.d.ts
CHANGED
|
@@ -29,10 +29,25 @@ export interface TaskEventDetails {
|
|
|
29
29
|
changes?: Record<string, TaskEventChange>;
|
|
30
30
|
[key: string]: unknown;
|
|
31
31
|
}
|
|
32
|
+
export type ActivityEntityType = 'task' | 'initiative' | 'workstream';
|
|
33
|
+
interface BaseEntityEvent {
|
|
34
|
+
id: string;
|
|
35
|
+
workspaceId: string;
|
|
36
|
+
entityType: ActivityEntityType;
|
|
37
|
+
entityId: string;
|
|
38
|
+
action: string;
|
|
39
|
+
actor: string;
|
|
40
|
+
actorType: 'human' | 'ai' | 'system';
|
|
41
|
+
createdAt: string;
|
|
42
|
+
details?: TaskEventDetails;
|
|
43
|
+
actorProfile?: TaskActor | null;
|
|
44
|
+
}
|
|
32
45
|
export interface TaskEvent {
|
|
33
46
|
id: string;
|
|
34
47
|
taskId: string;
|
|
35
48
|
workspaceId: string;
|
|
49
|
+
entityType?: 'task';
|
|
50
|
+
entityId?: string;
|
|
36
51
|
action: string;
|
|
37
52
|
actor: string;
|
|
38
53
|
actorType: 'human' | 'ai' | 'system';
|
|
@@ -40,6 +55,11 @@ export interface TaskEvent {
|
|
|
40
55
|
details?: TaskEventDetails;
|
|
41
56
|
actorProfile?: TaskActor | null;
|
|
42
57
|
}
|
|
58
|
+
export interface PlanningEntityEvent extends BaseEntityEvent {
|
|
59
|
+
entityType: 'initiative' | 'workstream';
|
|
60
|
+
entityId: string;
|
|
61
|
+
}
|
|
62
|
+
export type EntityEvent = TaskEvent | PlanningEntityEvent;
|
|
43
63
|
export interface CommentActivityItem {
|
|
44
64
|
id: string;
|
|
45
65
|
type: 'comment';
|
|
@@ -53,6 +73,13 @@ export interface AuditActivityItem {
|
|
|
53
73
|
event: TaskEvent;
|
|
54
74
|
}
|
|
55
75
|
export type TaskActivityItem = CommentActivityItem | AuditActivityItem;
|
|
76
|
+
export interface EntityAuditActivityItem {
|
|
77
|
+
id: string;
|
|
78
|
+
type: 'event';
|
|
79
|
+
timestamp: string;
|
|
80
|
+
event: EntityEvent;
|
|
81
|
+
}
|
|
82
|
+
export type EntityActivityItem = CommentActivityItem | EntityAuditActivityItem;
|
|
56
83
|
export type DeletedTaskSource = 'ui' | 'mcp' | 'sync' | 'workspace-delete' | 'system';
|
|
57
84
|
export interface DeletedTaskDetails {
|
|
58
85
|
reason?: string | null;
|
|
@@ -76,9 +103,9 @@ export interface AttachmentItem {
|
|
|
76
103
|
caption?: string;
|
|
77
104
|
displayName?: string;
|
|
78
105
|
originalFilename?: string;
|
|
79
|
-
assetId?: string;
|
|
106
|
+
assetId?: string | null;
|
|
80
107
|
referenceNumber?: number | null;
|
|
81
|
-
referenceLabel?: string;
|
|
108
|
+
referenceLabel?: string | null;
|
|
82
109
|
taskId?: string | null;
|
|
83
110
|
timestamp?: string;
|
|
84
111
|
}
|
|
@@ -122,6 +149,8 @@ export interface InitiativeItem {
|
|
|
122
149
|
description: string | null;
|
|
123
150
|
ownerId?: string | null;
|
|
124
151
|
comments?: Comment[];
|
|
152
|
+
activity?: EntityActivityItem[];
|
|
153
|
+
entityEvents?: PlanningEntityEvent[];
|
|
125
154
|
attachments?: Array<string | AttachmentItem>;
|
|
126
155
|
createdAt: string;
|
|
127
156
|
updatedAt?: string;
|
|
@@ -137,6 +166,8 @@ export interface WorkstreamItem {
|
|
|
137
166
|
description: string | null;
|
|
138
167
|
ownerId?: string | null;
|
|
139
168
|
comments?: Comment[];
|
|
169
|
+
activity?: EntityActivityItem[];
|
|
170
|
+
entityEvents?: PlanningEntityEvent[];
|
|
140
171
|
attachments?: Array<string | AttachmentItem>;
|
|
141
172
|
createdAt: string;
|
|
142
173
|
updatedAt?: string;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as c,j as e}from"./vendor-react-CKJs5o3c.js";import{s as Ue,p as _,u as ie,v as De,w as se,x as le,y as we,t as r,E as Te,z as Me,B as ke,C as fe,F as b,G as oe}from"./index-MAHKvFqp.js";import{Y as Re,w as $e,h as Ee,B as ne,m as C,b as Le,W as Be,a2 as Ge}from"./vendor-icons-B32hGuF2.js";import"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";import"./vendor-router-BbWMxlnO.js";function Fe(l){return typeof l.avatarUrl=="string"&&l.avatarUrl.trim().length>0}function K(l){return l?fe(l.avatarUrl,l.avatarRevision,l.avatarUpdatedAt):""}function ze(l){return l?fe(l.avatarSourceUrl,l.avatarRevision,l.avatarUpdatedAt):""}function He(l){return l.find(Fe)||l[0]}function ce(l){return`${l.seatScope||"unknown"}:${l.name.trim().toLowerCase()}`}function Oe(l){const m=Math.max(0,l-1);return`${m} duplicate${m===1?"":"s"}`}function de(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 pe(l,m){const U=m?.variant==="inline"?`${r.aiProfileSeatScopeIcon} ${r.aiProfileSeatScopeIconInline}`:m?.variant==="detail"?`${r.aiProfileSeatScopeIcon} ${r.aiProfileSeatScopeIconDetail}`:r.aiProfileSeatScopeIcon;return l==="cloud_metered"?e.jsx("span",{className:`${U} ${r.aiProfileSeatScopeIconCloud}`,title:"Cloud MCP","aria-label":"Cloud MCP",children:e.jsx(Be,{size:20})}):l==="local_unmetered"?e.jsx("span",{className:`${U} ${r.aiProfileSeatScopeIconLocal}`,title:"Local MCP","aria-label":"Local MCP",children:e.jsx(Ge,{size:20})}):null}function qe({workspaceId:l,cloudAuthConfigured:m=!1,authSessionResolved:U=!1,isAuthenticated:ue=!1,cloudAiProfileSeatUsage:me=null,agentTrayOpen:E=!1,onCloseAgentTray:he,mcpSettingsNode:V=null}){const[S,L]=c.useState([]),[ve,ge]=c.useState(null),[B,J]=c.useState(!1),[h,D]=c.useState(null),[w,v]=c.useState(null),[T,x]=c.useState(null),[W,G]=c.useState(null),[ye,Y]=c.useState(!1),[P,j]=c.useState(null),[q,Q]=c.useState(null),[X,M]=c.useState(!1),[Pe,g]=c.useState(null),k=c.useCallback(async()=>{if(l){J(!0);try{const a=`/api/taskforce/workspace/assignee-options?workspaceId=${encodeURIComponent(l)}&kind=agent`,t=await fetch(a,{credentials:"include"}),i=t.ok?await t.json().catch(()=>({})):{},o=de(i?.aiProfileSeatUsage),d=Array.isArray(i?.assignees)?i.assignees.filter(s=>s.kind==="agent").map(s=>({id:String(s.value||""),name:String(s.label||s.value||"Unknown Agent"),username:String(s.username||s.value||""),icon:String(s.icon||"Bot"),color:String(s.color||"#6B7280"),avatarUrl:typeof s.avatarUrl=="string"?s.avatarUrl:null,avatarSourceUrl:typeof s.avatarSourceUrl=="string"?s.avatarSourceUrl:null,avatarRevision:Number.isFinite(Number(s.avatarRevision))?Math.max(0,Math.floor(Number(s.avatarRevision))):0,avatarUpdatedAt:typeof s.avatarUpdatedAt=="string"?s.avatarUpdatedAt:null,kind:String(s.kind||"agent"),description:typeof s.description=="string"?s.description:null,role:typeof s.role=="string"?s.role:null,provider:typeof s.provider=="string"?s.provider:null,model:typeof s.model=="string"?s.model:null,surfaceType:_(s.surfaceType),seatScope:Ue(s.seatScope),archivedAt:typeof s.archivedAt=="string"?s.archivedAt:null,createdAt:String(s.createdAt||""),updatedAt:String(s.updatedAt||s.createdAt||""),lastActiveAt:typeof s.lastActiveAt=="string"?s.lastActiveAt:null})):[];L(d),ge(o),x(s=>s&&!d.some(p=>p.id===s.profileId)?null:s),G(s=>s&&!d.some(p=>p.id===s.profileId)?null:s)}finally{J(!1)}}},[l]);c.useEffect(()=>{k()},[k]);const R=c.useMemo(()=>{const a=new Map;for(const t of S){const i=ie(t.surfaceType);a.has(i)||a.set(i,new Map);const o=a.get(i),d=ce(t);o.has(d)||o.set(d,[]),o.get(d).push(t)}return De.map(t=>({section:t,label:se(t),groups:Array.from(a.get(t)?.entries()||[]).map(([i,o])=>({groupId:`${t}:${i}`,section:t,sectionLabel:se(t),profiles:o,primaryProfile:He(o)}))})).filter(t=>t.groups.length>0)},[S]),y=c.useMemo(()=>R.flatMap(a=>a.groups),[R]),n=c.useMemo(()=>y.find(a=>a.groupId===P)||y[0]||null,[y,P]),u=c.useMemo(()=>S.find(a=>a.id===q)||null,[S,q]);c.useEffect(()=>{if(!y.length){P!==null&&j(null);return}(!P||!y.some(a=>a.groupId===P))&&j(y[0].groupId)},[y,P]);const Ae=async(a,t)=>{v(null),x(null);try{const i=await fetch("/api/taskforce/workspace/ai-profiles/merge",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({keepId:a,mergeId:t})}),o=await i.json().catch(()=>({}));if(!i.ok){v({type:"error",message:String(o?.error||"Failed to merge AI profiles.")});return}D(null),v({type:"success",message:"AI profiles merged."}),await k(),b({workspaceId:l,profileId:a,reason:"merge"})}catch{v({type:"error",message:"Failed to merge AI profiles."})}},Z=async a=>{if(window.confirm(`Remove ${a.name} from the active roster? This frees an AI profile seat and preserves task and comment history.`)){x(null),v(null);try{const i=await fetch("/api/taskforce/workspace/ai-profiles/archive",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:a.id,reason:"manual_archive"})}),o=await i.json().catch(()=>({}));if(!i.ok){x({profileId:a.id,message:String(o?.error||"Failed to remove AI profile from roster.")});return}(h?.keepId===a.id||h?.mergeId===a.id)&&D(null),v({type:"success",message:"AI profile removed from active roster."}),await k(),b({workspaceId:l,profileId:a.id,reason:"archive"})}catch{x({profileId:a.id,message:"Failed to remove AI profile from roster."})}}},Se=async(a,t)=>{const i=_(t),o=new Set(a.profiles.map(p=>p.surfaceType??"")),d=i??"";if(o.size===1&&o.has(d))return;Y(!0),G(null),v(null);const s=[];try{for(const f of a.profiles){const I=await fetch("/api/taskforce/workspace/ai-profiles/surface-type",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:f.id,surfaceType:i})}),H=await I.json().catch(()=>({}));if(!I.ok||!H?.profile)throw new Error(String(H?.error||"Failed to update AI profile category."));const O=H.profile;s.push({...f,surfaceType:_(O.surfaceType),updatedAt:typeof O.updatedAt=="string"?O.updatedAt:f.updatedAt})}const p=new Map(s.map(f=>[f.id,f]));L(f=>f.map(I=>p.get(I.id)||I));const A=p.get(a.primaryProfile.id)||{...a.primaryProfile,surfaceType:i},Ce=ie(A.surfaceType);j(`${Ce}:${ce(A)}`),v({type:"success",message:"AI profile category updated."});for(const f of s)b({workspaceId:l,profileId:f.id,reason:"update"})}catch(p){G({profileId:a.primaryProfile.id,message:String(p?.message||"Failed to update AI profile category.")})}finally{Y(!1)}},ee=a=>new Promise((t,i)=>{const o=new FileReader;o.onload=()=>t(String(o.result||"")),o.onerror=()=>i(new Error("Failed to read image file.")),o.readAsDataURL(a)}),ae=a=>{const t=String(a?.id||"").trim();t&&L(i=>i.map(o=>o.id===t?{...o,avatarUrl:typeof a.avatarUrl=="string"?a.avatarUrl:null,avatarSourceUrl:typeof a.avatarSourceUrl=="string"?a.avatarSourceUrl:null,avatarRevision:Number.isFinite(Number(a.avatarRevision))?Math.max(0,Math.floor(Number(a.avatarRevision))):o.avatarRevision,avatarUpdatedAt:typeof a.avatarUpdatedAt=="string"?a.avatarUpdatedAt:o.avatarUpdatedAt,updatedAt:typeof a.updatedAt=="string"?a.updatedAt:o.updatedAt}:o))},xe=async(a,t,i)=>{const o=await ee(t),d=i?await ee(i):null,s={profileId:a,displayImage:{dataUrl:o,mimeType:t.type||"application/octet-stream",originalName:t.name||"display-avatar"}};i&&d&&(s.sourceImage={dataUrl:d,mimeType:i.type||"application/octet-stream",originalName:i.name||"source-avatar"});const p=await fetch("/api/taskforce/workspace/ai-profiles/avatar/upload",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),A=await p.json().catch(()=>({}));if(!p.ok||!A?.profile)throw new Error(String(A?.error||"Failed to update AI profile avatar."));ae(A.profile),b({workspaceId:l,profileId:a,reason:"avatar"})},je=async a=>{const t=await fetch("/api/taskforce/workspace/ai-profiles/avatar",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:a,avatarUrl:null,avatarSourceUrl:null})}),i=await t.json().catch(()=>({}));if(!t.ok||!i?.profile)throw new Error(String(i?.error||"Failed to update AI profile avatar."));ae(i.profile),b({workspaceId:l,profileId:a,reason:"avatar"})},Ne=async(a,t)=>{if(!u)return!1;if(!a.type.startsWith("image/"))return g("AI profile photo must be an image file."),!1;M(!0),g(null);try{const i=await oe(a,{maxBytes:5242880});if(i.exceededLimit)throw new Error(a.type==="image/gif"?"Animated GIF AI profile photos must be 5 MB or smaller.":"AI profile photo must be 5 MB or smaller.");const o=i.file;let d=null;if(t){const s=await oe(t,{maxBytes:5242880});if(s.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.");d=s.file}return await xe(u.id,o,d),!0}catch(i){return g(String(i?.message||"Failed to update AI profile photo.")),!1}finally{M(!1)}},Ie=async()=>{if(u){M(!0),g(null);try{await je(u.id)}catch(a){g(String(a?.message||"Failed to remove AI profile photo."))}finally{M(!1)}}},N=a=>{const t=String(a||"").trim();if(!t)return"Unknown";const i=Date.parse(t);return Number.isFinite(i)?new Date(i).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):t},re=c.useMemo(()=>{if(!n)return{attributes:[],dates:[]};const a=n.primaryProfile,t=i=>i||"Not set";return{attributes:[{label:"Category",value:a.surfaceType?le(a.surfaceType):""},{label:"Connection",value:a.seatScope?we(a.seatScope):""},{label:"Provider",value:a.provider||""},{label:"Model",value:a.model||""}].map(i=>({...i,value:t(i.value)})),dates:[{label:"Status",value:a.archivedAt?"Retired":"Active"},{label:"Recruited",value:N(a.createdAt)},{label:"Last updated",value:N(a.updatedAt)},{label:"Last active",value:N(a.lastActiveAt)}].map(i=>({...i,value:t(i.value)}))}},[n]),be=!!n&&n.profiles.length>1,te=m&&U&&!ue,$=m?de(me):ve,F=te?"Log into account for Cloud agents":$?`${$.used}/${$.limit===null?"Unlimited":$.limit}`:null,z=!!V;return e.jsxs("section",{className:`${r.agentsModuleRoot} ${z?r.agentsModuleWithTray:""} ${z&&E?r.agentsModuleTrayOpen:""}`.trim(),children:[z&&e.jsxs("aside",{className:`${r.agentTrayPanel} ${E?r.agentTrayPanelOpen:""}`.trim(),"aria-label":"Agent MCP settings tray","aria-hidden":!E,children:[e.jsxs("div",{className:r.agentTrayHeader,children:[e.jsxs("span",{className:r.agentTrayTitle,children:[e.jsx(Re,{size:14}),"MCP Settings"]}),e.jsx("button",{type:"button",className:"tf-control-icon",onClick:he,title:"Collapse agent tray","aria-label":"Collapse agent tray",children:e.jsx($e,{size:16})})]}),e.jsx("div",{className:`${r.agentTrayContent} tf-scrollbar tf-scrollbar--track-transparent`,children:e.jsx("div",{className:r.agentTrayContentInner,children:V})})]}),e.jsx("div",{className:r.agentsModuleContent,children:e.jsx("div",{className:`${r.settingGroup} ${r.agentsModuleGroup}`,children:e.jsxs("div",{children:[e.jsx("h4",{className:r.settingSubTitle,children:"Registered AI Profiles"}),e.jsx("p",{className:`${r.settingsHint} ${r.marginBottom12}`,children:"AI agents register profiles when connecting via MCP. Merge duplicates created when a token was lost, or remove inactive profiles from the active roster to free seats while preserving history."}),F&&e.jsx("div",{className:r.aiProfileSeatSummary,children:te?F:`Registered Cloud Agents: ${F}`}),B&&e.jsxs("div",{className:r.settingsHint,children:[e.jsx(Ee,{size:13,className:r.spinner})," Loading profiles…"]}),!B&&S.length===0&&e.jsx("div",{className:r.settingsHint,children:"No AI profiles registered yet."}),!B&&R.length>0&&e.jsxs("div",{className:r.aiProfilesExplorer,children:[e.jsx("div",{className:`${r.aiProfilesListPane} tf-scrollbar tf-scrollbar--track-transparent`,children:e.jsx("div",{className:r.aiProfilesList,children:R.map(a=>e.jsxs("div",{className:r.aiProfilesSection,children:[e.jsx("div",{className:r.aiProfilesSectionHeader,children:a.label}),a.groups.map(t=>{const i=n?.groupId===t.groupId,o=t.primaryProfile;return e.jsxs("div",{role:"button",tabIndex:0,className:`${r.aiProfileGroup} ${t.profiles.length>1?r.aiProfileGroupDuplicate:""} ${i?r.aiProfileGroupSelected:""}`,onClick:()=>j(t.groupId),onKeyDown:d=>{d.key!=="Enter"&&d.key!==" "||(d.preventDefault(),j(t.groupId))},"aria-pressed":i,children:[pe(o.seatScope),e.jsxs("div",{className:r.aiProfileGroupHeader,children:[e.jsx("span",{className:r.aiProfileGroupAvatar,style:{color:o.color},children:o.avatarUrl?e.jsx("img",{src:K(o),alt:""}):e.jsx(ne,{size:22})}),e.jsxs("span",{className:r.aiProfileGroupIdentity,children:[e.jsx("span",{className:r.aiProfileName,children:o.name}),e.jsxs("span",{className:r.aiProfileHandle,children:["@",o.username]}),e.jsx("span",{className:r.aiProfileRole,children:o.role||"Role not set"}),t.profiles.length>1&&e.jsxs("span",{className:r.aiProfileDuplicateBadge,children:[e.jsx(C,{size:11})," ",Oe(t.profiles.length)]})]})]})]},t.groupId)})]},a.section))})}),n&&e.jsx("div",{className:r.aiProfileDetailPane,children:e.jsxs("div",{className:r.aiProfileDetailCard,children:[pe(n.primaryProfile.seatScope,{variant:"detail"}),e.jsxs("div",{className:r.aiProfileDetailHero,children:[e.jsx(Te,{label:"Edit AI profile photo",imageUrl:K(n.primaryProfile),fallback:e.jsx(ne,{size:38}),accentColor:n.primaryProfile.color,size:176,width:153,height:207,radius:6,editBadgeSize:28,editIconSize:14,className:r.aiProfileDetailAvatar,onClick:()=>{g(null),Q(n.primaryProfile.id)}}),e.jsxs("div",{className:r.aiProfileDetailHeading,children:[e.jsx("div",{className:r.aiProfileDetailTitleRow,children:e.jsx("h5",{className:r.aiProfileDetailTitle,children:n.primaryProfile.name})}),e.jsxs("div",{className:r.aiProfileDetailMetaRow,children:[e.jsxs("span",{className:r.aiProfileDetailHandle,children:["@",n.primaryProfile.username]}),n.profiles.length>1&&e.jsxs("span",{className:r.aiProfileDetailLinkedCount,children:[n.profiles.length," linked"]})]}),e.jsxs("div",{className:r.aiProfileDetailRole,children:["Role: ",n.primaryProfile.role||"Not set"]}),n.primaryProfile.description&&e.jsx("div",{className:r.aiProfileDetailDescription,children:n.primaryProfile.description}),e.jsxs("div",{className:r.aiProfileSignatureColor,children:[e.jsx("span",{children:"Signature color"}),e.jsx("span",{className:r.aiProfileSignatureSwatch,style:{backgroundColor:n.primaryProfile.color},"aria-hidden":"true"}),e.jsx("span",{children:n.primaryProfile.color})]})]})]}),e.jsxs("div",{className:r.aiProfileDetailDataList,children:[e.jsx("div",{className:r.aiProfileDetailDataGroup,children:re.attributes.map(a=>e.jsxs("div",{className:r.aiProfileDetailDataRow,children:[e.jsx("span",{className:r.aiProfileDetailDataLabel,children:a.label}),a.label==="Category"?e.jsx("span",{className:r.aiProfileDetailDataValue,children:e.jsxs("select",{className:r.aiProfileStatusSelect,"aria-label":"Agent category",value:n.primaryProfile.surfaceType??"",disabled:ye,onChange:t=>{Se(n,t.target.value)},children:[e.jsx("option",{value:"",children:"Unclassified"}),Me.map(t=>e.jsx("option",{value:t,children:le(t)},t))]})}):e.jsx("span",{className:r.aiProfileDetailDataValue,children:a.value})]},a.label))}),e.jsx("div",{className:`${r.aiProfileDetailDataGroup} ${r.aiProfileDetailDateGroup}`,children:re.dates.map(a=>e.jsxs("div",{className:r.aiProfileDetailDataRow,children:[e.jsx("span",{className:r.aiProfileDetailDataLabel,children:a.label}),a.label==="Status"?e.jsx("span",{className:r.aiProfileDetailDataValue,children:e.jsxs("select",{className:r.aiProfileStatusSelect,"aria-label":"Agent roster status",value:n.primaryProfile.archivedAt?"retired":"active",onChange:t=>{t.target.value==="retire"&&Z(n.primaryProfile)},children:[e.jsx("option",{value:"active",children:"Active"}),n.primaryProfile.archivedAt?e.jsx("option",{value:"retired",children:"Retired"}):e.jsx("option",{value:"retire",children:"Retire from roster"})]})}):e.jsx("span",{className:r.aiProfileDetailDataValue,children:a.value})]},a.label))})]}),W?.profileId===n.primaryProfile.id&&e.jsxs("div",{className:r.aiProfileInlineError,role:"alert",children:[e.jsx(C,{size:12}),e.jsx("span",{children:W.message})]}),be?e.jsxs("div",{className:r.aiProfileInstanceSection,children:[e.jsxs("div",{className:r.aiProfileInstanceSectionHeader,children:[e.jsx("span",{children:"Profile instances"}),e.jsx("span",{className:r.settingsHint,children:"Choose a keeper here if duplicates need to be merged."})]}),e.jsx("div",{className:r.aiProfileInstanceList,children:n.profiles.map(a=>e.jsxs("div",{className:r.aiProfileInstanceCard,children:[e.jsxs("div",{className:r.aiProfileInstanceTopRow,children:[e.jsxs("div",{children:[e.jsxs("div",{className:r.aiProfileInstanceName,children:["@",a.username]}),e.jsx("div",{className:r.aiProfileIdChip,children:a.id})]}),h?.keepId===a.id&&e.jsx("span",{className:r.aiProfileKeepBadge,children:"Keeping"})]}),e.jsxs("div",{className:r.aiProfileInstanceMeta,children:[e.jsxs("span",{children:["Created ",N(a.createdAt)]}),e.jsxs("span",{children:["Updated ",N(a.updatedAt)]})]}),h?.keepId!==a.id&&e.jsx("button",{className:r.secondaryHeaderBtn,title:"Keep this profile, merge others into it",onClick:()=>{const t=n.profiles.find(i=>i.id!==a.id)?.id;t&&D({keepId:a.id,mergeId:t})},children:"Keep this"}),T?.profileId===a.id&&e.jsxs("div",{className:r.aiProfileInlineError,role:"alert",children:[e.jsx(C,{size:12}),e.jsx("span",{children:T.message})]}),e.jsx("button",{className:r.aiProfileDangerTextButton,title:"Remove this profile from the active roster",onClick:()=>{Z(a)},children:"Remove from roster"})]},a.id))}),h&&n.profiles.some(a=>a.id===h.keepId)&&e.jsxs("div",{className:r.aiProfileMergeActions,children:[e.jsx("button",{className:r.dangerBtn,onClick:()=>{Ae(h.keepId,h.mergeId)},children:"Merge duplicates"}),e.jsx("button",{className:r.secondaryHeaderBtn,onClick:()=>D(null),children:"Cancel"})]})]}):e.jsxs("div",{className:r.aiProfileIdFooter,children:[e.jsx("div",{className:r.aiProfileIdFooterValue,children:n.primaryProfile.id}),T?.profileId===n.primaryProfile.id&&e.jsxs("div",{className:r.aiProfileInlineError,role:"alert",children:[e.jsx(C,{size:12}),e.jsx("span",{children:T.message})]})]})]})})]}),w&&e.jsxs("div",{className:`${w.type==="success"?r.successMessage:r.errorMessage} ${r.marginTop12}`,children:[w.type==="success"?e.jsx(Le,{size:14}):e.jsx(C,{size:14}),w.message]})]})})}),e.jsx(ke,{isOpen:!!u,theme:"dark",title:"Edit AI Profile Photo",currentImageUrl:K(u),editorImageUrl:ze(u),fallbackInitial:(u?.name||"AI").charAt(0).toUpperCase(),accept:"image/png,image/jpeg,image/webp,image/gif",busy:X,hasPendingImage:!1,canRemove:!!u?.avatarUrl,error:Pe,notice:null,onClose:()=>{X||(Q(null),g(null))},onApplyImage:Ne,onRemoveImage:Ie})]})}export{qe as AgentsModule};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._shell_17mlo_1{--image-tray-width: min(332px, calc(100vw - 96px) );position:relative;align-self:stretch;width:100%;box-sizing:border-box;display:grid;grid-template-columns:minmax(220px,280px) minmax(0,1fr) minmax(280px,340px);gap:16px;height:100%;min-height:0;padding:16px;background:radial-gradient(circle at top left,color-mix(in srgb,var(--brand-primary) 8%,transparent),transparent 26%),linear-gradient(180deg,color-mix(in srgb,var(--surface-page) 84%,var(--surface-panel)) 0%,var(--surface-page) 100%)}._shellWithImageTray_17mlo_18{transition:padding-left .22s cubic-bezier(.4,0,.2,1)}._shellImageTrayOpen_17mlo_22{padding-left:calc(var(--image-tray-width) + 16px)}._imageTrayPanel_17mlo_26{position:absolute;top:0;bottom:0;left:0;width:var(--image-tray-width);min-width:260px;max-width:332px;display:flex;flex-direction:column;padding:0 12px;box-sizing:border-box;border-right:1px solid var(--border-primary);background:var(--bg-secondary);overflow:hidden;transform:translate(-100%);opacity:0;visibility:hidden;pointer-events:none;z-index:34;box-shadow:4px 0 18px #080a1829;transition:transform .22s cubic-bezier(.4,0,.2,1),opacity .16s ease,visibility 0s linear .22s}._imageTrayPanelOpen_17mlo_50{transform:translate(0);opacity:1;visibility:visible;pointer-events:auto;transition:transform .22s cubic-bezier(.4,0,.2,1),opacity .16s ease,visibility 0s linear 0s}._imageTrayHeader_17mlo_58{position:sticky;top:0;z-index:12;display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:12px 0 10px;border-bottom:1px solid var(--border-default);background:var(--bg-secondary);box-shadow:0 10px 16px color-mix(in srgb,var(--bg-secondary) 90%,transparent);flex-shrink:0}._imageTrayTitle_17mlo_73{flex:1;display:flex;align-items:center;gap:6px;font-size:.78rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary)}._imageTraySearch_17mlo_85{position:relative;padding:12px 0 0;flex-shrink:0}._imageTraySearchIcon_17mlo_91{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--text-muted);pointer-events:none}._imageTraySearchInput_17mlo_100{width:100%;padding:7px 8px 7px 28px;background:color-mix(in srgb,var(--surface-inset) 88%,transparent);border:1px solid var(--border-default);border-radius:var(--radius-md);color:var(--text-primary);font-size:.75rem;font-family:inherit;outline:none;box-sizing:border-box}._imageTraySearchInput_17mlo_100:focus{border-color:var(--brand-primary)}._imageTrayList_17mlo_117{display:flex;flex-direction:column;gap:.375rem;flex:1;overflow-y:auto;min-height:0;padding:12px 0;scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) var(--scrollbar-track)}._imageTrayState_17mlo_129,._imageTrayStateError_17mlo_130{padding:24px 16px;font-size:.75rem;color:var(--text-muted);text-align:center;line-height:1.5}._imageTrayStateError_17mlo_130{color:var(--status-error)}._imageTrayItem_17mlo_142{width:100%;display:flex;align-items:flex-start;gap:8px;padding:.55rem .65rem;border-radius:var(--radius-md);border:1px solid var(--border-default);background:color-mix(in srgb,var(--surface-inset) 88%,transparent);cursor:pointer;text-align:left;transition:background var(--transition-base),border-color var(--transition-base),box-shadow var(--transition-base),transform var(--transition-base);font-family:inherit;color:var(--text-primary);min-width:0}._imageTrayItem_17mlo_142:hover{background:color-mix(in srgb,var(--surface-hover) 72%,transparent);transform:translateY(-1px)}._imageTrayItemActive_17mlo_164{border-color:var(--brand-primary-border);background:color-mix(in srgb,var(--brand-primary-soft) 94%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--brand-primary-border) 42%,transparent)}._imageTrayItemActive_17mlo_164:hover{background:color-mix(in srgb,var(--brand-primary-soft) 92%,transparent)}._imageTrayThumb_17mlo_174{width:34px;height:34px;flex-shrink:0;border-radius:6px;overflow:hidden;background:var(--surface-inset);border:1px solid var(--border-subtle)}._imageTrayThumb_17mlo_174 img{width:100%;height:100%;object-fit:cover;display:block}._imageTrayItemBody_17mlo_191{display:flex;flex-direction:column;gap:.25rem;min-width:0;flex:1}._imageTrayItemTitle_17mlo_199,._imageTrayItemTask_17mlo_200,._imageTrayItemMetaDetails_17mlo_201{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._imageTrayItemTitle_17mlo_199{display:block;max-width:100%;font-size:.875rem;font-weight:700;line-height:1.28;color:var(--text-primary)}._imageTrayItemTask_17mlo_200{display:block;max-width:100%;font-size:.75rem;line-height:1.35;color:color-mix(in srgb,var(--text-secondary) 92%,transparent)}._imageTrayItemMeta_17mlo_201{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;font-size:.72rem;line-height:1.35;color:color-mix(in srgb,var(--text-secondary) 82%,transparent)}._imageTrayItemMetaDetails_17mlo_201{min-width:0}._imageTrayItemReference_17mlo_239{flex-shrink:0;font-size:.7rem;font-weight:700;color:var(--text-secondary)}._panel_17mlo_246{min-height:0;border-radius:var(--radius-md);box-shadow:0 18px 38px #0f172a14}._sessionPanel_17mlo_252,._detailPanel_17mlo_253{display:flex;flex-direction:column;overflow:hidden}._sessionContextBar_17mlo_259{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:58px;padding:12px 16px;border-bottom:1px solid var(--border-default);background:color-mix(in srgb,var(--surface-inset) 88%,transparent)}._sessionContextLeft_17mlo_270,._sessionContextRight_17mlo_271{display:flex;align-items:center;min-width:0}._sessionContextLeft_17mlo_270{flex:1}._sessionContextRight_17mlo_271{justify-content:flex-end;min-width:118px}._sessionContextLabel_17mlo_286{font-size:.84rem;font-weight:600;color:var(--text-secondary)}._sessionContextSpacer_17mlo_292{width:118px;height:32px}._canvasPanel_17mlo_297{display:flex;flex-direction:column;min-height:0;overflow:hidden}._canvasWorkspace_17mlo_304{display:grid;grid-template-columns:auto minmax(0,1fr);min-height:0;flex:1}._canvasMain_17mlo_311{display:flex;flex-direction:column;min-width:0;min-height:0}._panelHeader_17mlo_318{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px;border-bottom:1px solid var(--border-default)}._panelHeaderText_17mlo_327{min-width:0}._panelTitle_17mlo_331{font-size:1rem}._canvasHeading_17mlo_335{min-width:0}._sessionActions_17mlo_339{display:inline-flex;align-items:center;gap:8px;margin-left:auto;flex-shrink:0}._sessionList_17mlo_347,._annotationList_17mlo_348{display:flex;flex:1 1 auto;flex-direction:column;gap:10px;min-height:0;padding:14px;overflow:auto;scrollbar-gutter:stable}._annotationList_17mlo_348{gap:12px}._markerHelpModalBody_17mlo_363{display:flex;flex-direction:column;gap:14px}._openImageModalBody_17mlo_369{display:flex;flex-direction:column;gap:12px}._openImageField_17mlo_375{width:100%}._openImageActions_17mlo_379{display:flex;justify-content:flex-end;gap:8px}._markerHelpItem_17mlo_385{display:flex;flex-direction:column;gap:6px;padding:12px 14px;border-radius:var(--radius-md)}._markerHelpHeader_17mlo_393{display:flex;align-items:baseline;justify-content:space-between;gap:12px}._markerHelpItem_17mlo_385 p{margin:0;line-height:1.45}._markerHelpExample_17mlo_405{font-weight:600}._sessionCard_17mlo_409,._annotationCard_17mlo_410{display:flex;flex-direction:column;gap:8px;padding:12px;border-radius:var(--radius-md);text-align:left;transition:border-color var(--transition-base),box-shadow var(--transition-base),transform var(--transition-base)}._sessionCard_17mlo_409{gap:10px}._sessionEmptyState_17mlo_427{display:flex;flex-direction:column;gap:8px;padding:8px 2px 0}._sessionCardButton_17mlo_434,._annotationCardButton_17mlo_444{display:flex;flex-direction:column;gap:8px;padding:0;border:0;background:transparent;text-align:left}._sessionCardBody_17mlo_454{display:flex;flex-direction:column;gap:8px}._sessionCardActive_17mlo_460,._annotationCardActive_17mlo_461{border-color:var(--button-tile-active-border);box-shadow:0 0 0 1px transparent,0 12px 28px var(--brand-primary-glow-soft)}._sessionCard_17mlo_409:hover,._annotationCard_17mlo_410:hover{transform:translateY(-1px)}._annotationMeta_17mlo_471{display:flex;align-items:center;justify-content:space-between;gap:8px}._annotationInstructionPreview_17mlo_478{display:-webkit-box;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.45}._annotationPreviewFooter_17mlo_486{display:flex;align-items:center;justify-content:flex-start;min-height:16px}._annotationInstructionEditor_17mlo_493,._annotationTypeField_17mlo_499{display:flex;flex-direction:column;gap:8px}._annotationInstructionButton_17mlo_505{display:block;width:100%;padding:0;border:0;background:transparent;text-align:left}._annotationInstructionField_17mlo_514{min-height:92px}._sessionMeta_17mlo_518{display:flex;flex-direction:column;align-items:flex-start;gap:4px}._sessionTitle_17mlo_525,._annotationTitle_17mlo_526{font-size:.98rem;font-weight:700;color:var(--text-primary)}._sessionTimestamp_17mlo_532,._annotationKind_17mlo_533{text-transform:capitalize}._annotationInstructionTypeIcon_17mlo_537{display:inline-flex;align-items:center;justify-content:center}._sessionInstructionPreview_17mlo_543{line-height:1.45;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}._sessionInstructionEditor_17mlo_551{display:flex;flex-direction:column;gap:8px}._sessionCardFooter_17mlo_557{display:flex;align-items:center;justify-content:flex-end;gap:8px}._toolRail_17mlo_564{display:flex;flex-wrap:wrap;gap:8px;padding:0;border-bottom:1px solid var(--border-default);background:color-mix(in srgb,var(--surface-inset) 92%,transparent)}._canvasToolRail_17mlo_573{display:flex;flex-direction:column;align-items:center;gap:8px;padding:0;border-right:1px solid var(--border-default);background:color-mix(in srgb,var(--surface-inset) 94%,transparent)}._toolGroup_17mlo_583{display:inline-flex;flex-wrap:wrap;gap:8px;align-items:center;padding:4px;border:1px solid var(--border-default);border-radius:16px;background:var(--surface-panel)}._toolbarCluster_17mlo_594{display:inline-flex;flex-wrap:wrap;gap:8px;align-items:center}._toolbarViewportCluster_17mlo_601{margin-left:44px}._toolbarSeparator_17mlo_605{width:1px;align-self:stretch;background:var(--border-default)}._toolBtn_17mlo_611{white-space:nowrap}._toolRailButton_17mlo_615{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border-radius:var(--radius-md)}._toolbarButton_17mlo_625{min-height:44px;border-radius:var(--radius-md)}._toolBtnActive_17mlo_630{background:var(--button-tile-active-bg);border-color:var(--button-tile-active-border);color:var(--button-tile-active-text);box-shadow:0 0 0 1px transparent,0 8px 24px var(--brand-primary-glow-soft)}._toolbarActions_17mlo_637{display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px;flex:1 1 auto;min-width:0}._toolbarSelectionActions_17mlo_646{display:inline-flex;align-items:center;gap:8px;min-width:44px;flex-wrap:wrap}._toolbarColorPicker_17mlo_654{position:relative}._colorPickerButton_17mlo_658{min-width:44px;padding:0}._colorPickerSwatch_17mlo_663{width:24px;height:24px;border-radius:var(--radius-sm);border:2px solid color-mix(in srgb,var(--surface-panel) 88%,transparent);box-shadow:inset 0 0 0 1px #0f172a1f}._colorPickerPopover_17mlo_671{position:absolute;top:calc(100% + 8px);left:0;z-index:3;display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:10px;border:1px solid var(--border-default);border-radius:var(--radius-md);background:var(--surface-panel);box-shadow:0 18px 32px #0f172a24}._colorOption_17mlo_686{width:24px;height:24px;padding:0;border:2px solid transparent;border-radius:var(--radius-sm);cursor:pointer;box-shadow:inset 0 0 0 1px #0f172a24}._colorOptionActive_17mlo_696{border-color:color-mix(in srgb,var(--surface-panel) 78%,var(--brand-primary));box-shadow:inset 0 0 0 1px #0f172a24,0 0 0 2px color-mix(in srgb,var(--brand-primary) 24%,transparent)}._toolbarUtilities_17mlo_703{margin-left:auto;display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px}._toolbarGeometryFields_17mlo_711{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}._toolbarGeometryField_17mlo_711{display:inline-flex;align-items:center;gap:6px}._toolbarGeometryLabel_17mlo_724{margin:0;text-transform:uppercase;white-space:nowrap}._toolbarGeometryInput_17mlo_730{width:68px;text-align:right}._iconButton_17mlo_735{flex-shrink:0}._primaryBtn_17mlo_739,._ghostBtn_17mlo_740,._payloadBtn_17mlo_741,._backToTaskBtn_17mlo_742{white-space:nowrap}._backToTaskBtn_17mlo_742{padding:7px 10px;color:var(--text-secondary);font-size:.88rem;font-weight:600}._backToTaskBtn_17mlo_742:hover,._backToTaskBtn_17mlo_742:focus-visible{color:var(--text-primary)}._payloadBtn_17mlo_741{font-weight:700}._canvasScroller_17mlo_762{position:relative;flex:1;min-height:0;overflow:auto;display:block;scrollbar-gutter:stable;background:linear-gradient(45deg,color-mix(in srgb,var(--surface-inset) 66%,var(--border-default)) 25%,transparent 25%),linear-gradient(-45deg,color-mix(in srgb,var(--surface-inset) 66%,var(--border-default)) 25%,transparent 25%),linear-gradient(45deg,transparent 75%,color-mix(in srgb,var(--surface-inset) 66%,var(--border-default)) 75%),linear-gradient(-45deg,transparent 75%,color-mix(in srgb,var(--surface-inset) 66%,var(--border-default)) 75%);background-size:22px 22px;background-position:0 0,0 11px,11px -11px,-11px 0}._canvasFrame_17mlo_778{position:relative;display:block;width:max-content;min-width:100%}._canvasMedia_17mlo_785{position:relative;display:block;flex-shrink:0;margin:0 auto;overflow:hidden}._canvasStatusOverlay_17mlo_793{position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;padding:24px;background:color-mix(in srgb,var(--surface-scrim) 68%,transparent);pointer-events:none}._canvasStatusCard_17mlo_805{display:inline-flex;align-items:center;gap:10px;padding:12px 16px;border:1px solid color-mix(in srgb,var(--border-strong) 44%,white);border-radius:var(--radius-md);background:#0f172ac7;color:#fff;box-shadow:0 18px 30px #0f172a38;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}._canvasImage_17mlo_818{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}._overlay_17mlo_825{position:absolute;inset:0;cursor:crosshair}._overlaySelect_17mlo_831{cursor:default}._overlayPan_17mlo_835{cursor:grab}._overlaySvg_17mlo_839{position:absolute;inset:0;display:block;width:100%;height:100%;pointer-events:none}._overlayHitLayer_17mlo_848{position:absolute;inset:0;display:block;width:100%;height:100%;pointer-events:auto}._arrowHitArea_17mlo_857{stroke:transparent;stroke-width:24;pointer-events:stroke;cursor:move}._canvasHandleHit_17mlo_864{fill:transparent;pointer-events:all;cursor:grab;outline:none}._canvasResizeHandleHit_17mlo_871{cursor:nwse-resize}._canvasHandleVisible_17mlo_875{--canvas-handle-fill: var(--brand-primary);--canvas-handle-outline: var(--surface-elevated);--canvas-handle-shadow: 0 6px 12px rgba(15, 23, 42, .18);fill:var(--canvas-handle-fill);stroke:var(--canvas-handle-outline);stroke-width:3;vector-effect:non-scaling-stroke;filter:drop-shadow(var(--canvas-handle-shadow));pointer-events:none}._canvasHandleHit_17mlo_864:focus-visible+._canvasHandleVisible_17mlo_875{stroke:color-mix(in srgb,var(--brand-primary) 72%,var(--surface-elevated));stroke-width:4}._pin_17mlo_892,._note_17mlo_893{position:absolute;transform:translate(-50%,-50%);display:inline-flex;align-items:center;justify-content:center;min-width:28px;min-height:28px;border:2px solid var(--surface-elevated);border-radius:999px;box-shadow:0 8px 18px #0f172a38;color:#fff;font-size:.74rem;font-weight:800;pointer-events:auto}._annotationNumberBadge_17mlo_910{position:absolute;display:inline-flex;align-items:center;justify-content:center;min-width:28px;min-height:28px;padding:0 8px;border:2px solid var(--surface-elevated);border-radius:999px;box-shadow:0 8px 18px #0f172a38;color:#fff;font-size:.74rem;font-weight:800;line-height:1;pointer-events:none;z-index:2}._note_17mlo_893{min-width:38px;padding:0 10px;border-radius:999px}._box_17mlo_935{position:absolute;border:2px solid;border-radius:var(--radius-sm);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--surface-elevated) 34%,transparent);background:color-mix(in srgb,var(--surface-elevated) 10%,transparent);pointer-events:auto}._boxNumberBadge_17mlo_944{top:0;left:0;transform:translate(-28%,-36%)}._arrowNumberBadge_17mlo_950{transform:translate(-50%,-50%)}._boxSurface_17mlo_954{position:absolute;inset:0;border:0;background:transparent;cursor:move}._boxSurface_17mlo_954:focus-visible{outline:2px solid color-mix(in srgb,var(--brand-primary) 34%,var(--surface-elevated));outline-offset:2px}._selected_17mlo_967{outline:3px solid color-mix(in srgb,var(--surface-elevated) 92%,transparent);outline-offset:1px}._fieldGroup_17mlo_972{display:flex;flex-direction:column;gap:8px;padding:14px 16px}._detailPanel_17mlo_253 ._fieldGroup_17mlo_972{padding-top:12px;padding-bottom:12px}._textInput_17mlo_984,._textArea_17mlo_985,._select_17mlo_967{width:100%;box-sizing:border-box;font:inherit}._sessionTitleInput_17mlo_992{font-size:1rem;font-weight:600}._sessionInstructionField_17mlo_997{min-height:112px}._textArea_17mlo_985{min-height:110px;resize:vertical}._detailEmpty_17mlo_1006,._emptyState_17mlo_1007,._errorState_17mlo_1008{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;min-height:240px;padding:24px;text-align:center}._payloadModalBody_17mlo_1019{display:flex;flex-direction:column;gap:12px;min-height:0}._payloadModalToolbar_17mlo_1026{display:flex;align-items:center;justify-content:space-between;gap:12px}._payloadViewToggle_17mlo_1033,._payloadModalActions_17mlo_1034{display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px}._payloadModalPreview_17mlo_1041{margin:0;min-height:360px;max-height:min(70vh,720px);padding:16px;overflow:auto;scrollbar-gutter:stable;white-space:pre-wrap;word-break:break-word;font-size:.78rem;line-height:1.55;border-radius:var(--radius-md);color:var(--text-body)}._statusBar_17mlo_1056{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-top:1px solid var(--border-default);color:var(--text-secondary);font-size:.82rem;background:color-mix(in srgb,var(--surface-panel) 88%,var(--surface-inset))}._annotationSummary_17mlo_1068{font-size:.82rem;line-height:1.5}@media(max-width:1180px){._shell_17mlo_1{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(320px,1fr) auto;gap:12px;padding:12px}._sessionContextBar_17mlo_259,._panelHeader_17mlo_318,._toolRail_17mlo_564,._statusBar_17mlo_1056,._payloadModalToolbar_17mlo_1026,._markerHelpHeader_17mlo_393{flex-wrap:wrap}._sessionContextRight_17mlo_271,._sessionContextLeft_17mlo_270,._canvasHeading_17mlo_335{min-width:0}._sessionContextRight_17mlo_271{width:100%;justify-content:flex-start}._toolbarActions_17mlo_637{width:100%;margin-left:0}._toolbarUtilities_17mlo_703{margin-left:0}._toolGroup_17mlo_583{max-width:100%}._canvasWorkspace_17mlo_304{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}._toolbarViewportCluster_17mlo_601{margin-left:0}._canvasToolRail_17mlo_573{flex-direction:row;justify-content:flex-start;overflow-x:auto;padding:0;border-right:0;border-bottom:1px solid var(--border-default)}._statusBar_17mlo_1056{align-items:flex-start}._detailEmpty_17mlo_1006,._emptyState_17mlo_1007,._errorState_17mlo_1008{min-height:180px}}
|