@axiom-lattice/client-sdk 1.0.22 → 1.0.23

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.mjs CHANGED
@@ -22,6 +22,181 @@ var AuthenticationError = class extends Error {
22
22
 
23
23
  // src/client.ts
24
24
  import axios from "axios";
25
+
26
+ // src/wechat-client.ts
27
+ import { promisify } from "miniprogram-api-promise";
28
+ function createWechatClient(config) {
29
+ let wxApi = null;
30
+ if (typeof global !== "undefined" && global.wx) {
31
+ wxApi = global.wx;
32
+ } else if (typeof globalThis !== "undefined" && globalThis.wx) {
33
+ wxApi = globalThis.wx;
34
+ } else {
35
+ try {
36
+ const win = globalThis;
37
+ if (win.wx) {
38
+ wxApi = win.wx;
39
+ }
40
+ } catch (e) {
41
+ }
42
+ }
43
+ if (!wxApi) {
44
+ throw new Error("WeChat Mini Program environment not detected");
45
+ }
46
+ const request = promisify(wxApi.request);
47
+ const defaultHeaders = {
48
+ "Content-Type": "application/json",
49
+ ...config.headers
50
+ };
51
+ const interceptors = {
52
+ request: {
53
+ handlers: [],
54
+ use(fulfilled, rejected) {
55
+ const id = this.handlers.length;
56
+ this.handlers.push({ fulfilled, rejected });
57
+ return id;
58
+ },
59
+ eject(id) {
60
+ if (this.handlers[id]) {
61
+ this.handlers[id] = {};
62
+ }
63
+ }
64
+ },
65
+ response: {
66
+ handlers: [],
67
+ use(fulfilled, rejected) {
68
+ const id = this.handlers.length;
69
+ this.handlers.push({ fulfilled, rejected });
70
+ return id;
71
+ },
72
+ eject(id) {
73
+ if (this.handlers[id]) {
74
+ this.handlers[id] = {};
75
+ }
76
+ }
77
+ }
78
+ };
79
+ const processRequestInterceptors = (requestConfig) => {
80
+ let config2 = { ...requestConfig };
81
+ for (const handler of interceptors.request.handlers) {
82
+ if (handler.fulfilled) {
83
+ try {
84
+ config2 = handler.fulfilled(config2);
85
+ } catch (error) {
86
+ if (handler.rejected) {
87
+ handler.rejected(error);
88
+ }
89
+ throw error;
90
+ }
91
+ }
92
+ }
93
+ return config2;
94
+ };
95
+ const processResponseInterceptors = async (response) => {
96
+ let result = response;
97
+ for (const handler of interceptors.response.handlers) {
98
+ if (handler.fulfilled) {
99
+ try {
100
+ result = await handler.fulfilled(result);
101
+ } catch (error) {
102
+ if (handler.rejected) {
103
+ result = await handler.rejected(error);
104
+ } else {
105
+ throw error;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ return result;
111
+ };
112
+ const processErrorInterceptors = async (error) => {
113
+ let result = error;
114
+ for (const handler of interceptors.response.handlers) {
115
+ if (handler.rejected) {
116
+ try {
117
+ result = await handler.rejected(result);
118
+ } catch (newError) {
119
+ result = newError;
120
+ }
121
+ }
122
+ }
123
+ return Promise.reject(result);
124
+ };
125
+ const CancelToken = {
126
+ source() {
127
+ let cancel = () => {
128
+ };
129
+ const token = {
130
+ promise: new Promise((resolve) => {
131
+ cancel = (message = "Request cancelled") => resolve(message);
132
+ }),
133
+ reason: void 0
134
+ };
135
+ return {
136
+ token,
137
+ cancel
138
+ };
139
+ }
140
+ };
141
+ const isCancel = (value) => {
142
+ return value && value.__CANCEL__;
143
+ };
144
+ const makeRequest = async (method, url, data, customConfig) => {
145
+ try {
146
+ const requestConfig = processRequestInterceptors({
147
+ url: `${config.baseURL}${url}`,
148
+ method,
149
+ data,
150
+ header: { ...defaultHeaders, ...customConfig?.headers },
151
+ timeout: config.timeout || 3e4,
152
+ ...customConfig
153
+ });
154
+ if (customConfig?.cancelToken) {
155
+ customConfig.cancelToken.promise.then((reason) => {
156
+ throw Object.assign(new Error(reason), { __CANCEL__: true });
157
+ });
158
+ }
159
+ const response = await request(requestConfig);
160
+ const transformedResponse = {
161
+ data: response.data,
162
+ status: response.statusCode,
163
+ statusText: response.errMsg,
164
+ headers: response.header,
165
+ config: requestConfig
166
+ };
167
+ return await processResponseInterceptors(transformedResponse);
168
+ } catch (error) {
169
+ return processErrorInterceptors(error);
170
+ }
171
+ };
172
+ const client = {
173
+ get: (url, customConfig) => makeRequest("GET", url, null, customConfig),
174
+ post: (url, data, customConfig) => makeRequest("POST", url, data, customConfig),
175
+ delete: (url, customConfig) => makeRequest("DELETE", url, null, customConfig),
176
+ put: (url, data, customConfig) => makeRequest("PUT", url, data, customConfig),
177
+ patch: (url, data, customConfig) => makeRequest("PATCH", url, data, customConfig),
178
+ head: (url, customConfig) => makeRequest("HEAD", url, null, customConfig),
179
+ options: (url, customConfig) => makeRequest("OPTIONS", url, null, customConfig),
180
+ defaults: {
181
+ headers: defaultHeaders
182
+ },
183
+ interceptors: {
184
+ request: {
185
+ use: interceptors.request.use.bind(interceptors.request),
186
+ eject: interceptors.request.eject.bind(interceptors.request)
187
+ },
188
+ response: {
189
+ use: interceptors.response.use.bind(interceptors.response),
190
+ eject: interceptors.response.eject.bind(interceptors.response)
191
+ }
192
+ },
193
+ CancelToken,
194
+ isCancel
195
+ };
196
+ return client;
197
+ }
198
+
199
+ // src/client.ts
25
200
  var Client = class {
26
201
  /**
27
202
  * Creates a new Client instance
@@ -74,7 +249,8 @@ var Client = class {
74
249
  threadId: options.threadId,
75
250
  message: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
76
251
  streaming: true,
77
- background: options.background
252
+ background: options.background,
253
+ enableReturnStateWhenSteamCompleted: options.enableReturnStateWhenSteamCompleted
78
254
  },
79
255
  onEvent,
80
256
  onComplete,
@@ -108,18 +284,33 @@ var Client = class {
108
284
  };
109
285
  this.config = {
110
286
  timeout: 3e4,
287
+ environment: "web",
288
+ // Default to web environment
111
289
  ...config
112
290
  };
291
+ this.environment = this.config.environment || "web";
113
292
  this.assistantId = config.assistantId;
114
- this.client = axios.create({
115
- baseURL: this.config.baseURL,
116
- timeout: this.config.timeout,
117
- headers: {
118
- "Content-Type": "application/json",
119
- Authorization: `Bearer ${this.config.apiKey}`,
120
- ...this.config.headers
121
- }
122
- });
293
+ if (this.environment === "wechat-miniprogram") {
294
+ this.client = createWechatClient({
295
+ baseURL: this.config.baseURL,
296
+ timeout: this.config.timeout,
297
+ headers: {
298
+ "Content-Type": "application/json",
299
+ Authorization: `Bearer ${this.config.apiKey}`,
300
+ ...this.config.headers
301
+ }
302
+ });
303
+ } else {
304
+ this.client = axios.create({
305
+ baseURL: this.config.baseURL,
306
+ timeout: this.config.timeout,
307
+ headers: {
308
+ "Content-Type": "application/json",
309
+ Authorization: `Bearer ${this.config.apiKey}`,
310
+ ...this.config.headers
311
+ }
312
+ });
313
+ }
123
314
  this.setupInterceptors();
124
315
  }
125
316
  /**
@@ -321,24 +512,30 @@ var Client = class {
321
512
  * @returns A function that can be called to stop the stream
322
513
  */
323
514
  streamRun(options, onEvent, onComplete, onError) {
515
+ if (this.environment === "wechat-miniprogram") {
516
+ return this.streamRunWechat(options, onEvent, onComplete, onError);
517
+ } else {
518
+ return this.streamRunWeb(options, onEvent, onComplete, onError);
519
+ }
520
+ }
521
+ /**
522
+ * Stream run results using axios for web environment
523
+ * @private
524
+ */
525
+ streamRunWeb(options, onEvent, onComplete, onError) {
324
526
  const headers = {
325
527
  "Content-Type": "application/json"
326
528
  };
327
529
  if (this.tenantId) {
328
530
  headers["x-tenant-id"] = this.tenantId;
329
531
  }
330
- const controller = new AbortController();
331
- const signal = controller.signal;
532
+ const source = axios.CancelToken.source();
332
533
  (async () => {
333
534
  try {
334
- const response = await fetch(`${this.config.baseURL}/api/runs`, {
335
- method: "POST",
336
- headers: {
337
- "Content-Type": "application/json",
338
- Authorization: `Bearer ${this.config.apiKey}`,
339
- ...headers
340
- },
341
- body: JSON.stringify({
535
+ const axiosClient = this.client;
536
+ const response = await axiosClient.post(
537
+ "/api/runs",
538
+ {
342
539
  assistant_id: this.assistantId,
343
540
  thread_id: options.threadId,
344
541
  message: options.message,
@@ -346,54 +543,47 @@ var Client = class {
346
543
  command: options.command,
347
544
  streaming: true,
348
545
  background: options.background || false
349
- }),
350
- signal
351
- });
352
- if (!response.ok) {
353
- throw new Error(`HTTP error! status: ${response.status}`);
354
- }
355
- if (!response.body) {
356
- throw new Error("Response body is null");
357
- }
358
- const reader = response.body.getReader();
359
- const decoder = new TextDecoder();
360
- let buffer = "";
361
- while (true) {
362
- const { value, done } = await reader.read();
363
- if (done) {
364
- if (buffer.trim()) {
365
- try {
366
- const data = JSON.parse(buffer.trim());
367
- onEvent(data);
368
- } catch (error) {
369
- }
370
- }
371
- break;
372
- }
373
- const chunk = decoder.decode(value, { stream: true });
374
- buffer += chunk;
375
- const lines = buffer.split("\n");
376
- buffer = lines.pop() || "";
377
- for (const line of lines) {
378
- if (line.trim().startsWith("data: ")) {
379
- try {
380
- const data = JSON.parse(line.trim().slice(6));
381
- onEvent(data);
382
- } catch (error) {
383
- if (onError) {
384
- onError(
385
- error instanceof Error ? error : new Error(String(error))
386
- );
546
+ },
547
+ {
548
+ headers,
549
+ cancelToken: source.token,
550
+ responseType: "text",
551
+ transformResponse: (data) => {
552
+ if (!data)
553
+ return data;
554
+ const lines = data.split("\n");
555
+ for (const line of lines) {
556
+ if (line.trim().startsWith("data: ")) {
557
+ try {
558
+ const eventData = JSON.parse(line.trim().slice(6));
559
+ onEvent(eventData);
560
+ } catch (error) {
561
+ if (onError) {
562
+ onError(
563
+ error instanceof Error ? error : new Error(String(error))
564
+ );
565
+ }
566
+ }
387
567
  }
388
568
  }
569
+ return data;
389
570
  }
390
571
  }
391
- }
572
+ );
392
573
  if (onComplete) {
393
- onComplete();
574
+ if (options.enableReturnStateWhenSteamCompleted) {
575
+ try {
576
+ const state = await this.getAgentState(options.threadId);
577
+ onComplete(state);
578
+ } catch (error) {
579
+ onComplete();
580
+ }
581
+ } else {
582
+ onComplete();
583
+ }
394
584
  }
395
585
  } catch (error) {
396
- if (signal.aborted) {
586
+ if (axios.isCancel(error)) {
397
587
  return;
398
588
  }
399
589
  if (onError) {
@@ -402,7 +592,74 @@ var Client = class {
402
592
  }
403
593
  })();
404
594
  return () => {
405
- controller.abort();
595
+ source.cancel("Request cancelled by user");
596
+ };
597
+ }
598
+ /**
599
+ * Stream run results using WeChat Mini Program request API
600
+ * @private
601
+ */
602
+ streamRunWechat(options, onEvent, onComplete, onError) {
603
+ const wechatClient = this.client;
604
+ let isRunning = true;
605
+ let messageId = null;
606
+ const poll = async () => {
607
+ if (!isRunning)
608
+ return;
609
+ try {
610
+ if (!messageId) {
611
+ const response = await wechatClient.post("/api/runs", {
612
+ assistant_id: this.assistantId,
613
+ thread_id: options.threadId,
614
+ message: options.message,
615
+ files: options.files,
616
+ command: options.command,
617
+ streaming: false,
618
+ // We can't do true streaming in WeChat
619
+ background: options.background || false
620
+ });
621
+ if (response.data && response.data.id) {
622
+ messageId = response.data.id;
623
+ onEvent({
624
+ type: "ai",
625
+ data: {
626
+ id: messageId,
627
+ content: response.data.output || ""
628
+ }
629
+ });
630
+ if (response.data.tool_calls && response.data.tool_calls.length > 0) {
631
+ onEvent({
632
+ type: "ai",
633
+ data: {
634
+ id: messageId,
635
+ tool_calls: response.data.tool_calls
636
+ }
637
+ });
638
+ }
639
+ if (onComplete) {
640
+ if (options.enableReturnStateWhenSteamCompleted) {
641
+ try {
642
+ const state = await this.getAgentState(options.threadId);
643
+ onComplete(state);
644
+ } catch (error) {
645
+ onComplete();
646
+ }
647
+ } else {
648
+ onComplete();
649
+ }
650
+ }
651
+ }
652
+ }
653
+ } catch (error) {
654
+ if (onError) {
655
+ onError(error instanceof Error ? error : new Error(String(error)));
656
+ }
657
+ isRunning = false;
658
+ }
659
+ };
660
+ poll();
661
+ return () => {
662
+ isRunning = false;
406
663
  };
407
664
  }
408
665
  };
@@ -489,7 +746,6 @@ function createSimpleMessageMerger() {
489
746
  messages = msgs;
490
747
  }
491
748
  function push(chunk) {
492
- console.log(chunk);
493
749
  const role = normalizeRole(chunk.type);
494
750
  const message = ensureMessage(chunk.data.id, role);
495
751
  if (chunk.data.content) {
@@ -525,7 +781,8 @@ function createSimpleMessageMerger() {
525
781
  name: tc.name,
526
782
  args: tc.args,
527
783
  type: "tool_call",
528
- response: tc.response
784
+ response: tc.response,
785
+ status: "success"
529
786
  }));
530
787
  if (toolCalls.length > 0) {
531
788
  message.tool_calls = toolCalls;
@@ -568,7 +825,8 @@ function createSimpleMessageMerger() {
568
825
  if (toolResponse) {
569
826
  return {
570
827
  ...toolCall,
571
- response: toolResponse.content
828
+ response: toolResponse.content,
829
+ status: "success"
572
830
  };
573
831
  }
574
832
  return toolCall;