@shipfox/api-workflows 5.0.0 → 7.0.1

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 +89 -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 +28 -21
  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
@@ -1,3 +1,4 @@
1
+ import {readPersistedWorkflowModel} from '@shipfox/api-definitions-dto';
1
2
  import {and, asc, eq, inArray, sql} from 'drizzle-orm';
2
3
  import {isWorkflowRunTerminal, type WorkflowRun} from '#core/entities/workflow-run.js';
3
4
  import {NoFailedJobsError, RunNotTerminalError, SourceRunNotFoundError} from '#core/errors.js';
@@ -175,9 +176,11 @@ function materializeRerunGraphJobs(params: {
175
176
  readonly sourceJobByJobExecutionId: ReadonlyMap<string, JobDb>;
176
177
  readonly sourceSteps: readonly StepDb[];
177
178
  }): readonly MaterializedRunGraphJob[] {
178
- const sourceModelJobByKey = new Map(
179
- (params.sourceAttempt.model?.jobs ?? []).map((job) => [job.key, job]),
180
- );
179
+ const sourceModel =
180
+ params.sourceAttempt.model === null
181
+ ? null
182
+ : readPersistedWorkflowModel(params.sourceAttempt.model);
183
+ const sourceModelJobByKey = new Map((sourceModel?.jobs ?? []).map((job) => [job.key, job]));
181
184
  const sourceStepsByJobId = new Map<string, StepDb[]>();
182
185
  for (const step of params.sourceSteps) {
183
186
  const sourceJob = params.sourceJobByJobExecutionId.get(step.jobExecutionId);
package/src/index.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  import {dirname, resolve} from 'node:path';
2
2
  import {fileURLToPath} from 'node:url';
3
+ import type {AnnotationsInterModuleClient} from '@shipfox/annotations-dto/inter-module';
4
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
5
+ import type {AuthInterModuleClient} from '@shipfox/api-auth-dto/inter-module';
6
+ import type {DefinitionsInterModuleClient} from '@shipfox/api-definitions-dto/inter-module';
7
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
8
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
3
9
  import {
4
10
  RUNNER_JOB_CLAIMED,
5
11
  RUNNER_JOB_LEASE_EXPIRED,
6
12
  RUNNER_JOB_QUEUED,
7
13
  type RunnersEventMap,
8
14
  } from '@shipfox/api-runners-dto';
15
+ import type {RunnersInterModuleClient} from '@shipfox/api-runners-dto/inter-module';
16
+ import type {SecretsInterModuleClient} from '@shipfox/api-secrets-dto/inter-module';
9
17
  import {
10
18
  WORKFLOWS_JOB_EVENT_DELIVERED,
11
19
  WORKFLOWS_JOB_STEPS_SETTLED,
@@ -18,6 +26,7 @@ import {type ShipfoxModule, subscriberFactory} from '@shipfox/node-module';
18
26
  import {db, migrationsPath, workflowsOutbox} from '#db/index.js';
19
27
  import {registerWorkflowsServiceMetrics} from '#metrics/index.js';
20
28
  import {
29
+ createWorkflowRoutes,
21
30
  onJobEventDelivered,
22
31
  onJobStepsSettled,
23
32
  onRunnerJobClaimed,
@@ -25,14 +34,10 @@ import {
25
34
  onRunnerJobQueued,
26
35
  onWorkflowRunAttemptCreated,
27
36
  onWorkflowRunCancelled,
28
- routes,
29
37
  } from '#presentation/index.js';
38
+ import {createWorkflowsInterModulePresentation} from '#presentation/inter-module.js';
30
39
  import {createOrchestrationActivities, WORKFLOWS_TASK_QUEUE} from '#temporal/index.js';
31
40
 
32
- export {
33
- clearAgentToolMaterializationServices,
34
- setAgentToolMaterializationServices,
35
- } from '#core/agent-tools.js';
36
41
  export type {
37
42
  Job,
38
43
  JobListenerEvent,
@@ -51,7 +56,6 @@ export {
51
56
  runWorkflow,
52
57
  WorkflowRunNotCancellableError,
53
58
  } from '#core/index.js';
54
- export {setSourceControl} from '#core/source-control.js';
55
59
  export {
56
60
  closeDb,
57
61
  type DeliverEventToListenerParams,
@@ -63,7 +67,6 @@ export {
63
67
  migrationsPath,
64
68
  workflowsOutbox,
65
69
  } from '#db/index.js';
66
- export {routes} from '#presentation/index.js';
67
70
  export {loadRunningLeasedStep} from '#presentation/routes/leased-step.js';
68
71
 
69
72
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
@@ -71,29 +74,68 @@ const workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');
71
74
 
72
75
  const subscriber = subscriberFactory<WorkflowsEventMapDto & RunnersEventMap>();
73
76
 
74
- export const workflowsModule: ShipfoxModule = {
75
- name: 'workflows',
76
- database: {db, migrationsPath},
77
- routes,
78
- metrics: registerWorkflowsServiceMetrics,
79
- publishers: [
80
- {name: 'workflows', table: workflowsOutbox, db, eventSchemas: workflowsEventSchemas},
81
- ],
82
- subscribers: [
83
- subscriber(WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED, onWorkflowRunAttemptCreated),
84
- subscriber(WORKFLOWS_WORKFLOW_RUN_CANCELLED, onWorkflowRunCancelled),
85
- subscriber(WORKFLOWS_JOB_EVENT_DELIVERED, onJobEventDelivered),
86
- subscriber(WORKFLOWS_JOB_STEPS_SETTLED, onJobStepsSettled),
87
- subscriber(RUNNER_JOB_LEASE_EXPIRED, onRunnerJobLeaseExpired),
88
- subscriber(RUNNER_JOB_QUEUED, onRunnerJobQueued),
89
- subscriber(RUNNER_JOB_CLAIMED, onRunnerJobClaimed),
90
- ],
91
- workers: [
92
- {
93
- taskQueue: WORKFLOWS_TASK_QUEUE,
94
- workflowsPath,
95
- activities: createOrchestrationActivities,
96
- workflows: [],
97
- },
98
- ],
99
- };
77
+ export function createWorkflowsModule({
78
+ agent,
79
+ definitions,
80
+ annotations,
81
+ auth,
82
+ integrations,
83
+ projects,
84
+ runners,
85
+ secrets,
86
+ }: {
87
+ agent: AgentInterModuleClient;
88
+ definitions: DefinitionsInterModuleClient;
89
+ annotations: AnnotationsInterModuleClient;
90
+ auth: AuthInterModuleClient;
91
+ integrations: IntegrationsModuleClient;
92
+ projects: ProjectsModuleClient;
93
+ runners: RunnersInterModuleClient;
94
+ secrets: SecretsInterModuleClient;
95
+ }): ShipfoxModule {
96
+ return {
97
+ name: 'workflows',
98
+ database: {db, migrationsPath},
99
+ routes: createWorkflowRoutes({
100
+ agent,
101
+ annotations,
102
+ auth,
103
+ integrations,
104
+ projects,
105
+ runners,
106
+ secrets,
107
+ }),
108
+ metrics: registerWorkflowsServiceMetrics,
109
+ publishers: [
110
+ {name: 'workflows', table: workflowsOutbox, db, eventSchemas: workflowsEventSchemas},
111
+ ],
112
+ subscribers: [
113
+ subscriber(WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED, onWorkflowRunAttemptCreated),
114
+ subscriber(WORKFLOWS_WORKFLOW_RUN_CANCELLED, onWorkflowRunCancelled),
115
+ subscriber(WORKFLOWS_JOB_EVENT_DELIVERED, onJobEventDelivered),
116
+ subscriber(WORKFLOWS_JOB_STEPS_SETTLED, onJobStepsSettled),
117
+ subscriber(RUNNER_JOB_LEASE_EXPIRED, onRunnerJobLeaseExpired),
118
+ subscriber(RUNNER_JOB_QUEUED, onRunnerJobQueued),
119
+ subscriber(RUNNER_JOB_CLAIMED, onRunnerJobClaimed),
120
+ ],
121
+ workers: [
122
+ {
123
+ taskQueue: WORKFLOWS_TASK_QUEUE,
124
+ workflowsPath,
125
+ activities: () =>
126
+ createOrchestrationActivities({agent, integrations, projects, runners, secrets}),
127
+ workflows: [],
128
+ },
129
+ ],
130
+ interModulePresentations: [
131
+ createWorkflowsInterModulePresentation({
132
+ agent,
133
+ definitions,
134
+ integrations,
135
+ projects,
136
+ runners,
137
+ secrets,
138
+ }),
139
+ ],
140
+ };
141
+ }
@@ -1,4 +1,10 @@
1
- import type {CheckoutSpec} from '@shipfox/api-integration-core';
1
+ type CheckoutSpec = {
2
+ repositoryUrl: string;
3
+ ref: string;
4
+ credentials?: {username: string; token: string; expiresAt: Date} | undefined;
5
+ gitAuthor?: {name: string; email: string} | undefined;
6
+ };
7
+
2
8
  import type {CheckoutTokenResponseDto} from '@shipfox/api-workflows-dto';
3
9
 
4
10
  const SCP_LIKE_HOST_RE = /^(?:[^@:/]+@)?([^:/]+):/;
@@ -1,4 +1,4 @@
1
- export {workflowRoutes as routes} from './routes/index.js';
1
+ export {createWorkflowRoutes} from './routes/index.js';
2
2
  export {
3
3
  onJobEventDelivered,
4
4
  onJobStepsSettled,
@@ -0,0 +1,149 @@
1
+ import {workflowsInterModuleContract} from '@shipfox/api-workflows-dto/inter-module';
2
+ import {isInterModuleKnownError} from '@shipfox/inter-module';
3
+ import {InvalidJobRunnerLabelsError} from '#core/errors.js';
4
+ import {
5
+ AgentConfigUnresolvableError,
6
+ AgentIntegrationMaterializationError,
7
+ DefinitionNotFoundError,
8
+ InterpolationUnresolvableError,
9
+ ProjectMismatchError,
10
+ } from '#core/index.js';
11
+ import {createWorkflowsInterModulePresentation, toStartRunKnownError} from './inter-module.js';
12
+
13
+ const mocks = vi.hoisted(() => ({
14
+ getJobScope: vi.fn(),
15
+ getStepById: vi.fn(),
16
+ getStepByIdForJobExecution: vi.fn(),
17
+ }));
18
+
19
+ vi.mock('#db/index.js', () => mocks);
20
+
21
+ const input = {
22
+ workspaceId: '00000000-0000-4000-8000-000000000001',
23
+ projectId: '00000000-0000-4000-8000-000000000002',
24
+ definitionId: '00000000-0000-4000-8000-000000000003',
25
+ triggerPayload: {
26
+ provider: 'manual' as const,
27
+ source: 'manual' as const,
28
+ event: 'fire' as const,
29
+ subscriptionId: '00000000-0000-4000-8000-000000000004',
30
+ userId: '00000000-0000-4000-8000-000000000005',
31
+ },
32
+ idempotencyKey: 'manual-1',
33
+ };
34
+
35
+ describe('Workflows inter-module presentation', () => {
36
+ beforeEach(() => {
37
+ mocks.getJobScope.mockReset();
38
+ mocks.getStepById.mockReset();
39
+ mocks.getStepByIdForJobExecution.mockReset();
40
+ });
41
+
42
+ it('returns only the resolved harness for Logs', async () => {
43
+ mocks.getStepById.mockResolvedValue({config: {harness: 'claude'}});
44
+ const presentation = createWorkflowsInterModulePresentation({
45
+ agent: {} as never,
46
+ definitions: {} as never,
47
+ integrations: {} as never,
48
+ projects: {} as never,
49
+ runners: {} as never,
50
+ secrets: {} as never,
51
+ });
52
+
53
+ const result = await presentation.handlers.getStepLogContext(
54
+ {stepId: '00000000-0000-4000-8000-000000000006'},
55
+ {signal: new AbortController().signal},
56
+ );
57
+
58
+ expect(result).toEqual({harness: 'claude'});
59
+ });
60
+
61
+ it('returns materialized agent integrations for the active leased step', async () => {
62
+ const input = {
63
+ jobId: '00000000-0000-4000-8000-000000000006',
64
+ jobExecutionId: '00000000-0000-4000-8000-000000000007',
65
+ runnerSessionId: '00000000-0000-4000-8000-000000000008',
66
+ stepId: '00000000-0000-4000-8000-000000000009',
67
+ attempt: 1,
68
+ };
69
+ const integration = {
70
+ connectionId: 'connection-1',
71
+ connectionSlug: 'github',
72
+ provider: 'github',
73
+ requiredScope: [],
74
+ tools: [
75
+ {
76
+ id: 'files',
77
+ sensitivity: 'read' as const,
78
+ sensitive: false,
79
+ requiredScope: [],
80
+ inputSchema: {},
81
+ },
82
+ ],
83
+ };
84
+ mocks.getStepByIdForJobExecution.mockResolvedValue({
85
+ currentAttempt: input.attempt,
86
+ status: 'running',
87
+ type: 'agent',
88
+ config: {
89
+ harness: 'pi',
90
+ provider: 'openai',
91
+ model: 'gpt-5',
92
+ thinking: 'off',
93
+ prompt: 'Review the change.',
94
+ integrations: [integration],
95
+ },
96
+ });
97
+ mocks.getJobScope.mockResolvedValue({workspaceId: '00000000-0000-4000-8000-000000000010'});
98
+ const runners = {getLeaseState: vi.fn().mockResolvedValue({active: true})};
99
+ const presentation = createWorkflowsInterModulePresentation({
100
+ agent: {} as never,
101
+ definitions: {} as never,
102
+ integrations: {} as never,
103
+ projects: {} as never,
104
+ runners: runners as never,
105
+ secrets: {} as never,
106
+ });
107
+
108
+ const result = await presentation.handlers.getLeasedAgentToolContext(input, {
109
+ signal: new AbortController().signal,
110
+ });
111
+
112
+ expect(result).toEqual({
113
+ workspaceId: '00000000-0000-4000-8000-000000000010',
114
+ integrations: [integration],
115
+ });
116
+ expect(runners.getLeaseState).toHaveBeenCalledWith({
117
+ jobId: input.jobId,
118
+ jobExecutionId: input.jobExecutionId,
119
+ runnerSessionId: input.runnerSessionId,
120
+ });
121
+ });
122
+
123
+ test.each([
124
+ ['definition-not-found', () => new DefinitionNotFoundError(input.definitionId)],
125
+ ['project-mismatch', () => new ProjectMismatchError(input.projectId, input.definitionId)],
126
+ ['agent-config-unresolvable', () => new AgentConfigUnresolvableError(input.definitionId)],
127
+ [
128
+ 'agent-integration-materialization-failed',
129
+ () => new AgentIntegrationMaterializationError('integration unavailable'),
130
+ ],
131
+ [
132
+ 'interpolation-unresolvable',
133
+ () =>
134
+ new InterpolationUnresolvableError(input.definitionId, {
135
+ field: 'env',
136
+ source: 'event.ref',
137
+ envKey: 'REF',
138
+ }),
139
+ ],
140
+ ['invalid-job-runner-labels', () => new InvalidJobRunnerLabelsError(['gpu'])],
141
+ ] as const)('maps %s to the published contract error', (code, error) => {
142
+ const result = toStartRunKnownError(error(), input.definitionId);
143
+
144
+ expect(
145
+ isInterModuleKnownError(workflowsInterModuleContract.methods.startRunFromTrigger, result) &&
146
+ result.code,
147
+ ).toBe(code);
148
+ });
149
+ });
@@ -0,0 +1,132 @@
1
+ import {
2
+ DEFAULT_HARNESS,
3
+ harnessSchema,
4
+ materializedAgentStepConfigSchema,
5
+ } from '@shipfox/api-agent-dto';
6
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
7
+ import type {DefinitionsInterModuleClient} from '@shipfox/api-definitions-dto/inter-module';
8
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
9
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
10
+ import type {RunnersInterModuleClient} from '@shipfox/api-runners-dto/inter-module';
11
+ import type {SecretsInterModuleClient} from '@shipfox/api-secrets-dto/inter-module';
12
+ import {workflowsInterModuleContract} from '@shipfox/api-workflows-dto/inter-module';
13
+ import {
14
+ createInterModuleKnownError,
15
+ defineInterModulePresentation,
16
+ type InterModulePresentation,
17
+ } from '@shipfox/inter-module';
18
+ import {InvalidJobRunnerLabelsError} from '#core/errors.js';
19
+ import {
20
+ AgentConfigUnresolvableError,
21
+ AgentIntegrationMaterializationError,
22
+ DefinitionNotFoundError,
23
+ InterpolationUnresolvableError,
24
+ ProjectMismatchError,
25
+ runWorkflow,
26
+ } from '#core/index.js';
27
+ import {getJobScope, getStepById, getStepByIdForJobExecution} from '#db/index.js';
28
+ import {deliverEventToListener} from '#db/job-listener-events.js';
29
+
30
+ export function createWorkflowsInterModulePresentation(params: {
31
+ agent: AgentInterModuleClient;
32
+ definitions: DefinitionsInterModuleClient;
33
+ secrets: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'>;
34
+ runners: RunnersInterModuleClient;
35
+ integrations: IntegrationsModuleClient;
36
+ projects: ProjectsModuleClient;
37
+ }): InterModulePresentation<typeof workflowsInterModuleContract> {
38
+ return defineInterModulePresentation(workflowsInterModuleContract, {
39
+ startRunFromTrigger: async (input) => {
40
+ try {
41
+ const run = await runWorkflow(
42
+ params.definitions,
43
+ {
44
+ agent: params.agent,
45
+ workspaceId: input.workspaceId,
46
+ projectId: input.projectId,
47
+ definitionId: input.definitionId,
48
+ triggerPayload: input.triggerPayload,
49
+ inputs: input.inputs,
50
+ triggerIdempotencyKey: input.idempotencyKey,
51
+ integrations: params.integrations,
52
+ projects: params.projects,
53
+ },
54
+ {secrets: params.secrets},
55
+ );
56
+ return {id: run.id, name: run.name};
57
+ } catch (error) {
58
+ throw toStartRunKnownError(error, input.definitionId);
59
+ }
60
+ },
61
+ deliverEventToJobListener: async (input) =>
62
+ await deliverEventToListener({...input, receivedAt: new Date(input.receivedAt)}),
63
+ getStepLogContext: async ({stepId}) => {
64
+ const step = await getStepById(stepId);
65
+ const parsed = harnessSchema.safeParse(step?.config.harness);
66
+ return {harness: parsed.success ? parsed.data : DEFAULT_HARNESS};
67
+ },
68
+ getLeasedAgentToolContext: async (input) => {
69
+ const method = workflowsInterModuleContract.methods.getLeasedAgentToolContext;
70
+ const {active: leaseIsActive} = await params.runners.getLeaseState({
71
+ jobId: input.jobId,
72
+ jobExecutionId: input.jobExecutionId,
73
+ runnerSessionId: input.runnerSessionId,
74
+ });
75
+ if (!leaseIsActive) throw createInterModuleKnownError(method, 'lease-not-active', {});
76
+
77
+ const step = await getStepByIdForJobExecution({
78
+ stepId: input.stepId,
79
+ jobExecutionId: input.jobExecutionId,
80
+ });
81
+ if (!step) throw createInterModuleKnownError(method, 'step-not-found', {});
82
+
83
+ const scope = await getJobScope(input.jobId);
84
+ if (!scope) throw createInterModuleKnownError(method, 'job-not-found', {});
85
+ if (step.currentAttempt !== input.attempt) {
86
+ throw createInterModuleKnownError(method, 'step-attempt-mismatch', {});
87
+ }
88
+ if (step.status !== 'running')
89
+ throw createInterModuleKnownError(method, 'step-not-running', {});
90
+ if (step.type !== 'agent')
91
+ throw createInterModuleKnownError(method, 'leased-step-not-agent', {});
92
+
93
+ const config = materializedAgentStepConfigSchema.safeParse(step.config);
94
+ if (!config.success) {
95
+ throw createInterModuleKnownError(method, 'agent-step-config-invalid', {});
96
+ }
97
+ return {workspaceId: scope.workspaceId, integrations: config.data.integrations ?? []};
98
+ },
99
+ });
100
+ }
101
+
102
+ export function toStartRunKnownError(error: unknown, definitionId: string): unknown {
103
+ const method = workflowsInterModuleContract.methods.startRunFromTrigger;
104
+ if (error instanceof DefinitionNotFoundError) {
105
+ return createInterModuleKnownError(method, 'definition-not-found', {definitionId});
106
+ }
107
+ if (error instanceof ProjectMismatchError) {
108
+ return createInterModuleKnownError(method, 'project-mismatch', {});
109
+ }
110
+ if (error instanceof AgentConfigUnresolvableError) {
111
+ return createInterModuleKnownError(method, 'agent-config-unresolvable', {
112
+ definitionId: error.definitionId,
113
+ });
114
+ }
115
+ if (error instanceof AgentIntegrationMaterializationError) {
116
+ return createInterModuleKnownError(method, 'agent-integration-materialization-failed', {});
117
+ }
118
+ if (error instanceof InterpolationUnresolvableError) {
119
+ return createInterModuleKnownError(method, 'interpolation-unresolvable', {
120
+ definitionId: error.definitionId,
121
+ field: error.field,
122
+ source: error.source,
123
+ ...(error.envKey === undefined ? {} : {envKey: error.envKey}),
124
+ });
125
+ }
126
+ if (error instanceof InvalidJobRunnerLabelsError) {
127
+ return createInterModuleKnownError(method, 'invalid-job-runner-labels', {
128
+ labels: [...error.labels],
129
+ });
130
+ }
131
+ return error;
132
+ }
@@ -1,10 +1,20 @@
1
- import {createCustomModelProviderConfig, testAndSaveModelProviderConfig} from '@shipfox/api-agent';
1
+ import {
2
+ createAgentModule,
3
+ createCustomModelProviderConfig,
4
+ testAndSaveModelProviderConfig,
5
+ } from '@shipfox/api-agent';
2
6
  import {resolveRuntimeCredentials} from '@shipfox/api-agent/core/resolve-runtime-credentials';
7
+ import {agentInterModuleContract} from '@shipfox/api-agent-dto/inter-module';
3
8
  import {createLeaseTokenAuthMethod} from '@shipfox/api-auth';
4
- import type {WorkflowModel} from '@shipfox/api-definitions';
5
- import {SecretDecryptionError} from '@shipfox/api-secrets';
9
+ import type {WorkflowModel} from '@shipfox/api-definitions-dto';
10
+ import {secretsInterModuleContract} from '@shipfox/api-secrets-dto/inter-module';
11
+ import {createInterModuleKnownError} from '@shipfox/inter-module';
6
12
  import {closeApp, createApp, type FastifyInstance} from '@shipfox/node-fastify';
7
13
  import {createCapturingLogger} from '@shipfox/node-log/test';
14
+ import {
15
+ createInMemoryInterModuleTransport,
16
+ registerInterModulePresentations,
17
+ } from '@shipfox/node-module/inter-module';
8
18
  import {eq} from 'drizzle-orm';
9
19
  import type {StepStatus} from '#core/entities/step.js';
10
20
  import {db} from '#db/db.js';
@@ -13,8 +23,14 @@ import {steps as stepsTable} from '#db/schema/steps.js';
13
23
  import {createWorkflowRun, getJobsByWorkflowRunId, getStepsByJobId} from '#db/workflow-runs.js';
14
24
  import {workflowModel} from '#test/factories/workflow-model.js';
15
25
  import {insertRunningJobLease, mintActiveLeaseToken} from '#test/fixtures/active-lease-token.js';
26
+ import {resolveTestAgentDefaults} from '#test/fixtures/agent-inter-module.js';
27
+ import {annotationsTestClient} from '#test/fixtures/annotations-inter-module.js';
28
+ import {workflowsTestAuthClient} from '#test/fixtures/auth-inter-module.js';
16
29
  import {mintLeaseToken} from '#test/fixtures/lease-token.js';
17
- import {leaseTokenRouteGroup} from './index.js';
30
+ import {projectsTestClient} from '#test/fixtures/projects-inter-module.js';
31
+ import {runnersTestClient} from '#test/fixtures/runners-inter-module.js';
32
+ import {createTestSecretsClient} from '#test/fixtures/secrets-inter-module.js';
33
+ import {createLeaseTokenRouteGroup} from './index.js';
18
34
 
19
35
  const {captureExceptionMock} = vi.hoisted(() => ({captureExceptionMock: vi.fn()}));
20
36
  vi.mock('@shipfox/api-agent/core/resolve-runtime-credentials', async (importOriginal) => {
@@ -25,6 +41,14 @@ vi.mock('@shipfox/api-agent/core/resolve-runtime-credentials', async (importOrig
25
41
  vi.mock('@shipfox/node-error-monitoring', () => ({captureException: captureExceptionMock}));
26
42
 
27
43
  const URL = '/runs/jobs/current/agent-runtime-config';
44
+ const secrets = createTestSecretsClient();
45
+ const agentTransport = createInMemoryInterModuleTransport();
46
+ const agentTestClient = agentTransport.createClient(agentInterModuleContract);
47
+ registerInterModulePresentations({
48
+ transport: agentTransport,
49
+ modules: [createAgentModule({secrets})],
50
+ });
51
+ agentTransport.seal();
28
52
 
29
53
  describe('GET /runs/jobs/current/agent-runtime-config', () => {
30
54
  let app: FastifyInstance;
@@ -33,7 +57,17 @@ describe('GET /runs/jobs/current/agent-runtime-config', () => {
33
57
  beforeAll(async () => {
34
58
  app = await createApp({
35
59
  auth: [createLeaseTokenAuthMethod()],
36
- routes: [leaseTokenRouteGroup],
60
+ routes: [
61
+ createLeaseTokenRouteGroup({
62
+ agent: agentTestClient,
63
+ annotations: annotationsTestClient,
64
+ auth: workflowsTestAuthClient,
65
+ integrations: {} as never,
66
+ projects: projectsTestClient,
67
+ runners: runnersTestClient,
68
+ secrets,
69
+ }),
70
+ ],
37
71
  swagger: false,
38
72
  fastifyOptions: {loggerInstance: logger},
39
73
  });
@@ -174,7 +208,7 @@ describe('GET /runs/jobs/current/agent-runtime-config', () => {
174
208
  models: [{id: 'llama-3.1', label: 'Llama 3.1'}],
175
209
  },
176
210
  },
177
- {probe: async () => undefined},
211
+ {probe: async () => undefined, secrets},
178
212
  );
179
213
  const {job, step} = await createRunningAgentStep({
180
214
  workspaceId,
@@ -347,7 +381,13 @@ describe('GET /runs/jobs/current/agent-runtime-config', () => {
347
381
 
348
382
  test('returns 409 and reports when workspace credentials cannot be decrypted', async () => {
349
383
  const {job, step} = await createRunningAgentStep();
350
- vi.mocked(resolveRuntimeCredentials).mockRejectedValueOnce(new SecretDecryptionError());
384
+ vi.mocked(resolveRuntimeCredentials).mockRejectedValueOnce(
385
+ createInterModuleKnownError(
386
+ secretsInterModuleContract.methods.getSecretsByNamespace,
387
+ 'secret-decryption-failed',
388
+ {},
389
+ ),
390
+ );
351
391
  const token = await mintActiveLeaseToken({jobId: job.id});
352
392
 
353
393
  const res = await app.inject({
@@ -359,7 +399,10 @@ describe('GET /runs/jobs/current/agent-runtime-config', () => {
359
399
  expect(res.statusCode).toBe(409);
360
400
  expect(res.json().code).toBe('model-provider-credentials-invalid');
361
401
  expect(captureExceptionMock).toHaveBeenCalledWith(
362
- expect.objectContaining({name: 'SecretDecryptionError'}),
402
+ expect.objectContaining({
403
+ name: 'InterModuleKnownError',
404
+ code: 'model-provider-credentials-invalid',
405
+ }),
363
406
  );
364
407
  expect(JSON.stringify(res.json())).not.toContain('sk-');
365
408
  });
@@ -394,7 +437,7 @@ async function saveWorkspaceCredential(workspaceId: string, apiKey: string) {
394
437
  providerId: 'anthropic',
395
438
  credentials: {api_key: apiKey},
396
439
  },
397
- {probe: async () => undefined},
440
+ {probe: async () => undefined, secrets},
398
441
  );
399
442
  }
400
443
 
@@ -453,7 +496,7 @@ async function createStep(params: {
453
496
  projectId: crypto.randomUUID(),
454
497
  definitionId: crypto.randomUUID(),
455
498
  model: workflowModel({jobs: {build: {steps: params.steps}}}),
456
- resolveAgentDefaults: params.resolveAgentDefaults,
499
+ resolveAgentDefaults: params.resolveAgentDefaults ?? resolveTestAgentDefaults,
457
500
  triggerPayload: {
458
501
  source: 'manual',
459
502
  event: 'fire',