@meistrari/tela-sdk-js 1.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +976 -82
- package/dist/index.cjs +1352 -118
- package/dist/index.d.cts +1207 -422
- package/dist/index.d.mts +1207 -422
- package/dist/index.d.ts +1207 -422
- package/dist/index.mjs +1325 -119
- package/package.json +43 -32
package/README.md
CHANGED
|
@@ -7,13 +7,20 @@ The Tela SDK for JavaScript provides a simple and powerful way to interact with
|
|
|
7
7
|
- [Installation](#installation)
|
|
8
8
|
- [Usage](#usage)
|
|
9
9
|
- [Examples](#examples)
|
|
10
|
-
- [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
10
|
+
- [Canvas API](#canvas-api)
|
|
11
|
+
- [Synchronous Execution](#synchronous-execution)
|
|
12
|
+
- [Asynchronous Execution with Polling](#asynchronous-execution-with-polling)
|
|
13
|
+
- [Streaming Execution](#streaming-execution)
|
|
14
|
+
- [Event-Driven Execution](#event-driven-execution)
|
|
15
|
+
- [Schema Validation](#schema-validation)
|
|
16
|
+
- [Multiple Files](#multiple-files)
|
|
17
|
+
- [Webhook Notifications](#webhook-notifications)
|
|
18
|
+
- [Execution Tags](#execution-tags)
|
|
19
|
+
- [File Handling](#file-handling)
|
|
20
|
+
- [Migration Guide from v1.x to v2](#migration-guide-from-v1x-to-v2)
|
|
21
|
+
- [Breaking Changes](#breaking-changes)
|
|
22
|
+
- [Migration Checklist](#migration-checklist)
|
|
23
|
+
- [New Features in v2](#new-features-in-v2)
|
|
17
24
|
|
|
18
25
|
## Installation
|
|
19
26
|
|
|
@@ -30,130 +37,1017 @@ pnpm add @meistrari/tela-sdk-js
|
|
|
30
37
|
First, you need to import the SDK and initialize it with your API key:
|
|
31
38
|
|
|
32
39
|
```typescript
|
|
33
|
-
import {
|
|
40
|
+
import { TelaSDK } from '@meistrari/tela-sdk-js'
|
|
34
41
|
|
|
35
|
-
const tela =
|
|
42
|
+
const tela = new TelaSDK({ apiKey: 'your-api-key' })
|
|
36
43
|
```
|
|
37
44
|
|
|
38
45
|
## Examples
|
|
39
46
|
|
|
40
|
-
###
|
|
47
|
+
### Canvas API
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
The Canvas API provides a type-safe way to execute prompts with schema validation and multiple execution modes.
|
|
50
|
+
|
|
51
|
+
#### Synchronous Execution
|
|
52
|
+
|
|
53
|
+
Execute a canvas and wait for the complete result:
|
|
43
54
|
|
|
44
55
|
```typescript
|
|
45
|
-
import {
|
|
46
|
-
import type { TelaFile } from '@meistrari/tela-sdk-js'
|
|
56
|
+
import { TelaSDK } from '@meistrari/tela-sdk-js'
|
|
47
57
|
|
|
48
|
-
const tela =
|
|
49
|
-
apiKey:
|
|
58
|
+
const tela = new TelaSDK({
|
|
59
|
+
apiKey: 'your-api-key'
|
|
50
60
|
})
|
|
51
61
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
// Get canvas with input/output schemas
|
|
63
|
+
const canvas = await tela.canvas.get({
|
|
64
|
+
id: 'canvas-id',
|
|
65
|
+
input: schema => schema.object({
|
|
66
|
+
query: schema.string()
|
|
67
|
+
}),
|
|
68
|
+
output: schema => schema.object({
|
|
69
|
+
result: schema.string()
|
|
70
|
+
}),
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// Execute synchronously - direct result access
|
|
74
|
+
const result = await canvas.execute({ query: 'What is the capital of France?' }).result
|
|
75
|
+
|
|
76
|
+
console.log(result) // { result: "Paris" }
|
|
77
|
+
|
|
78
|
+
// Alternative: get execution object for more control
|
|
79
|
+
const execution = await canvas.execute({ query: 'What is the capital of France?' })
|
|
80
|
+
const result2 = await execution.result
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Asynchronous Execution with Polling
|
|
84
|
+
|
|
85
|
+
For long-running operations, use async mode with automatic polling:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const canvas = await tela.canvas.get({
|
|
89
|
+
id: 'canvas-id',
|
|
90
|
+
input: schema => schema.object({
|
|
91
|
+
document: schema.file(),
|
|
92
|
+
query: schema.string()
|
|
93
|
+
}),
|
|
94
|
+
output: schema => schema.object({
|
|
95
|
+
summary: schema.string()
|
|
96
|
+
}),
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// Execute asynchronously with polling - direct result access
|
|
100
|
+
const result = await canvas.execute(
|
|
101
|
+
{
|
|
102
|
+
document: TelaFile.create(documentBlob, { name: 'report.pdf' }),
|
|
103
|
+
query: 'Summarize this document'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
async: true,
|
|
107
|
+
pollingInterval: 1000, // Poll every 1 second
|
|
108
|
+
pollingTimeout: 60000, // Timeout after 60 seconds
|
|
109
|
+
}
|
|
110
|
+
).result
|
|
111
|
+
|
|
112
|
+
console.log(result.summary)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Streaming Execution
|
|
116
|
+
|
|
117
|
+
Stream results as they're generated:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const canvas = await tela.canvas.get({
|
|
121
|
+
id: 'canvas-id',
|
|
122
|
+
input: schema => schema.object({
|
|
123
|
+
prompt: schema.string()
|
|
124
|
+
}),
|
|
125
|
+
output: schema => schema.object({
|
|
126
|
+
response: schema.string()
|
|
127
|
+
}),
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Execute with streaming - direct iteration
|
|
131
|
+
for await (const chunk of canvas.execute(
|
|
132
|
+
{ prompt: 'Write a story about a robot' },
|
|
133
|
+
{ stream: true }
|
|
134
|
+
).result) {
|
|
135
|
+
process.stdout.write(chunk.response || '')
|
|
61
136
|
}
|
|
62
|
-
run().catch(console.error)
|
|
63
137
|
```
|
|
64
138
|
|
|
65
|
-
|
|
139
|
+
#### Event-Driven Execution
|
|
66
140
|
|
|
67
|
-
|
|
141
|
+
Monitor execution lifecycle with events. **Events are only useful with async executions** - synchronous and streaming executions complete too quickly for event-driven monitoring to be practical.
|
|
68
142
|
|
|
69
143
|
```typescript
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
144
|
+
const canvas = await tela.canvas.get({
|
|
145
|
+
id: 'canvas-id',
|
|
146
|
+
input: schema => schema.object({
|
|
147
|
+
query: schema.string()
|
|
148
|
+
}),
|
|
149
|
+
output: schema => schema.object({
|
|
150
|
+
result: schema.string()
|
|
151
|
+
}),
|
|
73
152
|
})
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
153
|
+
|
|
154
|
+
// Start async execution to attach event listeners
|
|
155
|
+
const execution = await canvas.execute(
|
|
156
|
+
{ query: 'What is the capital of France?' },
|
|
157
|
+
{
|
|
158
|
+
async: true,
|
|
159
|
+
pollingInterval: 1000,
|
|
160
|
+
pollingTimeout: 60000,
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
// Access current status at any time
|
|
165
|
+
console.log(execution.status) // 'created'
|
|
166
|
+
|
|
167
|
+
// Listen for status changes
|
|
168
|
+
execution.on('statusChange', (status) => {
|
|
169
|
+
console.log(`Status: ${status}`) // created → running → succeeded
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// Listen for polling updates
|
|
173
|
+
execution.on('poll', (pollResult) => {
|
|
174
|
+
console.log(`Poll - Status: ${pollResult.status}`)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
// Listen for successful completion
|
|
178
|
+
execution.on('success', (result) => {
|
|
179
|
+
console.log('Success!', result)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// Listen for errors (prevents throwing)
|
|
183
|
+
execution.on('error', (error) => {
|
|
184
|
+
console.error('Failed:', error.message)
|
|
185
|
+
// With error listener: error event is emitted, promise resolves to undefined
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// Start event-driven polling (non-blocking)
|
|
189
|
+
execution.poll()
|
|
190
|
+
|
|
191
|
+
// Events will fire as polling progresses
|
|
192
|
+
// The result will be available in the success event callback
|
|
193
|
+
// Continue with other work while polling happens in the background...
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Why Async Only?**
|
|
197
|
+
|
|
198
|
+
Events are designed for tracking progress over time. Synchronous executions complete immediately (blocking until done), so by the time you can access the execution object, all events have already fired. Streaming executions provide their own iteration mechanism via async generators, making events redundant.
|
|
199
|
+
|
|
200
|
+
**Status Property:**
|
|
201
|
+
|
|
202
|
+
The `status` property provides the current execution state:
|
|
203
|
+
- **Async**: `created` → `running` → `succeeded` or `failed`
|
|
204
|
+
|
|
205
|
+
Status is set to `succeeded` only after successful validation. If validation fails, status will be `failed` even if the API request succeeded.
|
|
206
|
+
|
|
207
|
+
**Available Events (Async Executions Only):**
|
|
208
|
+
- `success` - Emitted when execution completes successfully (after validation)
|
|
209
|
+
- `error` - Emitted on failure (if listeners exist, errors won't throw)
|
|
210
|
+
- `statusChange` - Emitted on status transitions
|
|
211
|
+
- `poll` - Emitted during polling (initial response + each poll)
|
|
212
|
+
|
|
213
|
+
**Error Handling:**
|
|
214
|
+
- **With error listener**: Errors emitted as events, promise resolves to `undefined`
|
|
215
|
+
- **Without error listener**: Errors throw and reject the promise
|
|
216
|
+
|
|
217
|
+
**Important:** You must call `execution.poll()` or `await execution.result` to start polling - events won't fire until polling begins.
|
|
218
|
+
|
|
219
|
+
See [Event Examples](./examples/events/) for detailed usage patterns.
|
|
220
|
+
|
|
221
|
+
#### Schema Validation
|
|
222
|
+
|
|
223
|
+
The Canvas API validates your inputs and outputs against the server schema:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const canvas = await tela.canvas.get({
|
|
227
|
+
id: 'canvas-id',
|
|
228
|
+
input: schema => schema.object({
|
|
229
|
+
text: schema.string(),
|
|
230
|
+
file: schema.file(), // TelaFile validator
|
|
231
|
+
settings: schema.object({
|
|
232
|
+
temperature: schema.number(),
|
|
233
|
+
maxTokens: schema.number(),
|
|
234
|
+
}),
|
|
235
|
+
}),
|
|
236
|
+
output: schema => schema.object({
|
|
237
|
+
analysis: schema.string(),
|
|
238
|
+
confidence: schema.number(),
|
|
239
|
+
}),
|
|
240
|
+
skipSchemaValidation: false, // Enable schema validation warnings during canvas retrieval (default)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
// TypeScript will ensure you provide the correct types
|
|
244
|
+
const result = await canvas.execute({
|
|
245
|
+
text: 'Analyze this document',
|
|
246
|
+
file: TelaFile.create(blob, { name: 'data.pdf' }),
|
|
247
|
+
settings: {
|
|
248
|
+
temperature: 0.7,
|
|
249
|
+
maxTokens: 1000,
|
|
250
|
+
}
|
|
251
|
+
}).result
|
|
252
|
+
|
|
253
|
+
// Skip result validation to trust API response without Zod validation
|
|
254
|
+
const resultWithoutValidation = await canvas.execute(
|
|
255
|
+
{
|
|
256
|
+
text: 'Analyze this document',
|
|
257
|
+
file: TelaFile.create(blob, { name: 'data.pdf' }),
|
|
258
|
+
settings: {
|
|
259
|
+
temperature: 0.7,
|
|
260
|
+
maxTokens: 1000,
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
skipResultValidation: true // Skip Zod validation on results, just typecast
|
|
265
|
+
}
|
|
266
|
+
).result
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Multiple Files
|
|
270
|
+
|
|
271
|
+
Process multiple files in a single canvas execution:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
const canvas = await tela.canvas.get({
|
|
275
|
+
id: 'canvas-id',
|
|
276
|
+
input: schema => schema.object({
|
|
277
|
+
documents: schema.array(schema.file()),
|
|
278
|
+
instructions: schema.string()
|
|
279
|
+
}),
|
|
280
|
+
output: schema => schema.object({
|
|
281
|
+
comparison: schema.string()
|
|
282
|
+
}),
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
const result = await canvas.execute({
|
|
286
|
+
documents: [
|
|
287
|
+
TelaFile.create('https://example.com/doc1.pdf', { range: [0, 5] }),
|
|
288
|
+
TelaFile.create('https://example.com/doc2.pdf', { range: [0, 5] }),
|
|
289
|
+
TelaFile.create(localFileBlob, { name: 'doc3.pdf' })
|
|
290
|
+
],
|
|
291
|
+
instructions: 'Compare these documents and identify key differences'
|
|
292
|
+
}).result
|
|
293
|
+
|
|
294
|
+
console.log(result.comparison)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### Webhook Notifications
|
|
298
|
+
|
|
299
|
+
Receive completion notifications via webhook for async executions:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
const canvas = await tela.canvas.get({
|
|
303
|
+
id: 'canvas-id',
|
|
304
|
+
input: schema => schema.object({
|
|
305
|
+
document: schema.file(),
|
|
306
|
+
query: schema.string()
|
|
307
|
+
}),
|
|
308
|
+
output: schema => schema.object({
|
|
309
|
+
analysis: schema.string()
|
|
310
|
+
}),
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
// Execute with webhook notification - you can still poll if needed
|
|
314
|
+
const result = await canvas.execute(
|
|
315
|
+
{
|
|
316
|
+
document: TelaFile.create('https://example.com/large-report.pdf'),
|
|
317
|
+
query: 'Analyze this report'
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
async: true,
|
|
321
|
+
webhookUrl: 'https://your-server.com/webhook',
|
|
322
|
+
pollingTimeout: 300000, // 5 minutes
|
|
323
|
+
}
|
|
324
|
+
).result
|
|
325
|
+
// OR wait for the webhook notification on your server instead of polling
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### Execution Tags
|
|
329
|
+
|
|
330
|
+
Add tags to your canvas executions for filtering, categorization, and analytics:
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
const canvas = await tela.canvas.get({
|
|
334
|
+
id: 'canvas-id',
|
|
335
|
+
input: schema => schema.object({
|
|
336
|
+
query: schema.string()
|
|
337
|
+
}),
|
|
338
|
+
output: schema => schema.object({
|
|
339
|
+
result: schema.string()
|
|
340
|
+
}),
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
// Execute with tags (works with all execution modes)
|
|
344
|
+
const result = await canvas.execute(
|
|
345
|
+
{ query: 'Analyze customer feedback' },
|
|
346
|
+
{
|
|
347
|
+
tags: ['production', 'analytics', 'customer-feedback']
|
|
348
|
+
}
|
|
349
|
+
).result
|
|
350
|
+
|
|
351
|
+
// Tags work with async executions
|
|
352
|
+
const asyncResult = await canvas.execute(
|
|
353
|
+
{ query: 'Process large dataset' },
|
|
354
|
+
{
|
|
355
|
+
async: true,
|
|
356
|
+
tags: ['batch-processing', 'analytics']
|
|
357
|
+
}
|
|
358
|
+
).result
|
|
359
|
+
|
|
360
|
+
// Tags work with streaming executions
|
|
361
|
+
for await (const chunk of canvas.execute(
|
|
362
|
+
{ query: 'Generate report' },
|
|
363
|
+
{
|
|
364
|
+
stream: true,
|
|
365
|
+
tags: ['streaming', 'reports']
|
|
366
|
+
}
|
|
367
|
+
).result) {
|
|
368
|
+
process.stdout.write(chunk.result || '')
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**Use Cases:**
|
|
373
|
+
- **Environment tracking**: Tag executions by environment (`production`, `staging`, `development`)
|
|
374
|
+
- **Feature categorization**: Organize executions by feature (`analytics`, `reporting`, `summarization`)
|
|
375
|
+
- **User segmentation**: Track executions by user tier or department
|
|
376
|
+
- **Cost allocation**: Attribute API usage to specific projects or teams
|
|
377
|
+
- **Performance monitoring**: Filter and analyze execution metrics by tag
|
|
378
|
+
|
|
379
|
+
Tags are sent to the Tela API and can be used for filtering and analytics in your Tela dashboard.
|
|
380
|
+
|
|
381
|
+
#### Fetching Existing Executions
|
|
382
|
+
|
|
383
|
+
Retrieve and monitor async executions by their ID, useful for job queues, resuming workflows, or multi-user dashboards:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
// Start an async execution
|
|
387
|
+
const execution = await canvas.execute(
|
|
388
|
+
{ query: 'Process this data' },
|
|
389
|
+
{ async: true }
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
// Store the execution ID (e.g., in a database)
|
|
393
|
+
const executionId = execution.id
|
|
394
|
+
|
|
395
|
+
// Later, fetch the execution by ID
|
|
396
|
+
const fetchedExecution = await canvas.getExecution(executionId, {
|
|
397
|
+
pollingInterval: 2000, // Optional: custom polling interval
|
|
398
|
+
pollingTimeout: 120000 // Optional: custom timeout
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
console.log(fetchedExecution.status) // 'running', 'succeeded', or 'failed'
|
|
402
|
+
|
|
403
|
+
// Use event-driven polling for non-blocking progress tracking
|
|
404
|
+
// Note: poll() works for ANY async execution, not just fetched ones!
|
|
405
|
+
fetchedExecution.on('statusChange', (status) => {
|
|
406
|
+
console.log(`Status: ${status}`)
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
fetchedExecution.on('success', (result) => {
|
|
410
|
+
console.log('Completed!', result)
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
fetchedExecution.on('error', (error) => {
|
|
414
|
+
console.error('Failed:', error)
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
// Start polling without blocking (returns immediately)
|
|
418
|
+
fetchedExecution.poll()
|
|
419
|
+
|
|
420
|
+
// Continue with other work while polling runs in background...
|
|
421
|
+
console.log('Polling in background, doing other work...')
|
|
422
|
+
|
|
423
|
+
// Later, you can still await the result if needed
|
|
424
|
+
const result = await fetchedExecution.result
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Alternative: Use `poll()` on newly started executions**
|
|
428
|
+
|
|
429
|
+
You can also use event-driven polling immediately when starting an execution:
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
const execution = await canvas.execute(
|
|
433
|
+
{ query: 'Process this data' },
|
|
434
|
+
{ async: true }
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
// Set up event listeners
|
|
438
|
+
execution.on('statusChange', status => console.log('Status:', status))
|
|
439
|
+
execution.on('success', result => console.log('Done!', result))
|
|
440
|
+
execution.on('error', error => console.error('Failed:', error))
|
|
441
|
+
|
|
442
|
+
// Start non-blocking polling
|
|
443
|
+
execution.poll()
|
|
444
|
+
|
|
445
|
+
// Do other work...
|
|
446
|
+
console.log('Execution polling in background')
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Key Features:**
|
|
450
|
+
|
|
451
|
+
- **`canvas.getExecution(id, options?)`** - Fetch execution by UUID
|
|
452
|
+
- Only async executions have UUIDs and can be fetched
|
|
453
|
+
- Returns execution in current state (running, succeeded, or failed)
|
|
454
|
+
- Supports custom polling options
|
|
455
|
+
|
|
456
|
+
- **`execution.poll()`** - Start event-driven polling
|
|
457
|
+
- Returns `void` (non-blocking)
|
|
458
|
+
- Emits events: `statusChange`, `poll`, `success`, `error`
|
|
459
|
+
- Perfect for UI updates, dashboards, and concurrent monitoring
|
|
460
|
+
|
|
461
|
+
**Important Notes:**
|
|
462
|
+
|
|
463
|
+
⚠️ **Events require polling or awaiting `.result`**: Events are only emitted when polling is active. You must either:
|
|
464
|
+
- Call `execution.poll()` to start event-driven polling, OR
|
|
465
|
+
- Await `execution.result` which starts polling automatically
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
// ❌ Events won't fire - no polling started
|
|
469
|
+
const execution = await canvas.execute({ query: 'test' }, { async: true })
|
|
470
|
+
execution.on('success', result => console.log('Done')) // This will never fire!
|
|
471
|
+
|
|
472
|
+
// ✅ Correct - poll() starts event-driven polling
|
|
473
|
+
const execution = await canvas.execute({ query: 'test' }, { async: true })
|
|
474
|
+
execution.on('success', result => console.log('Done'))
|
|
475
|
+
execution.poll() // Now events will fire
|
|
476
|
+
|
|
477
|
+
// ✅ Also correct - awaiting result starts polling
|
|
478
|
+
const execution = await canvas.execute({ query: 'test' }, { async: true })
|
|
479
|
+
execution.on('success', result => console.log('Done'))
|
|
480
|
+
await execution.result // Polling starts, events fire
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
⚠️ **Already completed executions don't emit events**: If you fetch an execution that has already finished (succeeded or failed), the `success` and `error` events won't fire because there's no polling needed. Instead, check the status and access the result directly:
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
const execution = await canvas.getExecution(executionId)
|
|
487
|
+
|
|
488
|
+
if (execution.status === 'succeeded') {
|
|
489
|
+
// Access result directly - success event won't fire
|
|
490
|
+
const result = await execution.result
|
|
491
|
+
console.log('Already completed:', result)
|
|
492
|
+
}
|
|
493
|
+
else if (execution.status === 'failed') {
|
|
494
|
+
// Handle failure - error event won't fire
|
|
495
|
+
try {
|
|
496
|
+
await execution.result
|
|
497
|
+
}
|
|
498
|
+
catch (error) {
|
|
499
|
+
console.error('Already failed:', error)
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
// Still running - events will fire when you start polling
|
|
504
|
+
execution.on('success', result => console.log('Completed!', result))
|
|
505
|
+
execution.on('error', error => console.error('Failed:', error))
|
|
506
|
+
execution.poll()
|
|
80
507
|
}
|
|
81
|
-
run().catch(console.error)
|
|
82
508
|
```
|
|
83
509
|
|
|
84
|
-
|
|
510
|
+
**Use Cases:**
|
|
511
|
+
- Job queue management systems
|
|
512
|
+
- Resuming monitoring after page refresh or server restart
|
|
513
|
+
- Multi-user dashboards showing execution status
|
|
514
|
+
- Background processing with real-time updates
|
|
515
|
+
- Retry mechanisms with persistent execution IDs
|
|
516
|
+
|
|
517
|
+
See [Fetch and Poll Examples](./examples/events/) for detailed usage patterns.
|
|
518
|
+
|
|
519
|
+
### File Handling
|
|
85
520
|
|
|
86
|
-
|
|
521
|
+
The `TelaFile` API provides flexible file handling with support for various input types:
|
|
87
522
|
|
|
88
523
|
```typescript
|
|
89
|
-
import {
|
|
524
|
+
import { TelaFile } from '@meistrari/tela-sdk-js'
|
|
525
|
+
|
|
526
|
+
// From a Blob or File
|
|
527
|
+
const fileFromBlob = TelaFile.create(blob, { name: 'custom.pdf' })
|
|
528
|
+
|
|
529
|
+
// From a URL
|
|
530
|
+
const fileFromUrl = TelaFile.create('https://example.com/document.pdf')
|
|
90
531
|
|
|
91
|
-
|
|
92
|
-
|
|
532
|
+
// From bytes with explicit MIME type
|
|
533
|
+
const fileFromBytes = TelaFile.create(
|
|
534
|
+
new Uint8Array(['...']),
|
|
535
|
+
{
|
|
536
|
+
mimeType: 'application/pdf',
|
|
537
|
+
name: 'document.pdf'
|
|
538
|
+
}
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
// From a ReadableStream with explicit MIME type
|
|
542
|
+
const fileFromStream = TelaFile.create(
|
|
543
|
+
readableStream,
|
|
544
|
+
{
|
|
545
|
+
mimeType: 'image/jpeg',
|
|
546
|
+
name: 'photo.jpg'
|
|
547
|
+
}
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
// Vault reference (for files already uploaded)
|
|
551
|
+
const vaultFile = TelaFile.create('vault://file-id')
|
|
552
|
+
|
|
553
|
+
// With page range for PDFs
|
|
554
|
+
const fileWithRange = TelaFile.create(
|
|
555
|
+
'https://example.com/document.pdf',
|
|
556
|
+
{
|
|
557
|
+
range: [0, 5], // Pages 0-5
|
|
558
|
+
parserType: 'pdf'
|
|
559
|
+
}
|
|
560
|
+
)
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
## Migration Guide from v1.x to v2
|
|
564
|
+
|
|
565
|
+
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.
|
|
566
|
+
|
|
567
|
+
### Breaking Changes
|
|
568
|
+
|
|
569
|
+
#### 1. API Surface Changed: `completions.create()` → `canvas.get()` + `execute()`
|
|
570
|
+
|
|
571
|
+
The v1 API used a single `completions.create()` method. V2 introduces a two-step pattern: first retrieve a canvas, then execute it.
|
|
572
|
+
|
|
573
|
+
**v1.x:**
|
|
574
|
+
```typescript
|
|
575
|
+
const tela = new TelaSDK({ apiKey: 'your-api-key' })
|
|
576
|
+
|
|
577
|
+
const completion = await tela.completions.create({
|
|
578
|
+
canvasId: 'canvas-id',
|
|
579
|
+
variables: {
|
|
580
|
+
query: 'What is the capital of France?'
|
|
581
|
+
}
|
|
93
582
|
})
|
|
94
583
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
584
|
+
console.log(completion.choices[0].message.content)
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**v2:**
|
|
588
|
+
```typescript
|
|
589
|
+
const tela = new TelaSDK({ apiKey: 'your-api-key' })
|
|
590
|
+
|
|
591
|
+
// First, get the canvas
|
|
592
|
+
const canvas = await tela.canvas.get({
|
|
593
|
+
id: 'canvas-id'
|
|
594
|
+
})
|
|
595
|
+
|
|
596
|
+
// Then execute it
|
|
597
|
+
const result = await canvas.execute({
|
|
598
|
+
query: 'What is the capital of France?'
|
|
599
|
+
}).result
|
|
600
|
+
|
|
601
|
+
console.log(result)
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
#### 2. Schema Validation and Type Safety (Optional)
|
|
605
|
+
|
|
606
|
+
V2 introduces **optional** runtime and compile-time type safety with Zod schema validation. Schemas validate data at runtime (catching invalid data) and provide TypeScript types at compile-time. You can use the SDK without schemas if you prefer.
|
|
607
|
+
|
|
608
|
+
**v1.x (no schema validation):**
|
|
609
|
+
```typescript
|
|
610
|
+
const completion = await tela.completions.create<
|
|
611
|
+
{ query: string },
|
|
612
|
+
{ result: string }
|
|
613
|
+
>({
|
|
614
|
+
canvasId: 'canvas-id',
|
|
615
|
+
variables: {
|
|
616
|
+
query: 'Hello'
|
|
617
|
+
}
|
|
618
|
+
})
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**v2 (without schemas - works just like v1.x):**
|
|
622
|
+
```typescript
|
|
623
|
+
const canvas = await tela.canvas.get({
|
|
624
|
+
id: 'canvas-id'
|
|
625
|
+
})
|
|
626
|
+
|
|
627
|
+
const result = await canvas.execute({ query: 'Hello' }).result
|
|
628
|
+
// result is typed as unknown, no runtime validation
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**v2 (with optional schema validation for runtime + compile-time safety):**
|
|
632
|
+
```typescript
|
|
633
|
+
const canvas = await tela.canvas.get({
|
|
634
|
+
id: 'canvas-id',
|
|
635
|
+
input: schema => schema.object({
|
|
636
|
+
query: schema.string()
|
|
637
|
+
}),
|
|
638
|
+
output: schema => schema.object({
|
|
639
|
+
result: schema.string()
|
|
640
|
+
})
|
|
641
|
+
})
|
|
642
|
+
|
|
643
|
+
// Runtime validation ensures data matches schema
|
|
644
|
+
// TypeScript knows the exact types at compile-time
|
|
645
|
+
const result = await canvas.execute({ query: 'Hello' }).result
|
|
646
|
+
// result.result is a string (validated and typed)
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
#### 3. File Handling Changes
|
|
650
|
+
|
|
651
|
+
The `TelaFile` constructor now requires `mimeType` for `Uint8Array` and `ReadableStream` inputs (for compatibility with storage solutions).
|
|
652
|
+
|
|
653
|
+
**v1.x:**
|
|
654
|
+
```typescript
|
|
655
|
+
import { TelaFile } from '@meistrari/tela-sdk-js'
|
|
656
|
+
|
|
657
|
+
const file = new TelaFile(blob, { range: [0, 5] })
|
|
658
|
+
const fileFromBytes = new TelaFile(new Uint8Array([/* ... */])) // mimeType optional
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**v2:**
|
|
662
|
+
```typescript
|
|
663
|
+
import { TelaFile } from '@meistrari/tela-sdk-js'
|
|
664
|
+
|
|
665
|
+
// No change needed for Blob, File, or URL strings
|
|
666
|
+
const file = new TelaFile(blob, { range: [0, 5] })
|
|
667
|
+
|
|
668
|
+
// For Uint8Array or ReadableStream, mimeType is now required:
|
|
669
|
+
const fileFromBytes = new TelaFile(
|
|
670
|
+
new Uint8Array([/* ... */]),
|
|
671
|
+
{
|
|
672
|
+
mimeType: 'application/pdf',
|
|
673
|
+
name: 'document.pdf'
|
|
674
|
+
}
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
// Alternative: use tela.createFile() helper
|
|
678
|
+
const fileFromStream = tela.createFile(readableStream, { mimeType: 'image/jpeg' })
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
#### 4. Streaming API Changes
|
|
682
|
+
|
|
683
|
+
Streaming now returns an async generator directly via the `.result` property.
|
|
684
|
+
|
|
685
|
+
**v1.x:**
|
|
686
|
+
```typescript
|
|
687
|
+
const stream = await tela.completions.create({
|
|
688
|
+
canvasId: 'canvas-id',
|
|
689
|
+
stream: true,
|
|
690
|
+
variables: { query: 'Tell me a story' }
|
|
691
|
+
})
|
|
692
|
+
|
|
693
|
+
for await (const chunk of stream) {
|
|
694
|
+
process.stdout.write(chunk.message.content || '')
|
|
695
|
+
}
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
**v2:**
|
|
699
|
+
```typescript
|
|
700
|
+
const canvas = await tela.canvas.get({
|
|
701
|
+
id: 'canvas-id',
|
|
702
|
+
input: schema => schema.object({
|
|
703
|
+
query: schema.string()
|
|
704
|
+
}),
|
|
705
|
+
output: schema => schema.object({
|
|
706
|
+
response: schema.string()
|
|
103
707
|
})
|
|
104
|
-
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
const execution = canvas.execute(
|
|
711
|
+
{ query: 'Tell me a story' },
|
|
712
|
+
{ stream: true }
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
for await (const chunk of execution.result) {
|
|
716
|
+
process.stdout.write(chunk.response || '')
|
|
105
717
|
}
|
|
106
|
-
run().catch(console.error)
|
|
107
718
|
```
|
|
108
719
|
|
|
109
|
-
|
|
720
|
+
#### 5. Async Execution with Polling
|
|
110
721
|
|
|
111
|
-
|
|
722
|
+
V2 introduces async execution with automatic polling. V1.x only supported synchronous execution (the request would block until completion).
|
|
112
723
|
|
|
724
|
+
**v1.x:**
|
|
113
725
|
```typescript
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
726
|
+
// Synchronous only - blocks until the execution completes
|
|
727
|
+
const response = await tela.completions.create({
|
|
728
|
+
canvasId: 'canvas-id',
|
|
729
|
+
variables: { query: 'Analyze this' }
|
|
730
|
+
})
|
|
731
|
+
// This could take a very long time for long-running executions
|
|
732
|
+
console.log(response.choices[0].message.content)
|
|
733
|
+
```
|
|
117
734
|
|
|
118
|
-
|
|
119
|
-
|
|
735
|
+
**v2:**
|
|
736
|
+
```typescript
|
|
737
|
+
const canvas = await tela.canvas.get({
|
|
738
|
+
id: 'canvas-id',
|
|
739
|
+
input: schema => schema.object({ query: schema.string() }),
|
|
740
|
+
output: schema => schema.object({ result: schema.string() })
|
|
120
741
|
})
|
|
121
742
|
|
|
122
|
-
|
|
123
|
-
const
|
|
743
|
+
// Automatic polling
|
|
744
|
+
const execution = canvas.execute(
|
|
745
|
+
{ query: 'Analyze this' },
|
|
746
|
+
{
|
|
747
|
+
async: true,
|
|
748
|
+
pollingInterval: 1000, // Poll every 1 second
|
|
749
|
+
pollingTimeout: 60000, // Timeout after 60 seconds
|
|
750
|
+
webhookUrl: 'https://your-server.com/webhook' // Optional
|
|
751
|
+
}
|
|
752
|
+
)
|
|
124
753
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
754
|
+
const result = await execution.result
|
|
755
|
+
console.log(result.result)
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### 6. Response Structure Changes
|
|
759
|
+
|
|
760
|
+
The response structure has been simplified.
|
|
761
|
+
|
|
762
|
+
**v1.x:**
|
|
763
|
+
```typescript
|
|
764
|
+
const completion = await tela.completions.create({
|
|
765
|
+
canvasId: 'canvas-id',
|
|
766
|
+
variables: { query: 'Hello' }
|
|
767
|
+
})
|
|
768
|
+
|
|
769
|
+
// Access via nested structure
|
|
770
|
+
console.log(completion.choices[0].message.content)
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
**v2:**
|
|
774
|
+
```typescript
|
|
775
|
+
const canvas = await tela.canvas.get({
|
|
776
|
+
id: 'canvas-id',
|
|
777
|
+
output: schema => schema.object({
|
|
778
|
+
answer: schema.string()
|
|
132
779
|
})
|
|
133
|
-
|
|
134
|
-
|
|
780
|
+
})
|
|
781
|
+
|
|
782
|
+
const response = await canvas.execute({ query: 'Hello' }).result
|
|
783
|
+
// Direct access to structured output
|
|
784
|
+
console.log(response.answer)
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Migration Checklist
|
|
788
|
+
|
|
789
|
+
- [ ] Replace `tela.completions.create()` with `tela.canvas.get()` + `canvas.execute()`
|
|
790
|
+
- [ ] (Optional) Add input/output schemas using the `schema` builder function for type safety
|
|
791
|
+
- [ ] Add `mimeType` parameter when creating `TelaFile` from `Uint8Array` or `ReadableStream`
|
|
792
|
+
- [ ] Update streaming code to use `.result` property for iteration
|
|
793
|
+
- [ ] Update async execution to use polling parameters instead of manual polling
|
|
794
|
+
- [ ] Update response access patterns to match new structure
|
|
795
|
+
- [ ] (If using schemas) Test schema validation warnings to ensure schemas match server configuration
|
|
796
|
+
|
|
797
|
+
### New Features in v2
|
|
798
|
+
|
|
799
|
+
#### Event-Driven Execution Monitoring
|
|
800
|
+
|
|
801
|
+
V2 introduces a comprehensive event system for monitoring execution lifecycle across all execution modes (sync, async, streaming):
|
|
802
|
+
|
|
803
|
+
```typescript
|
|
804
|
+
const execution = await canvas.execute(
|
|
805
|
+
{ query: 'Analyze this' },
|
|
806
|
+
{ async: true }
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
// Monitor progress with events
|
|
810
|
+
execution.on('statusChange', (status) => {
|
|
811
|
+
console.log(`Status: ${status}`)
|
|
812
|
+
})
|
|
813
|
+
|
|
814
|
+
execution.on('poll', (pollResult) => {
|
|
815
|
+
console.log(`Polling - ${pollResult.status}`)
|
|
816
|
+
})
|
|
817
|
+
|
|
818
|
+
execution.on('success', (result) => {
|
|
819
|
+
console.log('Completed!', result)
|
|
820
|
+
})
|
|
821
|
+
|
|
822
|
+
// Graceful error handling
|
|
823
|
+
execution.on('error', (error) => {
|
|
824
|
+
console.error('Failed:', error.message)
|
|
825
|
+
// With listener: no throw, promise resolves to undefined
|
|
826
|
+
})
|
|
827
|
+
|
|
828
|
+
const result = await execution.result
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Available Events:**
|
|
832
|
+
- `success` - Completion with validated result
|
|
833
|
+
- `error` - Failure notification (prevents throwing if listener exists)
|
|
834
|
+
- `statusChange` - Status transitions
|
|
835
|
+
- `poll` - Polling updates (async only)
|
|
836
|
+
|
|
837
|
+
See [Event Examples](./examples/events/) for comprehensive patterns and use cases.
|
|
838
|
+
|
|
839
|
+
#### Promise-like Execution API
|
|
840
|
+
|
|
841
|
+
V2 introduces a flexible execution API that supports both direct result access and execution object retrieval:
|
|
842
|
+
|
|
843
|
+
```typescript
|
|
844
|
+
// Direct result access (recommended for simple cases)
|
|
845
|
+
const result = await canvas.execute({ query: 'Hello' }).result
|
|
846
|
+
|
|
847
|
+
// Get execution object for more control
|
|
848
|
+
const execution = await canvas.execute({ query: 'Hello' })
|
|
849
|
+
const result2 = await execution.result
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
#### Schema Validation Warnings
|
|
853
|
+
|
|
854
|
+
V2 validates your schemas against the server configuration and warns you about mismatches:
|
|
855
|
+
|
|
856
|
+
```typescript
|
|
857
|
+
const canvas = await tela.canvas.get({
|
|
858
|
+
id: 'canvas-id',
|
|
859
|
+
input: schema => schema.object({
|
|
860
|
+
wrongField: schema.string() // Will warn if not in server schema
|
|
861
|
+
}),
|
|
862
|
+
skipSchemaValidation: false // Enable warnings (default)
|
|
863
|
+
})
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
#### Vault File References
|
|
867
|
+
|
|
868
|
+
V2 supports vault file references:
|
|
869
|
+
|
|
870
|
+
```typescript
|
|
871
|
+
const vaultFile = new TelaFile('vault://file-id')
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
#### Skip Result Validation
|
|
875
|
+
|
|
876
|
+
When you have schemas defined, you can skip runtime validation for better performance (you'll still get TypeScript types):
|
|
877
|
+
|
|
878
|
+
```typescript
|
|
879
|
+
const canvas = await tela.canvas.get({
|
|
880
|
+
id: 'canvas-id',
|
|
881
|
+
input: schema => schema.object({
|
|
882
|
+
query: schema.string()
|
|
883
|
+
}),
|
|
884
|
+
output: schema => schema.object({
|
|
885
|
+
answer: schema.string()
|
|
886
|
+
})
|
|
887
|
+
})
|
|
888
|
+
|
|
889
|
+
const execution = canvas.execute(
|
|
890
|
+
{ query: 'Hello' },
|
|
891
|
+
{ skipResultValidation: true } // Skip runtime validation, trust API response
|
|
892
|
+
)
|
|
893
|
+
|
|
894
|
+
// Still typed as { answer: string }, but no validation at runtime
|
|
895
|
+
const result = await execution.result
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
#### Access Raw API Responses
|
|
899
|
+
|
|
900
|
+
V2 provides access to the raw, unprocessed API response alongside the parsed result:
|
|
901
|
+
|
|
902
|
+
```typescript
|
|
903
|
+
const canvas = await tela.canvas.get({
|
|
904
|
+
id: 'canvas-id',
|
|
905
|
+
output: schema => schema.object({
|
|
906
|
+
answer: schema.string()
|
|
907
|
+
})
|
|
908
|
+
})
|
|
909
|
+
|
|
910
|
+
const execution = await canvas.execute({ query: 'Hello' })
|
|
911
|
+
|
|
912
|
+
// Get the parsed, validated result
|
|
913
|
+
const result = await execution.result
|
|
914
|
+
console.log(result.answer) // Type-safe access
|
|
915
|
+
|
|
916
|
+
// Get the raw API response
|
|
917
|
+
const rawResult = await execution.rawResult
|
|
918
|
+
console.log(rawResult) // Complete API response with all metadata
|
|
919
|
+
|
|
920
|
+
// You can await either one first - both will be available
|
|
921
|
+
const raw = await execution.rawResult // Triggers execution
|
|
922
|
+
const parsed = await execution.result // Reuses same execution
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
This is useful when you need:
|
|
926
|
+
- Full API response metadata (execution IDs, timestamps, etc.)
|
|
927
|
+
- Debugging and logging complete responses
|
|
928
|
+
- Access to data not in your schema
|
|
929
|
+
|
|
930
|
+
#### Fetch Existing Executions and Event-Driven Polling
|
|
931
|
+
|
|
932
|
+
V2 introduces the ability to fetch existing async executions by ID and monitor them with event-driven polling:
|
|
933
|
+
|
|
934
|
+
```typescript
|
|
935
|
+
// Start an async execution
|
|
936
|
+
const execution = await canvas.execute(
|
|
937
|
+
{ query: 'Process this data' },
|
|
938
|
+
{ async: true }
|
|
939
|
+
)
|
|
940
|
+
|
|
941
|
+
// Store the execution ID (e.g., in a database)
|
|
942
|
+
const executionId = execution.id
|
|
943
|
+
|
|
944
|
+
// Later, fetch the execution by ID
|
|
945
|
+
const fetchedExecution = await canvas.getExecution(executionId, {
|
|
946
|
+
pollingInterval: 2000,
|
|
947
|
+
pollingTimeout: 120000
|
|
948
|
+
})
|
|
949
|
+
|
|
950
|
+
// Use event-driven polling (non-blocking)
|
|
951
|
+
fetchedExecution.on('statusChange', (status) => {
|
|
952
|
+
console.log(`Status changed: ${status}`)
|
|
953
|
+
})
|
|
954
|
+
|
|
955
|
+
fetchedExecution.on('success', (result) => {
|
|
956
|
+
console.log('Completed!', result)
|
|
957
|
+
})
|
|
958
|
+
|
|
959
|
+
fetchedExecution.on('error', (error) => {
|
|
960
|
+
console.error('Failed:', error)
|
|
961
|
+
})
|
|
962
|
+
|
|
963
|
+
// Start polling without blocking
|
|
964
|
+
fetchedExecution.poll()
|
|
965
|
+
|
|
966
|
+
// Continue with other work...
|
|
967
|
+
console.log('Polling in background')
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
This enables powerful use cases:
|
|
971
|
+
- **Job queue management**: Start jobs, store IDs, fetch later to check status
|
|
972
|
+
- **Resumable workflows**: Continue monitoring after page refresh or server restart
|
|
973
|
+
- **Multi-user dashboards**: Monitor executions started by different users
|
|
974
|
+
- **Real-time UI updates**: Non-blocking polling with event listeners
|
|
975
|
+
- **Background processing**: Track multiple executions concurrently
|
|
976
|
+
|
|
977
|
+
See [Fetch and Poll Examples](./examples/events/) for detailed patterns.
|
|
978
|
+
|
|
979
|
+
#### Execution Tags
|
|
980
|
+
|
|
981
|
+
V2 introduces support for tagging executions for filtering, categorization, and analytics:
|
|
982
|
+
|
|
983
|
+
```typescript
|
|
984
|
+
// Add tags to any execution mode
|
|
985
|
+
const result = await canvas.execute(
|
|
986
|
+
{ query: 'Analyze customer feedback' },
|
|
987
|
+
{
|
|
988
|
+
tags: ['production', 'analytics', 'customer-feedback']
|
|
135
989
|
}
|
|
990
|
+
).result
|
|
991
|
+
|
|
992
|
+
// Tags work with async executions
|
|
993
|
+
const asyncResult = await canvas.execute(
|
|
994
|
+
{ query: 'Process large dataset' },
|
|
995
|
+
{
|
|
996
|
+
async: true,
|
|
997
|
+
tags: ['batch-processing', 'analytics']
|
|
998
|
+
}
|
|
999
|
+
).result
|
|
1000
|
+
|
|
1001
|
+
// Tags work with streaming executions
|
|
1002
|
+
for await (const chunk of canvas.execute(
|
|
1003
|
+
{ query: 'Generate report' },
|
|
1004
|
+
{
|
|
1005
|
+
stream: true,
|
|
1006
|
+
tags: ['streaming', 'reports']
|
|
1007
|
+
}
|
|
1008
|
+
).result) {
|
|
1009
|
+
process.stdout.write(chunk.result || '')
|
|
136
1010
|
}
|
|
137
|
-
run().catch(console.error)
|
|
138
1011
|
```
|
|
139
1012
|
|
|
140
|
-
|
|
1013
|
+
**Use Cases:**
|
|
1014
|
+
- **Environment tracking**: Tag executions by environment (`production`, `staging`, `development`)
|
|
1015
|
+
- **Feature categorization**: Organize executions by feature (`analytics`, `reporting`, `summarization`)
|
|
1016
|
+
- **User segmentation**: Track executions by user tier or department
|
|
1017
|
+
- **Cost allocation**: Attribute API usage to specific projects or teams
|
|
1018
|
+
- **Performance monitoring**: Filter and analyze execution metrics by tag
|
|
141
1019
|
|
|
142
|
-
|
|
1020
|
+
#### Application Execution Labels
|
|
143
1021
|
|
|
144
|
-
|
|
1022
|
+
V2 adds support for setting workspace task titles when using deployed applications via `applicationId`:
|
|
145
1023
|
|
|
146
|
-
|
|
1024
|
+
```typescript
|
|
1025
|
+
const canvas = await tela.canvas.get({
|
|
1026
|
+
applicationId: 'app-id' // Using deployed application instead of canvas ID
|
|
1027
|
+
})
|
|
147
1028
|
|
|
148
|
-
|
|
1029
|
+
// Set the title of the workspace task
|
|
1030
|
+
const result = await canvas.execute(
|
|
1031
|
+
{ query: 'Process request' },
|
|
1032
|
+
{
|
|
1033
|
+
label: 'Customer Dashboard Query'
|
|
1034
|
+
}
|
|
1035
|
+
).result
|
|
1036
|
+
```
|
|
149
1037
|
|
|
150
|
-
|
|
1038
|
+
When you execute a canvas using `applicationId`, it creates a task in the application's workspace. The `label` field sets the title of that workspace task, making it easier to identify and track executions in your Tela workspace.
|
|
151
1039
|
|
|
152
|
-
|
|
1040
|
+
**Note:** The `label` field is only applicable when using `applicationId`. A warning will be logged if you provide a label without an `applicationId`.
|
|
153
1041
|
|
|
154
|
-
|
|
155
|
-
-
|
|
1042
|
+
**Use Cases:**
|
|
1043
|
+
- **Task identification**: Give meaningful titles to workspace tasks for easier tracking
|
|
1044
|
+
- **Execution categorization**: Organize tasks by feature or workflow in the workspace
|
|
1045
|
+
- **User-friendly naming**: Display clear task names instead of generic execution IDs
|
|
1046
|
+
- **Dashboard clarity**: Make workspace task lists more readable and searchable
|
|
156
1047
|
|
|
157
|
-
|
|
1048
|
+
### Need Help?
|
|
158
1049
|
|
|
159
|
-
|
|
1050
|
+
If you encounter issues during migration, please:
|
|
1051
|
+
- Check the [examples](./examples/) directory for updated usage patterns
|
|
1052
|
+
- Review the [API documentation](./docs/)
|
|
1053
|
+
- Open an issue at [GitHub Issues](https://github.com/meistrari/tela-sdk-js/issues)
|