@shipfox/api-workflows-dto 12.2.0 → 12.5.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 (47) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/events.d.ts +18 -0
  4. package/dist/events.d.ts.map +1 -1
  5. package/dist/events.js +9 -1
  6. package/dist/events.js.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/schemas/evaluation-trace.d.ts +36 -0
  12. package/dist/schemas/evaluation-trace.d.ts.map +1 -0
  13. package/dist/schemas/evaluation-trace.js +25 -0
  14. package/dist/schemas/evaluation-trace.js.map +1 -0
  15. package/dist/schemas/index.d.ts +3 -2
  16. package/dist/schemas/index.d.ts.map +1 -1
  17. package/dist/schemas/index.js +3 -2
  18. package/dist/schemas/index.js.map +1 -1
  19. package/dist/schemas/job-execution.d.ts +21 -0
  20. package/dist/schemas/job-execution.d.ts.map +1 -1
  21. package/dist/schemas/job.d.ts +22 -0
  22. package/dist/schemas/job.d.ts.map +1 -1
  23. package/dist/schemas/job.js +7 -1
  24. package/dist/schemas/job.js.map +1 -1
  25. package/dist/schemas/step.d.ts +89 -0
  26. package/dist/schemas/step.d.ts.map +1 -1
  27. package/dist/schemas/step.js +13 -0
  28. package/dist/schemas/step.js.map +1 -1
  29. package/dist/schemas/workflow-run-detail.d.ts +219 -0
  30. package/dist/schemas/workflow-run-detail.d.ts.map +1 -1
  31. package/dist/schemas/workflow-run-detail.js +12 -1
  32. package/dist/schemas/workflow-run-detail.js.map +1 -1
  33. package/dist/tsconfig.test.tsbuildinfo +1 -1
  34. package/package.json +1 -1
  35. package/src/events.test.ts +40 -0
  36. package/src/events.ts +8 -0
  37. package/src/index.ts +11 -0
  38. package/src/schemas/evaluation-trace.test.ts +40 -0
  39. package/src/schemas/evaluation-trace.ts +30 -0
  40. package/src/schemas/index.ts +13 -0
  41. package/src/schemas/job.test.ts +16 -0
  42. package/src/schemas/job.ts +6 -0
  43. package/src/schemas/step-source-location.test.ts +2 -0
  44. package/src/schemas/step.test.ts +17 -1
  45. package/src/schemas/step.ts +20 -0
  46. package/src/schemas/workflow-run-detail.ts +15 -1
  47. package/tsconfig.build.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-workflows-dto",
3
3
  "license": "MIT",
4
- "version": "12.2.0",
4
+ "version": "12.5.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -100,6 +100,7 @@ const validStepAttemptTerminated = {
100
100
  projectId: 'proj-1',
101
101
  stepId: 'step-1',
102
102
  attempt: 1,
103
+ status: 'failed',
103
104
  logOutcome: 'drained',
104
105
  };
105
106
 
@@ -138,6 +139,45 @@ describe('workflowsJobTerminatedSchema', () => {
138
139
  expect(result).toEqual(input);
139
140
  });
140
141
 
142
+ it('accepts a string status reason message', () => {
143
+ const input = {
144
+ ...validJobTerminated,
145
+ status: 'failed',
146
+ statusReason: 'output_too_large',
147
+ statusReasonMessage: 'Job output exceeded the configured size limit.',
148
+ };
149
+
150
+ const result = workflowsJobTerminatedSchema.parse(input);
151
+
152
+ expect(result).toEqual(input);
153
+ });
154
+
155
+ it('accepts a null status reason message', () => {
156
+ const input = {
157
+ ...validJobTerminated,
158
+ status: 'failed',
159
+ statusReason: 'unknown',
160
+ statusReasonMessage: null,
161
+ };
162
+
163
+ const result = workflowsJobTerminatedSchema.parse(input);
164
+
165
+ expect(result).toEqual(input);
166
+ });
167
+
168
+ it('rejects a non-string status reason message', () => {
169
+ const input = {
170
+ ...validJobTerminated,
171
+ status: 'failed',
172
+ statusReason: 'output_too_large',
173
+ statusReasonMessage: 413,
174
+ };
175
+
176
+ const parse = () => workflowsJobTerminatedSchema.parse(input);
177
+
178
+ expect(parse).toThrow();
179
+ });
180
+
141
181
  it('strips unknown keys (tolerant of forward-compatible producer additions)', () => {
142
182
  const input = {...validJobTerminated, addedLater: 'ignored'};
143
183
 
package/src/events.ts CHANGED
@@ -139,10 +139,15 @@ export type WorkflowsJobEventDeliveredEventDto = z.infer<typeof workflowsJobEven
139
139
 
140
140
  export const workflowsJobTerminatedSchema = z.object({
141
141
  jobId: nonEmptyStringSchema,
142
+ // Optional for compatibility with terminal events written before the current execution
143
+ // identity became part of the event contract. New events always include the value, or null
144
+ // when the job was terminated before an execution was created.
145
+ jobExecutionId: nonEmptyStringSchema.nullable().optional(),
142
146
  workflowRunId: nonEmptyStringSchema,
143
147
  workflowRunAttemptId: nonEmptyStringSchema,
144
148
  status: jobTerminalStatusSchema,
145
149
  statusReason: jobStatusReasonSchema.nullable(),
150
+ statusReasonMessage: z.string().nullable().optional(),
146
151
  });
147
152
  export type WorkflowsJobTerminatedEventDto = z.infer<typeof workflowsJobTerminatedSchema>;
148
153
 
@@ -178,6 +183,9 @@ export const workflowsStepAttemptTerminatedSchema = z.object({
178
183
  projectId: nonEmptyStringSchema,
179
184
  stepId: nonEmptyStringSchema,
180
185
  attempt: z.number().int().positive(),
186
+ // Optional so the subscriber can continue to consume terminal events written
187
+ // before the status field was added. New outbox events always include it.
188
+ status: terminalStatusSchema.optional(),
181
189
  logOutcome: logOutcomeSchema,
182
190
  });
183
191
  export type WorkflowsStepAttemptTerminatedEventDto = z.infer<
package/src/index.ts CHANGED
@@ -15,6 +15,10 @@ export {
15
15
  checkoutTokenParamsSchema,
16
16
  checkoutTokenQuerySchema,
17
17
  checkoutTokenResponseSchema,
18
+ type EvaluationTraceDto,
19
+ type EvaluationTraceEntryDto,
20
+ evaluationTraceEntrySchema,
21
+ evaluationTraceSchema,
18
22
  type JobDto,
19
23
  type JobExecutionDto,
20
24
  type JobListeningDto,
@@ -45,18 +49,25 @@ export {
45
49
  resolutionReasonSchema,
46
50
  STEP_ERROR_MESSAGE_MAX_LENGTH,
47
51
  STEP_RESPONSE_MAX_LENGTH,
52
+ STEP_STATUS_REASONS,
53
+ type StepAttemptDetailDto,
54
+ type StepAttemptDetailResponseDto,
48
55
  type StepAttemptDto,
49
56
  type StepDto,
50
57
  type StepErrorCategoryDto,
51
58
  type StepErrorDto,
52
59
  type StepErrorReasonDto,
53
60
  type StepGateResultDto,
61
+ type StepStatusReasonDto,
62
+ stepAttemptDetailDtoSchema,
63
+ stepAttemptDetailResponseSchema,
54
64
  stepAttemptDtoSchema,
55
65
  stepDtoSchema,
56
66
  stepErrorCategorySchema,
57
67
  stepErrorDtoSchema,
58
68
  stepErrorReasonSchema,
59
69
  stepGateResultDtoSchema,
70
+ stepStatusReasonSchema,
60
71
  type TriggerEventsBatchDto,
61
72
  triggerEventsBatchSchema,
62
73
  type WorkflowExecutionContextDto,
@@ -0,0 +1,40 @@
1
+ import {evaluationTraceSchema} from './evaluation-trace.js';
2
+
3
+ describe('evaluation trace schema', () => {
4
+ it('accepts value entries with resolved and diagnostic metadata', () => {
5
+ const trace = evaluationTraceSchema.parse([
6
+ {
7
+ expression: 'inputs.environment',
8
+ roots: ['inputs.environment'],
9
+ fill_target: 'agent.prompt',
10
+ evaluated_at: '2026-08-05T12:00:00.000Z',
11
+ field: 'agent.prompt',
12
+ value: 'production',
13
+ reference: true,
14
+ degraded: false,
15
+ env_key: 'ENVIRONMENT',
16
+ },
17
+ ]);
18
+
19
+ expect(trace[0]).toMatchObject({
20
+ field: 'agent.prompt',
21
+ value: 'production',
22
+ reference: true,
23
+ env_key: 'ENVIRONMENT',
24
+ });
25
+ });
26
+
27
+ it('accepts an explicit trace budget marker', () => {
28
+ expect(evaluationTraceSchema.parse([{truncated: true, dropped: 3}])).toEqual([
29
+ {truncated: true, dropped: 3},
30
+ ]);
31
+ });
32
+
33
+ it('rejects malformed trace entries', () => {
34
+ const result = evaluationTraceSchema.safeParse([
35
+ {expression: 'inputs.environment', field: 'agent.prompt'},
36
+ ]);
37
+
38
+ expect(result.success).toBe(false);
39
+ });
40
+ });
@@ -0,0 +1,30 @@
1
+ import {z} from 'zod';
2
+
3
+ const evaluationTraceValueSchema = z.object({
4
+ expression: z.string(),
5
+ roots: z.array(z.string()),
6
+ fill_target: z.string(),
7
+ evaluated_at: z.string(),
8
+ field: z.string(),
9
+ value: z.string().optional(),
10
+ truncated: z.boolean().optional(),
11
+ expr_truncated: z.boolean().optional(),
12
+ reference: z.boolean().optional(),
13
+ degraded: z.boolean().optional(),
14
+ env_key: z.string().optional(),
15
+ });
16
+
17
+ const evaluationTraceLimitSchema = z.object({
18
+ truncated: z.literal(true),
19
+ dropped: z.number().int().nonnegative(),
20
+ });
21
+
22
+ export const evaluationTraceEntrySchema = z.union([
23
+ evaluationTraceValueSchema,
24
+ evaluationTraceLimitSchema,
25
+ ]);
26
+
27
+ export const evaluationTraceSchema = z.array(evaluationTraceEntrySchema);
28
+
29
+ export type EvaluationTraceEntryDto = z.infer<typeof evaluationTraceEntrySchema>;
30
+ export type EvaluationTraceDto = z.infer<typeof evaluationTraceSchema>;
@@ -13,6 +13,12 @@ export {
13
13
  checkoutTokenQuerySchema,
14
14
  checkoutTokenResponseSchema,
15
15
  } from './checkout-token.js';
16
+ export {
17
+ type EvaluationTraceDto,
18
+ type EvaluationTraceEntryDto,
19
+ evaluationTraceEntrySchema,
20
+ evaluationTraceSchema,
21
+ } from './evaluation-trace.js';
16
22
  export {
17
23
  type JobDto,
18
24
  type JobStatusDto,
@@ -56,18 +62,23 @@ export {
56
62
  type AgentConfigIssueDto,
57
63
  agentConfigIssueSchema,
58
64
  STEP_ERROR_MESSAGE_MAX_LENGTH,
65
+ STEP_STATUS_REASONS,
66
+ type StepAttemptDetailDto,
59
67
  type StepAttemptDto,
60
68
  type StepDto,
61
69
  type StepErrorCategoryDto,
62
70
  type StepErrorDto,
63
71
  type StepErrorReasonDto,
64
72
  type StepGateResultDto,
73
+ type StepStatusReasonDto,
74
+ stepAttemptDetailDtoSchema,
65
75
  stepAttemptDtoSchema,
66
76
  stepDtoSchema,
67
77
  stepErrorCategorySchema,
68
78
  stepErrorDtoSchema,
69
79
  stepErrorReasonSchema,
70
80
  stepGateResultDtoSchema,
81
+ stepStatusReasonSchema,
71
82
  } from './step.js';
72
83
  export {
73
84
  type RerunWorkflowRunBodyDto,
@@ -108,6 +119,8 @@ export {
108
119
  type JobExecutionDto,
109
120
  jobExecutionDtoSchema,
110
121
  jobExecutionStatusSchema,
122
+ type StepAttemptDetailResponseDto,
123
+ stepAttemptDetailResponseSchema,
111
124
  type WorkflowRunDetailResponseDto,
112
125
  type WorkflowRunJobDetailDto,
113
126
  type WorkflowRunJobExecutionDetailDto,
@@ -9,6 +9,9 @@ const baseJob = {
9
9
  status: 'pending',
10
10
  status_reason: null,
11
11
  carried_over: false,
12
+ success: null,
13
+ runner: null,
14
+ evaluation_trace: null,
12
15
  listening: null,
13
16
  listener_status: 'inactive',
14
17
  resolution_reason: null,
@@ -39,4 +42,17 @@ describe('job DTO schema', () => {
39
42
 
40
43
  expect(result.status_reason).toBe(statusReason);
41
44
  });
45
+
46
+ it.each([
47
+ 'output_too_large',
48
+ 'output_invalid',
49
+ ] as const)('accepts job failure reason "%s"', (statusReason) => {
50
+ const result = jobDtoSchema.parse({
51
+ ...baseJob,
52
+ status: 'failed',
53
+ status_reason: statusReason,
54
+ });
55
+
56
+ expect(result.status_reason).toBe(statusReason);
57
+ });
42
58
  });
@@ -1,4 +1,5 @@
1
1
  import {z} from 'zod';
2
+ import {evaluationTraceSchema} from './evaluation-trace.js';
2
3
  import {
3
4
  jobListeningSchema,
4
5
  jobModeSchema,
@@ -25,8 +26,10 @@ export const jobStatusReasonSchema = z.enum([
25
26
  'run_cancelled',
26
27
  'timed_out',
27
28
  'runner_lost',
29
+ 'output_too_large',
28
30
  'step_failed',
29
31
  'unknown',
32
+ 'output_invalid',
30
33
  ]);
31
34
 
32
35
  export const jobDtoSchema = z.object({
@@ -38,6 +41,9 @@ export const jobDtoSchema = z.object({
38
41
  status: jobStatusSchema,
39
42
  status_reason: jobStatusReasonSchema.nullable(),
40
43
  carried_over: z.boolean(),
44
+ success: z.string().nullable(),
45
+ runner: z.array(z.string()).nullable(),
46
+ evaluation_trace: evaluationTraceSchema.nullable(),
41
47
  listening: jobListeningSchema.nullable(),
42
48
  listener_status: listenerStatusSchema,
43
49
  resolution_reason: resolutionReasonSchema.nullable(),
@@ -6,8 +6,10 @@ const baseStep = {
6
6
  key: null,
7
7
  name: 'echo hello',
8
8
  status: 'pending',
9
+ status_reason: null,
9
10
  type: 'run',
10
11
  config: {run: 'echo hello'},
12
+ evaluation_trace: null,
11
13
  error: null,
12
14
  position: 1,
13
15
  current_attempt: 1,
@@ -1,4 +1,10 @@
1
- import {STEP_ERROR_MESSAGE_MAX_LENGTH, stepAttemptDtoSchema, stepErrorDtoSchema} from './step.js';
1
+ import {
2
+ STEP_ERROR_MESSAGE_MAX_LENGTH,
3
+ STEP_STATUS_REASONS,
4
+ stepAttemptDtoSchema,
5
+ stepErrorDtoSchema,
6
+ stepStatusReasonSchema,
7
+ } from './step.js';
2
8
 
3
9
  const baseAttempt = {
4
10
  id: '11111111-1111-4111-8111-111111111111',
@@ -111,6 +117,16 @@ describe('stepErrorDtoSchema', () => {
111
117
  });
112
118
  });
113
119
 
120
+ describe('stepStatusReasonSchema', () => {
121
+ it.each(STEP_STATUS_REASONS)('accepts the domain reason %s', (reason) => {
122
+ expect(stepStatusReasonSchema.parse(reason)).toBe(reason);
123
+ });
124
+
125
+ it('rejects an unknown step status reason', () => {
126
+ expect(stepStatusReasonSchema.safeParse('runner_lost').success).toBe(false);
127
+ });
128
+ });
129
+
114
130
  describe('stepAttemptDtoSchema', () => {
115
131
  it('accepts an attempt with no gate or restart feedback', () => {
116
132
  const attempt = {...baseAttempt, gate_result: {kind: 'none'}};
@@ -1,4 +1,15 @@
1
1
  import {z} from 'zod';
2
+ import {evaluationTraceSchema} from './evaluation-trace.js';
3
+
4
+ export const STEP_STATUS_REASONS = [
5
+ 'default_gate_rejected',
6
+ 'condition_rejected',
7
+ 'condition_errored',
8
+ ] as const;
9
+
10
+ export const stepStatusReasonSchema = z.enum(STEP_STATUS_REASONS);
11
+
12
+ export type StepStatusReasonDto = z.infer<typeof stepStatusReasonSchema>;
2
13
 
3
14
  // Machine-readable cause of a step failure, for DB troubleshooting. The runner
4
15
  // reports it and the server stores it as-is. The `checkout_*`, `git_unavailable`,
@@ -86,8 +97,10 @@ export const stepDtoSchema = z.object({
86
97
  name: z.string(),
87
98
  source_location: stepSourceLocationSchema.nullable(),
88
99
  status: z.string(),
100
+ status_reason: stepStatusReasonSchema.nullable(),
89
101
  type: z.string(),
90
102
  config: z.record(z.string(), z.unknown()),
103
+ evaluation_trace: evaluationTraceSchema.nullable(),
91
104
  error: stepErrorDtoSchema,
92
105
  position: z.number(),
93
106
  // Execution-attempt identity of the current projection (>1 after a restart).
@@ -165,3 +178,10 @@ export const stepAttemptDtoSchema = z.object({
165
178
  });
166
179
 
167
180
  export type StepAttemptDto = z.infer<typeof stepAttemptDtoSchema>;
181
+
182
+ export const stepAttemptDetailDtoSchema = stepAttemptDtoSchema.extend({
183
+ config: z.record(z.string(), z.unknown()).nullable(),
184
+ evaluation_trace: evaluationTraceSchema.nullable(),
185
+ });
186
+
187
+ export type StepAttemptDetailDto = z.infer<typeof stepAttemptDetailDtoSchema>;
@@ -1,7 +1,8 @@
1
1
  import {z} from 'zod';
2
+ import {evaluationTraceSchema} from './evaluation-trace.js';
2
3
  import {jobDtoSchema} from './job.js';
3
4
  import {workflowExecutionEventSchema} from './job-listening.js';
4
- import {stepAttemptDtoSchema, stepDtoSchema} from './step.js';
5
+ import {stepAttemptDetailDtoSchema, stepAttemptDtoSchema, stepDtoSchema} from './step.js';
5
6
  import {workflowRunAttemptDtoSchema, workflowRunResponseSchema} from './workflow-run.js';
6
7
 
7
8
  export const jobExecutionStatusSchema = z.enum([
@@ -19,8 +20,11 @@ export const jobExecutionDtoSchema = z.object({
19
20
  name: z.string(),
20
21
  status: jobExecutionStatusSchema,
21
22
  status_reason: z.string().nullable(),
23
+ status_reason_message: z.string().nullable().optional(),
24
+ runner: z.array(z.string()).nullable(),
22
25
  trigger_events: z.array(workflowExecutionEventSchema).default([]),
23
26
  outputs: z.record(z.string(), z.unknown()).nullable(),
27
+ evaluation_trace: evaluationTraceSchema.nullable(),
24
28
  queued_at: z.string().nullable(),
25
29
  started_at: z.string().nullable(),
26
30
  finished_at: z.string().nullable(),
@@ -43,6 +47,16 @@ export const workflowRunStepDetailDtoSchema = stepDtoSchema.extend({
43
47
 
44
48
  export type WorkflowRunStepDetailDto = z.infer<typeof workflowRunStepDetailDtoSchema>;
45
49
 
50
+ export const stepAttemptDetailResponseSchema = z.object({
51
+ step_id: z.string().uuid(),
52
+ attempt: stepAttemptDetailDtoSchema.shape.attempt,
53
+ authored_config: z.record(z.string(), z.unknown()).nullable(),
54
+ config: stepAttemptDetailDtoSchema.shape.config,
55
+ evaluation_trace: stepAttemptDetailDtoSchema.shape.evaluation_trace,
56
+ });
57
+
58
+ export type StepAttemptDetailResponseDto = z.infer<typeof stepAttemptDetailResponseSchema>;
59
+
46
60
  export const workflowRunJobExecutionDetailDtoSchema = jobExecutionDtoSchema.extend({
47
61
  steps: z.array(workflowRunStepDetailDtoSchema),
48
62
  });