@shipfox/api-workflows 5.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 +72 -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,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 {getJobById, getWorkflowRunByAttemptId} from '#db/workflow-runs.js';
4
4
  import {
5
5
  CheckoutIntentUnresolvedError,
@@ -20,15 +20,18 @@ export interface CheckoutIntent {
20
20
  * (`workflowRunId`/`workflowRunAttemptId`/`workspaceId` in the lease claim are informational).
21
21
  * Chain: job → attempt → run → project source metadata. Credential-free.
22
22
  */
23
- export async function resolveCheckoutIntent(jobId: string): Promise<CheckoutIntent> {
23
+ export async function resolveCheckoutIntent(
24
+ jobId: string,
25
+ projects: ProjectsModuleClient,
26
+ ): Promise<CheckoutIntent> {
24
27
  const job = await getJobById(jobId);
25
28
  if (!job) throw new JobNotFoundError(jobId);
26
29
 
27
30
  const run = await getWorkflowRunByAttemptId(job.workflowRunAttemptId);
28
31
  if (!run) throw new WorkflowRunNotFoundError(job.workflowRunAttemptId);
29
32
 
30
- const project = await getProjectById(run.projectId);
31
- if (!project) throw new CheckoutIntentUnresolvedError(run.projectId);
33
+ const {project} = await projects.getProjectById({projectId: run.projectId});
34
+ if (project === null) throw new CheckoutIntentUnresolvedError(run.projectId);
32
35
 
33
36
  return {
34
37
  workspaceId: project.workspaceId,
@@ -41,23 +44,47 @@ export async function resolveCheckoutIntent(jobId: string): Promise<CheckoutInte
41
44
 
42
45
  /**
43
46
  * Resolves the job's checkout intent and exchanges it for a short-lived,
44
- * scoped checkout spec. `ref` is left undefined so the provider defaults to the
45
- * repository's default branch.
47
+ * scoped checkout spec. Omitting `ref` lets the provider use the repository's
48
+ * default branch while preserving the JSON-only inter-module boundary.
46
49
  */
47
50
  export async function createJobCheckoutSpec({
48
51
  jobId,
49
- sourceControl,
52
+ integrations,
53
+ projects,
50
54
  }: {
51
55
  jobId: string;
52
- sourceControl: IntegrationSourceControlService;
53
- }): Promise<{spec: CheckoutSpec; persistCredentials: boolean}> {
54
- const intent = await resolveCheckoutIntent(jobId);
55
- const spec = await sourceControl.createCheckoutSpec({
56
+ integrations: IntegrationsModuleClient;
57
+ projects: ProjectsModuleClient;
58
+ }): Promise<{
59
+ spec: {
60
+ repositoryUrl: string;
61
+ ref: string;
62
+ credentials?: {username: string; token: string; expiresAt: Date};
63
+ gitAuthor?: {name: string; email: string};
64
+ };
65
+ persistCredentials: boolean;
66
+ }> {
67
+ const intent = await resolveCheckoutIntent(jobId, projects);
68
+ const response = await integrations.createCheckoutSpec({
56
69
  workspaceId: intent.workspaceId,
57
70
  connectionId: intent.connectionId,
58
71
  externalRepositoryId: intent.externalRepositoryId,
59
- ref: undefined,
60
72
  permissions: intent.permissions,
61
73
  });
62
- return {spec, persistCredentials: intent.persistCredentials};
74
+ const {credentials, gitAuthor, ...checkout} = response;
75
+ return {
76
+ spec: {
77
+ ...checkout,
78
+ ...(credentials
79
+ ? {
80
+ credentials: {
81
+ ...credentials,
82
+ expiresAt: new Date(credentials.expiresAt),
83
+ },
84
+ }
85
+ : {}),
86
+ ...(gitAuthor ? {gitAuthor} : {}),
87
+ },
88
+ persistCredentials: intent.persistCredentials,
89
+ };
63
90
  }
@@ -1,4 +1,4 @@
1
- import type {WorkflowModel} from '@shipfox/api-definitions';
1
+ import type {WorkflowModel} from '@shipfox/api-definitions-dto';
2
2
  import type {AgentToolMaterializationSnapshot} from '#core/agent-tools.js';
3
3
  import type {WorkflowRunStatus} from './workflow-run.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import {catalogDefaultAgentResolver} from '@shipfox/api-agent/core/resolve-agent-config';
1
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
2
2
  import type {LogOutcomeDto} from '@shipfox/api-workflows-dto';
3
3
  import {
4
4
  coerceStepOutputs,
@@ -26,6 +26,7 @@ import {
26
26
  recordWorkflowJobExecutionStepsSettled,
27
27
  recordWorkflowStepRestartEnqueued,
28
28
  } from '#metrics/instance.js';
29
+ import {createAgentDefaultsResolver} from './agent-defaults.js';
29
30
  import {defaultStepConditionTrace, explicitConditionTrace} from './condition-trace.js';
30
31
  import type {JobExecution} from './entities/job-execution.js';
31
32
  import type {PersistedEvaluationTraceEntry, Step, StepStatusReason} from './entities/step.js';
@@ -83,6 +84,7 @@ interface PendingStepDispatchParams {
83
84
  readonly jobExecution: JobExecution;
84
85
  readonly context: WorkflowEvaluationContext;
85
86
  readonly tx: Tx;
87
+ readonly agent?: AgentInterModuleClient | undefined;
86
88
  }
87
89
 
88
90
  interface ResolvePendingStepParams {
@@ -92,6 +94,7 @@ interface ResolvePendingStepParams {
92
94
  readonly attempts: Awaited<ReturnType<typeof getStepAttemptsByJobExecutionId>>;
93
95
  readonly jobs: Awaited<ReturnType<typeof getDirectDependencyJobContexts>>;
94
96
  readonly tx: Tx;
97
+ readonly agent?: AgentInterModuleClient | undefined;
95
98
  }
96
99
 
97
100
  type StepConditionOutcome =
@@ -105,6 +108,7 @@ type StepConditionOutcome =
105
108
  async function nextStepForJobExecutionInTransaction(
106
109
  jobExecutionId: string,
107
110
  tx: Tx,
111
+ agent?: AgentInterModuleClient | undefined,
108
112
  ): Promise<NextStep> {
109
113
  const steps = await getStepsByJobExecutionIdForUpdate(jobExecutionId, tx);
110
114
  const hasNoSteps = steps.length === 0;
@@ -129,7 +133,7 @@ async function nextStepForJobExecutionInTransaction(
129
133
  const attempts = await getStepAttemptsByJobExecutionId(jobExecutionId, tx);
130
134
  const jobs = await getDirectDependencyJobContexts(jobExecution.jobId, tx);
131
135
 
132
- return resolveNextPendingStep({jobExecutionId, steps, jobExecution, attempts, jobs, tx});
136
+ return resolveNextPendingStep({jobExecutionId, steps, jobExecution, attempts, jobs, tx, agent});
133
137
  }
134
138
 
135
139
  async function resolveNextPendingStep({
@@ -139,6 +143,7 @@ async function resolveNextPendingStep({
139
143
  attempts,
140
144
  jobs,
141
145
  tx,
146
+ agent,
142
147
  }: ResolvePendingStepParams): Promise<NextStep> {
143
148
  let skippedAny = false;
144
149
  let currentSteps = steps;
@@ -167,7 +172,7 @@ async function resolveNextPendingStep({
167
172
  });
168
173
  const condition = evaluateStepCondition({step: pending, context});
169
174
  if (condition.kind === 'run') {
170
- return dispatchPendingStep({jobExecutionId, pending, jobExecution, context, tx});
175
+ return dispatchPendingStep({jobExecutionId, pending, jobExecution, context, tx, agent});
171
176
  }
172
177
 
173
178
  const skipped = await markStepSkipped(
@@ -208,12 +213,13 @@ async function dispatchPendingStepWithConfigPlan({
208
213
  jobExecution,
209
214
  context,
210
215
  tx,
216
+ agent,
211
217
  }: PendingStepDispatchParams): Promise<NextStep> {
212
218
  try {
213
- const completed = completeStepDispatchConfig({
219
+ const completed = await completeStepDispatchConfig({
214
220
  step: pending,
215
221
  context,
216
- resolveAgentDefaults: catalogDefaultAgentResolver,
222
+ resolveAgentDefaults: agent ? createAgentDefaultsResolver(agent, null) : undefined,
217
223
  definitionId: jobExecution.jobId,
218
224
  });
219
225
  const marked = await dispatchStepWithCompletedConfig(
@@ -258,7 +264,7 @@ async function dispatchPendingStepWithConfigPlan({
258
264
  });
259
265
  if (status) recordWorkflowJobExecutionStepsSettled(status);
260
266
  return status === null
261
- ? nextStepForJobExecutionInTransaction(jobExecutionId, tx)
267
+ ? nextStepForJobExecutionInTransaction(jobExecutionId, tx, agent)
262
268
  : {kind: 'done', status};
263
269
  }
264
270
  }
@@ -333,6 +339,7 @@ export interface NextStepForLeasedJobExecutionParams {
333
339
  jobId: string;
334
340
  jobExecutionId: string;
335
341
  runnerSessionId: string;
342
+ agent?: AgentInterModuleClient | undefined;
336
343
  }
337
344
 
338
345
  export function nextStepForLeasedJobExecution(
@@ -342,16 +349,19 @@ export function nextStepForLeasedJobExecution(
342
349
  const leaseIsActive = await lockActiveJobExecutionLeaseForUpdate(params, tx);
343
350
  if (!leaseIsActive) throw new JobLeaseNotActiveError(params.jobExecutionId);
344
351
 
345
- return nextStepForJobExecutionInTransaction(params.jobExecutionId, tx);
352
+ return nextStepForJobExecutionInTransaction(params.jobExecutionId, tx, params.agent);
346
353
  });
347
354
  }
348
355
 
349
- export function nextStepForJob(jobId: string): Promise<NextStep> {
356
+ export function nextStepForJob(
357
+ jobId: string,
358
+ agent?: AgentInterModuleClient | undefined,
359
+ ): Promise<NextStep> {
350
360
  return withTransaction(async (tx) => {
351
361
  const jobExecution = await getLatestJobExecutionByJobId(jobId, tx);
352
362
  if (!jobExecution) throw new JobNotFoundError(jobId);
353
363
 
354
- return nextStepForJobExecutionInTransaction(jobExecution.id, tx);
364
+ return nextStepForJobExecutionInTransaction(jobExecution.id, tx, agent);
355
365
  });
356
366
  }
357
367
 
@@ -1,4 +1,4 @@
1
- import type {WorkflowModel} from '@shipfox/api-definitions';
1
+ import type {WorkflowModel} from '@shipfox/api-definitions-dto';
2
2
  import type {Job} from '../entities/job.js';
3
3
  import type {JobExecution} from '../entities/job-execution.js';
4
4
  import type {Step, StepAttempt} from '../entities/step.js';
@@ -1,4 +1,4 @@
1
- import {DEFAULT_JOB_SUCCESS} from '@shipfox/api-definitions';
1
+ import {DEFAULT_JOB_SUCCESS} from '@shipfox/api-definitions-dto';
2
2
  import {
3
3
  capTraceEntries,
4
4
  createWorkflowExpression,
@@ -1,8 +1,9 @@
1
+ import {resolveTestAgentDefaults} from '#test/fixtures/agent-inter-module.js';
1
2
  import {workflowModel} from '#test/index.js';
2
3
  import {materializeListenerExecution} from './listener-execution-materialization.js';
3
4
 
4
5
  describe('materializeListenerExecution', () => {
5
- it('fails cleanly when agent integration materialization is unresolvable', () => {
6
+ it('fails cleanly when agent integration materialization is unresolvable', async () => {
6
7
  const model = workflowModel({
7
8
  jobs: {
8
9
  review: {
@@ -16,7 +17,7 @@ describe('materializeListenerExecution', () => {
16
17
  },
17
18
  });
18
19
 
19
- const result = materializeListenerExecution({
20
+ const result = await materializeListenerExecution({
20
21
  model,
21
22
  run: {
22
23
  id: crypto.randomUUID(),
@@ -37,6 +38,7 @@ describe('materializeListenerExecution', () => {
37
38
  sequence: 1,
38
39
  triggerEvents: [],
39
40
  priorExecutions: [],
41
+ resolveAgentDefaults: resolveTestAgentDefaults,
40
42
  });
41
43
 
42
44
  expect(result).toMatchObject({
@@ -1,8 +1,5 @@
1
- import {
2
- type AgentDefaultsResolver,
3
- catalogDefaultAgentResolver,
4
- } from '@shipfox/api-agent/core/resolve-agent-config';
5
- import type {WorkflowModel} from '@shipfox/api-definitions';
1
+ import type {WorkflowModel} from '@shipfox/api-definitions-dto';
2
+ import type {AgentDefaultsResolver} from './agent-defaults.js';
6
3
  import type {
7
4
  AgentToolMaterializationContext,
8
5
  AgentToolMaterializationSnapshot,
@@ -61,9 +58,9 @@ export interface MaterializedListenerExecution {
61
58
  readonly steps: readonly MaterializedWorkflowStep[];
62
59
  }
63
60
 
64
- export function materializeListenerExecution(
61
+ export async function materializeListenerExecution(
65
62
  params: MaterializeListenerExecutionParams,
66
- ): MaterializedListenerExecution {
63
+ ): Promise<MaterializedListenerExecution> {
67
64
  const fallbackName = `${params.job.key} #${params.sequence}`;
68
65
  let executionName = fallbackName;
69
66
  let evaluationTrace: readonly PersistedEvaluationTraceEntry[] = [];
@@ -95,11 +92,11 @@ export function materializeListenerExecution(
95
92
  context,
96
93
  definitionId: params.run.definitionId,
97
94
  });
98
- steps = materializeJobExecutionSteps({
95
+ steps = await materializeJobExecutionSteps({
99
96
  model: params.model,
100
97
  job: modelJob,
101
98
  context,
102
- resolveAgentDefaults: params.resolveAgentDefaults ?? catalogDefaultAgentResolver,
99
+ resolveAgentDefaults: params.resolveAgentDefaults,
103
100
  definitionId: params.run.definitionId,
104
101
  agentToolContext: params.agentToolContext,
105
102
  agentToolSnapshot: params.agentToolSnapshot,
@@ -1,12 +1,14 @@
1
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
1
2
  import type {WorkflowDefinition} from '@shipfox/api-definitions';
3
+ import {createWorkflowModelSnapshot} from '@shipfox/api-definitions-dto';
4
+ import type {DefinitionsInterModuleClient} from '@shipfox/api-definitions-dto/inter-module';
2
5
  import {workflowModel} from '#test/index.js';
3
6
  import type {TriggerPayload} from './entities/workflow-run.js';
4
7
  import {DefinitionNotFoundError, ProjectMismatchError} from './errors.js';
5
8
  import {runWorkflow} from './run-workflow.js';
6
9
 
7
- const mockCreateWorkspaceAgentDefaultsResolver = vi.hoisted(() => vi.fn());
8
- const mockWorkspaceAgentDefaultsResolver = vi.hoisted(() =>
9
- vi.fn().mockReturnValue({
10
+ const mockResolveAgentConfig = vi.hoisted(() =>
11
+ vi.fn().mockResolvedValue({
10
12
  harness: 'pi',
11
13
  provider: 'openai',
12
14
  model: 'gpt-5.5-pro',
@@ -22,26 +24,26 @@ vi.mock('@shipfox/api-definitions', () => ({
22
24
  getDefinitionById: vi.fn(),
23
25
  }));
24
26
 
25
- vi.mock('@shipfox/api-agent/core/resolve-agent-config', () => {
26
- return {
27
- catalogDefaultAgentResolver: vi.fn().mockReturnValue({
28
- harness: 'pi',
29
- provider: 'anthropic',
30
- model: 'claude-opus-4-8',
31
- thinking: 'xhigh',
32
- }),
33
- };
34
- });
35
-
36
- vi.mock('@shipfox/api-agent/core/workspace-agent-defaults-resolver', () => {
37
- return {
38
- createWorkspaceAgentDefaultsResolver: mockCreateWorkspaceAgentDefaultsResolver,
39
- };
40
- });
41
-
42
27
  import {getDefinitionById} from '@shipfox/api-definitions';
43
28
 
44
29
  const mockGetDefinitionById = vi.mocked(getDefinitionById);
30
+ const definitions: DefinitionsInterModuleClient = {
31
+ getDefinitionForWorkflowRun: async ({definitionId}) => {
32
+ const definition = await mockGetDefinitionById(definitionId);
33
+ return {
34
+ definition:
35
+ definition === undefined
36
+ ? null
37
+ : {
38
+ id: definition.id,
39
+ projectId: definition.projectId,
40
+ name: definition.name,
41
+ model: createWorkflowModelSnapshot(definition.model),
42
+ sourceSnapshot: definition.sourceSnapshot,
43
+ },
44
+ };
45
+ },
46
+ };
45
47
 
46
48
  function buildDefinition(overrides?: Partial<WorkflowDefinition>): WorkflowDefinition {
47
49
  const model = workflowModel();
@@ -84,13 +86,15 @@ function manualPayload(): TriggerPayload {
84
86
  describe('runWorkflow', () => {
85
87
  let workspaceId: string;
86
88
  let projectId: string;
89
+ const agent: AgentInterModuleClient = {
90
+ resolveAgentConfig: mockResolveAgentConfig,
91
+ resolveRuntimeCredentials: vi.fn(),
92
+ };
87
93
 
88
94
  beforeEach(() => {
89
95
  workspaceId = crypto.randomUUID();
90
96
  projectId = crypto.randomUUID();
91
- mockCreateWorkspaceAgentDefaultsResolver.mockClear();
92
- mockCreateWorkspaceAgentDefaultsResolver.mockResolvedValue(mockWorkspaceAgentDefaultsResolver);
93
- mockWorkspaceAgentDefaultsResolver.mockClear();
97
+ mockResolveAgentConfig.mockClear();
94
98
  });
95
99
 
96
100
  test('creates a run from a valid definition with the provided manual trigger payload', async () => {
@@ -98,11 +102,12 @@ describe('runWorkflow', () => {
98
102
  mockGetDefinitionById.mockResolvedValue(definition);
99
103
  const triggerPayload = manualPayload();
100
104
 
101
- const run = await runWorkflow({
105
+ const run = await runWorkflow(definitions, {
102
106
  workspaceId,
103
107
  projectId,
104
108
  definitionId: definition.id,
105
109
  triggerPayload,
110
+ agent,
106
111
  });
107
112
 
108
113
  expect(run.id).toBeDefined();
@@ -114,7 +119,7 @@ describe('runWorkflow', () => {
114
119
  expect(run.triggerSource).toBe('manual');
115
120
  expect(run.triggerEvent).toBe('fire');
116
121
  expect(run.triggerPayload).toEqual(triggerPayload);
117
- expect(mockCreateWorkspaceAgentDefaultsResolver).not.toHaveBeenCalled();
122
+ expect(mockResolveAgentConfig).not.toHaveBeenCalled();
118
123
  });
119
124
 
120
125
  test('builds the workspace agent resolver only when the definition has an agent step', async () => {
@@ -126,21 +131,16 @@ describe('runWorkflow', () => {
126
131
  const definition = buildDefinition({projectId, model});
127
132
  mockGetDefinitionById.mockResolvedValue(definition);
128
133
 
129
- const run = await runWorkflow({
134
+ const run = await runWorkflow(definitions, {
130
135
  workspaceId,
131
136
  projectId,
132
137
  definitionId: definition.id,
133
138
  triggerPayload: manualPayload(),
139
+ agent,
134
140
  });
135
141
 
136
142
  expect(run.id).toBeDefined();
137
- expect(mockCreateWorkspaceAgentDefaultsResolver).toHaveBeenCalledWith(workspaceId);
138
- expect(mockWorkspaceAgentDefaultsResolver).toHaveBeenCalledWith({
139
- harness: undefined,
140
- provider: undefined,
141
- model: undefined,
142
- thinking: undefined,
143
- });
143
+ expect(mockResolveAgentConfig).toHaveBeenCalledWith({workspaceId, config: {}});
144
144
  });
145
145
 
146
146
  test('persists an integration trigger payload intact', async () => {
@@ -154,11 +154,12 @@ describe('runWorkflow', () => {
154
154
  data: {ref: 'main', headCommitSha: 'abc', externalRepositoryId: 'github:1'},
155
155
  };
156
156
 
157
- const run = await runWorkflow({
157
+ const run = await runWorkflow(definitions, {
158
158
  workspaceId,
159
159
  projectId,
160
160
  definitionId: definition.id,
161
161
  triggerPayload,
162
+ agent,
162
163
  });
163
164
 
164
165
  expect(run.triggerProvider).toBe('github');
@@ -172,11 +173,12 @@ describe('runWorkflow', () => {
172
173
  const definition = buildDefinition({projectId, sourceSnapshot});
173
174
  mockGetDefinitionById.mockResolvedValue(definition);
174
175
 
175
- const run = await runWorkflow({
176
+ const run = await runWorkflow(definitions, {
176
177
  workspaceId,
177
178
  projectId,
178
179
  definitionId: definition.id,
179
180
  triggerPayload: manualPayload(),
181
+ agent,
180
182
  });
181
183
 
182
184
  expect(run.sourceSnapshot).toEqual(sourceSnapshot);
@@ -188,11 +190,12 @@ describe('runWorkflow', () => {
188
190
  const unknownId = crypto.randomUUID();
189
191
 
190
192
  await expect(
191
- runWorkflow({
193
+ runWorkflow(definitions, {
192
194
  workspaceId,
193
195
  projectId,
194
196
  definitionId: unknownId,
195
197
  triggerPayload: manualPayload(),
198
+ agent,
196
199
  }),
197
200
  ).rejects.toThrow(DefinitionNotFoundError);
198
201
  });
@@ -203,11 +206,12 @@ describe('runWorkflow', () => {
203
206
  mockGetDefinitionById.mockResolvedValue(definition);
204
207
 
205
208
  await expect(
206
- runWorkflow({
209
+ runWorkflow(definitions, {
207
210
  workspaceId,
208
211
  projectId,
209
212
  definitionId: definition.id,
210
213
  triggerPayload: manualPayload(),
214
+ agent,
211
215
  }),
212
216
  ).rejects.toThrow(ProjectMismatchError);
213
217
  });
@@ -216,11 +220,12 @@ describe('runWorkflow', () => {
216
220
  const definition = buildDefinition({projectId});
217
221
  mockGetDefinitionById.mockResolvedValue(definition);
218
222
 
219
- const run = await runWorkflow({
223
+ const run = await runWorkflow(definitions, {
220
224
  workspaceId,
221
225
  projectId,
222
226
  definitionId: definition.id,
223
227
  triggerPayload: manualPayload(),
228
+ agent,
224
229
  inputs: {env: 'staging'},
225
230
  });
226
231
 
@@ -1,7 +1,11 @@
1
- import {catalogDefaultAgentResolver} from '@shipfox/api-agent/core/resolve-agent-config';
2
- import {createWorkspaceAgentDefaultsResolver} from '@shipfox/api-agent/core/workspace-agent-defaults-resolver';
3
- import {getDefinitionById} from '@shipfox/api-definitions';
1
+ import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
2
+ import {workflowModelFromSnapshot} from '@shipfox/api-definitions-dto';
3
+ import type {DefinitionsInterModuleClient} from '@shipfox/api-definitions-dto/inter-module';
4
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
5
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
6
+ import type {SecretsInterModuleClient} from '@shipfox/api-secrets-dto/inter-module';
4
7
  import {createWorkflowRun} from '#db/workflow-runs.js';
8
+ import {createAgentDefaultsResolver} from './agent-defaults.js';
5
9
  import type {TriggerPayload, WorkflowRun} from './entities/workflow-run.js';
6
10
  import {DefinitionNotFoundError, ProjectMismatchError} from './errors.js';
7
11
  import {modelHasAgentStep} from './step-config/materialize-workflow-model.js';
@@ -13,29 +17,42 @@ export interface RunWorkflowParams {
13
17
  triggerPayload: TriggerPayload;
14
18
  inputs?: Record<string, unknown> | undefined;
15
19
  triggerIdempotencyKey?: string | undefined;
20
+ integrations?: IntegrationsModuleClient | undefined;
21
+ projects?: ProjectsModuleClient | undefined;
16
22
  }
17
23
 
18
- export async function runWorkflow(params: RunWorkflowParams): Promise<WorkflowRun> {
19
- const definition = await getDefinitionById(params.definitionId);
24
+ export async function runWorkflow(
25
+ definitions: DefinitionsInterModuleClient,
26
+ params: RunWorkflowParams & {agent: AgentInterModuleClient},
27
+ options: {secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'>} = {},
28
+ ): Promise<WorkflowRun> {
29
+ const {definition} = await definitions.getDefinitionForWorkflowRun({
30
+ definitionId: params.definitionId,
31
+ });
20
32
  if (!definition) throw new DefinitionNotFoundError(params.definitionId);
21
33
 
22
34
  if (definition.projectId !== params.projectId) {
23
35
  throw new ProjectMismatchError(definition.projectId, params.projectId);
24
36
  }
25
- const resolveAgentDefaults = modelHasAgentStep(definition.model)
26
- ? await createWorkspaceAgentDefaultsResolver(params.workspaceId)
27
- : catalogDefaultAgentResolver;
37
+ const model = workflowModelFromSnapshot(definition.model);
38
+ const resolveAgentDefaults = createAgentDefaultsResolver(
39
+ params.agent,
40
+ modelHasAgentStep(model) ? params.workspaceId : null,
41
+ );
28
42
 
29
43
  return createWorkflowRun({
30
44
  workspaceId: params.workspaceId,
31
45
  projectId: params.projectId,
32
46
  definitionId: definition.id,
33
47
  name: definition.name,
34
- model: definition.model,
48
+ model,
35
49
  triggerPayload: params.triggerPayload,
36
50
  inputs: params.inputs,
37
51
  sourceSnapshot: definition.sourceSnapshot,
38
52
  triggerIdempotencyKey: params.triggerIdempotencyKey,
39
53
  resolveAgentDefaults,
54
+ secrets: options.secrets,
55
+ integrations: params.integrations,
56
+ projects: params.projects,
40
57
  });
41
58
  }
@@ -1,10 +1,3 @@
1
- import {
2
- InvalidAgentModelError,
3
- UnsupportedHarnessProviderError,
4
- UnsupportedHarnessThinkingError,
5
- UnsupportedModelProviderError,
6
- } from '@shipfox/api-agent/core/errors';
7
- import type {AgentDefaultsResolver} from '@shipfox/api-agent/core/resolve-agent-config';
8
1
  import {
9
2
  AGENT_INTEGRATION_MCP_AUTH,
10
3
  AGENT_INTEGRATION_MCP_ENDPOINT,
@@ -14,8 +7,11 @@ import {
14
7
  type AgentThinking,
15
8
  type MaterializedAgentIntegrationConfigDto,
16
9
  } from '@shipfox/api-agent-dto';
17
- import type {WorkflowModel} from '@shipfox/api-definitions';
10
+ import {agentInterModuleContract} from '@shipfox/api-agent-dto/inter-module';
11
+ import type {WorkflowModel} from '@shipfox/api-definitions-dto';
18
12
  import type {ResolvedField, SiteResolvedField} from '@shipfox/expression';
13
+ import {isInterModuleKnownError} from '@shipfox/inter-module';
14
+ import type {AgentDefaultsResolver, ResolvedAgentDefaults} from '#core/agent-defaults.js';
19
15
  import {
20
16
  type AgentToolMaterializationContext,
21
17
  type AgentToolMaterializationSnapshot,
@@ -55,7 +51,7 @@ export interface ResolveAgentStepConfigParams {
55
51
  readonly context: WorkflowEvaluationContext;
56
52
  readonly mode: StepConfigMode;
57
53
  readonly definitionId: string;
58
- readonly resolveAgentDefaults: AgentDefaultsResolver;
54
+ readonly resolveAgentDefaults?: AgentDefaultsResolver | undefined;
59
55
  readonly agentToolContext?: AgentToolMaterializationContext | undefined;
60
56
  readonly agentToolSnapshot?: AgentToolMaterializationSnapshot | null | undefined;
61
57
  }
@@ -68,7 +64,9 @@ export interface AgentStepConfig {
68
64
  readonly hasTemplates: boolean;
69
65
  }
70
66
 
71
- export function resolveAgentStepConfig(params: ResolveAgentStepConfigParams): AgentStepConfig {
67
+ export async function resolveAgentStepConfig(
68
+ params: ResolveAgentStepConfigParams,
69
+ ): Promise<AgentStepConfig> {
72
70
  const fields = resolveAgentFields(params);
73
71
  const usesAuthoredMode = params.mode === 'authored';
74
72
 
@@ -78,17 +76,17 @@ export function resolveAgentStepConfig(params: ResolveAgentStepConfigParams): Ag
78
76
  fields.model?.kind === 'residual' || fields.provider?.kind === 'residual';
79
77
  if (hasDeferredModelOrProvider) return deferredAgentStepConfig(params, fields);
80
78
 
81
- return agentStepConfigWithDefaults(params.step, params, fields);
79
+ return await agentStepConfigWithDefaults(params.step, params, fields);
82
80
  }
83
81
 
84
- export function completeAgentConfig(params: {
82
+ export async function completeAgentConfig(params: {
85
83
  readonly config: Record<string, unknown>;
86
84
  readonly plan: StepConfigDispatchPlan;
87
85
  readonly context: WorkflowEvaluationContext;
88
- readonly resolveAgentDefaults: AgentDefaultsResolver;
86
+ readonly resolveAgentDefaults?: AgentDefaultsResolver | undefined;
89
87
  readonly definitionId: string;
90
88
  readonly trace: PersistedEvaluationTraceEntry[];
91
- }): void {
89
+ }): Promise<void> {
92
90
  const agent = params.plan.agent;
93
91
  if (agent === undefined) return;
94
92
 
@@ -117,7 +115,7 @@ export function completeAgentConfig(params: {
117
115
  params,
118
116
  });
119
117
 
120
- const defaults = completeAgentDefaults({
118
+ const defaults = await completeAgentDefaults({
121
119
  harness: agent.harness ?? readConfigHarness(params.config),
122
120
  provider,
123
121
  model,
@@ -159,16 +157,18 @@ function completeAgentField(args: {
159
157
  return resolved.value;
160
158
  }
161
159
 
162
- export function completeAgentDefaults(params: {
160
+ export async function completeAgentDefaults(params: {
163
161
  readonly harness: WorkflowModelAgentStep['harness'] | undefined;
164
162
  readonly provider: string | undefined;
165
163
  readonly model: string | undefined;
166
164
  readonly thinking: AgentThinking | undefined;
167
- readonly resolveAgentDefaults: AgentDefaultsResolver;
165
+ readonly resolveAgentDefaults?: AgentDefaultsResolver | undefined;
168
166
  readonly definitionId: string;
169
- }): ReturnType<AgentDefaultsResolver> {
167
+ }): Promise<ResolvedAgentDefaults> {
168
+ if (!params.resolveAgentDefaults) throw new Error('Agent defaults resolver is required');
169
+
170
170
  try {
171
- return params.resolveAgentDefaults({
171
+ return await params.resolveAgentDefaults({
172
172
  harness: params.harness,
173
173
  provider: params.provider,
174
174
  model: params.model,
@@ -176,10 +176,8 @@ export function completeAgentDefaults(params: {
176
176
  });
177
177
  } catch (error) {
178
178
  if (
179
- error instanceof UnsupportedModelProviderError ||
180
- error instanceof UnsupportedHarnessProviderError ||
181
- error instanceof UnsupportedHarnessThinkingError ||
182
- error instanceof InvalidAgentModelError
179
+ isInterModuleKnownError(agentInterModuleContract.methods.resolveAgentConfig, error) &&
180
+ error.code === 'agent-config-invalid'
183
181
  ) {
184
182
  throw new AgentConfigUnresolvableError(params.definitionId, {cause: error});
185
183
  }
@@ -273,16 +271,16 @@ function deferredAgentStepConfig(
273
271
  };
274
272
  }
275
273
 
276
- function agentStepConfigWithDefaults(
274
+ async function agentStepConfigWithDefaults(
277
275
  step: WorkflowModelAgentStep,
278
276
  params: ResolveAgentStepConfigParams,
279
277
  fields: AgentFieldResolutions,
280
- ): AgentStepConfig {
278
+ ): Promise<AgentStepConfig> {
281
279
  const providerValue = frozenFieldValue(fields.provider);
282
280
  const modelValue = frozenFieldValue(fields.model);
283
281
  const promptIsDeferred = fields.prompt.kind === 'residual';
284
282
 
285
- const resolved = completeAgentDefaults({
283
+ const resolved = await completeAgentDefaults({
286
284
  harness: step.harness,
287
285
  provider: providerValue,
288
286
  model: modelValue,