@happyrobot-ai/sdk 0.1.18 → 0.1.20

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.
package/README.md CHANGED
@@ -168,8 +168,9 @@ await client.workflows.duplicate("my-workflow", { name: "Copy" });
168
168
  await client.workflows.publish("my-workflow");
169
169
  await client.workflows.unpublish("my-workflow");
170
170
 
171
- // Cancel all active runs
171
+ // Cancel current and queued runs. By default, this also unpublishes the workflow.
172
172
  await client.workflows.cancelRuns("my-workflow");
173
+ await client.workflows.cancelRuns("my-workflow", { unpublish_workflow: false });
173
174
 
174
175
  // List templates
175
176
  const { data } = await client.workflows.listTemplates();
@@ -195,7 +196,7 @@ const { run_id } = await client.workflows.triggerRun("my-workflow", { payload: {
195
196
  | `duplicate(workflowId, body?)` | POST | `/workflows/:id/duplicate` | Duplicate a workflow |
196
197
  | `publish(workflowId, body?)` | POST | `/workflows/:id/publish` | Publish the latest version |
197
198
  | `unpublish(workflowId)` | POST | `/workflows/:id/unpublish` | Unpublish a workflow |
198
- | `cancelRuns(workflowId)` | POST | `/workflows/:id/cancel-runs` | Cancel all active runs |
199
+ | `cancelRuns(workflowId, body?)` | POST | `/workflows/:id/cancel-runs` | Cancel current and queued runs |
199
200
  | `listTemplates(query?)` | GET | `/workflows/templates` | List workflow templates |
200
201
  | `listVersions(workflowId, query?)` | GET | `/workflows/:id/versions` | List versions for a workflow |
201
202
  | `listRuns(workflowId, query?)` | GET | `/workflows/:id/runs` | List runs for a workflow |
package/core/http.js CHANGED
@@ -14,6 +14,19 @@ const DEFAULT_BASE_URL = exports.CLUSTER_URLS.us;
14
14
  const DEFAULT_TIMEOUT = 30_000;
15
15
  const DEFAULT_MAX_RETRIES = 2;
16
16
  const INITIAL_BACKOFF_MS = 500;
17
+ function buildRequestBody(config) {
18
+ if (config.rawBody !== undefined) {
19
+ // Don't set Content-Type — let the runtime set it (with multipart boundary)
20
+ return { body: config.rawBody };
21
+ }
22
+ if (config.body !== undefined) {
23
+ return {
24
+ body: JSON.stringify(config.body),
25
+ contentType: "application/json",
26
+ };
27
+ }
28
+ return { body: undefined };
29
+ }
17
30
  class HttpClient {
18
31
  apiKey;
19
32
  baseUrl;
@@ -67,8 +80,9 @@ class HttpClient {
67
80
  Accept: "application/json",
68
81
  ...config.headers,
69
82
  };
70
- if (config.body !== undefined) {
71
- headers["Content-Type"] = "application/json";
83
+ const { body: requestBody, contentType } = buildRequestBody(config);
84
+ if (contentType) {
85
+ headers["Content-Type"] = contentType;
72
86
  }
73
87
  let lastError;
74
88
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
@@ -76,9 +90,7 @@ class HttpClient {
76
90
  const response = await this.fetchWithTimeout(url, {
77
91
  method: config.method,
78
92
  headers,
79
- body: config.body !== undefined
80
- ? JSON.stringify(config.body)
81
- : undefined,
93
+ body: requestBody,
82
94
  }, timeout);
83
95
  if (response.ok) {
84
96
  if (response.status === 204) {
package/core/types.d.ts CHANGED
@@ -22,6 +22,8 @@ export interface RequestConfig {
22
22
  query?: Record<string, string | number | boolean | undefined>;
23
23
  /** JSON request body. */
24
24
  body?: unknown;
25
+ /** Raw body (e.g. FormData for multipart). Skips JSON serialization and Content-Type. */
26
+ rawBody?: FormData | Blob | ReadableStream;
25
27
  /** Additional headers. */
26
28
  headers?: Record<string, string>;
27
29
  /** Override timeout for this request. */
@@ -3,6 +3,8 @@ import type { RunNodeOutput } from "../types/runs.types";
3
3
  export interface TriggerAndWaitForNodeOutputOptions {
4
4
  workflowId: string;
5
5
  payload?: Record<string, unknown>;
6
+ /** File to upload (sends as multipart/form-data instead of JSON). */
7
+ file?: Blob | File;
6
8
  environment?: "production" | "staging" | "development";
7
9
  nodePersistentId: string;
8
10
  timeoutMs?: number;
@@ -17,8 +17,9 @@ const NODE_READY_STATUSES = new Set([
17
17
  "skipped",
18
18
  ]);
19
19
  async function triggerAndWaitForNodeOutput(client, options) {
20
- const { workflowId, payload, environment = "production", nodePersistentId, timeoutMs = 300_000, pollIntervalMs = 2_000, } = options;
20
+ const { workflowId, payload, file, environment = "production", nodePersistentId, timeoutMs = 300_000, pollIntervalMs = 2_000, } = options;
21
21
  const triggerResponse = await client.workflows.triggerRun(workflowId, {
22
+ file,
22
23
  payload,
23
24
  environment,
24
25
  });
@@ -9,6 +9,8 @@ export interface TriggerAndWaitOptions {
9
9
  workflowId: string;
10
10
  /** Trigger payload. */
11
11
  payload?: Record<string, unknown>;
12
+ /** File to upload (sends as multipart/form-data instead of JSON). */
13
+ file?: Blob | File;
12
14
  /** Target environment. */
13
15
  environment?: "production" | "staging" | "development";
14
16
  /** Maximum time to wait in milliseconds. Defaults to 300_000 (5 min). */
@@ -25,9 +25,10 @@ const TERMINAL_STATUSES = new Set([
25
25
  * ```
26
26
  */
27
27
  async function triggerAndWait(client, options) {
28
- const { workflowId, payload, environment = "production", timeoutMs = 300_000, pollIntervalMs = 2_000, fetchSessions = true, } = options;
28
+ const { workflowId, payload, file, environment = "production", timeoutMs = 300_000, pollIntervalMs = 2_000, fetchSessions = true, } = options;
29
29
  // 1. Trigger the run
30
30
  const { run_id } = await client.workflows.triggerRun(workflowId, {
31
+ file,
31
32
  payload,
32
33
  environment,
33
34
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyrobot-ai/sdk",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "TypeScript SDK for the HappyRobot Public API",
5
5
  "main": "./index.js",
6
6
  "module": "./index.mjs",
@@ -17,8 +17,8 @@
17
17
  * POST /workflows/:workflow_id/runs
18
18
  */
19
19
  import type { HttpClient } from "../core/http";
20
- import type { WorkflowRunsQuery, PaginatedWorkflowRunsResponse, TriggerRunBody, TriggerRunResponse } from "../types/runs.types";
21
- import type { ListWorkflowsQuery, WorkflowListItem, PaginatedWorkflowsResponse, CreateWorkflowBody, CreateWorkflowResponse, WorkflowDetailResponse, UpdateWorkflowBody, UpdateWorkflowResponse, DuplicateWorkflowBody, DuplicateWorkflowResponse, ListTemplatesQuery, PaginatedTemplatesResponse, WorkflowPublishResponse, WorkflowUnpublishResponse, CancelRunsResponse, ListWorkflowVersionsQuery, PaginatedWorkflowVersionsResponse } from "../types/workflows.types";
20
+ import type { WorkflowRunsQuery, PaginatedWorkflowRunsResponse, TriggerRunBody, TriggerRunResponse, TriggerRunWithFileBody } from "../types/runs.types";
21
+ import type { ListWorkflowsQuery, WorkflowListItem, PaginatedWorkflowsResponse, CreateWorkflowBody, CreateWorkflowResponse, WorkflowDetailResponse, UpdateWorkflowBody, UpdateWorkflowResponse, DuplicateWorkflowBody, DuplicateWorkflowResponse, ListTemplatesQuery, PaginatedTemplatesResponse, WorkflowPublishResponse, WorkflowUnpublishResponse, CancelRunsBody, CancelRunsResponse, ListWorkflowVersionsQuery, PaginatedWorkflowVersionsResponse } from "../types/workflows.types";
22
22
  export declare class WorkflowsResource {
23
23
  private readonly http;
24
24
  constructor(http: HttpClient);
@@ -42,14 +42,15 @@ export declare class WorkflowsResource {
42
42
  }): Promise<WorkflowPublishResponse>;
43
43
  /** Unpublish a workflow. */
44
44
  unpublish(workflowId: string): Promise<WorkflowUnpublishResponse>;
45
- /** Cancel all active runs for a workflow. */
46
- cancelRuns(workflowId: string): Promise<CancelRunsResponse>;
45
+ /** Cancel current and queued runs for a workflow. By default, this also unpublishes it. */
46
+ cancelRuns(workflowId: string, body?: CancelRunsBody): Promise<CancelRunsResponse>;
47
47
  /** List templates for workflow creation. */
48
48
  listTemplates(query?: ListTemplatesQuery): Promise<PaginatedTemplatesResponse>;
49
49
  /** List versions for a workflow. */
50
50
  listVersions(workflowId: string, query?: ListWorkflowVersionsQuery): Promise<PaginatedWorkflowVersionsResponse>;
51
51
  /** List runs for a workflow. */
52
52
  listRuns(workflowId: string, query?: WorkflowRunsQuery): Promise<PaginatedWorkflowRunsResponse>;
53
- /** Trigger a run for a workflow. */
54
- triggerRun(workflowId: string, body?: TriggerRunBody): Promise<TriggerRunResponse>;
53
+ /** Trigger a run for a workflow (JSON payload or file upload). */
54
+ triggerRun(workflowId: string, body?: TriggerRunBody | TriggerRunWithFileBody): Promise<TriggerRunResponse>;
55
+ private triggerRunWithFile;
55
56
  }
@@ -90,11 +90,12 @@ class WorkflowsResource {
90
90
  path: `/workflows/${encodeURIComponent(workflowId)}/unpublish`,
91
91
  });
92
92
  }
93
- /** Cancel all active runs for a workflow. */
94
- async cancelRuns(workflowId) {
93
+ /** Cancel current and queued runs for a workflow. By default, this also unpublishes it. */
94
+ async cancelRuns(workflowId, body) {
95
95
  return this.http.request({
96
96
  method: "POST",
97
97
  path: `/workflows/${encodeURIComponent(workflowId)}/cancel-runs`,
98
+ ...(body ? { body } : {}),
98
99
  });
99
100
  }
100
101
  /** List templates for workflow creation. */
@@ -121,14 +122,35 @@ class WorkflowsResource {
121
122
  query: query,
122
123
  });
123
124
  }
124
- /** Trigger a run for a workflow. */
125
+ /** Trigger a run for a workflow (JSON payload or file upload). */
125
126
  async triggerRun(workflowId, body) {
127
+ const path = `/workflows/${encodeURIComponent(workflowId)}/runs`;
128
+ if (body && "file" in body && body.file) {
129
+ return this.triggerRunWithFile(path, body);
130
+ }
126
131
  return this.http.request({
127
132
  method: "POST",
128
- path: `/workflows/${encodeURIComponent(workflowId)}/runs`,
133
+ path,
129
134
  body: body ?? {},
130
135
  });
131
136
  }
137
+ async triggerRunWithFile(path, body) {
138
+ const formData = new FormData();
139
+ formData.append("file", body.file);
140
+ if (body.payload) {
141
+ for (const [key, value] of Object.entries(body.payload)) {
142
+ if (value !== undefined && value !== null) {
143
+ formData.append(key, typeof value === "string" ? value : JSON.stringify(value));
144
+ }
145
+ }
146
+ }
147
+ return this.http.request({
148
+ method: "POST",
149
+ path,
150
+ rawBody: formData,
151
+ query: { environment: body.environment ?? "production" },
152
+ });
153
+ }
132
154
  }
133
155
  exports.WorkflowsResource = WorkflowsResource;
134
156
  //# sourceMappingURL=workflows.js.map
@@ -3,10 +3,11 @@
3
3
  */
4
4
  import type { z } from "zod";
5
5
  import type { RunDetailSchema, MarkRunBodySchema, MarkRunResponseSchema, ListFlagsQuerySchema, PaginatedFlagsResponseSchema, FlagItemSchema, GetRunOutputResponseSchema, ListRunNodesQuerySchema, ListRunNodesResponseSchema, RunNodeOutputSchema } from "../../routes/runs/schemas";
6
- import type { WorkflowRunsQuerySchema, PaginatedWorkflowRunsResponseSchema, TriggerRunBodySchema, TriggerRunResponseSchema } from "../../routes/workflows/:workflow_id/runs/schemas";
6
+ import type { WorkflowRunsQuerySchema, PaginatedWorkflowRunsResponseSchema, TriggerRunBodySchema, TriggerRunWithFileBodySchema, TriggerRunResponseSchema } from "../../routes/workflows/:workflow_id/runs/schemas";
7
7
  export type WorkflowRunsQuery = z.input<typeof WorkflowRunsQuerySchema>;
8
8
  export type PaginatedWorkflowRunsResponse = z.infer<typeof PaginatedWorkflowRunsResponseSchema>;
9
9
  export type TriggerRunBody = z.input<typeof TriggerRunBodySchema>;
10
+ export type TriggerRunWithFileBody = z.input<typeof TriggerRunWithFileBodySchema>;
10
11
  export type TriggerRunResponse = z.infer<typeof TriggerRunResponseSchema>;
11
12
  export type RunDetail = z.infer<typeof RunDetailSchema>;
12
13
  export type MarkRunBody = z.input<typeof MarkRunBodySchema>;
@@ -3,7 +3,7 @@
3
3
  * Uses import type — erased at compile time.
4
4
  */
5
5
  import type { z } from "zod";
6
- import type { ListWorkflowsQuerySchema, WorkflowListItemSchema, PaginatedWorkflowsResponseSchema, CreateWorkflowBodySchema, CreateWorkflowResponseSchema, WorkflowDetailResponseSchema, UpdateWorkflowBodySchema, UpdateWorkflowResponseSchema, DuplicateWorkflowBodySchema, DuplicateWorkflowResponseSchema, PaginatedTemplatesResponseSchema, ListTemplatesQuerySchema, WorkflowPublishResponseSchema, WorkflowPublishErrorResponseSchema, WorkflowUnpublishResponseSchema, CancelRunsResponseSchema, ListWorkflowVersionsQuerySchema, PaginatedWorkflowVersionsResponseSchema } from "../../routes/workflows/schemas";
6
+ import type { ListWorkflowsQuerySchema, WorkflowListItemSchema, PaginatedWorkflowsResponseSchema, CreateWorkflowBodySchema, CreateWorkflowResponseSchema, WorkflowDetailResponseSchema, UpdateWorkflowBodySchema, UpdateWorkflowResponseSchema, DuplicateWorkflowBodySchema, DuplicateWorkflowResponseSchema, PaginatedTemplatesResponseSchema, ListTemplatesQuerySchema, WorkflowPublishResponseSchema, WorkflowPublishErrorResponseSchema, WorkflowUnpublishResponseSchema, CancelRunsBodySchema, CancelRunsResponseSchema, ListWorkflowVersionsQuerySchema, PaginatedWorkflowVersionsResponseSchema } from "../../routes/workflows/schemas";
7
7
  export type ListWorkflowsQuery = z.output<typeof ListWorkflowsQuerySchema>;
8
8
  export type WorkflowListItem = z.infer<typeof WorkflowListItemSchema>;
9
9
  export type PaginatedWorkflowsResponse = z.infer<typeof PaginatedWorkflowsResponseSchema>;
@@ -19,6 +19,7 @@ export type PaginatedTemplatesResponse = z.infer<typeof PaginatedTemplatesRespon
19
19
  export type WorkflowPublishResponse = z.infer<typeof WorkflowPublishResponseSchema>;
20
20
  export type WorkflowPublishErrorResponse = z.infer<typeof WorkflowPublishErrorResponseSchema>;
21
21
  export type WorkflowUnpublishResponse = z.infer<typeof WorkflowUnpublishResponseSchema>;
22
+ export type CancelRunsBody = z.input<typeof CancelRunsBodySchema>;
22
23
  export type CancelRunsResponse = z.infer<typeof CancelRunsResponseSchema>;
23
24
  export type ListWorkflowVersionsQuery = z.input<typeof ListWorkflowVersionsQuerySchema>;
24
25
  export type PaginatedWorkflowVersionsResponse = z.infer<typeof PaginatedWorkflowVersionsResponseSchema>;
@@ -1,19 +0,0 @@
1
- /**
2
- * Common types shared across the SDK.
3
- * Extracted from Zod schemas using import type only — zero runtime cost.
4
- */
5
- import type { z } from "zod";
6
- import type { PaginationMetadataSchema } from "../../routes/shared/pagination";
7
- export type PaginationMetadata = z.infer<typeof PaginationMetadataSchema>;
8
- /** Standard paginated response shape. */
9
- export interface PaginatedResponse<T> {
10
- data: T[];
11
- pagination: PaginationMetadata;
12
- }
13
- /** Standard error response shape. */
14
- export interface ErrorResponse {
15
- error: string;
16
- message: string;
17
- statusCode: number;
18
- details?: unknown;
19
- }
@@ -1,7 +0,0 @@
1
- "use strict";
2
- /**
3
- * Common types shared across the SDK.
4
- * Extracted from Zod schemas using import type only — zero runtime cost.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- //# sourceMappingURL=common.types.js.map
@@ -1 +0,0 @@
1
- export * from "./common.types.js";