@taskforcehq/taskforce 0.3.306 → 0.3.307
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/Taskforce.module.css +317 -27
- package/dist/TaskforceCore.js +1 -0
- package/dist/TaskforceCore.test.js +178 -0
- package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.js +15 -3
- package/dist/components/features/AgentsModule.d.ts +5 -1
- package/dist/components/features/AgentsModule.js +142 -39
- package/dist/components/features/AgentsModule.test.js +260 -11
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +3 -1
- package/dist/components/features/DocumentViewer.js +6 -5
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +20 -3
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +6 -2
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +14 -64
- package/dist/components/task/TaskKanban.js +0 -8
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.js +9 -1
- package/dist/components/views/PlanComparisonPage.test.js +19 -0
- package/dist/components/views/PlansPage.js +1 -1
- package/dist/components/views/StandaloneLayout.js +256 -69
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +19 -6
- package/dist/components/views/panels/PlanningDrawer.js +259 -51
- package/dist/components/views/panels/PlanningDrawer.test.js +392 -4
- package/dist/config/envSchema.js +1 -0
- package/dist/core/AiProfileService.d.ts +7 -0
- package/dist/core/AiProfileService.js +460 -35
- package/dist/core/AiProfiles.test.js +648 -2
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +58 -13
- package/dist/core/GlobalSettingsService.js +12 -0
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- package/dist/core/PlanningEntities.test.js +366 -4
- package/dist/core/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +190 -26
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +775 -71
- package/dist/core/Taskforce.mcpAuth.test.js +109 -0
- package/dist/core/types.d.ts +7 -0
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +2 -1
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +3 -3
- package/dist/hooks/sync/orchestratorShared.js +61 -1
- package/dist/hooks/sync/recovery.js +8 -0
- package/dist/hooks/sync/recovery.test.js +5 -5
- package/dist/hooks/sync/transfers.d.ts +2 -1
- package/dist/hooks/sync/transfers.js +36 -9
- package/dist/hooks/sync/transfers.test.js +534 -2
- package/dist/hooks/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.js +50 -5
- package/dist/hooks/useTaskforce.d.ts +85 -50
- package/dist/hooks/useTaskforce.js +44 -14
- package/dist/hooks/useTaskforce.runtime-routing.test.js +94 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +99 -0
- package/dist/hooks/useWorkspaceSyncController.js +7 -1
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +14 -7
- package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +113 -7
- package/dist/mcp/runtime.d.ts +1 -0
- package/dist/mcp/runtime.js +969 -122
- package/dist/mcp/runtime.test.js +1083 -11
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.js +21 -0
- package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +66 -7
- package/dist/server/index.js +4 -0
- package/dist/server/index.test.js +6 -1
- package/dist/server/routes/admin.js +187 -9
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +11 -0
- package/dist/server/routes/auth.js +189 -27
- package/dist/server/routes/authSupport.d.ts +4 -0
- package/dist/server/routes/authSupport.js +12 -1
- package/dist/server/routes/billing.js +11 -0
- package/dist/server/routes/billing.test.js +3 -0
- package/dist/server/routes/documents.js +10 -0
- package/dist/server/routes/shared.js +0 -10
- package/dist/server/routes/sync.integration.test.js +221 -0
- package/dist/server/routes/sync.js +13 -3
- package/dist/server/routes/syncSnapshotRoutes.js +2 -0
- package/dist/server/routes/tasks.js +12 -9
- package/dist/server/routes.js +87 -8
- package/dist/server/routes.test.js +890 -22
- package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- package/dist/storage/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- package/dist/sync/collaborationSyncPayload.js +2 -0
- package/dist/sync/collaborationSyncPayload.test.js +1 -0
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +5 -1
- package/dist/sync/contentSyncState.js +231 -37
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +4 -4
- package/dist/sync/syncApplyHandlers.js +89 -31
- package/dist/sync/syncApplyHandlers.test.js +184 -4
- package/dist/sync/syncResourceAdapters.d.ts +2 -0
- package/dist/sync/syncResourceAdapters.js +2 -0
- package/dist/sync/syncService.d.ts +1 -0
- package/dist/sync/syncService.js +13 -1
- package/dist/sync/syncService.test.js +39 -0
- package/dist/sync/workspacePullFeed.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +129 -70
- package/dist/sync/workspacePullFeed.test.js +49 -0
- package/dist/sync/workspaceSyncModel.d.ts +28 -6
- package/dist/sync/workspaceSyncModel.js +159 -45
- package/dist/sync/workspaceSyncModel.test.js +269 -3
- package/dist/types.d.ts +33 -2
- package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
- package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
- package/dist/ui/assets/{InitiativesModule-9E6ParrY.js → InitiativesModule-D4XseTwW.js} +1 -1
- package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
- package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
- package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
- package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BA7jcEpH.js → WorkflowsModule-oOA9bcdK.js} +4 -4
- package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
- package/dist/ui/assets/index-607WPo_X.js +4 -0
- package/dist/ui/assets/index-CYyodXsg.css +1 -0
- package/dist/ui/assets/{vendor-icons-DuEd_65c.js → vendor-icons-B32hGuF2.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +6 -0
- package/dist/utils/assignees.js +8 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -0
- package/dist/utils/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- package/dist/utils/taskActivity.d.ts +7 -1
- package/dist/utils/taskActivity.js +63 -1
- package/dist/utils/taskActivity.test.js +23 -1
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- package/package.json +1 -1
- package/dist/ui/assets/AgentsModule-DrLawwNl.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-Z9_whf7F.js +0 -3
- package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +0 -252
- package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +0 -1
- package/dist/ui/assets/PlansPage-CvfnMiWq.css +0 -1
- package/dist/ui/assets/PlansPage-DRXscYxH.js +0 -1
- package/dist/ui/assets/TaskSettings-DZX4jk7e.js +0 -9
- package/dist/ui/assets/index-9eT8e0Lu.css +0 -1
- package/dist/ui/assets/index-C6k75jr8.js +0 -6
|
@@ -910,6 +910,48 @@ describe('TaskforceCore Integration', () => {
|
|
|
910
910
|
});
|
|
911
911
|
expect(container.querySelector('[aria-pressed]')).not.toBeInTheDocument();
|
|
912
912
|
});
|
|
913
|
+
it('renders the cloud login route even while protected startup config is pending', async () => {
|
|
914
|
+
const hangingConfig = new Promise(() => { });
|
|
915
|
+
const fetchMock = vi.fn((url) => {
|
|
916
|
+
if (url.includes('/api/taskforce/auth/runtime-config')) {
|
|
917
|
+
return Promise.resolve({
|
|
918
|
+
ok: true,
|
|
919
|
+
json: () => Promise.resolve({
|
|
920
|
+
config: {
|
|
921
|
+
runtimeMode: 'cloud',
|
|
922
|
+
workspaceMode: 'multi-cloud',
|
|
923
|
+
authSource: 'cloud',
|
|
924
|
+
workspaceSwitchingEnabled: true
|
|
925
|
+
}
|
|
926
|
+
})
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
if (url.includes('/api/taskforce/auth/session')) {
|
|
930
|
+
return Promise.resolve({
|
|
931
|
+
ok: true,
|
|
932
|
+
json: () => Promise.resolve({
|
|
933
|
+
authenticated: false,
|
|
934
|
+
runtimeMode: 'cloud'
|
|
935
|
+
})
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
if (url.includes('/api/taskforce/config')) {
|
|
939
|
+
return hangingConfig;
|
|
940
|
+
}
|
|
941
|
+
if (url.includes('/api/taskforce/auth/providers')) {
|
|
942
|
+
return Promise.resolve({ ok: true, json: () => Promise.resolve({ providers: [] }) });
|
|
943
|
+
}
|
|
944
|
+
return Promise.resolve({ ok: true, json: () => Promise.resolve({}) });
|
|
945
|
+
});
|
|
946
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
947
|
+
render(_jsx(MemoryRouter, { initialEntries: ['/login?mode=login&next=%2Ftaskforce%2F'], children: _jsx(TaskforceCore, {}) }));
|
|
948
|
+
await waitFor(() => {
|
|
949
|
+
expect(screen.getByPlaceholderText('Email')).toBeInTheDocument();
|
|
950
|
+
expect(screen.getByPlaceholderText('Password')).toBeInTheDocument();
|
|
951
|
+
expect(screen.getByRole('button', { name: 'Sign In' })).toBeInTheDocument();
|
|
952
|
+
});
|
|
953
|
+
expect(screen.queryByText('Loading Taskforce')).not.toBeInTheDocument();
|
|
954
|
+
});
|
|
913
955
|
it('allows public access to /pricing in cloud mode without login redirect', async () => {
|
|
914
956
|
const fetchMock = vi.fn((url) => {
|
|
915
957
|
if (url.includes('/api/taskforce/auth/session')) {
|
|
@@ -6002,6 +6044,142 @@ describe('TaskforceCore Integration', () => {
|
|
|
6002
6044
|
await user.click(screen.getByTitle(/Account/i));
|
|
6003
6045
|
expect(await screen.findByText('Sign In / Register')).toBeInTheDocument();
|
|
6004
6046
|
});
|
|
6047
|
+
it('returns to the login screen after signing out from the cloud plans screen', async () => {
|
|
6048
|
+
const user = userEvent.setup();
|
|
6049
|
+
let signedIn = true;
|
|
6050
|
+
const fetchMock = vi.fn((url) => {
|
|
6051
|
+
if (url.includes('/api/taskforce/auth/runtime-config')) {
|
|
6052
|
+
return jsonResponse({ config: { runtimeMode: 'cloud', workspaceMode: 'team', authSource: 'cloud' } });
|
|
6053
|
+
}
|
|
6054
|
+
if (url.includes('/api/taskforce/auth/session')) {
|
|
6055
|
+
return jsonResponse({
|
|
6056
|
+
authenticated: signedIn,
|
|
6057
|
+
runtimeMode: 'cloud',
|
|
6058
|
+
authRequiredForApi: true,
|
|
6059
|
+
email: signedIn ? 'member@example.com' : '',
|
|
6060
|
+
userId: signedIn ? 'user-member' : 'anonymous',
|
|
6061
|
+
workspaceId: signedIn ? 'workspace-cloud-active' : '',
|
|
6062
|
+
betaAccess: true
|
|
6063
|
+
});
|
|
6064
|
+
}
|
|
6065
|
+
if (url.includes('/api/taskforce/auth/logout')) {
|
|
6066
|
+
signedIn = false;
|
|
6067
|
+
return jsonResponse({ success: true });
|
|
6068
|
+
}
|
|
6069
|
+
if (url.includes('/api/taskforce/config')) {
|
|
6070
|
+
return jsonResponse({
|
|
6071
|
+
...mockConfig,
|
|
6072
|
+
runtimeMode: 'cloud',
|
|
6073
|
+
authRequiredForApi: true,
|
|
6074
|
+
workspaceId: 'workspace-cloud-active',
|
|
6075
|
+
workspaceSwitchingEnabled: true,
|
|
6076
|
+
setupState: {
|
|
6077
|
+
globalSetupState: 'present',
|
|
6078
|
+
workspaceSetupState: 'present',
|
|
6079
|
+
runtimeMode: 'cloud',
|
|
6080
|
+
workspaceId: 'workspace-cloud-active',
|
|
6081
|
+
mode: 'core',
|
|
6082
|
+
forceSetup: false,
|
|
6083
|
+
forceGlobalSetup: false,
|
|
6084
|
+
forceWorkspaceSetup: false
|
|
6085
|
+
}
|
|
6086
|
+
});
|
|
6087
|
+
}
|
|
6088
|
+
if (url.includes('/api/taskforce/account/access-status')) {
|
|
6089
|
+
return jsonResponse({
|
|
6090
|
+
gate: 'plan_selection_required',
|
|
6091
|
+
hasEntitlement: false,
|
|
6092
|
+
canAccessApp: false,
|
|
6093
|
+
canAccessPlans: true
|
|
6094
|
+
});
|
|
6095
|
+
}
|
|
6096
|
+
if (url.includes('/api/taskforce/public/pricing')) {
|
|
6097
|
+
return jsonResponse({
|
|
6098
|
+
plans: [
|
|
6099
|
+
{
|
|
6100
|
+
planId: 'free',
|
|
6101
|
+
displayName: 'Free',
|
|
6102
|
+
status: 'active',
|
|
6103
|
+
features: [],
|
|
6104
|
+
pricing: {
|
|
6105
|
+
month: { pricingType: 'free', stripePriceId: null, unitAmount: 0, currency: null, interval: 'month' },
|
|
6106
|
+
year: null
|
|
6107
|
+
},
|
|
6108
|
+
defaultVersion: {
|
|
6109
|
+
planVersionId: 'free-v1',
|
|
6110
|
+
versionNumber: 1,
|
|
6111
|
+
seatLimit: null,
|
|
6112
|
+
metadata: {}
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
]
|
|
6116
|
+
});
|
|
6117
|
+
}
|
|
6118
|
+
if (url.includes('/api/taskforce/account/profile-summary')) {
|
|
6119
|
+
return jsonResponse({
|
|
6120
|
+
planId: 'free',
|
|
6121
|
+
planName: 'Free',
|
|
6122
|
+
planVersionId: 'free-v1',
|
|
6123
|
+
entitlementState: 'pending_plan_selection',
|
|
6124
|
+
gate: 'plan_selection_required',
|
|
6125
|
+
planSelectionRequired: true
|
|
6126
|
+
});
|
|
6127
|
+
}
|
|
6128
|
+
if (url.includes('/api/taskforce/workspaces')) {
|
|
6129
|
+
return jsonResponse({ workspaces: [] });
|
|
6130
|
+
}
|
|
6131
|
+
if (url.includes('/api/taskforce/ui-state?key=app')) {
|
|
6132
|
+
return jsonResponse({ success: true, state: {} });
|
|
6133
|
+
}
|
|
6134
|
+
if (url.includes('/api/taskforce/ui-state?key=workspace-sync')) {
|
|
6135
|
+
return jsonResponse({ success: true, state: {} });
|
|
6136
|
+
}
|
|
6137
|
+
if (url.includes('/api/taskforce/categories')) {
|
|
6138
|
+
return jsonResponse(mockCategories);
|
|
6139
|
+
}
|
|
6140
|
+
if (url.includes('/api/taskforce/tasks')) {
|
|
6141
|
+
return jsonResponse({ tasks: mockTasks });
|
|
6142
|
+
}
|
|
6143
|
+
if (url.includes('/api/taskforce/archive')) {
|
|
6144
|
+
return jsonResponse({ archived: [] });
|
|
6145
|
+
}
|
|
6146
|
+
if (url.includes('/api/taskforce/types')) {
|
|
6147
|
+
return jsonResponse({ types: [] });
|
|
6148
|
+
}
|
|
6149
|
+
if (url.includes('/api/taskforce/priorities')) {
|
|
6150
|
+
return jsonResponse({ priorities: [] });
|
|
6151
|
+
}
|
|
6152
|
+
if (url.includes('/api/taskforce/approaches')) {
|
|
6153
|
+
return jsonResponse({ approaches: [] });
|
|
6154
|
+
}
|
|
6155
|
+
if (url.includes('/api/taskforce/specialists')) {
|
|
6156
|
+
return jsonResponse({ specialists: [] });
|
|
6157
|
+
}
|
|
6158
|
+
if (url.includes('/api/taskforce/workflow-templates')) {
|
|
6159
|
+
return jsonResponse({ templates: [] });
|
|
6160
|
+
}
|
|
6161
|
+
if (url.includes('/api/taskforce/workspace/assignee-options')) {
|
|
6162
|
+
return jsonResponse({ assignees: [] });
|
|
6163
|
+
}
|
|
6164
|
+
if (url.includes('/api/taskforce/planning/bootstrap')) {
|
|
6165
|
+
return jsonResponse({
|
|
6166
|
+
initiatives: [],
|
|
6167
|
+
workstreams: [],
|
|
6168
|
+
workstreamTaskSummaries: [],
|
|
6169
|
+
});
|
|
6170
|
+
}
|
|
6171
|
+
return jsonResponse({});
|
|
6172
|
+
});
|
|
6173
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
6174
|
+
render(_jsx(MemoryRouter, { initialEntries: ['/?screen=plans&gate=plan_selection_required'], children: _jsx(TaskforceCore, { config: { cloudAuthBaseUrl: 'https://cloud.example.com' } }) }));
|
|
6175
|
+
expect(await screen.findByRole('heading', { name: 'Subscription Plans' })).toBeInTheDocument();
|
|
6176
|
+
await user.click(screen.getByTitle(/Account/i));
|
|
6177
|
+
await user.click(await screen.findByRole('menuitem', { name: 'Sign Out' }));
|
|
6178
|
+
await waitFor(() => {
|
|
6179
|
+
expect(fetchMock.mock.calls.some((call) => String(call[0]).includes('/api/taskforce/auth/logout'))).toBe(true);
|
|
6180
|
+
expect(screen.getByText('Sign in with your account credentials.')).toBeInTheDocument();
|
|
6181
|
+
});
|
|
6182
|
+
});
|
|
6005
6183
|
it('uses an explicit cloud sign-out redirect and broader cloud logout reset path', () => {
|
|
6006
6184
|
const standaloneLayoutSource = fs.readFileSync(path.join(__dirname, 'components/views/StandaloneLayout.tsx'), 'utf8');
|
|
6007
6185
|
const useTaskforceSource = fs.readFileSync(path.join(__dirname, 'hooks/useTaskforce.ts'), 'utf8');
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type TaskEventValueFormatter } from '../../utils/taskActivity';
|
|
3
|
+
import type { EntityActivityItem, TaskActor } from '../../types';
|
|
4
|
+
export type ActivityActorPresentation = {
|
|
5
|
+
kind: 'member' | 'agent' | 'system';
|
|
6
|
+
label: string;
|
|
7
|
+
color?: string;
|
|
8
|
+
ActorIcon: React.ComponentType<{
|
|
9
|
+
size?: number;
|
|
10
|
+
strokeWidth?: number;
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
export declare function EntityActivityTimeline({ activity, comments, formatFieldValue, resolveActorPresentation, onOpenTaskById, emptyMessage, listClassName, emptyClassName, endRef, }: {
|
|
14
|
+
activity?: EntityActivityItem[];
|
|
15
|
+
comments?: Array<{
|
|
16
|
+
id: string;
|
|
17
|
+
author: string;
|
|
18
|
+
text: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
actor?: TaskActor | null;
|
|
21
|
+
}>;
|
|
22
|
+
formatFieldValue?: TaskEventValueFormatter;
|
|
23
|
+
resolveActorPresentation: (input: {
|
|
24
|
+
actorId?: string | null;
|
|
25
|
+
actorType?: 'human' | 'ai' | 'system' | null;
|
|
26
|
+
actorProfile?: TaskActor | null;
|
|
27
|
+
fallbackKind?: 'member' | 'agent' | 'system';
|
|
28
|
+
}) => ActivityActorPresentation;
|
|
29
|
+
onOpenTaskById?: (taskId: string) => void;
|
|
30
|
+
emptyMessage?: string;
|
|
31
|
+
listClassName?: string;
|
|
32
|
+
emptyClassName?: string;
|
|
33
|
+
endRef?: React.Ref<HTMLDivElement>;
|
|
34
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Markdown } from '../ui/Markdown';
|
|
4
|
+
import { formatDate } from '../../utils/formatting';
|
|
5
|
+
import { getEntityActivityItems, getEntityEventPrimaryChangeField, summarizeEntityEvent, summarizeTaskChange, } from '../../utils/taskActivity';
|
|
6
|
+
import timelineStyles from './EntityActivityTimeline.module.css';
|
|
7
|
+
function hexToRgba(hex, opacity) {
|
|
8
|
+
const normalized = hex.replace('#', '').trim();
|
|
9
|
+
if (normalized.length !== 3 && normalized.length !== 6)
|
|
10
|
+
return '';
|
|
11
|
+
const expanded = normalized.length === 3
|
|
12
|
+
? normalized.split('').map((part) => part + part).join('')
|
|
13
|
+
: normalized;
|
|
14
|
+
const int = Number.parseInt(expanded, 16);
|
|
15
|
+
if (Number.isNaN(int))
|
|
16
|
+
return '';
|
|
17
|
+
const red = (int >> 16) & 255;
|
|
18
|
+
const green = (int >> 8) & 255;
|
|
19
|
+
const blue = int & 255;
|
|
20
|
+
return `rgba(${red}, ${green}, ${blue}, ${opacity})`;
|
|
21
|
+
}
|
|
22
|
+
export function EntityActivityTimeline({ activity, comments, formatFieldValue, resolveActorPresentation, onOpenTaskById, emptyMessage = 'No activity yet.', listClassName, emptyClassName, endRef, }) {
|
|
23
|
+
const items = React.useMemo(() => getEntityActivityItems({ activity, comments }), [activity, comments]);
|
|
24
|
+
return (_jsxs("div", { className: [timelineStyles.thread, listClassName].filter(Boolean).join(' '), children: [items.length === 0 ? (_jsx("div", { className: [timelineStyles.empty, emptyClassName].filter(Boolean).join(' '), children: emptyMessage })) : null, items.map((item) => {
|
|
25
|
+
if (item.type === 'comment') {
|
|
26
|
+
const actorPresentation = resolveActorPresentation({
|
|
27
|
+
actorId: item.comment.author,
|
|
28
|
+
actorType: item.comment.actor?.kind === 'ai'
|
|
29
|
+
? 'ai'
|
|
30
|
+
: item.comment.actor?.kind === 'human'
|
|
31
|
+
? 'human'
|
|
32
|
+
: null,
|
|
33
|
+
actorProfile: item.comment.actor || null,
|
|
34
|
+
});
|
|
35
|
+
const commentKind = actorPresentation.kind === 'agent' ? 'agent' : 'member';
|
|
36
|
+
const { ActorIcon } = actorPresentation;
|
|
37
|
+
const authorColor = actorPresentation.color;
|
|
38
|
+
const commentAccentStyle = authorColor && hexToRgba(authorColor, 0.35)
|
|
39
|
+
? {
|
|
40
|
+
background: `linear-gradient(135deg, ${hexToRgba(authorColor, 0.18)} 0%, ${hexToRgba(authorColor, 0.1)} 100%)`,
|
|
41
|
+
borderColor: hexToRgba(authorColor, 0.35),
|
|
42
|
+
}
|
|
43
|
+
: undefined;
|
|
44
|
+
return (_jsxs("div", { className: [
|
|
45
|
+
timelineStyles.item,
|
|
46
|
+
timelineStyles.comment,
|
|
47
|
+
commentKind === 'agent' ? timelineStyles.commentAgent : timelineStyles.commentMember,
|
|
48
|
+
].join(' '), children: [_jsxs("div", { className: timelineStyles.header, children: [_jsxs("span", { className: timelineStyles.author, style: authorColor ? { color: authorColor } : undefined, children: [_jsx(ActorIcon, { size: 12, strokeWidth: 1.5 }), actorPresentation.label] }), _jsx("span", { className: timelineStyles.time, children: formatDate(item.comment.timestamp, {
|
|
49
|
+
month: 'short',
|
|
50
|
+
day: 'numeric',
|
|
51
|
+
hour: '2-digit',
|
|
52
|
+
minute: '2-digit',
|
|
53
|
+
}) })] }), _jsx("div", { className: timelineStyles.commentText, style: commentAccentStyle, children: _jsx(Markdown, { onTaskIdClick: onOpenTaskById, children: item.comment.text }) })] }, item.id));
|
|
54
|
+
}
|
|
55
|
+
const actorPresentation = resolveActorPresentation({
|
|
56
|
+
actorId: item.event.actor,
|
|
57
|
+
actorType: item.event.actorType,
|
|
58
|
+
actorProfile: item.event.actorProfile || null,
|
|
59
|
+
fallbackKind: 'system',
|
|
60
|
+
});
|
|
61
|
+
const { ActorIcon } = actorPresentation;
|
|
62
|
+
const authorColor = actorPresentation.color;
|
|
63
|
+
const changeEntries = Object.entries(item.event.details?.changes || {});
|
|
64
|
+
const primaryChangeField = getEntityEventPrimaryChangeField(item.event);
|
|
65
|
+
const displayedChangeEntries = changeEntries.length > 1 && primaryChangeField
|
|
66
|
+
? changeEntries.filter(([field]) => field !== primaryChangeField)
|
|
67
|
+
: changeEntries.length > 1
|
|
68
|
+
? changeEntries
|
|
69
|
+
: [];
|
|
70
|
+
return (_jsxs("div", { className: [
|
|
71
|
+
timelineStyles.item,
|
|
72
|
+
timelineStyles.event,
|
|
73
|
+
actorPresentation.kind === 'system' ? timelineStyles.eventSystem : '',
|
|
74
|
+
].filter(Boolean).join(' '), children: [_jsxs("div", { className: [timelineStyles.header, timelineStyles.eventHeader].join(' '), children: [_jsxs("span", { className: timelineStyles.author, style: authorColor ? { color: authorColor } : undefined, children: [_jsx(ActorIcon, { size: 12, strokeWidth: 1.5 }), actorPresentation.label] }), _jsx("span", { className: timelineStyles.time, children: formatDate(item.event.createdAt, {
|
|
75
|
+
month: 'short',
|
|
76
|
+
day: 'numeric',
|
|
77
|
+
hour: '2-digit',
|
|
78
|
+
minute: '2-digit',
|
|
79
|
+
}) })] }), _jsxs("div", { className: timelineStyles.eventText, children: [_jsx("div", { children: summarizeEntityEvent(item.event, formatFieldValue) }), displayedChangeEntries.length > 0 ? (_jsx("div", { className: timelineStyles.eventChanges, children: displayedChangeEntries.map(([field, change]) => (_jsx("div", { className: timelineStyles.eventChange, children: summarizeTaskChange(field, change, formatFieldValue) }, field))) })) : null] })] }, item.id));
|
|
80
|
+
}), _jsx("div", { ref: endRef })] }));
|
|
81
|
+
}
|
|
@@ -299,7 +299,9 @@ export function ContextAttachmentManager(props) {
|
|
|
299
299
|
referenceNumber: typeof data.referenceNumber === 'number' ? data.referenceNumber : null,
|
|
300
300
|
referenceLabel: typeof data.referenceLabel === 'string' ? data.referenceLabel : undefined,
|
|
301
301
|
taskId: ownerType === 'task' && typeof data.taskId === 'string' ? data.taskId : null,
|
|
302
|
-
timestamp:
|
|
302
|
+
timestamp: typeof data.timestamp === 'string' && data.timestamp.trim().length > 0
|
|
303
|
+
? data.timestamp
|
|
304
|
+
: new Date().toISOString()
|
|
303
305
|
});
|
|
304
306
|
dispatchTaskforceContextAssetsMutated({
|
|
305
307
|
workspaceId: trimmedWorkspaceId || 'default',
|
|
@@ -507,7 +509,12 @@ export function ContextAttachmentManager(props) {
|
|
|
507
509
|
e.target.style.display = 'none';
|
|
508
510
|
e.target.parentElement.classList.add(styles.brokenImage);
|
|
509
511
|
} })) : (_jsxs("button", { type: "button", className: styles.contextFileLink, onClick: () => {
|
|
510
|
-
|
|
512
|
+
const markdownTarget = ownerType === 'task'
|
|
513
|
+
? (typeof item === 'string'
|
|
514
|
+
? { path: item, taskId: trimmedOwnerId }
|
|
515
|
+
: { ...item, taskId: trimmedOwnerId })
|
|
516
|
+
: item;
|
|
517
|
+
if (dispatchOpenMarkdownDocument(markdownTarget, fsPath))
|
|
511
518
|
return;
|
|
512
519
|
window.open(path, '_blank');
|
|
513
520
|
}, title: "Open file", children: [_jsx(FileUp, { size: 16 }), _jsx("span", { children: caption || fsPath || path.split('/').pop() || 'Context file' })] })), _jsxs("div", { className: styles.brokenImagePlaceholder, children: [_jsx(AlertTriangle, { size: 16 }), _jsx("span", { children: "Preview unavailable" })] }), _jsxs("div", { className: styles.attachmentActions, children: [canAnnotate && (_jsx("button", { type: "button", className: styles.attachmentActionBtn, onClick: (e) => {
|
|
@@ -537,7 +544,12 @@ export function ContextAttachmentManager(props) {
|
|
|
537
544
|
const documentReferenceLabel = typeof item === 'string' ? '' : getDocumentReferenceLabel(item);
|
|
538
545
|
const isExternalUrl = /^https?:\/\//i.test(path);
|
|
539
546
|
return (_jsxs("div", { className: styles.documentAttachmentItem, children: [_jsxs("div", { className: styles.documentAttachmentRow, children: [_jsxs("button", { type: "button", className: styles.documentAttachmentLink, onClick: () => {
|
|
540
|
-
|
|
547
|
+
const markdownTarget = ownerType === 'task'
|
|
548
|
+
? (typeof item === 'string'
|
|
549
|
+
? { path: item, taskId: trimmedOwnerId }
|
|
550
|
+
: { ...item, taskId: trimmedOwnerId })
|
|
551
|
+
: item;
|
|
552
|
+
if (dispatchOpenMarkdownDocument(markdownTarget, fsPath))
|
|
541
553
|
return;
|
|
542
554
|
window.open(path, '_blank');
|
|
543
555
|
}, title: displayName, children: [_jsxs("span", { className: styles.documentAttachmentMain, children: [_jsx("span", { className: styles.documentAttachmentIcon, "aria-hidden": "true", children: _jsx(File, { size: 13 }) }), _jsxs("span", { className: styles.documentAttachmentText, children: [_jsx("span", { className: styles.documentAttachmentName, children: displayName }), documentReferenceLabel && (_jsx("span", { className: styles.taskIdBadge, children: documentReferenceLabel }))] })] }), _jsx("span", { className: styles.documentAttachmentType, children: fileType })] }), _jsxs("div", { className: styles.documentAttachmentActions, children: [fsPath && (_jsx("button", { type: "button", className: styles.documentAttachmentActionBtn, onClick: () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
type AiProfileSeatUsage = {
|
|
2
3
|
used: number;
|
|
3
4
|
limit: number | null;
|
|
@@ -9,6 +10,9 @@ interface AgentsModuleProps {
|
|
|
9
10
|
authSessionResolved?: boolean;
|
|
10
11
|
isAuthenticated?: boolean;
|
|
11
12
|
cloudAiProfileSeatUsage?: AiProfileSeatUsage | null;
|
|
13
|
+
agentTrayOpen?: boolean;
|
|
14
|
+
onCloseAgentTray?: () => void;
|
|
15
|
+
mcpSettingsNode?: React.ReactNode;
|
|
12
16
|
}
|
|
13
|
-
export declare function AgentsModule({ workspaceId, cloudAuthConfigured, authSessionResolved, isAuthenticated, cloudAiProfileSeatUsage, }: AgentsModuleProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function AgentsModule({ workspaceId, cloudAuthConfigured, authSessionResolved, isAuthenticated, cloudAiProfileSeatUsage, agentTrayOpen, onCloseAgentTray, mcpSettingsNode, }: AgentsModuleProps): import("react/jsx-runtime").JSX.Element;
|
|
14
18
|
export {};
|