@vertesia/client 0.79.1 → 0.80.0-dev.20251121

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.
Files changed (75) hide show
  1. package/lib/cjs/ProjectsApi.js +6 -2
  2. package/lib/cjs/ProjectsApi.js.map +1 -1
  3. package/lib/cjs/client.js +2 -2
  4. package/lib/cjs/client.js.map +1 -1
  5. package/lib/cjs/index.js +0 -5
  6. package/lib/cjs/index.js.map +1 -1
  7. package/lib/cjs/store/CollectionsApi.js +9 -0
  8. package/lib/cjs/store/CollectionsApi.js.map +1 -1
  9. package/lib/esm/ProjectsApi.js +6 -1
  10. package/lib/esm/ProjectsApi.js.map +1 -1
  11. package/lib/esm/client.js +1 -1
  12. package/lib/esm/client.js.map +1 -1
  13. package/lib/esm/index.js +0 -2
  14. package/lib/esm/index.js.map +1 -1
  15. package/lib/esm/store/CollectionsApi.js +9 -0
  16. package/lib/esm/store/CollectionsApi.js.map +1 -1
  17. package/lib/tsconfig.tsbuildinfo +1 -1
  18. package/lib/types/AccountApi.d.ts +0 -1
  19. package/lib/types/AccountsApi.d.ts +0 -1
  20. package/lib/types/AnalyticsApi.d.ts +0 -1
  21. package/lib/types/ApiKeysApi.d.ts +0 -1
  22. package/lib/types/AppsApi.d.ts +0 -1
  23. package/lib/types/CommandsApi.d.ts +0 -1
  24. package/lib/types/EnvironmentsApi.d.ts +0 -1
  25. package/lib/types/GroupsApi.d.ts +0 -1
  26. package/lib/types/IamApi.d.ts +0 -1
  27. package/lib/types/InteractionBase.d.ts +0 -1
  28. package/lib/types/InteractionCatalogApi.d.ts +0 -1
  29. package/lib/types/InteractionOutput.d.ts +0 -1
  30. package/lib/types/InteractionResult.example.d.ts +0 -1
  31. package/lib/types/InteractionsApi.d.ts +0 -1
  32. package/lib/types/ProjectsApi.d.ts +3 -3
  33. package/lib/types/ProjectsApi.d.ts.map +1 -1
  34. package/lib/types/PromptsApi.d.ts +0 -1
  35. package/lib/types/RefsApi.d.ts +0 -1
  36. package/lib/types/RunsApi.d.ts +0 -1
  37. package/lib/types/StreamSource.d.ts +0 -1
  38. package/lib/types/TrainingApi.d.ts +0 -1
  39. package/lib/types/UsersApi.d.ts +0 -1
  40. package/lib/types/client.d.ts +1 -2
  41. package/lib/types/client.d.ts.map +1 -1
  42. package/lib/types/execute.d.ts +0 -1
  43. package/lib/types/index.d.ts +2 -5
  44. package/lib/types/index.d.ts.map +1 -1
  45. package/lib/types/nodejs/NodeStreamSource.d.ts +0 -1
  46. package/lib/types/nodejs/index.d.ts +0 -1
  47. package/lib/types/store/AgentsApi.d.ts +0 -1
  48. package/lib/types/store/AnalyzeDocApi.d.ts +0 -1
  49. package/lib/types/store/CollectionsApi.d.ts +11 -3
  50. package/lib/types/store/CollectionsApi.d.ts.map +1 -1
  51. package/lib/types/store/CommandsApi.d.ts +0 -1
  52. package/lib/types/store/EmbeddingsApi.d.ts +0 -1
  53. package/lib/types/store/FilesApi.d.ts +0 -1
  54. package/lib/types/store/ObjectsApi.d.ts +0 -1
  55. package/lib/types/store/TypesApi.d.ts +0 -1
  56. package/lib/types/store/WorkflowsApi.d.ts +0 -1
  57. package/lib/types/store/client.d.ts +0 -1
  58. package/lib/types/store/errors.d.ts +0 -1
  59. package/lib/types/store/index.d.ts +0 -1
  60. package/lib/types/store/version.d.ts +0 -1
  61. package/lib/vertesia-client.js +1 -1
  62. package/lib/vertesia-client.js.map +1 -1
  63. package/package.json +59 -54
  64. package/src/InteractionCatalogApi.ts +72 -0
  65. package/src/InteractionsApi.ts +19 -3
  66. package/src/ProjectsApi.ts +7 -1
  67. package/src/RunsApi.ts +8 -1
  68. package/src/client.test.ts +2 -0
  69. package/src/client.ts +128 -57
  70. package/src/index.ts +1 -0
  71. package/src/store/CollectionsApi.ts +15 -2
  72. package/src/store/FilesApi.ts +10 -8
  73. package/src/store/ObjectsApi.ts +7 -23
  74. package/src/store/WorkflowsApi.ts +166 -0
  75. package/src/store/client.ts +1 -0
@@ -10,6 +10,8 @@ import {
10
10
  ListWorkflowInteractionsResponse,
11
11
  ListWorkflowRunsPayload,
12
12
  ListWorkflowRunsResponse,
13
+ WebSocketClientMessage,
14
+ WebSocketServerMessage,
13
15
  WorkflowActionPayload,
14
16
  WorkflowDefinitionRef,
15
17
  WorkflowRule,
@@ -251,6 +253,170 @@ export class WorkflowsApi extends ApiTopic {
251
253
  });
252
254
  }
253
255
 
256
+ /**
257
+ * Stream workflow messages via WebSocket (for mobile/React Native clients)
258
+ * @param workflowId The workflow ID
259
+ * @param runId The run ID
260
+ * @param onMessage Callback for incoming messages
261
+ * @param since Optional timestamp to resume from
262
+ * @returns Promise that resolves with cleanup function and sendSignal helper
263
+ */
264
+ async streamMessagesWS(
265
+ workflowId: string,
266
+ runId: string,
267
+ onMessage?: (message: AgentMessage) => void,
268
+ since?: number
269
+ ): Promise<{ cleanup: () => void; sendSignal: (signalName: string, data: any) => void }> {
270
+ return new Promise((resolve, reject) => {
271
+ let reconnectAttempts = 0;
272
+ const maxReconnectAttempts = 10;
273
+ const baseDelay = 1000;
274
+ const maxDelay = 30000;
275
+ let ws: WebSocket | null = null;
276
+ let lastMessageTimestamp = since || 0;
277
+ let isClosed = false;
278
+
279
+ const calculateBackoffDelay = (attempts: number): number => {
280
+ const exponentialDelay = Math.min(baseDelay * Math.pow(2, attempts), maxDelay);
281
+ const jitter = Math.random() * 0.1 * exponentialDelay;
282
+ return exponentialDelay + jitter;
283
+ };
284
+
285
+ const connect = async () => {
286
+ if (isClosed) return;
287
+
288
+ try {
289
+ const client = this.client as VertesiaClient;
290
+ const wsUrl = new URL(client.workflows.baseUrl + `/runs/${workflowId}/${runId}/ws`);
291
+
292
+ // Replace http/https with ws/wss
293
+ wsUrl.protocol = wsUrl.protocol.replace('http', 'ws');
294
+
295
+ // Add query parameters
296
+ if (lastMessageTimestamp > 0) {
297
+ wsUrl.searchParams.set('since', lastMessageTimestamp.toString());
298
+ }
299
+
300
+ const bearerToken = client._auth ? await client._auth() : undefined;
301
+ if (!bearerToken) {
302
+ reject(new Error('No auth token available'));
303
+ return;
304
+ }
305
+
306
+ const token = bearerToken.split(' ')[1];
307
+ wsUrl.searchParams.set('access_token', token);
308
+
309
+ if (reconnectAttempts > 0) {
310
+ console.log(`Reconnecting to WebSocket for run ${runId} (attempt ${reconnectAttempts + 1}/${maxReconnectAttempts})`);
311
+ }
312
+
313
+ ws = new WebSocket(wsUrl.href);
314
+
315
+ ws.onopen = () => {
316
+ if (reconnectAttempts > 0) {
317
+ console.log(`Successfully reconnected to WebSocket for run ${runId}`);
318
+ }
319
+ reconnectAttempts = 0;
320
+
321
+ // Resolve with helpers on first successful connection
322
+ if (!isClosed) {
323
+ resolve({
324
+ cleanup: () => {
325
+ isClosed = true;
326
+ if (ws) {
327
+ ws.close();
328
+ ws = null;
329
+ }
330
+ },
331
+ sendSignal: (signalName: string, data: any) => {
332
+ if (ws?.readyState === WebSocket.OPEN) {
333
+ const message: WebSocketClientMessage = {
334
+ type: 'signal',
335
+ signalName,
336
+ data,
337
+ requestId: Date.now()
338
+ };
339
+ ws.send(JSON.stringify(message));
340
+ } else {
341
+ console.warn('WebSocket not open, cannot send signal');
342
+ }
343
+ }
344
+ });
345
+ }
346
+ };
347
+
348
+ ws.onmessage = (event: MessageEvent) => {
349
+ try {
350
+ const message = JSON.parse(event.data) as WebSocketServerMessage;
351
+
352
+ // Handle different message types
353
+ if ('workflow_run_id' in message) {
354
+ // This is an AgentMessage
355
+ const agentMessage = message as AgentMessage;
356
+
357
+ if (agentMessage.timestamp) {
358
+ lastMessageTimestamp = Math.max(lastMessageTimestamp, agentMessage.timestamp);
359
+ }
360
+
361
+ if (onMessage) onMessage(agentMessage);
362
+
363
+ // Check for stream completion
364
+ const streamIsOver =
365
+ agentMessage.type === AgentMessageType.TERMINATED ||
366
+ (agentMessage.type === AgentMessageType.COMPLETE &&
367
+ (!agentMessage.workstream_id || agentMessage.workstream_id === 'main'));
368
+
369
+ if (streamIsOver) {
370
+ console.log('Closing WebSocket due to workflow completion');
371
+ isClosed = true;
372
+ if (ws) {
373
+ ws.close();
374
+ ws = null;
375
+ }
376
+ }
377
+ } else if (message.type === 'pong') {
378
+ // Heartbeat response
379
+ console.debug('Received pong');
380
+ } else if (message.type === 'ack') {
381
+ console.debug('Signal acknowledged', message);
382
+ } else if (message.type === 'error') {
383
+ console.error('WebSocket error message', message);
384
+ }
385
+ } catch (err) {
386
+ console.error('Failed to parse WebSocket message', err);
387
+ }
388
+ };
389
+
390
+ ws.onerror = (err) => {
391
+ console.error('WebSocket error', err);
392
+ };
393
+
394
+ ws.onclose = () => {
395
+ if (!isClosed && reconnectAttempts < maxReconnectAttempts) {
396
+ const delay = calculateBackoffDelay(reconnectAttempts);
397
+ console.log(`WebSocket closed, reconnecting in ${delay}ms (attempt ${reconnectAttempts + 1}/${maxReconnectAttempts})`);
398
+ reconnectAttempts++;
399
+ setTimeout(connect, delay);
400
+ } else if (reconnectAttempts >= maxReconnectAttempts) {
401
+ reject(new Error(`WebSocket connection failed after ${maxReconnectAttempts} attempts`));
402
+ }
403
+ };
404
+ } catch (err) {
405
+ console.error('Error setting up WebSocket', err);
406
+ if (reconnectAttempts < maxReconnectAttempts) {
407
+ const delay = calculateBackoffDelay(reconnectAttempts);
408
+ reconnectAttempts++;
409
+ setTimeout(connect, delay);
410
+ } else {
411
+ reject(err);
412
+ }
413
+ }
414
+ };
415
+
416
+ connect();
417
+ });
418
+ }
419
+
254
420
  rules = new WorkflowsRulesApi(this);
255
421
  definitions = new WorkflowsDefinitionApi(this);
256
422
  }
@@ -13,6 +13,7 @@ import { WorkflowsApi } from "./WorkflowsApi.js";
13
13
 
14
14
  export interface ZenoClientProps {
15
15
  serverUrl?: string;
16
+ tokenServerUrl?: string;
16
17
  apikey?: string;
17
18
  onRequest?: (request: Request) => void;
18
19
  onResponse?: (response: Response) => void;