@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.
Files changed (237) hide show
  1. package/README.md +140 -247
  2. package/dist/Taskforce.module.css +102 -5
  3. package/dist/TaskforceCore.js +635 -238
  4. package/dist/TaskforceCore.test.js +2243 -495
  5. package/dist/annotatedAttachments/service.d.ts +1 -1
  6. package/dist/annotatedAttachments/types.d.ts +1 -1
  7. package/dist/compat/workspaceSyncCompat.js +6 -0
  8. package/dist/components/features/AgentsModule.js +1 -1
  9. package/dist/components/features/AgentsModule.test.js +1 -1
  10. package/dist/components/features/DocumentIndex.d.ts +1 -1
  11. package/dist/components/features/DocumentIndex.js +1 -1
  12. package/dist/components/features/DocumentViewer.d.ts +1 -1
  13. package/dist/components/features/DocumentViewer.js +32 -9
  14. package/dist/components/features/DocumentWorkspace.d.ts +5 -22
  15. package/dist/components/features/DocumentWorkspace.js +12 -155
  16. package/dist/components/features/DocumentWorkspace.test.js +193 -6
  17. package/dist/components/features/TaskSettings.js +87 -41
  18. package/dist/components/features/TaskSettings.test.js +180 -40
  19. package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
  20. package/dist/components/features/documentWorkspaceModel.js +57 -0
  21. package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
  22. package/dist/components/features/useDocumentWorkspaceController.js +113 -0
  23. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  24. package/dist/components/task/TaskActionHeader.js +3 -3
  25. package/dist/components/task/TaskActionHeader.test.js +8 -0
  26. package/dist/components/task/TaskCard.js +16 -1
  27. package/dist/components/task/TaskCard.test.js +31 -0
  28. package/dist/components/task/TaskForm.d.ts +9 -8
  29. package/dist/components/task/TaskForm.js +374 -219
  30. package/dist/components/task/TaskForm.test.js +482 -361
  31. package/dist/components/task/TaskKanban.d.ts +1 -1
  32. package/dist/components/task/TaskKanban.js +33 -161
  33. package/dist/components/task/TaskStatusActions.d.ts +6 -1
  34. package/dist/components/task/TaskStatusActions.js +8 -3
  35. package/dist/components/task/TaskStatusActions.test.js +9 -0
  36. package/dist/components/task/taskKanbanDropRules.d.ts +58 -0
  37. package/dist/components/task/taskKanbanDropRules.js +187 -0
  38. package/dist/components/task/taskKanbanDropRules.test.d.ts +1 -0
  39. package/dist/components/task/taskKanbanDropRules.test.js +114 -0
  40. package/dist/components/ui/Modal.d.ts +1 -1
  41. package/dist/components/ui/Modal.js +1 -0
  42. package/dist/components/views/AppShellHeader.js +5 -1
  43. package/dist/components/views/AppShellHeader.test.js +4 -0
  44. package/dist/components/views/PlanComparisonPage.d.ts +3 -2
  45. package/dist/components/views/PlanComparisonPage.js +9 -10
  46. package/dist/components/views/PlanComparisonPage.test.js +55 -41
  47. package/dist/components/views/PlansPage.d.ts +5 -1
  48. package/dist/components/views/PlansPage.js +150 -81
  49. package/dist/components/views/PlansPage.test.js +367 -41
  50. package/dist/components/views/StandaloneLayout.js +135 -54
  51. package/dist/components/views/WidgetView.js +11 -2
  52. package/dist/components/views/panels/FilterToolbar.test.js +6 -4
  53. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +2 -14
  54. package/dist/components/views/standalone/modals/AccountHubModal.js +12 -14
  55. package/dist/components/views/standalone/modals/AccountHubModal.test.js +24 -1
  56. package/dist/components/views/standalone/modals/SyncStatusModal.js +1 -1
  57. package/dist/config/envSchema.js +1 -1
  58. package/dist/core/AiProfileService.d.ts +6 -1
  59. package/dist/core/AiProfileService.js +161 -16
  60. package/dist/core/AiProfileService.test.js +3 -1
  61. package/dist/core/AiProfiles.test.js +200 -0
  62. package/dist/core/AuthTokenService.test.d.ts +1 -0
  63. package/dist/core/AuthTokenService.test.js +78 -0
  64. package/dist/core/DeletedTaskLifecycleService.d.ts +2 -1
  65. package/dist/core/EntitlementsPolicy.test.js +75 -13
  66. package/dist/core/PlanEntitlementService.d.ts +9 -1
  67. package/dist/core/PlanEntitlementService.js +144 -19
  68. package/dist/core/PlanVersionPolicy.test.js +19 -26
  69. package/dist/core/SignupMonetizationSettings.test.js +75 -15
  70. package/dist/core/SystemAdmin.test.js +212 -56
  71. package/dist/core/TaskActivityService.d.ts +4 -1
  72. package/dist/core/TaskActivityService.js +45 -0
  73. package/dist/core/TaskAuditTimeline.test.js +52 -1
  74. package/dist/core/TaskTaxonomyValidation.test.js +53 -0
  75. package/dist/core/Taskforce.d.ts +18 -11
  76. package/dist/core/Taskforce.js +93 -12
  77. package/dist/core/WorkspacePlanMode.test.js +73 -8
  78. package/dist/core/shared.d.ts +2 -0
  79. package/dist/core/shared.js +11 -0
  80. package/dist/documentReviews/service.d.ts +1 -1
  81. package/dist/documentReviews/types.d.ts +1 -1
  82. package/dist/hooks/auth/useTaskforceAuthBootstrap.d.ts +48 -0
  83. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +219 -0
  84. package/dist/hooks/sync/auth.d.ts +37 -0
  85. package/dist/hooks/sync/auth.js +63 -0
  86. package/dist/hooks/sync/bootstrap.d.ts +34 -0
  87. package/dist/hooks/sync/bootstrap.js +52 -0
  88. package/dist/hooks/sync/orchestratorShared.d.ts +36 -0
  89. package/dist/hooks/sync/orchestratorShared.js +209 -0
  90. package/dist/hooks/sync/orchestratorShared.test.d.ts +1 -0
  91. package/dist/hooks/sync/orchestratorShared.test.js +49 -0
  92. package/dist/hooks/sync/realtime.d.ts +25 -0
  93. package/dist/hooks/sync/realtime.js +60 -0
  94. package/dist/hooks/sync/recovery.d.ts +69 -0
  95. package/dist/hooks/sync/recovery.js +118 -0
  96. package/dist/hooks/sync/transfers.d.ts +123 -0
  97. package/dist/hooks/sync/transfers.js +435 -0
  98. package/dist/hooks/sync/useDataVersionRefresh.d.ts +16 -0
  99. package/dist/hooks/sync/useDataVersionRefresh.js +73 -0
  100. package/dist/hooks/ui/useResourceExport.d.ts +3 -1
  101. package/dist/hooks/ui/useResourceExport.js +5 -2
  102. package/dist/hooks/ui/useWorkflowTemplates.js +11 -6
  103. package/dist/hooks/useRealtimeSync.js +2 -1
  104. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +8 -0
  105. package/dist/hooks/useSyncOrchestrator.context-assets.test.d.ts +1 -0
  106. package/dist/hooks/useSyncOrchestrator.context-assets.test.js +228 -0
  107. package/dist/hooks/useSyncOrchestrator.d.ts +12 -8
  108. package/dist/hooks/useSyncOrchestrator.js +388 -879
  109. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +641 -6
  110. package/dist/hooks/useTaskMutations.d.ts +2 -1
  111. package/dist/hooks/useTaskMutations.js +57 -7
  112. package/dist/hooks/useTaskMutations.test.js +176 -0
  113. package/dist/hooks/useTaskforce.d.ts +13 -4
  114. package/dist/hooks/useTaskforce.js +302 -817
  115. package/dist/hooks/useTaskforce.sync-behavior.test.js +78 -0
  116. package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
  117. package/dist/hooks/useWorkspaceSyncController.js +33 -11
  118. package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
  119. package/dist/hooks/workspace/useTaskforceApiRouting.test.js +17 -0
  120. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +166 -0
  121. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +434 -0
  122. package/dist/hooks/workspace/workspaceLocalState.d.ts +19 -0
  123. package/dist/hooks/workspace/workspaceLocalState.js +100 -0
  124. package/dist/hooks/workspace/workspaceLocalState.test.d.ts +1 -0
  125. package/dist/hooks/workspace/workspaceLocalState.test.js +59 -0
  126. package/dist/localization/locales/en-US.js +2 -2
  127. package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
  128. package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
  129. package/dist/mcp/canonicalAssetHelpers.d.ts +70 -0
  130. package/dist/mcp/canonicalAssetHelpers.js +259 -0
  131. package/dist/mcp/clientIntegrations.d.ts +12 -1
  132. package/dist/mcp/clientIntegrations.js +161 -6
  133. package/dist/mcp/clientIntegrations.test.js +76 -4
  134. package/dist/mcp/collaborationRegistrar.d.ts +2 -0
  135. package/dist/mcp/collaborationRegistrar.js +71 -0
  136. package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
  137. package/dist/mcp/documentAssetRegistrar.js +346 -0
  138. package/dist/mcp/documentHelpers.d.ts +100 -0
  139. package/dist/mcp/documentHelpers.js +161 -0
  140. package/dist/mcp/runtime.js +2455 -3925
  141. package/dist/mcp/runtime.test.js +240 -8
  142. package/dist/mcp/taskAttachmentHelpers.d.ts +41 -0
  143. package/dist/mcp/taskAttachmentHelpers.js +60 -0
  144. package/dist/mcp/taskAttachmentTypes.d.ts +37 -0
  145. package/dist/mcp/taskAttachmentTypes.js +1 -0
  146. package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
  147. package/dist/mcp/taskPlanningRegistrar.js +418 -0
  148. package/dist/mcp/toolCatalog.d.ts +35 -0
  149. package/dist/mcp/toolCatalog.js +3 -0
  150. package/dist/plugins/vite.js +1 -1
  151. package/dist/runtime/appGateDefinitions.d.ts +1 -1
  152. package/dist/runtime/appGateDefinitions.js +1 -1
  153. package/dist/server/index.d.ts +1 -0
  154. package/dist/server/index.js +46 -3
  155. package/dist/server/index.test.js +12 -1
  156. package/dist/server/routes/admin.d.ts +1 -5
  157. package/dist/server/routes/admin.js +151 -80
  158. package/dist/server/routes/annotatedAttachments.d.ts +1 -1
  159. package/dist/server/routes/annotatedAttachments.js +1 -1
  160. package/dist/server/routes/auth.d.ts +1 -4
  161. package/dist/server/routes/auth.js +59 -64
  162. package/dist/server/routes/authSupport.d.ts +30 -0
  163. package/dist/server/routes/authSupport.js +81 -0
  164. package/dist/server/routes/billing.d.ts +1 -1
  165. package/dist/server/routes/billing.js +122 -255
  166. package/dist/server/routes/billing.test.js +257 -86
  167. package/dist/server/routes/documentReviews.d.ts +1 -1
  168. package/dist/server/routes/documentReviews.js +1 -1
  169. package/dist/server/routes/documents.d.ts +4 -2
  170. package/dist/server/routes/documents.js +73 -7
  171. package/dist/server/routes/primitives.d.ts +11 -0
  172. package/dist/server/routes/primitives.js +73 -0
  173. package/dist/server/routes/resources.d.ts +1 -1
  174. package/dist/server/routes/resources.js +1 -1
  175. package/dist/server/routes/shared.d.ts +31 -1
  176. package/dist/server/routes/shared.js +26 -0
  177. package/dist/server/routes/sync.d.ts +1 -1
  178. package/dist/server/routes/sync.integration.test.js +20 -0
  179. package/dist/server/routes/sync.js +111 -238
  180. package/dist/server/routes/tasks.d.ts +1 -1
  181. package/dist/server/routes/tasks.js +50 -8
  182. package/dist/server/routes/workspaces.d.ts +1 -1
  183. package/dist/server/routes/workspaces.js +1 -1
  184. package/dist/server/routes.d.ts +2 -9
  185. package/dist/server/routes.js +84 -181
  186. package/dist/server/routes.test.js +912 -32
  187. package/dist/shared/taskActor.d.ts +10 -0
  188. package/dist/shared/taskActor.js +1 -0
  189. package/dist/sync/collaborationSyncPayload.js +4 -0
  190. package/dist/sync/collaborationSyncPayload.test.js +8 -0
  191. package/dist/sync/collaborationSyncState.d.ts +3 -1
  192. package/dist/sync/collaborationSyncState.js +19 -0
  193. package/dist/sync/contentSyncState.js +28 -17
  194. package/dist/sync/syncApplyHandlers.d.ts +87 -1
  195. package/dist/sync/syncApplyHandlers.js +370 -8
  196. package/dist/sync/syncApplyHandlers.test.d.ts +1 -0
  197. package/dist/sync/syncApplyHandlers.test.js +379 -0
  198. package/dist/sync/syncService.d.ts +9 -1
  199. package/dist/sync/syncService.js +44 -2
  200. package/dist/sync/syncService.test.js +62 -0
  201. package/dist/sync/workspacePullFeed.d.ts +1 -0
  202. package/dist/sync/workspacePullFeed.js +66 -59
  203. package/dist/sync/workspacePullFeed.test.js +72 -4
  204. package/dist/sync/workspaceSyncModel.d.ts +25 -1
  205. package/dist/sync/workspaceSyncModel.js +77 -3
  206. package/dist/sync/workspaceSyncModel.test.js +153 -0
  207. package/dist/sync/workspaceSyncState.d.ts +2 -0
  208. package/dist/sync/workspaceSyncState.js +1 -0
  209. package/dist/types.d.ts +2 -10
  210. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +1 -0
  211. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-C_TmXZwA.js → AnnotatedAttachmentWorkspace-BG6P_GVW.js} +1 -1
  212. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +1 -0
  213. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +252 -0
  214. package/dist/ui/assets/{InitiativesModule-4-Rh2K2n.js → InitiativesModule-Dhm7M8e7.js} +1 -1
  215. package/dist/ui/assets/{PlansPage-BlVC_lRq.css → PlansPage-C2dd2n1X.css} +1 -1
  216. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +1 -0
  217. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +9 -0
  218. package/dist/ui/assets/{WorkflowsModule-CGk9s3NJ.js → WorkflowsModule-BcS4afRn.js} +1 -1
  219. package/dist/ui/assets/index-C2-OXZV7.css +1 -0
  220. package/dist/ui/assets/index-DcSI5F86.js +6 -0
  221. package/dist/ui/assets/{vendor-icons-pWocEipT.js → vendor-icons-BSUaRwF8.js} +1 -1
  222. package/dist/ui/index.html +4 -4
  223. package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
  224. package/dist/utils/commercialLifecyclePresentation.js +196 -0
  225. package/dist/utils/taskActivity.js +4 -0
  226. package/dist/utils/taskActivity.test.js +25 -1
  227. package/package.json +10 -1
  228. package/scripts/check-cloud-mcp.mjs +83 -0
  229. package/scripts/playwright-auth.sh +9 -1
  230. package/scripts/run-billing-performance-smoke.sh +24 -0
  231. package/dist/ui/assets/AgentsModule-CpsTmrIW.js +0 -1
  232. package/dist/ui/assets/DocumentWorkspace-C3GyzrWm.js +0 -250
  233. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
  234. package/dist/ui/assets/PlansPage-BP7AYOqr.js +0 -1
  235. package/dist/ui/assets/TaskSettings-BOC5F6Ag.js +0 -8
  236. package/dist/ui/assets/index-CLIMgR6g.js +0 -6
  237. package/dist/ui/assets/index-DneETxcu.css +0 -1
@@ -0,0 +1,11 @@
1
+ import { IncomingMessage, ServerResponse } from 'http';
2
+ import type { TaskforceAuthConfig } from '../auth.js';
3
+ import type { ResolvedObjectStorageConfig } from '../../storage/objectStorage.js';
4
+ export type RouteHandler = (req: IncomingMessage, res: ServerResponse, params: Record<string, string>) => Promise<void>;
5
+ export interface RouteContext {
6
+ authConfig?: TaskforceAuthConfig;
7
+ objectStorage?: ResolvedObjectStorageConfig;
8
+ }
9
+ export declare function parseJsonBody(req: IncomingMessage, maxBytes?: number): Promise<any>;
10
+ export declare function parseFormBody(req: IncomingMessage, maxBytes?: number): Promise<Record<string, string>>;
11
+ export declare function escapeHtml(value: unknown): string;
@@ -0,0 +1,73 @@
1
+ const DEFAULT_MAX_JSON_BODY_BYTES = 1024 * 1024; // 1MB
2
+ function createHttpError(message, statusCode) {
3
+ const error = new Error(message);
4
+ error.statusCode = statusCode;
5
+ return error;
6
+ }
7
+ export async function parseJsonBody(req, maxBytes = DEFAULT_MAX_JSON_BODY_BYTES) {
8
+ const safeMaxBytes = Number.isFinite(maxBytes) && maxBytes > 0
9
+ ? Math.floor(maxBytes)
10
+ : DEFAULT_MAX_JSON_BODY_BYTES;
11
+ return new Promise((resolve, reject) => {
12
+ let body = '';
13
+ let receivedBytes = 0;
14
+ req.on('data', chunk => {
15
+ receivedBytes += chunk.length;
16
+ if (receivedBytes > safeMaxBytes) {
17
+ req.pause();
18
+ reject(createHttpError(`Payload too large (max ${safeMaxBytes} bytes)`, 413));
19
+ return;
20
+ }
21
+ body += chunk;
22
+ });
23
+ req.on('end', () => {
24
+ try {
25
+ resolve(body ? JSON.parse(body) : {});
26
+ }
27
+ catch {
28
+ reject(createHttpError('Invalid JSON', 400));
29
+ }
30
+ });
31
+ req.on('error', reject);
32
+ });
33
+ }
34
+ export async function parseFormBody(req, maxBytes = DEFAULT_MAX_JSON_BODY_BYTES) {
35
+ const safeMaxBytes = Number.isFinite(maxBytes) && maxBytes > 0
36
+ ? Math.floor(maxBytes)
37
+ : DEFAULT_MAX_JSON_BODY_BYTES;
38
+ return new Promise((resolve, reject) => {
39
+ let body = '';
40
+ let receivedBytes = 0;
41
+ req.on('data', chunk => {
42
+ receivedBytes += chunk.length;
43
+ if (receivedBytes > safeMaxBytes) {
44
+ req.pause();
45
+ reject(createHttpError(`Payload too large (max ${safeMaxBytes} bytes)`, 413));
46
+ return;
47
+ }
48
+ body += chunk;
49
+ });
50
+ req.on('end', () => {
51
+ try {
52
+ const params = new URLSearchParams(body);
53
+ const parsed = {};
54
+ params.forEach((value, key) => {
55
+ parsed[String(key)] = String(value);
56
+ });
57
+ resolve(parsed);
58
+ }
59
+ catch {
60
+ reject(createHttpError('Invalid form body', 400));
61
+ }
62
+ });
63
+ req.on('error', reject);
64
+ });
65
+ }
66
+ export function escapeHtml(value) {
67
+ return String(value || '')
68
+ .replace(/&/g, '&amp;')
69
+ .replace(/</g, '&lt;')
70
+ .replace(/>/g, '&gt;')
71
+ .replace(/"/g, '&quot;')
72
+ .replace(/'/g, '&#39;');
73
+ }
@@ -17,7 +17,7 @@
17
17
  * GET /api/taskforce/environments
18
18
  */
19
19
  import type { TaskforceCore } from '../../core/Taskforce.js';
20
- import { type RouteHandler } from '../routes.js';
20
+ import { type RouteHandler } from './primitives.js';
21
21
  export interface ResourceRouteDependencies {
22
22
  addRoute: (method: string, path: string, handler: RouteHandler) => void;
23
23
  core: TaskforceCore;
@@ -19,7 +19,7 @@
19
19
  import * as fs from 'fs';
20
20
  import * as path from 'path';
21
21
  import { execFileSync } from 'child_process';
22
- import { parseJsonBody } from '../routes.js';
22
+ import { parseJsonBody } from './primitives.js';
23
23
  const WORKFLOW_EDITOR_LOCKED_FIELDS = {
24
24
  do: ['aliasesText', 'dispatchDefault', 'criticalToolsText', 'contentDefault'],
25
25
  execute: ['aliasesText', 'dispatchDefault', 'criticalToolsText', 'contentDefault']
@@ -7,8 +7,38 @@
7
7
  */
8
8
  import { IncomingMessage, ServerResponse } from 'http';
9
9
  import { TaskforceCore } from '../../core/Taskforce.js';
10
- import type { RouteContext } from '../routes.js';
10
+ import type { McpAccessTokenAuthResult, McpOAuthAccessTokenAuthResult, McpAccessTokenScope } from '../../core/Taskforce.js';
11
+ import type { RouteContext } from './primitives.js';
12
+ import type { AiProfileBootstrapConfig } from '../../mcp/aiProfileBootstrap.js';
11
13
  export declare function resolveErrorStatusCode(error: unknown, fallback?: number): number;
14
+ export declare function buildCloudMcpRuntimeAuth(input: {
15
+ req: IncomingMessage;
16
+ auth: {
17
+ authenticatedViaToken: McpAccessTokenAuthResult | null;
18
+ authenticatedViaOAuth: McpOAuthAccessTokenAuthResult | null;
19
+ userId: string | null;
20
+ } & Required<AiProfileBootstrapConfig>;
21
+ requestHeader: (req: IncomingMessage, name: string, fallback?: string) => string;
22
+ requestId?: string | null;
23
+ authScopes?: McpAccessTokenScope[] | null;
24
+ }): {
25
+ scopes?: McpAccessTokenScope[] | null;
26
+ userId?: string | null;
27
+ tokenId?: string | null;
28
+ aiProfileToken?: AiProfileBootstrapConfig['aiProfileToken'];
29
+ aiProfileName?: AiProfileBootstrapConfig['aiProfileName'];
30
+ aiProfileIcon?: AiProfileBootstrapConfig['aiProfileIcon'];
31
+ aiProfileColor?: AiProfileBootstrapConfig['aiProfileColor'];
32
+ aiProfileDescription?: AiProfileBootstrapConfig['aiProfileDescription'];
33
+ aiProfileRole?: AiProfileBootstrapConfig['aiProfileRole'];
34
+ aiProfileProvider?: AiProfileBootstrapConfig['aiProfileProvider'];
35
+ aiProfileModel?: AiProfileBootstrapConfig['aiProfileModel'];
36
+ aiProfileSurfaceType?: AiProfileBootstrapConfig['aiProfileSurfaceType'];
37
+ actorType?: 'local' | 'user' | 'token' | 'oauth';
38
+ requestId?: string | null;
39
+ ip?: string | null;
40
+ userAgent?: string | null;
41
+ };
12
42
  export declare function requestHeader(req: IncomingMessage, name: string, fallback?: string): string;
13
43
  export declare function requestWorkspaceHeader(req: IncomingMessage): string;
14
44
  export declare function requestAuthoritativeWorkspaceId(req: IncomingMessage): string;
@@ -17,6 +17,32 @@ export function resolveErrorStatusCode(error, fallback = 400) {
17
17
  }
18
18
  return fallback;
19
19
  }
20
+ export function buildCloudMcpRuntimeAuth(input) {
21
+ const { req, auth, requestHeader, requestId, authScopes } = input;
22
+ const actorType = auth.authenticatedViaToken
23
+ ? 'token'
24
+ : auth.authenticatedViaOAuth
25
+ ? 'oauth'
26
+ : 'user';
27
+ return {
28
+ scopes: authScopes || auth.authenticatedViaToken?.scopes || auth.authenticatedViaOAuth?.scopes || [],
29
+ userId: auth.authenticatedViaToken?.userId || auth.authenticatedViaOAuth?.userId || auth.userId || null,
30
+ tokenId: auth.authenticatedViaToken?.tokenId || auth.authenticatedViaOAuth?.grantId || null,
31
+ aiProfileToken: auth.aiProfileToken,
32
+ aiProfileName: auth.aiProfileName,
33
+ aiProfileIcon: auth.aiProfileIcon,
34
+ aiProfileColor: auth.aiProfileColor,
35
+ aiProfileDescription: auth.aiProfileDescription,
36
+ aiProfileRole: auth.aiProfileRole,
37
+ aiProfileProvider: auth.aiProfileProvider,
38
+ aiProfileModel: auth.aiProfileModel,
39
+ aiProfileSurfaceType: auth.aiProfileSurfaceType,
40
+ actorType,
41
+ requestId: String(requestId || req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || undefined,
42
+ ip: req.socket?.remoteAddress || null,
43
+ userAgent: requestHeader(req, 'user-agent', '') || null,
44
+ };
45
+ }
20
46
  // === SECTION: Request header helpers ===
21
47
  export function requestHeader(req, name, fallback = '') {
22
48
  const value = req.headers?.[name.toLowerCase()];
@@ -1,6 +1,6 @@
1
1
  import { IncomingMessage } from 'http';
2
2
  import { TaskforceCore, TaskforceSyncCapable } from '../../core/Taskforce.js';
3
- import { RouteHandler, RouteContext } from '../routes.js';
3
+ import { type RouteContext, type RouteHandler } from './primitives.js';
4
4
  import { resolveRequestAccess, createSessionTokenCookie } from '../auth.js';
5
5
  import { isReservedWorkspaceId } from '../../utils/workspaceIdentity.js';
6
6
  export interface SyncRouteDependencies {
@@ -344,6 +344,10 @@ describe('Server Routes Workspace Sync Integration', () => {
344
344
  username: 'codex',
345
345
  icon: 'Bot',
346
346
  color: '#0ea5e9',
347
+ description: 'Terminal-first coding agent',
348
+ role: 'Implementer',
349
+ provider: 'OpenAI',
350
+ model: 'gpt-5.4',
347
351
  surfaceType: 'coding_tool',
348
352
  createdAt: '2026-03-22T10:00:00.000Z',
349
353
  updatedAt: '2026-03-22T10:05:00.000Z',
@@ -361,6 +365,10 @@ describe('Server Routes Workspace Sync Integration', () => {
361
365
  id: 'ai-profile-codex',
362
366
  name: 'Codex',
363
367
  username: 'codex',
368
+ description: 'Terminal-first coding agent',
369
+ role: 'Implementer',
370
+ provider: 'OpenAI',
371
+ model: 'gpt-5.4',
364
372
  surfaceType: 'coding_tool'
365
373
  })
366
374
  ]);
@@ -1757,6 +1765,18 @@ describe('Server Routes Workspace Sync Integration', () => {
1757
1765
  const pushRes = createMockRes();
1758
1766
  await pushMatch?.handler(pushReq, pushRes, {});
1759
1767
  expect(pushRes.writeHead).toHaveBeenCalledWith(200, expect.any(Object));
1768
+ const pushBody = readJsonBody(pushRes);
1769
+ expect(Array.isArray(pushBody?.appliedTaskUpserts)).toBe(true);
1770
+ expect(pushBody?.appliedTaskUpserts).toEqual(expect.arrayContaining([
1771
+ expect.objectContaining({
1772
+ archived: false,
1773
+ task: expect.objectContaining({
1774
+ id: taskId,
1775
+ title: 'Offline provisional task',
1776
+ referenceNumber: 1
1777
+ })
1778
+ })
1779
+ ]));
1760
1780
  const persisted = core.getTask(taskId, workspaceId);
1761
1781
  expect(persisted?.referenceNumber).toBe(1);
1762
1782
  expect(Date.parse(String(persisted?.updatedAt || ''))).toBeGreaterThan(Date.parse(staleUpdatedAt));