@meistrari/tela-sdk-js 2.5.0 → 2.6.1

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
@@ -21,15 +21,14 @@ function _interopNamespaceCompat(e) {
21
21
 
22
22
  const changeCase__namespace = /*#__PURE__*/_interopNamespaceCompat(changeCase);
23
23
  const z__default = /*#__PURE__*/_interopDefaultCompat(z);
24
- const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
25
24
  const Emittery__default = /*#__PURE__*/_interopDefaultCompat(Emittery);
26
25
 
27
- const version = "2.5.0";
26
+ const version = "2.6.1";
28
27
 
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);
28
+ var __defProp$a = Object.defineProperty;
29
+ var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
30
+ var __publicField$a = (obj, key, value) => {
31
+ __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
33
32
  return value;
34
33
  };
35
34
  class TelaError extends Error {
@@ -57,7 +56,7 @@ class InvalidFileURL extends TelaError {
57
56
  class FileUploadError extends TelaError {
58
57
  constructor(message, statusCode) {
59
58
  super(`Failed to upload file: ${message} (Status code: ${statusCode})`);
60
- __publicField$8(this, "statusCode");
59
+ __publicField$a(this, "statusCode");
61
60
  this.statusCode = statusCode;
62
61
  }
63
62
  }
@@ -74,14 +73,21 @@ class InvalidExecutionModeError extends TelaError {
74
73
  class ExecutionFailedError extends TelaError {
75
74
  constructor(rawOutput) {
76
75
  super(`Execution failed: ${JSON.stringify(rawOutput)}`);
77
- __publicField$8(this, "rawOutput");
76
+ __publicField$a(this, "rawOutput");
78
77
  this.rawOutput = rawOutput;
79
78
  }
80
79
  }
80
+ class TaskFailedError extends TelaError {
81
+ constructor(rawTask, message, cause) {
82
+ super(`Task failed: ${JSON.stringify(rawTask)}`, { cause });
83
+ __publicField$a(this, "rawTask");
84
+ this.rawTask = rawTask;
85
+ }
86
+ }
81
87
  class BatchExecutionFailedError extends TelaError {
82
88
  constructor(rawResponse) {
83
89
  super(`Batch execution failed: ${JSON.stringify(rawResponse)}`);
84
- __publicField$8(this, "rawResponse");
90
+ __publicField$a(this, "rawResponse");
85
91
  this.rawResponse = rawResponse;
86
92
  }
87
93
  }
@@ -89,8 +95,8 @@ class APIError extends TelaError {
89
95
  constructor(statusCode, error, _message) {
90
96
  const message = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : _message;
91
97
  super(message);
92
- __publicField$8(this, "statusCode");
93
- __publicField$8(this, "error");
98
+ __publicField$a(this, "statusCode");
99
+ __publicField$a(this, "error");
94
100
  this.statusCode = statusCode;
95
101
  this.error = error;
96
102
  }
@@ -132,7 +138,7 @@ class APIError extends TelaError {
132
138
  class UserAbortError extends APIError {
133
139
  constructor({ message } = {}) {
134
140
  super(void 0, void 0, message || "User aborted.");
135
- __publicField$8(this, "statusCode");
141
+ __publicField$a(this, "statusCode");
136
142
  }
137
143
  }
138
144
  class ConnectionError extends APIError {
@@ -141,7 +147,7 @@ class ConnectionError extends APIError {
141
147
  cause
142
148
  }) {
143
149
  super(void 0, void 0, message || "Connection error.");
144
- __publicField$8(this, "statusCode");
150
+ __publicField$a(this, "statusCode");
145
151
  if (cause)
146
152
  this.cause = cause;
147
153
  }
@@ -151,57 +157,57 @@ class ConnectionTimeout extends APIError {
151
157
  message
152
158
  } = {}) {
153
159
  super(void 0, void 0, message || "Request timed out.");
154
- __publicField$8(this, "statusCode");
160
+ __publicField$a(this, "statusCode");
155
161
  }
156
162
  }
157
163
  class BadRequestError extends APIError {
158
164
  constructor() {
159
165
  super(...arguments);
160
- __publicField$8(this, "statusCode", 400);
166
+ __publicField$a(this, "statusCode", 400);
161
167
  }
162
168
  // todo: handle validation errors from zod/typebox
163
169
  }
164
170
  class AuthenticationError extends APIError {
165
171
  constructor() {
166
172
  super(...arguments);
167
- __publicField$8(this, "statusCode", 401);
173
+ __publicField$a(this, "statusCode", 401);
168
174
  }
169
175
  }
170
176
  class AuthorizationError extends APIError {
171
177
  constructor() {
172
178
  super(...arguments);
173
- __publicField$8(this, "statusCode", 403);
179
+ __publicField$a(this, "statusCode", 403);
174
180
  }
175
181
  }
176
182
  class NotFoundError extends APIError {
177
183
  constructor() {
178
184
  super(...arguments);
179
- __publicField$8(this, "statusCode", 404);
185
+ __publicField$a(this, "statusCode", 404);
180
186
  }
181
187
  }
182
188
  class ConflictError extends APIError {
183
189
  constructor() {
184
190
  super(...arguments);
185
- __publicField$8(this, "statusCode", 409);
191
+ __publicField$a(this, "statusCode", 409);
186
192
  }
187
193
  }
188
194
  class UnprocessableEntityError extends APIError {
189
195
  constructor() {
190
196
  super(...arguments);
191
197
  // todo: check if tela returns 400 or 422 for zod errors
192
- __publicField$8(this, "statusCode", 422);
198
+ __publicField$a(this, "statusCode", 422);
193
199
  }
194
200
  }
195
201
  class RateLimitError extends APIError {
196
202
  constructor() {
197
203
  super(...arguments);
198
- __publicField$8(this, "statusCode", 429);
204
+ __publicField$a(this, "statusCode", 429);
199
205
  }
200
206
  }
201
207
  class InternalServerError extends APIError {
202
208
  constructor() {
203
209
  super(...arguments);
204
- __publicField$8(this, "statusCode", 500);
210
+ __publicField$a(this, "statusCode", 500);
205
211
  }
206
212
  }
207
213
  function toError(err) {
@@ -340,10 +346,10 @@ function transformDurationToMs(durationStr) {
340
346
  return Number.parseInt(amount) * multiplier;
341
347
  }
342
348
 
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);
349
+ var __defProp$9 = Object.defineProperty;
350
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
351
+ var __publicField$9 = (obj, key, value) => {
352
+ __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
347
353
  return value;
348
354
  };
349
355
  class Stream {
@@ -607,9 +613,9 @@ function findDoubleNewlineIndex(buffer) {
607
613
  }
608
614
  class SSEDecoder {
609
615
  constructor() {
610
- __publicField$7(this, "data");
611
- __publicField$7(this, "event");
612
- __publicField$7(this, "chunks");
616
+ __publicField$9(this, "data");
617
+ __publicField$9(this, "event");
618
+ __publicField$9(this, "chunks");
613
619
  this.event = null;
614
620
  this.data = [];
615
621
  this.chunks = [];
@@ -650,9 +656,9 @@ class SSEDecoder {
650
656
  const _LineDecoder = class _LineDecoder {
651
657
  // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
652
658
  constructor() {
653
- __publicField$7(this, "buffer");
654
- __publicField$7(this, "trailingCR");
655
- __publicField$7(this, "textDecoder");
659
+ __publicField$9(this, "buffer");
660
+ __publicField$9(this, "trailingCR");
661
+ __publicField$9(this, "textDecoder");
656
662
  this.buffer = [];
657
663
  this.trailingCR = false;
658
664
  }
@@ -727,8 +733,8 @@ const _LineDecoder = class _LineDecoder {
727
733
  }
728
734
  };
729
735
  // prettier-ignore
730
- __publicField$7(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
731
- __publicField$7(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
736
+ __publicField$9(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
737
+ __publicField$9(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
732
738
  let LineDecoder = _LineDecoder;
733
739
  function partition(str, delimiter) {
734
740
  const index = str.indexOf(delimiter);
@@ -765,10 +771,10 @@ function readableStreamAsyncIterable(stream) {
765
771
  };
766
772
  }
767
773
 
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);
774
+ var __defProp$8 = Object.defineProperty;
775
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
776
+ var __publicField$8 = (obj, key, value) => {
777
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
772
778
  return value;
773
779
  };
774
780
  function getRequestIdFromResponse(response) {
@@ -824,31 +830,30 @@ async function defaultParseResponse(props) {
824
830
  const json = await response.json();
825
831
  debug("response", response.status, response.url, response.headers, json);
826
832
  const requestId = getRequestIdFromResponse(response);
827
- const finalJson = { ...json };
828
833
  if (requestId) {
829
- finalJson.requestId = requestId;
834
+ json.requestId = requestId;
830
835
  }
831
- return transformCase ? transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : finalJson;
836
+ return transformCase ? transformObjectFromSnakeCaseToCamelCase(json, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : json;
832
837
  }
833
838
  const text = await response.text();
834
839
  debug("response", response.status, response.url, response.headers, text);
835
840
  return text;
836
841
  }
837
- function transformBody(body, transformCase) {
838
- if (!body) {
839
- return void 0;
842
+ function transformObjectCase(obj, transformCase) {
843
+ if (!obj) {
844
+ return obj;
840
845
  }
841
846
  if (transformCase) {
842
- return transformObjectFromCamelCaseToSnakeCase(body, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
847
+ return transformObjectFromCamelCaseToSnakeCase(obj, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
843
848
  }
844
- return body;
849
+ return obj;
845
850
  }
846
851
  class BaseClient {
847
852
  constructor({ baseURL, maxRetries = 5, timeout = 0 }) {
848
- __publicField$6(this, "baseURL");
849
- __publicField$6(this, "maxRetries");
850
- __publicField$6(this, "timeout");
851
- __publicField$6(this, "fetch");
853
+ __publicField$8(this, "baseURL");
854
+ __publicField$8(this, "maxRetries");
855
+ __publicField$8(this, "timeout");
856
+ __publicField$8(this, "fetch");
852
857
  this.baseURL = baseURL;
853
858
  this.maxRetries = validateMaxRetries(maxRetries);
854
859
  this.timeout = validateTimeout(timeout);
@@ -890,8 +895,8 @@ class BaseClient {
890
895
  const { transformCase = true } = opts ?? {};
891
896
  const headers = this.createHeaders();
892
897
  debug("methodRequest", method, path, opts);
893
- const transformedQuery = opts?.query ? transformObjectFromCamelCaseToSnakeCase(opts.query, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : void 0;
894
- const transformedBody = transformBody(opts?.body, transformCase);
898
+ const transformedQuery = transformObjectCase(opts?.query, transformCase);
899
+ const transformedBody = transformObjectCase(opts?.body, transformCase);
895
900
  const { response, options, controller } = await this.request({
896
901
  method,
897
902
  path,
@@ -1072,6 +1077,9 @@ class BaseClient {
1072
1077
  if (value === null) {
1073
1078
  return `${encodeURIComponent(key)}=`;
1074
1079
  }
1080
+ if (Array.isArray(value)) {
1081
+ return value.map((item) => `${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`).join("&");
1082
+ }
1075
1083
  throw new TelaError(
1076
1084
  `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`
1077
1085
  );
@@ -1125,10 +1133,10 @@ async function getStreamSize(stream) {
1125
1133
  return size;
1126
1134
  }
1127
1135
 
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);
1136
+ var __defProp$7 = Object.defineProperty;
1137
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1138
+ var __publicField$7 = (obj, key, value) => {
1139
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
1132
1140
  return value;
1133
1141
  };
1134
1142
  function TelaFileSchema() {
@@ -1136,11 +1144,11 @@ function TelaFileSchema() {
1136
1144
  }
1137
1145
  class TelaFile {
1138
1146
  constructor(file, options = {}) {
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");
1147
+ __publicField$7(this, "_file");
1148
+ __publicField$7(this, "_options");
1149
+ __publicField$7(this, "_size", null);
1150
+ __publicField$7(this, "_mimeType");
1151
+ __publicField$7(this, "_name");
1144
1152
  this._file = file;
1145
1153
  if (file instanceof File || file instanceof Blob) {
1146
1154
  this._size = file.size;
@@ -1286,7 +1294,17 @@ class TelaFile {
1286
1294
  return url.startsWith("vault://");
1287
1295
  }
1288
1296
  }
1297
+ function isTelaFile(obj) {
1298
+ return obj instanceof TelaFile;
1299
+ }
1300
+ function isTelaFileArray(obj) {
1301
+ return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
1302
+ }
1289
1303
 
1304
+ const zod = {
1305
+ ...z.z,
1306
+ file: TelaFileSchema
1307
+ };
1290
1308
  function compareSchemas(clientSchema, serverSchema, path = "$") {
1291
1309
  const mismatches = [];
1292
1310
  if (clientSchema.type !== serverSchema.type) {
@@ -1443,87 +1461,54 @@ function validateInputSchema(clientSchema, serverVariables) {
1443
1461
  function validateOutputSchema(clientSchema, serverSchema) {
1444
1462
  return compareSchemas(clientSchema, serverSchema);
1445
1463
  }
1446
-
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);
1451
- return value;
1452
- };
1453
- function timeout(ms, signal) {
1454
- return new Promise((resolve, reject) => {
1455
- const timer = setTimeout(resolve, ms);
1456
- if (signal) {
1457
- signal.addEventListener("abort", () => {
1458
- clearTimeout(timer);
1459
- reject(signal.reason);
1460
- }, { once: true });
1461
- }
1462
- });
1463
- }
1464
- class Poller {
1465
- constructor({ interval, timeout: timeout2, abortSignal }) {
1466
- __publicField$4(this, "_interval");
1467
- __publicField$4(this, "_timeout");
1468
- __publicField$4(this, "_abortSignal");
1469
- __publicField$4(this, "_internalAbortController");
1470
- if (interval <= 0) {
1471
- throw new TelaError("Interval must be greater than 0");
1472
- }
1473
- if (timeout2 <= 0) {
1474
- throw new TelaError("Timeout must be greater than 0");
1464
+ function validateSchemas(resource, input, output, promptVersion) {
1465
+ const canvasIdentifier = `${promptVersion.title} (${promptVersion.promptId})`;
1466
+ if (input instanceof z.z.ZodType) {
1467
+ try {
1468
+ const inputSchema = z.z.toJSONSchema(input, { unrepresentable: "any" });
1469
+ const mismatches = validateInputSchema(inputSchema, promptVersion.variables);
1470
+ if (mismatches.length === 0) {
1471
+ return;
1472
+ }
1473
+ console.warn(
1474
+ `[Tela SDK - ${resource} Input Validation] Input schema mismatches for ${resource} "${canvasIdentifier}":`
1475
+ );
1476
+ for (const mismatch of mismatches) {
1477
+ console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
1478
+ }
1479
+ } catch (error) {
1480
+ console.warn(
1481
+ `[Tela SDK - ${resource} Input Validation] Failed to validate input schema for ${resource} "${canvasIdentifier}":`,
1482
+ error
1483
+ );
1475
1484
  }
1476
- this._interval = interval;
1477
- this._timeout = timeout2;
1478
- this._abortSignal = abortSignal ?? new AbortController().signal;
1479
- this._internalAbortController = new AbortController();
1480
- }
1481
- async startTimeout() {
1482
- await timeout(this._timeout, this._internalAbortController.signal);
1483
- throw new ConnectionTimeout({
1484
- message: `Reached timeout of ${this._timeout}ms when polling`
1485
- });
1486
1485
  }
1487
- /**
1488
- * Starts the polling operation, repeatedly calling the callback until completion.
1489
- * The callback is invoked at the configured interval and must return a PollerResult
1490
- * indicating whether polling should continue or if the final value is ready.
1491
- *
1492
- * @param callback - Function called on each polling iteration.
1493
- * @returns A promise resolving to the final result value.
1494
- * @throws {Error} If the polling operation times out.
1495
- * @throws {Error} If the operation is aborted via the AbortSignal.
1496
- * @throws Any error thrown by the callback function.
1497
- *
1498
- * @example
1499
- * ```typescript
1500
- * const result = await poller.start(async (signal) => {
1501
- * const response = await fetch('/api/status', { signal });
1502
- * const data = await response.json();
1503
- *
1504
- * if (data.status === 'completed') {
1505
- * return { done: true, value: data.result };
1506
- * }
1507
- * return { done: false };
1508
- * });
1509
- * ```
1510
- */
1511
- start(callback) {
1512
- const resultPromise = async () => {
1513
- try {
1514
- while (!this._abortSignal.aborted) {
1515
- const result = await callback();
1516
- if (result.done) {
1517
- return result.value;
1518
- }
1519
- await timeout(this._interval, this._abortSignal);
1520
- }
1521
- throw new UserAbortError({ message: "Polling aborted" });
1522
- } finally {
1523
- this._internalAbortController.abort();
1486
+ if (output instanceof z.z.ZodType) {
1487
+ try {
1488
+ const outputSchema = z.z.toJSONSchema(output);
1489
+ const serverOutput = promptVersion.configuration.structuredOutput;
1490
+ if (!serverOutput.enabled) {
1491
+ console.warn(
1492
+ `[Tela SDK - ${resource} Output Validation] Output schema provided for ${resource} "${canvasIdentifier}", but structured output is not enabled on the server. The schema may not be enforced.`
1493
+ );
1494
+ return;
1524
1495
  }
1525
- };
1526
- return Promise.race([this.startTimeout(), resultPromise()]);
1496
+ const mismatches = validateOutputSchema(outputSchema, serverOutput.schema);
1497
+ if (mismatches.length === 0) {
1498
+ return;
1499
+ }
1500
+ console.warn(
1501
+ `[Tela SDK - ${resource} Output Validation] Output schema mismatches for ${resource} "${canvasIdentifier}":`
1502
+ );
1503
+ for (const mismatch of mismatches) {
1504
+ console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
1505
+ }
1506
+ } catch (error) {
1507
+ console.warn(
1508
+ `[Tela SDK - ${resource} Output Validation] Failed to validate output schema for ${resource} "${canvasIdentifier}":`,
1509
+ error
1510
+ );
1511
+ }
1527
1512
  }
1528
1513
  }
1529
1514
 
@@ -1615,6 +1600,10 @@ async function uploadFile(file, client) {
1615
1600
  }
1616
1601
  return { fileUrl: `vault://${id}`, options: file.options };
1617
1602
  }
1603
+ async function uploadFiles(files, client) {
1604
+ const uploadPromises = files.map((file) => uploadFile(file, client));
1605
+ return Promise.all(uploadPromises);
1606
+ }
1618
1607
  async function downloadFile(vaultReference, client) {
1619
1608
  const vaultId = vaultReference.replace("vault://", "");
1620
1609
  const response = await client.get(`/_services/vault/files/${vaultId}`);
@@ -1634,18 +1623,95 @@ async function streamFile(vaultReference, client) {
1634
1623
  });
1635
1624
  }
1636
1625
 
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);
1626
+ var __defProp$6 = Object.defineProperty;
1627
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1628
+ var __publicField$6 = (obj, key, value) => {
1629
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
1641
1630
  return value;
1642
1631
  };
1643
- function isTelaFile(obj) {
1644
- return obj instanceof TelaFile;
1632
+ function timeout(ms, signal) {
1633
+ return new Promise((resolve, reject) => {
1634
+ const timer = setTimeout(resolve, ms);
1635
+ if (signal) {
1636
+ signal.addEventListener("abort", () => {
1637
+ clearTimeout(timer);
1638
+ reject(signal.reason);
1639
+ }, { once: true });
1640
+ }
1641
+ });
1645
1642
  }
1646
- function isTelaFileArray(obj) {
1647
- return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
1643
+ class Poller {
1644
+ constructor({ interval, timeout: timeout2, abortSignal }) {
1645
+ __publicField$6(this, "_interval");
1646
+ __publicField$6(this, "_timeout");
1647
+ __publicField$6(this, "_abortSignal");
1648
+ __publicField$6(this, "_internalAbortController");
1649
+ if (interval <= 0) {
1650
+ throw new TelaError("Interval must be greater than 0");
1651
+ }
1652
+ if (timeout2 <= 0) {
1653
+ throw new TelaError("Timeout must be greater than 0");
1654
+ }
1655
+ this._interval = interval;
1656
+ this._timeout = timeout2;
1657
+ this._abortSignal = abortSignal ?? new AbortController().signal;
1658
+ this._internalAbortController = new AbortController();
1659
+ }
1660
+ async startTimeout() {
1661
+ await timeout(this._timeout, this._internalAbortController.signal);
1662
+ throw new ConnectionTimeout({
1663
+ message: `Reached timeout of ${this._timeout}ms when polling`
1664
+ });
1665
+ }
1666
+ /**
1667
+ * Starts the polling operation, repeatedly calling the callback until completion.
1668
+ * The callback is invoked at the configured interval and must return a PollerResult
1669
+ * indicating whether polling should continue or if the final value is ready.
1670
+ *
1671
+ * @param callback - Function called on each polling iteration.
1672
+ * @returns A promise resolving to the final result value.
1673
+ * @throws {Error} If the polling operation times out.
1674
+ * @throws {Error} If the operation is aborted via the AbortSignal.
1675
+ * @throws Any error thrown by the callback function.
1676
+ *
1677
+ * @example
1678
+ * ```typescript
1679
+ * const result = await poller.start(async (signal) => {
1680
+ * const response = await fetch('/api/status', { signal });
1681
+ * const data = await response.json();
1682
+ *
1683
+ * if (data.status === 'completed') {
1684
+ * return { done: true, value: data.result };
1685
+ * }
1686
+ * return { done: false };
1687
+ * });
1688
+ * ```
1689
+ */
1690
+ start(callback) {
1691
+ const resultPromise = async () => {
1692
+ try {
1693
+ while (!this._abortSignal.aborted) {
1694
+ const result = await callback();
1695
+ if (result.done) {
1696
+ return result.value;
1697
+ }
1698
+ await timeout(this._interval, this._abortSignal);
1699
+ }
1700
+ throw new UserAbortError({ message: "Polling aborted" });
1701
+ } finally {
1702
+ this._internalAbortController.abort();
1703
+ }
1704
+ };
1705
+ return Promise.race([this.startTimeout(), resultPromise()]);
1706
+ }
1648
1707
  }
1708
+
1709
+ var __defProp$5 = Object.defineProperty;
1710
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1711
+ var __publicField$5 = (obj, key, value) => {
1712
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1713
+ return value;
1714
+ };
1649
1715
  function isUUID(str) {
1650
1716
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1651
1717
  return uuidRegex.test(str);
@@ -1677,6 +1743,17 @@ function getResultFromPollingResponse(response) {
1677
1743
  }
1678
1744
  throw new Error("Invalid response type");
1679
1745
  }
1746
+ function normalizeExecutionStatus(status) {
1747
+ switch (status) {
1748
+ case "completed":
1749
+ case "validating":
1750
+ return "succeeded";
1751
+ case "cancelled":
1752
+ return "failed";
1753
+ default:
1754
+ return status;
1755
+ }
1756
+ }
1680
1757
  class CanvasExecution extends Emittery__default {
1681
1758
  /**
1682
1759
  * Creates a new canvas execution instance.
@@ -1688,20 +1765,20 @@ class CanvasExecution extends Emittery__default {
1688
1765
  */
1689
1766
  constructor(variables, params = { async: false }, outputSchema, client, isTask = false) {
1690
1767
  super();
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");
1768
+ __publicField$5(this, "_id");
1769
+ __publicField$5(this, "_status");
1770
+ __publicField$5(this, "_variables");
1771
+ __publicField$5(this, "_params");
1772
+ __publicField$5(this, "_client");
1773
+ __publicField$5(this, "_outputSchema");
1774
+ __publicField$5(this, "_skipResultValidation");
1775
+ __publicField$5(this, "_abortController");
1776
+ __publicField$5(this, "_isTask");
1777
+ __publicField$5(this, "_resultPromise");
1778
+ __publicField$5(this, "_stream");
1779
+ __publicField$5(this, "_rawResultValue");
1780
+ __publicField$5(this, "_requestId");
1781
+ __publicField$5(this, "_task");
1705
1782
  this._variables = variables;
1706
1783
  this._params = params;
1707
1784
  this._outputSchema = outputSchema;
@@ -2207,13 +2284,13 @@ class CanvasExecution extends Emittery__default {
2207
2284
  const resolvedVariables = await this.resolveVariables();
2208
2285
  return await this.create(resolvedVariables, { async: true }).then((response) => {
2209
2286
  this._id = "completionRunId" in response ? response.completionRunId : response.id;
2210
- this.status = response.status;
2287
+ this.status = normalizeExecutionStatus(response.status);
2211
2288
  if (this._isTask) {
2212
2289
  this._task = response;
2213
2290
  }
2214
2291
  this.emit("poll", {
2215
2292
  id: response.id,
2216
- status: response.status,
2293
+ status: normalizeExecutionStatus(response.status),
2217
2294
  outputContent: response.outputContent,
2218
2295
  rawOutput: "rawOutput" in response ? response.rawOutput : void 0,
2219
2296
  requestId: response.requestId
@@ -2258,15 +2335,15 @@ class CanvasExecution extends Emittery__default {
2258
2335
  signal: this._abortController.signal
2259
2336
  }
2260
2337
  );
2261
- this.status = response.status;
2338
+ this.status = normalizeExecutionStatus(response.status);
2262
2339
  this.emit("poll", response);
2263
- if (response.status === "failed") {
2340
+ if (this.status === "failed") {
2264
2341
  const error = new ExecutionFailedError(response.rawOutput);
2265
2342
  this.cancel();
2266
2343
  this.emit("error", error);
2267
2344
  throw error;
2268
2345
  }
2269
- if (response.status !== "succeeded") {
2346
+ if (this.status !== "succeeded") {
2270
2347
  return {
2271
2348
  done: false,
2272
2349
  value: void 0
@@ -2275,7 +2352,7 @@ class CanvasExecution extends Emittery__default {
2275
2352
  this._rawResultValue = response;
2276
2353
  this.emit("success", { ...getResultFromPollingResponse(response), requestId: response?.requestId });
2277
2354
  return {
2278
- done: response.status === "succeeded",
2355
+ done: this.status === "succeeded",
2279
2356
  value: getResultFromPollingResponse(response)
2280
2357
  };
2281
2358
  }).then((value) => {
@@ -2284,7 +2361,7 @@ class CanvasExecution extends Emittery__default {
2284
2361
  }
2285
2362
  return this._outputSchema.parse(value);
2286
2363
  }).catch((error) => {
2287
- if (this._status !== "failed") {
2364
+ if (this.status !== "failed") {
2288
2365
  this.status = "failed";
2289
2366
  }
2290
2367
  if (this.listenerCount("error") > 0) {
@@ -2330,10 +2407,10 @@ class CanvasExecution extends Emittery__default {
2330
2407
  }
2331
2408
  }
2332
2409
 
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);
2410
+ var __defProp$4 = Object.defineProperty;
2411
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2412
+ var __publicField$4 = (obj, key, value) => {
2413
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
2337
2414
  return value;
2338
2415
  };
2339
2416
  const BatchResultItem = z__default.looseObject({
@@ -2428,8 +2505,8 @@ class BatchExecutionResult {
2428
2505
  * @internal
2429
2506
  */
2430
2507
  constructor(client, response) {
2431
- __publicField$2(this, "_client");
2432
- __publicField$2(this, "_response");
2508
+ __publicField$4(this, "_client");
2509
+ __publicField$4(this, "_response");
2433
2510
  this._client = client;
2434
2511
  this._response = response;
2435
2512
  }
@@ -2715,13 +2792,13 @@ class BatchExecution extends Emittery__default {
2715
2792
  */
2716
2793
  constructor(id, client, params = {}, creationResponse) {
2717
2794
  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");
2795
+ __publicField$4(this, "_client");
2796
+ __publicField$4(this, "_id");
2797
+ __publicField$4(this, "_params");
2798
+ __publicField$4(this, "_abortController");
2799
+ __publicField$4(this, "_creationResponse");
2800
+ __publicField$4(this, "_status", "created");
2801
+ __publicField$4(this, "_resultPromise");
2725
2802
  this._id = id;
2726
2803
  this._client = client;
2727
2804
  this._params = params;
@@ -2934,10 +3011,10 @@ class Batch {
2934
3011
  * @internal
2935
3012
  */
2936
3013
  constructor(client, canvasIdentifier, params = {}) {
2937
- __publicField$2(this, "_client");
2938
- __publicField$2(this, "_canvasIdentifier");
2939
- __publicField$2(this, "_items", []);
2940
- __publicField$2(this, "_params");
3014
+ __publicField$4(this, "_client");
3015
+ __publicField$4(this, "_canvasIdentifier");
3016
+ __publicField$4(this, "_items", []);
3017
+ __publicField$4(this, "_params");
2941
3018
  this._client = client;
2942
3019
  this._canvasIdentifier = canvasIdentifier;
2943
3020
  this._params = params;
@@ -3073,16 +3150,12 @@ class Batch {
3073
3150
  }
3074
3151
  }
3075
3152
 
3076
- var __defProp$1 = Object.defineProperty;
3077
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3078
- var __publicField$1 = (obj, key, value) => {
3079
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
3153
+ var __defProp$3 = Object.defineProperty;
3154
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3155
+ var __publicField$3 = (obj, key, value) => {
3156
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
3080
3157
  return value;
3081
3158
  };
3082
- const zod = {
3083
- ...z__namespace,
3084
- file: TelaFileSchema
3085
- };
3086
3159
  function fetchById(id, client) {
3087
3160
  return client.get(`/prompt/${id}/promoted-version`);
3088
3161
  }
@@ -3104,56 +3177,6 @@ function fetchByAny({ id, versionId, applicationId, client }) {
3104
3177
  }
3105
3178
  throw new Error("Either id, versionId, or applicationId must be provided");
3106
3179
  }
3107
- function validateSchemas(input, output, promptVersion) {
3108
- const canvasIdentifier = `${promptVersion.title} (${promptVersion.promptId})`;
3109
- if (input instanceof z.z.ZodType) {
3110
- try {
3111
- const inputSchema = z.z.toJSONSchema(input, { unrepresentable: "any" });
3112
- const mismatches = validateInputSchema(inputSchema, promptVersion.variables);
3113
- if (mismatches.length === 0) {
3114
- return;
3115
- }
3116
- console.warn(
3117
- `[Tela SDK - Canvas Input Validation] Input schema mismatches for canvas "${canvasIdentifier}":`
3118
- );
3119
- for (const mismatch of mismatches) {
3120
- console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
3121
- }
3122
- } catch (error) {
3123
- console.warn(
3124
- `[Tela SDK - Canvas Input Validation] Failed to validate input schema for canvas "${canvasIdentifier}":`,
3125
- error
3126
- );
3127
- }
3128
- }
3129
- if (output instanceof z.z.ZodType) {
3130
- try {
3131
- const outputSchema = z.z.toJSONSchema(output);
3132
- const serverOutput = promptVersion.configuration.structuredOutput;
3133
- if (!serverOutput.enabled) {
3134
- console.warn(
3135
- `[Tela SDK - Canvas Output Validation] Output schema provided for canvas "${canvasIdentifier}", but structured output is not enabled on the server. The schema may not be enforced.`
3136
- );
3137
- return;
3138
- }
3139
- const mismatches = validateOutputSchema(outputSchema, serverOutput.schema);
3140
- if (mismatches.length === 0) {
3141
- return;
3142
- }
3143
- console.warn(
3144
- `[Tela SDK - Canvas Output Validation] Output schema mismatches for canvas "${canvasIdentifier}":`
3145
- );
3146
- for (const mismatch of mismatches) {
3147
- console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
3148
- }
3149
- } catch (error) {
3150
- console.warn(
3151
- `[Tela SDK - Canvas Output Validation] Failed to validate output schema for canvas "${canvasIdentifier}":`,
3152
- error
3153
- );
3154
- }
3155
- }
3156
- }
3157
3180
  class Canvas {
3158
3181
  /**
3159
3182
  * Creates a new instance of the Canvas class. Usage of this constructor is not recommended.
@@ -3162,15 +3185,15 @@ class Canvas {
3162
3185
  * @private
3163
3186
  */
3164
3187
  constructor({ id, applicationId, name, versionId, input, output, client, variables, isWorkflow }) {
3165
- __publicField$1(this, "_id");
3166
- __publicField$1(this, "_versionId");
3167
- __publicField$1(this, "_applicationId");
3168
- __publicField$1(this, "_name");
3169
- __publicField$1(this, "_input");
3170
- __publicField$1(this, "_output");
3171
- __publicField$1(this, "_client");
3172
- __publicField$1(this, "_variables");
3173
- __publicField$1(this, "_isWorkflow");
3188
+ __publicField$3(this, "_id");
3189
+ __publicField$3(this, "_versionId");
3190
+ __publicField$3(this, "_applicationId");
3191
+ __publicField$3(this, "_name");
3192
+ __publicField$3(this, "_input");
3193
+ __publicField$3(this, "_output");
3194
+ __publicField$3(this, "_client");
3195
+ __publicField$3(this, "_variables");
3196
+ __publicField$3(this, "_isWorkflow");
3174
3197
  this._id = id;
3175
3198
  this._applicationId = applicationId;
3176
3199
  this._name = name;
@@ -3199,7 +3222,7 @@ class Canvas {
3199
3222
  const inputSchema = input && input(zod);
3200
3223
  const outputSchema = output && output(zod);
3201
3224
  if (!skipSchemaValidation) {
3202
- validateSchemas(inputSchema, outputSchema, promptVersion);
3225
+ validateSchemas("Canvas", inputSchema, outputSchema, promptVersion);
3203
3226
  }
3204
3227
  return new Canvas({
3205
3228
  id: promptVersion.promptId,
@@ -3389,6 +3412,663 @@ class Canvas {
3389
3412
  }
3390
3413
  }
3391
3414
 
3415
+ const TaskStatus = z.z.enum(["created", "failed", "running", "validating", "completed", "cancelled"]);
3416
+ const OutputContent = z.z.object({
3417
+ role: z.z.literal("assistant"),
3418
+ content: z.z.unknown(),
3419
+ toolCalls: z.z.array(z.z.any()),
3420
+ functionCall: z.z.any()
3421
+ });
3422
+ const RawInput = z.z.object({
3423
+ async: z.z.boolean(),
3424
+ stream: z.z.boolean(),
3425
+ variables: z.z.record(z.z.string(), z.z.unknown()),
3426
+ applicationId: z.z.string()
3427
+ });
3428
+ z.z.object({
3429
+ id: z.z.string(),
3430
+ reference: z.z.number(),
3431
+ name: z.z.string(),
3432
+ status: TaskStatus,
3433
+ rawInput: RawInput,
3434
+ inputContent: z.z.any(),
3435
+ outputContent: OutputContent,
3436
+ originalOutputContent: OutputContent,
3437
+ createdBy: z.z.string(),
3438
+ approvedBy: z.z.any(),
3439
+ approvedAt: z.z.any(),
3440
+ completionRunId: z.z.string(),
3441
+ workflowRunId: z.z.any(),
3442
+ promptVersionId: z.z.string(),
3443
+ promptApplicationId: z.z.string(),
3444
+ workspaceId: z.z.string(),
3445
+ metadata: z.z.any(),
3446
+ tags: z.z.array(z.z.string()),
3447
+ createdAt: z.z.string(),
3448
+ updatedAt: z.z.string(),
3449
+ deletedAt: z.z.any(),
3450
+ requestId: z.z.string()
3451
+ });
3452
+
3453
+ var __defProp$2 = Object.defineProperty;
3454
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3455
+ var __publicField$2 = (obj, key, value) => {
3456
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
3457
+ return value;
3458
+ };
3459
+ class Task extends Emittery__default {
3460
+ constructor(client, variables, task, requestId, outputSchema, skipResultValidation = false) {
3461
+ super();
3462
+ __publicField$2(this, "_variables");
3463
+ __publicField$2(this, "_task");
3464
+ __publicField$2(this, "_abortController", new AbortController());
3465
+ __publicField$2(this, "_client");
3466
+ __publicField$2(this, "_outputSchema");
3467
+ __publicField$2(this, "_skipResultValidation");
3468
+ __publicField$2(this, "_resultPromise");
3469
+ __publicField$2(this, "_status");
3470
+ __publicField$2(this, "_requestId");
3471
+ this._variables = variables;
3472
+ this._task = task;
3473
+ this._client = client;
3474
+ this._outputSchema = outputSchema;
3475
+ this._skipResultValidation = skipResultValidation;
3476
+ this._status = task.status;
3477
+ this._requestId = requestId;
3478
+ }
3479
+ /**
3480
+ * Gets the unique task ID assigned by the server.
3481
+ *
3482
+ * @returns The task ID.
3483
+ */
3484
+ get id() {
3485
+ if (!this._task.id) {
3486
+ throw new Error("Task ID is not available");
3487
+ }
3488
+ return this._task.id;
3489
+ }
3490
+ /**
3491
+ * Gets the request ID from the `x-request-id` header of the task creation request.
3492
+ *
3493
+ * This is the request ID from the initial POST /task request that created the task.
3494
+ * Each API request has its own unique request ID.
3495
+ *
3496
+ * For polling operations, different request IDs are available:
3497
+ * - `task.requestId` - ID from the task creation request
3498
+ * - `pollResult.requestId` - ID from each polling request (in poll events)
3499
+ * - `result.requestId` - ID from the final successful polling request (in success events)
3500
+ *
3501
+ * @returns A promise that resolves to the request ID from the task creation request.
3502
+ *
3503
+ * @example
3504
+ * ```typescript
3505
+ * const task = await workstation.createTask({ query: 'test' })
3506
+ * const requestId = await task.requestId
3507
+ * console.log('Request ID:', requestId)
3508
+ * ```
3509
+ */
3510
+ get requestId() {
3511
+ return this._requestId;
3512
+ }
3513
+ /**
3514
+ * Gets the latest known status of the task.
3515
+ *
3516
+ * Status values and transitions:
3517
+ * - `created` → `running` → `completed` or `failed`
3518
+ *
3519
+ * **Important:** Status is set to `completed` only after successful validation.
3520
+ * If validation fails, status will be `failed` even if the API request succeeded.
3521
+ *
3522
+ * Use the `statusChange` event to track status transitions in real-time.
3523
+ *
3524
+ * @returns The current status of the task.
3525
+ *
3526
+ * @example
3527
+ * ```typescript
3528
+ * const task = await workstation.createTask({ query: 'test' })
3529
+ * console.log(task.status) // 'created'
3530
+ *
3531
+ * await task.result
3532
+ * console.log(task.status) // 'completed' or 'failed'
3533
+ * ```
3534
+ */
3535
+ get status() {
3536
+ return this._status;
3537
+ }
3538
+ /**
3539
+ * Sets the status of the task and emits statusChange event.
3540
+ *
3541
+ * @param status - The new status of the task.
3542
+ * @private
3543
+ */
3544
+ set status(status) {
3545
+ const changed = this._status !== status;
3546
+ this._status = status;
3547
+ if (changed) {
3548
+ this.emit("statusChange", status);
3549
+ }
3550
+ }
3551
+ /**
3552
+ * Gets the input variables provided to this task.
3553
+ *
3554
+ * @returns The variables object.
3555
+ */
3556
+ get variables() {
3557
+ return this._variables;
3558
+ }
3559
+ /**
3560
+ * Gets the task label (alias for name).
3561
+ *
3562
+ * @returns The task name.
3563
+ */
3564
+ get label() {
3565
+ return this.name;
3566
+ }
3567
+ /**
3568
+ * Gets the task name.
3569
+ *
3570
+ * @returns The task name.
3571
+ */
3572
+ get name() {
3573
+ return this._task.name;
3574
+ }
3575
+ /**
3576
+ * Gets the task tags.
3577
+ *
3578
+ * @returns The task tags.
3579
+ */
3580
+ get tags() {
3581
+ return this._task.tags;
3582
+ }
3583
+ /**
3584
+ * Gets the raw task definition from the server.
3585
+ *
3586
+ * @returns The raw task definition.
3587
+ */
3588
+ get rawTask() {
3589
+ return this._task;
3590
+ }
3591
+ /**
3592
+ * Starts polling for the task result without waiting for the promise to resolve.
3593
+ * This allows users to track task progress via events rather than awaiting a promise.
3594
+ *
3595
+ * The following events will be emitted during polling:
3596
+ * - `statusChange`: Emitted when the task status changes (e.g., 'created' → 'running' → 'completed')
3597
+ * - `poll`: Emitted on each polling attempt with the server response
3598
+ * - `success`: Emitted when the task completes successfully with the final result
3599
+ * - `error`: Emitted if the task fails
3600
+ *
3601
+ * **Important:** Events are only emitted while polling is active. You must call `poll()` or
3602
+ * await `task.result` to start polling. Simply setting up event listeners without starting
3603
+ * polling will not trigger any events.
3604
+ *
3605
+ * @example
3606
+ * ```typescript
3607
+ * const task = await workstation.createTask({ query: 'test' })
3608
+ *
3609
+ * // Set up event listeners
3610
+ * task.on('statusChange', (status) => {
3611
+ * console.log('Status:', status)
3612
+ * })
3613
+ *
3614
+ * task.on('success', (result) => {
3615
+ * console.log('Completed:', result)
3616
+ * })
3617
+ *
3618
+ * task.on('error', (error) => {
3619
+ * console.error('Failed:', error)
3620
+ * })
3621
+ *
3622
+ * // Start polling without waiting
3623
+ * task.poll()
3624
+ * ```
3625
+ */
3626
+ poll() {
3627
+ if (this._resultPromise) {
3628
+ return;
3629
+ }
3630
+ this._resultPromise = this.startPolling();
3631
+ this._resultPromise.catch(() => {
3632
+ });
3633
+ }
3634
+ /**
3635
+ * Gets the task result. Automatically starts polling if not already started.
3636
+ *
3637
+ * @returns A promise that resolves to the validated task output.
3638
+ *
3639
+ * @example
3640
+ * ```typescript
3641
+ * const task = await workstation.createTask({ query: 'test' })
3642
+ * const result = await task.result
3643
+ * console.log(result)
3644
+ * ```
3645
+ */
3646
+ get result() {
3647
+ if (this._resultPromise) {
3648
+ return this._resultPromise;
3649
+ }
3650
+ this._resultPromise = this.startPolling();
3651
+ return this._resultPromise;
3652
+ }
3653
+ /**
3654
+ * Starts the polling process to retrieve task results.
3655
+ * Emits events during the polling lifecycle and validates output before resolving.
3656
+ *
3657
+ * @returns A promise that resolves to the validated task output.
3658
+ * @private
3659
+ */
3660
+ async startPolling() {
3661
+ const result = await new Poller({
3662
+ interval: 1e3,
3663
+ timeout: 6e4,
3664
+ abortSignal: this._abortController.signal
3665
+ }).start(async () => {
3666
+ const response = await this._client.get(`/task/${this.id}`, {
3667
+ signal: this._abortController.signal
3668
+ });
3669
+ const newStatus = response.status;
3670
+ this.status = newStatus;
3671
+ this.emit("poll", response);
3672
+ if (response.status === "failed") {
3673
+ const error = new TaskFailedError(response, "Task failure reported by the server");
3674
+ this.status = "failed";
3675
+ this.emit("error", error);
3676
+ if (this.listenerCount("error") === 0) {
3677
+ throw error;
3678
+ }
3679
+ return {
3680
+ done: true,
3681
+ value: void 0
3682
+ };
3683
+ }
3684
+ if (!["completed", "validating"].includes(response.status)) {
3685
+ return {
3686
+ done: false,
3687
+ value: void 0
3688
+ };
3689
+ }
3690
+ return {
3691
+ done: true,
3692
+ value: response
3693
+ };
3694
+ });
3695
+ try {
3696
+ const value = result;
3697
+ if (value === void 0) {
3698
+ return void 0;
3699
+ }
3700
+ const content = value.outputContent.content;
3701
+ const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType) ? content : this._outputSchema.parse(content);
3702
+ this.status = value.status;
3703
+ this.emit("success", validatedContent);
3704
+ return validatedContent;
3705
+ } catch (error) {
3706
+ this.status = "failed";
3707
+ const castError = error instanceof Error ? error : new Error(String(error));
3708
+ const message = castError instanceof z.ZodError ? z__default.prettifyError(castError) : castError.message;
3709
+ this.emit("error", new TaskFailedError(result, message, castError));
3710
+ if (this.listenerCount("error") === 0) {
3711
+ throw error;
3712
+ }
3713
+ return void 0;
3714
+ }
3715
+ }
3716
+ }
3717
+
3718
+ var __defProp$1 = Object.defineProperty;
3719
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3720
+ var __publicField$1 = (obj, key, value) => {
3721
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
3722
+ return value;
3723
+ };
3724
+ const DateRange = z__default.object({
3725
+ since: z__default.union([z__default.date().transform((date) => date.toISOString()), z__default.iso.datetime()]),
3726
+ until: z__default.union([z__default.date().transform((date) => date.toISOString()), z__default.iso.datetime()])
3727
+ });
3728
+ const TaskListFilters = z__default.looseObject({
3729
+ id: z__default.uuid().array().optional(),
3730
+ name: z__default.string().optional(),
3731
+ status: z__default.array(TaskStatus).optional(),
3732
+ approvedAt: DateRange.partial().optional(),
3733
+ createdAt: DateRange.partial().optional(),
3734
+ updatedAt: DateRange.partial().optional(),
3735
+ approvedBy: z__default.string().optional(),
3736
+ createdBy: z__default.string().optional(),
3737
+ completionRunId: z__default.uuid().optional(),
3738
+ promptVersionId: z__default.uuid().optional()
3739
+ }).transform(({ name, approvedAt, createdAt, updatedAt, ...rest }) => ({
3740
+ taskName: name,
3741
+ ...approvedAt ? { approvedAtSince: approvedAt.since, approvedAtUntil: approvedAt.until } : {},
3742
+ ...createdAt ? { createdAtSince: createdAt.since, createdAtUntil: createdAt.until } : {},
3743
+ ...updatedAt ? { updatedAtSince: updatedAt.since, updatedAtUntil: updatedAt.until } : {},
3744
+ ...rest
3745
+ }));
3746
+ const TaskListOptions = z__default.looseObject({
3747
+ limit: z__default.number().optional(),
3748
+ offset: z__default.number().optional(),
3749
+ order: z__default.object({
3750
+ by: z__default.enum(["createdAt", "updatedAt", "approvedAt", "status", "reference", "name"]),
3751
+ direction: z__default.enum(["asc", "desc"])
3752
+ }).optional()
3753
+ }).transform(({ order, ...rest }) => ({
3754
+ orderBy: order?.by,
3755
+ orderDirection: order?.direction,
3756
+ ...rest
3757
+ }));
3758
+ class Workstation {
3759
+ /**
3760
+ * Creates a new Workstation instance.
3761
+ *
3762
+ * Use {@link Workstation.get} instead.
3763
+ * @internal
3764
+ */
3765
+ constructor({ client, applicationId, promptVersion, input, output }) {
3766
+ __publicField$1(this, "_id");
3767
+ __publicField$1(this, "_promptVersion");
3768
+ __publicField$1(this, "_client");
3769
+ __publicField$1(this, "_input");
3770
+ __publicField$1(this, "_output");
3771
+ this._id = applicationId;
3772
+ this._promptVersion = promptVersion;
3773
+ this._client = client;
3774
+ this._input = input && input(zod);
3775
+ this._output = output && output(zod);
3776
+ }
3777
+ /**
3778
+ * The unique identifier for this workstation (application ID).
3779
+ */
3780
+ get id() {
3781
+ return this._id;
3782
+ }
3783
+ /**
3784
+ * The prompt version configuration for this workstation.
3785
+ */
3786
+ get promptVersion() {
3787
+ return this._promptVersion;
3788
+ }
3789
+ /**
3790
+ * Retrieves a workstation by application ID and optionally validates schemas.
3791
+ *
3792
+ * This is the recommended way to create a Workstation instance.
3793
+ *
3794
+ * @param options - Configuration options
3795
+ * @param options.client - The BaseClient instance for API communication
3796
+ * @param options.applicationId - The unique ID of the workstation
3797
+ * @param options.input - Optional input schema function
3798
+ * @param options.output - Optional output schema function
3799
+ * @param options.skipSchemaValidation - Whether to skip schema validation (defaults to false)
3800
+ * @returns A promise that resolves to a Workstation instance
3801
+ *
3802
+ * @throws {Error} If schema validation fails (when schemas are provided and skipSchemaValidation is false)
3803
+ *
3804
+ * @example
3805
+ * ```typescript
3806
+ * const workstation = await Workstation.get({
3807
+ * client,
3808
+ * applicationId: 'app-123',
3809
+ * input: schema => schema.object({
3810
+ * query: schema.string(),
3811
+ * }),
3812
+ * output: schema => schema.object({
3813
+ * answer: schema.string(),
3814
+ * }),
3815
+ * })
3816
+ * ```
3817
+ */
3818
+ static async get(options) {
3819
+ const { client, applicationId, input, output, skipSchemaValidation = false } = options;
3820
+ const id = z__default.uuid({ error: (error) => `Invalid application ID: '${error.input}'. Must be a valid UUID.` }).parse(applicationId);
3821
+ const promptVersion = await client.get(`/prompt-application/${id}/targetPromptVersion`);
3822
+ const inputSchema = input && input(zod);
3823
+ const outputSchema = output && output(zod);
3824
+ if (!skipSchemaValidation) {
3825
+ validateSchemas("Workstation", inputSchema, outputSchema, promptVersion);
3826
+ }
3827
+ return new Workstation({
3828
+ client,
3829
+ applicationId: id,
3830
+ promptVersion,
3831
+ input,
3832
+ output
3833
+ });
3834
+ }
3835
+ /**
3836
+ * Creates a new task for this workstation and returns a promise-like object.
3837
+ *
3838
+ * The returned object can be awaited directly to get the Task instance, or you can
3839
+ * access `.result` to get the final task output directly.
3840
+ *
3841
+ * @param variables - Input variables for the task (must match the input schema)
3842
+ * @param params - Optional task parameters (label, tags, skipResultValidation)
3843
+ * @returns A promise-like object that resolves to the Task instance
3844
+ *
3845
+ * @example
3846
+ * ```typescript
3847
+ * // Get the task instance
3848
+ * const task = await workstation.createTask({ query: 'test' })
3849
+ *
3850
+ * // Or get the result directly
3851
+ * const result = await workstation.createTask({ query: 'test' }).result
3852
+ * ```
3853
+ */
3854
+ createTask(variables, params = {}) {
3855
+ const validatedVariables = this.parseVariables(variables);
3856
+ const taskDefinitionPromise = this.resolveVariables(validatedVariables).then((resolvedVariables) => this._client.post(`/task`, {
3857
+ body: {
3858
+ name: params.label ?? "Task from SDK",
3859
+ tags: params.tags ?? void 0,
3860
+ promptApplicationId: this._id,
3861
+ rawInput: {
3862
+ variables: resolvedVariables
3863
+ }
3864
+ },
3865
+ transformCase: false
3866
+ })).then((response) => {
3867
+ return new Task(
3868
+ this._client,
3869
+ variables,
3870
+ response[0],
3871
+ response.requestId,
3872
+ this._output,
3873
+ params.skipResultValidation ?? false
3874
+ );
3875
+ });
3876
+ return {
3877
+ then(onfulfilled, onrejected) {
3878
+ return Promise.resolve(taskDefinitionPromise).then((task) => onfulfilled?.(task) ?? task).catch(onrejected);
3879
+ },
3880
+ get result() {
3881
+ return Promise.resolve(taskDefinitionPromise).then((task) => task.result);
3882
+ }
3883
+ };
3884
+ }
3885
+ /**
3886
+ * Retrieves an existing task by its ID.
3887
+ *
3888
+ * This is useful for resuming monitoring of a task that was created earlier.
3889
+ *
3890
+ * @param id - The task ID to retrieve
3891
+ * @param options - Optional configuration
3892
+ * @param options.skipResultValidation - Whether to skip output validation
3893
+ * @returns A promise that resolves to the Task instance
3894
+ *
3895
+ * @example
3896
+ * ```typescript
3897
+ * const task = await workstation.getTask('task-id')
3898
+ *
3899
+ * // Set up event listeners
3900
+ * task.on('statusChange', (status) => console.log('Status:', status))
3901
+ * task.on('success', (result) => console.log('Result:', result))
3902
+ *
3903
+ * // Start polling
3904
+ * task.poll()
3905
+ * ```
3906
+ */
3907
+ async getTask(id, options = {}) {
3908
+ const taskResponse = await this._client.get(`/task/${id}`);
3909
+ return new Task(
3910
+ this._client,
3911
+ taskResponse.rawInput.variables,
3912
+ taskResponse,
3913
+ taskResponse.requestId,
3914
+ this._output,
3915
+ options.skipResultValidation ?? false
3916
+ );
3917
+ }
3918
+ /**
3919
+ * Validates and parses input variables using the workstation input schema.
3920
+ *
3921
+ * @param variables - Raw input variables to validate.
3922
+ * @returns Parsed and validated variables.
3923
+ * @throws {ZodError} If validation fails when a Zod schema is configured.
3924
+ */
3925
+ parseVariables(variables) {
3926
+ try {
3927
+ if (this._input instanceof z__default.ZodType) {
3928
+ return this._input.parse(variables);
3929
+ }
3930
+ return variables;
3931
+ } catch (error) {
3932
+ if (!(error instanceof z.ZodError)) {
3933
+ throw error;
3934
+ }
3935
+ throw new Error(z__default.prettifyError(error));
3936
+ }
3937
+ }
3938
+ /**
3939
+ * Processes variables and uploads any TelaFile instances to the server.
3940
+ * Replaces TelaFile objects with their uploaded URLs while preserving other values.
3941
+ *
3942
+ * @returns A promise resolving to the processed variables object.
3943
+ */
3944
+ async resolveVariables(inputVariables) {
3945
+ const variables = {};
3946
+ for (const [key, value] of Object.entries(inputVariables)) {
3947
+ if (isTelaFileArray(value)) {
3948
+ variables[key] = { files: await uploadFiles(value, this._client) };
3949
+ continue;
3950
+ }
3951
+ if (isTelaFile(value)) {
3952
+ variables[key] = await uploadFile(value, this._client);
3953
+ continue;
3954
+ }
3955
+ variables[key] = value;
3956
+ }
3957
+ return variables;
3958
+ }
3959
+ /**
3960
+ * Lists tasks for this workstation with optional filtering and pagination.
3961
+ *
3962
+ * Returns a page of tasks matching the specified filters, along with metadata
3963
+ * for pagination.
3964
+ *
3965
+ * @param params - Query parameters
3966
+ * @param params.filters - Optional filters to apply (ID, name, status, dates, etc.)
3967
+ * @param params.options - Optional pagination and sorting options
3968
+ * @param params.rawQuery - Raw query object (internal use, overrides filters/options)
3969
+ * @returns A promise that resolves to an object containing tasks and pagination metadata
3970
+ *
3971
+ * @example
3972
+ * ```typescript
3973
+ * // Get first 10 completed tasks
3974
+ * const { tasks, meta } = await workstation.listTasks({
3975
+ * filters: { status: ['completed'] },
3976
+ * options: { limit: 10, offset: 0 },
3977
+ * })
3978
+ *
3979
+ * // Sort by creation date
3980
+ * const { tasks, meta } = await workstation.listTasks({
3981
+ * options: {
3982
+ * order: { by: 'createdAt', direction: 'desc' },
3983
+ * limit: 20,
3984
+ * },
3985
+ * })
3986
+ * ```
3987
+ */
3988
+ async listTasks({ filters, options, rawQuery }) {
3989
+ function getQuery(id) {
3990
+ if (rawQuery) {
3991
+ return rawQuery;
3992
+ }
3993
+ const validatedFilters = TaskListFilters.optional().parse(filters);
3994
+ const validatedOptions = TaskListOptions.optional().parse(options);
3995
+ return {
3996
+ promptApplicationId: id,
3997
+ objectLinks: true,
3998
+ ...validatedFilters,
3999
+ ...validatedOptions
4000
+ };
4001
+ }
4002
+ const query = getQuery(this._id);
4003
+ const response = await this._client.get(`/task`, {
4004
+ query,
4005
+ transformCase: false
4006
+ });
4007
+ const tasks = response.data.map((task) => new Task(
4008
+ this._client,
4009
+ task.rawInput?.variables,
4010
+ task,
4011
+ task.requestId,
4012
+ this._output
4013
+ ));
4014
+ return {
4015
+ tasks,
4016
+ meta: response.meta
4017
+ };
4018
+ }
4019
+ /**
4020
+ * Asynchronously iterates through all tasks matching the specified filters.
4021
+ *
4022
+ * This generator automatically handles pagination, fetching additional pages
4023
+ * as needed. Each iteration yields a task and the current page metadata.
4024
+ *
4025
+ * @param params - Query parameters
4026
+ * @param params.filters - Optional filters to apply (ID, name, status, dates, etc.)
4027
+ * @param params.options - Optional initial pagination and sorting options
4028
+ * @yields A tuple of [task, metadata] for each task
4029
+ *
4030
+ * @example
4031
+ * ```typescript
4032
+ * // Iterate through all pending tasks
4033
+ * for await (const [task, meta] of workstation.iterateTasks({
4034
+ * filters: { status: ['pending'] },
4035
+ * })) {
4036
+ * console.log(`Task ${task.id}: ${task.status}`)
4037
+ * console.log(`Page ${meta.currentPage} of ${meta.totalPages}`)
4038
+ * }
4039
+ *
4040
+ * // Process tasks in batches
4041
+ * for await (const [task, meta] of workstation.iterateTasks({
4042
+ * options: { limit: 50 },
4043
+ * })) {
4044
+ * await processTask(task)
4045
+ * }
4046
+ * ```
4047
+ */
4048
+ async *iterateTasks({ filters, options }) {
4049
+ let rawQuery;
4050
+ let hasMore = true;
4051
+ while (hasMore) {
4052
+ const { tasks, meta } = await this.listTasks({
4053
+ filters,
4054
+ options,
4055
+ rawQuery
4056
+ });
4057
+ for (const task of tasks) {
4058
+ yield [task, meta];
4059
+ }
4060
+ if (meta.links.next !== null) {
4061
+ rawQuery = {
4062
+ ...meta.links.next,
4063
+ objectLinks: true
4064
+ };
4065
+ } else {
4066
+ hasMore = false;
4067
+ }
4068
+ }
4069
+ }
4070
+ }
4071
+
3392
4072
  var __defProp = Object.defineProperty;
3393
4073
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3394
4074
  var __publicField = (obj, key, value) => {
@@ -3450,6 +4130,17 @@ const _TelaSDK = class _TelaSDK extends BaseClient {
3450
4130
  });
3451
4131
  }
3452
4132
  });
4133
+ __publicField(this, "workstation", {
4134
+ get: async (options) => {
4135
+ return Workstation.get({
4136
+ applicationId: options.applicationId,
4137
+ input: options.input,
4138
+ output: options.output,
4139
+ skipSchemaValidation: options.skipSchemaValidation,
4140
+ client: this
4141
+ });
4142
+ }
4143
+ });
3453
4144
  this.opts = { baseURL, ...rest };
3454
4145
  this.apiKey = apiKey;
3455
4146
  this.jwt = jwt;
@@ -3509,6 +4200,10 @@ __publicField(_TelaSDK, "FileUploadError", FileUploadError);
3509
4200
  __publicField(_TelaSDK, "MissingApiKeyOrJWTError", MissingApiKeyOrJWTError);
3510
4201
  /** Thrown when both an API key and a JWT are provided. */
3511
4202
  __publicField(_TelaSDK, "ConflictApiKeyAndJWTError", ConflictApiKeyAndJWTError);
4203
+ /** Thrown when a canvas execution fails on the server. */
4204
+ __publicField(_TelaSDK, "ExecutionFailedError", ExecutionFailedError);
4205
+ /** Thrown when a workstation task fails on the server. */
4206
+ __publicField(_TelaSDK, "TaskFailedError", TaskFailedError);
3512
4207
  let TelaSDK = _TelaSDK;
3513
4208
  function createTelaClient(opts) {
3514
4209
  return new TelaSDK(opts);
@@ -3534,6 +4229,7 @@ exports.InvalidFileURL = InvalidFileURL;
3534
4229
  exports.MissingApiKeyOrJWTError = MissingApiKeyOrJWTError;
3535
4230
  exports.NotFoundError = NotFoundError;
3536
4231
  exports.RateLimitError = RateLimitError;
4232
+ exports.TaskFailedError = TaskFailedError;
3537
4233
  exports.TelaError = TelaError;
3538
4234
  exports.TelaFile = TelaFile;
3539
4235
  exports.TelaFileSchema = TelaFileSchema;
@@ -3541,4 +4237,6 @@ exports.TelaSDK = TelaSDK;
3541
4237
  exports.UnprocessableEntityError = UnprocessableEntityError;
3542
4238
  exports.UserAbortError = UserAbortError;
3543
4239
  exports.createTelaClient = createTelaClient;
4240
+ exports.isTelaFile = isTelaFile;
4241
+ exports.isTelaFileArray = isTelaFileArray;
3544
4242
  exports.toError = toError;