支持一次对话同时调用多个工具
This commit is contained in:
parent
da482e26a9
commit
4c0566b470
@ -1,6 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
|
||||
## [main] 0.0.8
|
||||
- 大模型 API 测试时更加完整的报错
|
||||
- 修复 0.0.7 引入的bug:修改对话无法发出
|
||||
@ -8,6 +7,7 @@
|
||||
- 修复 bug:富文本编辑器发送前缀为空的字符会全部为空
|
||||
- 修复 bug:流式传输进行 function calling 时,多工具的索引串流导致的 JSON Schema 反序列化失败
|
||||
- 修复 bug:大模型返回大量重复错误信息
|
||||
- 新特性:支持一次对话同时调用多个工具
|
||||
|
||||
## [main] 0.0.7
|
||||
- 优化页面布局,使得调试窗口可以显示更多内容
|
||||
|
@ -131,6 +131,10 @@ a {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.tool-arguments .openmcp-code-block pre code::-webkit-scrollbar {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.tool-arguments .openmcp-code-block pre code {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ export interface IExtraInfo {
|
||||
|
||||
export interface ToolMessage {
|
||||
role: 'tool';
|
||||
index: number;
|
||||
content: ToolCallContent[];
|
||||
tool_call_id?: string
|
||||
name?: string // 工具名称,当 role 为 tool
|
||||
@ -95,15 +96,24 @@ export type RichTextItem = PromptTextItem | ResourceTextItem | TextItem;
|
||||
|
||||
export const allTools = ref<ToolItem[]>([]);
|
||||
|
||||
export interface IRenderMessage {
|
||||
role: 'user' | 'assistant/content' | 'assistant/tool_calls' | 'tool';
|
||||
export interface ICommonRenderMessage {
|
||||
role: 'user' | 'assistant/content';
|
||||
content: string;
|
||||
toolResult?: ToolCallContent[];
|
||||
tool_calls?: ToolCall[];
|
||||
showJson?: Ref<boolean>;
|
||||
extraInfo: IExtraInfo;
|
||||
}
|
||||
|
||||
export interface IToolRenderMessage {
|
||||
role: 'assistant/tool_calls';
|
||||
content: string;
|
||||
toolResults: ToolCallContent[][];
|
||||
tool_calls: ToolCall[];
|
||||
showJson?: Ref<boolean>;
|
||||
extraInfo: IExtraInfo;
|
||||
}
|
||||
|
||||
export type IRenderMessage = ICommonRenderMessage | IToolRenderMessage;
|
||||
|
||||
export function getToolSchema(enableTools: EnableToolItem[]) {
|
||||
const toolsSchema = [];
|
||||
for (let i = 0; i < enableTools.length; i++) {
|
||||
|
@ -65,6 +65,23 @@ const chatContext = inject('chatContext') as any;
|
||||
|
||||
chatContext.handleSend = handleSend;
|
||||
|
||||
function clearErrorMessage(errorMessage: string) {
|
||||
try {
|
||||
const errorObject = JSON.parse(errorMessage);
|
||||
if (errorObject.error) {
|
||||
return errorObject.error;
|
||||
}
|
||||
if (errorObject.message) {
|
||||
return errorObject.message;
|
||||
}
|
||||
if (errorObject.msg) {
|
||||
return errorObject.msg;
|
||||
}
|
||||
} catch (error) {
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
function handleSend(newMessage?: string) {
|
||||
// 将富文本信息转换成纯文本信息
|
||||
const userMessage = newMessage || userInput.value;
|
||||
@ -79,13 +96,16 @@ function handleSend(newMessage?: string) {
|
||||
loop = new TaskLoop(streamingContent, streamingToolCalls);
|
||||
|
||||
loop.registerOnError((error) => {
|
||||
console.log('error.msg');
|
||||
console.log(error.msg);
|
||||
|
||||
ElMessage.error(error.msg);
|
||||
const errorMessage = clearErrorMessage(error.msg);
|
||||
ElMessage.error(errorMessage);
|
||||
|
||||
if (error.state === MessageState.ReceiveChunkError) {
|
||||
tabStorage.messages.push({
|
||||
role: 'assistant',
|
||||
content: error.msg,
|
||||
content: errorMessage,
|
||||
extraInfo: {
|
||||
created: Date.now(),
|
||||
state: error.state,
|
||||
|
@ -0,0 +1,81 @@
|
||||
import { ToolCallResponse } from "@/hook/type";
|
||||
import { callTool } from "../../tool/tools";
|
||||
import { MessageState, ToolCall } from "../chat-box/chat";
|
||||
|
||||
export async function handleToolCalls(toolCall: ToolCall) {
|
||||
// 反序列化 streaming 来的参数字符串
|
||||
const toolName = toolCall.function.name;
|
||||
const argsResult = deserializeToolCallResponse(toolCall.function.arguments);
|
||||
|
||||
if (argsResult.error) {
|
||||
return {
|
||||
content: [{
|
||||
type: 'error',
|
||||
text: parseErrorObject(argsResult.error)
|
||||
}],
|
||||
state: MessageState.ParseJsonError
|
||||
};
|
||||
}
|
||||
|
||||
const toolArgs = argsResult.value;
|
||||
|
||||
// 进行调用,根据结果返回不同的值
|
||||
const toolResponse = await callTool(toolName, toolArgs);
|
||||
return handleToolResponse(toolResponse);
|
||||
}
|
||||
|
||||
function deserializeToolCallResponse(toolArgs: string) {
|
||||
try {
|
||||
const args = JSON.parse(toolArgs);
|
||||
return {
|
||||
value: args,
|
||||
error: undefined
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
value: undefined,
|
||||
error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleToolResponse(toolResponse: ToolCallResponse) {
|
||||
if (typeof toolResponse === 'string') {
|
||||
// 如果是 string,说明是错误信息
|
||||
console.log(toolResponse);
|
||||
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'error',
|
||||
text: toolResponse
|
||||
}],
|
||||
state: MessageState.ToolCall
|
||||
}
|
||||
|
||||
} else if (!toolResponse.isError) {
|
||||
|
||||
return {
|
||||
content: toolResponse.content,
|
||||
state: MessageState.Success
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
return {
|
||||
content: toolResponse.content,
|
||||
state: MessageState.ToolCall
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function parseErrorObject(error: any): string {
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
} else if (typeof error === 'object') {
|
||||
return JSON.stringify(error, null, 2);
|
||||
} else {
|
||||
return error.toString();
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import { callTool } from "../../tool/tools";
|
||||
import { llmManager, llms } from "@/views/setting/llm";
|
||||
import { pinkLog, redLog } from "@/views/setting/util";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { handleToolCalls } from "./handle-tool-calls";
|
||||
|
||||
export type ChatCompletionChunk = OpenAI.Chat.Completions.ChatCompletionChunk;
|
||||
export type ChatCompletionCreateParamsBase = OpenAI.Chat.Completions.ChatCompletionCreateParams & { id?: string };
|
||||
@ -44,87 +45,6 @@ export class TaskLoop {
|
||||
|
||||
}
|
||||
|
||||
private async handleToolCalls(toolCalls: ToolCall[]) {
|
||||
// TODO: 调用多个工具并返回调用结果?
|
||||
|
||||
const toolCall = toolCalls[0];
|
||||
|
||||
console.log('debug toolcall');
|
||||
console.log(toolCalls);
|
||||
|
||||
let toolName: string;
|
||||
let toolArgs: Record<string, any>;
|
||||
|
||||
try {
|
||||
toolName = toolCall.function.name;
|
||||
toolArgs = JSON.parse(toolCall.function.arguments);
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [{
|
||||
type: 'error',
|
||||
text: this.parseErrorObject(error)
|
||||
}],
|
||||
state: MessageState.ParseJsonError
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const toolResponse = await callTool(toolName, toolArgs);
|
||||
|
||||
console.log(toolResponse);
|
||||
|
||||
if (typeof toolResponse === 'string') {
|
||||
console.log(toolResponse);
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'error',
|
||||
text: toolResponse
|
||||
}],
|
||||
state: MessageState.ToolCall
|
||||
}
|
||||
} else if (!toolResponse.isError) {
|
||||
|
||||
return {
|
||||
content: toolResponse.content,
|
||||
state: MessageState.Success
|
||||
};
|
||||
} else {
|
||||
|
||||
return {
|
||||
content: toolResponse.content,
|
||||
state: MessageState.ToolCall
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.onError({
|
||||
state: MessageState.ToolCall,
|
||||
msg: `工具调用失败: ${(error as Error).message}`
|
||||
});
|
||||
console.error(error);
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'error',
|
||||
text: this.parseErrorObject(error)
|
||||
}],
|
||||
state: MessageState.ToolCall
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private parseErrorObject(error: any): string {
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
} else if (typeof error === 'object') {
|
||||
return JSON.stringify(error, null, 2);
|
||||
} else {
|
||||
return error.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private handleChunkDeltaContent(chunk: ChatCompletionChunk) {
|
||||
const content = chunk.choices[0]?.delta?.content || '';
|
||||
if (content) {
|
||||
@ -199,12 +119,7 @@ export class TaskLoop {
|
||||
});
|
||||
}, { once: true });
|
||||
|
||||
console.log('register error handler');
|
||||
|
||||
const errorHandler = this.bridge.addCommandListener('llm/chat/completions/error', data => {
|
||||
|
||||
console.log('enter error report');
|
||||
|
||||
this.onError({
|
||||
state: MessageState.ReceiveChunkError,
|
||||
msg: data.msg || '请求模型服务时发生错误'
|
||||
@ -219,6 +134,8 @@ export class TaskLoop {
|
||||
|
||||
}, { once: true });
|
||||
|
||||
console.log(chatData);
|
||||
|
||||
this.bridge.postMessage({
|
||||
command: 'llm/chat/completions',
|
||||
data: JSON.parse(JSON.stringify(chatData)),
|
||||
@ -360,16 +277,15 @@ export class TaskLoop {
|
||||
|
||||
pinkLog('调用工具数量:' + this.streamingToolCalls.value.length);
|
||||
|
||||
const toolCallResult = await this.handleToolCalls(this.streamingToolCalls.value);
|
||||
|
||||
console.log('toolCallResult', toolCallResult);
|
||||
for (const toolCall of this.streamingToolCalls.value || []) {
|
||||
const toolCallResult = await handleToolCalls(toolCall);
|
||||
|
||||
if (toolCallResult.state === MessageState.ParseJsonError) {
|
||||
// 如果是因为解析 JSON 错误,则重新开始
|
||||
tabStorage.messages.pop();
|
||||
jsonParseErrorRetryCount ++;
|
||||
|
||||
redLog('解析 JSON 错误 ' + this.streamingToolCalls.value[0]?.function?.arguments);
|
||||
redLog('解析 JSON 错误 ' + toolCall?.function?.arguments);
|
||||
|
||||
// 如果因为 JSON 错误而失败太多,就只能中断了
|
||||
if (jsonParseErrorRetryCount >= this.taskOptions.maxJsonParseRetry) {
|
||||
@ -386,10 +302,9 @@ export class TaskLoop {
|
||||
break;
|
||||
}
|
||||
} else if (toolCallResult.state === MessageState.Success) {
|
||||
const toolCall = this.streamingToolCalls.value[0];
|
||||
|
||||
tabStorage.messages.push({
|
||||
role: 'tool',
|
||||
index: toolCall.index || 0,
|
||||
tool_call_id: toolCall.id || toolCall.function.name,
|
||||
content: toolCallResult.content,
|
||||
extraInfo: {
|
||||
@ -400,10 +315,10 @@ export class TaskLoop {
|
||||
}
|
||||
});
|
||||
} else if (toolCallResult.state === MessageState.ToolCall) {
|
||||
const toolCall = this.streamingToolCalls.value[0];
|
||||
|
||||
tabStorage.messages.push({
|
||||
role: 'tool',
|
||||
index: toolCall.index || 0,
|
||||
tool_call_id: toolCall.id || toolCall.function.name,
|
||||
content: toolCallResult.content,
|
||||
extraInfo: {
|
||||
@ -414,6 +329,7 @@ export class TaskLoop {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else if (this.streamingContent.value) {
|
||||
tabStorage.messages.push({
|
||||
|
@ -25,7 +25,7 @@
|
||||
<div class="message-content" v-else-if="message.role === 'assistant/tool_calls'">
|
||||
<Message.Toolcall
|
||||
:message="message" :tab-id="props.tabId"
|
||||
@update:tool-result="(value, index) => (message.toolResult || [])[index] = value"
|
||||
@update:tool-result="(value, toolIndex, index) => message.toolResults[toolIndex][index] = value"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -97,6 +97,7 @@ const renderMessages = computed(() => {
|
||||
messages.push({
|
||||
role: 'assistant/tool_calls',
|
||||
content: message.content,
|
||||
toolResults: Array(message.tool_calls.length).fill([]),
|
||||
tool_calls: message.tool_calls,
|
||||
showJson: ref(false),
|
||||
extraInfo: {
|
||||
@ -116,8 +117,16 @@ const renderMessages = computed(() => {
|
||||
// 如果是工具,则合并进入 之前 assistant 一起渲染
|
||||
const lastAssistantMessage = messages[messages.length - 1];
|
||||
if (lastAssistantMessage.role === 'assistant/tool_calls') {
|
||||
lastAssistantMessage.toolResult = message.content;
|
||||
lastAssistantMessage.toolResults[message.index] = message.content;
|
||||
|
||||
if (lastAssistantMessage.extraInfo.state === MessageState.Unknown) {
|
||||
lastAssistantMessage.extraInfo.state = message.extraInfo.state;
|
||||
} else if (lastAssistantMessage.extraInfo.state === MessageState.Success
|
||||
|| message.extraInfo.state !== MessageState.Success
|
||||
) {
|
||||
lastAssistantMessage.extraInfo.state = message.extraInfo.state;
|
||||
}
|
||||
|
||||
lastAssistantMessage.extraInfo.usage = lastAssistantMessage.extraInfo.usage || message.extraInfo.usage;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="message-role">
|
||||
<span class="message-reminder" v-if="!props.message.toolResult">
|
||||
<span class="message-reminder" v-if="callingTools">
|
||||
Agent 正在使用工具
|
||||
<span class="tool-loading iconfont icon-double-loading">
|
||||
</span>
|
||||
@ -26,58 +26,77 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<div class="tool-arguments">
|
||||
<div class="inner">
|
||||
<div v-html="jsonResultToHtml(props.message.tool_calls[0].function.arguments)"></div>
|
||||
<div v-for="(toolResult, toolIndex) in props.message.toolResults" :key="toolIndex"
|
||||
class="toolcall-item">
|
||||
|
||||
<div class="tool-calls" v-if="toolIndex > 0">
|
||||
<div class="tool-call-header">
|
||||
<span class="tool-name">
|
||||
<span class="iconfont icon-tool"></span>
|
||||
|
||||
{{ props.message.tool_calls[toolIndex].function.name }}
|
||||
</span>
|
||||
<el-button size="small" @click="createTest(props.message.tool_calls[toolIndex])">
|
||||
<span class="iconfont icon-send"></span>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-arguments">
|
||||
<el-scrollbar width="100%">
|
||||
<div class="inner">
|
||||
<div v-html="jsonResultToHtml(props.message.tool_calls[toolIndex].function.arguments)">
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
|
||||
<!-- 工具调用结果 -->
|
||||
<div v-if="props.message.toolResult">
|
||||
<div v-if="toolResult.length > 0">
|
||||
<div class="tool-call-header result">
|
||||
<span class="tool-name">
|
||||
|
||||
<span class="tool-name" v-if="isValid(toolResult)">
|
||||
<span :class="`iconfont icon-info`"></span>
|
||||
{{ t("response") }}
|
||||
</span>
|
||||
<span class="tool-name" v-else>
|
||||
<span :class="`iconfont icon-${currentMessageLevel}`"></span>
|
||||
{{ isValid ? t("response") : t('error') }}
|
||||
<el-button v-if="!isValid" size="small"
|
||||
@click="gotoIssue()"
|
||||
>
|
||||
{{ isValid(toolResult) ? t("response") : t('error') }}
|
||||
<el-button size="small" @click="gotoIssue()">
|
||||
{{ t('feedback') }}
|
||||
</el-button>
|
||||
</span>
|
||||
<span style="width: 200px;" class="tools-dialog-container" v-if="currentMessageLevel === 'info'">
|
||||
|
||||
|
||||
<span style="width: 200px;" class="tools-dialog-container"
|
||||
v-if="currentMessageLevel === 'info'">
|
||||
<el-switch v-model="props.message.showJson!.value" inline-prompt active-text="JSON"
|
||||
inactive-text="Text" style="margin-left: 10px; width: 200px;"
|
||||
:inactive-action-style="'backgroundColor: var(--sidebar)'" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="tool-result" v-if="isValid">
|
||||
<div class="tool-result" v-if="isValid(toolResult)">
|
||||
<!-- 展示 JSON -->
|
||||
<div v-if="props.message.showJson!.value" class="tool-result-content">
|
||||
<div class="inner">
|
||||
<div v-html="toHtml(props.message.toolResult)"></div>
|
||||
<div v-html="toHtml(props.message.toolResults[toolIndex])"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 展示富文本 -->
|
||||
<span v-else>
|
||||
<div v-for="(item, index) in props.message.toolResult" :key="index"
|
||||
class="response-item"
|
||||
>
|
||||
<ToolcallResultItem
|
||||
:item="item"
|
||||
@update:item="value => updateToolCallResultItem(value, index)"
|
||||
@update:ocr-done="value => collposePanel()"
|
||||
/>
|
||||
<div v-for="(item, index) in props.message.toolResults[toolIndex]" :key="index"
|
||||
class="response-item">
|
||||
<ToolcallResultItem :item="item"
|
||||
@update:item="value => updateToolCallResultItem(value, toolIndex, index)"
|
||||
@update:ocr-done="value => collposePanel()" />
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div v-else class="tool-result">
|
||||
<div class="tool-result-content"
|
||||
v-for="(error, index) of collectErrors"
|
||||
:key="index"
|
||||
>
|
||||
<div class="tool-result-content" v-for="(error, index) of collectErrors(toolResult)"
|
||||
:key="index">
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
@ -91,17 +110,12 @@
|
||||
</div>
|
||||
<div class="tool-result-content">
|
||||
<div class="progress">
|
||||
<el-progress
|
||||
:percentage="100"
|
||||
:format="() => ''"
|
||||
:indeterminate="true"
|
||||
text-inside
|
||||
/>
|
||||
<el-progress :percentage="100" :format="() => ''" :indeterminate="true" text-inside />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MessageMeta :message="message" />
|
||||
<MessageMeta v-if="toolIndex === props.message.toolResults.length - 1" :message="message" />
|
||||
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
@ -110,13 +124,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, ref, watch, PropType, computed, defineEmits, inject, Ref } from 'vue';
|
||||
import { defineProps, ref, watch, PropType, computed, defineEmits } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import MessageMeta from './message-meta.vue';
|
||||
import { markdownToHtml } from '@/components/main-panel/chat/markdown/markdown';
|
||||
import { createTest } from '@/views/setting/llm';
|
||||
import { IRenderMessage, MessageState } from '../chat-box/chat';
|
||||
import { IToolRenderMessage, MessageState } from '../chat-box/chat';
|
||||
import { ToolCallContent } from '@/hook/type';
|
||||
|
||||
import ToolcallResultItem from './toolcall-result-item.vue';
|
||||
@ -125,7 +139,7 @@ const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
message: {
|
||||
type: Object as PropType<IRenderMessage>,
|
||||
type: Object as PropType<IToolRenderMessage>,
|
||||
required: true
|
||||
},
|
||||
tabId: {
|
||||
@ -135,20 +149,38 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const hasOcr = computed(() => {
|
||||
for (const item of props.message.toolResult || []) {
|
||||
|
||||
if (props.message.role === 'assistant/tool_calls') {
|
||||
for (const toolResult of props.message.toolResults) {
|
||||
for (const item of toolResult) {
|
||||
const metaInfo = item._meta || {};
|
||||
const { ocr = false } = metaInfo;
|
||||
if (ocr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
const activeNames = ref<string[]>(props.message.toolResult ? [''] : ['tool']);
|
||||
|
||||
const callingTools = computed(() => {
|
||||
const emptyToolResult = props.message.toolResults.find(item => item.length === 0);
|
||||
|
||||
if (emptyToolResult) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
const activeNames = ref<string[]>(callingTools.value ? ['tool']: []);
|
||||
|
||||
watch(
|
||||
() => props.message.toolResult,
|
||||
() => props.message,
|
||||
(value, _) => {
|
||||
if (hasOcr.value) {
|
||||
return;
|
||||
@ -191,9 +223,10 @@ function gotoIssue() {
|
||||
window.open('https://github.com/LSTM-Kirigaya/openmcp-client/issues', '_blank');
|
||||
}
|
||||
|
||||
const isValid = computed(() => {
|
||||
|
||||
function isValid(toolResult: ToolCallContent[]) {
|
||||
try {
|
||||
const item = props.message.toolResult![0];
|
||||
const item = toolResult[0];
|
||||
if (item.type === 'error') {
|
||||
return false;
|
||||
}
|
||||
@ -201,29 +234,34 @@ const isValid = computed(() => {
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const currentMessageLevel = computed(() => {
|
||||
|
||||
// 此时正在等待 mcp server 给出回应
|
||||
if (!props.message.toolResult) {
|
||||
for (const toolResult of props.message.toolResults) {
|
||||
if (toolResult.length === 0) {
|
||||
return 'info';
|
||||
}
|
||||
|
||||
if (!isValid.value) {
|
||||
if (!isValid(toolResult)) {
|
||||
return 'error';
|
||||
}
|
||||
if (props.message.extraInfo.state != MessageState.Success) {
|
||||
}
|
||||
|
||||
if (props.message.extraInfo.state !== MessageState.Success) {
|
||||
return 'warning';
|
||||
}
|
||||
return 'info';
|
||||
})
|
||||
|
||||
const collectErrors = computed(() => {
|
||||
return 'info';
|
||||
});
|
||||
|
||||
|
||||
function collectErrors(toolResult: ToolCallContent[]) {
|
||||
const errorMessages = [];
|
||||
try {
|
||||
const errorResults = props.message.toolResult!.filter(item => item.type === 'error');
|
||||
const errorResults = toolResult.filter(item => item.type === 'error');
|
||||
console.log(errorResults);
|
||||
|
||||
for (const errorResult of errorResults) {
|
||||
@ -233,12 +271,12 @@ const collectErrors = computed(() => {
|
||||
} catch {
|
||||
return errorMessages;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const emit = defineEmits(['update:tool-result']);
|
||||
const emits = defineEmits(['update:tool-result']);
|
||||
|
||||
function updateToolCallResultItem(value: any, index: number) {
|
||||
emit('update:tool-result', value, index);
|
||||
function updateToolCallResultItem(value: any, toolIndex: number, index: number) {
|
||||
emits('update:tool-result', value, toolIndex, index);
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -250,9 +288,6 @@ function updateToolCallResultItem(value: any, index: number) {
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
.tool-result-content .el-progress-bar__outer {
|
||||
}
|
||||
|
||||
.tool-result-content .progress {
|
||||
border-radius: .5em;
|
||||
background-color: var(--el-fill-color-light) !important;
|
||||
@ -295,6 +330,9 @@ function updateToolCallResultItem(value: any, index: number) {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.toolcall-item .tool-calls {
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.tool-call-item {
|
||||
margin-bottom: 10px;
|
||||
|
@ -30,9 +30,6 @@ export function callTool(toolName: string, toolArgs: Record<string, any>) {
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
pinkLog('callTool');
|
||||
console.log(toolArgs);
|
||||
|
||||
bridge.postMessage({
|
||||
command: 'tools/call',
|
||||
data: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user