@yushaw/sanqian-chat 0.3.0 → 0.3.3
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 +30 -3
- package/dist/core/index.d.ts +30 -3
- package/dist/core/index.js +155 -12
- package/dist/core/index.mjs +155 -12
- package/dist/main/index.js +21 -1
- package/dist/main/index.mjs +21 -1
- package/dist/renderer/index.d.mts +30 -3
- package/dist/renderer/index.d.ts +30 -3
- package/dist/renderer/index.js +286 -43
- package/dist/renderer/index.mjs +319 -76
- package/package.json +2 -2
- package/src/renderer/styles/variables.css +5 -5
package/dist/core/index.d.mts
CHANGED
|
@@ -84,8 +84,18 @@ type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
|
|
|
84
84
|
type ToolCallStatus = 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
|
|
85
85
|
type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error';
|
|
86
86
|
type ConnectionErrorCode = 'NOT_FOUND' | 'CONNECTION_FAILED' | 'WEBSOCKET_ERROR' | 'AUTH_ERROR' | 'TIMEOUT' | 'UNKNOWN';
|
|
87
|
+
interface ToolExecutionMetadata {
|
|
88
|
+
commandExitCode?: number;
|
|
89
|
+
durationMs?: number;
|
|
90
|
+
sandboxed?: boolean;
|
|
91
|
+
timedOut?: boolean;
|
|
92
|
+
truncated?: boolean;
|
|
93
|
+
stdoutPath?: string;
|
|
94
|
+
stderrPath?: string;
|
|
95
|
+
presentation?: string;
|
|
96
|
+
}
|
|
87
97
|
/** Tool call for UI rendering (extended from SDK) */
|
|
88
|
-
interface ToolCall {
|
|
98
|
+
interface ToolCall extends ToolExecutionMetadata {
|
|
89
99
|
id?: string;
|
|
90
100
|
name: string;
|
|
91
101
|
args?: Record<string, unknown>;
|
|
@@ -93,9 +103,12 @@ interface ToolCall {
|
|
|
93
103
|
status?: ToolCallStatus;
|
|
94
104
|
result?: unknown;
|
|
95
105
|
error?: string;
|
|
106
|
+
actionRequired?: string;
|
|
107
|
+
settingsTab?: string;
|
|
108
|
+
settingsSubTab?: string;
|
|
96
109
|
}
|
|
97
110
|
/** Message block for structured rendering */
|
|
98
|
-
interface MessageBlock {
|
|
111
|
+
interface MessageBlock extends ToolExecutionMetadata {
|
|
99
112
|
type: 'thinking' | 'text' | 'tool_call' | 'tool_result';
|
|
100
113
|
content: string;
|
|
101
114
|
timestamp: number;
|
|
@@ -104,6 +117,7 @@ interface MessageBlock {
|
|
|
104
117
|
toolArgsRaw?: string;
|
|
105
118
|
toolCallId?: string;
|
|
106
119
|
toolStatus?: ToolCallStatus;
|
|
120
|
+
actionRequired?: string;
|
|
107
121
|
isIntermediate?: boolean;
|
|
108
122
|
fromSubagent?: boolean;
|
|
109
123
|
}
|
|
@@ -533,6 +547,19 @@ type StreamEvent = {
|
|
|
533
547
|
type: 'tool_result';
|
|
534
548
|
tool_call_id: string;
|
|
535
549
|
result: unknown;
|
|
550
|
+
error?: string;
|
|
551
|
+
status?: 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
|
|
552
|
+
action_required?: string;
|
|
553
|
+
settings_tab?: string;
|
|
554
|
+
settings_sub_tab?: string;
|
|
555
|
+
command_exit_code?: number;
|
|
556
|
+
duration_ms?: number;
|
|
557
|
+
sandboxed?: boolean;
|
|
558
|
+
timed_out?: boolean;
|
|
559
|
+
truncated?: boolean;
|
|
560
|
+
stdout_path?: string;
|
|
561
|
+
stderr_path?: string;
|
|
562
|
+
presentation?: string;
|
|
536
563
|
} | {
|
|
537
564
|
type: 'done';
|
|
538
565
|
conversationId: string;
|
|
@@ -699,4 +726,4 @@ declare function parseToolCalls(toolCalls: unknown): ToolCall[] | undefined;
|
|
|
699
726
|
*/
|
|
700
727
|
declare function mergeConsecutiveAssistantMessages(rawMessages: ApiMessage[]): ChatMessage[];
|
|
701
728
|
|
|
702
|
-
export { type ApiMessage, type AttachConfig, type AttachPosition, type AttachState, type AttachedResource, type AttachmentMenuItem, type AttachmentMenuItemType, type ChatAdapter, type ChatAdapterConfig, type ChatFontSize, type ChatMessage, type ChatPanelConfig, type ChatPanelMode, type ChatPanelPosition, type ChatThemeMode, type ChatUiConfigSerializable, type ChatUiStrings, type ConnectionErrorCode, type ConnectionStatus, type ContextProviderInfo, type ConversationDetail, type ConversationInfo, type FloatingWindowConfig, type HitlInterruptData, type HitlResponseOutcome, type LinkClickEvent, type LinkHandlerConfig, type Locale, type MessageBlock, type MessageRole, type ResourcePickerItem, type ResourcePickerState, type SdkAdapterConfig, type SendMessage, type SessionResource, type SessionResourceEvent, type StoredSessionResource, type StreamEvent, type ToolCall, type ToolCallStatus, type WindowPosition, createChatAdapter, createSdkAdapter, mergeConsecutiveAssistantMessages, parseToolCalls };
|
|
729
|
+
export { type ApiMessage, type AttachConfig, type AttachPosition, type AttachState, type AttachedResource, type AttachmentMenuItem, type AttachmentMenuItemType, type ChatAdapter, type ChatAdapterConfig, type ChatFontSize, type ChatMessage, type ChatPanelConfig, type ChatPanelMode, type ChatPanelPosition, type ChatThemeMode, type ChatUiConfigSerializable, type ChatUiStrings, type ConnectionErrorCode, type ConnectionStatus, type ContextProviderInfo, type ConversationDetail, type ConversationInfo, type FloatingWindowConfig, type HitlInterruptData, type HitlResponseOutcome, type LinkClickEvent, type LinkHandlerConfig, type Locale, type MessageBlock, type MessageRole, type ResourcePickerItem, type ResourcePickerState, type SdkAdapterConfig, type SendMessage, type SessionResource, type SessionResourceEvent, type StoredSessionResource, type StreamEvent, type ToolCall, type ToolCallStatus, type ToolExecutionMetadata, type WindowPosition, createChatAdapter, createSdkAdapter, mergeConsecutiveAssistantMessages, parseToolCalls };
|
package/dist/core/index.d.ts
CHANGED
|
@@ -84,8 +84,18 @@ type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
|
|
|
84
84
|
type ToolCallStatus = 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
|
|
85
85
|
type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error';
|
|
86
86
|
type ConnectionErrorCode = 'NOT_FOUND' | 'CONNECTION_FAILED' | 'WEBSOCKET_ERROR' | 'AUTH_ERROR' | 'TIMEOUT' | 'UNKNOWN';
|
|
87
|
+
interface ToolExecutionMetadata {
|
|
88
|
+
commandExitCode?: number;
|
|
89
|
+
durationMs?: number;
|
|
90
|
+
sandboxed?: boolean;
|
|
91
|
+
timedOut?: boolean;
|
|
92
|
+
truncated?: boolean;
|
|
93
|
+
stdoutPath?: string;
|
|
94
|
+
stderrPath?: string;
|
|
95
|
+
presentation?: string;
|
|
96
|
+
}
|
|
87
97
|
/** Tool call for UI rendering (extended from SDK) */
|
|
88
|
-
interface ToolCall {
|
|
98
|
+
interface ToolCall extends ToolExecutionMetadata {
|
|
89
99
|
id?: string;
|
|
90
100
|
name: string;
|
|
91
101
|
args?: Record<string, unknown>;
|
|
@@ -93,9 +103,12 @@ interface ToolCall {
|
|
|
93
103
|
status?: ToolCallStatus;
|
|
94
104
|
result?: unknown;
|
|
95
105
|
error?: string;
|
|
106
|
+
actionRequired?: string;
|
|
107
|
+
settingsTab?: string;
|
|
108
|
+
settingsSubTab?: string;
|
|
96
109
|
}
|
|
97
110
|
/** Message block for structured rendering */
|
|
98
|
-
interface MessageBlock {
|
|
111
|
+
interface MessageBlock extends ToolExecutionMetadata {
|
|
99
112
|
type: 'thinking' | 'text' | 'tool_call' | 'tool_result';
|
|
100
113
|
content: string;
|
|
101
114
|
timestamp: number;
|
|
@@ -104,6 +117,7 @@ interface MessageBlock {
|
|
|
104
117
|
toolArgsRaw?: string;
|
|
105
118
|
toolCallId?: string;
|
|
106
119
|
toolStatus?: ToolCallStatus;
|
|
120
|
+
actionRequired?: string;
|
|
107
121
|
isIntermediate?: boolean;
|
|
108
122
|
fromSubagent?: boolean;
|
|
109
123
|
}
|
|
@@ -533,6 +547,19 @@ type StreamEvent = {
|
|
|
533
547
|
type: 'tool_result';
|
|
534
548
|
tool_call_id: string;
|
|
535
549
|
result: unknown;
|
|
550
|
+
error?: string;
|
|
551
|
+
status?: 'pending' | 'running' | 'completed' | 'error' | 'cancelled';
|
|
552
|
+
action_required?: string;
|
|
553
|
+
settings_tab?: string;
|
|
554
|
+
settings_sub_tab?: string;
|
|
555
|
+
command_exit_code?: number;
|
|
556
|
+
duration_ms?: number;
|
|
557
|
+
sandboxed?: boolean;
|
|
558
|
+
timed_out?: boolean;
|
|
559
|
+
truncated?: boolean;
|
|
560
|
+
stdout_path?: string;
|
|
561
|
+
stderr_path?: string;
|
|
562
|
+
presentation?: string;
|
|
536
563
|
} | {
|
|
537
564
|
type: 'done';
|
|
538
565
|
conversationId: string;
|
|
@@ -699,4 +726,4 @@ declare function parseToolCalls(toolCalls: unknown): ToolCall[] | undefined;
|
|
|
699
726
|
*/
|
|
700
727
|
declare function mergeConsecutiveAssistantMessages(rawMessages: ApiMessage[]): ChatMessage[];
|
|
701
728
|
|
|
702
|
-
export { type ApiMessage, type AttachConfig, type AttachPosition, type AttachState, type AttachedResource, type AttachmentMenuItem, type AttachmentMenuItemType, type ChatAdapter, type ChatAdapterConfig, type ChatFontSize, type ChatMessage, type ChatPanelConfig, type ChatPanelMode, type ChatPanelPosition, type ChatThemeMode, type ChatUiConfigSerializable, type ChatUiStrings, type ConnectionErrorCode, type ConnectionStatus, type ContextProviderInfo, type ConversationDetail, type ConversationInfo, type FloatingWindowConfig, type HitlInterruptData, type HitlResponseOutcome, type LinkClickEvent, type LinkHandlerConfig, type Locale, type MessageBlock, type MessageRole, type ResourcePickerItem, type ResourcePickerState, type SdkAdapterConfig, type SendMessage, type SessionResource, type SessionResourceEvent, type StoredSessionResource, type StreamEvent, type ToolCall, type ToolCallStatus, type WindowPosition, createChatAdapter, createSdkAdapter, mergeConsecutiveAssistantMessages, parseToolCalls };
|
|
729
|
+
export { type ApiMessage, type AttachConfig, type AttachPosition, type AttachState, type AttachedResource, type AttachmentMenuItem, type AttachmentMenuItemType, type ChatAdapter, type ChatAdapterConfig, type ChatFontSize, type ChatMessage, type ChatPanelConfig, type ChatPanelMode, type ChatPanelPosition, type ChatThemeMode, type ChatUiConfigSerializable, type ChatUiStrings, type ConnectionErrorCode, type ConnectionStatus, type ContextProviderInfo, type ConversationDetail, type ConversationInfo, type FloatingWindowConfig, type HitlInterruptData, type HitlResponseOutcome, type LinkClickEvent, type LinkHandlerConfig, type Locale, type MessageBlock, type MessageRole, type ResourcePickerItem, type ResourcePickerState, type SdkAdapterConfig, type SendMessage, type SessionResource, type SessionResourceEvent, type StoredSessionResource, type StreamEvent, type ToolCall, type ToolCallStatus, type ToolExecutionMetadata, type WindowPosition, createChatAdapter, createSdkAdapter, mergeConsecutiveAssistantMessages, parseToolCalls };
|
package/dist/core/index.js
CHANGED
|
@@ -37,7 +37,77 @@ __export(core_exports, {
|
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(core_exports);
|
|
39
39
|
|
|
40
|
+
// src/core/tool-status.ts
|
|
41
|
+
var BLOCKING_ACTION_REQUIRED = /* @__PURE__ */ new Set(["install_git_bash"]);
|
|
42
|
+
function normalizeToolExecutionStatus(status) {
|
|
43
|
+
if (typeof status !== "string") return void 0;
|
|
44
|
+
switch (status.trim().toLowerCase()) {
|
|
45
|
+
case "success":
|
|
46
|
+
case "completed":
|
|
47
|
+
case "ok":
|
|
48
|
+
return "completed";
|
|
49
|
+
case "error":
|
|
50
|
+
case "failed":
|
|
51
|
+
return "error";
|
|
52
|
+
case "cancelled":
|
|
53
|
+
case "canceled":
|
|
54
|
+
return "cancelled";
|
|
55
|
+
case "running":
|
|
56
|
+
return "running";
|
|
57
|
+
case "pending":
|
|
58
|
+
return "pending";
|
|
59
|
+
default:
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function deriveToolExecutionStatus(options) {
|
|
64
|
+
if (typeof options.actionRequired === "string" && BLOCKING_ACTION_REQUIRED.has(options.actionRequired)) {
|
|
65
|
+
return "error";
|
|
66
|
+
}
|
|
67
|
+
if (options.error === true) {
|
|
68
|
+
return "error";
|
|
69
|
+
}
|
|
70
|
+
if (typeof options.error === "string" && options.error.trim().length > 0) {
|
|
71
|
+
return "error";
|
|
72
|
+
}
|
|
73
|
+
const normalizedStatus = normalizeToolExecutionStatus(options.status);
|
|
74
|
+
if (normalizedStatus) {
|
|
75
|
+
return normalizedStatus;
|
|
76
|
+
}
|
|
77
|
+
if (options.result !== void 0 && options.result !== null) {
|
|
78
|
+
if (typeof options.result === "string") {
|
|
79
|
+
const normalizedResult = options.result.trimStart();
|
|
80
|
+
if (normalizedResult.startsWith("\u274C") || normalizedResult.startsWith("Error:")) {
|
|
81
|
+
return "error";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return "completed";
|
|
85
|
+
}
|
|
86
|
+
return options.fallback ?? "running";
|
|
87
|
+
}
|
|
88
|
+
|
|
40
89
|
// src/core/history.ts
|
|
90
|
+
function readToolExecutionNumber(value) {
|
|
91
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
92
|
+
}
|
|
93
|
+
function readToolExecutionBoolean(value) {
|
|
94
|
+
return typeof value === "boolean" ? value : void 0;
|
|
95
|
+
}
|
|
96
|
+
function readToolExecutionString(value) {
|
|
97
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
98
|
+
}
|
|
99
|
+
function readToolExecutionMetadata(tc) {
|
|
100
|
+
return {
|
|
101
|
+
commandExitCode: readToolExecutionNumber(tc.command_exit_code ?? tc.commandExitCode),
|
|
102
|
+
durationMs: readToolExecutionNumber(tc.duration_ms ?? tc.durationMs),
|
|
103
|
+
sandboxed: readToolExecutionBoolean(tc.sandboxed),
|
|
104
|
+
timedOut: readToolExecutionBoolean(tc.timed_out ?? tc.timedOut),
|
|
105
|
+
truncated: readToolExecutionBoolean(tc.truncated),
|
|
106
|
+
stdoutPath: readToolExecutionString(tc.stdout_path ?? tc.stdoutPath),
|
|
107
|
+
stderrPath: readToolExecutionString(tc.stderr_path ?? tc.stderrPath),
|
|
108
|
+
presentation: readToolExecutionString(tc.presentation)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
41
111
|
function safeParseArgs(value) {
|
|
42
112
|
if (!value) return void 0;
|
|
43
113
|
if (typeof value === "object") return value;
|
|
@@ -67,12 +137,26 @@ function parseToolCalls(toolCalls) {
|
|
|
67
137
|
const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
|
|
68
138
|
const args = safeParseArgs(rawArgs);
|
|
69
139
|
const id = tc.id || tc.tool_call_id || tc.call_id;
|
|
140
|
+
const actionRequired = tc.action_required || tc.actionRequired;
|
|
141
|
+
const settingsTab = tc.settings_tab || tc.settingsTab;
|
|
142
|
+
const settingsSubTab = tc.settings_sub_tab || tc.settingsSubTab;
|
|
70
143
|
return {
|
|
71
144
|
id,
|
|
72
145
|
name,
|
|
73
146
|
args,
|
|
74
|
-
|
|
75
|
-
|
|
147
|
+
result: tc.result,
|
|
148
|
+
error: typeof tc.error === "string" ? tc.error : void 0,
|
|
149
|
+
actionRequired,
|
|
150
|
+
settingsTab,
|
|
151
|
+
settingsSubTab,
|
|
152
|
+
status: deriveToolExecutionStatus({
|
|
153
|
+
status: tc.status,
|
|
154
|
+
result: tc.result,
|
|
155
|
+
actionRequired,
|
|
156
|
+
error: tc.error,
|
|
157
|
+
fallback: "completed"
|
|
158
|
+
}),
|
|
159
|
+
...readToolExecutionMetadata(tc)
|
|
76
160
|
};
|
|
77
161
|
}).filter((tc) => tc.name || tc.id);
|
|
78
162
|
}
|
|
@@ -140,6 +224,10 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
140
224
|
const consecutiveAssistantMsgs = [msg];
|
|
141
225
|
const toolMessages = [];
|
|
142
226
|
let j = i + 1;
|
|
227
|
+
const hasDeclaredToolCalls = (message) => {
|
|
228
|
+
const calls = parseToolCalls(message.toolCalls || message.tool_calls);
|
|
229
|
+
return Boolean(calls && calls.length > 0);
|
|
230
|
+
};
|
|
143
231
|
while (j < rawMessages.length) {
|
|
144
232
|
if (rawMessages[j].role === "assistant") {
|
|
145
233
|
consecutiveAssistantMsgs.push(rawMessages[j]);
|
|
@@ -155,15 +243,19 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
155
243
|
let blockTime = Date.now();
|
|
156
244
|
let fallbackToolCalls;
|
|
157
245
|
let lastEffectiveToolCalls;
|
|
246
|
+
const groupHasDeclaredToolCalls = consecutiveAssistantMsgs.some(hasDeclaredToolCalls);
|
|
158
247
|
for (let k = 0; k < consecutiveAssistantMsgs.length; k++) {
|
|
159
248
|
const assistantMsg = consecutiveAssistantMsgs[k];
|
|
160
249
|
const msgToolCalls = parseToolCalls(assistantMsg.toolCalls || assistantMsg.tool_calls);
|
|
161
250
|
const isLastAssistant = k === consecutiveAssistantMsgs.length - 1;
|
|
162
|
-
const fallbackCalls = isLastAssistant && toolMessages.length > 0 ? toolMessages.map((toolMessage, idx) => ({
|
|
251
|
+
const fallbackCalls = !groupHasDeclaredToolCalls && isLastAssistant && toolMessages.length > 0 ? toolMessages.map((toolMessage, idx) => ({
|
|
163
252
|
id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
|
|
164
253
|
name: "",
|
|
165
254
|
args: void 0,
|
|
166
|
-
status:
|
|
255
|
+
status: deriveToolExecutionStatus({
|
|
256
|
+
result: toolMessage.content,
|
|
257
|
+
fallback: "completed"
|
|
258
|
+
}),
|
|
167
259
|
result: toolMessage.content
|
|
168
260
|
})) : void 0;
|
|
169
261
|
const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
|
|
@@ -196,6 +288,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
196
288
|
const toolResultBlocks = [];
|
|
197
289
|
for (const tc of effectiveToolCalls) {
|
|
198
290
|
const toolIndex = effectiveToolCalls.indexOf(tc);
|
|
291
|
+
const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
|
|
292
|
+
const toolResultByIndex = toolMessages[toolIndex];
|
|
293
|
+
const toolResult = toolResultById || toolResultByIndex;
|
|
294
|
+
const toolStatus = deriveToolExecutionStatus({
|
|
295
|
+
status: tc.status,
|
|
296
|
+
result: tc.result ?? toolResult?.content,
|
|
297
|
+
actionRequired: tc.actionRequired,
|
|
298
|
+
error: tc.error,
|
|
299
|
+
fallback: "completed"
|
|
300
|
+
});
|
|
199
301
|
blocks.push({
|
|
200
302
|
type: "tool_call",
|
|
201
303
|
content: "",
|
|
@@ -203,12 +305,18 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
203
305
|
toolName: tc.name,
|
|
204
306
|
toolArgs: tc.args,
|
|
205
307
|
toolCallId: tc.id,
|
|
206
|
-
toolStatus
|
|
207
|
-
|
|
308
|
+
toolStatus,
|
|
309
|
+
actionRequired: tc.actionRequired,
|
|
310
|
+
isIntermediate: true,
|
|
311
|
+
commandExitCode: tc.commandExitCode,
|
|
312
|
+
durationMs: tc.durationMs,
|
|
313
|
+
sandboxed: tc.sandboxed,
|
|
314
|
+
timedOut: tc.timedOut,
|
|
315
|
+
truncated: tc.truncated,
|
|
316
|
+
stdoutPath: tc.stdoutPath,
|
|
317
|
+
stderrPath: tc.stderrPath,
|
|
318
|
+
presentation: tc.presentation
|
|
208
319
|
});
|
|
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
320
|
const resultContent = tc.result ?? toolResult?.content;
|
|
213
321
|
const toolResultId = toolResult?.tool_call_id || void 0;
|
|
214
322
|
if (resultContent) {
|
|
@@ -218,7 +326,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
218
326
|
timestamp: blockTime++,
|
|
219
327
|
toolName: tc.name,
|
|
220
328
|
toolCallId: tc.id || toolResultId,
|
|
221
|
-
|
|
329
|
+
actionRequired: tc.actionRequired,
|
|
330
|
+
isIntermediate: true,
|
|
331
|
+
commandExitCode: tc.commandExitCode,
|
|
332
|
+
durationMs: tc.durationMs,
|
|
333
|
+
sandboxed: tc.sandboxed,
|
|
334
|
+
timedOut: tc.timedOut,
|
|
335
|
+
truncated: tc.truncated,
|
|
336
|
+
stdoutPath: tc.stdoutPath,
|
|
337
|
+
stderrPath: tc.stderrPath,
|
|
338
|
+
presentation: tc.presentation
|
|
222
339
|
});
|
|
223
340
|
tc.result = resultContent;
|
|
224
341
|
}
|
|
@@ -251,6 +368,13 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
251
368
|
);
|
|
252
369
|
if (matchingToolCall) {
|
|
253
370
|
matchingToolCall.result = toolMsg.content;
|
|
371
|
+
matchingToolCall.status = deriveToolExecutionStatus({
|
|
372
|
+
status: matchingToolCall.status,
|
|
373
|
+
result: toolMsg.content,
|
|
374
|
+
actionRequired: matchingToolCall.actionRequired,
|
|
375
|
+
error: matchingToolCall.error,
|
|
376
|
+
fallback: "completed"
|
|
377
|
+
});
|
|
254
378
|
}
|
|
255
379
|
}
|
|
256
380
|
const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
|
|
@@ -568,9 +692,28 @@ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId, streamId) {
|
|
|
568
692
|
args: event.args || {}
|
|
569
693
|
});
|
|
570
694
|
break;
|
|
571
|
-
case "tool_result":
|
|
572
|
-
|
|
695
|
+
case "tool_result": {
|
|
696
|
+
const toolResultEvent = event;
|
|
697
|
+
forward({
|
|
698
|
+
type: "tool_result",
|
|
699
|
+
tool_call_id: toolResultEvent.tool_call_id || "",
|
|
700
|
+
result: toolResultEvent.result,
|
|
701
|
+
error: toolResultEvent.error,
|
|
702
|
+
status: toolResultEvent.status,
|
|
703
|
+
action_required: toolResultEvent.action_required,
|
|
704
|
+
settings_tab: toolResultEvent.settings_tab,
|
|
705
|
+
settings_sub_tab: toolResultEvent.settings_sub_tab,
|
|
706
|
+
command_exit_code: toolResultEvent.command_exit_code,
|
|
707
|
+
duration_ms: toolResultEvent.duration_ms,
|
|
708
|
+
sandboxed: toolResultEvent.sandboxed,
|
|
709
|
+
timed_out: toolResultEvent.timed_out,
|
|
710
|
+
truncated: toolResultEvent.truncated,
|
|
711
|
+
stdout_path: toolResultEvent.stdout_path,
|
|
712
|
+
stderr_path: toolResultEvent.stderr_path,
|
|
713
|
+
presentation: toolResultEvent.presentation
|
|
714
|
+
});
|
|
573
715
|
break;
|
|
716
|
+
}
|
|
574
717
|
case "done":
|
|
575
718
|
forward({ type: "done", conversationId: event.conversationId || "", title: event.title });
|
|
576
719
|
currentRunId = null;
|
package/dist/core/index.mjs
CHANGED
|
@@ -1,4 +1,74 @@
|
|
|
1
|
+
// src/core/tool-status.ts
|
|
2
|
+
var BLOCKING_ACTION_REQUIRED = /* @__PURE__ */ new Set(["install_git_bash"]);
|
|
3
|
+
function normalizeToolExecutionStatus(status) {
|
|
4
|
+
if (typeof status !== "string") return void 0;
|
|
5
|
+
switch (status.trim().toLowerCase()) {
|
|
6
|
+
case "success":
|
|
7
|
+
case "completed":
|
|
8
|
+
case "ok":
|
|
9
|
+
return "completed";
|
|
10
|
+
case "error":
|
|
11
|
+
case "failed":
|
|
12
|
+
return "error";
|
|
13
|
+
case "cancelled":
|
|
14
|
+
case "canceled":
|
|
15
|
+
return "cancelled";
|
|
16
|
+
case "running":
|
|
17
|
+
return "running";
|
|
18
|
+
case "pending":
|
|
19
|
+
return "pending";
|
|
20
|
+
default:
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function deriveToolExecutionStatus(options) {
|
|
25
|
+
if (typeof options.actionRequired === "string" && BLOCKING_ACTION_REQUIRED.has(options.actionRequired)) {
|
|
26
|
+
return "error";
|
|
27
|
+
}
|
|
28
|
+
if (options.error === true) {
|
|
29
|
+
return "error";
|
|
30
|
+
}
|
|
31
|
+
if (typeof options.error === "string" && options.error.trim().length > 0) {
|
|
32
|
+
return "error";
|
|
33
|
+
}
|
|
34
|
+
const normalizedStatus = normalizeToolExecutionStatus(options.status);
|
|
35
|
+
if (normalizedStatus) {
|
|
36
|
+
return normalizedStatus;
|
|
37
|
+
}
|
|
38
|
+
if (options.result !== void 0 && options.result !== null) {
|
|
39
|
+
if (typeof options.result === "string") {
|
|
40
|
+
const normalizedResult = options.result.trimStart();
|
|
41
|
+
if (normalizedResult.startsWith("\u274C") || normalizedResult.startsWith("Error:")) {
|
|
42
|
+
return "error";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return "completed";
|
|
46
|
+
}
|
|
47
|
+
return options.fallback ?? "running";
|
|
48
|
+
}
|
|
49
|
+
|
|
1
50
|
// src/core/history.ts
|
|
51
|
+
function readToolExecutionNumber(value) {
|
|
52
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
53
|
+
}
|
|
54
|
+
function readToolExecutionBoolean(value) {
|
|
55
|
+
return typeof value === "boolean" ? value : void 0;
|
|
56
|
+
}
|
|
57
|
+
function readToolExecutionString(value) {
|
|
58
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
59
|
+
}
|
|
60
|
+
function readToolExecutionMetadata(tc) {
|
|
61
|
+
return {
|
|
62
|
+
commandExitCode: readToolExecutionNumber(tc.command_exit_code ?? tc.commandExitCode),
|
|
63
|
+
durationMs: readToolExecutionNumber(tc.duration_ms ?? tc.durationMs),
|
|
64
|
+
sandboxed: readToolExecutionBoolean(tc.sandboxed),
|
|
65
|
+
timedOut: readToolExecutionBoolean(tc.timed_out ?? tc.timedOut),
|
|
66
|
+
truncated: readToolExecutionBoolean(tc.truncated),
|
|
67
|
+
stdoutPath: readToolExecutionString(tc.stdout_path ?? tc.stdoutPath),
|
|
68
|
+
stderrPath: readToolExecutionString(tc.stderr_path ?? tc.stderrPath),
|
|
69
|
+
presentation: readToolExecutionString(tc.presentation)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
2
72
|
function safeParseArgs(value) {
|
|
3
73
|
if (!value) return void 0;
|
|
4
74
|
if (typeof value === "object") return value;
|
|
@@ -28,12 +98,26 @@ function parseToolCalls(toolCalls) {
|
|
|
28
98
|
const rawArgs = fn?.arguments ?? tc.args ?? tc.arguments;
|
|
29
99
|
const args = safeParseArgs(rawArgs);
|
|
30
100
|
const id = tc.id || tc.tool_call_id || tc.call_id;
|
|
101
|
+
const actionRequired = tc.action_required || tc.actionRequired;
|
|
102
|
+
const settingsTab = tc.settings_tab || tc.settingsTab;
|
|
103
|
+
const settingsSubTab = tc.settings_sub_tab || tc.settingsSubTab;
|
|
31
104
|
return {
|
|
32
105
|
id,
|
|
33
106
|
name,
|
|
34
107
|
args,
|
|
35
|
-
|
|
36
|
-
|
|
108
|
+
result: tc.result,
|
|
109
|
+
error: typeof tc.error === "string" ? tc.error : void 0,
|
|
110
|
+
actionRequired,
|
|
111
|
+
settingsTab,
|
|
112
|
+
settingsSubTab,
|
|
113
|
+
status: deriveToolExecutionStatus({
|
|
114
|
+
status: tc.status,
|
|
115
|
+
result: tc.result,
|
|
116
|
+
actionRequired,
|
|
117
|
+
error: tc.error,
|
|
118
|
+
fallback: "completed"
|
|
119
|
+
}),
|
|
120
|
+
...readToolExecutionMetadata(tc)
|
|
37
121
|
};
|
|
38
122
|
}).filter((tc) => tc.name || tc.id);
|
|
39
123
|
}
|
|
@@ -101,6 +185,10 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
101
185
|
const consecutiveAssistantMsgs = [msg];
|
|
102
186
|
const toolMessages = [];
|
|
103
187
|
let j = i + 1;
|
|
188
|
+
const hasDeclaredToolCalls = (message) => {
|
|
189
|
+
const calls = parseToolCalls(message.toolCalls || message.tool_calls);
|
|
190
|
+
return Boolean(calls && calls.length > 0);
|
|
191
|
+
};
|
|
104
192
|
while (j < rawMessages.length) {
|
|
105
193
|
if (rawMessages[j].role === "assistant") {
|
|
106
194
|
consecutiveAssistantMsgs.push(rawMessages[j]);
|
|
@@ -116,15 +204,19 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
116
204
|
let blockTime = Date.now();
|
|
117
205
|
let fallbackToolCalls;
|
|
118
206
|
let lastEffectiveToolCalls;
|
|
207
|
+
const groupHasDeclaredToolCalls = consecutiveAssistantMsgs.some(hasDeclaredToolCalls);
|
|
119
208
|
for (let k = 0; k < consecutiveAssistantMsgs.length; k++) {
|
|
120
209
|
const assistantMsg = consecutiveAssistantMsgs[k];
|
|
121
210
|
const msgToolCalls = parseToolCalls(assistantMsg.toolCalls || assistantMsg.tool_calls);
|
|
122
211
|
const isLastAssistant = k === consecutiveAssistantMsgs.length - 1;
|
|
123
|
-
const fallbackCalls = isLastAssistant && toolMessages.length > 0 ? toolMessages.map((toolMessage, idx) => ({
|
|
212
|
+
const fallbackCalls = !groupHasDeclaredToolCalls && isLastAssistant && toolMessages.length > 0 ? toolMessages.map((toolMessage, idx) => ({
|
|
124
213
|
id: (toolMessage.tool_call_id || void 0) ?? `tool-${idx}`,
|
|
125
214
|
name: "",
|
|
126
215
|
args: void 0,
|
|
127
|
-
status:
|
|
216
|
+
status: deriveToolExecutionStatus({
|
|
217
|
+
result: toolMessage.content,
|
|
218
|
+
fallback: "completed"
|
|
219
|
+
}),
|
|
128
220
|
result: toolMessage.content
|
|
129
221
|
})) : void 0;
|
|
130
222
|
const effectiveToolCalls = msgToolCalls && msgToolCalls.length > 0 ? msgToolCalls : fallbackCalls;
|
|
@@ -157,6 +249,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
157
249
|
const toolResultBlocks = [];
|
|
158
250
|
for (const tc of effectiveToolCalls) {
|
|
159
251
|
const toolIndex = effectiveToolCalls.indexOf(tc);
|
|
252
|
+
const toolResultById = tc.id ? toolMessages.find((tm) => tm.tool_call_id === tc.id) : void 0;
|
|
253
|
+
const toolResultByIndex = toolMessages[toolIndex];
|
|
254
|
+
const toolResult = toolResultById || toolResultByIndex;
|
|
255
|
+
const toolStatus = deriveToolExecutionStatus({
|
|
256
|
+
status: tc.status,
|
|
257
|
+
result: tc.result ?? toolResult?.content,
|
|
258
|
+
actionRequired: tc.actionRequired,
|
|
259
|
+
error: tc.error,
|
|
260
|
+
fallback: "completed"
|
|
261
|
+
});
|
|
160
262
|
blocks.push({
|
|
161
263
|
type: "tool_call",
|
|
162
264
|
content: "",
|
|
@@ -164,12 +266,18 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
164
266
|
toolName: tc.name,
|
|
165
267
|
toolArgs: tc.args,
|
|
166
268
|
toolCallId: tc.id,
|
|
167
|
-
toolStatus
|
|
168
|
-
|
|
269
|
+
toolStatus,
|
|
270
|
+
actionRequired: tc.actionRequired,
|
|
271
|
+
isIntermediate: true,
|
|
272
|
+
commandExitCode: tc.commandExitCode,
|
|
273
|
+
durationMs: tc.durationMs,
|
|
274
|
+
sandboxed: tc.sandboxed,
|
|
275
|
+
timedOut: tc.timedOut,
|
|
276
|
+
truncated: tc.truncated,
|
|
277
|
+
stdoutPath: tc.stdoutPath,
|
|
278
|
+
stderrPath: tc.stderrPath,
|
|
279
|
+
presentation: tc.presentation
|
|
169
280
|
});
|
|
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
281
|
const resultContent = tc.result ?? toolResult?.content;
|
|
174
282
|
const toolResultId = toolResult?.tool_call_id || void 0;
|
|
175
283
|
if (resultContent) {
|
|
@@ -179,7 +287,16 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
179
287
|
timestamp: blockTime++,
|
|
180
288
|
toolName: tc.name,
|
|
181
289
|
toolCallId: tc.id || toolResultId,
|
|
182
|
-
|
|
290
|
+
actionRequired: tc.actionRequired,
|
|
291
|
+
isIntermediate: true,
|
|
292
|
+
commandExitCode: tc.commandExitCode,
|
|
293
|
+
durationMs: tc.durationMs,
|
|
294
|
+
sandboxed: tc.sandboxed,
|
|
295
|
+
timedOut: tc.timedOut,
|
|
296
|
+
truncated: tc.truncated,
|
|
297
|
+
stdoutPath: tc.stdoutPath,
|
|
298
|
+
stderrPath: tc.stderrPath,
|
|
299
|
+
presentation: tc.presentation
|
|
183
300
|
});
|
|
184
301
|
tc.result = resultContent;
|
|
185
302
|
}
|
|
@@ -212,6 +329,13 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
212
329
|
);
|
|
213
330
|
if (matchingToolCall) {
|
|
214
331
|
matchingToolCall.result = toolMsg.content;
|
|
332
|
+
matchingToolCall.status = deriveToolExecutionStatus({
|
|
333
|
+
status: matchingToolCall.status,
|
|
334
|
+
result: toolMsg.content,
|
|
335
|
+
actionRequired: matchingToolCall.actionRequired,
|
|
336
|
+
error: matchingToolCall.error,
|
|
337
|
+
fallback: "completed"
|
|
338
|
+
});
|
|
215
339
|
}
|
|
216
340
|
}
|
|
217
341
|
const thinkingParts = consecutiveAssistantMsgs.map((m) => m.thinking).filter((t) => t && t.trim());
|
|
@@ -529,9 +653,28 @@ function processStreamEvents(stream, onEvent, sdk, setCurrentRunId, streamId) {
|
|
|
529
653
|
args: event.args || {}
|
|
530
654
|
});
|
|
531
655
|
break;
|
|
532
|
-
case "tool_result":
|
|
533
|
-
|
|
656
|
+
case "tool_result": {
|
|
657
|
+
const toolResultEvent = event;
|
|
658
|
+
forward({
|
|
659
|
+
type: "tool_result",
|
|
660
|
+
tool_call_id: toolResultEvent.tool_call_id || "",
|
|
661
|
+
result: toolResultEvent.result,
|
|
662
|
+
error: toolResultEvent.error,
|
|
663
|
+
status: toolResultEvent.status,
|
|
664
|
+
action_required: toolResultEvent.action_required,
|
|
665
|
+
settings_tab: toolResultEvent.settings_tab,
|
|
666
|
+
settings_sub_tab: toolResultEvent.settings_sub_tab,
|
|
667
|
+
command_exit_code: toolResultEvent.command_exit_code,
|
|
668
|
+
duration_ms: toolResultEvent.duration_ms,
|
|
669
|
+
sandboxed: toolResultEvent.sandboxed,
|
|
670
|
+
timed_out: toolResultEvent.timed_out,
|
|
671
|
+
truncated: toolResultEvent.truncated,
|
|
672
|
+
stdout_path: toolResultEvent.stdout_path,
|
|
673
|
+
stderr_path: toolResultEvent.stderr_path,
|
|
674
|
+
presentation: toolResultEvent.presentation
|
|
675
|
+
});
|
|
534
676
|
break;
|
|
677
|
+
}
|
|
535
678
|
case "done":
|
|
536
679
|
forward({ type: "done", conversationId: event.conversationId || "", title: event.title });
|
|
537
680
|
currentRunId = null;
|
package/dist/main/index.js
CHANGED
|
@@ -617,7 +617,27 @@ 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
|
+
command_exit_code: evt.command_exit_code,
|
|
632
|
+
duration_ms: evt.duration_ms,
|
|
633
|
+
sandboxed: evt.sandboxed,
|
|
634
|
+
timed_out: evt.timed_out,
|
|
635
|
+
truncated: evt.truncated,
|
|
636
|
+
stdout_path: evt.stdout_path,
|
|
637
|
+
stderr_path: evt.stderr_path,
|
|
638
|
+
presentation: evt.presentation
|
|
639
|
+
}
|
|
640
|
+
});
|
|
621
641
|
break;
|
|
622
642
|
case "done":
|
|
623
643
|
sawTerminalEvent = true;
|
package/dist/main/index.mjs
CHANGED
|
@@ -586,7 +586,27 @@ 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
|
+
command_exit_code: evt.command_exit_code,
|
|
601
|
+
duration_ms: evt.duration_ms,
|
|
602
|
+
sandboxed: evt.sandboxed,
|
|
603
|
+
timed_out: evt.timed_out,
|
|
604
|
+
truncated: evt.truncated,
|
|
605
|
+
stdout_path: evt.stdout_path,
|
|
606
|
+
stderr_path: evt.stderr_path,
|
|
607
|
+
presentation: evt.presentation
|
|
608
|
+
}
|
|
609
|
+
});
|
|
590
610
|
break;
|
|
591
611
|
case "done":
|
|
592
612
|
sawTerminalEvent = true;
|