@outputai/cli 0.10.1-next.b7b2fbe.0 → 0.10.1-next.bf95a6f.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 (82) hide show
  1. package/dist/api/generated/api.d.ts +93 -26
  2. package/dist/api/generated/api.js +7 -4
  3. package/dist/api/http_client.js +2 -2
  4. package/dist/assets/docker/docker-compose-dev.yml +2 -2
  5. package/dist/commands/dev/down.d.ts +10 -0
  6. package/dist/commands/dev/down.js +34 -0
  7. package/dist/commands/dev/down.spec.js +71 -0
  8. package/dist/commands/dev/index.d.ts +4 -0
  9. package/dist/commands/dev/index.js +200 -53
  10. package/dist/commands/dev/index.spec.js +390 -42
  11. package/dist/commands/workflow/history.js +3 -3
  12. package/dist/commands/workflow/history.spec.js +31 -2
  13. package/dist/commands/workflow/monitor.d.ts +49 -0
  14. package/dist/commands/workflow/monitor.js +230 -0
  15. package/dist/commands/workflow/monitor.spec.d.ts +1 -0
  16. package/dist/commands/workflow/monitor.spec.js +243 -0
  17. package/dist/commands/workflow/result.js +2 -2
  18. package/dist/commands/workflow/result.spec.js +65 -1
  19. package/dist/commands/workflow/run.js +10 -3
  20. package/dist/commands/workflow/run.spec.js +42 -5
  21. package/dist/commands/workflow/start.d.ts +3 -1
  22. package/dist/commands/workflow/start.js +12 -2
  23. package/dist/commands/workflow/start.spec.js +30 -5
  24. package/dist/commands/workflow/status.spec.js +1 -1
  25. package/dist/commands/workflow/{test_eval.d.ts → test.d.ts} +0 -1
  26. package/dist/commands/workflow/{test_eval.js → test.js} +0 -1
  27. package/dist/commands/workflow/test.spec.d.ts +1 -0
  28. package/dist/commands/workflow/{test_eval.spec.js → test.spec.js} +4 -4
  29. package/dist/generated/framework_version.json +1 -1
  30. package/dist/services/docker.d.ts +28 -1
  31. package/dist/services/docker.js +106 -12
  32. package/dist/services/docker.spec.js +144 -14
  33. package/dist/services/workflow_history/correlator.d.ts +2 -0
  34. package/dist/services/workflow_history/correlator.js +2 -2
  35. package/dist/services/workflow_history.d.ts +28 -0
  36. package/dist/services/workflow_history.js +95 -12
  37. package/dist/services/workflow_history.spec.js +183 -1
  38. package/dist/templates/agent_instructions/CLAUDE.md.template +5 -3
  39. package/dist/templates/project/README.md.template +3 -1
  40. package/dist/templates/project/package.json.template +2 -2
  41. package/dist/templates/project/src/clients/jina.ts.template +4 -4
  42. package/dist/utils/color.d.ts +7 -0
  43. package/dist/utils/color.js +12 -0
  44. package/dist/utils/color.spec.d.ts +1 -0
  45. package/dist/utils/color.spec.js +43 -0
  46. package/dist/utils/env_loader.js +6 -2
  47. package/dist/utils/env_loader.spec.js +61 -32
  48. package/dist/utils/format_workflow_result.d.ts +4 -2
  49. package/dist/utils/format_workflow_result.js +10 -2
  50. package/dist/utils/format_workflow_result.spec.js +39 -6
  51. package/dist/utils/monitor_log.d.ts +20 -0
  52. package/dist/utils/monitor_log.js +48 -0
  53. package/dist/utils/monitor_log.spec.d.ts +1 -0
  54. package/dist/utils/monitor_log.spec.js +71 -0
  55. package/dist/utils/normalize_workflow_status.d.ts +4 -3
  56. package/dist/utils/normalize_workflow_status.js +12 -3
  57. package/dist/utils/normalize_workflow_status.spec.js +3 -0
  58. package/dist/utils/port_collision.d.ts +22 -7
  59. package/dist/utils/port_collision.js +39 -14
  60. package/dist/utils/port_collision.spec.js +40 -1
  61. package/dist/utils/resolve_input.d.ts +9 -1
  62. package/dist/utils/resolve_input.js +8 -2
  63. package/dist/utils/resolve_input.spec.d.ts +1 -0
  64. package/dist/utils/resolve_input.spec.js +75 -0
  65. package/dist/utils/waterfall.d.ts +3 -1
  66. package/dist/utils/waterfall.js +8 -2
  67. package/dist/views/dev/chrome/footer.d.ts +2 -0
  68. package/dist/views/dev/chrome/footer.js +4 -4
  69. package/dist/views/dev/components/workflow_status.js +1 -1
  70. package/dist/views/dev/dev_app.d.ts +1 -0
  71. package/dist/views/dev/dev_app.js +13 -4
  72. package/dist/views/dev/hooks/use_run_detail.js +8 -9
  73. package/dist/views/dev/hooks/use_run_detail.spec.js +1 -1
  74. package/dist/views/dev/hooks/use_step_graph.js +3 -1
  75. package/dist/views/dev/panels/runs_panel.js +2 -2
  76. package/dist/views/dev/utils/bounded_cache.d.ts +14 -0
  77. package/dist/views/dev/utils/bounded_cache.js +42 -0
  78. package/dist/views/dev/utils/bounded_cache.spec.d.ts +1 -0
  79. package/dist/views/dev/utils/bounded_cache.spec.js +53 -0
  80. package/oclif.manifest.json +126 -10
  81. package/package.json +7 -9
  82. /package/dist/commands/{workflow/test_eval.spec.d.ts → dev/down.spec.d.ts} +0 -0
@@ -66,22 +66,29 @@ export interface Workflow {
66
66
  /** Alternative names that resolve to this workflow */
67
67
  aliases?: string[];
68
68
  }
69
+ /**
70
+ * Legacy trace information containing nested destinations
71
+ * @nullable
72
+ */
73
+ export type TraceInfoV1 = {
74
+ /** Available destinations for trace data */
75
+ destinations?: {
76
+ /** Absolute path to local trace file, omitted if not saved locally */
77
+ local?: string;
78
+ /** Remote trace location (e.g., S3 URI), omitted if not saved remotely */
79
+ remote?: string;
80
+ };
81
+ } | null;
69
82
  /**
70
83
  * Available destinations for trace data
84
+ * @nullable
71
85
  */
72
- export type TraceInfoDestinations = {
86
+ export type TraceInfoV2 = {
73
87
  /** Absolute path to local trace file, omitted if not saved locally */
74
88
  local?: string;
75
89
  /** Remote trace location (e.g., S3 URI), omitted if not saved remotely */
76
90
  remote?: string;
77
- };
78
- /**
79
- * An object with information about the trace generated by the execution
80
- */
81
- export interface TraceInfo {
82
- /** Available destinations for trace data */
83
- destinations?: TraceInfoDestinations;
84
- }
91
+ } | null;
85
92
  /**
86
93
  * The workflow input
87
94
  */
@@ -148,7 +155,7 @@ export declare const WorkflowRunInfoStatus: {
148
155
  readonly running: "running";
149
156
  readonly completed: "completed";
150
157
  readonly failed: "failed";
151
- readonly canceled: "canceled";
158
+ readonly cancelled: "cancelled";
152
159
  readonly terminated: "terminated";
153
160
  readonly timed_out: "timed_out";
154
161
  readonly continued_as_new: "continued_as_new";
@@ -180,7 +187,7 @@ export interface WorkflowRunsResponse {
180
187
  */
181
188
  export type WorkflowStatusResponseStatus = typeof WorkflowStatusResponseStatus[keyof typeof WorkflowStatusResponseStatus];
182
189
  export declare const WorkflowStatusResponseStatus: {
183
- readonly canceled: "canceled";
190
+ readonly cancelled: "cancelled";
184
191
  readonly completed: "completed";
185
192
  readonly continued_as_new: "continued_as_new";
186
193
  readonly failed: "failed";
@@ -204,20 +211,33 @@ export interface WorkflowStatusResponse {
204
211
  /**
205
212
  * The workflow execution status
206
213
  */
207
- export type WorkflowResultResponseStatus = typeof WorkflowResultResponseStatus[keyof typeof WorkflowResultResponseStatus];
208
- export declare const WorkflowResultResponseStatus: {
214
+ export type WorkflowResultStatus = typeof WorkflowResultStatus[keyof typeof WorkflowResultStatus];
215
+ export declare const WorkflowResultStatus: {
209
216
  readonly completed: "completed";
210
217
  readonly failed: "failed";
211
- readonly canceled: "canceled";
218
+ readonly cancelled: "cancelled";
212
219
  readonly terminated: "terminated";
213
220
  readonly timed_out: "timed_out";
214
221
  readonly continued_as_new: "continued_as_new";
215
222
  };
223
+ /**
224
+ * Structured error details captured from the workflow or activity failure
225
+ * @nullable
226
+ */
227
+ export type SerializedWorkflowError = {
228
+ /** Failing activity type, omitted when the failure did not originate in an activity */
229
+ activityType?: string;
230
+ /** Original error class name */
231
+ name?: string;
232
+ /** Original error message */
233
+ message?: string;
234
+ [key: string]: unknown;
235
+ } | null;
216
236
  /**
217
237
  * Structured failure details if the workflow failed, null otherwise
218
238
  * @nullable
219
239
  */
220
- export type WorkflowResultResponseErrorDetails = {
240
+ export type WorkflowResultV1ResponseErrorDetails = {
221
241
  /**
222
242
  * Friendly failure message (from the underlying application error)
223
243
  * @nullable
@@ -246,29 +266,64 @@ export type WorkflowResultResponseErrorDetails = {
246
266
  [key: string]: unknown;
247
267
  } | null;
248
268
  } | null | null;
249
- export interface WorkflowResultResponse {
269
+ /**
270
+ * Legacy wrapped workflow result
271
+ * @deprecated
272
+ */
273
+ export interface WorkflowResultV1Response {
250
274
  /** The workflow execution id */
251
- workflowId?: string;
252
- /** The specific run id for this execution */
253
- runId?: string;
275
+ workflowId: string;
276
+ /**
277
+ * The specific run id for this execution
278
+ * @nullable
279
+ */
280
+ runId: string | null;
281
+ status: WorkflowResultStatus;
254
282
  /** The original input passed to the workflow, null if unavailable */
255
- input?: unknown;
283
+ input: unknown | null;
256
284
  /** The result of workflow, null if workflow failed */
257
- output?: unknown;
258
- trace?: TraceInfo;
259
- /** The workflow execution status */
260
- status?: WorkflowResultResponseStatus;
285
+ output: unknown | null;
286
+ trace: TraceInfoV1 | null;
261
287
  /**
262
288
  * Error message if workflow failed, null otherwise
263
289
  * @nullable
264
290
  */
265
- error?: string | null;
291
+ error: string | null;
266
292
  /**
267
293
  * Structured failure details if the workflow failed, null otherwise
268
294
  * @nullable
269
295
  */
270
- errorDetails?: WorkflowResultResponseErrorDetails;
296
+ errorDetails: WorkflowResultV1ResponseErrorDetails;
271
297
  }
298
+ /**
299
+ * Workflow result response version
300
+ */
301
+ export type WorkflowResultV2ResponseV = typeof WorkflowResultV2ResponseV[keyof typeof WorkflowResultV2ResponseV];
302
+ export declare const WorkflowResultV2ResponseV: {
303
+ readonly NUMBER_2: "2";
304
+ };
305
+ /**
306
+ * Current workflow result with direct output and memo-based trace information
307
+ */
308
+ export interface WorkflowResultV2Response {
309
+ /** Workflow result response version */
310
+ v: WorkflowResultV2ResponseV;
311
+ /** The workflow execution id */
312
+ workflowId: string;
313
+ /**
314
+ * The specific run id for this execution
315
+ * @nullable
316
+ */
317
+ runId: string | null;
318
+ status: WorkflowResultStatus;
319
+ /** The original input passed to the workflow, null if unavailable */
320
+ input: unknown | null;
321
+ /** Direct workflow output, null if no output is available */
322
+ output: unknown | null;
323
+ trace: TraceInfoV2 | null;
324
+ error: (SerializedWorkflowError | null) | null;
325
+ }
326
+ export type WorkflowResultResponse = WorkflowResultV2Response | WorkflowResultV1Response;
272
327
  export interface WorkflowInputResponse {
273
328
  /** The workflow execution id */
274
329
  workflowId: string;
@@ -393,6 +448,12 @@ export type GetWorkflowIdHistoryParams = {
393
448
  * Include decoded input/output payloads in events
394
449
  */
395
450
  includePayloads?: boolean;
451
+ /**
452
+ * When set, long-poll for a new event once caught up to the end of history instead of returning immediately, bounding the block by this many milliseconds. Clamped to the server's configured maximum — a caller can shorten the wait but never exceed it. Omit for an immediate response; on timeout returns the same page's cursor unchanged with an empty events array so the caller can retry. Lets a poller keep the block roughly aligned with its own tick interval.
453
+
454
+ * @minimum 1
455
+ */
456
+ longPollTimeoutMs?: number;
396
457
  };
397
458
  /**
398
459
  * Workflow metadata (null on subsequent pages)
@@ -431,6 +492,12 @@ export type GetWorkflowIdRunsRidHistoryParams = {
431
492
  * Include decoded input/output payloads in events
432
493
  */
433
494
  includePayloads?: boolean;
495
+ /**
496
+ * When set, long-poll for a new event once caught up to the end of history instead of returning immediately, bounding the block by this many milliseconds. Clamped to the server's configured maximum — a caller can shorten the wait but never exceed it. Omit for an immediate response; on timeout returns the same page's cursor unchanged with an empty events array so the caller can retry. Lets a poller keep the block roughly aligned with its own tick interval.
497
+
498
+ * @minimum 1
499
+ */
500
+ longPollTimeoutMs?: number;
434
501
  };
435
502
  /**
436
503
  * Workflow metadata (null on subsequent pages)
@@ -19,13 +19,13 @@ export const WorkflowRunInfoStatus = {
19
19
  running: 'running',
20
20
  completed: 'completed',
21
21
  failed: 'failed',
22
- canceled: 'canceled',
22
+ cancelled: 'cancelled',
23
23
  terminated: 'terminated',
24
24
  timed_out: 'timed_out',
25
25
  continued_as_new: 'continued_as_new',
26
26
  };
27
27
  export const WorkflowStatusResponseStatus = {
28
- canceled: 'canceled',
28
+ cancelled: 'cancelled',
29
29
  completed: 'completed',
30
30
  continued_as_new: 'continued_as_new',
31
31
  failed: 'failed',
@@ -34,14 +34,17 @@ export const WorkflowStatusResponseStatus = {
34
34
  timed_out: 'timed_out',
35
35
  unspecified: 'unspecified',
36
36
  };
37
- export const WorkflowResultResponseStatus = {
37
+ export const WorkflowResultStatus = {
38
38
  completed: 'completed',
39
39
  failed: 'failed',
40
- canceled: 'canceled',
40
+ cancelled: 'cancelled',
41
41
  terminated: 'terminated',
42
42
  timed_out: 'timed_out',
43
43
  continued_as_new: 'continued_as_new',
44
44
  };
45
+ export const WorkflowResultV2ResponseV = {
46
+ NUMBER_2: '2',
47
+ };
45
48
  ;
46
49
  export const getGetHealthUrl = () => {
47
50
  return `/health`;
@@ -18,7 +18,7 @@ const apiState = {};
18
18
  function getApi() {
19
19
  if (!apiState.api) {
20
20
  apiState.api = ky.create({
21
- prefixUrl: config.apiUrl,
21
+ prefix: config.apiUrl,
22
22
  timeout: config.requestTimeout,
23
23
  retry: {
24
24
  limit: 2,
@@ -28,7 +28,7 @@ function getApi() {
28
28
  throwHttpErrors: false,
29
29
  hooks: {
30
30
  beforeRequest: [
31
- request => {
31
+ ({ request }) => {
32
32
  if (config.apiToken) {
33
33
  request.headers.set('Authorization', `Basic ${config.apiToken}`);
34
34
  }
@@ -80,7 +80,7 @@ services:
80
80
  condition: service_healthy
81
81
  worker:
82
82
  condition: service_healthy
83
- image: outputai/api:${OUTPUT_API_VERSION:-0.10.1-next.b7b2fbe.0}
83
+ image: outputai/api:${OUTPUT_API_VERSION:-0.10.1-next.bf95a6f.0}
84
84
  init: true
85
85
  networks:
86
86
  - main
@@ -118,7 +118,7 @@ services:
118
118
  - OUTPUT_CATALOG_ID=${OUTPUT_CATALOG_ID:-main}
119
119
  - OUTPUT_REDIS_URL=redis://redis:6379
120
120
  - OUTPUT_TRACE_LOCAL_ON=${OUTPUT_TRACE_LOCAL_ON:-true}
121
- - OUTPUT_TRACE_HOST_PATH=${PWD}/logs
121
+ - OUTPUT_TRACE_HOST_PATH=${OUTPUT_TRACE_HOST_PATH:-${PWD}/logs}
122
122
  - OUTPUT_TRACE_HTTP_VERBOSE=${OUTPUT_TRACE_HTTP_VERBOSE:-true}
123
123
  - OUTPUT_ENABLE_ATTRIBUTE_SIGNAL_EMISSION=${OUTPUT_ENABLE_ATTRIBUTE_SIGNAL_EMISSION:-false}
124
124
  - TEMPORAL_ADDRESS=temporal:7233
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DevDown extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {};
6
+ static flags: {
7
+ 'compose-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,34 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { validateDockerEnvironment, stopDockerCompose, resolveDockerComposePath } from '#services/docker.js';
3
+ import { getErrorMessage } from '#utils/error_utils.js';
4
+ export default class DevDown extends Command {
5
+ static description = [
6
+ 'Stop Output development services started by `output dev`',
7
+ '',
8
+ 'Useful after `output dev -d`, or when an attached `output dev` session',
9
+ 'left the services running on quit.'
10
+ ].join('\n');
11
+ static examples = [
12
+ '<%= config.bin %> <%= command.id %>',
13
+ '<%= config.bin %> <%= command.id %> --compose-file ./custom-docker-compose.yml'
14
+ ];
15
+ static args = {};
16
+ static flags = {
17
+ 'compose-file': Flags.string({
18
+ description: 'Path to a custom docker-compose file',
19
+ required: false,
20
+ char: 'f'
21
+ })
22
+ };
23
+ async run() {
24
+ const { flags } = await this.parse(DevDown);
25
+ validateDockerEnvironment();
26
+ try {
27
+ const dockerComposePath = await resolveDockerComposePath(flags['compose-file']);
28
+ await stopDockerCompose(dockerComposePath);
29
+ }
30
+ catch (error) {
31
+ this.error(getErrorMessage(error), { exit: 1 });
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,71 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
+ import * as dockerService from '#services/docker.js';
4
+ import DevDown from './down.js';
5
+ vi.mock('#services/docker.js', () => ({
6
+ validateDockerEnvironment: vi.fn(),
7
+ stopDockerCompose: vi.fn().mockResolvedValue(undefined),
8
+ resolveDockerComposePath: vi.fn().mockResolvedValue('/path/to/docker-compose-dev.yml')
9
+ }));
10
+ const makeCmd = () => {
11
+ const cmd = new DevDown([], {});
12
+ cmd.log = vi.fn();
13
+ cmd.error = vi.fn();
14
+ Object.defineProperty(cmd, 'parse', {
15
+ value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined }, args: {} }),
16
+ configurable: true
17
+ });
18
+ return cmd;
19
+ };
20
+ describe('dev down command', () => {
21
+ beforeEach(() => {
22
+ vi.clearAllMocks();
23
+ vi.mocked(dockerService.validateDockerEnvironment).mockReturnValue(undefined);
24
+ vi.mocked(dockerService.stopDockerCompose).mockResolvedValue(undefined);
25
+ vi.mocked(dockerService.resolveDockerComposePath).mockResolvedValue('/path/to/docker-compose-dev.yml');
26
+ });
27
+ afterEach(() => {
28
+ vi.restoreAllMocks();
29
+ });
30
+ describe('command structure', () => {
31
+ it('should have a description mentioning stopping services', () => {
32
+ expect(DevDown.description).toBeDefined();
33
+ expect(DevDown.description).toContain('Stop');
34
+ });
35
+ it('should have no required arguments', () => {
36
+ expect(Object.keys(DevDown.args)).toHaveLength(0);
37
+ });
38
+ it('should have a compose-file flag', () => {
39
+ expect(DevDown.flags['compose-file']).toBeDefined();
40
+ expect(DevDown.flags['compose-file'].char).toBe('f');
41
+ });
42
+ });
43
+ describe('run', () => {
44
+ it('validates docker and stops the default stack', async () => {
45
+ const cmd = makeCmd();
46
+ await cmd.run();
47
+ expect(dockerService.validateDockerEnvironment).toHaveBeenCalled();
48
+ expect(dockerService.stopDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml');
49
+ expect(cmd.error).not.toHaveBeenCalled();
50
+ });
51
+ it('errors with the command formatter when the compose file is missing', async () => {
52
+ vi.mocked(dockerService.resolveDockerComposePath).mockRejectedValue(new Error('File not found'));
53
+ const cmd = makeCmd();
54
+ cmd.error = vi.fn(() => {
55
+ throw new Error('oclif-error-thrown');
56
+ });
57
+ await expect(cmd.run()).rejects.toThrow();
58
+ expect(cmd.error).toHaveBeenCalledWith(expect.stringContaining('File not found'), { exit: 1 });
59
+ expect(dockerService.stopDockerCompose).not.toHaveBeenCalled();
60
+ });
61
+ it('surfaces a teardown failure as an actionable error', async () => {
62
+ vi.mocked(dockerService.stopDockerCompose).mockRejectedValue(new Error('compose down failed'));
63
+ const cmd = makeCmd();
64
+ cmd.error = vi.fn(() => {
65
+ throw new Error('oclif-error-thrown');
66
+ });
67
+ await expect(cmd.run()).rejects.toThrow();
68
+ expect(cmd.error).toHaveBeenCalledWith(expect.stringContaining('compose down failed'), { exit: 1 });
69
+ });
70
+ });
71
+ });
@@ -10,4 +10,8 @@ export default class Dev extends Command {
10
10
  };
11
11
  private dockerProcess;
12
12
  run(): Promise<void>;
13
+ private probePorts;
14
+ private probePortsIfFreshStart;
15
+ private getServiceStatusOrWarn;
16
+ private upDetachedOrError;
13
17
  }