@meistrari/tela-sdk-js 2.4.3 → 2.6.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 +1926 -384
- package/dist/index.d.cts +2374 -532
- package/dist/index.d.mts +2374 -532
- package/dist/index.d.ts +2374 -532
- package/dist/index.mjs +1930 -392
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import * as changeCase from 'change-case';
|
|
2
2
|
import { minimatch } from 'minimatch';
|
|
3
|
-
import
|
|
4
|
-
import z__default, { z as z$1, ZodError } from 'zod';
|
|
3
|
+
import z, { z as z$1, ZodError } from 'zod';
|
|
5
4
|
import Emittery from 'emittery';
|
|
6
5
|
|
|
7
|
-
const version = "2.
|
|
6
|
+
const version = "2.6.0";
|
|
8
7
|
|
|
9
|
-
var __defProp$
|
|
10
|
-
var __defNormalProp$
|
|
11
|
-
var __publicField$
|
|
12
|
-
__defNormalProp$
|
|
8
|
+
var __defProp$a = Object.defineProperty;
|
|
9
|
+
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __publicField$a = (obj, key, value) => {
|
|
11
|
+
__defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
13
12
|
return value;
|
|
14
13
|
};
|
|
15
14
|
class TelaError extends Error {
|
|
@@ -37,7 +36,7 @@ class InvalidFileURL extends TelaError {
|
|
|
37
36
|
class FileUploadError extends TelaError {
|
|
38
37
|
constructor(message, statusCode) {
|
|
39
38
|
super(`Failed to upload file: ${message} (Status code: ${statusCode})`);
|
|
40
|
-
__publicField$
|
|
39
|
+
__publicField$a(this, "statusCode");
|
|
41
40
|
this.statusCode = statusCode;
|
|
42
41
|
}
|
|
43
42
|
}
|
|
@@ -54,16 +53,30 @@ class InvalidExecutionModeError extends TelaError {
|
|
|
54
53
|
class ExecutionFailedError extends TelaError {
|
|
55
54
|
constructor(rawOutput) {
|
|
56
55
|
super(`Execution failed: ${JSON.stringify(rawOutput)}`);
|
|
57
|
-
__publicField$
|
|
56
|
+
__publicField$a(this, "rawOutput");
|
|
58
57
|
this.rawOutput = rawOutput;
|
|
59
58
|
}
|
|
60
59
|
}
|
|
60
|
+
class TaskFailedError extends TelaError {
|
|
61
|
+
constructor(rawTask, message, cause) {
|
|
62
|
+
super(`Task failed: ${JSON.stringify(rawTask)}`, { cause });
|
|
63
|
+
__publicField$a(this, "rawTask");
|
|
64
|
+
this.rawTask = rawTask;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
class BatchExecutionFailedError extends TelaError {
|
|
68
|
+
constructor(rawResponse) {
|
|
69
|
+
super(`Batch execution failed: ${JSON.stringify(rawResponse)}`);
|
|
70
|
+
__publicField$a(this, "rawResponse");
|
|
71
|
+
this.rawResponse = rawResponse;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
61
74
|
class APIError extends TelaError {
|
|
62
75
|
constructor(statusCode, error, _message) {
|
|
63
76
|
const message = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : _message;
|
|
64
77
|
super(message);
|
|
65
|
-
__publicField$
|
|
66
|
-
__publicField$
|
|
78
|
+
__publicField$a(this, "statusCode");
|
|
79
|
+
__publicField$a(this, "error");
|
|
67
80
|
this.statusCode = statusCode;
|
|
68
81
|
this.error = error;
|
|
69
82
|
}
|
|
@@ -105,7 +118,7 @@ class APIError extends TelaError {
|
|
|
105
118
|
class UserAbortError extends APIError {
|
|
106
119
|
constructor({ message } = {}) {
|
|
107
120
|
super(void 0, void 0, message || "User aborted.");
|
|
108
|
-
__publicField$
|
|
121
|
+
__publicField$a(this, "statusCode");
|
|
109
122
|
}
|
|
110
123
|
}
|
|
111
124
|
class ConnectionError extends APIError {
|
|
@@ -114,7 +127,7 @@ class ConnectionError extends APIError {
|
|
|
114
127
|
cause
|
|
115
128
|
}) {
|
|
116
129
|
super(void 0, void 0, message || "Connection error.");
|
|
117
|
-
__publicField$
|
|
130
|
+
__publicField$a(this, "statusCode");
|
|
118
131
|
if (cause)
|
|
119
132
|
this.cause = cause;
|
|
120
133
|
}
|
|
@@ -124,57 +137,57 @@ class ConnectionTimeout extends APIError {
|
|
|
124
137
|
message
|
|
125
138
|
} = {}) {
|
|
126
139
|
super(void 0, void 0, message || "Request timed out.");
|
|
127
|
-
__publicField$
|
|
140
|
+
__publicField$a(this, "statusCode");
|
|
128
141
|
}
|
|
129
142
|
}
|
|
130
143
|
class BadRequestError extends APIError {
|
|
131
144
|
constructor() {
|
|
132
145
|
super(...arguments);
|
|
133
|
-
__publicField$
|
|
146
|
+
__publicField$a(this, "statusCode", 400);
|
|
134
147
|
}
|
|
135
148
|
// todo: handle validation errors from zod/typebox
|
|
136
149
|
}
|
|
137
150
|
class AuthenticationError extends APIError {
|
|
138
151
|
constructor() {
|
|
139
152
|
super(...arguments);
|
|
140
|
-
__publicField$
|
|
153
|
+
__publicField$a(this, "statusCode", 401);
|
|
141
154
|
}
|
|
142
155
|
}
|
|
143
156
|
class AuthorizationError extends APIError {
|
|
144
157
|
constructor() {
|
|
145
158
|
super(...arguments);
|
|
146
|
-
__publicField$
|
|
159
|
+
__publicField$a(this, "statusCode", 403);
|
|
147
160
|
}
|
|
148
161
|
}
|
|
149
162
|
class NotFoundError extends APIError {
|
|
150
163
|
constructor() {
|
|
151
164
|
super(...arguments);
|
|
152
|
-
__publicField$
|
|
165
|
+
__publicField$a(this, "statusCode", 404);
|
|
153
166
|
}
|
|
154
167
|
}
|
|
155
168
|
class ConflictError extends APIError {
|
|
156
169
|
constructor() {
|
|
157
170
|
super(...arguments);
|
|
158
|
-
__publicField$
|
|
171
|
+
__publicField$a(this, "statusCode", 409);
|
|
159
172
|
}
|
|
160
173
|
}
|
|
161
174
|
class UnprocessableEntityError extends APIError {
|
|
162
175
|
constructor() {
|
|
163
176
|
super(...arguments);
|
|
164
177
|
// todo: check if tela returns 400 or 422 for zod errors
|
|
165
|
-
__publicField$
|
|
178
|
+
__publicField$a(this, "statusCode", 422);
|
|
166
179
|
}
|
|
167
180
|
}
|
|
168
181
|
class RateLimitError extends APIError {
|
|
169
182
|
constructor() {
|
|
170
183
|
super(...arguments);
|
|
171
|
-
__publicField$
|
|
184
|
+
__publicField$a(this, "statusCode", 429);
|
|
172
185
|
}
|
|
173
186
|
}
|
|
174
187
|
class InternalServerError extends APIError {
|
|
175
188
|
constructor() {
|
|
176
189
|
super(...arguments);
|
|
177
|
-
__publicField$
|
|
190
|
+
__publicField$a(this, "statusCode", 500);
|
|
178
191
|
}
|
|
179
192
|
}
|
|
180
193
|
function toError(err) {
|
|
@@ -285,11 +298,38 @@ function transformObjectFromSnakeCaseToCamelCase(obj, exclusions = []) {
|
|
|
285
298
|
}
|
|
286
299
|
return result;
|
|
287
300
|
}
|
|
301
|
+
const DURATION_REGEX = /(?<amount>\d+)(?<unit>[smhd])/;
|
|
302
|
+
const DURATION_UNITS = {
|
|
303
|
+
s: 1e3,
|
|
304
|
+
// 1 second in milliseconds
|
|
305
|
+
m: 6e4,
|
|
306
|
+
// 1 minute in milliseconds
|
|
307
|
+
h: 36e5,
|
|
308
|
+
// 1 hour in milliseconds
|
|
309
|
+
d: 864e5
|
|
310
|
+
// 1 day in milliseconds
|
|
311
|
+
};
|
|
312
|
+
function transformDurationToMs(durationStr) {
|
|
313
|
+
if (!durationStr) {
|
|
314
|
+
return void 0;
|
|
315
|
+
}
|
|
316
|
+
if (typeof durationStr === "number") {
|
|
317
|
+
return durationStr;
|
|
318
|
+
}
|
|
319
|
+
const match = durationStr.match(DURATION_REGEX);
|
|
320
|
+
const amount = match?.groups?.amount;
|
|
321
|
+
const unit = match?.groups?.unit;
|
|
322
|
+
const multiplier = DURATION_UNITS[unit];
|
|
323
|
+
if (!amount || Number.isNaN(Number.parseInt(amount)) || !multiplier) {
|
|
324
|
+
return void 0;
|
|
325
|
+
}
|
|
326
|
+
return Number.parseInt(amount) * multiplier;
|
|
327
|
+
}
|
|
288
328
|
|
|
289
|
-
var __defProp$
|
|
290
|
-
var __defNormalProp$
|
|
291
|
-
var __publicField$
|
|
292
|
-
__defNormalProp$
|
|
329
|
+
var __defProp$9 = Object.defineProperty;
|
|
330
|
+
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
331
|
+
var __publicField$9 = (obj, key, value) => {
|
|
332
|
+
__defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
293
333
|
return value;
|
|
294
334
|
};
|
|
295
335
|
class Stream {
|
|
@@ -553,9 +593,9 @@ function findDoubleNewlineIndex(buffer) {
|
|
|
553
593
|
}
|
|
554
594
|
class SSEDecoder {
|
|
555
595
|
constructor() {
|
|
556
|
-
__publicField$
|
|
557
|
-
__publicField$
|
|
558
|
-
__publicField$
|
|
596
|
+
__publicField$9(this, "data");
|
|
597
|
+
__publicField$9(this, "event");
|
|
598
|
+
__publicField$9(this, "chunks");
|
|
559
599
|
this.event = null;
|
|
560
600
|
this.data = [];
|
|
561
601
|
this.chunks = [];
|
|
@@ -596,9 +636,9 @@ class SSEDecoder {
|
|
|
596
636
|
const _LineDecoder = class _LineDecoder {
|
|
597
637
|
// TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
|
|
598
638
|
constructor() {
|
|
599
|
-
__publicField$
|
|
600
|
-
__publicField$
|
|
601
|
-
__publicField$
|
|
639
|
+
__publicField$9(this, "buffer");
|
|
640
|
+
__publicField$9(this, "trailingCR");
|
|
641
|
+
__publicField$9(this, "textDecoder");
|
|
602
642
|
this.buffer = [];
|
|
603
643
|
this.trailingCR = false;
|
|
604
644
|
}
|
|
@@ -673,8 +713,8 @@ const _LineDecoder = class _LineDecoder {
|
|
|
673
713
|
}
|
|
674
714
|
};
|
|
675
715
|
// prettier-ignore
|
|
676
|
-
__publicField$
|
|
677
|
-
__publicField$
|
|
716
|
+
__publicField$9(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
|
|
717
|
+
__publicField$9(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
|
|
678
718
|
let LineDecoder = _LineDecoder;
|
|
679
719
|
function partition(str, delimiter) {
|
|
680
720
|
const index = str.indexOf(delimiter);
|
|
@@ -711,10 +751,10 @@ function readableStreamAsyncIterable(stream) {
|
|
|
711
751
|
};
|
|
712
752
|
}
|
|
713
753
|
|
|
714
|
-
var __defProp$
|
|
715
|
-
var __defNormalProp$
|
|
716
|
-
var __publicField$
|
|
717
|
-
__defNormalProp$
|
|
754
|
+
var __defProp$8 = Object.defineProperty;
|
|
755
|
+
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
756
|
+
var __publicField$8 = (obj, key, value) => {
|
|
757
|
+
__defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
718
758
|
return value;
|
|
719
759
|
};
|
|
720
760
|
function getRequestIdFromResponse(response) {
|
|
@@ -756,6 +796,7 @@ function getRequestIdFromResponse(response) {
|
|
|
756
796
|
}
|
|
757
797
|
async function defaultParseResponse(props) {
|
|
758
798
|
const { response } = props;
|
|
799
|
+
const { transformCase = true } = props.options;
|
|
759
800
|
if (props.options.stream) {
|
|
760
801
|
debug("response", response.status, response.url, response.headers, response.body);
|
|
761
802
|
return Stream.fromSSEResponse(response, props.controller);
|
|
@@ -769,22 +810,30 @@ async function defaultParseResponse(props) {
|
|
|
769
810
|
const json = await response.json();
|
|
770
811
|
debug("response", response.status, response.url, response.headers, json);
|
|
771
812
|
const requestId = getRequestIdFromResponse(response);
|
|
772
|
-
const finalJson = { ...json };
|
|
773
813
|
if (requestId) {
|
|
774
|
-
|
|
814
|
+
json.requestId = requestId;
|
|
775
815
|
}
|
|
776
|
-
return transformObjectFromSnakeCaseToCamelCase(
|
|
816
|
+
return transformCase ? transformObjectFromSnakeCaseToCamelCase(json, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : json;
|
|
777
817
|
}
|
|
778
818
|
const text = await response.text();
|
|
779
819
|
debug("response", response.status, response.url, response.headers, text);
|
|
780
820
|
return text;
|
|
781
821
|
}
|
|
822
|
+
function transformObjectCase(obj, transformCase) {
|
|
823
|
+
if (!obj) {
|
|
824
|
+
return obj;
|
|
825
|
+
}
|
|
826
|
+
if (transformCase) {
|
|
827
|
+
return transformObjectFromCamelCaseToSnakeCase(obj, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
|
|
828
|
+
}
|
|
829
|
+
return obj;
|
|
830
|
+
}
|
|
782
831
|
class BaseClient {
|
|
783
832
|
constructor({ baseURL, maxRetries = 5, timeout = 0 }) {
|
|
784
|
-
__publicField$
|
|
785
|
-
__publicField$
|
|
786
|
-
__publicField$
|
|
787
|
-
__publicField$
|
|
833
|
+
__publicField$8(this, "baseURL");
|
|
834
|
+
__publicField$8(this, "maxRetries");
|
|
835
|
+
__publicField$8(this, "timeout");
|
|
836
|
+
__publicField$8(this, "fetch");
|
|
788
837
|
this.baseURL = baseURL;
|
|
789
838
|
this.maxRetries = validateMaxRetries(maxRetries);
|
|
790
839
|
this.timeout = validateTimeout(timeout);
|
|
@@ -823,10 +872,11 @@ class BaseClient {
|
|
|
823
872
|
return this.methodRequest("DELETE", path, opts);
|
|
824
873
|
}
|
|
825
874
|
async methodRequest(method, path, opts) {
|
|
875
|
+
const { transformCase = true } = opts ?? {};
|
|
826
876
|
const headers = this.createHeaders();
|
|
827
877
|
debug("methodRequest", method, path, opts);
|
|
828
|
-
const transformedQuery = opts?.query
|
|
829
|
-
const transformedBody = opts?.body
|
|
878
|
+
const transformedQuery = transformObjectCase(opts?.query, transformCase);
|
|
879
|
+
const transformedBody = transformObjectCase(opts?.body, transformCase);
|
|
830
880
|
const { response, options, controller } = await this.request({
|
|
831
881
|
method,
|
|
832
882
|
path,
|
|
@@ -1007,6 +1057,9 @@ class BaseClient {
|
|
|
1007
1057
|
if (value === null) {
|
|
1008
1058
|
return `${encodeURIComponent(key)}=`;
|
|
1009
1059
|
}
|
|
1060
|
+
if (Array.isArray(value)) {
|
|
1061
|
+
return value.map((item) => `${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`).join("&");
|
|
1062
|
+
}
|
|
1010
1063
|
throw new TelaError(
|
|
1011
1064
|
`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.`
|
|
1012
1065
|
);
|
|
@@ -1060,22 +1113,22 @@ async function getStreamSize(stream) {
|
|
|
1060
1113
|
return size;
|
|
1061
1114
|
}
|
|
1062
1115
|
|
|
1063
|
-
var __defProp$
|
|
1064
|
-
var __defNormalProp$
|
|
1065
|
-
var __publicField$
|
|
1066
|
-
__defNormalProp$
|
|
1116
|
+
var __defProp$7 = Object.defineProperty;
|
|
1117
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1118
|
+
var __publicField$7 = (obj, key, value) => {
|
|
1119
|
+
__defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1067
1120
|
return value;
|
|
1068
1121
|
};
|
|
1069
1122
|
function TelaFileSchema() {
|
|
1070
|
-
return
|
|
1123
|
+
return z.custom((value) => value instanceof TelaFile, { message: "Value must be an instance of TelaFile" }).meta({ isTelaFile: true });
|
|
1071
1124
|
}
|
|
1072
1125
|
class TelaFile {
|
|
1073
1126
|
constructor(file, options = {}) {
|
|
1074
|
-
__publicField$
|
|
1075
|
-
__publicField$
|
|
1076
|
-
__publicField$
|
|
1077
|
-
__publicField$
|
|
1078
|
-
__publicField$
|
|
1127
|
+
__publicField$7(this, "_file");
|
|
1128
|
+
__publicField$7(this, "_options");
|
|
1129
|
+
__publicField$7(this, "_size", null);
|
|
1130
|
+
__publicField$7(this, "_mimeType");
|
|
1131
|
+
__publicField$7(this, "_name");
|
|
1079
1132
|
this._file = file;
|
|
1080
1133
|
if (file instanceof File || file instanceof Blob) {
|
|
1081
1134
|
this._size = file.size;
|
|
@@ -1221,7 +1274,17 @@ class TelaFile {
|
|
|
1221
1274
|
return url.startsWith("vault://");
|
|
1222
1275
|
}
|
|
1223
1276
|
}
|
|
1277
|
+
function isTelaFile(obj) {
|
|
1278
|
+
return obj instanceof TelaFile;
|
|
1279
|
+
}
|
|
1280
|
+
function isTelaFileArray(obj) {
|
|
1281
|
+
return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
|
|
1282
|
+
}
|
|
1224
1283
|
|
|
1284
|
+
const zod = {
|
|
1285
|
+
...z$1,
|
|
1286
|
+
file: TelaFileSchema
|
|
1287
|
+
};
|
|
1225
1288
|
function compareSchemas(clientSchema, serverSchema, path = "$") {
|
|
1226
1289
|
const mismatches = [];
|
|
1227
1290
|
if (clientSchema.type !== serverSchema.type) {
|
|
@@ -1378,11 +1441,172 @@ function validateInputSchema(clientSchema, serverVariables) {
|
|
|
1378
1441
|
function validateOutputSchema(clientSchema, serverSchema) {
|
|
1379
1442
|
return compareSchemas(clientSchema, serverSchema);
|
|
1380
1443
|
}
|
|
1444
|
+
function validateSchemas(resource, input, output, promptVersion) {
|
|
1445
|
+
const canvasIdentifier = `${promptVersion.title} (${promptVersion.promptId})`;
|
|
1446
|
+
if (input instanceof z$1.ZodType) {
|
|
1447
|
+
try {
|
|
1448
|
+
const inputSchema = z$1.toJSONSchema(input, { unrepresentable: "any" });
|
|
1449
|
+
const mismatches = validateInputSchema(inputSchema, promptVersion.variables);
|
|
1450
|
+
if (mismatches.length === 0) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
console.warn(
|
|
1454
|
+
`[Tela SDK - ${resource} Input Validation] Input schema mismatches for ${resource} "${canvasIdentifier}":`
|
|
1455
|
+
);
|
|
1456
|
+
for (const mismatch of mismatches) {
|
|
1457
|
+
console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
|
|
1458
|
+
}
|
|
1459
|
+
} catch (error) {
|
|
1460
|
+
console.warn(
|
|
1461
|
+
`[Tela SDK - ${resource} Input Validation] Failed to validate input schema for ${resource} "${canvasIdentifier}":`,
|
|
1462
|
+
error
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if (output instanceof z$1.ZodType) {
|
|
1467
|
+
try {
|
|
1468
|
+
const outputSchema = z$1.toJSONSchema(output);
|
|
1469
|
+
const serverOutput = promptVersion.configuration.structuredOutput;
|
|
1470
|
+
if (!serverOutput.enabled) {
|
|
1471
|
+
console.warn(
|
|
1472
|
+
`[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.`
|
|
1473
|
+
);
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
const mismatches = validateOutputSchema(outputSchema, serverOutput.schema);
|
|
1477
|
+
if (mismatches.length === 0) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
console.warn(
|
|
1481
|
+
`[Tela SDK - ${resource} Output Validation] Output schema mismatches for ${resource} "${canvasIdentifier}":`
|
|
1482
|
+
);
|
|
1483
|
+
for (const mismatch of mismatches) {
|
|
1484
|
+
console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
|
|
1485
|
+
}
|
|
1486
|
+
} catch (error) {
|
|
1487
|
+
console.warn(
|
|
1488
|
+
`[Tela SDK - ${resource} Output Validation] Failed to validate output schema for ${resource} "${canvasIdentifier}":`,
|
|
1489
|
+
error
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1381
1494
|
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1495
|
+
async function calculateSha256sum(content) {
|
|
1496
|
+
const stream = content instanceof File || content instanceof Blob ? content.stream() : content;
|
|
1497
|
+
const reader = stream.getReader();
|
|
1498
|
+
try {
|
|
1499
|
+
const { createHash } = await import('node:crypto');
|
|
1500
|
+
const hash = createHash("sha256");
|
|
1501
|
+
while (true) {
|
|
1502
|
+
const { done, value } = await reader.read();
|
|
1503
|
+
if (done)
|
|
1504
|
+
break;
|
|
1505
|
+
hash.update(value);
|
|
1506
|
+
}
|
|
1507
|
+
return hash.digest("hex");
|
|
1508
|
+
} catch {
|
|
1509
|
+
const chunks = [];
|
|
1510
|
+
while (true) {
|
|
1511
|
+
const { done, value } = await reader.read();
|
|
1512
|
+
if (done)
|
|
1513
|
+
break;
|
|
1514
|
+
chunks.push(value);
|
|
1515
|
+
}
|
|
1516
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
1517
|
+
const buffer = new Uint8Array(totalLength);
|
|
1518
|
+
let offset = 0;
|
|
1519
|
+
for (const chunk of chunks) {
|
|
1520
|
+
buffer.set(chunk, offset);
|
|
1521
|
+
offset += chunk.length;
|
|
1522
|
+
}
|
|
1523
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
|
|
1524
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1525
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1526
|
+
return hashHex;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
async function uploadFile(file, client) {
|
|
1531
|
+
let content = await file.getUploadableContent();
|
|
1532
|
+
let sha256sumStream;
|
|
1533
|
+
if (typeof content === "string") {
|
|
1534
|
+
return { fileUrl: content, options: file.options };
|
|
1535
|
+
}
|
|
1536
|
+
const filename = file.name ?? void 0;
|
|
1537
|
+
const fileType = file.type ?? void 0;
|
|
1538
|
+
const contentLength = file.size ?? void 0;
|
|
1539
|
+
if (content instanceof ReadableStream) {
|
|
1540
|
+
const [hashStream, contentStream] = content.tee();
|
|
1541
|
+
content = contentStream;
|
|
1542
|
+
sha256sumStream = hashStream;
|
|
1543
|
+
}
|
|
1544
|
+
const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
|
|
1545
|
+
const { id, uploadUrl } = await client.post("/_services/vault/files", {
|
|
1546
|
+
body: {
|
|
1547
|
+
fileName: filename,
|
|
1548
|
+
mimeType: fileType,
|
|
1549
|
+
size: contentLength ?? void 0,
|
|
1550
|
+
sha256sum
|
|
1551
|
+
},
|
|
1552
|
+
transformCase: false
|
|
1553
|
+
});
|
|
1554
|
+
if (content instanceof ReadableStream && typeof Bun !== "undefined") {
|
|
1555
|
+
console.warn(
|
|
1556
|
+
"[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
|
|
1557
|
+
{ fileName: filename, fileSize: contentLength }
|
|
1558
|
+
);
|
|
1559
|
+
const chunks = [];
|
|
1560
|
+
const reader = content.getReader();
|
|
1561
|
+
while (true) {
|
|
1562
|
+
const { done, value } = await reader.read();
|
|
1563
|
+
if (done)
|
|
1564
|
+
break;
|
|
1565
|
+
chunks.push(value);
|
|
1566
|
+
}
|
|
1567
|
+
content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
|
|
1568
|
+
}
|
|
1569
|
+
const request = new Request(uploadUrl, {
|
|
1570
|
+
method: "PUT",
|
|
1571
|
+
body: content,
|
|
1572
|
+
headers: {
|
|
1573
|
+
"Content-Type": fileType ?? "application/octet-stream",
|
|
1574
|
+
...file.size ? { "Content-Length": file.size.toString() } : {}
|
|
1575
|
+
}
|
|
1576
|
+
});
|
|
1577
|
+
const uploadResponse = await fetch(request);
|
|
1578
|
+
if (!uploadResponse.ok) {
|
|
1579
|
+
throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
|
|
1580
|
+
}
|
|
1581
|
+
return { fileUrl: `vault://${id}`, options: file.options };
|
|
1582
|
+
}
|
|
1583
|
+
async function uploadFiles(files, client) {
|
|
1584
|
+
const uploadPromises = files.map((file) => uploadFile(file, client));
|
|
1585
|
+
return Promise.all(uploadPromises);
|
|
1586
|
+
}
|
|
1587
|
+
async function downloadFile(vaultReference, client) {
|
|
1588
|
+
const vaultId = vaultReference.replace("vault://", "");
|
|
1589
|
+
const response = await client.get(`/_services/vault/files/${vaultId}`);
|
|
1590
|
+
return fetch(response.url).then((res) => res.blob());
|
|
1591
|
+
}
|
|
1592
|
+
async function streamFile(vaultReference, client) {
|
|
1593
|
+
const vaultId = vaultReference.replace("vault://", "");
|
|
1594
|
+
const response = await client.get(`/_services/vault/files/${vaultId}`);
|
|
1595
|
+
return fetch(response.url).then((res) => {
|
|
1596
|
+
if (!res.ok) {
|
|
1597
|
+
throw new Error("Failed to stream file", { cause: res.statusText });
|
|
1598
|
+
}
|
|
1599
|
+
if (!res.body) {
|
|
1600
|
+
throw new Error("Failed to stream file", { cause: "No body" });
|
|
1601
|
+
}
|
|
1602
|
+
return res.body;
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
var __defProp$6 = Object.defineProperty;
|
|
1607
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1608
|
+
var __publicField$6 = (obj, key, value) => {
|
|
1609
|
+
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1386
1610
|
return value;
|
|
1387
1611
|
};
|
|
1388
1612
|
function timeout(ms, signal) {
|
|
@@ -1398,10 +1622,10 @@ function timeout(ms, signal) {
|
|
|
1398
1622
|
}
|
|
1399
1623
|
class Poller {
|
|
1400
1624
|
constructor({ interval, timeout: timeout2, abortSignal }) {
|
|
1401
|
-
__publicField$
|
|
1402
|
-
__publicField$
|
|
1403
|
-
__publicField$
|
|
1404
|
-
__publicField$
|
|
1625
|
+
__publicField$6(this, "_interval");
|
|
1626
|
+
__publicField$6(this, "_timeout");
|
|
1627
|
+
__publicField$6(this, "_abortSignal");
|
|
1628
|
+
__publicField$6(this, "_internalAbortController");
|
|
1405
1629
|
if (interval <= 0) {
|
|
1406
1630
|
throw new TelaError("Interval must be greater than 0");
|
|
1407
1631
|
}
|
|
@@ -1447,7 +1671,7 @@ class Poller {
|
|
|
1447
1671
|
const resultPromise = async () => {
|
|
1448
1672
|
try {
|
|
1449
1673
|
while (!this._abortSignal.aborted) {
|
|
1450
|
-
const result = await callback(
|
|
1674
|
+
const result = await callback();
|
|
1451
1675
|
if (result.done) {
|
|
1452
1676
|
return result.value;
|
|
1453
1677
|
}
|
|
@@ -1462,53 +1686,12 @@ class Poller {
|
|
|
1462
1686
|
}
|
|
1463
1687
|
}
|
|
1464
1688
|
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
const { createHash } = await import('node:crypto');
|
|
1470
|
-
const hash = createHash("sha256");
|
|
1471
|
-
while (true) {
|
|
1472
|
-
const { done, value } = await reader.read();
|
|
1473
|
-
if (done)
|
|
1474
|
-
break;
|
|
1475
|
-
hash.update(value);
|
|
1476
|
-
}
|
|
1477
|
-
return hash.digest("hex");
|
|
1478
|
-
} catch {
|
|
1479
|
-
const chunks = [];
|
|
1480
|
-
while (true) {
|
|
1481
|
-
const { done, value } = await reader.read();
|
|
1482
|
-
if (done)
|
|
1483
|
-
break;
|
|
1484
|
-
chunks.push(value);
|
|
1485
|
-
}
|
|
1486
|
-
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
1487
|
-
const buffer = new Uint8Array(totalLength);
|
|
1488
|
-
let offset = 0;
|
|
1489
|
-
for (const chunk of chunks) {
|
|
1490
|
-
buffer.set(chunk, offset);
|
|
1491
|
-
offset += chunk.length;
|
|
1492
|
-
}
|
|
1493
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
|
|
1494
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1495
|
-
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1496
|
-
return hashHex;
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
var __defProp$2 = Object.defineProperty;
|
|
1501
|
-
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1502
|
-
var __publicField$2 = (obj, key, value) => {
|
|
1503
|
-
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1689
|
+
var __defProp$5 = Object.defineProperty;
|
|
1690
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1691
|
+
var __publicField$5 = (obj, key, value) => {
|
|
1692
|
+
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1504
1693
|
return value;
|
|
1505
1694
|
};
|
|
1506
|
-
function isTelaFile(obj) {
|
|
1507
|
-
return obj instanceof TelaFile;
|
|
1508
|
-
}
|
|
1509
|
-
function isTelaFileArray(obj) {
|
|
1510
|
-
return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
|
|
1511
|
-
}
|
|
1512
1695
|
function isUUID(str) {
|
|
1513
1696
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1514
1697
|
return uuidRegex.test(str);
|
|
@@ -1540,6 +1723,17 @@ function getResultFromPollingResponse(response) {
|
|
|
1540
1723
|
}
|
|
1541
1724
|
throw new Error("Invalid response type");
|
|
1542
1725
|
}
|
|
1726
|
+
function normalizeExecutionStatus(status) {
|
|
1727
|
+
switch (status) {
|
|
1728
|
+
case "completed":
|
|
1729
|
+
case "validating":
|
|
1730
|
+
return "succeeded";
|
|
1731
|
+
case "cancelled":
|
|
1732
|
+
return "failed";
|
|
1733
|
+
default:
|
|
1734
|
+
return status;
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1543
1737
|
class CanvasExecution extends Emittery {
|
|
1544
1738
|
/**
|
|
1545
1739
|
* Creates a new canvas execution instance.
|
|
@@ -1551,20 +1745,20 @@ class CanvasExecution extends Emittery {
|
|
|
1551
1745
|
*/
|
|
1552
1746
|
constructor(variables, params = { async: false }, outputSchema, client, isTask = false) {
|
|
1553
1747
|
super();
|
|
1554
|
-
__publicField$
|
|
1555
|
-
__publicField$
|
|
1556
|
-
__publicField$
|
|
1557
|
-
__publicField$
|
|
1558
|
-
__publicField$
|
|
1559
|
-
__publicField$
|
|
1560
|
-
__publicField$
|
|
1561
|
-
__publicField$
|
|
1562
|
-
__publicField$
|
|
1563
|
-
__publicField$
|
|
1564
|
-
__publicField$
|
|
1565
|
-
__publicField$
|
|
1566
|
-
__publicField$
|
|
1567
|
-
__publicField$
|
|
1748
|
+
__publicField$5(this, "_id");
|
|
1749
|
+
__publicField$5(this, "_status");
|
|
1750
|
+
__publicField$5(this, "_variables");
|
|
1751
|
+
__publicField$5(this, "_params");
|
|
1752
|
+
__publicField$5(this, "_client");
|
|
1753
|
+
__publicField$5(this, "_outputSchema");
|
|
1754
|
+
__publicField$5(this, "_skipResultValidation");
|
|
1755
|
+
__publicField$5(this, "_abortController");
|
|
1756
|
+
__publicField$5(this, "_isTask");
|
|
1757
|
+
__publicField$5(this, "_resultPromise");
|
|
1758
|
+
__publicField$5(this, "_stream");
|
|
1759
|
+
__publicField$5(this, "_rawResultValue");
|
|
1760
|
+
__publicField$5(this, "_requestId");
|
|
1761
|
+
__publicField$5(this, "_task");
|
|
1568
1762
|
this._variables = variables;
|
|
1569
1763
|
this._params = params;
|
|
1570
1764
|
this._outputSchema = outputSchema;
|
|
@@ -1629,7 +1823,7 @@ class CanvasExecution extends Emittery {
|
|
|
1629
1823
|
execution._rawResultValue = response;
|
|
1630
1824
|
const content = getResultFromPollingResponse(response);
|
|
1631
1825
|
try {
|
|
1632
|
-
const validatedContent = execution._skipResultValidation || !(outputSchema instanceof
|
|
1826
|
+
const validatedContent = execution._skipResultValidation || !(outputSchema instanceof z.ZodType) ? content : outputSchema.parse(content);
|
|
1633
1827
|
execution._resultPromise = Promise.resolve(validatedContent);
|
|
1634
1828
|
} catch (error) {
|
|
1635
1829
|
execution._resultPromise = Promise.reject(error);
|
|
@@ -1974,12 +2168,12 @@ class CanvasExecution extends Emittery {
|
|
|
1974
2168
|
label: this._params.label,
|
|
1975
2169
|
webhook_url: this._params.webhookUrl
|
|
1976
2170
|
};
|
|
1977
|
-
if (this._params.override && this._outputSchema instanceof
|
|
2171
|
+
if (this._params.override && this._outputSchema instanceof z.ZodType) {
|
|
1978
2172
|
return {
|
|
1979
2173
|
...body,
|
|
1980
2174
|
override: {
|
|
1981
2175
|
...this._params.override,
|
|
1982
|
-
structured_output:
|
|
2176
|
+
structured_output: z.toJSONSchema(this._outputSchema)
|
|
1983
2177
|
}
|
|
1984
2178
|
};
|
|
1985
2179
|
}
|
|
@@ -2046,7 +2240,7 @@ class CanvasExecution extends Emittery {
|
|
|
2046
2240
|
this._rawResultValue = response;
|
|
2047
2241
|
return { content: getResultFromPollingResponse(response), response };
|
|
2048
2242
|
}).then(({ content, response }) => {
|
|
2049
|
-
const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof
|
|
2243
|
+
const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z.ZodType) ? content : this._outputSchema.parse(content);
|
|
2050
2244
|
this.status = "succeeded";
|
|
2051
2245
|
this.emit("success", { ...validatedContent, requestId: response?.requestId });
|
|
2052
2246
|
return validatedContent;
|
|
@@ -2070,13 +2264,13 @@ class CanvasExecution extends Emittery {
|
|
|
2070
2264
|
const resolvedVariables = await this.resolveVariables();
|
|
2071
2265
|
return await this.create(resolvedVariables, { async: true }).then((response) => {
|
|
2072
2266
|
this._id = "completionRunId" in response ? response.completionRunId : response.id;
|
|
2073
|
-
this.status = response.status;
|
|
2267
|
+
this.status = normalizeExecutionStatus(response.status);
|
|
2074
2268
|
if (this._isTask) {
|
|
2075
2269
|
this._task = response;
|
|
2076
2270
|
}
|
|
2077
2271
|
this.emit("poll", {
|
|
2078
2272
|
id: response.id,
|
|
2079
|
-
status: response.status,
|
|
2273
|
+
status: normalizeExecutionStatus(response.status),
|
|
2080
2274
|
outputContent: response.outputContent,
|
|
2081
2275
|
rawOutput: "rawOutput" in response ? response.rawOutput : void 0,
|
|
2082
2276
|
requestId: response.requestId
|
|
@@ -2109,27 +2303,27 @@ class CanvasExecution extends Emittery {
|
|
|
2109
2303
|
throw new InvalidExecutionModeError("Polling is only supported for async executions");
|
|
2110
2304
|
}
|
|
2111
2305
|
return new Poller({
|
|
2112
|
-
interval: this._params.pollingInterval ?? 1e3,
|
|
2306
|
+
interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
|
|
2113
2307
|
// 1 second
|
|
2114
|
-
timeout: this._params.pollingTimeout ?? 6e4,
|
|
2308
|
+
timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
|
|
2115
2309
|
// 1 minute
|
|
2116
2310
|
abortSignal: this._abortController.signal
|
|
2117
|
-
}).start(async (
|
|
2311
|
+
}).start(async () => {
|
|
2118
2312
|
const response = await this._client.get(
|
|
2119
2313
|
`/v2/chat/completions/${this.id}`,
|
|
2120
2314
|
{
|
|
2121
|
-
signal
|
|
2315
|
+
signal: this._abortController.signal
|
|
2122
2316
|
}
|
|
2123
2317
|
);
|
|
2124
|
-
this.status = response.status;
|
|
2318
|
+
this.status = normalizeExecutionStatus(response.status);
|
|
2125
2319
|
this.emit("poll", response);
|
|
2126
|
-
if (
|
|
2320
|
+
if (this.status === "failed") {
|
|
2127
2321
|
const error = new ExecutionFailedError(response.rawOutput);
|
|
2128
2322
|
this.cancel();
|
|
2129
2323
|
this.emit("error", error);
|
|
2130
2324
|
throw error;
|
|
2131
2325
|
}
|
|
2132
|
-
if (
|
|
2326
|
+
if (this.status !== "succeeded") {
|
|
2133
2327
|
return {
|
|
2134
2328
|
done: false,
|
|
2135
2329
|
value: void 0
|
|
@@ -2138,16 +2332,16 @@ class CanvasExecution extends Emittery {
|
|
|
2138
2332
|
this._rawResultValue = response;
|
|
2139
2333
|
this.emit("success", { ...getResultFromPollingResponse(response), requestId: response?.requestId });
|
|
2140
2334
|
return {
|
|
2141
|
-
done:
|
|
2335
|
+
done: this.status === "succeeded",
|
|
2142
2336
|
value: getResultFromPollingResponse(response)
|
|
2143
2337
|
};
|
|
2144
2338
|
}).then((value) => {
|
|
2145
|
-
if (this._skipResultValidation || !(this._outputSchema instanceof
|
|
2339
|
+
if (this._skipResultValidation || !(this._outputSchema instanceof z.ZodType)) {
|
|
2146
2340
|
return value;
|
|
2147
2341
|
}
|
|
2148
2342
|
return this._outputSchema.parse(value);
|
|
2149
2343
|
}).catch((error) => {
|
|
2150
|
-
if (this.
|
|
2344
|
+
if (this.status !== "failed") {
|
|
2151
2345
|
this.status = "failed";
|
|
2152
2346
|
}
|
|
2153
2347
|
if (this.listenerCount("error") > 0) {
|
|
@@ -2176,56 +2370,7 @@ class CanvasExecution extends Emittery {
|
|
|
2176
2370
|
* ```
|
|
2177
2371
|
*/
|
|
2178
2372
|
async uploadFile(file) {
|
|
2179
|
-
|
|
2180
|
-
let sha256sumStream;
|
|
2181
|
-
if (typeof content === "string") {
|
|
2182
|
-
return { fileUrl: content, options: file.options };
|
|
2183
|
-
}
|
|
2184
|
-
const filename = file.name ?? void 0;
|
|
2185
|
-
const fileType = file.type ?? void 0;
|
|
2186
|
-
const contentLength = file.size ?? void 0;
|
|
2187
|
-
if (content instanceof ReadableStream) {
|
|
2188
|
-
const [hashStream, contentStream] = content.tee();
|
|
2189
|
-
content = contentStream;
|
|
2190
|
-
sha256sumStream = hashStream;
|
|
2191
|
-
}
|
|
2192
|
-
const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
|
|
2193
|
-
const { id, uploadUrl } = await this._client.post("/_services/vault/files", {
|
|
2194
|
-
body: {
|
|
2195
|
-
fileName: filename,
|
|
2196
|
-
mimeType: fileType,
|
|
2197
|
-
size: contentLength ?? void 0,
|
|
2198
|
-
sha256sum
|
|
2199
|
-
}
|
|
2200
|
-
});
|
|
2201
|
-
if (content instanceof ReadableStream && typeof Bun !== "undefined") {
|
|
2202
|
-
console.warn(
|
|
2203
|
-
"[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
|
|
2204
|
-
{ fileName: filename, fileSize: contentLength }
|
|
2205
|
-
);
|
|
2206
|
-
const chunks = [];
|
|
2207
|
-
const reader = content.getReader();
|
|
2208
|
-
while (true) {
|
|
2209
|
-
const { done, value } = await reader.read();
|
|
2210
|
-
if (done)
|
|
2211
|
-
break;
|
|
2212
|
-
chunks.push(value);
|
|
2213
|
-
}
|
|
2214
|
-
content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
|
|
2215
|
-
}
|
|
2216
|
-
const request = new Request(uploadUrl, {
|
|
2217
|
-
method: "PUT",
|
|
2218
|
-
body: content,
|
|
2219
|
-
headers: {
|
|
2220
|
-
"Content-Type": fileType ?? "application/octet-stream",
|
|
2221
|
-
...file.size ? { "Content-Length": file.size.toString() } : {}
|
|
2222
|
-
}
|
|
2223
|
-
});
|
|
2224
|
-
const uploadResponse = await fetch(request);
|
|
2225
|
-
if (!uploadResponse.ok) {
|
|
2226
|
-
throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
|
|
2227
|
-
}
|
|
2228
|
-
return { fileUrl: `vault://${id}`, options: file.options };
|
|
2373
|
+
return uploadFile(file, this._client);
|
|
2229
2374
|
}
|
|
2230
2375
|
/**
|
|
2231
2376
|
* Uploads multiple files and returns their URLs and options.
|
|
@@ -2242,213 +2387,1516 @@ class CanvasExecution extends Emittery {
|
|
|
2242
2387
|
}
|
|
2243
2388
|
}
|
|
2244
2389
|
|
|
2245
|
-
var __defProp$
|
|
2246
|
-
var __defNormalProp$
|
|
2247
|
-
var __publicField$
|
|
2248
|
-
__defNormalProp$
|
|
2390
|
+
var __defProp$4 = Object.defineProperty;
|
|
2391
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2392
|
+
var __publicField$4 = (obj, key, value) => {
|
|
2393
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2249
2394
|
return value;
|
|
2250
2395
|
};
|
|
2251
|
-
const
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2396
|
+
const BatchResultItem = z.looseObject({
|
|
2397
|
+
reference_id: z.string(),
|
|
2398
|
+
status: z.string(),
|
|
2399
|
+
execution_id: z.string(),
|
|
2400
|
+
result: z.object({
|
|
2401
|
+
id: z.string(),
|
|
2402
|
+
tags: z.array(z.string()),
|
|
2403
|
+
status: z.string(),
|
|
2404
|
+
metadata: z.object({
|
|
2405
|
+
promptVersion: z.object({
|
|
2406
|
+
modelConfigurations: z.object({
|
|
2407
|
+
type: z.string(),
|
|
2408
|
+
model: z.string(),
|
|
2409
|
+
temperature: z.number(),
|
|
2410
|
+
structuredOutput: z.object({
|
|
2411
|
+
schema: z.looseObject({}).optional(),
|
|
2412
|
+
enabled: z.boolean()
|
|
2413
|
+
})
|
|
2414
|
+
}),
|
|
2415
|
+
variablesDefinitions: z.array(
|
|
2416
|
+
z.object({
|
|
2417
|
+
name: z.string(),
|
|
2418
|
+
type: z.string(),
|
|
2419
|
+
required: z.boolean(),
|
|
2420
|
+
processingOptions: z.object({ allowMultimodal: z.boolean() })
|
|
2421
|
+
})
|
|
2422
|
+
)
|
|
2423
|
+
})
|
|
2424
|
+
}),
|
|
2425
|
+
promptId: z.string(),
|
|
2426
|
+
rawInput: z.object({
|
|
2427
|
+
tags: z.array(z.string()),
|
|
2428
|
+
async: z.boolean(),
|
|
2429
|
+
canvas_id: z.string(),
|
|
2430
|
+
variables: z.looseObject({})
|
|
2431
|
+
}),
|
|
2432
|
+
createdAt: z.string(),
|
|
2433
|
+
deletedAt: z.null(),
|
|
2434
|
+
rawOutput: z.object({
|
|
2435
|
+
id: z.string(),
|
|
2436
|
+
usage: z.object({
|
|
2437
|
+
cost: z.object({
|
|
2438
|
+
total_cost: z.number(),
|
|
2439
|
+
prompt_cost: z.number(),
|
|
2440
|
+
completion_cost: z.number()
|
|
2441
|
+
}),
|
|
2442
|
+
total_tokens: z.number(),
|
|
2443
|
+
prompt_tokens: z.number(),
|
|
2444
|
+
completion_tokens: z.number()
|
|
2445
|
+
}),
|
|
2446
|
+
object: z.string(),
|
|
2447
|
+
choices: z.array(
|
|
2448
|
+
z.object({
|
|
2449
|
+
message: z.object({
|
|
2450
|
+
role: z.string(),
|
|
2451
|
+
content: z.looseObject({}),
|
|
2452
|
+
tool_calls: z.array(z.object({ type: z.string(), function: z.object({ name: z.string(), arguments: z.looseObject({}) }) })),
|
|
2453
|
+
function_call: z.null()
|
|
2454
|
+
})
|
|
2455
|
+
})
|
|
2456
|
+
),
|
|
2457
|
+
created: z.number()
|
|
2458
|
+
}),
|
|
2459
|
+
updatedAt: z.string(),
|
|
2460
|
+
creditsUsed: z.number(),
|
|
2461
|
+
workspaceId: z.string(),
|
|
2462
|
+
inputContent: z.object({
|
|
2463
|
+
files: z.array(z.object({ file_url: z.string() })),
|
|
2464
|
+
messages: z.array(z.object({ role: z.string(), content: z.looseObject({}) })),
|
|
2465
|
+
variables: z.looseObject({})
|
|
2466
|
+
}),
|
|
2467
|
+
outputContent: z.object({
|
|
2468
|
+
role: z.string(),
|
|
2469
|
+
content: z.looseObject({}),
|
|
2470
|
+
tool_calls: z.array(z.looseObject({})),
|
|
2471
|
+
function_call: z.string().nullable()
|
|
2472
|
+
}),
|
|
2473
|
+
promptVersionId: z.string(),
|
|
2474
|
+
compatibilityDate: z.string(),
|
|
2475
|
+
promptApplicationId: z.string().nullable()
|
|
2476
|
+
}),
|
|
2477
|
+
error: z.null()
|
|
2478
|
+
});
|
|
2479
|
+
class BatchExecutionResult {
|
|
2480
|
+
/**
|
|
2481
|
+
* Creates a new batch execution result wrapper.
|
|
2482
|
+
*
|
|
2483
|
+
* @param client - HTTP client for making API requests.
|
|
2484
|
+
* @param response - Raw batch execution response from the server.
|
|
2485
|
+
* @internal
|
|
2486
|
+
*/
|
|
2487
|
+
constructor(client, response) {
|
|
2488
|
+
__publicField$4(this, "_client");
|
|
2489
|
+
__publicField$4(this, "_response");
|
|
2490
|
+
this._client = client;
|
|
2491
|
+
this._response = response;
|
|
2267
2492
|
}
|
|
2268
|
-
|
|
2269
|
-
return
|
|
2493
|
+
get requestId() {
|
|
2494
|
+
return this._response.requestId;
|
|
2270
2495
|
}
|
|
2271
|
-
|
|
2272
|
-
|
|
2496
|
+
/**
|
|
2497
|
+
* Gets the unique identifier for this batch execution.
|
|
2498
|
+
*
|
|
2499
|
+
* @returns The batch execution ID.
|
|
2500
|
+
*/
|
|
2501
|
+
get id() {
|
|
2502
|
+
return this._response.id;
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2505
|
+
* Gets the current status of the batch execution.
|
|
2506
|
+
*
|
|
2507
|
+
* @returns The batch status.
|
|
2508
|
+
*/
|
|
2509
|
+
get status() {
|
|
2510
|
+
return this._response.status;
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* Gets the progress statistics for this batch.
|
|
2514
|
+
*
|
|
2515
|
+
* @returns Object containing completed, failed, and total execution counts, or null if not available.
|
|
2516
|
+
*/
|
|
2517
|
+
get state() {
|
|
2518
|
+
return this._response.state;
|
|
2519
|
+
}
|
|
2520
|
+
/**
|
|
2521
|
+
* Gets the vault URL of the output JSONL file containing all results.
|
|
2522
|
+
*
|
|
2523
|
+
* @returns The output file URL, or null if batch is not completed.
|
|
2524
|
+
*/
|
|
2525
|
+
get outputFile() {
|
|
2526
|
+
return this._response.outputFile;
|
|
2527
|
+
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Gets the raw API response without any processing.
|
|
2530
|
+
*
|
|
2531
|
+
* @returns The complete batch response object.
|
|
2532
|
+
*/
|
|
2533
|
+
get rawResponse() {
|
|
2534
|
+
return this._response;
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Gets the timestamp when this batch was created.
|
|
2538
|
+
*
|
|
2539
|
+
* @returns Creation date.
|
|
2540
|
+
*/
|
|
2541
|
+
get createdAt() {
|
|
2542
|
+
return new Date(this._response.createdAt);
|
|
2543
|
+
}
|
|
2544
|
+
/**
|
|
2545
|
+
* Gets the timestamp when this batch was last updated.
|
|
2546
|
+
*
|
|
2547
|
+
* @returns Last update date.
|
|
2548
|
+
*/
|
|
2549
|
+
get updatedAt() {
|
|
2550
|
+
return new Date(this._response.updatedAt);
|
|
2551
|
+
}
|
|
2552
|
+
/**
|
|
2553
|
+
* Gets the timestamp when this batch completed successfully.
|
|
2554
|
+
*
|
|
2555
|
+
* @returns Completion date, or null if not completed.
|
|
2556
|
+
*/
|
|
2557
|
+
get completedAt() {
|
|
2558
|
+
return this._response.completedAt ? new Date(this._response.completedAt) : null;
|
|
2559
|
+
}
|
|
2560
|
+
/**
|
|
2561
|
+
* Gets the timestamp when this batch was canceled.
|
|
2562
|
+
*
|
|
2563
|
+
* @returns Cancellation date, or null if not canceled.
|
|
2564
|
+
*/
|
|
2565
|
+
get canceledAt() {
|
|
2566
|
+
return this._response.canceledAt ? new Date(this._response.canceledAt) : null;
|
|
2567
|
+
}
|
|
2568
|
+
/**
|
|
2569
|
+
* Gets the timestamp when this batch failed.
|
|
2570
|
+
*
|
|
2571
|
+
* @returns Failure date, or null if not failed.
|
|
2572
|
+
*/
|
|
2573
|
+
get failedAt() {
|
|
2574
|
+
return this._response.failedAt ? new Date(this._response.failedAt) : null;
|
|
2575
|
+
}
|
|
2576
|
+
/**
|
|
2577
|
+
* Downloads the complete output file as a Blob.
|
|
2578
|
+
*
|
|
2579
|
+
* The output file is a JSONL (JSON Lines) file where each line contains
|
|
2580
|
+
* one execution result with its reference ID, status, and output.
|
|
2581
|
+
*
|
|
2582
|
+
* @throws {Error} If batch is not completed or output file is unavailable.
|
|
2583
|
+
* @returns A promise resolving to the output file as a Blob.
|
|
2584
|
+
*
|
|
2585
|
+
* @example
|
|
2586
|
+
* ```typescript
|
|
2587
|
+
* const file = await result.downloadOutputFile()
|
|
2588
|
+
* const text = await file.text()
|
|
2589
|
+
* console.log(text) // JSONL content
|
|
2590
|
+
* ```
|
|
2591
|
+
*/
|
|
2592
|
+
downloadOutputFile() {
|
|
2593
|
+
this.validateOutputFile();
|
|
2594
|
+
return downloadFile(this._response.outputFile, this._client);
|
|
2595
|
+
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Streams the output file as a ReadableStream for memory-efficient processing.
|
|
2598
|
+
*
|
|
2599
|
+
* Useful for large batches where loading the entire file into memory is not practical.
|
|
2600
|
+
*
|
|
2601
|
+
* @throws {Error} If batch is not completed or output file is unavailable.
|
|
2602
|
+
* @returns A promise resolving to a ReadableStream of the output file.
|
|
2603
|
+
*
|
|
2604
|
+
* @example
|
|
2605
|
+
* ```typescript
|
|
2606
|
+
* const stream = await result.streamOutputFile()
|
|
2607
|
+
* // Process stream with custom logic
|
|
2608
|
+
* ```
|
|
2609
|
+
*/
|
|
2610
|
+
async streamOutputFile() {
|
|
2611
|
+
this.validateOutputFile();
|
|
2612
|
+
return streamFile(this._response.outputFile, this._client);
|
|
2613
|
+
}
|
|
2614
|
+
/**
|
|
2615
|
+
* Downloads and parses all results into an array.
|
|
2616
|
+
*
|
|
2617
|
+
* Loads the entire output file into memory, parses each line, and extracts
|
|
2618
|
+
* the output content. For large batches, consider using `iterateResults()` instead.
|
|
2619
|
+
*
|
|
2620
|
+
* @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
|
|
2621
|
+
* @returns A promise resolving to an array of all execution outputs.
|
|
2622
|
+
*
|
|
2623
|
+
* @example
|
|
2624
|
+
* ```typescript
|
|
2625
|
+
* const results = await result.getResults()
|
|
2626
|
+
* console.log(`Got ${results.length} results`)
|
|
2627
|
+
* results.forEach((output, i) => console.log(`Result ${i}:`, output))
|
|
2628
|
+
* ```
|
|
2629
|
+
*/
|
|
2630
|
+
async getResults() {
|
|
2631
|
+
const resultFile = await this.downloadOutputFile();
|
|
2632
|
+
const results = await resultFile.text();
|
|
2633
|
+
return results.split("\n").filter((line) => line.trim().length > 0).map((result) => JSON.parse(result)).map((result) => {
|
|
2634
|
+
const parsedResult = BatchResultItem.safeParse(result);
|
|
2635
|
+
if (!parsedResult.success) {
|
|
2636
|
+
throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
|
|
2637
|
+
}
|
|
2638
|
+
return parsedResult.data.result.outputContent.content;
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Asynchronously iterates over raw result items from the output file.
|
|
2643
|
+
*
|
|
2644
|
+
* Streams and parses the output file line-by-line, yielding raw JSON objects.
|
|
2645
|
+
* Each yielded object contains the full result structure including metadata.
|
|
2646
|
+
*
|
|
2647
|
+
* @param params - Iteration options.
|
|
2648
|
+
* @param params.abortController - Optional AbortController to cancel iteration.
|
|
2649
|
+
* @throws {Error} If batch is not completed or output file is unavailable.
|
|
2650
|
+
* @yields Raw result objects from the JSONL file.
|
|
2651
|
+
*
|
|
2652
|
+
* @example
|
|
2653
|
+
* ```typescript
|
|
2654
|
+
* for await (const rawResult of result.iterateRawResults()) {
|
|
2655
|
+
* console.log('Reference ID:', rawResult.reference_id)
|
|
2656
|
+
* console.log('Status:', rawResult.status)
|
|
2657
|
+
* console.log('Output:', rawResult.result.outputContent.content)
|
|
2658
|
+
* }
|
|
2659
|
+
* ```
|
|
2660
|
+
*/
|
|
2661
|
+
async *iterateRawResults(params = {}) {
|
|
2662
|
+
const { abortController = new AbortController() } = params;
|
|
2663
|
+
const stream = await this.streamOutputFile();
|
|
2664
|
+
for await (const result of Stream.fromReadableStream(stream, abortController)) {
|
|
2665
|
+
yield result;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Asynchronously iterates over parsed output content from the batch results.
|
|
2670
|
+
*
|
|
2671
|
+
* Streams and parses the output file line-by-line, yielding only the output content
|
|
2672
|
+
* (not the full result metadata). Memory-efficient for large batches.
|
|
2673
|
+
*
|
|
2674
|
+
* @param params - Iteration options.
|
|
2675
|
+
* @param params.abortController - Optional AbortController to cancel iteration.
|
|
2676
|
+
* @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
|
|
2677
|
+
* @yields Parsed output content from each execution.
|
|
2678
|
+
*
|
|
2679
|
+
* @example
|
|
2680
|
+
* ```typescript
|
|
2681
|
+
* const controller = new AbortController()
|
|
2682
|
+
*
|
|
2683
|
+
* for await (const output of result.iterateResults({ abortController: controller })) {
|
|
2684
|
+
* console.log(output)
|
|
2685
|
+
* if (someCondition) {
|
|
2686
|
+
* controller.abort() // Stop iteration early
|
|
2687
|
+
* }
|
|
2688
|
+
* }
|
|
2689
|
+
* ```
|
|
2690
|
+
*/
|
|
2691
|
+
async *iterateResults(params = {}) {
|
|
2692
|
+
for await (const result of this.iterateRawResults(params)) {
|
|
2693
|
+
const parsedResult = BatchResultItem.safeParse(result);
|
|
2694
|
+
if (!parsedResult.success) {
|
|
2695
|
+
throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
|
|
2696
|
+
}
|
|
2697
|
+
yield parsedResult.data.result.outputContent.content;
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
/**
|
|
2701
|
+
* Fetches the raw result metadata for a specific execution by its reference ID.
|
|
2702
|
+
*
|
|
2703
|
+
* Queries the API for the execution result using the reference ID tag.
|
|
2704
|
+
* Returns the complete execution metadata including input, output, and usage statistics.
|
|
2705
|
+
*
|
|
2706
|
+
* @param referenceId - The reference ID of the execution to retrieve.
|
|
2707
|
+
* @throws {Error} If no result found with the given reference ID.
|
|
2708
|
+
* @returns A promise resolving to the raw execution result object.
|
|
2709
|
+
*
|
|
2710
|
+
* @example
|
|
2711
|
+
* ```typescript
|
|
2712
|
+
* const rawResult = await result.getRawResult('my-ref-id')
|
|
2713
|
+
* console.log('Credits used:', rawResult.creditsUsed)
|
|
2714
|
+
* console.log('Execution status:', rawResult.status)
|
|
2715
|
+
* ```
|
|
2716
|
+
*/
|
|
2717
|
+
async getRawResult(referenceId) {
|
|
2718
|
+
const response = await this._client.get("/v1/completion-run/", {
|
|
2719
|
+
query: {
|
|
2720
|
+
tags: `reference_id:${referenceId}`
|
|
2721
|
+
}
|
|
2722
|
+
});
|
|
2723
|
+
const result = response.data[0];
|
|
2724
|
+
if (!result) {
|
|
2725
|
+
throw new Error("Result not found");
|
|
2726
|
+
}
|
|
2727
|
+
return result;
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Fetches the output content for a specific execution by its reference ID.
|
|
2731
|
+
*
|
|
2732
|
+
* Convenience method that retrieves the raw result and extracts just the output content.
|
|
2733
|
+
*
|
|
2734
|
+
* @param referenceId - The reference ID of the execution to retrieve.
|
|
2735
|
+
* @throws {Error} If no result found with the given reference ID.
|
|
2736
|
+
* @returns A promise resolving to the execution output content.
|
|
2737
|
+
*
|
|
2738
|
+
* @example
|
|
2739
|
+
* ```typescript
|
|
2740
|
+
* const output = await result.getResult('my-ref-id')
|
|
2741
|
+
* console.log('Output:', output)
|
|
2742
|
+
* ```
|
|
2743
|
+
*/
|
|
2744
|
+
async getResult(referenceId) {
|
|
2745
|
+
const result = await this.getRawResult(referenceId);
|
|
2746
|
+
return result.outputContent.content;
|
|
2747
|
+
}
|
|
2748
|
+
/**
|
|
2749
|
+
* Validates that the output file is available for access.
|
|
2750
|
+
*
|
|
2751
|
+
* @throws {Error} If batch is not completed or output file is missing.
|
|
2752
|
+
* @private
|
|
2753
|
+
*/
|
|
2754
|
+
validateOutputFile() {
|
|
2755
|
+
if (this._response.status !== "completed") {
|
|
2756
|
+
throw new Error("Batch execution is not completed");
|
|
2757
|
+
}
|
|
2758
|
+
if (!this._response.outputFile) {
|
|
2759
|
+
throw new Error("Output file not found");
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
class BatchExecution extends Emittery {
|
|
2764
|
+
/**
|
|
2765
|
+
* Creates a new batch execution instance.
|
|
2766
|
+
*
|
|
2767
|
+
* @param id - Unique identifier for this batch execution.
|
|
2768
|
+
* @param client - HTTP client for making API requests.
|
|
2769
|
+
* @param params - Batch execution parameters.
|
|
2770
|
+
* @param creationResponse - Initial response from batch creation.
|
|
2771
|
+
* @internal
|
|
2772
|
+
*/
|
|
2773
|
+
constructor(id, client, params = {}, creationResponse) {
|
|
2774
|
+
super();
|
|
2775
|
+
__publicField$4(this, "_client");
|
|
2776
|
+
__publicField$4(this, "_id");
|
|
2777
|
+
__publicField$4(this, "_params");
|
|
2778
|
+
__publicField$4(this, "_abortController");
|
|
2779
|
+
__publicField$4(this, "_creationResponse");
|
|
2780
|
+
__publicField$4(this, "_status", "created");
|
|
2781
|
+
__publicField$4(this, "_resultPromise");
|
|
2782
|
+
this._id = id;
|
|
2783
|
+
this._client = client;
|
|
2784
|
+
this._params = params;
|
|
2785
|
+
this._abortController = new AbortController();
|
|
2786
|
+
this._creationResponse = creationResponse;
|
|
2787
|
+
}
|
|
2788
|
+
/**
|
|
2789
|
+
* Gets the latest known status of the batch execution.
|
|
2790
|
+
*
|
|
2791
|
+
* Status values and transitions:
|
|
2792
|
+
* - `created` → `validating` → `running` → `completed` or `failed`
|
|
2793
|
+
* - Can transition to `canceled` from any non-terminal state
|
|
2794
|
+
*
|
|
2795
|
+
* Use the `statusChange` event to track status transitions in real-time.
|
|
2796
|
+
*
|
|
2797
|
+
* @returns The current status of the batch execution.
|
|
2798
|
+
*
|
|
2799
|
+
* @example
|
|
2800
|
+
* ```typescript
|
|
2801
|
+
* const execution = await batch.execute()
|
|
2802
|
+
* console.log(execution.status) // 'created'
|
|
2803
|
+
*
|
|
2804
|
+
* execution.on('statusChange', ([status]) => {
|
|
2805
|
+
* console.log('New status:', status)
|
|
2806
|
+
* })
|
|
2807
|
+
*
|
|
2808
|
+
* await execution.result
|
|
2809
|
+
* console.log(execution.status) // 'completed' or 'failed'
|
|
2810
|
+
* ```
|
|
2811
|
+
*/
|
|
2812
|
+
get status() {
|
|
2813
|
+
return this._status;
|
|
2814
|
+
}
|
|
2815
|
+
/**
|
|
2816
|
+
* Gets the unique identifier for this batch execution.
|
|
2817
|
+
*
|
|
2818
|
+
* @returns The batch execution ID.
|
|
2819
|
+
*/
|
|
2820
|
+
get id() {
|
|
2821
|
+
return this._id;
|
|
2822
|
+
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Gets the batch execution parameters.
|
|
2825
|
+
*
|
|
2826
|
+
* @returns The batch parameters.
|
|
2827
|
+
*/
|
|
2828
|
+
get params() {
|
|
2829
|
+
return this._params;
|
|
2830
|
+
}
|
|
2831
|
+
/**
|
|
2832
|
+
* Cancels the batch execution.
|
|
2833
|
+
*
|
|
2834
|
+
* Sends a cancellation request to the server and aborts any ongoing polling.
|
|
2835
|
+
* The batch will stop processing, but already-completed executions remain available.
|
|
2836
|
+
*
|
|
2837
|
+
* @returns A promise that resolves when the cancellation request completes.
|
|
2838
|
+
*
|
|
2839
|
+
* @example
|
|
2840
|
+
* ```typescript
|
|
2841
|
+
* const execution = await batch.execute()
|
|
2842
|
+
* execution.poll()
|
|
2843
|
+
*
|
|
2844
|
+
* // Cancel after some condition
|
|
2845
|
+
* if (shouldCancel) {
|
|
2846
|
+
* await execution.cancel()
|
|
2847
|
+
* console.log(execution.status) // 'canceled'
|
|
2848
|
+
* }
|
|
2849
|
+
* ```
|
|
2850
|
+
*/
|
|
2851
|
+
async cancel() {
|
|
2852
|
+
await this._client.put(`/_services/batch/batches/${this._id}/cancel`);
|
|
2853
|
+
this._status = "canceled";
|
|
2854
|
+
this._abortController.abort();
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* Starts polling for the batch result without waiting for the promise to resolve.
|
|
2858
|
+
* This allows users to track batch progress via events rather than awaiting a promise.
|
|
2859
|
+
*
|
|
2860
|
+
* The following events will be emitted during polling:
|
|
2861
|
+
* - `statusChange`: Emitted when the batch status changes (e.g., 'created' → 'running' → 'completed')
|
|
2862
|
+
* - `poll`: Emitted on each polling attempt with the server response
|
|
2863
|
+
* - `success`: Emitted when the batch completes successfully with the final result
|
|
2864
|
+
* - `error`: Emitted if the batch fails
|
|
2865
|
+
*
|
|
2866
|
+
* **Important:** Events are only emitted while polling is active. You must call `poll()` or
|
|
2867
|
+
* await `execution.result` to start polling. Simply setting up event listeners without starting
|
|
2868
|
+
* polling will not trigger any events.
|
|
2869
|
+
*
|
|
2870
|
+
* @example
|
|
2871
|
+
* ```typescript
|
|
2872
|
+
* const execution = await batch.execute()
|
|
2873
|
+
*
|
|
2874
|
+
* // Set up event listeners
|
|
2875
|
+
* execution.on('statusChange', ([status, response]) => {
|
|
2876
|
+
* console.log(`Status: ${status}`)
|
|
2877
|
+
* if (response.state) {
|
|
2878
|
+
* const { completed, total } = response.state
|
|
2879
|
+
* console.log(`Progress: ${completed}/${total}`)
|
|
2880
|
+
* }
|
|
2881
|
+
* })
|
|
2882
|
+
*
|
|
2883
|
+
* execution.on('success', (result) => {
|
|
2884
|
+
* console.log('Batch completed!')
|
|
2885
|
+
* console.log('Request ID:', result.requestId)
|
|
2886
|
+
* })
|
|
2887
|
+
*
|
|
2888
|
+
* execution.on('error', (error) => {
|
|
2889
|
+
* console.error('Batch failed:', error)
|
|
2890
|
+
* })
|
|
2891
|
+
*
|
|
2892
|
+
* // Start polling without waiting
|
|
2893
|
+
* execution.poll()
|
|
2894
|
+
* ```
|
|
2895
|
+
*/
|
|
2896
|
+
poll() {
|
|
2897
|
+
if (this._resultPromise) {
|
|
2898
|
+
return;
|
|
2899
|
+
}
|
|
2900
|
+
this._resultPromise = this.startPolling();
|
|
2901
|
+
this._resultPromise.catch(() => {
|
|
2902
|
+
});
|
|
2903
|
+
}
|
|
2904
|
+
/**
|
|
2905
|
+
* Sets the batch status and emits statusChange event if changed.
|
|
2906
|
+
*
|
|
2907
|
+
* @param status - The new status.
|
|
2908
|
+
* @param response - The response containing the status.
|
|
2909
|
+
* @private
|
|
2910
|
+
*/
|
|
2911
|
+
setStatus(status, response) {
|
|
2912
|
+
const changed = this._status !== status;
|
|
2913
|
+
this._status = status;
|
|
2914
|
+
if (changed) {
|
|
2915
|
+
this.emit("statusChange", [status, response]);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
/**
|
|
2919
|
+
* Starts polling the server for batch completion.
|
|
2920
|
+
* Continues polling until the batch completes, fails, or times out.
|
|
2921
|
+
*
|
|
2922
|
+
* @throws {BatchExecutionFailedError} If the batch fails on the server.
|
|
2923
|
+
* @throws {Error} If the polling operation times out.
|
|
2924
|
+
* @returns A promise resolving to the final batch result.
|
|
2925
|
+
* @private
|
|
2926
|
+
*/
|
|
2927
|
+
async startPolling() {
|
|
2928
|
+
this.emit("statusChange", [this._status, this._creationResponse]);
|
|
2929
|
+
return new Poller({
|
|
2930
|
+
interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
|
|
2931
|
+
// 1 second
|
|
2932
|
+
timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
|
|
2933
|
+
// 1 minute
|
|
2934
|
+
abortSignal: this._abortController.signal
|
|
2935
|
+
}).start(async () => {
|
|
2936
|
+
const response = await this._client.get(
|
|
2937
|
+
`/_services/batch/batches/${this._id}`,
|
|
2938
|
+
{ signal: this._abortController.signal }
|
|
2939
|
+
);
|
|
2940
|
+
this.emit("poll", response);
|
|
2941
|
+
this.setStatus(response.status, response);
|
|
2942
|
+
if (response.status === "failed") {
|
|
2943
|
+
const error = new BatchExecutionFailedError(response);
|
|
2944
|
+
this._abortController.abort();
|
|
2945
|
+
this.emit("error", error);
|
|
2946
|
+
throw error;
|
|
2947
|
+
}
|
|
2948
|
+
if (response.status !== "completed") {
|
|
2949
|
+
return {
|
|
2950
|
+
done: false,
|
|
2951
|
+
value: void 0
|
|
2952
|
+
};
|
|
2953
|
+
}
|
|
2954
|
+
const result = new BatchExecutionResult(this._client, response);
|
|
2955
|
+
this.emit("success", result);
|
|
2956
|
+
return {
|
|
2957
|
+
done: true,
|
|
2958
|
+
value: result
|
|
2959
|
+
};
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
/**
|
|
2963
|
+
* Gets the batch execution result. Automatically starts polling if not already started.
|
|
2964
|
+
*
|
|
2965
|
+
* @returns A promise resolving to the batch execution result.
|
|
2966
|
+
*
|
|
2967
|
+
* @example
|
|
2968
|
+
* ```typescript
|
|
2969
|
+
* const execution = await batch.execute()
|
|
2970
|
+
* const result = await execution.result
|
|
2971
|
+
*
|
|
2972
|
+
* // Access results
|
|
2973
|
+
* const outputs = await result.getResults()
|
|
2974
|
+
* console.log(`Got ${outputs.length} results`)
|
|
2975
|
+
* ```
|
|
2976
|
+
*/
|
|
2977
|
+
get result() {
|
|
2978
|
+
if (!this._resultPromise) {
|
|
2979
|
+
this._resultPromise = this.startPolling();
|
|
2980
|
+
}
|
|
2981
|
+
return this._resultPromise;
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
class Batch {
|
|
2985
|
+
/**
|
|
2986
|
+
* Creates a new batch builder.
|
|
2987
|
+
*
|
|
2988
|
+
* @param client - HTTP client for making API requests.
|
|
2989
|
+
* @param canvasIdentifier - Canvas identification (ID + version or application ID).
|
|
2990
|
+
* @param params - Optional batch execution parameters.
|
|
2991
|
+
* @internal
|
|
2992
|
+
*/
|
|
2993
|
+
constructor(client, canvasIdentifier, params = {}) {
|
|
2994
|
+
__publicField$4(this, "_client");
|
|
2995
|
+
__publicField$4(this, "_canvasIdentifier");
|
|
2996
|
+
__publicField$4(this, "_items", []);
|
|
2997
|
+
__publicField$4(this, "_params");
|
|
2998
|
+
this._client = client;
|
|
2999
|
+
this._canvasIdentifier = canvasIdentifier;
|
|
3000
|
+
this._params = params;
|
|
3001
|
+
}
|
|
3002
|
+
/**
|
|
3003
|
+
* Gets the current list of items in this batch.
|
|
3004
|
+
*
|
|
3005
|
+
* @returns Array of batch items.
|
|
3006
|
+
*/
|
|
3007
|
+
get items() {
|
|
3008
|
+
return this._items;
|
|
3009
|
+
}
|
|
3010
|
+
/**
|
|
3011
|
+
* Gets the batch execution parameters.
|
|
3012
|
+
*
|
|
3013
|
+
* @returns The batch parameters.
|
|
3014
|
+
*/
|
|
3015
|
+
get params() {
|
|
3016
|
+
return this._params;
|
|
3017
|
+
}
|
|
3018
|
+
/**
|
|
3019
|
+
* Gets the canvas identifier in the format expected by the API.
|
|
3020
|
+
*
|
|
3021
|
+
* @returns Canvas identifier object.
|
|
3022
|
+
* @private
|
|
3023
|
+
*/
|
|
3024
|
+
get canvasIdentifier() {
|
|
3025
|
+
return "applicationId" in this._canvasIdentifier ? { applicationId: this._canvasIdentifier.applicationId } : { versionId: this._canvasIdentifier.versionId, canvasID: this._canvasIdentifier.id };
|
|
3026
|
+
}
|
|
3027
|
+
/**
|
|
3028
|
+
* Adds one or more items to the batch.
|
|
3029
|
+
*
|
|
3030
|
+
* Items without a reference ID will have UUIDs generated automatically.
|
|
3031
|
+
* This method can be called multiple times to build up the batch incrementally.
|
|
3032
|
+
*
|
|
3033
|
+
* @param item - Single item or array of items to add to the batch.
|
|
3034
|
+
*
|
|
3035
|
+
* @example
|
|
3036
|
+
* ```typescript
|
|
3037
|
+
* // Add single item
|
|
3038
|
+
* batch.add({
|
|
3039
|
+
* referenceId: 'my-custom-id',
|
|
3040
|
+
* variables: { query: 'Hello' }
|
|
3041
|
+
* })
|
|
3042
|
+
*
|
|
3043
|
+
* // Add multiple items
|
|
3044
|
+
* batch.add([
|
|
3045
|
+
* { variables: { query: 'First' } },
|
|
3046
|
+
* { variables: { query: 'Second' } },
|
|
3047
|
+
* { variables: { query: 'Third' } }
|
|
3048
|
+
* ])
|
|
3049
|
+
*
|
|
3050
|
+
* console.log(`Batch has ${batch.items.length} items`)
|
|
3051
|
+
* ```
|
|
3052
|
+
*/
|
|
3053
|
+
add(item) {
|
|
3054
|
+
const items = Array.isArray(item) ? item : [item];
|
|
3055
|
+
for (const item2 of items) {
|
|
3056
|
+
this._items.push({
|
|
3057
|
+
...item2,
|
|
3058
|
+
referenceId: item2.referenceId ?? crypto.randomUUID()
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
/**
|
|
3063
|
+
* Executes the batch by uploading the input file and creating a batch execution on the server.
|
|
3064
|
+
*
|
|
3065
|
+
* Returns a promise-like object that allows flexible usage patterns:
|
|
3066
|
+
* - Await for execution object: `const exec = await batch.execute()`
|
|
3067
|
+
* - Direct result access: `const result = await batch.execute().result`
|
|
3068
|
+
*
|
|
3069
|
+
* The batch items are serialized to JSONL format, uploaded to vault storage,
|
|
3070
|
+
* and submitted to the batch API for processing.
|
|
3071
|
+
*
|
|
3072
|
+
* @returns A promise-like object with a `result` property for direct result access.
|
|
3073
|
+
*
|
|
3074
|
+
* @example
|
|
3075
|
+
* ```typescript
|
|
3076
|
+
* // Direct result access (recommended for simple cases)
|
|
3077
|
+
* const result = await batch.execute().result
|
|
3078
|
+
* const outputs = await result.getResults()
|
|
3079
|
+
*
|
|
3080
|
+
* // Get execution object for event monitoring
|
|
3081
|
+
* const execution = await batch.execute()
|
|
3082
|
+
*
|
|
3083
|
+
* execution.on('statusChange', ([status, response]) => {
|
|
3084
|
+
* console.log(`Status: ${status}`)
|
|
3085
|
+
* if (response.state) {
|
|
3086
|
+
* console.log(`Progress: ${response.state.completed}/${response.state.total}`)
|
|
3087
|
+
* }
|
|
3088
|
+
* })
|
|
3089
|
+
*
|
|
3090
|
+
* execution.on('success', (result) => {
|
|
3091
|
+
* console.log('Batch completed!', result.requestId)
|
|
3092
|
+
* })
|
|
3093
|
+
*
|
|
3094
|
+
* const result = await execution.result
|
|
3095
|
+
*
|
|
3096
|
+
* // Iterate through results
|
|
3097
|
+
* for await (const output of result.iterateResults()) {
|
|
3098
|
+
* console.log(output)
|
|
3099
|
+
* }
|
|
3100
|
+
* ```
|
|
3101
|
+
*/
|
|
3102
|
+
execute() {
|
|
3103
|
+
const jsonLines = this._items.map((item) => ({
|
|
3104
|
+
...this.canvasIdentifier,
|
|
3105
|
+
...item
|
|
3106
|
+
})).map((item) => transformObjectFromCamelCaseToSnakeCase(item)).map((item) => JSON.stringify(item));
|
|
3107
|
+
const fileContent = new Blob([jsonLines.join("\n")], { type: "application/jsonl" });
|
|
3108
|
+
const file = TelaFile.create(fileContent);
|
|
3109
|
+
const client = this._client;
|
|
3110
|
+
const params = this._params;
|
|
3111
|
+
async function execute() {
|
|
3112
|
+
const { fileUrl } = await uploadFile(file, client);
|
|
3113
|
+
const body = {
|
|
3114
|
+
task: "async-completion",
|
|
3115
|
+
inputFile: fileUrl,
|
|
3116
|
+
webhookUrl: params.webhookUrl
|
|
3117
|
+
};
|
|
3118
|
+
return client.post("/_services/batch/batches", {
|
|
3119
|
+
body
|
|
3120
|
+
}).then((response) => new BatchExecution(response.id, client, params, response));
|
|
3121
|
+
}
|
|
3122
|
+
return {
|
|
3123
|
+
then(onfulfilled, onrejected) {
|
|
3124
|
+
return Promise.resolve(execute()).then((execution) => onfulfilled?.(execution) ?? execution).catch(onrejected);
|
|
3125
|
+
},
|
|
3126
|
+
get result() {
|
|
3127
|
+
return Promise.resolve(execute()).then((execution) => execution.result);
|
|
3128
|
+
}
|
|
3129
|
+
};
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
var __defProp$3 = Object.defineProperty;
|
|
3134
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3135
|
+
var __publicField$3 = (obj, key, value) => {
|
|
3136
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3137
|
+
return value;
|
|
3138
|
+
};
|
|
3139
|
+
function fetchById(id, client) {
|
|
3140
|
+
return client.get(`/prompt/${id}/promoted-version`);
|
|
3141
|
+
}
|
|
3142
|
+
function fetchByVersionId(versionId, client) {
|
|
3143
|
+
return client.get(`/prompt-version/${versionId}`);
|
|
3144
|
+
}
|
|
3145
|
+
function fetchByApplicationId(applicationId, client) {
|
|
3146
|
+
return client.get(`/prompt-application/${applicationId}/targetPromptVersion`);
|
|
3147
|
+
}
|
|
3148
|
+
function fetchByAny({ id, versionId, applicationId, client }) {
|
|
3149
|
+
if (applicationId) {
|
|
3150
|
+
return fetchByApplicationId(applicationId, client);
|
|
3151
|
+
}
|
|
3152
|
+
if (versionId) {
|
|
3153
|
+
return fetchByVersionId(versionId, client);
|
|
3154
|
+
}
|
|
3155
|
+
if (id) {
|
|
3156
|
+
return fetchById(id, client);
|
|
2273
3157
|
}
|
|
2274
3158
|
throw new Error("Either id, versionId, or applicationId must be provided");
|
|
2275
3159
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
3160
|
+
class Canvas {
|
|
3161
|
+
/**
|
|
3162
|
+
* Creates a new instance of the Canvas class. Usage of this constructor is not recommended.
|
|
3163
|
+
* Use the `tela.getCanvas` method instead.
|
|
3164
|
+
*
|
|
3165
|
+
* @private
|
|
3166
|
+
*/
|
|
3167
|
+
constructor({ id, applicationId, name, versionId, input, output, client, variables, isWorkflow }) {
|
|
3168
|
+
__publicField$3(this, "_id");
|
|
3169
|
+
__publicField$3(this, "_versionId");
|
|
3170
|
+
__publicField$3(this, "_applicationId");
|
|
3171
|
+
__publicField$3(this, "_name");
|
|
3172
|
+
__publicField$3(this, "_input");
|
|
3173
|
+
__publicField$3(this, "_output");
|
|
3174
|
+
__publicField$3(this, "_client");
|
|
3175
|
+
__publicField$3(this, "_variables");
|
|
3176
|
+
__publicField$3(this, "_isWorkflow");
|
|
3177
|
+
this._id = id;
|
|
3178
|
+
this._applicationId = applicationId;
|
|
3179
|
+
this._name = name;
|
|
3180
|
+
this._versionId = versionId;
|
|
3181
|
+
this._input = input && input(zod);
|
|
3182
|
+
this._output = output && output(zod);
|
|
3183
|
+
this._client = client;
|
|
3184
|
+
this._variables = variables;
|
|
3185
|
+
this._isWorkflow = isWorkflow;
|
|
3186
|
+
}
|
|
3187
|
+
/**
|
|
3188
|
+
* Gets a canvas by its ID.
|
|
3189
|
+
*
|
|
3190
|
+
* @param options - The options to use to get the canvas.
|
|
3191
|
+
* @param options.id - The ID of the canvas to get.
|
|
3192
|
+
* @param options.versionId - The version ID of the canvas to get.
|
|
3193
|
+
* @param options.applicationId - The application ID of the canvas to get.
|
|
3194
|
+
* @param options.client - The client to use to make the request.
|
|
3195
|
+
* @param options.input - The input schema of the canvas to get.
|
|
3196
|
+
* @param options.output - The output schema of the canvas to get.
|
|
3197
|
+
* @returns The canvas.
|
|
3198
|
+
*/
|
|
3199
|
+
static async get(options) {
|
|
3200
|
+
const { id, versionId, applicationId, client, input, output, skipSchemaValidation = false } = options;
|
|
3201
|
+
const promptVersion = await fetchByAny({ id, versionId, applicationId, client });
|
|
3202
|
+
const inputSchema = input && input(zod);
|
|
3203
|
+
const outputSchema = output && output(zod);
|
|
3204
|
+
if (!skipSchemaValidation) {
|
|
3205
|
+
validateSchemas("Canvas", inputSchema, outputSchema, promptVersion);
|
|
3206
|
+
}
|
|
3207
|
+
return new Canvas({
|
|
3208
|
+
id: promptVersion.promptId,
|
|
3209
|
+
versionId: promptVersion.id,
|
|
3210
|
+
applicationId: applicationId ?? void 0,
|
|
3211
|
+
name: promptVersion.title,
|
|
3212
|
+
input,
|
|
3213
|
+
output,
|
|
3214
|
+
client,
|
|
3215
|
+
variables: promptVersion.variables,
|
|
3216
|
+
isWorkflow: promptVersion.isWorkflow
|
|
3217
|
+
});
|
|
3218
|
+
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Gets the unique identifier of this canvas.
|
|
3221
|
+
*
|
|
3222
|
+
* @returns The canvas ID.
|
|
3223
|
+
*/
|
|
3224
|
+
get id() {
|
|
3225
|
+
if (!this._id) {
|
|
3226
|
+
throw new Error("Canvas ID is not set");
|
|
3227
|
+
}
|
|
3228
|
+
return this._id;
|
|
3229
|
+
}
|
|
3230
|
+
/**
|
|
3231
|
+
* Gets the name of this canvas, if provided.
|
|
3232
|
+
*
|
|
3233
|
+
* @returns The canvas name or undefined.
|
|
3234
|
+
*/
|
|
3235
|
+
get name() {
|
|
3236
|
+
if (!this._name) {
|
|
3237
|
+
throw new Error("Canvas name is not set");
|
|
3238
|
+
}
|
|
3239
|
+
return this._name;
|
|
3240
|
+
}
|
|
3241
|
+
/**
|
|
3242
|
+
* Gets the version identifier of this canvas, if specified.
|
|
3243
|
+
* When undefined, the latest promoted version is used.
|
|
3244
|
+
*
|
|
3245
|
+
* @returns The version ID or undefined.
|
|
3246
|
+
*/
|
|
3247
|
+
get versionId() {
|
|
3248
|
+
if (!this._versionId) {
|
|
3249
|
+
throw new Error("Canvas version ID is not set");
|
|
3250
|
+
}
|
|
3251
|
+
return this._versionId;
|
|
3252
|
+
}
|
|
3253
|
+
get applicationId() {
|
|
3254
|
+
if (!this._applicationId) {
|
|
3255
|
+
throw new Error("Canvas application ID is not set");
|
|
3256
|
+
}
|
|
3257
|
+
return this._applicationId;
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* Gets the variables of this canvas.
|
|
3261
|
+
*
|
|
3262
|
+
* @returns The variables of the canvas.
|
|
3263
|
+
*/
|
|
3264
|
+
get variables() {
|
|
3265
|
+
return this._variables;
|
|
3266
|
+
}
|
|
3267
|
+
/**
|
|
3268
|
+
* Gets whether this canvas is a workflow.
|
|
3269
|
+
*
|
|
3270
|
+
* @returns True if the canvas is a workflow.
|
|
3271
|
+
*/
|
|
3272
|
+
get isWorkflow() {
|
|
3273
|
+
return this._isWorkflow;
|
|
3274
|
+
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Gets whether this canvas is a workstation.
|
|
3277
|
+
* This is true if an application ID is provided.
|
|
3278
|
+
*
|
|
3279
|
+
* @returns True if the canvas is a workstation.
|
|
3280
|
+
*/
|
|
3281
|
+
get isWorkstation() {
|
|
3282
|
+
return Boolean(this._applicationId);
|
|
3283
|
+
}
|
|
3284
|
+
/**
|
|
3285
|
+
* Validates and parses input variables using the canvas input schema.
|
|
3286
|
+
*
|
|
3287
|
+
* @param variables - Raw input variables to validate.
|
|
3288
|
+
* @returns Parsed and validated variables.
|
|
3289
|
+
* @throws {ZodError} If validation fails when a Zod schema is configured.
|
|
3290
|
+
*/
|
|
3291
|
+
parseVariables(variables) {
|
|
2279
3292
|
try {
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
if (mismatches.length === 0) {
|
|
2283
|
-
return;
|
|
2284
|
-
}
|
|
2285
|
-
console.warn(
|
|
2286
|
-
`[Tela SDK - Canvas Input Validation] Input schema mismatches for canvas "${canvasIdentifier}":`
|
|
2287
|
-
);
|
|
2288
|
-
for (const mismatch of mismatches) {
|
|
2289
|
-
console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
|
|
3293
|
+
if (this._input instanceof z$1.ZodType) {
|
|
3294
|
+
return this._input.parse(variables);
|
|
2290
3295
|
}
|
|
3296
|
+
return variables;
|
|
2291
3297
|
} catch (error) {
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
);
|
|
3298
|
+
if (!(error instanceof ZodError)) {
|
|
3299
|
+
throw error;
|
|
3300
|
+
}
|
|
3301
|
+
throw new Error(z$1.prettifyError(error));
|
|
2296
3302
|
}
|
|
2297
3303
|
}
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
3304
|
+
execute(variables, params) {
|
|
3305
|
+
const parsedInput = this.parseVariables(variables);
|
|
3306
|
+
const idObject = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, canvasId: this._id };
|
|
3307
|
+
const fullParams = {
|
|
3308
|
+
...params ?? { async: false },
|
|
3309
|
+
...idObject
|
|
3310
|
+
};
|
|
3311
|
+
const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client, this.isWorkstation);
|
|
3312
|
+
return {
|
|
3313
|
+
then(onfulfilled, onrejected) {
|
|
3314
|
+
return Promise.resolve(execution.start()).then(() => onfulfilled?.(execution) ?? execution).catch(onrejected);
|
|
3315
|
+
},
|
|
3316
|
+
get result() {
|
|
3317
|
+
return Promise.resolve(execution.start()).then(() => execution.result);
|
|
3318
|
+
}
|
|
3319
|
+
};
|
|
3320
|
+
}
|
|
3321
|
+
/**
|
|
3322
|
+
* Fetches an existing async execution by its ID.
|
|
3323
|
+
*
|
|
3324
|
+
* This method retrieves the current state of an async execution that was previously
|
|
3325
|
+
* started on this canvas. Only async executions can be fetched, as they are the only
|
|
3326
|
+
* ones with persistent UUIDs on the server.
|
|
3327
|
+
*
|
|
3328
|
+
* @param id - The UUID of the async execution to fetch.
|
|
3329
|
+
* @param options - Optional configuration for polling behavior.
|
|
3330
|
+
* @param options.pollingInterval - Time in milliseconds between polling attempts (default: 1000).
|
|
3331
|
+
* @param options.pollingTimeout - Maximum time in milliseconds to wait for completion (default: 60000).
|
|
3332
|
+
* @throws {InvalidExecutionModeError} If the provided ID is not a valid UUID.
|
|
3333
|
+
* @returns A promise resolving to a CanvasExecution instance with the fetched state.
|
|
3334
|
+
*
|
|
3335
|
+
* @example
|
|
3336
|
+
* ```typescript
|
|
3337
|
+
* // Start an async execution
|
|
3338
|
+
* const execution = await canvas.execute({ query: 'test' }, { async: true })
|
|
3339
|
+
* const executionId = execution.id
|
|
3340
|
+
*
|
|
3341
|
+
* // Later, fetch the execution by ID
|
|
3342
|
+
* const fetched = await canvas.getExecution(executionId)
|
|
3343
|
+
* console.log(fetched.status) // 'running', 'succeeded', or 'failed'
|
|
3344
|
+
*
|
|
3345
|
+
* // Use poll() for event-driven progress tracking
|
|
3346
|
+
* fetched.on('statusChange', (status) => console.log('Status:', status))
|
|
3347
|
+
* fetched.poll()
|
|
3348
|
+
* ```
|
|
3349
|
+
*/
|
|
3350
|
+
async getExecution(id, options) {
|
|
3351
|
+
return CanvasExecution.fetch(
|
|
3352
|
+
id,
|
|
3353
|
+
this._output,
|
|
3354
|
+
this._client,
|
|
3355
|
+
{
|
|
3356
|
+
...options,
|
|
3357
|
+
isTask: this.isWorkstation
|
|
3358
|
+
}
|
|
3359
|
+
);
|
|
3360
|
+
}
|
|
3361
|
+
/**
|
|
3362
|
+
* Prepares to execute this canvas in batch.
|
|
3363
|
+
*
|
|
3364
|
+
* @param params - The parameters for the batch.
|
|
3365
|
+
* @param params.pollingInterval - The interval between polling attempts.
|
|
3366
|
+
* @param params.pollingTimeout - The timeout for the batch.
|
|
3367
|
+
* @param params.webhookUrl - The webhook URL for the batch.
|
|
3368
|
+
*
|
|
3369
|
+
* @example
|
|
3370
|
+
* ```typescript
|
|
3371
|
+
* const batch = canvas.createBatch({
|
|
3372
|
+
* pollingInterval: '1s',
|
|
3373
|
+
* pollingTimeout: '1m',
|
|
3374
|
+
* webhookUrl: 'https://example.com/webhook',
|
|
3375
|
+
* })
|
|
3376
|
+
*
|
|
3377
|
+
* batch.add({
|
|
3378
|
+
* referenceId: crypto.randomUUID(), // Optional
|
|
3379
|
+
* variables: { query: 'Hello' },
|
|
3380
|
+
* })
|
|
3381
|
+
*
|
|
3382
|
+
* const execution = await batch.execute()
|
|
3383
|
+
* const result = await execution.result
|
|
3384
|
+
* const resultFile = await execution.downloadOutputFile()
|
|
3385
|
+
* ```
|
|
3386
|
+
*
|
|
3387
|
+
* @returns The batch instance that can be used to manage the batch.
|
|
3388
|
+
*/
|
|
3389
|
+
createBatch(params = {}) {
|
|
3390
|
+
const canvasIdentifier = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, id: this._id };
|
|
3391
|
+
return new Batch(this._client, canvasIdentifier, params);
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
const TaskStatus = z$1.enum(["created", "failed", "running", "validating", "completed", "cancelled"]);
|
|
3396
|
+
const OutputContent = z$1.object({
|
|
3397
|
+
role: z$1.literal("assistant"),
|
|
3398
|
+
content: z$1.unknown(),
|
|
3399
|
+
toolCalls: z$1.array(z$1.any()),
|
|
3400
|
+
functionCall: z$1.any()
|
|
3401
|
+
});
|
|
3402
|
+
const RawInput = z$1.object({
|
|
3403
|
+
async: z$1.boolean(),
|
|
3404
|
+
stream: z$1.boolean(),
|
|
3405
|
+
variables: z$1.record(z$1.string(), z$1.unknown()),
|
|
3406
|
+
applicationId: z$1.string()
|
|
3407
|
+
});
|
|
3408
|
+
z$1.object({
|
|
3409
|
+
id: z$1.string(),
|
|
3410
|
+
reference: z$1.number(),
|
|
3411
|
+
name: z$1.string(),
|
|
3412
|
+
status: TaskStatus,
|
|
3413
|
+
rawInput: RawInput,
|
|
3414
|
+
inputContent: z$1.any(),
|
|
3415
|
+
outputContent: OutputContent,
|
|
3416
|
+
originalOutputContent: OutputContent,
|
|
3417
|
+
createdBy: z$1.string(),
|
|
3418
|
+
approvedBy: z$1.any(),
|
|
3419
|
+
approvedAt: z$1.any(),
|
|
3420
|
+
completionRunId: z$1.string(),
|
|
3421
|
+
workflowRunId: z$1.any(),
|
|
3422
|
+
promptVersionId: z$1.string(),
|
|
3423
|
+
promptApplicationId: z$1.string(),
|
|
3424
|
+
workspaceId: z$1.string(),
|
|
3425
|
+
metadata: z$1.any(),
|
|
3426
|
+
tags: z$1.array(z$1.string()),
|
|
3427
|
+
createdAt: z$1.string(),
|
|
3428
|
+
updatedAt: z$1.string(),
|
|
3429
|
+
deletedAt: z$1.any(),
|
|
3430
|
+
requestId: z$1.string()
|
|
3431
|
+
});
|
|
3432
|
+
|
|
3433
|
+
var __defProp$2 = Object.defineProperty;
|
|
3434
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3435
|
+
var __publicField$2 = (obj, key, value) => {
|
|
3436
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3437
|
+
return value;
|
|
3438
|
+
};
|
|
3439
|
+
class Task extends Emittery {
|
|
3440
|
+
constructor(client, variables, task, requestId, outputSchema, skipResultValidation = false) {
|
|
3441
|
+
super();
|
|
3442
|
+
__publicField$2(this, "_variables");
|
|
3443
|
+
__publicField$2(this, "_task");
|
|
3444
|
+
__publicField$2(this, "_abortController", new AbortController());
|
|
3445
|
+
__publicField$2(this, "_client");
|
|
3446
|
+
__publicField$2(this, "_outputSchema");
|
|
3447
|
+
__publicField$2(this, "_skipResultValidation");
|
|
3448
|
+
__publicField$2(this, "_resultPromise");
|
|
3449
|
+
__publicField$2(this, "_status");
|
|
3450
|
+
__publicField$2(this, "_requestId");
|
|
3451
|
+
this._variables = variables;
|
|
3452
|
+
this._task = task;
|
|
3453
|
+
this._client = client;
|
|
3454
|
+
this._outputSchema = outputSchema;
|
|
3455
|
+
this._skipResultValidation = skipResultValidation;
|
|
3456
|
+
this._status = task.status;
|
|
3457
|
+
this._requestId = requestId;
|
|
3458
|
+
}
|
|
3459
|
+
/**
|
|
3460
|
+
* Gets the unique task ID assigned by the server.
|
|
3461
|
+
*
|
|
3462
|
+
* @returns The task ID.
|
|
3463
|
+
*/
|
|
3464
|
+
get id() {
|
|
3465
|
+
if (!this._task.id) {
|
|
3466
|
+
throw new Error("Task ID is not available");
|
|
3467
|
+
}
|
|
3468
|
+
return this._task.id;
|
|
3469
|
+
}
|
|
3470
|
+
/**
|
|
3471
|
+
* Gets the request ID from the `x-request-id` header of the task creation request.
|
|
3472
|
+
*
|
|
3473
|
+
* This is the request ID from the initial POST /task request that created the task.
|
|
3474
|
+
* Each API request has its own unique request ID.
|
|
3475
|
+
*
|
|
3476
|
+
* For polling operations, different request IDs are available:
|
|
3477
|
+
* - `task.requestId` - ID from the task creation request
|
|
3478
|
+
* - `pollResult.requestId` - ID from each polling request (in poll events)
|
|
3479
|
+
* - `result.requestId` - ID from the final successful polling request (in success events)
|
|
3480
|
+
*
|
|
3481
|
+
* @returns A promise that resolves to the request ID from the task creation request.
|
|
3482
|
+
*
|
|
3483
|
+
* @example
|
|
3484
|
+
* ```typescript
|
|
3485
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3486
|
+
* const requestId = await task.requestId
|
|
3487
|
+
* console.log('Request ID:', requestId)
|
|
3488
|
+
* ```
|
|
3489
|
+
*/
|
|
3490
|
+
get requestId() {
|
|
3491
|
+
return this._requestId;
|
|
3492
|
+
}
|
|
3493
|
+
/**
|
|
3494
|
+
* Gets the latest known status of the task.
|
|
3495
|
+
*
|
|
3496
|
+
* Status values and transitions:
|
|
3497
|
+
* - `created` → `running` → `completed` or `failed`
|
|
3498
|
+
*
|
|
3499
|
+
* **Important:** Status is set to `completed` only after successful validation.
|
|
3500
|
+
* If validation fails, status will be `failed` even if the API request succeeded.
|
|
3501
|
+
*
|
|
3502
|
+
* Use the `statusChange` event to track status transitions in real-time.
|
|
3503
|
+
*
|
|
3504
|
+
* @returns The current status of the task.
|
|
3505
|
+
*
|
|
3506
|
+
* @example
|
|
3507
|
+
* ```typescript
|
|
3508
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3509
|
+
* console.log(task.status) // 'created'
|
|
3510
|
+
*
|
|
3511
|
+
* await task.result
|
|
3512
|
+
* console.log(task.status) // 'completed' or 'failed'
|
|
3513
|
+
* ```
|
|
3514
|
+
*/
|
|
3515
|
+
get status() {
|
|
3516
|
+
return this._status;
|
|
3517
|
+
}
|
|
3518
|
+
/**
|
|
3519
|
+
* Sets the status of the task and emits statusChange event.
|
|
3520
|
+
*
|
|
3521
|
+
* @param status - The new status of the task.
|
|
3522
|
+
* @private
|
|
3523
|
+
*/
|
|
3524
|
+
set status(status) {
|
|
3525
|
+
const changed = this._status !== status;
|
|
3526
|
+
this._status = status;
|
|
3527
|
+
if (changed) {
|
|
3528
|
+
this.emit("statusChange", status);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
/**
|
|
3532
|
+
* Gets the input variables provided to this task.
|
|
3533
|
+
*
|
|
3534
|
+
* @returns The variables object.
|
|
3535
|
+
*/
|
|
3536
|
+
get variables() {
|
|
3537
|
+
return this._variables;
|
|
3538
|
+
}
|
|
3539
|
+
/**
|
|
3540
|
+
* Gets the task label (alias for name).
|
|
3541
|
+
*
|
|
3542
|
+
* @returns The task name.
|
|
3543
|
+
*/
|
|
3544
|
+
get label() {
|
|
3545
|
+
return this.name;
|
|
3546
|
+
}
|
|
3547
|
+
/**
|
|
3548
|
+
* Gets the task name.
|
|
3549
|
+
*
|
|
3550
|
+
* @returns The task name.
|
|
3551
|
+
*/
|
|
3552
|
+
get name() {
|
|
3553
|
+
return this._task.name;
|
|
3554
|
+
}
|
|
3555
|
+
/**
|
|
3556
|
+
* Gets the task tags.
|
|
3557
|
+
*
|
|
3558
|
+
* @returns The task tags.
|
|
3559
|
+
*/
|
|
3560
|
+
get tags() {
|
|
3561
|
+
return this._task.tags;
|
|
3562
|
+
}
|
|
3563
|
+
/**
|
|
3564
|
+
* Gets the raw task definition from the server.
|
|
3565
|
+
*
|
|
3566
|
+
* @returns The raw task definition.
|
|
3567
|
+
*/
|
|
3568
|
+
get rawTask() {
|
|
3569
|
+
return this._task;
|
|
3570
|
+
}
|
|
3571
|
+
/**
|
|
3572
|
+
* Starts polling for the task result without waiting for the promise to resolve.
|
|
3573
|
+
* This allows users to track task progress via events rather than awaiting a promise.
|
|
3574
|
+
*
|
|
3575
|
+
* The following events will be emitted during polling:
|
|
3576
|
+
* - `statusChange`: Emitted when the task status changes (e.g., 'created' → 'running' → 'completed')
|
|
3577
|
+
* - `poll`: Emitted on each polling attempt with the server response
|
|
3578
|
+
* - `success`: Emitted when the task completes successfully with the final result
|
|
3579
|
+
* - `error`: Emitted if the task fails
|
|
3580
|
+
*
|
|
3581
|
+
* **Important:** Events are only emitted while polling is active. You must call `poll()` or
|
|
3582
|
+
* await `task.result` to start polling. Simply setting up event listeners without starting
|
|
3583
|
+
* polling will not trigger any events.
|
|
3584
|
+
*
|
|
3585
|
+
* @example
|
|
3586
|
+
* ```typescript
|
|
3587
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3588
|
+
*
|
|
3589
|
+
* // Set up event listeners
|
|
3590
|
+
* task.on('statusChange', (status) => {
|
|
3591
|
+
* console.log('Status:', status)
|
|
3592
|
+
* })
|
|
3593
|
+
*
|
|
3594
|
+
* task.on('success', (result) => {
|
|
3595
|
+
* console.log('Completed:', result)
|
|
3596
|
+
* })
|
|
3597
|
+
*
|
|
3598
|
+
* task.on('error', (error) => {
|
|
3599
|
+
* console.error('Failed:', error)
|
|
3600
|
+
* })
|
|
3601
|
+
*
|
|
3602
|
+
* // Start polling without waiting
|
|
3603
|
+
* task.poll()
|
|
3604
|
+
* ```
|
|
3605
|
+
*/
|
|
3606
|
+
poll() {
|
|
3607
|
+
if (this._resultPromise) {
|
|
3608
|
+
return;
|
|
3609
|
+
}
|
|
3610
|
+
this._resultPromise = this.startPolling();
|
|
3611
|
+
this._resultPromise.catch(() => {
|
|
3612
|
+
});
|
|
3613
|
+
}
|
|
3614
|
+
/**
|
|
3615
|
+
* Gets the task result. Automatically starts polling if not already started.
|
|
3616
|
+
*
|
|
3617
|
+
* @returns A promise that resolves to the validated task output.
|
|
3618
|
+
*
|
|
3619
|
+
* @example
|
|
3620
|
+
* ```typescript
|
|
3621
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3622
|
+
* const result = await task.result
|
|
3623
|
+
* console.log(result)
|
|
3624
|
+
* ```
|
|
3625
|
+
*/
|
|
3626
|
+
get result() {
|
|
3627
|
+
if (this._resultPromise) {
|
|
3628
|
+
return this._resultPromise;
|
|
3629
|
+
}
|
|
3630
|
+
this._resultPromise = this.startPolling();
|
|
3631
|
+
return this._resultPromise;
|
|
3632
|
+
}
|
|
3633
|
+
/**
|
|
3634
|
+
* Starts the polling process to retrieve task results.
|
|
3635
|
+
* Emits events during the polling lifecycle and validates output before resolving.
|
|
3636
|
+
*
|
|
3637
|
+
* @returns A promise that resolves to the validated task output.
|
|
3638
|
+
* @private
|
|
3639
|
+
*/
|
|
3640
|
+
async startPolling() {
|
|
3641
|
+
const result = await new Poller({
|
|
3642
|
+
interval: 1e3,
|
|
3643
|
+
timeout: 6e4,
|
|
3644
|
+
abortSignal: this._abortController.signal
|
|
3645
|
+
}).start(async () => {
|
|
3646
|
+
const response = await this._client.get(`/task/${this.id}`, {
|
|
3647
|
+
signal: this._abortController.signal
|
|
3648
|
+
});
|
|
3649
|
+
const newStatus = response.status;
|
|
3650
|
+
this.status = newStatus;
|
|
3651
|
+
this.emit("poll", response);
|
|
3652
|
+
if (response.status === "failed") {
|
|
3653
|
+
const error = new TaskFailedError(response, "Task failure reported by the server");
|
|
3654
|
+
this.status = "failed";
|
|
3655
|
+
this.emit("error", error);
|
|
3656
|
+
if (this.listenerCount("error") === 0) {
|
|
3657
|
+
throw error;
|
|
3658
|
+
}
|
|
3659
|
+
return {
|
|
3660
|
+
done: true,
|
|
3661
|
+
value: void 0
|
|
3662
|
+
};
|
|
2307
3663
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
3664
|
+
if (!["completed", "validating"].includes(response.status)) {
|
|
3665
|
+
return {
|
|
3666
|
+
done: false,
|
|
3667
|
+
value: void 0
|
|
3668
|
+
};
|
|
2311
3669
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
3670
|
+
return {
|
|
3671
|
+
done: true,
|
|
3672
|
+
value: response
|
|
3673
|
+
};
|
|
3674
|
+
});
|
|
3675
|
+
try {
|
|
3676
|
+
const value = result;
|
|
3677
|
+
if (value === void 0) {
|
|
3678
|
+
return void 0;
|
|
2317
3679
|
}
|
|
3680
|
+
const content = value.outputContent.content;
|
|
3681
|
+
const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z.ZodType) ? content : this._outputSchema.parse(content);
|
|
3682
|
+
this.status = value.status;
|
|
3683
|
+
this.emit("success", validatedContent);
|
|
3684
|
+
return validatedContent;
|
|
2318
3685
|
} catch (error) {
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
);
|
|
3686
|
+
this.status = "failed";
|
|
3687
|
+
const castError = error instanceof Error ? error : new Error(String(error));
|
|
3688
|
+
const message = castError instanceof ZodError ? z.prettifyError(castError) : castError.message;
|
|
3689
|
+
this.emit("error", new TaskFailedError(result, message, castError));
|
|
3690
|
+
if (this.listenerCount("error") === 0) {
|
|
3691
|
+
throw error;
|
|
3692
|
+
}
|
|
3693
|
+
return void 0;
|
|
2323
3694
|
}
|
|
2324
3695
|
}
|
|
2325
3696
|
}
|
|
2326
|
-
|
|
3697
|
+
|
|
3698
|
+
var __defProp$1 = Object.defineProperty;
|
|
3699
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3700
|
+
var __publicField$1 = (obj, key, value) => {
|
|
3701
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3702
|
+
return value;
|
|
3703
|
+
};
|
|
3704
|
+
const DateRange = z.object({
|
|
3705
|
+
since: z.union([z.date().transform((date) => date.toISOString()), z.iso.datetime()]),
|
|
3706
|
+
until: z.union([z.date().transform((date) => date.toISOString()), z.iso.datetime()])
|
|
3707
|
+
});
|
|
3708
|
+
const TaskListFilters = z.looseObject({
|
|
3709
|
+
id: z.uuid().array().optional(),
|
|
3710
|
+
name: z.string().optional(),
|
|
3711
|
+
status: z.array(TaskStatus).optional(),
|
|
3712
|
+
approvedAt: DateRange.partial().optional(),
|
|
3713
|
+
createdAt: DateRange.partial().optional(),
|
|
3714
|
+
updatedAt: DateRange.partial().optional(),
|
|
3715
|
+
approvedBy: z.string().optional(),
|
|
3716
|
+
createdBy: z.string().optional(),
|
|
3717
|
+
completionRunId: z.uuid().optional(),
|
|
3718
|
+
promptVersionId: z.uuid().optional()
|
|
3719
|
+
}).transform(({ name, approvedAt, createdAt, updatedAt, ...rest }) => ({
|
|
3720
|
+
taskName: name,
|
|
3721
|
+
...approvedAt ? { approvedAtSince: approvedAt.since, approvedAtUntil: approvedAt.until } : {},
|
|
3722
|
+
...createdAt ? { createdAtSince: createdAt.since, createdAtUntil: createdAt.until } : {},
|
|
3723
|
+
...updatedAt ? { updatedAtSince: updatedAt.since, updatedAtUntil: updatedAt.until } : {},
|
|
3724
|
+
...rest
|
|
3725
|
+
}));
|
|
3726
|
+
const TaskListOptions = z.looseObject({
|
|
3727
|
+
limit: z.number().optional(),
|
|
3728
|
+
offset: z.number().optional(),
|
|
3729
|
+
order: z.object({
|
|
3730
|
+
by: z.enum(["createdAt", "updatedAt", "approvedAt", "status", "reference", "name"]),
|
|
3731
|
+
direction: z.enum(["asc", "desc"])
|
|
3732
|
+
}).optional()
|
|
3733
|
+
}).transform(({ order, ...rest }) => ({
|
|
3734
|
+
orderBy: order?.by,
|
|
3735
|
+
orderDirection: order?.direction,
|
|
3736
|
+
...rest
|
|
3737
|
+
}));
|
|
3738
|
+
class Workstation {
|
|
2327
3739
|
/**
|
|
2328
|
-
* Creates a new instance
|
|
2329
|
-
* Use the `tela.getCanvas` method instead.
|
|
3740
|
+
* Creates a new Workstation instance.
|
|
2330
3741
|
*
|
|
2331
|
-
* @
|
|
3742
|
+
* Use {@link Workstation.get} instead.
|
|
3743
|
+
* @internal
|
|
2332
3744
|
*/
|
|
2333
|
-
constructor({
|
|
3745
|
+
constructor({ client, applicationId, promptVersion, input, output }) {
|
|
2334
3746
|
__publicField$1(this, "_id");
|
|
2335
|
-
__publicField$1(this, "
|
|
2336
|
-
__publicField$1(this, "
|
|
2337
|
-
__publicField$1(this, "_name");
|
|
3747
|
+
__publicField$1(this, "_promptVersion");
|
|
3748
|
+
__publicField$1(this, "_client");
|
|
2338
3749
|
__publicField$1(this, "_input");
|
|
2339
3750
|
__publicField$1(this, "_output");
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
this._id = id;
|
|
2344
|
-
this._applicationId = applicationId;
|
|
2345
|
-
this._name = name;
|
|
2346
|
-
this._versionId = versionId;
|
|
3751
|
+
this._id = applicationId;
|
|
3752
|
+
this._promptVersion = promptVersion;
|
|
3753
|
+
this._client = client;
|
|
2347
3754
|
this._input = input && input(zod);
|
|
2348
3755
|
this._output = output && output(zod);
|
|
2349
|
-
this._client = client;
|
|
2350
|
-
this._variables = variables;
|
|
2351
|
-
this._isWorkflow = isWorkflow;
|
|
2352
3756
|
}
|
|
2353
3757
|
/**
|
|
2354
|
-
*
|
|
3758
|
+
* The unique identifier for this workstation (application ID).
|
|
3759
|
+
*/
|
|
3760
|
+
get id() {
|
|
3761
|
+
return this._id;
|
|
3762
|
+
}
|
|
3763
|
+
/**
|
|
3764
|
+
* The prompt version configuration for this workstation.
|
|
3765
|
+
*/
|
|
3766
|
+
get promptVersion() {
|
|
3767
|
+
return this._promptVersion;
|
|
3768
|
+
}
|
|
3769
|
+
/**
|
|
3770
|
+
* Retrieves a workstation by application ID and optionally validates schemas.
|
|
2355
3771
|
*
|
|
2356
|
-
*
|
|
2357
|
-
*
|
|
2358
|
-
* @param options
|
|
2359
|
-
* @param options.
|
|
2360
|
-
* @param options.
|
|
2361
|
-
* @param options.input -
|
|
2362
|
-
* @param options.output -
|
|
2363
|
-
* @
|
|
3772
|
+
* This is the recommended way to create a Workstation instance.
|
|
3773
|
+
*
|
|
3774
|
+
* @param options - Configuration options
|
|
3775
|
+
* @param options.client - The BaseClient instance for API communication
|
|
3776
|
+
* @param options.applicationId - The unique ID of the workstation
|
|
3777
|
+
* @param options.input - Optional input schema function
|
|
3778
|
+
* @param options.output - Optional output schema function
|
|
3779
|
+
* @param options.skipSchemaValidation - Whether to skip schema validation (defaults to false)
|
|
3780
|
+
* @returns A promise that resolves to a Workstation instance
|
|
3781
|
+
*
|
|
3782
|
+
* @throws {Error} If schema validation fails (when schemas are provided and skipSchemaValidation is false)
|
|
3783
|
+
*
|
|
3784
|
+
* @example
|
|
3785
|
+
* ```typescript
|
|
3786
|
+
* const workstation = await Workstation.get({
|
|
3787
|
+
* client,
|
|
3788
|
+
* applicationId: 'app-123',
|
|
3789
|
+
* input: schema => schema.object({
|
|
3790
|
+
* query: schema.string(),
|
|
3791
|
+
* }),
|
|
3792
|
+
* output: schema => schema.object({
|
|
3793
|
+
* answer: schema.string(),
|
|
3794
|
+
* }),
|
|
3795
|
+
* })
|
|
3796
|
+
* ```
|
|
2364
3797
|
*/
|
|
2365
3798
|
static async get(options) {
|
|
2366
|
-
const {
|
|
2367
|
-
const
|
|
3799
|
+
const { client, applicationId, input, output, skipSchemaValidation = false } = options;
|
|
3800
|
+
const id = z.uuid({ error: (error) => `Invalid application ID: '${error.input}'. Must be a valid UUID.` }).parse(applicationId);
|
|
3801
|
+
const promptVersion = await client.get(`/prompt-application/${id}/targetPromptVersion`);
|
|
2368
3802
|
const inputSchema = input && input(zod);
|
|
2369
3803
|
const outputSchema = output && output(zod);
|
|
2370
3804
|
if (!skipSchemaValidation) {
|
|
2371
|
-
validateSchemas(inputSchema, outputSchema, promptVersion);
|
|
3805
|
+
validateSchemas("Workstation", inputSchema, outputSchema, promptVersion);
|
|
2372
3806
|
}
|
|
2373
|
-
return new
|
|
2374
|
-
id: promptVersion.promptId,
|
|
2375
|
-
versionId: promptVersion.id,
|
|
2376
|
-
applicationId: applicationId ?? void 0,
|
|
2377
|
-
name: promptVersion.title,
|
|
2378
|
-
input,
|
|
2379
|
-
output,
|
|
3807
|
+
return new Workstation({
|
|
2380
3808
|
client,
|
|
2381
|
-
|
|
2382
|
-
|
|
3809
|
+
applicationId: id,
|
|
3810
|
+
promptVersion,
|
|
3811
|
+
input,
|
|
3812
|
+
output
|
|
2383
3813
|
});
|
|
2384
3814
|
}
|
|
2385
3815
|
/**
|
|
2386
|
-
*
|
|
3816
|
+
* Creates a new task for this workstation and returns a promise-like object.
|
|
2387
3817
|
*
|
|
2388
|
-
*
|
|
2389
|
-
|
|
2390
|
-
get id() {
|
|
2391
|
-
if (!this._id) {
|
|
2392
|
-
throw new Error("Canvas ID is not set");
|
|
2393
|
-
}
|
|
2394
|
-
return this._id;
|
|
2395
|
-
}
|
|
2396
|
-
/**
|
|
2397
|
-
* Gets the name of this canvas, if provided.
|
|
3818
|
+
* The returned object can be awaited directly to get the Task instance, or you can
|
|
3819
|
+
* access `.result` to get the final task output directly.
|
|
2398
3820
|
*
|
|
2399
|
-
* @
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
if (!this._name) {
|
|
2403
|
-
throw new Error("Canvas name is not set");
|
|
2404
|
-
}
|
|
2405
|
-
return this._name;
|
|
2406
|
-
}
|
|
2407
|
-
/**
|
|
2408
|
-
* Gets the version identifier of this canvas, if specified.
|
|
2409
|
-
* When undefined, the latest promoted version is used.
|
|
3821
|
+
* @param variables - Input variables for the task (must match the input schema)
|
|
3822
|
+
* @param params - Optional task parameters (label, tags, skipResultValidation)
|
|
3823
|
+
* @returns A promise-like object that resolves to the Task instance
|
|
2410
3824
|
*
|
|
2411
|
-
* @
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
throw new Error("Canvas version ID is not set");
|
|
2416
|
-
}
|
|
2417
|
-
return this._versionId;
|
|
2418
|
-
}
|
|
2419
|
-
get applicationId() {
|
|
2420
|
-
if (!this._applicationId) {
|
|
2421
|
-
throw new Error("Canvas application ID is not set");
|
|
2422
|
-
}
|
|
2423
|
-
return this._applicationId;
|
|
2424
|
-
}
|
|
2425
|
-
/**
|
|
2426
|
-
* Gets the variables of this canvas.
|
|
3825
|
+
* @example
|
|
3826
|
+
* ```typescript
|
|
3827
|
+
* // Get the task instance
|
|
3828
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
2427
3829
|
*
|
|
2428
|
-
*
|
|
3830
|
+
* // Or get the result directly
|
|
3831
|
+
* const result = await workstation.createTask({ query: 'test' }).result
|
|
3832
|
+
* ```
|
|
2429
3833
|
*/
|
|
2430
|
-
|
|
2431
|
-
|
|
3834
|
+
createTask(variables, params = {}) {
|
|
3835
|
+
const validatedVariables = this.parseVariables(variables);
|
|
3836
|
+
const taskDefinitionPromise = this.resolveVariables(validatedVariables).then((resolvedVariables) => this._client.post(`/task`, {
|
|
3837
|
+
body: {
|
|
3838
|
+
name: params.label ?? "Task from SDK",
|
|
3839
|
+
tags: params.tags ?? void 0,
|
|
3840
|
+
promptApplicationId: this._id,
|
|
3841
|
+
rawInput: {
|
|
3842
|
+
variables: resolvedVariables
|
|
3843
|
+
}
|
|
3844
|
+
},
|
|
3845
|
+
transformCase: false
|
|
3846
|
+
})).then((response) => {
|
|
3847
|
+
return new Task(
|
|
3848
|
+
this._client,
|
|
3849
|
+
variables,
|
|
3850
|
+
response[0],
|
|
3851
|
+
response.requestId,
|
|
3852
|
+
this._output,
|
|
3853
|
+
params.skipResultValidation ?? false
|
|
3854
|
+
);
|
|
3855
|
+
});
|
|
3856
|
+
return {
|
|
3857
|
+
then(onfulfilled, onrejected) {
|
|
3858
|
+
return Promise.resolve(taskDefinitionPromise).then((task) => onfulfilled?.(task) ?? task).catch(onrejected);
|
|
3859
|
+
},
|
|
3860
|
+
get result() {
|
|
3861
|
+
return Promise.resolve(taskDefinitionPromise).then((task) => task.result);
|
|
3862
|
+
}
|
|
3863
|
+
};
|
|
2432
3864
|
}
|
|
2433
3865
|
/**
|
|
2434
|
-
*
|
|
3866
|
+
* Retrieves an existing task by its ID.
|
|
2435
3867
|
*
|
|
2436
|
-
*
|
|
2437
|
-
*/
|
|
2438
|
-
get isWorkflow() {
|
|
2439
|
-
return this._isWorkflow;
|
|
2440
|
-
}
|
|
2441
|
-
/**
|
|
2442
|
-
* Gets whether this canvas is a workstation.
|
|
2443
|
-
* This is true if an application ID is provided.
|
|
3868
|
+
* This is useful for resuming monitoring of a task that was created earlier.
|
|
2444
3869
|
*
|
|
2445
|
-
* @
|
|
3870
|
+
* @param id - The task ID to retrieve
|
|
3871
|
+
* @param options - Optional configuration
|
|
3872
|
+
* @param options.skipResultValidation - Whether to skip output validation
|
|
3873
|
+
* @returns A promise that resolves to the Task instance
|
|
3874
|
+
*
|
|
3875
|
+
* @example
|
|
3876
|
+
* ```typescript
|
|
3877
|
+
* const task = await workstation.getTask('task-id')
|
|
3878
|
+
*
|
|
3879
|
+
* // Set up event listeners
|
|
3880
|
+
* task.on('statusChange', (status) => console.log('Status:', status))
|
|
3881
|
+
* task.on('success', (result) => console.log('Result:', result))
|
|
3882
|
+
*
|
|
3883
|
+
* // Start polling
|
|
3884
|
+
* task.poll()
|
|
3885
|
+
* ```
|
|
2446
3886
|
*/
|
|
2447
|
-
|
|
2448
|
-
|
|
3887
|
+
async getTask(id, options = {}) {
|
|
3888
|
+
const taskResponse = await this._client.get(`/task/${id}`);
|
|
3889
|
+
return new Task(
|
|
3890
|
+
this._client,
|
|
3891
|
+
taskResponse.rawInput.variables,
|
|
3892
|
+
taskResponse,
|
|
3893
|
+
taskResponse.requestId,
|
|
3894
|
+
this._output,
|
|
3895
|
+
options.skipResultValidation ?? false
|
|
3896
|
+
);
|
|
2449
3897
|
}
|
|
2450
3898
|
/**
|
|
2451
|
-
* Validates and parses input variables using the
|
|
3899
|
+
* Validates and parses input variables using the workstation input schema.
|
|
2452
3900
|
*
|
|
2453
3901
|
* @param variables - Raw input variables to validate.
|
|
2454
3902
|
* @returns Parsed and validated variables.
|
|
@@ -2456,7 +3904,7 @@ class Canvas {
|
|
|
2456
3904
|
*/
|
|
2457
3905
|
parseVariables(variables) {
|
|
2458
3906
|
try {
|
|
2459
|
-
if (this._input instanceof z
|
|
3907
|
+
if (this._input instanceof z.ZodType) {
|
|
2460
3908
|
return this._input.parse(variables);
|
|
2461
3909
|
}
|
|
2462
3910
|
return variables;
|
|
@@ -2464,65 +3912,140 @@ class Canvas {
|
|
|
2464
3912
|
if (!(error instanceof ZodError)) {
|
|
2465
3913
|
throw error;
|
|
2466
3914
|
}
|
|
2467
|
-
throw new Error(z
|
|
3915
|
+
throw new Error(z.prettifyError(error));
|
|
2468
3916
|
}
|
|
2469
3917
|
}
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
const
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
get result() {
|
|
2483
|
-
return Promise.resolve(execution.start()).then(() => execution.result);
|
|
3918
|
+
/**
|
|
3919
|
+
* Processes variables and uploads any TelaFile instances to the server.
|
|
3920
|
+
* Replaces TelaFile objects with their uploaded URLs while preserving other values.
|
|
3921
|
+
*
|
|
3922
|
+
* @returns A promise resolving to the processed variables object.
|
|
3923
|
+
*/
|
|
3924
|
+
async resolveVariables(inputVariables) {
|
|
3925
|
+
const variables = {};
|
|
3926
|
+
for (const [key, value] of Object.entries(inputVariables)) {
|
|
3927
|
+
if (isTelaFileArray(value)) {
|
|
3928
|
+
variables[key] = { files: await uploadFiles(value, this._client) };
|
|
3929
|
+
continue;
|
|
2484
3930
|
}
|
|
2485
|
-
|
|
3931
|
+
if (isTelaFile(value)) {
|
|
3932
|
+
variables[key] = await uploadFile(value, this._client);
|
|
3933
|
+
continue;
|
|
3934
|
+
}
|
|
3935
|
+
variables[key] = value;
|
|
3936
|
+
}
|
|
3937
|
+
return variables;
|
|
2486
3938
|
}
|
|
2487
3939
|
/**
|
|
2488
|
-
*
|
|
3940
|
+
* Lists tasks for this workstation with optional filtering and pagination.
|
|
2489
3941
|
*
|
|
2490
|
-
*
|
|
2491
|
-
*
|
|
2492
|
-
* ones with persistent UUIDs on the server.
|
|
3942
|
+
* Returns a page of tasks matching the specified filters, along with metadata
|
|
3943
|
+
* for pagination.
|
|
2493
3944
|
*
|
|
2494
|
-
* @param
|
|
2495
|
-
* @param
|
|
2496
|
-
* @param options
|
|
2497
|
-
* @param
|
|
2498
|
-
* @
|
|
2499
|
-
* @returns A promise resolving to a CanvasExecution instance with the fetched state.
|
|
3945
|
+
* @param params - Query parameters
|
|
3946
|
+
* @param params.filters - Optional filters to apply (ID, name, status, dates, etc.)
|
|
3947
|
+
* @param params.options - Optional pagination and sorting options
|
|
3948
|
+
* @param params.rawQuery - Raw query object (internal use, overrides filters/options)
|
|
3949
|
+
* @returns A promise that resolves to an object containing tasks and pagination metadata
|
|
2500
3950
|
*
|
|
2501
3951
|
* @example
|
|
2502
3952
|
* ```typescript
|
|
2503
|
-
* //
|
|
2504
|
-
* const
|
|
2505
|
-
*
|
|
2506
|
-
*
|
|
2507
|
-
*
|
|
2508
|
-
* const fetched = await canvas.getExecution(executionId)
|
|
2509
|
-
* console.log(fetched.status) // 'running', 'succeeded', or 'failed'
|
|
3953
|
+
* // Get first 10 completed tasks
|
|
3954
|
+
* const { tasks, meta } = await workstation.listTasks({
|
|
3955
|
+
* filters: { status: ['completed'] },
|
|
3956
|
+
* options: { limit: 10, offset: 0 },
|
|
3957
|
+
* })
|
|
2510
3958
|
*
|
|
2511
|
-
* //
|
|
2512
|
-
*
|
|
2513
|
-
*
|
|
3959
|
+
* // Sort by creation date
|
|
3960
|
+
* const { tasks, meta } = await workstation.listTasks({
|
|
3961
|
+
* options: {
|
|
3962
|
+
* order: { by: 'createdAt', direction: 'desc' },
|
|
3963
|
+
* limit: 20,
|
|
3964
|
+
* },
|
|
3965
|
+
* })
|
|
2514
3966
|
* ```
|
|
2515
3967
|
*/
|
|
2516
|
-
async
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
3968
|
+
async listTasks({ filters, options, rawQuery }) {
|
|
3969
|
+
function getQuery(id) {
|
|
3970
|
+
if (rawQuery) {
|
|
3971
|
+
return rawQuery;
|
|
3972
|
+
}
|
|
3973
|
+
const validatedFilters = TaskListFilters.optional().parse(filters);
|
|
3974
|
+
const validatedOptions = TaskListOptions.optional().parse(options);
|
|
3975
|
+
return {
|
|
3976
|
+
promptApplicationId: id,
|
|
3977
|
+
objectLinks: true,
|
|
3978
|
+
...validatedFilters,
|
|
3979
|
+
...validatedOptions
|
|
3980
|
+
};
|
|
3981
|
+
}
|
|
3982
|
+
const query = getQuery(this._id);
|
|
3983
|
+
const response = await this._client.get(`/task`, {
|
|
3984
|
+
query,
|
|
3985
|
+
transformCase: false
|
|
3986
|
+
});
|
|
3987
|
+
const tasks = response.data.map((task) => new Task(
|
|
2520
3988
|
this._client,
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
3989
|
+
task.rawInput?.variables,
|
|
3990
|
+
task,
|
|
3991
|
+
task.requestId,
|
|
3992
|
+
this._output
|
|
3993
|
+
));
|
|
3994
|
+
return {
|
|
3995
|
+
tasks,
|
|
3996
|
+
meta: response.meta
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
/**
|
|
4000
|
+
* Asynchronously iterates through all tasks matching the specified filters.
|
|
4001
|
+
*
|
|
4002
|
+
* This generator automatically handles pagination, fetching additional pages
|
|
4003
|
+
* as needed. Each iteration yields a task and the current page metadata.
|
|
4004
|
+
*
|
|
4005
|
+
* @param params - Query parameters
|
|
4006
|
+
* @param params.filters - Optional filters to apply (ID, name, status, dates, etc.)
|
|
4007
|
+
* @param params.options - Optional initial pagination and sorting options
|
|
4008
|
+
* @yields A tuple of [task, metadata] for each task
|
|
4009
|
+
*
|
|
4010
|
+
* @example
|
|
4011
|
+
* ```typescript
|
|
4012
|
+
* // Iterate through all pending tasks
|
|
4013
|
+
* for await (const [task, meta] of workstation.iterateTasks({
|
|
4014
|
+
* filters: { status: ['pending'] },
|
|
4015
|
+
* })) {
|
|
4016
|
+
* console.log(`Task ${task.id}: ${task.status}`)
|
|
4017
|
+
* console.log(`Page ${meta.currentPage} of ${meta.totalPages}`)
|
|
4018
|
+
* }
|
|
4019
|
+
*
|
|
4020
|
+
* // Process tasks in batches
|
|
4021
|
+
* for await (const [task, meta] of workstation.iterateTasks({
|
|
4022
|
+
* options: { limit: 50 },
|
|
4023
|
+
* })) {
|
|
4024
|
+
* await processTask(task)
|
|
4025
|
+
* }
|
|
4026
|
+
* ```
|
|
4027
|
+
*/
|
|
4028
|
+
async *iterateTasks({ filters, options }) {
|
|
4029
|
+
let rawQuery;
|
|
4030
|
+
let hasMore = true;
|
|
4031
|
+
while (hasMore) {
|
|
4032
|
+
const { tasks, meta } = await this.listTasks({
|
|
4033
|
+
filters,
|
|
4034
|
+
options,
|
|
4035
|
+
rawQuery
|
|
4036
|
+
});
|
|
4037
|
+
for (const task of tasks) {
|
|
4038
|
+
yield [task, meta];
|
|
2524
4039
|
}
|
|
2525
|
-
|
|
4040
|
+
if (meta.links.next !== null) {
|
|
4041
|
+
rawQuery = {
|
|
4042
|
+
...meta.links.next,
|
|
4043
|
+
objectLinks: true
|
|
4044
|
+
};
|
|
4045
|
+
} else {
|
|
4046
|
+
hasMore = false;
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
2526
4049
|
}
|
|
2527
4050
|
}
|
|
2528
4051
|
|
|
@@ -2587,6 +4110,17 @@ const _TelaSDK = class _TelaSDK extends BaseClient {
|
|
|
2587
4110
|
});
|
|
2588
4111
|
}
|
|
2589
4112
|
});
|
|
4113
|
+
__publicField(this, "workstation", {
|
|
4114
|
+
get: async (options) => {
|
|
4115
|
+
return Workstation.get({
|
|
4116
|
+
applicationId: options.applicationId,
|
|
4117
|
+
input: options.input,
|
|
4118
|
+
output: options.output,
|
|
4119
|
+
skipSchemaValidation: options.skipSchemaValidation,
|
|
4120
|
+
client: this
|
|
4121
|
+
});
|
|
4122
|
+
}
|
|
4123
|
+
});
|
|
2590
4124
|
this.opts = { baseURL, ...rest };
|
|
2591
4125
|
this.apiKey = apiKey;
|
|
2592
4126
|
this.jwt = jwt;
|
|
@@ -2646,9 +4180,13 @@ __publicField(_TelaSDK, "FileUploadError", FileUploadError);
|
|
|
2646
4180
|
__publicField(_TelaSDK, "MissingApiKeyOrJWTError", MissingApiKeyOrJWTError);
|
|
2647
4181
|
/** Thrown when both an API key and a JWT are provided. */
|
|
2648
4182
|
__publicField(_TelaSDK, "ConflictApiKeyAndJWTError", ConflictApiKeyAndJWTError);
|
|
4183
|
+
/** Thrown when a canvas execution fails on the server. */
|
|
4184
|
+
__publicField(_TelaSDK, "ExecutionFailedError", ExecutionFailedError);
|
|
4185
|
+
/** Thrown when a workstation task fails on the server. */
|
|
4186
|
+
__publicField(_TelaSDK, "TaskFailedError", TaskFailedError);
|
|
2649
4187
|
let TelaSDK = _TelaSDK;
|
|
2650
4188
|
function createTelaClient(opts) {
|
|
2651
4189
|
return new TelaSDK(opts);
|
|
2652
4190
|
}
|
|
2653
4191
|
|
|
2654
|
-
export { APIError, AuthenticationError, AuthorizationError, BadRequestError, BaseClient, ConflictApiKeyAndJWTError, ConflictError, ConnectionError, ConnectionTimeout, EmptyFileError, ExecutionFailedError, ExecutionNotStartedError, FileUploadError, InternalServerError, InvalidExecutionModeError, InvalidFileURL, MissingApiKeyOrJWTError, NotFoundError, RateLimitError, TelaError, TelaFile, TelaFileSchema, TelaSDK, UnprocessableEntityError, UserAbortError, createTelaClient, toError };
|
|
4192
|
+
export { APIError, AuthenticationError, AuthorizationError, BadRequestError, BaseClient, BatchExecutionFailedError, ConflictApiKeyAndJWTError, ConflictError, ConnectionError, ConnectionTimeout, EmptyFileError, ExecutionFailedError, ExecutionNotStartedError, FileUploadError, InternalServerError, InvalidExecutionModeError, InvalidFileURL, MissingApiKeyOrJWTError, NotFoundError, RateLimitError, TaskFailedError, TelaError, TelaFile, TelaFileSchema, TelaSDK, UnprocessableEntityError, UserAbortError, createTelaClient, isTelaFile, isTelaFileArray, toError };
|