@scenario-labs/sdk 1.0.0 → 1.2.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 (209) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +0 -2
  3. package/client.d.mts +8 -8
  4. package/client.d.mts.map +1 -1
  5. package/client.d.ts +8 -8
  6. package/client.d.ts.map +1 -1
  7. package/client.js +17 -6
  8. package/client.js.map +1 -1
  9. package/client.mjs +17 -6
  10. package/client.mjs.map +1 -1
  11. package/index.d.mts +3 -1
  12. package/index.d.mts.map +1 -1
  13. package/index.d.ts +3 -1
  14. package/index.d.ts.map +1 -1
  15. package/index.js +8 -1
  16. package/index.js.map +1 -1
  17. package/index.mjs +3 -1
  18. package/index.mjs.map +1 -1
  19. package/internal/request-options.d.mts +0 -4
  20. package/internal/request-options.d.mts.map +1 -1
  21. package/internal/request-options.d.ts +0 -4
  22. package/internal/request-options.d.ts.map +1 -1
  23. package/internal/request-options.js.map +1 -1
  24. package/internal/request-options.mjs.map +1 -1
  25. package/lib/asset.d.mts +55 -0
  26. package/lib/asset.d.mts.map +1 -0
  27. package/lib/asset.d.ts +55 -0
  28. package/lib/asset.d.ts.map +1 -0
  29. package/lib/asset.js +60 -0
  30. package/lib/asset.js.map +1 -0
  31. package/lib/asset.mjs +54 -0
  32. package/lib/asset.mjs.map +1 -0
  33. package/lib/job.d.mts +13 -1
  34. package/lib/job.d.mts.map +1 -1
  35. package/lib/job.d.ts +13 -1
  36. package/lib/job.d.ts.map +1 -1
  37. package/lib/job.js +18 -1
  38. package/lib/job.js.map +1 -1
  39. package/lib/job.mjs +16 -0
  40. package/lib/job.mjs.map +1 -1
  41. package/lib/scenario.d.mts +12 -0
  42. package/lib/scenario.d.mts.map +1 -1
  43. package/lib/scenario.d.ts +12 -0
  44. package/lib/scenario.d.ts.map +1 -1
  45. package/lib/scenario.js +12 -0
  46. package/lib/scenario.js.map +1 -1
  47. package/lib/scenario.mjs +12 -0
  48. package/lib/scenario.mjs.map +1 -1
  49. package/lib/upload.d.mts +56 -2
  50. package/lib/upload.d.mts.map +1 -1
  51. package/lib/upload.d.ts +56 -2
  52. package/lib/upload.d.ts.map +1 -1
  53. package/lib/upload.js +51 -2
  54. package/lib/upload.js.map +1 -1
  55. package/lib/upload.mjs +48 -1
  56. package/lib/upload.mjs.map +1 -1
  57. package/lib/workflow.d.mts +2 -2
  58. package/lib/workflow.d.mts.map +1 -1
  59. package/lib/workflow.d.ts +2 -2
  60. package/lib/workflow.d.ts.map +1 -1
  61. package/lib/workflow.js +2 -2
  62. package/lib/workflow.js.map +1 -1
  63. package/lib/workflow.mjs +2 -2
  64. package/lib/workflow.mjs.map +1 -1
  65. package/package.json +1 -1
  66. package/resources/assets/assets.d.mts +25 -29
  67. package/resources/assets/assets.d.mts.map +1 -1
  68. package/resources/assets/assets.d.ts +25 -29
  69. package/resources/assets/assets.d.ts.map +1 -1
  70. package/resources/assets/assets.js +0 -4
  71. package/resources/assets/assets.js.map +1 -1
  72. package/resources/assets/assets.mjs +0 -4
  73. package/resources/assets/assets.mjs.map +1 -1
  74. package/resources/assets/index.d.mts +0 -1
  75. package/resources/assets/index.d.mts.map +1 -1
  76. package/resources/assets/index.d.ts +0 -1
  77. package/resources/assets/index.d.ts.map +1 -1
  78. package/resources/assets/index.js +1 -3
  79. package/resources/assets/index.js.map +1 -1
  80. package/resources/assets/index.mjs +0 -1
  81. package/resources/assets/index.mjs.map +1 -1
  82. package/resources/generate.d.mts +1027 -242
  83. package/resources/generate.d.mts.map +1 -1
  84. package/resources/generate.d.ts +1027 -242
  85. package/resources/generate.d.ts.map +1 -1
  86. package/resources/generate.js +7 -0
  87. package/resources/generate.js.map +1 -1
  88. package/resources/generate.mjs +7 -0
  89. package/resources/generate.mjs.map +1 -1
  90. package/resources/index.d.mts +3 -2
  91. package/resources/index.d.mts.map +1 -1
  92. package/resources/index.d.ts +3 -2
  93. package/resources/index.d.ts.map +1 -1
  94. package/resources/index.js +3 -1
  95. package/resources/index.js.map +1 -1
  96. package/resources/index.mjs +1 -0
  97. package/resources/index.mjs.map +1 -1
  98. package/resources/jobs.d.mts +10 -3
  99. package/resources/jobs.d.mts.map +1 -1
  100. package/resources/jobs.d.ts +10 -3
  101. package/resources/jobs.d.ts.map +1 -1
  102. package/resources/models/description.d.mts +2 -2
  103. package/resources/models/description.d.mts.map +1 -1
  104. package/resources/models/description.d.ts +2 -2
  105. package/resources/models/description.d.ts.map +1 -1
  106. package/resources/models/examples.d.mts +4 -4
  107. package/resources/models/examples.d.mts.map +1 -1
  108. package/resources/models/examples.d.ts +4 -4
  109. package/resources/models/examples.d.ts.map +1 -1
  110. package/resources/models/models.d.mts +20 -18
  111. package/resources/models/models.d.mts.map +1 -1
  112. package/resources/models/models.d.ts +20 -18
  113. package/resources/models/models.d.ts.map +1 -1
  114. package/resources/models/models.js.map +1 -1
  115. package/resources/models/models.mjs.map +1 -1
  116. package/resources/models/train.d.mts +2 -2
  117. package/resources/models/train.d.mts.map +1 -1
  118. package/resources/models/train.d.ts +2 -2
  119. package/resources/models/train.d.ts.map +1 -1
  120. package/resources/oscu.d.mts +5 -0
  121. package/resources/oscu.d.mts.map +1 -1
  122. package/resources/oscu.d.ts +5 -0
  123. package/resources/oscu.d.ts.map +1 -1
  124. package/resources/oscu.js +5 -0
  125. package/resources/oscu.js.map +1 -1
  126. package/resources/oscu.mjs +5 -0
  127. package/resources/oscu.mjs.map +1 -1
  128. package/resources/pricing/index.d.mts +3 -0
  129. package/resources/pricing/index.d.mts.map +1 -0
  130. package/resources/pricing/index.d.ts +3 -0
  131. package/resources/pricing/index.d.ts.map +1 -0
  132. package/resources/pricing/index.js +9 -0
  133. package/resources/pricing/index.js.map +1 -0
  134. package/resources/pricing/index.mjs +4 -0
  135. package/resources/pricing/index.mjs.map +1 -0
  136. package/resources/pricing/oscu.d.mts +25 -0
  137. package/resources/pricing/oscu.d.mts.map +1 -0
  138. package/resources/pricing/oscu.d.ts +25 -0
  139. package/resources/pricing/oscu.d.ts.map +1 -0
  140. package/resources/pricing/oscu.js +16 -0
  141. package/resources/pricing/oscu.js.map +1 -0
  142. package/resources/pricing/oscu.mjs +12 -0
  143. package/resources/pricing/oscu.mjs.map +1 -0
  144. package/resources/pricing/pricing.d.mts +10 -0
  145. package/resources/pricing/pricing.d.mts.map +1 -0
  146. package/resources/pricing/pricing.d.ts +10 -0
  147. package/resources/pricing/pricing.d.ts.map +1 -0
  148. package/resources/pricing/pricing.js +17 -0
  149. package/resources/pricing/pricing.js.map +1 -0
  150. package/resources/pricing/pricing.mjs +12 -0
  151. package/resources/pricing/pricing.mjs.map +1 -0
  152. package/resources/pricing.d.mts +2 -0
  153. package/resources/pricing.d.mts.map +1 -0
  154. package/resources/pricing.d.ts +2 -0
  155. package/resources/pricing.d.ts.map +1 -0
  156. package/resources/pricing.js +6 -0
  157. package/resources/pricing.js.map +1 -0
  158. package/resources/pricing.mjs +3 -0
  159. package/resources/pricing.mjs.map +1 -0
  160. package/resources/usages.d.mts +8 -6
  161. package/resources/usages.d.mts.map +1 -1
  162. package/resources/usages.d.ts +8 -6
  163. package/resources/usages.d.ts.map +1 -1
  164. package/resources/workflows.d.mts +1156 -1142
  165. package/resources/workflows.d.mts.map +1 -1
  166. package/resources/workflows.d.ts +1156 -1142
  167. package/resources/workflows.d.ts.map +1 -1
  168. package/resources/workflows.js +13 -6
  169. package/resources/workflows.js.map +1 -1
  170. package/resources/workflows.mjs +13 -6
  171. package/resources/workflows.mjs.map +1 -1
  172. package/src/client.ts +28 -11
  173. package/src/index.ts +3 -1
  174. package/src/internal/request-options.ts +0 -2
  175. package/src/lib/asset.ts +85 -0
  176. package/src/lib/job.ts +28 -1
  177. package/src/lib/scenario.ts +12 -0
  178. package/src/lib/upload.ts +96 -2
  179. package/src/lib/workflow.ts +4 -4
  180. package/src/resources/assets/assets.ts +46 -20
  181. package/src/resources/assets/index.ts +0 -6
  182. package/src/resources/generate.ts +1227 -136
  183. package/src/resources/index.ts +5 -1
  184. package/src/resources/jobs.ts +12 -4
  185. package/src/resources/models/description.ts +4 -0
  186. package/src/resources/models/examples.ts +8 -0
  187. package/src/resources/models/models.ts +65 -11
  188. package/src/resources/models/train.ts +4 -0
  189. package/src/resources/oscu.ts +5 -0
  190. package/src/resources/pricing/index.ts +4 -0
  191. package/src/resources/pricing/oscu.ts +35 -0
  192. package/src/resources/pricing/pricing.ts +15 -0
  193. package/src/resources/pricing.ts +3 -0
  194. package/src/resources/usages.ts +12 -3
  195. package/src/resources/workflows.ts +1540 -1522
  196. package/src/version.ts +1 -1
  197. package/version.d.mts +1 -1
  198. package/version.d.ts +1 -1
  199. package/version.js +1 -1
  200. package/version.mjs +1 -1
  201. package/resources/assets/public.d.mts +0 -1538
  202. package/resources/assets/public.d.mts.map +0 -1
  203. package/resources/assets/public.d.ts +0 -1538
  204. package/resources/assets/public.d.ts.map +0 -1
  205. package/resources/assets/public.js +0 -28
  206. package/resources/assets/public.js.map +0 -1
  207. package/resources/assets/public.mjs +0 -24
  208. package/resources/assets/public.mjs.map +0 -1
  209. package/src/resources/assets/public.ts +0 -2451
package/src/client.ts CHANGED
@@ -49,6 +49,8 @@ import {
49
49
  GenerateEmbedResponse,
50
50
  GeneratePatchParams,
51
51
  GeneratePatchResponse,
52
+ GeneratePromptParams,
53
+ GeneratePromptResponse,
52
54
  GenerateRunModelParams,
53
55
  GenerateRunModelResponse,
54
56
  GenerateTranslateParams,
@@ -85,7 +87,6 @@ import {
85
87
  import { UsageListParams, UsageListResponse, Usages } from './resources/usages';
86
88
  import {
87
89
  WorkflowApproveUserParams,
88
- WorkflowApproveUserResponse,
89
90
  WorkflowCreateParams,
90
91
  WorkflowCreateResponse,
91
92
  WorkflowDeleteResponse,
@@ -99,6 +100,8 @@ import {
99
100
  WorkflowRunResponse,
100
101
  WorkflowUpdateParams,
101
102
  WorkflowUpdateResponse,
103
+ WorkflowUserApprovalParams,
104
+ WorkflowUserApprovalResponse,
102
105
  Workflows,
103
106
  } from './resources/workflows';
104
107
  import {
@@ -165,6 +168,7 @@ import {
165
168
  ModelUpdateTagsResponse,
166
169
  Models,
167
170
  } from './resources/models/models';
171
+ import { Pricing } from './resources/pricing/pricing';
168
172
  import { type Fetch } from './internal/builtin-types';
169
173
  import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
170
174
  import { FinalRequestOptions, RequestOptions } from './internal/request-options';
@@ -328,6 +332,18 @@ export class Scenario {
328
332
  this.fetch = options.fetch ?? Shims.getDefaultFetch();
329
333
  this.#encoder = Opts.FallbackEncoder;
330
334
 
335
+ const customHeadersEnv = readEnv('SCENARIO_CUSTOM_HEADERS');
336
+ if (customHeadersEnv) {
337
+ const parsed: Record<string, string> = {};
338
+ for (const line of customHeadersEnv.split('\n')) {
339
+ const colon = line.indexOf(':');
340
+ if (colon >= 0) {
341
+ parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim();
342
+ }
343
+ }
344
+ options.defaultHeaders = { ...parsed, ...options.defaultHeaders };
345
+ }
346
+
331
347
  this._options = options;
332
348
 
333
349
  this.apiKey = apiKey;
@@ -387,14 +403,8 @@ export class Scenario {
387
403
  );
388
404
  }
389
405
 
390
- protected async authHeaders(
391
- opts: FinalRequestOptions,
392
- schemes: { scBasicAuth?: boolean; scBearerAuth?: boolean },
393
- ): Promise<NullableHeaders | undefined> {
394
- return buildHeaders([
395
- schemes.scBasicAuth ? await this.scBasicAuth(opts) : null,
396
- schemes.scBearerAuth ? await this.scBearerAuth(opts) : null,
397
- ]);
406
+ protected async authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {
407
+ return buildHeaders([await this.scBasicAuth(opts), await this.scBearerAuth(opts)]);
398
408
  }
399
409
 
400
410
  protected async scBasicAuth(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {
@@ -865,7 +875,7 @@ export class Scenario {
865
875
  ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
866
876
  ...getPlatformHeaders(),
867
877
  },
868
- await this.authHeaders(options, options.__security ?? { scBasicAuth: true, scBearerAuth: true }),
878
+ await this.authHeaders(options),
869
879
  this._options.defaultHeaders,
870
880
  bodyHeaders,
871
881
  options.headers,
@@ -951,6 +961,7 @@ export class Scenario {
951
961
  generate: API.Generate = new API.Generate(this);
952
962
  jobs: API.Jobs = new API.Jobs(this);
953
963
  models: API.Models = new API.Models(this);
964
+ pricing: API.Pricing = new API.Pricing(this);
954
965
  oscu: API.Oscu = new API.Oscu(this);
955
966
  search: API.Search = new API.Search(this);
956
967
  tags: API.Tags = new API.Tags(this);
@@ -964,6 +975,7 @@ Scenario.Collections = Collections;
964
975
  Scenario.Generate = Generate;
965
976
  Scenario.Jobs = Jobs;
966
977
  Scenario.Models = Models;
978
+ Scenario.Pricing = Pricing;
967
979
  Scenario.Oscu = Oscu;
968
980
  Scenario.Search = Search;
969
981
  Scenario.Tags = Tags;
@@ -1058,6 +1070,7 @@ export declare namespace Scenario {
1058
1070
  type GenerateDetectResponse as GenerateDetectResponse,
1059
1071
  type GenerateEmbedResponse as GenerateEmbedResponse,
1060
1072
  type GeneratePatchResponse as GeneratePatchResponse,
1073
+ type GeneratePromptResponse as GeneratePromptResponse,
1061
1074
  type GenerateRunModelResponse as GenerateRunModelResponse,
1062
1075
  type GenerateTranslateResponse as GenerateTranslateResponse,
1063
1076
  type GenerateCaptionParams as GenerateCaptionParams,
@@ -1065,6 +1078,7 @@ export declare namespace Scenario {
1065
1078
  type GenerateDetectParams as GenerateDetectParams,
1066
1079
  type GenerateEmbedParams as GenerateEmbedParams,
1067
1080
  type GeneratePatchParams as GeneratePatchParams,
1081
+ type GeneratePromptParams as GeneratePromptParams,
1068
1082
  type GenerateRunModelParams as GenerateRunModelParams,
1069
1083
  type GenerateTranslateParams as GenerateTranslateParams,
1070
1084
  };
@@ -1105,6 +1119,8 @@ export declare namespace Scenario {
1105
1119
  type ModelUpdateTagsParams as ModelUpdateTagsParams,
1106
1120
  };
1107
1121
 
1122
+ export { Pricing as Pricing };
1123
+
1108
1124
  export { Oscu as Oscu, type OscuRetrievePricesResponse as OscuRetrievePricesResponse };
1109
1125
 
1110
1126
  export {
@@ -1146,9 +1162,9 @@ export declare namespace Scenario {
1146
1162
  type WorkflowUpdateResponse as WorkflowUpdateResponse,
1147
1163
  type WorkflowListResponse as WorkflowListResponse,
1148
1164
  type WorkflowDeleteResponse as WorkflowDeleteResponse,
1149
- type WorkflowApproveUserResponse as WorkflowApproveUserResponse,
1150
1165
  type WorkflowGetTagsResponse as WorkflowGetTagsResponse,
1151
1166
  type WorkflowRunResponse as WorkflowRunResponse,
1167
+ type WorkflowUserApprovalResponse as WorkflowUserApprovalResponse,
1152
1168
  type WorkflowListResponsesWorkflowsCursor as WorkflowListResponsesWorkflowsCursor,
1153
1169
  type WorkflowCreateParams as WorkflowCreateParams,
1154
1170
  type WorkflowUpdateParams as WorkflowUpdateParams,
@@ -1156,5 +1172,6 @@ export declare namespace Scenario {
1156
1172
  type WorkflowApproveUserParams as WorkflowApproveUserParams,
1157
1173
  type WorkflowGetTagsParams as WorkflowGetTagsParams,
1158
1174
  type WorkflowRunParams as WorkflowRunParams,
1175
+ type WorkflowUserApprovalParams as WorkflowUserApprovalParams,
1159
1176
  };
1160
1177
  }
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@ export {
22
22
  PermissionDeniedError,
23
23
  UnprocessableEntityError,
24
24
  } from './core/error';
25
- export { Job, type WaitOptions, type WithJob } from './lib/job';
25
+ export { EnhancedJobs, Job, type WaitOptions, type WithJob } from './lib/job';
26
26
  export { EnhancedWorkflows, WorkflowEntity } from './lib/workflow';
27
27
  export { validateWorkflowFlow } from './lib/workflow_validator';
28
28
  export {
@@ -34,3 +34,5 @@ export {
34
34
  } from './lib/workflow_import_validator';
35
35
  export { EnhancedGenerate } from './lib/generate';
36
36
  export { EnhancedModels, EnhancedTrain } from './lib/models';
37
+ export { EnhancedUploads, Upload, type UploadWaitOptions, type WithUpload } from './lib/upload';
38
+ export { EnhancedAssets, Asset, type WithAsset } from './lib/asset';
@@ -75,8 +75,6 @@ export type RequestOptions = {
75
75
  */
76
76
  defaultBaseURL?: string | undefined;
77
77
 
78
- __security?: { scBasicAuth?: boolean; scBearerAuth?: boolean };
79
-
80
78
  __binaryResponse?: boolean | undefined;
81
79
  };
82
80
 
@@ -0,0 +1,85 @@
1
+ import type { APIPromise } from '../core/api-promise';
2
+ import type { RequestOptions } from '../internal/request-options';
3
+ import {
4
+ Assets,
5
+ type AssetRetrieveParams,
6
+ type AssetRetrieveResponse,
7
+ type AssetUpdateParams,
8
+ type AssetUpdateResponse,
9
+ } from '../resources/assets/assets';
10
+
11
+ /** Asset methods added on top of the original asset fields. */
12
+ export class AssetMethods {
13
+ /**
14
+ * Fetch the asset's content as bytes, using the signed `url` field on the
15
+ * asset. Works in Node ≥18 and in browsers with no extra setup.
16
+ *
17
+ * This is a thin wrapper around `fetch(asset.url)` — use `asset.url`
18
+ * directly if you need streaming or a Response object.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const res = await client.assets.retrieve(assetId);
23
+ * const bytes = await res.asset.download();
24
+ * await fs.writeFile('out.png', bytes);
25
+ * ```
26
+ */
27
+ async download(this: Asset): Promise<Uint8Array> {
28
+ const res = await fetch(this.url);
29
+ if (!res.ok) {
30
+ throw new Error(`Failed to download asset ${this.id}: ${res.status} ${res.statusText}`);
31
+ }
32
+ return new Uint8Array(await res.arrayBuffer());
33
+ }
34
+
35
+ /** @internal Create an Asset from raw asset data. */
36
+ static from(data: AssetRetrieveResponse['asset']): Asset {
37
+ return Object.assign(Object.create(AssetMethods.prototype), data) as Asset;
38
+ }
39
+ }
40
+
41
+ /** An asset with all original fields plus `.download()`. */
42
+ export type Asset = AssetRetrieveResponse.Asset & AssetMethods;
43
+ export const Asset = AssetMethods;
44
+
45
+ /**
46
+ * @internal Helper type: adds `.download()` to the `asset` field of a response.
47
+ * Uses intersection so the original response type is preserved — a `WithAsset<T>` is still assignable to `T`.
48
+ */
49
+ export type WithAsset<T extends { asset: unknown }> = T & { asset: AssetMethods };
50
+
51
+ /**
52
+ * @internal Wrap `_thenUnwrap` to replace `response.asset` with an enhanced Asset.
53
+ */
54
+ export function enhanceAsset<T extends { asset: { id: string; url: string } }>(
55
+ promise: APIPromise<T>,
56
+ ): APIPromise<WithAsset<T>> {
57
+ return promise._thenUnwrap((data) => ({
58
+ ...data,
59
+ asset: Asset.from(data.asset as AssetRetrieveResponse['asset']),
60
+ }));
61
+ }
62
+
63
+ /**
64
+ * Enhanced Assets resource.
65
+ * All original methods (and subresources like `download`, `public`) are
66
+ * inherited. `retrieve` and `update` responses' `asset` field gains a
67
+ * `.download()` helper for fetching the asset's bytes.
68
+ */
69
+ export class EnhancedAssets extends Assets {
70
+ override retrieve(
71
+ assetID: string,
72
+ query: AssetRetrieveParams | null | undefined = {},
73
+ options?: RequestOptions,
74
+ ): APIPromise<WithAsset<AssetRetrieveResponse>> {
75
+ return enhanceAsset(super.retrieve(assetID, query, options));
76
+ }
77
+
78
+ override update(
79
+ assetID: string,
80
+ params: AssetUpdateParams,
81
+ options?: RequestOptions,
82
+ ): APIPromise<WithAsset<AssetUpdateResponse>> {
83
+ return enhanceAsset(super.update(assetID, params, options));
84
+ }
85
+ }
package/src/lib/job.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  import type { Scenario } from '../client';
2
2
  import type { APIPromise } from '../core/api-promise';
3
- import type { JobRetrieveResponse } from '../resources/jobs';
3
+ import type { RequestOptions } from '../internal/request-options';
4
+ import {
5
+ Jobs,
6
+ type JobRetrieveResponse,
7
+ type JobTriggerActionParams,
8
+ type JobTriggerActionResponse,
9
+ } from '../resources/jobs';
4
10
 
5
11
  export interface WaitOptions {
6
12
  /** Polling interval in milliseconds. Default: 3000 */
@@ -76,3 +82,24 @@ export function enhanceJob<T extends { job: { jobId: string; status: string } }>
76
82
  job: Job.from(client, data.job as JobRetrieveResponse['job']),
77
83
  }));
78
84
  }
85
+
86
+ /**
87
+ * Enhanced Jobs resource. `retrieve` and `triggerAction` responses' `job`
88
+ * field gains a `.wait()` helper — previously only job-creating endpoints
89
+ * (workflow.run, models.trigger, generate.*) had it. `list` is not enhanced:
90
+ * its items use a different (but structurally similar) type, and users
91
+ * typically fetch individual jobs via `retrieve` before acting on them.
92
+ */
93
+ export class EnhancedJobs extends Jobs {
94
+ override retrieve(jobID: string, options?: RequestOptions): APIPromise<WithJob<JobRetrieveResponse>> {
95
+ return enhanceJob(this._client, super.retrieve(jobID, options));
96
+ }
97
+
98
+ override triggerAction(
99
+ jobID: string,
100
+ params: JobTriggerActionParams,
101
+ options?: RequestOptions,
102
+ ): APIPromise<WithJob<JobTriggerActionResponse>> {
103
+ return enhanceJob(this._client, super.triggerAction(jobID, params, options));
104
+ }
105
+ }
@@ -1,5 +1,7 @@
1
1
  import { Scenario as BaseScenario } from '../client';
2
+ import { EnhancedAssets } from './asset';
2
3
  import { EnhancedGenerate } from './generate';
4
+ import { EnhancedJobs } from './job';
3
5
  import { EnhancedModels } from './models';
4
6
  import { EnhancedUploads } from './upload';
5
7
  import { EnhancedWorkflows } from './workflow';
@@ -31,6 +33,14 @@ import { EnhancedWorkflows } from './workflow';
31
33
  * // Enhanced: generate job.wait()
32
34
  * const gen = await client.generate.runModel(modelId, { body });
33
35
  * const done = await gen.job.wait();
36
+ *
37
+ * // Enhanced: upload.wait()
38
+ * const res = await client.uploads.retrieve(uploadId);
39
+ * const imported = await res.upload.wait();
40
+ *
41
+ * // Enhanced: asset.download()
42
+ * const a = await client.assets.retrieve(assetId);
43
+ * const bytes = await a.asset.download();
34
44
  * ```
35
45
  */
36
46
  export class Scenario extends BaseScenario {
@@ -38,4 +48,6 @@ export class Scenario extends BaseScenario {
38
48
  override generate: EnhancedGenerate = new EnhancedGenerate(this);
39
49
  override models: EnhancedModels = new EnhancedModels(this);
40
50
  override uploads: EnhancedUploads = new EnhancedUploads(this);
51
+ override assets: EnhancedAssets = new EnhancedAssets(this);
52
+ override jobs: EnhancedJobs = new EnhancedJobs(this);
41
53
  }
package/src/lib/upload.ts CHANGED
@@ -1,9 +1,13 @@
1
+ import type { Scenario } from '../client';
2
+ import type { APIPromise } from '../core/api-promise';
1
3
  import type { RequestOptions } from '../internal/request-options';
2
4
  import {
3
5
  Uploads,
4
6
  type UploadCreateParams,
5
7
  type UploadCreateResponse,
6
8
  type UploadRetrieveResponse,
9
+ type UploadTriggerActionParams,
10
+ type UploadTriggerActionResponse,
7
11
  } from '../resources/uploads';
8
12
  import type { AssetRetrieveResponse } from '../resources/assets/assets';
9
13
  import type { ModelRetrieveResponse } from '../resources/models/models';
@@ -64,19 +68,109 @@ const MAX_PART_SIZE = 5_368_709_120; // 5 GiB
64
68
  const MAX_PARTS = 10_000;
65
69
  const MAX_FILE_SIZE = 5_497_558_138_880; // 5 TiB
66
70
 
71
+ type UploadStatus = UploadRetrieveResponse.Upload['status'];
72
+
67
73
  // `validated` is intermediate — the server has validated the upload but
68
74
  // hasn't created the asset/model yet, so `entityId` isn't populated.
69
75
  // Real terminals are `imported` (asset/model created), `complete`, and
70
76
  // `failed`. Everything else means "keep polling".
71
- const TERMINAL_STATUSES = new Set(['complete', 'failed', 'imported']);
77
+ const TERMINAL_STATUSES: Set<UploadStatus> = new Set(['complete', 'failed', 'imported']);
78
+
79
+ export interface UploadWaitOptions {
80
+ /** Polling interval in milliseconds. Default: 2000 */
81
+ intervalMs?: number;
82
+ /** Maximum wait time in milliseconds. Default: 300000 */
83
+ timeoutMs?: number;
84
+ }
85
+
86
+ /** Upload methods added on top of the original upload fields. */
87
+ export class UploadMethods {
88
+ /** @internal */ declare readonly _client: Scenario;
89
+
90
+ /**
91
+ * Poll until the upload has been processed into an entity (asset or model),
92
+ * or reaches a terminal state (`imported`, `complete`, `failed`). Resolves
93
+ * with the latest upload data so you can read `entityId`, `status`, or
94
+ * `errorMessage` without a follow-up retrieve.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const res = await client.uploads.retrieve(uploadId);
99
+ * const done = await res.upload.wait();
100
+ * if (done.status === 'failed') throw new Error(done.errorMessage);
101
+ * console.log(done.entityId);
102
+ * ```
103
+ */
104
+ async wait(this: Upload, options?: UploadWaitOptions): Promise<Upload> {
105
+ const final = await pollUntilImported(
106
+ () => this._client.uploads.retrieve(this.id),
107
+ options?.intervalMs ?? 2_000,
108
+ options?.timeoutMs ?? 300_000,
109
+ );
110
+ return UploadMethods.from(this._client, final.upload);
111
+ }
112
+
113
+ /** @internal Create an Upload from raw upload data. */
114
+ static from(client: Scenario, data: UploadRetrieveResponse['upload']): Upload {
115
+ const upload = Object.assign(Object.create(UploadMethods.prototype), data) as Upload;
116
+ Object.defineProperty(upload, '_client', { value: client, enumerable: false });
117
+ return upload;
118
+ }
119
+ }
120
+
121
+ /** An upload with all original fields plus `.wait()`. */
122
+ export type Upload = UploadRetrieveResponse.Upload & UploadMethods;
123
+ export const Upload = UploadMethods;
124
+
125
+ /**
126
+ * @internal Helper type: adds `.wait()` to the `upload` field of a response.
127
+ * Uses intersection so the original response type is preserved — a `WithUpload<T>` is still assignable to `T`.
128
+ */
129
+ export type WithUpload<T extends { upload: unknown }> = T & { upload: UploadMethods };
130
+
131
+ /**
132
+ * @internal Wrap `_thenUnwrap` to replace `response.upload` with an enhanced Upload.
133
+ */
134
+ export function enhanceUpload<T extends { upload: { id: string; status: string } }>(
135
+ client: Scenario,
136
+ promise: APIPromise<T>,
137
+ ): APIPromise<WithUpload<T>> {
138
+ return promise._thenUnwrap((data) => ({
139
+ ...data,
140
+ upload: Upload.from(client, data.upload as UploadRetrieveResponse['upload']),
141
+ }));
142
+ }
72
143
 
73
144
  /**
74
145
  * Enhanced Uploads resource.
75
- * All original methods (`create`, `retrieve`, `triggerAction`) are inherited.
146
+ * All original methods (`create`, `retrieve`, `triggerAction`) are inherited,
147
+ * with each response's `upload` field enriched with a `.wait()` helper.
76
148
  * Adds `uploadFile()` — a one-call wrapper around the 4-step upload flow:
77
149
  * init → PUT parts to S3 → trigger complete → poll until imported.
78
150
  */
79
151
  export class EnhancedUploads extends Uploads {
152
+ override create(
153
+ body: UploadCreateParams,
154
+ options?: RequestOptions,
155
+ ): APIPromise<WithUpload<UploadCreateResponse>> {
156
+ return enhanceUpload(this._client, super.create(body, options));
157
+ }
158
+
159
+ override retrieve(
160
+ uploadID: string,
161
+ options?: RequestOptions,
162
+ ): APIPromise<WithUpload<UploadRetrieveResponse>> {
163
+ return enhanceUpload(this._client, super.retrieve(uploadID, options));
164
+ }
165
+
166
+ override triggerAction(
167
+ uploadID: string,
168
+ body: UploadTriggerActionParams,
169
+ options?: RequestOptions,
170
+ ): APIPromise<WithUpload<UploadTriggerActionResponse>> {
171
+ return enhanceUpload(this._client, super.triggerAction(uploadID, body, options));
172
+ }
173
+
80
174
  /**
81
175
  * Upload a file end-to-end. Computes an optimal part size (within AWS's
82
176
  * 5 MiB / 5 GiB / 10,000-part bounds), uploads all parts in parallel,
@@ -2,8 +2,8 @@ import type { APIPromise } from '../core/api-promise';
2
2
  import type { RequestOptions } from '../internal/request-options';
3
3
  import {
4
4
  Workflows,
5
+ WorkflowUserApprovalResponse,
5
6
  type WorkflowApproveUserParams,
6
- type WorkflowApproveUserResponse,
7
7
  type WorkflowRetrieveResponse,
8
8
  type WorkflowRunParams,
9
9
  type WorkflowRunResponse,
@@ -114,11 +114,11 @@ export class EnhancedWorkflows extends Workflows {
114
114
  }
115
115
 
116
116
  /** Approve a user approval node. Returns an enhanced response where `job` has `.wait()`. */
117
- override approveUser(
117
+ override userApproval(
118
118
  workflowID: string,
119
119
  body: WorkflowApproveUserParams,
120
120
  options?: RequestOptions,
121
- ): APIPromise<WithJob<WorkflowApproveUserResponse>> {
122
- return enhanceJob(this._client, super.approveUser(workflowID, body, options));
121
+ ): APIPromise<WithJob<WorkflowUserApprovalResponse>> {
122
+ return enhanceJob(this._client, super.userApproval(workflowID, body, options));
123
123
  }
124
124
  }