@taskforcehq/taskforce 0.3.328 → 0.3.329
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/dist/Taskforce.module.css +233 -34
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +147 -40
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +7 -31
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/config/envSchema.js +12 -0
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/Taskforce.d.ts +62 -2
- package/dist/core/Taskforce.js +635 -32
- package/dist/core/types.d.ts +6 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useTaskData.d.ts +10 -1
- package/dist/hooks/useTaskData.js +216 -7
- package/dist/hooks/useTaskMutations.d.ts +10 -2
- package/dist/hooks/useTaskMutations.js +223 -43
- package/dist/hooks/useTaskforce.d.ts +37 -9
- package/dist/hooks/useTaskforce.js +349 -39
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/documentAssetRegistrar.js +44 -35
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/runtime.js +172 -42
- package/dist/mcp/taskPlanningRegistrar.js +41 -38
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/migrations/taskSchemaMigrations.js +12 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +12 -13
- package/dist/runtime/appGates.js +29 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +15 -3
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +9 -1
- package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.js +1 -0
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.js +118 -16
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +9 -2
- package/dist/server/routes/localService.js +2 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncV3FeedRoutes.js +18 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +10 -0
- package/dist/server/routes/tasks.js +103 -11
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +112 -0
- package/dist/services/codexAppServerModelGateway.js +438 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
- package/dist/services/taskforceAgentMcpBridge.js +23 -3
- package/dist/shared/taskforceAgentDefinition.js +7 -1
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +30 -1
- package/dist/storage/postgresAdapter.d.ts +20 -3
- package/dist/storage/postgresAdapter.js +106 -14
- package/dist/storage/postgresWorker.js +13 -4
- package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +7 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +25 -8
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
- package/dist/sync/syncService.d.ts +2 -0
- package/dist/sync/syncService.js +4 -1
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +11 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
- package/dist/sync/v3/syncDurabilityStore.d.ts +7 -0
- package/dist/sync/v3/syncDurabilityStore.js +31 -11
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
- package/dist/sync/v3/taskChecklistMutationService.js +4 -0
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
- package/dist/sync/v3/taskStatusMutationService.js +4 -0
- package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
- package/dist/sync/v3/workflowAssignmentSync.js +3 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -1
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +30 -18
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +98 -47
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +58 -21
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +3 -0
- package/dist/sync/workspaceRepair.js +67 -6
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/{AiIdentityRosterCard-MZs7lVED.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-C8Rztyal.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Cj3c7X9y.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-B5uvzems.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-BVFvCB5R.js} +1 -1
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
- package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
- package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
- package/dist/ui/assets/{TaskforceAgentsModule-BazdUwxZ.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DEr5di_r.js} +1 -1
- package/dist/ui/assets/index-I5zhdtgt.js +7 -0
- package/dist/ui/assets/index-VRFsx3wz.css +1 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-D9Lpw-j4.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/package.json +16 -4
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
package/dist/ui/index.html
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
|
|
9
9
|
<link rel="apple-touch-icon" href="/taskforce/favicon/apple-touch-icon.png" />
|
|
10
10
|
<title>Taskforce</title>
|
|
11
|
-
<script type="module" crossorigin src="/taskforce/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/taskforce/assets/index-I5zhdtgt.js"></script>
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-react-CKJs5o3c.js">
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-D9Lpw-j4.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-markdown-_lhNCyq-.js">
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-dnd-CJ-AjP-Y.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-router-AqJMU8Lz.js">
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-VRFsx3wz.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="root"></div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EntityActivityItem, EntityEvent, TaskActivityItem, TaskEvent, TaskItem } from '../types';
|
|
1
|
+
import type { EntityActivityItem, EntityEvent, TaskActivityItem, TaskActivitySummaryItem, TaskEvent, TaskItem } from '../types';
|
|
2
2
|
export type TaskEventValueFormatter = (field: string, value: unknown) => string | undefined;
|
|
3
3
|
type AttachmentChange = {
|
|
4
4
|
from?: unknown;
|
|
@@ -11,6 +11,7 @@ type AttachmentChange = {
|
|
|
11
11
|
};
|
|
12
12
|
export declare function summarizeTaskChange(field: string, change: AttachmentChange | undefined, formatter?: TaskEventValueFormatter): string;
|
|
13
13
|
export declare function summarizeTaskEvent(event: TaskEvent, formatter?: TaskEventValueFormatter): string;
|
|
14
|
+
export declare function summarizeTaskEvent(event: Pick<TaskEvent, 'action' | 'details'>, formatter?: TaskEventValueFormatter): string;
|
|
14
15
|
export declare function summarizeEntityEvent(event: EntityEvent, formatter?: TaskEventValueFormatter): string;
|
|
15
16
|
export declare function getTaskEventPrimaryChangeField(event: TaskEvent): string | null;
|
|
16
17
|
export declare function getEntityEventPrimaryChangeField(event: EntityEvent): string | null;
|
|
@@ -20,5 +21,5 @@ export declare function getEntityActivityItems(task: {
|
|
|
20
21
|
}): EntityActivityItem[];
|
|
21
22
|
export declare function getTaskActivityItems(task: Pick<TaskItem, 'activity' | 'comments'>): TaskActivityItem[];
|
|
22
23
|
export declare function getLatestTaskActivity(task: Pick<TaskItem, 'activity' | 'comments'>): TaskActivityItem | null;
|
|
23
|
-
export declare function summarizeTaskActivity(item: TaskActivityItem | null, formatter?: TaskEventValueFormatter): string;
|
|
24
|
+
export declare function summarizeTaskActivity(item: TaskActivityItem | TaskActivitySummaryItem | null, formatter?: TaskEventValueFormatter): string;
|
|
24
25
|
export {};
|
|
@@ -5,8 +5,6 @@ function getActivityFieldLabel(field) {
|
|
|
5
5
|
return 'Title';
|
|
6
6
|
if (field === 'description')
|
|
7
7
|
return 'Description';
|
|
8
|
-
if (field === 'assignee')
|
|
9
|
-
return 'Assigned to';
|
|
10
8
|
if (field === 'ownerId')
|
|
11
9
|
return 'Owner';
|
|
12
10
|
if (field === 'status')
|
|
@@ -21,6 +19,14 @@ function getActivityFieldLabel(field) {
|
|
|
21
19
|
return 'Initiative';
|
|
22
20
|
return field;
|
|
23
21
|
}
|
|
22
|
+
function isUnassignedActivityValue(value) {
|
|
23
|
+
const normalized = String(value ?? '').trim().toLowerCase();
|
|
24
|
+
return !normalized
|
|
25
|
+
|| normalized === 'none'
|
|
26
|
+
|| normalized === 'null'
|
|
27
|
+
|| normalized === 'unassigned'
|
|
28
|
+
|| normalized === 'user';
|
|
29
|
+
}
|
|
24
30
|
function formatStatusValue(value) {
|
|
25
31
|
if (value === 'task')
|
|
26
32
|
return 'Task';
|
|
@@ -277,6 +283,17 @@ export function summarizeTaskChange(field, change, formatter) {
|
|
|
277
283
|
if (field === 'attachments') {
|
|
278
284
|
return summarizeAttachmentChange(change);
|
|
279
285
|
}
|
|
286
|
+
if (field === 'assignee') {
|
|
287
|
+
const previousAssignee = formatValue(change?.from, field, formatter);
|
|
288
|
+
const nextAssignee = formatValue(change?.to, field, formatter);
|
|
289
|
+
if (isUnassignedActivityValue(change?.from) && !isUnassignedActivityValue(change?.to)) {
|
|
290
|
+
return `Assigned to ${nextAssignee}`;
|
|
291
|
+
}
|
|
292
|
+
if (!isUnassignedActivityValue(change?.from) && isUnassignedActivityValue(change?.to)) {
|
|
293
|
+
return `Unassigned from ${previousAssignee}`;
|
|
294
|
+
}
|
|
295
|
+
return `Reassigned: ${previousAssignee} → ${nextAssignee}`;
|
|
296
|
+
}
|
|
280
297
|
const label = getActivityFieldLabel(field);
|
|
281
298
|
if (field === 'title') {
|
|
282
299
|
return `${label}: updated`;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AttachmentItem, ChecklistItem, TaskAssignee, TaskItem, TaskStatus } from '../types';
|
|
2
|
+
export interface TaskEditorDraft {
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
category: string;
|
|
6
|
+
type: string;
|
|
7
|
+
priority: number | string;
|
|
8
|
+
complexity: number;
|
|
9
|
+
status: TaskStatus;
|
|
10
|
+
assignee: TaskAssignee;
|
|
11
|
+
scheduledDate: string;
|
|
12
|
+
dueDate: string;
|
|
13
|
+
workstreamId: string;
|
|
14
|
+
taxonomies: Record<string, string | number | string[] | number[]>;
|
|
15
|
+
checklistItems: ChecklistItem[];
|
|
16
|
+
attachments: Array<string | AttachmentItem>;
|
|
17
|
+
}
|
|
18
|
+
export type TaskEditorScalarField = Exclude<keyof TaskEditorDraft, 'taxonomies' | 'checklistItems' | 'attachments'>;
|
|
19
|
+
export type TaskEditorConflict = {
|
|
20
|
+
field: TaskEditorScalarField;
|
|
21
|
+
} | {
|
|
22
|
+
field: 'taxonomies';
|
|
23
|
+
key: string;
|
|
24
|
+
} | {
|
|
25
|
+
field: 'checklistItems' | 'attachments';
|
|
26
|
+
key: string;
|
|
27
|
+
};
|
|
28
|
+
export interface TaskEditorReconciliation {
|
|
29
|
+
merged: TaskEditorDraft;
|
|
30
|
+
conflicts: TaskEditorConflict[];
|
|
31
|
+
remoteChangedFields: string[];
|
|
32
|
+
}
|
|
33
|
+
export declare function taskToEditorDraft(task: TaskItem): TaskEditorDraft;
|
|
34
|
+
export declare function applyEditorDraftToTask(task: TaskItem, draft: TaskEditorDraft): TaskItem;
|
|
35
|
+
export declare function reconcileTaskEditorDraft(base: TaskEditorDraft, local: TaskEditorDraft, remote: TaskEditorDraft): TaskEditorReconciliation;
|
|
36
|
+
export declare function resolveTaskEditorConflicts(reconciliation: TaskEditorReconciliation, remote: TaskEditorDraft, resolution: 'latest' | 'local', current?: TaskEditorDraft): TaskEditorDraft;
|
|
37
|
+
export declare function isTaskEditorConflictAligned(conflict: TaskEditorConflict, local: TaskEditorDraft, remote: TaskEditorDraft): boolean;
|
|
38
|
+
export declare function taskEditorConflictKey(conflict: TaskEditorConflict): string;
|
|
39
|
+
export declare function preserveUnresolvedTaskEditorConflicts(existing: TaskEditorConflict[], next: TaskEditorConflict[], local: TaskEditorDraft, remote: TaskEditorDraft): TaskEditorConflict[];
|
|
40
|
+
export declare function formatTaskEditorConflictFields(conflicts: TaskEditorConflict[]): string[];
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { canonicalWorkspaceSyncJson } from '../sync/v3/canonicalWorkspaceSyncJson.js';
|
|
2
|
+
const SCALAR_FIELDS = [
|
|
3
|
+
'title',
|
|
4
|
+
'description',
|
|
5
|
+
'category',
|
|
6
|
+
'type',
|
|
7
|
+
'priority',
|
|
8
|
+
'complexity',
|
|
9
|
+
'status',
|
|
10
|
+
'assignee',
|
|
11
|
+
'scheduledDate',
|
|
12
|
+
'dueDate',
|
|
13
|
+
'workstreamId',
|
|
14
|
+
];
|
|
15
|
+
export function taskToEditorDraft(task) {
|
|
16
|
+
return {
|
|
17
|
+
title: task.title || '',
|
|
18
|
+
description: task.description || '',
|
|
19
|
+
category: task.category || '',
|
|
20
|
+
type: task.type || '',
|
|
21
|
+
priority: task.priority,
|
|
22
|
+
complexity: Number(task.complexity) || 3,
|
|
23
|
+
status: task.status || 'task',
|
|
24
|
+
assignee: task.assignee || 'unassigned',
|
|
25
|
+
scheduledDate: task.scheduledDate || '',
|
|
26
|
+
dueDate: task.dueDate || '',
|
|
27
|
+
workstreamId: task.workstreamId || '',
|
|
28
|
+
taxonomies: { ...(task.taxonomies || {}) },
|
|
29
|
+
checklistItems: [...(task.checklistItems || [])],
|
|
30
|
+
attachments: [...(task.attachments || [])],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function applyEditorDraftToTask(task, draft) {
|
|
34
|
+
return {
|
|
35
|
+
...task,
|
|
36
|
+
title: draft.title,
|
|
37
|
+
description: draft.description || null,
|
|
38
|
+
category: draft.category,
|
|
39
|
+
type: draft.type,
|
|
40
|
+
priority: draft.priority,
|
|
41
|
+
complexity: draft.complexity,
|
|
42
|
+
status: draft.status,
|
|
43
|
+
assignee: draft.assignee,
|
|
44
|
+
scheduledDate: draft.scheduledDate || null,
|
|
45
|
+
dueDate: draft.dueDate || null,
|
|
46
|
+
workstreamId: draft.workstreamId || null,
|
|
47
|
+
taxonomies: draft.taxonomies,
|
|
48
|
+
checklistItems: draft.checklistItems,
|
|
49
|
+
attachments: draft.attachments,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function equal(left, right) {
|
|
53
|
+
return canonicalWorkspaceSyncJson(left ?? null) === canonicalWorkspaceSyncJson(right ?? null);
|
|
54
|
+
}
|
|
55
|
+
function mergeValue(base, local, remote) {
|
|
56
|
+
const localChanged = !equal(local, base);
|
|
57
|
+
const remoteChanged = !equal(remote, base);
|
|
58
|
+
if (!localChanged)
|
|
59
|
+
return { value: remote, conflict: false, remoteChanged };
|
|
60
|
+
if (!remoteChanged || equal(local, remote))
|
|
61
|
+
return { value: local, conflict: false, remoteChanged };
|
|
62
|
+
return { value: local, conflict: true, remoteChanged };
|
|
63
|
+
}
|
|
64
|
+
function attachmentKey(attachment) {
|
|
65
|
+
if (typeof attachment === 'string')
|
|
66
|
+
return `path:${attachment}`;
|
|
67
|
+
if (attachment.assetId)
|
|
68
|
+
return `asset:${attachment.assetId}`;
|
|
69
|
+
if (attachment.referenceLabel)
|
|
70
|
+
return `reference:${attachment.referenceLabel}`;
|
|
71
|
+
if (attachment.referenceNumber != null)
|
|
72
|
+
return `number:${attachment.referenceNumber}`;
|
|
73
|
+
return `path:${attachment.path || attachment.fsPath || canonicalWorkspaceSyncJson(attachment)}`;
|
|
74
|
+
}
|
|
75
|
+
function mergeKeyedCollection(baseItems, localItems, remoteItems, getKey) {
|
|
76
|
+
const base = new Map(baseItems.map((item) => [getKey(item), item]));
|
|
77
|
+
const local = new Map(localItems.map((item) => [getKey(item), item]));
|
|
78
|
+
const remote = new Map(remoteItems.map((item) => [getKey(item), item]));
|
|
79
|
+
const keys = new Set([...base.keys(), ...remote.keys(), ...local.keys()]);
|
|
80
|
+
const merged = new Map();
|
|
81
|
+
const conflictKeys = [];
|
|
82
|
+
for (const key of keys) {
|
|
83
|
+
const baseItem = base.get(key);
|
|
84
|
+
const localItem = local.get(key);
|
|
85
|
+
const remoteItem = remote.get(key);
|
|
86
|
+
const result = mergeValue(baseItem, localItem, remoteItem);
|
|
87
|
+
if (result.value !== undefined)
|
|
88
|
+
merged.set(key, result.value);
|
|
89
|
+
if (result.conflict)
|
|
90
|
+
conflictKeys.push(key);
|
|
91
|
+
}
|
|
92
|
+
const orderedKeys = [
|
|
93
|
+
...remoteItems.map(getKey),
|
|
94
|
+
...localItems.map(getKey).filter((key) => !remote.has(key)),
|
|
95
|
+
].filter((key, index, all) => all.indexOf(key) === index && merged.has(key));
|
|
96
|
+
return {
|
|
97
|
+
items: orderedKeys.map((key) => merged.get(key)),
|
|
98
|
+
conflictKeys,
|
|
99
|
+
remoteChanged: !equal(baseItems, remoteItems),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function reconcileTaskEditorDraft(base, local, remote) {
|
|
103
|
+
const merged = { ...remote };
|
|
104
|
+
const conflicts = [];
|
|
105
|
+
const remoteChangedFields = new Set();
|
|
106
|
+
for (const field of SCALAR_FIELDS) {
|
|
107
|
+
const result = mergeValue(base[field], local[field], remote[field]);
|
|
108
|
+
merged[field] = result.value;
|
|
109
|
+
if (result.conflict)
|
|
110
|
+
conflicts.push({ field });
|
|
111
|
+
if (result.remoteChanged)
|
|
112
|
+
remoteChangedFields.add(field);
|
|
113
|
+
}
|
|
114
|
+
const taxonomyKeys = new Set([
|
|
115
|
+
...Object.keys(base.taxonomies),
|
|
116
|
+
...Object.keys(local.taxonomies),
|
|
117
|
+
...Object.keys(remote.taxonomies),
|
|
118
|
+
]);
|
|
119
|
+
const mergedTaxonomies = {};
|
|
120
|
+
for (const key of taxonomyKeys) {
|
|
121
|
+
const result = mergeValue(base.taxonomies[key], local.taxonomies[key], remote.taxonomies[key]);
|
|
122
|
+
if (result.value !== undefined)
|
|
123
|
+
mergedTaxonomies[key] = result.value;
|
|
124
|
+
if (result.conflict)
|
|
125
|
+
conflicts.push({ field: 'taxonomies', key });
|
|
126
|
+
if (result.remoteChanged)
|
|
127
|
+
remoteChangedFields.add(`taxonomies.${key}`);
|
|
128
|
+
}
|
|
129
|
+
merged.taxonomies = mergedTaxonomies;
|
|
130
|
+
const checklist = mergeKeyedCollection(base.checklistItems, local.checklistItems, remote.checklistItems, (item) => item.id);
|
|
131
|
+
merged.checklistItems = checklist.items;
|
|
132
|
+
checklist.conflictKeys.forEach((key) => conflicts.push({ field: 'checklistItems', key }));
|
|
133
|
+
if (checklist.remoteChanged)
|
|
134
|
+
remoteChangedFields.add('checklistItems');
|
|
135
|
+
const attachments = mergeKeyedCollection(base.attachments, local.attachments, remote.attachments, attachmentKey);
|
|
136
|
+
merged.attachments = attachments.items;
|
|
137
|
+
attachments.conflictKeys.forEach((key) => conflicts.push({ field: 'attachments', key }));
|
|
138
|
+
if (attachments.remoteChanged)
|
|
139
|
+
remoteChangedFields.add('attachments');
|
|
140
|
+
return { merged, conflicts, remoteChangedFields: [...remoteChangedFields] };
|
|
141
|
+
}
|
|
142
|
+
export function resolveTaskEditorConflicts(reconciliation, remote, resolution, current = reconciliation.merged) {
|
|
143
|
+
if (resolution === 'local')
|
|
144
|
+
return current;
|
|
145
|
+
const resolved = {
|
|
146
|
+
...current,
|
|
147
|
+
taxonomies: { ...current.taxonomies },
|
|
148
|
+
checklistItems: [...current.checklistItems],
|
|
149
|
+
attachments: [...current.attachments],
|
|
150
|
+
};
|
|
151
|
+
for (const conflict of reconciliation.conflicts) {
|
|
152
|
+
if (conflict.field === 'taxonomies') {
|
|
153
|
+
const value = remote.taxonomies[conflict.key];
|
|
154
|
+
if (value === undefined)
|
|
155
|
+
delete resolved.taxonomies[conflict.key];
|
|
156
|
+
else
|
|
157
|
+
resolved.taxonomies[conflict.key] = value;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (conflict.field === 'checklistItems' || conflict.field === 'attachments') {
|
|
161
|
+
const getKey = conflict.field === 'checklistItems'
|
|
162
|
+
? (item) => item.id
|
|
163
|
+
: (item) => attachmentKey(item);
|
|
164
|
+
const current = resolved[conflict.field];
|
|
165
|
+
const latest = remote[conflict.field];
|
|
166
|
+
const latestItem = latest.find((item) => getKey(item) === conflict.key);
|
|
167
|
+
const withoutConflict = current.filter((item) => getKey(item) !== conflict.key);
|
|
168
|
+
resolved[conflict.field] = latestItem
|
|
169
|
+
? [...withoutConflict, latestItem]
|
|
170
|
+
: withoutConflict;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
resolved[conflict.field] = remote[conflict.field];
|
|
174
|
+
}
|
|
175
|
+
return resolved;
|
|
176
|
+
}
|
|
177
|
+
export function isTaskEditorConflictAligned(conflict, local, remote) {
|
|
178
|
+
if (conflict.field === 'taxonomies') {
|
|
179
|
+
return equal(local.taxonomies[conflict.key], remote.taxonomies[conflict.key]);
|
|
180
|
+
}
|
|
181
|
+
if (conflict.field === 'checklistItems') {
|
|
182
|
+
return equal(local.checklistItems.find((item) => item.id === conflict.key), remote.checklistItems.find((item) => item.id === conflict.key));
|
|
183
|
+
}
|
|
184
|
+
if (conflict.field === 'attachments') {
|
|
185
|
+
return equal(local.attachments.find((item) => attachmentKey(item) === conflict.key), remote.attachments.find((item) => attachmentKey(item) === conflict.key));
|
|
186
|
+
}
|
|
187
|
+
return equal(local[conflict.field], remote[conflict.field]);
|
|
188
|
+
}
|
|
189
|
+
export function taskEditorConflictKey(conflict) {
|
|
190
|
+
return 'key' in conflict ? `${conflict.field}:${conflict.key}` : conflict.field;
|
|
191
|
+
}
|
|
192
|
+
export function preserveUnresolvedTaskEditorConflicts(existing, next, local, remote) {
|
|
193
|
+
const conflictsByKey = new Map([
|
|
194
|
+
...existing.filter((conflict) => !isTaskEditorConflictAligned(conflict, local, remote)),
|
|
195
|
+
...next,
|
|
196
|
+
].map((conflict) => [taskEditorConflictKey(conflict), conflict]));
|
|
197
|
+
return [...conflictsByKey.values()];
|
|
198
|
+
}
|
|
199
|
+
export function formatTaskEditorConflictFields(conflicts) {
|
|
200
|
+
const labels = {
|
|
201
|
+
title: 'title',
|
|
202
|
+
description: 'description',
|
|
203
|
+
category: 'category',
|
|
204
|
+
type: 'type',
|
|
205
|
+
priority: 'priority',
|
|
206
|
+
complexity: 'complexity',
|
|
207
|
+
status: 'status',
|
|
208
|
+
assignee: 'assignee',
|
|
209
|
+
scheduledDate: 'scheduled date',
|
|
210
|
+
dueDate: 'due date',
|
|
211
|
+
workstreamId: 'workstream',
|
|
212
|
+
taxonomies: 'taxonomy',
|
|
213
|
+
checklistItems: 'checklist',
|
|
214
|
+
attachments: 'attachments',
|
|
215
|
+
};
|
|
216
|
+
return [...new Set(conflicts.map((conflict) => labels[conflict.field] || String(conflict.field)))];
|
|
217
|
+
}
|
|
@@ -13,6 +13,7 @@ export declare function normalizePriorityDefinitions(priorities: PriorityDefinit
|
|
|
13
13
|
changed: boolean;
|
|
14
14
|
};
|
|
15
15
|
export declare function normalizeTaskFromApi(task: any): TaskItem;
|
|
16
|
+
export declare function toTaskCollectionSummary(task: TaskItem): TaskItem;
|
|
16
17
|
export declare function getTaskContentRevision(task: TaskItem): string;
|
|
17
18
|
export declare function reconcileTaskCollection(previous: TaskItem[], incoming: TaskItem[]): TaskItem[];
|
|
18
19
|
export declare function mergeNormalizedTaskIntoCollections(task: unknown, tasks: TaskItem[], archivedTasks: TaskItem[]): {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cloneDefaultPriorityDefinitions } from '../shared/taxonomyDefaults.js';
|
|
2
2
|
import { formatLocalTaskReference, formatTaskReference } from './taskReferences.js';
|
|
3
|
+
import { getLatestTaskActivity } from './taskActivity.js';
|
|
3
4
|
export const DEFAULT_PRIORITY_DEFINITIONS = cloneDefaultPriorityDefinitions();
|
|
4
5
|
const PRIORITY_VALUE_BY_LABEL = {
|
|
5
6
|
low: 1,
|
|
@@ -96,6 +97,44 @@ export function normalizeTaskFromApi(task) {
|
|
|
96
97
|
status: normalizeTaskStatus(task.status)
|
|
97
98
|
};
|
|
98
99
|
}
|
|
100
|
+
export function toTaskCollectionSummary(task) {
|
|
101
|
+
const { description: _description, comments, activity: _activity, taskEvents: _taskEvents, attachments, checklistItems, createdByActor: _createdByActor, assigneeActor: _assigneeActor, ...summary } = task;
|
|
102
|
+
const latestRevision = (values) => values.reduce((latest, value) => String(value || '') > latest ? String(value || '') : latest, '');
|
|
103
|
+
const commentCount = task.commentCount ?? comments?.length ?? 0;
|
|
104
|
+
const checklistCount = task.checklistCount ?? checklistItems?.length ?? 0;
|
|
105
|
+
const completedChecklistCount = task.completedChecklistCount
|
|
106
|
+
?? checklistItems?.filter((item) => item.isCompleted).length
|
|
107
|
+
?? 0;
|
|
108
|
+
const attachmentCount = task.attachmentCount ?? attachments?.length ?? 0;
|
|
109
|
+
const relationshipCount = task.relationshipCount ?? 0;
|
|
110
|
+
const latestActivity = task.latestActivity ?? getLatestTaskActivity(task);
|
|
111
|
+
return {
|
|
112
|
+
...summary,
|
|
113
|
+
cardCoverAttachment: task.cardCoverAttachment ?? (task.cardCoverAssetId
|
|
114
|
+
? attachments?.find((attachment) => (typeof attachment !== 'string' && attachment.assetId === task.cardCoverAssetId)) || null
|
|
115
|
+
: null),
|
|
116
|
+
isSummary: true,
|
|
117
|
+
commentCount,
|
|
118
|
+
checklistCount,
|
|
119
|
+
completedChecklistCount,
|
|
120
|
+
attachmentCount,
|
|
121
|
+
relationshipCount,
|
|
122
|
+
latestActivity,
|
|
123
|
+
detailRevision: task.detailRevision || JSON.stringify([
|
|
124
|
+
String(task.updatedAt || task.createdAt || ''),
|
|
125
|
+
commentCount,
|
|
126
|
+
latestRevision(comments?.map((comment) => comment.timestamp) || []),
|
|
127
|
+
checklistCount,
|
|
128
|
+
completedChecklistCount,
|
|
129
|
+
latestRevision(checklistItems?.map((item) => item.updatedAt || item.createdAt) || []),
|
|
130
|
+
attachmentCount,
|
|
131
|
+
latestRevision(attachments?.map((attachment) => typeof attachment === 'string' ? '' : attachment.timestamp) || []),
|
|
132
|
+
relationshipCount,
|
|
133
|
+
latestActivity?.timestamp || '',
|
|
134
|
+
latestActivity?.id || '',
|
|
135
|
+
]),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
99
138
|
export function getTaskContentRevision(task) {
|
|
100
139
|
// Use the complete normalized snapshot: some task changes can arrive without a
|
|
101
140
|
// distinct updatedAt value, so a timestamp-only key could retain stale UI data.
|
package/dist/utils/taskSearch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { STATUS_OPTIONS } from './constants';
|
|
2
|
-
import { getTaskReferenceLabel } from './taskReferences';
|
|
1
|
+
import { STATUS_OPTIONS } from './constants.js';
|
|
2
|
+
import { getTaskReferenceLabel } from './taskReferences.js';
|
|
3
3
|
const DASH_LIKE_PATTERN = /[\u2010-\u2015\u2212]/g;
|
|
4
4
|
export function normalizeSearchText(value) {
|
|
5
5
|
return String(value ?? '')
|
package/dist/utils/uiNotice.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ export interface UiNotice {
|
|
|
5
5
|
ttlMs?: number;
|
|
6
6
|
actionLabel?: string;
|
|
7
7
|
onAction?: () => void;
|
|
8
|
+
actionPrimary?: boolean;
|
|
9
|
+
secondaryActionLabel?: string;
|
|
10
|
+
onSecondaryAction?: () => void;
|
|
11
|
+
dismissible?: boolean;
|
|
8
12
|
ownerKey?: string;
|
|
9
13
|
}
|
|
10
14
|
export declare function resolveUiNoticeTtl(tone: UiNoticeTone, ttlMs?: number): number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskforcehq/taskforce",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.329",
|
|
4
4
|
"description": "Shared task and planning workspace for humans collaborating with AI (public beta)",
|
|
5
5
|
"author": "Taskforce HQ <hello@taskforcehq.ai> (https://taskforcehq.ai)",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"mcp": "node dist/cli.js mcp",
|
|
68
68
|
"gen:mcp-contract": "node --import tsx scripts/generate-mcp-contract.ts",
|
|
69
69
|
"check:mcp-contract": "node --import tsx scripts/generate-mcp-contract.ts --check",
|
|
70
|
+
"measure:agent-prefix-cost": "node scripts/measure-agent-prefix-cost.mjs",
|
|
70
71
|
"cleanup:legacy-ai-avatars": "node --import tsx scripts/cleanup-legacy-ai-profile-avatar-assets.ts",
|
|
71
72
|
"db:export:postgres": "node scripts/export-sqlite-to-postgres.mjs",
|
|
72
73
|
"check:localization-strings": "node scripts/check-localization-strings.mjs",
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
"test:sync:recovery:coordinator": "vitest run src/test/syncRecoveryGate.test.ts src/test/syncRecoveryCoordinatorOwnership.test.ts src/test/syncRecoveryExecutionPermitExpiry.test.ts",
|
|
88
89
|
"test:sqlite:multiprocess": "TASKFORCE_SQLITE_MULTIPROCESS_GATE=true vitest run src/storage/sqliteWalMultiprocess.integration.test.ts",
|
|
89
90
|
"test:mcp:shared-local:gate-b": "npm run build && TASKFORCE_SHARED_LOCAL_MCP_GATE_B=true vitest run src/mcp/proxyServerBoundary.test.ts src/mcp/sharedLocalService.acceptance.test.ts",
|
|
90
|
-
"test:mcp:shared-local:gate-c": "npm run build && TASKFORCE_SHARED_LOCAL_OPEN_GATE_C=true vitest run src/service/localServiceClientLifecycle.test.ts src/server/localServiceLease.test.ts src/service/localServiceOpen.test.ts src/service/localServiceOpen.acceptance.test.ts",
|
|
91
|
+
"test:mcp:shared-local:gate-c": "npm run build && TASKFORCE_SHARED_LOCAL_OPEN_GATE_C=true vitest run --exclude '.worktrees/**' src/service/localServiceClientLifecycle.test.ts src/server/localServiceLease.test.ts src/service/localServiceOpen.test.ts src/service/localServiceOpen.acceptance.test.ts",
|
|
91
92
|
"test:mcp:shared-local:gate-d": "vitest run src/mcp/sharedLocalService.gateD.acceptance.test.ts",
|
|
92
93
|
"gate:mcp:shared-local:d:init": "node --import tsx scripts/run-shared-local-mcp-gate-d.ts --init",
|
|
93
94
|
"gate:mcp:shared-local:d:prerequisites": "node --import tsx scripts/run-shared-local-mcp-gate-d.ts --run-prerequisites",
|
|
@@ -103,6 +104,17 @@
|
|
|
103
104
|
"test:soak:stress": "SYNC_SOAK_PROFILE=stress sh scripts/run-soak.sh",
|
|
104
105
|
"test:soak:overnight": "SYNC_SOAK_PROFILE=overnight sh scripts/run-soak.sh",
|
|
105
106
|
"test:aqr:contract": "vitest run scripts/aqr/execution-capsule.test.ts",
|
|
107
|
+
"test:aqr:sync-coverage": "vitest run scripts/aqr/sync-coverage-contract.test.ts",
|
|
108
|
+
"test:aqr:multi-client": "vitest run scripts/aqr/multi-client-replay.test.ts scripts/aqr/qa-multi-client-adapter.test.ts",
|
|
109
|
+
"test:aqr:convergence": "vitest run scripts/aqr/convergence-oracle.test.ts",
|
|
110
|
+
"test:aqr:pr-sync-gate:contract": "vitest run scripts/aqr/pr-sync-gate.test.ts",
|
|
111
|
+
"test:aqr:pr-sync-gate": "node --import tsx scripts/aqr/pr-sync-gate.ts",
|
|
112
|
+
"test:aqr:sync-fault-matrix:contract": "vitest run scripts/aqr/sync-fault-matrix.test.ts",
|
|
113
|
+
"test:aqr:sync-fault-matrix": "node --import tsx scripts/aqr/sync-fault-matrix.ts",
|
|
114
|
+
"test:aqr:cloud-writers:contract": "vitest run scripts/aqr/cloud-writer-acceptance.test.ts",
|
|
115
|
+
"test:aqr:cloud-writers": "node --import tsx scripts/aqr/cloud-writer-acceptance.ts",
|
|
116
|
+
"test:aqr:remote-sync:contract": "vitest run scripts/aqr/remote-sync-run.test.ts",
|
|
117
|
+
"test:aqr:remote-sync": "node --import tsx scripts/aqr/remote-sync-run.ts",
|
|
106
118
|
"aqr:smoke": "node --import tsx scripts/run-aqr-capsule.ts --contract-smoke",
|
|
107
119
|
"test:e2e:realtime": "sh scripts/run-e2e-realtime.sh",
|
|
108
120
|
"test:e2e:realtime:release": "npm run test:e2e:realtime -- tests/e2e/attachment-sync.spec.ts tests/e2e/realtime-multiclient.spec.ts tests/e2e/realtime-reconnect.spec.ts",
|
|
@@ -110,7 +122,7 @@
|
|
|
110
122
|
"test:e2e:realtime:multiclient": "npm run test:e2e:realtime -- tests/e2e/realtime-multiclient.spec.ts",
|
|
111
123
|
"test:e2e:realtime:reconnect": "npm run test:e2e:realtime -- tests/e2e/realtime-reconnect.spec.ts",
|
|
112
124
|
"test:e2e:sync-coordinator": "SYNC_COORDINATOR_CANARY_ENABLED=true npm run test:e2e:realtime -- tests/e2e/sync-coordinator-multiclient.spec.ts",
|
|
113
|
-
"test:e2e:sync-coordinator:workspace-switch": "SYNC_COORDINATOR_WORKSPACE_SWITCH_CANARY_ENABLED=true npm run test:e2e:realtime -- tests/e2e/sync-coordinator-workspace-switch.spec.ts",
|
|
125
|
+
"test:e2e:sync-coordinator:workspace-switch": "SYNC_SOAK_CLOUD_BASE_URL=${SYNC_SOAK_CLOUD_BASE_URL:-https://staging-app.taskforcehq.ai} SYNC_COORDINATOR_WORKSPACE_SWITCH_CANARY_ENABLED=true npm run test:e2e:realtime -- tests/e2e/sync-coordinator-workspace-switch.spec.ts",
|
|
114
126
|
"test:e2e:sync-coordinator:process": "npm run test:e2e:realtime -- tests/e2e/sync-coordinator-process-ownership.spec.ts",
|
|
115
127
|
"test:e2e:realtime:durable-task-metadata": "npm run test:e2e:realtime -- tests/e2e/durable-task-metadata-canary.spec.ts",
|
|
116
128
|
"test:e2e:realtime:durable-task-create": "npm run test:e2e:realtime -- tests/e2e/durable-task-create-canary.spec.ts",
|
|
@@ -171,6 +183,7 @@
|
|
|
171
183
|
"ajv": "~8.18.0",
|
|
172
184
|
"better-sqlite3": "^12.6.2",
|
|
173
185
|
"chokidar": "^3.6.0",
|
|
186
|
+
"lucide-react": "^0.474.0",
|
|
174
187
|
"nodemailer": "^9.0.3",
|
|
175
188
|
"openai": "^6.45.0",
|
|
176
189
|
"pg": "^8.18.0",
|
|
@@ -197,7 +210,6 @@
|
|
|
197
210
|
"concurrently": "^8.2.2",
|
|
198
211
|
"html2canvas": "^1.4.1",
|
|
199
212
|
"jsdom": "^27.4.0",
|
|
200
|
-
"lucide-react": "^0.474.0",
|
|
201
213
|
"react": "^19.0.0",
|
|
202
214
|
"react-dom": "^19.0.0",
|
|
203
215
|
"react-markdown": "^9.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as f,j as a}from"./vendor-react-CKJs5o3c.js";import{ac as Qe,ad as re,O as Ue,ae as ea,af as W,t as r,U as aa,V as ra,ag as ta,ah as Re,W as ia,ai as oa,aj as te,ak as Me,al as la,Y as sa,X as Ee,$ as b,a0 as ke}from"./index-BUplSsv_.js";import{A as na,b as ca,r as Ce}from"./AiIdentityRosterCard-MZs7lVED.js";import{ay as da,ai as fa,U as ua,w as pa,Z as J,J as Le,ax as ma,aC as va}from"./vendor-icons-BkFLXavV.js";import"./vendor-markdown-_lhNCyq-.js";import"./vendor-dnd-CJ-AjP-Y.js";import"./vendor-router-AqJMU8Lz.js";const ga=["chat_app","ide","cli","coding_tool","taskforce_agent","agent","unclassified"];function L(o){return typeof o.avatarUrl=="string"&&o.avatarUrl.trim().length>0}function ie(o){return o?Ee(o.avatarUrl,o.avatarRevision,o.avatarUpdatedAt):""}function ha(o){return o?Ee(o.avatarSourceUrl,o.avatarRevision,o.avatarUpdatedAt):""}function ya(o){return o.find(L)||o[0]}function Pa({profile:o,className:g=""}){const A=ie(o),$=W(o),{activeImageUrl:T,handleImageError:Y}=sa(A,$);return T?a.jsx("img",{src:T,alt:"",className:g,onError:Y}):a.jsx(Le,{size:22})}function K(o){const g=te(o);return g?`taskforce-agent:${g}`:`${o.seatScope||"unknown"}:${o.name.trim().toLowerCase()}`}function oe(o){const g=o.providerMetadata?.taskforce;return!!(g&&typeof g=="object"&&!Array.isArray(g)&&String(g.taskforceAgentId||"").trim())}function Aa(o){return oe(o)?"taskforce_agent":Me(o.surfaceType)}function Te(o){return o==="taskforce_agent"?"Taskforce Agents":la(o)}function Sa(o){return oe(o)?"Taskforce Agent":o.surfaceType?Re(o.surfaceType):""}function xa(o){const g=Math.max(0,o-1);return`${g} duplicate${g===1?"":"s"}`}function we(o){return!o||typeof o!="object"?null:{used:Math.max(0,Number(o.used||0)),limit:o.limit===null||o.limit===void 0?null:Math.max(0,Number(o.limit||0)),remaining:o.remaining===null||o.remaining===void 0?null:Math.max(0,Number(o.remaining||0))}}function De(o,g){const A=g?.variant==="inline"?`${r.aiProfileSeatScopeIcon} ${r.aiProfileSeatScopeIconInline}`:g?.variant==="detail"?`${r.aiProfileSeatScopeIcon} ${r.aiProfileSeatScopeIconDetail}`:r.aiProfileSeatScopeIcon;return o==="cloud_metered"?a.jsx("span",{className:`${A} ${r.aiProfileSeatScopeIconCloud}`,title:"Cloud MCP","aria-label":"Cloud MCP",children:a.jsx(ma,{size:20})}):o==="local_unmetered"?a.jsx("span",{className:`${A} ${r.aiProfileSeatScopeIconLocal}`,title:"Local MCP","aria-label":"Local MCP",children:a.jsx(va,{size:20})}):null}function Ta({workspaceId:o,runtimeMode:g="local",cloudAuthConfigured:A=!1,authSessionResolved:$=!1,isAuthenticated:T=!1,cloudAiProfileSeatUsage:Y=null,agentTrayOpen:X=!1,onCloseAgentTray:$e,mcpSettingsNode:le=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,Z]=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(o){se(!0);try{const e=`/api/taskforce/workspace/assignee-options?workspaceId=${encodeURIComponent(o)}&kind=agent`,t=await fetch(e,{credentials:"include"}),l=t.ok?await t.json().catch(()=>({})):{},s=we(l?.aiProfileSeatUsage),d=Array.isArray(l?.assignees)?l.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),Z(i=>i&&!d.some(u=>u.id===i.profileId)?null:i)}finally{se(!1)}}},[o]);f.useEffect(()=>{C()},[C]),f.useEffect(()=>{const e=t=>{const l=t.detail;(String(l?.workspaceId||"").trim()||"default")===o&&l?.origin!=="ai-profiles-module"&&C()};return window.addEventListener(Ue,e),()=>window.removeEventListener(Ue,e)},[C,o]);const H=f.useMemo(()=>{const e=new Map;for(const t of N){const l=Aa(t);e.has(l)||e.set(l,new Map);const s=e.get(l),d=K(t);s.has(d)||s.set(d,[]),s.get(d).push(t)}return ga.map(t=>({section:t,label:Te(t),groups:Array.from(e.get(t)?.entries()||[]).map(([l,s])=>({groupId:`${t}:${l}`,section:t,sectionLabel:Te(t),profiles:s,primaryProfile:ya(s)}))})).filter(t=>t.groups.length>0)},[N]),j=f.useMemo(()=>H.flatMap(e=>e.groups),[H]),n=f.useMemo(()=>j.find(e=>e.groupId===U)||j[0]||null,[j,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(!j.length){U!==null&&_(null);return}(!U||!j.some(e=>e.groupId===U))&&_(j[0].groupId)},[j,U]);const Ve=async(e,t)=>{D(null);try{const l=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 l.json().catch(()=>({}));if(!l.ok){w?.(String(s?.error||"Failed to merge AI profiles."),"error");return}F(null),w?.("AI profiles merged.","success"),await C(),b({workspaceId:o,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 l=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 l.json().catch(()=>({}));if(!l.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:o,profileId:e.id,reason:"archive",origin:"ai-profiles-module"})}catch{D({profileId:e.id,message:"Failed to remove AI profile from roster."})}}},Je=async(e,t)=>{const l=re(t),s=new Set(e.profiles.map(u=>u.surfaceType??"")),d=l??"";if(s.size===1&&s.has(d))return;ce(!0),Z(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:l})}),v=await m.json().catch(()=>({}));if(!m.ok||!v?.profile)throw new Error(String(v?.error||"Failed to update AI profile category."));const I=v.profile;i.push({...c,surfaceType:re(I.surfaceType),updatedAt:typeof I.updatedAt=="string"?I.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:l},y=Me(h.surfaceType);_(`${y}:${K(h)}`),w?.("AI profile category updated.","success");for(const c of i)b({workspaceId:o,profileId:c.id,reason:"update",origin:"ai-profiles-module"})}catch(u){Z({profileId:e.primaryProfile.id,message:String(u?.message||"Failed to update AI profile category.")})}finally{ce(!1)}},je=async(e,t,l=!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:l})}),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:o,profileId:c.id,reason:"update",origin:"ai-profiles-module"})}catch(s){Pe(String(s?.message||"Failed to update AI profile color."))}finally{he(!1)}},Ie=e=>new Promise((t,l)=>{const s=new FileReader;s.onload=()=>t(String(s.result||"")),s.onerror=()=>l(new Error("Failed to read image file.")),s.readAsDataURL(e)}),Q=e=>{const t=String(e?.id||"").trim();t&&O(l=>l.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,l,s=!1)=>{const d=await Ie(t),i=l?await Ie(l):null,u={profileId:e,preserveExistingSource:s,displayImage:{dataUrl:d,mimeType:t.type||"application/octet-stream",originalName:t.name||"display-avatar"}};l&&i&&(u.sourceImage={dataUrl:i,mimeType:l.type||"application/octet-stream",originalName:l.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:o,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})}),l=await t.json().catch(()=>({}));if(!t.ok||!l?.profile)throw new Error(String(l?.error||"Failed to update AI profile avatar."));Q(l.profile),b({workspaceId:o,profileId:e,reason:"avatar",origin:"ai-profiles-module"})},Ye=async e=>{if(R)return!1;const t=te(e),l=L(e);if(l&&!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:o}:{workspaceId:o,profileId:e.id,visualDirection:s.slice(0,300),replaceExisting:l})}),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?I=>({...I,[e.id]:{error:null,notice:`Generated photo for ${e.name} was saved in Taskforce Cloud. The local copy will be retained when sync runs.`}}):I=>({...I,[e.id]:{error:null,notice:`Generated photo for ${e.name} was saved.`}})),b({workspaceId:o,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)}},Xe=async(e,t,l)=>{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,l?.preserveExistingSource===!0),!0}catch(s){return P(String(s?.message||"Failed to update AI profile photo.")),!1}finally{z(!1)}},Ze=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 l=Date.parse(t);return Number.isFinite(l)?new Date(l).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):t},be=f.useMemo(()=>{if(!n)return{attributes:[],dates:[]};const e=n.primaryProfile,t=l=>l||"Not set";return{attributes:[{label:"Category",value:Sa(e)},{label:"Connection",value:e.seatScope?ea(e.seatScope):""},{label:"Provider",value:e.provider||""},{label:"Model",value:e.model||""}].map(l=>({...l,value:t(l.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(l=>({...l,value:t(l.value)}))}},[n]),qe=!!n&&n.profiles.length>1,E=!!n&&!L(n.primaryProfile)&&!!W(n.primaryProfile),Ne=A&&$&&!T,V=A?we(Y):Oe,ee=Ne?"Log into account for Cloud AI Profiles":V?`${V.used}/${V.limit===null?"Unlimited":V.limit}`:null,ae=!!le;return a.jsxs("section",{className:`${r.agentsModuleRoot} ${ae?r.agentsModuleWithTray:""} ${ae&&X?r.agentsModuleTrayOpen:""}`.trim(),children:[ae&&a.jsxs("aside",{className:`${r.agentTrayPanel} ${X?r.agentTrayPanelOpen:""}`.trim(),"aria-label":"AI Profile MCP settings tray","aria-hidden":!X,children:[a.jsxs("div",{className:r.agentTrayHeader,children:[a.jsxs("span",{className:r.agentTrayTitle,children:[a.jsx(da,{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(fa,{size:16})})]}),a.jsx("div",{className:`${r.agentTrayContent} tf-scrollbar tf-scrollbar--track-transparent`,children:a.jsx("div",{className:r.agentTrayContentInner,children:le})})]}),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(ua,{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(pa,{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 l=n?.groupId===t.groupId,s=t.primaryProfile,d=!L(s)&&!!W(s);return a.jsx(na,{name:s.name,username:s.username,subtitle:s.role||"Role not set",selected:l,onSelect:()=>_(t.groupId),avatarVariant:d?"logo":"portrait",avatar:a.jsx(Pa,{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(J,{size:11})," ",xa(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:[ca.map(e=>{const t=ra[e];return 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:()=>{je(n,t)}},e)}),a.jsx("button",{type:"button",className:r.secondaryHeaderBtn,disabled:q,onClick:()=>{je(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"&&!oe(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=>{Je(n,t.target.value)},children:[a.jsx("option",{value:"",children:"Unclassified"}),ta.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(J,{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(l=>l.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(J,{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:()=>{Ve(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(J,{size:12}),a.jsx("span",{children:G.message})]})]})]})})})]})}),a.jsx(ia,{isOpen:!!p,theme:Be,title:"Edit AI Profile Photo",currentImageUrl:ie(p),editorImageUrl:ha(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:Xe,onGenerateImage:p&&(!R||R===p.id)&&(oa(p)||te(p))?()=>Ye(p):void 0,onRemoveImage:Ze},p?.id||"ai-profile-avatar-closed")]})}export{Ta as AiProfilesModule};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._shell_1tt0t_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,270px) minmax(0,1fr) minmax(220px,270px);gap:12px;height:100%;min-height:0;padding:12px;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_1tt0t_18{transition:padding-left .22s cubic-bezier(.4,0,.2,1)}._shellImageTrayOpen_1tt0t_22{padding-left:calc(var(--image-tray-width) + 12px)}._imageTrayPanel_1tt0t_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_1tt0t_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_1tt0t_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_1tt0t_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_1tt0t_85{position:relative;padding:12px 0 0;flex-shrink:0}._imageTraySearchIcon_1tt0t_91{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--text-muted);pointer-events:none}._imageTraySearchInput_1tt0t_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_1tt0t_100:focus{border-color:var(--brand-primary)}._imageTraySortControlRow_1tt0t_117{display:flex;justify-content:flex-end;padding:6px 0 4px;flex-shrink:0}._imageTrayList_1tt0t_124{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_1tt0t_136,._imageTrayStateError_1tt0t_137{padding:24px 16px;font-size:.75rem;color:var(--text-muted);text-align:center;line-height:1.5}._imageTrayStateError_1tt0t_137{color:var(--status-error)}._imageTrayItem_1tt0t_149{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_1tt0t_149:hover{background:color-mix(in srgb,var(--surface-hover) 72%,transparent);transform:translateY(-1px)}._imageTrayItemActive_1tt0t_171{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_1tt0t_171:hover{background:color-mix(in srgb,var(--brand-primary-soft) 92%,transparent)}._imageTrayThumb_1tt0t_181{width:34px;height:34px;flex-shrink:0;border-radius:6px;overflow:hidden;background:var(--surface-inset);border:1px solid var(--border-subtle)}._imageTrayThumb_1tt0t_181 img{width:100%;height:100%;object-fit:cover;display:block}._imageTrayItemBody_1tt0t_198{display:flex;flex-direction:column;gap:.25rem;min-width:0;flex:1}._imageTrayItemTitle_1tt0t_206,._imageTrayItemTask_1tt0t_207,._imageTrayItemMetaDetails_1tt0t_208{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._imageTrayItemTitle_1tt0t_206{display:block;max-width:100%;font-size:.875rem;font-weight:700;line-height:1.28;color:var(--text-primary)}._imageTrayItemTask_1tt0t_207{display:block;max-width:100%;font-size:.75rem;line-height:1.35;color:color-mix(in srgb,var(--text-secondary) 92%,transparent)}._imageTrayItemMeta_1tt0t_208{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_1tt0t_208{min-width:0}._imageTrayItemReference_1tt0t_246{flex-shrink:0;font-size:.7rem;font-weight:700;color:var(--text-secondary)}._panel_1tt0t_253{min-height:0;border-radius:var(--radius-sm);box-shadow:0 18px 38px #0f172a14}._sessionPanel_1tt0t_259,._detailPanel_1tt0t_260{display:flex;flex-direction:column;overflow:hidden}._sessionContextBar_1tt0t_266{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_1tt0t_277,._sessionContextRight_1tt0t_278{display:flex;align-items:center;min-width:0}._sessionContextLeft_1tt0t_277{flex:1}._sessionContextRight_1tt0t_278{justify-content:flex-end;min-width:118px}._sessionContextLabel_1tt0t_293{font-size:.84rem;font-weight:600;color:var(--text-secondary)}._sessionContextSpacer_1tt0t_299{width:118px;height:32px}._canvasPanel_1tt0t_304{display:flex;flex-direction:column;min-height:0;overflow:hidden}._canvasWorkspace_1tt0t_311{display:grid;grid-template-columns:auto minmax(0,1fr);min-height:0;flex:1}._canvasMain_1tt0t_318{display:flex;flex-direction:column;min-width:0;min-height:0}._panelHeader_1tt0t_325{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px;border-bottom:1px solid var(--border-default)}._panelHeaderText_1tt0t_334{min-width:0}._panelTitle_1tt0t_338{font-size:1rem}._canvasHeading_1tt0t_342{min-width:0}._sessionActions_1tt0t_346{display:inline-flex;align-items:center;gap:8px;margin-left:auto;flex-shrink:0}._taskLinkModalBody_1tt0t_354{display:flex;flex-direction:column;gap:12px}._taskLinkModalBody_1tt0t_354>p{margin:0}._taskLinkList_1tt0t_364{display:flex;flex-direction:column;gap:6px;max-height:280px;overflow:auto}._taskLinkOption_1tt0t_372{display:flex;flex-direction:column;align-items:flex-start;gap:3px;width:100%;padding:10px 12px;border:1px solid var(--border-default);border-radius:var(--radius-sm);color:inherit;text-align:left;cursor:pointer}._taskLinkOption_1tt0t_372:hover:not(:disabled),._taskLinkOptionActive_1tt0t_387{border-color:var(--accent-primary)}._taskLinkOption_1tt0t_372:disabled{cursor:default}._taskLinkOptionTitle_1tt0t_395{font-weight:600}._taskLinkActions_1tt0t_399{display:flex;justify-content:flex-end;gap:8px}._sessionList_1tt0t_405,._annotationList_1tt0t_406{display:flex;flex:1 1 auto;flex-direction:column;gap:6px;min-height:0;padding:8px;overflow:auto}._markerHelpModalBody_1tt0t_416{display:flex;flex-direction:column;gap:14px}._openImageModalBody_1tt0t_422{display:flex;flex-direction:column;gap:12px}._openImageField_1tt0t_428{width:100%}._openImageActions_1tt0t_432{display:flex;justify-content:flex-end;gap:8px}._markerHelpItem_1tt0t_438{display:flex;flex-direction:column;gap:6px;padding:12px 14px;border-radius:var(--radius-md)}._markerHelpHeader_1tt0t_446{display:flex;align-items:baseline;justify-content:space-between;gap:12px}._markerHelpItem_1tt0t_438 p{margin:0;line-height:1.45}._markerHelpExample_1tt0t_458{font-weight:600}._sessionCard_1tt0t_462,._annotationCard_1tt0t_463{display:flex;flex-direction:column;gap:6px;padding:10px;border-radius:var(--radius-sm);text-align:left;transition:border-color var(--transition-base),box-shadow var(--transition-base),opacity var(--transition-base),transform var(--transition-base)}._sessionEmptyState_1tt0t_477{display:flex;flex-direction:column;gap:8px;padding:8px 2px 0}._sessionCardButton_1tt0t_484{display:flex;flex-direction:column;gap:8px;padding:0;border:0;background:transparent;text-align:left}._annotationCardButton_1tt0t_494{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:8px;padding:0;border:0;background:transparent;text-align:left}._sessionCardBody_1tt0t_506{display:flex;flex-direction:column;gap:8px}._sessionCardActive_1tt0t_512,._annotationCardActive_1tt0t_513{border-color:var(--button-tile-active-border);box-shadow:0 0 0 1px transparent,0 12px 28px var(--brand-primary-glow-soft)}._annotationCardActive_1tt0t_513{border-color:var(--annotation-card-accent, var(--button-tile-active-border));box-shadow:0 0 0 1px color-mix(in srgb,var(--annotation-card-accent, var(--brand-primary)) 30%,transparent),0 12px 28px color-mix(in srgb,var(--annotation-card-accent, var(--brand-primary)) 18%,transparent)}._sessionCard_1tt0t_462:hover,._annotationCard_1tt0t_463:hover{transform:translateY(-1px)}._annotationMeta_1tt0t_528{display:flex;align-items:center;justify-content:space-between;gap:4px}._annotationDragHandle_1tt0t_535{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:18px;height:20px;margin-left:-2px;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text-helper);cursor:grab}._annotationDragHandle_1tt0t_535:hover,._annotationDragHandle_1tt0t_535:focus-visible{background:var(--surface-hover);color:var(--text-primary)}._annotationDragHandle_1tt0t_535:active{cursor:grabbing}._annotationCardDragging_1tt0t_561{opacity:.16}._annotationDragOverlay_1tt0t_565{width:min(100%,320px);opacity:.94;box-shadow:0 16px 32px color-mix(in srgb,var(--surface-page) 55%,transparent);pointer-events:none}._annotationDragOverlayGrip_1tt0t_572{color:var(--text-helper)}._annotationDragOverlayTitle_1tt0t_576{flex:1 1 auto;min-width:0;text-align:left}._annotationInstructionPreview_1tt0t_582{display:-webkit-box;overflow:hidden;-webkit-line-clamp:4;-webkit-box-orient:vertical;line-height:1.45}._annotationPreviewFooter_1tt0t_590{display:flex;align-items:center;justify-content:flex-start;min-height:16px}._annotationInstructionEditor_1tt0t_597,._annotationTypeField_1tt0t_603{display:flex;flex-direction:column;gap:8px}._annotationGeometryDetails_1tt0t_609{padding-top:8px;border-top:1px solid var(--border-default)}._annotationGeometryDetails_1tt0t_609>summary{cursor:pointer}._annotationGeometryFields_1tt0t_618{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:8px}._annotationGeometryField_1tt0t_618{display:flex;flex-direction:column;gap:4px}._annotationGeometryLabel_1tt0t_631{margin:0;text-transform:uppercase}._annotationGeometryInput_1tt0t_636{min-width:0;text-align:right}._annotationInstructionButton_1tt0t_641{display:block;width:100%;padding:0;border:0;background:transparent;text-align:left}._annotationInstructionField_1tt0t_650{min-height:92px}._sessionMeta_1tt0t_654{display:flex;flex-direction:column;align-items:flex-start;gap:4px}._sessionTitle_1tt0t_661,._annotationTitle_1tt0t_662{font-size:.98rem;font-weight:700;color:var(--text-primary)}._sessionTimestamp_1tt0t_668,._annotationKind_1tt0t_669{text-transform:capitalize}._annotationInstructionTypeIcon_1tt0t_673{display:inline-flex;align-items:center;justify-content:center}._sessionInstructionPreview_1tt0t_679{line-height:1.45;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}._sessionInstructionEditor_1tt0t_687{display:flex;flex-direction:column;gap:8px}._sessionCardFooter_1tt0t_693{display:flex;align-items:center;justify-content:flex-end;gap:8px}._toolRail_1tt0t_700{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_1tt0t_709{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_1tt0t_719{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_1tt0t_730{display:inline-flex;flex-wrap:wrap;gap:8px;align-items:center}._toolbarViewportCluster_1tt0t_737{margin-left:44px}._toolbarSeparator_1tt0t_741{width:1px;align-self:stretch;background:var(--border-default)}._toolBtn_1tt0t_747{white-space:nowrap}._toolRailButton_1tt0t_751{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border-radius:var(--radius-md)}._toolbarButton_1tt0t_761{min-height:44px;border-radius:var(--radius-md)}._toolBtnActive_1tt0t_766{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_1tt0t_773{display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px;flex:1 1 auto;min-width:0}._toolbarSelectionActions_1tt0t_782{display:inline-flex;align-items:center;gap:8px;min-width:44px;flex-wrap:wrap}._toolbarColorPicker_1tt0t_790{position:relative}._colorPickerButton_1tt0t_794{min-width:44px;padding:0}._colorPickerSwatch_1tt0t_799{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_1tt0t_807{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_1tt0t_822{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_1tt0t_832{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_1tt0t_839{margin-left:auto;display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px}._iconButton_1tt0t_847{flex-shrink:0}._primaryBtn_1tt0t_851,._ghostBtn_1tt0t_852,._payloadBtn_1tt0t_853,._backToTaskBtn_1tt0t_854{white-space:nowrap}._backToTaskBtn_1tt0t_854{padding:7px 10px;color:var(--text-secondary);font-size:.88rem;font-weight:600}._backToTaskBtn_1tt0t_854:hover,._backToTaskBtn_1tt0t_854:focus-visible{color:var(--text-primary)}._payloadBtn_1tt0t_853{font-weight:700}._canvasScroller_1tt0t_874{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_1tt0t_890{position:relative;display:grid;place-items:center;width:max-content;min-width:100%;min-height:100%}._canvasMedia_1tt0t_899{position:relative;display:block;flex-shrink:0;margin:0 auto;overflow:hidden}._canvasStatusOverlay_1tt0t_907{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_1tt0t_919{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_1tt0t_932{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}._overlay_1tt0t_939{position:absolute;inset:0;cursor:crosshair}._overlaySelect_1tt0t_945{cursor:default}._overlayPan_1tt0t_949{cursor:grab}._overlaySvg_1tt0t_953{position:absolute;inset:0;display:block;width:100%;height:100%;pointer-events:none}._overlayHitLayer_1tt0t_962{position:absolute;inset:0;display:block;width:100%;height:100%;pointer-events:auto}._arrowHitArea_1tt0t_971{stroke:transparent;stroke-width:24;pointer-events:stroke;cursor:move}._canvasHandleHit_1tt0t_978{fill:transparent;pointer-events:all;cursor:grab;outline:none}._canvasResizeHandleHit_1tt0t_985{cursor:nwse-resize}._canvasHandleVisible_1tt0t_989{--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_1tt0t_978:focus-visible+._canvasHandleVisible_1tt0t_989{stroke:color-mix(in srgb,var(--brand-primary) 72%,var(--surface-elevated));stroke-width:4}._pin_1tt0t_1006,._note_1tt0t_1007{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_1tt0t_1024{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_1tt0t_1007{min-width:38px;padding:0 10px;border-radius:999px}._box_1tt0t_1049{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_1tt0t_1058{top:0;left:0;transform:translate(-28%,-36%)}._arrowNumberBadge_1tt0t_1064{transform:translate(-50%,-50%)}._boxSurface_1tt0t_1068{position:absolute;inset:0;border:0;background:transparent;cursor:move}._boxSurface_1tt0t_1068:focus-visible{outline:2px solid color-mix(in srgb,var(--brand-primary) 34%,var(--surface-elevated));outline-offset:2px}._selected_1tt0t_1081{outline:3px solid color-mix(in srgb,var(--surface-elevated) 92%,transparent);outline-offset:1px}._fieldGroup_1tt0t_1086{display:flex;flex-direction:column;gap:8px;padding:14px 16px}._detailPanel_1tt0t_260 ._fieldGroup_1tt0t_1086{padding-top:12px;padding-bottom:12px}._textInput_1tt0t_1098,._textArea_1tt0t_1099,._select_1tt0t_1081{width:100%;box-sizing:border-box;font:inherit;font-size:.8125rem;line-height:1.5}._sessionTitleInput_1tt0t_1108{font-size:1rem;font-weight:600}._sessionInstructionField_1tt0t_1113{min-height:112px}._textArea_1tt0t_1099{min-height:110px;resize:vertical}._detailEmpty_1tt0t_1122,._emptyState_1tt0t_1123,._errorState_1tt0t_1124{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;min-height:240px;padding:24px;text-align:center}._payloadModalBody_1tt0t_1135{display:flex;flex-direction:column;gap:12px;min-height:0}._payloadModalToolbar_1tt0t_1142{display:flex;align-items:center;justify-content:space-between;gap:12px}._payloadViewToggle_1tt0t_1149,._payloadModalActions_1tt0t_1150{display:inline-flex;flex-wrap:wrap;align-items:center;gap:8px}._payloadModalPreview_1tt0t_1157{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_1tt0t_1172{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_1tt0t_1184{font-size:.82rem;line-height:1.5}@media(max-width:1180px){._shell_1tt0t_1{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(320px,1fr) auto;gap:12px;padding:12px}._sessionContextBar_1tt0t_266,._panelHeader_1tt0t_325,._toolRail_1tt0t_700,._statusBar_1tt0t_1172,._payloadModalToolbar_1tt0t_1142,._markerHelpHeader_1tt0t_446{flex-wrap:wrap}._sessionContextRight_1tt0t_278,._sessionContextLeft_1tt0t_277,._canvasHeading_1tt0t_342{min-width:0}._sessionContextRight_1tt0t_278{width:100%;justify-content:flex-start}._toolbarActions_1tt0t_773{width:100%;margin-left:0}._toolbarUtilities_1tt0t_839{margin-left:0}._toolGroup_1tt0t_719{max-width:100%}._canvasWorkspace_1tt0t_311{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}._toolbarViewportCluster_1tt0t_737{margin-left:0}._canvasToolRail_1tt0t_709{flex-direction:row;justify-content:flex-start;overflow-x:auto;padding:0;border-right:0;border-bottom:1px solid var(--border-default)}._statusBar_1tt0t_1172{align-items:flex-start}._detailEmpty_1tt0t_1122,._emptyState_1tt0t_1123,._errorState_1tt0t_1124{min-height:180px}}
|