@meistrari/tela-sdk-js 2.4.2 → 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.cjs CHANGED
@@ -24,12 +24,12 @@ const z__default = /*#__PURE__*/_interopDefaultCompat(z);
24
24
  const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
25
25
  const Emittery__default = /*#__PURE__*/_interopDefaultCompat(Emittery);
26
26
 
27
- const version = "2.4.2";
27
+ const version = "2.5.0";
28
28
 
29
- var __defProp$7 = Object.defineProperty;
30
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
31
- var __publicField$7 = (obj, key, value) => {
32
- __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
29
+ var __defProp$8 = Object.defineProperty;
30
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
31
+ var __publicField$8 = (obj, key, value) => {
32
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
33
33
  return value;
34
34
  };
35
35
  class TelaError extends Error {
@@ -57,7 +57,7 @@ class InvalidFileURL extends TelaError {
57
57
  class FileUploadError extends TelaError {
58
58
  constructor(message, statusCode) {
59
59
  super(`Failed to upload file: ${message} (Status code: ${statusCode})`);
60
- __publicField$7(this, "statusCode");
60
+ __publicField$8(this, "statusCode");
61
61
  this.statusCode = statusCode;
62
62
  }
63
63
  }
@@ -74,16 +74,23 @@ class InvalidExecutionModeError extends TelaError {
74
74
  class ExecutionFailedError extends TelaError {
75
75
  constructor(rawOutput) {
76
76
  super(`Execution failed: ${JSON.stringify(rawOutput)}`);
77
- __publicField$7(this, "rawOutput");
77
+ __publicField$8(this, "rawOutput");
78
78
  this.rawOutput = rawOutput;
79
79
  }
80
80
  }
81
+ class BatchExecutionFailedError extends TelaError {
82
+ constructor(rawResponse) {
83
+ super(`Batch execution failed: ${JSON.stringify(rawResponse)}`);
84
+ __publicField$8(this, "rawResponse");
85
+ this.rawResponse = rawResponse;
86
+ }
87
+ }
81
88
  class APIError extends TelaError {
82
89
  constructor(statusCode, error, _message) {
83
90
  const message = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : _message;
84
91
  super(message);
85
- __publicField$7(this, "statusCode");
86
- __publicField$7(this, "error");
92
+ __publicField$8(this, "statusCode");
93
+ __publicField$8(this, "error");
87
94
  this.statusCode = statusCode;
88
95
  this.error = error;
89
96
  }
@@ -125,7 +132,7 @@ class APIError extends TelaError {
125
132
  class UserAbortError extends APIError {
126
133
  constructor({ message } = {}) {
127
134
  super(void 0, void 0, message || "User aborted.");
128
- __publicField$7(this, "statusCode");
135
+ __publicField$8(this, "statusCode");
129
136
  }
130
137
  }
131
138
  class ConnectionError extends APIError {
@@ -134,7 +141,7 @@ class ConnectionError extends APIError {
134
141
  cause
135
142
  }) {
136
143
  super(void 0, void 0, message || "Connection error.");
137
- __publicField$7(this, "statusCode");
144
+ __publicField$8(this, "statusCode");
138
145
  if (cause)
139
146
  this.cause = cause;
140
147
  }
@@ -144,57 +151,57 @@ class ConnectionTimeout extends APIError {
144
151
  message
145
152
  } = {}) {
146
153
  super(void 0, void 0, message || "Request timed out.");
147
- __publicField$7(this, "statusCode");
154
+ __publicField$8(this, "statusCode");
148
155
  }
149
156
  }
150
157
  class BadRequestError extends APIError {
151
158
  constructor() {
152
159
  super(...arguments);
153
- __publicField$7(this, "statusCode", 400);
160
+ __publicField$8(this, "statusCode", 400);
154
161
  }
155
162
  // todo: handle validation errors from zod/typebox
156
163
  }
157
164
  class AuthenticationError extends APIError {
158
165
  constructor() {
159
166
  super(...arguments);
160
- __publicField$7(this, "statusCode", 401);
167
+ __publicField$8(this, "statusCode", 401);
161
168
  }
162
169
  }
163
170
  class AuthorizationError extends APIError {
164
171
  constructor() {
165
172
  super(...arguments);
166
- __publicField$7(this, "statusCode", 403);
173
+ __publicField$8(this, "statusCode", 403);
167
174
  }
168
175
  }
169
176
  class NotFoundError extends APIError {
170
177
  constructor() {
171
178
  super(...arguments);
172
- __publicField$7(this, "statusCode", 404);
179
+ __publicField$8(this, "statusCode", 404);
173
180
  }
174
181
  }
175
182
  class ConflictError extends APIError {
176
183
  constructor() {
177
184
  super(...arguments);
178
- __publicField$7(this, "statusCode", 409);
185
+ __publicField$8(this, "statusCode", 409);
179
186
  }
180
187
  }
181
188
  class UnprocessableEntityError extends APIError {
182
189
  constructor() {
183
190
  super(...arguments);
184
191
  // todo: check if tela returns 400 or 422 for zod errors
185
- __publicField$7(this, "statusCode", 422);
192
+ __publicField$8(this, "statusCode", 422);
186
193
  }
187
194
  }
188
195
  class RateLimitError extends APIError {
189
196
  constructor() {
190
197
  super(...arguments);
191
- __publicField$7(this, "statusCode", 429);
198
+ __publicField$8(this, "statusCode", 429);
192
199
  }
193
200
  }
194
201
  class InternalServerError extends APIError {
195
202
  constructor() {
196
203
  super(...arguments);
197
- __publicField$7(this, "statusCode", 500);
204
+ __publicField$8(this, "statusCode", 500);
198
205
  }
199
206
  }
200
207
  function toError(err) {
@@ -305,11 +312,38 @@ function transformObjectFromSnakeCaseToCamelCase(obj, exclusions = []) {
305
312
  }
306
313
  return result;
307
314
  }
315
+ const DURATION_REGEX = /(?<amount>\d+)(?<unit>[smhd])/;
316
+ const DURATION_UNITS = {
317
+ s: 1e3,
318
+ // 1 second in milliseconds
319
+ m: 6e4,
320
+ // 1 minute in milliseconds
321
+ h: 36e5,
322
+ // 1 hour in milliseconds
323
+ d: 864e5
324
+ // 1 day in milliseconds
325
+ };
326
+ function transformDurationToMs(durationStr) {
327
+ if (!durationStr) {
328
+ return void 0;
329
+ }
330
+ if (typeof durationStr === "number") {
331
+ return durationStr;
332
+ }
333
+ const match = durationStr.match(DURATION_REGEX);
334
+ const amount = match?.groups?.amount;
335
+ const unit = match?.groups?.unit;
336
+ const multiplier = DURATION_UNITS[unit];
337
+ if (!amount || Number.isNaN(Number.parseInt(amount)) || !multiplier) {
338
+ return void 0;
339
+ }
340
+ return Number.parseInt(amount) * multiplier;
341
+ }
308
342
 
309
- var __defProp$6 = Object.defineProperty;
310
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
311
- var __publicField$6 = (obj, key, value) => {
312
- __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
343
+ var __defProp$7 = Object.defineProperty;
344
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
345
+ var __publicField$7 = (obj, key, value) => {
346
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
313
347
  return value;
314
348
  };
315
349
  class Stream {
@@ -573,9 +607,9 @@ function findDoubleNewlineIndex(buffer) {
573
607
  }
574
608
  class SSEDecoder {
575
609
  constructor() {
576
- __publicField$6(this, "data");
577
- __publicField$6(this, "event");
578
- __publicField$6(this, "chunks");
610
+ __publicField$7(this, "data");
611
+ __publicField$7(this, "event");
612
+ __publicField$7(this, "chunks");
579
613
  this.event = null;
580
614
  this.data = [];
581
615
  this.chunks = [];
@@ -616,9 +650,9 @@ class SSEDecoder {
616
650
  const _LineDecoder = class _LineDecoder {
617
651
  // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
618
652
  constructor() {
619
- __publicField$6(this, "buffer");
620
- __publicField$6(this, "trailingCR");
621
- __publicField$6(this, "textDecoder");
653
+ __publicField$7(this, "buffer");
654
+ __publicField$7(this, "trailingCR");
655
+ __publicField$7(this, "textDecoder");
622
656
  this.buffer = [];
623
657
  this.trailingCR = false;
624
658
  }
@@ -693,8 +727,8 @@ const _LineDecoder = class _LineDecoder {
693
727
  }
694
728
  };
695
729
  // prettier-ignore
696
- __publicField$6(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
697
- __publicField$6(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
730
+ __publicField$7(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
731
+ __publicField$7(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
698
732
  let LineDecoder = _LineDecoder;
699
733
  function partition(str, delimiter) {
700
734
  const index = str.indexOf(delimiter);
@@ -731,10 +765,10 @@ function readableStreamAsyncIterable(stream) {
731
765
  };
732
766
  }
733
767
 
734
- var __defProp$5 = Object.defineProperty;
735
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
736
- var __publicField$5 = (obj, key, value) => {
737
- __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
768
+ var __defProp$6 = Object.defineProperty;
769
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
770
+ var __publicField$6 = (obj, key, value) => {
771
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
738
772
  return value;
739
773
  };
740
774
  function getRequestIdFromResponse(response) {
@@ -776,6 +810,7 @@ function getRequestIdFromResponse(response) {
776
810
  }
777
811
  async function defaultParseResponse(props) {
778
812
  const { response } = props;
813
+ const { transformCase = true } = props.options;
779
814
  if (props.options.stream) {
780
815
  debug("response", response.status, response.url, response.headers, response.body);
781
816
  return Stream.fromSSEResponse(response, props.controller);
@@ -793,18 +828,27 @@ async function defaultParseResponse(props) {
793
828
  if (requestId) {
794
829
  finalJson.requestId = requestId;
795
830
  }
796
- return transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
831
+ return transformCase ? transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : finalJson;
797
832
  }
798
833
  const text = await response.text();
799
834
  debug("response", response.status, response.url, response.headers, text);
800
835
  return text;
801
836
  }
837
+ function transformBody(body, transformCase) {
838
+ if (!body) {
839
+ return void 0;
840
+ }
841
+ if (transformCase) {
842
+ return transformObjectFromCamelCaseToSnakeCase(body, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
843
+ }
844
+ return body;
845
+ }
802
846
  class BaseClient {
803
847
  constructor({ baseURL, maxRetries = 5, timeout = 0 }) {
804
- __publicField$5(this, "baseURL");
805
- __publicField$5(this, "maxRetries");
806
- __publicField$5(this, "timeout");
807
- __publicField$5(this, "fetch");
848
+ __publicField$6(this, "baseURL");
849
+ __publicField$6(this, "maxRetries");
850
+ __publicField$6(this, "timeout");
851
+ __publicField$6(this, "fetch");
808
852
  this.baseURL = baseURL;
809
853
  this.maxRetries = validateMaxRetries(maxRetries);
810
854
  this.timeout = validateTimeout(timeout);
@@ -843,10 +887,11 @@ class BaseClient {
843
887
  return this.methodRequest("DELETE", path, opts);
844
888
  }
845
889
  async methodRequest(method, path, opts) {
890
+ const { transformCase = true } = opts ?? {};
846
891
  const headers = this.createHeaders();
847
892
  debug("methodRequest", method, path, opts);
848
893
  const transformedQuery = opts?.query ? transformObjectFromCamelCaseToSnakeCase(opts.query, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : void 0;
849
- const transformedBody = opts?.body ? transformObjectFromCamelCaseToSnakeCase(opts.body, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : void 0;
894
+ const transformedBody = transformBody(opts?.body, transformCase);
850
895
  const { response, options, controller } = await this.request({
851
896
  method,
852
897
  path,
@@ -1080,10 +1125,10 @@ async function getStreamSize(stream) {
1080
1125
  return size;
1081
1126
  }
1082
1127
 
1083
- var __defProp$4 = Object.defineProperty;
1084
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1085
- var __publicField$4 = (obj, key, value) => {
1086
- __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1128
+ var __defProp$5 = Object.defineProperty;
1129
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1130
+ var __publicField$5 = (obj, key, value) => {
1131
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1087
1132
  return value;
1088
1133
  };
1089
1134
  function TelaFileSchema() {
@@ -1091,11 +1136,11 @@ function TelaFileSchema() {
1091
1136
  }
1092
1137
  class TelaFile {
1093
1138
  constructor(file, options = {}) {
1094
- __publicField$4(this, "_file");
1095
- __publicField$4(this, "_options");
1096
- __publicField$4(this, "_size", null);
1097
- __publicField$4(this, "_mimeType");
1098
- __publicField$4(this, "_name");
1139
+ __publicField$5(this, "_file");
1140
+ __publicField$5(this, "_options");
1141
+ __publicField$5(this, "_size", null);
1142
+ __publicField$5(this, "_mimeType");
1143
+ __publicField$5(this, "_name");
1099
1144
  this._file = file;
1100
1145
  if (file instanceof File || file instanceof Blob) {
1101
1146
  this._size = file.size;
@@ -1399,10 +1444,10 @@ function validateOutputSchema(clientSchema, serverSchema) {
1399
1444
  return compareSchemas(clientSchema, serverSchema);
1400
1445
  }
1401
1446
 
1402
- var __defProp$3 = Object.defineProperty;
1403
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1404
- var __publicField$3 = (obj, key, value) => {
1405
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1447
+ var __defProp$4 = Object.defineProperty;
1448
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1449
+ var __publicField$4 = (obj, key, value) => {
1450
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1406
1451
  return value;
1407
1452
  };
1408
1453
  function timeout(ms, signal) {
@@ -1418,10 +1463,10 @@ function timeout(ms, signal) {
1418
1463
  }
1419
1464
  class Poller {
1420
1465
  constructor({ interval, timeout: timeout2, abortSignal }) {
1421
- __publicField$3(this, "_interval");
1422
- __publicField$3(this, "_timeout");
1423
- __publicField$3(this, "_abortSignal");
1424
- __publicField$3(this, "_internalAbortController");
1466
+ __publicField$4(this, "_interval");
1467
+ __publicField$4(this, "_timeout");
1468
+ __publicField$4(this, "_abortSignal");
1469
+ __publicField$4(this, "_internalAbortController");
1425
1470
  if (interval <= 0) {
1426
1471
  throw new TelaError("Interval must be greater than 0");
1427
1472
  }
@@ -1467,7 +1512,7 @@ class Poller {
1467
1512
  const resultPromise = async () => {
1468
1513
  try {
1469
1514
  while (!this._abortSignal.aborted) {
1470
- const result = await callback(this._abortSignal);
1515
+ const result = await callback();
1471
1516
  if (result.done) {
1472
1517
  return result.value;
1473
1518
  }
@@ -1517,10 +1562,82 @@ async function calculateSha256sum(content) {
1517
1562
  }
1518
1563
  }
1519
1564
 
1520
- var __defProp$2 = Object.defineProperty;
1521
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1522
- var __publicField$2 = (obj, key, value) => {
1523
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1565
+ async function uploadFile(file, client) {
1566
+ let content = await file.getUploadableContent();
1567
+ let sha256sumStream;
1568
+ if (typeof content === "string") {
1569
+ return { fileUrl: content, options: file.options };
1570
+ }
1571
+ const filename = file.name ?? void 0;
1572
+ const fileType = file.type ?? void 0;
1573
+ const contentLength = file.size ?? void 0;
1574
+ if (content instanceof ReadableStream) {
1575
+ const [hashStream, contentStream] = content.tee();
1576
+ content = contentStream;
1577
+ sha256sumStream = hashStream;
1578
+ }
1579
+ const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
1580
+ const { id, uploadUrl } = await client.post("/_services/vault/files", {
1581
+ body: {
1582
+ fileName: filename,
1583
+ mimeType: fileType,
1584
+ size: contentLength ?? void 0,
1585
+ sha256sum
1586
+ },
1587
+ transformCase: false
1588
+ });
1589
+ if (content instanceof ReadableStream && typeof Bun !== "undefined") {
1590
+ console.warn(
1591
+ "[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
1592
+ { fileName: filename, fileSize: contentLength }
1593
+ );
1594
+ const chunks = [];
1595
+ const reader = content.getReader();
1596
+ while (true) {
1597
+ const { done, value } = await reader.read();
1598
+ if (done)
1599
+ break;
1600
+ chunks.push(value);
1601
+ }
1602
+ content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
1603
+ }
1604
+ const request = new Request(uploadUrl, {
1605
+ method: "PUT",
1606
+ body: content,
1607
+ headers: {
1608
+ "Content-Type": fileType ?? "application/octet-stream",
1609
+ ...file.size ? { "Content-Length": file.size.toString() } : {}
1610
+ }
1611
+ });
1612
+ const uploadResponse = await fetch(request);
1613
+ if (!uploadResponse.ok) {
1614
+ throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
1615
+ }
1616
+ return { fileUrl: `vault://${id}`, options: file.options };
1617
+ }
1618
+ async function downloadFile(vaultReference, client) {
1619
+ const vaultId = vaultReference.replace("vault://", "");
1620
+ const response = await client.get(`/_services/vault/files/${vaultId}`);
1621
+ return fetch(response.url).then((res) => res.blob());
1622
+ }
1623
+ async function streamFile(vaultReference, client) {
1624
+ const vaultId = vaultReference.replace("vault://", "");
1625
+ const response = await client.get(`/_services/vault/files/${vaultId}`);
1626
+ return fetch(response.url).then((res) => {
1627
+ if (!res.ok) {
1628
+ throw new Error("Failed to stream file", { cause: res.statusText });
1629
+ }
1630
+ if (!res.body) {
1631
+ throw new Error("Failed to stream file", { cause: "No body" });
1632
+ }
1633
+ return res.body;
1634
+ });
1635
+ }
1636
+
1637
+ var __defProp$3 = Object.defineProperty;
1638
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1639
+ var __publicField$3 = (obj, key, value) => {
1640
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1524
1641
  return value;
1525
1642
  };
1526
1643
  function isTelaFile(obj) {
@@ -1569,26 +1686,29 @@ class CanvasExecution extends Emittery__default {
1569
1686
  * @param outputSchema - Zod schema or object schema for validating/parsing output.
1570
1687
  * @param client - HTTP client instance for making API requests.
1571
1688
  */
1572
- constructor(variables, params = { async: false }, outputSchema, client) {
1689
+ constructor(variables, params = { async: false }, outputSchema, client, isTask = false) {
1573
1690
  super();
1574
- __publicField$2(this, "_id");
1575
- __publicField$2(this, "_status");
1576
- __publicField$2(this, "_variables");
1577
- __publicField$2(this, "_params");
1578
- __publicField$2(this, "_client");
1579
- __publicField$2(this, "_outputSchema");
1580
- __publicField$2(this, "_skipResultValidation");
1581
- __publicField$2(this, "_abortController");
1582
- __publicField$2(this, "_resultPromise");
1583
- __publicField$2(this, "_stream");
1584
- __publicField$2(this, "_rawResultValue");
1585
- __publicField$2(this, "_requestId");
1691
+ __publicField$3(this, "_id");
1692
+ __publicField$3(this, "_status");
1693
+ __publicField$3(this, "_variables");
1694
+ __publicField$3(this, "_params");
1695
+ __publicField$3(this, "_client");
1696
+ __publicField$3(this, "_outputSchema");
1697
+ __publicField$3(this, "_skipResultValidation");
1698
+ __publicField$3(this, "_abortController");
1699
+ __publicField$3(this, "_isTask");
1700
+ __publicField$3(this, "_resultPromise");
1701
+ __publicField$3(this, "_stream");
1702
+ __publicField$3(this, "_rawResultValue");
1703
+ __publicField$3(this, "_requestId");
1704
+ __publicField$3(this, "_task");
1586
1705
  this._variables = variables;
1587
1706
  this._params = params;
1588
1707
  this._outputSchema = outputSchema;
1589
1708
  this._skipResultValidation = params.skipResultValidation ?? false;
1590
1709
  this._client = client;
1591
1710
  this._abortController = new AbortController();
1711
+ this._isTask = isTask;
1592
1712
  }
1593
1713
  /**
1594
1714
  * Fetches an existing asynchronous execution by its ID.
@@ -1603,6 +1723,7 @@ class CanvasExecution extends Emittery__default {
1603
1723
  * @param options - Optional configuration for polling behavior.
1604
1724
  * @param options.pollingInterval - Time in milliseconds between polling attempts (default: 1000).
1605
1725
  * @param options.pollingTimeout - Maximum time in milliseconds to wait for completion (default: 60000).
1726
+ * @param options.isTask - Whether the execution is a task of a workstation.
1606
1727
  * @throws {InvalidExecutionModeError} If the provided ID is not a valid UUID.
1607
1728
  * @returns A promise resolving to a CanvasExecution instance with the fetched state.
1608
1729
  *
@@ -1636,7 +1757,8 @@ class CanvasExecution extends Emittery__default {
1636
1757
  // No variables needed for fetched execution
1637
1758
  params,
1638
1759
  outputSchema,
1639
- client
1760
+ client,
1761
+ options?.isTask
1640
1762
  );
1641
1763
  execution._id = response.id;
1642
1764
  execution.status = response.status;
@@ -1809,6 +1931,14 @@ class CanvasExecution extends Emittery__default {
1809
1931
  get isStream() {
1810
1932
  return Boolean(this._params.stream);
1811
1933
  }
1934
+ /**
1935
+ * Gets the task associated with this execution if it was created from an application.
1936
+ *
1937
+ * @returns The task creation result or undefined.
1938
+ */
1939
+ get task() {
1940
+ return this._task;
1941
+ }
1812
1942
  /**
1813
1943
  * Gets the raw API response without any processing or validation.
1814
1944
  * Automatically starts execution and waits for completion (including polling for async executions).
@@ -1852,7 +1982,6 @@ class CanvasExecution extends Emittery__default {
1852
1982
  async start() {
1853
1983
  if (this._params.applicationId && !this._params.async) {
1854
1984
  console.warn("[Tela SDK - WARNING] ApplicationId was provided, but async mode was not enabled. This will create a task, and tasks are always async. ");
1855
- console.warn("[Tela SDK - WARNING] Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.");
1856
1985
  console.warn("[Tela SDK - WARNING] To disable these warnings, you can enable async mode explicitly.");
1857
1986
  this._params.async = true;
1858
1987
  }
@@ -1874,10 +2003,6 @@ class CanvasExecution extends Emittery__default {
1874
2003
  * @returns The execution result as a promise or async generator.
1875
2004
  */
1876
2005
  get result() {
1877
- if (this._params.applicationId && !this._params.canvasId) {
1878
- const message = "Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.";
1879
- return Promise.reject(new InvalidExecutionModeError(message));
1880
- }
1881
2006
  if (this.isSync) {
1882
2007
  if (!this._resultPromise) {
1883
2008
  return Promise.reject(new ExecutionNotStartedError());
@@ -1952,9 +2077,6 @@ class CanvasExecution extends Emittery__default {
1952
2077
  * ```
1953
2078
  */
1954
2079
  poll() {
1955
- if (this._params.applicationId && !this._params.canvasId) {
1956
- throw new InvalidExecutionModeError("Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.");
1957
- }
1958
2080
  if (!this.isAsync) {
1959
2081
  throw new InvalidExecutionModeError("Polling is only supported for async executions");
1960
2082
  }
@@ -2084,13 +2206,16 @@ class CanvasExecution extends Emittery__default {
2084
2206
  async startAsync() {
2085
2207
  const resolvedVariables = await this.resolveVariables();
2086
2208
  return await this.create(resolvedVariables, { async: true }).then((response) => {
2087
- this._id = response.id;
2209
+ this._id = "completionRunId" in response ? response.completionRunId : response.id;
2088
2210
  this.status = response.status;
2211
+ if (this._isTask) {
2212
+ this._task = response;
2213
+ }
2089
2214
  this.emit("poll", {
2090
2215
  id: response.id,
2091
2216
  status: response.status,
2092
- outputContent: response.output_content,
2093
- rawOutput: response.raw_output,
2217
+ outputContent: response.outputContent,
2218
+ rawOutput: "rawOutput" in response ? response.rawOutput : void 0,
2094
2219
  requestId: response.requestId
2095
2220
  });
2096
2221
  return response;
@@ -2121,16 +2246,16 @@ class CanvasExecution extends Emittery__default {
2121
2246
  throw new InvalidExecutionModeError("Polling is only supported for async executions");
2122
2247
  }
2123
2248
  return new Poller({
2124
- interval: this._params.pollingInterval ?? 1e3,
2249
+ interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
2125
2250
  // 1 second
2126
- timeout: this._params.pollingTimeout ?? 6e4,
2251
+ timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
2127
2252
  // 1 minute
2128
2253
  abortSignal: this._abortController.signal
2129
- }).start(async (signal) => {
2254
+ }).start(async () => {
2130
2255
  const response = await this._client.get(
2131
2256
  `/v2/chat/completions/${this.id}`,
2132
2257
  {
2133
- signal
2258
+ signal: this._abortController.signal
2134
2259
  }
2135
2260
  );
2136
2261
  this.status = response.status;
@@ -2188,56 +2313,7 @@ class CanvasExecution extends Emittery__default {
2188
2313
  * ```
2189
2314
  */
2190
2315
  async uploadFile(file) {
2191
- let content = await file.getUploadableContent();
2192
- let sha256sumStream;
2193
- if (typeof content === "string") {
2194
- return { fileUrl: content, options: file.options };
2195
- }
2196
- const filename = file.name ?? void 0;
2197
- const fileType = file.type ?? void 0;
2198
- const contentLength = file.size ?? void 0;
2199
- if (content instanceof ReadableStream) {
2200
- const [hashStream, contentStream] = content.tee();
2201
- content = contentStream;
2202
- sha256sumStream = hashStream;
2203
- }
2204
- const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
2205
- const { id, uploadUrl } = await this._client.post("/_services/vault/files", {
2206
- body: {
2207
- fileName: filename,
2208
- mimeType: fileType,
2209
- size: contentLength ?? void 0,
2210
- sha256sum
2211
- }
2212
- });
2213
- if (content instanceof ReadableStream && typeof Bun !== "undefined") {
2214
- console.warn(
2215
- "[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
2216
- { fileName: filename, fileSize: contentLength }
2217
- );
2218
- const chunks = [];
2219
- const reader = content.getReader();
2220
- while (true) {
2221
- const { done, value } = await reader.read();
2222
- if (done)
2223
- break;
2224
- chunks.push(value);
2225
- }
2226
- content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
2227
- }
2228
- const request = new Request(uploadUrl, {
2229
- method: "PUT",
2230
- body: content,
2231
- headers: {
2232
- "Content-Type": fileType ?? "application/octet-stream",
2233
- ...file.size ? { "Content-Length": file.size.toString() } : {}
2234
- }
2235
- });
2236
- const uploadResponse = await fetch(request);
2237
- if (!uploadResponse.ok) {
2238
- throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
2239
- }
2240
- return { fileUrl: `vault://${id}`, options: file.options };
2316
+ return uploadFile(file, this._client);
2241
2317
  }
2242
2318
  /**
2243
2319
  * Uploads multiple files and returns their URLs and options.
@@ -2254,6 +2330,749 @@ class CanvasExecution extends Emittery__default {
2254
2330
  }
2255
2331
  }
2256
2332
 
2333
+ var __defProp$2 = Object.defineProperty;
2334
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2335
+ var __publicField$2 = (obj, key, value) => {
2336
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
2337
+ return value;
2338
+ };
2339
+ const BatchResultItem = z__default.looseObject({
2340
+ reference_id: z__default.string(),
2341
+ status: z__default.string(),
2342
+ execution_id: z__default.string(),
2343
+ result: z__default.object({
2344
+ id: z__default.string(),
2345
+ tags: z__default.array(z__default.string()),
2346
+ status: z__default.string(),
2347
+ metadata: z__default.object({
2348
+ promptVersion: z__default.object({
2349
+ modelConfigurations: z__default.object({
2350
+ type: z__default.string(),
2351
+ model: z__default.string(),
2352
+ temperature: z__default.number(),
2353
+ structuredOutput: z__default.object({
2354
+ schema: z__default.looseObject({}).optional(),
2355
+ enabled: z__default.boolean()
2356
+ })
2357
+ }),
2358
+ variablesDefinitions: z__default.array(
2359
+ z__default.object({
2360
+ name: z__default.string(),
2361
+ type: z__default.string(),
2362
+ required: z__default.boolean(),
2363
+ processingOptions: z__default.object({ allowMultimodal: z__default.boolean() })
2364
+ })
2365
+ )
2366
+ })
2367
+ }),
2368
+ promptId: z__default.string(),
2369
+ rawInput: z__default.object({
2370
+ tags: z__default.array(z__default.string()),
2371
+ async: z__default.boolean(),
2372
+ canvas_id: z__default.string(),
2373
+ variables: z__default.looseObject({})
2374
+ }),
2375
+ createdAt: z__default.string(),
2376
+ deletedAt: z__default.null(),
2377
+ rawOutput: z__default.object({
2378
+ id: z__default.string(),
2379
+ usage: z__default.object({
2380
+ cost: z__default.object({
2381
+ total_cost: z__default.number(),
2382
+ prompt_cost: z__default.number(),
2383
+ completion_cost: z__default.number()
2384
+ }),
2385
+ total_tokens: z__default.number(),
2386
+ prompt_tokens: z__default.number(),
2387
+ completion_tokens: z__default.number()
2388
+ }),
2389
+ object: z__default.string(),
2390
+ choices: z__default.array(
2391
+ z__default.object({
2392
+ message: z__default.object({
2393
+ role: z__default.string(),
2394
+ content: z__default.looseObject({}),
2395
+ tool_calls: z__default.array(z__default.object({ type: z__default.string(), function: z__default.object({ name: z__default.string(), arguments: z__default.looseObject({}) }) })),
2396
+ function_call: z__default.null()
2397
+ })
2398
+ })
2399
+ ),
2400
+ created: z__default.number()
2401
+ }),
2402
+ updatedAt: z__default.string(),
2403
+ creditsUsed: z__default.number(),
2404
+ workspaceId: z__default.string(),
2405
+ inputContent: z__default.object({
2406
+ files: z__default.array(z__default.object({ file_url: z__default.string() })),
2407
+ messages: z__default.array(z__default.object({ role: z__default.string(), content: z__default.looseObject({}) })),
2408
+ variables: z__default.looseObject({})
2409
+ }),
2410
+ outputContent: z__default.object({
2411
+ role: z__default.string(),
2412
+ content: z__default.looseObject({}),
2413
+ tool_calls: z__default.array(z__default.looseObject({})),
2414
+ function_call: z__default.string().nullable()
2415
+ }),
2416
+ promptVersionId: z__default.string(),
2417
+ compatibilityDate: z__default.string(),
2418
+ promptApplicationId: z__default.string().nullable()
2419
+ }),
2420
+ error: z__default.null()
2421
+ });
2422
+ class BatchExecutionResult {
2423
+ /**
2424
+ * Creates a new batch execution result wrapper.
2425
+ *
2426
+ * @param client - HTTP client for making API requests.
2427
+ * @param response - Raw batch execution response from the server.
2428
+ * @internal
2429
+ */
2430
+ constructor(client, response) {
2431
+ __publicField$2(this, "_client");
2432
+ __publicField$2(this, "_response");
2433
+ this._client = client;
2434
+ this._response = response;
2435
+ }
2436
+ get requestId() {
2437
+ return this._response.requestId;
2438
+ }
2439
+ /**
2440
+ * Gets the unique identifier for this batch execution.
2441
+ *
2442
+ * @returns The batch execution ID.
2443
+ */
2444
+ get id() {
2445
+ return this._response.id;
2446
+ }
2447
+ /**
2448
+ * Gets the current status of the batch execution.
2449
+ *
2450
+ * @returns The batch status.
2451
+ */
2452
+ get status() {
2453
+ return this._response.status;
2454
+ }
2455
+ /**
2456
+ * Gets the progress statistics for this batch.
2457
+ *
2458
+ * @returns Object containing completed, failed, and total execution counts, or null if not available.
2459
+ */
2460
+ get state() {
2461
+ return this._response.state;
2462
+ }
2463
+ /**
2464
+ * Gets the vault URL of the output JSONL file containing all results.
2465
+ *
2466
+ * @returns The output file URL, or null if batch is not completed.
2467
+ */
2468
+ get outputFile() {
2469
+ return this._response.outputFile;
2470
+ }
2471
+ /**
2472
+ * Gets the raw API response without any processing.
2473
+ *
2474
+ * @returns The complete batch response object.
2475
+ */
2476
+ get rawResponse() {
2477
+ return this._response;
2478
+ }
2479
+ /**
2480
+ * Gets the timestamp when this batch was created.
2481
+ *
2482
+ * @returns Creation date.
2483
+ */
2484
+ get createdAt() {
2485
+ return new Date(this._response.createdAt);
2486
+ }
2487
+ /**
2488
+ * Gets the timestamp when this batch was last updated.
2489
+ *
2490
+ * @returns Last update date.
2491
+ */
2492
+ get updatedAt() {
2493
+ return new Date(this._response.updatedAt);
2494
+ }
2495
+ /**
2496
+ * Gets the timestamp when this batch completed successfully.
2497
+ *
2498
+ * @returns Completion date, or null if not completed.
2499
+ */
2500
+ get completedAt() {
2501
+ return this._response.completedAt ? new Date(this._response.completedAt) : null;
2502
+ }
2503
+ /**
2504
+ * Gets the timestamp when this batch was canceled.
2505
+ *
2506
+ * @returns Cancellation date, or null if not canceled.
2507
+ */
2508
+ get canceledAt() {
2509
+ return this._response.canceledAt ? new Date(this._response.canceledAt) : null;
2510
+ }
2511
+ /**
2512
+ * Gets the timestamp when this batch failed.
2513
+ *
2514
+ * @returns Failure date, or null if not failed.
2515
+ */
2516
+ get failedAt() {
2517
+ return this._response.failedAt ? new Date(this._response.failedAt) : null;
2518
+ }
2519
+ /**
2520
+ * Downloads the complete output file as a Blob.
2521
+ *
2522
+ * The output file is a JSONL (JSON Lines) file where each line contains
2523
+ * one execution result with its reference ID, status, and output.
2524
+ *
2525
+ * @throws {Error} If batch is not completed or output file is unavailable.
2526
+ * @returns A promise resolving to the output file as a Blob.
2527
+ *
2528
+ * @example
2529
+ * ```typescript
2530
+ * const file = await result.downloadOutputFile()
2531
+ * const text = await file.text()
2532
+ * console.log(text) // JSONL content
2533
+ * ```
2534
+ */
2535
+ downloadOutputFile() {
2536
+ this.validateOutputFile();
2537
+ return downloadFile(this._response.outputFile, this._client);
2538
+ }
2539
+ /**
2540
+ * Streams the output file as a ReadableStream for memory-efficient processing.
2541
+ *
2542
+ * Useful for large batches where loading the entire file into memory is not practical.
2543
+ *
2544
+ * @throws {Error} If batch is not completed or output file is unavailable.
2545
+ * @returns A promise resolving to a ReadableStream of the output file.
2546
+ *
2547
+ * @example
2548
+ * ```typescript
2549
+ * const stream = await result.streamOutputFile()
2550
+ * // Process stream with custom logic
2551
+ * ```
2552
+ */
2553
+ async streamOutputFile() {
2554
+ this.validateOutputFile();
2555
+ return streamFile(this._response.outputFile, this._client);
2556
+ }
2557
+ /**
2558
+ * Downloads and parses all results into an array.
2559
+ *
2560
+ * Loads the entire output file into memory, parses each line, and extracts
2561
+ * the output content. For large batches, consider using `iterateResults()` instead.
2562
+ *
2563
+ * @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
2564
+ * @returns A promise resolving to an array of all execution outputs.
2565
+ *
2566
+ * @example
2567
+ * ```typescript
2568
+ * const results = await result.getResults()
2569
+ * console.log(`Got ${results.length} results`)
2570
+ * results.forEach((output, i) => console.log(`Result ${i}:`, output))
2571
+ * ```
2572
+ */
2573
+ async getResults() {
2574
+ const resultFile = await this.downloadOutputFile();
2575
+ const results = await resultFile.text();
2576
+ return results.split("\n").filter((line) => line.trim().length > 0).map((result) => JSON.parse(result)).map((result) => {
2577
+ const parsedResult = BatchResultItem.safeParse(result);
2578
+ if (!parsedResult.success) {
2579
+ throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
2580
+ }
2581
+ return parsedResult.data.result.outputContent.content;
2582
+ });
2583
+ }
2584
+ /**
2585
+ * Asynchronously iterates over raw result items from the output file.
2586
+ *
2587
+ * Streams and parses the output file line-by-line, yielding raw JSON objects.
2588
+ * Each yielded object contains the full result structure including metadata.
2589
+ *
2590
+ * @param params - Iteration options.
2591
+ * @param params.abortController - Optional AbortController to cancel iteration.
2592
+ * @throws {Error} If batch is not completed or output file is unavailable.
2593
+ * @yields Raw result objects from the JSONL file.
2594
+ *
2595
+ * @example
2596
+ * ```typescript
2597
+ * for await (const rawResult of result.iterateRawResults()) {
2598
+ * console.log('Reference ID:', rawResult.reference_id)
2599
+ * console.log('Status:', rawResult.status)
2600
+ * console.log('Output:', rawResult.result.outputContent.content)
2601
+ * }
2602
+ * ```
2603
+ */
2604
+ async *iterateRawResults(params = {}) {
2605
+ const { abortController = new AbortController() } = params;
2606
+ const stream = await this.streamOutputFile();
2607
+ for await (const result of Stream.fromReadableStream(stream, abortController)) {
2608
+ yield result;
2609
+ }
2610
+ }
2611
+ /**
2612
+ * Asynchronously iterates over parsed output content from the batch results.
2613
+ *
2614
+ * Streams and parses the output file line-by-line, yielding only the output content
2615
+ * (not the full result metadata). Memory-efficient for large batches.
2616
+ *
2617
+ * @param params - Iteration options.
2618
+ * @param params.abortController - Optional AbortController to cancel iteration.
2619
+ * @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
2620
+ * @yields Parsed output content from each execution.
2621
+ *
2622
+ * @example
2623
+ * ```typescript
2624
+ * const controller = new AbortController()
2625
+ *
2626
+ * for await (const output of result.iterateResults({ abortController: controller })) {
2627
+ * console.log(output)
2628
+ * if (someCondition) {
2629
+ * controller.abort() // Stop iteration early
2630
+ * }
2631
+ * }
2632
+ * ```
2633
+ */
2634
+ async *iterateResults(params = {}) {
2635
+ for await (const result of this.iterateRawResults(params)) {
2636
+ const parsedResult = BatchResultItem.safeParse(result);
2637
+ if (!parsedResult.success) {
2638
+ throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
2639
+ }
2640
+ yield parsedResult.data.result.outputContent.content;
2641
+ }
2642
+ }
2643
+ /**
2644
+ * Fetches the raw result metadata for a specific execution by its reference ID.
2645
+ *
2646
+ * Queries the API for the execution result using the reference ID tag.
2647
+ * Returns the complete execution metadata including input, output, and usage statistics.
2648
+ *
2649
+ * @param referenceId - The reference ID of the execution to retrieve.
2650
+ * @throws {Error} If no result found with the given reference ID.
2651
+ * @returns A promise resolving to the raw execution result object.
2652
+ *
2653
+ * @example
2654
+ * ```typescript
2655
+ * const rawResult = await result.getRawResult('my-ref-id')
2656
+ * console.log('Credits used:', rawResult.creditsUsed)
2657
+ * console.log('Execution status:', rawResult.status)
2658
+ * ```
2659
+ */
2660
+ async getRawResult(referenceId) {
2661
+ const response = await this._client.get("/v1/completion-run/", {
2662
+ query: {
2663
+ tags: `reference_id:${referenceId}`
2664
+ }
2665
+ });
2666
+ const result = response.data[0];
2667
+ if (!result) {
2668
+ throw new Error("Result not found");
2669
+ }
2670
+ return result;
2671
+ }
2672
+ /**
2673
+ * Fetches the output content for a specific execution by its reference ID.
2674
+ *
2675
+ * Convenience method that retrieves the raw result and extracts just the output content.
2676
+ *
2677
+ * @param referenceId - The reference ID of the execution to retrieve.
2678
+ * @throws {Error} If no result found with the given reference ID.
2679
+ * @returns A promise resolving to the execution output content.
2680
+ *
2681
+ * @example
2682
+ * ```typescript
2683
+ * const output = await result.getResult('my-ref-id')
2684
+ * console.log('Output:', output)
2685
+ * ```
2686
+ */
2687
+ async getResult(referenceId) {
2688
+ const result = await this.getRawResult(referenceId);
2689
+ return result.outputContent.content;
2690
+ }
2691
+ /**
2692
+ * Validates that the output file is available for access.
2693
+ *
2694
+ * @throws {Error} If batch is not completed or output file is missing.
2695
+ * @private
2696
+ */
2697
+ validateOutputFile() {
2698
+ if (this._response.status !== "completed") {
2699
+ throw new Error("Batch execution is not completed");
2700
+ }
2701
+ if (!this._response.outputFile) {
2702
+ throw new Error("Output file not found");
2703
+ }
2704
+ }
2705
+ }
2706
+ class BatchExecution extends Emittery__default {
2707
+ /**
2708
+ * Creates a new batch execution instance.
2709
+ *
2710
+ * @param id - Unique identifier for this batch execution.
2711
+ * @param client - HTTP client for making API requests.
2712
+ * @param params - Batch execution parameters.
2713
+ * @param creationResponse - Initial response from batch creation.
2714
+ * @internal
2715
+ */
2716
+ constructor(id, client, params = {}, creationResponse) {
2717
+ super();
2718
+ __publicField$2(this, "_client");
2719
+ __publicField$2(this, "_id");
2720
+ __publicField$2(this, "_params");
2721
+ __publicField$2(this, "_abortController");
2722
+ __publicField$2(this, "_creationResponse");
2723
+ __publicField$2(this, "_status", "created");
2724
+ __publicField$2(this, "_resultPromise");
2725
+ this._id = id;
2726
+ this._client = client;
2727
+ this._params = params;
2728
+ this._abortController = new AbortController();
2729
+ this._creationResponse = creationResponse;
2730
+ }
2731
+ /**
2732
+ * Gets the latest known status of the batch execution.
2733
+ *
2734
+ * Status values and transitions:
2735
+ * - `created` → `validating` → `running` → `completed` or `failed`
2736
+ * - Can transition to `canceled` from any non-terminal state
2737
+ *
2738
+ * Use the `statusChange` event to track status transitions in real-time.
2739
+ *
2740
+ * @returns The current status of the batch execution.
2741
+ *
2742
+ * @example
2743
+ * ```typescript
2744
+ * const execution = await batch.execute()
2745
+ * console.log(execution.status) // 'created'
2746
+ *
2747
+ * execution.on('statusChange', ([status]) => {
2748
+ * console.log('New status:', status)
2749
+ * })
2750
+ *
2751
+ * await execution.result
2752
+ * console.log(execution.status) // 'completed' or 'failed'
2753
+ * ```
2754
+ */
2755
+ get status() {
2756
+ return this._status;
2757
+ }
2758
+ /**
2759
+ * Gets the unique identifier for this batch execution.
2760
+ *
2761
+ * @returns The batch execution ID.
2762
+ */
2763
+ get id() {
2764
+ return this._id;
2765
+ }
2766
+ /**
2767
+ * Gets the batch execution parameters.
2768
+ *
2769
+ * @returns The batch parameters.
2770
+ */
2771
+ get params() {
2772
+ return this._params;
2773
+ }
2774
+ /**
2775
+ * Cancels the batch execution.
2776
+ *
2777
+ * Sends a cancellation request to the server and aborts any ongoing polling.
2778
+ * The batch will stop processing, but already-completed executions remain available.
2779
+ *
2780
+ * @returns A promise that resolves when the cancellation request completes.
2781
+ *
2782
+ * @example
2783
+ * ```typescript
2784
+ * const execution = await batch.execute()
2785
+ * execution.poll()
2786
+ *
2787
+ * // Cancel after some condition
2788
+ * if (shouldCancel) {
2789
+ * await execution.cancel()
2790
+ * console.log(execution.status) // 'canceled'
2791
+ * }
2792
+ * ```
2793
+ */
2794
+ async cancel() {
2795
+ await this._client.put(`/_services/batch/batches/${this._id}/cancel`);
2796
+ this._status = "canceled";
2797
+ this._abortController.abort();
2798
+ }
2799
+ /**
2800
+ * Starts polling for the batch result without waiting for the promise to resolve.
2801
+ * This allows users to track batch progress via events rather than awaiting a promise.
2802
+ *
2803
+ * The following events will be emitted during polling:
2804
+ * - `statusChange`: Emitted when the batch status changes (e.g., 'created' → 'running' → 'completed')
2805
+ * - `poll`: Emitted on each polling attempt with the server response
2806
+ * - `success`: Emitted when the batch completes successfully with the final result
2807
+ * - `error`: Emitted if the batch fails
2808
+ *
2809
+ * **Important:** Events are only emitted while polling is active. You must call `poll()` or
2810
+ * await `execution.result` to start polling. Simply setting up event listeners without starting
2811
+ * polling will not trigger any events.
2812
+ *
2813
+ * @example
2814
+ * ```typescript
2815
+ * const execution = await batch.execute()
2816
+ *
2817
+ * // Set up event listeners
2818
+ * execution.on('statusChange', ([status, response]) => {
2819
+ * console.log(`Status: ${status}`)
2820
+ * if (response.state) {
2821
+ * const { completed, total } = response.state
2822
+ * console.log(`Progress: ${completed}/${total}`)
2823
+ * }
2824
+ * })
2825
+ *
2826
+ * execution.on('success', (result) => {
2827
+ * console.log('Batch completed!')
2828
+ * console.log('Request ID:', result.requestId)
2829
+ * })
2830
+ *
2831
+ * execution.on('error', (error) => {
2832
+ * console.error('Batch failed:', error)
2833
+ * })
2834
+ *
2835
+ * // Start polling without waiting
2836
+ * execution.poll()
2837
+ * ```
2838
+ */
2839
+ poll() {
2840
+ if (this._resultPromise) {
2841
+ return;
2842
+ }
2843
+ this._resultPromise = this.startPolling();
2844
+ this._resultPromise.catch(() => {
2845
+ });
2846
+ }
2847
+ /**
2848
+ * Sets the batch status and emits statusChange event if changed.
2849
+ *
2850
+ * @param status - The new status.
2851
+ * @param response - The response containing the status.
2852
+ * @private
2853
+ */
2854
+ setStatus(status, response) {
2855
+ const changed = this._status !== status;
2856
+ this._status = status;
2857
+ if (changed) {
2858
+ this.emit("statusChange", [status, response]);
2859
+ }
2860
+ }
2861
+ /**
2862
+ * Starts polling the server for batch completion.
2863
+ * Continues polling until the batch completes, fails, or times out.
2864
+ *
2865
+ * @throws {BatchExecutionFailedError} If the batch fails on the server.
2866
+ * @throws {Error} If the polling operation times out.
2867
+ * @returns A promise resolving to the final batch result.
2868
+ * @private
2869
+ */
2870
+ async startPolling() {
2871
+ this.emit("statusChange", [this._status, this._creationResponse]);
2872
+ return new Poller({
2873
+ interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
2874
+ // 1 second
2875
+ timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
2876
+ // 1 minute
2877
+ abortSignal: this._abortController.signal
2878
+ }).start(async () => {
2879
+ const response = await this._client.get(
2880
+ `/_services/batch/batches/${this._id}`,
2881
+ { signal: this._abortController.signal }
2882
+ );
2883
+ this.emit("poll", response);
2884
+ this.setStatus(response.status, response);
2885
+ if (response.status === "failed") {
2886
+ const error = new BatchExecutionFailedError(response);
2887
+ this._abortController.abort();
2888
+ this.emit("error", error);
2889
+ throw error;
2890
+ }
2891
+ if (response.status !== "completed") {
2892
+ return {
2893
+ done: false,
2894
+ value: void 0
2895
+ };
2896
+ }
2897
+ const result = new BatchExecutionResult(this._client, response);
2898
+ this.emit("success", result);
2899
+ return {
2900
+ done: true,
2901
+ value: result
2902
+ };
2903
+ });
2904
+ }
2905
+ /**
2906
+ * Gets the batch execution result. Automatically starts polling if not already started.
2907
+ *
2908
+ * @returns A promise resolving to the batch execution result.
2909
+ *
2910
+ * @example
2911
+ * ```typescript
2912
+ * const execution = await batch.execute()
2913
+ * const result = await execution.result
2914
+ *
2915
+ * // Access results
2916
+ * const outputs = await result.getResults()
2917
+ * console.log(`Got ${outputs.length} results`)
2918
+ * ```
2919
+ */
2920
+ get result() {
2921
+ if (!this._resultPromise) {
2922
+ this._resultPromise = this.startPolling();
2923
+ }
2924
+ return this._resultPromise;
2925
+ }
2926
+ }
2927
+ class Batch {
2928
+ /**
2929
+ * Creates a new batch builder.
2930
+ *
2931
+ * @param client - HTTP client for making API requests.
2932
+ * @param canvasIdentifier - Canvas identification (ID + version or application ID).
2933
+ * @param params - Optional batch execution parameters.
2934
+ * @internal
2935
+ */
2936
+ constructor(client, canvasIdentifier, params = {}) {
2937
+ __publicField$2(this, "_client");
2938
+ __publicField$2(this, "_canvasIdentifier");
2939
+ __publicField$2(this, "_items", []);
2940
+ __publicField$2(this, "_params");
2941
+ this._client = client;
2942
+ this._canvasIdentifier = canvasIdentifier;
2943
+ this._params = params;
2944
+ }
2945
+ /**
2946
+ * Gets the current list of items in this batch.
2947
+ *
2948
+ * @returns Array of batch items.
2949
+ */
2950
+ get items() {
2951
+ return this._items;
2952
+ }
2953
+ /**
2954
+ * Gets the batch execution parameters.
2955
+ *
2956
+ * @returns The batch parameters.
2957
+ */
2958
+ get params() {
2959
+ return this._params;
2960
+ }
2961
+ /**
2962
+ * Gets the canvas identifier in the format expected by the API.
2963
+ *
2964
+ * @returns Canvas identifier object.
2965
+ * @private
2966
+ */
2967
+ get canvasIdentifier() {
2968
+ return "applicationId" in this._canvasIdentifier ? { applicationId: this._canvasIdentifier.applicationId } : { versionId: this._canvasIdentifier.versionId, canvasID: this._canvasIdentifier.id };
2969
+ }
2970
+ /**
2971
+ * Adds one or more items to the batch.
2972
+ *
2973
+ * Items without a reference ID will have UUIDs generated automatically.
2974
+ * This method can be called multiple times to build up the batch incrementally.
2975
+ *
2976
+ * @param item - Single item or array of items to add to the batch.
2977
+ *
2978
+ * @example
2979
+ * ```typescript
2980
+ * // Add single item
2981
+ * batch.add({
2982
+ * referenceId: 'my-custom-id',
2983
+ * variables: { query: 'Hello' }
2984
+ * })
2985
+ *
2986
+ * // Add multiple items
2987
+ * batch.add([
2988
+ * { variables: { query: 'First' } },
2989
+ * { variables: { query: 'Second' } },
2990
+ * { variables: { query: 'Third' } }
2991
+ * ])
2992
+ *
2993
+ * console.log(`Batch has ${batch.items.length} items`)
2994
+ * ```
2995
+ */
2996
+ add(item) {
2997
+ const items = Array.isArray(item) ? item : [item];
2998
+ for (const item2 of items) {
2999
+ this._items.push({
3000
+ ...item2,
3001
+ referenceId: item2.referenceId ?? crypto.randomUUID()
3002
+ });
3003
+ }
3004
+ }
3005
+ /**
3006
+ * Executes the batch by uploading the input file and creating a batch execution on the server.
3007
+ *
3008
+ * Returns a promise-like object that allows flexible usage patterns:
3009
+ * - Await for execution object: `const exec = await batch.execute()`
3010
+ * - Direct result access: `const result = await batch.execute().result`
3011
+ *
3012
+ * The batch items are serialized to JSONL format, uploaded to vault storage,
3013
+ * and submitted to the batch API for processing.
3014
+ *
3015
+ * @returns A promise-like object with a `result` property for direct result access.
3016
+ *
3017
+ * @example
3018
+ * ```typescript
3019
+ * // Direct result access (recommended for simple cases)
3020
+ * const result = await batch.execute().result
3021
+ * const outputs = await result.getResults()
3022
+ *
3023
+ * // Get execution object for event monitoring
3024
+ * const execution = await batch.execute()
3025
+ *
3026
+ * execution.on('statusChange', ([status, response]) => {
3027
+ * console.log(`Status: ${status}`)
3028
+ * if (response.state) {
3029
+ * console.log(`Progress: ${response.state.completed}/${response.state.total}`)
3030
+ * }
3031
+ * })
3032
+ *
3033
+ * execution.on('success', (result) => {
3034
+ * console.log('Batch completed!', result.requestId)
3035
+ * })
3036
+ *
3037
+ * const result = await execution.result
3038
+ *
3039
+ * // Iterate through results
3040
+ * for await (const output of result.iterateResults()) {
3041
+ * console.log(output)
3042
+ * }
3043
+ * ```
3044
+ */
3045
+ execute() {
3046
+ const jsonLines = this._items.map((item) => ({
3047
+ ...this.canvasIdentifier,
3048
+ ...item
3049
+ })).map((item) => transformObjectFromCamelCaseToSnakeCase(item)).map((item) => JSON.stringify(item));
3050
+ const fileContent = new Blob([jsonLines.join("\n")], { type: "application/jsonl" });
3051
+ const file = TelaFile.create(fileContent);
3052
+ const client = this._client;
3053
+ const params = this._params;
3054
+ async function execute() {
3055
+ const { fileUrl } = await uploadFile(file, client);
3056
+ const body = {
3057
+ task: "async-completion",
3058
+ inputFile: fileUrl,
3059
+ webhookUrl: params.webhookUrl
3060
+ };
3061
+ return client.post("/_services/batch/batches", {
3062
+ body
3063
+ }).then((response) => new BatchExecution(response.id, client, params, response));
3064
+ }
3065
+ return {
3066
+ then(onfulfilled, onrejected) {
3067
+ return Promise.resolve(execute()).then((execution) => onfulfilled?.(execution) ?? execution).catch(onrejected);
3068
+ },
3069
+ get result() {
3070
+ return Promise.resolve(execute()).then((execution) => execution.result);
3071
+ }
3072
+ };
3073
+ }
3074
+ }
3075
+
2257
3076
  var __defProp$1 = Object.defineProperty;
2258
3077
  var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2259
3078
  var __publicField$1 = (obj, key, value) => {
@@ -2450,6 +3269,15 @@ class Canvas {
2450
3269
  get isWorkflow() {
2451
3270
  return this._isWorkflow;
2452
3271
  }
3272
+ /**
3273
+ * Gets whether this canvas is a workstation.
3274
+ * This is true if an application ID is provided.
3275
+ *
3276
+ * @returns True if the canvas is a workstation.
3277
+ */
3278
+ get isWorkstation() {
3279
+ return Boolean(this._applicationId);
3280
+ }
2453
3281
  /**
2454
3282
  * Validates and parses input variables using the canvas input schema.
2455
3283
  *
@@ -2477,7 +3305,7 @@ class Canvas {
2477
3305
  ...params ?? { async: false },
2478
3306
  ...idObject
2479
3307
  };
2480
- const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client);
3308
+ const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client, this.isWorkstation);
2481
3309
  return {
2482
3310
  then(onfulfilled, onrejected) {
2483
3311
  return Promise.resolve(execution.start()).then(() => onfulfilled?.(execution) ?? execution).catch(onrejected);
@@ -2521,9 +3349,44 @@ class Canvas {
2521
3349
  id,
2522
3350
  this._output,
2523
3351
  this._client,
2524
- options
3352
+ {
3353
+ ...options,
3354
+ isTask: this.isWorkstation
3355
+ }
2525
3356
  );
2526
3357
  }
3358
+ /**
3359
+ * Prepares to execute this canvas in batch.
3360
+ *
3361
+ * @param params - The parameters for the batch.
3362
+ * @param params.pollingInterval - The interval between polling attempts.
3363
+ * @param params.pollingTimeout - The timeout for the batch.
3364
+ * @param params.webhookUrl - The webhook URL for the batch.
3365
+ *
3366
+ * @example
3367
+ * ```typescript
3368
+ * const batch = canvas.createBatch({
3369
+ * pollingInterval: '1s',
3370
+ * pollingTimeout: '1m',
3371
+ * webhookUrl: 'https://example.com/webhook',
3372
+ * })
3373
+ *
3374
+ * batch.add({
3375
+ * referenceId: crypto.randomUUID(), // Optional
3376
+ * variables: { query: 'Hello' },
3377
+ * })
3378
+ *
3379
+ * const execution = await batch.execute()
3380
+ * const result = await execution.result
3381
+ * const resultFile = await execution.downloadOutputFile()
3382
+ * ```
3383
+ *
3384
+ * @returns The batch instance that can be used to manage the batch.
3385
+ */
3386
+ createBatch(params = {}) {
3387
+ const canvasIdentifier = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, id: this._id };
3388
+ return new Batch(this._client, canvasIdentifier, params);
3389
+ }
2527
3390
  }
2528
3391
 
2529
3392
  var __defProp = Object.defineProperty;
@@ -2656,6 +3519,7 @@ exports.AuthenticationError = AuthenticationError;
2656
3519
  exports.AuthorizationError = AuthorizationError;
2657
3520
  exports.BadRequestError = BadRequestError;
2658
3521
  exports.BaseClient = BaseClient;
3522
+ exports.BatchExecutionFailedError = BatchExecutionFailedError;
2659
3523
  exports.ConflictApiKeyAndJWTError = ConflictApiKeyAndJWTError;
2660
3524
  exports.ConflictError = ConflictError;
2661
3525
  exports.ConnectionError = ConnectionError;