@yushaw/sanqian-chat 0.2.44 → 0.3.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.
@@ -93,6 +93,9 @@ interface ToolCall {
93
93
  status?: ToolCallStatus;
94
94
  result?: unknown;
95
95
  error?: string;
96
+ actionRequired?: string;
97
+ settingsTab?: string;
98
+ settingsSubTab?: string;
96
99
  }
97
100
  /** Message block for structured rendering */
98
101
  interface MessageBlock {
@@ -533,6 +536,11 @@ type StreamEvent = {
533
536
  type: 'tool_result';
534
537
  tool_call_id: string;
535
538
  result: unknown;
539
+ error?: string;
540
+ status?: 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
541
+ action_required?: string;
542
+ settings_tab?: string;
543
+ settings_sub_tab?: string;
536
544
  } | {
537
545
  type: 'done';
538
546
  conversationId: string;
@@ -93,6 +93,9 @@ interface ToolCall {
93
93
  status?: ToolCallStatus;
94
94
  result?: unknown;
95
95
  error?: string;
96
+ actionRequired?: string;
97
+ settingsTab?: string;
98
+ settingsSubTab?: string;
96
99
  }
97
100
  /** Message block for structured rendering */
98
101
  interface MessageBlock {
@@ -533,6 +536,11 @@ type StreamEvent = {
533
536
  type: 'tool_result';
534
537
  tool_call_id: string;
535
538
  result: unknown;
539
+ error?: string;
540
+ status?: 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
541
+ action_required?: string;
542
+ settings_tab?: string;
543
+ settings_sub_tab?: string;
536
544
  } | {
537
545
  type: 'done';
538
546
  conversationId: string;
@@ -37,6 +37,54 @@ __export(core_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(core_exports);
39
39
 
40
+ // src/core/tool-status.ts
41
+ function normalizeToolExecutionStatus(status) {
42
+ if (typeof status !== "string") return void 0;
43
+ switch (status.trim().toLowerCase()) {
44
+ case "success":
45
+ case "completed":
46
+ case "ok":
47
+ return "completed";
48
+ case "error":
49
+ case "failed":
50
+ return "error";
51
+ case "cancelled":
52
+ case "canceled":
53
+ return "cancelled";
54
+ case "running":
55
+ return "running";
56
+ case "pending":
57
+ return "pending";
58
+ default:
59
+ return void 0;
60
+ }
61
+ }
62
+ function deriveToolExecutionStatus(options) {
63
+ if (typeof options.actionRequired === "string" && options.actionRequired.length > 0) {
64
+ return "error";
65
+ }
66
+ if (options.error === true) {
67
+ return "error";
68
+ }
69
+ if (typeof options.error === "string" && options.error.trim().length > 0) {
70
+ return "error";
71
+ }
72
+ const normalizedStatus = normalizeToolExecutionStatus(options.status);
73
+ if (normalizedStatus) {
74
+ return normalizedStatus;
75
+ }
76
+ if (options.result !== void 0 && options.result !== null) {
77
+ if (typeof options.result === "string") {
78
+ const normalizedResult = options.result.trimStart();
79
+ if (normalizedResult.startsWith("\u274C") || normalizedResult.startsWith("Error:")) {
80
+ return "error";
81
+ }
82
+ }
83
+ return "completed";
84
+ }
85
+ return options.fallback ?? "running";
86
+ }
87
+
40
88
  // src/core/history.ts
41
89
  function safeParseArgs(value) {
42
90
  if (!value) return void 0;
@@ -67,12 +115,25 @@ function parseToolCalls(toolCalls) {
67
115
  const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
68
116
  const args = safeParseArgs(rawArgs);
69
117
  const id = tc.id || tc.tool_call_id || tc.call_id;
118
+ const actionRequired = tc.action_required || tc.actionRequired;
119
+ const settingsTab = tc.settings_tab || tc.settingsTab;
120
+ const settingsSubTab = tc.settings_sub_tab || tc.settingsSubTab;
70
121
  return {
71
122
  id,
72
123
  name,
73
124
  args,
74
- status: "completed",
75
- result: tc.result
125
+ result: tc.result,
126
+ error: typeof tc.error === "string" ? tc.error : void 0,
127
+ actionRequired,
128
+ settingsTab,
129
+ settingsSubTab,
130
+ status: deriveToolExecutionStatus({
131
+ status: tc.status,
132
+ result: tc.result,
133
+ actionRequired,
134
+ error: tc.error,
135
+ fallback: "completed"
136
+ })
76
137
  };
77
138
  }).filter((tc) => tc.name || tc.id);
78
139
  }
@@ -163,7 +224,10 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
163
224
  id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
164
225
  name: "",
165
226
  args: void 0,
166
- status: "completed",
227
+ status: deriveToolExecutionStatus({
228
+ result: toolMessage.content,
229
+ fallback: "completed"
230
+ }),
167
231
  result: toolMessage.content
168
232
  })) : void 0;
169
233
  const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
@@ -196,6 +260,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
196
260
  const toolResultBlocks = [];
197
261
  for (const tc of effectiveToolCalls) {
198
262
  const toolIndex = effectiveToolCalls.indexOf(tc);
263
+ const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
264
+ const toolResultByIndex = toolMessages[toolIndex];
265
+ const toolResult = toolResultById || toolResultByIndex;
266
+ const toolStatus = deriveToolExecutionStatus({
267
+ status: tc.status,
268
+ result: tc.result ?? toolResult?.content,
269
+ actionRequired: tc.actionRequired,
270
+ error: tc.error,
271
+ fallback: "completed"
272
+ });
199
273
  blocks.push({
200
274
  type: "tool_call",
201
275
  content: "",
@@ -203,12 +277,9 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
203
277
  toolName: tc.name,
204
278
  toolArgs: tc.args,
205
279
  toolCallId: tc.id,
206
- toolStatus: "completed",
280
+ toolStatus,
207
281
  isIntermediate: true
208
282
  });
209
- const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
210
- const toolResultByIndex = toolMessages[toolIndex];
211
- const toolResult = toolResultById || toolResultByIndex;
212
283
  const resultContent = tc.result ?? toolResult?.content;
213
284
  const toolResultId = toolResult?.tool_call_id || void 0;
214
285
  if (resultContent) {
@@ -251,6 +322,13 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
251
322
  );
252
323
  if (matchingToolCall) {
253
324
  matchingToolCall.result = toolMsg.content;
325
+ matchingToolCall.status = deriveToolExecutionStatus({
326
+ status: matchingToolCall.status,
327
+ result: toolMsg.content,
328
+ actionRequired: matchingToolCall.actionRequired,
329
+ error: matchingToolCall.error,
330
+ fallback: "completed"
331
+ });
254
332
  }
255
333
  }
256
334
  const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
@@ -568,9 +646,20 @@ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId, streamId) {
568
646
  args: event.args || {}
569
647
  });
570
648
  break;
571
- case "tool_result":
572
- forward({ type: "tool_result", tool_call_id: event.tool_call_id || "", result: event.result });
649
+ case "tool_result": {
650
+ const toolResultEvent = event;
651
+ forward({
652
+ type: "tool_result",
653
+ tool_call_id: toolResultEvent.tool_call_id || "",
654
+ result: toolResultEvent.result,
655
+ error: toolResultEvent.error,
656
+ status: toolResultEvent.status,
657
+ action_required: toolResultEvent.action_required,
658
+ settings_tab: toolResultEvent.settings_tab,
659
+ settings_sub_tab: toolResultEvent.settings_sub_tab
660
+ });
573
661
  break;
662
+ }
574
663
  case "done":
575
664
  forward({ type: "done", conversationId: event.conversationId || "", title: event.title });
576
665
  currentRunId = null;
@@ -1,3 +1,51 @@
1
+ // src/core/tool-status.ts
2
+ function normalizeToolExecutionStatus(status) {
3
+ if (typeof status !== "string") return void 0;
4
+ switch (status.trim().toLowerCase()) {
5
+ case "success":
6
+ case "completed":
7
+ case "ok":
8
+ return "completed";
9
+ case "error":
10
+ case "failed":
11
+ return "error";
12
+ case "cancelled":
13
+ case "canceled":
14
+ return "cancelled";
15
+ case "running":
16
+ return "running";
17
+ case "pending":
18
+ return "pending";
19
+ default:
20
+ return void 0;
21
+ }
22
+ }
23
+ function deriveToolExecutionStatus(options) {
24
+ if (typeof options.actionRequired === "string" && options.actionRequired.length > 0) {
25
+ return "error";
26
+ }
27
+ if (options.error === true) {
28
+ return "error";
29
+ }
30
+ if (typeof options.error === "string" && options.error.trim().length > 0) {
31
+ return "error";
32
+ }
33
+ const normalizedStatus = normalizeToolExecutionStatus(options.status);
34
+ if (normalizedStatus) {
35
+ return normalizedStatus;
36
+ }
37
+ if (options.result !== void 0 && options.result !== null) {
38
+ if (typeof options.result === "string") {
39
+ const normalizedResult = options.result.trimStart();
40
+ if (normalizedResult.startsWith("\u274C") || normalizedResult.startsWith("Error:")) {
41
+ return "error";
42
+ }
43
+ }
44
+ return "completed";
45
+ }
46
+ return options.fallback ?? "running";
47
+ }
48
+
1
49
  // src/core/history.ts
2
50
  function safeParseArgs(value) {
3
51
  if (!value) return void 0;
@@ -28,12 +76,25 @@ function parseToolCalls(toolCalls) {
28
76
  const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
29
77
  const args = safeParseArgs(rawArgs);
30
78
  const id = tc.id || tc.tool_call_id || tc.call_id;
79
+ const actionRequired = tc.action_required || tc.actionRequired;
80
+ const settingsTab = tc.settings_tab || tc.settingsTab;
81
+ const settingsSubTab = tc.settings_sub_tab || tc.settingsSubTab;
31
82
  return {
32
83
  id,
33
84
  name,
34
85
  args,
35
- status: "completed",
36
- result: tc.result
86
+ result: tc.result,
87
+ error: typeof tc.error === "string" ? tc.error : void 0,
88
+ actionRequired,
89
+ settingsTab,
90
+ settingsSubTab,
91
+ status: deriveToolExecutionStatus({
92
+ status: tc.status,
93
+ result: tc.result,
94
+ actionRequired,
95
+ error: tc.error,
96
+ fallback: "completed"
97
+ })
37
98
  };
38
99
  }).filter((tc) => tc.name || tc.id);
39
100
  }
@@ -124,7 +185,10 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
124
185
  id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
125
186
  name: "",
126
187
  args: void 0,
127
- status: "completed",
188
+ status: deriveToolExecutionStatus({
189
+ result: toolMessage.content,
190
+ fallback: "completed"
191
+ }),
128
192
  result: toolMessage.content
129
193
  })) : void 0;
130
194
  const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
@@ -157,6 +221,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
157
221
  const toolResultBlocks = [];
158
222
  for (const tc of effectiveToolCalls) {
159
223
  const toolIndex = effectiveToolCalls.indexOf(tc);
224
+ const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
225
+ const toolResultByIndex = toolMessages[toolIndex];
226
+ const toolResult = toolResultById || toolResultByIndex;
227
+ const toolStatus = deriveToolExecutionStatus({
228
+ status: tc.status,
229
+ result: tc.result ?? toolResult?.content,
230
+ actionRequired: tc.actionRequired,
231
+ error: tc.error,
232
+ fallback: "completed"
233
+ });
160
234
  blocks.push({
161
235
  type: "tool_call",
162
236
  content: "",
@@ -164,12 +238,9 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
164
238
  toolName: tc.name,
165
239
  toolArgs: tc.args,
166
240
  toolCallId: tc.id,
167
- toolStatus: "completed",
241
+ toolStatus,
168
242
  isIntermediate: true
169
243
  });
170
- const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
171
- const toolResultByIndex = toolMessages[toolIndex];
172
- const toolResult = toolResultById || toolResultByIndex;
173
244
  const resultContent = tc.result ?? toolResult?.content;
174
245
  const toolResultId = toolResult?.tool_call_id || void 0;
175
246
  if (resultContent) {
@@ -212,6 +283,13 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
212
283
  );
213
284
  if (matchingToolCall) {
214
285
  matchingToolCall.result = toolMsg.content;
286
+ matchingToolCall.status = deriveToolExecutionStatus({
287
+ status: matchingToolCall.status,
288
+ result: toolMsg.content,
289
+ actionRequired: matchingToolCall.actionRequired,
290
+ error: matchingToolCall.error,
291
+ fallback: "completed"
292
+ });
215
293
  }
216
294
  }
217
295
  const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
@@ -529,9 +607,20 @@ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId, streamId) {
529
607
  args: event.args || {}
530
608
  });
531
609
  break;
532
- case "tool_result":
533
- forward({ type: "tool_result", tool_call_id: event.tool_call_id || "", result: event.result });
610
+ case "tool_result": {
611
+ const toolResultEvent = event;
612
+ forward({
613
+ type: "tool_result",
614
+ tool_call_id: toolResultEvent.tool_call_id || "",
615
+ result: toolResultEvent.result,
616
+ error: toolResultEvent.error,
617
+ status: toolResultEvent.status,
618
+ action_required: toolResultEvent.action_required,
619
+ settings_tab: toolResultEvent.settings_tab,
620
+ settings_sub_tab: toolResultEvent.settings_sub_tab
621
+ });
534
622
  break;
623
+ }
535
624
  case "done":
536
625
  forward({ type: "done", conversationId: event.conversationId || "", title: event.title });
537
626
  currentRunId = null;
@@ -575,7 +575,14 @@ function registerStreamIpcHandlers(ipcMainHandle, ctx) {
575
575
  (runId, ownerWebContentsId) => ctx.rememberRunOwner(runId, ownerWebContentsId),
576
576
  { overwrite: true }
577
577
  );
578
- webContents.send("sanqian-chat:streamEvent", { streamId, event: { type: "start", run_id: startEvt.run_id } });
578
+ webContents.send("sanqian-chat:streamEvent", {
579
+ streamId,
580
+ event: {
581
+ type: "start",
582
+ run_id: startEvt.run_id,
583
+ conversationId: startEvt.conversationId
584
+ }
585
+ });
579
586
  break;
580
587
  }
581
588
  case "text":
@@ -587,8 +594,42 @@ function registerStreamIpcHandlers(ipcMainHandle, ctx) {
587
594
  case "tool_call":
588
595
  webContents.send("sanqian-chat:streamEvent", { streamId, event: { type: "tool_call", tool_call: evt.tool_call } });
589
596
  break;
597
+ case "tool_args_chunk":
598
+ webContents.send("sanqian-chat:streamEvent", {
599
+ streamId,
600
+ event: {
601
+ type: "tool_args_chunk",
602
+ tool_call_id: evt.tool_call_id,
603
+ tool_name: evt.tool_name,
604
+ chunk: evt.chunk
605
+ }
606
+ });
607
+ break;
608
+ case "tool_args":
609
+ webContents.send("sanqian-chat:streamEvent", {
610
+ streamId,
611
+ event: {
612
+ type: "tool_args",
613
+ tool_call_id: evt.tool_call_id,
614
+ tool_name: evt.tool_name,
615
+ args: evt.args
616
+ }
617
+ });
618
+ break;
590
619
  case "tool_result":
591
- webContents.send("sanqian-chat:streamEvent", { streamId, event: { type: "tool_result", tool_call_id: evt.tool_call_id, result: evt.result } });
620
+ webContents.send("sanqian-chat:streamEvent", {
621
+ streamId,
622
+ event: {
623
+ type: "tool_result",
624
+ tool_call_id: evt.tool_call_id,
625
+ result: evt.result,
626
+ error: evt.error,
627
+ status: evt.status,
628
+ action_required: evt.action_required,
629
+ settings_tab: evt.settings_tab,
630
+ settings_sub_tab: evt.settings_sub_tab
631
+ }
632
+ });
592
633
  break;
593
634
  case "done":
594
635
  sawTerminalEvent = true;
@@ -544,7 +544,14 @@ function registerStreamIpcHandlers(ipcMainHandle, ctx) {
544
544
  (runId, ownerWebContentsId) => ctx.rememberRunOwner(runId, ownerWebContentsId),
545
545
  { overwrite: true }
546
546
  );
547
- webContents.send("sanqian-chat:streamEvent", { streamId, event: { type: "start", run_id: startEvt.run_id } });
547
+ webContents.send("sanqian-chat:streamEvent", {
548
+ streamId,
549
+ event: {
550
+ type: "start",
551
+ run_id: startEvt.run_id,
552
+ conversationId: startEvt.conversationId
553
+ }
554
+ });
548
555
  break;
549
556
  }
550
557
  case "text":
@@ -556,8 +563,42 @@ function registerStreamIpcHandlers(ipcMainHandle, ctx) {
556
563
  case "tool_call":
557
564
  webContents.send("sanqian-chat:streamEvent", { streamId, event: { type: "tool_call", tool_call: evt.tool_call } });
558
565
  break;
566
+ case "tool_args_chunk":
567
+ webContents.send("sanqian-chat:streamEvent", {
568
+ streamId,
569
+ event: {
570
+ type: "tool_args_chunk",
571
+ tool_call_id: evt.tool_call_id,
572
+ tool_name: evt.tool_name,
573
+ chunk: evt.chunk
574
+ }
575
+ });
576
+ break;
577
+ case "tool_args":
578
+ webContents.send("sanqian-chat:streamEvent", {
579
+ streamId,
580
+ event: {
581
+ type: "tool_args",
582
+ tool_call_id: evt.tool_call_id,
583
+ tool_name: evt.tool_name,
584
+ args: evt.args
585
+ }
586
+ });
587
+ break;
559
588
  case "tool_result":
560
- webContents.send("sanqian-chat:streamEvent", { streamId, event: { type: "tool_result", tool_call_id: evt.tool_call_id, result: evt.result } });
589
+ webContents.send("sanqian-chat:streamEvent", {
590
+ streamId,
591
+ event: {
592
+ type: "tool_result",
593
+ tool_call_id: evt.tool_call_id,
594
+ result: evt.result,
595
+ error: evt.error,
596
+ status: evt.status,
597
+ action_required: evt.action_required,
598
+ settings_tab: evt.settings_tab,
599
+ settings_sub_tab: evt.settings_sub_tab
600
+ }
601
+ });
561
602
  break;
562
603
  case "done":
563
604
  sawTerminalEvent = true;
@@ -96,6 +96,9 @@ interface ToolCall {
96
96
  status?: ToolCallStatus;
97
97
  result?: unknown;
98
98
  error?: string;
99
+ actionRequired?: string;
100
+ settingsTab?: string;
101
+ settingsSubTab?: string;
99
102
  }
100
103
  /** Message block for structured rendering */
101
104
  interface MessageBlock {
@@ -536,6 +539,11 @@ type StreamEvent = {
536
539
  type: 'tool_result';
537
540
  tool_call_id: string;
538
541
  result: unknown;
542
+ error?: string;
543
+ status?: 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
544
+ action_required?: string;
545
+ settings_tab?: string;
546
+ settings_sub_tab?: string;
539
547
  } | {
540
548
  type: 'done';
541
549
  conversationId: string;
@@ -96,6 +96,9 @@ interface ToolCall {
96
96
  status?: ToolCallStatus;
97
97
  result?: unknown;
98
98
  error?: string;
99
+ actionRequired?: string;
100
+ settingsTab?: string;
101
+ settingsSubTab?: string;
99
102
  }
100
103
  /** Message block for structured rendering */
101
104
  interface MessageBlock {
@@ -536,6 +539,11 @@ type StreamEvent = {
536
539
  type: 'tool_result';
537
540
  tool_call_id: string;
538
541
  result: unknown;
542
+ error?: string;
543
+ status?: 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
544
+ action_required?: string;
545
+ settings_tab?: string;
546
+ settings_sub_tab?: string;
539
547
  } | {
540
548
  type: 'done';
541
549
  conversationId: string;