thinkwork-cli 0.13.2 → 1.0.0

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 (231) hide show
  1. package/README.md +3 -14
  2. package/dist/{api-client-JYZXYQJR.js → api-client-4P4JZOBX.js} +1 -1
  3. package/dist/{chunk-Z2F6RJFR.js → chunk-4OMDWYZQ.js} +4 -5
  4. package/dist/{chunk-ILZKG5WV.js → chunk-AD2NIWB5.js} +434 -69
  5. package/dist/chunk-MWQ7RO76.js +137 -0
  6. package/dist/{chunk-DVPBI5HM.js → chunk-OLUQ4U2Z.js} +26 -26
  7. package/dist/{chunk-QOERT44A.js → chunk-YQCYD6NE.js} +57 -44
  8. package/dist/cli.js +4400 -16431
  9. package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
  10. package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
  11. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
  12. package/dist/{dist-es-CRV46D5B.js → dist-es-2OTNTL4N.js} +4 -4
  13. package/dist/{dist-es-ENBUC3JP.js → dist-es-2XVAH4BQ.js} +2 -2
  14. package/dist/{dist-es-DCY4IC3Y.js → dist-es-3DPDUJAH.js} +2 -2
  15. package/dist/{dist-es-G7PTG75M.js → dist-es-BNZTBBVC.js} +1 -1
  16. package/dist/{dist-es-GKDBE7E6.js → dist-es-CD2RBDAC.js} +1 -1
  17. package/dist/{dist-es-R7FGL2IB.js → dist-es-I4FW57PS.js} +1 -1
  18. package/dist/{dist-es-USORBXZ5.js → dist-es-KVFWJNDY.js} +4 -4
  19. package/dist/{dist-es-HY3535OI.js → dist-es-PS73DWNL.js} +2 -2
  20. package/dist/{dist-es-LDE437AM.js → dist-es-S3NZQFGT.js} +1 -1
  21. package/dist/{dist-es-G54LBMRN.js → dist-es-SGCA4P32.js} +1 -1
  22. package/dist/{dist-es-Q57SZXZ7.js → dist-es-WBM6J4RA.js} +2 -2
  23. package/dist/{dist-es-P26FWFLT.js → dist-es-ZGVADYIF.js} +8 -8
  24. package/dist/drizzle/0227_analyst_reader_role.sql +17 -26
  25. package/dist/drizzle/0230_analyst_rls.sql +28 -45
  26. package/dist/drizzle/0261_native_auth_control_plane.sql +7 -3
  27. package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
  28. package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
  29. package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
  30. package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
  31. package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
  32. package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
  33. package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
  34. package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
  35. package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
  36. package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
  37. package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
  38. package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
  39. package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
  40. package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
  41. package/dist/drizzle/0284_user_brain_claims.sql +69 -0
  42. package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
  43. package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
  44. package/dist/drizzle/0287_brain_subject.sql +25 -0
  45. package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
  46. package/dist/{loadSso-DJVB7BXE.js → loadSso-ETCXTR4I.js} +2 -2
  47. package/dist/{loadSso-JAMNA3WY.js → loadSso-UBD7KUHE.js} +2 -2
  48. package/dist/plugins/README.md +2 -2
  49. package/dist/plugins/catalog/package.json +0 -3
  50. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -3
  51. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
  52. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -25
  53. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -6
  54. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -15
  55. package/dist/plugins/catalog/src/contracts.ts +15 -0
  56. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -18
  57. package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
  58. package/dist/plugins/twenty/package.json +2 -1
  59. package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
  60. package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
  61. package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
  62. package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
  63. package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
  64. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
  65. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
  66. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
  67. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
  68. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
  69. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
  70. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
  71. package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
  72. package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
  73. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
  74. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
  75. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
  76. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
  77. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
  78. package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
  79. package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
  80. package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
  81. package/dist/plugins/twenty/test/manifest.test.ts +2 -4
  82. package/dist/scripts/post-deploy.sh +79 -1
  83. package/dist/{signin-UGDWTGS4.js → signin-5QZNRSOO.js} +2 -2
  84. package/dist/{sso-oidc-Q4VXANXY.js → sso-oidc-XK673P54.js} +2 -2
  85. package/dist/{sts-CWLSE3GH.js → sts-OXI2UALF.js} +6 -134
  86. package/dist/{sts-DNZLNVOV.js → sts-SQW4NBK3.js} +6 -134
  87. package/dist/terraform/examples/greenfield/main.tf +233 -175
  88. package/dist/terraform/examples/greenfield/terraform.tfvars.example +12 -8
  89. package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
  90. package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
  91. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
  92. package/dist/terraform/modules/app/agentcore-identity/main.tf +106 -26
  93. package/dist/terraform/modules/app/agentcore-identity/outputs.tf +6 -6
  94. package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +216 -99
  95. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +6 -9
  96. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
  97. package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
  98. package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +22 -7
  99. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +17 -46
  100. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +65 -3
  101. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
  102. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
  103. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
  104. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
  105. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
  106. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
  107. package/dist/terraform/modules/app/agentcore-identity/variables.tf +6 -0
  108. package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
  109. package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
  110. package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
  111. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  112. package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
  113. package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
  114. package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
  115. package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
  116. package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
  117. package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
  118. package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
  119. package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
  120. package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
  121. package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
  122. package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
  123. package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
  124. package/dist/terraform/modules/app/deployment-control-plane/runner.py +2641 -124
  125. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2034 -154
  126. package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
  127. package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
  128. package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
  129. package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
  130. package/dist/terraform/modules/app/lambda-api/handlers.tf +411 -723
  131. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +262 -198
  132. package/dist/terraform/modules/app/lambda-api/main.tf +51 -13
  133. package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +4 -181
  134. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
  135. package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
  136. package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -45
  137. package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
  138. package/dist/terraform/modules/app/lambda-api/variables.tf +219 -126
  139. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
  140. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
  141. package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
  142. package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
  143. package/dist/terraform/modules/app/static-site/main.tf +1 -1
  144. package/dist/terraform/modules/app/www-dns/main.tf +9 -27
  145. package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
  146. package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
  147. package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
  148. package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
  149. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
  150. package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
  151. package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
  152. package/dist/terraform/modules/foundation/cognito/main.tf +81 -8
  153. package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
  154. package/dist/terraform/modules/foundation/cognito/variables.tf +24 -12
  155. package/dist/terraform/modules/thinkwork/README.md +5 -1
  156. package/dist/terraform/modules/thinkwork/main.tf +376 -374
  157. package/dist/terraform/modules/thinkwork/outputs.tf +12 -158
  158. package/dist/terraform/modules/thinkwork/variables.tf +246 -89
  159. package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
  160. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
  161. package/dist/workspace-defaults/files/ROUTER.md +1 -1
  162. package/dist/workspace-defaults/files/TOOLS.md +9 -39
  163. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
  164. package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
  165. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
  166. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
  167. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
  168. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
  169. package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
  170. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
  171. package/package.json +1 -1
  172. package/dist/drizzle/0261_managed_harness_multiplayer.sql +0 -313
  173. package/dist/drizzle/0262_parallel_harness_threads.sql +0 -9
  174. package/dist/drizzle/0264_harness_tool_execution_ledger.sql +0 -113
  175. package/dist/plugins/company-data/README.md +0 -49
  176. package/dist/plugins/company-data/package.json +0 -21
  177. package/dist/plugins/company-data/src/index.ts +0 -30
  178. package/dist/plugins/company-data/src/manifest.ts +0 -26
  179. package/dist/plugins/company-data/test/manifest.test.ts +0 -116
  180. package/dist/plugins/company-data/tsconfig.json +0 -8
  181. package/dist/plugins/company-etl/README.md +0 -46
  182. package/dist/plugins/company-etl/package.json +0 -21
  183. package/dist/plugins/company-etl/src/index.ts +0 -29
  184. package/dist/plugins/company-etl/src/manifest.ts +0 -26
  185. package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
  186. package/dist/plugins/company-etl/tsconfig.json +0 -8
  187. package/dist/plugins/lastmile/README.md +0 -50
  188. package/dist/plugins/lastmile/package.json +0 -23
  189. package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
  190. package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
  191. package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
  192. package/dist/plugins/lastmile/src/index.ts +0 -46
  193. package/dist/plugins/lastmile/src/manifest.ts +0 -139
  194. package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
  195. package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
  196. package/dist/plugins/lastmile/tsconfig.json +0 -8
  197. package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
  198. package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
  199. package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
  200. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
  201. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
  202. package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
  203. package/dist/terraform/modules/app/agentcore-gateway/main.tf +0 -305
  204. package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +0 -44
  205. package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +0 -93
  206. package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +0 -33
  207. package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +0 -543
  208. package/dist/terraform/modules/app/agentcore-gateway/variables.tf +0 -70
  209. package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -330
  210. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -72
  211. package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +0 -5
  212. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +0 -430
  213. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +0 -180
  214. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +0 -193
  215. package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +0 -5
  216. package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +0 -5
  217. package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +0 -5
  218. package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -96
  219. package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
  220. package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
  221. package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +0 -88
  222. package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +0 -91
  223. package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
  224. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
  225. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
  226. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
  227. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
  228. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
  229. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
  230. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
  231. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/variables.tf +0 -0
@@ -1,572 +0,0 @@
1
- export type LinkedTaskStatus =
2
- | "unknown"
3
- | "todo"
4
- | "in_progress"
5
- | "completed"
6
- | "blocked"
7
- | "cancelled"
8
- | "not_applicable";
9
-
10
- export type LinkedTaskSyncStatus = "pending" | "synced" | "warning" | "error";
11
-
12
- export type SpaceWritebackPolicy =
13
- | "disabled"
14
- | "status_only"
15
- | "status_and_comments";
16
-
17
- export type ExternalTaskWritebackAction =
18
- | "status_summary"
19
- | "human_comment"
20
- | "agent_comment";
21
-
22
- export interface SpaceWritebackPolicyConfig {
23
- allowAgentComments?: boolean;
24
- agentCommentMode?: "disabled" | "requires_confirmation" | "allowed";
25
- }
26
-
27
- export interface EvaluateExternalTaskWritebackInput {
28
- policy?: SpaceWritebackPolicy | string | null;
29
- action: ExternalTaskWritebackAction;
30
- humanConfirmed?: boolean;
31
- config?: SpaceWritebackPolicyConfig | null;
32
- }
33
-
34
- export interface ExternalTaskWritebackDecision {
35
- allowed: boolean;
36
- policy: SpaceWritebackPolicy;
37
- reason:
38
- | "allowed"
39
- | "writeback_disabled"
40
- | "comments_disabled"
41
- | "agent_comment_confirmation_required"
42
- | "agent_comments_disabled";
43
- requiresHumanConfirmation: boolean;
44
- }
45
-
46
- export interface LastMileMcpToolCall {
47
- serverName: string;
48
- toolName: string;
49
- arguments: Record<string, unknown>;
50
- }
51
-
52
- export interface LastMileMcpToolResponse {
53
- content?: unknown;
54
- structuredContent?: unknown;
55
- isError?: boolean;
56
- }
57
-
58
- export interface LastMileMcpClient {
59
- callTool(call: LastMileMcpToolCall): Promise<LastMileMcpToolResponse>;
60
- }
61
-
62
- export interface LastMileTasksAdapterOptions {
63
- client: LastMileMcpClient;
64
- serverName?: string;
65
- toolNames?: Partial<LastMileTaskToolNames>;
66
- }
67
-
68
- export interface LastMileTaskToolNames {
69
- createTask: string;
70
- readTask: string;
71
- postComment: string;
72
- }
73
-
74
- export interface LastMileTaskAssigneeInput {
75
- roleKey?: string | null;
76
- externalId?: string | null;
77
- displayName?: string | null;
78
- }
79
-
80
- export interface CreateLastMileTaskInput {
81
- tenantId: string;
82
- spaceId: string;
83
- threadId: string;
84
- checklistItemId?: string | null;
85
- idempotencyKey: string;
86
- title: string;
87
- description?: string | null;
88
- required?: boolean;
89
- assignee?: LastMileTaskAssigneeInput | null;
90
- dueAt?: string | null;
91
- metadata?: Record<string, unknown> | null;
92
- }
93
-
94
- export interface ReadLastMileTaskInput {
95
- externalTaskId: string;
96
- }
97
-
98
- export interface PostLastMileTaskCommentInput {
99
- externalTaskId: string;
100
- body: string;
101
- writeback: EvaluateExternalTaskWritebackInput;
102
- metadata?: Record<string, unknown> | null;
103
- }
104
-
105
- export interface LastMileTaskSnapshot {
106
- externalTaskId: string;
107
- externalTaskUrl: string | null;
108
- title: string | null;
109
- status: LinkedTaskStatus;
110
- blocked: boolean;
111
- syncStatus: LinkedTaskSyncStatus;
112
- assignee: {
113
- externalId: string | null;
114
- displayName: string | null;
115
- } | null;
116
- dueAt: string | null;
117
- idempotent: boolean;
118
- needsTriage: boolean;
119
- raw: unknown;
120
- }
121
-
122
- export interface LastMileCommentResult {
123
- externalTaskId: string;
124
- commentId: string | null;
125
- postedAt: string | null;
126
- raw: unknown;
127
- }
128
-
129
- export interface LastMileProviderError {
130
- code: string;
131
- message: string;
132
- retryable: boolean;
133
- status?: number;
134
- detail?: unknown;
135
- }
136
-
137
- export type LastMileAdapterResult<T> =
138
- | { ok: true; value: T }
139
- | { ok: false; providerError: LastMileProviderError };
140
-
141
- export type LastMileCommentAdapterResult =
142
- | LastMileAdapterResult<LastMileCommentResult>
143
- | {
144
- ok: false;
145
- blockedByPolicy: ReturnType<typeof evaluateExternalTaskWriteback>;
146
- };
147
-
148
- const DEFAULT_TOOL_NAMES: LastMileTaskToolNames = {
149
- createTask: "create_task",
150
- readTask: "read_task",
151
- postComment: "post_comment",
152
- };
153
-
154
- export function createLastMileTasksAdapter(
155
- options: LastMileTasksAdapterOptions,
156
- ) {
157
- const serverName = options.serverName ?? "lastmile-tasks";
158
- const toolNames = { ...DEFAULT_TOOL_NAMES, ...options.toolNames };
159
-
160
- return {
161
- async createTask(
162
- input: CreateLastMileTaskInput,
163
- ): Promise<LastMileAdapterResult<LastMileTaskSnapshot>> {
164
- const response = await callProvider(options.client, {
165
- serverName,
166
- toolName: toolNames.createTask,
167
- arguments: {
168
- tenantId: input.tenantId,
169
- spaceId: input.spaceId,
170
- threadId: input.threadId,
171
- checklistItemId: input.checklistItemId ?? null,
172
- idempotencyKey: input.idempotencyKey,
173
- title: input.title,
174
- description: input.description ?? null,
175
- required: input.required ?? true,
176
- assignee: normalizeAssigneeInput(input.assignee),
177
- dueAt: input.dueAt ?? null,
178
- metadata: input.metadata ?? {},
179
- },
180
- });
181
- if (!response.ok) return response;
182
-
183
- return toTaskSnapshotResult(response.value, {
184
- fallback: {
185
- title: input.title,
186
- needsTriage:
187
- !input.assignee?.externalId && Boolean(input.assignee?.roleKey),
188
- },
189
- });
190
- },
191
-
192
- async readTask(
193
- input: ReadLastMileTaskInput,
194
- ): Promise<LastMileAdapterResult<LastMileTaskSnapshot>> {
195
- const response = await callProvider(options.client, {
196
- serverName,
197
- toolName: toolNames.readTask,
198
- arguments: { externalTaskId: input.externalTaskId },
199
- });
200
- if (!response.ok) return response;
201
- return toTaskSnapshotResult(response.value, { fallback: {} });
202
- },
203
-
204
- async postComment(
205
- input: PostLastMileTaskCommentInput,
206
- ): Promise<LastMileCommentAdapterResult> {
207
- const decision = evaluateExternalTaskWriteback(input.writeback);
208
- if (!decision.allowed) {
209
- return { ok: false, blockedByPolicy: decision };
210
- }
211
-
212
- const response = await callProvider(options.client, {
213
- serverName,
214
- toolName: toolNames.postComment,
215
- arguments: {
216
- externalTaskId: input.externalTaskId,
217
- body: input.body,
218
- metadata: input.metadata ?? {},
219
- },
220
- });
221
- if (!response.ok) return response;
222
-
223
- const record = objectRecord(response.value);
224
- return {
225
- ok: true,
226
- value: {
227
- externalTaskId: input.externalTaskId,
228
- commentId: stringValue(record.commentId) ?? stringValue(record.id),
229
- postedAt:
230
- stringValue(record.postedAt) ?? stringValue(record.createdAt),
231
- raw: response.value,
232
- },
233
- };
234
- },
235
- };
236
- }
237
-
238
- async function callProvider(
239
- client: LastMileMcpClient,
240
- call: LastMileMcpToolCall,
241
- ): Promise<LastMileAdapterResult<unknown>> {
242
- try {
243
- const response = await client.callTool(call);
244
- if (response.isError) {
245
- return {
246
- ok: false,
247
- providerError: toProviderError(
248
- extractPayload(response),
249
- "MCP_TOOL_ERROR",
250
- ),
251
- };
252
- }
253
- return { ok: true, value: extractPayload(response) };
254
- } catch (error) {
255
- return {
256
- ok: false,
257
- providerError: toProviderError(error, "MCP_CALL_FAILED"),
258
- };
259
- }
260
- }
261
-
262
- function toTaskSnapshotResult(
263
- value: unknown,
264
- options: { fallback: { title?: string; needsTriage?: boolean } },
265
- ): LastMileAdapterResult<LastMileTaskSnapshot> {
266
- const snapshot = toTaskSnapshot(value, options.fallback);
267
- if (!snapshot.externalTaskId) {
268
- return {
269
- ok: false,
270
- providerError: {
271
- code: "PROVIDER_RESPONSE_MISSING_TASK_ID",
272
- message: "LastMile task provider response did not include a task id",
273
- retryable: false,
274
- detail: redactSecrets(value),
275
- },
276
- };
277
- }
278
- return { ok: true, value: snapshot };
279
- }
280
-
281
- function toTaskSnapshot(
282
- value: unknown,
283
- fallback: { title?: string; needsTriage?: boolean },
284
- ): LastMileTaskSnapshot {
285
- const record = objectRecord(value);
286
- const assignee = normalizeAssigneeOutput(record.assignee);
287
- const normalizedStatus = normalizeExternalTaskStatus(
288
- record.status ?? record.state ?? record.taskStatus,
289
- );
290
- const blocked =
291
- typeof record.blocked === "boolean"
292
- ? record.blocked
293
- : normalizedStatus.blocked;
294
- return {
295
- externalTaskId:
296
- stringValue(record.externalTaskId) ??
297
- stringValue(record.taskId) ??
298
- stringValue(record.id) ??
299
- "",
300
- externalTaskUrl:
301
- stringValue(record.externalTaskUrl) ??
302
- stringValue(record.url) ??
303
- stringValue(record.webUrl),
304
- title: stringValue(record.title) ?? fallback.title ?? null,
305
- status: normalizedStatus.status,
306
- blocked,
307
- syncStatus: normalizedStatus.syncStatus,
308
- assignee,
309
- dueAt: stringValue(record.dueAt) ?? stringValue(record.dueDate),
310
- idempotent: Boolean(
311
- record.idempotent ??
312
- record.duplicate ??
313
- record.existing ??
314
- record.alreadyExists,
315
- ),
316
- needsTriage: Boolean(
317
- fallback.needsTriage || record.needsTriage || !assignee,
318
- ),
319
- raw: value,
320
- };
321
- }
322
-
323
- function normalizeAssigneeInput(
324
- input: LastMileTaskAssigneeInput | null | undefined,
325
- ) {
326
- if (!input) return null;
327
- return {
328
- roleKey: input.roleKey ?? null,
329
- externalId: input.externalId ?? null,
330
- displayName: input.displayName ?? null,
331
- };
332
- }
333
-
334
- function normalizeAssigneeOutput(value: unknown) {
335
- const record = objectRecord(value);
336
- const externalId =
337
- stringValue(record.externalId) ??
338
- stringValue(record.id) ??
339
- stringValue(record.userId);
340
- const displayName =
341
- stringValue(record.displayName) ??
342
- stringValue(record.name) ??
343
- stringValue(record.email);
344
- if (!externalId && !displayName) return null;
345
- return { externalId, displayName };
346
- }
347
-
348
- function extractPayload(response: LastMileMcpToolResponse): unknown {
349
- if (response.structuredContent !== undefined) {
350
- const structured = objectRecord(response.structuredContent);
351
- return structured.task ?? structured.result ?? structured;
352
- }
353
- if (Array.isArray(response.content)) {
354
- const text = response.content
355
- .map((item) => stringValue(objectRecord(item).text) ?? "")
356
- .join("\n")
357
- .trim();
358
- if (!text) return {};
359
- try {
360
- return JSON.parse(text);
361
- } catch {
362
- return { message: text };
363
- }
364
- }
365
- return response.content ?? {};
366
- }
367
-
368
- function toProviderError(
369
- value: unknown,
370
- fallbackCode: string,
371
- ): LastMileProviderError {
372
- const record = objectRecord(value);
373
- const status = numberValue(record.status) ?? numberValue(record.statusCode);
374
- const code =
375
- stringValue(record.code) ??
376
- stringValue(record.errorCode) ??
377
- (status === 403 ? "PERMISSION_DENIED" : fallbackCode);
378
- return {
379
- code,
380
- message:
381
- stringValue(record.message) ??
382
- stringValue(record.error) ??
383
- (value instanceof Error
384
- ? value.message
385
- : "LastMile task provider failed"),
386
- retryable:
387
- typeof record.retryable === "boolean"
388
- ? record.retryable
389
- : status === undefined || status >= 500,
390
- ...(status !== undefined ? { status } : {}),
391
- detail: redactSecrets(value),
392
- };
393
- }
394
-
395
- function normalizeExternalTaskStatus(value: unknown): {
396
- status: LinkedTaskStatus;
397
- blocked: boolean;
398
- syncStatus: LinkedTaskSyncStatus;
399
- } {
400
- const normalized = normalizeStatusToken(value);
401
- if (!normalized) {
402
- return { status: "unknown", blocked: false, syncStatus: "warning" };
403
- }
404
-
405
- if (
406
- normalized === "completed" ||
407
- normalized === "complete" ||
408
- normalized === "done" ||
409
- normalized === "closed"
410
- ) {
411
- return { status: "completed", blocked: false, syncStatus: "synced" };
412
- }
413
-
414
- if (
415
- normalized === "blocked" ||
416
- normalized === "on_hold" ||
417
- normalized === "waiting" ||
418
- normalized === "stalled"
419
- ) {
420
- return { status: "blocked", blocked: true, syncStatus: "synced" };
421
- }
422
-
423
- if (
424
- normalized === "in_progress" ||
425
- normalized === "started" ||
426
- normalized === "working" ||
427
- normalized === "active"
428
- ) {
429
- return { status: "in_progress", blocked: false, syncStatus: "synced" };
430
- }
431
-
432
- if (
433
- normalized === "todo" ||
434
- normalized === "to_do" ||
435
- normalized === "open" ||
436
- normalized === "new" ||
437
- normalized === "not_started"
438
- ) {
439
- return { status: "todo", blocked: false, syncStatus: "synced" };
440
- }
441
-
442
- if (
443
- normalized === "cancelled" ||
444
- normalized === "canceled" ||
445
- normalized === "void"
446
- ) {
447
- return { status: "cancelled", blocked: false, syncStatus: "synced" };
448
- }
449
-
450
- if (
451
- normalized === "not_applicable" ||
452
- normalized === "not_applicable_not_needed" ||
453
- normalized === "n_a" ||
454
- normalized === "na"
455
- ) {
456
- return { status: "not_applicable", blocked: false, syncStatus: "synced" };
457
- }
458
-
459
- return { status: "unknown", blocked: false, syncStatus: "warning" };
460
- }
461
-
462
- function evaluateExternalTaskWriteback(
463
- input: EvaluateExternalTaskWritebackInput,
464
- ): ExternalTaskWritebackDecision {
465
- const policy = normalizeSpaceWritebackPolicy(input.policy);
466
- if (policy === "disabled") {
467
- return deny(policy, "writeback_disabled", false);
468
- }
469
-
470
- if (input.action === "status_summary") {
471
- return allow(policy);
472
- }
473
-
474
- if (policy === "status_only") {
475
- return deny(policy, "comments_disabled", false);
476
- }
477
-
478
- if (input.action === "human_comment") {
479
- return allow(policy);
480
- }
481
-
482
- const agentCommentMode =
483
- input.config?.agentCommentMode ??
484
- (input.config?.allowAgentComments ? "allowed" : "requires_confirmation");
485
- if (agentCommentMode === "disabled") {
486
- return deny(policy, "agent_comments_disabled", false);
487
- }
488
- if (agentCommentMode === "allowed" || input.humanConfirmed === true) {
489
- return allow(policy);
490
- }
491
- return deny(policy, "agent_comment_confirmation_required", true);
492
- }
493
-
494
- function normalizeSpaceWritebackPolicy(
495
- value: SpaceWritebackPolicy | string | null | undefined,
496
- ): SpaceWritebackPolicy {
497
- if (typeof value !== "string") return "disabled";
498
- const normalized = value.trim().toLowerCase();
499
- if (
500
- normalized === "disabled" ||
501
- normalized === "status_only" ||
502
- normalized === "status_and_comments"
503
- ) {
504
- return normalized;
505
- }
506
- return "disabled";
507
- }
508
-
509
- function allow(policy: SpaceWritebackPolicy): ExternalTaskWritebackDecision {
510
- return {
511
- allowed: true,
512
- policy,
513
- reason: "allowed",
514
- requiresHumanConfirmation: false,
515
- };
516
- }
517
-
518
- function deny(
519
- policy: SpaceWritebackPolicy,
520
- reason: ExternalTaskWritebackDecision["reason"],
521
- requiresHumanConfirmation: boolean,
522
- ): ExternalTaskWritebackDecision {
523
- return {
524
- allowed: false,
525
- policy,
526
- reason,
527
- requiresHumanConfirmation,
528
- };
529
- }
530
-
531
- function normalizeStatusToken(value: unknown): string | null {
532
- if (value === undefined || value === null) return null;
533
- const normalized = String(value)
534
- .trim()
535
- .toLowerCase()
536
- .replace(/[\s/-]+/g, "_");
537
- return normalized.length > 0 ? normalized : null;
538
- }
539
-
540
- function redactSecrets(value: unknown): unknown {
541
- if (Array.isArray(value)) return value.map((item) => redactSecrets(item));
542
- if (!value || typeof value !== "object") {
543
- return value instanceof Error
544
- ? { name: value.name, message: value.message }
545
- : value;
546
- }
547
- const output: Record<string, unknown> = {};
548
- for (const [key, child] of Object.entries(value as Record<string, unknown>)) {
549
- if (/token|secret|password|authorization|api[-_]?key/i.test(key)) {
550
- output[key] = "[redacted]";
551
- } else {
552
- output[key] = redactSecrets(child);
553
- }
554
- }
555
- return output;
556
- }
557
-
558
- function objectRecord(value: unknown): Record<string, unknown> {
559
- return value && typeof value === "object"
560
- ? (value as Record<string, unknown>)
561
- : {};
562
- }
563
-
564
- function stringValue(value: unknown): string | null {
565
- return typeof value === "string" && value.trim() ? value : null;
566
- }
567
-
568
- function numberValue(value: unknown): number | undefined {
569
- return typeof value === "number" && Number.isFinite(value)
570
- ? value
571
- : undefined;
572
- }
@@ -1,64 +0,0 @@
1
- /**
2
- * Recorded LastMile OAuth discovery metadata (plan 2026-06-12-001 U9).
3
- *
4
- * Captured 2026-06-12 from the live RFC 9728 protected-resource metadata
5
- * endpoints:
6
- *
7
- * https://dev-mcp.lastmile-tei.com/.well-known/oauth-protected-resource/{crm,tasks,routing}
8
- *
9
- * `lastmile-discovery.test.ts` asserts the manifest against this fixture,
10
- * and `plugins/lastmile/smoke/lastmile-plugin-smoke.mjs` re-fetches the live
11
- * endpoints to catch drift between LastMile's deployment and this
12
- * recording. If LastMile changes its auth server, resources, or scope
13
- * vocabulary, update this fixture AND the manifest together.
14
- *
15
- * NOTE: these are LastMile's DEVELOP-stage endpoints (prod is
16
- * mcp.lastmile-tei.com). Per-stage endpoint parameterization is a known
17
- * v1 gap — see the manifest header.
18
- */
19
-
20
- export interface RecordedProtectedResourceMetadata {
21
- resource: string;
22
- authorization_servers: string[];
23
- bearer_methods_supported: string[];
24
- scopes_supported: string[];
25
- resource_documentation: string;
26
- }
27
-
28
- export const LASTMILE_DISCOVERY_CAPTURED_AT = "2026-06-12";
29
-
30
- export const lastmileDiscoveryFixture: Record<
31
- "crm" | "tasks" | "routing",
32
- RecordedProtectedResourceMetadata
33
- > = {
34
- crm: {
35
- resource: "https://dev-mcp.lastmile-tei.com/crm",
36
- authorization_servers: [
37
- "https://straightforward-dragon-14-staging.authkit.app",
38
- ],
39
- bearer_methods_supported: ["header"],
40
- scopes_supported: ["openid", "email", "profile", "offline_access"],
41
- resource_documentation:
42
- "https://github.com/homecareintel/web-apps/blob/main/docs/MCP.md",
43
- },
44
- tasks: {
45
- resource: "https://dev-mcp.lastmile-tei.com/tasks",
46
- authorization_servers: [
47
- "https://straightforward-dragon-14-staging.authkit.app",
48
- ],
49
- bearer_methods_supported: ["header"],
50
- scopes_supported: ["openid", "email", "profile", "offline_access"],
51
- resource_documentation:
52
- "https://github.com/homecareintel/web-apps/blob/main/docs/MCP.md",
53
- },
54
- routing: {
55
- resource: "https://dev-mcp.lastmile-tei.com/routing",
56
- authorization_servers: [
57
- "https://straightforward-dragon-14-staging.authkit.app",
58
- ],
59
- bearer_methods_supported: ["header"],
60
- scopes_supported: ["openid", "email", "profile", "offline_access"],
61
- resource_documentation:
62
- "https://github.com/homecareintel/web-apps/blob/main/docs/MCP.md",
63
- },
64
- };
@@ -1,46 +0,0 @@
1
- import { lastmileManifest } from "./manifest";
2
-
3
- export const lastmilePluginPackage = {
4
- packageKey: "lastmile",
5
- sourceRoot: "plugins/lastmile",
6
- manifest: lastmileManifest,
7
- ownedSources: [
8
- {
9
- kind: "manifest",
10
- path: "plugins/lastmile/src/manifest.ts",
11
- description: "LastMile catalog manifest and MCP component contract.",
12
- },
13
- {
14
- kind: "api",
15
- path: "plugins/lastmile/src/api/tasks-adapter.ts",
16
- description:
17
- "LastMile task adapter that normalizes MCP task provider calls.",
18
- },
19
- {
20
- kind: "api",
21
- path: "plugins/lastmile/src/discovery.fixture.ts",
22
- description:
23
- "Recorded protected-resource discovery metadata used by package drift tests.",
24
- },
25
- {
26
- kind: "smoke",
27
- path: "plugins/lastmile/smoke",
28
- description: "LastMile live plugin smoke validation script.",
29
- },
30
- {
31
- kind: "tests",
32
- path: "plugins/lastmile/test",
33
- description: "LastMile package-local discovery and manifest drift tests.",
34
- },
35
- {
36
- kind: "docs",
37
- path: "plugins/lastmile/README.md",
38
- description: "LastMile package ownership and verification notes.",
39
- },
40
- ],
41
- compatibilityLinks: [],
42
- } as const;
43
-
44
- export { lastmileManifest };
45
- export { lastmileDiscoveryFixture } from "./discovery.fixture";
46
- export * from "./api/tasks-adapter";