@taskforcehq/taskforce 0.3.303 → 0.3.305
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 +140 -247
- package/dist/Taskforce.module.css +102 -5
- package/dist/TaskforceCore.js +635 -238
- package/dist/TaskforceCore.test.js +2243 -495
- package/dist/annotatedAttachments/service.d.ts +1 -1
- package/dist/annotatedAttachments/types.d.ts +1 -1
- package/dist/compat/workspaceSyncCompat.js +6 -0
- package/dist/components/features/AgentsModule.js +1 -1
- package/dist/components/features/AgentsModule.test.js +1 -1
- package/dist/components/features/DocumentIndex.d.ts +1 -1
- package/dist/components/features/DocumentIndex.js +1 -1
- package/dist/components/features/DocumentViewer.d.ts +1 -1
- package/dist/components/features/DocumentViewer.js +32 -9
- package/dist/components/features/DocumentWorkspace.d.ts +5 -22
- package/dist/components/features/DocumentWorkspace.js +12 -155
- package/dist/components/features/DocumentWorkspace.test.js +193 -6
- package/dist/components/features/TaskSettings.js +87 -41
- package/dist/components/features/TaskSettings.test.js +180 -40
- package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
- package/dist/components/features/documentWorkspaceModel.js +57 -0
- package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
- package/dist/components/features/useDocumentWorkspaceController.js +113 -0
- package/dist/components/task/TaskActionHeader.d.ts +2 -1
- package/dist/components/task/TaskActionHeader.js +3 -3
- package/dist/components/task/TaskActionHeader.test.js +8 -0
- package/dist/components/task/TaskCard.js +16 -1
- package/dist/components/task/TaskCard.test.js +31 -0
- package/dist/components/task/TaskForm.d.ts +9 -8
- package/dist/components/task/TaskForm.js +374 -219
- package/dist/components/task/TaskForm.test.js +482 -361
- package/dist/components/task/TaskKanban.d.ts +1 -1
- package/dist/components/task/TaskKanban.js +33 -161
- package/dist/components/task/TaskStatusActions.d.ts +6 -1
- package/dist/components/task/TaskStatusActions.js +8 -3
- package/dist/components/task/TaskStatusActions.test.js +9 -0
- package/dist/components/task/taskKanbanDropRules.d.ts +58 -0
- package/dist/components/task/taskKanbanDropRules.js +187 -0
- package/dist/components/task/taskKanbanDropRules.test.d.ts +1 -0
- package/dist/components/task/taskKanbanDropRules.test.js +114 -0
- package/dist/components/ui/Modal.d.ts +1 -1
- package/dist/components/ui/Modal.js +1 -0
- package/dist/components/views/AppShellHeader.js +5 -1
- package/dist/components/views/AppShellHeader.test.js +4 -0
- package/dist/components/views/PlanComparisonPage.d.ts +3 -2
- package/dist/components/views/PlanComparisonPage.js +9 -10
- package/dist/components/views/PlanComparisonPage.test.js +55 -41
- package/dist/components/views/PlansPage.d.ts +5 -1
- package/dist/components/views/PlansPage.js +150 -81
- package/dist/components/views/PlansPage.test.js +367 -41
- package/dist/components/views/StandaloneLayout.js +135 -54
- package/dist/components/views/WidgetView.js +11 -2
- package/dist/components/views/panels/FilterToolbar.test.js +6 -4
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +2 -14
- package/dist/components/views/standalone/modals/AccountHubModal.js +12 -14
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +24 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +1 -1
- package/dist/config/envSchema.js +1 -1
- package/dist/core/AiProfileService.d.ts +6 -1
- package/dist/core/AiProfileService.js +161 -16
- package/dist/core/AiProfileService.test.js +3 -1
- package/dist/core/AiProfiles.test.js +200 -0
- package/dist/core/AuthTokenService.test.d.ts +1 -0
- package/dist/core/AuthTokenService.test.js +78 -0
- package/dist/core/DeletedTaskLifecycleService.d.ts +2 -1
- package/dist/core/EntitlementsPolicy.test.js +75 -13
- package/dist/core/PlanEntitlementService.d.ts +9 -1
- package/dist/core/PlanEntitlementService.js +144 -19
- package/dist/core/PlanVersionPolicy.test.js +19 -26
- package/dist/core/SignupMonetizationSettings.test.js +75 -15
- package/dist/core/SystemAdmin.test.js +212 -56
- package/dist/core/TaskActivityService.d.ts +4 -1
- package/dist/core/TaskActivityService.js +45 -0
- package/dist/core/TaskAuditTimeline.test.js +52 -1
- package/dist/core/TaskTaxonomyValidation.test.js +53 -0
- package/dist/core/Taskforce.d.ts +18 -11
- package/dist/core/Taskforce.js +93 -12
- package/dist/core/WorkspacePlanMode.test.js +73 -8
- package/dist/core/shared.d.ts +2 -0
- package/dist/core/shared.js +11 -0
- package/dist/documentReviews/service.d.ts +1 -1
- package/dist/documentReviews/types.d.ts +1 -1
- package/dist/hooks/auth/useTaskforceAuthBootstrap.d.ts +48 -0
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +219 -0
- package/dist/hooks/sync/auth.d.ts +37 -0
- package/dist/hooks/sync/auth.js +63 -0
- package/dist/hooks/sync/bootstrap.d.ts +34 -0
- package/dist/hooks/sync/bootstrap.js +52 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +36 -0
- package/dist/hooks/sync/orchestratorShared.js +209 -0
- package/dist/hooks/sync/orchestratorShared.test.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.test.js +49 -0
- package/dist/hooks/sync/realtime.d.ts +25 -0
- package/dist/hooks/sync/realtime.js +60 -0
- package/dist/hooks/sync/recovery.d.ts +69 -0
- package/dist/hooks/sync/recovery.js +118 -0
- package/dist/hooks/sync/transfers.d.ts +123 -0
- package/dist/hooks/sync/transfers.js +435 -0
- package/dist/hooks/sync/useDataVersionRefresh.d.ts +16 -0
- package/dist/hooks/sync/useDataVersionRefresh.js +73 -0
- package/dist/hooks/ui/useResourceExport.d.ts +3 -1
- package/dist/hooks/ui/useResourceExport.js +5 -2
- package/dist/hooks/ui/useWorkflowTemplates.js +11 -6
- package/dist/hooks/useRealtimeSync.js +2 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +8 -0
- package/dist/hooks/useSyncOrchestrator.context-assets.test.d.ts +1 -0
- package/dist/hooks/useSyncOrchestrator.context-assets.test.js +228 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +12 -8
- package/dist/hooks/useSyncOrchestrator.js +388 -879
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +641 -6
- package/dist/hooks/useTaskMutations.d.ts +2 -1
- package/dist/hooks/useTaskMutations.js +57 -7
- package/dist/hooks/useTaskMutations.test.js +176 -0
- package/dist/hooks/useTaskforce.d.ts +13 -4
- package/dist/hooks/useTaskforce.js +302 -817
- package/dist/hooks/useTaskforce.sync-behavior.test.js +78 -0
- package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
- package/dist/hooks/useWorkspaceSyncController.js +33 -11
- package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
- package/dist/hooks/workspace/useTaskforceApiRouting.test.js +17 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +166 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +434 -0
- package/dist/hooks/workspace/workspaceLocalState.d.ts +19 -0
- package/dist/hooks/workspace/workspaceLocalState.js +100 -0
- package/dist/hooks/workspace/workspaceLocalState.test.d.ts +1 -0
- package/dist/hooks/workspace/workspaceLocalState.test.js +59 -0
- package/dist/localization/locales/en-US.js +2 -2
- package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
- package/dist/mcp/canonicalAssetHelpers.d.ts +70 -0
- package/dist/mcp/canonicalAssetHelpers.js +259 -0
- package/dist/mcp/clientIntegrations.d.ts +12 -1
- package/dist/mcp/clientIntegrations.js +161 -6
- package/dist/mcp/clientIntegrations.test.js +76 -4
- package/dist/mcp/collaborationRegistrar.d.ts +2 -0
- package/dist/mcp/collaborationRegistrar.js +71 -0
- package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
- package/dist/mcp/documentAssetRegistrar.js +346 -0
- package/dist/mcp/documentHelpers.d.ts +100 -0
- package/dist/mcp/documentHelpers.js +161 -0
- package/dist/mcp/runtime.js +2455 -3925
- package/dist/mcp/runtime.test.js +240 -8
- package/dist/mcp/taskAttachmentHelpers.d.ts +41 -0
- package/dist/mcp/taskAttachmentHelpers.js +60 -0
- package/dist/mcp/taskAttachmentTypes.d.ts +37 -0
- package/dist/mcp/taskAttachmentTypes.js +1 -0
- package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
- package/dist/mcp/taskPlanningRegistrar.js +418 -0
- package/dist/mcp/toolCatalog.d.ts +35 -0
- package/dist/mcp/toolCatalog.js +3 -0
- package/dist/plugins/vite.js +1 -1
- package/dist/runtime/appGateDefinitions.d.ts +1 -1
- package/dist/runtime/appGateDefinitions.js +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +46 -3
- package/dist/server/index.test.js +12 -1
- package/dist/server/routes/admin.d.ts +1 -5
- package/dist/server/routes/admin.js +151 -80
- package/dist/server/routes/annotatedAttachments.d.ts +1 -1
- package/dist/server/routes/annotatedAttachments.js +1 -1
- package/dist/server/routes/auth.d.ts +1 -4
- package/dist/server/routes/auth.js +59 -64
- package/dist/server/routes/authSupport.d.ts +30 -0
- package/dist/server/routes/authSupport.js +81 -0
- package/dist/server/routes/billing.d.ts +1 -1
- package/dist/server/routes/billing.js +122 -255
- package/dist/server/routes/billing.test.js +257 -86
- package/dist/server/routes/documentReviews.d.ts +1 -1
- package/dist/server/routes/documentReviews.js +1 -1
- package/dist/server/routes/documents.d.ts +4 -2
- package/dist/server/routes/documents.js +73 -7
- package/dist/server/routes/primitives.d.ts +11 -0
- package/dist/server/routes/primitives.js +73 -0
- package/dist/server/routes/resources.d.ts +1 -1
- package/dist/server/routes/resources.js +1 -1
- package/dist/server/routes/shared.d.ts +31 -1
- package/dist/server/routes/shared.js +26 -0
- package/dist/server/routes/sync.d.ts +1 -1
- package/dist/server/routes/sync.integration.test.js +20 -0
- package/dist/server/routes/sync.js +111 -238
- package/dist/server/routes/tasks.d.ts +1 -1
- package/dist/server/routes/tasks.js +50 -8
- package/dist/server/routes/workspaces.d.ts +1 -1
- package/dist/server/routes/workspaces.js +1 -1
- package/dist/server/routes.d.ts +2 -9
- package/dist/server/routes.js +84 -181
- package/dist/server/routes.test.js +912 -32
- package/dist/shared/taskActor.d.ts +10 -0
- package/dist/shared/taskActor.js +1 -0
- package/dist/sync/collaborationSyncPayload.js +4 -0
- package/dist/sync/collaborationSyncPayload.test.js +8 -0
- package/dist/sync/collaborationSyncState.d.ts +3 -1
- package/dist/sync/collaborationSyncState.js +19 -0
- package/dist/sync/contentSyncState.js +28 -17
- package/dist/sync/syncApplyHandlers.d.ts +87 -1
- package/dist/sync/syncApplyHandlers.js +370 -8
- package/dist/sync/syncApplyHandlers.test.d.ts +1 -0
- package/dist/sync/syncApplyHandlers.test.js +379 -0
- package/dist/sync/syncService.d.ts +9 -1
- package/dist/sync/syncService.js +44 -2
- package/dist/sync/syncService.test.js +62 -0
- package/dist/sync/workspacePullFeed.d.ts +1 -0
- package/dist/sync/workspacePullFeed.js +66 -59
- package/dist/sync/workspacePullFeed.test.js +72 -4
- package/dist/sync/workspaceSyncModel.d.ts +25 -1
- package/dist/sync/workspaceSyncModel.js +77 -3
- package/dist/sync/workspaceSyncModel.test.js +153 -0
- package/dist/sync/workspaceSyncState.d.ts +2 -0
- package/dist/sync/workspaceSyncState.js +1 -0
- package/dist/types.d.ts +2 -10
- package/dist/ui/assets/AgentsModule-N2MnQBZk.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-C_TmXZwA.js → AnnotatedAttachmentWorkspace-BG6P_GVW.js} +1 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +252 -0
- package/dist/ui/assets/{InitiativesModule-4-Rh2K2n.js → InitiativesModule-Dhm7M8e7.js} +1 -1
- package/dist/ui/assets/{PlansPage-BlVC_lRq.css → PlansPage-C2dd2n1X.css} +1 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +1 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-CGk9s3NJ.js → WorkflowsModule-BcS4afRn.js} +1 -1
- package/dist/ui/assets/index-C2-OXZV7.css +1 -0
- package/dist/ui/assets/index-DcSI5F86.js +6 -0
- package/dist/ui/assets/{vendor-icons-pWocEipT.js → vendor-icons-BSUaRwF8.js} +1 -1
- package/dist/ui/index.html +4 -4
- package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
- package/dist/utils/commercialLifecyclePresentation.js +196 -0
- package/dist/utils/taskActivity.js +4 -0
- package/dist/utils/taskActivity.test.js +25 -1
- package/package.json +10 -1
- package/scripts/check-cloud-mcp.mjs +83 -0
- package/scripts/playwright-auth.sh +9 -1
- package/scripts/run-billing-performance-smoke.sh +24 -0
- package/dist/ui/assets/AgentsModule-CpsTmrIW.js +0 -1
- package/dist/ui/assets/DocumentWorkspace-C3GyzrWm.js +0 -250
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
- package/dist/ui/assets/PlansPage-BP7AYOqr.js +0 -1
- package/dist/ui/assets/TaskSettings-BOC5F6Ag.js +0 -8
- package/dist/ui/assets/index-CLIMgR6g.js +0 -6
- package/dist/ui/assets/index-DneETxcu.css +0 -1
package/dist/ui/index.html
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
|
|
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
|
-
<title>Taskforce
|
|
11
|
-
<script type="module" crossorigin src="/taskforce/assets/index-
|
|
10
|
+
<title>Taskforce</title>
|
|
11
|
+
<script type="module" crossorigin src="/taskforce/assets/index-DcSI5F86.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-BSUaRwF8.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-markdown-BUxTU7dS.js">
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-dnd-DRzYolkg.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-router-BbWMxlnO.js">
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-C2-OXZV7.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="root"></div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AccountProfileSummary } from './accountProfileSummaryCache';
|
|
2
|
+
export type CommercialLifecyclePrimaryAction = 'choose_plan' | 'open_plans' | 'manage_billing' | 'none';
|
|
3
|
+
export type CommercialLifecycleTone = 'success' | 'info' | 'error';
|
|
4
|
+
export interface CommercialLifecyclePresentation {
|
|
5
|
+
entitlementState: string | null;
|
|
6
|
+
gate: string | null;
|
|
7
|
+
isActive: boolean;
|
|
8
|
+
allowReturnToApp: boolean;
|
|
9
|
+
statusTone: CommercialLifecycleTone;
|
|
10
|
+
message: string | null;
|
|
11
|
+
primaryAction: CommercialLifecyclePrimaryAction;
|
|
12
|
+
primaryLabel: string | null;
|
|
13
|
+
showManageBilling: boolean;
|
|
14
|
+
markCurrentPlan: boolean;
|
|
15
|
+
}
|
|
16
|
+
type AccountProfileSummaryLike = Pick<AccountProfileSummary, 'billingConflictCode' | 'effectiveUntil' | 'entitlementState' | 'gate' | 'message' | 'planSelectionRequired' | 'stripeCustomerId' | 'stripeSubscriptionId' | 'trialEnd'> | null | undefined;
|
|
17
|
+
export declare function isCommercialEntitlementActive(raw: string | null | undefined): boolean;
|
|
18
|
+
export declare function resolveCommercialLifecyclePresentation(summary: AccountProfileSummaryLike, fallbackGate?: string | null): CommercialLifecyclePresentation;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const ACTIVE_ENTITLEMENT_STATES = new Set(['active', 'trialing', 'grace']);
|
|
2
|
+
const BILLING_CONFLICT_MESSAGES = {
|
|
3
|
+
CHECKOUT_SESSION_EXPIRED: 'Your previous checkout expired. Choose a plan to continue.',
|
|
4
|
+
CHECKOUT_SESSION_SUPERSEDED: 'A newer checkout replaced your previous checkout. Choose a plan to continue.'
|
|
5
|
+
};
|
|
6
|
+
const GATE_MESSAGES = {
|
|
7
|
+
planSelectionRequired: 'Choose a plan to continue.',
|
|
8
|
+
checkoutPending: 'Complete checkout to continue.',
|
|
9
|
+
misconfigured: 'Onboarding policy is misconfigured. Contact support or a system administrator.',
|
|
10
|
+
missingEntitlement: 'No entitlement is linked to this account.'
|
|
11
|
+
};
|
|
12
|
+
function normalizeString(value) {
|
|
13
|
+
return String(value || '').trim();
|
|
14
|
+
}
|
|
15
|
+
function normalizeEntitlementState(value) {
|
|
16
|
+
return normalizeString(value).toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function normalizeGate(value) {
|
|
19
|
+
return normalizeString(value).toLowerCase();
|
|
20
|
+
}
|
|
21
|
+
function hasBillingContext(summary) {
|
|
22
|
+
return Boolean(normalizeString(summary?.stripeCustomerId) || normalizeString(summary?.stripeSubscriptionId));
|
|
23
|
+
}
|
|
24
|
+
function resolveTrialMessage(summary) {
|
|
25
|
+
const trialEnd = normalizeString(summary?.trialEnd || summary?.effectiveUntil);
|
|
26
|
+
if (trialEnd) {
|
|
27
|
+
const formatted = new Date(trialEnd);
|
|
28
|
+
if (!Number.isNaN(formatted.getTime())) {
|
|
29
|
+
return `Your trial is active through ${formatted.toLocaleString()}.`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return 'Your trial is active. Continue to Taskforce or manage billing anytime.';
|
|
33
|
+
}
|
|
34
|
+
export function isCommercialEntitlementActive(raw) {
|
|
35
|
+
return ACTIVE_ENTITLEMENT_STATES.has(normalizeEntitlementState(raw));
|
|
36
|
+
}
|
|
37
|
+
export function resolveCommercialLifecyclePresentation(summary, fallbackGate) {
|
|
38
|
+
const entitlementState = normalizeEntitlementState(summary?.entitlementState);
|
|
39
|
+
const gate = normalizeGate(summary?.gate || fallbackGate);
|
|
40
|
+
const billingConflictCode = normalizeString(summary?.billingConflictCode).toUpperCase();
|
|
41
|
+
const summaryMessage = normalizeString(summary?.message);
|
|
42
|
+
const isActive = isCommercialEntitlementActive(entitlementState);
|
|
43
|
+
const billingAvailable = hasBillingContext(summary);
|
|
44
|
+
if (billingConflictCode === 'CHECKOUT_SESSION_EXPIRED') {
|
|
45
|
+
return {
|
|
46
|
+
entitlementState: entitlementState || null,
|
|
47
|
+
gate: gate || null,
|
|
48
|
+
isActive: false,
|
|
49
|
+
allowReturnToApp: false,
|
|
50
|
+
statusTone: 'info',
|
|
51
|
+
message: BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_EXPIRED,
|
|
52
|
+
primaryAction: 'choose_plan',
|
|
53
|
+
primaryLabel: 'Choose Plan',
|
|
54
|
+
showManageBilling: billingAvailable,
|
|
55
|
+
markCurrentPlan: false,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (billingConflictCode === 'CHECKOUT_SESSION_SUPERSEDED') {
|
|
59
|
+
return {
|
|
60
|
+
entitlementState: entitlementState || null,
|
|
61
|
+
gate: gate || null,
|
|
62
|
+
isActive: false,
|
|
63
|
+
allowReturnToApp: false,
|
|
64
|
+
statusTone: 'info',
|
|
65
|
+
message: BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_SUPERSEDED,
|
|
66
|
+
primaryAction: 'choose_plan',
|
|
67
|
+
primaryLabel: 'Choose Plan',
|
|
68
|
+
showManageBilling: billingAvailable,
|
|
69
|
+
markCurrentPlan: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (entitlementState === 'trialing') {
|
|
73
|
+
return {
|
|
74
|
+
entitlementState,
|
|
75
|
+
gate: gate || null,
|
|
76
|
+
isActive: true,
|
|
77
|
+
allowReturnToApp: true,
|
|
78
|
+
statusTone: 'success',
|
|
79
|
+
message: resolveTrialMessage(summary),
|
|
80
|
+
primaryAction: billingAvailable ? 'manage_billing' : 'none',
|
|
81
|
+
primaryLabel: billingAvailable ? 'Manage Billing' : null,
|
|
82
|
+
showManageBilling: billingAvailable,
|
|
83
|
+
markCurrentPlan: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (isActive) {
|
|
87
|
+
return {
|
|
88
|
+
entitlementState: entitlementState || null,
|
|
89
|
+
gate: gate || null,
|
|
90
|
+
isActive: true,
|
|
91
|
+
allowReturnToApp: true,
|
|
92
|
+
statusTone: 'success',
|
|
93
|
+
message: summaryMessage || null,
|
|
94
|
+
primaryAction: 'none',
|
|
95
|
+
primaryLabel: null,
|
|
96
|
+
showManageBilling: billingAvailable,
|
|
97
|
+
markCurrentPlan: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (entitlementState === 'suspended') {
|
|
101
|
+
return {
|
|
102
|
+
entitlementState,
|
|
103
|
+
gate: gate || null,
|
|
104
|
+
isActive: false,
|
|
105
|
+
allowReturnToApp: false,
|
|
106
|
+
statusTone: 'error',
|
|
107
|
+
message: 'Your access is suspended because billing needs attention. Update billing to restore access.',
|
|
108
|
+
primaryAction: billingAvailable ? 'manage_billing' : 'open_plans',
|
|
109
|
+
primaryLabel: billingAvailable ? 'Manage Billing' : 'Open Plans',
|
|
110
|
+
showManageBilling: billingAvailable,
|
|
111
|
+
markCurrentPlan: false,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (entitlementState === 'canceled') {
|
|
115
|
+
return {
|
|
116
|
+
entitlementState,
|
|
117
|
+
gate: gate || null,
|
|
118
|
+
isActive: false,
|
|
119
|
+
allowReturnToApp: false,
|
|
120
|
+
statusTone: 'error',
|
|
121
|
+
message: 'Your access has ended. Choose a plan to reactivate your workspace.',
|
|
122
|
+
primaryAction: 'choose_plan',
|
|
123
|
+
primaryLabel: 'Choose Plan',
|
|
124
|
+
showManageBilling: billingAvailable,
|
|
125
|
+
markCurrentPlan: false,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (entitlementState === 'pending_plan_selection' || summary?.planSelectionRequired === true || gate === 'plan_selection_required') {
|
|
129
|
+
return {
|
|
130
|
+
entitlementState: entitlementState || 'pending_plan_selection',
|
|
131
|
+
gate: gate || 'plan_selection_required',
|
|
132
|
+
isActive: false,
|
|
133
|
+
allowReturnToApp: false,
|
|
134
|
+
statusTone: 'info',
|
|
135
|
+
message: summaryMessage || GATE_MESSAGES.planSelectionRequired,
|
|
136
|
+
primaryAction: 'choose_plan',
|
|
137
|
+
primaryLabel: 'Choose Plan',
|
|
138
|
+
showManageBilling: false,
|
|
139
|
+
markCurrentPlan: false,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (entitlementState === 'checkout_pending' || gate === 'checkout_pending') {
|
|
143
|
+
return {
|
|
144
|
+
entitlementState: entitlementState || 'checkout_pending',
|
|
145
|
+
gate: gate || 'checkout_pending',
|
|
146
|
+
isActive: false,
|
|
147
|
+
allowReturnToApp: false,
|
|
148
|
+
statusTone: 'info',
|
|
149
|
+
message: summaryMessage || GATE_MESSAGES.checkoutPending,
|
|
150
|
+
primaryAction: 'open_plans',
|
|
151
|
+
primaryLabel: 'Open Plans',
|
|
152
|
+
showManageBilling: billingAvailable,
|
|
153
|
+
markCurrentPlan: false,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (gate === 'misconfigured') {
|
|
157
|
+
return {
|
|
158
|
+
entitlementState: entitlementState || null,
|
|
159
|
+
gate,
|
|
160
|
+
isActive: false,
|
|
161
|
+
allowReturnToApp: false,
|
|
162
|
+
statusTone: 'error',
|
|
163
|
+
message: GATE_MESSAGES.misconfigured,
|
|
164
|
+
primaryAction: 'none',
|
|
165
|
+
primaryLabel: null,
|
|
166
|
+
showManageBilling: false,
|
|
167
|
+
markCurrentPlan: false,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (gate === 'missing_entitlement') {
|
|
171
|
+
return {
|
|
172
|
+
entitlementState: entitlementState || null,
|
|
173
|
+
gate,
|
|
174
|
+
isActive: false,
|
|
175
|
+
allowReturnToApp: false,
|
|
176
|
+
statusTone: 'error',
|
|
177
|
+
message: GATE_MESSAGES.missingEntitlement,
|
|
178
|
+
primaryAction: 'choose_plan',
|
|
179
|
+
primaryLabel: 'Choose Plan',
|
|
180
|
+
showManageBilling: false,
|
|
181
|
+
markCurrentPlan: false,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
entitlementState: entitlementState || null,
|
|
186
|
+
gate: gate || null,
|
|
187
|
+
isActive: false,
|
|
188
|
+
allowReturnToApp: false,
|
|
189
|
+
statusTone: summaryMessage ? 'error' : 'info',
|
|
190
|
+
message: summaryMessage || null,
|
|
191
|
+
primaryAction: 'none',
|
|
192
|
+
primaryLabel: null,
|
|
193
|
+
showManageBilling: billingAvailable,
|
|
194
|
+
markCurrentPlan: false,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
@@ -5,6 +5,10 @@ function getActivityFieldLabel(field) {
|
|
|
5
5
|
return 'DESCRIPTION';
|
|
6
6
|
if (field === 'assignee')
|
|
7
7
|
return 'ASSIGNED TO';
|
|
8
|
+
if (field === 'workstreamId')
|
|
9
|
+
return 'WORKSTREAM';
|
|
10
|
+
if (field === 'initiativeId')
|
|
11
|
+
return 'INITIATIVE';
|
|
8
12
|
return field;
|
|
9
13
|
}
|
|
10
14
|
function formatValue(value, field, formatter) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { summarizeTaskChange } from './taskActivity';
|
|
2
|
+
import { summarizeTaskChange, summarizeTaskEvent } from './taskActivity';
|
|
3
3
|
describe('summarizeTaskChange', () => {
|
|
4
4
|
it('summarizes title edits without dumping before and after text', () => {
|
|
5
5
|
expect(summarizeTaskChange('title', {
|
|
@@ -58,4 +58,28 @@ describe('summarizeTaskChange', () => {
|
|
|
58
58
|
],
|
|
59
59
|
})).toBe('Checklist reordered');
|
|
60
60
|
});
|
|
61
|
+
it('uses readable labels for workstream relationship changes', () => {
|
|
62
|
+
expect(summarizeTaskChange('workstreamId', { from: null, to: 'workstream-1' }, (_field, value) => value === 'workstream-1' ? 'WS-12' : undefined)).toBe('WORKSTREAM: none -> WS-12');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('summarizeTaskEvent', () => {
|
|
66
|
+
it('uses readable labels for task relationship events', () => {
|
|
67
|
+
expect(summarizeTaskEvent({
|
|
68
|
+
id: 'event-1',
|
|
69
|
+
taskId: 'task-1',
|
|
70
|
+
workspaceId: 'default',
|
|
71
|
+
action: 'task-relationship-changed',
|
|
72
|
+
actor: 'user',
|
|
73
|
+
actorType: 'human',
|
|
74
|
+
createdAt: '2026-04-12T21:42:00.000Z',
|
|
75
|
+
details: {
|
|
76
|
+
changes: {
|
|
77
|
+
workstreamId: {
|
|
78
|
+
from: null,
|
|
79
|
+
to: 'workstream-1',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
}, (_field, value) => value === 'workstream-1' ? 'WS-12' : undefined)).toBe('Workstream: none -> WS-12');
|
|
84
|
+
});
|
|
61
85
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskforcehq/taskforce",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.305",
|
|
4
4
|
"description": "Mission Command center for AI-powered task management (beta - under active development)",
|
|
5
5
|
"author": "Taskforce HQ <hello@taskforcehq.ai> (https://taskforcehq.ai)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -76,11 +76,20 @@
|
|
|
76
76
|
"test:e2e:realtime:attachments": "npm run test:e2e:realtime -- tests/e2e/attachment-sync.spec.ts",
|
|
77
77
|
"test:e2e:realtime:multiclient": "npm run test:e2e:realtime -- tests/e2e/realtime-multiclient.spec.ts",
|
|
78
78
|
"test:e2e:realtime:reconnect": "npm run test:e2e:realtime -- tests/e2e/realtime-reconnect.spec.ts",
|
|
79
|
+
"test:e2e:onboarding": "npx playwright test -c playwright.e2e.config.ts tests/e2e/auth-runtime.spec.ts tests/e2e/billing-runtime.spec.ts",
|
|
80
|
+
"test:billing:deterministic": "npx vitest run src/server/routes/billing.test.ts src/components/views/PlansPage.test.tsx src/components/views/PlanComparisonPage.test.tsx src/migrations/billingSchemaParity.test.ts",
|
|
81
|
+
"test:billing:runtime:mock": "npx playwright test -c playwright.e2e.config.ts tests/e2e/billing-runtime.spec.ts",
|
|
82
|
+
"test:billing:local": "npm run test:billing:deterministic && npm run test:billing:runtime:mock",
|
|
83
|
+
"test:billing:performance:smoke": "sh scripts/run-billing-performance-smoke.sh",
|
|
84
|
+
"test:billing:performance:smoke:live": "TASKFORCE_BILLING_ENABLE_LIVE_PURCHASE=1 sh scripts/run-billing-performance-smoke.sh",
|
|
79
85
|
"playwright:auth:bootstrap": "node scripts/bootstrap-playwright-auth.mjs",
|
|
80
86
|
"playwright:auth": "sh scripts/playwright-auth.sh",
|
|
87
|
+
"playwright:interactive": "playwright test -c playwright.interactive.config.ts tests/e2e/interactive.smoke.spec.ts",
|
|
88
|
+
"playwright:interactive:headed": "playwright test --headed -c playwright.interactive.config.ts tests/e2e/interactive.smoke.spec.ts",
|
|
81
89
|
"qa:open": "node scripts/qa-open.mjs",
|
|
82
90
|
"check:env": "node --import tsx scripts/check-env.ts --target=server --strict=true",
|
|
83
91
|
"check:env:soak": "node --import tsx scripts/check-env.ts --target=soak --strict=true",
|
|
92
|
+
"check:mcp-smoke": "node scripts/check-cloud-mcp.mjs",
|
|
84
93
|
"check:compat": "node scripts/check-compat-boundaries.mjs",
|
|
85
94
|
"gen:env-example": "node --import tsx scripts/generate-env-example.ts",
|
|
86
95
|
"check:sync-smoke-preflight": "node --import tsx src/soak/preflight.cli.ts",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const DEFAULT_ENDPOINTS = {
|
|
4
|
+
production: 'https://mcp.taskforcehq.ai/mcp',
|
|
5
|
+
staging: 'https://staging-mcp.taskforcehq.ai/mcp',
|
|
6
|
+
performance: 'https://performance-mcp.taskforcehq.ai/mcp'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const REQUEST_TIMEOUT_MS = 10000;
|
|
10
|
+
|
|
11
|
+
function normalizeTargets(argv) {
|
|
12
|
+
const values = argv.length > 0 ? argv : Object.keys(DEFAULT_ENDPOINTS);
|
|
13
|
+
return values.map((value) => {
|
|
14
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
15
|
+
if (DEFAULT_ENDPOINTS[normalized]) {
|
|
16
|
+
return {
|
|
17
|
+
label: normalized,
|
|
18
|
+
url: DEFAULT_ENDPOINTS[normalized]
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
label: normalized || 'custom',
|
|
23
|
+
url: String(value || '').trim()
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function checkEndpoint(target) {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(target.url, {
|
|
33
|
+
method: 'GET',
|
|
34
|
+
headers: {
|
|
35
|
+
Accept: 'application/json'
|
|
36
|
+
},
|
|
37
|
+
signal: controller.signal
|
|
38
|
+
});
|
|
39
|
+
const contentType = String(response.headers.get('content-type') || '');
|
|
40
|
+
const responseText = await response.text();
|
|
41
|
+
let payload = null;
|
|
42
|
+
try {
|
|
43
|
+
payload = responseText ? JSON.parse(responseText) : null;
|
|
44
|
+
} catch {
|
|
45
|
+
payload = null;
|
|
46
|
+
}
|
|
47
|
+
const message = typeof payload?.error?.message === 'string'
|
|
48
|
+
? payload.error.message.trim()
|
|
49
|
+
: '';
|
|
50
|
+
|
|
51
|
+
if (response.status !== 401) {
|
|
52
|
+
throw new Error(`expected HTTP 401 but received ${response.status}`);
|
|
53
|
+
}
|
|
54
|
+
if (!contentType.includes('application/json')) {
|
|
55
|
+
throw new Error(`expected application/json response but received ${contentType || 'unknown content-type'}`);
|
|
56
|
+
}
|
|
57
|
+
if (message !== 'Unauthorized.') {
|
|
58
|
+
throw new Error(`expected MCP Unauthorized. payload but received message=${JSON.stringify(message || responseText.slice(0, 200))}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`[mcp-smoke] ${target.label} ok ${target.url} -> 401 Unauthorized.`);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
throw new Error(`[mcp-smoke] ${target.label} failed ${target.url}: ${message}`);
|
|
65
|
+
} finally {
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const targets = normalizeTargets(process.argv.slice(2));
|
|
72
|
+
for (const target of targets) {
|
|
73
|
+
if (!target.url) {
|
|
74
|
+
throw new Error(`[mcp-smoke] ${target.label} has no URL to check.`);
|
|
75
|
+
}
|
|
76
|
+
await checkEndpoint(target);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
main().catch((error) => {
|
|
81
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
});
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
|
+
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
5
6
|
|
|
6
7
|
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
7
9
|
# shellcheck disable=SC1090
|
|
8
10
|
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
12
|
+
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
13
|
+
set -a
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$REPO_E2E_ENV_FILE"
|
|
16
|
+
set +a
|
|
9
17
|
fi
|
|
10
18
|
|
|
11
19
|
exec node scripts/bootstrap-playwright-auth.mjs "$@"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
|
+
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
6
|
+
|
|
7
|
+
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
9
|
+
# shellcheck disable=SC1090
|
|
10
|
+
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
12
|
+
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
13
|
+
set -a
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$REPO_E2E_ENV_FILE"
|
|
16
|
+
set +a
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL="${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
|
|
20
|
+
export TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
|
|
21
|
+
export TASKFORCE_PLAYWRIGHT_BASE_URL="${TASKFORCE_PLAYWRIGHT_BASE_URL:-$TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL}"
|
|
22
|
+
|
|
23
|
+
node scripts/bootstrap-playwright-auth.mjs
|
|
24
|
+
exec npx playwright test -c playwright.interactive.config.ts tests/e2e/billing-performance.smoke.spec.ts "$@"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,j as e}from"./vendor-react-CKJs5o3c.js";import{p as T,u as C,v as w,w as S,t as s,x as M}from"./index-CLIMgR6g.js";import{h as L,B as A,k as I,a9 as H,aH as B,aI as D,b as R}from"./vendor-icons-pWocEipT.js";import"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";import"./vendor-router-BbWMxlnO.js";function F({workspaceId:h}){const[x,k]=n.useState([]),[j,y]=n.useState(!1),[c,P]=n.useState(null),[p,m]=n.useState(null),[d,g]=n.useState(null),N=n.useCallback(async()=>{if(h){y(!0);try{const a=await(await fetch(`/api/taskforce/workspace/assignee-options?workspaceId=${encodeURIComponent(h)}`,{credentials:"include"})).json().catch(()=>({})),t=Array.isArray(a?.assignees)?a.assignees.filter(i=>i.kind==="agent").map(i=>({id:String(i.value||""),name:String(i.label||i.value||"Unknown Agent"),username:String(i.username||i.value||""),icon:String(i.icon||"Bot"),color:String(i.color||"#6B7280"),kind:String(i.kind||"agent"),description:typeof i.description=="string"?i.description:null,role:typeof i.role=="string"?i.role:null,provider:typeof i.provider=="string"?i.provider:null,model:typeof i.model=="string"?i.model:null,surfaceType:T(i.surfaceType),createdAt:String(i.createdAt||""),updatedAt:String(i.updatedAt||i.createdAt||""),lastActiveAt:typeof i.lastActiveAt=="string"?i.lastActiveAt:null})):[];k(t)}finally{y(!1)}}},[h]);n.useEffect(()=>{N()},[N]);const f=n.useMemo(()=>{const r=new Map;for(const a of x){const t=C(a.surfaceType);r.has(t)||r.set(t,new Map);const i=r.get(t),v=a.name.toLowerCase();i.has(v)||i.set(v,[]),i.get(v).push(a)}return w.map(a=>({section:a,label:S(a),groups:Array.from(r.get(a)?.entries()||[]).map(([t,i])=>({groupId:`${a}:${t}`,section:a,sectionLabel:S(a),profiles:i,primaryProfile:i[0]}))})).filter(a=>a.groups.length>0)},[x]),o=n.useMemo(()=>f.flatMap(r=>r.groups),[f]),l=n.useMemo(()=>o.find(r=>r.groupId===d)||o[0]||null,[o,d]);n.useEffect(()=>{if(!o.length){d!==null&&g(null);return}(!d||!o.some(r=>r.groupId===d))&&g(o[0].groupId)},[o,d]);const b=async(r,a)=>{m(null);try{const t=await fetch("/api/taskforce/workspace/ai-profiles/merge",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({keepId:r,mergeId:a})}),i=await t.json().catch(()=>({}));if(!t.ok){m({type:"error",message:String(i?.error||"Failed to merge AI profiles.")});return}P(null),m({type:"success",message:"AI profiles merged."}),await N()}catch{m({type:"error",message:"Failed to merge AI profiles."})}},u=r=>{const a=String(r||"").trim();if(!a)return"Unknown";const t=Date.parse(a);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):a};return e.jsx("div",{className:`${s.standalonePage} ${s.standaloneContent}`,style:{overflow:"auto"},children:e.jsx("div",{className:s.settingsContent,style:{maxWidth:960,margin:"0 auto",width:"100%"},children:e.jsx("div",{className:s.settingGroup,children:e.jsxs("div",{children:[e.jsx("h4",{className:s.settingSubTitle,children:"Registered AI Profiles"}),e.jsx("p",{className:`${s.settingsHint} ${s.marginBottom12}`,children:"AI agents register profiles when connecting via MCP. Merge duplicates created when a token was lost."}),j&&e.jsxs("div",{className:s.settingsHint,children:[e.jsx(L,{size:13,className:s.spinner})," Loading profiles…"]}),!j&&x.length===0&&e.jsx("div",{className:s.settingsHint,children:"No AI profiles registered yet."}),!j&&f.length>0&&e.jsxs("div",{className:s.aiProfilesExplorer,children:[e.jsx("div",{className:s.aiProfilesListPane,children:e.jsx("div",{className:s.aiProfilesList,children:f.map(r=>e.jsxs("div",{className:s.aiProfilesSection,children:[e.jsx("div",{className:s.aiProfilesSectionHeader,children:r.label}),r.groups.map(a=>{const t=l?.groupId===a.groupId,i=a.primaryProfile;return e.jsxs("button",{type:"button",className:`${s.aiProfileGroup} ${a.profiles.length>1?s.aiProfileGroupDuplicate:""} ${t?s.aiProfileGroupSelected:""}`,onClick:()=>g(a.groupId),"aria-pressed":t,children:[e.jsxs("div",{className:s.aiProfileGroupHeader,children:[e.jsx(A,{size:13,style:{color:i.color}}),e.jsx("span",{className:s.aiProfileName,children:i.name}),a.profiles.length>1&&e.jsxs("span",{className:s.aiProfileDuplicateBadge,children:[e.jsx(I,{size:11})," ",a.profiles.length," duplicates"]})]}),e.jsxs("div",{className:s.settingsHint,style:{marginTop:6},children:["@",i.username]}),(i.surfaceType||i.role||i.provider||i.model)&&e.jsxs("div",{className:s.aiProfileMetaRow,children:[i.surfaceType&&e.jsx("span",{className:s.aiProfileSurfaceBadge,children:M(i.surfaceType)}),i.role&&e.jsx("span",{children:i.role}),i.provider&&e.jsx("span",{children:i.provider}),i.model&&e.jsx("span",{children:i.model})]}),i.description&&e.jsx("div",{className:s.settingsHint,style:{marginTop:4},children:i.description})]},a.groupId)})]},r.section))})}),l&&e.jsx("div",{className:s.aiProfileDetailPane,children:e.jsxs("div",{className:s.aiProfileDetailCard,children:[e.jsxs("div",{className:s.aiProfileDetailHero,children:[e.jsx("div",{className:s.aiProfileDetailIcon,style:{color:l.primaryProfile.color},children:e.jsx(A,{size:18})}),e.jsxs("div",{className:s.aiProfileDetailHeading,children:[e.jsx("div",{className:s.aiProfileDetailTitleRow,children:e.jsx("h5",{className:s.aiProfileDetailTitle,children:l.primaryProfile.name})}),e.jsxs("div",{className:s.aiProfileDetailMetaRow,children:[e.jsxs("span",{className:s.aiProfileDetailHandle,children:["@",l.primaryProfile.username]}),e.jsx("span",{className:s.aiProfileDetailSectionBadge,children:l.sectionLabel}),l.profiles.length>1&&e.jsxs("span",{className:s.aiProfileDetailLinkedCount,children:[l.profiles.length," linked"]})]})]})]}),l.primaryProfile.description&&e.jsx("div",{className:s.aiProfileDetailDescription,children:l.primaryProfile.description}),e.jsxs("div",{className:s.aiProfileDetailGrid,children:[e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(H,{size:12})," Role"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:l.primaryProfile.role||"Not set"})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(B,{size:12})," Provider"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:[l.primaryProfile.provider,l.primaryProfile.model].filter(Boolean).join(" · ")||"Not set"})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(D,{size:12})," Last active"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:u(l.primaryProfile.lastActiveAt)})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(D,{size:12})," Updated"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:u(l.primaryProfile.updatedAt)})]})]}),e.jsxs("div",{className:s.aiProfileInstanceSection,children:[e.jsxs("div",{className:s.aiProfileInstanceSectionHeader,children:[e.jsx("span",{children:"Profile instances"}),e.jsx("span",{className:s.settingsHint,children:"Choose a keeper here if duplicates need to be merged."})]}),e.jsx("div",{className:s.aiProfileInstanceList,children:l.profiles.map(r=>e.jsxs("div",{className:s.aiProfileInstanceCard,children:[e.jsxs("div",{className:s.aiProfileInstanceTopRow,children:[e.jsxs("div",{children:[e.jsxs("div",{className:s.aiProfileInstanceName,children:["@",r.username]}),e.jsx("div",{className:s.aiProfileIdChip,children:r.id})]}),l.profiles.length>1&&c?.keepId===r.id&&e.jsx("span",{className:s.aiProfileKeepBadge,children:"Keeping"})]}),e.jsxs("div",{className:s.aiProfileInstanceMeta,children:[e.jsxs("span",{children:["Created ",u(r.createdAt)]}),e.jsxs("span",{children:["Updated ",u(r.updatedAt)]})]}),l.profiles.length>1&&c?.keepId!==r.id&&e.jsx("button",{className:s.secondaryHeaderBtn,title:"Keep this profile, merge others into it",onClick:()=>{const a=l.profiles.find(t=>t.id!==r.id)?.id;a&&P({keepId:r.id,mergeId:a})},children:"Keep this"})]},r.id))}),c&&l.profiles.some(r=>r.id===c.keepId)&&e.jsxs("div",{className:s.aiProfileMergeActions,children:[e.jsx("button",{className:s.dangerBtn,onClick:()=>{b(c.keepId,c.mergeId)},children:"Merge duplicates"}),e.jsx("button",{className:s.secondaryHeaderBtn,onClick:()=>P(null),children:"Cancel"})]})]})]})})]}),p&&e.jsxs("div",{className:`${p.type==="success"?s.successMessage:s.errorMessage} ${s.marginTop12}`,children:[p.type==="success"?e.jsx(R,{size:14}):e.jsx(I,{size:14}),p.message]})]})})})})}export{F as AgentsModule};
|