@yushaw/sanqian-chat 0.1.1 → 0.2.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.
@@ -1,4 +1,491 @@
1
+ // src/core/history.ts
2
+ function safeParseArgs(value) {
3
+ if (!value) return void 0;
4
+ if (typeof value === "object") return value;
5
+ if (typeof value === "string") {
6
+ try {
7
+ return JSON.parse(value);
8
+ } catch {
9
+ return void 0;
10
+ }
11
+ }
12
+ return void 0;
13
+ }
14
+ function parseToolCalls(toolCalls) {
15
+ if (!toolCalls) return void 0;
16
+ let calls = toolCalls;
17
+ if (typeof calls === "string") {
18
+ try {
19
+ calls = JSON.parse(calls);
20
+ } catch {
21
+ return void 0;
22
+ }
23
+ }
24
+ if (!Array.isArray(calls)) return void 0;
25
+ return calls.map((tc) => {
26
+ const fn = tc.function || void 0;
27
+ const name = fn?.name || tc.name || tc.tool_name || "";
28
+ const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
29
+ const args = safeParseArgs(rawArgs);
30
+ const id = tc.id || tc.tool_call_id || tc.call_id;
31
+ return {
32
+ id,
33
+ name,
34
+ args,
35
+ status: "completed",
36
+ result: tc.result
37
+ };
38
+ }).filter((tc) => tc.name || tc.id);
39
+ }
40
+ function getNumericMessageId(message) {
41
+ if (typeof message.message_id === "number") {
42
+ return message.message_id;
43
+ }
44
+ if (typeof message.id === "string" && /^\d+$/.test(message.id)) {
45
+ return Number(message.id);
46
+ }
47
+ return void 0;
48
+ }
49
+ function mergeConsecutiveAssistantMessages(rawMessages) {
50
+ const result = [];
51
+ let i = 0;
52
+ while (i < rawMessages.length) {
53
+ const msg = rawMessages[i];
54
+ const numericMessageId = getNumericMessageId(msg);
55
+ const messageId = numericMessageId ? `history-${numericMessageId}` : msg.id || `history-${i}`;
56
+ if (msg.role === "assistant") {
57
+ const consecutiveAssistantMsgs = [msg];
58
+ const toolMessages = [];
59
+ let j = i + 1;
60
+ while (j < rawMessages.length) {
61
+ if (rawMessages[j].role === "assistant") {
62
+ consecutiveAssistantMsgs.push(rawMessages[j]);
63
+ j++;
64
+ } else if (rawMessages[j].role === "tool") {
65
+ toolMessages.push(rawMessages[j]);
66
+ j++;
67
+ } else {
68
+ break;
69
+ }
70
+ }
71
+ const blocks = [];
72
+ let blockTime = Date.now();
73
+ let fallbackToolCalls;
74
+ let lastEffectiveToolCalls;
75
+ for (let k = 0; k < consecutiveAssistantMsgs.length; k++) {
76
+ const assistantMsg = consecutiveAssistantMsgs[k];
77
+ const msgToolCalls = parseToolCalls(assistantMsg.toolCalls || assistantMsg.tool_calls);
78
+ const isLastAssistant = k === consecutiveAssistantMsgs.length - 1;
79
+ const fallbackCalls = isLastAssistant && toolMessages.length > 0 ? toolMessages.map((toolMessage, idx) => ({
80
+ id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
81
+ name: "",
82
+ args: void 0,
83
+ status: "completed",
84
+ result: toolMessage.content
85
+ })) : void 0;
86
+ const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
87
+ if (!msgToolCalls || msgToolCalls.length === 0) {
88
+ if (effectiveToolCalls && effectiveToolCalls.length > 0) {
89
+ fallbackToolCalls = effectiveToolCalls;
90
+ }
91
+ }
92
+ lastEffectiveToolCalls = effectiveToolCalls;
93
+ const hasToolCalls = effectiveToolCalls && effectiveToolCalls.length > 0;
94
+ if (assistantMsg.thinking && assistantMsg.thinking.trim()) {
95
+ blocks.push({
96
+ type: "thinking",
97
+ content: assistantMsg.thinking,
98
+ timestamp: blockTime++,
99
+ isIntermediate: true
100
+ });
101
+ }
102
+ const shouldDeferText = Boolean(hasToolCalls && isLastAssistant && toolMessages.length === 0);
103
+ const hasContent = Boolean(assistantMsg.content && assistantMsg.content.trim());
104
+ if (hasContent && !shouldDeferText) {
105
+ blocks.push({
106
+ type: "text",
107
+ content: assistantMsg.content,
108
+ timestamp: blockTime++,
109
+ isIntermediate: hasToolCalls || !isLastAssistant
110
+ });
111
+ }
112
+ if (effectiveToolCalls) {
113
+ const toolResultBlocks = [];
114
+ for (const tc of effectiveToolCalls) {
115
+ const toolIndex = effectiveToolCalls.indexOf(tc);
116
+ blocks.push({
117
+ type: "tool_call",
118
+ content: "",
119
+ timestamp: blockTime++,
120
+ toolName: tc.name,
121
+ toolArgs: tc.args,
122
+ toolCallId: tc.id,
123
+ toolStatus: "completed",
124
+ isIntermediate: true
125
+ });
126
+ const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
127
+ const toolResultByIndex = toolMessages[toolIndex];
128
+ const toolResult = toolResultById || toolResultByIndex;
129
+ const resultContent = tc.result ?? toolResult?.content;
130
+ const toolResultId = toolResult?.tool_call_id || void 0;
131
+ if (resultContent) {
132
+ toolResultBlocks.push({
133
+ type: "tool_result",
134
+ content: resultContent,
135
+ timestamp: blockTime++,
136
+ toolName: tc.name,
137
+ toolCallId: tc.id || toolResultId,
138
+ isIntermediate: true
139
+ });
140
+ tc.result = resultContent;
141
+ }
142
+ }
143
+ blocks.push(...toolResultBlocks);
144
+ }
145
+ if (hasContent && shouldDeferText) {
146
+ blocks.push({
147
+ type: "text",
148
+ content: assistantMsg.content,
149
+ timestamp: blockTime++,
150
+ isIntermediate: false
151
+ });
152
+ }
153
+ }
154
+ if (consecutiveAssistantMsgs.length > 1) {
155
+ let contentMessages = consecutiveAssistantMsgs.filter(
156
+ (m) => !m.toolCalls && !m.tool_calls
157
+ );
158
+ if (contentMessages.length === 0) {
159
+ contentMessages = [consecutiveAssistantMsgs[consecutiveAssistantMsgs.length - 1]];
160
+ }
161
+ const mergedContent = contentMessages.map((m) => m.content).filter((c) => c && c.trim()).join("\n\n");
162
+ const mergedToolCalls = consecutiveAssistantMsgs.flatMap((m) => parseToolCalls(m.toolCalls || m.tool_calls) || []);
163
+ const effectiveMergedToolCalls = mergedToolCalls.length > 0 ? mergedToolCalls : fallbackToolCalls || [];
164
+ for (const toolMsg of toolMessages) {
165
+ const toolCallId = toolMsg.tool_call_id;
166
+ const matchingToolCall = effectiveMergedToolCalls.find(
167
+ (tc) => toolCallId && tc.id === toolCallId || !tc.result
168
+ );
169
+ if (matchingToolCall) {
170
+ matchingToolCall.result = toolMsg.content;
171
+ }
172
+ }
173
+ const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
174
+ const mergedThinking = thinkingParts.length > 1 ? thinkingParts.join("\n\u2500\u2500\u2500\u2500\u2500\n") : thinkingParts[0] || "";
175
+ const lastAssistantMsg = consecutiveAssistantMsgs[consecutiveAssistantMsgs.length - 1];
176
+ const lastToolMsg = toolMessages[toolMessages.length - 1];
177
+ const lastMsgId = Math.max(
178
+ getNumericMessageId(lastAssistantMsg) || 0,
179
+ lastToolMsg ? getNumericMessageId(lastToolMsg) || 0 : 0
180
+ );
181
+ const mergedMessageId = lastMsgId > 0 ? `history-${lastMsgId}` : messageId;
182
+ result.push({
183
+ id: mergedMessageId,
184
+ role: "assistant",
185
+ content: mergedContent,
186
+ timestamp: msg.timestamp || msg.created_at || (/* @__PURE__ */ new Date()).toISOString(),
187
+ toolCalls: effectiveMergedToolCalls.length > 0 ? effectiveMergedToolCalls : void 0,
188
+ thinking: mergedThinking || void 0,
189
+ filePaths: msg.filePaths,
190
+ blocks: blocks.length > 0 ? blocks : void 0,
191
+ isComplete: true
192
+ });
193
+ i = j;
194
+ } else {
195
+ result.push({
196
+ id: messageId,
197
+ role: "assistant",
198
+ content: msg.content || "",
199
+ timestamp: msg.timestamp || msg.created_at || (/* @__PURE__ */ new Date()).toISOString(),
200
+ toolCalls: lastEffectiveToolCalls,
201
+ thinking: msg.thinking || void 0,
202
+ filePaths: msg.filePaths,
203
+ blocks: blocks.length > 0 ? blocks : void 0,
204
+ isComplete: true
205
+ });
206
+ i++;
207
+ }
208
+ } else if (msg.role === "tool") {
209
+ i++;
210
+ } else {
211
+ result.push({
212
+ id: messageId,
213
+ role: msg.role,
214
+ content: msg.content || "",
215
+ timestamp: msg.timestamp || msg.created_at || (/* @__PURE__ */ new Date()).toISOString(),
216
+ toolCalls: parseToolCalls(msg.toolCalls || msg.tool_calls),
217
+ thinking: msg.thinking || void 0,
218
+ filePaths: msg.filePaths
219
+ });
220
+ i++;
221
+ }
222
+ }
223
+ return result;
224
+ }
225
+
1
226
  // src/core/adapter.ts
227
+ function createChatAdapter(config) {
228
+ let sdkInstance = null;
229
+ let sdkPromise = null;
230
+ let connectionStatus = "disconnected";
231
+ const connectionListeners = /* @__PURE__ */ new Set();
232
+ let currentRunId = null;
233
+ let reconnectAcquired = false;
234
+ const updateStatus = (status, error, errorCode) => {
235
+ connectionStatus = status;
236
+ connectionListeners.forEach((cb) => cb(status, error, errorCode));
237
+ };
238
+ const ensureSdk = async () => {
239
+ if (sdkInstance) return sdkInstance;
240
+ if (sdkPromise) return sdkPromise;
241
+ sdkPromise = (async () => {
242
+ const { SanqianSDK: SDK } = await import("@yushaw/sanqian-sdk");
243
+ const tools = config.tools?.map((t) => ({
244
+ name: t.name,
245
+ description: t.description,
246
+ parameters: t.parameters,
247
+ handler: t.handler
248
+ })).filter((t) => !!t.handler) || [];
249
+ sdkInstance = new SDK({
250
+ appName: config.appName,
251
+ appVersion: config.appVersion,
252
+ tools
253
+ });
254
+ return sdkInstance;
255
+ })();
256
+ return sdkPromise;
257
+ };
258
+ return {
259
+ async connect() {
260
+ if (reconnectAcquired) {
261
+ return;
262
+ }
263
+ updateStatus("connecting");
264
+ try {
265
+ const sdk = await ensureSdk();
266
+ sdk.on("connected", () => updateStatus("connected"));
267
+ sdk.on("disconnected", () => {
268
+ if (reconnectAcquired && connectionStatus !== "disconnected") {
269
+ updateStatus("reconnecting");
270
+ }
271
+ });
272
+ sdk.on("error", (err) => updateStatus("error", err.message, "CONNECTION_FAILED"));
273
+ sdk.acquireReconnect();
274
+ reconnectAcquired = true;
275
+ await sdk.ensureReady();
276
+ updateStatus("connected");
277
+ } catch (e) {
278
+ updateStatus("error", e instanceof Error ? e.message : "Connection failed", "CONNECTION_FAILED");
279
+ throw e;
280
+ }
281
+ },
282
+ async disconnect() {
283
+ if (sdkInstance) {
284
+ if (reconnectAcquired) {
285
+ sdkInstance.releaseReconnect();
286
+ reconnectAcquired = false;
287
+ }
288
+ sdkInstance.removeAllListeners();
289
+ await sdkInstance.disconnect();
290
+ sdkInstance = null;
291
+ sdkPromise = null;
292
+ }
293
+ updateStatus("disconnected");
294
+ },
295
+ isConnected() {
296
+ return sdkInstance?.isConnected() ?? false;
297
+ },
298
+ getConnectionStatus() {
299
+ return connectionStatus;
300
+ },
301
+ onConnectionChange(callback) {
302
+ connectionListeners.add(callback);
303
+ callback(connectionStatus);
304
+ return () => connectionListeners.delete(callback);
305
+ },
306
+ async listConversations(options) {
307
+ const sdk = await ensureSdk();
308
+ await sdk.ensureReady();
309
+ const result = await sdk.listConversations({ agentId: config.agentId, ...options });
310
+ return {
311
+ conversations: result.conversations.map((c) => ({
312
+ id: c.conversation_id,
313
+ title: c.title || "Untitled",
314
+ createdAt: c.created_at || "",
315
+ updatedAt: c.updated_at || "",
316
+ messageCount: c.message_count,
317
+ agentId: c.agent_id || null
318
+ })),
319
+ total: result.total
320
+ };
321
+ },
322
+ async getConversation(id, options) {
323
+ const sdk = await ensureSdk();
324
+ await sdk.ensureReady();
325
+ const detail = await sdk.getConversation(id, { messageLimit: options?.messageLimit });
326
+ let rawMessages = detail.messages || [];
327
+ const sdkWithHistory = sdk;
328
+ if (typeof sdkWithHistory.getMessages === "function") {
329
+ try {
330
+ const history = await sdkWithHistory.getMessages(id, { limit: options?.messageLimit });
331
+ if (history?.messages && history.messages.length > 0) {
332
+ rawMessages = history.messages;
333
+ }
334
+ } catch (e) {
335
+ console.warn("[sanqian-chat] getMessages failed, fallback to getConversation:", e);
336
+ }
337
+ }
338
+ const normalizedMessages = mergeConsecutiveAssistantMessages(
339
+ rawMessages.map((m, i) => ({
340
+ id: m.id || `msg-${i}`,
341
+ role: m.role,
342
+ content: m.content,
343
+ created_at: m.created_at || void 0,
344
+ tool_calls: m.tool_calls || m.toolCalls,
345
+ tool_call_id: m.tool_call_id ?? null,
346
+ thinking: m.thinking || void 0,
347
+ message_id: m.message_id,
348
+ filePaths: m.file_paths || m.filePaths
349
+ }))
350
+ );
351
+ return {
352
+ id: detail.conversation_id,
353
+ title: detail.title || "Untitled",
354
+ createdAt: detail.created_at || "",
355
+ updatedAt: detail.updated_at || "",
356
+ messageCount: detail.message_count,
357
+ agentId: detail.agent_id || null,
358
+ messages: normalizedMessages
359
+ };
360
+ },
361
+ async deleteConversation(id) {
362
+ const sdk = await ensureSdk();
363
+ await sdk.ensureReady();
364
+ await sdk.deleteConversation(id);
365
+ },
366
+ async chatStream(messages, conversationId, onEvent, options) {
367
+ const sdk = await ensureSdk();
368
+ await sdk.ensureReady();
369
+ const agentId = options?.agentId ?? config.agentId;
370
+ const sdkMessages = messages.map((m) => ({ role: m.role, content: m.content }));
371
+ const stream = sdk.chatStream(
372
+ agentId,
373
+ sdkMessages,
374
+ {
375
+ conversationId,
376
+ persistHistory: config.persistHistory ?? false
377
+ }
378
+ );
379
+ return processStreamEvents(stream, onEvent, sdk, (id) => {
380
+ currentRunId = id;
381
+ });
382
+ },
383
+ sendHitlResponse(response, runId) {
384
+ if (!sdkInstance) return;
385
+ const id = runId || currentRunId;
386
+ if (id) {
387
+ sdkInstance.sendHitlResponse(id, response);
388
+ }
389
+ }
390
+ };
391
+ }
392
+ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId) {
393
+ const controller = new AbortController();
394
+ const signal = controller.signal;
395
+ let currentRunId = null;
396
+ (async () => {
397
+ try {
398
+ for await (const event of stream) {
399
+ if (signal.aborted) break;
400
+ switch (event.type) {
401
+ case "start":
402
+ if (event.run_id) {
403
+ currentRunId = event.run_id;
404
+ setCurrentRunId(event.run_id);
405
+ onEvent({ type: "start", run_id: event.run_id, conversationId: event.conversationId });
406
+ }
407
+ break;
408
+ case "text":
409
+ onEvent({ type: "text", content: event.content || "" });
410
+ break;
411
+ case "thinking":
412
+ onEvent({ type: "thinking", content: event.content || "" });
413
+ break;
414
+ case "tool_call":
415
+ if (event.tool_call) {
416
+ onEvent({ type: "tool_call", tool_call: event.tool_call });
417
+ }
418
+ break;
419
+ case "tool_args_chunk":
420
+ onEvent({
421
+ type: "tool_args_chunk",
422
+ tool_call_id: event.tool_call_id || "",
423
+ tool_name: event.tool_name,
424
+ chunk: event.chunk || ""
425
+ });
426
+ break;
427
+ case "tool_args":
428
+ onEvent({
429
+ type: "tool_args",
430
+ tool_call_id: event.tool_call_id || "",
431
+ tool_name: event.tool_name,
432
+ args: event.args || {}
433
+ });
434
+ break;
435
+ case "tool_result":
436
+ onEvent({ type: "tool_result", tool_call_id: event.tool_call_id || "", result: event.result });
437
+ break;
438
+ case "done":
439
+ onEvent({ type: "done", conversationId: event.conversationId || "", title: event.title });
440
+ currentRunId = null;
441
+ setCurrentRunId(null);
442
+ break;
443
+ case "cancelled":
444
+ onEvent({ type: "cancelled", run_id: event.run_id });
445
+ currentRunId = null;
446
+ setCurrentRunId(null);
447
+ break;
448
+ case "error":
449
+ onEvent({ type: "error", error: event.error || "Unknown error" });
450
+ currentRunId = null;
451
+ setCurrentRunId(null);
452
+ break;
453
+ default: {
454
+ const evt = event;
455
+ if (evt.type === "interrupt") {
456
+ currentRunId = evt.run_id || null;
457
+ setCurrentRunId(evt.run_id || null);
458
+ onEvent({
459
+ type: "interrupt",
460
+ interrupt_type: evt.interrupt_type || "",
461
+ interrupt_payload: evt.interrupt_payload,
462
+ run_id: evt.run_id
463
+ });
464
+ }
465
+ break;
466
+ }
467
+ }
468
+ }
469
+ } catch (e) {
470
+ if (!signal.aborted) {
471
+ onEvent({ type: "error", error: e instanceof Error ? e.message : "Stream error" });
472
+ }
473
+ }
474
+ })();
475
+ return {
476
+ cancel: () => {
477
+ controller.abort();
478
+ const sdkWithCancel = sdk;
479
+ if (currentRunId && typeof sdkWithCancel.cancelRun === "function") {
480
+ try {
481
+ sdkWithCancel.cancelRun(currentRunId);
482
+ } catch (e) {
483
+ console.warn("[chat adapter] Failed to cancel run:", e);
484
+ }
485
+ }
486
+ }
487
+ };
488
+ }
2
489
  function createSdkAdapter(config) {
3
490
  let connectionStatus = "disconnected";
4
491
  const connectionListeners = /* @__PURE__ */ new Set();
@@ -21,6 +508,10 @@ function createSdkAdapter(config) {
21
508
  }
22
509
  },
23
510
  async disconnect() {
511
+ const sdk = config.getSdk();
512
+ if (sdk) {
513
+ await sdk.disconnect();
514
+ }
24
515
  updateStatus("disconnected");
25
516
  },
26
517
  isConnected() {
@@ -46,7 +537,8 @@ function createSdkAdapter(config) {
46
537
  title: c.title || "Untitled",
47
538
  createdAt: c.created_at || "",
48
539
  updatedAt: c.updated_at || "",
49
- messageCount: c.message_count
540
+ messageCount: c.message_count,
541
+ agentId: c.agent_id || null
50
542
  })),
51
543
  total: result.total
52
544
  };
@@ -55,18 +547,39 @@ function createSdkAdapter(config) {
55
547
  const sdk = config.getSdk();
56
548
  if (!sdk) throw new Error("SDK not ready");
57
549
  const detail = await sdk.getConversation(id, { messageLimit: options?.messageLimit });
550
+ let rawMessages = detail.messages || [];
551
+ const sdkWithHistory = sdk;
552
+ if (typeof sdkWithHistory.getMessages === "function") {
553
+ try {
554
+ const history = await sdkWithHistory.getMessages(id, { limit: options?.messageLimit });
555
+ if (history?.messages && history.messages.length > 0) {
556
+ rawMessages = history.messages;
557
+ }
558
+ } catch (e) {
559
+ console.warn("[sanqian-chat] getMessages failed, fallback to getConversation:", e);
560
+ }
561
+ }
562
+ const normalizedMessages = mergeConsecutiveAssistantMessages(
563
+ rawMessages.map((m, i) => ({
564
+ id: m.id || `msg-${i}`,
565
+ role: m.role,
566
+ content: m.content,
567
+ created_at: m.created_at || void 0,
568
+ tool_calls: m.tool_calls || m.toolCalls,
569
+ tool_call_id: m.tool_call_id ?? null,
570
+ thinking: m.thinking || void 0,
571
+ message_id: m.message_id,
572
+ filePaths: m.file_paths || m.filePaths
573
+ }))
574
+ );
58
575
  return {
59
576
  id: detail.conversation_id,
60
577
  title: detail.title || "Untitled",
61
578
  createdAt: detail.created_at || "",
62
579
  updatedAt: detail.updated_at || "",
63
580
  messageCount: detail.message_count,
64
- messages: (detail.messages || []).map((m, i) => ({
65
- id: `msg-${i}`,
66
- role: m.role,
67
- content: m.content,
68
- timestamp: m.created_at || (/* @__PURE__ */ new Date()).toISOString()
69
- }))
581
+ agentId: detail.agent_id || null,
582
+ messages: normalizedMessages
70
583
  };
71
584
  },
72
585
  async deleteConversation(id) {
@@ -74,65 +587,20 @@ function createSdkAdapter(config) {
74
587
  if (!sdk) throw new Error("SDK not ready");
75
588
  await sdk.deleteConversation(id);
76
589
  },
77
- async chatStream(messages, conversationId, onEvent) {
590
+ async chatStream(messages, conversationId, onEvent, options) {
78
591
  const sdk = config.getSdk();
79
- const agentId = config.getAgentId();
592
+ const agentId = options?.agentId ?? config.getAgentId();
80
593
  if (!sdk || !agentId) throw new Error("SDK or agent not ready");
81
594
  await sdk.ensureReady();
82
595
  const sdkMessages = messages.map((m) => ({ role: m.role, content: m.content }));
83
- const stream = sdk.chatStream(agentId, sdkMessages, { conversationId });
84
- const controller = new AbortController();
85
- const signal = controller.signal;
86
- (async () => {
87
- try {
88
- for await (const event of stream) {
89
- if (signal.aborted) break;
90
- switch (event.type) {
91
- case "text":
92
- onEvent({ type: "text", content: event.content || "" });
93
- break;
94
- case "thinking":
95
- onEvent({ type: "thinking", content: event.content || "" });
96
- break;
97
- case "tool_call":
98
- if (event.tool_call) {
99
- onEvent({ type: "tool_call", tool_call: event.tool_call });
100
- }
101
- break;
102
- case "tool_result":
103
- onEvent({ type: "tool_result", tool_call_id: event.tool_call_id || "", result: event.result });
104
- break;
105
- case "done":
106
- onEvent({ type: "done", conversationId: event.conversationId || "", title: event.title });
107
- break;
108
- case "error":
109
- onEvent({ type: "error", error: event.error || "Unknown error" });
110
- break;
111
- default:
112
- const evt = event;
113
- if (evt.type === "interrupt") {
114
- currentRunId = evt.run_id || null;
115
- onEvent({
116
- type: "interrupt",
117
- interrupt_type: evt.interrupt_type || "",
118
- interrupt_payload: evt.interrupt_payload,
119
- run_id: evt.run_id
120
- });
121
- }
122
- break;
123
- }
124
- }
125
- } catch (e) {
126
- if (!signal.aborted) {
127
- onEvent({ type: "error", error: e instanceof Error ? e.message : "Stream error" });
128
- }
129
- }
130
- })();
131
- return {
132
- cancel: () => {
133
- controller.abort();
134
- }
135
- };
596
+ const stream = sdk.chatStream(
597
+ agentId,
598
+ sdkMessages,
599
+ { conversationId }
600
+ );
601
+ return processStreamEvents(stream, onEvent, sdk, (id) => {
602
+ currentRunId = id;
603
+ });
136
604
  },
137
605
  sendHitlResponse(response, runId) {
138
606
  const sdk = config.getSdk();
@@ -145,5 +613,8 @@ function createSdkAdapter(config) {
145
613
  };
146
614
  }
147
615
  export {
148
- createSdkAdapter
616
+ createChatAdapter,
617
+ createSdkAdapter,
618
+ mergeConsecutiveAssistantMessages,
619
+ parseToolCalls
149
620
  };