@meistrari/tela-sdk-js 2.9.4 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -1
- package/dist/index.cjs +425 -3
- package/dist/index.d.cts +552 -10
- package/dist/index.d.mts +552 -10
- package/dist/index.d.ts +552 -10
- package/dist/index.mjs +422 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ The Tela SDK for JavaScript provides a simple and powerful way to interact with
|
|
|
17
17
|
- [Webhook Notifications](#webhook-notifications)
|
|
18
18
|
- [Execution Tags](#execution-tags)
|
|
19
19
|
- [File Handling](#file-handling)
|
|
20
|
+
- [Tasks API](#tasks-api)
|
|
21
|
+
- [Vault API](#vault-api)
|
|
20
22
|
- [Migration Guide from v1.x to v2](#migration-guide-from-v1x-to-v2)
|
|
21
23
|
- [Breaking Changes](#breaking-changes)
|
|
22
24
|
- [Migration Checklist](#migration-checklist)
|
|
@@ -608,6 +610,111 @@ const fileWithRange = TelaFile.create(
|
|
|
608
610
|
)
|
|
609
611
|
```
|
|
610
612
|
|
|
613
|
+
### Tasks API
|
|
614
|
+
|
|
615
|
+
The Tasks API exposes the persistent task records that workstation (application) canvases create. Use it to fetch, list, update, approve, edit, re-run, or delete tasks without dropping down to raw HTTP.
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
import { TelaSDK, extractTaskOutput, normalizeTaskStatus } from '@meistrari/tela-sdk-js'
|
|
619
|
+
|
|
620
|
+
const tela = new TelaSDK({ apiKey: 'your-api-key' })
|
|
621
|
+
|
|
622
|
+
// Fetch a task by id
|
|
623
|
+
const task = await tela.tasks.get('task-id')
|
|
624
|
+
|
|
625
|
+
// Read the parsed output (handles canvas vs workflow shape automatically)
|
|
626
|
+
const output = await tela.tasks.getOutput<MyOutput>('task-id')
|
|
627
|
+
// or, if you already have the task in hand:
|
|
628
|
+
const sameOutput = extractTaskOutput<MyOutput>(task)
|
|
629
|
+
|
|
630
|
+
// List input files attached to the task (e.g. uploaded PDFs)
|
|
631
|
+
const files = await tela.tasks.getInputFiles('task-id')
|
|
632
|
+
|
|
633
|
+
// List tasks with filters
|
|
634
|
+
const { data, meta } = await tela.tasks.list({
|
|
635
|
+
promptApplicationId: 'app-id',
|
|
636
|
+
status: ['validating', 'completed'],
|
|
637
|
+
tags: 'product:my-app',
|
|
638
|
+
createdAtSince: new Date('2024-01-01'),
|
|
639
|
+
excludeInputOutputColumns: true, // omit raw input/input content/original output
|
|
640
|
+
orderBy: ['createdAt'],
|
|
641
|
+
order: 'desc',
|
|
642
|
+
limit: 50,
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
// Lean list rows still include outputContent and flattened inputFiles.
|
|
646
|
+
// Fetch a single task when you need raw input or original output payloads.
|
|
647
|
+
const fullTask = await tela.tasks.get(data[0].id)
|
|
648
|
+
|
|
649
|
+
// Mutations
|
|
650
|
+
await tela.tasks.rename('task-id', 'New name')
|
|
651
|
+
await tela.tasks.approve('task-id') // sets status: 'completed'
|
|
652
|
+
await tela.tasks.setTags('task-id', ['reviewed', 'q2'])
|
|
653
|
+
|
|
654
|
+
// ─── Updating output content ────────────────────────────────────
|
|
655
|
+
// The server uses *deep-merge* semantics on outputContent.content.
|
|
656
|
+
// Keys you do not provide are left untouched. There is no way to
|
|
657
|
+
// delete a field through this API. Three methods cover different
|
|
658
|
+
// use-cases:
|
|
659
|
+
|
|
660
|
+
// 1. Top-level partial patch (single PATCH, no fetch)
|
|
661
|
+
await tela.tasks.patchOutputContent('task-id', { reviewedBy: 'me' })
|
|
662
|
+
|
|
663
|
+
// 2. Single-field shortcut for nested *object* paths
|
|
664
|
+
// Do NOT use this for array indices — use updateOutputContent below.
|
|
665
|
+
await tela.tasks.patchOutputField('task-id', 'profile.email', 'b@x.com')
|
|
666
|
+
|
|
667
|
+
// 3. Read-modify-write — safe for arrays, multiple edits, and any
|
|
668
|
+
// change that needs the previous value. SDK fetches current,
|
|
669
|
+
// runs your updater, then sends the full content via patchOutputContent.
|
|
670
|
+
await tela.tasks.updateOutputContent<MenuOutput>('task-id', (current) => {
|
|
671
|
+
current.menu.items[2].price = 9.99 // mutate in place
|
|
672
|
+
current.menu.items.push({ name: 'New', price: 5 }) // grow arrays
|
|
673
|
+
})
|
|
674
|
+
// Updaters can also return a new value:
|
|
675
|
+
await tela.tasks.updateOutputContent('task-id', current => ({ ...current, reviewed: true }))
|
|
676
|
+
|
|
677
|
+
// Re-run a task (only allowed when status === 'failed')
|
|
678
|
+
const rerun = await tela.tasks.rerun('task-id')
|
|
679
|
+
console.log(rerun.executionRunId)
|
|
680
|
+
|
|
681
|
+
// Delete
|
|
682
|
+
await tela.tasks.delete('task-id') // → { success: true }
|
|
683
|
+
await tela.tasks.deleteBulk(['id1', 'id2']) // → { deleted: 2, deletedIds: [...] }
|
|
684
|
+
await tela.tasks.undoApprovalBulk(['id1', 'id2']) // → { undoApproval: 2, undoApprovalIds: [...] }
|
|
685
|
+
|
|
686
|
+
// Map server statuses to coarse client-friendly buckets
|
|
687
|
+
const uiStatus = normalizeTaskStatus(task.status)
|
|
688
|
+
// 'created' | 'running' → 'running'
|
|
689
|
+
// 'validating' → 'pending'
|
|
690
|
+
// 'completed' → 'succeeded'
|
|
691
|
+
// 'failed' | 'cancelled' → 'failed'
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
The full `Task`, `TaskListItem`, `TaskInputFile`, `TaskListQuery`, `TaskUpdatePayload`, and `TaskStatus` types are exported from the package root, so you don't need to type any task-related responses by hand.
|
|
695
|
+
|
|
696
|
+
### Vault API
|
|
697
|
+
|
|
698
|
+
The Vault API resolves and downloads files stored in the Tela vault. It accepts both `vault://<id>` references and bare ids, and passes through plain `https://` URLs unchanged.
|
|
699
|
+
|
|
700
|
+
```typescript
|
|
701
|
+
const tela = new TelaSDK({ apiKey: 'your-api-key' })
|
|
702
|
+
|
|
703
|
+
// Get a temporary signed URL
|
|
704
|
+
const signedUrl = await tela.vault.getSignedUrl('vault://abc-123')
|
|
705
|
+
|
|
706
|
+
// Resolve any reference (vault:// or https://) to a downloadable URL
|
|
707
|
+
const downloadUrl = await tela.vault.resolve(file.url)
|
|
708
|
+
|
|
709
|
+
// Download as a Blob
|
|
710
|
+
const blob = await tela.vault.download('vault://abc-123')
|
|
711
|
+
|
|
712
|
+
// Stream the file
|
|
713
|
+
const stream = await tela.vault.stream('vault://abc-123')
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
This is particularly useful when reading task input files: `tela.tasks.getInputFiles(id)` returns the file references, and `tela.vault.download(file.url)` downloads them in one call.
|
|
717
|
+
|
|
611
718
|
## Migration Guide from v1.x to v2
|
|
612
719
|
|
|
613
720
|
Version 2.0 of the Tela SDK introduces significant improvements to type safety, schema validation, and API design. This guide will help you migrate your code from v1.x to v2.
|
|
@@ -1097,5 +1204,6 @@ When you execute a canvas using `applicationId`, it creates a task in the applic
|
|
|
1097
1204
|
|
|
1098
1205
|
If you encounter issues during migration, please:
|
|
1099
1206
|
- Check the [examples](./examples/) directory for updated usage patterns
|
|
1100
|
-
- Review the [API documentation](
|
|
1207
|
+
- Review the [API documentation](https://sdk-js.tela.tools/)
|
|
1208
|
+
- Generate the API reference locally with `bun run docs` when checking changes
|
|
1101
1209
|
- Open an issue at [GitHub Issues](https://github.com/meistrari/tela-sdk-js/issues)
|
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,7 @@ const changeCase__namespace = /*#__PURE__*/_interopNamespaceCompat(changeCase);
|
|
|
23
23
|
const z__default = /*#__PURE__*/_interopDefaultCompat(z);
|
|
24
24
|
const Emittery__default = /*#__PURE__*/_interopDefaultCompat(Emittery);
|
|
25
25
|
|
|
26
|
-
const version = "2.
|
|
26
|
+
const version = "2.11.0";
|
|
27
27
|
|
|
28
28
|
var __defProp$a = Object.defineProperty;
|
|
29
29
|
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -1761,7 +1761,11 @@ async function uploadFiles(files, client) {
|
|
|
1761
1761
|
async function downloadFile(vaultReference, client) {
|
|
1762
1762
|
const vaultId = vaultReference.replace("vault://", "");
|
|
1763
1763
|
const response = await client.get(`/_services/vault/files/${vaultId}`);
|
|
1764
|
-
|
|
1764
|
+
const res = await fetch(response.url);
|
|
1765
|
+
if (!res.ok) {
|
|
1766
|
+
throw new Error(`Failed to download file: ${res.status} ${res.statusText}`);
|
|
1767
|
+
}
|
|
1768
|
+
return res.blob();
|
|
1765
1769
|
}
|
|
1766
1770
|
async function streamFile(vaultReference, client) {
|
|
1767
1771
|
const vaultId = vaultReference.replace("vault://", "");
|
|
@@ -3933,6 +3937,7 @@ const TaskListFilters = z__default.looseObject({
|
|
|
3933
3937
|
const TaskListOptions = z__default.looseObject({
|
|
3934
3938
|
limit: z__default.number().optional(),
|
|
3935
3939
|
offset: z__default.number().optional(),
|
|
3940
|
+
excludeInputOutputColumns: z__default.boolean().optional(),
|
|
3936
3941
|
order: z__default.object({
|
|
3937
3942
|
by: z__default.enum(["createdAt", "updatedAt", "approvedAt", "status", "reference", "name"]),
|
|
3938
3943
|
direction: z__default.enum(["asc", "desc"])
|
|
@@ -4235,6 +4240,7 @@ class Workstation {
|
|
|
4235
4240
|
async *iterateTasks({ filters, options }) {
|
|
4236
4241
|
let rawQuery;
|
|
4237
4242
|
let hasMore = true;
|
|
4243
|
+
const validatedOptions = TaskListOptions.optional().parse(options);
|
|
4238
4244
|
while (hasMore) {
|
|
4239
4245
|
const { tasks, meta } = await this.listTasks({
|
|
4240
4246
|
filters,
|
|
@@ -4247,7 +4253,8 @@ class Workstation {
|
|
|
4247
4253
|
if (meta.links.next !== null) {
|
|
4248
4254
|
rawQuery = {
|
|
4249
4255
|
...meta.links.next,
|
|
4250
|
-
objectLinks: true
|
|
4256
|
+
objectLinks: true,
|
|
4257
|
+
...validatedOptions?.excludeInputOutputColumns !== void 0 ? { excludeInputOutputColumns: validatedOptions.excludeInputOutputColumns } : {}
|
|
4251
4258
|
};
|
|
4252
4259
|
} else {
|
|
4253
4260
|
hasMore = false;
|
|
@@ -4256,6 +4263,393 @@ class Workstation {
|
|
|
4256
4263
|
}
|
|
4257
4264
|
}
|
|
4258
4265
|
|
|
4266
|
+
function extractTaskOutput(task) {
|
|
4267
|
+
const oc = task.outputContent;
|
|
4268
|
+
if (!oc)
|
|
4269
|
+
return null;
|
|
4270
|
+
if (oc.output && typeof oc.output === "object" && "output" in oc.output) {
|
|
4271
|
+
return oc.output.output ?? null;
|
|
4272
|
+
}
|
|
4273
|
+
if ("content" in oc && oc.content !== void 0) {
|
|
4274
|
+
return oc.content ?? null;
|
|
4275
|
+
}
|
|
4276
|
+
return null;
|
|
4277
|
+
}
|
|
4278
|
+
function normalizeTaskStatus(status) {
|
|
4279
|
+
switch (status) {
|
|
4280
|
+
case "created":
|
|
4281
|
+
case "running":
|
|
4282
|
+
return "running";
|
|
4283
|
+
case "validating":
|
|
4284
|
+
return "pending";
|
|
4285
|
+
case "completed":
|
|
4286
|
+
return "succeeded";
|
|
4287
|
+
case "failed":
|
|
4288
|
+
case "cancelled":
|
|
4289
|
+
return "failed";
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
const NO_TRANSFORM = { transformCase: false };
|
|
4294
|
+
class Tasks {
|
|
4295
|
+
constructor(client) {
|
|
4296
|
+
this.client = client;
|
|
4297
|
+
}
|
|
4298
|
+
/**
|
|
4299
|
+
* Fetches a task by id.
|
|
4300
|
+
*
|
|
4301
|
+
* @param id - The task id.
|
|
4302
|
+
* @param options - Optional flags.
|
|
4303
|
+
* @param options.includeAnalytics - Include analytics data on the task.
|
|
4304
|
+
*/
|
|
4305
|
+
async get(id, options) {
|
|
4306
|
+
return this.client.get(`/task/${id}`, {
|
|
4307
|
+
query: options?.includeAnalytics ? { includeAnalytics: "true" } : void 0,
|
|
4308
|
+
...NO_TRANSFORM
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
async list(query = {}) {
|
|
4312
|
+
const serialized = serializeTaskListQuery(query);
|
|
4313
|
+
return this.client.get("/task", {
|
|
4314
|
+
query: serialized,
|
|
4315
|
+
// The list endpoint expects pre-serialized array fields (JSON strings),
|
|
4316
|
+
// so disable automatic case transformation of the query payload.
|
|
4317
|
+
transformCase: false
|
|
4318
|
+
});
|
|
4319
|
+
}
|
|
4320
|
+
/**
|
|
4321
|
+
* Updates one or more fields of a task.
|
|
4322
|
+
*
|
|
4323
|
+
* Only `name`, `status`, `tags`, and `outputContent` may be updated.
|
|
4324
|
+
*/
|
|
4325
|
+
async update(id, payload) {
|
|
4326
|
+
return this.client.patch(`/task/${id}`, {
|
|
4327
|
+
body: payload,
|
|
4328
|
+
...NO_TRANSFORM
|
|
4329
|
+
});
|
|
4330
|
+
}
|
|
4331
|
+
/**
|
|
4332
|
+
* Renames a task. Convenience wrapper around {@link update}.
|
|
4333
|
+
*/
|
|
4334
|
+
async rename(id, name) {
|
|
4335
|
+
return this.update(id, { name });
|
|
4336
|
+
}
|
|
4337
|
+
/**
|
|
4338
|
+
* Approves a task by setting its status to `completed`.
|
|
4339
|
+
* Convenience wrapper around {@link update}.
|
|
4340
|
+
*/
|
|
4341
|
+
async approve(id) {
|
|
4342
|
+
return this.update(id, { status: "completed" });
|
|
4343
|
+
}
|
|
4344
|
+
/**
|
|
4345
|
+
* Patches a task's output content with a **deep merge** against the existing
|
|
4346
|
+
* content.
|
|
4347
|
+
*
|
|
4348
|
+
* ⚠️ **Merge semantics, not replace.** The server iterates the keys of the
|
|
4349
|
+
* provided payload and overlays them onto the current `outputContent.content`:
|
|
4350
|
+
*
|
|
4351
|
+
* - Keys you provide overwrite the existing values at the same path.
|
|
4352
|
+
* - Nested objects are merged recursively.
|
|
4353
|
+
* - Arrays of objects are merged positionally by index.
|
|
4354
|
+
* - **Keys you do not provide are left untouched** — there is no way to
|
|
4355
|
+
* delete a field through this API.
|
|
4356
|
+
*
|
|
4357
|
+
* If you only need to update a single (possibly nested) field, prefer
|
|
4358
|
+
* {@link patchOutputField} which handles building the nested payload for you.
|
|
4359
|
+
*
|
|
4360
|
+
* @example Top-level patch
|
|
4361
|
+
* ```typescript
|
|
4362
|
+
* // Existing content: { name: 'foo', price: 10 }
|
|
4363
|
+
* await tela.tasks.patchOutputContent(id, { price: 12 })
|
|
4364
|
+
* // Result: { name: 'foo', price: 12 }
|
|
4365
|
+
* ```
|
|
4366
|
+
*
|
|
4367
|
+
* @example Nested patch
|
|
4368
|
+
* ```typescript
|
|
4369
|
+
* // Existing content: { menu: { items: [{ name: 'A', price: 5 }] } }
|
|
4370
|
+
* await tela.tasks.patchOutputContent(id, { menu: { items: [{ price: 6 }] } })
|
|
4371
|
+
* // Result: { menu: { items: [{ name: 'A', price: 6 }] } }
|
|
4372
|
+
* ```
|
|
4373
|
+
*/
|
|
4374
|
+
async patchOutputContent(id, content) {
|
|
4375
|
+
return this.update(id, { outputContent: { content } });
|
|
4376
|
+
}
|
|
4377
|
+
/**
|
|
4378
|
+
* Patches a single field of a task's output content using a dot-notation path.
|
|
4379
|
+
*
|
|
4380
|
+
* Internally builds a nested object that mirrors the path and submits it via
|
|
4381
|
+
* {@link patchOutputContent}, relying on the server's deep-merge to leave
|
|
4382
|
+
* sibling fields untouched.
|
|
4383
|
+
*
|
|
4384
|
+
* Path syntax:
|
|
4385
|
+
* - `foo.bar.baz` — nested object keys
|
|
4386
|
+
* - `items.0.price` — numeric segments are treated as array indices
|
|
4387
|
+
*
|
|
4388
|
+
* ⚠️ **Use {@link updateOutputContent} for any change inside arrays.** The
|
|
4389
|
+
* server's deep-merge replaces an entire array whenever the patched array's
|
|
4390
|
+
* length differs from the current one. This method only sends a sparse
|
|
4391
|
+
* single-element array (e.g. `[{ price: 7 }]`), so an array index path will
|
|
4392
|
+
* truncate the rest of the items. It is safe for **object paths only**
|
|
4393
|
+
* (e.g. `profile.email`).
|
|
4394
|
+
*
|
|
4395
|
+
* @example Nested object update — safe
|
|
4396
|
+
* ```typescript
|
|
4397
|
+
* // Existing: { profile: { name: 'A', email: 'a@x' } }
|
|
4398
|
+
* await tela.tasks.patchOutputField(id, 'profile.email', 'b@x')
|
|
4399
|
+
* // Result: { profile: { name: 'A', email: 'b@x' } }
|
|
4400
|
+
* ```
|
|
4401
|
+
*
|
|
4402
|
+
* @example Array element update — UNSAFE, prefer updateOutputContent
|
|
4403
|
+
* ```typescript
|
|
4404
|
+
* // ❌ Do NOT use patchOutputField for array indices:
|
|
4405
|
+
* // await tela.tasks.patchOutputField(id, 'items.0.price', 7)
|
|
4406
|
+
* // → server replaces items[] with the single-element sparse array.
|
|
4407
|
+
*
|
|
4408
|
+
* // ✅ Use updateOutputContent instead:
|
|
4409
|
+
* await tela.tasks.updateOutputContent(id, (current) => {
|
|
4410
|
+
* current.items[0].price = 7
|
|
4411
|
+
* })
|
|
4412
|
+
* ```
|
|
4413
|
+
*/
|
|
4414
|
+
async patchOutputField(id, path, value) {
|
|
4415
|
+
if (path.length === 0) {
|
|
4416
|
+
throw new Error("tasks.patchOutputField: path cannot be empty");
|
|
4417
|
+
}
|
|
4418
|
+
const payload = buildNestedPayload(path, value);
|
|
4419
|
+
return this.patchOutputContent(id, payload);
|
|
4420
|
+
}
|
|
4421
|
+
/**
|
|
4422
|
+
* Read-modify-write helper for safely updating any part of a task's output
|
|
4423
|
+
* content — including array elements.
|
|
4424
|
+
*
|
|
4425
|
+
* Fetches the current output, hands you a deep clone via the `updater`
|
|
4426
|
+
* callback (which can mutate it in place or return a new value), then
|
|
4427
|
+
* submits the full updated content via {@link patchOutputContent}. Because
|
|
4428
|
+
* the entire arrays are sent back, the server's "replace on length mismatch"
|
|
4429
|
+
* array behavior never triggers — array element edits, additions, removals,
|
|
4430
|
+
* and reorders all work correctly.
|
|
4431
|
+
*
|
|
4432
|
+
* Use this whenever:
|
|
4433
|
+
* - You're modifying anything inside an array
|
|
4434
|
+
* - You need the previous value to compute the new one
|
|
4435
|
+
* - You're making multiple field changes in one logical operation
|
|
4436
|
+
*
|
|
4437
|
+
* For simple top-level patches without needing the current value, prefer
|
|
4438
|
+
* {@link patchOutputContent}.
|
|
4439
|
+
*
|
|
4440
|
+
* @example Update one menu item's price
|
|
4441
|
+
* ```typescript
|
|
4442
|
+
* await tela.tasks.updateOutputContent<MenuOutput>(id, (current) => {
|
|
4443
|
+
* current.menu.items[2].price = 9.99
|
|
4444
|
+
* })
|
|
4445
|
+
* ```
|
|
4446
|
+
*
|
|
4447
|
+
* @example Add a new array item
|
|
4448
|
+
* ```typescript
|
|
4449
|
+
* await tela.tasks.updateOutputContent<TodoOutput>(id, (current) => {
|
|
4450
|
+
* current.todos.push({ text: 'new task', done: false })
|
|
4451
|
+
* })
|
|
4452
|
+
* ```
|
|
4453
|
+
*
|
|
4454
|
+
* @example Return a brand-new value
|
|
4455
|
+
* ```typescript
|
|
4456
|
+
* await tela.tasks.updateOutputContent(id, (current) => ({
|
|
4457
|
+
* ...current,
|
|
4458
|
+
* reviewed: true,
|
|
4459
|
+
* }))
|
|
4460
|
+
* ```
|
|
4461
|
+
*
|
|
4462
|
+
* @throws If the task has no output content yet (still running).
|
|
4463
|
+
*/
|
|
4464
|
+
async updateOutputContent(id, updater) {
|
|
4465
|
+
const task = await this.get(id);
|
|
4466
|
+
const current = extractTaskOutput(task);
|
|
4467
|
+
if (current === null || current === void 0) {
|
|
4468
|
+
throw new Error(`tasks.updateOutputContent: task ${id} has no output content yet`);
|
|
4469
|
+
}
|
|
4470
|
+
const draft = structuredClone(current);
|
|
4471
|
+
const result = updater(draft);
|
|
4472
|
+
const next = result === void 0 ? draft : result;
|
|
4473
|
+
return this.patchOutputContent(id, next);
|
|
4474
|
+
}
|
|
4475
|
+
/**
|
|
4476
|
+
* Replaces a task's tags. Convenience wrapper around {@link update}.
|
|
4477
|
+
*/
|
|
4478
|
+
async setTags(id, tags) {
|
|
4479
|
+
return this.update(id, { tags });
|
|
4480
|
+
}
|
|
4481
|
+
/**
|
|
4482
|
+
* Soft-deletes a task.
|
|
4483
|
+
*/
|
|
4484
|
+
async delete(id) {
|
|
4485
|
+
return this.client.delete(`/task/${id}`, NO_TRANSFORM);
|
|
4486
|
+
}
|
|
4487
|
+
/**
|
|
4488
|
+
* Bulk soft-deletes multiple tasks.
|
|
4489
|
+
*
|
|
4490
|
+
* @throws If `ids` is empty.
|
|
4491
|
+
*/
|
|
4492
|
+
async deleteBulk(ids) {
|
|
4493
|
+
if (ids.length === 0) {
|
|
4494
|
+
throw new Error("tasks.deleteBulk: ids array cannot be empty");
|
|
4495
|
+
}
|
|
4496
|
+
return this.client.delete("/task/bulk", {
|
|
4497
|
+
body: ids,
|
|
4498
|
+
...NO_TRANSFORM
|
|
4499
|
+
});
|
|
4500
|
+
}
|
|
4501
|
+
/**
|
|
4502
|
+
* Reverts approval on multiple tasks (sets them back to `validating`).
|
|
4503
|
+
* Only tasks currently in `completed` status are eligible.
|
|
4504
|
+
*
|
|
4505
|
+
* @throws If `ids` is empty.
|
|
4506
|
+
*/
|
|
4507
|
+
async undoApprovalBulk(ids) {
|
|
4508
|
+
if (ids.length === 0) {
|
|
4509
|
+
throw new Error("tasks.undoApprovalBulk: ids array cannot be empty");
|
|
4510
|
+
}
|
|
4511
|
+
return this.client.post("/task/bulk/undo-approval", {
|
|
4512
|
+
body: ids,
|
|
4513
|
+
...NO_TRANSFORM
|
|
4514
|
+
});
|
|
4515
|
+
}
|
|
4516
|
+
/**
|
|
4517
|
+
* Re-runs a task. Returns the new execution metadata.
|
|
4518
|
+
*
|
|
4519
|
+
* Note: the server only allows re-running tasks in `failed` status. Calling
|
|
4520
|
+
* this on a task in any other state will result in a 400 response.
|
|
4521
|
+
*/
|
|
4522
|
+
async rerun(id) {
|
|
4523
|
+
return this.client.post(`/task/${id}/rerun`, NO_TRANSFORM);
|
|
4524
|
+
}
|
|
4525
|
+
/**
|
|
4526
|
+
* Returns the input files attached to a task.
|
|
4527
|
+
*
|
|
4528
|
+
* Convenience helper around {@link get} that extracts and normalizes the
|
|
4529
|
+
* `inputContent.files[]` array.
|
|
4530
|
+
*/
|
|
4531
|
+
async getInputFiles(id) {
|
|
4532
|
+
const task = await this.get(id);
|
|
4533
|
+
return task.inputContent?.files ?? [];
|
|
4534
|
+
}
|
|
4535
|
+
/**
|
|
4536
|
+
* Returns the parsed output of a task regardless of whether it came from a
|
|
4537
|
+
* canvas execution or a workflow execution.
|
|
4538
|
+
*
|
|
4539
|
+
* Returns `null` if the task has no output yet.
|
|
4540
|
+
*/
|
|
4541
|
+
async getOutput(id) {
|
|
4542
|
+
const task = await this.get(id);
|
|
4543
|
+
return extractTaskOutput(task);
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
function buildNestedPayload(path, value) {
|
|
4547
|
+
const segments = path.split(".");
|
|
4548
|
+
let current = value;
|
|
4549
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
4550
|
+
const seg = segments[i];
|
|
4551
|
+
if (/^\d+$/.test(seg)) {
|
|
4552
|
+
const arr = [];
|
|
4553
|
+
arr[Number(seg)] = current;
|
|
4554
|
+
current = arr;
|
|
4555
|
+
} else {
|
|
4556
|
+
current = { [seg]: current };
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
return current;
|
|
4560
|
+
}
|
|
4561
|
+
function serializeTaskListQuery(query) {
|
|
4562
|
+
const out = {};
|
|
4563
|
+
for (const [key, value] of Object.entries(query)) {
|
|
4564
|
+
if (value === void 0)
|
|
4565
|
+
continue;
|
|
4566
|
+
if (key === "ids" || key === "status" || key === "approvedBy" || key === "createdBy") {
|
|
4567
|
+
out[key] = JSON.stringify(value);
|
|
4568
|
+
continue;
|
|
4569
|
+
}
|
|
4570
|
+
if (key === "orderBy") {
|
|
4571
|
+
out[key] = Array.isArray(value) ? JSON.stringify(value) : value;
|
|
4572
|
+
continue;
|
|
4573
|
+
}
|
|
4574
|
+
if (value instanceof Date) {
|
|
4575
|
+
out[key] = value.toISOString();
|
|
4576
|
+
continue;
|
|
4577
|
+
}
|
|
4578
|
+
out[key] = value;
|
|
4579
|
+
}
|
|
4580
|
+
return out;
|
|
4581
|
+
}
|
|
4582
|
+
|
|
4583
|
+
function toVaultId(ref) {
|
|
4584
|
+
if (ref.startsWith("vault://"))
|
|
4585
|
+
return ref.slice("vault://".length);
|
|
4586
|
+
if (/^https?:\/\//i.test(ref))
|
|
4587
|
+
return null;
|
|
4588
|
+
return ref;
|
|
4589
|
+
}
|
|
4590
|
+
class Vault {
|
|
4591
|
+
constructor(client) {
|
|
4592
|
+
this.client = client;
|
|
4593
|
+
}
|
|
4594
|
+
/**
|
|
4595
|
+
* Returns a temporary signed URL for a vault file.
|
|
4596
|
+
*
|
|
4597
|
+
* @param ref - A `vault://<id>` reference or a bare vault id.
|
|
4598
|
+
* @throws If `ref` is an `https://` URL (already resolved). Use {@link resolve} for that case.
|
|
4599
|
+
*/
|
|
4600
|
+
async getSignedUrl(ref) {
|
|
4601
|
+
const id = toVaultId(ref);
|
|
4602
|
+
if (id === null) {
|
|
4603
|
+
throw new Error(`vault.getSignedUrl: '${ref}' is already an http(s) URL; use vault.resolve() instead`);
|
|
4604
|
+
}
|
|
4605
|
+
const response = await this.client.get(`/_services/vault/files/${id}`);
|
|
4606
|
+
return response.url;
|
|
4607
|
+
}
|
|
4608
|
+
/**
|
|
4609
|
+
* Resolves any file reference to a downloadable URL.
|
|
4610
|
+
*
|
|
4611
|
+
* - `vault://<id>` and bare ids are resolved through the vault service.
|
|
4612
|
+
* - `https://` / `http://` URLs are returned as-is.
|
|
4613
|
+
*/
|
|
4614
|
+
async resolve(ref) {
|
|
4615
|
+
if (toVaultId(ref) === null)
|
|
4616
|
+
return ref;
|
|
4617
|
+
return this.getSignedUrl(ref);
|
|
4618
|
+
}
|
|
4619
|
+
/**
|
|
4620
|
+
* Downloads a vault file as a Blob.
|
|
4621
|
+
*
|
|
4622
|
+
* @param ref - A `vault://<id>` reference or a bare vault id.
|
|
4623
|
+
*/
|
|
4624
|
+
async download(ref) {
|
|
4625
|
+
const id = toVaultId(ref);
|
|
4626
|
+
if (id === null) {
|
|
4627
|
+
const res = await fetch(ref);
|
|
4628
|
+
if (!res.ok) {
|
|
4629
|
+
throw new Error(`vault.download: failed to fetch ${ref}: ${res.status} ${res.statusText}`);
|
|
4630
|
+
}
|
|
4631
|
+
return res.blob();
|
|
4632
|
+
}
|
|
4633
|
+
return downloadFile(`vault://${id}`, this.client);
|
|
4634
|
+
}
|
|
4635
|
+
/**
|
|
4636
|
+
* Streams a vault file as a `ReadableStream`.
|
|
4637
|
+
*
|
|
4638
|
+
* @param ref - A `vault://<id>` reference or a bare vault id.
|
|
4639
|
+
*/
|
|
4640
|
+
async stream(ref) {
|
|
4641
|
+
const id = toVaultId(ref);
|
|
4642
|
+
if (id === null) {
|
|
4643
|
+
const res = await fetch(ref);
|
|
4644
|
+
if (!res.ok || !res.body) {
|
|
4645
|
+
throw new Error(`vault.stream: failed to fetch ${ref}: ${res.status} ${res.statusText}`);
|
|
4646
|
+
}
|
|
4647
|
+
return res.body;
|
|
4648
|
+
}
|
|
4649
|
+
return streamFile(`vault://${id}`, this.client);
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
|
|
4259
4653
|
var __defProp = Object.defineProperty;
|
|
4260
4654
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4261
4655
|
var __publicField = (obj, key, value) => {
|
|
@@ -4318,6 +4712,30 @@ const _TelaSDK = class _TelaSDK extends BaseClient {
|
|
|
4318
4712
|
});
|
|
4319
4713
|
}
|
|
4320
4714
|
});
|
|
4715
|
+
/**
|
|
4716
|
+
* Tasks API resource for managing workstation tasks (fetch, list, update,
|
|
4717
|
+
* approve, rename, edit output, re-run, etc.).
|
|
4718
|
+
*
|
|
4719
|
+
* @example
|
|
4720
|
+
* ```typescript
|
|
4721
|
+
* const task = await tela.tasks.get('task-id')
|
|
4722
|
+
* await tela.tasks.approve('task-id')
|
|
4723
|
+
* await tela.tasks.rename('task-id', 'New name')
|
|
4724
|
+
* const files = await tela.tasks.getInputFiles('task-id')
|
|
4725
|
+
* ```
|
|
4726
|
+
*/
|
|
4727
|
+
__publicField(this, "tasks", new Tasks(this));
|
|
4728
|
+
/**
|
|
4729
|
+
* Vault API resource for resolving, downloading, and streaming files
|
|
4730
|
+
* stored in the Tela vault.
|
|
4731
|
+
*
|
|
4732
|
+
* @example
|
|
4733
|
+
* ```typescript
|
|
4734
|
+
* const url = await tela.vault.getSignedUrl('vault://abc-123')
|
|
4735
|
+
* const blob = await tela.vault.download('vault://abc-123')
|
|
4736
|
+
* ```
|
|
4737
|
+
*/
|
|
4738
|
+
__publicField(this, "vault", new Vault(this));
|
|
4321
4739
|
__publicField(this, "workstation", {
|
|
4322
4740
|
get: async (options) => {
|
|
4323
4741
|
return Workstation.get({
|
|
@@ -4437,13 +4855,17 @@ exports.MissingAuthError = MissingAuthError;
|
|
|
4437
4855
|
exports.NotFoundError = NotFoundError;
|
|
4438
4856
|
exports.RateLimitError = RateLimitError;
|
|
4439
4857
|
exports.TaskFailedError = TaskFailedError;
|
|
4858
|
+
exports.Tasks = Tasks;
|
|
4440
4859
|
exports.TelaError = TelaError;
|
|
4441
4860
|
exports.TelaFile = TelaFile;
|
|
4442
4861
|
exports.TelaFileSchema = TelaFileSchema;
|
|
4443
4862
|
exports.TelaSDK = TelaSDK;
|
|
4444
4863
|
exports.UnprocessableEntityError = UnprocessableEntityError;
|
|
4445
4864
|
exports.UserAbortError = UserAbortError;
|
|
4865
|
+
exports.Vault = Vault;
|
|
4446
4866
|
exports.createTelaClient = createTelaClient;
|
|
4867
|
+
exports.extractTaskOutput = extractTaskOutput;
|
|
4447
4868
|
exports.isTelaFile = isTelaFile;
|
|
4448
4869
|
exports.isTelaFileArray = isTelaFileArray;
|
|
4870
|
+
exports.normalizeTaskStatus = normalizeTaskStatus;
|
|
4449
4871
|
exports.toError = toError;
|