feat: add tool status management and localization for skill installation

- Updated chat message types to include tool statuses.
- Enhanced localization files for English, Thai, and Chinese to support new tool status messages.
- Modified HomePage and SkillsPage components to handle tool statuses in chat messages.
- Implemented tool status merging and updating logic in the chat store.
- Added handling for tool status events in the gateway event processing.
- Created tests for chat message rendering with tool statuses and skill installation shortcuts.
- Improved gateway event dispatching for tool lifecycle events.
This commit is contained in:
duanshuwen
2026-04-23 20:27:54 +08:00
parent 979fb0a0f6
commit df600272d6
29 changed files with 2041 additions and 384 deletions

View File

@@ -1,7 +1,7 @@
import logManager from '@electron/service/logger';
import { extractBrowserOpenIntent, openUrlInBrowser } from '@electron/service/browser-open-service';
import { appendTranscriptLine } from '@electron/utils/token-usage-writer';
import type { RawMessage } from '@runtime/shared/chat-model';
import type { RawMessage, ToolStatus } from '@runtime/shared/chat-model';
import { sessionStore } from './session-store';
import type { GatewayEvent } from './types';
@@ -22,6 +22,21 @@ async function processBrowserOpen(
broadcast: (event: GatewayEvent) => void,
) {
let assistantText = '';
const toolCallId = `browser.open_url:${runId}`;
const startedAt = Date.now();
let finalToolStatus: ToolStatus | null = null;
broadcast({
type: 'tool:status',
sessionKey,
runId,
toolCallId,
toolName: 'browser.open_url',
status: 'running',
updatedAt: startedAt,
summary: `Opening ${url}`,
input: { url },
});
try {
const result = await openUrlInBrowser(url, { signal });
@@ -29,11 +44,61 @@ async function processBrowserOpen(
return;
}
assistantText = buildBrowserOpenResponseText(result);
finalToolStatus = {
id: toolCallId,
toolCallId,
name: 'browser.open_url',
status: 'completed',
updatedAt: Date.now(),
durationMs: Date.now() - startedAt,
summary: assistantText,
input: { url },
result,
};
broadcast({
type: 'tool:status',
sessionKey,
runId,
toolCallId,
toolName: 'browser.open_url',
status: finalToolStatus.status,
updatedAt: finalToolStatus.updatedAt,
durationMs: finalToolStatus.durationMs,
summary: finalToolStatus.summary,
input: finalToolStatus.input,
result: finalToolStatus.result,
});
} catch (error) {
if (signal.aborted) {
return;
}
assistantText = buildBrowserOpenErrorText(error);
finalToolStatus = {
id: toolCallId,
toolCallId,
name: 'browser.open_url',
status: 'error',
updatedAt: Date.now(),
durationMs: Date.now() - startedAt,
summary: assistantText,
input: { url },
result: {
error: error instanceof Error ? error.message : String(error),
},
};
broadcast({
type: 'tool:status',
sessionKey,
runId,
toolCallId,
toolName: 'browser.open_url',
status: finalToolStatus.status,
updatedAt: finalToolStatus.updatedAt,
durationMs: finalToolStatus.durationMs,
summary: finalToolStatus.summary,
input: finalToolStatus.input,
result: finalToolStatus.result,
});
}
sessionStore.clearActiveRun(sessionKey);
@@ -42,6 +107,7 @@ async function processBrowserOpen(
role: 'assistant',
content: assistantText,
timestamp: Date.now(),
_toolStatuses: finalToolStatus ? [finalToolStatus] : undefined,
};
sessionStore.appendMessage(sessionKey, finalMessage);