@vertesia/client 0.76.0 → 0.78.0-dev-9372725

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 (226) hide show
  1. package/package.json +59 -54
  2. package/src/AppsApi.ts +10 -1
  3. package/src/InteractionBase.ts +3 -3
  4. package/src/InteractionsApi.ts +19 -9
  5. package/src/RunsApi.ts +9 -2
  6. package/src/client.test.ts +2 -0
  7. package/src/client.ts +134 -56
  8. package/src/execute.ts +11 -5
  9. package/src/store/FilesApi.ts +2 -2
  10. package/src/store/ObjectsApi.ts +43 -13
  11. package/src/store/WorkflowsApi.ts +172 -4
  12. package/src/store/client.ts +8 -0
  13. package/lib/cjs/AccountApi.js +0 -85
  14. package/lib/cjs/AccountApi.js.map +0 -1
  15. package/lib/cjs/AccountsApi.js +0 -16
  16. package/lib/cjs/AccountsApi.js.map +0 -1
  17. package/lib/cjs/AnalyticsApi.js +0 -13
  18. package/lib/cjs/AnalyticsApi.js.map +0 -1
  19. package/lib/cjs/ApiKeysApi.js +0 -63
  20. package/lib/cjs/ApiKeysApi.js.map +0 -1
  21. package/lib/cjs/AppsApi.js +0 -111
  22. package/lib/cjs/AppsApi.js.map +0 -1
  23. package/lib/cjs/CommandsApi.js +0 -19
  24. package/lib/cjs/CommandsApi.js.map +0 -1
  25. package/lib/cjs/EnvironmentsApi.js +0 -58
  26. package/lib/cjs/EnvironmentsApi.js.map +0 -1
  27. package/lib/cjs/GroupsApi.js +0 -78
  28. package/lib/cjs/GroupsApi.js.map +0 -1
  29. package/lib/cjs/IamApi.js +0 -53
  30. package/lib/cjs/IamApi.js.map +0 -1
  31. package/lib/cjs/InteractionBase.js +0 -44
  32. package/lib/cjs/InteractionBase.js.map +0 -1
  33. package/lib/cjs/InteractionsApi.js +0 -209
  34. package/lib/cjs/InteractionsApi.js.map +0 -1
  35. package/lib/cjs/ProjectsApi.js +0 -48
  36. package/lib/cjs/ProjectsApi.js.map +0 -1
  37. package/lib/cjs/PromptsApi.js +0 -133
  38. package/lib/cjs/PromptsApi.js.map +0 -1
  39. package/lib/cjs/RefsApi.js +0 -14
  40. package/lib/cjs/RefsApi.js.map +0 -1
  41. package/lib/cjs/RunsApi.js +0 -105
  42. package/lib/cjs/RunsApi.js.map +0 -1
  43. package/lib/cjs/StreamSource.js +0 -17
  44. package/lib/cjs/StreamSource.js.map +0 -1
  45. package/lib/cjs/TrainingApi.js +0 -54
  46. package/lib/cjs/TrainingApi.js.map +0 -1
  47. package/lib/cjs/UsersApi.js +0 -13
  48. package/lib/cjs/UsersApi.js.map +0 -1
  49. package/lib/cjs/client.js +0 -263
  50. package/lib/cjs/client.js.map +0 -1
  51. package/lib/cjs/execute.js +0 -152
  52. package/lib/cjs/execute.js.map +0 -1
  53. package/lib/cjs/index.js +0 -21
  54. package/lib/cjs/index.js.map +0 -1
  55. package/lib/cjs/nodejs/NodeStreamSource.js +0 -45
  56. package/lib/cjs/nodejs/NodeStreamSource.js.map +0 -1
  57. package/lib/cjs/nodejs/index.js +0 -18
  58. package/lib/cjs/nodejs/index.js.map +0 -1
  59. package/lib/cjs/package.json +0 -3
  60. package/lib/cjs/store/AgentsApi.js +0 -16
  61. package/lib/cjs/store/AgentsApi.js.map +0 -1
  62. package/lib/cjs/store/AnalyzeDocApi.js +0 -56
  63. package/lib/cjs/store/AnalyzeDocApi.js.map +0 -1
  64. package/lib/cjs/store/CollectionsApi.js +0 -101
  65. package/lib/cjs/store/CollectionsApi.js.map +0 -1
  66. package/lib/cjs/store/CommandsApi.js +0 -17
  67. package/lib/cjs/store/CommandsApi.js.map +0 -1
  68. package/lib/cjs/store/EmbeddingsApi.js +0 -29
  69. package/lib/cjs/store/EmbeddingsApi.js.map +0 -1
  70. package/lib/cjs/store/FilesApi.js +0 -147
  71. package/lib/cjs/store/FilesApi.js.map +0 -1
  72. package/lib/cjs/store/ObjectsApi.js +0 -264
  73. package/lib/cjs/store/ObjectsApi.js.map +0 -1
  74. package/lib/cjs/store/TypesApi.js +0 -57
  75. package/lib/cjs/store/TypesApi.js.map +0 -1
  76. package/lib/cjs/store/WorkflowsApi.js +0 -263
  77. package/lib/cjs/store/WorkflowsApi.js.map +0 -1
  78. package/lib/cjs/store/client.js +0 -55
  79. package/lib/cjs/store/client.js.map +0 -1
  80. package/lib/cjs/store/errors.js +0 -11
  81. package/lib/cjs/store/errors.js.map +0 -1
  82. package/lib/cjs/store/index.js +0 -22
  83. package/lib/cjs/store/index.js.map +0 -1
  84. package/lib/esm/AccountApi.js +0 -82
  85. package/lib/esm/AccountApi.js.map +0 -1
  86. package/lib/esm/AccountsApi.js +0 -13
  87. package/lib/esm/AccountsApi.js.map +0 -1
  88. package/lib/esm/AnalyticsApi.js +0 -10
  89. package/lib/esm/AnalyticsApi.js.map +0 -1
  90. package/lib/esm/ApiKeysApi.js +0 -59
  91. package/lib/esm/ApiKeysApi.js.map +0 -1
  92. package/lib/esm/AppsApi.js +0 -108
  93. package/lib/esm/AppsApi.js.map +0 -1
  94. package/lib/esm/CommandsApi.js +0 -16
  95. package/lib/esm/CommandsApi.js.map +0 -1
  96. package/lib/esm/EnvironmentsApi.js +0 -55
  97. package/lib/esm/EnvironmentsApi.js.map +0 -1
  98. package/lib/esm/GroupsApi.js +0 -74
  99. package/lib/esm/GroupsApi.js.map +0 -1
  100. package/lib/esm/IamApi.js +0 -47
  101. package/lib/esm/IamApi.js.map +0 -1
  102. package/lib/esm/InteractionBase.js +0 -40
  103. package/lib/esm/InteractionBase.js.map +0 -1
  104. package/lib/esm/InteractionsApi.js +0 -206
  105. package/lib/esm/InteractionsApi.js.map +0 -1
  106. package/lib/esm/ProjectsApi.js +0 -45
  107. package/lib/esm/ProjectsApi.js.map +0 -1
  108. package/lib/esm/PromptsApi.js +0 -130
  109. package/lib/esm/PromptsApi.js.map +0 -1
  110. package/lib/esm/RefsApi.js +0 -10
  111. package/lib/esm/RefsApi.js.map +0 -1
  112. package/lib/esm/RunsApi.js +0 -101
  113. package/lib/esm/RunsApi.js.map +0 -1
  114. package/lib/esm/StreamSource.js +0 -13
  115. package/lib/esm/StreamSource.js.map +0 -1
  116. package/lib/esm/TrainingApi.js +0 -51
  117. package/lib/esm/TrainingApi.js.map +0 -1
  118. package/lib/esm/UsersApi.js +0 -10
  119. package/lib/esm/UsersApi.js.map +0 -1
  120. package/lib/esm/client.js +0 -254
  121. package/lib/esm/client.js.map +0 -1
  122. package/lib/esm/execute.js +0 -113
  123. package/lib/esm/execute.js.map +0 -1
  124. package/lib/esm/index.js +0 -5
  125. package/lib/esm/index.js.map +0 -1
  126. package/lib/esm/nodejs/NodeStreamSource.js +0 -41
  127. package/lib/esm/nodejs/NodeStreamSource.js.map +0 -1
  128. package/lib/esm/nodejs/index.js +0 -2
  129. package/lib/esm/nodejs/index.js.map +0 -1
  130. package/lib/esm/store/AgentsApi.js +0 -12
  131. package/lib/esm/store/AgentsApi.js.map +0 -1
  132. package/lib/esm/store/AnalyzeDocApi.js +0 -52
  133. package/lib/esm/store/AnalyzeDocApi.js.map +0 -1
  134. package/lib/esm/store/CollectionsApi.js +0 -97
  135. package/lib/esm/store/CollectionsApi.js.map +0 -1
  136. package/lib/esm/store/CommandsApi.js +0 -13
  137. package/lib/esm/store/CommandsApi.js.map +0 -1
  138. package/lib/esm/store/EmbeddingsApi.js +0 -25
  139. package/lib/esm/store/EmbeddingsApi.js.map +0 -1
  140. package/lib/esm/store/FilesApi.js +0 -142
  141. package/lib/esm/store/FilesApi.js.map +0 -1
  142. package/lib/esm/store/ObjectsApi.js +0 -260
  143. package/lib/esm/store/ObjectsApi.js.map +0 -1
  144. package/lib/esm/store/TypesApi.js +0 -53
  145. package/lib/esm/store/TypesApi.js.map +0 -1
  146. package/lib/esm/store/WorkflowsApi.js +0 -257
  147. package/lib/esm/store/WorkflowsApi.js.map +0 -1
  148. package/lib/esm/store/client.js +0 -51
  149. package/lib/esm/store/client.js.map +0 -1
  150. package/lib/esm/store/errors.js +0 -7
  151. package/lib/esm/store/errors.js.map +0 -1
  152. package/lib/esm/store/index.js +0 -6
  153. package/lib/esm/store/index.js.map +0 -1
  154. package/lib/tsconfig.tsbuildinfo +0 -1
  155. package/lib/types/AccountApi.d.ts +0 -59
  156. package/lib/types/AccountApi.d.ts.map +0 -1
  157. package/lib/types/AccountsApi.d.ts +0 -7
  158. package/lib/types/AccountsApi.d.ts.map +0 -1
  159. package/lib/types/AnalyticsApi.d.ts +0 -6
  160. package/lib/types/AnalyticsApi.d.ts.map +0 -1
  161. package/lib/types/ApiKeysApi.d.ts +0 -42
  162. package/lib/types/ApiKeysApi.d.ts.map +0 -1
  163. package/lib/types/AppsApi.d.ts +0 -59
  164. package/lib/types/AppsApi.d.ts.map +0 -1
  165. package/lib/types/CommandsApi.d.ts +0 -10
  166. package/lib/types/CommandsApi.d.ts.map +0 -1
  167. package/lib/types/EnvironmentsApi.d.ts +0 -30
  168. package/lib/types/EnvironmentsApi.d.ts.map +0 -1
  169. package/lib/types/GroupsApi.d.ts +0 -65
  170. package/lib/types/GroupsApi.d.ts.map +0 -1
  171. package/lib/types/IamApi.d.ts +0 -41
  172. package/lib/types/IamApi.d.ts.map +0 -1
  173. package/lib/types/InteractionBase.d.ts +0 -22
  174. package/lib/types/InteractionBase.d.ts.map +0 -1
  175. package/lib/types/InteractionsApi.d.ts +0 -150
  176. package/lib/types/InteractionsApi.d.ts.map +0 -1
  177. package/lib/types/ProjectsApi.d.ts +0 -17
  178. package/lib/types/ProjectsApi.d.ts.map +0 -1
  179. package/lib/types/PromptsApi.d.ts +0 -106
  180. package/lib/types/PromptsApi.d.ts.map +0 -1
  181. package/lib/types/RefsApi.d.ts +0 -6
  182. package/lib/types/RefsApi.d.ts.map +0 -1
  183. package/lib/types/RunsApi.d.ts +0 -77
  184. package/lib/types/RunsApi.d.ts.map +0 -1
  185. package/lib/types/StreamSource.d.ts +0 -7
  186. package/lib/types/StreamSource.d.ts.map +0 -1
  187. package/lib/types/TrainingApi.d.ts +0 -27
  188. package/lib/types/TrainingApi.d.ts.map +0 -1
  189. package/lib/types/UsersApi.d.ts +0 -6
  190. package/lib/types/UsersApi.d.ts.map +0 -1
  191. package/lib/types/client.d.ts +0 -114
  192. package/lib/types/client.d.ts.map +0 -1
  193. package/lib/types/execute.d.ts +0 -36
  194. package/lib/types/execute.d.ts.map +0 -1
  195. package/lib/types/index.d.ts +0 -8
  196. package/lib/types/index.d.ts.map +0 -1
  197. package/lib/types/nodejs/NodeStreamSource.d.ts +0 -9
  198. package/lib/types/nodejs/NodeStreamSource.d.ts.map +0 -1
  199. package/lib/types/nodejs/index.d.ts +0 -1
  200. package/lib/types/nodejs/index.d.ts.map +0 -1
  201. package/lib/types/store/AgentsApi.d.ts +0 -6
  202. package/lib/types/store/AgentsApi.d.ts.map +0 -1
  203. package/lib/types/store/AnalyzeDocApi.d.ts +0 -17
  204. package/lib/types/store/AnalyzeDocApi.d.ts.map +0 -1
  205. package/lib/types/store/CollectionsApi.d.ts +0 -66
  206. package/lib/types/store/CollectionsApi.d.ts.map +0 -1
  207. package/lib/types/store/CommandsApi.d.ts +0 -10
  208. package/lib/types/store/CommandsApi.d.ts.map +0 -1
  209. package/lib/types/store/EmbeddingsApi.d.ts +0 -12
  210. package/lib/types/store/EmbeddingsApi.d.ts.map +0 -1
  211. package/lib/types/store/FilesApi.d.ts +0 -47
  212. package/lib/types/store/FilesApi.d.ts.map +0 -1
  213. package/lib/types/store/ObjectsApi.d.ts +0 -118
  214. package/lib/types/store/ObjectsApi.d.ts.map +0 -1
  215. package/lib/types/store/TypesApi.d.ts +0 -23
  216. package/lib/types/store/TypesApi.d.ts.map +0 -1
  217. package/lib/types/store/WorkflowsApi.d.ts +0 -50
  218. package/lib/types/store/WorkflowsApi.d.ts.map +0 -1
  219. package/lib/types/store/client.d.ts +0 -29
  220. package/lib/types/store/client.d.ts.map +0 -1
  221. package/lib/types/store/errors.d.ts +0 -4
  222. package/lib/types/store/errors.d.ts.map +0 -1
  223. package/lib/types/store/index.d.ts +0 -5
  224. package/lib/types/store/index.d.ts.map +0 -1
  225. package/lib/vertesia-client.js +0 -2
  226. package/lib/vertesia-client.js.map +0 -1
@@ -1,9 +1,11 @@
1
1
  import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
2
  import {
3
+ ContentObjectApiHeaders,
3
4
  ComplexSearchPayload,
4
5
  ComputeObjectFacetPayload,
5
6
  ContentObject,
6
7
  ContentObjectItem,
8
+ ContentObjectProcessingPriority,
7
9
  ContentSource,
8
10
  CreateContentObjectPayload,
9
11
  Embedding,
@@ -47,7 +49,7 @@ export interface ComputeFacetsResponse {
47
49
  type?: { _id: string; count: number }[];
48
50
  location?: { _id: string; count: number }[];
49
51
  status?: { _id: string; count: number }[];
50
- total?: { count: number }[];
52
+ total?: number;
51
53
  }
52
54
 
53
55
  export interface SearchResponse {
@@ -218,6 +220,7 @@ export class ObjectsApi extends ApiTopic {
218
220
  payload: UploadContentObjectPayload,
219
221
  options?: {
220
222
  collection_id?: string;
223
+ processing_priority?: ContentObjectProcessingPriority;
221
224
  },
222
225
  ): Promise<ContentObject> {
223
226
  const createPayload: CreateContentObjectPayload = {
@@ -229,9 +232,18 @@ export class ObjectsApi extends ApiTopic {
229
232
  ) {
230
233
  createPayload.content = await this.upload(payload.content);
231
234
  }
235
+
236
+ const headers: Record<string, string> = {};
237
+ if (options?.processing_priority) {
238
+ headers[ContentObjectApiHeaders.PROCESSING_PRIORITY] = options.processing_priority;
239
+ }
240
+ if (options?.collection_id) {
241
+ headers[ContentObjectApiHeaders.COLLECTION_ID] = options.collection_id;
242
+ }
243
+
232
244
  return await this.post("/", {
233
245
  payload: createPayload,
234
- query: options || {},
246
+ headers: headers,
235
247
  });
236
248
  }
237
249
 
@@ -241,11 +253,16 @@ export class ObjectsApi extends ApiTopic {
241
253
  * For the s3 blobs you must use a hash with the blob #region. Ex: s3://bucket/path/to/file#us-east-1
242
254
  * @param uri
243
255
  * @param payload
256
+ * @param options
244
257
  * @returns
245
258
  */
246
259
  async createFromExternalSource(
247
260
  uri: string,
248
261
  payload: CreateContentObjectPayload = {},
262
+ options?: {
263
+ collection_id?: string;
264
+ processing_priority?: ContentObjectProcessingPriority;
265
+ },
249
266
  ): Promise<ContentObject> {
250
267
  const metadata = await (this.client as ZenoClient).files.getMetadata(
251
268
  uri,
@@ -259,8 +276,18 @@ export class ObjectsApi extends ApiTopic {
259
276
  etag: metadata.etag,
260
277
  },
261
278
  };
279
+
280
+ const headers: Record<string, string> = {};
281
+ if (options?.processing_priority) {
282
+ headers[ContentObjectApiHeaders.PROCESSING_PRIORITY] = options.processing_priority;
283
+ }
284
+ if (options?.collection_id) {
285
+ headers[ContentObjectApiHeaders.COLLECTION_ID] = options.collection_id;
286
+ }
287
+
262
288
  return await this.post("/", {
263
289
  payload: createPayload,
290
+ headers: headers,
264
291
  });
265
292
  }
266
293
 
@@ -281,6 +308,7 @@ export class ObjectsApi extends ApiTopic {
281
308
  options?: {
282
309
  createRevision?: boolean;
283
310
  revisionLabel?: string;
311
+ processing_priority?: ContentObjectProcessingPriority;
284
312
  },
285
313
  ): Promise<ContentObject> {
286
314
  const updatePayload: Partial<CreateContentObjectPayload> = {
@@ -295,19 +323,21 @@ export class ObjectsApi extends ApiTopic {
295
323
  updatePayload.content = await this.upload(payload.content);
296
324
  }
297
325
 
326
+ const headers: Record<string, string> = {};
327
+ if (options?.processing_priority) {
328
+ headers[ContentObjectApiHeaders.PROCESSING_PRIORITY] = options.processing_priority;
329
+ }
298
330
  if (options?.createRevision) {
299
- return this.put(`/${id}`, {
300
- payload: updatePayload,
301
- headers: {
302
- "x-create-revision": "true",
303
- "x-revision-label": options.revisionLabel || "",
304
- },
305
- });
306
- } else {
307
- return this.put(`/${id}`, {
308
- payload: updatePayload,
309
- });
331
+ headers[ContentObjectApiHeaders.CREATE_REVISION] = "true";
332
+ if (options.revisionLabel) {
333
+ headers[ContentObjectApiHeaders.REVISION_LABEL] = options.revisionLabel;
334
+ }
310
335
  }
336
+
337
+ return this.put(`/${id}`, {
338
+ payload: updatePayload,
339
+ headers,
340
+ });
311
341
  }
312
342
 
313
343
  /**
@@ -10,6 +10,8 @@ import {
10
10
  ListWorkflowInteractionsResponse,
11
11
  ListWorkflowRunsPayload,
12
12
  ListWorkflowRunsResponse,
13
+ WebSocketClientMessage,
14
+ WebSocketServerMessage,
13
15
  WorkflowDefinitionRef,
14
16
  WorkflowRule,
15
17
  WorkflowRuleItem,
@@ -32,8 +34,10 @@ export class WorkflowsApi extends ApiTopic {
32
34
  }
33
35
 
34
36
  /** List conversations the users has access to */
35
- listConversations(): Promise<ListWorkflowRunsResponse> {
36
- return this.get(`/conversations`);
37
+ listConversations(payload: ListWorkflowRunsPayload): Promise<ListWorkflowRunsResponse> {
38
+ return this.post(`/conversations`, {
39
+ payload
40
+ });
37
41
  }
38
42
 
39
43
  searchRuns(payload: ListWorkflowRunsPayload): Promise<ListWorkflowRunsResponse> {
@@ -176,8 +180,8 @@ export class WorkflowsApi extends ApiTopic {
176
180
 
177
181
  if (onMessage) onMessage(message, exit);
178
182
 
179
- const streamIsOver = message.type === AgentMessageType.TERMINATED ||
180
- (message.type === AgentMessageType.COMPLETE &&
183
+ const streamIsOver = message.type === AgentMessageType.TERMINATED ||
184
+ (message.type === AgentMessageType.COMPLETE &&
181
185
  (!message.workstream_id || message.workstream_id === 'main'));
182
186
 
183
187
  // Only close the stream when the main workstream completes or terminates
@@ -246,6 +250,170 @@ export class WorkflowsApi extends ApiTopic {
246
250
  });
247
251
  }
248
252
 
253
+ /**
254
+ * Stream workflow messages via WebSocket (for mobile/React Native clients)
255
+ * @param workflowId The workflow ID
256
+ * @param runId The run ID
257
+ * @param onMessage Callback for incoming messages
258
+ * @param since Optional timestamp to resume from
259
+ * @returns Promise that resolves with cleanup function and sendSignal helper
260
+ */
261
+ async streamMessagesWS(
262
+ workflowId: string,
263
+ runId: string,
264
+ onMessage?: (message: AgentMessage) => void,
265
+ since?: number
266
+ ): Promise<{ cleanup: () => void; sendSignal: (signalName: string, data: any) => void }> {
267
+ return new Promise((resolve, reject) => {
268
+ let reconnectAttempts = 0;
269
+ const maxReconnectAttempts = 10;
270
+ const baseDelay = 1000;
271
+ const maxDelay = 30000;
272
+ let ws: WebSocket | null = null;
273
+ let lastMessageTimestamp = since || 0;
274
+ let isClosed = false;
275
+
276
+ const calculateBackoffDelay = (attempts: number): number => {
277
+ const exponentialDelay = Math.min(baseDelay * Math.pow(2, attempts), maxDelay);
278
+ const jitter = Math.random() * 0.1 * exponentialDelay;
279
+ return exponentialDelay + jitter;
280
+ };
281
+
282
+ const connect = async () => {
283
+ if (isClosed) return;
284
+
285
+ try {
286
+ const client = this.client as VertesiaClient;
287
+ const wsUrl = new URL(client.workflows.baseUrl + `/runs/${workflowId}/${runId}/ws`);
288
+
289
+ // Replace http/https with ws/wss
290
+ wsUrl.protocol = wsUrl.protocol.replace('http', 'ws');
291
+
292
+ // Add query parameters
293
+ if (lastMessageTimestamp > 0) {
294
+ wsUrl.searchParams.set('since', lastMessageTimestamp.toString());
295
+ }
296
+
297
+ const bearerToken = client._auth ? await client._auth() : undefined;
298
+ if (!bearerToken) {
299
+ reject(new Error('No auth token available'));
300
+ return;
301
+ }
302
+
303
+ const token = bearerToken.split(' ')[1];
304
+ wsUrl.searchParams.set('access_token', token);
305
+
306
+ if (reconnectAttempts > 0) {
307
+ console.log(`Reconnecting to WebSocket for run ${runId} (attempt ${reconnectAttempts + 1}/${maxReconnectAttempts})`);
308
+ }
309
+
310
+ ws = new WebSocket(wsUrl.href);
311
+
312
+ ws.onopen = () => {
313
+ if (reconnectAttempts > 0) {
314
+ console.log(`Successfully reconnected to WebSocket for run ${runId}`);
315
+ }
316
+ reconnectAttempts = 0;
317
+
318
+ // Resolve with helpers on first successful connection
319
+ if (!isClosed) {
320
+ resolve({
321
+ cleanup: () => {
322
+ isClosed = true;
323
+ if (ws) {
324
+ ws.close();
325
+ ws = null;
326
+ }
327
+ },
328
+ sendSignal: (signalName: string, data: any) => {
329
+ if (ws?.readyState === WebSocket.OPEN) {
330
+ const message: WebSocketClientMessage = {
331
+ type: 'signal',
332
+ signalName,
333
+ data,
334
+ requestId: Date.now()
335
+ };
336
+ ws.send(JSON.stringify(message));
337
+ } else {
338
+ console.warn('WebSocket not open, cannot send signal');
339
+ }
340
+ }
341
+ });
342
+ }
343
+ };
344
+
345
+ ws.onmessage = (event: MessageEvent) => {
346
+ try {
347
+ const message = JSON.parse(event.data) as WebSocketServerMessage;
348
+
349
+ // Handle different message types
350
+ if ('workflow_run_id' in message) {
351
+ // This is an AgentMessage
352
+ const agentMessage = message as AgentMessage;
353
+
354
+ if (agentMessage.timestamp) {
355
+ lastMessageTimestamp = Math.max(lastMessageTimestamp, agentMessage.timestamp);
356
+ }
357
+
358
+ if (onMessage) onMessage(agentMessage);
359
+
360
+ // Check for stream completion
361
+ const streamIsOver =
362
+ agentMessage.type === AgentMessageType.TERMINATED ||
363
+ (agentMessage.type === AgentMessageType.COMPLETE &&
364
+ (!agentMessage.workstream_id || agentMessage.workstream_id === 'main'));
365
+
366
+ if (streamIsOver) {
367
+ console.log('Closing WebSocket due to workflow completion');
368
+ isClosed = true;
369
+ if (ws) {
370
+ ws.close();
371
+ ws = null;
372
+ }
373
+ }
374
+ } else if (message.type === 'pong') {
375
+ // Heartbeat response
376
+ console.debug('Received pong');
377
+ } else if (message.type === 'ack') {
378
+ console.debug('Signal acknowledged', message);
379
+ } else if (message.type === 'error') {
380
+ console.error('WebSocket error message', message);
381
+ }
382
+ } catch (err) {
383
+ console.error('Failed to parse WebSocket message', err);
384
+ }
385
+ };
386
+
387
+ ws.onerror = (err) => {
388
+ console.error('WebSocket error', err);
389
+ };
390
+
391
+ ws.onclose = () => {
392
+ if (!isClosed && reconnectAttempts < maxReconnectAttempts) {
393
+ const delay = calculateBackoffDelay(reconnectAttempts);
394
+ console.log(`WebSocket closed, reconnecting in ${delay}ms (attempt ${reconnectAttempts + 1}/${maxReconnectAttempts})`);
395
+ reconnectAttempts++;
396
+ setTimeout(connect, delay);
397
+ } else if (reconnectAttempts >= maxReconnectAttempts) {
398
+ reject(new Error(`WebSocket connection failed after ${maxReconnectAttempts} attempts`));
399
+ }
400
+ };
401
+ } catch (err) {
402
+ console.error('Error setting up WebSocket', err);
403
+ if (reconnectAttempts < maxReconnectAttempts) {
404
+ const delay = calculateBackoffDelay(reconnectAttempts);
405
+ reconnectAttempts++;
406
+ setTimeout(connect, delay);
407
+ } else {
408
+ reject(err);
409
+ }
410
+ }
411
+ };
412
+
413
+ connect();
414
+ });
415
+ }
416
+
249
417
  rules = new WorkflowsRulesApi(this);
250
418
  definitions = new WorkflowsDefinitionApi(this);
251
419
  }
@@ -12,6 +12,7 @@ import { CollectionsApi } from "./CollectionsApi.js";
12
12
 
13
13
  export interface ZenoClientProps {
14
14
  serverUrl?: string;
15
+ tokenServerUrl?: string;
15
16
  apikey?: string;
16
17
  onRequest?: (request: Request) => void;
17
18
  onResponse?: (response: Response) => void;
@@ -56,6 +57,13 @@ export class ZenoClient extends AbstractFetchClient<ZenoClient> {
56
57
  });
57
58
  }
58
59
 
60
+ get initialHeaders() {
61
+ return {
62
+ ...super.initialHeaders,
63
+ 'X-Api-Version': '20250925' // YYYYMMDD, client versioning for API endpoints. Increment manually for breaking changes
64
+ }
65
+ }
66
+
59
67
  objects = new ObjectsApi(this);
60
68
  types = new TypesApi(this);
61
69
  workflows = new WorkflowsApi(this);
@@ -1,85 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const api_fetch_client_1 = require("@vertesia/api-fetch-client");
4
- class AccountApi extends api_fetch_client_1.ApiTopic {
5
- constructor(parent) {
6
- super(parent, "/api/v1/account");
7
- }
8
- /**
9
- * Retrieve all account information for current account
10
- * @returns Account[]
11
- */
12
- info() {
13
- return this.get('/');
14
- }
15
- /**
16
- * Update account information
17
- * @returns Account
18
- */
19
- update(payload) {
20
- return this.put('/', { payload });
21
- }
22
- /**
23
- * Get all projects for account
24
- */
25
- projects() {
26
- return this.get('/projects').then(res => res.data);
27
- }
28
- members() {
29
- return this.get('/members');
30
- }
31
- /**
32
- * Invite User to account
33
- */
34
- inviteUser(payload) {
35
- return this.post('/invites', { payload });
36
- }
37
- /**
38
- * Fetch Invites for Principal
39
- * @returns UserInviteTokenData[]
40
- * */
41
- listInvites() {
42
- return this.get('/invites');
43
- }
44
- /**
45
- * Fetch Invites for specific account or project
46
- * @param type Filter for the type of invitation, either "project" or "account"
47
- * @returns UserInviteTokenData[]
48
- * */
49
- listInvitation(type = "project") {
50
- return this.get(`/invites/${type}`);
51
- }
52
- /**
53
- * Accept Invite for account
54
- * @returns UserInviteTokenData
55
- * */
56
- acceptInvite(id) {
57
- return this.put(`/invites/${id}`);
58
- }
59
- /**
60
- * Delete Invite for account
61
- * @returns UserInviteTokenData
62
- * */
63
- rejectInvite(id) {
64
- return this.delete(`/invites/${id}`);
65
- }
66
- /**
67
- * Get Onboarding Progress for account
68
- */
69
- onboardingProgress() {
70
- return this.get('/onboarding');
71
- }
72
- /**
73
- * Get a google auth token for the current project.
74
- * This token can be used to access exposed google cloud services
75
- * @returns
76
- */
77
- getGoogleToken() {
78
- return this.get('/google-token');
79
- }
80
- getStripeBillingStatus() {
81
- return this.get('/stripe-billing-status');
82
- }
83
- }
84
- exports.default = AccountApi;
85
- //# sourceMappingURL=AccountApi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AccountApi.js","sourceRoot":"","sources":["../../src/AccountApi.ts"],"names":[],"mappings":";;AAAA,iEAAkE;AAGlE,MAAqB,UAAW,SAAQ,2BAAQ;IAE5C,YAAY,MAAkB;QAC1B,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAED;;;OAGG;IACH,IAAI;QACA,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAA6B;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACtC,CAAC;IAED;;MAEE;IACF,QAAQ;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IAC/B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,OAAiC;QACxC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED;;;SAGK;IACL,WAAW;QACP,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IACD;;;;SAIK;IACL,cAAc,CAAC,OAA8B,SAAS;QAClD,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAED;;;SAGK;IACL,YAAY,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC;IAED;;;SAGK;IACL,YAAY,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,kBAAkB;QACd,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,cAAc;QACV,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IAED,sBAAsB;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;IAC7C,CAAC;CAEJ;AA5FD,6BA4FC"}
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const api_fetch_client_1 = require("@vertesia/api-fetch-client");
4
- class AccountsApi extends api_fetch_client_1.ApiTopic {
5
- constructor(parent) {
6
- super(parent, "/api/v1/accounts");
7
- }
8
- create(name) {
9
- return this.post('/', { payload: { name } });
10
- }
11
- list() {
12
- return this.get('/');
13
- }
14
- }
15
- exports.default = AccountsApi;
16
- //# sourceMappingURL=AccountsApi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AccountsApi.js","sourceRoot":"","sources":["../../src/AccountsApi.ts"],"names":[],"mappings":";;AACA,iEAAkE;AAElE,MAAqB,WAAY,SAAQ,2BAAQ;IAE7C,YAAY,MAAkB;QAC1B,KAAK,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,CAAC,IAAY;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI;QACA,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;CAMJ;AAlBD,8BAkBC"}
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const api_fetch_client_1 = require("@vertesia/api-fetch-client");
4
- class AnalyticsApi extends api_fetch_client_1.ApiTopic {
5
- constructor(parent) {
6
- super(parent, "/api/v1/analytics");
7
- }
8
- runs(params) {
9
- return this.post('/runs', { payload: params });
10
- }
11
- }
12
- exports.default = AnalyticsApi;
13
- //# sourceMappingURL=AnalyticsApi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnalyticsApi.js","sourceRoot":"","sources":["../../src/AnalyticsApi.ts"],"names":[],"mappings":";;AACA,iEAAkE;AAKlE,MAAqB,YAAa,SAAQ,2BAAQ;IAE9C,YAAY,MAAkB;QAC1B,KAAK,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IACtC,CAAC;IAED,IAAI,CAAC,MAAyB;QAE1B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnD,CAAC;CAGJ;AAbD,+BAaC"}
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ApiKeysApi = void 0;
4
- const api_fetch_client_1 = require("@vertesia/api-fetch-client");
5
- class ApiKeysApi extends api_fetch_client_1.ApiTopic {
6
- constructor(parent) {
7
- super(parent, "/api/v1/apikeys");
8
- }
9
- /**
10
- * List all keys for account without values
11
- * @returns ApiKey[]
12
- */
13
- list(level = 'account') {
14
- return this.get('/', { query: { level } });
15
- }
16
- /**
17
- * Create an new ApiKey for account
18
- * BE VERY CAREFUL USING THIS API
19
- * ALL REQUESTS ARE LOGGED IN SECURITY AUDIT LOG
20
- * @returns ApiKeyWithValue
21
- */
22
- create(payload) {
23
- return this.post('/', { payload });
24
- }
25
- /**
26
- * Update an existing ApiKey for account
27
- * @returns ApiKey
28
- */
29
- update(id, payload) {
30
- return this.put(`/${id}`, { payload });
31
- }
32
- /**
33
- * Retrieve an ApiKey and its value
34
- * BE VERY CAREFUL USING THIS API AS IT EXPOSE THE API KEY VALUE
35
- * ALL REQUESTS ARE LOGGED IN SECURITY AUDIT LOG
36
- * @returns ApiKeyWithValue
37
- * */
38
- retrieve(id, withValue = false) {
39
- if (withValue) {
40
- return this.get(`/${id}`, { query: { withValue: true } });
41
- }
42
- else {
43
- return this.get(`/${id}`);
44
- }
45
- }
46
- /**
47
- * get or create a temporary public key which can be used from browser to browse and execute interactions.
48
- * If a public key already exists for the given project (or for the current organization) then it is returned, otherwise a new one is created.
49
- * The payload object can contain the following properties:
50
- * - name: the name of the public key. If not specified a random name is generated.
51
- * - projectId: the id of the project to which the public key will be associated.
52
- * If not specified the key is associated with the current organization. (i.e. account).
53
- * - ttl: the time to live of the public key in seconds.
54
- * The ttl defaults to 1h.
55
- * @param opts
56
- * @returns
57
- */
58
- requestPublicKey(payload = {}) {
59
- return this.get('/pk', { query: payload });
60
- }
61
- }
62
- exports.ApiKeysApi = ApiKeysApi;
63
- //# sourceMappingURL=ApiKeysApi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApiKeysApi.js","sourceRoot":"","sources":["../../src/ApiKeysApi.ts"],"names":[],"mappings":";;;AACA,iEAAkE;AAElE,MAAa,UAAW,SAAQ,2BAAQ;IAGpC,YAAY,MAAkB;QAC1B,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IACpC,CAAC;IAGD;;;OAGG;IACH,IAAI,CAAC,QAA+B,SAAS;QACzC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAAoC;QACvC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,EAAU,EAAE,OAAoC;QACnD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;SAKK;IACL,QAAQ,CAAC,EAAU,EAAE,YAAqB,KAAK;QAC3C,IAAI,SAAS,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACJ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,UAAkC,EAAE;QACjD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,OAA0C,EAAE,CAAC,CAAC;IAClF,CAAC;CACJ;AA/DD,gCA+DC"}
@@ -1,111 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const api_fetch_client_1 = require("@vertesia/api-fetch-client");
4
- class AppsApi extends api_fetch_client_1.ApiTopic {
5
- constructor(parent) {
6
- super(parent, "/api/v1/apps");
7
- }
8
- create(manifest) {
9
- return this.post('/', { payload: manifest });
10
- }
11
- update(id, manifest) {
12
- return this.put(`/${id}`, { payload: manifest });
13
- }
14
- /**
15
- * @param ids - ids to filter by
16
- * @returns the app manifests but without the agent.tool property which can be big.
17
- */
18
- list() {
19
- return this.get('/');
20
- }
21
- /**
22
- * Install the app with the given id in the current project.
23
- * @param appId - the id of the app to install
24
- */
25
- install(appId, settings) {
26
- return this.post(`/install`, {
27
- payload: {
28
- app_id: appId,
29
- settings
30
- }
31
- });
32
- }
33
- /**
34
- * Remove the given app from the current project.
35
- * @param installationId - the id of the app installation
36
- * @returns
37
- */
38
- uninstall(installationId) {
39
- return this.del(`/install/${installationId}`);
40
- }
41
- /**
42
- * get an app unstallation given its name or null if the app is not installed
43
- * @returns
44
- */
45
- getAppInstallationByName(appName) {
46
- return this.get(`/installations/name/${appName}`).catch((err) => {
47
- if (err.status === 404) {
48
- return null;
49
- }
50
- else {
51
- throw err;
52
- }
53
- });
54
- }
55
- /**
56
- * Get the project refs where the application is visible by the current user.
57
- * The application is specified either by id or by name.
58
- * @param param0
59
- * @returns
60
- */
61
- getAppInstallationProjects(app) {
62
- if (!app.id && !app.name) {
63
- throw new Error("Invalid arguments: appId or appName must be specified");
64
- }
65
- const query = app.id ? {
66
- id: app.id
67
- } : {
68
- name: app.name
69
- };
70
- return this.get("/installations/projects", {
71
- query
72
- });
73
- }
74
- /**
75
- * Get the apps installed for the current authenticated project
76
- * @param kind - the kind of app installations to filter by (e.g., 'agent', 'tool', etc.)
77
- */
78
- getInstalledApps(kind) {
79
- return this.get('/installations', {
80
- query: {
81
- kind,
82
- }
83
- });
84
- }
85
- /**
86
- * This operation will return an array of all the found AppInstallations in the current project
87
- * including orphaned installations
88
- * This requires project admin since access is not checked on the insytallations.
89
- * For a user level list of available installations (with user permission check) use getInstalledApps
90
- * @returns
91
- */
92
- getAllAppInstallations() {
93
- return this.get('/installations/all');
94
- }
95
- /**
96
- * List the app installations of the current project.
97
- */
98
- listInstallations() {
99
- return this.get('/installations/refs');
100
- }
101
- updateInstallationSettings(settingsPayload) {
102
- return this.put(`/installations/settings/${settingsPayload.app_id}`, {
103
- payload: {
104
- app_id: settingsPayload.app_id,
105
- settings: settingsPayload.settings
106
- }
107
- });
108
- }
109
- }
110
- exports.default = AppsApi;
111
- //# sourceMappingURL=AppsApi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AppsApi.js","sourceRoot":"","sources":["../../src/AppsApi.ts"],"names":[],"mappings":";;AAAA,iEAA+E;AAO/E,MAAqB,OAAQ,SAAQ,2BAAQ;IAEzC,YAAY,MAAkB;QAC1B,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACjC,CAAC;IAED,MAAM,CAAC,QAAyB;QAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,CAAC,EAAU,EAAE,QAAyB;QACxC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;IAED;;;OAGG;IACH,IAAI;QACA,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,KAAa,EAAE,QAA8B;QACjD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACzB,OAAO,EAAE;gBACL,MAAM,EAAE,KAAK;gBACb,QAAQ;aACsB;SACrC,CAAC,CAAC;IACP,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,cAAsB;QAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,cAAc,EAAE,CAAC,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,wBAAwB,CAAC,OAAe;QACpC,OAAO,IAAI,CAAC,GAAG,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAgB,EAAE,EAAE;YACzE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,CAAC;YACd,CAAC;QACL,CAAC,CAAC,CAAA;IACN,CAAC;IAED;;;;;OAKG;IACH,0BAA0B,CAAC,GAAqE;QAC5F,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACnB,EAAE,EAAE,GAAG,CAAC,EAAE;SACb,CAAC,CAAC,CAAC;YACA,IAAI,EAAE,GAAG,CAAC,IAAI;SACjB,CAAA;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE;YACvC,KAAK;SACR,CAAC,CAAC;IACP,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,IAA0B;QACvC,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE;YAC9B,KAAK,EAAE;gBACH,IAAI;aACP;SACJ,CAAC,CAAC;IACP,CAAC;IAED;;;;;;OAMG;IACH,sBAAsB;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,iBAAiB;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAC3C,CAAC;IAED,0BAA0B,CAAC,eAAuC;QAC9D,OAAO,IAAI,CAAC,GAAG,CAAC,2BAA2B,eAAe,CAAC,MAAM,EAAE,EAAE;YACjE,OAAO,EAAE;gBACL,MAAM,EAAE,eAAe,CAAC,MAAM;gBAC9B,QAAQ,EAAE,eAAe,CAAC,QAAQ;aACJ;SACrC,CAAC,CAAC;IACP,CAAC;CAEJ;AArHD,0BAqHC"}