@shipfox/api-workflows-dto 2.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 (87) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +46 -0
  5. package/LICENSE +21 -0
  6. package/dist/events.d.ts +316 -0
  7. package/dist/events.d.ts.map +1 -0
  8. package/dist/events.js +144 -0
  9. package/dist/events.js.map +1 -0
  10. package/dist/index.d.ts +5 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +6 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/schemas/agent-runtime-config.d.ts +7 -0
  15. package/dist/schemas/agent-runtime-config.d.ts.map +1 -0
  16. package/dist/schemas/agent-runtime-config.js +7 -0
  17. package/dist/schemas/agent-runtime-config.js.map +1 -0
  18. package/dist/schemas/checkout-token.d.ts +56 -0
  19. package/dist/schemas/checkout-token.d.ts.map +1 -0
  20. package/dist/schemas/checkout-token.js +44 -0
  21. package/dist/schemas/checkout-token.js.map +1 -0
  22. package/dist/schemas/checkout.d.ts +10 -0
  23. package/dist/schemas/checkout.d.ts.map +1 -0
  24. package/dist/schemas/checkout.js +10 -0
  25. package/dist/schemas/checkout.js.map +1 -0
  26. package/dist/schemas/index.d.ts +11 -0
  27. package/dist/schemas/index.d.ts.map +1 -0
  28. package/dist/schemas/index.js +12 -0
  29. package/dist/schemas/index.js.map +1 -0
  30. package/dist/schemas/job-execution.d.ts +116 -0
  31. package/dist/schemas/job-execution.d.ts.map +1 -0
  32. package/dist/schemas/job-execution.js +42 -0
  33. package/dist/schemas/job-execution.js.map +1 -0
  34. package/dist/schemas/job-listening.d.ts +93 -0
  35. package/dist/schemas/job-listening.d.ts.map +1 -0
  36. package/dist/schemas/job-listening.js +60 -0
  37. package/dist/schemas/job-listening.js.map +1 -0
  38. package/dist/schemas/job.d.ts +101 -0
  39. package/dist/schemas/job.d.ts.map +1 -0
  40. package/dist/schemas/job.js +43 -0
  41. package/dist/schemas/job.js.map +1 -0
  42. package/dist/schemas/log-outcome.d.ts +7 -0
  43. package/dist/schemas/log-outcome.d.ts.map +1 -0
  44. package/dist/schemas/log-outcome.js +7 -0
  45. package/dist/schemas/log-outcome.js.map +1 -0
  46. package/dist/schemas/step.d.ts +186 -0
  47. package/dist/schemas/step.d.ts.map +1 -0
  48. package/dist/schemas/step.js +137 -0
  49. package/dist/schemas/step.js.map +1 -0
  50. package/dist/schemas/workflow-run-detail.d.ts +807 -0
  51. package/dist/schemas/workflow-run-detail.d.ts.map +1 -0
  52. package/dist/schemas/workflow-run-detail.js +51 -0
  53. package/dist/schemas/workflow-run-detail.js.map +1 -0
  54. package/dist/schemas/workflow-run.d.ts +213 -0
  55. package/dist/schemas/workflow-run.d.ts.map +1 -0
  56. package/dist/schemas/workflow-run.js +112 -0
  57. package/dist/schemas/workflow-run.js.map +1 -0
  58. package/dist/tsconfig.test.tsbuildinfo +1 -0
  59. package/package.json +55 -0
  60. package/src/events.test.ts +362 -0
  61. package/src/events.ts +180 -0
  62. package/src/index.ts +130 -0
  63. package/src/schemas/agent-runtime-config.test.ts +17 -0
  64. package/src/schemas/agent-runtime-config.ts +8 -0
  65. package/src/schemas/checkout-token.test.ts +162 -0
  66. package/src/schemas/checkout-token.ts +45 -0
  67. package/src/schemas/checkout.test.ts +49 -0
  68. package/src/schemas/checkout.ts +11 -0
  69. package/src/schemas/index.ts +104 -0
  70. package/src/schemas/job-execution.test.ts +27 -0
  71. package/src/schemas/job-execution.ts +92 -0
  72. package/src/schemas/job-listening.test.ts +64 -0
  73. package/src/schemas/job-listening.ts +59 -0
  74. package/src/schemas/job.test.ts +42 -0
  75. package/src/schemas/job.ts +53 -0
  76. package/src/schemas/log-outcome.ts +5 -0
  77. package/src/schemas/step-source-location.test.ts +45 -0
  78. package/src/schemas/step.test.ts +176 -0
  79. package/src/schemas/step.ts +163 -0
  80. package/src/schemas/workflow-run-detail.ts +67 -0
  81. package/src/schemas/workflow-run.test.ts +59 -0
  82. package/src/schemas/workflow-run.ts +144 -0
  83. package/tsconfig.build.json +9 -0
  84. package/tsconfig.build.tsbuildinfo +1 -0
  85. package/tsconfig.json +3 -0
  86. package/tsconfig.test.json +8 -0
  87. package/vitest.config.ts +3 -0
package/src/index.ts ADDED
@@ -0,0 +1,130 @@
1
+ export {
2
+ type AgentConfigIssueDto,
3
+ type AgentRuntimeConfigQueryDto,
4
+ agentConfigIssueSchema,
5
+ agentRuntimeConfigQuerySchema,
6
+ type CheckoutIntentDto,
7
+ type CheckoutTokenAuthDto,
8
+ type CheckoutTokenResponseDto,
9
+ checkoutIntentSchema,
10
+ checkoutTokenAuthSchema,
11
+ checkoutTokenResponseSchema,
12
+ type JobDto,
13
+ type JobExecutionDto,
14
+ type JobListeningDto,
15
+ type JobModeDto,
16
+ type JobStatusDto,
17
+ type JobStatusReasonDto,
18
+ jobDtoSchema,
19
+ jobListeningBatchSchema,
20
+ jobListeningSchema,
21
+ jobModeSchema,
22
+ jobStatusReasonSchema,
23
+ jobStatusSchema,
24
+ type ListenerStatusDto,
25
+ type ListeningTriggerDto,
26
+ type LogOutcomeDto,
27
+ listenerStatusSchema,
28
+ listeningTriggerSchema,
29
+ logOutcomeSchema,
30
+ type NextStepResponseDto,
31
+ nextStepResponseSchema,
32
+ type ReportStepBodyDto,
33
+ type ReportStepResponseDto,
34
+ type RerunWorkflowRunBodyDto,
35
+ type ResolutionReasonDto,
36
+ reportStepBodySchema,
37
+ reportStepResponseSchema,
38
+ rerunWorkflowRunBodySchema,
39
+ resolutionReasonSchema,
40
+ STEP_ERROR_MESSAGE_MAX_LENGTH,
41
+ STEP_RESPONSE_MAX_LENGTH,
42
+ type StepAttemptDto,
43
+ type StepDto,
44
+ type StepErrorCategoryDto,
45
+ type StepErrorDto,
46
+ type StepErrorReasonDto,
47
+ type StepGateResultDto,
48
+ stepAttemptDtoSchema,
49
+ stepDtoSchema,
50
+ stepErrorCategorySchema,
51
+ stepErrorDtoSchema,
52
+ stepErrorReasonSchema,
53
+ stepGateResultDtoSchema,
54
+ type TriggerEventsBatchDto,
55
+ triggerEventsBatchSchema,
56
+ type WorkflowExecutionContextDto,
57
+ type WorkflowExecutionEventDto,
58
+ type WorkflowRunAggregatesQueryDto,
59
+ type WorkflowRunAggregatesResponseDto,
60
+ type WorkflowRunAttemptDto,
61
+ type WorkflowRunAttemptsResponseDto,
62
+ type WorkflowRunDetailResponseDto,
63
+ type WorkflowRunDto,
64
+ type WorkflowRunJobDetailDto,
65
+ type WorkflowRunJobExecutionDetailDto,
66
+ type WorkflowRunListQueryDto,
67
+ type WorkflowRunListResponseDto,
68
+ type WorkflowRunRerunModeDto,
69
+ type WorkflowRunResponseDto,
70
+ type WorkflowRunStatusDto,
71
+ type WorkflowRunStepDetailDto,
72
+ workflowExecutionContextSchema,
73
+ workflowExecutionEventSchema,
74
+ workflowRunAggregatesQuerySchema,
75
+ workflowRunAggregatesResponseSchema,
76
+ workflowRunAttemptDtoSchema,
77
+ workflowRunAttemptsResponseSchema,
78
+ workflowRunDetailResponseSchema,
79
+ workflowRunDtoSchema,
80
+ workflowRunJobDetailDtoSchema,
81
+ workflowRunJobExecutionDetailDtoSchema,
82
+ workflowRunListQuerySchema,
83
+ workflowRunListResponseSchema,
84
+ workflowRunRerunModeSchema,
85
+ workflowRunResponseSchema,
86
+ workflowRunStatusSchema,
87
+ workflowRunStepDetailDtoSchema,
88
+ } from '#schemas/index.js';
89
+ export {type StepSourceLocationDto, stepSourceLocationSchema} from '#schemas/step.js';
90
+ export {
91
+ type WorkflowSourceSnapshotDto,
92
+ workflowSourceSnapshotSchema,
93
+ } from '#schemas/workflow-run.js';
94
+ export {
95
+ jobTerminalStatusSchema,
96
+ terminalStatusSchema,
97
+ WORKFLOWS_JOB_ACTIVATED,
98
+ WORKFLOWS_JOB_EVENT_DELIVERED,
99
+ WORKFLOWS_JOB_EXECUTION_TIMED_OUT,
100
+ WORKFLOWS_JOB_STEPS_SETTLED,
101
+ WORKFLOWS_JOB_TERMINATED,
102
+ WORKFLOWS_STEP_ATTEMPT_TERMINATED,
103
+ WORKFLOWS_STEP_RESTART_ENQUEUED,
104
+ WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED,
105
+ WORKFLOWS_WORKFLOW_RUN_CANCELLED,
106
+ WORKFLOWS_WORKFLOW_RUN_TERMINATED,
107
+ type WorkflowsEventMapDto,
108
+ type WorkflowsJobActivatedEventDto,
109
+ type WorkflowsJobEventDeliveredEventDto,
110
+ type WorkflowsJobExecutionTimedOutEventDto,
111
+ type WorkflowsJobStepsSettledEventDto,
112
+ type WorkflowsJobTerminatedEventDto,
113
+ type WorkflowsStepAttemptTerminatedEventDto,
114
+ type WorkflowsStepRestartEnqueuedEventDto,
115
+ type WorkflowsWorkflowRunAttemptCreatedEventDto,
116
+ type WorkflowsWorkflowRunCancelledEventDto,
117
+ type WorkflowsWorkflowRunTerminatedEventDto,
118
+ workflowRunTerminalStatusSchema,
119
+ workflowsEventSchemas,
120
+ workflowsJobActivatedSchema,
121
+ workflowsJobEventDeliveredSchema,
122
+ workflowsJobExecutionTimedOutSchema,
123
+ workflowsJobStepsSettledSchema,
124
+ workflowsJobTerminatedSchema,
125
+ workflowsStepAttemptTerminatedSchema,
126
+ workflowsStepRestartEnqueuedSchema,
127
+ workflowsWorkflowRunAttemptCreatedSchema,
128
+ workflowsWorkflowRunCancelledSchema,
129
+ workflowsWorkflowRunTerminatedSchema,
130
+ } from './events.js';
@@ -0,0 +1,17 @@
1
+ import {agentRuntimeConfigQuerySchema} from './agent-runtime-config.js';
2
+
3
+ describe('agentRuntimeConfigQuerySchema', () => {
4
+ it('coerces the attempt query param', () => {
5
+ const stepId = crypto.randomUUID();
6
+
7
+ const parsed = agentRuntimeConfigQuerySchema.parse({step_id: stepId, attempt: '2'});
8
+
9
+ expect(parsed).toEqual({step_id: stepId, attempt: 2});
10
+ });
11
+
12
+ it('rejects malformed query params', () => {
13
+ const parse = () => agentRuntimeConfigQuerySchema.parse({step_id: 'step-1', attempt: '0'});
14
+
15
+ expect(parse).toThrow();
16
+ });
17
+ });
@@ -0,0 +1,8 @@
1
+ import {z} from 'zod';
2
+
3
+ export const agentRuntimeConfigQuerySchema = z.object({
4
+ step_id: z.string().uuid(),
5
+ attempt: z.coerce.number().int().positive(),
6
+ });
7
+
8
+ export type AgentRuntimeConfigQueryDto = z.infer<typeof agentRuntimeConfigQuerySchema>;
@@ -0,0 +1,162 @@
1
+ import {checkoutTokenResponseSchema} from './checkout-token.js';
2
+
3
+ const bearerResponse = {
4
+ repository_url: 'https://github.com/acme/repo.git',
5
+ ref: 'main',
6
+ auth: {
7
+ kind: 'bearer',
8
+ token: 'gh-token',
9
+ expires_at: '2026-06-10T12:00:00.000Z',
10
+ carry: 'header',
11
+ host: 'github.com',
12
+ persist: true,
13
+ },
14
+ };
15
+
16
+ const basicResponse = {
17
+ repository_url: 'https://github.com/acme/repo.git',
18
+ ref: 'main',
19
+ auth: {
20
+ kind: 'basic',
21
+ username: 'x-access-token',
22
+ token: 'gh-token',
23
+ expires_at: '2026-06-10T12:00:00.000Z',
24
+ carry: 'header',
25
+ host: 'github.com',
26
+ persist: false,
27
+ },
28
+ };
29
+
30
+ describe('checkoutTokenResponseSchema', () => {
31
+ it('accepts and round-trips a bearer auth response (no username)', () => {
32
+ const result = checkoutTokenResponseSchema.parse(bearerResponse);
33
+
34
+ expect(result).toEqual(bearerResponse);
35
+ });
36
+
37
+ it('accepts and round-trips a basic auth response with a username', () => {
38
+ const result = checkoutTokenResponseSchema.parse(basicResponse);
39
+
40
+ expect(result).toEqual(basicResponse);
41
+ });
42
+
43
+ it('accepts a Git author identity', () => {
44
+ const input = {
45
+ ...basicResponse,
46
+ git_author: {
47
+ name: 'shipfox-test[bot]',
48
+ email: '1+shipfox-test[bot]@users.noreply.github.com',
49
+ },
50
+ };
51
+
52
+ const result = checkoutTokenResponseSchema.parse(input);
53
+
54
+ expect(result.git_author).toEqual(input.git_author);
55
+ });
56
+
57
+ it('accepts a credential-free response with no auth (debug provider)', () => {
58
+ const input = {repository_url: 'https://github.com/acme/repo.git', ref: 'main'};
59
+
60
+ const result = checkoutTokenResponseSchema.parse(input);
61
+
62
+ expect(result).toEqual(input);
63
+ expect(result.auth).toBeUndefined();
64
+ });
65
+
66
+ it('rejects basic auth missing a username', () => {
67
+ const {username: _username, ...basicAuthWithoutUsername} = basicResponse.auth;
68
+ const input = {...basicResponse, auth: basicAuthWithoutUsername};
69
+
70
+ const parse = () => checkoutTokenResponseSchema.parse(input);
71
+
72
+ expect(parse).toThrow();
73
+ });
74
+
75
+ it('rejects an unknown auth kind', () => {
76
+ const input = {...bearerResponse, auth: {...bearerResponse.auth, kind: 'oauth'}};
77
+
78
+ const parse = () => checkoutTokenResponseSchema.parse(input);
79
+
80
+ expect(parse).toThrow();
81
+ });
82
+
83
+ it('rejects a malformed (non-ISO) expires_at', () => {
84
+ const input = {...bearerResponse, auth: {...bearerResponse.auth, expires_at: 'soon'}};
85
+
86
+ const parse = () => checkoutTokenResponseSchema.parse(input);
87
+
88
+ expect(parse).toThrow();
89
+ });
90
+
91
+ it('accepts the toISOString() Z wire format for expires_at', () => {
92
+ const input = {
93
+ ...bearerResponse,
94
+ auth: {...bearerResponse.auth, expires_at: '2026-06-10T12:00:00.000Z'},
95
+ };
96
+
97
+ const result = checkoutTokenResponseSchema.parse(input);
98
+
99
+ expect(result.auth?.expires_at).toBe('2026-06-10T12:00:00.000Z');
100
+ });
101
+
102
+ it('accepts an offset (non-Z) expires_at', () => {
103
+ const input = {
104
+ ...bearerResponse,
105
+ auth: {...bearerResponse.auth, expires_at: '2026-06-10T12:00:00+02:00'},
106
+ };
107
+
108
+ const result = checkoutTokenResponseSchema.parse(input);
109
+
110
+ expect(result.auth?.expires_at).toBe('2026-06-10T12:00:00+02:00');
111
+ });
112
+
113
+ it('rejects an empty token', () => {
114
+ const input = {...bearerResponse, auth: {...bearerResponse.auth, token: ''}};
115
+
116
+ const parse = () => checkoutTokenResponseSchema.parse(input);
117
+
118
+ expect(parse).toThrow();
119
+ });
120
+
121
+ it('accepts userinfo carry mode', () => {
122
+ const input = {...bearerResponse, auth: {...bearerResponse.auth, carry: 'userinfo'}};
123
+
124
+ const result = checkoutTokenResponseSchema.parse(input);
125
+
126
+ expect(result.auth?.carry).toBe('userinfo');
127
+ });
128
+
129
+ it('rejects an unsupported carry mode', () => {
130
+ const input = {...bearerResponse, auth: {...bearerResponse.auth, carry: 'ssh-agent'}};
131
+
132
+ const parse = () => checkoutTokenResponseSchema.parse(input);
133
+
134
+ expect(parse).toThrow();
135
+ });
136
+
137
+ it('rejects auth missing host', () => {
138
+ const {host: _host, ...auth} = bearerResponse.auth;
139
+ const input = {...bearerResponse, auth};
140
+
141
+ const parse = () => checkoutTokenResponseSchema.parse(input);
142
+
143
+ expect(parse).toThrow();
144
+ });
145
+
146
+ it('rejects auth missing persist', () => {
147
+ const {persist: _persist, ...auth} = bearerResponse.auth;
148
+ const input = {...bearerResponse, auth};
149
+
150
+ const parse = () => checkoutTokenResponseSchema.parse(input);
151
+
152
+ expect(parse).toThrow();
153
+ });
154
+
155
+ it('rejects an empty repository_url', () => {
156
+ const input = {...bearerResponse, repository_url: ''};
157
+
158
+ const parse = () => checkoutTokenResponseSchema.parse(input);
159
+
160
+ expect(parse).toThrow();
161
+ });
162
+ });
@@ -0,0 +1,45 @@
1
+ import {z} from 'zod';
2
+
3
+ const carryFields = {
4
+ carry: z.enum(['header', 'userinfo']),
5
+ host: z.string().min(1),
6
+ persist: z.boolean(),
7
+ };
8
+
9
+ const checkoutGitAuthorSchema = z.object({
10
+ name: z.string().min(1),
11
+ email: z.string().min(1),
12
+ });
13
+
14
+ const checkoutTokenBasicAuthSchema = z.object({
15
+ kind: z.literal('basic'),
16
+ username: z.string().min(1),
17
+ token: z.string().min(1),
18
+ expires_at: z.string().datetime({offset: true}),
19
+ ...carryFields,
20
+ });
21
+
22
+ const checkoutTokenBearerAuthSchema = z.object({
23
+ kind: z.literal('bearer'),
24
+ token: z.string().min(1),
25
+ expires_at: z.string().datetime({offset: true}),
26
+ ...carryFields,
27
+ });
28
+
29
+ export const checkoutTokenAuthSchema = z.discriminatedUnion('kind', [
30
+ checkoutTokenBasicAuthSchema,
31
+ checkoutTokenBearerAuthSchema,
32
+ ]);
33
+
34
+ export type CheckoutTokenAuthDto = z.infer<typeof checkoutTokenAuthSchema>;
35
+
36
+ export const checkoutTokenResponseSchema = z.object({
37
+ repository_url: z.string().min(1),
38
+ ref: z.string().min(1),
39
+ git_author: checkoutGitAuthorSchema.optional(),
40
+ // Optional: credential-free providers (e.g. the debug source control) return a
41
+ // public clone URL with no auth material, so the runner clones without a token.
42
+ auth: checkoutTokenAuthSchema.optional(),
43
+ });
44
+
45
+ export type CheckoutTokenResponseDto = z.infer<typeof checkoutTokenResponseSchema>;
@@ -0,0 +1,49 @@
1
+ import {checkoutIntentSchema} from './checkout.js';
2
+
3
+ const validCheckout = {
4
+ repository_url: 'https://github.com/acme/repo.git',
5
+ ref: 'main',
6
+ provider: 'github',
7
+ source_connection_id: '22222222-2222-4222-8222-222222222222',
8
+ external_repository_id: 'acme/repo',
9
+ };
10
+
11
+ describe('checkoutIntentSchema', () => {
12
+ it('round-trips a valid credential-free intent unchanged', () => {
13
+ const result = checkoutIntentSchema.parse(validCheckout);
14
+
15
+ expect(result).toEqual(validCheckout);
16
+ });
17
+
18
+ it('rejects an intent missing a required field', () => {
19
+ const {provider: _provider, ...checkoutWithoutProvider} = validCheckout;
20
+
21
+ const parse = () => checkoutIntentSchema.parse(checkoutWithoutProvider);
22
+
23
+ expect(parse).toThrow();
24
+ });
25
+
26
+ it('rejects a non-UUID source_connection_id', () => {
27
+ const input = {...validCheckout, source_connection_id: 'not-a-uuid'};
28
+
29
+ const parse = () => checkoutIntentSchema.parse(input);
30
+
31
+ expect(parse).toThrow();
32
+ });
33
+
34
+ it('rejects an empty repository_url', () => {
35
+ const input = {...validCheckout, repository_url: ''};
36
+
37
+ const parse = () => checkoutIntentSchema.parse(input);
38
+
39
+ expect(parse).toThrow();
40
+ });
41
+
42
+ it('rejects an empty provider', () => {
43
+ const input = {...validCheckout, provider: ''};
44
+
45
+ const parse = () => checkoutIntentSchema.parse(input);
46
+
47
+ expect(parse).toThrow();
48
+ });
49
+ });
@@ -0,0 +1,11 @@
1
+ import {z} from 'zod';
2
+
3
+ export const checkoutIntentSchema = z.object({
4
+ repository_url: z.string().min(1),
5
+ ref: z.string().min(1),
6
+ provider: z.string().min(1),
7
+ source_connection_id: z.string().uuid(),
8
+ external_repository_id: z.string().min(1),
9
+ });
10
+
11
+ export type CheckoutIntentDto = z.infer<typeof checkoutIntentSchema>;
@@ -0,0 +1,104 @@
1
+ export {
2
+ type AgentRuntimeConfigQueryDto,
3
+ agentRuntimeConfigQuerySchema,
4
+ } from './agent-runtime-config.js';
5
+ export {type CheckoutIntentDto, checkoutIntentSchema} from './checkout.js';
6
+ export {
7
+ type CheckoutTokenAuthDto,
8
+ type CheckoutTokenResponseDto,
9
+ checkoutTokenAuthSchema,
10
+ checkoutTokenResponseSchema,
11
+ } from './checkout-token.js';
12
+ export {
13
+ type JobDto,
14
+ type JobStatusDto,
15
+ type JobStatusReasonDto,
16
+ jobDtoSchema,
17
+ jobStatusReasonSchema,
18
+ jobStatusSchema,
19
+ } from './job.js';
20
+ export {
21
+ type NextStepResponseDto,
22
+ nextStepResponseSchema,
23
+ type ReportStepBodyDto,
24
+ type ReportStepResponseDto,
25
+ reportStepBodySchema,
26
+ reportStepResponseSchema,
27
+ STEP_RESPONSE_MAX_LENGTH,
28
+ } from './job-execution.js';
29
+ export {
30
+ type JobListeningDto,
31
+ type JobModeDto,
32
+ jobListeningBatchSchema,
33
+ jobListeningSchema,
34
+ jobModeSchema,
35
+ type ListenerStatusDto,
36
+ type ListeningTriggerDto,
37
+ listenerStatusSchema,
38
+ listeningTriggerSchema,
39
+ type ResolutionReasonDto,
40
+ resolutionReasonSchema,
41
+ type TriggerEventsBatchDto,
42
+ triggerEventsBatchSchema,
43
+ type WorkflowExecutionContextDto,
44
+ type WorkflowExecutionEventDto,
45
+ workflowExecutionContextSchema,
46
+ workflowExecutionEventSchema,
47
+ } from './job-listening.js';
48
+ export {type LogOutcomeDto, logOutcomeSchema} from './log-outcome.js';
49
+ export {
50
+ type AgentConfigIssueDto,
51
+ agentConfigIssueSchema,
52
+ STEP_ERROR_MESSAGE_MAX_LENGTH,
53
+ type StepAttemptDto,
54
+ type StepDto,
55
+ type StepErrorCategoryDto,
56
+ type StepErrorDto,
57
+ type StepErrorReasonDto,
58
+ type StepGateResultDto,
59
+ stepAttemptDtoSchema,
60
+ stepDtoSchema,
61
+ stepErrorCategorySchema,
62
+ stepErrorDtoSchema,
63
+ stepErrorReasonSchema,
64
+ stepGateResultDtoSchema,
65
+ } from './step.js';
66
+ export {
67
+ type RerunWorkflowRunBodyDto,
68
+ rerunWorkflowRunBodySchema,
69
+ type WorkflowRunAggregatesQueryDto,
70
+ type WorkflowRunAggregatesResponseDto,
71
+ type WorkflowRunAttemptDto,
72
+ type WorkflowRunAttemptsResponseDto,
73
+ type WorkflowRunDto,
74
+ type WorkflowRunListQueryDto,
75
+ type WorkflowRunListResponseDto,
76
+ type WorkflowRunRerunModeDto,
77
+ type WorkflowRunResponseDto,
78
+ type WorkflowRunStatusDto,
79
+ type WorkflowSourceSnapshotDto,
80
+ workflowRunAggregatesQuerySchema,
81
+ workflowRunAggregatesResponseSchema,
82
+ workflowRunAttemptDtoSchema,
83
+ workflowRunAttemptsResponseSchema,
84
+ workflowRunDtoSchema,
85
+ workflowRunListQuerySchema,
86
+ workflowRunListResponseSchema,
87
+ workflowRunRerunModeSchema,
88
+ workflowRunResponseSchema,
89
+ workflowRunStatusSchema,
90
+ workflowSourceSnapshotSchema,
91
+ } from './workflow-run.js';
92
+ export {
93
+ type JobExecutionDto,
94
+ jobExecutionDtoSchema,
95
+ jobExecutionStatusSchema,
96
+ type WorkflowRunDetailResponseDto,
97
+ type WorkflowRunJobDetailDto,
98
+ type WorkflowRunJobExecutionDetailDto,
99
+ type WorkflowRunStepDetailDto,
100
+ workflowRunDetailResponseSchema,
101
+ workflowRunJobDetailDtoSchema,
102
+ workflowRunJobExecutionDetailDtoSchema,
103
+ workflowRunStepDetailDtoSchema,
104
+ } from './workflow-run-detail.js';
@@ -0,0 +1,27 @@
1
+ import {reportStepBodySchema, STEP_RESPONSE_MAX_LENGTH} from './job-execution.js';
2
+
3
+ describe('reportStepBodySchema', () => {
4
+ it('accepts a capped agent response', () => {
5
+ const parsed = reportStepBodySchema.parse({
6
+ status: 'succeeded',
7
+ attempt: 1,
8
+ exit_code: 0,
9
+ log_outcome: 'drained',
10
+ response: 'done',
11
+ });
12
+
13
+ expect(parsed.response).toBe('done');
14
+ });
15
+
16
+ it('rejects responses over the cap', () => {
17
+ const result = reportStepBodySchema.safeParse({
18
+ status: 'succeeded',
19
+ attempt: 1,
20
+ exit_code: 0,
21
+ log_outcome: 'drained',
22
+ response: 'x'.repeat(STEP_RESPONSE_MAX_LENGTH + 1),
23
+ });
24
+
25
+ expect(result.success).toBe(false);
26
+ });
27
+ });
@@ -0,0 +1,92 @@
1
+ import {z} from 'zod';
2
+ import {logOutcomeSchema} from './log-outcome.js';
3
+ import {stepDtoSchema, stepErrorDtoSchema} from './step.js';
4
+
5
+ export const STEP_RESPONSE_MAX_LENGTH = 8 * 1024;
6
+
7
+ /**
8
+ * The job to progress is identified by the caller's lease-token claims, never by
9
+ * the request. An unknown job is a 404, not a `done`.
10
+ */
11
+ export const nextStepResponseSchema = z.discriminatedUnion('kind', [
12
+ z.object({
13
+ kind: z.literal('step'),
14
+ step: stepDtoSchema,
15
+ attempt: z
16
+ .number()
17
+ .int()
18
+ .positive()
19
+ .describe(
20
+ 'Attempt number for this step dispatch. Echo it back when reporting the step result so stale reports from older attempts can be ignored.',
21
+ ),
22
+ lease_token: z
23
+ .string()
24
+ .min(1)
25
+ .describe(
26
+ 'Job-lease token re-scoped to this dispatched step attempt. The runner presents it as its lease for log-append authorization and carries it on later step requests.',
27
+ ),
28
+ }),
29
+ z.object({
30
+ kind: z.literal('done'),
31
+ status: z
32
+ .enum(['succeeded', 'failed'])
33
+ .describe('Terminal status of the job when no step remains to run.'),
34
+ }),
35
+ ]);
36
+
37
+ export type NextStepResponseDto = z.infer<typeof nextStepResponseSchema>;
38
+
39
+ export const reportStepBodySchema = z
40
+ .object({
41
+ status: z.enum(['succeeded', 'failed']).describe('Final status reported for the step attempt.'),
42
+ error: stepErrorDtoSchema
43
+ .optional()
44
+ .describe('Failure details. Required when status is failed.'),
45
+ attempt: z
46
+ .number()
47
+ .int()
48
+ .positive()
49
+ .optional()
50
+ .describe(
51
+ 'Attempt number echoed from next-step. Older runners may omit it; when present, it protects the workflow from stale reports.',
52
+ ),
53
+ exit_code: z
54
+ .number()
55
+ .int()
56
+ .nullable()
57
+ .optional()
58
+ .describe(
59
+ 'Process exit code for the step attempt. Persisted as the canonical attempt exit code and used by gate evaluation.',
60
+ ),
61
+ output: z
62
+ .record(z.string(), z.unknown())
63
+ .nullable()
64
+ .optional()
65
+ .describe(
66
+ 'Structured output captured for attempt history. Large textual logs are stored separately.',
67
+ ),
68
+ response: z
69
+ .string()
70
+ .max(STEP_RESPONSE_MAX_LENGTH)
71
+ .optional()
72
+ .describe('Capped final assistant response for agent step attempts. Omitted for run steps.'),
73
+ log_outcome: logOutcomeSchema.describe(
74
+ 'Whether the runner drained all locally spooled logs before reporting, or abandoned the log stream for backend closure.',
75
+ ),
76
+ })
77
+ .refine((body) => (body.status === 'succeeded' ? body.error == null : body.error != null), {
78
+ message: 'succeeded steps must not include an error and failed steps must include one',
79
+ });
80
+
81
+ export type ReportStepBodyDto = z.infer<typeof reportStepBodySchema>;
82
+
83
+ export const reportStepResponseSchema = z.object({
84
+ ok: z.boolean().describe('Whether the step report was accepted.'),
85
+ cancel: z
86
+ .boolean()
87
+ .describe(
88
+ 'Whether the runner should stop working on the job because it finished without full success.',
89
+ ),
90
+ });
91
+
92
+ export type ReportStepResponseDto = z.infer<typeof reportStepResponseSchema>;