@meistrari/tela-sdk-js 2.3.1 → 2.4.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/README.md CHANGED
@@ -171,12 +171,13 @@ execution.on('statusChange', (status) => {
171
171
 
172
172
  // Listen for polling updates
173
173
  execution.on('poll', (pollResult) => {
174
- console.log(`Poll - Status: ${pollResult.status}`)
174
+ console.log(`Poll - Status: ${pollResult.status}, Request ID: ${pollResult.requestId}`)
175
175
  })
176
176
 
177
177
  // Listen for successful completion
178
178
  execution.on('success', (result) => {
179
179
  console.log('Success!', result)
180
+ console.log('Request ID:', result.requestId)
180
181
  })
181
182
 
182
183
  // Listen for errors (prevents throwing)
@@ -218,6 +219,53 @@ Status is set to `succeeded` only after successful validation. If validation fai
218
219
 
219
220
  See [Event Examples](./examples/events/) for detailed usage patterns.
220
221
 
222
+ #### Accessing Request IDs
223
+
224
+ Every API request to Tela returns a unique `requestId` (from the `x-request-id` header) that can be used for debugging, tracking, and correlating with server logs. The SDK exposes request IDs in three ways:
225
+
226
+ ```typescript
227
+ const canvas = await tela.canvas.get({ id: 'canvas-id' })
228
+
229
+ // Start an async execution
230
+ const execution = await canvas.execute(
231
+ { query: 'test' },
232
+ { async: true }
233
+ )
234
+
235
+ // Method 1: Access directly from execution object
236
+ // This is the request ID from the initial request that created the execution
237
+ const requestId = await execution.requestId
238
+ console.log('Request ID:', requestId)
239
+
240
+ // Method 2: Access from poll events
241
+ // Each poll event includes the request ID from that specific polling request
242
+ execution.on('poll', (pollResult) => {
243
+ console.log('Request ID from this poll:', pollResult.requestId)
244
+ })
245
+
246
+ // Method 3: Access from success event
247
+ // The success event includes the request ID from the final successful polling request
248
+ execution.on('success', (result) => {
249
+ console.log('Request ID from final request:', result.requestId)
250
+ })
251
+
252
+ // Start polling
253
+ execution.poll()
254
+ ```
255
+
256
+ **Important Notes:**
257
+ - `execution.requestId` - Request ID from the execution creation request (POST /v2/chat/completions)
258
+ - `pollResult.requestId` - Request ID from each individual polling request (GET /v2/chat/completions/:id)
259
+ - `result.requestId` - Request ID from the final successful polling request
260
+
261
+ **Use Cases:**
262
+ - **Debugging**: Identify specific API requests when troubleshooting issues
263
+ - **Logging**: Track individual requests across distributed systems
264
+ - **Support**: Reference specific requests in support tickets
265
+ - **Monitoring**: Correlate client requests with server logs and traces
266
+
267
+ See [Request ID Example](./examples/events/request-id.ts) for a complete demonstration.
268
+
221
269
  #### Schema Validation
222
270
 
223
271
  The Canvas API validates your inputs and outputs against the server schema:
package/dist/index.cjs CHANGED
@@ -24,7 +24,7 @@ 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.3.1";
27
+ const version = "2.4.0";
28
28
 
29
29
  var __defProp$7 = Object.defineProperty;
30
30
  var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -319,13 +319,10 @@ class Stream {
319
319
  * @param iterator - A function that returns an AsyncIterator<Item>.
320
320
  * @param controller - The AbortController for this stream.
321
321
  */
322
- constructor(iterator, controller) {
322
+ constructor(iterator, controller, requestId) {
323
323
  this.iterator = iterator;
324
- /**
325
- * The AbortController associated with this stream.
326
- */
327
- __publicField$6(this, "controller");
328
324
  this.controller = controller;
325
+ this.requestId = requestId;
329
326
  }
330
327
  /**
331
328
  * Creates a Stream from a server-sent events (SSE) Response.
@@ -399,7 +396,8 @@ class Stream {
399
396
  controller.abort();
400
397
  }
401
398
  }
402
- return new Stream(iterator, controller);
399
+ const requestId = response.headers.get("x-request-id") || response.headers.get("request-id") || "";
400
+ return new Stream(iterator, controller, requestId);
403
401
  }
404
402
  /**
405
403
  * Creates a Stream from a newline-separated ReadableStream where each item is a JSON value.
@@ -739,31 +737,41 @@ var __publicField$5 = (obj, key, value) => {
739
737
  __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
740
738
  return value;
741
739
  };
742
- function tryGetResponseHeaders(response) {
740
+ function getRequestIdFromResponse(response) {
743
741
  try {
742
+ if (typeof response.headers.get === "function") {
743
+ return response.headers.get("x-request-id") || void 0;
744
+ }
744
745
  if (typeof response.headers.toJSON === "function") {
745
- return response.headers.toJSON();
746
+ const headers = response.headers.toJSON();
747
+ return headers["x-request-id"] || void 0;
746
748
  }
747
749
  if ("entries" in response.headers && typeof response.headers.entries === "function") {
748
- return Object.fromEntries(response.headers.entries());
750
+ for (const [key, value] of response.headers.entries()) {
751
+ if (key.toLowerCase() === "x-request-id") {
752
+ return value;
753
+ }
754
+ }
749
755
  }
750
756
  if (typeof response.headers.forEach === "function") {
751
- const headers = {};
757
+ let requestId;
752
758
  response.headers.forEach((value, key) => {
753
- headers[key] = value;
759
+ if (key.toLowerCase() === "x-request-id") {
760
+ requestId = value;
761
+ }
754
762
  });
755
- return headers;
763
+ return requestId;
756
764
  }
757
765
  if (response.headers && typeof response.headers[Symbol.iterator] === "function") {
758
- const headers = {};
759
766
  for (const [key, value] of response.headers) {
760
- headers[key] = value;
767
+ if (key.toLowerCase() === "x-request-id") {
768
+ return value;
769
+ }
761
770
  }
762
- return headers;
763
771
  }
764
- return {};
772
+ return void 0;
765
773
  } catch {
766
- return {};
774
+ return void 0;
767
775
  }
768
776
  }
769
777
  async function defaultParseResponse(props) {
@@ -780,7 +788,12 @@ async function defaultParseResponse(props) {
780
788
  if (isJSON) {
781
789
  const json = await response.json();
782
790
  debug("response", response.status, response.url, response.headers, json);
783
- return transformObjectFromSnakeCaseToCamelCase({ ...json, headers: tryGetResponseHeaders(response) }, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
791
+ const requestId = getRequestIdFromResponse(response);
792
+ const finalJson = { ...json };
793
+ if (requestId) {
794
+ finalJson.requestId = requestId;
795
+ }
796
+ return transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
784
797
  }
785
798
  const text = await response.text();
786
799
  debug("response", response.status, response.url, response.headers, text);
@@ -851,6 +864,7 @@ class BaseClient {
851
864
  remainingRetries = options.maxRetries ?? this.maxRetries;
852
865
  }
853
866
  const { req, url, timeout } = this.buildRequest(options);
867
+ debug("request", `[${options.method}] ${options.path} ${JSON.stringify(options.body)}`);
854
868
  if (options.signal?.aborted) {
855
869
  throw new UserAbortError();
856
870
  }
@@ -1522,13 +1536,13 @@ function isSyncWorkflowResult(obj) {
1522
1536
  return "output" in obj;
1523
1537
  }
1524
1538
  function isAsyncWorkflowResult(obj) {
1525
- return "outputContent" in obj && "output" in obj.outputContent;
1539
+ return "outputContent" in obj && obj.outputContent && typeof obj.outputContent === "object" && "output" in obj.outputContent;
1526
1540
  }
1527
1541
  function isSyncCanvasResult(obj) {
1528
1542
  return "choices" in obj;
1529
1543
  }
1530
1544
  function isAsyncCanvasResult(obj) {
1531
- return "outputContent" in obj && "content" in obj.outputContent;
1545
+ return "outputContent" in obj && obj.outputContent && typeof obj.outputContent === "object" && "content" in obj.outputContent;
1532
1546
  }
1533
1547
  function getResultFromPollingResponse(response) {
1534
1548
  if (isSyncWorkflowResult(response)) {
@@ -1567,6 +1581,7 @@ class CanvasExecution extends Emittery__default {
1567
1581
  __publicField$2(this, "_resultPromise");
1568
1582
  __publicField$2(this, "_stream");
1569
1583
  __publicField$2(this, "_rawResultValue");
1584
+ __publicField$2(this, "_requestId");
1570
1585
  this._variables = variables;
1571
1586
  this._params = params;
1572
1587
  this._outputSchema = outputSchema;
@@ -1662,6 +1677,53 @@ class CanvasExecution extends Emittery__default {
1662
1677
  }
1663
1678
  return this._id;
1664
1679
  }
1680
+ /**
1681
+ * Gets the request ID from the `x-request-id` header of the execution creation request.
1682
+ *
1683
+ * This is the request ID from the initial POST /v2/chat/completions request that created
1684
+ * the execution. Each API request has its own unique request ID.
1685
+ *
1686
+ * For async executions, different request IDs are available:
1687
+ * - `execution.requestId` - ID from the execution creation request
1688
+ * - `pollResult.requestId` - ID from each polling request (in poll events)
1689
+ * - `result.requestId` - ID from the final successful polling request (in success events)
1690
+ *
1691
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
1692
+ * @returns A promise that resolves to the request ID from the execution creation request.
1693
+ *
1694
+ * @example
1695
+ * ```typescript
1696
+ * const execution = await canvas.execute({ query: 'test' })
1697
+ * const requestId = await execution.requestId
1698
+ * console.log('Request ID:', requestId)
1699
+ * ```
1700
+ *
1701
+ * @example Accessing different request IDs in async executions
1702
+ * ```typescript
1703
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
1704
+ *
1705
+ * // Request ID from execution creation
1706
+ * const creationRequestId = await execution.requestId
1707
+ *
1708
+ * // Request IDs from polling
1709
+ * execution.on('poll', (pollResult) => {
1710
+ * console.log('Poll request ID:', pollResult.requestId)
1711
+ * })
1712
+ *
1713
+ * // Request ID from final result
1714
+ * execution.on('success', (result) => {
1715
+ * console.log('Final request ID:', result.requestId)
1716
+ * })
1717
+ *
1718
+ * execution.poll()
1719
+ * ```
1720
+ */
1721
+ get requestId() {
1722
+ if (!this._requestId) {
1723
+ throw new ExecutionNotStartedError();
1724
+ }
1725
+ return this._requestId;
1726
+ }
1665
1727
  /**
1666
1728
  * Gets the latest known status of the execution.
1667
1729
  *
@@ -1786,7 +1848,13 @@ class CanvasExecution extends Emittery__default {
1786
1848
  *
1787
1849
  * @returns A promise or async generator depending on execution mode.
1788
1850
  */
1789
- start() {
1851
+ async start() {
1852
+ if (this._params.applicationId && !this._params.async) {
1853
+ console.warn("[Tela SDK - WARNING] ApplicationId was provided, but async mode was not enabled. This will create a task, and tasks are always async. ");
1854
+ 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.");
1855
+ console.warn("[Tela SDK - WARNING] To disable these warnings, you can enable async mode explicitly.");
1856
+ this._params.async = true;
1857
+ }
1790
1858
  if (this._resultPromise || this._stream) {
1791
1859
  return this._resultPromise ?? this._stream;
1792
1860
  }
@@ -1805,15 +1873,19 @@ class CanvasExecution extends Emittery__default {
1805
1873
  * @returns The execution result as a promise or async generator.
1806
1874
  */
1807
1875
  get result() {
1876
+ if (this._params.applicationId && !this._params.canvasId) {
1877
+ const message = "Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.";
1878
+ return Promise.reject(new InvalidExecutionModeError(message));
1879
+ }
1808
1880
  if (this.isSync) {
1809
1881
  if (!this._resultPromise) {
1810
- throw new ExecutionNotStartedError();
1882
+ return Promise.reject(new ExecutionNotStartedError());
1811
1883
  }
1812
1884
  return this._resultPromise;
1813
1885
  }
1814
1886
  if (this.isStream) {
1815
1887
  if (!this._stream) {
1816
- throw new ExecutionNotStartedError();
1888
+ return Promise.reject(new ExecutionNotStartedError());
1817
1889
  }
1818
1890
  return this._stream;
1819
1891
  }
@@ -1879,6 +1951,9 @@ class CanvasExecution extends Emittery__default {
1879
1951
  * ```
1880
1952
  */
1881
1953
  poll() {
1954
+ if (this._params.applicationId && !this._params.canvasId) {
1955
+ throw new InvalidExecutionModeError("Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.");
1956
+ }
1882
1957
  if (!this.isAsync) {
1883
1958
  throw new InvalidExecutionModeError("Polling is only supported for async executions");
1884
1959
  }
@@ -1946,31 +2021,48 @@ class CanvasExecution extends Emittery__default {
1946
2021
  return variables;
1947
2022
  }
1948
2023
  /**
1949
- * Initiates a synchronous execution that waits for the complete result.
1950
- * The result is validated against the output schema if provided.
1951
- *
1952
- * @returns A promise resolving to the parsed execution result.
2024
+ * Creates an execution on the server by making a POST request to /v2/chat/completions.
2025
+ * This method is shared between sync, async, and streaming execution modes.
2026
+ * Automatically sets the _requestId property from response headers.
2027
+ *
2028
+ * @template TResponse - The expected response type (sync, async, or stream).
2029
+ * @param resolvedVariables - The processed variables with uploaded files.
2030
+ * @param options - Execution options.
2031
+ * @param options.async - Whether to create an async execution.
2032
+ * @param options.stream - Whether to create a streaming execution.
2033
+ * @returns A promise resolving to the execution creation response or stream.
1953
2034
  */
1954
- async startSync() {
1955
- const resolvedVariables = await this.resolveVariables();
2035
+ async create(resolvedVariables, options = {}) {
1956
2036
  const body = {
1957
- async: this._params.async ?? false,
1958
- stream: false,
2037
+ async: options.async ?? false,
2038
+ stream: options.stream ?? false,
1959
2039
  ...this.baseBody,
1960
2040
  variables: resolvedVariables
1961
2041
  };
1962
- this._resultPromise = this._client.post("/v2/chat/completions", {
2042
+ const responsePromise = this._client.post("/v2/chat/completions", {
1963
2043
  body,
1964
- stream: false,
2044
+ stream: options.stream ?? false,
1965
2045
  signal: this._abortController.signal
1966
- }).then((response) => {
2046
+ });
2047
+ this._requestId = responsePromise.then((response) => response?.requestId || "").catch(() => "");
2048
+ return await responsePromise;
2049
+ }
2050
+ /**
2051
+ * Initiates a synchronous execution that waits for the complete result.
2052
+ * The result is validated against the output schema if provided.
2053
+ *
2054
+ * @returns A promise resolving to the parsed execution result.
2055
+ */
2056
+ async startSync() {
2057
+ const resolvedVariables = await this.resolveVariables();
2058
+ this._resultPromise = this.create(resolvedVariables, { async: false }).then((response) => {
1967
2059
  this._id = response.id;
1968
2060
  this._rawResultValue = response;
1969
2061
  return { content: getResultFromPollingResponse(response), response };
1970
2062
  }).then(({ content, response }) => {
1971
2063
  const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType) ? content : this._outputSchema.parse(content);
1972
2064
  this.status = "succeeded";
1973
- this.emit("success", { ...validatedContent, headers: response?.headers ?? {} });
2065
+ this.emit("success", { ...validatedContent, requestId: response?.requestId });
1974
2066
  return validatedContent;
1975
2067
  }).catch((error) => {
1976
2068
  this.status = "failed";
@@ -1990,17 +2082,7 @@ class CanvasExecution extends Emittery__default {
1990
2082
  */
1991
2083
  async startAsync() {
1992
2084
  const resolvedVariables = await this.resolveVariables();
1993
- const body = {
1994
- async: true,
1995
- stream: false,
1996
- ...this.baseBody,
1997
- variables: resolvedVariables
1998
- };
1999
- return await this._client.post("/v2/chat/completions", {
2000
- body,
2001
- stream: false,
2002
- signal: this._abortController.signal
2003
- }).then((response) => {
2085
+ return await this.create(resolvedVariables, { async: true }).then((response) => {
2004
2086
  this._id = response.id;
2005
2087
  this.status = response.status;
2006
2088
  this.emit("poll", {
@@ -2008,7 +2090,7 @@ class CanvasExecution extends Emittery__default {
2008
2090
  status: response.status,
2009
2091
  outputContent: response.output_content,
2010
2092
  rawOutput: response.raw_output,
2011
- headers: response.headers
2093
+ requestId: response.requestId
2012
2094
  });
2013
2095
  return response;
2014
2096
  });
@@ -2020,16 +2102,7 @@ class CanvasExecution extends Emittery__default {
2020
2102
  */
2021
2103
  async startStream() {
2022
2104
  const resolvedVariables = await this.resolveVariables();
2023
- const body = {
2024
- ...this.baseBody,
2025
- stream: true,
2026
- variables: resolvedVariables
2027
- };
2028
- this._stream = await this._client.post("/v2/chat/completions", {
2029
- body,
2030
- stream: true,
2031
- signal: this._abortController.signal
2032
- });
2105
+ this._stream = await this.create(resolvedVariables, { stream: true });
2033
2106
  this.status = "streaming";
2034
2107
  return this._stream;
2035
2108
  }
@@ -2063,6 +2136,7 @@ class CanvasExecution extends Emittery__default {
2063
2136
  this.emit("poll", response);
2064
2137
  if (response.status === "failed") {
2065
2138
  const error = new ExecutionFailedError(response.rawOutput);
2139
+ this.cancel();
2066
2140
  this.emit("error", error);
2067
2141
  throw error;
2068
2142
  }
@@ -2073,7 +2147,7 @@ class CanvasExecution extends Emittery__default {
2073
2147
  };
2074
2148
  }
2075
2149
  this._rawResultValue = response;
2076
- this.emit("success", { ...getResultFromPollingResponse(response), headers: response?.headers ?? {} });
2150
+ this.emit("success", { ...getResultFromPollingResponse(response), requestId: response?.requestId });
2077
2151
  return {
2078
2152
  done: response.status === "succeeded",
2079
2153
  value: getResultFromPollingResponse(response)
@@ -2309,8 +2383,9 @@ class Canvas {
2309
2383
  }
2310
2384
  return new Canvas({
2311
2385
  id: promptVersion.promptId,
2312
- name: promptVersion.title,
2313
2386
  versionId: promptVersion.id,
2387
+ applicationId: applicationId ?? void 0,
2388
+ name: promptVersion.title,
2314
2389
  input,
2315
2390
  output,
2316
2391
  client,
@@ -2396,11 +2471,10 @@ class Canvas {
2396
2471
  }
2397
2472
  execute(variables, params) {
2398
2473
  const parsedInput = this.parseVariables(variables);
2474
+ const idObject = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, canvasId: this._id };
2399
2475
  const fullParams = {
2400
2476
  ...params ?? { async: false },
2401
- versionId: this._versionId,
2402
- canvasId: this._id,
2403
- applicationId: this._applicationId
2477
+ ...idObject
2404
2478
  };
2405
2479
  const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client);
2406
2480
  return {
package/dist/index.d.cts CHANGED
@@ -620,6 +620,17 @@ type AsyncCompletionCreateResult = {
620
620
  * This type will be refined in future versions with proper typing.
621
621
  */
622
622
  type RawAPIResult = any;
623
+ /**
624
+ * Helper type to add request ID to a response type.
625
+ *
626
+ * The `requestId` field contains the value from the `x-request-id` HTTP header
627
+ * returned by the API for that specific request.
628
+ *
629
+ * @template T - The base response type.
630
+ */
631
+ type WithRequestId<T> = T & {
632
+ requestId?: string;
633
+ };
623
634
  /**
624
635
  * Result returned when polling for asynchronous execution status.
625
636
  *
@@ -662,13 +673,21 @@ type ExecutionParams = AsyncExecutionParams | StreamExecutionParams | SyncExecut
662
673
  * @returns AsyncGenerator for streaming executions, Promise otherwise.
663
674
  */
664
675
  type CanvasExecutionResult<TParams, TOutput = unknown> = TParams extends StreamExecutionParams ? AsyncGenerator<Partial<TOutput>> : Promise<TOutput>;
676
+ /**
677
+ * Event types emitted by CanvasExecution during its lifecycle.
678
+ *
679
+ * @template TOutput - The output type.
680
+ *
681
+ * @property poll - Emitted during async polling with current status and output. Includes `requestId` from the polling request.
682
+ * @property success - Emitted when execution completes successfully with the final result. Includes `requestId` from the final request.
683
+ * @property error - Emitted when execution fails with the error object.
684
+ * @property statusChange - Emitted when execution status transitions to a new state.
685
+ *
686
+ * @category Canvas
687
+ */
665
688
  type CanvasExecutionEvents<TOutput> = {
666
- poll: AsyncCompletionPollingResult<TOutput> & {
667
- headers: Record<string, string>;
668
- };
669
- success: TOutput & {
670
- headers: Record<string, string>;
671
- };
689
+ poll: WithRequestId<AsyncCompletionPollingResult<TOutput>>;
690
+ success: WithRequestId<TOutput>;
672
691
  error: ExecutionFailedError;
673
692
  statusChange: ExecutionStatus;
674
693
  };
@@ -701,8 +720,8 @@ type CanvasExecutionEvents<TOutput> = {
701
720
  * @typeParam TInput - The input variables type
702
721
  * @typeParam TOutput - The output result type
703
722
  *
704
- * @fires poll - Emitted during async polling with current status and output (async executions only)
705
- * @fires success - Emitted when execution completes successfully with the final result
723
+ * @fires poll - Emitted during async polling with current status and output. Includes `requestId` from the polling request. (async executions only)
724
+ * @fires success - Emitted when execution completes successfully with the final result. Includes `requestId` from the final request.
706
725
  * @fires error - Emitted when execution fails (only if error listeners are registered, otherwise throws)
707
726
  * @fires statusChange - Emitted when execution status transitions to a new state
708
727
  *
@@ -734,6 +753,7 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
734
753
  private _resultPromise;
735
754
  private _stream;
736
755
  private _rawResultValue;
756
+ private _requestId;
737
757
  /**
738
758
  * Creates a new canvas execution instance.
739
759
  *
@@ -784,6 +804,48 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
784
804
  * @returns The execution ID.
785
805
  */
786
806
  get id(): string;
807
+ /**
808
+ * Gets the request ID from the `x-request-id` header of the execution creation request.
809
+ *
810
+ * This is the request ID from the initial POST /v2/chat/completions request that created
811
+ * the execution. Each API request has its own unique request ID.
812
+ *
813
+ * For async executions, different request IDs are available:
814
+ * - `execution.requestId` - ID from the execution creation request
815
+ * - `pollResult.requestId` - ID from each polling request (in poll events)
816
+ * - `result.requestId` - ID from the final successful polling request (in success events)
817
+ *
818
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
819
+ * @returns A promise that resolves to the request ID from the execution creation request.
820
+ *
821
+ * @example
822
+ * ```typescript
823
+ * const execution = await canvas.execute({ query: 'test' })
824
+ * const requestId = await execution.requestId
825
+ * console.log('Request ID:', requestId)
826
+ * ```
827
+ *
828
+ * @example Accessing different request IDs in async executions
829
+ * ```typescript
830
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
831
+ *
832
+ * // Request ID from execution creation
833
+ * const creationRequestId = await execution.requestId
834
+ *
835
+ * // Request IDs from polling
836
+ * execution.on('poll', (pollResult) => {
837
+ * console.log('Poll request ID:', pollResult.requestId)
838
+ * })
839
+ *
840
+ * // Request ID from final result
841
+ * execution.on('success', (result) => {
842
+ * console.log('Final request ID:', result.requestId)
843
+ * })
844
+ *
845
+ * execution.poll()
846
+ * ```
847
+ */
848
+ get requestId(): Promise<string>;
787
849
  /**
788
850
  * Gets the latest known status of the execution.
789
851
  *
@@ -871,9 +933,7 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
871
933
  *
872
934
  * @returns A promise or async generator depending on execution mode.
873
935
  */
874
- start(): Promise<CanvasExecutionResult<TParams, TOutput>> | AsyncGenerator<Partial<TOutput>, any, any> | Promise<AsyncGenerator<Partial<TOutput>, any, any>> | Promise<AsyncCompletionCreateResult & {
875
- headers: Record<string, string>;
876
- }>;
936
+ start(): Promise<CanvasExecutionResult<TParams, TOutput> | AsyncGenerator<Partial<TOutput>, any, any> | WithRequestId<AsyncCompletionCreateResult>>;
877
937
  /**
878
938
  * Gets the execution result. For async executions, automatically starts polling.
879
939
  * For sync executions, returns the result promise. For streams, returns the generator.
@@ -949,6 +1009,19 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
949
1009
  * @returns A promise resolving to the processed variables object.
950
1010
  */
951
1011
  private resolveVariables;
1012
+ /**
1013
+ * Creates an execution on the server by making a POST request to /v2/chat/completions.
1014
+ * This method is shared between sync, async, and streaming execution modes.
1015
+ * Automatically sets the _requestId property from response headers.
1016
+ *
1017
+ * @template TResponse - The expected response type (sync, async, or stream).
1018
+ * @param resolvedVariables - The processed variables with uploaded files.
1019
+ * @param options - Execution options.
1020
+ * @param options.async - Whether to create an async execution.
1021
+ * @param options.stream - Whether to create a streaming execution.
1022
+ * @returns A promise resolving to the execution creation response or stream.
1023
+ */
1024
+ private create;
952
1025
  /**
953
1026
  * Initiates a synchronous execution that waits for the complete result.
954
1027
  * The result is validated against the output schema if provided.
package/dist/index.d.mts CHANGED
@@ -620,6 +620,17 @@ type AsyncCompletionCreateResult = {
620
620
  * This type will be refined in future versions with proper typing.
621
621
  */
622
622
  type RawAPIResult = any;
623
+ /**
624
+ * Helper type to add request ID to a response type.
625
+ *
626
+ * The `requestId` field contains the value from the `x-request-id` HTTP header
627
+ * returned by the API for that specific request.
628
+ *
629
+ * @template T - The base response type.
630
+ */
631
+ type WithRequestId<T> = T & {
632
+ requestId?: string;
633
+ };
623
634
  /**
624
635
  * Result returned when polling for asynchronous execution status.
625
636
  *
@@ -662,13 +673,21 @@ type ExecutionParams = AsyncExecutionParams | StreamExecutionParams | SyncExecut
662
673
  * @returns AsyncGenerator for streaming executions, Promise otherwise.
663
674
  */
664
675
  type CanvasExecutionResult<TParams, TOutput = unknown> = TParams extends StreamExecutionParams ? AsyncGenerator<Partial<TOutput>> : Promise<TOutput>;
676
+ /**
677
+ * Event types emitted by CanvasExecution during its lifecycle.
678
+ *
679
+ * @template TOutput - The output type.
680
+ *
681
+ * @property poll - Emitted during async polling with current status and output. Includes `requestId` from the polling request.
682
+ * @property success - Emitted when execution completes successfully with the final result. Includes `requestId` from the final request.
683
+ * @property error - Emitted when execution fails with the error object.
684
+ * @property statusChange - Emitted when execution status transitions to a new state.
685
+ *
686
+ * @category Canvas
687
+ */
665
688
  type CanvasExecutionEvents<TOutput> = {
666
- poll: AsyncCompletionPollingResult<TOutput> & {
667
- headers: Record<string, string>;
668
- };
669
- success: TOutput & {
670
- headers: Record<string, string>;
671
- };
689
+ poll: WithRequestId<AsyncCompletionPollingResult<TOutput>>;
690
+ success: WithRequestId<TOutput>;
672
691
  error: ExecutionFailedError;
673
692
  statusChange: ExecutionStatus;
674
693
  };
@@ -701,8 +720,8 @@ type CanvasExecutionEvents<TOutput> = {
701
720
  * @typeParam TInput - The input variables type
702
721
  * @typeParam TOutput - The output result type
703
722
  *
704
- * @fires poll - Emitted during async polling with current status and output (async executions only)
705
- * @fires success - Emitted when execution completes successfully with the final result
723
+ * @fires poll - Emitted during async polling with current status and output. Includes `requestId` from the polling request. (async executions only)
724
+ * @fires success - Emitted when execution completes successfully with the final result. Includes `requestId` from the final request.
706
725
  * @fires error - Emitted when execution fails (only if error listeners are registered, otherwise throws)
707
726
  * @fires statusChange - Emitted when execution status transitions to a new state
708
727
  *
@@ -734,6 +753,7 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
734
753
  private _resultPromise;
735
754
  private _stream;
736
755
  private _rawResultValue;
756
+ private _requestId;
737
757
  /**
738
758
  * Creates a new canvas execution instance.
739
759
  *
@@ -784,6 +804,48 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
784
804
  * @returns The execution ID.
785
805
  */
786
806
  get id(): string;
807
+ /**
808
+ * Gets the request ID from the `x-request-id` header of the execution creation request.
809
+ *
810
+ * This is the request ID from the initial POST /v2/chat/completions request that created
811
+ * the execution. Each API request has its own unique request ID.
812
+ *
813
+ * For async executions, different request IDs are available:
814
+ * - `execution.requestId` - ID from the execution creation request
815
+ * - `pollResult.requestId` - ID from each polling request (in poll events)
816
+ * - `result.requestId` - ID from the final successful polling request (in success events)
817
+ *
818
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
819
+ * @returns A promise that resolves to the request ID from the execution creation request.
820
+ *
821
+ * @example
822
+ * ```typescript
823
+ * const execution = await canvas.execute({ query: 'test' })
824
+ * const requestId = await execution.requestId
825
+ * console.log('Request ID:', requestId)
826
+ * ```
827
+ *
828
+ * @example Accessing different request IDs in async executions
829
+ * ```typescript
830
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
831
+ *
832
+ * // Request ID from execution creation
833
+ * const creationRequestId = await execution.requestId
834
+ *
835
+ * // Request IDs from polling
836
+ * execution.on('poll', (pollResult) => {
837
+ * console.log('Poll request ID:', pollResult.requestId)
838
+ * })
839
+ *
840
+ * // Request ID from final result
841
+ * execution.on('success', (result) => {
842
+ * console.log('Final request ID:', result.requestId)
843
+ * })
844
+ *
845
+ * execution.poll()
846
+ * ```
847
+ */
848
+ get requestId(): Promise<string>;
787
849
  /**
788
850
  * Gets the latest known status of the execution.
789
851
  *
@@ -871,9 +933,7 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
871
933
  *
872
934
  * @returns A promise or async generator depending on execution mode.
873
935
  */
874
- start(): Promise<CanvasExecutionResult<TParams, TOutput>> | AsyncGenerator<Partial<TOutput>, any, any> | Promise<AsyncGenerator<Partial<TOutput>, any, any>> | Promise<AsyncCompletionCreateResult & {
875
- headers: Record<string, string>;
876
- }>;
936
+ start(): Promise<CanvasExecutionResult<TParams, TOutput> | AsyncGenerator<Partial<TOutput>, any, any> | WithRequestId<AsyncCompletionCreateResult>>;
877
937
  /**
878
938
  * Gets the execution result. For async executions, automatically starts polling.
879
939
  * For sync executions, returns the result promise. For streams, returns the generator.
@@ -949,6 +1009,19 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
949
1009
  * @returns A promise resolving to the processed variables object.
950
1010
  */
951
1011
  private resolveVariables;
1012
+ /**
1013
+ * Creates an execution on the server by making a POST request to /v2/chat/completions.
1014
+ * This method is shared between sync, async, and streaming execution modes.
1015
+ * Automatically sets the _requestId property from response headers.
1016
+ *
1017
+ * @template TResponse - The expected response type (sync, async, or stream).
1018
+ * @param resolvedVariables - The processed variables with uploaded files.
1019
+ * @param options - Execution options.
1020
+ * @param options.async - Whether to create an async execution.
1021
+ * @param options.stream - Whether to create a streaming execution.
1022
+ * @returns A promise resolving to the execution creation response or stream.
1023
+ */
1024
+ private create;
952
1025
  /**
953
1026
  * Initiates a synchronous execution that waits for the complete result.
954
1027
  * The result is validated against the output schema if provided.
package/dist/index.d.ts CHANGED
@@ -620,6 +620,17 @@ type AsyncCompletionCreateResult = {
620
620
  * This type will be refined in future versions with proper typing.
621
621
  */
622
622
  type RawAPIResult = any;
623
+ /**
624
+ * Helper type to add request ID to a response type.
625
+ *
626
+ * The `requestId` field contains the value from the `x-request-id` HTTP header
627
+ * returned by the API for that specific request.
628
+ *
629
+ * @template T - The base response type.
630
+ */
631
+ type WithRequestId<T> = T & {
632
+ requestId?: string;
633
+ };
623
634
  /**
624
635
  * Result returned when polling for asynchronous execution status.
625
636
  *
@@ -662,13 +673,21 @@ type ExecutionParams = AsyncExecutionParams | StreamExecutionParams | SyncExecut
662
673
  * @returns AsyncGenerator for streaming executions, Promise otherwise.
663
674
  */
664
675
  type CanvasExecutionResult<TParams, TOutput = unknown> = TParams extends StreamExecutionParams ? AsyncGenerator<Partial<TOutput>> : Promise<TOutput>;
676
+ /**
677
+ * Event types emitted by CanvasExecution during its lifecycle.
678
+ *
679
+ * @template TOutput - The output type.
680
+ *
681
+ * @property poll - Emitted during async polling with current status and output. Includes `requestId` from the polling request.
682
+ * @property success - Emitted when execution completes successfully with the final result. Includes `requestId` from the final request.
683
+ * @property error - Emitted when execution fails with the error object.
684
+ * @property statusChange - Emitted when execution status transitions to a new state.
685
+ *
686
+ * @category Canvas
687
+ */
665
688
  type CanvasExecutionEvents<TOutput> = {
666
- poll: AsyncCompletionPollingResult<TOutput> & {
667
- headers: Record<string, string>;
668
- };
669
- success: TOutput & {
670
- headers: Record<string, string>;
671
- };
689
+ poll: WithRequestId<AsyncCompletionPollingResult<TOutput>>;
690
+ success: WithRequestId<TOutput>;
672
691
  error: ExecutionFailedError;
673
692
  statusChange: ExecutionStatus;
674
693
  };
@@ -701,8 +720,8 @@ type CanvasExecutionEvents<TOutput> = {
701
720
  * @typeParam TInput - The input variables type
702
721
  * @typeParam TOutput - The output result type
703
722
  *
704
- * @fires poll - Emitted during async polling with current status and output (async executions only)
705
- * @fires success - Emitted when execution completes successfully with the final result
723
+ * @fires poll - Emitted during async polling with current status and output. Includes `requestId` from the polling request. (async executions only)
724
+ * @fires success - Emitted when execution completes successfully with the final result. Includes `requestId` from the final request.
706
725
  * @fires error - Emitted when execution fails (only if error listeners are registered, otherwise throws)
707
726
  * @fires statusChange - Emitted when execution status transitions to a new state
708
727
  *
@@ -734,6 +753,7 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
734
753
  private _resultPromise;
735
754
  private _stream;
736
755
  private _rawResultValue;
756
+ private _requestId;
737
757
  /**
738
758
  * Creates a new canvas execution instance.
739
759
  *
@@ -784,6 +804,48 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
784
804
  * @returns The execution ID.
785
805
  */
786
806
  get id(): string;
807
+ /**
808
+ * Gets the request ID from the `x-request-id` header of the execution creation request.
809
+ *
810
+ * This is the request ID from the initial POST /v2/chat/completions request that created
811
+ * the execution. Each API request has its own unique request ID.
812
+ *
813
+ * For async executions, different request IDs are available:
814
+ * - `execution.requestId` - ID from the execution creation request
815
+ * - `pollResult.requestId` - ID from each polling request (in poll events)
816
+ * - `result.requestId` - ID from the final successful polling request (in success events)
817
+ *
818
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
819
+ * @returns A promise that resolves to the request ID from the execution creation request.
820
+ *
821
+ * @example
822
+ * ```typescript
823
+ * const execution = await canvas.execute({ query: 'test' })
824
+ * const requestId = await execution.requestId
825
+ * console.log('Request ID:', requestId)
826
+ * ```
827
+ *
828
+ * @example Accessing different request IDs in async executions
829
+ * ```typescript
830
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
831
+ *
832
+ * // Request ID from execution creation
833
+ * const creationRequestId = await execution.requestId
834
+ *
835
+ * // Request IDs from polling
836
+ * execution.on('poll', (pollResult) => {
837
+ * console.log('Poll request ID:', pollResult.requestId)
838
+ * })
839
+ *
840
+ * // Request ID from final result
841
+ * execution.on('success', (result) => {
842
+ * console.log('Final request ID:', result.requestId)
843
+ * })
844
+ *
845
+ * execution.poll()
846
+ * ```
847
+ */
848
+ get requestId(): Promise<string>;
787
849
  /**
788
850
  * Gets the latest known status of the execution.
789
851
  *
@@ -871,9 +933,7 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
871
933
  *
872
934
  * @returns A promise or async generator depending on execution mode.
873
935
  */
874
- start(): Promise<CanvasExecutionResult<TParams, TOutput>> | AsyncGenerator<Partial<TOutput>, any, any> | Promise<AsyncGenerator<Partial<TOutput>, any, any>> | Promise<AsyncCompletionCreateResult & {
875
- headers: Record<string, string>;
876
- }>;
936
+ start(): Promise<CanvasExecutionResult<TParams, TOutput> | AsyncGenerator<Partial<TOutput>, any, any> | WithRequestId<AsyncCompletionCreateResult>>;
877
937
  /**
878
938
  * Gets the execution result. For async executions, automatically starts polling.
879
939
  * For sync executions, returns the result promise. For streams, returns the generator.
@@ -949,6 +1009,19 @@ declare class CanvasExecution<TParams extends ExecutionParams = SyncExecutionPar
949
1009
  * @returns A promise resolving to the processed variables object.
950
1010
  */
951
1011
  private resolveVariables;
1012
+ /**
1013
+ * Creates an execution on the server by making a POST request to /v2/chat/completions.
1014
+ * This method is shared between sync, async, and streaming execution modes.
1015
+ * Automatically sets the _requestId property from response headers.
1016
+ *
1017
+ * @template TResponse - The expected response type (sync, async, or stream).
1018
+ * @param resolvedVariables - The processed variables with uploaded files.
1019
+ * @param options - Execution options.
1020
+ * @param options.async - Whether to create an async execution.
1021
+ * @param options.stream - Whether to create a streaming execution.
1022
+ * @returns A promise resolving to the execution creation response or stream.
1023
+ */
1024
+ private create;
952
1025
  /**
953
1026
  * Initiates a synchronous execution that waits for the complete result.
954
1027
  * The result is validated against the output schema if provided.
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import * as z from 'zod';
4
4
  import z__default, { z as z$1, ZodError } from 'zod';
5
5
  import Emittery from 'emittery';
6
6
 
7
- const version = "2.3.1";
7
+ const version = "2.4.0";
8
8
 
9
9
  var __defProp$7 = Object.defineProperty;
10
10
  var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -299,13 +299,10 @@ class Stream {
299
299
  * @param iterator - A function that returns an AsyncIterator<Item>.
300
300
  * @param controller - The AbortController for this stream.
301
301
  */
302
- constructor(iterator, controller) {
302
+ constructor(iterator, controller, requestId) {
303
303
  this.iterator = iterator;
304
- /**
305
- * The AbortController associated with this stream.
306
- */
307
- __publicField$6(this, "controller");
308
304
  this.controller = controller;
305
+ this.requestId = requestId;
309
306
  }
310
307
  /**
311
308
  * Creates a Stream from a server-sent events (SSE) Response.
@@ -379,7 +376,8 @@ class Stream {
379
376
  controller.abort();
380
377
  }
381
378
  }
382
- return new Stream(iterator, controller);
379
+ const requestId = response.headers.get("x-request-id") || response.headers.get("request-id") || "";
380
+ return new Stream(iterator, controller, requestId);
383
381
  }
384
382
  /**
385
383
  * Creates a Stream from a newline-separated ReadableStream where each item is a JSON value.
@@ -719,31 +717,41 @@ var __publicField$5 = (obj, key, value) => {
719
717
  __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
720
718
  return value;
721
719
  };
722
- function tryGetResponseHeaders(response) {
720
+ function getRequestIdFromResponse(response) {
723
721
  try {
722
+ if (typeof response.headers.get === "function") {
723
+ return response.headers.get("x-request-id") || void 0;
724
+ }
724
725
  if (typeof response.headers.toJSON === "function") {
725
- return response.headers.toJSON();
726
+ const headers = response.headers.toJSON();
727
+ return headers["x-request-id"] || void 0;
726
728
  }
727
729
  if ("entries" in response.headers && typeof response.headers.entries === "function") {
728
- return Object.fromEntries(response.headers.entries());
730
+ for (const [key, value] of response.headers.entries()) {
731
+ if (key.toLowerCase() === "x-request-id") {
732
+ return value;
733
+ }
734
+ }
729
735
  }
730
736
  if (typeof response.headers.forEach === "function") {
731
- const headers = {};
737
+ let requestId;
732
738
  response.headers.forEach((value, key) => {
733
- headers[key] = value;
739
+ if (key.toLowerCase() === "x-request-id") {
740
+ requestId = value;
741
+ }
734
742
  });
735
- return headers;
743
+ return requestId;
736
744
  }
737
745
  if (response.headers && typeof response.headers[Symbol.iterator] === "function") {
738
- const headers = {};
739
746
  for (const [key, value] of response.headers) {
740
- headers[key] = value;
747
+ if (key.toLowerCase() === "x-request-id") {
748
+ return value;
749
+ }
741
750
  }
742
- return headers;
743
751
  }
744
- return {};
752
+ return void 0;
745
753
  } catch {
746
- return {};
754
+ return void 0;
747
755
  }
748
756
  }
749
757
  async function defaultParseResponse(props) {
@@ -760,7 +768,12 @@ async function defaultParseResponse(props) {
760
768
  if (isJSON) {
761
769
  const json = await response.json();
762
770
  debug("response", response.status, response.url, response.headers, json);
763
- return transformObjectFromSnakeCaseToCamelCase({ ...json, headers: tryGetResponseHeaders(response) }, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
771
+ const requestId = getRequestIdFromResponse(response);
772
+ const finalJson = { ...json };
773
+ if (requestId) {
774
+ finalJson.requestId = requestId;
775
+ }
776
+ return transformObjectFromSnakeCaseToCamelCase(finalJson, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
764
777
  }
765
778
  const text = await response.text();
766
779
  debug("response", response.status, response.url, response.headers, text);
@@ -831,6 +844,7 @@ class BaseClient {
831
844
  remainingRetries = options.maxRetries ?? this.maxRetries;
832
845
  }
833
846
  const { req, url, timeout } = this.buildRequest(options);
847
+ debug("request", `[${options.method}] ${options.path} ${JSON.stringify(options.body)}`);
834
848
  if (options.signal?.aborted) {
835
849
  throw new UserAbortError();
836
850
  }
@@ -1502,13 +1516,13 @@ function isSyncWorkflowResult(obj) {
1502
1516
  return "output" in obj;
1503
1517
  }
1504
1518
  function isAsyncWorkflowResult(obj) {
1505
- return "outputContent" in obj && "output" in obj.outputContent;
1519
+ return "outputContent" in obj && obj.outputContent && typeof obj.outputContent === "object" && "output" in obj.outputContent;
1506
1520
  }
1507
1521
  function isSyncCanvasResult(obj) {
1508
1522
  return "choices" in obj;
1509
1523
  }
1510
1524
  function isAsyncCanvasResult(obj) {
1511
- return "outputContent" in obj && "content" in obj.outputContent;
1525
+ return "outputContent" in obj && obj.outputContent && typeof obj.outputContent === "object" && "content" in obj.outputContent;
1512
1526
  }
1513
1527
  function getResultFromPollingResponse(response) {
1514
1528
  if (isSyncWorkflowResult(response)) {
@@ -1547,6 +1561,7 @@ class CanvasExecution extends Emittery {
1547
1561
  __publicField$2(this, "_resultPromise");
1548
1562
  __publicField$2(this, "_stream");
1549
1563
  __publicField$2(this, "_rawResultValue");
1564
+ __publicField$2(this, "_requestId");
1550
1565
  this._variables = variables;
1551
1566
  this._params = params;
1552
1567
  this._outputSchema = outputSchema;
@@ -1642,6 +1657,53 @@ class CanvasExecution extends Emittery {
1642
1657
  }
1643
1658
  return this._id;
1644
1659
  }
1660
+ /**
1661
+ * Gets the request ID from the `x-request-id` header of the execution creation request.
1662
+ *
1663
+ * This is the request ID from the initial POST /v2/chat/completions request that created
1664
+ * the execution. Each API request has its own unique request ID.
1665
+ *
1666
+ * For async executions, different request IDs are available:
1667
+ * - `execution.requestId` - ID from the execution creation request
1668
+ * - `pollResult.requestId` - ID from each polling request (in poll events)
1669
+ * - `result.requestId` - ID from the final successful polling request (in success events)
1670
+ *
1671
+ * @throws {ExecutionNotStartedError} If the execution has not been started yet.
1672
+ * @returns A promise that resolves to the request ID from the execution creation request.
1673
+ *
1674
+ * @example
1675
+ * ```typescript
1676
+ * const execution = await canvas.execute({ query: 'test' })
1677
+ * const requestId = await execution.requestId
1678
+ * console.log('Request ID:', requestId)
1679
+ * ```
1680
+ *
1681
+ * @example Accessing different request IDs in async executions
1682
+ * ```typescript
1683
+ * const execution = await canvas.execute({ query: 'test' }, { async: true })
1684
+ *
1685
+ * // Request ID from execution creation
1686
+ * const creationRequestId = await execution.requestId
1687
+ *
1688
+ * // Request IDs from polling
1689
+ * execution.on('poll', (pollResult) => {
1690
+ * console.log('Poll request ID:', pollResult.requestId)
1691
+ * })
1692
+ *
1693
+ * // Request ID from final result
1694
+ * execution.on('success', (result) => {
1695
+ * console.log('Final request ID:', result.requestId)
1696
+ * })
1697
+ *
1698
+ * execution.poll()
1699
+ * ```
1700
+ */
1701
+ get requestId() {
1702
+ if (!this._requestId) {
1703
+ throw new ExecutionNotStartedError();
1704
+ }
1705
+ return this._requestId;
1706
+ }
1645
1707
  /**
1646
1708
  * Gets the latest known status of the execution.
1647
1709
  *
@@ -1766,7 +1828,13 @@ class CanvasExecution extends Emittery {
1766
1828
  *
1767
1829
  * @returns A promise or async generator depending on execution mode.
1768
1830
  */
1769
- start() {
1831
+ async start() {
1832
+ if (this._params.applicationId && !this._params.async) {
1833
+ console.warn("[Tela SDK - WARNING] ApplicationId was provided, but async mode was not enabled. This will create a task, and tasks are always async. ");
1834
+ 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.");
1835
+ console.warn("[Tela SDK - WARNING] To disable these warnings, you can enable async mode explicitly.");
1836
+ this._params.async = true;
1837
+ }
1770
1838
  if (this._resultPromise || this._stream) {
1771
1839
  return this._resultPromise ?? this._stream;
1772
1840
  }
@@ -1785,15 +1853,19 @@ class CanvasExecution extends Emittery {
1785
1853
  * @returns The execution result as a promise or async generator.
1786
1854
  */
1787
1855
  get result() {
1856
+ if (this._params.applicationId && !this._params.canvasId) {
1857
+ const message = "Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.";
1858
+ return Promise.reject(new InvalidExecutionModeError(message));
1859
+ }
1788
1860
  if (this.isSync) {
1789
1861
  if (!this._resultPromise) {
1790
- throw new ExecutionNotStartedError();
1862
+ return Promise.reject(new ExecutionNotStartedError());
1791
1863
  }
1792
1864
  return this._resultPromise;
1793
1865
  }
1794
1866
  if (this.isStream) {
1795
1867
  if (!this._stream) {
1796
- throw new ExecutionNotStartedError();
1868
+ return Promise.reject(new ExecutionNotStartedError());
1797
1869
  }
1798
1870
  return this._stream;
1799
1871
  }
@@ -1859,6 +1931,9 @@ class CanvasExecution extends Emittery {
1859
1931
  * ```
1860
1932
  */
1861
1933
  poll() {
1934
+ if (this._params.applicationId && !this._params.canvasId) {
1935
+ throw new InvalidExecutionModeError("Tasks are not fully supported yet. You can create them, but cannot obtain the results or poll for their status.");
1936
+ }
1862
1937
  if (!this.isAsync) {
1863
1938
  throw new InvalidExecutionModeError("Polling is only supported for async executions");
1864
1939
  }
@@ -1926,31 +2001,48 @@ class CanvasExecution extends Emittery {
1926
2001
  return variables;
1927
2002
  }
1928
2003
  /**
1929
- * Initiates a synchronous execution that waits for the complete result.
1930
- * The result is validated against the output schema if provided.
1931
- *
1932
- * @returns A promise resolving to the parsed execution result.
2004
+ * Creates an execution on the server by making a POST request to /v2/chat/completions.
2005
+ * This method is shared between sync, async, and streaming execution modes.
2006
+ * Automatically sets the _requestId property from response headers.
2007
+ *
2008
+ * @template TResponse - The expected response type (sync, async, or stream).
2009
+ * @param resolvedVariables - The processed variables with uploaded files.
2010
+ * @param options - Execution options.
2011
+ * @param options.async - Whether to create an async execution.
2012
+ * @param options.stream - Whether to create a streaming execution.
2013
+ * @returns A promise resolving to the execution creation response or stream.
1933
2014
  */
1934
- async startSync() {
1935
- const resolvedVariables = await this.resolveVariables();
2015
+ async create(resolvedVariables, options = {}) {
1936
2016
  const body = {
1937
- async: this._params.async ?? false,
1938
- stream: false,
2017
+ async: options.async ?? false,
2018
+ stream: options.stream ?? false,
1939
2019
  ...this.baseBody,
1940
2020
  variables: resolvedVariables
1941
2021
  };
1942
- this._resultPromise = this._client.post("/v2/chat/completions", {
2022
+ const responsePromise = this._client.post("/v2/chat/completions", {
1943
2023
  body,
1944
- stream: false,
2024
+ stream: options.stream ?? false,
1945
2025
  signal: this._abortController.signal
1946
- }).then((response) => {
2026
+ });
2027
+ this._requestId = responsePromise.then((response) => response?.requestId || "").catch(() => "");
2028
+ return await responsePromise;
2029
+ }
2030
+ /**
2031
+ * Initiates a synchronous execution that waits for the complete result.
2032
+ * The result is validated against the output schema if provided.
2033
+ *
2034
+ * @returns A promise resolving to the parsed execution result.
2035
+ */
2036
+ async startSync() {
2037
+ const resolvedVariables = await this.resolveVariables();
2038
+ this._resultPromise = this.create(resolvedVariables, { async: false }).then((response) => {
1947
2039
  this._id = response.id;
1948
2040
  this._rawResultValue = response;
1949
2041
  return { content: getResultFromPollingResponse(response), response };
1950
2042
  }).then(({ content, response }) => {
1951
2043
  const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType) ? content : this._outputSchema.parse(content);
1952
2044
  this.status = "succeeded";
1953
- this.emit("success", { ...validatedContent, headers: response?.headers ?? {} });
2045
+ this.emit("success", { ...validatedContent, requestId: response?.requestId });
1954
2046
  return validatedContent;
1955
2047
  }).catch((error) => {
1956
2048
  this.status = "failed";
@@ -1970,17 +2062,7 @@ class CanvasExecution extends Emittery {
1970
2062
  */
1971
2063
  async startAsync() {
1972
2064
  const resolvedVariables = await this.resolveVariables();
1973
- const body = {
1974
- async: true,
1975
- stream: false,
1976
- ...this.baseBody,
1977
- variables: resolvedVariables
1978
- };
1979
- return await this._client.post("/v2/chat/completions", {
1980
- body,
1981
- stream: false,
1982
- signal: this._abortController.signal
1983
- }).then((response) => {
2065
+ return await this.create(resolvedVariables, { async: true }).then((response) => {
1984
2066
  this._id = response.id;
1985
2067
  this.status = response.status;
1986
2068
  this.emit("poll", {
@@ -1988,7 +2070,7 @@ class CanvasExecution extends Emittery {
1988
2070
  status: response.status,
1989
2071
  outputContent: response.output_content,
1990
2072
  rawOutput: response.raw_output,
1991
- headers: response.headers
2073
+ requestId: response.requestId
1992
2074
  });
1993
2075
  return response;
1994
2076
  });
@@ -2000,16 +2082,7 @@ class CanvasExecution extends Emittery {
2000
2082
  */
2001
2083
  async startStream() {
2002
2084
  const resolvedVariables = await this.resolveVariables();
2003
- const body = {
2004
- ...this.baseBody,
2005
- stream: true,
2006
- variables: resolvedVariables
2007
- };
2008
- this._stream = await this._client.post("/v2/chat/completions", {
2009
- body,
2010
- stream: true,
2011
- signal: this._abortController.signal
2012
- });
2085
+ this._stream = await this.create(resolvedVariables, { stream: true });
2013
2086
  this.status = "streaming";
2014
2087
  return this._stream;
2015
2088
  }
@@ -2043,6 +2116,7 @@ class CanvasExecution extends Emittery {
2043
2116
  this.emit("poll", response);
2044
2117
  if (response.status === "failed") {
2045
2118
  const error = new ExecutionFailedError(response.rawOutput);
2119
+ this.cancel();
2046
2120
  this.emit("error", error);
2047
2121
  throw error;
2048
2122
  }
@@ -2053,7 +2127,7 @@ class CanvasExecution extends Emittery {
2053
2127
  };
2054
2128
  }
2055
2129
  this._rawResultValue = response;
2056
- this.emit("success", { ...getResultFromPollingResponse(response), headers: response?.headers ?? {} });
2130
+ this.emit("success", { ...getResultFromPollingResponse(response), requestId: response?.requestId });
2057
2131
  return {
2058
2132
  done: response.status === "succeeded",
2059
2133
  value: getResultFromPollingResponse(response)
@@ -2289,8 +2363,9 @@ class Canvas {
2289
2363
  }
2290
2364
  return new Canvas({
2291
2365
  id: promptVersion.promptId,
2292
- name: promptVersion.title,
2293
2366
  versionId: promptVersion.id,
2367
+ applicationId: applicationId ?? void 0,
2368
+ name: promptVersion.title,
2294
2369
  input,
2295
2370
  output,
2296
2371
  client,
@@ -2376,11 +2451,10 @@ class Canvas {
2376
2451
  }
2377
2452
  execute(variables, params) {
2378
2453
  const parsedInput = this.parseVariables(variables);
2454
+ const idObject = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, canvasId: this._id };
2379
2455
  const fullParams = {
2380
2456
  ...params ?? { async: false },
2381
- versionId: this._versionId,
2382
- canvasId: this._id,
2383
- applicationId: this._applicationId
2457
+ ...idObject
2384
2458
  };
2385
2459
  const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client);
2386
2460
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-sdk-js",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/meistrari/tela-sdk-js.git"