@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.cjs
CHANGED
|
@@ -21,15 +21,14 @@ function _interopNamespaceCompat(e) {
|
|
|
21
21
|
|
|
22
22
|
const changeCase__namespace = /*#__PURE__*/_interopNamespaceCompat(changeCase);
|
|
23
23
|
const z__default = /*#__PURE__*/_interopDefaultCompat(z);
|
|
24
|
-
const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
|
|
25
24
|
const Emittery__default = /*#__PURE__*/_interopDefaultCompat(Emittery);
|
|
26
25
|
|
|
27
|
-
const version = "2.
|
|
26
|
+
const version = "2.6.0";
|
|
28
27
|
|
|
29
|
-
var __defProp$
|
|
30
|
-
var __defNormalProp$
|
|
31
|
-
var __publicField$
|
|
32
|
-
__defNormalProp$
|
|
28
|
+
var __defProp$a = Object.defineProperty;
|
|
29
|
+
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
30
|
+
var __publicField$a = (obj, key, value) => {
|
|
31
|
+
__defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
33
32
|
return value;
|
|
34
33
|
};
|
|
35
34
|
class TelaError extends Error {
|
|
@@ -57,7 +56,7 @@ class InvalidFileURL extends TelaError {
|
|
|
57
56
|
class FileUploadError extends TelaError {
|
|
58
57
|
constructor(message, statusCode) {
|
|
59
58
|
super(`Failed to upload file: ${message} (Status code: ${statusCode})`);
|
|
60
|
-
__publicField$
|
|
59
|
+
__publicField$a(this, "statusCode");
|
|
61
60
|
this.statusCode = statusCode;
|
|
62
61
|
}
|
|
63
62
|
}
|
|
@@ -74,16 +73,30 @@ class InvalidExecutionModeError extends TelaError {
|
|
|
74
73
|
class ExecutionFailedError extends TelaError {
|
|
75
74
|
constructor(rawOutput) {
|
|
76
75
|
super(`Execution failed: ${JSON.stringify(rawOutput)}`);
|
|
77
|
-
__publicField$
|
|
76
|
+
__publicField$a(this, "rawOutput");
|
|
78
77
|
this.rawOutput = rawOutput;
|
|
79
78
|
}
|
|
80
79
|
}
|
|
80
|
+
class TaskFailedError extends TelaError {
|
|
81
|
+
constructor(rawTask, message, cause) {
|
|
82
|
+
super(`Task failed: ${JSON.stringify(rawTask)}`, { cause });
|
|
83
|
+
__publicField$a(this, "rawTask");
|
|
84
|
+
this.rawTask = rawTask;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
class BatchExecutionFailedError extends TelaError {
|
|
88
|
+
constructor(rawResponse) {
|
|
89
|
+
super(`Batch execution failed: ${JSON.stringify(rawResponse)}`);
|
|
90
|
+
__publicField$a(this, "rawResponse");
|
|
91
|
+
this.rawResponse = rawResponse;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
81
94
|
class APIError extends TelaError {
|
|
82
95
|
constructor(statusCode, error, _message) {
|
|
83
96
|
const message = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : _message;
|
|
84
97
|
super(message);
|
|
85
|
-
__publicField$
|
|
86
|
-
__publicField$
|
|
98
|
+
__publicField$a(this, "statusCode");
|
|
99
|
+
__publicField$a(this, "error");
|
|
87
100
|
this.statusCode = statusCode;
|
|
88
101
|
this.error = error;
|
|
89
102
|
}
|
|
@@ -125,7 +138,7 @@ class APIError extends TelaError {
|
|
|
125
138
|
class UserAbortError extends APIError {
|
|
126
139
|
constructor({ message } = {}) {
|
|
127
140
|
super(void 0, void 0, message || "User aborted.");
|
|
128
|
-
__publicField$
|
|
141
|
+
__publicField$a(this, "statusCode");
|
|
129
142
|
}
|
|
130
143
|
}
|
|
131
144
|
class ConnectionError extends APIError {
|
|
@@ -134,7 +147,7 @@ class ConnectionError extends APIError {
|
|
|
134
147
|
cause
|
|
135
148
|
}) {
|
|
136
149
|
super(void 0, void 0, message || "Connection error.");
|
|
137
|
-
__publicField$
|
|
150
|
+
__publicField$a(this, "statusCode");
|
|
138
151
|
if (cause)
|
|
139
152
|
this.cause = cause;
|
|
140
153
|
}
|
|
@@ -144,57 +157,57 @@ class ConnectionTimeout extends APIError {
|
|
|
144
157
|
message
|
|
145
158
|
} = {}) {
|
|
146
159
|
super(void 0, void 0, message || "Request timed out.");
|
|
147
|
-
__publicField$
|
|
160
|
+
__publicField$a(this, "statusCode");
|
|
148
161
|
}
|
|
149
162
|
}
|
|
150
163
|
class BadRequestError extends APIError {
|
|
151
164
|
constructor() {
|
|
152
165
|
super(...arguments);
|
|
153
|
-
__publicField$
|
|
166
|
+
__publicField$a(this, "statusCode", 400);
|
|
154
167
|
}
|
|
155
168
|
// todo: handle validation errors from zod/typebox
|
|
156
169
|
}
|
|
157
170
|
class AuthenticationError extends APIError {
|
|
158
171
|
constructor() {
|
|
159
172
|
super(...arguments);
|
|
160
|
-
__publicField$
|
|
173
|
+
__publicField$a(this, "statusCode", 401);
|
|
161
174
|
}
|
|
162
175
|
}
|
|
163
176
|
class AuthorizationError extends APIError {
|
|
164
177
|
constructor() {
|
|
165
178
|
super(...arguments);
|
|
166
|
-
__publicField$
|
|
179
|
+
__publicField$a(this, "statusCode", 403);
|
|
167
180
|
}
|
|
168
181
|
}
|
|
169
182
|
class NotFoundError extends APIError {
|
|
170
183
|
constructor() {
|
|
171
184
|
super(...arguments);
|
|
172
|
-
__publicField$
|
|
185
|
+
__publicField$a(this, "statusCode", 404);
|
|
173
186
|
}
|
|
174
187
|
}
|
|
175
188
|
class ConflictError extends APIError {
|
|
176
189
|
constructor() {
|
|
177
190
|
super(...arguments);
|
|
178
|
-
__publicField$
|
|
191
|
+
__publicField$a(this, "statusCode", 409);
|
|
179
192
|
}
|
|
180
193
|
}
|
|
181
194
|
class UnprocessableEntityError extends APIError {
|
|
182
195
|
constructor() {
|
|
183
196
|
super(...arguments);
|
|
184
197
|
// todo: check if tela returns 400 or 422 for zod errors
|
|
185
|
-
__publicField$
|
|
198
|
+
__publicField$a(this, "statusCode", 422);
|
|
186
199
|
}
|
|
187
200
|
}
|
|
188
201
|
class RateLimitError extends APIError {
|
|
189
202
|
constructor() {
|
|
190
203
|
super(...arguments);
|
|
191
|
-
__publicField$
|
|
204
|
+
__publicField$a(this, "statusCode", 429);
|
|
192
205
|
}
|
|
193
206
|
}
|
|
194
207
|
class InternalServerError extends APIError {
|
|
195
208
|
constructor() {
|
|
196
209
|
super(...arguments);
|
|
197
|
-
__publicField$
|
|
210
|
+
__publicField$a(this, "statusCode", 500);
|
|
198
211
|
}
|
|
199
212
|
}
|
|
200
213
|
function toError(err) {
|
|
@@ -305,11 +318,38 @@ function transformObjectFromSnakeCaseToCamelCase(obj, exclusions = []) {
|
|
|
305
318
|
}
|
|
306
319
|
return result;
|
|
307
320
|
}
|
|
321
|
+
const DURATION_REGEX = /(?<amount>\d+)(?<unit>[smhd])/;
|
|
322
|
+
const DURATION_UNITS = {
|
|
323
|
+
s: 1e3,
|
|
324
|
+
// 1 second in milliseconds
|
|
325
|
+
m: 6e4,
|
|
326
|
+
// 1 minute in milliseconds
|
|
327
|
+
h: 36e5,
|
|
328
|
+
// 1 hour in milliseconds
|
|
329
|
+
d: 864e5
|
|
330
|
+
// 1 day in milliseconds
|
|
331
|
+
};
|
|
332
|
+
function transformDurationToMs(durationStr) {
|
|
333
|
+
if (!durationStr) {
|
|
334
|
+
return void 0;
|
|
335
|
+
}
|
|
336
|
+
if (typeof durationStr === "number") {
|
|
337
|
+
return durationStr;
|
|
338
|
+
}
|
|
339
|
+
const match = durationStr.match(DURATION_REGEX);
|
|
340
|
+
const amount = match?.groups?.amount;
|
|
341
|
+
const unit = match?.groups?.unit;
|
|
342
|
+
const multiplier = DURATION_UNITS[unit];
|
|
343
|
+
if (!amount || Number.isNaN(Number.parseInt(amount)) || !multiplier) {
|
|
344
|
+
return void 0;
|
|
345
|
+
}
|
|
346
|
+
return Number.parseInt(amount) * multiplier;
|
|
347
|
+
}
|
|
308
348
|
|
|
309
|
-
var __defProp$
|
|
310
|
-
var __defNormalProp$
|
|
311
|
-
var __publicField$
|
|
312
|
-
__defNormalProp$
|
|
349
|
+
var __defProp$9 = Object.defineProperty;
|
|
350
|
+
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
351
|
+
var __publicField$9 = (obj, key, value) => {
|
|
352
|
+
__defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
313
353
|
return value;
|
|
314
354
|
};
|
|
315
355
|
class Stream {
|
|
@@ -573,9 +613,9 @@ function findDoubleNewlineIndex(buffer) {
|
|
|
573
613
|
}
|
|
574
614
|
class SSEDecoder {
|
|
575
615
|
constructor() {
|
|
576
|
-
__publicField$
|
|
577
|
-
__publicField$
|
|
578
|
-
__publicField$
|
|
616
|
+
__publicField$9(this, "data");
|
|
617
|
+
__publicField$9(this, "event");
|
|
618
|
+
__publicField$9(this, "chunks");
|
|
579
619
|
this.event = null;
|
|
580
620
|
this.data = [];
|
|
581
621
|
this.chunks = [];
|
|
@@ -616,9 +656,9 @@ class SSEDecoder {
|
|
|
616
656
|
const _LineDecoder = class _LineDecoder {
|
|
617
657
|
// TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types.
|
|
618
658
|
constructor() {
|
|
619
|
-
__publicField$
|
|
620
|
-
__publicField$
|
|
621
|
-
__publicField$
|
|
659
|
+
__publicField$9(this, "buffer");
|
|
660
|
+
__publicField$9(this, "trailingCR");
|
|
661
|
+
__publicField$9(this, "textDecoder");
|
|
622
662
|
this.buffer = [];
|
|
623
663
|
this.trailingCR = false;
|
|
624
664
|
}
|
|
@@ -693,8 +733,8 @@ const _LineDecoder = class _LineDecoder {
|
|
|
693
733
|
}
|
|
694
734
|
};
|
|
695
735
|
// prettier-ignore
|
|
696
|
-
__publicField$
|
|
697
|
-
__publicField$
|
|
736
|
+
__publicField$9(_LineDecoder, "NEWLINE_CHARS", /* @__PURE__ */ new Set(["\n", "\r"]));
|
|
737
|
+
__publicField$9(_LineDecoder, "NEWLINE_REGEXP", /\r\n|[\n\r]/g);
|
|
698
738
|
let LineDecoder = _LineDecoder;
|
|
699
739
|
function partition(str, delimiter) {
|
|
700
740
|
const index = str.indexOf(delimiter);
|
|
@@ -731,10 +771,10 @@ function readableStreamAsyncIterable(stream) {
|
|
|
731
771
|
};
|
|
732
772
|
}
|
|
733
773
|
|
|
734
|
-
var __defProp$
|
|
735
|
-
var __defNormalProp$
|
|
736
|
-
var __publicField$
|
|
737
|
-
__defNormalProp$
|
|
774
|
+
var __defProp$8 = Object.defineProperty;
|
|
775
|
+
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
776
|
+
var __publicField$8 = (obj, key, value) => {
|
|
777
|
+
__defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
738
778
|
return value;
|
|
739
779
|
};
|
|
740
780
|
function getRequestIdFromResponse(response) {
|
|
@@ -776,6 +816,7 @@ function getRequestIdFromResponse(response) {
|
|
|
776
816
|
}
|
|
777
817
|
async function defaultParseResponse(props) {
|
|
778
818
|
const { response } = props;
|
|
819
|
+
const { transformCase = true } = props.options;
|
|
779
820
|
if (props.options.stream) {
|
|
780
821
|
debug("response", response.status, response.url, response.headers, response.body);
|
|
781
822
|
return Stream.fromSSEResponse(response, props.controller);
|
|
@@ -789,22 +830,30 @@ async function defaultParseResponse(props) {
|
|
|
789
830
|
const json = await response.json();
|
|
790
831
|
debug("response", response.status, response.url, response.headers, json);
|
|
791
832
|
const requestId = getRequestIdFromResponse(response);
|
|
792
|
-
const finalJson = { ...json };
|
|
793
833
|
if (requestId) {
|
|
794
|
-
|
|
834
|
+
json.requestId = requestId;
|
|
795
835
|
}
|
|
796
|
-
return transformObjectFromSnakeCaseToCamelCase(
|
|
836
|
+
return transformCase ? transformObjectFromSnakeCaseToCamelCase(json, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS) : json;
|
|
797
837
|
}
|
|
798
838
|
const text = await response.text();
|
|
799
839
|
debug("response", response.status, response.url, response.headers, text);
|
|
800
840
|
return text;
|
|
801
841
|
}
|
|
842
|
+
function transformObjectCase(obj, transformCase) {
|
|
843
|
+
if (!obj) {
|
|
844
|
+
return obj;
|
|
845
|
+
}
|
|
846
|
+
if (transformCase) {
|
|
847
|
+
return transformObjectFromCamelCaseToSnakeCase(obj, DEFAULT_FIELDS_TRANSFORMATION_EXCLUSIONS);
|
|
848
|
+
}
|
|
849
|
+
return obj;
|
|
850
|
+
}
|
|
802
851
|
class BaseClient {
|
|
803
852
|
constructor({ baseURL, maxRetries = 5, timeout = 0 }) {
|
|
804
|
-
__publicField$
|
|
805
|
-
__publicField$
|
|
806
|
-
__publicField$
|
|
807
|
-
__publicField$
|
|
853
|
+
__publicField$8(this, "baseURL");
|
|
854
|
+
__publicField$8(this, "maxRetries");
|
|
855
|
+
__publicField$8(this, "timeout");
|
|
856
|
+
__publicField$8(this, "fetch");
|
|
808
857
|
this.baseURL = baseURL;
|
|
809
858
|
this.maxRetries = validateMaxRetries(maxRetries);
|
|
810
859
|
this.timeout = validateTimeout(timeout);
|
|
@@ -843,10 +892,11 @@ class BaseClient {
|
|
|
843
892
|
return this.methodRequest("DELETE", path, opts);
|
|
844
893
|
}
|
|
845
894
|
async methodRequest(method, path, opts) {
|
|
895
|
+
const { transformCase = true } = opts ?? {};
|
|
846
896
|
const headers = this.createHeaders();
|
|
847
897
|
debug("methodRequest", method, path, opts);
|
|
848
|
-
const transformedQuery = opts?.query
|
|
849
|
-
const transformedBody = opts?.body
|
|
898
|
+
const transformedQuery = transformObjectCase(opts?.query, transformCase);
|
|
899
|
+
const transformedBody = transformObjectCase(opts?.body, transformCase);
|
|
850
900
|
const { response, options, controller } = await this.request({
|
|
851
901
|
method,
|
|
852
902
|
path,
|
|
@@ -1027,6 +1077,9 @@ class BaseClient {
|
|
|
1027
1077
|
if (value === null) {
|
|
1028
1078
|
return `${encodeURIComponent(key)}=`;
|
|
1029
1079
|
}
|
|
1080
|
+
if (Array.isArray(value)) {
|
|
1081
|
+
return value.map((item) => `${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`).join("&");
|
|
1082
|
+
}
|
|
1030
1083
|
throw new TelaError(
|
|
1031
1084
|
`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`
|
|
1032
1085
|
);
|
|
@@ -1080,10 +1133,10 @@ async function getStreamSize(stream) {
|
|
|
1080
1133
|
return size;
|
|
1081
1134
|
}
|
|
1082
1135
|
|
|
1083
|
-
var __defProp$
|
|
1084
|
-
var __defNormalProp$
|
|
1085
|
-
var __publicField$
|
|
1086
|
-
__defNormalProp$
|
|
1136
|
+
var __defProp$7 = Object.defineProperty;
|
|
1137
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1138
|
+
var __publicField$7 = (obj, key, value) => {
|
|
1139
|
+
__defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1087
1140
|
return value;
|
|
1088
1141
|
};
|
|
1089
1142
|
function TelaFileSchema() {
|
|
@@ -1091,11 +1144,11 @@ function TelaFileSchema() {
|
|
|
1091
1144
|
}
|
|
1092
1145
|
class TelaFile {
|
|
1093
1146
|
constructor(file, options = {}) {
|
|
1094
|
-
__publicField$
|
|
1095
|
-
__publicField$
|
|
1096
|
-
__publicField$
|
|
1097
|
-
__publicField$
|
|
1098
|
-
__publicField$
|
|
1147
|
+
__publicField$7(this, "_file");
|
|
1148
|
+
__publicField$7(this, "_options");
|
|
1149
|
+
__publicField$7(this, "_size", null);
|
|
1150
|
+
__publicField$7(this, "_mimeType");
|
|
1151
|
+
__publicField$7(this, "_name");
|
|
1099
1152
|
this._file = file;
|
|
1100
1153
|
if (file instanceof File || file instanceof Blob) {
|
|
1101
1154
|
this._size = file.size;
|
|
@@ -1241,7 +1294,17 @@ class TelaFile {
|
|
|
1241
1294
|
return url.startsWith("vault://");
|
|
1242
1295
|
}
|
|
1243
1296
|
}
|
|
1297
|
+
function isTelaFile(obj) {
|
|
1298
|
+
return obj instanceof TelaFile;
|
|
1299
|
+
}
|
|
1300
|
+
function isTelaFileArray(obj) {
|
|
1301
|
+
return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
|
|
1302
|
+
}
|
|
1244
1303
|
|
|
1304
|
+
const zod = {
|
|
1305
|
+
...z.z,
|
|
1306
|
+
file: TelaFileSchema
|
|
1307
|
+
};
|
|
1245
1308
|
function compareSchemas(clientSchema, serverSchema, path = "$") {
|
|
1246
1309
|
const mismatches = [];
|
|
1247
1310
|
if (clientSchema.type !== serverSchema.type) {
|
|
@@ -1398,11 +1461,172 @@ function validateInputSchema(clientSchema, serverVariables) {
|
|
|
1398
1461
|
function validateOutputSchema(clientSchema, serverSchema) {
|
|
1399
1462
|
return compareSchemas(clientSchema, serverSchema);
|
|
1400
1463
|
}
|
|
1464
|
+
function validateSchemas(resource, input, output, promptVersion) {
|
|
1465
|
+
const canvasIdentifier = `${promptVersion.title} (${promptVersion.promptId})`;
|
|
1466
|
+
if (input instanceof z.z.ZodType) {
|
|
1467
|
+
try {
|
|
1468
|
+
const inputSchema = z.z.toJSONSchema(input, { unrepresentable: "any" });
|
|
1469
|
+
const mismatches = validateInputSchema(inputSchema, promptVersion.variables);
|
|
1470
|
+
if (mismatches.length === 0) {
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
console.warn(
|
|
1474
|
+
`[Tela SDK - ${resource} Input Validation] Input schema mismatches for ${resource} "${canvasIdentifier}":`
|
|
1475
|
+
);
|
|
1476
|
+
for (const mismatch of mismatches) {
|
|
1477
|
+
console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
|
|
1478
|
+
}
|
|
1479
|
+
} catch (error) {
|
|
1480
|
+
console.warn(
|
|
1481
|
+
`[Tela SDK - ${resource} Input Validation] Failed to validate input schema for ${resource} "${canvasIdentifier}":`,
|
|
1482
|
+
error
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
if (output instanceof z.z.ZodType) {
|
|
1487
|
+
try {
|
|
1488
|
+
const outputSchema = z.z.toJSONSchema(output);
|
|
1489
|
+
const serverOutput = promptVersion.configuration.structuredOutput;
|
|
1490
|
+
if (!serverOutput.enabled) {
|
|
1491
|
+
console.warn(
|
|
1492
|
+
`[Tela SDK - ${resource} Output Validation] Output schema provided for ${resource} "${canvasIdentifier}", but structured output is not enabled on the server. The schema may not be enforced.`
|
|
1493
|
+
);
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
const mismatches = validateOutputSchema(outputSchema, serverOutput.schema);
|
|
1497
|
+
if (mismatches.length === 0) {
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
console.warn(
|
|
1501
|
+
`[Tela SDK - ${resource} Output Validation] Output schema mismatches for ${resource} "${canvasIdentifier}":`
|
|
1502
|
+
);
|
|
1503
|
+
for (const mismatch of mismatches) {
|
|
1504
|
+
console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
|
|
1505
|
+
}
|
|
1506
|
+
} catch (error) {
|
|
1507
|
+
console.warn(
|
|
1508
|
+
`[Tela SDK - ${resource} Output Validation] Failed to validate output schema for ${resource} "${canvasIdentifier}":`,
|
|
1509
|
+
error
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1401
1514
|
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1515
|
+
async function calculateSha256sum(content) {
|
|
1516
|
+
const stream = content instanceof File || content instanceof Blob ? content.stream() : content;
|
|
1517
|
+
const reader = stream.getReader();
|
|
1518
|
+
try {
|
|
1519
|
+
const { createHash } = await import('node:crypto');
|
|
1520
|
+
const hash = createHash("sha256");
|
|
1521
|
+
while (true) {
|
|
1522
|
+
const { done, value } = await reader.read();
|
|
1523
|
+
if (done)
|
|
1524
|
+
break;
|
|
1525
|
+
hash.update(value);
|
|
1526
|
+
}
|
|
1527
|
+
return hash.digest("hex");
|
|
1528
|
+
} catch {
|
|
1529
|
+
const chunks = [];
|
|
1530
|
+
while (true) {
|
|
1531
|
+
const { done, value } = await reader.read();
|
|
1532
|
+
if (done)
|
|
1533
|
+
break;
|
|
1534
|
+
chunks.push(value);
|
|
1535
|
+
}
|
|
1536
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
1537
|
+
const buffer = new Uint8Array(totalLength);
|
|
1538
|
+
let offset = 0;
|
|
1539
|
+
for (const chunk of chunks) {
|
|
1540
|
+
buffer.set(chunk, offset);
|
|
1541
|
+
offset += chunk.length;
|
|
1542
|
+
}
|
|
1543
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
|
|
1544
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1545
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1546
|
+
return hashHex;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
async function uploadFile(file, client) {
|
|
1551
|
+
let content = await file.getUploadableContent();
|
|
1552
|
+
let sha256sumStream;
|
|
1553
|
+
if (typeof content === "string") {
|
|
1554
|
+
return { fileUrl: content, options: file.options };
|
|
1555
|
+
}
|
|
1556
|
+
const filename = file.name ?? void 0;
|
|
1557
|
+
const fileType = file.type ?? void 0;
|
|
1558
|
+
const contentLength = file.size ?? void 0;
|
|
1559
|
+
if (content instanceof ReadableStream) {
|
|
1560
|
+
const [hashStream, contentStream] = content.tee();
|
|
1561
|
+
content = contentStream;
|
|
1562
|
+
sha256sumStream = hashStream;
|
|
1563
|
+
}
|
|
1564
|
+
const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
|
|
1565
|
+
const { id, uploadUrl } = await client.post("/_services/vault/files", {
|
|
1566
|
+
body: {
|
|
1567
|
+
fileName: filename,
|
|
1568
|
+
mimeType: fileType,
|
|
1569
|
+
size: contentLength ?? void 0,
|
|
1570
|
+
sha256sum
|
|
1571
|
+
},
|
|
1572
|
+
transformCase: false
|
|
1573
|
+
});
|
|
1574
|
+
if (content instanceof ReadableStream && typeof Bun !== "undefined") {
|
|
1575
|
+
console.warn(
|
|
1576
|
+
"[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
|
|
1577
|
+
{ fileName: filename, fileSize: contentLength }
|
|
1578
|
+
);
|
|
1579
|
+
const chunks = [];
|
|
1580
|
+
const reader = content.getReader();
|
|
1581
|
+
while (true) {
|
|
1582
|
+
const { done, value } = await reader.read();
|
|
1583
|
+
if (done)
|
|
1584
|
+
break;
|
|
1585
|
+
chunks.push(value);
|
|
1586
|
+
}
|
|
1587
|
+
content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
|
|
1588
|
+
}
|
|
1589
|
+
const request = new Request(uploadUrl, {
|
|
1590
|
+
method: "PUT",
|
|
1591
|
+
body: content,
|
|
1592
|
+
headers: {
|
|
1593
|
+
"Content-Type": fileType ?? "application/octet-stream",
|
|
1594
|
+
...file.size ? { "Content-Length": file.size.toString() } : {}
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
const uploadResponse = await fetch(request);
|
|
1598
|
+
if (!uploadResponse.ok) {
|
|
1599
|
+
throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
|
|
1600
|
+
}
|
|
1601
|
+
return { fileUrl: `vault://${id}`, options: file.options };
|
|
1602
|
+
}
|
|
1603
|
+
async function uploadFiles(files, client) {
|
|
1604
|
+
const uploadPromises = files.map((file) => uploadFile(file, client));
|
|
1605
|
+
return Promise.all(uploadPromises);
|
|
1606
|
+
}
|
|
1607
|
+
async function downloadFile(vaultReference, client) {
|
|
1608
|
+
const vaultId = vaultReference.replace("vault://", "");
|
|
1609
|
+
const response = await client.get(`/_services/vault/files/${vaultId}`);
|
|
1610
|
+
return fetch(response.url).then((res) => res.blob());
|
|
1611
|
+
}
|
|
1612
|
+
async function streamFile(vaultReference, client) {
|
|
1613
|
+
const vaultId = vaultReference.replace("vault://", "");
|
|
1614
|
+
const response = await client.get(`/_services/vault/files/${vaultId}`);
|
|
1615
|
+
return fetch(response.url).then((res) => {
|
|
1616
|
+
if (!res.ok) {
|
|
1617
|
+
throw new Error("Failed to stream file", { cause: res.statusText });
|
|
1618
|
+
}
|
|
1619
|
+
if (!res.body) {
|
|
1620
|
+
throw new Error("Failed to stream file", { cause: "No body" });
|
|
1621
|
+
}
|
|
1622
|
+
return res.body;
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
var __defProp$6 = Object.defineProperty;
|
|
1627
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1628
|
+
var __publicField$6 = (obj, key, value) => {
|
|
1629
|
+
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1406
1630
|
return value;
|
|
1407
1631
|
};
|
|
1408
1632
|
function timeout(ms, signal) {
|
|
@@ -1418,10 +1642,10 @@ function timeout(ms, signal) {
|
|
|
1418
1642
|
}
|
|
1419
1643
|
class Poller {
|
|
1420
1644
|
constructor({ interval, timeout: timeout2, abortSignal }) {
|
|
1421
|
-
__publicField$
|
|
1422
|
-
__publicField$
|
|
1423
|
-
__publicField$
|
|
1424
|
-
__publicField$
|
|
1645
|
+
__publicField$6(this, "_interval");
|
|
1646
|
+
__publicField$6(this, "_timeout");
|
|
1647
|
+
__publicField$6(this, "_abortSignal");
|
|
1648
|
+
__publicField$6(this, "_internalAbortController");
|
|
1425
1649
|
if (interval <= 0) {
|
|
1426
1650
|
throw new TelaError("Interval must be greater than 0");
|
|
1427
1651
|
}
|
|
@@ -1467,7 +1691,7 @@ class Poller {
|
|
|
1467
1691
|
const resultPromise = async () => {
|
|
1468
1692
|
try {
|
|
1469
1693
|
while (!this._abortSignal.aborted) {
|
|
1470
|
-
const result = await callback(
|
|
1694
|
+
const result = await callback();
|
|
1471
1695
|
if (result.done) {
|
|
1472
1696
|
return result.value;
|
|
1473
1697
|
}
|
|
@@ -1482,53 +1706,12 @@ class Poller {
|
|
|
1482
1706
|
}
|
|
1483
1707
|
}
|
|
1484
1708
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
const { createHash } = await import('node:crypto');
|
|
1490
|
-
const hash = createHash("sha256");
|
|
1491
|
-
while (true) {
|
|
1492
|
-
const { done, value } = await reader.read();
|
|
1493
|
-
if (done)
|
|
1494
|
-
break;
|
|
1495
|
-
hash.update(value);
|
|
1496
|
-
}
|
|
1497
|
-
return hash.digest("hex");
|
|
1498
|
-
} catch {
|
|
1499
|
-
const chunks = [];
|
|
1500
|
-
while (true) {
|
|
1501
|
-
const { done, value } = await reader.read();
|
|
1502
|
-
if (done)
|
|
1503
|
-
break;
|
|
1504
|
-
chunks.push(value);
|
|
1505
|
-
}
|
|
1506
|
-
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
1507
|
-
const buffer = new Uint8Array(totalLength);
|
|
1508
|
-
let offset = 0;
|
|
1509
|
-
for (const chunk of chunks) {
|
|
1510
|
-
buffer.set(chunk, offset);
|
|
1511
|
-
offset += chunk.length;
|
|
1512
|
-
}
|
|
1513
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
|
|
1514
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1515
|
-
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1516
|
-
return hashHex;
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
var __defProp$2 = Object.defineProperty;
|
|
1521
|
-
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1522
|
-
var __publicField$2 = (obj, key, value) => {
|
|
1523
|
-
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1709
|
+
var __defProp$5 = Object.defineProperty;
|
|
1710
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1711
|
+
var __publicField$5 = (obj, key, value) => {
|
|
1712
|
+
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1524
1713
|
return value;
|
|
1525
1714
|
};
|
|
1526
|
-
function isTelaFile(obj) {
|
|
1527
|
-
return obj instanceof TelaFile;
|
|
1528
|
-
}
|
|
1529
|
-
function isTelaFileArray(obj) {
|
|
1530
|
-
return Array.isArray(obj) && obj.length > 0 && obj.every(isTelaFile);
|
|
1531
|
-
}
|
|
1532
1715
|
function isUUID(str) {
|
|
1533
1716
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1534
1717
|
return uuidRegex.test(str);
|
|
@@ -1560,6 +1743,17 @@ function getResultFromPollingResponse(response) {
|
|
|
1560
1743
|
}
|
|
1561
1744
|
throw new Error("Invalid response type");
|
|
1562
1745
|
}
|
|
1746
|
+
function normalizeExecutionStatus(status) {
|
|
1747
|
+
switch (status) {
|
|
1748
|
+
case "completed":
|
|
1749
|
+
case "validating":
|
|
1750
|
+
return "succeeded";
|
|
1751
|
+
case "cancelled":
|
|
1752
|
+
return "failed";
|
|
1753
|
+
default:
|
|
1754
|
+
return status;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1563
1757
|
class CanvasExecution extends Emittery__default {
|
|
1564
1758
|
/**
|
|
1565
1759
|
* Creates a new canvas execution instance.
|
|
@@ -1571,20 +1765,20 @@ class CanvasExecution extends Emittery__default {
|
|
|
1571
1765
|
*/
|
|
1572
1766
|
constructor(variables, params = { async: false }, outputSchema, client, isTask = false) {
|
|
1573
1767
|
super();
|
|
1574
|
-
__publicField$
|
|
1575
|
-
__publicField$
|
|
1576
|
-
__publicField$
|
|
1577
|
-
__publicField$
|
|
1578
|
-
__publicField$
|
|
1579
|
-
__publicField$
|
|
1580
|
-
__publicField$
|
|
1581
|
-
__publicField$
|
|
1582
|
-
__publicField$
|
|
1583
|
-
__publicField$
|
|
1584
|
-
__publicField$
|
|
1585
|
-
__publicField$
|
|
1586
|
-
__publicField$
|
|
1587
|
-
__publicField$
|
|
1768
|
+
__publicField$5(this, "_id");
|
|
1769
|
+
__publicField$5(this, "_status");
|
|
1770
|
+
__publicField$5(this, "_variables");
|
|
1771
|
+
__publicField$5(this, "_params");
|
|
1772
|
+
__publicField$5(this, "_client");
|
|
1773
|
+
__publicField$5(this, "_outputSchema");
|
|
1774
|
+
__publicField$5(this, "_skipResultValidation");
|
|
1775
|
+
__publicField$5(this, "_abortController");
|
|
1776
|
+
__publicField$5(this, "_isTask");
|
|
1777
|
+
__publicField$5(this, "_resultPromise");
|
|
1778
|
+
__publicField$5(this, "_stream");
|
|
1779
|
+
__publicField$5(this, "_rawResultValue");
|
|
1780
|
+
__publicField$5(this, "_requestId");
|
|
1781
|
+
__publicField$5(this, "_task");
|
|
1588
1782
|
this._variables = variables;
|
|
1589
1783
|
this._params = params;
|
|
1590
1784
|
this._outputSchema = outputSchema;
|
|
@@ -2090,13 +2284,13 @@ class CanvasExecution extends Emittery__default {
|
|
|
2090
2284
|
const resolvedVariables = await this.resolveVariables();
|
|
2091
2285
|
return await this.create(resolvedVariables, { async: true }).then((response) => {
|
|
2092
2286
|
this._id = "completionRunId" in response ? response.completionRunId : response.id;
|
|
2093
|
-
this.status = response.status;
|
|
2287
|
+
this.status = normalizeExecutionStatus(response.status);
|
|
2094
2288
|
if (this._isTask) {
|
|
2095
2289
|
this._task = response;
|
|
2096
2290
|
}
|
|
2097
2291
|
this.emit("poll", {
|
|
2098
2292
|
id: response.id,
|
|
2099
|
-
status: response.status,
|
|
2293
|
+
status: normalizeExecutionStatus(response.status),
|
|
2100
2294
|
outputContent: response.outputContent,
|
|
2101
2295
|
rawOutput: "rawOutput" in response ? response.rawOutput : void 0,
|
|
2102
2296
|
requestId: response.requestId
|
|
@@ -2129,27 +2323,27 @@ class CanvasExecution extends Emittery__default {
|
|
|
2129
2323
|
throw new InvalidExecutionModeError("Polling is only supported for async executions");
|
|
2130
2324
|
}
|
|
2131
2325
|
return new Poller({
|
|
2132
|
-
interval: this._params.pollingInterval ?? 1e3,
|
|
2326
|
+
interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
|
|
2133
2327
|
// 1 second
|
|
2134
|
-
timeout: this._params.pollingTimeout ?? 6e4,
|
|
2328
|
+
timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
|
|
2135
2329
|
// 1 minute
|
|
2136
2330
|
abortSignal: this._abortController.signal
|
|
2137
|
-
}).start(async (
|
|
2331
|
+
}).start(async () => {
|
|
2138
2332
|
const response = await this._client.get(
|
|
2139
2333
|
`/v2/chat/completions/${this.id}`,
|
|
2140
2334
|
{
|
|
2141
|
-
signal
|
|
2335
|
+
signal: this._abortController.signal
|
|
2142
2336
|
}
|
|
2143
2337
|
);
|
|
2144
|
-
this.status = response.status;
|
|
2338
|
+
this.status = normalizeExecutionStatus(response.status);
|
|
2145
2339
|
this.emit("poll", response);
|
|
2146
|
-
if (
|
|
2340
|
+
if (this.status === "failed") {
|
|
2147
2341
|
const error = new ExecutionFailedError(response.rawOutput);
|
|
2148
2342
|
this.cancel();
|
|
2149
2343
|
this.emit("error", error);
|
|
2150
2344
|
throw error;
|
|
2151
2345
|
}
|
|
2152
|
-
if (
|
|
2346
|
+
if (this.status !== "succeeded") {
|
|
2153
2347
|
return {
|
|
2154
2348
|
done: false,
|
|
2155
2349
|
value: void 0
|
|
@@ -2158,7 +2352,7 @@ class CanvasExecution extends Emittery__default {
|
|
|
2158
2352
|
this._rawResultValue = response;
|
|
2159
2353
|
this.emit("success", { ...getResultFromPollingResponse(response), requestId: response?.requestId });
|
|
2160
2354
|
return {
|
|
2161
|
-
done:
|
|
2355
|
+
done: this.status === "succeeded",
|
|
2162
2356
|
value: getResultFromPollingResponse(response)
|
|
2163
2357
|
};
|
|
2164
2358
|
}).then((value) => {
|
|
@@ -2167,7 +2361,7 @@ class CanvasExecution extends Emittery__default {
|
|
|
2167
2361
|
}
|
|
2168
2362
|
return this._outputSchema.parse(value);
|
|
2169
2363
|
}).catch((error) => {
|
|
2170
|
-
if (this.
|
|
2364
|
+
if (this.status !== "failed") {
|
|
2171
2365
|
this.status = "failed";
|
|
2172
2366
|
}
|
|
2173
2367
|
if (this.listenerCount("error") > 0) {
|
|
@@ -2196,56 +2390,7 @@ class CanvasExecution extends Emittery__default {
|
|
|
2196
2390
|
* ```
|
|
2197
2391
|
*/
|
|
2198
2392
|
async uploadFile(file) {
|
|
2199
|
-
|
|
2200
|
-
let sha256sumStream;
|
|
2201
|
-
if (typeof content === "string") {
|
|
2202
|
-
return { fileUrl: content, options: file.options };
|
|
2203
|
-
}
|
|
2204
|
-
const filename = file.name ?? void 0;
|
|
2205
|
-
const fileType = file.type ?? void 0;
|
|
2206
|
-
const contentLength = file.size ?? void 0;
|
|
2207
|
-
if (content instanceof ReadableStream) {
|
|
2208
|
-
const [hashStream, contentStream] = content.tee();
|
|
2209
|
-
content = contentStream;
|
|
2210
|
-
sha256sumStream = hashStream;
|
|
2211
|
-
}
|
|
2212
|
-
const sha256sum = await calculateSha256sum(sha256sumStream ?? content);
|
|
2213
|
-
const { id, uploadUrl } = await this._client.post("/_services/vault/files", {
|
|
2214
|
-
body: {
|
|
2215
|
-
fileName: filename,
|
|
2216
|
-
mimeType: fileType,
|
|
2217
|
-
size: contentLength ?? void 0,
|
|
2218
|
-
sha256sum
|
|
2219
|
-
}
|
|
2220
|
-
});
|
|
2221
|
-
if (content instanceof ReadableStream && typeof Bun !== "undefined") {
|
|
2222
|
-
console.warn(
|
|
2223
|
-
"[Tela SDK - WARNING] Buffering file upload due to Bun fetch implementation. Large files may cause memory issues. Consider using Node.js for streaming uploads.",
|
|
2224
|
-
{ fileName: filename, fileSize: contentLength }
|
|
2225
|
-
);
|
|
2226
|
-
const chunks = [];
|
|
2227
|
-
const reader = content.getReader();
|
|
2228
|
-
while (true) {
|
|
2229
|
-
const { done, value } = await reader.read();
|
|
2230
|
-
if (done)
|
|
2231
|
-
break;
|
|
2232
|
-
chunks.push(value);
|
|
2233
|
-
}
|
|
2234
|
-
content = new Blob(chunks, { type: fileType ?? "application/octet-stream" });
|
|
2235
|
-
}
|
|
2236
|
-
const request = new Request(uploadUrl, {
|
|
2237
|
-
method: "PUT",
|
|
2238
|
-
body: content,
|
|
2239
|
-
headers: {
|
|
2240
|
-
"Content-Type": fileType ?? "application/octet-stream",
|
|
2241
|
-
...file.size ? { "Content-Length": file.size.toString() } : {}
|
|
2242
|
-
}
|
|
2243
|
-
});
|
|
2244
|
-
const uploadResponse = await fetch(request);
|
|
2245
|
-
if (!uploadResponse.ok) {
|
|
2246
|
-
throw new FileUploadError(await uploadResponse.text(), uploadResponse.status);
|
|
2247
|
-
}
|
|
2248
|
-
return { fileUrl: `vault://${id}`, options: file.options };
|
|
2393
|
+
return uploadFile(file, this._client);
|
|
2249
2394
|
}
|
|
2250
2395
|
/**
|
|
2251
2396
|
* Uploads multiple files and returns their URLs and options.
|
|
@@ -2262,213 +2407,1516 @@ class CanvasExecution extends Emittery__default {
|
|
|
2262
2407
|
}
|
|
2263
2408
|
}
|
|
2264
2409
|
|
|
2265
|
-
var __defProp$
|
|
2266
|
-
var __defNormalProp$
|
|
2267
|
-
var __publicField$
|
|
2268
|
-
__defNormalProp$
|
|
2410
|
+
var __defProp$4 = Object.defineProperty;
|
|
2411
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2412
|
+
var __publicField$4 = (obj, key, value) => {
|
|
2413
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2269
2414
|
return value;
|
|
2270
2415
|
};
|
|
2271
|
-
const
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2416
|
+
const BatchResultItem = z__default.looseObject({
|
|
2417
|
+
reference_id: z__default.string(),
|
|
2418
|
+
status: z__default.string(),
|
|
2419
|
+
execution_id: z__default.string(),
|
|
2420
|
+
result: z__default.object({
|
|
2421
|
+
id: z__default.string(),
|
|
2422
|
+
tags: z__default.array(z__default.string()),
|
|
2423
|
+
status: z__default.string(),
|
|
2424
|
+
metadata: z__default.object({
|
|
2425
|
+
promptVersion: z__default.object({
|
|
2426
|
+
modelConfigurations: z__default.object({
|
|
2427
|
+
type: z__default.string(),
|
|
2428
|
+
model: z__default.string(),
|
|
2429
|
+
temperature: z__default.number(),
|
|
2430
|
+
structuredOutput: z__default.object({
|
|
2431
|
+
schema: z__default.looseObject({}).optional(),
|
|
2432
|
+
enabled: z__default.boolean()
|
|
2433
|
+
})
|
|
2434
|
+
}),
|
|
2435
|
+
variablesDefinitions: z__default.array(
|
|
2436
|
+
z__default.object({
|
|
2437
|
+
name: z__default.string(),
|
|
2438
|
+
type: z__default.string(),
|
|
2439
|
+
required: z__default.boolean(),
|
|
2440
|
+
processingOptions: z__default.object({ allowMultimodal: z__default.boolean() })
|
|
2441
|
+
})
|
|
2442
|
+
)
|
|
2443
|
+
})
|
|
2444
|
+
}),
|
|
2445
|
+
promptId: z__default.string(),
|
|
2446
|
+
rawInput: z__default.object({
|
|
2447
|
+
tags: z__default.array(z__default.string()),
|
|
2448
|
+
async: z__default.boolean(),
|
|
2449
|
+
canvas_id: z__default.string(),
|
|
2450
|
+
variables: z__default.looseObject({})
|
|
2451
|
+
}),
|
|
2452
|
+
createdAt: z__default.string(),
|
|
2453
|
+
deletedAt: z__default.null(),
|
|
2454
|
+
rawOutput: z__default.object({
|
|
2455
|
+
id: z__default.string(),
|
|
2456
|
+
usage: z__default.object({
|
|
2457
|
+
cost: z__default.object({
|
|
2458
|
+
total_cost: z__default.number(),
|
|
2459
|
+
prompt_cost: z__default.number(),
|
|
2460
|
+
completion_cost: z__default.number()
|
|
2461
|
+
}),
|
|
2462
|
+
total_tokens: z__default.number(),
|
|
2463
|
+
prompt_tokens: z__default.number(),
|
|
2464
|
+
completion_tokens: z__default.number()
|
|
2465
|
+
}),
|
|
2466
|
+
object: z__default.string(),
|
|
2467
|
+
choices: z__default.array(
|
|
2468
|
+
z__default.object({
|
|
2469
|
+
message: z__default.object({
|
|
2470
|
+
role: z__default.string(),
|
|
2471
|
+
content: z__default.looseObject({}),
|
|
2472
|
+
tool_calls: z__default.array(z__default.object({ type: z__default.string(), function: z__default.object({ name: z__default.string(), arguments: z__default.looseObject({}) }) })),
|
|
2473
|
+
function_call: z__default.null()
|
|
2474
|
+
})
|
|
2475
|
+
})
|
|
2476
|
+
),
|
|
2477
|
+
created: z__default.number()
|
|
2478
|
+
}),
|
|
2479
|
+
updatedAt: z__default.string(),
|
|
2480
|
+
creditsUsed: z__default.number(),
|
|
2481
|
+
workspaceId: z__default.string(),
|
|
2482
|
+
inputContent: z__default.object({
|
|
2483
|
+
files: z__default.array(z__default.object({ file_url: z__default.string() })),
|
|
2484
|
+
messages: z__default.array(z__default.object({ role: z__default.string(), content: z__default.looseObject({}) })),
|
|
2485
|
+
variables: z__default.looseObject({})
|
|
2486
|
+
}),
|
|
2487
|
+
outputContent: z__default.object({
|
|
2488
|
+
role: z__default.string(),
|
|
2489
|
+
content: z__default.looseObject({}),
|
|
2490
|
+
tool_calls: z__default.array(z__default.looseObject({})),
|
|
2491
|
+
function_call: z__default.string().nullable()
|
|
2492
|
+
}),
|
|
2493
|
+
promptVersionId: z__default.string(),
|
|
2494
|
+
compatibilityDate: z__default.string(),
|
|
2495
|
+
promptApplicationId: z__default.string().nullable()
|
|
2496
|
+
}),
|
|
2497
|
+
error: z__default.null()
|
|
2498
|
+
});
|
|
2499
|
+
class BatchExecutionResult {
|
|
2500
|
+
/**
|
|
2501
|
+
* Creates a new batch execution result wrapper.
|
|
2502
|
+
*
|
|
2503
|
+
* @param client - HTTP client for making API requests.
|
|
2504
|
+
* @param response - Raw batch execution response from the server.
|
|
2505
|
+
* @internal
|
|
2506
|
+
*/
|
|
2507
|
+
constructor(client, response) {
|
|
2508
|
+
__publicField$4(this, "_client");
|
|
2509
|
+
__publicField$4(this, "_response");
|
|
2510
|
+
this._client = client;
|
|
2511
|
+
this._response = response;
|
|
2287
2512
|
}
|
|
2288
|
-
|
|
2289
|
-
return
|
|
2513
|
+
get requestId() {
|
|
2514
|
+
return this._response.requestId;
|
|
2290
2515
|
}
|
|
2291
|
-
|
|
2292
|
-
|
|
2516
|
+
/**
|
|
2517
|
+
* Gets the unique identifier for this batch execution.
|
|
2518
|
+
*
|
|
2519
|
+
* @returns The batch execution ID.
|
|
2520
|
+
*/
|
|
2521
|
+
get id() {
|
|
2522
|
+
return this._response.id;
|
|
2523
|
+
}
|
|
2524
|
+
/**
|
|
2525
|
+
* Gets the current status of the batch execution.
|
|
2526
|
+
*
|
|
2527
|
+
* @returns The batch status.
|
|
2528
|
+
*/
|
|
2529
|
+
get status() {
|
|
2530
|
+
return this._response.status;
|
|
2531
|
+
}
|
|
2532
|
+
/**
|
|
2533
|
+
* Gets the progress statistics for this batch.
|
|
2534
|
+
*
|
|
2535
|
+
* @returns Object containing completed, failed, and total execution counts, or null if not available.
|
|
2536
|
+
*/
|
|
2537
|
+
get state() {
|
|
2538
|
+
return this._response.state;
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* Gets the vault URL of the output JSONL file containing all results.
|
|
2542
|
+
*
|
|
2543
|
+
* @returns The output file URL, or null if batch is not completed.
|
|
2544
|
+
*/
|
|
2545
|
+
get outputFile() {
|
|
2546
|
+
return this._response.outputFile;
|
|
2547
|
+
}
|
|
2548
|
+
/**
|
|
2549
|
+
* Gets the raw API response without any processing.
|
|
2550
|
+
*
|
|
2551
|
+
* @returns The complete batch response object.
|
|
2552
|
+
*/
|
|
2553
|
+
get rawResponse() {
|
|
2554
|
+
return this._response;
|
|
2555
|
+
}
|
|
2556
|
+
/**
|
|
2557
|
+
* Gets the timestamp when this batch was created.
|
|
2558
|
+
*
|
|
2559
|
+
* @returns Creation date.
|
|
2560
|
+
*/
|
|
2561
|
+
get createdAt() {
|
|
2562
|
+
return new Date(this._response.createdAt);
|
|
2563
|
+
}
|
|
2564
|
+
/**
|
|
2565
|
+
* Gets the timestamp when this batch was last updated.
|
|
2566
|
+
*
|
|
2567
|
+
* @returns Last update date.
|
|
2568
|
+
*/
|
|
2569
|
+
get updatedAt() {
|
|
2570
|
+
return new Date(this._response.updatedAt);
|
|
2571
|
+
}
|
|
2572
|
+
/**
|
|
2573
|
+
* Gets the timestamp when this batch completed successfully.
|
|
2574
|
+
*
|
|
2575
|
+
* @returns Completion date, or null if not completed.
|
|
2576
|
+
*/
|
|
2577
|
+
get completedAt() {
|
|
2578
|
+
return this._response.completedAt ? new Date(this._response.completedAt) : null;
|
|
2579
|
+
}
|
|
2580
|
+
/**
|
|
2581
|
+
* Gets the timestamp when this batch was canceled.
|
|
2582
|
+
*
|
|
2583
|
+
* @returns Cancellation date, or null if not canceled.
|
|
2584
|
+
*/
|
|
2585
|
+
get canceledAt() {
|
|
2586
|
+
return this._response.canceledAt ? new Date(this._response.canceledAt) : null;
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2589
|
+
* Gets the timestamp when this batch failed.
|
|
2590
|
+
*
|
|
2591
|
+
* @returns Failure date, or null if not failed.
|
|
2592
|
+
*/
|
|
2593
|
+
get failedAt() {
|
|
2594
|
+
return this._response.failedAt ? new Date(this._response.failedAt) : null;
|
|
2595
|
+
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Downloads the complete output file as a Blob.
|
|
2598
|
+
*
|
|
2599
|
+
* The output file is a JSONL (JSON Lines) file where each line contains
|
|
2600
|
+
* one execution result with its reference ID, status, and output.
|
|
2601
|
+
*
|
|
2602
|
+
* @throws {Error} If batch is not completed or output file is unavailable.
|
|
2603
|
+
* @returns A promise resolving to the output file as a Blob.
|
|
2604
|
+
*
|
|
2605
|
+
* @example
|
|
2606
|
+
* ```typescript
|
|
2607
|
+
* const file = await result.downloadOutputFile()
|
|
2608
|
+
* const text = await file.text()
|
|
2609
|
+
* console.log(text) // JSONL content
|
|
2610
|
+
* ```
|
|
2611
|
+
*/
|
|
2612
|
+
downloadOutputFile() {
|
|
2613
|
+
this.validateOutputFile();
|
|
2614
|
+
return downloadFile(this._response.outputFile, this._client);
|
|
2615
|
+
}
|
|
2616
|
+
/**
|
|
2617
|
+
* Streams the output file as a ReadableStream for memory-efficient processing.
|
|
2618
|
+
*
|
|
2619
|
+
* Useful for large batches where loading the entire file into memory is not practical.
|
|
2620
|
+
*
|
|
2621
|
+
* @throws {Error} If batch is not completed or output file is unavailable.
|
|
2622
|
+
* @returns A promise resolving to a ReadableStream of the output file.
|
|
2623
|
+
*
|
|
2624
|
+
* @example
|
|
2625
|
+
* ```typescript
|
|
2626
|
+
* const stream = await result.streamOutputFile()
|
|
2627
|
+
* // Process stream with custom logic
|
|
2628
|
+
* ```
|
|
2629
|
+
*/
|
|
2630
|
+
async streamOutputFile() {
|
|
2631
|
+
this.validateOutputFile();
|
|
2632
|
+
return streamFile(this._response.outputFile, this._client);
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Downloads and parses all results into an array.
|
|
2636
|
+
*
|
|
2637
|
+
* Loads the entire output file into memory, parses each line, and extracts
|
|
2638
|
+
* the output content. For large batches, consider using `iterateResults()` instead.
|
|
2639
|
+
*
|
|
2640
|
+
* @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
|
|
2641
|
+
* @returns A promise resolving to an array of all execution outputs.
|
|
2642
|
+
*
|
|
2643
|
+
* @example
|
|
2644
|
+
* ```typescript
|
|
2645
|
+
* const results = await result.getResults()
|
|
2646
|
+
* console.log(`Got ${results.length} results`)
|
|
2647
|
+
* results.forEach((output, i) => console.log(`Result ${i}:`, output))
|
|
2648
|
+
* ```
|
|
2649
|
+
*/
|
|
2650
|
+
async getResults() {
|
|
2651
|
+
const resultFile = await this.downloadOutputFile();
|
|
2652
|
+
const results = await resultFile.text();
|
|
2653
|
+
return results.split("\n").filter((line) => line.trim().length > 0).map((result) => JSON.parse(result)).map((result) => {
|
|
2654
|
+
const parsedResult = BatchResultItem.safeParse(result);
|
|
2655
|
+
if (!parsedResult.success) {
|
|
2656
|
+
throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
|
|
2657
|
+
}
|
|
2658
|
+
return parsedResult.data.result.outputContent.content;
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
/**
|
|
2662
|
+
* Asynchronously iterates over raw result items from the output file.
|
|
2663
|
+
*
|
|
2664
|
+
* Streams and parses the output file line-by-line, yielding raw JSON objects.
|
|
2665
|
+
* Each yielded object contains the full result structure including metadata.
|
|
2666
|
+
*
|
|
2667
|
+
* @param params - Iteration options.
|
|
2668
|
+
* @param params.abortController - Optional AbortController to cancel iteration.
|
|
2669
|
+
* @throws {Error} If batch is not completed or output file is unavailable.
|
|
2670
|
+
* @yields Raw result objects from the JSONL file.
|
|
2671
|
+
*
|
|
2672
|
+
* @example
|
|
2673
|
+
* ```typescript
|
|
2674
|
+
* for await (const rawResult of result.iterateRawResults()) {
|
|
2675
|
+
* console.log('Reference ID:', rawResult.reference_id)
|
|
2676
|
+
* console.log('Status:', rawResult.status)
|
|
2677
|
+
* console.log('Output:', rawResult.result.outputContent.content)
|
|
2678
|
+
* }
|
|
2679
|
+
* ```
|
|
2680
|
+
*/
|
|
2681
|
+
async *iterateRawResults(params = {}) {
|
|
2682
|
+
const { abortController = new AbortController() } = params;
|
|
2683
|
+
const stream = await this.streamOutputFile();
|
|
2684
|
+
for await (const result of Stream.fromReadableStream(stream, abortController)) {
|
|
2685
|
+
yield result;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
/**
|
|
2689
|
+
* Asynchronously iterates over parsed output content from the batch results.
|
|
2690
|
+
*
|
|
2691
|
+
* Streams and parses the output file line-by-line, yielding only the output content
|
|
2692
|
+
* (not the full result metadata). Memory-efficient for large batches.
|
|
2693
|
+
*
|
|
2694
|
+
* @param params - Iteration options.
|
|
2695
|
+
* @param params.abortController - Optional AbortController to cancel iteration.
|
|
2696
|
+
* @throws {Error} If batch is not completed, output file is unavailable, or parsing fails.
|
|
2697
|
+
* @yields Parsed output content from each execution.
|
|
2698
|
+
*
|
|
2699
|
+
* @example
|
|
2700
|
+
* ```typescript
|
|
2701
|
+
* const controller = new AbortController()
|
|
2702
|
+
*
|
|
2703
|
+
* for await (const output of result.iterateResults({ abortController: controller })) {
|
|
2704
|
+
* console.log(output)
|
|
2705
|
+
* if (someCondition) {
|
|
2706
|
+
* controller.abort() // Stop iteration early
|
|
2707
|
+
* }
|
|
2708
|
+
* }
|
|
2709
|
+
* ```
|
|
2710
|
+
*/
|
|
2711
|
+
async *iterateResults(params = {}) {
|
|
2712
|
+
for await (const result of this.iterateRawResults(params)) {
|
|
2713
|
+
const parsedResult = BatchResultItem.safeParse(result);
|
|
2714
|
+
if (!parsedResult.success) {
|
|
2715
|
+
throw new Error("Invalid result from the batch API", { cause: parsedResult.error });
|
|
2716
|
+
}
|
|
2717
|
+
yield parsedResult.data.result.outputContent.content;
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Fetches the raw result metadata for a specific execution by its reference ID.
|
|
2722
|
+
*
|
|
2723
|
+
* Queries the API for the execution result using the reference ID tag.
|
|
2724
|
+
* Returns the complete execution metadata including input, output, and usage statistics.
|
|
2725
|
+
*
|
|
2726
|
+
* @param referenceId - The reference ID of the execution to retrieve.
|
|
2727
|
+
* @throws {Error} If no result found with the given reference ID.
|
|
2728
|
+
* @returns A promise resolving to the raw execution result object.
|
|
2729
|
+
*
|
|
2730
|
+
* @example
|
|
2731
|
+
* ```typescript
|
|
2732
|
+
* const rawResult = await result.getRawResult('my-ref-id')
|
|
2733
|
+
* console.log('Credits used:', rawResult.creditsUsed)
|
|
2734
|
+
* console.log('Execution status:', rawResult.status)
|
|
2735
|
+
* ```
|
|
2736
|
+
*/
|
|
2737
|
+
async getRawResult(referenceId) {
|
|
2738
|
+
const response = await this._client.get("/v1/completion-run/", {
|
|
2739
|
+
query: {
|
|
2740
|
+
tags: `reference_id:${referenceId}`
|
|
2741
|
+
}
|
|
2742
|
+
});
|
|
2743
|
+
const result = response.data[0];
|
|
2744
|
+
if (!result) {
|
|
2745
|
+
throw new Error("Result not found");
|
|
2746
|
+
}
|
|
2747
|
+
return result;
|
|
2748
|
+
}
|
|
2749
|
+
/**
|
|
2750
|
+
* Fetches the output content for a specific execution by its reference ID.
|
|
2751
|
+
*
|
|
2752
|
+
* Convenience method that retrieves the raw result and extracts just the output content.
|
|
2753
|
+
*
|
|
2754
|
+
* @param referenceId - The reference ID of the execution to retrieve.
|
|
2755
|
+
* @throws {Error} If no result found with the given reference ID.
|
|
2756
|
+
* @returns A promise resolving to the execution output content.
|
|
2757
|
+
*
|
|
2758
|
+
* @example
|
|
2759
|
+
* ```typescript
|
|
2760
|
+
* const output = await result.getResult('my-ref-id')
|
|
2761
|
+
* console.log('Output:', output)
|
|
2762
|
+
* ```
|
|
2763
|
+
*/
|
|
2764
|
+
async getResult(referenceId) {
|
|
2765
|
+
const result = await this.getRawResult(referenceId);
|
|
2766
|
+
return result.outputContent.content;
|
|
2767
|
+
}
|
|
2768
|
+
/**
|
|
2769
|
+
* Validates that the output file is available for access.
|
|
2770
|
+
*
|
|
2771
|
+
* @throws {Error} If batch is not completed or output file is missing.
|
|
2772
|
+
* @private
|
|
2773
|
+
*/
|
|
2774
|
+
validateOutputFile() {
|
|
2775
|
+
if (this._response.status !== "completed") {
|
|
2776
|
+
throw new Error("Batch execution is not completed");
|
|
2777
|
+
}
|
|
2778
|
+
if (!this._response.outputFile) {
|
|
2779
|
+
throw new Error("Output file not found");
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
class BatchExecution extends Emittery__default {
|
|
2784
|
+
/**
|
|
2785
|
+
* Creates a new batch execution instance.
|
|
2786
|
+
*
|
|
2787
|
+
* @param id - Unique identifier for this batch execution.
|
|
2788
|
+
* @param client - HTTP client for making API requests.
|
|
2789
|
+
* @param params - Batch execution parameters.
|
|
2790
|
+
* @param creationResponse - Initial response from batch creation.
|
|
2791
|
+
* @internal
|
|
2792
|
+
*/
|
|
2793
|
+
constructor(id, client, params = {}, creationResponse) {
|
|
2794
|
+
super();
|
|
2795
|
+
__publicField$4(this, "_client");
|
|
2796
|
+
__publicField$4(this, "_id");
|
|
2797
|
+
__publicField$4(this, "_params");
|
|
2798
|
+
__publicField$4(this, "_abortController");
|
|
2799
|
+
__publicField$4(this, "_creationResponse");
|
|
2800
|
+
__publicField$4(this, "_status", "created");
|
|
2801
|
+
__publicField$4(this, "_resultPromise");
|
|
2802
|
+
this._id = id;
|
|
2803
|
+
this._client = client;
|
|
2804
|
+
this._params = params;
|
|
2805
|
+
this._abortController = new AbortController();
|
|
2806
|
+
this._creationResponse = creationResponse;
|
|
2807
|
+
}
|
|
2808
|
+
/**
|
|
2809
|
+
* Gets the latest known status of the batch execution.
|
|
2810
|
+
*
|
|
2811
|
+
* Status values and transitions:
|
|
2812
|
+
* - `created` → `validating` → `running` → `completed` or `failed`
|
|
2813
|
+
* - Can transition to `canceled` from any non-terminal state
|
|
2814
|
+
*
|
|
2815
|
+
* Use the `statusChange` event to track status transitions in real-time.
|
|
2816
|
+
*
|
|
2817
|
+
* @returns The current status of the batch execution.
|
|
2818
|
+
*
|
|
2819
|
+
* @example
|
|
2820
|
+
* ```typescript
|
|
2821
|
+
* const execution = await batch.execute()
|
|
2822
|
+
* console.log(execution.status) // 'created'
|
|
2823
|
+
*
|
|
2824
|
+
* execution.on('statusChange', ([status]) => {
|
|
2825
|
+
* console.log('New status:', status)
|
|
2826
|
+
* })
|
|
2827
|
+
*
|
|
2828
|
+
* await execution.result
|
|
2829
|
+
* console.log(execution.status) // 'completed' or 'failed'
|
|
2830
|
+
* ```
|
|
2831
|
+
*/
|
|
2832
|
+
get status() {
|
|
2833
|
+
return this._status;
|
|
2834
|
+
}
|
|
2835
|
+
/**
|
|
2836
|
+
* Gets the unique identifier for this batch execution.
|
|
2837
|
+
*
|
|
2838
|
+
* @returns The batch execution ID.
|
|
2839
|
+
*/
|
|
2840
|
+
get id() {
|
|
2841
|
+
return this._id;
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Gets the batch execution parameters.
|
|
2845
|
+
*
|
|
2846
|
+
* @returns The batch parameters.
|
|
2847
|
+
*/
|
|
2848
|
+
get params() {
|
|
2849
|
+
return this._params;
|
|
2850
|
+
}
|
|
2851
|
+
/**
|
|
2852
|
+
* Cancels the batch execution.
|
|
2853
|
+
*
|
|
2854
|
+
* Sends a cancellation request to the server and aborts any ongoing polling.
|
|
2855
|
+
* The batch will stop processing, but already-completed executions remain available.
|
|
2856
|
+
*
|
|
2857
|
+
* @returns A promise that resolves when the cancellation request completes.
|
|
2858
|
+
*
|
|
2859
|
+
* @example
|
|
2860
|
+
* ```typescript
|
|
2861
|
+
* const execution = await batch.execute()
|
|
2862
|
+
* execution.poll()
|
|
2863
|
+
*
|
|
2864
|
+
* // Cancel after some condition
|
|
2865
|
+
* if (shouldCancel) {
|
|
2866
|
+
* await execution.cancel()
|
|
2867
|
+
* console.log(execution.status) // 'canceled'
|
|
2868
|
+
* }
|
|
2869
|
+
* ```
|
|
2870
|
+
*/
|
|
2871
|
+
async cancel() {
|
|
2872
|
+
await this._client.put(`/_services/batch/batches/${this._id}/cancel`);
|
|
2873
|
+
this._status = "canceled";
|
|
2874
|
+
this._abortController.abort();
|
|
2875
|
+
}
|
|
2876
|
+
/**
|
|
2877
|
+
* Starts polling for the batch result without waiting for the promise to resolve.
|
|
2878
|
+
* This allows users to track batch progress via events rather than awaiting a promise.
|
|
2879
|
+
*
|
|
2880
|
+
* The following events will be emitted during polling:
|
|
2881
|
+
* - `statusChange`: Emitted when the batch status changes (e.g., 'created' → 'running' → 'completed')
|
|
2882
|
+
* - `poll`: Emitted on each polling attempt with the server response
|
|
2883
|
+
* - `success`: Emitted when the batch completes successfully with the final result
|
|
2884
|
+
* - `error`: Emitted if the batch fails
|
|
2885
|
+
*
|
|
2886
|
+
* **Important:** Events are only emitted while polling is active. You must call `poll()` or
|
|
2887
|
+
* await `execution.result` to start polling. Simply setting up event listeners without starting
|
|
2888
|
+
* polling will not trigger any events.
|
|
2889
|
+
*
|
|
2890
|
+
* @example
|
|
2891
|
+
* ```typescript
|
|
2892
|
+
* const execution = await batch.execute()
|
|
2893
|
+
*
|
|
2894
|
+
* // Set up event listeners
|
|
2895
|
+
* execution.on('statusChange', ([status, response]) => {
|
|
2896
|
+
* console.log(`Status: ${status}`)
|
|
2897
|
+
* if (response.state) {
|
|
2898
|
+
* const { completed, total } = response.state
|
|
2899
|
+
* console.log(`Progress: ${completed}/${total}`)
|
|
2900
|
+
* }
|
|
2901
|
+
* })
|
|
2902
|
+
*
|
|
2903
|
+
* execution.on('success', (result) => {
|
|
2904
|
+
* console.log('Batch completed!')
|
|
2905
|
+
* console.log('Request ID:', result.requestId)
|
|
2906
|
+
* })
|
|
2907
|
+
*
|
|
2908
|
+
* execution.on('error', (error) => {
|
|
2909
|
+
* console.error('Batch failed:', error)
|
|
2910
|
+
* })
|
|
2911
|
+
*
|
|
2912
|
+
* // Start polling without waiting
|
|
2913
|
+
* execution.poll()
|
|
2914
|
+
* ```
|
|
2915
|
+
*/
|
|
2916
|
+
poll() {
|
|
2917
|
+
if (this._resultPromise) {
|
|
2918
|
+
return;
|
|
2919
|
+
}
|
|
2920
|
+
this._resultPromise = this.startPolling();
|
|
2921
|
+
this._resultPromise.catch(() => {
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
/**
|
|
2925
|
+
* Sets the batch status and emits statusChange event if changed.
|
|
2926
|
+
*
|
|
2927
|
+
* @param status - The new status.
|
|
2928
|
+
* @param response - The response containing the status.
|
|
2929
|
+
* @private
|
|
2930
|
+
*/
|
|
2931
|
+
setStatus(status, response) {
|
|
2932
|
+
const changed = this._status !== status;
|
|
2933
|
+
this._status = status;
|
|
2934
|
+
if (changed) {
|
|
2935
|
+
this.emit("statusChange", [status, response]);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
/**
|
|
2939
|
+
* Starts polling the server for batch completion.
|
|
2940
|
+
* Continues polling until the batch completes, fails, or times out.
|
|
2941
|
+
*
|
|
2942
|
+
* @throws {BatchExecutionFailedError} If the batch fails on the server.
|
|
2943
|
+
* @throws {Error} If the polling operation times out.
|
|
2944
|
+
* @returns A promise resolving to the final batch result.
|
|
2945
|
+
* @private
|
|
2946
|
+
*/
|
|
2947
|
+
async startPolling() {
|
|
2948
|
+
this.emit("statusChange", [this._status, this._creationResponse]);
|
|
2949
|
+
return new Poller({
|
|
2950
|
+
interval: transformDurationToMs(this._params.pollingInterval) ?? 1e3,
|
|
2951
|
+
// 1 second
|
|
2952
|
+
timeout: transformDurationToMs(this._params.pollingTimeout) ?? 6e4,
|
|
2953
|
+
// 1 minute
|
|
2954
|
+
abortSignal: this._abortController.signal
|
|
2955
|
+
}).start(async () => {
|
|
2956
|
+
const response = await this._client.get(
|
|
2957
|
+
`/_services/batch/batches/${this._id}`,
|
|
2958
|
+
{ signal: this._abortController.signal }
|
|
2959
|
+
);
|
|
2960
|
+
this.emit("poll", response);
|
|
2961
|
+
this.setStatus(response.status, response);
|
|
2962
|
+
if (response.status === "failed") {
|
|
2963
|
+
const error = new BatchExecutionFailedError(response);
|
|
2964
|
+
this._abortController.abort();
|
|
2965
|
+
this.emit("error", error);
|
|
2966
|
+
throw error;
|
|
2967
|
+
}
|
|
2968
|
+
if (response.status !== "completed") {
|
|
2969
|
+
return {
|
|
2970
|
+
done: false,
|
|
2971
|
+
value: void 0
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
2974
|
+
const result = new BatchExecutionResult(this._client, response);
|
|
2975
|
+
this.emit("success", result);
|
|
2976
|
+
return {
|
|
2977
|
+
done: true,
|
|
2978
|
+
value: result
|
|
2979
|
+
};
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
/**
|
|
2983
|
+
* Gets the batch execution result. Automatically starts polling if not already started.
|
|
2984
|
+
*
|
|
2985
|
+
* @returns A promise resolving to the batch execution result.
|
|
2986
|
+
*
|
|
2987
|
+
* @example
|
|
2988
|
+
* ```typescript
|
|
2989
|
+
* const execution = await batch.execute()
|
|
2990
|
+
* const result = await execution.result
|
|
2991
|
+
*
|
|
2992
|
+
* // Access results
|
|
2993
|
+
* const outputs = await result.getResults()
|
|
2994
|
+
* console.log(`Got ${outputs.length} results`)
|
|
2995
|
+
* ```
|
|
2996
|
+
*/
|
|
2997
|
+
get result() {
|
|
2998
|
+
if (!this._resultPromise) {
|
|
2999
|
+
this._resultPromise = this.startPolling();
|
|
3000
|
+
}
|
|
3001
|
+
return this._resultPromise;
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
class Batch {
|
|
3005
|
+
/**
|
|
3006
|
+
* Creates a new batch builder.
|
|
3007
|
+
*
|
|
3008
|
+
* @param client - HTTP client for making API requests.
|
|
3009
|
+
* @param canvasIdentifier - Canvas identification (ID + version or application ID).
|
|
3010
|
+
* @param params - Optional batch execution parameters.
|
|
3011
|
+
* @internal
|
|
3012
|
+
*/
|
|
3013
|
+
constructor(client, canvasIdentifier, params = {}) {
|
|
3014
|
+
__publicField$4(this, "_client");
|
|
3015
|
+
__publicField$4(this, "_canvasIdentifier");
|
|
3016
|
+
__publicField$4(this, "_items", []);
|
|
3017
|
+
__publicField$4(this, "_params");
|
|
3018
|
+
this._client = client;
|
|
3019
|
+
this._canvasIdentifier = canvasIdentifier;
|
|
3020
|
+
this._params = params;
|
|
3021
|
+
}
|
|
3022
|
+
/**
|
|
3023
|
+
* Gets the current list of items in this batch.
|
|
3024
|
+
*
|
|
3025
|
+
* @returns Array of batch items.
|
|
3026
|
+
*/
|
|
3027
|
+
get items() {
|
|
3028
|
+
return this._items;
|
|
3029
|
+
}
|
|
3030
|
+
/**
|
|
3031
|
+
* Gets the batch execution parameters.
|
|
3032
|
+
*
|
|
3033
|
+
* @returns The batch parameters.
|
|
3034
|
+
*/
|
|
3035
|
+
get params() {
|
|
3036
|
+
return this._params;
|
|
3037
|
+
}
|
|
3038
|
+
/**
|
|
3039
|
+
* Gets the canvas identifier in the format expected by the API.
|
|
3040
|
+
*
|
|
3041
|
+
* @returns Canvas identifier object.
|
|
3042
|
+
* @private
|
|
3043
|
+
*/
|
|
3044
|
+
get canvasIdentifier() {
|
|
3045
|
+
return "applicationId" in this._canvasIdentifier ? { applicationId: this._canvasIdentifier.applicationId } : { versionId: this._canvasIdentifier.versionId, canvasID: this._canvasIdentifier.id };
|
|
3046
|
+
}
|
|
3047
|
+
/**
|
|
3048
|
+
* Adds one or more items to the batch.
|
|
3049
|
+
*
|
|
3050
|
+
* Items without a reference ID will have UUIDs generated automatically.
|
|
3051
|
+
* This method can be called multiple times to build up the batch incrementally.
|
|
3052
|
+
*
|
|
3053
|
+
* @param item - Single item or array of items to add to the batch.
|
|
3054
|
+
*
|
|
3055
|
+
* @example
|
|
3056
|
+
* ```typescript
|
|
3057
|
+
* // Add single item
|
|
3058
|
+
* batch.add({
|
|
3059
|
+
* referenceId: 'my-custom-id',
|
|
3060
|
+
* variables: { query: 'Hello' }
|
|
3061
|
+
* })
|
|
3062
|
+
*
|
|
3063
|
+
* // Add multiple items
|
|
3064
|
+
* batch.add([
|
|
3065
|
+
* { variables: { query: 'First' } },
|
|
3066
|
+
* { variables: { query: 'Second' } },
|
|
3067
|
+
* { variables: { query: 'Third' } }
|
|
3068
|
+
* ])
|
|
3069
|
+
*
|
|
3070
|
+
* console.log(`Batch has ${batch.items.length} items`)
|
|
3071
|
+
* ```
|
|
3072
|
+
*/
|
|
3073
|
+
add(item) {
|
|
3074
|
+
const items = Array.isArray(item) ? item : [item];
|
|
3075
|
+
for (const item2 of items) {
|
|
3076
|
+
this._items.push({
|
|
3077
|
+
...item2,
|
|
3078
|
+
referenceId: item2.referenceId ?? crypto.randomUUID()
|
|
3079
|
+
});
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
/**
|
|
3083
|
+
* Executes the batch by uploading the input file and creating a batch execution on the server.
|
|
3084
|
+
*
|
|
3085
|
+
* Returns a promise-like object that allows flexible usage patterns:
|
|
3086
|
+
* - Await for execution object: `const exec = await batch.execute()`
|
|
3087
|
+
* - Direct result access: `const result = await batch.execute().result`
|
|
3088
|
+
*
|
|
3089
|
+
* The batch items are serialized to JSONL format, uploaded to vault storage,
|
|
3090
|
+
* and submitted to the batch API for processing.
|
|
3091
|
+
*
|
|
3092
|
+
* @returns A promise-like object with a `result` property for direct result access.
|
|
3093
|
+
*
|
|
3094
|
+
* @example
|
|
3095
|
+
* ```typescript
|
|
3096
|
+
* // Direct result access (recommended for simple cases)
|
|
3097
|
+
* const result = await batch.execute().result
|
|
3098
|
+
* const outputs = await result.getResults()
|
|
3099
|
+
*
|
|
3100
|
+
* // Get execution object for event monitoring
|
|
3101
|
+
* const execution = await batch.execute()
|
|
3102
|
+
*
|
|
3103
|
+
* execution.on('statusChange', ([status, response]) => {
|
|
3104
|
+
* console.log(`Status: ${status}`)
|
|
3105
|
+
* if (response.state) {
|
|
3106
|
+
* console.log(`Progress: ${response.state.completed}/${response.state.total}`)
|
|
3107
|
+
* }
|
|
3108
|
+
* })
|
|
3109
|
+
*
|
|
3110
|
+
* execution.on('success', (result) => {
|
|
3111
|
+
* console.log('Batch completed!', result.requestId)
|
|
3112
|
+
* })
|
|
3113
|
+
*
|
|
3114
|
+
* const result = await execution.result
|
|
3115
|
+
*
|
|
3116
|
+
* // Iterate through results
|
|
3117
|
+
* for await (const output of result.iterateResults()) {
|
|
3118
|
+
* console.log(output)
|
|
3119
|
+
* }
|
|
3120
|
+
* ```
|
|
3121
|
+
*/
|
|
3122
|
+
execute() {
|
|
3123
|
+
const jsonLines = this._items.map((item) => ({
|
|
3124
|
+
...this.canvasIdentifier,
|
|
3125
|
+
...item
|
|
3126
|
+
})).map((item) => transformObjectFromCamelCaseToSnakeCase(item)).map((item) => JSON.stringify(item));
|
|
3127
|
+
const fileContent = new Blob([jsonLines.join("\n")], { type: "application/jsonl" });
|
|
3128
|
+
const file = TelaFile.create(fileContent);
|
|
3129
|
+
const client = this._client;
|
|
3130
|
+
const params = this._params;
|
|
3131
|
+
async function execute() {
|
|
3132
|
+
const { fileUrl } = await uploadFile(file, client);
|
|
3133
|
+
const body = {
|
|
3134
|
+
task: "async-completion",
|
|
3135
|
+
inputFile: fileUrl,
|
|
3136
|
+
webhookUrl: params.webhookUrl
|
|
3137
|
+
};
|
|
3138
|
+
return client.post("/_services/batch/batches", {
|
|
3139
|
+
body
|
|
3140
|
+
}).then((response) => new BatchExecution(response.id, client, params, response));
|
|
3141
|
+
}
|
|
3142
|
+
return {
|
|
3143
|
+
then(onfulfilled, onrejected) {
|
|
3144
|
+
return Promise.resolve(execute()).then((execution) => onfulfilled?.(execution) ?? execution).catch(onrejected);
|
|
3145
|
+
},
|
|
3146
|
+
get result() {
|
|
3147
|
+
return Promise.resolve(execute()).then((execution) => execution.result);
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
|
|
3153
|
+
var __defProp$3 = Object.defineProperty;
|
|
3154
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3155
|
+
var __publicField$3 = (obj, key, value) => {
|
|
3156
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3157
|
+
return value;
|
|
3158
|
+
};
|
|
3159
|
+
function fetchById(id, client) {
|
|
3160
|
+
return client.get(`/prompt/${id}/promoted-version`);
|
|
3161
|
+
}
|
|
3162
|
+
function fetchByVersionId(versionId, client) {
|
|
3163
|
+
return client.get(`/prompt-version/${versionId}`);
|
|
3164
|
+
}
|
|
3165
|
+
function fetchByApplicationId(applicationId, client) {
|
|
3166
|
+
return client.get(`/prompt-application/${applicationId}/targetPromptVersion`);
|
|
3167
|
+
}
|
|
3168
|
+
function fetchByAny({ id, versionId, applicationId, client }) {
|
|
3169
|
+
if (applicationId) {
|
|
3170
|
+
return fetchByApplicationId(applicationId, client);
|
|
3171
|
+
}
|
|
3172
|
+
if (versionId) {
|
|
3173
|
+
return fetchByVersionId(versionId, client);
|
|
3174
|
+
}
|
|
3175
|
+
if (id) {
|
|
3176
|
+
return fetchById(id, client);
|
|
2293
3177
|
}
|
|
2294
3178
|
throw new Error("Either id, versionId, or applicationId must be provided");
|
|
2295
3179
|
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
3180
|
+
class Canvas {
|
|
3181
|
+
/**
|
|
3182
|
+
* Creates a new instance of the Canvas class. Usage of this constructor is not recommended.
|
|
3183
|
+
* Use the `tela.getCanvas` method instead.
|
|
3184
|
+
*
|
|
3185
|
+
* @private
|
|
3186
|
+
*/
|
|
3187
|
+
constructor({ id, applicationId, name, versionId, input, output, client, variables, isWorkflow }) {
|
|
3188
|
+
__publicField$3(this, "_id");
|
|
3189
|
+
__publicField$3(this, "_versionId");
|
|
3190
|
+
__publicField$3(this, "_applicationId");
|
|
3191
|
+
__publicField$3(this, "_name");
|
|
3192
|
+
__publicField$3(this, "_input");
|
|
3193
|
+
__publicField$3(this, "_output");
|
|
3194
|
+
__publicField$3(this, "_client");
|
|
3195
|
+
__publicField$3(this, "_variables");
|
|
3196
|
+
__publicField$3(this, "_isWorkflow");
|
|
3197
|
+
this._id = id;
|
|
3198
|
+
this._applicationId = applicationId;
|
|
3199
|
+
this._name = name;
|
|
3200
|
+
this._versionId = versionId;
|
|
3201
|
+
this._input = input && input(zod);
|
|
3202
|
+
this._output = output && output(zod);
|
|
3203
|
+
this._client = client;
|
|
3204
|
+
this._variables = variables;
|
|
3205
|
+
this._isWorkflow = isWorkflow;
|
|
3206
|
+
}
|
|
3207
|
+
/**
|
|
3208
|
+
* Gets a canvas by its ID.
|
|
3209
|
+
*
|
|
3210
|
+
* @param options - The options to use to get the canvas.
|
|
3211
|
+
* @param options.id - The ID of the canvas to get.
|
|
3212
|
+
* @param options.versionId - The version ID of the canvas to get.
|
|
3213
|
+
* @param options.applicationId - The application ID of the canvas to get.
|
|
3214
|
+
* @param options.client - The client to use to make the request.
|
|
3215
|
+
* @param options.input - The input schema of the canvas to get.
|
|
3216
|
+
* @param options.output - The output schema of the canvas to get.
|
|
3217
|
+
* @returns The canvas.
|
|
3218
|
+
*/
|
|
3219
|
+
static async get(options) {
|
|
3220
|
+
const { id, versionId, applicationId, client, input, output, skipSchemaValidation = false } = options;
|
|
3221
|
+
const promptVersion = await fetchByAny({ id, versionId, applicationId, client });
|
|
3222
|
+
const inputSchema = input && input(zod);
|
|
3223
|
+
const outputSchema = output && output(zod);
|
|
3224
|
+
if (!skipSchemaValidation) {
|
|
3225
|
+
validateSchemas("Canvas", inputSchema, outputSchema, promptVersion);
|
|
3226
|
+
}
|
|
3227
|
+
return new Canvas({
|
|
3228
|
+
id: promptVersion.promptId,
|
|
3229
|
+
versionId: promptVersion.id,
|
|
3230
|
+
applicationId: applicationId ?? void 0,
|
|
3231
|
+
name: promptVersion.title,
|
|
3232
|
+
input,
|
|
3233
|
+
output,
|
|
3234
|
+
client,
|
|
3235
|
+
variables: promptVersion.variables,
|
|
3236
|
+
isWorkflow: promptVersion.isWorkflow
|
|
3237
|
+
});
|
|
3238
|
+
}
|
|
3239
|
+
/**
|
|
3240
|
+
* Gets the unique identifier of this canvas.
|
|
3241
|
+
*
|
|
3242
|
+
* @returns The canvas ID.
|
|
3243
|
+
*/
|
|
3244
|
+
get id() {
|
|
3245
|
+
if (!this._id) {
|
|
3246
|
+
throw new Error("Canvas ID is not set");
|
|
3247
|
+
}
|
|
3248
|
+
return this._id;
|
|
3249
|
+
}
|
|
3250
|
+
/**
|
|
3251
|
+
* Gets the name of this canvas, if provided.
|
|
3252
|
+
*
|
|
3253
|
+
* @returns The canvas name or undefined.
|
|
3254
|
+
*/
|
|
3255
|
+
get name() {
|
|
3256
|
+
if (!this._name) {
|
|
3257
|
+
throw new Error("Canvas name is not set");
|
|
3258
|
+
}
|
|
3259
|
+
return this._name;
|
|
3260
|
+
}
|
|
3261
|
+
/**
|
|
3262
|
+
* Gets the version identifier of this canvas, if specified.
|
|
3263
|
+
* When undefined, the latest promoted version is used.
|
|
3264
|
+
*
|
|
3265
|
+
* @returns The version ID or undefined.
|
|
3266
|
+
*/
|
|
3267
|
+
get versionId() {
|
|
3268
|
+
if (!this._versionId) {
|
|
3269
|
+
throw new Error("Canvas version ID is not set");
|
|
3270
|
+
}
|
|
3271
|
+
return this._versionId;
|
|
3272
|
+
}
|
|
3273
|
+
get applicationId() {
|
|
3274
|
+
if (!this._applicationId) {
|
|
3275
|
+
throw new Error("Canvas application ID is not set");
|
|
3276
|
+
}
|
|
3277
|
+
return this._applicationId;
|
|
3278
|
+
}
|
|
3279
|
+
/**
|
|
3280
|
+
* Gets the variables of this canvas.
|
|
3281
|
+
*
|
|
3282
|
+
* @returns The variables of the canvas.
|
|
3283
|
+
*/
|
|
3284
|
+
get variables() {
|
|
3285
|
+
return this._variables;
|
|
3286
|
+
}
|
|
3287
|
+
/**
|
|
3288
|
+
* Gets whether this canvas is a workflow.
|
|
3289
|
+
*
|
|
3290
|
+
* @returns True if the canvas is a workflow.
|
|
3291
|
+
*/
|
|
3292
|
+
get isWorkflow() {
|
|
3293
|
+
return this._isWorkflow;
|
|
3294
|
+
}
|
|
3295
|
+
/**
|
|
3296
|
+
* Gets whether this canvas is a workstation.
|
|
3297
|
+
* This is true if an application ID is provided.
|
|
3298
|
+
*
|
|
3299
|
+
* @returns True if the canvas is a workstation.
|
|
3300
|
+
*/
|
|
3301
|
+
get isWorkstation() {
|
|
3302
|
+
return Boolean(this._applicationId);
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* Validates and parses input variables using the canvas input schema.
|
|
3306
|
+
*
|
|
3307
|
+
* @param variables - Raw input variables to validate.
|
|
3308
|
+
* @returns Parsed and validated variables.
|
|
3309
|
+
* @throws {ZodError} If validation fails when a Zod schema is configured.
|
|
3310
|
+
*/
|
|
3311
|
+
parseVariables(variables) {
|
|
2299
3312
|
try {
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
if (mismatches.length === 0) {
|
|
2303
|
-
return;
|
|
2304
|
-
}
|
|
2305
|
-
console.warn(
|
|
2306
|
-
`[Tela SDK - Canvas Input Validation] Input schema mismatches for canvas "${canvasIdentifier}":`
|
|
2307
|
-
);
|
|
2308
|
-
for (const mismatch of mismatches) {
|
|
2309
|
-
console.warn(` - ${mismatch.path}: ${mismatch.issue}`);
|
|
3313
|
+
if (this._input instanceof z.z.ZodType) {
|
|
3314
|
+
return this._input.parse(variables);
|
|
2310
3315
|
}
|
|
3316
|
+
return variables;
|
|
2311
3317
|
} catch (error) {
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
);
|
|
3318
|
+
if (!(error instanceof z.ZodError)) {
|
|
3319
|
+
throw error;
|
|
3320
|
+
}
|
|
3321
|
+
throw new Error(z.z.prettifyError(error));
|
|
2316
3322
|
}
|
|
2317
3323
|
}
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
3324
|
+
execute(variables, params) {
|
|
3325
|
+
const parsedInput = this.parseVariables(variables);
|
|
3326
|
+
const idObject = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, canvasId: this._id };
|
|
3327
|
+
const fullParams = {
|
|
3328
|
+
...params ?? { async: false },
|
|
3329
|
+
...idObject
|
|
3330
|
+
};
|
|
3331
|
+
const execution = new CanvasExecution(parsedInput, fullParams, this._output, this._client, this.isWorkstation);
|
|
3332
|
+
return {
|
|
3333
|
+
then(onfulfilled, onrejected) {
|
|
3334
|
+
return Promise.resolve(execution.start()).then(() => onfulfilled?.(execution) ?? execution).catch(onrejected);
|
|
3335
|
+
},
|
|
3336
|
+
get result() {
|
|
3337
|
+
return Promise.resolve(execution.start()).then(() => execution.result);
|
|
3338
|
+
}
|
|
3339
|
+
};
|
|
3340
|
+
}
|
|
3341
|
+
/**
|
|
3342
|
+
* Fetches an existing async execution by its ID.
|
|
3343
|
+
*
|
|
3344
|
+
* This method retrieves the current state of an async execution that was previously
|
|
3345
|
+
* started on this canvas. Only async executions can be fetched, as they are the only
|
|
3346
|
+
* ones with persistent UUIDs on the server.
|
|
3347
|
+
*
|
|
3348
|
+
* @param id - The UUID of the async execution to fetch.
|
|
3349
|
+
* @param options - Optional configuration for polling behavior.
|
|
3350
|
+
* @param options.pollingInterval - Time in milliseconds between polling attempts (default: 1000).
|
|
3351
|
+
* @param options.pollingTimeout - Maximum time in milliseconds to wait for completion (default: 60000).
|
|
3352
|
+
* @throws {InvalidExecutionModeError} If the provided ID is not a valid UUID.
|
|
3353
|
+
* @returns A promise resolving to a CanvasExecution instance with the fetched state.
|
|
3354
|
+
*
|
|
3355
|
+
* @example
|
|
3356
|
+
* ```typescript
|
|
3357
|
+
* // Start an async execution
|
|
3358
|
+
* const execution = await canvas.execute({ query: 'test' }, { async: true })
|
|
3359
|
+
* const executionId = execution.id
|
|
3360
|
+
*
|
|
3361
|
+
* // Later, fetch the execution by ID
|
|
3362
|
+
* const fetched = await canvas.getExecution(executionId)
|
|
3363
|
+
* console.log(fetched.status) // 'running', 'succeeded', or 'failed'
|
|
3364
|
+
*
|
|
3365
|
+
* // Use poll() for event-driven progress tracking
|
|
3366
|
+
* fetched.on('statusChange', (status) => console.log('Status:', status))
|
|
3367
|
+
* fetched.poll()
|
|
3368
|
+
* ```
|
|
3369
|
+
*/
|
|
3370
|
+
async getExecution(id, options) {
|
|
3371
|
+
return CanvasExecution.fetch(
|
|
3372
|
+
id,
|
|
3373
|
+
this._output,
|
|
3374
|
+
this._client,
|
|
3375
|
+
{
|
|
3376
|
+
...options,
|
|
3377
|
+
isTask: this.isWorkstation
|
|
3378
|
+
}
|
|
3379
|
+
);
|
|
3380
|
+
}
|
|
3381
|
+
/**
|
|
3382
|
+
* Prepares to execute this canvas in batch.
|
|
3383
|
+
*
|
|
3384
|
+
* @param params - The parameters for the batch.
|
|
3385
|
+
* @param params.pollingInterval - The interval between polling attempts.
|
|
3386
|
+
* @param params.pollingTimeout - The timeout for the batch.
|
|
3387
|
+
* @param params.webhookUrl - The webhook URL for the batch.
|
|
3388
|
+
*
|
|
3389
|
+
* @example
|
|
3390
|
+
* ```typescript
|
|
3391
|
+
* const batch = canvas.createBatch({
|
|
3392
|
+
* pollingInterval: '1s',
|
|
3393
|
+
* pollingTimeout: '1m',
|
|
3394
|
+
* webhookUrl: 'https://example.com/webhook',
|
|
3395
|
+
* })
|
|
3396
|
+
*
|
|
3397
|
+
* batch.add({
|
|
3398
|
+
* referenceId: crypto.randomUUID(), // Optional
|
|
3399
|
+
* variables: { query: 'Hello' },
|
|
3400
|
+
* })
|
|
3401
|
+
*
|
|
3402
|
+
* const execution = await batch.execute()
|
|
3403
|
+
* const result = await execution.result
|
|
3404
|
+
* const resultFile = await execution.downloadOutputFile()
|
|
3405
|
+
* ```
|
|
3406
|
+
*
|
|
3407
|
+
* @returns The batch instance that can be used to manage the batch.
|
|
3408
|
+
*/
|
|
3409
|
+
createBatch(params = {}) {
|
|
3410
|
+
const canvasIdentifier = this._applicationId ? { applicationId: this._applicationId } : { versionId: this._versionId, id: this._id };
|
|
3411
|
+
return new Batch(this._client, canvasIdentifier, params);
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
|
|
3415
|
+
const TaskStatus = z.z.enum(["created", "failed", "running", "validating", "completed", "cancelled"]);
|
|
3416
|
+
const OutputContent = z.z.object({
|
|
3417
|
+
role: z.z.literal("assistant"),
|
|
3418
|
+
content: z.z.unknown(),
|
|
3419
|
+
toolCalls: z.z.array(z.z.any()),
|
|
3420
|
+
functionCall: z.z.any()
|
|
3421
|
+
});
|
|
3422
|
+
const RawInput = z.z.object({
|
|
3423
|
+
async: z.z.boolean(),
|
|
3424
|
+
stream: z.z.boolean(),
|
|
3425
|
+
variables: z.z.record(z.z.string(), z.z.unknown()),
|
|
3426
|
+
applicationId: z.z.string()
|
|
3427
|
+
});
|
|
3428
|
+
z.z.object({
|
|
3429
|
+
id: z.z.string(),
|
|
3430
|
+
reference: z.z.number(),
|
|
3431
|
+
name: z.z.string(),
|
|
3432
|
+
status: TaskStatus,
|
|
3433
|
+
rawInput: RawInput,
|
|
3434
|
+
inputContent: z.z.any(),
|
|
3435
|
+
outputContent: OutputContent,
|
|
3436
|
+
originalOutputContent: OutputContent,
|
|
3437
|
+
createdBy: z.z.string(),
|
|
3438
|
+
approvedBy: z.z.any(),
|
|
3439
|
+
approvedAt: z.z.any(),
|
|
3440
|
+
completionRunId: z.z.string(),
|
|
3441
|
+
workflowRunId: z.z.any(),
|
|
3442
|
+
promptVersionId: z.z.string(),
|
|
3443
|
+
promptApplicationId: z.z.string(),
|
|
3444
|
+
workspaceId: z.z.string(),
|
|
3445
|
+
metadata: z.z.any(),
|
|
3446
|
+
tags: z.z.array(z.z.string()),
|
|
3447
|
+
createdAt: z.z.string(),
|
|
3448
|
+
updatedAt: z.z.string(),
|
|
3449
|
+
deletedAt: z.z.any(),
|
|
3450
|
+
requestId: z.z.string()
|
|
3451
|
+
});
|
|
3452
|
+
|
|
3453
|
+
var __defProp$2 = Object.defineProperty;
|
|
3454
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3455
|
+
var __publicField$2 = (obj, key, value) => {
|
|
3456
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3457
|
+
return value;
|
|
3458
|
+
};
|
|
3459
|
+
class Task extends Emittery__default {
|
|
3460
|
+
constructor(client, variables, task, requestId, outputSchema, skipResultValidation = false) {
|
|
3461
|
+
super();
|
|
3462
|
+
__publicField$2(this, "_variables");
|
|
3463
|
+
__publicField$2(this, "_task");
|
|
3464
|
+
__publicField$2(this, "_abortController", new AbortController());
|
|
3465
|
+
__publicField$2(this, "_client");
|
|
3466
|
+
__publicField$2(this, "_outputSchema");
|
|
3467
|
+
__publicField$2(this, "_skipResultValidation");
|
|
3468
|
+
__publicField$2(this, "_resultPromise");
|
|
3469
|
+
__publicField$2(this, "_status");
|
|
3470
|
+
__publicField$2(this, "_requestId");
|
|
3471
|
+
this._variables = variables;
|
|
3472
|
+
this._task = task;
|
|
3473
|
+
this._client = client;
|
|
3474
|
+
this._outputSchema = outputSchema;
|
|
3475
|
+
this._skipResultValidation = skipResultValidation;
|
|
3476
|
+
this._status = task.status;
|
|
3477
|
+
this._requestId = requestId;
|
|
3478
|
+
}
|
|
3479
|
+
/**
|
|
3480
|
+
* Gets the unique task ID assigned by the server.
|
|
3481
|
+
*
|
|
3482
|
+
* @returns The task ID.
|
|
3483
|
+
*/
|
|
3484
|
+
get id() {
|
|
3485
|
+
if (!this._task.id) {
|
|
3486
|
+
throw new Error("Task ID is not available");
|
|
3487
|
+
}
|
|
3488
|
+
return this._task.id;
|
|
3489
|
+
}
|
|
3490
|
+
/**
|
|
3491
|
+
* Gets the request ID from the `x-request-id` header of the task creation request.
|
|
3492
|
+
*
|
|
3493
|
+
* This is the request ID from the initial POST /task request that created the task.
|
|
3494
|
+
* Each API request has its own unique request ID.
|
|
3495
|
+
*
|
|
3496
|
+
* For polling operations, different request IDs are available:
|
|
3497
|
+
* - `task.requestId` - ID from the task creation request
|
|
3498
|
+
* - `pollResult.requestId` - ID from each polling request (in poll events)
|
|
3499
|
+
* - `result.requestId` - ID from the final successful polling request (in success events)
|
|
3500
|
+
*
|
|
3501
|
+
* @returns A promise that resolves to the request ID from the task creation request.
|
|
3502
|
+
*
|
|
3503
|
+
* @example
|
|
3504
|
+
* ```typescript
|
|
3505
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3506
|
+
* const requestId = await task.requestId
|
|
3507
|
+
* console.log('Request ID:', requestId)
|
|
3508
|
+
* ```
|
|
3509
|
+
*/
|
|
3510
|
+
get requestId() {
|
|
3511
|
+
return this._requestId;
|
|
3512
|
+
}
|
|
3513
|
+
/**
|
|
3514
|
+
* Gets the latest known status of the task.
|
|
3515
|
+
*
|
|
3516
|
+
* Status values and transitions:
|
|
3517
|
+
* - `created` → `running` → `completed` or `failed`
|
|
3518
|
+
*
|
|
3519
|
+
* **Important:** Status is set to `completed` only after successful validation.
|
|
3520
|
+
* If validation fails, status will be `failed` even if the API request succeeded.
|
|
3521
|
+
*
|
|
3522
|
+
* Use the `statusChange` event to track status transitions in real-time.
|
|
3523
|
+
*
|
|
3524
|
+
* @returns The current status of the task.
|
|
3525
|
+
*
|
|
3526
|
+
* @example
|
|
3527
|
+
* ```typescript
|
|
3528
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3529
|
+
* console.log(task.status) // 'created'
|
|
3530
|
+
*
|
|
3531
|
+
* await task.result
|
|
3532
|
+
* console.log(task.status) // 'completed' or 'failed'
|
|
3533
|
+
* ```
|
|
3534
|
+
*/
|
|
3535
|
+
get status() {
|
|
3536
|
+
return this._status;
|
|
3537
|
+
}
|
|
3538
|
+
/**
|
|
3539
|
+
* Sets the status of the task and emits statusChange event.
|
|
3540
|
+
*
|
|
3541
|
+
* @param status - The new status of the task.
|
|
3542
|
+
* @private
|
|
3543
|
+
*/
|
|
3544
|
+
set status(status) {
|
|
3545
|
+
const changed = this._status !== status;
|
|
3546
|
+
this._status = status;
|
|
3547
|
+
if (changed) {
|
|
3548
|
+
this.emit("statusChange", status);
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
/**
|
|
3552
|
+
* Gets the input variables provided to this task.
|
|
3553
|
+
*
|
|
3554
|
+
* @returns The variables object.
|
|
3555
|
+
*/
|
|
3556
|
+
get variables() {
|
|
3557
|
+
return this._variables;
|
|
3558
|
+
}
|
|
3559
|
+
/**
|
|
3560
|
+
* Gets the task label (alias for name).
|
|
3561
|
+
*
|
|
3562
|
+
* @returns The task name.
|
|
3563
|
+
*/
|
|
3564
|
+
get label() {
|
|
3565
|
+
return this.name;
|
|
3566
|
+
}
|
|
3567
|
+
/**
|
|
3568
|
+
* Gets the task name.
|
|
3569
|
+
*
|
|
3570
|
+
* @returns The task name.
|
|
3571
|
+
*/
|
|
3572
|
+
get name() {
|
|
3573
|
+
return this._task.name;
|
|
3574
|
+
}
|
|
3575
|
+
/**
|
|
3576
|
+
* Gets the task tags.
|
|
3577
|
+
*
|
|
3578
|
+
* @returns The task tags.
|
|
3579
|
+
*/
|
|
3580
|
+
get tags() {
|
|
3581
|
+
return this._task.tags;
|
|
3582
|
+
}
|
|
3583
|
+
/**
|
|
3584
|
+
* Gets the raw task definition from the server.
|
|
3585
|
+
*
|
|
3586
|
+
* @returns The raw task definition.
|
|
3587
|
+
*/
|
|
3588
|
+
get rawTask() {
|
|
3589
|
+
return this._task;
|
|
3590
|
+
}
|
|
3591
|
+
/**
|
|
3592
|
+
* Starts polling for the task result without waiting for the promise to resolve.
|
|
3593
|
+
* This allows users to track task progress via events rather than awaiting a promise.
|
|
3594
|
+
*
|
|
3595
|
+
* The following events will be emitted during polling:
|
|
3596
|
+
* - `statusChange`: Emitted when the task status changes (e.g., 'created' → 'running' → 'completed')
|
|
3597
|
+
* - `poll`: Emitted on each polling attempt with the server response
|
|
3598
|
+
* - `success`: Emitted when the task completes successfully with the final result
|
|
3599
|
+
* - `error`: Emitted if the task fails
|
|
3600
|
+
*
|
|
3601
|
+
* **Important:** Events are only emitted while polling is active. You must call `poll()` or
|
|
3602
|
+
* await `task.result` to start polling. Simply setting up event listeners without starting
|
|
3603
|
+
* polling will not trigger any events.
|
|
3604
|
+
*
|
|
3605
|
+
* @example
|
|
3606
|
+
* ```typescript
|
|
3607
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3608
|
+
*
|
|
3609
|
+
* // Set up event listeners
|
|
3610
|
+
* task.on('statusChange', (status) => {
|
|
3611
|
+
* console.log('Status:', status)
|
|
3612
|
+
* })
|
|
3613
|
+
*
|
|
3614
|
+
* task.on('success', (result) => {
|
|
3615
|
+
* console.log('Completed:', result)
|
|
3616
|
+
* })
|
|
3617
|
+
*
|
|
3618
|
+
* task.on('error', (error) => {
|
|
3619
|
+
* console.error('Failed:', error)
|
|
3620
|
+
* })
|
|
3621
|
+
*
|
|
3622
|
+
* // Start polling without waiting
|
|
3623
|
+
* task.poll()
|
|
3624
|
+
* ```
|
|
3625
|
+
*/
|
|
3626
|
+
poll() {
|
|
3627
|
+
if (this._resultPromise) {
|
|
3628
|
+
return;
|
|
3629
|
+
}
|
|
3630
|
+
this._resultPromise = this.startPolling();
|
|
3631
|
+
this._resultPromise.catch(() => {
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
/**
|
|
3635
|
+
* Gets the task result. Automatically starts polling if not already started.
|
|
3636
|
+
*
|
|
3637
|
+
* @returns A promise that resolves to the validated task output.
|
|
3638
|
+
*
|
|
3639
|
+
* @example
|
|
3640
|
+
* ```typescript
|
|
3641
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
3642
|
+
* const result = await task.result
|
|
3643
|
+
* console.log(result)
|
|
3644
|
+
* ```
|
|
3645
|
+
*/
|
|
3646
|
+
get result() {
|
|
3647
|
+
if (this._resultPromise) {
|
|
3648
|
+
return this._resultPromise;
|
|
3649
|
+
}
|
|
3650
|
+
this._resultPromise = this.startPolling();
|
|
3651
|
+
return this._resultPromise;
|
|
3652
|
+
}
|
|
3653
|
+
/**
|
|
3654
|
+
* Starts the polling process to retrieve task results.
|
|
3655
|
+
* Emits events during the polling lifecycle and validates output before resolving.
|
|
3656
|
+
*
|
|
3657
|
+
* @returns A promise that resolves to the validated task output.
|
|
3658
|
+
* @private
|
|
3659
|
+
*/
|
|
3660
|
+
async startPolling() {
|
|
3661
|
+
const result = await new Poller({
|
|
3662
|
+
interval: 1e3,
|
|
3663
|
+
timeout: 6e4,
|
|
3664
|
+
abortSignal: this._abortController.signal
|
|
3665
|
+
}).start(async () => {
|
|
3666
|
+
const response = await this._client.get(`/task/${this.id}`, {
|
|
3667
|
+
signal: this._abortController.signal
|
|
3668
|
+
});
|
|
3669
|
+
const newStatus = response.status;
|
|
3670
|
+
this.status = newStatus;
|
|
3671
|
+
this.emit("poll", response);
|
|
3672
|
+
if (response.status === "failed") {
|
|
3673
|
+
const error = new TaskFailedError(response, "Task failure reported by the server");
|
|
3674
|
+
this.status = "failed";
|
|
3675
|
+
this.emit("error", error);
|
|
3676
|
+
if (this.listenerCount("error") === 0) {
|
|
3677
|
+
throw error;
|
|
3678
|
+
}
|
|
3679
|
+
return {
|
|
3680
|
+
done: true,
|
|
3681
|
+
value: void 0
|
|
3682
|
+
};
|
|
2327
3683
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
3684
|
+
if (!["completed", "validating"].includes(response.status)) {
|
|
3685
|
+
return {
|
|
3686
|
+
done: false,
|
|
3687
|
+
value: void 0
|
|
3688
|
+
};
|
|
2331
3689
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
3690
|
+
return {
|
|
3691
|
+
done: true,
|
|
3692
|
+
value: response
|
|
3693
|
+
};
|
|
3694
|
+
});
|
|
3695
|
+
try {
|
|
3696
|
+
const value = result;
|
|
3697
|
+
if (value === void 0) {
|
|
3698
|
+
return void 0;
|
|
2337
3699
|
}
|
|
3700
|
+
const content = value.outputContent.content;
|
|
3701
|
+
const validatedContent = this._skipResultValidation || !(this._outputSchema instanceof z__default.ZodType) ? content : this._outputSchema.parse(content);
|
|
3702
|
+
this.status = value.status;
|
|
3703
|
+
this.emit("success", validatedContent);
|
|
3704
|
+
return validatedContent;
|
|
2338
3705
|
} catch (error) {
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
);
|
|
3706
|
+
this.status = "failed";
|
|
3707
|
+
const castError = error instanceof Error ? error : new Error(String(error));
|
|
3708
|
+
const message = castError instanceof z.ZodError ? z__default.prettifyError(castError) : castError.message;
|
|
3709
|
+
this.emit("error", new TaskFailedError(result, message, castError));
|
|
3710
|
+
if (this.listenerCount("error") === 0) {
|
|
3711
|
+
throw error;
|
|
3712
|
+
}
|
|
3713
|
+
return void 0;
|
|
2343
3714
|
}
|
|
2344
3715
|
}
|
|
2345
3716
|
}
|
|
2346
|
-
|
|
3717
|
+
|
|
3718
|
+
var __defProp$1 = Object.defineProperty;
|
|
3719
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3720
|
+
var __publicField$1 = (obj, key, value) => {
|
|
3721
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3722
|
+
return value;
|
|
3723
|
+
};
|
|
3724
|
+
const DateRange = z__default.object({
|
|
3725
|
+
since: z__default.union([z__default.date().transform((date) => date.toISOString()), z__default.iso.datetime()]),
|
|
3726
|
+
until: z__default.union([z__default.date().transform((date) => date.toISOString()), z__default.iso.datetime()])
|
|
3727
|
+
});
|
|
3728
|
+
const TaskListFilters = z__default.looseObject({
|
|
3729
|
+
id: z__default.uuid().array().optional(),
|
|
3730
|
+
name: z__default.string().optional(),
|
|
3731
|
+
status: z__default.array(TaskStatus).optional(),
|
|
3732
|
+
approvedAt: DateRange.partial().optional(),
|
|
3733
|
+
createdAt: DateRange.partial().optional(),
|
|
3734
|
+
updatedAt: DateRange.partial().optional(),
|
|
3735
|
+
approvedBy: z__default.string().optional(),
|
|
3736
|
+
createdBy: z__default.string().optional(),
|
|
3737
|
+
completionRunId: z__default.uuid().optional(),
|
|
3738
|
+
promptVersionId: z__default.uuid().optional()
|
|
3739
|
+
}).transform(({ name, approvedAt, createdAt, updatedAt, ...rest }) => ({
|
|
3740
|
+
taskName: name,
|
|
3741
|
+
...approvedAt ? { approvedAtSince: approvedAt.since, approvedAtUntil: approvedAt.until } : {},
|
|
3742
|
+
...createdAt ? { createdAtSince: createdAt.since, createdAtUntil: createdAt.until } : {},
|
|
3743
|
+
...updatedAt ? { updatedAtSince: updatedAt.since, updatedAtUntil: updatedAt.until } : {},
|
|
3744
|
+
...rest
|
|
3745
|
+
}));
|
|
3746
|
+
const TaskListOptions = z__default.looseObject({
|
|
3747
|
+
limit: z__default.number().optional(),
|
|
3748
|
+
offset: z__default.number().optional(),
|
|
3749
|
+
order: z__default.object({
|
|
3750
|
+
by: z__default.enum(["createdAt", "updatedAt", "approvedAt", "status", "reference", "name"]),
|
|
3751
|
+
direction: z__default.enum(["asc", "desc"])
|
|
3752
|
+
}).optional()
|
|
3753
|
+
}).transform(({ order, ...rest }) => ({
|
|
3754
|
+
orderBy: order?.by,
|
|
3755
|
+
orderDirection: order?.direction,
|
|
3756
|
+
...rest
|
|
3757
|
+
}));
|
|
3758
|
+
class Workstation {
|
|
2347
3759
|
/**
|
|
2348
|
-
* Creates a new instance
|
|
2349
|
-
* Use the `tela.getCanvas` method instead.
|
|
3760
|
+
* Creates a new Workstation instance.
|
|
2350
3761
|
*
|
|
2351
|
-
* @
|
|
3762
|
+
* Use {@link Workstation.get} instead.
|
|
3763
|
+
* @internal
|
|
2352
3764
|
*/
|
|
2353
|
-
constructor({
|
|
3765
|
+
constructor({ client, applicationId, promptVersion, input, output }) {
|
|
2354
3766
|
__publicField$1(this, "_id");
|
|
2355
|
-
__publicField$1(this, "
|
|
2356
|
-
__publicField$1(this, "
|
|
2357
|
-
__publicField$1(this, "_name");
|
|
3767
|
+
__publicField$1(this, "_promptVersion");
|
|
3768
|
+
__publicField$1(this, "_client");
|
|
2358
3769
|
__publicField$1(this, "_input");
|
|
2359
3770
|
__publicField$1(this, "_output");
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
this._id = id;
|
|
2364
|
-
this._applicationId = applicationId;
|
|
2365
|
-
this._name = name;
|
|
2366
|
-
this._versionId = versionId;
|
|
3771
|
+
this._id = applicationId;
|
|
3772
|
+
this._promptVersion = promptVersion;
|
|
3773
|
+
this._client = client;
|
|
2367
3774
|
this._input = input && input(zod);
|
|
2368
3775
|
this._output = output && output(zod);
|
|
2369
|
-
this._client = client;
|
|
2370
|
-
this._variables = variables;
|
|
2371
|
-
this._isWorkflow = isWorkflow;
|
|
2372
3776
|
}
|
|
2373
3777
|
/**
|
|
2374
|
-
*
|
|
3778
|
+
* The unique identifier for this workstation (application ID).
|
|
3779
|
+
*/
|
|
3780
|
+
get id() {
|
|
3781
|
+
return this._id;
|
|
3782
|
+
}
|
|
3783
|
+
/**
|
|
3784
|
+
* The prompt version configuration for this workstation.
|
|
3785
|
+
*/
|
|
3786
|
+
get promptVersion() {
|
|
3787
|
+
return this._promptVersion;
|
|
3788
|
+
}
|
|
3789
|
+
/**
|
|
3790
|
+
* Retrieves a workstation by application ID and optionally validates schemas.
|
|
2375
3791
|
*
|
|
2376
|
-
*
|
|
2377
|
-
*
|
|
2378
|
-
* @param options
|
|
2379
|
-
* @param options.
|
|
2380
|
-
* @param options.
|
|
2381
|
-
* @param options.input -
|
|
2382
|
-
* @param options.output -
|
|
2383
|
-
* @
|
|
3792
|
+
* This is the recommended way to create a Workstation instance.
|
|
3793
|
+
*
|
|
3794
|
+
* @param options - Configuration options
|
|
3795
|
+
* @param options.client - The BaseClient instance for API communication
|
|
3796
|
+
* @param options.applicationId - The unique ID of the workstation
|
|
3797
|
+
* @param options.input - Optional input schema function
|
|
3798
|
+
* @param options.output - Optional output schema function
|
|
3799
|
+
* @param options.skipSchemaValidation - Whether to skip schema validation (defaults to false)
|
|
3800
|
+
* @returns A promise that resolves to a Workstation instance
|
|
3801
|
+
*
|
|
3802
|
+
* @throws {Error} If schema validation fails (when schemas are provided and skipSchemaValidation is false)
|
|
3803
|
+
*
|
|
3804
|
+
* @example
|
|
3805
|
+
* ```typescript
|
|
3806
|
+
* const workstation = await Workstation.get({
|
|
3807
|
+
* client,
|
|
3808
|
+
* applicationId: 'app-123',
|
|
3809
|
+
* input: schema => schema.object({
|
|
3810
|
+
* query: schema.string(),
|
|
3811
|
+
* }),
|
|
3812
|
+
* output: schema => schema.object({
|
|
3813
|
+
* answer: schema.string(),
|
|
3814
|
+
* }),
|
|
3815
|
+
* })
|
|
3816
|
+
* ```
|
|
2384
3817
|
*/
|
|
2385
3818
|
static async get(options) {
|
|
2386
|
-
const {
|
|
2387
|
-
const
|
|
3819
|
+
const { client, applicationId, input, output, skipSchemaValidation = false } = options;
|
|
3820
|
+
const id = z__default.uuid({ error: (error) => `Invalid application ID: '${error.input}'. Must be a valid UUID.` }).parse(applicationId);
|
|
3821
|
+
const promptVersion = await client.get(`/prompt-application/${id}/targetPromptVersion`);
|
|
2388
3822
|
const inputSchema = input && input(zod);
|
|
2389
3823
|
const outputSchema = output && output(zod);
|
|
2390
3824
|
if (!skipSchemaValidation) {
|
|
2391
|
-
validateSchemas(inputSchema, outputSchema, promptVersion);
|
|
3825
|
+
validateSchemas("Workstation", inputSchema, outputSchema, promptVersion);
|
|
2392
3826
|
}
|
|
2393
|
-
return new
|
|
2394
|
-
id: promptVersion.promptId,
|
|
2395
|
-
versionId: promptVersion.id,
|
|
2396
|
-
applicationId: applicationId ?? void 0,
|
|
2397
|
-
name: promptVersion.title,
|
|
2398
|
-
input,
|
|
2399
|
-
output,
|
|
3827
|
+
return new Workstation({
|
|
2400
3828
|
client,
|
|
2401
|
-
|
|
2402
|
-
|
|
3829
|
+
applicationId: id,
|
|
3830
|
+
promptVersion,
|
|
3831
|
+
input,
|
|
3832
|
+
output
|
|
2403
3833
|
});
|
|
2404
3834
|
}
|
|
2405
3835
|
/**
|
|
2406
|
-
*
|
|
3836
|
+
* Creates a new task for this workstation and returns a promise-like object.
|
|
2407
3837
|
*
|
|
2408
|
-
*
|
|
2409
|
-
|
|
2410
|
-
get id() {
|
|
2411
|
-
if (!this._id) {
|
|
2412
|
-
throw new Error("Canvas ID is not set");
|
|
2413
|
-
}
|
|
2414
|
-
return this._id;
|
|
2415
|
-
}
|
|
2416
|
-
/**
|
|
2417
|
-
* Gets the name of this canvas, if provided.
|
|
3838
|
+
* The returned object can be awaited directly to get the Task instance, or you can
|
|
3839
|
+
* access `.result` to get the final task output directly.
|
|
2418
3840
|
*
|
|
2419
|
-
* @
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
if (!this._name) {
|
|
2423
|
-
throw new Error("Canvas name is not set");
|
|
2424
|
-
}
|
|
2425
|
-
return this._name;
|
|
2426
|
-
}
|
|
2427
|
-
/**
|
|
2428
|
-
* Gets the version identifier of this canvas, if specified.
|
|
2429
|
-
* When undefined, the latest promoted version is used.
|
|
3841
|
+
* @param variables - Input variables for the task (must match the input schema)
|
|
3842
|
+
* @param params - Optional task parameters (label, tags, skipResultValidation)
|
|
3843
|
+
* @returns A promise-like object that resolves to the Task instance
|
|
2430
3844
|
*
|
|
2431
|
-
* @
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
throw new Error("Canvas version ID is not set");
|
|
2436
|
-
}
|
|
2437
|
-
return this._versionId;
|
|
2438
|
-
}
|
|
2439
|
-
get applicationId() {
|
|
2440
|
-
if (!this._applicationId) {
|
|
2441
|
-
throw new Error("Canvas application ID is not set");
|
|
2442
|
-
}
|
|
2443
|
-
return this._applicationId;
|
|
2444
|
-
}
|
|
2445
|
-
/**
|
|
2446
|
-
* Gets the variables of this canvas.
|
|
3845
|
+
* @example
|
|
3846
|
+
* ```typescript
|
|
3847
|
+
* // Get the task instance
|
|
3848
|
+
* const task = await workstation.createTask({ query: 'test' })
|
|
2447
3849
|
*
|
|
2448
|
-
*
|
|
3850
|
+
* // Or get the result directly
|
|
3851
|
+
* const result = await workstation.createTask({ query: 'test' }).result
|
|
3852
|
+
* ```
|
|
2449
3853
|
*/
|
|
2450
|
-
|
|
2451
|
-
|
|
3854
|
+
createTask(variables, params = {}) {
|
|
3855
|
+
const validatedVariables = this.parseVariables(variables);
|
|
3856
|
+
const taskDefinitionPromise = this.resolveVariables(validatedVariables).then((resolvedVariables) => this._client.post(`/task`, {
|
|
3857
|
+
body: {
|
|
3858
|
+
name: params.label ?? "Task from SDK",
|
|
3859
|
+
tags: params.tags ?? void 0,
|
|
3860
|
+
promptApplicationId: this._id,
|
|
3861
|
+
rawInput: {
|
|
3862
|
+
variables: resolvedVariables
|
|
3863
|
+
}
|
|
3864
|
+
},
|
|
3865
|
+
transformCase: false
|
|
3866
|
+
})).then((response) => {
|
|
3867
|
+
return new Task(
|
|
3868
|
+
this._client,
|
|
3869
|
+
variables,
|
|
3870
|
+
response[0],
|
|
3871
|
+
response.requestId,
|
|
3872
|
+
this._output,
|
|
3873
|
+
params.skipResultValidation ?? false
|
|
3874
|
+
);
|
|
3875
|
+
});
|
|
3876
|
+
return {
|
|
3877
|
+
then(onfulfilled, onrejected) {
|
|
3878
|
+
return Promise.resolve(taskDefinitionPromise).then((task) => onfulfilled?.(task) ?? task).catch(onrejected);
|
|
3879
|
+
},
|
|
3880
|
+
get result() {
|
|
3881
|
+
return Promise.resolve(taskDefinitionPromise).then((task) => task.result);
|
|
3882
|
+
}
|
|
3883
|
+
};
|
|
2452
3884
|
}
|
|
2453
3885
|
/**
|
|
2454
|
-
*
|
|
3886
|
+
* Retrieves an existing task by its ID.
|
|
2455
3887
|
*
|
|
2456
|
-
*
|
|
2457
|
-
*/
|
|
2458
|
-
get isWorkflow() {
|
|
2459
|
-
return this._isWorkflow;
|
|
2460
|
-
}
|
|
2461
|
-
/**
|
|
2462
|
-
* Gets whether this canvas is a workstation.
|
|
2463
|
-
* This is true if an application ID is provided.
|
|
3888
|
+
* This is useful for resuming monitoring of a task that was created earlier.
|
|
2464
3889
|
*
|
|
2465
|
-
* @
|
|
3890
|
+
* @param id - The task ID to retrieve
|
|
3891
|
+
* @param options - Optional configuration
|
|
3892
|
+
* @param options.skipResultValidation - Whether to skip output validation
|
|
3893
|
+
* @returns A promise that resolves to the Task instance
|
|
3894
|
+
*
|
|
3895
|
+
* @example
|
|
3896
|
+
* ```typescript
|
|
3897
|
+
* const task = await workstation.getTask('task-id')
|
|
3898
|
+
*
|
|
3899
|
+
* // Set up event listeners
|
|
3900
|
+
* task.on('statusChange', (status) => console.log('Status:', status))
|
|
3901
|
+
* task.on('success', (result) => console.log('Result:', result))
|
|
3902
|
+
*
|
|
3903
|
+
* // Start polling
|
|
3904
|
+
* task.poll()
|
|
3905
|
+
* ```
|
|
2466
3906
|
*/
|
|
2467
|
-
|
|
2468
|
-
|
|
3907
|
+
async getTask(id, options = {}) {
|
|
3908
|
+
const taskResponse = await this._client.get(`/task/${id}`);
|
|
3909
|
+
return new Task(
|
|
3910
|
+
this._client,
|
|
3911
|
+
taskResponse.rawInput.variables,
|
|
3912
|
+
taskResponse,
|
|
3913
|
+
taskResponse.requestId,
|
|
3914
|
+
this._output,
|
|
3915
|
+
options.skipResultValidation ?? false
|
|
3916
|
+
);
|
|
2469
3917
|
}
|
|
2470
3918
|
/**
|
|
2471
|
-
* Validates and parses input variables using the
|
|
3919
|
+
* Validates and parses input variables using the workstation input schema.
|
|
2472
3920
|
*
|
|
2473
3921
|
* @param variables - Raw input variables to validate.
|
|
2474
3922
|
* @returns Parsed and validated variables.
|
|
@@ -2476,7 +3924,7 @@ class Canvas {
|
|
|
2476
3924
|
*/
|
|
2477
3925
|
parseVariables(variables) {
|
|
2478
3926
|
try {
|
|
2479
|
-
if (this._input instanceof
|
|
3927
|
+
if (this._input instanceof z__default.ZodType) {
|
|
2480
3928
|
return this._input.parse(variables);
|
|
2481
3929
|
}
|
|
2482
3930
|
return variables;
|
|
@@ -2484,65 +3932,140 @@ class Canvas {
|
|
|
2484
3932
|
if (!(error instanceof z.ZodError)) {
|
|
2485
3933
|
throw error;
|
|
2486
3934
|
}
|
|
2487
|
-
throw new Error(
|
|
3935
|
+
throw new Error(z__default.prettifyError(error));
|
|
2488
3936
|
}
|
|
2489
3937
|
}
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
const
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
get result() {
|
|
2503
|
-
return Promise.resolve(execution.start()).then(() => execution.result);
|
|
3938
|
+
/**
|
|
3939
|
+
* Processes variables and uploads any TelaFile instances to the server.
|
|
3940
|
+
* Replaces TelaFile objects with their uploaded URLs while preserving other values.
|
|
3941
|
+
*
|
|
3942
|
+
* @returns A promise resolving to the processed variables object.
|
|
3943
|
+
*/
|
|
3944
|
+
async resolveVariables(inputVariables) {
|
|
3945
|
+
const variables = {};
|
|
3946
|
+
for (const [key, value] of Object.entries(inputVariables)) {
|
|
3947
|
+
if (isTelaFileArray(value)) {
|
|
3948
|
+
variables[key] = { files: await uploadFiles(value, this._client) };
|
|
3949
|
+
continue;
|
|
2504
3950
|
}
|
|
2505
|
-
|
|
3951
|
+
if (isTelaFile(value)) {
|
|
3952
|
+
variables[key] = await uploadFile(value, this._client);
|
|
3953
|
+
continue;
|
|
3954
|
+
}
|
|
3955
|
+
variables[key] = value;
|
|
3956
|
+
}
|
|
3957
|
+
return variables;
|
|
2506
3958
|
}
|
|
2507
3959
|
/**
|
|
2508
|
-
*
|
|
3960
|
+
* Lists tasks for this workstation with optional filtering and pagination.
|
|
2509
3961
|
*
|
|
2510
|
-
*
|
|
2511
|
-
*
|
|
2512
|
-
* ones with persistent UUIDs on the server.
|
|
3962
|
+
* Returns a page of tasks matching the specified filters, along with metadata
|
|
3963
|
+
* for pagination.
|
|
2513
3964
|
*
|
|
2514
|
-
* @param
|
|
2515
|
-
* @param
|
|
2516
|
-
* @param options
|
|
2517
|
-
* @param
|
|
2518
|
-
* @
|
|
2519
|
-
* @returns A promise resolving to a CanvasExecution instance with the fetched state.
|
|
3965
|
+
* @param params - Query parameters
|
|
3966
|
+
* @param params.filters - Optional filters to apply (ID, name, status, dates, etc.)
|
|
3967
|
+
* @param params.options - Optional pagination and sorting options
|
|
3968
|
+
* @param params.rawQuery - Raw query object (internal use, overrides filters/options)
|
|
3969
|
+
* @returns A promise that resolves to an object containing tasks and pagination metadata
|
|
2520
3970
|
*
|
|
2521
3971
|
* @example
|
|
2522
3972
|
* ```typescript
|
|
2523
|
-
* //
|
|
2524
|
-
* const
|
|
2525
|
-
*
|
|
2526
|
-
*
|
|
2527
|
-
*
|
|
2528
|
-
* const fetched = await canvas.getExecution(executionId)
|
|
2529
|
-
* console.log(fetched.status) // 'running', 'succeeded', or 'failed'
|
|
3973
|
+
* // Get first 10 completed tasks
|
|
3974
|
+
* const { tasks, meta } = await workstation.listTasks({
|
|
3975
|
+
* filters: { status: ['completed'] },
|
|
3976
|
+
* options: { limit: 10, offset: 0 },
|
|
3977
|
+
* })
|
|
2530
3978
|
*
|
|
2531
|
-
* //
|
|
2532
|
-
*
|
|
2533
|
-
*
|
|
3979
|
+
* // Sort by creation date
|
|
3980
|
+
* const { tasks, meta } = await workstation.listTasks({
|
|
3981
|
+
* options: {
|
|
3982
|
+
* order: { by: 'createdAt', direction: 'desc' },
|
|
3983
|
+
* limit: 20,
|
|
3984
|
+
* },
|
|
3985
|
+
* })
|
|
2534
3986
|
* ```
|
|
2535
3987
|
*/
|
|
2536
|
-
async
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
3988
|
+
async listTasks({ filters, options, rawQuery }) {
|
|
3989
|
+
function getQuery(id) {
|
|
3990
|
+
if (rawQuery) {
|
|
3991
|
+
return rawQuery;
|
|
3992
|
+
}
|
|
3993
|
+
const validatedFilters = TaskListFilters.optional().parse(filters);
|
|
3994
|
+
const validatedOptions = TaskListOptions.optional().parse(options);
|
|
3995
|
+
return {
|
|
3996
|
+
promptApplicationId: id,
|
|
3997
|
+
objectLinks: true,
|
|
3998
|
+
...validatedFilters,
|
|
3999
|
+
...validatedOptions
|
|
4000
|
+
};
|
|
4001
|
+
}
|
|
4002
|
+
const query = getQuery(this._id);
|
|
4003
|
+
const response = await this._client.get(`/task`, {
|
|
4004
|
+
query,
|
|
4005
|
+
transformCase: false
|
|
4006
|
+
});
|
|
4007
|
+
const tasks = response.data.map((task) => new Task(
|
|
2540
4008
|
this._client,
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
4009
|
+
task.rawInput?.variables,
|
|
4010
|
+
task,
|
|
4011
|
+
task.requestId,
|
|
4012
|
+
this._output
|
|
4013
|
+
));
|
|
4014
|
+
return {
|
|
4015
|
+
tasks,
|
|
4016
|
+
meta: response.meta
|
|
4017
|
+
};
|
|
4018
|
+
}
|
|
4019
|
+
/**
|
|
4020
|
+
* Asynchronously iterates through all tasks matching the specified filters.
|
|
4021
|
+
*
|
|
4022
|
+
* This generator automatically handles pagination, fetching additional pages
|
|
4023
|
+
* as needed. Each iteration yields a task and the current page metadata.
|
|
4024
|
+
*
|
|
4025
|
+
* @param params - Query parameters
|
|
4026
|
+
* @param params.filters - Optional filters to apply (ID, name, status, dates, etc.)
|
|
4027
|
+
* @param params.options - Optional initial pagination and sorting options
|
|
4028
|
+
* @yields A tuple of [task, metadata] for each task
|
|
4029
|
+
*
|
|
4030
|
+
* @example
|
|
4031
|
+
* ```typescript
|
|
4032
|
+
* // Iterate through all pending tasks
|
|
4033
|
+
* for await (const [task, meta] of workstation.iterateTasks({
|
|
4034
|
+
* filters: { status: ['pending'] },
|
|
4035
|
+
* })) {
|
|
4036
|
+
* console.log(`Task ${task.id}: ${task.status}`)
|
|
4037
|
+
* console.log(`Page ${meta.currentPage} of ${meta.totalPages}`)
|
|
4038
|
+
* }
|
|
4039
|
+
*
|
|
4040
|
+
* // Process tasks in batches
|
|
4041
|
+
* for await (const [task, meta] of workstation.iterateTasks({
|
|
4042
|
+
* options: { limit: 50 },
|
|
4043
|
+
* })) {
|
|
4044
|
+
* await processTask(task)
|
|
4045
|
+
* }
|
|
4046
|
+
* ```
|
|
4047
|
+
*/
|
|
4048
|
+
async *iterateTasks({ filters, options }) {
|
|
4049
|
+
let rawQuery;
|
|
4050
|
+
let hasMore = true;
|
|
4051
|
+
while (hasMore) {
|
|
4052
|
+
const { tasks, meta } = await this.listTasks({
|
|
4053
|
+
filters,
|
|
4054
|
+
options,
|
|
4055
|
+
rawQuery
|
|
4056
|
+
});
|
|
4057
|
+
for (const task of tasks) {
|
|
4058
|
+
yield [task, meta];
|
|
2544
4059
|
}
|
|
2545
|
-
|
|
4060
|
+
if (meta.links.next !== null) {
|
|
4061
|
+
rawQuery = {
|
|
4062
|
+
...meta.links.next,
|
|
4063
|
+
objectLinks: true
|
|
4064
|
+
};
|
|
4065
|
+
} else {
|
|
4066
|
+
hasMore = false;
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
2546
4069
|
}
|
|
2547
4070
|
}
|
|
2548
4071
|
|
|
@@ -2607,6 +4130,17 @@ const _TelaSDK = class _TelaSDK extends BaseClient {
|
|
|
2607
4130
|
});
|
|
2608
4131
|
}
|
|
2609
4132
|
});
|
|
4133
|
+
__publicField(this, "workstation", {
|
|
4134
|
+
get: async (options) => {
|
|
4135
|
+
return Workstation.get({
|
|
4136
|
+
applicationId: options.applicationId,
|
|
4137
|
+
input: options.input,
|
|
4138
|
+
output: options.output,
|
|
4139
|
+
skipSchemaValidation: options.skipSchemaValidation,
|
|
4140
|
+
client: this
|
|
4141
|
+
});
|
|
4142
|
+
}
|
|
4143
|
+
});
|
|
2610
4144
|
this.opts = { baseURL, ...rest };
|
|
2611
4145
|
this.apiKey = apiKey;
|
|
2612
4146
|
this.jwt = jwt;
|
|
@@ -2666,6 +4200,10 @@ __publicField(_TelaSDK, "FileUploadError", FileUploadError);
|
|
|
2666
4200
|
__publicField(_TelaSDK, "MissingApiKeyOrJWTError", MissingApiKeyOrJWTError);
|
|
2667
4201
|
/** Thrown when both an API key and a JWT are provided. */
|
|
2668
4202
|
__publicField(_TelaSDK, "ConflictApiKeyAndJWTError", ConflictApiKeyAndJWTError);
|
|
4203
|
+
/** Thrown when a canvas execution fails on the server. */
|
|
4204
|
+
__publicField(_TelaSDK, "ExecutionFailedError", ExecutionFailedError);
|
|
4205
|
+
/** Thrown when a workstation task fails on the server. */
|
|
4206
|
+
__publicField(_TelaSDK, "TaskFailedError", TaskFailedError);
|
|
2669
4207
|
let TelaSDK = _TelaSDK;
|
|
2670
4208
|
function createTelaClient(opts) {
|
|
2671
4209
|
return new TelaSDK(opts);
|
|
@@ -2676,6 +4214,7 @@ exports.AuthenticationError = AuthenticationError;
|
|
|
2676
4214
|
exports.AuthorizationError = AuthorizationError;
|
|
2677
4215
|
exports.BadRequestError = BadRequestError;
|
|
2678
4216
|
exports.BaseClient = BaseClient;
|
|
4217
|
+
exports.BatchExecutionFailedError = BatchExecutionFailedError;
|
|
2679
4218
|
exports.ConflictApiKeyAndJWTError = ConflictApiKeyAndJWTError;
|
|
2680
4219
|
exports.ConflictError = ConflictError;
|
|
2681
4220
|
exports.ConnectionError = ConnectionError;
|
|
@@ -2690,6 +4229,7 @@ exports.InvalidFileURL = InvalidFileURL;
|
|
|
2690
4229
|
exports.MissingApiKeyOrJWTError = MissingApiKeyOrJWTError;
|
|
2691
4230
|
exports.NotFoundError = NotFoundError;
|
|
2692
4231
|
exports.RateLimitError = RateLimitError;
|
|
4232
|
+
exports.TaskFailedError = TaskFailedError;
|
|
2693
4233
|
exports.TelaError = TelaError;
|
|
2694
4234
|
exports.TelaFile = TelaFile;
|
|
2695
4235
|
exports.TelaFileSchema = TelaFileSchema;
|
|
@@ -2697,4 +4237,6 @@ exports.TelaSDK = TelaSDK;
|
|
|
2697
4237
|
exports.UnprocessableEntityError = UnprocessableEntityError;
|
|
2698
4238
|
exports.UserAbortError = UserAbortError;
|
|
2699
4239
|
exports.createTelaClient = createTelaClient;
|
|
4240
|
+
exports.isTelaFile = isTelaFile;
|
|
4241
|
+
exports.isTelaFileArray = isTelaFileArray;
|
|
2700
4242
|
exports.toError = toError;
|