@meistrari/tela-sdk-js 2.0.0 → 2.1.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
@@ -3,6 +3,7 @@
3
3
  const changeCase = require('change-case');
4
4
  const minimatch = require('minimatch');
5
5
  const z = require('zod');
6
+ const Emittery = require('emittery');
6
7
 
7
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
8
9
 
@@ -20,8 +21,10 @@ function _interopNamespaceCompat(e) {
20
21
 
21
22
  const changeCase__namespace = /*#__PURE__*/_interopNamespaceCompat(changeCase);
22
23
  const z__default = /*#__PURE__*/_interopDefaultCompat(z);
24
+ const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
25
+ const Emittery__default = /*#__PURE__*/_interopDefaultCompat(Emittery);
23
26
 
24
- const version = "2.0.0";
27
+ const version = "2.1.0";
25
28
 
26
29
  var __defProp$7 = Object.defineProperty;
27
30
  var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -1045,14 +1048,6 @@ function TelaFileSchema() {
1045
1048
  return z__default.custom((value) => value instanceof TelaFile, { message: "Value must be an instance of TelaFile" }).meta({ isTelaFile: true });
1046
1049
  }
1047
1050
  class TelaFile {
1048
- /**
1049
- * Creates an instance of `TelaFile`.
1050
- *
1051
- * @param file - The source of the file. Can be a URL string, Uint8Array, ReadableStream, ReadStream, Blob, or File.
1052
- * @param options - Optional configuration options such as byte range.
1053
- * @throws {InvalidFileURL} If the provided URL is not valid.
1054
- * @throws {EmptyFileError} If the provided file is empty.
1055
- */
1056
1051
  constructor(file, options = {}) {
1057
1052
  __publicField$4(this, "_file");
1058
1053
  __publicField$4(this, "_options");
@@ -1430,7 +1425,7 @@ class Poller {
1430
1425
  const resultPromise = async () => {
1431
1426
  try {
1432
1427
  while (!this._abortSignal.aborted) {
1433
- const result = await Promise.try(callback, this._abortSignal);
1428
+ const result = await callback(this._abortSignal);
1434
1429
  if (result.done) {
1435
1430
  return result.value;
1436
1431
  }
@@ -1492,7 +1487,11 @@ function isTelaFile(obj) {
1492
1487
  function isTelaFileArray(obj) {
1493
1488
  return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
1494
1489
  }
1495
- class CanvasExecution {
1490
+ function isUUID(str) {
1491
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1492
+ return uuidRegex.test(str);
1493
+ }
1494
+ class CanvasExecution extends Emittery__default {
1496
1495
  /**
1497
1496
  * Creates a new canvas execution instance.
1498
1497
  *
@@ -1502,16 +1501,18 @@ class CanvasExecution {
1502
1501
  * @param client - HTTP client instance for making API requests.
1503
1502
  */
1504
1503
  constructor(variables, params = { async: false }, outputSchema, client) {
1504
+ super();
1505
1505
  __publicField$2(this, "_id");
1506
+ __publicField$2(this, "_status");
1506
1507
  __publicField$2(this, "_variables");
1507
1508
  __publicField$2(this, "_params");
1508
1509
  __publicField$2(this, "_client");
1509
1510
  __publicField$2(this, "_outputSchema");
1510
1511
  __publicField$2(this, "_skipResultValidation");
1511
1512
  __publicField$2(this, "_abortController");
1512
- __publicField$2(this, "_startPropmise");
1513
1513
  __publicField$2(this, "_resultPromise");
1514
1514
  __publicField$2(this, "_stream");
1515
+ __publicField$2(this, "_rawResultValue");
1515
1516
  this._variables = variables;
1516
1517
  this._params = params;
1517
1518
  this._outputSchema = outputSchema;
@@ -1519,18 +1520,138 @@ class CanvasExecution {
1519
1520
  this._client = client;
1520
1521
  this._abortController = new AbortController();
1521
1522
  }
1523
+ /**
1524
+ * Fetches an existing asynchronous execution by its ID.
1525
+ *
1526
+ * This method retrieves the current state of an async execution and creates a new
1527
+ * CanvasExecution instance with the fetched data. Only async executions can be
1528
+ * fetched, as they are the only ones with persistent UUIDs on the server.
1529
+ *
1530
+ * @param id - The UUID of the async execution to fetch.
1531
+ * @param outputSchema - Zod schema or object schema for validating/parsing output.
1532
+ * @param client - HTTP client instance for making API requests.
1533
+ * @param options - Optional configuration for polling behavior.
1534
+ * @param options.pollingInterval - Time in milliseconds between polling attempts (default: 1000).
1535
+ * @param options.pollingTimeout - Maximum time in milliseconds to wait for completion (default: 60000).
1536
+ * @throws {InvalidExecutionModeError} If the provided ID is not a valid UUID.
1537
+ * @returns A promise resolving to a CanvasExecution instance with the fetched state.
1538
+ *
1539
+ * @example
1540
+ * ```typescript
1541
+ * const execution = await CanvasExecution.fetch(
1542
+ * 'execution-uuid',
1543
+ * z.object({ result: z.string() }),
1544
+ * client,
1545
+ * { pollingInterval: 2000, pollingTimeout: 120000 }
1546
+ * )
1547
+ * console.log(execution.status) // 'running' or 'succeeded' or 'failed'
1548
+ * ```
1549
+ */
1550
+ static async fetch(id, outputSchema, client, options) {
1551
+ if (!isUUID(id)) {
1552
+ throw new InvalidExecutionModeError(
1553
+ "Only async executions can be fetched by ID. The provided ID is not a valid UUID."
1554
+ );
1555
+ }
1556
+ const response = await client.get(
1557
+ `/v2/chat/completions/${id}`
1558
+ );
1559
+ const params = {
1560
+ async: true,
1561
+ pollingInterval: options?.pollingInterval,
1562
+ pollingTimeout: options?.pollingTimeout
1563
+ };
1564
+ const execution = new CanvasExecution(
1565
+ {},
1566
+ // No variables needed for fetched execution
1567
+ params,
1568
+ outputSchema,
1569
+ client
1570
+ );
1571
+ execution._id = response.id;
1572
+ execution.status = response.status;
1573
+ if (response.status === "succeeded") {
1574
+ execution._rawResultValue = response;
1575
+ const content = response.outputContent.content;
1576
+ try {
1577
+ const validatedContent = execution._skipResultValidation || !(outputSchema instanceof z__default.ZodType) ? content : outputSchema.parse(content);
1578
+ execution._resultPromise = Promise.resolve(validatedContent);
1579
+ } catch (error) {
1580
+ execution._resultPromise = Promise.reject(error);
1581
+ execution._resultPromise.catch(() => {
1582
+ });
1583
+ }
1584
+ } else if (response.status === "failed") {
1585
+ execution._rawResultValue = response;
1586
+ const error = new ExecutionFailedError(response.rawOutput);
1587
+ execution._resultPromise = Promise.reject(error);
1588
+ execution._resultPromise.catch(() => {
1589
+ });
1590
+ }
1591
+ return execution;
1592
+ }
1522
1593
  /**
1523
1594
  * Gets the unique execution ID assigned by the server.
1524
1595
  *
1525
- * @throws {Error} If the execution has not been started yet.
1596
+ * Note: Streaming executions do not have an ID as they don't create a tracked execution on the server.
1597
+ *
1598
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
1599
+ * @throws {InvalidExecutionModeError} If called on a streaming execution (streams don't have IDs).
1526
1600
  * @returns The execution ID.
1527
1601
  */
1528
1602
  get id() {
1603
+ if (this.isStream) {
1604
+ throw new InvalidExecutionModeError("Streaming executions do not have an execution ID");
1605
+ }
1529
1606
  if (!this._id) {
1530
1607
  throw new ExecutionNotStartedError();
1531
1608
  }
1532
1609
  return this._id;
1533
1610
  }
1611
+ /**
1612
+ * Gets the latest known status of the execution.
1613
+ *
1614
+ * Status values and transitions:
1615
+ * - **Sync**: `succeeded` (after validation) or `failed` (on any error)
1616
+ * - **Async**: `created` → `running` → `succeeded` or `failed`
1617
+ * - **Stream**: `streaming` (once started)
1618
+ *
1619
+ * **Important:** Status is set to `succeeded` only after successful validation.
1620
+ * If validation fails, status will be `failed` even if the API request succeeded.
1621
+ *
1622
+ * Use the `statusChange` event to track status transitions in real-time.
1623
+ *
1624
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
1625
+ * @returns The current status of the execution.
1626
+ *
1627
+ * @example
1628
+ * ```typescript
1629
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
1630
+ * console.log(execution.status) // 'created'
1631
+ *
1632
+ * await execution.result
1633
+ * console.log(execution.status) // 'succeeded' or 'failed'
1634
+ * ```
1635
+ */
1636
+ get status() {
1637
+ if (!this._status) {
1638
+ throw new ExecutionNotStartedError();
1639
+ }
1640
+ return this._status;
1641
+ }
1642
+ /**
1643
+ * Sets the status of the execution.
1644
+ *
1645
+ * @param status - The new status of the execution.
1646
+ * @private
1647
+ */
1648
+ set status(status) {
1649
+ const changed = this._status !== status;
1650
+ this._status = status;
1651
+ if (changed) {
1652
+ this.emit("statusChange", status);
1653
+ }
1654
+ }
1534
1655
  /**
1535
1656
  * Gets the input variables provided to this execution.
1536
1657
  *
@@ -1571,6 +1692,31 @@ class CanvasExecution {
1571
1692
  get isStream() {
1572
1693
  return Boolean(this._params.stream);
1573
1694
  }
1695
+ /**
1696
+ * Gets the raw API response without any processing or validation.
1697
+ * Automatically starts execution and waits for completion (including polling for async executions).
1698
+ *
1699
+ * For sync executions, returns the complete API response.
1700
+ * For async executions, returns the polling response with status and output.
1701
+ *
1702
+ * @throws {InvalidExecutionModeError} If called on a streaming execution.
1703
+ * @returns A promise resolving to the raw API result.
1704
+ */
1705
+ get rawResult() {
1706
+ if (this.isStream) {
1707
+ throw new InvalidExecutionModeError("rawResult is not available for streaming executions");
1708
+ }
1709
+ if (this.isSync) {
1710
+ if (!this._resultPromise) {
1711
+ throw new ExecutionNotStartedError();
1712
+ }
1713
+ return this._resultPromise.then(() => this._rawResultValue);
1714
+ }
1715
+ if (!this._resultPromise) {
1716
+ this._resultPromise = this.startPolling();
1717
+ }
1718
+ return this._resultPromise.then(() => this._rawResultValue);
1719
+ }
1574
1720
  /**
1575
1721
  * Type guard to check if params indicate async execution.
1576
1722
  *
@@ -1629,18 +1775,88 @@ class CanvasExecution {
1629
1775
  cancel() {
1630
1776
  this._abortController.abort();
1631
1777
  }
1778
+ /**
1779
+ * Starts polling for the execution result without waiting for the promise to resolve.
1780
+ * This allows users to track execution progress via events rather than awaiting a promise.
1781
+ *
1782
+ * The following events will be emitted during polling:
1783
+ * - `statusChange`: Emitted when the execution status changes (e.g., 'created' → 'running' → 'succeeded')
1784
+ * - `poll`: Emitted on each polling attempt with the server response
1785
+ * - `success`: Emitted when the execution completes successfully with the final result
1786
+ * - `error`: Emitted if the execution fails
1787
+ *
1788
+ * **Important:** Events are only emitted while polling is active. You must either call `poll()` or
1789
+ * await `execution.result` to start polling. Simply setting up event listeners without starting
1790
+ * polling will not trigger any events.
1791
+ *
1792
+ * **Note:** If the execution has already completed (succeeded or failed) when fetched, the `success`
1793
+ * and `error` events will not fire since no polling is needed. Check the `status` property and
1794
+ * access the `result` directly for already-completed executions.
1795
+ *
1796
+ * @throws {InvalidExecutionModeError} If called on a non-async execution (sync or stream).
1797
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet (no ID assigned).
1798
+ *
1799
+ * @example
1800
+ * ```typescript
1801
+ * const execution = await canvas.getExecution('execution-id')
1802
+ *
1803
+ * // Check if already completed
1804
+ * if (execution.status === 'succeeded' || execution.status === 'failed') {
1805
+ * // Access result directly - events won't fire
1806
+ * const result = await execution.result
1807
+ * console.log('Already completed:', result)
1808
+ * } else {
1809
+ * // Still running - set up events and start polling
1810
+ * execution.on('statusChange', (status) => {
1811
+ * console.log('Status:', status)
1812
+ * })
1813
+ *
1814
+ * execution.on('success', (result) => {
1815
+ * console.log('Completed:', result)
1816
+ * })
1817
+ *
1818
+ * execution.on('error', (error) => {
1819
+ * console.error('Failed:', error)
1820
+ * })
1821
+ *
1822
+ * // Start polling without waiting
1823
+ * execution.poll()
1824
+ * }
1825
+ * ```
1826
+ */
1827
+ poll() {
1828
+ if (!this.isAsync) {
1829
+ throw new InvalidExecutionModeError("Polling is only supported for async executions");
1830
+ }
1831
+ if (!this._id) {
1832
+ throw new ExecutionNotStartedError();
1833
+ }
1834
+ if (this._resultPromise) {
1835
+ return;
1836
+ }
1837
+ this._resultPromise = this.startPolling();
1838
+ this._resultPromise.catch(() => {
1839
+ });
1840
+ }
1632
1841
  /**
1633
1842
  * Builds the base request body shared across all execution types.
1634
- * Includes messages, overrides, and structured output configuration.
1843
+ * Includes messages, overrides, tags, label, and structured output configuration.
1635
1844
  *
1636
1845
  * @returns The base request body object.
1637
1846
  */
1638
1847
  get baseBody() {
1848
+ if (this._params.label && !this._params.applicationId) {
1849
+ console.warn(
1850
+ '[Tela SDK - WARNING] The "label" field is only applicable when using applicationId. It will be ignored since no applicationId is provided.'
1851
+ );
1852
+ }
1639
1853
  const body = {
1640
1854
  canvasId: this._params.canvasId,
1641
1855
  applicationId: this._params.applicationId,
1642
1856
  versionId: this._params.versionId,
1643
- messages: this._params.messages
1857
+ messages: this._params.messages,
1858
+ tags: this._params.tags,
1859
+ label: this._params.label
1644
1860
  };
1645
1861
  if (this._params.override && this._outputSchema instanceof z__default.ZodType) {
1646
1862
  return {
@@ -1694,12 +1910,20 @@ class CanvasExecution {
1694
1910
  signal: this._abortController.signal
1695
1911
  }).then((response) => {
1696
1912
  this._id = response.id;
1913
+ this._rawResultValue = response;
1697
1914
  return response.choices?.[0]?.message?.content;
1698
1915
  }).then((content) => {
1699
- if (this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType)) {
1700
- return content;
1916
+ const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType) ? content : this._outputSchema.parse(content);
1917
+ this.status = "succeeded";
1918
+ this.emit("success", validatedContent);
1919
+ return validatedContent;
1920
+ }).catch((error) => {
1921
+ this.status = "failed";
1922
+ if (this.listenerCount("error") > 0) {
1923
+ this.emit("error", error);
1924
+ return;
1701
1925
  }
1702
- return this._outputSchema.parse(content);
1926
+ throw error;
1703
1927
  });
1704
1928
  return this._resultPromise;
1705
1929
  }
@@ -1723,6 +1947,13 @@ class CanvasExecution {
1723
1947
  signal: this._abortController.signal
1724
1948
  }).then((response) => {
1725
1949
  this._id = response.id;
1950
+ this.status = response.status;
1951
+ this.emit("poll", {
1952
+ id: response.id,
1953
+ status: response.status,
1954
+ outputContent: response.output_content,
1955
+ rawOutput: response.raw_output
1956
+ });
1726
1957
  return response;
1727
1958
  });
1728
1959
  }
@@ -1743,6 +1974,7 @@ class CanvasExecution {
1743
1974
  stream: true,
1744
1975
  signal: this._abortController.signal
1745
1976
  });
1977
+ this.status = "streaming";
1746
1978
  return this._stream;
1747
1979
  }
1748
1980
  /**
@@ -1771,8 +2003,12 @@ class CanvasExecution {
1771
2003
  signal
1772
2004
  }
1773
2005
  );
2006
+ this.status = response.status;
2007
+ this.emit("poll", response);
1774
2008
  if (response.status === "failed") {
1775
- throw new ExecutionFailedError(response.rawOutput);
2009
+ const error = new ExecutionFailedError(response.rawOutput);
2010
+ this.emit("error", error);
2011
+ throw error;
1776
2012
  }
1777
2013
  if (response.status !== "succeeded") {
1778
2014
  return {
@@ -1780,6 +2016,8 @@ class CanvasExecution {
1780
2016
  value: void 0
1781
2017
  };
1782
2018
  }
2019
+ this._rawResultValue = response;
2020
+ this.emit("success", response.outputContent.content);
1783
2021
  return {
1784
2022
  done: response.status === "succeeded",
1785
2023
  value: response.outputContent.content
@@ -1789,6 +2027,17 @@ class CanvasExecution {
1789
2027
  return value;
1790
2028
  }
1791
2029
  return this._outputSchema.parse(value);
2030
+ }).catch((error) => {
2031
+ if (this._status !== "failed") {
2032
+ this.status = "failed";
2033
+ }
2034
+ if (this.listenerCount("error") > 0) {
2035
+ if (!(error instanceof ExecutionFailedError)) {
2036
+ this.emit("error", error);
2037
+ }
2038
+ return;
2039
+ }
2040
+ throw error;
1792
2041
  });
1793
2042
  }
1794
2043
  /**
@@ -1881,14 +2130,8 @@ var __publicField$1 = (obj, key, value) => {
1881
2130
  return value;
1882
2131
  };
1883
2132
  const zod = {
1884
- string: z.string,
1885
- number: z.number,
1886
- boolean: z.boolean,
1887
- object: z.object,
1888
- array: z.array,
1889
- file: TelaFileSchema,
1890
- any: z.any,
1891
- unknown: z.unknown
2133
+ ...z__namespace,
2134
+ file: TelaFileSchema
1892
2135
  };
1893
2136
  function fetchById(id, client) {
1894
2137
  return client.get(`/prompt/${id}/promoted-version`);
@@ -2102,6 +2345,43 @@ class Canvas {
2102
2345
  }
2103
2346
  };
2104
2347
  }
2348
+ /**
2349
+ * Fetches an existing async execution by its ID.
2350
+ *
2351
+ * This method retrieves the current state of an async execution that was previously
2352
+ * started on this canvas. Only async executions can be fetched, as they are the only
2353
+ * ones with persistent UUIDs on the server.
2354
+ *
2355
+ * @param id - The UUID of the async execution to fetch.
2356
+ * @param options - Optional configuration for polling behavior.
2357
+ * @param options.pollingInterval - Time in milliseconds between polling attempts (default: 1000).
2358
+ * @param options.pollingTimeout - Maximum time in milliseconds to wait for completion (default: 60000).
2359
+ * @throws {InvalidExecutionModeError} If the provided ID is not a valid UUID.
2360
+ * @returns A promise resolving to a CanvasExecution instance with the fetched state.
2361
+ *
2362
+ * @example
2363
+ * ```typescript
2364
+ * // Start an async execution
2365
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
2366
+ * const executionId = execution.id
2367
+ *
2368
+ * // Later, fetch the execution by ID
2369
+ * const fetched = await canvas.getExecution(executionId)
2370
+ * console.log(fetched.status) // 'running', 'succeeded', or 'failed'
2371
+ *
2372
+ * // Use poll() for event-driven progress tracking
2373
+ * fetched.on('statusChange', (status) => console.log('Status:', status))
2374
+ * fetched.poll()
2375
+ * ```
2376
+ */
2377
+ async getExecution(id, options) {
2378
+ return CanvasExecution.fetch(
2379
+ id,
2380
+ this._output,
2381
+ this._client,
2382
+ options
2383
+ );
2384
+ }
2105
2385
  }
2106
2386
 
2107
2387
  var __defProp = Object.defineProperty;
@@ -2129,20 +2409,22 @@ const _TelaSDK = class _TelaSDK extends BaseClient {
2129
2409
  __publicField(this, "createFile", TelaFile.create.bind(this));
2130
2410
  /**
2131
2411
  * Retrieves a canvas by its ID, version ID, or application ID.
2132
- * Validates input and output schemas if Zod schemas are provided.
2412
+ * Validates input and output schemas if provided via schema builder functions.
2133
2413
  *
2134
2414
  * @param options - Options for retrieving the canvas.
2135
2415
  * @returns A promise resolving to a Canvas instance.
2136
2416
  *
2137
2417
  * @example
2138
2418
  * ```typescript
2139
- * import { z } from 'zod';
2140
- *
2141
2419
  * // Get canvas by ID with schemas
2142
2420
  * const canvas = await tela.canvas.get({
2143
2421
  * id: 'canvas-id',
2144
- * input: z.object({ query: z.string() }),
2145
- * output: z.object({ response: z.string() })
2422
+ * input: schema => schema.object({
2423
+ * query: schema.string()
2424
+ * }),
2425
+ * output: schema => schema.object({
2426
+ * response: schema.string()
2427
+ * })
2146
2428
  * });
2147
2429
  *
2148
2430
  * // Get canvas by application ID