@lichen-ai/lichen-sdk 0.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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/dist/auth/error.d.ts +9 -0
  3. package/dist/auth/error.js +76 -0
  4. package/dist/auth/error.js.map +1 -0
  5. package/dist/auth/error.mjs +76 -0
  6. package/dist/auth/error.mjs.map +1 -0
  7. package/dist/auth/index.d.ts +18 -0
  8. package/dist/auth/index.js +35 -0
  9. package/dist/auth/index.js.map +1 -0
  10. package/dist/auth/index.mjs +35 -0
  11. package/dist/auth/index.mjs.map +1 -0
  12. package/dist/auth/types.d.ts +297 -0
  13. package/dist/auth/types.js +2 -0
  14. package/dist/auth/types.js.map +1 -0
  15. package/dist/auth/types.mjs +2 -0
  16. package/dist/auth/types.mjs.map +1 -0
  17. package/dist/client.d.ts +773 -0
  18. package/dist/client.js +1544 -0
  19. package/dist/client.js.map +1 -0
  20. package/dist/client.mjs +1544 -0
  21. package/dist/client.mjs.map +1 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.js +3 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/index.mjs +3 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/logging/index.d.ts +43 -0
  28. package/dist/logging/index.js +33 -0
  29. package/dist/logging/index.js.map +1 -0
  30. package/dist/logging/index.mjs +33 -0
  31. package/dist/logging/index.mjs.map +1 -0
  32. package/dist/schema.d.ts +661 -0
  33. package/dist/schema.js +30 -0
  34. package/dist/schema.js.map +1 -0
  35. package/dist/schema.mjs +30 -0
  36. package/dist/schema.mjs.map +1 -0
  37. package/dist/singletons/fetch.d.ts +7 -0
  38. package/dist/singletons/fetch.js +24 -0
  39. package/dist/singletons/fetch.js.map +1 -0
  40. package/dist/singletons/fetch.mjs +24 -0
  41. package/dist/singletons/fetch.mjs.map +1 -0
  42. package/dist/tests/fetch.test.d.ts +1 -0
  43. package/dist/tests/fetch.test.js +460 -0
  44. package/dist/tests/fetch.test.js.map +1 -0
  45. package/dist/tests/fetch.test.mjs +460 -0
  46. package/dist/tests/fetch.test.mjs.map +1 -0
  47. package/dist/tests/sse.test.d.ts +1 -0
  48. package/dist/tests/sse.test.js +132 -0
  49. package/dist/tests/sse.test.js.map +1 -0
  50. package/dist/tests/sse.test.mjs +132 -0
  51. package/dist/tests/sse.test.mjs.map +1 -0
  52. package/dist/types.d.ts +178 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/types.messages.d.ts +86 -0
  56. package/dist/types.messages.js +2 -0
  57. package/dist/types.messages.js.map +1 -0
  58. package/dist/types.messages.mjs +2 -0
  59. package/dist/types.messages.mjs.map +1 -0
  60. package/dist/types.mjs +2 -0
  61. package/dist/types.mjs.map +1 -0
  62. package/dist/types.stream.d.ts +212 -0
  63. package/dist/types.stream.js +2 -0
  64. package/dist/types.stream.js.map +1 -0
  65. package/dist/types.stream.mjs +2 -0
  66. package/dist/types.stream.mjs.map +1 -0
  67. package/dist/ui/branching.d.ts +35 -0
  68. package/dist/ui/branching.js +143 -0
  69. package/dist/ui/branching.js.map +1 -0
  70. package/dist/ui/branching.mjs +143 -0
  71. package/dist/ui/branching.mjs.map +1 -0
  72. package/dist/ui/branching.test.d.ts +1 -0
  73. package/dist/ui/branching.test.js +369 -0
  74. package/dist/ui/branching.test.js.map +1 -0
  75. package/dist/ui/branching.test.mjs +369 -0
  76. package/dist/ui/branching.test.mjs.map +1 -0
  77. package/dist/ui/errors.d.ts +12 -0
  78. package/dist/ui/errors.js +10 -0
  79. package/dist/ui/errors.js.map +1 -0
  80. package/dist/ui/errors.mjs +10 -0
  81. package/dist/ui/errors.mjs.map +1 -0
  82. package/dist/ui/manager.d.ts +87 -0
  83. package/dist/ui/manager.js +158 -0
  84. package/dist/ui/manager.js.map +1 -0
  85. package/dist/ui/manager.mjs +158 -0
  86. package/dist/ui/manager.mjs.map +1 -0
  87. package/dist/ui/messages.d.ts +18 -0
  88. package/dist/ui/messages.js +64 -0
  89. package/dist/ui/messages.js.map +1 -0
  90. package/dist/ui/messages.mjs +64 -0
  91. package/dist/ui/messages.mjs.map +1 -0
  92. package/dist/ui/utils.d.ts +2 -0
  93. package/dist/ui/utils.js +11 -0
  94. package/dist/ui/utils.js.map +1 -0
  95. package/dist/ui/utils.mjs +11 -0
  96. package/dist/ui/utils.mjs.map +1 -0
  97. package/dist/utils/async_caller.d.ts +48 -0
  98. package/dist/utils/async_caller.js +153 -0
  99. package/dist/utils/async_caller.js.map +1 -0
  100. package/dist/utils/async_caller.mjs +153 -0
  101. package/dist/utils/async_caller.mjs.map +1 -0
  102. package/dist/utils/env.d.ts +1 -0
  103. package/dist/utils/env.js +13 -0
  104. package/dist/utils/env.js.map +1 -0
  105. package/dist/utils/env.mjs +13 -0
  106. package/dist/utils/env.mjs.map +1 -0
  107. package/dist/utils/signals.d.ts +1 -0
  108. package/dist/utils/signals.js +19 -0
  109. package/dist/utils/signals.js.map +1 -0
  110. package/dist/utils/signals.mjs +19 -0
  111. package/dist/utils/signals.mjs.map +1 -0
  112. package/dist/utils/sse.d.ts +8 -0
  113. package/dist/utils/sse.js +151 -0
  114. package/dist/utils/sse.js.map +1 -0
  115. package/dist/utils/sse.mjs +151 -0
  116. package/dist/utils/sse.mjs.map +1 -0
  117. package/dist/utils/stream.d.ts +13 -0
  118. package/dist/utils/stream.js +109 -0
  119. package/dist/utils/stream.js.map +1 -0
  120. package/dist/utils/stream.mjs +109 -0
  121. package/dist/utils/stream.mjs.map +1 -0
  122. package/package.json +63 -0
@@ -0,0 +1,1544 @@
1
+ import { AsyncCaller } from "./utils/async_caller.mjs";
2
+ import { getEnvironmentVariable } from "./utils/env.mjs";
3
+ import { mergeSignals } from "./utils/signals.mjs";
4
+ import { BytesLineDecoder, SSEDecoder } from "./utils/sse.mjs";
5
+ import { IterableReadableStream } from "./utils/stream.mjs";
6
+ function* iterateHeaders(headers) {
7
+ let iter;
8
+ let shouldClear = false;
9
+ // eslint-disable-next-line no-instanceof/no-instanceof
10
+ if (headers instanceof Headers) {
11
+ const entries = [];
12
+ headers.forEach((value, name) => {
13
+ entries.push([name, value]);
14
+ });
15
+ iter = entries;
16
+ }
17
+ else if (Array.isArray(headers)) {
18
+ iter = headers;
19
+ }
20
+ else {
21
+ shouldClear = true;
22
+ iter = Object.entries(headers ?? {});
23
+ }
24
+ for (const item of iter) {
25
+ const name = item[0];
26
+ if (typeof name !== 'string')
27
+ throw new TypeError(`Expected header name to be a string, got ${typeof name}`);
28
+ const values = Array.isArray(item[1]) ? item[1] : [item[1]];
29
+ let didClear = false;
30
+ for (const value of values) {
31
+ if (value === undefined)
32
+ continue;
33
+ // New object keys should always overwrite older headers
34
+ // Yield a null to clear the header in the headers object
35
+ // before adding the new value
36
+ if (shouldClear && !didClear) {
37
+ didClear = true;
38
+ yield [name, null];
39
+ }
40
+ yield [name, value];
41
+ }
42
+ }
43
+ }
44
+ function mergeHeaders(...headerObjects) {
45
+ const outputHeaders = new Headers();
46
+ for (const headers of headerObjects) {
47
+ if (!headers)
48
+ continue;
49
+ for (const [name, value] of iterateHeaders(headers)) {
50
+ if (value === null)
51
+ outputHeaders.delete(name);
52
+ else
53
+ outputHeaders.append(name, value);
54
+ }
55
+ }
56
+ const headerEntries = [];
57
+ outputHeaders.forEach((value, name) => {
58
+ headerEntries.push([name, value]);
59
+ });
60
+ return Object.fromEntries(headerEntries);
61
+ }
62
+ /**
63
+ * Get the API key from the environment.
64
+ * Precedence:
65
+ * 1. explicit argument
66
+ * 2. LANGGRAPH_API_KEY
67
+ * 3. LANGSMITH_API_KEY
68
+ * 4. LANGCHAIN_API_KEY
69
+ *
70
+ * @param apiKey - Optional API key provided as an argument
71
+ * @returns The API key if found, otherwise undefined
72
+ */
73
+ export function getApiKey(apiKey) {
74
+ if (apiKey) {
75
+ return apiKey;
76
+ }
77
+ const prefixes = ['LANGGRAPH', 'LANGSMITH', 'LANGCHAIN'];
78
+ for (const prefix of prefixes) {
79
+ const envKey = getEnvironmentVariable(`${prefix}_API_KEY`);
80
+ if (envKey) {
81
+ // Remove surrounding quotes
82
+ return envKey.trim().replace(/^["']|["']$/g, '');
83
+ }
84
+ }
85
+ return undefined;
86
+ }
87
+ const REGEX_RUN_METADATA = /(\/threads\/(?<thread_id>.+))?\/runs\/(?<run_id>.+)/;
88
+ function getRunMetadataFromResponse(response) {
89
+ const contentLocation = response.headers.get('Content-Location');
90
+ if (!contentLocation)
91
+ return undefined;
92
+ const match = REGEX_RUN_METADATA.exec(contentLocation);
93
+ if (!match?.groups?.run_id)
94
+ return undefined;
95
+ return {
96
+ run_id: match.groups.run_id,
97
+ thread_id: match.groups.thread_id || undefined
98
+ };
99
+ }
100
+ function deriveSandboxApiUrl(apiUrl) {
101
+ if (!apiUrl)
102
+ return undefined;
103
+ const normalized = apiUrl.replace(/\/+$/, '');
104
+ if (normalized.endsWith('/api/ai')) {
105
+ return `${normalized.slice(0, -'/api/ai'.length)}/api/sandbox`;
106
+ }
107
+ return normalized;
108
+ }
109
+ class BaseClient {
110
+ asyncCaller;
111
+ timeoutMs;
112
+ apiUrl;
113
+ defaultHeaders;
114
+ onRequest;
115
+ constructor(config) {
116
+ const callerOptions = {
117
+ maxRetries: 4,
118
+ maxConcurrency: 4,
119
+ ...config?.callerOptions
120
+ };
121
+ let defaultApiUrl = 'http://localhost:8123';
122
+ if (!config?.apiUrl && typeof globalThis === 'object' && globalThis != null) {
123
+ const fetchSmb = Symbol.for('langgraph_api:fetch');
124
+ const urlSmb = Symbol.for('langgraph_api:url');
125
+ const global = globalThis;
126
+ if (global[fetchSmb])
127
+ callerOptions.fetch ??= global[fetchSmb];
128
+ if (global[urlSmb])
129
+ defaultApiUrl = global[urlSmb];
130
+ }
131
+ this.asyncCaller = new AsyncCaller(callerOptions);
132
+ this.timeoutMs = config?.timeoutMs;
133
+ // default limit being capped by Chrome
134
+ // https://github.com/nodejs/undici/issues/1373
135
+ // Regex to remove trailing slash, if present
136
+ this.apiUrl = config?.apiUrl?.replace(/\/$/, '') || defaultApiUrl;
137
+ this.defaultHeaders = config?.defaultHeaders || {};
138
+ this.onRequest = config?.onRequest;
139
+ const apiKey = getApiKey(config?.apiKey);
140
+ if (apiKey) {
141
+ this.defaultHeaders['x-api-key'] = apiKey;
142
+ }
143
+ }
144
+ prepareFetchOptions(path, options) {
145
+ const mutatedOptions = {
146
+ ...options,
147
+ headers: mergeHeaders(this.defaultHeaders, options?.headers)
148
+ };
149
+ if (mutatedOptions.json) {
150
+ mutatedOptions.body = JSON.stringify(mutatedOptions.json);
151
+ mutatedOptions.headers = mergeHeaders(mutatedOptions.headers, {
152
+ 'content-type': 'application/json'
153
+ });
154
+ delete mutatedOptions.json;
155
+ }
156
+ if (mutatedOptions.withResponse) {
157
+ delete mutatedOptions.withResponse;
158
+ }
159
+ let timeoutSignal = null;
160
+ if (typeof options?.timeoutMs !== 'undefined') {
161
+ if (options.timeoutMs != null) {
162
+ timeoutSignal = AbortSignal.timeout(options.timeoutMs);
163
+ }
164
+ }
165
+ else if (this.timeoutMs != null) {
166
+ timeoutSignal = AbortSignal.timeout(this.timeoutMs);
167
+ }
168
+ mutatedOptions.signal = mergeSignals(timeoutSignal, mutatedOptions.signal);
169
+ const targetUrl = new URL(`${this.apiUrl}${path}`);
170
+ if (mutatedOptions.params) {
171
+ for (const [key, value] of Object.entries(mutatedOptions.params)) {
172
+ if (value == null)
173
+ continue;
174
+ const strValue = typeof value === 'string' || typeof value === 'number' ? value.toString() : JSON.stringify(value);
175
+ targetUrl.searchParams.append(key, strValue);
176
+ }
177
+ delete mutatedOptions.params;
178
+ }
179
+ return [targetUrl, mutatedOptions];
180
+ }
181
+ async fetch(path, options) {
182
+ const [url, init] = this.prepareFetchOptions(path, options);
183
+ let finalInit = init;
184
+ if (this.onRequest) {
185
+ finalInit = await this.onRequest(url, init);
186
+ }
187
+ const response = await this.asyncCaller.fetch(url, finalInit);
188
+ const body = (() => {
189
+ if (response.status === 202 || response.status === 204) {
190
+ return undefined;
191
+ }
192
+ return response.json();
193
+ })();
194
+ if (options?.withResponse) {
195
+ return [await body, response];
196
+ }
197
+ return body;
198
+ }
199
+ }
200
+ export class CronsClient extends BaseClient {
201
+ /**
202
+ *
203
+ * @param threadId The ID of the thread.
204
+ * @param assistantId Assistant ID to use for this cron job.
205
+ * @param payload Payload for creating a cron job.
206
+ * @returns The created background run.
207
+ */
208
+ async createForThread(threadId, assistantId, payload) {
209
+ const json = {
210
+ schedule: payload?.schedule,
211
+ input: payload?.input,
212
+ config: payload?.config,
213
+ context: payload?.context,
214
+ metadata: payload?.metadata,
215
+ assistant_id: assistantId,
216
+ interrupt_before: payload?.interruptBefore,
217
+ interrupt_after: payload?.interruptAfter,
218
+ webhook: payload?.webhook,
219
+ multitask_strategy: payload?.multitaskStrategy,
220
+ if_not_exists: payload?.ifNotExists,
221
+ checkpoint_during: payload?.checkpointDuring,
222
+ durability: payload?.durability
223
+ };
224
+ return this.fetch(`/threads/${threadId}/runs/crons`, {
225
+ method: 'POST',
226
+ json
227
+ });
228
+ }
229
+ /**
230
+ *
231
+ * @param assistantId Assistant ID to use for this cron job.
232
+ * @param payload Payload for creating a cron job.
233
+ * @returns
234
+ */
235
+ async create(assistantId, payload) {
236
+ const json = {
237
+ schedule: payload?.schedule,
238
+ input: payload?.input,
239
+ config: payload?.config,
240
+ context: payload?.context,
241
+ metadata: payload?.metadata,
242
+ assistant_id: assistantId,
243
+ interrupt_before: payload?.interruptBefore,
244
+ interrupt_after: payload?.interruptAfter,
245
+ webhook: payload?.webhook,
246
+ multitask_strategy: payload?.multitaskStrategy,
247
+ if_not_exists: payload?.ifNotExists,
248
+ checkpoint_during: payload?.checkpointDuring,
249
+ durability: payload?.durability
250
+ };
251
+ return this.fetch(`/runs/crons`, {
252
+ method: 'POST',
253
+ json
254
+ });
255
+ }
256
+ /**
257
+ *
258
+ * @param cronId Cron ID of Cron job to delete.
259
+ */
260
+ async delete(cronId) {
261
+ await this.fetch(`/runs/crons/${cronId}`, {
262
+ method: 'DELETE'
263
+ });
264
+ }
265
+ /**
266
+ *
267
+ * @param query Query options.
268
+ * @returns List of crons.
269
+ */
270
+ async search(query) {
271
+ return this.fetch('/runs/crons/search', {
272
+ method: 'POST',
273
+ json: {
274
+ assistant_id: query?.assistantId ?? undefined,
275
+ thread_id: query?.threadId ?? undefined,
276
+ limit: query?.limit ?? 10,
277
+ offset: query?.offset ?? 0,
278
+ sort_by: query?.sortBy ?? undefined,
279
+ sort_order: query?.sortOrder ?? undefined,
280
+ select: query?.select ?? undefined
281
+ }
282
+ });
283
+ }
284
+ /**
285
+ * Count cron jobs matching filters.
286
+ *
287
+ * @param query.assistantId Assistant ID to filter by.
288
+ * @param query.threadId Thread ID to filter by.
289
+ * @returns Number of cron jobs matching the criteria.
290
+ */
291
+ async count(query) {
292
+ return this.fetch(`/runs/crons/count`, {
293
+ method: 'POST',
294
+ json: {
295
+ assistant_id: query?.assistantId ?? undefined,
296
+ thread_id: query?.threadId ?? undefined
297
+ }
298
+ });
299
+ }
300
+ }
301
+ export class AssistantsClient extends BaseClient {
302
+ /**
303
+ * Get an assistant by ID.
304
+ *
305
+ * @param assistantId The ID of the assistant.
306
+ * @returns Assistant
307
+ */
308
+ async get(assistantId) {
309
+ return this.fetch(`/assistants/${assistantId}`);
310
+ }
311
+ /**
312
+ * Get the JSON representation of the graph assigned to a runnable
313
+ * @param assistantId The ID of the assistant.
314
+ * @param options.xray Whether to include subgraphs in the serialized graph representation. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included.
315
+ * @returns Serialized graph
316
+ */
317
+ async getGraph(assistantId, options) {
318
+ return this.fetch(`/assistants/${assistantId}/graph`, {
319
+ params: { xray: options?.xray }
320
+ });
321
+ }
322
+ /**
323
+ * Get the state and config schema of the graph assigned to a runnable
324
+ * @param assistantId The ID of the assistant.
325
+ * @returns Graph schema
326
+ */
327
+ async getSchemas(assistantId) {
328
+ return this.fetch(`/assistants/${assistantId}/schemas`);
329
+ }
330
+ /**
331
+ * Get runtime-selectable skills and plugin middlewares for an assistant.
332
+ *
333
+ * @param assistantId The ID of the assistant.
334
+ * @param options.signal Optional abort signal.
335
+ * @returns Runtime capabilities available to the assistant.
336
+ */
337
+ async getRuntimeCapabilities(assistantId, options) {
338
+ return this.fetch(`/assistants/${assistantId}/runtime-capabilities`, {
339
+ signal: options?.signal
340
+ });
341
+ }
342
+ /**
343
+ * Get the schemas of an assistant by ID.
344
+ *
345
+ * @param assistantId The ID of the assistant to get the schema of.
346
+ * @param options Additional options for getting subgraphs, such as namespace or recursion extraction.
347
+ * @returns The subgraphs of the assistant.
348
+ */
349
+ async getSubgraphs(assistantId, options) {
350
+ if (options?.namespace) {
351
+ return this.fetch(`/assistants/${assistantId}/subgraphs/${options.namespace}`, {
352
+ params: { recurse: options?.recurse }
353
+ });
354
+ }
355
+ return this.fetch(`/assistants/${assistantId}/subgraphs`, {
356
+ params: { recurse: options?.recurse }
357
+ });
358
+ }
359
+ /**
360
+ * Create a new assistant.
361
+ * @param payload Payload for creating an assistant.
362
+ * @returns The created assistant.
363
+ */
364
+ async create(payload) {
365
+ return this.fetch('/assistants', {
366
+ method: 'POST',
367
+ json: {
368
+ graph_id: payload.graphId,
369
+ config: payload.config,
370
+ context: payload.context,
371
+ metadata: payload.metadata,
372
+ assistant_id: payload.assistantId,
373
+ if_exists: payload.ifExists,
374
+ name: payload.name,
375
+ description: payload.description
376
+ }
377
+ });
378
+ }
379
+ /**
380
+ * Update an assistant.
381
+ * @param assistantId ID of the assistant.
382
+ * @param payload Payload for updating the assistant.
383
+ * @returns The updated assistant.
384
+ */
385
+ async update(assistantId, payload) {
386
+ return this.fetch(`/assistants/${assistantId}`, {
387
+ method: 'PATCH',
388
+ json: {
389
+ graph_id: payload.graphId,
390
+ config: payload.config,
391
+ context: payload.context,
392
+ metadata: payload.metadata,
393
+ name: payload.name,
394
+ description: payload.description
395
+ }
396
+ });
397
+ }
398
+ /**
399
+ * Delete an assistant.
400
+ *
401
+ * @param assistantId ID of the assistant.
402
+ */
403
+ async delete(assistantId) {
404
+ return this.fetch(`/assistants/${assistantId}`, {
405
+ method: 'DELETE'
406
+ });
407
+ }
408
+ /**
409
+ * List assistants.
410
+ * @param query Query options.
411
+ * @returns List of assistants.
412
+ */
413
+ async search(query) {
414
+ return this.fetch('/assistants/search', {
415
+ method: 'POST',
416
+ json: {
417
+ graph_id: query?.graphId ?? undefined,
418
+ metadata: query?.metadata ?? undefined,
419
+ limit: query?.limit ?? 10,
420
+ offset: query?.offset ?? 0,
421
+ sort_by: query?.sortBy ?? undefined,
422
+ sort_order: query?.sortOrder ?? undefined,
423
+ select: query?.select ?? undefined
424
+ }
425
+ });
426
+ }
427
+ /**
428
+ * Count assistants matching filters.
429
+ *
430
+ * @param query.metadata Metadata to filter by. Exact match for each key/value.
431
+ * @param query.graphId Optional graph id to filter by.
432
+ * @returns Number of assistants matching the criteria.
433
+ */
434
+ async count(query) {
435
+ return this.fetch(`/assistants/count`, {
436
+ method: 'POST',
437
+ json: {
438
+ metadata: query?.metadata ?? undefined,
439
+ graph_id: query?.graphId ?? undefined
440
+ }
441
+ });
442
+ }
443
+ /**
444
+ * List all versions of an assistant.
445
+ *
446
+ * @param assistantId ID of the assistant.
447
+ * @returns List of assistant versions.
448
+ */
449
+ async getVersions(assistantId, payload) {
450
+ return this.fetch(`/assistants/${assistantId}/versions`, {
451
+ method: 'POST',
452
+ json: {
453
+ metadata: payload?.metadata ?? undefined,
454
+ limit: payload?.limit ?? 10,
455
+ offset: payload?.offset ?? 0
456
+ }
457
+ });
458
+ }
459
+ /**
460
+ * Change the version of an assistant.
461
+ *
462
+ * @param assistantId ID of the assistant.
463
+ * @param version The version to change to.
464
+ * @returns The updated assistant.
465
+ */
466
+ async setLatest(assistantId, version) {
467
+ return this.fetch(`/assistants/${assistantId}/latest`, {
468
+ method: 'POST',
469
+ json: { version }
470
+ });
471
+ }
472
+ }
473
+ export class ThreadsClient extends BaseClient {
474
+ /**
475
+ * Get a thread by ID.
476
+ *
477
+ * @param threadId ID of the thread.
478
+ * @returns The thread.
479
+ */
480
+ async get(threadId) {
481
+ return this.fetch(`/threads/${threadId}`);
482
+ }
483
+ /**
484
+ * Get latest-run context usage for a agent in thread.
485
+ *
486
+ * @param threadId ID of the thread.
487
+ * @param options.agentKey Agent key for usage filtering.
488
+ * @returns Context usage summary for the latest run tree.
489
+ */
490
+ async getContextUsage(threadId, options) {
491
+ return this.fetch(`/threads/${threadId}/context-usage`, {
492
+ params: {
493
+ agentKey: options?.agentKey
494
+ }
495
+ });
496
+ }
497
+ /**
498
+ * Create a new thread.
499
+ *
500
+ * @param payload Payload for creating a thread.
501
+ * @returns The created thread.
502
+ */
503
+ async create(payload) {
504
+ // Normalize ttl to an object if a number is provided
505
+ const ttlPayload = typeof payload?.ttl === 'number' ? { ttl: payload.ttl, strategy: 'delete' } : payload?.ttl;
506
+ return this.fetch(`/threads`, {
507
+ method: 'POST',
508
+ json: {
509
+ metadata: {
510
+ ...payload?.metadata,
511
+ graph_id: payload?.graphId
512
+ },
513
+ thread_id: payload?.threadId,
514
+ if_exists: payload?.ifExists,
515
+ supersteps: payload?.supersteps?.map((s) => ({
516
+ updates: s.updates.map((u) => ({
517
+ values: u.values,
518
+ command: u.command,
519
+ as_node: u.asNode
520
+ }))
521
+ })),
522
+ ttl: ttlPayload
523
+ }
524
+ });
525
+ }
526
+ /**
527
+ * Copy an existing thread
528
+ * @param threadId ID of the thread to be copied
529
+ * @returns Newly copied thread
530
+ */
531
+ async copy(threadId) {
532
+ return this.fetch(`/threads/${threadId}/copy`, {
533
+ method: 'POST'
534
+ });
535
+ }
536
+ /**
537
+ * Update a thread.
538
+ *
539
+ * @param threadId ID of the thread.
540
+ * @param payload Payload for updating the thread.
541
+ * @returns The updated thread.
542
+ */
543
+ async update(threadId, payload) {
544
+ const ttlPayload = typeof payload?.ttl === 'number' ? { ttl: payload.ttl, strategy: 'delete' } : payload?.ttl;
545
+ return this.fetch(`/threads/${threadId}`, {
546
+ method: 'PATCH',
547
+ json: { metadata: payload?.metadata, ttl: ttlPayload }
548
+ });
549
+ }
550
+ /**
551
+ * Delete a thread.
552
+ *
553
+ * @param threadId ID of the thread.
554
+ */
555
+ async delete(threadId) {
556
+ return this.fetch(`/threads/${threadId}`, {
557
+ method: 'DELETE'
558
+ });
559
+ }
560
+ /**
561
+ * List threads
562
+ *
563
+ * @param query Query options
564
+ * @returns List of threads
565
+ */
566
+ async search(query) {
567
+ return this.fetch('/threads/search', {
568
+ method: 'POST',
569
+ json: {
570
+ metadata: query?.metadata ?? undefined,
571
+ ids: query?.ids ?? undefined,
572
+ limit: query?.limit ?? 10,
573
+ offset: query?.offset ?? 0,
574
+ status: query?.status,
575
+ sort_by: query?.sortBy,
576
+ sort_order: query?.sortOrder,
577
+ select: query?.select ?? undefined
578
+ }
579
+ });
580
+ }
581
+ /**
582
+ * Count threads matching filters.
583
+ *
584
+ * @param query.metadata Thread metadata to filter on.
585
+ * @param query.values State values to filter on.
586
+ * @param query.status Thread status to filter on.
587
+ * @returns Number of threads matching the criteria.
588
+ */
589
+ async count(query) {
590
+ return this.fetch(`/threads/count`, {
591
+ method: 'POST',
592
+ json: {
593
+ metadata: query?.metadata ?? undefined,
594
+ values: query?.values ?? undefined,
595
+ status: query?.status ?? undefined
596
+ }
597
+ });
598
+ }
599
+ /**
600
+ * Get state for a thread.
601
+ *
602
+ * @param threadId ID of the thread.
603
+ * @returns Thread state.
604
+ */
605
+ async getState(threadId, checkpoint, options) {
606
+ if (checkpoint != null) {
607
+ if (typeof checkpoint !== 'string') {
608
+ return this.fetch(`/threads/${threadId}/state/checkpoint`, {
609
+ method: 'POST',
610
+ json: { checkpoint, subgraphs: options?.subgraphs }
611
+ });
612
+ }
613
+ // deprecated
614
+ return this.fetch(`/threads/${threadId}/state/${checkpoint}`, {
615
+ params: { subgraphs: options?.subgraphs }
616
+ });
617
+ }
618
+ return this.fetch(`/threads/${threadId}/state`, {
619
+ params: { subgraphs: options?.subgraphs }
620
+ });
621
+ }
622
+ /**
623
+ * Add state to a thread.
624
+ *
625
+ * @param threadId The ID of the thread.
626
+ * @returns
627
+ */
628
+ async updateState(threadId, options) {
629
+ return this.fetch(`/threads/${threadId}/state`, {
630
+ method: 'POST',
631
+ json: {
632
+ values: options.values,
633
+ checkpoint_id: options.checkpointId,
634
+ checkpoint: options.checkpoint,
635
+ as_node: options?.asNode
636
+ }
637
+ });
638
+ }
639
+ /**
640
+ * Patch the metadata of a thread.
641
+ *
642
+ * @param threadIdOrConfig Thread ID or config to patch the state of.
643
+ * @param metadata Metadata to patch the state with.
644
+ */
645
+ async patchState(threadIdOrConfig, metadata) {
646
+ let threadId;
647
+ if (typeof threadIdOrConfig !== 'string') {
648
+ if (typeof threadIdOrConfig.configurable?.thread_id !== 'string') {
649
+ throw new Error('Thread ID is required when updating state with a config.');
650
+ }
651
+ threadId = threadIdOrConfig.configurable.thread_id;
652
+ }
653
+ else {
654
+ threadId = threadIdOrConfig;
655
+ }
656
+ return this.fetch(`/threads/${threadId}/state`, {
657
+ method: 'PATCH',
658
+ json: { metadata }
659
+ });
660
+ }
661
+ /**
662
+ * Get all past states for a thread.
663
+ *
664
+ * @param threadId ID of the thread.
665
+ * @param options Additional options.
666
+ * @returns List of thread states.
667
+ */
668
+ async getHistory(threadId, options) {
669
+ return this.fetch(`/threads/${threadId}/history`, {
670
+ method: 'POST',
671
+ json: {
672
+ limit: options?.limit ?? 10,
673
+ before: options?.before,
674
+ metadata: options?.metadata,
675
+ checkpoint: options?.checkpoint
676
+ }
677
+ });
678
+ }
679
+ async *joinStream(threadId, options
680
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
681
+ ) {
682
+ let [url, init] = this.prepareFetchOptions(`/threads/${threadId}/stream`, {
683
+ method: 'GET',
684
+ headers: options?.lastEventId ? { 'Last-Event-ID': options.lastEventId } : undefined,
685
+ params: options?.streamMode ? { stream_mode: options.streamMode } : undefined
686
+ });
687
+ if (this.onRequest != null)
688
+ init = await this.onRequest(url, init);
689
+ const response = await this.asyncCaller.fetch(url, init);
690
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
691
+ const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
692
+ .pipeThrough(BytesLineDecoder())
693
+ .pipeThrough(SSEDecoder());
694
+ yield* IterableReadableStream.fromReadableStream(stream);
695
+ }
696
+ }
697
+ export class RunsClient extends BaseClient {
698
+ /**
699
+ * Create a run and stream the results.
700
+ *
701
+ * @param threadId The ID of the thread.
702
+ * @param assistantId Assistant ID to use for this run.
703
+ * @param payload Payload for creating a run.
704
+ */
705
+ async *stream(threadId, assistantId, payload) {
706
+ const json = {
707
+ input: payload?.input,
708
+ command: payload?.command,
709
+ config: payload?.config,
710
+ context: payload?.context,
711
+ metadata: payload?.metadata,
712
+ stream_mode: payload?.streamMode,
713
+ stream_subgraphs: payload?.streamSubgraphs,
714
+ stream_resumable: payload?.streamResumable,
715
+ feedback_keys: payload?.feedbackKeys,
716
+ assistant_id: assistantId,
717
+ interrupt_before: payload?.interruptBefore,
718
+ interrupt_after: payload?.interruptAfter,
719
+ checkpoint: payload?.checkpoint,
720
+ checkpoint_id: payload?.checkpointId,
721
+ webhook: payload?.webhook,
722
+ multitask_strategy: payload?.multitaskStrategy,
723
+ on_completion: payload?.onCompletion,
724
+ on_disconnect: payload?.onDisconnect,
725
+ after_seconds: payload?.afterSeconds,
726
+ if_not_exists: payload?.ifNotExists,
727
+ checkpoint_during: payload?.checkpointDuring,
728
+ durability: payload?.durability
729
+ };
730
+ const endpoint = threadId == null ? `/runs/stream` : `/threads/${threadId}/runs/stream`;
731
+ let [url, init] = this.prepareFetchOptions(endpoint, {
732
+ method: 'POST',
733
+ json,
734
+ timeoutMs: null,
735
+ signal: payload?.signal
736
+ });
737
+ if (this.onRequest != null)
738
+ init = await this.onRequest(url, init);
739
+ const response = await this.asyncCaller.fetch(url, init);
740
+ const runMetadata = getRunMetadataFromResponse(response);
741
+ if (runMetadata)
742
+ payload?.onRunCreated?.(runMetadata);
743
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
744
+ const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
745
+ .pipeThrough(BytesLineDecoder())
746
+ .pipeThrough(SSEDecoder());
747
+ yield* IterableReadableStream.fromReadableStream(stream);
748
+ }
749
+ /**
750
+ * Create a run.
751
+ *
752
+ * @param threadId The ID of the thread.
753
+ * @param assistantId Assistant ID to use for this run.
754
+ * @param payload Payload for creating a run.
755
+ * @returns The created run.
756
+ */
757
+ async create(threadId, assistantId, payload) {
758
+ const json = {
759
+ input: payload?.input,
760
+ command: payload?.command,
761
+ config: payload?.config,
762
+ context: payload?.context,
763
+ metadata: payload?.metadata,
764
+ stream_mode: payload?.streamMode,
765
+ stream_subgraphs: payload?.streamSubgraphs,
766
+ stream_resumable: payload?.streamResumable,
767
+ assistant_id: assistantId,
768
+ interrupt_before: payload?.interruptBefore,
769
+ interrupt_after: payload?.interruptAfter,
770
+ webhook: payload?.webhook,
771
+ checkpoint: payload?.checkpoint,
772
+ checkpoint_id: payload?.checkpointId,
773
+ multitask_strategy: payload?.multitaskStrategy,
774
+ after_seconds: payload?.afterSeconds,
775
+ if_not_exists: payload?.ifNotExists,
776
+ checkpoint_during: payload?.checkpointDuring,
777
+ durability: payload?.durability,
778
+ langsmith_tracer: payload?._langsmithTracer
779
+ ? {
780
+ project_name: payload?._langsmithTracer?.projectName,
781
+ example_id: payload?._langsmithTracer?.exampleId
782
+ }
783
+ : undefined
784
+ };
785
+ const endpoint = threadId === null ? '/runs' : `/threads/${threadId}/runs`;
786
+ const [run, response] = await this.fetch(endpoint, {
787
+ method: 'POST',
788
+ json,
789
+ signal: payload?.signal,
790
+ withResponse: true
791
+ });
792
+ const runMetadata = getRunMetadataFromResponse(response);
793
+ if (runMetadata)
794
+ payload?.onRunCreated?.(runMetadata);
795
+ return run;
796
+ }
797
+ /**
798
+ * Create a batch of stateless background runs.
799
+ *
800
+ * @param payloads An array of payloads for creating runs.
801
+ * @returns An array of created runs.
802
+ */
803
+ async createBatch(payloads) {
804
+ const filteredPayloads = payloads
805
+ .map((payload) => ({ ...payload, assistant_id: payload.assistantId }))
806
+ .map((payload) => {
807
+ return Object.fromEntries(Object.entries(payload).filter(([_, v]) => v !== undefined));
808
+ });
809
+ return this.fetch('/runs/batch', {
810
+ method: 'POST',
811
+ json: filteredPayloads
812
+ });
813
+ }
814
+ /**
815
+ * Create a run and wait for it to complete.
816
+ *
817
+ * @param threadId The ID of the thread.
818
+ * @param assistantId Assistant ID to use for this run.
819
+ * @param payload Payload for creating a run.
820
+ * @returns The last values chunk of the thread.
821
+ */
822
+ async wait(threadId, assistantId, payload) {
823
+ const json = {
824
+ input: payload?.input,
825
+ command: payload?.command,
826
+ config: payload?.config,
827
+ context: payload?.context,
828
+ metadata: payload?.metadata,
829
+ assistant_id: assistantId,
830
+ interrupt_before: payload?.interruptBefore,
831
+ interrupt_after: payload?.interruptAfter,
832
+ checkpoint: payload?.checkpoint,
833
+ checkpoint_id: payload?.checkpointId,
834
+ webhook: payload?.webhook,
835
+ multitask_strategy: payload?.multitaskStrategy,
836
+ on_completion: payload?.onCompletion,
837
+ on_disconnect: payload?.onDisconnect,
838
+ after_seconds: payload?.afterSeconds,
839
+ if_not_exists: payload?.ifNotExists,
840
+ checkpoint_during: payload?.checkpointDuring,
841
+ durability: payload?.durability,
842
+ langsmith_tracer: payload?._langsmithTracer
843
+ ? {
844
+ project_name: payload?._langsmithTracer?.projectName,
845
+ example_id: payload?._langsmithTracer?.exampleId
846
+ }
847
+ : undefined
848
+ };
849
+ const endpoint = threadId == null ? `/runs/wait` : `/threads/${threadId}/runs/wait`;
850
+ const [run, response] = await this.fetch(endpoint, {
851
+ method: 'POST',
852
+ json,
853
+ timeoutMs: null,
854
+ signal: payload?.signal,
855
+ withResponse: true
856
+ });
857
+ const runMetadata = getRunMetadataFromResponse(response);
858
+ if (runMetadata)
859
+ payload?.onRunCreated?.(runMetadata);
860
+ const raiseError = payload?.raiseError !== undefined ? payload.raiseError : true;
861
+ if (raiseError &&
862
+ '__error__' in run &&
863
+ typeof run.__error__ === 'object' &&
864
+ run.__error__ &&
865
+ 'error' in run.__error__ &&
866
+ 'message' in run.__error__) {
867
+ throw new Error(`${run.__error__?.error}: ${run.__error__?.message}`);
868
+ }
869
+ return run;
870
+ }
871
+ /**
872
+ * List all runs for a thread.
873
+ *
874
+ * @param threadId The ID of the thread.
875
+ * @param options Filtering and pagination options.
876
+ * @returns List of runs.
877
+ */
878
+ async list(threadId, options) {
879
+ return this.fetch(`/threads/${threadId}/runs`, {
880
+ params: {
881
+ limit: options?.limit ?? 10,
882
+ offset: options?.offset ?? 0,
883
+ status: options?.status ?? undefined,
884
+ select: options?.select ?? undefined
885
+ }
886
+ });
887
+ }
888
+ /**
889
+ * Get a run by ID.
890
+ *
891
+ * @param threadId The ID of the thread.
892
+ * @param runId The ID of the run.
893
+ * @returns The run.
894
+ */
895
+ async get(threadId, runId) {
896
+ return this.fetch(`/threads/${threadId}/runs/${runId}`);
897
+ }
898
+ /**
899
+ * Cancel a run.
900
+ *
901
+ * @param threadId The ID of the thread.
902
+ * @param runId The ID of the run.
903
+ * @param wait Whether to block when canceling
904
+ * @param action Action to take when cancelling the run. Possible values are `interrupt` or `rollback`. Default is `interrupt`.
905
+ * @returns
906
+ */
907
+ async cancel(threadId, runId, wait = false, action = 'interrupt') {
908
+ return this.fetch(`/threads/${threadId}/runs/${runId}/cancel`, {
909
+ method: 'POST',
910
+ params: {
911
+ wait: wait ? '1' : '0',
912
+ action
913
+ }
914
+ });
915
+ }
916
+ /**
917
+ * Block until a run is done.
918
+ *
919
+ * @param threadId The ID of the thread.
920
+ * @param runId The ID of the run.
921
+ * @returns
922
+ */
923
+ async join(threadId, runId, options) {
924
+ return this.fetch(`/threads/${threadId}/runs/${runId}/join`, {
925
+ timeoutMs: null,
926
+ signal: options?.signal
927
+ });
928
+ }
929
+ /**
930
+ * Stream output from a run in real-time, until the run is done.
931
+ *
932
+ * @param threadId The ID of the thread. Can be set to `null` | `undefined` for stateless runs.
933
+ * @param runId The ID of the run.
934
+ * @param options Additional options for controlling the stream behavior:
935
+ * - signal: An AbortSignal that can be used to cancel the stream request
936
+ * - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events.
937
+ * - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream
938
+ * - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes)
939
+ * Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all
940
+ * stream modes enabled.
941
+ * @returns An async generator yielding stream parts.
942
+ */
943
+ async *joinStream(threadId, runId, options
944
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
945
+ ) {
946
+ const opts = typeof options === 'object' &&
947
+ options != null &&
948
+ // eslint-disable-next-line no-instanceof/no-instanceof
949
+ options instanceof AbortSignal
950
+ ? { signal: options }
951
+ : options;
952
+ let [url, init] = this.prepareFetchOptions(threadId != null ? `/threads/${threadId}/runs/${runId}/stream` : `/runs/${runId}/stream`, {
953
+ method: 'GET',
954
+ timeoutMs: null,
955
+ signal: opts?.signal,
956
+ headers: opts?.lastEventId ? { 'Last-Event-ID': opts.lastEventId } : undefined,
957
+ params: {
958
+ cancel_on_disconnect: opts?.cancelOnDisconnect ? '1' : '0',
959
+ stream_mode: opts?.streamMode
960
+ }
961
+ });
962
+ if (this.onRequest != null)
963
+ init = await this.onRequest(url, init);
964
+ const response = await this.asyncCaller.fetch(url, init);
965
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
966
+ const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }))
967
+ .pipeThrough(BytesLineDecoder())
968
+ .pipeThrough(SSEDecoder());
969
+ yield* IterableReadableStream.fromReadableStream(stream);
970
+ }
971
+ /**
972
+ * Delete a run.
973
+ *
974
+ * @param threadId The ID of the thread.
975
+ * @param runId The ID of the run.
976
+ * @returns
977
+ */
978
+ async delete(threadId, runId) {
979
+ return this.fetch(`/threads/${threadId}/runs/${runId}`, {
980
+ method: 'DELETE'
981
+ });
982
+ }
983
+ }
984
+ export class StoreClient extends BaseClient {
985
+ /**
986
+ * Store or update an item.
987
+ *
988
+ * @param namespace A list of strings representing the namespace path.
989
+ * @param key The unique identifier for the item within the namespace.
990
+ * @param value A dictionary containing the item's data.
991
+ * @param options.index Controls search indexing - null (use defaults), false (disable), or list of field paths to index.
992
+ * @param options.ttl Optional time-to-live in minutes for the item, or null for no expiration.
993
+ * @returns Promise<void>
994
+ *
995
+ * @example
996
+ * ```typescript
997
+ * await client.store.putItem(
998
+ * ["documents", "user123"],
999
+ * "item456",
1000
+ * { title: "My Document", content: "Hello World" },
1001
+ * { ttl: 60 } // expires in 60 minutes
1002
+ * );
1003
+ * ```
1004
+ */
1005
+ async putItem(namespace, key, value, options) {
1006
+ namespace.forEach((label) => {
1007
+ if (label.includes('.')) {
1008
+ throw new Error(`Invalid namespace label '${label}'. Namespace labels cannot contain periods ('.')`);
1009
+ }
1010
+ });
1011
+ const payload = {
1012
+ namespace,
1013
+ key,
1014
+ value,
1015
+ index: options?.index,
1016
+ ttl: options?.ttl
1017
+ };
1018
+ return this.fetch('/store/items', {
1019
+ method: 'PUT',
1020
+ json: payload
1021
+ });
1022
+ }
1023
+ /**
1024
+ * Retrieve a single item.
1025
+ *
1026
+ * @param namespace A list of strings representing the namespace path.
1027
+ * @param key The unique identifier for the item.
1028
+ * @param options.refreshTtl Whether to refresh the TTL on this read operation. If null, uses the store's default behavior.
1029
+ * @returns Promise<Item>
1030
+ *
1031
+ * @example
1032
+ * ```typescript
1033
+ * const item = await client.store.getItem(
1034
+ * ["documents", "user123"],
1035
+ * "item456",
1036
+ * { refreshTtl: true }
1037
+ * );
1038
+ * console.log(item);
1039
+ * // {
1040
+ * // namespace: ["documents", "user123"],
1041
+ * // key: "item456",
1042
+ * // value: { title: "My Document", content: "Hello World" },
1043
+ * // createdAt: "2024-07-30T12:00:00Z",
1044
+ * // updatedAt: "2024-07-30T12:00:00Z"
1045
+ * // }
1046
+ * ```
1047
+ */
1048
+ async getItem(namespace, key, options) {
1049
+ namespace.forEach((label) => {
1050
+ if (label.includes('.')) {
1051
+ throw new Error(`Invalid namespace label '${label}'. Namespace labels cannot contain periods ('.')`);
1052
+ }
1053
+ });
1054
+ const params = {
1055
+ namespace: namespace.join('.'),
1056
+ key
1057
+ };
1058
+ if (options?.refreshTtl !== undefined) {
1059
+ params.refresh_ttl = options.refreshTtl;
1060
+ }
1061
+ const response = await this.fetch('/store/items', {
1062
+ params
1063
+ });
1064
+ return response
1065
+ ? {
1066
+ ...response,
1067
+ createdAt: response.created_at,
1068
+ updatedAt: response.updated_at
1069
+ }
1070
+ : null;
1071
+ }
1072
+ /**
1073
+ * Delete an item.
1074
+ *
1075
+ * @param namespace A list of strings representing the namespace path.
1076
+ * @param key The unique identifier for the item.
1077
+ * @returns Promise<void>
1078
+ */
1079
+ async deleteItem(namespace, key) {
1080
+ namespace.forEach((label) => {
1081
+ if (label.includes('.')) {
1082
+ throw new Error(`Invalid namespace label '${label}'. Namespace labels cannot contain periods ('.')`);
1083
+ }
1084
+ });
1085
+ return this.fetch('/store/items', {
1086
+ method: 'DELETE',
1087
+ json: { namespace, key }
1088
+ });
1089
+ }
1090
+ /**
1091
+ * Search for items within a namespace prefix.
1092
+ *
1093
+ * @param namespacePrefix List of strings representing the namespace prefix.
1094
+ * @param options.filter Optional dictionary of key-value pairs to filter results.
1095
+ * @param options.limit Maximum number of items to return (default is 10).
1096
+ * @param options.offset Number of items to skip before returning results (default is 0).
1097
+ * @param options.query Optional search query.
1098
+ * @param options.refreshTtl Whether to refresh the TTL on items returned by this search. If null, uses the store's default behavior.
1099
+ * @returns Promise<SearchItemsResponse>
1100
+ *
1101
+ * @example
1102
+ * ```typescript
1103
+ * const results = await client.store.searchItems(
1104
+ * ["documents"],
1105
+ * {
1106
+ * filter: { author: "John Doe" },
1107
+ * limit: 5,
1108
+ * refreshTtl: true
1109
+ * }
1110
+ * );
1111
+ * console.log(results);
1112
+ * // {
1113
+ * // items: [
1114
+ * // {
1115
+ * // namespace: ["documents", "user123"],
1116
+ * // key: "item789",
1117
+ * // value: { title: "Another Document", author: "John Doe" },
1118
+ * // createdAt: "2024-07-30T12:00:00Z",
1119
+ * // updatedAt: "2024-07-30T12:00:00Z"
1120
+ * // },
1121
+ * // // ... additional items ...
1122
+ * // ]
1123
+ * // }
1124
+ * ```
1125
+ */
1126
+ async searchItems(namespacePrefix, options) {
1127
+ const payload = {
1128
+ namespace_prefix: namespacePrefix,
1129
+ filter: options?.filter,
1130
+ limit: options?.limit ?? 10,
1131
+ offset: options?.offset ?? 0,
1132
+ query: options?.query,
1133
+ refresh_ttl: options?.refreshTtl
1134
+ };
1135
+ const response = await this.fetch('/store/items/search', {
1136
+ method: 'POST',
1137
+ json: payload
1138
+ });
1139
+ return {
1140
+ items: response.items.map((item) => ({
1141
+ ...item,
1142
+ createdAt: item.created_at,
1143
+ updatedAt: item.updated_at
1144
+ }))
1145
+ };
1146
+ }
1147
+ /**
1148
+ * List namespaces with optional match conditions.
1149
+ *
1150
+ * @param options.prefix Optional list of strings representing the prefix to filter namespaces.
1151
+ * @param options.suffix Optional list of strings representing the suffix to filter namespaces.
1152
+ * @param options.maxDepth Optional integer specifying the maximum depth of namespaces to return.
1153
+ * @param options.limit Maximum number of namespaces to return (default is 100).
1154
+ * @param options.offset Number of namespaces to skip before returning results (default is 0).
1155
+ * @returns Promise<ListNamespaceResponse>
1156
+ */
1157
+ async listNamespaces(options) {
1158
+ const payload = {
1159
+ prefix: options?.prefix,
1160
+ suffix: options?.suffix,
1161
+ max_depth: options?.maxDepth,
1162
+ limit: options?.limit ?? 100,
1163
+ offset: options?.offset ?? 0
1164
+ };
1165
+ return this.fetch('/store/namespaces', {
1166
+ method: 'POST',
1167
+ json: payload
1168
+ });
1169
+ }
1170
+ }
1171
+ class UiClient extends BaseClient {
1172
+ static promiseCache = {};
1173
+ static getOrCached(key, fn) {
1174
+ if (UiClient.promiseCache[key] != null) {
1175
+ return UiClient.promiseCache[key];
1176
+ }
1177
+ const promise = fn();
1178
+ UiClient.promiseCache[key] = promise;
1179
+ return promise;
1180
+ }
1181
+ async getComponent(assistantId, agentName) {
1182
+ return UiClient.getOrCached(`${this.apiUrl}-${assistantId}-${agentName}`, async () => {
1183
+ let [url, init] = this.prepareFetchOptions(`/ui/${assistantId}`, {
1184
+ headers: {
1185
+ Accept: 'text/html',
1186
+ 'Content-Type': 'application/json'
1187
+ },
1188
+ method: 'POST',
1189
+ json: { name: agentName }
1190
+ });
1191
+ if (this.onRequest != null)
1192
+ init = await this.onRequest(url, init);
1193
+ const response = await this.asyncCaller.fetch(url, init);
1194
+ return response.text();
1195
+ });
1196
+ }
1197
+ }
1198
+ export class Client {
1199
+ /**
1200
+ * The client for interacting with assistants.
1201
+ */
1202
+ assistants;
1203
+ /**
1204
+ * The client for interacting with threads.
1205
+ */
1206
+ threads;
1207
+ /**
1208
+ * The client for interacting with runs.
1209
+ */
1210
+ runs;
1211
+ /**
1212
+ * The client for interacting with cron runs.
1213
+ */
1214
+ crons;
1215
+ /**
1216
+ * The client for interacting with the KV store.
1217
+ */
1218
+ store;
1219
+ /**
1220
+ * The client for interacting with contexts (files, etc.).
1221
+ */
1222
+ contexts;
1223
+ /**
1224
+ * The client for interacting with knowledgebases.
1225
+ */
1226
+ knowledges;
1227
+ /**
1228
+ * The client for interacting with conversations.
1229
+ */
1230
+ conversations;
1231
+ /**
1232
+ * The client for interacting with sandbox runtime resources.
1233
+ */
1234
+ sandbox;
1235
+ /**
1236
+ * The client for interacting with the UI.
1237
+ * @internal Used by LoadExternalComponent and the API might change in the future.
1238
+ */
1239
+ '~ui';
1240
+ /**
1241
+ * @internal Used to obtain a stable key representing the client.
1242
+ */
1243
+ '~configHash';
1244
+ constructor(config) {
1245
+ this['~configHash'] = (() => JSON.stringify({
1246
+ apiUrl: config?.apiUrl,
1247
+ apiKey: config?.apiKey,
1248
+ timeoutMs: config?.timeoutMs,
1249
+ defaultHeaders: config?.defaultHeaders,
1250
+ maxConcurrency: config?.callerOptions?.maxConcurrency,
1251
+ maxRetries: config?.callerOptions?.maxRetries,
1252
+ callbacks: {
1253
+ onFailedResponseHook: config?.callerOptions?.onFailedResponseHook != null,
1254
+ onRequest: config?.onRequest != null,
1255
+ fetch: config?.callerOptions?.fetch != null
1256
+ }
1257
+ }))();
1258
+ this.assistants = new AssistantsClient(config);
1259
+ this.threads = new ThreadsClient(config);
1260
+ this.runs = new RunsClient(config);
1261
+ this.crons = new CronsClient(config);
1262
+ this.store = new StoreClient(config);
1263
+ this.contexts = new ContextsClient(config);
1264
+ this.knowledges = new KnowledgesClient(config);
1265
+ this.conversations = new ConversationsClient(config);
1266
+ this.sandbox = new SandboxClient(config);
1267
+ this['~ui'] = new UiClient(config);
1268
+ }
1269
+ }
1270
+ /**
1271
+ * @internal Used to obtain a stable key representing the client.
1272
+ */
1273
+ export function getClientConfigHash(client) {
1274
+ return client['~configHash'];
1275
+ }
1276
+ export class ContextsClient extends BaseClient {
1277
+ async uploadFile(file, options) {
1278
+ if (typeof FormData === 'undefined' || typeof Blob === 'undefined') {
1279
+ throw new Error('File uploads require FormData and Blob support in the current environment.');
1280
+ }
1281
+ const isBlob = file instanceof Blob;
1282
+ const blob = isBlob ? file : new Blob([file]);
1283
+ let filename = options?.filename;
1284
+ if (filename == null && typeof File !== 'undefined' && isBlob && file instanceof File) {
1285
+ filename = file.name;
1286
+ }
1287
+ if (filename == null || filename.trim() === '') {
1288
+ filename = 'upload';
1289
+ }
1290
+ const formData = new FormData();
1291
+ formData.append('file', blob, filename);
1292
+ return this.fetch('/contexts/file', {
1293
+ method: 'POST',
1294
+ body: formData
1295
+ });
1296
+ }
1297
+ async deleteFile(id) {
1298
+ await this.fetch(`/contexts/file/${id}`, {
1299
+ method: 'DELETE'
1300
+ });
1301
+ }
1302
+ }
1303
+ export class KnowledgesClient extends BaseClient {
1304
+ async create(payload) {
1305
+ return this.fetch(`/knowledges`, {
1306
+ method: 'POST',
1307
+ json: payload
1308
+ });
1309
+ }
1310
+ }
1311
+ function encodeSandboxPathSegment(value) {
1312
+ return encodeURIComponent(value);
1313
+ }
1314
+ function normalizeSandboxProxyPath(path) {
1315
+ if (!path || path === '/')
1316
+ return '/';
1317
+ return path.startsWith('/') ? path : `/${path}`;
1318
+ }
1319
+ export class SandboxClient extends BaseClient {
1320
+ constructor(config) {
1321
+ super({
1322
+ ...config,
1323
+ apiUrl: deriveSandboxApiUrl(config?.apiUrl)
1324
+ });
1325
+ }
1326
+ async listConversationServices(conversationId, options) {
1327
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services`, {
1328
+ params: { organizationId: options?.organizationId },
1329
+ signal: options?.signal
1330
+ });
1331
+ }
1332
+ async listThreadServices(threadId, options) {
1333
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services`, {
1334
+ params: { organizationId: options?.organizationId },
1335
+ signal: options?.signal
1336
+ });
1337
+ }
1338
+ async getConversationService(conversationId, serviceId, options) {
1339
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services/${encodeSandboxPathSegment(serviceId)}`, {
1340
+ params: { organizationId: options?.organizationId },
1341
+ signal: options?.signal
1342
+ });
1343
+ }
1344
+ async getThreadService(threadId, serviceId, options) {
1345
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services/${encodeSandboxPathSegment(serviceId)}`, {
1346
+ params: { organizationId: options?.organizationId },
1347
+ signal: options?.signal
1348
+ });
1349
+ }
1350
+ async startConversationService(conversationId, input, options) {
1351
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services/start`, {
1352
+ method: 'POST',
1353
+ json: input,
1354
+ params: { organizationId: options?.organizationId },
1355
+ signal: options?.signal
1356
+ });
1357
+ }
1358
+ async startThreadService(threadId, input, options) {
1359
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services/start`, {
1360
+ method: 'POST',
1361
+ json: input,
1362
+ params: { organizationId: options?.organizationId },
1363
+ signal: options?.signal
1364
+ });
1365
+ }
1366
+ async getConversationServiceLogs(conversationId, serviceId, options) {
1367
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services/${encodeSandboxPathSegment(serviceId)}/logs`, {
1368
+ params: {
1369
+ organizationId: options?.organizationId,
1370
+ tail: options?.tail
1371
+ },
1372
+ signal: options?.signal
1373
+ });
1374
+ }
1375
+ async getThreadServiceLogs(threadId, serviceId, options) {
1376
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services/${encodeSandboxPathSegment(serviceId)}/logs`, {
1377
+ params: {
1378
+ organizationId: options?.organizationId,
1379
+ tail: options?.tail
1380
+ },
1381
+ signal: options?.signal
1382
+ });
1383
+ }
1384
+ async stopConversationService(conversationId, serviceId, options) {
1385
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services/${encodeSandboxPathSegment(serviceId)}/stop`, {
1386
+ method: 'POST',
1387
+ params: { organizationId: options?.organizationId },
1388
+ signal: options?.signal
1389
+ });
1390
+ }
1391
+ async stopThreadService(threadId, serviceId, options) {
1392
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services/${encodeSandboxPathSegment(serviceId)}/stop`, {
1393
+ method: 'POST',
1394
+ params: { organizationId: options?.organizationId },
1395
+ signal: options?.signal
1396
+ });
1397
+ }
1398
+ async restartConversationService(conversationId, serviceId, options) {
1399
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services/${encodeSandboxPathSegment(serviceId)}/restart`, {
1400
+ method: 'POST',
1401
+ params: { organizationId: options?.organizationId },
1402
+ signal: options?.signal
1403
+ });
1404
+ }
1405
+ async restartThreadService(threadId, serviceId, options) {
1406
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services/${encodeSandboxPathSegment(serviceId)}/restart`, {
1407
+ method: 'POST',
1408
+ params: { organizationId: options?.organizationId },
1409
+ signal: options?.signal
1410
+ });
1411
+ }
1412
+ async createConversationServicePreviewSession(conversationId, serviceId, options) {
1413
+ return this.fetch(`/conversations/${encodeSandboxPathSegment(conversationId)}/services/${encodeSandboxPathSegment(serviceId)}/preview-session`, {
1414
+ method: 'POST',
1415
+ params: { organizationId: options?.organizationId },
1416
+ signal: options?.signal
1417
+ });
1418
+ }
1419
+ async createThreadServicePreviewSession(threadId, serviceId, options) {
1420
+ return this.fetch(`/threads/${encodeSandboxPathSegment(threadId)}/services/${encodeSandboxPathSegment(serviceId)}/preview-session`, {
1421
+ method: 'POST',
1422
+ params: { organizationId: options?.organizationId },
1423
+ signal: options?.signal
1424
+ });
1425
+ }
1426
+ getConversationServiceProxyUrl(conversationId, serviceId, path) {
1427
+ const normalizedPath = normalizeSandboxProxyPath(path);
1428
+ return `${this.apiUrl}/conversations/${encodeSandboxPathSegment(conversationId)}/services/${encodeSandboxPathSegment(serviceId)}/proxy${normalizedPath}`;
1429
+ }
1430
+ }
1431
+ // Conversations Client
1432
+ export class ConversationsClient extends BaseClient {
1433
+ async create(payload) {
1434
+ return this.fetch(`/conversations`, {
1435
+ method: 'POST',
1436
+ json: payload
1437
+ });
1438
+ }
1439
+ async get(conversationId) {
1440
+ return this.fetch(`/conversations/${conversationId}`);
1441
+ }
1442
+ async update(conversationId, payload) {
1443
+ return this.fetch(`/conversations/${conversationId}`, {
1444
+ method: 'PATCH',
1445
+ json: payload
1446
+ });
1447
+ }
1448
+ async delete(conversationId) {
1449
+ await this.fetch(`/conversations/${conversationId}`, {
1450
+ method: 'DELETE'
1451
+ });
1452
+ }
1453
+ async search(query) {
1454
+ return this.fetch(`/conversations/search`, {
1455
+ method: 'POST',
1456
+ json: {
1457
+ where: query?.where,
1458
+ order: query?.order,
1459
+ limit: query?.limit,
1460
+ offset: query?.offset,
1461
+ search: query?.search
1462
+ }
1463
+ });
1464
+ }
1465
+ async listMessages(conversationId, query) {
1466
+ return this.fetch(`/conversations/${conversationId}/messages`, {
1467
+ params: {
1468
+ limit: query?.limit,
1469
+ offset: query?.offset
1470
+ }
1471
+ });
1472
+ }
1473
+ async searchMessages(conversationId, query) {
1474
+ return this.fetch(`/conversations/${conversationId}/messages/search`, {
1475
+ method: 'POST',
1476
+ json: {
1477
+ where: query?.where,
1478
+ order: query?.order,
1479
+ limit: query?.limit,
1480
+ offset: query?.offset
1481
+ }
1482
+ });
1483
+ }
1484
+ async createMessage(conversationId, payload) {
1485
+ return this.fetch(`/conversations/${conversationId}/messages`, {
1486
+ method: 'POST',
1487
+ json: payload
1488
+ });
1489
+ }
1490
+ async getMessage(conversationId, messageId) {
1491
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}`);
1492
+ }
1493
+ async updateMessage(conversationId, messageId, payload) {
1494
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}`, {
1495
+ method: 'PATCH',
1496
+ json: payload
1497
+ });
1498
+ }
1499
+ async deleteMessage(conversationId, messageId) {
1500
+ await this.fetch(`/conversations/${conversationId}/messages/${messageId}`, {
1501
+ method: 'DELETE'
1502
+ });
1503
+ }
1504
+ async listFeedbacks(conversationId, messageId, query) {
1505
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}/feedbacks`, {
1506
+ params: {
1507
+ limit: query?.limit,
1508
+ offset: query?.offset
1509
+ }
1510
+ });
1511
+ }
1512
+ async searchFeedbacks(conversationId, messageId, query) {
1513
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}/feedbacks/search`, {
1514
+ method: 'POST',
1515
+ json: {
1516
+ where: query?.where,
1517
+ order: query?.order,
1518
+ limit: query?.limit,
1519
+ offset: query?.offset
1520
+ }
1521
+ });
1522
+ }
1523
+ async createFeedback(conversationId, messageId, payload) {
1524
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}/feedbacks`, {
1525
+ method: 'POST',
1526
+ json: payload
1527
+ });
1528
+ }
1529
+ async getFeedback(conversationId, messageId, feedbackId) {
1530
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}/feedbacks/${feedbackId}`);
1531
+ }
1532
+ async updateFeedback(conversationId, messageId, feedbackId, payload) {
1533
+ return this.fetch(`/conversations/${conversationId}/messages/${messageId}/feedbacks/${feedbackId}`, {
1534
+ method: 'PATCH',
1535
+ json: payload
1536
+ });
1537
+ }
1538
+ async deleteFeedback(conversationId, messageId, feedbackId) {
1539
+ await this.fetch(`/conversations/${conversationId}/messages/${messageId}/feedbacks/${feedbackId}`, {
1540
+ method: 'DELETE'
1541
+ });
1542
+ }
1543
+ }
1544
+ //# sourceMappingURL=client.mjs.map