@scenario-labs/sdk 0.2.0 → 1.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 (218) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +44 -8
  3. package/client.d.mts +36 -16
  4. package/client.d.mts.map +1 -1
  5. package/client.d.ts +36 -16
  6. package/client.d.ts.map +1 -1
  7. package/client.js +21 -11
  8. package/client.js.map +1 -1
  9. package/client.mjs +21 -11
  10. package/client.mjs.map +1 -1
  11. package/core/pagination.d.mts +153 -0
  12. package/core/pagination.d.mts.map +1 -0
  13. package/core/pagination.d.ts +153 -0
  14. package/core/pagination.d.ts.map +1 -0
  15. package/core/pagination.js +276 -0
  16. package/core/pagination.js.map +1 -0
  17. package/core/pagination.mjs +263 -0
  18. package/core/pagination.mjs.map +1 -0
  19. package/index.d.mts +3 -0
  20. package/index.d.mts.map +1 -1
  21. package/index.d.ts +3 -0
  22. package/index.d.ts.map +1 -1
  23. package/index.js +9 -1
  24. package/index.js.map +1 -1
  25. package/index.mjs +3 -0
  26. package/index.mjs.map +1 -1
  27. package/internal/request-options.d.mts +1 -1
  28. package/internal/request-options.d.mts.map +1 -1
  29. package/internal/request-options.d.ts +1 -1
  30. package/internal/request-options.d.ts.map +1 -1
  31. package/lib/models.d.mts +34 -2
  32. package/lib/models.d.mts.map +1 -1
  33. package/lib/models.d.ts +34 -2
  34. package/lib/models.d.ts.map +1 -1
  35. package/lib/models.js +39 -2
  36. package/lib/models.js.map +1 -1
  37. package/lib/models.mjs +37 -1
  38. package/lib/models.mjs.map +1 -1
  39. package/lib/scenario.d.mts +2 -0
  40. package/lib/scenario.d.mts.map +1 -1
  41. package/lib/scenario.d.ts +2 -0
  42. package/lib/scenario.d.ts.map +1 -1
  43. package/lib/scenario.js +2 -0
  44. package/lib/scenario.js.map +1 -1
  45. package/lib/scenario.mjs +2 -0
  46. package/lib/scenario.mjs.map +1 -1
  47. package/lib/upload.d.mts +89 -0
  48. package/lib/upload.d.mts.map +1 -0
  49. package/lib/upload.d.ts +89 -0
  50. package/lib/upload.d.ts.map +1 -0
  51. package/lib/upload.js +193 -0
  52. package/lib/upload.js.map +1 -0
  53. package/lib/upload.mjs +156 -0
  54. package/lib/upload.mjs.map +1 -0
  55. package/lib/workflow.d.mts +19 -3
  56. package/lib/workflow.d.mts.map +1 -1
  57. package/lib/workflow.d.ts +19 -3
  58. package/lib/workflow.d.ts.map +1 -1
  59. package/lib/workflow.js +26 -5
  60. package/lib/workflow.js.map +1 -1
  61. package/lib/workflow.mjs +26 -5
  62. package/lib/workflow.mjs.map +1 -1
  63. package/lib/workflow_import_validator.d.mts +40 -0
  64. package/lib/workflow_import_validator.d.mts.map +1 -0
  65. package/lib/workflow_import_validator.d.ts +40 -0
  66. package/lib/workflow_import_validator.d.ts.map +1 -0
  67. package/lib/workflow_import_validator.js +69 -0
  68. package/lib/workflow_import_validator.js.map +1 -0
  69. package/lib/workflow_import_validator.mjs +64 -0
  70. package/lib/workflow_import_validator.mjs.map +1 -0
  71. package/lib/workflow_validator.d.mts +22 -0
  72. package/lib/workflow_validator.d.mts.map +1 -0
  73. package/lib/workflow_validator.d.ts +22 -0
  74. package/lib/workflow_validator.d.ts.map +1 -0
  75. package/lib/workflow_validator.js +124 -0
  76. package/lib/workflow_validator.js.map +1 -0
  77. package/lib/workflow_validator.mjs +121 -0
  78. package/lib/workflow_validator.mjs.map +1 -0
  79. package/package.json +11 -1
  80. package/pagination.d.mts +2 -0
  81. package/pagination.d.mts.map +1 -0
  82. package/pagination.d.ts +2 -0
  83. package/pagination.d.ts.map +1 -0
  84. package/pagination.js +6 -0
  85. package/pagination.js.map +1 -0
  86. package/pagination.mjs +2 -0
  87. package/pagination.mjs.map +1 -0
  88. package/resources/assets/assets.d.mts +631 -648
  89. package/resources/assets/assets.d.mts.map +1 -1
  90. package/resources/assets/assets.d.ts +631 -648
  91. package/resources/assets/assets.d.ts.map +1 -1
  92. package/resources/assets/assets.js +5 -4
  93. package/resources/assets/assets.js.map +1 -1
  94. package/resources/assets/assets.mjs +5 -4
  95. package/resources/assets/assets.mjs.map +1 -1
  96. package/resources/assets/index.d.mts +1 -1
  97. package/resources/assets/index.d.mts.map +1 -1
  98. package/resources/assets/index.d.ts +1 -1
  99. package/resources/assets/index.d.ts.map +1 -1
  100. package/resources/assets/index.js.map +1 -1
  101. package/resources/assets/index.mjs.map +1 -1
  102. package/resources/collections/assets.d.mts +8 -2
  103. package/resources/collections/assets.d.mts.map +1 -1
  104. package/resources/collections/assets.d.ts +8 -2
  105. package/resources/collections/assets.d.ts.map +1 -1
  106. package/resources/collections/assets.js +2 -2
  107. package/resources/collections/assets.js.map +1 -1
  108. package/resources/collections/assets.mjs +2 -2
  109. package/resources/collections/assets.mjs.map +1 -1
  110. package/resources/collections/collections.d.mts +42 -53
  111. package/resources/collections/collections.d.mts.map +1 -1
  112. package/resources/collections/collections.d.ts +42 -53
  113. package/resources/collections/collections.d.ts.map +1 -1
  114. package/resources/collections/collections.js +5 -1
  115. package/resources/collections/collections.js.map +1 -1
  116. package/resources/collections/collections.mjs +5 -1
  117. package/resources/collections/collections.mjs.map +1 -1
  118. package/resources/collections/index.d.mts +3 -3
  119. package/resources/collections/index.d.mts.map +1 -1
  120. package/resources/collections/index.d.ts +3 -3
  121. package/resources/collections/index.d.ts.map +1 -1
  122. package/resources/collections/index.js.map +1 -1
  123. package/resources/collections/index.mjs +2 -2
  124. package/resources/collections/index.mjs.map +1 -1
  125. package/resources/collections/models.d.mts +8 -2
  126. package/resources/collections/models.d.mts.map +1 -1
  127. package/resources/collections/models.d.ts +8 -2
  128. package/resources/collections/models.d.ts.map +1 -1
  129. package/resources/collections/models.js +2 -2
  130. package/resources/collections/models.js.map +1 -1
  131. package/resources/collections/models.mjs +2 -2
  132. package/resources/collections/models.mjs.map +1 -1
  133. package/resources/index.d.mts +7 -7
  134. package/resources/index.d.mts.map +1 -1
  135. package/resources/index.d.ts +7 -7
  136. package/resources/index.d.ts.map +1 -1
  137. package/resources/index.js.map +1 -1
  138. package/resources/index.mjs.map +1 -1
  139. package/resources/jobs.d.mts +369 -380
  140. package/resources/jobs.d.mts.map +1 -1
  141. package/resources/jobs.d.ts +369 -380
  142. package/resources/jobs.d.ts.map +1 -1
  143. package/resources/jobs.js +2 -1
  144. package/resources/jobs.js.map +1 -1
  145. package/resources/jobs.mjs +2 -1
  146. package/resources/jobs.mjs.map +1 -1
  147. package/resources/models/index.d.mts +1 -1
  148. package/resources/models/index.d.mts.map +1 -1
  149. package/resources/models/index.d.ts +1 -1
  150. package/resources/models/index.d.ts.map +1 -1
  151. package/resources/models/index.js.map +1 -1
  152. package/resources/models/index.mjs.map +1 -1
  153. package/resources/models/models.d.mts +956 -967
  154. package/resources/models/models.d.mts.map +1 -1
  155. package/resources/models/models.d.ts +956 -967
  156. package/resources/models/models.d.ts.map +1 -1
  157. package/resources/models/models.js +2 -1
  158. package/resources/models/models.js.map +1 -1
  159. package/resources/models/models.mjs +2 -1
  160. package/resources/models/models.mjs.map +1 -1
  161. package/resources/models/train.d.mts +38 -38
  162. package/resources/models/train.d.mts.map +1 -1
  163. package/resources/models/train.d.ts +38 -38
  164. package/resources/models/train.d.ts.map +1 -1
  165. package/resources/search.d.mts +215 -295
  166. package/resources/search.d.mts.map +1 -1
  167. package/resources/search.d.ts +215 -295
  168. package/resources/search.d.ts.map +1 -1
  169. package/resources/search.js +9 -2
  170. package/resources/search.js.map +1 -1
  171. package/resources/search.mjs +9 -2
  172. package/resources/search.mjs.map +1 -1
  173. package/resources/tags.d.mts +23 -35
  174. package/resources/tags.d.mts.map +1 -1
  175. package/resources/tags.d.ts +23 -35
  176. package/resources/tags.d.ts.map +1 -1
  177. package/resources/tags.js +2 -1
  178. package/resources/tags.js.map +1 -1
  179. package/resources/tags.mjs +2 -1
  180. package/resources/tags.mjs.map +1 -1
  181. package/resources/workflows.d.mts +688 -704
  182. package/resources/workflows.d.mts.map +1 -1
  183. package/resources/workflows.d.ts +688 -704
  184. package/resources/workflows.d.ts.map +1 -1
  185. package/resources/workflows.js +5 -1
  186. package/resources/workflows.js.map +1 -1
  187. package/resources/workflows.mjs +5 -1
  188. package/resources/workflows.mjs.map +1 -1
  189. package/src/client.ts +118 -15
  190. package/src/core/pagination.ts +497 -0
  191. package/src/index.ts +9 -0
  192. package/src/internal/request-options.ts +1 -1
  193. package/src/lib/models.ts +62 -2
  194. package/src/lib/scenario.ts +2 -0
  195. package/src/lib/upload.ts +250 -0
  196. package/src/lib/workflow.ts +39 -5
  197. package/src/lib/workflow_import_validator.ts +104 -0
  198. package/src/lib/workflow_validator.ts +167 -0
  199. package/src/pagination.ts +2 -0
  200. package/src/resources/assets/assets.ts +971 -905
  201. package/src/resources/assets/index.ts +3 -0
  202. package/src/resources/collections/assets.ts +14 -2
  203. package/src/resources/collections/collections.ts +49 -56
  204. package/src/resources/collections/index.ts +15 -2
  205. package/src/resources/collections/models.ts +14 -2
  206. package/src/resources/index.ts +10 -1
  207. package/src/resources/jobs.ts +613 -622
  208. package/src/resources/models/index.ts +1 -0
  209. package/src/resources/models/models.ts +1118 -1130
  210. package/src/resources/models/train.ts +40 -40
  211. package/src/resources/search.ts +239 -327
  212. package/src/resources/tags.ts +32 -39
  213. package/src/resources/workflows.ts +850 -864
  214. package/src/version.ts +1 -1
  215. package/version.d.mts +1 -1
  216. package/version.d.ts +1 -1
  217. package/version.js +1 -1
  218. package/version.mjs +1 -1
package/lib/upload.js ADDED
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.EnhancedUploads = void 0;
37
+ const uploads_1 = require("../resources/uploads.js");
38
+ // AWS S3 multipart upload limits.
39
+ const MIN_PART_SIZE = 6000000; // 6 MB (spec minimum is 5 MiB; a bit over to be safe)
40
+ const MAX_PART_SIZE = 5368709120; // 5 GiB
41
+ const MAX_PARTS = 10000;
42
+ const MAX_FILE_SIZE = 5497558138880; // 5 TiB
43
+ // `validated` is intermediate — the server has validated the upload but
44
+ // hasn't created the asset/model yet, so `entityId` isn't populated.
45
+ // Real terminals are `imported` (asset/model created), `complete`, and
46
+ // `failed`. Everything else means "keep polling".
47
+ const TERMINAL_STATUSES = new Set(['complete', 'failed', 'imported']);
48
+ /**
49
+ * Enhanced Uploads resource.
50
+ * All original methods (`create`, `retrieve`, `triggerAction`) are inherited.
51
+ * Adds `uploadFile()` — a one-call wrapper around the 4-step upload flow:
52
+ * init → PUT parts to S3 → trigger complete → poll until imported.
53
+ */
54
+ class EnhancedUploads extends uploads_1.Uploads {
55
+ /**
56
+ * Upload a file end-to-end. Computes an optimal part size (within AWS's
57
+ * 5 MiB / 5 GiB / 10,000-part bounds), uploads all parts in parallel,
58
+ * triggers completion, polls until the server has validated and imported
59
+ * the file, and returns the resolved entity.
60
+ *
61
+ * The returned type narrows on `kind`: `'model'` returns a Model,
62
+ * everything else returns an Asset.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * // From a file path (Node)
67
+ * const { asset } = await client.uploads.uploadFile({
68
+ * file: './photo.jpg',
69
+ * fileName: 'photo.jpg',
70
+ * contentType: 'image/jpeg',
71
+ * kind: 'image',
72
+ * });
73
+ * console.log(asset.id, asset.url);
74
+ *
75
+ * // Or from bytes / Blob — anything you already have in memory
76
+ * await client.uploads.uploadFile({
77
+ * file: new Blob([pngBytes], { type: 'image/png' }),
78
+ * fileName: 'generated.png',
79
+ * contentType: 'image/png',
80
+ * kind: 'image',
81
+ * });
82
+ * ```
83
+ */
84
+ async uploadFile(params, options) {
85
+ const bytes = await normalizeToBytes(params.file);
86
+ const fileSize = bytes.byteLength;
87
+ if (fileSize === 0) {
88
+ throw new Error('Cannot upload an empty file');
89
+ }
90
+ if (fileSize > MAX_FILE_SIZE) {
91
+ throw new Error(`File size (${fileSize} bytes) exceeds the maximum allowed size of ${MAX_FILE_SIZE} bytes (5 TiB)`);
92
+ }
93
+ // Pick the smallest legal part size that fits within MAX_PARTS.
94
+ const requiredPartSize = Math.ceil(fileSize / MAX_PARTS);
95
+ const partSize = Math.max(MIN_PART_SIZE, requiredPartSize);
96
+ if (partSize > MAX_PART_SIZE) {
97
+ throw new Error(`File size (${fileSize} bytes) requires a part size of ${partSize} bytes, ` +
98
+ `which exceeds the maximum part size of ${MAX_PART_SIZE} bytes (5 GiB)`);
99
+ }
100
+ const partsCount = Math.max(1, Math.ceil(fileSize / partSize));
101
+ // Step 1 — init upload session and receive presigned S3 URLs.
102
+ const createBody = {
103
+ fileName: params.fileName,
104
+ fileSize,
105
+ contentType: params.contentType,
106
+ kind: params.kind,
107
+ parts: partsCount,
108
+ ...(params.kind !== 'model' && params.assetOptions ? { assetOptions: params.assetOptions } : {}),
109
+ };
110
+ const createRes = await this.create(createBody, options);
111
+ const session = createRes.upload;
112
+ const uploadId = session.id;
113
+ const parts = session.parts;
114
+ if (parts?.length !== partsCount) {
115
+ throw new Error(`Expected ${partsCount} presigned part URL(s), got ${parts?.length ?? 0}`);
116
+ }
117
+ // Step 2 — PUT each chunk to its presigned S3 URL, with a concurrency cap.
118
+ const concurrency = Math.max(1, params.partConcurrency ?? 4);
119
+ await uploadPartsWithConcurrency(bytes, parts, partSize, concurrency);
120
+ // Step 3 — tell the server all parts are uploaded.
121
+ await this.triggerAction(uploadId, { action: 'complete' }, options);
122
+ // Step 4 — poll until the upload has been processed into an entity.
123
+ const final = await pollUntilImported(() => this.retrieve(uploadId, options), params.pollIntervalMs ?? 2000, params.pollTimeoutMs ?? 300000);
124
+ if (final.upload.status === 'failed') {
125
+ throw new Error(`Upload ${uploadId} failed: ${final.upload.errorMessage ?? '<no error message>'}`);
126
+ }
127
+ const entityId = final.upload.entityId;
128
+ if (!entityId) {
129
+ throw new Error(`Upload ${uploadId} reached status "${final.upload.status}" but has no entityId`);
130
+ }
131
+ // Fetch and return the resolved entity (narrowed by kind).
132
+ if (params.kind === 'model') {
133
+ const model = await this._client.models.retrieve(entityId);
134
+ return model;
135
+ }
136
+ const asset = await this._client.assets.retrieve(entityId);
137
+ return asset;
138
+ }
139
+ }
140
+ exports.EnhancedUploads = EnhancedUploads;
141
+ // ─────────────────────── helpers ───────────────────────
142
+ async function normalizeToBytes(input) {
143
+ if (typeof input === 'string') {
144
+ // Dynamic import so browser bundlers don't pull in node:fs.
145
+ const { readFile } = await Promise.resolve().then(() => __importStar(require('node:fs/promises')));
146
+ return new Uint8Array(await readFile(input));
147
+ }
148
+ if (input instanceof Uint8Array) {
149
+ return input;
150
+ }
151
+ if (typeof Blob !== 'undefined' && input instanceof Blob) {
152
+ return new Uint8Array(await input.arrayBuffer());
153
+ }
154
+ throw new Error('uploadFile: unsupported input type — expected a path string, Uint8Array, or Blob');
155
+ }
156
+ async function uploadPartsWithConcurrency(bytes, parts, partSize, concurrency) {
157
+ // Sort by part number so slicing lines up with the presigned URL order.
158
+ const sorted = [...parts].sort((a, b) => a.number - b.number);
159
+ let nextIndex = 0;
160
+ const workers = Array.from({ length: concurrency }, () => worker());
161
+ await Promise.all(workers);
162
+ async function worker() {
163
+ while (true) {
164
+ const i = nextIndex++;
165
+ if (i >= sorted.length)
166
+ return;
167
+ const part = sorted[i];
168
+ if (!part)
169
+ continue;
170
+ const start = i * partSize;
171
+ const end = Math.min(bytes.byteLength, start + partSize);
172
+ const chunk = bytes.subarray(start, end);
173
+ const res = await fetch(part.url, { method: 'PUT', body: chunk });
174
+ if (!res.ok) {
175
+ throw new Error(`Failed to upload part ${part.number}/${sorted.length}: ${res.status} ${res.statusText}`);
176
+ }
177
+ }
178
+ }
179
+ }
180
+ async function pollUntilImported(retrieve, intervalMs, timeoutMs) {
181
+ const deadline = Date.now() + timeoutMs;
182
+ while (Date.now() < deadline) {
183
+ const res = await retrieve();
184
+ const { status } = res.upload;
185
+ // Return as soon as we have an entityId OR the upload reached a terminal state.
186
+ if (res.upload.entityId || TERMINAL_STATUSES.has(status)) {
187
+ return res;
188
+ }
189
+ await new Promise((r) => setTimeout(r, intervalMs));
190
+ }
191
+ throw new Error(`Upload did not reach a terminal status within ${timeoutMs / 1000}s`);
192
+ }
193
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../src/lib/upload.ts"],"names":[],"mappings":"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"}
package/lib/upload.mjs ADDED
@@ -0,0 +1,156 @@
1
+ import { Uploads, } from "../resources/uploads.mjs";
2
+ // AWS S3 multipart upload limits.
3
+ const MIN_PART_SIZE = 6000000; // 6 MB (spec minimum is 5 MiB; a bit over to be safe)
4
+ const MAX_PART_SIZE = 5368709120; // 5 GiB
5
+ const MAX_PARTS = 10000;
6
+ const MAX_FILE_SIZE = 5497558138880; // 5 TiB
7
+ // `validated` is intermediate — the server has validated the upload but
8
+ // hasn't created the asset/model yet, so `entityId` isn't populated.
9
+ // Real terminals are `imported` (asset/model created), `complete`, and
10
+ // `failed`. Everything else means "keep polling".
11
+ const TERMINAL_STATUSES = new Set(['complete', 'failed', 'imported']);
12
+ /**
13
+ * Enhanced Uploads resource.
14
+ * All original methods (`create`, `retrieve`, `triggerAction`) are inherited.
15
+ * Adds `uploadFile()` — a one-call wrapper around the 4-step upload flow:
16
+ * init → PUT parts to S3 → trigger complete → poll until imported.
17
+ */
18
+ export class EnhancedUploads extends Uploads {
19
+ /**
20
+ * Upload a file end-to-end. Computes an optimal part size (within AWS's
21
+ * 5 MiB / 5 GiB / 10,000-part bounds), uploads all parts in parallel,
22
+ * triggers completion, polls until the server has validated and imported
23
+ * the file, and returns the resolved entity.
24
+ *
25
+ * The returned type narrows on `kind`: `'model'` returns a Model,
26
+ * everything else returns an Asset.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // From a file path (Node)
31
+ * const { asset } = await client.uploads.uploadFile({
32
+ * file: './photo.jpg',
33
+ * fileName: 'photo.jpg',
34
+ * contentType: 'image/jpeg',
35
+ * kind: 'image',
36
+ * });
37
+ * console.log(asset.id, asset.url);
38
+ *
39
+ * // Or from bytes / Blob — anything you already have in memory
40
+ * await client.uploads.uploadFile({
41
+ * file: new Blob([pngBytes], { type: 'image/png' }),
42
+ * fileName: 'generated.png',
43
+ * contentType: 'image/png',
44
+ * kind: 'image',
45
+ * });
46
+ * ```
47
+ */
48
+ async uploadFile(params, options) {
49
+ const bytes = await normalizeToBytes(params.file);
50
+ const fileSize = bytes.byteLength;
51
+ if (fileSize === 0) {
52
+ throw new Error('Cannot upload an empty file');
53
+ }
54
+ if (fileSize > MAX_FILE_SIZE) {
55
+ throw new Error(`File size (${fileSize} bytes) exceeds the maximum allowed size of ${MAX_FILE_SIZE} bytes (5 TiB)`);
56
+ }
57
+ // Pick the smallest legal part size that fits within MAX_PARTS.
58
+ const requiredPartSize = Math.ceil(fileSize / MAX_PARTS);
59
+ const partSize = Math.max(MIN_PART_SIZE, requiredPartSize);
60
+ if (partSize > MAX_PART_SIZE) {
61
+ throw new Error(`File size (${fileSize} bytes) requires a part size of ${partSize} bytes, ` +
62
+ `which exceeds the maximum part size of ${MAX_PART_SIZE} bytes (5 GiB)`);
63
+ }
64
+ const partsCount = Math.max(1, Math.ceil(fileSize / partSize));
65
+ // Step 1 — init upload session and receive presigned S3 URLs.
66
+ const createBody = {
67
+ fileName: params.fileName,
68
+ fileSize,
69
+ contentType: params.contentType,
70
+ kind: params.kind,
71
+ parts: partsCount,
72
+ ...(params.kind !== 'model' && params.assetOptions ? { assetOptions: params.assetOptions } : {}),
73
+ };
74
+ const createRes = await this.create(createBody, options);
75
+ const session = createRes.upload;
76
+ const uploadId = session.id;
77
+ const parts = session.parts;
78
+ if (parts?.length !== partsCount) {
79
+ throw new Error(`Expected ${partsCount} presigned part URL(s), got ${parts?.length ?? 0}`);
80
+ }
81
+ // Step 2 — PUT each chunk to its presigned S3 URL, with a concurrency cap.
82
+ const concurrency = Math.max(1, params.partConcurrency ?? 4);
83
+ await uploadPartsWithConcurrency(bytes, parts, partSize, concurrency);
84
+ // Step 3 — tell the server all parts are uploaded.
85
+ await this.triggerAction(uploadId, { action: 'complete' }, options);
86
+ // Step 4 — poll until the upload has been processed into an entity.
87
+ const final = await pollUntilImported(() => this.retrieve(uploadId, options), params.pollIntervalMs ?? 2000, params.pollTimeoutMs ?? 300000);
88
+ if (final.upload.status === 'failed') {
89
+ throw new Error(`Upload ${uploadId} failed: ${final.upload.errorMessage ?? '<no error message>'}`);
90
+ }
91
+ const entityId = final.upload.entityId;
92
+ if (!entityId) {
93
+ throw new Error(`Upload ${uploadId} reached status "${final.upload.status}" but has no entityId`);
94
+ }
95
+ // Fetch and return the resolved entity (narrowed by kind).
96
+ if (params.kind === 'model') {
97
+ const model = await this._client.models.retrieve(entityId);
98
+ return model;
99
+ }
100
+ const asset = await this._client.assets.retrieve(entityId);
101
+ return asset;
102
+ }
103
+ }
104
+ // ─────────────────────── helpers ───────────────────────
105
+ async function normalizeToBytes(input) {
106
+ if (typeof input === 'string') {
107
+ // Dynamic import so browser bundlers don't pull in node:fs.
108
+ const { readFile } = await import('node:fs/promises');
109
+ return new Uint8Array(await readFile(input));
110
+ }
111
+ if (input instanceof Uint8Array) {
112
+ return input;
113
+ }
114
+ if (typeof Blob !== 'undefined' && input instanceof Blob) {
115
+ return new Uint8Array(await input.arrayBuffer());
116
+ }
117
+ throw new Error('uploadFile: unsupported input type — expected a path string, Uint8Array, or Blob');
118
+ }
119
+ async function uploadPartsWithConcurrency(bytes, parts, partSize, concurrency) {
120
+ // Sort by part number so slicing lines up with the presigned URL order.
121
+ const sorted = [...parts].sort((a, b) => a.number - b.number);
122
+ let nextIndex = 0;
123
+ const workers = Array.from({ length: concurrency }, () => worker());
124
+ await Promise.all(workers);
125
+ async function worker() {
126
+ while (true) {
127
+ const i = nextIndex++;
128
+ if (i >= sorted.length)
129
+ return;
130
+ const part = sorted[i];
131
+ if (!part)
132
+ continue;
133
+ const start = i * partSize;
134
+ const end = Math.min(bytes.byteLength, start + partSize);
135
+ const chunk = bytes.subarray(start, end);
136
+ const res = await fetch(part.url, { method: 'PUT', body: chunk });
137
+ if (!res.ok) {
138
+ throw new Error(`Failed to upload part ${part.number}/${sorted.length}: ${res.status} ${res.statusText}`);
139
+ }
140
+ }
141
+ }
142
+ }
143
+ async function pollUntilImported(retrieve, intervalMs, timeoutMs) {
144
+ const deadline = Date.now() + timeoutMs;
145
+ while (Date.now() < deadline) {
146
+ const res = await retrieve();
147
+ const { status } = res.upload;
148
+ // Return as soon as we have an entityId OR the upload reached a terminal state.
149
+ if (res.upload.entityId || TERMINAL_STATUSES.has(status)) {
150
+ return res;
151
+ }
152
+ await new Promise((r) => setTimeout(r, intervalMs));
153
+ }
154
+ throw new Error(`Upload did not reach a terminal status within ${timeoutMs / 1000}s`);
155
+ }
156
+ //# sourceMappingURL=upload.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.mjs","sourceRoot":"","sources":["../src/lib/upload.ts"],"names":[],"mappings":"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"}
@@ -2,27 +2,43 @@ import type { APIPromise } from "../core/api-promise.mjs";
2
2
  import type { RequestOptions } from "../internal/request-options.mjs";
3
3
  import { Workflows, type WorkflowApproveUserParams, type WorkflowApproveUserResponse, type WorkflowRetrieveResponse, type WorkflowRunParams, type WorkflowRunResponse } from "../resources/workflows.mjs";
4
4
  import { type WithJob } from "./job.mjs";
5
+ import type { Scenario } from "./scenario.mjs";
5
6
  type DefinitionFlow = WorkflowRetrieveResponse.Workflow.Flow;
6
7
  type NodeType = DefinitionFlow['type'];
7
8
  /**
8
9
  * Enhanced workflow object with helper methods.
9
- * Has all original workflow fields plus `findNode()`, `getNodesByType()`.
10
+ * Has all original workflow fields plus `findNode()`, `getNodesByType()`,
11
+ * `validate()`, and `run()`.
10
12
  *
11
13
  * @example
12
14
  * ```ts
13
15
  * const response = await client.workflows.retrieve(workflowId);
14
16
  * response.workflow.findNode('final_image');
15
17
  * response.workflow.getNodesByType('custom-model');
18
+ * const gen = await response.workflow.run({ body: { prompt: '...' } });
16
19
  * response.workflow.name; // original fields still work
17
20
  * ```
18
21
  */
19
22
  export declare class WorkflowEntity {
23
+ /** @internal */ readonly _client: Scenario;
20
24
  /** Find a node in the workflow definition by ID. */
21
25
  findNode(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow, nodeId: string): DefinitionFlow | undefined;
22
26
  /** Get all nodes of a specific type from the workflow definition. */
23
27
  getNodesByType(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow, type: NodeType): DefinitionFlow[];
28
+ /**
29
+ * Validate the structural integrity of a workflow flow.
30
+ * Throws an `Error` with a human-readable message on the first violation found.
31
+ */
32
+ validate(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow): void;
33
+ /**
34
+ * Run this workflow. Shortcut for
35
+ * `client.workflows.run(this.id, params)`.
36
+ *
37
+ * Returns an enhanced response where `response.job` has `.wait()`.
38
+ */
39
+ run(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow, params: WorkflowRunParams, options?: RequestOptions): APIPromise<WithJob<WorkflowRunResponse>>;
24
40
  /** @internal Create a WorkflowEntity from raw workflow data. */
25
- static from(data: WorkflowRetrieveResponse.Workflow): WorkflowRetrieveResponse.Workflow & WorkflowEntity;
41
+ static from(client: Scenario, data: WorkflowRetrieveResponse.Workflow): WorkflowRetrieveResponse.Workflow & WorkflowEntity;
26
42
  }
27
43
  /** Enhanced retrieve response with workflow entity methods. */
28
44
  export type EnhancedWorkflowRetrieveResponse = Omit<WorkflowRetrieveResponse, 'workflow'> & {
@@ -36,7 +52,7 @@ export type EnhancedWorkflowRetrieveResponse = Omit<WorkflowRetrieveResponse, 'w
36
52
  export declare class EnhancedWorkflows extends Workflows {
37
53
  /**
38
54
  * Get workflow by ID. Returns an enhanced response where `workflow` has
39
- * `findNode()` and `getNodesByType()`.
55
+ * `findNode()`, `getNodesByType()`, and `validate()`.
40
56
  */
41
57
  retrieve(workflowID: string, options?: RequestOptions): APIPromise<EnhancedWorkflowRetrieveResponse>;
42
58
  /** Run a workflow. Returns an enhanced response where `job` has `.wait()`. */
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.mts","sourceRoot":"","sources":["../src/lib/workflow.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,UAAU,EAAE;OACnB,KAAK,EAAE,cAAc,EAAE;OACvB,EACL,SAAS,EACT,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACzB;OACM,EAAE,KAAK,OAAO,EAAc;AAEnC,KAAK,cAAc,GAAG,wBAAwB,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC7D,KAAK,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;IACzB,oDAAoD;IACpD,QAAQ,CACN,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EACxD,MAAM,EAAE,MAAM,GACb,cAAc,GAAG,SAAS;IAI7B,qEAAqE;IACrE,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,cAAc,EAAE;IAI1G,gEAAgE;IAChE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,QAAQ,GAAG,wBAAwB,CAAC,QAAQ,GAAG,cAAc;CAGzG;AAED,+DAA+D;AAC/D,MAAM,MAAM,gCAAgC,GAAG,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GAAG;IAC1F,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,GAAG,cAAc,CAAC;CAC9D,CAAC;AAEF;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C;;;OAGG;IACM,QAAQ,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,gCAAgC,CAAC;IAO/C,8EAA8E;IACrE,GAAG,CACV,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAI3C,4FAA4F;IACnF,WAAW,CAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,yBAAyB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;CAGpD"}
1
+ {"version":3,"file":"workflow.d.mts","sourceRoot":"","sources":["../src/lib/workflow.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,UAAU,EAAE;OACnB,KAAK,EAAE,cAAc,EAAE;OACvB,EACL,SAAS,EACT,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACzB;OACM,EAAE,KAAK,OAAO,EAAc;OAG5B,KAAK,EAAE,QAAQ,EAAE;AAExB,KAAK,cAAc,GAAG,wBAAwB,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC7D,KAAK,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAEvC;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;IACzB,gBAAgB,CAAC,SAAiB,OAAO,EAAE,QAAQ,CAAC;IAEpD,oDAAoD;IACpD,QAAQ,CACN,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EACxD,MAAM,EAAE,MAAM,GACb,cAAc,GAAG,SAAS;IAI7B,qEAAqE;IACrE,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,cAAc,EAAE;IAI1G;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,GAAG,IAAI;IAIxE;;;;;OAKG;IACH,GAAG,CACD,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EACxD,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAI3C,gEAAgE;IAChE,MAAM,CAAC,IAAI,CACT,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,wBAAwB,CAAC,QAAQ,GACtC,wBAAwB,CAAC,QAAQ,GAAG,cAAc;CAKtD;AAED,+DAA+D;AAC/D,MAAM,MAAM,gCAAgC,GAAG,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GAAG;IAC1F,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,GAAG,cAAc,CAAC;CAC9D,CAAC;AAEF;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C;;;OAGG;IACM,QAAQ,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,gCAAgC,CAAC;IAO/C,8EAA8E;IACrE,GAAG,CACV,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAI3C,4FAA4F;IACnF,WAAW,CAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,yBAAyB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;CAGpD"}
package/lib/workflow.d.ts CHANGED
@@ -2,27 +2,43 @@ import type { APIPromise } from "../core/api-promise.js";
2
2
  import type { RequestOptions } from "../internal/request-options.js";
3
3
  import { Workflows, type WorkflowApproveUserParams, type WorkflowApproveUserResponse, type WorkflowRetrieveResponse, type WorkflowRunParams, type WorkflowRunResponse } from "../resources/workflows.js";
4
4
  import { type WithJob } from "./job.js";
5
+ import type { Scenario } from "./scenario.js";
5
6
  type DefinitionFlow = WorkflowRetrieveResponse.Workflow.Flow;
6
7
  type NodeType = DefinitionFlow['type'];
7
8
  /**
8
9
  * Enhanced workflow object with helper methods.
9
- * Has all original workflow fields plus `findNode()`, `getNodesByType()`.
10
+ * Has all original workflow fields plus `findNode()`, `getNodesByType()`,
11
+ * `validate()`, and `run()`.
10
12
  *
11
13
  * @example
12
14
  * ```ts
13
15
  * const response = await client.workflows.retrieve(workflowId);
14
16
  * response.workflow.findNode('final_image');
15
17
  * response.workflow.getNodesByType('custom-model');
18
+ * const gen = await response.workflow.run({ body: { prompt: '...' } });
16
19
  * response.workflow.name; // original fields still work
17
20
  * ```
18
21
  */
19
22
  export declare class WorkflowEntity {
23
+ /** @internal */ readonly _client: Scenario;
20
24
  /** Find a node in the workflow definition by ID. */
21
25
  findNode(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow, nodeId: string): DefinitionFlow | undefined;
22
26
  /** Get all nodes of a specific type from the workflow definition. */
23
27
  getNodesByType(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow, type: NodeType): DefinitionFlow[];
28
+ /**
29
+ * Validate the structural integrity of a workflow flow.
30
+ * Throws an `Error` with a human-readable message on the first violation found.
31
+ */
32
+ validate(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow): void;
33
+ /**
34
+ * Run this workflow. Shortcut for
35
+ * `client.workflows.run(this.id, params)`.
36
+ *
37
+ * Returns an enhanced response where `response.job` has `.wait()`.
38
+ */
39
+ run(this: WorkflowEntity & WorkflowRetrieveResponse.Workflow, params: WorkflowRunParams, options?: RequestOptions): APIPromise<WithJob<WorkflowRunResponse>>;
24
40
  /** @internal Create a WorkflowEntity from raw workflow data. */
25
- static from(data: WorkflowRetrieveResponse.Workflow): WorkflowRetrieveResponse.Workflow & WorkflowEntity;
41
+ static from(client: Scenario, data: WorkflowRetrieveResponse.Workflow): WorkflowRetrieveResponse.Workflow & WorkflowEntity;
26
42
  }
27
43
  /** Enhanced retrieve response with workflow entity methods. */
28
44
  export type EnhancedWorkflowRetrieveResponse = Omit<WorkflowRetrieveResponse, 'workflow'> & {
@@ -36,7 +52,7 @@ export type EnhancedWorkflowRetrieveResponse = Omit<WorkflowRetrieveResponse, 'w
36
52
  export declare class EnhancedWorkflows extends Workflows {
37
53
  /**
38
54
  * Get workflow by ID. Returns an enhanced response where `workflow` has
39
- * `findNode()` and `getNodesByType()`.
55
+ * `findNode()`, `getNodesByType()`, and `validate()`.
40
56
  */
41
57
  retrieve(workflowID: string, options?: RequestOptions): APIPromise<EnhancedWorkflowRetrieveResponse>;
42
58
  /** Run a workflow. Returns an enhanced response where `job` has `.wait()`. */
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/lib/workflow.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,UAAU,EAAE;OACnB,KAAK,EAAE,cAAc,EAAE;OACvB,EACL,SAAS,EACT,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACzB;OACM,EAAE,KAAK,OAAO,EAAc;AAEnC,KAAK,cAAc,GAAG,wBAAwB,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC7D,KAAK,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;IACzB,oDAAoD;IACpD,QAAQ,CACN,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EACxD,MAAM,EAAE,MAAM,GACb,cAAc,GAAG,SAAS;IAI7B,qEAAqE;IACrE,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,cAAc,EAAE;IAI1G,gEAAgE;IAChE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,QAAQ,GAAG,wBAAwB,CAAC,QAAQ,GAAG,cAAc;CAGzG;AAED,+DAA+D;AAC/D,MAAM,MAAM,gCAAgC,GAAG,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GAAG;IAC1F,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,GAAG,cAAc,CAAC;CAC9D,CAAC;AAEF;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C;;;OAGG;IACM,QAAQ,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,gCAAgC,CAAC;IAO/C,8EAA8E;IACrE,GAAG,CACV,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAI3C,4FAA4F;IACnF,WAAW,CAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,yBAAyB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;CAGpD"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/lib/workflow.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,UAAU,EAAE;OACnB,KAAK,EAAE,cAAc,EAAE;OACvB,EACL,SAAS,EACT,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACzB;OACM,EAAE,KAAK,OAAO,EAAc;OAG5B,KAAK,EAAE,QAAQ,EAAE;AAExB,KAAK,cAAc,GAAG,wBAAwB,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC7D,KAAK,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAEvC;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;IACzB,gBAAgB,CAAC,SAAiB,OAAO,EAAE,QAAQ,CAAC;IAEpD,oDAAoD;IACpD,QAAQ,CACN,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EACxD,MAAM,EAAE,MAAM,GACb,cAAc,GAAG,SAAS;IAI7B,qEAAqE;IACrE,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,cAAc,EAAE;IAI1G;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,GAAG,IAAI;IAIxE;;;;;OAKG;IACH,GAAG,CACD,IAAI,EAAE,cAAc,GAAG,wBAAwB,CAAC,QAAQ,EACxD,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAI3C,gEAAgE;IAChE,MAAM,CAAC,IAAI,CACT,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,wBAAwB,CAAC,QAAQ,GACtC,wBAAwB,CAAC,QAAQ,GAAG,cAAc;CAKtD;AAED,+DAA+D;AAC/D,MAAM,MAAM,gCAAgC,GAAG,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GAAG;IAC1F,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,GAAG,cAAc,CAAC;CAC9D,CAAC;AAEF;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C;;;OAGG;IACM,QAAQ,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,gCAAgC,CAAC;IAO/C,8EAA8E;IACrE,GAAG,CACV,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAI3C,4FAA4F;IACnF,WAAW,CAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,yBAAyB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;CAGpD"}
package/lib/workflow.js CHANGED
@@ -3,15 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EnhancedWorkflows = exports.WorkflowEntity = void 0;
4
4
  const workflows_1 = require("../resources/workflows.js");
5
5
  const job_1 = require("./job.js");
6
+ const workflow_validator_1 = require("./workflow_validator.js");
6
7
  /**
7
8
  * Enhanced workflow object with helper methods.
8
- * Has all original workflow fields plus `findNode()`, `getNodesByType()`.
9
+ * Has all original workflow fields plus `findNode()`, `getNodesByType()`,
10
+ * `validate()`, and `run()`.
9
11
  *
10
12
  * @example
11
13
  * ```ts
12
14
  * const response = await client.workflows.retrieve(workflowId);
13
15
  * response.workflow.findNode('final_image');
14
16
  * response.workflow.getNodesByType('custom-model');
17
+ * const gen = await response.workflow.run({ body: { prompt: '...' } });
15
18
  * response.workflow.name; // original fields still work
16
19
  * ```
17
20
  */
@@ -24,9 +27,27 @@ class WorkflowEntity {
24
27
  getNodesByType(type) {
25
28
  return this.flow.filter((node) => node.type === type);
26
29
  }
30
+ /**
31
+ * Validate the structural integrity of a workflow flow.
32
+ * Throws an `Error` with a human-readable message on the first violation found.
33
+ */
34
+ validate() {
35
+ (0, workflow_validator_1.validateWorkflowFlow)(this.flow);
36
+ }
37
+ /**
38
+ * Run this workflow. Shortcut for
39
+ * `client.workflows.run(this.id, params)`.
40
+ *
41
+ * Returns an enhanced response where `response.job` has `.wait()`.
42
+ */
43
+ run(params, options) {
44
+ return this._client.workflows.run(this.id, params, options);
45
+ }
27
46
  /** @internal Create a WorkflowEntity from raw workflow data. */
28
- static from(data) {
29
- return Object.assign(Object.create(WorkflowEntity.prototype), data);
47
+ static from(client, data) {
48
+ const entity = Object.assign(Object.create(WorkflowEntity.prototype), data);
49
+ Object.defineProperty(entity, '_client', { value: client, enumerable: false });
50
+ return entity;
30
51
  }
31
52
  }
32
53
  exports.WorkflowEntity = WorkflowEntity;
@@ -38,12 +59,12 @@ exports.WorkflowEntity = WorkflowEntity;
38
59
  class EnhancedWorkflows extends workflows_1.Workflows {
39
60
  /**
40
61
  * Get workflow by ID. Returns an enhanced response where `workflow` has
41
- * `findNode()` and `getNodesByType()`.
62
+ * `findNode()`, `getNodesByType()`, and `validate()`.
42
63
  */
43
64
  retrieve(workflowID, options) {
44
65
  return super.retrieve(workflowID, options)._thenUnwrap((data) => ({
45
66
  ...data,
46
- workflow: WorkflowEntity.from(data.workflow),
67
+ workflow: WorkflowEntity.from(this._client, data.workflow),
47
68
  }));
48
69
  }
49
70
  /** Run a workflow. Returns an enhanced response where `job` has `.wait()`. */
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../src/lib/workflow.ts"],"names":[],"mappings":";;;AAEA,yDAOgC;AAChC,kCAAiD;AAKjD;;;;;;;;;;;GAWG;AACH,MAAa,cAAc;IACzB,oDAAoD;IACpD,QAAQ,CAEN,MAAc;QAEd,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACtD,CAAC;IAED,qEAAqE;IACrE,cAAc,CAA2D,IAAc;QACrF,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,IAAI,CAAC,IAAuC;QACjD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC;CACF;AAlBD,wCAkBC;AAOD;;;;GAIG;AACH,MAAa,iBAAkB,SAAQ,qBAAS;IAC9C;;;OAGG;IACM,QAAQ,CACf,UAAkB,EAClB,OAAwB;QAExB,OAAO,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAChE,GAAG,IAAI;YACP,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;SAC7C,CAAC,CAAC,CAAC;IACN,CAAC;IAED,8EAA8E;IACrE,GAAG,CACV,UAAkB,EAClB,MAAyB,EACzB,OAAwB;QAExB,OAAO,IAAA,gBAAU,EAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,4FAA4F;IACnF,WAAW,CAClB,UAAkB,EAClB,IAA+B,EAC/B,OAAwB;QAExB,OAAO,IAAA,gBAAU,EAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAChF,CAAC;CACF;AAhCD,8CAgCC"}
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../src/lib/workflow.ts"],"names":[],"mappings":";;;AAEA,yDAOgC;AAChC,kCAAiD;AACjD,gEAA4D;AAO5D;;;;;;;;;;;;;GAaG;AACH,MAAa,cAAc;IAGzB,oDAAoD;IACpD,QAAQ,CAEN,MAAc;QAEd,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACtD,CAAC;IAED,qEAAqE;IACrE,cAAc,CAA2D,IAAc;QACrF,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,QAAQ;QACN,IAAA,yCAAoB,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAED,MAAyB,EACzB,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,IAAI,CACT,MAAgB,EAChB,IAAuC;QAEvC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5E,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA/CD,wCA+CC;AAOD;;;;GAIG;AACH,MAAa,iBAAkB,SAAQ,qBAAS;IAC9C;;;OAGG;IACM,QAAQ,CACf,UAAkB,EAClB,OAAwB;QAExB,OAAO,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAChE,GAAG,IAAI;YACP,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC;SACvE,CAAC,CAAC,CAAC;IACN,CAAC;IAED,8EAA8E;IACrE,GAAG,CACV,UAAkB,EAClB,MAAyB,EACzB,OAAwB;QAExB,OAAO,IAAA,gBAAU,EAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,4FAA4F;IACnF,WAAW,CAClB,UAAkB,EAClB,IAA+B,EAC/B,OAAwB;QAExB,OAAO,IAAA,gBAAU,EAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAChF,CAAC;CACF;AAhCD,8CAgCC"}
package/lib/workflow.mjs CHANGED
@@ -1,14 +1,17 @@
1
1
  import { Workflows, } from "../resources/workflows.mjs";
2
2
  import { enhanceJob } from "./job.mjs";
3
+ import { validateWorkflowFlow } from "./workflow_validator.mjs";
3
4
  /**
4
5
  * Enhanced workflow object with helper methods.
5
- * Has all original workflow fields plus `findNode()`, `getNodesByType()`.
6
+ * Has all original workflow fields plus `findNode()`, `getNodesByType()`,
7
+ * `validate()`, and `run()`.
6
8
  *
7
9
  * @example
8
10
  * ```ts
9
11
  * const response = await client.workflows.retrieve(workflowId);
10
12
  * response.workflow.findNode('final_image');
11
13
  * response.workflow.getNodesByType('custom-model');
14
+ * const gen = await response.workflow.run({ body: { prompt: '...' } });
12
15
  * response.workflow.name; // original fields still work
13
16
  * ```
14
17
  */
@@ -21,9 +24,27 @@ export class WorkflowEntity {
21
24
  getNodesByType(type) {
22
25
  return this.flow.filter((node) => node.type === type);
23
26
  }
27
+ /**
28
+ * Validate the structural integrity of a workflow flow.
29
+ * Throws an `Error` with a human-readable message on the first violation found.
30
+ */
31
+ validate() {
32
+ validateWorkflowFlow(this.flow);
33
+ }
34
+ /**
35
+ * Run this workflow. Shortcut for
36
+ * `client.workflows.run(this.id, params)`.
37
+ *
38
+ * Returns an enhanced response where `response.job` has `.wait()`.
39
+ */
40
+ run(params, options) {
41
+ return this._client.workflows.run(this.id, params, options);
42
+ }
24
43
  /** @internal Create a WorkflowEntity from raw workflow data. */
25
- static from(data) {
26
- return Object.assign(Object.create(WorkflowEntity.prototype), data);
44
+ static from(client, data) {
45
+ const entity = Object.assign(Object.create(WorkflowEntity.prototype), data);
46
+ Object.defineProperty(entity, '_client', { value: client, enumerable: false });
47
+ return entity;
27
48
  }
28
49
  }
29
50
  /**
@@ -34,12 +55,12 @@ export class WorkflowEntity {
34
55
  export class EnhancedWorkflows extends Workflows {
35
56
  /**
36
57
  * Get workflow by ID. Returns an enhanced response where `workflow` has
37
- * `findNode()` and `getNodesByType()`.
58
+ * `findNode()`, `getNodesByType()`, and `validate()`.
38
59
  */
39
60
  retrieve(workflowID, options) {
40
61
  return super.retrieve(workflowID, options)._thenUnwrap((data) => ({
41
62
  ...data,
42
- workflow: WorkflowEntity.from(data.workflow),
63
+ workflow: WorkflowEntity.from(this._client, data.workflow),
43
64
  }));
44
65
  }
45
66
  /** Run a workflow. Returns an enhanced response where `job` has `.wait()`. */