@yushaw/sanqian-chat 0.3.0 → 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.
- package/dist/core/index.d.mts +8 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +98 -9
- package/dist/core/index.mjs +98 -9
- package/dist/main/index.js +13 -1
- package/dist/main/index.mjs +13 -1
- package/dist/renderer/index.d.mts +8 -0
- package/dist/renderer/index.d.ts +8 -0
- package/dist/renderer/index.js +175 -34
- package/dist/renderer/index.mjs +175 -34
- package/package.json +2 -2
package/dist/core/index.d.mts
CHANGED
|
@@ -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;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -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;
|
package/dist/core/index.js
CHANGED
|
@@ -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
|
-
|
|
75
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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;
|
package/dist/core/index.mjs
CHANGED
|
@@ -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
|
-
|
|
36
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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;
|
package/dist/main/index.js
CHANGED
|
@@ -617,7 +617,19 @@ function registerStreamIpcHandlers(ipcMainHandle, ctx) {
|
|
|
617
617
|
});
|
|
618
618
|
break;
|
|
619
619
|
case "tool_result":
|
|
620
|
-
webContents.send("sanqian-chat:streamEvent", {
|
|
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
|
+
});
|
|
621
633
|
break;
|
|
622
634
|
case "done":
|
|
623
635
|
sawTerminalEvent = true;
|
package/dist/main/index.mjs
CHANGED
|
@@ -586,7 +586,19 @@ function registerStreamIpcHandlers(ipcMainHandle, ctx) {
|
|
|
586
586
|
});
|
|
587
587
|
break;
|
|
588
588
|
case "tool_result":
|
|
589
|
-
webContents.send("sanqian-chat:streamEvent", {
|
|
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
|
+
});
|
|
590
602
|
break;
|
|
591
603
|
case "done":
|
|
592
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;
|
package/dist/renderer/index.d.ts
CHANGED
|
@@ -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;
|
package/dist/renderer/index.js
CHANGED
|
@@ -88,6 +88,67 @@ module.exports = __toCommonJS(renderer_exports);
|
|
|
88
88
|
|
|
89
89
|
// src/renderer/hooks/useChat.ts
|
|
90
90
|
var import_react = require("react");
|
|
91
|
+
|
|
92
|
+
// src/core/tool-status.ts
|
|
93
|
+
function normalizeToolExecutionStatus(status) {
|
|
94
|
+
if (typeof status !== "string") return void 0;
|
|
95
|
+
switch (status.trim().toLowerCase()) {
|
|
96
|
+
case "success":
|
|
97
|
+
case "completed":
|
|
98
|
+
case "ok":
|
|
99
|
+
return "completed";
|
|
100
|
+
case "error":
|
|
101
|
+
case "failed":
|
|
102
|
+
return "error";
|
|
103
|
+
case "cancelled":
|
|
104
|
+
case "canceled":
|
|
105
|
+
return "cancelled";
|
|
106
|
+
case "running":
|
|
107
|
+
return "running";
|
|
108
|
+
case "pending":
|
|
109
|
+
return "pending";
|
|
110
|
+
default:
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function deriveToolExecutionStatus(options) {
|
|
115
|
+
if (typeof options.actionRequired === "string" && options.actionRequired.length > 0) {
|
|
116
|
+
return "error";
|
|
117
|
+
}
|
|
118
|
+
if (options.error === true) {
|
|
119
|
+
return "error";
|
|
120
|
+
}
|
|
121
|
+
if (typeof options.error === "string" && options.error.trim().length > 0) {
|
|
122
|
+
return "error";
|
|
123
|
+
}
|
|
124
|
+
const normalizedStatus = normalizeToolExecutionStatus(options.status);
|
|
125
|
+
if (normalizedStatus) {
|
|
126
|
+
return normalizedStatus;
|
|
127
|
+
}
|
|
128
|
+
if (options.result !== void 0 && options.result !== null) {
|
|
129
|
+
if (typeof options.result === "string") {
|
|
130
|
+
const normalizedResult = options.result.trimStart();
|
|
131
|
+
if (normalizedResult.startsWith("\u274C") || normalizedResult.startsWith("Error:")) {
|
|
132
|
+
return "error";
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return "completed";
|
|
136
|
+
}
|
|
137
|
+
return options.fallback ?? "running";
|
|
138
|
+
}
|
|
139
|
+
function formatToolResultContent(result, error) {
|
|
140
|
+
const value = result ?? error;
|
|
141
|
+
if (value === void 0 || value === null) return void 0;
|
|
142
|
+
if (typeof value === "string") return value;
|
|
143
|
+
try {
|
|
144
|
+
const serialized = JSON.stringify(value);
|
|
145
|
+
return serialized === void 0 ? String(value) : serialized;
|
|
146
|
+
} catch {
|
|
147
|
+
return String(value);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/renderer/hooks/useChat.ts
|
|
91
152
|
var TYPEWRITER_DELAYS = { VERY_FAST: 2, FAST: 5, NORMAL: 10, SLOW: 20 };
|
|
92
153
|
var TYPEWRITER_THRESHOLDS = { VERY_FAST: 100, FAST: 50, NORMAL: 20 };
|
|
93
154
|
var MAX_DETACHED_SNAPSHOTS = 30;
|
|
@@ -108,6 +169,15 @@ var findLastBlock = (blocks, predicate) => {
|
|
|
108
169
|
}
|
|
109
170
|
return void 0;
|
|
110
171
|
};
|
|
172
|
+
function getToolResultStatus(event) {
|
|
173
|
+
return deriveToolExecutionStatus({
|
|
174
|
+
status: event.status,
|
|
175
|
+
result: event.result,
|
|
176
|
+
actionRequired: event.action_required,
|
|
177
|
+
error: event.error,
|
|
178
|
+
fallback: "completed"
|
|
179
|
+
});
|
|
180
|
+
}
|
|
111
181
|
function cloneBlocks(blocks) {
|
|
112
182
|
return blocks?.map((block) => ({
|
|
113
183
|
...block,
|
|
@@ -251,7 +321,17 @@ function updateDetachedSnapshotForEvent(streamContext, event) {
|
|
|
251
321
|
return true;
|
|
252
322
|
}
|
|
253
323
|
case "tool_result": {
|
|
254
|
-
const
|
|
324
|
+
const toolStatus = getToolResultStatus(event);
|
|
325
|
+
const resultContent = formatToolResultContent(event.result, event.error);
|
|
326
|
+
const toolCalls = (assistant.toolCalls || []).map((toolCall) => toolCall.id === event.tool_call_id ? {
|
|
327
|
+
...toolCall,
|
|
328
|
+
status: toolStatus,
|
|
329
|
+
result: event.result,
|
|
330
|
+
error: toolStatus === "error" ? typeof event.error === "string" && event.error.trim().length > 0 ? event.error : resultContent : void 0,
|
|
331
|
+
actionRequired: event.action_required,
|
|
332
|
+
settingsTab: event.settings_tab,
|
|
333
|
+
settingsSubTab: event.settings_sub_tab
|
|
334
|
+
} : toolCall);
|
|
255
335
|
const hasRunning = toolCalls.some((toolCall) => toolCall.status === "running");
|
|
256
336
|
const blocks = cloneBlocks(assistant.blocks) || [];
|
|
257
337
|
const toolBlockIndex = blocks.findIndex(
|
|
@@ -260,17 +340,19 @@ function updateDetachedSnapshotForEvent(streamContext, event) {
|
|
|
260
340
|
if (toolBlockIndex !== -1) {
|
|
261
341
|
blocks[toolBlockIndex] = {
|
|
262
342
|
...blocks[toolBlockIndex],
|
|
263
|
-
toolStatus
|
|
343
|
+
toolStatus
|
|
264
344
|
};
|
|
265
345
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
346
|
+
if (resultContent) {
|
|
347
|
+
blocks.push({
|
|
348
|
+
type: "tool_result",
|
|
349
|
+
content: resultContent,
|
|
350
|
+
timestamp: Date.now(),
|
|
351
|
+
toolName: toolBlockIndex !== -1 ? blocks[toolBlockIndex].toolName : void 0,
|
|
352
|
+
toolCallId: event.tool_call_id,
|
|
353
|
+
isIntermediate: true
|
|
354
|
+
});
|
|
355
|
+
}
|
|
274
356
|
snapshot[assistantIndex] = {
|
|
275
357
|
...assistant,
|
|
276
358
|
toolCalls,
|
|
@@ -992,24 +1074,35 @@ function useChat(options) {
|
|
|
992
1074
|
case "tool_result": {
|
|
993
1075
|
flushTypewriter();
|
|
994
1076
|
const toolId = event.tool_call_id;
|
|
995
|
-
const
|
|
1077
|
+
const toolStatus = getToolResultStatus(event);
|
|
1078
|
+
const resultContent = formatToolResultContent(event.result, event.error);
|
|
996
1079
|
const blockIdx = currentBlocksRef.current.findIndex((b) => b.type === "tool_call" && b.toolCallId === toolId);
|
|
997
1080
|
const toolName = blockIdx !== -1 ? currentBlocksRef.current[blockIdx].toolName : void 0;
|
|
998
|
-
if (blockIdx !== -1) currentBlocksRef.current[blockIdx].toolStatus =
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1081
|
+
if (blockIdx !== -1) currentBlocksRef.current[blockIdx].toolStatus = toolStatus;
|
|
1082
|
+
if (resultContent) {
|
|
1083
|
+
currentBlocksRef.current.push({
|
|
1084
|
+
type: "tool_result",
|
|
1085
|
+
content: resultContent,
|
|
1086
|
+
timestamp: Date.now(),
|
|
1087
|
+
toolName,
|
|
1088
|
+
toolCallId: toolId,
|
|
1089
|
+
isIntermediate: true
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1007
1092
|
setMessages((prev) => {
|
|
1008
1093
|
const idx = prev.findIndex((m) => m.id === assistantMessageId);
|
|
1009
1094
|
if (idx === -1) return prev;
|
|
1010
1095
|
const msg = prev[idx];
|
|
1011
1096
|
const updatedCalls = (msg.toolCalls || []).map(
|
|
1012
|
-
(t) => t.id === toolId ? {
|
|
1097
|
+
(t) => t.id === toolId ? {
|
|
1098
|
+
...t,
|
|
1099
|
+
status: toolStatus,
|
|
1100
|
+
result: event.result,
|
|
1101
|
+
error: toolStatus === "error" ? typeof event.error === "string" && event.error.trim().length > 0 ? event.error : resultContent : void 0,
|
|
1102
|
+
actionRequired: event.action_required,
|
|
1103
|
+
settingsTab: event.settings_tab,
|
|
1104
|
+
settingsSubTab: event.settings_sub_tab
|
|
1105
|
+
} : t
|
|
1013
1106
|
);
|
|
1014
1107
|
const hasRunning = updatedCalls.some((tc) => tc.status === "running");
|
|
1015
1108
|
const updated = [...prev];
|
|
@@ -6395,12 +6488,25 @@ function parseToolCalls(toolCalls) {
|
|
|
6395
6488
|
const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
|
|
6396
6489
|
const args = safeParseArgs(rawArgs);
|
|
6397
6490
|
const id = tc.id || tc.tool_call_id || tc.call_id;
|
|
6491
|
+
const actionRequired = tc.action_required || tc.actionRequired;
|
|
6492
|
+
const settingsTab = tc.settings_tab || tc.settingsTab;
|
|
6493
|
+
const settingsSubTab = tc.settings_sub_tab || tc.settingsSubTab;
|
|
6398
6494
|
return {
|
|
6399
6495
|
id,
|
|
6400
6496
|
name,
|
|
6401
6497
|
args,
|
|
6402
|
-
|
|
6403
|
-
|
|
6498
|
+
result: tc.result,
|
|
6499
|
+
error: typeof tc.error === "string" ? tc.error : void 0,
|
|
6500
|
+
actionRequired,
|
|
6501
|
+
settingsTab,
|
|
6502
|
+
settingsSubTab,
|
|
6503
|
+
status: deriveToolExecutionStatus({
|
|
6504
|
+
status: tc.status,
|
|
6505
|
+
result: tc.result,
|
|
6506
|
+
actionRequired,
|
|
6507
|
+
error: tc.error,
|
|
6508
|
+
fallback: "completed"
|
|
6509
|
+
})
|
|
6404
6510
|
};
|
|
6405
6511
|
}).filter((tc) => tc.name || tc.id);
|
|
6406
6512
|
}
|
|
@@ -6491,7 +6597,10 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6491
6597
|
id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
|
|
6492
6598
|
name: "",
|
|
6493
6599
|
args: void 0,
|
|
6494
|
-
status:
|
|
6600
|
+
status: deriveToolExecutionStatus({
|
|
6601
|
+
result: toolMessage.content,
|
|
6602
|
+
fallback: "completed"
|
|
6603
|
+
}),
|
|
6495
6604
|
result: toolMessage.content
|
|
6496
6605
|
})) : void 0;
|
|
6497
6606
|
const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
|
|
@@ -6524,6 +6633,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6524
6633
|
const toolResultBlocks = [];
|
|
6525
6634
|
for (const tc of effectiveToolCalls) {
|
|
6526
6635
|
const toolIndex = effectiveToolCalls.indexOf(tc);
|
|
6636
|
+
const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
|
|
6637
|
+
const toolResultByIndex = toolMessages[toolIndex];
|
|
6638
|
+
const toolResult = toolResultById || toolResultByIndex;
|
|
6639
|
+
const toolStatus = deriveToolExecutionStatus({
|
|
6640
|
+
status: tc.status,
|
|
6641
|
+
result: tc.result ?? toolResult?.content,
|
|
6642
|
+
actionRequired: tc.actionRequired,
|
|
6643
|
+
error: tc.error,
|
|
6644
|
+
fallback: "completed"
|
|
6645
|
+
});
|
|
6527
6646
|
blocks.push({
|
|
6528
6647
|
type: "tool_call",
|
|
6529
6648
|
content: "",
|
|
@@ -6531,12 +6650,9 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6531
6650
|
toolName: tc.name,
|
|
6532
6651
|
toolArgs: tc.args,
|
|
6533
6652
|
toolCallId: tc.id,
|
|
6534
|
-
toolStatus
|
|
6653
|
+
toolStatus,
|
|
6535
6654
|
isIntermediate: true
|
|
6536
6655
|
});
|
|
6537
|
-
const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
|
|
6538
|
-
const toolResultByIndex = toolMessages[toolIndex];
|
|
6539
|
-
const toolResult = toolResultById || toolResultByIndex;
|
|
6540
6656
|
const resultContent = tc.result ?? toolResult?.content;
|
|
6541
6657
|
const toolResultId = toolResult?.tool_call_id || void 0;
|
|
6542
6658
|
if (resultContent) {
|
|
@@ -6579,6 +6695,13 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6579
6695
|
);
|
|
6580
6696
|
if (matchingToolCall) {
|
|
6581
6697
|
matchingToolCall.result = toolMsg.content;
|
|
6698
|
+
matchingToolCall.status = deriveToolExecutionStatus({
|
|
6699
|
+
status: matchingToolCall.status,
|
|
6700
|
+
result: toolMsg.content,
|
|
6701
|
+
actionRequired: matchingToolCall.actionRequired,
|
|
6702
|
+
error: matchingToolCall.error,
|
|
6703
|
+
fallback: "completed"
|
|
6704
|
+
});
|
|
6582
6705
|
}
|
|
6583
6706
|
}
|
|
6584
6707
|
const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
|
|
@@ -7177,9 +7300,20 @@ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId, streamId) {
|
|
|
7177
7300
|
args: event.args || {}
|
|
7178
7301
|
});
|
|
7179
7302
|
break;
|
|
7180
|
-
case "tool_result":
|
|
7181
|
-
|
|
7303
|
+
case "tool_result": {
|
|
7304
|
+
const toolResultEvent = event;
|
|
7305
|
+
forward({
|
|
7306
|
+
type: "tool_result",
|
|
7307
|
+
tool_call_id: toolResultEvent.tool_call_id || "",
|
|
7308
|
+
result: toolResultEvent.result,
|
|
7309
|
+
error: toolResultEvent.error,
|
|
7310
|
+
status: toolResultEvent.status,
|
|
7311
|
+
action_required: toolResultEvent.action_required,
|
|
7312
|
+
settings_tab: toolResultEvent.settings_tab,
|
|
7313
|
+
settings_sub_tab: toolResultEvent.settings_sub_tab
|
|
7314
|
+
});
|
|
7182
7315
|
break;
|
|
7316
|
+
}
|
|
7183
7317
|
case "done":
|
|
7184
7318
|
forward({ type: "done", conversationId: event.conversationId || "", title: event.title });
|
|
7185
7319
|
currentRunId = null;
|
|
@@ -7929,8 +8063,8 @@ function ToolCallItem({ toolCall, toolResult }) {
|
|
|
7929
8063
|
style: { color: "var(--chat-text)" },
|
|
7930
8064
|
children: [
|
|
7931
8065
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-mono", children: displayName }),
|
|
7932
|
-
|
|
7933
|
-
|
|
8066
|
+
toolCall.toolStatus === "completed" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-green-600 dark:text-green-400", children: TimelineIcons.check }),
|
|
8067
|
+
toolCall.toolStatus === "error" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-red-500", children: TimelineIcons.error }),
|
|
7934
8068
|
hasArgs && !expanded && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
|
|
7935
8069
|
"(",
|
|
7936
8070
|
Object.values(toolCall.toolArgs).slice(0, 1).map((v) => typeof v === "string" ? v.length > 18 ? v.slice(0, 18) + "\u2026" : v : "\u2026"),
|
|
@@ -7967,7 +8101,8 @@ function StreamingToolCallItem({
|
|
|
7967
8101
|
style: { color: "var(--chat-text)" },
|
|
7968
8102
|
children: [
|
|
7969
8103
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-mono", children: displayName }),
|
|
7970
|
-
|
|
8104
|
+
toolCall.toolStatus === "completed" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-green-600 dark:text-green-400", children: TimelineIcons.check }),
|
|
8105
|
+
toolCall.toolStatus === "error" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-red-500", children: TimelineIcons.error }),
|
|
7971
8106
|
isActive && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ml-0.5 text-amber-500 animate-pulse", children: "\u25C6" }),
|
|
7972
8107
|
hasArgs && !expanded && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
|
|
7973
8108
|
"(",
|
|
@@ -8388,7 +8523,13 @@ function buildFallbackBlocksFromToolCalls(toolCalls) {
|
|
|
8388
8523
|
const blocks = [];
|
|
8389
8524
|
let timestamp = Date.now();
|
|
8390
8525
|
for (const toolCall of toolCalls) {
|
|
8391
|
-
const toolStatus =
|
|
8526
|
+
const toolStatus = deriveToolExecutionStatus({
|
|
8527
|
+
status: toolCall.status,
|
|
8528
|
+
result: toolCall.result,
|
|
8529
|
+
actionRequired: toolCall.actionRequired,
|
|
8530
|
+
error: toolCall.error,
|
|
8531
|
+
fallback: "running"
|
|
8532
|
+
});
|
|
8392
8533
|
blocks.push({
|
|
8393
8534
|
type: "tool_call",
|
|
8394
8535
|
content: "",
|
package/dist/renderer/index.mjs
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
// src/renderer/hooks/useChat.ts
|
|
2
2
|
import { useState, useCallback, useRef, useEffect } from "react";
|
|
3
|
+
|
|
4
|
+
// src/core/tool-status.ts
|
|
5
|
+
function normalizeToolExecutionStatus(status) {
|
|
6
|
+
if (typeof status !== "string") return void 0;
|
|
7
|
+
switch (status.trim().toLowerCase()) {
|
|
8
|
+
case "success":
|
|
9
|
+
case "completed":
|
|
10
|
+
case "ok":
|
|
11
|
+
return "completed";
|
|
12
|
+
case "error":
|
|
13
|
+
case "failed":
|
|
14
|
+
return "error";
|
|
15
|
+
case "cancelled":
|
|
16
|
+
case "canceled":
|
|
17
|
+
return "cancelled";
|
|
18
|
+
case "running":
|
|
19
|
+
return "running";
|
|
20
|
+
case "pending":
|
|
21
|
+
return "pending";
|
|
22
|
+
default:
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function deriveToolExecutionStatus(options) {
|
|
27
|
+
if (typeof options.actionRequired === "string" && options.actionRequired.length > 0) {
|
|
28
|
+
return "error";
|
|
29
|
+
}
|
|
30
|
+
if (options.error === true) {
|
|
31
|
+
return "error";
|
|
32
|
+
}
|
|
33
|
+
if (typeof options.error === "string" && options.error.trim().length > 0) {
|
|
34
|
+
return "error";
|
|
35
|
+
}
|
|
36
|
+
const normalizedStatus = normalizeToolExecutionStatus(options.status);
|
|
37
|
+
if (normalizedStatus) {
|
|
38
|
+
return normalizedStatus;
|
|
39
|
+
}
|
|
40
|
+
if (options.result !== void 0 && options.result !== null) {
|
|
41
|
+
if (typeof options.result === "string") {
|
|
42
|
+
const normalizedResult = options.result.trimStart();
|
|
43
|
+
if (normalizedResult.startsWith("\u274C") || normalizedResult.startsWith("Error:")) {
|
|
44
|
+
return "error";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return "completed";
|
|
48
|
+
}
|
|
49
|
+
return options.fallback ?? "running";
|
|
50
|
+
}
|
|
51
|
+
function formatToolResultContent(result, error) {
|
|
52
|
+
const value = result ?? error;
|
|
53
|
+
if (value === void 0 || value === null) return void 0;
|
|
54
|
+
if (typeof value === "string") return value;
|
|
55
|
+
try {
|
|
56
|
+
const serialized = JSON.stringify(value);
|
|
57
|
+
return serialized === void 0 ? String(value) : serialized;
|
|
58
|
+
} catch {
|
|
59
|
+
return String(value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/renderer/hooks/useChat.ts
|
|
3
64
|
var TYPEWRITER_DELAYS = { VERY_FAST: 2, FAST: 5, NORMAL: 10, SLOW: 20 };
|
|
4
65
|
var TYPEWRITER_THRESHOLDS = { VERY_FAST: 100, FAST: 50, NORMAL: 20 };
|
|
5
66
|
var MAX_DETACHED_SNAPSHOTS = 30;
|
|
@@ -20,6 +81,15 @@ var findLastBlock = (blocks, predicate) => {
|
|
|
20
81
|
}
|
|
21
82
|
return void 0;
|
|
22
83
|
};
|
|
84
|
+
function getToolResultStatus(event) {
|
|
85
|
+
return deriveToolExecutionStatus({
|
|
86
|
+
status: event.status,
|
|
87
|
+
result: event.result,
|
|
88
|
+
actionRequired: event.action_required,
|
|
89
|
+
error: event.error,
|
|
90
|
+
fallback: "completed"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
23
93
|
function cloneBlocks(blocks) {
|
|
24
94
|
return blocks?.map((block) => ({
|
|
25
95
|
...block,
|
|
@@ -163,7 +233,17 @@ function updateDetachedSnapshotForEvent(streamContext, event) {
|
|
|
163
233
|
return true;
|
|
164
234
|
}
|
|
165
235
|
case "tool_result": {
|
|
166
|
-
const
|
|
236
|
+
const toolStatus = getToolResultStatus(event);
|
|
237
|
+
const resultContent = formatToolResultContent(event.result, event.error);
|
|
238
|
+
const toolCalls = (assistant.toolCalls || []).map((toolCall) => toolCall.id === event.tool_call_id ? {
|
|
239
|
+
...toolCall,
|
|
240
|
+
status: toolStatus,
|
|
241
|
+
result: event.result,
|
|
242
|
+
error: toolStatus === "error" ? typeof event.error === "string" && event.error.trim().length > 0 ? event.error : resultContent : void 0,
|
|
243
|
+
actionRequired: event.action_required,
|
|
244
|
+
settingsTab: event.settings_tab,
|
|
245
|
+
settingsSubTab: event.settings_sub_tab
|
|
246
|
+
} : toolCall);
|
|
167
247
|
const hasRunning = toolCalls.some((toolCall) => toolCall.status === "running");
|
|
168
248
|
const blocks = cloneBlocks(assistant.blocks) || [];
|
|
169
249
|
const toolBlockIndex = blocks.findIndex(
|
|
@@ -172,17 +252,19 @@ function updateDetachedSnapshotForEvent(streamContext, event) {
|
|
|
172
252
|
if (toolBlockIndex !== -1) {
|
|
173
253
|
blocks[toolBlockIndex] = {
|
|
174
254
|
...blocks[toolBlockIndex],
|
|
175
|
-
toolStatus
|
|
255
|
+
toolStatus
|
|
176
256
|
};
|
|
177
257
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
258
|
+
if (resultContent) {
|
|
259
|
+
blocks.push({
|
|
260
|
+
type: "tool_result",
|
|
261
|
+
content: resultContent,
|
|
262
|
+
timestamp: Date.now(),
|
|
263
|
+
toolName: toolBlockIndex !== -1 ? blocks[toolBlockIndex].toolName : void 0,
|
|
264
|
+
toolCallId: event.tool_call_id,
|
|
265
|
+
isIntermediate: true
|
|
266
|
+
});
|
|
267
|
+
}
|
|
186
268
|
snapshot[assistantIndex] = {
|
|
187
269
|
...assistant,
|
|
188
270
|
toolCalls,
|
|
@@ -904,24 +986,35 @@ function useChat(options) {
|
|
|
904
986
|
case "tool_result": {
|
|
905
987
|
flushTypewriter();
|
|
906
988
|
const toolId = event.tool_call_id;
|
|
907
|
-
const
|
|
989
|
+
const toolStatus = getToolResultStatus(event);
|
|
990
|
+
const resultContent = formatToolResultContent(event.result, event.error);
|
|
908
991
|
const blockIdx = currentBlocksRef.current.findIndex((b) => b.type === "tool_call" && b.toolCallId === toolId);
|
|
909
992
|
const toolName = blockIdx !== -1 ? currentBlocksRef.current[blockIdx].toolName : void 0;
|
|
910
|
-
if (blockIdx !== -1) currentBlocksRef.current[blockIdx].toolStatus =
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
993
|
+
if (blockIdx !== -1) currentBlocksRef.current[blockIdx].toolStatus = toolStatus;
|
|
994
|
+
if (resultContent) {
|
|
995
|
+
currentBlocksRef.current.push({
|
|
996
|
+
type: "tool_result",
|
|
997
|
+
content: resultContent,
|
|
998
|
+
timestamp: Date.now(),
|
|
999
|
+
toolName,
|
|
1000
|
+
toolCallId: toolId,
|
|
1001
|
+
isIntermediate: true
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
919
1004
|
setMessages((prev) => {
|
|
920
1005
|
const idx = prev.findIndex((m) => m.id === assistantMessageId);
|
|
921
1006
|
if (idx === -1) return prev;
|
|
922
1007
|
const msg = prev[idx];
|
|
923
1008
|
const updatedCalls = (msg.toolCalls || []).map(
|
|
924
|
-
(t) => t.id === toolId ? {
|
|
1009
|
+
(t) => t.id === toolId ? {
|
|
1010
|
+
...t,
|
|
1011
|
+
status: toolStatus,
|
|
1012
|
+
result: event.result,
|
|
1013
|
+
error: toolStatus === "error" ? typeof event.error === "string" && event.error.trim().length > 0 ? event.error : resultContent : void 0,
|
|
1014
|
+
actionRequired: event.action_required,
|
|
1015
|
+
settingsTab: event.settings_tab,
|
|
1016
|
+
settingsSubTab: event.settings_sub_tab
|
|
1017
|
+
} : t
|
|
925
1018
|
);
|
|
926
1019
|
const hasRunning = updatedCalls.some((tc) => tc.status === "running");
|
|
927
1020
|
const updated = [...prev];
|
|
@@ -6307,12 +6400,25 @@ function parseToolCalls(toolCalls) {
|
|
|
6307
6400
|
const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
|
|
6308
6401
|
const args = safeParseArgs(rawArgs);
|
|
6309
6402
|
const id = tc.id || tc.tool_call_id || tc.call_id;
|
|
6403
|
+
const actionRequired = tc.action_required || tc.actionRequired;
|
|
6404
|
+
const settingsTab = tc.settings_tab || tc.settingsTab;
|
|
6405
|
+
const settingsSubTab = tc.settings_sub_tab || tc.settingsSubTab;
|
|
6310
6406
|
return {
|
|
6311
6407
|
id,
|
|
6312
6408
|
name,
|
|
6313
6409
|
args,
|
|
6314
|
-
|
|
6315
|
-
|
|
6410
|
+
result: tc.result,
|
|
6411
|
+
error: typeof tc.error === "string" ? tc.error : void 0,
|
|
6412
|
+
actionRequired,
|
|
6413
|
+
settingsTab,
|
|
6414
|
+
settingsSubTab,
|
|
6415
|
+
status: deriveToolExecutionStatus({
|
|
6416
|
+
status: tc.status,
|
|
6417
|
+
result: tc.result,
|
|
6418
|
+
actionRequired,
|
|
6419
|
+
error: tc.error,
|
|
6420
|
+
fallback: "completed"
|
|
6421
|
+
})
|
|
6316
6422
|
};
|
|
6317
6423
|
}).filter((tc) => tc.name || tc.id);
|
|
6318
6424
|
}
|
|
@@ -6403,7 +6509,10 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6403
6509
|
id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
|
|
6404
6510
|
name: "",
|
|
6405
6511
|
args: void 0,
|
|
6406
|
-
status:
|
|
6512
|
+
status: deriveToolExecutionStatus({
|
|
6513
|
+
result: toolMessage.content,
|
|
6514
|
+
fallback: "completed"
|
|
6515
|
+
}),
|
|
6407
6516
|
result: toolMessage.content
|
|
6408
6517
|
})) : void 0;
|
|
6409
6518
|
const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
|
|
@@ -6436,6 +6545,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6436
6545
|
const toolResultBlocks = [];
|
|
6437
6546
|
for (const tc of effectiveToolCalls) {
|
|
6438
6547
|
const toolIndex = effectiveToolCalls.indexOf(tc);
|
|
6548
|
+
const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
|
|
6549
|
+
const toolResultByIndex = toolMessages[toolIndex];
|
|
6550
|
+
const toolResult = toolResultById || toolResultByIndex;
|
|
6551
|
+
const toolStatus = deriveToolExecutionStatus({
|
|
6552
|
+
status: tc.status,
|
|
6553
|
+
result: tc.result ?? toolResult?.content,
|
|
6554
|
+
actionRequired: tc.actionRequired,
|
|
6555
|
+
error: tc.error,
|
|
6556
|
+
fallback: "completed"
|
|
6557
|
+
});
|
|
6439
6558
|
blocks.push({
|
|
6440
6559
|
type: "tool_call",
|
|
6441
6560
|
content: "",
|
|
@@ -6443,12 +6562,9 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6443
6562
|
toolName: tc.name,
|
|
6444
6563
|
toolArgs: tc.args,
|
|
6445
6564
|
toolCallId: tc.id,
|
|
6446
|
-
toolStatus
|
|
6565
|
+
toolStatus,
|
|
6447
6566
|
isIntermediate: true
|
|
6448
6567
|
});
|
|
6449
|
-
const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
|
|
6450
|
-
const toolResultByIndex = toolMessages[toolIndex];
|
|
6451
|
-
const toolResult = toolResultById || toolResultByIndex;
|
|
6452
6568
|
const resultContent = tc.result ?? toolResult?.content;
|
|
6453
6569
|
const toolResultId = toolResult?.tool_call_id || void 0;
|
|
6454
6570
|
if (resultContent) {
|
|
@@ -6491,6 +6607,13 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
6491
6607
|
);
|
|
6492
6608
|
if (matchingToolCall) {
|
|
6493
6609
|
matchingToolCall.result = toolMsg.content;
|
|
6610
|
+
matchingToolCall.status = deriveToolExecutionStatus({
|
|
6611
|
+
status: matchingToolCall.status,
|
|
6612
|
+
result: toolMsg.content,
|
|
6613
|
+
actionRequired: matchingToolCall.actionRequired,
|
|
6614
|
+
error: matchingToolCall.error,
|
|
6615
|
+
fallback: "completed"
|
|
6616
|
+
});
|
|
6494
6617
|
}
|
|
6495
6618
|
}
|
|
6496
6619
|
const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
|
|
@@ -7089,9 +7212,20 @@ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId, streamId) {
|
|
|
7089
7212
|
args: event.args || {}
|
|
7090
7213
|
});
|
|
7091
7214
|
break;
|
|
7092
|
-
case "tool_result":
|
|
7093
|
-
|
|
7215
|
+
case "tool_result": {
|
|
7216
|
+
const toolResultEvent = event;
|
|
7217
|
+
forward({
|
|
7218
|
+
type: "tool_result",
|
|
7219
|
+
tool_call_id: toolResultEvent.tool_call_id || "",
|
|
7220
|
+
result: toolResultEvent.result,
|
|
7221
|
+
error: toolResultEvent.error,
|
|
7222
|
+
status: toolResultEvent.status,
|
|
7223
|
+
action_required: toolResultEvent.action_required,
|
|
7224
|
+
settings_tab: toolResultEvent.settings_tab,
|
|
7225
|
+
settings_sub_tab: toolResultEvent.settings_sub_tab
|
|
7226
|
+
});
|
|
7094
7227
|
break;
|
|
7228
|
+
}
|
|
7095
7229
|
case "done":
|
|
7096
7230
|
forward({ type: "done", conversationId: event.conversationId || "", title: event.title });
|
|
7097
7231
|
currentRunId = null;
|
|
@@ -7849,8 +7983,8 @@ function ToolCallItem({ toolCall, toolResult }) {
|
|
|
7849
7983
|
style: { color: "var(--chat-text)" },
|
|
7850
7984
|
children: [
|
|
7851
7985
|
/* @__PURE__ */ jsx8("span", { className: "font-mono", children: displayName }),
|
|
7852
|
-
|
|
7853
|
-
|
|
7986
|
+
toolCall.toolStatus === "completed" && /* @__PURE__ */ jsx8("span", { className: "text-green-600 dark:text-green-400", children: TimelineIcons.check }),
|
|
7987
|
+
toolCall.toolStatus === "error" && /* @__PURE__ */ jsx8("span", { className: "text-red-500", children: TimelineIcons.error }),
|
|
7854
7988
|
hasArgs && !expanded && /* @__PURE__ */ jsxs3("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
|
|
7855
7989
|
"(",
|
|
7856
7990
|
Object.values(toolCall.toolArgs).slice(0, 1).map((v) => typeof v === "string" ? v.length > 18 ? v.slice(0, 18) + "\u2026" : v : "\u2026"),
|
|
@@ -7887,7 +8021,8 @@ function StreamingToolCallItem({
|
|
|
7887
8021
|
style: { color: "var(--chat-text)" },
|
|
7888
8022
|
children: [
|
|
7889
8023
|
/* @__PURE__ */ jsx8("span", { className: "font-mono", children: displayName }),
|
|
7890
|
-
|
|
8024
|
+
toolCall.toolStatus === "completed" && /* @__PURE__ */ jsx8("span", { className: "text-green-600 dark:text-green-400", children: TimelineIcons.check }),
|
|
8025
|
+
toolCall.toolStatus === "error" && /* @__PURE__ */ jsx8("span", { className: "text-red-500", children: TimelineIcons.error }),
|
|
7891
8026
|
isActive && /* @__PURE__ */ jsx8("span", { className: "ml-0.5 text-amber-500 animate-pulse", children: "\u25C6" }),
|
|
7892
8027
|
hasArgs && !expanded && /* @__PURE__ */ jsxs3("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
|
|
7893
8028
|
"(",
|
|
@@ -8308,7 +8443,13 @@ function buildFallbackBlocksFromToolCalls(toolCalls) {
|
|
|
8308
8443
|
const blocks = [];
|
|
8309
8444
|
let timestamp = Date.now();
|
|
8310
8445
|
for (const toolCall of toolCalls) {
|
|
8311
|
-
const toolStatus =
|
|
8446
|
+
const toolStatus = deriveToolExecutionStatus({
|
|
8447
|
+
status: toolCall.status,
|
|
8448
|
+
result: toolCall.result,
|
|
8449
|
+
actionRequired: toolCall.actionRequired,
|
|
8450
|
+
error: toolCall.error,
|
|
8451
|
+
fallback: "running"
|
|
8452
|
+
});
|
|
8312
8453
|
blocks.push({
|
|
8313
8454
|
type: "tool_call",
|
|
8314
8455
|
content: "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yushaw/sanqian-chat",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Floating chat window SDK for Sanqian AI Assistant",
|
|
5
5
|
"main": "./dist/main/index.js",
|
|
6
6
|
"types": "./dist/main/index.d.ts",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@streamdown/code": "^1.0.3",
|
|
48
|
-
"@yushaw/sanqian-sdk": "^0.3.
|
|
48
|
+
"@yushaw/sanqian-sdk": "^0.3.28",
|
|
49
49
|
"react-virtuoso": "^4.15.0",
|
|
50
50
|
"rehype-harden": "^1.1.6",
|
|
51
51
|
"remark-gfm": "^4.0.1",
|