@axiom-lattice/client-sdk 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,648 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ ApiError: () => ApiError,
34
+ AuthenticationError: () => AuthenticationError,
35
+ Client: () => Client,
36
+ NetworkError: () => NetworkError,
37
+ createSimpleMessageMerger: () => createSimpleMessageMerger
38
+ });
39
+ module.exports = __toCommonJS(src_exports);
40
+
41
+ // src/types.ts
42
+ var ApiError = class extends Error {
43
+ constructor(message, statusCode, responseBody) {
44
+ super(message);
45
+ this.statusCode = statusCode;
46
+ this.responseBody = responseBody;
47
+ this.name = "ApiError";
48
+ }
49
+ };
50
+ var NetworkError = class extends Error {
51
+ constructor(message) {
52
+ super(message);
53
+ this.name = "NetworkError";
54
+ }
55
+ };
56
+ var AuthenticationError = class extends Error {
57
+ constructor(message) {
58
+ super(message);
59
+ this.name = "AuthenticationError";
60
+ }
61
+ };
62
+
63
+ // src/client.ts
64
+ var import_axios = __toESM(require("axios"));
65
+ var Client = class {
66
+ /**
67
+ * Creates a new Client instance
68
+ * @param config - Configuration options for the client
69
+ */
70
+ constructor(config) {
71
+ this.tenantId = "";
72
+ this.registeredTools = /* @__PURE__ */ new Map();
73
+ /**
74
+ * Chat namespace for sending messages and streaming responses
75
+ */
76
+ this.chat = {
77
+ /**
78
+ * Sends a message to a thread and receives a response
79
+ * @param options - Options for sending a message
80
+ * @returns A promise that resolves to the chat response
81
+ */
82
+ send: async (options) => {
83
+ try {
84
+ const message = options.messages[options.messages.length - 1];
85
+ const result = await this.run({
86
+ threadId: options.threadId,
87
+ message: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
88
+ streaming: false
89
+ });
90
+ return {
91
+ message: {
92
+ role: "ai",
93
+ content: result.output || "",
94
+ id: result.id || ""
95
+ },
96
+ traceId: result.id || ""
97
+ };
98
+ } catch (error) {
99
+ throw error;
100
+ }
101
+ },
102
+ /**
103
+ * Sends a message to a thread and streams the response
104
+ * @param options - Options for streaming a message
105
+ * @param onEvent - Callback function that receives stream events
106
+ * @param onComplete - Optional callback function called when streaming completes
107
+ * @param onError - Optional callback function called when an error occurs
108
+ * @returns A function that can be called to stop the stream
109
+ */
110
+ stream: (options, onEvent, onComplete, onError) => {
111
+ const message = options.messages[options.messages.length - 1];
112
+ return this.streamRun(
113
+ {
114
+ threadId: options.threadId,
115
+ message: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
116
+ streaming: true,
117
+ background: options.background
118
+ },
119
+ onEvent,
120
+ onComplete,
121
+ onError
122
+ );
123
+ }
124
+ };
125
+ /**
126
+ * Tools namespace for registering and unregistering client-side tools
127
+ */
128
+ this.tools = {
129
+ /**
130
+ * Registers a client-side tool
131
+ * @param options - Options for registering a tool
132
+ */
133
+ register: (options) => {
134
+ if (this.config.transport !== "ws") {
135
+ throw new Error(
136
+ "Client-side tools are only supported with WebSocket transport"
137
+ );
138
+ }
139
+ this.registeredTools.set(options.name, options);
140
+ },
141
+ /**
142
+ * Unregisters a client-side tool
143
+ * @param name - Tool name
144
+ */
145
+ unregister: (name) => {
146
+ this.registeredTools.delete(name);
147
+ }
148
+ };
149
+ this.config = {
150
+ timeout: 3e4,
151
+ ...config
152
+ };
153
+ this.assistantId = config.assistantId;
154
+ this.client = import_axios.default.create({
155
+ baseURL: this.config.baseURL,
156
+ timeout: this.config.timeout,
157
+ headers: {
158
+ "Content-Type": "application/json",
159
+ Authorization: `Bearer ${this.config.apiKey}`,
160
+ ...this.config.headers
161
+ }
162
+ });
163
+ this.setupInterceptors();
164
+ }
165
+ /**
166
+ * Sets up axios interceptors for error handling
167
+ * @private
168
+ */
169
+ setupInterceptors() {
170
+ this.client.interceptors.response.use(
171
+ (response) => response,
172
+ (error) => {
173
+ if (error.response) {
174
+ if (error.response.status === 401) {
175
+ throw new AuthenticationError(
176
+ error.response.data.message || "Authentication failed"
177
+ );
178
+ } else {
179
+ throw new ApiError(
180
+ error.response.data.message || "API Error",
181
+ error.response.status,
182
+ error.response.data
183
+ );
184
+ }
185
+ } else if (error.request) {
186
+ throw new NetworkError("No response received from server");
187
+ } else {
188
+ throw new Error(`Request error: ${error.message}`);
189
+ }
190
+ }
191
+ );
192
+ }
193
+ /**
194
+ * Set tenant ID for multi-tenant environments
195
+ * @param tenantId - Tenant identifier
196
+ */
197
+ setTenantId(tenantId) {
198
+ this.tenantId = tenantId;
199
+ this.client.defaults.headers["x-tenant-id"] = tenantId;
200
+ }
201
+ /**
202
+ * Creates a new thread
203
+ * @param options - Options for creating a thread
204
+ * @returns A promise that resolves to the thread ID
205
+ */
206
+ async createThread(options) {
207
+ try {
208
+ const response = await this.client.post("/threads", {
209
+ ...options,
210
+ assistantId: this.assistantId
211
+ });
212
+ return response.data.id;
213
+ } catch (error) {
214
+ throw error;
215
+ }
216
+ }
217
+ /**
218
+ * Retrieves thread information
219
+ * @param threadId - Thread identifier
220
+ * @returns A promise that resolves to the thread information
221
+ */
222
+ async getThread(threadId) {
223
+ try {
224
+ const response = await this.client.get(`/threads/${threadId}`, {
225
+ params: {
226
+ assistantId: this.assistantId
227
+ }
228
+ });
229
+ return response.data;
230
+ } catch (error) {
231
+ throw error;
232
+ }
233
+ }
234
+ /**
235
+ * Lists all threads
236
+ * @param options - Options for listing threads
237
+ * @returns A promise that resolves to an array of threads
238
+ */
239
+ async listThreads(options) {
240
+ try {
241
+ const response = await this.client.get("/threads", {
242
+ params: {
243
+ ...options,
244
+ assistantId: this.assistantId
245
+ }
246
+ });
247
+ return response.data.threads;
248
+ } catch (error) {
249
+ throw error;
250
+ }
251
+ }
252
+ /**
253
+ * Deletes a thread
254
+ * @param threadId - Thread identifier
255
+ * @returns A promise that resolves when the thread is deleted
256
+ */
257
+ async deleteThread(threadId) {
258
+ try {
259
+ await this.client.delete(`/threads/${threadId}`, {
260
+ params: {
261
+ assistantId: this.assistantId
262
+ }
263
+ });
264
+ } catch (error) {
265
+ throw error;
266
+ }
267
+ }
268
+ /**
269
+ * Retrieves messages from a thread
270
+ * @param options - Options for retrieving messages
271
+ * @returns A promise that resolves to an array of messages
272
+ */
273
+ async getMessages(options) {
274
+ try {
275
+ const response = await this.client.get(
276
+ `/api/assistants/${this.assistantId}/${options.threadId}/memory`,
277
+ {
278
+ params: {
279
+ limit: options.limit,
280
+ after: options.after,
281
+ reverse: options.reverse,
282
+ assistantId: this.assistantId
283
+ }
284
+ }
285
+ );
286
+ return response.data;
287
+ } catch (error) {
288
+ throw error;
289
+ }
290
+ }
291
+ /**
292
+ * Retrieves agent state
293
+ * @param threadId - Thread identifier
294
+ * @returns A promise that resolves to the agent state
295
+ */
296
+ async getAgentState(threadId) {
297
+ try {
298
+ const response = await this.client.get(
299
+ `/api/assistants/${this.assistantId}/${threadId}/state`
300
+ );
301
+ return response.data;
302
+ } catch (error) {
303
+ throw error;
304
+ }
305
+ }
306
+ /**
307
+ * Gets agent graph visualization
308
+ * @returns A promise that resolves to the graph visualization data
309
+ */
310
+ async getAgentGraph() {
311
+ try {
312
+ const response = await this.client.get(
313
+ `/api/assistants/${this.assistantId}/graph`
314
+ );
315
+ return response.data.image;
316
+ } catch (error) {
317
+ throw error;
318
+ }
319
+ }
320
+ /**
321
+ * Run agent with options
322
+ * @param options - Options for running the agent
323
+ * @returns A promise that resolves to the run result or a stream
324
+ */
325
+ async run(options) {
326
+ try {
327
+ const headers = {};
328
+ if (this.tenantId) {
329
+ headers["x-tenant-id"] = this.tenantId;
330
+ }
331
+ if (options.streaming) {
332
+ throw new Error(
333
+ "Streaming without callbacks is not supported. Use chat.stream with callbacks instead."
334
+ );
335
+ } else {
336
+ const response = await this.client.post(
337
+ "/api/runs",
338
+ {
339
+ assistant_id: this.assistantId,
340
+ thread_id: options.threadId,
341
+ message: options.message,
342
+ files: options.files,
343
+ command: options.command,
344
+ streaming: false,
345
+ background: options.background || false
346
+ },
347
+ { headers }
348
+ );
349
+ return response.data;
350
+ }
351
+ } catch (error) {
352
+ throw error;
353
+ }
354
+ }
355
+ /**
356
+ * Stream run results
357
+ * @param options - Options for streaming run results
358
+ * @param onEvent - Callback function that receives stream events
359
+ * @param onComplete - Optional callback function called when streaming completes
360
+ * @param onError - Optional callback function called when an error occurs
361
+ * @returns A function that can be called to stop the stream
362
+ */
363
+ streamRun(options, onEvent, onComplete, onError) {
364
+ const headers = {
365
+ "Content-Type": "application/json"
366
+ };
367
+ if (this.tenantId) {
368
+ headers["x-tenant-id"] = this.tenantId;
369
+ }
370
+ const controller = new AbortController();
371
+ const signal = controller.signal;
372
+ (async () => {
373
+ try {
374
+ const response = await fetch(`${this.config.baseURL}/api/runs`, {
375
+ method: "POST",
376
+ headers: {
377
+ "Content-Type": "application/json",
378
+ Authorization: `Bearer ${this.config.apiKey}`,
379
+ ...headers
380
+ },
381
+ body: JSON.stringify({
382
+ assistant_id: this.assistantId,
383
+ thread_id: options.threadId,
384
+ message: options.message,
385
+ files: options.files,
386
+ command: options.command,
387
+ streaming: true,
388
+ background: options.background || false
389
+ }),
390
+ signal
391
+ });
392
+ if (!response.ok) {
393
+ throw new Error(`HTTP error! status: ${response.status}`);
394
+ }
395
+ if (!response.body) {
396
+ throw new Error("Response body is null");
397
+ }
398
+ const reader = response.body.getReader();
399
+ const decoder = new TextDecoder();
400
+ let buffer = "";
401
+ while (true) {
402
+ const { value, done } = await reader.read();
403
+ if (done) {
404
+ if (buffer.trim()) {
405
+ try {
406
+ const data = JSON.parse(buffer.trim());
407
+ onEvent(data);
408
+ } catch (error) {
409
+ }
410
+ }
411
+ break;
412
+ }
413
+ const chunk = decoder.decode(value, { stream: true });
414
+ buffer += chunk;
415
+ const lines = buffer.split("\n");
416
+ buffer = lines.pop() || "";
417
+ for (const line of lines) {
418
+ if (line.trim().startsWith("data: ")) {
419
+ try {
420
+ const data = JSON.parse(line.trim().slice(6));
421
+ onEvent(data);
422
+ } catch (error) {
423
+ if (onError) {
424
+ onError(
425
+ error instanceof Error ? error : new Error(String(error))
426
+ );
427
+ }
428
+ }
429
+ }
430
+ }
431
+ }
432
+ if (onComplete) {
433
+ onComplete();
434
+ }
435
+ } catch (error) {
436
+ if (signal.aborted) {
437
+ return;
438
+ }
439
+ if (onError) {
440
+ onError(error instanceof Error ? error : new Error(String(error)));
441
+ }
442
+ }
443
+ })();
444
+ return () => {
445
+ controller.abort();
446
+ };
447
+ }
448
+ };
449
+
450
+ // src/ChunkMessageMerger.ts
451
+ function createSimpleMessageMerger() {
452
+ let messages = [];
453
+ const messageMap = /* @__PURE__ */ new Map();
454
+ const toolBuilders = /* @__PURE__ */ new Map();
455
+ function normalizeRole(type) {
456
+ switch (type) {
457
+ case "ai":
458
+ return "ai";
459
+ case "human":
460
+ case "user":
461
+ return "human";
462
+ case "system":
463
+ return "system";
464
+ case "tool":
465
+ return "tool";
466
+ case "developer":
467
+ return "developer";
468
+ default:
469
+ return "ai";
470
+ }
471
+ }
472
+ function safeJsonParse(str) {
473
+ try {
474
+ return JSON.parse(str);
475
+ } catch {
476
+ return str;
477
+ }
478
+ }
479
+ function ensureMessage(id, role) {
480
+ const index = messageMap.get(id);
481
+ if (index !== void 0) {
482
+ return messages[index];
483
+ }
484
+ let newMessage;
485
+ switch (role) {
486
+ case "human":
487
+ newMessage = { id, role: "human", content: "" };
488
+ break;
489
+ case "system":
490
+ newMessage = { id, role: "system", content: "" };
491
+ break;
492
+ case "tool":
493
+ newMessage = { id, role: "tool", content: "", tool_call_id: "" };
494
+ break;
495
+ case "developer":
496
+ newMessage = { id, role: "developer", content: "" };
497
+ break;
498
+ default:
499
+ newMessage = { id, role: "ai", content: "" };
500
+ }
501
+ messages.push(newMessage);
502
+ messageMap.set(id, messages.length - 1);
503
+ return newMessage;
504
+ }
505
+ function updateToolCalls(message) {
506
+ if (message.role !== "ai")
507
+ return;
508
+ const builders = toolBuilders.get(message.id);
509
+ if (!builders || builders.size === 0)
510
+ return;
511
+ const toolCalls = [];
512
+ for (const [index, builder] of Array.from(builders.entries())) {
513
+ if (builder.name && builder.id) {
514
+ const args = builder.args.trim();
515
+ const parsedArgs = safeJsonParse(args);
516
+ toolCalls.push({
517
+ id: builder.id,
518
+ name: builder.name,
519
+ args: typeof parsedArgs === "object" ? parsedArgs : { value: parsedArgs },
520
+ type: "tool_call"
521
+ });
522
+ }
523
+ }
524
+ if (toolCalls.length > 0) {
525
+ message.tool_calls = toolCalls;
526
+ }
527
+ }
528
+ function initialMessages(msgs) {
529
+ messages = msgs;
530
+ }
531
+ function push(chunk) {
532
+ const role = normalizeRole(chunk.type);
533
+ const message = ensureMessage(chunk.data.id, role);
534
+ if (chunk.data.content) {
535
+ message.content = (message.content || "") + chunk.data.content;
536
+ }
537
+ if (message.role === "tool" && chunk.data.tool_call_id) {
538
+ message.tool_call_id = chunk.data.tool_call_id;
539
+ }
540
+ if (chunk.data.tool_call_chunks && message.role === "ai") {
541
+ let builders = toolBuilders.get(message.id);
542
+ if (!builders) {
543
+ builders = /* @__PURE__ */ new Map();
544
+ toolBuilders.set(message.id, builders);
545
+ }
546
+ for (const chunk_item of chunk.data.tool_call_chunks) {
547
+ let builder = builders.get(chunk_item.index);
548
+ if (!builder) {
549
+ builder = { args: "" };
550
+ builders.set(chunk_item.index, builder);
551
+ }
552
+ if (chunk_item.name)
553
+ builder.name = chunk_item.name;
554
+ if (chunk_item.id)
555
+ builder.id = chunk_item.id;
556
+ if (chunk_item.args)
557
+ builder.args += chunk_item.args;
558
+ }
559
+ updateToolCalls(message);
560
+ }
561
+ if (chunk.data.tool_calls && message.role === "ai") {
562
+ const toolCalls = chunk.data.tool_calls.filter((tc) => tc.name && tc.id).map((tc) => ({
563
+ id: tc.id,
564
+ name: tc.name,
565
+ args: tc.args,
566
+ type: "tool_call",
567
+ response: tc.response
568
+ }));
569
+ if (toolCalls.length > 0) {
570
+ message.tool_calls = toolCalls;
571
+ }
572
+ }
573
+ if (chunk.data.additional_kwargs?.tool_calls && message.role === "ai" && !message.tool_calls) {
574
+ const toolCalls = [];
575
+ for (const tc of chunk.data.additional_kwargs.tool_calls) {
576
+ if (tc.function?.name && tc.id) {
577
+ const args = typeof tc.function.arguments === "string" ? safeJsonParse(tc.function.arguments) : tc.function.arguments || {};
578
+ toolCalls.push({
579
+ id: tc.id,
580
+ name: tc.function.name,
581
+ args,
582
+ type: "tool_call"
583
+ });
584
+ }
585
+ }
586
+ if (toolCalls.length > 0) {
587
+ message.tool_calls = toolCalls;
588
+ }
589
+ }
590
+ }
591
+ function getMessages() {
592
+ const toolResponsesMap = {};
593
+ messages.forEach((message) => {
594
+ if (message.role === "tool" && message.tool_call_id) {
595
+ toolResponsesMap[message.tool_call_id] = message;
596
+ }
597
+ });
598
+ return messages.filter((message) => {
599
+ return message.role !== "tool";
600
+ }).map((message) => {
601
+ if (message.role === "ai" && message.tool_calls) {
602
+ const mergedMessage = { ...message };
603
+ if (mergedMessage.tool_calls) {
604
+ mergedMessage.tool_calls = mergedMessage.tool_calls.map(
605
+ (toolCall) => {
606
+ const toolResponse = toolResponsesMap[toolCall.id];
607
+ if (toolResponse) {
608
+ return {
609
+ ...toolCall,
610
+ response: toolResponse.content
611
+ };
612
+ }
613
+ return toolCall;
614
+ }
615
+ );
616
+ }
617
+ return mergedMessage;
618
+ }
619
+ return message;
620
+ });
621
+ }
622
+ function getMessagesWithoutToolCalls() {
623
+ return messages.filter(
624
+ (message) => message.role !== "tool" && (message.role !== "ai" || !message.tool_calls)
625
+ );
626
+ }
627
+ function reset() {
628
+ messages.length = 0;
629
+ messageMap.clear();
630
+ toolBuilders.clear();
631
+ }
632
+ return {
633
+ push,
634
+ initialMessages,
635
+ getMessages,
636
+ getMessagesWithoutToolCalls,
637
+ reset
638
+ };
639
+ }
640
+ // Annotate the CommonJS export names for ESM import in node:
641
+ 0 && (module.exports = {
642
+ ApiError,
643
+ AuthenticationError,
644
+ Client,
645
+ NetworkError,
646
+ createSimpleMessageMerger
647
+ });
648
+ //# sourceMappingURL=index.js.map