@shipfox/api-workflows 7.1.0 → 9.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 (153) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +80 -0
  3. package/dist/core/agent-defaults.d.ts +2 -1
  4. package/dist/core/agent-defaults.d.ts.map +1 -1
  5. package/dist/core/agent-defaults.js.map +1 -1
  6. package/dist/core/agent-tools.d.ts +5 -2
  7. package/dist/core/agent-tools.d.ts.map +1 -1
  8. package/dist/core/agent-tools.js.map +1 -1
  9. package/dist/core/checkout.d.ts +2 -2
  10. package/dist/core/checkout.d.ts.map +1 -1
  11. package/dist/core/checkout.js.map +1 -1
  12. package/dist/core/entities/step.d.ts +2 -1
  13. package/dist/core/entities/step.d.ts.map +1 -1
  14. package/dist/core/entities/step.js.map +1 -1
  15. package/dist/core/errors.d.ts +0 -4
  16. package/dist/core/errors.d.ts.map +1 -1
  17. package/dist/core/errors.js +0 -6
  18. package/dist/core/errors.js.map +1 -1
  19. package/dist/core/job-execution.d.ts +0 -2
  20. package/dist/core/job-execution.d.ts.map +1 -1
  21. package/dist/core/job-execution.js +3 -7
  22. package/dist/core/job-execution.js.map +1 -1
  23. package/dist/core/run-workflow.d.ts +2 -2
  24. package/dist/core/run-workflow.d.ts.map +1 -1
  25. package/dist/core/run-workflow.js.map +1 -1
  26. package/dist/core/step-config/agent.d.ts +1 -1
  27. package/dist/core/step-config/agent.d.ts.map +1 -1
  28. package/dist/core/step-config/agent.js.map +1 -1
  29. package/dist/db/job-listeners.d.ts +2 -2
  30. package/dist/db/job-listeners.d.ts.map +1 -1
  31. package/dist/db/job-listeners.js.map +1 -1
  32. package/dist/db/workflow-runs/job-executions.d.ts +0 -5
  33. package/dist/db/workflow-runs/job-executions.d.ts.map +1 -1
  34. package/dist/db/workflow-runs/job-executions.js +0 -7
  35. package/dist/db/workflow-runs/job-executions.js.map +1 -1
  36. package/dist/db/workflow-runs/run-create.d.ts +2 -2
  37. package/dist/db/workflow-runs/run-create.d.ts.map +1 -1
  38. package/dist/db/workflow-runs/run-create.js.map +1 -1
  39. package/dist/db/workflow-runs.d.ts +1 -1
  40. package/dist/db/workflow-runs.d.ts.map +1 -1
  41. package/dist/db/workflow-runs.js +1 -1
  42. package/dist/db/workflow-runs.js.map +1 -1
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +2 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/presentation/inter-module.d.ts +2 -2
  48. package/dist/presentation/inter-module.d.ts.map +1 -1
  49. package/dist/presentation/inter-module.js +2 -1
  50. package/dist/presentation/inter-module.js.map +1 -1
  51. package/dist/presentation/routes/cancel-run.d.ts +1 -1
  52. package/dist/presentation/routes/cancel-run.d.ts.map +1 -1
  53. package/dist/presentation/routes/cancel-run.js.map +1 -1
  54. package/dist/presentation/routes/checkout-token.d.ts +2 -2
  55. package/dist/presentation/routes/checkout-token.d.ts.map +1 -1
  56. package/dist/presentation/routes/checkout-token.js +1 -1
  57. package/dist/presentation/routes/checkout-token.js.map +1 -1
  58. package/dist/presentation/routes/get-run-aggregates.d.ts +1 -1
  59. package/dist/presentation/routes/get-run-aggregates.d.ts.map +1 -1
  60. package/dist/presentation/routes/get-run-aggregates.js.map +1 -1
  61. package/dist/presentation/routes/get-run.d.ts +1 -1
  62. package/dist/presentation/routes/get-run.d.ts.map +1 -1
  63. package/dist/presentation/routes/get-run.js.map +1 -1
  64. package/dist/presentation/routes/index.d.ts +2 -2
  65. package/dist/presentation/routes/index.d.ts.map +1 -1
  66. package/dist/presentation/routes/index.js.map +1 -1
  67. package/dist/presentation/routes/list-run-attempts.d.ts +1 -1
  68. package/dist/presentation/routes/list-run-attempts.d.ts.map +1 -1
  69. package/dist/presentation/routes/list-run-attempts.js.map +1 -1
  70. package/dist/presentation/routes/list-runs.d.ts +1 -1
  71. package/dist/presentation/routes/list-runs.d.ts.map +1 -1
  72. package/dist/presentation/routes/list-runs.js.map +1 -1
  73. package/dist/presentation/routes/next-step.d.ts.map +1 -1
  74. package/dist/presentation/routes/next-step.js +11 -8
  75. package/dist/presentation/routes/next-step.js.map +1 -1
  76. package/dist/presentation/routes/project-access.d.ts +1 -1
  77. package/dist/presentation/routes/project-access.d.ts.map +1 -1
  78. package/dist/presentation/routes/project-access.js.map +1 -1
  79. package/dist/presentation/routes/require-accessible-run.d.ts +1 -1
  80. package/dist/presentation/routes/require-accessible-run.d.ts.map +1 -1
  81. package/dist/presentation/routes/require-accessible-run.js.map +1 -1
  82. package/dist/presentation/routes/rerun-run.d.ts +1 -1
  83. package/dist/presentation/routes/rerun-run.d.ts.map +1 -1
  84. package/dist/presentation/routes/rerun-run.js.map +1 -1
  85. package/dist/temporal/activities/index.d.ts +2 -2
  86. package/dist/temporal/activities/index.d.ts.map +1 -1
  87. package/dist/temporal/activities/index.js.map +1 -1
  88. package/dist/temporal/activities/orchestration-activities.d.ts +2 -2
  89. package/dist/temporal/activities/orchestration-activities.d.ts.map +1 -1
  90. package/dist/temporal/activities/orchestration-activities.js.map +1 -1
  91. package/dist/tsconfig.test.tsbuildinfo +1 -1
  92. package/package.json +26 -28
  93. package/src/core/agent-defaults.ts +2 -1
  94. package/src/core/agent-tool-capability-warning.test.ts +26 -56
  95. package/src/core/agent-tools.ts +9 -7
  96. package/src/core/checkout.test.ts +2 -2
  97. package/src/core/checkout.ts +2 -2
  98. package/src/core/entities/step.ts +1 -2
  99. package/src/core/errors.ts +0 -7
  100. package/src/core/job-execution.ts +3 -10
  101. package/src/core/run-workflow.test.ts +22 -55
  102. package/src/core/run-workflow.ts +2 -2
  103. package/src/core/step-config/agent.ts +1 -1
  104. package/src/core/step-config/materialize-job-execution-steps.test.ts +1 -2
  105. package/src/core/step-config/materialize-workflow-model.test.ts +10 -13
  106. package/src/db/job-listeners.ts +2 -2
  107. package/src/db/workflow-runs/job-executions.ts +0 -21
  108. package/src/db/workflow-runs/run-create.test.ts +30 -23
  109. package/src/db/workflow-runs/run-create.ts +2 -2
  110. package/src/db/workflow-runs.ts +0 -1
  111. package/src/index.ts +3 -3
  112. package/src/presentation/dto/checkout-token.test.ts +7 -1
  113. package/src/presentation/inter-module.ts +4 -7
  114. package/src/presentation/routes/agent-runtime-config.test.ts +40 -132
  115. package/src/presentation/routes/cancel-run.test.ts +1 -1
  116. package/src/presentation/routes/cancel-run.ts +1 -1
  117. package/src/presentation/routes/checkout-token.test.ts +4 -37
  118. package/src/presentation/routes/checkout-token.ts +2 -2
  119. package/src/presentation/routes/get-run-aggregates.test.ts +1 -1
  120. package/src/presentation/routes/get-run-aggregates.ts +1 -1
  121. package/src/presentation/routes/get-run.test.ts +1 -1
  122. package/src/presentation/routes/get-run.ts +1 -1
  123. package/src/presentation/routes/get-step-secrets.test.ts +2 -2
  124. package/src/presentation/routes/index.test.ts +3 -3
  125. package/src/presentation/routes/index.ts +2 -2
  126. package/src/presentation/routes/list-run-attempts.test.ts +1 -1
  127. package/src/presentation/routes/list-run-attempts.ts +1 -1
  128. package/src/presentation/routes/list-runs.test.ts +1 -1
  129. package/src/presentation/routes/list-runs.ts +1 -1
  130. package/src/presentation/routes/next-step.test.ts +27 -69
  131. package/src/presentation/routes/next-step.ts +9 -5
  132. package/src/presentation/routes/project-access.ts +1 -1
  133. package/src/presentation/routes/report-step.test.ts +2 -3
  134. package/src/presentation/routes/require-accessible-run.ts +1 -1
  135. package/src/presentation/routes/rerun-run.test.ts +1 -1
  136. package/src/presentation/routes/rerun-run.ts +1 -1
  137. package/src/temporal/activities/index.ts +2 -2
  138. package/src/temporal/activities/orchestration-activities.ts +2 -2
  139. package/test/factories/workflow-model.ts +3 -1
  140. package/test/fixtures/active-lease-token.ts +5 -32
  141. package/test/fixtures/agent-inter-module.ts +32 -1
  142. package/test/fixtures/auth-inter-module.ts +2 -13
  143. package/test/fixtures/lease-token.ts +43 -29
  144. package/test/fixtures/projects-inter-module.ts +1 -1
  145. package/test/fixtures/runners-inter-module.ts +40 -48
  146. package/test/globalSetup.ts +0 -38
  147. package/test/setup.ts +2 -0
  148. package/tsconfig.build.tsbuildinfo +1 -1
  149. package/dist/db/runner-lease-table.d.ts +0 -469
  150. package/dist/db/runner-lease-table.d.ts.map +0 -1
  151. package/dist/db/runner-lease-table.js +0 -43
  152. package/dist/db/runner-lease-table.js.map +0 -1
  153. package/src/db/runner-lease-table.ts +0 -39
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-workflows",
3
3
  "license": "MIT",
4
- "version": "7.1.0",
4
+ "version": "9.0.1",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -11,10 +11,6 @@
11
11
  "type": "module",
12
12
  "main": "dist/index.js",
13
13
  "types": "dist/index.d.ts",
14
- "imports": {
15
- "#test/*": "./test/*",
16
- "#*": "./dist/*"
17
- },
18
14
  "exports": {
19
15
  ".": {
20
16
  "types": "./dist/index.d.ts",
@@ -26,29 +22,31 @@
26
22
  "@temporalio/workflow": "1.18.1",
27
23
  "drizzle-orm": "^0.45.2",
28
24
  "zod": "^4.4.3",
29
- "@shipfox/api-auth-context": "7.1.0",
30
- "@shipfox/api-auth-dto": "7.1.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-runners": "7.1.0",
37
- "@shipfox/api-projects": "7.1.0",
38
- "@shipfox/api-secrets-dto": "6.0.0",
39
- "@shipfox/api-workflows-dto": "6.0.0",
40
- "@shipfox/api-runners-dto": "7.0.1",
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.2.0",
45
- "@shipfox/node-fastify": "0.3.0",
46
- "@shipfox/node-module": "0.5.0",
47
- "@shipfox/node-opentelemetry": "0.6.0",
48
- "@shipfox/node-outbox": "0.2.4",
49
- "@shipfox/node-postgres": "0.4.2",
50
- "@shipfox/node-temporal": "0.4.0",
51
- "@shipfox/runner-labels": "0.1.1"
25
+ "@shipfox/api-auth-dto": "9.0.1",
26
+ "@shipfox/api-agent-dto": "9.0.1",
27
+ "@shipfox/annotations-dto": "9.0.1",
28
+ "@shipfox/api-auth-context": "9.0.1",
29
+ "@shipfox/api-definitions-dto": "9.0.1",
30
+ "@shipfox/api-projects-dto": "9.0.1",
31
+ "@shipfox/api-secrets-dto": "9.0.1",
32
+ "@shipfox/api-workflows-dto": "9.0.1",
33
+ "@shipfox/api-integration-core-dto": "9.0.1",
34
+ "@shipfox/inter-module": "0.2.1",
35
+ "@shipfox/api-runners-dto": "9.0.1",
36
+ "@shipfox/expression": "1.1.4",
37
+ "@shipfox/node-error-monitoring": "0.2.1",
38
+ "@shipfox/node-fastify": "0.3.1",
39
+ "@shipfox/node-opentelemetry": "0.6.1",
40
+ "@shipfox/node-outbox": "0.2.5",
41
+ "@shipfox/node-postgres": "0.4.3",
42
+ "@shipfox/node-module": "1.0.0",
43
+ "@shipfox/node-temporal": "0.4.1",
44
+ "@shipfox/runner-labels": "0.1.2",
45
+ "@shipfox/node-drizzle": "0.3.3",
46
+ "@shipfox/workflow-document": "2.1.2"
47
+ },
48
+ "imports": {
49
+ "#*": "./dist/*"
52
50
  },
53
51
  "scripts": {
54
52
  "build": "shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js",
@@ -1,5 +1,6 @@
1
- import type {AgentThinking, Harness, ModelProviderRef} from '@shipfox/api-agent-dto';
1
+ import type {ModelProviderRef} from '@shipfox/api-agent-dto';
2
2
  import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
3
+ import type {AgentThinking, Harness} from '@shipfox/workflow-document';
3
4
 
4
5
  export interface AgentDefaultsInput {
5
6
  readonly harness?: Harness | undefined;
@@ -1,8 +1,7 @@
1
1
  import type {AnnotationsInterModuleClient} from '@shipfox/annotations-dto/inter-module';
2
- import type {JobLeaseTokenClaims} from '@shipfox/api-auth';
3
- import {sql} from 'drizzle-orm';
4
- import {db} from '#db/db.js';
5
- import {runnersTestClient} from '#test/fixtures/runners-inter-module.js';
2
+ import type {JobLeaseTokenClaims} from '@shipfox/api-auth-dto';
3
+ import type {RunnersInterModuleClient} from '@shipfox/api-runners-dto/inter-module';
4
+ import {runnersTestClient, setRunnerToolCapabilities} from '#test/fixtures/runners-inter-module.js';
6
5
  import {warnAgentToolCapabilityMismatchOnDispatch as warnAgentToolCapabilityMismatchOnDispatchImpl} from './agent-tool-capability-warning.js';
7
6
  import type {Step} from './entities/step.js';
8
7
 
@@ -86,45 +85,20 @@ function agentStep(params: Partial<Step> = {}): Step {
86
85
  };
87
86
  }
88
87
 
89
- async function insertRunnerSession(params: {
88
+ function setRunnerSessionCapabilities(params: {
90
89
  runnerSessionId: string;
91
90
  workspaceId: string;
92
- toolCapabilities: Record<string, unknown> | null;
91
+ toolCapabilities:
92
+ | Awaited<
93
+ ReturnType<RunnersInterModuleClient['getEffectiveRunnerToolCapabilities']>
94
+ >['capabilities']
95
+ | null;
93
96
  reportedAt?: 'fresh' | 'stale' | 'missing';
94
- }): Promise<void> {
95
- const reportedAt =
96
- params.reportedAt === 'missing'
97
- ? sql`NULL`
98
- : params.reportedAt === 'stale'
99
- ? sql`now() - interval '1 hour'`
100
- : sql`now()`;
101
- const toolCapabilities =
102
- params.toolCapabilities === null
103
- ? sql`NULL`
104
- : sql`${JSON.stringify(params.toolCapabilities)}::jsonb`;
105
-
106
- await db().execute(sql`
107
- INSERT INTO runners_runner_sessions (
108
- id,
109
- workspace_id,
110
- scope,
111
- registration_token_id,
112
- registration_token_kind,
113
- labels,
114
- tool_capabilities,
115
- tool_capabilities_reported_at
116
- )
117
- VALUES (
118
- ${params.runnerSessionId},
119
- ${params.workspaceId},
120
- 'workspace',
121
- ${crypto.randomUUID()},
122
- 'manual',
123
- ARRAY['linux'],
124
- ${toolCapabilities},
125
- ${reportedAt}
126
- )
127
- `);
97
+ }): void {
98
+ setRunnerToolCapabilities(params.runnerSessionId, {
99
+ capabilities: params.toolCapabilities === null ? {harnesses: {}} : params.toolCapabilities,
100
+ reportFresh: params.reportedAt !== 'missing' && params.reportedAt !== 'stale',
101
+ });
128
102
  }
129
103
 
130
104
  function annotationsFor(jobExecutionId: string): Array<{context: string; body: string}> {
@@ -138,7 +112,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
138
112
  it('writes a warning when the matched runner advertised a set without requested tools', async () => {
139
113
  const identity = lease();
140
114
  const step = agentStep({jobExecutionId: identity.jobExecutionId});
141
- await insertRunnerSession({
115
+ setRunnerSessionCapabilities({
142
116
  runnerSessionId: identity.runnerSessionId,
143
117
  workspaceId: identity.workspaceId,
144
118
  toolCapabilities: {harnesses: {pi: {tools: ['read']}}},
@@ -156,7 +130,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
156
130
  it('writes unknown wording when capabilities are missing', async () => {
157
131
  const identity = lease();
158
132
  const step = agentStep({jobExecutionId: identity.jobExecutionId});
159
- await insertRunnerSession({
133
+ setRunnerSessionCapabilities({
160
134
  runnerSessionId: identity.runnerSessionId,
161
135
  workspaceId: identity.workspaceId,
162
136
  toolCapabilities: null,
@@ -173,7 +147,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
173
147
  it('writes missing-harness wording when fresh capabilities omit the harness', async () => {
174
148
  const identity = lease();
175
149
  const step = agentStep({jobExecutionId: identity.jobExecutionId});
176
- await insertRunnerSession({
150
+ setRunnerSessionCapabilities({
177
151
  runnerSessionId: identity.runnerSessionId,
178
152
  workspaceId: identity.workspaceId,
179
153
  toolCapabilities: {harnesses: {claude: {tools: ['read', 'web_search']}}},
@@ -199,7 +173,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
199
173
  prompt: 'Fix it.',
200
174
  },
201
175
  });
202
- await insertRunnerSession({
176
+ setRunnerSessionCapabilities({
203
177
  runnerSessionId: identity.runnerSessionId,
204
178
  workspaceId: identity.workspaceId,
205
179
  toolCapabilities: {harnesses: {pi: {tools: ['read']}}},
@@ -214,20 +188,16 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
214
188
  it('removes an existing warning when a later dispatch has all requested tools', async () => {
215
189
  const identity = lease();
216
190
  const step = agentStep({jobExecutionId: identity.jobExecutionId});
217
- await insertRunnerSession({
191
+ setRunnerSessionCapabilities({
218
192
  runnerSessionId: identity.runnerSessionId,
219
193
  workspaceId: identity.workspaceId,
220
194
  toolCapabilities: {harnesses: {pi: {tools: ['read']}}},
221
195
  });
222
196
  await warnAgentToolCapabilityMismatchOnDispatch({leaseIdentity: identity, step});
223
- await db().execute(sql`
224
- UPDATE runners_runner_sessions
225
- SET tool_capabilities = ${JSON.stringify({
226
- harnesses: {pi: {tools: ['read', 'web_search']}},
227
- })}::jsonb,
228
- tool_capabilities_reported_at = now()
229
- WHERE id = ${identity.runnerSessionId}
230
- `);
197
+ setRunnerToolCapabilities(identity.runnerSessionId, {
198
+ capabilities: {harnesses: {pi: {tools: ['read', 'web_search']}}},
199
+ reportFresh: true,
200
+ });
231
201
 
232
202
  await warnAgentToolCapabilityMismatchOnDispatch({leaseIdentity: identity, step});
233
203
 
@@ -247,7 +217,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
247
217
  prompt: 'Fix it.',
248
218
  },
249
219
  });
250
- await insertRunnerSession({
220
+ setRunnerSessionCapabilities({
251
221
  runnerSessionId: identity.runnerSessionId,
252
222
  workspaceId: identity.workspaceId,
253
223
  toolCapabilities: null,
@@ -265,7 +235,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
265
235
  type: 'run',
266
236
  config: {run: 'echo ok'},
267
237
  });
268
- await insertRunnerSession({
238
+ setRunnerSessionCapabilities({
269
239
  runnerSessionId: identity.runnerSessionId,
270
240
  workspaceId: identity.workspaceId,
271
241
  toolCapabilities: null,
@@ -290,7 +260,7 @@ describe('warnAgentToolCapabilityMismatchOnDispatch', () => {
290
260
  prompt: 'Fix it.',
291
261
  },
292
262
  });
293
- await insertRunnerSession({
263
+ setRunnerSessionCapabilities({
294
264
  runnerSessionId: identity.runnerSessionId,
295
265
  workspaceId: identity.workspaceId,
296
266
  toolCapabilities: {harnesses: {pi: {tools: []}}},
@@ -3,18 +3,20 @@ import type {
3
3
  MaterializedAgentIntegrationToolConfigDto,
4
4
  } from '@shipfox/api-agent-dto';
5
5
  import type {WorkflowModel} from '@shipfox/api-definitions-dto';
6
- import type {
7
- AgentToolCatalogEntry,
8
- AgentToolCatalogMethod,
9
- IntegrationProviderKind,
10
- IntegrationsModuleClient,
11
- } from '@shipfox/api-integration-core-dto';
12
- import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
6
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
7
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
13
8
  import {AgentIntegrationMaterializationError} from './errors.js';
14
9
 
15
10
  type WorkflowModelJob = WorkflowModel['jobs'][number];
16
11
  type WorkflowModelAgentStep = Extract<WorkflowModelJob['steps'][number], {kind: 'agent'}>;
17
12
  type WorkflowModelStepIntegration = NonNullable<WorkflowModelAgentStep['integrations']>[number];
13
+ type IntegrationsAgentToolsContext = Awaited<
14
+ ReturnType<IntegrationsModuleClient['getAgentToolsContext']>
15
+ >;
16
+ export type AgentToolCatalogEntry =
17
+ IntegrationsAgentToolsContext['catalogs'][number]['tools'][number];
18
+ type AgentToolCatalogMethod = NonNullable<AgentToolCatalogEntry['methods']>[number];
19
+ type IntegrationProviderKind = IntegrationsAgentToolsContext['catalogs'][number]['provider'];
18
20
  type AgentToolCatalogs = ReadonlyMap<IntegrationProviderKind, readonly AgentToolCatalogEntry[]>;
19
21
  type WorkspaceConnectionSnapshot = ReadonlyMap<
20
22
  string,
@@ -1,5 +1,5 @@
1
- import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
2
- import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
1
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
2
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
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';
@@ -1,5 +1,5 @@
1
- import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
2
- import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
1
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
2
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
3
3
  import {getJobById, getWorkflowRunByAttemptId} from '#db/workflow-runs.js';
4
4
  import {
5
5
  CheckoutIntentUnresolvedError,
@@ -1,7 +1,5 @@
1
1
  import type {
2
2
  AgentIntegrationMcpServerConfigDto,
3
- AgentThinking,
4
- Harness,
5
3
  MaterializedAgentIntegrationConfigDto,
6
4
  } from '@shipfox/api-agent-dto';
7
5
  import type {
@@ -10,6 +8,7 @@ import type {
10
8
  ResolvedField,
11
9
  WorkflowExpression,
12
10
  } from '@shipfox/expression';
11
+ import type {AgentThinking, Harness} from '@shipfox/workflow-document';
13
12
  import type {InterpolationUnresolvableField} from '../errors.js';
14
13
 
15
14
  export type StepStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'skipped';
@@ -104,13 +104,6 @@ export class JobNotFoundError extends Error {
104
104
  }
105
105
  }
106
106
 
107
- export class JobLeaseNotActiveError extends Error {
108
- constructor(readonly jobExecutionId: string) {
109
- super(`Job lease is no longer active: ${jobExecutionId}`);
110
- this.name = 'JobLeaseNotActiveError';
111
- }
112
- }
113
-
114
107
  export class InvalidJobRunnerLabelsError extends Error {
115
108
  constructor(readonly labels: readonly string[]) {
116
109
  super(`Job runner labels are invalid: ${labels.join(', ')}`);
@@ -16,7 +16,6 @@ import {
16
16
  getStepAttemptsByJobExecutionId,
17
17
  getStepsByJobExecutionIdForUpdate,
18
18
  insertRunningStepAttempt,
19
- lockActiveJobExecutionLeaseForUpdate,
20
19
  markStepRunning,
21
20
  markStepSkipped,
22
21
  settleJobFailed,
@@ -33,7 +32,6 @@ import type {PersistedEvaluationTraceEntry, Step, StepStatusReason} from './enti
33
32
  import {
34
33
  AgentConfigUnresolvableError,
35
34
  InterpolationUnresolvableError,
36
- JobLeaseNotActiveError,
37
35
  JobNotFoundError,
38
36
  StepAttemptAheadError,
39
37
  StepNotFoundError,
@@ -336,21 +334,16 @@ function dispatchConfigError(error: DispatchConfigError): Record<string, unknown
336
334
  }
337
335
 
338
336
  export interface NextStepForLeasedJobExecutionParams {
339
- jobId: string;
340
337
  jobExecutionId: string;
341
- runnerSessionId: string;
342
338
  agent?: AgentInterModuleClient | undefined;
343
339
  }
344
340
 
345
341
  export function nextStepForLeasedJobExecution(
346
342
  params: NextStepForLeasedJobExecutionParams,
347
343
  ): Promise<NextStep> {
348
- return withTransaction(async (tx) => {
349
- const leaseIsActive = await lockActiveJobExecutionLeaseForUpdate(params, tx);
350
- if (!leaseIsActive) throw new JobLeaseNotActiveError(params.jobExecutionId);
351
-
352
- return nextStepForJobExecutionInTransaction(params.jobExecutionId, tx, params.agent);
353
- });
344
+ return withTransaction((tx) =>
345
+ nextStepForJobExecutionInTransaction(params.jobExecutionId, tx, params.agent),
346
+ );
354
347
  }
355
348
 
356
349
  export function nextStepForJob(
@@ -1,7 +1,7 @@
1
1
  import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
2
- import type {WorkflowDefinition} from '@shipfox/api-definitions';
3
- import {createWorkflowModelSnapshot} from '@shipfox/api-definitions-dto';
2
+ import {createWorkflowModelSnapshot, type WorkflowModel} from '@shipfox/api-definitions-dto';
4
3
  import type {DefinitionsInterModuleClient} from '@shipfox/api-definitions-dto/inter-module';
4
+ import {agentValidationCatalog} from '#test/fixtures/agent-inter-module.js';
5
5
  import {workflowModel} from '#test/index.js';
6
6
  import type {TriggerPayload} from './entities/workflow-run.js';
7
7
  import {DefinitionNotFoundError, ProjectMismatchError} from './errors.js';
@@ -16,61 +16,26 @@ const mockResolveAgentConfig = vi.hoisted(() =>
16
16
  }),
17
17
  );
18
18
 
19
- vi.mock('@shipfox/api-definitions', () => ({
20
- DEFAULT_JOB_CHECKOUT: {
21
- permissions: {contents: 'read'},
22
- persistCredentials: true,
23
- },
24
- getDefinitionById: vi.fn(),
25
- }));
19
+ type DefinitionForWorkflowRun = NonNullable<
20
+ Awaited<ReturnType<DefinitionsInterModuleClient['getDefinitionForWorkflowRun']>>['definition']
21
+ >;
26
22
 
27
- import {getDefinitionById} from '@shipfox/api-definitions';
28
-
29
- const mockGetDefinitionById = vi.mocked(getDefinitionById);
23
+ let definitionResponse: DefinitionForWorkflowRun | null = null;
30
24
  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
- },
25
+ getDefinitionForWorkflowRun: async () => ({definition: definitionResponse}),
46
26
  };
47
27
 
48
- function buildDefinition(overrides?: Partial<WorkflowDefinition>): WorkflowDefinition {
49
- const model = workflowModel();
50
- const document = {
51
- name: model.name,
52
- jobs: {
53
- build: {steps: [{run: 'echo hello'}]},
54
- },
55
- };
28
+ function buildDefinition(
29
+ overrides: Partial<Omit<DefinitionForWorkflowRun, 'model'>> & {model?: WorkflowModel} = {},
30
+ ): DefinitionForWorkflowRun {
31
+ const {model = workflowModel(), ...definitionOverrides} = overrides;
56
32
  return {
57
33
  id: crypto.randomUUID(),
58
34
  projectId: crypto.randomUUID(),
59
- configPath: '.shipfox/workflows/test.yml',
60
- source: 'manual',
61
- sha: null,
62
- ref: null,
63
35
  name: 'Test Workflow',
64
- definition: document,
65
- document,
66
- model,
36
+ model: createWorkflowModelSnapshot(model),
67
37
  sourceSnapshot: null,
68
- contentHash: null,
69
- fetchedAt: new Date(),
70
- createdAt: new Date(),
71
- updatedAt: new Date(),
72
- deletedAt: null,
73
- ...overrides,
38
+ ...definitionOverrides,
74
39
  };
75
40
  }
76
41
 
@@ -87,6 +52,7 @@ describe('runWorkflow', () => {
87
52
  let workspaceId: string;
88
53
  let projectId: string;
89
54
  const agent: AgentInterModuleClient = {
55
+ getValidationCatalog: vi.fn().mockResolvedValue(agentValidationCatalog),
90
56
  resolveAgentConfig: mockResolveAgentConfig,
91
57
  resolveRuntimeCredentials: vi.fn(),
92
58
  };
@@ -95,11 +61,12 @@ describe('runWorkflow', () => {
95
61
  workspaceId = crypto.randomUUID();
96
62
  projectId = crypto.randomUUID();
97
63
  mockResolveAgentConfig.mockClear();
64
+ definitionResponse = null;
98
65
  });
99
66
 
100
67
  test('creates a run from a valid definition with the provided manual trigger payload', async () => {
101
68
  const definition = buildDefinition({projectId});
102
- mockGetDefinitionById.mockResolvedValue(definition);
69
+ definitionResponse = definition;
103
70
  const triggerPayload = manualPayload();
104
71
 
105
72
  const run = await runWorkflow(definitions, {
@@ -129,7 +96,7 @@ describe('runWorkflow', () => {
129
96
  },
130
97
  });
131
98
  const definition = buildDefinition({projectId, model});
132
- mockGetDefinitionById.mockResolvedValue(definition);
99
+ definitionResponse = definition;
133
100
 
134
101
  const run = await runWorkflow(definitions, {
135
102
  workspaceId,
@@ -145,7 +112,7 @@ describe('runWorkflow', () => {
145
112
 
146
113
  test('persists an integration trigger payload intact', async () => {
147
114
  const definition = buildDefinition({projectId});
148
- mockGetDefinitionById.mockResolvedValue(definition);
115
+ definitionResponse = definition;
149
116
  const triggerPayload: TriggerPayload = {
150
117
  provider: 'github',
151
118
  source: 'github_acme',
@@ -171,7 +138,7 @@ describe('runWorkflow', () => {
171
138
  test('creates the run with the definition source snapshot', async () => {
172
139
  const sourceSnapshot = {content: 'name: Test Workflow\njobs: {}\n', format: 'yaml'} as const;
173
140
  const definition = buildDefinition({projectId, sourceSnapshot});
174
- mockGetDefinitionById.mockResolvedValue(definition);
141
+ definitionResponse = definition;
175
142
 
176
143
  const run = await runWorkflow(definitions, {
177
144
  workspaceId,
@@ -185,7 +152,7 @@ describe('runWorkflow', () => {
185
152
  });
186
153
 
187
154
  test('throws DefinitionNotFoundError for unknown definition', async () => {
188
- mockGetDefinitionById.mockResolvedValue(undefined);
155
+ definitionResponse = null;
189
156
 
190
157
  const unknownId = crypto.randomUUID();
191
158
 
@@ -203,7 +170,7 @@ describe('runWorkflow', () => {
203
170
  test('throws ProjectMismatchError when definition.projectId does not match', async () => {
204
171
  const otherProjectId = crypto.randomUUID();
205
172
  const definition = buildDefinition({projectId: otherProjectId});
206
- mockGetDefinitionById.mockResolvedValue(definition);
173
+ definitionResponse = definition;
207
174
 
208
175
  await expect(
209
176
  runWorkflow(definitions, {
@@ -218,7 +185,7 @@ describe('runWorkflow', () => {
218
185
 
219
186
  test('passes inputs through to the run', async () => {
220
187
  const definition = buildDefinition({projectId});
221
- mockGetDefinitionById.mockResolvedValue(definition);
188
+ definitionResponse = definition;
222
189
 
223
190
  const run = await runWorkflow(definitions, {
224
191
  workspaceId,
@@ -1,8 +1,8 @@
1
1
  import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
2
2
  import {workflowModelFromSnapshot} from '@shipfox/api-definitions-dto';
3
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';
4
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
5
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
6
6
  import type {SecretsInterModuleClient} from '@shipfox/api-secrets-dto/inter-module';
7
7
  import {createWorkflowRun} from '#db/workflow-runs.js';
8
8
  import {createAgentDefaultsResolver} from './agent-defaults.js';
@@ -4,13 +4,13 @@ import {
4
4
  AGENT_INTEGRATION_MCP_SERVER_NAME,
5
5
  AGENT_INTEGRATION_MCP_TRANSPORT,
6
6
  type AgentIntegrationMcpServerConfigDto,
7
- type AgentThinking,
8
7
  type MaterializedAgentIntegrationConfigDto,
9
8
  } from '@shipfox/api-agent-dto';
10
9
  import {agentInterModuleContract} from '@shipfox/api-agent-dto/inter-module';
11
10
  import type {WorkflowModel} from '@shipfox/api-definitions-dto';
12
11
  import type {ResolvedField, SiteResolvedField} from '@shipfox/expression';
13
12
  import {isInterModuleKnownError} from '@shipfox/inter-module';
13
+ import type {AgentThinking} from '@shipfox/workflow-document';
14
14
  import type {AgentDefaultsResolver, ResolvedAgentDefaults} from '#core/agent-defaults.js';
15
15
  import {
16
16
  type AgentToolMaterializationContext,
@@ -5,10 +5,9 @@ import {
5
5
  AGENT_INTEGRATION_MCP_TRANSPORT,
6
6
  } from '@shipfox/api-agent-dto';
7
7
  import {agentInterModuleContract} from '@shipfox/api-agent-dto/inter-module';
8
- import type {AgentToolCatalogEntry} from '@shipfox/api-integration-core';
9
8
  import {createInterModuleKnownError} from '@shipfox/inter-module';
10
9
  import type {AgentDefaultsResolver} from '#core/agent-defaults.js';
11
- import type {AgentToolMaterializationContext} from '#core/agent-tools.js';
10
+ import type {AgentToolCatalogEntry, AgentToolMaterializationContext} from '#core/agent-tools.js';
12
11
  import {AgentConfigUnresolvableError, InterpolationUnresolvableError} from '#core/errors.js';
13
12
  import {resolveTestAgentDefaults} from '#test/fixtures/agent-inter-module.js';
14
13
  import {workflowModel} from '#test/index.js';
@@ -1,9 +1,5 @@
1
1
  import {agentInterModuleContract} from '@shipfox/api-agent-dto/inter-module';
2
- import {
3
- DEFAULT_JOB_CHECKOUT,
4
- normalizeWorkflowDocument,
5
- type WorkflowModel,
6
- } from '@shipfox/api-definitions';
2
+ import {DEFAULT_JOB_CHECKOUT, type WorkflowModel} from '@shipfox/api-definitions-dto';
7
3
  import {createInterModuleKnownError} from '@shipfox/inter-module';
8
4
  import type {AgentDefaultsResolver} from '#core/agent-defaults.js';
9
5
  import {AgentConfigUnresolvableError, InterpolationUnresolvableError} from '#core/errors.js';
@@ -539,7 +535,7 @@ describe('materializeWorkflowModel', () => {
539
535
  });
540
536
 
541
537
  it('freezes vars from the run-creation context into step config', async () => {
542
- const model = normalizeWorkflowDocument({
538
+ const model = workflowModel({
543
539
  name: 'vars workflow',
544
540
  runner: 'ubuntu-latest',
545
541
  jobs: {
@@ -999,14 +995,15 @@ describe('materializeWorkflowModel', () => {
999
995
 
1000
996
  it('skips listening job steps at workflow-run creation', async () => {
1001
997
  const stepNameSource = `Review ${template('execution.index')}`;
1002
- const model = normalizeWorkflowDocument({
998
+ const model = workflowModel({
1003
999
  name: 'Listening workflow',
1004
1000
  runner: 'ubuntu-latest',
1005
1001
  jobs: {
1006
1002
  review: {
1007
1003
  listening: {
1008
1004
  on: [{source: 'github', event: 'pull_request_review'}],
1009
- max_executions: 3,
1005
+ maxExecutions: 3,
1006
+ onResolve: 'finish',
1010
1007
  },
1011
1008
  steps: [{name: stepNameSource, prompt: 'Summarize the review.'}],
1012
1009
  },
@@ -1027,14 +1024,15 @@ describe('materializeWorkflowModel', () => {
1027
1024
  });
1028
1025
 
1029
1026
  it('materializes one-shot siblings while skipping listening steps', async () => {
1030
- const model = normalizeWorkflowDocument({
1027
+ const model = workflowModel({
1031
1028
  name: 'Mixed workflow',
1032
1029
  runner: 'ubuntu-latest',
1033
1030
  jobs: {
1034
1031
  review: {
1035
1032
  listening: {
1036
1033
  on: [{source: 'github', event: 'pull_request_review'}],
1037
- max_executions: 3,
1034
+ maxExecutions: 3,
1035
+ onResolve: 'finish',
1038
1036
  },
1039
1037
  steps: [{name: `Review ${template('execution.index')}`, prompt: 'Summarize it.'}],
1040
1038
  },
@@ -1095,12 +1093,12 @@ describe('materializeWorkflowModel', () => {
1095
1093
  });
1096
1094
 
1097
1095
  it('materializes step if as server-owned condition outside runner config', async () => {
1098
- const model = normalizeWorkflowDocument({
1096
+ const model = workflowModel({
1099
1097
  name: 'Conditional workflow',
1100
1098
  runner: 'ubuntu-latest',
1101
1099
  jobs: {
1102
1100
  build: {
1103
- steps: [{if: template('false'), run: 'npm test'}],
1101
+ steps: [{if: expression('false'), run: 'npm test'}],
1104
1102
  },
1105
1103
  },
1106
1104
  });
@@ -1112,7 +1110,6 @@ describe('materializeWorkflowModel', () => {
1112
1110
  language: 'cel',
1113
1111
  source: 'false',
1114
1112
  check: 'typed',
1115
- resultType: 'bool',
1116
1113
  });
1117
1114
  expect(step?.config).toEqual({run: 'npm test'});
1118
1115
  });
@@ -1,7 +1,7 @@
1
1
  import type {AgentInterModuleClient} from '@shipfox/api-agent-dto/inter-module';
2
2
  import {readPersistedWorkflowModel} from '@shipfox/api-definitions-dto';
3
- import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto';
4
- import type {ProjectsModuleClient} from '@shipfox/api-projects-dto';
3
+ import type {IntegrationsModuleClient} from '@shipfox/api-integration-core-dto/inter-module';
4
+ import type {ProjectsModuleClient} from '@shipfox/api-projects-dto/inter-module';
5
5
  import {
6
6
  WORKFLOWS_JOB_ACTIVATED,
7
7
  type WorkflowsJobActivatedEventDto,