@shipfox/api-workflows 4.0.0 → 6.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 (277) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +104 -0
  3. package/dist/core/agent-defaults.d.ts +17 -0
  4. package/dist/core/agent-defaults.d.ts.map +1 -0
  5. package/dist/core/agent-defaults.js +21 -0
  6. package/dist/core/agent-defaults.js.map +1 -0
  7. package/dist/core/agent-tool-capability-warning.d.ts +4 -0
  8. package/dist/core/agent-tool-capability-warning.d.ts.map +1 -1
  9. package/dist/core/agent-tool-capability-warning.js +15 -17
  10. package/dist/core/agent-tool-capability-warning.js.map +1 -1
  11. package/dist/core/agent-tools.d.ts +11 -9
  12. package/dist/core/agent-tools.d.ts.map +1 -1
  13. package/dist/core/agent-tools.js +23 -18
  14. package/dist/core/agent-tools.js.map +1 -1
  15. package/dist/core/checkout.d.ts +21 -7
  16. package/dist/core/checkout.d.ts.map +1 -1
  17. package/dist/core/checkout.js +23 -11
  18. package/dist/core/checkout.js.map +1 -1
  19. package/dist/core/entities/workflow-run-attempt.d.ts +1 -1
  20. package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -1
  21. package/dist/core/entities/workflow-run-attempt.js.map +1 -1
  22. package/dist/core/job-execution.d.ts +3 -1
  23. package/dist/core/job-execution.d.ts.map +1 -1
  24. package/dist/core/job-execution.js +14 -12
  25. package/dist/core/job-execution.js.map +1 -1
  26. package/dist/core/job-transition/derive-job-execution-outputs.d.ts +1 -1
  27. package/dist/core/job-transition/derive-job-execution-outputs.d.ts.map +1 -1
  28. package/dist/core/job-transition/derive-job-execution-outputs.js.map +1 -1
  29. package/dist/core/job-transition/derive-job-success.js +1 -1
  30. package/dist/core/job-transition/derive-job-success.js.map +1 -1
  31. package/dist/core/listener-execution-materialization.d.ts +3 -3
  32. package/dist/core/listener-execution-materialization.d.ts.map +1 -1
  33. package/dist/core/listener-execution-materialization.js +3 -4
  34. package/dist/core/listener-execution-materialization.js.map +1 -1
  35. package/dist/core/run-workflow.d.ts +12 -1
  36. package/dist/core/run-workflow.d.ts.map +1 -1
  37. package/dist/core/run-workflow.js +13 -8
  38. package/dist/core/run-workflow.js.map +1 -1
  39. package/dist/core/step-config/agent.d.ts +8 -8
  40. package/dist/core/step-config/agent.d.ts.map +1 -1
  41. package/dist/core/step-config/agent.js +12 -10
  42. package/dist/core/step-config/agent.js.map +1 -1
  43. package/dist/core/step-config/complete-step-dispatch-config.d.ts +4 -4
  44. package/dist/core/step-config/complete-step-dispatch-config.d.ts.map +1 -1
  45. package/dist/core/step-config/complete-step-dispatch-config.js +2 -2
  46. package/dist/core/step-config/complete-step-dispatch-config.js.map +1 -1
  47. package/dist/core/step-config/materialize-job-execution-steps.d.ts +3 -3
  48. package/dist/core/step-config/materialize-job-execution-steps.d.ts.map +1 -1
  49. package/dist/core/step-config/materialize-job-execution-steps.js +5 -6
  50. package/dist/core/step-config/materialize-job-execution-steps.js.map +1 -1
  51. package/dist/core/step-config/materialize-workflow-model.d.ts +3 -3
  52. package/dist/core/step-config/materialize-workflow-model.d.ts.map +1 -1
  53. package/dist/core/step-config/materialize-workflow-model.js +4 -4
  54. package/dist/core/step-config/materialize-workflow-model.js.map +1 -1
  55. package/dist/core/step-config/resolve-job-execution-name.d.ts +1 -1
  56. package/dist/core/step-config/resolve-job-execution-name.d.ts.map +1 -1
  57. package/dist/core/step-config/resolve-job-execution-name.js.map +1 -1
  58. package/dist/core/step-config/resolve-step-config.d.ts +4 -4
  59. package/dist/core/step-config/resolve-step-config.d.ts.map +1 -1
  60. package/dist/core/step-config/resolve-step-config.js +6 -6
  61. package/dist/core/step-config/resolve-step-config.js.map +1 -1
  62. package/dist/core/step-config/run.d.ts +1 -1
  63. package/dist/core/step-config/run.d.ts.map +1 -1
  64. package/dist/core/step-config/run.js.map +1 -1
  65. package/dist/core/workflow-run-creation.d.ts +3 -3
  66. package/dist/core/workflow-run-creation.d.ts.map +1 -1
  67. package/dist/core/workflow-run-creation.js +3 -4
  68. package/dist/core/workflow-run-creation.js.map +1 -1
  69. package/dist/db/db.d.ts +16 -4
  70. package/dist/db/db.d.ts.map +1 -1
  71. package/dist/db/job-listeners.d.ts +7 -1
  72. package/dist/db/job-listeners.d.ts.map +1 -1
  73. package/dist/db/job-listeners.js +10 -5
  74. package/dist/db/job-listeners.js.map +1 -1
  75. package/dist/db/runner-lease-table.d.ts +5 -5
  76. package/dist/db/runner-lease-table.d.ts.map +1 -1
  77. package/dist/db/runner-lease-table.js +3 -2
  78. package/dist/db/runner-lease-table.js.map +1 -1
  79. package/dist/db/schema/workflow-run-attempts.d.ts +9 -3
  80. package/dist/db/schema/workflow-run-attempts.d.ts.map +1 -1
  81. package/dist/db/schema/workflow-run-attempts.js +2 -1
  82. package/dist/db/schema/workflow-run-attempts.js.map +1 -1
  83. package/dist/db/schema/workflow-runs.js +1 -1
  84. package/dist/db/schema/workflow-runs.js.map +1 -1
  85. package/dist/db/workflow-runs/job-executions.d.ts +5 -0
  86. package/dist/db/workflow-runs/job-executions.d.ts.map +1 -1
  87. package/dist/db/workflow-runs/job-executions.js +14 -7
  88. package/dist/db/workflow-runs/job-executions.js.map +1 -1
  89. package/dist/db/workflow-runs/jobs.d.ts.map +1 -1
  90. package/dist/db/workflow-runs/jobs.js +3 -1
  91. package/dist/db/workflow-runs/jobs.js.map +1 -1
  92. package/dist/db/workflow-runs/run-create.d.ts +9 -2
  93. package/dist/db/workflow-runs/run-create.d.ts.map +1 -1
  94. package/dist/db/workflow-runs/run-create.js +12 -9
  95. package/dist/db/workflow-runs/run-create.js.map +1 -1
  96. package/dist/db/workflow-runs/run-rerun.d.ts.map +1 -1
  97. package/dist/db/workflow-runs/run-rerun.js +3 -1
  98. package/dist/db/workflow-runs/run-rerun.js.map +1 -1
  99. package/dist/index.d.ts +18 -4
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +61 -37
  102. package/dist/index.js.map +1 -1
  103. package/dist/presentation/dto/checkout-token.d.ts +14 -1
  104. package/dist/presentation/dto/checkout-token.d.ts.map +1 -1
  105. package/dist/presentation/dto/checkout-token.js.map +1 -1
  106. package/dist/presentation/index.d.ts +1 -1
  107. package/dist/presentation/index.d.ts.map +1 -1
  108. package/dist/presentation/index.js +1 -1
  109. package/dist/presentation/index.js.map +1 -1
  110. package/dist/presentation/inter-module.d.ts +18 -0
  111. package/dist/presentation/inter-module.d.ts.map +1 -0
  112. package/dist/presentation/inter-module.js +113 -0
  113. package/dist/presentation/inter-module.js.map +1 -0
  114. package/dist/presentation/routes/agent-runtime-config.d.ts +6 -1
  115. package/dist/presentation/routes/agent-runtime-config.d.ts.map +1 -1
  116. package/dist/presentation/routes/agent-runtime-config.js +59 -57
  117. package/dist/presentation/routes/agent-runtime-config.js.map +1 -1
  118. package/dist/presentation/routes/cancel-run.d.ts +2 -1
  119. package/dist/presentation/routes/cancel-run.d.ts.map +1 -1
  120. package/dist/presentation/routes/cancel-run.js +37 -34
  121. package/dist/presentation/routes/cancel-run.js.map +1 -1
  122. package/dist/presentation/routes/checkout-token.d.ts +8 -1
  123. package/dist/presentation/routes/checkout-token.d.ts.map +1 -1
  124. package/dist/presentation/routes/checkout-token.js +65 -47
  125. package/dist/presentation/routes/checkout-token.js.map +1 -1
  126. package/dist/presentation/routes/get-run-aggregates.d.ts +2 -1
  127. package/dist/presentation/routes/get-run-aggregates.d.ts.map +1 -1
  128. package/dist/presentation/routes/get-run-aggregates.js +44 -53
  129. package/dist/presentation/routes/get-run-aggregates.js.map +1 -1
  130. package/dist/presentation/routes/get-run.d.ts +2 -1
  131. package/dist/presentation/routes/get-run.d.ts.map +1 -1
  132. package/dist/presentation/routes/get-run.js +53 -50
  133. package/dist/presentation/routes/get-run.js.map +1 -1
  134. package/dist/presentation/routes/get-step-secrets.d.ts +3 -1
  135. package/dist/presentation/routes/get-step-secrets.d.ts.map +1 -1
  136. package/dist/presentation/routes/get-step-secrets.js +72 -68
  137. package/dist/presentation/routes/get-step-secrets.js.map +1 -1
  138. package/dist/presentation/routes/index.d.ts +19 -2
  139. package/dist/presentation/routes/index.d.ts.map +1 -1
  140. package/dist/presentation/routes/index.js +38 -30
  141. package/dist/presentation/routes/index.js.map +1 -1
  142. package/dist/presentation/routes/leased-step.d.ts +2 -0
  143. package/dist/presentation/routes/leased-step.d.ts.map +1 -1
  144. package/dist/presentation/routes/leased-step.js +1 -2
  145. package/dist/presentation/routes/leased-step.js.map +1 -1
  146. package/dist/presentation/routes/list-run-attempts.d.ts +2 -1
  147. package/dist/presentation/routes/list-run-attempts.d.ts.map +1 -1
  148. package/dist/presentation/routes/list-run-attempts.js +29 -26
  149. package/dist/presentation/routes/list-run-attempts.js.map +1 -1
  150. package/dist/presentation/routes/list-runs.d.ts +2 -1
  151. package/dist/presentation/routes/list-runs.d.ts.map +1 -1
  152. package/dist/presentation/routes/list-runs.js +51 -60
  153. package/dist/presentation/routes/list-runs.js.map +1 -1
  154. package/dist/presentation/routes/next-step.d.ts +10 -1
  155. package/dist/presentation/routes/next-step.d.ts.map +1 -1
  156. package/dist/presentation/routes/next-step.js +64 -50
  157. package/dist/presentation/routes/next-step.js.map +1 -1
  158. package/dist/presentation/routes/project-access.d.ts +10 -0
  159. package/dist/presentation/routes/project-access.d.ts.map +1 -0
  160. package/dist/presentation/routes/project-access.js +17 -0
  161. package/dist/presentation/routes/project-access.js.map +1 -0
  162. package/dist/presentation/routes/report-step.d.ts +2 -1
  163. package/dist/presentation/routes/report-step.d.ts.map +1 -1
  164. package/dist/presentation/routes/report-step.js +62 -61
  165. package/dist/presentation/routes/report-step.js.map +1 -1
  166. package/dist/presentation/routes/require-accessible-run.d.ts +3 -1
  167. package/dist/presentation/routes/require-accessible-run.d.ts.map +1 -1
  168. package/dist/presentation/routes/require-accessible-run.js +3 -6
  169. package/dist/presentation/routes/require-accessible-run.js.map +1 -1
  170. package/dist/presentation/routes/rerun-run.d.ts +2 -1
  171. package/dist/presentation/routes/rerun-run.d.ts.map +1 -1
  172. package/dist/presentation/routes/rerun-run.js +46 -43
  173. package/dist/presentation/routes/rerun-run.js.map +1 -1
  174. package/dist/temporal/activities/index.d.ts +44 -9
  175. package/dist/temporal/activities/index.d.ts.map +1 -1
  176. package/dist/temporal/activities/index.js +13 -9
  177. package/dist/temporal/activities/index.js.map +1 -1
  178. package/dist/temporal/activities/orchestration-activities.d.ts +20 -11
  179. package/dist/temporal/activities/orchestration-activities.d.ts.map +1 -1
  180. package/dist/temporal/activities/orchestration-activities.js +48 -33
  181. package/dist/temporal/activities/orchestration-activities.js.map +1 -1
  182. package/dist/tsconfig.test.tsbuildinfo +1 -1
  183. package/package.json +41 -44
  184. package/src/core/agent-defaults.test.ts +28 -0
  185. package/src/core/agent-defaults.ts +36 -0
  186. package/src/core/agent-tool-capability-warning.test.ts +36 -11
  187. package/src/core/agent-tool-capability-warning.ts +27 -25
  188. package/src/core/agent-tools.ts +33 -36
  189. package/src/core/checkout.test.ts +38 -25
  190. package/src/core/checkout.ts +41 -14
  191. package/src/core/entities/workflow-run-attempt.ts +1 -1
  192. package/src/core/job-execution.ts +19 -9
  193. package/src/core/job-transition/derive-job-execution-outputs.ts +1 -1
  194. package/src/core/job-transition/derive-job-success.ts +1 -1
  195. package/src/core/listener-execution-materialization.test.ts +4 -2
  196. package/src/core/listener-execution-materialization.ts +6 -9
  197. package/src/core/run-workflow.test.ts +43 -38
  198. package/src/core/run-workflow.ts +26 -9
  199. package/src/core/step-config/agent.ts +24 -26
  200. package/src/core/step-config/complete-step-dispatch-config.test.ts +22 -23
  201. package/src/core/step-config/complete-step-dispatch-config.ts +6 -6
  202. package/src/core/step-config/materialize-job-execution-steps.test.ts +34 -23
  203. package/src/core/step-config/materialize-job-execution-steps.ts +38 -39
  204. package/src/core/step-config/materialize-workflow-model.test.ts +94 -82
  205. package/src/core/step-config/materialize-workflow-model.ts +31 -29
  206. package/src/core/step-config/resolve-job-execution-name.ts +1 -1
  207. package/src/core/step-config/resolve-step-config.ts +11 -9
  208. package/src/core/step-config/run.ts +1 -1
  209. package/src/core/workflow-run-creation.test.ts +14 -10
  210. package/src/core/workflow-run-creation.ts +6 -9
  211. package/src/db/job-listeners.ts +20 -5
  212. package/src/db/runner-lease-table.ts +2 -2
  213. package/src/db/schema/workflow-run-attempts.ts +7 -3
  214. package/src/db/schema/workflow-runs.ts +1 -1
  215. package/src/db/workflow-runs/job-executions.ts +15 -1
  216. package/src/db/workflow-runs/jobs.ts +4 -1
  217. package/src/db/workflow-runs/run-create.test.ts +7 -1
  218. package/src/db/workflow-runs/run-create.ts +25 -15
  219. package/src/db/workflow-runs/run-rerun.test.ts +1 -1
  220. package/src/db/workflow-runs/run-rerun.ts +6 -3
  221. package/src/index.ts +75 -33
  222. package/src/presentation/dto/checkout-token.ts +7 -1
  223. package/src/presentation/index.ts +1 -1
  224. package/src/presentation/inter-module.test.ts +149 -0
  225. package/src/presentation/inter-module.ts +132 -0
  226. package/src/presentation/routes/agent-runtime-config.test.ts +53 -10
  227. package/src/presentation/routes/agent-runtime-config.ts +89 -64
  228. package/src/presentation/routes/cancel-run.test.ts +10 -20
  229. package/src/presentation/routes/cancel-run.ts +30 -27
  230. package/src/presentation/routes/checkout-token.test.ts +52 -33
  231. package/src/presentation/routes/checkout-token.ts +109 -49
  232. package/src/presentation/routes/get-run-aggregates.test.ts +13 -7
  233. package/src/presentation/routes/get-run-aggregates.ts +54 -57
  234. package/src/presentation/routes/get-run.test.ts +10 -18
  235. package/src/presentation/routes/get-run.ts +51 -48
  236. package/src/presentation/routes/get-step-secrets.test.ts +29 -7
  237. package/src/presentation/routes/get-step-secrets.ts +72 -61
  238. package/src/presentation/routes/index.test.ts +16 -1
  239. package/src/presentation/routes/index.ts +54 -29
  240. package/src/presentation/routes/leased-step.ts +3 -2
  241. package/src/presentation/routes/list-run-attempts.test.ts +9 -19
  242. package/src/presentation/routes/list-run-attempts.ts +21 -18
  243. package/src/presentation/routes/list-runs.test.ts +13 -7
  244. package/src/presentation/routes/list-runs.ts +64 -67
  245. package/src/presentation/routes/next-step.test.ts +30 -11
  246. package/src/presentation/routes/next-step.ts +68 -48
  247. package/src/presentation/routes/project-access.ts +16 -0
  248. package/src/presentation/routes/report-step.test.ts +18 -2
  249. package/src/presentation/routes/report-step.ts +51 -49
  250. package/src/presentation/routes/require-accessible-run.ts +5 -2
  251. package/src/presentation/routes/rerun-run.test.ts +9 -19
  252. package/src/presentation/routes/rerun-run.ts +39 -36
  253. package/src/temporal/activities/index.ts +32 -12
  254. package/src/temporal/activities/orchestration-activities.test.ts +10 -8
  255. package/src/temporal/activities/orchestration-activities.ts +74 -50
  256. package/src/temporal/workflows/job-execution-orchestration.test.ts +47 -2
  257. package/test/env.ts +1 -3
  258. package/test/factories/project.ts +10 -5
  259. package/test/factories/workflow-model.test.ts +5 -1
  260. package/test/factories/workflow-model.ts +1 -1
  261. package/test/factories/workflow-run.ts +1 -1
  262. package/test/fixtures/agent-inter-module.ts +27 -0
  263. package/test/fixtures/annotations-inter-module.ts +5 -0
  264. package/test/fixtures/auth-inter-module.ts +22 -0
  265. package/test/fixtures/lease-token.ts +2 -1
  266. package/test/fixtures/projects-inter-module.ts +8 -0
  267. package/test/fixtures/runners-inter-module.ts +52 -0
  268. package/test/fixtures/secrets-inter-module.ts +61 -0
  269. package/test/globalSetup.ts +11 -11
  270. package/tsconfig.build.tsbuildinfo +1 -1
  271. package/dist/core/source-control.d.ts +0 -5
  272. package/dist/core/source-control.d.ts.map +0 -1
  273. package/dist/core/source-control.js +0 -19
  274. package/dist/core/source-control.js.map +0 -1
  275. package/src/core/source-control.test.ts +0 -17
  276. package/src/core/source-control.ts +0 -22
  277. package/src/temporal/workflows/job-execution-orchestration-timeout.test.ts +0 -165
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-workflows",
3
3
  "license": "MIT",
4
- "version": "4.0.0",
4
+ "version": "6.0.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -13,22 +13,12 @@
13
13
  "types": "dist/index.d.ts",
14
14
  "imports": {
15
15
  "#test/*": "./test/*",
16
- "#*": {
17
- "workspace-source": "./src/*",
18
- "development": "./src/*",
19
- "default": "./dist/*"
20
- }
16
+ "#*": "./dist/*"
21
17
  },
22
18
  "exports": {
23
19
  ".": {
24
- "development": {
25
- "types": "./src/index.ts",
26
- "default": "./src/index.ts"
27
- },
28
- "default": {
29
- "types": "./dist/index.d.ts",
30
- "default": "./dist/index.js"
31
- }
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
32
22
  }
33
23
  },
34
24
  "dependencies": {
@@ -36,29 +26,29 @@
36
26
  "@temporalio/workflow": "1.18.1",
37
27
  "drizzle-orm": "^0.45.2",
38
28
  "zod": "^4.4.3",
39
- "@shipfox/api-agent": "4.0.0",
40
- "@shipfox/api-auth": "4.0.0",
41
- "@shipfox/api-auth-context": "3.0.0",
42
- "@shipfox/api-agent-dto": "3.0.0",
43
- "@shipfox/annotations": "4.0.0",
44
- "@shipfox/api-definitions": "4.0.0",
45
- "@shipfox/api-integration-core": "4.0.0",
46
- "@shipfox/api-projects": "4.0.0",
47
- "@shipfox/api-runners": "4.0.0",
48
- "@shipfox/api-runners-dto": "2.0.0",
49
- "@shipfox/api-secrets": "4.0.0",
50
- "@shipfox/api-secrets-dto": "2.0.0",
51
- "@shipfox/api-workflows-dto": "2.0.0",
52
- "@shipfox/expression": "1.1.2",
53
- "@shipfox/node-drizzle": "0.3.0",
54
- "@shipfox/node-error-monitoring": "0.1.2",
55
- "@shipfox/node-fastify": "0.2.2",
56
- "@shipfox/node-module": "0.3.1",
57
- "@shipfox/node-opentelemetry": "0.5.1",
58
- "@shipfox/node-outbox": "0.2.2",
59
- "@shipfox/node-postgres": "0.4.1",
60
- "@shipfox/node-temporal": "0.3.0",
61
- "@shipfox/runner-labels": "0.1.0"
29
+ "@shipfox/api-auth-context": "6.0.0",
30
+ "@shipfox/api-auth-dto": "6.0.0",
31
+ "@shipfox/api-agent-dto": "6.0.0",
32
+ "@shipfox/annotations-dto": "6.0.0",
33
+ "@shipfox/api-definitions-dto": "6.0.0",
34
+ "@shipfox/api-projects-dto": "6.0.0",
35
+ "@shipfox/api-integration-core-dto": "6.0.0",
36
+ "@shipfox/api-projects": "6.0.0",
37
+ "@shipfox/api-runners": "6.0.0",
38
+ "@shipfox/api-runners-dto": "6.0.0",
39
+ "@shipfox/api-secrets-dto": "6.0.0",
40
+ "@shipfox/api-workflows-dto": "6.0.0",
41
+ "@shipfox/inter-module": "0.2.0",
42
+ "@shipfox/expression": "1.1.3",
43
+ "@shipfox/node-drizzle": "0.3.2",
44
+ "@shipfox/node-error-monitoring": "0.1.3",
45
+ "@shipfox/node-fastify": "0.2.4",
46
+ "@shipfox/node-module": "0.4.0",
47
+ "@shipfox/node-opentelemetry": "0.5.2",
48
+ "@shipfox/node-outbox": "0.2.4",
49
+ "@shipfox/node-postgres": "0.4.2",
50
+ "@shipfox/node-temporal": "0.3.2",
51
+ "@shipfox/runner-labels": "0.1.1"
62
52
  },
63
53
  "devDependencies": {
64
54
  "@temporalio/activity": "1.18.1",
@@ -70,19 +60,26 @@
70
60
  "fastify": "^5.3.3",
71
61
  "fastify-type-provider-zod": "^6.0.0",
72
62
  "fishery": "^2.4.0",
73
- "@shipfox/api-auth-dto": "2.0.0",
74
- "@shipfox/biome": "1.8.1",
75
- "@shipfox/node-jwt": "0.2.0",
76
- "@shipfox/node-log": "0.3.3",
77
- "@shipfox/swc": "1.2.5",
63
+ "@shipfox/node-auth-root-key": "0.2.0",
64
+ "@shipfox/annotations": "6.0.0",
65
+ "@shipfox/api-auth": "6.0.0",
66
+ "@shipfox/api-agent": "6.0.0",
67
+ "@shipfox/api-definitions": "6.0.0",
68
+ "@shipfox/api-integration-core": "6.0.0",
69
+ "@shipfox/biome": "1.8.2",
70
+ "@shipfox/depcruise": "1.0.2",
71
+ "@shipfox/node-jwt": "0.3.0",
72
+ "@shipfox/node-log": "0.3.4",
73
+ "@shipfox/swc": "1.2.6",
78
74
  "@shipfox/ts-config": "1.3.8",
79
- "@shipfox/typescript": "1.1.6",
80
- "@shipfox/vitest": "1.2.2"
75
+ "@shipfox/typescript": "1.1.7",
76
+ "@shipfox/vitest": "1.2.3"
81
77
  },
82
78
  "scripts": {
83
79
  "build": "shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js",
84
80
  "check": "shipfox-biome-check",
85
81
  "check:fix": "shipfox-biome-check --write",
82
+ "depcruise": "shipfox-depcruise",
86
83
  "test": "shipfox-vitest-run",
87
84
  "test:watch": "shipfox-vitest-watch",
88
85
  "type": "shipfox-tsc-check",
@@ -0,0 +1,28 @@
1
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
2
+ import {createAgentDefaultsResolver} from './agent-defaults.js';
3
+
4
+ describe('createAgentDefaultsResolver', () => {
5
+ test('omits unresolved optional fields from the inter-module input', async () => {
6
+ const resolveAgentConfig = vi.fn().mockResolvedValue({
7
+ harness: 'pi',
8
+ provider: 'anthropic',
9
+ model: 'claude-opus-4-8',
10
+ thinking: 'xhigh',
11
+ });
12
+ const agent = {resolveAgentConfig} as unknown as AgentInterModuleClient;
13
+ const resolve = createAgentDefaultsResolver(agent, crypto.randomUUID());
14
+
15
+ const defaults = await resolve({});
16
+
17
+ expect(defaults).toEqual({
18
+ harness: 'pi',
19
+ provider: 'anthropic',
20
+ model: 'claude-opus-4-8',
21
+ thinking: 'xhigh',
22
+ });
23
+ expect(resolveAgentConfig).toHaveBeenCalledWith({
24
+ workspaceId: expect.any(String),
25
+ config: {},
26
+ });
27
+ });
28
+ });
@@ -0,0 +1,36 @@
1
+ import type {AgentThinking, Harness, ModelProviderRef} from '@shipfox/api-agent-dto';
2
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
3
+
4
+ export interface AgentDefaultsInput {
5
+ readonly harness?: Harness | undefined;
6
+ readonly provider?: ModelProviderRef | undefined;
7
+ readonly model?: string | undefined;
8
+ readonly thinking?: AgentThinking | undefined;
9
+ }
10
+
11
+ export interface ResolvedAgentDefaults {
12
+ readonly harness: Harness;
13
+ readonly provider: ModelProviderRef;
14
+ readonly model: string;
15
+ readonly thinking: AgentThinking;
16
+ }
17
+
18
+ export type AgentDefaultsResolver = (
19
+ input: AgentDefaultsInput,
20
+ ) => ResolvedAgentDefaults | Promise<ResolvedAgentDefaults>;
21
+
22
+ export function createAgentDefaultsResolver(
23
+ agent: AgentInterModuleClient,
24
+ workspaceId: string | null,
25
+ ): AgentDefaultsResolver {
26
+ return async (config) =>
27
+ await agent.resolveAgentConfig({
28
+ workspaceId,
29
+ config: {
30
+ ...(config.harness === undefined ? {} : {harness: config.harness}),
31
+ ...(config.provider === undefined ? {} : {provider: config.provider}),
32
+ ...(config.model === undefined ? {} : {model: config.model}),
33
+ ...(config.thinking === undefined ? {} : {thinking: config.thinking}),
34
+ },
35
+ });
36
+ }
@@ -1,9 +1,39 @@
1
+ import type {AnnotationsInterModuleClient} from '@shipfox/annotations-dto/inter-module';
1
2
  import type {JobLeaseTokenClaims} from '@shipfox/api-auth';
2
3
  import {sql} from 'drizzle-orm';
3
4
  import {db} from '#db/db.js';
4
- import {warnAgentToolCapabilityMismatchOnDispatch} from './agent-tool-capability-warning.js';
5
+ import {runnersTestClient} from '#test/fixtures/runners-inter-module.js';
6
+ import {warnAgentToolCapabilityMismatchOnDispatch as warnAgentToolCapabilityMismatchOnDispatchImpl} from './agent-tool-capability-warning.js';
5
7
  import type {Step} from './entities/step.js';
6
8
 
9
+ async function warnAgentToolCapabilityMismatchOnDispatch(
10
+ params: Omit<
11
+ Parameters<typeof warnAgentToolCapabilityMismatchOnDispatchImpl>[0],
12
+ 'annotations' | 'runners'
13
+ >,
14
+ ) {
15
+ return await warnAgentToolCapabilityMismatchOnDispatchImpl({
16
+ annotations: annotationsTestClient,
17
+ runners: runnersTestClient,
18
+ ...params,
19
+ });
20
+ }
21
+
22
+ const annotationBodiesByExecution = new Map<string, Map<string, string>>();
23
+
24
+ const annotationsTestClient: AnnotationsInterModuleClient = {
25
+ replaceOrRemoveAnnotation(input) {
26
+ const annotations = annotationBodiesByExecution.get(input.jobExecutionId) ?? new Map();
27
+ annotationBodiesByExecution.set(input.jobExecutionId, annotations);
28
+ if (input.annotation.op === 'remove') {
29
+ annotations.delete(input.context);
30
+ } else {
31
+ annotations.set(input.context, input.annotation.body);
32
+ }
33
+ return Promise.resolve({});
34
+ },
35
+ };
36
+
7
37
  function lease(params: Partial<JobLeaseTokenClaims> = {}): JobLeaseTokenClaims {
8
38
  const now = Math.floor(Date.now() / 1000);
9
39
  return {
@@ -97,16 +127,11 @@ async function insertRunnerSession(params: {
97
127
  `);
98
128
  }
99
129
 
100
- async function annotationsFor(
101
- jobExecutionId: string,
102
- ): Promise<Array<{context: string; body: string}>> {
103
- const result = await db().execute<{context: string; body: string}>(sql`
104
- SELECT context, body
105
- FROM annotations_annotations
106
- WHERE job_execution_id = ${jobExecutionId}
107
- ORDER BY sequence
108
- `);
109
- return [...result.rows];
130
+ function annotationsFor(jobExecutionId: string): Array<{context: string; body: string}> {
131
+ return Array.from(annotationBodiesByExecution.get(jobExecutionId) ?? [], ([context, body]) => ({
132
+ context,
133
+ body,
134
+ }));
110
135
  }
111
136
 
112
137
  describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
@@ -1,17 +1,15 @@
1
1
  import {
2
- AnnotationBodyTooLargeError,
3
- AnnotationCountLimitExceededError,
4
- AnnotationTotalBytesLimitExceededError,
5
- type WriteAnnotationsParams,
6
- writeAnnotations,
7
- } from '@shipfox/annotations';
2
+ type AnnotationsInterModuleClient,
3
+ annotationsInterModuleContract,
4
+ } from '@shipfox/annotations-dto/inter-module';
8
5
  import {
9
6
  harnessSchema,
10
7
  type MaterializedAgentStepConfigDto,
11
8
  materializedAgentStepConfigSchema,
12
9
  } from '@shipfox/api-agent-dto';
13
10
  import type {LeasedJobContext} from '@shipfox/api-auth-context';
14
- import {getEffectiveRunnerToolCapabilities, unadvertisedRunnerTools} from '@shipfox/api-runners';
11
+ import type {RunnersInterModuleClient} from '@shipfox/api-runners-dto/inter-module';
12
+ import {isInterModuleKnownError} from '@shipfox/inter-module';
15
13
  import {logger} from '@shipfox/node-opentelemetry';
16
14
  import {recordWorkflowAgentToolWarningFailed} from '#metrics/instance.js';
17
15
  import type {Step} from './entities/step.js';
@@ -22,6 +20,8 @@ type WarningFailureReason = 'budget' | 'lookup' | 'write';
22
20
  type WarningReason = 'known-absence' | 'harness-not-advertised' | 'unknown-or-stale';
23
21
 
24
22
  export async function warnAgentToolCapabilityMismatchOnDispatch(params: {
23
+ annotations: AnnotationsInterModuleClient;
24
+ runners: RunnersInterModuleClient;
25
25
  leaseIdentity: LeasedJobContext;
26
26
  step: Step;
27
27
  }): Promise<void> {
@@ -34,9 +34,11 @@ export async function warnAgentToolCapabilityMismatchOnDispatch(params: {
34
34
  const harness = harnessSchema.safeParse(config.harness);
35
35
  if (!harness.success) return;
36
36
 
37
- let effective: Awaited<ReturnType<typeof getEffectiveRunnerToolCapabilities>>;
37
+ let effective: Awaited<
38
+ ReturnType<RunnersInterModuleClient['getEffectiveRunnerToolCapabilities']>
39
+ >;
38
40
  try {
39
- effective = await getEffectiveRunnerToolCapabilities({
41
+ effective = await params.runners.getEffectiveRunnerToolCapabilities({
40
42
  runnerSessionId: params.leaseIdentity.runnerSessionId,
41
43
  });
42
44
  } catch (error) {
@@ -48,11 +50,8 @@ export async function warnAgentToolCapabilityMismatchOnDispatch(params: {
48
50
  return;
49
51
  }
50
52
 
51
- const missing = unadvertisedRunnerTools({
52
- harness: harness.data,
53
- requestedTools,
54
- capabilities: effective.capabilities,
55
- });
53
+ const advertised = new Set(effective.capabilities.harnesses[harness.data]?.tools ?? []);
54
+ const missing = requestedTools.filter((tool) => !advertised.has(tool));
56
55
  const context = `agent-tool-capability:${params.step.id}`;
57
56
 
58
57
  const operation =
@@ -67,17 +66,18 @@ export async function warnAgentToolCapabilityMismatchOnDispatch(params: {
67
66
  missing,
68
67
  reason: warningReason({
69
68
  reportFresh: effective.reportFresh,
70
- harnessKnown: effective.harnessKnown(harness.data),
69
+ harnessKnown: effective.capabilities.harnesses[harness.data] !== undefined,
71
70
  }),
72
71
  }),
73
72
  };
74
73
 
75
74
  try {
76
- await writeAnnotations({
77
- ...writeParamsFromLease(params.leaseIdentity),
75
+ await params.annotations.replaceOrRemoveAnnotation({
76
+ ...annotationTargetFromLease(params.leaseIdentity),
78
77
  originStepId: params.step.id,
79
78
  originStepAttempt: params.step.currentAttempt,
80
- operations: [operation],
79
+ context,
80
+ annotation: operation.op === 'remove' ? {op: 'remove'} : operation,
81
81
  });
82
82
  } catch (error) {
83
83
  const reason = isAnnotationBudgetError(error) ? 'budget' : 'write';
@@ -103,7 +103,7 @@ export async function warnAgentToolCapabilityMismatchOnDispatch(params: {
103
103
  missing,
104
104
  reason: warningReason({
105
105
  reportFresh: effective.reportFresh,
106
- harnessKnown: effective.harnessKnown(harness.data),
106
+ harnessKnown: effective.capabilities.harnesses[harness.data] !== undefined,
107
107
  }),
108
108
  },
109
109
  'Runner missing requested agent tools; dispatch is continuing',
@@ -173,9 +173,12 @@ function warningReason(params: {reportFresh: boolean; harnessKnown: boolean}): W
173
173
  return params.reportFresh ? 'harness-not-advertised' : 'unknown-or-stale';
174
174
  }
175
175
 
176
- function writeParamsFromLease(
176
+ function annotationTargetFromLease(
177
177
  lease: LeasedJobContext,
178
- ): Omit<WriteAnnotationsParams, 'originStepId' | 'originStepAttempt' | 'operations'> {
178
+ ): Omit<
179
+ Parameters<AnnotationsInterModuleClient['replaceOrRemoveAnnotation']>[0],
180
+ 'originStepId' | 'originStepAttempt' | 'context' | 'annotation'
181
+ > {
179
182
  return {
180
183
  workspaceId: lease.workspaceId,
181
184
  projectId: lease.projectId,
@@ -188,10 +191,9 @@ function writeParamsFromLease(
188
191
  }
189
192
 
190
193
  function isAnnotationBudgetError(error: unknown): boolean {
191
- return (
192
- error instanceof AnnotationBodyTooLargeError ||
193
- error instanceof AnnotationCountLimitExceededError ||
194
- error instanceof AnnotationTotalBytesLimitExceededError
194
+ return isInterModuleKnownError(
195
+ annotationsInterModuleContract.methods.replaceOrRemoveAnnotation,
196
+ error,
195
197
  );
196
198
  }
197
199
 
@@ -2,28 +2,28 @@ import type {
2
2
  MaterializedAgentIntegrationConfigDto,
3
3
  MaterializedAgentIntegrationToolConfigDto,
4
4
  } from '@shipfox/api-agent-dto';
5
- import type {WorkflowModel} from '@shipfox/api-definitions';
5
+ import type {WorkflowModel} from '@shipfox/api-definitions-dto';
6
6
  import type {
7
7
  AgentToolCatalogEntry,
8
8
  AgentToolCatalogMethod,
9
- AgentToolCatalogs,
10
- GetIntegrationConnectionByIdFn,
11
9
  IntegrationProviderKind,
12
- LoadWorkspaceConnectionSnapshot,
13
- WorkspaceConnectionSnapshot,
14
- } from '@shipfox/api-integration-core';
15
- import {getProjectById} from '@shipfox/api-projects';
10
+ IntegrationsModuleClient,
11
+ } from '@shipfox/api-integration-core-dto';
12
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
16
13
  import {AgentIntegrationMaterializationError} from './errors.js';
17
14
 
18
15
  type WorkflowModelJob = WorkflowModel['jobs'][number];
19
16
  type WorkflowModelAgentStep = Extract<WorkflowModelJob['steps'][number], {kind: 'agent'}>;
20
17
  type WorkflowModelStepIntegration = NonNullable<WorkflowModelAgentStep['integrations']>[number];
21
-
22
- interface AgentToolMaterializationServices {
23
- readonly catalogs: AgentToolCatalogs;
24
- readonly loadWorkspaceConnectionSnapshot: LoadWorkspaceConnectionSnapshot;
25
- readonly getIntegrationConnectionById: GetIntegrationConnectionByIdFn;
26
- }
18
+ type AgentToolCatalogs = ReadonlyMap<IntegrationProviderKind, readonly AgentToolCatalogEntry[]>;
19
+ type WorkspaceConnectionSnapshot = ReadonlyMap<
20
+ string,
21
+ {
22
+ id: string;
23
+ provider: IntegrationProviderKind;
24
+ capabilities: readonly ('source_control' | 'agent_tools')[];
25
+ }
26
+ >;
27
27
 
28
28
  export interface AgentToolMaterializationContext {
29
29
  readonly catalogs: AgentToolCatalogs;
@@ -51,48 +51,45 @@ interface SelectedToolState {
51
51
  selectedStandalone: boolean;
52
52
  }
53
53
 
54
- let services: AgentToolMaterializationServices | undefined;
55
-
56
- export function setAgentToolMaterializationServices(
57
- nextServices: AgentToolMaterializationServices,
58
- ): void {
59
- services = nextServices;
60
- }
61
-
62
- export function clearAgentToolMaterializationServices(): void {
63
- services = undefined;
64
- }
65
-
66
54
  export async function loadAgentToolMaterializationContext(params: {
67
55
  readonly model: WorkflowModel | null;
68
56
  readonly workspaceId: string;
69
57
  readonly projectId: string;
58
+ readonly integrations?: IntegrationsModuleClient | undefined;
59
+ readonly projects?: ProjectsModuleClient | undefined;
70
60
  readonly jobs?: readonly WorkflowModelJob[] | undefined;
71
61
  }): Promise<AgentToolMaterializationContext | undefined> {
72
62
  if (!modelHasAgentStepIntegrations(params.model, params.jobs)) return undefined;
73
- if (services === undefined) {
74
- throw new AgentIntegrationMaterializationError('Agent tool materialization is not configured');
75
- }
76
63
 
77
- const project = await getProjectById(params.projectId);
78
- if (project === undefined) {
64
+ if (params.projects === undefined) {
65
+ throw new AgentIntegrationMaterializationError('Project access is not configured');
66
+ }
67
+ const {project} = await params.projects.getProjectById({projectId: params.projectId});
68
+ if (project === null) {
79
69
  throw new AgentIntegrationMaterializationError(
80
70
  `Project ${params.projectId} was not found while materializing agent integrations`,
81
71
  );
82
72
  }
83
73
 
84
- const [workspaceConnectionSnapshot, defaultConnection] = await Promise.all([
85
- services.loadWorkspaceConnectionSnapshot(params.workspaceId),
86
- services.getIntegrationConnectionById(project.sourceConnectionId),
87
- ]);
88
- if (defaultConnection === undefined) {
74
+ if (params.integrations === undefined) {
75
+ throw new AgentIntegrationMaterializationError('Agent tool materialization is not configured');
76
+ }
77
+ const context = await params.integrations.getAgentToolsContext({
78
+ workspaceId: params.workspaceId,
79
+ defaultConnectionId: project.sourceConnectionId,
80
+ });
81
+ const workspaceConnectionSnapshot = new Map(
82
+ context.workspaceConnections.map(({slug, ...connection}) => [slug, connection]),
83
+ );
84
+ const defaultConnection = context.defaultConnection;
85
+ if (defaultConnection === null) {
89
86
  throw new AgentIntegrationMaterializationError(
90
87
  `Source connection ${project.sourceConnectionId} was not found while materializing agent integrations`,
91
88
  );
92
89
  }
93
90
 
94
91
  return {
95
- catalogs: services.catalogs,
92
+ catalogs: new Map(context.catalogs.map(({provider, tools}) => [provider, tools])),
96
93
  workspaceConnectionSnapshot,
97
94
  defaultConnection: {
98
95
  id: defaultConnection.id,
@@ -1,5 +1,5 @@
1
- import type {CheckoutSpec, IntegrationSourceControlService} from '@shipfox/api-integration-core';
2
- import {getProjectById} from '@shipfox/api-projects';
1
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
2
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
3
3
  import * as workflowRuns from '#db/workflow-runs.js';
4
4
  import {jobFactory} from '#test/factories/job.js';
5
5
  import {projectFactory} from '#test/factories/project.js';
@@ -10,16 +10,16 @@ import {
10
10
  WorkflowRunNotFoundError,
11
11
  } from './errors.js';
12
12
 
13
- vi.mock('@shipfox/api-projects', () => ({getProjectById: vi.fn()}));
14
- const mockGetProjectById = vi.mocked(getProjectById);
13
+ const getProjectById = vi.fn();
14
+ const projects = {getProjectById} as Pick<ProjectsModuleClient, 'getProjectById'>;
15
15
 
16
16
  describe('resolveCheckoutIntent', () => {
17
17
  it('resolves connection + repo from the project, using the project workspace', async () => {
18
18
  const project = projectFactory.build();
19
- mockGetProjectById.mockResolvedValue(project);
19
+ getProjectById.mockResolvedValue({project});
20
20
  const job = await jobFactory.create({}, {transient: {projectId: project.id}});
21
21
 
22
- const intent = await resolveCheckoutIntent(job.id);
22
+ const intent = await resolveCheckoutIntent(job.id, projects as ProjectsModuleClient);
23
23
 
24
24
  expect(intent).toEqual({
25
25
  workspaceId: project.workspaceId,
@@ -31,79 +31,92 @@ describe('resolveCheckoutIntent', () => {
31
31
  });
32
32
 
33
33
  it('throws JobNotFoundError for an unknown job', async () => {
34
- const act = resolveCheckoutIntent(crypto.randomUUID());
34
+ const act = resolveCheckoutIntent(crypto.randomUUID(), projects as ProjectsModuleClient);
35
35
 
36
36
  await expect(act).rejects.toBeInstanceOf(JobNotFoundError);
37
37
  });
38
38
 
39
39
  it('resolves the checkout target while the parent job projection is still pending', async () => {
40
40
  const project = projectFactory.build();
41
- mockGetProjectById.mockResolvedValue(project);
41
+ getProjectById.mockResolvedValue({project});
42
42
  const job = await jobFactory.create(
43
43
  {},
44
44
  {transient: {projectId: project.id, status: 'pending'}},
45
45
  );
46
46
 
47
- const intent = await resolveCheckoutIntent(job.id);
47
+ const intent = await resolveCheckoutIntent(job.id, projects as ProjectsModuleClient);
48
48
 
49
49
  expect(intent.connectionId).toBe(project.sourceConnectionId);
50
50
  });
51
51
 
52
52
  it('throws WorkflowRunNotFoundError when the run is missing', async () => {
53
53
  const project = projectFactory.build();
54
- mockGetProjectById.mockResolvedValue(project);
54
+ getProjectById.mockResolvedValue({project});
55
55
  const job = await jobFactory.create({}, {transient: {projectId: project.id}});
56
56
  vi.spyOn(workflowRuns, 'getWorkflowRunByAttemptId').mockResolvedValue(undefined);
57
57
 
58
- const act = resolveCheckoutIntent(job.id);
58
+ const act = resolveCheckoutIntent(job.id, projects as ProjectsModuleClient);
59
59
 
60
60
  await expect(act).rejects.toBeInstanceOf(WorkflowRunNotFoundError);
61
61
  });
62
62
 
63
63
  it('throws CheckoutIntentUnresolvedError when the project is missing', async () => {
64
64
  const project = projectFactory.build();
65
- mockGetProjectById.mockResolvedValue(undefined);
65
+ getProjectById.mockResolvedValue({project: null});
66
66
  const job = await jobFactory.create({}, {transient: {projectId: project.id}});
67
67
 
68
- const act = resolveCheckoutIntent(job.id);
68
+ const act = resolveCheckoutIntent(job.id, projects as ProjectsModuleClient);
69
69
 
70
70
  await expect(act).rejects.toBeInstanceOf(CheckoutIntentUnresolvedError);
71
71
  });
72
72
  });
73
73
 
74
74
  describe('createJobCheckoutSpec', () => {
75
- it('passes the resolved intent and an undefined ref to the service', async () => {
75
+ it('passes the resolved intent without a ref to the service', async () => {
76
76
  const project = projectFactory.build();
77
- mockGetProjectById.mockResolvedValue(project);
77
+ getProjectById.mockResolvedValue({project});
78
78
  const job = await jobFactory.create({}, {transient: {projectId: project.id}});
79
- const spec: CheckoutSpec = {repositoryUrl: 'https://github.com/acme/repo.git', ref: 'main'};
79
+ const spec = {repositoryUrl: 'https://github.com/acme/repo.git', ref: 'main'};
80
80
  const createCheckoutSpec = vi.fn().mockResolvedValue(spec);
81
- const sourceControl = {createCheckoutSpec} as unknown as IntegrationSourceControlService;
82
-
83
- const result = await createJobCheckoutSpec({jobId: job.id, sourceControl});
81
+ const integrations = {createCheckoutSpec} as Pick<
82
+ IntegrationsModuleClient,
83
+ 'createCheckoutSpec'
84
+ >;
85
+
86
+ const result = await createJobCheckoutSpec({
87
+ jobId: job.id,
88
+ integrations: integrations as IntegrationsModuleClient,
89
+ projects: projects as ProjectsModuleClient,
90
+ });
84
91
 
85
92
  expect(result).toEqual({spec, persistCredentials: true});
86
93
  expect(createCheckoutSpec).toHaveBeenCalledWith({
87
94
  workspaceId: project.workspaceId,
88
95
  connectionId: project.sourceConnectionId,
89
96
  externalRepositoryId: project.sourceExternalRepositoryId,
90
- ref: undefined,
91
97
  permissions: {contents: 'read'},
92
98
  });
93
99
  });
94
100
 
95
101
  it('passes requested write contents permission to the service', async () => {
96
102
  const project = projectFactory.build();
97
- mockGetProjectById.mockResolvedValue(project);
103
+ getProjectById.mockResolvedValue({project});
98
104
  const job = await jobFactory.create(
99
105
  {},
100
106
  {transient: {projectId: project.id, checkout: {permissions: {contents: 'write'}}}},
101
107
  );
102
- const spec: CheckoutSpec = {repositoryUrl: 'https://github.com/acme/repo.git', ref: 'main'};
108
+ const spec = {repositoryUrl: 'https://github.com/acme/repo.git', ref: 'main'};
103
109
  const createCheckoutSpec = vi.fn().mockResolvedValue(spec);
104
- const sourceControl = {createCheckoutSpec} as unknown as IntegrationSourceControlService;
105
-
106
- await createJobCheckoutSpec({jobId: job.id, sourceControl});
110
+ const integrations = {createCheckoutSpec} as Pick<
111
+ IntegrationsModuleClient,
112
+ 'createCheckoutSpec'
113
+ >;
114
+
115
+ await createJobCheckoutSpec({
116
+ jobId: job.id,
117
+ integrations: integrations as IntegrationsModuleClient,
118
+ projects: projects as ProjectsModuleClient,
119
+ });
107
120
 
108
121
  expect(createCheckoutSpec).toHaveBeenCalledWith(
109
122
  expect.objectContaining({permissions: {contents: 'write'}}),