@meistrari/tela-sdk-js 2.4.3 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4,12 +4,12 @@ import * as z from 'zod';
4
4
  import z__default, { z as z$1, ZodError } from 'zod';
5
5
  import Emittery from 'emittery';
6
6
 
7
- const version = "2.4.3";
7
+ const version = "2.5.0";
8
8
 
9
- var __defProp$7 = Object.defineProperty;
10
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
- var __publicField$7 = (obj, key, value) => {
12
- __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
9
+ var __defProp$8 = Object.defineProperty;
10
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __publicField$8 = (obj, key, value) => {
12
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
13
13
  return value;
14
14
  };
15
15
  class TelaError extends Error {
@@ -37,7 +37,7 @@ class InvalidFileURL extends TelaError {
37
37
  class FileUploadError extends TelaError {
38
38
  constructor(message, statusCode) {
39
39
  super(`Failed to upload file: ${message} (Status code: ${statusCode})`);
40
- __publicField$7(this, "statusCode");
40
+ __publicField$8(this, "statusCode");
41
41
  this.statusCode = statusCode;
42
42
  }
43
43
  }
@@ -54,16 +54,23 @@ class InvalidExecutionModeError extends TelaError {
54
54
  class ExecutionFailedError extends TelaError {
55
55
  constructor(rawOutput) {
56
56
  super(`Execution failed: ${JSON.stringify(rawOutput)}`);
57
- __publicField$7(this, "rawOutput");
57
+ __publicField$8(this, "rawOutput");
58
58
  this.rawOutput = rawOutput;
59
59
  }
60
60
  }
61
+ class BatchExecutionFailedError extends TelaError {
62
+ constructor(rawResponse) {
63
+ super(`Batch execution failed: ${JSON.stringify(rawResponse)}`);
64
+ __publicField$8(this, "rawResponse");
65
+ this.rawResponse = rawResponse;
66
+ }
67
+ }
61
68
  class APIError extends TelaError {
62
69
  constructor(statusCode, error, _message) {
63
70
  const message = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : _message;
64
71
  super(message);
65
- __publicField$7(this, "statusCode");
66
- __publicField$7(this, "error");
72
+ __publicField$8(this, "statusCode");
73
+ __publicField$8(this, "error");
67
74
  this.statusCode = statusCode;
68
75
  this.error = error;
69
76
  }
@@ -105,7 +112,7 @@ class APIError extends TelaError {
105
112
  class UserAbortError extends APIError {
106
113
  constructor({ message } = {}) {
107
114
  super(void 0, void 0, message || "User aborted.");
108
- __publicField$7(this, "statusCode");
115
+ __publicField$8(this, "statusCode");
109
116
  }
110
117
  }
111
118
  class ConnectionError extends APIError {
@@ -114,7 +121,7 @@ class ConnectionError extends APIError {
114
121
  cause
115
122
  }) {
116
123
  super(void 0, void 0, message || "Connection error.");
117
- __publicField$7(this, "statusCode");
124
+ __publicField$8(this, "statusCode");
118
125
  if (cause)
119
126
  this.cause = cause;
120
127
  }
@@ -124,57 +131,57 @@ class ConnectionTimeout extends APIError {
124
131
  message
125
132
  } = {}) {
126
133
  super(void 0, void 0, message || "Request timed out.");
127
- __publicField$7(this, "statusCode");
134
+ __publicField$8(this, "statusCode");
128
135
  }
129
136
  }
130
137
  class BadRequestError extends APIError {
131
138
  constructor() {
132
139
  super(...arguments);
133
- __publicField$7(this, "statusCode", 400);
140
+ __publicField$8(this, "statusCode", 400);
134
141
  }
135
142
  // todo: handle validation errors from zod/typebox
136
143
  }
137
144
  class AuthenticationError extends APIError {
138
145
  constructor() {
139
146
  super(...arguments);
140
- __publicField$7(this, "statusCode", 401);
147
+ __publicField$8(this, "statusCode", 401);
141
148
  }
142
149
  }
143
150
  class AuthorizationError extends APIError {
144
151
  constructor() {
145
152
  super(...arguments);
146
- __publicField$7(this, "statusCode", 403);
153
+ __publicField$8(this, "statusCode", 403);
147
154
  }
148
155
  }
149
156
  class NotFoundError extends APIError {
150
157
  constructor() {
151
158
  super(...arguments);
152
- __publicField$7(this, "statusCode", 404);
159
+ __publicField$8(this, "statusCode", 404);
153
160
  }
154
161
  }
155
162
  class ConflictError extends APIError {
156
163
  constructor() {
157
164
  super(...arguments);
158
- __publicField$7(this, "statusCode", 409);
165
+ __publicField$8(this, "statusCode", 409);
159
166
  }
160
167
  }
161
168
  class UnprocessableEntityError extends APIError {
162
169
  constructor() {
163
170
  super(...arguments);
164
171
  // todo: check if tela returns 400 or 422 for zod errors
165
- __publicField$7(this, "statusCode", 422);
172
+ __publicField$8(this, "statusCode", 422);
166
173
  }
167
174
  }
168
175
  class RateLimitError extends APIError {
169
176
  constructor() {
170
177
  super(...arguments);
171
- __publicField$7(this, "statusCode", 429);
178
+ __publicField$8(this, "statusCode", 429);
172
179
  }
173
180
  }
174
181
  class InternalServerError extends APIError {
175
182
  constructor() {
176
183
  super(...arguments);
177
- __publicField$7(this, "statusCode", 500);
184
+ __publicField$8(this, "statusCode", 500);
178
185
  }
179
186
  }
180
187
  function toError(err) {
@@ -285,11 +292,38 @@ function transformObjectFromSnakeCaseToCamelCase(obj, exclusions = []) {
285
292
  }
286
293
  return result;
287
294
  }
295
+ const DURATION_REGEX = /(?<amount>\d+)(?<unit>[smhd])/;
296
+ const DURATION_UNITS = {
297
+ s: 1e3,
298
+ // 1 second in milliseconds
299
+ m: 6e4,
300
+ // 1 minute in milliseconds
301
+ h: 36e5,
302
+ // 1 hour in milliseconds
303
+ d: 864e5
304
+ // 1 day in milliseconds
305
+ };
306
+ function transformDurationToMs(durationStr) {
307
+ if (!durationStr) {
308
+ return void 0;
309
+ }
310
+ if (typeof durationStr === "number") {
311
+ return durationStr;
312
+ }
313
+ const match = durationStr.match(DURATION_REGEX);
314
+ const amount = match?.groups?.amount;
315
+ const unit = match?.groups?.unit;
316
+ const multiplier = DURATION_UNITS[unit];
317
+ if (!amount || Number.isNaN(Number.parseInt(amount)) || !multiplier) {
318
+ return void 0;
319
+ }
320
+ return Number.parseInt(amount) * multiplier;
321
+ }
288
322
 
289
- var __defProp$6 = Object.defineProperty;
290
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
291
- var __publicField$6 = (obj, key, value) => {
292
- __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
323
+ var __defProp$7 = Object.defineProperty;
324
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
325
+ var __publicField$7 = (obj, key, value) => {
326
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
293
327
  return value;
294
328
  };
295
329
  class Stream {
@@ -553,9 +587,9 @@ function findDoubleNewlineIndex(buffer) {
553
587
  }
554
588
  class SSEDecoder {
555
589
  constructor() {
556
- __publicField$6(this, "data");
557
- __publicField$6(this, "event");
558
- __publicField$6(this, "chunks");
590
+ __publicField$7(this, "data");
591
+ __publicField$7(this, "event");
592
+ __publicField$7(this, "chunks");
559
593
  this.event = null;
560
594
  this.data = [];
561
595
  this.chunks = [];
@@ -596,9 +630,9 @@ class SSEDecoder {
596
630
  const _LineDecoder = class _LineDecoder {
597
631
  // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
598
632
  constructor() {
599
- __publicField$6(this, "buffer");
600
- __publicField$6(this, "trailingCR");
601
- __publicField$6(this, "textDecoder");
633
+ __publicField$7(this, "buffer");
634
+ __publicField$7(this, "trailingCR");
635
+ __publicField$7(this, "textDecoder");
602
636
  this.buffer = [];
603
637
  this.trailingCR = false;
604
638
  }
@@ -673,8 +707,8 @@ const _LineDecoder = class _LineDecoder {
673
707
  }
674
708
  };
675
709
  // prettier-ignore
676
- __publicField$6(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
677
- __publicField$6(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
710
+ __publicField$7(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
711
+ __publicField$7(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
678
712
  let LineDecoder = _LineDecoder;
679
713
  function partition(str, delimiter) {
680
714
  const index = str.indexOf(delimiter);
@@ -711,10 +745,10 @@ function readableStreamAsyncIterable(stream) {
711
745
  };
712
746
  }
713
747
 
714
- var __defProp$5 = Object.defineProperty;
715
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
716
- var __publicField$5 = (obj, key, value) => {
717
- __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
748
+ var __defProp$6 = Object.defineProperty;
749
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
750
+ var __publicField$6 = (obj, key, value) => {
751
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
718
752
  return value;
719
753
  };
720
754
  function getRequestIdFromResponse(response) {
@@ -756,6 +790,7 @@ function getRequestIdFromResponse(response) {
756
790
  }
757
791
  async function defaultParseResponse(props) {
758
792
  const { response } = props;
793
+ const { transformCase = true } = props.options;
759
794
  if (props.options.stream) {
760
795
  debug("response", response.status, response.url, response.headers, response.body);
761
796
  return Stream.fromSSEResponse(response, props.controller);
@@ -773,18 +808,27 @@ async function defaultParseResponse(props) {
773
808
  if (requestId) {
774
809
  finalJson.requestId = requestId;
775
810
  }
776
- return transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
811
+ return transformCase ? transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : finalJson;
777
812
  }
778
813
  const text = await response.text();
779
814
  debug("response", response.status, response.url, response.headers, text);
780
815
  return text;
781
816
  }
817
+ function transformBody(body, transformCase) {
818
+ if (!body) {
819
+ return void 0;
820
+ }
821
+ if (transformCase) {
822
+ return transformObjectFromCamelCaseToSnakeCase(body, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
823
+ }
824
+ return body;
825
+ }
782
826
  class BaseClient {
783
827
  constructor({ baseURL, maxRetries = 5, timeout = 0 }) {
784
- __publicField$5(this, "baseURL");
785
- __publicField$5(this, "maxRetries");
786
- __publicField$5(this, "timeout");
787
- __publicField$5(this, "fetch");
828
+ __publicField$6(this, "baseURL");
829
+ __publicField$6(this, "maxRetries");
830
+ __publicField$6(this, "timeout");
831
+ __publicField$6(this, "fetch");
788
832
  this.baseURL = baseURL;
789
833
  this.maxRetries = validateMaxRetries(maxRetries);
790
834
  this.timeout = validateTimeout(timeout);
@@ -823,10 +867,11 @@ class BaseClient {
823
867
  return this.methodRequest("DELETE", path, opts);
824
868
  }
825
869
  async methodRequest(method, path, opts) {
870
+ const { transformCase = true } = opts ?? {};
826
871
  const headers = this.createHeaders();
827
872
  debug("methodRequest", method, path, opts);
828
873
  const transformedQuery = opts?.query ? transformObjectFromCamelCaseToSnakeCase(opts.query, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : void 0;
829
- const transformedBody = opts?.body ? transformObjectFromCamelCaseToSnakeCase(opts.body, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : void 0;
874
+ const transformedBody = transformBody(opts?.body, transformCase);
830
875
  const { response, options, controller } = await this.request({
831
876
  method,
832
877
  path,
@@ -1060,10 +1105,10 @@ async function getStreamSize(stream) {
1060
1105
  return size;
1061
1106
  }
1062
1107
 
1063
- var __defProp$4 = Object.defineProperty;
1064
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1065
- var __publicField$4 = (obj, key, value) => {
1066
- __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1108
+ var __defProp$5 = Object.defineProperty;
1109
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1110
+ var __publicField$5 = (obj, key, value) => {
1111
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1067
1112
  return value;
1068
1113
  };
1069
1114
  function TelaFileSchema() {
@@ -1071,11 +1116,11 @@ function TelaFileSchema() {
1071
1116
  }
1072
1117
  class TelaFile {
1073
1118
  constructor(file, options = {}) {
1074
- __publicField$4(this, "_file");
1075
- __publicField$4(this, "_options");
1076
- __publicField$4(this, "_size", null);
1077
- __publicField$4(this, "_mimeType");
1078
- __publicField$4(this, "_name");
1119
+ __publicField$5(this, "_file");
1120
+ __publicField$5(this, "_options");
1121
+ __publicField$5(this, "_size", null);
1122
+ __publicField$5(this, "_mimeType");
1123
+ __publicField$5(this, "_name");
1079
1124
  this._file = file;
1080
1125
  if (file instanceof File || file instanceof Blob) {
1081
1126
  this._size = file.size;
@@ -1379,10 +1424,10 @@ function validateOutputSchema(clientSchema, serverSchema) {
1379
1424
  return compareSchemas(clientSchema, serverSchema);
1380
1425
  }
1381
1426
 
1382
- var __defProp$3 = Object.defineProperty;
1383
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1384
- var __publicField$3 = (obj, key, value) => {
1385
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1427
+ var __defProp$4 = Object.defineProperty;
1428
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1429
+ var __publicField$4 = (obj, key, value) => {
1430
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1386
1431
  return value;
1387
1432
  };
1388
1433
  function timeout(ms, signal) {
@@ -1398,10 +1443,10 @@ function timeout(ms, signal) {
1398
1443
  }
1399
1444
  class Poller {
1400
1445
  constructor({ interval, timeout: timeout2, abortSignal }) {
1401
- __publicField$3(this, "_interval");
1402
- __publicField$3(this, "_timeout");
1403
- __publicField$3(this, "_abortSignal");
1404
- __publicField$3(this, "_internalAbortController");
1446
+ __publicField$4(this, "_interval");
1447
+ __publicField$4(this, "_timeout");
1448
+ __publicField$4(this, "_abortSignal");
1449
+ __publicField$4(this, "_internalAbortController");
1405
1450
  if (interval <= 0) {
1406
1451
  throw new TelaError("Interval must be greater than 0");
1407
1452
  }
@@ -1447,7 +1492,7 @@ class Poller {
1447
1492
  const resultPromise = async () => {
1448
1493
  try {
1449
1494
  while (!this._abortSignal.aborted) {
1450
- const result = await callback(this._abortSignal);
1495
+ const result = await callback();
1451
1496
  if (result.done) {
1452
1497
  return result.value;
1453
1498
  }
@@ -1497,10 +1542,82 @@ async function calculateSha256sum(content) {
1497
1542
  }
1498
1543
  }
1499
1544
 
1500
- var __defProp$2 = Object.defineProperty;
1501
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1502
- var __publicField$2 = (obj, key, value) => {
1503
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1545
+ async function uploadFile(file, client) {
1546
+ let content = await file.getUploadableContent();
1547
+ let sha256sumStream;
1548
+ if (typeof content === "string") {
1549
+ return { fileUrl: content, options: file.options };
1550
+ }
1551
+ const filename = file.name ?? void 0;
1552
+ const fileType = file.type ?? void 0;
1553
+ const contentLength = file.size ?? void 0;
1554
+ if (content instanceof ReadableStream) {
1555
+ const [hashStream, contentStream] = content.tee();
1556
+ content = contentStream;
1557
+ sha256sumStream = hashStream;
1558
+ }
1559
+ const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
1560
+ const { id, uploadUrl } = await client.post("/_services/vault/files", {
1561
+ body: {
1562
+ fileName: filename,
1563
+ mimeType: fileType,
1564
+ size: contentLength ?? void 0,
1565
+ sha256sum
1566
+ },
1567
+ transformCase: false
1568
+ });
1569
+ if (content instanceof ReadableStream && typeof Bun !== "undefined") {
1570
+ console.warn(
1571
+ "[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
1572
+ { fileName: filename, fileSize: contentLength }
1573
+ );
1574
+ const chunks = [];
1575
+ const reader = content.getReader();
1576
+ while (true) {
1577
+ const { done, value } = await reader.read();
1578
+ if (done)
1579
+ break;
1580
+ chunks.push(value);
1581
+ }
1582
+ content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
1583
+ }
1584
+ const request = new Request(uploadUrl, {
1585
+ method: "PUT",
1586
+ body: content,
1587
+ headers: {
1588
+ "Content-Type": fileType ?? "application/octet-stream",
1589
+ ...file.size ? { "Content-Length": file.size.toString() } : {}
1590
+ }
1591
+ });
1592
+ const uploadResponse = await fetch(request);
1593
+ if (!uploadResponse.ok) {
1594
+ throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
1595
+ }
1596
+ return { fileUrl: `vault://${id}`, options: file.options };
1597
+ }
1598
+ async function downloadFile(vaultReference, client) {
1599
+ const vaultId = vaultReference.replace("vault://", "");
1600
+ const response = await client.get(`/_services/vault/files/${vaultId}`);
1601
+ return fetch(response.url).then((res) => res.blob());
1602
+ }
1603
+ async function streamFile(vaultReference, client) {
1604
+ const vaultId = vaultReference.replace("vault://", "");
1605
+ const response = await client.get(`/_services/vault/files/${vaultId}`);
1606
+ return fetch(response.url).then((res) => {
1607
+ if (!res.ok) {
1608
+ throw new Error("Failed to stream file", { cause: res.statusText });
1609
+ }
1610
+ if (!res.body) {
1611
+ throw new Error("Failed to stream file", { cause: "No body" });
1612
+ }
1613
+ return res.body;
1614
+ });
1615
+ }
1616
+
1617
+ var __defProp$3 = Object.defineProperty;
1618
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1619
+ var __publicField$3 = (obj, key, value) => {
1620
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1504
1621
  return value;
1505
1622
  };
1506
1623
  function isTelaFile(obj) {
@@ -1551,20 +1668,20 @@ class CanvasExecution extends Emittery {
1551
1668
  */
1552
1669
  constructor(variables, params = { async: false }, outputSchema, client, isTask = false) {
1553
1670
  super();
1554
- __publicField$2(this, "_id");
1555
- __publicField$2(this, "_status");
1556
- __publicField$2(this, "_variables");
1557
- __publicField$2(this, "_params");
1558
- __publicField$2(this, "_client");
1559
- __publicField$2(this, "_outputSchema");
1560
- __publicField$2(this, "_skipResultValidation");
1561
- __publicField$2(this, "_abortController");
1562
- __publicField$2(this, "_isTask");
1563
- __publicField$2(this, "_resultPromise");
1564
- __publicField$2(this, "_stream");
1565
- __publicField$2(this, "_rawResultValue");
1566
- __publicField$2(this, "_requestId");
1567
- __publicField$2(this, "_task");
1671
+ __publicField$3(this, "_id");
1672
+ __publicField$3(this, "_status");
1673
+ __publicField$3(this, "_variables");
1674
+ __publicField$3(this, "_params");
1675
+ __publicField$3(this, "_client");
1676
+ __publicField$3(this, "_outputSchema");
1677
+ __publicField$3(this, "_skipResultValidation");
1678
+ __publicField$3(this, "_abortController");
1679
+ __publicField$3(this, "_isTask");
1680
+ __publicField$3(this, "_resultPromise");
1681
+ __publicField$3(this, "_stream");
1682
+ __publicField$3(this, "_rawResultValue");
1683
+ __publicField$3(this, "_requestId");
1684
+ __publicField$3(this, "_task");
1568
1685
  this._variables = variables;
1569
1686
  this._params = params;
1570
1687
  this._outputSchema = outputSchema;
@@ -2109,16 +2226,16 @@ class CanvasExecution extends Emittery {
2109
2226
  throw new InvalidExecutionModeError("Polling is only supported for async executions");
2110
2227
  }
2111
2228
  return new Poller({
2112
- interval: this._params.pollingInterval ?? 1e3,
2229
+ interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
2113
2230
  // 1 second
2114
- timeout: this._params.pollingTimeout ?? 6e4,
2231
+ timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
2115
2232
  // 1 minute
2116
2233
  abortSignal: this._abortController.signal
2117
- }).start(async (signal) => {
2234
+ }).start(async () => {
2118
2235
  const response = await this._client.get(
2119
2236
  `/v2/chat/completions/${this.id}`,
2120
2237
  {
2121
- signal
2238
+ signal: this._abortController.signal
2122
2239
  }
2123
2240
  );
2124
2241
  this.status = response.status;
@@ -2176,56 +2293,7 @@ class CanvasExecution extends Emittery {
2176
2293
  * ```
2177
2294
  */
2178
2295
  async uploadFile(file) {
2179
- let content = await file.getUploadableContent();
2180
- let sha256sumStream;
2181
- if (typeof content === "string") {
2182
- return { fileUrl: content, options: file.options };
2183
- }
2184
- const filename = file.name ?? void 0;
2185
- const fileType = file.type ?? void 0;
2186
- const contentLength = file.size ?? void 0;
2187
- if (content instanceof ReadableStream) {
2188
- const [hashStream, contentStream] = content.tee();
2189
- content = contentStream;
2190
- sha256sumStream = hashStream;
2191
- }
2192
- const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
2193
- const { id, uploadUrl } = await this._client.post("/_services/vault/files", {
2194
- body: {
2195
- fileName: filename,
2196
- mimeType: fileType,
2197
- size: contentLength ?? void 0,
2198
- sha256sum
2199
- }
2200
- });
2201
- if (content instanceof ReadableStream && typeof Bun !== "undefined") {
2202
- console.warn(
2203
- "[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
2204
- { fileName: filename, fileSize: contentLength }
2205
- );
2206
- const chunks = [];
2207
- const reader = content.getReader();
2208
- while (true) {
2209
- const { done, value } = await reader.read();
2210
- if (done)
2211
- break;
2212
- chunks.push(value);
2213
- }
2214
- content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
2215
- }
2216
- const request = new Request(uploadUrl, {
2217
- method: "PUT",
2218
- body: content,
2219
- headers: {
2220
- "Content-Type": fileType ?? "application/octet-stream",
2221
- ...file.size ? { "Content-Length": file.size.toString() } : {}
2222
- }
2223
- });
2224
- const uploadResponse = await fetch(request);
2225
- if (!uploadResponse.ok) {
2226
- throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
2227
- }
2228
- return { fileUrl: `vault://${id}`, options: file.options };
2296
+ return uploadFile(file, this._client);
2229
2297
  }
2230
2298
  /**
2231
2299
  * Uploads multiple files and returns their URLs and options.
@@ -2242,6 +2310,749 @@ class CanvasExecution extends Emittery {
2242
2310
  }
2243
2311
  }
2244
2312
 
2313
+ var __defProp$2 = Object.defineProperty;
2314
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2315
+ var __publicField$2 = (obj, key, value) => {
2316
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
2317
+ return value;
2318
+ };
2319
+ const BatchResultItem = z__default.looseObject({
2320
+ reference_id: z__default.string(),
2321
+ status: z__default.string(),
2322
+ execution_id: z__default.string(),
2323
+ result: z__default.object({
2324
+ id: z__default.string(),
2325
+ tags: z__default.array(z__default.string()),
2326
+ status: z__default.string(),
2327
+ metadata: z__default.object({
2328
+ promptVersion: z__default.object({
2329
+ modelConfigurations: z__default.object({
2330
+ type: z__default.string(),
2331
+ model: z__default.string(),
2332
+ temperature: z__default.number(),
2333
+ structuredOutput: z__default.object({
2334
+ schema: z__default.looseObject({}).optional(),
2335
+ enabled: z__default.boolean()
2336
+ })
2337
+ }),
2338
+ variablesDefinitions: z__default.array(
2339
+ z__default.object({
2340
+ name: z__default.string(),
2341
+ type: z__default.string(),
2342
+ required: z__default.boolean(),
2343
+ processingOptions: z__default.object({ allowMultimodal: z__default.boolean() })
2344
+ })
2345
+ )
2346
+ })
2347
+ }),
2348
+ promptId: z__default.string(),
2349
+ rawInput: z__default.object({
2350
+ tags: z__default.array(z__default.string()),
2351
+ async: z__default.boolean(),
2352
+ canvas_id: z__default.string(),
2353
+ variables: z__default.looseObject({})
2354
+ }),
2355
+ createdAt: z__default.string(),
2356
+ deletedAt: z__default.null(),
2357
+ rawOutput: z__default.object({
2358
+ id: z__default.string(),
2359
+ usage: z__default.object({
2360
+ cost: z__default.object({
2361
+ total_cost: z__default.number(),
2362
+ prompt_cost: z__default.number(),
2363
+ completion_cost: z__default.number()
2364
+ }),
2365
+ total_tokens: z__default.number(),
2366
+ prompt_tokens: z__default.number(),
2367
+ completion_tokens: z__default.number()
2368
+ }),
2369
+ object: z__default.string(),
2370
+ choices: z__default.array(
2371
+ z__default.object({
2372
+ message: z__default.object({
2373
+ role: z__default.string(),
2374
+ content: z__default.looseObject({}),
2375
+ tool_calls: z__default.array(z__default.object({ type: z__default.string(), function: z__default.object({ name: z__default.string(), arguments: z__default.looseObject({}) }) })),
2376
+ function_call: z__default.null()
2377
+ })
2378
+ })
2379
+ ),
2380
+ created: z__default.number()
2381
+ }),
2382
+ updatedAt: z__default.string(),
2383
+ creditsUsed: z__default.number(),
2384
+ workspaceId: z__default.string(),
2385
+ inputContent: z__default.object({
2386
+ files: z__default.array(z__default.object({ file_url: z__default.string() })),
2387
+ messages: z__default.array(z__default.object({ role: z__default.string(), content: z__default.looseObject({}) })),
2388
+ variables: z__default.looseObject({})
2389
+ }),
2390
+ outputContent: z__default.object({
2391
+ role: z__default.string(),
2392
+ content: z__default.looseObject({}),
2393
+ tool_calls: z__default.array(z__default.looseObject({})),
2394
+ function_call: z__default.string().nullable()
2395
+ }),
2396
+ promptVersionId: z__default.string(),
2397
+ compatibilityDate: z__default.string(),
2398
+ promptApplicationId: z__default.string().nullable()
2399
+ }),
2400
+ error: z__default.null()
2401
+ });
2402
+ class BatchExecutionResult {
2403
+ /**
2404
+ * Creates a new batch execution result wrapper.
2405
+ *
2406
+ * @param client - HTTP client for making API requests.
2407
+ * @param response - Raw batch execution response from the server.
2408
+ * @internal
2409
+ */
2410
+ constructor(client, response) {
2411
+ __publicField$2(this, "_client");
2412
+ __publicField$2(this, "_response");
2413
+ this._client = client;
2414
+ this._response = response;
2415
+ }
2416
+ get requestId() {
2417
+ return this._response.requestId;
2418
+ }
2419
+ /**
2420
+ * Gets the unique identifier for this batch execution.
2421
+ *
2422
+ * @returns The batch execution ID.
2423
+ */
2424
+ get id() {
2425
+ return this._response.id;
2426
+ }
2427
+ /**
2428
+ * Gets the current status of the batch execution.
2429
+ *
2430
+ * @returns The batch status.
2431
+ */
2432
+ get status() {
2433
+ return this._response.status;
2434
+ }
2435
+ /**
2436
+ * Gets the progress statistics for this batch.
2437
+ *
2438
+ * @returns Object containing completed, failed, and total execution counts, or null if not available.
2439
+ */
2440
+ get state() {
2441
+ return this._response.state;
2442
+ }
2443
+ /**
2444
+ * Gets the vault URL of the output JSONL file containing all results.
2445
+ *
2446
+ * @returns The output file URL, or null if batch is not completed.
2447
+ */
2448
+ get outputFile() {
2449
+ return this._response.outputFile;
2450
+ }
2451
+ /**
2452
+ * Gets the raw API response without any processing.
2453
+ *
2454
+ * @returns The complete batch response object.
2455
+ */
2456
+ get rawResponse() {
2457
+ return this._response;
2458
+ }
2459
+ /**
2460
+ * Gets the timestamp when this batch was created.
2461
+ *
2462
+ * @returns Creation date.
2463
+ */
2464
+ get createdAt() {
2465
+ return new Date(this._response.createdAt);
2466
+ }
2467
+ /**
2468
+ * Gets the timestamp when this batch was last updated.
2469
+ *
2470
+ * @returns Last update date.
2471
+ */
2472
+ get updatedAt() {
2473
+ return new Date(this._response.updatedAt);
2474
+ }
2475
+ /**
2476
+ * Gets the timestamp when this batch completed successfully.
2477
+ *
2478
+ * @returns Completion date, or null if not completed.
2479
+ */
2480
+ get completedAt() {
2481
+ return this._response.completedAt ? new Date(this._response.completedAt) : null;
2482
+ }
2483
+ /**
2484
+ * Gets the timestamp when this batch was canceled.
2485
+ *
2486
+ * @returns Cancellation date, or null if not canceled.
2487
+ */
2488
+ get canceledAt() {
2489
+ return this._response.canceledAt ? new Date(this._response.canceledAt) : null;
2490
+ }
2491
+ /**
2492
+ * Gets the timestamp when this batch failed.
2493
+ *
2494
+ * @returns Failure date, or null if not failed.
2495
+ */
2496
+ get failedAt() {
2497
+ return this._response.failedAt ? new Date(this._response.failedAt) : null;
2498
+ }
2499
+ /**
2500
+ * Downloads the complete output file as a Blob.
2501
+ *
2502
+ * The output file is a JSONL (JSON Lines) file where each line contains
2503
+ * one execution result with its reference ID, status, and output.
2504
+ *
2505
+ * @throws {Error} If batch is not completed or output file is unavailable.
2506
+ * @returns A promise resolving to the output file as a Blob.
2507
+ *
2508
+ * @example
2509
+ * ```typescript
2510
+ * const file = await result.downloadOutputFile()
2511
+ * const text = await file.text()
2512
+ * console.log(text) // JSONL content
2513
+ * ```
2514
+ */
2515
+ downloadOutputFile() {
2516
+ this.validateOutputFile();
2517
+ return downloadFile(this._response.outputFile, this._client);
2518
+ }
2519
+ /**
2520
+ * Streams the output file as a ReadableStream for memory-efficient processing.
2521
+ *
2522
+ * Useful for large batches where loading the entire file into memory is not practical.
2523
+ *
2524
+ * @throws {Error} If batch is not completed or output file is unavailable.
2525
+ * @returns A promise resolving to a ReadableStream of the output file.
2526
+ *
2527
+ * @example
2528
+ * ```typescript
2529
+ * const stream = await result.streamOutputFile()
2530
+ * // Process stream with custom logic
2531
+ * ```
2532
+ */
2533
+ async streamOutputFile() {
2534
+ this.validateOutputFile();
2535
+ return streamFile(this._response.outputFile, this._client);
2536
+ }
2537
+ /**
2538
+ * Downloads and parses all results into an array.
2539
+ *
2540
+ * Loads the entire output file into memory, parses each line, and extracts
2541
+ * the output content. For large batches, consider using `iterateResults()` instead.
2542
+ *
2543
+ * @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
2544
+ * @returns A promise resolving to an array of all execution outputs.
2545
+ *
2546
+ * @example
2547
+ * ```typescript
2548
+ * const results = await result.getResults()
2549
+ * console.log(`Got ${results.length} results`)
2550
+ * results.forEach((output, i) => console.log(`Result ${i}:`, output))
2551
+ * ```
2552
+ */
2553
+ async getResults() {
2554
+ const resultFile = await this.downloadOutputFile();
2555
+ const results = await resultFile.text();
2556
+ return results.split("\n").filter((line) => line.trim().length > 0).map((result) => JSON.parse(result)).map((result) => {
2557
+ const parsedResult = BatchResultItem.safeParse(result);
2558
+ if (!parsedResult.success) {
2559
+ throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
2560
+ }
2561
+ return parsedResult.data.result.outputContent.content;
2562
+ });
2563
+ }
2564
+ /**
2565
+ * Asynchronously iterates over raw result items from the output file.
2566
+ *
2567
+ * Streams and parses the output file line-by-line, yielding raw JSON objects.
2568
+ * Each yielded object contains the full result structure including metadata.
2569
+ *
2570
+ * @param params - Iteration options.
2571
+ * @param params.abortController - Optional AbortController to cancel iteration.
2572
+ * @throws {Error} If batch is not completed or output file is unavailable.
2573
+ * @yields Raw result objects from the JSONL file.
2574
+ *
2575
+ * @example
2576
+ * ```typescript
2577
+ * for await (const rawResult of result.iterateRawResults()) {
2578
+ * console.log('Reference ID:', rawResult.reference_id)
2579
+ * console.log('Status:', rawResult.status)
2580
+ * console.log('Output:', rawResult.result.outputContent.content)
2581
+ * }
2582
+ * ```
2583
+ */
2584
+ async *iterateRawResults(params = {}) {
2585
+ const { abortController = new AbortController() } = params;
2586
+ const stream = await this.streamOutputFile();
2587
+ for await (const result of Stream.fromReadableStream(stream, abortController)) {
2588
+ yield result;
2589
+ }
2590
+ }
2591
+ /**
2592
+ * Asynchronously iterates over parsed output content from the batch results.
2593
+ *
2594
+ * Streams and parses the output file line-by-line, yielding only the output content
2595
+ * (not the full result metadata). Memory-efficient for large batches.
2596
+ *
2597
+ * @param params - Iteration options.
2598
+ * @param params.abortController - Optional AbortController to cancel iteration.
2599
+ * @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
2600
+ * @yields Parsed output content from each execution.
2601
+ *
2602
+ * @example
2603
+ * ```typescript
2604
+ * const controller = new AbortController()
2605
+ *
2606
+ * for await (const output of result.iterateResults({ abortController: controller })) {
2607
+ * console.log(output)
2608
+ * if (someCondition) {
2609
+ * controller.abort() // Stop iteration early
2610
+ * }
2611
+ * }
2612
+ * ```
2613
+ */
2614
+ async *iterateResults(params = {}) {
2615
+ for await (const result of this.iterateRawResults(params)) {
2616
+ const parsedResult = BatchResultItem.safeParse(result);
2617
+ if (!parsedResult.success) {
2618
+ throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
2619
+ }
2620
+ yield parsedResult.data.result.outputContent.content;
2621
+ }
2622
+ }
2623
+ /**
2624
+ * Fetches the raw result metadata for a specific execution by its reference ID.
2625
+ *
2626
+ * Queries the API for the execution result using the reference ID tag.
2627
+ * Returns the complete execution metadata including input, output, and usage statistics.
2628
+ *
2629
+ * @param referenceId - The reference ID of the execution to retrieve.
2630
+ * @throws {Error} If no result found with the given reference ID.
2631
+ * @returns A promise resolving to the raw execution result object.
2632
+ *
2633
+ * @example
2634
+ * ```typescript
2635
+ * const rawResult = await result.getRawResult('my-ref-id')
2636
+ * console.log('Credits used:', rawResult.creditsUsed)
2637
+ * console.log('Execution status:', rawResult.status)
2638
+ * ```
2639
+ */
2640
+ async getRawResult(referenceId) {
2641
+ const response = await this._client.get("/v1/completion-run/", {
2642
+ query: {
2643
+ tags: `reference_id:${referenceId}`
2644
+ }
2645
+ });
2646
+ const result = response.data[0];
2647
+ if (!result) {
2648
+ throw new Error("Result not found");
2649
+ }
2650
+ return result;
2651
+ }
2652
+ /**
2653
+ * Fetches the output content for a specific execution by its reference ID.
2654
+ *
2655
+ * Convenience method that retrieves the raw result and extracts just the output content.
2656
+ *
2657
+ * @param referenceId - The reference ID of the execution to retrieve.
2658
+ * @throws {Error} If no result found with the given reference ID.
2659
+ * @returns A promise resolving to the execution output content.
2660
+ *
2661
+ * @example
2662
+ * ```typescript
2663
+ * const output = await result.getResult('my-ref-id')
2664
+ * console.log('Output:', output)
2665
+ * ```
2666
+ */
2667
+ async getResult(referenceId) {
2668
+ const result = await this.getRawResult(referenceId);
2669
+ return result.outputContent.content;
2670
+ }
2671
+ /**
2672
+ * Validates that the output file is available for access.
2673
+ *
2674
+ * @throws {Error} If batch is not completed or output file is missing.
2675
+ * @private
2676
+ */
2677
+ validateOutputFile() {
2678
+ if (this._response.status !== "completed") {
2679
+ throw new Error("Batch execution is not completed");
2680
+ }
2681
+ if (!this._response.outputFile) {
2682
+ throw new Error("Output file not found");
2683
+ }
2684
+ }
2685
+ }
2686
+ class BatchExecution extends Emittery {
2687
+ /**
2688
+ * Creates a new batch execution instance.
2689
+ *
2690
+ * @param id - Unique identifier for this batch execution.
2691
+ * @param client - HTTP client for making API requests.
2692
+ * @param params - Batch execution parameters.
2693
+ * @param creationResponse - Initial response from batch creation.
2694
+ * @internal
2695
+ */
2696
+ constructor(id, client, params = {}, creationResponse) {
2697
+ super();
2698
+ __publicField$2(this, "_client");
2699
+ __publicField$2(this, "_id");
2700
+ __publicField$2(this, "_params");
2701
+ __publicField$2(this, "_abortController");
2702
+ __publicField$2(this, "_creationResponse");
2703
+ __publicField$2(this, "_status", "created");
2704
+ __publicField$2(this, "_resultPromise");
2705
+ this._id = id;
2706
+ this._client = client;
2707
+ this._params = params;
2708
+ this._abortController = new AbortController();
2709
+ this._creationResponse = creationResponse;
2710
+ }
2711
+ /**
2712
+ * Gets the latest known status of the batch execution.
2713
+ *
2714
+ * Status values and transitions:
2715
+ * - `created` → `validating` → `running` → `completed` or `failed`
2716
+ * - Can transition to `canceled` from any non-terminal state
2717
+ *
2718
+ * Use the `statusChange` event to track status transitions in real-time.
2719
+ *
2720
+ * @returns The current status of the batch execution.
2721
+ *
2722
+ * @example
2723
+ * ```typescript
2724
+ * const execution = await batch.execute()
2725
+ * console.log(execution.status) // 'created'
2726
+ *
2727
+ * execution.on('statusChange', ([status]) => {
2728
+ * console.log('New status:', status)
2729
+ * })
2730
+ *
2731
+ * await execution.result
2732
+ * console.log(execution.status) // 'completed' or 'failed'
2733
+ * ```
2734
+ */
2735
+ get status() {
2736
+ return this._status;
2737
+ }
2738
+ /**
2739
+ * Gets the unique identifier for this batch execution.
2740
+ *
2741
+ * @returns The batch execution ID.
2742
+ */
2743
+ get id() {
2744
+ return this._id;
2745
+ }
2746
+ /**
2747
+ * Gets the batch execution parameters.
2748
+ *
2749
+ * @returns The batch parameters.
2750
+ */
2751
+ get params() {
2752
+ return this._params;
2753
+ }
2754
+ /**
2755
+ * Cancels the batch execution.
2756
+ *
2757
+ * Sends a cancellation request to the server and aborts any ongoing polling.
2758
+ * The batch will stop processing, but already-completed executions remain available.
2759
+ *
2760
+ * @returns A promise that resolves when the cancellation request completes.
2761
+ *
2762
+ * @example
2763
+ * ```typescript
2764
+ * const execution = await batch.execute()
2765
+ * execution.poll()
2766
+ *
2767
+ * // Cancel after some condition
2768
+ * if (shouldCancel) {
2769
+ * await execution.cancel()
2770
+ * console.log(execution.status) // 'canceled'
2771
+ * }
2772
+ * ```
2773
+ */
2774
+ async cancel() {
2775
+ await this._client.put(`/_services/batch/batches/${this._id}/cancel`);
2776
+ this._status = "canceled";
2777
+ this._abortController.abort();
2778
+ }
2779
+ /**
2780
+ * Starts polling for the batch result without waiting for the promise to resolve.
2781
+ * This allows users to track batch progress via events rather than awaiting a promise.
2782
+ *
2783
+ * The following events will be emitted during polling:
2784
+ * - `statusChange`: Emitted when the batch status changes (e.g., 'created' → 'running' → 'completed')
2785
+ * - `poll`: Emitted on each polling attempt with the server response
2786
+ * - `success`: Emitted when the batch completes successfully with the final result
2787
+ * - `error`: Emitted if the batch fails
2788
+ *
2789
+ * **Important:** Events are only emitted while polling is active. You must call `poll()` or
2790
+ * await `execution.result` to start polling. Simply setting up event listeners without starting
2791
+ * polling will not trigger any events.
2792
+ *
2793
+ * @example
2794
+ * ```typescript
2795
+ * const execution = await batch.execute()
2796
+ *
2797
+ * // Set up event listeners
2798
+ * execution.on('statusChange', ([status, response]) => {
2799
+ * console.log(`Status: ${status}`)
2800
+ * if (response.state) {
2801
+ * const { completed, total } = response.state
2802
+ * console.log(`Progress: ${completed}/${total}`)
2803
+ * }
2804
+ * })
2805
+ *
2806
+ * execution.on('success', (result) => {
2807
+ * console.log('Batch completed!')
2808
+ * console.log('Request ID:', result.requestId)
2809
+ * })
2810
+ *
2811
+ * execution.on('error', (error) => {
2812
+ * console.error('Batch failed:', error)
2813
+ * })
2814
+ *
2815
+ * // Start polling without waiting
2816
+ * execution.poll()
2817
+ * ```
2818
+ */
2819
+ poll() {
2820
+ if (this._resultPromise) {
2821
+ return;
2822
+ }
2823
+ this._resultPromise = this.startPolling();
2824
+ this._resultPromise.catch(() => {
2825
+ });
2826
+ }
2827
+ /**
2828
+ * Sets the batch status and emits statusChange event if changed.
2829
+ *
2830
+ * @param status - The new status.
2831
+ * @param response - The response containing the status.
2832
+ * @private
2833
+ */
2834
+ setStatus(status, response) {
2835
+ const changed = this._status !== status;
2836
+ this._status = status;
2837
+ if (changed) {
2838
+ this.emit("statusChange", [status, response]);
2839
+ }
2840
+ }
2841
+ /**
2842
+ * Starts polling the server for batch completion.
2843
+ * Continues polling until the batch completes, fails, or times out.
2844
+ *
2845
+ * @throws {BatchExecutionFailedError} If the batch fails on the server.
2846
+ * @throws {Error} If the polling operation times out.
2847
+ * @returns A promise resolving to the final batch result.
2848
+ * @private
2849
+ */
2850
+ async startPolling() {
2851
+ this.emit("statusChange", [this._status, this._creationResponse]);
2852
+ return new Poller({
2853
+ interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
2854
+ // 1 second
2855
+ timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
2856
+ // 1 minute
2857
+ abortSignal: this._abortController.signal
2858
+ }).start(async () => {
2859
+ const response = await this._client.get(
2860
+ `/_services/batch/batches/${this._id}`,
2861
+ { signal: this._abortController.signal }
2862
+ );
2863
+ this.emit("poll", response);
2864
+ this.setStatus(response.status, response);
2865
+ if (response.status === "failed") {
2866
+ const error = new BatchExecutionFailedError(response);
2867
+ this._abortController.abort();
2868
+ this.emit("error", error);
2869
+ throw error;
2870
+ }
2871
+ if (response.status !== "completed") {
2872
+ return {
2873
+ done: false,
2874
+ value: void 0
2875
+ };
2876
+ }
2877
+ const result = new BatchExecutionResult(this._client, response);
2878
+ this.emit("success", result);
2879
+ return {
2880
+ done: true,
2881
+ value: result
2882
+ };
2883
+ });
2884
+ }
2885
+ /**
2886
+ * Gets the batch execution result. Automatically starts polling if not already started.
2887
+ *
2888
+ * @returns A promise resolving to the batch execution result.
2889
+ *
2890
+ * @example
2891
+ * ```typescript
2892
+ * const execution = await batch.execute()
2893
+ * const result = await execution.result
2894
+ *
2895
+ * // Access results
2896
+ * const outputs = await result.getResults()
2897
+ * console.log(`Got ${outputs.length} results`)
2898
+ * ```
2899
+ */
2900
+ get result() {
2901
+ if (!this._resultPromise) {
2902
+ this._resultPromise = this.startPolling();
2903
+ }
2904
+ return this._resultPromise;
2905
+ }
2906
+ }
2907
+ class Batch {
2908
+ /**
2909
+ * Creates a new batch builder.
2910
+ *
2911
+ * @param client - HTTP client for making API requests.
2912
+ * @param canvasIdentifier - Canvas identification (ID + version or application ID).
2913
+ * @param params - Optional batch execution parameters.
2914
+ * @internal
2915
+ */
2916
+ constructor(client, canvasIdentifier, params = {}) {
2917
+ __publicField$2(this, "_client");
2918
+ __publicField$2(this, "_canvasIdentifier");
2919
+ __publicField$2(this, "_items", []);
2920
+ __publicField$2(this, "_params");
2921
+ this._client = client;
2922
+ this._canvasIdentifier = canvasIdentifier;
2923
+ this._params = params;
2924
+ }
2925
+ /**
2926
+ * Gets the current list of items in this batch.
2927
+ *
2928
+ * @returns Array of batch items.
2929
+ */
2930
+ get items() {
2931
+ return this._items;
2932
+ }
2933
+ /**
2934
+ * Gets the batch execution parameters.
2935
+ *
2936
+ * @returns The batch parameters.
2937
+ */
2938
+ get params() {
2939
+ return this._params;
2940
+ }
2941
+ /**
2942
+ * Gets the canvas identifier in the format expected by the API.
2943
+ *
2944
+ * @returns Canvas identifier object.
2945
+ * @private
2946
+ */
2947
+ get canvasIdentifier() {
2948
+ return "applicationId" in this._canvasIdentifier ? { applicationId: this._canvasIdentifier.applicationId } : { versionId: this._canvasIdentifier.versionId, canvasID: this._canvasIdentifier.id };
2949
+ }
2950
+ /**
2951
+ * Adds one or more items to the batch.
2952
+ *
2953
+ * Items without a reference ID will have UUIDs generated automatically.
2954
+ * This method can be called multiple times to build up the batch incrementally.
2955
+ *
2956
+ * @param item - Single item or array of items to add to the batch.
2957
+ *
2958
+ * @example
2959
+ * ```typescript
2960
+ * // Add single item
2961
+ * batch.add({
2962
+ * referenceId: 'my-custom-id',
2963
+ * variables: { query: 'Hello' }
2964
+ * })
2965
+ *
2966
+ * // Add multiple items
2967
+ * batch.add([
2968
+ * { variables: { query: 'First' } },
2969
+ * { variables: { query: 'Second' } },
2970
+ * { variables: { query: 'Third' } }
2971
+ * ])
2972
+ *
2973
+ * console.log(`Batch has ${batch.items.length} items`)
2974
+ * ```
2975
+ */
2976
+ add(item) {
2977
+ const items = Array.isArray(item) ? item : [item];
2978
+ for (const item2 of items) {
2979
+ this._items.push({
2980
+ ...item2,
2981
+ referenceId: item2.referenceId ?? crypto.randomUUID()
2982
+ });
2983
+ }
2984
+ }
2985
+ /**
2986
+ * Executes the batch by uploading the input file and creating a batch execution on the server.
2987
+ *
2988
+ * Returns a promise-like object that allows flexible usage patterns:
2989
+ * - Await for execution object: `const exec = await batch.execute()`
2990
+ * - Direct result access: `const result = await batch.execute().result`
2991
+ *
2992
+ * The batch items are serialized to JSONL format, uploaded to vault storage,
2993
+ * and submitted to the batch API for processing.
2994
+ *
2995
+ * @returns A promise-like object with a `result` property for direct result access.
2996
+ *
2997
+ * @example
2998
+ * ```typescript
2999
+ * // Direct result access (recommended for simple cases)
3000
+ * const result = await batch.execute().result
3001
+ * const outputs = await result.getResults()
3002
+ *
3003
+ * // Get execution object for event monitoring
3004
+ * const execution = await batch.execute()
3005
+ *
3006
+ * execution.on('statusChange', ([status, response]) => {
3007
+ * console.log(`Status: ${status}`)
3008
+ * if (response.state) {
3009
+ * console.log(`Progress: ${response.state.completed}/${response.state.total}`)
3010
+ * }
3011
+ * })
3012
+ *
3013
+ * execution.on('success', (result) => {
3014
+ * console.log('Batch completed!', result.requestId)
3015
+ * })
3016
+ *
3017
+ * const result = await execution.result
3018
+ *
3019
+ * // Iterate through results
3020
+ * for await (const output of result.iterateResults()) {
3021
+ * console.log(output)
3022
+ * }
3023
+ * ```
3024
+ */
3025
+ execute() {
3026
+ const jsonLines = this._items.map((item) => ({
3027
+ ...this.canvasIdentifier,
3028
+ ...item
3029
+ })).map((item) => transformObjectFromCamelCaseToSnakeCase(item)).map((item) => JSON.stringify(item));
3030
+ const fileContent = new Blob([jsonLines.join("\n")], { type: "application/jsonl" });
3031
+ const file = TelaFile.create(fileContent);
3032
+ const client = this._client;
3033
+ const params = this._params;
3034
+ async function execute() {
3035
+ const { fileUrl } = await uploadFile(file, client);
3036
+ const body = {
3037
+ task: "async-completion",
3038
+ inputFile: fileUrl,
3039
+ webhookUrl: params.webhookUrl
3040
+ };
3041
+ return client.post("/_services/batch/batches", {
3042
+ body
3043
+ }).then((response) => new BatchExecution(response.id, client, params, response));
3044
+ }
3045
+ return {
3046
+ then(onfulfilled, onrejected) {
3047
+ return Promise.resolve(execute()).then((execution) => onfulfilled?.(execution) ?? execution).catch(onrejected);
3048
+ },
3049
+ get result() {
3050
+ return Promise.resolve(execute()).then((execution) => execution.result);
3051
+ }
3052
+ };
3053
+ }
3054
+ }
3055
+
2245
3056
  var __defProp$1 = Object.defineProperty;
2246
3057
  var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2247
3058
  var __publicField$1 = (obj, key, value) => {
@@ -2524,6 +3335,38 @@ class Canvas {
2524
3335
  }
2525
3336
  );
2526
3337
  }
3338
+ /**
3339
+ * Prepares to execute this canvas in batch.
3340
+ *
3341
+ * @param params - The parameters for the batch.
3342
+ * @param params.pollingInterval - The interval between polling attempts.
3343
+ * @param params.pollingTimeout - The timeout for the batch.
3344
+ * @param params.webhookUrl - The webhook URL for the batch.
3345
+ *
3346
+ * @example
3347
+ * ```typescript
3348
+ * const batch = canvas.createBatch({
3349
+ * pollingInterval: '1s',
3350
+ * pollingTimeout: '1m',
3351
+ * webhookUrl: 'https://example.com/webhook',
3352
+ * })
3353
+ *
3354
+ * batch.add({
3355
+ * referenceId: crypto.randomUUID(), // Optional
3356
+ * variables: { query: 'Hello' },
3357
+ * })
3358
+ *
3359
+ * const execution = await batch.execute()
3360
+ * const result = await execution.result
3361
+ * const resultFile = await execution.downloadOutputFile()
3362
+ * ```
3363
+ *
3364
+ * @returns The batch instance that can be used to manage the batch.
3365
+ */
3366
+ createBatch(params = {}) {
3367
+ const canvasIdentifier = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, id: this._id };
3368
+ return new Batch(this._client, canvasIdentifier, params);
3369
+ }
2527
3370
  }
2528
3371
 
2529
3372
  var __defProp = Object.defineProperty;
@@ -2651,4 +3494,4 @@ function createTelaClient(opts) {
2651
3494
  return new TelaSDK(opts);
2652
3495
  }
2653
3496
 
2654
- export { APIError, AuthenticationError, AuthorizationError, BadRequestError, BaseClient, ConflictApiKeyAndJWTError, ConflictError, ConnectionError, ConnectionTimeout, EmptyFileError, ExecutionFailedError, ExecutionNotStartedError, FileUploadError, InternalServerError, InvalidExecutionModeError, InvalidFileURL, MissingApiKeyOrJWTError, NotFoundError, RateLimitError, TelaError, TelaFile, TelaFileSchema, TelaSDK, UnprocessableEntityError, UserAbortError, createTelaClient, toError };
3497
+ export { APIError, AuthenticationError, AuthorizationError, BadRequestError, BaseClient, BatchExecutionFailedError, ConflictApiKeyAndJWTError, ConflictError, ConnectionError, ConnectionTimeout, EmptyFileError, ExecutionFailedError, ExecutionNotStartedError, FileUploadError, InternalServerError, InvalidExecutionModeError, InvalidFileURL, MissingApiKeyOrJWTError, NotFoundError, RateLimitError, TelaError, TelaFile, TelaFileSchema, TelaSDK, UnprocessableEntityError, UserAbortError, createTelaClient, toError };